Deleted Added
full compact
ac97.c (113907) ac97.c (119209)
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

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

25 */
26
27#include <dev/sound/pcm/sound.h>
28#include <dev/sound/pcm/ac97.h>
29#include <dev/sound/pcm/ac97_patch.h>
30
31#include "mixer_if.h"
32
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

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

25 */
26
27#include <dev/sound/pcm/sound.h>
28#include <dev/sound/pcm/ac97.h>
29#include <dev/sound/pcm/ac97_patch.h>
30
31#include "mixer_if.h"
32
33SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/ac97.c 113907 2003-04-23 16:49:53Z jhb $");
33SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/ac97.c 119209 2003-08-21 15:50:32Z orion $");
34
35MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
36
37struct ac97mixtable_entry {
38 int reg:8; /* register index */
39 /* reg < 0 if inverted polarity */
40 unsigned bits:4; /* width of control field */
41 unsigned ofs:4; /* offset (only if stereo=0) */

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

70 u_int8_t noext:1;
71 char *name;
72 ac97_patch patch;
73};
74
75static const struct ac97mixtable_entry ac97mixtable_default[32] = {
76 /* [offset] reg bits of st mu re mk en */
77 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
34
35MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
36
37struct ac97mixtable_entry {
38 int reg:8; /* register index */
39 /* reg < 0 if inverted polarity */
40 unsigned bits:4; /* width of control field */
41 unsigned ofs:4; /* offset (only if stereo=0) */

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

70 u_int8_t noext:1;
71 char *name;
72 ac97_patch patch;
73};
74
75static const struct ac97mixtable_entry ac97mixtable_default[32] = {
76 /* [offset] reg bits of st mu re mk en */
77 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
78 [SOUND_MIXER_MONITOR] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 },
78 [SOUND_MIXER_OGAIN] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 },
79 [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
80 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
81 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
82 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
83 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
84 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
85 [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
86 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },

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

119static struct ac97_codecid ac97codecid[] = {
120 { 0x41445303, 0x00, 0, "AD1819", 0 },
121 { 0x41445340, 0x00, 0, "AD1881", 0 },
122 { 0x41445348, 0x00, 0, "AD1881A", 0 },
123 { 0x41445360, 0x00, 0, "AD1885", 0 },
124 { 0x41445361, 0x00, 0, "AD1886", ad1886_patch },
125 { 0x41445362, 0x00, 0, "AD1887", 0 },
126 { 0x41445363, 0x00, 0, "AD1886A", 0 },
79 [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
80 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
81 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
82 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
83 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
84 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
85 [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
86 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },

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

119static struct ac97_codecid ac97codecid[] = {
120 { 0x41445303, 0x00, 0, "AD1819", 0 },
121 { 0x41445340, 0x00, 0, "AD1881", 0 },
122 { 0x41445348, 0x00, 0, "AD1881A", 0 },
123 { 0x41445360, 0x00, 0, "AD1885", 0 },
124 { 0x41445361, 0x00, 0, "AD1886", ad1886_patch },
125 { 0x41445362, 0x00, 0, "AD1887", 0 },
126 { 0x41445363, 0x00, 0, "AD1886A", 0 },
127 { 0x41445370, 0x00, 0, "AD1980", 0 },
127 { 0x41445370, 0x00, 0, "AD1980", ad198x_patch },
128 { 0x41445372, 0x00, 0, "AD1981A", 0 },
129 { 0x41445374, 0x00, 0, "AD1981B", 0 },
128 { 0x41445372, 0x00, 0, "AD1981A", 0 },
129 { 0x41445374, 0x00, 0, "AD1981B", 0 },
130 { 0x41445375, 0x00, 0, "AD1985", 0 },
130 { 0x41445375, 0x00, 0, "AD1985", ad198x_patch },
131 { 0x414b4d00, 0x00, 1, "AK4540", 0 },
132 { 0x414b4d01, 0x00, 1, "AK4542", 0 },
133 { 0x414b4d02, 0x00, 1, "AK4543", 0 },
134 { 0x414c4320, 0x0f, 0, "ALC100", 0 },
131 { 0x414b4d00, 0x00, 1, "AK4540", 0 },
132 { 0x414b4d01, 0x00, 1, "AK4542", 0 },
133 { 0x414b4d02, 0x00, 1, "AK4543", 0 },
134 { 0x414c4320, 0x0f, 0, "ALC100", 0 },
135 { 0x414c4730, 0x0f, 0, "ALC101", 0 },
135 { 0x414c4730, 0x0f, 0, "ALC101", 0 },
136 { 0x414c4710, 0x0f, 0, "ALC200", 0 },
137 { 0x414c4740, 0x0f, 0, "ALC202", 0 },
138 { 0x414c4720, 0x0f, 0, "ALC650", 0 },
139 { 0x43525900, 0x07, 0, "CS4297", 0 },
140 { 0x43525910, 0x07, 0, "CS4297A", 0 },
141 { 0x43525920, 0x07, 0, "CS4294/98", 0 },
142 { 0x43525930, 0x07, 0, "CS4299", 0 },
143 { 0x43525940, 0x07, 0, "CS4201", 0 },

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

399
400 if (e->reg > 0) {
401 left = 100 - left;
402 right = 100 - right;
403 }
404
405 /*
406 * For mono controls, trim val and mask, also taking
136 { 0x414c4710, 0x0f, 0, "ALC200", 0 },
137 { 0x414c4740, 0x0f, 0, "ALC202", 0 },
138 { 0x414c4720, 0x0f, 0, "ALC650", 0 },
139 { 0x43525900, 0x07, 0, "CS4297", 0 },
140 { 0x43525910, 0x07, 0, "CS4297A", 0 },
141 { 0x43525920, 0x07, 0, "CS4294/98", 0 },
142 { 0x43525930, 0x07, 0, "CS4299", 0 },
143 { 0x43525940, 0x07, 0, "CS4201", 0 },

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

399
400 if (e->reg > 0) {
401 left = 100 - left;
402 right = 100 - right;
403 }
404
405 /*
406 * For mono controls, trim val and mask, also taking
407 * care of e->ofs (offset of control field).
407 * care of e->ofs (offset of control field).
408 */
409 if (e->ofs) {
410 val &= max;
411 val <<= e->ofs;
412 mask = (max << e->ofs);
413 }
414
415 /*

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

435 snd_mtxunlock(codec->lock);
436 return left | (right << 8);
437 } else {
438 /* printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable); */
439 return -1;
440 }
441}
442
408 */
409 if (e->ofs) {
410 val &= max;
411 val <<= e->ofs;
412 mask = (max << e->ofs);
413 }
414
415 /*

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

435 snd_mtxunlock(codec->lock);
436 return left | (right << 8);
437 } else {
438 /* printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable); */
439 return -1;
440 }
441}
442
443#if 0
444static int
445ac97_getmixer(struct ac97_info *codec, int channel)
446{
447 struct ac97mixtable_entry *e = &codec->mix[channel];
448 if (channel < SOUND_MIXER_NRDEVICES && e->reg != 0) {
449 int max, val, volume;
450
451 max = (1 << e->bits) - 1;
452 val = ac97_rdcd(code, e->reg);
453 if (val == AC97_MUTE && e->mute == 1)
454 volume = 0;
455 else {
456 if (e->stereo == 0) val >>= e->ofs;
457 val &= max;
458 volume = (val * 100) / max;
459 if (e->reg > 0) volume = 100 - volume;
460 }
461 return volume;
462 } else
463 return -1;
464}
465#endif
466
467static void
468ac97_fix_auxout(struct ac97_info *codec)
469{
443static void
444ac97_fix_auxout(struct ac97_info *codec)
445{
470 /* Determine what AUXOUT really means, it can be:
446 /*
447 * Determine if AUX_OUT is a valid control.
471 *
448 *
449 * Control will read zero if not valid after a reset, other gain
450 * controls read muted (0x8000).
451 */
452 if (ac97_rdcd(codec, AC97_MIX_AUXOUT) == 0) {
453 bzero(&codec->mix[SOUND_MIXER_OGAIN],
454 sizeof(codec->mix[SOUND_MIXER_OGAIN]));
455 }
456
457 /*
458 * Determine what AUX_OUT really means, it can be:
459 *
472 * 1. Headphone out.
473 * 2. 4-Channel Out
474 * 3. True line level out (effectively master volume).
475 *
476 * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
477 */
460 * 1. Headphone out.
461 * 2. 4-Channel Out
462 * 3. True line level out (effectively master volume).
463 *
464 * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
465 */
478 if (codec->caps & AC97_CAP_HEADPHONE) {
479 /* XXX We should probably check the AUX_OUT initial value.
480 * Leave AC97_MIX_AUXOUT - SOUND_MIXER_MONITOR relationship */
481 return;
482 } else if (codec->extcaps & AC97_EXTCAP_SDAC &&
483 ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
484 /* 4-Channel Out, add an additional gain setting. */
485 codec->mix[SOUND_MIXER_OGAIN] = codec->mix[SOUND_MIXER_MONITOR];
486 } else {
487 /* Master volume is/maybe fixed in h/w, not sufficiently
488 * clear in spec to blat SOUND_MIXER_MASTER. */
489 codec->mix[SOUND_MIXER_OGAIN] = codec->mix[SOUND_MIXER_MONITOR];
466 if (codec->extcaps & AC97_EXTCAP_SDAC &&
467 ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
468 codec->mix[SOUND_MIXER_VOLUME].reg = AC97_MIXEXT_SURROUND;
469 } else if (codec->caps & AC97_CAP_HEADPHONE) {
470 /* Headphone out present/selected AUX_OUT is effectively
471 * master volume control. */
472 struct ac97mixtable_entry tmp = codec->mix[SOUND_MIXER_VOLUME];
473 codec->mix[SOUND_MIXER_VOLUME] = codec->mix[SOUND_MIXER_OGAIN];
474 codec->mix[SOUND_MIXER_OGAIN] = tmp;
490 }
475 }
491 /* Blat monitor, inappropriate label if we get here */
492 bzero(&codec->mix[SOUND_MIXER_MONITOR],
493 sizeof(codec->mix[SOUND_MIXER_MONITOR]));
494}
495
476}
477
478static void
479ac97_fix_tone(struct ac97_info *codec)
480{
481 /* Hide treble and bass if they don't exist */
482 if ((codec->caps & AC97_CAP_TONE) == 0) {
483 bzero(&codec->mix[SOUND_MIXER_BASS],
484 sizeof(codec->mix[SOUND_MIXER_BASS]));
485 bzero(&codec->mix[SOUND_MIXER_TREBLE],
486 sizeof(codec->mix[SOUND_MIXER_TREBLE]));
487 }
488}
489
496static const char*
497ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
498{
499 if (cname == NULL) {
500 sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
501 return buf;
502 }
503
504 if (vname == NULL) vname = "Unknown";
490static const char*
491ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
492{
493 if (cname == NULL) {
494 sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
495 return buf;
496 }
497
498 if (vname == NULL) vname = "Unknown";
505
499
506 if (bootverbose) {
507 sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
508 } else {
509 sprintf(buf, "%s %s AC97 Codec", vname, cname);
510 }
511 return buf;
512}
513

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

581 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
582 }
583 }
584
585 for (i = 0; i < 32; i++) {
586 codec->mix[i] = ac97mixtable_default[i];
587 }
588 ac97_fix_auxout(codec);
500 if (bootverbose) {
501 sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
502 } else {
503 sprintf(buf, "%s %s AC97 Codec", vname, cname);
504 }
505 return buf;
506}
507

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

575 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
576 }
577 }
578
579 for (i = 0; i < 32; i++) {
580 codec->mix[i] = ac97mixtable_default[i];
581 }
582 ac97_fix_auxout(codec);
583 ac97_fix_tone(codec);
589 if (codec_patch)
590 codec_patch(codec);
591
592 for (i = 0; i < 32; i++) {
593 k = codec->noext? codec->mix[i].enable : 1;
594 if (k && (codec->mix[i].reg > 0)) {
595 old = ac97_rdcd(codec, codec->mix[i].reg);
596 ac97_wrcd(codec, codec->mix[i].reg, 0x3f);

--- 210 unchanged lines hidden ---
584 if (codec_patch)
585 codec_patch(codec);
586
587 for (i = 0; i < 32; i++) {
588 k = codec->noext? codec->mix[i].enable : 1;
589 if (k && (codec->mix[i].reg > 0)) {
590 old = ac97_rdcd(codec, codec->mix[i].reg);
591 ac97_wrcd(codec, codec->mix[i].reg, 0x3f);

--- 210 unchanged lines hidden ---