diff --git a/sys/dev/sound/pcm/ac97.c b/sys/dev/sound/pcm/ac97.c index 1ef4418b699b..2cd2d99123d1 100644 --- a/sys/dev/sound/pcm/ac97.c +++ b/sys/dev/sound/pcm/ac97.c @@ -50,8 +50,7 @@ struct ac97_info { kobj_t methods; device_t dev; void *devinfo; - char *id; - char rev; + u_int32_t id; unsigned count, caps, se, extcaps, extid, extstat, noext:1; u_int32_t flags; struct ac97mixtable_entry mix[32]; @@ -59,9 +58,16 @@ struct ac97_info { struct mtx *lock; }; +struct ac97_vendorid { + u_int32_t id; + const char *name; +}; + struct ac97_codecid { - u_int32_t id, noext:1; - char *name; + u_int32_t id; + u_int8_t stepmask; + u_int8_t noext:1; + char *name; ac97_patch patch; }; @@ -82,52 +88,92 @@ static const struct ac97mixtable_entry ac97mixtable_default[32] = { [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 } }; +static const struct ac97_vendorid ac97vendorid[] = { + { 0x41445300, "Analog Devices" }, + { 0x414b4d00, "Asahi Kasei" }, + { 0x414c4300, "Realtek" }, + { 0x414c4700, "Avance Logic" }, + { 0x43525900, "Cirrus Logic" }, + { 0x434d4900, "C-Media Electronics" }, + { 0x43585400, "Conexant" }, + { 0x45838300, "ESS Technology" }, + { 0x49434500, "ICEnsemble" }, + { 0x4e534300, "National Semiconductor" }, + { 0x50534300, "Philips Semiconductor" }, + { 0x83847600, "SigmaTel" }, + { 0x53494c00, "Silicon Laboratory" }, + { 0x54524100, "TriTech" }, + { 0x56494100, "VIA Technologies" }, + { 0x574d4c00, "Wolfson" }, + { 0x594d4800, "Yamaha" }, + { 0x00000000, NULL } +}; + static struct ac97_codecid ac97codecid[] = { - { 0x41445303, 0, "Analog Devices AD1819", 0 }, - { 0x41445340, 0, "Analog Devices AD1881", 0 }, - { 0x41445348, 0, "Analog Devices AD1881A", 0 }, - { 0x41445360, 0, "Analog Devices AD1885", 0 }, - { 0x41445361, 0, "Analog Devices AD1886", ad1886_patch }, - { 0x414b4d00, 1, "Asahi Kasei AK4540", 0 }, - { 0x414b4d01, 1, "Asahi Kasei AK4542", 0 }, - { 0x414b4d02, 1, "Asahi Kasei AK4543", 0 }, - { 0x414c4710, 0, "Avance Logic ALC200/200P", 0 }, - { 0x414c4720, 0, "Realtek ALC650", 0 }, - { 0x43525900, 0, "Cirrus Logic CS4297", 0 }, - { 0x43525903, 0, "Cirrus Logic CS4297", 0 }, - { 0x43525913, 0, "Cirrus Logic CS4297A", 0 }, - { 0x43525914, 0, "Cirrus Logic CS4297B", 0 }, - { 0x43525923, 0, "Cirrus Logic CS4294C", 0 }, - { 0x4352592b, 0, "Cirrus Logic CS4298C", 0 }, - { 0x43525931, 0, "Cirrus Logic CS4299A", 0 }, - { 0x43525933, 0, "Cirrus Logic CS4299C", 0 }, - { 0x43525934, 0, "Cirrus Logic CS4299D", 0 }, - { 0x43525941, 0, "Cirrus Logic CS4201A", 0 }, - { 0x43525951, 0, "Cirrus Logic CS4205A", 0 }, - { 0x4352595b, 0, "Cirrus Logic CS4205", 0 }, - { 0x43525961, 0, "Cirrus Logic CS4291A", 0 }, - { 0x43585429, 0, "Conexant CX20468", 0 }, - { 0x45838308, 0, "ESS Technology ES1921", 0 }, - { 0x49434511, 0, "ICEnsemble ICE1232", 0 }, - { 0x4e534331, 0, "National Semiconductor LM4549", 0 }, - { 0x83847600, 0, "SigmaTel STAC9700/9783/9784", 0 }, - { 0x83847604, 0, "SigmaTel STAC9701/9703/9704/9705", 0 }, - { 0x83847605, 0, "SigmaTel STAC9704", 0 }, - { 0x83847608, 0, "SigmaTel STAC9708/9711", 0 }, - { 0x83847609, 0, "SigmaTel STAC9721/9723", 0 }, - { 0x83847644, 0, "SigmaTel STAC9744", 0 }, - { 0x83847650, 0, "SigmaTel STAC9750", 0 }, - { 0x83847656, 0, "SigmaTel STAC9756/9757", 0 }, - { 0x53494c22, 0, "Silicon Laboratory Si3036", 0 }, - { 0x53494c23, 0, "Silicon Laboratory Si3038", 0 }, - { 0x54524103, 0, "TriTech TR?????", 0 }, - { 0x54524106, 0, "TriTech TR28026", 0 }, - { 0x54524108, 0, "TriTech TR28028", 0 }, - { 0x54524123, 0, "TriTech TR28602", 0 }, - { 0x574d4c00, 0, "Wolfson WM9701A", 0 }, - { 0x574d4c03, 0, "Wolfson WM9703/9704", 0 }, - { 0x574d4c04, 0, "Wolfson WM9704 (quad)", 0 }, - { 0, 0, NULL, 0 } + { 0x41445303, 0x00, 0, "AD1819", 0 }, + { 0x41445340, 0x00, 0, "AD1881", 0 }, + { 0x41445348, 0x00, 0, "AD1881A", 0 }, + { 0x41445360, 0x00, 0, "AD1885", 0 }, + { 0x41445361, 0x00, 0, "AD1886", ad1886_patch }, + { 0x414b4d00, 0x00, 1, "AK4540", 0 }, + { 0x414b4d01, 0x00, 1, "AK4542", 0 }, + { 0x414b4d02, 0x00, 1, "AK4543", 0 }, + { 0x414c4320, 0x0f, 0, "ALC100", 0 }, + { 0x414c4320, 0x0f, 0, "ALC101", 0 }, + { 0x414c4710, 0x0f, 0, "ALC200", 0 }, + { 0x414c4740, 0x0f, 0, "ALC202", 0 }, + { 0x414c4720, 0x0f, 0, "ALC650", 0 }, + { 0x43525900, 0x07, 0, "CS4297", 0 }, + { 0x43525910, 0x07, 0, "CS4297A", 0 }, + { 0x43525920, 0x07, 0, "CS4294/98", 0 }, + { 0x43525930, 0x07, 0, "CS4299", 0 }, + { 0x43525940, 0x07, 0, "CS4201", 0 }, + { 0x43525950, 0x07, 0, "CS4205", 0 }, + { 0x43525960, 0x07, 0, "CS4291A", 0 }, + { 0x434d4961, 0x00, 0, "CMI9739", 0 }, + { 0x434d4941, 0x00, 0, "CMI9738", 0 }, + { 0x43585429, 0x00, 0, "CX20468", 0 }, + { 0x45838308, 0x00, 0, "ES1988", 0 }, /* Formerly ES1921(?) */ + { 0x49434501, 0x00, 0, "ICE1230", 0 }, + { 0x49434511, 0x00, 0, "ICE1232", 0 }, + { 0x49434514, 0x00, 0, "ICE1232A", 0 }, + { 0x49434551, 0x00, 0, "VT1616", 0 }, /* Via badged ICE */ + { 0x4e534340, 0x00, 0, "LM4540", 0 }, /* Spec blank on revid */ + { 0x4e534343, 0x00, 0, "LM4543", 0 }, /* Ditto */ + { 0x4e534346, 0x00, 0, "LM4546A", 0 }, + { 0x4e534348, 0x00, 0, "LM4548A", 0 }, + { 0x4e534331, 0x00, 0, "LM4549", 0 }, /* (?) */ + { 0x4e534349, 0x00, 0, "LM4549A", 0 }, + { 0x4e534350, 0x00, 0, "LM4550", 0 }, + { 0x50534301, 0x00, 0, "UCB1510", 0 }, + { 0x50534304, 0x00, 0, "UCB1400", 0 }, + { 0x83847600, 0x00, 0, "STAC9700/83/84", 0 }, + { 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 }, + { 0x83847605, 0x00, 0, "STAC9704", 0 }, + { 0x83847608, 0x00, 0, "STAC9708/11", 0 }, + { 0x83847609, 0x00, 0, "STAC9721/23", 0 }, + { 0x83847644, 0x00, 0, "STAC9744/45", 0 }, + { 0x83847650, 0x00, 0, "STAC9750/51", 0 }, + { 0x83847652, 0x00, 0, "STAC9752/53", 0 }, + { 0x83847656, 0x00, 0, "STAC9756/57", 0 }, + { 0x83847658, 0x00, 0, "STAC9758/59", 0 }, + { 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */ + { 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */ + { 0x53494c22, 0x00, 0, "Si3036", 0 }, + { 0x53494c23, 0x00, 0, "Si3038", 0 }, + { 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */ + { 0x54524106, 0x00, 0, "TR28026", 0 }, + { 0x54524108, 0x00, 0, "TR28028", 0 }, + { 0x54524123, 0x00, 0, "TR28602", 0 }, + { 0x56494161, 0x00, 0, "VIA1612A", 0 }, + { 0x574d4c00, 0x00, 0, "WM9701A", 0 }, + { 0x574d4c03, 0x00, 0, "WM9703/4/7/8", 0 }, + { 0x574d4c04, 0x00, 0, "WM9704Q", 0 }, + { 0x574d4c05, 0x00, 0, "WM9705/10", 0 }, + { 0x594d4800, 0x00, 0, "YMF743", 0 }, + { 0x594d4802, 0x00, 0, "YMF752", 0 }, + { 0x594d4803, 0x00, 0, "YMF753", 0 }, + { 0, 0, 0, NULL, 0 } }; static char *ac97enhancement[] = { @@ -404,10 +450,31 @@ ac97_fix_auxout(struct ac97_info *codec) sizeof(codec->mix[SOUND_MIXER_MONITOR])); } +static const char* +ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf) +{ + if (cname == NULL) { + sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id); + return buf; + } + + if (vname == NULL) vname = "Unknown"; + + if (bootverbose) { + sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id); + } else { + sprintf(buf, "%s %s AC97 Codec", vname, cname); + } + return buf; +} + static unsigned ac97_initmixer(struct ac97_info *codec) { ac97_patch codec_patch; + const char *cname, *vname; + char desc[80]; + u_int8_t model, step; unsigned i, j, k, old; u_int32_t id; @@ -428,21 +495,35 @@ ac97_initmixer(struct ac97_info *codec) codec->se = (i & 0x7c00) >> 10; id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2); - codec->rev = id & 0x000000ff; if (id == 0 || id == 0xffffffff) { device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id); snd_mtxunlock(codec->lock); return ENODEV; } + codec->id = id; codec->noext = 0; - codec->id = NULL; codec_patch = NULL; + + cname = NULL; + model = step = 0; for (i = 0; ac97codecid[i].id; i++) { - if (ac97codecid[i].id == id) { - codec->id = ac97codecid[i].name; + u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask; + if ((ac97codecid[i].id & modelmask) == (id & modelmask)) { codec->noext = ac97codecid[i].noext; codec_patch = ac97codecid[i].patch; + cname = ac97codecid[i].name; + model = (id & modelmask) & 0xff; + step = (id & ~modelmask) & 0xff; + break; + } + } + + vname = NULL; + for (i = 0; ac97vendorid[i].id; i++) { + if (ac97vendorid[i].id == (id & 0xffffff00)) { + vname = ac97vendorid[i].name; + break; } } @@ -479,15 +560,11 @@ ac97_initmixer(struct ac97_info *codec) /* printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); */ } - if (codec->id) { - device_printf(codec->dev, "<%s ac97 codec>\n", codec->id); - } else { - device_printf(codec->dev, - " (id=0x%08x)\n", id); - } + device_printf(codec->dev, "<%s>\n", + ac97_hw_desc(codec->id, vname, cname, desc)); if (bootverbose) { - device_printf(codec->dev, "ac97 codec features "); + device_printf(codec->dev, "Codec features "); for (i = j = 0; i < 10; i++) if (codec->caps & (1 << i)) printf("%s%s", j++? ", " : "", ac97feature[i]); @@ -495,8 +572,8 @@ ac97_initmixer(struct ac97_info *codec) printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); if (codec->extcaps != 0 || codec->extid) { - device_printf(codec->dev, "ac97 %s codec", - codec->extid? "secondary" : "primary"); + device_printf(codec->dev, "%s codec", + codec->extid? "Secondary" : "Primary"); if (codec->extcaps) printf(" extended features "); for (i = j = 0; i < 14; i++)