diff options
Diffstat (limited to 'sound/soc/tegra/tegra30_ahub.c')
-rw-r--r-- | sound/soc/tegra/tegra30_ahub.c | 138 |
1 files changed, 88 insertions, 50 deletions
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 31154338c1eb..d6f4c9940e0c 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -24,8 +24,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/slab.h> -#include <linux/clk/tegra.h> #include <sound/soc.h> #include "tegra30_ahub.h" @@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev) } int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, - dma_addr_t *fiforeg, - unsigned int *reqsel) + char *dmachan, int dmachan_len, + dma_addr_t *fiforeg) { int channel; u32 reg, val; @@ -110,9 +110,11 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, __set_bit(channel, ahub->rx_usage); *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel; + snprintf(dmachan, dmachan_len, "rx%d", channel); *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO + (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE); - *reqsel = ahub->dma_sel + channel; + + pm_runtime_get_sync(ahub->dev); reg = TEGRA30_AHUB_CHANNEL_CTRL + (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); @@ -140,6 +142,8 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE); ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_rx_fifo); @@ -149,12 +153,16 @@ int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif) int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; int reg, val; + pm_runtime_get_sync(ahub->dev); + reg = TEGRA30_AHUB_CHANNEL_CTRL + (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); val = tegra30_apbif_read(reg); val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN; tegra30_apbif_write(reg, val); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_enable_rx_fifo); @@ -164,12 +172,16 @@ int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif) int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; int reg, val; + pm_runtime_get_sync(ahub->dev); + reg = TEGRA30_AHUB_CHANNEL_CTRL + (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); val = tegra30_apbif_read(reg); val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN; tegra30_apbif_write(reg, val); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_disable_rx_fifo); @@ -185,8 +197,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif) EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, - dma_addr_t *fiforeg, - unsigned int *reqsel) + char *dmachan, int dmachan_len, + dma_addr_t *fiforeg) { int channel; u32 reg, val; @@ -200,9 +212,11 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, __set_bit(channel, ahub->tx_usage); *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel; + snprintf(dmachan, dmachan_len, "tx%d", channel); *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO + (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE); - *reqsel = ahub->dma_sel + channel; + + pm_runtime_get_sync(ahub->dev); reg = TEGRA30_AHUB_CHANNEL_CTRL + (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); @@ -230,6 +244,8 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE); ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_tx_fifo); @@ -239,12 +255,16 @@ int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif) int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; int reg, val; + pm_runtime_get_sync(ahub->dev); + reg = TEGRA30_AHUB_CHANNEL_CTRL + (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); val = tegra30_apbif_read(reg); val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN; tegra30_apbif_write(reg, val); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_enable_tx_fifo); @@ -254,12 +274,16 @@ int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif) int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0; int reg, val; + pm_runtime_get_sync(ahub->dev); + reg = TEGRA30_AHUB_CHANNEL_CTRL + (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE); val = tegra30_apbif_read(reg); val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN; tegra30_apbif_write(reg, val); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_disable_tx_fifo); @@ -280,10 +304,14 @@ int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif, int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; int reg; + pm_runtime_get_sync(ahub->dev); + reg = TEGRA30_AHUB_AUDIO_RX + (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE); tegra30_audio_write(reg, 1 << txcif); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_source); @@ -293,35 +321,51 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif) int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0; int reg; + pm_runtime_get_sync(ahub->dev); + reg = TEGRA30_AHUB_AUDIO_RX + (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE); tegra30_audio_write(reg, 0); + pm_runtime_put(ahub->dev); + return 0; } EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source); -#define CLK_LIST_MASK_TEGRA30 BIT(0) -#define CLK_LIST_MASK_TEGRA114 BIT(1) +#define MOD_LIST_MASK_TEGRA30 BIT(0) +#define MOD_LIST_MASK_TEGRA114 BIT(1) +#define MOD_LIST_MASK_TEGRA124 BIT(2) -#define CLK_LIST_MASK_TEGRA30_OR_LATER \ - (CLK_LIST_MASK_TEGRA30 | CLK_LIST_MASK_TEGRA114) +#define MOD_LIST_MASK_TEGRA30_OR_LATER \ + (MOD_LIST_MASK_TEGRA30 | MOD_LIST_MASK_TEGRA114 | \ + MOD_LIST_MASK_TEGRA124) +#define MOD_LIST_MASK_TEGRA114_OR_LATER \ + (MOD_LIST_MASK_TEGRA114 | MOD_LIST_MASK_TEGRA124) static const struct { - const char *clk_name; - u32 clk_list_mask; -} configlink_clocks[] = { - { "i2s0", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s1", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s2", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s3", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s4", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "dam0", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "dam1", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "dam2", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "spdif_in", CLK_LIST_MASK_TEGRA30_OR_LATER }, - { "amx", CLK_LIST_MASK_TEGRA114 }, - { "adx", CLK_LIST_MASK_TEGRA114 }, + const char *rst_name; + u32 mod_list_mask; +} configlink_mods[] = { + { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "i2s3", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "i2s4", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "dam0", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "dam1", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "dam2", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "spdif", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "amx", MOD_LIST_MASK_TEGRA114_OR_LATER }, + { "adx", MOD_LIST_MASK_TEGRA114_OR_LATER }, + { "amx1", MOD_LIST_MASK_TEGRA124 }, + { "adx1", MOD_LIST_MASK_TEGRA124 }, + { "afc0", MOD_LIST_MASK_TEGRA124 }, + { "afc1", MOD_LIST_MASK_TEGRA124 }, + { "afc2", MOD_LIST_MASK_TEGRA124 }, + { "afc3", MOD_LIST_MASK_TEGRA124 }, + { "afc4", MOD_LIST_MASK_TEGRA124 }, + { "afc5", MOD_LIST_MASK_TEGRA124 }, }; #define LAST_REG(name) \ @@ -450,17 +494,17 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { }; static struct tegra30_ahub_soc_data soc_data_tegra30 = { - .clk_list_mask = CLK_LIST_MASK_TEGRA30, + .mod_list_mask = MOD_LIST_MASK_TEGRA30, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra114 = { - .clk_list_mask = CLK_LIST_MASK_TEGRA114, + .mod_list_mask = MOD_LIST_MASK_TEGRA114, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra124 = { - .clk_list_mask = CLK_LIST_MASK_TEGRA114, + .mod_list_mask = MOD_LIST_MASK_TEGRA124, .set_audio_cif = tegra124_ahub_set_cif, }; @@ -475,10 +519,9 @@ static int tegra30_ahub_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct tegra30_ahub_soc_data *soc_data; - struct clk *clk; + struct reset_control *rst; int i; struct resource *res0, *res1, *region; - u32 of_dma[2]; void __iomem *regs_apbif, *regs_ahub; int ret = 0; @@ -495,19 +538,24 @@ static int tegra30_ahub_probe(struct platform_device *pdev) * operate correctly, all devices on this bus must be out of reset. * Ensure that here. */ - for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) { - if (!(configlink_clocks[i].clk_list_mask & - soc_data->clk_list_mask)) + for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) { + if (!(configlink_mods[i].mod_list_mask & + soc_data->mod_list_mask)) continue; - clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "Can't get clock %s\n", - configlink_clocks[i].clk_name); - ret = PTR_ERR(clk); + + rst = reset_control_get(&pdev->dev, + configlink_mods[i].rst_name); + if (IS_ERR(rst)) { + dev_err(&pdev->dev, "Can't get reset %s\n", + configlink_mods[i].rst_name); + ret = PTR_ERR(rst); goto err; } - tegra_periph_reset_deassert(clk); - clk_put(clk); + + ret = reset_control_deassert(rst); + reset_control_put(rst); + if (ret) + goto err; } ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), @@ -536,16 +584,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev) goto err_clk_put_d_audio; } - if (of_property_read_u32_array(pdev->dev.of_node, - "nvidia,dma-request-selector", - of_dma, 2) < 0) { - dev_err(&pdev->dev, - "Missing property nvidia,dma-request-selector\n"); - ret = -ENODEV; - goto err_clk_put_d_audio; - } - ahub->dma_sel = of_dma[1]; - res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res0) { dev_err(&pdev->dev, "No apbif memory resource\n"); |