summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/ac97.c
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-09-17 23:51:00 +0000
committercg <cg@FreeBSD.org>2000-09-17 23:51:00 +0000
commit9bd1dd51e891dac2ce769ee3a6a6917efb9fe430 (patch)
tree507ffb23f2a3a716d3451bf6a3f95df23601d4c9 /sys/dev/sound/pcm/ac97.c
parent2078d1f36cd4d10d7fba4191624fd6b5bac4ccc7 (diff)
downloadFreeBSD-src-9bd1dd51e891dac2ce769ee3a6a6917efb9fe430.zip
FreeBSD-src-9bd1dd51e891dac2ce769ee3a6a6917efb9fe430.tar.gz
dynamify- probe codec for supported channels
add channel mappings for mixer
Diffstat (limited to 'sys/dev/sound/pcm/ac97.c')
-rw-r--r--sys/dev/sound/pcm/ac97.c80
1 files changed, 50 insertions, 30 deletions
diff --git a/sys/dev/sound/pcm/ac97.c b/sys/dev/sound/pcm/ac97.c
index 8fe3662..a5aaccb 100644
--- a/sys/dev/sound/pcm/ac97.c
+++ b/sys/dev/sound/pcm/ac97.c
@@ -37,6 +37,7 @@ struct ac97mixtable_entry {
unsigned mute:1;
unsigned recidx:4;
unsigned mask:1;
+ unsigned enable:1;
};
struct ac97_info {
@@ -57,29 +58,22 @@ struct ac97_codecid {
};
static const struct ac97mixtable_entry ac97mixtable_default[32] = {
- [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0 },
- [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1 },
- [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1 },
- [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0 },
- [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0 },
- [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0 },
- [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 0 },
- [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0 },
- [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0 },
- [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0 },
- [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0 }
+ [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
+ [SOUND_MIXER_MONITOR] = { AC97_MIX_PHONES, 5, 0, 1, 1, 0, 0, 0 },
+ [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
+ [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
+ [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
+ [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
+ [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
+ [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
+ [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
+ [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 0, 1 },
+ [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
+ [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
+ [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 },
+ [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
};
-static const unsigned ac97mixdevs =
- SOUND_MASK_VOLUME |
- SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
- SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_LINE1 |
- SOUND_MASK_VIDEO | SOUND_MASK_RECLEV;
-
-static const unsigned ac97recdevs =
- SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_MIC |
- SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO;
-
static struct ac97_codecid ac97codecid[] = {
{ 0x414b4d00, 1, "Asahi Kasei AK4540 rev 0" },
{ 0x414b4d01, 1, "Asahi Kasei AK4540 rev 1" },
@@ -213,6 +207,7 @@ static int
ac97_setrecsrc(struct ac97_info *codec, int channel)
{
struct ac97mixtable_entry *e = &codec->mix[channel];
+
if (e->recidx > 0) {
int val = e->recidx - 1;
val |= val << 8;
@@ -226,7 +221,8 @@ static int
ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
{
struct ac97mixtable_entry *e = &codec->mix[channel];
- if (e->reg != 0) {
+
+ if (e->reg && e->enable && e->bits) {
int max, val, reg = (e->reg >= 0)? e->reg : -e->reg;
if (!e->stereo)
@@ -262,8 +258,10 @@ ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned
val = AC97_MUTE;
wrcd(codec, reg, val);
return left | (right << 8);
- } else
+ } else {
+ /* printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable); */
return -1;
+ }
}
#if 0
@@ -293,7 +291,7 @@ ac97_getmixer(struct ac97_info *codec, int channel)
static unsigned
ac97_initmixer(struct ac97_info *codec)
{
- unsigned i, j;
+ unsigned i, j, k, old;
u_int32_t id;
for (i = 0; i < 32; i++)
@@ -342,10 +340,18 @@ ac97_initmixer(struct ac97_info *codec)
codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
}
- wrcd(codec, AC97_MIX_MASTER, 0x20);
- if ((rdcd(codec, AC97_MIX_MASTER) & 0x20) == 0x20)
- codec->mix[SOUND_MIXER_VOLUME].bits++;
- wrcd(codec, AC97_MIX_MASTER, 0x00);
+ for (i = 0; i < 32; i++) {
+ if (codec->mix[i].reg > 0) {
+ old = rdcd(codec, codec->mix[i].reg);
+ wrcd(codec, codec->mix[i].reg, 0x3f);
+ j = rdcd(codec, codec->mix[i].reg);
+ wrcd(codec, codec->mix[i].reg, old);
+ codec->mix[i].enable = j? 1 : 0;
+ for (k = 1; j & (1 << k); k++);
+ codec->mix[i].bits = j? k - codec->mix[i].ofs : 0;
+ }
+ /* printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); */
+ }
if (bootverbose) {
device_printf(codec->dev, "ac97 codec id 0x%08x", id);
@@ -402,12 +408,23 @@ static int
ac97mix_init(snd_mixer *m)
{
struct ac97_info *codec = mix_getdevinfo(m);
+ u_int32_t i, mask;
+
if (codec == NULL)
return -1;
+
if (ac97_initmixer(codec))
return -1;
- mix_setdevs(m, ac97mixdevs | ((codec->caps & 4)? SOUND_MASK_BASS | SOUND_MASK_TREBLE : 0));
- mix_setrecdevs(m, ac97recdevs);
+
+ mask = 0;
+ for (i = 0; i < 32; i++)
+ mask |= codec->mix[i].enable? 1 << i : 0;
+ mix_setdevs(m, mask);
+
+ mask = 0;
+ for (i = 0; i < 32; i++)
+ mask |= codec->mix[i].recidx? 1 << i : 0;
+ mix_setrecdevs(m, mask);
return 0;
}
@@ -415,6 +432,7 @@ static int
ac97mix_uninit(snd_mixer *m)
{
struct ac97_info *codec = mix_getdevinfo(m);
+
if (codec == NULL)
return -1;
/*
@@ -429,6 +447,7 @@ static int
ac97mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
struct ac97_info *codec = mix_getdevinfo(m);
+
if (codec == NULL)
return -1;
return ac97_setmixer(codec, dev, left, right);
@@ -439,6 +458,7 @@ ac97mix_setrecsrc(snd_mixer *m, u_int32_t src)
{
int i;
struct ac97_info *codec = mix_getdevinfo(m);
+
if (codec == NULL)
return -1;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
OpenPOWER on IntegriCloud