Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[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 "jack.h"
35 #include "intel_sst.h"
36 #include "intel_sst_ioctl.h"
37 #include "intelmid_snd_control.h"
38 #include "intelmid.h"
39
40
41 void period_elapsed(void *mad_substream)
42 {
43         struct snd_pcm_substream *substream = mad_substream;
44         struct mad_stream_pvt *stream;
45
46
47
48         if (!substream || !substream->runtime)
49                 return;
50         stream = substream->runtime->private_data;
51         if (!stream)
52                 return;
53
54         if (stream->stream_status != RUNNING)
55                 return;
56         pr_debug("calling period elapsed\n");
57         snd_pcm_period_elapsed(substream);
58         return;
59 }
60
61
62 int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream)
63 {
64         struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
65         struct mad_stream_pvt *stream = substream->runtime->private_data;
66         struct snd_sst_stream_params param = {{{0,},},};
67         struct snd_sst_params str_params = {0};
68         int ret_val;
69
70         /* set codec params and inform SST driver the same */
71
72         param.uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
73         param.uc.pcm_params.num_chan = (u8) substream->runtime->channels;
74         param.uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
75         param.uc.pcm_params.reserved = 0;
76         param.uc.pcm_params.sfreq = substream->runtime->rate;
77         param.uc.pcm_params.ring_buffer_size =
78                                         snd_pcm_lib_buffer_bytes(substream);
79         param.uc.pcm_params.period_count = substream->runtime->period_size;
80         param.uc.pcm_params.ring_buffer_addr =
81                                 virt_to_phys(substream->runtime->dma_area);
82         pr_debug("period_cnt = %d\n", param.uc.pcm_params.period_count);
83         pr_debug("sfreq= %d, wd_sz = %d\n",
84                  param.uc.pcm_params.sfreq, param.uc.pcm_params.pcm_wd_sz);
85
86         str_params.sparams = param;
87         str_params.codec = SST_CODEC_TYPE_PCM;
88
89         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
90                 str_params.ops = STREAM_OPS_PLAYBACK;
91                 pr_debug("Playbck stream,Device %d\n", stream->device);
92         } else {
93                 str_params.ops = STREAM_OPS_CAPTURE;
94                 stream->device = SND_SST_DEVICE_CAPTURE;
95                 pr_debug("Capture stream,Device %d\n", stream->device);
96         }
97         str_params.device_type = stream->device;
98         ret_val = intelmaddata->sstdrv_ops->pcm_control->open(&str_params);
99         pr_debug("sst: SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
100         if (ret_val < 0)
101                 return ret_val;
102
103         stream->stream_info.str_id = ret_val;
104         stream->stream_status = INIT;
105         stream->stream_info.buffer_ptr = 0;
106         pr_debug("str id :  %d\n", stream->stream_info.str_id);
107
108         return ret_val;
109 }
110
111 int snd_intelmad_init_stream(struct snd_pcm_substream *substream)
112 {
113         struct mad_stream_pvt *stream = substream->runtime->private_data;
114         struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
115         int ret_val;
116
117         pr_debug("setting buffer ptr param\n");
118         stream->stream_info.period_elapsed = period_elapsed;
119         stream->stream_info.mad_substream = substream;
120         stream->stream_info.buffer_ptr = 0;
121         stream->stream_info.sfreq = substream->runtime->rate;
122         ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
123                         SST_SND_STREAM_INIT, &stream->stream_info);
124         if (ret_val)
125                 pr_err("control_set ret error %d\n", ret_val);
126         return ret_val;
127
128 }
129
130
131 /**
132  * sst_sc_reg_access - IPC read/write wrapper
133  *
134  * @sc_access:  array of data, addresses and mask
135  * @type: operation type
136  * @num_val: number of reg to opertae on
137  *
138  * Reads/writes/read-modify operations on registers accessed through SCU (sound
139  * card and few SST DSP regsisters that are not accissible to IA)
140  */
141 int sst_sc_reg_access(struct sc_reg_access *sc_access,
142                                         int type, int num_val)
143 {
144         int i, retval = 0;
145         if (type == PMIC_WRITE) {
146                 for (i = 0; i < num_val; i++) {
147                         retval = intel_scu_ipc_iowrite8(sc_access[i].reg_addr,
148                                                         sc_access[i].value);
149                         if (retval)
150                                 goto err;
151                 }
152         } else if (type == PMIC_READ) {
153                 for (i = 0; i < num_val; i++) {
154                         retval = intel_scu_ipc_ioread8(sc_access[i].reg_addr,
155                                                         &(sc_access[i].value));
156                         if (retval)
157                                 goto err;
158                 }
159         } else {
160                 for (i = 0; i < num_val; i++) {
161                         retval = intel_scu_ipc_update_register(
162                                 sc_access[i].reg_addr, sc_access[i].value,
163                                 sc_access[i].mask);
164                         if (retval)
165                                 goto err;
166                 }
167         }
168         return 0;
169 err:
170         pr_err("IPC failed for cmd %d, %d\n", retval, type);
171         pr_err("reg:0x%2x addr:0x%2x\n",
172                 sc_access[i].reg_addr, sc_access[i].value);
173         return retval;
174 }