Loading sound/soc/msm/device_event.h 0 → 100644 +20 −0 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __DEVICE_EVENT_H #define __DEVICE_EVENT_H #define QC_AUDIO_EXTERNAL_SPK_1_EVENT "qc_ext_spk_1" #define QC_AUDIO_EXTERNAL_SPK_2_EVENT "qc_ext_spk_2" #define QC_AUDIO_EXTERNAL_MIC_EVENT "qc_ext_mic" #endif /* __DEVICE_EVENT_H */ sound/soc/msm/msm8994.c +130 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/regulator/consumer.h> #include <linux/io.h> #include <linux/module.h> #include <linux/switch.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/soc-dapm.h> Loading @@ -27,6 +28,7 @@ #include <sound/jack.h> #include <sound/q6afe-v2.h> #include <sound/pcm_params.h> #include <device_event.h> #include "qdsp6v2/msm-pcm-routing-v2.h" #include "qdsp6v2/q6core.h" #include "../codecs/wcd9xxx-common.h" Loading Loading @@ -113,6 +115,16 @@ static int clk_users; static atomic_t prim_auxpcm_rsc_ref; static atomic_t sec_auxpcm_rsc_ref; struct msm8994_liquid_dock_dev { int dock_plug_gpio; int dock_plug_irq; int dock_plug_det; struct work_struct irq_work; struct switch_dev audio_sdev; }; static struct msm8994_liquid_dock_dev *msm8994_liquid_dock_dev; static const char *const pin_states[] = {"Disable", "active"}; static const char *const spk_function[] = {"Off", "On"}; static const char *const slim0_rx_ch_text[] = {"One", "Two"}; Loading Loading @@ -199,6 +211,103 @@ static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit) } } static void msm8994_liquid_docking_irq_work(struct work_struct *work) { struct msm8994_liquid_dock_dev *dock_dev = container_of(work, struct msm8994_liquid_dock_dev, irq_work); dock_dev->dock_plug_det = gpio_get_value(dock_dev->dock_plug_gpio); switch_set_state(&dock_dev->audio_sdev, dock_dev->dock_plug_det); /*notify to audio deamon*/ sysfs_notify(&dock_dev->audio_sdev.dev->kobj, NULL, "state"); } static irqreturn_t msm8994_liquid_docking_irq_handler(int irq, void *dev) { struct msm8994_liquid_dock_dev *dock_dev = dev; /* switch speakers should not run in interrupt context */ schedule_work(&dock_dev->irq_work); return IRQ_HANDLED; } static int msm8994_liquid_init_docking(void) { int ret = 0; int dock_plug_gpio = 0; /* plug in docking speaker+plug in device OR unplug one of them */ u32 dock_plug_irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED; dock_plug_gpio = of_get_named_gpio(spdev->dev.of_node, "qcom,dock-plug-det-irq", 0); if (dock_plug_gpio >= 0) { msm8994_liquid_dock_dev = kzalloc(sizeof(*msm8994_liquid_dock_dev), GFP_KERNEL); if (!msm8994_liquid_dock_dev) { pr_err("msm8994_liquid_dock_dev alloc fail.\n"); ret = -ENOMEM; goto exit; } msm8994_liquid_dock_dev->dock_plug_gpio = dock_plug_gpio; ret = gpio_request(msm8994_liquid_dock_dev->dock_plug_gpio, "dock-plug-det-irq"); if (ret) { pr_err("%s:failed request msm8994_liquid_dock_plug_gpio err = %d\n", __func__, ret); ret = -EINVAL; goto fail_dock_gpio; } msm8994_liquid_dock_dev->dock_plug_det = gpio_get_value(msm8994_liquid_dock_dev->dock_plug_gpio); msm8994_liquid_dock_dev->dock_plug_irq = gpio_to_irq(msm8994_liquid_dock_dev->dock_plug_gpio); ret = request_irq(msm8994_liquid_dock_dev->dock_plug_irq, msm8994_liquid_docking_irq_handler, dock_plug_irq_flags, "liquid_dock_plug_irq", msm8994_liquid_dock_dev); if (ret < 0) { pr_err("%s: Request Irq Failed err = %d\n", __func__, ret); goto fail_dock_gpio; } msm8994_liquid_dock_dev->audio_sdev.name = QC_AUDIO_EXTERNAL_SPK_1_EVENT; if (switch_dev_register( &msm8994_liquid_dock_dev->audio_sdev) < 0) { pr_err("%s: dock device register in switch diretory failed\n", __func__); goto fail_switch_dev; } INIT_WORK( &msm8994_liquid_dock_dev->irq_work, msm8994_liquid_docking_irq_work); } return 0; fail_switch_dev: free_irq(msm8994_liquid_dock_dev->dock_plug_irq, msm8994_liquid_dock_dev); fail_dock_gpio: gpio_free(msm8994_liquid_dock_dev->dock_plug_gpio); exit: kfree(msm8994_liquid_dock_dev); msm8994_liquid_dock_dev = NULL; return ret; } static void msm8994_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; Loading Loading @@ -1469,6 +1578,13 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) return err; } err = msm8994_liquid_init_docking(); if (err) { pr_err("%s: 8994 init Docking stat IRQ failed (%d)\n", __func__, err); return err; } err = msm8994_ext_us_amp_init(); if (err) { pr_err("%s: MTP 8994 US Emitter GPIO init failed (%d)\n", Loading Loading @@ -2961,6 +3077,20 @@ static int msm8994_asoc_machine_remove(struct platform_device *pdev) gpio_free(pdata->mclk_gpio); gpio_free(pdata->us_euro_gpio); if (msm8994_liquid_dock_dev != NULL) { switch_dev_unregister(&msm8994_liquid_dock_dev->audio_sdev); if (msm8994_liquid_dock_dev->dock_plug_irq) free_irq(msm8994_liquid_dock_dev->dock_plug_irq, msm8994_liquid_dock_dev); if (msm8994_liquid_dock_dev->dock_plug_gpio) gpio_free(msm8994_liquid_dock_dev->dock_plug_gpio); kfree(msm8994_liquid_dock_dev); msm8994_liquid_dock_dev = NULL; } msm_auxpcm_release_pinctrl(pdev, SEC_MI2S_PCM); msm_mi2s_release_pinctrl(pdev, PRI_MI2S_PCM); snd_soc_unregister_card(card); Loading Loading
sound/soc/msm/device_event.h 0 → 100644 +20 −0 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __DEVICE_EVENT_H #define __DEVICE_EVENT_H #define QC_AUDIO_EXTERNAL_SPK_1_EVENT "qc_ext_spk_1" #define QC_AUDIO_EXTERNAL_SPK_2_EVENT "qc_ext_spk_2" #define QC_AUDIO_EXTERNAL_MIC_EVENT "qc_ext_mic" #endif /* __DEVICE_EVENT_H */
sound/soc/msm/msm8994.c +130 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/regulator/consumer.h> #include <linux/io.h> #include <linux/module.h> #include <linux/switch.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/soc-dapm.h> Loading @@ -27,6 +28,7 @@ #include <sound/jack.h> #include <sound/q6afe-v2.h> #include <sound/pcm_params.h> #include <device_event.h> #include "qdsp6v2/msm-pcm-routing-v2.h" #include "qdsp6v2/q6core.h" #include "../codecs/wcd9xxx-common.h" Loading Loading @@ -113,6 +115,16 @@ static int clk_users; static atomic_t prim_auxpcm_rsc_ref; static atomic_t sec_auxpcm_rsc_ref; struct msm8994_liquid_dock_dev { int dock_plug_gpio; int dock_plug_irq; int dock_plug_det; struct work_struct irq_work; struct switch_dev audio_sdev; }; static struct msm8994_liquid_dock_dev *msm8994_liquid_dock_dev; static const char *const pin_states[] = {"Disable", "active"}; static const char *const spk_function[] = {"Off", "On"}; static const char *const slim0_rx_ch_text[] = {"One", "Two"}; Loading Loading @@ -199,6 +211,103 @@ static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit) } } static void msm8994_liquid_docking_irq_work(struct work_struct *work) { struct msm8994_liquid_dock_dev *dock_dev = container_of(work, struct msm8994_liquid_dock_dev, irq_work); dock_dev->dock_plug_det = gpio_get_value(dock_dev->dock_plug_gpio); switch_set_state(&dock_dev->audio_sdev, dock_dev->dock_plug_det); /*notify to audio deamon*/ sysfs_notify(&dock_dev->audio_sdev.dev->kobj, NULL, "state"); } static irqreturn_t msm8994_liquid_docking_irq_handler(int irq, void *dev) { struct msm8994_liquid_dock_dev *dock_dev = dev; /* switch speakers should not run in interrupt context */ schedule_work(&dock_dev->irq_work); return IRQ_HANDLED; } static int msm8994_liquid_init_docking(void) { int ret = 0; int dock_plug_gpio = 0; /* plug in docking speaker+plug in device OR unplug one of them */ u32 dock_plug_irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED; dock_plug_gpio = of_get_named_gpio(spdev->dev.of_node, "qcom,dock-plug-det-irq", 0); if (dock_plug_gpio >= 0) { msm8994_liquid_dock_dev = kzalloc(sizeof(*msm8994_liquid_dock_dev), GFP_KERNEL); if (!msm8994_liquid_dock_dev) { pr_err("msm8994_liquid_dock_dev alloc fail.\n"); ret = -ENOMEM; goto exit; } msm8994_liquid_dock_dev->dock_plug_gpio = dock_plug_gpio; ret = gpio_request(msm8994_liquid_dock_dev->dock_plug_gpio, "dock-plug-det-irq"); if (ret) { pr_err("%s:failed request msm8994_liquid_dock_plug_gpio err = %d\n", __func__, ret); ret = -EINVAL; goto fail_dock_gpio; } msm8994_liquid_dock_dev->dock_plug_det = gpio_get_value(msm8994_liquid_dock_dev->dock_plug_gpio); msm8994_liquid_dock_dev->dock_plug_irq = gpio_to_irq(msm8994_liquid_dock_dev->dock_plug_gpio); ret = request_irq(msm8994_liquid_dock_dev->dock_plug_irq, msm8994_liquid_docking_irq_handler, dock_plug_irq_flags, "liquid_dock_plug_irq", msm8994_liquid_dock_dev); if (ret < 0) { pr_err("%s: Request Irq Failed err = %d\n", __func__, ret); goto fail_dock_gpio; } msm8994_liquid_dock_dev->audio_sdev.name = QC_AUDIO_EXTERNAL_SPK_1_EVENT; if (switch_dev_register( &msm8994_liquid_dock_dev->audio_sdev) < 0) { pr_err("%s: dock device register in switch diretory failed\n", __func__); goto fail_switch_dev; } INIT_WORK( &msm8994_liquid_dock_dev->irq_work, msm8994_liquid_docking_irq_work); } return 0; fail_switch_dev: free_irq(msm8994_liquid_dock_dev->dock_plug_irq, msm8994_liquid_dock_dev); fail_dock_gpio: gpio_free(msm8994_liquid_dock_dev->dock_plug_gpio); exit: kfree(msm8994_liquid_dock_dev); msm8994_liquid_dock_dev = NULL; return ret; } static void msm8994_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; Loading Loading @@ -1469,6 +1578,13 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) return err; } err = msm8994_liquid_init_docking(); if (err) { pr_err("%s: 8994 init Docking stat IRQ failed (%d)\n", __func__, err); return err; } err = msm8994_ext_us_amp_init(); if (err) { pr_err("%s: MTP 8994 US Emitter GPIO init failed (%d)\n", Loading Loading @@ -2961,6 +3077,20 @@ static int msm8994_asoc_machine_remove(struct platform_device *pdev) gpio_free(pdata->mclk_gpio); gpio_free(pdata->us_euro_gpio); if (msm8994_liquid_dock_dev != NULL) { switch_dev_unregister(&msm8994_liquid_dock_dev->audio_sdev); if (msm8994_liquid_dock_dev->dock_plug_irq) free_irq(msm8994_liquid_dock_dev->dock_plug_irq, msm8994_liquid_dock_dev); if (msm8994_liquid_dock_dev->dock_plug_gpio) gpio_free(msm8994_liquid_dock_dev->dock_plug_gpio); kfree(msm8994_liquid_dock_dev); msm8994_liquid_dock_dev = NULL; } msm_auxpcm_release_pinctrl(pdev, SEC_MI2S_PCM); msm_mi2s_release_pinctrl(pdev, PRI_MI2S_PCM); snd_soc_unregister_card(card); Loading