mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 16:46:15 -04:00
intel_sst: Line out support
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>
This commit is contained in:
parent
c3e25a24b5
commit
5572a44829
12 changed files with 330 additions and 24 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@
|
|||
#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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue