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