Commit 5572a448 authored by Dharageswari R's avatar Dharageswari R Committed by Greg Kroah-Hartman

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: default avatarDharageswari R <dharageswari.r@intel.com>
Signed-off-by: default avatarRamesh Babu K V <ramesh.babu@intel.com>
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c3e25a24
...@@ -82,12 +82,14 @@ struct snd_pmic_ops { ...@@ -82,12 +82,14 @@ struct snd_pmic_ops {
int num_channel; int num_channel;
int input_dev_id; int input_dev_id;
int mute_status; int mute_status;
int pb_on; int pb_on, pbhs_on;
int cap_on; int cap_on;
int output_dev_id; 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_input_dev) (u8 value);
int (*set_output_dev) (u8 value); int (*set_output_dev) (u8 value);
int (*set_lineout_dev) (u8 value);
int (*set_mute) (int dev_id, u8 value); int (*set_mute) (int dev_id, u8 value);
int (*get_mute) (int dev_id, u8 *value); int (*get_mute) (int dev_id, u8 *value);
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
* Common private declarations for SST * Common private declarations for SST
*/ */
#define SST_DRIVER_VERSION "1.2.11" #define SST_DRIVER_VERSION "1.2.14"
#define SST_VERSION_NUM 0x1211 #define SST_VERSION_NUM 0x1214
/* driver names */ /* driver names */
#define SST_DRV_NAME "intel_sst_driver" #define SST_DRV_NAME "intel_sst_driver"
......
...@@ -110,9 +110,14 @@ void free_stream_context(unsigned int str_id) ...@@ -110,9 +110,14 @@ void free_stream_context(unsigned int str_id)
if (stream->ops == STREAM_OPS_PLAYBACK || if (stream->ops == STREAM_OPS_PLAYBACK ||
stream->ops == STREAM_OPS_PLAYBACK_DRM) { stream->ops == STREAM_OPS_PLAYBACK_DRM) {
sst_drv_ctx->pb_streams--; 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( sst_drv_ctx->scard_ops->power_down_pmic_pb(
stream->device); 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) { } else if (stream->ops == STREAM_OPS_CAPTURE) {
sst_drv_ctx->cp_streams--; sst_drv_ctx->cp_streams--;
if (sst_drv_ctx->cp_streams == 0) if (sst_drv_ctx->cp_streams == 0)
......
...@@ -73,6 +73,8 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot) ...@@ -73,6 +73,8 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
*pcm_slot = 0x07; *pcm_slot = 0x07;
else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4) else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4)
*pcm_slot = 0x0F; *pcm_slot = 0x0F;
else if (device == SND_SST_DEVICE_CAPTURE && num_chan > 4)
*pcm_slot = 0x1F;
else { else {
pr_debug("No condition satisfied.. ret err\n"); pr_debug("No condition satisfied.. ret err\n");
return -EINVAL; return -EINVAL;
......
...@@ -187,7 +187,7 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -187,7 +187,7 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream)
return ret_val; return ret_val;
} }
ret_val = snd_intelmad_alloc_stream(substream); ret_val = snd_intelmad_alloc_stream(substream);
if (ret_val < 0) if (ret_val < 0)
return ret_val; return ret_val;
stream->dbg_cum_bytes = 0; stream->dbg_cum_bytes = 0;
...@@ -797,6 +797,7 @@ static int __devinit snd_intelmad_sst_register( ...@@ -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->input_dev_id = DMIC;
intelmaddata->sstdrv_ops->scard_ops->output_dev_id = intelmaddata->sstdrv_ops->scard_ops->output_dev_id =
STEREO_HEADPHONE; STEREO_HEADPHONE;
intelmaddata->sstdrv_ops->scard_ops->lineout_dev_id = NONE;
} }
/* registering with SST driver to get access to SST APIs to use */ /* registering with SST driver to get access to SST APIs to use */
......
...@@ -53,11 +53,11 @@ ...@@ -53,11 +53,11 @@
#define STEREO_CNTL 2 #define STEREO_CNTL 2
#define MIN_CHANNEL 1 #define MIN_CHANNEL 1
#define MAX_CHANNEL_AMIC 2 #define MAX_CHANNEL_AMIC 2
#define MAX_CHANNEL_DMIC 4 #define MAX_CHANNEL_DMIC 5
#define FIFO_SIZE 0 /* fifo not being used */ #define FIFO_SIZE 0 /* fifo not being used */
#define INTEL_MAD "Intel MAD" #define INTEL_MAD "Intel MAD"
#define MAX_CTRL_MRST 7 #define MAX_CTRL_MRST 7
#define MAX_CTRL_MFLD 2 #define MAX_CTRL_MFLD 3
#define MAX_CTRL 7 #define MAX_CTRL 7
#define MAX_VENDORS 4 #define MAX_VENDORS 4
/* TODO +6 db */ /* TODO +6 db */
...@@ -116,6 +116,7 @@ struct snd_intelmad { ...@@ -116,6 +116,7 @@ struct snd_intelmad {
void __iomem *int_base; void __iomem *int_base;
int output_sel; int output_sel;
int input_sel; int input_sel;
int lineout_sel;
int master_mute; int master_mute;
struct mad_jack jack[4]; struct mad_jack jack[4];
int playback_cnt; int playback_cnt;
...@@ -163,6 +164,9 @@ enum _widget_ctrl { ...@@ -163,6 +164,9 @@ enum _widget_ctrl {
CAPTURE_MUTE, CAPTURE_MUTE,
MASTER_MUTE MASTER_MUTE
}; };
enum _widget_ctrl_mfld {
LINEOUT_SEL_MFLD = 3,
};
void period_elapsed(void *mad_substream); void period_elapsed(void *mad_substream);
int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream); int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream);
......
...@@ -40,6 +40,11 @@ static char *out_names_mrst[] = {"Headphones", ...@@ -40,6 +40,11 @@ static char *out_names_mrst[] = {"Headphones",
static char *in_names_mrst[] = {"AMIC", static char *in_names_mrst[] = {"AMIC",
"DMIC", "DMIC",
"HS_MIC"}; "HS_MIC"};
static char *line_out_names_mfld[] = {"Headset",
"IHF ",
"Vibra1 ",
"Vibra2 ",
"NONE "};
static char *out_names_mfld[] = {"Headset ", static char *out_names_mfld[] = {"Headset ",
"EarPiece "}; "EarPiece "};
static char *in_names_mfld[] = {"AMIC", static char *in_names_mfld[] = {"AMIC",
...@@ -179,13 +184,27 @@ static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol, ...@@ -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, static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
struct snd_pmic_ops *scard_ops;
struct snd_intelmad *intelmaddata;
WARN_ON(!kcontrol); WARN_ON(!kcontrol);
WARN_ON(!uinfo); 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 */ /* setup device select as drop down controls with different values */
if (kcontrol->id.numid == OUTPUT_SEL) if (kcontrol->id.numid == OUTPUT_SEL)
uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld); 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); 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->count = MONO_CNTL;
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
...@@ -195,10 +214,16 @@ static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol, ...@@ -195,10 +214,16 @@ static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
strncpy(uinfo->value.enumerated.name, strncpy(uinfo->value.enumerated.name,
out_names_mfld[uinfo->value.enumerated.item], out_names_mfld[uinfo->value.enumerated.item],
sizeof(uinfo->value.enumerated.name)-1); sizeof(uinfo->value.enumerated.name)-1);
else else if (kcontrol->id.numid == INPUT_SEL)
strncpy(uinfo->value.enumerated.name, strncpy(uinfo->value.enumerated.name,
in_names_mfld[uinfo->value.enumerated.item], in_names_mfld[uinfo->value.enumerated.item],
sizeof(uinfo->value.enumerated.name)-1); 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; return 0;
} }
...@@ -472,6 +497,9 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol, ...@@ -472,6 +497,9 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
else if (kcontrol->id.numid == INPUT_SEL) else if (kcontrol->id.numid == INPUT_SEL)
uval->value.enumerated.item[0] = uval->value.enumerated.item[0] =
scard_ops->input_dev_id; scard_ops->input_dev_id;
else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
uval->value.enumerated.item[0] =
scard_ops->lineout_dev_id;
else else
return -EINVAL; return -EINVAL;
} else } else
...@@ -534,6 +562,11 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol, ...@@ -534,6 +562,11 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
uval->value.enumerated.item[0]); uval->value.enumerated.item[0]);
intelmaddata->input_sel = uval->value.enumerated.item[0]; intelmaddata->input_sel = uval->value.enumerated.item[0];
break; 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: default:
return -EINVAL; return -EINVAL;
} }
...@@ -627,5 +660,14 @@ snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = { ...@@ -627,5 +660,14 @@ snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
.put = snd_intelmad_device_set, .put = snd_intelmad_device_set,
.private_value = 0, .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,
},
}; };
...@@ -80,6 +80,13 @@ enum SND_INPUT_DEVICE { ...@@ -80,6 +80,13 @@ enum SND_INPUT_DEVICE {
HS_MIC, HS_MIC,
IN_UNDEFINED IN_UNDEFINED
}; };
enum SND_LINE_OUT_DEVICE {
HEADSET,
IHF,
VIBRA1,
VIBRA2,
NONE,
};
enum SND_OUTPUT_DEVICE { enum SND_OUTPUT_DEVICE {
STEREO_HEADPHONE, STEREO_HEADPHONE,
......
...@@ -494,7 +494,10 @@ static int fs_set_selected_output_dev(u8 value) ...@@ -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) static int fs_set_mute(int dev_id, u8 value)
{ {
struct sc_reg_access sc_access[6] = {{0,},}; struct sc_reg_access sc_access[6] = {{0,},};
...@@ -756,6 +759,7 @@ static int fs_get_vol(int dev_id, int *value) ...@@ -756,6 +759,7 @@ static int fs_get_vol(int dev_id, int *value)
struct snd_pmic_ops snd_pmic_ops_fs = { struct snd_pmic_ops snd_pmic_ops_fs = {
.set_input_dev = fs_set_selected_input_dev, .set_input_dev = fs_set_selected_input_dev,
.set_output_dev = fs_set_selected_output_dev, .set_output_dev = fs_set_selected_output_dev,
.set_lineout_dev = fs_set_selected_lineout_dev,
.set_mute = fs_set_mute, .set_mute = fs_set_mute,
.get_mute = fs_get_mute, .get_mute = fs_get_mute,
.set_vol = fs_set_vol, .set_vol = fs_set_vol,
......
...@@ -584,6 +584,10 @@ static int mx_set_selected_input_dev(u8 dev_id) ...@@ -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); 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) static int mx_set_mute(int dev_id, u8 value)
{ {
...@@ -834,6 +838,7 @@ static int mx_get_vol(int dev_id, int *value) ...@@ -834,6 +838,7 @@ static int mx_get_vol(int dev_id, int *value)
struct snd_pmic_ops snd_pmic_ops_mx = { struct snd_pmic_ops snd_pmic_ops_mx = {
.set_input_dev = mx_set_selected_input_dev, .set_input_dev = mx_set_selected_input_dev,
.set_output_dev = mx_set_selected_output_dev, .set_output_dev = mx_set_selected_output_dev,
.set_lineout_dev = mx_set_selected_lineout_dev,
.set_mute = mx_set_mute, .set_mute = mx_set_mute,
.get_mute = mx_get_mute, .get_mute = mx_get_mute,
.set_vol = mx_set_vol, .set_vol = mx_set_vol,
......
...@@ -884,7 +884,10 @@ static int nc_set_selected_input_dev(u8 value) ...@@ -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); 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) static int nc_get_mute(int dev_id, u8 *value)
{ {
int retval = 0, mask = 0; int retval = 0, mask = 0;
...@@ -989,6 +992,7 @@ static int nc_get_vol(int dev_id, int *value) ...@@ -989,6 +992,7 @@ static int nc_get_vol(int dev_id, int *value)
struct snd_pmic_ops snd_pmic_ops_nc = { struct snd_pmic_ops snd_pmic_ops_nc = {
.set_input_dev = nc_set_selected_input_dev, .set_input_dev = nc_set_selected_input_dev,
.set_output_dev = nc_set_selected_output_dev, .set_output_dev = nc_set_selected_output_dev,
.set_lineout_dev = nc_set_selected_lineout_dev,
.set_mute = nc_set_mute, .set_mute = nc_set_mute,
.get_mute = nc_get_mute, .get_mute = nc_get_mute,
.set_vol = nc_set_vol, .set_vol = nc_set_vol,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment