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