aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/lola
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-03 10:14:46 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-03 10:31:05 -0400
commitd43f3010b8fa7530c3780c087fad9b0a8a437ba1 (patch)
treef54b55676b5b66115ee0bfc1df0994044cd9b697 /sound/pci/lola
parent521cb40b0c44418a4fd36dc633f575813d59a43d (diff)
ALSA: Add the driver for Digigram Lola PCI-e boards
Added a new driver for supporting Digigram Lola PCI-e boards. Lola has a similar h/w design like HD-audio but with extended verbs. Thus the driver is written similarly like HD-audio driver in the bus part. The codec part is rather written in a fixed way specific to the Lola board because of the verb incompatibility. The driver provides basic PCM, supporting multi-streams and mixing. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/lola')
-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
7 files changed, 3095 insertions, 0 deletions
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}