aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt7
-rw-r--r--sound/pci/Kconfig9
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/lola/Makefile3
-rw-r--r--sound/pci/lola/lola.c731
-rw-r--r--sound/pci/lola/lola.h520
-rw-r--r--sound/pci/lola/lola_clock.c322
-rw-r--r--sound/pci/lola/lola_mixer.c826
-rw-r--r--sound/pci/lola/lola_pcm.c607
-rw-r--r--sound/pci/lola/lola_proc.c86
10 files changed, 3112 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 3c1eddd9fcc7..caf3ae2fe07b 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1230,6 +1230,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1230 This module supports multiple cards. 1230 This module supports multiple cards.
1231 The driver requires the firmware loader support on kernel. 1231 The driver requires the firmware loader support on kernel.
1232 1232
1233 Module snd-lola
1234 ---------------
1235
1236 Module for Digigram Lola PCI-e boards
1237
1238 This module supports multiple cards.
1239
1233 Module snd-lx6464es 1240 Module snd-lx6464es
1234 ------------------- 1241 -------------------
1235 1242
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 9823d59d7ad7..92ead69cc4b7 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -652,6 +652,15 @@ config SND_KORG1212
652 To compile this driver as a module, choose M here: the module 652 To compile this driver as a module, choose M here: the module
653 will be called snd-korg1212. 653 will be called snd-korg1212.
654 654
655config SND_LOLA
656 tristate "Digigram Lola"
657 select SND_PCM
658 help
659 Say Y to include support for Digigram Lola boards.
660
661 To compile this driver as a module, choose M here: the module
662 will be called snd-lola.
663
655config SND_LX6464ES 664config SND_LX6464ES
656 tristate "Digigram LX6464ES" 665 tristate "Digigram LX6464ES"
657 select SND_PCM 666 select SND_PCM
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 9cf4348ec137..54fe325e3aa5 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_SND) += \
64 ca0106/ \ 64 ca0106/ \
65 cs46xx/ \ 65 cs46xx/ \
66 cs5535audio/ \ 66 cs5535audio/ \
67 lola/ \
67 lx6464es/ \ 68 lx6464es/ \
68 echoaudio/ \ 69 echoaudio/ \
69 emu10k1/ \ 70 emu10k1/ \
diff --git a/sound/pci/lola/Makefile b/sound/pci/lola/Makefile
new file mode 100644
index 000000000000..674715a84965
--- /dev/null
+++ b/sound/pci/lola/Makefile
@@ -0,0 +1,3 @@
1snd-lola-y := lola.o lola_pcm.o lola_clock.o lola_mixer.o
2snd-lola-$(CONFIG_SND_DEBUG) += lola_proc.o
3obj-m = snd-lola.o
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
new file mode 100644
index 000000000000..f59ce085a1a4
--- /dev/null
+++ b/sound/pci/lola/lola.c
@@ -0,0 +1,731 @@
1/*
2 * Support for Digigram Lola PCI-e boards
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/moduleparam.h>
24#include <linux/dma-mapping.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/slab.h>
28#include <linux/pci.h>
29#include <sound/core.h>
30#include <sound/control.h>
31#include <sound/pcm.h>
32#include <sound/initval.h>
33#include "lola.h"
34
35static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
36static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
37static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
38
39module_param_array(index, int, NULL, 0444);
40MODULE_PARM_DESC(index, "Index value for Digigram Lola driver.");
41module_param_array(id, charp, NULL, 0444);
42MODULE_PARM_DESC(id, "ID string for Digigram Lola driver.");
43module_param_array(enable, bool, NULL, 0444);
44MODULE_PARM_DESC(enable, "Enable Digigram Lola driver.");
45
46MODULE_LICENSE("GPL");
47MODULE_SUPPORTED_DEVICE("{{Digigram, Lola}}");
48MODULE_DESCRIPTION("Digigram Lola driver");
49MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
50
51#ifdef CONFIG_SND_DEBUG_VERBOSE
52static int debug;
53module_param(debug, int, 0644);
54#define verbose_debug(fmt, args...) \
55 do { if (debug > 1) printk(KERN_DEBUG SFX fmt, ##args); } while (0)
56#else
57#define verbose_debug(fmt, args...)
58#endif
59
60/*
61 * pseudo-codec read/write via CORB/RIRB
62 */
63
64static int corb_send_verb(struct lola *chip, unsigned int nid,
65 unsigned int verb, unsigned int data,
66 unsigned int extdata)
67{
68 unsigned long flags;
69 int ret = -EIO;
70
71 chip->last_cmd_nid = nid;
72 chip->last_verb = verb;
73 chip->last_data = data;
74 chip->last_extdata = extdata;
75 data |= (nid << 20) | (verb << 8);
76 spin_lock_irqsave(&chip->reg_lock, flags);
77 if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) {
78 unsigned int wp = chip->corb.wp + 1;
79 wp %= LOLA_CORB_ENTRIES;
80 chip->corb.wp = wp;
81 chip->corb.buf[wp * 2] = cpu_to_le32(data);
82 chip->corb.buf[wp * 2 + 1] = cpu_to_le32(extdata);
83 lola_writew(chip, BAR0, CORBWP, wp);
84 chip->rirb.cmds++;
85 smp_wmb();
86 ret = 0;
87 }
88 spin_unlock_irqrestore(&chip->reg_lock, flags);
89 return ret;
90}
91
92static void lola_queue_unsol_event(struct lola *chip, unsigned int res,
93 unsigned int res_ex)
94{
95 lola_update_ext_clock_freq(chip, res);
96}
97
98/* retrieve RIRB entry - called from interrupt handler */
99static void lola_update_rirb(struct lola *chip)
100{
101 unsigned int rp, wp;
102 u32 res, res_ex;
103
104 wp = lola_readw(chip, BAR0, RIRBWP);
105 if (wp == chip->rirb.wp)
106 return;
107 chip->rirb.wp = wp;
108
109 while (chip->rirb.rp != wp) {
110 chip->rirb.rp++;
111 chip->rirb.rp %= LOLA_CORB_ENTRIES;
112
113 rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
114 res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
115 res = le32_to_cpu(chip->rirb.buf[rp]);
116 if (res_ex & LOLA_RIRB_EX_UNSOL_EV)
117 lola_queue_unsol_event(chip, res, res_ex);
118 else if (chip->rirb.cmds) {
119 chip->res = res;
120 chip->res_ex = res_ex;
121 smp_wmb();
122 chip->rirb.cmds--;
123 }
124 }
125}
126
127static int rirb_get_response(struct lola *chip, unsigned int *val,
128 unsigned int *extval)
129{
130 unsigned long timeout;
131
132 timeout = jiffies + msecs_to_jiffies(1000);
133 for (;;) {
134 if (!chip->rirb.cmds) {
135 *val = chip->res;
136 if (extval)
137 *extval = chip->res_ex;
138 verbose_debug("get_response: %x, %x\n",
139 chip->res, chip->res_ex);
140 if (chip->res_ex & LOLA_RIRB_EX_ERROR) {
141 printk(KERN_WARNING SFX "RIRB ERROR: "
142 "NID=%x, verb=%x, data=%x, ext=%x\n",
143 chip->last_cmd_nid,
144 chip->last_verb, chip->last_data,
145 chip->last_extdata);
146 return -EIO;
147 }
148 return 0;
149 }
150 if (time_after(jiffies, timeout))
151 break;
152 udelay(20);
153 cond_resched();
154 lola_update_rirb(chip);
155 }
156 printk(KERN_WARNING SFX "RIRB response error\n");
157 return -EIO;
158}
159
160/* aynchronous write of a codec verb with data */
161int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb,
162 unsigned int data, unsigned int extdata)
163{
164 verbose_debug("codec_write NID=%x, verb=%x, data=%x, ext=%x\n",
165 nid, verb, data, extdata);
166 return corb_send_verb(chip, nid, verb, data, extdata);
167}
168
169/* write a codec verb with data and read the returned status */
170int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb,
171 unsigned int data, unsigned int extdata,
172 unsigned int *val, unsigned int *extval)
173{
174 int err;
175
176 verbose_debug("codec_read NID=%x, verb=%x, data=%x, ext=%x\n",
177 nid, verb, data, extdata);
178 err = corb_send_verb(chip, nid, verb, data, extdata);
179 if (err < 0)
180 return err;
181 err = rirb_get_response(chip, val, extval);
182 return err;
183}
184
185/* flush all pending codec writes */
186int lola_codec_flush(struct lola *chip)
187{
188 unsigned int tmp;
189 return rirb_get_response(chip, &tmp, NULL);
190}
191
192/*
193 * interrupt handler
194 */
195static irqreturn_t lola_interrupt(int irq, void *dev_id)
196{
197 struct lola *chip = dev_id;
198 unsigned int notify_ins, notify_outs, error_ins, error_outs;
199 int handled = 0;
200 int i;
201
202 notify_ins = notify_outs = error_ins = error_outs = 0;
203 spin_lock(&chip->reg_lock);
204 for (;;) {
205 unsigned int status, in_sts, out_sts;
206 unsigned int reg;
207
208 status = lola_readl(chip, BAR1, DINTSTS);
209 if (!status || status == -1)
210 break;
211
212 in_sts = lola_readl(chip, BAR1, DIINTSTS);
213 out_sts = lola_readl(chip, BAR1, DOINTSTS);
214
215 /* clear Input Interrupts */
216 for (i = 0; in_sts && i < chip->pcm[CAPT].num_streams; i++) {
217 if (!(in_sts & (1 << i)))
218 continue;
219 in_sts &= ~(1 << i);
220 reg = lola_dsd_read(chip, i, STS);
221 if (reg & LOLA_DSD_STS_DESE) /* error */
222 error_ins |= (1 << i);
223 if (reg & LOLA_DSD_STS_BCIS) /* notify */
224 notify_ins |= (1 << i);
225 /* clear */
226 lola_dsd_write(chip, i, STS, reg);
227 }
228
229 /* clear Output Interrupts */
230 for (i = 0; out_sts && i < chip->pcm[PLAY].num_streams; i++) {
231 if (!(out_sts & (1 << i)))
232 continue;
233 out_sts &= ~(1 << i);
234 reg = lola_dsd_read(chip, i + MAX_STREAM_IN_COUNT, STS);
235 if (reg & LOLA_DSD_STS_DESE) /* error */
236 error_outs |= (1 << i);
237 if (reg & LOLA_DSD_STS_BCIS) /* notify */
238 notify_outs |= (1 << i);
239 lola_dsd_write(chip, i + MAX_STREAM_IN_COUNT, STS, reg);
240 }
241
242 if (status & LOLA_DINT_CTRL) {
243 unsigned char rbsts; /* ring status is byte access */
244 rbsts = lola_readb(chip, BAR0, RIRBSTS);
245 rbsts &= LOLA_RIRB_INT_MASK;
246 if (rbsts)
247 lola_writeb(chip, BAR0, RIRBSTS, rbsts);
248 rbsts = lola_readb(chip, BAR0, CORBSTS);
249 rbsts &= LOLA_CORB_INT_MASK;
250 if (rbsts)
251 lola_writeb(chip, BAR0, CORBSTS, rbsts);
252
253 lola_update_rirb(chip);
254 }
255
256 if (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR)) {
257 /* clear global fifo error interrupt */
258 lola_writel(chip, BAR1, DINTSTS,
259 (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR)));
260 }
261 handled = 1;
262 }
263 spin_unlock(&chip->reg_lock);
264
265 lola_pcm_update(chip, &chip->pcm[CAPT], notify_ins);
266 lola_pcm_update(chip, &chip->pcm[PLAY], notify_outs);
267
268 return IRQ_RETVAL(handled);
269}
270
271
272/*
273 * controller
274 */
275static int reset_controller(struct lola *chip)
276{
277 unsigned int gctl = lola_readl(chip, BAR0, GCTL);
278 unsigned long end_time;
279
280 if (gctl) {
281 /* to be sure */
282 lola_writel(chip, BAR1, BOARD_MODE, 0);
283 return 0;
284 }
285
286 chip->cold_reset = 1;
287 lola_writel(chip, BAR0, GCTL, LOLA_GCTL_RESET);
288 end_time = jiffies + msecs_to_jiffies(200);
289 do {
290 msleep(1);
291 gctl = lola_readl(chip, BAR0, GCTL);
292 if (gctl)
293 break;
294 } while (time_before(jiffies, end_time));
295 if (!gctl) {
296 printk(KERN_ERR SFX "cannot reset controller\n");
297 return -EIO;
298 }
299 return 0;
300}
301
302static void lola_irq_enable(struct lola *chip)
303{
304 unsigned int val;
305
306 /* enalbe all I/O streams */
307 val = (1 << chip->pcm[PLAY].num_streams) - 1;
308 lola_writel(chip, BAR1, DOINTCTL, val);
309 val = (1 << chip->pcm[CAPT].num_streams) - 1;
310 lola_writel(chip, BAR1, DIINTCTL, val);
311
312 /* enable global irqs */
313 val = LOLA_DINT_GLOBAL | LOLA_DINT_CTRL | LOLA_DINT_FIFOERR |
314 LOLA_DINT_MUERR;
315 lola_writel(chip, BAR1, DINTCTL, val);
316}
317
318static void lola_irq_disable(struct lola *chip)
319{
320 lola_writel(chip, BAR1, DINTCTL, 0);
321 lola_writel(chip, BAR1, DIINTCTL, 0);
322 lola_writel(chip, BAR1, DOINTCTL, 0);
323}
324
325static int setup_corb_rirb(struct lola *chip)
326{
327 int err;
328 unsigned char tmp;
329 unsigned long end_time;
330
331 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
332 snd_dma_pci_data(chip->pci),
333 PAGE_SIZE, &chip->rb);
334 if (err < 0)
335 return err;
336
337 chip->corb.addr = chip->rb.addr;
338 chip->corb.buf = (u32 *)chip->rb.area;
339 chip->rirb.addr = chip->rb.addr + 2048;
340 chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
341 lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr);
342 lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr));
343
344 /* disable ringbuffer DMAs */
345 lola_writeb(chip, BAR0, RIRBCTL, 0);
346 lola_writeb(chip, BAR0, CORBCTL, 0);
347
348 end_time = jiffies + msecs_to_jiffies(200);
349 do {
350 if (!lola_readb(chip, BAR0, RIRBCTL) &&
351 !lola_readb(chip, BAR0, CORBCTL))
352 break;
353 msleep(1);
354 } while (time_before(jiffies, end_time));
355
356 /* CORB set up */
357 lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr);
358 lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr));
359 /* set the corb size to 256 entries */
360 lola_writeb(chip, BAR0, CORBSIZE, 0x02);
361 /* set the corb write pointer to 0 */
362 lola_writew(chip, BAR0, CORBWP, 0);
363 /* reset the corb hw read pointer */
364 lola_writew(chip, BAR0, CORBRP, LOLA_RBRWP_CLR);
365 /* enable corb dma */
366 lola_writeb(chip, BAR0, CORBCTL, LOLA_RBCTL_DMA_EN);
367 /* clear flags if set */
368 tmp = lola_readb(chip, BAR0, CORBSTS) & LOLA_CORB_INT_MASK;
369 if (tmp)
370 lola_writeb(chip, BAR0, CORBSTS, tmp);
371 chip->corb.wp = 0;
372
373 /* RIRB set up */
374 lola_writel(chip, BAR0, RIRBLBASE, (u32)chip->rirb.addr);
375 lola_writel(chip, BAR0, RIRBUBASE, upper_32_bits(chip->rirb.addr));
376 /* set the rirb size to 256 entries */
377 lola_writeb(chip, BAR0, RIRBSIZE, 0x02);
378 /* reset the rirb hw write pointer */
379 lola_writew(chip, BAR0, RIRBWP, LOLA_RBRWP_CLR);
380 /* set N=1, get RIRB response interrupt for new entry */
381 lola_writew(chip, BAR0, RINTCNT, 1);
382 /* enable rirb dma and response irq */
383 lola_writeb(chip, BAR0, RIRBCTL, LOLA_RBCTL_DMA_EN | LOLA_RBCTL_IRQ_EN);
384 /* clear flags if set */
385 tmp = lola_readb(chip, BAR0, RIRBSTS) & LOLA_RIRB_INT_MASK;
386 if (tmp)
387 lola_writeb(chip, BAR0, RIRBSTS, tmp);
388 chip->rirb.rp = chip->rirb.cmds = 0;
389
390 return 0;
391}
392
393static void stop_corb_rirb(struct lola *chip)
394{
395 /* disable ringbuffer DMAs */
396 lola_writeb(chip, BAR0, RIRBCTL, 0);
397 lola_writeb(chip, BAR0, CORBCTL, 0);
398}
399
400static void lola_reset_setups(struct lola *chip)
401{
402 /* update the granularity */
403 lola_set_granularity(chip, chip->granularity, true);
404 /* update the sample clock */
405 lola_set_clock_index(chip, chip->clock.cur_index);
406 /* enable unsolicited events of the clock widget */
407 lola_enable_clock_events(chip);
408 /* update the analog gains */
409 lola_setup_all_analog_gains(chip, CAPT, false); /* input, update */
410 /* update SRC configuration if applicable */
411 lola_set_src_config(chip, chip->input_src_mask, false);
412 /* update the analog outputs */
413 lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */
414}
415
416static int lola_parse_tree(struct lola *chip)
417{
418 unsigned int val;
419 int nid, err;
420
421 err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val);
422 if (err < 0) {
423 printk(KERN_ERR SFX "Can't read VENDOR_ID\n");
424 return err;
425 }
426 val >>= 16;
427 if (val != 0x1369) {
428 printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val);
429 return -EINVAL;
430 }
431
432 err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val);
433 if (err < 0) {
434 printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid);
435 return err;
436 }
437 if (val != 1) {
438 printk(KERN_ERR SFX "Unknown function type %d\n", val);
439 return -EINVAL;
440 }
441
442 err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val);
443 if (err < 0) {
444 printk(KERN_ERR SFX "Can't read SPECCAPS\n");
445 return err;
446 }
447 chip->lola_caps = val;
448 chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps);
449 chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps);
450 snd_printd(SFX "speccaps=0x%x, pins in=%d, out=%d\n",
451 chip->lola_caps,
452 chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins);
453
454 if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT ||
455 chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) {
456 printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val);
457 return -EINVAL;
458 }
459
460 nid = 0x02;
461 err = lola_init_pcm(chip, CAPT, &nid);
462 if (err < 0)
463 return err;
464 err = lola_init_pcm(chip, PLAY, &nid);
465 if (err < 0)
466 return err;
467
468 err = lola_init_pins(chip, CAPT, &nid);
469 if (err < 0)
470 return err;
471 err = lola_init_pins(chip, PLAY, &nid);
472 if (err < 0)
473 return err;
474
475 if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) {
476 err = lola_init_clock_widget(chip, nid);
477 if (err < 0)
478 return err;
479 nid++;
480 }
481 if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) {
482 err = lola_init_mixer_widget(chip, nid);
483 if (err < 0)
484 return err;
485 nid++;
486 }
487
488 /* enable unsolicited events of the clock widget */
489 err = lola_enable_clock_events(chip);
490 if (err < 0)
491 return err;
492
493 /* if last ResetController was not a ColdReset, we don't know
494 * the state of the card; initialize here again
495 */
496 if (!chip->cold_reset) {
497 lola_reset_setups(chip);
498 chip->cold_reset = 1;
499 }
500
501 return 0;
502}
503
504static void lola_stop_hw(struct lola *chip)
505{
506 stop_corb_rirb(chip);
507 lola_irq_disable(chip);
508}
509
510static void lola_free(struct lola *chip)
511{
512 if (chip->initialized)
513 lola_stop_hw(chip);
514 lola_free_pcm(chip);
515 lola_free_mixer(chip);
516 if (chip->irq >= 0)
517 free_irq(chip->irq, (void *)chip);
518 if (chip->bar[0].remap_addr)
519 iounmap(chip->bar[0].remap_addr);
520 if (chip->bar[1].remap_addr)
521 iounmap(chip->bar[1].remap_addr);
522 if (chip->rb.area)
523 snd_dma_free_pages(&chip->rb);
524 pci_release_regions(chip->pci);
525 pci_disable_device(chip->pci);
526 kfree(chip);
527}
528
529static int lola_dev_free(struct snd_device *device)
530{
531 lola_free(device->device_data);
532 return 0;
533}
534
535static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
536 struct lola **rchip)
537{
538 struct lola *chip;
539 int err;
540 unsigned int dever;
541 static struct snd_device_ops ops = {
542 .dev_free = lola_dev_free,
543 };
544
545 *rchip = NULL;
546
547 err = pci_enable_device(pci);
548 if (err < 0)
549 return err;
550
551 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
552 if (!chip) {
553 snd_printk(KERN_ERR SFX "cannot allocate chip\n");
554 pci_disable_device(pci);
555 return -ENOMEM;
556 }
557
558 spin_lock_init(&chip->reg_lock);
559 mutex_init(&chip->open_mutex);
560 chip->card = card;
561 chip->pci = pci;
562 chip->irq = -1;
563
564 chip->sample_rate_min = 48000;
565 chip->granularity = LOLA_GRANULARITY_MIN;
566
567 err = pci_request_regions(pci, DRVNAME);
568 if (err < 0) {
569 kfree(chip);
570 pci_disable_device(pci);
571 return err;
572 }
573
574 chip->bar[0].addr = pci_resource_start(pci, 0);
575 chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0);
576 chip->bar[1].addr = pci_resource_start(pci, 2);
577 chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2);
578 if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) {
579 snd_printk(KERN_ERR SFX "ioremap error\n");
580 err = -ENXIO;
581 goto errout;
582 }
583
584 pci_set_master(pci);
585
586 err = reset_controller(chip);
587 if (err < 0)
588 goto errout;
589
590 if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
591 DRVNAME, chip)) {
592 printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
593 err = -EBUSY;
594 goto errout;
595 }
596 chip->irq = pci->irq;
597 synchronize_irq(chip->irq);
598
599 dever = lola_readl(chip, BAR1, DEVER);
600 chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff;
601 chip->pcm[PLAY].num_streams = (dever >> 10) & 0x3ff;
602 chip->version = (dever >> 24) & 0xff;
603 snd_printd(SFX "streams in=%d, out=%d, version=0x%x\n",
604 chip->pcm[CAPT].num_streams, chip->pcm[PLAY].num_streams,
605 chip->version);
606
607 /* Test LOLA_BAR1_DEVER */
608 if (chip->pcm[CAPT].num_streams > MAX_STREAM_IN_COUNT ||
609 chip->pcm[PLAY].num_streams > MAX_STREAM_OUT_COUNT ||
610 (!chip->pcm[CAPT].num_streams &&
611 !chip->pcm[PLAY].num_streams)) {
612 printk(KERN_ERR SFX "invalid DEVER = %x\n", dever);
613 err = -EINVAL;
614 goto errout;
615 }
616
617 err = setup_corb_rirb(chip);
618 if (err < 0)
619 goto errout;
620
621 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
622 if (err < 0) {
623 snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
624 goto errout;
625 }
626
627 strcpy(card->driver, "Lola");
628 strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
629 snprintf(card->longname, sizeof(card->longname),
630 "%s at 0x%lx irq %i",
631 card->shortname, chip->bar[0].addr, chip->irq);
632 strcpy(card->mixername, card->shortname);
633
634 lola_irq_enable(chip);
635
636 chip->initialized = 1;
637 *rchip = chip;
638 return 0;
639
640 errout:
641 lola_free(chip);
642 return err;
643}
644
645static int __devinit lola_probe(struct pci_dev *pci,
646 const struct pci_device_id *pci_id)
647{
648 static int dev;
649 struct snd_card *card;
650 struct lola *chip;
651 int err;
652
653 if (dev >= SNDRV_CARDS)
654 return -ENODEV;
655 if (!enable[dev]) {
656 dev++;
657 return -ENOENT;
658 }
659
660 err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
661 if (err < 0) {
662 snd_printk(KERN_ERR SFX "Error creating card!\n");
663 return err;
664 }
665
666 snd_card_set_dev(card, &pci->dev);
667
668 err = lola_create(card, pci, &chip);
669 if (err < 0)
670 goto out_free;
671 card->private_data = chip;
672
673 err = lola_parse_tree(chip);
674 if (err < 0)
675 goto out_free;
676
677 err = lola_create_pcm(chip);
678 if (err < 0)
679 goto out_free;
680
681 err = lola_create_mixer(chip);
682 if (err < 0)
683 goto out_free;
684
685 lola_proc_debug_new(chip);
686
687 err = snd_card_register(card);
688 if (err < 0)
689 goto out_free;
690
691 pci_set_drvdata(pci, card);
692 dev++;
693 return err;
694out_free:
695 snd_card_free(card);
696 return err;
697}
698
699static void __devexit lola_remove(struct pci_dev *pci)
700{
701 snd_card_free(pci_get_drvdata(pci));
702 pci_set_drvdata(pci, NULL);
703}
704
705/* PCI IDs */
706static DEFINE_PCI_DEVICE_TABLE(lola_ids) = {
707 { PCI_VDEVICE(DIGIGRAM, 0x0001) },
708 { 0, }
709};
710MODULE_DEVICE_TABLE(pci, lola_ids);
711
712/* pci_driver definition */
713static struct pci_driver driver = {
714 .name = DRVNAME,
715 .id_table = lola_ids,
716 .probe = lola_probe,
717 .remove = __devexit_p(lola_remove),
718};
719
720static int __init alsa_card_lola_init(void)
721{
722 return pci_register_driver(&driver);
723}
724
725static void __exit alsa_card_lola_exit(void)
726{
727 pci_unregister_driver(&driver);
728}
729
730module_init(alsa_card_lola_init)
731module_exit(alsa_card_lola_exit)
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
new file mode 100644
index 000000000000..4734c7c6f83e
--- /dev/null
+++ b/sound/pci/lola/lola.h
@@ -0,0 +1,520 @@
1/*
2 * Support for Digigram Lola PCI-e boards
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef _LOLA_H
22#define _LOLA_H
23
24#define DRVNAME "snd-lola"
25#define SFX DRVNAME ": "
26
27/*
28 * Lola HD Audio Registers BAR0
29 */
30#define LOLA_BAR0_GCAP 0x00
31#define LOLA_BAR0_VMIN 0x02
32#define LOLA_BAR0_VMAJ 0x03
33#define LOLA_BAR0_OUTPAY 0x04
34#define LOLA_BAR0_INPAY 0x06
35#define LOLA_BAR0_GCTL 0x08
36#define LOLA_BAR0_WAKEEN 0x0c
37#define LOLA_BAR0_STATESTS 0x0e
38#define LOLA_BAR0_GSTS 0x10
39#define LOLA_BAR0_OUTSTRMPAY 0x18
40#define LOLA_BAR0_INSTRMPAY 0x1a
41#define LOLA_BAR0_INTCTL 0x20
42#define LOLA_BAR0_INTSTS 0x24
43#define LOLA_BAR0_WALCLK 0x30
44#define LOLA_BAR0_SSYNC 0x38
45
46#define LOLA_BAR0_CORBLBASE 0x40
47#define LOLA_BAR0_CORBUBASE 0x44
48#define LOLA_BAR0_CORBWP 0x48 /* no ULONG access */
49#define LOLA_BAR0_CORBRP 0x4a /* no ULONG access */
50#define LOLA_BAR0_CORBCTL 0x4c /* no ULONG access */
51#define LOLA_BAR0_CORBSTS 0x4d /* UCHAR access only */
52#define LOLA_BAR0_CORBSIZE 0x4e /* no ULONG access */
53
54#define LOLA_BAR0_RIRBLBASE 0x50
55#define LOLA_BAR0_RIRBUBASE 0x54
56#define LOLA_BAR0_RIRBWP 0x58
57#define LOLA_BAR0_RINTCNT 0x5a /* no ULONG access */
58#define LOLA_BAR0_RIRBCTL 0x5c
59#define LOLA_BAR0_RIRBSTS 0x5d /* UCHAR access only */
60#define LOLA_BAR0_RIRBSIZE 0x5e /* no ULONG access */
61
62#define LOLA_BAR0_ICW 0x60
63#define LOLA_BAR0_IRR 0x64
64#define LOLA_BAR0_ICS 0x68
65#define LOLA_BAR0_DPLBASE 0x70
66#define LOLA_BAR0_DPUBASE 0x74
67
68/* stream register offsets from stream base 0x80 */
69#define LOLA_BAR0_SD0_OFFSET 0x80
70#define LOLA_REG0_SD_CTL 0x00
71#define LOLA_REG0_SD_STS 0x03
72#define LOLA_REG0_SD_LPIB 0x04
73#define LOLA_REG0_SD_CBL 0x08
74#define LOLA_REG0_SD_LVI 0x0c
75#define LOLA_REG0_SD_FIFOW 0x0e
76#define LOLA_REG0_SD_FIFOSIZE 0x10
77#define LOLA_REG0_SD_FORMAT 0x12
78#define LOLA_REG0_SD_BDLPL 0x18
79#define LOLA_REG0_SD_BDLPU 0x1c
80
81/*
82 * Lola Digigram Registers BAR1
83 */
84#define LOLA_BAR1_FPGAVER 0x00
85#define LOLA_BAR1_DEVER 0x04
86#define LOLA_BAR1_UCBMV 0x08
87#define LOLA_BAR1_JTAG 0x0c
88#define LOLA_BAR1_UARTRX 0x10
89#define LOLA_BAR1_UARTTX 0x14
90#define LOLA_BAR1_UARTCR 0x18
91#define LOLA_BAR1_NVRAMVER 0x1c
92#define LOLA_BAR1_CTRLSPI 0x20
93#define LOLA_BAR1_DSPI 0x24
94#define LOLA_BAR1_AISPI 0x28
95#define LOLA_BAR1_GRAN 0x2c
96
97#define LOLA_BAR1_DINTCTL 0x80
98#define LOLA_BAR1_DIINTCTL 0x84
99#define LOLA_BAR1_DOINTCTL 0x88
100#define LOLA_BAR1_LRC 0x90
101#define LOLA_BAR1_DINTSTS 0x94
102#define LOLA_BAR1_DIINTSTS 0x98
103#define LOLA_BAR1_DOINTSTS 0x9c
104
105#define LOLA_BAR1_DSD0_OFFSET 0xa0
106#define LOLA_BAR1_DSD_SIZE 0x18
107
108#define LOLA_BAR1_DSDnSTS 0x00
109#define LOLA_BAR1_DSDnLPIB 0x04
110#define LOLA_BAR1_DSDnCTL 0x08
111#define LOLA_BAR1_DSDnLVI 0x0c
112#define LOLA_BAR1_DSDnBDPL 0x10
113#define LOLA_BAR1_DSDnBDPU 0x14
114
115#define LOLA_BAR1_SSYNC 0x03e8
116
117#define LOLA_BAR1_BOARD_CTRL 0x0f00
118#define LOLA_BAR1_BOARD_MODE 0x0f02
119
120#define LOLA_BAR1_SOURCE_GAIN_ENABLE 0x1000
121#define LOLA_BAR1_DEST00_MIX_GAIN_ENABLE 0x1004
122#define LOLA_BAR1_DEST31_MIX_GAIN_ENABLE 0x1080
123#define LOLA_BAR1_SOURCE00_01_GAIN 0x1084
124#define LOLA_BAR1_SOURCE30_31_GAIN 0x10c0
125#define LOLA_BAR1_SOURCE_GAIN(src) \
126 (LOLA_BAR1_SOURCE00_01_GAIN + (src) * 2)
127#define LOLA_BAR1_DEST00_MIX00_01_GAIN 0x10c4
128#define LOLA_BAR1_DEST00_MIX30_31_GAIN 0x1100
129#define LOLA_BAR1_DEST01_MIX00_01_GAIN 0x1104
130#define LOLA_BAR1_DEST01_MIX30_31_GAIN 0x1140
131#define LOLA_BAR1_DEST31_MIX00_01_GAIN 0x1884
132#define LOLA_BAR1_DEST31_MIX30_31_GAIN 0x18c0
133#define LOLA_BAR1_MIX_GAIN(dest, mix) \
134 (LOLA_BAR1_DEST00_MIX00_01_GAIN + (dest) * 0x40 + (mix) * 2)
135#define LOLA_BAR1_ANALOG_CLIP_IN 0x18c4
136#define LOLA_BAR1_PEAKMETERS_SOURCE00_01 0x18c8
137#define LOLA_BAR1_PEAKMETERS_SOURCE30_31 0x1904
138#define LOLA_BAR1_PEAKMETERS_SOURCE(src) \
139 (LOLA_BAR1_PEAKMETERS_SOURCE00_01 + (src) * 2)
140#define LOLA_BAR1_PEAKMETERS_DEST00_01 0x1908
141#define LOLA_BAR1_PEAKMETERS_DEST30_31 0x1944
142#define LOLA_BAR1_PEAKMETERS_DEST(dest) \
143 (LOLA_BAR1_PEAKMETERS_DEST00_01 + (dest) * 2)
144#define LOLA_BAR1_PEAKMETERS_AGC00_01 0x1948
145#define LOLA_BAR1_PEAKMETERS_AGC14_15 0x1964
146#define LOLA_BAR1_PEAKMETERS_AGC(x) \
147 (LOLA_BAR1_PEAKMETERS_AGC00_01 + (x) * 2)
148
149/* GCTL reset bit */
150#define LOLA_GCTL_RESET (1 << 0)
151/* GCTL unsolicited response enable bit */
152#define LOLA_GCTL_UREN (1 << 8)
153
154/* CORB/RIRB control, read/write pointer */
155#define LOLA_RBCTL_DMA_EN 0x02 /* enable DMA */
156#define LOLA_RBCTL_IRQ_EN 0x01 /* enable IRQ */
157#define LOLA_RBRWP_CLR 0x8000 /* read/write pointer clear */
158
159#define LOLA_RIRB_EX_UNSOL_EV 0x40000000
160#define LOLA_RIRB_EX_ERROR 0x80000000
161
162/* CORB int mask: CMEI[0] */
163#define LOLA_CORB_INT_CMEI 0x01
164#define LOLA_CORB_INT_MASK LOLA_CORB_INT_CMEI
165
166/* RIRB int mask: overrun[2], response[0] */
167#define LOLA_RIRB_INT_RESPONSE 0x01
168#define LOLA_RIRB_INT_OVERRUN 0x04
169#define LOLA_RIRB_INT_MASK (LOLA_RIRB_INT_RESPONSE | LOLA_RIRB_INT_OVERRUN)
170
171/* DINTCTL and DINTSTS */
172#define LOLA_DINT_GLOBAL 0x80000000 /* global interrupt enable bit */
173#define LOLA_DINT_CTRL 0x40000000 /* controller interrupt enable bit */
174#define LOLA_DINT_FIFOERR 0x20000000 /* global fifo error enable bit */
175#define LOLA_DINT_MUERR 0x10000000 /* global microcontroller underrun error */
176
177/* DSDnCTL bits */
178#define LOLA_DSD_CTL_SRST 0x01 /* stream reset bit */
179#define LOLA_DSD_CTL_SRUN 0x02 /* stream DMA start bit */
180#define LOLA_DSD_CTL_IOCE 0x04 /* interrupt on completion enable */
181#define LOLA_DSD_CTL_DEIE 0x10 /* descriptor error interrupt enable */
182#define LOLA_DSD_CTL_VLRCV 0x20 /* valid LRCountValue information in bits 8..31 */
183#define LOLA_LRC_MASK 0xffffff00
184
185/* DSDnSTS */
186#define LOLA_DSD_STS_BCIS 0x04 /* buffer completion interrupt status */
187#define LOLA_DSD_STS_DESE 0x10 /* descriptor error interrupt */
188#define LOLA_DSD_STS_FIFORDY 0x20 /* fifo ready */
189
190#define LOLA_CORB_ENTRIES 256
191
192#define MAX_STREAM_IN_COUNT 16
193#define MAX_STREAM_OUT_COUNT 16
194#define MAX_STREAM_COUNT 16
195#define MAX_PINS MAX_STREAM_COUNT
196#define MAX_STREAM_BUFFER_COUNT 16
197#define MAX_AUDIO_INOUT_COUNT 16
198
199#define LOLA_CLOCK_TYPE_INTERNAL 0
200#define LOLA_CLOCK_TYPE_AES 1
201#define LOLA_CLOCK_TYPE_AES_SYNC 2
202#define LOLA_CLOCK_TYPE_WORDCLOCK 3
203#define LOLA_CLOCK_TYPE_ETHERSOUND 4
204#define LOLA_CLOCK_TYPE_VIDEO 5
205
206#define LOLA_CLOCK_FORMAT_NONE 0
207#define LOLA_CLOCK_FORMAT_NTSC 1
208#define LOLA_CLOCK_FORMAT_PAL 2
209
210#define MAX_SAMPLE_CLOCK_COUNT 48
211
212/* parameters used with mixer widget's mixer capabilities */
213#define LOLA_PEAK_METER_CAN_AGC_MASK 1
214#define LOLA_PEAK_METER_CAN_ANALOG_CLIP_MASK 2
215
216struct lola_bar {
217 unsigned long addr;
218 void __iomem *remap_addr;
219};
220
221/* CORB/RIRB */
222struct lola_rb {
223 u32 *buf; /* CORB/RIRB buffer, 8 byte per each entry */
224 dma_addr_t addr; /* physical address of CORB/RIRB buffer */
225 unsigned short rp, wp; /* read/write pointers */
226 int cmds; /* number of pending requests */
227};
228
229/* Pin widget setup */
230struct lola_pin {
231 unsigned int nid;
232 bool is_analog;
233 unsigned int amp_mute;
234 unsigned int amp_step_size;
235 unsigned int amp_num_steps;
236 unsigned int amp_offset;
237 unsigned int max_level;
238 unsigned int config_default_reg;
239 unsigned int fixed_gain_list_len;
240 unsigned int cur_gain_step;
241};
242
243struct lola_pin_array {
244 unsigned int num_pins;
245 struct lola_pin pins[MAX_PINS];
246};
247
248/* Clock widget setup */
249struct lola_sample_clock {
250 unsigned int type;
251 unsigned int format;
252 unsigned int freq;
253};
254
255struct lola_clock_widget {
256 unsigned int nid;
257 unsigned int items;
258 unsigned int cur_index;
259 unsigned int cur_freq;
260 bool cur_valid;
261 struct lola_sample_clock sample_clock[MAX_SAMPLE_CLOCK_COUNT];
262 unsigned int idx_lookup[MAX_SAMPLE_CLOCK_COUNT];
263};
264
265#define LOLA_MIXER_DIM 32
266struct lola_mixer_array {
267 u32 src_gain_enable;
268 u32 dest_mix_gain_enable[LOLA_MIXER_DIM];
269 u16 src_gain[LOLA_MIXER_DIM];
270 u16 dest_mix_gain[LOLA_MIXER_DIM][LOLA_MIXER_DIM];
271};
272
273/* Mixer widget setup */
274struct lola_mixer_widget {
275 unsigned int nid;
276 unsigned int caps;
277 struct lola_mixer_array __user *array;
278 struct lola_mixer_array *array_saved;
279 unsigned int src_stream_outs;
280 unsigned int src_phys_ins;
281 unsigned int dest_stream_ins;
282 unsigned int dest_phys_outs;
283 unsigned int src_stream_out_ofs;
284 unsigned int dest_phys_out_ofs;
285 unsigned int src_mask;
286 unsigned int dest_mask;
287};
288
289/* Audio stream */
290struct lola_stream {
291 unsigned int nid; /* audio widget NID */
292 unsigned int index; /* array index */
293 unsigned int dsd; /* DSD index */
294 bool can_float;
295 struct snd_pcm_substream *substream; /* assigned PCM substream */
296 struct lola_stream *master; /* master stream (for multi-channel) */
297
298 /* buffer setup */
299 unsigned int bufsize;
300 unsigned int period_bytes;
301 unsigned int frags;
302 struct snd_dma_buffer bdl; /* BDL buffer */
303
304 /* format + channel setup */
305 unsigned int format_verb;
306
307 /* flags */
308 unsigned int opened:1;
309 unsigned int running:1;
310};
311
312#define PLAY SNDRV_PCM_STREAM_PLAYBACK
313#define CAPT SNDRV_PCM_STREAM_CAPTURE
314
315struct lola_pcm {
316 unsigned int num_streams;
317 struct lola_stream streams[MAX_STREAM_COUNT];
318};
319
320/* card instance */
321struct lola {
322 struct snd_card *card;
323 struct pci_dev *pci;
324
325 /* pci resources */
326 struct lola_bar bar[2];
327 int irq;
328
329 /* locks */
330 spinlock_t reg_lock;
331 struct mutex open_mutex;
332
333 /* CORB/RIRB */
334 struct lola_rb corb;
335 struct lola_rb rirb;
336 unsigned int res, res_ex; /* last read values */
337 /* last command (for debugging) */
338 unsigned int last_cmd_nid, last_verb, last_data, last_extdata;
339
340 /* CORB/RIRB buffers */
341 struct snd_dma_buffer rb;
342
343 /* unsolicited events */
344 unsigned int last_unsol_res;
345
346 /* streams */
347 struct lola_pcm pcm[2];
348
349 /* input src */
350 unsigned int input_src_caps_mask;
351 unsigned int input_src_mask;
352
353 /* pins */
354 struct lola_pin_array pin[2];
355
356 /* clock */
357 struct lola_clock_widget clock;
358
359 /* mixer */
360 struct lola_mixer_widget mixer;
361
362 /* hw info */
363 unsigned int version;
364 unsigned int lola_caps;
365
366 /* parameters */
367 unsigned int granularity;
368 unsigned int sample_rate_min;
369
370 /* flags */
371 unsigned int running :1;
372 unsigned int initialized :1;
373 unsigned int cold_reset :1;
374
375 /* for debugging */
376 unsigned int debug_res;
377 unsigned int debug_res_ex;
378};
379
380#define BAR0 0
381#define BAR1 1
382
383/* Helper macros */
384#define lola_readl(chip, idx, name) \
385 readl((chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
386#define lola_readw(chip, idx, name) \
387 readw((chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
388#define lola_readb(chip, idx, name) \
389 readb((chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
390#define lola_writel(chip, idx, name, val) \
391 writel((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
392#define lola_writew(chip, idx, name, val) \
393 writew((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
394#define lola_writeb(chip, idx, name, val) \
395 writeb((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
396
397#define lola_dsd_read(chip, dsd, name) \
398 readl((chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \
399 (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name)
400#define lola_dsd_write(chip, dsd, name, val) \
401 writel((val), (chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \
402 (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name)
403
404/* GET verbs HDAudio */
405#define LOLA_VERB_GET_STREAM_FORMAT 0xa00
406#define LOLA_VERB_GET_AMP_GAIN_MUTE 0xb00
407#define LOLA_VERB_PARAMETERS 0xf00
408#define LOLA_VERB_GET_POWER_STATE 0xf05
409#define LOLA_VERB_GET_CONV 0xf06
410#define LOLA_VERB_GET_UNSOLICITED_RESPONSE 0xf08
411#define LOLA_VERB_GET_DIGI_CONVERT_1 0xf0d
412#define LOLA_VERB_GET_CONFIG_DEFAULT 0xf1c
413#define LOLA_VERB_GET_SUBSYSTEM_ID 0xf20
414/* GET verbs Digigram */
415#define LOLA_VERB_GET_FIXED_GAIN 0xfc0
416#define LOLA_VERB_GET_GAIN_SELECT 0xfc1
417#define LOLA_VERB_GET_MAX_LEVEL 0xfc2
418#define LOLA_VERB_GET_CLOCK_LIST 0xfc3
419#define LOLA_VERB_GET_CLOCK_SELECT 0xfc4
420#define LOLA_VERB_GET_CLOCK_STATUS 0xfc5
421
422/* SET verbs HDAudio */
423#define LOLA_VERB_SET_STREAM_FORMAT 0x200
424#define LOLA_VERB_SET_AMP_GAIN_MUTE 0x300
425#define LOLA_VERB_SET_POWER_STATE 0x705
426#define LOLA_VERB_SET_CHANNEL_STREAMID 0x706
427#define LOLA_VERB_SET_UNSOLICITED_ENABLE 0x708
428#define LOLA_VERB_SET_DIGI_CONVERT_1 0x70d
429/* SET verbs Digigram */
430#define LOLA_VERB_SET_GAIN_SELECT 0xf81
431#define LOLA_VERB_SET_CLOCK_SELECT 0xf84
432#define LOLA_VERB_SET_GRANULARITY_STEPS 0xf86
433#define LOLA_VERB_SET_SOURCE_GAIN 0xf87
434#define LOLA_VERB_SET_MIX_GAIN 0xf88
435#define LOLA_VERB_SET_DESTINATION_GAIN 0xf89
436#define LOLA_VERB_SET_SRC 0xf8a
437
438/* Parameter IDs used with LOLA_VERB_PARAMETERS */
439#define LOLA_PAR_VENDOR_ID 0x00
440#define LOLA_PAR_FUNCTION_TYPE 0x05
441#define LOLA_PAR_AUDIO_WIDGET_CAP 0x09
442#define LOLA_PAR_PCM 0x0a
443#define LOLA_PAR_STREAM_FORMATS 0x0b
444#define LOLA_PAR_PIN_CAP 0x0c
445#define LOLA_PAR_AMP_IN_CAP 0x0d
446#define LOLA_PAR_CONNLIST_LEN 0x0e
447#define LOLA_PAR_POWER_STATE 0x0f
448#define LOLA_PAR_GPIO_CAP 0x11
449#define LOLA_PAR_AMP_OUT_CAP 0x12
450#define LOLA_PAR_SPECIFIC_CAPS 0x80
451#define LOLA_PAR_FIXED_GAIN_LIST 0x81
452
453/* extract results of LOLA_PAR_SPECIFIC_CAPS */
454#define LOLA_AFG_MIXER_WIDGET_PRESENT(res) ((res & (1 << 21)) != 0)
455#define LOLA_AFG_CLOCK_WIDGET_PRESENT(res) ((res & (1 << 20)) != 0)
456#define LOLA_AFG_INPUT_PIN_COUNT(res) ((res >> 10) & 0x2ff)
457#define LOLA_AFG_OUTPUT_PIN_COUNT(res) ((res) & 0x2ff)
458
459/* extract results of LOLA_PAR_AMP_IN_CAP / LOLA_PAR_AMP_OUT_CAP */
460#define LOLA_AMP_MUTE_CAPABLE(res) ((res & (1 << 31)) != 0)
461#define LOLA_AMP_STEP_SIZE(res) ((res >> 24) & 0x7f)
462#define LOLA_AMP_NUM_STEPS(res) ((res >> 12) & 0x3ff)
463#define LOLA_AMP_OFFSET(res) ((res) & 0x3ff)
464
465#define LOLA_GRANULARITY_MIN 8
466#define LOLA_GRANULARITY_MAX 32
467#define LOLA_GRANULARITY_STEP 8
468
469/* parameters used with unsolicited command/response */
470#define LOLA_UNSOLICITED_TAG_MASK 0x3f
471#define LOLA_UNSOLICITED_TAG 0x1a
472#define LOLA_UNSOLICITED_ENABLE 0x80
473#define LOLA_UNSOL_RESP_TAG_OFFSET 26
474
475/* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */
476#define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res) ((res >> 2) & 0x1f)
477#define LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(res) ((res >> 7) & 0x1f)
478
479int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb,
480 unsigned int data, unsigned int extdata);
481int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb,
482 unsigned int data, unsigned int extdata,
483 unsigned int *val, unsigned int *extval);
484int lola_codec_flush(struct lola *chip);
485#define lola_read_param(chip, nid, param, val) \
486 lola_codec_read(chip, nid, LOLA_VERB_PARAMETERS, param, 0, val, NULL)
487
488/* PCM */
489int lola_create_pcm(struct lola *chip);
490void lola_free_pcm(struct lola *chip);
491int lola_init_pcm(struct lola *chip, int dir, int *nidp);
492void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits);
493
494/* clock */
495int lola_init_clock_widget(struct lola *chip, int nid);
496int lola_set_granularity(struct lola *chip, unsigned int val, bool force);
497int lola_enable_clock_events(struct lola *chip);
498int lola_set_clock_index(struct lola *chip, unsigned int idx);
499int lola_set_clock(struct lola *chip, int idx);
500int lola_set_sample_rate(struct lola *chip, int rate);
501bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val);
502
503/* mixer */
504int lola_init_pins(struct lola *chip, int dir, int *nidp);
505int lola_init_mixer_widget(struct lola *chip, int nid);
506void lola_free_mixer(struct lola *chip);
507int lola_create_mixer(struct lola *chip);
508int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute);
509void lola_save_mixer(struct lola *chip);
510void lola_restore_mixer(struct lola *chip);
511int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update);
512
513/* proc */
514#ifdef CONFIG_SND_DEBUG
515void lola_proc_debug_new(struct lola *chip);
516#else
517#define lola_proc_debug_new(chip)
518#endif
519
520#endif /* _LOLA_H */
diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c
new file mode 100644
index 000000000000..a364dc67e55f
--- /dev/null
+++ b/sound/pci/lola/lola_clock.c
@@ -0,0 +1,322 @@
1/*
2 * Support for Digigram Lola PCI-e boards
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include "lola.h"
26
27static unsigned int sample_rate_convert(unsigned int coded)
28{
29 unsigned int freq;
30
31 /* base frequency */
32 switch (coded & 0x3) {
33 case 0: freq = 48000; break;
34 case 1: freq = 44100; break;
35 case 2: freq = 32000; break;
36 default: return 0; /* error */
37 }
38
39 /* multiplier / devisor */
40 switch (coded & 0x1c) {
41 case (0 << 2): break;
42 case (4 << 2): break;
43 case (1 << 2): freq *= 2; break;
44 case (2 << 2): freq *= 4; break;
45 case (5 << 2): freq /= 2; break;
46 case (6 << 2): freq /= 4; break;
47 default: return 0; /* error */
48 }
49
50 /* ajustement */
51 switch (coded & 0x60) {
52 case (0 << 5): break;
53 case (1 << 5): freq = (freq * 999) / 1000; break;
54 case (2 << 5): freq = (freq * 1001) / 1000; break;
55 default: return 0; /* error */
56 }
57 return freq;
58}
59
60/*
61 * Granualrity
62 */
63
64#define LOLA_MAXFREQ_AT_GRANULARITY_MIN 48000
65#define LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX 96000
66
67static bool check_gran_clock_compatibility(struct lola *chip,
68 unsigned int val,
69 unsigned int freq)
70{
71 if (!chip->granularity)
72 return true;
73
74 if (val < LOLA_GRANULARITY_MIN || val > LOLA_GRANULARITY_MAX ||
75 (val % LOLA_GRANULARITY_STEP) != 0)
76 return false;
77
78 if (val == LOLA_GRANULARITY_MIN) {
79 if (freq > LOLA_MAXFREQ_AT_GRANULARITY_MIN)
80 return false;
81 } else if (val < LOLA_GRANULARITY_MAX) {
82 if (freq > LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX)
83 return false;
84 }
85 return true;
86}
87
88int lola_set_granularity(struct lola *chip, unsigned int val, bool force)
89{
90 int err;
91
92 if (!force) {
93 if (val == chip->granularity)
94 return 0;
95#if 0
96 /* change Gran only if there are no streams allocated ! */
97 if (chip->audio_in_alloc_mask || chip->audio_out_alloc_mask)
98 return -EBUSY;
99#endif
100 if (!check_gran_clock_compatibility(chip, val,
101 chip->clock.cur_freq))
102 return -EINVAL;
103 }
104
105 chip->granularity = val;
106 val /= LOLA_GRANULARITY_STEP;
107
108 /* audio function group */
109 err = lola_codec_write(chip, 1, LOLA_VERB_SET_GRANULARITY_STEPS,
110 val, 0);
111 if (err < 0)
112 return err;
113 /* this can be a very slow function !!! */
114 usleep_range(400 * val, 20000);
115 return lola_codec_flush(chip);
116}
117
118/*
119 * Clock widget handling
120 */
121
122int __devinit lola_init_clock_widget(struct lola *chip, int nid)
123{
124 unsigned int val;
125 int i, j, nitems, nb_verbs, idx, idx_list;
126 int err;
127
128 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
129 if (err < 0) {
130 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
131 return err;
132 }
133
134 if ((val & 0xfff00000) != 0x01f00000) { /* test SubType and Type */
135 snd_printdd("No valid clock widget\n");
136 return 0;
137 }
138
139 chip->clock.nid = nid;
140 chip->clock.items = val & 0xff;
141 snd_printdd("clock_list nid=%x, entries=%d\n", nid,
142 chip->clock.items);
143 if (chip->clock.items > MAX_SAMPLE_CLOCK_COUNT) {
144 printk(KERN_ERR SFX "CLOCK_LIST too big: %d\n",
145 chip->clock.items);
146 return -EINVAL;
147 }
148
149 nitems = chip->clock.items;
150 nb_verbs = (nitems + 3) / 4;
151 idx = 0;
152 idx_list = 0;
153 for (i = 0; i < nb_verbs; i++) {
154 unsigned int res_ex;
155 unsigned short items[4];
156
157 err = lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST,
158 idx, 0, &val, &res_ex);
159 if (err < 0) {
160 printk(KERN_ERR SFX "Can't read CLOCK_LIST\n");
161 return -EINVAL;
162 }
163
164 items[0] = val & 0xfff;
165 items[1] = (val >> 16) & 0xfff;
166 items[2] = res_ex & 0xfff;
167 items[3] = (res_ex >> 16) & 0xfff;
168
169 for (j = 0; j < 4; j++) {
170 unsigned char type = items[j] >> 8;
171 unsigned int freq = items[j] & 0xff;
172 int format = LOLA_CLOCK_FORMAT_NONE;
173 bool add_clock = true;
174 if (type == LOLA_CLOCK_TYPE_INTERNAL) {
175 freq = sample_rate_convert(freq);
176 if (freq < chip->sample_rate_min)
177 add_clock = false;
178 else if (freq == 48000) {
179 chip->clock.cur_index = idx_list;
180 chip->clock.cur_freq = 48000;
181 chip->clock.cur_valid = true;
182 }
183 } else if (type == LOLA_CLOCK_TYPE_VIDEO) {
184 freq = sample_rate_convert(freq);
185 if (freq < chip->sample_rate_min)
186 add_clock = false;
187 /* video clock has a format (0:NTSC, 1:PAL)*/
188 if (items[j] & 0x80)
189 format = LOLA_CLOCK_FORMAT_NTSC;
190 else
191 format = LOLA_CLOCK_FORMAT_PAL;
192 }
193 if (add_clock) {
194 struct lola_sample_clock *sc;
195 sc = &chip->clock.sample_clock[idx_list];
196 sc->type = type;
197 sc->format = format;
198 sc->freq = freq;
199 /* keep the index used with the board */
200 chip->clock.idx_lookup[idx_list] = idx;
201 idx_list++;
202 } else {
203 chip->clock.items--;
204 }
205 if (++idx >= nitems)
206 break;
207 }
208 }
209 return 0;
210}
211
212/* enable unsolicited events of the clock widget */
213int lola_enable_clock_events(struct lola *chip)
214{
215 unsigned int res;
216 int err;
217
218 err = lola_codec_read(chip, chip->clock.nid,
219 LOLA_VERB_SET_UNSOLICITED_ENABLE,
220 LOLA_UNSOLICITED_ENABLE | LOLA_UNSOLICITED_TAG,
221 0, &res, NULL);
222 if (err < 0)
223 return err;
224 if (res) {
225 printk(KERN_WARNING SFX "error in enable_clock_events %d\n",
226 res);
227 return -EINVAL;
228 }
229 return 0;
230}
231
232int lola_set_clock_index(struct lola *chip, unsigned int idx)
233{
234 unsigned int res;
235 int err;
236
237 err = lola_codec_read(chip, chip->clock.nid,
238 LOLA_VERB_SET_CLOCK_SELECT,
239 chip->clock.idx_lookup[idx],
240 0, &res, NULL);
241 if (err < 0)
242 return err;
243 if (res) {
244 printk(KERN_WARNING SFX "error in set_clock %d\n", res);
245 return -EINVAL;
246 }
247 return 0;
248}
249
250bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val)
251{
252 unsigned int tag;
253
254 /* the current EXTERNAL clock information gets updated by interrupt
255 * with an unsolicited response
256 */
257 if (!val)
258 return false;
259 tag = (val >> LOLA_UNSOL_RESP_TAG_OFFSET) & LOLA_UNSOLICITED_TAG_MASK;
260 if (tag != LOLA_UNSOLICITED_TAG)
261 return false;
262
263 /* only for current = external clocks */
264 if (chip->clock.sample_clock[chip->clock.cur_index].type !=
265 LOLA_CLOCK_TYPE_INTERNAL) {
266 chip->clock.cur_freq = sample_rate_convert(val & 0x7f);
267 chip->clock.cur_valid = (val & 0x100) != 0;
268 }
269 return true;
270}
271
272int lola_set_clock(struct lola *chip, int idx)
273{
274 int freq = 0;
275 bool valid = false;
276
277 if (idx == chip->clock.cur_index) {
278 /* current clock is allowed */
279 freq = chip->clock.cur_freq;
280 valid = chip->clock.cur_valid;
281 } else if (chip->clock.sample_clock[idx].type ==
282 LOLA_CLOCK_TYPE_INTERNAL) {
283 /* internal clocks allowed */
284 freq = chip->clock.sample_clock[idx].freq;
285 valid = true;
286 }
287
288 if (!freq || !valid)
289 return -EINVAL;
290
291 if (!check_gran_clock_compatibility(chip, chip->granularity, freq))
292 return -EINVAL;
293
294 if (idx != chip->clock.cur_index) {
295 int err = lola_set_clock_index(chip, idx);
296 if (err < 0)
297 return err;
298 /* update new settings */
299 chip->clock.cur_index = idx;
300 chip->clock.cur_freq = freq;
301 chip->clock.cur_valid = true;
302 }
303 return 0;
304}
305
306int lola_set_sample_rate(struct lola *chip, int rate)
307{
308 int i;
309
310 if (chip->clock.cur_freq == rate && chip->clock.cur_valid)
311 return 0;
312 /* search for new dwClockIndex */
313 for (i = 0; i < chip->clock.items; i++) {
314 if (chip->clock.sample_clock[i].type == LOLA_CLOCK_TYPE_INTERNAL &&
315 chip->clock.sample_clock[i].freq == rate)
316 break;
317 }
318 if (i >= chip->clock.items)
319 return -EINVAL;
320 return lola_set_clock(chip, i);
321}
322
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c
new file mode 100644
index 000000000000..0d09689d7b8d
--- /dev/null
+++ b/sound/pci/lola/lola_mixer.c
@@ -0,0 +1,826 @@
1/*
2 * Support for Digigram Lola PCI-e boards
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/vmalloc.h>
24#include <linux/io.h>
25#include <sound/core.h>
26#include <sound/control.h>
27#include <sound/pcm.h>
28#include <sound/tlv.h>
29#include "lola.h"
30
31static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
32 int dir, int nid)
33{
34 unsigned int val;
35 int err;
36
37 pin->nid = nid;
38 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
39 if (err < 0) {
40 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
41 return err;
42 }
43 val &= 0x00f00fff; /* test TYPE and bits 0..11 */
44 if (val == 0x00400200) /* Type = 4, Digital = 1 */
45 pin->is_analog = false;
46 else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */
47 pin->is_analog = true;
48 else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */
49 pin->is_analog = true;
50 else {
51 printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid);
52 return -EINVAL;
53 }
54
55 /* analog parameters only following, so continue in case of Digital pin
56 */
57 if (!pin->is_analog)
58 return 0;
59
60 if (dir == PLAY)
61 err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val);
62 else
63 err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val);
64 if (err < 0) {
65 printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid);
66 return err;
67 }
68
69 pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val);
70 pin->amp_step_size = LOLA_AMP_STEP_SIZE(val);
71 pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val);
72 if (pin->amp_num_steps) {
73 /* zero as mute state */
74 pin->amp_num_steps++;
75 pin->amp_step_size++;
76 }
77 pin->amp_offset = LOLA_AMP_OFFSET(val);
78
79 err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val,
80 NULL);
81 if (err < 0) {
82 printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid);
83 return err;
84 }
85 pin->max_level = val & 0x3ff; /* 10 bits */
86
87 pin->config_default_reg = 0;
88 pin->fixed_gain_list_len = 0;
89 pin->cur_gain_step = 0;
90
91 return 0;
92}
93
94int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp)
95{
96 int i, err, nid;
97 nid = *nidp;
98 for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) {
99 err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid);
100 if (err < 0)
101 return err;
102 }
103 *nidp = nid;
104 return 0;
105}
106
107void lola_free_mixer(struct lola *chip)
108{
109 if (chip->mixer.array_saved)
110 vfree(chip->mixer.array_saved);
111}
112
113int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
114{
115 unsigned int val;
116 int err;
117
118 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
119 if (err < 0) {
120 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
121 return err;
122 }
123
124 if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */
125 snd_printdd("No valid mixer widget\n");
126 return 0;
127 }
128
129 chip->mixer.nid = nid;
130 chip->mixer.caps = val;
131 chip->mixer.array = (struct lola_mixer_array __iomem *)
132 (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);
133
134 /* reserve memory to copy mixer data for sleep mode transitions */
135 chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));
136
137 /* mixer matrix sources are physical input data and play streams */
138 chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
139 chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;
140
141 /* mixer matrix destinations are record streams and physical output */
142 chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
143 chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
144
145 /* mixer matrix can have unused areas between PhysIn and
146 * Play or Record and PhysOut zones
147 */
148 chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
149 LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
150 chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
151 LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val);
152
153 /* example : MixerMatrix of LoLa881
154 * 0-------8------16-------8------16
155 * | | | | |
156 * | INPUT | | INPUT | |
157 * | -> |unused | -> |unused |
158 * | RECORD| | OUTPUT| |
159 * | | | | |
160 * 8--------------------------------
161 * | | | | |
162 * | | | | |
163 * |unused |unused |unused |unused |
164 * | | | | |
165 * | | | | |
166 * 16-------------------------------
167 * | | | | |
168 * | PLAY | | PLAY | |
169 * | -> |unused | -> |unused |
170 * | RECORD| | OUTPUT| |
171 * | | | | |
172 * 8--------------------------------
173 * | | | | |
174 * | | | | |
175 * |unused |unused |unused |unused |
176 * | | | | |
177 * | | | | |
178 * 16-------------------------------
179 */
180 if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
181 chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
182 printk(KERN_ERR SFX "Invalid mixer widget size\n");
183 return -EINVAL;
184 }
185
186 chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) |
187 (((1U << chip->mixer.src_stream_outs) - 1)
188 << chip->mixer.src_stream_out_ofs);
189 chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) |
190 (((1U << chip->mixer.dest_phys_outs) - 1)
191 << chip->mixer.dest_phys_out_ofs);
192
193 return 0;
194}
195
196static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
197 unsigned short gain, bool on)
198{
199 unsigned int oldval, val;
200
201 if (!(chip->mixer.src_mask & (1 << id)))
202 return -EINVAL;
203 writew(gain, &chip->mixer.array->src_gain[id]);
204 oldval = val = readl(&chip->mixer.array->src_gain_enable);
205 if (on)
206 val |= (1 << id);
207 else
208 val &= ~(1 << id);
209 writel(val, &chip->mixer.array->src_gain_enable);
210 lola_codec_flush(chip);
211 /* inform micro-controller about the new source gain */
212 return lola_codec_write(chip, chip->mixer.nid,
213 LOLA_VERB_SET_SOURCE_GAIN, id, 0);
214}
215
216#if 0 /* not used */
217static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask,
218 unsigned short *gains)
219{
220 int i;
221
222 if ((chip->mixer.src_mask & mask) != mask)
223 return -EINVAL;
224 for (i = 0; i < LOLA_MIXER_DIM; i++) {
225 if (mask & (1 << i)) {
226 writew(*gains, &chip->mixer.array->src_gain[i]);
227 gains++;
228 }
229 }
230 writel(mask, &chip->mixer.array->src_gain_enable);
231 lola_codec_flush(chip);
232 if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) {
233 /* update for all srcs at once */
234 return lola_codec_write(chip, chip->mixer.nid,
235 LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
236 }
237 /* update manually */
238 for (i = 0; i < LOLA_MIXER_DIM; i++) {
239 if (mask & (1 << i)) {
240 lola_codec_write(chip, chip->mixer.nid,
241 LOLA_VERB_SET_SOURCE_GAIN, i, 0);
242 }
243 }
244 return 0;
245}
246#endif /* not used */
247
248static int lola_mixer_set_mapping_gain(struct lola *chip,
249 unsigned int src, unsigned int dest,
250 unsigned short gain, bool on)
251{
252 unsigned int val;
253
254 if (!(chip->mixer.src_mask & (1 << src)) ||
255 !(chip->mixer.dest_mask & (1 << dest)))
256 return -EINVAL;
257 if (on)
258 writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]);
259 val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]);
260 if (on)
261 val |= (1 << src);
262 else
263 val &= ~(1 << src);
264 writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]);
265 lola_codec_flush(chip);
266 return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN,
267 src, dest);
268}
269
270static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
271 unsigned int mask, unsigned short *gains)
272{
273 int i;
274
275 if (!(chip->mixer.dest_mask & (1 << id)) ||
276 (chip->mixer.src_mask & mask) != mask)
277 return -EINVAL;
278 for (i = 0; i < LOLA_MIXER_DIM; i++) {
279 if (mask & (1 << i)) {
280 writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]);
281 gains++;
282 }
283 }
284 writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]);
285 lola_codec_flush(chip);
286 /* update for all dests at once */
287 return lola_codec_write(chip, chip->mixer.nid,
288 LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
289}
290
291/*
292 */
293
294static int set_analog_volume(struct lola *chip, int dir,
295 unsigned int idx, unsigned int val,
296 bool external_call);
297
298int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
299{
300 struct lola_pin *pin;
301 int idx, max_idx;
302
303 pin = chip->pin[dir].pins;
304 max_idx = chip->pin[dir].num_pins;
305 for (idx = 0; idx < max_idx; idx++) {
306 if (pin[idx].is_analog) {
307 unsigned int val = mute ? 0 : pin[idx].cur_gain_step;
308 /* set volume and do not save the value */
309 set_analog_volume(chip, dir, idx, val, false);
310 }
311 }
312 return lola_codec_flush(chip);
313}
314
315void lola_save_mixer(struct lola *chip)
316{
317 /* mute analog output */
318 if (chip->mixer.array_saved) {
319 /* store contents of mixer array */
320 memcpy_fromio(chip->mixer.array_saved, chip->mixer.array,
321 sizeof(*chip->mixer.array));
322 }
323 lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */
324}
325
326void lola_restore_mixer(struct lola *chip)
327{
328 int i;
329
330 /*lola_reset_setups(chip);*/
331 if (chip->mixer.array_saved) {
332 /* restore contents of mixer array */
333 memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
334 sizeof(*chip->mixer.array));
335 /* inform micro-controller about all restored values
336 * and ignore return values
337 */
338 for (i = 0; i < chip->mixer.src_phys_ins; i++)
339 lola_codec_write(chip, chip->mixer.nid,
340 LOLA_VERB_SET_SOURCE_GAIN,
341 i, 0);
342 for (i = 0; i < chip->mixer.src_stream_outs; i++)
343 lola_codec_write(chip, chip->mixer.nid,
344 LOLA_VERB_SET_SOURCE_GAIN,
345 chip->mixer.src_stream_out_ofs + i, 0);
346 for (i = 0; i < chip->mixer.dest_stream_ins; i++)
347 lola_codec_write(chip, chip->mixer.nid,
348 LOLA_VERB_SET_DESTINATION_GAIN,
349 i, 0);
350 for (i = 0; i < chip->mixer.dest_phys_outs; i++)
351 lola_codec_write(chip, chip->mixer.nid,
352 LOLA_VERB_SET_DESTINATION_GAIN,
353 chip->mixer.dest_phys_out_ofs + i, 0);
354 lola_codec_flush(chip);
355 }
356}
357
358/*
359 */
360
361static int set_analog_volume(struct lola *chip, int dir,
362 unsigned int idx, unsigned int val,
363 bool external_call)
364{
365 struct lola_pin *pin;
366 int err;
367
368 if (idx >= chip->pin[dir].num_pins)
369 return -EINVAL;
370 pin = &chip->pin[dir].pins[idx];
371 if (!pin->is_analog || pin->amp_num_steps <= val)
372 return -EINVAL;
373 if (external_call && pin->cur_gain_step == val)
374 return 0;
375 if (external_call)
376 lola_codec_flush(chip);
377 err = lola_codec_write(chip, pin->nid,
378 LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0);
379 if (err < 0)
380 return err;
381 if (external_call)
382 pin->cur_gain_step = val;
383 return 0;
384}
385
386int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update)
387{
388 int ret = 0;
389 int success = 0;
390 int n, err;
391
392 /* SRC can be activated and the dwInputSRCMask is valid? */
393 if ((chip->input_src_caps_mask & src_mask) != src_mask)
394 return -EINVAL;
395 /* handle all even Inputs - SRC is a stereo setting !!! */
396 for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) {
397 unsigned int mask = 3U << n; /* handle the stereo case */
398 unsigned int new_src, src_state;
399 if (!(chip->input_src_caps_mask & mask))
400 continue;
401 /* if one IO needs SRC, both stereo IO will get SRC */
402 new_src = (src_mask & mask) != 0;
403 if (update) {
404 src_state = (chip->input_src_mask & mask) != 0;
405 if (src_state == new_src)
406 continue; /* nothing to change for this IO */
407 }
408 err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid,
409 LOLA_VERB_SET_SRC, new_src, 0);
410 if (!err)
411 success++;
412 else
413 ret = err;
414 }
415 if (success)
416 ret = lola_codec_flush(chip);
417 if (!ret)
418 chip->input_src_mask = src_mask;
419 return ret;
420}
421
422/*
423 */
424static int init_mixer_values(struct lola *chip)
425{
426 int i;
427
428 /* all src on */
429 lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
430
431 /* clear all matrix */
432 memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
433 /* set src gain to 0dB */
434 for (i = 0; i < chip->mixer.src_phys_ins; i++)
435 lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */
436 for (i = 0; i < chip->mixer.src_stream_outs; i++)
437 lola_mixer_set_src_gain(chip,
438 i + chip->mixer.src_stream_out_ofs,
439 336, true); /* 0dB */
440 /* set 1:1 dest gain */
441 for (i = 0; i < chip->mixer.dest_stream_ins; i++) {
442 int src = i % chip->mixer.src_phys_ins;
443 lola_mixer_set_mapping_gain(chip, src, i, 336, true);
444 }
445 for (i = 0; i < chip->mixer.src_stream_outs; i++) {
446 int src = chip->mixer.src_stream_out_ofs + i;
447 int dst = chip->mixer.dest_phys_out_ofs +
448 i % chip->mixer.dest_phys_outs;
449 lola_mixer_set_mapping_gain(chip, src, dst, 336, true);
450 }
451 return 0;
452}
453
454/*
455 * analog mixer control element
456 */
457static int lola_analog_vol_info(struct snd_kcontrol *kcontrol,
458 struct snd_ctl_elem_info *uinfo)
459{
460 struct lola *chip = snd_kcontrol_chip(kcontrol);
461 int dir = kcontrol->private_value;
462
463 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
464 uinfo->count = chip->pin[dir].num_pins;
465 uinfo->value.integer.min = 0;
466 uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps;
467 return 0;
468}
469
470static int lola_analog_vol_get(struct snd_kcontrol *kcontrol,
471 struct snd_ctl_elem_value *ucontrol)
472{
473 struct lola *chip = snd_kcontrol_chip(kcontrol);
474 int dir = kcontrol->private_value;
475 int i;
476
477 for (i = 0; i < chip->pin[dir].num_pins; i++)
478 ucontrol->value.integer.value[i] =
479 chip->pin[dir].pins[i].cur_gain_step;
480 return 0;
481}
482
483static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
484 struct snd_ctl_elem_value *ucontrol)
485{
486 struct lola *chip = snd_kcontrol_chip(kcontrol);
487 int dir = kcontrol->private_value;
488 int i, err;
489
490 for (i = 0; i < chip->pin[dir].num_pins; i++) {
491 err = set_analog_volume(chip, dir, i,
492 ucontrol->value.integer.value[i],
493 true);
494 if (err < 0)
495 return err;
496 }
497 return 0;
498}
499
500static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
501 unsigned int size, unsigned int __user *tlv)
502{
503 struct lola *chip = snd_kcontrol_chip(kcontrol);
504 int dir = kcontrol->private_value;
505 unsigned int val1, val2;
506 struct lola_pin *pin;
507
508 if (size < 4 * sizeof(unsigned int))
509 return -ENOMEM;
510 pin = &chip->pin[dir].pins[0];
511
512 val2 = pin->amp_step_size * 25;
513 val1 = -1 * (int)pin->amp_offset * (int)val2;
514#ifdef TLV_DB_SCALE_MUTE
515 val2 |= TLV_DB_SCALE_MUTE;
516#endif
517 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv))
518 return -EFAULT;
519 if (put_user(2 * sizeof(unsigned int), tlv + 1))
520 return -EFAULT;
521 if (put_user(val1, tlv + 2))
522 return -EFAULT;
523 if (put_user(val2, tlv + 3))
524 return -EFAULT;
525 return 0;
526}
527
528static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
529 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
530 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
531 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
532 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
533 .info = lola_analog_vol_info,
534 .get = lola_analog_vol_get,
535 .put = lola_analog_vol_put,
536 .tlv.c = lola_analog_vol_tlv,
537};
538
539static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name)
540{
541 if (!chip->pin[dir].num_pins)
542 return 0;
543 lola_analog_mixer.name = name;
544 lola_analog_mixer.private_value = dir;
545 return snd_ctl_add(chip->card,
546 snd_ctl_new1(&lola_analog_mixer, chip));
547}
548
549/*
550 */
551static int lola_input_src_info(struct snd_kcontrol *kcontrol,
552 struct snd_ctl_elem_info *uinfo)
553{
554 struct lola *chip = snd_kcontrol_chip(kcontrol);
555
556 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
557 uinfo->count = chip->pin[CAPT].num_pins;
558 uinfo->value.integer.min = 0;
559 uinfo->value.integer.max = 1;
560 return 0;
561}
562
563static int lola_input_src_get(struct snd_kcontrol *kcontrol,
564 struct snd_ctl_elem_value *ucontrol)
565{
566 struct lola *chip = snd_kcontrol_chip(kcontrol);
567 int i;
568
569 for (i = 0; i < chip->pin[CAPT].num_pins; i++)
570 ucontrol->value.integer.value[i] =
571 !!(chip->input_src_mask & (1 << i));
572 return 0;
573}
574
575static int lola_input_src_put(struct snd_kcontrol *kcontrol,
576 struct snd_ctl_elem_value *ucontrol)
577{
578 struct lola *chip = snd_kcontrol_chip(kcontrol);
579 int i;
580 unsigned int mask;
581
582 mask = 0;
583 for (i = 0; i < chip->pin[CAPT].num_pins; i++)
584 if (ucontrol->value.integer.value[i])
585 mask |= 1 << i;
586 return lola_set_src_config(chip, mask, true);
587}
588
589static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
590 .name = "Analog Capture Switch",
591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
592 .info = lola_input_src_info,
593 .get = lola_input_src_get,
594 .put = lola_input_src_put,
595};
596
597static int __devinit create_input_src_mixer(struct lola *chip)
598{
599 return snd_ctl_add(chip->card,
600 snd_ctl_new1(&lola_input_src_mixer, chip));
601}
602
603/*
604 * src gain mixer
605 */
606static int lola_src_gain_info(struct snd_kcontrol *kcontrol,
607 struct snd_ctl_elem_info *uinfo)
608{
609 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
610
611 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
612 uinfo->count = count;
613 uinfo->value.integer.min = 0;
614 uinfo->value.integer.max = 409;
615 return 0;
616}
617
618static int lola_src_gain_get(struct snd_kcontrol *kcontrol,
619 struct snd_ctl_elem_value *ucontrol)
620{
621 struct lola *chip = snd_kcontrol_chip(kcontrol);
622 unsigned int ofs = kcontrol->private_value & 0xff;
623 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
624 unsigned int mask, i;
625
626 mask = readl(&chip->mixer.array->src_gain_enable);
627 for (i = 0; i < count; i++) {
628 unsigned int idx = ofs + i;
629 unsigned short val;
630 if (!(chip->mixer.src_mask & (1 << idx)))
631 return -EINVAL;
632 if (mask & (1 << idx))
633 val = readw(&chip->mixer.array->src_gain[idx]) + 1;
634 else
635 val = 0;
636 ucontrol->value.integer.value[i] = val;
637 }
638 return 0;
639}
640
641static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
642 struct snd_ctl_elem_value *ucontrol)
643{
644 struct lola *chip = snd_kcontrol_chip(kcontrol);
645 unsigned int ofs = kcontrol->private_value & 0xff;
646 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
647 int i, err;
648
649 for (i = 0; i < count; i++) {
650 unsigned int idx = ofs + i;
651 unsigned short val = ucontrol->value.integer.value[i];
652 if (val)
653 val--;
654 err = lola_mixer_set_src_gain(chip, idx, val, !!val);
655 if (err < 0)
656 return err;
657 }
658 return 0;
659}
660
661/* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
662static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
663
664static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
666 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
667 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
668 .info = lola_src_gain_info,
669 .get = lola_src_gain_get,
670 .put = lola_src_gain_put,
671 .tlv.p = lola_src_gain_tlv,
672};
673
674static int __devinit create_src_gain_mixer(struct lola *chip,
675 int num, int ofs, char *name)
676{
677 lola_src_gain_mixer.name = name;
678 lola_src_gain_mixer.private_value = ofs + (num << 8);
679 return snd_ctl_add(chip->card,
680 snd_ctl_new1(&lola_src_gain_mixer, chip));
681}
682
683/*
684 * destination gain (matrix-like) mixer
685 */
686static int lola_dest_gain_info(struct snd_kcontrol *kcontrol,
687 struct snd_ctl_elem_info *uinfo)
688{
689 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
690
691 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
692 uinfo->count = src_num;
693 uinfo->value.integer.min = 0;
694 uinfo->value.integer.max = 433;
695 return 0;
696}
697
698static int lola_dest_gain_get(struct snd_kcontrol *kcontrol,
699 struct snd_ctl_elem_value *ucontrol)
700{
701 struct lola *chip = snd_kcontrol_chip(kcontrol);
702 unsigned int src_ofs = kcontrol->private_value & 0xff;
703 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
704 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
705 unsigned int dst, mask, i;
706
707 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
708 mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]);
709 for (i = 0; i < src_num; i++) {
710 unsigned int src = src_ofs + i;
711 unsigned short val;
712 if (!(chip->mixer.src_mask & (1 << src)))
713 return -EINVAL;
714 if (mask & (1 << dst))
715 val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1;
716 else
717 val = 0;
718 ucontrol->value.integer.value[i] = val;
719 }
720 return 0;
721}
722
723static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
724 struct snd_ctl_elem_value *ucontrol)
725{
726 struct lola *chip = snd_kcontrol_chip(kcontrol);
727 unsigned int src_ofs = kcontrol->private_value & 0xff;
728 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
729 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
730 unsigned int dst, mask;
731 unsigned short gains[MAX_STREAM_COUNT];
732 int i, num;
733
734 mask = 0;
735 num = 0;
736 for (i = 0; i < src_num; i++) {
737 unsigned short val = ucontrol->value.integer.value[i];
738 if (val) {
739 gains[num++] = val - 1;
740 mask |= 1 << i;
741 }
742 }
743 mask <<= src_ofs;
744 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
745 return lola_mixer_set_dest_gains(chip, dst, mask, gains);
746}
747
748static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
749
750static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
751 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
752 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
753 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
754 .info = lola_dest_gain_info,
755 .get = lola_dest_gain_get,
756 .put = lola_dest_gain_put,
757 .tlv.p = lola_dest_gain_tlv,
758};
759
760static int __devinit create_dest_gain_mixer(struct lola *chip,
761 int src_num, int src_ofs,
762 int num, int ofs, char *name)
763{
764 lola_dest_gain_mixer.count = num;
765 lola_dest_gain_mixer.name = name;
766 lola_dest_gain_mixer.private_value =
767 src_ofs + (src_num << 8) + (ofs << 16) + (num << 24);
768 return snd_ctl_add(chip->card,
769 snd_ctl_new1(&lola_dest_gain_mixer, chip));
770}
771
772/*
773 */
774int __devinit lola_create_mixer(struct lola *chip)
775{
776 int err;
777
778 err = create_analog_mixer(chip, PLAY, "Analog Playback Volume");
779 if (err < 0)
780 return err;
781 err = create_analog_mixer(chip, CAPT, "Analog Capture Volume");
782 if (err < 0)
783 return err;
784 err = create_input_src_mixer(chip);
785 if (err < 0)
786 return err;
787 err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0,
788 "Line Source Gain Volume");
789 if (err < 0)
790 return err;
791 err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs,
792 chip->mixer.src_stream_out_ofs,
793 "Stream Source Gain Volume");
794 if (err < 0)
795 return err;
796 err = create_dest_gain_mixer(chip,
797 chip->mixer.src_phys_ins, 0,
798 chip->mixer.dest_stream_ins, 0,
799 "Line Capture Volume");
800 if (err < 0)
801 return err;
802 err = create_dest_gain_mixer(chip,
803 chip->mixer.src_stream_outs,
804 chip->mixer.src_stream_out_ofs,
805 chip->mixer.dest_stream_ins, 0,
806 "Stream-Loopback Capture Volume");
807 if (err < 0)
808 return err;
809 err = create_dest_gain_mixer(chip,
810 chip->mixer.src_phys_ins, 0,
811 chip->mixer.dest_phys_outs,
812 chip->mixer.dest_phys_out_ofs,
813 "Line-Loopback Playback Volume");
814 if (err < 0)
815 return err;
816 err = create_dest_gain_mixer(chip,
817 chip->mixer.src_stream_outs,
818 chip->mixer.src_stream_out_ofs,
819 chip->mixer.dest_phys_outs,
820 chip->mixer.dest_phys_out_ofs,
821 "Stream Playback Volume");
822 if (err < 0)
823 return err;
824
825 return init_mixer_values(chip);
826}
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
new file mode 100644
index 000000000000..bf17f921d45f
--- /dev/null
+++ b/sound/pci/lola/lola_pcm.c
@@ -0,0 +1,607 @@
1/*
2 * Support for Digigram Lola PCI-e boards
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/dma-mapping.h>
24#include <linux/pci.h>
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include "lola.h"
28
29#define BDL_SIZE 4096
30#define LOLA_MAX_BDL_ENTRIES (BDL_SIZE / 16)
31#define LOLA_MAX_FRAG 32
32#define LOLA_MAX_BUF_SIZE (1024*1024*1024)
33
34static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream)
35{
36 struct lola *chip = snd_pcm_substream_chip(substream);
37 return &chip->pcm[substream->stream];
38}
39
40static struct lola_stream *lola_get_stream(struct snd_pcm_substream *substream)
41{
42 struct lola_pcm *pcm = lola_get_pcm(substream);
43 unsigned int idx = substream->number;
44 return &pcm->streams[idx];
45}
46
47static unsigned int lola_get_lrc(struct lola *chip)
48{
49 return lola_readl(chip, BAR1, LRC);
50}
51
52static unsigned int lola_get_tstamp(struct lola *chip, bool quick_no_sync)
53{
54 unsigned int tstamp = lola_get_lrc(chip) >> 8;
55 if (chip->granularity) {
56 unsigned int wait_banks = quick_no_sync ? 0 : 8;
57 tstamp += (wait_banks + 1) * chip->granularity - 1;
58 tstamp -= tstamp % chip->granularity;
59 }
60 return tstamp << 8;
61}
62
63/* clear any pending interrupt status */
64static void lola_stream_clear_pending_irq(struct lola *chip,
65 struct lola_stream *str)
66{
67 unsigned int val = lola_dsd_read(chip, str->dsd, STS);
68 val &= LOLA_DSD_STS_DESE | LOLA_DSD_STS_BCIS;
69 if (val)
70 lola_dsd_write(chip, str->dsd, STS, val);
71}
72
73static void lola_stream_start(struct lola *chip, struct lola_stream *str,
74 unsigned int tstamp)
75{
76 lola_stream_clear_pending_irq(chip, str);
77 lola_dsd_write(chip, str->dsd, CTL,
78 LOLA_DSD_CTL_SRUN |
79 LOLA_DSD_CTL_IOCE |
80 LOLA_DSD_CTL_DEIE |
81 LOLA_DSD_CTL_VLRCV |
82 tstamp);
83}
84
85static void lola_stream_stop(struct lola *chip, struct lola_stream *str,
86 unsigned int tstamp)
87{
88 lola_dsd_write(chip, str->dsd, CTL,
89 LOLA_DSD_CTL_IOCE |
90 LOLA_DSD_CTL_DEIE |
91 LOLA_DSD_CTL_VLRCV |
92 tstamp);
93 lola_stream_clear_pending_irq(chip, str);
94}
95
96static void lola_stream_clear(struct lola *chip, struct lola_stream *str)
97{
98 lola_dsd_write(chip, str->dsd, CTL, 0);
99 lola_stream_clear_pending_irq(chip, str);
100}
101
102static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
103{
104 unsigned long end_time = jiffies + msecs_to_jiffies(50);
105 while (time_before(jiffies, end_time)) {
106 unsigned int val;
107 val = lola_dsd_read(chip, str->dsd, CTL);
108 if (!(val & LOLA_DSD_CTL_SRST))
109 return;
110 msleep(1);
111 }
112 printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd);
113}
114
115static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
116{
117 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST);
118 lola_dsd_write(chip, str->dsd, LVI, 0);
119 lola_dsd_write(chip, str->dsd, BDPU, 0);
120 lola_dsd_write(chip, str->dsd, BDPL, 0);
121 wait_for_srst_clear(chip, str);
122}
123
124static int lola_stream_wait_for_fifo_ready(struct lola *chip,
125 struct lola_stream *str)
126{
127 unsigned long end_time = jiffies + msecs_to_jiffies(50);
128 while (time_before(jiffies, end_time)) {
129 unsigned int val = lola_dsd_read(chip, str->dsd, STS);
130 if (val & LOLA_DSD_STS_FIFORDY)
131 return 0;
132 msleep(1);
133 }
134 printk(KERN_WARNING SFX "FIFO not ready (stream %d)\n", str->dsd);
135 return -EIO;
136}
137
138static struct snd_pcm_hardware lola_pcm_hw = {
139 .info = (SNDRV_PCM_INFO_MMAP |
140 SNDRV_PCM_INFO_INTERLEAVED |
141 SNDRV_PCM_INFO_BLOCK_TRANSFER |
142 SNDRV_PCM_INFO_MMAP_VALID |
143 SNDRV_PCM_INFO_PAUSE),
144 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
145 SNDRV_PCM_FMTBIT_S24_LE |
146 SNDRV_PCM_FMTBIT_S32_LE |
147 SNDRV_PCM_FMTBIT_FLOAT_LE),
148 .rates = SNDRV_PCM_RATE_48000,
149 .rate_min = 48000,
150 .rate_max = 48000,
151 .channels_min = 1,
152 .channels_max = 2,
153 .buffer_bytes_max = LOLA_MAX_BUF_SIZE,
154 .period_bytes_min = 128,
155 .period_bytes_max = LOLA_MAX_BUF_SIZE / 2,
156 .periods_min = 2,
157 .periods_max = LOLA_MAX_FRAG,
158 .fifo_size = 0,
159};
160
161static int lola_pcm_open(struct snd_pcm_substream *substream)
162{
163 struct lola *chip = snd_pcm_substream_chip(substream);
164 struct lola_pcm *pcm = lola_get_pcm(substream);
165 struct lola_stream *str = lola_get_stream(substream);
166 struct snd_pcm_runtime *runtime = substream->runtime;
167 int err;
168
169 mutex_lock(&chip->open_mutex);
170 if (str->opened) {
171 mutex_unlock(&chip->open_mutex);
172 return -EBUSY;
173 }
174 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
175 snd_dma_pci_data(chip->pci),
176 PAGE_SIZE, &str->bdl);
177 if (err < 0) {
178 mutex_unlock(&chip->open_mutex);
179 printk(KERN_ERR SFX "Can't allocate BDL\n");
180 return err;
181 }
182 str->substream = substream;
183 str->master = NULL;
184 str->opened = 1;
185 runtime->hw = lola_pcm_hw;
186 runtime->hw.channels_max = pcm->num_streams - str->index;
187 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
188 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
189 128);
190 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
191 128);
192 mutex_unlock(&chip->open_mutex);
193 return 0;
194}
195
196static void lola_cleanup_slave_streams(struct lola_pcm *pcm,
197 struct lola_stream *str)
198{
199 int i;
200 for (i = str->index + 1; i < pcm->num_streams; i++) {
201 struct lola_stream *s = &pcm->streams[i];
202 if (s->master != str)
203 break;
204 s->master = NULL;
205 s->opened = 0;
206 }
207}
208
209static int lola_pcm_close(struct snd_pcm_substream *substream)
210{
211 struct lola *chip = snd_pcm_substream_chip(substream);
212 struct lola_stream *str = lola_get_stream(substream);
213
214 mutex_lock(&chip->open_mutex);
215 if (str->substream == substream) {
216 str->substream = NULL;
217 str->opened = 0;
218 }
219 snd_dma_free_pages(&str->bdl);
220 mutex_unlock(&chip->open_mutex);
221 return 0;
222}
223
224static int lola_pcm_hw_params(struct snd_pcm_substream *substream,
225 struct snd_pcm_hw_params *hw_params)
226{
227 struct lola_stream *str = lola_get_stream(substream);
228
229 str->bufsize = 0;
230 str->period_bytes = 0;
231 str->format_verb = 0;
232 return snd_pcm_lib_malloc_pages(substream,
233 params_buffer_bytes(hw_params));
234}
235
236static int lola_pcm_hw_free(struct snd_pcm_substream *substream)
237{
238 struct lola *chip = snd_pcm_substream_chip(substream);
239 struct lola_pcm *pcm = lola_get_pcm(substream);
240 struct lola_stream *str = lola_get_stream(substream);
241
242 mutex_lock(&chip->open_mutex);
243 lola_stream_reset(chip, str);
244 lola_cleanup_slave_streams(pcm, str);
245 mutex_unlock(&chip->open_mutex);
246 return snd_pcm_lib_free_pages(substream);
247}
248
249/*
250 * set up a BDL entry
251 */
252static int setup_bdle(struct snd_pcm_substream *substream,
253 struct lola_stream *str, u32 **bdlp,
254 int ofs, int size)
255{
256 u32 *bdl = *bdlp;
257
258 while (size > 0) {
259 dma_addr_t addr;
260 int chunk;
261
262 if (str->frags >= LOLA_MAX_BDL_ENTRIES)
263 return -EINVAL;
264
265 addr = snd_pcm_sgbuf_get_addr(substream, ofs);
266 /* program the address field of the BDL entry */
267 bdl[0] = cpu_to_le32((u32)addr);
268 bdl[1] = cpu_to_le32(upper_32_bits(addr));
269 /* program the size field of the BDL entry */
270 chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);
271 bdl[2] = cpu_to_le32(chunk);
272 /* program the IOC to enable interrupt
273 * only when the whole fragment is processed
274 */
275 size -= chunk;
276 bdl[3] = size ? 0 : cpu_to_le32(0x01);
277 bdl += 4;
278 str->frags++;
279 ofs += chunk;
280 }
281 *bdlp = bdl;
282 return ofs;
283}
284
285/*
286 * set up BDL entries
287 */
288static int lola_setup_periods(struct lola *chip,
289 struct snd_pcm_substream *substream,
290 struct lola_stream *str)
291{
292 u32 *bdl;
293 int i, ofs, periods, period_bytes;
294
295 period_bytes = str->period_bytes;
296 periods = str->bufsize / period_bytes;
297
298 /* program the initial BDL entries */
299 bdl = (u32 *)str->bdl.area;
300 ofs = 0;
301 str->frags = 0;
302 for (i = 0; i < periods; i++) {
303 ofs = setup_bdle(substream, str, &bdl, ofs, period_bytes);
304 if (ofs < 0)
305 goto error;
306 }
307 return 0;
308
309 error:
310 snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n",
311 str->bufsize, period_bytes);
312 return -EINVAL;
313}
314
315static unsigned int lola_get_format_verb(struct snd_pcm_substream *substream)
316{
317 unsigned int verb;
318
319 switch (substream->runtime->format) {
320 case SNDRV_PCM_FORMAT_S16_LE:
321 verb = 0x00000000;
322 break;
323 case SNDRV_PCM_FORMAT_S24_LE:
324 verb = 0x00000200;
325 break;
326 case SNDRV_PCM_FORMAT_S32_LE:
327 verb = 0x00000300;
328 break;
329 case SNDRV_PCM_FORMAT_FLOAT_LE:
330 verb = 0x00001300;
331 break;
332 default:
333 return 0;
334 }
335 verb |= substream->runtime->channels;
336 return verb;
337}
338
339static int lola_set_stream_config(struct lola *chip,
340 struct lola_stream *str,
341 int channels)
342{
343 int i, err;
344 unsigned int verb, val;
345
346 /* set format info for all channels
347 * (with only one command for the first channel)
348 */
349 err = lola_codec_read(chip, str->nid, LOLA_VERB_SET_STREAM_FORMAT,
350 str->format_verb, 0, &val, NULL);
351 if (err < 0) {
352 printk(KERN_ERR SFX "Cannot set stream format 0x%x\n",
353 str->format_verb);
354 return err;
355 }
356
357 /* update stream - channel config */
358 for (i = 0; i < channels; i++) {
359 verb = (str->index << 6) | i;
360 err = lola_codec_read(chip, str[i].nid,
361 LOLA_VERB_SET_CHANNEL_STREAMID, 0, verb,
362 &val, NULL);
363 if (err < 0) {
364 printk(KERN_ERR SFX "Cannot set stream channel %d\n", i);
365 return err;
366 }
367 }
368 return 0;
369}
370
371/*
372 * set up the SD for streaming
373 */
374static int lola_setup_controller(struct lola *chip, struct lola_stream *str)
375{
376 /* make sure the run bit is zero for SD */
377 lola_stream_clear(chip, str);
378 /* set up BDL */
379 lola_dsd_write(chip, str->dsd, BDPL, (u32)str->bdl.addr);
380 lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(str->bdl.addr));
381 /* program the stream LVI (last valid index) of the BDL */
382 lola_dsd_write(chip, str->dsd, LVI, str->frags - 1);
383 lola_stream_stop(chip, str, lola_get_tstamp(chip, false));
384 lola_stream_wait_for_fifo_ready(chip, str);
385
386 return 0;
387}
388
389static int lola_pcm_prepare(struct snd_pcm_substream *substream)
390{
391 struct lola *chip = snd_pcm_substream_chip(substream);
392 struct lola_pcm *pcm = lola_get_pcm(substream);
393 struct lola_stream *str = lola_get_stream(substream);
394 struct snd_pcm_runtime *runtime = substream->runtime;
395 unsigned int bufsize, period_bytes, format_verb;
396 int i, err;
397
398 mutex_lock(&chip->open_mutex);
399 lola_stream_reset(chip, str);
400 lola_cleanup_slave_streams(pcm, str);
401 if (str->index + runtime->channels >= pcm->num_streams) {
402 mutex_unlock(&chip->open_mutex);
403 return -EINVAL;
404 }
405 for (i = 1; i < runtime->channels; i++) {
406 str[i].master = str;
407 str[i].opened = 1;
408 }
409 mutex_unlock(&chip->open_mutex);
410
411 bufsize = snd_pcm_lib_buffer_bytes(substream);
412 period_bytes = snd_pcm_lib_period_bytes(substream);
413 format_verb = lola_get_format_verb(substream);
414
415 if (bufsize != str->bufsize ||
416 period_bytes != str->period_bytes ||
417 format_verb != str->format_verb) {
418 str->bufsize = bufsize;
419 str->period_bytes = period_bytes;
420 str->format_verb = format_verb;
421 err = lola_setup_periods(chip, substream, str);
422 if (err < 0)
423 return err;
424 }
425
426 err = lola_set_stream_config(chip, str, runtime->channels);
427 if (err < 0)
428 return err;
429
430 return lola_setup_controller(chip, str);
431}
432
433static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
434{
435 struct lola *chip = snd_pcm_substream_chip(substream);
436 struct lola_stream *str;
437 struct snd_pcm_substream *s;
438 unsigned int start;
439 unsigned int tstamp;
440
441 switch (cmd) {
442 case SNDRV_PCM_TRIGGER_START:
443 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
444 case SNDRV_PCM_TRIGGER_RESUME:
445 start = 1;
446 break;
447 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
448 case SNDRV_PCM_TRIGGER_SUSPEND:
449 case SNDRV_PCM_TRIGGER_STOP:
450 start = 0;
451 break;
452 default:
453 return -EINVAL;
454 }
455
456 tstamp = lola_get_tstamp(chip, false);
457 spin_lock(&chip->reg_lock);
458 snd_pcm_group_for_each_entry(s, substream) {
459 if (s->pcm->card != substream->pcm->card)
460 continue;
461 str = lola_get_stream(s);
462 if (start)
463 lola_stream_start(chip, str, tstamp);
464 else
465 lola_stream_stop(chip, str, tstamp);
466 str->running = start;
467 snd_pcm_trigger_done(s, substream);
468 }
469 spin_unlock(&chip->reg_lock);
470 return 0;
471}
472
473static snd_pcm_uframes_t lola_pcm_pointer(struct snd_pcm_substream *substream)
474{
475 struct lola *chip = snd_pcm_substream_chip(substream);
476 struct lola_stream *str = lola_get_stream(substream);
477 unsigned int pos = lola_dsd_read(chip, str->dsd, LPIB);
478
479 if (pos >= str->bufsize)
480 pos = 0;
481 return bytes_to_frames(substream->runtime, pos);
482}
483
484void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits)
485{
486 int i;
487
488 for (i = 0; bits && i < pcm->num_streams; i++) {
489 if (bits & (1 << i)) {
490 struct lola_stream *str = &pcm->streams[i];
491 if (str->substream && str->running)
492 snd_pcm_period_elapsed(str->substream);
493 bits &= ~(1 << i);
494 }
495 }
496}
497
498static struct snd_pcm_ops lola_pcm_ops = {
499 .open = lola_pcm_open,
500 .close = lola_pcm_close,
501 .ioctl = snd_pcm_lib_ioctl,
502 .hw_params = lola_pcm_hw_params,
503 .hw_free = lola_pcm_hw_free,
504 .prepare = lola_pcm_prepare,
505 .trigger = lola_pcm_trigger,
506 .pointer = lola_pcm_pointer,
507 .page = snd_pcm_sgbuf_ops_page,
508};
509
510int __devinit lola_create_pcm(struct lola *chip)
511{
512 struct snd_pcm *pcm;
513 int i, err;
514
515 err = snd_pcm_new(chip->card, "Digigram Lola", 0,
516 chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams,
517 chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams,
518 &pcm);
519 if (err < 0)
520 return err;
521 strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
522 pcm->private_data = chip;
523 for (i = 0; i < 2; i++) {
524 if (chip->pcm[i].num_streams)
525 snd_pcm_set_ops(pcm, i, &lola_pcm_ops);
526 }
527 /* buffer pre-allocation */
528 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
529 snd_dma_pci_data(chip->pci),
530 1024 * 64, 32 * 1024 * 1024);
531 return 0;
532}
533
534void lola_free_pcm(struct lola *chip)
535{
536 /* nothing to do */
537}
538
539/*
540 */
541
542static int lola_init_stream(struct lola *chip, struct lola_stream *str,
543 int idx, int nid, int dir)
544{
545 unsigned int val;
546 int err;
547
548 str->nid = nid;
549 str->index = idx;
550 str->dsd = idx;
551 if (dir == PLAY)
552 str->dsd += MAX_STREAM_IN_COUNT;
553 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
554 if (err < 0) {
555 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
556 return err;
557 }
558 if (dir == PLAY) {
559 /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */
560 if ((val & 0x00f00dff) != 0x00000010) {
561 printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n",
562 val, nid);
563 return -EINVAL;
564 }
565 } else {
566 /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1)
567 * (bug : ignore bit8: Conn list = 0/1)
568 */
569 if ((val & 0x00f00cff) != 0x00100010) {
570 printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n",
571 val, nid);
572 return -EINVAL;
573 }
574 /* test bit9:DIGITAL and bit12:SRC_PRESENT*/
575 if ((val & 0x00001200) == 0x00001200)
576 chip->input_src_caps_mask |= (1 << idx);
577 }
578
579 err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val);
580 if (err < 0) {
581 printk(KERN_ERR SFX "Can't read FORMATS 0x%x\n", nid);
582 return err;
583 }
584 val &= 3;
585 if (val == 3)
586 str->can_float = true;
587 if (!(val & 1)) {
588 printk(KERN_ERR SFX "Invalid formats 0x%x for 0x%x", val, nid);
589 return -EINVAL;
590 }
591 return 0;
592}
593
594int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp)
595{
596 struct lola_pcm *pcm = &chip->pcm[dir];
597 int i, nid, err;
598
599 nid = *nidp;
600 for (i = 0; i < pcm->num_streams; i++, nid++) {
601 err = lola_init_stream(chip, &pcm->streams[i], i, nid, dir);
602 if (err < 0)
603 return err;
604 }
605 *nidp = nid;
606 return 0;
607}
diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c
new file mode 100644
index 000000000000..247fa2477171
--- /dev/null
+++ b/sound/pci/lola/lola_proc.c
@@ -0,0 +1,86 @@
1/*
2 * Support for Digigram Lola PCI-e boards
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/io.h>
24#include <sound/core.h>
25#include <sound/info.h>
26#include <sound/pcm.h>
27#include "lola.h"
28
29/* direct codec access for debugging */
30static void lola_proc_codec_write(struct snd_info_entry *entry,
31 struct snd_info_buffer *buffer)
32{
33 struct lola *chip = entry->private_data;
34 char line[64];
35 unsigned int id, verb, data, extdata;
36 while (!snd_info_get_line(buffer, line, sizeof(line))) {
37 if (sscanf(line, "%i %i %i %i", &id, &verb, &data, &extdata) != 4)
38 continue;
39 lola_codec_read(chip, id, verb, data, extdata,
40 &chip->debug_res,
41 &chip->debug_res_ex);
42 }
43}
44
45static void lola_proc_codec_read(struct snd_info_entry *entry,
46 struct snd_info_buffer *buffer)
47{
48 struct lola *chip = entry->private_data;
49 snd_iprintf(buffer, "0x%x 0x%x\n", chip->debug_res, chip->debug_res_ex);
50}
51
52/*
53 * dump some registers
54 */
55static void lola_proc_regs_read(struct snd_info_entry *entry,
56 struct snd_info_buffer *buffer)
57{
58 struct lola *chip = entry->private_data;
59 int i;
60
61 for (i = 0; i < 0x40; i += 4) {
62 snd_iprintf(buffer, "BAR0 %02x: %08x\n", i,
63 readl(chip->bar[BAR0].remap_addr + i));
64 }
65 for (i = 0; i < 0x30; i += 4) {
66 snd_iprintf(buffer, "BAR1 %02x: %08x\n", i,
67 readl(chip->bar[BAR1].remap_addr + i));
68 }
69 for (i = 0x80; i < 0xa0; i += 4) {
70 snd_iprintf(buffer, "BAR1 %02x: %08x\n", i,
71 readl(chip->bar[BAR1].remap_addr + i));
72 }
73}
74
75void __devinit lola_proc_debug_new(struct lola *chip)
76{
77 struct snd_info_entry *entry;
78
79 if (!snd_card_proc_new(chip->card, "codec", &entry)) {
80 snd_info_set_text_ops(entry, chip, lola_proc_codec_read);
81 entry->mode |= S_IWUSR;
82 entry->c.text.write = lola_proc_codec_write;
83 }
84 if (!snd_card_proc_new(chip->card, "regs", &entry))
85 snd_info_set_text_ops(entry, chip, lola_proc_regs_read);
86}