diff options
Diffstat (limited to 'sound/soc/tegra/tegra_wired_jack.c')
-rw-r--r-- | sound/soc/tegra/tegra_wired_jack.c | 132 |
1 files changed, 104 insertions, 28 deletions
diff --git a/sound/soc/tegra/tegra_wired_jack.c b/sound/soc/tegra/tegra_wired_jack.c index 10fb237ce64a..b846fa003c62 100644 --- a/sound/soc/tegra/tegra_wired_jack.c +++ b/sound/soc/tegra/tegra_wired_jack.c @@ -29,6 +29,7 @@ #include "tegra_soc.h" #define HEAD_DET_GPIO 0 +#define MIC_DET_GPIO 1 struct wired_jack_conf tegra_wired_jack_conf = { -1, -1, -1, -1 @@ -37,7 +38,7 @@ struct wired_jack_conf tegra_wired_jack_conf = { /* jack */ static struct snd_soc_jack *tegra_wired_jack; -static struct snd_soc_jack_pin hs_jack_pins[] = { +static struct snd_soc_jack_pin wired_jack_pins[] = { { .pin = "Headset Jack", .mask = SND_JACK_HEADSET, @@ -52,7 +53,7 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { }, }; -static struct snd_soc_jack_gpio hs_jack_gpios[] = { +static struct snd_soc_jack_gpio wired_jack_gpios[] = { { /* gpio pin depends on board traits */ .name = "headphone-detect-gpio", @@ -60,6 +61,13 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { .invert = 1, .debounce_time = 200, }, + { + /* gpio pin depens on board traits */ + .name = "mic-detect-gpio", + .report = SND_JACK_MICROPHONE, + .invert = 1, + .debounce_time = 200, + }, }; static struct switch_dev wired_switch_dev = { @@ -76,16 +84,49 @@ static int wired_swith_notify(struct notifier_block *self, unsigned long action, void* dev) { int state = 0; + int flag = 0; + int hp_gpio = -1; + int mic_gpio = -1;; + + /* hp_det_n is low active pin */ + if (tegra_wired_jack_conf.hp_det_n != -1) + hp_gpio = gpio_get_value(tegra_wired_jack_conf.hp_det_n); + if (tegra_wired_jack_conf.cdc_irq != -1) + mic_gpio = gpio_get_value(tegra_wired_jack_conf.cdc_irq); + + flag = (hp_gpio << 4) | mic_gpio; switch (action) { case SND_JACK_HEADSET: state = 1; break; case SND_JACK_HEADPHONE: - state = 2; + if (mic_gpio) + state = 1; + else + state = 2; + break; + case SND_JACK_MICROPHONE: + if (!hp_gpio) /* low = hp */ + state = 1; break; default: - state = 0; + switch (flag) { + case 0x010: + state = 0; + break; + case 0x01: + state = 1; + break; + case 0x11: + /* mic: would not report */ + break; + case 0x00: + state = 2; + break; + default: + state = 0; + } } tegra_switch_set_state(state); @@ -101,30 +142,55 @@ static struct notifier_block wired_switch_nb = { static int tegra_wired_jack_probe(struct platform_device *pdev) { int ret; - int hp_det_n; + int hp_det_n, cdc_irq; + int en_mic_int, en_mic_ext; int en_spkr; struct tegra_wired_jack_conf *pdata; pdata = (struct tegra_wired_jack_conf *)pdev->dev.platform_data; - if (!pdata || !pdata->hp_det_n || !pdata->en_spkr) { + if (!pdata || !pdata->hp_det_n || !pdata->en_spkr || + !pdata->cdc_irq || !pdata->en_mic_int || !pdata->en_mic_ext) { pr_err("Please set up gpio pins for jack.\n"); return -EBUSY; } hp_det_n = pdata->hp_det_n; - hs_jack_gpios[HEAD_DET_GPIO].gpio = hp_det_n; + wired_jack_gpios[HEAD_DET_GPIO].gpio = hp_det_n; + + cdc_irq = pdata->cdc_irq; + wired_jack_gpios[MIC_DET_GPIO].gpio = cdc_irq; ret = snd_soc_jack_add_gpios(tegra_wired_jack, - ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); + ARRAY_SIZE(wired_jack_gpios), + wired_jack_gpios); if (ret) { pr_err("Could NOT set up gpio pins for jack.\n"); snd_soc_jack_free_gpios(tegra_wired_jack, - ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); + ARRAY_SIZE(wired_jack_gpios), + wired_jack_gpios); return ret; } + /* Mic switch controlling pins */ + en_mic_int = pdata->en_mic_int; + en_mic_ext = pdata->en_mic_ext; + + ret = gpio_request(en_mic_int, "en_mic_int"); + if (ret) { + pr_err("Could NOT get gpio for internal mic controlling.\n"); + gpio_free(en_mic_int); + } + gpio_direction_output(en_mic_int, 0); + gpio_export(en_mic_int, false); + + ret = gpio_request(en_mic_ext, "en_mic_ext"); + if (ret) { + pr_err("Could NOT get gpio for external mic controlling.\n"); + gpio_free(en_mic_ext); + } + gpio_direction_output(en_mic_ext, 0); + gpio_export(en_mic_ext, false); + en_spkr = pdata->en_spkr; ret = gpio_request(en_spkr, "en_spkr"); if (ret) { @@ -136,23 +202,44 @@ static int tegra_wired_jack_probe(struct platform_device *pdev) /* restore configuration of these pins */ tegra_wired_jack_conf.hp_det_n = hp_det_n; + tegra_wired_jack_conf.en_mic_int = en_mic_int; + tegra_wired_jack_conf.en_mic_ext = en_mic_ext; + tegra_wired_jack_conf.cdc_irq = cdc_irq; tegra_wired_jack_conf.en_spkr = en_spkr; + /* Addd h2w swith class support */ + ret = switch_dev_register(&wired_switch_dev); + if (ret < 0) + goto switch_dev_failed; + + snd_soc_jack_notifier_register(tegra_wired_jack, + &wired_switch_nb); + return 0; + +switch_dev_failed: + switch_dev_unregister(&wired_switch_dev); + return ret; } static int tegra_wired_jack_remove(struct platform_device *pdev) { snd_soc_jack_free_gpios(tegra_wired_jack, - ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); + ARRAY_SIZE(wired_jack_gpios), + wired_jack_gpios); + + gpio_free(tegra_wired_jack_conf.en_mic_int); + gpio_free(tegra_wired_jack_conf.en_mic_ext); + gpio_free(tegra_wired_jack_conf.en_spkr); + + switch_dev_unregister(&wired_switch_dev); return 0; } static struct platform_driver tegra_wired_jack_driver = { .probe = tegra_wired_jack_probe, - .remove = __devexit_p(tegra_wired_jack_remove), + .remove = tegra_wired_jack_remove, .driver = { .name = "tegra_wired_jack", .owner = THIS_MODULE, @@ -174,33 +261,23 @@ int tegra_jack_init(struct snd_soc_codec *codec) } /* Add jack detection */ - ret = snd_soc_jack_new(codec->socdev->card, "Headset Jack", + ret = snd_soc_jack_new(codec->socdev->card, "Wired Accessory Jack", SND_JACK_HEADSET, tegra_wired_jack); if (ret < 0) goto failed; ret = snd_soc_jack_add_pins(tegra_wired_jack, - ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); + ARRAY_SIZE(wired_jack_pins), + wired_jack_pins); if (ret < 0) goto failed; - /* Addd h2w swith class support */ - ret = switch_dev_register(&wired_switch_dev); - if (ret < 0) - goto switch_dev_failed; - - snd_soc_jack_notifier_register(tegra_wired_jack, - &wired_switch_nb); - ret = platform_driver_register(&tegra_wired_jack_driver); if (ret < 0) goto platform_dev_failed; return 0; -switch_dev_failed: - switch_dev_unregister(&wired_switch_dev); platform_dev_failed: platform_driver_unregister(&tegra_wired_jack_driver); failed: @@ -213,7 +290,6 @@ failed: void tegra_jack_exit(void) { - switch_dev_unregister(&wired_switch_dev); platform_driver_unregister(&tegra_wired_jack_driver); if (tegra_wired_jack) { |