Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / staging / intel_sst / intelmid_pvt.c
1 /*
2  *   intelmid_pvt.h - Intel Sound card driver for MID
3  *
4  *  Copyright (C) 2008-10 Intel Corp
5  *  Authors:    Harsha Priya <priya.harsha@intel.com>
6  *              Vinod Koul <vinod.koul@intel.com>
7  *              KP Jeeja <jeeja.kp@intel.com>
8  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; version 2 of the License.
13  *
14  *  This program is distributed in the hope that it will be useful, but
15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License along
20  *  with this program; if not, write to the Free Software Foundation, Inc.,
21  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22  *
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  * ALSA driver for Intel MID sound card chipset - holding private functions
25  */
26
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29 #include <linux/io.h>
30 #include <asm/intel_scu_ipc.h>
31 #include <sound/core.h>
32 #include <sound/control.h>
33 #include <sound/pcm.h>
34 #include "intel_sst.h"
35 #include "intel_sst_ioctl.h"
36 #include "intelmid_snd_control.h"
37 #include "intelmid.h"
38
39
40 void period_elapsed(void *mad_substream)
41 {
42         struct snd_pcm_substream *substream = mad_substream;
43         struct mad_stream_pvt *stream;
44
45
46
47         if (!substream || !substream->runtime)
48                 return;
49         stream = substream->runtime->private_data;
50         if (!stream)
51                 return;
52
53         if (stream->stream_status != RUNNING)
54                 return;
55         pr_debug("calling period elapsed\n");
56         snd_pcm_period_elapsed(substream);
57         return;
58 }
59
60
61 int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream)
62 {
63         struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
64         struct mad_stream_pvt *stream = substream->runtime->private_data;
65         struct snd_sst_stream_params param = {{{0,},},};
66         struct snd_sst_params str_params = {0};
67         int ret_val;
68
69         /* set codec params and inform SST driver the same */
70
71         param.uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
72         param.uc.pcm_params.num_chan = (u8) substream->runtime->channels;
73         param.uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
74         param.uc.pcm_params.reserved = 0;
75         param.uc.pcm_params.sfreq = substream->runtime->rate;
76         param.uc.pcm_params.ring_buffer_size =
77                                         snd_pcm_lib_buffer_bytes(substream);
78         param.uc.pcm_params.period_count = substream->runtime->period_size;
79         param.uc.pcm_params.ring_buffer_addr =
80                                 virt_to_phys(substream->runtime->dma_area);
81         pr_debug("period_cnt = %d\n", param.uc.pcm_params.period_count);
82         pr_debug("sfreq= %d, wd_sz = %d\n",
83                  param.uc.pcm_params.sfreq, param.uc.pcm_params.pcm_wd_sz);
84
85         str_params.sparams = param;
86         str_params.codec = SST_CODEC_TYPE_PCM;
87
88         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
89                 str_params.ops = STREAM_OPS_PLAYBACK;
90                 pr_debug("Playbck stream,Device %d\n", stream->device);
91         } else {
92                 str_params.ops = STREAM_OPS_CAPTURE;
93                 stream->device = SND_SST_DEVICE_CAPTURE;
94                 pr_debug("Capture stream,Device %d\n", stream->device);
95         }
96         str_params.device_type = stream->device;
97         ret_val = intelmaddata->sstdrv_ops->pcm_control->open(&str_params);
98         pr_debug("sst: SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
99         if (ret_val < 0)
100                 return ret_val;
101
102         stream->stream_info.str_id = ret_val;
103         stream->stream_status = INIT;
104         stream->stream_info.buffer_ptr = 0;
105         pr_debug("str id :  %d\n", stream->stream_info.str_id);
106
107         return ret_val;
108 }
109
110 int snd_intelmad_init_stream(struct snd_pcm_substream *substream)
111 {
112         struct mad_stream_pvt *stream = substream->runtime->private_data;
113         struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
114         int ret_val;
115
116         pr_debug("setting buffer ptr param\n");
117         stream->stream_info.period_elapsed = period_elapsed;
118         stream->stream_info.mad_substream = substream;
119         stream->stream_info.buffer_ptr = 0;
120         stream->stream_info.sfreq = substream->runtime->rate;
121         ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
122                         SST_SND_STREAM_INIT, &stream->stream_info);
123         if (ret_val)
124                 pr_err("control_set ret error %d\n", ret_val);
125         return ret_val;
126
127 }
128
129
130 /**
131  * sst_sc_reg_access - IPC read/write wrapper
132  *
133  * @sc_access:  array of data, addresses and mask
134  * @type: operation type
135  * @num_val: number of reg to opertae on
136  *
137  * Reads/writes/read-modify operations on registers accessed through SCU (sound
138  * card and few SST DSP regsisters that are not accissible to IA)
139  */
140 int sst_sc_reg_access(struct sc_reg_access *sc_access,
141                                         int type, int num_val)
142 {
143         int i, retval = 0;
144         if (type == PMIC_WRITE) {
145                 for (i = 0; i < num_val; i++) {
146                         retval = intel_scu_ipc_iowrite8(sc_access[i].reg_addr,
147                                                         sc_access[i].value);
148                         if (retval)
149                                 goto err;
150                 }
151         } else if (type == PMIC_READ) {
152                 for (i = 0; i < num_val; i++) {
153                         retval = intel_scu_ipc_ioread8(sc_access[i].reg_addr,
154                                                         &(sc_access[i].value));
155                         if (retval)
156                                 goto err;
157                 }
158         } else {
159                 for (i = 0; i < num_val; i++) {
160                         retval = intel_scu_ipc_update_register(
161                                 sc_access[i].reg_addr, sc_access[i].value,
162                                 sc_access[i].mask);
163                         if (retval)
164                                 goto err;
165                 }
166         }
167         return 0;
168 err:
169         pr_err("IPC failed for cmd %d, %d\n", retval, type);
170         pr_err("reg:0x%2x addr:0x%2x\n",
171                 sc_access[i].reg_addr, sc_access[i].value);
172         return retval;
173 }