aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/intel_sst
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/intel_sst')
-rw-r--r--drivers/staging/intel_sst/Kconfig19
-rw-r--r--drivers/staging/intel_sst/Makefile7
-rw-r--r--drivers/staging/intel_sst/TODO13
-rw-r--r--drivers/staging/intel_sst/intel_sst.c646
-rw-r--r--drivers/staging/intel_sst/intel_sst.h162
-rw-r--r--drivers/staging/intel_sst/intel_sst_app_interface.c1460
-rw-r--r--drivers/staging/intel_sst/intel_sst_common.h623
-rw-r--r--drivers/staging/intel_sst/intel_sst_drv_interface.c563
-rw-r--r--drivers/staging/intel_sst/intel_sst_dsp.c496
-rw-r--r--drivers/staging/intel_sst/intel_sst_fw_ipc.h416
-rw-r--r--drivers/staging/intel_sst/intel_sst_ioctl.h440
-rw-r--r--drivers/staging/intel_sst/intel_sst_ipc.c774
-rw-r--r--drivers/staging/intel_sst/intel_sst_pvt.c313
-rw-r--r--drivers/staging/intel_sst/intel_sst_stream.c583
-rw-r--r--drivers/staging/intel_sst/intel_sst_stream_encoded.c1273
-rw-r--r--drivers/staging/intel_sst/intelmid.c1021
-rw-r--r--drivers/staging/intel_sst/intelmid.h209
-rw-r--r--drivers/staging/intel_sst/intelmid_adc_control.h193
-rw-r--r--drivers/staging/intel_sst/intelmid_ctrl.c921
-rw-r--r--drivers/staging/intel_sst/intelmid_msic_control.c1047
-rw-r--r--drivers/staging/intel_sst/intelmid_pvt.c173
-rw-r--r--drivers/staging/intel_sst/intelmid_snd_control.h123
-rw-r--r--drivers/staging/intel_sst/intelmid_v0_control.c866
-rw-r--r--drivers/staging/intel_sst/intelmid_v1_control.c978
-rw-r--r--drivers/staging/intel_sst/intelmid_v2_control.c1156
25 files changed, 14475 insertions, 0 deletions
diff --git a/drivers/staging/intel_sst/Kconfig b/drivers/staging/intel_sst/Kconfig
new file mode 100644
index 00000000000..82391077b38
--- /dev/null
+++ b/drivers/staging/intel_sst/Kconfig
@@ -0,0 +1,19 @@
1config SND_INTEL_SST
2 tristate "Intel SST (LPE) Driver"
3 depends on X86 && INTEL_SCU_IPC
4 default n
5 help
6 Say Y here to include support for the Intel(R) MID SST DSP driver
7 On other PC platforms if you are unsure answer 'N'
8
9config SND_INTELMID
10 tristate "Intel MID sound card driver"
11 depends on SOUND && SND
12 select SND_PCM
13 select SND_SEQUENCER
14 select SND_JACK
15 depends on SND_INTEL_SST
16 default n
17 help
18 Say Y here to include support for the Intel(R) MID sound card driver
19 On other PC platforms if you are unsure answer 'N'
diff --git a/drivers/staging/intel_sst/Makefile b/drivers/staging/intel_sst/Makefile
new file mode 100644
index 00000000000..9eb7c158bb6
--- /dev/null
+++ b/drivers/staging/intel_sst/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for Intel MID Audio drivers
3#
4snd-intel-sst-y := intel_sst.o intel_sst_ipc.o intel_sst_stream.o intel_sst_drv_interface.o intel_sst_dsp.o intel_sst_pvt.o intel_sst_stream_encoded.o intel_sst_app_interface.o
5snd-intelmid-y := intelmid.o intelmid_msic_control.o intelmid_ctrl.o intelmid_pvt.o intelmid_v0_control.o intelmid_v1_control.o intelmid_v2_control.o
6obj-$(CONFIG_SND_INTEL_SST) += snd-intel-sst.o
7obj-$(CONFIG_SND_INTELMID) += snd-intelmid.o
diff --git a/drivers/staging/intel_sst/TODO b/drivers/staging/intel_sst/TODO
new file mode 100644
index 00000000000..c733d701109
--- /dev/null
+++ b/drivers/staging/intel_sst/TODO
@@ -0,0 +1,13 @@
1TODO
2----
3
4Get the memrar driver cleaned up and upstream (dependency blocking SST)
5Replace long/short press with two virtual buttons
6Review the printks and kill off any left over ST_ERR: messages
7Review the misc device ioctls for 32/64bit safety and sanity
8Review the misc device ioctls for size safety depending on config and decide
9 if space/unused areas should be left
10What the sound folks turn up on full review
11Using the ALSA frameworks properly
12
13
diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
new file mode 100644
index 00000000000..d892861346f
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -0,0 +1,646 @@
1/*
2 * intel_sst.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This driver exposes the audio engine functionalities to the ALSA
27 * and middleware.
28 *
29 * This file contains all init functions
30 */
31
32#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
34#include <linux/pci.h>
35#include <linux/fs.h>
36#include <linux/interrupt.h>
37#include <linux/firmware.h>
38#include <linux/miscdevice.h>
39#include <linux/pm_runtime.h>
40#include <asm/mrst.h>
41#include "intel_sst.h"
42#include "intel_sst_ioctl.h"
43#include "intel_sst_fw_ipc.h"
44#include "intel_sst_common.h"
45
46
47MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
48MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
49MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
50MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
51MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine Driver");
52MODULE_LICENSE("GPL v2");
53MODULE_VERSION(SST_DRIVER_VERSION);
54
55struct intel_sst_drv *sst_drv_ctx;
56static struct mutex drv_ctx_lock;
57struct class *sst_class;
58
59/* fops Routines */
60static const struct file_operations intel_sst_fops = {
61 .owner = THIS_MODULE,
62 .open = intel_sst_open,
63 .release = intel_sst_release,
64 .read = intel_sst_read,
65 .write = intel_sst_write,
66 .unlocked_ioctl = intel_sst_ioctl,
67 .mmap = intel_sst_mmap,
68 .aio_read = intel_sst_aio_read,
69 .aio_write = intel_sst_aio_write,
70};
71static const struct file_operations intel_sst_fops_cntrl = {
72 .owner = THIS_MODULE,
73 .open = intel_sst_open_cntrl,
74 .release = intel_sst_release_cntrl,
75 .unlocked_ioctl = intel_sst_ioctl,
76};
77
78static struct miscdevice lpe_dev = {
79 .minor = MISC_DYNAMIC_MINOR,/* dynamic allocation */
80 .name = "intel_sst",/* /dev/intel_sst */
81 .fops = &intel_sst_fops
82};
83
84
85static struct miscdevice lpe_ctrl = {
86 .minor = MISC_DYNAMIC_MINOR,/* dynamic allocation */
87 .name = "intel_sst_ctrl",/* /dev/intel_sst_ctrl */
88 .fops = &intel_sst_fops_cntrl
89};
90
91/**
92* intel_sst_interrupt - Interrupt service routine for SST
93*
94* @irq: irq number of interrupt
95* @context: pointer to device structre
96*
97* This function is called by OS when SST device raises
98* an interrupt. This will be result of write in IPC register
99* Source can be busy or done interrupt
100*/
101static irqreturn_t intel_sst_interrupt(int irq, void *context)
102{
103 union interrupt_reg isr;
104 union ipc_header header;
105 union interrupt_reg imr;
106 struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
107 unsigned int size = 0, str_id;
108 struct stream_info *stream ;
109
110 /* Do not handle interrupt in suspended state */
111 if (drv->sst_state == SST_SUSPENDED)
112 return IRQ_NONE;
113 /* Interrupt arrived, check src */
114 isr.full = sst_shim_read(drv->shim, SST_ISRX);
115
116 if (isr.part.busy_interrupt) {
117 header.full = sst_shim_read(drv->shim, SST_IPCD);
118 if (header.part.msg_id == IPC_SST_PERIOD_ELAPSED) {
119 sst_clear_interrupt();
120 str_id = header.part.str_id;
121 stream = &sst_drv_ctx->streams[str_id];
122 if (stream->period_elapsed)
123 stream->period_elapsed(stream->pcm_substream);
124 return IRQ_HANDLED;
125 }
126 if (header.part.large)
127 size = header.part.data;
128 if (header.part.msg_id & REPLY_MSG) {
129 sst_drv_ctx->ipc_process_msg.header = header;
130 memcpy_fromio(sst_drv_ctx->ipc_process_msg.mailbox,
131 drv->mailbox + SST_MAILBOX_RCV, size);
132 queue_work(sst_drv_ctx->process_msg_wq,
133 &sst_drv_ctx->ipc_process_msg.wq);
134 } else {
135 sst_drv_ctx->ipc_process_reply.header = header;
136 memcpy_fromio(sst_drv_ctx->ipc_process_reply.mailbox,
137 drv->mailbox + SST_MAILBOX_RCV, size);
138 queue_work(sst_drv_ctx->process_reply_wq,
139 &sst_drv_ctx->ipc_process_reply.wq);
140 }
141 /* mask busy inetrrupt */
142 imr.full = sst_shim_read(drv->shim, SST_IMRX);
143 imr.part.busy_interrupt = 1;
144 sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
145 return IRQ_HANDLED;
146 } else if (isr.part.done_interrupt) {
147 /* Clear done bit */
148 header.full = sst_shim_read(drv->shim, SST_IPCX);
149 header.part.done = 0;
150 sst_shim_write(sst_drv_ctx->shim, SST_IPCX, header.full);
151 /* write 1 to clear status register */;
152 isr.part.done_interrupt = 1;
153 /* dummy register for shim workaround */
154 sst_shim_write(sst_drv_ctx->shim, SST_ISRX, isr.full);
155 queue_work(sst_drv_ctx->post_msg_wq,
156 &sst_drv_ctx->ipc_post_msg.wq);
157 return IRQ_HANDLED;
158 } else
159 return IRQ_NONE;
160
161}
162
163
164/*
165* intel_sst_probe - PCI probe function
166*
167* @pci: PCI device structure
168* @pci_id: PCI device ID structure
169*
170* This function is called by OS when a device is found
171* This enables the device, interrupt etc
172*/
173static int __devinit intel_sst_probe(struct pci_dev *pci,
174 const struct pci_device_id *pci_id)
175{
176 int i, ret = 0;
177
178 pr_debug("Probe for DID %x\n", pci->device);
179 mutex_lock(&drv_ctx_lock);
180 if (sst_drv_ctx) {
181 pr_err("Only one sst handle is supported\n");
182 mutex_unlock(&drv_ctx_lock);
183 return -EBUSY;
184 }
185
186 sst_drv_ctx = kzalloc(sizeof(*sst_drv_ctx), GFP_KERNEL);
187 if (!sst_drv_ctx) {
188 pr_err("malloc fail\n");
189 mutex_unlock(&drv_ctx_lock);
190 return -ENOMEM;
191 }
192 mutex_unlock(&drv_ctx_lock);
193
194 sst_drv_ctx->pci_id = pci->device;
195
196 mutex_init(&sst_drv_ctx->stream_lock);
197 mutex_init(&sst_drv_ctx->sst_lock);
198 sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
199
200 sst_drv_ctx->stream_cnt = 0;
201 sst_drv_ctx->encoded_cnt = 0;
202 sst_drv_ctx->am_cnt = 0;
203 sst_drv_ctx->pb_streams = 0;
204 sst_drv_ctx->cp_streams = 0;
205 sst_drv_ctx->unique_id = 0;
206 sst_drv_ctx->pmic_port_instance = SST_DEFAULT_PMIC_PORT;
207
208 INIT_LIST_HEAD(&sst_drv_ctx->ipc_dispatch_list);
209 INIT_WORK(&sst_drv_ctx->ipc_post_msg.wq, sst_post_message);
210 INIT_WORK(&sst_drv_ctx->ipc_process_msg.wq, sst_process_message);
211 INIT_WORK(&sst_drv_ctx->ipc_process_reply.wq, sst_process_reply);
212 INIT_WORK(&sst_drv_ctx->mad_ops.wq, sst_process_mad_ops);
213 init_waitqueue_head(&sst_drv_ctx->wait_queue);
214
215 sst_drv_ctx->mad_wq = create_workqueue("sst_mad_wq");
216 if (!sst_drv_ctx->mad_wq)
217 goto do_free_drv_ctx;
218 sst_drv_ctx->post_msg_wq = create_workqueue("sst_post_msg_wq");
219 if (!sst_drv_ctx->post_msg_wq)
220 goto free_mad_wq;
221 sst_drv_ctx->process_msg_wq = create_workqueue("sst_process_msg_wqq");
222 if (!sst_drv_ctx->process_msg_wq)
223 goto free_post_msg_wq;
224 sst_drv_ctx->process_reply_wq = create_workqueue("sst_proces_reply_wq");
225 if (!sst_drv_ctx->process_reply_wq)
226 goto free_process_msg_wq;
227
228 for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
229 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
230 sst_drv_ctx->alloc_block[i].ops_block.condition = false;
231 }
232 spin_lock_init(&sst_drv_ctx->list_spin_lock);
233
234 sst_drv_ctx->max_streams = pci_id->driver_data;
235 pr_debug("Got drv data max stream %d\n",
236 sst_drv_ctx->max_streams);
237 for (i = 1; i <= sst_drv_ctx->max_streams; i++) {
238 struct stream_info *stream = &sst_drv_ctx->streams[i];
239 INIT_LIST_HEAD(&stream->bufs);
240 mutex_init(&stream->lock);
241 spin_lock_init(&stream->pcm_lock);
242 }
243 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
244 sst_drv_ctx->mmap_mem = NULL;
245 sst_drv_ctx->mmap_len = SST_MMAP_PAGES * PAGE_SIZE;
246 while (sst_drv_ctx->mmap_len > 0) {
247 sst_drv_ctx->mmap_mem =
248 kzalloc(sst_drv_ctx->mmap_len, GFP_KERNEL);
249 if (sst_drv_ctx->mmap_mem) {
250 pr_debug("Got memory %p size 0x%x\n",
251 sst_drv_ctx->mmap_mem,
252 sst_drv_ctx->mmap_len);
253 break;
254 }
255 if (sst_drv_ctx->mmap_len < (SST_MMAP_STEP*PAGE_SIZE)) {
256 pr_err("mem alloc fail...abort!!\n");
257 ret = -ENOMEM;
258 goto free_process_reply_wq;
259 }
260 sst_drv_ctx->mmap_len -= (SST_MMAP_STEP * PAGE_SIZE);
261 pr_debug("mem alloc failed...trying %d\n",
262 sst_drv_ctx->mmap_len);
263 }
264 }
265
266 /* Init the device */
267 ret = pci_enable_device(pci);
268 if (ret) {
269 pr_err("device can't be enabled\n");
270 goto do_free_mem;
271 }
272 sst_drv_ctx->pci = pci_dev_get(pci);
273 ret = pci_request_regions(pci, SST_DRV_NAME);
274 if (ret)
275 goto do_disable_device;
276 /* map registers */
277 /* SST Shim */
278 sst_drv_ctx->shim_phy_add = pci_resource_start(pci, 1);
279 sst_drv_ctx->shim = pci_ioremap_bar(pci, 1);
280 if (!sst_drv_ctx->shim)
281 goto do_release_regions;
282 pr_debug("SST Shim Ptr %p\n", sst_drv_ctx->shim);
283
284 /* Shared SRAM */
285 sst_drv_ctx->mailbox = pci_ioremap_bar(pci, 2);
286 if (!sst_drv_ctx->mailbox)
287 goto do_unmap_shim;
288 pr_debug("SRAM Ptr %p\n", sst_drv_ctx->mailbox);
289
290 /* IRAM */
291 sst_drv_ctx->iram = pci_ioremap_bar(pci, 3);
292 if (!sst_drv_ctx->iram)
293 goto do_unmap_sram;
294 pr_debug("IRAM Ptr %p\n", sst_drv_ctx->iram);
295
296 /* DRAM */
297 sst_drv_ctx->dram = pci_ioremap_bar(pci, 4);
298 if (!sst_drv_ctx->dram)
299 goto do_unmap_iram;
300 pr_debug("DRAM Ptr %p\n", sst_drv_ctx->dram);
301
302 mutex_lock(&sst_drv_ctx->sst_lock);
303 sst_drv_ctx->sst_state = SST_UN_INIT;
304 mutex_unlock(&sst_drv_ctx->sst_lock);
305 /* Register the ISR */
306 ret = request_irq(pci->irq, intel_sst_interrupt,
307 IRQF_SHARED, SST_DRV_NAME, sst_drv_ctx);
308 if (ret)
309 goto do_unmap_dram;
310 pr_debug("Registered IRQ 0x%x\n", pci->irq);
311
312 /*Register LPE Control as misc driver*/
313 ret = misc_register(&lpe_ctrl);
314 if (ret) {
315 pr_err("couldn't register control device\n");
316 goto do_free_irq;
317 }
318
319 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
320 ret = misc_register(&lpe_dev);
321 if (ret) {
322 pr_err("couldn't register LPE device\n");
323 goto do_free_misc;
324 }
325 } else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
326 u32 csr;
327
328 /*allocate mem for fw context save during suspend*/
329 sst_drv_ctx->fw_cntx = kzalloc(FW_CONTEXT_MEM, GFP_KERNEL);
330 if (!sst_drv_ctx->fw_cntx) {
331 ret = -ENOMEM;
332 goto do_free_misc;
333 }
334 /*setting zero as that is valid mem to restore*/
335 sst_drv_ctx->fw_cntx_size = 0;
336
337 /*set lpe start clock and ram size*/
338 csr = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
339 csr |= 0x30060; /*remove the clock ratio after fw fix*/
340 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr);
341 }
342 sst_drv_ctx->lpe_stalled = 0;
343 pci_set_drvdata(pci, sst_drv_ctx);
344 pm_runtime_allow(&pci->dev);
345 pm_runtime_put_noidle(&pci->dev);
346 pr_debug("...successfully done!!!\n");
347 return ret;
348
349do_free_misc:
350 misc_deregister(&lpe_ctrl);
351do_free_irq:
352 free_irq(pci->irq, sst_drv_ctx);
353do_unmap_dram:
354 iounmap(sst_drv_ctx->dram);
355do_unmap_iram:
356 iounmap(sst_drv_ctx->iram);
357do_unmap_sram:
358 iounmap(sst_drv_ctx->mailbox);
359do_unmap_shim:
360 iounmap(sst_drv_ctx->shim);
361do_release_regions:
362 pci_release_regions(pci);
363do_disable_device:
364 pci_disable_device(pci);
365do_free_mem:
366 kfree(sst_drv_ctx->mmap_mem);
367free_process_reply_wq:
368 destroy_workqueue(sst_drv_ctx->process_reply_wq);
369free_process_msg_wq:
370 destroy_workqueue(sst_drv_ctx->process_msg_wq);
371free_post_msg_wq:
372 destroy_workqueue(sst_drv_ctx->post_msg_wq);
373free_mad_wq:
374 destroy_workqueue(sst_drv_ctx->mad_wq);
375do_free_drv_ctx:
376 kfree(sst_drv_ctx);
377 sst_drv_ctx = NULL;
378 pr_err("Probe failed with %d\n", ret);
379 return ret;
380}
381
382/**
383* intel_sst_remove - PCI remove function
384*
385* @pci: PCI device structure
386*
387* This function is called by OS when a device is unloaded
388* This frees the interrupt etc
389*/
390static void __devexit intel_sst_remove(struct pci_dev *pci)
391{
392 pm_runtime_get_noresume(&pci->dev);
393 pm_runtime_forbid(&pci->dev);
394 pci_dev_put(sst_drv_ctx->pci);
395 mutex_lock(&sst_drv_ctx->sst_lock);
396 sst_drv_ctx->sst_state = SST_UN_INIT;
397 mutex_unlock(&sst_drv_ctx->sst_lock);
398 misc_deregister(&lpe_ctrl);
399 free_irq(pci->irq, sst_drv_ctx);
400 iounmap(sst_drv_ctx->dram);
401 iounmap(sst_drv_ctx->iram);
402 iounmap(sst_drv_ctx->mailbox);
403 iounmap(sst_drv_ctx->shim);
404 sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
405 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
406 misc_deregister(&lpe_dev);
407 kfree(sst_drv_ctx->mmap_mem);
408 } else
409 kfree(sst_drv_ctx->fw_cntx);
410 flush_scheduled_work();
411 destroy_workqueue(sst_drv_ctx->process_reply_wq);
412 destroy_workqueue(sst_drv_ctx->process_msg_wq);
413 destroy_workqueue(sst_drv_ctx->post_msg_wq);
414 destroy_workqueue(sst_drv_ctx->mad_wq);
415 kfree(pci_get_drvdata(pci));
416 sst_drv_ctx = NULL;
417 pci_release_regions(pci);
418 pci_disable_device(pci);
419 pci_set_drvdata(pci, NULL);
420}
421
422void sst_save_dsp_context(void)
423{
424 struct snd_sst_ctxt_params fw_context;
425 unsigned int pvt_id, i;
426 struct ipc_post *msg = NULL;
427
428 /*check cpu type*/
429 if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID)
430 return;
431 /*not supported for rest*/
432 if (sst_drv_ctx->sst_state != SST_FW_RUNNING) {
433 pr_debug("fw not running no context save ...\n");
434 return;
435 }
436
437 /*send msg to fw*/
438 if (sst_create_large_msg(&msg))
439 return;
440 pvt_id = sst_assign_pvt_id(sst_drv_ctx);
441 i = sst_get_block_stream(sst_drv_ctx);
442 sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
443 sst_fill_header(&msg->header, IPC_IA_GET_FW_CTXT, 1, pvt_id);
444 msg->header.part.data = sizeof(fw_context) + sizeof(u32);
445 fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx);
446 fw_context.size = FW_CONTEXT_MEM;
447 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
448 memcpy(msg->mailbox_data + sizeof(u32),
449 &fw_context, sizeof(fw_context));
450 spin_lock(&sst_drv_ctx->list_spin_lock);
451 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
452 spin_unlock(&sst_drv_ctx->list_spin_lock);
453 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
454 /*wait for reply*/
455 if (sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]))
456 pr_debug("err fw context save timeout ...\n");
457 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
458 pr_debug("fw context saved ...\n");
459 return;
460}
461
462/* Power Management */
463/*
464* intel_sst_suspend - PCI suspend function
465*
466* @pci: PCI device structure
467* @state: PM message
468*
469* This function is called by OS when a power event occurs
470*/
471int intel_sst_suspend(struct pci_dev *pci, pm_message_t state)
472{
473 union config_status_reg csr;
474
475 pr_debug("intel_sst_suspend called\n");
476
477 if (sst_drv_ctx->stream_cnt) {
478 pr_err("active streams,not able to suspend\n");
479 return -EBUSY;
480 }
481 /*save fw context*/
482 sst_save_dsp_context();
483 /*Assert RESET on LPE Processor*/
484 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
485 csr.full = csr.full | 0x2;
486 /* Move the SST state to Suspended */
487 mutex_lock(&sst_drv_ctx->sst_lock);
488 sst_drv_ctx->sst_state = SST_SUSPENDED;
489 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
490 mutex_unlock(&sst_drv_ctx->sst_lock);
491 pci_set_drvdata(pci, sst_drv_ctx);
492 pci_save_state(pci);
493 pci_disable_device(pci);
494 pci_set_power_state(pci, PCI_D3hot);
495 return 0;
496}
497
498/**
499* intel_sst_resume - PCI resume function
500*
501* @pci: PCI device structure
502*
503* This function is called by OS when a power event occurs
504*/
505int intel_sst_resume(struct pci_dev *pci)
506{
507 int ret = 0;
508
509 pr_debug("intel_sst_resume called\n");
510 if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
511 pr_err("SST is not in suspended state\n");
512 return 0;
513 }
514 sst_drv_ctx = pci_get_drvdata(pci);
515 pci_set_power_state(pci, PCI_D0);
516 pci_restore_state(pci);
517 ret = pci_enable_device(pci);
518 if (ret)
519 pr_err("device can't be enabled\n");
520
521 mutex_lock(&sst_drv_ctx->sst_lock);
522 sst_drv_ctx->sst_state = SST_UN_INIT;
523 mutex_unlock(&sst_drv_ctx->sst_lock);
524 return 0;
525}
526
527/* The runtime_suspend/resume is pretty much similar to the legacy suspend/resume with the noted exception below:
528 * The PCI core takes care of taking the system through D3hot and restoring it back to D0 and so there is
529 * no need to duplicate that here.
530 */
531static int intel_sst_runtime_suspend(struct device *dev)
532{
533 union config_status_reg csr;
534
535 pr_debug("intel_sst_runtime_suspend called\n");
536 if (sst_drv_ctx->stream_cnt) {
537 pr_err("active streams,not able to suspend\n");
538 return -EBUSY;
539 }
540 /*save fw context*/
541 sst_save_dsp_context();
542 /*Assert RESET on LPE Processor*/
543 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
544 csr.full = csr.full | 0x2;
545 /* Move the SST state to Suspended */
546 mutex_lock(&sst_drv_ctx->sst_lock);
547 sst_drv_ctx->sst_state = SST_SUSPENDED;
548
549 /* Only needed by Medfield */
550 if (sst_drv_ctx->pci_id != SST_MRST_PCI_ID)
551 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
552 mutex_unlock(&sst_drv_ctx->sst_lock);
553 return 0;
554}
555
556static int intel_sst_runtime_resume(struct device *dev)
557{
558
559 pr_debug("intel_sst_runtime_resume called\n");
560 if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
561 pr_err("SST is not in suspended state\n");
562 return 0;
563 }
564
565 mutex_lock(&sst_drv_ctx->sst_lock);
566 sst_drv_ctx->sst_state = SST_UN_INIT;
567 mutex_unlock(&sst_drv_ctx->sst_lock);
568 return 0;
569}
570
571static int intel_sst_runtime_idle(struct device *dev)
572{
573 pr_debug("runtime_idle called\n");
574 if (sst_drv_ctx->stream_cnt == 0 && sst_drv_ctx->am_cnt == 0)
575 pm_schedule_suspend(dev, SST_SUSPEND_DELAY);
576 return -EBUSY;
577}
578
579static const struct dev_pm_ops intel_sst_pm = {
580 .runtime_suspend = intel_sst_runtime_suspend,
581 .runtime_resume = intel_sst_runtime_resume,
582 .runtime_idle = intel_sst_runtime_idle,
583};
584
585/* PCI Routines */
586static struct pci_device_id intel_sst_ids[] = {
587 { PCI_VDEVICE(INTEL, SST_MRST_PCI_ID), 3},
588 { PCI_VDEVICE(INTEL, SST_MFLD_PCI_ID), 6},
589 { 0, }
590};
591MODULE_DEVICE_TABLE(pci, intel_sst_ids);
592
593static struct pci_driver driver = {
594 .name = SST_DRV_NAME,
595 .id_table = intel_sst_ids,
596 .probe = intel_sst_probe,
597 .remove = __devexit_p(intel_sst_remove),
598#ifdef CONFIG_PM
599 .suspend = intel_sst_suspend,
600 .resume = intel_sst_resume,
601 .driver = {
602 .pm = &intel_sst_pm,
603 },
604#endif
605};
606
607/**
608* intel_sst_init - Module init function
609*
610* Registers with PCI
611* Registers with /dev
612* Init all data strutures
613*/
614static int __init intel_sst_init(void)
615{
616 /* Init all variables, data structure etc....*/
617 int ret = 0;
618 pr_debug("INFO: ******** SST DRIVER loading.. Ver: %s\n",
619 SST_DRIVER_VERSION);
620
621 mutex_init(&drv_ctx_lock);
622 /* Register with PCI */
623 ret = pci_register_driver(&driver);
624 if (ret)
625 pr_err("PCI register failed\n");
626 return ret;
627}
628
629/**
630* intel_sst_exit - Module exit function
631*
632* Unregisters with PCI
633* Unregisters with /dev
634* Frees all data strutures
635*/
636static void __exit intel_sst_exit(void)
637{
638 pci_unregister_driver(&driver);
639
640 pr_debug("driver unloaded\n");
641 sst_drv_ctx = NULL;
642 return;
643}
644
645module_init(intel_sst_init);
646module_exit(intel_sst_exit);
diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
new file mode 100644
index 00000000000..4ad2829105a
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -0,0 +1,162 @@
1#ifndef __INTEL_SST_H__
2#define __INTEL_SST_H__
3/*
4 * intel_sst.h - Intel SST Driver for audio engine
5 *
6 * Copyright (C) 2008-10 Intel Corporation
7 * Authors: Vinod Koul <vinod.koul@intel.com>
8 * Harsha Priya <priya.harsha@intel.com>
9 * Dharageswari R <dharageswari.r@intel.com>
10 * KP Jeeja <jeeja.kp@intel.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 *
28 * This driver exposes the audio engine functionalities to the ALSA
29 * and middleware.
30 * This file is shared between the SST and MAD drivers
31 */
32#include "intel_sst_ioctl.h"
33#include <sound/jack.h>
34
35#define SST_CARD_NAMES "intel_mid_card"
36
37#define MFLD_MAX_HW_CH 4
38/* control list Pmic & Lpe */
39/* Input controls */
40enum port_status {
41 ACTIVATE = 1,
42 DEACTIVATE,
43};
44
45/* Card states */
46enum sst_card_states {
47 SND_CARD_UN_INIT = 0,
48 SND_CARD_INIT_DONE,
49};
50
51enum sst_controls {
52 SST_SND_ALLOC = 0x1000,
53 SST_SND_PAUSE = 0x1001,
54 SST_SND_RESUME = 0x1002,
55 SST_SND_DROP = 0x1003,
56 SST_SND_FREE = 0x1004,
57 SST_SND_BUFFER_POINTER = 0x1005,
58 SST_SND_STREAM_INIT = 0x1006,
59 SST_SND_START = 0x1007,
60 SST_SND_STREAM_PROCESS = 0x1008,
61 SST_MAX_CONTROLS = 0x1008,
62 SST_CONTROL_BASE = 0x1000,
63 SST_ENABLE_RX_TIME_SLOT = 0x1009,
64};
65
66enum SND_CARDS {
67 SND_FS = 0,
68 SND_MX,
69 SND_NC,
70 SND_MSIC
71};
72
73struct pcm_stream_info {
74 int str_id;
75 void *mad_substream;
76 void (*period_elapsed) (void *mad_substream);
77 unsigned long long buffer_ptr;
78 int sfreq;
79};
80
81struct snd_pmic_ops {
82 int card_status;
83 int master_mute;
84 int num_channel;
85 int input_dev_id;
86 int mute_status;
87 struct mutex lock;
88 int pb_on, pbhs_on;
89 int cap_on;
90 int output_dev_id;
91 int lineout_dev_id, line_out_names_cnt;
92 int prev_lineout_dev_id;
93 bool jack_interrupt_status;
94 int (*set_input_dev) (u8 value);
95 int (*set_output_dev) (u8 value);
96 int (*set_lineout_dev) (u8 value);
97 int (*set_mute) (int dev_id, u8 value);
98 int (*get_mute) (int dev_id, u8 *value);
99
100 int (*set_vol) (int dev_id, int value);
101 int (*get_vol) (int dev_id, int *value);
102
103 int (*init_card) (void);
104 int (*set_pcm_audio_params)
105 (int sfreq, int word_size , int num_channel);
106 int (*set_pcm_voice_params) (void);
107 int (*set_voice_port) (int status);
108 int (*set_audio_port) (int status);
109
110 int (*power_up_pmic_pb) (unsigned int port);
111 int (*power_up_pmic_cp) (unsigned int port);
112 int (*power_down_pmic_pb) (unsigned int device);
113 int (*power_down_pmic_cp) (unsigned int device);
114 int (*power_down_pmic) (void);
115 void (*pmic_irq_cb) (void *cb_data, u8 value);
116 void (*pmic_irq_enable)(void *data);
117 int (*pmic_jack_enable) (void);
118 int (*pmic_get_mic_bias)(void *intelmaddata);
119 int (*pmic_set_headset_state)(int state);
120
121 unsigned int hw_dmic_map[MFLD_MAX_HW_CH];
122 unsigned int available_dmics;
123 int (*set_hw_dmic_route) (u8 index);
124
125 int gpio_amp;
126};
127
128extern void sst_mad_send_jack_report(struct snd_jack *jack,
129 int buttonpressevent,
130 int status);
131
132
133int intemad_set_headset_state(int state);
134int intelmad_get_mic_bias(void);
135
136struct intel_sst_pcm_control {
137 int (*open) (struct snd_sst_params *str_param);
138 int (*device_control) (int cmd, void *arg);
139 int (*close) (unsigned int str_id);
140};
141struct intel_sst_card_ops {
142 char *module_name;
143 unsigned int vendor_id;
144 struct intel_sst_pcm_control *pcm_control;
145 struct snd_pmic_ops *scard_ops;
146};
147
148/* modified for generic access */
149struct sc_reg_access {
150 u16 reg_addr;
151 u8 value;
152 u8 mask;
153};
154enum sc_reg_access_type {
155 PMIC_READ = 0,
156 PMIC_WRITE,
157 PMIC_READ_MODIFY,
158};
159
160int register_sst_card(struct intel_sst_card_ops *card);
161void unregister_sst_card(struct intel_sst_card_ops *card);
162#endif /* __INTEL_SST_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c
new file mode 100644
index 00000000000..93b41a284d8
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_app_interface.c
@@ -0,0 +1,1460 @@
1/*
2 * intel_sst_interface.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * Jeeja KP <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 * This driver exposes the audio engine functionalities to the ALSA
26 * and middleware.
27 * Upper layer interfaces (MAD driver, MMF) to SST driver
28 */
29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#include <linux/pci.h>
33#include <linux/fs.h>
34#include <linux/uio.h>
35#include <linux/aio.h>
36#include <linux/uaccess.h>
37#include <linux/firmware.h>
38#include <linux/pm_runtime.h>
39#include <linux/ioctl.h>
40#ifdef CONFIG_MRST_RAR_HANDLER
41#include <linux/rar_register.h>
42#include "../../../drivers/staging/memrar/memrar.h"
43#endif
44#include "intel_sst.h"
45#include "intel_sst_ioctl.h"
46#include "intel_sst_fw_ipc.h"
47#include "intel_sst_common.h"
48
49#define AM_MODULE 1
50#define STREAM_MODULE 0
51
52
53/**
54* intel_sst_check_device - checks SST device
55*
56* This utility function checks the state of SST device and downlaods FW if
57* not done, or resumes the device if suspended
58*/
59
60static int intel_sst_check_device(void)
61{
62 int retval = 0;
63 if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
64 pr_warn("Sound card not available\n");
65 return -EIO;
66 }
67 if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
68 pr_debug("Resuming from Suspended state\n");
69 retval = intel_sst_resume(sst_drv_ctx->pci);
70 if (retval) {
71 pr_debug("Resume Failed= %#x,abort\n", retval);
72 return retval;
73 }
74 }
75
76 if (sst_drv_ctx->sst_state == SST_UN_INIT) {
77 /* FW is not downloaded */
78 retval = sst_download_fw();
79 if (retval)
80 return -ENODEV;
81 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
82 retval = sst_drv_ctx->rx_time_slot_status;
83 if (retval != RX_TIMESLOT_UNINIT
84 && sst_drv_ctx->pmic_vendor != SND_NC)
85 sst_enable_rx_timeslot(retval);
86 }
87 }
88 return 0;
89}
90
91/**
92 * intel_sst_open - opens a handle to driver
93 *
94 * @i_node: inode structure
95 * @file_ptr:pointer to file
96 *
97 * This function is called by OS when a user space component
98 * tries to get a driver handle. Only one handle at a time
99 * will be allowed
100 */
101int intel_sst_open(struct inode *i_node, struct file *file_ptr)
102{
103 unsigned int retval;
104
105 mutex_lock(&sst_drv_ctx->stream_lock);
106 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
107 retval = intel_sst_check_device();
108 if (retval) {
109 pm_runtime_put(&sst_drv_ctx->pci->dev);
110 mutex_unlock(&sst_drv_ctx->stream_lock);
111 return retval;
112 }
113
114 if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
115 struct ioctl_pvt_data *data =
116 kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
117 if (!data) {
118 pm_runtime_put(&sst_drv_ctx->pci->dev);
119 mutex_unlock(&sst_drv_ctx->stream_lock);
120 return -ENOMEM;
121 }
122
123 sst_drv_ctx->encoded_cnt++;
124 mutex_unlock(&sst_drv_ctx->stream_lock);
125 data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
126 data->str_id = 0;
127 file_ptr->private_data = (void *)data;
128 pr_debug("pvt_id handle = %d!\n", data->pvt_id);
129 } else {
130 retval = -EUSERS;
131 pm_runtime_put(&sst_drv_ctx->pci->dev);
132 mutex_unlock(&sst_drv_ctx->stream_lock);
133 }
134 return retval;
135}
136
137/**
138 * intel_sst_open_cntrl - opens a handle to driver
139 *
140 * @i_node: inode structure
141 * @file_ptr:pointer to file
142 *
143 * This function is called by OS when a user space component
144 * tries to get a driver handle to /dev/intel_sst_control.
145 * Only one handle at a time will be allowed
146 * This is for control operations only
147 */
148int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
149{
150 unsigned int retval;
151
152 /* audio manager open */
153 mutex_lock(&sst_drv_ctx->stream_lock);
154 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
155 retval = intel_sst_check_device();
156 if (retval) {
157 pm_runtime_put(&sst_drv_ctx->pci->dev);
158 mutex_unlock(&sst_drv_ctx->stream_lock);
159 return retval;
160 }
161
162 if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
163 sst_drv_ctx->am_cnt++;
164 pr_debug("AM handle opened...\n");
165 file_ptr->private_data = NULL;
166 } else {
167 retval = -EACCES;
168 pm_runtime_put(&sst_drv_ctx->pci->dev);
169 }
170
171 mutex_unlock(&sst_drv_ctx->stream_lock);
172 return retval;
173}
174
175/**
176 * intel_sst_release - releases a handle to driver
177 *
178 * @i_node: inode structure
179 * @file_ptr: pointer to file
180 *
181 * This function is called by OS when a user space component
182 * tries to release a driver handle.
183 */
184int intel_sst_release(struct inode *i_node, struct file *file_ptr)
185{
186 struct ioctl_pvt_data *data = file_ptr->private_data;
187
188 pr_debug("Release called, closing app handle\n");
189 mutex_lock(&sst_drv_ctx->stream_lock);
190 sst_drv_ctx->encoded_cnt--;
191 sst_drv_ctx->stream_cnt--;
192 pm_runtime_put(&sst_drv_ctx->pci->dev);
193 mutex_unlock(&sst_drv_ctx->stream_lock);
194 free_stream_context(data->str_id);
195 kfree(data);
196 return 0;
197}
198
199int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
200{
201 /* audio manager close */
202 mutex_lock(&sst_drv_ctx->stream_lock);
203 sst_drv_ctx->am_cnt--;
204 pm_runtime_put(&sst_drv_ctx->pci->dev);
205 mutex_unlock(&sst_drv_ctx->stream_lock);
206 pr_debug("AM handle closed\n");
207 return 0;
208}
209
210/**
211* intel_sst_mmap - mmaps a kernel buffer to user space for copying data
212*
213* @vma: vm area structure instance
214* @file_ptr: pointer to file
215*
216* This function is called by OS when a user space component
217* tries to get mmap memory from driver
218*/
219int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
220{
221 int retval, length;
222 struct ioctl_pvt_data *data =
223 (struct ioctl_pvt_data *)file_ptr->private_data;
224 int str_id = data->str_id;
225 void *mem_area;
226
227 retval = sst_validate_strid(str_id);
228 if (retval)
229 return -EINVAL;
230
231 length = vma->vm_end - vma->vm_start;
232 pr_debug("called for stream %d length 0x%x\n", str_id, length);
233
234 if (length > sst_drv_ctx->mmap_len)
235 return -ENOMEM;
236 if (!sst_drv_ctx->mmap_mem)
237 return -EIO;
238
239 /* round it up to the page boundary */
240 /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
241 + PAGE_SIZE - 1) & PAGE_MASK);*/
242 mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
243
244 /* map the whole physically contiguous area in one piece */
245 retval = remap_pfn_range(vma,
246 vma->vm_start,
247 virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
248 length,
249 vma->vm_page_prot);
250 if (retval)
251 sst_drv_ctx->streams[str_id].mmapped = false;
252 else
253 sst_drv_ctx->streams[str_id].mmapped = true;
254
255 pr_debug("mmap ret 0x%x\n", retval);
256 return retval;
257}
258
259/* sets mmap data buffers to play/capture*/
260static int intel_sst_mmap_play_capture(u32 str_id,
261 struct snd_sst_mmap_buffs *mmap_buf)
262{
263 struct sst_stream_bufs *bufs;
264 int retval, i;
265 struct stream_info *stream;
266 struct snd_sst_mmap_buff_entry *buf_entry;
267 struct snd_sst_mmap_buff_entry *tmp_buf;
268
269 pr_debug("called for str_id %d\n", str_id);
270 retval = sst_validate_strid(str_id);
271 if (retval)
272 return -EINVAL;
273
274 stream = &sst_drv_ctx->streams[str_id];
275 if (stream->mmapped != true)
276 return -EIO;
277
278 if (stream->status == STREAM_UN_INIT ||
279 stream->status == STREAM_DECODE) {
280 return -EBADRQC;
281 }
282 stream->curr_bytes = 0;
283 stream->cumm_bytes = 0;
284
285 tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
286 if (!tmp_buf)
287 return -ENOMEM;
288 if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
289 mmap_buf->entries * sizeof(*tmp_buf))) {
290 retval = -EFAULT;
291 goto out_free;
292 }
293
294 pr_debug("new buffers count %d status %d\n",
295 mmap_buf->entries, stream->status);
296 buf_entry = tmp_buf;
297 for (i = 0; i < mmap_buf->entries; i++) {
298 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
299 if (!bufs) {
300 retval = -ENOMEM;
301 goto out_free;
302 }
303 bufs->size = buf_entry->size;
304 bufs->offset = buf_entry->offset;
305 bufs->addr = sst_drv_ctx->mmap_mem;
306 bufs->in_use = false;
307 buf_entry++;
308 /* locking here */
309 mutex_lock(&stream->lock);
310 list_add_tail(&bufs->node, &stream->bufs);
311 mutex_unlock(&stream->lock);
312 }
313
314 mutex_lock(&stream->lock);
315 stream->data_blk.condition = false;
316 stream->data_blk.ret_code = 0;
317 if (stream->status == STREAM_INIT &&
318 stream->prev != STREAM_UN_INIT &&
319 stream->need_draining != true) {
320 stream->prev = stream->status;
321 stream->status = STREAM_RUNNING;
322 if (stream->ops == STREAM_OPS_PLAYBACK) {
323 if (sst_play_frame(str_id) < 0) {
324 pr_warn("play frames fail\n");
325 mutex_unlock(&stream->lock);
326 retval = -EIO;
327 goto out_free;
328 }
329 } else if (stream->ops == STREAM_OPS_CAPTURE) {
330 if (sst_capture_frame(str_id) < 0) {
331 pr_warn("capture frame fail\n");
332 mutex_unlock(&stream->lock);
333 retval = -EIO;
334 goto out_free;
335 }
336 }
337 }
338 mutex_unlock(&stream->lock);
339 /* Block the call for reply */
340 if (!list_empty(&stream->bufs)) {
341 stream->data_blk.on = true;
342 retval = sst_wait_interruptible(sst_drv_ctx,
343 &stream->data_blk);
344 }
345
346 if (retval >= 0)
347 retval = stream->cumm_bytes;
348 pr_debug("end of play/rec ioctl bytes = %d!!\n", retval);
349
350out_free:
351 kfree(tmp_buf);
352 return retval;
353}
354
355/*sets user data buffers to play/capture*/
356static int intel_sst_play_capture(struct stream_info *stream, int str_id)
357{
358 int retval;
359
360 stream->data_blk.ret_code = 0;
361 stream->data_blk.on = true;
362 stream->data_blk.condition = false;
363
364 mutex_lock(&stream->lock);
365 if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
366 /* stream is started */
367 stream->prev = stream->status;
368 stream->status = STREAM_RUNNING;
369 }
370
371 if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
372 /* stream is not started yet */
373 pr_debug("Stream isn't in started state %d, prev %d\n",
374 stream->status, stream->prev);
375 } else if ((stream->status == STREAM_RUNNING ||
376 stream->status == STREAM_PAUSED) &&
377 stream->need_draining != true) {
378 /* stream is started */
379 if (stream->ops == STREAM_OPS_PLAYBACK ||
380 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
381 if (sst_play_frame(str_id) < 0) {
382 pr_warn("play frames failed\n");
383 mutex_unlock(&stream->lock);
384 return -EIO;
385 }
386 } else if (stream->ops == STREAM_OPS_CAPTURE) {
387 if (sst_capture_frame(str_id) < 0) {
388 pr_warn("capture frames failed\n");
389 mutex_unlock(&stream->lock);
390 return -EIO;
391 }
392 }
393 } else {
394 mutex_unlock(&stream->lock);
395 return -EIO;
396 }
397 mutex_unlock(&stream->lock);
398 /* Block the call for reply */
399
400 retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
401 if (retval) {
402 stream->status = STREAM_INIT;
403 pr_debug("wait returned error...\n");
404 }
405 return retval;
406}
407
408/* fills kernel list with buffer addresses for SST DSP driver to process*/
409static int snd_sst_fill_kernel_list(struct stream_info *stream,
410 const struct iovec *iovec, unsigned long nr_segs,
411 struct list_head *copy_to_list)
412{
413 struct sst_stream_bufs *stream_bufs;
414 unsigned long index, mmap_len;
415 unsigned char __user *bufp;
416 unsigned long size, copied_size;
417 int retval = 0, add_to_list = 0;
418 static int sent_offset;
419 static unsigned long sent_index;
420
421#ifdef CONFIG_MRST_RAR_HANDLER
422 if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
423 for (index = stream->sg_index; index < nr_segs; index++) {
424 __u32 rar_handle;
425 struct sst_stream_bufs *stream_bufs =
426 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
427
428 stream->sg_index = index;
429 if (!stream_bufs)
430 return -ENOMEM;
431 if (copy_from_user((void *) &rar_handle,
432 iovec[index].iov_base,
433 sizeof(__u32))) {
434 kfree(stream_bufs);
435 return -EFAULT;
436 }
437 stream_bufs->addr = (char *)rar_handle;
438 stream_bufs->in_use = false;
439 stream_bufs->size = iovec[0].iov_len;
440 /* locking here */
441 mutex_lock(&stream->lock);
442 list_add_tail(&stream_bufs->node, &stream->bufs);
443 mutex_unlock(&stream->lock);
444 }
445 stream->sg_index = index;
446 return retval;
447 }
448#endif
449 stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
450 if (!stream_bufs)
451 return -ENOMEM;
452 stream_bufs->addr = sst_drv_ctx->mmap_mem;
453 mmap_len = sst_drv_ctx->mmap_len;
454 stream_bufs->addr = sst_drv_ctx->mmap_mem;
455 bufp = stream->cur_ptr;
456
457 copied_size = 0;
458
459 if (!stream->sg_index)
460 sent_index = sent_offset = 0;
461
462 for (index = stream->sg_index; index < nr_segs; index++) {
463 stream->sg_index = index;
464 if (!stream->cur_ptr)
465 bufp = iovec[index].iov_base;
466
467 size = ((unsigned long)iovec[index].iov_base
468 + iovec[index].iov_len) - (unsigned long) bufp;
469
470 if ((copied_size + size) > mmap_len)
471 size = mmap_len - copied_size;
472
473
474 if (stream->ops == STREAM_OPS_PLAYBACK) {
475 if (copy_from_user((void *)
476 (stream_bufs->addr + copied_size),
477 bufp, size)) {
478 /* Clean up the list and return error code */
479 retval = -EFAULT;
480 break;
481 }
482 } else if (stream->ops == STREAM_OPS_CAPTURE) {
483 struct snd_sst_user_cap_list *entry =
484 kzalloc(sizeof(*entry), GFP_KERNEL);
485
486 if (!entry) {
487 kfree(stream_bufs);
488 return -ENOMEM;
489 }
490 entry->iov_index = index;
491 entry->iov_offset = (unsigned long) bufp -
492 (unsigned long)iovec[index].iov_base;
493 entry->offset = copied_size;
494 entry->size = size;
495 list_add_tail(&entry->node, copy_to_list);
496 }
497
498 stream->cur_ptr = bufp + size;
499
500 if (((unsigned long)iovec[index].iov_base
501 + iovec[index].iov_len) <
502 ((unsigned long)iovec[index].iov_base)) {
503 pr_debug("Buffer overflows\n");
504 kfree(stream_bufs);
505 return -EINVAL;
506 }
507
508 if (((unsigned long)iovec[index].iov_base
509 + iovec[index].iov_len) ==
510 (unsigned long)stream->cur_ptr) {
511 stream->cur_ptr = NULL;
512 stream->sg_index++;
513 }
514
515 copied_size += size;
516 pr_debug("copied_size - %lx\n", copied_size);
517 if ((copied_size >= mmap_len) ||
518 (stream->sg_index == nr_segs)) {
519 add_to_list = 1;
520 }
521
522 if (add_to_list) {
523 stream_bufs->in_use = false;
524 stream_bufs->size = copied_size;
525 /* locking here */
526 mutex_lock(&stream->lock);
527 list_add_tail(&stream_bufs->node, &stream->bufs);
528 mutex_unlock(&stream->lock);
529 break;
530 }
531 }
532 return retval;
533}
534
535/* This function copies the captured data returned from SST DSP engine
536 * to the user buffers*/
537static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
538 const struct iovec *iovec,
539 struct list_head *copy_to_list)
540{
541 struct snd_sst_user_cap_list *entry, *_entry;
542 struct sst_stream_bufs *kbufs = NULL, *_kbufs;
543 int retval = 0;
544
545 /* copy sent buffers */
546 pr_debug("capture stream copying to user now...\n");
547 list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
548 if (kbufs->in_use == true) {
549 /* copy to user */
550 list_for_each_entry_safe(entry, _entry,
551 copy_to_list, node) {
552 if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset,
553 kbufs->addr + entry->offset,
554 entry->size)) {
555 /* Clean up the list and return error */
556 retval = -EFAULT;
557 break;
558 }
559 list_del(&entry->node);
560 kfree(entry);
561 }
562 }
563 }
564 pr_debug("end of cap copy\n");
565 return retval;
566}
567
568/*
569 * snd_sst_userbufs_play_cap - constructs the list from user buffers
570 *
571 * @iovec:pointer to iovec structure
572 * @nr_segs:number entries in the iovec structure
573 * @str_id:stream id
574 * @stream:pointer to stream_info structure
575 *
576 * This function will traverse the user list and copy the data to the kernel
577 * space buffers.
578 */
579static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
580 unsigned long nr_segs, unsigned int str_id,
581 struct stream_info *stream)
582{
583 int retval;
584 LIST_HEAD(copy_to_list);
585
586
587 retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
588 &copy_to_list);
589
590 retval = intel_sst_play_capture(stream, str_id);
591 if (retval < 0)
592 return retval;
593
594 if (stream->ops == STREAM_OPS_CAPTURE) {
595 retval = snd_sst_copy_userbuf_capture(stream, iovec,
596 &copy_to_list);
597 }
598 return retval;
599}
600
601/* This function is common function across read/write
602 for user buffers called from system calls*/
603static int intel_sst_read_write(unsigned int str_id, char __user *buf,
604 size_t count)
605{
606 int retval;
607 struct stream_info *stream;
608 struct iovec iovec;
609 unsigned long nr_segs;
610
611 retval = sst_validate_strid(str_id);
612 if (retval)
613 return -EINVAL;
614 stream = &sst_drv_ctx->streams[str_id];
615 if (stream->mmapped == true) {
616 pr_warn("user write and stream is mapped\n");
617 return -EIO;
618 }
619 if (!count)
620 return -EINVAL;
621 stream->curr_bytes = 0;
622 stream->cumm_bytes = 0;
623 /* copy user buf details */
624 pr_debug("new buffers %p, copy size %d, status %d\n" ,
625 buf, (int) count, (int) stream->status);
626
627 stream->buf_type = SST_BUF_USER_STATIC;
628 iovec.iov_base = buf;
629 iovec.iov_len = count;
630 nr_segs = 1;
631
632 do {
633 retval = snd_sst_userbufs_play_cap(
634 &iovec, nr_segs, str_id, stream);
635 if (retval < 0)
636 break;
637
638 } while (stream->sg_index < nr_segs);
639
640 stream->sg_index = 0;
641 stream->cur_ptr = NULL;
642 if (retval >= 0)
643 retval = stream->cumm_bytes;
644 pr_debug("end of play/rec bytes = %d!!\n", retval);
645 return retval;
646}
647
648/***
649 * intel_sst_write - This function is called when user tries to play out data
650 *
651 * @file_ptr:pointer to file
652 * @buf:user buffer to be played out
653 * @count:size of tthe buffer
654 * @offset:offset to start from
655 *
656 * writes the encoded data into DSP
657 */
658int intel_sst_write(struct file *file_ptr, const char __user *buf,
659 size_t count, loff_t *offset)
660{
661 struct ioctl_pvt_data *data = file_ptr->private_data;
662 int str_id = data->str_id;
663 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
664
665 pr_debug("called for %d\n", str_id);
666 if (stream->status == STREAM_UN_INIT ||
667 stream->status == STREAM_DECODE) {
668 return -EBADRQC;
669 }
670 return intel_sst_read_write(str_id, (char __user *)buf, count);
671}
672
673/*
674 * intel_sst_aio_write - write buffers
675 *
676 * @kiocb:pointer to a structure containing file pointer
677 * @iov:list of user buffer to be played out
678 * @nr_segs:number of entries
679 * @offset:offset to start from
680 *
681 * This function is called when user tries to play out multiple data buffers
682 */
683ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
684 unsigned long nr_segs, loff_t offset)
685{
686 int retval;
687 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
688 int str_id = data->str_id;
689 struct stream_info *stream;
690
691 pr_debug("entry - %ld\n", nr_segs);
692
693 if (is_sync_kiocb(kiocb) == false)
694 return -EINVAL;
695
696 pr_debug("called for str_id %d\n", str_id);
697 retval = sst_validate_strid(str_id);
698 if (retval)
699 return -EINVAL;
700 stream = &sst_drv_ctx->streams[str_id];
701 if (stream->mmapped == true)
702 return -EIO;
703 if (stream->status == STREAM_UN_INIT ||
704 stream->status == STREAM_DECODE) {
705 return -EBADRQC;
706 }
707 stream->curr_bytes = 0;
708 stream->cumm_bytes = 0;
709 pr_debug("new segs %ld, offset %d, status %d\n" ,
710 nr_segs, (int) offset, (int) stream->status);
711 stream->buf_type = SST_BUF_USER_STATIC;
712 do {
713 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
714 str_id, stream);
715 if (retval < 0)
716 break;
717
718 } while (stream->sg_index < nr_segs);
719
720 stream->sg_index = 0;
721 stream->cur_ptr = NULL;
722 if (retval >= 0)
723 retval = stream->cumm_bytes;
724 pr_debug("end of play/rec bytes = %d!!\n", retval);
725 return retval;
726}
727
728/*
729 * intel_sst_read - read the encoded data
730 *
731 * @file_ptr: pointer to file
732 * @buf: user buffer to be filled with captured data
733 * @count: size of tthe buffer
734 * @offset: offset to start from
735 *
736 * This function is called when user tries to capture data
737 */
738int intel_sst_read(struct file *file_ptr, char __user *buf,
739 size_t count, loff_t *offset)
740{
741 struct ioctl_pvt_data *data = file_ptr->private_data;
742 int str_id = data->str_id;
743 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
744
745 pr_debug("called for %d\n", str_id);
746 if (stream->status == STREAM_UN_INIT ||
747 stream->status == STREAM_DECODE)
748 return -EBADRQC;
749 return intel_sst_read_write(str_id, buf, count);
750}
751
752/*
753 * intel_sst_aio_read - aio read
754 *
755 * @kiocb: pointer to a structure containing file pointer
756 * @iov: list of user buffer to be filled with captured
757 * @nr_segs: number of entries
758 * @offset: offset to start from
759 *
760 * This function is called when user tries to capture out multiple data buffers
761 */
762ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
763 unsigned long nr_segs, loff_t offset)
764{
765 int retval;
766 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
767 int str_id = data->str_id;
768 struct stream_info *stream;
769
770 pr_debug("entry - %ld\n", nr_segs);
771
772 if (is_sync_kiocb(kiocb) == false) {
773 pr_debug("aio_read from user space is not allowed\n");
774 return -EINVAL;
775 }
776
777 pr_debug("called for str_id %d\n", str_id);
778 retval = sst_validate_strid(str_id);
779 if (retval)
780 return -EINVAL;
781 stream = &sst_drv_ctx->streams[str_id];
782 if (stream->mmapped == true)
783 return -EIO;
784 if (stream->status == STREAM_UN_INIT ||
785 stream->status == STREAM_DECODE)
786 return -EBADRQC;
787 stream->curr_bytes = 0;
788 stream->cumm_bytes = 0;
789
790 pr_debug("new segs %ld, offset %d, status %d\n" ,
791 nr_segs, (int) offset, (int) stream->status);
792 stream->buf_type = SST_BUF_USER_STATIC;
793 do {
794 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
795 str_id, stream);
796 if (retval < 0)
797 break;
798
799 } while (stream->sg_index < nr_segs);
800
801 stream->sg_index = 0;
802 stream->cur_ptr = NULL;
803 if (retval >= 0)
804 retval = stream->cumm_bytes;
805 pr_debug("end of play/rec bytes = %d!!\n", retval);
806 return retval;
807}
808
809/* sst_print_stream_params - prints the stream parameters (debug fn)*/
810static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
811{
812 pr_debug("codec params:result = %d\n",
813 get_prm->codec_params.result);
814 pr_debug("codec params:stream = %d\n",
815 get_prm->codec_params.stream_id);
816 pr_debug("codec params:codec = %d\n",
817 get_prm->codec_params.codec);
818 pr_debug("codec params:ops = %d\n",
819 get_prm->codec_params.ops);
820 pr_debug("codec params:stream_type = %d\n",
821 get_prm->codec_params.stream_type);
822 pr_debug("pcmparams:sfreq = %d\n",
823 get_prm->pcm_params.sfreq);
824 pr_debug("pcmparams:num_chan = %d\n",
825 get_prm->pcm_params.num_chan);
826 pr_debug("pcmparams:pcm_wd_sz = %d\n",
827 get_prm->pcm_params.pcm_wd_sz);
828 return;
829}
830
831/**
832 * sst_create_algo_ipc - create ipc msg for algorithm parameters
833 *
834 * @algo_params: Algorithm parameters
835 * @msg: post msg pointer
836 *
837 * This function is called to create ipc msg
838 */
839int sst_create_algo_ipc(struct snd_ppp_params *algo_params,
840 struct ipc_post **msg)
841{
842 if (sst_create_large_msg(msg))
843 return -ENOMEM;
844 sst_fill_header(&(*msg)->header,
845 IPC_IA_ALG_PARAMS, 1, algo_params->str_id);
846 (*msg)->header.part.data = sizeof(u32) +
847 sizeof(*algo_params) + algo_params->size;
848 memcpy((*msg)->mailbox_data, &(*msg)->header, sizeof(u32));
849 memcpy((*msg)->mailbox_data + sizeof(u32),
850 algo_params, sizeof(*algo_params));
851 return 0;
852}
853
854/**
855 * sst_send_algo_ipc - send ipc msg for algorithm parameters
856 *
857 * @msg: post msg pointer
858 *
859 * This function is called to send ipc msg
860 */
861int sst_send_algo_ipc(struct ipc_post **msg)
862{
863 sst_drv_ctx->ppp_params_blk.condition = false;
864 sst_drv_ctx->ppp_params_blk.ret_code = 0;
865 sst_drv_ctx->ppp_params_blk.on = true;
866 sst_drv_ctx->ppp_params_blk.data = NULL;
867 spin_lock(&sst_drv_ctx->list_spin_lock);
868 list_add_tail(&(*msg)->node, &sst_drv_ctx->ipc_dispatch_list);
869 spin_unlock(&sst_drv_ctx->list_spin_lock);
870 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
871 return sst_wait_interruptible_timeout(sst_drv_ctx,
872 &sst_drv_ctx->ppp_params_blk, SST_BLOCK_TIMEOUT);
873}
874
875/**
876 * intel_sst_ioctl_dsp - receives the device ioctl's
877 *
878 * @cmd:Ioctl cmd
879 * @arg:data
880 *
881 * This function is called when a user space component
882 * sends a DSP Ioctl to SST driver
883 */
884long intel_sst_ioctl_dsp(unsigned int cmd, unsigned long arg)
885{
886 int retval = 0;
887 struct snd_ppp_params algo_params;
888 struct snd_ppp_params *algo_params_copied;
889 struct ipc_post *msg;
890
891 switch (_IOC_NR(cmd)) {
892 case _IOC_NR(SNDRV_SST_SET_ALGO):
893 if (copy_from_user(&algo_params, (void __user *)arg,
894 sizeof(algo_params)))
895 return -EFAULT;
896 if (algo_params.size > SST_MAILBOX_SIZE)
897 return -EMSGSIZE;
898
899 pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
900 algo_params.algo_id, algo_params.str_id,
901 algo_params.enable, algo_params.size);
902 retval = sst_create_algo_ipc(&algo_params, &msg);
903 if (retval)
904 break;
905 algo_params.reserved = 0;
906 if (copy_from_user(msg->mailbox_data + sizeof(algo_params),
907 algo_params.params, algo_params.size))
908 return -EFAULT;
909
910 retval = sst_send_algo_ipc(&msg);
911 if (retval) {
912 pr_debug("Error in sst_set_algo = %d\n", retval);
913 retval = -EIO;
914 }
915 break;
916
917 case _IOC_NR(SNDRV_SST_GET_ALGO):
918 if (copy_from_user(&algo_params, (void __user *)arg,
919 sizeof(algo_params)))
920 return -EFAULT;
921 pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
922 algo_params.algo_id, algo_params.str_id,
923 algo_params.enable, algo_params.size);
924 retval = sst_create_algo_ipc(&algo_params, &msg);
925 if (retval)
926 break;
927 algo_params.reserved = 1;
928 retval = sst_send_algo_ipc(&msg);
929 if (retval) {
930 pr_debug("Error in sst_get_algo = %d\n", retval);
931 retval = -EIO;
932 break;
933 }
934 algo_params_copied = (struct snd_ppp_params *)
935 sst_drv_ctx->ppp_params_blk.data;
936 if (algo_params_copied->size > algo_params.size) {
937 pr_debug("mem insufficient to copy\n");
938 retval = -EMSGSIZE;
939 goto free_mem;
940 } else {
941 char __user *tmp;
942
943 if (copy_to_user(algo_params.params,
944 algo_params_copied->params,
945 algo_params_copied->size)) {
946 retval = -EFAULT;
947 goto free_mem;
948 }
949 tmp = (char __user *)arg + offsetof(
950 struct snd_ppp_params, size);
951 if (copy_to_user(tmp, &algo_params_copied->size,
952 sizeof(__u32))) {
953 retval = -EFAULT;
954 goto free_mem;
955 }
956
957 }
958free_mem:
959 kfree(algo_params_copied->params);
960 kfree(algo_params_copied);
961 break;
962 }
963 return retval;
964}
965
966
967int sst_ioctl_tuning_params(unsigned long arg)
968{
969 struct snd_sst_tuning_params params;
970 struct ipc_post *msg;
971
972 if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
973 return -EFAULT;
974 if (params.size > SST_MAILBOX_SIZE)
975 return -ENOMEM;
976 pr_debug("Parameter %d, Stream %d, Size %d\n", params.type,
977 params.str_id, params.size);
978 if (sst_create_large_msg(&msg))
979 return -ENOMEM;
980
981 sst_fill_header(&msg->header, IPC_IA_TUNING_PARAMS, 1, params.str_id);
982 msg->header.part.data = sizeof(u32) + sizeof(params) + params.size;
983 memcpy(msg->mailbox_data, &msg->header.full, sizeof(u32));
984 memcpy(msg->mailbox_data + sizeof(u32), &params, sizeof(params));
985 if (copy_from_user(msg->mailbox_data + sizeof(params),
986 (void __user *)(unsigned long)params.addr,
987 params.size)) {
988 kfree(msg->mailbox_data);
989 kfree(msg);
990 return -EFAULT;
991 }
992 return sst_send_algo_ipc(&msg);
993}
994/**
995 * intel_sst_ioctl - receives the device ioctl's
996 * @file_ptr:pointer to file
997 * @cmd:Ioctl cmd
998 * @arg:data
999 *
1000 * This function is called by OS when a user space component
1001 * sends an Ioctl to SST driver
1002 */
1003long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
1004{
1005 int retval = 0;
1006 struct ioctl_pvt_data *data = NULL;
1007 int str_id = 0, minor = 0;
1008
1009 data = file_ptr->private_data;
1010 if (data) {
1011 minor = 0;
1012 str_id = data->str_id;
1013 } else
1014 minor = 1;
1015
1016 if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
1017 return -EBUSY;
1018
1019 switch (_IOC_NR(cmd)) {
1020 case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
1021 pr_debug("IOCTL_PAUSE received for %d!\n", str_id);
1022 if (minor != STREAM_MODULE) {
1023 retval = -EBADRQC;
1024 break;
1025 }
1026 retval = sst_pause_stream(str_id);
1027 break;
1028
1029 case _IOC_NR(SNDRV_SST_STREAM_RESUME):
1030 pr_debug("SNDRV_SST_IOCTL_RESUME received!\n");
1031 if (minor != STREAM_MODULE) {
1032 retval = -EBADRQC;
1033 break;
1034 }
1035 retval = sst_resume_stream(str_id);
1036 break;
1037
1038 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
1039 struct snd_sst_params str_param;
1040
1041 pr_debug("IOCTL_SET_PARAMS received!\n");
1042 if (minor != STREAM_MODULE) {
1043 retval = -EBADRQC;
1044 break;
1045 }
1046
1047 if (copy_from_user(&str_param, (void __user *)arg,
1048 sizeof(str_param))) {
1049 retval = -EFAULT;
1050 break;
1051 }
1052
1053 if (!str_id) {
1054
1055 retval = sst_get_stream(&str_param);
1056 if (retval > 0) {
1057 struct stream_info *str_info;
1058 char __user *dest;
1059
1060 sst_drv_ctx->stream_cnt++;
1061 data->str_id = retval;
1062 str_info = &sst_drv_ctx->streams[retval];
1063 str_info->src = SST_DRV;
1064 dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id);
1065 retval = copy_to_user(dest, &retval, sizeof(__u32));
1066 if (retval)
1067 retval = -EFAULT;
1068 } else {
1069 if (retval == -SST_ERR_INVALID_PARAMS)
1070 retval = -EINVAL;
1071 }
1072 } else {
1073 pr_debug("SET_STREAM_PARAMS received!\n");
1074 /* allocated set params only */
1075 retval = sst_set_stream_param(str_id, &str_param);
1076 /* Block the call for reply */
1077 if (!retval) {
1078 int sfreq = 0, word_size = 0, num_channel = 0;
1079 sfreq = str_param.sparams.uc.pcm_params.sfreq;
1080 word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
1081 num_channel = str_param.sparams.uc.pcm_params.num_chan;
1082 if (str_param.ops == STREAM_OPS_CAPTURE) {
1083 sst_drv_ctx->scard_ops->\
1084 set_pcm_audio_params(sfreq,
1085 word_size, num_channel);
1086 }
1087 }
1088 }
1089 break;
1090 }
1091 case _IOC_NR(SNDRV_SST_SET_VOL): {
1092 struct snd_sst_vol set_vol;
1093
1094 if (copy_from_user(&set_vol, (void __user *)arg,
1095 sizeof(set_vol))) {
1096 pr_debug("copy failed\n");
1097 retval = -EFAULT;
1098 break;
1099 }
1100 pr_debug("SET_VOLUME received for %d!\n",
1101 set_vol.stream_id);
1102 if (minor == STREAM_MODULE && set_vol.stream_id == 0) {
1103 pr_debug("invalid operation!\n");
1104 retval = -EPERM;
1105 break;
1106 }
1107 retval = sst_set_vol(&set_vol);
1108 break;
1109 }
1110 case _IOC_NR(SNDRV_SST_GET_VOL): {
1111 struct snd_sst_vol get_vol;
1112
1113 if (copy_from_user(&get_vol, (void __user *)arg,
1114 sizeof(get_vol))) {
1115 retval = -EFAULT;
1116 break;
1117 }
1118 pr_debug("IOCTL_GET_VOLUME received for stream = %d!\n",
1119 get_vol.stream_id);
1120 if (minor == STREAM_MODULE && get_vol.stream_id == 0) {
1121 pr_debug("invalid operation!\n");
1122 retval = -EPERM;
1123 break;
1124 }
1125 retval = sst_get_vol(&get_vol);
1126 if (retval) {
1127 retval = -EIO;
1128 break;
1129 }
1130 pr_debug("id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
1131 get_vol.stream_id, get_vol.volume,
1132 get_vol.ramp_duration, get_vol.ramp_type);
1133 if (copy_to_user((struct snd_sst_vol __user *)arg,
1134 &get_vol, sizeof(get_vol))) {
1135 retval = -EFAULT;
1136 break;
1137 }
1138 /*sst_print_get_vol_info(str_id, &get_vol);*/
1139 break;
1140 }
1141
1142 case _IOC_NR(SNDRV_SST_MUTE): {
1143 struct snd_sst_mute set_mute;
1144
1145 if (copy_from_user(&set_mute, (void __user *)arg,
1146 sizeof(set_mute))) {
1147 retval = -EFAULT;
1148 break;
1149 }
1150 pr_debug("SNDRV_SST_SET_VOLUME received for %d!\n",
1151 set_mute.stream_id);
1152 if (minor == STREAM_MODULE && set_mute.stream_id == 0) {
1153 retval = -EPERM;
1154 break;
1155 }
1156 retval = sst_set_mute(&set_mute);
1157 break;
1158 }
1159 case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
1160 struct snd_sst_get_stream_params get_params;
1161
1162 pr_debug("IOCTL_GET_PARAMS received!\n");
1163 if (minor != 0) {
1164 retval = -EBADRQC;
1165 break;
1166 }
1167
1168 retval = sst_get_stream_params(str_id, &get_params);
1169 if (retval) {
1170 retval = -EIO;
1171 break;
1172 }
1173 if (copy_to_user((struct snd_sst_get_stream_params __user *)arg,
1174 &get_params, sizeof(get_params))) {
1175 retval = -EFAULT;
1176 break;
1177 }
1178 sst_print_stream_params(&get_params);
1179 break;
1180 }
1181
1182 case _IOC_NR(SNDRV_SST_MMAP_PLAY):
1183 case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
1184 struct snd_sst_mmap_buffs mmap_buf;
1185
1186 pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE received!\n");
1187 if (minor != STREAM_MODULE) {
1188 retval = -EBADRQC;
1189 break;
1190 }
1191 if (copy_from_user(&mmap_buf, (void __user *)arg,
1192 sizeof(mmap_buf))) {
1193 retval = -EFAULT;
1194 break;
1195 }
1196 retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
1197 break;
1198 }
1199 case _IOC_NR(SNDRV_SST_STREAM_DROP):
1200 pr_debug("SNDRV_SST_IOCTL_DROP received!\n");
1201 if (minor != STREAM_MODULE) {
1202 retval = -EINVAL;
1203 break;
1204 }
1205 retval = sst_drop_stream(str_id);
1206 break;
1207
1208 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1209 struct snd_sst_tstamp tstamp = {0};
1210 unsigned long long time, freq, mod;
1211
1212 pr_debug("SNDRV_SST_STREAM_GET_TSTAMP received!\n");
1213 if (minor != STREAM_MODULE) {
1214 retval = -EBADRQC;
1215 break;
1216 }
1217 memcpy_fromio(&tstamp,
1218 sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1219 sizeof(tstamp));
1220 time = tstamp.samples_rendered;
1221 freq = (unsigned long long) tstamp.sampling_frequency;
1222 time = time * 1000; /* converting it to ms */
1223 mod = do_div(time, freq);
1224 if (copy_to_user((void __user *)arg, &time,
1225 sizeof(unsigned long long)))
1226 retval = -EFAULT;
1227 break;
1228 }
1229
1230 case _IOC_NR(SNDRV_SST_STREAM_START):{
1231 struct stream_info *stream;
1232
1233 pr_debug("SNDRV_SST_STREAM_START received!\n");
1234 if (minor != STREAM_MODULE) {
1235 retval = -EINVAL;
1236 break;
1237 }
1238 retval = sst_validate_strid(str_id);
1239 if (retval)
1240 break;
1241 stream = &sst_drv_ctx->streams[str_id];
1242 mutex_lock(&stream->lock);
1243 if (stream->status == STREAM_INIT &&
1244 stream->need_draining != true) {
1245 stream->prev = stream->status;
1246 stream->status = STREAM_RUNNING;
1247 if (stream->ops == STREAM_OPS_PLAYBACK ||
1248 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1249 retval = sst_play_frame(str_id);
1250 } else if (stream->ops == STREAM_OPS_CAPTURE)
1251 retval = sst_capture_frame(str_id);
1252 else {
1253 retval = -EINVAL;
1254 mutex_unlock(&stream->lock);
1255 break;
1256 }
1257 if (retval < 0) {
1258 stream->status = STREAM_INIT;
1259 mutex_unlock(&stream->lock);
1260 break;
1261 }
1262 } else {
1263 retval = -EINVAL;
1264 }
1265 mutex_unlock(&stream->lock);
1266 break;
1267 }
1268
1269 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1270 struct snd_sst_target_device target_device;
1271
1272 pr_debug("SET_TARGET_DEVICE received!\n");
1273 if (copy_from_user(&target_device, (void __user *)arg,
1274 sizeof(target_device))) {
1275 retval = -EFAULT;
1276 break;
1277 }
1278 if (minor != AM_MODULE) {
1279 retval = -EBADRQC;
1280 break;
1281 }
1282 retval = sst_target_device_select(&target_device);
1283 break;
1284 }
1285
1286 case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1287 struct snd_sst_driver_info info;
1288
1289 pr_debug("SNDRV_SST_DRIVER_INFO received\n");
1290 info.version = SST_VERSION_NUM;
1291 /* hard coding, shud get sumhow later */
1292 info.active_pcm_streams = sst_drv_ctx->stream_cnt -
1293 sst_drv_ctx->encoded_cnt;
1294 info.active_enc_streams = sst_drv_ctx->encoded_cnt;
1295 info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1296 info.max_enc_streams = MAX_ENC_STREAM;
1297 info.buf_per_stream = sst_drv_ctx->mmap_len;
1298 if (copy_to_user((void __user *)arg, &info,
1299 sizeof(info)))
1300 retval = -EFAULT;
1301 break;
1302 }
1303
1304 case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1305 struct snd_sst_dbufs param;
1306 struct snd_sst_dbufs dbufs_local;
1307 struct snd_sst_buffs ibufs, obufs;
1308 struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
1309 char __user *dest;
1310
1311 pr_debug("SNDRV_SST_STREAM_DECODE received\n");
1312 if (minor != STREAM_MODULE) {
1313 retval = -EBADRQC;
1314 break;
1315 }
1316 if (copy_from_user(&param, (void __user *)arg,
1317 sizeof(param))) {
1318 retval = -EFAULT;
1319 break;
1320 }
1321
1322 dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
1323 dbufs_local.output_bytes_produced =
1324 param.output_bytes_produced;
1325
1326 if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) {
1327 retval = -EFAULT;
1328 break;
1329 }
1330 if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) {
1331 retval = -EFAULT;
1332 break;
1333 }
1334
1335 ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
1336 obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
1337 if (!ibuf_tmp || !obuf_tmp) {
1338 retval = -ENOMEM;
1339 goto free_iobufs;
1340 }
1341
1342 if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry,
1343 ibufs.entries * sizeof(*ibuf_tmp))) {
1344 retval = -EFAULT;
1345 goto free_iobufs;
1346 }
1347 ibufs.buff_entry = ibuf_tmp;
1348 dbufs_local.ibufs = &ibufs;
1349
1350 if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry,
1351 obufs.entries * sizeof(*obuf_tmp))) {
1352 retval = -EFAULT;
1353 goto free_iobufs;
1354 }
1355 obufs.buff_entry = obuf_tmp;
1356 dbufs_local.obufs = &obufs;
1357
1358 retval = sst_decode(str_id, &dbufs_local);
1359 if (retval) {
1360 retval = -EAGAIN;
1361 goto free_iobufs;
1362 }
1363
1364 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1365 if (copy_to_user(dest,
1366 &dbufs_local.input_bytes_consumed,
1367 sizeof(unsigned long long))) {
1368 retval = -EFAULT;
1369 goto free_iobufs;
1370 }
1371
1372 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1373 if (copy_to_user(dest,
1374 &dbufs_local.output_bytes_produced,
1375 sizeof(unsigned long long))) {
1376 retval = -EFAULT;
1377 goto free_iobufs;
1378 }
1379free_iobufs:
1380 kfree(ibuf_tmp);
1381 kfree(obuf_tmp);
1382 break;
1383 }
1384
1385 case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1386 pr_debug("SNDRV_SST_STREAM_DRAIN received\n");
1387 if (minor != STREAM_MODULE) {
1388 retval = -EINVAL;
1389 break;
1390 }
1391 retval = sst_drain_stream(str_id);
1392 break;
1393
1394 case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1395 unsigned long long __user *bytes = (unsigned long long __user *)arg;
1396 struct snd_sst_tstamp tstamp = {0};
1397
1398 pr_debug("STREAM_BYTES_DECODED received!\n");
1399 if (minor != STREAM_MODULE) {
1400 retval = -EINVAL;
1401 break;
1402 }
1403 memcpy_fromio(&tstamp,
1404 sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1405 sizeof(tstamp));
1406 if (copy_to_user(bytes, &tstamp.bytes_processed,
1407 sizeof(*bytes)))
1408 retval = -EFAULT;
1409 break;
1410 }
1411 case _IOC_NR(SNDRV_SST_FW_INFO): {
1412 struct snd_sst_fw_info *fw_info;
1413
1414 pr_debug("SNDRV_SST_FW_INFO received\n");
1415
1416 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1417 if (!fw_info) {
1418 retval = -ENOMEM;
1419 break;
1420 }
1421 retval = sst_get_fw_info(fw_info);
1422 if (retval) {
1423 retval = -EIO;
1424 kfree(fw_info);
1425 break;
1426 }
1427 if (copy_to_user((struct snd_sst_dbufs __user *)arg,
1428 fw_info, sizeof(*fw_info))) {
1429 kfree(fw_info);
1430 retval = -EFAULT;
1431 break;
1432 }
1433 /*sst_print_fw_info(fw_info);*/
1434 kfree(fw_info);
1435 break;
1436 }
1437 case _IOC_NR(SNDRV_SST_GET_ALGO):
1438 case _IOC_NR(SNDRV_SST_SET_ALGO):
1439 if (minor != AM_MODULE) {
1440 retval = -EBADRQC;
1441 break;
1442 }
1443 retval = intel_sst_ioctl_dsp(cmd, arg);
1444 break;
1445
1446 case _IOC_NR(SNDRV_SST_TUNING_PARAMS):
1447 if (minor != AM_MODULE) {
1448 retval = -EBADRQC;
1449 break;
1450 }
1451 retval = sst_ioctl_tuning_params(arg);
1452 break;
1453
1454 default:
1455 retval = -EINVAL;
1456 }
1457 pr_debug("intel_sst_ioctl:complete ret code = %d\n", retval);
1458 return retval;
1459}
1460
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
new file mode 100644
index 00000000000..870981ba3c9
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -0,0 +1,623 @@
1#ifndef __INTEL_SST_COMMON_H__
2#define __INTEL_SST_COMMON_H__
3/*
4 * intel_sst_common.h - Intel SST Driver for audio engine
5 *
6 * Copyright (C) 2008-10 Intel Corporation
7 * Authors: Vinod Koul <vinod.koul@intel.com>
8 * Harsha Priya <priya.harsha@intel.com>
9 * Dharageswari R <dharageswari.r@intel.com>
10 * KP Jeeja <jeeja.kp@intel.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 *
28 * Common private declarations for SST
29 */
30
31#define SST_DRIVER_VERSION "1.2.17"
32#define SST_VERSION_NUM 0x1217
33
34/* driver names */
35#define SST_DRV_NAME "intel_sst_driver"
36#define SST_MRST_PCI_ID 0x080A
37#define SST_MFLD_PCI_ID 0x082F
38#define PCI_ID_LENGTH 4
39#define SST_SUSPEND_DELAY 2000
40#define FW_CONTEXT_MEM (64*1024)
41
42enum sst_states {
43 SST_FW_LOADED = 1,
44 SST_FW_RUNNING,
45 SST_UN_INIT,
46 SST_ERROR,
47 SST_SUSPENDED
48};
49
50#define MAX_ACTIVE_STREAM 3
51#define MAX_ENC_STREAM 1
52#define MAX_AM_HANDLES 1
53#define ALLOC_TIMEOUT 5000
54/* SST numbers */
55#define SST_BLOCK_TIMEOUT 5000
56#define TARGET_DEV_BLOCK_TIMEOUT 5000
57
58#define BLOCK_UNINIT -1
59#define RX_TIMESLOT_UNINIT -1
60
61/* SST register map */
62#define SST_CSR 0x00
63#define SST_PISR 0x08
64#define SST_PIMR 0x10
65#define SST_ISRX 0x18
66#define SST_IMRX 0x28
67#define SST_IPCX 0x38 /* IPC IA-SST */
68#define SST_IPCD 0x40 /* IPC SST-IA */
69#define SST_ISRD 0x20 /* dummy register for shim workaround */
70#define SST_SHIM_SIZE 0X44
71
72#define SPI_MODE_ENABLE_BASE_ADDR 0xffae4000
73#define FW_SIGNATURE_SIZE 4
74
75/* PMIC and SST hardware states */
76enum sst_mad_states {
77 SND_MAD_UN_INIT = 0,
78 SND_MAD_INIT_DONE,
79};
80
81/* stream states */
82enum sst_stream_states {
83 STREAM_UN_INIT = 0, /* Freed/Not used stream */
84 STREAM_RUNNING = 1, /* Running */
85 STREAM_PAUSED = 2, /* Paused stream */
86 STREAM_DECODE = 3, /* stream is in decoding only state */
87 STREAM_INIT = 4, /* stream init, waiting for data */
88};
89
90
91enum sst_ram_type {
92 SST_IRAM = 1,
93 SST_DRAM = 2,
94};
95/* SST shim registers to structure mapping */
96union config_status_reg {
97 struct {
98 u32 mfld_strb:1;
99 u32 sst_reset:1;
100 u32 hw_rsvd:3;
101 u32 sst_clk:2;
102 u32 bypass:3;
103 u32 run_stall:1;
104 u32 rsvd1:2;
105 u32 strb_cntr_rst:1;
106 u32 rsvd:18;
107 } part;
108 u32 full;
109};
110
111union interrupt_reg {
112 struct {
113 u32 done_interrupt:1;
114 u32 busy_interrupt:1;
115 u32 rsvd:30;
116 } part;
117 u32 full;
118};
119
120union sst_pisr_reg {
121 struct {
122 u32 pssp0:1;
123 u32 pssp1:1;
124 u32 rsvd0:3;
125 u32 dmac:1;
126 u32 rsvd1:26;
127 } part;
128 u32 full;
129};
130
131union sst_pimr_reg {
132 struct {
133 u32 ssp0:1;
134 u32 ssp1:1;
135 u32 rsvd0:3;
136 u32 dmac:1;
137 u32 rsvd1:10;
138 u32 ssp0_sc:1;
139 u32 ssp1_sc:1;
140 u32 rsvd2:3;
141 u32 dmac_sc:1;
142 u32 rsvd3:10;
143 } part;
144 u32 full;
145};
146
147
148struct sst_stream_bufs {
149 struct list_head node;
150 u32 size;
151 const char *addr;
152 u32 data_copied;
153 bool in_use;
154 u32 offset;
155};
156
157struct snd_sst_user_cap_list {
158 unsigned int iov_index; /* index of iov */
159 unsigned long iov_offset; /* offset in iov */
160 unsigned long offset; /* offset in kmem */
161 unsigned long size; /* size copied */
162 struct list_head node;
163};
164/*
165This structure is used to block a user/fw data call to another
166fw/user call
167*/
168struct sst_block {
169 bool condition; /* condition for blocking check */
170 int ret_code; /* ret code when block is released */
171 void *data; /* data to be appsed for block if any */
172 bool on;
173};
174
175enum snd_sst_buf_type {
176 SST_BUF_USER_STATIC = 1,
177 SST_BUF_USER_DYNAMIC,
178 SST_BUF_MMAP_STATIC,
179 SST_BUF_MMAP_DYNAMIC,
180};
181
182enum snd_src {
183 SST_DRV = 1,
184 MAD_DRV = 2
185};
186
187/**
188 * struct stream_info - structure that holds the stream information
189 *
190 * @status : stream current state
191 * @prev : stream prev state
192 * @codec : stream codec
193 * @sst_id : stream id
194 * @ops : stream operation pb/cp/drm...
195 * @bufs: stream buffer list
196 * @lock : stream mutex for protecting state
197 * @pcm_lock : spinlock for pcm path only
198 * @mmapped : is stream mmapped
199 * @sg_index : current stream user buffer index
200 * @cur_ptr : stream user buffer pointer
201 * @buf_entry : current user buffer
202 * @data_blk : stream block for data operations
203 * @ctrl_blk : stream block for ctrl operations
204 * @buf_type : stream user buffer type
205 * @pcm_substream : PCM substream
206 * @period_elapsed : PCM period elapsed callback
207 * @sfreq : stream sampling freq
208 * @decode_ibuf : Decoded i/p buffers pointer
209 * @decode_obuf : Decoded o/p buffers pointer
210 * @decode_isize : Decoded i/p buffers size
211 * @decode_osize : Decoded o/p buffers size
212 * @decode_ibuf_type : Decoded i/p buffer type
213 * @decode_obuf_type : Decoded o/p buffer type
214 * @idecode_alloc : Decode alloc index
215 * @need_draining : stream set for drain
216 * @str_type : stream type
217 * @curr_bytes : current bytes decoded
218 * @cumm_bytes : cummulative bytes decoded
219 * @str_type : stream type
220 * @src : stream source
221 * @device : output device type (medfield only)
222 * @pcm_slot : pcm slot value
223 */
224struct stream_info {
225 unsigned int status;
226 unsigned int prev;
227 u8 codec;
228 unsigned int sst_id;
229 unsigned int ops;
230 struct list_head bufs;
231 struct mutex lock; /* mutex */
232 spinlock_t pcm_lock;
233 bool mmapped;
234 unsigned int sg_index; /* current buf Index */
235 unsigned char __user *cur_ptr; /* Current static bufs */
236 struct snd_sst_buf_entry __user *buf_entry;
237 struct sst_block data_blk; /* stream ops block */
238 struct sst_block ctrl_blk; /* stream control cmd block */
239 enum snd_sst_buf_type buf_type;
240 void *pcm_substream;
241 void (*period_elapsed) (void *pcm_substream);
242 unsigned int sfreq;
243 void *decode_ibuf, *decode_obuf;
244 unsigned int decode_isize, decode_osize;
245 u8 decode_ibuf_type, decode_obuf_type;
246 unsigned int idecode_alloc;
247 unsigned int need_draining;
248 unsigned int str_type;
249 u32 curr_bytes;
250 u32 cumm_bytes;
251 u32 src;
252 enum snd_sst_audio_device_type device;
253 u8 pcm_slot;
254};
255
256/*
257 * struct stream_alloc_bloc - this structure is used for blocking the user's
258 * alloc calls to fw's response to alloc calls
259 *
260 * @sst_id : session id of blocked stream
261 * @ops_block : ops block struture
262 */
263struct stream_alloc_block {
264 int sst_id; /* session id of blocked stream */
265 struct sst_block ops_block; /* ops block struture */
266};
267
268#define SST_FW_SIGN "$SST"
269#define SST_FW_LIB_SIGN "$LIB"
270
271/*
272 * struct fw_header - FW file headers
273 *
274 * @signature : FW signature
275 * @modules : # of modules
276 * @file_format : version of header format
277 * @reserved : reserved fields
278 */
279struct fw_header {
280 unsigned char signature[FW_SIGNATURE_SIZE]; /* FW signature */
281 u32 file_size; /* size of fw minus this header */
282 u32 modules; /* # of modules */
283 u32 file_format; /* version of header format */
284 u32 reserved[4];
285};
286
287struct fw_module_header {
288 unsigned char signature[FW_SIGNATURE_SIZE]; /* module signature */
289 u32 mod_size; /* size of module */
290 u32 blocks; /* # of blocks */
291 u32 type; /* codec type, pp lib */
292 u32 entry_point;
293};
294
295struct dma_block_info {
296 enum sst_ram_type type; /* IRAM/DRAM */
297 u32 size; /* Bytes */
298 u32 ram_offset; /* Offset in I/DRAM */
299 u32 rsvd; /* Reserved field */
300};
301
302struct ioctl_pvt_data {
303 int str_id;
304 int pvt_id;
305};
306
307struct sst_ipc_msg_wq {
308 union ipc_header header;
309 char mailbox[SST_MAILBOX_SIZE];
310 struct work_struct wq;
311};
312
313struct mad_ops_wq {
314 int stream_id;
315 enum sst_controls control_op;
316 struct work_struct wq;
317
318};
319
320#define SST_MMAP_PAGES (640*1024 / PAGE_SIZE)
321#define SST_MMAP_STEP (40*1024 / PAGE_SIZE)
322
323/***
324 * struct intel_sst_drv - driver ops
325 *
326 * @pmic_state : pmic state
327 * @pmic_vendor : pmic vendor detected
328 * @sst_state : current sst device state
329 * @pci_id : PCI device id loaded
330 * @shim : SST shim pointer
331 * @mailbox : SST mailbox pointer
332 * @iram : SST IRAM pointer
333 * @dram : SST DRAM pointer
334 * @shim_phy_add : SST shim phy addr
335 * @ipc_dispatch_list : ipc messages dispatched
336 * @ipc_post_msg_wq : wq to post IPC messages context
337 * @ipc_process_msg : wq to process msgs from FW context
338 * @ipc_process_reply : wq to process reply from FW context
339 * @ipc_post_msg : wq to post reply from FW context
340 * @mad_ops : MAD driver operations registered
341 * @mad_wq : MAD driver wq
342 * @post_msg_wq : wq to post IPC messages
343 * @process_msg_wq : wq to process msgs from FW
344 * @process_reply_wq : wq to process reply from FW
345 * @streams : sst stream contexts
346 * @alloc_block : block structure for alloc
347 * @tgt_dev_blk : block structure for target device
348 * @fw_info_blk : block structure for fw info block
349 * @vol_info_blk : block structure for vol info block
350 * @mute_info_blk : block structure for mute info block
351 * @hs_info_blk : block structure for hs info block
352 * @list_lock : sst driver list lock (deprecated)
353 * @list_spin_lock : sst driver spin lock block
354 * @scard_ops : sst card ops
355 * @pci : sst pci device struture
356 * @active_streams : sst active streams
357 * @sst_lock : sst device lock
358 * @stream_lock : sst stream lock
359 * @unique_id : sst unique id
360 * @stream_cnt : total sst active stream count
361 * @pb_streams : total active pb streams
362 * @cp_streams : total active cp streams
363 * @lpe_stalled : lpe stall status
364 * @pmic_port_instance : active pmic port instance
365 * @rx_time_slot_status : active rx slot
366 * @lpaudio_start : lpaudio status
367 * @audio_start : audio status
368 * @devt_d : pointer to /dev/lpe node
369 * @devt_c : pointer to /dev/lpe_ctrl node
370 * @max_streams : max streams allowed
371 */
372struct intel_sst_drv {
373 bool pmic_state;
374 int pmic_vendor;
375 int sst_state;
376 unsigned int pci_id;
377 void __iomem *shim;
378 void __iomem *mailbox;
379 void __iomem *iram;
380 void __iomem *dram;
381 unsigned int shim_phy_add;
382 struct list_head ipc_dispatch_list;
383 struct work_struct ipc_post_msg_wq;
384 struct sst_ipc_msg_wq ipc_process_msg;
385 struct sst_ipc_msg_wq ipc_process_reply;
386 struct sst_ipc_msg_wq ipc_post_msg;
387 struct mad_ops_wq mad_ops;
388 wait_queue_head_t wait_queue;
389 struct workqueue_struct *mad_wq;
390 struct workqueue_struct *post_msg_wq;
391 struct workqueue_struct *process_msg_wq;
392 struct workqueue_struct *process_reply_wq;
393
394 struct stream_info streams[MAX_NUM_STREAMS];
395 struct stream_alloc_block alloc_block[MAX_ACTIVE_STREAM];
396 struct sst_block tgt_dev_blk, fw_info_blk, ppp_params_blk,
397 vol_info_blk, mute_info_blk, hs_info_blk;
398 struct mutex list_lock;/* mutex for IPC list locking */
399 spinlock_t list_spin_lock; /* mutex for IPC list locking */
400 struct snd_pmic_ops *scard_ops;
401 struct pci_dev *pci;
402 int active_streams[MAX_NUM_STREAMS];
403 void *mmap_mem;
404 struct mutex sst_lock;
405 struct mutex stream_lock;
406 unsigned int mmap_len;
407 unsigned int unique_id;
408 unsigned int stream_cnt; /* total streams */
409 unsigned int encoded_cnt; /* enocded streams only */
410 unsigned int am_cnt;
411 unsigned int pb_streams; /* pb streams active */
412 unsigned int cp_streams; /* cp streams active */
413 unsigned int lpe_stalled; /* LPE is stalled or not */
414 unsigned int pmic_port_instance; /*pmic port instance*/
415 int rx_time_slot_status;
416 unsigned int lpaudio_start;
417 /* 1 - LPA stream(MP3 pb) in progress*/
418 unsigned int audio_start;
419 dev_t devt_d, devt_c;
420 unsigned int max_streams;
421 unsigned int *fw_cntx;
422 unsigned int fw_cntx_size;
423
424 unsigned int fw_downloaded;
425};
426
427extern struct intel_sst_drv *sst_drv_ctx;
428
429#define CHIP_REV_REG 0xff108000
430#define CHIP_REV_ADDR 0x78
431
432/* misc definitions */
433#define FW_DWNL_ID 0xFF
434#define LOOP1 0x11111111
435#define LOOP2 0x22222222
436#define LOOP3 0x33333333
437#define LOOP4 0x44444444
438
439#define SST_DEFAULT_PMIC_PORT 1 /*audio port*/
440/* NOTE: status will have +ve for good cases and -ve for error ones */
441#define MAX_STREAM_FIELD 255
442
443int sst_alloc_stream(char *params, unsigned int stream_ops, u8 codec,
444 unsigned int session_id);
445int sst_alloc_stream_response(unsigned int str_id,
446 struct snd_sst_alloc_response *response);
447int sst_stalled(void);
448int sst_pause_stream(int id);
449int sst_resume_stream(int id);
450int sst_enable_rx_timeslot(int status);
451int sst_drop_stream(int id);
452int sst_free_stream(int id);
453int sst_start_stream(int streamID);
454int sst_play_frame(int streamID);
455int sst_pcm_play_frame(int str_id, struct sst_stream_bufs *sst_buf);
456int sst_capture_frame(int streamID);
457int sst_set_stream_param(int streamID, struct snd_sst_params *str_param);
458int sst_target_device_select(struct snd_sst_target_device *target_device);
459int sst_decode(int str_id, struct snd_sst_dbufs *dbufs);
460int sst_get_decoded_bytes(int str_id, unsigned long long *bytes);
461int sst_get_fw_info(struct snd_sst_fw_info *info);
462int sst_get_stream_params(int str_id,
463 struct snd_sst_get_stream_params *get_params);
464int sst_get_stream(struct snd_sst_params *str_param);
465int sst_get_stream_allocated(struct snd_sst_params *str_param,
466 struct snd_sst_lib_download **lib_dnld);
467int sst_drain_stream(int str_id);
468int sst_get_vol(struct snd_sst_vol *set_vol);
469int sst_set_vol(struct snd_sst_vol *set_vol);
470int sst_set_mute(struct snd_sst_mute *set_mute);
471
472
473void sst_post_message(struct work_struct *work);
474void sst_process_message(struct work_struct *work);
475void sst_process_reply(struct work_struct *work);
476void sst_process_mad_ops(struct work_struct *work);
477void sst_process_mad_jack_detection(struct work_struct *work);
478
479long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd,
480 unsigned long arg);
481int intel_sst_open(struct inode *i_node, struct file *file_ptr);
482int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr);
483int intel_sst_release(struct inode *i_node, struct file *file_ptr);
484int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr);
485int intel_sst_read(struct file *file_ptr, char __user *buf,
486 size_t count, loff_t *ppos);
487int intel_sst_write(struct file *file_ptr, const char __user *buf,
488 size_t count, loff_t *ppos);
489int intel_sst_mmap(struct file *fp, struct vm_area_struct *vma);
490ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
491 unsigned long nr_segs, loff_t offset);
492ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
493 unsigned long nr_segs, loff_t offset);
494
495int sst_load_fw(const struct firmware *fw, void *context);
496int sst_load_library(struct snd_sst_lib_download *lib, u8 ops);
497int sst_spi_mode_enable(void);
498int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx);
499
500int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
501 struct sst_block *block);
502int sst_wait_interruptible_timeout(struct intel_sst_drv *sst_drv_ctx,
503 struct sst_block *block, int timeout);
504int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
505 struct stream_alloc_block *block);
506int sst_create_large_msg(struct ipc_post **arg);
507int sst_create_short_msg(struct ipc_post **arg);
508void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx,
509 u8 sst_id, int status, void *data);
510void sst_clear_interrupt(void);
511int intel_sst_resume(struct pci_dev *pci);
512int sst_download_fw(void);
513void free_stream_context(unsigned int str_id);
514void sst_clean_stream(struct stream_info *stream);
515
516/*
517 * sst_fill_header - inline to fill sst header
518 *
519 * @header : ipc header
520 * @msg : IPC message to be sent
521 * @large : is ipc large msg
522 * @str_id : stream id
523 *
524 * this function is an inline function that sets the headers before
525 * sending a message
526 */
527static inline void sst_fill_header(union ipc_header *header,
528 int msg, int large, int str_id)
529{
530 header->part.msg_id = msg;
531 header->part.str_id = str_id;
532 header->part.large = large;
533 header->part.done = 0;
534 header->part.busy = 1;
535 header->part.data = 0;
536}
537
538/*
539 * sst_assign_pvt_id - assign a pvt id for stream
540 *
541 * @sst_drv_ctx : driver context
542 *
543 * this inline function assigns a private id for calls that dont have stream
544 * context yet, should be called with lock held
545 */
546static inline unsigned int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx)
547{
548 sst_drv_ctx->unique_id++;
549 if (sst_drv_ctx->unique_id >= MAX_NUM_STREAMS)
550 sst_drv_ctx->unique_id = 1;
551 return sst_drv_ctx->unique_id;
552}
553
554/*
555 * sst_init_stream - this function initialzes stream context
556 *
557 * @stream : stream struture
558 * @codec : codec for stream
559 * @sst_id : stream id
560 * @ops : stream operation
561 * @slot : stream pcm slot
562 * @device : device type
563 *
564 * this inline function initialzes stream context for allocated stream
565 */
566static inline void sst_init_stream(struct stream_info *stream,
567 int codec, int sst_id, int ops, u8 slot,
568 enum snd_sst_audio_device_type device)
569{
570 stream->status = STREAM_INIT;
571 stream->prev = STREAM_UN_INIT;
572 stream->codec = codec;
573 stream->sst_id = sst_id;
574 stream->str_type = 0;
575 stream->ops = ops;
576 stream->data_blk.on = false;
577 stream->data_blk.condition = false;
578 stream->data_blk.ret_code = 0;
579 stream->data_blk.data = NULL;
580 stream->ctrl_blk.on = false;
581 stream->ctrl_blk.condition = false;
582 stream->ctrl_blk.ret_code = 0;
583 stream->ctrl_blk.data = NULL;
584 stream->need_draining = false;
585 stream->decode_ibuf = NULL;
586 stream->decode_isize = 0;
587 stream->mmapped = false;
588 stream->pcm_slot = slot;
589 stream->device = device;
590}
591
592
593/*
594 * sst_validate_strid - this function validates the stream id
595 *
596 * @str_id : stream id to be validated
597 *
598 * returns 0 if valid stream
599 */
600static inline int sst_validate_strid(int str_id)
601{
602 if (str_id <= 0 || str_id > sst_drv_ctx->max_streams) {
603 pr_err("SST ERR: invalid stream id : %d MAX_STREAMS:%d\n",
604 str_id, sst_drv_ctx->max_streams);
605 return -EINVAL;
606 } else
607 return 0;
608}
609
610static inline int sst_shim_write(void __iomem *addr, int offset, int value)
611{
612
613 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
614 writel(value, addr + SST_ISRD); /*dummy*/
615 writel(value, addr + offset);
616 return 0;
617}
618
619static inline int sst_shim_read(void __iomem *addr, int offset)
620{
621 return readl(addr + offset);
622}
623#endif /* __INTEL_SST_COMMON_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
new file mode 100644
index 00000000000..69daa1404b6
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -0,0 +1,563 @@
1/*
2 * intel_sst_interface.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@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 * This driver exposes the audio engine functionalities to the ALSA
25 * and middleware.
26 * Upper layer interfaces (MAD driver, MMF) to SST driver
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/delay.h>
32#include <linux/pci.h>
33#include <linux/fs.h>
34#include <linux/firmware.h>
35#include <linux/pm_runtime.h>
36#include "intel_sst.h"
37#include "intel_sst_ioctl.h"
38#include "intel_sst_fw_ipc.h"
39#include "intel_sst_common.h"
40
41
42/*
43 * sst_download_fw - download the audio firmware to DSP
44 *
45 * This function is called when the FW needs to be downloaded to SST DSP engine
46 */
47int sst_download_fw(void)
48{
49 int retval;
50 const struct firmware *fw_sst;
51 char name[20];
52
53 if (sst_drv_ctx->sst_state != SST_UN_INIT)
54 return -EPERM;
55
56 /* Reload firmware is not needed for MRST */
57 if ( (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) && sst_drv_ctx->fw_downloaded) {
58 pr_debug("FW already downloaded, skip for MRST platform\n");
59 sst_drv_ctx->sst_state = SST_FW_RUNNING;
60 return 0;
61 }
62
63 snprintf(name, sizeof(name), "%s%04x%s", "fw_sst_",
64 sst_drv_ctx->pci_id, ".bin");
65
66 pr_debug("Downloading %s FW now...\n", name);
67 retval = request_firmware(&fw_sst, name, &sst_drv_ctx->pci->dev);
68 if (retval) {
69 pr_err("request fw failed %d\n", retval);
70 return retval;
71 }
72 sst_drv_ctx->alloc_block[0].sst_id = FW_DWNL_ID;
73 sst_drv_ctx->alloc_block[0].ops_block.condition = false;
74 retval = sst_load_fw(fw_sst, NULL);
75 if (retval)
76 goto end_restore;
77
78 retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]);
79 if (retval)
80 pr_err("fw download failed %d\n" , retval);
81 else
82 sst_drv_ctx->fw_downloaded = 1;
83
84end_restore:
85 release_firmware(fw_sst);
86 sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT;
87 return retval;
88}
89
90
91/*
92 * sst_stalled - this function checks if the lpe is in stalled state
93 */
94int sst_stalled(void)
95{
96 int retry = 1000;
97 int retval = -1;
98
99 while (retry) {
100 if (!sst_drv_ctx->lpe_stalled)
101 return 0;
102 /*wait for time and re-check*/
103 msleep(1);
104
105 retry--;
106 }
107 pr_debug("in Stalled State\n");
108 return retval;
109}
110
111void free_stream_context(unsigned int str_id)
112{
113 struct stream_info *stream;
114
115 if (!sst_validate_strid(str_id)) {
116 /* str_id is valid, so stream is alloacted */
117 stream = &sst_drv_ctx->streams[str_id];
118 if (sst_free_stream(str_id))
119 sst_clean_stream(&sst_drv_ctx->streams[str_id]);
120 if (stream->ops == STREAM_OPS_PLAYBACK ||
121 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
122 sst_drv_ctx->pb_streams--;
123 if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
124 sst_drv_ctx->scard_ops->power_down_pmic_pb(
125 stream->device);
126 else {
127 if (sst_drv_ctx->pb_streams == 0)
128 sst_drv_ctx->scard_ops->
129 power_down_pmic_pb(stream->device);
130 }
131 } else if (stream->ops == STREAM_OPS_CAPTURE) {
132 sst_drv_ctx->cp_streams--;
133 if (sst_drv_ctx->cp_streams == 0)
134 sst_drv_ctx->scard_ops->power_down_pmic_cp(
135 stream->device);
136 }
137 if (sst_drv_ctx->pb_streams == 0
138 && sst_drv_ctx->cp_streams == 0)
139 sst_drv_ctx->scard_ops->power_down_pmic();
140 }
141}
142
143/*
144 * sst_get_stream_allocated - this function gets a stream allocated with
145 * the given params
146 *
147 * @str_param : stream params
148 * @lib_dnld : pointer to pointer of lib downlaod struct
149 *
150 * This creates new stream id for a stream, in case lib is to be downloaded to
151 * DSP, it downloads that
152 */
153int sst_get_stream_allocated(struct snd_sst_params *str_param,
154 struct snd_sst_lib_download **lib_dnld)
155{
156 int retval, str_id;
157 struct stream_info *str_info;
158
159 retval = sst_alloc_stream((char *) &str_param->sparams, str_param->ops,
160 str_param->codec, str_param->device_type);
161 if (retval < 0) {
162 pr_err("sst_alloc_stream failed %d\n", retval);
163 return retval;
164 }
165 pr_debug("Stream allocated %d\n", retval);
166 str_id = retval;
167 str_info = &sst_drv_ctx->streams[str_id];
168 /* Block the call for reply */
169 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
170 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
171 if ((retval != 0) || (str_info->ctrl_blk.ret_code != 0)) {
172 pr_debug("FW alloc failed retval %d, ret_code %d\n",
173 retval, str_info->ctrl_blk.ret_code);
174 str_id = -str_info->ctrl_blk.ret_code; /*return error*/
175 *lib_dnld = str_info->ctrl_blk.data;
176 sst_clean_stream(str_info);
177 } else
178 pr_debug("FW Stream allocated success\n");
179 return str_id; /*will ret either error (in above if) or correct str id*/
180}
181
182/*
183 * sst_get_sfreq - this function returns the frequency of the stream
184 *
185 * @str_param : stream params
186 */
187static int sst_get_sfreq(struct snd_sst_params *str_param)
188{
189 switch (str_param->codec) {
190 case SST_CODEC_TYPE_PCM:
191 return 48000; /*str_param->sparams.uc.pcm_params.sfreq;*/
192 case SST_CODEC_TYPE_MP3:
193 return str_param->sparams.uc.mp3_params.sfreq;
194 case SST_CODEC_TYPE_AAC:
195 return str_param->sparams.uc.aac_params.sfreq;
196 case SST_CODEC_TYPE_WMA9:
197 return str_param->sparams.uc.wma_params.sfreq;
198 default:
199 return 0;
200 }
201}
202
203/*
204 * sst_get_stream - this function prepares for stream allocation
205 *
206 * @str_param : stream param
207 */
208int sst_get_stream(struct snd_sst_params *str_param)
209{
210 int i, retval;
211 struct stream_info *str_info;
212 struct snd_sst_lib_download *lib_dnld;
213
214 /* stream is not allocated, we are allocating */
215 retval = sst_get_stream_allocated(str_param, &lib_dnld);
216 if (retval == -(SST_LIB_ERR_LIB_DNLD_REQUIRED)) {
217 /* codec download is required */
218 struct snd_sst_alloc_response *response;
219
220 pr_debug("Codec is required.... trying that\n");
221 if (lib_dnld == NULL) {
222 pr_err("lib download null!!! abort\n");
223 return -EIO;
224 }
225 i = sst_get_block_stream(sst_drv_ctx);
226 response = sst_drv_ctx->alloc_block[i].ops_block.data;
227 pr_debug("alloc block allocated = %d\n", i);
228 if (i < 0) {
229 kfree(lib_dnld);
230 return -ENOMEM;
231 }
232 retval = sst_load_library(lib_dnld, str_param->ops);
233 kfree(lib_dnld);
234
235 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
236 if (!retval) {
237 pr_debug("codec was downloaded successfully\n");
238
239 retval = sst_get_stream_allocated(str_param, &lib_dnld);
240 if (retval <= 0)
241 goto err;
242
243 pr_debug("Alloc done stream id %d\n", retval);
244 } else {
245 pr_debug("codec download failed\n");
246 retval = -EIO;
247 goto err;
248 }
249 } else if (retval <= 0)
250 goto err;
251 /*else
252 set_port_params(str_param, str_param->ops);*/
253
254 /* store sampling freq */
255 str_info = &sst_drv_ctx->streams[retval];
256 str_info->sfreq = sst_get_sfreq(str_param);
257
258 /* power on the analog, if reqd */
259 if (str_param->ops == STREAM_OPS_PLAYBACK ||
260 str_param->ops == STREAM_OPS_PLAYBACK_DRM) {
261 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
262 sst_drv_ctx->scard_ops->power_up_pmic_pb(
263 sst_drv_ctx->pmic_port_instance);
264 else
265 sst_drv_ctx->scard_ops->power_up_pmic_pb(
266 str_info->device);
267 /*Only if the playback is MP3 - Send a message*/
268 sst_drv_ctx->pb_streams++;
269 } else if (str_param->ops == STREAM_OPS_CAPTURE) {
270
271 sst_drv_ctx->scard_ops->power_up_pmic_cp(
272 sst_drv_ctx->pmic_port_instance);
273 /*Send a messageif not sent already*/
274 sst_drv_ctx->cp_streams++;
275 }
276
277err:
278 return retval;
279}
280
281void sst_process_mad_ops(struct work_struct *work)
282{
283
284 struct mad_ops_wq *mad_ops =
285 container_of(work, struct mad_ops_wq, wq);
286 int retval = 0;
287
288 switch (mad_ops->control_op) {
289 case SST_SND_PAUSE:
290 retval = sst_pause_stream(mad_ops->stream_id);
291 break;
292 case SST_SND_RESUME:
293 retval = sst_resume_stream(mad_ops->stream_id);
294 break;
295 case SST_SND_DROP:
296 retval = sst_drop_stream(mad_ops->stream_id);
297 break;
298 case SST_SND_START:
299 pr_debug("SST Debug: start stream\n");
300 retval = sst_start_stream(mad_ops->stream_id);
301 break;
302 case SST_SND_STREAM_PROCESS:
303 pr_debug("play/capt frames...\n");
304 break;
305 default:
306 pr_err(" wrong control_ops reported\n");
307 }
308 return;
309}
310
311void send_intial_rx_timeslot(void)
312{
313 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID &&
314 sst_drv_ctx->rx_time_slot_status != RX_TIMESLOT_UNINIT
315 && sst_drv_ctx->pmic_vendor != SND_NC)
316 sst_enable_rx_timeslot(sst_drv_ctx->rx_time_slot_status);
317}
318
319/*
320 * sst_open_pcm_stream - Open PCM interface
321 *
322 * @str_param: parameters of pcm stream
323 *
324 * This function is called by MID sound card driver to open
325 * a new pcm interface
326 */
327int sst_open_pcm_stream(struct snd_sst_params *str_param)
328{
329 struct stream_info *str_info;
330 int retval;
331
332 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
333
334 if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
335 /* LPE is suspended, resume it before proceeding*/
336 pr_debug("Resuming from Suspended state\n");
337 retval = intel_sst_resume(sst_drv_ctx->pci);
338 if (retval) {
339 pr_err("Resume Failed = %#x, abort\n", retval);
340 pm_runtime_put(&sst_drv_ctx->pci->dev);
341 return retval;
342 }
343 }
344 if (sst_drv_ctx->sst_state == SST_UN_INIT) {
345 /* FW is not downloaded */
346 pr_debug("DSP Downloading FW now...\n");
347 retval = sst_download_fw();
348 if (retval) {
349 pr_err("FW download fail %x, abort\n", retval);
350 pm_runtime_put(&sst_drv_ctx->pci->dev);
351 return retval;
352 }
353 send_intial_rx_timeslot();
354 }
355
356 if (!str_param) {
357 pm_runtime_put(&sst_drv_ctx->pci->dev);
358 return -EINVAL;
359 }
360
361 retval = sst_get_stream(str_param);
362 if (retval > 0) {
363 sst_drv_ctx->stream_cnt++;
364 str_info = &sst_drv_ctx->streams[retval];
365 str_info->src = MAD_DRV;
366 } else
367 pm_runtime_put(&sst_drv_ctx->pci->dev);
368
369 return retval;
370}
371
372/*
373 * sst_close_pcm_stream - Close PCM interface
374 *
375 * @str_id: stream id to be closed
376 *
377 * This function is called by MID sound card driver to close
378 * an existing pcm interface
379 */
380int sst_close_pcm_stream(unsigned int str_id)
381{
382 struct stream_info *stream;
383
384 pr_debug("sst: stream free called\n");
385 if (sst_validate_strid(str_id))
386 return -EINVAL;
387 stream = &sst_drv_ctx->streams[str_id];
388 free_stream_context(str_id);
389 stream->pcm_substream = NULL;
390 stream->status = STREAM_UN_INIT;
391 stream->period_elapsed = NULL;
392 sst_drv_ctx->stream_cnt--;
393 pr_debug("sst: will call runtime put now\n");
394 pm_runtime_put(&sst_drv_ctx->pci->dev);
395 return 0;
396}
397
398/*
399 * sst_device_control - Set Control params
400 *
401 * @cmd: control cmd to be set
402 * @arg: command argument
403 *
404 * This function is called by MID sound card driver to set
405 * SST/Sound card controls for an opened stream.
406 * This is registered with MID driver
407 */
408int sst_device_control(int cmd, void *arg)
409{
410 int retval = 0, str_id = 0;
411
412 switch (cmd) {
413 case SST_SND_PAUSE:
414 case SST_SND_RESUME:
415 case SST_SND_DROP:
416 case SST_SND_START:
417 sst_drv_ctx->mad_ops.control_op = cmd;
418 sst_drv_ctx->mad_ops.stream_id = *(int *)arg;
419 queue_work(sst_drv_ctx->mad_wq, &sst_drv_ctx->mad_ops.wq);
420 break;
421
422 case SST_SND_STREAM_INIT: {
423 struct pcm_stream_info *str_info;
424 struct stream_info *stream;
425
426 pr_debug("stream init called\n");
427 str_info = (struct pcm_stream_info *)arg;
428 str_id = str_info->str_id;
429 retval = sst_validate_strid(str_id);
430 if (retval)
431 break;
432
433 stream = &sst_drv_ctx->streams[str_id];
434 pr_debug("setting the period ptrs\n");
435 stream->pcm_substream = str_info->mad_substream;
436 stream->period_elapsed = str_info->period_elapsed;
437 stream->sfreq = str_info->sfreq;
438 stream->prev = stream->status;
439 stream->status = STREAM_INIT;
440 break;
441 }
442
443 case SST_SND_BUFFER_POINTER: {
444 struct pcm_stream_info *stream_info;
445 struct snd_sst_tstamp fw_tstamp = {0,};
446 struct stream_info *stream;
447
448
449 stream_info = (struct pcm_stream_info *)arg;
450 str_id = stream_info->str_id;
451 retval = sst_validate_strid(str_id);
452 if (retval)
453 break;
454 stream = &sst_drv_ctx->streams[str_id];
455
456 if (!stream->pcm_substream)
457 break;
458 memcpy_fromio(&fw_tstamp,
459 ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
460 +(str_id * sizeof(fw_tstamp))),
461 sizeof(fw_tstamp));
462
463 pr_debug("Pointer Query on strid = %d ops %d\n",
464 str_id, stream->ops);
465
466 if (stream->ops == STREAM_OPS_PLAYBACK)
467 stream_info->buffer_ptr = fw_tstamp.samples_rendered;
468 else
469 stream_info->buffer_ptr = fw_tstamp.samples_processed;
470 pr_debug("Samples rendered = %llu, buffer ptr %llu\n",
471 fw_tstamp.samples_rendered, stream_info->buffer_ptr);
472 break;
473 }
474 case SST_ENABLE_RX_TIME_SLOT: {
475 int status = *(int *)arg;
476 sst_drv_ctx->rx_time_slot_status = status ;
477 sst_enable_rx_timeslot(status);
478 break;
479 }
480 default:
481 /* Illegal case */
482 pr_warn("illegal req\n");
483 return -EINVAL;
484 }
485
486 return retval;
487}
488
489
490struct intel_sst_pcm_control pcm_ops = {
491 .open = sst_open_pcm_stream,
492 .device_control = sst_device_control,
493 .close = sst_close_pcm_stream,
494};
495
496struct intel_sst_card_ops sst_pmic_ops = {
497 .pcm_control = &pcm_ops,
498};
499
500/*
501 * register_sst_card - function for sound card to register
502 *
503 * @card: pointer to structure of operations
504 *
505 * This function is called card driver loads and is ready for registration
506 */
507int register_sst_card(struct intel_sst_card_ops *card)
508{
509 if (!sst_drv_ctx) {
510 pr_err("No SST driver register card reject\n");
511 return -ENODEV;
512 }
513
514 if (!card || !card->module_name) {
515 pr_err("Null Pointer Passed\n");
516 return -EINVAL;
517 }
518 if (sst_drv_ctx->pmic_state == SND_MAD_UN_INIT) {
519 /* register this driver */
520 if ((strncmp(SST_CARD_NAMES, card->module_name,
521 strlen(SST_CARD_NAMES))) == 0) {
522 sst_drv_ctx->pmic_vendor = card->vendor_id;
523 sst_drv_ctx->scard_ops = card->scard_ops;
524 sst_pmic_ops.module_name = card->module_name;
525 sst_drv_ctx->pmic_state = SND_MAD_INIT_DONE;
526 sst_drv_ctx->rx_time_slot_status = 0; /*default AMIC*/
527 card->pcm_control = sst_pmic_ops.pcm_control;
528 return 0;
529 } else {
530 pr_err("strcmp fail %s\n", card->module_name);
531 return -EINVAL;
532 }
533
534 } else {
535 /* already registered a driver */
536 pr_err("Repeat for registration..denied\n");
537 return -EBADRQC;
538 }
539 /* The ASoC code doesn't set scard_ops */
540 if (sst_drv_ctx->scard_ops)
541 sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
542 return 0;
543}
544EXPORT_SYMBOL_GPL(register_sst_card);
545
546/*
547 * unregister_sst_card- function for sound card to un-register
548 *
549 * @card: pointer to structure of operations
550 *
551 * This function is called when card driver unloads
552 */
553void unregister_sst_card(struct intel_sst_card_ops *card)
554{
555 if (sst_pmic_ops.pcm_control == card->pcm_control) {
556 /* unreg */
557 sst_pmic_ops.module_name = "";
558 sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
559 pr_debug("Unregistered %s\n", card->module_name);
560 }
561 return;
562}
563EXPORT_SYMBOL_GPL(unregister_sst_card);
diff --git a/drivers/staging/intel_sst/intel_sst_dsp.c b/drivers/staging/intel_sst/intel_sst_dsp.c
new file mode 100644
index 00000000000..a89e1ade847
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_dsp.c
@@ -0,0 +1,496 @@
1/*
2 * intel_sst_dsp.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This driver exposes the audio engine functionalities to the ALSA
27 * and middleware.
28 *
29 * This file contains all dsp controlling functions like firmware download,
30 * setting/resetting dsp cores, etc
31 */
32
33#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34
35#include <linux/pci.h>
36#include <linux/fs.h>
37#include <linux/firmware.h>
38#include "intel_sst.h"
39#include "intel_sst_ioctl.h"
40#include "intel_sst_fw_ipc.h"
41#include "intel_sst_common.h"
42
43
44/**
45 * intel_sst_reset_dsp_mrst - Resetting SST DSP
46 *
47 * This resets DSP in case of MRST platfroms
48 */
49static int intel_sst_reset_dsp_mrst(void)
50{
51 union config_status_reg csr;
52
53 pr_debug("Resetting the DSP in mrst\n");
54 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
55 csr.full |= 0x382;
56 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
57 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
58 csr.part.strb_cntr_rst = 0;
59 csr.part.run_stall = 0x1;
60 csr.part.bypass = 0x7;
61 csr.part.sst_reset = 0x1;
62 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
63 return 0;
64}
65
66/**
67 * intel_sst_reset_dsp_medfield - Resetting SST DSP
68 *
69 * This resets DSP in case of Medfield platfroms
70 */
71static int intel_sst_reset_dsp_medfield(void)
72{
73 union config_status_reg csr;
74
75 pr_debug("Resetting the DSP in medfield\n");
76 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
77 csr.full |= 0x382;
78 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
79
80 return 0;
81}
82
83/**
84 * sst_start_mrst - Start the SST DSP processor
85 *
86 * This starts the DSP in MRST platfroms
87 */
88static int sst_start_mrst(void)
89{
90 union config_status_reg csr;
91
92 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
93 csr.part.bypass = 0;
94 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
95 csr.part.run_stall = 0;
96 csr.part.sst_reset = 0;
97 csr.part.strb_cntr_rst = 1;
98 pr_debug("Setting SST to execute_mrst 0x%x\n", csr.full);
99 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
100
101 return 0;
102}
103
104/**
105 * sst_start_medfield - Start the SST DSP processor
106 *
107 * This starts the DSP in MRST platfroms
108 */
109static int sst_start_medfield(void)
110{
111 union config_status_reg csr;
112
113 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
114 csr.part.bypass = 0;
115 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
116 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
117 csr.part.mfld_strb = 1;
118 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
119 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
120 csr.part.run_stall = 0;
121 csr.part.sst_reset = 0;
122 pr_debug("Starting the DSP_medfld %x\n", csr.full);
123 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
124 pr_debug("Starting the DSP_medfld\n");
125
126 return 0;
127}
128
129/**
130 * sst_parse_module - Parse audio FW modules
131 *
132 * @module: FW module header
133 *
134 * Parses modules that need to be placed in SST IRAM and DRAM
135 * returns error or 0 if module sizes are proper
136 */
137static int sst_parse_module(struct fw_module_header *module)
138{
139 struct dma_block_info *block;
140 u32 count;
141 void __iomem *ram;
142
143 pr_debug("module sign %s size %x blocks %x type %x\n",
144 module->signature, module->mod_size,
145 module->blocks, module->type);
146 pr_debug("module entrypoint 0x%x\n", module->entry_point);
147
148 block = (void *)module + sizeof(*module);
149
150 for (count = 0; count < module->blocks; count++) {
151 if (block->size <= 0) {
152 pr_err("block size invalid\n");
153 return -EINVAL;
154 }
155 switch (block->type) {
156 case SST_IRAM:
157 ram = sst_drv_ctx->iram;
158 break;
159 case SST_DRAM:
160 ram = sst_drv_ctx->dram;
161 break;
162 default:
163 pr_err("wrong ram type0x%x in block0x%x\n",
164 block->type, count);
165 return -EINVAL;
166 }
167 memcpy_toio(ram + block->ram_offset,
168 (void *)block + sizeof(*block), block->size);
169 block = (void *)block + sizeof(*block) + block->size;
170 }
171 return 0;
172}
173
174/**
175 * sst_parse_fw_image - parse and load FW
176 *
177 * @sst_fw: pointer to audio fw
178 *
179 * This function is called to parse and download the FW image
180 */
181static int sst_parse_fw_image(const struct firmware *sst_fw)
182{
183 struct fw_header *header;
184 u32 count;
185 int ret_val;
186 struct fw_module_header *module;
187
188 BUG_ON(!sst_fw);
189
190 /* Read the header information from the data pointer */
191 header = (struct fw_header *)sst_fw->data;
192
193 /* verify FW */
194 if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) ||
195 (sst_fw->size != header->file_size + sizeof(*header))) {
196 /* Invalid FW signature */
197 pr_err("Invalid FW sign/filesize mismatch\n");
198 return -EINVAL;
199 }
200 pr_debug("header sign=%s size=%x modules=%x fmt=%x size=%x\n",
201 header->signature, header->file_size, header->modules,
202 header->file_format, sizeof(*header));
203 module = (void *)sst_fw->data + sizeof(*header);
204 for (count = 0; count < header->modules; count++) {
205 /* module */
206 ret_val = sst_parse_module(module);
207 if (ret_val)
208 return ret_val;
209 module = (void *)module + sizeof(*module) + module->mod_size ;
210 }
211
212 return 0;
213}
214
215/**
216 * sst_load_fw - function to load FW into DSP
217 *
218 * @fw: Pointer to driver loaded FW
219 * @context: driver context
220 *
221 * This function is called by OS when the FW is loaded into kernel
222 */
223int sst_load_fw(const struct firmware *fw, void *context)
224{
225 int ret_val;
226
227 pr_debug("load_fw called\n");
228 BUG_ON(!fw);
229
230 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
231 ret_val = intel_sst_reset_dsp_mrst();
232 else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
233 ret_val = intel_sst_reset_dsp_medfield();
234 if (ret_val)
235 return ret_val;
236
237 ret_val = sst_parse_fw_image(fw);
238 if (ret_val)
239 return ret_val;
240 mutex_lock(&sst_drv_ctx->sst_lock);
241 sst_drv_ctx->sst_state = SST_FW_LOADED;
242 mutex_unlock(&sst_drv_ctx->sst_lock);
243 /* 7. ask scu to reset the bypass bits */
244 /* 8.bring sst out of reset */
245 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
246 ret_val = sst_start_mrst();
247 else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
248 ret_val = sst_start_medfield();
249 if (ret_val)
250 return ret_val;
251
252 pr_debug("fw loaded successful!!!\n");
253 return ret_val;
254}
255
256/*This function is called when any codec/post processing library
257 needs to be downloaded*/
258static int sst_download_library(const struct firmware *fw_lib,
259 struct snd_sst_lib_download_info *lib)
260{
261 /* send IPC message and wait */
262 int i;
263 u8 pvt_id;
264 struct ipc_post *msg = NULL;
265 union config_status_reg csr;
266 struct snd_sst_str_type str_type = {0};
267 int retval = 0;
268
269 if (sst_create_large_msg(&msg))
270 return -ENOMEM;
271
272 pvt_id = sst_assign_pvt_id(sst_drv_ctx);
273 i = sst_get_block_stream(sst_drv_ctx);
274 pr_debug("alloc block allocated = %d, pvt_id %d\n", i, pvt_id);
275 if (i < 0) {
276 kfree(msg);
277 return -ENOMEM;
278 }
279 sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
280 sst_fill_header(&msg->header, IPC_IA_PREP_LIB_DNLD, 1, pvt_id);
281 msg->header.part.data = sizeof(u32) + sizeof(str_type);
282 str_type.codec_type = lib->dload_lib.lib_info.lib_type;
283 /*str_type.pvt_id = pvt_id;*/
284 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
285 memcpy(msg->mailbox_data + sizeof(u32), &str_type, sizeof(str_type));
286 spin_lock(&sst_drv_ctx->list_spin_lock);
287 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
288 spin_unlock(&sst_drv_ctx->list_spin_lock);
289 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
290 retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]);
291 if (retval) {
292 /* error */
293 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
294 pr_err("Prep codec downloaded failed %d\n",
295 retval);
296 return -EIO;
297 }
298 pr_debug("FW responded, ready for download now...\n");
299 /* downloading on success */
300 mutex_lock(&sst_drv_ctx->sst_lock);
301 sst_drv_ctx->sst_state = SST_FW_LOADED;
302 mutex_unlock(&sst_drv_ctx->sst_lock);
303 csr.full = readl(sst_drv_ctx->shim + SST_CSR);
304 csr.part.run_stall = 1;
305 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
306
307 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
308 csr.part.bypass = 0x7;
309 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
310
311 sst_parse_fw_image(fw_lib);
312
313 /* set the FW to running again */
314 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
315 csr.part.bypass = 0x0;
316 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
317
318 csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
319 csr.part.run_stall = 0;
320 sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
321
322 /* send download complete and wait */
323 if (sst_create_large_msg(&msg)) {
324 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
325 return -ENOMEM;
326 }
327
328 sst_fill_header(&msg->header, IPC_IA_LIB_DNLD_CMPLT, 1, pvt_id);
329 sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
330 msg->header.part.data = sizeof(u32) + sizeof(*lib);
331 lib->pvt_id = pvt_id;
332 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
333 memcpy(msg->mailbox_data + sizeof(u32), lib, sizeof(*lib));
334 spin_lock(&sst_drv_ctx->list_spin_lock);
335 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
336 spin_unlock(&sst_drv_ctx->list_spin_lock);
337 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
338 pr_debug("Waiting for FW response Download complete\n");
339 sst_drv_ctx->alloc_block[i].ops_block.condition = false;
340 retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]);
341 if (retval) {
342 /* error */
343 mutex_lock(&sst_drv_ctx->sst_lock);
344 sst_drv_ctx->sst_state = SST_UN_INIT;
345 mutex_unlock(&sst_drv_ctx->sst_lock);
346 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
347 return -EIO;
348 }
349
350 pr_debug("FW success on Download complete\n");
351 sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
352 mutex_lock(&sst_drv_ctx->sst_lock);
353 sst_drv_ctx->sst_state = SST_FW_RUNNING;
354 mutex_unlock(&sst_drv_ctx->sst_lock);
355 return 0;
356
357}
358
359/* This function is called before downloading the codec/postprocessing
360library is set for download to SST DSP*/
361static int sst_validate_library(const struct firmware *fw_lib,
362 struct lib_slot_info *slot,
363 u32 *entry_point)
364{
365 struct fw_header *header;
366 struct fw_module_header *module;
367 struct dma_block_info *block;
368 unsigned int n_blk, isize = 0, dsize = 0;
369 int err = 0;
370
371 header = (struct fw_header *)fw_lib->data;
372 if (header->modules != 1) {
373 pr_err("Module no mismatch found\n");
374 err = -EINVAL;
375 goto exit;
376 }
377 module = (void *)fw_lib->data + sizeof(*header);
378 *entry_point = module->entry_point;
379 pr_debug("Module entry point 0x%x\n", *entry_point);
380 pr_debug("Module Sign %s, Size 0x%x, Blocks 0x%x Type 0x%x\n",
381 module->signature, module->mod_size,
382 module->blocks, module->type);
383
384 block = (void *)module + sizeof(*module);
385 for (n_blk = 0; n_blk < module->blocks; n_blk++) {
386 switch (block->type) {
387 case SST_IRAM:
388 isize += block->size;
389 break;
390 case SST_DRAM:
391 dsize += block->size;
392 break;
393 default:
394 pr_err("Invalid block type for 0x%x\n", n_blk);
395 err = -EINVAL;
396 goto exit;
397 }
398 block = (void *)block + sizeof(*block) + block->size;
399 }
400 if (isize > slot->iram_size || dsize > slot->dram_size) {
401 pr_err("library exceeds size allocated\n");
402 err = -EINVAL;
403 goto exit;
404 } else
405 pr_debug("Library is safe for download...\n");
406
407 pr_debug("iram 0x%x, dram 0x%x, iram 0x%x, dram 0x%x\n",
408 isize, dsize, slot->iram_size, slot->dram_size);
409exit:
410 return err;
411
412}
413
414/* This function is called when FW requests for a particular library download
415This function prepares the library to download*/
416int sst_load_library(struct snd_sst_lib_download *lib, u8 ops)
417{
418 char buf[20];
419 const char *type, *dir;
420 int len = 0, error = 0;
421 u32 entry_point;
422 const struct firmware *fw_lib;
423 struct snd_sst_lib_download_info dload_info = {{{0},},};
424
425 memset(buf, 0, sizeof(buf));
426
427 pr_debug("Lib Type 0x%x, Slot 0x%x, ops 0x%x\n",
428 lib->lib_info.lib_type, lib->slot_info.slot_num, ops);
429 pr_debug("Version 0x%x, name %s, caps 0x%x media type 0x%x\n",
430 lib->lib_info.lib_version, lib->lib_info.lib_name,
431 lib->lib_info.lib_caps, lib->lib_info.media_type);
432
433 pr_debug("IRAM Size 0x%x, offset 0x%x\n",
434 lib->slot_info.iram_size, lib->slot_info.iram_offset);
435 pr_debug("DRAM Size 0x%x, offset 0x%x\n",
436 lib->slot_info.dram_size, lib->slot_info.dram_offset);
437
438 switch (lib->lib_info.lib_type) {
439 case SST_CODEC_TYPE_MP3:
440 type = "mp3_";
441 break;
442 case SST_CODEC_TYPE_AAC:
443 type = "aac_";
444 break;
445 case SST_CODEC_TYPE_AACP:
446 type = "aac_v1_";
447 break;
448 case SST_CODEC_TYPE_eAACP:
449 type = "aac_v2_";
450 break;
451 case SST_CODEC_TYPE_WMA9:
452 type = "wma9_";
453 break;
454 default:
455 pr_err("Invalid codec type\n");
456 error = -EINVAL;
457 goto wake;
458 }
459
460 if (ops == STREAM_OPS_CAPTURE)
461 dir = "enc_";
462 else
463 dir = "dec_";
464 len = strlen(type) + strlen(dir);
465 strncpy(buf, type, sizeof(buf)-1);
466 strncpy(buf + strlen(type), dir, sizeof(buf)-strlen(type)-1);
467 len += snprintf(buf + len, sizeof(buf) - len, "%d",
468 lib->slot_info.slot_num);
469 len += snprintf(buf + len, sizeof(buf) - len, ".bin");
470
471 pr_debug("Requesting %s\n", buf);
472
473 error = request_firmware(&fw_lib, buf, &sst_drv_ctx->pci->dev);
474 if (error) {
475 pr_err("library load failed %d\n", error);
476 goto wake;
477 }
478 error = sst_validate_library(fw_lib, &lib->slot_info, &entry_point);
479 if (error)
480 goto wake_free;
481
482 lib->mod_entry_pt = entry_point;
483 memcpy(&dload_info.dload_lib, lib, sizeof(*lib));
484 error = sst_download_library(fw_lib, &dload_info);
485 if (error)
486 goto wake_free;
487
488 /* lib is downloaded and init send alloc again */
489 pr_debug("Library is downloaded now...\n");
490wake_free:
491 /* sst_wake_up_alloc_block(sst_drv_ctx, pvt_id, error, NULL); */
492 release_firmware(fw_lib);
493wake:
494 return error;
495}
496
diff --git a/drivers/staging/intel_sst/intel_sst_fw_ipc.h b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
new file mode 100644
index 00000000000..5d0cc56aaef
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
@@ -0,0 +1,416 @@
1#ifndef __INTEL_SST_FW_IPC_H__
2#define __INTEL_SST_FW_IPC_H__
3/*
4* intel_sst_fw_ipc.h - Intel SST Driver for audio engine
5*
6* Copyright (C) 2008-10 Intel Corporation
7* Author: Vinod Koul <vinod.koul@intel.com>
8* Harsha Priya <priya.harsha@intel.com>
9* Dharageswari R <dharageswari.r@intel.com>
10* KP Jeeja <jeeja.kp@intel.com>
11* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12*
13* This program is free software; you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by
15* the Free Software Foundation; version 2 of the License.
16*
17* This program is distributed in the hope that it will be useful, but
18* WITHOUT ANY WARRANTY; without even the implied warranty of
19* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20* General Public License for more details.
21*
22* You should have received a copy of the GNU General Public License along
23* with this program; if not, write to the Free Software Foundation, Inc.,
24* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25*
26* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27*
28* This driver exposes the audio engine functionalities to the ALSA
29* and middleware.
30* This file has definitions shared between the firmware and driver
31*/
32
33#define MAX_NUM_STREAMS_MRST 3
34#define MAX_NUM_STREAMS_MFLD 6
35#define MAX_NUM_STREAMS 6
36#define MAX_DBG_RW_BYTES 80
37#define MAX_NUM_SCATTER_BUFFERS 8
38#define MAX_LOOP_BACK_DWORDS 8
39/* IPC base address and mailbox, timestamp offsets */
40#define SST_MAILBOX_SIZE 0x0400
41#define SST_MAILBOX_SEND 0x0000
42#define SST_MAILBOX_RCV 0x0804
43#define SST_TIME_STAMP 0x1800
44#define SST_RESERVED_OFFSET 0x1A00
45#define SST_CHEKPOINT_OFFSET 0x1C00
46#define REPLY_MSG 0x80
47
48/* Message ID's for IPC messages */
49/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
50
51/* I2L Firmware/Codec Download msgs */
52#define IPC_IA_PREP_LIB_DNLD 0x01
53#define IPC_IA_LIB_DNLD_CMPLT 0x02
54
55#define IPC_IA_SET_PMIC_TYPE 0x03
56#define IPC_IA_GET_FW_VERSION 0x04
57#define IPC_IA_GET_FW_BUILD_INF 0x05
58#define IPC_IA_GET_FW_INFO 0x06
59#define IPC_IA_GET_FW_CTXT 0x07
60#define IPC_IA_SET_FW_CTXT 0x08
61
62/* I2L Codec Config/control msgs */
63#define IPC_IA_SET_CODEC_PARAMS 0x10
64#define IPC_IA_GET_CODEC_PARAMS 0x11
65#define IPC_IA_SET_PPP_PARAMS 0x12
66#define IPC_IA_GET_PPP_PARAMS 0x13
67#define IPC_IA_PLAY_FRAMES 0x14
68#define IPC_IA_CAPT_FRAMES 0x15
69#define IPC_IA_PLAY_VOICE 0x16
70#define IPC_IA_CAPT_VOICE 0x17
71#define IPC_IA_DECODE_FRAMES 0x18
72
73#define IPC_IA_ALG_PARAMS 0x1A
74#define IPC_IA_TUNING_PARAMS 0x1B
75
76/* I2L Stream config/control msgs */
77#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
78#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
79#define IPC_IA_SET_STREAM_PARAMS 0x22
80#define IPC_IA_GET_STREAM_PARAMS 0x23
81#define IPC_IA_PAUSE_STREAM 0x24
82#define IPC_IA_RESUME_STREAM 0x25
83#define IPC_IA_DROP_STREAM 0x26
84#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
85#define IPC_IA_TARGET_DEV_SELECT 0x28
86#define IPC_IA_CONTROL_ROUTING 0x29
87
88#define IPC_IA_SET_STREAM_VOL 0x2A /*Vol for stream, pre mixer */
89#define IPC_IA_GET_STREAM_VOL 0x2B
90#define IPC_IA_SET_STREAM_MUTE 0x2C
91#define IPC_IA_GET_STREAM_MUTE 0x2D
92#define IPC_IA_ENABLE_RX_TIME_SLOT 0x2E /* Enable Rx time slot 0 or 1 */
93
94#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
95
96/* Debug msgs */
97#define IPC_IA_DBG_MEM_READ 0x40
98#define IPC_IA_DBG_MEM_WRITE 0x41
99#define IPC_IA_DBG_LOOP_BACK 0x42
100
101/* L2I Firmware/Codec Download msgs */
102#define IPC_IA_FW_INIT_CMPLT 0x81
103#define IPC_IA_LPE_GETTING_STALLED 0x82
104#define IPC_IA_LPE_UNSTALLED 0x83
105
106/* L2I Codec Config/control msgs */
107#define IPC_SST_GET_PLAY_FRAMES 0x90 /* Request IA more data */
108#define IPC_SST_GET_CAPT_FRAMES 0x91 /* Request IA more data */
109#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
110#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
111#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
112#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
113#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
114#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
115#define IPC_IA_TARGET_DEV_CHNGD 0x98 /* error in processing a stream */
116
117#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
118/* L2S messages */
119#define IPC_SC_DDR_LINK_UP 0xC0
120#define IPC_SC_DDR_LINK_DOWN 0xC1
121#define IPC_SC_SET_LPECLK_REQ 0xC2
122#define IPC_SC_SSP_BIT_BANG 0xC3
123
124/* L2I Error reporting msgs */
125#define IPC_IA_MEM_ALLOC_FAIL 0xE0
126#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
127 stream can be used by playback and
128 capture modules */
129
130/* L2I Debug msgs */
131#define IPC_IA_PRINT_STRING 0xF0
132
133
134
135/* Command Response or Acknowledge message to any IPC message will have
136 * same message ID and stream ID information which is sent.
137 * There is no specific Ack message ID. The data field is used as response
138 * meaning.
139 */
140enum ackData {
141 IPC_ACK_SUCCESS = 0,
142 IPC_ACK_FAILURE
143};
144
145
146enum sst_error_codes {
147 /* Error code,response to msgId: Description */
148 /* Common error codes */
149 SST_SUCCESS = 0, /* Success */
150 SST_ERR_INVALID_STREAM_ID = 1,
151 SST_ERR_INVALID_MSG_ID = 2,
152 SST_ERR_INVALID_STREAM_OP = 3,
153 SST_ERR_INVALID_PARAMS = 4,
154 SST_ERR_INVALID_CODEC = 5,
155 SST_ERR_INVALID_MEDIA_TYPE = 6,
156 SST_ERR_STREAM_ERR = 7,
157
158 /* IPC specific error codes */
159 SST_IPC_ERR_CALL_BACK_NOT_REGD = 8,
160 SST_IPC_ERR_STREAM_NOT_ALLOCATED = 9,
161 SST_IPC_ERR_STREAM_ALLOC_FAILED = 10,
162 SST_IPC_ERR_GET_STREAM_FAILED = 11,
163 SST_ERR_MOD_NOT_AVAIL = 12,
164 SST_ERR_MOD_DNLD_RQD = 13,
165 SST_ERR_STREAM_STOPPED = 14,
166 SST_ERR_STREAM_IN_USE = 15,
167
168 /* Capture specific error codes */
169 SST_CAP_ERR_INCMPLTE_CAPTURE_MSG = 16,
170 SST_CAP_ERR_CAPTURE_FAIL = 17,
171 SST_CAP_ERR_GET_DDR_NEW_SGLIST = 18,
172 SST_CAP_ERR_UNDER_RUN = 19,
173 SST_CAP_ERR_OVERFLOW = 20,
174
175 /* Playback specific error codes*/
176 SST_PB_ERR_INCMPLTE_PLAY_MSG = 21,
177 SST_PB_ERR_PLAY_FAIL = 22,
178 SST_PB_ERR_GET_DDR_NEW_SGLIST = 23,
179
180 /* Codec manager specific error codes */
181 SST_LIB_ERR_LIB_DNLD_REQUIRED = 24,
182 SST_LIB_ERR_LIB_NOT_SUPPORTED = 25,
183
184 /* Library manager specific error codes */
185 SST_SCC_ERR_PREP_DNLD_FAILED = 26,
186 SST_SCC_ERR_LIB_DNLD_RES_FAILED = 27,
187 /* Scheduler specific error codes */
188 SST_SCH_ERR_FAIL = 28,
189
190 /* DMA specific error codes */
191 SST_DMA_ERR_NO_CHNL_AVAILABLE = 29,
192 SST_DMA_ERR_INVALID_INPUT_PARAMS = 30,
193 SST_DMA_ERR_CHNL_ALREADY_SUSPENDED = 31,
194 SST_DMA_ERR_CHNL_ALREADY_STARTED = 32,
195 SST_DMA_ERR_CHNL_NOT_ENABLED = 33,
196 SST_DMA_ERR_TRANSFER_FAILED = 34,
197
198 SST_SSP_ERR_ALREADY_ENABLED = 35,
199 SST_SSP_ERR_ALREADY_DISABLED = 36,
200 SST_SSP_ERR_NOT_INITIALIZED = 37,
201 SST_SSP_ERR_SRAM_NO_DMA_DATA = 38,
202
203 /* Other error codes */
204 SST_ERR_MOD_INIT_FAIL = 39,
205
206 /* FW init error codes */
207 SST_RDR_ERR_IO_DEV_SEL_NOT_ALLOWED = 40,
208 SST_RDR_ERR_ROUTE_ALREADY_STARTED = 41,
209 SST_RDR_ERR_IO_DEV_SEL_FAILED = 42,
210 SST_RDR_PREP_CODEC_DNLD_FAILED = 43,
211
212 /* Memory debug error codes */
213 SST_ERR_DBG_MEM_READ_FAIL = 44,
214 SST_ERR_DBG_MEM_WRITE_FAIL = 45,
215 SST_ERR_INSUFFICIENT_INPUT_SG_LIST = 46,
216 SST_ERR_INSUFFICIENT_OUTPUT_SG_LIST = 47,
217
218 SST_ERR_BUFFER_NOT_AVAILABLE = 48,
219 SST_ERR_BUFFER_NOT_ALLOCATED = 49,
220 SST_ERR_INVALID_REGION_TYPE = 50,
221 SST_ERR_NULL_PTR = 51,
222 SST_ERR_INVALID_BUFFER_SIZE = 52,
223 SST_ERR_INVALID_BUFFER_INDEX = 53,
224
225 /*IIPC specific error codes */
226 SST_IIPC_QUEUE_FULL = 54,
227 SST_IIPC_ERR_MSG_SND_FAILED = 55,
228 SST_PB_ERR_UNDERRUN_OCCURED = 56,
229 SST_RDR_INSUFFICIENT_MIXER_BUFFER = 57,
230 SST_INVALID_TIME_SLOTS = 58,
231};
232
233enum dbg_mem_data_type {
234 /* Data type of debug read/write */
235 DATA_TYPE_U32,
236 DATA_TYPE_U16,
237 DATA_TYPE_U8,
238};
239
240/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
241
242/* IPC Header */
243union ipc_header {
244 struct {
245 u32 msg_id:8; /* Message ID - Max 256 Message Types */
246 u32 str_id:5;
247 u32 large:1; /* Large Message if large = 1 */
248 u32 reserved:2; /* Reserved for future use */
249 u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */
250 u32 done:1; /* bit 30 */
251 u32 busy:1; /* bit 31 */
252 } part;
253 u32 full;
254} __attribute__ ((packed));
255
256/* Firmware build info */
257struct sst_fw_build_info {
258 unsigned char date[16]; /* Firmware build date */
259 unsigned char time[16]; /* Firmware build time */
260} __attribute__ ((packed));
261
262struct ipc_header_fw_init {
263 struct snd_sst_fw_version fw_version;/* Firmware version details */
264 struct sst_fw_build_info build_info;
265 u16 result; /* Fw init result */
266 u8 module_id; /* Module ID in case of error */
267 u8 debug_info; /* Debug info from Module ID in case of fail */
268} __attribute__ ((packed));
269
270/* Address and size info of a frame buffer in DDR */
271struct sst_address_info {
272 u32 addr; /* Address at IA */
273 u32 size; /* Size of the buffer */
274} __attribute__ ((packed));
275
276/* Time stamp */
277struct snd_sst_tstamp {
278 u64 samples_processed;/* capture - data in DDR */
279 u64 samples_rendered;/* playback - data rendered */
280 u64 bytes_processed;/* bytes decoded or encoded */
281 u32 sampling_frequency;/* eg: 48000, 44100 */
282 u32 dma_base_address;/* DMA base address */
283 u16 dma_channel_no;/* DMA Channel used for the data transfer*/
284 u16 reserved;/* 32 bit alignment */
285};
286
287/* Frame info to play or capture */
288struct sst_frame_info {
289 u16 num_entries; /* number of entries to follow */
290 u16 rsrvd;
291 struct sst_address_info addr[MAX_NUM_SCATTER_BUFFERS];
292} __attribute__ ((packed));
293
294/* Frames info for decode */
295struct snd_sst_decode_info {
296 unsigned long long input_bytes_consumed;
297 unsigned long long output_bytes_produced;
298 struct sst_frame_info frames_in;
299 struct sst_frame_info frames_out;
300} __attribute__ ((packed));
301
302/* SST to IA print debug message*/
303struct ipc_sst_ia_print_params {
304 u32 string_size;/* Max value is 160 */
305 u8 prt_string[160];/* Null terminated Char string */
306} __attribute__ ((packed));
307
308/* Voice data message */
309struct snd_sst_voice_data {
310 u16 num_bytes;/* Number of valid voice data bytes */
311 u8 pcm_wd_size;/* 0=8 bit, 1=16 bit 2=32 bit */
312 u8 reserved;/* Reserved */
313 u8 voice_data_buf[0];/* Voice data buffer in bytes, little endian */
314} __attribute__ ((packed));
315
316/* SST to IA memory read debug message */
317struct ipc_sst_ia_dbg_mem_rw {
318 u16 num_bytes;/* Maximum of MAX_DBG_RW_BYTES */
319 u16 data_type;/* enum: dbg_mem_data_type */
320 u32 address; /* Memory address of data memory of data_type */
321 u8 rw_bytes[MAX_DBG_RW_BYTES];/* Maximum of 64 bytes can be RW */
322} __attribute__ ((packed));
323
324struct ipc_sst_ia_dbg_loop_back {
325 u16 num_dwords; /* Maximum of MAX_DBG_RW_BYTES */
326 u16 increment_val;/* Increments dwords by this value, 0- no increment */
327 u32 lpbk_dwords[MAX_LOOP_BACK_DWORDS];/* Maximum of 8 dwords loopback */
328} __attribute__ ((packed));
329
330/* Stream type params struture for Alloc stream */
331struct snd_sst_str_type {
332 u8 codec_type; /* Codec type */
333 u8 str_type; /* 1 = voice 2 = music */
334 u8 operation; /* Playback or Capture */
335 u8 protected_str; /* 0=Non DRM, 1=DRM */
336 u8 time_slots;
337 u8 reserved; /* Reserved */
338 u16 result; /* Result used for acknowledgment */
339} __attribute__ ((packed));
340
341/* Library info structure */
342struct module_info {
343 u32 lib_version;
344 u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
345 u32 media_type;
346 u8 lib_name[12];
347 u32 lib_caps;
348 unsigned char b_date[16]; /* Lib build date */
349 unsigned char b_time[16]; /* Lib build time */
350} __attribute__ ((packed));
351
352/* Library slot info */
353struct lib_slot_info {
354 u8 slot_num; /* 1 or 2 */
355 u8 reserved1;
356 u16 reserved2;
357 u32 iram_size; /* slot size in IRAM */
358 u32 dram_size; /* slot size in DRAM */
359 u32 iram_offset; /* starting offset of slot in IRAM */
360 u32 dram_offset; /* starting offset of slot in DRAM */
361} __attribute__ ((packed));
362
363struct snd_sst_lib_download {
364 struct module_info lib_info; /* library info type, capabilities etc */
365 struct lib_slot_info slot_info; /* slot info to be downloaded */
366 u32 mod_entry_pt;
367};
368
369struct snd_sst_lib_download_info {
370 struct snd_sst_lib_download dload_lib;
371 u16 result; /* Result used for acknowledgment */
372 u8 pvt_id; /* Private ID */
373 u8 reserved; /* for alignment */
374};
375
376/* Alloc stream params structure */
377struct snd_sst_alloc_params {
378 struct snd_sst_str_type str_type;
379 struct snd_sst_stream_params stream_params;
380};
381
382struct snd_sst_fw_get_stream_params {
383 struct snd_sst_stream_params codec_params;
384 struct snd_sst_pmic_config pcm_params;
385};
386
387/* Alloc stream response message */
388struct snd_sst_alloc_response {
389 struct snd_sst_str_type str_type; /* Stream type for allocation */
390 struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
391};
392
393/* Drop response */
394struct snd_sst_drop_response {
395 u32 result;
396 u32 bytes;
397};
398
399/* CSV Voice call routing structure */
400struct snd_sst_control_routing {
401 u8 control; /* 0=start, 1=Stop */
402 u8 reserved[3]; /* Reserved- for 32 bit alignment */
403};
404
405
406struct ipc_post {
407 struct list_head node;
408 union ipc_header header; /* driver specific */
409 char *mailbox_data;
410};
411
412struct snd_sst_ctxt_params {
413 u32 address; /* Physical Address in DDR where the context is stored */
414 u32 size; /* size of the context */
415};
416#endif /* __INTEL_SST_FW_IPC_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_ioctl.h b/drivers/staging/intel_sst/intel_sst_ioctl.h
new file mode 100644
index 00000000000..5da5ee092c6
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_ioctl.h
@@ -0,0 +1,440 @@
1#ifndef __INTEL_SST_IOCTL_H__
2#define __INTEL_SST_IOCTL_H__
3/*
4 * intel_sst_ioctl.h - Intel SST Driver for audio engine
5 *
6 * Copyright (C) 2008-10 Intel Corporation
7 * Authors: Vinod Koul <vinod.koul@intel.com>
8 * Harsha Priya <priya.harsha@intel.com>
9 * Dharageswari R <dharageswari.r@intel.com>
10 * KP Jeeja <jeeja.kp@intel.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 *
28 * This file defines all sst ioctls
29 */
30
31/* codec and post/pre processing related info */
32
33#include <linux/types.h>
34
35enum sst_codec_types {
36/* AUDIO/MUSIC CODEC Type Definitions */
37 SST_CODEC_TYPE_UNKNOWN = 0,
38 SST_CODEC_TYPE_PCM, /* Pass through Audio codec */
39 SST_CODEC_TYPE_MP3,
40 SST_CODEC_TYPE_MP24,
41 SST_CODEC_TYPE_AAC,
42 SST_CODEC_TYPE_AACP,
43 SST_CODEC_TYPE_eAACP,
44 SST_CODEC_TYPE_WMA9,
45 SST_CODEC_TYPE_WMA10,
46 SST_CODEC_TYPE_WMA10P,
47 SST_CODEC_TYPE_RA,
48 SST_CODEC_TYPE_DDAC3,
49 SST_CODEC_TYPE_STEREO_TRUE_HD,
50 SST_CODEC_TYPE_STEREO_HD_PLUS,
51
52 /* VOICE CODEC Type Definitions */
53 SST_CODEC_TYPE_VOICE_PCM = 0x21, /* Pass through voice codec */
54};
55
56enum sst_algo_types {
57 SST_CODEC_SRC = 0x64,
58 SST_CODEC_MIXER = 0x65,
59 SST_CODEC_DOWN_MIXER = 0x66,
60 SST_CODEC_VOLUME_CONTROL = 0x67,
61 SST_CODEC_OEM1 = 0xC8,
62 SST_CODEC_OEM2 = 0xC9,
63};
64
65enum snd_sst_stream_ops {
66 STREAM_OPS_PLAYBACK = 0, /* Decode */
67 STREAM_OPS_CAPTURE, /* Encode */
68 STREAM_OPS_PLAYBACK_DRM, /* Play Audio/Voice */
69 STREAM_OPS_PLAYBACK_ALERT, /* Play Audio/Voice */
70 STREAM_OPS_CAPTURE_VOICE_CALL, /* CSV Voice recording */
71};
72
73enum stream_mode {
74 SST_STREAM_MODE_NONE = 0,
75 SST_STREAM_MODE_DNR = 1,
76 SST_STREAM_MODE_FNF = 2,
77 SST_STREAM_MODE_CAPTURE = 3
78};
79
80enum stream_type {
81 SST_STREAM_TYPE_NONE = 0,
82 SST_STREAM_TYPE_MUSIC = 1,
83 SST_STREAM_TYPE_NORMAL = 2,
84 SST_STREAM_TYPE_LONG_PB = 3,
85 SST_STREAM_TYPE_LOW_LATENCY = 4,
86};
87
88enum snd_sst_audio_device_type {
89 SND_SST_DEVICE_HEADSET = 1,
90 SND_SST_DEVICE_IHF,
91 SND_SST_DEVICE_VIBRA,
92 SND_SST_DEVICE_HAPTIC,
93 SND_SST_DEVICE_CAPTURE,
94};
95
96/* Firmware Version info */
97struct snd_sst_fw_version {
98 __u8 build; /* build number*/
99 __u8 minor; /* minor number*/
100 __u8 major; /* major number*/
101 __u8 type; /* build type */
102};
103
104/* Port info structure */
105struct snd_sst_port_info {
106 __u16 port_type;
107 __u16 reserved;
108};
109
110/* Mixer info structure */
111struct snd_sst_mix_info {
112 __u16 max_streams;
113 __u16 reserved;
114};
115
116/* PCM Parameters */
117struct snd_pcm_params {
118 __u16 codec; /* codec type */
119 __u8 num_chan; /* 1=Mono, 2=Stereo */
120 __u8 pcm_wd_sz; /* 16/24 - bit*/
121 __u32 reserved; /* Bitrate in bits per second */
122 __u32 sfreq; /* Sampling rate in Hz */
123 __u32 ring_buffer_size;
124 __u32 period_count; /* period elapsed in samples*/
125 __u32 ring_buffer_addr;
126};
127
128/* MP3 Music Parameters Message */
129struct snd_mp3_params {
130 __u16 codec;
131 __u8 num_chan; /* 1=Mono, 2=Stereo */
132 __u8 pcm_wd_sz; /* 16/24 - bit*/
133 __u32 brate; /* Use the hard coded value. */
134 __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
135 __u8 crc_check; /* crc_check - disable (0) or enable (1) */
136 __u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB*/
137 __u16 reserved; /* Unused */
138};
139
140#define AAC_BIT_STREAM_ADTS 0
141#define AAC_BIT_STREAM_ADIF 1
142#define AAC_BIT_STREAM_RAW 2
143
144/* AAC Music Parameters Message */
145struct snd_aac_params {
146 __u16 codec;
147 __u8 num_chan; /* 1=Mono, 2=Stereo*/
148 __u8 pcm_wd_sz; /* 16/24 - bit*/
149 __u32 brate;
150 __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
151 __u32 aac_srate; /* Plain AAC decoder operating sample rate */
152 __u8 mpg_id; /* 0=MPEG-2, 1=MPEG-4 */
153 __u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */
154 __u8 aac_profile; /* 0=Main Profile, 1=LC profile, 3=SSR profile */
155 __u8 ext_chl; /* No.of external channels */
156 __u8 aot; /* Audio object type. 1=Main , 2=LC , 3=SSR, 4=SBR*/
157 __u8 op_align; /* output alignment 0=16 bit , 1=MSB, 2= LSB align */
158 __u8 brate_type; /* 0=CBR, 1=VBR */
159 __u8 crc_check; /* crc check 0= disable, 1=enable */
160 __s8 bit_stream_format[8]; /* input bit stream format adts/adif/raw */
161 __u8 jstereo; /* Joint stereo Flag */
162 __u8 sbr_present; /* 1 = SBR Present, 0 = SBR absent, for RAW */
163 __u8 downsample; /* 1 = Downsampling ON, 0 = Downsampling OFF */
164 __u8 num_syntc_elems; /* 1- Mono/stereo, 0 - Dual Mono, 0 - for raw */
165 __s8 syntc_id[2]; /* 0 for ID_SCE(Dula Mono), -1 for raw */
166 __s8 syntc_tag[2]; /* raw - -1 and 0 -16 for rest of the streams */
167 __u8 pce_present; /* Flag. 1- present 0 - not present, for RAW */
168 __u8 sbr_type; /* sbr_type: 0-plain aac, 1-aac-v1, 2-aac-v2 */
169 __u8 outchmode; /*0- mono, 1-stereo, 2-dual mono 3-Parametric stereo */
170 __u8 ps_present;
171};
172
173/* WMA Music Parameters Message */
174struct snd_wma_params {
175 __u16 codec;
176 __u8 num_chan; /* 1=Mono, 2=Stereo */
177 __u8 pcm_wd_sz; /* 16/24 - bit*/
178 __u32 brate; /* Use the hard coded value. */
179 __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
180 __u32 channel_mask; /* Channel Mask */
181 __u16 format_tag; /* Format Tag */
182 __u16 block_align; /* packet size */
183 __u16 wma_encode_opt;/* Encoder option */
184 __u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */
185 __u8 pcm_src; /* input pcm bit width */
186};
187
188/* Pre processing param structure */
189struct snd_prp_params {
190 __u32 reserved; /* No pre-processing defined yet */
191};
192
193/* Pre and post processing params structure */
194struct snd_ppp_params {
195 __u8 algo_id;/* Post/Pre processing algorithm ID */
196 __u8 str_id; /*Only 5 bits used 0 - 31 are valid*/
197 __u8 enable; /* 0= disable, 1= enable*/
198 __u8 reserved;
199 __u32 size; /*Size of parameters for all blocks*/
200 void *params;
201} __attribute__ ((packed));
202
203struct snd_sst_postproc_info {
204 __u32 src_min; /* Supported SRC Min sampling freq */
205 __u32 src_max; /* Supported SRC Max sampling freq */
206 __u8 src; /* 0=Not supported, 1=Supported */
207 __u8 bass_boost; /* 0=Not Supported, 1=Supported */
208 __u8 stereo_widening; /* 0=Not Supported, 1=Supported */
209 __u8 volume_control; /* 0=Not Supported, 1=Supported */
210 __s16 min_vol; /* Minimum value of Volume in dB */
211 __s16 max_vol; /* Maximum value of Volume in dB */
212 __u8 mute_control; /* 0=No Mute, 1=Mute */
213 __u8 reserved1;
214 __u16 reserved2;
215};
216
217/* pre processing Capability info structure */
218struct snd_sst_prp_info {
219 __s16 min_vol; /* Minimum value of Volume in dB */
220 __s16 max_vol; /* Maximum value of Volume in dB */
221 __u8 volume_control; /* 0=Not Supported, 1=Supported */
222 __u8 reserved1; /* for 32 bit alignment */
223 __u16 reserved2; /* for 32 bit alignment */
224} __attribute__ ((packed));
225
226/*Pre / Post processing algorithms support*/
227struct snd_sst_ppp_info {
228 __u32 src:1; /* 0=Not supported, 1=Supported */
229 __u32 mixer:1; /* 0=Not supported, 1=Supported */
230 __u32 volume_control:1; /* 0=Not Supported, 1=Supported */
231 __u32 mute_control:1; /* 0=Not Supported, 1=Supported */
232 __u32 anc:1; /* 0=Not Supported, 1=Supported */
233 __u32 side_tone:1; /* 0=Not Supported, 1=Supported */
234 __u32 dc_removal:1; /* 0=Not Supported, 1=Supported */
235 __u32 equalizer:1; /* 0=Not Supported, 1=Supported */
236 __u32 spkr_prot:1; /* 0=Not Supported, 1=Supported */
237 __u32 bass_boost:1; /* 0=Not Supported, 1=Supported */
238 __u32 stereo_widening:1;/* 0=Not Supported, 1=Supported */
239 __u32 rsvd1:21;
240 __u32 rsvd2;
241};
242
243/* Firmware capabilities info */
244struct snd_sst_fw_info {
245 struct snd_sst_fw_version fw_version; /* Firmware version */
246 __u8 audio_codecs_supported[8]; /* Codecs supported by FW */
247 __u32 recommend_min_duration; /* Min duration for Lowpower Playback */
248 __u8 max_pcm_streams_supported; /* Max num of PCM streams supported */
249 __u8 max_enc_streams_supported; /* Max number of Encoded streams */
250 __u16 reserved; /* 32 bit alignment*/
251 struct snd_sst_ppp_info ppp_info; /* pre_processing mod cap info */
252 struct snd_sst_postproc_info pop_info; /* Post processing cap info*/
253 struct snd_sst_port_info port_info[3]; /* Port info */
254 struct snd_sst_mix_info mix_info;/* Mixer info */
255 __u32 min_input_buf; /* minmum i/p buffer for decode */
256};
257
258/* Codec params struture */
259union snd_sst_codec_params {
260 struct snd_pcm_params pcm_params;
261 struct snd_mp3_params mp3_params;
262 struct snd_aac_params aac_params;
263 struct snd_wma_params wma_params;
264};
265
266
267struct snd_sst_stream_params {
268 union snd_sst_codec_params uc;
269} __attribute__ ((packed));
270
271struct snd_sst_params {
272 __u32 result;
273 __u32 stream_id;
274 __u8 codec;
275 __u8 ops;
276 __u8 stream_type;
277 __u8 device_type;
278 struct snd_sst_stream_params sparams;
279};
280
281struct snd_sst_vol {
282 __u32 stream_id;
283 __s32 volume;
284 __u32 ramp_duration;
285 __u32 ramp_type; /* Ramp type, default=0 */
286};
287
288struct snd_sst_mute {
289 __u32 stream_id;
290 __u32 mute;
291};
292
293/* ioctl related stuff here */
294struct snd_sst_pmic_config {
295 __u32 sfreq; /* Sampling rate in Hz */
296 __u16 num_chan; /* Mono =1 or Stereo =2 */
297 __u16 pcm_wd_sz; /* Number of bits per sample */
298} __attribute__ ((packed));
299
300struct snd_sst_get_stream_params {
301 struct snd_sst_params codec_params;
302 struct snd_sst_pmic_config pcm_params;
303};
304
305enum snd_sst_target_type {
306 SND_SST_TARGET_PMIC = 1,
307 SND_SST_TARGET_LPE,
308 SND_SST_TARGET_MODEM,
309 SND_SST_TARGET_BT,
310 SND_SST_TARGET_FM,
311 SND_SST_TARGET_NONE,
312};
313
314enum snd_sst_device_type {
315 SND_SST_DEVICE_SSP = 1,
316 SND_SST_DEVICE_PCM,
317 SND_SST_DEVICE_OTHER,
318};
319
320enum snd_sst_device_mode {
321
322 SND_SST_DEV_MODE_PCM_MODE1 = 1, /*(16-bit word, bit-length frame sync)*/
323 SND_SST_DEV_MODE_PCM_MODE2,
324 SND_SST_DEV_MODE_PCM_MODE3,
325 SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED,
326 SND_SST_DEV_MODE_PCM_MODE4_LEFT_JUSTIFIED,
327 SND_SST_DEV_MODE_PCM_MODE4_I2S, /*(I2S mode, 16-bit words)*/
328 SND_SST_DEV_MODE_PCM_MODE5,
329 SND_SST_DEV_MODE_PCM_MODE6,
330};
331
332enum snd_sst_port_action {
333 SND_SST_PORT_PREPARE = 1,
334 SND_SST_PORT_ACTIVATE,
335};
336
337/* Target selection per device structure */
338struct snd_sst_slot_info {
339 __u8 mix_enable; /* Mixer enable or disable */
340 __u8 device_type;
341 __u8 device_instance; /* 0, 1, 2 */
342 __u8 target_device;
343 __u16 target_sink;
344 __u8 slot[2];
345 __u8 master;
346 __u8 action;
347 __u8 device_mode;
348 __u8 reserved;
349 struct snd_sst_pmic_config pcm_params;
350} __attribute__ ((packed));
351
352#define SST_MAX_TARGET_DEVICES 3
353/* Target device list structure */
354struct snd_sst_target_device {
355 __u32 device_route;
356 struct snd_sst_slot_info devices[SST_MAX_TARGET_DEVICES];
357} __attribute__ ((packed));
358
359struct snd_sst_driver_info {
360 __u32 version; /* Version of the driver */
361 __u32 active_pcm_streams;
362 __u32 active_enc_streams;
363 __u32 max_pcm_streams;
364 __u32 max_enc_streams;
365 __u32 buf_per_stream;
366};
367
368enum snd_sst_buff_type {
369 SST_BUF_USER = 1,
370 SST_BUF_MMAP,
371 SST_BUF_RAR,
372};
373
374struct snd_sst_mmap_buff_entry {
375 unsigned int offset;
376 unsigned int size;
377};
378
379struct snd_sst_mmap_buffs {
380 unsigned int entries;
381 enum snd_sst_buff_type type;
382 struct snd_sst_mmap_buff_entry *buff;
383};
384
385struct snd_sst_buff_entry {
386 void *buffer;
387 unsigned int size;
388};
389
390struct snd_sst_buffs {
391 unsigned int entries;
392 __u8 type;
393 struct snd_sst_buff_entry *buff_entry;
394};
395
396struct snd_sst_dbufs {
397 unsigned long long input_bytes_consumed;
398 unsigned long long output_bytes_produced;
399 struct snd_sst_buffs *ibufs;
400 struct snd_sst_buffs *obufs;
401};
402
403struct snd_sst_tuning_params {
404 __u8 type;
405 __u8 str_id;
406 __u8 size;
407 __u8 rsvd;
408 __aligned_u64 addr;
409} __attribute__ ((packed));
410/*IOCTL defined here */
411/*SST MMF IOCTLS only */
412#define SNDRV_SST_STREAM_SET_PARAMS _IOR('L', 0x00, \
413 struct snd_sst_stream_params *)
414#define SNDRV_SST_STREAM_GET_PARAMS _IOWR('L', 0x01, \
415 struct snd_sst_get_stream_params *)
416#define SNDRV_SST_STREAM_GET_TSTAMP _IOWR('L', 0x02, __u64 *)
417#define SNDRV_SST_STREAM_DECODE _IOWR('L', 0x03, struct snd_sst_dbufs *)
418#define SNDRV_SST_STREAM_BYTES_DECODED _IOWR('L', 0x04, __u64 *)
419#define SNDRV_SST_STREAM_START _IO('A', 0x42)
420#define SNDRV_SST_STREAM_DROP _IO('A', 0x43)
421#define SNDRV_SST_STREAM_DRAIN _IO('A', 0x44)
422#define SNDRV_SST_STREAM_PAUSE _IOW('A', 0x45, int)
423#define SNDRV_SST_STREAM_RESUME _IO('A', 0x47)
424#define SNDRV_SST_MMAP_PLAY _IOW('L', 0x05, struct snd_sst_mmap_buffs *)
425#define SNDRV_SST_MMAP_CAPTURE _IOW('L', 0x06, struct snd_sst_mmap_buffs *)
426/*SST common ioctls */
427#define SNDRV_SST_DRIVER_INFO _IOR('L', 0x10, struct snd_sst_driver_info *)
428#define SNDRV_SST_SET_VOL _IOW('L', 0x11, struct snd_sst_vol *)
429#define SNDRV_SST_GET_VOL _IOW('L', 0x12, struct snd_sst_vol *)
430#define SNDRV_SST_MUTE _IOW('L', 0x13, struct snd_sst_mute *)
431/*AM Ioctly only */
432#define SNDRV_SST_FW_INFO _IOR('L', 0x20, struct snd_sst_fw_info *)
433#define SNDRV_SST_SET_TARGET_DEVICE _IOW('L', 0x21, \
434 struct snd_sst_target_device *)
435/*DSP Ioctls on /dev/intel_sst_ctrl only*/
436#define SNDRV_SST_SET_ALGO _IOW('L', 0x30, struct snd_ppp_params *)
437#define SNDRV_SST_GET_ALGO _IOWR('L', 0x31, struct snd_ppp_params *)
438#define SNDRV_SST_TUNING_PARAMS _IOW('L', 0x32, struct snd_sst_tuning_params *)
439
440#endif /* __INTEL_SST_IOCTL_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_ipc.c b/drivers/staging/intel_sst/intel_sst_ipc.c
new file mode 100644
index 00000000000..5c3444f6ab4
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_ipc.c
@@ -0,0 +1,774 @@
1/*
2 * intel_sst_ipc.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corporation
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This file defines all ipc functions
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/pci.h>
32#include <linux/firmware.h>
33#include <linux/sched.h>
34#include "intel_sst.h"
35#include "intel_sst_ioctl.h"
36#include "intel_sst_fw_ipc.h"
37#include "intel_sst_common.h"
38
39/*
40 * sst_send_sound_card_type - send sound card type
41 *
42 * this function sends the sound card type to sst dsp engine
43 */
44static void sst_send_sound_card_type(void)
45{
46 struct ipc_post *msg = NULL;
47
48 if (sst_create_short_msg(&msg))
49 return;
50
51 sst_fill_header(&msg->header, IPC_IA_SET_PMIC_TYPE, 0, 0);
52 msg->header.part.data = sst_drv_ctx->pmic_vendor;
53 spin_lock(&sst_drv_ctx->list_spin_lock);
54 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
55 spin_unlock(&sst_drv_ctx->list_spin_lock);
56 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
57 return;
58}
59
60/**
61* sst_post_message - Posts message to SST
62*
63* @work: Pointer to work structure
64*
65* This function is called by any component in driver which
66* wants to send an IPC message. This will post message only if
67* busy bit is free
68*/
69void sst_post_message(struct work_struct *work)
70{
71 struct ipc_post *msg;
72 union ipc_header header;
73 union interrupt_reg imr;
74 int retval = 0;
75 imr.full = 0;
76
77 /*To check if LPE is in stalled state.*/
78 retval = sst_stalled();
79 if (retval < 0) {
80 pr_err("in stalled state\n");
81 return;
82 }
83 pr_debug("post message called\n");
84 spin_lock(&sst_drv_ctx->list_spin_lock);
85
86 /* check list */
87 if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) {
88 /* list is empty, mask imr */
89 pr_debug("Empty msg queue... masking\n");
90 imr.full = readl(sst_drv_ctx->shim + SST_IMRX);
91 imr.part.done_interrupt = 1;
92 /* dummy register for shim workaround */
93 sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
94 spin_unlock(&sst_drv_ctx->list_spin_lock);
95 return;
96 }
97
98 /* check busy bit */
99 header.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCX);
100 if (header.part.busy) {
101 /* busy, unmask */
102 pr_debug("Busy not free... unmasking\n");
103 imr.full = readl(sst_drv_ctx->shim + SST_IMRX);
104 imr.part.done_interrupt = 0;
105 /* dummy register for shim workaround */
106 sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
107 spin_unlock(&sst_drv_ctx->list_spin_lock);
108 return;
109 }
110 /* copy msg from list */
111 msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next,
112 struct ipc_post, node);
113 list_del(&msg->node);
114 pr_debug("Post message: header = %x\n", msg->header.full);
115 pr_debug("size: = %x\n", msg->header.part.data);
116 if (msg->header.part.large)
117 memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND,
118 msg->mailbox_data, msg->header.part.data);
119 /* dummy register for shim workaround */
120
121 sst_shim_write(sst_drv_ctx->shim, SST_IPCX, msg->header.full);
122 spin_unlock(&sst_drv_ctx->list_spin_lock);
123
124 kfree(msg->mailbox_data);
125 kfree(msg);
126 return;
127}
128
129/*
130 * sst_clear_interrupt - clear the SST FW interrupt
131 *
132 * This function clears the interrupt register after the interrupt
133 * bottom half is complete allowing next interrupt to arrive
134 */
135void sst_clear_interrupt(void)
136{
137 union interrupt_reg isr;
138 union interrupt_reg imr;
139 union ipc_header clear_ipc;
140
141 imr.full = sst_shim_read(sst_drv_ctx->shim, SST_IMRX);
142 isr.full = sst_shim_read(sst_drv_ctx->shim, SST_ISRX);
143 /* write 1 to clear */;
144 isr.part.busy_interrupt = 1;
145 sst_shim_write(sst_drv_ctx->shim, SST_ISRX, isr.full);
146 /* Set IA done bit */
147 clear_ipc.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCD);
148 clear_ipc.part.busy = 0;
149 clear_ipc.part.done = 1;
150 clear_ipc.part.data = IPC_ACK_SUCCESS;
151 sst_shim_write(sst_drv_ctx->shim, SST_IPCD, clear_ipc.full);
152 /* un mask busy interrupt */
153 imr.part.busy_interrupt = 0;
154 sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
155}
156
157void sst_restore_fw_context(void)
158{
159 struct snd_sst_ctxt_params fw_context;
160 struct ipc_post *msg = NULL;
161
162 pr_debug("restore_fw_context\n");
163 /*check cpu type*/
164 if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID)
165 return;
166 /*not supported for rest*/
167 if (!sst_drv_ctx->fw_cntx_size)
168 return;
169 /*nothing to restore*/
170 pr_debug("restoring context......\n");
171 /*send msg to fw*/
172 if (sst_create_large_msg(&msg))
173 return;
174
175 sst_fill_header(&msg->header, IPC_IA_SET_FW_CTXT, 1, 0);
176 msg->header.part.data = sizeof(fw_context) + sizeof(u32);
177 fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx);
178 fw_context.size = sst_drv_ctx->fw_cntx_size;
179 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
180 memcpy(msg->mailbox_data + sizeof(u32),
181 &fw_context, sizeof(fw_context));
182 spin_lock(&sst_drv_ctx->list_spin_lock);
183 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
184 spin_unlock(&sst_drv_ctx->list_spin_lock);
185 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
186 return;
187}
188/*
189 * process_fw_init - process the FW init msg
190 *
191 * @msg: IPC message from FW
192 *
193 * This function processes the FW init msg from FW
194 * marks FW state and prints debug info of loaded FW
195 */
196int process_fw_init(struct sst_ipc_msg_wq *msg)
197{
198 struct ipc_header_fw_init *init =
199 (struct ipc_header_fw_init *)msg->mailbox;
200 int retval = 0;
201
202 pr_debug("*** FW Init msg came***\n");
203 if (init->result) {
204 mutex_lock(&sst_drv_ctx->sst_lock);
205 sst_drv_ctx->sst_state = SST_ERROR;
206 mutex_unlock(&sst_drv_ctx->sst_lock);
207 pr_debug("FW Init failed, Error %x\n", init->result);
208 pr_err("FW Init failed, Error %x\n", init->result);
209 retval = -init->result;
210 return retval;
211 }
212 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
213 sst_send_sound_card_type();
214 mutex_lock(&sst_drv_ctx->sst_lock);
215 sst_drv_ctx->sst_state = SST_FW_RUNNING;
216 sst_drv_ctx->lpe_stalled = 0;
217 mutex_unlock(&sst_drv_ctx->sst_lock);
218 pr_debug("FW Version %02x.%02x.%02x\n", init->fw_version.major,
219 init->fw_version.minor, init->fw_version.build);
220 pr_debug("Build Type %x\n", init->fw_version.type);
221 pr_debug(" Build date %s Time %s\n",
222 init->build_info.date, init->build_info.time);
223 sst_wake_up_alloc_block(sst_drv_ctx, FW_DWNL_ID, retval, NULL);
224 sst_restore_fw_context();
225 return retval;
226}
227/**
228* sst_process_message - Processes message from SST
229*
230* @work: Pointer to work structure
231*
232* This function is scheduled by ISR
233* It take a msg from process_queue and does action based on msg
234*/
235void sst_process_message(struct work_struct *work)
236{
237 struct sst_ipc_msg_wq *msg =
238 container_of(work, struct sst_ipc_msg_wq, wq);
239 int str_id = msg->header.part.str_id;
240
241 pr_debug("IPC process for %x\n", msg->header.full);
242
243 /* based on msg in list call respective handler */
244 switch (msg->header.part.msg_id) {
245 case IPC_SST_BUF_UNDER_RUN:
246 case IPC_SST_BUF_OVER_RUN:
247 if (sst_validate_strid(str_id)) {
248 pr_err("stream id %d invalid\n", str_id);
249 break;
250 }
251 pr_err("Buffer under/overrun for %d\n",
252 msg->header.part.str_id);
253 pr_err("Got Underrun & not to send data...ignore\n");
254 break;
255
256 case IPC_SST_GET_PLAY_FRAMES:
257 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
258 struct stream_info *stream ;
259
260 if (sst_validate_strid(str_id)) {
261 pr_err("strid %d invalid\n", str_id);
262 break;
263 }
264 /* call sst_play_frame */
265 stream = &sst_drv_ctx->streams[str_id];
266 pr_debug("sst_play_frames for %d\n",
267 msg->header.part.str_id);
268 mutex_lock(&sst_drv_ctx->streams[str_id].lock);
269 sst_play_frame(msg->header.part.str_id);
270 mutex_unlock(&sst_drv_ctx->streams[str_id].lock);
271 break;
272 } else
273 pr_err("sst_play_frames for Penwell!!\n");
274
275 case IPC_SST_GET_CAPT_FRAMES:
276 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
277 struct stream_info *stream;
278 /* call sst_capture_frame */
279 if (sst_validate_strid(str_id)) {
280 pr_err("str id %d invalid\n", str_id);
281 break;
282 }
283 stream = &sst_drv_ctx->streams[str_id];
284 pr_debug("sst_capture_frames for %d\n",
285 msg->header.part.str_id);
286 mutex_lock(&stream->lock);
287 if (stream->mmapped == false &&
288 stream->src == SST_DRV) {
289 pr_debug("waking up block for copy.\n");
290 stream->data_blk.ret_code = 0;
291 stream->data_blk.condition = true;
292 stream->data_blk.on = false;
293 wake_up(&sst_drv_ctx->wait_queue);
294 } else
295 sst_capture_frame(msg->header.part.str_id);
296 mutex_unlock(&stream->lock);
297 } else
298 pr_err("sst_play_frames for Penwell!!\n");
299 break;
300
301 case IPC_IA_PRINT_STRING:
302 pr_debug("been asked to print something by fw\n");
303 /* TBD */
304 break;
305
306 case IPC_IA_FW_INIT_CMPLT: {
307 /* send next data to FW */
308 process_fw_init(msg);
309 break;
310 }
311
312 case IPC_SST_STREAM_PROCESS_FATAL_ERR:
313 if (sst_validate_strid(str_id)) {
314 pr_err("stream id %d invalid\n", str_id);
315 break;
316 }
317 pr_err("codec fatal error %x stream %d...\n",
318 msg->header.full, msg->header.part.str_id);
319 pr_err("Dropping the stream\n");
320 sst_drop_stream(msg->header.part.str_id);
321 break;
322 case IPC_IA_LPE_GETTING_STALLED:
323 sst_drv_ctx->lpe_stalled = 1;
324 break;
325 case IPC_IA_LPE_UNSTALLED:
326 sst_drv_ctx->lpe_stalled = 0;
327 break;
328 default:
329 /* Illegal case */
330 pr_err("Unhandled msg %x header %x\n",
331 msg->header.part.msg_id, msg->header.full);
332 }
333 sst_clear_interrupt();
334 return;
335}
336
337/**
338* sst_process_reply - Processes reply message from SST
339*
340* @work: Pointer to work structure
341*
342* This function is scheduled by ISR
343* It take a reply msg from response_queue and
344* does action based on msg
345*/
346void sst_process_reply(struct work_struct *work)
347{
348 struct sst_ipc_msg_wq *msg =
349 container_of(work, struct sst_ipc_msg_wq, wq);
350
351 int str_id = msg->header.part.str_id;
352 struct stream_info *str_info;
353
354 switch (msg->header.part.msg_id) {
355 case IPC_IA_TARGET_DEV_SELECT:
356 if (!msg->header.part.data) {
357 sst_drv_ctx->tgt_dev_blk.ret_code = 0;
358 } else {
359 pr_err(" Msg %x reply error %x\n",
360 msg->header.part.msg_id, msg->header.part.data);
361 sst_drv_ctx->tgt_dev_blk.ret_code =
362 -msg->header.part.data;
363 }
364
365 if (sst_drv_ctx->tgt_dev_blk.on == true) {
366 sst_drv_ctx->tgt_dev_blk.condition = true;
367 wake_up(&sst_drv_ctx->wait_queue);
368 }
369 break;
370 case IPC_IA_ALG_PARAMS: {
371 pr_debug("sst:IPC_ALG_PARAMS response %x\n", msg->header.full);
372 pr_debug("sst: data value %x\n", msg->header.part.data);
373 pr_debug("sst: large value %x\n", msg->header.part.large);
374
375 if (!msg->header.part.large) {
376 if (!msg->header.part.data) {
377 pr_debug("sst: alg set success\n");
378 sst_drv_ctx->ppp_params_blk.ret_code = 0;
379 } else {
380 pr_debug("sst: alg set failed\n");
381 sst_drv_ctx->ppp_params_blk.ret_code =
382 -msg->header.part.data;
383 }
384
385 } else if (msg->header.part.data) {
386 struct snd_ppp_params *mailbox_params, *get_params;
387 char *params;
388
389 pr_debug("sst: alg get success\n");
390 mailbox_params = (struct snd_ppp_params *)msg->mailbox;
391 get_params = kzalloc(sizeof(*get_params), GFP_KERNEL);
392 if (get_params == NULL) {
393 pr_err("sst: out of memory for ALG PARAMS");
394 break;
395 }
396 memcpy_fromio(get_params, mailbox_params,
397 sizeof(*get_params));
398 get_params->params = kzalloc(mailbox_params->size,
399 GFP_KERNEL);
400 if (get_params->params == NULL) {
401 kfree(get_params);
402 pr_err("sst: out of memory for ALG PARAMS block");
403 break;
404 }
405 params = msg->mailbox;
406 params = params + sizeof(*mailbox_params) - sizeof(u32);
407 memcpy_fromio(get_params->params, params,
408 get_params->size);
409 sst_drv_ctx->ppp_params_blk.ret_code = 0;
410 sst_drv_ctx->ppp_params_blk.data = get_params;
411 }
412
413 if (sst_drv_ctx->ppp_params_blk.on == true) {
414 sst_drv_ctx->ppp_params_blk.condition = true;
415 wake_up(&sst_drv_ctx->wait_queue);
416 }
417 break;
418 }
419
420 case IPC_IA_TUNING_PARAMS: {
421 pr_debug("sst:IPC_TUNING_PARAMS resp: %x\n", msg->header.full);
422 pr_debug("data value %x\n", msg->header.part.data);
423 if (msg->header.part.large) {
424 pr_debug("alg set failed\n");
425 sst_drv_ctx->ppp_params_blk.ret_code =
426 -msg->header.part.data;
427 } else {
428 pr_debug("alg set success\n");
429 sst_drv_ctx->ppp_params_blk.ret_code = 0;
430 }
431 if (sst_drv_ctx->ppp_params_blk.on == true) {
432 sst_drv_ctx->ppp_params_blk.condition = true;
433 wake_up(&sst_drv_ctx->wait_queue);
434 }
435 }
436
437 case IPC_IA_GET_FW_INFO: {
438 struct snd_sst_fw_info *fw_info =
439 (struct snd_sst_fw_info *)msg->mailbox;
440 if (msg->header.part.large) {
441 int major = fw_info->fw_version.major;
442 int minor = fw_info->fw_version.minor;
443 int build = fw_info->fw_version.build;
444 pr_debug("Msg succeeded %x\n",
445 msg->header.part.msg_id);
446 pr_debug("INFO: ***FW*** = %02d.%02d.%02d\n",
447 major, minor, build);
448 memcpy_fromio(sst_drv_ctx->fw_info_blk.data,
449 ((struct snd_sst_fw_info *)(msg->mailbox)),
450 sizeof(struct snd_sst_fw_info));
451 sst_drv_ctx->fw_info_blk.ret_code = 0;
452 } else {
453 pr_err(" Msg %x reply error %x\n",
454 msg->header.part.msg_id, msg->header.part.data);
455 sst_drv_ctx->fw_info_blk.ret_code =
456 -msg->header.part.data;
457 }
458 if (sst_drv_ctx->fw_info_blk.on == true) {
459 pr_debug("Memcopy succeeded\n");
460 sst_drv_ctx->fw_info_blk.on = false;
461 sst_drv_ctx->fw_info_blk.condition = true;
462 wake_up(&sst_drv_ctx->wait_queue);
463 }
464 break;
465 }
466 case IPC_IA_SET_STREAM_MUTE:
467 if (!msg->header.part.data) {
468 pr_debug("Msg succeeded %x\n",
469 msg->header.part.msg_id);
470 sst_drv_ctx->mute_info_blk.ret_code = 0;
471 } else {
472 pr_err(" Msg %x reply error %x\n",
473 msg->header.part.msg_id, msg->header.part.data);
474 sst_drv_ctx->mute_info_blk.ret_code =
475 -msg->header.part.data;
476
477 }
478 if (sst_drv_ctx->mute_info_blk.on == true) {
479 sst_drv_ctx->mute_info_blk.on = false;
480 sst_drv_ctx->mute_info_blk.condition = true;
481 wake_up(&sst_drv_ctx->wait_queue);
482 }
483 break;
484 case IPC_IA_SET_STREAM_VOL:
485 if (!msg->header.part.data) {
486 pr_debug("Msg succeeded %x\n",
487 msg->header.part.msg_id);
488 sst_drv_ctx->vol_info_blk.ret_code = 0;
489 } else {
490 pr_err(" Msg %x reply error %x\n",
491 msg->header.part.msg_id,
492 msg->header.part.data);
493 sst_drv_ctx->vol_info_blk.ret_code =
494 -msg->header.part.data;
495
496 }
497
498 if (sst_drv_ctx->vol_info_blk.on == true) {
499 sst_drv_ctx->vol_info_blk.on = false;
500 sst_drv_ctx->vol_info_blk.condition = true;
501 wake_up(&sst_drv_ctx->wait_queue);
502 }
503 break;
504 case IPC_IA_GET_STREAM_VOL:
505 if (msg->header.part.large) {
506 pr_debug("Large Msg Received Successfully\n");
507 pr_debug("Msg succeeded %x\n",
508 msg->header.part.msg_id);
509 memcpy_fromio(sst_drv_ctx->vol_info_blk.data,
510 (void *) msg->mailbox,
511 sizeof(struct snd_sst_vol));
512 sst_drv_ctx->vol_info_blk.ret_code = 0;
513 } else {
514 pr_err("Msg %x reply error %x\n",
515 msg->header.part.msg_id, msg->header.part.data);
516 sst_drv_ctx->vol_info_blk.ret_code =
517 -msg->header.part.data;
518 }
519 if (sst_drv_ctx->vol_info_blk.on == true) {
520 sst_drv_ctx->vol_info_blk.on = false;
521 sst_drv_ctx->vol_info_blk.condition = true;
522 wake_up(&sst_drv_ctx->wait_queue);
523 }
524 break;
525
526 case IPC_IA_GET_STREAM_PARAMS:
527 if (sst_validate_strid(str_id)) {
528 pr_err("stream id %d invalid\n", str_id);
529 break;
530 }
531 str_info = &sst_drv_ctx->streams[str_id];
532 if (msg->header.part.large) {
533 pr_debug("Get stream large success\n");
534 memcpy_fromio(str_info->ctrl_blk.data,
535 ((void *)(msg->mailbox)),
536 sizeof(struct snd_sst_fw_get_stream_params));
537 str_info->ctrl_blk.ret_code = 0;
538 } else {
539 pr_err("Msg %x reply error %x\n",
540 msg->header.part.msg_id, msg->header.part.data);
541 str_info->ctrl_blk.ret_code = -msg->header.part.data;
542 }
543 if (str_info->ctrl_blk.on == true) {
544 str_info->ctrl_blk.on = false;
545 str_info->ctrl_blk.condition = true;
546 wake_up(&sst_drv_ctx->wait_queue);
547 }
548 break;
549 case IPC_IA_DECODE_FRAMES:
550 if (sst_validate_strid(str_id)) {
551 pr_err("stream id %d invalid\n", str_id);
552 break;
553 }
554 str_info = &sst_drv_ctx->streams[str_id];
555 if (msg->header.part.large) {
556 pr_debug("Msg succeeded %x\n",
557 msg->header.part.msg_id);
558 memcpy_fromio(str_info->data_blk.data,
559 ((void *)(msg->mailbox)),
560 sizeof(struct snd_sst_decode_info));
561 str_info->data_blk.ret_code = 0;
562 } else {
563 pr_err("Msg %x reply error %x\n",
564 msg->header.part.msg_id, msg->header.part.data);
565 str_info->data_blk.ret_code = -msg->header.part.data;
566 }
567 if (str_info->data_blk.on == true) {
568 str_info->data_blk.on = false;
569 str_info->data_blk.condition = true;
570 wake_up(&sst_drv_ctx->wait_queue);
571 }
572 break;
573 case IPC_IA_DRAIN_STREAM:
574 if (sst_validate_strid(str_id)) {
575 pr_err("stream id %d invalid\n", str_id);
576 break;
577 }
578 str_info = &sst_drv_ctx->streams[str_id];
579 if (!msg->header.part.data) {
580 pr_debug("Msg succeeded %x\n",
581 msg->header.part.msg_id);
582 str_info->ctrl_blk.ret_code = 0;
583
584 } else {
585 pr_err(" Msg %x reply error %x\n",
586 msg->header.part.msg_id, msg->header.part.data);
587 str_info->ctrl_blk.ret_code = -msg->header.part.data;
588
589 }
590 str_info = &sst_drv_ctx->streams[str_id];
591 if (str_info->data_blk.on == true) {
592 str_info->data_blk.on = false;
593 str_info->data_blk.condition = true;
594 wake_up(&sst_drv_ctx->wait_queue);
595 }
596 break;
597
598 case IPC_IA_DROP_STREAM:
599 if (sst_validate_strid(str_id)) {
600 pr_err("str id %d invalid\n", str_id);
601 break;
602 }
603 str_info = &sst_drv_ctx->streams[str_id];
604 if (msg->header.part.large) {
605 struct snd_sst_drop_response *drop_resp =
606 (struct snd_sst_drop_response *)msg->mailbox;
607
608 pr_debug("Drop ret bytes %x\n", drop_resp->bytes);
609
610 str_info->curr_bytes = drop_resp->bytes;
611 str_info->ctrl_blk.ret_code = 0;
612 } else {
613 pr_err(" Msg %x reply error %x\n",
614 msg->header.part.msg_id, msg->header.part.data);
615 str_info->ctrl_blk.ret_code = -msg->header.part.data;
616 }
617 if (str_info->ctrl_blk.on == true) {
618 str_info->ctrl_blk.on = false;
619 str_info->ctrl_blk.condition = true;
620 wake_up(&sst_drv_ctx->wait_queue);
621 }
622 break;
623 case IPC_IA_ENABLE_RX_TIME_SLOT:
624 if (!msg->header.part.data) {
625 pr_debug("RX_TIME_SLOT success\n");
626 sst_drv_ctx->hs_info_blk.ret_code = 0;
627 } else {
628 pr_err(" Msg %x reply error %x\n",
629 msg->header.part.msg_id,
630 msg->header.part.data);
631 sst_drv_ctx->hs_info_blk.ret_code =
632 -msg->header.part.data;
633 }
634 if (sst_drv_ctx->hs_info_blk.on == true) {
635 sst_drv_ctx->hs_info_blk.on = false;
636 sst_drv_ctx->hs_info_blk.condition = true;
637 wake_up(&sst_drv_ctx->wait_queue);
638 }
639 break;
640 case IPC_IA_PAUSE_STREAM:
641 case IPC_IA_RESUME_STREAM:
642 case IPC_IA_SET_STREAM_PARAMS:
643 str_info = &sst_drv_ctx->streams[str_id];
644 if (!msg->header.part.data) {
645 pr_debug("Msg succeeded %x\n",
646 msg->header.part.msg_id);
647 str_info->ctrl_blk.ret_code = 0;
648 } else {
649 pr_err(" Msg %x reply error %x\n",
650 msg->header.part.msg_id,
651 msg->header.part.data);
652 str_info->ctrl_blk.ret_code = -msg->header.part.data;
653 }
654 if (sst_validate_strid(str_id)) {
655 pr_err(" stream id %d invalid\n", str_id);
656 break;
657 }
658
659 if (str_info->ctrl_blk.on == true) {
660 str_info->ctrl_blk.on = false;
661 str_info->ctrl_blk.condition = true;
662 wake_up(&sst_drv_ctx->wait_queue);
663 }
664 break;
665
666 case IPC_IA_FREE_STREAM:
667 str_info = &sst_drv_ctx->streams[str_id];
668 if (!msg->header.part.data) {
669 pr_debug("Stream %d freed\n", str_id);
670 } else {
671 pr_err("Free for %d ret error %x\n",
672 str_id, msg->header.part.data);
673 }
674 if (str_info->ctrl_blk.on == true) {
675 str_info->ctrl_blk.on = false;
676 str_info->ctrl_blk.condition = true;
677 wake_up(&sst_drv_ctx->wait_queue);
678 }
679 break;
680 case IPC_IA_ALLOC_STREAM: {
681 /* map to stream, call play */
682 struct snd_sst_alloc_response *resp =
683 (struct snd_sst_alloc_response *)msg->mailbox;
684 if (resp->str_type.result)
685 pr_err("error alloc stream = %x\n",
686 resp->str_type.result);
687 sst_alloc_stream_response(str_id, resp);
688 break;
689 }
690
691 case IPC_IA_PLAY_FRAMES:
692 case IPC_IA_CAPT_FRAMES:
693 if (sst_validate_strid(str_id)) {
694 pr_err("stream id %d invalid\n", str_id);
695 break;
696 }
697 pr_debug("Ack for play/capt frames received\n");
698 break;
699
700 case IPC_IA_PREP_LIB_DNLD: {
701 struct snd_sst_str_type *str_type =
702 (struct snd_sst_str_type *)msg->mailbox;
703 pr_debug("Prep Lib download %x\n",
704 msg->header.part.msg_id);
705 if (str_type->result)
706 pr_err("Prep lib download %x\n", str_type->result);
707 else
708 pr_debug("Can download codec now...\n");
709 sst_wake_up_alloc_block(sst_drv_ctx, str_id,
710 str_type->result, NULL);
711 break;
712 }
713
714 case IPC_IA_LIB_DNLD_CMPLT: {
715 struct snd_sst_lib_download_info *resp =
716 (struct snd_sst_lib_download_info *)msg->mailbox;
717 int retval = resp->result;
718
719 pr_debug("Lib downloaded %x\n", msg->header.part.msg_id);
720 if (resp->result) {
721 pr_err("err in lib dload %x\n", resp->result);
722 } else {
723 pr_debug("Codec download complete...\n");
724 pr_debug("codec Type %d Ver %d Built %s: %s\n",
725 resp->dload_lib.lib_info.lib_type,
726 resp->dload_lib.lib_info.lib_version,
727 resp->dload_lib.lib_info.b_date,
728 resp->dload_lib.lib_info.b_time);
729 }
730 sst_wake_up_alloc_block(sst_drv_ctx, str_id,
731 retval, NULL);
732 break;
733 }
734
735 case IPC_IA_GET_FW_VERSION: {
736 struct ipc_header_fw_init *version =
737 (struct ipc_header_fw_init *)msg->mailbox;
738 int major = version->fw_version.major;
739 int minor = version->fw_version.minor;
740 int build = version->fw_version.build;
741 dev_info(&sst_drv_ctx->pci->dev,
742 "INFO: ***LOADED SST FW VERSION*** = %02d.%02d.%02d\n",
743 major, minor, build);
744 break;
745 }
746 case IPC_IA_GET_FW_BUILD_INF: {
747 struct sst_fw_build_info *build =
748 (struct sst_fw_build_info *)msg->mailbox;
749 pr_debug("Build date:%sTime:%s", build->date, build->time);
750 break;
751 }
752 case IPC_IA_SET_PMIC_TYPE:
753 break;
754 case IPC_IA_START_STREAM:
755 pr_debug("reply for START STREAM %x\n", msg->header.full);
756 break;
757
758 case IPC_IA_GET_FW_CTXT:
759 pr_debug("reply for get fw ctxt %x\n", msg->header.full);
760 if (msg->header.part.data)
761 sst_drv_ctx->fw_cntx_size = 0;
762 else
763 sst_drv_ctx->fw_cntx_size = *sst_drv_ctx->fw_cntx;
764 pr_debug("fw copied data %x\n", sst_drv_ctx->fw_cntx_size);
765 sst_wake_up_alloc_block(
766 sst_drv_ctx, str_id, msg->header.part.data, NULL);
767 break;
768 default:
769 /* Illegal case */
770 pr_err("process reply:default = %x\n", msg->header.full);
771 }
772 sst_clear_interrupt();
773 return;
774}
diff --git a/drivers/staging/intel_sst/intel_sst_pvt.c b/drivers/staging/intel_sst/intel_sst_pvt.c
new file mode 100644
index 00000000000..e034bea56f1
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_pvt.c
@@ -0,0 +1,313 @@
1/*
2 * intel_sst_pvt.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This driver exposes the audio engine functionalities to the ALSA
27 * and middleware.
28 *
29 * This file contains all private functions
30 */
31
32#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
34#include <linux/pci.h>
35#include <linux/fs.h>
36#include <linux/firmware.h>
37#include <linux/sched.h>
38#include "intel_sst.h"
39#include "intel_sst_ioctl.h"
40#include "intel_sst_fw_ipc.h"
41#include "intel_sst_common.h"
42
43/*
44 * sst_get_block_stream - get a new block stream
45 *
46 * @sst_drv_ctx: Driver context structure
47 *
48 * This function assigns a block for the calls that dont have stream context yet
49 * the blocks are used for waiting on Firmware's response for any operation
50 * Should be called with stream lock held
51 */
52int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx)
53{
54 int i;
55
56 for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
57 if (sst_drv_ctx->alloc_block[i].sst_id == BLOCK_UNINIT) {
58 sst_drv_ctx->alloc_block[i].ops_block.condition = false;
59 sst_drv_ctx->alloc_block[i].ops_block.ret_code = 0;
60 sst_drv_ctx->alloc_block[i].sst_id = 0;
61 break;
62 }
63 }
64 if (i == MAX_ACTIVE_STREAM) {
65 pr_err("max alloc_stream reached\n");
66 i = -EBUSY; /* active stream limit reached */
67 }
68 return i;
69}
70
71/*
72 * sst_wait_interruptible - wait on event
73 *
74 * @sst_drv_ctx: Driver context
75 * @block: Driver block to wait on
76 *
77 * This function waits without a timeout (and is interruptable) for a
78 * given block event
79 */
80int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
81 struct sst_block *block)
82{
83 int retval = 0;
84
85 if (!wait_event_interruptible(sst_drv_ctx->wait_queue,
86 block->condition)) {
87 /* event wake */
88 if (block->ret_code < 0) {
89 pr_err("stream failed %d\n", block->ret_code);
90 retval = -EBUSY;
91 } else {
92 pr_debug("event up\n");
93 retval = 0;
94 }
95 } else {
96 pr_err("signal interrupted\n");
97 retval = -EINTR;
98 }
99 return retval;
100
101}
102
103
104/*
105 * sst_wait_interruptible_timeout - wait on event interruptable
106 *
107 * @sst_drv_ctx: Driver context
108 * @block: Driver block to wait on
109 * @timeout: time for wait on
110 *
111 * This function waits with a timeout value (and is interruptible) on a
112 * given block event
113 */
114int sst_wait_interruptible_timeout(
115 struct intel_sst_drv *sst_drv_ctx,
116 struct sst_block *block, int timeout)
117{
118 int retval = 0;
119
120 pr_debug("sst_wait_interruptible_timeout - waiting....\n");
121 if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue,
122 block->condition,
123 msecs_to_jiffies(timeout))) {
124 if (block->ret_code < 0)
125 pr_err("stream failed %d\n", block->ret_code);
126 else
127 pr_debug("event up\n");
128 retval = block->ret_code;
129 } else {
130 block->on = false;
131 pr_err("timeout occurred...\n");
132 /*setting firmware state as uninit so that the
133 firmware will get re-downloaded on next request
134 this is because firmare not responding for 5 sec
135 is equalant to some unrecoverable error of FW
136 sst_drv_ctx->sst_state = SST_UN_INIT;*/
137 retval = -EBUSY;
138 }
139 return retval;
140
141}
142
143
144/*
145 * sst_wait_timeout - wait on event for timeout
146 *
147 * @sst_drv_ctx: Driver context
148 * @block: Driver block to wait on
149 *
150 * This function waits with a timeout value (and is not interruptible) on a
151 * given block event
152 */
153int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
154 struct stream_alloc_block *block)
155{
156 int retval = 0;
157
158 /* NOTE:
159 Observed that FW processes the alloc msg and replies even
160 before the alloc thread has finished execution */
161 pr_debug("waiting for %x, condition %x\n",
162 block->sst_id, block->ops_block.condition);
163 if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue,
164 block->ops_block.condition,
165 msecs_to_jiffies(SST_BLOCK_TIMEOUT))) {
166 /* event wake */
167 pr_debug("Event wake %x\n", block->ops_block.condition);
168 pr_debug("message ret: %d\n", block->ops_block.ret_code);
169 retval = block->ops_block.ret_code;
170 } else {
171 block->ops_block.on = false;
172 pr_err("Wait timed-out %x\n", block->ops_block.condition);
173 /* settign firmware state as uninit so that the
174 firmware will get redownloaded on next request
175 this is because firmare not responding for 5 sec
176 is equalant to some unrecoverable error of FW
177 sst_drv_ctx->sst_state = SST_UN_INIT;*/
178 retval = -EBUSY;
179 }
180 return retval;
181
182}
183
184/*
185 * sst_create_large_msg - create a large IPC message
186 *
187 * @arg: ipc message
188 *
189 * this function allocates structures to send a large message to the firmware
190 */
191int sst_create_large_msg(struct ipc_post **arg)
192{
193 struct ipc_post *msg;
194
195 msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC);
196 if (!msg) {
197 pr_err("kzalloc msg failed\n");
198 return -ENOMEM;
199 }
200
201 msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
202 if (!msg->mailbox_data) {
203 kfree(msg);
204 pr_err("kzalloc mailbox_data failed");
205 return -ENOMEM;
206 }
207 *arg = msg;
208 return 0;
209}
210
211/*
212 * sst_create_short_msg - create a short IPC message
213 *
214 * @arg: ipc message
215 *
216 * this function allocates structures to send a short message to the firmware
217 */
218int sst_create_short_msg(struct ipc_post **arg)
219{
220 struct ipc_post *msg;
221
222 msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
223 if (!msg) {
224 pr_err("kzalloc msg failed\n");
225 return -ENOMEM;
226 }
227 msg->mailbox_data = NULL;
228 *arg = msg;
229 return 0;
230}
231
232/*
233 * sst_clean_stream - clean the stream context
234 *
235 * @stream: stream structure
236 *
237 * this function resets the stream contexts
238 * should be called in free
239 */
240void sst_clean_stream(struct stream_info *stream)
241{
242 struct sst_stream_bufs *bufs = NULL, *_bufs;
243 stream->status = STREAM_UN_INIT;
244 stream->prev = STREAM_UN_INIT;
245 mutex_lock(&stream->lock);
246 list_for_each_entry_safe(bufs, _bufs, &stream->bufs, node) {
247 list_del(&bufs->node);
248 kfree(bufs);
249 }
250 mutex_unlock(&stream->lock);
251
252 if (stream->ops != STREAM_OPS_PLAYBACK_DRM)
253 kfree(stream->decode_ibuf);
254}
255
256/*
257 * sst_wake_up_alloc_block - wake up waiting block
258 *
259 * @sst_drv_ctx: Driver context
260 * @sst_id: stream id
261 * @status: status of wakeup
262 * @data: data pointer of wakeup
263 *
264 * This function wakes up a sleeping block event based on the response
265 */
266void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx,
267 u8 sst_id, int status, void *data)
268{
269 int i;
270
271 /* Unblock with retval code */
272 for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
273 if (sst_id == sst_drv_ctx->alloc_block[i].sst_id) {
274 sst_drv_ctx->alloc_block[i].ops_block.condition = true;
275 sst_drv_ctx->alloc_block[i].ops_block.ret_code = status;
276 sst_drv_ctx->alloc_block[i].ops_block.data = data;
277 wake_up(&sst_drv_ctx->wait_queue);
278 break;
279 }
280 }
281}
282
283/*
284 * sst_enable_rx_timeslot - Send msg to query for stream parameters
285 * @status: rx timeslot to be enabled
286 *
287 * This function is called when the RX timeslot is required to be enabled
288 */
289int sst_enable_rx_timeslot(int status)
290{
291 int retval = 0;
292 struct ipc_post *msg = NULL;
293
294 if (sst_create_short_msg(&msg)) {
295 pr_err("mem allocation failed\n");
296 return -ENOMEM;
297 }
298 pr_debug("ipc message sending: ENABLE_RX_TIME_SLOT\n");
299 sst_fill_header(&msg->header, IPC_IA_ENABLE_RX_TIME_SLOT, 0, 0);
300 msg->header.part.data = status;
301 sst_drv_ctx->hs_info_blk.condition = false;
302 sst_drv_ctx->hs_info_blk.ret_code = 0;
303 sst_drv_ctx->hs_info_blk.on = true;
304 spin_lock(&sst_drv_ctx->list_spin_lock);
305 list_add_tail(&msg->node,
306 &sst_drv_ctx->ipc_dispatch_list);
307 spin_unlock(&sst_drv_ctx->list_spin_lock);
308 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
309 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
310 &sst_drv_ctx->hs_info_blk, SST_BLOCK_TIMEOUT);
311 return retval;
312}
313
diff --git a/drivers/staging/intel_sst/intel_sst_stream.c b/drivers/staging/intel_sst/intel_sst_stream.c
new file mode 100644
index 00000000000..be4565e74f8
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_stream.c
@@ -0,0 +1,583 @@
1/*
2 * intel_sst_stream.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This file contains the stream operations of SST driver
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/pci.h>
32#include <linux/firmware.h>
33#include <linux/sched.h>
34#include <linux/delay.h>
35#include "intel_sst_ioctl.h"
36#include "intel_sst.h"
37#include "intel_sst_fw_ipc.h"
38#include "intel_sst_common.h"
39
40/*
41 * sst_check_device_type - Check the medfield device type
42 *
43 * @device: Device to be checked
44 * @num_ch: Number of channels queried
45 * @pcm_slot: slot to be enabled for this device
46 *
47 * This checks the deivce against the map and calculates pcm_slot value
48 */
49int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
50{
51 if (device >= MAX_NUM_STREAMS_MFLD) {
52 pr_debug("device type invalid %d\n", device);
53 return -EINVAL;
54 }
55 if (sst_drv_ctx->streams[device].status == STREAM_UN_INIT) {
56 if (device == SND_SST_DEVICE_VIBRA && num_chan == 1)
57 *pcm_slot = 0x10;
58 else if (device == SND_SST_DEVICE_HAPTIC && num_chan == 1)
59 *pcm_slot = 0x20;
60 else if (device == SND_SST_DEVICE_IHF && num_chan == 1)
61 *pcm_slot = 0x04;
62 else if (device == SND_SST_DEVICE_IHF && num_chan == 2)
63 *pcm_slot = 0x0C;
64 else if (device == SND_SST_DEVICE_HEADSET && num_chan == 1)
65 *pcm_slot = 0x01;
66 else if (device == SND_SST_DEVICE_HEADSET && num_chan == 2)
67 *pcm_slot = 0x03;
68 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 1)
69 *pcm_slot = 0x01;
70 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 2)
71 *pcm_slot = 0x03;
72 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 3)
73 *pcm_slot = 0x07;
74 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4)
75 *pcm_slot = 0x0F;
76 else if (device == SND_SST_DEVICE_CAPTURE && num_chan > 4)
77 *pcm_slot = 0x1F;
78 else {
79 pr_debug("No condition satisfied.. ret err\n");
80 return -EINVAL;
81 }
82 } else {
83 pr_debug("this stream state is not uni-init, is %d\n",
84 sst_drv_ctx->streams[device].status);
85 return -EBADRQC;
86 }
87 pr_debug("returning slot %x\n", *pcm_slot);
88 return 0;
89}
90/**
91 * get_mrst_stream_id - gets a new stream id for use
92 *
93 * This functions searches the current streams and allocated an empty stream
94 * lock stream_lock required to be held before calling this
95 */
96static unsigned int get_mrst_stream_id(void)
97{
98 int i;
99
100 for (i = 1; i <= MAX_NUM_STREAMS_MRST; i++) {
101 if (sst_drv_ctx->streams[i].status == STREAM_UN_INIT)
102 return i;
103 }
104 pr_debug("Didn't find empty stream for mrst\n");
105 return -EBUSY;
106}
107
108/**
109 * sst_alloc_stream - Send msg for a new stream ID
110 *
111 * @params: stream params
112 * @stream_ops: operation of stream PB/capture
113 * @codec: codec for stream
114 * @device: device stream to be allocated for
115 *
116 * This function is called by any function which wants to start
117 * a new stream. This also check if a stream exists which is idle
118 * it initializes idle stream id to this request
119 */
120int sst_alloc_stream(char *params, unsigned int stream_ops,
121 u8 codec, unsigned int device)
122{
123 struct ipc_post *msg = NULL;
124 struct snd_sst_alloc_params alloc_param;
125 unsigned int pcm_slot = 0, num_ch;
126 int str_id;
127 struct snd_sst_stream_params *sparams;
128 struct stream_info *str_info;
129
130 pr_debug("SST DBG:entering sst_alloc_stream\n");
131 pr_debug("SST DBG:%d %d %d\n", stream_ops, codec, device);
132
133 BUG_ON(!params);
134 sparams = (struct snd_sst_stream_params *)params;
135 num_ch = sparams->uc.pcm_params.num_chan;
136 /*check the device type*/
137 if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
138 if (sst_check_device_type(device, num_ch, &pcm_slot))
139 return -EINVAL;
140 mutex_lock(&sst_drv_ctx->stream_lock);
141 str_id = device;
142 mutex_unlock(&sst_drv_ctx->stream_lock);
143 pr_debug("SST_DBG: slot %x\n", pcm_slot);
144 } else {
145 mutex_lock(&sst_drv_ctx->stream_lock);
146 str_id = get_mrst_stream_id();
147 mutex_unlock(&sst_drv_ctx->stream_lock);
148 if (str_id <= 0)
149 return -EBUSY;
150 }
151 /*allocate device type context*/
152 sst_init_stream(&sst_drv_ctx->streams[str_id], codec,
153 str_id, stream_ops, pcm_slot, device);
154 /* send msg to FW to allocate a stream */
155 if (sst_create_large_msg(&msg))
156 return -ENOMEM;
157
158 sst_fill_header(&msg->header, IPC_IA_ALLOC_STREAM, 1, str_id);
159 msg->header.part.data = sizeof(alloc_param) + sizeof(u32);
160 alloc_param.str_type.codec_type = codec;
161 alloc_param.str_type.str_type = SST_STREAM_TYPE_MUSIC;
162 alloc_param.str_type.operation = stream_ops;
163 alloc_param.str_type.protected_str = 0; /* non drm */
164 alloc_param.str_type.time_slots = pcm_slot;
165 alloc_param.str_type.result = alloc_param.str_type.reserved = 0;
166 memcpy(&alloc_param.stream_params, params,
167 sizeof(struct snd_sst_stream_params));
168
169 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
170 memcpy(msg->mailbox_data + sizeof(u32), &alloc_param,
171 sizeof(alloc_param));
172 str_info = &sst_drv_ctx->streams[str_id];
173 str_info->ctrl_blk.condition = false;
174 str_info->ctrl_blk.ret_code = 0;
175 str_info->ctrl_blk.on = true;
176 spin_lock(&sst_drv_ctx->list_spin_lock);
177 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
178 spin_unlock(&sst_drv_ctx->list_spin_lock);
179 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
180 pr_debug("SST DBG:alloc stream done\n");
181 return str_id;
182}
183
184
185/*
186 * sst_alloc_stream_response - process alloc reply
187 *
188 * @str_id: stream id for which the stream has been allocated
189 * @resp the stream response from firware
190 *
191 * This function is called by firmware as a response to stream allcoation
192 * request
193 */
194int sst_alloc_stream_response(unsigned int str_id,
195 struct snd_sst_alloc_response *resp)
196{
197 int retval = 0;
198 struct stream_info *str_info;
199 struct snd_sst_lib_download *lib_dnld;
200
201 pr_debug("SST DEBUG: stream number given = %d\n", str_id);
202 str_info = &sst_drv_ctx->streams[str_id];
203 if (resp->str_type.result == SST_LIB_ERR_LIB_DNLD_REQUIRED) {
204 lib_dnld = kzalloc(sizeof(*lib_dnld), GFP_KERNEL);
205 memcpy(lib_dnld, &resp->lib_dnld, sizeof(*lib_dnld));
206 } else
207 lib_dnld = NULL;
208 if (str_info->ctrl_blk.on == true) {
209 str_info->ctrl_blk.on = false;
210 str_info->ctrl_blk.data = lib_dnld;
211 str_info->ctrl_blk.condition = true;
212 str_info->ctrl_blk.ret_code = resp->str_type.result;
213 pr_debug("SST DEBUG: sst_alloc_stream_response: waking up.\n");
214 wake_up(&sst_drv_ctx->wait_queue);
215 }
216 return retval;
217}
218
219
220/**
221* sst_get_fw_info - Send msg to query for firmware configurations
222* @info: out param that holds the firmare configurations
223*
224* This function is called when the firmware configurations are queiried for
225*/
226int sst_get_fw_info(struct snd_sst_fw_info *info)
227{
228 int retval = 0;
229 struct ipc_post *msg = NULL;
230
231 pr_debug("SST DBG:sst_get_fw_info called\n");
232
233 if (sst_create_short_msg(&msg)) {
234 pr_err("SST ERR: message creation failed\n");
235 return -ENOMEM;
236 }
237
238 sst_fill_header(&msg->header, IPC_IA_GET_FW_INFO, 0, 0);
239 sst_drv_ctx->fw_info_blk.condition = false;
240 sst_drv_ctx->fw_info_blk.ret_code = 0;
241 sst_drv_ctx->fw_info_blk.on = true;
242 sst_drv_ctx->fw_info_blk.data = info;
243 spin_lock(&sst_drv_ctx->list_spin_lock);
244 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
245 spin_unlock(&sst_drv_ctx->list_spin_lock);
246 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
247 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
248 &sst_drv_ctx->fw_info_blk, SST_BLOCK_TIMEOUT);
249 if (retval) {
250 pr_err("SST ERR: error in fw_info = %d\n", retval);
251 retval = -EIO;
252 }
253 return retval;
254}
255
256
257/**
258* sst_pause_stream - Send msg for a pausing stream
259* @str_id: stream ID
260*
261* This function is called by any function which wants to pause
262* an already running stream.
263*/
264int sst_start_stream(int str_id)
265{
266 int retval = 0;
267 struct ipc_post *msg = NULL;
268 struct stream_info *str_info;
269
270 pr_debug("sst_start_stream for %d\n", str_id);
271 retval = sst_validate_strid(str_id);
272 if (retval)
273 return retval;
274 str_info = &sst_drv_ctx->streams[str_id];
275 if (str_info->status != STREAM_INIT)
276 return -EBADRQC;
277 if (sst_create_short_msg(&msg))
278 return -ENOMEM;
279
280 sst_fill_header(&msg->header, IPC_IA_START_STREAM, 0, str_id);
281 spin_lock(&sst_drv_ctx->list_spin_lock);
282 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
283 spin_unlock(&sst_drv_ctx->list_spin_lock);
284 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
285 return retval;
286}
287
288/*
289 * sst_pause_stream - Send msg for a pausing stream
290 * @str_id: stream ID
291 *
292 * This function is called by any function which wants to pause
293 * an already running stream.
294 */
295int sst_pause_stream(int str_id)
296{
297 int retval = 0;
298 struct ipc_post *msg = NULL;
299 struct stream_info *str_info;
300
301 pr_debug("SST DBG:sst_pause_stream for %d\n", str_id);
302 retval = sst_validate_strid(str_id);
303 if (retval)
304 return retval;
305 str_info = &sst_drv_ctx->streams[str_id];
306 if (str_info->status == STREAM_PAUSED)
307 return 0;
308 if (str_info->status == STREAM_RUNNING ||
309 str_info->status == STREAM_INIT) {
310 if (str_info->prev == STREAM_UN_INIT)
311 return -EBADRQC;
312 if (str_info->ctrl_blk.on == true) {
313 pr_err("SST ERR: control path is in use\n");
314 return -EINVAL;
315 }
316 if (sst_create_short_msg(&msg))
317 return -ENOMEM;
318
319 sst_fill_header(&msg->header, IPC_IA_PAUSE_STREAM, 0, str_id);
320 str_info->ctrl_blk.condition = false;
321 str_info->ctrl_blk.ret_code = 0;
322 str_info->ctrl_blk.on = true;
323 spin_lock(&sst_drv_ctx->list_spin_lock);
324 list_add_tail(&msg->node,
325 &sst_drv_ctx->ipc_dispatch_list);
326 spin_unlock(&sst_drv_ctx->list_spin_lock);
327 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
328 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
329 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
330 if (retval == 0) {
331 str_info->prev = str_info->status;
332 str_info->status = STREAM_PAUSED;
333 } else if (retval == SST_ERR_INVALID_STREAM_ID) {
334 retval = -EINVAL;
335 mutex_lock(&sst_drv_ctx->stream_lock);
336 sst_clean_stream(str_info);
337 mutex_unlock(&sst_drv_ctx->stream_lock);
338 }
339 } else {
340 retval = -EBADRQC;
341 pr_err("SST ERR: BADQRC for stream\n");
342 }
343
344 return retval;
345}
346
347/**
348 * sst_resume_stream - Send msg for resuming stream
349 * @str_id: stream ID
350 *
351 * This function is called by any function which wants to resume
352 * an already paused stream.
353 */
354int sst_resume_stream(int str_id)
355{
356 int retval = 0;
357 struct ipc_post *msg = NULL;
358 struct stream_info *str_info;
359
360 pr_debug("SST DBG:sst_resume_stream for %d\n", str_id);
361 retval = sst_validate_strid(str_id);
362 if (retval)
363 return retval;
364 str_info = &sst_drv_ctx->streams[str_id];
365 if (str_info->status == STREAM_RUNNING)
366 return 0;
367 if (str_info->status == STREAM_PAUSED) {
368 if (str_info->ctrl_blk.on == true) {
369 pr_err("SST ERR: control path in use\n");
370 return -EINVAL;
371 }
372 if (sst_create_short_msg(&msg)) {
373 pr_err("SST ERR: mem allocation failed\n");
374 return -ENOMEM;
375 }
376 sst_fill_header(&msg->header, IPC_IA_RESUME_STREAM, 0, str_id);
377 str_info->ctrl_blk.condition = false;
378 str_info->ctrl_blk.ret_code = 0;
379 str_info->ctrl_blk.on = true;
380 spin_lock(&sst_drv_ctx->list_spin_lock);
381 list_add_tail(&msg->node,
382 &sst_drv_ctx->ipc_dispatch_list);
383 spin_unlock(&sst_drv_ctx->list_spin_lock);
384 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
385 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
386 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
387 if (!retval) {
388 if (str_info->prev == STREAM_RUNNING)
389 str_info->status = STREAM_RUNNING;
390 else
391 str_info->status = STREAM_INIT;
392 str_info->prev = STREAM_PAUSED;
393 } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
394 retval = -EINVAL;
395 mutex_lock(&sst_drv_ctx->stream_lock);
396 sst_clean_stream(str_info);
397 mutex_unlock(&sst_drv_ctx->stream_lock);
398 }
399 } else {
400 retval = -EBADRQC;
401 pr_err("SST ERR: BADQRC for stream\n");
402 }
403
404 return retval;
405}
406
407
408/**
409 * sst_drop_stream - Send msg for stopping stream
410 * @str_id: stream ID
411 *
412 * This function is called by any function which wants to stop
413 * a stream.
414 */
415int sst_drop_stream(int str_id)
416{
417 int retval = 0;
418 struct ipc_post *msg = NULL;
419 struct sst_stream_bufs *bufs = NULL, *_bufs;
420 struct stream_info *str_info;
421
422 pr_debug("SST DBG:sst_drop_stream for %d\n", str_id);
423 retval = sst_validate_strid(str_id);
424 if (retval)
425 return retval;
426 str_info = &sst_drv_ctx->streams[str_id];
427
428 if (str_info->status != STREAM_UN_INIT &&
429 str_info->status != STREAM_DECODE) {
430 if (str_info->ctrl_blk.on == true) {
431 pr_err("SST ERR: control path in use\n");
432 return -EINVAL;
433 }
434 if (sst_create_short_msg(&msg)) {
435 pr_err("SST ERR: mem allocation failed\n");
436 return -ENOMEM;
437 }
438 sst_fill_header(&msg->header, IPC_IA_DROP_STREAM, 0, str_id);
439 str_info->ctrl_blk.condition = false;
440 str_info->ctrl_blk.ret_code = 0;
441 str_info->ctrl_blk.on = true;
442 spin_lock(&sst_drv_ctx->list_spin_lock);
443 list_add_tail(&msg->node,
444 &sst_drv_ctx->ipc_dispatch_list);
445 spin_unlock(&sst_drv_ctx->list_spin_lock);
446 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
447 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
448 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
449 if (!retval) {
450 pr_debug("SST DBG:drop success\n");
451 str_info->prev = STREAM_UN_INIT;
452 str_info->status = STREAM_INIT;
453 if (str_info->src != MAD_DRV) {
454 mutex_lock(&str_info->lock);
455 list_for_each_entry_safe(bufs, _bufs,
456 &str_info->bufs, node) {
457 list_del(&bufs->node);
458 kfree(bufs);
459 }
460 mutex_unlock(&str_info->lock);
461 }
462 str_info->cumm_bytes += str_info->curr_bytes;
463 } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
464 retval = -EINVAL;
465 mutex_lock(&sst_drv_ctx->stream_lock);
466 sst_clean_stream(str_info);
467 mutex_unlock(&sst_drv_ctx->stream_lock);
468 }
469 if (str_info->data_blk.on == true) {
470 str_info->data_blk.condition = true;
471 str_info->data_blk.ret_code = retval;
472 wake_up(&sst_drv_ctx->wait_queue);
473 }
474 } else {
475 retval = -EBADRQC;
476 pr_err("SST ERR: BADQRC for stream\n");
477 }
478 return retval;
479}
480
481/**
482* sst_drain_stream - Send msg for draining stream
483* @str_id: stream ID
484*
485* This function is called by any function which wants to drain
486* a stream.
487*/
488int sst_drain_stream(int str_id)
489{
490 int retval = 0;
491 struct ipc_post *msg = NULL;
492 struct stream_info *str_info;
493
494 pr_debug("SST DBG:sst_drain_stream for %d\n", str_id);
495 retval = sst_validate_strid(str_id);
496 if (retval)
497 return retval;
498 str_info = &sst_drv_ctx->streams[str_id];
499
500 if (str_info->status != STREAM_RUNNING &&
501 str_info->status != STREAM_INIT &&
502 str_info->status != STREAM_PAUSED) {
503 pr_err("SST ERR: BADQRC for stream = %d\n",
504 str_info->status);
505 return -EBADRQC;
506 }
507
508 if (str_info->status == STREAM_INIT) {
509 if (sst_create_short_msg(&msg)) {
510 pr_err("SST ERR: mem allocation failed\n");
511 return -ENOMEM;
512 }
513 sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id);
514 spin_lock(&sst_drv_ctx->list_spin_lock);
515 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
516 spin_unlock(&sst_drv_ctx->list_spin_lock);
517 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
518 } else
519 str_info->need_draining = true;
520 str_info->data_blk.condition = false;
521 str_info->data_blk.ret_code = 0;
522 str_info->data_blk.on = true;
523 retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
524 str_info->need_draining = false;
525 return retval;
526}
527
528/**
529 * sst_free_stream - Frees a stream
530 * @str_id: stream ID
531 *
532 * This function is called by any function which wants to free
533 * a stream.
534 */
535int sst_free_stream(int str_id)
536{
537 int retval = 0;
538 struct ipc_post *msg = NULL;
539 struct stream_info *str_info;
540
541 pr_debug("SST DBG:sst_free_stream for %d\n", str_id);
542
543 retval = sst_validate_strid(str_id);
544 if (retval)
545 return retval;
546 str_info = &sst_drv_ctx->streams[str_id];
547
548 if (str_info->status != STREAM_UN_INIT) {
549 if (sst_create_short_msg(&msg)) {
550 pr_err("SST ERR: mem allocation failed\n");
551 return -ENOMEM;
552 }
553 sst_fill_header(&msg->header, IPC_IA_FREE_STREAM, 0, str_id);
554 spin_lock(&sst_drv_ctx->list_spin_lock);
555 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
556 spin_unlock(&sst_drv_ctx->list_spin_lock);
557 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
558 str_info->prev = str_info->status;
559 str_info->status = STREAM_UN_INIT;
560 if (str_info->data_blk.on == true) {
561 str_info->data_blk.condition = true;
562 str_info->data_blk.ret_code = 0;
563 wake_up(&sst_drv_ctx->wait_queue);
564 }
565 str_info->data_blk.on = true;
566 str_info->data_blk.condition = false;
567 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
568 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
569 pr_debug("wait for free returned %d\n", retval);
570 msleep(100);
571 mutex_lock(&sst_drv_ctx->stream_lock);
572 sst_clean_stream(str_info);
573 mutex_unlock(&sst_drv_ctx->stream_lock);
574 pr_debug("SST DBG:Stream freed\n");
575 } else {
576 retval = -EBADRQC;
577 pr_debug("SST DBG:BADQRC for stream\n");
578 }
579
580 return retval;
581}
582
583
diff --git a/drivers/staging/intel_sst/intel_sst_stream_encoded.c b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
new file mode 100644
index 00000000000..2be58c5cba0
--- /dev/null
+++ b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
@@ -0,0 +1,1273 @@
1/*
2 * intel_sst_stream.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This file contains the stream operations of SST driver
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/pci.h>
32#include <linux/syscalls.h>
33#include <linux/firmware.h>
34#include <linux/sched.h>
35#ifdef CONFIG_MRST_RAR_HANDLER
36#include <linux/rar_register.h>
37#include "../memrar/memrar.h"
38#endif
39#include "intel_sst_ioctl.h"
40#include "intel_sst.h"
41#include "intel_sst_fw_ipc.h"
42#include "intel_sst_common.h"
43/**
44* sst_get_stream_params - Send msg to query for stream parameters
45* @str_id: stream id for which the parameters are queried for
46* @get_params: out parameters to which the parameters are copied to
47*
48* This function is called when the stream parameters are queiried for
49*/
50int sst_get_stream_params(int str_id,
51 struct snd_sst_get_stream_params *get_params)
52{
53 int retval = 0;
54 struct ipc_post *msg = NULL;
55 struct stream_info *str_info;
56 struct snd_sst_fw_get_stream_params *fw_params;
57
58 pr_debug("get_stream for %d\n", str_id);
59 retval = sst_validate_strid(str_id);
60 if (retval)
61 return retval;
62
63 str_info = &sst_drv_ctx->streams[str_id];
64 if (str_info->status != STREAM_UN_INIT) {
65 if (str_info->ctrl_blk.on == true) {
66 pr_err("control path in use\n");
67 return -EINVAL;
68 }
69 if (sst_create_short_msg(&msg)) {
70 pr_err("message creation failed\n");
71 return -ENOMEM;
72 }
73 fw_params = kzalloc(sizeof(*fw_params), GFP_ATOMIC);
74 if (!fw_params) {
75 pr_err("mem allocation failed\n");
76 kfree(msg);
77 return -ENOMEM;
78 }
79
80 sst_fill_header(&msg->header, IPC_IA_GET_STREAM_PARAMS,
81 0, str_id);
82 str_info->ctrl_blk.condition = false;
83 str_info->ctrl_blk.ret_code = 0;
84 str_info->ctrl_blk.on = true;
85 str_info->ctrl_blk.data = (void *) fw_params;
86 spin_lock(&sst_drv_ctx->list_spin_lock);
87 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
88 spin_unlock(&sst_drv_ctx->list_spin_lock);
89 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
90 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
91 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
92 if (retval) {
93 get_params->codec_params.result = retval;
94 kfree(fw_params);
95 return -EIO;
96 }
97 memcpy(&get_params->pcm_params, &fw_params->pcm_params,
98 sizeof(fw_params->pcm_params));
99 memcpy(&get_params->codec_params.sparams,
100 &fw_params->codec_params,
101 sizeof(fw_params->codec_params));
102 get_params->codec_params.result = 0;
103 get_params->codec_params.stream_id = str_id;
104 get_params->codec_params.codec = str_info->codec;
105 get_params->codec_params.ops = str_info->ops;
106 get_params->codec_params.stream_type = str_info->str_type;
107 kfree(fw_params);
108 } else {
109 pr_debug("Stream is not in the init state\n");
110 }
111 return retval;
112}
113
114/**
115 * sst_set_stream_param - Send msg for setting stream parameters
116 *
117 * @str_id: stream id
118 * @str_param: stream params
119 *
120 * This function sets stream params during runtime
121 */
122int sst_set_stream_param(int str_id, struct snd_sst_params *str_param)
123{
124 int retval = 0;
125 struct ipc_post *msg = NULL;
126 struct stream_info *str_info;
127
128 BUG_ON(!str_param);
129 if (sst_drv_ctx->streams[str_id].ops != str_param->ops) {
130 pr_err("Invalid operation\n");
131 return -EINVAL;
132 }
133 retval = sst_validate_strid(str_id);
134 if (retval)
135 return retval;
136 pr_debug("set_stream for %d\n", str_id);
137 str_info = &sst_drv_ctx->streams[str_id];
138 if (sst_drv_ctx->streams[str_id].status == STREAM_INIT) {
139 if (str_info->ctrl_blk.on == true) {
140 pr_err("control path in use\n");
141 return -EAGAIN;
142 }
143 if (sst_create_large_msg(&msg))
144 return -ENOMEM;
145
146 sst_fill_header(&msg->header,
147 IPC_IA_SET_STREAM_PARAMS, 1, str_id);
148 str_info->ctrl_blk.condition = false;
149 str_info->ctrl_blk.ret_code = 0;
150 str_info->ctrl_blk.on = true;
151 msg->header.part.data = sizeof(u32) +
152 sizeof(str_param->sparams);
153 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
154 memcpy(msg->mailbox_data + sizeof(u32), &str_param->sparams,
155 sizeof(str_param->sparams));
156 spin_lock(&sst_drv_ctx->list_spin_lock);
157 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
158 spin_unlock(&sst_drv_ctx->list_spin_lock);
159 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
160 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
161 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
162 if (retval < 0) {
163 retval = -EIO;
164 sst_clean_stream(str_info);
165 }
166 } else {
167 retval = -EBADRQC;
168 pr_err("BADQRC for stream\n");
169 }
170 return retval;
171}
172
173/**
174* sst_get_vol - This function allows to get the premix gain or gain of a stream
175*
176* @get_vol: this is an output param through which the volume
177* structure is passed back to user
178*
179* This function is called when the premix gain or stream gain is queried for
180*/
181int sst_get_vol(struct snd_sst_vol *get_vol)
182{
183 int retval = 0;
184 struct ipc_post *msg = NULL;
185 struct snd_sst_vol *fw_get_vol;
186 int str_id = get_vol->stream_id;
187
188 pr_debug("get vol called\n");
189
190 if (sst_create_short_msg(&msg))
191 return -ENOMEM;
192
193 sst_fill_header(&msg->header,
194 IPC_IA_GET_STREAM_VOL, 0, str_id);
195 sst_drv_ctx->vol_info_blk.condition = false;
196 sst_drv_ctx->vol_info_blk.ret_code = 0;
197 sst_drv_ctx->vol_info_blk.on = true;
198 fw_get_vol = kzalloc(sizeof(*fw_get_vol), GFP_ATOMIC);
199 if (!fw_get_vol) {
200 pr_err("mem allocation failed\n");
201 kfree(msg);
202 return -ENOMEM;
203 }
204 sst_drv_ctx->vol_info_blk.data = (void *)fw_get_vol;
205 spin_lock(&sst_drv_ctx->list_spin_lock);
206 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
207 spin_unlock(&sst_drv_ctx->list_spin_lock);
208 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
209 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
210 &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
211 if (retval)
212 retval = -EIO;
213 else {
214 pr_debug("stream id %d\n", fw_get_vol->stream_id);
215 pr_debug("volume %d\n", fw_get_vol->volume);
216 pr_debug("ramp duration %d\n", fw_get_vol->ramp_duration);
217 pr_debug("ramp_type %d\n", fw_get_vol->ramp_type);
218 memcpy(get_vol, fw_get_vol, sizeof(*fw_get_vol));
219 }
220 return retval;
221}
222
223/**
224* sst_set_vol - This function allows to set the premix gain or gain of a stream
225*
226* @set_vol: this holds the volume structure that needs to be set
227*
228* This function is called when premix gain or stream gain is requested to be set
229*/
230int sst_set_vol(struct snd_sst_vol *set_vol)
231{
232
233 int retval = 0;
234 struct ipc_post *msg = NULL;
235
236 pr_debug("set vol called\n");
237
238 if (sst_create_large_msg(&msg)) {
239 pr_err("message creation failed\n");
240 return -ENOMEM;
241 }
242 sst_fill_header(&msg->header, IPC_IA_SET_STREAM_VOL, 1,
243 set_vol->stream_id);
244
245 msg->header.part.data = sizeof(u32) + sizeof(*set_vol);
246 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
247 memcpy(msg->mailbox_data + sizeof(u32), set_vol, sizeof(*set_vol));
248 sst_drv_ctx->vol_info_blk.condition = false;
249 sst_drv_ctx->vol_info_blk.ret_code = 0;
250 sst_drv_ctx->vol_info_blk.on = true;
251 sst_drv_ctx->vol_info_blk.data = set_vol;
252 spin_lock(&sst_drv_ctx->list_spin_lock);
253 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
254 spin_unlock(&sst_drv_ctx->list_spin_lock);
255 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
256 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
257 &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
258 if (retval) {
259 pr_err("error in set_vol = %d\n", retval);
260 retval = -EIO;
261 }
262 return retval;
263}
264
265/**
266* sst_set_mute - This function sets premix mute or soft mute of a stream
267*
268* @set_mute: this holds the mute structure that needs to be set
269*
270* This function is called when premix mute or stream mute requested to be set
271*/
272int sst_set_mute(struct snd_sst_mute *set_mute)
273{
274
275 int retval = 0;
276 struct ipc_post *msg = NULL;
277
278 pr_debug("set mute called\n");
279
280 if (sst_create_large_msg(&msg)) {
281 pr_err("message creation failed\n");
282 return -ENOMEM;
283 }
284 sst_fill_header(&msg->header, IPC_IA_SET_STREAM_MUTE, 1,
285 set_mute->stream_id);
286 sst_drv_ctx->mute_info_blk.condition = false;
287 sst_drv_ctx->mute_info_blk.ret_code = 0;
288 sst_drv_ctx->mute_info_blk.on = true;
289 sst_drv_ctx->mute_info_blk.data = set_mute;
290
291 msg->header.part.data = sizeof(u32) + sizeof(*set_mute);
292 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
293 memcpy(msg->mailbox_data + sizeof(u32), set_mute,
294 sizeof(*set_mute));
295 spin_lock(&sst_drv_ctx->list_spin_lock);
296 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
297 spin_unlock(&sst_drv_ctx->list_spin_lock);
298 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
299 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
300 &sst_drv_ctx->mute_info_blk, SST_BLOCK_TIMEOUT);
301 if (retval) {
302 pr_err("error in set_mute = %d\n", retval);
303 retval = -EIO;
304 }
305 return retval;
306}
307
308int sst_prepare_target(struct snd_sst_slot_info *slot)
309{
310 if (slot->target_device == SND_SST_TARGET_PMIC
311 && slot->device_instance == 1) {
312 /*music mode*/
313 if (sst_drv_ctx->pmic_port_instance == 0)
314 sst_drv_ctx->scard_ops->set_voice_port(
315 DEACTIVATE);
316 } else if ((slot->target_device == SND_SST_TARGET_PMIC ||
317 slot->target_device == SND_SST_TARGET_MODEM) &&
318 slot->device_instance == 0) {
319 /*voip mode where pcm0 is active*/
320 if (sst_drv_ctx->pmic_port_instance == 1)
321 sst_drv_ctx->scard_ops->set_audio_port(
322 DEACTIVATE);
323 }
324 return 0;
325}
326
327int sst_activate_target(struct snd_sst_slot_info *slot)
328{
329 if (slot->target_device == SND_SST_TARGET_PMIC &&
330 slot->device_instance == 1) {
331 /*music mode*/
332 sst_drv_ctx->pmic_port_instance = 1;
333 sst_drv_ctx->scard_ops->set_audio_port(ACTIVATE);
334 sst_drv_ctx->scard_ops->set_pcm_audio_params(
335 slot->pcm_params.sfreq,
336 slot->pcm_params.pcm_wd_sz,
337 slot->pcm_params.num_chan);
338 if (sst_drv_ctx->pb_streams)
339 sst_drv_ctx->scard_ops->power_up_pmic_pb(1);
340 if (sst_drv_ctx->cp_streams)
341 sst_drv_ctx->scard_ops->power_up_pmic_cp(1);
342 } else if ((slot->target_device == SND_SST_TARGET_PMIC ||
343 slot->target_device == SND_SST_TARGET_MODEM) &&
344 slot->device_instance == 0) {
345 /*voip mode where pcm0 is active*/
346 sst_drv_ctx->pmic_port_instance = 0;
347 sst_drv_ctx->scard_ops->set_voice_port(
348 ACTIVATE);
349 sst_drv_ctx->scard_ops->power_up_pmic_pb(0);
350 /*sst_drv_ctx->scard_ops->power_up_pmic_cp(0);*/
351 }
352 return 0;
353}
354
355int sst_parse_target(struct snd_sst_slot_info *slot)
356{
357 int retval = 0;
358
359 if (slot->action == SND_SST_PORT_ACTIVATE &&
360 slot->device_type == SND_SST_DEVICE_PCM) {
361 retval = sst_activate_target(slot);
362 if (retval)
363 pr_err("SST_Activate_target_fail\n");
364 else
365 pr_err("SST_Activate_target_pass\n");
366 } else if (slot->action == SND_SST_PORT_PREPARE &&
367 slot->device_type == SND_SST_DEVICE_PCM) {
368 retval = sst_prepare_target(slot);
369 if (retval)
370 pr_err("SST_prepare_target_fail\n");
371 else
372 pr_err("SST_prepare_target_pass\n");
373 } else {
374 pr_err("slot_action : %d, device_type: %d\n",
375 slot->action, slot->device_type);
376 }
377 return retval;
378}
379
380int sst_send_target(struct snd_sst_target_device *target)
381{
382 int retval;
383 struct ipc_post *msg;
384
385 if (sst_create_large_msg(&msg)) {
386 pr_err("message creation failed\n");
387 return -ENOMEM;
388 }
389 sst_fill_header(&msg->header, IPC_IA_TARGET_DEV_SELECT, 1, 0);
390 sst_drv_ctx->tgt_dev_blk.condition = false;
391 sst_drv_ctx->tgt_dev_blk.ret_code = 0;
392 sst_drv_ctx->tgt_dev_blk.on = true;
393
394 msg->header.part.data = sizeof(u32) + sizeof(*target);
395 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
396 memcpy(msg->mailbox_data + sizeof(u32), target,
397 sizeof(*target));
398 spin_lock(&sst_drv_ctx->list_spin_lock);
399 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
400 spin_unlock(&sst_drv_ctx->list_spin_lock);
401 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
402 pr_debug("message sent- waiting\n");
403 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
404 &sst_drv_ctx->tgt_dev_blk, TARGET_DEV_BLOCK_TIMEOUT);
405 if (retval)
406 pr_err("target device ipc failed = 0x%x\n", retval);
407 return retval;
408
409}
410
411int sst_target_device_validate(struct snd_sst_target_device *target)
412{
413 int retval = 0;
414 int i;
415
416 for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
417 if (target->devices[i].device_type == SND_SST_DEVICE_PCM) {
418 /*pcm device, check params*/
419 if (target->devices[i].device_instance == 1) {
420 if ((target->devices[i].device_mode !=
421 SND_SST_DEV_MODE_PCM_MODE4_I2S) &&
422 (target->devices[i].device_mode !=
423 SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED)
424 && (target->devices[i].device_mode !=
425 SND_SST_DEV_MODE_PCM_MODE1))
426 goto err;
427 } else if (target->devices[i].device_instance == 0) {
428 if ((target->devices[i].device_mode !=
429 SND_SST_DEV_MODE_PCM_MODE2)
430 && (target->devices[i].device_mode !=
431 SND_SST_DEV_MODE_PCM_MODE4_I2S)
432 && (target->devices[i].device_mode !=
433 SND_SST_DEV_MODE_PCM_MODE1))
434 goto err;
435 if (target->devices[i].pcm_params.sfreq != 8000
436 || target->devices[i].pcm_params.num_chan != 1
437 || target->devices[i].pcm_params.pcm_wd_sz !=
438 16)
439 goto err;
440 } else {
441err:
442 pr_err("i/p params incorrect\n");
443 return -EINVAL;
444 }
445 }
446 }
447 return retval;
448}
449
450/**
451 * sst_target_device_select - This function sets the target device configurations
452 *
453 * @target: this parameter holds the configurations to be set
454 *
455 * This function is called when the user layer wants to change the target
456 * device's configurations
457 */
458
459int sst_target_device_select(struct snd_sst_target_device *target)
460{
461 int retval, i, prepare_count = 0;
462
463 pr_debug("Target Device Select\n");
464
465 if (target->device_route < 0 || target->device_route > 2) {
466 pr_err("device route is invalid\n");
467 return -EINVAL;
468 }
469
470 if (target->device_route != 0) {
471 pr_err("Unsupported config\n");
472 return -EIO;
473 }
474 retval = sst_target_device_validate(target);
475 if (retval)
476 return retval;
477
478 retval = sst_send_target(target);
479 if (retval)
480 return retval;
481 for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
482 if (target->devices[i].action == SND_SST_PORT_ACTIVATE) {
483 pr_debug("activate called in %d\n", i);
484 retval = sst_parse_target(&target->devices[i]);
485 if (retval)
486 return retval;
487 } else if (target->devices[i].action == SND_SST_PORT_PREPARE) {
488 pr_debug("PREPARE in %d, Forwarding\n", i);
489 retval = sst_parse_target(&target->devices[i]);
490 if (retval) {
491 pr_err("Parse Target fail %d\n", retval);
492 return retval;
493 }
494 pr_debug("Parse Target successful %d\n", retval);
495 if (target->devices[i].device_type ==
496 SND_SST_DEVICE_PCM)
497 prepare_count++;
498 }
499 }
500 if (target->devices[0].action == SND_SST_PORT_PREPARE &&
501 prepare_count == 0)
502 sst_drv_ctx->scard_ops->power_down_pmic();
503
504 return retval;
505}
506#ifdef CONFIG_MRST_RAR_HANDLER
507/*This function gets the physical address of the secure memory from the handle*/
508static inline int sst_get_RAR(struct RAR_buffer *buffers, int count)
509{
510 int retval = 0, rar_status = 0;
511
512 rar_status = rar_handle_to_bus(buffers, count);
513
514 if (count != rar_status) {
515 pr_err("The rar CALL Failed");
516 retval = -EIO;
517 }
518 if (buffers->info.type != RAR_TYPE_AUDIO) {
519 pr_err("Invalid RAR type\n");
520 return -EINVAL;
521 }
522 return retval;
523}
524
525#endif
526
527/* This function creates the scatter gather list to be sent to firmware to
528capture/playback data*/
529static int sst_create_sg_list(struct stream_info *stream,
530 struct sst_frame_info *sg_list)
531{
532 struct sst_stream_bufs *kbufs = NULL;
533#ifdef CONFIG_MRST_RAR_HANDLER
534 struct RAR_buffer rar_buffers;
535 int retval = 0;
536#endif
537 int i = 0;
538 list_for_each_entry(kbufs, &stream->bufs, node) {
539 if (kbufs->in_use == false) {
540#ifdef CONFIG_MRST_RAR_HANDLER
541 if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
542 pr_debug("DRM playback handling\n");
543 rar_buffers.info.handle = (__u32)kbufs->addr;
544 rar_buffers.info.size = kbufs->size;
545 pr_debug("rar handle 0x%x size=0x%x\n",
546 rar_buffers.info.handle,
547 rar_buffers.info.size);
548 retval = sst_get_RAR(&rar_buffers, 1);
549
550 if (retval)
551 return retval;
552 sg_list->addr[i].addr = rar_buffers.bus_address;
553 /* rar_buffers.info.size; */
554 sg_list->addr[i].size = (__u32)kbufs->size;
555 pr_debug("phyaddr[%d] 0x%x Size:0x%x\n"
556 , i, sg_list->addr[i].addr,
557 sg_list->addr[i].size);
558 }
559#endif
560 if (stream->ops != STREAM_OPS_PLAYBACK_DRM) {
561 sg_list->addr[i].addr =
562 virt_to_phys((void *)
563 kbufs->addr + kbufs->offset);
564 sg_list->addr[i].size = kbufs->size;
565 pr_debug("phyaddr[%d]:0x%x Size:0x%x\n"
566 , i , sg_list->addr[i].addr, kbufs->size);
567 }
568 stream->curr_bytes += sg_list->addr[i].size;
569 kbufs->in_use = true;
570 i++;
571 }
572 if (i >= MAX_NUM_SCATTER_BUFFERS)
573 break;
574 }
575
576 sg_list->num_entries = i;
577 pr_debug("sg list entries = %d\n", sg_list->num_entries);
578 return i;
579}
580
581
582/**
583 * sst_play_frame - Send msg for sending stream frames
584 *
585 * @str_id: ID of stream
586 *
587 * This function is called to send data to be played out
588 * to the firmware
589 */
590int sst_play_frame(int str_id)
591{
592 int i = 0, retval = 0;
593 struct ipc_post *msg = NULL;
594 struct sst_frame_info sg_list = {0};
595 struct sst_stream_bufs *kbufs = NULL, *_kbufs;
596 struct stream_info *stream;
597
598 pr_debug("play frame for %d\n", str_id);
599 retval = sst_validate_strid(str_id);
600 if (retval)
601 return retval;
602
603 stream = &sst_drv_ctx->streams[str_id];
604 /* clear prev sent buffers */
605 list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
606 if (kbufs->in_use == true) {
607 spin_lock(&stream->pcm_lock);
608 list_del(&kbufs->node);
609 spin_unlock(&stream->pcm_lock);
610 kfree(kbufs);
611 }
612 }
613 /* update bytes sent */
614 stream->cumm_bytes += stream->curr_bytes;
615 stream->curr_bytes = 0;
616 if (list_empty(&stream->bufs)) {
617 /* no user buffer available */
618 pr_debug("Null buffer stream status %d\n", stream->status);
619 stream->prev = stream->status;
620 stream->status = STREAM_INIT;
621 pr_debug("new stream status = %d\n", stream->status);
622 if (stream->need_draining == true) {
623 pr_debug("draining stream\n");
624 if (sst_create_short_msg(&msg)) {
625 pr_err("mem allocation failed\n");
626 return -ENOMEM;
627 }
628 sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM,
629 0, str_id);
630 spin_lock(&sst_drv_ctx->list_spin_lock);
631 list_add_tail(&msg->node,
632 &sst_drv_ctx->ipc_dispatch_list);
633 spin_unlock(&sst_drv_ctx->list_spin_lock);
634 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
635 } else if (stream->data_blk.on == true) {
636 pr_debug("user list empty.. wake\n");
637 /* unblock */
638 stream->data_blk.ret_code = 0;
639 stream->data_blk.condition = true;
640 stream->data_blk.on = false;
641 wake_up(&sst_drv_ctx->wait_queue);
642 }
643 return 0;
644 }
645
646 /* create list */
647 i = sst_create_sg_list(stream, &sg_list);
648
649 /* post msg */
650 if (sst_create_large_msg(&msg))
651 return -ENOMEM;
652
653 sst_fill_header(&msg->header, IPC_IA_PLAY_FRAMES, 1, str_id);
654 msg->header.part.data = sizeof(u32) + sizeof(sg_list);
655 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
656 memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
657 spin_lock(&sst_drv_ctx->list_spin_lock);
658 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
659 spin_unlock(&sst_drv_ctx->list_spin_lock);
660 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
661 return 0;
662
663}
664
665/**
666 * sst_capture_frame - Send msg for sending stream frames
667 *
668 * @str_id: ID of stream
669 *
670 * This function is called to capture data from the firmware
671 */
672int sst_capture_frame(int str_id)
673{
674 int i = 0, retval = 0;
675 struct ipc_post *msg = NULL;
676 struct sst_frame_info sg_list = {0};
677 struct sst_stream_bufs *kbufs = NULL, *_kbufs;
678 struct stream_info *stream;
679
680
681 pr_debug("capture frame for %d\n", str_id);
682 retval = sst_validate_strid(str_id);
683 if (retval)
684 return retval;
685 stream = &sst_drv_ctx->streams[str_id];
686 /* clear prev sent buffers */
687 list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
688 if (kbufs->in_use == true) {
689 list_del(&kbufs->node);
690 kfree(kbufs);
691 pr_debug("del node\n");
692 }
693 }
694 if (list_empty(&stream->bufs)) {
695 /* no user buffer available */
696 pr_debug("Null buffer!!!!stream status %d\n",
697 stream->status);
698 stream->prev = stream->status;
699 stream->status = STREAM_INIT;
700 pr_debug("new stream status = %d\n",
701 stream->status);
702 if (stream->data_blk.on == true) {
703 pr_debug("user list empty.. wake\n");
704 /* unblock */
705 stream->data_blk.ret_code = 0;
706 stream->data_blk.condition = true;
707 stream->data_blk.on = false;
708 wake_up(&sst_drv_ctx->wait_queue);
709
710 }
711 return 0;
712 }
713 /* create new sg list */
714 i = sst_create_sg_list(stream, &sg_list);
715
716 /* post msg */
717 if (sst_create_large_msg(&msg))
718 return -ENOMEM;
719
720 sst_fill_header(&msg->header, IPC_IA_CAPT_FRAMES, 1, str_id);
721 msg->header.part.data = sizeof(u32) + sizeof(sg_list);
722 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
723 memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
724 spin_lock(&sst_drv_ctx->list_spin_lock);
725 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
726 spin_unlock(&sst_drv_ctx->list_spin_lock);
727 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
728
729
730 /*update bytes recevied*/
731 stream->cumm_bytes += stream->curr_bytes;
732 stream->curr_bytes = 0;
733
734 pr_debug("Cum bytes = %d\n", stream->cumm_bytes);
735 return 0;
736}
737
738/*This function is used to calculate the minimum size of input buffers given*/
739static unsigned int calculate_min_size(struct snd_sst_buffs *bufs)
740{
741 int i, min_val = bufs->buff_entry[0].size;
742 for (i = 1 ; i < bufs->entries; i++) {
743 if (bufs->buff_entry[i].size < min_val)
744 min_val = bufs->buff_entry[i].size;
745 }
746 pr_debug("min_val = %d\n", min_val);
747 return min_val;
748}
749
750static unsigned int calculate_max_size(struct snd_sst_buffs *bufs)
751{
752 int i, max_val = bufs->buff_entry[0].size;
753 for (i = 1 ; i < bufs->entries; i++) {
754 if (bufs->buff_entry[i].size > max_val)
755 max_val = bufs->buff_entry[i].size;
756 }
757 pr_debug("max_val = %d\n", max_val);
758 return max_val;
759}
760
761/*This function is used to allocate input and output buffers to be sent to
762the firmware that will take encoded data and return decoded data*/
763static int sst_allocate_decode_buf(struct stream_info *str_info,
764 struct snd_sst_dbufs *dbufs,
765 unsigned int cum_input_given,
766 unsigned int cum_output_given)
767{
768#ifdef CONFIG_MRST_RAR_HANDLER
769 if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
770
771 if (dbufs->ibufs->type == SST_BUF_RAR &&
772 dbufs->obufs->type == SST_BUF_RAR) {
773 if (dbufs->ibufs->entries == dbufs->obufs->entries)
774 return 0;
775 else {
776 pr_err("RAR entries dont match\n");
777 return -EINVAL;
778 }
779 } else
780 str_info->decode_osize = cum_output_given;
781 return 0;
782
783 }
784#endif
785 if (!str_info->decode_ibuf) {
786 pr_debug("no i/p buffers, trying full size\n");
787 str_info->decode_isize = cum_input_given;
788 str_info->decode_ibuf = kzalloc(str_info->decode_isize,
789 GFP_KERNEL);
790 str_info->idecode_alloc = str_info->decode_isize;
791 }
792 if (!str_info->decode_ibuf) {
793 pr_debug("buff alloc failed, try max size\n");
794 str_info->decode_isize = calculate_max_size(dbufs->ibufs);
795 str_info->decode_ibuf = kzalloc(
796 str_info->decode_isize, GFP_KERNEL);
797 str_info->idecode_alloc = str_info->decode_isize;
798 }
799 if (!str_info->decode_ibuf) {
800 pr_debug("buff alloc failed, try min size\n");
801 str_info->decode_isize = calculate_min_size(dbufs->ibufs);
802 str_info->decode_ibuf = kzalloc(str_info->decode_isize,
803 GFP_KERNEL);
804 if (!str_info->decode_ibuf) {
805 pr_err("mem allocation failed\n");
806 return -ENOMEM;
807 }
808 str_info->idecode_alloc = str_info->decode_isize;
809 }
810 str_info->decode_osize = cum_output_given;
811 if (str_info->decode_osize > sst_drv_ctx->mmap_len)
812 str_info->decode_osize = sst_drv_ctx->mmap_len;
813 return 0;
814}
815
816/*This function is used to send the message to firmware to decode the data*/
817static int sst_send_decode_mess(int str_id, struct stream_info *str_info,
818 struct snd_sst_decode_info *dec_info)
819{
820 struct ipc_post *msg = NULL;
821 int retval = 0;
822
823 pr_debug("SST DBG:sst_set_mute:called\n");
824
825 if (str_info->decode_ibuf_type == SST_BUF_RAR) {
826#ifdef CONFIG_MRST_RAR_HANDLER
827 dec_info->frames_in.addr[0].addr =
828 (unsigned long)str_info->decode_ibuf;
829 dec_info->frames_in.addr[0].size =
830 str_info->decode_isize;
831#endif
832
833 } else {
834 dec_info->frames_in.addr[0].addr = virt_to_phys((void *)
835 str_info->decode_ibuf);
836 dec_info->frames_in.addr[0].size = str_info->decode_isize;
837 }
838
839
840 if (str_info->decode_obuf_type == SST_BUF_RAR) {
841#ifdef CONFIG_MRST_RAR_HANDLER
842 dec_info->frames_out.addr[0].addr =
843 (unsigned long)str_info->decode_obuf;
844 dec_info->frames_out.addr[0].size = str_info->decode_osize;
845#endif
846
847 } else {
848 dec_info->frames_out.addr[0].addr = virt_to_phys((void *)
849 str_info->decode_obuf) ;
850 dec_info->frames_out.addr[0].size = str_info->decode_osize;
851 }
852
853 dec_info->frames_in.num_entries = 1;
854 dec_info->frames_out.num_entries = 1;
855 dec_info->frames_in.rsrvd = 0;
856 dec_info->frames_out.rsrvd = 0;
857 dec_info->input_bytes_consumed = 0;
858 dec_info->output_bytes_produced = 0;
859 if (sst_create_large_msg(&msg)) {
860 pr_err("message creation failed\n");
861 return -ENOMEM;
862 }
863
864 sst_fill_header(&msg->header, IPC_IA_DECODE_FRAMES, 1, str_id);
865 msg->header.part.data = sizeof(u32) + sizeof(*dec_info);
866 memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
867 memcpy(msg->mailbox_data + sizeof(u32), dec_info,
868 sizeof(*dec_info));
869 spin_lock(&sst_drv_ctx->list_spin_lock);
870 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
871 spin_unlock(&sst_drv_ctx->list_spin_lock);
872 str_info->data_blk.condition = false;
873 str_info->data_blk.ret_code = 0;
874 str_info->data_blk.on = true;
875 str_info->data_blk.data = dec_info;
876 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
877 retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
878 return retval;
879}
880
881#ifdef CONFIG_MRST_RAR_HANDLER
882static int sst_prepare_input_buffers_rar(struct stream_info *str_info,
883 struct snd_sst_dbufs *dbufs,
884 int *input_index, int *in_copied,
885 int *input_index_valid_size, int *new_entry_flag)
886{
887 int retval = 0, i;
888
889 if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
890 struct RAR_buffer rar_buffers;
891 __u32 info;
892 retval = copy_from_user((void *) &info,
893 dbufs->ibufs->buff_entry[i].buffer,
894 sizeof(__u32));
895 if (retval) {
896 pr_err("cpy from user fail\n");
897 return -EAGAIN;
898 }
899 rar_buffers.info.type = dbufs->ibufs->type;
900 rar_buffers.info.size = dbufs->ibufs->buff_entry[i].size;
901 rar_buffers.info.handle = info;
902 pr_debug("rar in DnR(input buffer function)=0x%x size=0x%x",
903 rar_buffers.info.handle,
904 rar_buffers.info.size);
905 retval = sst_get_RAR(&rar_buffers, 1);
906 if (retval) {
907 pr_debug("SST ERR: RAR API failed\n");
908 return retval;
909 }
910 str_info->decode_ibuf =
911 (void *) ((unsigned long) rar_buffers.bus_address);
912 pr_debug("RAR buf addr in DnR (input buffer function)0x%lu",
913 (unsigned long) str_info->decode_ibuf);
914 pr_debug("rar in DnR decode function/output b_add rar =0x%lu",
915 (unsigned long) rar_buffers.bus_address);
916 *input_index = i + 1;
917 str_info->decode_isize = dbufs->ibufs->buff_entry[i].size;
918 str_info->decode_ibuf_type = dbufs->ibufs->type;
919 *in_copied = str_info->decode_isize;
920 }
921 return retval;
922}
923#endif
924/*This function is used to prepare the kernel input buffers with contents
925before sending for decode*/
926static int sst_prepare_input_buffers(struct stream_info *str_info,
927 struct snd_sst_dbufs *dbufs,
928 int *input_index, int *in_copied,
929 int *input_index_valid_size, int *new_entry_flag)
930{
931 int i, cpy_size, retval = 0;
932
933 pr_debug("input_index = %d, input entries = %d\n",
934 *input_index, dbufs->ibufs->entries);
935 for (i = *input_index; i < dbufs->ibufs->entries; i++) {
936#ifdef CONFIG_MRST_RAR_HANDLER
937 retval = sst_prepare_input_buffers_rar(str_info,
938 dbufs, input_index, in_copied,
939 input_index_valid_size, new_entry_flag);
940 if (retval) {
941 pr_err("In prepare input buffers for RAR\n");
942 return -EIO;
943 }
944#endif
945 *input_index = i;
946 if (*input_index_valid_size == 0)
947 *input_index_valid_size =
948 dbufs->ibufs->buff_entry[i].size;
949 pr_debug("inout addr = %p, size = %d\n",
950 dbufs->ibufs->buff_entry[i].buffer,
951 *input_index_valid_size);
952 pr_debug("decode_isize = %d, in_copied %d\n",
953 str_info->decode_isize, *in_copied);
954 if (*input_index_valid_size <=
955 (str_info->decode_isize - *in_copied))
956 cpy_size = *input_index_valid_size;
957 else
958 cpy_size = str_info->decode_isize - *in_copied;
959
960 pr_debug("cpy size = %d\n", cpy_size);
961 if (!dbufs->ibufs->buff_entry[i].buffer) {
962 pr_err("i/p buffer is null\n");
963 return -EINVAL;
964 }
965 pr_debug("Try copy To %p, From %p, size %d\n",
966 str_info->decode_ibuf + *in_copied,
967 dbufs->ibufs->buff_entry[i].buffer, cpy_size);
968
969 retval =
970 copy_from_user((void *)(str_info->decode_ibuf + *in_copied),
971 (void *) dbufs->ibufs->buff_entry[i].buffer,
972 cpy_size);
973 if (retval) {
974 pr_err("copy from user failed\n");
975 return -EIO;
976 }
977 *in_copied += cpy_size;
978 *input_index_valid_size -= cpy_size;
979 pr_debug("in buff size = %d, in_copied = %d\n",
980 *input_index_valid_size, *in_copied);
981 if (*input_index_valid_size != 0) {
982 pr_debug("more input buffers left\n");
983 dbufs->ibufs->buff_entry[i].buffer += cpy_size;
984 break;
985 }
986 if (*in_copied == str_info->decode_isize &&
987 *input_index_valid_size == 0 &&
988 (i+1) <= dbufs->ibufs->entries) {
989 pr_debug("all input buffers copied\n");
990 *new_entry_flag = true;
991 *input_index = i + 1;
992 break;
993 }
994 }
995 return retval;
996}
997
998/* This function is used to copy the decoded data from kernel buffers to
999the user output buffers with contents after decode*/
1000static int sst_prepare_output_buffers(struct stream_info *str_info,
1001 struct snd_sst_dbufs *dbufs,
1002 int *output_index, int output_size,
1003 int *out_copied)
1004
1005{
1006 int i, cpy_size, retval = 0;
1007 pr_debug("output_index = %d, output entries = %d\n",
1008 *output_index,
1009 dbufs->obufs->entries);
1010 for (i = *output_index; i < dbufs->obufs->entries; i++) {
1011 *output_index = i;
1012 pr_debug("output addr = %p, size = %d\n",
1013 dbufs->obufs->buff_entry[i].buffer,
1014 dbufs->obufs->buff_entry[i].size);
1015 pr_debug("output_size = %d, out_copied = %d\n",
1016 output_size, *out_copied);
1017 if (dbufs->obufs->buff_entry[i].size <
1018 (output_size - *out_copied))
1019 cpy_size = dbufs->obufs->buff_entry[i].size;
1020 else
1021 cpy_size = output_size - *out_copied;
1022 pr_debug("cpy size = %d\n", cpy_size);
1023 pr_debug("Try copy To: %p, From %p, size %d\n",
1024 dbufs->obufs->buff_entry[i].buffer,
1025 sst_drv_ctx->mmap_mem + *out_copied,
1026 cpy_size);
1027 retval = copy_to_user(dbufs->obufs->buff_entry[i].buffer,
1028 sst_drv_ctx->mmap_mem + *out_copied,
1029 cpy_size);
1030 if (retval) {
1031 pr_err("copy to user failed\n");
1032 return -EIO;
1033 } else
1034 pr_debug("copy to user passed\n");
1035 *out_copied += cpy_size;
1036 dbufs->obufs->buff_entry[i].size -= cpy_size;
1037 pr_debug("o/p buff size %d, out_copied %d\n",
1038 dbufs->obufs->buff_entry[i].size, *out_copied);
1039 if (dbufs->obufs->buff_entry[i].size != 0) {
1040 *output_index = i;
1041 dbufs->obufs->buff_entry[i].buffer += cpy_size;
1042 break;
1043 } else if (*out_copied == output_size) {
1044 *output_index = i + 1;
1045 break;
1046 }
1047 }
1048 return retval;
1049}
1050
1051/**
1052 * sst_decode - Send msg for decoding frames
1053 *
1054 * @str_id: ID of stream
1055 * @dbufs: param that holds the user input and output buffers and size
1056 *
1057 * This function is called to decode data from the firmware
1058 */
1059int sst_decode(int str_id, struct snd_sst_dbufs *dbufs)
1060{
1061 int retval = 0, i;
1062 unsigned long long total_input = 0 , total_output = 0;
1063 unsigned int cum_input_given = 0 , cum_output_given = 0;
1064 int copy_in_done = false, copy_out_done = false;
1065 int input_index = 0, output_index = 0;
1066 int input_index_valid_size = 0;
1067 int in_copied, out_copied;
1068 int new_entry_flag;
1069 u64 output_size;
1070 struct stream_info *str_info;
1071 struct snd_sst_decode_info dec_info;
1072 unsigned long long input_bytes, output_bytes;
1073
1074 sst_drv_ctx->scard_ops->power_down_pmic();
1075 pr_debug("Powering_down_PMIC...\n");
1076
1077 retval = sst_validate_strid(str_id);
1078 if (retval)
1079 return retval;
1080
1081 str_info = &sst_drv_ctx->streams[str_id];
1082 if (str_info->status != STREAM_INIT) {
1083 pr_err("invalid stream state = %d\n",
1084 str_info->status);
1085 return -EINVAL;
1086 }
1087
1088 str_info->prev = str_info->status;
1089 str_info->status = STREAM_DECODE;
1090
1091 for (i = 0; i < dbufs->ibufs->entries; i++)
1092 cum_input_given += dbufs->ibufs->buff_entry[i].size;
1093 for (i = 0; i < dbufs->obufs->entries; i++)
1094 cum_output_given += dbufs->obufs->buff_entry[i].size;
1095
1096 /* input and output buffer allocation */
1097 retval = sst_allocate_decode_buf(str_info, dbufs,
1098 cum_input_given, cum_output_given);
1099 if (retval) {
1100 pr_err("mem allocation failed, abort!!!\n");
1101 retval = -ENOMEM;
1102 goto finish;
1103 }
1104
1105 str_info->decode_isize = str_info->idecode_alloc;
1106 str_info->decode_ibuf_type = dbufs->ibufs->type;
1107 str_info->decode_obuf_type = dbufs->obufs->type;
1108
1109 while ((copy_out_done == false) && (copy_in_done == false)) {
1110 in_copied = 0;
1111 new_entry_flag = false;
1112 retval = sst_prepare_input_buffers(str_info,\
1113 dbufs, &input_index, &in_copied,
1114 &input_index_valid_size, &new_entry_flag);
1115 if (retval) {
1116 pr_err("prepare in buffers failed\n");
1117 goto finish;
1118 }
1119
1120 if (str_info->ops != STREAM_OPS_PLAYBACK_DRM)
1121 str_info->decode_obuf = sst_drv_ctx->mmap_mem;
1122
1123#ifdef CONFIG_MRST_RAR_HANDLER
1124 else {
1125 if (dbufs->obufs->type == SST_BUF_RAR) {
1126 struct RAR_buffer rar_buffers;
1127 __u32 info;
1128
1129 pr_debug("DRM");
1130 retval = copy_from_user((void *) &info,
1131 dbufs->obufs->
1132 buff_entry[output_index].buffer,
1133 sizeof(__u32));
1134
1135 rar_buffers.info.size = dbufs->obufs->
1136 buff_entry[output_index].size;
1137 rar_buffers.info.handle = info;
1138 retval = sst_get_RAR(&rar_buffers, 1);
1139 if (retval)
1140 return retval;
1141
1142 str_info->decode_obuf = (void *)((unsigned long)
1143 rar_buffers.bus_address);
1144 str_info->decode_osize = dbufs->obufs->
1145 buff_entry[output_index].size;
1146 str_info->decode_obuf_type = dbufs->obufs->type;
1147 pr_debug("DRM handling\n");
1148 pr_debug("o/p_add=0x%lu Size=0x%x\n",
1149 (unsigned long) str_info->decode_obuf,
1150 str_info->decode_osize);
1151 } else {
1152 str_info->decode_obuf = sst_drv_ctx->mmap_mem;
1153 str_info->decode_osize = dbufs->obufs->
1154 buff_entry[output_index].size;
1155
1156 }
1157 }
1158#endif
1159 if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
1160 if (str_info->decode_isize > in_copied) {
1161 str_info->decode_isize = in_copied;
1162 pr_debug("i/p size = %d\n",
1163 str_info->decode_isize);
1164 }
1165 }
1166
1167
1168 retval = sst_send_decode_mess(str_id, str_info, &dec_info);
1169 if (retval || dec_info.input_bytes_consumed == 0) {
1170 pr_err("SST ERR: mess failed or no input consumed\n");
1171 goto finish;
1172 }
1173 input_bytes = dec_info.input_bytes_consumed;
1174 output_bytes = dec_info.output_bytes_produced;
1175
1176 pr_debug("in_copied=%d, con=%lld, prod=%lld\n",
1177 in_copied, input_bytes, output_bytes);
1178 if (dbufs->obufs->type == SST_BUF_RAR) {
1179 output_index += 1;
1180 if (output_index == dbufs->obufs->entries) {
1181 copy_in_done = true;
1182 pr_debug("all i/p cpy done\n");
1183 }
1184 total_output += output_bytes;
1185 } else {
1186 out_copied = 0;
1187 output_size = output_bytes;
1188 retval = sst_prepare_output_buffers(str_info, dbufs,
1189 &output_index, output_size, &out_copied);
1190 if (retval) {
1191 pr_err("prep out buff fail\n");
1192 goto finish;
1193 }
1194 if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
1195 if (in_copied != input_bytes) {
1196 int bytes_left = in_copied -
1197 input_bytes;
1198 pr_debug("bytes %d\n",
1199 bytes_left);
1200 if (new_entry_flag == true)
1201 input_index--;
1202 while (bytes_left) {
1203 struct snd_sst_buffs *ibufs;
1204 struct snd_sst_buff_entry
1205 *buff_entry;
1206 unsigned int size_sent;
1207
1208 ibufs = dbufs->ibufs;
1209 buff_entry =
1210 &ibufs->buff_entry[input_index];
1211 size_sent = buff_entry->size -\
1212 input_index_valid_size;
1213 if (bytes_left == size_sent) {
1214 bytes_left = 0;
1215 } else if (bytes_left <
1216 size_sent) {
1217 buff_entry->buffer +=
1218 (size_sent -
1219 bytes_left);
1220 buff_entry->size -=
1221 (size_sent -
1222 bytes_left);
1223 bytes_left = 0;
1224 } else {
1225 bytes_left -= size_sent;
1226 input_index--;
1227 input_index_valid_size =
1228 0;
1229 }
1230 }
1231
1232 }
1233 }
1234
1235 total_output += out_copied;
1236 if (str_info->decode_osize != out_copied) {
1237 str_info->decode_osize -= out_copied;
1238 pr_debug("output size modified = %d\n",
1239 str_info->decode_osize);
1240 }
1241 }
1242 total_input += input_bytes;
1243
1244 if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
1245 if (total_input == cum_input_given)
1246 copy_in_done = true;
1247 copy_out_done = true;
1248
1249 } else {
1250 if (total_output == cum_output_given) {
1251 copy_out_done = true;
1252 pr_debug("all o/p cpy done\n");
1253 }
1254
1255 if (total_input == cum_input_given) {
1256 copy_in_done = true;
1257 pr_debug("all i/p cpy done\n");
1258 }
1259 }
1260
1261 pr_debug("copy_out = %d, copy_in = %d\n",
1262 copy_out_done, copy_in_done);
1263 }
1264
1265finish:
1266 dbufs->input_bytes_consumed = total_input;
1267 dbufs->output_bytes_produced = total_output;
1268 str_info->status = str_info->prev;
1269 str_info->prev = STREAM_DECODE;
1270 kfree(str_info->decode_ibuf);
1271 str_info->decode_ibuf = NULL;
1272 return retval;
1273}
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
new file mode 100644
index 00000000000..25656ad2802
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -0,0 +1,1021 @@
1/*
2 * intelmid.c - 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 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 * ALSA driver for Intel MID sound card chipset
26 */
27
28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
30#include <linux/slab.h>
31#include <linux/io.h>
32#include <linux/platform_device.h>
33#include <linux/interrupt.h>
34#include <linux/sched.h>
35#include <linux/firmware.h>
36#include <linux/input.h>
37#include <sound/control.h>
38#include <asm/mrst.h>
39#include <sound/pcm.h>
40#include <sound/jack.h>
41#include <sound/pcm_params.h>
42#include <sound/initval.h>
43#include <linux/gpio.h>
44#include "intel_sst.h"
45#include "intel_sst_ioctl.h"
46#include "intel_sst_fw_ipc.h"
47#include "intel_sst_common.h"
48#include "intelmid_snd_control.h"
49#include "intelmid_adc_control.h"
50#include "intelmid.h"
51
52MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
53MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
54MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
55MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
56MODULE_DESCRIPTION("Intel MAD Sound card driver");
57MODULE_LICENSE("GPL v2");
58MODULE_SUPPORTED_DEVICE("{Intel,Intel_MAD}");
59
60
61static int card_index = SNDRV_DEFAULT_IDX1;/* Index 0-MAX */
62static char *card_id = SNDRV_DEFAULT_STR1; /* ID for this card */
63
64module_param(card_index, int, 0444);
65MODULE_PARM_DESC(card_index, "Index value for INTELMAD soundcard.");
66module_param(card_id, charp, 0444);
67MODULE_PARM_DESC(card_id, "ID string for INTELMAD soundcard.");
68
69int sst_card_vendor_id;
70int intelmid_audio_interrupt_enable;/*checkpatch fix*/
71struct snd_intelmad *intelmad_drv;
72
73#define INFO(_cpu_id, _irq_cache, _size) \
74 ((kernel_ulong_t)&(struct snd_intelmad_probe_info) { \
75 .cpu_id = (_cpu_id), \
76 .irq_cache = (_irq_cache), \
77 .size = (_size), \
78 })
79/* Data path functionalities */
80static struct snd_pcm_hardware snd_intelmad_stream = {
81 .info = (SNDRV_PCM_INFO_INTERLEAVED |
82 SNDRV_PCM_INFO_DOUBLE |
83 SNDRV_PCM_INFO_PAUSE |
84 SNDRV_PCM_INFO_RESUME |
85 SNDRV_PCM_INFO_MMAP|
86 SNDRV_PCM_INFO_MMAP_VALID |
87 SNDRV_PCM_INFO_BLOCK_TRANSFER |
88 SNDRV_PCM_INFO_SYNC_START),
89 .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
90 SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
91 SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
92 .rates = (SNDRV_PCM_RATE_8000|
93 SNDRV_PCM_RATE_44100 |
94 SNDRV_PCM_RATE_48000),
95 .rate_min = MIN_RATE,
96
97 .rate_max = MAX_RATE,
98 .channels_min = MIN_CHANNEL,
99 .channels_max = MAX_CHANNEL_AMIC,
100 .buffer_bytes_max = MAX_BUFFER,
101 .period_bytes_min = MIN_PERIOD_BYTES,
102 .period_bytes_max = MAX_PERIOD_BYTES,
103 .periods_min = MIN_PERIODS,
104 .periods_max = MAX_PERIODS,
105 .fifo_size = FIFO_SIZE,
106};
107
108
109/**
110 * snd_intelmad_pcm_trigger - stream activities are handled here
111 *
112 * @substream:substream for which the stream function is called
113 * @cmd:the stream commamd that requested from upper layer
114 *
115 * This function is called whenever an a stream activity is invoked
116 */
117static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream,
118 int cmd)
119{
120 int ret_val = 0, str_id;
121 struct snd_intelmad *intelmaddata;
122 struct mad_stream_pvt *stream;
123 struct intel_sst_pcm_control *sst_ops;
124
125 WARN_ON(!substream);
126
127 intelmaddata = snd_pcm_substream_chip(substream);
128 stream = substream->runtime->private_data;
129
130 WARN_ON(!intelmaddata->sstdrv_ops);
131 WARN_ON(!intelmaddata->sstdrv_ops->scard_ops);
132 sst_ops = intelmaddata->sstdrv_ops->pcm_control;
133 str_id = stream->stream_info.str_id;
134
135 switch (cmd) {
136 case SNDRV_PCM_TRIGGER_START:
137 pr_debug("Trigger Start\n");
138 ret_val = sst_ops->device_control(SST_SND_START, &str_id);
139 if (ret_val)
140 return ret_val;
141 stream->stream_status = RUNNING;
142 stream->substream = substream;
143 break;
144 case SNDRV_PCM_TRIGGER_STOP:
145 pr_debug("in stop\n");
146 ret_val = sst_ops->device_control(SST_SND_DROP, &str_id);
147 if (ret_val)
148 return ret_val;
149 stream->stream_status = DROPPED;
150 break;
151 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
152 pr_debug("in pause\n");
153 ret_val = sst_ops->device_control(SST_SND_PAUSE, &str_id);
154 if (ret_val)
155 return ret_val;
156 stream->stream_status = PAUSED;
157 break;
158 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
159 pr_debug("in pause release\n");
160 ret_val = sst_ops->device_control(SST_SND_RESUME, &str_id);
161 if (ret_val)
162 return ret_val;
163 stream->stream_status = RUNNING;
164 break;
165 default:
166 return -EINVAL;
167 }
168 return ret_val;
169}
170
171/**
172* snd_intelmad_pcm_prepare- internal preparation before starting a stream
173*
174* @substream: substream for which the function is called
175*
176* This function is called when a stream is started for internal preparation.
177*/
178static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream)
179{
180 struct mad_stream_pvt *stream;
181 int ret_val = 0;
182 struct snd_intelmad *intelmaddata;
183
184 pr_debug("pcm_prepare called\n");
185
186 WARN_ON(!substream);
187 stream = substream->runtime->private_data;
188 intelmaddata = snd_pcm_substream_chip(substream);
189 pr_debug("pb cnt = %d cap cnt = %d\n",\
190 intelmaddata->playback_cnt,
191 intelmaddata->capture_cnt);
192
193 if (stream->stream_info.str_id) {
194 pr_debug("Prepare called for already set stream\n");
195 ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
196 SST_SND_DROP, &stream->stream_info.str_id);
197 return ret_val;
198 }
199
200 ret_val = snd_intelmad_alloc_stream(substream);
201 if (ret_val < 0)
202 return ret_val;
203 stream->dbg_cum_bytes = 0;
204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
205 intelmaddata->playback_cnt++;
206 else
207 intelmaddata->capture_cnt++;
208 /* return back the stream id */
209 snprintf(substream->pcm->id, sizeof(substream->pcm->id),
210 "%d", stream->stream_info.str_id);
211 pr_debug("stream id to user = %s\n",
212 substream->pcm->id);
213
214 ret_val = snd_intelmad_init_stream(substream);
215 if (ret_val)
216 return ret_val;
217 substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
218 return ret_val;
219}
220
221static int snd_intelmad_hw_params(struct snd_pcm_substream *substream,
222 struct snd_pcm_hw_params *hw_params)
223{
224 int ret_val;
225
226 pr_debug("snd_intelmad_hw_params called\n");
227 ret_val = snd_pcm_lib_malloc_pages(substream,
228 params_buffer_bytes(hw_params));
229 memset(substream->runtime->dma_area, 0,
230 params_buffer_bytes(hw_params));
231
232 return ret_val;
233}
234
235static int snd_intelmad_hw_free(struct snd_pcm_substream *substream)
236{
237 pr_debug("snd_intelmad_hw_free called\n");
238 return snd_pcm_lib_free_pages(substream);
239}
240
241/**
242 * snd_intelmad_pcm_pointer- to send the current buffer pointer processed by hw
243 *
244 * @substream: substream for which the function is called
245 *
246 * This function is called by ALSA framework to get the current hw buffer ptr
247 * when a period is elapsed
248 */
249static snd_pcm_uframes_t snd_intelmad_pcm_pointer
250 (struct snd_pcm_substream *substream)
251{
252 /* struct snd_pcm_runtime *runtime = substream->runtime; */
253 struct mad_stream_pvt *stream;
254 struct snd_intelmad *intelmaddata;
255 int ret_val;
256
257 WARN_ON(!substream);
258
259 intelmaddata = snd_pcm_substream_chip(substream);
260 stream = substream->runtime->private_data;
261 if (stream->stream_status == INIT)
262 return 0;
263
264 ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
265 SST_SND_BUFFER_POINTER, &stream->stream_info);
266 if (ret_val) {
267 pr_err("error code = 0x%x\n", ret_val);
268 return ret_val;
269 }
270 pr_debug("samples reported out 0x%llx\n",
271 stream->stream_info.buffer_ptr);
272 pr_debug("Frame bits:: %d period_count :: %d\n",
273 (int)substream->runtime->frame_bits,
274 (int)substream->runtime->period_size);
275
276 return stream->stream_info.buffer_ptr;
277
278}
279
280/**
281 * snd_intelmad_close- to free parameteres when stream is stopped
282 *
283 * @substream: substream for which the function is called
284 *
285 * This function is called by ALSA framework when stream is stopped
286 */
287static int snd_intelmad_close(struct snd_pcm_substream *substream)
288{
289 struct snd_intelmad *intelmaddata;
290 struct mad_stream_pvt *stream;
291 int ret_val = 0, str_id;
292
293 WARN_ON(!substream);
294
295 stream = substream->runtime->private_data;
296 str_id = stream->stream_info.str_id;
297
298 pr_debug("sst: snd_intelmad_close called for %d\n", str_id);
299 intelmaddata = snd_pcm_substream_chip(substream);
300
301 pr_debug("str id = %d\n", stream->stream_info.str_id);
302 if (stream->stream_info.str_id) {
303 /* SST API to actually stop/free the stream */
304 ret_val = intelmaddata->sstdrv_ops->pcm_control->close(str_id);
305 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
306 intelmaddata->playback_cnt--;
307 else
308 intelmaddata->capture_cnt--;
309 }
310 pr_debug("snd_intelmad_close : pb cnt = %d cap cnt = %d\n",
311 intelmaddata->playback_cnt, intelmaddata->capture_cnt);
312 kfree(substream->runtime->private_data);
313 return ret_val;
314}
315
316/**
317 * snd_intelmad_open- to set runtime parameters during stream start
318 *
319 * @substream: substream for which the function is called
320 * @type: audio device type
321 *
322 * This function is called by ALSA framework when stream is started
323 */
324static int snd_intelmad_open(struct snd_pcm_substream *substream,
325 enum snd_sst_audio_device_type type)
326{
327 struct snd_intelmad *intelmaddata;
328 struct snd_pcm_runtime *runtime;
329 struct mad_stream_pvt *stream;
330
331 WARN_ON(!substream);
332
333 pr_debug("snd_intelmad_open called\n");
334
335 intelmaddata = snd_pcm_substream_chip(substream);
336 runtime = substream->runtime;
337 /* set the runtime hw parameter with local snd_pcm_hardware struct */
338 runtime->hw = snd_intelmad_stream;
339 if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
340 /*
341 * MRST firmware currently denies stereo recording requests.
342 */
343 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
344 runtime->hw.formats = (SNDRV_PCM_FMTBIT_S16 |
345 SNDRV_PCM_FMTBIT_U16);
346 runtime->hw.channels_max = 1;
347 }
348 }
349 if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
350 runtime->hw = snd_intelmad_stream;
351 runtime->hw.rates = SNDRV_PCM_RATE_48000;
352 runtime->hw.rate_min = MAX_RATE;
353 runtime->hw.formats = (SNDRV_PCM_FMTBIT_S24 |
354 SNDRV_PCM_FMTBIT_U24);
355 if (intelmaddata->sstdrv_ops->scard_ops->input_dev_id == AMIC)
356 runtime->hw.channels_max = MAX_CHANNEL_AMIC;
357 else
358 runtime->hw.channels_max = MAX_CHANNEL_DMIC;
359
360 }
361 /* setup the internal datastruture stream pointers based on it being
362 playback or capture stream */
363 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
364 if (!stream)
365 return -ENOMEM;
366 stream->stream_info.str_id = 0;
367 stream->device = type;
368 stream->stream_status = INIT;
369 runtime->private_data = stream;
370 return snd_pcm_hw_constraint_integer(runtime,
371 SNDRV_PCM_HW_PARAM_PERIODS);
372}
373
374static int snd_intelmad_headset_open(struct snd_pcm_substream *substream)
375{
376 return snd_intelmad_open(substream, SND_SST_DEVICE_HEADSET);
377}
378
379static int snd_intelmad_ihf_open(struct snd_pcm_substream *substream)
380{
381 return snd_intelmad_open(substream, SND_SST_DEVICE_IHF);
382}
383
384static int snd_intelmad_vibra_open(struct snd_pcm_substream *substream)
385{
386 return snd_intelmad_open(substream, SND_SST_DEVICE_VIBRA);
387}
388
389static int snd_intelmad_haptic_open(struct snd_pcm_substream *substream)
390{
391 return snd_intelmad_open(substream, SND_SST_DEVICE_HAPTIC);
392}
393
394static struct snd_pcm_ops snd_intelmad_headset_ops = {
395 .open = snd_intelmad_headset_open,
396 .close = snd_intelmad_close,
397 .ioctl = snd_pcm_lib_ioctl,
398 .hw_params = snd_intelmad_hw_params,
399 .hw_free = snd_intelmad_hw_free,
400 .prepare = snd_intelmad_pcm_prepare,
401 .trigger = snd_intelmad_pcm_trigger,
402 .pointer = snd_intelmad_pcm_pointer,
403};
404
405static struct snd_pcm_ops snd_intelmad_ihf_ops = {
406 .open = snd_intelmad_ihf_open,
407 .close = snd_intelmad_close,
408 .ioctl = snd_pcm_lib_ioctl,
409 .hw_params = snd_intelmad_hw_params,
410 .hw_free = snd_intelmad_hw_free,
411 .prepare = snd_intelmad_pcm_prepare,
412 .trigger = snd_intelmad_pcm_trigger,
413 .pointer = snd_intelmad_pcm_pointer,
414};
415
416static struct snd_pcm_ops snd_intelmad_vibra_ops = {
417 .open = snd_intelmad_vibra_open,
418 .close = snd_intelmad_close,
419 .ioctl = snd_pcm_lib_ioctl,
420 .hw_params = snd_intelmad_hw_params,
421 .hw_free = snd_intelmad_hw_free,
422 .prepare = snd_intelmad_pcm_prepare,
423 .trigger = snd_intelmad_pcm_trigger,
424 .pointer = snd_intelmad_pcm_pointer,
425};
426
427static struct snd_pcm_ops snd_intelmad_haptic_ops = {
428 .open = snd_intelmad_haptic_open,
429 .close = snd_intelmad_close,
430 .ioctl = snd_pcm_lib_ioctl,
431 .hw_params = snd_intelmad_hw_params,
432 .hw_free = snd_intelmad_hw_free,
433 .prepare = snd_intelmad_pcm_prepare,
434 .trigger = snd_intelmad_pcm_trigger,
435 .pointer = snd_intelmad_pcm_pointer,
436};
437
438static struct snd_pcm_ops snd_intelmad_capture_ops = {
439 .open = snd_intelmad_headset_open,
440 .close = snd_intelmad_close,
441 .ioctl = snd_pcm_lib_ioctl,
442 .hw_params = snd_intelmad_hw_params,
443 .hw_free = snd_intelmad_hw_free,
444 .prepare = snd_intelmad_pcm_prepare,
445 .trigger = snd_intelmad_pcm_trigger,
446 .pointer = snd_intelmad_pcm_pointer,
447};
448
449int intelmad_get_mic_bias(void)
450{
451 struct snd_pmic_ops *pmic_ops;
452
453 if (!intelmad_drv || !intelmad_drv->sstdrv_ops)
454 return -ENODEV;
455 pmic_ops = intelmad_drv->sstdrv_ops->scard_ops;
456 if (pmic_ops && pmic_ops->pmic_get_mic_bias)
457 return pmic_ops->pmic_get_mic_bias(intelmad_drv);
458 else
459 return -ENODEV;
460}
461EXPORT_SYMBOL_GPL(intelmad_get_mic_bias);
462
463int intelmad_set_headset_state(int state)
464{
465 struct snd_pmic_ops *pmic_ops;
466
467 if (!intelmad_drv || !intelmad_drv->sstdrv_ops)
468 return -ENODEV;
469 pmic_ops = intelmad_drv->sstdrv_ops->scard_ops;
470 if (pmic_ops && pmic_ops->pmic_set_headset_state)
471 return pmic_ops->pmic_set_headset_state(state);
472 else
473 return -ENODEV;
474}
475EXPORT_SYMBOL_GPL(intelmad_set_headset_state);
476
477void sst_process_mad_jack_detection(struct work_struct *work)
478{
479 u8 interrupt_status;
480 struct mad_jack_msg_wq *mad_jack_detect =
481 container_of(work, struct mad_jack_msg_wq, wq);
482
483 struct snd_intelmad *intelmaddata =
484 mad_jack_detect->intelmaddata;
485
486 if (!intelmaddata)
487 return;
488
489 interrupt_status = mad_jack_detect->intsts;
490 if (intelmaddata->sstdrv_ops && intelmaddata->sstdrv_ops->scard_ops
491 && intelmaddata->sstdrv_ops->scard_ops->pmic_irq_cb) {
492 intelmaddata->sstdrv_ops->scard_ops->pmic_irq_cb(
493 (void *)intelmaddata, interrupt_status);
494 intelmaddata->sstdrv_ops->scard_ops->pmic_jack_enable();
495 }
496 kfree(mad_jack_detect);
497}
498/**
499 * snd_intelmad_intr_handler- interrupt handler
500 *
501 * @irq : irq number of the interrupt received
502 * @dev: device context
503 *
504 * This function is called when an interrupt is raised at the sound card
505 */
506static irqreturn_t snd_intelmad_intr_handler(int irq, void *dev)
507{
508 struct snd_intelmad *intelmaddata =
509 (struct snd_intelmad *)dev;
510 u8 interrupt_status;
511 struct mad_jack_msg_wq *mad_jack_msg;
512 memcpy_fromio(&interrupt_status,
513 ((void *)(intelmaddata->int_base)),
514 sizeof(u8));
515
516 mad_jack_msg = kzalloc(sizeof(*mad_jack_msg), GFP_ATOMIC);
517 mad_jack_msg->intsts = interrupt_status;
518 mad_jack_msg->intelmaddata = intelmaddata;
519 INIT_WORK(&mad_jack_msg->wq, sst_process_mad_jack_detection);
520 queue_work(intelmaddata->mad_jack_wq, &mad_jack_msg->wq);
521
522 return IRQ_HANDLED;
523}
524
525void sst_mad_send_jack_report(struct snd_jack *jack,
526 int buttonpressevent , int status)
527{
528
529 if (!jack) {
530 pr_debug("MAD error jack empty\n");
531
532 } else {
533 snd_jack_report(jack, status);
534 /* button pressed and released */
535 if (buttonpressevent)
536 snd_jack_report(jack, 0);
537 pr_debug("MAD sending jack report Done !!!\n");
538 }
539}
540
541static int __devinit snd_intelmad_register_irq(
542 struct snd_intelmad *intelmaddata, unsigned int regbase,
543 unsigned int regsize)
544{
545 int ret_val;
546 char *drv_name;
547
548 pr_debug("irq reg regbase 0x%x, regsize 0x%x\n",
549 regbase, regsize);
550 intelmaddata->int_base = ioremap_nocache(regbase, regsize);
551 if (!intelmaddata->int_base)
552 pr_err("Mapping of cache failed\n");
553 pr_debug("irq = 0x%x\n", intelmaddata->irq);
554 if (intelmaddata->cpu_id == CPU_CHIP_PENWELL)
555 drv_name = DRIVER_NAME_MFLD;
556 else
557 drv_name = DRIVER_NAME_MRST;
558 ret_val = request_irq(intelmaddata->irq,
559 snd_intelmad_intr_handler,
560 IRQF_SHARED, drv_name,
561 intelmaddata);
562 if (ret_val)
563 pr_err("cannot register IRQ\n");
564 return ret_val;
565}
566
567static int __devinit snd_intelmad_sst_register(
568 struct snd_intelmad *intelmaddata)
569{
570 int ret_val = 0;
571 struct snd_pmic_ops *intelmad_vendor_ops[MAX_VENDORS] = {
572 &snd_pmic_ops_fs,
573 &snd_pmic_ops_mx,
574 &snd_pmic_ops_nc,
575 &snd_msic_ops
576 };
577
578 struct sc_reg_access vendor_addr = {0x00, 0x00, 0x00};
579
580 if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
581 ret_val = sst_sc_reg_access(&vendor_addr, PMIC_READ, 1);
582 if (ret_val)
583 return ret_val;
584 sst_card_vendor_id = (vendor_addr.value & (MASK2|MASK1|MASK0));
585 pr_debug("original n extrated vendor id = 0x%x %d\n",
586 vendor_addr.value, sst_card_vendor_id);
587 if (sst_card_vendor_id < 0 || sst_card_vendor_id > 2) {
588 pr_err("vendor card not supported!!\n");
589 return -EIO;
590 }
591 } else
592 sst_card_vendor_id = 0x3;
593
594 intelmaddata->sstdrv_ops->module_name = SST_CARD_NAMES;
595 intelmaddata->sstdrv_ops->vendor_id = sst_card_vendor_id;
596 BUG_ON(!intelmad_vendor_ops[sst_card_vendor_id]);
597 intelmaddata->sstdrv_ops->scard_ops =
598 intelmad_vendor_ops[sst_card_vendor_id];
599
600 if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
601 intelmaddata->sstdrv_ops->scard_ops->pb_on = 0;
602 intelmaddata->sstdrv_ops->scard_ops->cap_on = 0;
603 intelmaddata->sstdrv_ops->scard_ops->input_dev_id = DMIC;
604 intelmaddata->sstdrv_ops->scard_ops->output_dev_id =
605 STEREO_HEADPHONE;
606 intelmaddata->sstdrv_ops->scard_ops->lineout_dev_id = NONE;
607 }
608
609 /* registering with SST driver to get access to SST APIs to use */
610 ret_val = register_sst_card(intelmaddata->sstdrv_ops);
611 if (ret_val) {
612 pr_err("sst card registration failed\n");
613 return ret_val;
614 }
615 sst_card_vendor_id = intelmaddata->sstdrv_ops->vendor_id;
616 intelmaddata->pmic_status = PMIC_UNINIT;
617 return ret_val;
618}
619
620static void snd_intelmad_page_free(struct snd_pcm *pcm)
621{
622 snd_pcm_lib_preallocate_free_for_all(pcm);
623}
624/* Driver Init/exit functionalities */
625/**
626 * snd_intelmad_pcm_new - to setup pcm for the card
627 *
628 * @card: pointer to the sound card structure
629 * @intelmaddata: pointer to internal context
630 * @pb: playback count for this card
631 * @cap: capture count for this card
632 * @index: device index
633 *
634 * This function is called from probe function to set up pcm params
635 * and functions
636 */
637static int __devinit snd_intelmad_pcm_new(struct snd_card *card,
638 struct snd_intelmad *intelmaddata,
639 unsigned int pb, unsigned int cap, unsigned int index)
640{
641 int ret_val = 0;
642 struct snd_pcm *pcm;
643 char name[32] = INTEL_MAD;
644 struct snd_pcm_ops *pb_ops = NULL, *cap_ops = NULL;
645
646 pr_debug("called for pb %d, cp %d, idx %d\n", pb, cap, index);
647 ret_val = snd_pcm_new(card, name, index, pb, cap, &pcm);
648 if (ret_val)
649 return ret_val;
650 /* setup the ops for playback and capture streams */
651 switch (index) {
652 case 0:
653 pb_ops = &snd_intelmad_headset_ops;
654 cap_ops = &snd_intelmad_capture_ops;
655 break;
656 case 1:
657 pb_ops = &snd_intelmad_ihf_ops;
658 cap_ops = &snd_intelmad_capture_ops;
659 break;
660 case 2:
661 pb_ops = &snd_intelmad_vibra_ops;
662 cap_ops = &snd_intelmad_capture_ops;
663 break;
664 case 3:
665 pb_ops = &snd_intelmad_haptic_ops;
666 cap_ops = &snd_intelmad_capture_ops;
667 break;
668 }
669 if (pb)
670 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, pb_ops);
671 if (cap)
672 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, cap_ops);
673 /* setup private data which can be retrieved when required */
674 pcm->private_data = intelmaddata;
675 pcm->private_free = snd_intelmad_page_free;
676 pcm->info_flags = 0;
677 strncpy(pcm->name, card->shortname, strlen(card->shortname));
678 /* allocate dma pages for ALSA stream operations */
679 snd_pcm_lib_preallocate_pages_for_all(pcm,
680 SNDRV_DMA_TYPE_CONTINUOUS,
681 snd_dma_continuous_data(GFP_KERNEL),
682 MIN_BUFFER, MAX_BUFFER);
683 return ret_val;
684}
685
686static int __devinit snd_intelmad_pcm(struct snd_card *card,
687 struct snd_intelmad *intelmaddata)
688{
689 int ret_val = 0;
690
691 WARN_ON(!card);
692 WARN_ON(!intelmaddata);
693 pr_debug("snd_intelmad_pcm called\n");
694 ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 1, 0);
695 if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT)
696 return ret_val;
697 ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 0, 1);
698 if (ret_val)
699 return ret_val;
700 ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 0, 2);
701 if (ret_val)
702 return ret_val;
703 return snd_intelmad_pcm_new(card, intelmaddata, 1, 0, 3);
704}
705
706/**
707 * snd_intelmad_jack- to setup jack settings of the card
708 *
709 * @intelmaddata: pointer to internal context
710 *
711 * This function is called send jack events
712 */
713static int snd_intelmad_jack(struct snd_intelmad *intelmaddata)
714{
715 struct snd_jack *jack;
716 int retval;
717
718 pr_debug("snd_intelmad_jack called\n");
719 jack = &intelmaddata->jack[0].jack;
720 snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PHONE);
721 retval = snd_jack_new(intelmaddata->card, "Intel(R) MID Audio Jack",
722 SND_JACK_HEADPHONE | SND_JACK_HEADSET |
723 SW_JACK_PHYSICAL_INSERT | SND_JACK_BTN_0
724 | SND_JACK_BTN_1, &jack);
725 pr_debug("snd_intelmad_jack called\n");
726 if (retval < 0)
727 return retval;
728 snd_jack_report(jack, 0);
729
730 jack->private_data = jack;
731 intelmaddata->jack[0].jack = *jack;
732
733 return retval;
734}
735
736/**
737 * snd_intelmad_mixer- to setup mixer settings of the card
738 *
739 * @intelmaddata: pointer to internal context
740 *
741 * This function is called from probe function to set up mixer controls
742 */
743static int __devinit snd_intelmad_mixer(struct snd_intelmad *intelmaddata)
744{
745 struct snd_card *card;
746 unsigned int idx;
747 int ret_val = 0, max_controls = 0;
748 char *mixername = "IntelMAD Controls";
749 struct snd_kcontrol_new *controls;
750
751 WARN_ON(!intelmaddata);
752
753 card = intelmaddata->card;
754 strncpy(card->mixername, mixername, sizeof(card->mixername)-1);
755 /* add all widget controls and expose the same */
756 if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
757 max_controls = MAX_CTRL_MFLD;
758 controls = snd_intelmad_controls_mfld;
759 } else {
760 max_controls = MAX_CTRL_MRST;
761 controls = snd_intelmad_controls_mrst;
762 }
763 for (idx = 0; idx < max_controls; idx++) {
764 ret_val = snd_ctl_add(card,
765 snd_ctl_new1(&controls[idx],
766 intelmaddata));
767 pr_debug("mixer[idx]=%d added\n", idx);
768 if (ret_val) {
769 pr_err("in adding of control index = %d\n", idx);
770 break;
771 }
772 }
773 return ret_val;
774}
775
776static int snd_intelmad_dev_free(struct snd_device *device)
777{
778 struct snd_intelmad *intelmaddata;
779
780 WARN_ON(!device);
781
782 intelmaddata = device->device_data;
783
784 pr_debug("snd_intelmad_dev_free called\n");
785 unregister_sst_card(intelmaddata->sstdrv_ops);
786
787 /* free allocated memory for internal context */
788 destroy_workqueue(intelmaddata->mad_jack_wq);
789 device->device_data = NULL;
790 kfree(intelmaddata->sstdrv_ops);
791 kfree(intelmaddata);
792
793 return 0;
794}
795
796static int __devinit snd_intelmad_create(
797 struct snd_intelmad *intelmaddata,
798 struct snd_card *card)
799{
800 int ret_val;
801 static struct snd_device_ops ops = {
802 .dev_free = snd_intelmad_dev_free,
803 };
804
805 WARN_ON(!intelmaddata);
806 WARN_ON(!card);
807 /* ALSA api to register for the device */
808 ret_val = snd_device_new(card, SNDRV_DEV_LOWLEVEL, intelmaddata, &ops);
809 return ret_val;
810}
811
812/**
813* snd_intelmad_probe- function registred for init
814* @pdev : pointer to the device struture
815* This function is called when the device is initialized
816*/
817int __devinit snd_intelmad_probe(struct platform_device *pdev)
818{
819 struct snd_card *card;
820 int ret_val;
821 struct snd_intelmad *intelmaddata;
822 const struct platform_device_id *id = platform_get_device_id(pdev);
823 struct snd_intelmad_probe_info *info = (void *)id->driver_data;
824
825 pr_debug("probe for %s cpu_id %d\n", pdev->name, info->cpu_id);
826 pr_debug("rq_chache %x of size %x\n", info->irq_cache, info->size);
827 if (!strcmp(pdev->name, DRIVER_NAME_MRST))
828 pr_debug("detected MRST\n");
829 else if (!strcmp(pdev->name, DRIVER_NAME_MFLD))
830 pr_debug("detected MFLD\n");
831 else {
832 pr_err("detected unknown device abort!!\n");
833 return -EIO;
834 }
835 if ((info->cpu_id < CPU_CHIP_LINCROFT) ||
836 (info->cpu_id > CPU_CHIP_PENWELL)) {
837 pr_err("detected unknown cpu_id abort!!\n");
838 return -EIO;
839 }
840 /* allocate memory for saving internal context and working */
841 intelmaddata = kzalloc(sizeof(*intelmaddata), GFP_KERNEL);
842 if (!intelmaddata) {
843 pr_debug("mem alloctn fail\n");
844 return -ENOMEM;
845 }
846 intelmad_drv = intelmaddata;
847
848 /* allocate memory for LPE API set */
849 intelmaddata->sstdrv_ops = kzalloc(sizeof(struct intel_sst_card_ops),
850 GFP_KERNEL);
851 if (!intelmaddata->sstdrv_ops) {
852 pr_err("mem allocation for ops fail\n");
853 kfree(intelmaddata);
854 return -ENOMEM;
855 }
856
857 intelmaddata->cpu_id = info->cpu_id;
858 /* create a card instance with ALSA framework */
859 ret_val = snd_card_create(card_index, card_id, THIS_MODULE, 0, &card);
860 if (ret_val) {
861 pr_err("snd_card_create fail\n");
862 goto free_allocs;
863 }
864
865 intelmaddata->pdev = pdev;
866 intelmaddata->irq = platform_get_irq(pdev, 0);
867 platform_set_drvdata(pdev, intelmaddata);
868 intelmaddata->card = card;
869 intelmaddata->card_id = card_id;
870 intelmaddata->card_index = card_index;
871 intelmaddata->master_mute = UNMUTE;
872 intelmaddata->playback_cnt = intelmaddata->capture_cnt = 0;
873 strncpy(card->driver, INTEL_MAD, strlen(INTEL_MAD));
874 strncpy(card->shortname, INTEL_MAD, strlen(INTEL_MAD));
875
876 intelmaddata->sstdrv_ops->module_name = SST_CARD_NAMES;
877 /* registering with LPE driver to get access to SST APIs to use */
878 ret_val = snd_intelmad_sst_register(intelmaddata);
879 if (ret_val) {
880 pr_err("snd_intelmad_sst_register failed\n");
881 goto set_null_data;
882 }
883
884 intelmaddata->pmic_status = PMIC_INIT;
885
886 ret_val = snd_intelmad_pcm(card, intelmaddata);
887 if (ret_val) {
888 pr_err("snd_intelmad_pcm failed\n");
889 goto free_sst;
890 }
891
892 ret_val = snd_intelmad_mixer(intelmaddata);
893 if (ret_val) {
894 pr_err("snd_intelmad_mixer failed\n");
895 goto free_card;
896 }
897
898 ret_val = snd_intelmad_jack(intelmaddata);
899 if (ret_val) {
900 pr_err("snd_intelmad_jack failed\n");
901 goto free_card;
902 }
903 intelmaddata->adc_address = mid_initialize_adc();
904
905 /*create work queue for jack interrupt*/
906 INIT_WORK(&intelmaddata->mad_jack_msg.wq,
907 sst_process_mad_jack_detection);
908
909 intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");
910 if (!intelmaddata->mad_jack_wq)
911 goto free_card;
912
913 ret_val = snd_intelmad_register_irq(intelmaddata,
914 info->irq_cache, info->size);
915 if (ret_val) {
916 pr_err("snd_intelmad_register_irq fail\n");
917 goto free_mad_jack_wq;
918 }
919
920 /* internal function call to register device with ALSA */
921 ret_val = snd_intelmad_create(intelmaddata, card);
922 if (ret_val) {
923 pr_err("snd_intelmad_create failed\n");
924 goto set_pvt_data;
925 }
926 card->private_data = &intelmaddata;
927 snd_card_set_dev(card, &pdev->dev);
928 ret_val = snd_card_register(card);
929 if (ret_val) {
930 pr_err("snd_card_register failed\n");
931 goto set_pvt_data;
932 }
933 if (pdev->dev.platform_data) {
934 int gpio_amp = *(int *)pdev->dev.platform_data;
935 if (gpio_request_one(gpio_amp, GPIOF_OUT_INIT_LOW, "amp power"))
936 gpio_amp = 0;
937 intelmaddata->sstdrv_ops->scard_ops->gpio_amp = gpio_amp;
938 }
939
940 pr_debug("snd_intelmad_probe complete\n");
941 return ret_val;
942
943set_pvt_data:
944 card->private_data = NULL;
945free_mad_jack_wq:
946 destroy_workqueue(intelmaddata->mad_jack_wq);
947free_card:
948 snd_card_free(intelmaddata->card);
949free_sst:
950 unregister_sst_card(intelmaddata->sstdrv_ops);
951set_null_data:
952 platform_set_drvdata(pdev, NULL);
953free_allocs:
954 pr_err("probe failed\n");
955 snd_card_free(card);
956 kfree(intelmaddata->sstdrv_ops);
957 kfree(intelmaddata);
958 return ret_val;
959}
960
961
962static int snd_intelmad_remove(struct platform_device *pdev)
963{
964 struct snd_intelmad *intelmaddata = platform_get_drvdata(pdev);
965
966 if (intelmaddata) {
967 if (intelmaddata->sstdrv_ops->scard_ops->gpio_amp)
968 gpio_free(intelmaddata->sstdrv_ops->scard_ops->gpio_amp);
969 free_irq(intelmaddata->irq, intelmaddata);
970 snd_card_free(intelmaddata->card);
971 }
972 intelmad_drv = NULL;
973 platform_set_drvdata(pdev, NULL);
974 return 0;
975}
976
977/*********************************************************************
978 * Driver initialization and exit
979 *********************************************************************/
980static const struct platform_device_id snd_intelmad_ids[] = {
981 {DRIVER_NAME_MRST, INFO(CPU_CHIP_LINCROFT, AUDINT_BASE, 1)},
982 {DRIVER_NAME_MFLD, INFO(CPU_CHIP_PENWELL, 0xFFFF7FCD, 1)},
983 {"", 0},
984
985};
986
987static struct platform_driver snd_intelmad_driver = {
988 .driver = {
989 .owner = THIS_MODULE,
990 .name = "intel_mid_sound_card",
991 },
992 .id_table = snd_intelmad_ids,
993 .probe = snd_intelmad_probe,
994 .remove = __devexit_p(snd_intelmad_remove),
995};
996
997/*
998 * alsa_card_intelmad_init- driver init function
999 *
1000 * This function is called when driver module is inserted
1001 */
1002static int __init alsa_card_intelmad_init(void)
1003{
1004 pr_debug("mad_init called\n");
1005 return platform_driver_register(&snd_intelmad_driver);
1006}
1007
1008/**
1009 * alsa_card_intelmad_exit- driver exit function
1010 *
1011 * This function is called when driver module is removed
1012 */
1013static void __exit alsa_card_intelmad_exit(void)
1014{
1015 pr_debug("mad_exit called\n");
1016 return platform_driver_unregister(&snd_intelmad_driver);
1017}
1018
1019module_init(alsa_card_intelmad_init)
1020module_exit(alsa_card_intelmad_exit)
1021
diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
new file mode 100644
index 00000000000..14a7ba078b7
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid.h
@@ -0,0 +1,209 @@
1/*
2 * intelmid.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 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 * ALSA driver header for Intel MAD chipset
26 */
27#ifndef __INTELMID_H
28#define __INTELMID_H
29
30#include <linux/time.h>
31#include <sound/jack.h>
32
33#define DRIVER_NAME_MFLD "msic_audio"
34#define DRIVER_NAME_MRST "pmic_audio"
35#define DRIVER_NAME "intelmid_audio"
36#define PMIC_SOUND_IRQ_TYPE_MASK (1 << 15)
37#define AUDINT_BASE (0xFFFFEFF8 + (6 * sizeof(u8)))
38#define REG_IRQ
39/* values #defined */
40/* will differ for different hw - to be taken from config */
41#define MAX_DEVICES 1
42#define MIN_RATE 8000
43#define MAX_RATE 48000
44#define MAX_BUFFER (800*1024) /* for PCM */
45#define MIN_BUFFER (800*1024)
46#define MAX_PERIODS (1024*2)
47#define MIN_PERIODS 2
48#define MAX_PERIOD_BYTES MAX_BUFFER
49#define MIN_PERIOD_BYTES 32
50/*#define MIN_PERIOD_BYTES 160*/
51#define MAX_MUTE 1
52#define MIN_MUTE 0
53#define MONO_CNTL 1
54#define STEREO_CNTL 2
55#define MIN_CHANNEL 1
56#define MAX_CHANNEL_AMIC 2
57#define MAX_CHANNEL_DMIC 5
58#define FIFO_SIZE 0 /* fifo not being used */
59#define INTEL_MAD "Intel MAD"
60#define MAX_CTRL_MRST 8
61#define MAX_CTRL_MFLD 7
62#define MAX_CTRL 8
63#define MAX_VENDORS 4
64/* TODO +6 db */
65#define MAX_VOL 64
66/* TODO -57 db */
67#define MIN_VOL 0
68#define PLAYBACK_COUNT 1
69#define CAPTURE_COUNT 1
70#define ADC_ONE_LSB_MULTIPLIER 2346
71
72#define MID_JACK_HS_LONG_PRESS SND_JACK_BTN_0
73#define MID_JACK_HS_SHORT_PRESS SND_JACK_BTN_1
74
75extern int sst_card_vendor_id;
76
77struct mad_jack {
78 struct snd_jack jack;
79 int jack_status;
80 int jack_dev_state;
81 struct timeval buttonpressed;
82 struct timeval buttonreleased;
83};
84
85struct mad_jack_msg_wq {
86 u8 intsts;
87 struct snd_intelmad *intelmaddata;
88 struct work_struct wq;
89
90};
91
92struct snd_intelmad_probe_info {
93 unsigned int cpu_id;
94 unsigned int irq_cache;
95 unsigned int size;
96};
97
98/**
99 * struct snd_intelmad - intelmad driver structure
100 *
101 * @card: ptr to the card details
102 * @card_index: sound card index
103 * @card_id: sound card id detected
104 * @sstdrv_ops: ptr to sst driver ops
105 * @pdev: ptr to platform device
106 * @irq: interrupt number detected
107 * @pmic_status: Device status of sound card
108 * @int_base: ptr to MMIO interrupt region
109 * @output_sel: device selected as o/p
110 * @input_sel: device selected as i/p
111 * @master_mute: master mute status
112 * @jack: jack status
113 * @playback_cnt: active pb streams
114 * @capture_cnt: active cp streams
115 * @mad_jack_msg: wq struct for jack interrupt processing
116 * @mad_jack_wq: wq for jack interrupt processing
117 * @jack_prev_state: Previos state of jack detected
118 * @cpu_id: current cpu id loaded for
119 */
120struct snd_intelmad {
121 struct snd_card *card; /* ptr to the card details */
122 int card_index;/* card index */
123 char *card_id; /* card id */
124 struct intel_sst_card_ops *sstdrv_ops;/* ptr to sst driver ops */
125 struct platform_device *pdev;
126 int irq;
127 int pmic_status;
128 void __iomem *int_base;
129 int output_sel;
130 int input_sel;
131 int lineout_sel;
132 int master_mute;
133 struct mad_jack jack[4];
134 int playback_cnt;
135 int capture_cnt;
136 u16 adc_address;
137 struct mad_jack_msg_wq mad_jack_msg;
138 struct workqueue_struct *mad_jack_wq;
139 u8 jack_prev_state;
140 unsigned int cpu_id;
141};
142
143struct snd_control_val {
144 int playback_vol_max;
145 int playback_vol_min;
146 int capture_vol_max;
147 int capture_vol_min;
148 int master_vol_max;
149 int master_vol_min;
150};
151
152struct mad_stream_pvt {
153 int stream_status;
154 int stream_ops;
155 struct snd_pcm_substream *substream;
156 struct pcm_stream_info stream_info;
157 ssize_t dbg_cum_bytes;
158 enum snd_sst_device_type device;
159};
160
161enum mad_drv_status {
162 INIT = 1,
163 STARTED,
164 RUNNING,
165 PAUSED,
166 DROPPED,
167};
168
169enum mad_pmic_status {
170 PMIC_UNINIT = 1,
171 PMIC_INIT,
172};
173enum _widget_ctrl {
174 OUTPUT_SEL = 1,
175 INPUT_SEL,
176 PLAYBACK_VOL,
177 PLAYBACK_MUTE,
178 CAPTURE_VOL,
179 CAPTURE_MUTE,
180 MASTER_VOL,
181 MASTER_MUTE
182};
183enum _widget_ctrl_mfld {
184 LINEOUT_SEL_MFLD = 3,
185};
186enum hw_chs {
187 HW_CH0 = 0,
188 HW_CH1,
189 HW_CH2,
190 HW_CH3
191};
192
193void period_elapsed(void *mad_substream);
194int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream);
195int snd_intelmad_init_stream(struct snd_pcm_substream *substream);
196
197int sst_sc_reg_access(struct sc_reg_access *sc_access,
198 int type, int num_val);
199#define CPU_CHIP_LINCROFT 1 /* System running lincroft */
200#define CPU_CHIP_PENWELL 2 /* System running penwell */
201
202extern struct snd_control_val intelmad_ctrl_val[];
203extern struct snd_kcontrol_new snd_intelmad_controls_mrst[];
204extern struct snd_kcontrol_new snd_intelmad_controls_mfld[];
205extern struct snd_pmic_ops *intelmad_vendor_ops[];
206void sst_mad_send_jack_report(struct snd_jack *jack,
207 int buttonpressevent , int status);
208
209#endif /* __INTELMID_H */
diff --git a/drivers/staging/intel_sst/intelmid_adc_control.h b/drivers/staging/intel_sst/intelmid_adc_control.h
new file mode 100644
index 00000000000..65d5c398876
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_adc_control.h
@@ -0,0 +1,193 @@
1#ifndef __INTELMID_ADC_CONTROL_H__
2#define __INTELMID_ADC_CONTROL_H_
3/*
4 * intelmid_adc_control.h - Intel SST Driver for audio engine
5 *
6 * Copyright (C) 2008-10 Intel Corporation
7 * Authors: R Durgadadoss <r.durgadoss@intel.com>
8 * Dharageswari R <dharageswari.r@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * Common private ADC declarations for SST
27 */
28
29
30#define MSIC_ADC1CNTL1 0x1C0
31#define MSIC_ADC_ENBL 0x10
32#define MSIC_ADC_START 0x08
33
34#define MSIC_ADC1CNTL3 0x1C2
35#define MSIC_ADCTHERM_ENBL 0x04
36#define MSIC_ADCRRDATA_ENBL 0x05
37
38#define MSIC_STOPBIT_MASK 16
39#define MSIC_ADCTHERM_MASK 4
40
41#define ADC_CHANLS_MAX 15 /* Number of ADC channels */
42#define ADC_LOOP_MAX (ADC_CHANLS_MAX - 1)
43
44/* ADC channel code values */
45#define AUDIO_DETECT_CODE 0x06
46
47/* ADC base addresses */
48#define ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
49#define ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
50
51
52/**
53 * configure_adc - enables/disables the ADC for conversion
54 * @val: zero: disables the ADC non-zero:enables the ADC
55 *
56 * Enable/Disable the ADC depending on the argument
57 *
58 * Can sleep
59 */
60static inline int configure_adc(int val)
61{
62 int ret;
63 struct sc_reg_access sc_access = {0,};
64
65
66 sc_access.reg_addr = MSIC_ADC1CNTL1;
67 ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
68 if (ret)
69 return ret;
70
71 if (val)
72 /* Enable and start the ADC */
73 sc_access.value |= (MSIC_ADC_ENBL | MSIC_ADC_START);
74 else
75 /* Just stop the ADC */
76 sc_access.value &= (~MSIC_ADC_START);
77 sc_access.reg_addr = MSIC_ADC1CNTL1;
78 return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
79}
80
81/**
82 * reset_stopbit - sets the stop bit to 0 on the given channel
83 * @addr: address of the channel
84 *
85 * Can sleep
86 */
87static inline int reset_stopbit(uint16_t addr)
88{
89 int ret;
90 struct sc_reg_access sc_access = {0,};
91 sc_access.reg_addr = addr;
92 ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
93 if (ret)
94 return ret;
95 /* Set the stop bit to zero */
96 sc_access.reg_addr = addr;
97 sc_access.value = (sc_access.value) & 0xEF;
98 return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
99}
100
101/**
102 * find_free_channel - finds an empty channel for conversion
103 *
104 * If the ADC is not enabled then start using 0th channel
105 * itself. Otherwise find an empty channel by looking for a
106 * channel in which the stopbit is set to 1. returns the index
107 * of the first free channel if succeeds or an error code.
108 *
109 * Context: can sleep
110 *
111 */
112static inline int find_free_channel(void)
113{
114 int ret;
115 int i;
116
117 struct sc_reg_access sc_access = {0,};
118
119 /* check whether ADC is enabled */
120 sc_access.reg_addr = MSIC_ADC1CNTL1;
121 ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
122 if (ret)
123 return ret;
124
125 if ((sc_access.value & MSIC_ADC_ENBL) == 0)
126 return 0;
127
128 /* ADC is already enabled; Looking for an empty channel */
129 for (i = 0; i < ADC_CHANLS_MAX; i++) {
130
131 sc_access.reg_addr = ADC_CHNL_START_ADDR + i;
132 ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
133 if (ret)
134 return ret;
135
136 if (sc_access.value & MSIC_STOPBIT_MASK) {
137 ret = i;
138 break;
139 }
140 }
141 return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
142}
143
144/**
145 * mid_initialize_adc - initializing the ADC
146 * @dev: our device structure
147 *
148 * Initialize the ADC for reading thermistor values. Can sleep.
149 */
150static inline int mid_initialize_adc(void)
151{
152 int base_addr, chnl_addr;
153 int ret;
154 static int channel_index;
155 struct sc_reg_access sc_access = {0,};
156
157 /* Index of the first channel in which the stop bit is set */
158 channel_index = find_free_channel();
159 if (channel_index < 0) {
160 pr_err("No free ADC channels");
161 return channel_index;
162 }
163
164 base_addr = ADC_CHNL_START_ADDR + channel_index;
165
166 if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
167 /* Reset stop bit for channels other than 0 and 12 */
168 ret = reset_stopbit(base_addr);
169 if (ret)
170 return ret;
171
172 /* Index of the first free channel */
173 base_addr++;
174 channel_index++;
175 }
176
177 /* Since this is the last channel, set the stop bit
178 to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
179 sc_access.reg_addr = base_addr;
180 sc_access.value = AUDIO_DETECT_CODE | 0x10;
181 ret = sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
182 if (ret) {
183 pr_err("unable to enable ADC");
184 return ret;
185 }
186
187 chnl_addr = ADC_DATA_START_ADDR + 2 * channel_index;
188 pr_debug("mid_initialize : %x", chnl_addr);
189 configure_adc(1);
190 return chnl_addr;
191}
192#endif
193
diff --git a/drivers/staging/intel_sst/intelmid_ctrl.c b/drivers/staging/intel_sst/intelmid_ctrl.c
new file mode 100644
index 00000000000..19ec474b362
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_ctrl.c
@@ -0,0 +1,921 @@
1/*
2 * intelmid_ctrl.c - 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 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 * ALSA driver handling mixer controls for Intel MAD chipset
26 */
27
28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
30#include <sound/core.h>
31#include <sound/control.h>
32#include "intel_sst.h"
33#include "intel_sst_ioctl.h"
34#include "intelmid_snd_control.h"
35#include "intelmid.h"
36
37#define HW_CH_BASE 4
38
39
40#define HW_CH_0 "Hw1"
41#define HW_CH_1 "Hw2"
42#define HW_CH_2 "Hw3"
43#define HW_CH_3 "Hw4"
44
45static char *router_dmics[] = { "DMIC1",
46 "DMIC2",
47 "DMIC3",
48 "DMIC4",
49 "DMIC5",
50 "DMIC6"
51 };
52
53static char *out_names_mrst[] = {"Headphones",
54 "Internal speakers"};
55static char *in_names_mrst[] = {"AMIC",
56 "DMIC",
57 "HS_MIC"};
58static char *line_out_names_mfld[] = {"Headset",
59 "IHF ",
60 "Vibra1 ",
61 "Vibra2 ",
62 "NONE "};
63static char *out_names_mfld[] = {"Headset ",
64 "EarPiece "};
65static char *in_names_mfld[] = {"AMIC",
66 "DMIC"};
67
68struct snd_control_val intelmad_ctrl_val[MAX_VENDORS] = {
69 {
70 .playback_vol_max = 63,
71 .playback_vol_min = 0,
72 .capture_vol_max = 63,
73 .capture_vol_min = 0,
74 },
75 {
76 .playback_vol_max = 0,
77 .playback_vol_min = -31,
78 .capture_vol_max = 0,
79 .capture_vol_min = -20,
80 },
81 {
82 .playback_vol_max = 0,
83 .playback_vol_min = -31,
84 .capture_vol_max = 0,
85 .capture_vol_min = -31,
86 .master_vol_max = 0,
87 .master_vol_min = -126,
88 },
89};
90
91/* control path functionalities */
92
93static inline int snd_intelmad_volume_info(struct snd_ctl_elem_info *uinfo,
94 int control_type, int max, int min)
95{
96 WARN_ON(!uinfo);
97
98 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
99 uinfo->count = control_type;
100 uinfo->value.integer.min = min;
101 uinfo->value.integer.max = max;
102 return 0;
103}
104
105/**
106* snd_intelmad_mute_info - provides information about the mute controls
107*
108* @kcontrol: pointer to the control
109* @uinfo: pointer to the structure where the control's info need
110* to be filled
111*
112* This function is called when a mixer application requests for control's info
113*/
114static int snd_intelmad_mute_info(struct snd_kcontrol *kcontrol,
115 struct snd_ctl_elem_info *uinfo)
116{
117 WARN_ON(!uinfo);
118 WARN_ON(!kcontrol);
119
120 /* set up the mute as a boolean mono control with min-max values */
121 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
122 uinfo->count = MONO_CNTL;
123 uinfo->value.integer.min = MIN_MUTE;
124 uinfo->value.integer.max = MAX_MUTE;
125 return 0;
126}
127
128/**
129* snd_intelmad_capture_volume_info - provides info about the volume control
130*
131* @kcontrol: pointer to the control
132* @uinfo: pointer to the structure where the control's info need
133* to be filled
134*
135* This function is called when a mixer application requests for control's info
136*/
137static int snd_intelmad_capture_volume_info(struct snd_kcontrol *kcontrol,
138 struct snd_ctl_elem_info *uinfo)
139{
140 snd_intelmad_volume_info(uinfo, MONO_CNTL,
141 intelmad_ctrl_val[sst_card_vendor_id].capture_vol_max,
142 intelmad_ctrl_val[sst_card_vendor_id].capture_vol_min);
143 return 0;
144}
145
146/**
147* snd_intelmad_playback_volume_info - provides info about the volume control
148*
149* @kcontrol: pointer to the control
150* @uinfo: pointer to the structure where the control's info need
151* to be filled
152*
153* This function is called when a mixer application requests for control's info
154*/
155static int snd_intelmad_playback_volume_info(struct snd_kcontrol *kcontrol,
156 struct snd_ctl_elem_info *uinfo)
157{
158 snd_intelmad_volume_info(uinfo, STEREO_CNTL,
159 intelmad_ctrl_val[sst_card_vendor_id].playback_vol_max,
160 intelmad_ctrl_val[sst_card_vendor_id].playback_vol_min);
161 return 0;
162}
163
164static int snd_intelmad_master_volume_info(struct snd_kcontrol *kcontrol,
165 struct snd_ctl_elem_info *uinfo)
166{
167 snd_intelmad_volume_info(uinfo, STEREO_CNTL,
168 intelmad_ctrl_val[sst_card_vendor_id].master_vol_max,
169 intelmad_ctrl_val[sst_card_vendor_id].master_vol_min);
170 return 0;
171}
172
173/**
174* snd_intelmad_device_info_mrst - provides information about the devices available
175*
176* @kcontrol: pointer to the control
177* @uinfo: pointer to the structure where the devices's info need
178* to be filled
179*
180* This function is called when a mixer application requests for device's info
181*/
182static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol,
183 struct snd_ctl_elem_info *uinfo)
184{
185
186 WARN_ON(!kcontrol);
187 WARN_ON(!uinfo);
188
189 /* setup device select as drop down controls with different values */
190 if (kcontrol->id.numid == OUTPUT_SEL)
191 uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mrst);
192 else
193 uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mrst);
194 uinfo->count = MONO_CNTL;
195 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
196
197 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
198 uinfo->value.enumerated.item = 1;
199 if (kcontrol->id.numid == OUTPUT_SEL)
200 strncpy(uinfo->value.enumerated.name,
201 out_names_mrst[uinfo->value.enumerated.item],
202 sizeof(uinfo->value.enumerated.name)-1);
203 else
204 strncpy(uinfo->value.enumerated.name,
205 in_names_mrst[uinfo->value.enumerated.item],
206 sizeof(uinfo->value.enumerated.name)-1);
207 return 0;
208}
209
210static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
211 struct snd_ctl_elem_info *uinfo)
212{
213 struct snd_pmic_ops *scard_ops;
214 struct snd_intelmad *intelmaddata;
215
216 WARN_ON(!kcontrol);
217 WARN_ON(!uinfo);
218
219 intelmaddata = kcontrol->private_data;
220
221 WARN_ON(!intelmaddata->sstdrv_ops);
222
223 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
224 /* setup device select as drop down controls with different values */
225 if (kcontrol->id.numid == OUTPUT_SEL)
226 uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld);
227 else if (kcontrol->id.numid == INPUT_SEL)
228 uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld);
229 else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) {
230 uinfo->value.enumerated.items = ARRAY_SIZE(line_out_names_mfld);
231 scard_ops->line_out_names_cnt = uinfo->value.enumerated.items;
232 } else
233 return -EINVAL;
234 uinfo->count = MONO_CNTL;
235 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
236
237 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
238 uinfo->value.enumerated.item = 1;
239 if (kcontrol->id.numid == OUTPUT_SEL)
240 strncpy(uinfo->value.enumerated.name,
241 out_names_mfld[uinfo->value.enumerated.item],
242 sizeof(uinfo->value.enumerated.name)-1);
243 else if (kcontrol->id.numid == INPUT_SEL)
244 strncpy(uinfo->value.enumerated.name,
245 in_names_mfld[uinfo->value.enumerated.item],
246 sizeof(uinfo->value.enumerated.name)-1);
247 else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
248 strncpy(uinfo->value.enumerated.name,
249 line_out_names_mfld[uinfo->value.enumerated.item],
250 sizeof(uinfo->value.enumerated.name)-1);
251 else
252 return -EINVAL;
253 return 0;
254}
255
256/**
257* snd_intelmad_volume_get - gets the current volume for the control
258*
259* @kcontrol: pointer to the control
260* @uval: pointer to the structure where the control's info need
261* to be filled
262*
263* This function is called when .get function of a control is invoked from app
264*/
265static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
266 struct snd_ctl_elem_value *uval)
267{
268 int ret_val = 0, cntl_list[2] = {0,};
269 int value = 0;
270 struct snd_intelmad *intelmaddata;
271 struct snd_pmic_ops *scard_ops;
272
273 pr_debug("snd_intelmad_volume_get called\n");
274
275 WARN_ON(!uval);
276 WARN_ON(!kcontrol);
277
278 intelmaddata = kcontrol->private_data;
279
280 WARN_ON(!intelmaddata->sstdrv_ops);
281
282 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
283
284 WARN_ON(!scard_ops);
285
286 switch (kcontrol->id.numid) {
287 case PLAYBACK_VOL:
288 cntl_list[0] = PMIC_SND_RIGHT_PB_VOL;
289 cntl_list[1] = PMIC_SND_LEFT_PB_VOL;
290 break;
291
292 case CAPTURE_VOL:
293 cntl_list[0] = PMIC_SND_CAPTURE_VOL;
294 break;
295
296 case MASTER_VOL:
297 cntl_list[0] = PMIC_SND_RIGHT_MASTER_VOL;
298 cntl_list[1] = PMIC_SND_LEFT_MASTER_VOL;
299 break;
300 default:
301 return -EINVAL;
302 }
303
304 ret_val = scard_ops->get_vol(cntl_list[0], &value);
305 uval->value.integer.value[0] = value;
306
307 if (ret_val)
308 return ret_val;
309
310 if (kcontrol->id.numid == PLAYBACK_VOL ||
311 kcontrol->id.numid == MASTER_VOL) {
312 ret_val = scard_ops->get_vol(cntl_list[1], &value);
313 uval->value.integer.value[1] = value;
314 }
315 return ret_val;
316}
317
318/**
319* snd_intelmad_mute_get - gets the current mute status for the control
320*
321* @kcontrol: pointer to the control
322* @uval: pointer to the structure where the control's info need
323* to be filled
324*
325* This function is called when .get function of a control is invoked from app
326*/
327static int snd_intelmad_mute_get(struct snd_kcontrol *kcontrol,
328 struct snd_ctl_elem_value *uval)
329{
330
331 int cntl_list = 0, ret_val = 0;
332 u8 value = 0;
333 struct snd_intelmad *intelmaddata;
334 struct snd_pmic_ops *scard_ops;
335
336 pr_debug("Mute_get called\n");
337
338 WARN_ON(!uval);
339 WARN_ON(!kcontrol);
340
341 intelmaddata = kcontrol->private_data;
342
343 WARN_ON(!intelmaddata->sstdrv_ops);
344
345 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
346
347 WARN_ON(!scard_ops);
348
349 switch (kcontrol->id.numid) {
350 case PLAYBACK_MUTE:
351 if (intelmaddata->output_sel == STEREO_HEADPHONE)
352 cntl_list = PMIC_SND_LEFT_HP_MUTE;
353 else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
354 (intelmaddata->output_sel == MONO_EARPIECE))
355 cntl_list = PMIC_SND_LEFT_SPEAKER_MUTE;
356 break;
357
358 case CAPTURE_MUTE:
359 if (intelmaddata->input_sel == DMIC)
360 cntl_list = PMIC_SND_DMIC_MUTE;
361 else if (intelmaddata->input_sel == AMIC)
362 cntl_list = PMIC_SND_AMIC_MUTE;
363 else if (intelmaddata->input_sel == HS_MIC)
364 cntl_list = PMIC_SND_HP_MIC_MUTE;
365 break;
366 case MASTER_MUTE:
367 uval->value.integer.value[0] = intelmaddata->master_mute;
368 return 0;
369 default:
370 return -EINVAL;
371 }
372
373 ret_val = scard_ops->get_mute(cntl_list, &value);
374 uval->value.integer.value[0] = value;
375 return ret_val;
376}
377
378/**
379* snd_intelmad_volume_set - sets the volume control's info
380*
381* @kcontrol: pointer to the control
382* @uval: pointer to the structure where the control's info is
383* available to be set
384*
385* This function is called when .set function of a control is invoked from app
386*/
387static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
388 struct snd_ctl_elem_value *uval)
389{
390
391 int ret_val, cntl_list[2] = {0,};
392 struct snd_intelmad *intelmaddata;
393 struct snd_pmic_ops *scard_ops;
394
395 pr_debug("volume set called:%ld %ld\n",
396 uval->value.integer.value[0],
397 uval->value.integer.value[1]);
398
399 WARN_ON(!uval);
400 WARN_ON(!kcontrol);
401
402 intelmaddata = kcontrol->private_data;
403
404 WARN_ON(!intelmaddata->sstdrv_ops);
405
406 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
407
408 WARN_ON(!scard_ops);
409
410 switch (kcontrol->id.numid) {
411 case PLAYBACK_VOL:
412 cntl_list[0] = PMIC_SND_LEFT_PB_VOL;
413 cntl_list[1] = PMIC_SND_RIGHT_PB_VOL;
414 break;
415
416 case CAPTURE_VOL:
417 cntl_list[0] = PMIC_SND_CAPTURE_VOL;
418 break;
419
420 case MASTER_VOL:
421 cntl_list[0] = PMIC_SND_LEFT_MASTER_VOL;
422 cntl_list[1] = PMIC_SND_RIGHT_MASTER_VOL;
423 break;
424
425 default:
426 return -EINVAL;
427 }
428
429 ret_val = scard_ops->set_vol(cntl_list[0],
430 uval->value.integer.value[0]);
431 if (ret_val)
432 return ret_val;
433
434 if (kcontrol->id.numid == PLAYBACK_VOL ||
435 kcontrol->id.numid == MASTER_VOL)
436 ret_val = scard_ops->set_vol(cntl_list[1],
437 uval->value.integer.value[1]);
438 return ret_val;
439}
440
441/**
442* snd_intelmad_mute_set - sets the mute control's info
443*
444* @kcontrol: pointer to the control
445* @uval: pointer to the structure where the control's info is
446* available to be set
447*
448* This function is called when .set function of a control is invoked from app
449*/
450static int snd_intelmad_mute_set(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_value *uval)
452{
453 int cntl_list[2] = {0,}, ret_val;
454 struct snd_intelmad *intelmaddata;
455 struct snd_pmic_ops *scard_ops;
456
457 pr_debug("snd_intelmad_mute_set called\n");
458
459 WARN_ON(!uval);
460 WARN_ON(!kcontrol);
461
462 intelmaddata = kcontrol->private_data;
463
464 WARN_ON(!intelmaddata->sstdrv_ops);
465
466 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
467
468 WARN_ON(!scard_ops);
469
470 kcontrol->private_value = uval->value.integer.value[0];
471
472 switch (kcontrol->id.numid) {
473 case PLAYBACK_MUTE:
474 if (intelmaddata->output_sel == STEREO_HEADPHONE) {
475 cntl_list[0] = PMIC_SND_LEFT_HP_MUTE;
476 cntl_list[1] = PMIC_SND_RIGHT_HP_MUTE;
477 } else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
478 (intelmaddata->output_sel == MONO_EARPIECE)) {
479 cntl_list[0] = PMIC_SND_LEFT_SPEAKER_MUTE;
480 cntl_list[1] = PMIC_SND_RIGHT_SPEAKER_MUTE;
481 }
482 break;
483
484 case CAPTURE_MUTE:/*based on sel device mute the i/p dev*/
485 if (intelmaddata->input_sel == DMIC)
486 cntl_list[0] = PMIC_SND_DMIC_MUTE;
487 else if (intelmaddata->input_sel == AMIC)
488 cntl_list[0] = PMIC_SND_AMIC_MUTE;
489 else if (intelmaddata->input_sel == HS_MIC)
490 cntl_list[0] = PMIC_SND_HP_MIC_MUTE;
491 break;
492 case MASTER_MUTE:
493 cntl_list[0] = PMIC_SND_MUTE_ALL;
494 intelmaddata->master_mute = uval->value.integer.value[0];
495 break;
496 default:
497 return -EINVAL;
498 }
499
500 ret_val = scard_ops->set_mute(cntl_list[0],
501 uval->value.integer.value[0]);
502 if (ret_val)
503 return ret_val;
504
505 if (kcontrol->id.numid == PLAYBACK_MUTE)
506 ret_val = scard_ops->set_mute(cntl_list[1],
507 uval->value.integer.value[0]);
508 return ret_val;
509}
510
511/**
512* snd_intelmad_device_get - get the device select control's info
513*
514* @kcontrol: pointer to the control
515* @uval: pointer to the structure where the control's info is
516* to be filled
517*
518* This function is called when .get function of a control is invoked from app
519*/
520static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_value *uval)
522{
523 struct snd_intelmad *intelmaddata;
524 struct snd_pmic_ops *scard_ops;
525 pr_debug("device_get called\n");
526
527 WARN_ON(!uval);
528 WARN_ON(!kcontrol);
529
530 intelmaddata = kcontrol->private_data;
531 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
532 if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
533 if (kcontrol->id.numid == OUTPUT_SEL)
534 uval->value.enumerated.item[0] =
535 scard_ops->output_dev_id;
536 else if (kcontrol->id.numid == INPUT_SEL)
537 uval->value.enumerated.item[0] =
538 scard_ops->input_dev_id;
539 else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
540 uval->value.enumerated.item[0] =
541 scard_ops->lineout_dev_id;
542 else
543 return -EINVAL;
544 } else if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
545 if (kcontrol->id.numid == OUTPUT_SEL)
546 /* There is a mismatch here.
547 * ALSA expects 1 for internal speaker.
548 * But internally, we may give 2 for internal speaker.
549 */
550 if (scard_ops->output_dev_id == MONO_EARPIECE ||
551 scard_ops->output_dev_id == INTERNAL_SPKR)
552 uval->value.enumerated.item[0] = MONO_EARPIECE;
553 else if (scard_ops->output_dev_id == STEREO_HEADPHONE)
554 uval->value.enumerated.item[0] =
555 STEREO_HEADPHONE;
556 else
557 return -EINVAL;
558 else if (kcontrol->id.numid == INPUT_SEL)
559 uval->value.enumerated.item[0] =
560 scard_ops->input_dev_id;
561 else
562 return -EINVAL;
563 } else
564 uval->value.enumerated.item[0] = kcontrol->private_value;
565 return 0;
566}
567
568/**
569* snd_intelmad_device_set - set the device select control's info
570*
571* @kcontrol: pointer to the control
572* @uval: pointer to the structure where the control's info is
573* available to be set
574*
575* This function is called when .set function of a control is invoked from app
576*/
577static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
578 struct snd_ctl_elem_value *uval)
579{
580 struct snd_intelmad *intelmaddata;
581 struct snd_pmic_ops *scard_ops;
582 int ret_val = 0, vendor, status;
583 struct intel_sst_pcm_control *pcm_control;
584
585 pr_debug("snd_intelmad_device_set called\n");
586
587 WARN_ON(!uval);
588 WARN_ON(!kcontrol);
589 status = -1;
590
591 intelmaddata = kcontrol->private_data;
592
593 WARN_ON(!intelmaddata->sstdrv_ops);
594
595 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
596
597 WARN_ON(!scard_ops);
598
599 /* store value with driver */
600 kcontrol->private_value = uval->value.enumerated.item[0];
601
602 switch (kcontrol->id.numid) {
603 case OUTPUT_SEL:
604 ret_val = scard_ops->set_output_dev(
605 uval->value.enumerated.item[0]);
606 intelmaddata->output_sel = uval->value.enumerated.item[0];
607 break;
608 case INPUT_SEL:
609 vendor = intelmaddata->sstdrv_ops->vendor_id;
610 if ((vendor == SND_MX) || (vendor == SND_FS)) {
611 pcm_control = intelmaddata->sstdrv_ops->pcm_control;
612 if (uval->value.enumerated.item[0] == HS_MIC)
613 status = 1;
614 else
615 status = 0;
616 pcm_control->device_control(
617 SST_ENABLE_RX_TIME_SLOT, &status);
618 }
619 ret_val = scard_ops->set_input_dev(
620 uval->value.enumerated.item[0]);
621 intelmaddata->input_sel = uval->value.enumerated.item[0];
622 break;
623 case LINEOUT_SEL_MFLD:
624 ret_val = scard_ops->set_lineout_dev(
625 uval->value.enumerated.item[0]);
626 intelmaddata->lineout_sel = uval->value.enumerated.item[0];
627 break;
628 default:
629 return -EINVAL;
630 }
631 kcontrol->private_value = uval->value.enumerated.item[0];
632 return ret_val;
633}
634
635static int snd_intelmad_device_dmic_get(struct snd_kcontrol *kcontrol,
636 struct snd_ctl_elem_value *uval)
637{
638 struct snd_intelmad *intelmaddata;
639 struct snd_pmic_ops *scard_ops;
640
641 WARN_ON(!uval);
642 WARN_ON(!kcontrol);
643
644 intelmaddata = kcontrol->private_data;
645 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
646
647 if (scard_ops->input_dev_id != DMIC) {
648 pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
649 return 0;
650 }
651
652 if (intelmaddata->cpu_id == CPU_CHIP_PENWELL)
653 uval->value.enumerated.item[0] = kcontrol->private_value;
654 else
655 pr_debug(" CPU id = 0x%xis invalid.\n",
656 intelmaddata->cpu_id);
657 return 0;
658}
659
660void msic_set_bit(u8 index, unsigned int *available_dmics)
661{
662 *available_dmics |= (1 << index);
663}
664
665void msic_clear_bit(u8 index, unsigned int *available_dmics)
666{
667 *available_dmics &= ~(1 << index);
668}
669
670int msic_is_set_bit(u8 index, unsigned int *available_dmics)
671{
672 int ret_val;
673
674 ret_val = (*available_dmics & (1 << index));
675 return ret_val;
676}
677
678static int snd_intelmad_device_dmic_set(struct snd_kcontrol *kcontrol,
679 struct snd_ctl_elem_value *uval)
680{
681 struct snd_intelmad *intelmaddata;
682 struct snd_pmic_ops *scard_ops;
683 int i, dmic_index;
684 unsigned int available_dmics;
685 int jump_count;
686 int max_dmics = ARRAY_SIZE(router_dmics);
687
688 WARN_ON(!uval);
689 WARN_ON(!kcontrol);
690
691 intelmaddata = kcontrol->private_data;
692 WARN_ON(!intelmaddata->sstdrv_ops);
693
694 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
695 WARN_ON(!scard_ops);
696
697 if (scard_ops->input_dev_id != DMIC) {
698 pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
699 return 0;
700 }
701
702 available_dmics = scard_ops->available_dmics;
703
704 if (kcontrol->private_value > uval->value.enumerated.item[0]) {
705 pr_debug("jump count -1.\n");
706 jump_count = -1;
707 } else {
708 pr_debug("jump count 1.\n");
709 jump_count = 1;
710 }
711
712 dmic_index = uval->value.enumerated.item[0];
713 pr_debug("set function. dmic_index = %d, avl_dmic = 0x%x\n",
714 dmic_index, available_dmics);
715 for (i = 0; i < max_dmics; i++) {
716 pr_debug("set function. loop index = 0x%x. dmic_index = 0x%x\n",
717 i, dmic_index);
718 if (!msic_is_set_bit(dmic_index, &available_dmics)) {
719 msic_clear_bit(kcontrol->private_value,
720 &available_dmics);
721 msic_set_bit(dmic_index, &available_dmics);
722 kcontrol->private_value = dmic_index;
723 scard_ops->available_dmics = available_dmics;
724 scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
725 kcontrol->private_value;
726 scard_ops->set_hw_dmic_route
727 (kcontrol->id.numid-HW_CH_BASE);
728 return 0;
729 }
730
731 dmic_index += jump_count;
732
733 if (dmic_index > (max_dmics - 1) && jump_count == 1) {
734 pr_debug("Resettingthe dmic index to 0.\n");
735 dmic_index = 0;
736 } else if (dmic_index == -1 && jump_count == -1) {
737 pr_debug("Resetting the dmic index to 5.\n");
738 dmic_index = max_dmics - 1;
739 }
740 }
741
742 return -EINVAL;
743}
744
745static int snd_intelmad_device_dmic_info_mfld(struct snd_kcontrol *kcontrol,
746 struct snd_ctl_elem_info *uinfo)
747{
748 struct snd_intelmad *intelmaddata;
749 struct snd_pmic_ops *scard_ops;
750
751 uinfo->count = MONO_CNTL;
752 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
753 uinfo->value.enumerated.items = ARRAY_SIZE(router_dmics);
754
755 intelmaddata = kcontrol->private_data;
756 WARN_ON(!intelmaddata->sstdrv_ops);
757
758 scard_ops = intelmaddata->sstdrv_ops->scard_ops;
759 WARN_ON(!scard_ops);
760
761 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
762 uinfo->value.enumerated.item =
763 uinfo->value.enumerated.items - 1;
764
765 strncpy(uinfo->value.enumerated.name,
766 router_dmics[uinfo->value.enumerated.item],
767 sizeof(uinfo->value.enumerated.name)-1);
768
769
770 msic_set_bit(kcontrol->private_value, &scard_ops->available_dmics);
771 pr_debug("info function. avl_dmic = 0x%x",
772 scard_ops->available_dmics);
773
774 scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
775 kcontrol->private_value;
776
777 return 0;
778}
779
780struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
781{
782 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
783 .name = "PCM Playback Source",
784 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
785 .info = snd_intelmad_device_info_mrst,
786 .get = snd_intelmad_device_get,
787 .put = snd_intelmad_device_set,
788 .private_value = 0,
789},
790{
791 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
792 .name = "PCM Capture Source",
793 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
794 .info = snd_intelmad_device_info_mrst,
795 .get = snd_intelmad_device_get,
796 .put = snd_intelmad_device_set,
797 .private_value = 0,
798},
799{
800 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
801 .name = "PCM Playback Volume",
802 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
803 .info = snd_intelmad_playback_volume_info,
804 .get = snd_intelmad_volume_get,
805 .put = snd_intelmad_volume_set,
806 .private_value = 0,
807},
808{
809 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
810 .name = "PCM Playback Switch",
811 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
812 .info = snd_intelmad_mute_info,
813 .get = snd_intelmad_mute_get,
814 .put = snd_intelmad_mute_set,
815 .private_value = 0,
816},
817{
818 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
819 .name = "PCM Capture Volume",
820 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
821 .info = snd_intelmad_capture_volume_info,
822 .get = snd_intelmad_volume_get,
823 .put = snd_intelmad_volume_set,
824 .private_value = 0,
825},
826{
827 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
828 .name = "PCM Capture Switch",
829 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
830 .info = snd_intelmad_mute_info,
831 .get = snd_intelmad_mute_get,
832 .put = snd_intelmad_mute_set,
833 .private_value = 0,
834},
835{
836 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
837 .name = "Master Playback Volume",
838 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
839 .info = snd_intelmad_master_volume_info,
840 .get = snd_intelmad_volume_get,
841 .put = snd_intelmad_volume_set,
842 .private_value = 0,
843},
844{
845 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
846 .name = "Master Playback Switch",
847 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
848 .info = snd_intelmad_mute_info,
849 .get = snd_intelmad_mute_get,
850 .put = snd_intelmad_mute_set,
851 .private_value = 0,
852},
853};
854
855struct snd_kcontrol_new
856snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
857{
858 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
859 .name = "PCM Playback Source",
860 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
861 .info = snd_intelmad_device_info_mfld,
862 .get = snd_intelmad_device_get,
863 .put = snd_intelmad_device_set,
864 .private_value = 0,
865},
866{
867 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
868 .name = "PCM Capture Source",
869 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
870 .info = snd_intelmad_device_info_mfld,
871 .get = snd_intelmad_device_get,
872 .put = snd_intelmad_device_set,
873 .private_value = 0,
874},
875{
876 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877 .name = "Line out",
878 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
879 .info = snd_intelmad_device_info_mfld,
880 .get = snd_intelmad_device_get,
881 .put = snd_intelmad_device_set,
882 .private_value = 0,
883},
884{
885 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
886 .name = HW_CH_0,
887 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
888 .info = snd_intelmad_device_dmic_info_mfld,
889 .get = snd_intelmad_device_dmic_get,
890 .put = snd_intelmad_device_dmic_set,
891 .private_value = 0
892},
893{
894 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
895 .name = HW_CH_1,
896 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
897 .info = snd_intelmad_device_dmic_info_mfld,
898 .get = snd_intelmad_device_dmic_get,
899 .put = snd_intelmad_device_dmic_set,
900 .private_value = 1
901},
902{
903 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
904 .name = HW_CH_2,
905 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
906 .info = snd_intelmad_device_dmic_info_mfld,
907 .get = snd_intelmad_device_dmic_get,
908 .put = snd_intelmad_device_dmic_set,
909 .private_value = 2
910},
911{
912 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
913 .name = HW_CH_3,
914 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
915 .info = snd_intelmad_device_dmic_info_mfld,
916 .get = snd_intelmad_device_dmic_get,
917 .put = snd_intelmad_device_dmic_set,
918 .private_value = 3
919}
920};
921
diff --git a/drivers/staging/intel_sst/intelmid_msic_control.c b/drivers/staging/intel_sst/intelmid_msic_control.c
new file mode 100644
index 00000000000..70cdb169781
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_msic_control.c
@@ -0,0 +1,1047 @@
1/*
2 * intelmid_vm_control.c - Intel Sound card driver for MID
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 * This file contains the control operations of msic vendors
25 */
26
27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29#include <linux/pci.h>
30#include <linux/file.h>
31#include <linux/delay.h>
32#include <sound/control.h>
33#include "intel_sst.h"
34#include <linux/input.h>
35#include "intelmid_snd_control.h"
36#include "intelmid.h"
37
38#define AUDIOMUX12 0x24c
39#define AUDIOMUX34 0x24d
40
41static int msic_init_card(void)
42{
43 struct sc_reg_access sc_access[] = {
44 /* dmic configuration */
45 {0x241, 0x85, 0},
46 {0x242, 0x02, 0},
47 /* audio paths config */
48 {0x24C, 0x10, 0},
49 {0x24D, 0x32, 0},
50 /* PCM2 interface slots */
51 /* preconfigured slots for 0-5 both tx, rx */
52 {0x272, 0x10, 0},
53 {0x273, 0x32, 0},
54 {0x274, 0xFF, 0},
55 {0x275, 0x10, 0},
56 {0x276, 0x32, 0},
57 {0x277, 0x54, 0},
58 /*Sinc5 decimator*/
59 {0x24E, 0x28, 0},
60 /*TI vibra w/a settings*/
61 {0x384, 0x80, 0},
62 {0x385, 0x80, 0},
63 {0x267, 0x00, 0},
64 {0x261, 0x00, 0},
65 /* pcm port setting */
66 {0x278, 0x00, 0},
67 {0x27B, 0x01, 0},
68 {0x27C, 0x0a, 0},
69 /* Set vol HSLRVOLCTRL, IHFVOL */
70 {0x259, 0x08, 0},
71 {0x25A, 0x08, 0},
72 {0x25B, 0x08, 0},
73 {0x25C, 0x08, 0},
74 /* HSEPRXCTRL Enable the headset left and right FIR filters */
75 {0x250, 0x30, 0},
76 /* HSMIXER */
77 {0x256, 0x11, 0},
78 /* amic configuration */
79 {0x249, 0x01, 0x0},
80 {0x24A, 0x01, 0x0},
81 /* unmask ocaudio/accdet interrupts */
82 {0x1d, 0x00, 0x00},
83 {0x1e, 0x00, 0x00},
84 };
85 snd_msic_ops.card_status = SND_CARD_INIT_DONE;
86 sst_sc_reg_access(sc_access, PMIC_WRITE, 28);
87 snd_msic_ops.pb_on = 0;
88 snd_msic_ops.pbhs_on = 0;
89 snd_msic_ops.cap_on = 0;
90 snd_msic_ops.input_dev_id = DMIC; /*def dev*/
91 snd_msic_ops.output_dev_id = STEREO_HEADPHONE;
92 snd_msic_ops.jack_interrupt_status = false;
93 pr_debug("msic init complete!!\n");
94 return 0;
95}
96static int msic_line_out_restore(u8 value)
97{
98 struct sc_reg_access hs_drv_en[] = {
99 {0x25d, 0x03, 0x03},
100 };
101 struct sc_reg_access ep_drv_en[] = {
102 {0x25d, 0x40, 0x40},
103 };
104 struct sc_reg_access ihf_drv_en[] = {
105 {0x25d, 0x0c, 0x0c},
106 };
107 struct sc_reg_access vib1_drv_en[] = {
108 {0x25d, 0x10, 0x10},
109 };
110 struct sc_reg_access vib2_drv_en[] = {
111 {0x25d, 0x20, 0x20},
112 };
113 struct sc_reg_access pmode_enable[] = {
114 {0x381, 0x10, 0x10},
115 };
116 int retval = 0;
117
118 pr_debug("msic_lineout_restore_lineout_dev:%d\n", value);
119
120 switch (value) {
121 case HEADSET:
122 pr_debug("Selecting Lineout-HEADSET-restore\n");
123 if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE)
124 retval = sst_sc_reg_access(hs_drv_en,
125 PMIC_READ_MODIFY, 1);
126 else
127 retval = sst_sc_reg_access(ep_drv_en,
128 PMIC_READ_MODIFY, 1);
129 break;
130 case IHF:
131 pr_debug("Selecting Lineout-IHF-restore\n");
132 retval = sst_sc_reg_access(ihf_drv_en, PMIC_READ_MODIFY, 1);
133 if (retval)
134 return retval;
135 retval = sst_sc_reg_access(pmode_enable, PMIC_READ_MODIFY, 1);
136 break;
137 case VIBRA1:
138 pr_debug("Selecting Lineout-Vibra1-restore\n");
139 retval = sst_sc_reg_access(vib1_drv_en, PMIC_READ_MODIFY, 1);
140 break;
141 case VIBRA2:
142 pr_debug("Selecting Lineout-VIBRA2-restore\n");
143 retval = sst_sc_reg_access(vib2_drv_en, PMIC_READ_MODIFY, 1);
144 break;
145 case NONE:
146 pr_debug("Selecting Lineout-NONE-restore\n");
147 break;
148 default:
149 return -EINVAL;
150 }
151 return retval;
152}
153static int msic_get_lineout_prvstate(void)
154{
155 struct sc_reg_access hs_ihf_drv[2] = {
156 {0x257, 0x0, 0x0},
157 {0x25d, 0x0, 0x0},
158 };
159 struct sc_reg_access vib1drv[2] = {
160 {0x264, 0x0, 0x0},
161 {0x25D, 0x0, 0x0},
162 };
163 struct sc_reg_access vib2drv[2] = {
164 {0x26A, 0x0, 0x0},
165 {0x25D, 0x0, 0x0},
166 };
167 int retval = 0, drv_en, dac_en, dev_id, mask;
168 for (dev_id = 0; dev_id < snd_msic_ops.line_out_names_cnt; dev_id++) {
169 switch (dev_id) {
170 case HEADSET:
171 pr_debug("msic_get_lineout_prvs_state: HEADSET\n");
172 sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
173
174 mask = (MASK0|MASK1);
175 dac_en = (hs_ihf_drv[0].value) & mask;
176
177 mask = ((MASK0|MASK1)|MASK6);
178 drv_en = (hs_ihf_drv[1].value) & mask;
179
180 if (dac_en && (!drv_en)) {
181 snd_msic_ops.prev_lineout_dev_id = HEADSET;
182 return retval;
183 }
184 break;
185 case IHF:
186 pr_debug("msic_get_lineout_prvstate: IHF\n");
187 sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
188
189 mask = (MASK2 | MASK3);
190 dac_en = (hs_ihf_drv[0].value) & mask;
191
192 mask = (MASK2 | MASK3);
193 drv_en = (hs_ihf_drv[1].value) & mask;
194
195 if (dac_en && (!drv_en)) {
196 snd_msic_ops.prev_lineout_dev_id = IHF;
197 return retval;
198 }
199 break;
200 case VIBRA1:
201 pr_debug("msic_get_lineout_prvstate: vibra1\n");
202 sst_sc_reg_access(vib1drv, PMIC_READ, 2);
203
204 mask = MASK1;
205 dac_en = (vib1drv[0].value) & mask;
206
207 mask = MASK4;
208 drv_en = (vib1drv[1].value) & mask;
209
210 if (dac_en && (!drv_en)) {
211 snd_msic_ops.prev_lineout_dev_id = VIBRA1;
212 return retval;
213 }
214 break;
215 case VIBRA2:
216 pr_debug("msic_get_lineout_prvstate: vibra2\n");
217 sst_sc_reg_access(vib2drv, PMIC_READ, 2);
218
219 mask = MASK1;
220 dac_en = (vib2drv[0].value) & mask;
221
222 mask = MASK5;
223 drv_en = ((vib2drv[1].value) & mask);
224
225 if (dac_en && (!drv_en)) {
226 snd_msic_ops.prev_lineout_dev_id = VIBRA2;
227 return retval;
228 }
229 break;
230 case NONE:
231 pr_debug("msic_get_lineout_prvstate: NONE\n");
232 snd_msic_ops.prev_lineout_dev_id = NONE;
233 return retval;
234 default:
235 pr_debug("Invalid device id\n");
236 snd_msic_ops.prev_lineout_dev_id = NONE;
237 return -EINVAL;
238 }
239 }
240 return retval;
241}
242static int msic_set_selected_lineout_dev(u8 value)
243{
244 struct sc_reg_access lout_hs[] = {
245 {0x25e, 0x33, 0xFF},
246 {0x25d, 0x0, 0x43},
247 };
248 struct sc_reg_access lout_ihf[] = {
249 {0x25e, 0x55, 0xff},
250 {0x25d, 0x0, 0x0c},
251 };
252 struct sc_reg_access lout_vibra1[] = {
253
254 {0x25e, 0x61, 0xff},
255 {0x25d, 0x0, 0x10},
256 };
257 struct sc_reg_access lout_vibra2[] = {
258
259 {0x25e, 0x16, 0xff},
260 {0x25d, 0x0, 0x20},
261 };
262 struct sc_reg_access lout_def[] = {
263 {0x25e, 0x66, 0x0},
264 };
265 struct sc_reg_access pmode_disable[] = {
266 {0x381, 0x00, 0x10},
267 };
268 struct sc_reg_access pmode_enable[] = {
269 {0x381, 0x10, 0x10},
270 };
271 int retval = 0;
272
273 pr_debug("msic_set_selected_lineout_dev:%d\n", value);
274 msic_get_lineout_prvstate();
275 msic_line_out_restore(snd_msic_ops.prev_lineout_dev_id);
276 snd_msic_ops.lineout_dev_id = value;
277
278 switch (value) {
279 case HEADSET:
280 pr_debug("Selecting Lineout-HEADSET\n");
281 if (snd_msic_ops.pb_on)
282 retval = sst_sc_reg_access(lout_hs,
283 PMIC_READ_MODIFY, 2);
284 if (retval)
285 return retval;
286 retval = sst_sc_reg_access(pmode_disable,
287 PMIC_READ_MODIFY, 1);
288 break;
289 case IHF:
290 pr_debug("Selecting Lineout-IHF\n");
291 if (snd_msic_ops.pb_on)
292 retval = sst_sc_reg_access(lout_ihf,
293 PMIC_READ_MODIFY, 2);
294 if (retval)
295 return retval;
296 retval = sst_sc_reg_access(pmode_enable,
297 PMIC_READ_MODIFY, 1);
298 break;
299 case VIBRA1:
300 pr_debug("Selecting Lineout-Vibra1\n");
301 if (snd_msic_ops.pb_on)
302 retval = sst_sc_reg_access(lout_vibra1,
303 PMIC_READ_MODIFY, 2);
304 if (retval)
305 return retval;
306 retval = sst_sc_reg_access(pmode_disable,
307 PMIC_READ_MODIFY, 1);
308 break;
309 case VIBRA2:
310 pr_debug("Selecting Lineout-VIBRA2\n");
311 if (snd_msic_ops.pb_on)
312 retval = sst_sc_reg_access(lout_vibra2,
313 PMIC_READ_MODIFY, 2);
314 if (retval)
315 return retval;
316 retval = sst_sc_reg_access(pmode_disable,
317 PMIC_READ_MODIFY, 1);
318 break;
319 case NONE:
320 pr_debug("Selecting Lineout-NONE\n");
321 retval = sst_sc_reg_access(lout_def,
322 PMIC_WRITE, 1);
323 if (retval)
324 return retval;
325 retval = sst_sc_reg_access(pmode_disable,
326 PMIC_READ_MODIFY, 1);
327 break;
328 default:
329 return -EINVAL;
330 }
331 return retval;
332}
333
334
335static int msic_power_up_pb(unsigned int device)
336{
337 struct sc_reg_access vaud[] = {
338 /* turn on the audio power supplies */
339 {0x0DB, 0x07, 0},
340 };
341 struct sc_reg_access pll[] = {
342 /* turn on PLL */
343 {0x240, 0x20, 0},
344 };
345 struct sc_reg_access vhs[] = {
346 /* VHSP */
347 {0x0DC, 0x3D, 0},
348 /* VHSN */
349 {0x0DD, 0x3F, 0},
350 };
351 struct sc_reg_access hsdac[] = {
352 {0x382, 0x40, 0x40},
353 /* disable driver */
354 {0x25D, 0x0, 0x43},
355 /* DAC CONFIG ; both HP, LP on */
356 {0x257, 0x03, 0x03},
357 };
358 struct sc_reg_access hs_filter[] = {
359 /* HSEPRXCTRL Enable the headset left and right FIR filters */
360 {0x250, 0x30, 0},
361 /* HSMIXER */
362 {0x256, 0x11, 0},
363 };
364 struct sc_reg_access hs_enable[] = {
365 /* enable driver */
366 {0x25D, 0x3, 0x3},
367 {0x26C, 0x0, 0x2},
368 /* unmute the headset */
369 { 0x259, 0x80, 0x80},
370 { 0x25A, 0x80, 0x80},
371 };
372 struct sc_reg_access vihf[] = {
373 /* VIHF ON */
374 {0x0C9, 0x27, 0x00},
375 };
376 struct sc_reg_access ihf_filter[] = {
377 /* disable driver */
378 {0x25D, 0x00, 0x0C},
379 /*Filer DAC enable*/
380 {0x251, 0x03, 0x03},
381 {0x257, 0x0C, 0x0C},
382 };
383 struct sc_reg_access ihf_en[] = {
384 /*enable drv*/
385 {0x25D, 0x0C, 0x0c},
386 };
387 struct sc_reg_access ihf_unmute[] = {
388 /*unmute headset*/
389 {0x25B, 0x80, 0x80},
390 {0x25C, 0x80, 0x80},
391 };
392 struct sc_reg_access epdac[] = {
393 /* disable driver */
394 {0x25D, 0x0, 0x43},
395 /* DAC CONFIG ; both HP, LP on */
396 {0x257, 0x03, 0x03},
397 };
398 struct sc_reg_access ep_enable[] = {
399 /* enable driver */
400 {0x25D, 0x40, 0x40},
401 /* unmute the headset */
402 { 0x259, 0x80, 0x80},
403 { 0x25A, 0x80, 0x80},
404 };
405 struct sc_reg_access vib1_en[] = {
406 /* enable driver, ADC */
407 {0x25D, 0x10, 0x10},
408 {0x264, 0x02, 0x82},
409 };
410 struct sc_reg_access vib2_en[] = {
411 /* enable driver, ADC */
412 {0x25D, 0x20, 0x20},
413 {0x26A, 0x02, 0x82},
414 };
415 struct sc_reg_access pcm2_en[] = {
416 /* enable pcm 2 */
417 {0x27C, 0x1, 0x1},
418 };
419 int retval = 0;
420
421 if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
422 retval = msic_init_card();
423 if (retval)
424 return retval;
425 }
426
427 pr_debug("powering up pb.... Device %d\n", device);
428 sst_sc_reg_access(vaud, PMIC_WRITE, 1);
429 msleep(1);
430 sst_sc_reg_access(pll, PMIC_WRITE, 1);
431 msleep(1);
432 switch (device) {
433 case SND_SST_DEVICE_HEADSET:
434 snd_msic_ops.pb_on = 1;
435 snd_msic_ops.pbhs_on = 1;
436 if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) {
437 sst_sc_reg_access(vhs, PMIC_WRITE, 2);
438 sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 3);
439 sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
440 sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 4);
441 } else {
442 sst_sc_reg_access(epdac, PMIC_READ_MODIFY, 2);
443 sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
444 sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3);
445 }
446 if (snd_msic_ops.lineout_dev_id == HEADSET)
447 msic_set_selected_lineout_dev(HEADSET);
448 break;
449 case SND_SST_DEVICE_IHF:
450 snd_msic_ops.pb_on = 1;
451 sst_sc_reg_access(vihf, PMIC_WRITE, 1);
452 sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3);
453 sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1);
454 sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2);
455 if (snd_msic_ops.lineout_dev_id == IHF)
456 msic_set_selected_lineout_dev(IHF);
457 break;
458
459 case SND_SST_DEVICE_VIBRA:
460 snd_msic_ops.pb_on = 1;
461 sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2);
462 if (snd_msic_ops.lineout_dev_id == VIBRA1)
463 msic_set_selected_lineout_dev(VIBRA1);
464 break;
465
466 case SND_SST_DEVICE_HAPTIC:
467 snd_msic_ops.pb_on = 1;
468 sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2);
469 if (snd_msic_ops.lineout_dev_id == VIBRA2)
470 msic_set_selected_lineout_dev(VIBRA2);
471 break;
472
473 default:
474 pr_warn("Wrong Device %d, selected %d\n",
475 device, snd_msic_ops.output_dev_id);
476 }
477 return sst_sc_reg_access(pcm2_en, PMIC_READ_MODIFY, 1);
478}
479
480static int msic_power_up_cp(unsigned int device)
481{
482 struct sc_reg_access vaud[] = {
483 /* turn on the audio power supplies */
484 {0x0DB, 0x07, 0},
485 };
486 struct sc_reg_access pll[] = {
487 /* turn on PLL */
488 {0x240, 0x20, 0},
489 };
490 struct sc_reg_access dmic_bias[] = {
491 /* Turn on AMIC supply */
492 {0x247, 0xA0, 0xA0},
493 };
494 struct sc_reg_access dmic[] = {
495 /* mic demux enable */
496 {0x245, 0x3F, 0x3F},
497 {0x246, 0x07, 0x07},
498
499 };
500 struct sc_reg_access amic_bias[] = {
501 /* Turn on AMIC supply */
502 {0x247, 0xFC, 0xFC},
503 };
504 struct sc_reg_access amic[] = {
505 /*MIC EN*/
506 {0x249, 0x01, 0x01},
507 {0x24A, 0x01, 0x01},
508 /*ADC EN*/
509 {0x248, 0x05, 0x0F},
510
511 };
512 struct sc_reg_access pcm2[] = {
513 /* enable pcm 2 */
514 {0x27C, 0x1, 0x1},
515 };
516 struct sc_reg_access tx_on[] = {
517 /*wait for mic to stabalize before turning on audio channels*/
518 {0x24F, 0x3C, 0x0},
519 };
520 int retval = 0;
521
522 if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
523 retval = msic_init_card();
524 if (retval)
525 return retval;
526 }
527
528 pr_debug("powering up cp....%d\n", snd_msic_ops.input_dev_id);
529 sst_sc_reg_access(vaud, PMIC_WRITE, 1);
530 msleep(500);/*FIXME need optimzed value here*/
531 sst_sc_reg_access(pll, PMIC_WRITE, 1);
532 msleep(1);
533 snd_msic_ops.cap_on = 1;
534 if (snd_msic_ops.input_dev_id == AMIC) {
535 sst_sc_reg_access(amic_bias, PMIC_READ_MODIFY, 1);
536 msleep(1);
537 sst_sc_reg_access(amic, PMIC_READ_MODIFY, 3);
538 } else {
539 sst_sc_reg_access(dmic_bias, PMIC_READ_MODIFY, 1);
540 msleep(1);
541 sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 2);
542 }
543 msleep(1);
544 sst_sc_reg_access(tx_on, PMIC_WRITE, 1);
545 return sst_sc_reg_access(pcm2, PMIC_READ_MODIFY, 1);
546}
547
548static int msic_power_down(void)
549{
550 struct sc_reg_access power_dn[] = {
551 /* VHSP */
552 {0x0DC, 0xC4, 0},
553 /* VHSN */
554 {0x0DD, 0x04, 0},
555 /* VIHF */
556 {0x0C9, 0x24, 0},
557 };
558 struct sc_reg_access pll[] = {
559 /* turn off PLL*/
560 {0x240, 0x00, 0x0},
561 };
562 struct sc_reg_access vaud[] = {
563 /* turn off VAUD*/
564 {0x0DB, 0x04, 0},
565 };
566
567 pr_debug("powering dn msic\n");
568 snd_msic_ops.pbhs_on = 0;
569 snd_msic_ops.pb_on = 0;
570 snd_msic_ops.cap_on = 0;
571 sst_sc_reg_access(power_dn, PMIC_WRITE, 3);
572 msleep(1);
573 sst_sc_reg_access(pll, PMIC_WRITE, 1);
574 msleep(1);
575 sst_sc_reg_access(vaud, PMIC_WRITE, 1);
576 return 0;
577}
578
579static int msic_power_down_pb(unsigned int device)
580{
581 struct sc_reg_access drv_enable[] = {
582 {0x25D, 0x00, 0x00},
583 };
584 struct sc_reg_access hs_mute[] = {
585 {0x259, 0x80, 0x80},
586 {0x25A, 0x80, 0x80},
587 {0x26C, 0x02, 0x02},
588 };
589 struct sc_reg_access hs_off[] = {
590 {0x257, 0x00, 0x03},
591 {0x250, 0x00, 0x30},
592 {0x382, 0x00, 0x40},
593 };
594 struct sc_reg_access ihf_mute[] = {
595 {0x25B, 0x80, 0x80},
596 {0x25C, 0x80, 0x80},
597 };
598 struct sc_reg_access ihf_off[] = {
599 {0x257, 0x00, 0x0C},
600 {0x251, 0x00, 0x03},
601 };
602 struct sc_reg_access vib1_off[] = {
603 {0x264, 0x00, 0x82},
604 };
605 struct sc_reg_access vib2_off[] = {
606 {0x26A, 0x00, 0x82},
607 };
608 struct sc_reg_access lout_off[] = {
609 {0x25e, 0x66, 0x00},
610 };
611 struct sc_reg_access pmode_disable[] = {
612 {0x381, 0x00, 0x10},
613 };
614
615
616
617 pr_debug("powering dn pb for device %d\n", device);
618 switch (device) {
619 case SND_SST_DEVICE_HEADSET:
620 snd_msic_ops.pbhs_on = 0;
621 sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3);
622 drv_enable[0].mask = 0x43;
623 sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
624 sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 3);
625 if (snd_msic_ops.lineout_dev_id == HEADSET)
626 sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
627 break;
628
629 case SND_SST_DEVICE_IHF:
630 sst_sc_reg_access(ihf_mute, PMIC_READ_MODIFY, 2);
631 drv_enable[0].mask = 0x0C;
632 sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
633 sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2);
634 if (snd_msic_ops.lineout_dev_id == IHF) {
635 sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
636 sst_sc_reg_access(pmode_disable, PMIC_READ_MODIFY, 1);
637 }
638 break;
639
640 case SND_SST_DEVICE_VIBRA:
641 sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 1);
642 drv_enable[0].mask = 0x10;
643 sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
644 if (snd_msic_ops.lineout_dev_id == VIBRA1)
645 sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
646 break;
647
648 case SND_SST_DEVICE_HAPTIC:
649 sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 1);
650 drv_enable[0].mask = 0x20;
651 sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
652 if (snd_msic_ops.lineout_dev_id == VIBRA2)
653 sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
654 break;
655 }
656 return 0;
657}
658
659static int msic_power_down_cp(unsigned int device)
660{
661 struct sc_reg_access dmic[] = {
662 {0x247, 0x00, 0xA0},
663 {0x245, 0x00, 0x38},
664 {0x246, 0x00, 0x07},
665 };
666 struct sc_reg_access amic[] = {
667 {0x248, 0x00, 0x05},
668 {0x249, 0x00, 0x01},
669 {0x24A, 0x00, 0x01},
670 {0x247, 0x00, 0xA3},
671 };
672 struct sc_reg_access tx_off[] = {
673 {0x24F, 0x00, 0x3C},
674 };
675
676 pr_debug("powering dn cp....\n");
677 snd_msic_ops.cap_on = 0;
678 sst_sc_reg_access(tx_off, PMIC_READ_MODIFY, 1);
679 if (snd_msic_ops.input_dev_id == DMIC)
680 sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 3);
681 else
682 sst_sc_reg_access(amic, PMIC_READ_MODIFY, 4);
683 return 0;
684}
685
686static int msic_set_selected_output_dev(u8 value)
687{
688 int retval = 0;
689
690 pr_debug("msic set selected output:%d\n", value);
691 snd_msic_ops.output_dev_id = value;
692 if (snd_msic_ops.pbhs_on)
693 msic_power_up_pb(SND_SST_DEVICE_HEADSET);
694 return retval;
695}
696
697static int msic_set_selected_input_dev(u8 value)
698{
699
700 struct sc_reg_access sc_access_dmic[] = {
701 {0x24C, 0x10, 0x0},
702 };
703 struct sc_reg_access sc_access_amic[] = {
704 {0x24C, 0x76, 0x0},
705
706 };
707 int retval = 0;
708
709 pr_debug("msic_set_selected_input_dev:%d\n", value);
710 snd_msic_ops.input_dev_id = value;
711 switch (value) {
712 case AMIC:
713 pr_debug("Selecting AMIC1\n");
714 retval = sst_sc_reg_access(sc_access_amic, PMIC_WRITE, 1);
715 break;
716 case DMIC:
717 pr_debug("Selecting DMIC1\n");
718 retval = sst_sc_reg_access(sc_access_dmic, PMIC_WRITE, 1);
719 break;
720 default:
721 return -EINVAL;
722
723 }
724 if (snd_msic_ops.cap_on)
725 retval = msic_power_up_cp(SND_SST_DEVICE_CAPTURE);
726 return retval;
727}
728
729static int msic_set_hw_dmic_route(u8 hw_ch_index)
730{
731 struct sc_reg_access sc_access_router;
732 int retval = -EINVAL;
733
734 switch (hw_ch_index) {
735 case HW_CH0:
736 sc_access_router.reg_addr = AUDIOMUX12;
737 sc_access_router.value = snd_msic_ops.hw_dmic_map[0];
738 sc_access_router.mask = (MASK2 | MASK1 | MASK0);
739 pr_debug("hw_ch0. value = 0x%x\n",
740 sc_access_router.value);
741 retval = sst_sc_reg_access(&sc_access_router,
742 PMIC_READ_MODIFY, 1);
743 break;
744
745 case HW_CH1:
746 sc_access_router.reg_addr = AUDIOMUX12;
747 sc_access_router.value = (snd_msic_ops.hw_dmic_map[1]) << 4;
748 sc_access_router.mask = (MASK6 | MASK5 | MASK4);
749 pr_debug("### hw_ch1. value = 0x%x\n",
750 sc_access_router.value);
751 retval = sst_sc_reg_access(&sc_access_router,
752 PMIC_READ_MODIFY, 1);
753 break;
754
755 case HW_CH2:
756 sc_access_router.reg_addr = AUDIOMUX34;
757 sc_access_router.value = snd_msic_ops.hw_dmic_map[2];
758 sc_access_router.mask = (MASK2 | MASK1 | MASK0);
759 pr_debug("hw_ch2. value = 0x%x\n",
760 sc_access_router.value);
761 retval = sst_sc_reg_access(&sc_access_router,
762 PMIC_READ_MODIFY, 1);
763 break;
764
765 case HW_CH3:
766 sc_access_router.reg_addr = AUDIOMUX34;
767 sc_access_router.value = (snd_msic_ops.hw_dmic_map[3]) << 4;
768 sc_access_router.mask = (MASK6 | MASK5 | MASK4);
769 pr_debug("hw_ch3. value = 0x%x\n",
770 sc_access_router.value);
771 retval = sst_sc_reg_access(&sc_access_router,
772 PMIC_READ_MODIFY, 1);
773 break;
774 }
775
776 return retval;
777}
778
779
780static int msic_set_pcm_voice_params(void)
781{
782 return 0;
783}
784
785static int msic_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
786{
787 return 0;
788}
789
790static int msic_set_audio_port(int status)
791{
792 return 0;
793}
794
795static int msic_set_voice_port(int status)
796{
797 return 0;
798}
799
800static int msic_set_mute(int dev_id, u8 value)
801{
802 return 0;
803}
804
805static int msic_set_vol(int dev_id, int value)
806{
807 return 0;
808}
809
810static int msic_get_mute(int dev_id, u8 *value)
811{
812 return 0;
813}
814
815static int msic_get_vol(int dev_id, int *value)
816{
817 return 0;
818}
819
820static int msic_set_headset_state(int state)
821{
822 struct sc_reg_access hs_enable[] = {
823 {0x25D, 0x03, 0x03},
824 };
825
826 if (state)
827 /*enable*/
828 sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 1);
829 else {
830 hs_enable[0].value = 0;
831 sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 1);
832 }
833 return 0;
834}
835
836static int msic_enable_mic_bias(void)
837{
838 struct sc_reg_access jack_interrupt_reg[] = {
839 {0x0DB, 0x07, 0x00},
840
841 };
842 struct sc_reg_access jack_bias_reg[] = {
843 {0x247, 0x0C, 0x0C},
844 };
845
846 sst_sc_reg_access(jack_interrupt_reg, PMIC_WRITE, 1);
847 sst_sc_reg_access(jack_bias_reg, PMIC_READ_MODIFY, 1);
848 return 0;
849}
850
851static int msic_disable_mic_bias(void)
852{
853 if (snd_msic_ops.jack_interrupt_status == true)
854 return 0;
855 if (!(snd_msic_ops.pb_on || snd_msic_ops.cap_on))
856 msic_power_down();
857 return 0;
858}
859
860static int msic_disable_jack_btn(void)
861{
862 struct sc_reg_access btn_disable[] = {
863 {0x26C, 0x00, 0x01}
864 };
865
866 if (!(snd_msic_ops.pb_on || snd_msic_ops.cap_on))
867 msic_power_down();
868 snd_msic_ops.jack_interrupt_status = false;
869 return sst_sc_reg_access(btn_disable, PMIC_READ_MODIFY, 1);
870}
871
872static int msic_enable_jack_btn(void)
873{
874 struct sc_reg_access btn_enable[] = {
875 {0x26b, 0x77, 0x00},
876 {0x26C, 0x01, 0x00},
877 };
878 return sst_sc_reg_access(btn_enable, PMIC_WRITE, 2);
879}
880static int msic_convert_adc_to_mvolt(unsigned int mic_bias)
881{
882 return (ADC_ONE_LSB_MULTIPLIER * mic_bias) / 1000;
883}
884int msic_get_headset_state(int mic_bias)
885{
886 struct sc_reg_access msic_hs_toggle[] = {
887 {0x070, 0x00, 0x01},
888 };
889 if (mic_bias >= 0 && mic_bias < 400) {
890
891 pr_debug("Detected Headphone!!!\n");
892 sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
893
894 } else if (mic_bias > 400 && mic_bias < 650) {
895
896 pr_debug("Detected American headset\n");
897 msic_hs_toggle[0].value = 0x01;
898 sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
899
900 } else if (mic_bias >= 650 && mic_bias < 2000) {
901
902 pr_debug("Detected Headset!!!\n");
903 sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
904 /*power on jack and btn*/
905 snd_msic_ops.jack_interrupt_status = true;
906 msic_enable_jack_btn();
907 msic_enable_mic_bias();
908 return SND_JACK_HEADSET;
909
910 } else
911 pr_debug("Detected Open Cable!!!\n");
912
913 return SND_JACK_HEADPHONE;
914}
915
916static int msic_get_mic_bias(void *arg)
917{
918 struct snd_intelmad *intelmad_drv = (struct snd_intelmad *)arg;
919 u16 adc_adr = intelmad_drv->adc_address;
920 u16 adc_val;
921 int ret;
922 struct sc_reg_access adc_ctrl3[2] = {
923 {0x1C2, 0x05, 0x0},
924 };
925
926 struct sc_reg_access audio_adc_reg1 = {0,};
927 struct sc_reg_access audio_adc_reg2 = {0,};
928
929 msic_enable_mic_bias();
930 /* Enable the msic for conversion before reading */
931 ret = sst_sc_reg_access(adc_ctrl3, PMIC_WRITE, 1);
932 if (ret)
933 return ret;
934 adc_ctrl3[0].value = 0x04;
935 /* Re-toggle the RRDATARD bit */
936 ret = sst_sc_reg_access(adc_ctrl3, PMIC_WRITE, 1);
937 if (ret)
938 return ret;
939
940 audio_adc_reg1.reg_addr = adc_adr;
941 /* Read the higher bits of data */
942 msleep(1000);
943 ret = sst_sc_reg_access(&audio_adc_reg1, PMIC_READ, 1);
944 if (ret)
945 return ret;
946 pr_debug("adc read value %x", audio_adc_reg1.value);
947
948 /* Shift bits to accomodate the lower two data bits */
949 adc_val = (audio_adc_reg1.value << 2);
950 adc_adr++;
951 audio_adc_reg2. reg_addr = adc_adr;
952 ret = sst_sc_reg_access(&audio_adc_reg2, PMIC_READ, 1);
953 if (ret)
954 return ret;
955 pr_debug("adc read value %x", audio_adc_reg2.value);
956
957 /* Adding lower two bits to the higher bits */
958 audio_adc_reg2.value &= 03;
959 adc_val += audio_adc_reg2.value;
960
961 pr_debug("ADC value 0x%x", adc_val);
962 msic_disable_mic_bias();
963 return adc_val;
964}
965
966static void msic_pmic_irq_cb(void *cb_data, u8 intsts)
967{
968 struct mad_jack *mjack = NULL;
969 unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
970 struct snd_intelmad *intelmaddata = cb_data;
971 int retval = 0;
972
973 pr_debug("value returned = 0x%x\n", intsts);
974
975 if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
976 retval = msic_init_card();
977 if (retval)
978 return;
979 }
980
981 mjack = &intelmaddata->jack[0];
982 if (intsts & 0x1) {
983 pr_debug("MAD short_push detected\n");
984 present = SND_JACK_BTN_0;
985 jack_event_flag = buttonpressflag = 1;
986 mjack->jack.type = SND_JACK_BTN_0;
987 mjack->jack.key[0] = BTN_0 ;
988 }
989
990 if (intsts & 0x2) {
991 pr_debug(":MAD long_push detected\n");
992 jack_event_flag = buttonpressflag = 1;
993 mjack->jack.type = present = SND_JACK_BTN_1;
994 mjack->jack.key[1] = BTN_1;
995 }
996
997 if (intsts & 0x4) {
998 unsigned int mic_bias;
999 jack_event_flag = 1;
1000 buttonpressflag = 0;
1001 mic_bias = msic_get_mic_bias(intelmaddata);
1002 pr_debug("mic_bias = %d\n", mic_bias);
1003 mic_bias = msic_convert_adc_to_mvolt(mic_bias);
1004 pr_debug("mic_bias after conversion = %d mV\n", mic_bias);
1005 mjack->jack_dev_state = msic_get_headset_state(mic_bias);
1006 mjack->jack.type = present = mjack->jack_dev_state;
1007 }
1008
1009 if (intsts & 0x8) {
1010 mjack->jack.type = mjack->jack_dev_state;
1011 present = 0;
1012 jack_event_flag = 1;
1013 buttonpressflag = 0;
1014 msic_disable_jack_btn();
1015 msic_disable_mic_bias();
1016 }
1017 if (jack_event_flag)
1018 sst_mad_send_jack_report(&mjack->jack,
1019 buttonpressflag, present);
1020}
1021
1022
1023
1024struct snd_pmic_ops snd_msic_ops = {
1025 .set_input_dev = msic_set_selected_input_dev,
1026 .set_output_dev = msic_set_selected_output_dev,
1027 .set_lineout_dev = msic_set_selected_lineout_dev,
1028 .set_hw_dmic_route = msic_set_hw_dmic_route,
1029 .set_mute = msic_set_mute,
1030 .get_mute = msic_get_mute,
1031 .set_vol = msic_set_vol,
1032 .get_vol = msic_get_vol,
1033 .init_card = msic_init_card,
1034 .set_pcm_audio_params = msic_set_pcm_audio_params,
1035 .set_pcm_voice_params = msic_set_pcm_voice_params,
1036 .set_voice_port = msic_set_voice_port,
1037 .set_audio_port = msic_set_audio_port,
1038 .power_up_pmic_pb = msic_power_up_pb,
1039 .power_up_pmic_cp = msic_power_up_cp,
1040 .power_down_pmic_pb = msic_power_down_pb,
1041 .power_down_pmic_cp = msic_power_down_cp,
1042 .power_down_pmic = msic_power_down,
1043 .pmic_irq_cb = msic_pmic_irq_cb,
1044 .pmic_jack_enable = msic_enable_mic_bias,
1045 .pmic_get_mic_bias = msic_get_mic_bias,
1046 .pmic_set_headset_state = msic_set_headset_state,
1047};
diff --git a/drivers/staging/intel_sst/intelmid_pvt.c b/drivers/staging/intel_sst/intelmid_pvt.c
new file mode 100644
index 00000000000..90e0e64c0ab
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_pvt.c
@@ -0,0 +1,173 @@
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
40void 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
61int 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
110int 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 */
140int 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;
168err:
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}
diff --git a/drivers/staging/intel_sst/intelmid_snd_control.h b/drivers/staging/intel_sst/intelmid_snd_control.h
new file mode 100644
index 00000000000..06ad3a10099
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_snd_control.h
@@ -0,0 +1,123 @@
1#ifndef __INTELMID_SND_CTRL_H__
2#define __INTELMID_SND_CTRL_H__
3/*
4 * intelmid_snd_control.h - Intel Sound card driver for MID
5 *
6 * Copyright (C) 2008-10 Intel Corporation
7 * Authors: Vinod Koul <vinod.koul@intel.com>
8 * Harsha Priya <priya.harsha@intel.com>
9 * Dharageswari R <dharageswari.r@intel.com>
10 * KP Jeeja <jeeja.kp@intel.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 *
28 * This file defines all snd control functions
29 */
30
31/*
32Mask bits
33*/
34#define MASK0 0x01 /* 0000 0001 */
35#define MASK1 0x02 /* 0000 0010 */
36#define MASK2 0x04 /* 0000 0100 */
37#define MASK3 0x08 /* 0000 1000 */
38#define MASK4 0x10 /* 0001 0000 */
39#define MASK5 0x20 /* 0010 0000 */
40#define MASK6 0x40 /* 0100 0000 */
41#define MASK7 0x80 /* 1000 0000 */
42/*
43value bits
44*/
45#define VALUE0 0x01 /* 0000 0001 */
46#define VALUE1 0x02 /* 0000 0010 */
47#define VALUE2 0x04 /* 0000 0100 */
48#define VALUE3 0x08 /* 0000 1000 */
49#define VALUE4 0x10 /* 0001 0000 */
50#define VALUE5 0x20 /* 0010 0000 */
51#define VALUE6 0x40 /* 0100 0000 */
52#define VALUE7 0x80 /* 1000 0000 */
53
54#define MUTE 0 /* ALSA Passes 0 for mute */
55#define UNMUTE 1 /* ALSA Passes 1 for unmute */
56
57#define MAX_VOL_PMIC_VENDOR0 0x3f /* max vol in dB for stereo & voice DAC */
58#define MIN_VOL_PMIC_VENDOR0 0 /* min vol in dB for stereo & voice DAC */
59/* Head phone volume control */
60#define MAX_HP_VOL_PMIC_VENDOR1 6 /* max volume in dB for HP */
61#define MIN_HP_VOL_PMIC_VENDOR1 (-84) /* min volume in dB for HP */
62#define MAX_HP_VOL_INDX_PMIC_VENDOR1 40 /* Number of HP volume control values */
63
64/* Mono Earpiece Volume control */
65#define MAX_EP_VOL_PMIC_VENDOR1 0 /* max volume in dB for EP */
66#define MIN_EP_VOL_PMIC_VENDOR1 (-75) /* min volume in dB for EP */
67#define MAX_EP_VOL_INDX_PMIC_VENDOR1 32 /* Number of EP volume control values */
68
69int sst_sc_reg_access(struct sc_reg_access *sc_access,
70 int type, int num_val);
71extern struct snd_pmic_ops snd_pmic_ops_fs;
72extern struct snd_pmic_ops snd_pmic_ops_mx;
73extern struct snd_pmic_ops snd_pmic_ops_nc;
74extern struct snd_pmic_ops snd_msic_ops;
75
76/* device */
77enum SND_INPUT_DEVICE {
78 AMIC,
79 DMIC,
80 HS_MIC,
81 IN_UNDEFINED
82};
83enum SND_LINE_OUT_DEVICE {
84 HEADSET,
85 IHF,
86 VIBRA1,
87 VIBRA2,
88 NONE,
89};
90
91enum SND_OUTPUT_DEVICE {
92 STEREO_HEADPHONE,
93 MONO_EARPIECE,
94
95 INTERNAL_SPKR,
96 RECEIVER,
97 OUT_UNDEFINED
98};
99
100enum pmic_controls {
101 PMIC_SND_HP_MIC_MUTE = 0x0001,
102 PMIC_SND_AMIC_MUTE = 0x0002,
103 PMIC_SND_DMIC_MUTE = 0x0003,
104 PMIC_SND_CAPTURE_VOL = 0x0004,
105/* Output controls */
106 PMIC_SND_LEFT_PB_VOL = 0x0010,
107 PMIC_SND_RIGHT_PB_VOL = 0x0011,
108 PMIC_SND_LEFT_HP_MUTE = 0x0012,
109 PMIC_SND_RIGHT_HP_MUTE = 0x0013,
110 PMIC_SND_LEFT_SPEAKER_MUTE = 0x0014,
111 PMIC_SND_RIGHT_SPEAKER_MUTE = 0x0015,
112 PMIC_SND_RECEIVER_VOL = 0x0016,
113 PMIC_SND_RECEIVER_MUTE = 0x0017,
114 PMIC_SND_LEFT_MASTER_VOL = 0x0018,
115 PMIC_SND_RIGHT_MASTER_VOL = 0x0019,
116/* Other controls */
117 PMIC_SND_MUTE_ALL = 0x0020,
118 PMIC_MAX_CONTROLS = 0x0020,
119};
120
121#endif /* __INTELMID_SND_CTRL_H__ */
122
123
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
new file mode 100644
index 00000000000..b8dfdb9bc1a
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_v0_control.c
@@ -0,0 +1,866 @@
1/*
2 * intel_sst_v0_control.c - Intel SST Driver for audio engine
3 *
4 * Copyright (C) 2008-10 Intel Corporation
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * KP Jeeja <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This file contains the control operations of vendor 1
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/pci.h>
32#include <linux/file.h>
33#include <sound/control.h>
34#include "intel_sst.h"
35#include "intelmid_snd_control.h"
36#include "intelmid.h"
37
38enum _reg_v1 {
39 VOICEPORT1 = 0x180,
40 VOICEPORT2 = 0x181,
41 AUDIOPORT1 = 0x182,
42 AUDIOPORT2 = 0x183,
43 MISCVOICECTRL = 0x184,
44 MISCAUDCTRL = 0x185,
45 DMICCTRL1 = 0x186,
46 AUDIOBIAS = 0x187,
47 MICCTRL = 0x188,
48 MICLICTRL1 = 0x189,
49 MICLICTRL2 = 0x18A,
50 MICLICTRL3 = 0x18B,
51 VOICEDACCTRL1 = 0x18C,
52 STEREOADCCTRL = 0x18D,
53 AUD15 = 0x18E,
54 AUD16 = 0x18F,
55 AUD17 = 0x190,
56 AUD18 = 0x191,
57 RMIXOUTSEL = 0x192,
58 ANALOGLBR = 0x193,
59 ANALOGLBL = 0x194,
60 POWERCTRL1 = 0x195,
61 POWERCTRL2 = 0x196,
62 HEADSETDETECTINT = 0x197,
63 HEADSETDETECTINTMASK = 0x198,
64 TRIMENABLE = 0x199,
65};
66
67int rev_id = 0x20;
68static bool jack_det_enabled;
69
70/****
71 * fs_init_card - initialize the sound card
72 *
73 * This initializes the audio paths to know values in case of this sound card
74 */
75static int fs_init_card(void)
76{
77 struct sc_reg_access sc_access[] = {
78 {0x180, 0x00, 0x0},
79 {0x181, 0x00, 0x0},
80 {0x182, 0xF8, 0x0},
81 {0x183, 0x08, 0x0},
82 {0x184, 0x00, 0x0},
83 {0x185, 0x40, 0x0},
84 {0x186, 0x06, 0x0},
85 {0x187, 0x80, 0x0},
86 {0x188, 0x40, 0x0},
87 {0x189, 0x39, 0x0},
88 {0x18a, 0x39, 0x0},
89 {0x18b, 0x1F, 0x0},
90 {0x18c, 0x00, 0x0},
91 {0x18d, 0x00, 0x0},
92 {0x18e, 0x39, 0x0},
93 {0x18f, 0x39, 0x0},
94 {0x190, 0x39, 0x0},
95 {0x191, 0x11, 0x0},
96 {0x192, 0x0E, 0x0},
97 {0x193, 0x00, 0x0},
98 {0x194, 0x00, 0x0},
99 {0x195, 0x00, 0x0},
100 {0x196, 0x7C, 0x0},
101 {0x197, 0x00, 0x0},
102 {0x198, 0x0B, 0x0},
103 {0x199, 0x00, 0x0},
104 {0x037, 0x3F, 0x0},
105 };
106
107 snd_pmic_ops_fs.card_status = SND_CARD_INIT_DONE;
108 snd_pmic_ops_fs.master_mute = UNMUTE;
109 snd_pmic_ops_fs.mute_status = UNMUTE;
110 snd_pmic_ops_fs.num_channel = 2;
111 return sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
112}
113
114static int fs_enable_audiodac(int value)
115{
116 struct sc_reg_access sc_access[3];
117 sc_access[0].reg_addr = AUD16;
118 sc_access[1].reg_addr = AUD17;
119 sc_access[2].reg_addr = AUD15;
120 sc_access[0].mask = sc_access[1].mask = sc_access[2].mask = MASK7;
121
122 if (snd_pmic_ops_fs.mute_status == MUTE)
123 return 0;
124 if (value == MUTE) {
125 sc_access[0].value = sc_access[1].value =
126 sc_access[2].value = 0x80;
127
128 } else {
129 sc_access[0].value = sc_access[1].value =
130 sc_access[2].value = 0x0;
131 }
132 if (snd_pmic_ops_fs.num_channel == 1)
133 sc_access[1].value = sc_access[2].value = 0x80;
134 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
135
136}
137
138static int fs_power_up_pb(unsigned int port)
139{
140 struct sc_reg_access sc_access[] = {
141 {AUDIOBIAS, 0x00, MASK7},
142 {POWERCTRL1, 0xC6, 0xC6},
143 {POWERCTRL2, 0x30, 0x30},
144
145 };
146 int retval = 0;
147
148 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
149 retval = fs_init_card();
150 if (retval)
151 return retval;
152 retval = fs_enable_audiodac(MUTE);
153 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
154
155 if (retval)
156 return retval;
157
158 pr_debug("in fs power up pb\n");
159 return fs_enable_audiodac(UNMUTE);
160}
161
162static int fs_power_down_pb(unsigned int device)
163{
164 struct sc_reg_access sc_access[] = {
165 {POWERCTRL1, 0x00, 0xC6},
166 {POWERCTRL2, 0x00, 0x30},
167 };
168 int retval = 0;
169
170 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
171 retval = fs_init_card();
172 if (retval)
173 return retval;
174 retval = fs_enable_audiodac(MUTE);
175 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
176
177 if (retval)
178 return retval;
179
180 pr_debug("in fsl power down pb\n");
181 return fs_enable_audiodac(UNMUTE);
182}
183
184static int fs_power_up_cp(unsigned int port)
185{
186 struct sc_reg_access sc_access[] = {
187 {POWERCTRL2, 0x32, 0x32}, /*NOTE power up A ADC only as*/
188 {AUDIOBIAS, 0x00, MASK7},
189 /*as turning on V ADC causes noise*/
190 };
191 int retval = 0;
192
193 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
194 retval = fs_init_card();
195 if (retval)
196 return retval;
197 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
198}
199
200static int fs_power_down_cp(unsigned int device)
201{
202 struct sc_reg_access sc_access[] = {
203 {POWERCTRL2, 0x00, 0x03},
204 };
205 int retval = 0;
206
207 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
208 retval = fs_init_card();
209 if (retval)
210 return retval;
211 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
212}
213
214static int fs_power_down(void)
215{
216 int retval = 0;
217 struct sc_reg_access sc_access[] = {
218 {AUDIOBIAS, MASK7, MASK7},
219 };
220
221 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
222 retval = fs_init_card();
223 if (retval)
224 return retval;
225 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
226}
227
228static int fs_set_pcm_voice_params(void)
229{
230 struct sc_reg_access sc_access[] = {
231 {0x180, 0xA0, 0},
232 {0x181, 0x04, 0},
233 {0x182, 0x0, 0},
234 {0x183, 0x0, 0},
235 {0x184, 0x18, 0},
236 {0x185, 0x40, 0},
237 {0x186, 0x06, 0},
238 {0x187, 0x0, 0},
239 {0x188, 0x10, 0},
240 {0x189, 0x39, 0},
241 {0x18a, 0x39, 0},
242 {0x18b, 0x02, 0},
243 {0x18c, 0x0, 0},
244 {0x18d, 0x0, 0},
245 {0x18e, 0x39, 0},
246 {0x18f, 0x0, 0},
247 {0x190, 0x0, 0},
248 {0x191, 0x20, 0},
249 {0x192, 0x20, 0},
250 {0x193, 0x0, 0},
251 {0x194, 0x0, 0},
252 {0x195, 0x06, 0},
253 {0x196, 0x25, 0},
254 {0x197, 0x0, 0},
255 {0x198, 0xF, 0},
256 {0x199, 0x0, 0},
257 };
258 int retval = 0;
259
260 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
261 retval = fs_init_card();
262 if (retval)
263 return retval;
264 return sst_sc_reg_access(sc_access, PMIC_WRITE, 26);
265}
266
267static int fs_set_audio_port(int status)
268{
269 struct sc_reg_access sc_access[2];
270 int retval = 0;
271
272 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
273 retval = fs_init_card();
274 if (retval)
275 return retval;
276 if (status == DEACTIVATE) {
277 /* Deactivate audio port-tristate and power */
278 sc_access[0].value = 0x00;
279 sc_access[0].mask = MASK6|MASK7;
280 sc_access[0].reg_addr = AUDIOPORT1;
281 sc_access[1].value = 0x00;
282 sc_access[1].mask = MASK4|MASK5;
283 sc_access[1].reg_addr = POWERCTRL2;
284 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
285 } else if (status == ACTIVATE) {
286 /* activate audio port */
287 sc_access[0].value = 0xC0;
288 sc_access[0].mask = MASK6|MASK7;
289 sc_access[0].reg_addr = AUDIOPORT1;
290 sc_access[1].value = 0x30;
291 sc_access[1].mask = MASK4|MASK5;
292 sc_access[1].reg_addr = POWERCTRL2;
293 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
294 } else
295 return -EINVAL;
296}
297
298static int fs_set_voice_port(int status)
299{
300 struct sc_reg_access sc_access[2];
301 int retval = 0;
302
303 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
304 retval = fs_init_card();
305 if (retval)
306 return retval;
307 if (status == DEACTIVATE) {
308 /* Deactivate audio port-tristate and power */
309 sc_access[0].value = 0x00;
310 sc_access[0].mask = MASK6|MASK7;
311 sc_access[0].reg_addr = VOICEPORT1;
312 sc_access[1].value = 0x00;
313 sc_access[1].mask = MASK0|MASK1;
314 sc_access[1].reg_addr = POWERCTRL2;
315 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
316 } else if (status == ACTIVATE) {
317 /* activate audio port */
318 sc_access[0].value = 0xC0;
319 sc_access[0].mask = MASK6|MASK7;
320 sc_access[0].reg_addr = VOICEPORT1;
321 sc_access[1].value = 0x03;
322 sc_access[1].mask = MASK0|MASK1;
323 sc_access[1].reg_addr = POWERCTRL2;
324 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
325 } else
326 return -EINVAL;
327}
328
329static int fs_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
330{
331 u8 config1 = 0;
332 struct sc_reg_access sc_access[4];
333 int retval = 0, num_value = 0;
334
335 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
336 retval = fs_init_card();
337 if (retval)
338 return retval;
339 switch (sfreq) {
340 case 8000:
341 config1 = 0x00;
342 break;
343 case 11025:
344 config1 = 0x01;
345 break;
346 case 12000:
347 config1 = 0x02;
348 break;
349 case 16000:
350 config1 = 0x03;
351 break;
352 case 22050:
353 config1 = 0x04;
354 break;
355 case 24000:
356 config1 = 0x05;
357 break;
358 case 26000:
359 config1 = 0x06;
360 break;
361 case 32000:
362 config1 = 0x07;
363 break;
364 case 44100:
365 config1 = 0x08;
366 break;
367 case 48000:
368 config1 = 0x09;
369 break;
370 }
371 snd_pmic_ops_fs.num_channel = num_channel;
372 if (snd_pmic_ops_fs.num_channel == 1) {
373 sc_access[0].reg_addr = AUD17;
374 sc_access[1].reg_addr = AUD15;
375 sc_access[0].mask = sc_access[1].mask = MASK7;
376 sc_access[0].value = sc_access[1].value = 0x80;
377 sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
378
379 } else {
380 sc_access[0].reg_addr = AUD17;
381 sc_access[1].reg_addr = AUD15;
382 sc_access[0].mask = sc_access[1].mask = MASK7;
383 sc_access[0].value = sc_access[1].value = 0x00;
384 sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
385
386 }
387 pr_debug("sfreq:%d,Register value = %x\n", sfreq, config1);
388
389 if (word_size == 24) {
390 sc_access[0].reg_addr = AUDIOPORT1;
391 sc_access[0].mask = MASK0|MASK1|MASK2|MASK3;
392 sc_access[0].value = 0xFB;
393
394
395 sc_access[1].reg_addr = AUDIOPORT2;
396 sc_access[1].value = config1 | 0x10;
397 sc_access[1].mask = MASK0 | MASK1 | MASK2 | MASK3
398 | MASK4 | MASK5 | MASK6;
399
400 sc_access[2].reg_addr = MISCAUDCTRL;
401 sc_access[2].value = 0x02;
402 sc_access[2].mask = 0x02;
403
404 num_value = 3 ;
405
406 } else {
407
408 sc_access[0].reg_addr = AUDIOPORT2;
409 sc_access[0].value = config1;
410 sc_access[0].mask = MASK0|MASK1|MASK2|MASK3;
411
412 sc_access[1].reg_addr = MISCAUDCTRL;
413 sc_access[1].value = 0x00;
414 sc_access[1].mask = 0x02;
415 num_value = 2;
416 }
417 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_value);
418
419}
420
421static int fs_set_selected_input_dev(u8 value)
422{
423 struct sc_reg_access sc_access_dmic[] = {
424 {MICCTRL, 0x81, 0xf7},
425 {MICLICTRL3, 0x00, 0xE0},
426 };
427 struct sc_reg_access sc_access_mic[] = {
428 {MICCTRL, 0x40, MASK2|MASK4|MASK5|MASK6|MASK7},
429 {MICLICTRL3, 0x00, 0xE0},
430 };
431 struct sc_reg_access sc_access_hsmic[] = {
432 {MICCTRL, 0x10, MASK2|MASK4|MASK5|MASK6|MASK7},
433 {MICLICTRL3, 0x00, 0xE0},
434 };
435
436 int retval = 0;
437
438 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
439 retval = fs_init_card();
440 if (retval)
441 return retval;
442
443 switch (value) {
444 case AMIC:
445 pr_debug("Selecting amic not supported in mono cfg\n");
446 return sst_sc_reg_access(sc_access_mic, PMIC_READ_MODIFY, 2);
447 break;
448
449 case HS_MIC:
450 pr_debug("Selecting hsmic\n");
451 return sst_sc_reg_access(sc_access_hsmic,
452 PMIC_READ_MODIFY, 2);
453 break;
454
455 case DMIC:
456 pr_debug("Selecting dmic\n");
457 return sst_sc_reg_access(sc_access_dmic, PMIC_READ_MODIFY, 2);
458 break;
459
460 default:
461 return -EINVAL;
462
463 }
464}
465
466static int fs_set_selected_output_dev(u8 value)
467{
468 struct sc_reg_access sc_access_hp[] = {
469 {0x191, 0x11, 0x0},
470 {0x192, 0x0E, 0x0},
471 };
472 struct sc_reg_access sc_access_is[] = {
473 {0x191, 0x17, 0xFF},
474 {0x192, 0x08, 0xFF},
475 };
476 int retval = 0;
477
478 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
479 retval = fs_init_card();
480 if (retval)
481 return retval;
482
483 switch (value) {
484 case STEREO_HEADPHONE:
485 pr_debug("SST DBG:Selecting headphone\n");
486 return sst_sc_reg_access(sc_access_hp, PMIC_WRITE, 2);
487 break;
488 case MONO_EARPIECE:
489 case INTERNAL_SPKR:
490 pr_debug("SST DBG:Selecting internal spkr\n");
491 return sst_sc_reg_access(sc_access_is, PMIC_READ_MODIFY, 2);
492 break;
493
494 default:
495 return -EINVAL;
496
497 }
498}
499
500static int fs_set_mute(int dev_id, u8 value)
501{
502 struct sc_reg_access sc_access[6] = {{0,},};
503 int reg_num = 0;
504 int retval = 0;
505
506 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
507 retval = fs_init_card();
508 if (retval)
509 return retval;
510
511
512 pr_debug("dev_id:0x%x value:0x%x\n", dev_id, value);
513 switch (dev_id) {
514 case PMIC_SND_DMIC_MUTE:
515 sc_access[0].reg_addr = MICCTRL;
516 sc_access[1].reg_addr = MICLICTRL1;
517 sc_access[2].reg_addr = MICLICTRL2;
518 sc_access[0].mask = MASK5;
519 sc_access[1].mask = sc_access[2].mask = MASK6;
520 if (value == MUTE) {
521 sc_access[0].value = 0x20;
522 sc_access[2].value = sc_access[1].value = 0x40;
523 } else
524 sc_access[0].value = sc_access[1].value
525 = sc_access[2].value = 0x0;
526 reg_num = 3;
527 break;
528 case PMIC_SND_HP_MIC_MUTE:
529 case PMIC_SND_AMIC_MUTE:
530 sc_access[0].reg_addr = MICLICTRL1;
531 sc_access[1].reg_addr = MICLICTRL2;
532 sc_access[0].mask = sc_access[1].mask = MASK6;
533 if (value == MUTE)
534 sc_access[0].value = sc_access[1].value = 0x40;
535 else
536 sc_access[0].value = sc_access[1].value = 0x0;
537 reg_num = 2;
538 break;
539 case PMIC_SND_LEFT_SPEAKER_MUTE:
540 case PMIC_SND_LEFT_HP_MUTE:
541 sc_access[0].reg_addr = AUD16;
542 sc_access[1].reg_addr = AUD15;
543
544 sc_access[0].mask = sc_access[1].mask = MASK7;
545 if (value == MUTE)
546 sc_access[0].value = sc_access[1].value = 0x80;
547 else
548 sc_access[0].value = sc_access[1].value = 0x0;
549 reg_num = 2;
550 snd_pmic_ops_fs.mute_status = value;
551 break;
552 case PMIC_SND_RIGHT_HP_MUTE:
553 case PMIC_SND_RIGHT_SPEAKER_MUTE:
554 sc_access[0].reg_addr = AUD17;
555 sc_access[1].reg_addr = AUD15;
556 sc_access[0].mask = sc_access[1].mask = MASK7;
557 if (value == MUTE)
558 sc_access[0].value = sc_access[1].value = 0x80;
559 else
560 sc_access[0].value = sc_access[1].value = 0x0;
561 snd_pmic_ops_fs.mute_status = value;
562 if (snd_pmic_ops_fs.num_channel == 1)
563 sc_access[0].value = sc_access[1].value = 0x80;
564 reg_num = 2;
565 break;
566 case PMIC_SND_MUTE_ALL:
567 sc_access[0].reg_addr = AUD16;
568 sc_access[1].reg_addr = AUD17;
569 sc_access[2].reg_addr = AUD15;
570 sc_access[3].reg_addr = MICCTRL;
571 sc_access[4].reg_addr = MICLICTRL1;
572 sc_access[5].reg_addr = MICLICTRL2;
573 sc_access[0].mask = sc_access[1].mask =
574 sc_access[2].mask = MASK7;
575 sc_access[3].mask = MASK5;
576 sc_access[4].mask = sc_access[5].mask = MASK6;
577
578 if (value == MUTE) {
579 sc_access[0].value =
580 sc_access[1].value = sc_access[2].value = 0x80;
581 sc_access[3].value = 0x20;
582 sc_access[4].value = sc_access[5].value = 0x40;
583
584 } else {
585 sc_access[0].value = sc_access[1].value =
586 sc_access[2].value = sc_access[3].value =
587 sc_access[4].value = sc_access[5].value = 0x0;
588 }
589 if (snd_pmic_ops_fs.num_channel == 1)
590 sc_access[1].value = sc_access[2].value = 0x80;
591 reg_num = 6;
592 snd_pmic_ops_fs.mute_status = value;
593 snd_pmic_ops_fs.master_mute = value;
594 break;
595
596 }
597 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
598}
599
600static int fs_set_vol(int dev_id, int value)
601{
602 struct sc_reg_access sc_acces, sc_access[4] = {{0},};
603 int reg_num = 0;
604 int retval = 0;
605
606 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
607 retval = fs_init_card();
608 if (retval)
609 return retval;
610
611 switch (dev_id) {
612 case PMIC_SND_LEFT_PB_VOL:
613 pr_debug("PMIC_SND_LEFT_PB_VOL:%d\n", value);
614 sc_access[0].value = sc_access[1].value = value;
615 sc_access[0].reg_addr = AUD16;
616 sc_access[1].reg_addr = AUD15;
617 sc_access[0].mask = sc_access[1].mask =
618 (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
619 reg_num = 2;
620 break;
621
622 case PMIC_SND_RIGHT_PB_VOL:
623 pr_debug("PMIC_SND_RIGHT_PB_VOL:%d\n", value);
624 sc_access[0].value = sc_access[1].value = value;
625 sc_access[0].reg_addr = AUD17;
626 sc_access[1].reg_addr = AUD15;
627 sc_access[0].mask = sc_access[1].mask =
628 (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
629 if (snd_pmic_ops_fs.num_channel == 1) {
630 sc_access[0].value = sc_access[1].value = 0x80;
631 sc_access[0].mask = sc_access[1].mask = MASK7;
632 }
633 reg_num = 2;
634 break;
635 case PMIC_SND_CAPTURE_VOL:
636 pr_debug("PMIC_SND_CAPTURE_VOL:%d\n", value);
637 sc_access[0].reg_addr = MICLICTRL1;
638 sc_access[1].reg_addr = MICLICTRL2;
639 sc_access[2].reg_addr = DMICCTRL1;
640 sc_access[2].value = value;
641 sc_access[0].value = sc_access[1].value = value;
642 sc_acces.reg_addr = MICLICTRL3;
643 sc_acces.value = value;
644 sc_acces.mask = (MASK0|MASK1|MASK2|MASK3|MASK5|MASK6|MASK7);
645 retval = sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
646 sc_access[0].mask = sc_access[1].mask =
647 sc_access[2].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
648 reg_num = 3;
649 break;
650
651 default:
652 return -EINVAL;
653 }
654
655 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
656}
657
658static int fs_get_mute(int dev_id, u8 *value)
659{
660 struct sc_reg_access sc_access[6] = {{0,},};
661
662 int retval = 0, temp_value = 0, mask = 0;
663
664 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
665 retval = fs_init_card();
666 if (retval)
667 return retval;
668
669 switch (dev_id) {
670
671 case PMIC_SND_AMIC_MUTE:
672 case PMIC_SND_HP_MIC_MUTE:
673 sc_access[0].reg_addr = MICLICTRL1;
674 mask = MASK6;
675 retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
676 if (sc_access[0].value & mask)
677 *value = MUTE;
678 else
679 *value = UNMUTE;
680 break;
681 case PMIC_SND_DMIC_MUTE:
682 sc_access[0].reg_addr = MICCTRL;
683 mask = MASK5;
684 retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
685 temp_value = (sc_access[0].value & mask);
686 if (temp_value == 0)
687 *value = UNMUTE;
688 else
689 *value = MUTE;
690 break;
691
692 case PMIC_SND_LEFT_HP_MUTE:
693 case PMIC_SND_LEFT_SPEAKER_MUTE:
694 sc_access[0].reg_addr = AUD16;
695 mask = MASK7;
696 retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
697 temp_value = sc_access[0].value & mask;
698 if (temp_value == 0)
699 *value = UNMUTE;
700 else
701 *value = MUTE;
702 break;
703 case PMIC_SND_RIGHT_HP_MUTE:
704 case PMIC_SND_RIGHT_SPEAKER_MUTE:
705 sc_access[0].reg_addr = AUD17;
706 mask = MASK7;
707 retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
708 temp_value = sc_access[0].value & mask;
709 if (temp_value == 0)
710 *value = UNMUTE;
711 else
712 *value = MUTE;
713 break;
714 default:
715 return -EINVAL;
716 }
717
718 return retval;
719}
720
721static int fs_get_vol(int dev_id, int *value)
722{
723 struct sc_reg_access sc_access = {0,};
724 int retval = 0, mask = 0;
725
726 if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
727 retval = fs_init_card();
728 if (retval)
729 return retval;
730
731 switch (dev_id) {
732 case PMIC_SND_CAPTURE_VOL:
733 pr_debug("PMIC_SND_CAPTURE_VOL\n");
734 sc_access.reg_addr = MICLICTRL1;
735 mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
736 break;
737 case PMIC_SND_LEFT_PB_VOL:
738 pr_debug("PMIC_SND_LEFT_PB_VOL\n");
739 sc_access.reg_addr = AUD16;
740 mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
741 break;
742 case PMIC_SND_RIGHT_PB_VOL:
743 pr_debug("PMIC_SND_RT_PB_VOL\n");
744 sc_access.reg_addr = AUD17;
745 mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
746 break;
747 default:
748 return -EINVAL;
749 }
750
751 retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
752 pr_debug("value read = 0x%x\n", sc_access.value);
753 *value = (int) (sc_access.value & mask);
754 pr_debug("value returned = 0x%x\n", *value);
755 return retval;
756}
757
758static void fs_pmic_irq_enable(void *data)
759{
760 struct snd_intelmad *intelmaddata = data;
761 struct sc_reg_access sc_access[] = {
762 {0x187, 0x00, MASK7},
763 {0x188, 0x10, MASK4},
764 {0x18b, 0x10, MASK4},
765 };
766
767 struct sc_reg_access sc_access_write[] = {
768 {0x198, 0x00, 0x0},
769 };
770 pr_debug("Audio interrupt enable\n");
771 sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
772 sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
773
774 intelmaddata->jack[0].jack_status = 0;
775 /*intelmaddata->jack[1].jack_status = 0;*/
776
777 jack_det_enabled = true;
778 return;
779}
780
781static void fs_pmic_irq_cb(void *cb_data, u8 value)
782{
783 struct mad_jack *mjack = NULL;
784 struct snd_intelmad *intelmaddata = cb_data;
785 unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
786
787 mjack = &intelmaddata->jack[0];
788
789 if (value & 0x4) {
790 if (!jack_det_enabled)
791 fs_pmic_irq_enable(intelmaddata);
792
793 /* send headphone detect */
794 pr_debug(":MAD headphone %d\n", value & 0x4);
795 present = !(mjack->jack_status);
796 mjack->jack_status = present;
797 jack_event_flag = 1;
798 mjack->jack.type = SND_JACK_HEADPHONE;
799 }
800
801 if (value & 0x2) {
802 /* send short push */
803 pr_debug(":MAD short push %d\n", value & 0x2);
804 present = 1;
805 jack_event_flag = 1;
806 buttonpressflag = 1;
807 mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
808 }
809
810 if (value & 0x1) {
811 /* send long push */
812 pr_debug(":MAD long push %d\n", value & 0x1);
813 present = 1;
814 jack_event_flag = 1;
815 buttonpressflag = 1;
816 mjack->jack.type = MID_JACK_HS_LONG_PRESS;
817 }
818
819 if (value & 0x8) {
820 if (!jack_det_enabled)
821 fs_pmic_irq_enable(intelmaddata);
822 /* send headset detect */
823 pr_debug(":MAD headset = %d\n", value & 0x8);
824 present = !(mjack->jack_status);
825 mjack->jack_status = present;
826 jack_event_flag = 1;
827 mjack->jack.type = SND_JACK_HEADSET;
828 }
829
830
831 if (jack_event_flag)
832 sst_mad_send_jack_report(&mjack->jack,
833 buttonpressflag, present);
834
835 return;
836}
837static int fs_jack_enable(void)
838{
839 return 0;
840}
841
842struct snd_pmic_ops snd_pmic_ops_fs = {
843 .set_input_dev = fs_set_selected_input_dev,
844 .set_output_dev = fs_set_selected_output_dev,
845 .set_mute = fs_set_mute,
846 .get_mute = fs_get_mute,
847 .set_vol = fs_set_vol,
848 .get_vol = fs_get_vol,
849 .init_card = fs_init_card,
850 .set_pcm_audio_params = fs_set_pcm_audio_params,
851 .set_pcm_voice_params = fs_set_pcm_voice_params,
852 .set_voice_port = fs_set_voice_port,
853 .set_audio_port = fs_set_audio_port,
854 .power_up_pmic_pb = fs_power_up_pb,
855 .power_up_pmic_cp = fs_power_up_cp,
856 .power_down_pmic_pb = fs_power_down_pb,
857 .power_down_pmic_cp = fs_power_down_cp,
858 .power_down_pmic = fs_power_down,
859 .pmic_irq_cb = fs_pmic_irq_cb,
860 /*
861 * Jack detection enabling
862 * need be delayed till first IRQ happen.
863 */
864 .pmic_irq_enable = NULL,
865 .pmic_jack_enable = fs_jack_enable,
866};
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c
new file mode 100644
index 00000000000..9d00728d8de
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_v1_control.c
@@ -0,0 +1,978 @@
1/* intel_sst_v1_control.c - Intel SST Driver for audio engine
2 *
3 * Copyright (C) 2008-10 Intel Corp
4 * Authors: Vinod Koul <vinod.koul@intel.com>
5 * Harsha Priya <priya.harsha@intel.com>
6 * Dharageswari R <dharageswari.r@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 *
25 * This file contains the control operations of vendor 2
26 */
27
28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
30#include <linux/pci.h>
31#include <linux/delay.h>
32#include <linux/file.h>
33#include <asm/mrst.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/control.h>
37#include <sound/initval.h>
38#include "intel_sst.h"
39#include "intel_sst_ioctl.h"
40#include "intelmid.h"
41#include "intelmid_snd_control.h"
42
43#include <linux/gpio.h>
44#define KOSKI_VOICE_CODEC_ENABLE 46
45
46enum _reg_v2 {
47
48 MASTER_CLOCK_PRESCALAR = 0x205,
49 SET_MASTER_AND_LR_CLK1 = 0x20b,
50 SET_MASTER_AND_LR_CLK2 = 0x20c,
51 MASTER_MODE_AND_DATA_DELAY = 0x20d,
52 DIGITAL_INTERFACE_TO_DAI2 = 0x20e,
53 CLK_AND_FS1 = 0x208,
54 CLK_AND_FS2 = 0x209,
55 DAI2_TO_DAC_HP = 0x210,
56 HP_OP_SINGLE_ENDED = 0x224,
57 ENABLE_OPDEV_CTRL = 0x226,
58 ENABLE_DEV_AND_USE_XTAL = 0x227,
59
60 /* Max audio subsystem (PQ49) MAX 8921 */
61 AS_IP_MODE_CTL = 0xF9,
62 AS_LEFT_SPKR_VOL_CTL = 0xFA, /* Mono Earpiece volume control */
63 AS_RIGHT_SPKR_VOL_CTL = 0xFB,
64 AS_LEFT_HP_VOL_CTL = 0xFC,
65 AS_RIGHT_HP_VOL_CTL = 0xFD,
66 AS_OP_MIX_CTL = 0xFE,
67 AS_CONFIG = 0xFF,
68
69 /* Headphone volume control & mute registers */
70 VOL_CTRL_LT = 0x21c,
71 VOL_CTRL_RT = 0x21d,
72
73};
74/**
75 * mx_init_card - initialize the sound card
76 *
77 * This initializes the audio paths to know values in case of this sound card
78 */
79static int mx_init_card(void)
80{
81 struct sc_reg_access sc_access[] = {
82 {0x200, 0x80, 0x00},
83 {0x201, 0xC0, 0x00},
84 {0x202, 0x00, 0x00},
85 {0x203, 0x00, 0x00},
86 {0x204, 0x02, 0x00},
87 {0x205, 0x10, 0x00},
88 {0x206, 0x60, 0x00},
89 {0x207, 0x00, 0x00},
90 {0x208, 0x90, 0x00},
91 {0x209, 0x51, 0x00},
92 {0x20a, 0x00, 0x00},
93 {0x20b, 0x10, 0x00},
94 {0x20c, 0x00, 0x00},
95 {0x20d, 0x00, 0x00},
96 {0x20e, 0x21, 0x00},
97 {0x20f, 0x00, 0x00},
98 {0x210, 0x84, 0x00},
99 {0x211, 0xB3, 0x00},
100 {0x212, 0x00, 0x00},
101 {0x213, 0x00, 0x00},
102 {0x214, 0x41, 0x00},
103 {0x215, 0x00, 0x00},
104 {0x216, 0x00, 0x00},
105 {0x217, 0x00, 0x00},
106 {0x218, 0x03, 0x00},
107 {0x219, 0x03, 0x00},
108 {0x21a, 0x00, 0x00},
109 {0x21b, 0x00, 0x00},
110 {0x21c, 0x00, 0x00},
111 {0x21d, 0x00, 0x00},
112 {0x21e, 0x00, 0x00},
113 {0x21f, 0x00, 0x00},
114 {0x220, 0x20, 0x00},
115 {0x221, 0x20, 0x00},
116 {0x222, 0x51, 0x00},
117 {0x223, 0x20, 0x00},
118 {0x224, 0x04, 0x00},
119 {0x225, 0x80, 0x00},
120 {0x226, 0x0F, 0x00},
121 {0x227, 0x08, 0x00},
122 {0xf9, 0x40, 0x00},
123 {0xfa, 0x1f, 0x00},
124 {0xfb, 0x1f, 0x00},
125 {0xfc, 0x1f, 0x00},
126 {0xfd, 0x1f, 0x00},
127 {0xfe, 0x00, 0x00},
128 {0xff, 0x0c, 0x00},
129 };
130 snd_pmic_ops_mx.card_status = SND_CARD_INIT_DONE;
131 snd_pmic_ops_mx.num_channel = 2;
132 snd_pmic_ops_mx.master_mute = UNMUTE;
133 snd_pmic_ops_mx.mute_status = UNMUTE;
134 return sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
135}
136
137static int mx_enable_audiodac(int value)
138{
139 struct sc_reg_access sc_access[3];
140 int mute_val = 0;
141 int mute_val1 = 0;
142 int retval = 0;
143
144 sc_access[0].reg_addr = AS_LEFT_HP_VOL_CTL;
145 sc_access[1].reg_addr = AS_RIGHT_HP_VOL_CTL;
146
147 if (value == UNMUTE) {
148 mute_val = 0x1F;
149 mute_val1 = 0x00;
150 } else {
151 mute_val = 0x00;
152 mute_val1 = 0x40;
153 }
154 sc_access[0].mask = sc_access[1].mask = MASK0|MASK1|MASK2|MASK3|MASK4;
155 sc_access[0].value = sc_access[1].value = (u8)mute_val;
156 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
157 if (retval)
158 return retval;
159 pr_debug("mute status = %d\n", snd_pmic_ops_mx.mute_status);
160 if (snd_pmic_ops_mx.mute_status == MUTE ||
161 snd_pmic_ops_mx.master_mute == MUTE)
162 return retval;
163
164 sc_access[0].reg_addr = VOL_CTRL_LT;
165 sc_access[1].reg_addr = VOL_CTRL_RT;
166 sc_access[0].mask = sc_access[1].mask = MASK6;
167 sc_access[0].value = sc_access[1].value = mute_val1;
168 if (snd_pmic_ops_mx.num_channel == 1)
169 sc_access[1].value = 0x40;
170 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
171}
172
173static int mx_power_up_pb(unsigned int port)
174{
175
176 int retval = 0;
177 struct sc_reg_access sc_access[3];
178
179 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
180 retval = mx_init_card();
181 if (retval)
182 return retval;
183 }
184 retval = mx_enable_audiodac(MUTE);
185 if (retval)
186 return retval;
187
188 msleep(10);
189
190 sc_access[0].reg_addr = AS_CONFIG;
191 sc_access[0].mask = MASK7;
192 sc_access[0].value = 0x80;
193 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
194 if (retval)
195 return retval;
196
197 sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
198 sc_access[0].mask = 0xff;
199 sc_access[0].value = 0x3C;
200 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
201 if (retval)
202 return retval;
203
204 sc_access[0].reg_addr = ENABLE_DEV_AND_USE_XTAL;
205 sc_access[0].mask = 0x80;
206 sc_access[0].value = 0x80;
207 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
208 if (retval)
209 return retval;
210
211 return mx_enable_audiodac(UNMUTE);
212}
213
214static int mx_power_down_pb(unsigned int device)
215{
216 struct sc_reg_access sc_access[3];
217 int retval = 0;
218
219 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
220 retval = mx_init_card();
221 if (retval)
222 return retval;
223 }
224
225 retval = mx_enable_audiodac(MUTE);
226 if (retval)
227 return retval;
228
229 sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
230 sc_access[0].mask = MASK3|MASK2;
231 sc_access[0].value = 0x00;
232
233 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
234 if (retval)
235 return retval;
236
237 return mx_enable_audiodac(UNMUTE);
238}
239
240static int mx_power_up_cp(unsigned int port)
241{
242 int retval = 0;
243 struct sc_reg_access sc_access[] = {
244 {ENABLE_DEV_AND_USE_XTAL, 0x80, MASK7},
245 {ENABLE_OPDEV_CTRL, 0x3, 0x3},
246 };
247
248 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
249 retval = mx_init_card();
250 if (retval)
251 return retval;
252 }
253
254 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
255}
256
257static int mx_power_down_cp(unsigned int device)
258{
259 struct sc_reg_access sc_access[] = {
260 {ENABLE_OPDEV_CTRL, 0x00, MASK1|MASK0},
261 };
262 int retval = 0;
263
264 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
265 retval = mx_init_card();
266 if (retval)
267 return retval;
268 }
269
270 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
271}
272
273static int mx_power_down(void)
274{
275 int retval = 0;
276 struct sc_reg_access sc_access[3];
277
278 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
279 retval = mx_init_card();
280 if (retval)
281 return retval;
282 }
283
284 retval = mx_enable_audiodac(MUTE);
285 if (retval)
286 return retval;
287
288 sc_access[0].reg_addr = AS_CONFIG;
289 sc_access[0].mask = MASK7;
290 sc_access[0].value = 0x00;
291 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
292 if (retval)
293 return retval;
294
295 sc_access[0].reg_addr = ENABLE_DEV_AND_USE_XTAL;
296 sc_access[0].mask = MASK7;
297 sc_access[0].value = 0x00;
298 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
299 if (retval)
300 return retval;
301
302 sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
303 sc_access[0].mask = MASK3|MASK2;
304 sc_access[0].value = 0x00;
305 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
306 if (retval)
307 return retval;
308
309 return mx_enable_audiodac(UNMUTE);
310}
311
312static int mx_set_pcm_voice_params(void)
313{
314 int retval = 0;
315 struct sc_reg_access sc_access[] = {
316 {0x200, 0x80, 0x00},
317 {0x201, 0xC0, 0x00},
318 {0x202, 0x00, 0x00},
319 {0x203, 0x00, 0x00},
320 {0x204, 0x0e, 0x00},
321 {0x205, 0x20, 0x00},
322 {0x206, 0x8f, 0x00},
323 {0x207, 0x21, 0x00},
324 {0x208, 0x18, 0x00},
325 {0x209, 0x32, 0x00},
326 {0x20a, 0x00, 0x00},
327 {0x20b, 0x5A, 0x00},
328 {0x20c, 0xBE, 0x00},/* 0x00 -> 0xBE Koski */
329 {0x20d, 0x00, 0x00}, /* DAI2 'off' */
330 {0x20e, 0x40, 0x00},
331 {0x20f, 0x00, 0x00},
332 {0x210, 0x84, 0x00},
333 {0x211, 0x33, 0x00}, /* Voice filter */
334 {0x212, 0x00, 0x00},
335 {0x213, 0x00, 0x00},
336 {0x214, 0x41, 0x00},
337 {0x215, 0x00, 0x00},
338 {0x216, 0x00, 0x00},
339 {0x217, 0x20, 0x00},
340 {0x218, 0x00, 0x00},
341 {0x219, 0x00, 0x00},
342 {0x21a, 0x40, 0x00},
343 {0x21b, 0x40, 0x00},
344 {0x21c, 0x09, 0x00},
345 {0x21d, 0x09, 0x00},
346 {0x21e, 0x00, 0x00},
347 {0x21f, 0x00, 0x00},
348 {0x220, 0x00, 0x00}, /* Microphone configurations */
349 {0x221, 0x00, 0x00}, /* Microphone configurations */
350 {0x222, 0x50, 0x00}, /* Microphone configurations */
351 {0x223, 0x21, 0x00}, /* Microphone configurations */
352 {0x224, 0x00, 0x00},
353 {0x225, 0x80, 0x00},
354 {0xf9, 0x40, 0x00},
355 {0xfa, 0x19, 0x00},
356 {0xfb, 0x19, 0x00},
357 {0xfc, 0x12, 0x00},
358 {0xfd, 0x12, 0x00},
359 {0xfe, 0x00, 0x00},
360 };
361
362 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
363 retval = mx_init_card();
364 if (retval)
365 return retval;
366 }
367 pr_debug("SST DBG:mx_set_pcm_voice_params called\n");
368 return sst_sc_reg_access(sc_access, PMIC_WRITE, 44);
369}
370
371static int mx_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
372{
373 int retval = 0;
374
375 int config1 = 0, config2 = 0, filter = 0xB3;
376 struct sc_reg_access sc_access[5];
377
378 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
379 retval = mx_init_card();
380 if (retval)
381 return retval;
382 }
383
384 switch (sfreq) {
385 case 8000:
386 config1 = 0x10;
387 config2 = 0x00;
388 filter = 0x33;
389 break;
390 case 11025:
391 config1 = 0x16;
392 config2 = 0x0d;
393 break;
394 case 12000:
395 config1 = 0x18;
396 config2 = 0x00;
397 break;
398 case 16000:
399 config1 = 0x20;
400 config2 = 0x00;
401 break;
402 case 22050:
403 config1 = 0x2c;
404 config2 = 0x1a;
405 break;
406 case 24000:
407 config1 = 0x30;
408 config2 = 0x00;
409 break;
410 case 32000:
411 config1 = 0x40;
412 config2 = 0x00;
413 break;
414 case 44100:
415 config1 = 0x58;
416 config2 = 0x33;
417 break;
418 case 48000:
419 config1 = 0x60;
420 config2 = 0x00;
421 break;
422 }
423 snd_pmic_ops_mx.num_channel = num_channel;
424 /*mute the right channel if MONO*/
425 if (snd_pmic_ops_mx.num_channel == 1) {
426 sc_access[0].reg_addr = VOL_CTRL_RT;
427 sc_access[0].value = 0x40;
428 sc_access[0].mask = MASK6;
429
430 sc_access[1].reg_addr = 0x224;
431 sc_access[1].value = 0x05;
432 sc_access[1].mask = MASK0|MASK1|MASK2;
433
434 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
435 if (retval)
436 return retval;
437 } else {
438 sc_access[0].reg_addr = VOL_CTRL_RT;
439 sc_access[0].value = 0x00;
440 sc_access[0].mask = MASK6;
441
442 sc_access[1].reg_addr = 0x224;
443 sc_access[1].value = 0x04;
444 sc_access[1].mask = MASK0|MASK1|MASK2;
445
446 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
447 if (retval)
448 return retval;
449 }
450 sc_access[0].reg_addr = 0x206;
451 sc_access[0].value = config1;
452 sc_access[1].reg_addr = 0x207;
453 sc_access[1].value = config2;
454
455 if (word_size == 16) {
456 sc_access[2].value = 0x51;
457 sc_access[3].value = 0x31;
458 } else if (word_size == 24) {
459 sc_access[2].value = 0x52;
460 sc_access[3].value = 0x92;
461 }
462
463 sc_access[2].reg_addr = 0x209;
464 sc_access[3].reg_addr = 0x20e;
465
466 sc_access[4].reg_addr = 0x211;
467 sc_access[4].value = filter;
468
469 return sst_sc_reg_access(sc_access, PMIC_WRITE, 5);
470}
471
472static int mx_set_selected_output_dev(u8 dev_id)
473{
474 struct sc_reg_access sc_access[2];
475 int num_reg = 0;
476 int retval = 0;
477
478 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
479 retval = mx_init_card();
480 if (retval)
481 return retval;
482 }
483
484 pr_debug("mx_set_selected_output_dev dev_id:0x%x\n", dev_id);
485 snd_pmic_ops_mx.output_dev_id = dev_id;
486 switch (dev_id) {
487 case STEREO_HEADPHONE:
488 sc_access[0].reg_addr = 0xFF;
489 sc_access[0].value = 0x8C;
490 sc_access[0].mask =
491 MASK2|MASK3|MASK5|MASK6|MASK4;
492
493 num_reg = 1;
494 break;
495 case MONO_EARPIECE:
496 case INTERNAL_SPKR:
497 sc_access[0].reg_addr = 0xFF;
498 sc_access[0].value = 0xb0;
499 sc_access[0].mask = MASK2|MASK3|MASK5|MASK6|MASK4;
500
501 num_reg = 1;
502 break;
503 case RECEIVER:
504 pr_debug("RECEIVER Koski selected\n");
505
506 /* configuration - AS enable, receiver enable */
507 sc_access[0].reg_addr = 0xFF;
508 sc_access[0].value = 0x81;
509 sc_access[0].mask = 0xff;
510
511 num_reg = 1;
512 break;
513 default:
514 pr_err("Not a valid output dev\n");
515 return 0;
516 }
517 return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
518}
519
520
521static int mx_set_voice_port(int status)
522{
523 int retval = 0;
524
525 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
526 retval = mx_init_card();
527 if (retval)
528 return retval;
529 }
530 if (status == ACTIVATE)
531 retval = mx_set_pcm_voice_params();
532
533 return retval;
534}
535
536static int mx_set_audio_port(int status)
537{
538 return 0;
539}
540
541static int mx_set_selected_input_dev(u8 dev_id)
542{
543 struct sc_reg_access sc_access[2];
544 int num_reg = 0;
545 int retval = 0;
546
547 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
548 retval = mx_init_card();
549 if (retval)
550 return retval;
551 }
552 snd_pmic_ops_mx.input_dev_id = dev_id;
553 pr_debug("mx_set_selected_input_dev dev_id:0x%x\n", dev_id);
554
555 switch (dev_id) {
556 case AMIC:
557 sc_access[0].reg_addr = 0x223;
558 sc_access[0].value = 0x00;
559 sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
560 sc_access[1].reg_addr = 0x222;
561 sc_access[1].value = 0x50;
562 sc_access[1].mask = MASK7|MASK6|MASK5|MASK4;
563 num_reg = 2;
564 break;
565
566 case HS_MIC:
567 sc_access[0].reg_addr = 0x223;
568 sc_access[0].value = 0x20;
569 sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
570 sc_access[1].reg_addr = 0x222;
571 sc_access[1].value = 0x51;
572 sc_access[1].mask = MASK7|MASK6|MASK5|MASK4;
573 num_reg = 2;
574 break;
575 case DMIC:
576 sc_access[1].reg_addr = 0x222;
577 sc_access[1].value = 0x00;
578 sc_access[1].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
579 sc_access[0].reg_addr = 0x223;
580 sc_access[0].value = 0x20;
581 sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
582 num_reg = 2;
583 break;
584 }
585 return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
586}
587
588static int mx_set_mute(int dev_id, u8 value)
589{
590 struct sc_reg_access sc_access[5];
591 int num_reg = 0;
592 int retval = 0;
593
594 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
595 retval = mx_init_card();
596 if (retval)
597 return retval;
598 }
599
600
601 pr_debug("set_mute dev_id:0x%x , value:%d\n", dev_id, value);
602
603 switch (dev_id) {
604 case PMIC_SND_DMIC_MUTE:
605 case PMIC_SND_AMIC_MUTE:
606 case PMIC_SND_HP_MIC_MUTE:
607 sc_access[0].reg_addr = 0x220;
608 sc_access[1].reg_addr = 0x221;
609 sc_access[2].reg_addr = 0x223;
610 if (value == MUTE) {
611 sc_access[0].value = 0x00;
612 sc_access[1].value = 0x00;
613 if (snd_pmic_ops_mx.input_dev_id == DMIC)
614 sc_access[2].value = 0x00;
615 else
616 sc_access[2].value = 0x20;
617 } else {
618 sc_access[0].value = 0x20;
619 sc_access[1].value = 0x20;
620 if (snd_pmic_ops_mx.input_dev_id == DMIC)
621 sc_access[2].value = 0x20;
622 else
623 sc_access[2].value = 0x00;
624 }
625 sc_access[0].mask = MASK5|MASK6;
626 sc_access[1].mask = MASK5|MASK6;
627 sc_access[2].mask = MASK5|MASK6;
628 num_reg = 3;
629 break;
630 case PMIC_SND_LEFT_SPEAKER_MUTE:
631 case PMIC_SND_LEFT_HP_MUTE:
632 sc_access[0].reg_addr = VOL_CTRL_LT;
633 if (value == MUTE)
634 sc_access[0].value = 0x40;
635 else
636 sc_access[0].value = 0x00;
637 sc_access[0].mask = MASK6;
638 num_reg = 1;
639 snd_pmic_ops_mx.mute_status = value;
640 break;
641 case PMIC_SND_RIGHT_SPEAKER_MUTE:
642 case PMIC_SND_RIGHT_HP_MUTE:
643 sc_access[0].reg_addr = VOL_CTRL_RT;
644 if (snd_pmic_ops_mx.num_channel == 1)
645 value = MUTE;
646 if (value == MUTE)
647 sc_access[0].value = 0x40;
648 else
649 sc_access[0].value = 0x00;
650 sc_access[0].mask = MASK6;
651 num_reg = 1;
652 snd_pmic_ops_mx.mute_status = value;
653 break;
654 case PMIC_SND_MUTE_ALL:
655 sc_access[0].reg_addr = VOL_CTRL_RT;
656 sc_access[1].reg_addr = VOL_CTRL_LT;
657 sc_access[2].reg_addr = 0x220;
658 sc_access[3].reg_addr = 0x221;
659 sc_access[4].reg_addr = 0x223;
660 snd_pmic_ops_mx.master_mute = value;
661 if (value == MUTE) {
662 sc_access[0].value = sc_access[1].value = 0x40;
663 sc_access[2].value = 0x00;
664 sc_access[3].value = 0x00;
665 if (snd_pmic_ops_mx.input_dev_id == DMIC)
666 sc_access[4].value = 0x00;
667 else
668 sc_access[4].value = 0x20;
669
670 } else {
671 sc_access[0].value = sc_access[1].value = 0x00;
672 sc_access[2].value = sc_access[3].value = 0x20;
673 sc_access[4].value = 0x20;
674 if (snd_pmic_ops_mx.input_dev_id == DMIC)
675 sc_access[4].value = 0x20;
676 else
677 sc_access[4].value = 0x00;
678
679
680 }
681 if (snd_pmic_ops_mx.num_channel == 1)
682 sc_access[0].value = 0x40;
683 sc_access[0].mask = sc_access[1].mask = MASK6;
684 sc_access[2].mask = MASK5|MASK6;
685 sc_access[3].mask = MASK5|MASK6|MASK2|MASK4;
686 sc_access[4].mask = MASK5|MASK6|MASK4;
687
688 num_reg = 5;
689 break;
690 case PMIC_SND_RECEIVER_MUTE:
691 sc_access[0].reg_addr = VOL_CTRL_RT;
692 if (value == MUTE)
693 sc_access[0].value = 0x40;
694 else
695 sc_access[0].value = 0x00;
696 sc_access[0].mask = MASK6;
697 num_reg = 1;
698 break;
699 }
700
701 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
702}
703
704static int mx_set_vol(int dev_id, int value)
705{
706 struct sc_reg_access sc_access[2] = {{0},};
707 int num_reg = 0;
708 int retval = 0;
709
710 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
711 retval = mx_init_card();
712 if (retval)
713 return retval;
714 }
715 pr_debug("set_vol dev_id:0x%x ,value:%d\n", dev_id, value);
716 switch (dev_id) {
717 case PMIC_SND_RECEIVER_VOL:
718 return 0;
719 break;
720 case PMIC_SND_CAPTURE_VOL:
721 sc_access[0].reg_addr = 0x220;
722 sc_access[1].reg_addr = 0x221;
723 sc_access[0].value = sc_access[1].value = -value;
724 sc_access[0].mask = sc_access[1].mask =
725 (MASK0|MASK1|MASK2|MASK3|MASK4);
726 num_reg = 2;
727 break;
728 case PMIC_SND_LEFT_PB_VOL:
729 sc_access[0].value = -value;
730 sc_access[0].reg_addr = VOL_CTRL_LT;
731 sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
732 num_reg = 1;
733 break;
734 case PMIC_SND_RIGHT_PB_VOL:
735 sc_access[0].value = -value;
736 sc_access[0].reg_addr = VOL_CTRL_RT;
737 sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
738 if (snd_pmic_ops_mx.num_channel == 1) {
739 sc_access[0].value = 0x40;
740 sc_access[0].mask = MASK6;
741 sc_access[0].reg_addr = VOL_CTRL_RT;
742 }
743 num_reg = 1;
744 break;
745 }
746 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
747}
748
749static int mx_get_mute(int dev_id, u8 *value)
750{
751 struct sc_reg_access sc_access[4] = {{0},};
752 int retval = 0, num_reg = 0, mask = 0;
753
754 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
755 retval = mx_init_card();
756 if (retval)
757 return retval;
758 }
759 switch (dev_id) {
760 case PMIC_SND_DMIC_MUTE:
761 case PMIC_SND_AMIC_MUTE:
762 case PMIC_SND_HP_MIC_MUTE:
763 sc_access[0].reg_addr = 0x220;
764 mask = MASK5|MASK6;
765 num_reg = 1;
766 retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
767 if (retval)
768 return retval;
769 *value = sc_access[0].value & mask;
770 if (*value)
771 *value = UNMUTE;
772 else
773 *value = MUTE;
774 return retval;
775 case PMIC_SND_LEFT_HP_MUTE:
776 case PMIC_SND_LEFT_SPEAKER_MUTE:
777 sc_access[0].reg_addr = VOL_CTRL_LT;
778 num_reg = 1;
779 mask = MASK6;
780 break;
781 case PMIC_SND_RIGHT_HP_MUTE:
782 case PMIC_SND_RIGHT_SPEAKER_MUTE:
783 sc_access[0].reg_addr = VOL_CTRL_RT;
784 num_reg = 1;
785 mask = MASK6;
786 break;
787 }
788 retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
789 if (retval)
790 return retval;
791 *value = sc_access[0].value & mask;
792 if (*value)
793 *value = MUTE;
794 else
795 *value = UNMUTE;
796 return retval;
797}
798
799static int mx_get_vol(int dev_id, int *value)
800{
801 struct sc_reg_access sc_access = {0,};
802 int retval = 0, mask = 0, num_reg = 0;
803
804 if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
805 retval = mx_init_card();
806 if (retval)
807 return retval;
808 }
809 switch (dev_id) {
810 case PMIC_SND_CAPTURE_VOL:
811 sc_access.reg_addr = 0x220;
812 mask = MASK0|MASK1|MASK2|MASK3|MASK4;
813 num_reg = 1;
814 break;
815 case PMIC_SND_LEFT_PB_VOL:
816 sc_access.reg_addr = VOL_CTRL_LT;
817 mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
818 num_reg = 1;
819 break;
820 case PMIC_SND_RIGHT_PB_VOL:
821 sc_access.reg_addr = VOL_CTRL_RT;
822 mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
823 num_reg = 1;
824 break;
825 }
826 retval = sst_sc_reg_access(&sc_access, PMIC_READ, num_reg);
827 if (retval)
828 return retval;
829 *value = -(sc_access.value & mask);
830 pr_debug("get volume value extracted %d\n", *value);
831 return retval;
832}
833
834static u8 mx_get_jack_status(void)
835{
836 struct sc_reg_access sc_access_read = {0,};
837
838 sc_access_read.reg_addr = 0x201;
839 sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
840 pr_debug("value returned = 0x%x\n", sc_access_read.value);
841 return sc_access_read.value;
842}
843
844static void mx_pmic_irq_enable(void *data)
845{
846 struct snd_intelmad *intelmaddata = data;
847
848 intelmaddata->jack_prev_state = 0xc0;
849 return;
850}
851
852static void mx_pmic_irq_cb(void *cb_data, u8 intsts)
853{
854 u8 jack_cur_status, jack_prev_state = 0;
855 struct mad_jack *mjack = NULL;
856 unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
857 time_t timediff;
858 struct snd_intelmad *intelmaddata = cb_data;
859
860 mjack = &intelmaddata->jack[0];
861 if (intsts & 0x2) {
862 jack_cur_status = mx_get_jack_status();
863 jack_prev_state = intelmaddata->jack_prev_state;
864 if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x40)) {
865 /*headset insert detected. */
866 pr_debug("MAD headset inserted\n");
867 present = 1;
868 jack_event_flag = 1;
869 mjack->jack_status = 1;
870 mjack->jack.type = SND_JACK_HEADSET;
871 }
872
873 if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x00)) {
874 /* headphone insert detected. */
875 pr_debug("MAD headphone inserted\n");
876 present = 1;
877 jack_event_flag = 1;
878 mjack->jack.type = SND_JACK_HEADPHONE;
879 }
880
881 if ((jack_prev_state == 0x40) && (jack_cur_status == 0xc0)) {
882 /* headset remove detected. */
883 pr_debug("MAD headset removed\n");
884
885 present = 0;
886 jack_event_flag = 1;
887 mjack->jack_status = 0;
888 mjack->jack.type = SND_JACK_HEADSET;
889 }
890
891 if ((jack_prev_state == 0x00) && (jack_cur_status == 0xc0)) {
892 /* headphone remove detected. */
893 pr_debug("MAD headphone removed\n");
894 present = 0;
895 jack_event_flag = 1;
896 mjack->jack.type = SND_JACK_HEADPHONE;
897 }
898
899 if ((jack_prev_state == 0x40) && (jack_cur_status == 0x00)) {
900 /* button pressed */
901 do_gettimeofday(&mjack->buttonpressed);
902 pr_debug("MAD button press detected\n");
903 }
904
905 if ((jack_prev_state == 0x00) && (jack_cur_status == 0x40)) {
906 if (mjack->jack_status) {
907 /*button pressed */
908 do_gettimeofday(
909 &mjack->buttonreleased);
910 /*button pressed */
911 pr_debug("MAD Button Released detected\n");
912 timediff = mjack->buttonreleased.tv_sec -
913 mjack->buttonpressed.tv_sec;
914 buttonpressflag = 1;
915
916 if (timediff > 1) {
917 pr_debug("MAD long press dtd\n");
918 /* send headphone detect/undetect */
919 present = 1;
920 jack_event_flag = 1;
921 mjack->jack.type =
922 MID_JACK_HS_LONG_PRESS;
923 } else {
924 pr_debug("MAD short press dtd\n");
925 /* send headphone detect/undetect */
926 present = 1;
927 jack_event_flag = 1;
928 mjack->jack.type =
929 MID_JACK_HS_SHORT_PRESS;
930 }
931 } else {
932 /***workaround for maxim
933 hw issue,0x00 t 0x40 is not
934 a valid transiton for Headset insertion */
935 /*headset insert detected. */
936 pr_debug("MAD headset inserted\n");
937 present = 1;
938 jack_event_flag = 1;
939 mjack->jack_status = 1;
940 mjack->jack.type = SND_JACK_HEADSET;
941 }
942 }
943 intelmaddata->jack_prev_state = jack_cur_status;
944 pr_debug("mx_pmic_irq_cb prv_state= 0x%x\n",
945 intelmaddata->jack_prev_state);
946 }
947
948 if (jack_event_flag)
949 sst_mad_send_jack_report(&mjack->jack,
950 buttonpressflag, present);
951}
952static int mx_jack_enable(void)
953{
954 return 0;
955}
956
957struct snd_pmic_ops snd_pmic_ops_mx = {
958 .set_input_dev = mx_set_selected_input_dev,
959 .set_output_dev = mx_set_selected_output_dev,
960 .set_mute = mx_set_mute,
961 .get_mute = mx_get_mute,
962 .set_vol = mx_set_vol,
963 .get_vol = mx_get_vol,
964 .init_card = mx_init_card,
965 .set_pcm_audio_params = mx_set_pcm_audio_params,
966 .set_pcm_voice_params = mx_set_pcm_voice_params,
967 .set_voice_port = mx_set_voice_port,
968 .set_audio_port = mx_set_audio_port,
969 .power_up_pmic_pb = mx_power_up_pb,
970 .power_up_pmic_cp = mx_power_up_cp,
971 .power_down_pmic_pb = mx_power_down_pb,
972 .power_down_pmic_cp = mx_power_down_cp,
973 .power_down_pmic = mx_power_down,
974 .pmic_irq_cb = mx_pmic_irq_cb,
975 .pmic_irq_enable = mx_pmic_irq_enable,
976 .pmic_jack_enable = mx_jack_enable,
977};
978
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
new file mode 100644
index 00000000000..46ab55eb809
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -0,0 +1,1156 @@
1/*
2 * intelmid_v2_control.c - Intel Sound card driver for MID
3 *
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * KP Jeeja <jeeja.kp@intel.com>
8 * Dharageswari R <dharageswari.r@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * This file contains the control operations of vendor 3
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/gpio.h>
32#include <linux/pci.h>
33#include <linux/delay.h>
34#include <linux/file.h>
35#include <sound/control.h>
36#include "intel_sst.h"
37#include "intelmid_snd_control.h"
38#include "intelmid.h"
39
40enum reg_v3 {
41 VAUDIOCNT = 0x51,
42 VOICEPORT1 = 0x100,
43 VOICEPORT2 = 0x101,
44 AUDIOPORT1 = 0x102,
45 AUDIOPORT2 = 0x103,
46 ADCSAMPLERATE = 0x104,
47 DMICCTRL1 = 0x105,
48 DMICCTRL2 = 0x106,
49 MICCTRL = 0x107,
50 MICSELVOL = 0x108,
51 LILSEL = 0x109,
52 LIRSEL = 0x10a,
53 VOICEVOL = 0x10b,
54 AUDIOLVOL = 0x10c,
55 AUDIORVOL = 0x10d,
56 LMUTE = 0x10e,
57 RMUTE = 0x10f,
58 POWERCTRL1 = 0x110,
59 POWERCTRL2 = 0x111,
60 DRVPOWERCTRL = 0x112,
61 VREFPLL = 0x113,
62 PCMBUFCTRL = 0x114,
63 SOFTMUTE = 0x115,
64 DTMFPATH = 0x116,
65 DTMFVOL = 0x117,
66 DTMFFREQ = 0x118,
67 DTMFHFREQ = 0x119,
68 DTMFLFREQ = 0x11a,
69 DTMFCTRL = 0x11b,
70 DTMFASON = 0x11c,
71 DTMFASOFF = 0x11d,
72 DTMFASINUM = 0x11e,
73 CLASSDVOL = 0x11f,
74 VOICEDACAVOL = 0x120,
75 AUDDACAVOL = 0x121,
76 LOMUTEVOL = 0x122,
77 HPLVOL = 0x123,
78 HPRVOL = 0x124,
79 MONOVOL = 0x125,
80 LINEOUTMIXVOL = 0x126,
81 EPMIXVOL = 0x127,
82 LINEOUTLSEL = 0x128,
83 LINEOUTRSEL = 0x129,
84 EPMIXOUTSEL = 0x12a,
85 HPLMIXSEL = 0x12b,
86 HPRMIXSEL = 0x12c,
87 LOANTIPOP = 0x12d,
88 AUXDBNC = 0x12f,
89};
90
91static void nc_set_amp_power(int power)
92{
93 if (snd_pmic_ops_nc.gpio_amp)
94 gpio_set_value(snd_pmic_ops_nc.gpio_amp, power);
95}
96
97/****
98 * nc_init_card - initialize the sound card
99 *
100 * This initializes the audio paths to know values in case of this sound card
101 */
102static int nc_init_card(void)
103{
104 struct sc_reg_access sc_access[] = {
105 {VAUDIOCNT, 0x25, 0},
106 {VOICEPORT1, 0x00, 0},
107 {VOICEPORT2, 0x00, 0},
108 {AUDIOPORT1, 0x98, 0},
109 {AUDIOPORT2, 0x09, 0},
110 {AUDIOLVOL, 0x00, 0},
111 {AUDIORVOL, 0x00, 0},
112 {LMUTE, 0x03, 0},
113 {RMUTE, 0x03, 0},
114 {POWERCTRL1, 0x00, 0},
115 {POWERCTRL2, 0x00, 0},
116 {DRVPOWERCTRL, 0x00, 0},
117 {VREFPLL, 0x10, 0},
118 {HPLMIXSEL, 0xee, 0},
119 {HPRMIXSEL, 0xf6, 0},
120 {PCMBUFCTRL, 0x0, 0},
121 {VOICEVOL, 0x0e, 0},
122 {HPLVOL, 0x06, 0},
123 {HPRVOL, 0x06, 0},
124 {MICCTRL, 0x51, 0x00},
125 {ADCSAMPLERATE, 0x8B, 0x00},
126 {MICSELVOL, 0x5B, 0x00},
127 {LILSEL, 0x06, 0},
128 {LIRSEL, 0x46, 0},
129 {LOANTIPOP, 0x00, 0},
130 {DMICCTRL1, 0x40, 0},
131 {AUXDBNC, 0xff, 0},
132 };
133 snd_pmic_ops_nc.card_status = SND_CARD_INIT_DONE;
134 snd_pmic_ops_nc.master_mute = UNMUTE;
135 snd_pmic_ops_nc.mute_status = UNMUTE;
136 sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
137 mutex_init(&snd_pmic_ops_nc.lock);
138 pr_debug("init complete!!\n");
139 return 0;
140}
141
142static int nc_enable_audiodac(int value)
143{
144 struct sc_reg_access sc_access[3];
145 int mute_val = 0;
146
147 if (snd_pmic_ops_nc.mute_status == MUTE)
148 return 0;
149
150 if (((snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE) ||
151 (snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)) &&
152 (value == UNMUTE))
153 return 0;
154 if (value == UNMUTE) {
155 /* unmute the system, set the 7th bit to zero */
156 mute_val = 0x00;
157 } else {
158 /* MUTE:Set the seventh bit */
159 mute_val = 0x04;
160
161 }
162 sc_access[0].reg_addr = LMUTE;
163 sc_access[1].reg_addr = RMUTE;
164 sc_access[0].mask = sc_access[1].mask = MASK2;
165 sc_access[0].value = sc_access[1].value = mute_val;
166
167 if (snd_pmic_ops_nc.num_channel == 1)
168 sc_access[1].value = 0x04;
169 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
170
171}
172
173static int nc_power_up_pb(unsigned int port)
174{
175 struct sc_reg_access sc_access[7];
176 int retval = 0;
177
178 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
179 retval = nc_init_card();
180 if (retval)
181 return retval;
182 if (port == 0xFF)
183 return 0;
184 mutex_lock(&snd_pmic_ops_nc.lock);
185 nc_enable_audiodac(MUTE);
186 msleep(30);
187
188 pr_debug("powering up pb....\n");
189
190 sc_access[0].reg_addr = VAUDIOCNT;
191 sc_access[0].value = 0x27;
192 sc_access[0].mask = 0x27;
193 sc_access[1].reg_addr = VREFPLL;
194 if (port == 0) {
195 sc_access[1].value = 0x3A;
196 sc_access[1].mask = 0x3A;
197 } else if (port == 1) {
198 sc_access[1].value = 0x35;
199 sc_access[1].mask = 0x35;
200 }
201 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
202
203
204
205 sc_access[0].reg_addr = POWERCTRL1;
206 if (port == 0) {
207 sc_access[0].value = 0x40;
208 sc_access[0].mask = 0x40;
209 } else if (port == 1) {
210 sc_access[0].value = 0x01;
211 sc_access[0].mask = 0x01;
212 }
213 sc_access[1].reg_addr = POWERCTRL2;
214 sc_access[1].value = 0x0C;
215 sc_access[1].mask = 0x0C;
216
217 sc_access[2].reg_addr = DRVPOWERCTRL;
218 sc_access[2].value = 0x86;
219 sc_access[2].mask = 0x86;
220
221 sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
222
223 msleep(30);
224
225 snd_pmic_ops_nc.pb_on = 1;
226
227 /*
228 * There is a mismatch between Playback Sources and the enumerated
229 * values of output sources. This mismatch causes ALSA upper to send
230 * Item 1 for Internal Speaker, but the expected enumeration is 2! For
231 * now, treat MONO_EARPIECE and INTERNAL_SPKR identically and power up
232 * the needed resources
233 */
234 if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
235 snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
236 nc_set_amp_power(1);
237 nc_enable_audiodac(UNMUTE);
238 mutex_unlock(&snd_pmic_ops_nc.lock);
239 return 0;
240}
241
242static int nc_power_up_cp(unsigned int port)
243{
244 struct sc_reg_access sc_access[5];
245 int retval = 0;
246
247
248 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
249 retval = nc_init_card();
250 if (retval)
251 return retval;
252
253
254 pr_debug("powering up cp....\n");
255
256 if (port == 0xFF)
257 return 0;
258 sc_access[0].reg_addr = VAUDIOCNT;
259 sc_access[0].value = 0x27;
260 sc_access[0].mask = 0x27;
261 sc_access[1].reg_addr = VREFPLL;
262 if (port == 0) {
263 sc_access[1].value = 0x3E;
264 sc_access[1].mask = 0x3E;
265 } else if (port == 1) {
266 sc_access[1].value = 0x35;
267 sc_access[1].mask = 0x35;
268 }
269
270 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
271
272
273 sc_access[0].reg_addr = POWERCTRL1;
274 if (port == 0) {
275 sc_access[0].value = 0xB4;
276 sc_access[0].mask = 0xB4;
277 } else if (port == 1) {
278 sc_access[0].value = 0xBF;
279 sc_access[0].mask = 0xBF;
280 }
281 sc_access[1].reg_addr = POWERCTRL2;
282 if (port == 0) {
283 sc_access[1].value = 0x0C;
284 sc_access[1].mask = 0x0C;
285 } else if (port == 1) {
286 sc_access[1].value = 0x02;
287 sc_access[1].mask = 0x02;
288 }
289
290 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
291
292}
293
294static int nc_power_down(void)
295{
296 int retval = 0;
297 struct sc_reg_access sc_access[5];
298
299 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
300 retval = nc_init_card();
301 if (retval)
302 return retval;
303 nc_enable_audiodac(MUTE);
304
305
306 pr_debug("powering dn nc_power_down ....\n");
307
308 if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
309 snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
310 nc_set_amp_power(0);
311
312 msleep(30);
313
314 sc_access[0].reg_addr = DRVPOWERCTRL;
315 sc_access[0].value = 0x00;
316 sc_access[0].mask = 0x00;
317
318 sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
319
320 sc_access[0].reg_addr = POWERCTRL1;
321 sc_access[0].value = 0x00;
322 sc_access[0].mask = 0x00;
323
324 sc_access[1].reg_addr = POWERCTRL2;
325 sc_access[1].value = 0x00;
326 sc_access[1].mask = 0x00;
327
328
329
330 sst_sc_reg_access(sc_access, PMIC_WRITE, 2);
331
332 msleep(30);
333 sc_access[0].reg_addr = VREFPLL;
334 sc_access[0].value = 0x10;
335 sc_access[0].mask = 0x10;
336
337 sc_access[1].reg_addr = VAUDIOCNT;
338 sc_access[1].value = 0x25;
339 sc_access[1].mask = 0x25;
340
341
342 retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 2);
343
344 msleep(30);
345 return nc_enable_audiodac(UNMUTE);
346}
347
348static int nc_power_down_pb(unsigned int device)
349{
350
351 int retval = 0;
352 struct sc_reg_access sc_access[5];
353
354 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
355 retval = nc_init_card();
356 if (retval)
357 return retval;
358
359 pr_debug("powering dn pb....\n");
360 mutex_lock(&snd_pmic_ops_nc.lock);
361 nc_enable_audiodac(MUTE);
362
363
364 msleep(30);
365
366
367 sc_access[0].reg_addr = DRVPOWERCTRL;
368 sc_access[0].value = 0x00;
369 sc_access[0].mask = 0x00;
370
371 sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
372
373 msleep(30);
374
375 sc_access[0].reg_addr = POWERCTRL1;
376 sc_access[0].value = 0x00;
377 sc_access[0].mask = 0x41;
378
379 sc_access[1].reg_addr = POWERCTRL2;
380 sc_access[1].value = 0x00;
381 sc_access[1].mask = 0x0C;
382
383 sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
384
385 msleep(30);
386
387 snd_pmic_ops_nc.pb_on = 0;
388
389 nc_enable_audiodac(UNMUTE);
390 mutex_unlock(&snd_pmic_ops_nc.lock);
391 return 0;
392}
393
394static int nc_power_down_cp(unsigned int device)
395{
396 struct sc_reg_access sc_access[] = {
397 {POWERCTRL1, 0x00, 0xBE},
398 {POWERCTRL2, 0x00, 0x02},
399 };
400 int retval = 0;
401
402 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
403 retval = nc_init_card();
404 if (retval)
405 return retval;
406
407 pr_debug("powering dn cp....\n");
408 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
409}
410
411static int nc_set_pcm_voice_params(void)
412{
413 struct sc_reg_access sc_access[] = {
414 {0x100, 0xD5, 0},
415 {0x101, 0x08, 0},
416 {0x104, 0x03, 0},
417 {0x107, 0x10, 0},
418 {0x10B, 0x0E, 0},
419 {0x10E, 0x03, 0},
420 {0x10F, 0x03, 0},
421 {0x114, 0x13, 0},
422 {0x115, 0x00, 0},
423 {0x128, 0xFE, 0},
424 {0x129, 0xFE, 0},
425 {0x12A, 0xFE, 0},
426 {0x12B, 0xDE, 0},
427 {0x12C, 0xDE, 0},
428 };
429 int retval = 0;
430
431 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
432 retval = nc_init_card();
433 if (retval)
434 return retval;
435
436 sst_sc_reg_access(sc_access, PMIC_WRITE, 14);
437 pr_debug("Voice parameters set successfully!!\n");
438 return 0;
439}
440
441
442static int nc_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
443{
444 int config2 = 0;
445 struct sc_reg_access sc_access;
446 int retval = 0;
447
448 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
449 retval = nc_init_card();
450 if (retval)
451 return retval;
452
453 switch (sfreq) {
454 case 8000:
455 config2 = 0x00;
456 break;
457 case 11025:
458 config2 = 0x01;
459 break;
460 case 12000:
461 config2 = 0x02;
462 break;
463 case 16000:
464 config2 = 0x03;
465 break;
466 case 22050:
467 config2 = 0x04;
468 break;
469 case 24000:
470 config2 = 0x05;
471 break;
472 case 32000:
473 config2 = 0x07;
474 break;
475 case 44100:
476 config2 = 0x08;
477 break;
478 case 48000:
479 config2 = 0x09;
480 break;
481 }
482
483 snd_pmic_ops_nc.num_channel = num_channel;
484 if (snd_pmic_ops_nc.num_channel == 1) {
485
486 sc_access.value = 0x07;
487 sc_access.reg_addr = RMUTE;
488 pr_debug("RIGHT_HP_MUTE value%d\n", sc_access.value);
489 sc_access.mask = MASK2;
490 sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
491 } else {
492 sc_access.value = 0x00;
493 sc_access.reg_addr = RMUTE;
494 pr_debug("RIGHT_HP_MUTE value %d\n", sc_access.value);
495 sc_access.mask = MASK2;
496 sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
497
498
499 }
500
501 pr_debug("word_size = %d\n", word_size);
502
503 if (word_size == 24) {
504 sc_access.reg_addr = AUDIOPORT2;
505 sc_access.value = config2 | 0x10;
506 sc_access.mask = 0x1F;
507 } else {
508 sc_access.value = config2;
509 sc_access.mask = 0x1F;
510 sc_access.reg_addr = AUDIOPORT2;
511 }
512 sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
513
514 pr_debug("word_size = %d\n", word_size);
515 sc_access.reg_addr = AUDIOPORT1;
516 sc_access.mask = MASK5|MASK4|MASK1|MASK0;
517 if (word_size == 16)
518 sc_access.value = 0x98;
519 else if (word_size == 24)
520 sc_access.value = 0xAB;
521
522 return sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
523
524
525
526}
527
528static int nc_set_selected_output_dev(u8 value)
529{
530 struct sc_reg_access sc_access_HP[] = {
531 {LMUTE, 0x02, 0x06},
532 {RMUTE, 0x02, 0x06},
533 {DRVPOWERCTRL, 0x06, 0x06},
534 };
535 struct sc_reg_access sc_access_IS[] = {
536 {LMUTE, 0x04, 0x06},
537 {RMUTE, 0x04, 0x06},
538 {DRVPOWERCTRL, 0x00, 0x06},
539 };
540 int retval = 0;
541
542 snd_pmic_ops_nc.output_dev_id = value;
543 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
544 retval = nc_init_card();
545 if (retval)
546 return retval;
547 pr_debug("nc set selected output:%d\n", value);
548 mutex_lock(&snd_pmic_ops_nc.lock);
549 switch (value) {
550 case STEREO_HEADPHONE:
551 if (snd_pmic_ops_nc.pb_on)
552 sst_sc_reg_access(sc_access_HP+2, PMIC_WRITE, 1);
553 retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2);
554 nc_set_amp_power(0);
555 break;
556 case MONO_EARPIECE:
557 case INTERNAL_SPKR:
558 retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 3);
559 if (snd_pmic_ops_nc.pb_on)
560 nc_set_amp_power(1);
561 break;
562 default:
563 pr_err("rcvd illegal request: %d\n", value);
564 mutex_unlock(&snd_pmic_ops_nc.lock);
565 return -EINVAL;
566 }
567 mutex_unlock(&snd_pmic_ops_nc.lock);
568 return retval;
569}
570
571static int nc_audio_init(void)
572{
573 struct sc_reg_access sc_acces, sc_access[] = {
574 {0x100, 0x00, 0},
575 {0x101, 0x00, 0},
576 {0x104, 0x8B, 0},
577 {0x107, 0x11, 0},
578 {0x10B, 0x0E, 0},
579 {0x114, 0x00, 0},
580 {0x115, 0x00, 0},
581 {0x128, 0x00, 0},
582 {0x129, 0x00, 0},
583 {0x12A, 0x00, 0},
584 {0x12B, 0xee, 0},
585 {0x12C, 0xf6, 0},
586 };
587
588 sst_sc_reg_access(sc_access, PMIC_WRITE, 12);
589 pr_debug("Audio Init successfully!!\n");
590
591 /*set output device */
592 nc_set_selected_output_dev(snd_pmic_ops_nc.output_dev_id);
593
594 if (snd_pmic_ops_nc.num_channel == 1) {
595 sc_acces.value = 0x07;
596 sc_acces.reg_addr = RMUTE;
597 pr_debug("RIGHT_HP_MUTE value%d\n", sc_acces.value);
598 sc_acces.mask = MASK2;
599 sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
600 } else {
601 sc_acces.value = 0x00;
602 sc_acces.reg_addr = RMUTE;
603 pr_debug("RIGHT_HP_MUTE value%d\n", sc_acces.value);
604 sc_acces.mask = MASK2;
605 sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
606 }
607
608 return 0;
609}
610
611static int nc_set_audio_port(int status)
612{
613 struct sc_reg_access sc_access[2] = {{0,},};
614 int retval = 0;
615
616 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
617 retval = nc_init_card();
618 if (retval)
619 return retval;
620
621 if (status == DEACTIVATE) {
622 /* Deactivate audio port-tristate and power */
623 sc_access[0].value = 0x00;
624 sc_access[0].mask = MASK4|MASK5;
625 sc_access[0].reg_addr = AUDIOPORT1;
626 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
627 } else if (status == ACTIVATE) {
628 /* activate audio port */
629 nc_audio_init();
630 sc_access[0].value = 0x10;
631 sc_access[0].mask = MASK4|MASK5 ;
632 sc_access[0].reg_addr = AUDIOPORT1;
633 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
634 } else
635 return -EINVAL;
636
637}
638
639static int nc_set_voice_port(int status)
640{
641 struct sc_reg_access sc_access[2] = {{0,},};
642 int retval = 0;
643
644 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
645 retval = nc_init_card();
646 if (retval)
647 return retval;
648
649 if (status == DEACTIVATE) {
650 /* Activate Voice port */
651 sc_access[0].value = 0x00;
652 sc_access[0].mask = MASK4;
653 sc_access[0].reg_addr = VOICEPORT1;
654 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
655 } else if (status == ACTIVATE) {
656 /* Deactivate voice port */
657 nc_set_pcm_voice_params();
658 sc_access[0].value = 0x10;
659 sc_access[0].mask = MASK4;
660 sc_access[0].reg_addr = VOICEPORT1;
661 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
662 } else
663 return -EINVAL;
664}
665
666static int nc_set_mute(int dev_id, u8 value)
667{
668 struct sc_reg_access sc_access[3];
669 u8 mute_val, cap_mute;
670 int retval = 0;
671
672 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
673 retval = nc_init_card();
674 if (retval)
675 return retval;
676
677 pr_debug("set device id::%d, value %d\n", dev_id, value);
678
679 switch (dev_id) {
680 case PMIC_SND_MUTE_ALL:
681 pr_debug("PMIC_SND_MUTE_ALL value %d\n", value);
682 snd_pmic_ops_nc.mute_status = value;
683 snd_pmic_ops_nc.master_mute = value;
684 if (value == UNMUTE) {
685 /* unmute the system, set the 7th bit to zero */
686 mute_val = cap_mute = 0x00;
687 } else {
688 /* MUTE:Set the seventh bit */
689 mute_val = 0x80;
690 cap_mute = 0x40;
691 }
692 sc_access[0].reg_addr = AUDIOLVOL;
693 sc_access[1].reg_addr = AUDIORVOL;
694 sc_access[0].mask = sc_access[1].mask = MASK7;
695 sc_access[0].value = sc_access[1].value = mute_val;
696 if (snd_pmic_ops_nc.num_channel == 1)
697 sc_access[1].value = 0x80;
698 if (!sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2)) {
699 sc_access[0].reg_addr = 0x109;
700 sc_access[1].reg_addr = 0x10a;
701 sc_access[2].reg_addr = 0x105;
702 sc_access[0].mask = sc_access[1].mask =
703 sc_access[2].mask = MASK6;
704 sc_access[0].value = sc_access[1].value =
705 sc_access[2].value = cap_mute;
706
707 if ((snd_pmic_ops_nc.input_dev_id == AMIC) ||
708 (snd_pmic_ops_nc.input_dev_id == DMIC))
709 sc_access[1].value = 0x40;
710 if (snd_pmic_ops_nc.input_dev_id == HS_MIC)
711 sc_access[0].value = 0x40;
712 retval = sst_sc_reg_access(sc_access,
713 PMIC_READ_MODIFY, 3);
714 }
715 break;
716 case PMIC_SND_HP_MIC_MUTE:
717 pr_debug("PMIC_SND_HPMIC_MUTE value %d\n", value);
718 if (value == UNMUTE) {
719 /* unmute the system, set the 6th bit to one */
720 sc_access[0].value = 0x00;
721 } else {
722 /* mute the system, reset the 6th bit to zero */
723 sc_access[0].value = 0x40;
724 }
725 sc_access[0].reg_addr = LIRSEL;
726 sc_access[0].mask = MASK6;
727 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
728 break;
729 case PMIC_SND_AMIC_MUTE:
730 pr_debug("PMIC_SND_AMIC_MUTE value %d\n", value);
731 if (value == UNMUTE) {
732 /* unmute the system, set the 6th bit to one */
733 sc_access[0].value = 0x00;
734 } else {
735 /* mute the system, reset the 6th bit to zero */
736 sc_access[0].value = 0x40;
737 }
738 sc_access[0].reg_addr = LILSEL;
739 sc_access[0].mask = MASK6;
740 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
741 break;
742
743 case PMIC_SND_DMIC_MUTE:
744 pr_debug("INPUT_MUTE_DMIC value%d\n", value);
745 if (value == UNMUTE) {
746 /* unmute the system, set the 6th bit to one */
747 sc_access[1].value = 0x00;
748 sc_access[0].value = 0x00;
749 } else {
750 /* mute the system, reset the 6th bit to zero */
751 sc_access[1].value = 0x40;
752 sc_access[0].value = 0x40;
753 }
754 sc_access[0].reg_addr = DMICCTRL1;
755 sc_access[0].mask = MASK6;
756 sc_access[1].reg_addr = LILSEL;
757 sc_access[1].mask = MASK6;
758 retval = sst_sc_reg_access(sc_access,
759 PMIC_READ_MODIFY, 2);
760 break;
761
762 case PMIC_SND_LEFT_HP_MUTE:
763 case PMIC_SND_RIGHT_HP_MUTE:
764 snd_pmic_ops_nc.mute_status = value;
765 if (value == UNMUTE)
766 sc_access[0].value = 0x0;
767 else
768 sc_access[0].value = 0x04;
769
770 if (dev_id == PMIC_SND_LEFT_HP_MUTE) {
771 sc_access[0].reg_addr = LMUTE;
772 pr_debug("LEFT_HP_MUTE value %d\n",
773 sc_access[0].value);
774 } else {
775 if (snd_pmic_ops_nc.num_channel == 1)
776 sc_access[0].value = 0x04;
777 sc_access[0].reg_addr = RMUTE;
778 pr_debug("RIGHT_HP_MUTE value %d\n",
779 sc_access[0].value);
780 }
781 sc_access[0].mask = MASK2;
782 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
783 break;
784 case PMIC_SND_LEFT_SPEAKER_MUTE:
785 case PMIC_SND_RIGHT_SPEAKER_MUTE:
786 if (value == UNMUTE)
787 sc_access[0].value = 0x00;
788 else
789 sc_access[0].value = 0x03;
790 sc_access[0].reg_addr = LMUTE;
791 pr_debug("SPEAKER_MUTE %d\n", sc_access[0].value);
792 sc_access[0].mask = MASK1;
793 retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
794 break;
795 default:
796 return -EINVAL;
797 }
798 return retval ;
799
800}
801
802static int nc_set_vol(int dev_id, int value)
803{
804 struct sc_reg_access sc_access[3];
805 int retval = 0, entries = 0;
806
807 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
808 retval = nc_init_card();
809 if (retval)
810 return retval;
811
812 pr_debug("set volume:%d\n", dev_id);
813 switch (dev_id) {
814 case PMIC_SND_CAPTURE_VOL:
815 pr_debug("PMIC_SND_CAPTURE_VOL:value::%d\n", value);
816 sc_access[0].value = sc_access[1].value =
817 sc_access[2].value = -value;
818 sc_access[0].mask = sc_access[1].mask = sc_access[2].mask =
819 (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
820 sc_access[0].reg_addr = 0x10a;
821 sc_access[1].reg_addr = 0x109;
822 sc_access[2].reg_addr = 0x105;
823 entries = 3;
824 break;
825
826 case PMIC_SND_LEFT_PB_VOL:
827 pr_debug("PMIC_SND_LEFT_HP_VOL %d\n", value);
828 sc_access[0].value = -value;
829 sc_access[0].reg_addr = HPLVOL;
830 sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
831 entries = 1;
832 break;
833
834 case PMIC_SND_RIGHT_PB_VOL:
835 pr_debug("PMIC_SND_RIGHT_HP_VOL value %d\n", value);
836 if (snd_pmic_ops_nc.num_channel == 1) {
837 sc_access[0].value = 0x04;
838 sc_access[0].reg_addr = RMUTE;
839 sc_access[0].mask = MASK2;
840 } else {
841 sc_access[0].value = -value;
842 sc_access[0].reg_addr = HPRVOL;
843 sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
844 }
845 entries = 1;
846 break;
847
848 case PMIC_SND_LEFT_MASTER_VOL:
849 pr_debug("PMIC_SND_LEFT_MASTER_VOL value %d\n", value);
850 sc_access[0].value = -value;
851 sc_access[0].reg_addr = AUDIOLVOL;
852 sc_access[0].mask =
853 (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
854 entries = 1;
855 break;
856
857 case PMIC_SND_RIGHT_MASTER_VOL:
858 pr_debug("PMIC_SND_RIGHT_MASTER_VOL value %d\n", value);
859 sc_access[0].value = -value;
860 sc_access[0].reg_addr = AUDIORVOL;
861 sc_access[0].mask =
862 (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
863 entries = 1;
864 break;
865
866 default:
867 return -EINVAL;
868
869 }
870 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, entries);
871}
872
873static int nc_set_selected_input_dev(u8 value)
874{
875 struct sc_reg_access sc_access[6];
876 u8 num_val;
877 int retval = 0;
878
879 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
880 retval = nc_init_card();
881 if (retval)
882 return retval;
883 snd_pmic_ops_nc.input_dev_id = value;
884
885 pr_debug("nc set selected input:%d\n", value);
886
887 switch (value) {
888 case AMIC:
889 pr_debug("Selecting AMIC\n");
890 sc_access[0].reg_addr = 0x107;
891 sc_access[0].value = 0x40;
892 sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
893 sc_access[1].reg_addr = 0x10a;
894 sc_access[1].value = 0x40;
895 sc_access[1].mask = MASK6;
896 sc_access[2].reg_addr = 0x109;
897 sc_access[2].value = 0x00;
898 sc_access[2].mask = MASK6;
899 sc_access[3].reg_addr = 0x105;
900 sc_access[3].value = 0x40;
901 sc_access[3].mask = MASK6;
902 num_val = 4;
903 break;
904
905 case HS_MIC:
906 pr_debug("Selecting HS_MIC\n");
907 sc_access[0].reg_addr = MICCTRL;
908 sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
909 sc_access[0].value = 0x00;
910 sc_access[1].reg_addr = 0x109;
911 sc_access[1].mask = MASK6;
912 sc_access[1].value = 0x40;
913 sc_access[2].reg_addr = 0x10a;
914 sc_access[2].mask = MASK6;
915 sc_access[2].value = 0x00;
916 sc_access[3].reg_addr = 0x105;
917 sc_access[3].value = 0x40;
918 sc_access[3].mask = MASK6;
919 sc_access[4].reg_addr = ADCSAMPLERATE;
920 sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
921 sc_access[4].value = 0xc8;
922 num_val = 5;
923 break;
924
925 case DMIC:
926 pr_debug("DMIC\n");
927 sc_access[0].reg_addr = MICCTRL;
928 sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
929 sc_access[0].value = 0x0B;
930 sc_access[1].reg_addr = 0x105;
931 sc_access[1].value = 0x80;
932 sc_access[1].mask = MASK7|MASK6;
933 sc_access[2].reg_addr = 0x10a;
934 sc_access[2].value = 0x40;
935 sc_access[2].mask = MASK6;
936 sc_access[3].reg_addr = LILSEL;
937 sc_access[3].mask = MASK6;
938 sc_access[3].value = 0x00;
939 sc_access[4].reg_addr = ADCSAMPLERATE;
940 sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
941 sc_access[4].value = 0x33;
942 num_val = 5;
943 break;
944 default:
945 return -EINVAL;
946 }
947 return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
948}
949
950static int nc_get_mute(int dev_id, u8 *value)
951{
952 int retval = 0, mask = 0;
953 struct sc_reg_access sc_access = {0,};
954
955 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
956 retval = nc_init_card();
957 if (retval)
958 return retval;
959
960 pr_debug("get mute::%d\n", dev_id);
961
962 switch (dev_id) {
963 case PMIC_SND_AMIC_MUTE:
964 pr_debug("PMIC_SND_INPUT_MUTE_MIC1\n");
965 sc_access.reg_addr = LILSEL;
966 mask = MASK6;
967 break;
968 case PMIC_SND_HP_MIC_MUTE:
969 pr_debug("PMIC_SND_INPUT_MUTE_MIC2\n");
970 sc_access.reg_addr = LIRSEL;
971 mask = MASK6;
972 break;
973 case PMIC_SND_LEFT_HP_MUTE:
974 case PMIC_SND_RIGHT_HP_MUTE:
975 mask = MASK2;
976 pr_debug("PMIC_SN_LEFT/RIGHT_HP_MUTE\n");
977 if (dev_id == PMIC_SND_RIGHT_HP_MUTE)
978 sc_access.reg_addr = RMUTE;
979 else
980 sc_access.reg_addr = LMUTE;
981 break;
982
983 case PMIC_SND_LEFT_SPEAKER_MUTE:
984 pr_debug("PMIC_MONO_EARPIECE_MUTE\n");
985 sc_access.reg_addr = RMUTE;
986 mask = MASK1;
987 break;
988 case PMIC_SND_DMIC_MUTE:
989 pr_debug("PMIC_SND_INPUT_MUTE_DMIC\n");
990 sc_access.reg_addr = 0x105;
991 mask = MASK6;
992 break;
993 default:
994 return -EINVAL;
995
996 }
997 retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
998 pr_debug("reg value = %d\n", sc_access.value);
999 if (retval)
1000 return retval;
1001 *value = (sc_access.value) & mask;
1002 pr_debug("masked value = %d\n", *value);
1003 if (*value)
1004 *value = 0;
1005 else
1006 *value = 1;
1007 pr_debug("value returned = 0x%x\n", *value);
1008 return retval;
1009}
1010
1011static int nc_get_vol(int dev_id, int *value)
1012{
1013 int retval = 0, mask = 0;
1014 struct sc_reg_access sc_access = {0,};
1015
1016 if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
1017 retval = nc_init_card();
1018 if (retval)
1019 return retval;
1020
1021 switch (dev_id) {
1022 case PMIC_SND_CAPTURE_VOL:
1023 pr_debug("PMIC_SND_INPUT_CAPTURE_VOL\n");
1024 sc_access.reg_addr = LILSEL;
1025 mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
1026 break;
1027
1028 case PMIC_SND_LEFT_MASTER_VOL:
1029 pr_debug("GET_VOLUME_PMIC_LEFT_MASTER_VOL\n");
1030 sc_access.reg_addr = AUDIOLVOL;
1031 mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
1032 break;
1033
1034 case PMIC_SND_RIGHT_MASTER_VOL:
1035 pr_debug("GET_VOLUME_PMIC_RIGHT_MASTER_VOL\n");
1036 sc_access.reg_addr = AUDIORVOL;
1037 mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
1038 break;
1039
1040 case PMIC_SND_RIGHT_PB_VOL:
1041 pr_debug("GET_VOLUME_PMIC_RIGHT_HP_VOL\n");
1042 sc_access.reg_addr = HPRVOL;
1043 mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
1044 break;
1045
1046 case PMIC_SND_LEFT_PB_VOL:
1047 pr_debug("GET_VOLUME_PMIC_LEFT_HP_VOL\n");
1048 sc_access.reg_addr = HPLVOL;
1049 mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
1050 break;
1051
1052 default:
1053 return -EINVAL;
1054
1055 }
1056 retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
1057 pr_debug("value read = 0x%x\n", sc_access.value);
1058 *value = -((sc_access.value) & mask);
1059 pr_debug("get vol value returned = %d\n", *value);
1060 return retval;
1061}
1062
1063static void hp_automute(enum snd_jack_types type, int present)
1064{
1065 u8 in = DMIC;
1066 u8 out = INTERNAL_SPKR;
1067 if (present) {
1068 if (type == SND_JACK_HEADSET)
1069 in = HS_MIC;
1070 out = STEREO_HEADPHONE;
1071 }
1072 nc_set_selected_input_dev(in);
1073 nc_set_selected_output_dev(out);
1074}
1075
1076static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
1077{
1078 u8 value = 0;
1079 struct mad_jack *mjack = NULL;
1080 unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
1081 struct snd_intelmad *intelmaddata = cb_data;
1082 struct sc_reg_access sc_access_read = {0,};
1083
1084 sc_access_read.reg_addr = 0x132;
1085 sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
1086 value = (sc_access_read.value);
1087 pr_debug("value returned = 0x%x\n", value);
1088
1089 mjack = &intelmaddata->jack[0];
1090 if (intsts & 0x1) {
1091 pr_debug("SST DBG:MAD headset detected\n");
1092 /* send headset detect/undetect */
1093 present = (value == 0x1) ? 3 : 0;
1094 jack_event_flag = 1;
1095 mjack->jack.type = SND_JACK_HEADSET;
1096 hp_automute(SND_JACK_HEADSET, present);
1097 }
1098
1099 if (intsts & 0x2) {
1100 pr_debug(":MAD headphone detected\n");
1101 /* send headphone detect/undetect */
1102 present = (value == 0x2) ? 1 : 0;
1103 jack_event_flag = 1;
1104 mjack->jack.type = SND_JACK_HEADPHONE;
1105 hp_automute(SND_JACK_HEADPHONE, present);
1106 }
1107
1108 if (intsts & 0x4) {
1109 pr_debug("MAD short push detected\n");
1110 /* send short push */
1111 present = 1;
1112 jack_event_flag = 1;
1113 buttonpressflag = 1;
1114 mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
1115 }
1116
1117 if (intsts & 0x8) {
1118 pr_debug(":MAD long push detected\n");
1119 /* send long push */
1120 present = 1;
1121 jack_event_flag = 1;
1122 buttonpressflag = 1;
1123 mjack->jack.type = MID_JACK_HS_LONG_PRESS;
1124 }
1125
1126 if (jack_event_flag)
1127 sst_mad_send_jack_report(&mjack->jack,
1128 buttonpressflag, present);
1129}
1130static int nc_jack_enable(void)
1131{
1132 return 0;
1133}
1134
1135struct snd_pmic_ops snd_pmic_ops_nc = {
1136 .input_dev_id = DMIC,
1137 .output_dev_id = INTERNAL_SPKR,
1138 .set_input_dev = nc_set_selected_input_dev,
1139 .set_output_dev = nc_set_selected_output_dev,
1140 .set_mute = nc_set_mute,
1141 .get_mute = nc_get_mute,
1142 .set_vol = nc_set_vol,
1143 .get_vol = nc_get_vol,
1144 .init_card = nc_init_card,
1145 .set_pcm_audio_params = nc_set_pcm_audio_params,
1146 .set_pcm_voice_params = nc_set_pcm_voice_params,
1147 .set_voice_port = nc_set_voice_port,
1148 .set_audio_port = nc_set_audio_port,
1149 .power_up_pmic_pb = nc_power_up_pb,
1150 .power_up_pmic_cp = nc_power_up_cp,
1151 .power_down_pmic_pb = nc_power_down_pb,
1152 .power_down_pmic_cp = nc_power_down_cp,
1153 .power_down_pmic = nc_power_down,
1154 .pmic_irq_cb = nc_pmic_irq_cb,
1155 .pmic_jack_enable = nc_jack_enable,
1156};