FreeBSD/Linux Kernel Cross Reference
sys/pci/es1371.c
1 /*
2 * Support Sound Cards based on the Ensoniq/Creative Labs ES1371/1373
3 *
4 * Copyright (c) 1999 by Russell Cattelan. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. All advertising materials mentioning features or use of this
19 * software must display the following acknowledgement:
20 * This product includes software developed by Russell Cattelan.
21 *
22 * 4. The name of the author may not be used to endorse or promote
23 * products derived from this software without specific prior
24 * written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
36 * OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * $FreeBSD$
39 */
40
41
42 #include <sys/param.h>
43 #include <machine/bus_pio.h>
44 #include <machine/bus.h>
45
46 #include <i386/isa/snd/sound.h>
47
48 #include <pci/es1370_reg.h>
49
50 /* -------------------------------------------------------------------- */
51 /*
52 * hweightN: returns the hamming weight (i.e. the number
53 * of bits set) of a N-bit word
54 */
55
56 unsigned int hweight32(unsigned int w);
57
58 __inline__ unsigned int hweight32(unsigned int w)
59 {
60 unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
61 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
62 res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
63 res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
64 return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
65 }
66
67 /* #define ES1371_REG_STATUS 0x14 */
68 #define ES1371_REG_CODEC 0x14 /* this is really for the 1371 */
69 #define ES1371_CODEC_INDEX_SHIFT 16 /* this is really for the 1371 */
70 #define ES1371_REG_RECSRC 0x1a
71
72 #define ES1371_REG_LEGACY 0x18 /* W/R: Legacy control/status register */
73 #define ES1371_REG_SMPRATE 0x10 /* W/R: Codec rate converter interface register */
74 #define ES1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25) /* address of the sample rate converter */
75 #define ES1371_SRC_RAM_ADDRM (0x7f<<25) /* mask for above */
76 #define ES1371_SRC_RAM_ADDRI(i) (((i)>>25)&0x7f) /* address of the sample rate converter */
77 #define ES1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */
78 #define ES1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */
79 #define ES1371_SRC_DISABLE (1<<22) /* sample rate converter disable */
80 #define ES1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */
81 #define ES1371_DIS_P2 (1<<20) /* playback channel 1 accumulator update disable */
82 #define ES1371_DIS_R1 (1<<19) /* record channel accumulator update disable */
83 #define ES1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0) /* current value of the sample rate converter */
84 #define ES1371_SRC_RAM_DATAM (0xffff<<0) /* mask for above */
85 #define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */
86 #define ES_1371_SYNC_RES (1<<14) /* Warm AC97 reset */
87 #define ES1371_CSTAT (1<<30)
88
89 #define CODEC_RDY 0x80000000 /* AC97 read data valid */
90 #define CODEC_WIP 0x40000000 /* AC97 write in progress */
91 #define CODEC_PORD 0x00800000 /* 0 = write AC97 register */
92 #define CODEC_POADD_MASK 0x007f0000
93 #define CODEC_POADD_SHIFT 16
94 #define CODEC_PODAT_MASK 0x0000ffff
95 #define CODEC_PODAT_SHIFT 0
96
97 /* codec constants */
98
99 #define CODEC_ID_DEDICATEDMIC 0x001
100 #define CODEC_ID_MODEMCODEC 0x002
101 #define CODEC_ID_BASSTREBLE 0x004
102 #define CODEC_ID_SIMULATEDSTEREO 0x008
103 #define CODEC_ID_HEADPHONEOUT 0x010
104 #define CODEC_ID_LOUDNESS 0x020
105 #define CODEC_ID_18BITDAC 0x040
106 #define CODEC_ID_20BITDAC 0x080
107 #define CODEC_ID_18BITADC 0x100
108 #define CODEC_ID_20BITADC 0x200
109
110 #define CODEC_ID_SESHIFT 10
111 #define CODEC_ID_SEMASK 0x1f
112
113 /* sample rate converter */
114 #define SRC_RAMADDR_MASK 0xfe000000
115 #define SRC_RAMADDR_SHIFT 25
116 #define SRC_WE 0x01000000 /* read/write control for SRC RAM */
117 #define SRC_BUSY 0x00800000 /* SRC busy */
118 #define SRC_DIS 0x00400000 /* 1 = disable SRC */
119 #define SRC_DDAC1 0x00200000 /* 1 = disable accum update for DAC1 */
120 #define SRC_DDAC2 0x00100000 /* 1 = disable accum update for DAC2 */
121 #define SRC_DADC 0x00080000 /* 1 = disable accum update for ADC2 */
122 #define SRC_RAMDATA_MASK 0x0000ffff
123 #define SRC_RAMDATA_SHIFT 0
124 /*
125 * Sample rate converter addresses
126 */
127
128 #define ES_SMPREG_DAC1 0x70
129 #define ES_SMPREG_DAC2 0x74
130 #define ES_SMPREG_ADC 0x78
131 #define ES_SMPREG_VOL_ADC 0x6c
132 #define ES_SMPREG_VOL_DAC1 0x7c
133 #define ES_SMPREG_VOL_DAC2 0x7e
134 #define ES_SMPREG_TRUNC_N 0x00
135 #define ES_SMPREG_INT_REGS 0x01
136 #define ES_SMPREG_ACCUM_FRAC 0x02
137 #define ES_SMPREG_VFREQ_FRAC 0x03
138
139
140 #define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */
141 #define CODEC_PIADD_MASK 0x007f0000
142 #define CODEC_PIADD_SHIFT 16
143 #define CODEC_PIDAT_MASK 0x0000ffff
144 #define CODEC_PIDAT_SHIFT 0
145
146
147 struct initvol {
148 int mixch;
149 int vol;
150 };
151
152 struct initvol initvol[] = {
153 { SOUND_MIXER_WRITE_LINE, 0x4040 },
154 { SOUND_MIXER_WRITE_CD, 0x4040 },
155 { MIXER_WRITE(SOUND_MIXER_VIDEO), 0x4040 },
156 { SOUND_MIXER_WRITE_LINE1, 0x4040 },
157 /* { SOUND_MIXER_WRITE_PCM, 0x4040 }, */
158 { SOUND_MIXER_WRITE_PCM, 0x6464 },
159 { SOUND_MIXER_WRITE_VOLUME, 0x4040 },
160 { SOUND_MIXER_WRITE_BASS, 0x1010 },
161 { SOUND_MIXER_WRITE_TREBLE, 0x1010 },
162 { MIXER_WRITE(SOUND_MIXER_PHONEOUT), 0x4040 },
163 { SOUND_MIXER_WRITE_OGAIN, 0x4040 },
164 { MIXER_WRITE(SOUND_MIXER_PHONEIN), 0x4040 },
165 { SOUND_MIXER_WRITE_SPEAKER, 0x4040 },
166 { SOUND_MIXER_WRITE_MIC, 0x4040 },
167 { SOUND_MIXER_WRITE_RECLEV, 0x4040 },
168 { SOUND_MIXER_WRITE_IGAIN, 0x4040 }
169 };
170
171
172 static const char *stereo_enhancement[] =
173 {
174 "no 3D stereo enhancement",
175 "Analog Devices Phat Stereo",
176 "Creative Stereo Enhancement",
177 "National Semiconductor 3D Stereo Enhancement",
178 "YAMAHA Ymersion",
179 "BBE 3D Stereo Enhancement",
180 "Crystal Semiconductor 3D Stereo Enhancement",
181 "Qsound QXpander",
182 "Spatializer 3D Stereo Enhancement",
183 "SRS 3D Stereo Enhancement",
184 "Platform Technologies 3D Stereo Enhancement",
185 "AKM 3D Audio",
186 "Aureal Stereo Enhancement",
187 "AZTECH 3D Enhancement",
188 "Binaura 3D Audio Enhancement",
189 "ESS Technology Stereo Enhancement",
190 "Harman International VMAx",
191 "NVidea 3D Stereo Enhancement",
192 "Philips Incredible Sound",
193 "Texas Instruments 3D Stereo Enhancement",
194 "VLSI Technology 3D Stereo Enhancement"
195 };
196
197
198 static const unsigned int recsrc[8] =
199 {
200 SOUND_MASK_MIC,
201 SOUND_MASK_CD,
202 SOUND_MASK_VIDEO,
203 SOUND_MASK_LINE1,
204 SOUND_MASK_LINE,
205 SOUND_MASK_VOLUME,
206 SOUND_MASK_PHONEOUT,
207 SOUND_MASK_PHONEIN
208 };
209
210 static const unsigned char volreg[] =
211 {
212 /* 5 bit stereo */
213 [SOUND_MIXER_LINE] = 0x10,
214 [SOUND_MIXER_CD] = 0x12,
215 [SOUND_MIXER_VIDEO] = 0x14,
216 [SOUND_MIXER_LINE1] = 0x16,
217 [SOUND_MIXER_PCM] = 0x18,
218 /* 6 bit stereo */
219 [SOUND_MIXER_VOLUME] = 0x02,
220 [SOUND_MIXER_PHONEOUT] = 0x04,
221 /* 6 bit mono */
222 [SOUND_MIXER_OGAIN] = 0x06,
223 [SOUND_MIXER_PHONEIN] = 0x0c,
224 /* 4 bit mono but shifted by 1 */
225 [SOUND_MIXER_SPEAKER] = 0x08,
226 /* 6 bit mono + preamp */
227 [SOUND_MIXER_MIC] = 0x0e,
228 /* 4 bit stereo */
229 [SOUND_MIXER_RECLEV] = 0x1c,
230 /* 4 bit mono */
231 [SOUND_MIXER_IGAIN] = 0x1e
232 };
233
234
235 #define swab(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
236 #define AC97_PESSIMISTIC
237 #define put_user(a,b) *b=a
238
239
240 int
241 es_init_1371(snddev_info *d){
242 struct es_info *es = (struct es_info *)d->device_data;
243 u_int i;
244 int idx;
245 int val, val2 = 0;
246 if(es_debug > 0) printf("es_init_1371\n");
247
248 strncpy(d->name,"ES1371",strlen("ES1371"));
249 es->ctrl = 0;
250 es->sctrl = 0;
251 /* initialize the chips */
252 bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
253 bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
254 bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, 0);
255 /* AC'97 warm reset to start the bitclk */
256 bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, es->ctrl | ES_1371_SYNC_RES);
257 DELAY(2000);
258 bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL,es->ctrl);
259 /* Init the sample rate converter */
260 bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, ES1371_SRC_DISABLE);
261 for (idx = 0; idx < 0x80; idx++)
262 es1371_src_write(d, idx, 0);
263 es1371_src_write(d, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
264 es1371_src_write(d, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
265 es1371_src_write(d, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
266 es1371_src_write(d, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
267 es1371_src_write(d, ES_SMPREG_VOL_ADC, 1 << 12);
268 es1371_src_write(d, ES_SMPREG_VOL_ADC + 1, 1 << 12);
269 es1371_src_write(d, ES_SMPREG_VOL_DAC1, 1 << 12);
270 es1371_src_write(d, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
271 es1371_src_write(d, ES_SMPREG_VOL_DAC2, 1 << 12);
272 es1371_src_write(d, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
273 es1371_adc_rate(d, 22050, 1);
274 es1371_dac1_rate(d, 22050, 1);
275 es1371_dac2_rate(d, 22050, 1);
276 /* WARNING:
277 * enabling the sample rate converter without properly programming
278 * its parameters causes the chip to lock up (the SRC busy bit will
279 * be stuck high, and I've found no way to rectify this other than
280 * power cycle)
281 */
282 /*outl(0, s->io+ES1371_REG_SRCONV); */
283 bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, 0);
284 /* codec init */
285 wrcodec(d, 0x00, 0); /* reset codec */
286 d->bd_id = rdcodec(d, 0x00); /* get codec ID */
287 val = rdcodec(d, 0x7c);
288 val2 = rdcodec(d, 0x7e);
289 if(es_debug > 0) printf("init: d->bd_id 0x%x val 0x%x val2 0x%x\n",d->bd_id,val,val2);
290 d->bd_id |= CODEC_ID_BASSTREBLE;
291 printf("es1371: codec vendor %c%c%c revision %d\n",
292 (val >> 8) & 0xff, val & 0xff, (val2 >> 8) & 0xff, val2 & 0xff);
293 printf("es1371: codec features");
294 if (d->bd_id & CODEC_ID_DEDICATEDMIC)
295 printf(" dedicated MIC PCM in");
296 if (d->bd_id & CODEC_ID_MODEMCODEC)
297 printf(" Modem Line Codec");
298 if (d->bd_id & CODEC_ID_BASSTREBLE)
299 printf(" Bass & Treble");
300 if (d->bd_id & CODEC_ID_SIMULATEDSTEREO)
301 printf(" Simulated Stereo");
302 if (d->bd_id & CODEC_ID_HEADPHONEOUT)
303 printf(" Headphone out");
304 if (d->bd_id & CODEC_ID_LOUDNESS)
305 printf(" Loudness");
306 if (d->bd_id & CODEC_ID_18BITDAC)
307 printf(" 18bit DAC");
308 if (d->bd_id & CODEC_ID_20BITDAC)
309 printf(" 20bit DAC");
310 if (d->bd_id & CODEC_ID_18BITADC)
311 printf(" 18bit ADC");
312 if (d->bd_id & CODEC_ID_20BITADC)
313 printf(" 20bit ADC");
314 printf("%s\n", (d->bd_id & 0x3ff) ? "" : " none");
315 val = (d->bd_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
316 printf("es1371: stereo enhancement: %s\n", (val <= 20) ? stereo_enhancement[val] : "unknown");
317 val = SOUND_MASK_LINE;
318 mixer_ioctl_1371(d, SOUND_MIXER_WRITE_RECSRC, (caddr_t)&val, 0,NULL);
319 for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
320 val = initvol[i].vol;
321 if(es_debug > 0) printf("es_init -> mixer_ioctl_1371 0x%x\n",val);
322 mixer_ioctl_1371(d, initvol[i].mixch, (caddr_t)&val, 0,NULL);
323 }
324 return 0;
325 }
326
327
328 int mixer_rdch(snddev_info *s, unsigned int ch, int *arg)
329 {
330 int j;
331
332 if(es_debug > 0) printf("mixer_rdch ch 0x%x\n",ch);
333 switch (ch) {
334 case SOUND_MIXER_MIC:
335 j = rdcodec(s, 0x0e);
336 if (j & 0x8000){
337 put_user(0, (int *)arg);
338 return (*arg);
339 }
340 put_user(0x4949 - 0x202 * (j & 0x1f) + ((j & 0x40) ? 0x1b1b : 0), (int *)arg);
341 return (*arg);
342
343 case SOUND_MIXER_OGAIN:
344 case SOUND_MIXER_PHONEIN:
345 j = rdcodec(s, volreg[ch]);
346 if (j & 0x8000){
347 put_user(0, (int *)arg);
348 return (*arg);
349 }
350 put_user(0x6464 - 0x303 * (j & 0x1f), (int *)arg);
351 return (*arg);
352
353 case SOUND_MIXER_PHONEOUT:
354 if (!(s->bd_id & CODEC_ID_HEADPHONEOUT))
355 return EINVAL;
356 /* fall through */
357 case SOUND_MIXER_VOLUME:
358 j = rdcodec(s, volreg[ch]);
359 if (j & 0x8000){
360 put_user(0, (int *)arg);
361 return (*arg);
362 }
363 put_user(0x6464 - (swab(j) & 0x1f1f) * 3, (int *)arg);
364 return (*arg);
365 case SOUND_MIXER_SPEAKER:
366 j = rdcodec(s, 0x0a);
367 if (j & 0x8000){
368 put_user(0, (int *)arg);
369 return (*arg);
370 }
371 put_user(0x6464 - ((j >> 1) & 0xf) * 0x606, (int *)arg);
372 return (*arg);
373
374 case SOUND_MIXER_LINE:
375 case SOUND_MIXER_CD:
376 case SOUND_MIXER_VIDEO:
377 case SOUND_MIXER_LINE1:
378 case SOUND_MIXER_PCM:
379 j = rdcodec(s, volreg[ch]);
380 if (j & 0x8000){
381 put_user(0, (int *)arg);
382 return (*arg);
383 }
384 put_user(0x6464 - (swab(j) & 0x1f1f) * 3, (int *)arg);
385 return (*arg);
386
387 case SOUND_MIXER_BASS:
388 case SOUND_MIXER_TREBLE:
389 if (!(s->bd_id & CODEC_ID_BASSTREBLE))
390 return EINVAL;
391 j = rdcodec(s, 0x08);
392 if (ch == SOUND_MIXER_BASS)
393 j >>= 8;
394 put_user((((j & 15) * 100) / 15) * 0x101, (int *)arg);
395 return (*arg);
396
397 /* SOUND_MIXER_RECLEV and SOUND_MIXER_IGAIN specify gain */
398 case SOUND_MIXER_RECLEV:
399 j = rdcodec(s, 0x1c);
400 if (j & 0x8000){
401 put_user(0, (int *)arg);
402 return (*arg);
403 }
404 put_user((swab(j) & 0xf0f) * 6 + 0xa0a, (int *)arg);
405 return (*arg);
406
407 case SOUND_MIXER_IGAIN:
408 if (!(s->bd_id & CODEC_ID_DEDICATEDMIC))
409 return EINVAL;
410 j = rdcodec(s, 0x1e);
411 if (j & 0x8000){
412 put_user(0, (int *)arg);
413 return (*arg);
414 }
415 put_user((j & 0xf) * 0x606 + 0xa0a, (int *)arg);
416 return (*arg);
417
418 default:
419 return EINVAL;
420 }
421 }
422
423 int mixer_wrch(snddev_info *s, unsigned int ich, int val)
424 {
425 int i;
426 unsigned l1, r1;
427
428 u_int ch = (ich & 0xff);
429 if(es_debug > 0) printf("mixer_wrch ch 0x%x val 0x%x\t",ch,(val & 0xffff));
430
431 l1 = val & 0xff;
432 r1 = (val >> 8) & 0xff;
433 if(es_debug > 0) printf ("l1 0x%x r1 0x%x\n",l1,r1);
434 if (l1 > 100)
435 l1 = 100;
436 if (r1 > 100)
437 r1 = 100;
438 s->mix_levels[ch] = ((u_int) r1 << 8) | l1;
439 switch (ch) {
440 case SOUND_MIXER_LINE:
441 /* printf("SOUND_MIXER_LINE\n"); */
442 case SOUND_MIXER_CD:
443 /* printf("SOUND_MIXER_CD\n"); */
444 case SOUND_MIXER_VIDEO:
445 /* printf("SOUND_MIXER_VIDEO\n"); */
446 case SOUND_MIXER_LINE1:
447 /* printf("SOUND_MIXEgR_LINE1\n");*/
448 case SOUND_MIXER_PCM:
449 if (es_debug >0 ) printf("SOUND_MIXER_PCM\n");
450 if (l1 < 7 && r1 < 7) {
451 wrcodec(s, volreg[ch], 0x8000);
452 return 0;
453 }
454 if (l1 < 7)
455 l1 = 7;
456 if (r1 < 7)
457 r1 = 7;
458 wrcodec(s, volreg[ch], (((100 - l1) / 3) << 8) | ((100 - r1) / 3));
459 return 0;
460
461 case SOUND_MIXER_PHONEOUT:
462 if(es_debug > 0) printf("SOUND_MIXER_PHONEOUT\n");
463 if (!(s->bd_id & CODEC_ID_HEADPHONEOUT))
464 return EINVAL;
465 /* fall through */
466 case SOUND_MIXER_VOLUME:
467 if(es_debug > 0) printf("SOUND_MIXER_VOLUME\n");
468 #ifdef AC97_PESSIMISTIC
469 if (l1 < 7 && r1 < 7) {
470 wrcodec(s, volreg[ch], 0x8000);
471 return 0;
472 }
473 if (l1 < 7)
474 l1 = 7;
475 if (r1 < 7)
476 r1 = 7;
477 wrcodec(s, volreg[ch], (((100 - l1) / 3) << 8) | ((100 - r1) / 3));
478 /* es1371_src_write(s, volreg[ch], (((100 - l1) / 3) << 8) | ((100 - r1) / 3)); */
479 return 0;
480 #else /* AC97_PESSIMISTIC */
481 if (l1 < 4 && r1 < 4) {
482 wrcodec(s, volreg[ch], 0x8000);
483 return 0;
484 }
485 if (l1 < 4)
486 l1 = 4;
487 if (r1 < 4)
488 r1 = 4;
489 wrcodec(s, volreg[ch], ((2 * (100 - l1) / 3) << 8) | (2 * (100 - r1) / 3));
490 return 0;
491 #endif /* AC97_PESSIMISTIC */
492
493 case SOUND_MIXER_OGAIN:
494 if(es_debug > 0) printf("SOUND_MIXER_OGAIN\n");
495 case SOUND_MIXER_PHONEIN:
496 if(es_debug > 0) printf("SOUND_MIXER_PHONEIN\n");
497 #ifdef AC97_PESSIMISTIC
498 wrcodec(s, volreg[ch], (l1 < 7) ? 0x8000 : (100 - l1) / 3);
499 return 0;
500 #else /* AC97_PESSIMISTIC */
501 wrcodec(s, volreg[ch], (l1 < 4) ? 0x8000 : (2 * (100 - l1) / 3));
502 return 0;
503 #endif /* AC97_PESSIMISTIC */
504
505 case SOUND_MIXER_SPEAKER:
506 wrcodec(s, 0x0a, (l1 < 10) ? 0x8000 : ((100 - l1) / 6) << 1);
507 return 0;
508
509 case SOUND_MIXER_MIC:
510 if(es_debug > 0) printf("SOUND_MIXER_MIC\n");
511 #ifdef AC97_PESSIMISTIC
512 if (l1 < 11) {
513 wrcodec(s, 0x0e, 0x8000);
514 return 0;
515 }
516 i = 0;
517 if (l1 >= 27) {
518 l1 -= 27;
519 i = 0x40;
520 }
521 if (l1 < 11)
522 l1 = 11;
523 wrcodec(s, 0x0e, ((73 - l1) / 2) | i);
524 return 0;
525 #else /* AC97_PESSIMISTIC */
526 if (l1 < 9) {
527 wrcodec(s, 0x0e, 0x8000);
528 return 0;
529 }
530 i = 0;
531 if (l1 >= 13) {
532 l1 -= 13;
533 i = 0x40;
534 }
535 if (l1 < 9)
536 l1 = 9;
537 wrcodec(s, 0x0e, (((87 - l1) * 4) / 5) | i);
538 return 0;
539 #endif /* AC97_PESSIMISTIC */
540
541 case SOUND_MIXER_BASS:
542 if(es_debug > 0) printf("SOUND_MIXER_BASS\n");
543 val = ((l1 * 15) / 100) & 0xf;
544 wrcodec(s, 0x08, (rdcodec(s, 0x08) & 0x00ff) | (val << 8));
545 return 0;
546
547 case SOUND_MIXER_TREBLE:
548 if(es_debug > 0) printf("SOUND_MIXER_TREBLE\n");
549 val = ((l1 * 15) / 100) & 0xf;
550 wrcodec(s, 0x08, (rdcodec(s, 0x08) & 0xff00) | val);
551 return 0;
552
553 /* SOUND_MIXER_RECLEV and SOUND_MIXER_IGAIN specify gain */
554 case SOUND_MIXER_RECLEV:
555 if(es_debug > 0) printf("SOUND_MIXER_RECLEV\n");
556 if (l1 < 10 || r1 < 10) {
557 wrcodec(s, 0x1c, 0x8000);
558 return 0;
559 }
560 if (l1 < 10)
561 l1 = 10;
562 if (r1 < 10)
563 r1 = 10;
564 wrcodec(s, 0x1c, (((l1 - 10) / 6) << 8) | ((r1 - 10) / 6));
565 return 0;
566
567 case SOUND_MIXER_IGAIN:
568 if(es_debug > 0) printf("SOUND_MIXER_IGAIN\n");
569 if (!(s->bd_id & CODEC_ID_DEDICATEDMIC))
570 return EINVAL;
571 wrcodec(s, 0x1e, (l1 < 10) ? 0x8000 : ((l1 - 10) / 6) & 0xf);
572 return 0;
573
574 default:
575 return EINVAL;
576 }
577 }
578
579
580 /* --------------------------------------------------------------------- */
581
582 #if 0
583 /* hmm for some reason I changed this in the es1370 code ... should wrcodec handle this */
584 /* make sure to find out where this is called from */
585 static int
586 write_codec_1371(snddev_info *d, u_char i, u_char data)
587 {
588 struct es_info *es = (struct es_info *)d->device_data;
589 int wait = 100; /* 100 msec timeout */
590 u_int32_t ret;
591 do {
592 if ((ret = bus_space_read_4(es->st, es->sh, ES1371_REG_STATUS) &
593 ES1371_CSTAT) == 0) {
594 bus_space_write_2(es->st, es->sh, ES1371_REG_CODEC,
595 ((u_short)i << ES1371_CODEC_INDEX_SHIFT) | data);
596 return (0);
597 }
598 if(es_debug > 0) printf("write_codec ret 0x%x ret & ES1371_CSTAT 0x%x\n",ret,ret & STAT_CSTAT);
599 DELAY(1000);
600 /* tsleep(&wait, PZERO, "sndaw", hz / 1000); */
601 } while (--wait);
602 printf("pcm: write_codec timed out\n");
603 return (-1);
604 }
605 #endif
606
607
608 void wrcodec(snddev_info *s, unsigned addr, unsigned data)
609 {
610 /* unsigned long flags; */
611 int sl;
612 unsigned t, x;
613 struct es_info *es = (struct es_info *)s->device_data;
614
615 if(es_debug > 0) printf("wrcodec addr 0x%x data 0x%x\n",addr,data);
616
617 for (t = 0; t < 0x1000; t++)
618 if(!(bus_space_read_4(es->st, es->sh,ES1371_REG_CODEC) & CODEC_WIP))
619 break;
620 /* spin_lock_irqsave(&s->lock, flags); */
621 sl = spltty();
622 /* save the current state for later */
623 x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
624 /* enable SRC state data in SRC mux */
625 bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
626 (es1371_wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)));
627 /* wait for a SAFE time to write addr/data and then do it, dammit */
628 for (t = 0; t < 0x1000; t++)
629 if (( bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
630 break;
631
632 if(es_debug > 2) printf("one b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_CODEC,
633 ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
634 ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
635
636 bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
637 ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
638 ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
639 /* restore SRC reg */
640 es1371_wait_src_ready(s);
641 if(es_debug > 2) printf("two b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_SMPRATE,x);
642 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,x);
643 /* spin_unlock_irqrestore(&s->lock, flags); */
644 splx(sl);
645 }
646
647 unsigned rdcodec(snddev_info *s, unsigned addr)
648 {
649 /* unsigned long flags; */
650 int sl;
651 unsigned t, x;
652
653 struct es_info *es = (struct es_info *)s->device_data;
654 if(es_debug > 5) printf("rdcodec ");
655
656 for (t = 0; t < 0x1000; t++)
657 if (!(x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC) & CODEC_WIP))
658 break;
659 sl = spltty();
660 /* save the current state for later */
661 x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
662 /* enable SRC state data in SRC mux */
663 bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
664 (es1371_wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)));
665 /* wait for a SAFE time to write addr/data and then do it, dammit */
666 for (t = 0; t < 0x1000; t++)
667 if (( bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
668 break;
669
670 bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
671 ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD);
672
673 /* restore SRC reg */
674 es1371_wait_src_ready(s);
675 bus_space_write_4(es->st,es->sh,ES1371_REG_SMPRATE,x);
676 splx(sl);
677 /* now wait for the stinkin' data (RDY) */
678 for (t = 0; t < 0x1000; t++)
679 if ((x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC)) & CODEC_RDY)
680 break;
681 if(es_debug > 5) printf("0x%x ret 0x%x\n",x,((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT));
682 return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
683 }
684
685
686
687 int
688 mixer_ioctl_1371(snddev_info *s, u_long cmd, caddr_t data, int fflag, struct proc *p)
689 {
690 int cmdi;
691 int val;
692 int *arg = (int *)data;
693
694 val = *(int *)data;
695 cmdi = cmd & 0xff;
696
697 if(es_debug > 0) printf("mixer_ioctl_1371 cmd 0x%x cmdi 0x%x write %s read %s ",(u_int)cmd,cmdi,
698 (((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0))?"yes":"no"),
699 (((cmd & MIXER_READ(0)) == MIXER_READ(0))?"yes":"no"));
700
701 if (cmdi == OSS_GETVERSION){
702 put_user(SOUND_VERSION, (int *)arg);
703 return (0);
704 }
705
706 if ((cmd & MIXER_READ(0)) == MIXER_READ(0)){
707 switch (cmdi) {
708 case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
709 if (es_debug > 4) printf("mixer_ioctl_1371: SOUND_MIXER_RECSRC\n");
710 put_user(recsrc[rdcodec(s, ES1371_REG_RECSRC) & 7], (int *)arg);
711 break;
712 case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
713 put_user(SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_VIDEO |
714 SOUND_MASK_LINE1 | SOUND_MASK_PCM | SOUND_MASK_VOLUME |
715 SOUND_MASK_OGAIN | SOUND_MASK_PHONEIN | SOUND_MASK_SPEAKER |
716 SOUND_MASK_MIC | SOUND_MASK_RECLEV |
717 ((s->bd_id & CODEC_ID_BASSTREBLE) ? (SOUND_MASK_BASS | SOUND_MASK_TREBLE) : 0) |
718 ((s->bd_id & CODEC_ID_HEADPHONEOUT) ? SOUND_MASK_PHONEOUT : 0) |
719 ((s->bd_id & CODEC_ID_DEDICATEDMIC) ? SOUND_MASK_IGAIN : 0), (int *)arg);
720 if (es_debug > 4) printf("mixer_ioctl_1371: SOUND_MIXER_DEVMASK s->bd_id 0x%x arg 0x%x\n",s->bd_id,*arg);
721 break;
722 case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
723 if (es_debug > 4) printf("mixer_ioctl_1371: SOUND_MIXER_RECMASK\n");
724 put_user(SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VIDEO | SOUND_MASK_LINE1 |
725 SOUND_MASK_LINE | SOUND_MASK_VOLUME | SOUND_MASK_PHONEOUT |
726 SOUND_MASK_PHONEIN, (int *)arg);
727 break;
728 case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
729 if (es_debug > 4) printf("mixer_ioctl_1371: SOUND_MIXER_STEREODEVS\n");
730 put_user(SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_VIDEO |
731 SOUND_MASK_LINE1 | SOUND_MASK_PCM | SOUND_MASK_VOLUME |
732 SOUND_MASK_PHONEOUT | SOUND_MASK_RECLEV, (int *)arg);
733 break;
734 case SOUND_MIXER_CAPS:
735 if (es_debug > 4) printf("mixer_ioctl_1371: SOUND_MIXER_CAPS\n");
736 put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
737 break;
738 default:
739 if (es_debug > 4) printf("mixer_ioctl_1371: default\n");
740 cmdi = cmd & 0xff;
741 if (cmdi >= SOUND_MIXER_NRDEVICES)
742 return EINVAL;
743 { int ret;
744 ret = mixer_rdch(s, cmdi, arg);
745 if(es_debug > 0) printf("READ done ret 0x%x arg 0x%x\n",ret,*arg);
746 }
747 }
748 }
749 if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)){
750 if(es_debug > 0) printf("WRITE cmdi 0x%x data 0x%x val 0x%x sizeof(val) %d\n",cmdi,*data,val,sizeof(val));
751 switch (cmdi) {
752 int i;
753 case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
754 /* get_user_ret(val, (int *)arg, EFAULT); */
755 i = hweight32(val);
756 if (es_debug > 0) printf("SOUND_MIXER_RECSRC i: %d\n",i);
757 if (i == 0)
758 return 0; /*val = mixer_recmask(s);*/
759 else if (i > 1)
760 val &= ~recsrc[rdcodec(s, ES1371_REG_RECSRC) & 7];
761 for (i = 0; i < 8; i++) {
762 if (val & recsrc[i]) {
763 wrcodec(s, ES1371_REG_RECSRC, 0x101 * i);
764 return 0;
765 }
766 }
767 return 0;
768 default:
769 if (es_debug > 0) printf("mixer_ioctl_1371 default cmdi: %d\n",cmdi);
770 if (cmdi >= SOUND_MIXER_NRDEVICES)
771 return EINVAL;
772 /* get_user_ret(val, (int *)arg, EFAULT); */
773 if (mixer_wrch(s, cmdi, val))
774 return EINVAL;
775 { int ret;
776 ret = mixer_rdch(s, cmdi, (int *)arg);
777 if(es_debug > 0) printf("WRITE done ret 0x%x arg 0x%x\n",ret,*arg);
778 }
779 }
780 }
781 return (0);
782 }
783
784 u_int es1371_wait_src_ready(snddev_info *d){
785 struct es_info *es = (struct es_info *)d->device_data;
786 u_int t, r;
787
788 for (t = 0; t < 500; t++) {
789 if (!((r = bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)){
790 return r;
791 }
792 /* snd_delay(1); */
793 DELAY(1000);
794 }
795 printf("es1371: wait source ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r);
796 return 0;
797 }
798
799 static u_int es1371_src_read(snddev_info *d,
800 u_short reg){
801 struct es_info *es = (struct es_info *)d->device_data;
802 unsigned int r;
803
804 r = es1371_wait_src_ready(d) &
805 (ES1371_SRC_DISABLE |
806 ES1371_DIS_P1 |
807 ES1371_DIS_P2 |
808 ES1371_DIS_R1);
809 r |= ES1371_SRC_RAM_ADDRO(reg);
810 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
811 return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(d));
812 }
813
814 void es1371_src_write(snddev_info *d,
815 u_short reg,
816 u_short data){
817 struct es_info *es = (struct es_info *)d->device_data;
818 u_int r;
819
820 r = es1371_wait_src_ready(d) &
821 (ES1371_SRC_DISABLE |
822 ES1371_DIS_P1 |
823 ES1371_DIS_P2 |
824 ES1371_DIS_R1);
825 r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data);
826 if(es_debug > 1 ) printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE);
827 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE);
828 }
829
830 u_int
831 es1371_adc_rate(snddev_info *d,
832 u_int rate,
833 int set){
834 u_int n, truncm, freq, result;
835
836 if (rate > 48000)
837 rate = 48000;
838 if (rate < 4000)
839 rate = 4000;
840 n = rate / 3000;
841 if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
842 n--;
843 truncm = (21 * n - 1) | 1;
844 freq = ((48000UL << 15) / rate) * n;
845 result = (48000UL << 15) / (freq / n);
846 if (set) {
847 if (rate >= 24000) {
848 if (truncm > 239)
849 truncm = 239;
850 es1371_src_write(d, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
851 (((239 - truncm) >> 1) << 9) | (n << 4));
852 } else {
853 if (truncm > 119)
854 truncm = 119;
855 es1371_src_write(d, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
856 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
857 }
858 es1371_src_write(d, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
859 (es1371_src_read(d,
860 ES_SMPREG_ADC +
861 ES_SMPREG_INT_REGS) &
862 0x00ff) | ((freq >> 5) & 0xfc00));
863 es1371_src_write(d, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
864 es1371_src_write(d, ES_SMPREG_VOL_ADC, n << 8);
865 es1371_src_write(d, ES_SMPREG_VOL_ADC + 1, n << 8);
866 }
867 return result;
868 }
869
870 u_int
871 es1371_dac1_rate(snddev_info *d,
872 u_int rate,
873 int set){
874 struct es_info *es = (struct es_info *)d->device_data;
875 u_int freq, r, result;
876
877
878 if (rate > 48000)
879 rate = 48000;
880 if (rate < 4000)
881 rate = 4000;
882 freq = (rate << 15) / 3000;
883 result = (freq * 3000) >> 15;
884 if (set) {
885 r = (es1371_wait_src_ready(d) & (ES1371_SRC_DISABLE | ES1371_DIS_P2 | ES1371_DIS_R1)) | ES1371_DIS_P1;
886 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
887 if(es_debug > 0) printf("dac1_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE));
888 es1371_src_write(d, ES_SMPREG_DAC1 +
889 ES_SMPREG_INT_REGS,
890 (es1371_src_read(d,
891 ES_SMPREG_DAC1 +
892 ES_SMPREG_INT_REGS) &
893 0x00ff) | ((freq >> 5) & 0xfc00));
894 es1371_src_write(d, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
895 r = (es1371_wait_src_ready(d) & (ES1371_SRC_DISABLE | ES1371_DIS_P2 | ES1371_DIS_R1));
896 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
897 if(es_debug > 0) printf("dac1_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE));
898 }
899 return result;
900 }
901
902 u_int
903 es1371_dac2_rate(snddev_info *d,
904 u_int rate,
905 int set){
906 u_int freq, r, result;
907 struct es_info *es = (struct es_info *)d->device_data;
908
909 if (rate > 48000)
910 rate = 48000;
911 if (rate < 4000)
912 rate = 4000;
913 freq = (rate << 15) / 3000;
914 result = (freq * 3000) >> 15;
915 if (set) {
916 r = (es1371_wait_src_ready(d) & (ES1371_SRC_DISABLE | ES1371_DIS_P1 | ES1371_DIS_R1)) | ES1371_DIS_P2;
917 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
918 if(es_debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE));
919 es1371_src_write(d, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS,
920 (es1371_src_read(d, ES_SMPREG_DAC2 +
921 ES_SMPREG_INT_REGS) &
922 0x00ff) | ((freq >> 5) & 0xfc00));
923 es1371_src_write(d, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
924 r = (es1371_wait_src_ready(d) & (ES1371_SRC_DISABLE | ES1371_DIS_P1 | ES1371_DIS_R1));
925 bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
926 if(es_debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE));
927 }
928 return result;
929 }
Cache object: 28a2f12ef2964157dcf11ed420f20a94
|