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/mach-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(__FUNCTION__, __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, __FUNCTION__ , ##args))
201#define DBGE(fmt, args...) (DBGX("%s" fmt, __FUNCTION__ , ##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 = (!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 = (!LI_CCTL_RESET |
642 SHIFT_FIELD(size, LI_CCTL_SIZE) |
643 !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 mode_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 file->f_flags |= O_NONBLOCK;
2677 return 0;
2678
2679 case SNDCTL_DSP_RESET:
2680 DBGX("SNDCTL_DSP_RESET\n");
2681
2682
2683
2684
2685
2686 if (wport && wport->swbuf) {
2687 wport->swstate = SW_INITIAL;
2688 pcm_output(devc, 0, 0);
2689 pcm_write_sync(devc);
2690 }
2691 pcm_shutdown(devc, rport, wport);
2692 return 0;
2693
2694 case SNDCTL_DSP_SYNC:
2695 DBGX("SNDCTL_DSP_SYNC\n");
2696 if (wport) {
2697 pcm_flush_frag(devc);
2698 pcm_write_sync(devc);
2699 }
2700 pcm_shutdown(devc, rport, wport);
2701 return 0;
2702
2703 case SNDCTL_DSP_POST:
2704 DBGX("SNDCTL_DSP_POST\n");
2705 if (!wport)
2706 return -EINVAL;
2707 pcm_flush_frag(devc);
2708 return 0;
2709
2710 case SNDCTL_DSP_GETIPTR:
2711 DBGX("SNDCTL_DSP_GETIPTR\n");
2712 if (!rport)
2713 return -EINVAL;
2714 spin_lock_irqsave(&rport->lock, flags);
2715 {
2716 ustmsc_t ustmsc;
2717 if (rport->hwstate == HW_RUNNING) {
2718 ASSERT(rport->swstate == SW_RUN);
2719 li_read_USTMSC(&rport->chan, &ustmsc);
2720 info.bytes = ustmsc.msc - rport->MSC_offset;
2721 info.bytes *= rport->frame_size;
2722 } else {
2723 info.bytes = rport->byte_count;
2724 }
2725 info.blocks = rport->frag_count;
2726 info.ptr = 0;
2727 rport->frag_count = 0;
2728 }
2729 spin_unlock_irqrestore(&rport->lock, flags);
2730 if (copy_to_user((void *) arg, &info, sizeof info))
2731 return -EFAULT;
2732 return 0;
2733
2734 case SNDCTL_DSP_GETOPTR:
2735 DBGX("SNDCTL_DSP_GETOPTR\n");
2736 if (!wport)
2737 return -EINVAL;
2738 spin_lock_irqsave(&wport->lock, flags);
2739 {
2740 ustmsc_t ustmsc;
2741 if (wport->hwstate == HW_RUNNING) {
2742 ASSERT(wport->swstate == SW_RUN);
2743 li_read_USTMSC(&wport->chan, &ustmsc);
2744 info.bytes = ustmsc.msc - wport->MSC_offset;
2745 info.bytes *= wport->frame_size;
2746 } else {
2747 info.bytes = wport->byte_count;
2748 }
2749 info.blocks = wport->frag_count;
2750 info.ptr = 0;
2751 wport->frag_count = 0;
2752 }
2753 spin_unlock_irqrestore(&wport->lock, flags);
2754 if (copy_to_user((void *) arg, &info, sizeof info))
2755 return -EFAULT;
2756 return 0;
2757
2758 case SNDCTL_DSP_GETODELAY:
2759 DBGX("SNDCTL_DSP_GETODELAY\n");
2760 if (!wport)
2761 return -EINVAL;
2762 spin_lock_irqsave(&wport->lock, flags);
2763 {
2764 int fsize = wport->frame_size;
2765 ival = wport->swb_i_avail / fsize;
2766 if (wport->hwstate == HW_RUNNING) {
2767 int swptr, hwptr, hwframes, hwbytes, hwsize;
2768 int totalhwbytes;
2769 ustmsc_t ustmsc;
2770
2771 hwsize = wport->hwbuf_size;
2772 swptr = li_read_swptr(&wport->chan);
2773 li_read_USTMSC(&wport->chan, &ustmsc);
2774 hwframes = ustmsc.msc - wport->MSC_offset;
2775 totalhwbytes = hwframes * fsize;
2776 hwptr = totalhwbytes % hwsize;
2777 hwbytes = (swptr - hwptr + hwsize) % hwsize;
2778 ival += hwbytes / fsize;
2779 }
2780 }
2781 spin_unlock_irqrestore(&wport->lock, flags);
2782 return put_user(ival, (int *) arg);
2783
2784 case SNDCTL_DSP_PROFILE:
2785 DBGX("SNDCTL_DSP_PROFILE\n");
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802 break;
2803
2804 case SNDCTL_DSP_GETTRIGGER:
2805 DBGX("SNDCTL_DSP_GETTRIGGER\n");
2806 ival = 0;
2807 if (rport) {
2808 spin_lock_irqsave(&rport->lock, flags);
2809 {
2810 if (!(rport->flags & DISABLED))
2811 ival |= PCM_ENABLE_INPUT;
2812 }
2813 spin_unlock_irqrestore(&rport->lock, flags);
2814 }
2815 if (wport) {
2816 spin_lock_irqsave(&wport->lock, flags);
2817 {
2818 if (!(wport->flags & DISABLED))
2819 ival |= PCM_ENABLE_OUTPUT;
2820 }
2821 spin_unlock_irqrestore(&wport->lock, flags);
2822 }
2823 return put_user(ival, (int *) arg);
2824
2825 case SNDCTL_DSP_SETTRIGGER:
2826 if (get_user(ival, (int *) arg))
2827 return -EFAULT;
2828 DBGX("SNDCTL_DSP_SETTRIGGER %d\n", ival);
2829
2830
2831
2832
2833
2834
2835 if (((rport && !(ival & PCM_ENABLE_INPUT)) ||
2836 (wport && !(ival & PCM_ENABLE_OUTPUT))) &&
2837 aport->swstate != SW_INITIAL)
2838 return -EINVAL;
2839
2840 if (rport) {
2841 vwsnd_port_hwstate_t hwstate;
2842 spin_lock_irqsave(&rport->lock, flags);
2843 {
2844 hwstate = rport->hwstate;
2845 if (ival & PCM_ENABLE_INPUT)
2846 rport->flags &= ~DISABLED;
2847 else
2848 rport->flags |= DISABLED;
2849 }
2850 spin_unlock_irqrestore(&rport->lock, flags);
2851 if (hwstate != HW_RUNNING && ival & PCM_ENABLE_INPUT) {
2852
2853 if (rport->swstate == SW_INITIAL)
2854 pcm_setup(devc, rport, wport);
2855 else
2856 li_activate_dma(&rport->chan);
2857 }
2858 }
2859 if (wport) {
2860 vwsnd_port_flags_t pflags;
2861 spin_lock_irqsave(&wport->lock, flags);
2862 {
2863 pflags = wport->flags;
2864 if (ival & PCM_ENABLE_OUTPUT)
2865 wport->flags &= ~DISABLED;
2866 else
2867 wport->flags |= DISABLED;
2868 }
2869 spin_unlock_irqrestore(&wport->lock, flags);
2870 if (pflags & DISABLED && ival & PCM_ENABLE_OUTPUT) {
2871 if (wport->swstate == SW_RUN)
2872 pcm_output(devc, 0, 0);
2873 }
2874 }
2875 return 0;
2876
2877 default:
2878 DBGP("unknown ioctl 0x%x\n", cmd);
2879 return -EINVAL;
2880 }
2881 DBGP("unimplemented ioctl 0x%x\n", cmd);
2882 return -EINVAL;
2883}
2884
2885static int vwsnd_audio_ioctl(struct inode *inode,
2886 struct file *file,
2887 unsigned int cmd,
2888 unsigned long arg)
2889{
2890 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
2891 int ret;
2892
2893 mutex_lock(&devc->io_mutex);
2894 ret = vwsnd_audio_do_ioctl(inode, file, cmd, arg);
2895 mutex_unlock(&devc->io_mutex);
2896 return ret;
2897}
2898
2899
2900
2901static int vwsnd_audio_mmap(struct file *file, struct vm_area_struct *vma)
2902{
2903 DBGE("(file=0x%p, vma=0x%p)\n", file, vma);
2904 return -ENODEV;
2905}
2906
2907
2908
2909
2910
2911
2912
2913static int vwsnd_audio_open(struct inode *inode, struct file *file)
2914{
2915 vwsnd_dev_t *devc;
2916 int minor = iminor(inode);
2917 int sw_samplefmt;
2918
2919 DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
2920
2921 INC_USE_COUNT;
2922 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
2923 if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
2924 break;
2925
2926 if (devc == NULL) {
2927 DEC_USE_COUNT;
2928 return -ENODEV;
2929 }
2930
2931 mutex_lock(&devc->open_mutex);
2932 while (devc->open_mode & file->f_mode) {
2933 mutex_unlock(&devc->open_mutex);
2934 if (file->f_flags & O_NONBLOCK) {
2935 DEC_USE_COUNT;
2936 return -EBUSY;
2937 }
2938 interruptible_sleep_on(&devc->open_wait);
2939 if (signal_pending(current)) {
2940 DEC_USE_COUNT;
2941 return -ERESTARTSYS;
2942 }
2943 mutex_lock(&devc->open_mutex);
2944 }
2945 devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
2946 mutex_unlock(&devc->open_mutex);
2947
2948
2949
2950 sw_samplefmt = 0;
2951 if ((minor & 0xF) == SND_DEV_DSP)
2952 sw_samplefmt = AFMT_U8;
2953 else if ((minor & 0xF) == SND_DEV_AUDIO)
2954 sw_samplefmt = AFMT_MU_LAW;
2955 else if ((minor & 0xF) == SND_DEV_DSP16)
2956 sw_samplefmt = AFMT_S16_LE;
2957 else
2958 ASSERT(0);
2959
2960
2961
2962 mutex_lock(&devc->io_mutex);
2963 {
2964 if (file->f_mode & FMODE_READ) {
2965 devc->rport.swstate = SW_INITIAL;
2966 devc->rport.flags = 0;
2967 devc->rport.sw_channels = 1;
2968 devc->rport.sw_samplefmt = sw_samplefmt;
2969 devc->rport.sw_framerate = 8000;
2970 devc->rport.sw_fragshift = DEFAULT_FRAGSHIFT;
2971 devc->rport.sw_fragcount = DEFAULT_FRAGCOUNT;
2972 devc->rport.sw_subdivshift = DEFAULT_SUBDIVSHIFT;
2973 devc->rport.byte_count = 0;
2974 devc->rport.frag_count = 0;
2975 }
2976 if (file->f_mode & FMODE_WRITE) {
2977 devc->wport.swstate = SW_INITIAL;
2978 devc->wport.flags = 0;
2979 devc->wport.sw_channels = 1;
2980 devc->wport.sw_samplefmt = sw_samplefmt;
2981 devc->wport.sw_framerate = 8000;
2982 devc->wport.sw_fragshift = DEFAULT_FRAGSHIFT;
2983 devc->wport.sw_fragcount = DEFAULT_FRAGCOUNT;
2984 devc->wport.sw_subdivshift = DEFAULT_SUBDIVSHIFT;
2985 devc->wport.byte_count = 0;
2986 devc->wport.frag_count = 0;
2987 }
2988 }
2989 mutex_unlock(&devc->io_mutex);
2990
2991 file->private_data = devc;
2992 DBGRV();
2993 return 0;
2994}
2995
2996
2997
2998
2999
3000static int vwsnd_audio_release(struct inode *inode, struct file *file)
3001{
3002 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
3003 vwsnd_port_t *wport = NULL, *rport = NULL;
3004 int err = 0;
3005
3006 lock_kernel();
3007 mutex_lock(&devc->io_mutex);
3008 {
3009 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3010
3011 if (file->f_mode & FMODE_READ)
3012 rport = &devc->rport;
3013 if (file->f_mode & FMODE_WRITE) {
3014 wport = &devc->wport;
3015 pcm_flush_frag(devc);
3016 pcm_write_sync(devc);
3017 }
3018 pcm_shutdown(devc, rport, wport);
3019 if (rport)
3020 rport->swstate = SW_OFF;
3021 if (wport)
3022 wport->swstate = SW_OFF;
3023 }
3024 mutex_unlock(&devc->io_mutex);
3025
3026 mutex_lock(&devc->open_mutex);
3027 {
3028 devc->open_mode &= ~file->f_mode;
3029 }
3030 mutex_unlock(&devc->open_mutex);
3031 wake_up(&devc->open_wait);
3032 DEC_USE_COUNT;
3033 DBGR();
3034 unlock_kernel();
3035 return err;
3036}
3037
3038static const struct file_operations vwsnd_audio_fops = {
3039 .owner = THIS_MODULE,
3040 .llseek = no_llseek,
3041 .read = vwsnd_audio_read,
3042 .write = vwsnd_audio_write,
3043 .poll = vwsnd_audio_poll,
3044 .ioctl = vwsnd_audio_ioctl,
3045 .mmap = vwsnd_audio_mmap,
3046 .open = vwsnd_audio_open,
3047 .release = vwsnd_audio_release,
3048};
3049
3050
3051
3052
3053
3054
3055static int vwsnd_mixer_open(struct inode *inode, struct file *file)
3056{
3057 vwsnd_dev_t *devc;
3058
3059 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3060
3061 INC_USE_COUNT;
3062 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
3063 if (devc->mixer_minor == iminor(inode))
3064 break;
3065
3066 if (devc == NULL) {
3067 DEC_USE_COUNT;
3068 return -ENODEV;
3069 }
3070 file->private_data = devc;
3071 return 0;
3072}
3073
3074
3075
3076static int vwsnd_mixer_release(struct inode *inode, struct file *file)
3077{
3078 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3079 DEC_USE_COUNT;
3080 return 0;
3081}
3082
3083
3084
3085static int mixer_read_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg)
3086{
3087 int val = -1;
3088
3089 DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg);
3090
3091 switch (nr) {
3092 case SOUND_MIXER_CAPS:
3093 val = SOUND_CAP_EXCL_INPUT;
3094 break;
3095
3096 case SOUND_MIXER_DEVMASK:
3097 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3098 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV);
3099 break;
3100
3101 case SOUND_MIXER_STEREODEVS:
3102 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3103 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV);
3104 break;
3105
3106 case SOUND_MIXER_OUTMASK:
3107 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3108 SOUND_MASK_MIC | SOUND_MASK_CD);
3109 break;
3110
3111 case SOUND_MIXER_RECMASK:
3112 val = (SOUND_MASK_PCM | SOUND_MASK_LINE |
3113 SOUND_MASK_MIC | SOUND_MASK_CD);
3114 break;
3115
3116 case SOUND_MIXER_PCM:
3117 val = ad1843_get_gain(&devc->lith, &ad1843_gain_PCM);
3118 break;
3119
3120 case SOUND_MIXER_LINE:
3121 val = ad1843_get_gain(&devc->lith, &ad1843_gain_LINE);
3122 break;
3123
3124 case SOUND_MIXER_MIC:
3125 val = ad1843_get_gain(&devc->lith, &ad1843_gain_MIC);
3126 break;
3127
3128 case SOUND_MIXER_CD:
3129 val = ad1843_get_gain(&devc->lith, &ad1843_gain_CD);
3130 break;
3131
3132 case SOUND_MIXER_RECLEV:
3133 val = ad1843_get_gain(&devc->lith, &ad1843_gain_RECLEV);
3134 break;
3135
3136 case SOUND_MIXER_RECSRC:
3137 val = ad1843_get_recsrc(&devc->lith);
3138 break;
3139
3140 case SOUND_MIXER_OUTSRC:
3141 val = ad1843_get_outsrc(&devc->lith);
3142 break;
3143
3144 default:
3145 return -EINVAL;
3146 }
3147 return put_user(val, (int __user *) arg);
3148}
3149
3150
3151
3152static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg)
3153{
3154 int val;
3155 int err;
3156
3157 DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg);
3158
3159 err = get_user(val, (int __user *) arg);
3160 if (err)
3161 return -EFAULT;
3162 switch (nr) {
3163 case SOUND_MIXER_PCM:
3164 val = ad1843_set_gain(&devc->lith, &ad1843_gain_PCM, val);
3165 break;
3166
3167 case SOUND_MIXER_LINE:
3168 val = ad1843_set_gain(&devc->lith, &ad1843_gain_LINE, val);
3169 break;
3170
3171 case SOUND_MIXER_MIC:
3172 val = ad1843_set_gain(&devc->lith, &ad1843_gain_MIC, val);
3173 break;
3174
3175 case SOUND_MIXER_CD:
3176 val = ad1843_set_gain(&devc->lith, &ad1843_gain_CD, val);
3177 break;
3178
3179 case SOUND_MIXER_RECLEV:
3180 val = ad1843_set_gain(&devc->lith, &ad1843_gain_RECLEV, val);
3181 break;
3182
3183 case SOUND_MIXER_RECSRC:
3184 if (devc->rport.swbuf || devc->wport.swbuf)
3185 return -EBUSY;
3186 val = ad1843_set_recsrc(&devc->lith, val);
3187 break;
3188
3189 case SOUND_MIXER_OUTSRC:
3190 val = ad1843_set_outsrc(&devc->lith, val);
3191 break;
3192
3193 default:
3194 return -EINVAL;
3195 }
3196 if (val < 0)
3197 return val;
3198 return put_user(val, (int __user *) arg);
3199}
3200
3201
3202
3203static int vwsnd_mixer_ioctl(struct inode *ioctl,
3204 struct file *file,
3205 unsigned int cmd,
3206 unsigned long arg)
3207{
3208 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
3209 const unsigned int nrmask = _IOC_NRMASK << _IOC_NRSHIFT;
3210 const unsigned int nr = (cmd & nrmask) >> _IOC_NRSHIFT;
3211 int retval;
3212
3213 DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
3214
3215 mutex_lock(&devc->mix_mutex);
3216 {
3217 if ((cmd & ~nrmask) == MIXER_READ(0))
3218 retval = mixer_read_ioctl(devc, nr, (void __user *) arg);
3219 else if ((cmd & ~nrmask) == MIXER_WRITE(0))
3220 retval = mixer_write_ioctl(devc, nr, (void __user *) arg);
3221 else
3222 retval = -EINVAL;
3223 }
3224 mutex_unlock(&devc->mix_mutex);
3225 return retval;
3226}
3227
3228static const struct file_operations vwsnd_mixer_fops = {
3229 .owner = THIS_MODULE,
3230 .llseek = no_llseek,
3231 .ioctl = vwsnd_mixer_ioctl,
3232 .open = vwsnd_mixer_open,
3233 .release = vwsnd_mixer_release,
3234};
3235
3236
3237
3238
3239
3240
3241static int __init probe_vwsnd(struct address_info *hw_config)
3242{
3243 lithium_t lith;
3244 int w;
3245 unsigned long later;
3246
3247 DBGEV("(hw_config=0x%p)\n", hw_config);
3248
3249
3250
3251 if (li_create(&lith, hw_config->io_base) != 0) {
3252 printk(KERN_WARNING "probe_vwsnd: can't map lithium\n");
3253 return 0;
3254 }
3255 later = jiffies + 2;
3256 li_writel(&lith, LI_HOST_CONTROLLER, LI_HC_LINK_ENABLE);
3257 do {
3258 w = li_readl(&lith, LI_HOST_CONTROLLER);
3259 } while (w == LI_HC_LINK_ENABLE && time_before(jiffies, later));
3260
3261 li_destroy(&lith);
3262
3263 DBGPV("HC = 0x%04x\n", w);
3264
3265 if ((w == LI_HC_LINK_ENABLE) || (w & LI_HC_LINK_CODEC)) {
3266
3267
3268
3269
3270
3271 printk(KERN_WARNING "probe_vwsnd: audio codec not found\n");
3272 return 0;
3273 }
3274
3275 if (w & LI_HC_LINK_FAILURE) {
3276 printk(KERN_WARNING "probe_vwsnd: can't init audio codec\n");
3277 return 0;
3278 }
3279
3280 printk(KERN_INFO "vwsnd: lithium audio at mmio %#x irq %d\n",
3281 hw_config->io_base, hw_config->irq);
3282
3283 return 1;
3284}
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294static int __init attach_vwsnd(struct address_info *hw_config)
3295{
3296 vwsnd_dev_t *devc = NULL;
3297 int err = -ENOMEM;
3298
3299 DBGEV("(hw_config=0x%p)\n", hw_config);
3300
3301 devc = kmalloc(sizeof (vwsnd_dev_t), GFP_KERNEL);
3302 if (devc == NULL)
3303 goto fail0;
3304
3305 err = li_create(&devc->lith, hw_config->io_base);
3306 if (err)
3307 goto fail1;
3308
3309 init_waitqueue_head(&devc->open_wait);
3310
3311 devc->rport.hwbuf_size = HWBUF_SIZE;
3312 devc->rport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
3313 if (!devc->rport.hwbuf_vaddr)
3314 goto fail2;
3315 devc->rport.hwbuf = (void *) devc->rport.hwbuf_vaddr;
3316 devc->rport.hwbuf_paddr = virt_to_phys(devc->rport.hwbuf);
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331 li_writel(&devc->lith, LI_COMM1_BASE,
3332 devc->rport.hwbuf_paddr >> 8 | 1 << (37 - 8));
3333
3334 devc->wport.hwbuf_size = HWBUF_SIZE;
3335 devc->wport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
3336 if (!devc->wport.hwbuf_vaddr)
3337 goto fail3;
3338 devc->wport.hwbuf = (void *) devc->wport.hwbuf_vaddr;
3339 devc->wport.hwbuf_paddr = virt_to_phys(devc->wport.hwbuf);
3340 DBGP("wport hwbuf = 0x%p\n", devc->wport.hwbuf);
3341
3342 DBGDO(shut_up++);
3343 err = ad1843_init(&devc->lith);
3344 DBGDO(shut_up--);
3345 if (err)
3346 goto fail4;
3347
3348
3349
3350 err = request_irq(hw_config->irq, vwsnd_audio_intr, 0, "vwsnd", devc);
3351 if (err)
3352 goto fail5;
3353
3354
3355
3356 devc->audio_minor = register_sound_dsp(&vwsnd_audio_fops, -1);
3357 if ((err = devc->audio_minor) < 0) {
3358 DBGDO(printk(KERN_WARNING
3359 "attach_vwsnd: register_sound_dsp error %d\n",
3360 err));
3361 goto fail6;
3362 }
3363 devc->mixer_minor = register_sound_mixer(&vwsnd_mixer_fops,
3364 devc->audio_minor >> 4);
3365 if ((err = devc->mixer_minor) < 0) {
3366 DBGDO(printk(KERN_WARNING
3367 "attach_vwsnd: register_sound_mixer error %d\n",
3368 err));
3369 goto fail7;
3370 }
3371
3372
3373
3374 hw_config->slots[0] = devc->audio_minor;
3375
3376
3377
3378 mutex_init(&devc->open_mutex);
3379 mutex_init(&devc->io_mutex);
3380 mutex_init(&devc->mix_mutex);
3381 devc->open_mode = 0;
3382 spin_lock_init(&devc->rport.lock);
3383 init_waitqueue_head(&devc->rport.queue);
3384 devc->rport.swstate = SW_OFF;
3385 devc->rport.hwstate = HW_STOPPED;
3386 devc->rport.flags = 0;
3387 devc->rport.swbuf = NULL;
3388 spin_lock_init(&devc->wport.lock);
3389 init_waitqueue_head(&devc->wport.queue);
3390 devc->wport.swstate = SW_OFF;
3391 devc->wport.hwstate = HW_STOPPED;
3392 devc->wport.flags = 0;
3393 devc->wport.swbuf = NULL;
3394
3395
3396
3397 devc->next_dev = vwsnd_dev_list;
3398 vwsnd_dev_list = devc;
3399 return devc->audio_minor;
3400
3401
3402
3403 fail7:
3404 unregister_sound_dsp(devc->audio_minor);
3405 fail6:
3406 free_irq(hw_config->irq, devc);
3407 fail5:
3408 fail4:
3409 free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER);
3410 fail3:
3411 free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER);
3412 fail2:
3413 li_destroy(&devc->lith);
3414 fail1:
3415 kfree(devc);
3416 fail0:
3417 return err;
3418}
3419
3420static int __exit unload_vwsnd(struct address_info *hw_config)
3421{
3422 vwsnd_dev_t *devc, **devcp;
3423
3424 DBGE("()\n");
3425
3426 devcp = &vwsnd_dev_list;
3427 while ((devc = *devcp)) {
3428 if (devc->audio_minor == hw_config->slots[0]) {
3429 *devcp = devc->next_dev;
3430 break;
3431 }
3432 devcp = &devc->next_dev;
3433 }
3434
3435 if (!devc)
3436 return -ENODEV;
3437
3438 unregister_sound_mixer(devc->mixer_minor);
3439 unregister_sound_dsp(devc->audio_minor);
3440 free_irq(hw_config->irq, devc);
3441 free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER);
3442 free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER);
3443 li_destroy(&devc->lith);
3444 kfree(devc);
3445
3446 return 0;
3447}
3448
3449
3450
3451
3452static struct address_info the_hw_config = {
3453 0xFF001000,
3454 CO_IRQ(CO_APIC_LI_AUDIO)
3455};
3456
3457MODULE_DESCRIPTION("SGI Visual Workstation sound module");
3458MODULE_AUTHOR("Bob Miller <kbob@sgi.com>");
3459MODULE_LICENSE("GPL");
3460
3461static int __init init_vwsnd(void)
3462{
3463 int err;
3464
3465 DBGXV("\n");
3466 DBGXV("sound::vwsnd::init_module()\n");
3467
3468 if (!probe_vwsnd(&the_hw_config))
3469 return -ENODEV;
3470
3471 err = attach_vwsnd(&the_hw_config);
3472 if (err < 0)
3473 return err;
3474 return 0;
3475}
3476
3477static void __exit cleanup_vwsnd(void)
3478{
3479 DBGX("sound::vwsnd::cleanup_module()\n");
3480
3481 unload_vwsnd(&the_hw_config);
3482}
3483
3484module_init(init_vwsnd);
3485module_exit(cleanup_vwsnd);
3486