Commit ec8ffe18 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: wm8996: Move register default configuration to I2C probe



This gets the registers set up as early as possible, mainly useful for the
GPIOs to ensure that they're in the correct mode.

Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent d4b3d0fb
Loading
Loading
Loading
Loading
+180 −151
Original line number Diff line number Diff line
@@ -2619,7 +2619,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
	int ret;
	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
	struct i2c_client *i2c = to_i2c_client(codec->dev);
	int i, irq_flags;
	int irq_flags;

	wm8996->codec = codec;

@@ -2634,162 +2634,12 @@ static int wm8996_probe(struct snd_soc_codec *codec)
		goto err;
	}

	/* Apply platform data settings */
	snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
			    WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
			    wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
			    wm8996->pdata.inr_mode);

	for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
		if (!wm8996->pdata.gpio_default[i])
			continue;

		snd_soc_write(codec, WM8996_GPIO_1 + i,
			      wm8996->pdata.gpio_default[i] & 0xffff);
	}

	if (wm8996->pdata.spkmute_seq)
		snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
				    WM8996_SPK_MUTE_ENDIAN |
				    WM8996_SPK_MUTE_SEQ1_MASK,
				    wm8996->pdata.spkmute_seq);

	snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2,
			    WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
			    WM8996_MICD_SRC, wm8996->pdata.micdet_def);

	/* Latch volume update bits */
	snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME,
			    WM8996_IN1_VU, WM8996_IN1_VU);
	snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME,
			    WM8996_IN1_VU, WM8996_IN1_VU);

	snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME,
			    WM8996_DAC1_VU, WM8996_DAC1_VU);
	snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME,
			    WM8996_DAC1_VU, WM8996_DAC1_VU);
	snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME,
			    WM8996_DAC2_VU, WM8996_DAC2_VU);
	snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME,
			    WM8996_DAC2_VU, WM8996_DAC2_VU);

	snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME,
			    WM8996_DAC1_VU, WM8996_DAC1_VU);
	snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME,
			    WM8996_DAC1_VU, WM8996_DAC1_VU);
	snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME,
			    WM8996_DAC2_VU, WM8996_DAC2_VU);
	snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME,
			    WM8996_DAC2_VU, WM8996_DAC2_VU);

	snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME,
			    WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
	snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME,
			    WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
	snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME,
			    WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
	snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME,
			    WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);

	snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME,
			    WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
	snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME,
			    WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
	snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME,
			    WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
	snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME,
			    WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);

	/* No support currently for the underclocked TDM modes and
	 * pick a default TDM layout with each channel pair working with
	 * slots 0 and 1. */
	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
			    WM8996_AIF1RX_CHAN0_SLOTS_MASK |
			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
			    WM8996_AIF1RX_CHAN1_SLOTS_MASK |
			    WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
			    1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
			    WM8996_AIF1RX_CHAN2_SLOTS_MASK |
			    WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
			    1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
			    WM8996_AIF1RX_CHAN3_SLOTS_MASK |
			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
			    WM8996_AIF1RX_CHAN4_SLOTS_MASK |
			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
			    WM8996_AIF1RX_CHAN5_SLOTS_MASK |
			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);

	snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
			    WM8996_AIF2RX_CHAN0_SLOTS_MASK |
			    WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
			    WM8996_AIF2RX_CHAN1_SLOTS_MASK |
			    WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
			    1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);

	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
			    WM8996_AIF1TX_CHAN0_SLOTS_MASK |
			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
			    WM8996_AIF1TX_CHAN1_SLOTS_MASK |
			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
			    WM8996_AIF1TX_CHAN2_SLOTS_MASK |
			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
			    WM8996_AIF1TX_CHAN3_SLOTS_MASK |
			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
			    WM8996_AIF1TX_CHAN4_SLOTS_MASK |
			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
			    WM8996_AIF1TX_CHAN5_SLOTS_MASK |
			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);

	snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
			    WM8996_AIF2TX_CHAN0_SLOTS_MASK |
			    WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
			    1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
			    WM8996_AIF2TX_CHAN1_SLOTS_MASK |
			    WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
			    1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);

	if (wm8996->pdata.num_retune_mobile_cfgs)
		wm8996_retune_mobile_pdata(codec);
	else
		snd_soc_add_codec_controls(codec, wm8996_eq_controls,
				     ARRAY_SIZE(wm8996_eq_controls));

	/* If the TX LRCLK pins are not in LRCLK mode configure the
	 * AIFs to source their clocks from the RX LRCLKs.
	 */
	if ((snd_soc_read(codec, WM8996_GPIO_1)))
		snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2,
				    WM8996_AIF1TX_LRCLK_MODE,
				    WM8996_AIF1TX_LRCLK_MODE);

	if ((snd_soc_read(codec, WM8996_GPIO_2)))
		snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2,
				    WM8996_AIF2TX_LRCLK_MODE,
				    WM8996_AIF2TX_LRCLK_MODE);

	if (i2c->irq) {
		if (wm8996->pdata.irq_flags)
			irq_flags = wm8996->pdata.irq_flags;
@@ -3023,6 +2873,185 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,

	regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);

	/* Apply platform data settings */
	regmap_update_bits(wm8996->regmap, WM8996_LINE_INPUT_CONTROL,
			   WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
			   wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
			   wm8996->pdata.inr_mode);

	for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
		if (!wm8996->pdata.gpio_default[i])
			continue;

		regmap_write(wm8996->regmap, WM8996_GPIO_1 + i,
			     wm8996->pdata.gpio_default[i] & 0xffff);
	}

	if (wm8996->pdata.spkmute_seq)
		regmap_update_bits(wm8996->regmap,
				   WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
				   WM8996_SPK_MUTE_ENDIAN |
				   WM8996_SPK_MUTE_SEQ1_MASK,
				   wm8996->pdata.spkmute_seq);

	regmap_update_bits(wm8996->regmap, WM8996_ACCESSORY_DETECT_MODE_2,
			   WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
			   WM8996_MICD_SRC, wm8996->pdata.micdet_def);

	/* Latch volume update bits */
	regmap_update_bits(wm8996->regmap, WM8996_LEFT_LINE_INPUT_VOLUME,
			   WM8996_IN1_VU, WM8996_IN1_VU);
	regmap_update_bits(wm8996->regmap, WM8996_RIGHT_LINE_INPUT_VOLUME,
			   WM8996_IN1_VU, WM8996_IN1_VU);

	regmap_update_bits(wm8996->regmap, WM8996_DAC1_LEFT_VOLUME,
			   WM8996_DAC1_VU, WM8996_DAC1_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DAC1_RIGHT_VOLUME,
			   WM8996_DAC1_VU, WM8996_DAC1_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DAC2_LEFT_VOLUME,
			   WM8996_DAC2_VU, WM8996_DAC2_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DAC2_RIGHT_VOLUME,
			   WM8996_DAC2_VU, WM8996_DAC2_VU);

	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_LEFT_VOLUME,
			   WM8996_DAC1_VU, WM8996_DAC1_VU);
	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_RIGHT_VOLUME,
			   WM8996_DAC1_VU, WM8996_DAC1_VU);
	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_LEFT_VOLUME,
			   WM8996_DAC2_VU, WM8996_DAC2_VU);
	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_RIGHT_VOLUME,
			   WM8996_DAC2_VU, WM8996_DAC2_VU);

	regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_LEFT_VOLUME,
			   WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_RIGHT_VOLUME,
			   WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_LEFT_VOLUME,
			   WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_RIGHT_VOLUME,
			   WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);

	regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_LEFT_VOLUME,
			   WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_RIGHT_VOLUME,
			   WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_LEFT_VOLUME,
			   WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
	regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_RIGHT_VOLUME,
			   WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);

	/* No support currently for the underclocked TDM modes and
	 * pick a default TDM layout with each channel pair working with
	 * slots 0 and 1. */
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
			   WM8996_AIF1RX_CHAN0_SLOTS_MASK |
			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
			   WM8996_AIF1RX_CHAN1_SLOTS_MASK |
			   WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
			   1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
			   WM8996_AIF1RX_CHAN2_SLOTS_MASK |
			   WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
			   1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
			   WM8996_AIF1RX_CHAN3_SLOTS_MASK |
			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
			   WM8996_AIF1RX_CHAN4_SLOTS_MASK |
			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
			   WM8996_AIF1RX_CHAN5_SLOTS_MASK |
			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);

	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
			   WM8996_AIF2RX_CHAN0_SLOTS_MASK |
			   WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
			   WM8996_AIF2RX_CHAN1_SLOTS_MASK |
			   WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
			   1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);

	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
			   WM8996_AIF1TX_CHAN0_SLOTS_MASK |
			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
			   WM8996_AIF1TX_CHAN1_SLOTS_MASK |
			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
			   WM8996_AIF1TX_CHAN2_SLOTS_MASK |
			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
			   WM8996_AIF1TX_CHAN3_SLOTS_MASK |
			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
			   WM8996_AIF1TX_CHAN4_SLOTS_MASK |
			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
			   WM8996_AIF1TX_CHAN5_SLOTS_MASK |
			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);

	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
			   WM8996_AIF2TX_CHAN0_SLOTS_MASK |
			   WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
			   1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
	regmap_update_bits(wm8996->regmap,
			   WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
			   WM8996_AIF2TX_CHAN1_SLOTS_MASK |
			   WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
			   1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);

	/* If the TX LRCLK pins are not in LRCLK mode configure the
	 * AIFs to source their clocks from the RX LRCLKs.
	 */
	ret = regmap_read(wm8996->regmap, WM8996_GPIO_1, &reg);
	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to read GPIO1: %d\n", ret);
		goto err_regmap;
	}

	if (reg & WM8996_GP1_FN_MASK)
		regmap_update_bits(wm8996->regmap, WM8996_AIF1_TX_LRCLK_2,
				   WM8996_AIF1TX_LRCLK_MODE,
				   WM8996_AIF1TX_LRCLK_MODE);

	ret = regmap_read(wm8996->regmap, WM8996_GPIO_2, &reg);
	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to read GPIO2: %d\n", ret);
		goto err_regmap;
	}

	if (reg & WM8996_GP2_FN_MASK)
		regmap_update_bits(wm8996->regmap, WM8996_AIF2_TX_LRCLK_2,
				   WM8996_AIF2TX_LRCLK_MODE,
				   WM8996_AIF2TX_LRCLK_MODE);

	wm8996_init_gpio(wm8996);

	ret = snd_soc_register_codec(&i2c->dev,