1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
|
#include "codec.h"
/* Timeouts in milliseconds */
#define WIP_TIMEOUT 250UL
#define DRDY_TIMEOUT 250UL
/* The default SRC syncronization state number is 1. This state occurs
just after de-assertion of SYNC. This is supposed to be the safest
state for accessing the codec with an ES1371 Rev 1. Later versions
of the chip allegedly don't require syncronization. Be very careful
if you change this ! */
#define SRC_UNSYNCED 0xffffffffUL
static u32_t SrcSyncState = 0x00010000UL;
void CodecSetSrcSyncState (int state)
{
if (state < 0)
SrcSyncState = SRC_UNSYNCED;
else {
SrcSyncState = (u32_t)state << 16;
SrcSyncState &= 0x00070000Ul;
}
}
int CodecWrite (DEV_STRUCT * pCC, u16_t wAddr, u16_t wData)
{
u32_t dtemp, i;
u16_t wBaseAddr = pCC->base;
/* wait for WIP bit (Write In Progress) to go away */
/* remember, register CONC_dCODECCTL_OFF (0x14)
is a pseudo read-write register */
if (WaitBitd (wBaseAddr + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT)){
printf("CODEC_ERR_WIP_TIMEOUT\n");
return (CODEC_ERR_WIP_TIMEOUT);
}
if (SRC_UNSYNCED != SrcSyncState)
{
/* enable SRC state data in SRC mux */
if (WaitBitd (wBaseAddr + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
/* todo: why are we writing an undefined register? */
dtemp = pci_inl(wBaseAddr + CONC_dSRCIO_OFF);
pci_outl(wBaseAddr + CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) |
0x00010000UL);
/* wait for a SAFE time to write addr/data and then do it */
/*_disable(); */
for( i = 0; i < 0x1000UL; ++i )
if( (pci_inl(wBaseAddr + CONC_dSRCIO_OFF) & 0x00070000UL) ==
SrcSyncState )
break;
if (i >= 0x1000UL) {
/* _enable(); */
return (CODEC_ERR_SRC_SYNC_TIMEOUT);
}
}
/* A test for 5880 - prime the PCI data bus */
{
u32_t dat = ((u32_t) wAddr << 16) | wData;
char page = pci_inb(wBaseAddr + CONC_bMEMPAGE_OFF);
pci_outl (wBaseAddr + CONC_bMEMPAGE_OFF, dat);
/* write addr and data */
pci_outl(wBaseAddr + CONC_dCODECCTL_OFF, dat);
pci_outb(wBaseAddr + CONC_bMEMPAGE_OFF, page); /* restore page reg */
}
if (SRC_UNSYNCED != SrcSyncState)
{
/* _enable(); */
/* restore SRC reg */
if (WaitBitd (wBaseAddr + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
pci_outl(wBaseAddr + CONC_dSRCIO_OFF, dtemp & 0xfff8ffffUL);
}
return 0;
}
int CodecRead (DEV_STRUCT * pCC, u16_t wAddr, u16_t *data)
{
u32_t dtemp, i;
u16_t base = pCC->base;
/* wait for WIP to go away */
if (WaitBitd (base + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT))
return (CODEC_ERR_WIP_TIMEOUT);
if (SRC_UNSYNCED != SrcSyncState)
{
/* enable SRC state data in SRC mux */
if (WaitBitd (base + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
dtemp = pci_inl(base + CONC_dSRCIO_OFF);
pci_outl(base + CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) |
0x00010000UL);
/* wait for a SAFE time to write a read request and then do it */
/* todo: how do we solve the lock() problem? */
/* _disable(); */
for( i = 0; i < 0x1000UL; ++i )
if( (pci_inl(base + CONC_dSRCIO_OFF) & 0x00070000UL) ==
SrcSyncState )
break;
if (i >= 0x1000UL) {
/*_enable();*/
return (CODEC_ERR_SRC_SYNC_TIMEOUT);
}
}
/* A test for 5880 - prime the PCI data bus */
{
/* set bit 23, this means read in stead of write. */
u32_t dat = ((u32_t) wAddr << 16) | (1UL << 23);
char page = pci_inb(base + CONC_bMEMPAGE_OFF);
/* todo: why are we putting data in the mem page register??? */
pci_outl(base + CONC_bMEMPAGE_OFF, dat);
/* write addr w/data=0 and assert read request */
pci_outl(base + CONC_dCODECCTL_OFF, dat);
pci_outb(base + CONC_bMEMPAGE_OFF, page); /* restore page reg */
}
if (SRC_UNSYNCED != SrcSyncState)
{
/*_enable();*/
/* restore SRC reg */
if (WaitBitd (base + CONC_dSRCIO_OFF, SRC_BUSY_BIT, 0, 1000))
return (CODEC_ERR_SRC_NOT_BUSY_TIMEOUT);
pci_outl(base + CONC_dSRCIO_OFF, dtemp & 0xfff8ffffUL);
}
/* now wait for the stinkin' data (DRDY = data ready) */
if (WaitBitd (base + CONC_dCODECCTL_OFF, 31, 1, DRDY_TIMEOUT))
return (CODEC_ERR_DATA_TIMEOUT);
dtemp = pci_inl(base + CONC_dCODECCTL_OFF);
if (data)
*data = (u16_t) dtemp;
return 0;
}
int CodecWriteUnsynced (DEV_STRUCT * pCC, u16_t wAddr, u16_t wData)
{
/* wait for WIP to go away */
if (WaitBitd (pCC->base + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT))
return (CODEC_ERR_WIP_TIMEOUT);
/* write addr and data */
pci_outl(pCC->base + CONC_dCODECCTL_OFF, ((u32_t) wAddr << 16) | wData);
return 0;
}
int CodecReadUnsynced (DEV_STRUCT * pCC, u16_t wAddr, u16_t *data)
{
u32_t dtemp;
/* wait for WIP to go away */
if (WaitBitd (pCC->base + CONC_dCODECCTL_OFF, 30, 0, WIP_TIMEOUT))
return (CODEC_ERR_WIP_TIMEOUT);
/* write addr w/data=0 and assert read request */
pci_outl(pCC->base + CONC_dCODECCTL_OFF, ((u32_t) wAddr << 16) | (1UL << 23));
/* now wait for the stinkin' data (RDY) */
if (WaitBitd (pCC->base + CONC_dCODECCTL_OFF, 31, 1, DRDY_TIMEOUT))
return (CODEC_ERR_DATA_TIMEOUT);
dtemp = pci_inl(pCC->base + CONC_dCODECCTL_OFF);
if (data)
*data = (u16_t) dtemp;
return 0;
}
int CODECInit( DEV_STRUCT * pCC )
{
int retVal;
/* All powerdown modes: off */
retVal = CodecWrite (pCC, AC97_POWERDOWN_CONTROL_STAT, 0x0000U);
if (OK != retVal)
return (retVal);
/* Mute Line Out & set to 0dB attenuation */
retVal = CodecWrite (pCC, AC97_MASTER_VOLUME, 0x0000U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_MONO_VOLUME, 0x8000U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_PHONE_VOLUME, 0x8008U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_MIC_VOLUME, 0x0008U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_LINE_IN_VOLUME, 0x0808U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_CD_VOLUME, 0x0808U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_AUX_IN_VOLUME, 0x0808U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_PCM_OUT_VOLUME, 0x0808U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_RECORD_GAIN_VOLUME, 0x0000U);
if (OK != retVal)
return (retVal);
/* Connect Line In to ADC */
retVal = CodecWrite (pCC, AC97_RECORD_SELECT, 0x0404U);
if (OK != retVal)
return (retVal);
retVal = CodecWrite (pCC, AC97_GENERAL_PURPOSE, 0x0000U);
if (OK != retVal)
return (retVal);
return OK;
}
|