Merge "ARM: dts: msm: Add EN2 gpio for mic/gnd swap for SDM845 QRD target"

This commit is contained in:
Linux Build Service Account 2017-06-03 23:29:53 -07:00 committed by Gerrit - the friendly Code Review server
commit db727b2695
9 changed files with 243 additions and 52 deletions

View File

@ -2256,8 +2256,8 @@ Optional properties:
- qcom,wcn-btfm : Property to specify if WCN BT/FM chip is used for the target
- qcom,msm-mbhc-usbc-audio-supported : Property to specify if analog audio feature is
enabled or not.
- qcom,usbc-analog-en1_gpio : EN1 GPIO to enable USB type-C analog audio
- qcom,usbc-analog-en2_n_gpio : EN2 GPIO to enable USB type-C analog audio
- qcom,usbc-analog-en1-gpio : EN1 GPIO to enable USB type-C analog audio
- qcom,usbc-analog-en2-gpio : EN2 GPIO to enable USB type-C analog audio
- qcom,usbc-analog-force_detect_gpio : Force detect GPIO to enable USB type-C analog audio
Example:
@ -2333,8 +2333,8 @@ Example:
qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
"SpkrRight", "SpkrLeft";
qcom,msm-mbhc-usbc-audio-supported = <1>;
qcom,usbc-analog-en1_gpio = <&wcd_usbc_analog_en1_gpio>;
qcom,usbc-analog-en2_n_gpio = <&wcd_usbc_analog_en2n_gpio>;
qcom,usbc-analog-en1-gpio = <&wcd_usbc_analog_en1_gpio>;
qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
qcom,usbc-analog-force_detect_gpio = <&wcd_usbc_analog_f_gpio>;
};

View File

@ -78,6 +78,9 @@
qcom,hph-en0-gpio = <&tavil_hph_en0>;
qcom,hph-en1-gpio = <&tavil_hph_en1>;
qcom,tavil-mclk-clk-freq = <9600000>;
qcom,usbc-analog-en1-gpio = <&wcd_usbc_analog_en1_gpio>;
asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
<&loopback>, <&compress>, <&hostless>,
<&afe>, <&lsm>, <&routing>, <&compr>,
@ -136,6 +139,18 @@
<&wsa881x_0213>, <&wsa881x_0214>;
qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
"SpkrLeft", "SpkrRight";
qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
pinctrl-names = "aud_active", "aud_sleep";
pinctrl-0 = <&wcd_usbc_analog_en2_active>;
pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
};
wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl@49 {
compatible = "qcom,msm-cdc-pinctrl";
pinctrl-names = "aud_active", "aud_sleep";
pinctrl-0 = <&wcd_usbc_analog_en1_active>;
pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
};
wcd9xxx_intc: wcd9xxx-irq {

View File

@ -299,6 +299,63 @@
};
};
/* USB C analog configuration */
wcd_usbc_analog_en1 {
wcd_usbc_analog_en1_idle: wcd_usbc_ana_en1_idle {
mux {
pins = "gpio49";
function = "gpio";
};
config {
pins = "gpio49";
drive-strength = <2>;
bias-pull-down;
output-low;
};
};
wcd_usbc_analog_en1_active: wcd_usbc_ana_en1_active {
mux {
pins = "gpio49";
function = "gpio";
};
config {
pins = "gpio49";
drive-strength = <2>;
bias-disable;
output-high;
};
};
};
wcd_usbc_analog_en2 {
wcd_usbc_analog_en2_idle: wcd_usbc_ana_en2_idle {
mux {
pins = "gpio51";
function = "gpio";
};
config {
pins = "gpio51";
drive-strength = <2>;
bias-pull-down;
output-low;
};
};
wcd_usbc_analog_en2_active: wcd_usbc_ana_en2_active {
mux {
pins = "gpio51";
function = "gpio";
};
config {
pins = "gpio51";
drive-strength = <2>;
bias-disable;
output-high;
};
};
};
pri_aux_pcm_clk {
pri_aux_pcm_clk_sleep: pri_aux_pcm_clk_sleep {
mux {

View File

@ -105,6 +105,41 @@
qcom,wsa-max-devs = <1>;
qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
qcom,msm-mbhc-usbc-audio-supported = <1>;
qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
pinctrl-names = "aud_active", "aud_sleep";
pinctrl-0 = <&wcd_usbc_analog_en2_active>;
pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
};
};
&wcd934x_cdc {
wcd: wcd_pinctrl@5 {
us_euro_sw_wcd_active: us_euro_sw_wcd_active {
mux {
pins = "gpio1";
};
config {
pins = "gpio1";
/delete-property/ output-high;
bias-high-impedance;
};
};
us_euro_sw_wcd_sleep: us_euro_sw_wcd_sleep {
mux {
pins = "gpio1";
};
config {
pins = "gpio1";
/delete-property/ output-low;
bias-high-impedance;
};
};
};
};

View File

@ -729,7 +729,8 @@ correct_plug_type:
* otherwise report unsupported plug
*/
if (mbhc->mbhc_cfg->swap_gnd_mic &&
mbhc->mbhc_cfg->swap_gnd_mic(codec)) {
mbhc->mbhc_cfg->swap_gnd_mic(codec,
true)) {
pr_debug("%s: US_EU gpio present,flip switch\n"
, __func__);
continue;

View File

@ -633,7 +633,8 @@ correct_plug_type:
* otherwise report unsupported plug
*/
if (mbhc->mbhc_cfg->swap_gnd_mic &&
mbhc->mbhc_cfg->swap_gnd_mic(codec)) {
mbhc->mbhc_cfg->swap_gnd_mic(codec,
true)) {
pr_debug("%s: US_EU gpio present,flip switch\n"
, __func__);
continue;

View File

@ -1460,18 +1460,12 @@ static int wcd_mbhc_usb_c_analog_setup_gpios(struct wcd_mbhc *mbhc,
if (config->usbc_en1_gpio_p)
rc = msm_cdc_pinctrl_select_active_state(
config->usbc_en1_gpio_p);
if (rc == 0 && config->usbc_en2n_gpio_p)
rc = msm_cdc_pinctrl_select_active_state(
config->usbc_en2n_gpio_p);
if (rc == 0 && config->usbc_force_gpio_p)
rc = msm_cdc_pinctrl_select_active_state(
config->usbc_force_gpio_p);
mbhc->usbc_mode = POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
} else {
/* no delay is required when disabling GPIOs */
if (config->usbc_en2n_gpio_p)
msm_cdc_pinctrl_select_sleep_state(
config->usbc_en2n_gpio_p);
if (config->usbc_en1_gpio_p)
msm_cdc_pinctrl_select_sleep_state(
config->usbc_en1_gpio_p);
@ -1490,6 +1484,8 @@ static int wcd_mbhc_usb_c_analog_setup_gpios(struct wcd_mbhc *mbhc,
}
mbhc->usbc_mode = POWER_SUPPLY_TYPEC_NONE;
if (mbhc->mbhc_cfg->swap_gnd_mic)
mbhc->mbhc_cfg->swap_gnd_mic(mbhc->codec, false);
}
return rc;
@ -1675,19 +1671,12 @@ int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg)
dev_dbg(mbhc->codec->dev, "%s: usbc analog enabled\n",
__func__);
rc = wcd_mbhc_init_gpio(mbhc, mbhc_cfg,
"qcom,usbc-analog-en1_gpio",
"qcom,usbc-analog-en1-gpio",
&config->usbc_en1_gpio,
&config->usbc_en1_gpio_p);
if (rc)
goto err;
rc = wcd_mbhc_init_gpio(mbhc, mbhc_cfg,
"qcom,usbc-analog-en2_n_gpio",
&config->usbc_en2n_gpio,
&config->usbc_en2n_gpio_p);
if (rc)
goto err;
if (of_find_property(card->dev->of_node,
"qcom,usbc-analog-force_detect_gpio",
NULL)) {
@ -1734,12 +1723,6 @@ err:
gpio_free(config->usbc_en1_gpio);
config->usbc_en1_gpio = 0;
}
if (config->usbc_en2n_gpio > 0) {
dev_dbg(card->dev, "%s free usb_en2 gpio %d\n",
__func__, config->usbc_en2n_gpio);
gpio_free(config->usbc_en2n_gpio);
config->usbc_en2n_gpio = 0;
}
if (config->usbc_force_gpio > 0) {
dev_dbg(card->dev, "%s free usb_force gpio %d\n",
__func__, config->usbc_force_gpio);
@ -1748,8 +1731,6 @@ err:
}
if (config->usbc_en1_gpio_p)
of_node_put(config->usbc_en1_gpio_p);
if (config->usbc_en2n_gpio_p)
of_node_put(config->usbc_en2n_gpio_p);
if (config->usbc_force_gpio_p)
of_node_put(config->usbc_force_gpio_p);
dev_dbg(mbhc->codec->dev, "%s: leave %d\n", __func__, rc);
@ -1790,15 +1771,11 @@ void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
/* free GPIOs */
if (config->usbc_en1_gpio > 0)
gpio_free(config->usbc_en1_gpio);
if (config->usbc_en2n_gpio > 0)
gpio_free(config->usbc_en2n_gpio);
if (config->usbc_force_gpio)
gpio_free(config->usbc_force_gpio);
if (config->usbc_en1_gpio_p)
of_node_put(config->usbc_en1_gpio_p);
if (config->usbc_en2n_gpio_p)
of_node_put(config->usbc_en2n_gpio_p);
if (config->usbc_force_gpio_p)
of_node_put(config->usbc_force_gpio_p);
}

View File

@ -404,10 +404,10 @@ enum mbhc_moisture_rref {
struct usbc_ana_audio_config {
int usbc_en1_gpio;
int usbc_en2n_gpio;
int usbc_en2_gpio;
int usbc_force_gpio;
struct device_node *usbc_en1_gpio_p; /* used by pinctrl API */
struct device_node *usbc_en2n_gpio_p; /* used by pinctrl API */
struct device_node *usbc_en2_gpio_p; /* used by pinctrl API */
struct device_node *usbc_force_gpio_p; /* used by pinctrl API */
};
@ -416,7 +416,7 @@ struct wcd_mbhc_config {
void *calibration;
bool detect_extn_cable;
bool mono_stero_detection;
bool (*swap_gnd_mic)(struct snd_soc_codec *codec);
bool (*swap_gnd_mic)(struct snd_soc_codec *codec, bool active);
bool hs_ext_micbias;
bool gnd_det_en;
int key_code[WCD_MBHC_KEYCODE_NUM];

View File

@ -173,7 +173,9 @@ struct msm_pinctrl_info {
struct msm_asoc_mach_data {
u32 mclk_freq;
int us_euro_gpio; /* used by gpio driver API */
int usbc_en2_gpio; /* used by gpio driver API */
struct device_node *us_euro_gpio_p; /* used by pinctrl API */
struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
struct snd_info_entry *codec_root;
@ -3106,27 +3108,126 @@ done:
return rc;
}
static bool msm_swap_gnd_mic(struct snd_soc_codec *codec)
static bool msm_usbc_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
{
struct snd_soc_card *card = codec->component.card;
struct msm_asoc_mach_data *pdata =
snd_soc_card_get_drvdata(card);
int value = 0;
bool ret = 0;
struct snd_soc_card *card = codec->component.card;
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
struct pinctrl_state *en2_pinctrl_active;
struct pinctrl_state *en2_pinctrl_sleep;
if (pdata->us_euro_gpio_p) {
value = msm_cdc_pinctrl_get_state(pdata->us_euro_gpio_p);
if (value)
msm_cdc_pinctrl_select_sleep_state(
pdata->us_euro_gpio_p);
else
msm_cdc_pinctrl_select_active_state(
pdata->us_euro_gpio_p);
} else if (pdata->us_euro_gpio >= 0) {
value = gpio_get_value_cansleep(pdata->us_euro_gpio);
gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
if (!pdata->usbc_en2_gpio_p) {
if (active) {
/* if active and usbc_en2_gpio undefined, get pin */
pdata->usbc_en2_gpio_p = devm_pinctrl_get(card->dev);
if (IS_ERR_OR_NULL(pdata->usbc_en2_gpio_p)) {
dev_err(card->dev,
"%s: Can't get EN2 gpio pinctrl:%ld\n",
__func__,
PTR_ERR(pdata->usbc_en2_gpio_p));
pdata->usbc_en2_gpio_p = NULL;
return false;
}
} else
/* if not active and usbc_en2_gpio undefined, return */
return false;
}
pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
return true;
pdata->usbc_en2_gpio = of_get_named_gpio(card->dev->of_node,
"qcom,usbc-analog-en2-gpio", 0);
if (!gpio_is_valid(pdata->usbc_en2_gpio)) {
dev_err(card->dev, "%s, property %s not in node %s",
__func__, "qcom,usbc-analog-en2-gpio",
card->dev->of_node->full_name);
return false;
}
en2_pinctrl_active = pinctrl_lookup_state(
pdata->usbc_en2_gpio_p, "aud_active");
if (IS_ERR_OR_NULL(en2_pinctrl_active)) {
dev_err(card->dev,
"%s: Cannot get aud_active pinctrl state:%ld\n",
__func__, PTR_ERR(en2_pinctrl_active));
ret = false;
goto err_lookup_state;
}
en2_pinctrl_sleep = pinctrl_lookup_state(
pdata->usbc_en2_gpio_p, "aud_sleep");
if (IS_ERR_OR_NULL(en2_pinctrl_sleep)) {
dev_err(card->dev,
"%s: Cannot get aud_sleep pinctrl state:%ld\n",
__func__, PTR_ERR(en2_pinctrl_sleep));
ret = false;
goto err_lookup_state;
}
/* if active and usbc_en2_gpio_p defined, swap using usbc_en2_gpio_p */
if (active) {
dev_dbg(codec->dev, "%s: enter\n", __func__);
if (pdata->usbc_en2_gpio_p) {
value = gpio_get_value_cansleep(pdata->usbc_en2_gpio);
if (value)
pinctrl_select_state(pdata->usbc_en2_gpio_p,
en2_pinctrl_sleep);
else
pinctrl_select_state(pdata->usbc_en2_gpio_p,
en2_pinctrl_active);
} else if (pdata->usbc_en2_gpio >= 0) {
value = gpio_get_value_cansleep(pdata->usbc_en2_gpio);
gpio_set_value_cansleep(pdata->usbc_en2_gpio, !value);
}
pr_debug("%s: swap select switch %d to %d\n", __func__,
value, !value);
ret = true;
} else {
/* if not active, release usbc_en2_gpio_p pin */
pinctrl_select_state(pdata->usbc_en2_gpio_p,
en2_pinctrl_sleep);
}
err_lookup_state:
devm_pinctrl_put(pdata->usbc_en2_gpio_p);
pdata->usbc_en2_gpio_p = NULL;
return ret;
}
static bool msm_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
{
int value = 0;
int ret = 0;
struct snd_soc_card *card = codec->component.card;
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
if (!pdata)
return false;
if (!wcd_mbhc_cfg.enable_usbc_analog) {
/* if usbc is not defined, swap using us_euro_gpio_p */
if (pdata->us_euro_gpio_p) {
value = msm_cdc_pinctrl_get_state(
pdata->us_euro_gpio_p);
if (value)
msm_cdc_pinctrl_select_sleep_state(
pdata->us_euro_gpio_p);
else
msm_cdc_pinctrl_select_active_state(
pdata->us_euro_gpio_p);
} else if (pdata->us_euro_gpio >= 0) {
value = gpio_get_value_cansleep(
pdata->us_euro_gpio);
gpio_set_value_cansleep(
pdata->us_euro_gpio, !value);
}
pr_debug("%s: swap select switch %d to %d\n", __func__,
value, !value);
ret = true;
} else {
/* if usbc is defined, swap using usbc_en2 */
ret = msm_usbc_swap_gnd_mic(codec, active);
}
return ret;
}
static int msm_afe_set_config(struct snd_soc_codec *codec)
@ -6454,6 +6555,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
char *mclk_freq_prop_name;
const struct of_device_id *match;
int ret;
const char *usb_c_dt = "qcom,msm-mbhc-usbc-audio-supported";
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "No platform supplied from device tree\n");
@ -6601,6 +6703,9 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
}
if (of_find_property(pdev->dev.of_node, usb_c_dt, NULL))
wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
ret = msm_prepare_us_euro(card);
if (ret)
dev_dbg(&pdev->dev, "msm_prepare_us_euro failed (%d)\n",