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