diff options
Diffstat (limited to 'drivers/staging/intel_sst/intelmid_pvt.c')
-rw-r--r-- | drivers/staging/intel_sst/intelmid_pvt.c | 174 |
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 000000000000..9ed9475ccc7b --- /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; +} |