Deleted Added
full compact
ac97.c (65490) ac97.c (66013)
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/sound/pcm/ac97.c 65490 2000-09-05 21:08:01Z cg $
26 * $FreeBSD: head/sys/dev/sound/pcm/ac97.c 66013 2000-09-17 23:51:00Z cg $
27 */
28
29#include <dev/sound/pcm/sound.h>
30#include <dev/sound/pcm/ac97.h>
31
32struct ac97mixtable_entry {
33 int reg:8;
34 unsigned bits:4;
35 unsigned ofs:4;
36 unsigned stereo:1;
37 unsigned mute:1;
38 unsigned recidx:4;
39 unsigned mask:1;
27 */
28
29#include <dev/sound/pcm/sound.h>
30#include <dev/sound/pcm/ac97.h>
31
32struct ac97mixtable_entry {
33 int reg:8;
34 unsigned bits:4;
35 unsigned ofs:4;
36 unsigned stereo:1;
37 unsigned mute:1;
38 unsigned recidx:4;
39 unsigned mask:1;
40 unsigned enable:1;
40};
41
42struct ac97_info {
43 device_t dev;
44 ac97_init *init;
45 ac97_read *read;
46 ac97_write *write;
47 void *devinfo;

--- 4 unchanged lines hidden (view full) ---

52};
53
54struct ac97_codecid {
55 u_int32_t id, noext:1;
56 char *name;
57};
58
59static const struct ac97mixtable_entry ac97mixtable_default[32] = {
41};
42
43struct ac97_info {
44 device_t dev;
45 ac97_init *init;
46 ac97_read *read;
47 ac97_write *write;
48 void *devinfo;

--- 4 unchanged lines hidden (view full) ---

53};
54
55struct ac97_codecid {
56 u_int32_t id, noext:1;
57 char *name;
58};
59
60static const struct ac97mixtable_entry ac97mixtable_default[32] = {
60 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0 },
61 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1 },
62 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1 },
63 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0 },
64 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0 },
65 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0 },
66 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 0 },
67 [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0 },
68 [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0 },
69 [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0 },
70 [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0 }
61 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
62 [SOUND_MIXER_MONITOR] = { AC97_MIX_PHONES, 5, 0, 1, 1, 0, 0, 0 },
63 [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
64 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
65 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
66 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
67 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
68 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
69 [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
70 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 0, 1 },
71 [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
72 [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
73 [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 },
74 [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
71};
72
75};
76
73static const unsigned ac97mixdevs =
74 SOUND_MASK_VOLUME |
75 SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
76 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_LINE1 |
77 SOUND_MASK_VIDEO | SOUND_MASK_RECLEV;
78
79static const unsigned ac97recdevs =
80 SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_MIC |
81 SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO;
82
83static struct ac97_codecid ac97codecid[] = {
84 { 0x414b4d00, 1, "Asahi Kasei AK4540 rev 0" },
85 { 0x414b4d01, 1, "Asahi Kasei AK4540 rev 1" },
86 { 0x43525900, 0, "Cirrus Logic CS4297" },
87 { 0x83847600, 0, "SigmaTel STAC????" },
88 { 0x83847604, 0, "SigmaTel STAC9701/3/4/5" },
89 { 0x83847605, 0, "SigmaTel STAC9704" },
90 { 0x83847608, 0, "SigmaTel STAC9708" },

--- 117 unchanged lines hidden (view full) ---

208 codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
209 return (mode == codec->extstat)? 0 : -1;
210}
211
212static int
213ac97_setrecsrc(struct ac97_info *codec, int channel)
214{
215 struct ac97mixtable_entry *e = &codec->mix[channel];
77static struct ac97_codecid ac97codecid[] = {
78 { 0x414b4d00, 1, "Asahi Kasei AK4540 rev 0" },
79 { 0x414b4d01, 1, "Asahi Kasei AK4540 rev 1" },
80 { 0x43525900, 0, "Cirrus Logic CS4297" },
81 { 0x83847600, 0, "SigmaTel STAC????" },
82 { 0x83847604, 0, "SigmaTel STAC9701/3/4/5" },
83 { 0x83847605, 0, "SigmaTel STAC9704" },
84 { 0x83847608, 0, "SigmaTel STAC9708" },

--- 117 unchanged lines hidden (view full) ---

202 codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
203 return (mode == codec->extstat)? 0 : -1;
204}
205
206static int
207ac97_setrecsrc(struct ac97_info *codec, int channel)
208{
209 struct ac97mixtable_entry *e = &codec->mix[channel];
210
216 if (e->recidx > 0) {
217 int val = e->recidx - 1;
218 val |= val << 8;
219 wrcd(codec, AC97_REG_RECSEL, val);
220 return 0;
221 } else
222 return -1;
223}
224
225static int
226ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
227{
228 struct ac97mixtable_entry *e = &codec->mix[channel];
211 if (e->recidx > 0) {
212 int val = e->recidx - 1;
213 val |= val << 8;
214 wrcd(codec, AC97_REG_RECSEL, val);
215 return 0;
216 } else
217 return -1;
218}
219
220static int
221ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
222{
223 struct ac97mixtable_entry *e = &codec->mix[channel];
229 if (e->reg != 0) {
224
225 if (e->reg && e->enable && e->bits) {
230 int max, val, reg = (e->reg >= 0)? e->reg : -e->reg;
231
232 if (!e->stereo)
233 right = left;
234 if (e->reg > 0) {
235 left = 100 - left;
236 right = 100 - right;
237 }

--- 19 unchanged lines hidden (view full) ---

257 int cur = rdcd(codec, e->reg);
258 val |= cur & ~(max << e->ofs);
259 }
260 }
261 if (left == 0 && right == 0 && e->mute == 1)
262 val = AC97_MUTE;
263 wrcd(codec, reg, val);
264 return left | (right << 8);
226 int max, val, reg = (e->reg >= 0)? e->reg : -e->reg;
227
228 if (!e->stereo)
229 right = left;
230 if (e->reg > 0) {
231 left = 100 - left;
232 right = 100 - right;
233 }

--- 19 unchanged lines hidden (view full) ---

253 int cur = rdcd(codec, e->reg);
254 val |= cur & ~(max << e->ofs);
255 }
256 }
257 if (left == 0 && right == 0 && e->mute == 1)
258 val = AC97_MUTE;
259 wrcd(codec, reg, val);
260 return left | (right << 8);
265 } else
261 } else {
262 /* printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable); */
266 return -1;
263 return -1;
264 }
267}
268
269#if 0
270static int
271ac97_getmixer(struct ac97_info *codec, int channel)
272{
273 struct ac97mixtable_entry *e = &codec->mix[channel];
274 if (channel < SOUND_MIXER_NRDEVICES && e->reg != 0) {

--- 13 unchanged lines hidden (view full) ---

288 } else
289 return -1;
290}
291#endif
292
293static unsigned
294ac97_initmixer(struct ac97_info *codec)
295{
265}
266
267#if 0
268static int
269ac97_getmixer(struct ac97_info *codec, int channel)
270{
271 struct ac97mixtable_entry *e = &codec->mix[channel];
272 if (channel < SOUND_MIXER_NRDEVICES && e->reg != 0) {

--- 13 unchanged lines hidden (view full) ---

286 } else
287 return -1;
288}
289#endif
290
291static unsigned
292ac97_initmixer(struct ac97_info *codec)
293{
296 unsigned i, j;
294 unsigned i, j, k, old;
297 u_int32_t id;
298
299 for (i = 0; i < 32; i++)
300 codec->mix[i] = ac97mixtable_default[i];
301
302 if (codec->init) {
303 codec->count = codec->init(codec->devinfo);
304 if (codec->count == 0) {

--- 32 unchanged lines hidden (view full) ---

337 codec->extstat = 0;
338 } else {
339 i = rdcd(codec, AC97_REGEXT_ID);
340 codec->extcaps = i & 0x3fff;
341 codec->extid = (i & 0xc000) >> 14;
342 codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
343 }
344
295 u_int32_t id;
296
297 for (i = 0; i < 32; i++)
298 codec->mix[i] = ac97mixtable_default[i];
299
300 if (codec->init) {
301 codec->count = codec->init(codec->devinfo);
302 if (codec->count == 0) {

--- 32 unchanged lines hidden (view full) ---

335 codec->extstat = 0;
336 } else {
337 i = rdcd(codec, AC97_REGEXT_ID);
338 codec->extcaps = i & 0x3fff;
339 codec->extid = (i & 0xc000) >> 14;
340 codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
341 }
342
345 wrcd(codec, AC97_MIX_MASTER, 0x20);
346 if ((rdcd(codec, AC97_MIX_MASTER) & 0x20) == 0x20)
347 codec->mix[SOUND_MIXER_VOLUME].bits++;
348 wrcd(codec, AC97_MIX_MASTER, 0x00);
343 for (i = 0; i < 32; i++) {
344 if (codec->mix[i].reg > 0) {
345 old = rdcd(codec, codec->mix[i].reg);
346 wrcd(codec, codec->mix[i].reg, 0x3f);
347 j = rdcd(codec, codec->mix[i].reg);
348 wrcd(codec, codec->mix[i].reg, old);
349 codec->mix[i].enable = j? 1 : 0;
350 for (k = 1; j & (1 << k); k++);
351 codec->mix[i].bits = j? k - codec->mix[i].ofs : 0;
352 }
353 /* printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); */
354 }
349
350 if (bootverbose) {
351 device_printf(codec->dev, "ac97 codec id 0x%08x", id);
352 if (codec->name)
353 printf(" (%s)", codec->name);
354 printf("\n");
355 device_printf(codec->dev, "ac97 codec features ");
356 for (i = j = 0; i < 10; i++)

--- 40 unchanged lines hidden (view full) ---

397{
398 free(codec, M_DEVBUF);
399}
400
401static int
402ac97mix_init(snd_mixer *m)
403{
404 struct ac97_info *codec = mix_getdevinfo(m);
355
356 if (bootverbose) {
357 device_printf(codec->dev, "ac97 codec id 0x%08x", id);
358 if (codec->name)
359 printf(" (%s)", codec->name);
360 printf("\n");
361 device_printf(codec->dev, "ac97 codec features ");
362 for (i = j = 0; i < 10; i++)

--- 40 unchanged lines hidden (view full) ---

403{
404 free(codec, M_DEVBUF);
405}
406
407static int
408ac97mix_init(snd_mixer *m)
409{
410 struct ac97_info *codec = mix_getdevinfo(m);
411 u_int32_t i, mask;
412
405 if (codec == NULL)
406 return -1;
413 if (codec == NULL)
414 return -1;
415
407 if (ac97_initmixer(codec))
408 return -1;
416 if (ac97_initmixer(codec))
417 return -1;
409 mix_setdevs(m, ac97mixdevs | ((codec->caps & 4)? SOUND_MASK_BASS | SOUND_MASK_TREBLE : 0));
410 mix_setrecdevs(m, ac97recdevs);
418
419 mask = 0;
420 for (i = 0; i < 32; i++)
421 mask |= codec->mix[i].enable? 1 << i : 0;
422 mix_setdevs(m, mask);
423
424 mask = 0;
425 for (i = 0; i < 32; i++)
426 mask |= codec->mix[i].recidx? 1 << i : 0;
427 mix_setrecdevs(m, mask);
411 return 0;
412}
413
414static int
415ac97mix_uninit(snd_mixer *m)
416{
417 struct ac97_info *codec = mix_getdevinfo(m);
428 return 0;
429}
430
431static int
432ac97mix_uninit(snd_mixer *m)
433{
434 struct ac97_info *codec = mix_getdevinfo(m);
435
418 if (codec == NULL)
419 return -1;
420 /*
421 if (ac97_uninitmixer(codec))
422 return -1;
423 */
424 ac97_destroy(codec);
425 return 0;
426}
427
428static int
429ac97mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
430{
431 struct ac97_info *codec = mix_getdevinfo(m);
436 if (codec == NULL)
437 return -1;
438 /*
439 if (ac97_uninitmixer(codec))
440 return -1;
441 */
442 ac97_destroy(codec);
443 return 0;
444}
445
446static int
447ac97mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
448{
449 struct ac97_info *codec = mix_getdevinfo(m);
450
432 if (codec == NULL)
433 return -1;
434 return ac97_setmixer(codec, dev, left, right);
435}
436
437static int
438ac97mix_setrecsrc(snd_mixer *m, u_int32_t src)
439{
440 int i;
441 struct ac97_info *codec = mix_getdevinfo(m);
451 if (codec == NULL)
452 return -1;
453 return ac97_setmixer(codec, dev, left, right);
454}
455
456static int
457ac97mix_setrecsrc(snd_mixer *m, u_int32_t src)
458{
459 int i;
460 struct ac97_info *codec = mix_getdevinfo(m);
461
442 if (codec == NULL)
443 return -1;
444 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
445 if ((src & (1 << i)) != 0)
446 break;
447 return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
448}
449
450snd_mixer ac97_mixer = {
451 "AC97 mixer",
452 ac97mix_init,
453 ac97mix_uninit,
454 ac97mix_set,
455 ac97mix_setrecsrc,
456};
457
462 if (codec == NULL)
463 return -1;
464 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
465 if ((src & (1 << i)) != 0)
466 break;
467 return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
468}
469
470snd_mixer ac97_mixer = {
471 "AC97 mixer",
472 ac97mix_init,
473 ac97mix_uninit,
474 ac97mix_set,
475 ac97mix_setrecsrc,
476};
477