From d4686c654bb1d7ea226578d5725ca34911d6e34c Mon Sep 17 00:00:00 2001 From: Jorge Eduardo Candelaria Date: Mon, 20 Dec 2010 11:32:47 -0600 Subject: ASoC: mcbsp: Add McBSP support for OMAP4 This patch adds McBSP support for the OMAP4 CPU Signed-off-by: Jorge Eduardo Candelaria Signed-off-by: Margarita Olaya Cabrera Acked-by: Mark Brown Acked-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Liam Girdwood diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 7e84f24..d203f4d 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -102,6 +102,17 @@ static const int omap24xx_dma_reqs[][2] = { static const int omap24xx_dma_reqs[][2] = {}; #endif +#if defined(CONFIG_ARCH_OMAP4) +static const int omap44xx_dma_reqs[][2] = { + { OMAP44XX_DMA_MCBSP1_TX, OMAP44XX_DMA_MCBSP1_RX }, + { OMAP44XX_DMA_MCBSP2_TX, OMAP44XX_DMA_MCBSP2_RX }, + { OMAP44XX_DMA_MCBSP3_TX, OMAP44XX_DMA_MCBSP3_RX }, + { OMAP44XX_DMA_MCBSP4_TX, OMAP44XX_DMA_MCBSP4_RX }, +}; +#else +static const int omap44xx_dma_reqs[][2] = {}; +#endif + #if defined(CONFIG_ARCH_OMAP2420) static const unsigned long omap2420_mcbsp_port[][2] = { { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1, @@ -147,6 +158,21 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { static const unsigned long omap34xx_mcbsp_port[][2] = {}; #endif +#if defined(CONFIG_ARCH_OMAP4) +static const unsigned long omap44xx_mcbsp_port[][2] = { + { OMAP44XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR, + OMAP44XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR }, + { OMAP44XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR, + OMAP44XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR }, + { OMAP44XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR, + OMAP44XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR }, + { OMAP44XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR, + OMAP44XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR }, +}; +#else +static const unsigned long omap44xx_mcbsp_port[][2] = {}; +#endif + static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -224,7 +250,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) */ - if (cpu_is_omap343x()) { + if (cpu_is_omap343x() || cpu_is_omap44xx()) { /* * Rule for the buffer size. We should not allow * smaller buffer than the FIFO size to avoid underruns @@ -332,6 +358,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, } else if (cpu_is_omap343x()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; + } else if (cpu_is_omap44xx()) { + dma = omap44xx_dma_reqs[bus_id][substream->stream]; + port = omap44xx_mcbsp_port[bus_id][substream->stream]; } else { return -ENODEV; } @@ -498,11 +527,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); /* RFIG and XFIG are not defined in 34xx */ - if (!cpu_is_omap34xx()) { + if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { regs->rcr2 |= RFIG; regs->xcr2 |= XFIG; } - if (cpu_is_omap2430() || cpu_is_omap34xx()) { + if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; } diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index ffdcc5a..110c106 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -50,6 +50,10 @@ enum omap_mcbsp_div { #undef NUM_LINKS #define NUM_LINKS 3 #endif +#if defined(CONFIG_ARCH_OMAP4) +#undef NUM_LINKS +#define NUM_LINKS 4 +#endif #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) #undef NUM_LINKS #define NUM_LINKS 5 -- cgit v0.10.2 From f769bdf2a7ee97c8e762fc133ff00aabe935867b Mon Sep 17 00:00:00 2001 From: "Olaya, Margarita" Date: Mon, 20 Dec 2010 10:39:20 -0600 Subject: ASoC: twl6040: Convert HF and HS drivers to use DAPM OUT_DRV widget Make the phoenix HS and HF drivers use the new DAPM driver widget in order to guarantee power ON/OFF order sequence. Signed-off-by: Margarita Olaya Cabrera Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 2f68f59..4bbf1b1 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1138,19 +1138,19 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { SND_SOC_NOPM, 0, 0, &hsr_mux_controls), /* Analog playback drivers */ - SND_SOC_DAPM_PGA_E("Handsfree Left Driver", + SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver", TWL6040_REG_HFLCTL, 4, 0, NULL, 0, pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Handsfree Right Driver", + SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver", TWL6040_REG_HFRCTL, 4, 0, NULL, 0, pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Headset Left Driver", + SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver", TWL6040_REG_HSLCTL, 2, 0, NULL, 0, pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Headset Right Driver", + SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver", TWL6040_REG_HSRCTL, 2, 0, NULL, 0, pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -- cgit v0.10.2 From 3591f4cd53a3835e6d59dd509337503c2c61173e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Dec 2010 10:45:16 +0200 Subject: ASoC: tlv320dac33: Remove manual FIFO configuration The manual FIFO configuration was the first version to enable the use of the FIFO in the codec. It had served it's purpose as debugging aid, but the automatic FIFO configuration is much safer to use. The removal of the manual controls, and configuration makes it easier to add new features for the codec later, since the manual mode neded different ways to calculate, and protect against misconfiguration. Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 776ac80..c574ae2 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -46,8 +46,6 @@ * 6144 stereo */ #define DAC33_BUFFER_SIZE_SAMPLES 6144 -#define NSAMPLE_MAX 5700 - #define MODE7_LTHR 10 #define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) @@ -99,16 +97,10 @@ struct tlv320dac33_priv { unsigned int refclk; unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */ - unsigned int nsample_min; /* nsample should not be lower than - * this */ - unsigned int nsample_max; /* nsample should not be higher than - * this */ enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ unsigned int nsample; /* burst read amount from host */ int mode1_latency; /* latency caused by the i2c writes in * us */ - int auto_fifo_config; /* Configure the FIFO based on the - * period size */ u8 burst_bclkdiv; /* BCLK divider value in burst mode */ unsigned int burst_rate; /* Interface speed in Burst modes */ @@ -436,73 +428,6 @@ static int dac33_playback_event(struct snd_soc_dapm_widget *w, return 0; } -static int dac33_get_nsample(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = dac33->nsample; - - return 0; -} - -static int dac33_set_nsample(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - if (dac33->nsample == ucontrol->value.integer.value[0]) - return 0; - - if (ucontrol->value.integer.value[0] < dac33->nsample_min || - ucontrol->value.integer.value[0] > dac33->nsample_max) { - ret = -EINVAL; - } else { - dac33->nsample = ucontrol->value.integer.value[0]; - /* Re calculate the burst time */ - dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, - dac33->nsample); - } - - return ret; -} - -static int dac33_get_uthr(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = dac33->uthr; - - return 0; -} - -static int dac33_set_uthr(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - if (dac33->substream) - return -EBUSY; - - if (dac33->uthr == ucontrol->value.integer.value[0]) - return 0; - - if (ucontrol->value.integer.value[0] < (MODE7_LTHR + 10) || - ucontrol->value.integer.value[0] > MODE7_UTHR) - ret = -EINVAL; - else - dac33->uthr = ucontrol->value.integer.value[0]; - - return ret; -} - static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -587,13 +512,6 @@ static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { dac33_get_fifo_mode, dac33_set_fifo_mode), }; -static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = { - SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, - dac33_get_nsample, dac33_set_nsample), - SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0, - dac33_get_uthr, dac33_set_uthr), -}; - /* Analog bypass */ static const struct snd_kcontrol_new dac33_dapm_abypassl_control = SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1); @@ -853,10 +771,6 @@ static void dac33_shutdown(struct snd_pcm_substream *substream, struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33->substream = NULL; - - /* Reset the nSample restrictions */ - dac33->nsample_min = 0; - dac33->nsample_max = NSAMPLE_MAX; } static int dac33_hw_params(struct snd_pcm_substream *substream, @@ -1112,39 +1026,19 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; - if (dac33->auto_fifo_config) { - if (period_size <= dac33->alarm_threshold) - /* - * Configure nSamaple to number of periods, - * which covers the latency requironment. - */ - dac33->nsample = period_size * - ((dac33->alarm_threshold / period_size) + - (dac33->alarm_threshold % period_size ? - 1 : 0)); - else if (period_size > nsample_limit) - dac33->nsample = nsample_limit; - else - dac33->nsample = period_size; - } else { - /* nSample time shall not be shorter than i2c latency */ - dac33->nsample_min = dac33->alarm_threshold; + if (period_size <= dac33->alarm_threshold) /* - * nSample should not be bigger than alsa buffer minus - * size of one period to avoid overruns + * Configure nSamaple to number of periods, + * which covers the latency requironment. */ - dac33->nsample_max = substream->runtime->buffer_size - - period_size; - - if (dac33->nsample_max > nsample_limit) - dac33->nsample_max = nsample_limit; - - /* Correct the nSample if it is outside of the ranges */ - if (dac33->nsample < dac33->nsample_min) - dac33->nsample = dac33->nsample_min; - if (dac33->nsample > dac33->nsample_max) - dac33->nsample = dac33->nsample_max; - } + dac33->nsample = period_size * + ((dac33->alarm_threshold / period_size) + + (dac33->alarm_threshold % period_size ? + 1 : 0)); + else if (period_size > nsample_limit) + dac33->nsample = nsample_limit; + else + dac33->nsample = period_size; dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, dac33->nsample); @@ -1152,16 +1046,13 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) dac33->t_stamp2 = 0; break; case DAC33_FIFO_MODE7: - if (dac33->auto_fifo_config) { - dac33->uthr = UTHR_FROM_PERIOD_SIZE( - period_size, - rate, - dac33->burst_rate) + 9; - if (dac33->uthr > MODE7_UTHR) - dac33->uthr = MODE7_UTHR; - if (dac33->uthr < (MODE7_LTHR + 10)) - dac33->uthr = (MODE7_LTHR + 10); - } + dac33->uthr = UTHR_FROM_PERIOD_SIZE(period_size, rate, + dac33->burst_rate) + 9; + if (dac33->uthr > MODE7_UTHR) + dac33->uthr = MODE7_UTHR; + if (dac33->uthr < (MODE7_LTHR + 10)) + dac33->uthr = (MODE7_LTHR + 10); + dac33->mode7_us_to_lthr = SAMPLES_TO_US(substream->runtime->rate, dac33->uthr - MODE7_LTHR + 1); @@ -1486,14 +1377,10 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) snd_soc_add_controls(codec, dac33_snd_controls, ARRAY_SIZE(dac33_snd_controls)); /* Only add the FIFO controls, if we have valid IRQ number */ - if (dac33->irq >= 0) { + if (dac33->irq >= 0) snd_soc_add_controls(codec, dac33_mode_snd_controls, ARRAY_SIZE(dac33_mode_snd_controls)); - /* FIFO usage controls only, if autoio config is not selected */ - if (!dac33->auto_fifo_config) - snd_soc_add_controls(codec, dac33_fifo_snd_controls, - ARRAY_SIZE(dac33_fifo_snd_controls)); - } + dac33_add_widgets(codec); err_power: @@ -1593,14 +1480,10 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, /* Pre calculate the burst rate */ dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; dac33->keep_bclk = pdata->keep_bclk; - dac33->auto_fifo_config = pdata->auto_fifo_config; dac33->mode1_latency = pdata->mode1_latency; if (!dac33->mode1_latency) dac33->mode1_latency = 10000; /* 10ms */ dac33->irq = client->irq; - dac33->nsample = NSAMPLE_MAX; - dac33->nsample_max = NSAMPLE_MAX; - dac33->uthr = MODE7_UTHR; /* Disable FIFO use by default */ dac33->fifo_mode = DAC33_FIFO_BYPASS; -- cgit v0.10.2 From 549675ed658761b9a84cb579795c9ec1da227fea Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Dec 2010 10:45:17 +0200 Subject: ASoC: tlv320dac33: Some cleanup for 32/24 bit support Change the structure of FIFO handling in order to pave the way for adding 32/24 bit audio support. Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index c574ae2..05a4e9f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -42,12 +42,15 @@ #include #include "tlv320dac33.h" -#define DAC33_BUFFER_SIZE_BYTES 24576 /* bytes, 12288 16 bit words, - * 6144 stereo */ -#define DAC33_BUFFER_SIZE_SAMPLES 6144 - -#define MODE7_LTHR 10 -#define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) +/* + * The internal FIFO is 24576 bytes long + * It can be configured to hold 16bit or 24bit samples + * In 16bit configuration the FIFO can hold 6144 stereo samples + * In 24bit configuration the FIFO can hold 4096 stereo samples + */ +#define DAC33_FIFO_SIZE_16BIT 6144 +#define DAC33_FIFO_SIZE_24BIT 4096 +#define DAC33_MODE7_MARGIN 10 /* Safety margin for FIFO in Mode7 */ #define BURST_BASEFREQ_HZ 49152000 @@ -98,6 +101,7 @@ struct tlv320dac33_priv { unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */ enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ + unsigned int fifo_size; /* Size of the FIFO in samples */ unsigned int nsample; /* burst read amount from host */ int mode1_latency; /* latency caused by the i2c writes in * us */ @@ -650,7 +654,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) spin_unlock_irq(&dac33->lock); dac33_write16(codec, DAC33_PREFILL_MSB, - DAC33_THRREG(MODE7_LTHR)); + DAC33_THRREG(DAC33_MODE7_MARGIN)); /* Enable Upper Threshold IRQ */ dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MUT); @@ -773,12 +777,15 @@ static void dac33_shutdown(struct snd_pcm_substream *substream, dac33->substream = NULL; } +#define CALC_BURST_RATE(bclkdiv, bclk_per_sample) \ + (BURST_BASEFREQ_HZ / bclkdiv / bclk_per_sample) static int dac33_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); /* Check parameters for validity */ switch (params_rate(params)) { @@ -793,6 +800,8 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: + dac33->fifo_size = DAC33_FIFO_SIZE_16BIT; + dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32); break; default: dev_err(codec->dev, "unsupported format %d\n", @@ -994,7 +1003,8 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) * at the bottom, and also at the top of the FIFO */ dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr)); - dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR)); + dac33_write16(codec, DAC33_LTHR_MSB, + DAC33_THRREG(DAC33_MODE7_MARGIN)); break; default: break; @@ -1023,8 +1033,7 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) /* Number of samples under i2c latency */ dac33->alarm_threshold = US_TO_SAMPLES(rate, dac33->mode1_latency); - nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - - dac33->alarm_threshold; + nsample_limit = dac33->fifo_size - dac33->alarm_threshold; if (period_size <= dac33->alarm_threshold) /* @@ -1048,14 +1057,14 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) case DAC33_FIFO_MODE7: dac33->uthr = UTHR_FROM_PERIOD_SIZE(period_size, rate, dac33->burst_rate) + 9; - if (dac33->uthr > MODE7_UTHR) - dac33->uthr = MODE7_UTHR; - if (dac33->uthr < (MODE7_LTHR + 10)) - dac33->uthr = (MODE7_LTHR + 10); + if (dac33->uthr > (dac33->fifo_size - DAC33_MODE7_MARGIN)) + dac33->uthr = dac33->fifo_size - DAC33_MODE7_MARGIN; + if (dac33->uthr < (DAC33_MODE7_MARGIN + 10)) + dac33->uthr = (DAC33_MODE7_MARGIN + 10); dac33->mode7_us_to_lthr = SAMPLES_TO_US(substream->runtime->rate, - dac33->uthr - MODE7_LTHR + 1); + dac33->uthr - DAC33_MODE7_MARGIN + 1); dac33->t_stamp1 = 0; break; default: @@ -1173,8 +1182,8 @@ static snd_pcm_sframes_t dac33_dai_delay( samples += (samples_in - samples_out); if (likely(samples > 0)) - delay = samples > DAC33_BUFFER_SIZE_SAMPLES ? - DAC33_BUFFER_SIZE_SAMPLES : samples; + delay = samples > dac33->fifo_size ? + dac33->fifo_size : samples; else delay = 0; } @@ -1226,7 +1235,7 @@ static snd_pcm_sframes_t dac33_dai_delay( samples_in = US_TO_SAMPLES( dac33->burst_rate, time_delta); - delay = MODE7_LTHR + samples_in - samples_out; + delay = DAC33_MODE7_MARGIN + samples_in - samples_out; if (unlikely(delay > uthr)) delay = uthr; @@ -1477,8 +1486,6 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, dac33->power_gpio = pdata->power_gpio; dac33->burst_bclkdiv = pdata->burst_bclkdiv; - /* Pre calculate the burst rate */ - dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; dac33->keep_bclk = pdata->keep_bclk; dac33->mode1_latency = pdata->mode1_latency; if (!dac33->mode1_latency) -- cgit v0.10.2 From 0d99d2b036974ed1160f9d10457b6054646fb7d6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Dec 2010 10:45:18 +0200 Subject: ASoC: tlv320dac33: Add 32/24 bit audio support Add support for 24 bit audio (with S32_LE msbits 24). The reason to limit the msbits to 24, is that the FIFO can be configured for 16 or 24 bit layout. It is unknown how the codec would downsample from 32 to 24 bit, if the interface is configured to receive 32 bit data. Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 05a4e9f..13d521c 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -764,6 +764,8 @@ static int dac33_startup(struct snd_pcm_substream *substream, /* Stream started, save the substream pointer */ dac33->substream = substream; + snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24); + return 0; } @@ -803,6 +805,10 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, dac33->fifo_size = DAC33_FIFO_SIZE_16BIT; dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32); break; + case SNDRV_PCM_FORMAT_S32_LE: + dac33->fifo_size = DAC33_FIFO_SIZE_24BIT; + dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64); + break; default: dev_err(codec->dev, "unsupported format %d\n", params_format(params)); @@ -856,6 +862,9 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) aictrl_a |= (DAC33_NCYCL_16 | DAC33_WLEN_16); fifoctrl_a |= DAC33_WIDTH; break; + case SNDRV_PCM_FORMAT_S32_LE: + aictrl_a |= (DAC33_NCYCL_32 | DAC33_WLEN_24); + break; default: dev_err(codec->dev, "unsupported format %d\n", substream->runtime->format); @@ -990,7 +999,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, dac33->burst_bclkdiv); else - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32); + if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE) + dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32); + else + dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 16); switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: @@ -1438,7 +1450,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) -#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE +#define DAC33_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) static struct snd_soc_dai_ops dac33_dai_ops = { .startup = dac33_startup, -- cgit v0.10.2 From a710770e05563fd5add9af686569ee9fa56bbd65 Mon Sep 17 00:00:00 2001 From: David Lambert Date: Thu, 6 Jan 2011 08:00:37 -0600 Subject: ASoC: DMIC codec: Adding a generic DMIC codec This codec is to be used by the DMIC driver to control the DMIC codec. This driver will be used on future implementations of the DMIC driver to support codec specific features. At this time, the codec driver just registers the codec DAI. Signed-off-by: David Lambert Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0f33db2..f6c6d31 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -166,6 +166,9 @@ config SND_SOC_L3 config SND_SOC_DA7210 tristate +config SND_SOC_DMIC + tristate + config SND_SOC_MAX98088 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 10e5e09..9139cf9 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -14,6 +14,7 @@ snd-soc-cs42l51-objs := cs42l51.o snd-soc-cs4270-objs := cs4270.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o +snd-soc-dmic-objs := dmic.o snd-soc-l3-objs := l3.o snd-soc-max98088-objs := max98088.o snd-soc-pcm3008-objs := pcm3008.o @@ -91,6 +92,7 @@ obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o +obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c new file mode 100644 index 0000000..57e9dac --- /dev/null +++ b/sound/soc/codecs/dmic.c @@ -0,0 +1,81 @@ +/* + * dmic.c -- SoC audio for Generic Digital MICs + * + * Author: Liam Girdwood + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include + +static struct snd_soc_dai_driver dmic_dai = { + .name = "dmic-hifi", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .formats = SNDRV_PCM_FMTBIT_S32_LE + | SNDRV_PCM_FMTBIT_S24_LE + | SNDRV_PCM_FMTBIT_S16_LE, + }, +}; + +static struct snd_soc_codec_driver soc_dmic = {}; + +static int __devinit dmic_dev_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, + &soc_dmic, &dmic_dai, 1); +} + +static int __devexit dmic_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +MODULE_ALIAS("platform:dmic-codec"); + +static struct platform_driver dmic_driver = { + .driver = { + .name = "dmic-codec", + .owner = THIS_MODULE, + }, + .probe = dmic_dev_probe, + .remove = __devexit_p(dmic_dev_remove), +}; + +static int __init dmic_init(void) +{ + return platform_driver_register(&dmic_driver); +} +module_init(dmic_init); + +static void __exit dmic_exit(void) +{ + platform_driver_unregister(&dmic_driver); +} +module_exit(dmic_exit); + +MODULE_DESCRIPTION("Generic DMIC driver"); +MODULE_AUTHOR("Liam Girdwood "); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 399b82e4930f5f97556c7fd84ea3ef312718adee Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Jan 2011 15:39:49 +0200 Subject: ASoC: tlv320dac33: Add DAPM selection for LOM invert The L/R LOM line can be invertined side of the corresponding DAC, or inverted from the corresponding LOP. Add control for user space to select the source of the LOM inversion. When only the analog bypass is enabled, and the LOM is inverted from DAC output, we need to power the corresponding DAC. Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 13d521c..71d7be8 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -298,7 +298,6 @@ static void dac33_init_chip(struct snd_soc_codec *codec) if (unlikely(!dac33->chip_power)) return; - /* 44-46: DAC Control Registers */ /* A : DAC sample rate Fsref/1.5 */ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); /* B : DAC src=normal, not muted */ @@ -321,6 +320,10 @@ static void dac33_init_chip(struct snd_soc_codec *codec) dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL)); dac33_write(codec, DAC33_LINER_TO_RLO_VOL, dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL)); + + dac33_write(codec, DAC33_OUT_AMP_CTRL, + dac33_read_reg_cache(codec, DAC33_OUT_AMP_CTRL)); + } static inline int dac33_read_id(struct snd_soc_codec *codec) @@ -523,6 +526,25 @@ static const struct snd_kcontrol_new dac33_dapm_abypassl_control = static const struct snd_kcontrol_new dac33_dapm_abypassr_control = SOC_DAPM_SINGLE("Switch", DAC33_LINER_TO_RLO_VOL, 7, 1, 1); +/* LOP L/R invert selection */ +static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; + +static const struct soc_enum dac33_left_lom_enum = + SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3, + ARRAY_SIZE(dac33_lr_lom_texts), + dac33_lr_lom_texts); + +static const struct snd_kcontrol_new dac33_dapm_left_lom_control = +SOC_DAPM_ENUM("Route", dac33_left_lom_enum); + +static const struct soc_enum dac33_right_lom_enum = + SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2, + ARRAY_SIZE(dac33_lr_lom_texts), + dac33_lr_lom_texts); + +static const struct snd_kcontrol_new dac33_dapm_right_lom_control = +SOC_DAPM_ENUM("Route", dac33_right_lom_enum); + static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("LEFT_LO"), SND_SOC_DAPM_OUTPUT("RIGHT_LO"), @@ -539,6 +561,18 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, &dac33_dapm_abypassr_control), + SND_SOC_DAPM_MUX("Left LOM Inverted From", SND_SOC_NOPM, 0, 0, + &dac33_dapm_left_lom_control), + SND_SOC_DAPM_MUX("Right LOM Inverted From", SND_SOC_NOPM, 0, 0, + &dac33_dapm_right_lom_control), + /* + * For DAPM path, when only the anlog bypass path is enabled, and the + * LOP inverted from the corresponding DAC side. + * This is needed, so we can attach the DAC power supply in this case. + */ + SND_SOC_DAPM_PGA("Left Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier", DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier", @@ -561,11 +595,22 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Output Left Amplifier", NULL, "DACL"}, {"Output Right Amplifier", NULL, "DACR"}, - {"Output Left Amplifier", NULL, "Analog Left Bypass"}, - {"Output Right Amplifier", NULL, "Analog Right Bypass"}, + {"Left Bypass PGA", NULL, "Analog Left Bypass"}, + {"Right Bypass PGA", NULL, "Analog Right Bypass"}, + + {"Left LOM Inverted From", "DAC", "Left Bypass PGA"}, + {"Right LOM Inverted From", "DAC", "Right Bypass PGA"}, + {"Left LOM Inverted From", "LOP", "Analog Left Bypass"}, + {"Right LOM Inverted From", "LOP", "Analog Right Bypass"}, + + {"Output Left Amplifier", NULL, "Left LOM Inverted From"}, + {"Output Right Amplifier", NULL, "Right LOM Inverted From"}, + + {"DACL", NULL, "Left DAC Power"}, + {"DACR", NULL, "Right DAC Power"}, - {"Output Left Amplifier", NULL, "Left DAC Power"}, - {"Output Right Amplifier", NULL, "Right DAC Power"}, + {"Left Bypass PGA", NULL, "Left DAC Power"}, + {"Right Bypass PGA", NULL, "Right DAC Power"}, /* output */ {"LEFT_LO", NULL, "Output Left Amplifier"}, -- cgit v0.10.2 From 559a8cd629f1b797732fd97afd58b41d8b6fb312 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 28 Dec 2010 11:16:19 +0200 Subject: ASoC: tpa6130a2: Fix compiler warning sound/soc/codecs/tpa6130a2.c: In function 'tpa6130a2_add_controls': sound/soc/codecs/tpa6130a2.c:342: warning: unused variable 'dapm' Introduced by commit 39646871a47fd8808c08de0ce7d7ca8393af2805 ("ASoC: tpa6130a2: Replace DAPM code with direct interface"). The DAPM code has been removed from the driver, but the dapm struct remained. Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown Signed-off-by: Liam Girdwood diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 0a99f31..1f1ac81 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); int tpa6130a2_add_controls(struct snd_soc_codec *codec) { struct tpa6130a2_data *data; - struct snd_soc_dapm_context *dapm = &codec->dapm; if (tpa6130a2_client == NULL) return -ENODEV; -- cgit v0.10.2