intel_sst: Line out support
authorDharageswari R <dharageswari.r@intel.com>
Tue, 3 May 2011 16:32:38 +0000 (17:32 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 May 2011 19:55:54 +0000 (12:55 -0700)
This patch adds the support for lineout. The
lineout input can be selected as any input channel
by using a new alsa mixer kcontrol.

Signed-off-by: Dharageswari R <dharageswari.r@intel.com>
Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
12 files changed:
drivers/staging/intel_sst/intel_sst.h
drivers/staging/intel_sst/intel_sst_common.h
drivers/staging/intel_sst/intel_sst_drv_interface.c
drivers/staging/intel_sst/intel_sst_stream.c
drivers/staging/intel_sst/intelmid.c
drivers/staging/intel_sst/intelmid.h
drivers/staging/intel_sst/intelmid_ctrl.c
drivers/staging/intel_sst/intelmid_msic_control.c
drivers/staging/intel_sst/intelmid_snd_control.h
drivers/staging/intel_sst/intelmid_v0_control.c
drivers/staging/intel_sst/intelmid_v1_control.c
drivers/staging/intel_sst/intelmid_v2_control.c

index bf0f9e2130bfccdcc6cbda50d15a5017a434fce0..ea6cd97076c6dcb35a61ba8d7017c2b2df98a341 100644 (file)
@@ -82,12 +82,14 @@ struct snd_pmic_ops {
        int num_channel;
        int input_dev_id;
        int mute_status;
-       int pb_on;
+       int pb_on, pbhs_on;
        int cap_on;
        int output_dev_id;
+       int lineout_dev_id, line_out_names_cnt;
+       int prev_lineout_dev_id;
        int (*set_input_dev) (u8 value);
        int (*set_output_dev) (u8 value);
-
+       int (*set_lineout_dev) (u8 value);
        int (*set_mute) (int dev_id, u8 value);
        int (*get_mute) (int dev_id, u8 *value);
 
index 0f488384f9d0b3fb8b40884c0ab850866e5ea47c..9aff1a397318555b7f75798bf9e6b76af81f7b00 100644 (file)
@@ -28,8 +28,8 @@
  *  Common private declarations for SST
  */
 
-#define SST_DRIVER_VERSION "1.2.11"
-#define SST_VERSION_NUM 0x1211
+#define SST_DRIVER_VERSION "1.2.14"
+#define SST_VERSION_NUM 0x1214
 
 /* driver names */
 #define SST_DRV_NAME "intel_sst_driver"
index a47e3823e607177f4320cf1a49b0f47774bea824..1e8c05605aeca583decbe6a259e59f210aeca2cb 100644 (file)
@@ -110,9 +110,14 @@ void free_stream_context(unsigned int str_id)
                if (stream->ops == STREAM_OPS_PLAYBACK ||
                                stream->ops == STREAM_OPS_PLAYBACK_DRM) {
                        sst_drv_ctx->pb_streams--;
-                       if (sst_drv_ctx->pb_streams == 0)
+                       if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
                                sst_drv_ctx->scard_ops->power_down_pmic_pb(
                                                stream->device);
+                       else {
+                               if (sst_drv_ctx->pb_streams == 0)
+                                       sst_drv_ctx->scard_ops->
+                                       power_down_pmic_pb(stream->device);
+                       }
                } else if (stream->ops == STREAM_OPS_CAPTURE) {
                        sst_drv_ctx->cp_streams--;
                        if (sst_drv_ctx->cp_streams == 0)
index 55a561ccc4abbba3d9f4506ae879bbaf0b51dea3..dd9c5300471f096f170b5f20405984986fa4b0ec 100644 (file)
@@ -73,6 +73,8 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
                        *pcm_slot = 0x07;
                else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4)
                        *pcm_slot = 0x0F;
+               else if (device == SND_SST_DEVICE_CAPTURE && num_chan > 4)
+                       *pcm_slot = 0x1F;
                else {
                        pr_debug("No condition satisfied.. ret err\n");
                        return -EINVAL;
index 0925a88ed40e582d445f6b0f98bd8f0df0ac3573..ee070e3eecb56d398303688de3af59ff15c8883d 100644 (file)
@@ -187,7 +187,7 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream)
                return ret_val;
        }
 
-        ret_val = snd_intelmad_alloc_stream(substream);
+       ret_val = snd_intelmad_alloc_stream(substream);
        if (ret_val < 0)
                return ret_val;
        stream->dbg_cum_bytes = 0;
@@ -797,6 +797,7 @@ static int __devinit snd_intelmad_sst_register(
                intelmaddata->sstdrv_ops->scard_ops->input_dev_id = DMIC;
                intelmaddata->sstdrv_ops->scard_ops->output_dev_id =
                                                        STEREO_HEADPHONE;
+               intelmaddata->sstdrv_ops->scard_ops->lineout_dev_id = NONE;
        }
 
        /* registering with SST driver to get access to SST APIs to use */
index e77da87e1df0f52e08ec8f880b072c455f870196..4ed4a94047f0840a82df771ac88c7b128c3f2aa6 100644 (file)
 #define STEREO_CNTL            2
 #define MIN_CHANNEL            1
 #define MAX_CHANNEL_AMIC       2
-#define MAX_CHANNEL_DMIC       4
+#define MAX_CHANNEL_DMIC       5
 #define FIFO_SIZE              0 /* fifo not being used */
 #define INTEL_MAD              "Intel MAD"
 #define MAX_CTRL_MRST          7
-#define MAX_CTRL_MFLD          2
+#define MAX_CTRL_MFLD          3
 #define MAX_CTRL               7
 #define MAX_VENDORS            4
 /* TODO +6 db */
@@ -116,6 +116,7 @@ struct snd_intelmad {
        void __iomem *int_base;
        int output_sel;
        int input_sel;
+       int lineout_sel;
        int master_mute;
        struct mad_jack jack[4];
        int playback_cnt;
@@ -163,6 +164,9 @@ enum _widget_ctrl {
        CAPTURE_MUTE,
        MASTER_MUTE
 };
+enum _widget_ctrl_mfld {
+       LINEOUT_SEL_MFLD = 3,
+};
 
 void period_elapsed(void *mad_substream);
 int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream);
index 69af0704ce946335d6f4a46ed35c786ee6000c00..3036928efc6fed5c6cd904779bb65cb6f78be63a 100644 (file)
@@ -40,6 +40,11 @@ static char *out_names_mrst[] = {"Headphones",
 static char *in_names_mrst[] = {"AMIC",
                                "DMIC",
                                "HS_MIC"};
+static char *line_out_names_mfld[] = {"Headset",
+                               "IHF    ",
+                               "Vibra1 ",
+                               "Vibra2 ",
+                               "NONE   "};
 static char *out_names_mfld[] = {"Headset ",
                                "EarPiece  "};
 static char *in_names_mfld[] = {"AMIC",
@@ -179,13 +184,27 @@ static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol,
 static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_info *uinfo)
 {
+       struct snd_pmic_ops *scard_ops;
+       struct snd_intelmad *intelmaddata;
+
        WARN_ON(!kcontrol);
        WARN_ON(!uinfo);
+
+       intelmaddata = kcontrol->private_data;
+
+       WARN_ON(!intelmaddata->sstdrv_ops);
+
+       scard_ops = intelmaddata->sstdrv_ops->scard_ops;
        /* setup device select as drop down controls with different values */
        if (kcontrol->id.numid == OUTPUT_SEL)
                uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld);
-       else
+       else if (kcontrol->id.numid == INPUT_SEL)
                uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld);
+       else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) {
+               uinfo->value.enumerated.items = ARRAY_SIZE(line_out_names_mfld);
+               scard_ops->line_out_names_cnt = uinfo->value.enumerated.items;
+       } else
+               return -EINVAL;
        uinfo->count = MONO_CNTL;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 
@@ -195,10 +214,16 @@ static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
                strncpy(uinfo->value.enumerated.name,
                        out_names_mfld[uinfo->value.enumerated.item],
                        sizeof(uinfo->value.enumerated.name)-1);
-       else
+       else if (kcontrol->id.numid == INPUT_SEL)
                strncpy(uinfo->value.enumerated.name,
                        in_names_mfld[uinfo->value.enumerated.item],
                        sizeof(uinfo->value.enumerated.name)-1);
+       else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
+               strncpy(uinfo->value.enumerated.name,
+                       line_out_names_mfld[uinfo->value.enumerated.item],
+                       sizeof(uinfo->value.enumerated.name)-1);
+       else
+               return -EINVAL;
        return 0;
 }
 
@@ -472,6 +497,9 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
                else if (kcontrol->id.numid == INPUT_SEL)
                        uval->value.enumerated.item[0] =
                                        scard_ops->input_dev_id;
+               else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
+                       uval->value.enumerated.item[0] =
+                                       scard_ops->lineout_dev_id;
                else
                        return -EINVAL;
        } else
@@ -534,6 +562,11 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
                                uval->value.enumerated.item[0]);
                intelmaddata->input_sel = uval->value.enumerated.item[0];
                break;
+       case LINEOUT_SEL_MFLD:
+               ret_val = scard_ops->set_lineout_dev(
+                                       uval->value.enumerated.item[0]);
+               intelmaddata->lineout_sel = uval->value.enumerated.item[0];
+               break;
        default:
                return -EINVAL;
        }
@@ -627,5 +660,14 @@ snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
        .put            =       snd_intelmad_device_set,
        .private_value  =       0,
 },
+{
+       .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           =       "Line out",
+       .access         =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info           =       snd_intelmad_device_info_mfld,
+       .get            =       snd_intelmad_device_get,
+       .put            =       snd_intelmad_device_set,
+       .private_value  =       0,
+},
 };
 
index bbe9ab20f9673fe12165d41d943cc6b3cc22e175..10073c5b5f644f7ed05cd5287c2ba753e378da76 100644 (file)
@@ -54,11 +54,8 @@ static int msic_init_card(void)
                /*TI vibra w/a settings*/
                {0x384, 0x80, 0},
                {0x385, 0x80, 0},
-               /*vibra settings*/
                {0x267, 0x00, 0},
-               {0x26A, 0x10, 0},
                {0x261, 0x00, 0},
-               {0x264, 0x10, 0},
                /* pcm port setting */
                {0x278, 0x00, 0},
                {0x27B, 0x01, 0},
@@ -80,14 +77,221 @@ static int msic_init_card(void)
                {0x1e, 0x00, 0x00},
        };
        snd_msic_ops.card_status = SND_CARD_INIT_DONE;
-       sst_sc_reg_access(sc_access, PMIC_WRITE, 30);
+       sst_sc_reg_access(sc_access, PMIC_WRITE, 28);
        snd_msic_ops.pb_on = 0;
+       snd_msic_ops.pbhs_on = 0;
        snd_msic_ops.cap_on = 0;
        snd_msic_ops.input_dev_id = DMIC; /*def dev*/
        snd_msic_ops.output_dev_id = STEREO_HEADPHONE;
        pr_debug("msic init complete!!\n");
        return 0;
 }
+static int msic_line_out_restore(u8 value)
+{
+       struct sc_reg_access hs_drv_en[] = {
+               {0x25d, 0x03, 0x03},
+       };
+       struct sc_reg_access ep_drv_en[] = {
+               {0x25d, 0x40, 0x40},
+       };
+       struct sc_reg_access ihf_drv_en[] = {
+               {0x25d, 0x0c, 0x0c},
+       };
+       struct sc_reg_access vib1_drv_en[] = {
+               {0x25d, 0x10, 0x10},
+       };
+       struct sc_reg_access vib2_drv_en[] = {
+               {0x25d, 0x20, 0x20},
+       };
+       int retval = 0;
+
+       pr_debug("msic_lineout_restore_lineout_dev:%d\n", value);
+
+       switch (value) {
+       case HEADSET:
+               pr_debug("Selecting Lineout-HEADSET-restore\n");
+               if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE)
+                       retval = sst_sc_reg_access(hs_drv_en,
+                                                       PMIC_READ_MODIFY, 1);
+               else
+                       retval = sst_sc_reg_access(ep_drv_en,
+                                                       PMIC_READ_MODIFY, 1);
+               break;
+       case IHF:
+               pr_debug("Selecting Lineout-IHF-restore\n");
+               retval = sst_sc_reg_access(ihf_drv_en, PMIC_READ_MODIFY, 1);
+               break;
+       case VIBRA1:
+               pr_debug("Selecting Lineout-Vibra1-restore\n");
+               retval = sst_sc_reg_access(vib1_drv_en, PMIC_READ_MODIFY, 1);
+               break;
+       case VIBRA2:
+               pr_debug("Selecting Lineout-VIBRA2-restore\n");
+               retval = sst_sc_reg_access(vib2_drv_en, PMIC_READ_MODIFY, 1);
+               break;
+       case NONE:
+               pr_debug("Selecting Lineout-NONE-restore\n");
+               break;
+       default:
+               return -EINVAL;
+       }
+       return retval;
+}
+static int msic_get_lineout_prvstate(void)
+{
+       struct sc_reg_access hs_ihf_drv[2] = {
+               {0x257, 0x0, 0x0},
+               {0x25d, 0x0, 0x0},
+       };
+       struct sc_reg_access vib1drv[2] = {
+               {0x264, 0x0, 0x0},
+               {0x25D, 0x0, 0x0},
+       };
+       struct sc_reg_access vib2drv[2] = {
+               {0x26A, 0x0, 0x0},
+               {0x25D, 0x0, 0x0},
+       };
+       int retval = 0, drv_en, dac_en, dev_id, mask;
+       for (dev_id = 0; dev_id < snd_msic_ops.line_out_names_cnt; dev_id++) {
+               switch (dev_id) {
+               case HEADSET:
+                       pr_debug("msic_get_lineout_prvs_state: HEADSET\n");
+                       sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
+
+                       mask = (MASK0|MASK1);
+                       dac_en = (hs_ihf_drv[0].value) & mask;
+
+                       mask = ((MASK0|MASK1)|MASK6);
+                       drv_en = (hs_ihf_drv[1].value) & mask;
+
+                       if (dac_en && (!drv_en)) {
+                               snd_msic_ops.prev_lineout_dev_id = HEADSET;
+                               return retval;
+                       }
+                       break;
+               case IHF:
+                       pr_debug("msic_get_lineout_prvstate: IHF\n");
+                       sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
+
+                       mask = (MASK2 | MASK3);
+                       dac_en = (hs_ihf_drv[0].value) & mask;
+
+                       mask = (MASK2 | MASK3);
+                       drv_en = (hs_ihf_drv[1].value) & mask;
+
+                       if (dac_en && (!drv_en)) {
+                               snd_msic_ops.prev_lineout_dev_id = IHF;
+                               return retval;
+                       }
+                       break;
+               case VIBRA1:
+                       pr_debug("msic_get_lineout_prvstate: vibra1\n");
+                       sst_sc_reg_access(vib1drv, PMIC_READ, 2);
+
+                       mask = MASK1;
+                       dac_en = (vib1drv[0].value) & mask;
+
+                       mask = MASK4;
+                       drv_en = (vib1drv[1].value) & mask;
+
+                       if (dac_en && (!drv_en)) {
+                               snd_msic_ops.prev_lineout_dev_id = VIBRA1;
+                               return retval;
+                       }
+                       break;
+               case VIBRA2:
+                       pr_debug("msic_get_lineout_prvstate: vibra2\n");
+                       sst_sc_reg_access(vib2drv, PMIC_READ, 2);
+
+                       mask = MASK1;
+                       dac_en = (vib2drv[0].value) & mask;
+
+                       mask = MASK5;
+                       drv_en = ((vib2drv[1].value) & mask);
+
+                       if (dac_en && (!drv_en)) {
+                               snd_msic_ops.prev_lineout_dev_id = VIBRA2;
+                               return retval;
+                       }
+                       break;
+               case NONE:
+                       pr_debug("msic_get_lineout_prvstate: NONE\n");
+                       snd_msic_ops.prev_lineout_dev_id = NONE;
+                       return retval;
+               default:
+                       pr_debug("Invalid device id\n");
+                       snd_msic_ops.prev_lineout_dev_id = NONE;
+                       return -EINVAL;
+               }
+       }
+       return retval;
+}
+static int msic_set_selected_lineout_dev(u8 value)
+{
+       struct sc_reg_access lout_hs[] = {
+               {0x25e, 0x33, 0xFF},
+               {0x25d, 0x0, 0x43},
+       };
+       struct sc_reg_access lout_ihf[] = {
+               {0x25e, 0x55, 0xff},
+               {0x25d, 0x0, 0x0c},
+       };
+       struct sc_reg_access lout_vibra1[] = {
+
+               {0x25e, 0x61, 0xff},
+               {0x25d, 0x0, 0x10},
+       };
+       struct sc_reg_access lout_vibra2[] = {
+
+               {0x25e, 0x16, 0xff},
+               {0x25d, 0x0, 0x20},
+       };
+       struct sc_reg_access lout_def[] = {
+               {0x25e, 0x66, 0x0},
+       };
+       int retval = 0;
+
+       pr_debug("msic_set_selected_lineout_dev:%d\n", value);
+       msic_get_lineout_prvstate();
+       msic_line_out_restore(snd_msic_ops.prev_lineout_dev_id);
+       snd_msic_ops.lineout_dev_id = value;
+
+       switch (value) {
+       case HEADSET:
+               pr_debug("Selecting Lineout-HEADSET\n");
+               if (snd_msic_ops.pb_on)
+                       retval = sst_sc_reg_access(lout_hs,
+                                       PMIC_READ_MODIFY, 2);
+               break;
+       case IHF:
+               pr_debug("Selecting Lineout-IHF\n");
+               if (snd_msic_ops.pb_on)
+                       retval = sst_sc_reg_access(lout_ihf,
+                                                       PMIC_READ_MODIFY, 2);
+               break;
+       case VIBRA1:
+               pr_debug("Selecting Lineout-Vibra1\n");
+               if (snd_msic_ops.pb_on)
+                       retval = sst_sc_reg_access(lout_vibra1,
+                                                       PMIC_READ_MODIFY, 2);
+               break;
+       case VIBRA2:
+               pr_debug("Selecting Lineout-VIBRA2\n");
+               if (snd_msic_ops.pb_on)
+                       retval = sst_sc_reg_access(lout_vibra2,
+                                                       PMIC_READ_MODIFY, 2);
+               break;
+       case NONE:
+               pr_debug("Selecting Lineout-NONE\n");
+                       retval = sst_sc_reg_access(lout_def,
+                                                       PMIC_WRITE, 1);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return retval;
+}
+
 
 static int msic_power_up_pb(unsigned int device)
 {
@@ -161,12 +365,12 @@ static int msic_power_up_pb(unsigned int device)
        struct sc_reg_access vib1_en[] = {
                /* enable driver, ADC */
                {0x25D, 0x10, 0x10},
-               {0x264, 0x02, 0x02},
+               {0x264, 0x02, 0x82},
        };
        struct sc_reg_access vib2_en[] = {
                /* enable driver, ADC */
                {0x25D, 0x20, 0x20},
-               {0x26A, 0x02, 0x02},
+               {0x26A, 0x02, 0x82},
        };
        struct sc_reg_access pcm2_en[] = {
                /* enable pcm 2 */
@@ -187,6 +391,8 @@ static int msic_power_up_pb(unsigned int device)
        msleep(1);
        switch (device) {
        case SND_SST_DEVICE_HEADSET:
+               snd_msic_ops.pb_on = 1;
+               snd_msic_ops.pbhs_on = 1;
                if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) {
                        sst_sc_reg_access(vhs, PMIC_WRITE, 2);
                        sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 2);
@@ -197,22 +403,31 @@ static int msic_power_up_pb(unsigned int device)
                        sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
                        sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3);
                }
-               snd_msic_ops.pb_on = 1;
+               if (snd_msic_ops.lineout_dev_id == HEADSET)
+                       msic_set_selected_lineout_dev(HEADSET);
                break;
-
        case SND_SST_DEVICE_IHF:
+               snd_msic_ops.pb_on = 1;
                sst_sc_reg_access(vihf, PMIC_WRITE, 1);
                sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3);
                sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1);
                sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2);
+               if (snd_msic_ops.lineout_dev_id == IHF)
+                       msic_set_selected_lineout_dev(IHF);
                break;
 
        case SND_SST_DEVICE_VIBRA:
+               snd_msic_ops.pb_on = 1;
                sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2);
+               if (snd_msic_ops.lineout_dev_id == VIBRA1)
+                       msic_set_selected_lineout_dev(VIBRA1);
                break;
 
        case SND_SST_DEVICE_HAPTIC:
+               snd_msic_ops.pb_on = 1;
                sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2);
+               if (snd_msic_ops.lineout_dev_id == VIBRA2)
+                       msic_set_selected_lineout_dev(VIBRA2);
                break;
 
        default:
@@ -310,6 +525,7 @@ static int msic_power_down(void)
        };
 
        pr_debug("powering dn msic\n");
+       snd_msic_ops.pbhs_on = 0;
        snd_msic_ops.pb_on = 0;
        snd_msic_ops.cap_on = 0;
        sst_sc_reg_access(power_dn, PMIC_WRITE, 3);
@@ -348,15 +564,22 @@ static int msic_power_down_pb(unsigned int device)
        struct sc_reg_access vib2_off[] = {
                {0x26A, 0x00, 0x82},
        };
+       struct sc_reg_access lout_off[] = {
+               {0x25e, 0x66, 0x00},
+       };
+
+
 
        pr_debug("powering dn pb for device %d\n", device);
        switch (device) {
        case SND_SST_DEVICE_HEADSET:
-               snd_msic_ops.pb_on = 0;
+               snd_msic_ops.pbhs_on = 0;
                sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3);
                drv_enable[0].mask = 0x43;
                sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
                sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 2);
+               if (snd_msic_ops.lineout_dev_id == HEADSET)
+                       sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
                break;
 
        case SND_SST_DEVICE_IHF:
@@ -364,18 +587,24 @@ static int msic_power_down_pb(unsigned int device)
                drv_enable[0].mask = 0x0C;
                sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
                sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2);
+               if (snd_msic_ops.lineout_dev_id == IHF)
+                       sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
                break;
 
        case SND_SST_DEVICE_VIBRA:
-               sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 2);
+               sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 1);
                drv_enable[0].mask = 0x10;
                sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+               if (snd_msic_ops.lineout_dev_id == VIBRA1)
+                       sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
                break;
 
        case SND_SST_DEVICE_HAPTIC:
-               sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 2);
+               sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 1);
                drv_enable[0].mask = 0x20;
                sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+               if (snd_msic_ops.lineout_dev_id == VIBRA2)
+                       sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
                break;
        }
        return 0;
@@ -414,7 +643,7 @@ static int msic_set_selected_output_dev(u8 value)
 
        pr_debug("msic set selected output:%d\n", value);
        snd_msic_ops.output_dev_id = value;
-       if (snd_msic_ops.pb_on)
+       if (snd_msic_ops.pbhs_on)
                msic_power_up_pb(SND_SST_DEVICE_HEADSET);
        return retval;
 }
@@ -494,6 +723,7 @@ static int msic_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_msic_ops = {
        .set_input_dev  =       msic_set_selected_input_dev,
        .set_output_dev =       msic_set_selected_output_dev,
+       .set_lineout_dev =      msic_set_selected_lineout_dev,
        .set_mute       =       msic_set_mute,
        .get_mute       =       msic_get_mute,
        .set_vol        =       msic_set_vol,
index a4565f33a91b225ec40323d6d700de7e32b9babf..c7e9f1619f474b767a827144737911efcf4fab11 100644 (file)
@@ -80,6 +80,13 @@ enum SND_INPUT_DEVICE {
        HS_MIC,
        IN_UNDEFINED
 };
+enum SND_LINE_OUT_DEVICE {
+       HEADSET,
+       IHF,
+       VIBRA1,
+       VIBRA2,
+       NONE,
+};
 
 enum SND_OUTPUT_DEVICE {
        STEREO_HEADPHONE,
index 6cf5901dbb6c9bf7e6d677d4134a7c0e60eb2f8f..964c412d83952a81dea6670e60f81f0713b9cd0e 100644 (file)
@@ -494,7 +494,10 @@ static int fs_set_selected_output_dev(u8 value)
 
        }
 }
-
+static int fs_set_selected_lineout_dev(u8 value)
+{
+       return 0;
+}
 static int fs_set_mute(int dev_id, u8 value)
 {
        struct sc_reg_access sc_access[6] = {{0,},};
@@ -756,6 +759,7 @@ static int fs_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_pmic_ops_fs = {
        .set_input_dev = fs_set_selected_input_dev,
        .set_output_dev = fs_set_selected_output_dev,
+       .set_lineout_dev = fs_set_selected_lineout_dev,
        .set_mute = fs_set_mute,
        .get_mute = fs_get_mute,
        .set_vol = fs_set_vol,
index 770cb93c4c61ec6599780b705ed85012cb3bc1bd..3392f0857274d70b0ef6b1ccb8bf6a571ea207cb 100644 (file)
@@ -584,6 +584,10 @@ static int mx_set_selected_input_dev(u8 dev_id)
        }
        return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
 }
+static int mx_set_selected_lineout_dev(u8 dev_id)
+{
+       return 0;
+}
 
 static int mx_set_mute(int dev_id, u8 value)
 {
@@ -834,6 +838,7 @@ static int mx_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_pmic_ops_mx = {
        .set_input_dev = mx_set_selected_input_dev,
        .set_output_dev = mx_set_selected_output_dev,
+       .set_lineout_dev = mx_set_selected_lineout_dev,
        .set_mute = mx_set_mute,
        .get_mute = mx_get_mute,
        .set_vol = mx_set_vol,
index 3ea304a9a943dc764a926fc97cba842d7b533cf9..499fe640cbc9c4ee1d054c4805cf961ae792ae70 100644 (file)
@@ -884,7 +884,10 @@ static int nc_set_selected_input_dev(u8 value)
        }
        return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
 }
-
+static int nc_set_selected_lineout_dev(u8 dev_id)
+{
+       return 0;
+}
 static int nc_get_mute(int dev_id, u8 *value)
 {
        int retval = 0, mask = 0;
@@ -989,6 +992,7 @@ static int nc_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_pmic_ops_nc = {
        .set_input_dev  =       nc_set_selected_input_dev,
        .set_output_dev =       nc_set_selected_output_dev,
+       .set_lineout_dev =      nc_set_selected_lineout_dev,
        .set_mute       =       nc_set_mute,
        .get_mute       =       nc_get_mute,
        .set_vol        =       nc_set_vol,