1*433d6423SLionel Sambuc #include "codec.h"
2*433d6423SLionel Sambuc
3*433d6423SLionel Sambuc
4*433d6423SLionel Sambuc /* Timeouts in milliseconds */
5*433d6423SLionel Sambuc #define WIP_TIMEOUT 250UL
6*433d6423SLionel Sambuc #define DRDY_TIMEOUT 250UL
7*433d6423SLionel Sambuc
8*433d6423SLionel Sambuc /* The default SRC syncronization state number is 1. This state occurs
9*433d6423SLionel Sambuc just after de-assertion of SYNC. This is supposed to be the safest
10*433d6423SLionel Sambuc state for accessing the codec with an ES1371 Rev 1. Later versions
11*433d6423SLionel Sambuc of the chip allegedly don't require syncronization. Be very careful
12*433d6423SLionel Sambuc if you change this ! */
13*433d6423SLionel Sambuc
14*433d6423SLionel Sambuc #define SRC_UNSYNCED 0xffffffffUL
15*433d6423SLionel Sambuc static u32_t SrcSyncState = 0x00010000UL;
16*433d6423SLionel Sambuc
17*433d6423SLionel Sambuc
CodecSetSrcSyncState(int state)18*433d6423SLionel Sambuc void CodecSetSrcSyncState (int state)
19*433d6423SLionel Sambuc {
20*433d6423SLionel Sambuc if (state < 0)
21*433d6423SLionel Sambuc SrcSyncState = SRC_UNSYNCED;
22*433d6423SLionel Sambuc else {
23*433d6423SLionel Sambuc SrcSyncState = (u32_t)state << 16;
24*433d6423SLionel Sambuc SrcSyncState &= 0x00070000Ul;
25*433d6423SLionel Sambuc }
26*433d6423SLionel Sambuc }
27*433d6423SLionel Sambuc
28*433d6423SLionel Sambuc
CodecWrite(DEV_STRUCT * pCC,u16_t wAddr,u16_t wData)29*433d6423SLionel Sambuc int CodecWrite (DEV_STRUCT * pCC, u16_t wAddr, u16_t wData)
30*433d6423SLionel Sambuc {
31*433d6423SLionel Sambuc u32_t dtemp, i;
32*433d6423SLionel Sambuc u16_t wBaseAddr = pCC->base;
33*433d6423SLionel Sambuc
34*433d6423SLionel Sambuc /* wait for WIP bit (Write In Progress) to go away */
35*433d6423SLionel Sambuc /* remember, register CONC_dCODECCTL_OFF (0x14)
36*433d6423SLionel Sambuc is a pseudo read-write register */
37*433d6423SLionel Sambuc if (WaitBitd (wBaseAddr + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT)){
38*433d6423SLionel Sambuc printf("CODEC_ERR_WIP_TIMEOUT\n");
39*433d6423SLionel Sambuc return (CODEC_ERR_WIP_TIMEOUT);
40*433d6423SLionel Sambuc }
41*433d6423SLionel Sambuc if (SRC_UNSYNCED != SrcSyncState)
42*433d6423SLionel Sambuc {
43*433d6423SLionel Sambuc /* enable SRC state data in SRC mux */
44*433d6423SLionel Sambuc if (WaitBitd (wBaseAddr + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
45*433d6423SLionel Sambuc return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
46*433d6423SLionel Sambuc
47*433d6423SLionel Sambuc /* todo: why are we writing an undefined register? */
48*433d6423SLionel Sambuc dtemp = pci_inl(wBaseAddr + CONC_dSRCIO_OFF);
49*433d6423SLionel Sambuc pci_outl(wBaseAddr + CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) |
50*433d6423SLionel Sambuc 0x00010000UL);
51*433d6423SLionel Sambuc
52*433d6423SLionel Sambuc /* wait for a SAFE time to write addr/data and then do it */
53*433d6423SLionel Sambuc /*_disable(); */
54*433d6423SLionel Sambuc for( i = 0; i < 0x1000UL; ++i )
55*433d6423SLionel Sambuc if( (pci_inl(wBaseAddr + CONC_dSRCIO_OFF) & 0x00070000UL) ==
56*433d6423SLionel Sambuc SrcSyncState )
57*433d6423SLionel Sambuc break;
58*433d6423SLionel Sambuc
59*433d6423SLionel Sambuc if (i >= 0x1000UL) {
60*433d6423SLionel Sambuc /* _enable(); */
61*433d6423SLionel Sambuc return (CODEC_ERR_SRC_SYNC_TIMEOUT);
62*433d6423SLionel Sambuc }
63*433d6423SLionel Sambuc }
64*433d6423SLionel Sambuc
65*433d6423SLionel Sambuc /* A test for 5880 - prime the PCI data bus */
66*433d6423SLionel Sambuc {
67*433d6423SLionel Sambuc u32_t dat = ((u32_t) wAddr << 16) | wData;
68*433d6423SLionel Sambuc char page = pci_inb(wBaseAddr + CONC_bMEMPAGE_OFF);
69*433d6423SLionel Sambuc
70*433d6423SLionel Sambuc pci_outl (wBaseAddr + CONC_bMEMPAGE_OFF, dat);
71*433d6423SLionel Sambuc
72*433d6423SLionel Sambuc /* write addr and data */
73*433d6423SLionel Sambuc pci_outl(wBaseAddr + CONC_dCODECCTL_OFF, dat);
74*433d6423SLionel Sambuc
75*433d6423SLionel Sambuc pci_outb(wBaseAddr + CONC_bMEMPAGE_OFF, page); /* restore page reg */
76*433d6423SLionel Sambuc }
77*433d6423SLionel Sambuc
78*433d6423SLionel Sambuc if (SRC_UNSYNCED != SrcSyncState)
79*433d6423SLionel Sambuc {
80*433d6423SLionel Sambuc /* _enable(); */
81*433d6423SLionel Sambuc
82*433d6423SLionel Sambuc /* restore SRC reg */
83*433d6423SLionel Sambuc if (WaitBitd (wBaseAddr + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
84*433d6423SLionel Sambuc return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
85*433d6423SLionel Sambuc
86*433d6423SLionel Sambuc pci_outl(wBaseAddr + CONC_dSRCIO_OFF, dtemp & 0xfff8ffffUL);
87*433d6423SLionel Sambuc }
88*433d6423SLionel Sambuc
89*433d6423SLionel Sambuc return 0;
90*433d6423SLionel Sambuc }
91*433d6423SLionel Sambuc
CodecRead(DEV_STRUCT * pCC,u16_t wAddr,u16_t * data)92*433d6423SLionel Sambuc int CodecRead (DEV_STRUCT * pCC, u16_t wAddr, u16_t *data)
93*433d6423SLionel Sambuc {
94*433d6423SLionel Sambuc u32_t dtemp, i;
95*433d6423SLionel Sambuc u16_t base = pCC->base;
96*433d6423SLionel Sambuc
97*433d6423SLionel Sambuc /* wait for WIP to go away */
98*433d6423SLionel Sambuc if (WaitBitd (base + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT))
99*433d6423SLionel Sambuc return (CODEC_ERR_WIP_TIMEOUT);
100*433d6423SLionel Sambuc
101*433d6423SLionel Sambuc if (SRC_UNSYNCED != SrcSyncState)
102*433d6423SLionel Sambuc {
103*433d6423SLionel Sambuc /* enable SRC state data in SRC mux */
104*433d6423SLionel Sambuc if (WaitBitd (base + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
105*433d6423SLionel Sambuc return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
106*433d6423SLionel Sambuc
107*433d6423SLionel Sambuc dtemp = pci_inl(base + CONC_dSRCIO_OFF);
108*433d6423SLionel Sambuc pci_outl(base + CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) |
109*433d6423SLionel Sambuc 0x00010000UL);
110*433d6423SLionel Sambuc
111*433d6423SLionel Sambuc /* wait for a SAFE time to write a read request and then do it */
112*433d6423SLionel Sambuc /* todo: how do we solve the lock() problem? */
113*433d6423SLionel Sambuc /* _disable(); */
114*433d6423SLionel Sambuc for( i = 0; i < 0x1000UL; ++i )
115*433d6423SLionel Sambuc if( (pci_inl(base + CONC_dSRCIO_OFF) & 0x00070000UL) ==
116*433d6423SLionel Sambuc SrcSyncState )
117*433d6423SLionel Sambuc break;
118*433d6423SLionel Sambuc
119*433d6423SLionel Sambuc if (i >= 0x1000UL) {
120*433d6423SLionel Sambuc /*_enable();*/
121*433d6423SLionel Sambuc return (CODEC_ERR_SRC_SYNC_TIMEOUT);
122*433d6423SLionel Sambuc }
123*433d6423SLionel Sambuc }
124*433d6423SLionel Sambuc
125*433d6423SLionel Sambuc /* A test for 5880 - prime the PCI data bus */
126*433d6423SLionel Sambuc {
127*433d6423SLionel Sambuc /* set bit 23, this means read in stead of write. */
128*433d6423SLionel Sambuc u32_t dat = ((u32_t) wAddr << 16) | (1UL << 23);
129*433d6423SLionel Sambuc char page = pci_inb(base + CONC_bMEMPAGE_OFF);
130*433d6423SLionel Sambuc
131*433d6423SLionel Sambuc /* todo: why are we putting data in the mem page register??? */
132*433d6423SLionel Sambuc pci_outl(base + CONC_bMEMPAGE_OFF, dat);
133*433d6423SLionel Sambuc
134*433d6423SLionel Sambuc /* write addr w/data=0 and assert read request */
135*433d6423SLionel Sambuc pci_outl(base + CONC_dCODECCTL_OFF, dat);
136*433d6423SLionel Sambuc
137*433d6423SLionel Sambuc pci_outb(base + CONC_bMEMPAGE_OFF, page); /* restore page reg */
138*433d6423SLionel Sambuc
139*433d6423SLionel Sambuc }
140*433d6423SLionel Sambuc if (SRC_UNSYNCED != SrcSyncState)
141*433d6423SLionel Sambuc {
142*433d6423SLionel Sambuc
143*433d6423SLionel Sambuc /*_enable();*/
144*433d6423SLionel Sambuc
145*433d6423SLionel Sambuc /* restore SRC reg */
146*433d6423SLionel Sambuc if (WaitBitd (base + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
147*433d6423SLionel Sambuc return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
148*433d6423SLionel Sambuc
149*433d6423SLionel Sambuc pci_outl(base + CONC_dSRCIO_OFF, dtemp & 0xfff8ffffUL);
150*433d6423SLionel Sambuc }
151*433d6423SLionel Sambuc
152*433d6423SLionel Sambuc /* now wait for the stinkin' data (DRDY = data ready) */
153*433d6423SLionel Sambuc if (WaitBitd (base + CONC_dCODECCTL_OFF, 31, 1, DRDY_TIMEOUT))
154*433d6423SLionel Sambuc return (CODEC_ERR_DATA_TIMEOUT);
155*433d6423SLionel Sambuc
156*433d6423SLionel Sambuc dtemp = pci_inl(base + CONC_dCODECCTL_OFF);
157*433d6423SLionel Sambuc
158*433d6423SLionel Sambuc if (data)
159*433d6423SLionel Sambuc *data = (u16_t) dtemp;
160*433d6423SLionel Sambuc
161*433d6423SLionel Sambuc return 0;
162*433d6423SLionel Sambuc }
163*433d6423SLionel Sambuc
164*433d6423SLionel Sambuc
CodecWriteUnsynced(DEV_STRUCT * pCC,u16_t wAddr,u16_t wData)165*433d6423SLionel Sambuc int CodecWriteUnsynced (DEV_STRUCT * pCC, u16_t wAddr, u16_t wData)
166*433d6423SLionel Sambuc {
167*433d6423SLionel Sambuc /* wait for WIP to go away */
168*433d6423SLionel Sambuc if (WaitBitd (pCC->base + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT))
169*433d6423SLionel Sambuc return (CODEC_ERR_WIP_TIMEOUT);
170*433d6423SLionel Sambuc
171*433d6423SLionel Sambuc /* write addr and data */
172*433d6423SLionel Sambuc pci_outl(pCC->base + CONC_dCODECCTL_OFF, ((u32_t) wAddr << 16) | wData);
173*433d6423SLionel Sambuc return 0;
174*433d6423SLionel Sambuc }
175*433d6423SLionel Sambuc
176*433d6423SLionel Sambuc
CodecReadUnsynced(DEV_STRUCT * pCC,u16_t wAddr,u16_t * data)177*433d6423SLionel Sambuc int CodecReadUnsynced (DEV_STRUCT * pCC, u16_t wAddr, u16_t *data)
178*433d6423SLionel Sambuc {
179*433d6423SLionel Sambuc u32_t dtemp;
180*433d6423SLionel Sambuc
181*433d6423SLionel Sambuc /* wait for WIP to go away */
182*433d6423SLionel Sambuc if (WaitBitd (pCC->base + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT))
183*433d6423SLionel Sambuc return (CODEC_ERR_WIP_TIMEOUT);
184*433d6423SLionel Sambuc
185*433d6423SLionel Sambuc /* write addr w/data=0 and assert read request */
186*433d6423SLionel Sambuc pci_outl(pCC->base + CONC_dCODECCTL_OFF, ((u32_t) wAddr << 16) | (1UL << 23));
187*433d6423SLionel Sambuc
188*433d6423SLionel Sambuc /* now wait for the stinkin' data (RDY) */
189*433d6423SLionel Sambuc if (WaitBitd (pCC->base + CONC_dCODECCTL_OFF, 31, 1, DRDY_TIMEOUT))
190*433d6423SLionel Sambuc return (CODEC_ERR_DATA_TIMEOUT);
191*433d6423SLionel Sambuc
192*433d6423SLionel Sambuc dtemp = pci_inl(pCC->base + CONC_dCODECCTL_OFF);
193*433d6423SLionel Sambuc
194*433d6423SLionel Sambuc if (data)
195*433d6423SLionel Sambuc *data = (u16_t) dtemp;
196*433d6423SLionel Sambuc
197*433d6423SLionel Sambuc return 0;
198*433d6423SLionel Sambuc }
199*433d6423SLionel Sambuc
CODECInit(DEV_STRUCT * pCC)200*433d6423SLionel Sambuc int CODECInit( DEV_STRUCT * pCC )
201*433d6423SLionel Sambuc {
202*433d6423SLionel Sambuc int retVal;
203*433d6423SLionel Sambuc /* All powerdown modes: off */
204*433d6423SLionel Sambuc
205*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_POWERDOWN_CONTROL_STAT, 0x0000U);
206*433d6423SLionel Sambuc if (OK != retVal)
207*433d6423SLionel Sambuc return (retVal);
208*433d6423SLionel Sambuc
209*433d6423SLionel Sambuc /* Mute Line Out & set to 0dB attenuation */
210*433d6423SLionel Sambuc
211*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_MASTER_VOLUME, 0x0000U);
212*433d6423SLionel Sambuc if (OK != retVal)
213*433d6423SLionel Sambuc return (retVal);
214*433d6423SLionel Sambuc
215*433d6423SLionel Sambuc
216*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_MONO_VOLUME, 0x8000U);
217*433d6423SLionel Sambuc if (OK != retVal)
218*433d6423SLionel Sambuc return (retVal);
219*433d6423SLionel Sambuc
220*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_PHONE_VOLUME, 0x8008U);
221*433d6423SLionel Sambuc if (OK != retVal)
222*433d6423SLionel Sambuc return (retVal);
223*433d6423SLionel Sambuc
224*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_MIC_VOLUME, 0x0008U);
225*433d6423SLionel Sambuc if (OK != retVal)
226*433d6423SLionel Sambuc return (retVal);
227*433d6423SLionel Sambuc
228*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_LINE_IN_VOLUME, 0x0808U);
229*433d6423SLionel Sambuc if (OK != retVal)
230*433d6423SLionel Sambuc return (retVal);
231*433d6423SLionel Sambuc
232*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_CD_VOLUME, 0x0808U);
233*433d6423SLionel Sambuc if (OK != retVal)
234*433d6423SLionel Sambuc return (retVal);
235*433d6423SLionel Sambuc
236*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_AUX_IN_VOLUME, 0x0808U);
237*433d6423SLionel Sambuc if (OK != retVal)
238*433d6423SLionel Sambuc return (retVal);
239*433d6423SLionel Sambuc
240*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_PCM_OUT_VOLUME, 0x0808U);
241*433d6423SLionel Sambuc if (OK != retVal)
242*433d6423SLionel Sambuc return (retVal);
243*433d6423SLionel Sambuc
244*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_RECORD_GAIN_VOLUME, 0x0000U);
245*433d6423SLionel Sambuc if (OK != retVal)
246*433d6423SLionel Sambuc return (retVal);
247*433d6423SLionel Sambuc
248*433d6423SLionel Sambuc /* Connect Line In to ADC */
249*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_RECORD_SELECT, 0x0404U);
250*433d6423SLionel Sambuc if (OK != retVal)
251*433d6423SLionel Sambuc return (retVal);
252*433d6423SLionel Sambuc
253*433d6423SLionel Sambuc retVal = CodecWrite (pCC, AC97_GENERAL_PURPOSE, 0x0000U);
254*433d6423SLionel Sambuc if (OK != retVal)
255*433d6423SLionel Sambuc return (retVal);
256*433d6423SLionel Sambuc
257*433d6423SLionel Sambuc return OK;
258*433d6423SLionel Sambuc }
259*433d6423SLionel Sambuc
260*433d6423SLionel Sambuc
261*433d6423SLionel Sambuc
262*433d6423SLionel Sambuc
263*433d6423SLionel Sambuc
264*433d6423SLionel Sambuc
265