summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/arizona.c2
-rw-r--r--sound/soc/codecs/hdac_hdmi.c180
-rw-r--r--sound/soc/codecs/rt5640.c103
-rw-r--r--sound/soc/codecs/rt5640.h17
-rw-r--r--sound/soc/codecs/rt5645.c4
-rw-r--r--sound/soc/codecs/rt5645.h4
-rw-r--r--sound/soc/codecs/wm5110.c8
7 files changed, 241 insertions, 77 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 38a73e3da508..fb8f18880524 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1656,7 +1656,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
bool reconfig;
unsigned int aif_tx_state, aif_rx_state;
- if (params_rate(params) % 8000)
+ if (params_rate(params) % 4000)
rates = &arizona_44k1_bclk_rates[0];
else
rates = &arizona_48k_bclk_rates[0];
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 1a2f33b4abfc..5a1ec0f7a1a6 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -43,11 +43,13 @@ struct hdac_hdmi_cvt_params {
};
struct hdac_hdmi_cvt {
+ struct list_head head;
hda_nid_t nid;
struct hdac_hdmi_cvt_params params;
};
struct hdac_hdmi_pin {
+ struct list_head head;
hda_nid_t nid;
int num_mux_nids;
hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
@@ -55,21 +57,23 @@ struct hdac_hdmi_pin {
struct hdac_hdmi_dai_pin_map {
int dai_id;
- struct hdac_hdmi_pin pin;
- struct hdac_hdmi_cvt cvt;
+ struct hdac_hdmi_pin *pin;
+ struct hdac_hdmi_cvt *cvt;
};
struct hdac_hdmi_priv {
- hda_nid_t pin_nid[3];
- hda_nid_t cvt_nid[3];
struct hdac_hdmi_dai_pin_map dai_map[3];
+ struct list_head pin_list;
+ struct list_head cvt_list;
+ int num_pin;
+ int num_cvt;
};
static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
{
- struct hdac_device *hdac = container_of(dev, struct hdac_device, dev);
+ struct hdac_device *hdac = dev_to_hdac_dev(dev);
- return container_of(hdac, struct hdac_ext_device, hdac);
+ return to_ehdac_device(hdac);
}
static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
@@ -149,13 +153,15 @@ static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
struct hdac_hdmi_dai_pin_map *dai_map, unsigned int pwr_state)
{
/* Power up pin widget */
- if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin.nid, pwr_state))
- snd_hdac_codec_write(&edev->hdac, dai_map->pin.nid, 0,
+ if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin->nid,
+ pwr_state))
+ snd_hdac_codec_write(&edev->hdac, dai_map->pin->nid, 0,
AC_VERB_SET_POWER_STATE, pwr_state);
/* Power up converter */
- if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt.nid, pwr_state))
- snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0,
+ if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt->nid,
+ pwr_state))
+ snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
AC_VERB_SET_POWER_STATE, pwr_state);
}
@@ -179,13 +185,13 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n",
dd->stream_tag, dd->format);
- ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt.nid,
- dai_map->pin.nid);
+ ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
+ dai_map->pin->nid);
if (ret < 0)
return ret;
- return hdac_hdmi_setup_stream(hdac, dai_map->cvt.nid, dai_map->pin.nid,
- dd->stream_tag, dd->format);
+ return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid,
+ dai_map->pin->nid, dd->stream_tag, dd->format);
}
static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
@@ -221,9 +227,9 @@ static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
dai_map = &hdmi->dai_map[dai->id];
- snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0,
+ snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
AC_VERB_SET_CHANNEL_STREAMID, 0);
- snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0,
+ snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
AC_VERB_SET_STREAM_FORMAT, 0);
dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
@@ -249,7 +255,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
dai_map = &hdmi->dai_map[dai->id];
- val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin.nid, 0,
+ val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin->nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
dev_info(&hdac->hdac.dev, "Val for AC_VERB_GET_PIN_SENSE: %x\n", val);
@@ -260,7 +266,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0);
- snd_hdac_codec_write(&hdac->hdac, dai_map->pin.nid, 0,
+ snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -280,7 +286,7 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
- snd_hdac_codec_write(&hdac->hdac, dai_map->pin.nid, 0,
+ snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
}
@@ -304,26 +310,6 @@ hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
return err;
}
-static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac,
- struct hdac_hdmi_pin *pin)
-{
- if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
- dev_warn(&hdac->hdac.dev,
- "HDMI: pin %d wcaps %#x does not support connection list\n",
- pin->nid, get_wcaps(&hdac->hdac, pin->nid));
- return -EINVAL;
- }
-
- pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
- pin->mux_nids, HDA_MAX_CONNECTIONS);
- if (pin->num_mux_nids == 0) {
- dev_err(&hdac->hdac.dev, "No connections found\n");
- return -ENODEV;
- }
-
- return pin->num_mux_nids;
-}
-
static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w,
enum snd_soc_dapm_type id,
const char *wname, const char *stream)
@@ -366,40 +352,79 @@ static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm,
snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route));
}
-static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev,
- struct hdac_hdmi_dai_pin_map *dai_map,
- hda_nid_t pin_nid, hda_nid_t cvt_nid, int dai_id)
+static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
{
- int ret;
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_dai_pin_map *dai_map = &hdmi->dai_map[0];
+ struct hdac_hdmi_cvt *cvt;
+ struct hdac_hdmi_pin *pin;
- dai_map->dai_id = dai_id;
- dai_map->pin.nid = pin_nid;
+ if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
+ return -EINVAL;
- ret = hdac_hdmi_query_pin_connlist(edev, &dai_map->pin);
- if (ret < 0) {
- dev_err(&edev->hdac.dev,
- "Error querying connection list: %d\n", ret);
- return ret;
- }
+ /*
+ * Currently on board only 1 pin and 1 converter is enabled for
+ * simplification, more will be added eventually
+ * So using fixed map for dai_id:pin:cvt
+ */
+ cvt = list_first_entry(&hdmi->cvt_list, struct hdac_hdmi_cvt, head);
+ pin = list_first_entry(&hdmi->pin_list, struct hdac_hdmi_pin, head);
+
+ dai_map->dai_id = 0;
+ dai_map->pin = pin;
- dai_map->cvt.nid = cvt_nid;
+ dai_map->cvt = cvt;
/* Enable out path for this pin widget */
- snd_hdac_codec_write(&edev->hdac, pin_nid, 0,
+ snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
/* Enable transmission */
- snd_hdac_codec_write(&edev->hdac, cvt_nid, 0,
+ snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
AC_VERB_SET_DIGI_CONVERT_1, 1);
/* Category Code (CC) to zero */
- snd_hdac_codec_write(&edev->hdac, cvt_nid, 0,
+ snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
AC_VERB_SET_DIGI_CONVERT_2, 0);
- snd_hdac_codec_write(&edev->hdac, pin_nid, 0,
+ snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
AC_VERB_SET_CONNECT_SEL, 0);
- return hdac_hdmi_query_cvt_params(&edev->hdac, &dai_map->cvt);
+ return 0;
+}
+
+static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
+{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_cvt *cvt;
+
+ cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
+ if (!cvt)
+ return -ENOMEM;
+
+ cvt->nid = nid;
+
+ list_add_tail(&cvt->head, &hdmi->cvt_list);
+ hdmi->num_cvt++;
+
+ return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
+}
+
+static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
+{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_pin *pin;
+
+ pin = kzalloc(sizeof(*pin), GFP_KERNEL);
+ if (!pin)
+ return -ENOMEM;
+
+ pin->nid = nid;
+
+ list_add_tail(&pin->head, &hdmi->pin_list);
+ hdmi->num_pin++;
+
+ return 0;
}
/*
@@ -412,10 +437,10 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
int i, num_nodes;
struct hdac_device *hdac = &edev->hdac;
struct hdac_hdmi_priv *hdmi = edev->private_data;
- int cvt_nid = 0, pin_nid = 0;
+ int ret;
num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
- if (!nid || num_nodes < 0) {
+ if (!nid || num_nodes <= 0) {
dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
return -EINVAL;
}
@@ -436,29 +461,25 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
switch (type) {
case AC_WID_AUD_OUT:
- hdmi->cvt_nid[cvt_nid] = nid;
- cvt_nid++;
+ ret = hdac_hdmi_add_cvt(edev, nid);
+ if (ret < 0)
+ return ret;
break;
case AC_WID_PIN:
- hdmi->pin_nid[pin_nid] = nid;
- pin_nid++;
+ ret = hdac_hdmi_add_pin(edev, nid);
+ if (ret < 0)
+ return ret;
break;
}
}
hdac->end_nid = nid;
- if (!pin_nid || !cvt_nid)
+ if (!hdmi->num_pin || !hdmi->num_cvt)
return -EIO;
- /*
- * Currently on board only 1 pin and 1 converter is enabled for
- * simplification, more will be added eventually
- * So using fixed map for dai_id:pin:cvt
- */
- return hdac_hdmi_init_dai_map(edev, &hdmi->dai_map[0], hdmi->pin_nid[0],
- hdmi->cvt_nid[0], 0);
+ return hdac_hdmi_init_dai_map(edev);
}
static int hdmi_codec_probe(struct snd_soc_codec *codec)
@@ -542,6 +563,9 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
dev_set_drvdata(&codec->dev, edev);
+ INIT_LIST_HEAD(&hdmi_priv->pin_list);
+ INIT_LIST_HEAD(&hdmi_priv->cvt_list);
+
ret = hdac_hdmi_parse_and_map_nid(edev);
if (ret < 0)
return ret;
@@ -553,8 +577,22 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_pin *pin, *pin_next;
+ struct hdac_hdmi_cvt *cvt, *cvt_next;
+
snd_soc_unregister_codec(&edev->hdac.dev);
+ list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
+ list_del(&cvt->head);
+ kfree(cvt);
+ }
+
+ list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
+ list_del(&pin->head);
+ kfree(pin);
+ }
+
return 0;
}
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index f2beb1aa5763..11d032cdc658 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -488,6 +488,18 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
return 0;
}
+static int is_using_asrc(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
+ struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+ if (!rt5640->asrc_en)
+ return 0;
+
+ return 1;
+}
+
/* Digital Mixer */
static const struct snd_kcontrol_new rt5640_sto_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
@@ -1059,6 +1071,20 @@ static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w,
static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
RT5640_PWR_PLL_BIT, 0, NULL, 0),
+
+ /* ASRC */
+ SND_SOC_DAPM_SUPPLY_S("Stereo Filter ASRC", 1, RT5640_ASRC_1,
+ 15, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S2 Filter ASRC", 1, RT5640_ASRC_1,
+ 12, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5640_ASRC_1,
+ 11, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DMIC1 ASRC", 1, RT5640_ASRC_1,
+ 9, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DMIC2 ASRC", 1, RT5640_ASRC_1,
+ 8, 0, NULL, 0),
+
+
/* Input Side */
/* micbias */
SND_SOC_DAPM_SUPPLY("LDO2", RT5640_PWR_ANLG1,
@@ -1319,6 +1345,12 @@ static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = {
};
static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
+ { "I2S1", NULL, "Stereo Filter ASRC", is_using_asrc },
+ { "I2S2", NULL, "I2S2 ASRC", is_using_asrc },
+ { "I2S2", NULL, "I2S2 Filter ASRC", is_using_asrc },
+ { "DMIC1", NULL, "DMIC1 ASRC", is_using_asrc },
+ { "DMIC2", NULL, "DMIC2 ASRC", is_using_asrc },
+
{"IN1P", NULL, "LDO2"},
{"IN2P", NULL, "LDO2"},
{"IN3P", NULL, "LDO2"},
@@ -1981,6 +2013,76 @@ int rt5640_dmic_enable(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(rt5640_dmic_enable);
+int rt5640_sel_asrc_clk_src(struct snd_soc_codec *codec,
+ unsigned int filter_mask, unsigned int clk_src)
+{
+ struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+ unsigned int asrc2_mask = 0;
+ unsigned int asrc2_value = 0;
+
+ switch (clk_src) {
+ case RT5640_CLK_SEL_SYS:
+ case RT5640_CLK_SEL_ASRC:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (!filter_mask)
+ return -EINVAL;
+
+ if (filter_mask & RT5640_DA_STEREO_FILTER) {
+ asrc2_mask |= RT5640_STO_DAC_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_STO_DAC_M_MASK)
+ | (clk_src << RT5640_STO_DAC_M_SFT);
+ }
+
+ if (filter_mask & RT5640_DA_MONO_L_FILTER) {
+ asrc2_mask |= RT5640_MDA_L_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MDA_L_M_MASK)
+ | (clk_src << RT5640_MDA_L_M_SFT);
+ }
+
+ if (filter_mask & RT5640_DA_MONO_R_FILTER) {
+ asrc2_mask |= RT5640_MDA_R_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MDA_R_M_MASK)
+ | (clk_src << RT5640_MDA_R_M_SFT);
+ }
+
+ if (filter_mask & RT5640_AD_STEREO_FILTER) {
+ asrc2_mask |= RT5640_ADC_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_ADC_M_MASK)
+ | (clk_src << RT5640_ADC_M_SFT);
+ }
+
+ if (filter_mask & RT5640_AD_MONO_L_FILTER) {
+ asrc2_mask |= RT5640_MAD_L_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MAD_L_M_MASK)
+ | (clk_src << RT5640_MAD_L_M_SFT);
+ }
+
+ if (filter_mask & RT5640_AD_MONO_R_FILTER) {
+ asrc2_mask |= RT5640_MAD_R_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MAD_R_M_MASK)
+ | (clk_src << RT5640_MAD_R_M_SFT);
+ }
+
+ snd_soc_update_bits(codec, RT5640_ASRC_2,
+ asrc2_mask, asrc2_value);
+
+ if (snd_soc_read(codec, RT5640_ASRC_2)) {
+ rt5640->asrc_en = true;
+ snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x3);
+ } else {
+ rt5640->asrc_en = false;
+ snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x0);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src);
+
static int rt5640_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
@@ -2175,6 +2277,7 @@ static const struct acpi_device_id rt5640_acpi_match[] = {
{ "INT33CA", 0 },
{ "10EC5640", 0 },
{ "10EC5642", 0 },
+ { "INTCCFFD", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 3deb8babeabb..83a7150ddc24 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -1033,6 +1033,10 @@
#define RT5640_DMIC_2_M_NOR (0x0 << 8)
#define RT5640_DMIC_2_M_ASYN (0x1 << 8)
+/* ASRC clock source selection (0x84) */
+#define RT5640_CLK_SEL_SYS (0x0)
+#define RT5640_CLK_SEL_ASRC (0x1)
+
/* ASRC Control 2 (0x84) */
#define RT5640_MDA_L_M_MASK (0x1 << 15)
#define RT5640_MDA_L_M_SFT 15
@@ -2079,6 +2083,16 @@ enum {
RT5640_DMIC2,
};
+/* filter mask */
+enum {
+ RT5640_DA_STEREO_FILTER = 0x1,
+ RT5640_DA_MONO_L_FILTER = (0x1 << 1),
+ RT5640_DA_MONO_R_FILTER = (0x1 << 2),
+ RT5640_AD_STEREO_FILTER = (0x1 << 3),
+ RT5640_AD_MONO_L_FILTER = (0x1 << 4),
+ RT5640_AD_MONO_R_FILTER = (0x1 << 5),
+};
+
struct rt5640_priv {
struct snd_soc_codec *codec;
struct rt5640_platform_data pdata;
@@ -2095,9 +2109,12 @@ struct rt5640_priv {
int pll_out;
bool hp_mute;
+ bool asrc_en;
};
int rt5640_dmic_enable(struct snd_soc_codec *codec,
bool dmic1_data_pin, bool dmic2_data_pin);
+int rt5640_sel_asrc_clk_src(struct snd_soc_codec *codec,
+ unsigned int filter_mask, unsigned int clk_src);
#endif
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 3e8d66661b7e..6ac9926da330 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -1822,9 +1822,13 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
RT5645_PWR_CLS_D_L,
RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
RT5645_PWR_CLS_D_L);
+ snd_soc_update_bits(codec, RT5645_GEN_CTRL3,
+ RT5645_DET_CLK_MASK, RT5645_DET_CLK_MODE1);
break;
case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5645_GEN_CTRL3,
+ RT5645_DET_CLK_MASK, RT5645_DET_CLK_DIS);
snd_soc_write(codec, RT5645_EQ_CTRL2, 0);
snd_soc_update_bits(codec, RT5645_PWR_DIG1,
RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index 093e46d559fb..205e0715c99a 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -2122,6 +2122,10 @@ enum {
/* General Control3 (0xfc) */
#define RT5645_JD_PSV_MODE (0x1 << 12)
#define RT5645_IRQ_CLK_GATE_CTRL (0x1 << 11)
+#define RT5645_DET_CLK_MASK (0x3 << 9)
+#define RT5645_DET_CLK_DIS (0x0 << 9)
+#define RT5645_DET_CLK_MODE1 (0x1 << 9)
+#define RT5645_DET_CLK_MODE2 (0x2 << 9)
#define RT5645_MICINDET_MANU (0x1 << 7)
#define RT5645_RING2_SLEEVE_GND (0x1 << 5)
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index c36409601835..8d3b20ac7e30 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -360,15 +360,13 @@ static int wm5110_hp_ev(struct snd_soc_dapm_widget *w,
static int wm5110_clear_pga_volume(struct arizona *arizona, int output)
{
- struct reg_sequence clear_pga = {
- ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80
- };
+ unsigned int reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4;
int ret;
- ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1);
+ ret = regmap_write(arizona->regmap, reg, 0x80);
if (ret)
dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n",
- clear_pga.reg, ret);
+ reg, ret);
return ret;
}