1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#undef VWSND_DEBUG
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144#include <linux/module.h>
145#include <linux/init.h>
146
147#include <linux/spinlock.h>
148#include <linux/smp_lock.h>
149#include <linux/wait.h>
150#include <linux/interrupt.h>
151#include <linux/mutex.h>
152#include <linux/slab.h>
153
154#include <asm/visws/cobalt.h>
155
156#include "sound_config.h"
157
158
159
160
161#ifdef VWSND_DEBUG
162
163static int shut_up = 1;
164
165
166
167
168
169static void dbgassert(const char *fcn, int line, const char *expr)
170{
171 if (in_interrupt())
172 panic("ASSERTION FAILED IN INTERRUPT, %s:%s:%d %s\n",
173 __FILE__, fcn, line, expr);
174 else {
175 int x;
176 printk(KERN_ERR "ASSERTION FAILED, %s:%s:%d %s\n",
177 __FILE__, fcn, line, expr);
178 x = * (volatile int *) 0;
179 }
180}
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198#define ASSERT(e) ((e) ? (void) 0 : dbgassert(__func__, __LINE__, #e))
199#define DBGDO(x) x
200#define DBGX(fmt, args...) (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args))
201#define DBGP(fmt, args...) (DBGX("%s: " fmt, __func__ , ##args))
202#define DBGE(fmt, args...) (DBGX("%s" fmt, __func__ , ##args))
203#define DBGC(rtn) (DBGP("calling %s\n", rtn))
204#define DBGR() (DBGP("returning\n"))
205#define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args))
206#define DBGPV(fmt, args...) (shut_up ? 0 : DBGP(fmt, ##args))
207#define DBGEV(fmt, args...) (shut_up ? 0 : DBGE(fmt, ##args))
208#define DBGCV(rtn) (shut_up ? 0 : DBGC(rtn))
209#define DBGRV() (shut_up ? 0 : DBGR())
210
211#else
212
213#define ASSERT(e) ((void) 0)
214#define DBGDO(x)
215#define DBGX(fmt, args...) ((void) 0)
216#define DBGP(fmt, args...) ((void) 0)
217#define DBGE(fmt, args...) ((void) 0)
218#define DBGC(rtn) ((void) 0)
219#define DBGR() ((void) 0)
220#define DBGPV(fmt, args...) ((void) 0)
221#define DBGXV(fmt, args...) ((void) 0)
222#define DBGEV(fmt, args...) ((void) 0)
223#define DBGCV(rtn) ((void) 0)
224#define DBGRV() ((void) 0)
225
226#endif
227
228
229
230
231
232
233
234
235
236enum {
237 LI_PAGE0_OFFSET = 0x01000 - 0x1000,
238 LI_PAGE1_OFFSET = 0x0F000 - 0x1000,
239 LI_PAGE2_OFFSET = 0x10000 - 0x1000,
240};
241
242
243
244typedef struct lithium {
245 void * page0;
246 void * page1;
247 void * page2;
248 spinlock_t lock;
249} lithium_t;
250
251
252
253
254
255static void li_destroy(lithium_t *lith)
256{
257 if (lith->page0) {
258 iounmap(lith->page0);
259 lith->page0 = NULL;
260 }
261 if (lith->page1) {
262 iounmap(lith->page1);
263 lith->page1 = NULL;
264 }
265 if (lith->page2) {
266 iounmap(lith->page2);
267 lith->page2 = NULL;
268 }
269}
270
271
272
273
274
275
276
277static int __init li_create(lithium_t *lith, unsigned long baseaddr)
278{
279 spin_lock_init(&lith->lock);
280 lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE);
281 lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE);
282 lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE);
283 if (!lith->page0 || !lith->page1 || !lith->page2) {
284 li_destroy(lith);
285 return -ENOMEM;
286 }
287 return 0;
288}
289
290
291
292
293
294static __inline__ unsigned long li_readl(lithium_t *lith, int off)
295{
296 return * (volatile unsigned long *) (lith->page0 + off);
297}
298
299static __inline__ unsigned char li_readb(lithium_t *lith, int off)
300{
301 return * (volatile unsigned char *) (lith->page0 + off);
302}
303
304static __inline__ void li_writel(lithium_t *lith, int off, unsigned long val)
305{
306 * (volatile unsigned long *) (lith->page0 + off) = val;
307}
308
309static __inline__ void li_writeb(lithium_t *lith, int off, unsigned char val)
310{
311 * (volatile unsigned char *) (lith->page0 + off) = val;
312}
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367#define LI_HOST_CONTROLLER 0x000
368# define LI_HC_RESET 0x00008000
369# define LI_HC_LINK_ENABLE 0x00004000
370# define LI_HC_LINK_FAILURE 0x00000004
371# define LI_HC_LINK_CODEC 0x00000002
372# define LI_HC_LINK_READY 0x00000001
373
374#define LI_INTR_STATUS 0x010
375#define LI_INTR_MASK 0x014
376# define LI_INTR_LINK_ERR 0x00008000
377# define LI_INTR_COMM2_TRIG 0x00000008
378# define LI_INTR_COMM2_UNDERFLOW 0x00000004
379# define LI_INTR_COMM1_TRIG 0x00000002
380# define LI_INTR_COMM1_OVERFLOW 0x00000001
381
382#define LI_CODEC_COMMAND 0x018
383# define LI_CC_BUSY 0x00008000
384# define LI_CC_DIR 0x00000080
385# define LI_CC_DIR_RD LI_CC_DIR
386# define LI_CC_DIR_WR (!LI_CC_DIR)
387# define LI_CC_ADDR_MASK 0x0000007F
388
389#define LI_CODEC_DATA 0x01C
390
391#define LI_COMM1_BASE 0x100
392#define LI_COMM1_CTL 0x104
393# define LI_CCTL_RESET 0x80000000
394# define LI_CCTL_SIZE 0x70000000
395# define LI_CCTL_DMA_ENABLE 0x08000000
396# define LI_CCTL_TMASK 0x07000000
397# define LI_CCTL_TPTR 0x00FF0000
398# define LI_CCTL_RPTR 0x0000FF00
399# define LI_CCTL_WPTR 0x000000FF
400#define LI_COMM1_CFG 0x108
401# define LI_CCFG_LOCK 0x00008000
402# define LI_CCFG_SLOT 0x00000070
403# define LI_CCFG_DIRECTION 0x00000008
404# define LI_CCFG_DIR_IN (!LI_CCFG_DIRECTION)
405# define LI_CCFG_DIR_OUT LI_CCFG_DIRECTION
406# define LI_CCFG_MODE 0x00000004
407# define LI_CCFG_MODE_MONO (!LI_CCFG_MODE)
408# define LI_CCFG_MODE_STEREO LI_CCFG_MODE
409# define LI_CCFG_FORMAT 0x00000003
410# define LI_CCFG_FMT_8BIT 0x00000000
411# define LI_CCFG_FMT_16BIT 0x00000001
412#define LI_COMM2_BASE 0x10C
413#define LI_COMM2_CTL 0x110
414
415#define LI_COMM2_CFG 0x114
416
417
418#define LI_UST_LOW 0x200
419#define LI_UST_HIGH 0x204
420
421#define LI_AUDIO1_UST 0x300
422#define LI_AUDIO1_MSC 0x304
423#define LI_AUDIO2_UST 0x308
424#define LI_AUDIO2_MSC 0x30C
425
426
427
428
429
430
431#define DMACHUNK_SHIFT 5
432#define DMACHUNK_SIZE (1 << DMACHUNK_SHIFT)
433#define BYTES_TO_CHUNKS(bytes) ((bytes) >> DMACHUNK_SHIFT)
434#define CHUNKS_TO_BYTES(chunks) ((chunks) << DMACHUNK_SHIFT)
435
436
437
438
439
440
441
442
443
444#define SHIFT_FIELD(val, mask) (((val) * ((mask) & -(mask))) & (mask))
445#define UNSHIFT_FIELD(val, mask) (((val) & (mask)) / ((mask) & -(mask)))
446
447
448
449
450
451
452
453
454
455
456typedef struct dma_chan_desc {
457 int basereg;
458 int cfgreg;
459 int ctlreg;
460 int hwptrreg;
461 int swptrreg;
462 int ustreg;
463 int mscreg;
464 unsigned long swptrmask;
465 int ad1843_slot;
466 int direction;
467} dma_chan_desc_t;
468
469static const dma_chan_desc_t li_comm1 = {
470 LI_COMM1_BASE,
471 LI_COMM1_CFG,
472 LI_COMM1_CTL,
473 LI_COMM1_CTL + 0,
474 LI_COMM1_CTL + 1,
475 LI_AUDIO1_UST,
476 LI_AUDIO1_MSC,
477 LI_CCTL_RPTR,
478 2,
479 LI_CCFG_DIR_IN
480};
481
482static const dma_chan_desc_t li_comm2 = {
483 LI_COMM2_BASE,
484 LI_COMM2_CFG,
485 LI_COMM2_CTL,
486 LI_COMM2_CTL + 1,
487 LI_COMM2_CTL + 0,
488 LI_AUDIO2_UST,
489 LI_AUDIO2_MSC,
490 LI_CCTL_WPTR,
491 2,
492 LI_CCFG_DIR_OUT
493};
494
495
496
497
498
499
500
501
502
503
504typedef struct dma_chan {
505 const dma_chan_desc_t *desc;
506 lithium_t *lith;
507 unsigned long baseval;
508 unsigned long cfgval;
509 unsigned long ctlval;
510} dma_chan_t;
511
512
513
514
515
516
517
518typedef struct ustmsc {
519 unsigned long long ust;
520 unsigned long msc;
521} ustmsc_t;
522
523
524
525
526
527
528
529
530static int li_ad1843_wait(lithium_t *lith)
531{
532 unsigned long later = jiffies + 2;
533 while (li_readl(lith, LI_CODEC_COMMAND) & LI_CC_BUSY)
534 if (time_after_eq(jiffies, later))
535 return -EBUSY;
536 return 0;
537}
538
539
540
541
542
543
544
545static int li_read_ad1843_reg(lithium_t *lith, int reg)
546{
547 int val;
548
549 ASSERT(!in_interrupt());
550 spin_lock(&lith->lock);
551 {
552 val = li_ad1843_wait(lith);
553 if (val == 0) {
554 li_writel(lith, LI_CODEC_COMMAND, LI_CC_DIR_RD | reg);
555 val = li_ad1843_wait(lith);
556 }
557 if (val == 0)
558 val = li_readl(lith, LI_CODEC_DATA);
559 }
560 spin_unlock(&lith->lock);
561
562 DBGXV("li_read_ad1843_reg(lith=0x%p, reg=%d) returns 0x%04x\n",
563 lith, reg, val);
564
565 return val;
566}
567
568
569
570
571
572static void li_write_ad1843_reg(lithium_t *lith, int reg, int newval)
573{
574 spin_lock(&lith->lock);
575 {
576 if (li_ad1843_wait(lith) == 0) {
577 li_writel(lith, LI_CODEC_DATA, newval);
578 li_writel(lith, LI_CODEC_COMMAND, LI_CC_DIR_WR | reg);
579 }
580 }
581 spin_unlock(&lith->lock);
582}
583
584
585
586
587
588
589static void li_setup_dma(dma_chan_t *chan,
590 const dma_chan_desc_t *desc,
591 lithium_t *lith,
592 unsigned long buffer_paddr,
593 int bufshift,
594 int fragshift,
595 int channels,
596 int sampsize)
597{
598 unsigned long mode, format;
599 unsigned long size, tmask;
600
601 DBGEV("(chan=0x%p, desc=0x%p, lith=0x%p, buffer_paddr=0x%lx, "
602 "bufshift=%d, fragshift=%d, channels=%d, sampsize=%d)\n",
603 chan, desc, lith, buffer_paddr,
604 bufshift, fragshift, channels, sampsize);
605
606
607
608 li_writel(lith, desc->ctlreg, LI_CCTL_RESET);
609
610 ASSERT(channels == 1 || channels == 2);
611 if (channels == 2)
612 mode = LI_CCFG_MODE_STEREO;
613 else
614 mode = LI_CCFG_MODE_MONO;
615 ASSERT(sampsize == 1 || sampsize == 2);
616 if (sampsize == 2)
617 format = LI_CCFG_FMT_16BIT;
618 else
619 format = LI_CCFG_FMT_8BIT;
620 chan->desc = desc;
621 chan->lith = lith;
622
623
624
625
626
627
628
629 ASSERT(!(buffer_paddr & 0xFF));
630 chan->baseval = (buffer_paddr >> 8) | 1 << (37 - 8);
631
632 chan->cfgval = ((chan->cfgval & ~LI_CCFG_LOCK) |
633 SHIFT_FIELD(desc->ad1843_slot, LI_CCFG_SLOT) |
634 desc->direction |
635 mode |
636 format);
637
638 size = bufshift - 6;
639 tmask = 13 - fragshift;
640 ASSERT(size >= 2 && size <= 7);
641 ASSERT(tmask >= 1 && tmask <= 7);
642 chan->ctlval = ((chan->ctlval & ~LI_CCTL_RESET) |
643 SHIFT_FIELD(size, LI_CCTL_SIZE) |
644 (chan->ctlval & ~LI_CCTL_DMA_ENABLE) |
645 SHIFT_FIELD(tmask, LI_CCTL_TMASK) |
646 SHIFT_FIELD(0, LI_CCTL_TPTR));
647
648 DBGPV("basereg 0x%x = 0x%lx\n", desc->basereg, chan->baseval);
649 DBGPV("cfgreg 0x%x = 0x%lx\n", desc->cfgreg, chan->cfgval);
650 DBGPV("ctlreg 0x%x = 0x%lx\n", desc->ctlreg, chan->ctlval);
651
652 li_writel(lith, desc->basereg, chan->baseval);
653 li_writel(lith, desc->cfgreg, chan->cfgval);
654 li_writel(lith, desc->ctlreg, chan->ctlval);
655
656 DBGRV();
657}
658
659static void li_shutdown_dma(dma_chan_t *chan)
660{
661 lithium_t *lith = chan->lith;
662 void * lith1 = lith->page1;
663
664 DBGEV("(chan=0x%p)\n", chan);
665
666 chan->ctlval &= ~LI_CCTL_DMA_ENABLE;
667 DBGPV("ctlreg 0x%x = 0x%lx\n", chan->desc->ctlreg, chan->ctlval);
668 li_writel(lith, chan->desc->ctlreg, chan->ctlval);
669
670
671
672
673
674
675
676
677
678
679
680
681 if (lith1 && chan->desc->direction == LI_CCFG_DIR_OUT)
682 * (volatile unsigned long *) (lith1 + 0x500) = 0;
683}
684
685
686
687
688
689
690
691static __inline__ void li_activate_dma(dma_chan_t *chan)
692{
693 chan->ctlval |= LI_CCTL_DMA_ENABLE;
694 DBGPV("ctlval = 0x%lx\n", chan->ctlval);
695 li_writel(chan->lith, chan->desc->ctlreg, chan->ctlval);
696}
697
698static void li_deactivate_dma(dma_chan_t *chan)
699{
700 lithium_t *lith = chan->lith;
701 void * lith2 = lith->page2;
702
703 chan->ctlval &= ~(LI_CCTL_DMA_ENABLE | LI_CCTL_RPTR | LI_CCTL_WPTR);
704 DBGPV("ctlval = 0x%lx\n", chan->ctlval);
705 DBGPV("ctlreg 0x%x = 0x%lx\n", chan->desc->ctlreg, chan->ctlval);
706 li_writel(lith, chan->desc->ctlreg, chan->ctlval);
707
708
709
710
711
712
713
714
715
716
717
718 if (lith2 && chan->desc->direction == LI_CCFG_DIR_OUT) {
719 * (volatile unsigned long *) (lith2 + 0x98) = 0;
720 * (volatile unsigned long *) (lith2 + 0x9C) = 0;
721 }
722}
723
724
725
726
727
728
729static __inline__ int li_read_swptr(dma_chan_t *chan)
730{
731 const unsigned long mask = chan->desc->swptrmask;
732
733 return CHUNKS_TO_BYTES(UNSHIFT_FIELD(chan->ctlval, mask));
734}
735
736static __inline__ int li_read_hwptr(dma_chan_t *chan)
737{
738 return CHUNKS_TO_BYTES(li_readb(chan->lith, chan->desc->hwptrreg));
739}
740
741static __inline__ void li_write_swptr(dma_chan_t *chan, int val)
742{
743 const unsigned long mask = chan->desc->swptrmask;
744
745 ASSERT(!(val & ~CHUNKS_TO_BYTES(0xFF)));
746 val = BYTES_TO_CHUNKS(val);
747 chan->ctlval = (chan->ctlval & ~mask) | SHIFT_FIELD(val, mask);
748 li_writeb(chan->lith, chan->desc->swptrreg, val);
749}
750
751
752
753static void li_read_USTMSC(dma_chan_t *chan, ustmsc_t *ustmsc)
754{
755 lithium_t *lith = chan->lith;
756 const dma_chan_desc_t *desc = chan->desc;
757 unsigned long now_low, now_high0, now_high1, chan_ust;
758
759 spin_lock(&lith->lock);
760 {
761
762
763
764
765
766 do {
767 now_high0 = li_readl(lith, LI_UST_HIGH);
768 now_low = li_readl(lith, LI_UST_LOW);
769
770
771
772
773
774
775
776 ustmsc->msc = li_readl(lith, desc->mscreg);
777 chan_ust = li_readl(lith, desc->ustreg);
778
779 now_high1 = li_readl(lith, LI_UST_HIGH);
780 } while (now_high0 != now_high1);
781 }
782 spin_unlock(&lith->lock);
783 ustmsc->ust = ((unsigned long long) now_high0 << 32 | chan_ust);
784}
785
786static void li_enable_interrupts(lithium_t *lith, unsigned int mask)
787{
788 DBGEV("(lith=0x%p, mask=0x%x)\n", lith, mask);
789
790
791
792 li_writel(lith, LI_INTR_STATUS, mask);
793
794
795
796 mask |= li_readl(lith, LI_INTR_MASK);
797 li_writel(lith, LI_INTR_MASK, mask);
798}
799
800static void li_disable_interrupts(lithium_t *lith, unsigned int mask)
801{
802 unsigned int keepmask;
803
804 DBGEV("(lith=0x%p, mask=0x%x)\n", lith, mask);
805
806
807
808 keepmask = li_readl(lith, LI_INTR_MASK) & ~mask;
809 li_writel(lith, LI_INTR_MASK, keepmask);
810
811
812
813 li_writel(lith, LI_INTR_STATUS, mask);
814}
815
816
817
818static unsigned int li_get_clear_intr_status(lithium_t *lith)
819{
820 unsigned int status;
821
822 status = li_readl(lith, LI_INTR_STATUS);
823 li_writel(lith, LI_INTR_STATUS, ~0);
824 return status & li_readl(lith, LI_INTR_MASK);
825}
826
827static int li_init(lithium_t *lith)
828{
829
830
831
832
833 li_writel(lith, LI_HOST_CONTROLLER, LI_HC_RESET);
834 udelay(1);
835
836
837
838
839
840 li_writel(lith, LI_HOST_CONTROLLER, LI_HC_LINK_ENABLE);
841 udelay(1);
842
843 return 0;
844}
845
846
847
848
849
850
851
852
853
854
855
856
857
858typedef struct ad1843_bitfield {
859 char reg;
860 char lo_bit;
861 char nbits;
862} ad1843_bitfield_t;
863
864static const ad1843_bitfield_t
865 ad1843_PDNO = { 0, 14, 1 },
866 ad1843_INIT = { 0, 15, 1 },
867 ad1843_RIG = { 2, 0, 4 },
868 ad1843_RMGE = { 2, 4, 1 },
869 ad1843_RSS = { 2, 5, 3 },
870 ad1843_LIG = { 2, 8, 4 },
871 ad1843_LMGE = { 2, 12, 1 },
872 ad1843_LSS = { 2, 13, 3 },
873 ad1843_RX1M = { 4, 0, 5 },
874 ad1843_RX1MM = { 4, 7, 1 },
875 ad1843_LX1M = { 4, 8, 5 },
876 ad1843_LX1MM = { 4, 15, 1 },
877 ad1843_RX2M = { 5, 0, 5 },
878 ad1843_RX2MM = { 5, 7, 1 },
879 ad1843_LX2M = { 5, 8, 5 },
880 ad1843_LX2MM = { 5, 15, 1 },
881 ad1843_RMCM = { 7, 0, 5 },
882 ad1843_RMCMM = { 7, 7, 1 },
883 ad1843_LMCM = { 7, 8, 5 },
884 ad1843_LMCMM = { 7, 15, 1 },
885 ad1843_HPOS = { 8, 4, 1 },
886 ad1843_HPOM = { 8, 5, 1 },
887 ad1843_RDA1G = { 9, 0, 6 },
888 ad1843_RDA1GM = { 9, 7, 1 },
889 ad1843_LDA1G = { 9, 8, 6 },
890 ad1843_LDA1GM = { 9, 15, 1 },
891 ad1843_RDA1AM = { 11, 7, 1 },
892 ad1843_LDA1AM = { 11, 15, 1 },
893 ad1843_ADLC = { 15, 0, 2 },
894 ad1843_ADRC = { 15, 2, 2 },
895 ad1843_DA1C = { 15, 8, 2 },
896 ad1843_C1C = { 17, 0, 16 },
897 ad1843_C2C = { 20, 0, 16 },
898 ad1843_DAADL = { 25, 4, 2 },
899 ad1843_DAADR = { 25, 6, 2 },
900 ad1843_DRSFLT = { 25, 15, 1 },
901 ad1843_ADLF = { 26, 0, 2 },
902 ad1843_ADRF = { 26, 2, 2 },
903 ad1843_ADTLK = { 26, 4, 1 },
904 ad1843_SCF = { 26, 7, 1 },
905 ad1843_DA1F = { 26, 8, 2 },
906 ad1843_DA1SM = { 26, 14, 1 },
907 ad1843_ADLEN = { 27, 0, 1 },
908 ad1843_ADREN = { 27, 1, 1 },
909 ad1843_AAMEN = { 27, 4, 1 },
910 ad1843_ANAEN = { 27, 7, 1 },
911 ad1843_DA1EN = { 27, 8, 1 },
912 ad1843_DA2EN = { 27, 9, 1 },
913 ad1843_C1EN = { 28, 11, 1 },
914 ad1843_C2EN = { 28, 12, 1 },
915 ad1843_PDNI = { 28, 15, 1 };
916
917
918
919
920
921
922
923typedef struct ad1843_gain {
924
925 int negative;
926 const ad1843_bitfield_t *lfield;
927 const ad1843_bitfield_t *rfield;
928
929} ad1843_gain_t;
930
931static const ad1843_gain_t ad1843_gain_RECLEV
932 = { 0, &ad1843_LIG, &ad1843_RIG };
933static const ad1843_gain_t ad1843_gain_LINE
934 = { 1, &ad1843_LX1M, &ad1843_RX1M };
935static const ad1843_gain_t ad1843_gain_CD
936 = { 1, &ad1843_LX2M, &ad1843_RX2M };
937static const ad1843_gain_t ad1843_gain_MIC
938 = { 1, &ad1843_LMCM, &ad1843_RMCM };
939static const ad1843_gain_t ad1843_gain_PCM
940 = { 1, &ad1843_LDA1G, &ad1843_RDA1G };
941
942
943
944static int ad1843_read_bits(lithium_t *lith, const ad1843_bitfield_t *field)
945{
946 int w = li_read_ad1843_reg(lith, field->reg);
947 int val = w >> field->lo_bit & ((1 << field->nbits) - 1);
948
949 DBGXV("ad1843_read_bits(lith=0x%p, field->{%d %d %d}) returns 0x%x\n",
950 lith, field->reg, field->lo_bit, field->nbits, val);
951
952 return val;
953}
954
955
956
957
958
959static int ad1843_write_bits(lithium_t *lith,
960 const ad1843_bitfield_t *field,
961 int newval)
962{
963 int w = li_read_ad1843_reg(lith, field->reg);
964 int mask = ((1 << field->nbits) - 1) << field->lo_bit;
965 int oldval = (w & mask) >> field->lo_bit;
966 int newbits = (newval << field->lo_bit) & mask;
967 w = (w & ~mask) | newbits;
968 (void) li_write_ad1843_reg(lith, field->reg, w);
969
970 DBGXV("ad1843_write_bits(lith=0x%p, field->{%d %d %d}, val=0x%x) "
971 "returns 0x%x\n",
972 lith, field->reg, field->lo_bit, field->nbits, newval,
973 oldval);
974
975 return oldval;
976}
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991static void ad1843_read_multi(lithium_t *lith, int argcount, ...)
992{
993 va_list ap;
994 const ad1843_bitfield_t *fp;
995 int w = 0, mask, *value, reg = -1;
996
997 va_start(ap, argcount);
998 while (--argcount >= 0) {
999 fp = va_arg(ap, const ad1843_bitfield_t *);
1000 value = va_arg(ap, int *);
1001 if (reg == -1) {
1002 reg = fp->reg;
1003 w = li_read_ad1843_reg(lith, reg);
1004 }
1005 ASSERT(reg == fp->reg);
1006 mask = (1 << fp->nbits) - 1;
1007 *value = w >> fp->lo_bit & mask;
1008 }
1009 va_end(ap);
1010}
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023static void ad1843_write_multi(lithium_t *lith, int argcount, ...)
1024{
1025 va_list ap;
1026 int reg;
1027 const ad1843_bitfield_t *fp;
1028 int value;
1029 int w, m, mask, bits;
1030
1031 mask = 0;
1032 bits = 0;
1033 reg = -1;
1034
1035 va_start(ap, argcount);
1036 while (--argcount >= 0) {
1037 fp = va_arg(ap, const ad1843_bitfield_t *);
1038 value = va_arg(ap, int);
1039 if (reg == -1)
1040 reg = fp->reg;
1041 ASSERT(fp->reg == reg);
1042 m = ((1 << fp->nbits) - 1) << fp->lo_bit;
1043 mask |= m;
1044 bits |= (value << fp->lo_bit) & m;
1045 }
1046 va_end(ap);
1047 ASSERT(!(bits & ~mask));
1048 if (~mask & 0xFFFF)
1049 w = li_read_ad1843_reg(lith, reg);
1050 else
1051 w = 0;
1052 w = (w & ~mask) | bits;
1053 (void) li_write_ad1843_reg(lith, reg, w);
1054}
1055
1056
1057
1058
1059
1060
1061static int ad1843_get_gain(lithium_t *lith, const ad1843_gain_t *gp)
1062{
1063 int lg, rg;
1064 unsigned short mask = (1 << gp->lfield->nbits) - 1;
1065
1066 ad1843_read_multi(lith, 2, gp->lfield, &lg, gp->rfield, &rg);
1067 if (gp->negative) {
1068 lg = mask - lg;
1069 rg = mask - rg;
1070 }
1071 lg = (lg * 100 + (mask >> 1)) / mask;
1072 rg = (rg * 100 + (mask >> 1)) / mask;
1073 return lg << 0 | rg << 8;
1074}
1075
1076
1077
1078
1079
1080
1081
1082
1083static int ad1843_set_gain(lithium_t *lith,
1084 const ad1843_gain_t *gp,
1085 int newval)
1086{
1087 unsigned short mask = (1 << gp->lfield->nbits) - 1;
1088
1089 int lg = newval >> 0 & 0xFF;
1090 int rg = newval >> 8;
1091 if (lg < 0 || lg > 100 || rg < 0 || rg > 100)
1092 return -EINVAL;
1093 lg = (lg * mask + (mask >> 1)) / 100;
1094 rg = (rg * mask + (mask >> 1)) / 100;
1095 if (gp->negative) {
1096 lg = mask - lg;
1097 rg = mask - rg;
1098 }
1099 ad1843_write_multi(lith, 2, gp->lfield, lg, gp->rfield, rg);
1100 return ad1843_get_gain(lith, gp);
1101}
1102
1103
1104
1105static int ad1843_get_recsrc(lithium_t *lith)
1106{
1107 int ls = ad1843_read_bits(lith, &ad1843_LSS);
1108
1109 switch (ls) {
1110 case 1:
1111 return SOUND_MASK_MIC;
1112 case 2:
1113 return SOUND_MASK_LINE;
1114 case 3:
1115 return SOUND_MASK_CD;
1116 case 6:
1117 return SOUND_MASK_PCM;
1118 default:
1119 ASSERT(0);
1120 return -1;
1121 }
1122}
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139static void ad1843_set_resample_mode(lithium_t *lith, int onoff)
1140{
1141
1142 int save_da1 = li_read_ad1843_reg(lith, 9);
1143
1144
1145 ad1843_write_multi(lith, 4,
1146 &ad1843_DA1EN, 0,
1147 &ad1843_DA2EN, 0,
1148 &ad1843_ADLEN, 0,
1149 &ad1843_ADREN, 0);
1150
1151
1152 ASSERT(onoff == 0 || onoff == 1);
1153 ad1843_write_bits(lith, &ad1843_DRSFLT, onoff);
1154
1155
1156 ad1843_write_multi(lith, 3,
1157 &ad1843_DA1EN, 1,
1158 &ad1843_ADLEN, 1,
1159 &ad1843_ADREN, 1);
1160
1161
1162 li_write_ad1843_reg(lith, 9, save_da1);
1163}
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175static int ad1843_set_recsrc(lithium_t *lith, int newsrc)
1176{
1177 int bits;
1178 int oldbits;
1179
1180 switch (newsrc) {
1181 case SOUND_MASK_PCM:
1182 bits = 6;
1183 break;
1184
1185 case SOUND_MASK_MIC:
1186 bits = 1;
1187 break;
1188
1189 case SOUND_MASK_LINE:
1190 bits = 2;
1191 break;
1192
1193 case SOUND_MASK_CD:
1194 bits = 3;
1195 break;
1196
1197 default:
1198 return -EINVAL;
1199 }
1200 oldbits = ad1843_read_bits(lith, &ad1843_LSS);
1201 if (newsrc == SOUND_MASK_PCM && oldbits != 6) {
1202 DBGP("enabling digital resample mode\n");
1203 ad1843_set_resample_mode(lith, 1);
1204 ad1843_write_multi(lith, 2,
1205 &ad1843_DAADL, 2,
1206 &ad1843_DAADR, 2);
1207 } else if (newsrc != SOUND_MASK_PCM && oldbits == 6) {
1208 DBGP("disabling digital resample mode\n");
1209 ad1843_set_resample_mode(lith, 0);
1210 ad1843_write_multi(lith, 2,
1211 &ad1843_DAADL, 0,
1212 &ad1843_DAADR, 0);
1213 }
1214 ad1843_write_multi(lith, 2, &ad1843_LSS, bits, &ad1843_RSS, bits);
1215 return newsrc;
1216}
1217
1218
1219
1220
1221
1222static int ad1843_get_outsrc(lithium_t *lith)
1223{
1224 int pcm, line, mic, cd;
1225
1226 pcm = ad1843_read_bits(lith, &ad1843_LDA1GM) ? 0 : SOUND_MASK_PCM;
1227 line = ad1843_read_bits(lith, &ad1843_LX1MM) ? 0 : SOUND_MASK_LINE;
1228 cd = ad1843_read_bits(lith, &ad1843_LX2MM) ? 0 : SOUND_MASK_CD;
1229 mic = ad1843_read_bits(lith, &ad1843_LMCMM) ? 0 : SOUND_MASK_MIC;
1230
1231 return pcm | line | cd | mic;
1232}
1233
1234
1235
1236
1237
1238
1239
1240static int ad1843_set_outsrc(lithium_t *lith, int mask)
1241{
1242 int pcm, line, mic, cd;
1243
1244 if (mask & ~(SOUND_MASK_PCM | SOUND_MASK_LINE |
1245 SOUND_MASK_CD | SOUND_MASK_MIC))
1246 return -EINVAL;
1247 pcm = (mask & SOUND_MASK_PCM) ? 0 : 1;
1248 line = (mask & SOUND_MASK_LINE) ? 0 : 1;
1249 mic = (mask & SOUND_MASK_MIC) ? 0 : 1;
1250 cd = (mask & SOUND_MASK_CD) ? 0 : 1;
1251
1252 ad1843_write_multi(lith, 2, &ad1843_LDA1GM, pcm, &ad1843_RDA1GM, pcm);
1253 ad1843_write_multi(lith, 2, &ad1843_LX1MM, line, &ad1843_RX1MM, line);
1254 ad1843_write_multi(lith, 2, &ad1843_LX2MM, cd, &ad1843_RX2MM, cd);
1255 ad1843_write_multi(lith, 2, &ad1843_LMCMM, mic, &ad1843_RMCMM, mic);
1256
1257 return mask;
1258}
1259
1260
1261
1262static void ad1843_setup_dac(lithium_t *lith,
1263 int framerate,
1264 int fmt,
1265 int channels)
1266{
1267 int ad_fmt = 0, ad_mode = 0;
1268
1269 DBGEV("(lith=0x%p, framerate=%d, fmt=%d, channels=%d)\n",
1270 lith, framerate, fmt, channels);
1271
1272 switch (fmt) {
1273 case AFMT_S8: ad_fmt = 1; break;
1274 case AFMT_U8: ad_fmt = 1; break;
1275 case AFMT_S16_LE: ad_fmt = 1; break;
1276 case AFMT_MU_LAW: ad_fmt = 2; break;
1277 case AFMT_A_LAW: ad_fmt = 3; break;
1278 default: ASSERT(0);
1279 }
1280
1281 switch (channels) {
1282 case 2: ad_mode = 0; break;
1283 case 1: ad_mode = 1; break;
1284 default: ASSERT(0);
1285 }
1286
1287 DBGPV("ad_mode = %d, ad_fmt = %d\n", ad_mode, ad_fmt);
1288 ASSERT(framerate >= 4000 && framerate <= 49000);
1289 ad1843_write_bits(lith, &ad1843_C1C, framerate);
1290 ad1843_write_multi(lith, 2,
1291 &ad1843_DA1SM, ad_mode, &ad1843_DA1F, ad_fmt);
1292}
1293
1294static void ad1843_shutdown_dac(lithium_t *lith)
1295{
1296 ad1843_write_bits(lith, &ad1843_DA1F, 1);
1297}
1298
1299static void ad1843_setup_adc(lithium_t *lith, int framerate, int fmt, int channels)
1300{
1301 int da_fmt = 0;
1302
1303 DBGEV("(lith=0x%p, framerate=%d, fmt=%d, channels=%d)\n",
1304 lith, framerate, fmt, channels);
1305
1306 switch (fmt) {
1307 case AFMT_S8: da_fmt = 1; break;
1308 case AFMT_U8: da_fmt = 1; break;
1309 case AFMT_S16_LE: da_fmt = 1; break;
1310 case AFMT_MU_LAW: da_fmt = 2; break;
1311 case AFMT_A_LAW: da_fmt = 3; break;
1312 default: ASSERT(0);
1313 }
1314
1315 DBGPV("da_fmt = %d\n", da_fmt);
1316 ASSERT(framerate >= 4000 && framerate <= 49000);
1317 ad1843_write_bits(lith, &ad1843_C2C, framerate);
1318 ad1843_write_multi(lith, 2,
1319 &ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt);
1320}
1321
1322static void ad1843_shutdown_adc(lithium_t *lith)
1323{
1324
1325}
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335static int __init ad1843_init(lithium_t *lith)
1336{
1337 unsigned long later;
1338 int err;
1339
1340 err = li_init(lith);
1341 if (err)
1342 return err;
1343
1344 if (ad1843_read_bits(lith, &ad1843_INIT) != 0) {
1345 printk(KERN_ERR "vwsnd sound: AD1843 won't initialize\n");
1346 return -EIO;
1347 }
1348
1349 ad1843_write_bits(lith, &ad1843_SCF, 1);
1350
1351
1352
1353 ad1843_write_bits(lith, &ad1843_PDNI, 0);
1354 later = jiffies + HZ / 2;
1355 DBGDO(shut_up++);
1356 while (ad1843_read_bits(lith, &ad1843_PDNO)) {
1357 if (time_after(jiffies, later)) {
1358 printk(KERN_ERR
1359 "vwsnd audio: AD1843 won't power up\n");
1360 return -EIO;
1361 }
1362 schedule();
1363 }
1364 DBGDO(shut_up--);
1365
1366
1367
1368 ad1843_write_multi(lith, 2, &ad1843_C1EN, 1, &ad1843_C2EN, 1);
1369
1370
1371
1372
1373
1374 ad1843_write_multi(lith, 3,
1375 &ad1843_DA1C, 1,
1376 &ad1843_ADLC, 2,
1377 &ad1843_ADRC, 2);
1378
1379
1380
1381 ad1843_write_bits(lith, &ad1843_ADTLK, 1);
1382 ad1843_write_multi(lith, 5,
1383 &ad1843_ANAEN, 1,
1384 &ad1843_AAMEN, 1,
1385 &ad1843_DA1EN, 1,
1386 &ad1843_ADLEN, 1,
1387 &ad1843_ADREN, 1);
1388
1389
1390
1391 ad1843_write_bits(lith, &ad1843_DA1C, 1);
1392
1393
1394
1395 ad1843_set_outsrc(lith,
1396 (SOUND_MASK_PCM | SOUND_MASK_LINE |
1397 SOUND_MASK_MIC | SOUND_MASK_CD));
1398 ad1843_write_multi(lith, 2, &ad1843_LDA1AM, 0, &ad1843_RDA1AM, 0);
1399
1400
1401
1402
1403
1404 ad1843_set_recsrc(lith, SOUND_MASK_LINE);
1405 ad1843_write_multi(lith, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1);
1406
1407
1408
1409 ad1843_write_multi(lith, 2, &ad1843_HPOS, 1, &ad1843_HPOM, 0);
1410
1411 return 0;
1412}
1413
1414
1415
1416
1417#define READ_INTR_MASK (LI_INTR_COMM1_TRIG | LI_INTR_COMM1_OVERFLOW)
1418#define WRITE_INTR_MASK (LI_INTR_COMM2_TRIG | LI_INTR_COMM2_UNDERFLOW)
1419
1420typedef enum vwsnd_port_swstate {
1421 SW_OFF,
1422 SW_INITIAL,
1423 SW_RUN,
1424 SW_DRAIN,
1425} vwsnd_port_swstate_t;
1426
1427typedef enum vwsnd_port_hwstate {
1428 HW_STOPPED,
1429 HW_RUNNING,
1430} vwsnd_port_hwstate_t;
1431
1432
1433
1434
1435
1436typedef enum vwsnd_port_flags {
1437 DISABLED = 1 << 0,
1438 ERFLOWN = 1 << 1,
1439 HW_BUSY = 1 << 2,
1440} vwsnd_port_flags_t;
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457typedef struct vwsnd_port {
1458
1459 spinlock_t lock;
1460 wait_queue_head_t queue;
1461 vwsnd_port_swstate_t swstate;
1462 vwsnd_port_hwstate_t hwstate;
1463 vwsnd_port_flags_t flags;
1464
1465 int sw_channels;
1466 int sw_samplefmt;
1467 int sw_framerate;
1468 int sample_size;
1469 int frame_size;
1470 unsigned int zero_word;
1471
1472 int sw_fragshift;
1473 int sw_fragcount;
1474 int sw_subdivshift;
1475
1476 unsigned int hw_fragshift;
1477 unsigned int hw_fragsize;
1478 unsigned int hw_fragcount;
1479
1480 int hwbuf_size;
1481 unsigned long hwbuf_paddr;
1482 unsigned long hwbuf_vaddr;
1483 void * hwbuf;
1484 int hwbuf_max;
1485
1486 void * swbuf;
1487 unsigned int swbuf_size;
1488 unsigned int swb_u_idx;
1489 unsigned int swb_i_idx;
1490 unsigned int swb_u_avail;
1491 unsigned int swb_i_avail;
1492
1493 dma_chan_t chan;
1494
1495
1496
1497 int byte_count;
1498 int frag_count;
1499 int MSC_offset;
1500
1501} vwsnd_port_t;
1502
1503
1504
1505typedef struct vwsnd_dev {
1506 struct vwsnd_dev *next_dev;
1507 int audio_minor;
1508 int mixer_minor;
1509
1510 struct mutex open_mutex;
1511 struct mutex io_mutex;
1512 struct mutex mix_mutex;
1513 fmode_t open_mode;
1514 wait_queue_head_t open_wait;
1515
1516 lithium_t lith;
1517
1518 vwsnd_port_t rport;
1519 vwsnd_port_t wport;
1520} vwsnd_dev_t;
1521
1522static vwsnd_dev_t *vwsnd_dev_list;
1523
1524static atomic_t vwsnd_use_count = ATOMIC_INIT(0);
1525
1526# define INC_USE_COUNT (atomic_inc(&vwsnd_use_count))
1527# define DEC_USE_COUNT (atomic_dec(&vwsnd_use_count))
1528# define IN_USE (atomic_read(&vwsnd_use_count) != 0)
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543#define HWBUF_SHIFT 13
1544#define HWBUF_SIZE (1 << HWBUF_SHIFT)
1545# define HBO (HWBUF_SHIFT > PAGE_SHIFT ? HWBUF_SHIFT - PAGE_SHIFT : 0)
1546# define HWBUF_ORDER (HBO + 1)
1547#define MIN_SPEED 4000
1548#define MAX_SPEED 49000
1549
1550#define MIN_FRAGSHIFT (DMACHUNK_SHIFT + 1)
1551#define MAX_FRAGSHIFT (PAGE_SHIFT)
1552#define MIN_FRAGSIZE (1 << MIN_FRAGSHIFT)
1553#define MAX_FRAGSIZE (1 << MAX_FRAGSHIFT)
1554#define MIN_FRAGCOUNT(fragsize) 3
1555#define MAX_FRAGCOUNT(fragsize) (32 * PAGE_SIZE / (fragsize))
1556#define DEFAULT_FRAGSHIFT 12
1557#define DEFAULT_FRAGCOUNT 16
1558#define DEFAULT_SUBDIVSHIFT 0
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583static __inline__ unsigned int __swb_inc_u(vwsnd_port_t *port, int inc)
1584{
1585 if (inc) {
1586 port->swb_u_idx += inc;
1587 port->swb_u_idx %= port->swbuf_size;
1588 port->swb_u_avail -= inc;
1589 port->swb_i_avail += inc;
1590 }
1591 return port->swb_u_avail;
1592}
1593
1594static __inline__ unsigned int swb_inc_u(vwsnd_port_t *port, int inc)
1595{
1596 unsigned long flags;
1597 unsigned int ret;
1598
1599 spin_lock_irqsave(&port->lock, flags);
1600 {
1601 ret = __swb_inc_u(port, inc);
1602 }
1603 spin_unlock_irqrestore(&port->lock, flags);
1604 return ret;
1605}
1606
1607static __inline__ unsigned int __swb_inc_i(vwsnd_port_t *port, int inc)
1608{
1609 if (inc) {
1610 port->swb_i_idx += inc;
1611 port->swb_i_idx %= port->swbuf_size;
1612 port->swb_i_avail -= inc;
1613 port->swb_u_avail += inc;
1614 }
1615 return port->swb_i_avail;
1616}
1617
1618static __inline__ unsigned int swb_inc_i(vwsnd_port_t *port, int inc)
1619{
1620 unsigned long flags;
1621 unsigned int ret;
1622
1623 spin_lock_irqsave(&port->lock, flags);
1624 {
1625 ret = __swb_inc_i(port, inc);
1626 }
1627 spin_unlock_irqrestore(&port->lock, flags);
1628 return ret;
1629}
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641static int pcm_setup(vwsnd_dev_t *devc,
1642 vwsnd_port_t *rport,
1643 vwsnd_port_t *wport)
1644{
1645 vwsnd_port_t *aport = rport ? rport : wport;
1646 int sample_size;
1647 unsigned int zero_word;
1648
1649 DBGEV("(devc=0x%p, rport=0x%p, wport=0x%p)\n", devc, rport, wport);
1650
1651 ASSERT(aport != NULL);
1652 if (aport->swbuf != NULL)
1653 return 0;
1654 switch (aport->sw_samplefmt) {
1655 case AFMT_MU_LAW:
1656 sample_size = 1;
1657 zero_word = 0xFFFFFFFF ^ 0x80808080;
1658 break;
1659
1660 case AFMT_A_LAW:
1661 sample_size = 1;
1662 zero_word = 0xD5D5D5D5 ^ 0x80808080;
1663 break;
1664
1665 case AFMT_U8:
1666 sample_size = 1;
1667 zero_word = 0x80808080;
1668 break;
1669
1670 case AFMT_S8:
1671 sample_size = 1;
1672 zero_word = 0x00000000;
1673 break;
1674
1675 case AFMT_S16_LE:
1676 sample_size = 2;
1677 zero_word = 0x00000000;
1678 break;
1679
1680 default:
1681 sample_size = 0;
1682 zero_word = 0;
1683 ASSERT(0);
1684 }
1685 aport->sample_size = sample_size;
1686 aport->zero_word = zero_word;
1687 aport->frame_size = aport->sw_channels * aport->sample_size;
1688 aport->hw_fragshift = aport->sw_fragshift - aport->sw_subdivshift;
1689 aport->hw_fragsize = 1 << aport->hw_fragshift;
1690 aport->hw_fragcount = aport->sw_fragcount << aport->sw_subdivshift;
1691 ASSERT(aport->hw_fragsize >= MIN_FRAGSIZE);
1692 ASSERT(aport->hw_fragsize <= MAX_FRAGSIZE);
1693 ASSERT(aport->hw_fragcount >= MIN_FRAGCOUNT(aport->hw_fragsize));
1694 ASSERT(aport->hw_fragcount <= MAX_FRAGCOUNT(aport->hw_fragsize));
1695 if (rport) {
1696 int hwfrags, swfrags;
1697 rport->hwbuf_max = aport->hwbuf_size - DMACHUNK_SIZE;
1698 hwfrags = rport->hwbuf_max >> aport->hw_fragshift;
1699 swfrags = aport->hw_fragcount - hwfrags;
1700 if (swfrags < 2)
1701 swfrags = 2;
1702 rport->swbuf_size = swfrags * aport->hw_fragsize;
1703 DBGPV("hwfrags = %d, swfrags = %d\n", hwfrags, swfrags);
1704 DBGPV("read hwbuf_max = %d, swbuf_size = %d\n",
1705 rport->hwbuf_max, rport->swbuf_size);
1706 }
1707 if (wport) {
1708 int hwfrags, swfrags;
1709 int total_bytes = aport->hw_fragcount * aport->hw_fragsize;
1710 wport->hwbuf_max = aport->hwbuf_size - DMACHUNK_SIZE;
1711 if (wport->hwbuf_max > total_bytes)
1712 wport->hwbuf_max = total_bytes;
1713 hwfrags = wport->hwbuf_max >> aport->hw_fragshift;
1714 DBGPV("hwfrags = %d\n", hwfrags);
1715 swfrags = aport->hw_fragcount - hwfrags;
1716 if (swfrags < 2)
1717 swfrags = 2;
1718 wport->swbuf_size = swfrags * aport->hw_fragsize;
1719 DBGPV("hwfrags = %d, swfrags = %d\n", hwfrags, swfrags);
1720 DBGPV("write hwbuf_max = %d, swbuf_size = %d\n",
1721 wport->hwbuf_max, wport->swbuf_size);
1722 }
1723
1724 aport->swb_u_idx = 0;
1725 aport->swb_i_idx = 0;
1726 aport->byte_count = 0;
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737 aport->swbuf = vmalloc(aport->swbuf_size + PAGE_SIZE);
1738 if (!aport->swbuf)
1739 return -ENOMEM;
1740 if (rport && wport) {
1741 ASSERT(aport == rport);
1742 ASSERT(wport->swbuf == NULL);
1743
1744 wport->swbuf = vmalloc(aport->swbuf_size + PAGE_SIZE);
1745 if (!wport->swbuf) {
1746 vfree(aport->swbuf);
1747 aport->swbuf = NULL;
1748 return -ENOMEM;
1749 }
1750 wport->sample_size = rport->sample_size;
1751 wport->zero_word = rport->zero_word;
1752 wport->frame_size = rport->frame_size;
1753 wport->hw_fragshift = rport->hw_fragshift;
1754 wport->hw_fragsize = rport->hw_fragsize;
1755 wport->hw_fragcount = rport->hw_fragcount;
1756 wport->swbuf_size = rport->swbuf_size;
1757 wport->hwbuf_max = rport->hwbuf_max;
1758 wport->swb_u_idx = rport->swb_u_idx;
1759 wport->swb_i_idx = rport->swb_i_idx;
1760 wport->byte_count = rport->byte_count;
1761 }
1762 if (rport) {
1763 rport->swb_u_avail = 0;
1764 rport->swb_i_avail = rport->swbuf_size;
1765 rport->swstate = SW_RUN;
1766 li_setup_dma(&rport->chan,
1767 &li_comm1,
1768 &devc->lith,
1769 rport->hwbuf_paddr,
1770 HWBUF_SHIFT,
1771 rport->hw_fragshift,
1772 rport->sw_channels,
1773 rport->sample_size);
1774 ad1843_setup_adc(&devc->lith,
1775 rport->sw_framerate,
1776 rport->sw_samplefmt,
1777 rport->sw_channels);
1778 li_enable_interrupts(&devc->lith, READ_INTR_MASK);
1779 if (!(rport->flags & DISABLED)) {
1780 ustmsc_t ustmsc;
1781 rport->hwstate = HW_RUNNING;
1782 li_activate_dma(&rport->chan);
1783 li_read_USTMSC(&rport->chan, &ustmsc);
1784 rport->MSC_offset = ustmsc.msc;
1785 }
1786 }
1787 if (wport) {
1788 if (wport->hwbuf_max > wport->swbuf_size)
1789 wport->hwbuf_max = wport->swbuf_size;
1790 wport->flags &= ~ERFLOWN;
1791 wport->swb_u_avail = wport->swbuf_size;
1792 wport->swb_i_avail = 0;
1793 wport->swstate = SW_RUN;
1794 li_setup_dma(&wport->chan,
1795 &li_comm2,
1796 &devc->lith,
1797 wport->hwbuf_paddr,
1798 HWBUF_SHIFT,
1799 wport->hw_fragshift,
1800 wport->sw_channels,
1801 wport->sample_size);
1802 ad1843_setup_dac(&devc->lith,
1803 wport->sw_framerate,
1804 wport->sw_samplefmt,
1805 wport->sw_channels);
1806 li_enable_interrupts(&devc->lith, WRITE_INTR_MASK);
1807 }
1808 DBGRV();
1809 return 0;
1810}
1811
1812
1813
1814
1815
1816
1817static void pcm_shutdown_port(vwsnd_dev_t *devc,
1818 vwsnd_port_t *aport,
1819 unsigned int mask)
1820{
1821 unsigned long flags;
1822 vwsnd_port_hwstate_t hwstate;
1823 DECLARE_WAITQUEUE(wait, current);
1824
1825 aport->swstate = SW_INITIAL;
1826 add_wait_queue(&aport->queue, &wait);
1827 while (1) {
1828 set_current_state(TASK_UNINTERRUPTIBLE);
1829 spin_lock_irqsave(&aport->lock, flags);
1830 {
1831 hwstate = aport->hwstate;
1832 }
1833 spin_unlock_irqrestore(&aport->lock, flags);
1834 if (hwstate == HW_STOPPED)
1835 break;
1836 schedule();
1837 }
1838 current->state = TASK_RUNNING;
1839 remove_wait_queue(&aport->queue, &wait);
1840 li_disable_interrupts(&devc->lith, mask);
1841 if (aport == &devc->rport)
1842 ad1843_shutdown_adc(&devc->lith);
1843 else
1844 ad1843_shutdown_dac(&devc->lith);
1845 li_shutdown_dma(&aport->chan);
1846 vfree(aport->swbuf);
1847 aport->swbuf = NULL;
1848 aport->byte_count = 0;
1849}
1850
1851
1852
1853
1854
1855
1856static void pcm_shutdown(vwsnd_dev_t *devc,
1857 vwsnd_port_t *rport,
1858 vwsnd_port_t *wport)
1859{
1860 DBGEV("(devc=0x%p, rport=0x%p, wport=0x%p)\n", devc, rport, wport);
1861
1862 if (rport && rport->swbuf) {
1863 DBGPV("shutting down rport\n");
1864 pcm_shutdown_port(devc, rport, READ_INTR_MASK);
1865 }
1866 if (wport && wport->swbuf) {
1867 DBGPV("shutting down wport\n");
1868 pcm_shutdown_port(devc, wport, WRITE_INTR_MASK);
1869 }
1870 DBGRV();
1871}
1872
1873static void pcm_copy_in(vwsnd_port_t *rport, int swidx, int hwidx, int nb)
1874{
1875 char *src = rport->hwbuf + hwidx;
1876 char *dst = rport->swbuf + swidx;
1877 int fmt = rport->sw_samplefmt;
1878
1879 DBGPV("swidx = %d, hwidx = %d\n", swidx, hwidx);
1880 ASSERT(rport->hwbuf != NULL);
1881 ASSERT(rport->swbuf != NULL);
1882 ASSERT(nb > 0 && (nb % 32) == 0);
1883 ASSERT(swidx % 32 == 0 && hwidx % 32 == 0);
1884 ASSERT(swidx >= 0 && swidx + nb <= rport->swbuf_size);
1885 ASSERT(hwidx >= 0 && hwidx + nb <= rport->hwbuf_size);
1886
1887 if (fmt == AFMT_MU_LAW || fmt == AFMT_A_LAW || fmt == AFMT_S8) {
1888
1889
1890
1891 char *end = src + nb;
1892 while (src < end)
1893 *dst++ = *src++ ^ 0x80;
1894 } else
1895 memcpy(dst, src, nb);
1896}
1897
1898static void pcm_copy_out(vwsnd_port_t *wport, int swidx, int hwidx, int nb)
1899{
1900 char *src = wport->swbuf + swidx;
1901 char *dst = wport->hwbuf + hwidx;
1902 int fmt = wport->sw_samplefmt;
1903
1904 ASSERT(nb > 0 && (nb % 32) == 0);
1905 ASSERT(wport->hwbuf != NULL);
1906 ASSERT(wport->swbuf != NULL);
1907 ASSERT(swidx % 32 == 0 && hwidx % 32 == 0);
1908 ASSERT(swidx >= 0 && swidx + nb <= wport->swbuf_size);
1909 ASSERT(hwidx >= 0 && hwidx + nb <= wport->hwbuf_size);
1910 if (fmt == AFMT_MU_LAW || fmt == AFMT_A_LAW || fmt == AFMT_S8) {
1911
1912
1913
1914 char *end = src + nb;
1915 while (src < end)
1916 *dst++ = *src++ ^ 0x80;
1917 } else
1918 memcpy(dst, src, nb);
1919}
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940static void pcm_output(vwsnd_dev_t *devc, int erflown, int nb)
1941{
1942 vwsnd_port_t *wport = &devc->wport;
1943 const int hwmax = wport->hwbuf_max;
1944 const int hwsize = wport->hwbuf_size;
1945 const int swsize = wport->swbuf_size;
1946 const int fragsize = wport->hw_fragsize;
1947 unsigned long iflags;
1948
1949 DBGEV("(devc=0x%p, erflown=%d, nb=%d)\n", devc, erflown, nb);
1950 spin_lock_irqsave(&wport->lock, iflags);
1951 if (erflown)
1952 wport->flags |= ERFLOWN;
1953 (void) __swb_inc_u(wport, nb);
1954 if (wport->flags & HW_BUSY) {
1955 spin_unlock_irqrestore(&wport->lock, iflags);
1956 DBGPV("returning: HW BUSY\n");
1957 return;
1958 }
1959 if (wport->flags & DISABLED) {
1960 spin_unlock_irqrestore(&wport->lock, iflags);
1961 DBGPV("returning: DISABLED\n");
1962 return;
1963 }
1964 wport->flags |= HW_BUSY;
1965 while (1) {
1966 int swptr, hwptr, hw_avail, sw_avail, swidx;
1967 vwsnd_port_hwstate_t hwstate = wport->hwstate;
1968 vwsnd_port_swstate_t swstate = wport->swstate;
1969 int hw_unavail;
1970 ustmsc_t ustmsc;
1971
1972 hwptr = li_read_hwptr(&wport->chan);
1973 swptr = li_read_swptr(&wport->chan);
1974 hw_unavail = (swptr - hwptr + hwsize) % hwsize;
1975 hw_avail = (hwmax - hw_unavail) & -fragsize;
1976 sw_avail = wport->swb_i_avail & -fragsize;
1977 if (sw_avail && swstate == SW_RUN) {
1978 if (wport->flags & ERFLOWN) {
1979 wport->flags &= ~ERFLOWN;
1980 }
1981 } else if (swstate == SW_INITIAL ||
1982 swstate == SW_OFF ||
1983 (swstate == SW_DRAIN &&
1984 !sw_avail &&
1985 (wport->flags & ERFLOWN))) {
1986 DBGP("stopping. hwstate = %d\n", hwstate);
1987 if (hwstate != HW_STOPPED) {
1988 li_deactivate_dma(&wport->chan);
1989 wport->hwstate = HW_STOPPED;
1990 }
1991 wake_up(&wport->queue);
1992 break;
1993 }
1994 if (!sw_avail || !hw_avail)
1995 break;
1996 spin_unlock_irqrestore(&wport->lock, iflags);
1997
1998
1999
2000
2001
2002
2003
2004 swidx = wport->swb_i_idx;
2005 nb = hw_avail;
2006 if (nb > sw_avail)
2007 nb = sw_avail;
2008 if (nb > hwsize - swptr)
2009 nb = hwsize - swptr;
2010 if (nb > swsize - swidx)
2011 nb = swsize - swidx;
2012 ASSERT(nb > 0);
2013 if (nb % fragsize) {
2014 DBGP("nb = %d, fragsize = %d\n", nb, fragsize);
2015 DBGP("hw_avail = %d\n", hw_avail);
2016 DBGP("sw_avail = %d\n", sw_avail);
2017 DBGP("hwsize = %d, swptr = %d\n", hwsize, swptr);
2018 DBGP("swsize = %d, swidx = %d\n", swsize, swidx);
2019 }
2020 ASSERT(!(nb % fragsize));
2021 DBGPV("copying swb[%d..%d] to hwb[%d..%d]\n",
2022 swidx, swidx + nb, swptr, swptr + nb);
2023 pcm_copy_out(wport, swidx, swptr, nb);
2024 li_write_swptr(&wport->chan, (swptr + nb) % hwsize);
2025 spin_lock_irqsave(&wport->lock, iflags);
2026 if (hwstate == HW_STOPPED) {
2027 DBGPV("starting\n");
2028 li_activate_dma(&wport->chan);
2029 wport->hwstate = HW_RUNNING;
2030 li_read_USTMSC(&wport->chan, &ustmsc);
2031 ASSERT(wport->byte_count % wport->frame_size == 0);
2032 wport->MSC_offset = ustmsc.msc - wport->byte_count / wport->frame_size;
2033 }
2034 __swb_inc_i(wport, nb);
2035 wport->byte_count += nb;
2036 wport->frag_count += nb / fragsize;
2037 ASSERT(nb % fragsize == 0);
2038 wake_up(&wport->queue);
2039 }
2040 wport->flags &= ~HW_BUSY;
2041 spin_unlock_irqrestore(&wport->lock, iflags);
2042 DBGRV();
2043}
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064static void pcm_input(vwsnd_dev_t *devc, int erflown, int nb)
2065{
2066 vwsnd_port_t *rport = &devc->rport;
2067 const int hwmax = rport->hwbuf_max;
2068 const int hwsize = rport->hwbuf_size;
2069 const int swsize = rport->swbuf_size;
2070 const int fragsize = rport->hw_fragsize;
2071 unsigned long iflags;
2072
2073 DBGEV("(devc=0x%p, erflown=%d, nb=%d)\n", devc, erflown, nb);
2074
2075 spin_lock_irqsave(&rport->lock, iflags);
2076 if (erflown)
2077 rport->flags |= ERFLOWN;
2078 (void) __swb_inc_u(rport, nb);
2079 if (rport->flags & HW_BUSY || !rport->swbuf) {
2080 spin_unlock_irqrestore(&rport->lock, iflags);
2081 DBGPV("returning: HW BUSY or !swbuf\n");
2082 return;
2083 }
2084 if (rport->flags & DISABLED) {
2085 spin_unlock_irqrestore(&rport->lock, iflags);
2086 DBGPV("returning: DISABLED\n");
2087 return;
2088 }
2089 rport->flags |= HW_BUSY;
2090 while (1) {
2091 int swptr, hwptr, hw_avail, sw_avail, swidx;
2092 vwsnd_port_hwstate_t hwstate = rport->hwstate;
2093 vwsnd_port_swstate_t swstate = rport->swstate;
2094
2095 hwptr = li_read_hwptr(&rport->chan);
2096 swptr = li_read_swptr(&rport->chan);
2097 hw_avail = (hwptr - swptr + hwsize) % hwsize & -fragsize;
2098 if (hw_avail > hwmax)
2099 hw_avail = hwmax;
2100 sw_avail = rport->swb_i_avail & -fragsize;
2101 if (swstate != SW_RUN) {
2102 DBGP("stopping. hwstate = %d\n", hwstate);
2103 if (hwstate != HW_STOPPED) {
2104 li_deactivate_dma(&rport->chan);
2105 rport->hwstate = HW_STOPPED;
2106 }
2107 wake_up(&rport->queue);
2108 break;
2109 }
2110 if (!sw_avail || !hw_avail)
2111 break;
2112 spin_unlock_irqrestore(&rport->lock, iflags);
2113
2114
2115
2116
2117
2118
2119
2120 swidx = rport->swb_i_idx;
2121 nb = hw_avail;
2122 if (nb > sw_avail)
2123 nb = sw_avail;
2124 if (nb > hwsize - swptr)
2125 nb = hwsize - swptr;
2126 if (nb > swsize - swidx)
2127 nb = swsize - swidx;
2128 ASSERT(nb > 0);
2129 if (nb % fragsize) {
2130 DBGP("nb = %d, fragsize = %d\n", nb, fragsize);
2131 DBGP("hw_avail = %d\n", hw_avail);
2132 DBGP("sw_avail = %d\n", sw_avail);
2133 DBGP("hwsize = %d, swptr = %d\n", hwsize, swptr);
2134 DBGP("swsize = %d, swidx = %d\n", swsize, swidx);
2135 }
2136 ASSERT(!(nb % fragsize));
2137 DBGPV("copying hwb[%d..%d] to swb[%d..%d]\n",
2138 swptr, swptr + nb, swidx, swidx + nb);
2139 pcm_copy_in(rport, swidx, swptr, nb);
2140 li_write_swptr(&rport->chan, (swptr + nb) % hwsize);
2141 spin_lock_irqsave(&rport->lock, iflags);
2142 __swb_inc_i(rport, nb);
2143 rport->byte_count += nb;
2144 rport->frag_count += nb / fragsize;
2145 ASSERT(nb % fragsize == 0);
2146 wake_up(&rport->queue);
2147 }
2148 rport->flags &= ~HW_BUSY;
2149 spin_unlock_irqrestore(&rport->lock, iflags);
2150 DBGRV();
2151}
2152
2153
2154
2155
2156
2157
2158
2159
2160static void pcm_flush_frag(vwsnd_dev_t *devc)
2161{
2162 vwsnd_port_t *wport = &devc->wport;
2163
2164 DBGPV("swstate = %d\n", wport->swstate);
2165 if (wport->swstate == SW_RUN) {
2166 int idx = wport->swb_u_idx;
2167 int end = (idx + wport->hw_fragsize - 1)
2168 >> wport->hw_fragshift
2169 << wport->hw_fragshift;
2170 int nb = end - idx;
2171 DBGPV("clearing %d bytes\n", nb);
2172 if (nb)
2173 memset(wport->swbuf + idx,
2174 (char) wport->zero_word,
2175 nb);
2176 wport->swstate = SW_DRAIN;
2177 pcm_output(devc, 0, nb);
2178 }
2179 DBGRV();
2180}
2181
2182
2183
2184
2185
2186
2187
2188static void pcm_write_sync(vwsnd_dev_t *devc)
2189{
2190 vwsnd_port_t *wport = &devc->wport;
2191 DECLARE_WAITQUEUE(wait, current);
2192 unsigned long flags;
2193 vwsnd_port_hwstate_t hwstate;
2194
2195 DBGEV("(devc=0x%p)\n", devc);
2196 add_wait_queue(&wport->queue, &wait);
2197 while (1) {
2198 set_current_state(TASK_UNINTERRUPTIBLE);
2199 spin_lock_irqsave(&wport->lock, flags);
2200 {
2201 hwstate = wport->hwstate;
2202 }
2203 spin_unlock_irqrestore(&wport->lock, flags);
2204 if (hwstate == HW_STOPPED)
2205 break;
2206 schedule();
2207 }
2208 current->state = TASK_RUNNING;
2209 remove_wait_queue(&wport->queue, &wait);
2210 DBGPV("swstate = %d, hwstate = %d\n", wport->swstate, wport->hwstate);
2211 DBGRV();
2212}
2213
2214
2215
2216
2217
2218
2219
2220
2221static void vwsnd_audio_read_intr(vwsnd_dev_t *devc, unsigned int status)
2222{
2223 int overflown = status & LI_INTR_COMM1_OVERFLOW;
2224
2225 if (status & READ_INTR_MASK)
2226 pcm_input(devc, overflown, 0);
2227}
2228
2229static void vwsnd_audio_write_intr(vwsnd_dev_t *devc, unsigned int status)
2230{
2231 int underflown = status & LI_INTR_COMM2_UNDERFLOW;
2232
2233 if (status & WRITE_INTR_MASK)
2234 pcm_output(devc, underflown, 0);
2235}
2236
2237static irqreturn_t vwsnd_audio_intr(int irq, void *dev_id)
2238{
2239 vwsnd_dev_t *devc = dev_id;
2240 unsigned int status;
2241
2242 DBGEV("(irq=%d, dev_id=0x%p)\n", irq, dev_id);
2243
2244 status = li_get_clear_intr_status(&devc->lith);
2245 vwsnd_audio_read_intr(devc, status);
2246 vwsnd_audio_write_intr(devc, status);
2247 return IRQ_HANDLED;
2248}
2249
2250static ssize_t vwsnd_audio_do_read(struct file *file,
2251 char *buffer,
2252 size_t count,
2253 loff_t *ppos)
2254{
2255 vwsnd_dev_t *devc = file->private_data;
2256 vwsnd_port_t *rport = ((file->f_mode & FMODE_READ) ?
2257 &devc->rport : NULL);
2258 int ret, nb;
2259
2260 DBGEV("(file=0x%p, buffer=0x%p, count=%d, ppos=0x%p)\n",
2261 file, buffer, count, ppos);
2262
2263 if (!rport)
2264 return -EINVAL;
2265
2266 if (rport->swbuf == NULL) {
2267 vwsnd_port_t *wport = (file->f_mode & FMODE_WRITE) ?
2268 &devc->wport : NULL;
2269 ret = pcm_setup(devc, rport, wport);
2270 if (ret < 0)
2271 return ret;
2272 }
2273
2274 if (!access_ok(VERIFY_READ, buffer, count))
2275 return -EFAULT;
2276 ret = 0;
2277 while (count) {
2278 DECLARE_WAITQUEUE(wait, current);
2279 add_wait_queue(&rport->queue, &wait);
2280 while ((nb = swb_inc_u(rport, 0)) == 0) {
2281 DBGPV("blocking\n");
2282 set_current_state(TASK_INTERRUPTIBLE);
2283 if (rport->flags & DISABLED ||
2284 file->f_flags & O_NONBLOCK) {
2285 current->state = TASK_RUNNING;
2286 remove_wait_queue(&rport->queue, &wait);
2287 return ret ? ret : -EAGAIN;
2288 }
2289 schedule();
2290 if (signal_pending(current)) {
2291 current->state = TASK_RUNNING;
2292 remove_wait_queue(&rport->queue, &wait);
2293 return ret ? ret : -ERESTARTSYS;
2294 }
2295 }
2296 current->state = TASK_RUNNING;
2297 remove_wait_queue(&rport->queue, &wait);
2298 pcm_input(devc, 0, 0);
2299
2300 if (nb > count)
2301 nb = count;
2302 DBGPV("nb = %d\n", nb);
2303 if (copy_to_user(buffer, rport->swbuf + rport->swb_u_idx, nb))
2304 return -EFAULT;
2305 (void) swb_inc_u(rport, nb);
2306 buffer += nb;
2307 count -= nb;
2308 ret += nb;
2309 }
2310 DBGPV("returning %d\n", ret);
2311 return ret;
2312}
2313
2314static ssize_t vwsnd_audio_read(struct file *file,
2315 char *buffer,
2316 size_t count,
2317 loff_t *ppos)
2318{
2319 vwsnd_dev_t *devc = file->private_data;
2320 ssize_t ret;
2321
2322 mutex_lock(&devc->io_mutex);
2323 ret = vwsnd_audio_do_read(file, buffer, count, ppos);
2324 mutex_unlock(&devc->io_mutex);
2325 return ret;
2326}
2327
2328static ssize_t vwsnd_audio_do_write(struct file *file,
2329 const char *buffer,
2330 size_t count,
2331 loff_t *ppos)
2332{
2333 vwsnd_dev_t *devc = file->private_data;
2334 vwsnd_port_t *wport = ((file->f_mode & FMODE_WRITE) ?
2335 &devc->wport : NULL);
2336 int ret, nb;
2337
2338 DBGEV("(file=0x%p, buffer=0x%p, count=%d, ppos=0x%p)\n",
2339 file, buffer, count, ppos);
2340
2341 if (!wport)
2342 return -EINVAL;
2343
2344 if (wport->swbuf == NULL) {
2345 vwsnd_port_t *rport = (file->f_mode & FMODE_READ) ?
2346 &devc->rport : NULL;
2347 ret = pcm_setup(devc, rport, wport);
2348 if (ret < 0)
2349 return ret;
2350 }
2351 if (!access_ok(VERIFY_WRITE, buffer, count))
2352 return -EFAULT;
2353 ret = 0;
2354 while (count) {
2355 DECLARE_WAITQUEUE(wait, current);
2356 add_wait_queue(&wport->queue, &wait);
2357 while ((nb = swb_inc_u(wport, 0)) == 0) {
2358 set_current_state(TASK_INTERRUPTIBLE);
2359 if (wport->flags & DISABLED ||
2360 file->f_flags & O_NONBLOCK) {
2361 current->state = TASK_RUNNING;
2362 remove_wait_queue(&wport->queue, &wait);
2363 return ret ? ret : -EAGAIN;
2364 }
2365 schedule();
2366 if (signal_pending(current)) {
2367 current->state = TASK_RUNNING;
2368 remove_wait_queue(&wport->queue, &wait);
2369 return ret ? ret : -ERESTARTSYS;
2370 }
2371 }
2372 current->state = TASK_RUNNING;
2373 remove_wait_queue(&wport->queue, &wait);
2374
2375 if (nb > count)
2376 nb = count;
2377 DBGPV("nb = %d\n", nb);
2378 if (copy_from_user(wport->swbuf + wport->swb_u_idx, buffer, nb))
2379 return -EFAULT;
2380 pcm_output(devc, 0, nb);
2381 buffer += nb;
2382 count -= nb;
2383 ret += nb;
2384 }
2385 DBGPV("returning %d\n", ret);
2386 return ret;
2387}
2388
2389static ssize_t vwsnd_audio_write(struct file *file,
2390 const char *buffer,
2391 size_t count,
2392 loff_t *ppos)
2393{
2394 vwsnd_dev_t *devc = file->private_data;
2395 ssize_t ret;
2396
2397 mutex_lock(&devc->io_mutex);
2398 ret = vwsnd_audio_do_write(file, buffer, count, ppos);
2399 mutex_unlock(&devc->io_mutex);
2400 return ret;
2401}
2402
2403
2404static unsigned int vwsnd_audio_poll(struct file *file,
2405 struct poll_table_struct *wait)
2406{
2407 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
2408 vwsnd_port_t *rport = (file->f_mode & FMODE_READ) ?
2409 &devc->rport : NULL;
2410 vwsnd_port_t *wport = (file->f_mode & FMODE_WRITE) ?
2411 &devc->wport : NULL;
2412 unsigned int mask = 0;
2413
2414 DBGEV("(file=0x%p, wait=0x%p)\n", file, wait);
2415
2416 ASSERT(rport || wport);
2417 if (rport) {
2418 poll_wait(file, &rport->queue, wait);
2419 if (swb_inc_u(rport, 0))
2420 mask |= (POLLIN | POLLRDNORM);
2421 }
2422 if (wport) {
2423 poll_wait(file, &wport->queue, wait);
2424 if (wport->swbuf == NULL || swb_inc_u(wport, 0))
2425 mask |= (POLLOUT | POLLWRNORM);
2426 }
2427
2428 DBGPV("returning 0x%x\n", mask);
2429 return mask;
2430}
2431
2432static int vwsnd_audio_do_ioctl(struct inode *inode,
2433 struct file *file,
2434 unsigned int cmd,
2435 unsigned long arg)
2436{
2437 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
2438 vwsnd_port_t *rport = (file->f_mode & FMODE_READ) ?
2439 &devc->rport : NULL;
2440 vwsnd_port_t *wport = (file->f_mode & FMODE_WRITE) ?
2441 &devc->wport : NULL;
2442 vwsnd_port_t *aport = rport ? rport : wport;
2443 struct audio_buf_info buf_info;
2444 struct count_info info;
2445 unsigned long flags;
2446 int ival;
2447
2448
2449 DBGEV("(inode=0x%p, file=0x%p, cmd=0x%x, arg=0x%lx)\n",
2450 inode, file, cmd, arg);
2451 switch (cmd) {
2452 case OSS_GETVERSION:
2453 DBGX("OSS_GETVERSION\n");
2454 ival = SOUND_VERSION;
2455 return put_user(ival, (int *) arg);
2456
2457 case SNDCTL_DSP_GETCAPS:
2458 DBGX("SNDCTL_DSP_GETCAPS\n");
2459 ival = DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER;
2460 return put_user(ival, (int *) arg);
2461
2462 case SNDCTL_DSP_GETFMTS:
2463 DBGX("SNDCTL_DSP_GETFMTS\n");
2464 ival = (AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW |
2465 AFMT_U8 | AFMT_S8);
2466 return put_user(ival, (int *) arg);
2467 break;
2468
2469 case SOUND_PCM_READ_RATE:
2470 DBGX("SOUND_PCM_READ_RATE\n");
2471 ival = aport->sw_framerate;
2472 return put_user(ival, (int *) arg);
2473
2474 case SOUND_PCM_READ_CHANNELS:
2475 DBGX("SOUND_PCM_READ_CHANNELS\n");
2476 ival = aport->sw_channels;
2477 return put_user(ival, (int *) arg);
2478
2479 case SNDCTL_DSP_SPEED:
2480 if (get_user(ival, (int *) arg))
2481 return -EFAULT;
2482 DBGX("SNDCTL_DSP_SPEED %d\n", ival);
2483 if (ival) {
2484 if (aport->swstate != SW_INITIAL) {
2485 DBGX("SNDCTL_DSP_SPEED failed: swstate = %d\n",
2486 aport->swstate);
2487 return -EINVAL;
2488 }
2489 if (ival < MIN_SPEED)
2490 ival = MIN_SPEED;
2491 if (ival > MAX_SPEED)
2492 ival = MAX_SPEED;
2493 if (rport)
2494 rport->sw_framerate = ival;
2495 if (wport)
2496 wport->sw_framerate = ival;
2497 } else
2498 ival = aport->sw_framerate;
2499 return put_user(ival, (int *) arg);
2500
2501 case SNDCTL_DSP_STEREO:
2502 if (get_user(ival, (int *) arg))
2503 return -EFAULT;
2504 DBGX("SNDCTL_DSP_STEREO %d\n", ival);
2505 if (ival != 0 && ival != 1)
2506 return -EINVAL;
2507 if (aport->swstate != SW_INITIAL)
2508 return -EINVAL;
2509 if (rport)
2510 rport->sw_channels = ival + 1;
2511 if (wport)
2512 wport->sw_channels = ival + 1;
2513 return put_user(ival, (int *) arg);
2514
2515 case SNDCTL_DSP_CHANNELS:
2516 if (get_user(ival, (int *) arg))
2517 return -EFAULT;
2518 DBGX("SNDCTL_DSP_CHANNELS %d\n", ival);
2519 if (ival != 1 && ival != 2)
2520 return -EINVAL;
2521 if (aport->swstate != SW_INITIAL)
2522 return -EINVAL;
2523 if (rport)
2524 rport->sw_channels = ival;
2525 if (wport)
2526 wport->sw_channels = ival;
2527 return put_user(ival, (int *) arg);
2528
2529 case SNDCTL_DSP_GETBLKSIZE:
2530 ival = pcm_setup(devc, rport, wport);
2531 if (ival < 0) {
2532 DBGX("SNDCTL_DSP_GETBLKSIZE failed, errno %d\n", ival);
2533 return ival;
2534 }
2535 ival = 1 << aport->sw_fragshift;
2536 DBGX("SNDCTL_DSP_GETBLKSIZE returning %d\n", ival);
2537 return put_user(ival, (int *) arg);
2538
2539 case SNDCTL_DSP_SETFRAGMENT:
2540 if (get_user(ival, (int *) arg))
2541 return -EFAULT;
2542 DBGX("SNDCTL_DSP_SETFRAGMENT %d:%d\n",
2543 ival >> 16, ival & 0xFFFF);
2544 if (aport->swstate != SW_INITIAL)
2545 return -EINVAL;
2546 {
2547 int sw_fragshift = ival & 0xFFFF;
2548 int sw_subdivshift = aport->sw_subdivshift;
2549 int hw_fragshift = sw_fragshift - sw_subdivshift;
2550 int sw_fragcount = (ival >> 16) & 0xFFFF;
2551 int hw_fragsize;
2552 if (hw_fragshift < MIN_FRAGSHIFT)
2553 hw_fragshift = MIN_FRAGSHIFT;
2554 if (hw_fragshift > MAX_FRAGSHIFT)
2555 hw_fragshift = MAX_FRAGSHIFT;
2556 sw_fragshift = hw_fragshift + aport->sw_subdivshift;
2557 hw_fragsize = 1 << hw_fragshift;
2558 if (sw_fragcount < MIN_FRAGCOUNT(hw_fragsize))
2559 sw_fragcount = MIN_FRAGCOUNT(hw_fragsize);
2560 if (sw_fragcount > MAX_FRAGCOUNT(hw_fragsize))
2561 sw_fragcount = MAX_FRAGCOUNT(hw_fragsize);
2562 DBGPV("sw_fragshift = %d\n", sw_fragshift);
2563 DBGPV("rport = 0x%p, wport = 0x%p\n", rport, wport);
2564 if (rport) {
2565 rport->sw_fragshift = sw_fragshift;
2566 rport->sw_fragcount = sw_fragcount;
2567 }
2568 if (wport) {
2569 wport->sw_fragshift = sw_fragshift;
2570 wport->sw_fragcount = sw_fragcount;
2571 }
2572 ival = sw_fragcount << 16 | sw_fragshift;
2573 }
2574 DBGX("SNDCTL_DSP_SETFRAGMENT returns %d:%d\n",
2575 ival >> 16, ival & 0xFFFF);
2576 return put_user(ival, (int *) arg);
2577
2578 case SNDCTL_DSP_SUBDIVIDE:
2579 if (get_user(ival, (int *) arg))
2580 return -EFAULT;
2581 DBGX("SNDCTL_DSP_SUBDIVIDE %d\n", ival);
2582 if (aport->swstate != SW_INITIAL)
2583 return -EINVAL;
2584 {
2585 int subdivshift;
2586 int hw_fragshift, hw_fragsize, hw_fragcount;
2587 switch (ival) {
2588 case 1: subdivshift = 0; break;
2589 case 2: subdivshift = 1; break;
2590 case 4: subdivshift = 2; break;
2591 default: return -EINVAL;
2592 }
2593 hw_fragshift = aport->sw_fragshift - subdivshift;
2594 if (hw_fragshift < MIN_FRAGSHIFT ||
2595 hw_fragshift > MAX_FRAGSHIFT)
2596 return -EINVAL;
2597 hw_fragsize = 1 << hw_fragshift;
2598 hw_fragcount = aport->sw_fragcount >> subdivshift;
2599 if (hw_fragcount < MIN_FRAGCOUNT(hw_fragsize) ||
2600 hw_fragcount > MAX_FRAGCOUNT(hw_fragsize))
2601 return -EINVAL;
2602 if (rport)
2603 rport->sw_subdivshift = subdivshift;
2604 if (wport)
2605 wport->sw_subdivshift = subdivshift;
2606 }
2607 return 0;
2608
2609 case SNDCTL_DSP_SETFMT:
2610 if (get_user(ival, (int *) arg))
2611 return -EFAULT;
2612 DBGX("SNDCTL_DSP_SETFMT %d\n", ival);
2613 if (ival != AFMT_QUERY) {
2614 if (aport->swstate != SW_INITIAL) {
2615 DBGP("SETFMT failed, swstate = %d\n",
2616 aport->swstate);
2617 return -EINVAL;
2618 }
2619 switch (ival) {
2620 case AFMT_MU_LAW:
2621 case AFMT_A_LAW:
2622 case AFMT_U8:
2623 case AFMT_S8:
2624 case AFMT_S16_LE:
2625 if (rport)
2626 rport->sw_samplefmt = ival;
2627 if (wport)
2628 wport->sw_samplefmt = ival;
2629 break;
2630 default:
2631 return -EINVAL;
2632 }
2633 }
2634 ival = aport->sw_samplefmt;
2635 return put_user(ival, (int *) arg);
2636
2637 case SNDCTL_DSP_GETOSPACE:
2638 DBGXV("SNDCTL_DSP_GETOSPACE\n");
2639 if (!wport)
2640 return -EINVAL;
2641 ival = pcm_setup(devc, rport, wport);
2642 if (ival < 0)
2643 return ival;
2644 ival = swb_inc_u(wport, 0);
2645 buf_info.fragments = ival >> wport->sw_fragshift;
2646 buf_info.fragstotal = wport->sw_fragcount;
2647 buf_info.fragsize = 1 << wport->sw_fragshift;
2648 buf_info.bytes = ival;
2649 DBGXV("SNDCTL_DSP_GETOSPACE returns { %d %d %d %d }\n",
2650 buf_info.fragments, buf_info.fragstotal,
2651 buf_info.fragsize, buf_info.bytes);
2652 if (copy_to_user((void *) arg, &buf_info, sizeof buf_info))
2653 return -EFAULT;
2654 return 0;
2655
2656 case SNDCTL_DSP_GETISPACE:
2657 DBGX("SNDCTL_DSP_GETISPACE\n");
2658 if (!rport)
2659 return -EINVAL;
2660 ival = pcm_setup(devc, rport, wport);
2661 if (ival < 0)
2662 return ival;
2663 ival = swb_inc_u(rport, 0);
2664 buf_info.fragments = ival >> rport->sw_fragshift;
2665 buf_info.fragstotal = rport->sw_fragcount;
2666 buf_info.fragsize = 1 << rport->sw_fragshift;
2667 buf_info.bytes = ival;
2668 DBGX("SNDCTL_DSP_GETISPACE returns { %d %d %d %d }\n",
2669 buf_info.fragments, buf_info.fragstotal,
2670 buf_info.fragsize, buf_info.bytes);
2671 if (copy_to_user((void *) arg, &buf_info, sizeof buf_info))
2672 return -EFAULT;
2673 return 0;
2674
2675 case SNDCTL_DSP_NONBLOCK:
2676 DBGX("SNDCTL_DSP_NONBLOCK\n");
2677 spin_lock(&file->f_lock);
2678 file->f_flags |= O_NONBLOCK;
2679 spin_unlock(&file->f_lock);
2680 return 0;
2681
2682 case SNDCTL_DSP_RESET:
2683 DBGX("SNDCTL_DSP_RESET\n");
2684
2685
2686
2687
2688
2689 if (wport && wport->swbuf) {
2690 wport->swstate = SW_INITIAL;
2691 pcm_output(devc, 0, 0);
2692 pcm_write_sync(devc);
2693 }
2694 pcm_shutdown(devc, rport, wport);
2695 return 0;
2696
2697 case SNDCTL_DSP_SYNC:
2698 DBGX("SNDCTL_DSP_SYNC\n");
2699 if (wport) {
2700 pcm_flush_frag(devc);
2701 pcm_write_sync(devc);
2702 }
2703 pcm_shutdown(devc, rport, wport);
2704 return 0;
2705
2706 case SNDCTL_DSP_POST:
2707 DBGX("SNDCTL_DSP_POST\n");
2708 if (!wport)
2709 return -EINVAL;
2710 pcm_flush_frag(devc);
2711 return 0;
2712
2713 case SNDCTL_DSP_GETIPTR:
2714 DBGX("SNDCTL_DSP_GETIPTR\n");
2715 if (!rport)
2716 return -EINVAL;
2717 spin_lock_irqsave(&rport->lock, flags);
2718 {
2719 ustmsc_t ustmsc;
2720 if (rport->hwstate == HW_RUNNING) {
2721 ASSERT(rport->swstate == SW_RUN);
2722 li_read_USTMSC(&rport->chan, &ustmsc);
2723 info.bytes = ustmsc.msc - rport->MSC_offset;
2724 info.bytes *= rport->frame_size;
2725 } else {
2726 info.bytes = rport->byte_count;
2727 }
2728 info.blocks = rport->frag_count;
2729 info.ptr = 0;
2730 rport->frag_count = 0;
2731 }
2732 spin_unlock_irqrestore(&rport->lock, flags);
2733 if (copy_to_user((void *) arg, &info, sizeof info))
2734 return -EFAULT;
2735 return 0;
2736
2737 case SNDCTL_DSP_GETOPTR:
2738 DBGX("SNDCTL_DSP_GETOPTR\n");
2739 if (!wport)
2740 return -EINVAL;
2741 spin_lock_irqsave(&wport->lock, flags);
2742 {
2743 ustmsc_t ustmsc;
2744 if (wport->hwstate == HW_RUNNING) {
2745 ASSERT(wport->swstate == SW_RUN);
2746 li_read_USTMSC(&wport->chan, &ustmsc);
2747 info.bytes = ustmsc.msc - wport->MSC_offset;
2748 info.bytes *= wport->frame_size;
2749 } else {
2750 info.bytes = wport->byte_count;
2751 }
2752 info.blocks = wport->frag_count;
2753 info.ptr = 0;
2754 wport->frag_count = 0;
2755 }
2756 spin_unlock_irqrestore(&wport->lock, flags);
2757 if (copy_to_user((void *) arg, &info, sizeof info))
2758 return -EFAULT;
2759 return 0;
2760
2761 case SNDCTL_DSP_GETODELAY:
2762 DBGX("SNDCTL_DSP_GETODELAY\n");
2763 if (!wport)
2764 return -EINVAL;
2765 spin_lock_irqsave(&wport->lock, flags);
2766 {
2767 int fsize = wport->frame_size;
2768 ival = wport->swb_i_avail / fsize;
2769 if (wport->hwstate == HW_RUNNING) {
2770 int swptr, hwptr, hwframes, hwbytes, hwsize;
2771 int totalhwbytes;
2772 ustmsc_t ustmsc;
2773
2774 hwsize = wport->hwbuf_size;
2775 swptr = li_read_swptr(&wport->chan);
2776 li_read_USTMSC(&wport->chan, &ustmsc);
2777 hwframes = ustmsc.msc - wport->MSC_offset;
2778 totalhwbytes = hwframes * fsize;
2779 hwptr = totalhwbytes % hwsize;
2780 hwbytes = (swptr - hwptr + hwsize) % hwsize;
2781 ival += hwbytes / fsize;
2782 }
2783 }
2784 spin_unlock_irqrestore(&wport->lock, flags);
2785 return put_user(ival, (int *) arg);
2786
2787 case SNDCTL_DSP_PROFILE:
2788 DBGX("SNDCTL_DSP_PROFILE\n");
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805 break;
2806
2807 case SNDCTL_DSP_GETTRIGGER:
2808 DBGX("SNDCTL_DSP_GETTRIGGER\n");
2809 ival = 0;
2810 if (rport) {
2811 spin_lock_irqsave(&rport->lock, flags);
2812 {
2813 if (!(rport->flags & DISABLED))
2814 ival |= PCM_ENABLE_INPUT;
2815 }
2816 spin_unlock_irqrestore(&rport->lock, flags);
2817 }
2818 if (wport) {
2819 spin_lock_irqsave(&wport->lock, flags);
2820 {
2821 if (!(wport->flags & DISABLED))
2822 ival |= PCM_ENABLE_OUTPUT;
2823 }
2824 spin_unlock_irqrestore(&wport->lock, flags);
2825 }
2826 return put_user(ival, (int *) arg);
2827
2828 case SNDCTL_DSP_SETTRIGGER:
2829 if (get_user(ival, (int *) arg))
2830 return -EFAULT;
2831 DBGX("SNDCTL_DSP_SETTRIGGER %d\n", ival);
2832
2833
2834
2835
2836
2837
2838 if (((rport && !(ival & PCM_ENABLE_INPUT)) ||
2839 (wport && !(ival & PCM_ENABLE_OUTPUT))) &&
2840 aport->swstate != SW_INITIAL)
2841 return -EINVAL;
2842
2843 if (rport) {
2844 vwsnd_port_hwstate_t hwstate;
2845 spin_lock_irqsave(&rport->lock, flags);
2846 {
2847 hwstate = rport->hwstate;
2848 if (ival & PCM_ENABLE_INPUT)
2849 rport->flags &= ~DISABLED;
2850 else
2851 rport->flags |= DISABLED;
2852 }
2853 spin_unlock_irqrestore(&rport->lock, flags);
2854 if (hwstate != HW_RUNNING && ival & PCM_ENABLE_INPUT) {
2855
2856 if (rport->swstate == SW_INITIAL)
2857 pcm_setup(devc, rport, wport);
2858 else
2859 li_activate_dma(&rport->chan);
2860 }
2861 }
2862 if (wport) {
2863 vwsnd_port_flags_t pflags;
2864 spin_lock_irqsave(&wport->lock, flags);
2865 {
2866 pflags = wport->flags;
2867 if (ival & PCM_ENABLE_OUTPUT)
2868 wport->flags &= ~DISABLED;
2869 else
2870 wport->flags |= DISABLED;
2871 }
2872 spin_unlock_irqrestore(&wport->lock, flags);
2873 if (pflags & DISABLED && ival & PCM_ENABLE_OUTPUT) {
2874 if (wport->swstate == SW_RUN)
2875 pcm_output(devc, 0, 0);
2876 }
2877 }
2878 return 0;
2879
2880 default:
2881 DBGP("unknown ioctl 0x%x\n", cmd);
2882 return -EINVAL;
2883 }
2884 DBGP("unimplemented ioctl 0x%x\n", cmd);
2885 return -EINVAL;
2886}
2887
2888static int vwsnd_audio_ioctl(struct inode *inode,
2889 struct file *file,
2890 unsigned int cmd,
2891 unsigned long arg)
2892{
2893 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
2894 int ret;
2895
2896 mutex_lock(&devc->io_mutex);
2897 ret = vwsnd_audio_do_ioctl(inode, file, cmd, arg);
2898 mutex_unlock(&devc->io_mutex);
2899 return ret;
2900}
2901
2902
2903
2904static int vwsnd_audio_mmap(struct file *file, struct vm_area_struct *vma)
2905{
2906 DBGE("(file=0x%p, vma=0x%p)\n", file, vma);
2907 return -ENODEV;
2908}
2909
2910
2911
2912
2913
2914
2915
2916static int vwsnd_audio_open(struct inode *inode, struct file *file)
2917{
2918 vwsnd_dev_t *devc;
2919 int minor = iminor(inode);
2920 int sw_samplefmt;
2921
2922 DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
2923
2924 INC_USE_COUNT;
2925 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
2926 if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
2927 break;
2928
2929 if (devc == NULL) {
2930 DEC_USE_COUNT;
2931 return -ENODEV;
2932 }
2933
2934 mutex_lock(&devc->open_mutex);
2935 while (devc->open_mode & file->f_mode) {
2936 mutex_unlock(&devc->open_mutex);
2937 if (file->f_flags & O_NONBLOCK) {
2938 DEC_USE_COUNT;
2939 return -EBUSY;
2940 }
2941 interruptible_sleep_on(&devc->open_wait);
2942 if (signal_pending(current)) {
2943 DEC_USE_COUNT;
2944 return -ERESTARTSYS;
2945 }
2946 mutex_lock(&devc->open_mutex);
2947 }
2948 devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
2949 mutex_unlock(&devc->open_mutex);
2950
2951
2952
2953 sw_samplefmt = 0;
2954 if ((minor & 0xF) == SND_DEV_DSP)
2955 sw_samplefmt = AFMT_U8;
2956 else if ((minor & 0xF) == SND_DEV_AUDIO)
2957 sw_samplefmt = AFMT_MU_LAW;
2958 else if ((minor & 0xF) == SND_DEV_DSP16)
2959 sw_samplefmt = AFMT_S16_LE;
2960 else
2961 ASSERT(0);
2962
2963
2964
2965 mutex_lock(&devc->io_mutex);
2966 {
2967 if (file->f_mode & FMODE_READ) {
2968 devc->rport.swstate = SW_INITIAL;
2969 devc->rport.flags = 0;
2970 devc->rport.sw_channels = 1;
2971 devc->rport.sw_samplefmt = sw_samplefmt;
2972 devc->rport.sw_framerate = 8000;
2973 devc->rport.sw_fragshift = DEFAULT_FRAGSHIFT;
2974 devc->rport.sw_fragcount = DEFAULT_FRAGCOUNT;
2975 devc->rport.sw_subdivshift = DEFAULT_SUBDIVSHIFT;
2976 devc->rport.byte_count = 0;
2977 devc->rport.frag_count = 0;
2978 }
2979 if (file->f_mode & FMODE_WRITE) {
2980 devc->wport.swstate = SW_INITIAL;
2981 devc->wport.flags = 0;
2982 devc->wport.sw_channels = 1;
2983 devc->wport.sw_samplefmt = sw_samplefmt;
2984 devc->wport.sw_framerate = 8000;
2985 devc->wport.sw_fragshift = DEFAULT_FRAGSHIFT;
2986 devc->wport.sw_fragcount = DEFAULT_FRAGCOUNT;
2987 devc->wport.sw_subdivshift = DEFAULT_SUBDIVSHIFT;
2988 devc->wport.byte_count = 0;
2989 devc->wport.frag_count = 0;
2990 }
2991 }
2992 mutex_unlock(&devc->io_mutex);
2993
2994 file->private_data = devc;
2995 DBGRV();
2996 return 0;
2997}
2998
2999
3000
3001
3002
3003static int vwsnd_audio_release(struct inode *inode, struct file *file)
3004{
3005 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
3006 vwsnd_port_t *wport = NULL, *rport = NULL;
3007 int err = 0;
3008
3009 lock_kernel();
3010 mutex_lock(&devc->io_mutex);
3011 {
3012 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3013
3014 if (file->f_mode & FMODE_READ)
3015 rport = &devc->rport;
3016 if (file->f_mode & FMODE_WRITE) {
3017 wport = &devc->wport;
3018 pcm_flush_frag(devc);
3019 pcm_write_sync(devc);
3020 }
3021 pcm_shutdown(devc, rport, wport);
3022 if (rport)
3023 rport->swstate = SW_OFF;
3024 if (wport)
3025 wport->swstate = SW_OFF;
3026 }
3027 mutex_unlock(&devc->io_mutex);
3028
3029 mutex_lock(&devc->open_mutex);
3030 {
3031 devc->open_mode &= ~file->f_mode;
3032 }
3033 mutex_unlock(&devc->open_mutex);
3034 wake_up(&devc->open_wait);
3035 DEC_USE_COUNT;
3036 DBGR();
3037 unlock_kernel();
3038 return err;
3039}
3040
3041static const struct file_operations vwsnd_audio_fops = {
3042 .owner = THIS_MODULE,
3043 .llseek = no_llseek,
3044 .read = vwsnd_audio_read,
3045 .write = vwsnd_audio_write,
3046 .poll = vwsnd_audio_poll,
3047 .ioctl = vwsnd_audio_ioctl,
3048 .mmap = vwsnd_audio_mmap,
3049 .open = vwsnd_audio_open,
3050 .release = vwsnd_audio_release,
3051};
3052
3053
3054
3055
3056
3057
3058static int vwsnd_mixer_open(struct inode *inode, struct file *file)
3059{
3060 vwsnd_dev_t *devc;
3061
3062 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3063
3064 INC_USE_COUNT;
3065 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
3066 if (devc->mixer_minor == iminor(inode))
3067 break;
3068
3069 if (devc == NULL) {
3070 DEC_USE_COUNT;
3071 return -ENODEV;
3072 }
3073 file->private_data = devc;
3074 return 0;
3075}
3076
3077
3078
3079static int vwsnd_mixer_release(struct inode *inode, struct file *file)
3080{
3081 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3082 DEC_USE_COUNT;
3083 return 0;
3084}
3085
3086
3087
3088static int mixer_read_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg)
3089{
3090 int val = -1;
3091
3092 DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg);
3093
3094 switch (nr) {
3095 case SOUND_MIXER_CAPS:
3096 val = SOUND_CAP_EXCL_INPUT;
3097 break;
3098
3099 case SOUND_MIXER_DEVMASK:
3100 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3101 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV);
3102 break;
3103
3104 case SOUND_MIXER_STEREODEVS:
3105 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3106 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV);
3107 break;
3108
3109 case SOUND_MIXER_OUTMASK:
3110 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3111 SOUND_MASK_MIC | SOUND_MASK_CD);
3112 break;
3113
3114 case SOUND_MIXER_RECMASK:
3115 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3116 SOUND_MASK_MIC | SOUND_MASK_CD);
3117 break;
3118
3119 case SOUND_MIXER_PCM:
3120 val = ad1843_get_gain(&devc->lith, &ad1843_gain_PCM);
3121 break;
3122
3123 case SOUND_MIXER_LINE:
3124 val = ad1843_get_gain(&devc->lith, &ad1843_gain_LINE);
3125 break;
3126
3127 case SOUND_MIXER_MIC:
3128 val = ad1843_get_gain(&devc->lith, &ad1843_gain_MIC);
3129 break;
3130
3131 case SOUND_MIXER_CD:
3132 val = ad1843_get_gain(&devc->lith, &ad1843_gain_CD);
3133 break;
3134
3135 case SOUND_MIXER_RECLEV:
3136 val = ad1843_get_gain(&devc->lith, &ad1843_gain_RECLEV);
3137 break;
3138
3139 case SOUND_MIXER_RECSRC:
3140 val = ad1843_get_recsrc(&devc->lith);
3141 break;
3142
3143 case SOUND_MIXER_OUTSRC:
3144 val = ad1843_get_outsrc(&devc->lith);
3145 break;
3146
3147 default:
3148 return -EINVAL;
3149 }
3150 return put_user(val, (int __user *) arg);
3151}
3152
3153
3154
3155static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg)
3156{
3157 int val;
3158 int err;
3159
3160 DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg);
3161
3162 err = get_user(val, (int __user *) arg);
3163 if (err)
3164 return -EFAULT;
3165 switch (nr) {
3166 case SOUND_MIXER_PCM:
3167 val = ad1843_set_gain(&devc->lith, &ad1843_gain_PCM, val);
3168 break;
3169
3170 case SOUND_MIXER_LINE:
3171 val = ad1843_set_gain(&devc->lith, &ad1843_gain_LINE, val);
3172 break;
3173
3174 case SOUND_MIXER_MIC:
3175 val = ad1843_set_gain(&devc->lith, &ad1843_gain_MIC, val);
3176 break;
3177
3178 case SOUND_MIXER_CD:
3179 val = ad1843_set_gain(&devc->lith, &ad1843_gain_CD, val);
3180 break;
3181
3182 case SOUND_MIXER_RECLEV:
3183 val = ad1843_set_gain(&devc->lith, &ad1843_gain_RECLEV, val);
3184 break;
3185
3186 case SOUND_MIXER_RECSRC:
3187 if (devc->rport.swbuf || devc->wport.swbuf)
3188 return -EBUSY;
3189 val = ad1843_set_recsrc(&devc->lith, val);
3190 break;
3191
3192 case SOUND_MIXER_OUTSRC:
3193 val = ad1843_set_outsrc(&devc->lith, val);
3194 break;
3195
3196 default:
3197 return -EINVAL;
3198 }
3199 if (val < 0)
3200 return val;
3201 return put_user(val, (int __user *) arg);
3202}
3203
3204
3205
3206static int vwsnd_mixer_ioctl(struct inode *ioctl,
3207 struct file *file,
3208 unsigned int cmd,
3209 unsigned long arg)
3210{
3211 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
3212 const unsigned int nrmask = _IOC_NRMASK << _IOC_NRSHIFT;
3213 const unsigned int nr = (cmd & nrmask) >> _IOC_NRSHIFT;
3214 int retval;
3215
3216 DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
3217
3218 mutex_lock(&devc->mix_mutex);
3219 {
3220 if ((cmd & ~nrmask) == MIXER_READ(0))
3221 retval = mixer_read_ioctl(devc, nr, (void __user *) arg);
3222 else if ((cmd & ~nrmask) == MIXER_WRITE(0))
3223 retval = mixer_write_ioctl(devc, nr, (void __user *) arg);
3224 else
3225 retval = -EINVAL;
3226 }
3227 mutex_unlock(&devc->mix_mutex);
3228 return retval;
3229}
3230
3231static const struct file_operations vwsnd_mixer_fops = {
3232 .owner = THIS_MODULE,
3233 .llseek = no_llseek,
3234 .ioctl = vwsnd_mixer_ioctl,
3235 .open = vwsnd_mixer_open,
3236 .release = vwsnd_mixer_release,
3237};
3238
3239
3240
3241
3242
3243
3244static int __init probe_vwsnd(struct address_info *hw_config)
3245{
3246 lithium_t lith;
3247 int w;
3248 unsigned long later;
3249
3250 DBGEV("(hw_config=0x%p)\n", hw_config);
3251
3252
3253
3254 if (li_create(&lith, hw_config->io_base) != 0) {
3255 printk(KERN_WARNING "probe_vwsnd: can't map lithium\n");
3256 return 0;
3257 }
3258 later = jiffies + 2;
3259 li_writel(&lith, LI_HOST_CONTROLLER, LI_HC_LINK_ENABLE);
3260 do {
3261 w = li_readl(&lith, LI_HOST_CONTROLLER);
3262 } while (w == LI_HC_LINK_ENABLE && time_before(jiffies, later));
3263
3264 li_destroy(&lith);
3265
3266 DBGPV("HC = 0x%04x\n", w);
3267
3268 if ((w == LI_HC_LINK_ENABLE) || (w & LI_HC_LINK_CODEC)) {
3269
3270
3271
3272
3273
3274 printk(KERN_WARNING "probe_vwsnd: audio codec not found\n");
3275 return 0;
3276 }
3277
3278 if (w & LI_HC_LINK_FAILURE) {
3279 printk(KERN_WARNING "probe_vwsnd: can't init audio codec\n");
3280 return 0;
3281 }
3282
3283 printk(KERN_INFO "vwsnd: lithium audio at mmio %#x irq %d\n",
3284 hw_config->io_base, hw_config->irq);
3285
3286 return 1;
3287}
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297static int __init attach_vwsnd(struct address_info *hw_config)
3298{
3299 vwsnd_dev_t *devc = NULL;
3300 int err = -ENOMEM;
3301
3302 DBGEV("(hw_config=0x%p)\n", hw_config);
3303
3304 devc = kmalloc(sizeof (vwsnd_dev_t), GFP_KERNEL);
3305 if (devc == NULL)
3306 goto fail0;
3307
3308 err = li_create(&devc->lith, hw_config->io_base);
3309 if (err)
3310 goto fail1;
3311
3312 init_waitqueue_head(&devc->open_wait);
3313
3314 devc->rport.hwbuf_size = HWBUF_SIZE;
3315 devc->rport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
3316 if (!devc->rport.hwbuf_vaddr)
3317 goto fail2;
3318 devc->rport.hwbuf = (void *) devc->rport.hwbuf_vaddr;
3319 devc->rport.hwbuf_paddr = virt_to_phys(devc->rport.hwbuf);
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334 li_writel(&devc->lith, LI_COMM1_BASE,
3335 devc->rport.hwbuf_paddr >> 8 | 1 << (37 - 8));
3336
3337 devc->wport.hwbuf_size = HWBUF_SIZE;
3338 devc->wport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
3339 if (!devc->wport.hwbuf_vaddr)
3340 goto fail3;
3341 devc->wport.hwbuf = (void *) devc->wport.hwbuf_vaddr;
3342 devc->wport.hwbuf_paddr = virt_to_phys(devc->wport.hwbuf);
3343 DBGP("wport hwbuf = 0x%p\n", devc->wport.hwbuf);
3344
3345 DBGDO(shut_up++);
3346 err = ad1843_init(&devc->lith);
3347 DBGDO(shut_up--);
3348 if (err)
3349 goto fail4;
3350
3351
3352
3353 err = request_irq(hw_config->irq, vwsnd_audio_intr, 0, "vwsnd", devc);
3354 if (err)
3355 goto fail5;
3356
3357
3358
3359 devc->audio_minor = register_sound_dsp(&vwsnd_audio_fops, -1);
3360 if ((err = devc->audio_minor) < 0) {
3361 DBGDO(printk(KERN_WARNING
3362 "attach_vwsnd: register_sound_dsp error %d\n",
3363 err));
3364 goto fail6;
3365 }
3366 devc->mixer_minor = register_sound_mixer(&vwsnd_mixer_fops,
3367 devc->audio_minor >> 4);
3368 if ((err = devc->mixer_minor) < 0) {
3369 DBGDO(printk(KERN_WARNING
3370 "attach_vwsnd: register_sound_mixer error %d\n",
3371 err));
3372 goto fail7;
3373 }
3374
3375
3376
3377 hw_config->slots[0] = devc->audio_minor;
3378
3379
3380
3381 mutex_init(&devc->open_mutex);
3382 mutex_init(&devc->io_mutex);
3383 mutex_init(&devc->mix_mutex);
3384 devc->open_mode = 0;
3385 spin_lock_init(&devc->rport.lock);
3386 init_waitqueue_head(&devc->rport.queue);
3387 devc->rport.swstate = SW_OFF;
3388 devc->rport.hwstate = HW_STOPPED;
3389 devc->rport.flags = 0;
3390 devc->rport.swbuf = NULL;
3391 spin_lock_init(&devc->wport.lock);
3392 init_waitqueue_head(&devc->wport.queue);
3393 devc->wport.swstate = SW_OFF;
3394 devc->wport.hwstate = HW_STOPPED;
3395 devc->wport.flags = 0;
3396 devc->wport.swbuf = NULL;
3397
3398
3399
3400 devc->next_dev = vwsnd_dev_list;
3401 vwsnd_dev_list = devc;
3402 return devc->audio_minor;
3403
3404
3405
3406 fail7:
3407 unregister_sound_dsp(devc->audio_minor);
3408 fail6:
3409 free_irq(hw_config->irq, devc);
3410 fail5:
3411 fail4:
3412 free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER);
3413 fail3:
3414 free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER);
3415 fail2:
3416 li_destroy(&devc->lith);
3417 fail1:
3418 kfree(devc);
3419 fail0:
3420 return err;
3421}
3422
3423static int __exit unload_vwsnd(struct address_info *hw_config)
3424{
3425 vwsnd_dev_t *devc, **devcp;
3426
3427 DBGE("()\n");
3428
3429 devcp = &vwsnd_dev_list;
3430 while ((devc = *devcp)) {
3431 if (devc->audio_minor == hw_config->slots[0]) {
3432 *devcp = devc->next_dev;
3433 break;
3434 }
3435 devcp = &devc->next_dev;
3436 }
3437
3438 if (!devc)
3439 return -ENODEV;
3440
3441 unregister_sound_mixer(devc->mixer_minor);
3442 unregister_sound_dsp(devc->audio_minor);
3443 free_irq(hw_config->irq, devc);
3444 free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER);
3445 free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER);
3446 li_destroy(&devc->lith);
3447 kfree(devc);
3448
3449 return 0;
3450}
3451
3452
3453
3454
3455static struct address_info the_hw_config = {
3456 0xFF001000,
3457 CO_IRQ(CO_APIC_LI_AUDIO)
3458};
3459
3460MODULE_DESCRIPTION("SGI Visual Workstation sound module");
3461MODULE_AUTHOR("Bob Miller <kbob@sgi.com>");
3462MODULE_LICENSE("GPL");
3463
3464static int __init init_vwsnd(void)
3465{
3466 int err;
3467
3468 DBGXV("\n");
3469 DBGXV("sound::vwsnd::init_module()\n");
3470
3471 if (!probe_vwsnd(&the_hw_config))
3472 return -ENODEV;
3473
3474 err = attach_vwsnd(&the_hw_config);
3475 if (err < 0)
3476 return err;
3477 return 0;
3478}
3479
3480static void __exit cleanup_vwsnd(void)
3481{
3482 DBGX("sound::vwsnd::cleanup_module()\n");
3483
3484 unload_vwsnd(&the_hw_config);
3485}
3486
3487module_init(init_vwsnd);
3488module_exit(cleanup_vwsnd);
3489