asoc: tegra: add control to set headset state
Nikesh Oswal [Thu, 3 Jan 2013 15:22:37 +0000 (20:22 +0530)]
add alsa control to set headset switch state

Bug 1203124

Change-Id: Ieacf387e5a9b0d3215ad1e022fa5ab606618d44a
Signed-off-by: Nikesh Oswal <noswal@nvidia.com>
Reviewed-on: http://git-master/r/188337
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Scott Peterson <speterson@nvidia.com>

sound/soc/tegra/tegra_asoc_utils.c
sound/soc/tegra/tegra_asoc_utils.h

index df7d736..21f8a21 100644 (file)
@@ -36,6 +36,13 @@ int g_is_call_mode;
 
 #ifdef CONFIG_SWITCH
 static bool is_switch_registered;
+struct switch_dev *psdev;
+/* These values are copied from WiredAccessoryObserver */
+enum headset_state {
+       BIT_NO_HEADSET = 0,
+       BIT_HEADSET = (1 << 0),
+       BIT_HEADSET_NO_MIC = (1 << 1),
+};
 #endif
 
 bool tegra_is_voice_call_active(void)
@@ -195,6 +202,36 @@ struct snd_kcontrol_new tegra_avp_controls[] = {
                        0, tegra_get_dma_addr, tegra_set_dma_addr),
 };
 
+static int tegra_set_headset_plug_state(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+       int switch_state;
+
+       data->headset_plug_state = ucontrol->value.integer.value[0];
+       switch_state = data->headset_plug_state == 1 ? BIT_HEADSET
+               : BIT_NO_HEADSET;
+       if (psdev)
+               switch_set_state(psdev, switch_state);
+
+       return 1;
+}
+
+static int tegra_get_headset_plug_state(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = data->headset_plug_state;
+
+       return 0;
+}
+
+struct snd_kcontrol_new tegra_switch_controls =
+       SOC_SINGLE_EXT("Headset Plug State", 0, 0, 1, \
+       0, tegra_get_headset_plug_state, tegra_set_headset_plug_state);
+
+
 int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
                              int mclk)
 {
@@ -327,6 +364,13 @@ int tegra_asoc_utils_register_ctls(struct tegra_asoc_utils_data *data)
                }
        }
 
+       ret = snd_ctl_add(data->card->snd_card,
+                       snd_ctl_new1(&tegra_switch_controls, data));
+       if (ret < 0) {
+               dev_err(data->dev, "Can't add switch alsa control");
+               return ret;
+       }
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(tegra_asoc_utils_register_ctls);
@@ -487,8 +531,10 @@ int tegra_asoc_switch_register(struct switch_dev *sdev)
 
        ret = switch_dev_register(sdev);
 
-       if (ret >= 0)
+       if (ret >= 0) {
+               psdev = sdev;
                is_switch_registered = true;
+       }
 
        return ret;
 }
@@ -501,6 +547,7 @@ void tegra_asoc_switch_unregister(struct switch_dev *sdev)
 
        switch_dev_unregister(sdev);
        is_switch_registered = false;
+       psdev = NULL;
 }
 EXPORT_SYMBOL_GPL(tegra_asoc_switch_unregister);
 #endif
index dd4170d..cee3806 100644 (file)
@@ -48,6 +48,7 @@ struct tegra_asoc_utils_data {
        int lock_count;
        int avp_device_id;
        unsigned int avp_dma_addr;
+       int headset_plug_state;
 };
 
 int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,