xref: /minix/minix/drivers/audio/es1371/AC97.c (revision 83133719)
1 #include "AC97.h"
2 
3 
4 
5 
6 
7 /* AC97 Mixer and Mode control function prototypes */
8 
9 static int AC97_write(const DEV_STRUCT * pCC, u16_t wAddr, u16_t
10 	wData);
11 static int AC97_write_unsynced(const DEV_STRUCT * pCC, u16_t wAddr,
12 	u16_t wData);
13 static int AC97_read_unsynced(const DEV_STRUCT * pCC, u16_t wAddr,
14 	u16_t *data);
15 static void set_nice_volume(void);
16 static int AC97_get_volume(struct volume_level *level);
17 static int AC97_set_volume(const struct volume_level *level);
18 
19 
20 
21 #define AC97_0DB_GAIN          0x0008
22 #define AC97_MAX_ATTN          0x003f
23 #define AC97_MUTE              0x8000U
24 
25 
26 /* Control function defines */
27 #define AC97_CTL_4SPKR         0x00U   /* 4-spkr output mode enable */
28 #define AC97_CTL_MICBOOST      0x01U   /* Mic boost (+30 dB) enable */
29 #define AC97_CTL_PWRDOWN       0x02U   /* power-down mode */
30 #define AC97_CTL_DOSMODE       0x03U   /* A/D sync to DAC1 */
31 
32                                                 /* Timeout waiting for: */
33 #define AC97_ERR_WIP_TIMEOUT           -1      /* write in progress complete */
34 #define AC97_ERR_DATA_TIMEOUT          -2      /* data ready */
35 #define AC97_ERR_SRC_NOT_BUSY_TIMEOUT  -3      /* SRC not busy */
36 #define AC97_ERR_SRC_SYNC_TIMEOUT      -4      /* state #1 */
37 
38 
39 
40 
41 
42 
43 /* Timeouts in milliseconds */
44 #define WIP_TIMEOUT     250UL
45 #define DRDY_TIMEOUT    250UL
46 
47 /* The default SRC syncronization state number is 1.  This state occurs
48    just after de-assertion of SYNC.  This is supposed to be the safest
49    state for accessing the codec with an ES1371 Rev 1.  Later versions
50    of the chip allegedly don't require syncronization.  Be very careful
51    if you change this ! */
52 
53 #define SRC_UNSYNCED 0xffffffffUL
54 static u32_t SrcSyncState = 0x00010000UL;
55 static DEV_STRUCT *dev;
56 
57 
58 #if 0
59 static void set_src_sync_state (int state)
60 {
61     if (state < 0)
62         SrcSyncState = SRC_UNSYNCED;
63     else {
64         SrcSyncState = (u32_t)state << 16;
65         SrcSyncState &= 0x00070000Ul;
66     }
67 }
68 #endif
69 
70 
71 static int AC97_write (const DEV_STRUCT * pCC, u16_t wAddr, u16_t wData)
72 {
73 u32_t dtemp, i;
74 u16_t  wBaseAddr = pCC->base;
75 
76     /* wait for WIP bit (Write In Progress) to go away */
77     /* remember, register CODEC_READ (0x14)
78        is a pseudo read-write register */
79     if (WaitBitd (wBaseAddr + CODEC_READ, 30, 0, WIP_TIMEOUT)){
80         printf("AC97_ERR_WIP_TIMEOUT\n");
81         return (AC97_ERR_WIP_TIMEOUT);
82     }
83     if (SRC_UNSYNCED != SrcSyncState)
84     {
85         /* enable SRC state data in SRC mux */
86         if (WaitBitd (wBaseAddr + SAMPLE_RATE_CONV, SRC_BUSY_BIT, 0, 1000))
87             return (AC97_ERR_SRC_NOT_BUSY_TIMEOUT);
88 
89         /* todo: why are we writing an undefined register? */
90         dtemp = pci_inl(wBaseAddr + SAMPLE_RATE_CONV);
91         pci_outl(wBaseAddr + SAMPLE_RATE_CONV, (dtemp & SRC_CTLMASK) |
92                 0x00010000UL);
93 
94         /* wait for a SAFE time to write addr/data and then do it */
95         /*_disable(); */
96         for( i = 0; i < 0x1000UL; ++i )
97             if( (pci_inl(wBaseAddr + SAMPLE_RATE_CONV) & 0x00070000UL) ==
98                     SrcSyncState )
99             break;
100 
101         if (i >= 0x1000UL) {
102             /* _enable(); */
103             return (AC97_ERR_SRC_SYNC_TIMEOUT);
104         }
105     }
106 
107     /* A test for 5880 - prime the PCI data bus */
108     {
109         u32_t dat = ((u32_t) wAddr << 16) | wData;
110         char page = pci_inb(wBaseAddr + MEM_PAGE);
111 
112         pci_outl (wBaseAddr + MEM_PAGE, dat);
113 
114         /* write addr and data */
115         pci_outl(wBaseAddr + CODEC_READ, dat);
116 
117         pci_outb(wBaseAddr + MEM_PAGE, page);  /* restore page reg */
118     }
119 
120     if (SRC_UNSYNCED != SrcSyncState)
121     {
122          /* _enable(); */
123 
124         /* restore SRC reg */
125         if (WaitBitd (wBaseAddr + SAMPLE_RATE_CONV, SRC_BUSY_BIT, 0, 1000))
126             return (AC97_ERR_SRC_NOT_BUSY_TIMEOUT);
127 
128         pci_outl(wBaseAddr + SAMPLE_RATE_CONV, dtemp & 0xfff8ffffUL);
129     }
130 
131     return 0;
132 }
133 
134 
135 #if 0
136 static int AC97_read (const DEV_STRUCT * pCC, u16_t wAddr, u16_t *data)
137 {
138 u32_t dtemp, i;
139 u16_t  base = pCC->base;
140 
141     /* wait for WIP to go away */
142     if (WaitBitd (base + CODEC_READ, 30, 0, WIP_TIMEOUT))
143         return (AC97_ERR_WIP_TIMEOUT);
144 
145     if (SRC_UNSYNCED != SrcSyncState)
146     {
147         /* enable SRC state data in SRC mux */
148         if (WaitBitd (base + SAMPLE_RATE_CONV, SRC_BUSY_BIT, 0, 1000))
149             return (AC97_ERR_SRC_NOT_BUSY_TIMEOUT);
150 
151         dtemp = pci_inl(base + SAMPLE_RATE_CONV);
152         pci_outl(base + SAMPLE_RATE_CONV, (dtemp & SRC_CTLMASK) |
153                 0x00010000UL);
154 
155         /* wait for a SAFE time to write a read request and then do it */
156         /* todo: how do we solve the lock() problem? */
157         /* _disable(); */
158         for( i = 0; i < 0x1000UL; ++i )
159             if( (pci_inl(base + SAMPLE_RATE_CONV) & 0x00070000UL) ==
160                     SrcSyncState )
161             break;
162 
163         if (i >= 0x1000UL) {
164             /*_enable();*/
165             return (AC97_ERR_SRC_SYNC_TIMEOUT);
166         }
167     }
168 
169     /* A test for 5880 - prime the PCI data bus */
170     {
171         /* set bit 23, this means read in stead of write. */
172         u32_t dat = ((u32_t) wAddr << 16) | (1UL << 23);
173         char page = pci_inb(base + MEM_PAGE);
174 
175         /* todo: why are we putting data in the mem page register??? */
176         pci_outl(base + MEM_PAGE, dat);
177 
178         /* write addr w/data=0 and assert read request */
179         pci_outl(base + CODEC_READ, dat);
180 
181         pci_outb(base + MEM_PAGE, page);  /* restore page reg */
182 
183     }
184     if (SRC_UNSYNCED != SrcSyncState)
185     {
186 
187         /*_enable();*/
188 
189         /* restore SRC reg */
190         if (WaitBitd (base + SAMPLE_RATE_CONV, SRC_BUSY_BIT, 0, 1000))
191             return (AC97_ERR_SRC_NOT_BUSY_TIMEOUT);
192 
193         pci_outl(base + SAMPLE_RATE_CONV, dtemp & 0xfff8ffffUL);
194     }
195 
196     /* now wait for the stinkin' data (DRDY = data ready) */
197     if (WaitBitd (base + CODEC_READ, 31, 1, DRDY_TIMEOUT))
198         return (AC97_ERR_DATA_TIMEOUT);
199 
200     dtemp = pci_inl(base + CODEC_READ);
201 
202     if (data)
203         *data = (u16_t) dtemp;
204 
205     return 0;
206 }
207 #endif
208 
209 
210 static int AC97_write_unsynced (const DEV_STRUCT * pCC, u16_t wAddr,
211     u16_t wData)
212 {
213     /* wait for WIP to go away */
214     if (WaitBitd (pCC->base + CODEC_READ, 30, 0, WIP_TIMEOUT))
215         return (AC97_ERR_WIP_TIMEOUT);
216 
217     /* write addr and data */
218     pci_outl(pCC->base + CODEC_READ, ((u32_t) wAddr << 16) | wData);
219     return 0;
220 }
221 
222 
223 static int AC97_read_unsynced (const DEV_STRUCT * pCC, u16_t wAddr,
224     u16_t *data)
225 {
226 u32_t dtemp;
227 
228     /* wait for WIP to go away */
229     if (WaitBitd (pCC->base + CODEC_READ, 30, 0, WIP_TIMEOUT))
230         return (AC97_ERR_WIP_TIMEOUT);
231 
232     /* write addr w/data=0 and assert read request */
233     pci_outl(pCC->base + CODEC_READ, ((u32_t) wAddr << 16) | (1UL << 23));
234 
235     /* now wait for the stinkin' data (RDY) */
236     if (WaitBitd (pCC->base + CODEC_READ, 31, 1, DRDY_TIMEOUT))
237         return (AC97_ERR_DATA_TIMEOUT);
238 
239     dtemp = pci_inl(pCC->base + CODEC_READ);
240 
241     if (data)
242         *data = (u16_t) dtemp;
243 
244     return 0;
245 }
246 
247 
248 int AC97_init( DEV_STRUCT * pCC ) {
249 	int retVal;
250     /* All powerdown modes: off */
251 
252 	dev = pCC;
253 
254     retVal = AC97_write (pCC, AC97_POWERDOWN_CONTROL_STAT,  0x0000U);
255     if (OK != retVal)
256         return (retVal);
257 
258     /* Mute Line Out & set to 0dB attenuation */
259 
260     retVal = AC97_write (pCC, AC97_MASTER_VOLUME, 0x0000U);
261     if (OK != retVal)
262         return (retVal);
263 
264 
265     retVal = AC97_write (pCC, AC97_MONO_VOLUME,   0x8000U);
266     if (OK != retVal)
267         return (retVal);
268 
269     retVal = AC97_write (pCC, AC97_PHONE_VOLUME,  0x8008U);
270     if (OK != retVal)
271         return (retVal);
272 
273     retVal = AC97_write (pCC, AC97_MIC_VOLUME,    0x0008U);
274     if (OK != retVal)
275         return (retVal);
276 
277     retVal = AC97_write (pCC, AC97_LINE_IN_VOLUME,   0x0808U);
278     if (OK != retVal)
279         return (retVal);
280 
281     retVal = AC97_write (pCC, AC97_CD_VOLUME,     0x0808U);
282     if (OK != retVal)
283         return (retVal);
284 
285     retVal = AC97_write (pCC, AC97_AUX_IN_VOLUME,    0x0808U);
286     if (OK != retVal)
287         return (retVal);
288 
289     retVal = AC97_write (pCC, AC97_PCM_OUT_VOLUME,    0x0808U);
290     if (OK != retVal)
291         return (retVal);
292 
293     retVal = AC97_write (pCC, AC97_RECORD_GAIN_VOLUME, 0x0000U);
294     if (OK != retVal)
295         return (retVal);
296 
297     /* Connect Line In to ADC */
298     retVal = AC97_write (pCC, AC97_RECORD_SELECT, 0x0404U);
299     if (OK != retVal)
300         return (retVal);
301 
302     retVal = AC97_write (pCC, AC97_GENERAL_PURPOSE, 0x0000U);
303     if (OK != retVal)
304         return (retVal);
305 
306 	set_nice_volume();
307 
308     return OK;
309 }
310 
311 
312 static void set_nice_volume(void) {
313   /* goofy code to set the DAC1 channel to an audibe volume
314      to be able to test it without using the mixer */
315 
316   AC97_write_unsynced(dev, AC97_PCM_OUT_VOLUME, 0x0808);/* the higher,
317 														   the softer */
318   AC97_write_unsynced(dev, AC97_MASTER_VOLUME, 0x0101);
319   AC97_write_unsynced(dev, 0x38, 0);                    /* not crucial */
320 
321   AC97_write_unsynced(dev, AC97_LINE_IN_VOLUME, 0x0303);
322   AC97_write_unsynced(dev, AC97_MIC_VOLUME, 0x005f);
323 
324   /* mute record gain */
325   AC97_write_unsynced(dev, AC97_RECORD_GAIN_VOLUME, 0xFFFF);
326   /* mic record volume high */
327   AC97_write_unsynced(dev, AC97_RECORD_GAIN_MIC_VOL, 0x0000);
328 
329    /* Also, to be able test recording without mixer:
330      select ONE channel as input below. */
331 
332   /* select LINE IN */
333   /*AC97_write_unsynced(dev, AC97_RECORD_SELECT, 0x0404);*/
334 
335   /* select MIC */
336   AC97_write_unsynced(dev, AC97_RECORD_SELECT, 0x0000);
337 
338   /* unmute record gain */
339   AC97_write_unsynced(dev, AC97_RECORD_GAIN_VOLUME, 0x0000);
340 }
341 
342 
343 static int get_volume(u8_t *left, u8_t *right, int cmd) {
344 	u16_t value = 0;
345 
346 	AC97_read_unsynced(dev, (u16_t)cmd, &value);
347 
348 	*left = value>>8;
349 	*right = value&0xff;
350 
351 	return OK;
352 }
353 
354 
355 static int set_volume(int left, int right, int cmd) {
356 	u16_t waarde;
357 
358 	waarde = (u16_t)((left<<8)|right);
359 
360 	AC97_write_unsynced(dev, (u16_t)cmd, waarde);
361 
362 	return OK;
363 }
364 
365 
366 void convert(int left_in, int right_in, int max_in, int *left_out,
367 		int *right_out, int max_out, int swaplr) {
368 	int tmp;
369 
370 	if(left_in < 0) left_in = 0;
371 	else if(left_in > max_in) left_in = max_in;
372 	if(right_in < 0) right_in = 0;
373 	else if(right_in > max_in) right_in = max_in;
374 
375 	if (swaplr) {
376 		tmp = left_in;
377 		left_in = right_in;
378 		right_in = tmp;
379 	}
380 
381 	*left_out = (-left_in) + max_out;
382 	*right_out = (-right_in) + max_out;
383 }
384 
385 
386 int AC97_get_set_volume(struct volume_level *level, int flag) {
387 	if (flag) {
388 		return AC97_set_volume(level);
389 	}
390 	else {
391 		return AC97_get_volume(level);
392 	}
393 }
394 
395 
396 static int AC97_get_volume(struct volume_level *level) {
397 	int cmd;
398 	u8_t left;
399 	u8_t right;
400 
401 	switch(level->device) {
402 		case Master:
403 			cmd = AC97_MASTER_VOLUME;
404 			get_volume(&left, &right, cmd);
405 			convert(left, right, 0x1f,
406 					&(level->left), &(level->right), 0x1f, 0);
407 			break;
408 		case Dac:
409 			return EINVAL;
410 			break;
411 		case Fm:
412 			cmd = AC97_PCM_OUT_VOLUME;
413 			get_volume(&left, &right, cmd);
414 			convert(left, right, 0x1f,
415 					&(level->left), &(level->right), 0x1f, 0);
416 			break;
417 		case Cd:
418 			cmd = AC97_CD_VOLUME;
419 			get_volume(&left, &right, cmd);
420 			convert(left, right, 0x1f,
421 					&(level->left), &(level->right), 0x1f, 0);
422 			break;
423 		case Line:
424 			cmd = AC97_LINE_IN_VOLUME;
425 			get_volume(&left, &right, cmd);
426 			convert(left, right, 0x1f,
427 					&(level->left), &(level->right), 0x1f, 0);
428 			break;
429 		case Mic:
430 			cmd = AC97_MIC_VOLUME;
431 			get_volume(&left, &right, cmd);
432 			convert(left, right, 0x1f,
433 					&(level->left), &(level->right), 0x1f, 1);
434 			break;
435 		case Speaker:
436 			return EINVAL;
437 		case Treble:
438 			cmd = AC97_MASTER_TONE;
439 			get_volume(&left, &right, cmd);
440 			convert(left, right, 0xf,
441 					&(level->left), &(level->right), 0xf, 1);
442 			break;
443 		case Bass:
444 			cmd = AC97_MASTER_TONE;
445 			get_volume(&left, &right, cmd);
446 			convert(left, right, 0xf,
447 					&(level->left), &(level->right), 0xf, 1);
448 			break;
449 		default:
450 			return EINVAL;
451 	}
452 	return OK;
453 }
454 
455 
456 static int AC97_set_volume(const struct volume_level *level) {
457 	int cmd;
458 	int left;
459 	int right;
460 
461 	switch(level->device) {
462 		case Master:
463 			cmd = AC97_MASTER_VOLUME;
464 			convert(level->left, level->right, 0x1f, &left, &right, 0x1f, 0);
465 			break;
466 		case Dac:
467 			return EINVAL;
468 		case Fm:
469 			cmd = AC97_PCM_OUT_VOLUME;
470 			convert(level->left, level->right, 0x1f, &left, &right, 0x1f, 0);
471 			break;
472 		case Cd:
473 			cmd = AC97_CD_VOLUME;
474 			convert(level->left, level->right, 0x1f, &left, &right, 0x1f, 0);
475 			break;
476 		case Line:
477 			cmd = AC97_LINE_IN_VOLUME;
478 			convert(level->left, level->right, 0x1f, &left, &right, 0x1f, 0);
479 			break;
480 		case Mic:
481 			cmd = AC97_MIC_VOLUME;
482 			convert(level->left, level->right, 0x1f, &left, &right, 0x1f, 1);
483 			break;
484 		case Speaker:
485 			return EINVAL;
486 		case Treble:
487 			return EINVAL;
488 		case Bass:
489 			return EINVAL;
490 		default:
491 			return EINVAL;
492 	}
493 	set_volume(left, right, cmd);
494 
495 	return OK;
496 }
497