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

Commit 53a61d96 authored by Mark Brown's avatar Mark Brown
Browse files

Merge branch 'for-2.6.34' into for-2.6.35

Conflicts due to context changes next to the backported DMA data change:
	include/sound/soc.h
parents 88766984 5f712b2b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -381,7 +381,7 @@ struct snd_soc_pcm_stream {
	unsigned int rate_max;		/* max rate */
	unsigned int channels_min;	/* min channels */
	unsigned int channels_max;	/* max channels */
	unsigned int active;		/* num of active users of the stream */
	unsigned int active;		/* stream is in use */
	void *dma_data;			/* used by platform code */
};

+31 −25
Original line number Diff line number Diff line
@@ -3015,18 +3015,22 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
		break;

	case SND_SOC_BIAS_OFF:
		if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
			/* Switch over to startup biases */
			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
				    WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
					    WM8994_BIAS_SRC |
					    WM8994_STARTUP_BIAS_ENA |
					    WM8994_VMID_BUF_ENA |
					    WM8994_VMID_RAMP_MASK,
				    WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
					    WM8994_BIAS_SRC |
					    WM8994_STARTUP_BIAS_ENA |
					    WM8994_VMID_BUF_ENA |
					    (1 << WM8994_VMID_RAMP_SHIFT));

			/* Disable main biases */
			snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
				    WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
					    WM8994_BIAS_ENA |
					    WM8994_VMID_SEL_MASK, 0);

			/* Discharge line */
			snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
@@ -3039,10 +3043,11 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,

			/* Switch off startup biases */
			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
				    WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
					    WM8994_BIAS_SRC |
					    WM8994_STARTUP_BIAS_ENA |
					    WM8994_VMID_BUF_ENA |
					    WM8994_VMID_RAMP_MASK, 0);

		}
		break;
	}
	codec->bias_level = level;
@@ -3866,12 +3871,13 @@ static int wm8994_codec_probe(struct platform_device *pdev)
	case 3:
		wm8994->hubs.dcs_codes = -5;
		wm8994->hubs.hp_startup_mode = 1;
		wm8994->hubs.dcs_readback_mode = 1;
		break;
	default:
		wm8994->hubs.dcs_readback_mode = 1;
		break;
	}


	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
				 wm8994_mic_irq, "Mic 1 detect", wm8994);
	if (ret != 0)
+51 −32
Original line number Diff line number Diff line
@@ -62,21 +62,27 @@ static const char *speaker_mode_text[] = {
static const struct soc_enum speaker_mode =
	SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);

static void wait_for_dc_servo(struct snd_soc_codec *codec)
static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
{
	unsigned int reg;
	int count = 0;
	unsigned int val;

	val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;

	/* Trigger the command */
	snd_soc_write(codec, WM8993_DC_SERVO_0, val);

	dev_dbg(codec->dev, "Waiting for DC servo...\n");

	do {
		count++;
		msleep(1);
		reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
		reg = snd_soc_read(codec, WM8993_DC_SERVO_0);
		dev_dbg(codec->dev, "DC servo: %x\n", reg);
	} while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400);
	} while (reg & op && count < 400);

	if (reg & WM8993_DCS_DATAPATH_BUSY)
	if (reg & op)
		dev_err(codec->dev, "Timed out waiting for DC Servo\n");
}

@@ -86,51 +92,58 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
static void calibrate_dc_servo(struct snd_soc_codec *codec)
{
	struct wm_hubs_data *hubs = codec->private_data;
	u16 reg, dcs_cfg;
	u16 reg, reg_l, reg_r, dcs_cfg;

	/* Set for 32 series updates */
	snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
			    WM8993_DCS_SERIES_NO_01_MASK,
			    32 << WM8993_DCS_SERIES_NO_01_SHIFT);

	/* Enable the DC servo.  Write all bits to avoid triggering startup
	 * or write calibration.
	 */
	snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
			    0xFFFF,
			    WM8993_DCS_ENA_CHAN_0 |
			    WM8993_DCS_ENA_CHAN_1 |
			    WM8993_DCS_TRIG_SERIES_1 |
			    WM8993_DCS_TRIG_SERIES_0);

	wait_for_dc_servo(codec);
	wait_for_dc_servo(codec,
			  WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1);

	/* Apply correction to DC servo result */
	if (hubs->dcs_codes) {
		dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
			hubs->dcs_codes);

		/* Different chips in the family support different
		 * readback methods.
		 */
		switch (hubs->dcs_readback_mode) {
		case 0:
			reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1)
				& WM8993_DCS_INTEG_CHAN_0_MASK;;
			reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
				& WM8993_DCS_INTEG_CHAN_1_MASK;
			break;
		case 1:
			reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
			reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
				>> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
			reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
			break;
		default:
			WARN(1, "Unknown DCS readback method");
			break;
		}

		/* HPOUT1L */
		reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) &
			WM8993_DCS_INTEG_CHAN_0_MASK;;
		reg += hubs->dcs_codes;
		dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
		if (reg_l + hubs->dcs_codes > 0 &&
		    reg_l + hubs->dcs_codes < 0xff)
			reg_l += hubs->dcs_codes;
		dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT;

		/* HPOUT1R */
		reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) &
			WM8993_DCS_INTEG_CHAN_1_MASK;
		reg += hubs->dcs_codes;
		dcs_cfg |= reg;
		if (reg_r + hubs->dcs_codes > 0 &&
		    reg_r + hubs->dcs_codes < 0xff)
			reg_r += hubs->dcs_codes;
		dcs_cfg |= reg_r;

		/* Do it */
		snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg);
		snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
				    WM8993_DCS_TRIG_DAC_WR_0 |
				    WM8993_DCS_TRIG_DAC_WR_1,
		wait_for_dc_servo(codec,
				  WM8993_DCS_TRIG_DAC_WR_0 |
				  WM8993_DCS_TRIG_DAC_WR_1);

		wait_for_dc_servo(codec);
	}
}

@@ -141,10 +154,16 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
	struct wm_hubs_data *hubs = codec->private_data;
	int ret;

	ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);

	/* If we're applying an offset correction then updating the
	 * callibration would be likely to introduce further offsets. */
	if (hubs->dcs_codes)
		return ret;

	/* Only need to do this if the outputs are active */
	if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1)
	    & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
/* This *must* be the first element of the codec->private_data struct */
struct wm_hubs_data {
	int dcs_codes;
	int dcs_readback_mode;
	int hp_startup_mode;
};

+8 −9
Original line number Diff line number Diff line
@@ -60,12 +60,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
	struct omap_runtime_data *prtd = runtime->private_data;
	unsigned long flags;

	if ((cpu_is_omap1510()) &&
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
	if ((cpu_is_omap1510())) {
		/*
		 * OMAP1510 doesn't fully support DMA progress counter
		 * and there is no software emulation implemented yet,
		 * so have to maintain our own playback progress counter
		 * so have to maintain our own progress counters
		 * that can be used by omap_pcm_pointer() instead.
		 */
		spin_lock_irqsave(&prtd->lock, flags);
@@ -191,8 +190,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
	dma_params.frame_count	= runtime->periods;
	omap_set_dma_params(prtd->dma_ch, &dma_params);

	if ((cpu_is_omap1510()) &&
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
	if ((cpu_is_omap1510()))
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
			      OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
	else
@@ -250,14 +248,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
	dma_addr_t ptr;
	snd_pcm_uframes_t offset;

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
	if (cpu_is_omap1510()) {
		offset = prtd->period_index * runtime->period_size;
	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		ptr = omap_get_dma_dst_pos(prtd->dma_ch);
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	} else if (!(cpu_is_omap1510())) {
	} else {
		ptr = omap_get_dma_src_pos(prtd->dma_ch);
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	} else
		offset = prtd->period_index * runtime->period_size;
	}

	if (offset >= runtime->buffer_size)
		offset = 0;