Loading include/sound/tlv320dac33-plat.h +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ struct tlv320dac33_platform_data { int power_gpio; int mode1_latency; /* latency caused by the i2c writes in us */ int auto_fifo_config; /* FIFO config based on the period size */ int keep_bclk; /* Keep the BCLK running in FIFO modes */ u8 burst_bclkdiv; }; Loading sound/soc/codecs/tlv320dac33.c +80 −45 Original line number Diff line number Diff line Loading @@ -49,8 +49,6 @@ #define NSAMPLE_MAX 5700 #define LATENCY_TIME_MS 20 #define MODE7_LTHR 10 #define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) Loading @@ -62,6 +60,9 @@ #define US_TO_SAMPLES(rate, us) \ (rate / (1000000 / us)) #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate))) static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); Loading Loading @@ -107,6 +108,10 @@ struct tlv320dac33_priv { * 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 */ Loading Loading @@ -538,13 +543,16 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = { DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), }; static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, 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), SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, dac33_get_fifo_mode, dac33_set_fifo_mode), }; /* Analog bypass */ Loading Loading @@ -649,7 +657,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: dac33_write16(codec, DAC33_NSAMPLE_MSB, DAC33_THRREG(dac33->nsample + dac33->alarm_threshold)); DAC33_THRREG(dac33->nsample)); /* Take the timestamps */ spin_lock_irq(&dac33->lock); Loading Loading @@ -798,6 +806,10 @@ 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, Loading Loading @@ -1040,54 +1052,68 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned int period_size = substream->runtime->period_size; unsigned int rate = substream->runtime->rate; unsigned int nsample_limit; /* In bypass mode we don't need to calculate */ if (!dac33->fifo_mode) return; /* Number of samples (16bit, stereo) in one period */ dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4; /* Number of samples (16bit, stereo) in ALSA buffer */ dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4; /* Subtract one period from the total */ dac33->nsample_max -= dac33->nsample_min; /* Number of samples for LATENCY_TIME_MS / 2 */ dac33->alarm_threshold = substream->runtime->rate / (1000 / (LATENCY_TIME_MS / 2)); /* Find and fix up the lowest nsmaple limit */ nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS); if (dac33->nsample_min < nsample_limit) dac33->nsample_min = nsample_limit; if (dac33->nsample < dac33->nsample_min) dac33->nsample = dac33->nsample_min; switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: /* Number of samples under i2c latency */ dac33->alarm_threshold = US_TO_SAMPLES(rate, dac33->mode1_latency); if (dac33->auto_fifo_config) { if (period_size <= dac33->alarm_threshold) /* * Find and fix up the highest nsmaple limit * In order to not overflow the DAC33 buffer substract the * alarm_threshold value from the size of the DAC33 buffer * Configure nSamaple to number of periods, * which covers the latency requironment. */ nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; dac33->nsample = period_size * ((dac33->alarm_threshold / period_size) + (dac33->alarm_threshold % period_size ? 1 : 0)); else dac33->nsample = period_size; } else { /* nSample time shall not be shorter than i2c latency */ dac33->nsample_min = dac33->alarm_threshold; /* * nSample should not be bigger than alsa buffer minus * size of one period to avoid overruns */ dac33->nsample_max = substream->runtime->buffer_size - period_size; nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; 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; } switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, dac33->nsample); dac33->t_stamp1 = 0; 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->mode7_us_to_lthr = SAMPLES_TO_US(substream->runtime->rate, dac33->uthr - MODE7_LTHR + 1); Loading Loading @@ -1385,10 +1411,15 @@ static int dac33_soc_probe(struct platform_device *pdev) snd_soc_add_controls(codec, dac33_snd_controls, ARRAY_SIZE(dac33_snd_controls)); /* Only add the nSample controls, if we have valid IRQ number */ if (dac33->irq >= 0) snd_soc_add_controls(codec, dac33_nsample_snd_controls, ARRAY_SIZE(dac33_nsample_snd_controls)); /* Only add the FIFO controls, if we have valid IRQ number */ 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); Loading Loading @@ -1519,6 +1550,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; Loading sound/soc/codecs/twl4030.c +0 −2 Original line number Diff line number Diff line Loading @@ -1432,11 +1432,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { TX2 Left/Right: either analog Left/Right or Digimic1 */ SND_SOC_DAPM_MUX_E("TX1 Capture Route", SND_SOC_NOPM, 0, 0, &twl4030_dapm_micpathtx1_control, micpath_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| SND_SOC_DAPM_POST_REG), SND_SOC_DAPM_MUX_E("TX2 Capture Route", SND_SOC_NOPM, 0, 0, &twl4030_dapm_micpathtx2_control, micpath_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| SND_SOC_DAPM_POST_REG), /* Analog input mixers for the capture amplifiers */ Loading sound/soc/omap/omap-mcbsp.c +76 −61 Original line number Diff line number Diff line Loading @@ -155,12 +155,22 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_pcm_dma_data *dma_data; int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); int words; dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) /* The FIFO size depends on the McBSP word configuration */ /* * Configure McBSP threshold based on either: * packet_size, when the sDMA is in packet mode, or * based on the period size. */ if (dma_data->packet_size) words = dma_data->packet_size; else words = snd_pcm_lib_period_bytes(substream) / (mcbsp_data->wlen / 8); else Loading Loading @@ -192,31 +202,6 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, return snd_interval_refine(buffer_size, &frames); } static int omap_mcbsp_hwrule_max_periodsize(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval *period_size = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_pcm_substream *substream = rule->private; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct snd_interval frames; int size; snd_interval_any(&frames); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) size = omap_mcbsp_get_max_tx_threshold(mcbsp_data->bus_id); else size = omap_mcbsp_get_max_rx_threshold(mcbsp_data->bus_id); frames.max = size / channels->min; frames.integer = 1; return snd_interval_refine(period_size, &frames); } static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { Loading Loading @@ -245,10 +230,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) */ if (cpu_is_omap343x()) { int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); /* * The first rule is for the buffer size, we should not allow * Rule for the buffer size. We should not allow * smaller buffer than the FIFO size to avoid underruns */ snd_pcm_hw_rule_add(substream->runtime, 0, Loading @@ -257,17 +240,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, mcbsp_data, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); /* * In case of threshold mode, the rule will ensure, that the * period size is not bigger than the maximum allowed threshold * value. */ if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, omap_mcbsp_hwrule_max_periodsize, substream, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); /* Make sure, that the period size is always even */ snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); } return err; Loading Loading @@ -348,11 +323,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; struct omap_pcm_dma_data *dma_data; int dma, bus_id = mcbsp_data->bus_id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; int pkt_size = 0; unsigned long port; unsigned int format, div, framesize, master; dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; if (cpu_class_is_omap1()) { dma = omap1_dma_reqs[bus_id][substream->stream]; port = omap1_mcbsp_port[bus_id][substream->stream]; Loading @@ -365,35 +343,74 @@ 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]; omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) sync_mode = OMAP_DMA_SYNC_FRAME; } else { return -ENODEV; } omap_mcbsp_dai_dma_params[id][substream->stream].name = substream->stream ? "Audio Capture" : "Audio Playback"; omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: omap_mcbsp_dai_dma_params[id][substream->stream].data_type = OMAP_DMA_DATA_TYPE_S16; dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: omap_mcbsp_dai_dma_params[id][substream->stream].data_type = OMAP_DMA_DATA_TYPE_S32; dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: return -EINVAL; } if (cpu_is_omap343x()) { dma_data->set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = omap_mcbsp_get_max_tx_threshold( mcbsp_data->bus_id); else max_thrsh = omap_mcbsp_get_max_rx_threshold( mcbsp_data->bus_id); /* * If the period contains less or equal number of words, * we are using the original threshold mode setup: * McBSP threshold = sDMA frame size = period_size * Otherwise we switch to sDMA packet mode: * McBSP threshold = sDMA packet size * sDMA frame size = period size */ if (period_words > max_thrsh) { int divider = 0; /* * Look for the biggest threshold value, which * divides the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; sync_mode = OMAP_DMA_SYNC_PACKET; } else { sync_mode = OMAP_DMA_SYNC_FRAME; } } } snd_soc_dai_set_dma_data(cpu_dai, substream, &omap_mcbsp_dai_dma_params[id][substream->stream]); dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; dma_data->dma_req = dma; dma_data->port_addr = port; dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); if (mcbsp_data->configured) { /* McBSP already configured by another stream */ Loading @@ -419,7 +436,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ wlen = 16; regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); Loading @@ -427,7 +443,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ wlen = 32; regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); Loading Loading
include/sound/tlv320dac33-plat.h +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ struct tlv320dac33_platform_data { int power_gpio; int mode1_latency; /* latency caused by the i2c writes in us */ int auto_fifo_config; /* FIFO config based on the period size */ int keep_bclk; /* Keep the BCLK running in FIFO modes */ u8 burst_bclkdiv; }; Loading
sound/soc/codecs/tlv320dac33.c +80 −45 Original line number Diff line number Diff line Loading @@ -49,8 +49,6 @@ #define NSAMPLE_MAX 5700 #define LATENCY_TIME_MS 20 #define MODE7_LTHR 10 #define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) Loading @@ -62,6 +60,9 @@ #define US_TO_SAMPLES(rate, us) \ (rate / (1000000 / us)) #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate))) static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); Loading Loading @@ -107,6 +108,10 @@ struct tlv320dac33_priv { * 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 */ Loading Loading @@ -538,13 +543,16 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = { DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), }; static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, 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), SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, dac33_get_fifo_mode, dac33_set_fifo_mode), }; /* Analog bypass */ Loading Loading @@ -649,7 +657,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: dac33_write16(codec, DAC33_NSAMPLE_MSB, DAC33_THRREG(dac33->nsample + dac33->alarm_threshold)); DAC33_THRREG(dac33->nsample)); /* Take the timestamps */ spin_lock_irq(&dac33->lock); Loading Loading @@ -798,6 +806,10 @@ 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, Loading Loading @@ -1040,54 +1052,68 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned int period_size = substream->runtime->period_size; unsigned int rate = substream->runtime->rate; unsigned int nsample_limit; /* In bypass mode we don't need to calculate */ if (!dac33->fifo_mode) return; /* Number of samples (16bit, stereo) in one period */ dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4; /* Number of samples (16bit, stereo) in ALSA buffer */ dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4; /* Subtract one period from the total */ dac33->nsample_max -= dac33->nsample_min; /* Number of samples for LATENCY_TIME_MS / 2 */ dac33->alarm_threshold = substream->runtime->rate / (1000 / (LATENCY_TIME_MS / 2)); /* Find and fix up the lowest nsmaple limit */ nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS); if (dac33->nsample_min < nsample_limit) dac33->nsample_min = nsample_limit; if (dac33->nsample < dac33->nsample_min) dac33->nsample = dac33->nsample_min; switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: /* Number of samples under i2c latency */ dac33->alarm_threshold = US_TO_SAMPLES(rate, dac33->mode1_latency); if (dac33->auto_fifo_config) { if (period_size <= dac33->alarm_threshold) /* * Find and fix up the highest nsmaple limit * In order to not overflow the DAC33 buffer substract the * alarm_threshold value from the size of the DAC33 buffer * Configure nSamaple to number of periods, * which covers the latency requironment. */ nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; dac33->nsample = period_size * ((dac33->alarm_threshold / period_size) + (dac33->alarm_threshold % period_size ? 1 : 0)); else dac33->nsample = period_size; } else { /* nSample time shall not be shorter than i2c latency */ dac33->nsample_min = dac33->alarm_threshold; /* * nSample should not be bigger than alsa buffer minus * size of one period to avoid overruns */ dac33->nsample_max = substream->runtime->buffer_size - period_size; nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; 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; } switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, dac33->nsample); dac33->t_stamp1 = 0; 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->mode7_us_to_lthr = SAMPLES_TO_US(substream->runtime->rate, dac33->uthr - MODE7_LTHR + 1); Loading Loading @@ -1385,10 +1411,15 @@ static int dac33_soc_probe(struct platform_device *pdev) snd_soc_add_controls(codec, dac33_snd_controls, ARRAY_SIZE(dac33_snd_controls)); /* Only add the nSample controls, if we have valid IRQ number */ if (dac33->irq >= 0) snd_soc_add_controls(codec, dac33_nsample_snd_controls, ARRAY_SIZE(dac33_nsample_snd_controls)); /* Only add the FIFO controls, if we have valid IRQ number */ 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); Loading Loading @@ -1519,6 +1550,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; Loading
sound/soc/codecs/twl4030.c +0 −2 Original line number Diff line number Diff line Loading @@ -1432,11 +1432,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { TX2 Left/Right: either analog Left/Right or Digimic1 */ SND_SOC_DAPM_MUX_E("TX1 Capture Route", SND_SOC_NOPM, 0, 0, &twl4030_dapm_micpathtx1_control, micpath_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| SND_SOC_DAPM_POST_REG), SND_SOC_DAPM_MUX_E("TX2 Capture Route", SND_SOC_NOPM, 0, 0, &twl4030_dapm_micpathtx2_control, micpath_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| SND_SOC_DAPM_POST_REG), /* Analog input mixers for the capture amplifiers */ Loading
sound/soc/omap/omap-mcbsp.c +76 −61 Original line number Diff line number Diff line Loading @@ -155,12 +155,22 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_pcm_dma_data *dma_data; int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); int words; dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) /* The FIFO size depends on the McBSP word configuration */ /* * Configure McBSP threshold based on either: * packet_size, when the sDMA is in packet mode, or * based on the period size. */ if (dma_data->packet_size) words = dma_data->packet_size; else words = snd_pcm_lib_period_bytes(substream) / (mcbsp_data->wlen / 8); else Loading Loading @@ -192,31 +202,6 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, return snd_interval_refine(buffer_size, &frames); } static int omap_mcbsp_hwrule_max_periodsize(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval *period_size = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_pcm_substream *substream = rule->private; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct snd_interval frames; int size; snd_interval_any(&frames); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) size = omap_mcbsp_get_max_tx_threshold(mcbsp_data->bus_id); else size = omap_mcbsp_get_max_rx_threshold(mcbsp_data->bus_id); frames.max = size / channels->min; frames.integer = 1; return snd_interval_refine(period_size, &frames); } static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { Loading Loading @@ -245,10 +230,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) */ if (cpu_is_omap343x()) { int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); /* * The first rule is for the buffer size, we should not allow * Rule for the buffer size. We should not allow * smaller buffer than the FIFO size to avoid underruns */ snd_pcm_hw_rule_add(substream->runtime, 0, Loading @@ -257,17 +240,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, mcbsp_data, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); /* * In case of threshold mode, the rule will ensure, that the * period size is not bigger than the maximum allowed threshold * value. */ if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, omap_mcbsp_hwrule_max_periodsize, substream, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); /* Make sure, that the period size is always even */ snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); } return err; Loading Loading @@ -348,11 +323,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; struct omap_pcm_dma_data *dma_data; int dma, bus_id = mcbsp_data->bus_id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; int pkt_size = 0; unsigned long port; unsigned int format, div, framesize, master; dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; if (cpu_class_is_omap1()) { dma = omap1_dma_reqs[bus_id][substream->stream]; port = omap1_mcbsp_port[bus_id][substream->stream]; Loading @@ -365,35 +343,74 @@ 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]; omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) sync_mode = OMAP_DMA_SYNC_FRAME; } else { return -ENODEV; } omap_mcbsp_dai_dma_params[id][substream->stream].name = substream->stream ? "Audio Capture" : "Audio Playback"; omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: omap_mcbsp_dai_dma_params[id][substream->stream].data_type = OMAP_DMA_DATA_TYPE_S16; dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: omap_mcbsp_dai_dma_params[id][substream->stream].data_type = OMAP_DMA_DATA_TYPE_S32; dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: return -EINVAL; } if (cpu_is_omap343x()) { dma_data->set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = omap_mcbsp_get_max_tx_threshold( mcbsp_data->bus_id); else max_thrsh = omap_mcbsp_get_max_rx_threshold( mcbsp_data->bus_id); /* * If the period contains less or equal number of words, * we are using the original threshold mode setup: * McBSP threshold = sDMA frame size = period_size * Otherwise we switch to sDMA packet mode: * McBSP threshold = sDMA packet size * sDMA frame size = period size */ if (period_words > max_thrsh) { int divider = 0; /* * Look for the biggest threshold value, which * divides the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; sync_mode = OMAP_DMA_SYNC_PACKET; } else { sync_mode = OMAP_DMA_SYNC_FRAME; } } } snd_soc_dai_set_dma_data(cpu_dai, substream, &omap_mcbsp_dai_dma_params[id][substream->stream]); dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; dma_data->dma_req = dma; dma_data->port_addr = port; dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); if (mcbsp_data->configured) { /* McBSP already configured by another stream */ Loading @@ -419,7 +436,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ wlen = 16; regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); Loading @@ -427,7 +443,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ wlen = 32; regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); Loading