Loading Documentation/devicetree/bindings/sound/fsl,asrc.txt +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ Required properties: "mem" Peripheral access clock to access registers. "ipg" Peripheral clock to driver module. "asrck_<0-f>" Clock sources for input and output clock. "spba" The spba clock is required when ASRC is placed as a bus slave of the Shared Peripheral Bus and when two or more bus masters (CPU, DMA or DSP) try to access it. This property is optional depending on the SoC design. - big-endian : If this property is absent, the little endian mode will be in use as default. Otherwise, the big endian Loading Documentation/devicetree/bindings/sound/fsl,esai.txt +5 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,11 @@ Required properties: derive HCK, SCK and FS. "fsys" The system clock derived from ahb clock used to derive HCK, SCK and FS. "spba" The spba clock is required when ESAI is placed as a bus slave of the Shared Peripheral Bus and when two or more bus masters (CPU, DMA or DSP) try to access it. This property is optional depending on the SoC design. - fsl,fifo-depth : The number of elements in the transmit and receive FIFOs. This number is the maximum allowed value for Loading include/sound/designware_i2s.h +5 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,11 @@ struct i2s_platform_data { u32 snd_fmts; u32 snd_rates; #define DW_I2S_QUIRK_COMP_REG_OFFSET (1 << 0) unsigned int quirks; unsigned int i2s_reg_comp1; unsigned int i2s_reg_comp2; void *play_dma_data; void *capture_dma_data; bool (*filter)(struct dma_chan *chan, void *slave); Loading sound/soc/dwc/designware_i2s.c +82 −31 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/pm_runtime.h> #include <sound/designware_i2s.h> #include <sound/pcm.h> #include <sound/pcm_params.h> Loading Loading @@ -93,7 +94,12 @@ struct dw_i2s_dev { struct clk *clk; int active; unsigned int capability; unsigned int quirks; unsigned int i2s_reg_comp1; unsigned int i2s_reg_comp2; struct device *dev; u32 ccr; u32 xfer_resolution; /* data related to DMA transfers b/w i2s and DMAC */ union dw_i2s_snd_dma_data play_dma_data; Loading Loading @@ -213,31 +219,58 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream, return 0; } static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) { u32 ch_reg, irq; struct i2s_clk_config_data *config = &dev->config; i2s_disable_channels(dev, stream); for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_write_reg(dev->i2s_base, TCR(ch_reg), dev->xfer_resolution); i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); } else { i2s_write_reg(dev->i2s_base, RCR(ch_reg), dev->xfer_resolution); i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); } } } static int dw_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); struct i2s_clk_config_data *config = &dev->config; u32 ccr, xfer_resolution, ch_reg, irq; int ret; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: config->data_width = 16; ccr = 0x00; xfer_resolution = 0x02; dev->ccr = 0x00; dev->xfer_resolution = 0x02; break; case SNDRV_PCM_FORMAT_S24_LE: config->data_width = 24; ccr = 0x08; xfer_resolution = 0x04; dev->ccr = 0x08; dev->xfer_resolution = 0x04; break; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; ccr = 0x10; xfer_resolution = 0x05; dev->ccr = 0x10; dev->xfer_resolution = 0x05; break; default: Loading @@ -258,27 +291,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } i2s_disable_channels(dev, substream->stream); dw_i2s_config(dev, substream->stream); for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution); i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); } else { i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution); i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); } } i2s_write_reg(dev->i2s_base, CCR, ccr); i2s_write_reg(dev->i2s_base, CCR, dev->ccr); config->sample_rate = params_rate(params); Loading Loading @@ -394,6 +409,23 @@ static const struct snd_soc_component_driver dw_i2s_component = { }; #ifdef CONFIG_PM static int dw_i2s_runtime_suspend(struct device *dev) { struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); if (dw_dev->capability & DW_I2S_MASTER) clk_disable(dw_dev->clk); return 0; } static int dw_i2s_runtime_resume(struct device *dev) { struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); if (dw_dev->capability & DW_I2S_MASTER) clk_enable(dw_dev->clk); return 0; } static int dw_i2s_suspend(struct snd_soc_dai *dai) { Loading @@ -410,6 +442,11 @@ static int dw_i2s_resume(struct snd_soc_dai *dai) if (dev->capability & DW_I2S_MASTER) clk_enable(dev->clk); if (dai->playback_active) dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK); if (dai->capture_active) dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); return 0; } Loading Loading @@ -459,8 +496,8 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, * Read component parameter registers to extract * the I2S block's configuration. */ u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2); u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1); u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2); u32 idx; if (COMP1_TX_ENABLED(comp1)) { Loading Loading @@ -503,7 +540,7 @@ static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev, struct resource *res, const struct i2s_platform_data *pdata) { u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1); u32 idx = COMP1_APB_DATA_WIDTH(comp1); int ret; Loading Loading @@ -607,6 +644,14 @@ static int dw_i2s_probe(struct platform_device *pdev) if (pdata) { dev->capability = pdata->cap; clk_id = NULL; dev->quirks = pdata->quirks; if (dev->quirks & DW_I2S_QUIRK_COMP_REG_OFFSET) { dev->i2s_reg_comp1 = pdata->i2s_reg_comp1; dev->i2s_reg_comp2 = pdata->i2s_reg_comp2; } else { dev->i2s_reg_comp1 = I2S_COMP_PARAM_1; dev->i2s_reg_comp2 = I2S_COMP_PARAM_2; } ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); } else { clk_id = "i2sclk"; Loading Loading @@ -649,7 +694,7 @@ static int dw_i2s_probe(struct platform_device *pdev) goto err_clk_disable; } } pm_runtime_enable(&pdev->dev); return 0; err_clk_disable: Loading @@ -665,6 +710,7 @@ static int dw_i2s_remove(struct platform_device *pdev) if (dev->capability & DW_I2S_MASTER) clk_disable_unprepare(dev->clk); pm_runtime_disable(&pdev->dev); return 0; } Loading @@ -677,12 +723,17 @@ static const struct of_device_id dw_i2s_of_match[] = { MODULE_DEVICE_TABLE(of, dw_i2s_of_match); #endif static const struct dev_pm_ops dwc_pm_ops = { SET_RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL) }; static struct platform_driver dw_i2s_driver = { .probe = dw_i2s_probe, .remove = dw_i2s_remove, .driver = { .name = "designware-i2s", .of_match_table = of_match_ptr(dw_i2s_of_match), .pm = &dwc_pm_ops, }, }; Loading sound/soc/fsl/fsl-asoc-card.c +9 −1 Original line number Diff line number Diff line Loading @@ -107,6 +107,13 @@ static const struct snd_soc_dapm_route audio_map[] = { {"CPU-Capture", NULL, "Capture"}, }; static const struct snd_soc_dapm_route audio_map_ac97[] = { {"AC97 Playback", NULL, "ASRC-Playback"}, {"Playback", NULL, "AC97 Playback"}, {"ASRC-Capture", NULL, "AC97 Capture"}, {"AC97 Capture", NULL, "Capture"}, }; /* Add all possible widgets into here without being redundant */ static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = { SND_SOC_DAPM_LINE("Line Out Jack", NULL), Loading Loading @@ -579,7 +586,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dev = &pdev->dev; priv->card.name = priv->name; priv->card.dai_link = priv->dai_link; priv->card.dapm_routes = audio_map; priv->card.dapm_routes = fsl_asoc_card_is_ac97(priv) ? audio_map_ac97 : audio_map; priv->card.late_probe = fsl_asoc_card_late_probe; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets; Loading Loading
Documentation/devicetree/bindings/sound/fsl,asrc.txt +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ Required properties: "mem" Peripheral access clock to access registers. "ipg" Peripheral clock to driver module. "asrck_<0-f>" Clock sources for input and output clock. "spba" The spba clock is required when ASRC is placed as a bus slave of the Shared Peripheral Bus and when two or more bus masters (CPU, DMA or DSP) try to access it. This property is optional depending on the SoC design. - big-endian : If this property is absent, the little endian mode will be in use as default. Otherwise, the big endian Loading
Documentation/devicetree/bindings/sound/fsl,esai.txt +5 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,11 @@ Required properties: derive HCK, SCK and FS. "fsys" The system clock derived from ahb clock used to derive HCK, SCK and FS. "spba" The spba clock is required when ESAI is placed as a bus slave of the Shared Peripheral Bus and when two or more bus masters (CPU, DMA or DSP) try to access it. This property is optional depending on the SoC design. - fsl,fifo-depth : The number of elements in the transmit and receive FIFOs. This number is the maximum allowed value for Loading
include/sound/designware_i2s.h +5 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,11 @@ struct i2s_platform_data { u32 snd_fmts; u32 snd_rates; #define DW_I2S_QUIRK_COMP_REG_OFFSET (1 << 0) unsigned int quirks; unsigned int i2s_reg_comp1; unsigned int i2s_reg_comp2; void *play_dma_data; void *capture_dma_data; bool (*filter)(struct dma_chan *chan, void *slave); Loading
sound/soc/dwc/designware_i2s.c +82 −31 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/pm_runtime.h> #include <sound/designware_i2s.h> #include <sound/pcm.h> #include <sound/pcm_params.h> Loading Loading @@ -93,7 +94,12 @@ struct dw_i2s_dev { struct clk *clk; int active; unsigned int capability; unsigned int quirks; unsigned int i2s_reg_comp1; unsigned int i2s_reg_comp2; struct device *dev; u32 ccr; u32 xfer_resolution; /* data related to DMA transfers b/w i2s and DMAC */ union dw_i2s_snd_dma_data play_dma_data; Loading Loading @@ -213,31 +219,58 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream, return 0; } static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) { u32 ch_reg, irq; struct i2s_clk_config_data *config = &dev->config; i2s_disable_channels(dev, stream); for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_write_reg(dev->i2s_base, TCR(ch_reg), dev->xfer_resolution); i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); } else { i2s_write_reg(dev->i2s_base, RCR(ch_reg), dev->xfer_resolution); i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); } } } static int dw_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); struct i2s_clk_config_data *config = &dev->config; u32 ccr, xfer_resolution, ch_reg, irq; int ret; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: config->data_width = 16; ccr = 0x00; xfer_resolution = 0x02; dev->ccr = 0x00; dev->xfer_resolution = 0x02; break; case SNDRV_PCM_FORMAT_S24_LE: config->data_width = 24; ccr = 0x08; xfer_resolution = 0x04; dev->ccr = 0x08; dev->xfer_resolution = 0x04; break; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; ccr = 0x10; xfer_resolution = 0x05; dev->ccr = 0x10; dev->xfer_resolution = 0x05; break; default: Loading @@ -258,27 +291,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } i2s_disable_channels(dev, substream->stream); dw_i2s_config(dev, substream->stream); for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution); i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); } else { i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution); i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); } } i2s_write_reg(dev->i2s_base, CCR, ccr); i2s_write_reg(dev->i2s_base, CCR, dev->ccr); config->sample_rate = params_rate(params); Loading Loading @@ -394,6 +409,23 @@ static const struct snd_soc_component_driver dw_i2s_component = { }; #ifdef CONFIG_PM static int dw_i2s_runtime_suspend(struct device *dev) { struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); if (dw_dev->capability & DW_I2S_MASTER) clk_disable(dw_dev->clk); return 0; } static int dw_i2s_runtime_resume(struct device *dev) { struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); if (dw_dev->capability & DW_I2S_MASTER) clk_enable(dw_dev->clk); return 0; } static int dw_i2s_suspend(struct snd_soc_dai *dai) { Loading @@ -410,6 +442,11 @@ static int dw_i2s_resume(struct snd_soc_dai *dai) if (dev->capability & DW_I2S_MASTER) clk_enable(dev->clk); if (dai->playback_active) dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK); if (dai->capture_active) dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); return 0; } Loading Loading @@ -459,8 +496,8 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, * Read component parameter registers to extract * the I2S block's configuration. */ u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2); u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1); u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2); u32 idx; if (COMP1_TX_ENABLED(comp1)) { Loading Loading @@ -503,7 +540,7 @@ static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev, struct resource *res, const struct i2s_platform_data *pdata) { u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1); u32 idx = COMP1_APB_DATA_WIDTH(comp1); int ret; Loading Loading @@ -607,6 +644,14 @@ static int dw_i2s_probe(struct platform_device *pdev) if (pdata) { dev->capability = pdata->cap; clk_id = NULL; dev->quirks = pdata->quirks; if (dev->quirks & DW_I2S_QUIRK_COMP_REG_OFFSET) { dev->i2s_reg_comp1 = pdata->i2s_reg_comp1; dev->i2s_reg_comp2 = pdata->i2s_reg_comp2; } else { dev->i2s_reg_comp1 = I2S_COMP_PARAM_1; dev->i2s_reg_comp2 = I2S_COMP_PARAM_2; } ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); } else { clk_id = "i2sclk"; Loading Loading @@ -649,7 +694,7 @@ static int dw_i2s_probe(struct platform_device *pdev) goto err_clk_disable; } } pm_runtime_enable(&pdev->dev); return 0; err_clk_disable: Loading @@ -665,6 +710,7 @@ static int dw_i2s_remove(struct platform_device *pdev) if (dev->capability & DW_I2S_MASTER) clk_disable_unprepare(dev->clk); pm_runtime_disable(&pdev->dev); return 0; } Loading @@ -677,12 +723,17 @@ static const struct of_device_id dw_i2s_of_match[] = { MODULE_DEVICE_TABLE(of, dw_i2s_of_match); #endif static const struct dev_pm_ops dwc_pm_ops = { SET_RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL) }; static struct platform_driver dw_i2s_driver = { .probe = dw_i2s_probe, .remove = dw_i2s_remove, .driver = { .name = "designware-i2s", .of_match_table = of_match_ptr(dw_i2s_of_match), .pm = &dwc_pm_ops, }, }; Loading
sound/soc/fsl/fsl-asoc-card.c +9 −1 Original line number Diff line number Diff line Loading @@ -107,6 +107,13 @@ static const struct snd_soc_dapm_route audio_map[] = { {"CPU-Capture", NULL, "Capture"}, }; static const struct snd_soc_dapm_route audio_map_ac97[] = { {"AC97 Playback", NULL, "ASRC-Playback"}, {"Playback", NULL, "AC97 Playback"}, {"ASRC-Capture", NULL, "AC97 Capture"}, {"AC97 Capture", NULL, "Capture"}, }; /* Add all possible widgets into here without being redundant */ static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = { SND_SOC_DAPM_LINE("Line Out Jack", NULL), Loading Loading @@ -579,7 +586,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dev = &pdev->dev; priv->card.name = priv->name; priv->card.dai_link = priv->dai_link; priv->card.dapm_routes = audio_map; priv->card.dapm_routes = fsl_asoc_card_is_ac97(priv) ? audio_map_ac97 : audio_map; priv->card.late_probe = fsl_asoc_card_late_probe; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets; Loading