diff options
30 files changed, 322 insertions, 113 deletions
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 212d97084bd..bc384d3561d 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -208,7 +208,7 @@ static struct snd_platform_data da830_evm_snd_data = { .num_serializer = ARRAY_SIZE(da830_iis_serializer_direction), .tdm_slots = 2, .serial_dir = da830_iis_serializer_direction, - .eventq_no = EVENTQ_0, + .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_2, .txnumevt = 1, .rxnumevt = 1, diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 2ec3095ffb7..d4ec18d0b4a 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -342,7 +342,7 @@ static struct snd_platform_data da850_evm_snd_data = { .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction), .tdm_slots = 2, .serial_dir = da850_iis_serializer_direction, - .eventq_no = EVENTQ_1, + .asp_chan_q = EVENTQ_1, .version = MCASP_VERSION_2, .txnumevt = 1, .rxnumevt = 1, diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 6d8889342c9..87521f2d69c 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -323,7 +323,7 @@ static struct snd_platform_data dm646x_evm_snd_data[] = { .num_serializer = ARRAY_SIZE(dm646x_iis_serializer_direction), .tdm_slots = 2, .serial_dir = dm646x_iis_serializer_direction, - .eventq_no = EVENTQ_0, + .asp_chan_q = EVENTQ_0, }, { .tx_dma_offset = 0x400, @@ -332,7 +332,7 @@ static struct snd_platform_data dm646x_evm_snd_data[] = { .num_serializer = ARRAY_SIZE(dm646x_dit_serializer_direction), .tdm_slots = 32, .serial_dir = dm646x_dit_serializer_direction, - .eventq_no = EVENTQ_0, + .asp_chan_q = EVENTQ_0, }, }; diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h index b12c69edeea..9aa240909a2 100644 --- a/arch/arm/mach-davinci/include/mach/asp.h +++ b/arch/arm/mach-davinci/include/mach/asp.h @@ -52,7 +52,8 @@ struct snd_platform_data { u32 tx_dma_offset; u32 rx_dma_offset; - enum dma_event_q eventq_no; /* event queue number */ + enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ + enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ unsigned int codec_fmt; /* * Allowing this is more efficient and eliminates left and right swaps diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index c0227361a87..6ac71863c70 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h @@ -12,6 +12,9 @@ * published by the Free Software Foundation. */ +#define FSI_PORT_A 0 +#define FSI_PORT_B 1 + /* flags format * 0xABCDEEFF @@ -55,12 +58,12 @@ #define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK) #define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK) -#define SH_FSI_FMT_MONO (1 << 0) -#define SH_FSI_FMT_MONO_DELAY (1 << 1) -#define SH_FSI_FMT_PCM (1 << 2) -#define SH_FSI_FMT_I2S (1 << 3) -#define SH_FSI_FMT_TDM (1 << 4) -#define SH_FSI_FMT_TDM_DELAY (1 << 5) +#define SH_FSI_FMT_MONO 0 +#define SH_FSI_FMT_MONO_DELAY 1 +#define SH_FSI_FMT_PCM 2 +#define SH_FSI_FMT_I2S 3 +#define SH_FSI_FMT_TDM 4 +#define SH_FSI_FMT_TDM_DELAY 5 #define SH_FSI_IFMT_TDM_CH(x) \ (SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x)) @@ -72,9 +75,41 @@ #define SH_FSI_OFMT_TDM_DELAY_CH(x) \ (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x)) + +/* + * set_rate return value + * + * see ACKMD/BPFMD on + * ACK_MD (FSI2) + * CKG1 (FSI) + * + * err: return value < 0 + * + * 0x-00000AB + * + * A: ACKMD value + * B: BPFMD value + */ + +#define SH_FSI_ACKMD_MASK (0xF << 0) +#define SH_FSI_ACKMD_512 (1 << 0) +#define SH_FSI_ACKMD_256 (2 << 0) +#define SH_FSI_ACKMD_128 (3 << 0) +#define SH_FSI_ACKMD_64 (4 << 0) +#define SH_FSI_ACKMD_32 (5 << 0) + +#define SH_FSI_BPFMD_MASK (0xF << 4) +#define SH_FSI_BPFMD_512 (1 << 4) +#define SH_FSI_BPFMD_256 (2 << 4) +#define SH_FSI_BPFMD_128 (3 << 4) +#define SH_FSI_BPFMD_64 (4 << 4) +#define SH_FSI_BPFMD_32 (5 << 4) +#define SH_FSI_BPFMD_16 (6 << 4) + struct sh_fsi_platform_info { unsigned long porta_flags; unsigned long portb_flags; + int (*set_rate)(int is_porta, int rate); /* for master mode */ }; extern struct snd_soc_dai fsi_soc_dai[2]; diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 737b2384f6c..6083fe7799f 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -300,7 +300,7 @@ struct snd_soc_dai au1xpsc_i2s_dai = { }; EXPORT_SYMBOL(au1xpsc_i2s_dai); -static int __init au1xpsc_i2s_drvprobe(struct platform_device *pdev) +static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) { struct resource *r; unsigned long sel; diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 523b7fc33f4..c0eba510998 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -255,8 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops); #ifdef CONFIG_PM static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) { - struct sport_device *sport = - (struct sport_device *)dai->private_data; + struct sport_device *sport = dai->private_data; pr_debug("%s : sport %d\n", __func__, dai->id); if (!dai->active) @@ -271,8 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) static int bf5xx_ac97_resume(struct snd_soc_dai *dai) { int ret; - struct sport_device *sport = - (struct sport_device *)dai->private_data; + struct sport_device *sport = dai->private_data; pr_debug("%s : sport %d\n", __func__, dai->id); if (!dai->active) diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 4b360124083..24c14269f4b 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c @@ -210,8 +210,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, #ifdef CONFIG_PM static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) { - struct sport_device *sport = - (struct sport_device *)dai->private_data; + struct sport_device *sport = dai->private_data; if (!dai->active) return 0; @@ -225,8 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) static int bf5xx_tdm_resume(struct snd_soc_dai *dai) { int ret; - struct sport_device *sport = - (struct sport_device *)dai->private_data; + struct sport_device *sport = dai->private_data; if (!dai->active) return 0; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ea1f5edde3d..55bc2beffb3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -85,8 +85,8 @@ config SND_SOC_ALL_CODECS config SND_SOC_WM_HUBS tristate - default y if SND_SOC_WM8993=y - default m if SND_SOC_WM8993=m + default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y + default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m config SND_SOC_AC97_CODEC tristate diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 1072621e93f..9d1df262813 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -127,6 +127,8 @@ static __devinit int wm8727_platform_probe(struct platform_device *pdev) goto err_codec; } + return 0; + err_codec: snd_soc_unregister_codec(codec); err: diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 7e4a627b4c7..4e212ed62ea 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -94,7 +94,6 @@ SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0), static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = { SND_SOC_DAPM_INPUT("AUX"), -SND_SOC_DAPM_INPUT("AUX"), SND_SOC_DAPM_INPUT("AIN1"), SND_SOC_DAPM_INPUT("AIN2"), diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 0417dae32e6..19ad590ca0b 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -885,7 +885,6 @@ static int wm8988_register(struct wm8988_priv *wm8988, ret = snd_soc_register_dai(&wm8988_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); goto err_codec; } diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index c41cf47f400..a87046a96f2 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2361,6 +2361,20 @@ SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, 0, 1, 0), }; +static const struct snd_kcontrol_new aif1adc2l_mix[] = { +SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING, + 1, 1, 0), +SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING, + 0, 1, 0), +}; + +static const struct snd_kcontrol_new aif1adc2r_mix[] = { +SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING, + 1, 1, 0), +SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING, + 0, 1, 0), +}; + static const struct snd_kcontrol_new aif2dac2l_mix[] = { SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, 5, 1, 0), @@ -2527,6 +2541,11 @@ SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0, aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), +SND_SOC_DAPM_MIXER("AIF1ADC2L Mixer", SND_SOC_NOPM, 0, 0, + aif1adc2l_mix, ARRAY_SIZE(aif1adc2l_mix)), +SND_SOC_DAPM_MIXER("AIF1ADC2R Mixer", SND_SOC_NOPM, 0, 0, + aif1adc2r_mix, ARRAY_SIZE(aif1adc2r_mix)), + SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0, aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0, @@ -2689,6 +2708,14 @@ static const struct snd_soc_dapm_route intercon[] = { { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" }, { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" }, + { "AIF1ADC2L", NULL, "AIF1ADC2L Mixer" }, + { "AIF1ADC2L Mixer", "DMIC Switch", "DMIC2L" }, + { "AIF1ADC2L Mixer", "AIF2 Switch", "AIF2DACL" }, + + { "AIF1ADC2R", NULL, "AIF1ADC2R Mixer" }, + { "AIF1ADC2R Mixer", "DMIC Switch", "DMIC2R" }, + { "AIF1ADC2R Mixer", "AIF2 Switch", "AIF2DACR" }, + /* Pin level routing for AIF3 */ { "AIF1DAC1L", NULL, "AIF1DAC Mux" }, { "AIF1DAC1R", NULL, "AIF1DAC Mux" }, @@ -4047,6 +4074,11 @@ static int wm8994_codec_probe(struct platform_device *pdev) 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); + /* Unconditionally enable AIF1 ADC TDM mode; it only affects + * behaviour on idle TDM clock cycles. */ + snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, + WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); + wm8994_update_class_w(codec); ret = snd_soc_register_codec(codec); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 16f1a57da08..2cb81538cd9 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -410,6 +410,8 @@ static int hp_event(struct snd_soc_dapm_widget *w, WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY, 0); + snd_soc_write(codec, WM8993_DC_SERVO_0, 0); + snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, 0); diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index b251bc9a981..9e8932abf15 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -648,6 +648,8 @@ static int davinci_i2s_probe(struct platform_device *pdev) struct snd_platform_data *pdata = pdev->dev.platform_data; struct davinci_mcbsp_dev *dev; struct resource *mem, *ioarea, *res; + enum dma_event_q asp_chan_q = EVENTQ_0; + enum dma_event_q ram_chan_q = EVENTQ_1; int ret; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -676,7 +678,15 @@ static int davinci_i2s_probe(struct platform_device *pdev) pdata->sram_size_capture; dev->clk_input_pin = pdata->clk_input_pin; dev->i2s_accurate_sck = pdata->i2s_accurate_sck; + asp_chan_q = pdata->asp_chan_q; + ram_chan_q = pdata->ram_chan_q; } + + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q; + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q; + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q; + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q; + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { ret = -ENODEV; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index d3955096d87..b24720894af 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -890,7 +890,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dev->rxnumevt = pdata->rxnumevt; dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->eventq_no = pdata->eventq_no; + dma_data->asp_chan_q = pdata->asp_chan_q; + dma_data->ram_chan_q = pdata->ram_chan_q; dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + io_v2p(dev->base)); @@ -904,7 +905,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_data->channel = res->start; dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->eventq_no = pdata->eventq_no; + dma_data->asp_chan_q = pdata->asp_chan_q; + dma_data->ram_chan_q = pdata->ram_chan_q; dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + io_v2p(dev->base)); diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 2dc406f42fe..a7124116d2e 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -381,7 +381,7 @@ static int request_ping_pong(struct snd_pcm_substream *substream, /* Request ram master channel */ link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, davinci_pcm_dma_irq, substream, - EVENTQ_1); + prtd->params->ram_chan_q); if (link < 0) goto exit1; @@ -477,7 +477,8 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) /* Request asp master DMA channel */ link = prtd->asp_channel = edma_alloc_channel(params->channel, - davinci_pcm_dma_irq, substream, EVENTQ_0); + davinci_pcm_dma_irq, substream, + prtd->params->asp_chan_q); if (link < 0) goto exit1; @@ -800,7 +801,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm) dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, buf->addr); buf->area = NULL; - iram_dma = (struct snd_dma_buffer *)buf->private_data; + iram_dma = buf->private_data; if (iram_dma) { sram_free(iram_dma->area, iram_dma->bytes); kfree(iram_dma); diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index 0764944cf10..b799a02333d 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -21,7 +21,8 @@ struct davinci_pcm_dma_params { unsigned short acnt; dma_addr_t dma_addr; /* device physical address for DMA */ unsigned sram_size; - enum dma_event_q eventq_no; /* event queue number */ + enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ + enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ unsigned char data_type; /* xfer data type */ unsigned char convert_mono_stereo; unsigned int fifo_level; diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 9aa980d3823..48678533da7 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c @@ -203,7 +203,7 @@ static int davinci_vcif_probe(struct platform_device *pdev) int ret; davinci_vcif_dev = kzalloc(sizeof(struct davinci_vcif_dev), GFP_KERNEL); - if (!davinci_vc) { + if (!davinci_vcif_dev) { dev_dbg(&pdev->dev, "could not allocate memory for private data\n"); return -ENOMEM; diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 2f0d6d3e75d..52dac5e3874 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -32,6 +32,6 @@ config SND_SOC_EUKREA_TLV320 select SND_SOC_TLV320AIC23 help Enable I2S based access to the TLV320AIC23B codec attached - to the SSI4 interface + to the SSI interface endif # SND_IMX_SOC diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index 45f5e4b32cb..f15dfbdc47e 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -101,7 +101,8 @@ static int __init eukrea_tlv320_init(void) { int ret; - if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd()) + if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd() + && !machine_is_eukrea_cpuimx35sd()) /* return happy. We might run on a totally different machine */ return 0; diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 05f19c9284f..0a595da4811 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -292,12 +292,16 @@ static int snd_imx_open(struct snd_pcm_substream *substream) int ret; iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); + if (iprtd == NULL) + return -ENOMEM; runtime->private_data = iprtd; ret = snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) + if (ret < 0) { + kfree(iprtd); return ret; + } snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); return 0; diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index 6b518e07eea..b2bf27282cd 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c @@ -192,6 +192,8 @@ static int snd_imx_open(struct snd_pcm_substream *substream) int ret; iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); + if (iprtd == NULL) + return -ENOMEM; runtime->private_data = iprtd; iprtd->substream = substream; @@ -202,8 +204,10 @@ static int snd_imx_open(struct snd_pcm_substream *substream) ret = snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) + if (ret < 0) { + kfree(iprtd); return ret; + } snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); return 0; diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 0fdc7db7a46..981ffc2a13c 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -153,6 +153,15 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, default: return -EINVAL; } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + value &= ~KIRKWOOD_PLAYCTL_MONO_MASK; + if (params_channels(params) == 1) + value |= KIRKWOOD_PLAYCTL_MONO_BOTH; + else + value |= KIRKWOOD_PLAYCTL_MONO_OFF; + } + writel(i2s_value, priv->io+i2s_reg); writel(value, priv->io+reg); @@ -184,7 +193,8 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, /* configure audio & enable i2s playback */ value = readl(priv->io + KIRKWOOD_PLAYCTL); value &= ~KIRKWOOD_PLAYCTL_BURST_MASK; - value &= ~(KIRKWOOD_PLAYCTL_PAUSE|KIRKWOOD_PLAYCTL_SPDIF_EN); + value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE + | KIRKWOOD_PLAYCTL_SPDIF_EN); if (priv->burst == 32) value |= KIRKWOOD_PLAYCTL_BURST_32; @@ -197,7 +207,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: /* stop audio, disable interrupts */ value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE; + value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; writel(value, priv->io + KIRKWOOD_PLAYCTL); value = readl(priv->io + KIRKWOOD_INT_MASK); @@ -213,14 +223,14 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE; + value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; writel(value, priv->io + KIRKWOOD_PLAYCTL); break; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~KIRKWOOD_PLAYCTL_PAUSE; + value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); writel(value, priv->io + KIRKWOOD_PLAYCTL); break; @@ -253,7 +263,8 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, value = readl(priv->io + KIRKWOOD_RECCTL); value &= ~KIRKWOOD_RECCTL_BURST_MASK; value &= ~KIRKWOOD_RECCTL_MONO; - value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_SPDIF_EN); + value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE + | KIRKWOOD_RECCTL_SPDIF_EN); if (priv->burst == 32) value |= KIRKWOOD_RECCTL_BURST_32; @@ -267,7 +278,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: /* stop audio, disable interrupts */ value = readl(priv->io + KIRKWOOD_RECCTL); - value |= KIRKWOOD_RECCTL_PAUSE; + value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; writel(value, priv->io + KIRKWOOD_RECCTL); value = readl(priv->io + KIRKWOOD_INT_MASK); @@ -283,14 +294,14 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: value = readl(priv->io + KIRKWOOD_RECCTL); - value |= KIRKWOOD_RECCTL_PAUSE; + value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; writel(value, priv->io + KIRKWOOD_RECCTL); break; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: value = readl(priv->io + KIRKWOOD_RECCTL); - value &= ~KIRKWOOD_RECCTL_PAUSE; + value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE); writel(value, priv->io + KIRKWOOD_RECCTL); break; diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h index b6e4f68d71d..bb6e6a5648c 100644 --- a/sound/soc/kirkwood/kirkwood.h +++ b/sound/soc/kirkwood/kirkwood.h @@ -49,6 +49,9 @@ #define KIRKWOOD_PLAYCTL_BURST_32 (1<<11) #define KIRKWOOD_PLAYCTL_PAUSE (1<<9) #define KIRKWOOD_PLAYCTL_SPDIF_MUTE (1<<8) +#define KIRKWOOD_PLAYCTL_MONO_MASK (3<<5) +#define KIRKWOOD_PLAYCTL_MONO_BOTH (3<<5) +#define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5) #define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7) #define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4) #define KIRKWOOD_PLAYCTL_I2S_EN (1<<3) diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index 13311c8cf96..64376b2aac7 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c @@ -32,7 +32,8 @@ #undef S3C_IIS_V2_SUPPORTED -#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) +#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) \ + || defined(CONFIG_CPU_S5PV210) #define S3C_IIS_V2_SUPPORTED #endif diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index 2871a200160..dad575a2262 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c @@ -29,7 +29,7 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link fsi_dai_link = { .name = "AK4642", .stream_name = "AK4642", - .cpu_dai = &fsi_soc_dai[0], /* fsi */ + .cpu_dai = &fsi_soc_dai[FSI_PORT_A], .codec_dai = &ak4642_dai, .init = fsi_ak4642_dai_init, .ops = NULL, @@ -53,7 +53,7 @@ static int __init fsi_ak4642_init(void) { int ret = -ENOMEM; - fsi_snd_device = platform_device_alloc("soc-audio", -1); + fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_A); if (!fsi_snd_device) goto out; diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index 4d4fd777b45..121bbb07bb0 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c @@ -24,7 +24,7 @@ static int fsi_da7210_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link fsi_da7210_dai = { .name = "DA7210", .stream_name = "DA7210", - .cpu_dai = &fsi_soc_dai[1], /* FSI B */ + .cpu_dai = &fsi_soc_dai[FSI_PORT_B], .codec_dai = &da7210_dai, .init = fsi_da7210_init, }; @@ -47,7 +47,7 @@ static int __init fsi_da7210_sound_init(void) { int ret; - fsi_da7210_snd_device = platform_device_alloc("soc-audio", -1); + fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B); if (!fsi_da7210_snd_device) return -ENOMEM; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 30765ab512f..a1ce6089177 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -48,13 +48,12 @@ /* DO_FMT */ /* DI_FMT */ -#define CR_FMT(param) ((param) << 4) -# define CR_MONO 0x0 -# define CR_MONO_D 0x1 -# define CR_PCM 0x2 -# define CR_I2S 0x3 -# define CR_TDM 0x4 -# define CR_TDM_D 0x5 +#define CR_MONO (0x0 << 4) +#define CR_MONO_D (0x1 << 4) +#define CR_PCM (0x2 << 4) +#define CR_I2S (0x3 << 4) +#define CR_TDM (0x4 << 4) +#define CR_TDM_D (0x5 << 4) /* DOFF_CTL */ /* DIFF_CTL */ @@ -66,6 +65,10 @@ #define ERR_UNDER 0x00000001 #define ST_ERR (ERR_OVER | ERR_UNDER) +/* CKG1 */ +#define ACKMD_MASK 0x00007000 +#define BPFMD_MASK 0x00000700 + /* CLK_RST */ #define B_CLK 0x00000010 #define A_CLK 0x00000001 @@ -112,7 +115,9 @@ struct fsi_priv { int periods; }; -struct fsi_regs { +struct fsi_core { + int ver; + u32 int_st; u32 iemsk; u32 imsk; @@ -123,7 +128,7 @@ struct fsi_master { int irq; struct fsi_priv fsia; struct fsi_priv fsib; - struct fsi_regs *regs; + struct fsi_core *core; struct sh_fsi_platform_info *info; spinlock_t lock; }; @@ -160,24 +165,30 @@ static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) { - if (reg > REG_END) + if (reg > REG_END) { + pr_err("fsi: register access err (%s)\n", __func__); return; + } __fsi_reg_write((u32)(fsi->base + reg), data); } static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) { - if (reg > REG_END) + if (reg > REG_END) { + pr_err("fsi: register access err (%s)\n", __func__); return 0; + } return __fsi_reg_read((u32)(fsi->base + reg)); } static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) { - if (reg > REG_END) + if (reg > REG_END) { + pr_err("fsi: register access err (%s)\n", __func__); return; + } __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); } @@ -187,8 +198,10 @@ static void fsi_master_write(struct fsi_master *master, u32 reg, u32 data) unsigned long flags; if ((reg < MREG_START) || - (reg > MREG_END)) + (reg > MREG_END)) { + pr_err("fsi: register access err (%s)\n", __func__); return; + } spin_lock_irqsave(&master->lock, flags); __fsi_reg_write((u32)(master->base + reg), data); @@ -201,8 +214,10 @@ static u32 fsi_master_read(struct fsi_master *master, u32 reg) unsigned long flags; if ((reg < MREG_START) || - (reg > MREG_END)) + (reg > MREG_END)) { + pr_err("fsi: register access err (%s)\n", __func__); return 0; + } spin_lock_irqsave(&master->lock, flags); ret = __fsi_reg_read((u32)(master->base + reg)); @@ -217,8 +232,10 @@ static void fsi_master_mask_set(struct fsi_master *master, unsigned long flags; if ((reg < MREG_START) || - (reg > MREG_END)) + (reg > MREG_END)) { + pr_err("fsi: register access err (%s)\n", __func__); return; + } spin_lock_irqsave(&master->lock, flags); __fsi_reg_mask_set((u32)(master->base + reg), mask, data); @@ -340,8 +357,8 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) u32 data = fsi_port_ab_io_bit(fsi, is_play); struct fsi_master *master = fsi_get_master(fsi); - fsi_master_mask_set(master, master->regs->imsk, data, data); - fsi_master_mask_set(master, master->regs->iemsk, data, data); + fsi_master_mask_set(master, master->core->imsk, data, data); + fsi_master_mask_set(master, master->core->iemsk, data, data); } static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) @@ -349,18 +366,18 @@ static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) u32 data = fsi_port_ab_io_bit(fsi, is_play); struct fsi_master *master = fsi_get_master(fsi); - fsi_master_mask_set(master, master->regs->imsk, data, 0); - fsi_master_mask_set(master, master->regs->iemsk, data, 0); + fsi_master_mask_set(master, master->core->imsk, data, 0); + fsi_master_mask_set(master, master->core->iemsk, data, 0); } static u32 fsi_irq_get_status(struct fsi_master *master) { - return fsi_master_read(master, master->regs->int_st); + return fsi_master_read(master, master->core->int_st); } static void fsi_irq_clear_all_status(struct fsi_master *master) { - fsi_master_write(master, master->regs->int_st, 0x0000000); + fsi_master_write(master, master->core->int_st, 0); } static void fsi_irq_clear_status(struct fsi_priv *fsi) @@ -372,7 +389,7 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi) data |= fsi_port_ab_io_bit(fsi, 1); /* clear interrupt factor */ - fsi_master_mask_set(master, master->regs->int_st, data, 0); + fsi_master_mask_set(master, master->core->int_st, data, 0); } /************************************************************************ @@ -653,7 +670,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsi_priv *fsi = fsi_get_priv(substream); - const char *msg; u32 flags = fsi_get_info_flags(fsi); u32 fmt; u32 reg; @@ -674,20 +690,15 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, /* clock inversion (CKG2) */ data = 0; - switch (SH_FSI_INVERSION_MASK & flags) { - case SH_FSI_LRM_INV: - data = 1 << 12; - break; - case SH_FSI_BRM_INV: - data = 1 << 8; - break; - case SH_FSI_LRS_INV: - data = 1 << 4; - break; - case SH_FSI_BRS_INV: - data = 1 << 0; - break; - } + if (SH_FSI_LRM_INV & flags) + data |= 1 << 12; + if (SH_FSI_BRM_INV & flags) + data |= 1 << 8; + if (SH_FSI_LRS_INV & flags) + data |= 1 << 4; + if (SH_FSI_BRS_INV & flags) + data |= 1 << 0; + fsi_reg_write(fsi, CKG2, data); /* do fmt, di fmt */ @@ -696,36 +707,30 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); switch (fmt) { case SH_FSI_FMT_MONO: - msg = "MONO"; - data = CR_FMT(CR_MONO); + data = CR_MONO; fsi->chan = 1; break; case SH_FSI_FMT_MONO_DELAY: - msg = "MONO Delay"; - data = CR_FMT(CR_MONO_D); + data = CR_MONO_D; fsi->chan = 1; break; case SH_FSI_FMT_PCM: - msg = "PCM"; - data = CR_FMT(CR_PCM); + data = CR_PCM; fsi->chan = 2; break; case SH_FSI_FMT_I2S: - msg = "I2S"; - data = CR_FMT(CR_I2S); + data = CR_I2S; fsi->chan = 2; break; case SH_FSI_FMT_TDM: - msg = "TDM"; - data = CR_FMT(CR_TDM) | (fsi->chan - 1); fsi->chan = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); + data = CR_TDM | (fsi->chan - 1); break; case SH_FSI_FMT_TDM_DELAY: - msg = "TDM Delay"; - data = CR_FMT(CR_TDM_D) | (fsi->chan - 1); fsi->chan = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); + data = CR_TDM_D | (fsi->chan - 1); break; default: dev_err(dai->dev, "unknown format.\n"); @@ -733,12 +738,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, } fsi_reg_write(fsi, reg, data); - /* - * clear clk reset if master mode - */ - if (is_master) - fsi_clk_ctrl(fsi, 1); - /* irq clear */ fsi_irq_disable(fsi, is_play); fsi_irq_clear_status(fsi); @@ -785,10 +784,98 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } +static int fsi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct fsi_priv *fsi = fsi_get_priv(substream); + struct fsi_master *master = fsi_get_master(fsi); + int (*set_rate)(int is_porta, int rate) = master->info->set_rate; + int fsi_ver = master->core->ver; + int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + int ret; + + /* if slave mode, set_rate is not needed */ + if (!fsi_is_master_mode(fsi, is_play)) + return 0; + + /* it is error if no set_rate */ + if (!set_rate) + return -EIO; + + /* clock stop */ + pm_runtime_put_sync(dai->dev); + fsi_clk_ctrl(fsi, 0); + + ret = set_rate(fsi_is_port_a(fsi), params_rate(params)); + if (ret > 0) { + u32 data = 0; + + switch (ret & SH_FSI_ACKMD_MASK) { + default: + /* FALL THROUGH */ + case SH_FSI_ACKMD_512: + data |= (0x0 << 12); + break; + case SH_FSI_ACKMD_256: + data |= (0x1 << 12); + break; + case SH_FSI_ACKMD_128: + data |= (0x2 << 12); + break; + case SH_FSI_ACKMD_64: + data |= (0x3 << 12); + break; + case SH_FSI_ACKMD_32: + if (fsi_ver < 2) + dev_err(dai->dev, "unsupported ACKMD\n"); + else + data |= (0x4 << 12); + break; + } + + switch (ret & SH_FSI_BPFMD_MASK) { + default: + /* FALL THROUGH */ + case SH_FSI_BPFMD_32: + data |= (0x0 << 8); + break; + case SH_FSI_BPFMD_64: + data |= (0x1 << 8); + break; + case SH_FSI_BPFMD_128: + data |= (0x2 << 8); + break; + case SH_FSI_BPFMD_256: + data |= (0x3 << 8); + break; + case SH_FSI_BPFMD_512: + data |= (0x4 << 8); + break; + case SH_FSI_BPFMD_16: + if (fsi_ver < 2) + dev_err(dai->dev, "unsupported ACKMD\n"); + else + data |= (0x7 << 8); + break; + } + + fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); + udelay(10); + fsi_clk_ctrl(fsi, 1); + ret = 0; + } + pm_runtime_get_sync(dai->dev); + + return ret; + +} + static struct snd_soc_dai_ops fsi_dai_ops = { .startup = fsi_dai_startup, .shutdown = fsi_dai_shutdown, .trigger = fsi_dai_trigger, + .hw_params = fsi_dai_hw_params, }; /************************************************************************ @@ -1000,7 +1087,7 @@ static int fsi_probe(struct platform_device *pdev) master->fsia.master = master; master->fsib.base = master->base + 0x40; master->fsib.master = master; - master->regs = (struct fsi_regs *)id_entry->driver_data; + master->core = (struct fsi_core *)id_entry->driver_data; spin_lock_init(&master->lock); pm_runtime_enable(&pdev->dev); @@ -1081,21 +1168,27 @@ static struct dev_pm_ops fsi_pm_ops = { .runtime_resume = fsi_runtime_nop, }; -static struct fsi_regs fsi_regs = { +static struct fsi_core fsi1_core = { + .ver = 1, + + /* Interrupt */ .int_st = INT_ST, .iemsk = IEMSK, .imsk = IMSK, }; -static struct fsi_regs fsi2_regs = { +static struct fsi_core fsi2_core = { + .ver = 2, + + /* Interrupt */ .int_st = CPU_INT_ST, .iemsk = CPU_IEMSK, .imsk = CPU_IMSK, }; static struct platform_device_id fsi_id_table[] = { - { "sh_fsi", (kernel_ulong_t)&fsi_regs }, - { "sh_fsi2", (kernel_ulong_t)&fsi2_regs }, + { "sh_fsi", (kernel_ulong_t)&fsi1_core }, + { "sh_fsi2", (kernel_ulong_t)&fsi2_core }, }; static struct platform_driver fsi_driver = { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8b79d90efdc..5299932db0b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -84,7 +84,7 @@ static int run_delayed_work(struct delayed_work *dwork) /* codec register dump */ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) { - int i, step = 1, count = 0; + int ret, i, step = 1, count = 0; if (!codec->reg_cache_size) return 0; @@ -101,12 +101,24 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) if (count >= PAGE_SIZE - 1) break; - if (codec->display_register) + if (codec->display_register) { count += codec->display_register(codec, buf + count, PAGE_SIZE - count, i); - else - count += snprintf(buf + count, PAGE_SIZE - count, - "%4x", codec->read(codec, i)); + } else { + /* If the read fails it's almost certainly due to + * the register being volatile and the device being + * powered off. + */ + ret = codec->read(codec, i); + if (ret >= 0) + count += snprintf(buf + count, + PAGE_SIZE - count, + "%4x", ret); + else + count += snprintf(buf + count, + PAGE_SIZE - count, + "<no data: %d>", ret); + } if (count >= PAGE_SIZE - 1) break; |