ASoC: Intel: create atom folder and move atom platform files in
authorJie Yang <yang.jie@intel.com>
Thu, 2 Apr 2015 07:37:04 +0000 (15:37 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 6 Apr 2015 16:49:45 +0000 (17:49 +0100)
Restructure the sound/soc/intel/ directory: create atom folder, and move
sst atom platform files here.

Signed-off-by: Jie Yang <yang.jie@intel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
37 files changed:
sound/soc/intel/Makefile
sound/soc/intel/atom/Makefile [new file with mode: 0644]
sound/soc/intel/atom/sst-atom-controls.c [new file with mode: 0644]
sound/soc/intel/atom/sst-atom-controls.h [new file with mode: 0644]
sound/soc/intel/atom/sst-mfld-dsp.h [new file with mode: 0644]
sound/soc/intel/atom/sst-mfld-platform-compress.c [new file with mode: 0644]
sound/soc/intel/atom/sst-mfld-platform-pcm.c [new file with mode: 0644]
sound/soc/intel/atom/sst-mfld-platform.h [new file with mode: 0644]
sound/soc/intel/atom/sst/Makefile [new file with mode: 0644]
sound/soc/intel/atom/sst/sst.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst.h [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_acpi.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_drv_interface.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_ipc.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_loader.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_pci.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_pvt.c [new file with mode: 0644]
sound/soc/intel/atom/sst/sst_stream.c [new file with mode: 0644]
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/intel/sst-atom-controls.c [deleted file]
sound/soc/intel/sst-atom-controls.h [deleted file]
sound/soc/intel/sst-mfld-dsp.h [deleted file]
sound/soc/intel/sst-mfld-platform-compress.c [deleted file]
sound/soc/intel/sst-mfld-platform-pcm.c [deleted file]
sound/soc/intel/sst-mfld-platform.h [deleted file]
sound/soc/intel/sst/Makefile [deleted file]
sound/soc/intel/sst/sst.c [deleted file]
sound/soc/intel/sst/sst.h [deleted file]
sound/soc/intel/sst/sst_acpi.c [deleted file]
sound/soc/intel/sst/sst_drv_interface.c [deleted file]
sound/soc/intel/sst/sst_ipc.c [deleted file]
sound/soc/intel/sst/sst_loader.c [deleted file]
sound/soc/intel/sst/sst_pci.c [deleted file]
sound/soc/intel/sst/sst_pvt.c [deleted file]
sound/soc/intel/sst/sst_stream.c [deleted file]

index 62de82af670367af94ce9ceea872ca78c61525a9..cd9aee9871a36a4400646441f1105d949fe5a2af 100644 (file)
@@ -1,19 +1,10 @@
 # Core support
 obj-$(CONFIG_SND_SOC_INTEL_SST) += common/
 
-snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \
-       sst-mfld-platform-compress.o sst-atom-controls.o
-snd-soc-mfld-machine-objs := mfld_machine.o
-
-obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o
-obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o
-
 # Platform Support
 obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/
 obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/
+obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += atom/
 
 # Machine support
 obj-$(CONFIG_SND_SOC_INTEL_SST) += boards/
-
-# DSP driver
-obj-$(CONFIG_SND_SST_IPC) += sst/
diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile
new file mode 100644 (file)
index 0000000..ce8074f
--- /dev/null
@@ -0,0 +1,7 @@
+snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \
+               sst-mfld-platform-compress.o sst-atom-controls.o
+
+obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o
+
+# DSP driver
+obj-$(CONFIG_SND_SST_IPC) += sst/
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c
new file mode 100644 (file)
index 0000000..90aa5c0
--- /dev/null
@@ -0,0 +1,1422 @@
+/*
+ *  sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld
+ *
+ *  Copyright (C) 2013-14 Intel Corp
+ *  Author: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
+ *     Vinod Koul <vinod.koul@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  In the dpcm driver modelling when a particular FE/BE/Mixer/Pipe is active
+ *  we forward the settings and parameters, rest we keep the values  in
+ *  driver and forward when DAPM enables them
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "sst-mfld-platform.h"
+#include "sst-atom-controls.h"
+
+static int sst_fill_byte_control(struct sst_data *drv,
+                                        u8 ipc_msg, u8 block,
+                                        u8 task_id, u8 pipe_id,
+                                        u16 len, void *cmd_data)
+{
+       struct snd_sst_bytes_v2 *byte_data = drv->byte_stream;
+
+       byte_data->type = SST_CMD_BYTES_SET;
+       byte_data->ipc_msg = ipc_msg;
+       byte_data->block = block;
+       byte_data->task_id = task_id;
+       byte_data->pipe_id = pipe_id;
+
+       if (len > SST_MAX_BIN_BYTES - sizeof(*byte_data)) {
+               dev_err(&drv->pdev->dev, "command length too big (%u)", len);
+               return -EINVAL;
+       }
+       byte_data->len = len;
+       memcpy(byte_data->bytes, cmd_data, len);
+       print_hex_dump_bytes("writing to lpe: ", DUMP_PREFIX_OFFSET,
+                            byte_data, len + sizeof(*byte_data));
+       return 0;
+}
+
+static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv,
+                                u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id,
+                                void *cmd_data, u16 len)
+{
+       int ret = 0;
+
+       ret = sst_fill_byte_control(drv, ipc_msg,
+                               block, task_id, pipe_id, len, cmd_data);
+       if (ret < 0)
+               return ret;
+       return sst->ops->send_byte_stream(sst->dev, drv->byte_stream);
+}
+
+/**
+ * sst_fill_and_send_cmd - generate the IPC message and send it to the FW
+ * @ipc_msg:   type of IPC (CMD, SET_PARAMS, GET_PARAMS)
+ * @cmd_data:  the IPC payload
+ */
+static int sst_fill_and_send_cmd(struct sst_data *drv,
+                                u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id,
+                                void *cmd_data, u16 len)
+{
+       int ret;
+
+       mutex_lock(&drv->lock);
+       ret = sst_fill_and_send_cmd_unlocked(drv, ipc_msg, block,
+                                       task_id, pipe_id, cmd_data, len);
+       mutex_unlock(&drv->lock);
+
+       return ret;
+}
+
+/**
+ * tx map value is a bitfield where each bit represents a FW channel
+ *
+ *                     3 2 1 0         # 0 = codec0, 1 = codec1
+ *                     RLRLRLRL        # 3, 4 = reserved
+ *
+ * e.g. slot 0 rx map =        00001100b -> data from slot 0 goes into codec_in1 L,R
+ */
+static u8 sst_ssp_tx_map[SST_MAX_TDM_SLOTS] = {
+       0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default rx map */
+};
+
+/**
+ * rx map value is a bitfield where each bit represents a slot
+ *
+ *                       76543210      # 0 = slot 0, 1 = slot 1
+ *
+ * e.g. codec1_0 tx map = 00000101b -> data from codec_out1_0 goes into slot 0, 2
+ */
+static u8 sst_ssp_rx_map[SST_MAX_TDM_SLOTS] = {
+       0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default tx map */
+};
+
+/**
+ * NOTE: this is invoked with lock held
+ */
+static int sst_send_slot_map(struct sst_data *drv)
+{
+       struct sst_param_sba_ssp_slot_map cmd;
+
+       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
+       cmd.header.command_id = SBA_SET_SSP_SLOT_MAP;
+       cmd.header.length = sizeof(struct sst_param_sba_ssp_slot_map)
+                               - sizeof(struct sst_dsp_header);
+
+       cmd.param_id = SBA_SET_SSP_SLOT_MAP;
+       cmd.param_len = sizeof(cmd.rx_slot_map) + sizeof(cmd.tx_slot_map)
+                                       + sizeof(cmd.ssp_index);
+       cmd.ssp_index = SSP_CODEC;
+
+       memcpy(cmd.rx_slot_map, &sst_ssp_tx_map[0], sizeof(cmd.rx_slot_map));
+       memcpy(cmd.tx_slot_map, &sst_ssp_rx_map[0], sizeof(cmd.tx_slot_map));
+
+       return sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS,
+                       SST_FLAG_BLOCKED, SST_TASK_SBA, 0, &cmd,
+                             sizeof(cmd.header) + cmd.header.length);
+}
+
+int sst_slot_enum_info(struct snd_kcontrol *kcontrol,
+                      struct snd_ctl_elem_info *uinfo)
+{
+       struct sst_enum *e = (struct sst_enum *)kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = e->max;
+
+       if (uinfo->value.enumerated.item > e->max - 1)
+               uinfo->value.enumerated.item = e->max - 1;
+       strcpy(uinfo->value.enumerated.name,
+               e->texts[uinfo->value.enumerated.item]);
+
+       return 0;
+}
+
+/**
+ * sst_slot_get - get the status of the interleaver/deinterleaver control
+ *
+ * Searches the map where the control status is stored, and gets the
+ * channel/slot which is currently set for this enumerated control. Since it is
+ * an enumerated control, there is only one possible value.
+ */
+static int sst_slot_get(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct sst_enum *e = (void *)kcontrol->private_value;
+       struct snd_soc_component *c = snd_kcontrol_chip(kcontrol);
+       struct sst_data *drv = snd_soc_component_get_drvdata(c);
+       unsigned int ctl_no = e->reg;
+       unsigned int is_tx = e->tx;
+       unsigned int val, mux;
+       u8 *map = is_tx ? sst_ssp_rx_map : sst_ssp_tx_map;
+
+       mutex_lock(&drv->lock);
+       val = 1 << ctl_no;
+       /* search which slot/channel has this bit set - there should be only one */
+       for (mux = e->max; mux > 0;  mux--)
+               if (map[mux - 1] & val)
+                       break;
+
+       ucontrol->value.enumerated.item[0] = mux;
+       mutex_unlock(&drv->lock);
+
+       dev_dbg(c->dev, "%s - %s map = %#x\n",
+                       is_tx ? "tx channel" : "rx slot",
+                        e->texts[mux], mux ? map[mux - 1] : -1);
+       return 0;
+}
+
+/* sst_check_and_send_slot_map - helper for checking power state and sending
+ * slot map cmd
+ *
+ * called with lock held
+ */
+static int sst_check_and_send_slot_map(struct sst_data *drv, struct snd_kcontrol *kcontrol)
+{
+       struct sst_enum *e = (void *)kcontrol->private_value;
+       int ret = 0;
+
+       if (e->w && e->w->power)
+               ret = sst_send_slot_map(drv);
+       else
+               dev_err(&drv->pdev->dev, "Slot control: %s doesn't have DAPM widget!!!\n",
+                               kcontrol->id.name);
+       return ret;
+}
+
+/**
+ * sst_slot_put - set the status of interleaver/deinterleaver control
+ *
+ * (de)interleaver controls are defined in opposite sense to be user-friendly
+ *
+ * Instead of the enum value being the value written to the register, it is the
+ * register address; and the kcontrol number (register num) is the value written
+ * to the register. This is so that there can be only one value for each
+ * slot/channel since there is only one control for each slot/channel.
+ *
+ * This means that whenever an enum is set, we need to clear the bit
+ * for that kcontrol_no for all the interleaver OR deinterleaver registers
+ */
+static int sst_slot_put(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+       struct sst_data *drv = snd_soc_component_get_drvdata(c);
+       struct sst_enum *e = (void *)kcontrol->private_value;
+       int i, ret = 0;
+       unsigned int ctl_no = e->reg;
+       unsigned int is_tx = e->tx;
+       unsigned int slot_channel_no;
+       unsigned int val, mux;
+       u8 *map;
+
+       map = is_tx ? sst_ssp_rx_map : sst_ssp_tx_map;
+
+       val = 1 << ctl_no;
+       mux = ucontrol->value.enumerated.item[0];
+       if (mux > e->max - 1)
+               return -EINVAL;
+
+       mutex_lock(&drv->lock);
+       /* first clear all registers of this bit */
+       for (i = 0; i < e->max; i++)
+               map[i] &= ~val;
+
+       if (mux == 0) {
+               /* kctl set to 'none' and we reset the bits so send IPC */
+               ret = sst_check_and_send_slot_map(drv, kcontrol);
+
+               mutex_unlock(&drv->lock);
+               return ret;
+       }
+
+       /* offset by one to take "None" into account */
+       slot_channel_no = mux - 1;
+       map[slot_channel_no] |= val;
+
+       dev_dbg(c->dev, "%s %s map = %#x\n",
+                       is_tx ? "tx channel" : "rx slot",
+                       e->texts[mux], map[slot_channel_no]);
+
+       ret = sst_check_and_send_slot_map(drv, kcontrol);
+
+       mutex_unlock(&drv->lock);
+       return ret;
+}
+
+static int sst_send_algo_cmd(struct sst_data *drv,
+                             struct sst_algo_control *bc)
+{
+       int len, ret = 0;
+       struct sst_cmd_set_params *cmd;
+
+       /*bc->max includes sizeof algos + length field*/
+       len = sizeof(cmd->dst) + sizeof(cmd->command_id) + bc->max;
+
+       cmd = kzalloc(len, GFP_KERNEL);
+       if (cmd == NULL)
+               return -ENOMEM;
+
+       SST_FILL_DESTINATION(2, cmd->dst, bc->pipe_id, bc->module_id);
+       cmd->command_id = bc->cmd_id;
+       memcpy(cmd->params, bc->params, bc->max);
+
+       ret = sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS,
+                               SST_FLAG_BLOCKED, bc->task_id, 0, cmd, len);
+       kfree(cmd);
+       return ret;
+}
+
+/**
+ * sst_find_and_send_pipe_algo - send all the algo parameters for a pipe
+ *
+ * The algos which are in each pipeline are sent to the firmware one by one
+ *
+ * Called with lock held
+ */
+static int sst_find_and_send_pipe_algo(struct sst_data *drv,
+                                       const char *pipe, struct sst_ids *ids)
+{
+       int ret = 0;
+       struct sst_algo_control *bc;
+       struct sst_module *algo = NULL;
+
+       dev_dbg(&drv->pdev->dev, "Enter: widget=%s\n", pipe);
+
+       list_for_each_entry(algo, &ids->algo_list, node) {
+               bc = (void *)algo->kctl->private_value;
+
+               dev_dbg(&drv->pdev->dev, "Found algo control name=%s pipe=%s\n",
+                               algo->kctl->id.name, pipe);
+               ret = sst_send_algo_cmd(drv, bc);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+static int sst_algo_bytes_ctl_info(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_info *uinfo)
+{
+       struct sst_algo_control *bc = (void *)kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+       uinfo->count = bc->max;
+
+       return 0;
+}
+
+static int sst_algo_control_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct sst_algo_control *bc = (void *)kcontrol->private_value;
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+
+       switch (bc->type) {
+       case SST_ALGO_PARAMS:
+               memcpy(ucontrol->value.bytes.data, bc->params, bc->max);
+               break;
+       default:
+               dev_err(component->dev, "Invalid Input- algo type:%d\n",
+                               bc->type);
+               return -EINVAL;
+
+       }
+       return 0;
+}
+
+static int sst_algo_control_set(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       int ret = 0;
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt);
+       struct sst_algo_control *bc = (void *)kcontrol->private_value;
+
+       dev_dbg(cmpnt->dev, "control_name=%s\n", kcontrol->id.name);
+       mutex_lock(&drv->lock);
+       switch (bc->type) {
+       case SST_ALGO_PARAMS:
+               memcpy(bc->params, ucontrol->value.bytes.data, bc->max);
+               break;
+       default:
+               mutex_unlock(&drv->lock);
+               dev_err(cmpnt->dev, "Invalid Input- algo type:%d\n",
+                               bc->type);
+               return -EINVAL;
+       }
+       /*if pipe is enabled, need to send the algo params from here*/
+       if (bc->w && bc->w->power)
+               ret = sst_send_algo_cmd(drv, bc);
+       mutex_unlock(&drv->lock);
+
+       return ret;
+}
+
+static int sst_gain_ctl_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       struct sst_gain_mixer_control *mc = (void *)kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = mc->stereo ? 2 : 1;
+       uinfo->value.integer.min = mc->min;
+       uinfo->value.integer.max = mc->max;
+
+       return 0;
+}
+
+/**
+ * sst_send_gain_cmd - send the gain algorithm IPC to the FW
+ * @gv:                the stored value of gain (also contains rampduration)
+ * @mute:      flag that indicates whether this was called from the
+ *             digital_mute callback or directly. If called from the
+ *             digital_mute callback, module will be muted/unmuted based on this
+ *             flag. The flag is always 0 if called directly.
+ *
+ * Called with sst_data.lock held
+ *
+ * The user-set gain value is sent only if the user-controllable 'mute' control
+ * is OFF (indicated by gv->mute). Otherwise, the mute value (MIN value) is
+ * sent.
+ */
+static int sst_send_gain_cmd(struct sst_data *drv, struct sst_gain_value *gv,
+                             u16 task_id, u16 loc_id, u16 module_id, int mute)
+{
+       struct sst_cmd_set_gain_dual cmd;
+
+       dev_dbg(&drv->pdev->dev, "Enter\n");
+
+       cmd.header.command_id = MMX_SET_GAIN;
+       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
+       cmd.gain_cell_num = 1;
+
+       if (mute || gv->mute) {
+               cmd.cell_gains[0].cell_gain_left = SST_GAIN_MIN_VALUE;
+               cmd.cell_gains[0].cell_gain_right = SST_GAIN_MIN_VALUE;
+       } else {
+               cmd.cell_gains[0].cell_gain_left = gv->l_gain;
+               cmd.cell_gains[0].cell_gain_right = gv->r_gain;
+       }
+
+       SST_FILL_DESTINATION(2, cmd.cell_gains[0].dest,
+                            loc_id, module_id);
+       cmd.cell_gains[0].gain_time_constant = gv->ramp_duration;
+
+       cmd.header.length = sizeof(struct sst_cmd_set_gain_dual)
+                               - sizeof(struct sst_dsp_header);
+
+       /* we are with lock held, so call the unlocked api  to send */
+       return sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS,
+                               SST_FLAG_BLOCKED, task_id, 0, &cmd,
+                             sizeof(cmd.header) + cmd.header.length);
+}
+
+static int sst_gain_get(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct sst_gain_mixer_control *mc = (void *)kcontrol->private_value;
+       struct sst_gain_value *gv = mc->gain_val;
+
+       switch (mc->type) {
+       case SST_GAIN_TLV:
+               ucontrol->value.integer.value[0] = gv->l_gain;
+               ucontrol->value.integer.value[1] = gv->r_gain;
+               break;
+
+       case SST_GAIN_MUTE:
+               ucontrol->value.integer.value[0] = gv->mute ? 1 : 0;
+               break;
+
+       case SST_GAIN_RAMP_DURATION:
+               ucontrol->value.integer.value[0] = gv->ramp_duration;
+               break;
+
+       default:
+               dev_err(component->dev, "Invalid Input- gain type:%d\n",
+                               mc->type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int sst_gain_put(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       int ret = 0;
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt);
+       struct sst_gain_mixer_control *mc = (void *)kcontrol->private_value;
+       struct sst_gain_value *gv = mc->gain_val;
+
+       mutex_lock(&drv->lock);
+
+       switch (mc->type) {
+       case SST_GAIN_TLV:
+               gv->l_gain = ucontrol->value.integer.value[0];
+               gv->r_gain = ucontrol->value.integer.value[1];
+               dev_dbg(cmpnt->dev, "%s: Volume %d, %d\n",
+                               mc->pname, gv->l_gain, gv->r_gain);
+               break;
+
+       case SST_GAIN_MUTE:
+               gv->mute = !!ucontrol->value.integer.value[0];
+               dev_dbg(cmpnt->dev, "%s: Mute %d\n", mc->pname, gv->mute);
+               break;
+
+       case SST_GAIN_RAMP_DURATION:
+               gv->ramp_duration = ucontrol->value.integer.value[0];
+               dev_dbg(cmpnt->dev, "%s: Ramp Delay%d\n",
+                                       mc->pname, gv->ramp_duration);
+               break;
+
+       default:
+               mutex_unlock(&drv->lock);
+               dev_err(cmpnt->dev, "Invalid Input- gain type:%d\n",
+                               mc->type);
+               return -EINVAL;
+       }
+
+       if (mc->w && mc->w->power)
+               ret = sst_send_gain_cmd(drv, gv, mc->task_id,
+                       mc->pipe_id | mc->instance_id, mc->module_id, 0);
+       mutex_unlock(&drv->lock);
+
+       return ret;
+}
+
+static int sst_set_pipe_gain(struct sst_ids *ids,
+                               struct sst_data *drv, int mute);
+
+static int sst_send_pipe_module_params(struct snd_soc_dapm_widget *w,
+               struct snd_kcontrol *kcontrol)
+{
+       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+       struct sst_data *drv = snd_soc_component_get_drvdata(c);
+       struct sst_ids *ids = w->priv;
+
+       mutex_lock(&drv->lock);
+       sst_find_and_send_pipe_algo(drv, w->name, ids);
+       sst_set_pipe_gain(ids, drv, 0);
+       mutex_unlock(&drv->lock);
+
+       return 0;
+}
+
+static int sst_generic_modules_event(struct snd_soc_dapm_widget *w,
+                                    struct snd_kcontrol *k, int event)
+{
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               return sst_send_pipe_module_params(w, k);
+       return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(sst_gain_tlv_common, SST_GAIN_MIN_VALUE * 10, 10, 0);
+
+/* Look up table to convert MIXER SW bit regs to SWM inputs */
+static const uint swm_mixer_input_ids[SST_SWM_INPUT_COUNT] = {
+       [SST_IP_CODEC0]         = SST_SWM_IN_CODEC0,
+       [SST_IP_CODEC1]         = SST_SWM_IN_CODEC1,
+       [SST_IP_LOOP0]          = SST_SWM_IN_SPROT_LOOP,
+       [SST_IP_LOOP1]          = SST_SWM_IN_MEDIA_LOOP1,
+       [SST_IP_LOOP2]          = SST_SWM_IN_MEDIA_LOOP2,
+       [SST_IP_PCM0]           = SST_SWM_IN_PCM0,
+       [SST_IP_PCM1]           = SST_SWM_IN_PCM1,
+       [SST_IP_MEDIA0]         = SST_SWM_IN_MEDIA0,
+       [SST_IP_MEDIA1]         = SST_SWM_IN_MEDIA1,
+       [SST_IP_MEDIA2]         = SST_SWM_IN_MEDIA2,
+       [SST_IP_MEDIA3]         = SST_SWM_IN_MEDIA3,
+};
+
+/**
+ * fill_swm_input - fill in the SWM input ids given the register
+ *
+ * The register value is a bit-field inicated which mixer inputs are ON. Use the
+ * lookup table to get the input-id and fill it in the structure.
+ */
+static int fill_swm_input(struct snd_soc_component *cmpnt,
+               struct swm_input_ids *swm_input, unsigned int reg)
+{
+       uint i, is_set, nb_inputs = 0;
+       u16 input_loc_id;
+
+       dev_dbg(cmpnt->dev, "reg: %#x\n", reg);
+       for (i = 0; i < SST_SWM_INPUT_COUNT; i++) {
+               is_set = reg & BIT(i);
+               if (!is_set)
+                       continue;
+
+               input_loc_id = swm_mixer_input_ids[i];
+               SST_FILL_DESTINATION(2, swm_input->input_id,
+                                    input_loc_id, SST_DEFAULT_MODULE_ID);
+               nb_inputs++;
+               swm_input++;
+               dev_dbg(cmpnt->dev, "input id: %#x, nb_inputs: %d\n",
+                               input_loc_id, nb_inputs);
+
+               if (nb_inputs == SST_CMD_SWM_MAX_INPUTS) {
+                       dev_warn(cmpnt->dev, "SET_SWM cmd max inputs reached");
+                       break;
+               }
+       }
+       return nb_inputs;
+}
+
+
+/**
+ * called with lock held
+ */
+static int sst_set_pipe_gain(struct sst_ids *ids,
+                       struct sst_data *drv, int mute)
+{
+       int ret = 0;
+       struct sst_gain_mixer_control *mc;
+       struct sst_gain_value *gv;
+       struct sst_module *gain = NULL;
+
+       list_for_each_entry(gain, &ids->gain_list, node) {
+               struct snd_kcontrol *kctl = gain->kctl;
+
+               dev_dbg(&drv->pdev->dev, "control name=%s\n", kctl->id.name);
+               mc = (void *)kctl->private_value;
+               gv = mc->gain_val;
+
+               ret = sst_send_gain_cmd(drv, gv, mc->task_id,
+                       mc->pipe_id | mc->instance_id, mc->module_id, mute);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+static int sst_swm_mixer_event(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *k, int event)
+{
+       struct sst_cmd_set_swm cmd;
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt);
+       struct sst_ids *ids = w->priv;
+       bool set_mixer = false;
+       struct soc_mixer_control *mc;
+       int val = 0;
+       int i = 0;
+
+       dev_dbg(cmpnt->dev, "widget = %s\n", w->name);
+       /*
+        * Identify which mixer input is on and send the bitmap of the
+        * inputs as an IPC to the DSP.
+        */
+       for (i = 0; i < w->num_kcontrols; i++) {
+               if (dapm_kcontrol_get_value(w->kcontrols[i])) {
+                       mc = (struct soc_mixer_control *)(w->kcontrols[i])->private_value;
+                       val |= 1 << mc->shift;
+               }
+       }
+       dev_dbg(cmpnt->dev, "val = %#x\n", val);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+       case SND_SOC_DAPM_POST_PMD:
+               set_mixer = true;
+               break;
+       case SND_SOC_DAPM_POST_REG:
+               if (w->power)
+                       set_mixer = true;
+               break;
+       default:
+               set_mixer = false;
+       }
+
+       if (set_mixer == false)
+               return 0;
+
+       if (SND_SOC_DAPM_EVENT_ON(event) ||
+           event == SND_SOC_DAPM_POST_REG)
+               cmd.switch_state = SST_SWM_ON;
+       else
+               cmd.switch_state = SST_SWM_OFF;
+
+       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
+       /* MMX_SET_SWM == SBA_SET_SWM */
+       cmd.header.command_id = SBA_SET_SWM;
+
+       SST_FILL_DESTINATION(2, cmd.output_id,
+                            ids->location_id, SST_DEFAULT_MODULE_ID);
+       cmd.nb_inputs = fill_swm_input(cmpnt, &cmd.input[0], val);
+       cmd.header.length = offsetof(struct sst_cmd_set_swm, input)
+                               - sizeof(struct sst_dsp_header)
+                               + (cmd.nb_inputs * sizeof(cmd.input[0]));
+
+       return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
+                             ids->task_id, 0, &cmd,
+                             sizeof(cmd.header) + cmd.header.length);
+}
+
+/* SBA mixers - 16 inputs */
+#define SST_SBA_DECLARE_MIX_CONTROLS(kctl_name)                                                        \
+       static const struct snd_kcontrol_new kctl_name[] = {                                    \
+               SOC_DAPM_SINGLE("codec_in0 Switch", SND_SOC_NOPM, SST_IP_CODEC0, 1, 0),         \
+               SOC_DAPM_SINGLE("codec_in1 Switch", SND_SOC_NOPM, SST_IP_CODEC1, 1, 0),         \
+               SOC_DAPM_SINGLE("sprot_loop_in Switch", SND_SOC_NOPM, SST_IP_LOOP0, 1, 0),      \
+               SOC_DAPM_SINGLE("media_loop1_in Switch", SND_SOC_NOPM, SST_IP_LOOP1, 1, 0),     \
+               SOC_DAPM_SINGLE("media_loop2_in Switch", SND_SOC_NOPM, SST_IP_LOOP2, 1, 0),     \
+               SOC_DAPM_SINGLE("pcm0_in Switch", SND_SOC_NOPM, SST_IP_PCM0, 1, 0),             \
+               SOC_DAPM_SINGLE("pcm1_in Switch", SND_SOC_NOPM, SST_IP_PCM1, 1, 0),             \
+       }
+
+#define SST_SBA_MIXER_GRAPH_MAP(mix_name)                      \
+       { mix_name, "codec_in0 Switch", "codec_in0" },          \
+       { mix_name, "codec_in1 Switch", "codec_in1" },          \
+       { mix_name, "sprot_loop_in Switch",     "sprot_loop_in" },      \
+       { mix_name, "media_loop1_in Switch",    "media_loop1_in" },     \
+       { mix_name, "media_loop2_in Switch",    "media_loop2_in" },     \
+       { mix_name, "pcm0_in Switch",           "pcm0_in" },            \
+       { mix_name, "pcm1_in Switch",           "pcm1_in" }
+
+#define SST_MMX_DECLARE_MIX_CONTROLS(kctl_name)                                                \
+       static const struct snd_kcontrol_new kctl_name[] = {                            \
+               SOC_DAPM_SINGLE("media0_in Switch", SND_SOC_NOPM, SST_IP_MEDIA0, 1, 0), \
+               SOC_DAPM_SINGLE("media1_in Switch", SND_SOC_NOPM, SST_IP_MEDIA1, 1, 0), \
+               SOC_DAPM_SINGLE("media2_in Switch", SND_SOC_NOPM, SST_IP_MEDIA2, 1, 0), \
+               SOC_DAPM_SINGLE("media3_in Switch", SND_SOC_NOPM, SST_IP_MEDIA3, 1, 0), \
+       }
+
+SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media0_controls);
+SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media1_controls);
+
+/* 18 SBA mixers */
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm0_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm1_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls);
+SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls);
+
+/*
+ * sst_handle_vb_timer - Start/Stop the DSP scheduler
+ *
+ * The DSP expects first cmd to be SBA_VB_START, so at first startup send
+ * that.
+ * DSP expects last cmd to be SBA_VB_IDLE, so at last shutdown send that.
+ *
+ * Do refcount internally so that we send command only at first start
+ * and last end. Since SST driver does its own ref count, invoke sst's
+ * power ops always!
+ */
+int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable)
+{
+       int ret = 0;
+       struct sst_cmd_generic cmd;
+       struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
+       static int timer_usage;
+
+       if (enable)
+               cmd.header.command_id = SBA_VB_START;
+       else
+               cmd.header.command_id = SBA_IDLE;
+       dev_dbg(dai->dev, "enable=%u, usage=%d\n", enable, timer_usage);
+
+       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
+       cmd.header.length = 0;
+
+       if (enable) {
+               ret = sst->ops->power(sst->dev, true);
+               if (ret < 0)
+                       return ret;
+       }
+
+       mutex_lock(&drv->lock);
+       if (enable)
+               timer_usage++;
+       else
+               timer_usage--;
+
+       /*
+        * Send the command only if this call is the first enable or last
+        * disable
+        */
+       if ((enable && (timer_usage == 1)) ||
+           (!enable && (timer_usage == 0))) {
+               ret = sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_CMD,
+                               SST_FLAG_BLOCKED, SST_TASK_SBA, 0, &cmd,
+                               sizeof(cmd.header) + cmd.header.length);
+               if (ret && enable) {
+                       timer_usage--;
+                       enable  = false;
+               }
+       }
+       mutex_unlock(&drv->lock);
+
+       if (!enable)
+               sst->ops->power(sst->dev, false);
+       return ret;
+}
+
+/**
+ * sst_ssp_config - contains SSP configuration for media UC
+ */
+static const struct sst_ssp_config sst_ssp_configs = {
+       .ssp_id = SSP_CODEC,
+       .bits_per_slot = 24,
+       .slots = 4,
+       .ssp_mode = SSP_MODE_MASTER,
+       .pcm_mode = SSP_PCM_MODE_NETWORK,
+       .duplex = SSP_DUPLEX,
+       .ssp_protocol = SSP_MODE_PCM,
+       .fs_width = 1,
+       .fs_frequency = SSP_FS_48_KHZ,
+       .active_slot_map = 0xF,
+       .start_delay = 0,
+};
+
+int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable)
+{
+       struct sst_cmd_sba_hw_set_ssp cmd;
+       struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
+       const struct sst_ssp_config *config;
+
+       dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id);
+
+       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
+       cmd.header.command_id = SBA_HW_SET_SSP;
+       cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp)
+                               - sizeof(struct sst_dsp_header);
+
+       config = &sst_ssp_configs;
+       dev_dbg(dai->dev, "ssp_id: %u\n", config->ssp_id);
+
+       if (enable)
+               cmd.switch_state = SST_SWITCH_ON;
+       else
+               cmd.switch_state = SST_SWITCH_OFF;
+
+       cmd.selection = config->ssp_id;
+       cmd.nb_bits_per_slots = config->bits_per_slot;
+       cmd.nb_slots = config->slots;
+       cmd.mode = config->ssp_mode | (config->pcm_mode << 1);
+       cmd.duplex = config->duplex;
+       cmd.active_tx_slot_map = config->active_slot_map;
+       cmd.active_rx_slot_map = config->active_slot_map;
+       cmd.frame_sync_frequency = config->fs_frequency;
+       cmd.frame_sync_polarity = SSP_FS_ACTIVE_HIGH;
+       cmd.data_polarity = 1;
+       cmd.frame_sync_width = config->fs_width;
+       cmd.ssp_protocol = config->ssp_protocol;
+       cmd.start_delay = config->start_delay;
+       cmd.reserved1 = cmd.reserved2 = 0xFF;
+
+       return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
+                               SST_TASK_SBA, 0, &cmd,
+                               sizeof(cmd.header) + cmd.header.length);
+}
+
+static int sst_set_be_modules(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *k, int event)
+{
+       int ret = 0;
+       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+       struct sst_data *drv = snd_soc_component_get_drvdata(c);
+
+       dev_dbg(c->dev, "Enter: widget=%s\n", w->name);
+
+       if (SND_SOC_DAPM_EVENT_ON(event)) {
+               ret = sst_send_slot_map(drv);
+               if (ret)
+                       return ret;
+               ret = sst_send_pipe_module_params(w, k);
+       }
+       return ret;
+}
+
+static int sst_set_media_path(struct snd_soc_dapm_widget *w,
+                             struct snd_kcontrol *k, int event)
+{
+       int ret = 0;
+       struct sst_cmd_set_media_path cmd;
+       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+       struct sst_data *drv = snd_soc_component_get_drvdata(c);
+       struct sst_ids *ids = w->priv;
+
+       dev_dbg(c->dev, "widget=%s\n", w->name);
+       dev_dbg(c->dev, "task=%u, location=%#x\n",
+                               ids->task_id, ids->location_id);
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               cmd.switch_state = SST_PATH_ON;
+       else
+               cmd.switch_state = SST_PATH_OFF;
+
+       SST_FILL_DESTINATION(2, cmd.header.dst,
+                            ids->location_id, SST_DEFAULT_MODULE_ID);
+
+       /* MMX_SET_MEDIA_PATH == SBA_SET_MEDIA_PATH */
+       cmd.header.command_id = MMX_SET_MEDIA_PATH;
+       cmd.header.length = sizeof(struct sst_cmd_set_media_path)
+                               - sizeof(struct sst_dsp_header);
+
+       ret = sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
+                             ids->task_id, 0, &cmd,
+                             sizeof(cmd.header) + cmd.header.length);
+       if (ret)
+               return ret;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               ret = sst_send_pipe_module_params(w, k);
+       return ret;
+}
+
+static int sst_set_media_loop(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *k, int event)
+{
+       int ret = 0;
+       struct sst_cmd_sba_set_media_loop_map cmd;
+       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+       struct sst_data *drv = snd_soc_component_get_drvdata(c);
+       struct sst_ids *ids = w->priv;
+
+       dev_dbg(c->dev, "Enter:widget=%s\n", w->name);
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               cmd.switch_state = SST_SWITCH_ON;
+       else
+               cmd.switch_state = SST_SWITCH_OFF;
+
+       SST_FILL_DESTINATION(2, cmd.header.dst,
+                            ids->location_id, SST_DEFAULT_MODULE_ID);
+
+       cmd.header.command_id = SBA_SET_MEDIA_LOOP_MAP;
+       cmd.header.length = sizeof(struct sst_cmd_sba_set_media_loop_map)
+                                - sizeof(struct sst_dsp_header);
+       cmd.param.part.cfg.rate = 2; /* 48khz */
+
+       cmd.param.part.cfg.format = ids->format; /* stereo/Mono */
+       cmd.param.part.cfg.s_length = 1; /* 24bit left justified */
+       cmd.map = 0; /* Algo sequence: Gain - DRP - FIR - IIR */
+
+       ret = sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
+                             SST_TASK_SBA, 0, &cmd,
+                             sizeof(cmd.header) + cmd.header.length);
+       if (ret)
+               return ret;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               ret = sst_send_pipe_module_params(w, k);
+       return ret;
+}
+
+static const struct snd_soc_dapm_widget sst_dapm_widgets[] = {
+       SST_AIF_IN("codec_in0", sst_set_be_modules),
+       SST_AIF_IN("codec_in1", sst_set_be_modules),
+       SST_AIF_OUT("codec_out0", sst_set_be_modules),
+       SST_AIF_OUT("codec_out1", sst_set_be_modules),
+
+       /* Media Paths */
+       /* MediaX IN paths are set via ALLOC, so no SET_MEDIA_PATH command */
+       SST_PATH_INPUT("media0_in", SST_TASK_MMX, SST_SWM_IN_MEDIA0, sst_generic_modules_event),
+       SST_PATH_INPUT("media1_in", SST_TASK_MMX, SST_SWM_IN_MEDIA1, NULL),
+       SST_PATH_INPUT("media2_in", SST_TASK_MMX, SST_SWM_IN_MEDIA2, sst_set_media_path),
+       SST_PATH_INPUT("media3_in", SST_TASK_MMX, SST_SWM_IN_MEDIA3, NULL),
+       SST_PATH_OUTPUT("media0_out", SST_TASK_MMX, SST_SWM_OUT_MEDIA0, sst_set_media_path),
+       SST_PATH_OUTPUT("media1_out", SST_TASK_MMX, SST_SWM_OUT_MEDIA1, sst_set_media_path),
+
+       /* SBA PCM Paths */
+       SST_PATH_INPUT("pcm0_in", SST_TASK_SBA, SST_SWM_IN_PCM0, sst_set_media_path),
+       SST_PATH_INPUT("pcm1_in", SST_TASK_SBA, SST_SWM_IN_PCM1, sst_set_media_path),
+       SST_PATH_OUTPUT("pcm0_out", SST_TASK_SBA, SST_SWM_OUT_PCM0, sst_set_media_path),
+       SST_PATH_OUTPUT("pcm1_out", SST_TASK_SBA, SST_SWM_OUT_PCM1, sst_set_media_path),
+       SST_PATH_OUTPUT("pcm2_out", SST_TASK_SBA, SST_SWM_OUT_PCM2, sst_set_media_path),
+
+       /* SBA Loops */
+       SST_PATH_INPUT("sprot_loop_in", SST_TASK_SBA, SST_SWM_IN_SPROT_LOOP, NULL),
+       SST_PATH_INPUT("media_loop1_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP1, NULL),
+       SST_PATH_INPUT("media_loop2_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP2, NULL),
+       SST_PATH_MEDIA_LOOP_OUTPUT("sprot_loop_out", SST_TASK_SBA, SST_SWM_OUT_SPROT_LOOP, SST_FMT_MONO, sst_set_media_loop),
+       SST_PATH_MEDIA_LOOP_OUTPUT("media_loop1_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP1, SST_FMT_MONO, sst_set_media_loop),
+       SST_PATH_MEDIA_LOOP_OUTPUT("media_loop2_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP2, SST_FMT_STEREO, sst_set_media_loop),
+
+       /* Media Mixers */
+       SST_SWM_MIXER("media0_out mix 0", SND_SOC_NOPM, SST_TASK_MMX, SST_SWM_OUT_MEDIA0,
+                     sst_mix_media0_controls, sst_swm_mixer_event),
+       SST_SWM_MIXER("media1_out mix 0", SND_SOC_NOPM, SST_TASK_MMX, SST_SWM_OUT_MEDIA1,
+                     sst_mix_media1_controls, sst_swm_mixer_event),
+
+       /* SBA PCM mixers */
+       SST_SWM_MIXER("pcm0_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_PCM0,
+                     sst_mix_pcm0_controls, sst_swm_mixer_event),
+       SST_SWM_MIXER("pcm1_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_PCM1,
+                     sst_mix_pcm1_controls, sst_swm_mixer_event),
+       SST_SWM_MIXER("pcm2_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_PCM2,
+                     sst_mix_pcm2_controls, sst_swm_mixer_event),
+
+       /* SBA Loop mixers */
+       SST_SWM_MIXER("sprot_loop_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_SPROT_LOOP,
+                     sst_mix_sprot_l0_controls, sst_swm_mixer_event),
+       SST_SWM_MIXER("media_loop1_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP1,
+                     sst_mix_media_l1_controls, sst_swm_mixer_event),
+       SST_SWM_MIXER("media_loop2_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP2,
+                     sst_mix_media_l2_controls, sst_swm_mixer_event),
+
+       /* SBA Backend mixers */
+       SST_SWM_MIXER("codec_out0 mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_CODEC0,
+                     sst_mix_codec0_controls, sst_swm_mixer_event),
+       SST_SWM_MIXER("codec_out1 mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_CODEC1,
+                     sst_mix_codec1_controls, sst_swm_mixer_event),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+       {"media0_in", NULL, "Compress Playback"},
+       {"media1_in", NULL, "Headset Playback"},
+       {"media2_in", NULL, "pcm0_out"},
+
+       {"media0_out mix 0", "media0_in Switch", "media0_in"},
+       {"media0_out mix 0", "media1_in Switch", "media1_in"},
+       {"media0_out mix 0", "media2_in Switch", "media2_in"},
+       {"media0_out mix 0", "media3_in Switch", "media3_in"},
+       {"media1_out mix 0", "media0_in Switch", "media0_in"},
+       {"media1_out mix 0", "media1_in Switch", "media1_in"},
+       {"media1_out mix 0", "media2_in Switch", "media2_in"},
+       {"media1_out mix 0", "media3_in Switch", "media3_in"},
+
+       {"media0_out", NULL, "media0_out mix 0"},
+       {"media1_out", NULL, "media1_out mix 0"},
+       {"pcm0_in", NULL, "media0_out"},
+       {"pcm1_in", NULL, "media1_out"},
+
+       {"Headset Capture", NULL, "pcm1_out"},
+       {"Headset Capture", NULL, "pcm2_out"},
+       {"pcm0_out", NULL, "pcm0_out mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("pcm0_out mix 0"),
+       {"pcm1_out", NULL, "pcm1_out mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("pcm1_out mix 0"),
+       {"pcm2_out", NULL, "pcm2_out mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("pcm2_out mix 0"),
+
+       {"media_loop1_in", NULL, "media_loop1_out"},
+       {"media_loop1_out", NULL, "media_loop1_out mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("media_loop1_out mix 0"),
+       {"media_loop2_in", NULL, "media_loop2_out"},
+       {"media_loop2_out", NULL, "media_loop2_out mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("media_loop2_out mix 0"),
+       {"sprot_loop_in", NULL, "sprot_loop_out"},
+       {"sprot_loop_out", NULL, "sprot_loop_out mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("sprot_loop_out mix 0"),
+
+       {"codec_out0", NULL, "codec_out0 mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("codec_out0 mix 0"),
+       {"codec_out1", NULL, "codec_out1 mix 0"},
+       SST_SBA_MIXER_GRAPH_MAP("codec_out1 mix 0"),
+
+};
+static const char * const slot_names[] = {
+       "none",
+       "slot 0", "slot 1", "slot 2", "slot 3",
+       "slot 4", "slot 5", "slot 6", "slot 7", /* not supported by FW */
+};
+
+static const char * const channel_names[] = {
+       "none",
+       "codec_out0_0", "codec_out0_1", "codec_out1_0", "codec_out1_1",
+       "codec_out2_0", "codec_out2_1", "codec_out3_0", "codec_out3_1", /* not supported by FW */
+};
+
+#define SST_INTERLEAVER(xpname, slot_name, slotno) \
+       SST_SSP_SLOT_CTL(xpname, "tx interleaver", slot_name, slotno, true, \
+                        channel_names, sst_slot_get, sst_slot_put)
+
+#define SST_DEINTERLEAVER(xpname, channel_name, channel_no) \
+       SST_SSP_SLOT_CTL(xpname, "rx deinterleaver", channel_name, channel_no, false, \
+                        slot_names, sst_slot_get, sst_slot_put)
+
+static const struct snd_kcontrol_new sst_slot_controls[] = {
+       SST_INTERLEAVER("codec_out", "slot 0", 0),
+       SST_INTERLEAVER("codec_out", "slot 1", 1),
+       SST_INTERLEAVER("codec_out", "slot 2", 2),
+       SST_INTERLEAVER("codec_out", "slot 3", 3),
+       SST_DEINTERLEAVER("codec_in", "codec_in0_0", 0),
+       SST_DEINTERLEAVER("codec_in", "codec_in0_1", 1),
+       SST_DEINTERLEAVER("codec_in", "codec_in1_0", 2),
+       SST_DEINTERLEAVER("codec_in", "codec_in1_1", 3),
+};
+
+/* Gain helper with min/max set */
+#define SST_GAIN(name, path_id, task_id, instance, gain_var)                           \
+       SST_GAIN_KCONTROLS(name, "Gain", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE,        \
+               SST_GAIN_TC_MIN, SST_GAIN_TC_MAX,                                       \
+               sst_gain_get, sst_gain_put,                                             \
+               SST_MODULE_ID_GAIN_CELL, path_id, instance, task_id,                    \
+               sst_gain_tlv_common, gain_var)
+
+#define SST_VOLUME(name, path_id, task_id, instance, gain_var)                         \
+       SST_GAIN_KCONTROLS(name, "Volume", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE,      \
+               SST_GAIN_TC_MIN, SST_GAIN_TC_MAX,                                       \
+               sst_gain_get, sst_gain_put,                                             \
+               SST_MODULE_ID_VOLUME, path_id, instance, task_id,                       \
+               sst_gain_tlv_common, gain_var)
+
+static struct sst_gain_value sst_gains[];
+
+static const struct snd_kcontrol_new sst_gain_controls[] = {
+       SST_GAIN("media0_in", SST_PATH_INDEX_MEDIA0_IN, SST_TASK_MMX, 0, &sst_gains[0]),
+       SST_GAIN("media1_in", SST_PATH_INDEX_MEDIA1_IN, SST_TASK_MMX, 0, &sst_gains[1]),
+       SST_GAIN("media2_in", SST_PATH_INDEX_MEDIA2_IN, SST_TASK_MMX, 0, &sst_gains[2]),
+       SST_GAIN("media3_in", SST_PATH_INDEX_MEDIA3_IN, SST_TASK_MMX, 0, &sst_gains[3]),
+
+       SST_GAIN("pcm0_in", SST_PATH_INDEX_PCM0_IN, SST_TASK_SBA, 0, &sst_gains[4]),
+       SST_GAIN("pcm1_in", SST_PATH_INDEX_PCM1_IN, SST_TASK_SBA, 0, &sst_gains[5]),
+       SST_GAIN("pcm1_out", SST_PATH_INDEX_PCM1_OUT, SST_TASK_SBA, 0, &sst_gains[6]),
+       SST_GAIN("pcm2_out", SST_PATH_INDEX_PCM2_OUT, SST_TASK_SBA, 0, &sst_gains[7]),
+
+       SST_GAIN("codec_in0", SST_PATH_INDEX_CODEC_IN0, SST_TASK_SBA, 0, &sst_gains[8]),
+       SST_GAIN("codec_in1", SST_PATH_INDEX_CODEC_IN1, SST_TASK_SBA, 0, &sst_gains[9]),
+       SST_GAIN("codec_out0", SST_PATH_INDEX_CODEC_OUT0, SST_TASK_SBA, 0, &sst_gains[10]),
+       SST_GAIN("codec_out1", SST_PATH_INDEX_CODEC_OUT1, SST_TASK_SBA, 0, &sst_gains[11]),
+       SST_GAIN("media_loop1_out", SST_PATH_INDEX_MEDIA_LOOP1_OUT, SST_TASK_SBA, 0, &sst_gains[12]),
+       SST_GAIN("media_loop2_out", SST_PATH_INDEX_MEDIA_LOOP2_OUT, SST_TASK_SBA, 0, &sst_gains[13]),
+       SST_GAIN("sprot_loop_out", SST_PATH_INDEX_SPROT_LOOP_OUT, SST_TASK_SBA, 0, &sst_gains[14]),
+       SST_VOLUME("media0_in", SST_PATH_INDEX_MEDIA0_IN, SST_TASK_MMX, 0, &sst_gains[15]),
+};
+
+#define SST_GAIN_NUM_CONTROLS 3
+/* the SST_GAIN macro above will create three alsa controls for each
+ * instance invoked, gain, mute and ramp duration, which use the same gain
+ * cell sst_gain to keep track of data
+ * To calculate number of gain cell instances we need to device by 3 in
+ * below caulcation for gain cell memory.
+ * This gets rid of static number and issues while adding new controls
+ */
+static struct sst_gain_value sst_gains[ARRAY_SIZE(sst_gain_controls)/SST_GAIN_NUM_CONTROLS];
+
+static const struct snd_kcontrol_new sst_algo_controls[] = {
+       SST_ALGO_KCONTROL_BYTES("media_loop1_out", "fir", 272, SST_MODULE_ID_FIR_24,
+                SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_VB_SET_FIR),
+       SST_ALGO_KCONTROL_BYTES("media_loop1_out", "iir", 300, SST_MODULE_ID_IIR_24,
+               SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
+       SST_ALGO_KCONTROL_BYTES("media_loop1_out", "mdrp", 286, SST_MODULE_ID_MDRP,
+               SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_SET_MDRP),
+       SST_ALGO_KCONTROL_BYTES("media_loop2_out", "fir", 272, SST_MODULE_ID_FIR_24,
+               SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_VB_SET_FIR),
+       SST_ALGO_KCONTROL_BYTES("media_loop2_out", "iir", 300, SST_MODULE_ID_IIR_24,
+               SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
+       SST_ALGO_KCONTROL_BYTES("media_loop2_out", "mdrp", 286, SST_MODULE_ID_MDRP,
+               SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_SET_MDRP),
+       SST_ALGO_KCONTROL_BYTES("sprot_loop_out", "lpro", 192, SST_MODULE_ID_SPROT,
+               SST_PATH_INDEX_SPROT_LOOP_OUT, 0, SST_TASK_SBA, SBA_VB_LPRO),
+       SST_ALGO_KCONTROL_BYTES("codec_in0", "dcr", 52, SST_MODULE_ID_FILT_DCR,
+               SST_PATH_INDEX_CODEC_IN0, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
+       SST_ALGO_KCONTROL_BYTES("codec_in1", "dcr", 52, SST_MODULE_ID_FILT_DCR,
+               SST_PATH_INDEX_CODEC_IN1, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
+
+};
+
+static int sst_algo_control_init(struct device *dev)
+{
+       int i = 0;
+       struct sst_algo_control *bc;
+       /*allocate space to cache the algo parameters in the driver*/
+       for (i = 0; i < ARRAY_SIZE(sst_algo_controls); i++) {
+               bc = (struct sst_algo_control *)sst_algo_controls[i].private_value;
+               bc->params = devm_kzalloc(dev, bc->max, GFP_KERNEL);
+               if (bc->params == NULL)
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
+static bool is_sst_dapm_widget(struct snd_soc_dapm_widget *w)
+{
+       switch (w->id) {
+       case snd_soc_dapm_pga:
+       case snd_soc_dapm_aif_in:
+       case snd_soc_dapm_aif_out:
+       case snd_soc_dapm_input:
+       case snd_soc_dapm_output:
+       case snd_soc_dapm_mixer:
+               return true;
+       default:
+               return false;
+       }
+}
+
+/**
+ * sst_send_pipe_gains - send gains for the front-end DAIs
+ *
+ * The gains in the pipes connected to the front-ends are muted/unmuted
+ * automatically via the digital_mute() DAPM callback. This function sends the
+ * gains for the front-end pipes.
+ */
+int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute)
+{
+       struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
+       struct snd_soc_dapm_widget *w;
+       struct snd_soc_dapm_path *p = NULL;
+
+       dev_dbg(dai->dev, "enter, dai-name=%s dir=%d\n", dai->name, stream);
+
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               dev_dbg(dai->dev, "Stream name=%s\n",
+                               dai->playback_widget->name);
+               w = dai->playback_widget;
+               list_for_each_entry(p, &w->sinks, list_source) {
+                       if (p->connected && !p->connected(w, p->sink))
+                               continue;
+
+                       if (p->connect && p->sink->power &&
+                                       is_sst_dapm_widget(p->sink)) {
+                               struct sst_ids *ids = p->sink->priv;
+
+                               dev_dbg(dai->dev, "send gains for widget=%s\n",
+                                               p->sink->name);
+                               mutex_lock(&drv->lock);
+                               sst_set_pipe_gain(ids, drv, mute);
+                               mutex_unlock(&drv->lock);
+                       }
+               }
+       } else {
+               dev_dbg(dai->dev, "Stream name=%s\n",
+                               dai->capture_widget->name);
+               w = dai->capture_widget;
+               list_for_each_entry(p, &w->sources, list_sink) {
+                       if (p->connected && !p->connected(w, p->sink))
+                               continue;
+
+                       if (p->connect &&  p->source->power &&
+                                       is_sst_dapm_widget(p->source)) {
+                               struct sst_ids *ids = p->source->priv;
+
+                               dev_dbg(dai->dev, "send gain for widget=%s\n",
+                                               p->source->name);
+                               mutex_lock(&drv->lock);
+                               sst_set_pipe_gain(ids, drv, mute);
+                               mutex_unlock(&drv->lock);
+                       }
+               }
+       }
+       return 0;
+}
+
+/**
+ * sst_fill_module_list - populate the list of modules/gains for a pipe
+ *
+ *
+ * Fills the widget pointer in the kcontrol private data, and also fills the
+ * kcontrol pointer in the widget private data.
+ *
+ * Widget pointer is used to send the algo/gain in the .put() handler if the
+ * widget is powerd on.
+ *
+ * Kcontrol pointer is used to send the algo/gain in the widget power ON/OFF
+ * event handler. Each widget (pipe) has multiple algos stored in the algo_list.
+ */
+static int sst_fill_module_list(struct snd_kcontrol *kctl,
+        struct snd_soc_dapm_widget *w, int type)
+{
+       struct sst_module *module = NULL;
+       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+       struct sst_ids *ids = w->priv;
+       int ret = 0;
+
+       module = devm_kzalloc(c->dev, sizeof(*module), GFP_KERNEL);
+       if (!module)
+               return -ENOMEM;
+
+       if (type == SST_MODULE_GAIN) {
+               struct sst_gain_mixer_control *mc = (void *)kctl->private_value;
+
+               mc->w = w;
+               module->kctl = kctl;
+               list_add_tail(&module->node, &ids->gain_list);
+       } else if (type == SST_MODULE_ALGO) {
+               struct sst_algo_control *bc = (void *)kctl->private_value;
+
+               bc->w = w;
+               module->kctl = kctl;
+               list_add_tail(&module->node, &ids->algo_list);
+       } else {
+               dev_err(c->dev, "invoked for unknown type %d module %s",
+                               type, kctl->id.name);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/**
+ * sst_fill_widget_module_info - fill list of gains/algos for the pipe
+ * @widget:    pipe modelled as a DAPM widget
+ *
+ * Fill the list of gains/algos for the widget by looking at all the card
+ * controls and comparing the name of the widget with the first part of control
+ * name. First part of control name contains the pipe name (widget name).
+ */
+static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
+       struct snd_soc_platform *platform)
+{
+       struct snd_kcontrol *kctl;
+       int index, ret = 0;
+       struct snd_card *card = platform->component.card->snd_card;
+       char *idx;
+
+       down_read(&card->controls_rwsem);
+
+       list_for_each_entry(kctl, &card->controls, list) {
+               idx = strstr(kctl->id.name, " ");
+               if (idx == NULL)
+                       continue;
+               index  = strlen(kctl->id.name) - strlen(idx);
+
+               if (strstr(kctl->id.name, "Volume") &&
+                   !strncmp(kctl->id.name, w->name, index))
+                       ret = sst_fill_module_list(kctl, w, SST_MODULE_GAIN);
+
+               else if (strstr(kctl->id.name, "params") &&
+                        !strncmp(kctl->id.name, w->name, index))
+                       ret = sst_fill_module_list(kctl, w, SST_MODULE_ALGO);
+
+               else if (strstr(kctl->id.name, "Switch") &&
+                        !strncmp(kctl->id.name, w->name, index) &&
+                        strstr(kctl->id.name, "Gain")) {
+                       struct sst_gain_mixer_control *mc =
+                                               (void *)kctl->private_value;
+
+                       mc->w = w;
+
+               } else if (strstr(kctl->id.name, "interleaver") &&
+                        !strncmp(kctl->id.name, w->name, index)) {
+                       struct sst_enum *e = (void *)kctl->private_value;
+
+                       e->w = w;
+
+               } else if (strstr(kctl->id.name, "deinterleaver") &&
+                        !strncmp(kctl->id.name, w->name, index)) {
+
+                       struct sst_enum *e = (void *)kctl->private_value;
+
+                       e->w = w;
+               }
+
+               if (ret < 0) {
+                       up_read(&card->controls_rwsem);
+                       return ret;
+               }
+       }
+
+       up_read(&card->controls_rwsem);
+       return 0;
+}
+
+/**
+ * sst_fill_linked_widgets - fill the parent pointer for the linked widget
+ */
+static void sst_fill_linked_widgets(struct snd_soc_platform *platform,
+                                               struct sst_ids *ids)
+{
+       struct snd_soc_dapm_widget *w;
+       unsigned int len = strlen(ids->parent_wname);
+
+       list_for_each_entry(w, &platform->component.card->widgets, list) {
+               if (!strncmp(ids->parent_wname, w->name, len)) {
+                       ids->parent_w = w;
+                       break;
+               }
+       }
+}
+
+/**
+ * sst_map_modules_to_pipe - fill algo/gains list for all pipes
+ */
+static int sst_map_modules_to_pipe(struct snd_soc_platform *platform)
+{
+       struct snd_soc_dapm_widget *w;
+       int ret = 0;
+
+       list_for_each_entry(w, &platform->component.card->widgets, list) {
+               if (is_sst_dapm_widget(w) && (w->priv)) {
+                       struct sst_ids *ids = w->priv;
+
+                       dev_dbg(platform->dev, "widget type=%d name=%s\n",
+                                       w->id, w->name);
+                       INIT_LIST_HEAD(&ids->algo_list);
+                       INIT_LIST_HEAD(&ids->gain_list);
+                       ret = sst_fill_widget_module_info(w, platform);
+
+                       if (ret < 0)
+                               return ret;
+
+                       /* fill linked widgets */
+                       if (ids->parent_wname !=  NULL)
+                               sst_fill_linked_widgets(platform, ids);
+               }
+       }
+       return 0;
+}
+
+int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform)
+{
+       int i, ret = 0;
+       struct snd_soc_dapm_context *dapm =
+                       snd_soc_component_get_dapm(&platform->component);
+       struct sst_data *drv = snd_soc_platform_get_drvdata(platform);
+       unsigned int gains = ARRAY_SIZE(sst_gain_controls)/3;
+
+       drv->byte_stream = devm_kzalloc(platform->dev,
+                                       SST_MAX_BIN_BYTES, GFP_KERNEL);
+       if (!drv->byte_stream)
+               return -ENOMEM;
+
+       snd_soc_dapm_new_controls(dapm, sst_dapm_widgets,
+                       ARRAY_SIZE(sst_dapm_widgets));
+       snd_soc_dapm_add_routes(dapm, intercon,
+                       ARRAY_SIZE(intercon));
+       snd_soc_dapm_new_widgets(dapm->card);
+
+       for (i = 0; i < gains; i++) {
+               sst_gains[i].mute = SST_GAIN_MUTE_DEFAULT;
+               sst_gains[i].l_gain = SST_GAIN_VOLUME_DEFAULT;
+               sst_gains[i].r_gain = SST_GAIN_VOLUME_DEFAULT;
+               sst_gains[i].ramp_duration = SST_GAIN_RAMP_DURATION_DEFAULT;
+       }
+
+       ret = snd_soc_add_platform_controls(platform, sst_gain_controls,
+                       ARRAY_SIZE(sst_gain_controls));
+       if (ret)
+               return ret;
+
+       /* Initialize algo control params */
+       ret = sst_algo_control_init(platform->dev);
+       if (ret)
+               return ret;
+       ret = snd_soc_add_platform_controls(platform, sst_algo_controls,
+                       ARRAY_SIZE(sst_algo_controls));
+       if (ret)
+               return ret;
+
+       ret = snd_soc_add_platform_controls(platform, sst_slot_controls,
+                       ARRAY_SIZE(sst_slot_controls));
+       if (ret)
+               return ret;
+
+       ret = sst_map_modules_to_pipe(platform);
+
+       return ret;
+}
diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h
new file mode 100644 (file)
index 0000000..daecc58
--- /dev/null
@@ -0,0 +1,870 @@
+/*
+ *  sst-atom-controls.h - Intel MID Platform driver header file
+ *
+ *  Copyright (C) 2013-14 Intel Corp
+ *  Author: Ramesh Babu <ramesh.babu.koul@intel.com>
+ *     Omair M Abdullah <omair.m.abdullah@intel.com>
+ *     Samreen Nilofer <samreen.nilofer@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#ifndef __SST_ATOM_CONTROLS_H__
+#define __SST_ATOM_CONTROLS_H__
+
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+enum {
+       MERR_DPCM_AUDIO = 0,
+       MERR_DPCM_COMPR,
+};
+
+/* define a bit for each mixer input */
+#define SST_MIX_IP(x)          (x)
+
+#define SST_IP_CODEC0          SST_MIX_IP(2)
+#define SST_IP_CODEC1          SST_MIX_IP(3)
+#define SST_IP_LOOP0           SST_MIX_IP(4)
+#define SST_IP_LOOP1           SST_MIX_IP(5)
+#define SST_IP_LOOP2           SST_MIX_IP(6)
+#define SST_IP_PROBE           SST_MIX_IP(7)
+#define SST_IP_VOIP            SST_MIX_IP(12)
+#define SST_IP_PCM0            SST_MIX_IP(13)
+#define SST_IP_PCM1            SST_MIX_IP(14)
+#define SST_IP_MEDIA0          SST_MIX_IP(17)
+#define SST_IP_MEDIA1          SST_MIX_IP(18)
+#define SST_IP_MEDIA2          SST_MIX_IP(19)
+#define SST_IP_MEDIA3          SST_MIX_IP(20)
+
+#define SST_IP_LAST            SST_IP_MEDIA3
+
+#define SST_SWM_INPUT_COUNT    (SST_IP_LAST + 1)
+#define SST_CMD_SWM_MAX_INPUTS 6
+
+#define SST_PATH_ID_SHIFT      8
+#define SST_DEFAULT_LOCATION_ID        0xFFFF
+#define SST_DEFAULT_CELL_NBR   0xFF
+#define SST_DEFAULT_MODULE_ID  0xFFFF
+
+/*
+ * Audio DSP Path Ids. Specified by the audio DSP FW
+ */
+enum sst_path_index {
+       SST_PATH_INDEX_CODEC_OUT0               = (0x02 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_CODEC_OUT1               = (0x03 << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_SPROT_LOOP_OUT           = (0x04 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA_LOOP1_OUT          = (0x05 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA_LOOP2_OUT          = (0x06 << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_VOIP_OUT                 = (0x0C << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_PCM0_OUT                 = (0x0D << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_PCM1_OUT                 = (0x0E << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_PCM2_OUT                 = (0x0F << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_MEDIA0_OUT               = (0x12 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA1_OUT               = (0x13 << SST_PATH_ID_SHIFT),
+
+
+       /* Start of input paths */
+       SST_PATH_INDEX_CODEC_IN0                = (0x82 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_CODEC_IN1                = (0x83 << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_SPROT_LOOP_IN            = (0x84 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA_LOOP1_IN           = (0x85 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA_LOOP2_IN           = (0x86 << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_VOIP_IN                  = (0x8C << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_PCM0_IN                  = (0x8D << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_PCM1_IN                  = (0x8E << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_MEDIA0_IN                = (0x8F << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA1_IN                = (0x90 << SST_PATH_ID_SHIFT),
+       SST_PATH_INDEX_MEDIA2_IN                = (0x91 << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_MEDIA3_IN                = (0x9C << SST_PATH_ID_SHIFT),
+
+       SST_PATH_INDEX_RESERVED                 = (0xFF << SST_PATH_ID_SHIFT),
+};
+
+/*
+ * path IDs
+ */
+enum sst_swm_inputs {
+       SST_SWM_IN_CODEC0       = (SST_PATH_INDEX_CODEC_IN0       | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_CODEC1       = (SST_PATH_INDEX_CODEC_IN1       | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_SPROT_LOOP   = (SST_PATH_INDEX_SPROT_LOOP_IN   | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_MEDIA_LOOP1  = (SST_PATH_INDEX_MEDIA_LOOP1_IN  | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_MEDIA_LOOP2  = (SST_PATH_INDEX_MEDIA_LOOP2_IN  | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_VOIP         = (SST_PATH_INDEX_VOIP_IN         | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_PCM0         = (SST_PATH_INDEX_PCM0_IN         | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_PCM1         = (SST_PATH_INDEX_PCM1_IN         | SST_DEFAULT_CELL_NBR),
+       SST_SWM_IN_MEDIA0       = (SST_PATH_INDEX_MEDIA0_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
+       SST_SWM_IN_MEDIA1       = (SST_PATH_INDEX_MEDIA1_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
+       SST_SWM_IN_MEDIA2       = (SST_PATH_INDEX_MEDIA2_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
+       SST_SWM_IN_MEDIA3       = (SST_PATH_INDEX_MEDIA3_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
+       SST_SWM_IN_END          = (SST_PATH_INDEX_RESERVED        | SST_DEFAULT_CELL_NBR)
+};
+
+/*
+ * path IDs
+ */
+enum sst_swm_outputs {
+       SST_SWM_OUT_CODEC0      = (SST_PATH_INDEX_CODEC_OUT0      | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_CODEC1      = (SST_PATH_INDEX_CODEC_OUT1      | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_SPROT_LOOP  = (SST_PATH_INDEX_SPROT_LOOP_OUT  | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_OUT | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_OUT | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_VOIP        = (SST_PATH_INDEX_VOIP_OUT        | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_PCM0        = (SST_PATH_INDEX_PCM0_OUT        | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_PCM1        = (SST_PATH_INDEX_PCM1_OUT        | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_PCM2        = (SST_PATH_INDEX_PCM2_OUT        | SST_DEFAULT_CELL_NBR),
+       SST_SWM_OUT_MEDIA0      = (SST_PATH_INDEX_MEDIA0_OUT      | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
+       SST_SWM_OUT_MEDIA1      = (SST_PATH_INDEX_MEDIA1_OUT      | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
+       SST_SWM_OUT_END         = (SST_PATH_INDEX_RESERVED        | SST_DEFAULT_CELL_NBR),
+};
+
+enum sst_ipc_msg {
+       SST_IPC_IA_CMD = 1,
+       SST_IPC_IA_SET_PARAMS,
+       SST_IPC_IA_GET_PARAMS,
+};
+
+enum sst_cmd_type {
+       SST_CMD_BYTES_SET = 1,
+       SST_CMD_BYTES_GET = 2,
+};
+
+enum sst_task {
+       SST_TASK_SBA = 1,
+       SST_TASK_MMX = 3,
+};
+
+enum sst_type {
+       SST_TYPE_CMD = 1,
+       SST_TYPE_PARAMS,
+};
+
+enum sst_flag {
+       SST_FLAG_BLOCKED = 1,
+       SST_FLAG_NONBLOCK,
+};
+
+/*
+ * Enumeration for indexing the gain cells in VB_SET_GAIN DSP command
+ */
+enum sst_gain_index {
+       /* GAIN IDs for SB task start here */
+       SST_GAIN_INDEX_CODEC_OUT0,
+       SST_GAIN_INDEX_CODEC_OUT1,
+       SST_GAIN_INDEX_CODEC_IN0,
+       SST_GAIN_INDEX_CODEC_IN1,
+
+       SST_GAIN_INDEX_SPROT_LOOP_OUT,
+       SST_GAIN_INDEX_MEDIA_LOOP1_OUT,
+       SST_GAIN_INDEX_MEDIA_LOOP2_OUT,
+
+       SST_GAIN_INDEX_PCM0_IN_LEFT,
+       SST_GAIN_INDEX_PCM0_IN_RIGHT,
+
+       SST_GAIN_INDEX_PCM1_OUT_LEFT,
+       SST_GAIN_INDEX_PCM1_OUT_RIGHT,
+       SST_GAIN_INDEX_PCM1_IN_LEFT,
+       SST_GAIN_INDEX_PCM1_IN_RIGHT,
+       SST_GAIN_INDEX_PCM2_OUT_LEFT,
+
+       SST_GAIN_INDEX_PCM2_OUT_RIGHT,
+       SST_GAIN_INDEX_VOIP_OUT,
+       SST_GAIN_INDEX_VOIP_IN,
+
+       /* Gain IDs for MMX task start here */
+       SST_GAIN_INDEX_MEDIA0_IN_LEFT,
+       SST_GAIN_INDEX_MEDIA0_IN_RIGHT,
+       SST_GAIN_INDEX_MEDIA1_IN_LEFT,
+       SST_GAIN_INDEX_MEDIA1_IN_RIGHT,
+
+       SST_GAIN_INDEX_MEDIA2_IN_LEFT,
+       SST_GAIN_INDEX_MEDIA2_IN_RIGHT,
+
+       SST_GAIN_INDEX_GAIN_END
+};
+
+/*
+ * Audio DSP module IDs specified by FW spec
+ * TODO: Update with all modules
+ */
+enum sst_module_id {
+       SST_MODULE_ID_PCM                 = 0x0001,
+       SST_MODULE_ID_MP3                 = 0x0002,
+       SST_MODULE_ID_MP24                = 0x0003,
+       SST_MODULE_ID_AAC                 = 0x0004,
+       SST_MODULE_ID_AACP                = 0x0005,
+       SST_MODULE_ID_EAACP               = 0x0006,
+       SST_MODULE_ID_WMA9                = 0x0007,
+       SST_MODULE_ID_WMA10               = 0x0008,
+       SST_MODULE_ID_WMA10P              = 0x0009,
+       SST_MODULE_ID_RA                  = 0x000A,
+       SST_MODULE_ID_DDAC3               = 0x000B,
+       SST_MODULE_ID_TRUE_HD             = 0x000C,
+       SST_MODULE_ID_HD_PLUS             = 0x000D,
+
+       SST_MODULE_ID_SRC                 = 0x0064,
+       SST_MODULE_ID_DOWNMIX             = 0x0066,
+       SST_MODULE_ID_GAIN_CELL           = 0x0067,
+       SST_MODULE_ID_SPROT               = 0x006D,
+       SST_MODULE_ID_BASS_BOOST          = 0x006E,
+       SST_MODULE_ID_STEREO_WDNG         = 0x006F,
+       SST_MODULE_ID_AV_REMOVAL          = 0x0070,
+       SST_MODULE_ID_MIC_EQ              = 0x0071,
+       SST_MODULE_ID_SPL                 = 0x0072,
+       SST_MODULE_ID_ALGO_VTSV           = 0x0073,
+       SST_MODULE_ID_NR                  = 0x0076,
+       SST_MODULE_ID_BWX                 = 0x0077,
+       SST_MODULE_ID_DRP                 = 0x0078,
+       SST_MODULE_ID_MDRP                = 0x0079,
+
+       SST_MODULE_ID_ANA                 = 0x007A,
+       SST_MODULE_ID_AEC                 = 0x007B,
+       SST_MODULE_ID_NR_SNS              = 0x007C,
+       SST_MODULE_ID_SER                 = 0x007D,
+       SST_MODULE_ID_AGC                 = 0x007E,
+
+       SST_MODULE_ID_CNI                 = 0x007F,
+       SST_MODULE_ID_CONTEXT_ALGO_AWARE  = 0x0080,
+       SST_MODULE_ID_FIR_24              = 0x0081,
+       SST_MODULE_ID_IIR_24              = 0x0082,
+
+       SST_MODULE_ID_ASRC                = 0x0083,
+       SST_MODULE_ID_TONE_GEN            = 0x0084,
+       SST_MODULE_ID_BMF                 = 0x0086,
+       SST_MODULE_ID_EDL                 = 0x0087,
+       SST_MODULE_ID_GLC                 = 0x0088,
+
+       SST_MODULE_ID_FIR_16              = 0x0089,
+       SST_MODULE_ID_IIR_16              = 0x008A,
+       SST_MODULE_ID_DNR                 = 0x008B,
+
+       SST_MODULE_ID_VIRTUALIZER         = 0x008C,
+       SST_MODULE_ID_VISUALIZATION       = 0x008D,
+       SST_MODULE_ID_LOUDNESS_OPTIMIZER  = 0x008E,
+       SST_MODULE_ID_REVERBERATION       = 0x008F,
+
+       SST_MODULE_ID_CNI_TX              = 0x0090,
+       SST_MODULE_ID_REF_LINE            = 0x0091,
+       SST_MODULE_ID_VOLUME              = 0x0092,
+       SST_MODULE_ID_FILT_DCR            = 0x0094,
+       SST_MODULE_ID_SLV                 = 0x009A,
+       SST_MODULE_ID_NLF                 = 0x009B,
+       SST_MODULE_ID_TNR                 = 0x009C,
+       SST_MODULE_ID_WNR                 = 0x009D,
+
+       SST_MODULE_ID_LOG                 = 0xFF00,
+
+       SST_MODULE_ID_TASK                = 0xFFFF,
+};
+
+enum sst_cmd {
+       SBA_IDLE                = 14,
+       SBA_VB_SET_SPEECH_PATH  = 26,
+       MMX_SET_GAIN            = 33,
+       SBA_VB_SET_GAIN         = 33,
+       FBA_VB_RX_CNI           = 35,
+       MMX_SET_GAIN_TIMECONST  = 36,
+       SBA_VB_SET_TIMECONST    = 36,
+       SBA_VB_START            = 85,
+       SBA_SET_SWM             = 114,
+       SBA_SET_MDRP            = 116,
+       SBA_HW_SET_SSP          = 117,
+       SBA_SET_MEDIA_LOOP_MAP  = 118,
+       SBA_SET_MEDIA_PATH      = 119,
+       MMX_SET_MEDIA_PATH      = 119,
+       SBA_VB_LPRO             = 126,
+       SBA_VB_SET_FIR          = 128,
+       SBA_VB_SET_IIR          = 129,
+       SBA_SET_SSP_SLOT_MAP    = 130,
+};
+
+enum sst_dsp_switch {
+       SST_SWITCH_OFF = 0,
+       SST_SWITCH_ON = 3,
+};
+
+enum sst_path_switch {
+       SST_PATH_OFF = 0,
+       SST_PATH_ON = 1,
+};
+
+enum sst_swm_state {
+       SST_SWM_OFF = 0,
+       SST_SWM_ON = 3,
+};
+
+#define SST_FILL_LOCATION_IDS(dst, cell_idx, pipe_id)          do {    \
+               dst.location_id.p.cell_nbr_idx = (cell_idx);            \
+               dst.location_id.p.path_id = (pipe_id);                  \
+       } while (0)
+#define SST_FILL_LOCATION_ID(dst, loc_id)                              (\
+       dst.location_id.f = (loc_id))
+#define SST_FILL_MODULE_ID(dst, mod_id)                                        (\
+       dst.module_id = (mod_id))
+
+#define SST_FILL_DESTINATION1(dst, id)                         do {    \
+               SST_FILL_LOCATION_ID(dst, (id) & 0xFFFF);               \
+               SST_FILL_MODULE_ID(dst, ((id) & 0xFFFF0000) >> 16);     \
+       } while (0)
+#define SST_FILL_DESTINATION2(dst, loc_id, mod_id)             do {    \
+               SST_FILL_LOCATION_ID(dst, loc_id);                      \
+               SST_FILL_MODULE_ID(dst, mod_id);                        \
+       } while (0)
+#define SST_FILL_DESTINATION3(dst, cell_idx, path_id, mod_id)  do {    \
+               SST_FILL_LOCATION_IDS(dst, cell_idx, path_id);          \
+               SST_FILL_MODULE_ID(dst, mod_id);                        \
+       } while (0)
+
+#define SST_FILL_DESTINATION(level, dst, ...)                          \
+       SST_FILL_DESTINATION##level(dst, __VA_ARGS__)
+#define SST_FILL_DEFAULT_DESTINATION(dst)                              \
+       SST_FILL_DESTINATION(2, dst, SST_DEFAULT_LOCATION_ID, SST_DEFAULT_MODULE_ID)
+
+struct sst_destination_id {
+       union sst_location_id {
+               struct {
+                       u8 cell_nbr_idx;        /* module index */
+                       u8 path_id;             /* pipe_id */
+               } __packed      p;              /* part */
+               u16             f;              /* full */
+       } __packed location_id;
+       u16        module_id;
+} __packed;
+struct sst_dsp_header {
+       struct sst_destination_id dst;
+       u16 command_id;
+       u16 length;
+} __packed;
+
+/*
+ *
+ * Common Commands
+ *
+ */
+struct sst_cmd_generic {
+       struct sst_dsp_header header;
+} __packed;
+
+struct swm_input_ids {
+       struct sst_destination_id input_id;
+} __packed;
+
+struct sst_cmd_set_swm {
+       struct sst_dsp_header header;
+       struct sst_destination_id output_id;
+       u16    switch_state;
+       u16    nb_inputs;
+       struct swm_input_ids input[SST_CMD_SWM_MAX_INPUTS];
+} __packed;
+
+struct sst_cmd_set_media_path {
+       struct sst_dsp_header header;
+       u16    switch_state;
+} __packed;
+
+struct pcm_cfg {
+               u8 s_length:2;
+               u8 rate:3;
+               u8 format:3;
+} __packed;
+
+struct sst_cmd_set_speech_path {
+       struct sst_dsp_header header;
+       u16    switch_state;
+       struct {
+               u16 rsvd:8;
+               struct pcm_cfg cfg;
+       } config;
+} __packed;
+
+struct gain_cell {
+       struct sst_destination_id dest;
+       s16 cell_gain_left;
+       s16 cell_gain_right;
+       u16 gain_time_constant;
+} __packed;
+
+#define NUM_GAIN_CELLS 1
+struct sst_cmd_set_gain_dual {
+       struct sst_dsp_header header;
+       u16    gain_cell_num;
+       struct gain_cell cell_gains[NUM_GAIN_CELLS];
+} __packed;
+struct sst_cmd_set_params {
+       struct sst_destination_id dst;
+       u16 command_id;
+       char params[0];
+} __packed;
+
+
+struct sst_cmd_sba_vb_start {
+       struct sst_dsp_header header;
+} __packed;
+
+union sba_media_loop_params {
+       struct {
+               u16 rsvd:8;
+               struct pcm_cfg cfg;
+       } part;
+       u16 full;
+} __packed;
+
+struct sst_cmd_sba_set_media_loop_map {
+       struct  sst_dsp_header header;
+       u16     switch_state;
+       union   sba_media_loop_params param;
+       u16     map;
+} __packed;
+
+struct sst_cmd_tone_stop {
+       struct  sst_dsp_header header;
+       u16     switch_state;
+} __packed;
+
+enum sst_ssp_mode {
+       SSP_MODE_MASTER = 0,
+       SSP_MODE_SLAVE = 1,
+};
+
+enum sst_ssp_pcm_mode {
+       SSP_PCM_MODE_NORMAL = 0,
+       SSP_PCM_MODE_NETWORK = 1,
+};
+
+enum sst_ssp_duplex {
+       SSP_DUPLEX = 0,
+       SSP_RX = 1,
+       SSP_TX = 2,
+};
+
+enum sst_ssp_fs_frequency {
+       SSP_FS_8_KHZ = 0,
+       SSP_FS_16_KHZ = 1,
+       SSP_FS_44_1_KHZ = 2,
+       SSP_FS_48_KHZ = 3,
+};
+
+enum sst_ssp_fs_polarity {
+       SSP_FS_ACTIVE_LOW = 0,
+       SSP_FS_ACTIVE_HIGH = 1,
+};
+
+enum sst_ssp_protocol {
+       SSP_MODE_PCM = 0,
+       SSP_MODE_I2S = 1,
+};
+
+enum sst_ssp_port_id {
+       SSP_MODEM = 0,
+       SSP_BT = 1,
+       SSP_FM = 2,
+       SSP_CODEC = 3,
+};
+
+struct sst_cmd_sba_hw_set_ssp {
+       struct sst_dsp_header header;
+       u16 selection;                  /* 0:SSP0(def), 1:SSP1, 2:SSP2 */
+
+       u16 switch_state;
+
+       u16 nb_bits_per_slots:6;        /* 0-32 bits, 24 (def) */
+       u16 nb_slots:4;                 /* 0-8: slots per frame  */
+       u16 mode:3;                     /* 0:Master, 1: Slave  */
+       u16 duplex:3;
+
+       u16 active_tx_slot_map:8;       /* Bit map, 0:off, 1:on */
+       u16 reserved1:8;
+
+       u16 active_rx_slot_map:8;       /* Bit map 0: Off, 1:On */
+       u16 reserved2:8;
+
+       u16 frame_sync_frequency;
+
+       u16 frame_sync_polarity:8;
+       u16 data_polarity:8;
+
+       u16 frame_sync_width;           /* 1 to N clocks */
+       u16 ssp_protocol:8;
+       u16 start_delay:8;              /* Start delay in terms of clock ticks */
+} __packed;
+
+#define SST_MAX_TDM_SLOTS 8
+
+struct sst_param_sba_ssp_slot_map {
+       struct sst_dsp_header header;
+
+       u16 param_id;
+       u16 param_len;
+       u16 ssp_index;
+
+       u8 rx_slot_map[SST_MAX_TDM_SLOTS];
+       u8 tx_slot_map[SST_MAX_TDM_SLOTS];
+} __packed;
+
+enum {
+       SST_PROBE_EXTRACTOR = 0,
+       SST_PROBE_INJECTOR = 1,
+};
+
+/**** widget defines *****/
+
+#define SST_MODULE_GAIN 1
+#define SST_MODULE_ALGO 2
+
+#define SST_FMT_MONO 0
+#define SST_FMT_STEREO 3
+
+/* physical SSP numbers */
+enum {
+       SST_SSP0 = 0,
+       SST_SSP1,
+       SST_SSP2,
+       SST_SSP_LAST = SST_SSP2,
+};
+
+#define SST_NUM_SSPS           (SST_SSP_LAST + 1)      /* physical SSPs */
+#define SST_MAX_SSP_MUX                2                       /* single SSP muxed between pipes */
+#define SST_MAX_SSP_DOMAINS    2                       /* domains present in each pipe */
+
+struct sst_module {
+       struct snd_kcontrol *kctl;
+       struct list_head node;
+};
+
+struct sst_ssp_config {
+       u8 ssp_id;
+       u8 bits_per_slot;
+       u8 slots;
+       u8 ssp_mode;
+       u8 pcm_mode;
+       u8 duplex;
+       u8 ssp_protocol;
+       u8 fs_frequency;
+       u8 active_slot_map;
+       u8 start_delay;
+       u16 fs_width;
+};
+
+struct sst_ssp_cfg {
+       const u8 ssp_number;
+       const int *mux_shift;
+       const int (*domain_shift)[SST_MAX_SSP_MUX];
+       const struct sst_ssp_config (*ssp_config)[SST_MAX_SSP_MUX][SST_MAX_SSP_DOMAINS];
+};
+
+struct sst_ids {
+       u16 location_id;
+       u16 module_id;
+       u8  task_id;
+       u8  format;
+       u8  reg;
+       const char *parent_wname;
+       struct snd_soc_dapm_widget *parent_w;
+       struct list_head algo_list;
+       struct list_head gain_list;
+       const struct sst_pcm_format *pcm_fmt;
+};
+
+
+#define SST_AIF_IN(wname, wevent)                                                      \
+{      .id = snd_soc_dapm_aif_in, .name = wname, .sname = NULL,                        \
+       .reg = SND_SOC_NOPM, .shift = 0,                                        \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
+       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
+}
+
+#define SST_AIF_OUT(wname, wevent)                                                     \
+{      .id = snd_soc_dapm_aif_out, .name = wname, .sname = NULL,                       \
+       .reg = SND_SOC_NOPM, .shift = 0,                                                \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
+       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
+}
+
+#define SST_INPUT(wname, wevent)                                                       \
+{      .id = snd_soc_dapm_input, .name = wname, .sname = NULL,                         \
+       .reg = SND_SOC_NOPM, .shift = 0,                                                \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
+       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
+}
+
+#define SST_OUTPUT(wname, wevent)                                                      \
+{      .id = snd_soc_dapm_output, .name = wname, .sname = NULL,                        \
+       .reg = SND_SOC_NOPM, .shift = 0,                                                \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
+       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
+}
+
+#define SST_DAPM_OUTPUT(wname, wloc_id, wtask_id, wformat, wevent)                      \
+{      .id = snd_soc_dapm_output, .name = wname, .sname = NULL,                        \
+       .reg = SND_SOC_NOPM, .shift = 0,                                                \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
+       .priv = (void *)&(struct sst_ids) { .location_id = wloc_id, .task_id = wtask_id,\
+                                               .pcm_fmt = wformat, }                   \
+}
+
+#define SST_PATH(wname, wtask, wloc_id, wevent, wflags)                                        \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
+       .kcontrol_news = NULL, .num_kcontrols = 0,                              \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = wflags,                                         \
+       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id, } \
+}
+
+#define SST_LINKED_PATH(wname, wtask, wloc_id, linked_wname, wevent, wflags)           \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
+       .kcontrol_news = NULL, .num_kcontrols = 0,                              \
+       .on_val = 1, .off_val = 0,                                                      \
+       .event = wevent, .event_flags = wflags,                                         \
+       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
+                                       .parent_wname = linked_wname}                   \
+}
+
+#define SST_PATH_MEDIA_LOOP(wname, wtask, wloc_id, wformat, wevent, wflags)             \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
+       .kcontrol_news = NULL, .num_kcontrols = 0,                         \
+       .event = wevent, .event_flags = wflags,                                         \
+       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
+                                           .format = wformat,}                         \
+}
+
+/* output is triggered before input */
+#define SST_PATH_INPUT(name, task_id, loc_id, event)                                   \
+       SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
+
+#define SST_PATH_LINKED_INPUT(name, task_id, loc_id, linked_wname, event)              \
+       SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,                     \
+                                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
+
+#define SST_PATH_OUTPUT(name, task_id, loc_id, event)                                  \
+       SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
+
+#define SST_PATH_LINKED_OUTPUT(name, task_id, loc_id, linked_wname, event)             \
+       SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,                     \
+                                       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
+
+#define SST_PATH_MEDIA_LOOP_OUTPUT(name, task_id, loc_id, format, event)               \
+       SST_PATH_MEDIA_LOOP(name, task_id, loc_id, format, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
+
+
+#define SST_SWM_MIXER(wname, wreg, wtask, wloc_id, wcontrols, wevent)                  \
+{      .id = snd_soc_dapm_mixer, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,       \
+       .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols),\
+       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD |  \
+                                       SND_SOC_DAPM_POST_REG,                          \
+       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
+                                           .reg = wreg }                               \
+}
+
+enum sst_gain_kcontrol_type {
+       SST_GAIN_TLV,
+       SST_GAIN_MUTE,
+       SST_GAIN_RAMP_DURATION,
+};
+
+struct sst_gain_mixer_control {
+       bool stereo;
+       enum sst_gain_kcontrol_type type;
+       struct sst_gain_value *gain_val;
+       int max;
+       int min;
+       u16 instance_id;
+       u16 module_id;
+       u16 pipe_id;
+       u16 task_id;
+       char pname[44];
+       struct snd_soc_dapm_widget *w;
+};
+
+struct sst_gain_value {
+       u16 ramp_duration;
+       s16 l_gain;
+       s16 r_gain;
+       bool mute;
+};
+#define SST_GAIN_VOLUME_DEFAULT                (-1440)
+#define SST_GAIN_RAMP_DURATION_DEFAULT 5 /* timeconstant */
+#define SST_GAIN_MUTE_DEFAULT          true
+
+#define SST_GAIN_KCONTROL_TLV(xname, xhandler_get, xhandler_put, \
+                             xmod, xpipe, xinstance, xtask, tlv_array, xgain_val, \
+                             xmin, xmax, xpname) \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+                 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+       .tlv.p = (tlv_array), \
+       .info = sst_gain_ctl_info,\
+       .get = xhandler_get, .put = xhandler_put, \
+       .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
+       { .stereo = true, .max = xmax, .min = xmin, .type = SST_GAIN_TLV, \
+         .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
+         .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
+
+#define SST_GAIN_KCONTROL_INT(xname, xhandler_get, xhandler_put, \
+                             xmod, xpipe, xinstance, xtask, xtype, xgain_val, \
+                             xmin, xmax, xpname) \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = sst_gain_ctl_info, \
+       .get = xhandler_get, .put = xhandler_put, \
+       .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
+       { .stereo = false, .max = xmax, .min = xmin, .type = xtype, \
+         .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
+         .instance_id = xinstance, .gain_val = xgain_val, .pname =  xpname}
+
+#define SST_GAIN_KCONTROL_BOOL(xname, xhandler_get, xhandler_put,\
+                              xmod, xpipe, xinstance, xtask, xgain_val, xpname) \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = snd_soc_info_bool_ext, \
+       .get = xhandler_get, .put = xhandler_put, \
+       .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
+       { .stereo = false, .type = SST_GAIN_MUTE, \
+         .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
+         .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
+#define SST_CONTROL_NAME(xpname, xmname, xinstance, xtype) \
+       xpname " " xmname " " #xinstance " " xtype
+
+#define SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, xtype, xsubmodule) \
+       xpname " " xmname " " #xinstance " " xtype " " xsubmodule
+
+/*
+ * 3 Controls for each Gain module
+ * e.g.        - pcm0_in Gain 0 Volume
+ *     - pcm0_in Gain 0 Ramp Delay
+ *     - pcm0_in Gain 0 Switch
+ */
+#define SST_GAIN_KCONTROLS(xpname, xmname, xmin_gain, xmax_gain, xmin_tc, xmax_tc, \
+                          xhandler_get, xhandler_put, \
+                          xmod, xpipe, xinstance, xtask, tlv_array, xgain_val) \
+       { SST_GAIN_KCONTROL_INT(SST_CONTROL_NAME(xpname, xmname, xinstance, "Ramp Delay"), \
+               xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, SST_GAIN_RAMP_DURATION, \
+               xgain_val, xmin_tc, xmax_tc, xpname) }, \
+       { SST_GAIN_KCONTROL_BOOL(SST_CONTROL_NAME(xpname, xmname, xinstance, "Switch"), \
+               xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, \
+               xgain_val, xpname) } ,\
+       { SST_GAIN_KCONTROL_TLV(SST_CONTROL_NAME(xpname, xmname, xinstance, "Volume"), \
+               xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, tlv_array, \
+               xgain_val, xmin_gain, xmax_gain, xpname) }
+
+#define SST_GAIN_TC_MIN                5
+#define SST_GAIN_TC_MAX                5000
+#define SST_GAIN_MIN_VALUE     -1440 /* in 0.1 DB units */
+#define SST_GAIN_MAX_VALUE     360
+
+enum sst_algo_kcontrol_type {
+       SST_ALGO_PARAMS,
+       SST_ALGO_BYPASS,
+};
+
+struct sst_algo_control {
+       enum sst_algo_kcontrol_type type;
+       int max;
+       u16 module_id;
+       u16 pipe_id;
+       u16 task_id;
+       u16 cmd_id;
+       bool bypass;
+       unsigned char *params;
+       struct snd_soc_dapm_widget *w;
+};
+
+/* size of the control = size of params + size of length field */
+#define SST_ALGO_CTL_VALUE(xcount, xtype, xpipe, xmod, xtask, xcmd)                    \
+       (struct sst_algo_control){                                                      \
+               .max = xcount + sizeof(u16), .type = xtype, .module_id = xmod,                  \
+               .pipe_id = xpipe, .task_id = xtask, .cmd_id = xcmd,                     \
+       }
+
+#define SST_ALGO_KCONTROL(xname, xcount, xmod, xpipe,                                  \
+                         xtask, xcmd, xtype, xinfo, xget, xput)                        \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                                            \
+       .name =  xname,                                                                 \
+       .info = xinfo, .get = xget, .put = xput,                                        \
+       .private_value = (unsigned long)&                                               \
+                       SST_ALGO_CTL_VALUE(xcount, xtype, xpipe,                        \
+                                          xmod, xtask, xcmd),                          \
+}
+
+#define SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod,                          \
+                               xpipe, xinstance, xtask, xcmd)                          \
+       SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "params"),        \
+                         xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,            \
+                         sst_algo_bytes_ctl_info,                                      \
+                         sst_algo_control_get, sst_algo_control_set)
+
+#define SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask)          \
+       SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "bypass"),        \
+                         0, xmod, xpipe, xtask, 0, SST_ALGO_BYPASS,                    \
+                         snd_soc_info_bool_ext,                                        \
+                         sst_algo_control_get, sst_algo_control_set)
+
+#define SST_ALGO_BYPASS_PARAMS(xpname, xmname, xcount, xmod, xpipe,                    \
+                               xinstance, xtask, xcmd)                                 \
+       SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask),          \
+       SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod, xpipe, xinstance, xtask, xcmd)
+
+#define SST_COMBO_ALGO_KCONTROL_BYTES(xpname, xmname, xsubmod, xcount, xmod,           \
+                                     xpipe, xinstance, xtask, xcmd)                    \
+       SST_ALGO_KCONTROL(SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, "params",   \
+                                                xsubmod),                              \
+                         xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,            \
+                         sst_algo_bytes_ctl_info,                                      \
+                         sst_algo_control_get, sst_algo_control_set)
+
+
+struct sst_enum {
+       bool tx;
+       unsigned short reg;
+       unsigned int max;
+       const char * const *texts;
+       struct snd_soc_dapm_widget *w;
+};
+
+/* only 4 slots/channels supported atm */
+#define SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts) \
+       (struct sst_enum){ .reg = s_ch_no, .tx = is_tx, .max = 4+1, .texts = xtexts, }
+
+#define SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name) \
+       xpname " " xmname " " s_ch_name
+
+#define SST_SSP_SLOT_CTL(xpname, xmname, s_ch_name, s_ch_no, is_tx, xtexts, xget, xput) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name), \
+       .info = sst_slot_enum_info, \
+       .get = xget, .put = xput, \
+       .private_value = (unsigned long)&SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts), \
+}
+
+#define SST_MUX_CTL_NAME(xpname, xinstance) \
+       xpname " " #xinstance
+
+#define SST_SSP_MUX_ENUM(xreg, xshift, xtexts) \
+       (struct soc_enum) SOC_ENUM_DOUBLE(xreg, xshift, xshift, ARRAY_SIZE(xtexts), xtexts)
+
+#define SST_SSP_MUX_CTL(xpname, xinstance, xreg, xshift, xtexts) \
+       SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
+                         SST_SSP_MUX_ENUM(xreg, xshift, xtexts))
+
+#endif
diff --git a/sound/soc/intel/atom/sst-mfld-dsp.h b/sound/soc/intel/atom/sst-mfld-dsp.h
new file mode 100644 (file)
index 0000000..4257263
--- /dev/null
@@ -0,0 +1,533 @@
+#ifndef __SST_MFLD_DSP_H__
+#define __SST_MFLD_DSP_H__
+/*
+ *  sst_mfld_dsp.h - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14 Intel Corporation
+ *  Authors:   Vinod Koul <vinod.koul@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define SST_MAX_BIN_BYTES 1024
+
+#define MAX_DBG_RW_BYTES 80
+#define MAX_NUM_SCATTER_BUFFERS 8
+#define MAX_LOOP_BACK_DWORDS 8
+/* IPC base address and mailbox, timestamp offsets */
+#define SST_MAILBOX_SIZE 0x0400
+#define SST_MAILBOX_SEND 0x0000
+#define SST_TIME_STAMP 0x1800
+#define SST_TIME_STAMP_MRFLD 0x800
+#define SST_RESERVED_OFFSET 0x1A00
+#define SST_SCU_LPE_MAILBOX 0x1000
+#define SST_LPE_SCU_MAILBOX 0x1400
+#define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16)
+#define PROCESS_MSG 0x80
+
+/* Message ID's for IPC messages */
+/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
+
+/* I2L Firmware/Codec Download msgs */
+#define IPC_IA_PREP_LIB_DNLD 0x01
+#define IPC_IA_LIB_DNLD_CMPLT 0x02
+#define IPC_IA_GET_FW_VERSION 0x04
+#define IPC_IA_GET_FW_BUILD_INF 0x05
+#define IPC_IA_GET_FW_INFO 0x06
+#define IPC_IA_GET_FW_CTXT 0x07
+#define IPC_IA_SET_FW_CTXT 0x08
+#define IPC_IA_PREPARE_SHUTDOWN 0x31
+/* I2L Codec Config/control msgs */
+#define IPC_PREP_D3 0x10
+#define IPC_IA_SET_CODEC_PARAMS 0x10
+#define IPC_IA_GET_CODEC_PARAMS 0x11
+#define IPC_IA_SET_PPP_PARAMS 0x12
+#define IPC_IA_GET_PPP_PARAMS 0x13
+#define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA
+#define IPC_IA_ALG_PARAMS 0x1A
+#define IPC_IA_TUNING_PARAMS 0x1B
+#define IPC_IA_SET_RUNTIME_PARAMS 0x1C
+#define IPC_IA_SET_PARAMS 0x1
+#define IPC_IA_GET_PARAMS 0x2
+
+#define IPC_EFFECTS_CREATE 0xE
+#define IPC_EFFECTS_DESTROY 0xF
+
+/* I2L Stream config/control msgs */
+#define IPC_IA_ALLOC_STREAM_MRFLD 0x2
+#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
+#define IPC_IA_FREE_STREAM_MRFLD 0x03
+#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
+#define IPC_IA_SET_STREAM_PARAMS 0x22
+#define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12
+#define IPC_IA_GET_STREAM_PARAMS 0x23
+#define IPC_IA_PAUSE_STREAM 0x24
+#define IPC_IA_PAUSE_STREAM_MRFLD 0x4
+#define IPC_IA_RESUME_STREAM 0x25
+#define IPC_IA_RESUME_STREAM_MRFLD 0x5
+#define IPC_IA_DROP_STREAM 0x26
+#define IPC_IA_DROP_STREAM_MRFLD 0x07
+#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
+#define IPC_IA_DRAIN_STREAM_MRFLD 0x8
+#define IPC_IA_CONTROL_ROUTING 0x29
+#define IPC_IA_VTSV_UPDATE_MODULES 0x20
+#define IPC_IA_VTSV_DETECTED 0x21
+
+#define IPC_IA_START_STREAM_MRFLD 0X06
+#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
+
+#define IPC_IA_SET_GAIN_MRFLD 0x21
+/* Debug msgs */
+#define IPC_IA_DBG_MEM_READ 0x40
+#define IPC_IA_DBG_MEM_WRITE 0x41
+#define IPC_IA_DBG_LOOP_BACK 0x42
+#define IPC_IA_DBG_LOG_ENABLE 0x45
+#define IPC_IA_DBG_SET_PROBE_PARAMS 0x47
+
+/* L2I Firmware/Codec Download msgs */
+#define IPC_IA_FW_INIT_CMPLT 0x81
+#define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01
+#define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11
+
+/* L2I Codec Config/control msgs */
+#define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */
+
+#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
+#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
+#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
+#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
+#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
+#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
+
+#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
+/* L2S messages */
+#define IPC_SC_DDR_LINK_UP 0xC0
+#define IPC_SC_DDR_LINK_DOWN 0xC1
+#define IPC_SC_SET_LPECLK_REQ 0xC2
+#define IPC_SC_SSP_BIT_BANG 0xC3
+
+/* L2I Error reporting msgs */
+#define IPC_IA_MEM_ALLOC_FAIL 0xE0
+#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
+                                       stream can be used by playback and
+                                       capture modules */
+
+/* L2I Debug msgs */
+#define IPC_IA_PRINT_STRING 0xF0
+
+/* Buffer under-run */
+#define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B
+
+/* Mrfld specific defines:
+ * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR)
+ * received from FW, the format is:
+ *  - IPC High: pvt_id is set to zero. Always short message.
+ *  - msg_id is in lower 16-bits of IPC low payload.
+ *  - pipe_id is in higher 16-bits of IPC low payload for period_elapsed.
+ *  - error id is in higher 16-bits of IPC low payload for async errors.
+ */
+#define SST_ASYNC_DRV_ID 0
+
+/* Command Response or Acknowledge message to any IPC message will have
+ * same message ID and stream ID information which is sent.
+ * There is no specific Ack message ID. The data field is used as response
+ * meaning.
+ */
+enum ackData {
+       IPC_ACK_SUCCESS = 0,
+       IPC_ACK_FAILURE,
+};
+
+enum ipc_ia_msg_id {
+       IPC_CMD = 1,            /*!< Task Control message ID */
+       IPC_SET_PARAMS = 2,/*!< Task Set param message ID */
+       IPC_GET_PARAMS = 3,     /*!< Task Get param message ID */
+       IPC_INVALID = 0xFF,     /*!<Task Get param message ID */
+};
+
+enum sst_codec_types {
+       /*  AUDIO/MUSIC CODEC Type Definitions */
+       SST_CODEC_TYPE_UNKNOWN = 0,
+       SST_CODEC_TYPE_PCM,     /* Pass through Audio codec */
+       SST_CODEC_TYPE_MP3,
+       SST_CODEC_TYPE_MP24,
+       SST_CODEC_TYPE_AAC,
+       SST_CODEC_TYPE_AACP,
+       SST_CODEC_TYPE_eAACP,
+};
+
+enum stream_type {
+       SST_STREAM_TYPE_NONE = 0,
+       SST_STREAM_TYPE_MUSIC = 1,
+};
+
+enum sst_error_codes {
+       /* Error code,response to msgId: Description */
+       /* Common error codes */
+       SST_SUCCESS = 0,        /* Success */
+       SST_ERR_INVALID_STREAM_ID = 1,
+       SST_ERR_INVALID_MSG_ID = 2,
+       SST_ERR_INVALID_STREAM_OP = 3,
+       SST_ERR_INVALID_PARAMS = 4,
+       SST_ERR_INVALID_CODEC = 5,
+       SST_ERR_INVALID_MEDIA_TYPE = 6,
+       SST_ERR_STREAM_ERR = 7,
+
+       SST_ERR_STREAM_IN_USE = 15,
+};
+
+struct ipc_dsp_hdr {
+       u16 mod_index_id:8;             /*!< DSP Command ID specific to tasks */
+       u16 pipe_id:8;  /*!< instance of the module in the pipeline */
+       u16 mod_id;             /*!< Pipe_id */
+       u16 cmd_id;             /*!< Module ID = lpe_algo_types_t */
+       u16 length;             /*!< Length of the payload only */
+} __packed;
+
+union ipc_header_high {
+       struct {
+               u32  msg_id:8;      /* Message ID - Max 256 Message Types */
+               u32  task_id:4;     /* Task ID associated with this comand */
+               u32  drv_id:4;    /* Identifier for the driver to track*/
+               u32  rsvd1:8;       /* Reserved */
+               u32  result:4;      /* Reserved */
+               u32  res_rqd:1;     /* Response rqd */
+               u32  large:1;       /* Large Message if large = 1 */
+               u32  done:1;        /* bit 30 - Done bit */
+               u32  busy:1;        /* bit 31 - busy bit*/
+       } part;
+       u32 full;
+} __packed;
+/* IPC header */
+union ipc_header_mrfld {
+       struct {
+               u32 header_low_payload;
+               union ipc_header_high header_high;
+       } p;
+       u64 full;
+} __packed;
+/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
+
+/* IPC Header */
+union ipc_header {
+       struct {
+               u32  msg_id:8; /* Message ID - Max 256 Message Types */
+               u32  str_id:5;
+               u32  large:1;   /* Large Message if large = 1 */
+               u32  reserved:2;        /* Reserved for future use */
+               u32  data:14;   /* Ack/Info for msg, size of msg in Mailbox */
+               u32  done:1; /* bit 30 */
+               u32  busy:1; /* bit 31 */
+       } part;
+       u32 full;
+} __packed;
+
+/* Firmware build info */
+struct sst_fw_build_info {
+       unsigned char  date[16]; /* Firmware build date */
+       unsigned char  time[16]; /* Firmware build time */
+} __packed;
+
+/* Firmware Version info */
+struct snd_sst_fw_version {
+       u8 build;       /* build number*/
+       u8 minor;       /* minor number*/
+       u8 major;       /* major number*/
+       u8 type;        /* build type */
+};
+
+struct ipc_header_fw_init {
+       struct snd_sst_fw_version fw_version;/* Firmware version details */
+       struct sst_fw_build_info build_info;
+       u16 result;     /* Fw init result */
+       u8 module_id; /* Module ID in case of error */
+       u8 debug_info; /* Debug info from Module ID in case of fail */
+} __packed;
+
+struct snd_sst_tstamp {
+       u64 ring_buffer_counter;        /* PB/CP: Bytes copied from/to DDR. */
+       u64 hardware_counter;       /* PB/CP: Bytes DMAed to/from SSP. */
+       u64 frames_decoded;
+       u64 bytes_decoded;
+       u64 bytes_copied;
+       u32 sampling_frequency;
+       u32 channel_peak[8];
+} __packed;
+
+/* Stream type params struture for Alloc stream */
+struct snd_sst_str_type {
+       u8 codec_type;          /* Codec type */
+       u8 str_type;            /* 1 = voice 2 = music */
+       u8 operation;           /* Playback or Capture */
+       u8 protected_str;       /* 0=Non DRM, 1=DRM */
+       u8 time_slots;
+       u8 reserved;            /* Reserved */
+       u16 result;             /* Result used for acknowledgment */
+} __packed;
+
+/* Library info structure */
+struct module_info {
+       u32 lib_version;
+       u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
+       u32 media_type;
+       u8  lib_name[12];
+       u32 lib_caps;
+       unsigned char  b_date[16]; /* Lib build date */
+       unsigned char  b_time[16]; /* Lib build time */
+} __packed;
+
+/* Library slot info */
+struct lib_slot_info {
+       u8  slot_num; /* 1 or 2 */
+       u8  reserved1;
+       u16 reserved2;
+       u32 iram_size; /* slot size in IRAM */
+       u32 dram_size; /* slot size in DRAM */
+       u32 iram_offset; /* starting offset of slot in IRAM */
+       u32 dram_offset; /* starting offset of slot in DRAM */
+} __packed;
+
+struct snd_ppp_mixer_params {
+       __u32                   type; /*Type of the parameter */
+       __u32                   size;
+       __u32                   input_stream_bitmap; /*Input stream Bit Map*/
+} __packed;
+
+struct snd_sst_lib_download {
+       struct module_info lib_info; /* library info type, capabilities etc */
+       struct lib_slot_info slot_info; /* slot info to be downloaded */
+       u32 mod_entry_pt;
+};
+
+struct snd_sst_lib_download_info {
+       struct snd_sst_lib_download dload_lib;
+       u16 result;     /* Result used for acknowledgment */
+       u8 pvt_id; /* Private ID */
+       u8 reserved;  /* for alignment */
+};
+struct snd_pcm_params {
+       u8 num_chan;    /* 1=Mono, 2=Stereo */
+       u8 pcm_wd_sz;   /* 16/24 - bit*/
+       u8 use_offload_path;    /* 0-PCM using period elpased & ALSA interfaces
+                                  1-PCM stream via compressed interface  */
+       u8 reserved2;
+       u32 sfreq;    /* Sampling rate in Hz */
+       u8 channel_map[8];
+} __packed;
+
+/* MP3 Music Parameters Message */
+struct snd_mp3_params {
+       u8  num_chan;   /* 1=Mono, 2=Stereo     */
+       u8  pcm_wd_sz; /* 16/24 - bit*/
+       u8  crc_check; /* crc_check - disable (0) or enable (1) */
+       u8  reserved1; /* unused*/
+       u16 reserved2;  /* Unused */
+} __packed;
+
+#define AAC_BIT_STREAM_ADTS            0
+#define AAC_BIT_STREAM_ADIF            1
+#define AAC_BIT_STREAM_RAW             2
+
+/* AAC Music Parameters Message */
+struct snd_aac_params {
+       u8 num_chan; /* 1=Mono, 2=Stereo*/
+       u8 pcm_wd_sz; /* 16/24 - bit*/
+       u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */
+       u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */
+       u16  reser2;
+       u32 externalsr; /*sampling rate of basic AAC raw bit stream*/
+       u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/
+       u8 reser1;
+       u16  reser3;
+} __packed;
+
+/* WMA Music Parameters Message */
+struct snd_wma_params {
+       u8  num_chan;   /* 1=Mono, 2=Stereo */
+       u8  pcm_wd_sz;  /* 16/24 - bit*/
+       u16 reserved1;
+       u32 brate;      /* Use the hard coded value. */
+       u32 sfreq;      /* Sampling freq eg. 8000, 441000, 48000 */
+       u32 channel_mask;  /* Channel Mask */
+       u16 format_tag; /* Format Tag */
+       u16 block_align;        /* packet size */
+       u16 wma_encode_opt;/* Encoder option */
+       u8 op_align;    /* op align 0- 16 bit, 1- MSB, 2 LSB */
+       u8 reserved;    /* reserved */
+} __packed;
+
+/* Codec params struture */
+union  snd_sst_codec_params {
+       struct snd_pcm_params pcm_params;
+       struct snd_mp3_params mp3_params;
+       struct snd_aac_params aac_params;
+       struct snd_wma_params wma_params;
+} __packed;
+
+/* Address and size info of a frame buffer */
+struct sst_address_info {
+       u32 addr; /* Address at IA */
+       u32 size; /* Size of the buffer */
+};
+
+struct snd_sst_alloc_params_ext {
+       __u16 sg_count;
+       __u16 reserved;
+       __u32 frag_size;        /*Number of samples after which period elapsed
+                                 message is sent valid only if path  = 0*/
+       struct sst_address_info  ring_buf_info[8];
+};
+
+struct snd_sst_stream_params {
+       union snd_sst_codec_params uc;
+} __packed;
+
+struct snd_sst_params {
+       u32 result;
+       u32 stream_id;
+       u8 codec;
+       u8 ops;
+       u8 stream_type;
+       u8 device_type;
+       u8 task;
+       struct snd_sst_stream_params sparams;
+       struct snd_sst_alloc_params_ext aparams;
+};
+
+struct snd_sst_alloc_mrfld {
+       u16 codec_type;
+       u8 operation;
+       u8 sg_count;
+       struct sst_address_info ring_buf_info[8];
+       u32 frag_size;
+       u32 ts;
+       struct snd_sst_stream_params codec_params;
+} __packed;
+
+/* Alloc stream params structure */
+struct snd_sst_alloc_params {
+       struct snd_sst_str_type str_type;
+       struct snd_sst_stream_params stream_params;
+       struct snd_sst_alloc_params_ext alloc_params;
+} __packed;
+
+/* Alloc stream response message */
+struct snd_sst_alloc_response {
+       struct snd_sst_str_type str_type; /* Stream type for allocation */
+       struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
+};
+
+/* Drop response */
+struct snd_sst_drop_response {
+       u32 result;
+       u32 bytes;
+};
+
+struct snd_sst_async_msg {
+       u32 msg_id; /* Async msg id */
+       u32 payload[0];
+};
+
+struct snd_sst_async_err_msg {
+       u32 fw_resp; /* Firmware Result */
+       u32 lib_resp; /*Library result */
+} __packed;
+
+struct snd_sst_vol {
+       u32     stream_id;
+       s32     volume;
+       u32     ramp_duration;
+       u32     ramp_type;              /* Ramp type, default=0 */
+};
+
+/* Gain library parameters for mrfld
+ * based on DSP command spec v0.82
+ */
+struct snd_sst_gain_v2 {
+       u16 gain_cell_num;  /* num of gain cells to modify*/
+       u8 cell_nbr_idx; /* instance index*/
+       u8 cell_path_idx; /* pipe-id */
+       u16 module_id; /*module id */
+       u16 left_cell_gain; /* left gain value in dB*/
+       u16 right_cell_gain; /* right gain value in dB*/
+       u16 gain_time_const; /* gain time constant*/
+} __packed;
+
+struct snd_sst_mute {
+       u32     stream_id;
+       u32     mute;
+};
+
+struct snd_sst_runtime_params {
+       u8 type;
+       u8 str_id;
+       u8 size;
+       u8 rsvd;
+       void *addr;
+} __packed;
+
+enum stream_param_type {
+       SST_SET_TIME_SLOT = 0,
+       SST_SET_CHANNEL_INFO = 1,
+       OTHERS = 2, /*reserved for future params*/
+};
+
+/* CSV Voice call routing structure */
+struct snd_sst_control_routing {
+       u8 control; /* 0=start, 1=Stop */
+       u8 reserved[3]; /* Reserved- for 32 bit alignment */
+};
+
+struct ipc_post {
+       struct list_head node;
+       union ipc_header header; /* driver specific */
+       bool is_large;
+       bool is_process_reply;
+       union ipc_header_mrfld mrfld_header;
+       char *mailbox_data;
+};
+
+struct snd_sst_ctxt_params {
+       u32 address; /* Physical Address in DDR where the context is stored */
+       u32 size; /* size of the context */
+};
+
+struct snd_sst_lpe_log_params {
+       u8 dbg_type;
+       u8 module_id;
+       u8 log_level;
+       u8 reserved;
+} __packed;
+
+enum snd_sst_bytes_type {
+       SND_SST_BYTES_SET = 0x1,
+       SND_SST_BYTES_GET = 0x2,
+};
+
+struct snd_sst_bytes_v2 {
+       u8 type;
+       u8 ipc_msg;
+       u8 block;
+       u8 task_id;
+       u8 pipe_id;
+       u8 rsvd;
+       u16 len;
+       char bytes[0];
+};
+
+#define MAX_VTSV_FILES 2
+struct snd_sst_vtsv_info {
+       struct sst_address_info vfiles[MAX_VTSV_FILES];
+} __packed;
+
+#endif /* __SST_MFLD_DSP_H__ */
diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c
new file mode 100644 (file)
index 0000000..3951689
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ *  sst_mfld_platform.c - Intel MID Platform driver
+ *
+ *  Copyright (C) 2010-2014 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include "sst-mfld-platform.h"
+
+/* compress stream operations */
+static void sst_compr_fragment_elapsed(void *arg)
+{
+       struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
+
+       pr_debug("fragment elapsed by driver\n");
+       if (cstream)
+               snd_compr_fragment_elapsed(cstream);
+}
+
+static void sst_drain_notify(void *arg)
+{
+       struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
+
+       pr_debug("drain notify by driver\n");
+       if (cstream)
+               snd_compr_drain_notify(cstream);
+}
+
+static int sst_platform_compr_open(struct snd_compr_stream *cstream)
+{
+
+       int ret_val = 0;
+       struct snd_compr_runtime *runtime = cstream->runtime;
+       struct sst_runtime_stream *stream;
+
+       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+       if (!stream)
+               return -ENOMEM;
+
+       spin_lock_init(&stream->status_lock);
+
+       /* get the sst ops */
+       if (!sst || !try_module_get(sst->dev->driver->owner)) {
+               pr_err("no device available to run\n");
+               ret_val = -ENODEV;
+               goto out_ops;
+       }
+       stream->compr_ops = sst->compr_ops;
+       stream->id = 0;
+
+       /* Turn on LPE */
+       sst->compr_ops->power(sst->dev, true);
+
+       sst_set_stream_status(stream, SST_PLATFORM_INIT);
+       runtime->private_data = stream;
+       return 0;
+out_ops:
+       kfree(stream);
+       return ret_val;
+}
+
+static int sst_platform_compr_free(struct snd_compr_stream *cstream)
+{
+       struct sst_runtime_stream *stream;
+       int ret_val = 0, str_id;
+
+       stream = cstream->runtime->private_data;
+       /* Turn off LPE */
+       sst->compr_ops->power(sst->dev, false);
+
+       /*need to check*/
+       str_id = stream->id;
+       if (str_id)
+               ret_val = stream->compr_ops->close(sst->dev, str_id);
+       module_put(sst->dev->driver->owner);
+       kfree(stream);
+       pr_debug("%s: %d\n", __func__, ret_val);
+       return 0;
+}
+
+static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
+                                       struct snd_compr_params *params)
+{
+       struct sst_runtime_stream *stream;
+       int retval;
+       struct snd_sst_params str_params;
+       struct sst_compress_cb cb;
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
+
+       stream = cstream->runtime->private_data;
+       /* construct fw structure for this*/
+       memset(&str_params, 0, sizeof(str_params));
+
+       /* fill the device type and stream id to pass to SST driver */
+       retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
+       pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
+       if (retval < 0)
+               return retval;
+
+       switch (params->codec.id) {
+       case SND_AUDIOCODEC_MP3: {
+               str_params.codec = SST_CODEC_TYPE_MP3;
+               str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
+               str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
+               break;
+       }
+
+       case SND_AUDIOCODEC_AAC: {
+               str_params.codec = SST_CODEC_TYPE_AAC;
+               str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
+               str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
+               if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
+                       str_params.sparams.uc.aac_params.bs_format =
+                                                       AAC_BIT_STREAM_ADTS;
+               else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
+                       str_params.sparams.uc.aac_params.bs_format =
+                                                       AAC_BIT_STREAM_RAW;
+               else {
+                       pr_err("Undefined format%d\n", params->codec.format);
+                       return -EINVAL;
+               }
+               str_params.sparams.uc.aac_params.externalsr =
+                                               params->codec.sample_rate;
+               break;
+       }
+
+       default:
+               pr_err("codec not supported, id =%d\n", params->codec.id);
+               return -EINVAL;
+       }
+
+       str_params.aparams.ring_buf_info[0].addr  =
+                                       virt_to_phys(cstream->runtime->buffer);
+       str_params.aparams.ring_buf_info[0].size =
+                                       cstream->runtime->buffer_size;
+       str_params.aparams.sg_count = 1;
+       str_params.aparams.frag_size = cstream->runtime->fragment_size;
+
+       cb.param = cstream;
+       cb.compr_cb = sst_compr_fragment_elapsed;
+       cb.drain_cb_param = cstream;
+       cb.drain_notify = sst_drain_notify;
+
+       retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
+       if (retval < 0) {
+               pr_err("stream allocation failed %d\n", retval);
+               return retval;
+       }
+
+       stream->id = retval;
+       return 0;
+}
+
+static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
+{
+       struct sst_runtime_stream *stream = cstream->runtime->private_data;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               if (stream->compr_ops->stream_start)
+                       return stream->compr_ops->stream_start(sst->dev, stream->id);
+       case SNDRV_PCM_TRIGGER_STOP:
+               if (stream->compr_ops->stream_drop)
+                       return stream->compr_ops->stream_drop(sst->dev, stream->id);
+       case SND_COMPR_TRIGGER_DRAIN:
+               if (stream->compr_ops->stream_drain)
+                       return stream->compr_ops->stream_drain(sst->dev, stream->id);
+       case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
+               if (stream->compr_ops->stream_partial_drain)
+                       return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (stream->compr_ops->stream_pause)
+                       return stream->compr_ops->stream_pause(sst->dev, stream->id);
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (stream->compr_ops->stream_pause_release)
+                       return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
+                                       struct snd_compr_tstamp *tstamp)
+{
+       struct sst_runtime_stream *stream;
+
+       stream  = cstream->runtime->private_data;
+       stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
+       tstamp->byte_offset = tstamp->copied_total %
+                                (u32)cstream->runtime->buffer_size;
+       pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
+       return 0;
+}
+
+static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
+                                       size_t bytes)
+{
+       struct sst_runtime_stream *stream;
+
+       stream  = cstream->runtime->private_data;
+       stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
+       stream->bytes_written += bytes;
+
+       return 0;
+}
+
+static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
+                                       struct snd_compr_caps *caps)
+{
+       struct sst_runtime_stream *stream =
+               cstream->runtime->private_data;
+
+       return stream->compr_ops->get_caps(caps);
+}
+
+static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
+                                       struct snd_compr_codec_caps *codec)
+{
+       struct sst_runtime_stream *stream =
+               cstream->runtime->private_data;
+
+       return stream->compr_ops->get_codec_caps(codec);
+}
+
+static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
+                                       struct snd_compr_metadata *metadata)
+{
+       struct sst_runtime_stream *stream  =
+                cstream->runtime->private_data;
+
+       return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
+}
+
+struct snd_compr_ops sst_platform_compr_ops = {
+
+       .open = sst_platform_compr_open,
+       .free = sst_platform_compr_free,
+       .set_params = sst_platform_compr_set_params,
+       .set_metadata = sst_platform_compr_set_metadata,
+       .trigger = sst_platform_compr_trigger,
+       .pointer = sst_platform_compr_pointer,
+       .ack = sst_platform_compr_ack,
+       .get_caps = sst_platform_compr_get_caps,
+       .get_codec_caps = sst_platform_compr_get_codec_caps,
+};
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
new file mode 100644 (file)
index 0000000..2fbaf2c
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+ *  sst_mfld_platform.c - Intel MID Platform driver
+ *
+ *  Copyright (C) 2010-2014 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <asm/platform_sst_audio.h>
+#include "sst-mfld-platform.h"
+#include "sst-atom-controls.h"
+
+struct sst_device *sst;
+static DEFINE_MUTEX(sst_lock);
+extern struct snd_compr_ops sst_platform_compr_ops;
+
+int sst_register_dsp(struct sst_device *dev)
+{
+       if (WARN_ON(!dev))
+               return -EINVAL;
+       if (!try_module_get(dev->dev->driver->owner))
+               return -ENODEV;
+       mutex_lock(&sst_lock);
+       if (sst) {
+               dev_err(dev->dev, "we already have a device %s\n", sst->name);
+               module_put(dev->dev->driver->owner);
+               mutex_unlock(&sst_lock);
+               return -EEXIST;
+       }
+       dev_dbg(dev->dev, "registering device %s\n", dev->name);
+       sst = dev;
+       mutex_unlock(&sst_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sst_register_dsp);
+
+int sst_unregister_dsp(struct sst_device *dev)
+{
+       if (WARN_ON(!dev))
+               return -EINVAL;
+       if (dev != sst)
+               return -EINVAL;
+
+       mutex_lock(&sst_lock);
+
+       if (!sst) {
+               mutex_unlock(&sst_lock);
+               return -EIO;
+       }
+
+       module_put(sst->dev->driver->owner);
+       dev_dbg(dev->dev, "unreg %s\n", sst->name);
+       sst = NULL;
+       mutex_unlock(&sst_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sst_unregister_dsp);
+
+static struct snd_pcm_hardware sst_platform_pcm_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED |
+                       SNDRV_PCM_INFO_DOUBLE |
+                       SNDRV_PCM_INFO_PAUSE |
+                       SNDRV_PCM_INFO_RESUME |
+                       SNDRV_PCM_INFO_MMAP|
+                       SNDRV_PCM_INFO_MMAP_VALID |
+                       SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                       SNDRV_PCM_INFO_SYNC_START),
+       .buffer_bytes_max = SST_MAX_BUFFER,
+       .period_bytes_min = SST_MIN_PERIOD_BYTES,
+       .period_bytes_max = SST_MAX_PERIOD_BYTES,
+       .periods_min = SST_MIN_PERIODS,
+       .periods_max = SST_MAX_PERIODS,
+       .fifo_size = SST_FIFO_SIZE,
+};
+
+static struct sst_dev_stream_map dpcm_strm_map[] = {
+       {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
+       {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
+       {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
+       {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
+};
+
+static int sst_media_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+
+       return sst_send_pipe_gains(dai, stream, mute);
+}
+
+/* helper functions */
+void sst_set_stream_status(struct sst_runtime_stream *stream,
+                                       int state)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&stream->status_lock, flags);
+       stream->stream_status = state;
+       spin_unlock_irqrestore(&stream->status_lock, flags);
+}
+
+static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
+{
+       int state;
+       unsigned long flags;
+
+       spin_lock_irqsave(&stream->status_lock, flags);
+       state = stream->stream_status;
+       spin_unlock_irqrestore(&stream->status_lock, flags);
+       return state;
+}
+
+static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
+                               struct snd_sst_alloc_params_ext *alloc_param)
+{
+       unsigned int channels;
+       snd_pcm_uframes_t period_size;
+       ssize_t periodbytes;
+       ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+       u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
+
+       channels = substream->runtime->channels;
+       period_size = substream->runtime->period_size;
+       periodbytes = samples_to_bytes(substream->runtime, period_size);
+       alloc_param->ring_buf_info[0].addr = buffer_addr;
+       alloc_param->ring_buf_info[0].size = buffer_bytes;
+       alloc_param->sg_count = 1;
+       alloc_param->reserved = 0;
+       alloc_param->frag_size = periodbytes * channels;
+
+}
+static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
+                               struct snd_sst_stream_params *param)
+{
+       param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
+       param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
+       param->uc.pcm_params.sfreq = substream->runtime->rate;
+
+       /* PCM stream via ALSA interface */
+       param->uc.pcm_params.use_offload_path = 0;
+       param->uc.pcm_params.reserved2 = 0;
+       memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
+
+}
+
+static int sst_get_stream_mapping(int dev, int sdev, int dir,
+       struct sst_dev_stream_map *map, int size)
+{
+       int i;
+
+       if (map == NULL)
+               return -EINVAL;
+
+
+       /* index 0 is not used in stream map */
+       for (i = 1; i < size; i++) {
+               if ((map[i].dev_num == dev) && (map[i].direction == dir))
+                       return i;
+       }
+       return 0;
+}
+
+int sst_fill_stream_params(void *substream,
+       const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
+{
+       int map_size;
+       int index;
+       struct sst_dev_stream_map *map;
+       struct snd_pcm_substream *pstream = NULL;
+       struct snd_compr_stream *cstream = NULL;
+
+       map = ctx->pdata->pdev_strm_map;
+       map_size = ctx->pdata->strm_map_size;
+
+       if (is_compress == true)
+               cstream = (struct snd_compr_stream *)substream;
+       else
+               pstream = (struct snd_pcm_substream *)substream;
+
+       str_params->stream_type = SST_STREAM_TYPE_MUSIC;
+
+       /* For pcm streams */
+       if (pstream) {
+               index = sst_get_stream_mapping(pstream->pcm->device,
+                                         pstream->number, pstream->stream,
+                                         map, map_size);
+               if (index <= 0)
+                       return -EINVAL;
+
+               str_params->stream_id = index;
+               str_params->device_type = map[index].device_id;
+               str_params->task = map[index].task_id;
+
+               str_params->ops = (u8)pstream->stream;
+       }
+
+       if (cstream) {
+               index = sst_get_stream_mapping(cstream->device->device,
+                                              0, cstream->direction,
+                                              map, map_size);
+               if (index <= 0)
+                       return -EINVAL;
+               str_params->stream_id = index;
+               str_params->device_type = map[index].device_id;
+               str_params->task = map[index].task_id;
+
+               str_params->ops = (u8)cstream->direction;
+       }
+       return 0;
+}
+
+static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct sst_runtime_stream *stream =
+                       substream->runtime->private_data;
+       struct snd_sst_stream_params param = {{{0,},},};
+       struct snd_sst_params str_params = {0};
+       struct snd_sst_alloc_params_ext alloc_params = {0};
+       int ret_val = 0;
+       struct sst_data *ctx = snd_soc_dai_get_drvdata(dai);
+
+       /* set codec params and inform SST driver the same */
+       sst_fill_pcm_params(substream, &param);
+       sst_fill_alloc_params(substream, &alloc_params);
+       substream->runtime->dma_area = substream->dma_buffer.area;
+       str_params.sparams = param;
+       str_params.aparams = alloc_params;
+       str_params.codec = SST_CODEC_TYPE_PCM;
+
+       /* fill the device type and stream id to pass to SST driver */
+       ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
+       if (ret_val < 0)
+               return ret_val;
+
+       stream->stream_info.str_id = str_params.stream_id;
+
+       ret_val = stream->ops->open(sst->dev, &str_params);
+       if (ret_val <= 0)
+               return ret_val;
+
+
+       return ret_val;
+}
+
+static void sst_period_elapsed(void *arg)
+{
+       struct snd_pcm_substream *substream = arg;
+       struct sst_runtime_stream *stream;
+       int status;
+
+       if (!substream || !substream->runtime)
+               return;
+       stream = substream->runtime->private_data;
+       if (!stream)
+               return;
+       status = sst_get_stream_status(stream);
+       if (status != SST_PLATFORM_RUNNING)
+               return;
+       snd_pcm_period_elapsed(substream);
+}
+
+static int sst_platform_init_stream(struct snd_pcm_substream *substream)
+{
+       struct sst_runtime_stream *stream =
+                       substream->runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int ret_val;
+
+       dev_dbg(rtd->dev, "setting buffer ptr param\n");
+       sst_set_stream_status(stream, SST_PLATFORM_INIT);
+       stream->stream_info.period_elapsed = sst_period_elapsed;
+       stream->stream_info.arg = substream;
+       stream->stream_info.buffer_ptr = 0;
+       stream->stream_info.sfreq = substream->runtime->rate;
+       ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info);
+       if (ret_val)
+               dev_err(rtd->dev, "control_set ret error %d\n", ret_val);
+       return ret_val;
+
+}
+
+static int power_up_sst(struct sst_runtime_stream *stream)
+{
+       return stream->ops->power(sst->dev, true);
+}
+
+static void power_down_sst(struct sst_runtime_stream *stream)
+{
+       stream->ops->power(sst->dev, false);
+}
+
+static int sst_media_open(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       int ret_val = 0;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct sst_runtime_stream *stream;
+
+       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+       if (!stream)
+               return -ENOMEM;
+       spin_lock_init(&stream->status_lock);
+
+       /* get the sst ops */
+       mutex_lock(&sst_lock);
+       if (!sst ||
+           !try_module_get(sst->dev->driver->owner)) {
+               dev_err(dai->dev, "no device available to run\n");
+               ret_val = -ENODEV;
+               goto out_ops;
+       }
+       stream->ops = sst->ops;
+       mutex_unlock(&sst_lock);
+
+       stream->stream_info.str_id = 0;
+
+       stream->stream_info.arg = substream;
+       /* allocate memory for SST API set */
+       runtime->private_data = stream;
+
+       ret_val = power_up_sst(stream);
+       if (ret_val < 0)
+               return ret_val;
+
+       /* Make sure, that the period size is always even */
+       snd_pcm_hw_constraint_step(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_PERIODS, 2);
+
+       return snd_pcm_hw_constraint_integer(runtime,
+                        SNDRV_PCM_HW_PARAM_PERIODS);
+out_ops:
+       kfree(stream);
+       mutex_unlock(&sst_lock);
+       return ret_val;
+}
+
+static void sst_media_close(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct sst_runtime_stream *stream;
+       int ret_val = 0, str_id;
+
+       stream = substream->runtime->private_data;
+       power_down_sst(stream);
+
+       str_id = stream->stream_info.str_id;
+       if (str_id)
+               ret_val = stream->ops->close(sst->dev, str_id);
+       module_put(sst->dev->driver->owner);
+       kfree(stream);
+}
+
+static inline unsigned int get_current_pipe_id(struct snd_soc_dai *dai,
+                                              struct snd_pcm_substream *substream)
+{
+       struct sst_data *sst = snd_soc_dai_get_drvdata(dai);
+       struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
+       struct sst_runtime_stream *stream =
+                       substream->runtime->private_data;
+       u32 str_id = stream->stream_info.str_id;
+       unsigned int pipe_id;
+
+       pipe_id = map[str_id].device_id;
+
+       dev_dbg(dai->dev, "got pipe_id = %#x for str_id = %d\n",
+                       pipe_id, str_id);
+       return pipe_id;
+}
+
+static int sst_media_prepare(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct sst_runtime_stream *stream;
+       int ret_val = 0, str_id;
+
+       stream = substream->runtime->private_data;
+       str_id = stream->stream_info.str_id;
+       if (stream->stream_info.str_id) {
+               ret_val = stream->ops->stream_drop(sst->dev, str_id);
+               return ret_val;
+       }
+
+       ret_val = sst_platform_alloc_stream(substream, dai);
+       if (ret_val <= 0)
+               return ret_val;
+       snprintf(substream->pcm->id, sizeof(substream->pcm->id),
+                       "%d", stream->stream_info.str_id);
+
+       ret_val = sst_platform_init_stream(substream);
+       if (ret_val)
+               return ret_val;
+       substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
+       return ret_val;
+}
+
+static int sst_media_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *dai)
+{
+       snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
+       return 0;
+}
+
+static int sst_media_hw_free(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static int sst_enable_ssp(struct snd_pcm_substream *substream,
+                       struct snd_soc_dai *dai)
+{
+       int ret = 0;
+
+       if (!dai->active) {
+               ret = sst_handle_vb_timer(dai, true);
+               if (ret)
+                       return ret;
+               ret = send_ssp_cmd(dai, dai->name, 1);
+       }
+       return ret;
+}
+
+static void sst_disable_ssp(struct snd_pcm_substream *substream,
+                       struct snd_soc_dai *dai)
+{
+       if (!dai->active) {
+               send_ssp_cmd(dai, dai->name, 0);
+               sst_handle_vb_timer(dai, false);
+       }
+}
+
+static struct snd_soc_dai_ops sst_media_dai_ops = {
+       .startup = sst_media_open,
+       .shutdown = sst_media_close,
+       .prepare = sst_media_prepare,
+       .hw_params = sst_media_hw_params,
+       .hw_free = sst_media_hw_free,
+       .mute_stream = sst_media_digital_mute,
+};
+
+static struct snd_soc_dai_ops sst_compr_dai_ops = {
+       .mute_stream = sst_media_digital_mute,
+};
+
+static struct snd_soc_dai_ops sst_be_dai_ops = {
+       .startup = sst_enable_ssp,
+       .shutdown = sst_disable_ssp,
+};
+
+static struct snd_soc_dai_driver sst_platform_dai[] = {
+{
+       .name = "media-cpu-dai",
+       .ops = &sst_media_dai_ops,
+       .playback = {
+               .stream_name = "Headset Playback",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "Headset Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+{
+       .name = "compress-cpu-dai",
+       .compress_dai = 1,
+       .ops = &sst_compr_dai_ops,
+       .playback = {
+               .stream_name = "Compress Playback",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+/* BE CPU  Dais */
+{
+       .name = "ssp0-port",
+       .ops = &sst_be_dai_ops,
+       .playback = {
+               .stream_name = "ssp0 Tx",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp0 Rx",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+{
+       .name = "ssp1-port",
+       .ops = &sst_be_dai_ops,
+       .playback = {
+               .stream_name = "ssp1 Tx",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp1 Rx",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+{
+       .name = "ssp2-port",
+       .ops = &sst_be_dai_ops,
+       .playback = {
+               .stream_name = "ssp2 Tx",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp2 Rx",
+               .channels_min = SST_STEREO,
+               .channels_max = SST_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+};
+
+static int sst_platform_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime;
+
+       if (substream->pcm->internal)
+               return 0;
+
+       runtime = substream->runtime;
+       runtime->hw = sst_platform_pcm_hw;
+       return 0;
+}
+
+static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
+                                       int cmd)
+{
+       int ret_val = 0, str_id;
+       struct sst_runtime_stream *stream;
+       int status;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+       dev_dbg(rtd->dev, "sst_platform_pcm_trigger called\n");
+       if (substream->pcm->internal)
+               return 0;
+       stream = substream->runtime->private_data;
+       str_id = stream->stream_info.str_id;
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               dev_dbg(rtd->dev, "sst: Trigger Start\n");
+               status = SST_PLATFORM_RUNNING;
+               stream->stream_info.arg = substream;
+               ret_val = stream->ops->stream_start(sst->dev, str_id);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               dev_dbg(rtd->dev, "sst: in stop\n");
+               status = SST_PLATFORM_DROPPED;
+               ret_val = stream->ops->stream_drop(sst->dev, str_id);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               dev_dbg(rtd->dev, "sst: in pause\n");
+               status = SST_PLATFORM_PAUSED;
+               ret_val = stream->ops->stream_pause(sst->dev, str_id);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               dev_dbg(rtd->dev, "sst: in pause release\n");
+               status = SST_PLATFORM_RUNNING;
+               ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (!ret_val)
+               sst_set_stream_status(stream, status);
+
+       return ret_val;
+}
+
+
+static snd_pcm_uframes_t sst_platform_pcm_pointer
+                       (struct snd_pcm_substream *substream)
+{
+       struct sst_runtime_stream *stream;
+       int ret_val, status;
+       struct pcm_stream_info *str_info;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+       stream = substream->runtime->private_data;
+       status = sst_get_stream_status(stream);
+       if (status == SST_PLATFORM_INIT)
+               return 0;
+       str_info = &stream->stream_info;
+       ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info);
+       if (ret_val) {
+               dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
+               return ret_val;
+       }
+       substream->runtime->delay = str_info->pcm_delay;
+       return str_info->buffer_ptr;
+}
+
+static struct snd_pcm_ops sst_platform_ops = {
+       .open = sst_platform_open,
+       .ioctl = snd_pcm_lib_ioctl,
+       .trigger = sst_platform_pcm_trigger,
+       .pointer = sst_platform_pcm_pointer,
+};
+
+static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->cpu_dai;
+       struct snd_pcm *pcm = rtd->pcm;
+       int retval = 0;
+
+       if (dai->driver->playback.channels_min ||
+                       dai->driver->capture.channels_min) {
+               retval =  snd_pcm_lib_preallocate_pages_for_all(pcm,
+                       SNDRV_DMA_TYPE_CONTINUOUS,
+                       snd_dma_continuous_data(GFP_DMA),
+                       SST_MIN_BUFFER, SST_MAX_BUFFER);
+               if (retval) {
+                       dev_err(rtd->dev, "dma buffer allocationf fail\n");
+                       return retval;
+               }
+       }
+       return retval;
+}
+
+static int sst_soc_probe(struct snd_soc_platform *platform)
+{
+       struct sst_data *drv = dev_get_drvdata(platform->dev);
+
+       drv->soc_card = platform->component.card;
+       return sst_dsp_init_v2_dpcm(platform);
+}
+
+static struct snd_soc_platform_driver sst_soc_platform_drv  = {
+       .probe          = sst_soc_probe,
+       .ops            = &sst_platform_ops,
+       .compr_ops      = &sst_platform_compr_ops,
+       .pcm_new        = sst_pcm_new,
+};
+
+static const struct snd_soc_component_driver sst_component = {
+       .name           = "sst",
+};
+
+
+static int sst_platform_probe(struct platform_device *pdev)
+{
+       struct sst_data *drv;
+       int ret;
+       struct sst_platform_data *pdata;
+
+       drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+       if (drv == NULL) {
+               return -ENOMEM;
+       }
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (pdata == NULL) {
+               return -ENOMEM;
+       }
+
+       pdata->pdev_strm_map = dpcm_strm_map;
+       pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
+       drv->pdata = pdata;
+       drv->pdev = pdev;
+       mutex_init(&drv->lock);
+       dev_set_drvdata(&pdev->dev, drv);
+
+       ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
+       if (ret) {
+               dev_err(&pdev->dev, "registering soc platform failed\n");
+               return ret;
+       }
+
+       ret = snd_soc_register_component(&pdev->dev, &sst_component,
+                               sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
+       if (ret) {
+               dev_err(&pdev->dev, "registering cpu dais failed\n");
+               snd_soc_unregister_platform(&pdev->dev);
+       }
+       return ret;
+}
+
+static int sst_platform_remove(struct platform_device *pdev)
+{
+
+       snd_soc_unregister_component(&pdev->dev);
+       snd_soc_unregister_platform(&pdev->dev);
+       dev_dbg(&pdev->dev, "sst_platform_remove success\n");
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int sst_soc_prepare(struct device *dev)
+{
+       struct sst_data *drv = dev_get_drvdata(dev);
+       int i;
+
+       /* suspend all pcms first */
+       snd_soc_suspend(drv->soc_card->dev);
+       snd_soc_poweroff(drv->soc_card->dev);
+
+       /* set the SSPs to idle */
+       for (i = 0; i < drv->soc_card->num_rtd; i++) {
+               struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+
+               if (dai->active) {
+                       send_ssp_cmd(dai, dai->name, 0);
+                       sst_handle_vb_timer(dai, false);
+               }
+       }
+
+       return 0;
+}
+
+static void sst_soc_complete(struct device *dev)
+{
+       struct sst_data *drv = dev_get_drvdata(dev);
+       int i;
+
+       /* restart SSPs */
+       for (i = 0; i < drv->soc_card->num_rtd; i++) {
+               struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+
+               if (dai->active) {
+                       sst_handle_vb_timer(dai, true);
+                       send_ssp_cmd(dai, dai->name, 1);
+               }
+       }
+       snd_soc_resume(drv->soc_card->dev);
+}
+
+#else
+
+#define sst_soc_prepare NULL
+#define sst_soc_complete NULL
+
+#endif
+
+
+static const struct dev_pm_ops sst_platform_pm = {
+       .prepare        = sst_soc_prepare,
+       .complete       = sst_soc_complete,
+};
+
+static struct platform_driver sst_platform_driver = {
+       .driver         = {
+               .name           = "sst-mfld-platform",
+               .pm             = &sst_platform_pm,
+       },
+       .probe          = sst_platform_probe,
+       .remove         = sst_platform_remove,
+};
+
+module_platform_driver(sst_platform_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sst-mfld-platform");
diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h
new file mode 100644 (file)
index 0000000..9094314
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *  sst_mfld_platform.h - Intel MID Platform driver header file
+ *
+ *  Copyright (C) 2010 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#ifndef __SST_PLATFORMDRV_H__
+#define __SST_PLATFORMDRV_H__
+
+#include "sst-mfld-dsp.h"
+
+extern struct sst_device *sst;
+
+#define SST_MONO               1
+#define SST_STEREO             2
+#define SST_MAX_CAP            5
+
+#define SST_MAX_BUFFER         (800*1024)
+#define SST_MIN_BUFFER         (800*1024)
+#define SST_MIN_PERIOD_BYTES   32
+#define SST_MAX_PERIOD_BYTES   SST_MAX_BUFFER
+#define SST_MIN_PERIODS                2
+#define SST_MAX_PERIODS                (1024*2)
+#define SST_FIFO_SIZE          0
+
+struct pcm_stream_info {
+       int str_id;
+       void *arg;
+       void (*period_elapsed) (void *arg);
+       unsigned long long buffer_ptr;
+       unsigned long long pcm_delay;
+       int sfreq;
+};
+
+enum sst_drv_status {
+       SST_PLATFORM_INIT = 1,
+       SST_PLATFORM_STARTED,
+       SST_PLATFORM_RUNNING,
+       SST_PLATFORM_PAUSED,
+       SST_PLATFORM_DROPPED,
+};
+
+enum sst_stream_ops {
+       STREAM_OPS_PLAYBACK = 0,
+       STREAM_OPS_CAPTURE,
+};
+
+enum sst_audio_device_type {
+       SND_SST_DEVICE_HEADSET = 1,
+       SND_SST_DEVICE_IHF,
+       SND_SST_DEVICE_VIBRA,
+       SND_SST_DEVICE_HAPTIC,
+       SND_SST_DEVICE_CAPTURE,
+       SND_SST_DEVICE_COMPRESS,
+};
+
+/* PCM Parameters */
+struct sst_pcm_params {
+       u16 codec;      /* codec type */
+       u8 num_chan;    /* 1=Mono, 2=Stereo */
+       u8 pcm_wd_sz;   /* 16/24 - bit*/
+       u32 reserved;   /* Bitrate in bits per second */
+       u32 sfreq;      /* Sampling rate in Hz */
+       u32 ring_buffer_size;
+       u32 period_count;       /* period elapsed in samples*/
+       u32 ring_buffer_addr;
+};
+
+struct sst_stream_params {
+       u32 result;
+       u32 stream_id;
+       u8 codec;
+       u8 ops;
+       u8 stream_type;
+       u8 device_type;
+       struct sst_pcm_params sparams;
+};
+
+struct sst_compress_cb {
+       void *param;
+       void (*compr_cb)(void *param);
+       void *drain_cb_param;
+       void (*drain_notify)(void *param);
+};
+
+struct compress_sst_ops {
+       const char *name;
+       int (*open)(struct device *dev,
+               struct snd_sst_params *str_params, struct sst_compress_cb *cb);
+       int (*stream_start)(struct device *dev, unsigned int str_id);
+       int (*stream_drop)(struct device *dev, unsigned int str_id);
+       int (*stream_drain)(struct device *dev, unsigned int str_id);
+       int (*stream_partial_drain)(struct device *dev, unsigned int str_id);
+       int (*stream_pause)(struct device *dev, unsigned int str_id);
+       int (*stream_pause_release)(struct device *dev, unsigned int str_id);
+
+       int (*tstamp)(struct device *dev, unsigned int str_id,
+                       struct snd_compr_tstamp *tstamp);
+       int (*ack)(struct device *dev, unsigned int str_id,
+                       unsigned long bytes);
+       int (*close)(struct device *dev, unsigned int str_id);
+       int (*get_caps)(struct snd_compr_caps *caps);
+       int (*get_codec_caps)(struct snd_compr_codec_caps *codec);
+       int (*set_metadata)(struct device *dev, unsigned int str_id,
+                       struct snd_compr_metadata *mdata);
+       int (*power)(struct device *dev, bool state);
+};
+
+struct sst_ops {
+       int (*open)(struct device *dev, struct snd_sst_params *str_param);
+       int (*stream_init)(struct device *dev, struct pcm_stream_info *str_info);
+       int (*stream_start)(struct device *dev, int str_id);
+       int (*stream_drop)(struct device *dev, int str_id);
+       int (*stream_pause)(struct device *dev, int str_id);
+       int (*stream_pause_release)(struct device *dev, int str_id);
+       int (*stream_read_tstamp)(struct device *dev, struct pcm_stream_info *str_info);
+       int (*send_byte_stream)(struct device *dev, struct snd_sst_bytes_v2 *bytes);
+       int (*close)(struct device *dev, unsigned int str_id);
+       int (*power)(struct device *dev, bool state);
+};
+
+struct sst_runtime_stream {
+       int     stream_status;
+       unsigned int id;
+       size_t bytes_written;
+       struct pcm_stream_info stream_info;
+       struct sst_ops *ops;
+       struct compress_sst_ops *compr_ops;
+       spinlock_t      status_lock;
+};
+
+struct sst_device {
+       char *name;
+       struct device *dev;
+       struct sst_ops *ops;
+       struct platform_device *pdev;
+       struct compress_sst_ops *compr_ops;
+};
+
+struct sst_data;
+
+int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform);
+int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute);
+int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable);
+int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable);
+
+void sst_set_stream_status(struct sst_runtime_stream *stream, int state);
+int sst_fill_stream_params(void *substream, const struct sst_data *ctx,
+                          struct snd_sst_params *str_params, bool is_compress);
+
+struct sst_algo_int_control_v2 {
+       struct soc_mixer_control mc;
+       u16 module_id; /* module identifieer */
+       u16 pipe_id; /* location info: pipe_id + instance_id */
+       u16 instance_id;
+       unsigned int value; /* Value received is stored here */
+};
+struct sst_data {
+       struct platform_device *pdev;
+       struct sst_platform_data *pdata;
+       struct snd_sst_bytes_v2 *byte_stream;
+       struct mutex lock;
+       struct snd_soc_card *soc_card;
+};
+int sst_register_dsp(struct sst_device *sst);
+int sst_unregister_dsp(struct sst_device *sst);
+#endif
diff --git a/sound/soc/intel/atom/sst/Makefile b/sound/soc/intel/atom/sst/Makefile
new file mode 100644 (file)
index 0000000..fd21726
--- /dev/null
@@ -0,0 +1,7 @@
+snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o
+snd-intel-sst-pci-objs += sst_pci.o
+snd-intel-sst-acpi-objs += sst_acpi.o
+
+obj-$(CONFIG_SND_SST_IPC) += snd-intel-sst-core.o
+obj-$(CONFIG_SND_SST_IPC_PCI) += snd-intel-sst-pci.o
+obj-$(CONFIG_SND_SST_IPC_ACPI) += snd-intel-sst-acpi.o
diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c
new file mode 100644 (file)
index 0000000..96c2e42
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ *  sst.c - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14      Intel Corp
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <linux/async.h>
+#include <linux/acpi.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+#include "../../common/sst-dsp.h"
+
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
+MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine Driver");
+MODULE_LICENSE("GPL v2");
+
+static inline bool sst_is_process_reply(u32 msg_id)
+{
+       return ((msg_id & PROCESS_MSG) ? true : false);
+}
+
+static inline bool sst_validate_mailbox_size(unsigned int size)
+{
+       return ((size <= SST_MAILBOX_SIZE) ? true : false);
+}
+
+static irqreturn_t intel_sst_interrupt_mrfld(int irq, void *context)
+{
+       union interrupt_reg_mrfld isr;
+       union ipc_header_mrfld header;
+       union sst_imr_reg_mrfld imr;
+       struct ipc_post *msg = NULL;
+       unsigned int size = 0;
+       struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
+       irqreturn_t retval = IRQ_HANDLED;
+
+       /* Interrupt arrived, check src */
+       isr.full = sst_shim_read64(drv->shim, SST_ISRX);
+
+       if (isr.part.done_interrupt) {
+               /* Clear done bit */
+               spin_lock(&drv->ipc_spin_lock);
+               header.full = sst_shim_read64(drv->shim,
+                                       drv->ipc_reg.ipcx);
+               header.p.header_high.part.done = 0;
+               sst_shim_write64(drv->shim, drv->ipc_reg.ipcx, header.full);
+
+               /* write 1 to clear status register */;
+               isr.part.done_interrupt = 1;
+               sst_shim_write64(drv->shim, SST_ISRX, isr.full);
+               spin_unlock(&drv->ipc_spin_lock);
+
+               /* we can send more messages to DSP so trigger work */
+               queue_work(drv->post_msg_wq, &drv->ipc_post_msg_wq);
+               retval = IRQ_HANDLED;
+       }
+
+       if (isr.part.busy_interrupt) {
+               /* message from dsp so copy that */
+               spin_lock(&drv->ipc_spin_lock);
+               imr.full = sst_shim_read64(drv->shim, SST_IMRX);
+               imr.part.busy_interrupt = 1;
+               sst_shim_write64(drv->shim, SST_IMRX, imr.full);
+               spin_unlock(&drv->ipc_spin_lock);
+               header.full =  sst_shim_read64(drv->shim, drv->ipc_reg.ipcd);
+
+               if (sst_create_ipc_msg(&msg, header.p.header_high.part.large)) {
+                       drv->ops->clear_interrupt(drv);
+                       return IRQ_HANDLED;
+               }
+
+               if (header.p.header_high.part.large) {
+                       size = header.p.header_low_payload;
+                       if (sst_validate_mailbox_size(size)) {
+                               memcpy_fromio(msg->mailbox_data,
+                                       drv->mailbox + drv->mailbox_recv_offset, size);
+                       } else {
+                               dev_err(drv->dev,
+                                       "Mailbox not copied, payload size is: %u\n", size);
+                               header.p.header_low_payload = 0;
+                       }
+               }
+
+               msg->mrfld_header = header;
+               msg->is_process_reply =
+                       sst_is_process_reply(header.p.header_high.part.msg_id);
+               spin_lock(&drv->rx_msg_lock);
+               list_add_tail(&msg->node, &drv->rx_list);
+               spin_unlock(&drv->rx_msg_lock);
+               drv->ops->clear_interrupt(drv);
+               retval = IRQ_WAKE_THREAD;
+       }
+       return retval;
+}
+
+static irqreturn_t intel_sst_irq_thread_mrfld(int irq, void *context)
+{
+       struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
+       struct ipc_post *__msg, *msg = NULL;
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&drv->rx_msg_lock, irq_flags);
+       if (list_empty(&drv->rx_list)) {
+               spin_unlock_irqrestore(&drv->rx_msg_lock, irq_flags);
+               return IRQ_HANDLED;
+       }
+
+       list_for_each_entry_safe(msg, __msg, &drv->rx_list, node) {
+               list_del(&msg->node);
+               spin_unlock_irqrestore(&drv->rx_msg_lock, irq_flags);
+               if (msg->is_process_reply)
+                       drv->ops->process_message(msg);
+               else
+                       drv->ops->process_reply(drv, msg);
+
+               if (msg->is_large)
+                       kfree(msg->mailbox_data);
+               kfree(msg);
+               spin_lock_irqsave(&drv->rx_msg_lock, irq_flags);
+       }
+       spin_unlock_irqrestore(&drv->rx_msg_lock, irq_flags);
+       return IRQ_HANDLED;
+}
+
+static int sst_save_dsp_context_v2(struct intel_sst_drv *sst)
+{
+       int ret = 0;
+
+       ret = sst_prepare_and_post_msg(sst, SST_TASK_ID_MEDIA, IPC_CMD,
+                       IPC_PREP_D3, PIPE_RSVD, 0, NULL, NULL,
+                       true, true, false, true);
+
+       if (ret < 0) {
+               dev_err(sst->dev, "not suspending FW!!, Err: %d\n", ret);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+
+static struct intel_sst_ops mrfld_ops = {
+       .interrupt = intel_sst_interrupt_mrfld,
+       .irq_thread = intel_sst_irq_thread_mrfld,
+       .clear_interrupt = intel_sst_clear_intr_mrfld,
+       .start = sst_start_mrfld,
+       .reset = intel_sst_reset_dsp_mrfld,
+       .post_message = sst_post_message_mrfld,
+       .process_reply = sst_process_reply_mrfld,
+       .save_dsp_context =  sst_save_dsp_context_v2,
+       .alloc_stream = sst_alloc_stream_mrfld,
+       .post_download = sst_post_download_mrfld,
+};
+
+int sst_driver_ops(struct intel_sst_drv *sst)
+{
+
+       switch (sst->dev_id) {
+       case SST_MRFLD_PCI_ID:
+       case SST_BYT_ACPI_ID:
+       case SST_CHV_ACPI_ID:
+               sst->tstamp = SST_TIME_STAMP_MRFLD;
+               sst->ops = &mrfld_ops;
+               return 0;
+
+       default:
+               dev_err(sst->dev,
+                       "SST Driver capablities missing for dev_id: %x", sst->dev_id);
+               return -EINVAL;
+       };
+}
+
+void sst_process_pending_msg(struct work_struct *work)
+{
+       struct intel_sst_drv *ctx = container_of(work,
+                       struct intel_sst_drv, ipc_post_msg_wq);
+
+       ctx->ops->post_message(ctx, NULL, false);
+}
+
+static int sst_workqueue_init(struct intel_sst_drv *ctx)
+{
+       INIT_LIST_HEAD(&ctx->memcpy_list);
+       INIT_LIST_HEAD(&ctx->rx_list);
+       INIT_LIST_HEAD(&ctx->ipc_dispatch_list);
+       INIT_LIST_HEAD(&ctx->block_list);
+       INIT_WORK(&ctx->ipc_post_msg_wq, sst_process_pending_msg);
+       init_waitqueue_head(&ctx->wait_queue);
+
+       ctx->post_msg_wq =
+               create_singlethread_workqueue("sst_post_msg_wq");
+       if (!ctx->post_msg_wq)
+               return -EBUSY;
+       return 0;
+}
+
+static void sst_init_locks(struct intel_sst_drv *ctx)
+{
+       mutex_init(&ctx->sst_lock);
+       spin_lock_init(&ctx->rx_msg_lock);
+       spin_lock_init(&ctx->ipc_spin_lock);
+       spin_lock_init(&ctx->block_lock);
+}
+
+int sst_alloc_drv_context(struct intel_sst_drv **ctx,
+               struct device *dev, unsigned int dev_id)
+{
+       *ctx = devm_kzalloc(dev, sizeof(struct intel_sst_drv), GFP_KERNEL);
+       if (!(*ctx))
+               return -ENOMEM;
+
+       (*ctx)->dev = dev;
+       (*ctx)->dev_id = dev_id;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sst_alloc_drv_context);
+
+int sst_context_init(struct intel_sst_drv *ctx)
+{
+       int ret = 0, i;
+
+       if (!ctx->pdata)
+               return -EINVAL;
+
+       if (!ctx->pdata->probe_data)
+               return -EINVAL;
+
+       memcpy(&ctx->info, ctx->pdata->probe_data, sizeof(ctx->info));
+
+       ret = sst_driver_ops(ctx);
+       if (ret != 0)
+               return -EINVAL;
+
+       sst_init_locks(ctx);
+       sst_set_fw_state_locked(ctx, SST_RESET);
+
+       /* pvt_id 0 reserved for async messages */
+       ctx->pvt_id = 1;
+       ctx->stream_cnt = 0;
+       ctx->fw_in_mem = NULL;
+       /* we use memcpy, so set to 0 */
+       ctx->use_dma = 0;
+       ctx->use_lli = 0;
+
+       if (sst_workqueue_init(ctx))
+               return -EINVAL;
+
+       ctx->mailbox_recv_offset = ctx->pdata->ipc_info->mbox_recv_off;
+       ctx->ipc_reg.ipcx = SST_IPCX + ctx->pdata->ipc_info->ipc_offset;
+       ctx->ipc_reg.ipcd = SST_IPCD + ctx->pdata->ipc_info->ipc_offset;
+
+       dev_info(ctx->dev, "Got drv data max stream %d\n",
+                               ctx->info.max_streams);
+
+       for (i = 1; i <= ctx->info.max_streams; i++) {
+               struct stream_info *stream = &ctx->streams[i];
+
+               memset(stream, 0, sizeof(*stream));
+               stream->pipe_id = PIPE_RSVD;
+               mutex_init(&stream->lock);
+       }
+
+       /* Register the ISR */
+       ret = devm_request_threaded_irq(ctx->dev, ctx->irq_num, ctx->ops->interrupt,
+                                       ctx->ops->irq_thread, 0, SST_DRV_NAME,
+                                       ctx);
+       if (ret)
+               goto do_free_mem;
+
+       dev_dbg(ctx->dev, "Registered IRQ %#x\n", ctx->irq_num);
+
+       /* default intr are unmasked so set this as masked */
+       sst_shim_write64(ctx->shim, SST_IMRX, 0xFFFF0038);
+
+       ctx->qos = devm_kzalloc(ctx->dev,
+               sizeof(struct pm_qos_request), GFP_KERNEL);
+       if (!ctx->qos) {
+               ret = -ENOMEM;
+               goto do_free_mem;
+       }
+       pm_qos_add_request(ctx->qos, PM_QOS_CPU_DMA_LATENCY,
+                               PM_QOS_DEFAULT_VALUE);
+
+       dev_dbg(ctx->dev, "Requesting FW %s now...\n", ctx->firmware_name);
+       ret = request_firmware_nowait(THIS_MODULE, true, ctx->firmware_name,
+                                     ctx->dev, GFP_KERNEL, ctx, sst_firmware_load_cb);
+       if (ret) {
+               dev_err(ctx->dev, "Firmware download failed:%d\n", ret);
+               goto do_free_mem;
+       }
+       sst_register(ctx->dev);
+       return 0;
+
+do_free_mem:
+       destroy_workqueue(ctx->post_msg_wq);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(sst_context_init);
+
+void sst_context_cleanup(struct intel_sst_drv *ctx)
+{
+       pm_runtime_get_noresume(ctx->dev);
+       pm_runtime_disable(ctx->dev);
+       sst_unregister(ctx->dev);
+       sst_set_fw_state_locked(ctx, SST_SHUTDOWN);
+       flush_scheduled_work();
+       destroy_workqueue(ctx->post_msg_wq);
+       pm_qos_remove_request(ctx->qos);
+       kfree(ctx->fw_sg_list.src);
+       kfree(ctx->fw_sg_list.dst);
+       ctx->fw_sg_list.list_len = 0;
+       kfree(ctx->fw_in_mem);
+       ctx->fw_in_mem = NULL;
+       sst_memcpy_free_resources(ctx);
+       ctx = NULL;
+}
+EXPORT_SYMBOL_GPL(sst_context_cleanup);
+
+static inline void sst_save_shim64(struct intel_sst_drv *ctx,
+                           void __iomem *shim,
+                           struct sst_shim_regs64 *shim_regs)
+{
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
+
+       shim_regs->imrx = sst_shim_read64(shim, SST_IMRX);
+       shim_regs->csr = sst_shim_read64(shim, SST_CSR);
+
+
+       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
+}
+
+static inline void sst_restore_shim64(struct intel_sst_drv *ctx,
+                                     void __iomem *shim,
+                                     struct sst_shim_regs64 *shim_regs)
+{
+       unsigned long irq_flags;
+
+       /*
+        * we only need to restore IMRX for this case, rest will be
+        * initialize by FW or driver when firmware is loaded
+        */
+       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
+       sst_shim_write64(shim, SST_IMRX, shim_regs->imrx),
+       sst_shim_write64(shim, SST_CSR, shim_regs->csr),
+       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
+}
+
+void sst_configure_runtime_pm(struct intel_sst_drv *ctx)
+{
+       pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY);
+       pm_runtime_use_autosuspend(ctx->dev);
+       /*
+        * For acpi devices, the actual physical device state is
+        * initially active. So change the state to active before
+        * enabling the pm
+        */
+
+       if (!acpi_disabled)
+               pm_runtime_set_active(ctx->dev);
+
+       pm_runtime_enable(ctx->dev);
+
+       if (acpi_disabled)
+               pm_runtime_set_active(ctx->dev);
+       else
+               pm_runtime_put_noidle(ctx->dev);
+
+       sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
+}
+EXPORT_SYMBOL_GPL(sst_configure_runtime_pm);
+
+static int intel_sst_runtime_suspend(struct device *dev)
+{
+       int ret = 0;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (ctx->sst_state == SST_RESET) {
+               dev_dbg(dev, "LPE is already in RESET state, No action\n");
+               return 0;
+       }
+       /* save fw context */
+       if (ctx->ops->save_dsp_context(ctx))
+               return -EBUSY;
+
+       /* Move the SST state to Reset */
+       sst_set_fw_state_locked(ctx, SST_RESET);
+
+       synchronize_irq(ctx->irq_num);
+       flush_workqueue(ctx->post_msg_wq);
+
+       ctx->ops->reset(ctx);
+       /* save the shim registers because PMC doesn't save state */
+       sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
+
+       return ret;
+}
+
+static int intel_sst_suspend(struct device *dev)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+       struct sst_fw_save *fw_save;
+       int i, ret = 0;
+
+       /* check first if we are already in SW reset */
+       if (ctx->sst_state == SST_RESET)
+               return 0;
+
+       /*
+        * check if any stream is active and running
+        * they should already by suspend by soc_suspend
+        */
+       for (i = 1; i <= ctx->info.max_streams; i++) {
+               struct stream_info *stream = &ctx->streams[i];
+
+               if (stream->status == STREAM_RUNNING) {
+                       dev_err(dev, "stream %d is running, cant susupend, abort\n", i);
+                       return -EBUSY;
+               }
+       }
+       synchronize_irq(ctx->irq_num);
+       flush_workqueue(ctx->post_msg_wq);
+
+       /* Move the SST state to Reset */
+       sst_set_fw_state_locked(ctx, SST_RESET);
+
+       /* tell DSP we are suspending */
+       if (ctx->ops->save_dsp_context(ctx))
+               return -EBUSY;
+
+       /* save the memories */
+       fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
+       if (!fw_save)
+               return -ENOMEM;
+       fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
+       if (!fw_save->iram) {
+               ret = -ENOMEM;
+               goto iram;
+       }
+       fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
+       if (!fw_save->dram) {
+               ret = -ENOMEM;
+               goto dram;
+       }
+       fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
+       if (!fw_save->sram) {
+               ret = -ENOMEM;
+               goto sram;
+       }
+
+       fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
+       if (!fw_save->ddr) {
+               ret = -ENOMEM;
+               goto ddr;
+       }
+
+       memcpy32_fromio(fw_save->iram, ctx->iram, ctx->iram_end - ctx->iram_base);
+       memcpy32_fromio(fw_save->dram, ctx->dram, ctx->dram_end - ctx->dram_base);
+       memcpy32_fromio(fw_save->sram, ctx->mailbox, SST_MAILBOX_SIZE);
+       memcpy32_fromio(fw_save->ddr, ctx->ddr, ctx->ddr_end - ctx->ddr_base);
+
+       ctx->fw_save = fw_save;
+       ctx->ops->reset(ctx);
+       return 0;
+ddr:
+       kfree(fw_save->sram);
+sram:
+       kfree(fw_save->dram);
+dram:
+       kfree(fw_save->iram);
+iram:
+       kfree(fw_save);
+       return ret;
+}
+
+static int intel_sst_resume(struct device *dev)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+       struct sst_fw_save *fw_save = ctx->fw_save;
+       int ret = 0;
+       struct sst_block *block;
+
+       if (!fw_save)
+               return 0;
+
+       sst_set_fw_state_locked(ctx, SST_FW_LOADING);
+
+       /* we have to restore the memory saved */
+       ctx->ops->reset(ctx);
+
+       ctx->fw_save = NULL;
+
+       memcpy32_toio(ctx->iram, fw_save->iram, ctx->iram_end - ctx->iram_base);
+       memcpy32_toio(ctx->dram, fw_save->dram, ctx->dram_end - ctx->dram_base);
+       memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
+       memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
+
+       kfree(fw_save->sram);
+       kfree(fw_save->dram);
+       kfree(fw_save->iram);
+       kfree(fw_save->ddr);
+       kfree(fw_save);
+
+       block = sst_create_block(ctx, 0, FW_DWNL_ID);
+       if (block == NULL)
+               return -ENOMEM;
+
+
+       /* start and wait for ack */
+       ctx->ops->start(ctx);
+       ret = sst_wait_timeout(ctx, block);
+       if (ret) {
+               dev_err(ctx->dev, "fw download failed %d\n", ret);
+               /* FW download failed due to timeout */
+               ret = -EBUSY;
+
+       } else {
+               sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
+       }
+
+       sst_free_block(ctx, block);
+       return ret;
+}
+
+const struct dev_pm_ops intel_sst_pm = {
+       .suspend = intel_sst_suspend,
+       .resume = intel_sst_resume,
+       .runtime_suspend = intel_sst_runtime_suspend,
+};
+EXPORT_SYMBOL_GPL(intel_sst_pm);
diff --git a/sound/soc/intel/atom/sst/sst.h b/sound/soc/intel/atom/sst/sst.h
new file mode 100644 (file)
index 0000000..3f49386
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ *  sst.h - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14 Intel Corporation
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  Common private declarations for SST
+ */
+#ifndef __SST_H__
+#define __SST_H__
+
+#include <linux/firmware.h>
+
+/* driver names */
+#define SST_DRV_NAME "intel_sst_driver"
+#define SST_MRFLD_PCI_ID 0x119A
+#define SST_BYT_ACPI_ID        0x80860F28
+#define SST_CHV_ACPI_ID        0x808622A8
+
+#define SST_SUSPEND_DELAY 2000
+#define FW_CONTEXT_MEM (64*1024)
+#define SST_ICCM_BOUNDARY 4
+#define SST_CONFIG_SSP_SIGN 0x7ffe8001
+
+#define MRFLD_FW_VIRTUAL_BASE 0xC0000000
+#define MRFLD_FW_DDR_BASE_OFFSET 0x0
+#define MRFLD_FW_FEATURE_BASE_OFFSET 0x4
+#define MRFLD_FW_BSS_RESET_BIT 0
+
+extern const struct dev_pm_ops intel_sst_pm;
+enum sst_states {
+       SST_FW_LOADING = 1,
+       SST_FW_RUNNING,
+       SST_RESET,
+       SST_SHUTDOWN,
+};
+
+enum sst_algo_ops {
+       SST_SET_ALGO = 0,
+       SST_GET_ALGO = 1,
+};
+
+#define SST_BLOCK_TIMEOUT      1000
+
+#define FW_SIGNATURE_SIZE      4
+#define FW_NAME_SIZE           32
+
+/* stream states */
+enum sst_stream_states {
+       STREAM_UN_INIT  = 0,    /* Freed/Not used stream */
+       STREAM_RUNNING  = 1,    /* Running */
+       STREAM_PAUSED   = 2,    /* Paused stream */
+       STREAM_DECODE   = 3,    /* stream is in decoding only state */
+       STREAM_INIT     = 4,    /* stream init, waiting for data */
+       STREAM_RESET    = 5,    /* force reset on recovery */
+};
+
+enum sst_ram_type {
+       SST_IRAM        = 1,
+       SST_DRAM        = 2,
+       SST_DDR = 5,
+       SST_CUSTOM_INFO = 7,    /* consists of FW binary information */
+};
+
+/* SST shim registers to structure mapping */
+union interrupt_reg {
+       struct {
+               u64 done_interrupt:1;
+               u64 busy_interrupt:1;
+               u64 rsvd:62;
+       } part;
+       u64 full;
+};
+
+union sst_pisr_reg {
+       struct {
+               u32 pssp0:1;
+               u32 pssp1:1;
+               u32 rsvd0:3;
+               u32 dmac:1;
+               u32 rsvd1:26;
+       } part;
+       u32 full;
+};
+
+union sst_pimr_reg {
+       struct {
+               u32 ssp0:1;
+               u32 ssp1:1;
+               u32 rsvd0:3;
+               u32 dmac:1;
+               u32 rsvd1:10;
+               u32 ssp0_sc:1;
+               u32 ssp1_sc:1;
+               u32 rsvd2:3;
+               u32 dmac_sc:1;
+               u32 rsvd3:10;
+       } part;
+       u32 full;
+};
+
+union config_status_reg_mrfld {
+       struct {
+               u64 lpe_reset:1;
+               u64 lpe_reset_vector:1;
+               u64 runstall:1;
+               u64 pwaitmode:1;
+               u64 clk_sel:3;
+               u64 rsvd2:1;
+               u64 sst_clk:3;
+               u64 xt_snoop:1;
+               u64 rsvd3:4;
+               u64 clk_sel1:6;
+               u64 clk_enable:3;
+               u64 rsvd4:6;
+               u64 slim0baseclk:1;
+               u64 rsvd:32;
+       } part;
+       u64 full;
+};
+
+union interrupt_reg_mrfld {
+       struct {
+               u64 done_interrupt:1;
+               u64 busy_interrupt:1;
+               u64 rsvd:62;
+       } part;
+       u64 full;
+};
+
+union sst_imr_reg_mrfld {
+       struct {
+               u64 done_interrupt:1;
+               u64 busy_interrupt:1;
+               u64 rsvd:62;
+       } part;
+       u64 full;
+};
+
+/**
+ * struct sst_block - This structure is used to block a user/fw data call to another
+ * fw/user call
+ *
+ * @condition: condition for blocking check
+ * @ret_code: ret code when block is released
+ * @data: data ptr
+ * @size: size of data
+ * @on: block condition
+ * @msg_id: msg_id = msgid in mfld/ctp, mrfld = NULL
+ * @drv_id: str_id in mfld/ctp, = drv_id in mrfld
+ * @node: list head node
+ */
+struct sst_block {
+       bool    condition;
+       int     ret_code;
+       void    *data;
+       u32     size;
+       bool    on;
+       u32     msg_id;
+       u32     drv_id;
+       struct list_head node;
+};
+
+/**
+ * struct stream_info - structure that holds the stream information
+ *
+ * @status : stream current state
+ * @prev : stream prev state
+ * @ops : stream operation pb/cp/drm...
+ * @bufs: stream buffer list
+ * @lock : stream mutex for protecting state
+ * @pcm_substream : PCM substream
+ * @period_elapsed : PCM period elapsed callback
+ * @sfreq : stream sampling freq
+ * @str_type : stream type
+ * @cumm_bytes : cummulative bytes decoded
+ * @str_type : stream type
+ * @src : stream source
+ */
+struct stream_info {
+       unsigned int            status;
+       unsigned int            prev;
+       unsigned int            ops;
+       struct mutex            lock;
+
+       void                    *pcm_substream;
+       void (*period_elapsed)(void *pcm_substream);
+
+       unsigned int            sfreq;
+       u32                     cumm_bytes;
+
+       void                    *compr_cb_param;
+       void (*compr_cb)(void *compr_cb_param);
+
+       void                    *drain_cb_param;
+       void (*drain_notify)(void *drain_cb_param);
+
+       unsigned int            num_ch;
+       unsigned int            pipe_id;
+       unsigned int            str_id;
+       unsigned int            task_id;
+};
+
+#define SST_FW_SIGN "$SST"
+#define SST_FW_LIB_SIGN "$LIB"
+
+/**
+ * struct sst_fw_header - FW file headers
+ *
+ * @signature : FW signature
+ * @file_size: size of fw image
+ * @modules : # of modules
+ * @file_format : version of header format
+ * @reserved : reserved fields
+ */
+struct sst_fw_header {
+       unsigned char signature[FW_SIGNATURE_SIZE];
+       u32 file_size;
+       u32 modules;
+       u32 file_format;
+       u32 reserved[4];
+};
+
+/**
+ * struct fw_module_header - module header in FW
+ *
+ * @signature: module signature
+ * @mod_size: size of module
+ * @blocks: block count
+ * @type: block type
+ * @entry_point: module netry point
+ */
+struct fw_module_header {
+       unsigned char signature[FW_SIGNATURE_SIZE];
+       u32 mod_size;
+       u32 blocks;
+       u32 type;
+       u32 entry_point;
+};
+
+/**
+ * struct fw_block_info - block header for FW
+ *
+ * @type: block ram type I/D
+ * @size: size of block
+ * @ram_offset: offset in ram
+ */
+struct fw_block_info {
+       enum sst_ram_type       type;
+       u32                     size;
+       u32                     ram_offset;
+       u32                     rsvd;
+};
+
+struct sst_runtime_param {
+       struct snd_sst_runtime_params param;
+};
+
+struct sst_sg_list {
+       struct scatterlist *src;
+       struct scatterlist *dst;
+       int list_len;
+       unsigned int sg_idx;
+};
+
+struct sst_memcpy_list {
+       struct list_head memcpylist;
+       void *dstn;
+       const void *src;
+       u32 size;
+       bool is_io;
+};
+
+/*Firmware Module Information*/
+enum sst_lib_dwnld_status {
+       SST_LIB_NOT_FOUND = 0,
+       SST_LIB_FOUND,
+       SST_LIB_DOWNLOADED,
+};
+
+struct sst_module_info {
+       const char *name; /*Library name*/
+       u32     id; /*Module ID*/
+       u32     entry_pt; /*Module entry point*/
+       u8      status; /*module status*/
+       u8      rsvd1;
+       u16     rsvd2;
+};
+
+/*
+ * Structure for managing the Library Region(1.5MB)
+ * in DDR in Merrifield
+ */
+struct sst_mem_mgr {
+       phys_addr_t current_base;
+       int avail;
+       unsigned int count;
+};
+
+struct sst_ipc_reg {
+       int ipcx;
+       int ipcd;
+};
+
+struct sst_shim_regs64 {
+       u64 csr;
+       u64 pisr;
+       u64 pimr;
+       u64 isrx;
+       u64 isrd;
+       u64 imrx;
+       u64 imrd;
+       u64 ipcx;
+       u64 ipcd;
+       u64 isrsc;
+       u64 isrlpesc;
+       u64 imrsc;
+       u64 imrlpesc;
+       u64 ipcsc;
+       u64 ipclpesc;
+       u64 clkctl;
+       u64 csr2;
+};
+
+struct sst_fw_save {
+       void *iram;
+       void *dram;
+       void *sram;
+       void *ddr;
+};
+
+/**
+ * struct intel_sst_drv - driver ops
+ *
+ * @sst_state : current sst device state
+ * @dev_id : device identifier, pci_id for pci devices and acpi_id for acpi
+ *          devices
+ * @shim : SST shim pointer
+ * @mailbox : SST mailbox pointer
+ * @iram : SST IRAM pointer
+ * @dram : SST DRAM pointer
+ * @pdata : SST info passed as a part of pci platform data
+ * @shim_phy_add : SST shim phy addr
+ * @shim_regs64: Struct to save shim registers
+ * @ipc_dispatch_list : ipc messages dispatched
+ * @rx_list : to copy the process_reply/process_msg from DSP
+ * @ipc_post_msg_wq : wq to post IPC messages context
+ * @mad_ops : MAD driver operations registered
+ * @mad_wq : MAD driver wq
+ * @post_msg_wq : wq to post IPC messages
+ * @streams : sst stream contexts
+ * @list_lock : sst driver list lock (deprecated)
+ * @ipc_spin_lock : spin lock to handle audio shim access and ipc queue
+ * @block_lock : spin lock to add block to block_list and assign pvt_id
+ * @rx_msg_lock : spin lock to handle the rx messages from the DSP
+ * @scard_ops : sst card ops
+ * @pci : sst pci device struture
+ * @dev : pointer to current device struct
+ * @sst_lock : sst device lock
+ * @pvt_id : sst private id
+ * @stream_cnt : total sst active stream count
+ * @pb_streams : total active pb streams
+ * @cp_streams : total active cp streams
+ * @audio_start : audio status
+ * @qos                : PM Qos struct
+ * firmware_name : Firmware / Library name
+ */
+struct intel_sst_drv {
+       int                     sst_state;
+       int                     irq_num;
+       unsigned int            dev_id;
+       void __iomem            *ddr;
+       void __iomem            *shim;
+       void __iomem            *mailbox;
+       void __iomem            *iram;
+       void __iomem            *dram;
+       unsigned int            mailbox_add;
+       unsigned int            iram_base;
+       unsigned int            dram_base;
+       unsigned int            shim_phy_add;
+       unsigned int            iram_end;
+       unsigned int            dram_end;
+       unsigned int            ddr_end;
+       unsigned int            ddr_base;
+       unsigned int            mailbox_recv_offset;
+       struct sst_shim_regs64  *shim_regs64;
+       struct list_head        block_list;
+       struct list_head        ipc_dispatch_list;
+       struct sst_platform_info *pdata;
+       struct list_head        rx_list;
+       struct work_struct      ipc_post_msg_wq;
+       wait_queue_head_t       wait_queue;
+       struct workqueue_struct *post_msg_wq;
+       unsigned int            tstamp;
+       /* str_id 0 is not used */
+       struct stream_info      streams[MAX_NUM_STREAMS+1];
+       spinlock_t              ipc_spin_lock;
+       spinlock_t              block_lock;
+       spinlock_t              rx_msg_lock;
+       struct pci_dev          *pci;
+       struct device           *dev;
+       volatile long unsigned          pvt_id;
+       struct mutex            sst_lock;
+       unsigned int            stream_cnt;
+       unsigned int            csr_value;
+       void                    *fw_in_mem;
+       struct sst_sg_list      fw_sg_list, library_list;
+       struct intel_sst_ops    *ops;
+       struct sst_info         info;
+       struct pm_qos_request   *qos;
+       unsigned int            use_dma;
+       unsigned int            use_lli;
+       atomic_t                fw_clear_context;
+       bool                    lib_dwnld_reqd;
+       struct list_head        memcpy_list;
+       struct sst_ipc_reg      ipc_reg;
+       struct sst_mem_mgr      lib_mem_mgr;
+       /*
+        * Holder for firmware name. Due to async call it needs to be
+        * persistent till worker thread gets called
+        */
+       char firmware_name[FW_NAME_SIZE];
+
+       struct sst_fw_save      *fw_save;
+};
+
+/* misc definitions */
+#define FW_DWNL_ID 0x01
+
+struct intel_sst_ops {
+       irqreturn_t (*interrupt)(int, void *);
+       irqreturn_t (*irq_thread)(int, void *);
+       void (*clear_interrupt)(struct intel_sst_drv *ctx);
+       int (*start)(struct intel_sst_drv *ctx);
+       int (*reset)(struct intel_sst_drv *ctx);
+       void (*process_reply)(struct intel_sst_drv *ctx, struct ipc_post *msg);
+       int (*post_message)(struct intel_sst_drv *ctx,
+                       struct ipc_post *msg, bool sync);
+       void (*process_message)(struct ipc_post *msg);
+       void (*set_bypass)(bool set);
+       int (*save_dsp_context)(struct intel_sst_drv *sst);
+       void (*restore_dsp_context)(void);
+       int (*alloc_stream)(struct intel_sst_drv *ctx, void *params);
+       void (*post_download)(struct intel_sst_drv *sst);
+};
+
+int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int id);
+int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int id);
+int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int id);
+int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int id);
+int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id);
+int sst_send_byte_stream_mrfld(struct intel_sst_drv *ctx,
+                       struct snd_sst_bytes_v2 *sbytes);
+int sst_set_stream_param(int str_id, struct snd_sst_params *str_param);
+int sst_set_metadata(int str_id, char *params);
+int sst_get_stream(struct intel_sst_drv *sst_drv_ctx,
+               struct snd_sst_params *str_param);
+int sst_get_stream_allocated(struct intel_sst_drv *ctx,
+               struct snd_sst_params *str_param,
+               struct snd_sst_lib_download **lib_dnld);
+int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
+               int str_id, bool partial_drain);
+int sst_post_message_mrfld(struct intel_sst_drv *ctx,
+               struct ipc_post *msg, bool sync);
+void sst_process_reply_mrfld(struct intel_sst_drv *ctx, struct ipc_post *msg);
+int sst_start_mrfld(struct intel_sst_drv *ctx);
+int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *ctx);
+void intel_sst_clear_intr_mrfld(struct intel_sst_drv *ctx);
+
+int sst_load_fw(struct intel_sst_drv *ctx);
+int sst_load_library(struct snd_sst_lib_download *lib, u8 ops);
+void sst_post_download_mrfld(struct intel_sst_drv *ctx);
+int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx);
+void sst_memcpy_free_resources(struct intel_sst_drv *ctx);
+
+int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
+                               struct sst_block *block);
+int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
+                       struct sst_block *block);
+int sst_create_ipc_msg(struct ipc_post **arg, bool large);
+int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id);
+void sst_clean_stream(struct stream_info *stream);
+int intel_sst_register_compress(struct intel_sst_drv *sst);
+int intel_sst_remove_compress(struct intel_sst_drv *sst);
+void sst_cdev_fragment_elapsed(struct intel_sst_drv *ctx, int str_id);
+int sst_send_sync_msg(int ipc, int str_id);
+int sst_get_num_channel(struct snd_sst_params *str_param);
+int sst_get_sfreq(struct snd_sst_params *str_param);
+int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params);
+void sst_restore_fw_context(void);
+struct sst_block *sst_create_block(struct intel_sst_drv *ctx,
+                               u32 msg_id, u32 drv_id);
+int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large,
+               struct intel_sst_drv *sst_drv_ctx, struct sst_block **block,
+               u32 msg_id, u32 drv_id);
+int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed);
+int sst_wake_up_block(struct intel_sst_drv *ctx, int result,
+               u32 drv_id, u32 ipc, void *data, u32 size);
+int sst_request_firmware_async(struct intel_sst_drv *ctx);
+int sst_driver_ops(struct intel_sst_drv *sst);
+struct sst_platform_info *sst_get_acpi_driver_data(const char *hid);
+void sst_firmware_load_cb(const struct firmware *fw, void *context);
+int sst_prepare_and_post_msg(struct intel_sst_drv *sst,
+               int task_id, int ipc_msg, int cmd_id, int pipe_id,
+               size_t mbox_data_len, const void *mbox_data, void **data,
+               bool large, bool fill_dsp, bool sync, bool response);
+
+void sst_process_pending_msg(struct work_struct *work);
+int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx);
+void sst_init_stream(struct stream_info *stream,
+               int codec, int sst_id, int ops, u8 slot);
+int sst_validate_strid(struct intel_sst_drv *sst_drv_ctx, int str_id);
+struct stream_info *get_stream_info(struct intel_sst_drv *sst_drv_ctx,
+               int str_id);
+int get_stream_id_mrfld(struct intel_sst_drv *sst_drv_ctx,
+               u32 pipe_id);
+u32 relocate_imr_addr_mrfld(u32 base_addr);
+void sst_add_to_dispatch_list_and_post(struct intel_sst_drv *sst,
+                                       struct ipc_post *msg);
+int sst_pm_runtime_put(struct intel_sst_drv *sst_drv);
+int sst_shim_write(void __iomem *addr, int offset, int value);
+u32 sst_shim_read(void __iomem *addr, int offset);
+u64 sst_reg_read64(void __iomem *addr, int offset);
+int sst_shim_write64(void __iomem *addr, int offset, u64 value);
+u64 sst_shim_read64(void __iomem *addr, int offset);
+void sst_set_fw_state_locked(
+               struct intel_sst_drv *sst_drv_ctx, int sst_state);
+void sst_fill_header_mrfld(union ipc_header_mrfld *header,
+                               int msg, int task_id, int large, int drv_id);
+void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg,
+                                       int pipe_id, int len);
+
+int sst_register(struct device *);
+int sst_unregister(struct device *);
+
+int sst_alloc_drv_context(struct intel_sst_drv **ctx,
+               struct device *dev, unsigned int dev_id);
+int sst_context_init(struct intel_sst_drv *ctx);
+void sst_context_cleanup(struct intel_sst_drv *ctx);
+void sst_configure_runtime_pm(struct intel_sst_drv *ctx);
+void memcpy32_toio(void __iomem *dst, const void *src, int count);
+void memcpy32_fromio(void *dst, const void __iomem *src, int count);
+
+#endif
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
new file mode 100644 (file)
index 0000000..678f36e
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration.
+ *
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ *  Authors:   Ramesh Babu K V <Ramesh.Babu@intel.com>
+ *  Authors:   Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <linux/acpi.h>
+#include <asm/platform_sst_audio.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <acpi/acbuffer.h>
+#include <acpi/platform/acenv.h>
+#include <acpi/platform/aclinux.h>
+#include <acpi/actypes.h>
+#include <acpi/acpi_bus.h>
+#include "../sst-mfld-platform.h"
+#include "../../common/sst-dsp.h"
+#include "sst.h"
+
+struct sst_machines {
+       char *codec_id;
+       char board[32];
+       char machine[32];
+       void (*machine_quirk)(void);
+       char firmware[FW_NAME_SIZE];
+       struct sst_platform_info *pdata;
+
+};
+
+/* LPE viewpoint addresses */
+#define SST_BYT_IRAM_PHY_START 0xff2c0000
+#define SST_BYT_IRAM_PHY_END   0xff2d4000
+#define SST_BYT_DRAM_PHY_START 0xff300000
+#define SST_BYT_DRAM_PHY_END   0xff320000
+#define SST_BYT_IMR_VIRT_START 0xc0000000 /* virtual addr in LPE */
+#define SST_BYT_IMR_VIRT_END   0xc01fffff
+#define SST_BYT_SHIM_PHY_ADDR  0xff340000
+#define SST_BYT_MBOX_PHY_ADDR  0xff344000
+#define SST_BYT_DMA0_PHY_ADDR  0xff298000
+#define SST_BYT_DMA1_PHY_ADDR  0xff29c000
+#define SST_BYT_SSP0_PHY_ADDR  0xff2a0000
+#define SST_BYT_SSP2_PHY_ADDR  0xff2a2000
+
+#define BYT_FW_MOD_TABLE_OFFSET        0x80000
+#define BYT_FW_MOD_TABLE_SIZE  0x100
+#define BYT_FW_MOD_OFFSET      (BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE)
+
+static const struct sst_info byt_fwparse_info = {
+       .use_elf        = false,
+       .max_streams    = 25,
+       .iram_start     = SST_BYT_IRAM_PHY_START,
+       .iram_end       = SST_BYT_IRAM_PHY_END,
+       .iram_use       = true,
+       .dram_start     = SST_BYT_DRAM_PHY_START,
+       .dram_end       = SST_BYT_DRAM_PHY_END,
+       .dram_use       = true,
+       .imr_start      = SST_BYT_IMR_VIRT_START,
+       .imr_end        = SST_BYT_IMR_VIRT_END,
+       .imr_use        = true,
+       .mailbox_start  = SST_BYT_MBOX_PHY_ADDR,
+       .num_probes     = 0,
+       .lpe_viewpt_rqd  = true,
+};
+
+static const struct sst_ipc_info byt_ipc_info = {
+       .ipc_offset = 0,
+       .mbox_recv_off = 0x400,
+};
+
+static const struct sst_lib_dnld_info  byt_lib_dnld_info = {
+       .mod_base           = SST_BYT_IMR_VIRT_START,
+       .mod_end            = SST_BYT_IMR_VIRT_END,
+       .mod_table_offset   = BYT_FW_MOD_TABLE_OFFSET,
+       .mod_table_size     = BYT_FW_MOD_TABLE_SIZE,
+       .mod_ddr_dnld       = false,
+};
+
+static const struct sst_res_info byt_rvp_res_info = {
+       .shim_offset = 0x140000,
+       .shim_size = 0x000100,
+       .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
+       .ssp0_offset = 0xa0000,
+       .ssp0_size = 0x1000,
+       .dma0_offset = 0x98000,
+       .dma0_size = 0x4000,
+       .dma1_offset = 0x9c000,
+       .dma1_size = 0x4000,
+       .iram_offset = 0x0c0000,
+       .iram_size = 0x14000,
+       .dram_offset = 0x100000,
+       .dram_size = 0x28000,
+       .mbox_offset = 0x144000,
+       .mbox_size = 0x1000,
+       .acpi_lpe_res_index = 0,
+       .acpi_ddr_index = 2,
+       .acpi_ipc_irq_index = 5,
+};
+
+static struct sst_platform_info byt_rvp_platform_data = {
+       .probe_data = &byt_fwparse_info,
+       .ipc_info = &byt_ipc_info,
+       .lib_info = &byt_lib_dnld_info,
+       .res_info = &byt_rvp_res_info,
+       .platform = "sst-mfld-platform",
+};
+
+/* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
+ * so pdata is same as Baytrail.
+ */
+static struct sst_platform_info chv_platform_data = {
+       .probe_data = &byt_fwparse_info,
+       .ipc_info = &byt_ipc_info,
+       .lib_info = &byt_lib_dnld_info,
+       .res_info = &byt_rvp_res_info,
+       .platform = "sst-mfld-platform",
+};
+
+static int sst_platform_get_resources(struct intel_sst_drv *ctx)
+{
+       struct resource *rsrc;
+       struct platform_device *pdev = to_platform_device(ctx->dev);
+
+       /* All ACPI resource request here */
+       /* Get Shim addr */
+       rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
+                                       ctx->pdata->res_info->acpi_lpe_res_index);
+       if (!rsrc) {
+               dev_err(ctx->dev, "Invalid SHIM base from IFWI");
+               return -EIO;
+       }
+       dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start,
+                                       (unsigned int)resource_size(rsrc));
+
+       ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset;
+       ctx->iram_end =  ctx->iram_base + ctx->pdata->res_info->iram_size - 1;
+       dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base);
+       ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base,
+                                        ctx->pdata->res_info->iram_size);
+       if (!ctx->iram) {
+               dev_err(ctx->dev, "unable to map IRAM");
+               return -EIO;
+       }
+
+       ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset;
+       ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1;
+       dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base);
+       ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base,
+                                        ctx->pdata->res_info->dram_size);
+       if (!ctx->dram) {
+               dev_err(ctx->dev, "unable to map DRAM");
+               return -EIO;
+       }
+
+       ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset;
+       dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add);
+       ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add,
+                                       ctx->pdata->res_info->shim_size);
+       if (!ctx->shim) {
+               dev_err(ctx->dev, "unable to map SHIM");
+               return -EIO;
+       }
+
+       /* reassign physical address to LPE viewpoint address */
+       ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr;
+
+       /* Get mailbox addr */
+       ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset;
+       dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add);
+       ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add,
+                                           ctx->pdata->res_info->mbox_size);
+       if (!ctx->mailbox) {
+               dev_err(ctx->dev, "unable to map mailbox");
+               return -EIO;
+       }
+
+       /* reassign physical address to LPE viewpoint address */
+       ctx->mailbox_add = ctx->info.mailbox_start;
+
+       rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
+                                       ctx->pdata->res_info->acpi_ddr_index);
+       if (!rsrc) {
+               dev_err(ctx->dev, "Invalid DDR base from IFWI");
+               return -EIO;
+       }
+       ctx->ddr_base = rsrc->start;
+       ctx->ddr_end = rsrc->end;
+       dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base);
+       ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base,
+                                       resource_size(rsrc));
+       if (!ctx->ddr) {
+               dev_err(ctx->dev, "unable to map DDR");
+               return -EIO;
+       }
+
+       /* Find the IRQ */
+       ctx->irq_num = platform_get_irq(pdev,
+                               ctx->pdata->res_info->acpi_ipc_irq_index);
+       return 0;
+}
+
+static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
+                                      void *context, void **ret)
+{
+       *(bool *)context = true;
+       return AE_OK;
+}
+
+static struct sst_machines *sst_acpi_find_machine(
+       struct sst_machines *machines)
+{
+       struct sst_machines *mach;
+       bool found = false;
+
+       for (mach = machines; mach->codec_id; mach++)
+               if (ACPI_SUCCESS(acpi_get_devices(mach->codec_id,
+                                                 sst_acpi_mach_match,
+                                                 &found, NULL)) && found)
+                       return mach;
+
+       return NULL;
+}
+
+static int sst_acpi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       int ret = 0;
+       struct intel_sst_drv *ctx;
+       const struct acpi_device_id *id;
+       struct sst_machines *mach;
+       struct platform_device *mdev;
+       struct platform_device *plat_dev;
+       unsigned int dev_id;
+
+       id = acpi_match_device(dev->driver->acpi_match_table, dev);
+       if (!id)
+               return -ENODEV;
+       dev_dbg(dev, "for %s", id->id);
+
+       mach = (struct sst_machines *)id->driver_data;
+       mach = sst_acpi_find_machine(mach);
+       if (mach == NULL) {
+               dev_err(dev, "No matching machine driver found\n");
+               return -ENODEV;
+       }
+
+       ret = kstrtouint(id->id, 16, &dev_id);
+       if (ret < 0) {
+               dev_err(dev, "Unique device id conversion error: %d\n", ret);
+               return ret;
+       }
+
+       dev_dbg(dev, "ACPI device id: %x\n", dev_id);
+
+       plat_dev = platform_device_register_data(dev, mach->pdata->platform, -1, NULL, 0);
+       if (IS_ERR(plat_dev)) {
+               dev_err(dev, "Failed to create machine device: %s\n", mach->pdata->platform);
+               return PTR_ERR(plat_dev);
+       }
+
+       /* Create platform device for sst machine driver */
+       mdev = platform_device_register_data(dev, mach->machine, -1, NULL, 0);
+       if (IS_ERR(mdev)) {
+               dev_err(dev, "Failed to create machine device: %s\n", mach->machine);
+               return PTR_ERR(mdev);
+       }
+
+       ret = sst_alloc_drv_context(&ctx, dev, dev_id);
+       if (ret < 0)
+               return ret;
+
+       /* Fill sst platform data */
+       ctx->pdata = mach->pdata;
+       strcpy(ctx->firmware_name, mach->firmware);
+
+       ret = sst_platform_get_resources(ctx);
+       if (ret)
+               return ret;
+
+       ret = sst_context_init(ctx);
+       if (ret < 0)
+               return ret;
+
+       /* need to save shim registers in BYT */
+       ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64),
+                                       GFP_KERNEL);
+       if (!ctx->shim_regs64) {
+               return -ENOMEM;
+               goto do_sst_cleanup;
+       }
+
+       sst_configure_runtime_pm(ctx);
+       platform_set_drvdata(pdev, ctx);
+       return ret;
+
+do_sst_cleanup:
+       sst_context_cleanup(ctx);
+       platform_set_drvdata(pdev, NULL);
+       dev_err(ctx->dev, "failed with %d\n", ret);
+       return ret;
+}
+
+/**
+* intel_sst_remove - remove function
+*
+* @pdev:       platform device structure
+*
+* This function is called by OS when a device is unloaded
+* This frees the interrupt etc
+*/
+static int sst_acpi_remove(struct platform_device *pdev)
+{
+       struct intel_sst_drv *ctx;
+
+       ctx = platform_get_drvdata(pdev);
+       sst_context_cleanup(ctx);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct sst_machines sst_acpi_bytcr[] = {
+       {"10EC5640", "T100", "bytt100_rt5640", NULL, "intel/fw_sst_0f28.bin",
+                                               &byt_rvp_platform_data },
+       {},
+};
+
+/* Cherryview-based platforms: CherryTrail and Braswell */
+static struct sst_machines sst_acpi_chv[] = {
+       {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin",
+                                               &chv_platform_data },
+       {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
+                                               &chv_platform_data },
+       {},
+};
+
+static const struct acpi_device_id sst_acpi_ids[] = {
+       { "80860F28", (unsigned long)&sst_acpi_bytcr},
+       { "808622A8", (unsigned long) &sst_acpi_chv},
+       { },
+};
+
+MODULE_DEVICE_TABLE(acpi, sst_acpi_ids);
+
+static struct platform_driver sst_acpi_driver = {
+       .driver = {
+               .name                   = "intel_sst_acpi",
+               .acpi_match_table       = ACPI_PTR(sst_acpi_ids),
+               .pm                     = &intel_sst_pm,
+       },
+       .probe  = sst_acpi_probe,
+       .remove = sst_acpi_remove,
+};
+
+module_platform_driver(sst_acpi_driver);
+
+MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver");
+MODULE_AUTHOR("Ramesh Babu K V");
+MODULE_AUTHOR("Omair Mohammed Abdullah");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("sst");
diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c
new file mode 100644 (file)
index 0000000..718838b
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+ *  sst_drv_interface.c - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14 Intel Corp
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <linux/math64.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+#include "../../common/sst-dsp.h"
+
+
+
+#define NUM_CODEC 2
+#define MIN_FRAGMENT 2
+#define MAX_FRAGMENT 4
+#define MIN_FRAGMENT_SIZE (50 * 1024)
+#define MAX_FRAGMENT_SIZE (1024 * 1024)
+#define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz)  (((pcm_wd_sz + 15) >> 4) << 1)
+
+int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id)
+{
+       struct stream_info *stream;
+       int ret = 0;
+
+       stream = get_stream_info(ctx, str_id);
+       if (stream) {
+               /* str_id is valid, so stream is alloacted */
+               ret = sst_free_stream(ctx, str_id);
+               if (ret)
+                       sst_clean_stream(&ctx->streams[str_id]);
+               return ret;
+       } else {
+               dev_err(ctx->dev, "we tried to free stream context %d which was freed!!!\n", str_id);
+       }
+       return ret;
+}
+
+int sst_get_stream_allocated(struct intel_sst_drv *ctx,
+       struct snd_sst_params *str_param,
+       struct snd_sst_lib_download **lib_dnld)
+{
+       int retval;
+
+       retval = ctx->ops->alloc_stream(ctx, str_param);
+       if (retval > 0)
+               dev_dbg(ctx->dev, "Stream allocated %d\n", retval);
+       return retval;
+
+}
+
+/*
+ * sst_get_sfreq - this function returns the frequency of the stream
+ *
+ * @str_param : stream params
+ */
+int sst_get_sfreq(struct snd_sst_params *str_param)
+{
+       switch (str_param->codec) {
+       case SST_CODEC_TYPE_PCM:
+               return str_param->sparams.uc.pcm_params.sfreq;
+       case SST_CODEC_TYPE_AAC:
+               return str_param->sparams.uc.aac_params.externalsr;
+       case SST_CODEC_TYPE_MP3:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+/*
+ * sst_get_num_channel - get number of channels for the stream
+ *
+ * @str_param : stream params
+ */
+int sst_get_num_channel(struct snd_sst_params *str_param)
+{
+       switch (str_param->codec) {
+       case SST_CODEC_TYPE_PCM:
+               return str_param->sparams.uc.pcm_params.num_chan;
+       case SST_CODEC_TYPE_MP3:
+               return str_param->sparams.uc.mp3_params.num_chan;
+       case SST_CODEC_TYPE_AAC:
+               return str_param->sparams.uc.aac_params.num_chan;
+       default:
+               return -EINVAL;
+       }
+}
+
+/*
+ * sst_get_stream - this function prepares for stream allocation
+ *
+ * @str_param : stream param
+ */
+int sst_get_stream(struct intel_sst_drv *ctx,
+                       struct snd_sst_params *str_param)
+{
+       int retval;
+       struct stream_info *str_info;
+
+       /* stream is not allocated, we are allocating */
+       retval = ctx->ops->alloc_stream(ctx, str_param);
+       if (retval <= 0) {
+               return -EIO;
+       }
+       /* store sampling freq */
+       str_info = &ctx->streams[retval];
+       str_info->sfreq = sst_get_sfreq(str_param);
+
+       return retval;
+}
+
+static int sst_power_control(struct device *dev, bool state)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+       int ret = 0;
+       int usage_count = 0;
+
+#ifdef CONFIG_PM
+       usage_count = atomic_read(&dev->power.usage_count);
+#else
+       usage_count = 1;
+#endif
+
+       if (state == true) {
+               ret = pm_runtime_get_sync(dev);
+
+               dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
+               if (ret < 0) {
+                       dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
+                       return ret;
+               }
+               if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
+                       ret = sst_load_fw(ctx);
+                       if (ret) {
+                               dev_err(dev, "FW download fail %d\n", ret);
+                               sst_set_fw_state_locked(ctx, SST_RESET);
+                               ret = sst_pm_runtime_put(ctx);
+                       }
+               }
+       } else {
+               dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
+               return sst_pm_runtime_put(ctx);
+       }
+       return ret;
+}
+
+/*
+ * sst_open_pcm_stream - Open PCM interface
+ *
+ * @str_param: parameters of pcm stream
+ *
+ * This function is called by MID sound card driver to open
+ * a new pcm interface
+ */
+static int sst_open_pcm_stream(struct device *dev,
+               struct snd_sst_params *str_param)
+{
+       int retval;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (!str_param)
+               return -EINVAL;
+
+       retval = sst_get_stream(ctx, str_param);
+       if (retval > 0)
+               ctx->stream_cnt++;
+       else
+               dev_err(ctx->dev, "sst_get_stream returned err %d\n", retval);
+
+       return retval;
+}
+
+static int sst_cdev_open(struct device *dev,
+               struct snd_sst_params *str_params, struct sst_compress_cb *cb)
+{
+       int str_id, retval;
+       struct stream_info *stream;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       retval = pm_runtime_get_sync(ctx->dev);
+       if (retval < 0)
+               return retval;
+
+       str_id = sst_get_stream(ctx, str_params);
+       if (str_id > 0) {
+               dev_dbg(dev, "stream allocated in sst_cdev_open %d\n", str_id);
+               stream = &ctx->streams[str_id];
+               stream->compr_cb = cb->compr_cb;
+               stream->compr_cb_param = cb->param;
+               stream->drain_notify = cb->drain_notify;
+               stream->drain_cb_param = cb->drain_cb_param;
+       } else {
+               dev_err(dev, "stream encountered error during alloc %d\n", str_id);
+               str_id = -EINVAL;
+               sst_pm_runtime_put(ctx);
+       }
+       return str_id;
+}
+
+static int sst_cdev_close(struct device *dev, unsigned int str_id)
+{
+       int retval;
+       struct stream_info *stream;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       stream = get_stream_info(ctx, str_id);
+       if (!stream) {
+               dev_err(dev, "stream info is NULL for str %d!!!\n", str_id);
+               return -EINVAL;
+       }
+
+       if (stream->status == STREAM_RESET) {
+               dev_dbg(dev, "stream in reset state...\n");
+               stream->status = STREAM_UN_INIT;
+
+               retval = 0;
+               goto put;
+       }
+
+       retval = sst_free_stream(ctx, str_id);
+put:
+       stream->compr_cb_param = NULL;
+       stream->compr_cb = NULL;
+
+       if (retval)
+               dev_err(dev, "free stream returned err %d\n", retval);
+
+       dev_dbg(dev, "End\n");
+       return retval;
+
+}
+
+static int sst_cdev_ack(struct device *dev, unsigned int str_id,
+               unsigned long bytes)
+{
+       struct stream_info *stream;
+       struct snd_sst_tstamp fw_tstamp = {0,};
+       int offset;
+       void __iomem *addr;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       stream = get_stream_info(ctx, str_id);
+       if (!stream)
+               return -EINVAL;
+
+       /* update bytes sent */
+       stream->cumm_bytes += bytes;
+       dev_dbg(dev, "bytes copied %d inc by %ld\n", stream->cumm_bytes, bytes);
+
+       memcpy_fromio(&fw_tstamp,
+               ((void *)(ctx->mailbox + ctx->tstamp)
+               +(str_id * sizeof(fw_tstamp))),
+               sizeof(fw_tstamp));
+
+       fw_tstamp.bytes_copied = stream->cumm_bytes;
+       dev_dbg(dev, "bytes sent to fw %llu inc by %ld\n",
+                       fw_tstamp.bytes_copied, bytes);
+
+       addr =  ((void *)(ctx->mailbox + ctx->tstamp)) +
+                       (str_id * sizeof(fw_tstamp));
+       offset =  offsetof(struct snd_sst_tstamp, bytes_copied);
+       sst_shim_write(addr, offset, fw_tstamp.bytes_copied);
+       return 0;
+}
+
+static int sst_cdev_set_metadata(struct device *dev,
+               unsigned int str_id, struct snd_compr_metadata *metadata)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       dev_dbg(dev, "set metadata for stream %d\n", str_id);
+
+       str_info = get_stream_info(ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+
+       dev_dbg(dev, "pipe id = %d\n", str_info->pipe_id);
+       retval = sst_prepare_and_post_msg(ctx, str_info->task_id, IPC_CMD,
+                       IPC_IA_SET_STREAM_PARAMS_MRFLD, str_info->pipe_id,
+                       sizeof(*metadata), metadata, NULL,
+                       true, true, true, false);
+
+       return retval;
+}
+
+static int sst_cdev_stream_pause(struct device *dev, unsigned int str_id)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       return sst_pause_stream(ctx, str_id);
+}
+
+static int sst_cdev_stream_pause_release(struct device *dev,
+               unsigned int str_id)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       return sst_resume_stream(ctx, str_id);
+}
+
+static int sst_cdev_stream_start(struct device *dev, unsigned int str_id)
+{
+       struct stream_info *str_info;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       str_info = get_stream_info(ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       str_info->prev = str_info->status;
+       str_info->status = STREAM_RUNNING;
+       return sst_start_stream(ctx, str_id);
+}
+
+static int sst_cdev_stream_drop(struct device *dev, unsigned int str_id)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       return sst_drop_stream(ctx, str_id);
+}
+
+static int sst_cdev_stream_drain(struct device *dev, unsigned int str_id)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       return sst_drain_stream(ctx, str_id, false);
+}
+
+static int sst_cdev_stream_partial_drain(struct device *dev,
+               unsigned int str_id)
+{
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       return sst_drain_stream(ctx, str_id, true);
+}
+
+static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
+               struct snd_compr_tstamp *tstamp)
+{
+       struct snd_sst_tstamp fw_tstamp = {0,};
+       struct stream_info *stream;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       memcpy_fromio(&fw_tstamp,
+               ((void *)(ctx->mailbox + ctx->tstamp)
+               +(str_id * sizeof(fw_tstamp))),
+               sizeof(fw_tstamp));
+
+       stream = get_stream_info(ctx, str_id);
+       if (!stream)
+               return -EINVAL;
+       dev_dbg(dev, "rb_counter %llu in bytes\n", fw_tstamp.ring_buffer_counter);
+
+       tstamp->copied_total = fw_tstamp.ring_buffer_counter;
+       tstamp->pcm_frames = fw_tstamp.frames_decoded;
+       tstamp->pcm_io_frames = div_u64(fw_tstamp.hardware_counter,
+                       (u64)((stream->num_ch) * SST_GET_BYTES_PER_SAMPLE(24)));
+       tstamp->sampling_rate = fw_tstamp.sampling_frequency;
+
+       dev_dbg(dev, "PCM  = %u\n", tstamp->pcm_io_frames);
+       dev_dbg(dev, "Ptr Query on strid = %d  copied_total %d, decodec %d\n",
+               str_id, tstamp->copied_total, tstamp->pcm_frames);
+       dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames);
+
+       return 0;
+}
+
+static int sst_cdev_caps(struct snd_compr_caps *caps)
+{
+       caps->num_codecs = NUM_CODEC;
+       caps->min_fragment_size = MIN_FRAGMENT_SIZE;  /* 50KB */
+       caps->max_fragment_size = MAX_FRAGMENT_SIZE;  /* 1024KB */
+       caps->min_fragments = MIN_FRAGMENT;
+       caps->max_fragments = MAX_FRAGMENT;
+       caps->codecs[0] = SND_AUDIOCODEC_MP3;
+       caps->codecs[1] = SND_AUDIOCODEC_AAC;
+       return 0;
+}
+
+static struct snd_compr_codec_caps caps_mp3 = {
+       .num_descriptors = 1,
+       .descriptor[0].max_ch = 2,
+       .descriptor[0].sample_rates[0] = 48000,
+       .descriptor[0].sample_rates[1] = 44100,
+       .descriptor[0].sample_rates[2] = 32000,
+       .descriptor[0].sample_rates[3] = 16000,
+       .descriptor[0].sample_rates[4] = 8000,
+       .descriptor[0].num_sample_rates = 5,
+       .descriptor[0].bit_rate[0] = 320,
+       .descriptor[0].bit_rate[1] = 192,
+       .descriptor[0].num_bitrates = 2,
+       .descriptor[0].profiles = 0,
+       .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
+       .descriptor[0].formats = 0,
+};
+
+static struct snd_compr_codec_caps caps_aac = {
+       .num_descriptors = 2,
+       .descriptor[1].max_ch = 2,
+       .descriptor[0].sample_rates[0] = 48000,
+       .descriptor[0].sample_rates[1] = 44100,
+       .descriptor[0].sample_rates[2] = 32000,
+       .descriptor[0].sample_rates[3] = 16000,
+       .descriptor[0].sample_rates[4] = 8000,
+       .descriptor[0].num_sample_rates = 5,
+       .descriptor[1].bit_rate[0] = 320,
+       .descriptor[1].bit_rate[1] = 192,
+       .descriptor[1].num_bitrates = 2,
+       .descriptor[1].profiles = 0,
+       .descriptor[1].modes = 0,
+       .descriptor[1].formats =
+                       (SND_AUDIOSTREAMFORMAT_MP4ADTS |
+                               SND_AUDIOSTREAMFORMAT_RAW),
+};
+
+static int sst_cdev_codec_caps(struct snd_compr_codec_caps *codec)
+{
+       if (codec->codec == SND_AUDIOCODEC_MP3)
+               *codec = caps_mp3;
+       else if (codec->codec == SND_AUDIOCODEC_AAC)
+               *codec = caps_aac;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+void sst_cdev_fragment_elapsed(struct intel_sst_drv *ctx, int str_id)
+{
+       struct stream_info *stream;
+
+       dev_dbg(ctx->dev, "fragment elapsed from firmware for str_id %d\n",
+                       str_id);
+       stream = &ctx->streams[str_id];
+       if (stream->compr_cb)
+               stream->compr_cb(stream->compr_cb_param);
+}
+
+/*
+ * sst_close_pcm_stream - Close PCM interface
+ *
+ * @str_id: stream id to be closed
+ *
+ * This function is called by MID sound card driver to close
+ * an existing pcm interface
+ */
+static int sst_close_pcm_stream(struct device *dev, unsigned int str_id)
+{
+       struct stream_info *stream;
+       int retval = 0;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       stream = get_stream_info(ctx, str_id);
+       if (!stream) {
+               dev_err(ctx->dev, "stream info is NULL for str %d!!!\n", str_id);
+               return -EINVAL;
+       }
+
+       if (stream->status == STREAM_RESET) {
+               /* silently fail here as we have cleaned the stream earlier */
+               dev_dbg(ctx->dev, "stream in reset state...\n");
+
+               retval = 0;
+               goto put;
+       }
+
+       retval = free_stream_context(ctx, str_id);
+put:
+       stream->pcm_substream = NULL;
+       stream->status = STREAM_UN_INIT;
+       stream->period_elapsed = NULL;
+       ctx->stream_cnt--;
+
+       if (retval)
+               dev_err(ctx->dev, "free stream returned err %d\n", retval);
+
+       dev_dbg(ctx->dev, "Exit\n");
+       return 0;
+}
+
+static inline int sst_calc_tstamp(struct intel_sst_drv *ctx,
+               struct pcm_stream_info *info,
+               struct snd_pcm_substream *substream,
+               struct snd_sst_tstamp *fw_tstamp)
+{
+       size_t delay_bytes, delay_frames;
+       size_t buffer_sz;
+       u32 pointer_bytes, pointer_samples;
+
+       dev_dbg(ctx->dev, "mrfld ring_buffer_counter %llu in bytes\n",
+                       fw_tstamp->ring_buffer_counter);
+       dev_dbg(ctx->dev, "mrfld hardware_counter %llu in bytes\n",
+                        fw_tstamp->hardware_counter);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               delay_bytes = (size_t) (fw_tstamp->ring_buffer_counter -
+                                       fw_tstamp->hardware_counter);
+       else
+               delay_bytes = (size_t) (fw_tstamp->hardware_counter -
+                                       fw_tstamp->ring_buffer_counter);
+       delay_frames = bytes_to_frames(substream->runtime, delay_bytes);
+       buffer_sz = snd_pcm_lib_buffer_bytes(substream);
+       div_u64_rem(fw_tstamp->ring_buffer_counter, buffer_sz, &pointer_bytes);
+       pointer_samples = bytes_to_samples(substream->runtime, pointer_bytes);
+
+       dev_dbg(ctx->dev, "pcm delay %zu in bytes\n", delay_bytes);
+
+       info->buffer_ptr = pointer_samples / substream->runtime->channels;
+
+       info->pcm_delay = delay_frames / substream->runtime->channels;
+       dev_dbg(ctx->dev, "buffer ptr %llu pcm_delay rep: %llu\n",
+                       info->buffer_ptr, info->pcm_delay);
+       return 0;
+}
+
+static int sst_read_timestamp(struct device *dev, struct pcm_stream_info *info)
+{
+       struct stream_info *stream;
+       struct snd_pcm_substream *substream;
+       struct snd_sst_tstamp fw_tstamp;
+       unsigned int str_id;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       str_id = info->str_id;
+       stream = get_stream_info(ctx, str_id);
+       if (!stream)
+               return -EINVAL;
+
+       if (!stream->pcm_substream)
+               return -EINVAL;
+       substream = stream->pcm_substream;
+
+       memcpy_fromio(&fw_tstamp,
+               ((void *)(ctx->mailbox + ctx->tstamp)
+                       + (str_id * sizeof(fw_tstamp))),
+               sizeof(fw_tstamp));
+       return sst_calc_tstamp(ctx, info, substream, &fw_tstamp);
+}
+
+static int sst_stream_start(struct device *dev, int str_id)
+{
+       struct stream_info *str_info;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (ctx->sst_state != SST_FW_RUNNING)
+               return 0;
+       str_info = get_stream_info(ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       str_info->prev = str_info->status;
+       str_info->status = STREAM_RUNNING;
+       sst_start_stream(ctx, str_id);
+
+       return 0;
+}
+
+static int sst_stream_drop(struct device *dev, int str_id)
+{
+       struct stream_info *str_info;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (ctx->sst_state != SST_FW_RUNNING)
+               return 0;
+
+       str_info = get_stream_info(ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       str_info->prev = STREAM_UN_INIT;
+       str_info->status = STREAM_INIT;
+       return sst_drop_stream(ctx, str_id);
+}
+
+static int sst_stream_pause(struct device *dev, int str_id)
+{
+       struct stream_info *str_info;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (ctx->sst_state != SST_FW_RUNNING)
+               return 0;
+
+       str_info = get_stream_info(ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+
+       return sst_pause_stream(ctx, str_id);
+}
+
+static int sst_stream_resume(struct device *dev, int str_id)
+{
+       struct stream_info *str_info;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (ctx->sst_state != SST_FW_RUNNING)
+               return 0;
+
+       str_info = get_stream_info(ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       return sst_resume_stream(ctx, str_id);
+}
+
+static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
+{
+       int str_id = 0;
+       struct stream_info *stream;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       str_id = str_info->str_id;
+
+       if (ctx->sst_state != SST_FW_RUNNING)
+               return 0;
+
+       stream = get_stream_info(ctx, str_id);
+       if (!stream)
+               return -EINVAL;
+
+       dev_dbg(ctx->dev, "setting the period ptrs\n");
+       stream->pcm_substream = str_info->arg;
+       stream->period_elapsed = str_info->period_elapsed;
+       stream->sfreq = str_info->sfreq;
+       stream->prev = stream->status;
+       stream->status = STREAM_INIT;
+       dev_dbg(ctx->dev,
+               "pcm_substream %p, period_elapsed %p, sfreq %d, status %d\n",
+               stream->pcm_substream, stream->period_elapsed,
+               stream->sfreq, stream->status);
+
+       return 0;
+}
+
+/*
+ * sst_set_byte_stream - 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_send_byte_stream(struct device *dev,
+               struct snd_sst_bytes_v2 *bytes)
+{
+       int ret_val = 0;
+       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
+
+       if (NULL == bytes)
+               return -EINVAL;
+       ret_val = pm_runtime_get_sync(ctx->dev);
+       if (ret_val < 0)
+               return ret_val;
+
+       ret_val = sst_send_byte_stream_mrfld(ctx, bytes);
+       sst_pm_runtime_put(ctx);
+
+       return ret_val;
+}
+
+static struct sst_ops pcm_ops = {
+       .open = sst_open_pcm_stream,
+       .stream_init = sst_stream_init,
+       .stream_start = sst_stream_start,
+       .stream_drop = sst_stream_drop,
+       .stream_pause = sst_stream_pause,
+       .stream_pause_release = sst_stream_resume,
+       .stream_read_tstamp = sst_read_timestamp,
+       .send_byte_stream = sst_send_byte_stream,
+       .close = sst_close_pcm_stream,
+       .power = sst_power_control,
+};
+
+static struct compress_sst_ops compr_ops = {
+       .open = sst_cdev_open,
+       .close = sst_cdev_close,
+       .stream_pause = sst_cdev_stream_pause,
+       .stream_pause_release = sst_cdev_stream_pause_release,
+       .stream_start = sst_cdev_stream_start,
+       .stream_drop = sst_cdev_stream_drop,
+       .stream_drain = sst_cdev_stream_drain,
+       .stream_partial_drain = sst_cdev_stream_partial_drain,
+       .tstamp = sst_cdev_tstamp,
+       .ack = sst_cdev_ack,
+       .get_caps = sst_cdev_caps,
+       .get_codec_caps = sst_cdev_codec_caps,
+       .set_metadata = sst_cdev_set_metadata,
+       .power = sst_power_control,
+};
+
+static struct sst_device sst_dsp_device = {
+       .name = "Intel(R) SST LPE",
+       .dev = NULL,
+       .ops = &pcm_ops,
+       .compr_ops = &compr_ops,
+};
+
+/*
+ * sst_register - function to register DSP
+ *
+ * This functions registers DSP with the platform driver
+ */
+int sst_register(struct device *dev)
+{
+       int ret_val;
+
+       sst_dsp_device.dev = dev;
+       ret_val = sst_register_dsp(&sst_dsp_device);
+       if (ret_val)
+               dev_err(dev, "Unable to register DSP with platform driver\n");
+
+       return ret_val;
+}
+
+int sst_unregister(struct device *dev)
+{
+       return sst_unregister_dsp(&sst_dsp_device);
+}
diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c
new file mode 100644 (file)
index 0000000..5a27861
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *  sst_ipc.c - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14 Intel Corporation
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <asm/intel-mid.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+#include "../../common/sst-dsp.h"
+
+struct sst_block *sst_create_block(struct intel_sst_drv *ctx,
+                                       u32 msg_id, u32 drv_id)
+{
+       struct sst_block *msg = NULL;
+
+       dev_dbg(ctx->dev, "Enter\n");
+       msg = kzalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return NULL;
+       msg->condition = false;
+       msg->on = true;
+       msg->msg_id = msg_id;
+       msg->drv_id = drv_id;
+       spin_lock_bh(&ctx->block_lock);
+       list_add_tail(&msg->node, &ctx->block_list);
+       spin_unlock_bh(&ctx->block_lock);
+
+       return msg;
+}
+
+/*
+ * while handling the interrupts, we need to check for message status and
+ * then if we are blocking for a message
+ *
+ * here we are unblocking the blocked ones, this is based on id we have
+ * passed and search that for block threads.
+ * We will not find block in two cases
+ *  a) when its small message and block in not there, so silently ignore
+ *  them
+ *  b) when we are actually not able to find the block (bug perhaps)
+ *
+ *  Since we have bit of small messages we can spam kernel log with err
+ *  print on above so need to keep as debug prints which should be enabled
+ *  via dynamic debug while debugging IPC issues
+ */
+int sst_wake_up_block(struct intel_sst_drv *ctx, int result,
+               u32 drv_id, u32 ipc, void *data, u32 size)
+{
+       struct sst_block *block = NULL;
+
+       dev_dbg(ctx->dev, "Enter\n");
+
+       spin_lock_bh(&ctx->block_lock);
+       list_for_each_entry(block, &ctx->block_list, node) {
+               dev_dbg(ctx->dev, "Block ipc %d, drv_id %d\n", block->msg_id,
+                                                       block->drv_id);
+               if (block->msg_id == ipc && block->drv_id == drv_id) {
+                       dev_dbg(ctx->dev, "free up the block\n");
+                       block->ret_code = result;
+                       block->data = data;
+                       block->size = size;
+                       block->condition = true;
+                       spin_unlock_bh(&ctx->block_lock);
+                       wake_up(&ctx->wait_queue);
+                       return 0;
+               }
+       }
+       spin_unlock_bh(&ctx->block_lock);
+       dev_dbg(ctx->dev,
+               "Block not found or a response received for a short msg for ipc %d, drv_id %d\n",
+               ipc, drv_id);
+       return -EINVAL;
+}
+
+int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed)
+{
+       struct sst_block *block = NULL, *__block;
+
+       dev_dbg(ctx->dev, "Enter\n");
+       spin_lock_bh(&ctx->block_lock);
+       list_for_each_entry_safe(block, __block, &ctx->block_list, node) {
+               if (block == freed) {
+                       pr_debug("pvt_id freed --> %d\n", freed->drv_id);
+                       /* toggle the index position of pvt_id */
+                       list_del(&freed->node);
+                       spin_unlock_bh(&ctx->block_lock);
+                       kfree(freed->data);
+                       freed->data = NULL;
+                       kfree(freed);
+                       return 0;
+               }
+       }
+       spin_unlock_bh(&ctx->block_lock);
+       dev_err(ctx->dev, "block is already freed!!!\n");
+       return -EINVAL;
+}
+
+int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx,
+               struct ipc_post *ipc_msg, bool sync)
+{
+       struct ipc_post *msg = ipc_msg;
+       union ipc_header_mrfld header;
+       unsigned int loop_count = 0;
+       int retval = 0;
+       unsigned long irq_flags;
+
+       dev_dbg(sst_drv_ctx->dev, "Enter: sync: %d\n", sync);
+       spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
+       header.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCX);
+       if (sync) {
+               while (header.p.header_high.part.busy) {
+                       if (loop_count > 25) {
+                               dev_err(sst_drv_ctx->dev,
+                                       "sst: Busy wait failed, cant send this msg\n");
+                               retval = -EBUSY;
+                               goto out;
+                       }
+                       cpu_relax();
+                       loop_count++;
+                       header.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCX);
+               }
+       } else {
+               if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) {
+                       /* queue is empty, nothing to send */
+                       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
+                       dev_dbg(sst_drv_ctx->dev,
+                                       "Empty msg queue... NO Action\n");
+                       return 0;
+               }
+
+               if (header.p.header_high.part.busy) {
+                       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
+                       dev_dbg(sst_drv_ctx->dev, "Busy not free... post later\n");
+                       return 0;
+               }
+
+               /* copy msg from list */
+               msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next,
+                               struct ipc_post, node);
+               list_del(&msg->node);
+       }
+       dev_dbg(sst_drv_ctx->dev, "sst: Post message: header = %x\n",
+                               msg->mrfld_header.p.header_high.full);
+       dev_dbg(sst_drv_ctx->dev, "sst: size = 0x%x\n",
+                       msg->mrfld_header.p.header_low_payload);
+
+       if (msg->mrfld_header.p.header_high.part.large)
+               memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND,
+                       msg->mailbox_data,
+                       msg->mrfld_header.p.header_low_payload);
+
+       sst_shim_write64(sst_drv_ctx->shim, SST_IPCX, msg->mrfld_header.full);
+
+out:
+       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
+       kfree(msg->mailbox_data);
+       kfree(msg);
+       return retval;
+}
+
+void intel_sst_clear_intr_mrfld(struct intel_sst_drv *sst_drv_ctx)
+{
+       union interrupt_reg_mrfld isr;
+       union interrupt_reg_mrfld imr;
+       union ipc_header_mrfld clear_ipc;
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
+       imr.full = sst_shim_read64(sst_drv_ctx->shim, SST_IMRX);
+       isr.full = sst_shim_read64(sst_drv_ctx->shim, SST_ISRX);
+
+       /* write 1 to clear*/
+       isr.part.busy_interrupt = 1;
+       sst_shim_write64(sst_drv_ctx->shim, SST_ISRX, isr.full);
+
+       /* Set IA done bit */
+       clear_ipc.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCD);
+
+       clear_ipc.p.header_high.part.busy = 0;
+       clear_ipc.p.header_high.part.done = 1;
+       clear_ipc.p.header_low_payload = IPC_ACK_SUCCESS;
+       sst_shim_write64(sst_drv_ctx->shim, SST_IPCD, clear_ipc.full);
+       /* un mask busy interrupt */
+       imr.part.busy_interrupt = 0;
+       sst_shim_write64(sst_drv_ctx->shim, SST_IMRX, imr.full);
+       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
+}
+
+
+/*
+ * process_fw_init - process the FW init msg
+ *
+ * @msg: IPC message mailbox data from FW
+ *
+ * This function processes the FW init msg from FW
+ * marks FW state and prints debug info of loaded FW
+ */
+static void process_fw_init(struct intel_sst_drv *sst_drv_ctx,
+                       void *msg)
+{
+       struct ipc_header_fw_init *init =
+               (struct ipc_header_fw_init *)msg;
+       int retval = 0;
+
+       dev_dbg(sst_drv_ctx->dev, "*** FW Init msg came***\n");
+       if (init->result) {
+               sst_set_fw_state_locked(sst_drv_ctx, SST_RESET);
+               dev_err(sst_drv_ctx->dev, "FW Init failed, Error %x\n",
+                               init->result);
+               retval = init->result;
+               goto ret;
+       }
+
+ret:
+       sst_wake_up_block(sst_drv_ctx, retval, FW_DWNL_ID, 0 , NULL, 0);
+}
+
+static void process_fw_async_msg(struct intel_sst_drv *sst_drv_ctx,
+                       struct ipc_post *msg)
+{
+       u32 msg_id;
+       int str_id;
+       u32 data_size, i;
+       void *data_offset;
+       struct stream_info *stream;
+       union ipc_header_high msg_high;
+       u32 msg_low, pipe_id;
+
+       msg_high = msg->mrfld_header.p.header_high;
+       msg_low = msg->mrfld_header.p.header_low_payload;
+       msg_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->cmd_id;
+       data_offset = (msg->mailbox_data + sizeof(struct ipc_dsp_hdr));
+       data_size =  msg_low - (sizeof(struct ipc_dsp_hdr));
+
+       switch (msg_id) {
+       case IPC_SST_PERIOD_ELAPSED_MRFLD:
+               pipe_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->pipe_id;
+               str_id = get_stream_id_mrfld(sst_drv_ctx, pipe_id);
+               if (str_id > 0) {
+                       dev_dbg(sst_drv_ctx->dev,
+                               "Period elapsed rcvd for pipe id 0x%x\n",
+                               pipe_id);
+                       stream = &sst_drv_ctx->streams[str_id];
+                       if (stream->period_elapsed)
+                               stream->period_elapsed(stream->pcm_substream);
+                       if (stream->compr_cb)
+                               stream->compr_cb(stream->compr_cb_param);
+               }
+               break;
+
+       case IPC_IA_DRAIN_STREAM_MRFLD:
+               pipe_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->pipe_id;
+               str_id = get_stream_id_mrfld(sst_drv_ctx, pipe_id);
+               if (str_id > 0) {
+                       stream = &sst_drv_ctx->streams[str_id];
+                       if (stream->drain_notify)
+                               stream->drain_notify(stream->drain_cb_param);
+               }
+               break;
+
+       case IPC_IA_FW_ASYNC_ERR_MRFLD:
+               dev_err(sst_drv_ctx->dev, "FW sent async error msg:\n");
+               for (i = 0; i < (data_size/4); i++)
+                       print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE,
+                                       16, 4, data_offset, data_size, false);
+               break;
+
+       case IPC_IA_FW_INIT_CMPLT_MRFLD:
+               process_fw_init(sst_drv_ctx, data_offset);
+               break;
+
+       case IPC_IA_BUF_UNDER_RUN_MRFLD:
+               pipe_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->pipe_id;
+               str_id = get_stream_id_mrfld(sst_drv_ctx, pipe_id);
+               if (str_id > 0)
+                       dev_err(sst_drv_ctx->dev,
+                               "Buffer under-run for pipe:%#x str_id:%d\n",
+                               pipe_id, str_id);
+               break;
+
+       default:
+               dev_err(sst_drv_ctx->dev,
+                       "Unrecognized async msg from FW msg_id %#x\n", msg_id);
+       }
+}
+
+void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx,
+               struct ipc_post *msg)
+{
+       unsigned int drv_id;
+       void *data;
+       union ipc_header_high msg_high;
+       u32 msg_low;
+       struct ipc_dsp_hdr *dsp_hdr;
+       unsigned int cmd_id;
+
+       msg_high = msg->mrfld_header.p.header_high;
+       msg_low = msg->mrfld_header.p.header_low_payload;
+
+       dev_dbg(sst_drv_ctx->dev, "IPC process message header %x payload %x\n",
+                       msg->mrfld_header.p.header_high.full,
+                       msg->mrfld_header.p.header_low_payload);
+
+       drv_id = msg_high.part.drv_id;
+
+       /* Check for async messages first */
+       if (drv_id == SST_ASYNC_DRV_ID) {
+               /*FW sent async large message*/
+               process_fw_async_msg(sst_drv_ctx, msg);
+               return;
+       }
+
+       /* FW sent short error response for an IPC */
+       if (msg_high.part.result && drv_id && !msg_high.part.large) {
+               /* 32-bit FW error code in msg_low */
+               dev_err(sst_drv_ctx->dev, "FW sent error response 0x%x", msg_low);
+               sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
+                       msg_high.part.drv_id,
+                       msg_high.part.msg_id, NULL, 0);
+               return;
+       }
+
+       /*
+        * Process all valid responses
+        * if it is a large message, the payload contains the size to
+        * copy from mailbox
+        **/
+       if (msg_high.part.large) {
+               data = kzalloc(msg_low, GFP_KERNEL);
+               if (!data)
+                       return;
+               memcpy(data, (void *) msg->mailbox_data, msg_low);
+               /* Copy command id so that we can use to put sst to reset */
+               dsp_hdr = (struct ipc_dsp_hdr *)data;
+               cmd_id = dsp_hdr->cmd_id;
+               dev_dbg(sst_drv_ctx->dev, "cmd_id %d\n", dsp_hdr->cmd_id);
+               if (sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
+                               msg_high.part.drv_id,
+                               msg_high.part.msg_id, data, msg_low))
+                       kfree(data);
+       } else {
+               sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
+                               msg_high.part.drv_id,
+                               msg_high.part.msg_id, NULL, 0);
+       }
+
+}
diff --git a/sound/soc/intel/atom/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c
new file mode 100644 (file)
index 0000000..3391714
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ *  sst_dsp.c - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14      Intel Corp
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This file contains all dsp controlling functions like firmware download,
+ * setting/resetting dsp cores, etc
+ */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/firmware.h>
+#include <linux/dmaengine.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+#include "../../common/sst-dsp.h"
+
+void memcpy32_toio(void __iomem *dst, const void *src, int count)
+{
+       /* __iowrite32_copy uses 32-bit count values so divide by 4 for
+        * right count in words
+        */
+       __iowrite32_copy(dst, src, count/4);
+}
+
+void memcpy32_fromio(void *dst, const void __iomem *src, int count)
+{
+       /* __iowrite32_copy uses 32-bit count values so divide by 4 for
+        * right count in words
+        */
+       __iowrite32_copy(dst, src, count/4);
+}
+
+/**
+ * intel_sst_reset_dsp_mrfld - Resetting SST DSP
+ *
+ * This resets DSP in case of MRFLD platfroms
+ */
+int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx)
+{
+       union config_status_reg_mrfld csr;
+
+       dev_dbg(sst_drv_ctx->dev, "sst: Resetting the DSP in mrfld\n");
+       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
+
+       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
+
+       csr.full |= 0x7;
+       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
+       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
+
+       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
+
+       csr.full &= ~(0x1);
+       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
+
+       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
+       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
+       return 0;
+}
+
+/**
+ * sst_start_merrifield - Start the SST DSP processor
+ *
+ * This starts the DSP in MERRIFIELD platfroms
+ */
+int sst_start_mrfld(struct intel_sst_drv *sst_drv_ctx)
+{
+       union config_status_reg_mrfld csr;
+
+       dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP in mrfld LALALALA\n");
+       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
+       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
+
+       csr.full |= 0x7;
+       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
+
+       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
+       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
+
+       csr.part.xt_snoop = 1;
+       csr.full &= ~(0x5);
+       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
+
+       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
+       dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP_merrifield:%llx\n",
+                       csr.full);
+       return 0;
+}
+
+static int sst_validate_fw_image(struct intel_sst_drv *ctx, unsigned long size,
+               struct fw_module_header **module, u32 *num_modules)
+{
+       struct sst_fw_header *header;
+       const void *sst_fw_in_mem = ctx->fw_in_mem;
+
+       dev_dbg(ctx->dev, "Enter\n");
+
+       /* Read the header information from the data pointer */
+       header = (struct sst_fw_header *)sst_fw_in_mem;
+       dev_dbg(ctx->dev,
+               "header sign=%s size=%x modules=%x fmt=%x size=%zx\n",
+               header->signature, header->file_size, header->modules,
+               header->file_format, sizeof(*header));
+
+       /* verify FW */
+       if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) ||
+               (size != header->file_size + sizeof(*header))) {
+               /* Invalid FW signature */
+               dev_err(ctx->dev, "InvalidFW sign/filesize mismatch\n");
+               return -EINVAL;
+       }
+       *num_modules = header->modules;
+       *module = (void *)sst_fw_in_mem + sizeof(*header);
+
+       return 0;
+}
+
+/*
+ * sst_fill_memcpy_list - Fill the memcpy list
+ *
+ * @memcpy_list: List to be filled
+ * @destn: Destination addr to be filled in the list
+ * @src: Source addr to be filled in the list
+ * @size: Size to be filled in the list
+ *
+ * Adds the node to the list after required fields
+ * are populated in the node
+ */
+static int sst_fill_memcpy_list(struct list_head *memcpy_list,
+                       void *destn, const void *src, u32 size, bool is_io)
+{
+       struct sst_memcpy_list *listnode;
+
+       listnode = kzalloc(sizeof(*listnode), GFP_KERNEL);
+       if (listnode == NULL)
+               return -ENOMEM;
+       listnode->dstn = destn;
+       listnode->src = src;
+       listnode->size = size;
+       listnode->is_io = is_io;
+       list_add_tail(&listnode->memcpylist, memcpy_list);
+
+       return 0;
+}
+
+/**
+ * sst_parse_module_memcpy - Parse audio FW modules and populate the memcpy list
+ *
+ * @sst_drv_ctx                : driver context
+ * @module             : FW module header
+ * @memcpy_list        : Pointer to the list to be populated
+ * Create the memcpy list as the number of block to be copied
+ * returns error or 0 if module sizes are proper
+ */
+static int sst_parse_module_memcpy(struct intel_sst_drv *sst_drv_ctx,
+               struct fw_module_header *module, struct list_head *memcpy_list)
+{
+       struct fw_block_info *block;
+       u32 count;
+       int ret_val = 0;
+       void __iomem *ram_iomem;
+
+       dev_dbg(sst_drv_ctx->dev, "module sign %s size %x blocks %x type %x\n",
+                       module->signature, module->mod_size,
+                       module->blocks, module->type);
+       dev_dbg(sst_drv_ctx->dev, "module entrypoint 0x%x\n", module->entry_point);
+
+       block = (void *)module + sizeof(*module);
+
+       for (count = 0; count < module->blocks; count++) {
+               if (block->size <= 0) {
+                       dev_err(sst_drv_ctx->dev, "block size invalid\n");
+                       return -EINVAL;
+               }
+               switch (block->type) {
+               case SST_IRAM:
+                       ram_iomem = sst_drv_ctx->iram;
+                       break;
+               case SST_DRAM:
+                       ram_iomem = sst_drv_ctx->dram;
+                       break;
+               case SST_DDR:
+                       ram_iomem = sst_drv_ctx->ddr;
+                       break;
+               case SST_CUSTOM_INFO:
+                       block = (void *)block + sizeof(*block) + block->size;
+                       continue;
+               default:
+                       dev_err(sst_drv_ctx->dev, "wrong ram type0x%x in block0x%x\n",
+                                       block->type, count);
+                       return -EINVAL;
+               }
+
+               ret_val = sst_fill_memcpy_list(memcpy_list,
+                               ram_iomem + block->ram_offset,
+                               (void *)block + sizeof(*block), block->size, 1);
+               if (ret_val)
+                       return ret_val;
+
+               block = (void *)block + sizeof(*block) + block->size;
+       }
+       return 0;
+}
+
+/**
+ * sst_parse_fw_memcpy - parse the firmware image & populate the list for memcpy
+ *
+ * @ctx                        : pointer to drv context
+ * @size               : size of the firmware
+ * @fw_list            : pointer to list_head to be populated
+ * This function parses the FW image and saves the parsed image in the list
+ * for memcpy
+ */
+static int sst_parse_fw_memcpy(struct intel_sst_drv *ctx, unsigned long size,
+                               struct list_head *fw_list)
+{
+       struct fw_module_header *module;
+       u32 count, num_modules;
+       int ret_val;
+
+       ret_val = sst_validate_fw_image(ctx, size, &module, &num_modules);
+       if (ret_val)
+               return ret_val;
+
+       for (count = 0; count < num_modules; count++) {
+               ret_val = sst_parse_module_memcpy(ctx, module, fw_list);
+               if (ret_val)
+                       return ret_val;
+               module = (void *)module + sizeof(*module) + module->mod_size;
+       }
+
+       return 0;
+}
+
+/**
+ * sst_do_memcpy - function initiates the memcpy
+ *
+ * @memcpy_list: Pter to memcpy list on which the memcpy needs to be initiated
+ *
+ * Triggers the memcpy
+ */
+static void sst_do_memcpy(struct list_head *memcpy_list)
+{
+       struct sst_memcpy_list *listnode;
+
+       list_for_each_entry(listnode, memcpy_list, memcpylist) {
+               if (listnode->is_io == true)
+                       memcpy32_toio((void __iomem *)listnode->dstn,
+                                       listnode->src, listnode->size);
+               else
+                       memcpy(listnode->dstn, listnode->src, listnode->size);
+       }
+}
+
+void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx)
+{
+       struct sst_memcpy_list *listnode, *tmplistnode;
+
+       /* Free the list */
+       if (!list_empty(&sst_drv_ctx->memcpy_list)) {
+               list_for_each_entry_safe(listnode, tmplistnode,
+                               &sst_drv_ctx->memcpy_list, memcpylist) {
+                       list_del(&listnode->memcpylist);
+                       kfree(listnode);
+               }
+       }
+}
+
+static int sst_cache_and_parse_fw(struct intel_sst_drv *sst,
+               const struct firmware *fw)
+{
+       int retval = 0;
+
+       sst->fw_in_mem = kzalloc(fw->size, GFP_KERNEL);
+       if (!sst->fw_in_mem) {
+               retval = -ENOMEM;
+               goto end_release;
+       }
+       dev_dbg(sst->dev, "copied fw to %p", sst->fw_in_mem);
+       dev_dbg(sst->dev, "phys: %lx", (unsigned long)virt_to_phys(sst->fw_in_mem));
+       memcpy(sst->fw_in_mem, fw->data, fw->size);
+       retval = sst_parse_fw_memcpy(sst, fw->size, &sst->memcpy_list);
+       if (retval) {
+               dev_err(sst->dev, "Failed to parse fw\n");
+               kfree(sst->fw_in_mem);
+               sst->fw_in_mem = NULL;
+       }
+
+end_release:
+       release_firmware(fw);
+       return retval;
+
+}
+
+void sst_firmware_load_cb(const struct firmware *fw, void *context)
+{
+       struct intel_sst_drv *ctx = context;
+
+       dev_dbg(ctx->dev, "Enter\n");
+
+       if (fw == NULL) {
+               dev_err(ctx->dev, "request fw failed\n");
+               return;
+       }
+
+       mutex_lock(&ctx->sst_lock);
+
+       if (ctx->sst_state != SST_RESET ||
+                       ctx->fw_in_mem != NULL) {
+               release_firmware(fw);
+               mutex_unlock(&ctx->sst_lock);
+               return;
+       }
+
+       dev_dbg(ctx->dev, "Request Fw completed\n");
+       sst_cache_and_parse_fw(ctx, fw);
+       mutex_unlock(&ctx->sst_lock);
+}
+
+/*
+ * sst_request_fw - requests audio fw from kernel and saves a copy
+ *
+ * This function requests the SST FW from the kernel, parses it and
+ * saves a copy in the driver context
+ */
+static int sst_request_fw(struct intel_sst_drv *sst)
+{
+       int retval = 0;
+       const struct firmware *fw;
+
+       retval = request_firmware(&fw, sst->firmware_name, sst->dev);
+       if (fw == NULL) {
+               dev_err(sst->dev, "fw is returning as null\n");
+               return -EINVAL;
+       }
+       if (retval) {
+               dev_err(sst->dev, "request fw failed %d\n", retval);
+               return retval;
+       }
+       mutex_lock(&sst->sst_lock);
+       retval = sst_cache_and_parse_fw(sst, fw);
+       mutex_unlock(&sst->sst_lock);
+
+       return retval;
+}
+
+/*
+ * Writing the DDR physical base to DCCM offset
+ * so that FW can use it to setup TLB
+ */
+static void sst_dccm_config_write(void __iomem *dram_base,
+               unsigned int ddr_base)
+{
+       void __iomem *addr;
+       u32 bss_reset = 0;
+
+       addr = (void __iomem *)(dram_base + MRFLD_FW_DDR_BASE_OFFSET);
+       memcpy32_toio(addr, (void *)&ddr_base, sizeof(u32));
+       bss_reset |= (1 << MRFLD_FW_BSS_RESET_BIT);
+       addr = (void __iomem *)(dram_base + MRFLD_FW_FEATURE_BASE_OFFSET);
+       memcpy32_toio(addr, &bss_reset, sizeof(u32));
+
+}
+
+void sst_post_download_mrfld(struct intel_sst_drv *ctx)
+{
+       sst_dccm_config_write(ctx->dram, ctx->ddr_base);
+       dev_dbg(ctx->dev, "config written to DCCM\n");
+}
+
+/**
+ * sst_load_fw - function to load FW into DSP
+ * Transfers the FW to DSP using dma/memcpy
+ */
+int sst_load_fw(struct intel_sst_drv *sst_drv_ctx)
+{
+       int ret_val = 0;
+       struct sst_block *block;
+
+       dev_dbg(sst_drv_ctx->dev, "sst_load_fw\n");
+
+       if (sst_drv_ctx->sst_state !=  SST_RESET ||
+                       sst_drv_ctx->sst_state == SST_SHUTDOWN)
+               return -EAGAIN;
+
+       if (!sst_drv_ctx->fw_in_mem) {
+               dev_dbg(sst_drv_ctx->dev, "sst: FW not in memory retry to download\n");
+               ret_val = sst_request_fw(sst_drv_ctx);
+               if (ret_val)
+                       return ret_val;
+       }
+
+       BUG_ON(!sst_drv_ctx->fw_in_mem);
+       block = sst_create_block(sst_drv_ctx, 0, FW_DWNL_ID);
+       if (block == NULL)
+               return -ENOMEM;
+
+       /* Prevent C-states beyond C6 */
+       pm_qos_update_request(sst_drv_ctx->qos, 0);
+
+       sst_drv_ctx->sst_state = SST_FW_LOADING;
+
+       ret_val = sst_drv_ctx->ops->reset(sst_drv_ctx);
+       if (ret_val)
+               goto restore;
+
+       sst_do_memcpy(&sst_drv_ctx->memcpy_list);
+
+       /* Write the DRAM/DCCM config before enabling FW */
+       if (sst_drv_ctx->ops->post_download)
+               sst_drv_ctx->ops->post_download(sst_drv_ctx);
+
+       /* bring sst out of reset */
+       ret_val = sst_drv_ctx->ops->start(sst_drv_ctx);
+       if (ret_val)
+               goto restore;
+
+       ret_val = sst_wait_timeout(sst_drv_ctx, block);
+       if (ret_val) {
+               dev_err(sst_drv_ctx->dev, "fw download failed %d\n" , ret_val);
+               /* FW download failed due to timeout */
+               ret_val = -EBUSY;
+
+       }
+
+
+restore:
+       /* Re-enable Deeper C-states beyond C6 */
+       pm_qos_update_request(sst_drv_ctx->qos, PM_QOS_DEFAULT_VALUE);
+       sst_free_block(sst_drv_ctx, block);
+       dev_dbg(sst_drv_ctx->dev, "fw load successful!!!\n");
+
+       if (sst_drv_ctx->ops->restore_dsp_context)
+               sst_drv_ctx->ops->restore_dsp_context();
+       sst_drv_ctx->sst_state = SST_FW_RUNNING;
+       return ret_val;
+}
+
diff --git a/sound/soc/intel/atom/sst/sst_pci.c b/sound/soc/intel/atom/sst/sst_pci.c
new file mode 100644 (file)
index 0000000..3a0b3bf
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  sst_pci.c - SST (LPE) driver init file for pci enumeration.
+ *
+ *  Copyright (C) 2008-14      Intel Corp
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+
+static int sst_platform_get_resources(struct intel_sst_drv *ctx)
+{
+       int ddr_base, ret = 0;
+       struct pci_dev *pci = ctx->pci;
+
+       ret = pci_request_regions(pci, SST_DRV_NAME);
+       if (ret)
+               return ret;
+
+       /* map registers */
+       /* DDR base */
+       if (ctx->dev_id == SST_MRFLD_PCI_ID) {
+               ctx->ddr_base = pci_resource_start(pci, 0);
+               /* check that the relocated IMR base matches with FW Binary */
+               ddr_base = relocate_imr_addr_mrfld(ctx->ddr_base);
+               if (!ctx->pdata->lib_info) {
+                       dev_err(ctx->dev, "lib_info pointer NULL\n");
+                       ret = -EINVAL;
+                       goto do_release_regions;
+               }
+               if (ddr_base != ctx->pdata->lib_info->mod_base) {
+                       dev_err(ctx->dev,
+                                       "FW LSP DDR BASE does not match with IFWI\n");
+                       ret = -EINVAL;
+                       goto do_release_regions;
+               }
+               ctx->ddr_end = pci_resource_end(pci, 0);
+
+               ctx->ddr = pcim_iomap(pci, 0,
+                                       pci_resource_len(pci, 0));
+               if (!ctx->ddr) {
+                       ret = -EINVAL;
+                       goto do_release_regions;
+               }
+               dev_dbg(ctx->dev, "sst: DDR Ptr %p\n", ctx->ddr);
+       } else {
+               ctx->ddr = NULL;
+       }
+       /* SHIM */
+       ctx->shim_phy_add = pci_resource_start(pci, 1);
+       ctx->shim = pcim_iomap(pci, 1, pci_resource_len(pci, 1));
+       if (!ctx->shim) {
+               ret = -EINVAL;
+               goto do_release_regions;
+       }
+       dev_dbg(ctx->dev, "SST Shim Ptr %p\n", ctx->shim);
+
+       /* Shared SRAM */
+       ctx->mailbox_add = pci_resource_start(pci, 2);
+       ctx->mailbox = pcim_iomap(pci, 2, pci_resource_len(pci, 2));
+       if (!ctx->mailbox) {
+               ret = -EINVAL;
+               goto do_release_regions;
+       }
+       dev_dbg(ctx->dev, "SRAM Ptr %p\n", ctx->mailbox);
+
+       /* IRAM */
+       ctx->iram_end = pci_resource_end(pci, 3);
+       ctx->iram_base = pci_resource_start(pci, 3);
+       ctx->iram = pcim_iomap(pci, 3, pci_resource_len(pci, 3));
+       if (!ctx->iram) {
+               ret = -EINVAL;
+               goto do_release_regions;
+       }
+       dev_dbg(ctx->dev, "IRAM Ptr %p\n", ctx->iram);
+
+       /* DRAM */
+       ctx->dram_end = pci_resource_end(pci, 4);
+       ctx->dram_base = pci_resource_start(pci, 4);
+       ctx->dram = pcim_iomap(pci, 4, pci_resource_len(pci, 4));
+       if (!ctx->dram) {
+               ret = -EINVAL;
+               goto do_release_regions;
+       }
+       dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram);
+do_release_regions:
+       pci_release_regions(pci);
+       return 0;
+}
+
+/*
+ * intel_sst_probe - PCI probe function
+ *
+ * @pci:       PCI device structure
+ * @pci_id: PCI device ID structure
+ *
+ */
+static int intel_sst_probe(struct pci_dev *pci,
+                       const struct pci_device_id *pci_id)
+{
+       int ret = 0;
+       struct intel_sst_drv *sst_drv_ctx;
+       struct sst_platform_info *sst_pdata = pci->dev.platform_data;
+
+       dev_dbg(&pci->dev, "Probe for DID %x\n", pci->device);
+       ret = sst_alloc_drv_context(&sst_drv_ctx, &pci->dev, pci->device);
+       if (ret < 0)
+               return ret;
+
+       sst_drv_ctx->pdata = sst_pdata;
+       sst_drv_ctx->irq_num = pci->irq;
+       snprintf(sst_drv_ctx->firmware_name, sizeof(sst_drv_ctx->firmware_name),
+                       "%s%04x%s", "fw_sst_",
+                       sst_drv_ctx->dev_id, ".bin");
+
+       ret = sst_context_init(sst_drv_ctx);
+       if (ret < 0)
+               return ret;
+
+       /* Init the device */
+       ret = pcim_enable_device(pci);
+       if (ret) {
+               dev_err(sst_drv_ctx->dev,
+                       "device can't be enabled. Returned err: %d\n", ret);
+               goto do_free_drv_ctx;
+       }
+       sst_drv_ctx->pci = pci_dev_get(pci);
+       ret = sst_platform_get_resources(sst_drv_ctx);
+       if (ret < 0)
+               goto do_free_drv_ctx;
+
+       pci_set_drvdata(pci, sst_drv_ctx);
+       sst_configure_runtime_pm(sst_drv_ctx);
+
+       return ret;
+
+do_free_drv_ctx:
+       sst_context_cleanup(sst_drv_ctx);
+       dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret);
+       return ret;
+}
+
+/**
+ * intel_sst_remove - PCI remove function
+ *
+ * @pci:       PCI device structure
+ *
+ * This function is called by OS when a device is unloaded
+ * This frees the interrupt etc
+ */
+static void intel_sst_remove(struct pci_dev *pci)
+{
+       struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci);
+
+       sst_context_cleanup(sst_drv_ctx);
+       pci_dev_put(sst_drv_ctx->pci);
+       pci_release_regions(pci);
+       pci_set_drvdata(pci, NULL);
+}
+
+/* PCI Routines */
+static struct pci_device_id intel_sst_ids[] = {
+       { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0},
+       { 0, }
+};
+
+static struct pci_driver sst_driver = {
+       .name = SST_DRV_NAME,
+       .id_table = intel_sst_ids,
+       .probe = intel_sst_probe,
+       .remove = intel_sst_remove,
+#ifdef CONFIG_PM
+       .driver = {
+               .pm = &intel_sst_pm,
+       },
+#endif
+};
+
+module_pci_driver(sst_driver);
+
+MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
+MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
+MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("sst");
diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c
new file mode 100644 (file)
index 0000000..3c17844
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ *  sst_pvt.c - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14      Intel Corp
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/kobject.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <sound/asound.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+#include "../../common/sst-dsp.h"
+
+int sst_shim_write(void __iomem *addr, int offset, int value)
+{
+       writel(value, addr + offset);
+       return 0;
+}
+
+u32 sst_shim_read(void __iomem *addr, int offset)
+{
+       return readl(addr + offset);
+}
+
+u64 sst_reg_read64(void __iomem *addr, int offset)
+{
+       u64 val = 0;
+
+       memcpy_fromio(&val, addr + offset, sizeof(val));
+
+       return val;
+}
+
+int sst_shim_write64(void __iomem *addr, int offset, u64 value)
+{
+       memcpy_toio(addr + offset, &value, sizeof(value));
+       return 0;
+}
+
+u64 sst_shim_read64(void __iomem *addr, int offset)
+{
+       u64 val = 0;
+
+       memcpy_fromio(&val, addr + offset, sizeof(val));
+       return val;
+}
+
+void sst_set_fw_state_locked(
+               struct intel_sst_drv *sst_drv_ctx, int sst_state)
+{
+       mutex_lock(&sst_drv_ctx->sst_lock);
+       sst_drv_ctx->sst_state = sst_state;
+       mutex_unlock(&sst_drv_ctx->sst_lock);
+}
+
+/*
+ * sst_wait_interruptible - wait on event
+ *
+ * @sst_drv_ctx: Driver context
+ * @block: Driver block to wait on
+ *
+ * This function waits without a timeout (and is interruptable) for a
+ * given block event
+ */
+int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
+                               struct sst_block *block)
+{
+       int retval = 0;
+
+       if (!wait_event_interruptible(sst_drv_ctx->wait_queue,
+                               block->condition)) {
+               /* event wake */
+               if (block->ret_code < 0) {
+                       dev_err(sst_drv_ctx->dev,
+                               "stream failed %d\n", block->ret_code);
+                       retval = -EBUSY;
+               } else {
+                       dev_dbg(sst_drv_ctx->dev, "event up\n");
+                       retval = 0;
+               }
+       } else {
+               dev_err(sst_drv_ctx->dev, "signal interrupted\n");
+               retval = -EINTR;
+       }
+       return retval;
+
+}
+
+unsigned long long read_shim_data(struct intel_sst_drv *sst, int addr)
+{
+       unsigned long long val = 0;
+
+       switch (sst->dev_id) {
+       case SST_MRFLD_PCI_ID:
+       case SST_BYT_ACPI_ID:
+               val = sst_shim_read64(sst->shim, addr);
+               break;
+       }
+       return val;
+}
+
+void write_shim_data(struct intel_sst_drv *sst, int addr,
+                               unsigned long long data)
+{
+       switch (sst->dev_id) {
+       case SST_MRFLD_PCI_ID:
+       case SST_BYT_ACPI_ID:
+               sst_shim_write64(sst->shim, addr, (u64) data);
+               break;
+       }
+}
+
+/*
+ * sst_wait_timeout - wait on event for timeout
+ *
+ * @sst_drv_ctx: Driver context
+ * @block: Driver block to wait on
+ *
+ * This function waits with a timeout value (and is not interruptible) on a
+ * given block event
+ */
+int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, struct sst_block *block)
+{
+       int retval = 0;
+
+       /*
+        * NOTE:
+        * Observed that FW processes the alloc msg and replies even
+        * before the alloc thread has finished execution
+        */
+       dev_dbg(sst_drv_ctx->dev,
+               "waiting for condition %x ipc %d drv_id %d\n",
+               block->condition, block->msg_id, block->drv_id);
+       if (wait_event_timeout(sst_drv_ctx->wait_queue,
+                               block->condition,
+                               msecs_to_jiffies(SST_BLOCK_TIMEOUT))) {
+               /* event wake */
+               dev_dbg(sst_drv_ctx->dev, "Event wake %x\n",
+                               block->condition);
+               dev_dbg(sst_drv_ctx->dev, "message ret: %d\n",
+                               block->ret_code);
+               retval = -block->ret_code;
+       } else {
+               block->on = false;
+               dev_err(sst_drv_ctx->dev,
+                       "Wait timed-out condition:%#x, msg_id:%#x fw_state %#x\n",
+                       block->condition, block->msg_id, sst_drv_ctx->sst_state);
+               sst_drv_ctx->sst_state = SST_RESET;
+
+               retval = -EBUSY;
+       }
+       return retval;
+}
+
+/*
+ * sst_create_ipc_msg - create a IPC message
+ *
+ * @arg: ipc message
+ * @large: large or short message
+ *
+ * this function allocates structures to send a large or short
+ * message to the firmware
+ */
+int sst_create_ipc_msg(struct ipc_post **arg, bool large)
+{
+       struct ipc_post *msg;
+
+       msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
+       if (large) {
+               msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
+               if (!msg->mailbox_data) {
+                       kfree(msg);
+                       return -ENOMEM;
+               }
+       } else {
+               msg->mailbox_data = NULL;
+       }
+       msg->is_large = large;
+       *arg = msg;
+       return 0;
+}
+
+/*
+ * sst_create_block_and_ipc_msg - Creates IPC message and sst block
+ * @arg: passed to sst_create_ipc_message API
+ * @large: large or short message
+ * @sst_drv_ctx: sst driver context
+ * @block: return block allocated
+ * @msg_id: IPC
+ * @drv_id: stream id or private id
+ */
+int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large,
+               struct intel_sst_drv *sst_drv_ctx, struct sst_block **block,
+               u32 msg_id, u32 drv_id)
+{
+       int retval = 0;
+
+       retval = sst_create_ipc_msg(arg, large);
+       if (retval)
+               return retval;
+       *block = sst_create_block(sst_drv_ctx, msg_id, drv_id);
+       if (*block == NULL) {
+               kfree(*arg);
+               return -ENOMEM;
+       }
+       return retval;
+}
+
+/*
+ * sst_clean_stream - clean the stream context
+ *
+ * @stream: stream structure
+ *
+ * this function resets the stream contexts
+ * should be called in free
+ */
+void sst_clean_stream(struct stream_info *stream)
+{
+       stream->status = STREAM_UN_INIT;
+       stream->prev = STREAM_UN_INIT;
+       mutex_lock(&stream->lock);
+       stream->cumm_bytes = 0;
+       mutex_unlock(&stream->lock);
+}
+
+int sst_prepare_and_post_msg(struct intel_sst_drv *sst,
+               int task_id, int ipc_msg, int cmd_id, int pipe_id,
+               size_t mbox_data_len, const void *mbox_data, void **data,
+               bool large, bool fill_dsp, bool sync, bool response)
+{
+       struct ipc_post *msg = NULL;
+       struct ipc_dsp_hdr dsp_hdr;
+       struct sst_block *block;
+       int ret = 0, pvt_id;
+
+       pvt_id = sst_assign_pvt_id(sst);
+       if (pvt_id < 0)
+               return pvt_id;
+
+       if (response)
+               ret = sst_create_block_and_ipc_msg(
+                               &msg, large, sst, &block, ipc_msg, pvt_id);
+       else
+               ret = sst_create_ipc_msg(&msg, large);
+
+       if (ret < 0) {
+               test_and_clear_bit(pvt_id, &sst->pvt_id);
+               return -ENOMEM;
+       }
+
+       dev_dbg(sst->dev, "pvt_id = %d, pipe id = %d, task = %d ipc_msg: %d\n",
+                pvt_id, pipe_id, task_id, ipc_msg);
+       sst_fill_header_mrfld(&msg->mrfld_header, ipc_msg,
+                                       task_id, large, pvt_id);
+       msg->mrfld_header.p.header_low_payload = sizeof(dsp_hdr) + mbox_data_len;
+       msg->mrfld_header.p.header_high.part.res_rqd = !sync;
+       dev_dbg(sst->dev, "header:%x\n",
+                       msg->mrfld_header.p.header_high.full);
+       dev_dbg(sst->dev, "response rqd: %x",
+                       msg->mrfld_header.p.header_high.part.res_rqd);
+       dev_dbg(sst->dev, "msg->mrfld_header.p.header_low_payload:%d",
+                       msg->mrfld_header.p.header_low_payload);
+       if (fill_dsp) {
+               sst_fill_header_dsp(&dsp_hdr, cmd_id, pipe_id, mbox_data_len);
+               memcpy(msg->mailbox_data, &dsp_hdr, sizeof(dsp_hdr));
+               if (mbox_data_len) {
+                       memcpy(msg->mailbox_data + sizeof(dsp_hdr),
+                                       mbox_data, mbox_data_len);
+               }
+       }
+
+       if (sync)
+               sst->ops->post_message(sst, msg, true);
+       else
+               sst_add_to_dispatch_list_and_post(sst, msg);
+
+       if (response) {
+               ret = sst_wait_timeout(sst, block);
+               if (ret < 0) {
+                       goto out;
+               } else if(block->data) {
+                       if (!data)
+                               goto out;
+                       *data = kzalloc(block->size, GFP_KERNEL);
+                       if (!(*data)) {
+                               ret = -ENOMEM;
+                               goto out;
+                       } else
+                               memcpy(data, (void *) block->data, block->size);
+               }
+       }
+out:
+       if (response)
+               sst_free_block(sst, block);
+       test_and_clear_bit(pvt_id, &sst->pvt_id);
+       return ret;
+}
+
+int sst_pm_runtime_put(struct intel_sst_drv *sst_drv)
+{
+       int ret;
+
+       pm_runtime_mark_last_busy(sst_drv->dev);
+       ret = pm_runtime_put_autosuspend(sst_drv->dev);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
+void sst_fill_header_mrfld(union ipc_header_mrfld *header,
+                               int msg, int task_id, int large, int drv_id)
+{
+       header->full = 0;
+       header->p.header_high.part.msg_id = msg;
+       header->p.header_high.part.task_id = task_id;
+       header->p.header_high.part.large = large;
+       header->p.header_high.part.drv_id = drv_id;
+       header->p.header_high.part.done = 0;
+       header->p.header_high.part.busy = 1;
+       header->p.header_high.part.res_rqd = 1;
+}
+
+void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg,
+                                       int pipe_id, int len)
+{
+       dsp->cmd_id = msg;
+       dsp->mod_index_id = 0xff;
+       dsp->pipe_id = pipe_id;
+       dsp->length = len;
+       dsp->mod_id = 0;
+}
+
+#define SST_MAX_BLOCKS 15
+/*
+ * sst_assign_pvt_id - assign a pvt id for stream
+ *
+ * @sst_drv_ctx : driver context
+ *
+ * this function assigns a private id for calls that dont have stream
+ * context yet, should be called with lock held
+ * uses bits for the id, and finds first free bits and assigns that
+ */
+int sst_assign_pvt_id(struct intel_sst_drv *drv)
+{
+       int local;
+
+       spin_lock(&drv->block_lock);
+       /* find first zero index from lsb */
+       local = ffz(drv->pvt_id);
+       dev_dbg(drv->dev, "pvt_id assigned --> %d\n", local);
+       if (local >= SST_MAX_BLOCKS){
+               spin_unlock(&drv->block_lock);
+               dev_err(drv->dev, "PVT _ID error: no free id blocks ");
+               return -EINVAL;
+       }
+       /* toggle the index */
+       change_bit(local, &drv->pvt_id);
+       spin_unlock(&drv->block_lock);
+       return local;
+}
+
+void sst_init_stream(struct stream_info *stream,
+               int codec, int sst_id, int ops, u8 slot)
+{
+       stream->status = STREAM_INIT;
+       stream->prev = STREAM_UN_INIT;
+       stream->ops = ops;
+}
+
+int sst_validate_strid(
+               struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       if (str_id <= 0 || str_id > sst_drv_ctx->info.max_streams) {
+               dev_err(sst_drv_ctx->dev,
+                       "SST ERR: invalid stream id : %d, max %d\n",
+                       str_id, sst_drv_ctx->info.max_streams);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+struct stream_info *get_stream_info(
+               struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       if (sst_validate_strid(sst_drv_ctx, str_id))
+               return NULL;
+       return &sst_drv_ctx->streams[str_id];
+}
+
+int get_stream_id_mrfld(struct intel_sst_drv *sst_drv_ctx,
+               u32 pipe_id)
+{
+       int i;
+
+       for (i = 1; i <= sst_drv_ctx->info.max_streams; i++)
+               if (pipe_id == sst_drv_ctx->streams[i].pipe_id)
+                       return i;
+
+       dev_dbg(sst_drv_ctx->dev, "no such pipe_id(%u)", pipe_id);
+       return -1;
+}
+
+u32 relocate_imr_addr_mrfld(u32 base_addr)
+{
+       /* Get the difference from 512MB aligned base addr */
+       /* relocate the base */
+       base_addr = MRFLD_FW_VIRTUAL_BASE + (base_addr % (512 * 1024 * 1024));
+       return base_addr;
+}
+EXPORT_SYMBOL_GPL(relocate_imr_addr_mrfld);
+
+void sst_add_to_dispatch_list_and_post(struct intel_sst_drv *sst,
+                                               struct ipc_post *msg)
+{
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&sst->ipc_spin_lock, irq_flags);
+       list_add_tail(&msg->node, &sst->ipc_dispatch_list);
+       spin_unlock_irqrestore(&sst->ipc_spin_lock, irq_flags);
+       sst->ops->post_message(sst, NULL, false);
+}
diff --git a/sound/soc/intel/atom/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c
new file mode 100644 (file)
index 0000000..a74c64c
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ *  sst_stream.c - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-14 Intel Corp
+ *  Authors:   Vinod Koul <vinod.koul@intel.com>
+ *             Harsha Priya <priya.harsha@intel.com>
+ *             Dharageswari R <dharageswari.r@intel.com>
+ *             KP Jeeja <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/compress_driver.h>
+#include <asm/platform_sst_audio.h>
+#include "../sst-mfld-platform.h"
+#include "sst.h"
+#include "../../common/sst-dsp.h"
+
+int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
+{
+       struct snd_sst_alloc_mrfld alloc_param;
+       struct snd_sst_params *str_params;
+       struct snd_sst_tstamp fw_tstamp;
+       struct stream_info *str_info;
+       struct snd_sst_alloc_response *response;
+       unsigned int str_id, pipe_id, task_id;
+       int i, num_ch, ret = 0;
+       void *data = NULL;
+
+       dev_dbg(sst_drv_ctx->dev, "Enter\n");
+       BUG_ON(!params);
+
+       str_params = (struct snd_sst_params *)params;
+       memset(&alloc_param, 0, sizeof(alloc_param));
+       alloc_param.operation = str_params->ops;
+       alloc_param.codec_type = str_params->codec;
+       alloc_param.sg_count = str_params->aparams.sg_count;
+       alloc_param.ring_buf_info[0].addr =
+               str_params->aparams.ring_buf_info[0].addr;
+       alloc_param.ring_buf_info[0].size =
+               str_params->aparams.ring_buf_info[0].size;
+       alloc_param.frag_size = str_params->aparams.frag_size;
+
+       memcpy(&alloc_param.codec_params, &str_params->sparams,
+                       sizeof(struct snd_sst_stream_params));
+
+       /*
+        * fill channel map params for multichannel support.
+        * Ideally channel map should be received from upper layers
+        * for multichannel support.
+        * Currently hardcoding as per FW reqm.
+        */
+       num_ch = sst_get_num_channel(str_params);
+       for (i = 0; i < 8; i++) {
+               if (i < num_ch)
+                       alloc_param.codec_params.uc.pcm_params.channel_map[i] = i;
+               else
+                       alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF;
+       }
+
+       str_id = str_params->stream_id;
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (str_info == NULL) {
+               dev_err(sst_drv_ctx->dev, "get stream info returned null\n");
+               return -EINVAL;
+       }
+
+       pipe_id = str_params->device_type;
+       task_id = str_params->task;
+       sst_drv_ctx->streams[str_id].pipe_id = pipe_id;
+       sst_drv_ctx->streams[str_id].task_id = task_id;
+       sst_drv_ctx->streams[str_id].num_ch = num_ch;
+
+       if (sst_drv_ctx->info.lpe_viewpt_rqd)
+               alloc_param.ts = sst_drv_ctx->info.mailbox_start +
+                       sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
+       else
+               alloc_param.ts = sst_drv_ctx->mailbox_add +
+                       sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
+
+       dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
+                       alloc_param.ts);
+       dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
+                       pipe_id, task_id);
+
+       /* allocate device type context */
+       sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type,
+                       str_id, alloc_param.operation, 0);
+
+       dev_info(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
+                       str_id, pipe_id);
+       ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
+                       IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
+                       &alloc_param, data, true, true, false, true);
+
+       if (ret < 0) {
+               dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
+               /* alloc failed, so reset the state to uninit */
+               str_info->status = STREAM_UN_INIT;
+               str_id = ret;
+       } else if (data) {
+               response = (struct snd_sst_alloc_response *)data;
+               ret = response->str_type.result;
+               if (!ret)
+                       goto out;
+               dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
+               if (ret == SST_ERR_STREAM_IN_USE) {
+                       dev_err(sst_drv_ctx->dev,
+                               "FW not in clean state, send free for:%d\n", str_id);
+                       sst_free_stream(sst_drv_ctx, str_id);
+               }
+               str_id = -ret;
+       }
+out:
+       kfree(data);
+       return str_id;
+}
+
+/**
+* sst_start_stream - Send msg for a starting stream
+* @str_id:      stream ID
+*
+* This function is called by any function which wants to start
+* a stream.
+*/
+int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+       u16 data = 0;
+
+       dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       if (str_info->status != STREAM_RUNNING)
+               return -EBADRQC;
+
+       retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
+                       IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id,
+                       sizeof(u16), &data, NULL, true, true, true, false);
+
+       return retval;
+}
+
+int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
+               struct snd_sst_bytes_v2 *bytes)
+{      struct ipc_post *msg = NULL;
+       u32 length;
+       int pvt_id, ret = 0;
+       struct sst_block *block = NULL;
+
+       dev_dbg(sst_drv_ctx->dev,
+               "type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n",
+               bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id,
+               bytes->pipe_id, bytes->len);
+
+       if (sst_create_ipc_msg(&msg, true))
+               return -ENOMEM;
+
+       pvt_id = sst_assign_pvt_id(sst_drv_ctx);
+       sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg,
+                       bytes->task_id, 1, pvt_id);
+       msg->mrfld_header.p.header_high.part.res_rqd = bytes->block;
+       length = bytes->len;
+       msg->mrfld_header.p.header_low_payload = length;
+       dev_dbg(sst_drv_ctx->dev, "length is %d\n", length);
+       memcpy(msg->mailbox_data, &bytes->bytes, bytes->len);
+       if (bytes->block) {
+               block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id);
+               if (block == NULL) {
+                       kfree(msg);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+       }
+
+       sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg);
+       dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d",
+                       msg->mrfld_header.p.header_low_payload);
+
+       if (bytes->block) {
+               ret = sst_wait_timeout(sst_drv_ctx, block);
+               if (ret) {
+                       dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
+                       sst_free_block(sst_drv_ctx, block);
+                       goto out;
+               }
+       }
+       if (bytes->type == SND_SST_BYTES_GET) {
+               /*
+                * copy the reply and send back
+                * we need to update only sz and payload
+                */
+               if (bytes->block) {
+                       unsigned char *r = block->data;
+
+                       dev_dbg(sst_drv_ctx->dev, "read back %d bytes",
+                                       bytes->len);
+                       memcpy(bytes->bytes, r, bytes->len);
+               }
+       }
+       if (bytes->block)
+               sst_free_block(sst_drv_ctx, block);
+out:
+       test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
+       return 0;
+}
+
+/*
+ * sst_pause_stream - Send msg for a pausing stream
+ * @str_id:     stream ID
+ *
+ * This function is called by any function which wants to pause
+ * an already running stream.
+ */
+int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+
+       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       if (str_info->status == STREAM_PAUSED)
+               return 0;
+       if (str_info->status == STREAM_RUNNING ||
+               str_info->status == STREAM_INIT) {
+               if (str_info->prev == STREAM_UN_INIT)
+                       return -EBADRQC;
+
+               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
+                               IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id,
+                               0, NULL, NULL, true, true, false, true);
+
+               if (retval == 0) {
+                       str_info->prev = str_info->status;
+                       str_info->status = STREAM_PAUSED;
+               } else if (retval == SST_ERR_INVALID_STREAM_ID) {
+                       retval = -EINVAL;
+                       mutex_lock(&sst_drv_ctx->sst_lock);
+                       sst_clean_stream(str_info);
+                       mutex_unlock(&sst_drv_ctx->sst_lock);
+               }
+       } else {
+               retval = -EBADRQC;
+               dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n ");
+       }
+
+       return retval;
+}
+
+/**
+ * sst_resume_stream - Send msg for resuming stream
+ * @str_id:            stream ID
+ *
+ * This function is called by any function which wants to resume
+ * an already paused stream.
+ */
+int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+
+       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       if (str_info->status == STREAM_RUNNING)
+                       return 0;
+       if (str_info->status == STREAM_PAUSED) {
+               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
+                               IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
+                               str_info->pipe_id, 0, NULL, NULL,
+                               true, true, false, true);
+
+               if (!retval) {
+                       if (str_info->prev == STREAM_RUNNING)
+                               str_info->status = STREAM_RUNNING;
+                       else
+                               str_info->status = STREAM_INIT;
+                       str_info->prev = STREAM_PAUSED;
+               } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
+                       retval = -EINVAL;
+                       mutex_lock(&sst_drv_ctx->sst_lock);
+                       sst_clean_stream(str_info);
+                       mutex_unlock(&sst_drv_ctx->sst_lock);
+               }
+       } else {
+               retval = -EBADRQC;
+               dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n");
+       }
+
+       return retval;
+}
+
+
+/**
+ * sst_drop_stream - Send msg for stopping stream
+ * @str_id:            stream ID
+ *
+ * This function is called by any function which wants to stop
+ * a stream.
+ */
+int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+
+       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+
+       if (str_info->status != STREAM_UN_INIT) {
+               str_info->prev = STREAM_UN_INIT;
+               str_info->status = STREAM_INIT;
+               str_info->cumm_bytes = 0;
+               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
+                               IPC_CMD, IPC_IA_DROP_STREAM_MRFLD,
+                               str_info->pipe_id, 0, NULL, NULL,
+                               true, true, true, false);
+       } else {
+               retval = -EBADRQC;
+               dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n",
+                               str_info->status);
+       }
+       return retval;
+}
+
+/**
+* sst_drain_stream - Send msg for draining stream
+* @str_id:             stream ID
+*
+* This function is called by any function which wants to drain
+* a stream.
+*/
+int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
+                       int str_id, bool partial_drain)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+
+       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       if (str_info->status != STREAM_RUNNING &&
+               str_info->status != STREAM_INIT &&
+               str_info->status != STREAM_PAUSED) {
+                       dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
+                                      str_info->status);
+                       return -EBADRQC;
+       }
+
+       retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
+                       IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id,
+                       sizeof(u8), &partial_drain, NULL, true, true, false, false);
+       /*
+        * with new non blocked drain implementation in core we dont need to
+        * wait for respsonse, and need to only invoke callback for drain
+        * complete
+        */
+
+       return retval;
+}
+
+/**
+ * sst_free_stream - Frees a stream
+ * @str_id:            stream ID
+ *
+ * This function is called by any function which wants to free
+ * a stream.
+ */
+int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
+{
+       int retval = 0;
+       struct stream_info *str_info;
+       struct intel_sst_ops *ops;
+
+       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
+
+       mutex_lock(&sst_drv_ctx->sst_lock);
+       if (sst_drv_ctx->sst_state == SST_RESET) {
+               mutex_unlock(&sst_drv_ctx->sst_lock);
+               return -ENODEV;
+       }
+       mutex_unlock(&sst_drv_ctx->sst_lock);
+       str_info = get_stream_info(sst_drv_ctx, str_id);
+       if (!str_info)
+               return -EINVAL;
+       ops = sst_drv_ctx->ops;
+
+       mutex_lock(&str_info->lock);
+       if (str_info->status != STREAM_UN_INIT) {
+               str_info->prev =  str_info->status;
+               str_info->status = STREAM_UN_INIT;
+               mutex_unlock(&str_info->lock);
+
+               dev_info(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
+                               str_id, str_info->pipe_id);
+               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
+                               IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
+                               NULL, NULL, true, true, false, true);
+
+               dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n",
+                               retval);
+               mutex_lock(&sst_drv_ctx->sst_lock);
+               sst_clean_stream(str_info);
+               mutex_unlock(&sst_drv_ctx->sst_lock);
+               dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n");
+       } else {
+               mutex_unlock(&str_info->lock);
+               retval = -EBADRQC;
+               dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n");
+       }
+
+       return retval;
+}
index 5c2d8fabb5ede433b0b2ee1d53d2065c3e4f6173..7f55d59024a88bd7b53ddd6f66a00fc8adeeaabd 100644 (file)
@@ -27,7 +27,7 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include "../../codecs/rt5640.h"
-#include "../sst-atom-controls.h"
+#include "../atom/sst-atom-controls.h"
 
 static const struct snd_soc_dapm_widget byt_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Headphone", NULL),
index 93bb6711ba3d3663c8715586eba7073d25cf4948..20a28b22e30fea84853f798f960130cbdf99bf7f 100644 (file)
@@ -28,7 +28,7 @@
 #include <sound/soc.h>
 #include <sound/jack.h>
 #include "../../codecs/rt5645.h"
-#include "../sst-atom-controls.h"
+#include "../atom/sst-atom-controls.h"
 
 #define CHT_PLAT_CLK_3_HZ      19200000
 #define CHT_CODEC_DAI  "rt5645-aif1"
index 2cea002a31bb91cd7a774bc7a1a06c1a1e0c2f45..2c9cc5be439e654bccb875df435eb651cf25163f 100644 (file)
@@ -24,7 +24,7 @@
 #include <sound/soc.h>
 #include <sound/jack.h>
 #include "../../codecs/rt5670.h"
-#include "../sst-atom-controls.h"
+#include "../atom/sst-atom-controls.h"
 
 /* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */
 #define CHT_PLAT_CLK_3_HZ      19200000
diff --git a/sound/soc/intel/sst-atom-controls.c b/sound/soc/intel/sst-atom-controls.c
deleted file mode 100644 (file)
index 90aa5c0..0000000
+++ /dev/null
@@ -1,1422 +0,0 @@
-/*
- *  sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld
- *
- *  Copyright (C) 2013-14 Intel Corp
- *  Author: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
- *     Vinod Koul <vinod.koul@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  In the dpcm driver modelling when a particular FE/BE/Mixer/Pipe is active
- *  we forward the settings and parameters, rest we keep the values  in
- *  driver and forward when DAPM enables them
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/slab.h>
-#include <sound/soc.h>
-#include <sound/tlv.h>
-#include "sst-mfld-platform.h"
-#include "sst-atom-controls.h"
-
-static int sst_fill_byte_control(struct sst_data *drv,
-                                        u8 ipc_msg, u8 block,
-                                        u8 task_id, u8 pipe_id,
-                                        u16 len, void *cmd_data)
-{
-       struct snd_sst_bytes_v2 *byte_data = drv->byte_stream;
-
-       byte_data->type = SST_CMD_BYTES_SET;
-       byte_data->ipc_msg = ipc_msg;
-       byte_data->block = block;
-       byte_data->task_id = task_id;
-       byte_data->pipe_id = pipe_id;
-
-       if (len > SST_MAX_BIN_BYTES - sizeof(*byte_data)) {
-               dev_err(&drv->pdev->dev, "command length too big (%u)", len);
-               return -EINVAL;
-       }
-       byte_data->len = len;
-       memcpy(byte_data->bytes, cmd_data, len);
-       print_hex_dump_bytes("writing to lpe: ", DUMP_PREFIX_OFFSET,
-                            byte_data, len + sizeof(*byte_data));
-       return 0;
-}
-
-static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv,
-                                u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id,
-                                void *cmd_data, u16 len)
-{
-       int ret = 0;
-
-       ret = sst_fill_byte_control(drv, ipc_msg,
-                               block, task_id, pipe_id, len, cmd_data);
-       if (ret < 0)
-               return ret;
-       return sst->ops->send_byte_stream(sst->dev, drv->byte_stream);
-}
-
-/**
- * sst_fill_and_send_cmd - generate the IPC message and send it to the FW
- * @ipc_msg:   type of IPC (CMD, SET_PARAMS, GET_PARAMS)
- * @cmd_data:  the IPC payload
- */
-static int sst_fill_and_send_cmd(struct sst_data *drv,
-                                u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id,
-                                void *cmd_data, u16 len)
-{
-       int ret;
-
-       mutex_lock(&drv->lock);
-       ret = sst_fill_and_send_cmd_unlocked(drv, ipc_msg, block,
-                                       task_id, pipe_id, cmd_data, len);
-       mutex_unlock(&drv->lock);
-
-       return ret;
-}
-
-/**
- * tx map value is a bitfield where each bit represents a FW channel
- *
- *                     3 2 1 0         # 0 = codec0, 1 = codec1
- *                     RLRLRLRL        # 3, 4 = reserved
- *
- * e.g. slot 0 rx map =        00001100b -> data from slot 0 goes into codec_in1 L,R
- */
-static u8 sst_ssp_tx_map[SST_MAX_TDM_SLOTS] = {
-       0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default rx map */
-};
-
-/**
- * rx map value is a bitfield where each bit represents a slot
- *
- *                       76543210      # 0 = slot 0, 1 = slot 1
- *
- * e.g. codec1_0 tx map = 00000101b -> data from codec_out1_0 goes into slot 0, 2
- */
-static u8 sst_ssp_rx_map[SST_MAX_TDM_SLOTS] = {
-       0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default tx map */
-};
-
-/**
- * NOTE: this is invoked with lock held
- */
-static int sst_send_slot_map(struct sst_data *drv)
-{
-       struct sst_param_sba_ssp_slot_map cmd;
-
-       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
-       cmd.header.command_id = SBA_SET_SSP_SLOT_MAP;
-       cmd.header.length = sizeof(struct sst_param_sba_ssp_slot_map)
-                               - sizeof(struct sst_dsp_header);
-
-       cmd.param_id = SBA_SET_SSP_SLOT_MAP;
-       cmd.param_len = sizeof(cmd.rx_slot_map) + sizeof(cmd.tx_slot_map)
-                                       + sizeof(cmd.ssp_index);
-       cmd.ssp_index = SSP_CODEC;
-
-       memcpy(cmd.rx_slot_map, &sst_ssp_tx_map[0], sizeof(cmd.rx_slot_map));
-       memcpy(cmd.tx_slot_map, &sst_ssp_rx_map[0], sizeof(cmd.tx_slot_map));
-
-       return sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS,
-                       SST_FLAG_BLOCKED, SST_TASK_SBA, 0, &cmd,
-                             sizeof(cmd.header) + cmd.header.length);
-}
-
-int sst_slot_enum_info(struct snd_kcontrol *kcontrol,
-                      struct snd_ctl_elem_info *uinfo)
-{
-       struct sst_enum *e = (struct sst_enum *)kcontrol->private_value;
-
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = 1;
-       uinfo->value.enumerated.items = e->max;
-
-       if (uinfo->value.enumerated.item > e->max - 1)
-               uinfo->value.enumerated.item = e->max - 1;
-       strcpy(uinfo->value.enumerated.name,
-               e->texts[uinfo->value.enumerated.item]);
-
-       return 0;
-}
-
-/**
- * sst_slot_get - get the status of the interleaver/deinterleaver control
- *
- * Searches the map where the control status is stored, and gets the
- * channel/slot which is currently set for this enumerated control. Since it is
- * an enumerated control, there is only one possible value.
- */
-static int sst_slot_get(struct snd_kcontrol *kcontrol,
-                       struct snd_ctl_elem_value *ucontrol)
-{
-       struct sst_enum *e = (void *)kcontrol->private_value;
-       struct snd_soc_component *c = snd_kcontrol_chip(kcontrol);
-       struct sst_data *drv = snd_soc_component_get_drvdata(c);
-       unsigned int ctl_no = e->reg;
-       unsigned int is_tx = e->tx;
-       unsigned int val, mux;
-       u8 *map = is_tx ? sst_ssp_rx_map : sst_ssp_tx_map;
-
-       mutex_lock(&drv->lock);
-       val = 1 << ctl_no;
-       /* search which slot/channel has this bit set - there should be only one */
-       for (mux = e->max; mux > 0;  mux--)
-               if (map[mux - 1] & val)
-                       break;
-
-       ucontrol->value.enumerated.item[0] = mux;
-       mutex_unlock(&drv->lock);
-
-       dev_dbg(c->dev, "%s - %s map = %#x\n",
-                       is_tx ? "tx channel" : "rx slot",
-                        e->texts[mux], mux ? map[mux - 1] : -1);
-       return 0;
-}
-
-/* sst_check_and_send_slot_map - helper for checking power state and sending
- * slot map cmd
- *
- * called with lock held
- */
-static int sst_check_and_send_slot_map(struct sst_data *drv, struct snd_kcontrol *kcontrol)
-{
-       struct sst_enum *e = (void *)kcontrol->private_value;
-       int ret = 0;
-
-       if (e->w && e->w->power)
-               ret = sst_send_slot_map(drv);
-       else
-               dev_err(&drv->pdev->dev, "Slot control: %s doesn't have DAPM widget!!!\n",
-                               kcontrol->id.name);
-       return ret;
-}
-
-/**
- * sst_slot_put - set the status of interleaver/deinterleaver control
- *
- * (de)interleaver controls are defined in opposite sense to be user-friendly
- *
- * Instead of the enum value being the value written to the register, it is the
- * register address; and the kcontrol number (register num) is the value written
- * to the register. This is so that there can be only one value for each
- * slot/channel since there is only one control for each slot/channel.
- *
- * This means that whenever an enum is set, we need to clear the bit
- * for that kcontrol_no for all the interleaver OR deinterleaver registers
- */
-static int sst_slot_put(struct snd_kcontrol *kcontrol,
-                       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
-       struct sst_data *drv = snd_soc_component_get_drvdata(c);
-       struct sst_enum *e = (void *)kcontrol->private_value;
-       int i, ret = 0;
-       unsigned int ctl_no = e->reg;
-       unsigned int is_tx = e->tx;
-       unsigned int slot_channel_no;
-       unsigned int val, mux;
-       u8 *map;
-
-       map = is_tx ? sst_ssp_rx_map : sst_ssp_tx_map;
-
-       val = 1 << ctl_no;
-       mux = ucontrol->value.enumerated.item[0];
-       if (mux > e->max - 1)
-               return -EINVAL;
-
-       mutex_lock(&drv->lock);
-       /* first clear all registers of this bit */
-       for (i = 0; i < e->max; i++)
-               map[i] &= ~val;
-
-       if (mux == 0) {
-               /* kctl set to 'none' and we reset the bits so send IPC */
-               ret = sst_check_and_send_slot_map(drv, kcontrol);
-
-               mutex_unlock(&drv->lock);
-               return ret;
-       }
-
-       /* offset by one to take "None" into account */
-       slot_channel_no = mux - 1;
-       map[slot_channel_no] |= val;
-
-       dev_dbg(c->dev, "%s %s map = %#x\n",
-                       is_tx ? "tx channel" : "rx slot",
-                       e->texts[mux], map[slot_channel_no]);
-
-       ret = sst_check_and_send_slot_map(drv, kcontrol);
-
-       mutex_unlock(&drv->lock);
-       return ret;
-}
-
-static int sst_send_algo_cmd(struct sst_data *drv,
-                             struct sst_algo_control *bc)
-{
-       int len, ret = 0;
-       struct sst_cmd_set_params *cmd;
-
-       /*bc->max includes sizeof algos + length field*/
-       len = sizeof(cmd->dst) + sizeof(cmd->command_id) + bc->max;
-
-       cmd = kzalloc(len, GFP_KERNEL);
-       if (cmd == NULL)
-               return -ENOMEM;
-
-       SST_FILL_DESTINATION(2, cmd->dst, bc->pipe_id, bc->module_id);
-       cmd->command_id = bc->cmd_id;
-       memcpy(cmd->params, bc->params, bc->max);
-
-       ret = sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS,
-                               SST_FLAG_BLOCKED, bc->task_id, 0, cmd, len);
-       kfree(cmd);
-       return ret;
-}
-
-/**
- * sst_find_and_send_pipe_algo - send all the algo parameters for a pipe
- *
- * The algos which are in each pipeline are sent to the firmware one by one
- *
- * Called with lock held
- */
-static int sst_find_and_send_pipe_algo(struct sst_data *drv,
-                                       const char *pipe, struct sst_ids *ids)
-{
-       int ret = 0;
-       struct sst_algo_control *bc;
-       struct sst_module *algo = NULL;
-
-       dev_dbg(&drv->pdev->dev, "Enter: widget=%s\n", pipe);
-
-       list_for_each_entry(algo, &ids->algo_list, node) {
-               bc = (void *)algo->kctl->private_value;
-
-               dev_dbg(&drv->pdev->dev, "Found algo control name=%s pipe=%s\n",
-                               algo->kctl->id.name, pipe);
-               ret = sst_send_algo_cmd(drv, bc);
-               if (ret)
-                       return ret;
-       }
-       return ret;
-}
-
-static int sst_algo_bytes_ctl_info(struct snd_kcontrol *kcontrol,
-                           struct snd_ctl_elem_info *uinfo)
-{
-       struct sst_algo_control *bc = (void *)kcontrol->private_value;
-
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-       uinfo->count = bc->max;
-
-       return 0;
-}
-
-static int sst_algo_control_get(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct sst_algo_control *bc = (void *)kcontrol->private_value;
-       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-
-       switch (bc->type) {
-       case SST_ALGO_PARAMS:
-               memcpy(ucontrol->value.bytes.data, bc->params, bc->max);
-               break;
-       default:
-               dev_err(component->dev, "Invalid Input- algo type:%d\n",
-                               bc->type);
-               return -EINVAL;
-
-       }
-       return 0;
-}
-
-static int sst_algo_control_set(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       int ret = 0;
-       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
-       struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt);
-       struct sst_algo_control *bc = (void *)kcontrol->private_value;
-
-       dev_dbg(cmpnt->dev, "control_name=%s\n", kcontrol->id.name);
-       mutex_lock(&drv->lock);
-       switch (bc->type) {
-       case SST_ALGO_PARAMS:
-               memcpy(bc->params, ucontrol->value.bytes.data, bc->max);
-               break;
-       default:
-               mutex_unlock(&drv->lock);
-               dev_err(cmpnt->dev, "Invalid Input- algo type:%d\n",
-                               bc->type);
-               return -EINVAL;
-       }
-       /*if pipe is enabled, need to send the algo params from here*/
-       if (bc->w && bc->w->power)
-               ret = sst_send_algo_cmd(drv, bc);
-       mutex_unlock(&drv->lock);
-
-       return ret;
-}
-
-static int sst_gain_ctl_info(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo)
-{
-       struct sst_gain_mixer_control *mc = (void *)kcontrol->private_value;
-
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = mc->stereo ? 2 : 1;
-       uinfo->value.integer.min = mc->min;
-       uinfo->value.integer.max = mc->max;
-
-       return 0;
-}
-
-/**
- * sst_send_gain_cmd - send the gain algorithm IPC to the FW
- * @gv:                the stored value of gain (also contains rampduration)
- * @mute:      flag that indicates whether this was called from the
- *             digital_mute callback or directly. If called from the
- *             digital_mute callback, module will be muted/unmuted based on this
- *             flag. The flag is always 0 if called directly.
- *
- * Called with sst_data.lock held
- *
- * The user-set gain value is sent only if the user-controllable 'mute' control
- * is OFF (indicated by gv->mute). Otherwise, the mute value (MIN value) is
- * sent.
- */
-static int sst_send_gain_cmd(struct sst_data *drv, struct sst_gain_value *gv,
-                             u16 task_id, u16 loc_id, u16 module_id, int mute)
-{
-       struct sst_cmd_set_gain_dual cmd;
-
-       dev_dbg(&drv->pdev->dev, "Enter\n");
-
-       cmd.header.command_id = MMX_SET_GAIN;
-       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
-       cmd.gain_cell_num = 1;
-
-       if (mute || gv->mute) {
-               cmd.cell_gains[0].cell_gain_left = SST_GAIN_MIN_VALUE;
-               cmd.cell_gains[0].cell_gain_right = SST_GAIN_MIN_VALUE;
-       } else {
-               cmd.cell_gains[0].cell_gain_left = gv->l_gain;
-               cmd.cell_gains[0].cell_gain_right = gv->r_gain;
-       }
-
-       SST_FILL_DESTINATION(2, cmd.cell_gains[0].dest,
-                            loc_id, module_id);
-       cmd.cell_gains[0].gain_time_constant = gv->ramp_duration;
-
-       cmd.header.length = sizeof(struct sst_cmd_set_gain_dual)
-                               - sizeof(struct sst_dsp_header);
-
-       /* we are with lock held, so call the unlocked api  to send */
-       return sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS,
-                               SST_FLAG_BLOCKED, task_id, 0, &cmd,
-                             sizeof(cmd.header) + cmd.header.length);
-}
-
-static int sst_gain_get(struct snd_kcontrol *kcontrol,
-                       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-       struct sst_gain_mixer_control *mc = (void *)kcontrol->private_value;
-       struct sst_gain_value *gv = mc->gain_val;
-
-       switch (mc->type) {
-       case SST_GAIN_TLV:
-               ucontrol->value.integer.value[0] = gv->l_gain;
-               ucontrol->value.integer.value[1] = gv->r_gain;
-               break;
-
-       case SST_GAIN_MUTE:
-               ucontrol->value.integer.value[0] = gv->mute ? 1 : 0;
-               break;
-
-       case SST_GAIN_RAMP_DURATION:
-               ucontrol->value.integer.value[0] = gv->ramp_duration;
-               break;
-
-       default:
-               dev_err(component->dev, "Invalid Input- gain type:%d\n",
-                               mc->type);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int sst_gain_put(struct snd_kcontrol *kcontrol,
-                       struct snd_ctl_elem_value *ucontrol)
-{
-       int ret = 0;
-       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
-       struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt);
-       struct sst_gain_mixer_control *mc = (void *)kcontrol->private_value;
-       struct sst_gain_value *gv = mc->gain_val;
-
-       mutex_lock(&drv->lock);
-
-       switch (mc->type) {
-       case SST_GAIN_TLV:
-               gv->l_gain = ucontrol->value.integer.value[0];
-               gv->r_gain = ucontrol->value.integer.value[1];
-               dev_dbg(cmpnt->dev, "%s: Volume %d, %d\n",
-                               mc->pname, gv->l_gain, gv->r_gain);
-               break;
-
-       case SST_GAIN_MUTE:
-               gv->mute = !!ucontrol->value.integer.value[0];
-               dev_dbg(cmpnt->dev, "%s: Mute %d\n", mc->pname, gv->mute);
-               break;
-
-       case SST_GAIN_RAMP_DURATION:
-               gv->ramp_duration = ucontrol->value.integer.value[0];
-               dev_dbg(cmpnt->dev, "%s: Ramp Delay%d\n",
-                                       mc->pname, gv->ramp_duration);
-               break;
-
-       default:
-               mutex_unlock(&drv->lock);
-               dev_err(cmpnt->dev, "Invalid Input- gain type:%d\n",
-                               mc->type);
-               return -EINVAL;
-       }
-
-       if (mc->w && mc->w->power)
-               ret = sst_send_gain_cmd(drv, gv, mc->task_id,
-                       mc->pipe_id | mc->instance_id, mc->module_id, 0);
-       mutex_unlock(&drv->lock);
-
-       return ret;
-}
-
-static int sst_set_pipe_gain(struct sst_ids *ids,
-                               struct sst_data *drv, int mute);
-
-static int sst_send_pipe_module_params(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol)
-{
-       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
-       struct sst_data *drv = snd_soc_component_get_drvdata(c);
-       struct sst_ids *ids = w->priv;
-
-       mutex_lock(&drv->lock);
-       sst_find_and_send_pipe_algo(drv, w->name, ids);
-       sst_set_pipe_gain(ids, drv, 0);
-       mutex_unlock(&drv->lock);
-
-       return 0;
-}
-
-static int sst_generic_modules_event(struct snd_soc_dapm_widget *w,
-                                    struct snd_kcontrol *k, int event)
-{
-       if (SND_SOC_DAPM_EVENT_ON(event))
-               return sst_send_pipe_module_params(w, k);
-       return 0;
-}
-
-static const DECLARE_TLV_DB_SCALE(sst_gain_tlv_common, SST_GAIN_MIN_VALUE * 10, 10, 0);
-
-/* Look up table to convert MIXER SW bit regs to SWM inputs */
-static const uint swm_mixer_input_ids[SST_SWM_INPUT_COUNT] = {
-       [SST_IP_CODEC0]         = SST_SWM_IN_CODEC0,
-       [SST_IP_CODEC1]         = SST_SWM_IN_CODEC1,
-       [SST_IP_LOOP0]          = SST_SWM_IN_SPROT_LOOP,
-       [SST_IP_LOOP1]          = SST_SWM_IN_MEDIA_LOOP1,
-       [SST_IP_LOOP2]          = SST_SWM_IN_MEDIA_LOOP2,
-       [SST_IP_PCM0]           = SST_SWM_IN_PCM0,
-       [SST_IP_PCM1]           = SST_SWM_IN_PCM1,
-       [SST_IP_MEDIA0]         = SST_SWM_IN_MEDIA0,
-       [SST_IP_MEDIA1]         = SST_SWM_IN_MEDIA1,
-       [SST_IP_MEDIA2]         = SST_SWM_IN_MEDIA2,
-       [SST_IP_MEDIA3]         = SST_SWM_IN_MEDIA3,
-};
-
-/**
- * fill_swm_input - fill in the SWM input ids given the register
- *
- * The register value is a bit-field inicated which mixer inputs are ON. Use the
- * lookup table to get the input-id and fill it in the structure.
- */
-static int fill_swm_input(struct snd_soc_component *cmpnt,
-               struct swm_input_ids *swm_input, unsigned int reg)
-{
-       uint i, is_set, nb_inputs = 0;
-       u16 input_loc_id;
-
-       dev_dbg(cmpnt->dev, "reg: %#x\n", reg);
-       for (i = 0; i < SST_SWM_INPUT_COUNT; i++) {
-               is_set = reg & BIT(i);
-               if (!is_set)
-                       continue;
-
-               input_loc_id = swm_mixer_input_ids[i];
-               SST_FILL_DESTINATION(2, swm_input->input_id,
-                                    input_loc_id, SST_DEFAULT_MODULE_ID);
-               nb_inputs++;
-               swm_input++;
-               dev_dbg(cmpnt->dev, "input id: %#x, nb_inputs: %d\n",
-                               input_loc_id, nb_inputs);
-
-               if (nb_inputs == SST_CMD_SWM_MAX_INPUTS) {
-                       dev_warn(cmpnt->dev, "SET_SWM cmd max inputs reached");
-                       break;
-               }
-       }
-       return nb_inputs;
-}
-
-
-/**
- * called with lock held
- */
-static int sst_set_pipe_gain(struct sst_ids *ids,
-                       struct sst_data *drv, int mute)
-{
-       int ret = 0;
-       struct sst_gain_mixer_control *mc;
-       struct sst_gain_value *gv;
-       struct sst_module *gain = NULL;
-
-       list_for_each_entry(gain, &ids->gain_list, node) {
-               struct snd_kcontrol *kctl = gain->kctl;
-
-               dev_dbg(&drv->pdev->dev, "control name=%s\n", kctl->id.name);
-               mc = (void *)kctl->private_value;
-               gv = mc->gain_val;
-
-               ret = sst_send_gain_cmd(drv, gv, mc->task_id,
-                       mc->pipe_id | mc->instance_id, mc->module_id, mute);
-               if (ret)
-                       return ret;
-       }
-       return ret;
-}
-
-static int sst_swm_mixer_event(struct snd_soc_dapm_widget *w,
-                       struct snd_kcontrol *k, int event)
-{
-       struct sst_cmd_set_swm cmd;
-       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
-       struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt);
-       struct sst_ids *ids = w->priv;
-       bool set_mixer = false;
-       struct soc_mixer_control *mc;
-       int val = 0;
-       int i = 0;
-
-       dev_dbg(cmpnt->dev, "widget = %s\n", w->name);
-       /*
-        * Identify which mixer input is on and send the bitmap of the
-        * inputs as an IPC to the DSP.
-        */
-       for (i = 0; i < w->num_kcontrols; i++) {
-               if (dapm_kcontrol_get_value(w->kcontrols[i])) {
-                       mc = (struct soc_mixer_control *)(w->kcontrols[i])->private_value;
-                       val |= 1 << mc->shift;
-               }
-       }
-       dev_dbg(cmpnt->dev, "val = %#x\n", val);
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-       case SND_SOC_DAPM_POST_PMD:
-               set_mixer = true;
-               break;
-       case SND_SOC_DAPM_POST_REG:
-               if (w->power)
-                       set_mixer = true;
-               break;
-       default:
-               set_mixer = false;
-       }
-
-       if (set_mixer == false)
-               return 0;
-
-       if (SND_SOC_DAPM_EVENT_ON(event) ||
-           event == SND_SOC_DAPM_POST_REG)
-               cmd.switch_state = SST_SWM_ON;
-       else
-               cmd.switch_state = SST_SWM_OFF;
-
-       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
-       /* MMX_SET_SWM == SBA_SET_SWM */
-       cmd.header.command_id = SBA_SET_SWM;
-
-       SST_FILL_DESTINATION(2, cmd.output_id,
-                            ids->location_id, SST_DEFAULT_MODULE_ID);
-       cmd.nb_inputs = fill_swm_input(cmpnt, &cmd.input[0], val);
-       cmd.header.length = offsetof(struct sst_cmd_set_swm, input)
-                               - sizeof(struct sst_dsp_header)
-                               + (cmd.nb_inputs * sizeof(cmd.input[0]));
-
-       return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
-                             ids->task_id, 0, &cmd,
-                             sizeof(cmd.header) + cmd.header.length);
-}
-
-/* SBA mixers - 16 inputs */
-#define SST_SBA_DECLARE_MIX_CONTROLS(kctl_name)                                                        \
-       static const struct snd_kcontrol_new kctl_name[] = {                                    \
-               SOC_DAPM_SINGLE("codec_in0 Switch", SND_SOC_NOPM, SST_IP_CODEC0, 1, 0),         \
-               SOC_DAPM_SINGLE("codec_in1 Switch", SND_SOC_NOPM, SST_IP_CODEC1, 1, 0),         \
-               SOC_DAPM_SINGLE("sprot_loop_in Switch", SND_SOC_NOPM, SST_IP_LOOP0, 1, 0),      \
-               SOC_DAPM_SINGLE("media_loop1_in Switch", SND_SOC_NOPM, SST_IP_LOOP1, 1, 0),     \
-               SOC_DAPM_SINGLE("media_loop2_in Switch", SND_SOC_NOPM, SST_IP_LOOP2, 1, 0),     \
-               SOC_DAPM_SINGLE("pcm0_in Switch", SND_SOC_NOPM, SST_IP_PCM0, 1, 0),             \
-               SOC_DAPM_SINGLE("pcm1_in Switch", SND_SOC_NOPM, SST_IP_PCM1, 1, 0),             \
-       }
-
-#define SST_SBA_MIXER_GRAPH_MAP(mix_name)                      \
-       { mix_name, "codec_in0 Switch", "codec_in0" },          \
-       { mix_name, "codec_in1 Switch", "codec_in1" },          \
-       { mix_name, "sprot_loop_in Switch",     "sprot_loop_in" },      \
-       { mix_name, "media_loop1_in Switch",    "media_loop1_in" },     \
-       { mix_name, "media_loop2_in Switch",    "media_loop2_in" },     \
-       { mix_name, "pcm0_in Switch",           "pcm0_in" },            \
-       { mix_name, "pcm1_in Switch",           "pcm1_in" }
-
-#define SST_MMX_DECLARE_MIX_CONTROLS(kctl_name)                                                \
-       static const struct snd_kcontrol_new kctl_name[] = {                            \
-               SOC_DAPM_SINGLE("media0_in Switch", SND_SOC_NOPM, SST_IP_MEDIA0, 1, 0), \
-               SOC_DAPM_SINGLE("media1_in Switch", SND_SOC_NOPM, SST_IP_MEDIA1, 1, 0), \
-               SOC_DAPM_SINGLE("media2_in Switch", SND_SOC_NOPM, SST_IP_MEDIA2, 1, 0), \
-               SOC_DAPM_SINGLE("media3_in Switch", SND_SOC_NOPM, SST_IP_MEDIA3, 1, 0), \
-       }
-
-SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media0_controls);
-SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media1_controls);
-
-/* 18 SBA mixers */
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm0_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm1_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls);
-SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls);
-
-/*
- * sst_handle_vb_timer - Start/Stop the DSP scheduler
- *
- * The DSP expects first cmd to be SBA_VB_START, so at first startup send
- * that.
- * DSP expects last cmd to be SBA_VB_IDLE, so at last shutdown send that.
- *
- * Do refcount internally so that we send command only at first start
- * and last end. Since SST driver does its own ref count, invoke sst's
- * power ops always!
- */
-int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable)
-{
-       int ret = 0;
-       struct sst_cmd_generic cmd;
-       struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
-       static int timer_usage;
-
-       if (enable)
-               cmd.header.command_id = SBA_VB_START;
-       else
-               cmd.header.command_id = SBA_IDLE;
-       dev_dbg(dai->dev, "enable=%u, usage=%d\n", enable, timer_usage);
-
-       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
-       cmd.header.length = 0;
-
-       if (enable) {
-               ret = sst->ops->power(sst->dev, true);
-               if (ret < 0)
-                       return ret;
-       }
-
-       mutex_lock(&drv->lock);
-       if (enable)
-               timer_usage++;
-       else
-               timer_usage--;
-
-       /*
-        * Send the command only if this call is the first enable or last
-        * disable
-        */
-       if ((enable && (timer_usage == 1)) ||
-           (!enable && (timer_usage == 0))) {
-               ret = sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_CMD,
-                               SST_FLAG_BLOCKED, SST_TASK_SBA, 0, &cmd,
-                               sizeof(cmd.header) + cmd.header.length);
-               if (ret && enable) {
-                       timer_usage--;
-                       enable  = false;
-               }
-       }
-       mutex_unlock(&drv->lock);
-
-       if (!enable)
-               sst->ops->power(sst->dev, false);
-       return ret;
-}
-
-/**
- * sst_ssp_config - contains SSP configuration for media UC
- */
-static const struct sst_ssp_config sst_ssp_configs = {
-       .ssp_id = SSP_CODEC,
-       .bits_per_slot = 24,
-       .slots = 4,
-       .ssp_mode = SSP_MODE_MASTER,
-       .pcm_mode = SSP_PCM_MODE_NETWORK,
-       .duplex = SSP_DUPLEX,
-       .ssp_protocol = SSP_MODE_PCM,
-       .fs_width = 1,
-       .fs_frequency = SSP_FS_48_KHZ,
-       .active_slot_map = 0xF,
-       .start_delay = 0,
-};
-
-int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable)
-{
-       struct sst_cmd_sba_hw_set_ssp cmd;
-       struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
-       const struct sst_ssp_config *config;
-
-       dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id);
-
-       SST_FILL_DEFAULT_DESTINATION(cmd.header.dst);
-       cmd.header.command_id = SBA_HW_SET_SSP;
-       cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp)
-                               - sizeof(struct sst_dsp_header);
-
-       config = &sst_ssp_configs;
-       dev_dbg(dai->dev, "ssp_id: %u\n", config->ssp_id);
-
-       if (enable)
-               cmd.switch_state = SST_SWITCH_ON;
-       else
-               cmd.switch_state = SST_SWITCH_OFF;
-
-       cmd.selection = config->ssp_id;
-       cmd.nb_bits_per_slots = config->bits_per_slot;
-       cmd.nb_slots = config->slots;
-       cmd.mode = config->ssp_mode | (config->pcm_mode << 1);
-       cmd.duplex = config->duplex;
-       cmd.active_tx_slot_map = config->active_slot_map;
-       cmd.active_rx_slot_map = config->active_slot_map;
-       cmd.frame_sync_frequency = config->fs_frequency;
-       cmd.frame_sync_polarity = SSP_FS_ACTIVE_HIGH;
-       cmd.data_polarity = 1;
-       cmd.frame_sync_width = config->fs_width;
-       cmd.ssp_protocol = config->ssp_protocol;
-       cmd.start_delay = config->start_delay;
-       cmd.reserved1 = cmd.reserved2 = 0xFF;
-
-       return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
-                               SST_TASK_SBA, 0, &cmd,
-                               sizeof(cmd.header) + cmd.header.length);
-}
-
-static int sst_set_be_modules(struct snd_soc_dapm_widget *w,
-                        struct snd_kcontrol *k, int event)
-{
-       int ret = 0;
-       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
-       struct sst_data *drv = snd_soc_component_get_drvdata(c);
-
-       dev_dbg(c->dev, "Enter: widget=%s\n", w->name);
-
-       if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = sst_send_slot_map(drv);
-               if (ret)
-                       return ret;
-               ret = sst_send_pipe_module_params(w, k);
-       }
-       return ret;
-}
-
-static int sst_set_media_path(struct snd_soc_dapm_widget *w,
-                             struct snd_kcontrol *k, int event)
-{
-       int ret = 0;
-       struct sst_cmd_set_media_path cmd;
-       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
-       struct sst_data *drv = snd_soc_component_get_drvdata(c);
-       struct sst_ids *ids = w->priv;
-
-       dev_dbg(c->dev, "widget=%s\n", w->name);
-       dev_dbg(c->dev, "task=%u, location=%#x\n",
-                               ids->task_id, ids->location_id);
-
-       if (SND_SOC_DAPM_EVENT_ON(event))
-               cmd.switch_state = SST_PATH_ON;
-       else
-               cmd.switch_state = SST_PATH_OFF;
-
-       SST_FILL_DESTINATION(2, cmd.header.dst,
-                            ids->location_id, SST_DEFAULT_MODULE_ID);
-
-       /* MMX_SET_MEDIA_PATH == SBA_SET_MEDIA_PATH */
-       cmd.header.command_id = MMX_SET_MEDIA_PATH;
-       cmd.header.length = sizeof(struct sst_cmd_set_media_path)
-                               - sizeof(struct sst_dsp_header);
-
-       ret = sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
-                             ids->task_id, 0, &cmd,
-                             sizeof(cmd.header) + cmd.header.length);
-       if (ret)
-               return ret;
-
-       if (SND_SOC_DAPM_EVENT_ON(event))
-               ret = sst_send_pipe_module_params(w, k);
-       return ret;
-}
-
-static int sst_set_media_loop(struct snd_soc_dapm_widget *w,
-                       struct snd_kcontrol *k, int event)
-{
-       int ret = 0;
-       struct sst_cmd_sba_set_media_loop_map cmd;
-       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
-       struct sst_data *drv = snd_soc_component_get_drvdata(c);
-       struct sst_ids *ids = w->priv;
-
-       dev_dbg(c->dev, "Enter:widget=%s\n", w->name);
-       if (SND_SOC_DAPM_EVENT_ON(event))
-               cmd.switch_state = SST_SWITCH_ON;
-       else
-               cmd.switch_state = SST_SWITCH_OFF;
-
-       SST_FILL_DESTINATION(2, cmd.header.dst,
-                            ids->location_id, SST_DEFAULT_MODULE_ID);
-
-       cmd.header.command_id = SBA_SET_MEDIA_LOOP_MAP;
-       cmd.header.length = sizeof(struct sst_cmd_sba_set_media_loop_map)
-                                - sizeof(struct sst_dsp_header);
-       cmd.param.part.cfg.rate = 2; /* 48khz */
-
-       cmd.param.part.cfg.format = ids->format; /* stereo/Mono */
-       cmd.param.part.cfg.s_length = 1; /* 24bit left justified */
-       cmd.map = 0; /* Algo sequence: Gain - DRP - FIR - IIR */
-
-       ret = sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED,
-                             SST_TASK_SBA, 0, &cmd,
-                             sizeof(cmd.header) + cmd.header.length);
-       if (ret)
-               return ret;
-
-       if (SND_SOC_DAPM_EVENT_ON(event))
-               ret = sst_send_pipe_module_params(w, k);
-       return ret;
-}
-
-static const struct snd_soc_dapm_widget sst_dapm_widgets[] = {
-       SST_AIF_IN("codec_in0", sst_set_be_modules),
-       SST_AIF_IN("codec_in1", sst_set_be_modules),
-       SST_AIF_OUT("codec_out0", sst_set_be_modules),
-       SST_AIF_OUT("codec_out1", sst_set_be_modules),
-
-       /* Media Paths */
-       /* MediaX IN paths are set via ALLOC, so no SET_MEDIA_PATH command */
-       SST_PATH_INPUT("media0_in", SST_TASK_MMX, SST_SWM_IN_MEDIA0, sst_generic_modules_event),
-       SST_PATH_INPUT("media1_in", SST_TASK_MMX, SST_SWM_IN_MEDIA1, NULL),
-       SST_PATH_INPUT("media2_in", SST_TASK_MMX, SST_SWM_IN_MEDIA2, sst_set_media_path),
-       SST_PATH_INPUT("media3_in", SST_TASK_MMX, SST_SWM_IN_MEDIA3, NULL),
-       SST_PATH_OUTPUT("media0_out", SST_TASK_MMX, SST_SWM_OUT_MEDIA0, sst_set_media_path),
-       SST_PATH_OUTPUT("media1_out", SST_TASK_MMX, SST_SWM_OUT_MEDIA1, sst_set_media_path),
-
-       /* SBA PCM Paths */
-       SST_PATH_INPUT("pcm0_in", SST_TASK_SBA, SST_SWM_IN_PCM0, sst_set_media_path),
-       SST_PATH_INPUT("pcm1_in", SST_TASK_SBA, SST_SWM_IN_PCM1, sst_set_media_path),
-       SST_PATH_OUTPUT("pcm0_out", SST_TASK_SBA, SST_SWM_OUT_PCM0, sst_set_media_path),
-       SST_PATH_OUTPUT("pcm1_out", SST_TASK_SBA, SST_SWM_OUT_PCM1, sst_set_media_path),
-       SST_PATH_OUTPUT("pcm2_out", SST_TASK_SBA, SST_SWM_OUT_PCM2, sst_set_media_path),
-
-       /* SBA Loops */
-       SST_PATH_INPUT("sprot_loop_in", SST_TASK_SBA, SST_SWM_IN_SPROT_LOOP, NULL),
-       SST_PATH_INPUT("media_loop1_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP1, NULL),
-       SST_PATH_INPUT("media_loop2_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP2, NULL),
-       SST_PATH_MEDIA_LOOP_OUTPUT("sprot_loop_out", SST_TASK_SBA, SST_SWM_OUT_SPROT_LOOP, SST_FMT_MONO, sst_set_media_loop),
-       SST_PATH_MEDIA_LOOP_OUTPUT("media_loop1_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP1, SST_FMT_MONO, sst_set_media_loop),
-       SST_PATH_MEDIA_LOOP_OUTPUT("media_loop2_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP2, SST_FMT_STEREO, sst_set_media_loop),
-
-       /* Media Mixers */
-       SST_SWM_MIXER("media0_out mix 0", SND_SOC_NOPM, SST_TASK_MMX, SST_SWM_OUT_MEDIA0,
-                     sst_mix_media0_controls, sst_swm_mixer_event),
-       SST_SWM_MIXER("media1_out mix 0", SND_SOC_NOPM, SST_TASK_MMX, SST_SWM_OUT_MEDIA1,
-                     sst_mix_media1_controls, sst_swm_mixer_event),
-
-       /* SBA PCM mixers */
-       SST_SWM_MIXER("pcm0_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_PCM0,
-                     sst_mix_pcm0_controls, sst_swm_mixer_event),
-       SST_SWM_MIXER("pcm1_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_PCM1,
-                     sst_mix_pcm1_controls, sst_swm_mixer_event),
-       SST_SWM_MIXER("pcm2_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_PCM2,
-                     sst_mix_pcm2_controls, sst_swm_mixer_event),
-
-       /* SBA Loop mixers */
-       SST_SWM_MIXER("sprot_loop_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_SPROT_LOOP,
-                     sst_mix_sprot_l0_controls, sst_swm_mixer_event),
-       SST_SWM_MIXER("media_loop1_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP1,
-                     sst_mix_media_l1_controls, sst_swm_mixer_event),
-       SST_SWM_MIXER("media_loop2_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP2,
-                     sst_mix_media_l2_controls, sst_swm_mixer_event),
-
-       /* SBA Backend mixers */
-       SST_SWM_MIXER("codec_out0 mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_CODEC0,
-                     sst_mix_codec0_controls, sst_swm_mixer_event),
-       SST_SWM_MIXER("codec_out1 mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_CODEC1,
-                     sst_mix_codec1_controls, sst_swm_mixer_event),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-       {"media0_in", NULL, "Compress Playback"},
-       {"media1_in", NULL, "Headset Playback"},
-       {"media2_in", NULL, "pcm0_out"},
-
-       {"media0_out mix 0", "media0_in Switch", "media0_in"},
-       {"media0_out mix 0", "media1_in Switch", "media1_in"},
-       {"media0_out mix 0", "media2_in Switch", "media2_in"},
-       {"media0_out mix 0", "media3_in Switch", "media3_in"},
-       {"media1_out mix 0", "media0_in Switch", "media0_in"},
-       {"media1_out mix 0", "media1_in Switch", "media1_in"},
-       {"media1_out mix 0", "media2_in Switch", "media2_in"},
-       {"media1_out mix 0", "media3_in Switch", "media3_in"},
-
-       {"media0_out", NULL, "media0_out mix 0"},
-       {"media1_out", NULL, "media1_out mix 0"},
-       {"pcm0_in", NULL, "media0_out"},
-       {"pcm1_in", NULL, "media1_out"},
-
-       {"Headset Capture", NULL, "pcm1_out"},
-       {"Headset Capture", NULL, "pcm2_out"},
-       {"pcm0_out", NULL, "pcm0_out mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("pcm0_out mix 0"),
-       {"pcm1_out", NULL, "pcm1_out mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("pcm1_out mix 0"),
-       {"pcm2_out", NULL, "pcm2_out mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("pcm2_out mix 0"),
-
-       {"media_loop1_in", NULL, "media_loop1_out"},
-       {"media_loop1_out", NULL, "media_loop1_out mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("media_loop1_out mix 0"),
-       {"media_loop2_in", NULL, "media_loop2_out"},
-       {"media_loop2_out", NULL, "media_loop2_out mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("media_loop2_out mix 0"),
-       {"sprot_loop_in", NULL, "sprot_loop_out"},
-       {"sprot_loop_out", NULL, "sprot_loop_out mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("sprot_loop_out mix 0"),
-
-       {"codec_out0", NULL, "codec_out0 mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("codec_out0 mix 0"),
-       {"codec_out1", NULL, "codec_out1 mix 0"},
-       SST_SBA_MIXER_GRAPH_MAP("codec_out1 mix 0"),
-
-};
-static const char * const slot_names[] = {
-       "none",
-       "slot 0", "slot 1", "slot 2", "slot 3",
-       "slot 4", "slot 5", "slot 6", "slot 7", /* not supported by FW */
-};
-
-static const char * const channel_names[] = {
-       "none",
-       "codec_out0_0", "codec_out0_1", "codec_out1_0", "codec_out1_1",
-       "codec_out2_0", "codec_out2_1", "codec_out3_0", "codec_out3_1", /* not supported by FW */
-};
-
-#define SST_INTERLEAVER(xpname, slot_name, slotno) \
-       SST_SSP_SLOT_CTL(xpname, "tx interleaver", slot_name, slotno, true, \
-                        channel_names, sst_slot_get, sst_slot_put)
-
-#define SST_DEINTERLEAVER(xpname, channel_name, channel_no) \
-       SST_SSP_SLOT_CTL(xpname, "rx deinterleaver", channel_name, channel_no, false, \
-                        slot_names, sst_slot_get, sst_slot_put)
-
-static const struct snd_kcontrol_new sst_slot_controls[] = {
-       SST_INTERLEAVER("codec_out", "slot 0", 0),
-       SST_INTERLEAVER("codec_out", "slot 1", 1),
-       SST_INTERLEAVER("codec_out", "slot 2", 2),
-       SST_INTERLEAVER("codec_out", "slot 3", 3),
-       SST_DEINTERLEAVER("codec_in", "codec_in0_0", 0),
-       SST_DEINTERLEAVER("codec_in", "codec_in0_1", 1),
-       SST_DEINTERLEAVER("codec_in", "codec_in1_0", 2),
-       SST_DEINTERLEAVER("codec_in", "codec_in1_1", 3),
-};
-
-/* Gain helper with min/max set */
-#define SST_GAIN(name, path_id, task_id, instance, gain_var)                           \
-       SST_GAIN_KCONTROLS(name, "Gain", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE,        \
-               SST_GAIN_TC_MIN, SST_GAIN_TC_MAX,                                       \
-               sst_gain_get, sst_gain_put,                                             \
-               SST_MODULE_ID_GAIN_CELL, path_id, instance, task_id,                    \
-               sst_gain_tlv_common, gain_var)
-
-#define SST_VOLUME(name, path_id, task_id, instance, gain_var)                         \
-       SST_GAIN_KCONTROLS(name, "Volume", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE,      \
-               SST_GAIN_TC_MIN, SST_GAIN_TC_MAX,                                       \
-               sst_gain_get, sst_gain_put,                                             \
-               SST_MODULE_ID_VOLUME, path_id, instance, task_id,                       \
-               sst_gain_tlv_common, gain_var)
-
-static struct sst_gain_value sst_gains[];
-
-static const struct snd_kcontrol_new sst_gain_controls[] = {
-       SST_GAIN("media0_in", SST_PATH_INDEX_MEDIA0_IN, SST_TASK_MMX, 0, &sst_gains[0]),
-       SST_GAIN("media1_in", SST_PATH_INDEX_MEDIA1_IN, SST_TASK_MMX, 0, &sst_gains[1]),
-       SST_GAIN("media2_in", SST_PATH_INDEX_MEDIA2_IN, SST_TASK_MMX, 0, &sst_gains[2]),
-       SST_GAIN("media3_in", SST_PATH_INDEX_MEDIA3_IN, SST_TASK_MMX, 0, &sst_gains[3]),
-
-       SST_GAIN("pcm0_in", SST_PATH_INDEX_PCM0_IN, SST_TASK_SBA, 0, &sst_gains[4]),
-       SST_GAIN("pcm1_in", SST_PATH_INDEX_PCM1_IN, SST_TASK_SBA, 0, &sst_gains[5]),
-       SST_GAIN("pcm1_out", SST_PATH_INDEX_PCM1_OUT, SST_TASK_SBA, 0, &sst_gains[6]),
-       SST_GAIN("pcm2_out", SST_PATH_INDEX_PCM2_OUT, SST_TASK_SBA, 0, &sst_gains[7]),
-
-       SST_GAIN("codec_in0", SST_PATH_INDEX_CODEC_IN0, SST_TASK_SBA, 0, &sst_gains[8]),
-       SST_GAIN("codec_in1", SST_PATH_INDEX_CODEC_IN1, SST_TASK_SBA, 0, &sst_gains[9]),
-       SST_GAIN("codec_out0", SST_PATH_INDEX_CODEC_OUT0, SST_TASK_SBA, 0, &sst_gains[10]),
-       SST_GAIN("codec_out1", SST_PATH_INDEX_CODEC_OUT1, SST_TASK_SBA, 0, &sst_gains[11]),
-       SST_GAIN("media_loop1_out", SST_PATH_INDEX_MEDIA_LOOP1_OUT, SST_TASK_SBA, 0, &sst_gains[12]),
-       SST_GAIN("media_loop2_out", SST_PATH_INDEX_MEDIA_LOOP2_OUT, SST_TASK_SBA, 0, &sst_gains[13]),
-       SST_GAIN("sprot_loop_out", SST_PATH_INDEX_SPROT_LOOP_OUT, SST_TASK_SBA, 0, &sst_gains[14]),
-       SST_VOLUME("media0_in", SST_PATH_INDEX_MEDIA0_IN, SST_TASK_MMX, 0, &sst_gains[15]),
-};
-
-#define SST_GAIN_NUM_CONTROLS 3
-/* the SST_GAIN macro above will create three alsa controls for each
- * instance invoked, gain, mute and ramp duration, which use the same gain
- * cell sst_gain to keep track of data
- * To calculate number of gain cell instances we need to device by 3 in
- * below caulcation for gain cell memory.
- * This gets rid of static number and issues while adding new controls
- */
-static struct sst_gain_value sst_gains[ARRAY_SIZE(sst_gain_controls)/SST_GAIN_NUM_CONTROLS];
-
-static const struct snd_kcontrol_new sst_algo_controls[] = {
-       SST_ALGO_KCONTROL_BYTES("media_loop1_out", "fir", 272, SST_MODULE_ID_FIR_24,
-                SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_VB_SET_FIR),
-       SST_ALGO_KCONTROL_BYTES("media_loop1_out", "iir", 300, SST_MODULE_ID_IIR_24,
-               SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
-       SST_ALGO_KCONTROL_BYTES("media_loop1_out", "mdrp", 286, SST_MODULE_ID_MDRP,
-               SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_SET_MDRP),
-       SST_ALGO_KCONTROL_BYTES("media_loop2_out", "fir", 272, SST_MODULE_ID_FIR_24,
-               SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_VB_SET_FIR),
-       SST_ALGO_KCONTROL_BYTES("media_loop2_out", "iir", 300, SST_MODULE_ID_IIR_24,
-               SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
-       SST_ALGO_KCONTROL_BYTES("media_loop2_out", "mdrp", 286, SST_MODULE_ID_MDRP,
-               SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_SET_MDRP),
-       SST_ALGO_KCONTROL_BYTES("sprot_loop_out", "lpro", 192, SST_MODULE_ID_SPROT,
-               SST_PATH_INDEX_SPROT_LOOP_OUT, 0, SST_TASK_SBA, SBA_VB_LPRO),
-       SST_ALGO_KCONTROL_BYTES("codec_in0", "dcr", 52, SST_MODULE_ID_FILT_DCR,
-               SST_PATH_INDEX_CODEC_IN0, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
-       SST_ALGO_KCONTROL_BYTES("codec_in1", "dcr", 52, SST_MODULE_ID_FILT_DCR,
-               SST_PATH_INDEX_CODEC_IN1, 0, SST_TASK_SBA, SBA_VB_SET_IIR),
-
-};
-
-static int sst_algo_control_init(struct device *dev)
-{
-       int i = 0;
-       struct sst_algo_control *bc;
-       /*allocate space to cache the algo parameters in the driver*/
-       for (i = 0; i < ARRAY_SIZE(sst_algo_controls); i++) {
-               bc = (struct sst_algo_control *)sst_algo_controls[i].private_value;
-               bc->params = devm_kzalloc(dev, bc->max, GFP_KERNEL);
-               if (bc->params == NULL)
-                       return -ENOMEM;
-       }
-       return 0;
-}
-
-static bool is_sst_dapm_widget(struct snd_soc_dapm_widget *w)
-{
-       switch (w->id) {
-       case snd_soc_dapm_pga:
-       case snd_soc_dapm_aif_in:
-       case snd_soc_dapm_aif_out:
-       case snd_soc_dapm_input:
-       case snd_soc_dapm_output:
-       case snd_soc_dapm_mixer:
-               return true;
-       default:
-               return false;
-       }
-}
-
-/**
- * sst_send_pipe_gains - send gains for the front-end DAIs
- *
- * The gains in the pipes connected to the front-ends are muted/unmuted
- * automatically via the digital_mute() DAPM callback. This function sends the
- * gains for the front-end pipes.
- */
-int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute)
-{
-       struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
-       struct snd_soc_dapm_widget *w;
-       struct snd_soc_dapm_path *p = NULL;
-
-       dev_dbg(dai->dev, "enter, dai-name=%s dir=%d\n", dai->name, stream);
-
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               dev_dbg(dai->dev, "Stream name=%s\n",
-                               dai->playback_widget->name);
-               w = dai->playback_widget;
-               list_for_each_entry(p, &w->sinks, list_source) {
-                       if (p->connected && !p->connected(w, p->sink))
-                               continue;
-
-                       if (p->connect && p->sink->power &&
-                                       is_sst_dapm_widget(p->sink)) {
-                               struct sst_ids *ids = p->sink->priv;
-
-                               dev_dbg(dai->dev, "send gains for widget=%s\n",
-                                               p->sink->name);
-                               mutex_lock(&drv->lock);
-                               sst_set_pipe_gain(ids, drv, mute);
-                               mutex_unlock(&drv->lock);
-                       }
-               }
-       } else {
-               dev_dbg(dai->dev, "Stream name=%s\n",
-                               dai->capture_widget->name);
-               w = dai->capture_widget;
-               list_for_each_entry(p, &w->sources, list_sink) {
-                       if (p->connected && !p->connected(w, p->sink))
-                               continue;
-
-                       if (p->connect &&  p->source->power &&
-                                       is_sst_dapm_widget(p->source)) {
-                               struct sst_ids *ids = p->source->priv;
-
-                               dev_dbg(dai->dev, "send gain for widget=%s\n",
-                                               p->source->name);
-                               mutex_lock(&drv->lock);
-                               sst_set_pipe_gain(ids, drv, mute);
-                               mutex_unlock(&drv->lock);
-                       }
-               }
-       }
-       return 0;
-}
-
-/**
- * sst_fill_module_list - populate the list of modules/gains for a pipe
- *
- *
- * Fills the widget pointer in the kcontrol private data, and also fills the
- * kcontrol pointer in the widget private data.
- *
- * Widget pointer is used to send the algo/gain in the .put() handler if the
- * widget is powerd on.
- *
- * Kcontrol pointer is used to send the algo/gain in the widget power ON/OFF
- * event handler. Each widget (pipe) has multiple algos stored in the algo_list.
- */
-static int sst_fill_module_list(struct snd_kcontrol *kctl,
-        struct snd_soc_dapm_widget *w, int type)
-{
-       struct sst_module *module = NULL;
-       struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
-       struct sst_ids *ids = w->priv;
-       int ret = 0;
-
-       module = devm_kzalloc(c->dev, sizeof(*module), GFP_KERNEL);
-       if (!module)
-               return -ENOMEM;
-
-       if (type == SST_MODULE_GAIN) {
-               struct sst_gain_mixer_control *mc = (void *)kctl->private_value;
-
-               mc->w = w;
-               module->kctl = kctl;
-               list_add_tail(&module->node, &ids->gain_list);
-       } else if (type == SST_MODULE_ALGO) {
-               struct sst_algo_control *bc = (void *)kctl->private_value;
-
-               bc->w = w;
-               module->kctl = kctl;
-               list_add_tail(&module->node, &ids->algo_list);
-       } else {
-               dev_err(c->dev, "invoked for unknown type %d module %s",
-                               type, kctl->id.name);
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-/**
- * sst_fill_widget_module_info - fill list of gains/algos for the pipe
- * @widget:    pipe modelled as a DAPM widget
- *
- * Fill the list of gains/algos for the widget by looking at all the card
- * controls and comparing the name of the widget with the first part of control
- * name. First part of control name contains the pipe name (widget name).
- */
-static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
-       struct snd_soc_platform *platform)
-{
-       struct snd_kcontrol *kctl;
-       int index, ret = 0;
-       struct snd_card *card = platform->component.card->snd_card;
-       char *idx;
-
-       down_read(&card->controls_rwsem);
-
-       list_for_each_entry(kctl, &card->controls, list) {
-               idx = strstr(kctl->id.name, " ");
-               if (idx == NULL)
-                       continue;
-               index  = strlen(kctl->id.name) - strlen(idx);
-
-               if (strstr(kctl->id.name, "Volume") &&
-                   !strncmp(kctl->id.name, w->name, index))
-                       ret = sst_fill_module_list(kctl, w, SST_MODULE_GAIN);
-
-               else if (strstr(kctl->id.name, "params") &&
-                        !strncmp(kctl->id.name, w->name, index))
-                       ret = sst_fill_module_list(kctl, w, SST_MODULE_ALGO);
-
-               else if (strstr(kctl->id.name, "Switch") &&
-                        !strncmp(kctl->id.name, w->name, index) &&
-                        strstr(kctl->id.name, "Gain")) {
-                       struct sst_gain_mixer_control *mc =
-                                               (void *)kctl->private_value;
-
-                       mc->w = w;
-
-               } else if (strstr(kctl->id.name, "interleaver") &&
-                        !strncmp(kctl->id.name, w->name, index)) {
-                       struct sst_enum *e = (void *)kctl->private_value;
-
-                       e->w = w;
-
-               } else if (strstr(kctl->id.name, "deinterleaver") &&
-                        !strncmp(kctl->id.name, w->name, index)) {
-
-                       struct sst_enum *e = (void *)kctl->private_value;
-
-                       e->w = w;
-               }
-
-               if (ret < 0) {
-                       up_read(&card->controls_rwsem);
-                       return ret;
-               }
-       }
-
-       up_read(&card->controls_rwsem);
-       return 0;
-}
-
-/**
- * sst_fill_linked_widgets - fill the parent pointer for the linked widget
- */
-static void sst_fill_linked_widgets(struct snd_soc_platform *platform,
-                                               struct sst_ids *ids)
-{
-       struct snd_soc_dapm_widget *w;
-       unsigned int len = strlen(ids->parent_wname);
-
-       list_for_each_entry(w, &platform->component.card->widgets, list) {
-               if (!strncmp(ids->parent_wname, w->name, len)) {
-                       ids->parent_w = w;
-                       break;
-               }
-       }
-}
-
-/**
- * sst_map_modules_to_pipe - fill algo/gains list for all pipes
- */
-static int sst_map_modules_to_pipe(struct snd_soc_platform *platform)
-{
-       struct snd_soc_dapm_widget *w;
-       int ret = 0;
-
-       list_for_each_entry(w, &platform->component.card->widgets, list) {
-               if (is_sst_dapm_widget(w) && (w->priv)) {
-                       struct sst_ids *ids = w->priv;
-
-                       dev_dbg(platform->dev, "widget type=%d name=%s\n",
-                                       w->id, w->name);
-                       INIT_LIST_HEAD(&ids->algo_list);
-                       INIT_LIST_HEAD(&ids->gain_list);
-                       ret = sst_fill_widget_module_info(w, platform);
-
-                       if (ret < 0)
-                               return ret;
-
-                       /* fill linked widgets */
-                       if (ids->parent_wname !=  NULL)
-                               sst_fill_linked_widgets(platform, ids);
-               }
-       }
-       return 0;
-}
-
-int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform)
-{
-       int i, ret = 0;
-       struct snd_soc_dapm_context *dapm =
-                       snd_soc_component_get_dapm(&platform->component);
-       struct sst_data *drv = snd_soc_platform_get_drvdata(platform);
-       unsigned int gains = ARRAY_SIZE(sst_gain_controls)/3;
-
-       drv->byte_stream = devm_kzalloc(platform->dev,
-                                       SST_MAX_BIN_BYTES, GFP_KERNEL);
-       if (!drv->byte_stream)
-               return -ENOMEM;
-
-       snd_soc_dapm_new_controls(dapm, sst_dapm_widgets,
-                       ARRAY_SIZE(sst_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, intercon,
-                       ARRAY_SIZE(intercon));
-       snd_soc_dapm_new_widgets(dapm->card);
-
-       for (i = 0; i < gains; i++) {
-               sst_gains[i].mute = SST_GAIN_MUTE_DEFAULT;
-               sst_gains[i].l_gain = SST_GAIN_VOLUME_DEFAULT;
-               sst_gains[i].r_gain = SST_GAIN_VOLUME_DEFAULT;
-               sst_gains[i].ramp_duration = SST_GAIN_RAMP_DURATION_DEFAULT;
-       }
-
-       ret = snd_soc_add_platform_controls(platform, sst_gain_controls,
-                       ARRAY_SIZE(sst_gain_controls));
-       if (ret)
-               return ret;
-
-       /* Initialize algo control params */
-       ret = sst_algo_control_init(platform->dev);
-       if (ret)
-               return ret;
-       ret = snd_soc_add_platform_controls(platform, sst_algo_controls,
-                       ARRAY_SIZE(sst_algo_controls));
-       if (ret)
-               return ret;
-
-       ret = snd_soc_add_platform_controls(platform, sst_slot_controls,
-                       ARRAY_SIZE(sst_slot_controls));
-       if (ret)
-               return ret;
-
-       ret = sst_map_modules_to_pipe(platform);
-
-       return ret;
-}
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h
deleted file mode 100644 (file)
index daecc58..0000000
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- *  sst-atom-controls.h - Intel MID Platform driver header file
- *
- *  Copyright (C) 2013-14 Intel Corp
- *  Author: Ramesh Babu <ramesh.babu.koul@intel.com>
- *     Omair M Abdullah <omair.m.abdullah@intel.com>
- *     Samreen Nilofer <samreen.nilofer@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-
-#ifndef __SST_ATOM_CONTROLS_H__
-#define __SST_ATOM_CONTROLS_H__
-
-#include <sound/soc.h>
-#include <sound/tlv.h>
-
-enum {
-       MERR_DPCM_AUDIO = 0,
-       MERR_DPCM_COMPR,
-};
-
-/* define a bit for each mixer input */
-#define SST_MIX_IP(x)          (x)
-
-#define SST_IP_CODEC0          SST_MIX_IP(2)
-#define SST_IP_CODEC1          SST_MIX_IP(3)
-#define SST_IP_LOOP0           SST_MIX_IP(4)
-#define SST_IP_LOOP1           SST_MIX_IP(5)
-#define SST_IP_LOOP2           SST_MIX_IP(6)
-#define SST_IP_PROBE           SST_MIX_IP(7)
-#define SST_IP_VOIP            SST_MIX_IP(12)
-#define SST_IP_PCM0            SST_MIX_IP(13)
-#define SST_IP_PCM1            SST_MIX_IP(14)
-#define SST_IP_MEDIA0          SST_MIX_IP(17)
-#define SST_IP_MEDIA1          SST_MIX_IP(18)
-#define SST_IP_MEDIA2          SST_MIX_IP(19)
-#define SST_IP_MEDIA3          SST_MIX_IP(20)
-
-#define SST_IP_LAST            SST_IP_MEDIA3
-
-#define SST_SWM_INPUT_COUNT    (SST_IP_LAST + 1)
-#define SST_CMD_SWM_MAX_INPUTS 6
-
-#define SST_PATH_ID_SHIFT      8
-#define SST_DEFAULT_LOCATION_ID        0xFFFF
-#define SST_DEFAULT_CELL_NBR   0xFF
-#define SST_DEFAULT_MODULE_ID  0xFFFF
-
-/*
- * Audio DSP Path Ids. Specified by the audio DSP FW
- */
-enum sst_path_index {
-       SST_PATH_INDEX_CODEC_OUT0               = (0x02 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_CODEC_OUT1               = (0x03 << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_SPROT_LOOP_OUT           = (0x04 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA_LOOP1_OUT          = (0x05 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA_LOOP2_OUT          = (0x06 << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_VOIP_OUT                 = (0x0C << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_PCM0_OUT                 = (0x0D << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_PCM1_OUT                 = (0x0E << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_PCM2_OUT                 = (0x0F << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_MEDIA0_OUT               = (0x12 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA1_OUT               = (0x13 << SST_PATH_ID_SHIFT),
-
-
-       /* Start of input paths */
-       SST_PATH_INDEX_CODEC_IN0                = (0x82 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_CODEC_IN1                = (0x83 << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_SPROT_LOOP_IN            = (0x84 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA_LOOP1_IN           = (0x85 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA_LOOP2_IN           = (0x86 << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_VOIP_IN                  = (0x8C << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_PCM0_IN                  = (0x8D << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_PCM1_IN                  = (0x8E << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_MEDIA0_IN                = (0x8F << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA1_IN                = (0x90 << SST_PATH_ID_SHIFT),
-       SST_PATH_INDEX_MEDIA2_IN                = (0x91 << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_MEDIA3_IN                = (0x9C << SST_PATH_ID_SHIFT),
-
-       SST_PATH_INDEX_RESERVED                 = (0xFF << SST_PATH_ID_SHIFT),
-};
-
-/*
- * path IDs
- */
-enum sst_swm_inputs {
-       SST_SWM_IN_CODEC0       = (SST_PATH_INDEX_CODEC_IN0       | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_CODEC1       = (SST_PATH_INDEX_CODEC_IN1       | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_SPROT_LOOP   = (SST_PATH_INDEX_SPROT_LOOP_IN   | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_MEDIA_LOOP1  = (SST_PATH_INDEX_MEDIA_LOOP1_IN  | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_MEDIA_LOOP2  = (SST_PATH_INDEX_MEDIA_LOOP2_IN  | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_VOIP         = (SST_PATH_INDEX_VOIP_IN         | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_PCM0         = (SST_PATH_INDEX_PCM0_IN         | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_PCM1         = (SST_PATH_INDEX_PCM1_IN         | SST_DEFAULT_CELL_NBR),
-       SST_SWM_IN_MEDIA0       = (SST_PATH_INDEX_MEDIA0_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
-       SST_SWM_IN_MEDIA1       = (SST_PATH_INDEX_MEDIA1_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
-       SST_SWM_IN_MEDIA2       = (SST_PATH_INDEX_MEDIA2_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
-       SST_SWM_IN_MEDIA3       = (SST_PATH_INDEX_MEDIA3_IN       | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
-       SST_SWM_IN_END          = (SST_PATH_INDEX_RESERVED        | SST_DEFAULT_CELL_NBR)
-};
-
-/*
- * path IDs
- */
-enum sst_swm_outputs {
-       SST_SWM_OUT_CODEC0      = (SST_PATH_INDEX_CODEC_OUT0      | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_CODEC1      = (SST_PATH_INDEX_CODEC_OUT1      | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_SPROT_LOOP  = (SST_PATH_INDEX_SPROT_LOOP_OUT  | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_OUT | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_OUT | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_VOIP        = (SST_PATH_INDEX_VOIP_OUT        | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_PCM0        = (SST_PATH_INDEX_PCM0_OUT        | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_PCM1        = (SST_PATH_INDEX_PCM1_OUT        | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_PCM2        = (SST_PATH_INDEX_PCM2_OUT        | SST_DEFAULT_CELL_NBR),
-       SST_SWM_OUT_MEDIA0      = (SST_PATH_INDEX_MEDIA0_OUT      | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
-       SST_SWM_OUT_MEDIA1      = (SST_PATH_INDEX_MEDIA1_OUT      | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
-       SST_SWM_OUT_END         = (SST_PATH_INDEX_RESERVED        | SST_DEFAULT_CELL_NBR),
-};
-
-enum sst_ipc_msg {
-       SST_IPC_IA_CMD = 1,
-       SST_IPC_IA_SET_PARAMS,
-       SST_IPC_IA_GET_PARAMS,
-};
-
-enum sst_cmd_type {
-       SST_CMD_BYTES_SET = 1,
-       SST_CMD_BYTES_GET = 2,
-};
-
-enum sst_task {
-       SST_TASK_SBA = 1,
-       SST_TASK_MMX = 3,
-};
-
-enum sst_type {
-       SST_TYPE_CMD = 1,
-       SST_TYPE_PARAMS,
-};
-
-enum sst_flag {
-       SST_FLAG_BLOCKED = 1,
-       SST_FLAG_NONBLOCK,
-};
-
-/*
- * Enumeration for indexing the gain cells in VB_SET_GAIN DSP command
- */
-enum sst_gain_index {
-       /* GAIN IDs for SB task start here */
-       SST_GAIN_INDEX_CODEC_OUT0,
-       SST_GAIN_INDEX_CODEC_OUT1,
-       SST_GAIN_INDEX_CODEC_IN0,
-       SST_GAIN_INDEX_CODEC_IN1,
-
-       SST_GAIN_INDEX_SPROT_LOOP_OUT,
-       SST_GAIN_INDEX_MEDIA_LOOP1_OUT,
-       SST_GAIN_INDEX_MEDIA_LOOP2_OUT,
-
-       SST_GAIN_INDEX_PCM0_IN_LEFT,
-       SST_GAIN_INDEX_PCM0_IN_RIGHT,
-
-       SST_GAIN_INDEX_PCM1_OUT_LEFT,
-       SST_GAIN_INDEX_PCM1_OUT_RIGHT,
-       SST_GAIN_INDEX_PCM1_IN_LEFT,
-       SST_GAIN_INDEX_PCM1_IN_RIGHT,
-       SST_GAIN_INDEX_PCM2_OUT_LEFT,
-
-       SST_GAIN_INDEX_PCM2_OUT_RIGHT,
-       SST_GAIN_INDEX_VOIP_OUT,
-       SST_GAIN_INDEX_VOIP_IN,
-
-       /* Gain IDs for MMX task start here */
-       SST_GAIN_INDEX_MEDIA0_IN_LEFT,
-       SST_GAIN_INDEX_MEDIA0_IN_RIGHT,
-       SST_GAIN_INDEX_MEDIA1_IN_LEFT,
-       SST_GAIN_INDEX_MEDIA1_IN_RIGHT,
-
-       SST_GAIN_INDEX_MEDIA2_IN_LEFT,
-       SST_GAIN_INDEX_MEDIA2_IN_RIGHT,
-
-       SST_GAIN_INDEX_GAIN_END
-};
-
-/*
- * Audio DSP module IDs specified by FW spec
- * TODO: Update with all modules
- */
-enum sst_module_id {
-       SST_MODULE_ID_PCM                 = 0x0001,
-       SST_MODULE_ID_MP3                 = 0x0002,
-       SST_MODULE_ID_MP24                = 0x0003,
-       SST_MODULE_ID_AAC                 = 0x0004,
-       SST_MODULE_ID_AACP                = 0x0005,
-       SST_MODULE_ID_EAACP               = 0x0006,
-       SST_MODULE_ID_WMA9                = 0x0007,
-       SST_MODULE_ID_WMA10               = 0x0008,
-       SST_MODULE_ID_WMA10P              = 0x0009,
-       SST_MODULE_ID_RA                  = 0x000A,
-       SST_MODULE_ID_DDAC3               = 0x000B,
-       SST_MODULE_ID_TRUE_HD             = 0x000C,
-       SST_MODULE_ID_HD_PLUS             = 0x000D,
-
-       SST_MODULE_ID_SRC                 = 0x0064,
-       SST_MODULE_ID_DOWNMIX             = 0x0066,
-       SST_MODULE_ID_GAIN_CELL           = 0x0067,
-       SST_MODULE_ID_SPROT               = 0x006D,
-       SST_MODULE_ID_BASS_BOOST          = 0x006E,
-       SST_MODULE_ID_STEREO_WDNG         = 0x006F,
-       SST_MODULE_ID_AV_REMOVAL          = 0x0070,
-       SST_MODULE_ID_MIC_EQ              = 0x0071,
-       SST_MODULE_ID_SPL                 = 0x0072,
-       SST_MODULE_ID_ALGO_VTSV           = 0x0073,
-       SST_MODULE_ID_NR                  = 0x0076,
-       SST_MODULE_ID_BWX                 = 0x0077,
-       SST_MODULE_ID_DRP                 = 0x0078,
-       SST_MODULE_ID_MDRP                = 0x0079,
-
-       SST_MODULE_ID_ANA                 = 0x007A,
-       SST_MODULE_ID_AEC                 = 0x007B,
-       SST_MODULE_ID_NR_SNS              = 0x007C,
-       SST_MODULE_ID_SER                 = 0x007D,
-       SST_MODULE_ID_AGC                 = 0x007E,
-
-       SST_MODULE_ID_CNI                 = 0x007F,
-       SST_MODULE_ID_CONTEXT_ALGO_AWARE  = 0x0080,
-       SST_MODULE_ID_FIR_24              = 0x0081,
-       SST_MODULE_ID_IIR_24              = 0x0082,
-
-       SST_MODULE_ID_ASRC                = 0x0083,
-       SST_MODULE_ID_TONE_GEN            = 0x0084,
-       SST_MODULE_ID_BMF                 = 0x0086,
-       SST_MODULE_ID_EDL                 = 0x0087,
-       SST_MODULE_ID_GLC                 = 0x0088,
-
-       SST_MODULE_ID_FIR_16              = 0x0089,
-       SST_MODULE_ID_IIR_16              = 0x008A,
-       SST_MODULE_ID_DNR                 = 0x008B,
-
-       SST_MODULE_ID_VIRTUALIZER         = 0x008C,
-       SST_MODULE_ID_VISUALIZATION       = 0x008D,
-       SST_MODULE_ID_LOUDNESS_OPTIMIZER  = 0x008E,
-       SST_MODULE_ID_REVERBERATION       = 0x008F,
-
-       SST_MODULE_ID_CNI_TX              = 0x0090,
-       SST_MODULE_ID_REF_LINE            = 0x0091,
-       SST_MODULE_ID_VOLUME              = 0x0092,
-       SST_MODULE_ID_FILT_DCR            = 0x0094,
-       SST_MODULE_ID_SLV                 = 0x009A,
-       SST_MODULE_ID_NLF                 = 0x009B,
-       SST_MODULE_ID_TNR                 = 0x009C,
-       SST_MODULE_ID_WNR                 = 0x009D,
-
-       SST_MODULE_ID_LOG                 = 0xFF00,
-
-       SST_MODULE_ID_TASK                = 0xFFFF,
-};
-
-enum sst_cmd {
-       SBA_IDLE                = 14,
-       SBA_VB_SET_SPEECH_PATH  = 26,
-       MMX_SET_GAIN            = 33,
-       SBA_VB_SET_GAIN         = 33,
-       FBA_VB_RX_CNI           = 35,
-       MMX_SET_GAIN_TIMECONST  = 36,
-       SBA_VB_SET_TIMECONST    = 36,
-       SBA_VB_START            = 85,
-       SBA_SET_SWM             = 114,
-       SBA_SET_MDRP            = 116,
-       SBA_HW_SET_SSP          = 117,
-       SBA_SET_MEDIA_LOOP_MAP  = 118,
-       SBA_SET_MEDIA_PATH      = 119,
-       MMX_SET_MEDIA_PATH      = 119,
-       SBA_VB_LPRO             = 126,
-       SBA_VB_SET_FIR          = 128,
-       SBA_VB_SET_IIR          = 129,
-       SBA_SET_SSP_SLOT_MAP    = 130,
-};
-
-enum sst_dsp_switch {
-       SST_SWITCH_OFF = 0,
-       SST_SWITCH_ON = 3,
-};
-
-enum sst_path_switch {
-       SST_PATH_OFF = 0,
-       SST_PATH_ON = 1,
-};
-
-enum sst_swm_state {
-       SST_SWM_OFF = 0,
-       SST_SWM_ON = 3,
-};
-
-#define SST_FILL_LOCATION_IDS(dst, cell_idx, pipe_id)          do {    \
-               dst.location_id.p.cell_nbr_idx = (cell_idx);            \
-               dst.location_id.p.path_id = (pipe_id);                  \
-       } while (0)
-#define SST_FILL_LOCATION_ID(dst, loc_id)                              (\
-       dst.location_id.f = (loc_id))
-#define SST_FILL_MODULE_ID(dst, mod_id)                                        (\
-       dst.module_id = (mod_id))
-
-#define SST_FILL_DESTINATION1(dst, id)                         do {    \
-               SST_FILL_LOCATION_ID(dst, (id) & 0xFFFF);               \
-               SST_FILL_MODULE_ID(dst, ((id) & 0xFFFF0000) >> 16);     \
-       } while (0)
-#define SST_FILL_DESTINATION2(dst, loc_id, mod_id)             do {    \
-               SST_FILL_LOCATION_ID(dst, loc_id);                      \
-               SST_FILL_MODULE_ID(dst, mod_id);                        \
-       } while (0)
-#define SST_FILL_DESTINATION3(dst, cell_idx, path_id, mod_id)  do {    \
-               SST_FILL_LOCATION_IDS(dst, cell_idx, path_id);          \
-               SST_FILL_MODULE_ID(dst, mod_id);                        \
-       } while (0)
-
-#define SST_FILL_DESTINATION(level, dst, ...)                          \
-       SST_FILL_DESTINATION##level(dst, __VA_ARGS__)
-#define SST_FILL_DEFAULT_DESTINATION(dst)                              \
-       SST_FILL_DESTINATION(2, dst, SST_DEFAULT_LOCATION_ID, SST_DEFAULT_MODULE_ID)
-
-struct sst_destination_id {
-       union sst_location_id {
-               struct {
-                       u8 cell_nbr_idx;        /* module index */
-                       u8 path_id;             /* pipe_id */
-               } __packed      p;              /* part */
-               u16             f;              /* full */
-       } __packed location_id;
-       u16        module_id;
-} __packed;
-struct sst_dsp_header {
-       struct sst_destination_id dst;
-       u16 command_id;
-       u16 length;
-} __packed;
-
-/*
- *
- * Common Commands
- *
- */
-struct sst_cmd_generic {
-       struct sst_dsp_header header;
-} __packed;
-
-struct swm_input_ids {
-       struct sst_destination_id input_id;
-} __packed;
-
-struct sst_cmd_set_swm {
-       struct sst_dsp_header header;
-       struct sst_destination_id output_id;
-       u16    switch_state;
-       u16    nb_inputs;
-       struct swm_input_ids input[SST_CMD_SWM_MAX_INPUTS];
-} __packed;
-
-struct sst_cmd_set_media_path {
-       struct sst_dsp_header header;
-       u16    switch_state;
-} __packed;
-
-struct pcm_cfg {
-               u8 s_length:2;
-               u8 rate:3;
-               u8 format:3;
-} __packed;
-
-struct sst_cmd_set_speech_path {
-       struct sst_dsp_header header;
-       u16    switch_state;
-       struct {
-               u16 rsvd:8;
-               struct pcm_cfg cfg;
-       } config;
-} __packed;
-
-struct gain_cell {
-       struct sst_destination_id dest;
-       s16 cell_gain_left;
-       s16 cell_gain_right;
-       u16 gain_time_constant;
-} __packed;
-
-#define NUM_GAIN_CELLS 1
-struct sst_cmd_set_gain_dual {
-       struct sst_dsp_header header;
-       u16    gain_cell_num;
-       struct gain_cell cell_gains[NUM_GAIN_CELLS];
-} __packed;
-struct sst_cmd_set_params {
-       struct sst_destination_id dst;
-       u16 command_id;
-       char params[0];
-} __packed;
-
-
-struct sst_cmd_sba_vb_start {
-       struct sst_dsp_header header;
-} __packed;
-
-union sba_media_loop_params {
-       struct {
-               u16 rsvd:8;
-               struct pcm_cfg cfg;
-       } part;
-       u16 full;
-} __packed;
-
-struct sst_cmd_sba_set_media_loop_map {
-       struct  sst_dsp_header header;
-       u16     switch_state;
-       union   sba_media_loop_params param;
-       u16     map;
-} __packed;
-
-struct sst_cmd_tone_stop {
-       struct  sst_dsp_header header;
-       u16     switch_state;
-} __packed;
-
-enum sst_ssp_mode {
-       SSP_MODE_MASTER = 0,
-       SSP_MODE_SLAVE = 1,
-};
-
-enum sst_ssp_pcm_mode {
-       SSP_PCM_MODE_NORMAL = 0,
-       SSP_PCM_MODE_NETWORK = 1,
-};
-
-enum sst_ssp_duplex {
-       SSP_DUPLEX = 0,
-       SSP_RX = 1,
-       SSP_TX = 2,
-};
-
-enum sst_ssp_fs_frequency {
-       SSP_FS_8_KHZ = 0,
-       SSP_FS_16_KHZ = 1,
-       SSP_FS_44_1_KHZ = 2,
-       SSP_FS_48_KHZ = 3,
-};
-
-enum sst_ssp_fs_polarity {
-       SSP_FS_ACTIVE_LOW = 0,
-       SSP_FS_ACTIVE_HIGH = 1,
-};
-
-enum sst_ssp_protocol {
-       SSP_MODE_PCM = 0,
-       SSP_MODE_I2S = 1,
-};
-
-enum sst_ssp_port_id {
-       SSP_MODEM = 0,
-       SSP_BT = 1,
-       SSP_FM = 2,
-       SSP_CODEC = 3,
-};
-
-struct sst_cmd_sba_hw_set_ssp {
-       struct sst_dsp_header header;
-       u16 selection;                  /* 0:SSP0(def), 1:SSP1, 2:SSP2 */
-
-       u16 switch_state;
-
-       u16 nb_bits_per_slots:6;        /* 0-32 bits, 24 (def) */
-       u16 nb_slots:4;                 /* 0-8: slots per frame  */
-       u16 mode:3;                     /* 0:Master, 1: Slave  */
-       u16 duplex:3;
-
-       u16 active_tx_slot_map:8;       /* Bit map, 0:off, 1:on */
-       u16 reserved1:8;
-
-       u16 active_rx_slot_map:8;       /* Bit map 0: Off, 1:On */
-       u16 reserved2:8;
-
-       u16 frame_sync_frequency;
-
-       u16 frame_sync_polarity:8;
-       u16 data_polarity:8;
-
-       u16 frame_sync_width;           /* 1 to N clocks */
-       u16 ssp_protocol:8;
-       u16 start_delay:8;              /* Start delay in terms of clock ticks */
-} __packed;
-
-#define SST_MAX_TDM_SLOTS 8
-
-struct sst_param_sba_ssp_slot_map {
-       struct sst_dsp_header header;
-
-       u16 param_id;
-       u16 param_len;
-       u16 ssp_index;
-
-       u8 rx_slot_map[SST_MAX_TDM_SLOTS];
-       u8 tx_slot_map[SST_MAX_TDM_SLOTS];
-} __packed;
-
-enum {
-       SST_PROBE_EXTRACTOR = 0,
-       SST_PROBE_INJECTOR = 1,
-};
-
-/**** widget defines *****/
-
-#define SST_MODULE_GAIN 1
-#define SST_MODULE_ALGO 2
-
-#define SST_FMT_MONO 0
-#define SST_FMT_STEREO 3
-
-/* physical SSP numbers */
-enum {
-       SST_SSP0 = 0,
-       SST_SSP1,
-       SST_SSP2,
-       SST_SSP_LAST = SST_SSP2,
-};
-
-#define SST_NUM_SSPS           (SST_SSP_LAST + 1)      /* physical SSPs */
-#define SST_MAX_SSP_MUX                2                       /* single SSP muxed between pipes */
-#define SST_MAX_SSP_DOMAINS    2                       /* domains present in each pipe */
-
-struct sst_module {
-       struct snd_kcontrol *kctl;
-       struct list_head node;
-};
-
-struct sst_ssp_config {
-       u8 ssp_id;
-       u8 bits_per_slot;
-       u8 slots;
-       u8 ssp_mode;
-       u8 pcm_mode;
-       u8 duplex;
-       u8 ssp_protocol;
-       u8 fs_frequency;
-       u8 active_slot_map;
-       u8 start_delay;
-       u16 fs_width;
-};
-
-struct sst_ssp_cfg {
-       const u8 ssp_number;
-       const int *mux_shift;
-       const int (*domain_shift)[SST_MAX_SSP_MUX];
-       const struct sst_ssp_config (*ssp_config)[SST_MAX_SSP_MUX][SST_MAX_SSP_DOMAINS];
-};
-
-struct sst_ids {
-       u16 location_id;
-       u16 module_id;
-       u8  task_id;
-       u8  format;
-       u8  reg;
-       const char *parent_wname;
-       struct snd_soc_dapm_widget *parent_w;
-       struct list_head algo_list;
-       struct list_head gain_list;
-       const struct sst_pcm_format *pcm_fmt;
-};
-
-
-#define SST_AIF_IN(wname, wevent)                                                      \
-{      .id = snd_soc_dapm_aif_in, .name = wname, .sname = NULL,                        \
-       .reg = SND_SOC_NOPM, .shift = 0,                                        \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
-       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
-}
-
-#define SST_AIF_OUT(wname, wevent)                                                     \
-{      .id = snd_soc_dapm_aif_out, .name = wname, .sname = NULL,                       \
-       .reg = SND_SOC_NOPM, .shift = 0,                                                \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
-       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
-}
-
-#define SST_INPUT(wname, wevent)                                                       \
-{      .id = snd_soc_dapm_input, .name = wname, .sname = NULL,                         \
-       .reg = SND_SOC_NOPM, .shift = 0,                                                \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
-       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
-}
-
-#define SST_OUTPUT(wname, wevent)                                                      \
-{      .id = snd_soc_dapm_output, .name = wname, .sname = NULL,                        \
-       .reg = SND_SOC_NOPM, .shift = 0,                                                \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
-       .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }            \
-}
-
-#define SST_DAPM_OUTPUT(wname, wloc_id, wtask_id, wformat, wevent)                      \
-{      .id = snd_soc_dapm_output, .name = wname, .sname = NULL,                        \
-       .reg = SND_SOC_NOPM, .shift = 0,                                                \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
-       .priv = (void *)&(struct sst_ids) { .location_id = wloc_id, .task_id = wtask_id,\
-                                               .pcm_fmt = wformat, }                   \
-}
-
-#define SST_PATH(wname, wtask, wloc_id, wevent, wflags)                                        \
-{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
-       .kcontrol_news = NULL, .num_kcontrols = 0,                              \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = wflags,                                         \
-       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id, } \
-}
-
-#define SST_LINKED_PATH(wname, wtask, wloc_id, linked_wname, wevent, wflags)           \
-{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
-       .kcontrol_news = NULL, .num_kcontrols = 0,                              \
-       .on_val = 1, .off_val = 0,                                                      \
-       .event = wevent, .event_flags = wflags,                                         \
-       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
-                                       .parent_wname = linked_wname}                   \
-}
-
-#define SST_PATH_MEDIA_LOOP(wname, wtask, wloc_id, wformat, wevent, wflags)             \
-{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
-       .kcontrol_news = NULL, .num_kcontrols = 0,                         \
-       .event = wevent, .event_flags = wflags,                                         \
-       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
-                                           .format = wformat,}                         \
-}
-
-/* output is triggered before input */
-#define SST_PATH_INPUT(name, task_id, loc_id, event)                                   \
-       SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
-
-#define SST_PATH_LINKED_INPUT(name, task_id, loc_id, linked_wname, event)              \
-       SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,                     \
-                                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
-
-#define SST_PATH_OUTPUT(name, task_id, loc_id, event)                                  \
-       SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
-
-#define SST_PATH_LINKED_OUTPUT(name, task_id, loc_id, linked_wname, event)             \
-       SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,                     \
-                                       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
-
-#define SST_PATH_MEDIA_LOOP_OUTPUT(name, task_id, loc_id, format, event)               \
-       SST_PATH_MEDIA_LOOP(name, task_id, loc_id, format, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
-
-
-#define SST_SWM_MIXER(wname, wreg, wtask, wloc_id, wcontrols, wevent)                  \
-{      .id = snd_soc_dapm_mixer, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,       \
-       .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols),\
-       .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD |  \
-                                       SND_SOC_DAPM_POST_REG,                          \
-       .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
-                                           .reg = wreg }                               \
-}
-
-enum sst_gain_kcontrol_type {
-       SST_GAIN_TLV,
-       SST_GAIN_MUTE,
-       SST_GAIN_RAMP_DURATION,
-};
-
-struct sst_gain_mixer_control {
-       bool stereo;
-       enum sst_gain_kcontrol_type type;
-       struct sst_gain_value *gain_val;
-       int max;
-       int min;
-       u16 instance_id;
-       u16 module_id;
-       u16 pipe_id;
-       u16 task_id;
-       char pname[44];
-       struct snd_soc_dapm_widget *w;
-};
-
-struct sst_gain_value {
-       u16 ramp_duration;
-       s16 l_gain;
-       s16 r_gain;
-       bool mute;
-};
-#define SST_GAIN_VOLUME_DEFAULT                (-1440)
-#define SST_GAIN_RAMP_DURATION_DEFAULT 5 /* timeconstant */
-#define SST_GAIN_MUTE_DEFAULT          true
-
-#define SST_GAIN_KCONTROL_TLV(xname, xhandler_get, xhandler_put, \
-                             xmod, xpipe, xinstance, xtask, tlv_array, xgain_val, \
-                             xmin, xmax, xpname) \
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-                 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-       .tlv.p = (tlv_array), \
-       .info = sst_gain_ctl_info,\
-       .get = xhandler_get, .put = xhandler_put, \
-       .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
-       { .stereo = true, .max = xmax, .min = xmin, .type = SST_GAIN_TLV, \
-         .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
-         .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
-
-#define SST_GAIN_KCONTROL_INT(xname, xhandler_get, xhandler_put, \
-                             xmod, xpipe, xinstance, xtask, xtype, xgain_val, \
-                             xmin, xmax, xpname) \
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .info = sst_gain_ctl_info, \
-       .get = xhandler_get, .put = xhandler_put, \
-       .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
-       { .stereo = false, .max = xmax, .min = xmin, .type = xtype, \
-         .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
-         .instance_id = xinstance, .gain_val = xgain_val, .pname =  xpname}
-
-#define SST_GAIN_KCONTROL_BOOL(xname, xhandler_get, xhandler_put,\
-                              xmod, xpipe, xinstance, xtask, xgain_val, xpname) \
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .info = snd_soc_info_bool_ext, \
-       .get = xhandler_get, .put = xhandler_put, \
-       .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
-       { .stereo = false, .type = SST_GAIN_MUTE, \
-         .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
-         .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
-#define SST_CONTROL_NAME(xpname, xmname, xinstance, xtype) \
-       xpname " " xmname " " #xinstance " " xtype
-
-#define SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, xtype, xsubmodule) \
-       xpname " " xmname " " #xinstance " " xtype " " xsubmodule
-
-/*
- * 3 Controls for each Gain module
- * e.g.        - pcm0_in Gain 0 Volume
- *     - pcm0_in Gain 0 Ramp Delay
- *     - pcm0_in Gain 0 Switch
- */
-#define SST_GAIN_KCONTROLS(xpname, xmname, xmin_gain, xmax_gain, xmin_tc, xmax_tc, \
-                          xhandler_get, xhandler_put, \
-                          xmod, xpipe, xinstance, xtask, tlv_array, xgain_val) \
-       { SST_GAIN_KCONTROL_INT(SST_CONTROL_NAME(xpname, xmname, xinstance, "Ramp Delay"), \
-               xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, SST_GAIN_RAMP_DURATION, \
-               xgain_val, xmin_tc, xmax_tc, xpname) }, \
-       { SST_GAIN_KCONTROL_BOOL(SST_CONTROL_NAME(xpname, xmname, xinstance, "Switch"), \
-               xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, \
-               xgain_val, xpname) } ,\
-       { SST_GAIN_KCONTROL_TLV(SST_CONTROL_NAME(xpname, xmname, xinstance, "Volume"), \
-               xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, tlv_array, \
-               xgain_val, xmin_gain, xmax_gain, xpname) }
-
-#define SST_GAIN_TC_MIN                5
-#define SST_GAIN_TC_MAX                5000
-#define SST_GAIN_MIN_VALUE     -1440 /* in 0.1 DB units */
-#define SST_GAIN_MAX_VALUE     360
-
-enum sst_algo_kcontrol_type {
-       SST_ALGO_PARAMS,
-       SST_ALGO_BYPASS,
-};
-
-struct sst_algo_control {
-       enum sst_algo_kcontrol_type type;
-       int max;
-       u16 module_id;
-       u16 pipe_id;
-       u16 task_id;
-       u16 cmd_id;
-       bool bypass;
-       unsigned char *params;
-       struct snd_soc_dapm_widget *w;
-};
-
-/* size of the control = size of params + size of length field */
-#define SST_ALGO_CTL_VALUE(xcount, xtype, xpipe, xmod, xtask, xcmd)                    \
-       (struct sst_algo_control){                                                      \
-               .max = xcount + sizeof(u16), .type = xtype, .module_id = xmod,                  \
-               .pipe_id = xpipe, .task_id = xtask, .cmd_id = xcmd,                     \
-       }
-
-#define SST_ALGO_KCONTROL(xname, xcount, xmod, xpipe,                                  \
-                         xtask, xcmd, xtype, xinfo, xget, xput)                        \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                                            \
-       .name =  xname,                                                                 \
-       .info = xinfo, .get = xget, .put = xput,                                        \
-       .private_value = (unsigned long)&                                               \
-                       SST_ALGO_CTL_VALUE(xcount, xtype, xpipe,                        \
-                                          xmod, xtask, xcmd),                          \
-}
-
-#define SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod,                          \
-                               xpipe, xinstance, xtask, xcmd)                          \
-       SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "params"),        \
-                         xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,            \
-                         sst_algo_bytes_ctl_info,                                      \
-                         sst_algo_control_get, sst_algo_control_set)
-
-#define SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask)          \
-       SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "bypass"),        \
-                         0, xmod, xpipe, xtask, 0, SST_ALGO_BYPASS,                    \
-                         snd_soc_info_bool_ext,                                        \
-                         sst_algo_control_get, sst_algo_control_set)
-
-#define SST_ALGO_BYPASS_PARAMS(xpname, xmname, xcount, xmod, xpipe,                    \
-                               xinstance, xtask, xcmd)                                 \
-       SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask),          \
-       SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod, xpipe, xinstance, xtask, xcmd)
-
-#define SST_COMBO_ALGO_KCONTROL_BYTES(xpname, xmname, xsubmod, xcount, xmod,           \
-                                     xpipe, xinstance, xtask, xcmd)                    \
-       SST_ALGO_KCONTROL(SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, "params",   \
-                                                xsubmod),                              \
-                         xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,            \
-                         sst_algo_bytes_ctl_info,                                      \
-                         sst_algo_control_get, sst_algo_control_set)
-
-
-struct sst_enum {
-       bool tx;
-       unsigned short reg;
-       unsigned int max;
-       const char * const *texts;
-       struct snd_soc_dapm_widget *w;
-};
-
-/* only 4 slots/channels supported atm */
-#define SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts) \
-       (struct sst_enum){ .reg = s_ch_no, .tx = is_tx, .max = 4+1, .texts = xtexts, }
-
-#define SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name) \
-       xpname " " xmname " " s_ch_name
-
-#define SST_SSP_SLOT_CTL(xpname, xmname, s_ch_name, s_ch_no, is_tx, xtexts, xget, xput) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name), \
-       .info = sst_slot_enum_info, \
-       .get = xget, .put = xput, \
-       .private_value = (unsigned long)&SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts), \
-}
-
-#define SST_MUX_CTL_NAME(xpname, xinstance) \
-       xpname " " #xinstance
-
-#define SST_SSP_MUX_ENUM(xreg, xshift, xtexts) \
-       (struct soc_enum) SOC_ENUM_DOUBLE(xreg, xshift, xshift, ARRAY_SIZE(xtexts), xtexts)
-
-#define SST_SSP_MUX_CTL(xpname, xinstance, xreg, xshift, xtexts) \
-       SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
-                         SST_SSP_MUX_ENUM(xreg, xshift, xtexts))
-
-#endif
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h
deleted file mode 100644 (file)
index 4257263..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-#ifndef __SST_MFLD_DSP_H__
-#define __SST_MFLD_DSP_H__
-/*
- *  sst_mfld_dsp.h - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14 Intel Corporation
- *  Authors:   Vinod Koul <vinod.koul@linux.intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#define SST_MAX_BIN_BYTES 1024
-
-#define MAX_DBG_RW_BYTES 80
-#define MAX_NUM_SCATTER_BUFFERS 8
-#define MAX_LOOP_BACK_DWORDS 8
-/* IPC base address and mailbox, timestamp offsets */
-#define SST_MAILBOX_SIZE 0x0400
-#define SST_MAILBOX_SEND 0x0000
-#define SST_TIME_STAMP 0x1800
-#define SST_TIME_STAMP_MRFLD 0x800
-#define SST_RESERVED_OFFSET 0x1A00
-#define SST_SCU_LPE_MAILBOX 0x1000
-#define SST_LPE_SCU_MAILBOX 0x1400
-#define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16)
-#define PROCESS_MSG 0x80
-
-/* Message ID's for IPC messages */
-/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
-
-/* I2L Firmware/Codec Download msgs */
-#define IPC_IA_PREP_LIB_DNLD 0x01
-#define IPC_IA_LIB_DNLD_CMPLT 0x02
-#define IPC_IA_GET_FW_VERSION 0x04
-#define IPC_IA_GET_FW_BUILD_INF 0x05
-#define IPC_IA_GET_FW_INFO 0x06
-#define IPC_IA_GET_FW_CTXT 0x07
-#define IPC_IA_SET_FW_CTXT 0x08
-#define IPC_IA_PREPARE_SHUTDOWN 0x31
-/* I2L Codec Config/control msgs */
-#define IPC_PREP_D3 0x10
-#define IPC_IA_SET_CODEC_PARAMS 0x10
-#define IPC_IA_GET_CODEC_PARAMS 0x11
-#define IPC_IA_SET_PPP_PARAMS 0x12
-#define IPC_IA_GET_PPP_PARAMS 0x13
-#define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA
-#define IPC_IA_ALG_PARAMS 0x1A
-#define IPC_IA_TUNING_PARAMS 0x1B
-#define IPC_IA_SET_RUNTIME_PARAMS 0x1C
-#define IPC_IA_SET_PARAMS 0x1
-#define IPC_IA_GET_PARAMS 0x2
-
-#define IPC_EFFECTS_CREATE 0xE
-#define IPC_EFFECTS_DESTROY 0xF
-
-/* I2L Stream config/control msgs */
-#define IPC_IA_ALLOC_STREAM_MRFLD 0x2
-#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
-#define IPC_IA_FREE_STREAM_MRFLD 0x03
-#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
-#define IPC_IA_SET_STREAM_PARAMS 0x22
-#define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12
-#define IPC_IA_GET_STREAM_PARAMS 0x23
-#define IPC_IA_PAUSE_STREAM 0x24
-#define IPC_IA_PAUSE_STREAM_MRFLD 0x4
-#define IPC_IA_RESUME_STREAM 0x25
-#define IPC_IA_RESUME_STREAM_MRFLD 0x5
-#define IPC_IA_DROP_STREAM 0x26
-#define IPC_IA_DROP_STREAM_MRFLD 0x07
-#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
-#define IPC_IA_DRAIN_STREAM_MRFLD 0x8
-#define IPC_IA_CONTROL_ROUTING 0x29
-#define IPC_IA_VTSV_UPDATE_MODULES 0x20
-#define IPC_IA_VTSV_DETECTED 0x21
-
-#define IPC_IA_START_STREAM_MRFLD 0X06
-#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
-
-#define IPC_IA_SET_GAIN_MRFLD 0x21
-/* Debug msgs */
-#define IPC_IA_DBG_MEM_READ 0x40
-#define IPC_IA_DBG_MEM_WRITE 0x41
-#define IPC_IA_DBG_LOOP_BACK 0x42
-#define IPC_IA_DBG_LOG_ENABLE 0x45
-#define IPC_IA_DBG_SET_PROBE_PARAMS 0x47
-
-/* L2I Firmware/Codec Download msgs */
-#define IPC_IA_FW_INIT_CMPLT 0x81
-#define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01
-#define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11
-
-/* L2I Codec Config/control msgs */
-#define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */
-
-#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
-#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
-#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
-#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
-#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
-#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
-
-#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
-/* L2S messages */
-#define IPC_SC_DDR_LINK_UP 0xC0
-#define IPC_SC_DDR_LINK_DOWN 0xC1
-#define IPC_SC_SET_LPECLK_REQ 0xC2
-#define IPC_SC_SSP_BIT_BANG 0xC3
-
-/* L2I Error reporting msgs */
-#define IPC_IA_MEM_ALLOC_FAIL 0xE0
-#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
-                                       stream can be used by playback and
-                                       capture modules */
-
-/* L2I Debug msgs */
-#define IPC_IA_PRINT_STRING 0xF0
-
-/* Buffer under-run */
-#define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B
-
-/* Mrfld specific defines:
- * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR)
- * received from FW, the format is:
- *  - IPC High: pvt_id is set to zero. Always short message.
- *  - msg_id is in lower 16-bits of IPC low payload.
- *  - pipe_id is in higher 16-bits of IPC low payload for period_elapsed.
- *  - error id is in higher 16-bits of IPC low payload for async errors.
- */
-#define SST_ASYNC_DRV_ID 0
-
-/* Command Response or Acknowledge message to any IPC message will have
- * same message ID and stream ID information which is sent.
- * There is no specific Ack message ID. The data field is used as response
- * meaning.
- */
-enum ackData {
-       IPC_ACK_SUCCESS = 0,
-       IPC_ACK_FAILURE,
-};
-
-enum ipc_ia_msg_id {
-       IPC_CMD = 1,            /*!< Task Control message ID */
-       IPC_SET_PARAMS = 2,/*!< Task Set param message ID */
-       IPC_GET_PARAMS = 3,     /*!< Task Get param message ID */
-       IPC_INVALID = 0xFF,     /*!<Task Get param message ID */
-};
-
-enum sst_codec_types {
-       /*  AUDIO/MUSIC CODEC Type Definitions */
-       SST_CODEC_TYPE_UNKNOWN = 0,
-       SST_CODEC_TYPE_PCM,     /* Pass through Audio codec */
-       SST_CODEC_TYPE_MP3,
-       SST_CODEC_TYPE_MP24,
-       SST_CODEC_TYPE_AAC,
-       SST_CODEC_TYPE_AACP,
-       SST_CODEC_TYPE_eAACP,
-};
-
-enum stream_type {
-       SST_STREAM_TYPE_NONE = 0,
-       SST_STREAM_TYPE_MUSIC = 1,
-};
-
-enum sst_error_codes {
-       /* Error code,response to msgId: Description */
-       /* Common error codes */
-       SST_SUCCESS = 0,        /* Success */
-       SST_ERR_INVALID_STREAM_ID = 1,
-       SST_ERR_INVALID_MSG_ID = 2,
-       SST_ERR_INVALID_STREAM_OP = 3,
-       SST_ERR_INVALID_PARAMS = 4,
-       SST_ERR_INVALID_CODEC = 5,
-       SST_ERR_INVALID_MEDIA_TYPE = 6,
-       SST_ERR_STREAM_ERR = 7,
-
-       SST_ERR_STREAM_IN_USE = 15,
-};
-
-struct ipc_dsp_hdr {
-       u16 mod_index_id:8;             /*!< DSP Command ID specific to tasks */
-       u16 pipe_id:8;  /*!< instance of the module in the pipeline */
-       u16 mod_id;             /*!< Pipe_id */
-       u16 cmd_id;             /*!< Module ID = lpe_algo_types_t */
-       u16 length;             /*!< Length of the payload only */
-} __packed;
-
-union ipc_header_high {
-       struct {
-               u32  msg_id:8;      /* Message ID - Max 256 Message Types */
-               u32  task_id:4;     /* Task ID associated with this comand */
-               u32  drv_id:4;    /* Identifier for the driver to track*/
-               u32  rsvd1:8;       /* Reserved */
-               u32  result:4;      /* Reserved */
-               u32  res_rqd:1;     /* Response rqd */
-               u32  large:1;       /* Large Message if large = 1 */
-               u32  done:1;        /* bit 30 - Done bit */
-               u32  busy:1;        /* bit 31 - busy bit*/
-       } part;
-       u32 full;
-} __packed;
-/* IPC header */
-union ipc_header_mrfld {
-       struct {
-               u32 header_low_payload;
-               union ipc_header_high header_high;
-       } p;
-       u64 full;
-} __packed;
-/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
-
-/* IPC Header */
-union ipc_header {
-       struct {
-               u32  msg_id:8; /* Message ID - Max 256 Message Types */
-               u32  str_id:5;
-               u32  large:1;   /* Large Message if large = 1 */
-               u32  reserved:2;        /* Reserved for future use */
-               u32  data:14;   /* Ack/Info for msg, size of msg in Mailbox */
-               u32  done:1; /* bit 30 */
-               u32  busy:1; /* bit 31 */
-       } part;
-       u32 full;
-} __packed;
-
-/* Firmware build info */
-struct sst_fw_build_info {
-       unsigned char  date[16]; /* Firmware build date */
-       unsigned char  time[16]; /* Firmware build time */
-} __packed;
-
-/* Firmware Version info */
-struct snd_sst_fw_version {
-       u8 build;       /* build number*/
-       u8 minor;       /* minor number*/
-       u8 major;       /* major number*/
-       u8 type;        /* build type */
-};
-
-struct ipc_header_fw_init {
-       struct snd_sst_fw_version fw_version;/* Firmware version details */
-       struct sst_fw_build_info build_info;
-       u16 result;     /* Fw init result */
-       u8 module_id; /* Module ID in case of error */
-       u8 debug_info; /* Debug info from Module ID in case of fail */
-} __packed;
-
-struct snd_sst_tstamp {
-       u64 ring_buffer_counter;        /* PB/CP: Bytes copied from/to DDR. */
-       u64 hardware_counter;       /* PB/CP: Bytes DMAed to/from SSP. */
-       u64 frames_decoded;
-       u64 bytes_decoded;
-       u64 bytes_copied;
-       u32 sampling_frequency;
-       u32 channel_peak[8];
-} __packed;
-
-/* Stream type params struture for Alloc stream */
-struct snd_sst_str_type {
-       u8 codec_type;          /* Codec type */
-       u8 str_type;            /* 1 = voice 2 = music */
-       u8 operation;           /* Playback or Capture */
-       u8 protected_str;       /* 0=Non DRM, 1=DRM */
-       u8 time_slots;
-       u8 reserved;            /* Reserved */
-       u16 result;             /* Result used for acknowledgment */
-} __packed;
-
-/* Library info structure */
-struct module_info {
-       u32 lib_version;
-       u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
-       u32 media_type;
-       u8  lib_name[12];
-       u32 lib_caps;
-       unsigned char  b_date[16]; /* Lib build date */
-       unsigned char  b_time[16]; /* Lib build time */
-} __packed;
-
-/* Library slot info */
-struct lib_slot_info {
-       u8  slot_num; /* 1 or 2 */
-       u8  reserved1;
-       u16 reserved2;
-       u32 iram_size; /* slot size in IRAM */
-       u32 dram_size; /* slot size in DRAM */
-       u32 iram_offset; /* starting offset of slot in IRAM */
-       u32 dram_offset; /* starting offset of slot in DRAM */
-} __packed;
-
-struct snd_ppp_mixer_params {
-       __u32                   type; /*Type of the parameter */
-       __u32                   size;
-       __u32                   input_stream_bitmap; /*Input stream Bit Map*/
-} __packed;
-
-struct snd_sst_lib_download {
-       struct module_info lib_info; /* library info type, capabilities etc */
-       struct lib_slot_info slot_info; /* slot info to be downloaded */
-       u32 mod_entry_pt;
-};
-
-struct snd_sst_lib_download_info {
-       struct snd_sst_lib_download dload_lib;
-       u16 result;     /* Result used for acknowledgment */
-       u8 pvt_id; /* Private ID */
-       u8 reserved;  /* for alignment */
-};
-struct snd_pcm_params {
-       u8 num_chan;    /* 1=Mono, 2=Stereo */
-       u8 pcm_wd_sz;   /* 16/24 - bit*/
-       u8 use_offload_path;    /* 0-PCM using period elpased & ALSA interfaces
-                                  1-PCM stream via compressed interface  */
-       u8 reserved2;
-       u32 sfreq;    /* Sampling rate in Hz */
-       u8 channel_map[8];
-} __packed;
-
-/* MP3 Music Parameters Message */
-struct snd_mp3_params {
-       u8  num_chan;   /* 1=Mono, 2=Stereo     */
-       u8  pcm_wd_sz; /* 16/24 - bit*/
-       u8  crc_check; /* crc_check - disable (0) or enable (1) */
-       u8  reserved1; /* unused*/
-       u16 reserved2;  /* Unused */
-} __packed;
-
-#define AAC_BIT_STREAM_ADTS            0
-#define AAC_BIT_STREAM_ADIF            1
-#define AAC_BIT_STREAM_RAW             2
-
-/* AAC Music Parameters Message */
-struct snd_aac_params {
-       u8 num_chan; /* 1=Mono, 2=Stereo*/
-       u8 pcm_wd_sz; /* 16/24 - bit*/
-       u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */
-       u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */
-       u16  reser2;
-       u32 externalsr; /*sampling rate of basic AAC raw bit stream*/
-       u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/
-       u8 reser1;
-       u16  reser3;
-} __packed;
-
-/* WMA Music Parameters Message */
-struct snd_wma_params {
-       u8  num_chan;   /* 1=Mono, 2=Stereo */
-       u8  pcm_wd_sz;  /* 16/24 - bit*/
-       u16 reserved1;
-       u32 brate;      /* Use the hard coded value. */
-       u32 sfreq;      /* Sampling freq eg. 8000, 441000, 48000 */
-       u32 channel_mask;  /* Channel Mask */
-       u16 format_tag; /* Format Tag */
-       u16 block_align;        /* packet size */
-       u16 wma_encode_opt;/* Encoder option */
-       u8 op_align;    /* op align 0- 16 bit, 1- MSB, 2 LSB */
-       u8 reserved;    /* reserved */
-} __packed;
-
-/* Codec params struture */
-union  snd_sst_codec_params {
-       struct snd_pcm_params pcm_params;
-       struct snd_mp3_params mp3_params;
-       struct snd_aac_params aac_params;
-       struct snd_wma_params wma_params;
-} __packed;
-
-/* Address and size info of a frame buffer */
-struct sst_address_info {
-       u32 addr; /* Address at IA */
-       u32 size; /* Size of the buffer */
-};
-
-struct snd_sst_alloc_params_ext {
-       __u16 sg_count;
-       __u16 reserved;
-       __u32 frag_size;        /*Number of samples after which period elapsed
-                                 message is sent valid only if path  = 0*/
-       struct sst_address_info  ring_buf_info[8];
-};
-
-struct snd_sst_stream_params {
-       union snd_sst_codec_params uc;
-} __packed;
-
-struct snd_sst_params {
-       u32 result;
-       u32 stream_id;
-       u8 codec;
-       u8 ops;
-       u8 stream_type;
-       u8 device_type;
-       u8 task;
-       struct snd_sst_stream_params sparams;
-       struct snd_sst_alloc_params_ext aparams;
-};
-
-struct snd_sst_alloc_mrfld {
-       u16 codec_type;
-       u8 operation;
-       u8 sg_count;
-       struct sst_address_info ring_buf_info[8];
-       u32 frag_size;
-       u32 ts;
-       struct snd_sst_stream_params codec_params;
-} __packed;
-
-/* Alloc stream params structure */
-struct snd_sst_alloc_params {
-       struct snd_sst_str_type str_type;
-       struct snd_sst_stream_params stream_params;
-       struct snd_sst_alloc_params_ext alloc_params;
-} __packed;
-
-/* Alloc stream response message */
-struct snd_sst_alloc_response {
-       struct snd_sst_str_type str_type; /* Stream type for allocation */
-       struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
-};
-
-/* Drop response */
-struct snd_sst_drop_response {
-       u32 result;
-       u32 bytes;
-};
-
-struct snd_sst_async_msg {
-       u32 msg_id; /* Async msg id */
-       u32 payload[0];
-};
-
-struct snd_sst_async_err_msg {
-       u32 fw_resp; /* Firmware Result */
-       u32 lib_resp; /*Library result */
-} __packed;
-
-struct snd_sst_vol {
-       u32     stream_id;
-       s32     volume;
-       u32     ramp_duration;
-       u32     ramp_type;              /* Ramp type, default=0 */
-};
-
-/* Gain library parameters for mrfld
- * based on DSP command spec v0.82
- */
-struct snd_sst_gain_v2 {
-       u16 gain_cell_num;  /* num of gain cells to modify*/
-       u8 cell_nbr_idx; /* instance index*/
-       u8 cell_path_idx; /* pipe-id */
-       u16 module_id; /*module id */
-       u16 left_cell_gain; /* left gain value in dB*/
-       u16 right_cell_gain; /* right gain value in dB*/
-       u16 gain_time_const; /* gain time constant*/
-} __packed;
-
-struct snd_sst_mute {
-       u32     stream_id;
-       u32     mute;
-};
-
-struct snd_sst_runtime_params {
-       u8 type;
-       u8 str_id;
-       u8 size;
-       u8 rsvd;
-       void *addr;
-} __packed;
-
-enum stream_param_type {
-       SST_SET_TIME_SLOT = 0,
-       SST_SET_CHANNEL_INFO = 1,
-       OTHERS = 2, /*reserved for future params*/
-};
-
-/* CSV Voice call routing structure */
-struct snd_sst_control_routing {
-       u8 control; /* 0=start, 1=Stop */
-       u8 reserved[3]; /* Reserved- for 32 bit alignment */
-};
-
-struct ipc_post {
-       struct list_head node;
-       union ipc_header header; /* driver specific */
-       bool is_large;
-       bool is_process_reply;
-       union ipc_header_mrfld mrfld_header;
-       char *mailbox_data;
-};
-
-struct snd_sst_ctxt_params {
-       u32 address; /* Physical Address in DDR where the context is stored */
-       u32 size; /* size of the context */
-};
-
-struct snd_sst_lpe_log_params {
-       u8 dbg_type;
-       u8 module_id;
-       u8 log_level;
-       u8 reserved;
-} __packed;
-
-enum snd_sst_bytes_type {
-       SND_SST_BYTES_SET = 0x1,
-       SND_SST_BYTES_GET = 0x2,
-};
-
-struct snd_sst_bytes_v2 {
-       u8 type;
-       u8 ipc_msg;
-       u8 block;
-       u8 task_id;
-       u8 pipe_id;
-       u8 rsvd;
-       u16 len;
-       char bytes[0];
-};
-
-#define MAX_VTSV_FILES 2
-struct snd_sst_vtsv_info {
-       struct sst_address_info vfiles[MAX_VTSV_FILES];
-} __packed;
-
-#endif /* __SST_MFLD_DSP_H__ */
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c
deleted file mode 100644 (file)
index 3951689..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- *  sst_mfld_platform.c - Intel MID Platform driver
- *
- *  Copyright (C) 2010-2014 Intel Corp
- *  Author: Vinod Koul <vinod.koul@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include "sst-mfld-platform.h"
-
-/* compress stream operations */
-static void sst_compr_fragment_elapsed(void *arg)
-{
-       struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
-
-       pr_debug("fragment elapsed by driver\n");
-       if (cstream)
-               snd_compr_fragment_elapsed(cstream);
-}
-
-static void sst_drain_notify(void *arg)
-{
-       struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
-
-       pr_debug("drain notify by driver\n");
-       if (cstream)
-               snd_compr_drain_notify(cstream);
-}
-
-static int sst_platform_compr_open(struct snd_compr_stream *cstream)
-{
-
-       int ret_val = 0;
-       struct snd_compr_runtime *runtime = cstream->runtime;
-       struct sst_runtime_stream *stream;
-
-       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
-       if (!stream)
-               return -ENOMEM;
-
-       spin_lock_init(&stream->status_lock);
-
-       /* get the sst ops */
-       if (!sst || !try_module_get(sst->dev->driver->owner)) {
-               pr_err("no device available to run\n");
-               ret_val = -ENODEV;
-               goto out_ops;
-       }
-       stream->compr_ops = sst->compr_ops;
-       stream->id = 0;
-
-       /* Turn on LPE */
-       sst->compr_ops->power(sst->dev, true);
-
-       sst_set_stream_status(stream, SST_PLATFORM_INIT);
-       runtime->private_data = stream;
-       return 0;
-out_ops:
-       kfree(stream);
-       return ret_val;
-}
-
-static int sst_platform_compr_free(struct snd_compr_stream *cstream)
-{
-       struct sst_runtime_stream *stream;
-       int ret_val = 0, str_id;
-
-       stream = cstream->runtime->private_data;
-       /* Turn off LPE */
-       sst->compr_ops->power(sst->dev, false);
-
-       /*need to check*/
-       str_id = stream->id;
-       if (str_id)
-               ret_val = stream->compr_ops->close(sst->dev, str_id);
-       module_put(sst->dev->driver->owner);
-       kfree(stream);
-       pr_debug("%s: %d\n", __func__, ret_val);
-       return 0;
-}
-
-static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
-                                       struct snd_compr_params *params)
-{
-       struct sst_runtime_stream *stream;
-       int retval;
-       struct snd_sst_params str_params;
-       struct sst_compress_cb cb;
-       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-       struct snd_soc_platform *platform = rtd->platform;
-       struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
-
-       stream = cstream->runtime->private_data;
-       /* construct fw structure for this*/
-       memset(&str_params, 0, sizeof(str_params));
-
-       /* fill the device type and stream id to pass to SST driver */
-       retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
-       pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
-       if (retval < 0)
-               return retval;
-
-       switch (params->codec.id) {
-       case SND_AUDIOCODEC_MP3: {
-               str_params.codec = SST_CODEC_TYPE_MP3;
-               str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
-               str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
-               break;
-       }
-
-       case SND_AUDIOCODEC_AAC: {
-               str_params.codec = SST_CODEC_TYPE_AAC;
-               str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
-               str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
-               if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
-                       str_params.sparams.uc.aac_params.bs_format =
-                                                       AAC_BIT_STREAM_ADTS;
-               else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
-                       str_params.sparams.uc.aac_params.bs_format =
-                                                       AAC_BIT_STREAM_RAW;
-               else {
-                       pr_err("Undefined format%d\n", params->codec.format);
-                       return -EINVAL;
-               }
-               str_params.sparams.uc.aac_params.externalsr =
-                                               params->codec.sample_rate;
-               break;
-       }
-
-       default:
-               pr_err("codec not supported, id =%d\n", params->codec.id);
-               return -EINVAL;
-       }
-
-       str_params.aparams.ring_buf_info[0].addr  =
-                                       virt_to_phys(cstream->runtime->buffer);
-       str_params.aparams.ring_buf_info[0].size =
-                                       cstream->runtime->buffer_size;
-       str_params.aparams.sg_count = 1;
-       str_params.aparams.frag_size = cstream->runtime->fragment_size;
-
-       cb.param = cstream;
-       cb.compr_cb = sst_compr_fragment_elapsed;
-       cb.drain_cb_param = cstream;
-       cb.drain_notify = sst_drain_notify;
-
-       retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
-       if (retval < 0) {
-               pr_err("stream allocation failed %d\n", retval);
-               return retval;
-       }
-
-       stream->id = retval;
-       return 0;
-}
-
-static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
-{
-       struct sst_runtime_stream *stream = cstream->runtime->private_data;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               if (stream->compr_ops->stream_start)
-                       return stream->compr_ops->stream_start(sst->dev, stream->id);
-       case SNDRV_PCM_TRIGGER_STOP:
-               if (stream->compr_ops->stream_drop)
-                       return stream->compr_ops->stream_drop(sst->dev, stream->id);
-       case SND_COMPR_TRIGGER_DRAIN:
-               if (stream->compr_ops->stream_drain)
-                       return stream->compr_ops->stream_drain(sst->dev, stream->id);
-       case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
-               if (stream->compr_ops->stream_partial_drain)
-                       return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (stream->compr_ops->stream_pause)
-                       return stream->compr_ops->stream_pause(sst->dev, stream->id);
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               if (stream->compr_ops->stream_pause_release)
-                       return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
-                                       struct snd_compr_tstamp *tstamp)
-{
-       struct sst_runtime_stream *stream;
-
-       stream  = cstream->runtime->private_data;
-       stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
-       tstamp->byte_offset = tstamp->copied_total %
-                                (u32)cstream->runtime->buffer_size;
-       pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
-       return 0;
-}
-
-static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
-                                       size_t bytes)
-{
-       struct sst_runtime_stream *stream;
-
-       stream  = cstream->runtime->private_data;
-       stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
-       stream->bytes_written += bytes;
-
-       return 0;
-}
-
-static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
-                                       struct snd_compr_caps *caps)
-{
-       struct sst_runtime_stream *stream =
-               cstream->runtime->private_data;
-
-       return stream->compr_ops->get_caps(caps);
-}
-
-static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
-                                       struct snd_compr_codec_caps *codec)
-{
-       struct sst_runtime_stream *stream =
-               cstream->runtime->private_data;
-
-       return stream->compr_ops->get_codec_caps(codec);
-}
-
-static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
-                                       struct snd_compr_metadata *metadata)
-{
-       struct sst_runtime_stream *stream  =
-                cstream->runtime->private_data;
-
-       return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
-}
-
-struct snd_compr_ops sst_platform_compr_ops = {
-
-       .open = sst_platform_compr_open,
-       .free = sst_platform_compr_free,
-       .set_params = sst_platform_compr_set_params,
-       .set_metadata = sst_platform_compr_set_metadata,
-       .trigger = sst_platform_compr_trigger,
-       .pointer = sst_platform_compr_pointer,
-       .ack = sst_platform_compr_ack,
-       .get_caps = sst_platform_compr_get_caps,
-       .get_codec_caps = sst_platform_compr_get_codec_caps,
-};
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c
deleted file mode 100644 (file)
index 2fbaf2c..0000000
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- *  sst_mfld_platform.c - Intel MID Platform driver
- *
- *  Copyright (C) 2010-2014 Intel Corp
- *  Author: Vinod Koul <vinod.koul@intel.com>
- *  Author: Harsha Priya <priya.harsha@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <asm/platform_sst_audio.h>
-#include "sst-mfld-platform.h"
-#include "sst-atom-controls.h"
-
-struct sst_device *sst;
-static DEFINE_MUTEX(sst_lock);
-extern struct snd_compr_ops sst_platform_compr_ops;
-
-int sst_register_dsp(struct sst_device *dev)
-{
-       if (WARN_ON(!dev))
-               return -EINVAL;
-       if (!try_module_get(dev->dev->driver->owner))
-               return -ENODEV;
-       mutex_lock(&sst_lock);
-       if (sst) {
-               dev_err(dev->dev, "we already have a device %s\n", sst->name);
-               module_put(dev->dev->driver->owner);
-               mutex_unlock(&sst_lock);
-               return -EEXIST;
-       }
-       dev_dbg(dev->dev, "registering device %s\n", dev->name);
-       sst = dev;
-       mutex_unlock(&sst_lock);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(sst_register_dsp);
-
-int sst_unregister_dsp(struct sst_device *dev)
-{
-       if (WARN_ON(!dev))
-               return -EINVAL;
-       if (dev != sst)
-               return -EINVAL;
-
-       mutex_lock(&sst_lock);
-
-       if (!sst) {
-               mutex_unlock(&sst_lock);
-               return -EIO;
-       }
-
-       module_put(sst->dev->driver->owner);
-       dev_dbg(dev->dev, "unreg %s\n", sst->name);
-       sst = NULL;
-       mutex_unlock(&sst_lock);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(sst_unregister_dsp);
-
-static struct snd_pcm_hardware sst_platform_pcm_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED |
-                       SNDRV_PCM_INFO_DOUBLE |
-                       SNDRV_PCM_INFO_PAUSE |
-                       SNDRV_PCM_INFO_RESUME |
-                       SNDRV_PCM_INFO_MMAP|
-                       SNDRV_PCM_INFO_MMAP_VALID |
-                       SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                       SNDRV_PCM_INFO_SYNC_START),
-       .buffer_bytes_max = SST_MAX_BUFFER,
-       .period_bytes_min = SST_MIN_PERIOD_BYTES,
-       .period_bytes_max = SST_MAX_PERIOD_BYTES,
-       .periods_min = SST_MIN_PERIODS,
-       .periods_max = SST_MAX_PERIODS,
-       .fifo_size = SST_FIFO_SIZE,
-};
-
-static struct sst_dev_stream_map dpcm_strm_map[] = {
-       {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
-       {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
-       {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
-       {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
-};
-
-static int sst_media_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
-{
-
-       return sst_send_pipe_gains(dai, stream, mute);
-}
-
-/* helper functions */
-void sst_set_stream_status(struct sst_runtime_stream *stream,
-                                       int state)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&stream->status_lock, flags);
-       stream->stream_status = state;
-       spin_unlock_irqrestore(&stream->status_lock, flags);
-}
-
-static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
-{
-       int state;
-       unsigned long flags;
-
-       spin_lock_irqsave(&stream->status_lock, flags);
-       state = stream->stream_status;
-       spin_unlock_irqrestore(&stream->status_lock, flags);
-       return state;
-}
-
-static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
-                               struct snd_sst_alloc_params_ext *alloc_param)
-{
-       unsigned int channels;
-       snd_pcm_uframes_t period_size;
-       ssize_t periodbytes;
-       ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-       u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
-
-       channels = substream->runtime->channels;
-       period_size = substream->runtime->period_size;
-       periodbytes = samples_to_bytes(substream->runtime, period_size);
-       alloc_param->ring_buf_info[0].addr = buffer_addr;
-       alloc_param->ring_buf_info[0].size = buffer_bytes;
-       alloc_param->sg_count = 1;
-       alloc_param->reserved = 0;
-       alloc_param->frag_size = periodbytes * channels;
-
-}
-static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
-                               struct snd_sst_stream_params *param)
-{
-       param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
-       param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
-       param->uc.pcm_params.sfreq = substream->runtime->rate;
-
-       /* PCM stream via ALSA interface */
-       param->uc.pcm_params.use_offload_path = 0;
-       param->uc.pcm_params.reserved2 = 0;
-       memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
-
-}
-
-static int sst_get_stream_mapping(int dev, int sdev, int dir,
-       struct sst_dev_stream_map *map, int size)
-{
-       int i;
-
-       if (map == NULL)
-               return -EINVAL;
-
-
-       /* index 0 is not used in stream map */
-       for (i = 1; i < size; i++) {
-               if ((map[i].dev_num == dev) && (map[i].direction == dir))
-                       return i;
-       }
-       return 0;
-}
-
-int sst_fill_stream_params(void *substream,
-       const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
-{
-       int map_size;
-       int index;
-       struct sst_dev_stream_map *map;
-       struct snd_pcm_substream *pstream = NULL;
-       struct snd_compr_stream *cstream = NULL;
-
-       map = ctx->pdata->pdev_strm_map;
-       map_size = ctx->pdata->strm_map_size;
-
-       if (is_compress == true)
-               cstream = (struct snd_compr_stream *)substream;
-       else
-               pstream = (struct snd_pcm_substream *)substream;
-
-       str_params->stream_type = SST_STREAM_TYPE_MUSIC;
-
-       /* For pcm streams */
-       if (pstream) {
-               index = sst_get_stream_mapping(pstream->pcm->device,
-                                         pstream->number, pstream->stream,
-                                         map, map_size);
-               if (index <= 0)
-                       return -EINVAL;
-
-               str_params->stream_id = index;
-               str_params->device_type = map[index].device_id;
-               str_params->task = map[index].task_id;
-
-               str_params->ops = (u8)pstream->stream;
-       }
-
-       if (cstream) {
-               index = sst_get_stream_mapping(cstream->device->device,
-                                              0, cstream->direction,
-                                              map, map_size);
-               if (index <= 0)
-                       return -EINVAL;
-               str_params->stream_id = index;
-               str_params->device_type = map[index].device_id;
-               str_params->task = map[index].task_id;
-
-               str_params->ops = (u8)cstream->direction;
-       }
-       return 0;
-}
-
-static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       struct sst_runtime_stream *stream =
-                       substream->runtime->private_data;
-       struct snd_sst_stream_params param = {{{0,},},};
-       struct snd_sst_params str_params = {0};
-       struct snd_sst_alloc_params_ext alloc_params = {0};
-       int ret_val = 0;
-       struct sst_data *ctx = snd_soc_dai_get_drvdata(dai);
-
-       /* set codec params and inform SST driver the same */
-       sst_fill_pcm_params(substream, &param);
-       sst_fill_alloc_params(substream, &alloc_params);
-       substream->runtime->dma_area = substream->dma_buffer.area;
-       str_params.sparams = param;
-       str_params.aparams = alloc_params;
-       str_params.codec = SST_CODEC_TYPE_PCM;
-
-       /* fill the device type and stream id to pass to SST driver */
-       ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
-       if (ret_val < 0)
-               return ret_val;
-
-       stream->stream_info.str_id = str_params.stream_id;
-
-       ret_val = stream->ops->open(sst->dev, &str_params);
-       if (ret_val <= 0)
-               return ret_val;
-
-
-       return ret_val;
-}
-
-static void sst_period_elapsed(void *arg)
-{
-       struct snd_pcm_substream *substream = arg;
-       struct sst_runtime_stream *stream;
-       int status;
-
-       if (!substream || !substream->runtime)
-               return;
-       stream = substream->runtime->private_data;
-       if (!stream)
-               return;
-       status = sst_get_stream_status(stream);
-       if (status != SST_PLATFORM_RUNNING)
-               return;
-       snd_pcm_period_elapsed(substream);
-}
-
-static int sst_platform_init_stream(struct snd_pcm_substream *substream)
-{
-       struct sst_runtime_stream *stream =
-                       substream->runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       int ret_val;
-
-       dev_dbg(rtd->dev, "setting buffer ptr param\n");
-       sst_set_stream_status(stream, SST_PLATFORM_INIT);
-       stream->stream_info.period_elapsed = sst_period_elapsed;
-       stream->stream_info.arg = substream;
-       stream->stream_info.buffer_ptr = 0;
-       stream->stream_info.sfreq = substream->runtime->rate;
-       ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info);
-       if (ret_val)
-               dev_err(rtd->dev, "control_set ret error %d\n", ret_val);
-       return ret_val;
-
-}
-
-static int power_up_sst(struct sst_runtime_stream *stream)
-{
-       return stream->ops->power(sst->dev, true);
-}
-
-static void power_down_sst(struct sst_runtime_stream *stream)
-{
-       stream->ops->power(sst->dev, false);
-}
-
-static int sst_media_open(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       int ret_val = 0;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct sst_runtime_stream *stream;
-
-       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
-       if (!stream)
-               return -ENOMEM;
-       spin_lock_init(&stream->status_lock);
-
-       /* get the sst ops */
-       mutex_lock(&sst_lock);
-       if (!sst ||
-           !try_module_get(sst->dev->driver->owner)) {
-               dev_err(dai->dev, "no device available to run\n");
-               ret_val = -ENODEV;
-               goto out_ops;
-       }
-       stream->ops = sst->ops;
-       mutex_unlock(&sst_lock);
-
-       stream->stream_info.str_id = 0;
-
-       stream->stream_info.arg = substream;
-       /* allocate memory for SST API set */
-       runtime->private_data = stream;
-
-       ret_val = power_up_sst(stream);
-       if (ret_val < 0)
-               return ret_val;
-
-       /* Make sure, that the period size is always even */
-       snd_pcm_hw_constraint_step(substream->runtime, 0,
-                          SNDRV_PCM_HW_PARAM_PERIODS, 2);
-
-       return snd_pcm_hw_constraint_integer(runtime,
-                        SNDRV_PCM_HW_PARAM_PERIODS);
-out_ops:
-       kfree(stream);
-       mutex_unlock(&sst_lock);
-       return ret_val;
-}
-
-static void sst_media_close(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       struct sst_runtime_stream *stream;
-       int ret_val = 0, str_id;
-
-       stream = substream->runtime->private_data;
-       power_down_sst(stream);
-
-       str_id = stream->stream_info.str_id;
-       if (str_id)
-               ret_val = stream->ops->close(sst->dev, str_id);
-       module_put(sst->dev->driver->owner);
-       kfree(stream);
-}
-
-static inline unsigned int get_current_pipe_id(struct snd_soc_dai *dai,
-                                              struct snd_pcm_substream *substream)
-{
-       struct sst_data *sst = snd_soc_dai_get_drvdata(dai);
-       struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
-       struct sst_runtime_stream *stream =
-                       substream->runtime->private_data;
-       u32 str_id = stream->stream_info.str_id;
-       unsigned int pipe_id;
-
-       pipe_id = map[str_id].device_id;
-
-       dev_dbg(dai->dev, "got pipe_id = %#x for str_id = %d\n",
-                       pipe_id, str_id);
-       return pipe_id;
-}
-
-static int sst_media_prepare(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       struct sst_runtime_stream *stream;
-       int ret_val = 0, str_id;
-
-       stream = substream->runtime->private_data;
-       str_id = stream->stream_info.str_id;
-       if (stream->stream_info.str_id) {
-               ret_val = stream->ops->stream_drop(sst->dev, str_id);
-               return ret_val;
-       }
-
-       ret_val = sst_platform_alloc_stream(substream, dai);
-       if (ret_val <= 0)
-               return ret_val;
-       snprintf(substream->pcm->id, sizeof(substream->pcm->id),
-                       "%d", stream->stream_info.str_id);
-
-       ret_val = sst_platform_init_stream(substream);
-       if (ret_val)
-               return ret_val;
-       substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
-       return ret_val;
-}
-
-static int sst_media_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *dai)
-{
-       snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-       memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
-       return 0;
-}
-
-static int sst_media_hw_free(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
-static int sst_enable_ssp(struct snd_pcm_substream *substream,
-                       struct snd_soc_dai *dai)
-{
-       int ret = 0;
-
-       if (!dai->active) {
-               ret = sst_handle_vb_timer(dai, true);
-               if (ret)
-                       return ret;
-               ret = send_ssp_cmd(dai, dai->name, 1);
-       }
-       return ret;
-}
-
-static void sst_disable_ssp(struct snd_pcm_substream *substream,
-                       struct snd_soc_dai *dai)
-{
-       if (!dai->active) {
-               send_ssp_cmd(dai, dai->name, 0);
-               sst_handle_vb_timer(dai, false);
-       }
-}
-
-static struct snd_soc_dai_ops sst_media_dai_ops = {
-       .startup = sst_media_open,
-       .shutdown = sst_media_close,
-       .prepare = sst_media_prepare,
-       .hw_params = sst_media_hw_params,
-       .hw_free = sst_media_hw_free,
-       .mute_stream = sst_media_digital_mute,
-};
-
-static struct snd_soc_dai_ops sst_compr_dai_ops = {
-       .mute_stream = sst_media_digital_mute,
-};
-
-static struct snd_soc_dai_ops sst_be_dai_ops = {
-       .startup = sst_enable_ssp,
-       .shutdown = sst_disable_ssp,
-};
-
-static struct snd_soc_dai_driver sst_platform_dai[] = {
-{
-       .name = "media-cpu-dai",
-       .ops = &sst_media_dai_ops,
-       .playback = {
-               .stream_name = "Headset Playback",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .stream_name = "Headset Capture",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-},
-{
-       .name = "compress-cpu-dai",
-       .compress_dai = 1,
-       .ops = &sst_compr_dai_ops,
-       .playback = {
-               .stream_name = "Compress Playback",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-},
-/* BE CPU  Dais */
-{
-       .name = "ssp0-port",
-       .ops = &sst_be_dai_ops,
-       .playback = {
-               .stream_name = "ssp0 Tx",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .stream_name = "ssp0 Rx",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-},
-{
-       .name = "ssp1-port",
-       .ops = &sst_be_dai_ops,
-       .playback = {
-               .stream_name = "ssp1 Tx",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .stream_name = "ssp1 Rx",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-},
-{
-       .name = "ssp2-port",
-       .ops = &sst_be_dai_ops,
-       .playback = {
-               .stream_name = "ssp2 Tx",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .stream_name = "ssp2 Rx",
-               .channels_min = SST_STEREO,
-               .channels_max = SST_STEREO,
-               .rates = SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-},
-};
-
-static int sst_platform_open(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime;
-
-       if (substream->pcm->internal)
-               return 0;
-
-       runtime = substream->runtime;
-       runtime->hw = sst_platform_pcm_hw;
-       return 0;
-}
-
-static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
-                                       int cmd)
-{
-       int ret_val = 0, str_id;
-       struct sst_runtime_stream *stream;
-       int status;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
-       dev_dbg(rtd->dev, "sst_platform_pcm_trigger called\n");
-       if (substream->pcm->internal)
-               return 0;
-       stream = substream->runtime->private_data;
-       str_id = stream->stream_info.str_id;
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               dev_dbg(rtd->dev, "sst: Trigger Start\n");
-               status = SST_PLATFORM_RUNNING;
-               stream->stream_info.arg = substream;
-               ret_val = stream->ops->stream_start(sst->dev, str_id);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               dev_dbg(rtd->dev, "sst: in stop\n");
-               status = SST_PLATFORM_DROPPED;
-               ret_val = stream->ops->stream_drop(sst->dev, str_id);
-               break;
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-               dev_dbg(rtd->dev, "sst: in pause\n");
-               status = SST_PLATFORM_PAUSED;
-               ret_val = stream->ops->stream_pause(sst->dev, str_id);
-               break;
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-       case SNDRV_PCM_TRIGGER_RESUME:
-               dev_dbg(rtd->dev, "sst: in pause release\n");
-               status = SST_PLATFORM_RUNNING;
-               ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (!ret_val)
-               sst_set_stream_status(stream, status);
-
-       return ret_val;
-}
-
-
-static snd_pcm_uframes_t sst_platform_pcm_pointer
-                       (struct snd_pcm_substream *substream)
-{
-       struct sst_runtime_stream *stream;
-       int ret_val, status;
-       struct pcm_stream_info *str_info;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
-       stream = substream->runtime->private_data;
-       status = sst_get_stream_status(stream);
-       if (status == SST_PLATFORM_INIT)
-               return 0;
-       str_info = &stream->stream_info;
-       ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info);
-       if (ret_val) {
-               dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
-               return ret_val;
-       }
-       substream->runtime->delay = str_info->pcm_delay;
-       return str_info->buffer_ptr;
-}
-
-static struct snd_pcm_ops sst_platform_ops = {
-       .open = sst_platform_open,
-       .ioctl = snd_pcm_lib_ioctl,
-       .trigger = sst_platform_pcm_trigger,
-       .pointer = sst_platform_pcm_pointer,
-};
-
-static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_dai *dai = rtd->cpu_dai;
-       struct snd_pcm *pcm = rtd->pcm;
-       int retval = 0;
-
-       if (dai->driver->playback.channels_min ||
-                       dai->driver->capture.channels_min) {
-               retval =  snd_pcm_lib_preallocate_pages_for_all(pcm,
-                       SNDRV_DMA_TYPE_CONTINUOUS,
-                       snd_dma_continuous_data(GFP_DMA),
-                       SST_MIN_BUFFER, SST_MAX_BUFFER);
-               if (retval) {
-                       dev_err(rtd->dev, "dma buffer allocationf fail\n");
-                       return retval;
-               }
-       }
-       return retval;
-}
-
-static int sst_soc_probe(struct snd_soc_platform *platform)
-{
-       struct sst_data *drv = dev_get_drvdata(platform->dev);
-
-       drv->soc_card = platform->component.card;
-       return sst_dsp_init_v2_dpcm(platform);
-}
-
-static struct snd_soc_platform_driver sst_soc_platform_drv  = {
-       .probe          = sst_soc_probe,
-       .ops            = &sst_platform_ops,
-       .compr_ops      = &sst_platform_compr_ops,
-       .pcm_new        = sst_pcm_new,
-};
-
-static const struct snd_soc_component_driver sst_component = {
-       .name           = "sst",
-};
-
-
-static int sst_platform_probe(struct platform_device *pdev)
-{
-       struct sst_data *drv;
-       int ret;
-       struct sst_platform_data *pdata;
-
-       drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-       if (drv == NULL) {
-               return -ENOMEM;
-       }
-
-       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-       if (pdata == NULL) {
-               return -ENOMEM;
-       }
-
-       pdata->pdev_strm_map = dpcm_strm_map;
-       pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
-       drv->pdata = pdata;
-       drv->pdev = pdev;
-       mutex_init(&drv->lock);
-       dev_set_drvdata(&pdev->dev, drv);
-
-       ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
-       if (ret) {
-               dev_err(&pdev->dev, "registering soc platform failed\n");
-               return ret;
-       }
-
-       ret = snd_soc_register_component(&pdev->dev, &sst_component,
-                               sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
-       if (ret) {
-               dev_err(&pdev->dev, "registering cpu dais failed\n");
-               snd_soc_unregister_platform(&pdev->dev);
-       }
-       return ret;
-}
-
-static int sst_platform_remove(struct platform_device *pdev)
-{
-
-       snd_soc_unregister_component(&pdev->dev);
-       snd_soc_unregister_platform(&pdev->dev);
-       dev_dbg(&pdev->dev, "sst_platform_remove success\n");
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-
-static int sst_soc_prepare(struct device *dev)
-{
-       struct sst_data *drv = dev_get_drvdata(dev);
-       int i;
-
-       /* suspend all pcms first */
-       snd_soc_suspend(drv->soc_card->dev);
-       snd_soc_poweroff(drv->soc_card->dev);
-
-       /* set the SSPs to idle */
-       for (i = 0; i < drv->soc_card->num_rtd; i++) {
-               struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
-
-               if (dai->active) {
-                       send_ssp_cmd(dai, dai->name, 0);
-                       sst_handle_vb_timer(dai, false);
-               }
-       }
-
-       return 0;
-}
-
-static void sst_soc_complete(struct device *dev)
-{
-       struct sst_data *drv = dev_get_drvdata(dev);
-       int i;
-
-       /* restart SSPs */
-       for (i = 0; i < drv->soc_card->num_rtd; i++) {
-               struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
-
-               if (dai->active) {
-                       sst_handle_vb_timer(dai, true);
-                       send_ssp_cmd(dai, dai->name, 1);
-               }
-       }
-       snd_soc_resume(drv->soc_card->dev);
-}
-
-#else
-
-#define sst_soc_prepare NULL
-#define sst_soc_complete NULL
-
-#endif
-
-
-static const struct dev_pm_ops sst_platform_pm = {
-       .prepare        = sst_soc_prepare,
-       .complete       = sst_soc_complete,
-};
-
-static struct platform_driver sst_platform_driver = {
-       .driver         = {
-               .name           = "sst-mfld-platform",
-               .pm             = &sst_platform_pm,
-       },
-       .probe          = sst_platform_probe,
-       .remove         = sst_platform_remove,
-};
-
-module_platform_driver(sst_platform_driver);
-
-MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
-MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:sst-mfld-platform");
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h
deleted file mode 100644 (file)
index 9094314..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *  sst_mfld_platform.h - Intel MID Platform driver header file
- *
- *  Copyright (C) 2010 Intel Corp
- *  Author: Vinod Koul <vinod.koul@intel.com>
- *  Author: Harsha Priya <priya.harsha@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#ifndef __SST_PLATFORMDRV_H__
-#define __SST_PLATFORMDRV_H__
-
-#include "sst-mfld-dsp.h"
-
-extern struct sst_device *sst;
-
-#define SST_MONO               1
-#define SST_STEREO             2
-#define SST_MAX_CAP            5
-
-#define SST_MAX_BUFFER         (800*1024)
-#define SST_MIN_BUFFER         (800*1024)
-#define SST_MIN_PERIOD_BYTES   32
-#define SST_MAX_PERIOD_BYTES   SST_MAX_BUFFER
-#define SST_MIN_PERIODS                2
-#define SST_MAX_PERIODS                (1024*2)
-#define SST_FIFO_SIZE          0
-
-struct pcm_stream_info {
-       int str_id;
-       void *arg;
-       void (*period_elapsed) (void *arg);
-       unsigned long long buffer_ptr;
-       unsigned long long pcm_delay;
-       int sfreq;
-};
-
-enum sst_drv_status {
-       SST_PLATFORM_INIT = 1,
-       SST_PLATFORM_STARTED,
-       SST_PLATFORM_RUNNING,
-       SST_PLATFORM_PAUSED,
-       SST_PLATFORM_DROPPED,
-};
-
-enum sst_stream_ops {
-       STREAM_OPS_PLAYBACK = 0,
-       STREAM_OPS_CAPTURE,
-};
-
-enum sst_audio_device_type {
-       SND_SST_DEVICE_HEADSET = 1,
-       SND_SST_DEVICE_IHF,
-       SND_SST_DEVICE_VIBRA,
-       SND_SST_DEVICE_HAPTIC,
-       SND_SST_DEVICE_CAPTURE,
-       SND_SST_DEVICE_COMPRESS,
-};
-
-/* PCM Parameters */
-struct sst_pcm_params {
-       u16 codec;      /* codec type */
-       u8 num_chan;    /* 1=Mono, 2=Stereo */
-       u8 pcm_wd_sz;   /* 16/24 - bit*/
-       u32 reserved;   /* Bitrate in bits per second */
-       u32 sfreq;      /* Sampling rate in Hz */
-       u32 ring_buffer_size;
-       u32 period_count;       /* period elapsed in samples*/
-       u32 ring_buffer_addr;
-};
-
-struct sst_stream_params {
-       u32 result;
-       u32 stream_id;
-       u8 codec;
-       u8 ops;
-       u8 stream_type;
-       u8 device_type;
-       struct sst_pcm_params sparams;
-};
-
-struct sst_compress_cb {
-       void *param;
-       void (*compr_cb)(void *param);
-       void *drain_cb_param;
-       void (*drain_notify)(void *param);
-};
-
-struct compress_sst_ops {
-       const char *name;
-       int (*open)(struct device *dev,
-               struct snd_sst_params *str_params, struct sst_compress_cb *cb);
-       int (*stream_start)(struct device *dev, unsigned int str_id);
-       int (*stream_drop)(struct device *dev, unsigned int str_id);
-       int (*stream_drain)(struct device *dev, unsigned int str_id);
-       int (*stream_partial_drain)(struct device *dev, unsigned int str_id);
-       int (*stream_pause)(struct device *dev, unsigned int str_id);
-       int (*stream_pause_release)(struct device *dev, unsigned int str_id);
-
-       int (*tstamp)(struct device *dev, unsigned int str_id,
-                       struct snd_compr_tstamp *tstamp);
-       int (*ack)(struct device *dev, unsigned int str_id,
-                       unsigned long bytes);
-       int (*close)(struct device *dev, unsigned int str_id);
-       int (*get_caps)(struct snd_compr_caps *caps);
-       int (*get_codec_caps)(struct snd_compr_codec_caps *codec);
-       int (*set_metadata)(struct device *dev, unsigned int str_id,
-                       struct snd_compr_metadata *mdata);
-       int (*power)(struct device *dev, bool state);
-};
-
-struct sst_ops {
-       int (*open)(struct device *dev, struct snd_sst_params *str_param);
-       int (*stream_init)(struct device *dev, struct pcm_stream_info *str_info);
-       int (*stream_start)(struct device *dev, int str_id);
-       int (*stream_drop)(struct device *dev, int str_id);
-       int (*stream_pause)(struct device *dev, int str_id);
-       int (*stream_pause_release)(struct device *dev, int str_id);
-       int (*stream_read_tstamp)(struct device *dev, struct pcm_stream_info *str_info);
-       int (*send_byte_stream)(struct device *dev, struct snd_sst_bytes_v2 *bytes);
-       int (*close)(struct device *dev, unsigned int str_id);
-       int (*power)(struct device *dev, bool state);
-};
-
-struct sst_runtime_stream {
-       int     stream_status;
-       unsigned int id;
-       size_t bytes_written;
-       struct pcm_stream_info stream_info;
-       struct sst_ops *ops;
-       struct compress_sst_ops *compr_ops;
-       spinlock_t      status_lock;
-};
-
-struct sst_device {
-       char *name;
-       struct device *dev;
-       struct sst_ops *ops;
-       struct platform_device *pdev;
-       struct compress_sst_ops *compr_ops;
-};
-
-struct sst_data;
-
-int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform);
-int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute);
-int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable);
-int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable);
-
-void sst_set_stream_status(struct sst_runtime_stream *stream, int state);
-int sst_fill_stream_params(void *substream, const struct sst_data *ctx,
-                          struct snd_sst_params *str_params, bool is_compress);
-
-struct sst_algo_int_control_v2 {
-       struct soc_mixer_control mc;
-       u16 module_id; /* module identifieer */
-       u16 pipe_id; /* location info: pipe_id + instance_id */
-       u16 instance_id;
-       unsigned int value; /* Value received is stored here */
-};
-struct sst_data {
-       struct platform_device *pdev;
-       struct sst_platform_data *pdata;
-       struct snd_sst_bytes_v2 *byte_stream;
-       struct mutex lock;
-       struct snd_soc_card *soc_card;
-};
-int sst_register_dsp(struct sst_device *sst);
-int sst_unregister_dsp(struct sst_device *sst);
-#endif
diff --git a/sound/soc/intel/sst/Makefile b/sound/soc/intel/sst/Makefile
deleted file mode 100644 (file)
index fd21726..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o
-snd-intel-sst-pci-objs += sst_pci.o
-snd-intel-sst-acpi-objs += sst_acpi.o
-
-obj-$(CONFIG_SND_SST_IPC) += snd-intel-sst-core.o
-obj-$(CONFIG_SND_SST_IPC_PCI) += snd-intel-sst-pci.o
-obj-$(CONFIG_SND_SST_IPC_ACPI) += snd-intel-sst-acpi.o
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c
deleted file mode 100644 (file)
index 26b1e31..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- *  sst.c - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14      Intel Corp
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
-#include <linux/async.h>
-#include <linux/acpi.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-#include "../common/sst-dsp.h"
-
-MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
-MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine Driver");
-MODULE_LICENSE("GPL v2");
-
-static inline bool sst_is_process_reply(u32 msg_id)
-{
-       return ((msg_id & PROCESS_MSG) ? true : false);
-}
-
-static inline bool sst_validate_mailbox_size(unsigned int size)
-{
-       return ((size <= SST_MAILBOX_SIZE) ? true : false);
-}
-
-static irqreturn_t intel_sst_interrupt_mrfld(int irq, void *context)
-{
-       union interrupt_reg_mrfld isr;
-       union ipc_header_mrfld header;
-       union sst_imr_reg_mrfld imr;
-       struct ipc_post *msg = NULL;
-       unsigned int size = 0;
-       struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
-       irqreturn_t retval = IRQ_HANDLED;
-
-       /* Interrupt arrived, check src */
-       isr.full = sst_shim_read64(drv->shim, SST_ISRX);
-
-       if (isr.part.done_interrupt) {
-               /* Clear done bit */
-               spin_lock(&drv->ipc_spin_lock);
-               header.full = sst_shim_read64(drv->shim,
-                                       drv->ipc_reg.ipcx);
-               header.p.header_high.part.done = 0;
-               sst_shim_write64(drv->shim, drv->ipc_reg.ipcx, header.full);
-
-               /* write 1 to clear status register */;
-               isr.part.done_interrupt = 1;
-               sst_shim_write64(drv->shim, SST_ISRX, isr.full);
-               spin_unlock(&drv->ipc_spin_lock);
-
-               /* we can send more messages to DSP so trigger work */
-               queue_work(drv->post_msg_wq, &drv->ipc_post_msg_wq);
-               retval = IRQ_HANDLED;
-       }
-
-       if (isr.part.busy_interrupt) {
-               /* message from dsp so copy that */
-               spin_lock(&drv->ipc_spin_lock);
-               imr.full = sst_shim_read64(drv->shim, SST_IMRX);
-               imr.part.busy_interrupt = 1;
-               sst_shim_write64(drv->shim, SST_IMRX, imr.full);
-               spin_unlock(&drv->ipc_spin_lock);
-               header.full =  sst_shim_read64(drv->shim, drv->ipc_reg.ipcd);
-
-               if (sst_create_ipc_msg(&msg, header.p.header_high.part.large)) {
-                       drv->ops->clear_interrupt(drv);
-                       return IRQ_HANDLED;
-               }
-
-               if (header.p.header_high.part.large) {
-                       size = header.p.header_low_payload;
-                       if (sst_validate_mailbox_size(size)) {
-                               memcpy_fromio(msg->mailbox_data,
-                                       drv->mailbox + drv->mailbox_recv_offset, size);
-                       } else {
-                               dev_err(drv->dev,
-                                       "Mailbox not copied, payload size is: %u\n", size);
-                               header.p.header_low_payload = 0;
-                       }
-               }
-
-               msg->mrfld_header = header;
-               msg->is_process_reply =
-                       sst_is_process_reply(header.p.header_high.part.msg_id);
-               spin_lock(&drv->rx_msg_lock);
-               list_add_tail(&msg->node, &drv->rx_list);
-               spin_unlock(&drv->rx_msg_lock);
-               drv->ops->clear_interrupt(drv);
-               retval = IRQ_WAKE_THREAD;
-       }
-       return retval;
-}
-
-static irqreturn_t intel_sst_irq_thread_mrfld(int irq, void *context)
-{
-       struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
-       struct ipc_post *__msg, *msg = NULL;
-       unsigned long irq_flags;
-
-       spin_lock_irqsave(&drv->rx_msg_lock, irq_flags);
-       if (list_empty(&drv->rx_list)) {
-               spin_unlock_irqrestore(&drv->rx_msg_lock, irq_flags);
-               return IRQ_HANDLED;
-       }
-
-       list_for_each_entry_safe(msg, __msg, &drv->rx_list, node) {
-               list_del(&msg->node);
-               spin_unlock_irqrestore(&drv->rx_msg_lock, irq_flags);
-               if (msg->is_process_reply)
-                       drv->ops->process_message(msg);
-               else
-                       drv->ops->process_reply(drv, msg);
-
-               if (msg->is_large)
-                       kfree(msg->mailbox_data);
-               kfree(msg);
-               spin_lock_irqsave(&drv->rx_msg_lock, irq_flags);
-       }
-       spin_unlock_irqrestore(&drv->rx_msg_lock, irq_flags);
-       return IRQ_HANDLED;
-}
-
-static int sst_save_dsp_context_v2(struct intel_sst_drv *sst)
-{
-       int ret = 0;
-
-       ret = sst_prepare_and_post_msg(sst, SST_TASK_ID_MEDIA, IPC_CMD,
-                       IPC_PREP_D3, PIPE_RSVD, 0, NULL, NULL,
-                       true, true, false, true);
-
-       if (ret < 0) {
-               dev_err(sst->dev, "not suspending FW!!, Err: %d\n", ret);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-
-static struct intel_sst_ops mrfld_ops = {
-       .interrupt = intel_sst_interrupt_mrfld,
-       .irq_thread = intel_sst_irq_thread_mrfld,
-       .clear_interrupt = intel_sst_clear_intr_mrfld,
-       .start = sst_start_mrfld,
-       .reset = intel_sst_reset_dsp_mrfld,
-       .post_message = sst_post_message_mrfld,
-       .process_reply = sst_process_reply_mrfld,
-       .save_dsp_context =  sst_save_dsp_context_v2,
-       .alloc_stream = sst_alloc_stream_mrfld,
-       .post_download = sst_post_download_mrfld,
-};
-
-int sst_driver_ops(struct intel_sst_drv *sst)
-{
-
-       switch (sst->dev_id) {
-       case SST_MRFLD_PCI_ID:
-       case SST_BYT_ACPI_ID:
-       case SST_CHV_ACPI_ID:
-               sst->tstamp = SST_TIME_STAMP_MRFLD;
-               sst->ops = &mrfld_ops;
-               return 0;
-
-       default:
-               dev_err(sst->dev,
-                       "SST Driver capablities missing for dev_id: %x", sst->dev_id);
-               return -EINVAL;
-       };
-}
-
-void sst_process_pending_msg(struct work_struct *work)
-{
-       struct intel_sst_drv *ctx = container_of(work,
-                       struct intel_sst_drv, ipc_post_msg_wq);
-
-       ctx->ops->post_message(ctx, NULL, false);
-}
-
-static int sst_workqueue_init(struct intel_sst_drv *ctx)
-{
-       INIT_LIST_HEAD(&ctx->memcpy_list);
-       INIT_LIST_HEAD(&ctx->rx_list);
-       INIT_LIST_HEAD(&ctx->ipc_dispatch_list);
-       INIT_LIST_HEAD(&ctx->block_list);
-       INIT_WORK(&ctx->ipc_post_msg_wq, sst_process_pending_msg);
-       init_waitqueue_head(&ctx->wait_queue);
-
-       ctx->post_msg_wq =
-               create_singlethread_workqueue("sst_post_msg_wq");
-       if (!ctx->post_msg_wq)
-               return -EBUSY;
-       return 0;
-}
-
-static void sst_init_locks(struct intel_sst_drv *ctx)
-{
-       mutex_init(&ctx->sst_lock);
-       spin_lock_init(&ctx->rx_msg_lock);
-       spin_lock_init(&ctx->ipc_spin_lock);
-       spin_lock_init(&ctx->block_lock);
-}
-
-int sst_alloc_drv_context(struct intel_sst_drv **ctx,
-               struct device *dev, unsigned int dev_id)
-{
-       *ctx = devm_kzalloc(dev, sizeof(struct intel_sst_drv), GFP_KERNEL);
-       if (!(*ctx))
-               return -ENOMEM;
-
-       (*ctx)->dev = dev;
-       (*ctx)->dev_id = dev_id;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(sst_alloc_drv_context);
-
-int sst_context_init(struct intel_sst_drv *ctx)
-{
-       int ret = 0, i;
-
-       if (!ctx->pdata)
-               return -EINVAL;
-
-       if (!ctx->pdata->probe_data)
-               return -EINVAL;
-
-       memcpy(&ctx->info, ctx->pdata->probe_data, sizeof(ctx->info));
-
-       ret = sst_driver_ops(ctx);
-       if (ret != 0)
-               return -EINVAL;
-
-       sst_init_locks(ctx);
-       sst_set_fw_state_locked(ctx, SST_RESET);
-
-       /* pvt_id 0 reserved for async messages */
-       ctx->pvt_id = 1;
-       ctx->stream_cnt = 0;
-       ctx->fw_in_mem = NULL;
-       /* we use memcpy, so set to 0 */
-       ctx->use_dma = 0;
-       ctx->use_lli = 0;
-
-       if (sst_workqueue_init(ctx))
-               return -EINVAL;
-
-       ctx->mailbox_recv_offset = ctx->pdata->ipc_info->mbox_recv_off;
-       ctx->ipc_reg.ipcx = SST_IPCX + ctx->pdata->ipc_info->ipc_offset;
-       ctx->ipc_reg.ipcd = SST_IPCD + ctx->pdata->ipc_info->ipc_offset;
-
-       dev_info(ctx->dev, "Got drv data max stream %d\n",
-                               ctx->info.max_streams);
-
-       for (i = 1; i <= ctx->info.max_streams; i++) {
-               struct stream_info *stream = &ctx->streams[i];
-
-               memset(stream, 0, sizeof(*stream));
-               stream->pipe_id = PIPE_RSVD;
-               mutex_init(&stream->lock);
-       }
-
-       /* Register the ISR */
-       ret = devm_request_threaded_irq(ctx->dev, ctx->irq_num, ctx->ops->interrupt,
-                                       ctx->ops->irq_thread, 0, SST_DRV_NAME,
-                                       ctx);
-       if (ret)
-               goto do_free_mem;
-
-       dev_dbg(ctx->dev, "Registered IRQ %#x\n", ctx->irq_num);
-
-       /* default intr are unmasked so set this as masked */
-       sst_shim_write64(ctx->shim, SST_IMRX, 0xFFFF0038);
-
-       ctx->qos = devm_kzalloc(ctx->dev,
-               sizeof(struct pm_qos_request), GFP_KERNEL);
-       if (!ctx->qos) {
-               ret = -ENOMEM;
-               goto do_free_mem;
-       }
-       pm_qos_add_request(ctx->qos, PM_QOS_CPU_DMA_LATENCY,
-                               PM_QOS_DEFAULT_VALUE);
-
-       dev_dbg(ctx->dev, "Requesting FW %s now...\n", ctx->firmware_name);
-       ret = request_firmware_nowait(THIS_MODULE, true, ctx->firmware_name,
-                                     ctx->dev, GFP_KERNEL, ctx, sst_firmware_load_cb);
-       if (ret) {
-               dev_err(ctx->dev, "Firmware download failed:%d\n", ret);
-               goto do_free_mem;
-       }
-       sst_register(ctx->dev);
-       return 0;
-
-do_free_mem:
-       destroy_workqueue(ctx->post_msg_wq);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(sst_context_init);
-
-void sst_context_cleanup(struct intel_sst_drv *ctx)
-{
-       pm_runtime_get_noresume(ctx->dev);
-       pm_runtime_disable(ctx->dev);
-       sst_unregister(ctx->dev);
-       sst_set_fw_state_locked(ctx, SST_SHUTDOWN);
-       flush_scheduled_work();
-       destroy_workqueue(ctx->post_msg_wq);
-       pm_qos_remove_request(ctx->qos);
-       kfree(ctx->fw_sg_list.src);
-       kfree(ctx->fw_sg_list.dst);
-       ctx->fw_sg_list.list_len = 0;
-       kfree(ctx->fw_in_mem);
-       ctx->fw_in_mem = NULL;
-       sst_memcpy_free_resources(ctx);
-       ctx = NULL;
-}
-EXPORT_SYMBOL_GPL(sst_context_cleanup);
-
-static inline void sst_save_shim64(struct intel_sst_drv *ctx,
-                           void __iomem *shim,
-                           struct sst_shim_regs64 *shim_regs)
-{
-       unsigned long irq_flags;
-
-       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
-
-       shim_regs->imrx = sst_shim_read64(shim, SST_IMRX);
-       shim_regs->csr = sst_shim_read64(shim, SST_CSR);
-
-
-       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
-}
-
-static inline void sst_restore_shim64(struct intel_sst_drv *ctx,
-                                     void __iomem *shim,
-                                     struct sst_shim_regs64 *shim_regs)
-{
-       unsigned long irq_flags;
-
-       /*
-        * we only need to restore IMRX for this case, rest will be
-        * initialize by FW or driver when firmware is loaded
-        */
-       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
-       sst_shim_write64(shim, SST_IMRX, shim_regs->imrx),
-       sst_shim_write64(shim, SST_CSR, shim_regs->csr),
-       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
-}
-
-void sst_configure_runtime_pm(struct intel_sst_drv *ctx)
-{
-       pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY);
-       pm_runtime_use_autosuspend(ctx->dev);
-       /*
-        * For acpi devices, the actual physical device state is
-        * initially active. So change the state to active before
-        * enabling the pm
-        */
-
-       if (!acpi_disabled)
-               pm_runtime_set_active(ctx->dev);
-
-       pm_runtime_enable(ctx->dev);
-
-       if (acpi_disabled)
-               pm_runtime_set_active(ctx->dev);
-       else
-               pm_runtime_put_noidle(ctx->dev);
-
-       sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
-}
-EXPORT_SYMBOL_GPL(sst_configure_runtime_pm);
-
-static int intel_sst_runtime_suspend(struct device *dev)
-{
-       int ret = 0;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (ctx->sst_state == SST_RESET) {
-               dev_dbg(dev, "LPE is already in RESET state, No action\n");
-               return 0;
-       }
-       /* save fw context */
-       if (ctx->ops->save_dsp_context(ctx))
-               return -EBUSY;
-
-       /* Move the SST state to Reset */
-       sst_set_fw_state_locked(ctx, SST_RESET);
-
-       synchronize_irq(ctx->irq_num);
-       flush_workqueue(ctx->post_msg_wq);
-
-       ctx->ops->reset(ctx);
-       /* save the shim registers because PMC doesn't save state */
-       sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
-
-       return ret;
-}
-
-static int intel_sst_suspend(struct device *dev)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-       struct sst_fw_save *fw_save;
-       int i, ret = 0;
-
-       /* check first if we are already in SW reset */
-       if (ctx->sst_state == SST_RESET)
-               return 0;
-
-       /*
-        * check if any stream is active and running
-        * they should already by suspend by soc_suspend
-        */
-       for (i = 1; i <= ctx->info.max_streams; i++) {
-               struct stream_info *stream = &ctx->streams[i];
-
-               if (stream->status == STREAM_RUNNING) {
-                       dev_err(dev, "stream %d is running, cant susupend, abort\n", i);
-                       return -EBUSY;
-               }
-       }
-       synchronize_irq(ctx->irq_num);
-       flush_workqueue(ctx->post_msg_wq);
-
-       /* Move the SST state to Reset */
-       sst_set_fw_state_locked(ctx, SST_RESET);
-
-       /* tell DSP we are suspending */
-       if (ctx->ops->save_dsp_context(ctx))
-               return -EBUSY;
-
-       /* save the memories */
-       fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
-       if (!fw_save)
-               return -ENOMEM;
-       fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
-       if (!fw_save->iram) {
-               ret = -ENOMEM;
-               goto iram;
-       }
-       fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
-       if (!fw_save->dram) {
-               ret = -ENOMEM;
-               goto dram;
-       }
-       fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
-       if (!fw_save->sram) {
-               ret = -ENOMEM;
-               goto sram;
-       }
-
-       fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
-       if (!fw_save->ddr) {
-               ret = -ENOMEM;
-               goto ddr;
-       }
-
-       memcpy32_fromio(fw_save->iram, ctx->iram, ctx->iram_end - ctx->iram_base);
-       memcpy32_fromio(fw_save->dram, ctx->dram, ctx->dram_end - ctx->dram_base);
-       memcpy32_fromio(fw_save->sram, ctx->mailbox, SST_MAILBOX_SIZE);
-       memcpy32_fromio(fw_save->ddr, ctx->ddr, ctx->ddr_end - ctx->ddr_base);
-
-       ctx->fw_save = fw_save;
-       ctx->ops->reset(ctx);
-       return 0;
-ddr:
-       kfree(fw_save->sram);
-sram:
-       kfree(fw_save->dram);
-dram:
-       kfree(fw_save->iram);
-iram:
-       kfree(fw_save);
-       return ret;
-}
-
-static int intel_sst_resume(struct device *dev)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-       struct sst_fw_save *fw_save = ctx->fw_save;
-       int ret = 0;
-       struct sst_block *block;
-
-       if (!fw_save)
-               return 0;
-
-       sst_set_fw_state_locked(ctx, SST_FW_LOADING);
-
-       /* we have to restore the memory saved */
-       ctx->ops->reset(ctx);
-
-       ctx->fw_save = NULL;
-
-       memcpy32_toio(ctx->iram, fw_save->iram, ctx->iram_end - ctx->iram_base);
-       memcpy32_toio(ctx->dram, fw_save->dram, ctx->dram_end - ctx->dram_base);
-       memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
-       memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
-
-       kfree(fw_save->sram);
-       kfree(fw_save->dram);
-       kfree(fw_save->iram);
-       kfree(fw_save->ddr);
-       kfree(fw_save);
-
-       block = sst_create_block(ctx, 0, FW_DWNL_ID);
-       if (block == NULL)
-               return -ENOMEM;
-
-
-       /* start and wait for ack */
-       ctx->ops->start(ctx);
-       ret = sst_wait_timeout(ctx, block);
-       if (ret) {
-               dev_err(ctx->dev, "fw download failed %d\n", ret);
-               /* FW download failed due to timeout */
-               ret = -EBUSY;
-
-       } else {
-               sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
-       }
-
-       sst_free_block(ctx, block);
-       return ret;
-}
-
-const struct dev_pm_ops intel_sst_pm = {
-       .suspend = intel_sst_suspend,
-       .resume = intel_sst_resume,
-       .runtime_suspend = intel_sst_runtime_suspend,
-};
-EXPORT_SYMBOL_GPL(intel_sst_pm);
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/sst/sst.h
deleted file mode 100644 (file)
index 3f49386..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- *  sst.h - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14 Intel Corporation
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  Common private declarations for SST
- */
-#ifndef __SST_H__
-#define __SST_H__
-
-#include <linux/firmware.h>
-
-/* driver names */
-#define SST_DRV_NAME "intel_sst_driver"
-#define SST_MRFLD_PCI_ID 0x119A
-#define SST_BYT_ACPI_ID        0x80860F28
-#define SST_CHV_ACPI_ID        0x808622A8
-
-#define SST_SUSPEND_DELAY 2000
-#define FW_CONTEXT_MEM (64*1024)
-#define SST_ICCM_BOUNDARY 4
-#define SST_CONFIG_SSP_SIGN 0x7ffe8001
-
-#define MRFLD_FW_VIRTUAL_BASE 0xC0000000
-#define MRFLD_FW_DDR_BASE_OFFSET 0x0
-#define MRFLD_FW_FEATURE_BASE_OFFSET 0x4
-#define MRFLD_FW_BSS_RESET_BIT 0
-
-extern const struct dev_pm_ops intel_sst_pm;
-enum sst_states {
-       SST_FW_LOADING = 1,
-       SST_FW_RUNNING,
-       SST_RESET,
-       SST_SHUTDOWN,
-};
-
-enum sst_algo_ops {
-       SST_SET_ALGO = 0,
-       SST_GET_ALGO = 1,
-};
-
-#define SST_BLOCK_TIMEOUT      1000
-
-#define FW_SIGNATURE_SIZE      4
-#define FW_NAME_SIZE           32
-
-/* stream states */
-enum sst_stream_states {
-       STREAM_UN_INIT  = 0,    /* Freed/Not used stream */
-       STREAM_RUNNING  = 1,    /* Running */
-       STREAM_PAUSED   = 2,    /* Paused stream */
-       STREAM_DECODE   = 3,    /* stream is in decoding only state */
-       STREAM_INIT     = 4,    /* stream init, waiting for data */
-       STREAM_RESET    = 5,    /* force reset on recovery */
-};
-
-enum sst_ram_type {
-       SST_IRAM        = 1,
-       SST_DRAM        = 2,
-       SST_DDR = 5,
-       SST_CUSTOM_INFO = 7,    /* consists of FW binary information */
-};
-
-/* SST shim registers to structure mapping */
-union interrupt_reg {
-       struct {
-               u64 done_interrupt:1;
-               u64 busy_interrupt:1;
-               u64 rsvd:62;
-       } part;
-       u64 full;
-};
-
-union sst_pisr_reg {
-       struct {
-               u32 pssp0:1;
-               u32 pssp1:1;
-               u32 rsvd0:3;
-               u32 dmac:1;
-               u32 rsvd1:26;
-       } part;
-       u32 full;
-};
-
-union sst_pimr_reg {
-       struct {
-               u32 ssp0:1;
-               u32 ssp1:1;
-               u32 rsvd0:3;
-               u32 dmac:1;
-               u32 rsvd1:10;
-               u32 ssp0_sc:1;
-               u32 ssp1_sc:1;
-               u32 rsvd2:3;
-               u32 dmac_sc:1;
-               u32 rsvd3:10;
-       } part;
-       u32 full;
-};
-
-union config_status_reg_mrfld {
-       struct {
-               u64 lpe_reset:1;
-               u64 lpe_reset_vector:1;
-               u64 runstall:1;
-               u64 pwaitmode:1;
-               u64 clk_sel:3;
-               u64 rsvd2:1;
-               u64 sst_clk:3;
-               u64 xt_snoop:1;
-               u64 rsvd3:4;
-               u64 clk_sel1:6;
-               u64 clk_enable:3;
-               u64 rsvd4:6;
-               u64 slim0baseclk:1;
-               u64 rsvd:32;
-       } part;
-       u64 full;
-};
-
-union interrupt_reg_mrfld {
-       struct {
-               u64 done_interrupt:1;
-               u64 busy_interrupt:1;
-               u64 rsvd:62;
-       } part;
-       u64 full;
-};
-
-union sst_imr_reg_mrfld {
-       struct {
-               u64 done_interrupt:1;
-               u64 busy_interrupt:1;
-               u64 rsvd:62;
-       } part;
-       u64 full;
-};
-
-/**
- * struct sst_block - This structure is used to block a user/fw data call to another
- * fw/user call
- *
- * @condition: condition for blocking check
- * @ret_code: ret code when block is released
- * @data: data ptr
- * @size: size of data
- * @on: block condition
- * @msg_id: msg_id = msgid in mfld/ctp, mrfld = NULL
- * @drv_id: str_id in mfld/ctp, = drv_id in mrfld
- * @node: list head node
- */
-struct sst_block {
-       bool    condition;
-       int     ret_code;
-       void    *data;
-       u32     size;
-       bool    on;
-       u32     msg_id;
-       u32     drv_id;
-       struct list_head node;
-};
-
-/**
- * struct stream_info - structure that holds the stream information
- *
- * @status : stream current state
- * @prev : stream prev state
- * @ops : stream operation pb/cp/drm...
- * @bufs: stream buffer list
- * @lock : stream mutex for protecting state
- * @pcm_substream : PCM substream
- * @period_elapsed : PCM period elapsed callback
- * @sfreq : stream sampling freq
- * @str_type : stream type
- * @cumm_bytes : cummulative bytes decoded
- * @str_type : stream type
- * @src : stream source
- */
-struct stream_info {
-       unsigned int            status;
-       unsigned int            prev;
-       unsigned int            ops;
-       struct mutex            lock;
-
-       void                    *pcm_substream;
-       void (*period_elapsed)(void *pcm_substream);
-
-       unsigned int            sfreq;
-       u32                     cumm_bytes;
-
-       void                    *compr_cb_param;
-       void (*compr_cb)(void *compr_cb_param);
-
-       void                    *drain_cb_param;
-       void (*drain_notify)(void *drain_cb_param);
-
-       unsigned int            num_ch;
-       unsigned int            pipe_id;
-       unsigned int            str_id;
-       unsigned int            task_id;
-};
-
-#define SST_FW_SIGN "$SST"
-#define SST_FW_LIB_SIGN "$LIB"
-
-/**
- * struct sst_fw_header - FW file headers
- *
- * @signature : FW signature
- * @file_size: size of fw image
- * @modules : # of modules
- * @file_format : version of header format
- * @reserved : reserved fields
- */
-struct sst_fw_header {
-       unsigned char signature[FW_SIGNATURE_SIZE];
-       u32 file_size;
-       u32 modules;
-       u32 file_format;
-       u32 reserved[4];
-};
-
-/**
- * struct fw_module_header - module header in FW
- *
- * @signature: module signature
- * @mod_size: size of module
- * @blocks: block count
- * @type: block type
- * @entry_point: module netry point
- */
-struct fw_module_header {
-       unsigned char signature[FW_SIGNATURE_SIZE];
-       u32 mod_size;
-       u32 blocks;
-       u32 type;
-       u32 entry_point;
-};
-
-/**
- * struct fw_block_info - block header for FW
- *
- * @type: block ram type I/D
- * @size: size of block
- * @ram_offset: offset in ram
- */
-struct fw_block_info {
-       enum sst_ram_type       type;
-       u32                     size;
-       u32                     ram_offset;
-       u32                     rsvd;
-};
-
-struct sst_runtime_param {
-       struct snd_sst_runtime_params param;
-};
-
-struct sst_sg_list {
-       struct scatterlist *src;
-       struct scatterlist *dst;
-       int list_len;
-       unsigned int sg_idx;
-};
-
-struct sst_memcpy_list {
-       struct list_head memcpylist;
-       void *dstn;
-       const void *src;
-       u32 size;
-       bool is_io;
-};
-
-/*Firmware Module Information*/
-enum sst_lib_dwnld_status {
-       SST_LIB_NOT_FOUND = 0,
-       SST_LIB_FOUND,
-       SST_LIB_DOWNLOADED,
-};
-
-struct sst_module_info {
-       const char *name; /*Library name*/
-       u32     id; /*Module ID*/
-       u32     entry_pt; /*Module entry point*/
-       u8      status; /*module status*/
-       u8      rsvd1;
-       u16     rsvd2;
-};
-
-/*
- * Structure for managing the Library Region(1.5MB)
- * in DDR in Merrifield
- */
-struct sst_mem_mgr {
-       phys_addr_t current_base;
-       int avail;
-       unsigned int count;
-};
-
-struct sst_ipc_reg {
-       int ipcx;
-       int ipcd;
-};
-
-struct sst_shim_regs64 {
-       u64 csr;
-       u64 pisr;
-       u64 pimr;
-       u64 isrx;
-       u64 isrd;
-       u64 imrx;
-       u64 imrd;
-       u64 ipcx;
-       u64 ipcd;
-       u64 isrsc;
-       u64 isrlpesc;
-       u64 imrsc;
-       u64 imrlpesc;
-       u64 ipcsc;
-       u64 ipclpesc;
-       u64 clkctl;
-       u64 csr2;
-};
-
-struct sst_fw_save {
-       void *iram;
-       void *dram;
-       void *sram;
-       void *ddr;
-};
-
-/**
- * struct intel_sst_drv - driver ops
- *
- * @sst_state : current sst device state
- * @dev_id : device identifier, pci_id for pci devices and acpi_id for acpi
- *          devices
- * @shim : SST shim pointer
- * @mailbox : SST mailbox pointer
- * @iram : SST IRAM pointer
- * @dram : SST DRAM pointer
- * @pdata : SST info passed as a part of pci platform data
- * @shim_phy_add : SST shim phy addr
- * @shim_regs64: Struct to save shim registers
- * @ipc_dispatch_list : ipc messages dispatched
- * @rx_list : to copy the process_reply/process_msg from DSP
- * @ipc_post_msg_wq : wq to post IPC messages context
- * @mad_ops : MAD driver operations registered
- * @mad_wq : MAD driver wq
- * @post_msg_wq : wq to post IPC messages
- * @streams : sst stream contexts
- * @list_lock : sst driver list lock (deprecated)
- * @ipc_spin_lock : spin lock to handle audio shim access and ipc queue
- * @block_lock : spin lock to add block to block_list and assign pvt_id
- * @rx_msg_lock : spin lock to handle the rx messages from the DSP
- * @scard_ops : sst card ops
- * @pci : sst pci device struture
- * @dev : pointer to current device struct
- * @sst_lock : sst device lock
- * @pvt_id : sst private id
- * @stream_cnt : total sst active stream count
- * @pb_streams : total active pb streams
- * @cp_streams : total active cp streams
- * @audio_start : audio status
- * @qos                : PM Qos struct
- * firmware_name : Firmware / Library name
- */
-struct intel_sst_drv {
-       int                     sst_state;
-       int                     irq_num;
-       unsigned int            dev_id;
-       void __iomem            *ddr;
-       void __iomem            *shim;
-       void __iomem            *mailbox;
-       void __iomem            *iram;
-       void __iomem            *dram;
-       unsigned int            mailbox_add;
-       unsigned int            iram_base;
-       unsigned int            dram_base;
-       unsigned int            shim_phy_add;
-       unsigned int            iram_end;
-       unsigned int            dram_end;
-       unsigned int            ddr_end;
-       unsigned int            ddr_base;
-       unsigned int            mailbox_recv_offset;
-       struct sst_shim_regs64  *shim_regs64;
-       struct list_head        block_list;
-       struct list_head        ipc_dispatch_list;
-       struct sst_platform_info *pdata;
-       struct list_head        rx_list;
-       struct work_struct      ipc_post_msg_wq;
-       wait_queue_head_t       wait_queue;
-       struct workqueue_struct *post_msg_wq;
-       unsigned int            tstamp;
-       /* str_id 0 is not used */
-       struct stream_info      streams[MAX_NUM_STREAMS+1];
-       spinlock_t              ipc_spin_lock;
-       spinlock_t              block_lock;
-       spinlock_t              rx_msg_lock;
-       struct pci_dev          *pci;
-       struct device           *dev;
-       volatile long unsigned          pvt_id;
-       struct mutex            sst_lock;
-       unsigned int            stream_cnt;
-       unsigned int            csr_value;
-       void                    *fw_in_mem;
-       struct sst_sg_list      fw_sg_list, library_list;
-       struct intel_sst_ops    *ops;
-       struct sst_info         info;
-       struct pm_qos_request   *qos;
-       unsigned int            use_dma;
-       unsigned int            use_lli;
-       atomic_t                fw_clear_context;
-       bool                    lib_dwnld_reqd;
-       struct list_head        memcpy_list;
-       struct sst_ipc_reg      ipc_reg;
-       struct sst_mem_mgr      lib_mem_mgr;
-       /*
-        * Holder for firmware name. Due to async call it needs to be
-        * persistent till worker thread gets called
-        */
-       char firmware_name[FW_NAME_SIZE];
-
-       struct sst_fw_save      *fw_save;
-};
-
-/* misc definitions */
-#define FW_DWNL_ID 0x01
-
-struct intel_sst_ops {
-       irqreturn_t (*interrupt)(int, void *);
-       irqreturn_t (*irq_thread)(int, void *);
-       void (*clear_interrupt)(struct intel_sst_drv *ctx);
-       int (*start)(struct intel_sst_drv *ctx);
-       int (*reset)(struct intel_sst_drv *ctx);
-       void (*process_reply)(struct intel_sst_drv *ctx, struct ipc_post *msg);
-       int (*post_message)(struct intel_sst_drv *ctx,
-                       struct ipc_post *msg, bool sync);
-       void (*process_message)(struct ipc_post *msg);
-       void (*set_bypass)(bool set);
-       int (*save_dsp_context)(struct intel_sst_drv *sst);
-       void (*restore_dsp_context)(void);
-       int (*alloc_stream)(struct intel_sst_drv *ctx, void *params);
-       void (*post_download)(struct intel_sst_drv *sst);
-};
-
-int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int id);
-int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int id);
-int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int id);
-int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int id);
-int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id);
-int sst_send_byte_stream_mrfld(struct intel_sst_drv *ctx,
-                       struct snd_sst_bytes_v2 *sbytes);
-int sst_set_stream_param(int str_id, struct snd_sst_params *str_param);
-int sst_set_metadata(int str_id, char *params);
-int sst_get_stream(struct intel_sst_drv *sst_drv_ctx,
-               struct snd_sst_params *str_param);
-int sst_get_stream_allocated(struct intel_sst_drv *ctx,
-               struct snd_sst_params *str_param,
-               struct snd_sst_lib_download **lib_dnld);
-int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
-               int str_id, bool partial_drain);
-int sst_post_message_mrfld(struct intel_sst_drv *ctx,
-               struct ipc_post *msg, bool sync);
-void sst_process_reply_mrfld(struct intel_sst_drv *ctx, struct ipc_post *msg);
-int sst_start_mrfld(struct intel_sst_drv *ctx);
-int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *ctx);
-void intel_sst_clear_intr_mrfld(struct intel_sst_drv *ctx);
-
-int sst_load_fw(struct intel_sst_drv *ctx);
-int sst_load_library(struct snd_sst_lib_download *lib, u8 ops);
-void sst_post_download_mrfld(struct intel_sst_drv *ctx);
-int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx);
-void sst_memcpy_free_resources(struct intel_sst_drv *ctx);
-
-int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
-                               struct sst_block *block);
-int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
-                       struct sst_block *block);
-int sst_create_ipc_msg(struct ipc_post **arg, bool large);
-int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id);
-void sst_clean_stream(struct stream_info *stream);
-int intel_sst_register_compress(struct intel_sst_drv *sst);
-int intel_sst_remove_compress(struct intel_sst_drv *sst);
-void sst_cdev_fragment_elapsed(struct intel_sst_drv *ctx, int str_id);
-int sst_send_sync_msg(int ipc, int str_id);
-int sst_get_num_channel(struct snd_sst_params *str_param);
-int sst_get_sfreq(struct snd_sst_params *str_param);
-int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params);
-void sst_restore_fw_context(void);
-struct sst_block *sst_create_block(struct intel_sst_drv *ctx,
-                               u32 msg_id, u32 drv_id);
-int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large,
-               struct intel_sst_drv *sst_drv_ctx, struct sst_block **block,
-               u32 msg_id, u32 drv_id);
-int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed);
-int sst_wake_up_block(struct intel_sst_drv *ctx, int result,
-               u32 drv_id, u32 ipc, void *data, u32 size);
-int sst_request_firmware_async(struct intel_sst_drv *ctx);
-int sst_driver_ops(struct intel_sst_drv *sst);
-struct sst_platform_info *sst_get_acpi_driver_data(const char *hid);
-void sst_firmware_load_cb(const struct firmware *fw, void *context);
-int sst_prepare_and_post_msg(struct intel_sst_drv *sst,
-               int task_id, int ipc_msg, int cmd_id, int pipe_id,
-               size_t mbox_data_len, const void *mbox_data, void **data,
-               bool large, bool fill_dsp, bool sync, bool response);
-
-void sst_process_pending_msg(struct work_struct *work);
-int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx);
-void sst_init_stream(struct stream_info *stream,
-               int codec, int sst_id, int ops, u8 slot);
-int sst_validate_strid(struct intel_sst_drv *sst_drv_ctx, int str_id);
-struct stream_info *get_stream_info(struct intel_sst_drv *sst_drv_ctx,
-               int str_id);
-int get_stream_id_mrfld(struct intel_sst_drv *sst_drv_ctx,
-               u32 pipe_id);
-u32 relocate_imr_addr_mrfld(u32 base_addr);
-void sst_add_to_dispatch_list_and_post(struct intel_sst_drv *sst,
-                                       struct ipc_post *msg);
-int sst_pm_runtime_put(struct intel_sst_drv *sst_drv);
-int sst_shim_write(void __iomem *addr, int offset, int value);
-u32 sst_shim_read(void __iomem *addr, int offset);
-u64 sst_reg_read64(void __iomem *addr, int offset);
-int sst_shim_write64(void __iomem *addr, int offset, u64 value);
-u64 sst_shim_read64(void __iomem *addr, int offset);
-void sst_set_fw_state_locked(
-               struct intel_sst_drv *sst_drv_ctx, int sst_state);
-void sst_fill_header_mrfld(union ipc_header_mrfld *header,
-                               int msg, int task_id, int large, int drv_id);
-void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg,
-                                       int pipe_id, int len);
-
-int sst_register(struct device *);
-int sst_unregister(struct device *);
-
-int sst_alloc_drv_context(struct intel_sst_drv **ctx,
-               struct device *dev, unsigned int dev_id);
-int sst_context_init(struct intel_sst_drv *ctx);
-void sst_context_cleanup(struct intel_sst_drv *ctx);
-void sst_configure_runtime_pm(struct intel_sst_drv *ctx);
-void memcpy32_toio(void __iomem *dst, const void *src, int count);
-void memcpy32_fromio(void *dst, const void __iomem *src, int count);
-
-#endif
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/sst/sst_acpi.c
deleted file mode 100644 (file)
index 2a19cbc..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration.
- *
- * Copyright (c) 2013, Intel Corporation.
- *
- *  Authors:   Ramesh Babu K V <Ramesh.Babu@intel.com>
- *  Authors:   Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- *
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
-#include <linux/acpi.h>
-#include <asm/platform_sst_audio.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <acpi/acbuffer.h>
-#include <acpi/platform/acenv.h>
-#include <acpi/platform/aclinux.h>
-#include <acpi/actypes.h>
-#include <acpi/acpi_bus.h>
-#include "../sst-mfld-platform.h"
-#include "../common/sst-dsp.h"
-#include "sst.h"
-
-struct sst_machines {
-       char *codec_id;
-       char board[32];
-       char machine[32];
-       void (*machine_quirk)(void);
-       char firmware[FW_NAME_SIZE];
-       struct sst_platform_info *pdata;
-
-};
-
-/* LPE viewpoint addresses */
-#define SST_BYT_IRAM_PHY_START 0xff2c0000
-#define SST_BYT_IRAM_PHY_END   0xff2d4000
-#define SST_BYT_DRAM_PHY_START 0xff300000
-#define SST_BYT_DRAM_PHY_END   0xff320000
-#define SST_BYT_IMR_VIRT_START 0xc0000000 /* virtual addr in LPE */
-#define SST_BYT_IMR_VIRT_END   0xc01fffff
-#define SST_BYT_SHIM_PHY_ADDR  0xff340000
-#define SST_BYT_MBOX_PHY_ADDR  0xff344000
-#define SST_BYT_DMA0_PHY_ADDR  0xff298000
-#define SST_BYT_DMA1_PHY_ADDR  0xff29c000
-#define SST_BYT_SSP0_PHY_ADDR  0xff2a0000
-#define SST_BYT_SSP2_PHY_ADDR  0xff2a2000
-
-#define BYT_FW_MOD_TABLE_OFFSET        0x80000
-#define BYT_FW_MOD_TABLE_SIZE  0x100
-#define BYT_FW_MOD_OFFSET      (BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE)
-
-static const struct sst_info byt_fwparse_info = {
-       .use_elf        = false,
-       .max_streams    = 25,
-       .iram_start     = SST_BYT_IRAM_PHY_START,
-       .iram_end       = SST_BYT_IRAM_PHY_END,
-       .iram_use       = true,
-       .dram_start     = SST_BYT_DRAM_PHY_START,
-       .dram_end       = SST_BYT_DRAM_PHY_END,
-       .dram_use       = true,
-       .imr_start      = SST_BYT_IMR_VIRT_START,
-       .imr_end        = SST_BYT_IMR_VIRT_END,
-       .imr_use        = true,
-       .mailbox_start  = SST_BYT_MBOX_PHY_ADDR,
-       .num_probes     = 0,
-       .lpe_viewpt_rqd  = true,
-};
-
-static const struct sst_ipc_info byt_ipc_info = {
-       .ipc_offset = 0,
-       .mbox_recv_off = 0x400,
-};
-
-static const struct sst_lib_dnld_info  byt_lib_dnld_info = {
-       .mod_base           = SST_BYT_IMR_VIRT_START,
-       .mod_end            = SST_BYT_IMR_VIRT_END,
-       .mod_table_offset   = BYT_FW_MOD_TABLE_OFFSET,
-       .mod_table_size     = BYT_FW_MOD_TABLE_SIZE,
-       .mod_ddr_dnld       = false,
-};
-
-static const struct sst_res_info byt_rvp_res_info = {
-       .shim_offset = 0x140000,
-       .shim_size = 0x000100,
-       .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
-       .ssp0_offset = 0xa0000,
-       .ssp0_size = 0x1000,
-       .dma0_offset = 0x98000,
-       .dma0_size = 0x4000,
-       .dma1_offset = 0x9c000,
-       .dma1_size = 0x4000,
-       .iram_offset = 0x0c0000,
-       .iram_size = 0x14000,
-       .dram_offset = 0x100000,
-       .dram_size = 0x28000,
-       .mbox_offset = 0x144000,
-       .mbox_size = 0x1000,
-       .acpi_lpe_res_index = 0,
-       .acpi_ddr_index = 2,
-       .acpi_ipc_irq_index = 5,
-};
-
-static struct sst_platform_info byt_rvp_platform_data = {
-       .probe_data = &byt_fwparse_info,
-       .ipc_info = &byt_ipc_info,
-       .lib_info = &byt_lib_dnld_info,
-       .res_info = &byt_rvp_res_info,
-       .platform = "sst-mfld-platform",
-};
-
-/* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
- * so pdata is same as Baytrail.
- */
-static struct sst_platform_info chv_platform_data = {
-       .probe_data = &byt_fwparse_info,
-       .ipc_info = &byt_ipc_info,
-       .lib_info = &byt_lib_dnld_info,
-       .res_info = &byt_rvp_res_info,
-       .platform = "sst-mfld-platform",
-};
-
-static int sst_platform_get_resources(struct intel_sst_drv *ctx)
-{
-       struct resource *rsrc;
-       struct platform_device *pdev = to_platform_device(ctx->dev);
-
-       /* All ACPI resource request here */
-       /* Get Shim addr */
-       rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
-                                       ctx->pdata->res_info->acpi_lpe_res_index);
-       if (!rsrc) {
-               dev_err(ctx->dev, "Invalid SHIM base from IFWI");
-               return -EIO;
-       }
-       dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start,
-                                       (unsigned int)resource_size(rsrc));
-
-       ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset;
-       ctx->iram_end =  ctx->iram_base + ctx->pdata->res_info->iram_size - 1;
-       dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base);
-       ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base,
-                                        ctx->pdata->res_info->iram_size);
-       if (!ctx->iram) {
-               dev_err(ctx->dev, "unable to map IRAM");
-               return -EIO;
-       }
-
-       ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset;
-       ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1;
-       dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base);
-       ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base,
-                                        ctx->pdata->res_info->dram_size);
-       if (!ctx->dram) {
-               dev_err(ctx->dev, "unable to map DRAM");
-               return -EIO;
-       }
-
-       ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset;
-       dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add);
-       ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add,
-                                       ctx->pdata->res_info->shim_size);
-       if (!ctx->shim) {
-               dev_err(ctx->dev, "unable to map SHIM");
-               return -EIO;
-       }
-
-       /* reassign physical address to LPE viewpoint address */
-       ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr;
-
-       /* Get mailbox addr */
-       ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset;
-       dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add);
-       ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add,
-                                           ctx->pdata->res_info->mbox_size);
-       if (!ctx->mailbox) {
-               dev_err(ctx->dev, "unable to map mailbox");
-               return -EIO;
-       }
-
-       /* reassign physical address to LPE viewpoint address */
-       ctx->mailbox_add = ctx->info.mailbox_start;
-
-       rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
-                                       ctx->pdata->res_info->acpi_ddr_index);
-       if (!rsrc) {
-               dev_err(ctx->dev, "Invalid DDR base from IFWI");
-               return -EIO;
-       }
-       ctx->ddr_base = rsrc->start;
-       ctx->ddr_end = rsrc->end;
-       dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base);
-       ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base,
-                                       resource_size(rsrc));
-       if (!ctx->ddr) {
-               dev_err(ctx->dev, "unable to map DDR");
-               return -EIO;
-       }
-
-       /* Find the IRQ */
-       ctx->irq_num = platform_get_irq(pdev,
-                               ctx->pdata->res_info->acpi_ipc_irq_index);
-       return 0;
-}
-
-static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
-                                      void *context, void **ret)
-{
-       *(bool *)context = true;
-       return AE_OK;
-}
-
-static struct sst_machines *sst_acpi_find_machine(
-       struct sst_machines *machines)
-{
-       struct sst_machines *mach;
-       bool found = false;
-
-       for (mach = machines; mach->codec_id; mach++)
-               if (ACPI_SUCCESS(acpi_get_devices(mach->codec_id,
-                                                 sst_acpi_mach_match,
-                                                 &found, NULL)) && found)
-                       return mach;
-
-       return NULL;
-}
-
-static int sst_acpi_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       int ret = 0;
-       struct intel_sst_drv *ctx;
-       const struct acpi_device_id *id;
-       struct sst_machines *mach;
-       struct platform_device *mdev;
-       struct platform_device *plat_dev;
-       unsigned int dev_id;
-
-       id = acpi_match_device(dev->driver->acpi_match_table, dev);
-       if (!id)
-               return -ENODEV;
-       dev_dbg(dev, "for %s", id->id);
-
-       mach = (struct sst_machines *)id->driver_data;
-       mach = sst_acpi_find_machine(mach);
-       if (mach == NULL) {
-               dev_err(dev, "No matching machine driver found\n");
-               return -ENODEV;
-       }
-
-       ret = kstrtouint(id->id, 16, &dev_id);
-       if (ret < 0) {
-               dev_err(dev, "Unique device id conversion error: %d\n", ret);
-               return ret;
-       }
-
-       dev_dbg(dev, "ACPI device id: %x\n", dev_id);
-
-       plat_dev = platform_device_register_data(dev, mach->pdata->platform, -1, NULL, 0);
-       if (IS_ERR(plat_dev)) {
-               dev_err(dev, "Failed to create machine device: %s\n", mach->pdata->platform);
-               return PTR_ERR(plat_dev);
-       }
-
-       /* Create platform device for sst machine driver */
-       mdev = platform_device_register_data(dev, mach->machine, -1, NULL, 0);
-       if (IS_ERR(mdev)) {
-               dev_err(dev, "Failed to create machine device: %s\n", mach->machine);
-               return PTR_ERR(mdev);
-       }
-
-       ret = sst_alloc_drv_context(&ctx, dev, dev_id);
-       if (ret < 0)
-               return ret;
-
-       /* Fill sst platform data */
-       ctx->pdata = mach->pdata;
-       strcpy(ctx->firmware_name, mach->firmware);
-
-       ret = sst_platform_get_resources(ctx);
-       if (ret)
-               return ret;
-
-       ret = sst_context_init(ctx);
-       if (ret < 0)
-               return ret;
-
-       /* need to save shim registers in BYT */
-       ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64),
-                                       GFP_KERNEL);
-       if (!ctx->shim_regs64) {
-               return -ENOMEM;
-               goto do_sst_cleanup;
-       }
-
-       sst_configure_runtime_pm(ctx);
-       platform_set_drvdata(pdev, ctx);
-       return ret;
-
-do_sst_cleanup:
-       sst_context_cleanup(ctx);
-       platform_set_drvdata(pdev, NULL);
-       dev_err(ctx->dev, "failed with %d\n", ret);
-       return ret;
-}
-
-/**
-* intel_sst_remove - remove function
-*
-* @pdev:       platform device structure
-*
-* This function is called by OS when a device is unloaded
-* This frees the interrupt etc
-*/
-static int sst_acpi_remove(struct platform_device *pdev)
-{
-       struct intel_sst_drv *ctx;
-
-       ctx = platform_get_drvdata(pdev);
-       sst_context_cleanup(ctx);
-       platform_set_drvdata(pdev, NULL);
-       return 0;
-}
-
-static struct sst_machines sst_acpi_bytcr[] = {
-       {"10EC5640", "T100", "bytt100_rt5640", NULL, "intel/fw_sst_0f28.bin",
-                                               &byt_rvp_platform_data },
-       {},
-};
-
-/* Cherryview-based platforms: CherryTrail and Braswell */
-static struct sst_machines sst_acpi_chv[] = {
-       {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin",
-                                               &chv_platform_data },
-       {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
-                                               &chv_platform_data },
-       {},
-};
-
-static const struct acpi_device_id sst_acpi_ids[] = {
-       { "80860F28", (unsigned long)&sst_acpi_bytcr},
-       { "808622A8", (unsigned long) &sst_acpi_chv},
-       { },
-};
-
-MODULE_DEVICE_TABLE(acpi, sst_acpi_ids);
-
-static struct platform_driver sst_acpi_driver = {
-       .driver = {
-               .name                   = "intel_sst_acpi",
-               .acpi_match_table       = ACPI_PTR(sst_acpi_ids),
-               .pm                     = &intel_sst_pm,
-       },
-       .probe  = sst_acpi_probe,
-       .remove = sst_acpi_remove,
-};
-
-module_platform_driver(sst_acpi_driver);
-
-MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver");
-MODULE_AUTHOR("Ramesh Babu K V");
-MODULE_AUTHOR("Omair Mohammed Abdullah");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("sst");
diff --git a/sound/soc/intel/sst/sst_drv_interface.c b/sound/soc/intel/sst/sst_drv_interface.c
deleted file mode 100644 (file)
index 36d68b8..0000000
+++ /dev/null
@@ -1,741 +0,0 @@
-/*
- *  sst_drv_interface.c - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14 Intel Corp
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com)
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
-#include <linux/math64.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-#include "../common/sst-dsp.h"
-
-
-
-#define NUM_CODEC 2
-#define MIN_FRAGMENT 2
-#define MAX_FRAGMENT 4
-#define MIN_FRAGMENT_SIZE (50 * 1024)
-#define MAX_FRAGMENT_SIZE (1024 * 1024)
-#define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz)  (((pcm_wd_sz + 15) >> 4) << 1)
-
-int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id)
-{
-       struct stream_info *stream;
-       int ret = 0;
-
-       stream = get_stream_info(ctx, str_id);
-       if (stream) {
-               /* str_id is valid, so stream is alloacted */
-               ret = sst_free_stream(ctx, str_id);
-               if (ret)
-                       sst_clean_stream(&ctx->streams[str_id]);
-               return ret;
-       } else {
-               dev_err(ctx->dev, "we tried to free stream context %d which was freed!!!\n", str_id);
-       }
-       return ret;
-}
-
-int sst_get_stream_allocated(struct intel_sst_drv *ctx,
-       struct snd_sst_params *str_param,
-       struct snd_sst_lib_download **lib_dnld)
-{
-       int retval;
-
-       retval = ctx->ops->alloc_stream(ctx, str_param);
-       if (retval > 0)
-               dev_dbg(ctx->dev, "Stream allocated %d\n", retval);
-       return retval;
-
-}
-
-/*
- * sst_get_sfreq - this function returns the frequency of the stream
- *
- * @str_param : stream params
- */
-int sst_get_sfreq(struct snd_sst_params *str_param)
-{
-       switch (str_param->codec) {
-       case SST_CODEC_TYPE_PCM:
-               return str_param->sparams.uc.pcm_params.sfreq;
-       case SST_CODEC_TYPE_AAC:
-               return str_param->sparams.uc.aac_params.externalsr;
-       case SST_CODEC_TYPE_MP3:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-/*
- * sst_get_num_channel - get number of channels for the stream
- *
- * @str_param : stream params
- */
-int sst_get_num_channel(struct snd_sst_params *str_param)
-{
-       switch (str_param->codec) {
-       case SST_CODEC_TYPE_PCM:
-               return str_param->sparams.uc.pcm_params.num_chan;
-       case SST_CODEC_TYPE_MP3:
-               return str_param->sparams.uc.mp3_params.num_chan;
-       case SST_CODEC_TYPE_AAC:
-               return str_param->sparams.uc.aac_params.num_chan;
-       default:
-               return -EINVAL;
-       }
-}
-
-/*
- * sst_get_stream - this function prepares for stream allocation
- *
- * @str_param : stream param
- */
-int sst_get_stream(struct intel_sst_drv *ctx,
-                       struct snd_sst_params *str_param)
-{
-       int retval;
-       struct stream_info *str_info;
-
-       /* stream is not allocated, we are allocating */
-       retval = ctx->ops->alloc_stream(ctx, str_param);
-       if (retval <= 0) {
-               return -EIO;
-       }
-       /* store sampling freq */
-       str_info = &ctx->streams[retval];
-       str_info->sfreq = sst_get_sfreq(str_param);
-
-       return retval;
-}
-
-static int sst_power_control(struct device *dev, bool state)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-       int ret = 0;
-       int usage_count = 0;
-
-#ifdef CONFIG_PM
-       usage_count = atomic_read(&dev->power.usage_count);
-#else
-       usage_count = 1;
-#endif
-
-       if (state == true) {
-               ret = pm_runtime_get_sync(dev);
-
-               dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
-               if (ret < 0) {
-                       dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
-                       return ret;
-               }
-               if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
-                       ret = sst_load_fw(ctx);
-                       if (ret) {
-                               dev_err(dev, "FW download fail %d\n", ret);
-                               sst_set_fw_state_locked(ctx, SST_RESET);
-                               ret = sst_pm_runtime_put(ctx);
-                       }
-               }
-       } else {
-               dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
-               return sst_pm_runtime_put(ctx);
-       }
-       return ret;
-}
-
-/*
- * sst_open_pcm_stream - Open PCM interface
- *
- * @str_param: parameters of pcm stream
- *
- * This function is called by MID sound card driver to open
- * a new pcm interface
- */
-static int sst_open_pcm_stream(struct device *dev,
-               struct snd_sst_params *str_param)
-{
-       int retval;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (!str_param)
-               return -EINVAL;
-
-       retval = sst_get_stream(ctx, str_param);
-       if (retval > 0)
-               ctx->stream_cnt++;
-       else
-               dev_err(ctx->dev, "sst_get_stream returned err %d\n", retval);
-
-       return retval;
-}
-
-static int sst_cdev_open(struct device *dev,
-               struct snd_sst_params *str_params, struct sst_compress_cb *cb)
-{
-       int str_id, retval;
-       struct stream_info *stream;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       retval = pm_runtime_get_sync(ctx->dev);
-       if (retval < 0)
-               return retval;
-
-       str_id = sst_get_stream(ctx, str_params);
-       if (str_id > 0) {
-               dev_dbg(dev, "stream allocated in sst_cdev_open %d\n", str_id);
-               stream = &ctx->streams[str_id];
-               stream->compr_cb = cb->compr_cb;
-               stream->compr_cb_param = cb->param;
-               stream->drain_notify = cb->drain_notify;
-               stream->drain_cb_param = cb->drain_cb_param;
-       } else {
-               dev_err(dev, "stream encountered error during alloc %d\n", str_id);
-               str_id = -EINVAL;
-               sst_pm_runtime_put(ctx);
-       }
-       return str_id;
-}
-
-static int sst_cdev_close(struct device *dev, unsigned int str_id)
-{
-       int retval;
-       struct stream_info *stream;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       stream = get_stream_info(ctx, str_id);
-       if (!stream) {
-               dev_err(dev, "stream info is NULL for str %d!!!\n", str_id);
-               return -EINVAL;
-       }
-
-       if (stream->status == STREAM_RESET) {
-               dev_dbg(dev, "stream in reset state...\n");
-               stream->status = STREAM_UN_INIT;
-
-               retval = 0;
-               goto put;
-       }
-
-       retval = sst_free_stream(ctx, str_id);
-put:
-       stream->compr_cb_param = NULL;
-       stream->compr_cb = NULL;
-
-       if (retval)
-               dev_err(dev, "free stream returned err %d\n", retval);
-
-       dev_dbg(dev, "End\n");
-       return retval;
-
-}
-
-static int sst_cdev_ack(struct device *dev, unsigned int str_id,
-               unsigned long bytes)
-{
-       struct stream_info *stream;
-       struct snd_sst_tstamp fw_tstamp = {0,};
-       int offset;
-       void __iomem *addr;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       stream = get_stream_info(ctx, str_id);
-       if (!stream)
-               return -EINVAL;
-
-       /* update bytes sent */
-       stream->cumm_bytes += bytes;
-       dev_dbg(dev, "bytes copied %d inc by %ld\n", stream->cumm_bytes, bytes);
-
-       memcpy_fromio(&fw_tstamp,
-               ((void *)(ctx->mailbox + ctx->tstamp)
-               +(str_id * sizeof(fw_tstamp))),
-               sizeof(fw_tstamp));
-
-       fw_tstamp.bytes_copied = stream->cumm_bytes;
-       dev_dbg(dev, "bytes sent to fw %llu inc by %ld\n",
-                       fw_tstamp.bytes_copied, bytes);
-
-       addr =  ((void *)(ctx->mailbox + ctx->tstamp)) +
-                       (str_id * sizeof(fw_tstamp));
-       offset =  offsetof(struct snd_sst_tstamp, bytes_copied);
-       sst_shim_write(addr, offset, fw_tstamp.bytes_copied);
-       return 0;
-}
-
-static int sst_cdev_set_metadata(struct device *dev,
-               unsigned int str_id, struct snd_compr_metadata *metadata)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       dev_dbg(dev, "set metadata for stream %d\n", str_id);
-
-       str_info = get_stream_info(ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-
-       dev_dbg(dev, "pipe id = %d\n", str_info->pipe_id);
-       retval = sst_prepare_and_post_msg(ctx, str_info->task_id, IPC_CMD,
-                       IPC_IA_SET_STREAM_PARAMS_MRFLD, str_info->pipe_id,
-                       sizeof(*metadata), metadata, NULL,
-                       true, true, true, false);
-
-       return retval;
-}
-
-static int sst_cdev_stream_pause(struct device *dev, unsigned int str_id)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       return sst_pause_stream(ctx, str_id);
-}
-
-static int sst_cdev_stream_pause_release(struct device *dev,
-               unsigned int str_id)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       return sst_resume_stream(ctx, str_id);
-}
-
-static int sst_cdev_stream_start(struct device *dev, unsigned int str_id)
-{
-       struct stream_info *str_info;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       str_info = get_stream_info(ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       str_info->prev = str_info->status;
-       str_info->status = STREAM_RUNNING;
-       return sst_start_stream(ctx, str_id);
-}
-
-static int sst_cdev_stream_drop(struct device *dev, unsigned int str_id)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       return sst_drop_stream(ctx, str_id);
-}
-
-static int sst_cdev_stream_drain(struct device *dev, unsigned int str_id)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       return sst_drain_stream(ctx, str_id, false);
-}
-
-static int sst_cdev_stream_partial_drain(struct device *dev,
-               unsigned int str_id)
-{
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       return sst_drain_stream(ctx, str_id, true);
-}
-
-static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
-               struct snd_compr_tstamp *tstamp)
-{
-       struct snd_sst_tstamp fw_tstamp = {0,};
-       struct stream_info *stream;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       memcpy_fromio(&fw_tstamp,
-               ((void *)(ctx->mailbox + ctx->tstamp)
-               +(str_id * sizeof(fw_tstamp))),
-               sizeof(fw_tstamp));
-
-       stream = get_stream_info(ctx, str_id);
-       if (!stream)
-               return -EINVAL;
-       dev_dbg(dev, "rb_counter %llu in bytes\n", fw_tstamp.ring_buffer_counter);
-
-       tstamp->copied_total = fw_tstamp.ring_buffer_counter;
-       tstamp->pcm_frames = fw_tstamp.frames_decoded;
-       tstamp->pcm_io_frames = div_u64(fw_tstamp.hardware_counter,
-                       (u64)((stream->num_ch) * SST_GET_BYTES_PER_SAMPLE(24)));
-       tstamp->sampling_rate = fw_tstamp.sampling_frequency;
-
-       dev_dbg(dev, "PCM  = %u\n", tstamp->pcm_io_frames);
-       dev_dbg(dev, "Ptr Query on strid = %d  copied_total %d, decodec %d\n",
-               str_id, tstamp->copied_total, tstamp->pcm_frames);
-       dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames);
-
-       return 0;
-}
-
-static int sst_cdev_caps(struct snd_compr_caps *caps)
-{
-       caps->num_codecs = NUM_CODEC;
-       caps->min_fragment_size = MIN_FRAGMENT_SIZE;  /* 50KB */
-       caps->max_fragment_size = MAX_FRAGMENT_SIZE;  /* 1024KB */
-       caps->min_fragments = MIN_FRAGMENT;
-       caps->max_fragments = MAX_FRAGMENT;
-       caps->codecs[0] = SND_AUDIOCODEC_MP3;
-       caps->codecs[1] = SND_AUDIOCODEC_AAC;
-       return 0;
-}
-
-static struct snd_compr_codec_caps caps_mp3 = {
-       .num_descriptors = 1,
-       .descriptor[0].max_ch = 2,
-       .descriptor[0].sample_rates[0] = 48000,
-       .descriptor[0].sample_rates[1] = 44100,
-       .descriptor[0].sample_rates[2] = 32000,
-       .descriptor[0].sample_rates[3] = 16000,
-       .descriptor[0].sample_rates[4] = 8000,
-       .descriptor[0].num_sample_rates = 5,
-       .descriptor[0].bit_rate[0] = 320,
-       .descriptor[0].bit_rate[1] = 192,
-       .descriptor[0].num_bitrates = 2,
-       .descriptor[0].profiles = 0,
-       .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
-       .descriptor[0].formats = 0,
-};
-
-static struct snd_compr_codec_caps caps_aac = {
-       .num_descriptors = 2,
-       .descriptor[1].max_ch = 2,
-       .descriptor[0].sample_rates[0] = 48000,
-       .descriptor[0].sample_rates[1] = 44100,
-       .descriptor[0].sample_rates[2] = 32000,
-       .descriptor[0].sample_rates[3] = 16000,
-       .descriptor[0].sample_rates[4] = 8000,
-       .descriptor[0].num_sample_rates = 5,
-       .descriptor[1].bit_rate[0] = 320,
-       .descriptor[1].bit_rate[1] = 192,
-       .descriptor[1].num_bitrates = 2,
-       .descriptor[1].profiles = 0,
-       .descriptor[1].modes = 0,
-       .descriptor[1].formats =
-                       (SND_AUDIOSTREAMFORMAT_MP4ADTS |
-                               SND_AUDIOSTREAMFORMAT_RAW),
-};
-
-static int sst_cdev_codec_caps(struct snd_compr_codec_caps *codec)
-{
-       if (codec->codec == SND_AUDIOCODEC_MP3)
-               *codec = caps_mp3;
-       else if (codec->codec == SND_AUDIOCODEC_AAC)
-               *codec = caps_aac;
-       else
-               return -EINVAL;
-
-       return 0;
-}
-
-void sst_cdev_fragment_elapsed(struct intel_sst_drv *ctx, int str_id)
-{
-       struct stream_info *stream;
-
-       dev_dbg(ctx->dev, "fragment elapsed from firmware for str_id %d\n",
-                       str_id);
-       stream = &ctx->streams[str_id];
-       if (stream->compr_cb)
-               stream->compr_cb(stream->compr_cb_param);
-}
-
-/*
- * sst_close_pcm_stream - Close PCM interface
- *
- * @str_id: stream id to be closed
- *
- * This function is called by MID sound card driver to close
- * an existing pcm interface
- */
-static int sst_close_pcm_stream(struct device *dev, unsigned int str_id)
-{
-       struct stream_info *stream;
-       int retval = 0;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       stream = get_stream_info(ctx, str_id);
-       if (!stream) {
-               dev_err(ctx->dev, "stream info is NULL for str %d!!!\n", str_id);
-               return -EINVAL;
-       }
-
-       if (stream->status == STREAM_RESET) {
-               /* silently fail here as we have cleaned the stream earlier */
-               dev_dbg(ctx->dev, "stream in reset state...\n");
-
-               retval = 0;
-               goto put;
-       }
-
-       retval = free_stream_context(ctx, str_id);
-put:
-       stream->pcm_substream = NULL;
-       stream->status = STREAM_UN_INIT;
-       stream->period_elapsed = NULL;
-       ctx->stream_cnt--;
-
-       if (retval)
-               dev_err(ctx->dev, "free stream returned err %d\n", retval);
-
-       dev_dbg(ctx->dev, "Exit\n");
-       return 0;
-}
-
-static inline int sst_calc_tstamp(struct intel_sst_drv *ctx,
-               struct pcm_stream_info *info,
-               struct snd_pcm_substream *substream,
-               struct snd_sst_tstamp *fw_tstamp)
-{
-       size_t delay_bytes, delay_frames;
-       size_t buffer_sz;
-       u32 pointer_bytes, pointer_samples;
-
-       dev_dbg(ctx->dev, "mrfld ring_buffer_counter %llu in bytes\n",
-                       fw_tstamp->ring_buffer_counter);
-       dev_dbg(ctx->dev, "mrfld hardware_counter %llu in bytes\n",
-                        fw_tstamp->hardware_counter);
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               delay_bytes = (size_t) (fw_tstamp->ring_buffer_counter -
-                                       fw_tstamp->hardware_counter);
-       else
-               delay_bytes = (size_t) (fw_tstamp->hardware_counter -
-                                       fw_tstamp->ring_buffer_counter);
-       delay_frames = bytes_to_frames(substream->runtime, delay_bytes);
-       buffer_sz = snd_pcm_lib_buffer_bytes(substream);
-       div_u64_rem(fw_tstamp->ring_buffer_counter, buffer_sz, &pointer_bytes);
-       pointer_samples = bytes_to_samples(substream->runtime, pointer_bytes);
-
-       dev_dbg(ctx->dev, "pcm delay %zu in bytes\n", delay_bytes);
-
-       info->buffer_ptr = pointer_samples / substream->runtime->channels;
-
-       info->pcm_delay = delay_frames / substream->runtime->channels;
-       dev_dbg(ctx->dev, "buffer ptr %llu pcm_delay rep: %llu\n",
-                       info->buffer_ptr, info->pcm_delay);
-       return 0;
-}
-
-static int sst_read_timestamp(struct device *dev, struct pcm_stream_info *info)
-{
-       struct stream_info *stream;
-       struct snd_pcm_substream *substream;
-       struct snd_sst_tstamp fw_tstamp;
-       unsigned int str_id;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       str_id = info->str_id;
-       stream = get_stream_info(ctx, str_id);
-       if (!stream)
-               return -EINVAL;
-
-       if (!stream->pcm_substream)
-               return -EINVAL;
-       substream = stream->pcm_substream;
-
-       memcpy_fromio(&fw_tstamp,
-               ((void *)(ctx->mailbox + ctx->tstamp)
-                       + (str_id * sizeof(fw_tstamp))),
-               sizeof(fw_tstamp));
-       return sst_calc_tstamp(ctx, info, substream, &fw_tstamp);
-}
-
-static int sst_stream_start(struct device *dev, int str_id)
-{
-       struct stream_info *str_info;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (ctx->sst_state != SST_FW_RUNNING)
-               return 0;
-       str_info = get_stream_info(ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       str_info->prev = str_info->status;
-       str_info->status = STREAM_RUNNING;
-       sst_start_stream(ctx, str_id);
-
-       return 0;
-}
-
-static int sst_stream_drop(struct device *dev, int str_id)
-{
-       struct stream_info *str_info;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (ctx->sst_state != SST_FW_RUNNING)
-               return 0;
-
-       str_info = get_stream_info(ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       str_info->prev = STREAM_UN_INIT;
-       str_info->status = STREAM_INIT;
-       return sst_drop_stream(ctx, str_id);
-}
-
-static int sst_stream_pause(struct device *dev, int str_id)
-{
-       struct stream_info *str_info;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (ctx->sst_state != SST_FW_RUNNING)
-               return 0;
-
-       str_info = get_stream_info(ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-
-       return sst_pause_stream(ctx, str_id);
-}
-
-static int sst_stream_resume(struct device *dev, int str_id)
-{
-       struct stream_info *str_info;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (ctx->sst_state != SST_FW_RUNNING)
-               return 0;
-
-       str_info = get_stream_info(ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       return sst_resume_stream(ctx, str_id);
-}
-
-static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
-{
-       int str_id = 0;
-       struct stream_info *stream;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       str_id = str_info->str_id;
-
-       if (ctx->sst_state != SST_FW_RUNNING)
-               return 0;
-
-       stream = get_stream_info(ctx, str_id);
-       if (!stream)
-               return -EINVAL;
-
-       dev_dbg(ctx->dev, "setting the period ptrs\n");
-       stream->pcm_substream = str_info->arg;
-       stream->period_elapsed = str_info->period_elapsed;
-       stream->sfreq = str_info->sfreq;
-       stream->prev = stream->status;
-       stream->status = STREAM_INIT;
-       dev_dbg(ctx->dev,
-               "pcm_substream %p, period_elapsed %p, sfreq %d, status %d\n",
-               stream->pcm_substream, stream->period_elapsed,
-               stream->sfreq, stream->status);
-
-       return 0;
-}
-
-/*
- * sst_set_byte_stream - 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_send_byte_stream(struct device *dev,
-               struct snd_sst_bytes_v2 *bytes)
-{
-       int ret_val = 0;
-       struct intel_sst_drv *ctx = dev_get_drvdata(dev);
-
-       if (NULL == bytes)
-               return -EINVAL;
-       ret_val = pm_runtime_get_sync(ctx->dev);
-       if (ret_val < 0)
-               return ret_val;
-
-       ret_val = sst_send_byte_stream_mrfld(ctx, bytes);
-       sst_pm_runtime_put(ctx);
-
-       return ret_val;
-}
-
-static struct sst_ops pcm_ops = {
-       .open = sst_open_pcm_stream,
-       .stream_init = sst_stream_init,
-       .stream_start = sst_stream_start,
-       .stream_drop = sst_stream_drop,
-       .stream_pause = sst_stream_pause,
-       .stream_pause_release = sst_stream_resume,
-       .stream_read_tstamp = sst_read_timestamp,
-       .send_byte_stream = sst_send_byte_stream,
-       .close = sst_close_pcm_stream,
-       .power = sst_power_control,
-};
-
-static struct compress_sst_ops compr_ops = {
-       .open = sst_cdev_open,
-       .close = sst_cdev_close,
-       .stream_pause = sst_cdev_stream_pause,
-       .stream_pause_release = sst_cdev_stream_pause_release,
-       .stream_start = sst_cdev_stream_start,
-       .stream_drop = sst_cdev_stream_drop,
-       .stream_drain = sst_cdev_stream_drain,
-       .stream_partial_drain = sst_cdev_stream_partial_drain,
-       .tstamp = sst_cdev_tstamp,
-       .ack = sst_cdev_ack,
-       .get_caps = sst_cdev_caps,
-       .get_codec_caps = sst_cdev_codec_caps,
-       .set_metadata = sst_cdev_set_metadata,
-       .power = sst_power_control,
-};
-
-static struct sst_device sst_dsp_device = {
-       .name = "Intel(R) SST LPE",
-       .dev = NULL,
-       .ops = &pcm_ops,
-       .compr_ops = &compr_ops,
-};
-
-/*
- * sst_register - function to register DSP
- *
- * This functions registers DSP with the platform driver
- */
-int sst_register(struct device *dev)
-{
-       int ret_val;
-
-       sst_dsp_device.dev = dev;
-       ret_val = sst_register_dsp(&sst_dsp_device);
-       if (ret_val)
-               dev_err(dev, "Unable to register DSP with platform driver\n");
-
-       return ret_val;
-}
-
-int sst_unregister(struct device *dev)
-{
-       return sst_unregister_dsp(&sst_dsp_device);
-}
diff --git a/sound/soc/intel/sst/sst_ipc.c b/sound/soc/intel/sst/sst_ipc.c
deleted file mode 100644 (file)
index 3943ae8..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- *  sst_ipc.c - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14 Intel Corporation
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <asm/intel-mid.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-#include "../common/sst-dsp.h"
-
-struct sst_block *sst_create_block(struct intel_sst_drv *ctx,
-                                       u32 msg_id, u32 drv_id)
-{
-       struct sst_block *msg = NULL;
-
-       dev_dbg(ctx->dev, "Enter\n");
-       msg = kzalloc(sizeof(*msg), GFP_KERNEL);
-       if (!msg)
-               return NULL;
-       msg->condition = false;
-       msg->on = true;
-       msg->msg_id = msg_id;
-       msg->drv_id = drv_id;
-       spin_lock_bh(&ctx->block_lock);
-       list_add_tail(&msg->node, &ctx->block_list);
-       spin_unlock_bh(&ctx->block_lock);
-
-       return msg;
-}
-
-/*
- * while handling the interrupts, we need to check for message status and
- * then if we are blocking for a message
- *
- * here we are unblocking the blocked ones, this is based on id we have
- * passed and search that for block threads.
- * We will not find block in two cases
- *  a) when its small message and block in not there, so silently ignore
- *  them
- *  b) when we are actually not able to find the block (bug perhaps)
- *
- *  Since we have bit of small messages we can spam kernel log with err
- *  print on above so need to keep as debug prints which should be enabled
- *  via dynamic debug while debugging IPC issues
- */
-int sst_wake_up_block(struct intel_sst_drv *ctx, int result,
-               u32 drv_id, u32 ipc, void *data, u32 size)
-{
-       struct sst_block *block = NULL;
-
-       dev_dbg(ctx->dev, "Enter\n");
-
-       spin_lock_bh(&ctx->block_lock);
-       list_for_each_entry(block, &ctx->block_list, node) {
-               dev_dbg(ctx->dev, "Block ipc %d, drv_id %d\n", block->msg_id,
-                                                       block->drv_id);
-               if (block->msg_id == ipc && block->drv_id == drv_id) {
-                       dev_dbg(ctx->dev, "free up the block\n");
-                       block->ret_code = result;
-                       block->data = data;
-                       block->size = size;
-                       block->condition = true;
-                       spin_unlock_bh(&ctx->block_lock);
-                       wake_up(&ctx->wait_queue);
-                       return 0;
-               }
-       }
-       spin_unlock_bh(&ctx->block_lock);
-       dev_dbg(ctx->dev,
-               "Block not found or a response received for a short msg for ipc %d, drv_id %d\n",
-               ipc, drv_id);
-       return -EINVAL;
-}
-
-int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed)
-{
-       struct sst_block *block = NULL, *__block;
-
-       dev_dbg(ctx->dev, "Enter\n");
-       spin_lock_bh(&ctx->block_lock);
-       list_for_each_entry_safe(block, __block, &ctx->block_list, node) {
-               if (block == freed) {
-                       pr_debug("pvt_id freed --> %d\n", freed->drv_id);
-                       /* toggle the index position of pvt_id */
-                       list_del(&freed->node);
-                       spin_unlock_bh(&ctx->block_lock);
-                       kfree(freed->data);
-                       freed->data = NULL;
-                       kfree(freed);
-                       return 0;
-               }
-       }
-       spin_unlock_bh(&ctx->block_lock);
-       dev_err(ctx->dev, "block is already freed!!!\n");
-       return -EINVAL;
-}
-
-int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx,
-               struct ipc_post *ipc_msg, bool sync)
-{
-       struct ipc_post *msg = ipc_msg;
-       union ipc_header_mrfld header;
-       unsigned int loop_count = 0;
-       int retval = 0;
-       unsigned long irq_flags;
-
-       dev_dbg(sst_drv_ctx->dev, "Enter: sync: %d\n", sync);
-       spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
-       header.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCX);
-       if (sync) {
-               while (header.p.header_high.part.busy) {
-                       if (loop_count > 25) {
-                               dev_err(sst_drv_ctx->dev,
-                                       "sst: Busy wait failed, cant send this msg\n");
-                               retval = -EBUSY;
-                               goto out;
-                       }
-                       cpu_relax();
-                       loop_count++;
-                       header.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCX);
-               }
-       } else {
-               if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) {
-                       /* queue is empty, nothing to send */
-                       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
-                       dev_dbg(sst_drv_ctx->dev,
-                                       "Empty msg queue... NO Action\n");
-                       return 0;
-               }
-
-               if (header.p.header_high.part.busy) {
-                       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
-                       dev_dbg(sst_drv_ctx->dev, "Busy not free... post later\n");
-                       return 0;
-               }
-
-               /* copy msg from list */
-               msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next,
-                               struct ipc_post, node);
-               list_del(&msg->node);
-       }
-       dev_dbg(sst_drv_ctx->dev, "sst: Post message: header = %x\n",
-                               msg->mrfld_header.p.header_high.full);
-       dev_dbg(sst_drv_ctx->dev, "sst: size = 0x%x\n",
-                       msg->mrfld_header.p.header_low_payload);
-
-       if (msg->mrfld_header.p.header_high.part.large)
-               memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND,
-                       msg->mailbox_data,
-                       msg->mrfld_header.p.header_low_payload);
-
-       sst_shim_write64(sst_drv_ctx->shim, SST_IPCX, msg->mrfld_header.full);
-
-out:
-       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
-       kfree(msg->mailbox_data);
-       kfree(msg);
-       return retval;
-}
-
-void intel_sst_clear_intr_mrfld(struct intel_sst_drv *sst_drv_ctx)
-{
-       union interrupt_reg_mrfld isr;
-       union interrupt_reg_mrfld imr;
-       union ipc_header_mrfld clear_ipc;
-       unsigned long irq_flags;
-
-       spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
-       imr.full = sst_shim_read64(sst_drv_ctx->shim, SST_IMRX);
-       isr.full = sst_shim_read64(sst_drv_ctx->shim, SST_ISRX);
-
-       /* write 1 to clear*/
-       isr.part.busy_interrupt = 1;
-       sst_shim_write64(sst_drv_ctx->shim, SST_ISRX, isr.full);
-
-       /* Set IA done bit */
-       clear_ipc.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCD);
-
-       clear_ipc.p.header_high.part.busy = 0;
-       clear_ipc.p.header_high.part.done = 1;
-       clear_ipc.p.header_low_payload = IPC_ACK_SUCCESS;
-       sst_shim_write64(sst_drv_ctx->shim, SST_IPCD, clear_ipc.full);
-       /* un mask busy interrupt */
-       imr.part.busy_interrupt = 0;
-       sst_shim_write64(sst_drv_ctx->shim, SST_IMRX, imr.full);
-       spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
-}
-
-
-/*
- * process_fw_init - process the FW init msg
- *
- * @msg: IPC message mailbox data from FW
- *
- * This function processes the FW init msg from FW
- * marks FW state and prints debug info of loaded FW
- */
-static void process_fw_init(struct intel_sst_drv *sst_drv_ctx,
-                       void *msg)
-{
-       struct ipc_header_fw_init *init =
-               (struct ipc_header_fw_init *)msg;
-       int retval = 0;
-
-       dev_dbg(sst_drv_ctx->dev, "*** FW Init msg came***\n");
-       if (init->result) {
-               sst_set_fw_state_locked(sst_drv_ctx, SST_RESET);
-               dev_err(sst_drv_ctx->dev, "FW Init failed, Error %x\n",
-                               init->result);
-               retval = init->result;
-               goto ret;
-       }
-
-ret:
-       sst_wake_up_block(sst_drv_ctx, retval, FW_DWNL_ID, 0 , NULL, 0);
-}
-
-static void process_fw_async_msg(struct intel_sst_drv *sst_drv_ctx,
-                       struct ipc_post *msg)
-{
-       u32 msg_id;
-       int str_id;
-       u32 data_size, i;
-       void *data_offset;
-       struct stream_info *stream;
-       union ipc_header_high msg_high;
-       u32 msg_low, pipe_id;
-
-       msg_high = msg->mrfld_header.p.header_high;
-       msg_low = msg->mrfld_header.p.header_low_payload;
-       msg_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->cmd_id;
-       data_offset = (msg->mailbox_data + sizeof(struct ipc_dsp_hdr));
-       data_size =  msg_low - (sizeof(struct ipc_dsp_hdr));
-
-       switch (msg_id) {
-       case IPC_SST_PERIOD_ELAPSED_MRFLD:
-               pipe_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->pipe_id;
-               str_id = get_stream_id_mrfld(sst_drv_ctx, pipe_id);
-               if (str_id > 0) {
-                       dev_dbg(sst_drv_ctx->dev,
-                               "Period elapsed rcvd for pipe id 0x%x\n",
-                               pipe_id);
-                       stream = &sst_drv_ctx->streams[str_id];
-                       if (stream->period_elapsed)
-                               stream->period_elapsed(stream->pcm_substream);
-                       if (stream->compr_cb)
-                               stream->compr_cb(stream->compr_cb_param);
-               }
-               break;
-
-       case IPC_IA_DRAIN_STREAM_MRFLD:
-               pipe_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->pipe_id;
-               str_id = get_stream_id_mrfld(sst_drv_ctx, pipe_id);
-               if (str_id > 0) {
-                       stream = &sst_drv_ctx->streams[str_id];
-                       if (stream->drain_notify)
-                               stream->drain_notify(stream->drain_cb_param);
-               }
-               break;
-
-       case IPC_IA_FW_ASYNC_ERR_MRFLD:
-               dev_err(sst_drv_ctx->dev, "FW sent async error msg:\n");
-               for (i = 0; i < (data_size/4); i++)
-                       print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE,
-                                       16, 4, data_offset, data_size, false);
-               break;
-
-       case IPC_IA_FW_INIT_CMPLT_MRFLD:
-               process_fw_init(sst_drv_ctx, data_offset);
-               break;
-
-       case IPC_IA_BUF_UNDER_RUN_MRFLD:
-               pipe_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->pipe_id;
-               str_id = get_stream_id_mrfld(sst_drv_ctx, pipe_id);
-               if (str_id > 0)
-                       dev_err(sst_drv_ctx->dev,
-                               "Buffer under-run for pipe:%#x str_id:%d\n",
-                               pipe_id, str_id);
-               break;
-
-       default:
-               dev_err(sst_drv_ctx->dev,
-                       "Unrecognized async msg from FW msg_id %#x\n", msg_id);
-       }
-}
-
-void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx,
-               struct ipc_post *msg)
-{
-       unsigned int drv_id;
-       void *data;
-       union ipc_header_high msg_high;
-       u32 msg_low;
-       struct ipc_dsp_hdr *dsp_hdr;
-       unsigned int cmd_id;
-
-       msg_high = msg->mrfld_header.p.header_high;
-       msg_low = msg->mrfld_header.p.header_low_payload;
-
-       dev_dbg(sst_drv_ctx->dev, "IPC process message header %x payload %x\n",
-                       msg->mrfld_header.p.header_high.full,
-                       msg->mrfld_header.p.header_low_payload);
-
-       drv_id = msg_high.part.drv_id;
-
-       /* Check for async messages first */
-       if (drv_id == SST_ASYNC_DRV_ID) {
-               /*FW sent async large message*/
-               process_fw_async_msg(sst_drv_ctx, msg);
-               return;
-       }
-
-       /* FW sent short error response for an IPC */
-       if (msg_high.part.result && drv_id && !msg_high.part.large) {
-               /* 32-bit FW error code in msg_low */
-               dev_err(sst_drv_ctx->dev, "FW sent error response 0x%x", msg_low);
-               sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
-                       msg_high.part.drv_id,
-                       msg_high.part.msg_id, NULL, 0);
-               return;
-       }
-
-       /*
-        * Process all valid responses
-        * if it is a large message, the payload contains the size to
-        * copy from mailbox
-        **/
-       if (msg_high.part.large) {
-               data = kzalloc(msg_low, GFP_KERNEL);
-               if (!data)
-                       return;
-               memcpy(data, (void *) msg->mailbox_data, msg_low);
-               /* Copy command id so that we can use to put sst to reset */
-               dsp_hdr = (struct ipc_dsp_hdr *)data;
-               cmd_id = dsp_hdr->cmd_id;
-               dev_dbg(sst_drv_ctx->dev, "cmd_id %d\n", dsp_hdr->cmd_id);
-               if (sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
-                               msg_high.part.drv_id,
-                               msg_high.part.msg_id, data, msg_low))
-                       kfree(data);
-       } else {
-               sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
-                               msg_high.part.drv_id,
-                               msg_high.part.msg_id, NULL, 0);
-       }
-
-}
diff --git a/sound/soc/intel/sst/sst_loader.c b/sound/soc/intel/sst/sst_loader.c
deleted file mode 100644 (file)
index 6622e66..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- *  sst_dsp.c - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14      Intel Corp
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This file contains all dsp controlling functions like firmware download,
- * setting/resetting dsp cores, etc
- */
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/firmware.h>
-#include <linux/dmaengine.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-#include "../common/sst-dsp.h"
-
-void memcpy32_toio(void __iomem *dst, const void *src, int count)
-{
-       /* __iowrite32_copy uses 32-bit count values so divide by 4 for
-        * right count in words
-        */
-       __iowrite32_copy(dst, src, count/4);
-}
-
-void memcpy32_fromio(void *dst, const void __iomem *src, int count)
-{
-       /* __iowrite32_copy uses 32-bit count values so divide by 4 for
-        * right count in words
-        */
-       __iowrite32_copy(dst, src, count/4);
-}
-
-/**
- * intel_sst_reset_dsp_mrfld - Resetting SST DSP
- *
- * This resets DSP in case of MRFLD platfroms
- */
-int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx)
-{
-       union config_status_reg_mrfld csr;
-
-       dev_dbg(sst_drv_ctx->dev, "sst: Resetting the DSP in mrfld\n");
-       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
-
-       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
-
-       csr.full |= 0x7;
-       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
-       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
-
-       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
-
-       csr.full &= ~(0x1);
-       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
-
-       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
-       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
-       return 0;
-}
-
-/**
- * sst_start_merrifield - Start the SST DSP processor
- *
- * This starts the DSP in MERRIFIELD platfroms
- */
-int sst_start_mrfld(struct intel_sst_drv *sst_drv_ctx)
-{
-       union config_status_reg_mrfld csr;
-
-       dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP in mrfld LALALALA\n");
-       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
-       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
-
-       csr.full |= 0x7;
-       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
-
-       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
-       dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
-
-       csr.part.xt_snoop = 1;
-       csr.full &= ~(0x5);
-       sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
-
-       csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
-       dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP_merrifield:%llx\n",
-                       csr.full);
-       return 0;
-}
-
-static int sst_validate_fw_image(struct intel_sst_drv *ctx, unsigned long size,
-               struct fw_module_header **module, u32 *num_modules)
-{
-       struct sst_fw_header *header;
-       const void *sst_fw_in_mem = ctx->fw_in_mem;
-
-       dev_dbg(ctx->dev, "Enter\n");
-
-       /* Read the header information from the data pointer */
-       header = (struct sst_fw_header *)sst_fw_in_mem;
-       dev_dbg(ctx->dev,
-               "header sign=%s size=%x modules=%x fmt=%x size=%zx\n",
-               header->signature, header->file_size, header->modules,
-               header->file_format, sizeof(*header));
-
-       /* verify FW */
-       if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) ||
-               (size != header->file_size + sizeof(*header))) {
-               /* Invalid FW signature */
-               dev_err(ctx->dev, "InvalidFW sign/filesize mismatch\n");
-               return -EINVAL;
-       }
-       *num_modules = header->modules;
-       *module = (void *)sst_fw_in_mem + sizeof(*header);
-
-       return 0;
-}
-
-/*
- * sst_fill_memcpy_list - Fill the memcpy list
- *
- * @memcpy_list: List to be filled
- * @destn: Destination addr to be filled in the list
- * @src: Source addr to be filled in the list
- * @size: Size to be filled in the list
- *
- * Adds the node to the list after required fields
- * are populated in the node
- */
-static int sst_fill_memcpy_list(struct list_head *memcpy_list,
-                       void *destn, const void *src, u32 size, bool is_io)
-{
-       struct sst_memcpy_list *listnode;
-
-       listnode = kzalloc(sizeof(*listnode), GFP_KERNEL);
-       if (listnode == NULL)
-               return -ENOMEM;
-       listnode->dstn = destn;
-       listnode->src = src;
-       listnode->size = size;
-       listnode->is_io = is_io;
-       list_add_tail(&listnode->memcpylist, memcpy_list);
-
-       return 0;
-}
-
-/**
- * sst_parse_module_memcpy - Parse audio FW modules and populate the memcpy list
- *
- * @sst_drv_ctx                : driver context
- * @module             : FW module header
- * @memcpy_list        : Pointer to the list to be populated
- * Create the memcpy list as the number of block to be copied
- * returns error or 0 if module sizes are proper
- */
-static int sst_parse_module_memcpy(struct intel_sst_drv *sst_drv_ctx,
-               struct fw_module_header *module, struct list_head *memcpy_list)
-{
-       struct fw_block_info *block;
-       u32 count;
-       int ret_val = 0;
-       void __iomem *ram_iomem;
-
-       dev_dbg(sst_drv_ctx->dev, "module sign %s size %x blocks %x type %x\n",
-                       module->signature, module->mod_size,
-                       module->blocks, module->type);
-       dev_dbg(sst_drv_ctx->dev, "module entrypoint 0x%x\n", module->entry_point);
-
-       block = (void *)module + sizeof(*module);
-
-       for (count = 0; count < module->blocks; count++) {
-               if (block->size <= 0) {
-                       dev_err(sst_drv_ctx->dev, "block size invalid\n");
-                       return -EINVAL;
-               }
-               switch (block->type) {
-               case SST_IRAM:
-                       ram_iomem = sst_drv_ctx->iram;
-                       break;
-               case SST_DRAM:
-                       ram_iomem = sst_drv_ctx->dram;
-                       break;
-               case SST_DDR:
-                       ram_iomem = sst_drv_ctx->ddr;
-                       break;
-               case SST_CUSTOM_INFO:
-                       block = (void *)block + sizeof(*block) + block->size;
-                       continue;
-               default:
-                       dev_err(sst_drv_ctx->dev, "wrong ram type0x%x in block0x%x\n",
-                                       block->type, count);
-                       return -EINVAL;
-               }
-
-               ret_val = sst_fill_memcpy_list(memcpy_list,
-                               ram_iomem + block->ram_offset,
-                               (void *)block + sizeof(*block), block->size, 1);
-               if (ret_val)
-                       return ret_val;
-
-               block = (void *)block + sizeof(*block) + block->size;
-       }
-       return 0;
-}
-
-/**
- * sst_parse_fw_memcpy - parse the firmware image & populate the list for memcpy
- *
- * @ctx                        : pointer to drv context
- * @size               : size of the firmware
- * @fw_list            : pointer to list_head to be populated
- * This function parses the FW image and saves the parsed image in the list
- * for memcpy
- */
-static int sst_parse_fw_memcpy(struct intel_sst_drv *ctx, unsigned long size,
-                               struct list_head *fw_list)
-{
-       struct fw_module_header *module;
-       u32 count, num_modules;
-       int ret_val;
-
-       ret_val = sst_validate_fw_image(ctx, size, &module, &num_modules);
-       if (ret_val)
-               return ret_val;
-
-       for (count = 0; count < num_modules; count++) {
-               ret_val = sst_parse_module_memcpy(ctx, module, fw_list);
-               if (ret_val)
-                       return ret_val;
-               module = (void *)module + sizeof(*module) + module->mod_size;
-       }
-
-       return 0;
-}
-
-/**
- * sst_do_memcpy - function initiates the memcpy
- *
- * @memcpy_list: Pter to memcpy list on which the memcpy needs to be initiated
- *
- * Triggers the memcpy
- */
-static void sst_do_memcpy(struct list_head *memcpy_list)
-{
-       struct sst_memcpy_list *listnode;
-
-       list_for_each_entry(listnode, memcpy_list, memcpylist) {
-               if (listnode->is_io == true)
-                       memcpy32_toio((void __iomem *)listnode->dstn,
-                                       listnode->src, listnode->size);
-               else
-                       memcpy(listnode->dstn, listnode->src, listnode->size);
-       }
-}
-
-void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx)
-{
-       struct sst_memcpy_list *listnode, *tmplistnode;
-
-       /* Free the list */
-       if (!list_empty(&sst_drv_ctx->memcpy_list)) {
-               list_for_each_entry_safe(listnode, tmplistnode,
-                               &sst_drv_ctx->memcpy_list, memcpylist) {
-                       list_del(&listnode->memcpylist);
-                       kfree(listnode);
-               }
-       }
-}
-
-static int sst_cache_and_parse_fw(struct intel_sst_drv *sst,
-               const struct firmware *fw)
-{
-       int retval = 0;
-
-       sst->fw_in_mem = kzalloc(fw->size, GFP_KERNEL);
-       if (!sst->fw_in_mem) {
-               retval = -ENOMEM;
-               goto end_release;
-       }
-       dev_dbg(sst->dev, "copied fw to %p", sst->fw_in_mem);
-       dev_dbg(sst->dev, "phys: %lx", (unsigned long)virt_to_phys(sst->fw_in_mem));
-       memcpy(sst->fw_in_mem, fw->data, fw->size);
-       retval = sst_parse_fw_memcpy(sst, fw->size, &sst->memcpy_list);
-       if (retval) {
-               dev_err(sst->dev, "Failed to parse fw\n");
-               kfree(sst->fw_in_mem);
-               sst->fw_in_mem = NULL;
-       }
-
-end_release:
-       release_firmware(fw);
-       return retval;
-
-}
-
-void sst_firmware_load_cb(const struct firmware *fw, void *context)
-{
-       struct intel_sst_drv *ctx = context;
-
-       dev_dbg(ctx->dev, "Enter\n");
-
-       if (fw == NULL) {
-               dev_err(ctx->dev, "request fw failed\n");
-               return;
-       }
-
-       mutex_lock(&ctx->sst_lock);
-
-       if (ctx->sst_state != SST_RESET ||
-                       ctx->fw_in_mem != NULL) {
-               release_firmware(fw);
-               mutex_unlock(&ctx->sst_lock);
-               return;
-       }
-
-       dev_dbg(ctx->dev, "Request Fw completed\n");
-       sst_cache_and_parse_fw(ctx, fw);
-       mutex_unlock(&ctx->sst_lock);
-}
-
-/*
- * sst_request_fw - requests audio fw from kernel and saves a copy
- *
- * This function requests the SST FW from the kernel, parses it and
- * saves a copy in the driver context
- */
-static int sst_request_fw(struct intel_sst_drv *sst)
-{
-       int retval = 0;
-       const struct firmware *fw;
-
-       retval = request_firmware(&fw, sst->firmware_name, sst->dev);
-       if (fw == NULL) {
-               dev_err(sst->dev, "fw is returning as null\n");
-               return -EINVAL;
-       }
-       if (retval) {
-               dev_err(sst->dev, "request fw failed %d\n", retval);
-               return retval;
-       }
-       mutex_lock(&sst->sst_lock);
-       retval = sst_cache_and_parse_fw(sst, fw);
-       mutex_unlock(&sst->sst_lock);
-
-       return retval;
-}
-
-/*
- * Writing the DDR physical base to DCCM offset
- * so that FW can use it to setup TLB
- */
-static void sst_dccm_config_write(void __iomem *dram_base,
-               unsigned int ddr_base)
-{
-       void __iomem *addr;
-       u32 bss_reset = 0;
-
-       addr = (void __iomem *)(dram_base + MRFLD_FW_DDR_BASE_OFFSET);
-       memcpy32_toio(addr, (void *)&ddr_base, sizeof(u32));
-       bss_reset |= (1 << MRFLD_FW_BSS_RESET_BIT);
-       addr = (void __iomem *)(dram_base + MRFLD_FW_FEATURE_BASE_OFFSET);
-       memcpy32_toio(addr, &bss_reset, sizeof(u32));
-
-}
-
-void sst_post_download_mrfld(struct intel_sst_drv *ctx)
-{
-       sst_dccm_config_write(ctx->dram, ctx->ddr_base);
-       dev_dbg(ctx->dev, "config written to DCCM\n");
-}
-
-/**
- * sst_load_fw - function to load FW into DSP
- * Transfers the FW to DSP using dma/memcpy
- */
-int sst_load_fw(struct intel_sst_drv *sst_drv_ctx)
-{
-       int ret_val = 0;
-       struct sst_block *block;
-
-       dev_dbg(sst_drv_ctx->dev, "sst_load_fw\n");
-
-       if (sst_drv_ctx->sst_state !=  SST_RESET ||
-                       sst_drv_ctx->sst_state == SST_SHUTDOWN)
-               return -EAGAIN;
-
-       if (!sst_drv_ctx->fw_in_mem) {
-               dev_dbg(sst_drv_ctx->dev, "sst: FW not in memory retry to download\n");
-               ret_val = sst_request_fw(sst_drv_ctx);
-               if (ret_val)
-                       return ret_val;
-       }
-
-       BUG_ON(!sst_drv_ctx->fw_in_mem);
-       block = sst_create_block(sst_drv_ctx, 0, FW_DWNL_ID);
-       if (block == NULL)
-               return -ENOMEM;
-
-       /* Prevent C-states beyond C6 */
-       pm_qos_update_request(sst_drv_ctx->qos, 0);
-
-       sst_drv_ctx->sst_state = SST_FW_LOADING;
-
-       ret_val = sst_drv_ctx->ops->reset(sst_drv_ctx);
-       if (ret_val)
-               goto restore;
-
-       sst_do_memcpy(&sst_drv_ctx->memcpy_list);
-
-       /* Write the DRAM/DCCM config before enabling FW */
-       if (sst_drv_ctx->ops->post_download)
-               sst_drv_ctx->ops->post_download(sst_drv_ctx);
-
-       /* bring sst out of reset */
-       ret_val = sst_drv_ctx->ops->start(sst_drv_ctx);
-       if (ret_val)
-               goto restore;
-
-       ret_val = sst_wait_timeout(sst_drv_ctx, block);
-       if (ret_val) {
-               dev_err(sst_drv_ctx->dev, "fw download failed %d\n" , ret_val);
-               /* FW download failed due to timeout */
-               ret_val = -EBUSY;
-
-       }
-
-
-restore:
-       /* Re-enable Deeper C-states beyond C6 */
-       pm_qos_update_request(sst_drv_ctx->qos, PM_QOS_DEFAULT_VALUE);
-       sst_free_block(sst_drv_ctx, block);
-       dev_dbg(sst_drv_ctx->dev, "fw load successful!!!\n");
-
-       if (sst_drv_ctx->ops->restore_dsp_context)
-               sst_drv_ctx->ops->restore_dsp_context();
-       sst_drv_ctx->sst_state = SST_FW_RUNNING;
-       return ret_val;
-}
-
diff --git a/sound/soc/intel/sst/sst_pci.c b/sound/soc/intel/sst/sst_pci.c
deleted file mode 100644 (file)
index 3a0b3bf..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- *  sst_pci.c - SST (LPE) driver init file for pci enumeration.
- *
- *  Copyright (C) 2008-14      Intel Corp
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-
-static int sst_platform_get_resources(struct intel_sst_drv *ctx)
-{
-       int ddr_base, ret = 0;
-       struct pci_dev *pci = ctx->pci;
-
-       ret = pci_request_regions(pci, SST_DRV_NAME);
-       if (ret)
-               return ret;
-
-       /* map registers */
-       /* DDR base */
-       if (ctx->dev_id == SST_MRFLD_PCI_ID) {
-               ctx->ddr_base = pci_resource_start(pci, 0);
-               /* check that the relocated IMR base matches with FW Binary */
-               ddr_base = relocate_imr_addr_mrfld(ctx->ddr_base);
-               if (!ctx->pdata->lib_info) {
-                       dev_err(ctx->dev, "lib_info pointer NULL\n");
-                       ret = -EINVAL;
-                       goto do_release_regions;
-               }
-               if (ddr_base != ctx->pdata->lib_info->mod_base) {
-                       dev_err(ctx->dev,
-                                       "FW LSP DDR BASE does not match with IFWI\n");
-                       ret = -EINVAL;
-                       goto do_release_regions;
-               }
-               ctx->ddr_end = pci_resource_end(pci, 0);
-
-               ctx->ddr = pcim_iomap(pci, 0,
-                                       pci_resource_len(pci, 0));
-               if (!ctx->ddr) {
-                       ret = -EINVAL;
-                       goto do_release_regions;
-               }
-               dev_dbg(ctx->dev, "sst: DDR Ptr %p\n", ctx->ddr);
-       } else {
-               ctx->ddr = NULL;
-       }
-       /* SHIM */
-       ctx->shim_phy_add = pci_resource_start(pci, 1);
-       ctx->shim = pcim_iomap(pci, 1, pci_resource_len(pci, 1));
-       if (!ctx->shim) {
-               ret = -EINVAL;
-               goto do_release_regions;
-       }
-       dev_dbg(ctx->dev, "SST Shim Ptr %p\n", ctx->shim);
-
-       /* Shared SRAM */
-       ctx->mailbox_add = pci_resource_start(pci, 2);
-       ctx->mailbox = pcim_iomap(pci, 2, pci_resource_len(pci, 2));
-       if (!ctx->mailbox) {
-               ret = -EINVAL;
-               goto do_release_regions;
-       }
-       dev_dbg(ctx->dev, "SRAM Ptr %p\n", ctx->mailbox);
-
-       /* IRAM */
-       ctx->iram_end = pci_resource_end(pci, 3);
-       ctx->iram_base = pci_resource_start(pci, 3);
-       ctx->iram = pcim_iomap(pci, 3, pci_resource_len(pci, 3));
-       if (!ctx->iram) {
-               ret = -EINVAL;
-               goto do_release_regions;
-       }
-       dev_dbg(ctx->dev, "IRAM Ptr %p\n", ctx->iram);
-
-       /* DRAM */
-       ctx->dram_end = pci_resource_end(pci, 4);
-       ctx->dram_base = pci_resource_start(pci, 4);
-       ctx->dram = pcim_iomap(pci, 4, pci_resource_len(pci, 4));
-       if (!ctx->dram) {
-               ret = -EINVAL;
-               goto do_release_regions;
-       }
-       dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram);
-do_release_regions:
-       pci_release_regions(pci);
-       return 0;
-}
-
-/*
- * intel_sst_probe - PCI probe function
- *
- * @pci:       PCI device structure
- * @pci_id: PCI device ID structure
- *
- */
-static int intel_sst_probe(struct pci_dev *pci,
-                       const struct pci_device_id *pci_id)
-{
-       int ret = 0;
-       struct intel_sst_drv *sst_drv_ctx;
-       struct sst_platform_info *sst_pdata = pci->dev.platform_data;
-
-       dev_dbg(&pci->dev, "Probe for DID %x\n", pci->device);
-       ret = sst_alloc_drv_context(&sst_drv_ctx, &pci->dev, pci->device);
-       if (ret < 0)
-               return ret;
-
-       sst_drv_ctx->pdata = sst_pdata;
-       sst_drv_ctx->irq_num = pci->irq;
-       snprintf(sst_drv_ctx->firmware_name, sizeof(sst_drv_ctx->firmware_name),
-                       "%s%04x%s", "fw_sst_",
-                       sst_drv_ctx->dev_id, ".bin");
-
-       ret = sst_context_init(sst_drv_ctx);
-       if (ret < 0)
-               return ret;
-
-       /* Init the device */
-       ret = pcim_enable_device(pci);
-       if (ret) {
-               dev_err(sst_drv_ctx->dev,
-                       "device can't be enabled. Returned err: %d\n", ret);
-               goto do_free_drv_ctx;
-       }
-       sst_drv_ctx->pci = pci_dev_get(pci);
-       ret = sst_platform_get_resources(sst_drv_ctx);
-       if (ret < 0)
-               goto do_free_drv_ctx;
-
-       pci_set_drvdata(pci, sst_drv_ctx);
-       sst_configure_runtime_pm(sst_drv_ctx);
-
-       return ret;
-
-do_free_drv_ctx:
-       sst_context_cleanup(sst_drv_ctx);
-       dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret);
-       return ret;
-}
-
-/**
- * intel_sst_remove - PCI remove function
- *
- * @pci:       PCI device structure
- *
- * This function is called by OS when a device is unloaded
- * This frees the interrupt etc
- */
-static void intel_sst_remove(struct pci_dev *pci)
-{
-       struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci);
-
-       sst_context_cleanup(sst_drv_ctx);
-       pci_dev_put(sst_drv_ctx->pci);
-       pci_release_regions(pci);
-       pci_set_drvdata(pci, NULL);
-}
-
-/* PCI Routines */
-static struct pci_device_id intel_sst_ids[] = {
-       { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0},
-       { 0, }
-};
-
-static struct pci_driver sst_driver = {
-       .name = SST_DRV_NAME,
-       .id_table = intel_sst_ids,
-       .probe = intel_sst_probe,
-       .remove = intel_sst_remove,
-#ifdef CONFIG_PM
-       .driver = {
-               .pm = &intel_sst_pm,
-       },
-#endif
-};
-
-module_pci_driver(sst_driver);
-
-MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver");
-MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
-MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
-MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("sst");
diff --git a/sound/soc/intel/sst/sst_pvt.c b/sound/soc/intel/sst/sst_pvt.c
deleted file mode 100644 (file)
index 2bb0e9e..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- *  sst_pvt.c - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14      Intel Corp
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/kobject.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <sound/asound.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-#include "../common/sst-dsp.h"
-
-int sst_shim_write(void __iomem *addr, int offset, int value)
-{
-       writel(value, addr + offset);
-       return 0;
-}
-
-u32 sst_shim_read(void __iomem *addr, int offset)
-{
-       return readl(addr + offset);
-}
-
-u64 sst_reg_read64(void __iomem *addr, int offset)
-{
-       u64 val = 0;
-
-       memcpy_fromio(&val, addr + offset, sizeof(val));
-
-       return val;
-}
-
-int sst_shim_write64(void __iomem *addr, int offset, u64 value)
-{
-       memcpy_toio(addr + offset, &value, sizeof(value));
-       return 0;
-}
-
-u64 sst_shim_read64(void __iomem *addr, int offset)
-{
-       u64 val = 0;
-
-       memcpy_fromio(&val, addr + offset, sizeof(val));
-       return val;
-}
-
-void sst_set_fw_state_locked(
-               struct intel_sst_drv *sst_drv_ctx, int sst_state)
-{
-       mutex_lock(&sst_drv_ctx->sst_lock);
-       sst_drv_ctx->sst_state = sst_state;
-       mutex_unlock(&sst_drv_ctx->sst_lock);
-}
-
-/*
- * sst_wait_interruptible - wait on event
- *
- * @sst_drv_ctx: Driver context
- * @block: Driver block to wait on
- *
- * This function waits without a timeout (and is interruptable) for a
- * given block event
- */
-int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
-                               struct sst_block *block)
-{
-       int retval = 0;
-
-       if (!wait_event_interruptible(sst_drv_ctx->wait_queue,
-                               block->condition)) {
-               /* event wake */
-               if (block->ret_code < 0) {
-                       dev_err(sst_drv_ctx->dev,
-                               "stream failed %d\n", block->ret_code);
-                       retval = -EBUSY;
-               } else {
-                       dev_dbg(sst_drv_ctx->dev, "event up\n");
-                       retval = 0;
-               }
-       } else {
-               dev_err(sst_drv_ctx->dev, "signal interrupted\n");
-               retval = -EINTR;
-       }
-       return retval;
-
-}
-
-unsigned long long read_shim_data(struct intel_sst_drv *sst, int addr)
-{
-       unsigned long long val = 0;
-
-       switch (sst->dev_id) {
-       case SST_MRFLD_PCI_ID:
-       case SST_BYT_ACPI_ID:
-               val = sst_shim_read64(sst->shim, addr);
-               break;
-       }
-       return val;
-}
-
-void write_shim_data(struct intel_sst_drv *sst, int addr,
-                               unsigned long long data)
-{
-       switch (sst->dev_id) {
-       case SST_MRFLD_PCI_ID:
-       case SST_BYT_ACPI_ID:
-               sst_shim_write64(sst->shim, addr, (u64) data);
-               break;
-       }
-}
-
-/*
- * sst_wait_timeout - wait on event for timeout
- *
- * @sst_drv_ctx: Driver context
- * @block: Driver block to wait on
- *
- * This function waits with a timeout value (and is not interruptible) on a
- * given block event
- */
-int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, struct sst_block *block)
-{
-       int retval = 0;
-
-       /*
-        * NOTE:
-        * Observed that FW processes the alloc msg and replies even
-        * before the alloc thread has finished execution
-        */
-       dev_dbg(sst_drv_ctx->dev,
-               "waiting for condition %x ipc %d drv_id %d\n",
-               block->condition, block->msg_id, block->drv_id);
-       if (wait_event_timeout(sst_drv_ctx->wait_queue,
-                               block->condition,
-                               msecs_to_jiffies(SST_BLOCK_TIMEOUT))) {
-               /* event wake */
-               dev_dbg(sst_drv_ctx->dev, "Event wake %x\n",
-                               block->condition);
-               dev_dbg(sst_drv_ctx->dev, "message ret: %d\n",
-                               block->ret_code);
-               retval = -block->ret_code;
-       } else {
-               block->on = false;
-               dev_err(sst_drv_ctx->dev,
-                       "Wait timed-out condition:%#x, msg_id:%#x fw_state %#x\n",
-                       block->condition, block->msg_id, sst_drv_ctx->sst_state);
-               sst_drv_ctx->sst_state = SST_RESET;
-
-               retval = -EBUSY;
-       }
-       return retval;
-}
-
-/*
- * sst_create_ipc_msg - create a IPC message
- *
- * @arg: ipc message
- * @large: large or short message
- *
- * this function allocates structures to send a large or short
- * message to the firmware
- */
-int sst_create_ipc_msg(struct ipc_post **arg, bool large)
-{
-       struct ipc_post *msg;
-
-       msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC);
-       if (!msg)
-               return -ENOMEM;
-       if (large) {
-               msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
-               if (!msg->mailbox_data) {
-                       kfree(msg);
-                       return -ENOMEM;
-               }
-       } else {
-               msg->mailbox_data = NULL;
-       }
-       msg->is_large = large;
-       *arg = msg;
-       return 0;
-}
-
-/*
- * sst_create_block_and_ipc_msg - Creates IPC message and sst block
- * @arg: passed to sst_create_ipc_message API
- * @large: large or short message
- * @sst_drv_ctx: sst driver context
- * @block: return block allocated
- * @msg_id: IPC
- * @drv_id: stream id or private id
- */
-int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large,
-               struct intel_sst_drv *sst_drv_ctx, struct sst_block **block,
-               u32 msg_id, u32 drv_id)
-{
-       int retval = 0;
-
-       retval = sst_create_ipc_msg(arg, large);
-       if (retval)
-               return retval;
-       *block = sst_create_block(sst_drv_ctx, msg_id, drv_id);
-       if (*block == NULL) {
-               kfree(*arg);
-               return -ENOMEM;
-       }
-       return retval;
-}
-
-/*
- * sst_clean_stream - clean the stream context
- *
- * @stream: stream structure
- *
- * this function resets the stream contexts
- * should be called in free
- */
-void sst_clean_stream(struct stream_info *stream)
-{
-       stream->status = STREAM_UN_INIT;
-       stream->prev = STREAM_UN_INIT;
-       mutex_lock(&stream->lock);
-       stream->cumm_bytes = 0;
-       mutex_unlock(&stream->lock);
-}
-
-int sst_prepare_and_post_msg(struct intel_sst_drv *sst,
-               int task_id, int ipc_msg, int cmd_id, int pipe_id,
-               size_t mbox_data_len, const void *mbox_data, void **data,
-               bool large, bool fill_dsp, bool sync, bool response)
-{
-       struct ipc_post *msg = NULL;
-       struct ipc_dsp_hdr dsp_hdr;
-       struct sst_block *block;
-       int ret = 0, pvt_id;
-
-       pvt_id = sst_assign_pvt_id(sst);
-       if (pvt_id < 0)
-               return pvt_id;
-
-       if (response)
-               ret = sst_create_block_and_ipc_msg(
-                               &msg, large, sst, &block, ipc_msg, pvt_id);
-       else
-               ret = sst_create_ipc_msg(&msg, large);
-
-       if (ret < 0) {
-               test_and_clear_bit(pvt_id, &sst->pvt_id);
-               return -ENOMEM;
-       }
-
-       dev_dbg(sst->dev, "pvt_id = %d, pipe id = %d, task = %d ipc_msg: %d\n",
-                pvt_id, pipe_id, task_id, ipc_msg);
-       sst_fill_header_mrfld(&msg->mrfld_header, ipc_msg,
-                                       task_id, large, pvt_id);
-       msg->mrfld_header.p.header_low_payload = sizeof(dsp_hdr) + mbox_data_len;
-       msg->mrfld_header.p.header_high.part.res_rqd = !sync;
-       dev_dbg(sst->dev, "header:%x\n",
-                       msg->mrfld_header.p.header_high.full);
-       dev_dbg(sst->dev, "response rqd: %x",
-                       msg->mrfld_header.p.header_high.part.res_rqd);
-       dev_dbg(sst->dev, "msg->mrfld_header.p.header_low_payload:%d",
-                       msg->mrfld_header.p.header_low_payload);
-       if (fill_dsp) {
-               sst_fill_header_dsp(&dsp_hdr, cmd_id, pipe_id, mbox_data_len);
-               memcpy(msg->mailbox_data, &dsp_hdr, sizeof(dsp_hdr));
-               if (mbox_data_len) {
-                       memcpy(msg->mailbox_data + sizeof(dsp_hdr),
-                                       mbox_data, mbox_data_len);
-               }
-       }
-
-       if (sync)
-               sst->ops->post_message(sst, msg, true);
-       else
-               sst_add_to_dispatch_list_and_post(sst, msg);
-
-       if (response) {
-               ret = sst_wait_timeout(sst, block);
-               if (ret < 0) {
-                       goto out;
-               } else if(block->data) {
-                       if (!data)
-                               goto out;
-                       *data = kzalloc(block->size, GFP_KERNEL);
-                       if (!(*data)) {
-                               ret = -ENOMEM;
-                               goto out;
-                       } else
-                               memcpy(data, (void *) block->data, block->size);
-               }
-       }
-out:
-       if (response)
-               sst_free_block(sst, block);
-       test_and_clear_bit(pvt_id, &sst->pvt_id);
-       return ret;
-}
-
-int sst_pm_runtime_put(struct intel_sst_drv *sst_drv)
-{
-       int ret;
-
-       pm_runtime_mark_last_busy(sst_drv->dev);
-       ret = pm_runtime_put_autosuspend(sst_drv->dev);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-void sst_fill_header_mrfld(union ipc_header_mrfld *header,
-                               int msg, int task_id, int large, int drv_id)
-{
-       header->full = 0;
-       header->p.header_high.part.msg_id = msg;
-       header->p.header_high.part.task_id = task_id;
-       header->p.header_high.part.large = large;
-       header->p.header_high.part.drv_id = drv_id;
-       header->p.header_high.part.done = 0;
-       header->p.header_high.part.busy = 1;
-       header->p.header_high.part.res_rqd = 1;
-}
-
-void sst_fill_header_dsp(struct ipc_dsp_hdr *dsp, int msg,
-                                       int pipe_id, int len)
-{
-       dsp->cmd_id = msg;
-       dsp->mod_index_id = 0xff;
-       dsp->pipe_id = pipe_id;
-       dsp->length = len;
-       dsp->mod_id = 0;
-}
-
-#define SST_MAX_BLOCKS 15
-/*
- * sst_assign_pvt_id - assign a pvt id for stream
- *
- * @sst_drv_ctx : driver context
- *
- * this function assigns a private id for calls that dont have stream
- * context yet, should be called with lock held
- * uses bits for the id, and finds first free bits and assigns that
- */
-int sst_assign_pvt_id(struct intel_sst_drv *drv)
-{
-       int local;
-
-       spin_lock(&drv->block_lock);
-       /* find first zero index from lsb */
-       local = ffz(drv->pvt_id);
-       dev_dbg(drv->dev, "pvt_id assigned --> %d\n", local);
-       if (local >= SST_MAX_BLOCKS){
-               spin_unlock(&drv->block_lock);
-               dev_err(drv->dev, "PVT _ID error: no free id blocks ");
-               return -EINVAL;
-       }
-       /* toggle the index */
-       change_bit(local, &drv->pvt_id);
-       spin_unlock(&drv->block_lock);
-       return local;
-}
-
-void sst_init_stream(struct stream_info *stream,
-               int codec, int sst_id, int ops, u8 slot)
-{
-       stream->status = STREAM_INIT;
-       stream->prev = STREAM_UN_INIT;
-       stream->ops = ops;
-}
-
-int sst_validate_strid(
-               struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       if (str_id <= 0 || str_id > sst_drv_ctx->info.max_streams) {
-               dev_err(sst_drv_ctx->dev,
-                       "SST ERR: invalid stream id : %d, max %d\n",
-                       str_id, sst_drv_ctx->info.max_streams);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-struct stream_info *get_stream_info(
-               struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       if (sst_validate_strid(sst_drv_ctx, str_id))
-               return NULL;
-       return &sst_drv_ctx->streams[str_id];
-}
-
-int get_stream_id_mrfld(struct intel_sst_drv *sst_drv_ctx,
-               u32 pipe_id)
-{
-       int i;
-
-       for (i = 1; i <= sst_drv_ctx->info.max_streams; i++)
-               if (pipe_id == sst_drv_ctx->streams[i].pipe_id)
-                       return i;
-
-       dev_dbg(sst_drv_ctx->dev, "no such pipe_id(%u)", pipe_id);
-       return -1;
-}
-
-u32 relocate_imr_addr_mrfld(u32 base_addr)
-{
-       /* Get the difference from 512MB aligned base addr */
-       /* relocate the base */
-       base_addr = MRFLD_FW_VIRTUAL_BASE + (base_addr % (512 * 1024 * 1024));
-       return base_addr;
-}
-EXPORT_SYMBOL_GPL(relocate_imr_addr_mrfld);
-
-void sst_add_to_dispatch_list_and_post(struct intel_sst_drv *sst,
-                                               struct ipc_post *msg)
-{
-       unsigned long irq_flags;
-
-       spin_lock_irqsave(&sst->ipc_spin_lock, irq_flags);
-       list_add_tail(&msg->node, &sst->ipc_dispatch_list);
-       spin_unlock_irqrestore(&sst->ipc_spin_lock, irq_flags);
-       sst->ops->post_message(sst, NULL, false);
-}
diff --git a/sound/soc/intel/sst/sst_stream.c b/sound/soc/intel/sst/sst_stream.c
deleted file mode 100644 (file)
index 7638fca..0000000
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- *  sst_stream.c - Intel SST Driver for audio engine
- *
- *  Copyright (C) 2008-14 Intel Corp
- *  Authors:   Vinod Koul <vinod.koul@intel.com>
- *             Harsha Priya <priya.harsha@intel.com>
- *             Dharageswari R <dharageswari.r@intel.com>
- *             KP Jeeja <jeeja.kp@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/compress_driver.h>
-#include <asm/platform_sst_audio.h>
-#include "../sst-mfld-platform.h"
-#include "sst.h"
-#include "../common/sst-dsp.h"
-
-int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
-{
-       struct snd_sst_alloc_mrfld alloc_param;
-       struct snd_sst_params *str_params;
-       struct snd_sst_tstamp fw_tstamp;
-       struct stream_info *str_info;
-       struct snd_sst_alloc_response *response;
-       unsigned int str_id, pipe_id, task_id;
-       int i, num_ch, ret = 0;
-       void *data = NULL;
-
-       dev_dbg(sst_drv_ctx->dev, "Enter\n");
-       BUG_ON(!params);
-
-       str_params = (struct snd_sst_params *)params;
-       memset(&alloc_param, 0, sizeof(alloc_param));
-       alloc_param.operation = str_params->ops;
-       alloc_param.codec_type = str_params->codec;
-       alloc_param.sg_count = str_params->aparams.sg_count;
-       alloc_param.ring_buf_info[0].addr =
-               str_params->aparams.ring_buf_info[0].addr;
-       alloc_param.ring_buf_info[0].size =
-               str_params->aparams.ring_buf_info[0].size;
-       alloc_param.frag_size = str_params->aparams.frag_size;
-
-       memcpy(&alloc_param.codec_params, &str_params->sparams,
-                       sizeof(struct snd_sst_stream_params));
-
-       /*
-        * fill channel map params for multichannel support.
-        * Ideally channel map should be received from upper layers
-        * for multichannel support.
-        * Currently hardcoding as per FW reqm.
-        */
-       num_ch = sst_get_num_channel(str_params);
-       for (i = 0; i < 8; i++) {
-               if (i < num_ch)
-                       alloc_param.codec_params.uc.pcm_params.channel_map[i] = i;
-               else
-                       alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF;
-       }
-
-       str_id = str_params->stream_id;
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (str_info == NULL) {
-               dev_err(sst_drv_ctx->dev, "get stream info returned null\n");
-               return -EINVAL;
-       }
-
-       pipe_id = str_params->device_type;
-       task_id = str_params->task;
-       sst_drv_ctx->streams[str_id].pipe_id = pipe_id;
-       sst_drv_ctx->streams[str_id].task_id = task_id;
-       sst_drv_ctx->streams[str_id].num_ch = num_ch;
-
-       if (sst_drv_ctx->info.lpe_viewpt_rqd)
-               alloc_param.ts = sst_drv_ctx->info.mailbox_start +
-                       sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
-       else
-               alloc_param.ts = sst_drv_ctx->mailbox_add +
-                       sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
-
-       dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
-                       alloc_param.ts);
-       dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
-                       pipe_id, task_id);
-
-       /* allocate device type context */
-       sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type,
-                       str_id, alloc_param.operation, 0);
-
-       dev_info(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
-                       str_id, pipe_id);
-       ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
-                       IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
-                       &alloc_param, data, true, true, false, true);
-
-       if (ret < 0) {
-               dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
-               /* alloc failed, so reset the state to uninit */
-               str_info->status = STREAM_UN_INIT;
-               str_id = ret;
-       } else if (data) {
-               response = (struct snd_sst_alloc_response *)data;
-               ret = response->str_type.result;
-               if (!ret)
-                       goto out;
-               dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
-               if (ret == SST_ERR_STREAM_IN_USE) {
-                       dev_err(sst_drv_ctx->dev,
-                               "FW not in clean state, send free for:%d\n", str_id);
-                       sst_free_stream(sst_drv_ctx, str_id);
-               }
-               str_id = -ret;
-       }
-out:
-       kfree(data);
-       return str_id;
-}
-
-/**
-* sst_start_stream - Send msg for a starting stream
-* @str_id:      stream ID
-*
-* This function is called by any function which wants to start
-* a stream.
-*/
-int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-       u16 data = 0;
-
-       dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       if (str_info->status != STREAM_RUNNING)
-               return -EBADRQC;
-
-       retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
-                       IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id,
-                       sizeof(u16), &data, NULL, true, true, true, false);
-
-       return retval;
-}
-
-int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
-               struct snd_sst_bytes_v2 *bytes)
-{      struct ipc_post *msg = NULL;
-       u32 length;
-       int pvt_id, ret = 0;
-       struct sst_block *block = NULL;
-
-       dev_dbg(sst_drv_ctx->dev,
-               "type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n",
-               bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id,
-               bytes->pipe_id, bytes->len);
-
-       if (sst_create_ipc_msg(&msg, true))
-               return -ENOMEM;
-
-       pvt_id = sst_assign_pvt_id(sst_drv_ctx);
-       sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg,
-                       bytes->task_id, 1, pvt_id);
-       msg->mrfld_header.p.header_high.part.res_rqd = bytes->block;
-       length = bytes->len;
-       msg->mrfld_header.p.header_low_payload = length;
-       dev_dbg(sst_drv_ctx->dev, "length is %d\n", length);
-       memcpy(msg->mailbox_data, &bytes->bytes, bytes->len);
-       if (bytes->block) {
-               block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id);
-               if (block == NULL) {
-                       kfree(msg);
-                       ret = -ENOMEM;
-                       goto out;
-               }
-       }
-
-       sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg);
-       dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d",
-                       msg->mrfld_header.p.header_low_payload);
-
-       if (bytes->block) {
-               ret = sst_wait_timeout(sst_drv_ctx, block);
-               if (ret) {
-                       dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
-                       sst_free_block(sst_drv_ctx, block);
-                       goto out;
-               }
-       }
-       if (bytes->type == SND_SST_BYTES_GET) {
-               /*
-                * copy the reply and send back
-                * we need to update only sz and payload
-                */
-               if (bytes->block) {
-                       unsigned char *r = block->data;
-
-                       dev_dbg(sst_drv_ctx->dev, "read back %d bytes",
-                                       bytes->len);
-                       memcpy(bytes->bytes, r, bytes->len);
-               }
-       }
-       if (bytes->block)
-               sst_free_block(sst_drv_ctx, block);
-out:
-       test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
-       return 0;
-}
-
-/*
- * sst_pause_stream - Send msg for a pausing stream
- * @str_id:     stream ID
- *
- * This function is called by any function which wants to pause
- * an already running stream.
- */
-int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-
-       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       if (str_info->status == STREAM_PAUSED)
-               return 0;
-       if (str_info->status == STREAM_RUNNING ||
-               str_info->status == STREAM_INIT) {
-               if (str_info->prev == STREAM_UN_INIT)
-                       return -EBADRQC;
-
-               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
-                               IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id,
-                               0, NULL, NULL, true, true, false, true);
-
-               if (retval == 0) {
-                       str_info->prev = str_info->status;
-                       str_info->status = STREAM_PAUSED;
-               } else if (retval == SST_ERR_INVALID_STREAM_ID) {
-                       retval = -EINVAL;
-                       mutex_lock(&sst_drv_ctx->sst_lock);
-                       sst_clean_stream(str_info);
-                       mutex_unlock(&sst_drv_ctx->sst_lock);
-               }
-       } else {
-               retval = -EBADRQC;
-               dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n ");
-       }
-
-       return retval;
-}
-
-/**
- * sst_resume_stream - Send msg for resuming stream
- * @str_id:            stream ID
- *
- * This function is called by any function which wants to resume
- * an already paused stream.
- */
-int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-
-       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       if (str_info->status == STREAM_RUNNING)
-                       return 0;
-       if (str_info->status == STREAM_PAUSED) {
-               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
-                               IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
-                               str_info->pipe_id, 0, NULL, NULL,
-                               true, true, false, true);
-
-               if (!retval) {
-                       if (str_info->prev == STREAM_RUNNING)
-                               str_info->status = STREAM_RUNNING;
-                       else
-                               str_info->status = STREAM_INIT;
-                       str_info->prev = STREAM_PAUSED;
-               } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
-                       retval = -EINVAL;
-                       mutex_lock(&sst_drv_ctx->sst_lock);
-                       sst_clean_stream(str_info);
-                       mutex_unlock(&sst_drv_ctx->sst_lock);
-               }
-       } else {
-               retval = -EBADRQC;
-               dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n");
-       }
-
-       return retval;
-}
-
-
-/**
- * sst_drop_stream - Send msg for stopping stream
- * @str_id:            stream ID
- *
- * This function is called by any function which wants to stop
- * a stream.
- */
-int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-
-       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-
-       if (str_info->status != STREAM_UN_INIT) {
-               str_info->prev = STREAM_UN_INIT;
-               str_info->status = STREAM_INIT;
-               str_info->cumm_bytes = 0;
-               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
-                               IPC_CMD, IPC_IA_DROP_STREAM_MRFLD,
-                               str_info->pipe_id, 0, NULL, NULL,
-                               true, true, true, false);
-       } else {
-               retval = -EBADRQC;
-               dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n",
-                               str_info->status);
-       }
-       return retval;
-}
-
-/**
-* sst_drain_stream - Send msg for draining stream
-* @str_id:             stream ID
-*
-* This function is called by any function which wants to drain
-* a stream.
-*/
-int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
-                       int str_id, bool partial_drain)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-
-       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       if (str_info->status != STREAM_RUNNING &&
-               str_info->status != STREAM_INIT &&
-               str_info->status != STREAM_PAUSED) {
-                       dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
-                                      str_info->status);
-                       return -EBADRQC;
-       }
-
-       retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
-                       IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id,
-                       sizeof(u8), &partial_drain, NULL, true, true, false, false);
-       /*
-        * with new non blocked drain implementation in core we dont need to
-        * wait for respsonse, and need to only invoke callback for drain
-        * complete
-        */
-
-       return retval;
-}
-
-/**
- * sst_free_stream - Frees a stream
- * @str_id:            stream ID
- *
- * This function is called by any function which wants to free
- * a stream.
- */
-int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
-{
-       int retval = 0;
-       struct stream_info *str_info;
-       struct intel_sst_ops *ops;
-
-       dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
-
-       mutex_lock(&sst_drv_ctx->sst_lock);
-       if (sst_drv_ctx->sst_state == SST_RESET) {
-               mutex_unlock(&sst_drv_ctx->sst_lock);
-               return -ENODEV;
-       }
-       mutex_unlock(&sst_drv_ctx->sst_lock);
-       str_info = get_stream_info(sst_drv_ctx, str_id);
-       if (!str_info)
-               return -EINVAL;
-       ops = sst_drv_ctx->ops;
-
-       mutex_lock(&str_info->lock);
-       if (str_info->status != STREAM_UN_INIT) {
-               str_info->prev =  str_info->status;
-               str_info->status = STREAM_UN_INIT;
-               mutex_unlock(&str_info->lock);
-
-               dev_info(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
-                               str_id, str_info->pipe_id);
-               retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
-                               IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
-                               NULL, NULL, true, true, false, true);
-
-               dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n",
-                               retval);
-               mutex_lock(&sst_drv_ctx->sst_lock);
-               sst_clean_stream(str_info);
-               mutex_unlock(&sst_drv_ctx->sst_lock);
-               dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n");
-       } else {
-               mutex_unlock(&str_info->lock);
-               retval = -EBADRQC;
-               dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n");
-       }
-
-       return retval;
-}
This page took 0.189687 seconds and 5 git commands to generate.