audio:add support for mono speaker
authorRamesh Babu K V <ramesh.babu@intel.com>
Tue, 28 Feb 2012 15:36:40 +0000 (21:06 +0530)
committerbuildbot <buildbot@intel.com>
Thu, 15 Mar 2012 20:50:03 +0000 (13:50 -0700)
BZ: 23041

This patch adds support for mono speaker configuration
using runtime sst params.

If particular board has mono speaker, kernel config
SND_MFLD_MONO_SPEAKER_SUPPORT needs to selected to enable
the mono speaker support.

Change-Id: I3084772106669c129c426981c140b60afe658d41
Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
Reviewed-on: http://android.intel.com:8080/36911
Reviewed-by: Koul, Vinod <vinod.koul@intel.com>
Reviewed-by: Gupta, ArvindX K <arvindx.k.gupta@intel.com>
Reviewed-by: Hibare, PramodX <pramodx.hibare@intel.com>
Tested-by: Hibare, PramodX <pramodx.hibare@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
include/sound/intel_sst.h
include/sound/intel_sst_ioctl.h
sound/pci/sst/intel_sst.c
sound/pci/sst/intel_sst_common.h
sound/pci/sst/intel_sst_drv_interface.c
sound/pci/sst/intel_sst_ipc.c
sound/soc/mid-x86/Kconfig
sound/soc/mid-x86/mfld_machine.c
sound/soc/mid-x86/sst_platform.c

index 82be67f..3111289 100644 (file)
@@ -65,7 +65,8 @@ enum sst_controls {
        SST_VMIC_CHANNEL_SELECT =       0x1011,
        SST_SND_DEVICE_RESUME =         0x1012,
        SST_SND_DEVICE_RESUME_SYNC =    0x1013,
-       SST_MAX_CONTROLS =              0x1013,
+       SST_SET_RUNTIME_PARAMS =        0x1014,
+       SST_MAX_CONTROLS =              0x1014,
 };
 
 enum SND_CARDS {
@@ -118,6 +119,7 @@ int intelmad_get_mic_bias(void);
 struct intel_sst_pcm_control {
        int (*open) (struct snd_sst_params *str_param);
        int (*device_control) (int cmd, void *arg);
+       int (*set_generic_params) (enum sst_controls cmd, void *arg);
        int (*close) (unsigned int str_id);
 };
 struct intel_sst_card_ops {
index f7a7c6a..eaea339 100644 (file)
@@ -335,8 +335,9 @@ enum snd_sst_port_action {
 };
 
 enum stream_param_type {
-       SET_TIME_SLOT = 0,
-       OTHERS = 1, /*reserved for other params that need to be set in future*/
+       SST_SET_TIME_SLOT = 0,
+       SST_SET_CHANNEL_INFO = 1,
+       OTHERS = 2, /*reserved for other params that need to be set in future*/
 };
 
 /* Target selection per device structure */
@@ -412,6 +413,14 @@ struct snd_sst_tuning_params {
        __u8 rsvd;
        __u64 addr;
 } __attribute__ ((packed));
+
+struct snd_sst_runtime_params {
+       __u8 type;
+       __u8 str_id;
+       __u8 size;
+       __u8 rsvd;
+       void *addr;
+} __attribute__ ((packed));
 /*IOCTL defined here */
 /*SST MMF IOCTLS only */
 #define SNDRV_SST_STREAM_SET_PARAMS _IOWR('L', 0x00, \
index de97691..ce69d07 100644 (file)
@@ -447,6 +447,7 @@ static void __devexit intel_sst_remove(struct pci_dev *pci)
                kfree(sst_drv_ctx->mmap_mem);
        } else
                kfree(sst_drv_ctx->fw_cntx);
+       kfree(sst_drv_ctx->runtime_param.param.addr);
        flush_scheduled_work();
        destroy_workqueue(sst_drv_ctx->process_reply_wq);
        destroy_workqueue(sst_drv_ctx->process_msg_wq);
index 37f80c6..932961d 100644 (file)
@@ -344,7 +344,9 @@ struct sst_dma {
        struct pci_dev *dmac;
 };
 
-
+struct sst_runtime_param {
+       struct snd_sst_runtime_params param;
+};
 #define PCI_DMAC_MFLD_ID 0x0830
 #define PCI_DMAC_CLV_ID 0x08F0
 #define SST_MAX_DMA_LEN (4095*4)
@@ -454,6 +456,7 @@ struct intel_sst_drv {
        struct list_head        fw_list;
        struct sst_dma          dma;
        void                    *fw_in_mem;
+       struct sst_runtime_param runtime_param;
 };
 
 extern struct intel_sst_drv *sst_drv_ctx;
index 58befa1..4a6c06e 100644 (file)
@@ -575,10 +575,70 @@ static int sst_device_control(int cmd, void *arg)
        return retval;
 }
 
+/*
+ * sst_copy_runtime_param - copy runtime params from src to dst
+ *                              structure.
+ *
+ *@dst: destination runtime structure
+ *@src: source runtime structure
+ *
+ * This helper function is called to copy the runtime parameter
+ * structure.
+*/
+static int sst_copy_runtime_param(struct snd_sst_runtime_params *dst,
+                       struct snd_sst_runtime_params *src)
+{
+       dst->type = src->type;
+       dst->str_id = src->str_id;
+       dst->size = src->size;
+       if (dst->addr) {
+               pr_err("mem allocated in prev setting, use the same memory\n");
+               return -EINVAL;
+       }
+       dst->addr = kzalloc(dst->size, GFP_KERNEL);
+       if (!dst->addr)
+               return -ENOMEM;
+       memcpy(dst->addr, src->addr, dst->size);
+       return 0;
+}
+/*
+ * sst_set_generic_params - Set generic params
+ *
+ * @cmd: control cmd to be set
+ * @arg: command argument
+ *
+ * This function is called by MID sound card driver to configure
+ * SST runtime params.
+ */
+static int sst_set_generic_params(enum sst_controls cmd, void *arg)
+{
+       int ret_val = 0;
+       pr_debug("Enter:%s, cmd:%d\n", __func__, cmd);
+
+       if (NULL == arg)
+               return -EINVAL;
+
+       switch (cmd) {
+       case SST_SET_RUNTIME_PARAMS: {
+               struct snd_sst_runtime_params *src;
+               struct snd_sst_runtime_params *dst;
+
+               src = (struct snd_sst_runtime_params *)arg;
+               dst = &(sst_drv_ctx->runtime_param.param);
+               ret_val = sst_copy_runtime_param(dst, src);
+               break;
+               }
+       default:
+               pr_err("Invalid cmd request:%d\n", cmd);
+               ret_val = -EINVAL;
+       }
+       return ret_val;
+}
 
 static struct intel_sst_pcm_control pcm_ops = {
        .open = sst_open_pcm_stream,
        .device_control = sst_device_control,
+       .set_generic_params = sst_set_generic_params,
        .close = sst_close_pcm_stream,
 };
 
index d5c894b..893e74b 100644 (file)
 #include "intel_sst_fw_ipc.h"
 #include "intel_sst_common.h"
 
+/**
+ * sst_send_ipc_msg_nowait - send ipc msg for algorithm parameters
+ *             and returns immediately without waiting for reply
+ *
+ * @msg: post msg pointer
+ *
+ * This function is called to send ipc msg
+ */
+static int sst_send_ipc_msg_nowait(struct ipc_post **msg)
+{
+       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);
+       return  0;
+}
+
 /*
  * sst_send_sound_card_type - send sound card type
  *
@@ -56,6 +73,30 @@ static void sst_send_sound_card_type(void)
        sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
 }
 
+/*
+ * sst_send_runtime_param - send runtime param to SST
+ *
+ * this function sends the runtime parameter to sst dsp engine
+ */
+static int sst_send_runtime_param(struct snd_sst_runtime_params *params)
+{
+       struct ipc_post *msg = NULL;
+       int ret_val;
+
+       pr_debug("Enter:%s\n", __func__);
+       ret_val = sst_create_large_msg(&msg);
+       if (ret_val)
+               return ret_val;
+       sst_fill_header(&msg->header, IPC_IA_SET_RUNTIME_PARAMS, 1,
+                                                       params->str_id);
+       msg->header.part.data = sizeof(u32) + sizeof(*params) + params->size;
+       memcpy(msg->mailbox_data, &msg->header.full, sizeof(u32));
+       memcpy(msg->mailbox_data + sizeof(u32), params, sizeof(*params));
+       /* driver doesn't need to send address, so overwrite addr with data */
+       memcpy(msg->mailbox_data + sizeof(u32) + sizeof(*params) - sizeof(params->addr),
+                       params->addr, params->size);
+       return sst_send_ipc_msg_nowait(&msg);
+}
 /**
 * sst_post_message - Posts message to SST
 *
@@ -176,6 +217,9 @@ static int process_fw_init(struct sst_ipc_msg_wq *msg)
        }
        if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
                sst_send_sound_card_type();
+       /* If there any runtime parameter to set, send it */
+       if (sst_drv_ctx->runtime_param.param.addr)
+               sst_send_runtime_param(&(sst_drv_ctx->runtime_param.param));
        mutex_lock(&sst_drv_ctx->sst_lock);
        sst_drv_ctx->lpe_stalled = 0;
        mutex_unlock(&sst_drv_ctx->sst_lock);
index 7ed9c3d..75da0c5 100644 (file)
@@ -27,3 +27,12 @@ config SND_CLV_MACHINE
 
 config SND_SST_PLATFORM
        tristate
+
+config SND_MFLD_MONO_SPEAKER_SUPPORT
+       tristate "Mono Speaker support for Medfield based devices"
+       default N
+       help
+          This adds support for Mono speaker support on Intel(R) MID Medfield based devices.
+          Say Y if you have device with mono speaker. If you say N support for stereo speakers
+          will be enabled.
+          If unsure select "N".
index 39c55d3..d939a98 100644 (file)
@@ -345,6 +345,18 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
        return ret_val;
 }
 
+#ifdef CONFIG_SND_MFLD_MONO_SPEAKER_SUPPORT
+static int mfld_speaker_init(struct snd_soc_pcm_runtime *runtime)
+{
+       struct snd_soc_dai *cpu_dai = runtime->cpu_dai;
+       struct snd_soc_dapm_context *dapm = &runtime->codec->dapm;
+
+       snd_soc_dapm_disable_pin(dapm, "IHFOUTR");
+       snd_soc_dapm_sync(dapm);
+       return cpu_dai->driver->ops->set_tdm_slot(cpu_dai, 0, 0, 1, 0);
+}
+#endif
+
 static struct snd_soc_dai_link mfld_msic_dailink[] = {
        {
                .name = "Medfield Headset",
@@ -363,7 +375,11 @@ static struct snd_soc_dai_link mfld_msic_dailink[] = {
                .codec_dai_name = "SN95031 Speaker",
                .codec_name = "sn95031",
                .platform_name = "sst-platform",
+#ifdef CONFIG_SND_MFLD_MONO_SPEAKER_SUPPORT
+               .init = mfld_speaker_init,
+#else
                .init = NULL,
+#endif
                .ignore_suspend = 1,
        },
 /*
index 6739ee5..d57d9e8 100644 (file)
@@ -67,6 +67,38 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
        .fifo_size = SST_FIFO_SIZE,
 };
 
+static int sst_platform_ihf_set_tdm_slot(struct snd_soc_dai *dai,
+                       unsigned int tx_mask, unsigned int rx_mask,
+                       int slots, int slot_width) {
+       struct intel_sst_card_ops *sstdrv_ops;
+       struct snd_sst_runtime_params params_data;
+       int channels = slots;
+       int ret_val;
+
+       /* allocate memory for SST API set */
+       sstdrv_ops = kzalloc(sizeof(*sstdrv_ops), GFP_KERNEL);
+       if (!sstdrv_ops)
+               return -ENOMEM;
+       /* registering with SST driver to get access to SST APIs to use */
+       ret_val = register_sst_card(sstdrv_ops);
+       if (ret_val) {
+               pr_err("sst: sst card registration failed\n");
+               return -EIO;
+       }
+       params_data.type = SST_SET_CHANNEL_INFO;
+       params_data.str_id = SND_SST_DEVICE_IHF;
+       params_data.size = sizeof(channels);
+       params_data.addr = &channels;
+       ret_val = sstdrv_ops->pcm_control->set_generic_params(SST_SET_RUNTIME_PARAMS,
+                                                       (void *)&params_data);
+       kfree(sstdrv_ops);
+       return ret_val;
+}
+
+static const struct snd_soc_dai_ops sst_ihf_ops = {
+       .set_tdm_slot = sst_platform_ihf_set_tdm_slot,
+};
+
 /* MFLD - MSIC */
 static struct snd_soc_dai_driver sst_platform_dai[] = {
 {
@@ -105,6 +137,7 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
 #endif
                .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
+       .ops = &sst_ihf_ops,
 },
 {
        .name = "Vibra1-cpu-dai",