ASoC: tegra: headset: improve dock switch code
Remove all audio routing and use two switch devices
to signal userspace of dock changes. Routing can
then be done in userspace for the dock.
Change-Id: Id73a5ea6754a780897bc23aec02157749a3a5fd6
Signed-off-by: Simon Wilson <simonwilson@google.com>
diff --git a/sound/soc/tegra/headset.c b/sound/soc/tegra/headset.c
index 651eb62..368d0cd 100644
--- a/sound/soc/tegra/headset.c
+++ b/sound/soc/tegra/headset.c
@@ -74,7 +74,7 @@
static int switch_config_gpio(void);
int hs_micbias_power(int on);
static irqreturn_t dockin_irq_handler(int irq, void *dev_id);
-static void audio_dock_switch(void);
+static void set_dock_switches(void);
/*----------------------------------------------------------------------------
** GLOBAL VARIABLES
**----------------------------------------------------------------------------*/
@@ -118,19 +118,13 @@
static u32 lineout_gpio;
static int gpio_dock_in = 0;
-static ssize_t dock_status_show(struct device *dev,struct device_attribute *attr, char *buf)
-{
- int dock_status = 0;
-
- if(gpio_get_value(gpio_dock_in))
- dock_status = 0;
- else
- dock_status = 1;
+static struct switch_dev dock_switch = {
+ .name = "dock",
+};
- return sprintf(buf, "%d\n", dock_status);
-}
-
-DEVICE_ATTR(dock_status, S_IRUGO, dock_status_show, NULL);
+static struct switch_dev audio_switch = {
+ .name = "usb_audio",
+};
static ssize_t headset_name_show(struct switch_dev *sdev, char *buf)
{
@@ -375,9 +369,24 @@
}
+static void set_dock_switches(void)
+{
+ bool docked = !gpio_get_value(gpio_dock_in);
+
+ /* LE desk dock == 3, undocked == 0. */
+ switch_set_state(&dock_switch, docked ? 3 : 0);
+
+ /*
+ * Analog audio == 1, no audio == 0.
+ * Note that because we cannot detect the presence of a 3.5mm jack
+ * in the dock's audio socket, when docked, audio is always on.
+ */
+ switch_set_state(&audio_switch, docked ? 1 : 0);
+}
+
static void dock_work_queue(struct work_struct *work)
{
- audio_dock_switch();
+ set_dock_switches();
}
/**********************************************************
@@ -435,42 +444,8 @@
return ret;
}
-static void audio_dock_switch(void)
-{
-
- struct snd_soc_dapm_context *dapm;
-
- dapm = &rt5640_audio_codec->dapm;
-
- if(!gpio_get_value(gpio_dock_in)){
- /* Change route to dock if current output device is spk */
- if(snd_soc_dapm_get_pin_status(dapm, "Int Spk")){
- snd_soc_dapm_disable_pin(dapm, "Int Spk");
- snd_soc_dapm_enable_pin(dapm, "AUX");
- snd_soc_update_bits(rt5640_audio_codec,
- RT5640_DIG_INF_DATA, RT5640_IF1_DAC_SEL_MASK,
- 0x0000);
- snd_soc_dapm_sync(dapm);
- }else{
- snd_soc_dapm_disable_pin(dapm, "AUX");
- snd_soc_dapm_sync(dapm);
- }
- }else{
- if(!snd_soc_dapm_get_pin_status(dapm, "Headphone Jack")){
- snd_soc_dapm_enable_pin(dapm, "Int Spk");
- snd_soc_update_bits(rt5640_audio_codec,
- RT5640_DIG_INF_DATA, RT5640_IF1_DAC_SEL_MASK,
- 0x4000);
- }
- snd_soc_dapm_disable_pin(dapm, "AUX");
- snd_soc_dapm_sync(dapm);
- }
-
-}
-
static irqreturn_t dockin_irq_handler(int irq, void *dev_id)
{
- printk("%s\n", __func__);
schedule_work(&dock_work);
return IRQ_HANDLED;
@@ -598,13 +573,10 @@
if (ret < 0)
goto err_switch_dev_register;
-
- ret = device_create_file(rt5640_audio_codec->dev, &dev_attr_dock_status);
- if (ret != 0) {
- dev_err(rt5640_audio_codec->dev,
- "Failed to create dock status: %d\n", ret);
- goto err_switch_dev_register;
- }
+ WARN_ON(switch_dev_register(&dock_switch));
+ WARN_ON(switch_dev_register(&audio_switch));
+ /* Make sure dock switches are correct at boot */
+ set_dock_switches();
g_detection_work_queue = create_workqueue("detection");
@@ -647,6 +619,8 @@
free_irq(hs_data->irq, 0);
destroy_workqueue(g_detection_work_queue);
switch_dev_unregister(&hs_data->sdev);
+ switch_dev_unregister(&dock_switch);
+ switch_dev_unregister(&audio_switch);
}
module_init(headset_init);