mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-01 02:21:16 +00:00
ASoC: msm: add support for MIC-GND swap switch
If the board has a switch to swap the GND and MIC connections for headset jack, enable the support to flip the switch through gpio to swap GND and MIC. CRs-Fixed: 642944 Change-Id: Ifca2c10ef7789925f1c720a79088a376b4a0adcb Signed-off-by: Simmi Pateriya <simmip@codeaurora.org>
This commit is contained in:
parent
44e45af813
commit
6380abb455
5 changed files with 110 additions and 4 deletions
|
@ -504,9 +504,17 @@ normally open.
|
|||
switch type on target typically the switch type will be normally open or
|
||||
normally close, value for this property 0 for normally close and 1 for
|
||||
normally open.
|
||||
- pinctrl-names : Pincntrl entries to configure the PDM gpio lines accordingly
|
||||
- pinctrl-0 : This exoplains the active state of the PDM gpio lines
|
||||
- pinctrl-1 : This exoplains the suspend state of the PDM gpio lines
|
||||
- pinctrl-names : Pincntrl entries to configure the PDM gpio lines and
|
||||
cross connection switch gpio accordingly
|
||||
- pinctrl-0 : This explains the active state of the PDM gpio lines
|
||||
- pinctrl-1 : This explains the suspend state of the PDM gpio lines
|
||||
- pinctrl-2 : This explains the active state of the cross connection
|
||||
gpio lines
|
||||
- pinctrl-3 : This explains the suspend state of the cross connection
|
||||
gpio lines
|
||||
|
||||
Optional Properties:
|
||||
- qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -517,6 +525,7 @@ Example:
|
|||
qcom,msm-codec-type = "internal";
|
||||
qcom,msm-mbhc-hphl-swh = <0>;
|
||||
qcom,msm-mbhc-gnd-swh = <0>;
|
||||
qcom,cdc-us-euro-gpios = <&msmgpio 120 0>;
|
||||
qcom,audio-routing =
|
||||
"RX_BIAS", "MCLK",
|
||||
"INT_LDO_H", "MCLK",
|
||||
|
@ -527,9 +536,13 @@ Example:
|
|||
"AMIC2", "MIC BIAS Internal2",
|
||||
"AMIC3", "MIC BIAS External";
|
||||
pinctrl-names = "cdc_pdm_lines_act",
|
||||
"cdc_pdm_lines_sus";
|
||||
"cdc_pdm_lines_sus",
|
||||
"cross_conn_det_act",
|
||||
"cross_conn_det_sus";
|
||||
pinctrl-0 = <&cdc_pdm_lines_act>;
|
||||
pinctrl-1 = <&cdc_pdm_lines_sus>;
|
||||
pinctrl-2 = <&cross_conn_det_act>;
|
||||
pinctrl-3 = <&cross_conn_det_sus>;
|
||||
};
|
||||
|
||||
* MSM8974 ASoC Machine driver
|
||||
|
|
|
@ -119,6 +119,7 @@ struct msm8x16_wcd_regulator {
|
|||
|
||||
struct msm8916_asoc_mach_data {
|
||||
int codec_type;
|
||||
int us_euro_gpio;
|
||||
atomic_t mclk_rsc_ref;
|
||||
atomic_t dis_work_mclk;
|
||||
struct mutex cdc_mclk_mutex;
|
||||
|
|
|
@ -441,6 +441,7 @@ static void wcd_mbhc_detect_plug_type(struct wcd_mbhc *mbhc)
|
|||
if (!result1 && !(swap_res & 0x04)) {
|
||||
plug_type = PLUG_TYPE_GND_MIC_SWAP;
|
||||
pr_debug("%s: Cross connection identified", __func__);
|
||||
goto eu_us_switch;
|
||||
} else {
|
||||
pr_debug("%s: No Cross connection found", __func__);
|
||||
}
|
||||
|
@ -468,6 +469,25 @@ static void wcd_mbhc_detect_plug_type(struct wcd_mbhc *mbhc)
|
|||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
eu_us_switch:
|
||||
if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
|
||||
pr_debug("%s: cross connection found\n", __func__);
|
||||
if (mbhc->mbhc_cfg->swap_gnd_mic) {
|
||||
pr_debug("%s: US_EU gpio present, flip switch\n",
|
||||
__func__);
|
||||
if (mbhc->mbhc_cfg->swap_gnd_mic(codec))
|
||||
plug_type = PLUG_TYPE_HEADSET;
|
||||
}
|
||||
/* Disable micbias and schmitt trigger */
|
||||
snd_soc_update_bits(codec,
|
||||
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2,
|
||||
0x6, 0x0);
|
||||
snd_soc_update_bits(codec,
|
||||
MSM8X16_WCD_A_ANALOG_MICB_2_EN,
|
||||
0x80, 0x00);
|
||||
}
|
||||
|
||||
pr_debug("%s: Valid plug found, plug type is %d\n",
|
||||
__func__, plug_type);
|
||||
wcd_mbhc_find_plug_and_report(mbhc, plug_type);
|
||||
|
|
|
@ -31,6 +31,7 @@ struct wcd_mbhc_config {
|
|||
void *calibration;
|
||||
bool detect_extn_cable;
|
||||
bool mono_stero_detection;
|
||||
bool (*swap_gnd_mic) (struct snd_soc_codec *codec);
|
||||
};
|
||||
|
||||
struct wcd_mbhc_intr {
|
||||
|
|
|
@ -56,6 +56,7 @@ static struct wcd_mbhc_config mbhc_cfg = {
|
|||
.calibration = NULL,
|
||||
.detect_extn_cable = true,
|
||||
.mono_stero_detection = false,
|
||||
.swap_gnd_mic = NULL,
|
||||
};
|
||||
|
||||
static struct afe_clk_cfg mi2s_rx_clk = {
|
||||
|
@ -82,6 +83,8 @@ struct cdc_pdm_pinctrl_info {
|
|||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *cdc_pdm_sus;
|
||||
struct pinctrl_state *cdc_pdm_act;
|
||||
struct pinctrl_state *cross_conn_det_sus;
|
||||
struct pinctrl_state *cross_conn_det_act;
|
||||
};
|
||||
|
||||
static struct cdc_pdm_pinctrl_info pinctrl_info;
|
||||
|
@ -970,7 +973,29 @@ static int cdc_pdm_get_pinctrl(struct platform_device *pdev)
|
|||
pr_err("%s: Failed to disable the TLMM pins\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
/* get pinctrl handle for cross det pin*/
|
||||
pinctrl_info.cross_conn_det_sus = pinctrl_lookup_state(pinctrl,
|
||||
"cross_conn_det_sus");
|
||||
if (IS_ERR(pinctrl_info.cross_conn_det_sus)) {
|
||||
pr_err("%s: Unable to get pinctrl disable state handle\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pinctrl_info.cross_conn_det_act = pinctrl_lookup_state(pinctrl,
|
||||
"cross_conn_det_act");
|
||||
if (IS_ERR(pinctrl_info.cross_conn_det_act)) {
|
||||
pr_err("%s: Unable to get pinctrl active state handle\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Reset cross conn det pins to default state*/
|
||||
ret = pinctrl_select_state(pinctrl_info.pinctrl,
|
||||
pinctrl_info.cross_conn_det_sus);
|
||||
if (ret != 0) {
|
||||
pr_err("%s: Failed to disable cross conn det pins\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -998,6 +1023,50 @@ void enable_mclk(struct work_struct *work)
|
|||
mutex_unlock(&pdata->cdc_mclk_mutex);
|
||||
}
|
||||
|
||||
static bool msm8x16_swap_gnd_mic(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
|
||||
int value, ret;
|
||||
|
||||
if (!gpio_is_valid(pdata->us_euro_gpio)) {
|
||||
pr_debug("%s: Invalid gpio: %d", __func__, pdata->us_euro_gpio);
|
||||
return false;
|
||||
}
|
||||
ret = pinctrl_select_state(pinctrl_info.pinctrl,
|
||||
pinctrl_info.cross_conn_det_act);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to configure the gpio\n");
|
||||
return ret;
|
||||
}
|
||||
value = gpio_get_value_cansleep(pdata->us_euro_gpio);
|
||||
gpio_direction_output(pdata->us_euro_gpio, !value);
|
||||
pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
|
||||
ret = pinctrl_select_state(pinctrl_info.pinctrl,
|
||||
pinctrl_info.cross_conn_det_sus);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to configure the gpio\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void msm8x16_setup_hs_jack(struct platform_device *pdev,
|
||||
struct msm8916_asoc_mach_data *pdata)
|
||||
{
|
||||
pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
|
||||
"qcom,cdc-us-euro-gpios", 0);
|
||||
if (pdata->us_euro_gpio < 0) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"property %s in node %s not found %d\n",
|
||||
"qcom,cdc-us-euro-gpios", pdev->dev.of_node->full_name,
|
||||
pdata->us_euro_gpio);
|
||||
} else {
|
||||
mbhc_cfg.swap_gnd_mic = msm8x16_swap_gnd_mic;
|
||||
}
|
||||
}
|
||||
|
||||
static int msm8x16_asoc_machine_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card;
|
||||
|
@ -1065,6 +1134,8 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev)
|
|||
}
|
||||
card = &bear_cards[pdev->id];
|
||||
|
||||
msm8x16_setup_hs_jack(pdev, pdata);
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, card);
|
||||
snd_soc_card_set_drvdata(card, pdata);
|
||||
|
|
Loading…
Reference in a new issue