Commit 480d060b authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/da7218', 'asoc/topic/da7219' and...

Merge remote-tracking branches 'asoc/topic/da7218', 'asoc/topic/da7219' and 'asoc/topic/dpcm' into asoc-next
...@@ -34,6 +34,8 @@ enum da7219_mic_amp_in_sel { ...@@ -34,6 +34,8 @@ enum da7219_mic_amp_in_sel {
struct da7219_aad_pdata; struct da7219_aad_pdata;
struct da7219_pdata { struct da7219_pdata {
bool wakeup_source;
/* Mic */ /* Mic */
enum da7219_micbias_voltage micbias_lvl; enum da7219_micbias_voltage micbias_lvl;
enum da7219_mic_amp_in_sel mic_amp_in_sel; enum da7219_mic_amp_in_sel mic_amp_in_sel;
......
...@@ -1819,7 +1819,7 @@ static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -1819,7 +1819,7 @@ static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai,
if (da7218->mclk_rate == freq) if (da7218->mclk_rate == freq)
return 0; return 0;
if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) { if ((freq < 2000000) || (freq > 54000000)) {
dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
freq); freq);
return -EINVAL; return -EINVAL;
...@@ -1866,11 +1866,8 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, ...@@ -1866,11 +1866,8 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
u32 freq_ref; u32 freq_ref;
u64 frac_div; u64 frac_div;
/* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ /* Verify 2MHz - 54MHz MCLK provided, and set input divider */
if (da7218->mclk_rate == 32768) { if (da7218->mclk_rate < 2000000) {
indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ;
indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL;
} else if (da7218->mclk_rate < 2000000) {
dev_err(codec->dev, "PLL input clock %d below valid range\n", dev_err(codec->dev, "PLL input clock %d below valid range\n",
da7218->mclk_rate); da7218->mclk_rate);
return -EINVAL; return -EINVAL;
...@@ -1911,9 +1908,6 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, ...@@ -1911,9 +1908,6 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
case DA7218_SYSCLK_PLL_SRM: case DA7218_SYSCLK_PLL_SRM:
pll_ctrl |= DA7218_PLL_MODE_SRM; pll_ctrl |= DA7218_PLL_MODE_SRM;
break; break;
case DA7218_SYSCLK_PLL_32KHZ:
pll_ctrl |= DA7218_PLL_MODE_32KHZ;
break;
default: default:
dev_err(codec->dev, "Invalid PLL config\n"); dev_err(codec->dev, "Invalid PLL config\n");
return -EINVAL; return -EINVAL;
...@@ -2589,20 +2583,22 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, ...@@ -2589,20 +2583,22 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec,
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_PREPARE:
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Enable MCLK for transition to ON state */
/* MCLK */ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
if (da7218->mclk) { if (da7218->mclk) {
ret = clk_prepare_enable(da7218->mclk); ret = clk_prepare_enable(da7218->mclk);
if (ret) { if (ret) {
dev_err(codec->dev, dev_err(codec->dev, "Failed to enable mclk\n");
"Failed to enable mclk\n");
return ret; return ret;
} }
} }
}
break;
case SND_SOC_BIAS_STANDBY:
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
/* Master bias */ /* Master bias */
snd_soc_update_bits(codec, DA7218_REFERENCES, snd_soc_update_bits(codec, DA7218_REFERENCES,
DA7218_BIAS_EN_MASK, DA7218_BIAS_EN_MASK,
...@@ -2612,6 +2608,10 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, ...@@ -2612,6 +2608,10 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, DA7218_LDO_CTRL, snd_soc_update_bits(codec, DA7218_LDO_CTRL,
DA7218_LDO_EN_MASK, DA7218_LDO_EN_MASK,
DA7218_LDO_EN_MASK); DA7218_LDO_EN_MASK);
} else {
/* Remove MCLK */
if (da7218->mclk)
clk_disable_unprepare(da7218->mclk);
} }
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
...@@ -2625,10 +2625,6 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, ...@@ -2625,10 +2625,6 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, DA7218_REFERENCES, snd_soc_update_bits(codec, DA7218_REFERENCES,
DA7218_BIAS_EN_MASK, 0); DA7218_BIAS_EN_MASK, 0);
} }
/* MCLK */
if (da7218->mclk)
clk_disable_unprepare(da7218->mclk);
break; break;
} }
......
...@@ -888,7 +888,6 @@ ...@@ -888,7 +888,6 @@
#define DA7218_PLL_MODE_BYPASS (0x0 << 6) #define DA7218_PLL_MODE_BYPASS (0x0 << 6)
#define DA7218_PLL_MODE_NORMAL (0x1 << 6) #define DA7218_PLL_MODE_NORMAL (0x1 << 6)
#define DA7218_PLL_MODE_SRM (0x2 << 6) #define DA7218_PLL_MODE_SRM (0x2 << 6)
#define DA7218_PLL_MODE_32KHZ (0x3 << 6)
/* DA7218_PLL_FRAC_TOP = 0x92 */ /* DA7218_PLL_FRAC_TOP = 0x92 */
#define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT 0 #define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT 0
...@@ -1371,7 +1370,6 @@ enum da7218_sys_clk { ...@@ -1371,7 +1370,6 @@ enum da7218_sys_clk {
DA7218_SYSCLK_MCLK = 0, DA7218_SYSCLK_MCLK = 0,
DA7218_SYSCLK_PLL, DA7218_SYSCLK_PLL,
DA7218_SYSCLK_PLL_SRM, DA7218_SYSCLK_PLL_SRM,
DA7218_SYSCLK_PLL_32KHZ
}; };
enum da7218_dev_id { enum da7218_dev_id {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/pm_wakeirq.h> #include <linux/pm_wakeirq.h>
...@@ -114,13 +115,38 @@ static void da7219_aad_hptest_work(struct work_struct *work) ...@@ -114,13 +115,38 @@ static void da7219_aad_hptest_work(struct work_struct *work)
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
u16 tonegen_freq_hptest; u16 tonegen_freq_hptest;
u8 accdet_cfg8; u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8;
int report = 0; int report = 0, ret = 0;
/* Lock DAPM and any Kcontrols that are affected by this test */ /* Lock DAPM and any Kcontrols that are affected by this test */
snd_soc_dapm_mutex_lock(dapm); snd_soc_dapm_mutex_lock(dapm);
mutex_lock(&da7219->lock); mutex_lock(&da7219->lock);
/* Ensure MCLK is available for HP test procedure */
if (da7219->mclk) {
ret = clk_prepare_enable(da7219->mclk);
if (ret) {
dev_err(codec->dev, "Failed to enable mclk - %d\n", ret);
mutex_unlock(&da7219->lock);
snd_soc_dapm_mutex_unlock(dapm);
return;
}
}
/*
* If MCLK not present, then we're using the internal oscillator and
* require different frequency settings to achieve the same result.
*/
pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS);
if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)
tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
else
tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC);
/* Ensure gain ramping at fastest rate */
gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL);
snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8);
/* Bypass cache so it saves current settings */ /* Bypass cache so it saves current settings */
regcache_cache_bypass(da7219->regmap, true); regcache_cache_bypass(da7219->regmap, true);
...@@ -183,9 +209,15 @@ static void da7219_aad_hptest_work(struct work_struct *work) ...@@ -183,9 +209,15 @@ static void da7219_aad_hptest_work(struct work_struct *work)
snd_soc_write(codec, DA7219_HP_R_CTRL, snd_soc_write(codec, DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);
/*
* If we're running from the internal oscillator then give audio paths
* time to settle before running test.
*/
if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
/* Configure & start Tone Generator */ /* Configure & start Tone Generator */
snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK); snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK);
tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
&tonegen_freq_hptest, sizeof(tonegen_freq_hptest)); &tonegen_freq_hptest, sizeof(tonegen_freq_hptest));
snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2, snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2,
...@@ -244,12 +276,26 @@ static void da7219_aad_hptest_work(struct work_struct *work) ...@@ -244,12 +276,26 @@ static void da7219_aad_hptest_work(struct work_struct *work)
snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8,
DA7219_HPTEST_EN_MASK, 0); DA7219_HPTEST_EN_MASK, 0);
/*
* If we're running from the internal oscillator then give audio paths
* time to settle before allowing headphones to be driven as required.
*/
if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
/* Restore gain ramping rate */
snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl);
/* Drive Headphones/lineout */ /* Drive Headphones/lineout */
snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK,
DA7219_HP_L_AMP_OE_MASK); DA7219_HP_L_AMP_OE_MASK);
snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK,
DA7219_HP_R_AMP_OE_MASK); DA7219_HP_R_AMP_OE_MASK);
/* Remove MCLK, if previously enabled */
if (da7219->mclk)
clk_disable_unprepare(da7219->mclk);
mutex_unlock(&da7219->lock); mutex_unlock(&da7219->lock);
snd_soc_dapm_mutex_unlock(dapm); snd_soc_dapm_mutex_unlock(dapm);
...@@ -750,6 +796,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) ...@@ -750,6 +796,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec)
} }
/*
* Suspend/Resume
*/
void da7219_aad_suspend(struct snd_soc_codec *codec)
{
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
struct da7219_aad_priv *da7219_aad = da7219->aad;
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
u8 micbias_ctrl;
if (da7219_aad->jack) {
/* Disable jack detection during suspend */
snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
DA7219_ACCDET_EN_MASK, 0);
/*
* If we have a 4-pole jack inserted, then micbias will be
* enabled. We can disable micbias here, and keep a note to
* re-enable it on resume. If jack removal occurred during
* suspend then this will be dealt with through the IRQ handler.
*/
if (da7219_aad->jack_inserted) {
micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL);
if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) {
snd_soc_dapm_disable_pin(dapm, "Mic Bias");
snd_soc_dapm_sync(dapm);
da7219_aad->micbias_resume_enable = true;
}
}
}
}
void da7219_aad_resume(struct snd_soc_codec *codec)
{
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
struct da7219_aad_priv *da7219_aad = da7219->aad;
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
if (da7219_aad->jack) {
/* Re-enable micbias if previously enabled for 4-pole jack */
if (da7219_aad->jack_inserted &&
da7219_aad->micbias_resume_enable) {
snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
snd_soc_dapm_sync(dapm);
da7219_aad->micbias_resume_enable = false;
}
/* Re-enable jack detection */
snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
DA7219_ACCDET_EN_MASK,
DA7219_ACCDET_EN_MASK);
}
}
/* /*
* Init/Exit * Init/Exit
*/ */
......
...@@ -177,7 +177,9 @@ ...@@ -177,7 +177,9 @@
#define DA7219_AAD_MICBIAS_CHK_RETRIES 5 #define DA7219_AAD_MICBIAS_CHK_RETRIES 5
#define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 #define DA7219_AAD_HPTEST_RAMP_FREQ 0x28
#define DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC 0x4D
#define DA7219_AAD_HPTEST_PERIOD 65 #define DA7219_AAD_HPTEST_PERIOD 65
#define DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY 20
enum da7219_aad_event_regs { enum da7219_aad_event_regs {
DA7219_AAD_IRQ_REG_A = 0, DA7219_AAD_IRQ_REG_A = 0,
...@@ -199,12 +201,17 @@ struct da7219_aad_priv { ...@@ -199,12 +201,17 @@ struct da7219_aad_priv {
struct work_struct hptest_work; struct work_struct hptest_work;
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
bool micbias_resume_enable;
bool jack_inserted; bool jack_inserted;
}; };
/* AAD control */ /* AAD control */
void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
/* Suspend/Resume */
void da7219_aad_suspend(struct snd_soc_codec *codec);
void da7219_aad_resume(struct snd_soc_codec *codec);
/* Init/Exit */ /* Init/Exit */
int da7219_aad_init(struct snd_soc_codec *codec); int da7219_aad_init(struct snd_soc_codec *codec);
void da7219_aad_exit(struct snd_soc_codec *codec); void da7219_aad_exit(struct snd_soc_codec *codec);
......
...@@ -801,7 +801,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, ...@@ -801,7 +801,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w,
++i; ++i;
msleep(50); msleep(50);
} }
} while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); } while ((i < DA7219_SRM_CHECK_RETRIES) && (!srm_lock));
if (!srm_lock) if (!srm_lock)
dev_warn(codec->dev, "SRM failed to lock\n"); dev_warn(codec->dev, "SRM failed to lock\n");
...@@ -1482,6 +1482,8 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_codec *codec) ...@@ -1482,6 +1482,8 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_codec *codec)
if (!pdata) if (!pdata)
return NULL; return NULL;
pdata->wakeup_source = device_property_read_bool(dev, "wakeup-source");
if (device_property_read_u32(dev, "dlg,micbias-lvl", &of_val32) >= 0) if (device_property_read_u32(dev, "dlg,micbias-lvl", &of_val32) >= 0)
pdata->micbias_lvl = da7219_fw_micbias_lvl(dev, of_val32); pdata->micbias_lvl = da7219_fw_micbias_lvl(dev, of_val32);
else else
...@@ -1508,11 +1510,10 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, ...@@ -1508,11 +1510,10 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec,
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_PREPARE:
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Enable MCLK for transition to ON state */
/* MCLK */ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
if (da7219->mclk) { if (da7219->mclk) {
ret = clk_prepare_enable(da7219->mclk); ret = clk_prepare_enable(da7219->mclk);
if (ret) { if (ret) {
...@@ -1521,22 +1522,28 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, ...@@ -1521,22 +1522,28 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec,
return ret; return ret;
} }
} }
}
break;
case SND_SOC_BIAS_STANDBY:
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
/* Master bias */ /* Master bias */
snd_soc_update_bits(codec, DA7219_REFERENCES, snd_soc_update_bits(codec, DA7219_REFERENCES,
DA7219_BIAS_EN_MASK, DA7219_BIAS_EN_MASK,
DA7219_BIAS_EN_MASK); DA7219_BIAS_EN_MASK);
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) {
/* Remove MCLK */
if (da7219->mclk)
clk_disable_unprepare(da7219->mclk);
} }
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
/* Only disable master bias if jack detection not active */ /* Only disable master bias if we're not a wake-up source */
if (!da7219->aad->jack) if (!da7219->wakeup_source)
snd_soc_update_bits(codec, DA7219_REFERENCES, snd_soc_update_bits(codec, DA7219_REFERENCES,
DA7219_BIAS_EN_MASK, 0); DA7219_BIAS_EN_MASK, 0);
/* MCLK */
if (da7219->mclk)
clk_disable_unprepare(da7219->mclk);
break; break;
} }
...@@ -1599,6 +1606,8 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec) ...@@ -1599,6 +1606,8 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec)
if (pdata) { if (pdata) {
u8 micbias_lvl = 0; u8 micbias_lvl = 0;
da7219->wakeup_source = pdata->wakeup_source;
/* Mic Bias voltages */ /* Mic Bias voltages */
switch (pdata->micbias_lvl) { switch (pdata->micbias_lvl) {
case DA7219_MICBIAS_1_6V: case DA7219_MICBIAS_1_6V:
...@@ -1733,11 +1742,11 @@ static int da7219_suspend(struct snd_soc_codec *codec) ...@@ -1733,11 +1742,11 @@ static int da7219_suspend(struct snd_soc_codec *codec)
{ {
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); /* Suspend AAD if we're not a wake-up source */
if (!da7219->wakeup_source)
da7219_aad_suspend(codec);
/* Put device into standby mode if jack detection disabled */ snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
if (!da7219->aad->jack)
snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 0);
return 0; return 0;
} }
...@@ -1746,13 +1755,12 @@ static int da7219_resume(struct snd_soc_codec *codec) ...@@ -1746,13 +1755,12 @@ static int da7219_resume(struct snd_soc_codec *codec)
{ {
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
/* Put device into active mode if previously pushed to standby */
if (!da7219->aad->jack)
snd_soc_write(codec, DA7219_SYSTEM_ACTIVE,
DA7219_SYSTEM_ACTIVE_MASK);
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Resume AAD if previously suspended */
if (!da7219->wakeup_source)
da7219_aad_resume(codec);
return 0; return 0;
} }
#else #else
...@@ -1922,7 +1930,8 @@ static int da7219_i2c_probe(struct i2c_client *i2c, ...@@ -1922,7 +1930,8 @@ static int da7219_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct da7219_priv *da7219; struct da7219_priv *da7219;
int ret; unsigned int system_active, system_status;
int i, ret;
da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv),
GFP_KERNEL); GFP_KERNEL);
...@@ -1938,14 +1947,37 @@ static int da7219_i2c_probe(struct i2c_client *i2c, ...@@ -1938,14 +1947,37 @@ static int da7219_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
/* Software reset codec. */ regcache_cache_bypass(da7219->regmap, true);
/* Disable audio paths if still active from previous start */
regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active);
if (system_active) {
regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL,
DA7219_GAIN_RAMP_RATE_NOMINAL);
regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00);
regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01);
for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) {
regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS,
&system_status);
if (!system_status)
break;
msleep(DA7219_SYS_STAT_CHECK_DELAY);
}
}
/* Soft reset codec */
regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1,
DA7219_ACCDET_EN_MASK, 0); DA7219_ACCDET_EN_MASK, 0);
regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL,
DA7219_CIF_REG_SOFT_RESET_MASK, 0); DA7219_CIF_REG_SOFT_RESET_MASK,
DA7219_CIF_REG_SOFT_RESET_MASK);
regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE,
DA7219_SYSTEM_ACTIVE_MASK, 0); DA7219_SYSTEM_ACTIVE_MASK, 0);
regcache_cache_bypass(da7219->regmap, false);
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219,
&da7219_dai, 1); &da7219_dai, 1);
if (ret < 0) { if (ret < 0) {
......
...@@ -224,6 +224,7 @@ ...@@ -224,6 +224,7 @@
#define DA7219_PLL_SRM_STATE_MASK (0xF << 0) #define DA7219_PLL_SRM_STATE_MASK (0xF << 0)
#define DA7219_PLL_SRM_STATUS_SHIFT 4 #define DA7219_PLL_SRM_STATUS_SHIFT 4
#define DA7219_PLL_SRM_STATUS_MASK (0xF << 4) #define DA7219_PLL_SRM_STATUS_MASK (0xF << 4)
#define DA7219_PLL_SRM_STS_MCLK (0x1 << 4)
#define DA7219_PLL_SRM_STS_SRM_LOCK (0x1 << 7) #define DA7219_PLL_SRM_STS_SRM_LOCK (0x1 << 7)
/* DA7219_DIG_ROUTING_DAI = 0x2A */ /* DA7219_DIG_ROUTING_DAI = 0x2A */
...@@ -576,6 +577,8 @@ ...@@ -576,6 +577,8 @@
/* DA7219_GAIN_RAMP_CTRL = 0x92 */ /* DA7219_GAIN_RAMP_CTRL = 0x92 */
#define DA7219_GAIN_RAMP_RATE_SHIFT 0 #define DA7219_GAIN_RAMP_RATE_SHIFT 0
#define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0)
#define DA7219_GAIN_RAMP_RATE_X8 (0x0 << 0)
#define DA7219_GAIN_RAMP_RATE_NOMINAL (0x1 << 0)
#define DA7219_GAIN_RAMP_RATE_MAX 4 #define DA7219_GAIN_RAMP_RATE_MAX 4
/* DA7219_PC_COUNT = 0x94 */ /* DA7219_PC_COUNT = 0x94 */
...@@ -770,6 +773,10 @@ ...@@ -770,6 +773,10 @@
/* SRM */ /* SRM */
#define DA7219_SRM_CHECK_RETRIES 8 #define DA7219_SRM_CHECK_RETRIES 8
/* System Controller */
#define DA7219_SYS_STAT_CHECK_RETRIES 6
#define DA7219_SYS_STAT_CHECK_DELAY 50
enum da7219_clk_src { enum da7219_clk_src {
DA7219_CLKSRC_MCLK = 0, DA7219_CLKSRC_MCLK = 0,
DA7219_CLKSRC_MCLK_SQR, DA7219_CLKSRC_MCLK_SQR,
...@@ -796,6 +803,7 @@ struct da7219_priv { ...@@ -796,6 +803,7 @@ struct da7219_priv {
struct da7219_aad_priv *aad; struct da7219_aad_priv *aad;
struct da7219_pdata *pdata; struct da7219_pdata *pdata;
bool wakeup_source;
struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES];
struct regmap *regmap; struct regmap *regmap;
struct mutex lock; struct mutex lock;
......
...@@ -1694,6 +1694,9 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, ...@@ -1694,6 +1694,9 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
struct snd_soc_pcm_runtime *rtd = be_substream->private_data; struct snd_soc_pcm_runtime *rtd = be_substream->private_data;
int i; int i;
if (rtd->dai_link->be_hw_params_fixup)
continue;
if (soc_pcm_has_symmetry(be_substream)) if (soc_pcm_has_symmetry(be_substream))
be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
...@@ -1790,7 +1793,7 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) ...@@ -1790,7 +1793,7 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
continue; continue;
dev_dbg(be->dev, "ASoC: close BE %s\n", dev_dbg(be->dev, "ASoC: close BE %s\n",
dpcm->fe->dai_link->name); be->dai_link->name);
soc_pcm_close(be_substream); soc_pcm_close(be_substream);
be_substream->runtime = NULL; be_substream->runtime = NULL;
...@@ -1856,7 +1859,7 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) ...@@ -1856,7 +1859,7 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
continue; continue;
dev_dbg(be->dev, "ASoC: hw_free BE %s\n", dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
dpcm->fe->dai_link->name); be->dai_link->name);
soc_pcm_hw_free(be_substream); soc_pcm_hw_free(be_substream);
...@@ -1934,7 +1937,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) ...@@ -1934,7 +1937,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
continue; continue;
dev_dbg(be->dev, "ASoC: hw_params BE %s\n", dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
dpcm->fe->dai_link->name); be->dai_link->name);
ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params); ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
if (ret < 0) { if (ret < 0) {
...@@ -2014,7 +2017,7 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm, ...@@ -2014,7 +2017,7 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm,
int ret; int ret;
dev_dbg(dpcm->be->dev, "ASoC: trigger BE %s cmd %d\n", dev_dbg(dpcm->be->dev, "ASoC: trigger BE %s cmd %d\n",
dpcm->fe->dai_link->name, cmd); dpcm->be->dai_link->name, cmd);
ret = soc_pcm_trigger(substream, cmd); ret = soc_pcm_trigger(substream, cmd);
if (ret < 0) if (ret < 0)
...@@ -2229,7 +2232,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) ...@@ -2229,7 +2232,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
continue; continue;
dev_dbg(be->dev, "ASoC: prepare BE %s\n", dev_dbg(be->dev, "ASoC: prepare BE %s\n",
dpcm->fe->dai_link->name); be->dai_link->name);
ret = soc_pcm_prepare(be_substream); ret = soc_pcm_prepare(be_substream);
if (ret < 0) { if (ret < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment