summaryrefslogtreecommitdiffstats
path: root/drivers/staging/intel_sst/intelmid_pvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/intel_sst/intelmid_pvt.c')
-rw-r--r--drivers/staging/intel_sst/intelmid_pvt.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/drivers/staging/intel_sst/intelmid_pvt.c b/drivers/staging/intel_sst/intelmid_pvt.c
new file mode 100644
index 0000000..9ed9475
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_pvt.c
@@ -0,0 +1,174 @@
+/*
+ * intelmid_pvt.h - Intel Sound card driver for MID
+ *
+ * Copyright (C) 2008-10 Intel Corp
+ * Authors: Harsha Priya <priya.harsha@intel.com>
+ * Vinod Koul <vinod.koul@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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * ALSA driver for Intel MID sound card chipset - holding private functions
+ */
+#include <linux/io.h>
+#include <asm/intel_scu_ipc.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include "jack.h"
+#include "intel_sst.h"
+#include "intel_sst_ioctl.h"
+#include "intelmid_snd_control.h"
+#include "intelmid.h"
+
+
+void period_elapsed(void *mad_substream)
+{
+ struct snd_pcm_substream *substream = mad_substream;
+ struct mad_stream_pvt *stream;
+
+
+
+ if (!substream || !substream->runtime)
+ return;
+ stream = substream->runtime->private_data;
+ if (!stream)
+ return;
+
+ if (stream->stream_status != RUNNING)
+ return;
+ pr_debug("sst: calling period elapsed\n");
+ snd_pcm_period_elapsed(substream);
+ return;
+}
+
+
+int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream)
+{
+ struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
+ struct mad_stream_pvt *stream = substream->runtime->private_data;
+ struct snd_sst_stream_params param = {{{0,},},};
+ struct snd_sst_params str_params = {0};
+ int ret_val;
+
+ /* set codec params and inform SST driver the same */
+
+ param.uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
+ 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.reserved = 0;
+ param.uc.pcm_params.sfreq = substream->runtime->rate;
+ param.uc.pcm_params.ring_buffer_size =
+ snd_pcm_lib_buffer_bytes(substream);
+ param.uc.pcm_params.period_count = substream->runtime->period_size;
+ param.uc.pcm_params.ring_buffer_addr =
+ virt_to_phys(substream->runtime->dma_area);
+ pr_debug("sst: period_cnt = %d\n", param.uc.pcm_params.period_count);
+ pr_debug("sst: sfreq= %d, wd_sz = %d\n",
+ param.uc.pcm_params.sfreq, param.uc.pcm_params.pcm_wd_sz);
+
+ str_params.sparams = param;
+ str_params.codec = SST_CODEC_TYPE_PCM;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ str_params.ops = STREAM_OPS_PLAYBACK;
+ pr_debug("sst: Playbck stream,Device %d\n", stream->device);
+ } else {
+ str_params.ops = STREAM_OPS_CAPTURE;
+ stream->device = SND_SST_DEVICE_CAPTURE;
+ pr_debug("sst: Capture stream,Device %d\n", stream->device);
+ }
+ str_params.device_type = stream->device;
+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_ALLOC,
+ &str_params);
+ pr_debug("sst: SST_SND_PLAY/CAPTURE ret_val = %x\n",
+ ret_val);
+ if (ret_val < 0)
+ return ret_val;
+
+ stream->stream_info.str_id = ret_val;
+ stream->stream_status = INIT;
+ stream->stream_info.buffer_ptr = 0;
+ pr_debug("sst: str id : %d\n", stream->stream_info.str_id);
+
+ return ret_val;
+}
+
+int snd_intelmad_init_stream(struct snd_pcm_substream *substream)
+{
+ struct mad_stream_pvt *stream = substream->runtime->private_data;
+ struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
+ int ret_val;
+
+ pr_debug("sst: setting buffer ptr param\n");
+ stream->stream_info.period_elapsed = period_elapsed;
+ stream->stream_info.mad_substream = substream;
+ stream->stream_info.buffer_ptr = 0;
+ stream->stream_info.sfreq = substream->runtime->rate;
+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_STREAM_INIT,
+ &stream->stream_info);
+ if (ret_val)
+ pr_err("sst: control_set ret error %d\n", ret_val);
+ return ret_val;
+
+}
+
+
+/**
+ * sst_sc_reg_access - IPC read/write wrapper
+ *
+ * @sc_access: array of data, addresses and mask
+ * @type: operation type
+ * @num_val: number of reg to opertae on
+ *
+ * Reads/writes/read-modify operations on registers accessed through SCU (sound
+ * card and few SST DSP regsisters that are not accissible to IA)
+ */
+int sst_sc_reg_access(struct sc_reg_access *sc_access,
+ int type, int num_val)
+{
+ int i, retval = 0;
+ if (type == PMIC_WRITE) {
+ for (i = 0; i < num_val; i++) {
+ retval = intel_scu_ipc_iowrite8(sc_access[i].reg_addr,
+ sc_access[i].value);
+ if (retval) {
+ pr_err("sst: IPC write failed!!! %d\n", retval);
+ return retval;
+ }
+ }
+ } else if (type == PMIC_READ) {
+ for (i = 0; i < num_val; i++) {
+ retval = intel_scu_ipc_ioread8(sc_access[i].reg_addr,
+ &(sc_access[i].value));
+ if (retval) {
+ pr_err("sst: IPC read failed!!!!!%d\n", retval);
+ return retval;
+ }
+ }
+ } else {
+ for (i = 0; i < num_val; i++) {
+ retval = intel_scu_ipc_update_register(
+ sc_access[i].reg_addr, sc_access[i].value,
+ sc_access[i].mask);
+ if (retval) {
+ pr_err("sst: IPC Modify failed!!!%d\n", retval);
+ return retval;
+ }
+ }
+ }
+ return retval;
+}
OpenPOWER on IntegriCloud