xref: /minix3/minix/drivers/audio/es1371/SRC.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 #include "SRC.h"
2 
3 #define SRC_RATE        48000U
4 #define reg(n) DSP->base + n
5 
6 
SRCInit(DEV_STRUCT * DSP)7 int SRCInit ( DEV_STRUCT * DSP )
8 {
9     u32_t   i;
10     int     retVal;
11 
12     /* Clear all SRC RAM then init - keep SRC disabled until done */
13     if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
14         return (SRC_ERR_NOT_BUSY_TIMEOUT);
15 
16     pci_outl(reg(CONC_dSRCIO_OFF), SRC_DISABLE);
17 
18     for( i = 0; i < 0x80; ++i )
19         if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, (u16_t)i, 0U)))
20             return (retVal);
21 
22     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_BASE + SRC_TRUNC_N_OFF, 16 << 4)))
23         return (retVal);
24     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_BASE + SRC_INT_REGS_OFF, 16 << 10)))
25         return (retVal);
26     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_BASE + SRC_TRUNC_N_OFF, 16 << 4)))
27         return (retVal);
28     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_BASE + SRC_INT_REGS_OFF, 16 << 10)))
29         return (retVal);
30     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_LVOL, 1 << 12)))
31         return (retVal);
32     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_RVOL, 1 << 12)))
33         return (retVal);
34     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_LVOL, 1 << 12)))
35         return (retVal);
36     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_RVOL, 1 << 12)))
37         return (retVal);
38     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_ADC_LVOL, 1 << 12)))
39         return (retVal);
40     if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_ADC_RVOL, 1 << 12)))
41         return (retVal);
42 
43     /* default some rates */
44     SRCSetRate(DSP, SRC_SYNTH_BASE, SRC_RATE);
45     SRCSetRate(DSP, SRC_DAC_BASE,   SRC_RATE);
46     SRCSetRate(DSP, SRC_ADC_BASE,   SRC_RATE);
47 
48     /* now enable the whole deal */
49     if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
50         return (SRC_ERR_NOT_BUSY_TIMEOUT);
51 
52     pci_outl(reg(CONC_dSRCIO_OFF), 0UL);
53 
54     return 0;
55 }
56 
57 
SRCRegRead(DEV_STRUCT * DSP,u16_t reg,u16_t * data)58 int SRCRegRead(DEV_STRUCT * DSP, u16_t reg, u16_t *data)
59 {
60     u32_t dtemp;
61 
62     /* wait for ready */
63     if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
64         return (SRC_ERR_NOT_BUSY_TIMEOUT);
65 
66     dtemp = pci_inl(reg(CONC_dSRCIO_OFF));
67 
68     /* assert a read request */
69     pci_outl(reg(CONC_dSRCIO_OFF),
70             (dtemp & SRC_CTLMASK) | ((u32_t) reg << 25));
71 
72     /* now wait for the data */
73     if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
74         return (SRC_ERR_NOT_BUSY_TIMEOUT);
75 
76     if (NULL != data)
77         *data = (u16_t) pci_inl(reg(CONC_dSRCIO_OFF));
78 
79     return 0;
80 }
81 
82 
SRCRegWrite(DEV_STRUCT * DSP,u16_t reg,u16_t val)83 int SRCRegWrite(DEV_STRUCT * DSP, u16_t reg, u16_t val)
84 {
85     u32_t dtemp;
86 
87 
88     /* wait for ready */
89     if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
90         return (SRC_ERR_NOT_BUSY_TIMEOUT);
91 
92     dtemp = pci_inl(reg(CONC_dSRCIO_OFF));
93 
94     /* assert the write request */
95     pci_outl(reg(CONC_dSRCIO_OFF),
96             (dtemp & SRC_CTLMASK) | SRC_WENABLE | ((u32_t) reg << 25) | val);
97 
98     return 0;
99 }
100 
101 
SRCSetRate(DEV_STRUCT * DSP,char base,u16_t rate)102 void SRCSetRate(DEV_STRUCT * DSP, char base, u16_t rate)
103 {
104   u32_t    freq, dtemp, i;
105   u16_t     N, truncM, truncStart, wtemp;
106 
107 
108   if( base != SRC_ADC_BASE )
109   {
110       /* freeze the channel */
111       dtemp = base == SRC_SYNTH_BASE ? SRC_SYNTHFREEZE : SRC_DACFREEZE;
112       for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
113           if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
114               break;
115       pci_outl(reg(CONC_dSRCIO_OFF),
116               (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) |
117               dtemp);
118 
119       /* calculate new frequency and write it - preserve accum */
120       /* please don't try to understand. */
121       freq = ((u32_t) rate << 16) / 3000U;
122       SRCRegRead(DSP, base + SRC_INT_REGS_OFF, &wtemp);
123 
124       SRCRegWrite(DSP, base + SRC_INT_REGS_OFF,
125               (wtemp & 0x00ffU) |
126               (u16_t) (freq >> 6) & 0xfc00);
127 
128       SRCRegWrite(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
129 
130       /* un-freeze the channel */
131       dtemp = base == SRC_SYNTH_BASE ? SRC_SYNTHFREEZE : SRC_DACFREEZE;
132       for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
133           if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
134               break;
135       pci_outl(reg(CONC_dSRCIO_OFF),
136               (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) &
137               ~dtemp);
138   }
139   else /* setting ADC rate */
140   {
141     /* freeze the channel */
142     for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
143         if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
144             break;
145     pci_outl(reg(CONC_dSRCIO_OFF),
146             (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) |
147             SRC_ADCFREEZE);
148 
149 
150 
151     /* derive oversample ratio */
152     N = rate/3000U;
153     if( N == 15 || N == 13 || N == 11 || N == 9 )
154         --N;
155     SRCRegWrite(DSP, SRC_ADC_LVOL, N << 8);
156     SRCRegWrite(DSP, SRC_ADC_RVOL, N << 8);
157 
158     /* truncate the filter and write n/trunc_start */
159     truncM = (21*N - 1) | 1;
160     if( rate >= 24000U )
161     {
162         if( truncM > 239 )
163             truncM = 239;
164         truncStart = (239 - truncM) >> 1;
165         SRCRegWrite(DSP, base + SRC_TRUNC_N_OFF,
166                 (truncStart << 9) | (N << 4));
167     }
168     else
169     {
170         if( truncM > 119 )
171             truncM = 119;
172         truncStart = (119 - truncM) >> 1;
173         SRCRegWrite(DSP, base + SRC_TRUNC_N_OFF,
174                 0x8000U | (truncStart << 9) | (N << 4));
175     }
176 
177     /* calculate new frequency and write it - preserve accum */
178     freq = ((48000UL << 16) / rate) * N;
179     SRCRegRead(DSP, base + SRC_INT_REGS_OFF, &wtemp);
180     SRCRegWrite(DSP, base + SRC_INT_REGS_OFF,
181             (wtemp & 0x00ffU) |
182             (u16_t) (freq >> 6) & 0xfc00);
183     SRCRegWrite(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
184 
185     /* un-freeze the channel */
186     for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
187         if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
188             break;
189     pci_outl(reg(CONC_dSRCIO_OFF),
190             (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) &
191             ~SRC_ADCFREEZE);
192   }
193   return;
194 }
195 
196 
197