Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 988b0dc1 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'for-2.6.36' of...

Merge branch 'for-2.6.36' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into topic/asoc
parents 3bc28070 998a8a69
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
};
+80 −45
Original line number Diff line number Diff line
@@ -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)

@@ -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);

@@ -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 */

@@ -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 */
@@ -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);
@@ -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,
@@ -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);
@@ -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);

@@ -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;
+0 −2
Original line number Diff line number Diff line
@@ -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 */
+76 −61
Original line number Diff line number Diff line
@@ -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
@@ -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)
{
@@ -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,
@@ -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;
@@ -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];
@@ -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 */
@@ -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);
@@ -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);