>From f44814d59badc396f4f66e954375ee75da7aa9b1 Mon Sep 17 00:00:00 2001 From: R Dharageswari <[email protected]> Date: Tue, 7 Dec 2010 18:03:49 +0530 Subject: [PATCH 3/4] sst:vmic implementation in audio driver
Medfield supports virtual mic which pulseaudio can use for post-porcessing algorithms. This patch enable virtual mic feature in dsp fw and adds a new alsamixer kcontrol for specifying the vmic device. Signed-off-by: R Dharageswari <[email protected]> Signed-off-by: Ramesh Babu K V <[email protected]> --- include/sound/intel_sst.h | 1 + sound/pci/sst/intel_sst_common.h | 9 +++- sound/pci/sst/intel_sst_drv_interface.c | 13 ++++++- sound/pci/sst/intel_sst_fw_ipc.h | 1 + sound/pci/sst/intel_sst_ipc.c | 18 ++++++++ sound/pci/sst/intel_sst_pvt.c | 29 ++++++++++++++ sound/pci/sst/intel_sst_stream.c | 2 +- sound/pci/sst/intelmid.h | 14 ++++++- sound/pci/sst/intelmid_ctrl.c | 65 ++++++++++++++++++++++++++++++- 9 files changed, 143 insertions(+), 9 deletions(-) diff --git a/include/sound/intel_sst.h b/include/sound/intel_sst.h index a8f7941..d2d3653 100644 --- a/include/sound/intel_sst.h +++ b/include/sound/intel_sst.h @@ -59,6 +59,7 @@ enum sst_controls { SST_MAX_CONTROLS = 0x1008, SST_CONTROL_BASE = 0x1000, SST_ENABLE_RX_TIME_SLOT = 0x1009, + SST_VMIC_CHANNEL_SELECT = 0x1011, }; enum SND_CARDS { diff --git a/sound/pci/sst/intel_sst_common.h b/sound/pci/sst/intel_sst_common.h index 30fccab..4e02dd9 100644 --- a/sound/pci/sst/intel_sst_common.h +++ b/sound/pci/sst/intel_sst_common.h @@ -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" @@ -394,7 +394,8 @@ struct intel_sst_drv { struct stream_info streams[MAX_NUM_STREAMS]; struct stream_alloc_block alloc_block[MAX_ACTIVE_STREAM]; struct sst_block tgt_dev_blk, fw_info_blk, ppp_params_blk, - vol_info_blk, mute_info_blk, hs_info_blk; + vol_info_blk, mute_info_blk, hs_info_blk, + vmic_info_blk; struct mutex list_lock;/* mutex for IPC list locking */ spinlock_t list_spin_lock; /* mutex for IPC list locking */ struct snd_pmic_ops *scard_ops; @@ -413,6 +414,7 @@ struct intel_sst_drv { unsigned int lpe_stalled; /* LPE is stalled or not */ unsigned int pmic_port_instance; /*pmic port instance*/ int rx_time_slot_status; + int vmic_device; unsigned int lpaudio_start; /* 1 - LPA stream(MP3 pb) in progress*/ unsigned int audio_start; @@ -446,6 +448,7 @@ int sst_stalled(void); int sst_pause_stream(int id); int sst_resume_stream(int id); int sst_enable_rx_timeslot(int status); +int sst_enable_vmic(u32 device); int sst_drop_stream(int id); int sst_free_stream(int id); int sst_start_stream(int streamID); diff --git a/sound/pci/sst/intel_sst_drv_interface.c b/sound/pci/sst/intel_sst_drv_interface.c index 2a9c232..51b19e5 100644 --- a/sound/pci/sst/intel_sst_drv_interface.c +++ b/sound/pci/sst/intel_sst_drv_interface.c @@ -107,9 +107,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) @@ -458,6 +463,12 @@ int sst_device_control(int cmd, void *arg) sst_enable_rx_timeslot(status); break; } + case SST_VMIC_CHANNEL_SELECT: { + int device = *(int *)arg; + sst_drv_ctx->vmic_device = device; + sst_enable_vmic(device); + break; + } default: /* Illegal case */ pr_warn("sst: illegal req\n"); diff --git a/sound/pci/sst/intel_sst_fw_ipc.h b/sound/pci/sst/intel_sst_fw_ipc.h index ed237c3..11f9da9 100644 --- a/sound/pci/sst/intel_sst_fw_ipc.h +++ b/sound/pci/sst/intel_sst_fw_ipc.h @@ -91,6 +91,7 @@ #define IPC_IA_ENABLE_RX_TIME_SLOT 0x2E /* Enable Rx time slot 0 or 1 */ #define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */ +#define IPC_IA_VMIC_CHANL_SELECT 0x33 /* Debug msgs */ #define IPC_IA_DBG_MEM_READ 0x40 diff --git a/sound/pci/sst/intel_sst_ipc.c b/sound/pci/sst/intel_sst_ipc.c index 4ff6470..5da1df2 100644 --- a/sound/pci/sst/intel_sst_ipc.c +++ b/sound/pci/sst/intel_sst_ipc.c @@ -607,6 +607,24 @@ void sst_process_reply(struct work_struct *work) wake_up(&sst_drv_ctx->wait_queue); } break; + case IPC_IA_VMIC_CHANL_SELECT: + if (!msg->header.part.data) { + pr_debug("sst: VMIC_Device success\n"); + sst_drv_ctx->vmic_info_blk.ret_code = 0; + } else { + pr_err("sst: Msg %x reply error %x\n", + msg->header.part.msg_id, + msg->header.part.data); + sst_drv_ctx->vmic_info_blk.ret_code = + -msg->header.part.data; + } + if (sst_drv_ctx->vmic_info_blk.on == true) { + sst_drv_ctx->vmic_info_blk.on = false; + sst_drv_ctx->vmic_info_blk.condition = true; + wake_up(&sst_drv_ctx->wait_queue); + } + break; + case IPC_IA_PAUSE_STREAM: case IPC_IA_RESUME_STREAM: case IPC_IA_SET_STREAM_PARAMS: diff --git a/sound/pci/sst/intel_sst_pvt.c b/sound/pci/sst/intel_sst_pvt.c index 7f2f8d7..5105070 100644 --- a/sound/pci/sst/intel_sst_pvt.c +++ b/sound/pci/sst/intel_sst_pvt.c @@ -307,4 +307,33 @@ int sst_enable_rx_timeslot(int status) &sst_drv_ctx->hs_info_blk, SST_BLOCK_TIMEOUT); return retval; } +/** + * sst_enable_vmic - Send information of the vmic device selected to the firmware + * @status: rx timeslot to be enabled + * + * This function is called when VMIC info is to be sent to the firmware + */ +int sst_enable_vmic(u32 device) +{ + int retval = 0; + struct ipc_post *msg = NULL; + + if (sst_create_short_msg(&msg)) { + pr_err("sst: mem allocation failed\n"); + return -ENOMEM; + } + pr_debug("sst: ipc message sending: VMIC_DEVICE:%d\n", device); + sst_fill_header(&msg->header, IPC_IA_VMIC_CHANL_SELECT, 0, 0); + msg->header.part.data = device; + sst_drv_ctx->vmic_info_blk.condition = false; + sst_drv_ctx->vmic_info_blk.ret_code = 0; + sst_drv_ctx->vmic_info_blk.on = true; + spin_lock(&sst_drv_ctx->list_spin_lock); + list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); + spin_unlock(&sst_drv_ctx->list_spin_lock); + sst_post_message(&sst_drv_ctx->ipc_post_msg_wq); + retval = sst_wait_interruptible_timeout(sst_drv_ctx, + &sst_drv_ctx->vmic_info_blk, SST_BLOCK_TIMEOUT); + return retval; +} diff --git a/sound/pci/sst/intel_sst_stream.c b/sound/pci/sst/intel_sst_stream.c index ee5bd5d..2d247fb 100644 --- a/sound/pci/sst/intel_sst_stream.c +++ b/sound/pci/sst/intel_sst_stream.c @@ -68,7 +68,7 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot) *pcm_slot = 0x03; else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 3) *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; else { pr_debug("sst: No condition satisfied.. ret err\n"); diff --git a/sound/pci/sst/intelmid.h b/sound/pci/sst/intelmid.h index 0ce1031..9f1790a 100644 --- a/sound/pci/sst/intelmid.h +++ b/sound/pci/sst/intelmid.h @@ -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 4 #define MAX_CTRL 7 #define MAX_VENDORS 4 /* TODO +6 db */ @@ -163,6 +163,16 @@ enum _widget_ctrl { CAPTURE_MUTE, MASTER_MUTE }; +enum _widget_ctrl_mfld { + LINEOUT_SEL_MFLD = 3, + VMIC_SEL_MFLD, +}; +enum vmic_controls { + IHFL, + IHFR, + HSL, + HSR +}; void period_elapsed(void *mad_substream); int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream); diff --git a/sound/pci/sst/intelmid_ctrl.c b/sound/pci/sst/intelmid_ctrl.c index 105606e..e996474 100644 --- a/sound/pci/sst/intelmid_ctrl.c +++ b/sound/pci/sst/intelmid_ctrl.c @@ -36,6 +36,10 @@ static char *out_names_mrst[] = {"Headphones", static char *in_names_mrst[] = {"AMIC", "DMIC", "HS_MIC"}; +static char *vmic_names_mfld[] = {"IHF-left ", + "IHF-right ", + "Headset-Left ", + "Headset-Right"}; static char *out_names_mfld[] = {"Headset ", "EarPiece "}; static char *in_names_mfld[] = {"AMIC", @@ -175,13 +179,26 @@ 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 == VMIC_SEL_MFLD) + uinfo->value.enumerated.items = ARRAY_SIZE(vmic_names_mfld); + else + return -EINVAL; uinfo->count = MONO_CNTL; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -191,10 +208,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 == VMIC_SEL_MFLD) + strncpy(uinfo->value.enumerated.name, + vmic_names_mfld[uinfo->value.enumerated.item], + sizeof(uinfo->value.enumerated.name)-1); + else + return -EINVAL; return 0; } @@ -468,6 +491,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 == VMIC_SEL_MFLD) + uval->value.enumerated.item[0] = + kcontrol->private_value; else return -EINVAL; } else @@ -490,6 +516,7 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol, struct snd_intelmad *intelmaddata; struct snd_pmic_ops *scard_ops; int ret_val = 0, vendor, status; + u32 device; struct intel_sst_pcm_control *pcm_control; pr_debug("sst: snd_intelmad_device_set called\n"); @@ -530,6 +557,22 @@ 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 VMIC_SEL_MFLD: + pcm_control = intelmaddata->sstdrv_ops->pcm_control; + if (uval->value.enumerated.item[0] == IHFL) + device = 0x02; + else if (uval->value.enumerated.item[0] == IHFR) + device = 0x03; + else if (uval->value.enumerated.item[0] == HSL) + device = 0x00; + else if (uval->value.enumerated.item[0] == HSR) + device = 0x01; + else + pr_debug("sst: Invalid selection\n"); + pcm_control->device_control( + SST_VMIC_CHANNEL_SELECT, &device); + break; + default: return -EINVAL; } @@ -623,5 +666,23 @@ 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, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Virtual MIC", + .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, +}, }; -- 1.6.2.5
0003-sst-vmic-implementation-in-audio-driver.patch
Description: 0003-sst-vmic-implementation-in-audio-driver.patch
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
