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

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

Merge remote-tracking branch 'asoc/topic/core' into asoc-next

parents 89a88dd3 a5053a8e
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -586,8 +586,6 @@ struct snd_soc_dapm_update {
/* DAPM context */
struct snd_soc_dapm_context {
	enum snd_soc_bias_level bias_level;
	enum snd_soc_bias_level suspend_bias_level;
	struct delayed_work delayed_work;
	unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
	/* Go to BIAS_OFF in suspend if the DAPM context is idle */
	unsigned int suspend_bias_off:1;
+1 −1
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,

/* internal use only */
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
int soc_dpcm_runtime_update(struct snd_soc_card *);

int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
+11 −14
Original line number Diff line number Diff line
@@ -69,14 +69,14 @@ struct wm8350_data {
	struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
	int fll_freq_out;
	int fll_freq_in;
	struct delayed_work pga_work;
};

/*
 * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown.
 */
static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec)
static inline int wm8350_out1_ramp_step(struct wm8350_data *wm8350_data)
{
	struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
	struct wm8350_output *out1 = &wm8350_data->out1;
	struct wm8350 *wm8350 = wm8350_data->wm8350;
	int left_complete = 0, right_complete = 0;
@@ -140,9 +140,8 @@ static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec)
/*
 * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown.
 */
static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
static inline int wm8350_out2_ramp_step(struct wm8350_data *wm8350_data)
{
	struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
	struct wm8350_output *out2 = &wm8350_data->out2;
	struct wm8350 *wm8350 = wm8350_data->wm8350;
	int left_complete = 0, right_complete = 0;
@@ -210,10 +209,8 @@ static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
 */
static void wm8350_pga_work(struct work_struct *work)
{
	struct snd_soc_dapm_context *dapm =
	    container_of(work, struct snd_soc_dapm_context, delayed_work.work);
	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
	struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
	struct wm8350_data *wm8350_data =
		container_of(work, struct wm8350_data, pga_work.work);
	struct wm8350_output *out1 = &wm8350_data->out1,
	    *out2 = &wm8350_data->out2;
	int i, out1_complete, out2_complete;
@@ -226,9 +223,9 @@ static void wm8350_pga_work(struct work_struct *work)
	for (i = 0; i <= 63; i++) {
		out1_complete = 1, out2_complete = 1;
		if (out1->ramp != WM8350_RAMP_NONE)
			out1_complete = wm8350_out1_ramp_step(codec);
			out1_complete = wm8350_out1_ramp_step(wm8350_data);
		if (out2->ramp != WM8350_RAMP_NONE)
			out2_complete = wm8350_out2_ramp_step(codec);
			out2_complete = wm8350_out2_ramp_step(wm8350_data);

		/* ramp finished ? */
		if (out1_complete && out2_complete)
@@ -283,7 +280,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
		out->ramp = WM8350_RAMP_UP;
		out->active = 1;

		schedule_delayed_work(&codec->dapm.delayed_work,
		schedule_delayed_work(&wm8350_data->pga_work,
				      msecs_to_jiffies(1));
		break;

@@ -291,7 +288,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
		out->ramp = WM8350_RAMP_DOWN;
		out->active = 0;

		schedule_delayed_work(&codec->dapm.delayed_work,
		schedule_delayed_work(&wm8350_data->pga_work,
				      msecs_to_jiffies(1));
		break;
	}
@@ -1492,7 +1489,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
	/* Put the codec into reset if it wasn't already */
	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);

	INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work);
	INIT_DELAYED_WORK(&priv->pga_work, wm8350_pga_work);
	INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work);
	INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work);

@@ -1578,7 +1575,7 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec)

	/* if there was any work waiting then we run it now and
	 * wait for its completion */
	flush_delayed_work(&codec->dapm.delayed_work);
	flush_delayed_work(&priv->pga_work);

	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);

+25 −48
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ struct wm8753_priv {
	unsigned int hifi_fmt;

	int dai_func;
	struct delayed_work charge_work;
};

#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
@@ -1326,9 +1327,19 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
	return 0;
}

static void wm8753_charge_work(struct work_struct *work)
{
	struct wm8753_priv *wm8753 =
		container_of(work, struct wm8753_priv, charge_work.work);

	/* Set to 500k */
	regmap_update_bits(wm8753->regmap, WM8753_PWR1, 0x0180, 0x0100);
}

static int wm8753_set_bias_level(struct snd_soc_codec *codec,
				 enum snd_soc_bias_level level)
{
	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
	u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;

	switch (level) {
@@ -1337,14 +1348,22 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
		break;
	case SND_SOC_BIAS_PREPARE:
		/* set vmid to 5k for quick power up */
		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
		/* Wait until fully charged */
		flush_delayed_work(&wm8753->charge_work);
		break;
	case SND_SOC_BIAS_STANDBY:
		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
			/* set vmid to 5k for quick power up */
			snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
			schedule_delayed_work(&wm8753->charge_work,
				msecs_to_jiffies(caps_charge));
		} else {
			/* mute dac and set vmid to 500k, enable VREF */
			snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
		}
		break;
	case SND_SOC_BIAS_OFF:
		cancel_delayed_work_sync(&wm8753->charge_work);
		snd_soc_write(codec, WM8753_PWR1, 0x0001);
		break;
	}
@@ -1428,38 +1447,12 @@ static struct snd_soc_dai_driver wm8753_dai[] = {
},
};

static void wm8753_work(struct work_struct *work)
{
	struct snd_soc_dapm_context *dapm =
		container_of(work, struct snd_soc_dapm_context,
			     delayed_work.work);
	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
	wm8753_set_bias_level(codec, dapm->bias_level);
}

static int wm8753_suspend(struct snd_soc_codec *codec)
{
	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
	return 0;
}

static int wm8753_resume(struct snd_soc_codec *codec)
{
	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);

	regcache_sync(wm8753->regmap);

	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	/* charge wm8753 caps */
	if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
		wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
		codec->dapm.bias_level = SND_SOC_BIAS_ON;
		queue_delayed_work(system_power_efficient_wq,
				   &codec->dapm.delayed_work,
				   msecs_to_jiffies(caps_charge));
	}

	return 0;
}

@@ -1468,7 +1461,7 @@ static int wm8753_probe(struct snd_soc_codec *codec)
	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
	int ret;

	INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
	INIT_DELAYED_WORK(&wm8753->charge_work, wm8753_charge_work);

	ret = wm8753_reset(codec);
	if (ret < 0) {
@@ -1476,14 +1469,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
		return ret;
	}

	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	wm8753->dai_func = 0;

	/* charge output caps */
	wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
	schedule_delayed_work(&codec->dapm.delayed_work,
			      msecs_to_jiffies(caps_charge));

	/* set the update bits */
	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
@@ -1499,21 +1486,11 @@ static int wm8753_probe(struct snd_soc_codec *codec)
	return 0;
}

/* power down chip */
static int wm8753_remove(struct snd_soc_codec *codec)
{
	flush_delayed_work(&codec->dapm.delayed_work);
	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);

	return 0;
}

static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
	.probe =	wm8753_probe,
	.remove =	wm8753_remove,
	.suspend =	wm8753_suspend,
	.resume =	wm8753_resume,
	.set_bias_level = wm8753_set_bias_level,
	.suspend_bias_off = true,

	.controls = wm8753_snd_controls,
	.num_controls = ARRAY_SIZE(wm8753_snd_controls),
+30 −69
Original line number Diff line number Diff line
@@ -31,11 +31,11 @@

#define	WM8971_REG_COUNT		43

static struct workqueue_struct *wm8971_workq = NULL;

/* codec private data */
struct wm8971_priv {
	unsigned int sysclk;
	struct delayed_work charge_work;
	struct regmap *regmap;
};

/*
@@ -552,9 +552,19 @@ static int wm8971_mute(struct snd_soc_dai *dai, int mute)
	return 0;
}

static void wm8971_charge_work(struct work_struct *work)
{
	struct wm8971_priv *wm8971 =
		container_of(work, struct wm8971_priv, charge_work.work);

	/* Set to 500k */
	regmap_update_bits(wm8971->regmap, WM8971_PWR1, 0x0180, 0x0100);
}

static int wm8971_set_bias_level(struct snd_soc_codec *codec,
	enum snd_soc_bias_level level)
{
	struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
	u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;

	switch (level) {
@@ -563,15 +573,24 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
		snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
		break;
	case SND_SOC_BIAS_PREPARE:
		/* Wait until fully charged */
		flush_delayed_work(&wm8971->charge_work);
		break;
	case SND_SOC_BIAS_STANDBY:
		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
			snd_soc_cache_sync(codec);

			/* charge output caps - set vmid to 5k for quick power up */
			snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x01c0);
			queue_delayed_work(system_power_efficient_wq,
				&wm8971->charge_work, msecs_to_jiffies(1000));
		} else {
			/* mute dac and set vmid to 500k, enable VREF */
			snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
		}

		break;
	case SND_SOC_BIAS_OFF:
		cancel_delayed_work_sync(&wm8971->charge_work);
		snd_soc_write(codec, WM8971_PWR1, 0x0001);
		break;
	}
@@ -610,58 +629,14 @@ static struct snd_soc_dai_driver wm8971_dai = {
	.ops = &wm8971_dai_ops,
};

static void wm8971_work(struct work_struct *work)
{
	struct snd_soc_dapm_context *dapm =
		container_of(work, struct snd_soc_dapm_context,
			     delayed_work.work);
	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
	wm8971_set_bias_level(codec, codec->dapm.bias_level);
}

static int wm8971_suspend(struct snd_soc_codec *codec)
{
	wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
	return 0;
}

static int wm8971_resume(struct snd_soc_codec *codec)
{
	u16 reg;

	wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	/* charge wm8971 caps */
	if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
		reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
		snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
		codec->dapm.bias_level = SND_SOC_BIAS_ON;
		queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work,
			msecs_to_jiffies(1000));
	}

	return 0;
}

static int wm8971_probe(struct snd_soc_codec *codec)
{
	int ret = 0;
	u16 reg;
	struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);

	INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work);
	wm8971_workq = create_workqueue("wm8971");
	if (wm8971_workq == NULL)
		return -ENOMEM;
	INIT_DELAYED_WORK(&wm8971->charge_work, wm8971_charge_work);

	wm8971_reset(codec);

	/* charge output caps - set vmid to 5k for quick power up */
	reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
	snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
	codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
	queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work,
		msecs_to_jiffies(1000));

	/* set the update bits */
	snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100);
	snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100);
@@ -672,26 +647,13 @@ static int wm8971_probe(struct snd_soc_codec *codec)
	snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
	snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);

	return ret;
}


/* power down chip */
static int wm8971_remove(struct snd_soc_codec *codec)
{
	wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);

	if (wm8971_workq)
		destroy_workqueue(wm8971_workq);
	return 0;
}

static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
	.probe =	wm8971_probe,
	.remove =	wm8971_remove,
	.suspend =	wm8971_suspend,
	.resume =	wm8971_resume,
	.set_bias_level = wm8971_set_bias_level,
	.suspend_bias_off = true,

	.controls = wm8971_snd_controls,
	.num_controls = ARRAY_SIZE(wm8971_snd_controls),
@@ -715,7 +677,6 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct wm8971_priv *wm8971;
	struct regmap *regmap;
	int ret;

	wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
@@ -723,9 +684,9 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
	if (wm8971 == NULL)
		return -ENOMEM;

	regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
	if (IS_ERR(regmap))
		return PTR_ERR(regmap);
	wm8971->regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
	if (IS_ERR(wm8971->regmap))
		return PTR_ERR(wm8971->regmap);

	i2c_set_clientdata(i2c, wm8971);

Loading