patch-2.4.9 linux/drivers/sound/ac97_codec.c
Next file: linux/drivers/sound/btaudio.c
Previous file: linux/drivers/sound/Makefile
Back to the patch index
Back to the overall index
- Lines: 212
- Date:
Sun Aug 12 10:51:42 2001
- Orig file:
v2.4.8/linux/drivers/sound/ac97_codec.c
- Orig date:
Thu Apr 19 22:58:20 2001
diff -u --recursive --new-file v2.4.8/linux/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c
@@ -65,54 +65,83 @@
static int sigmatel_9708_init(struct ac97_codec *codec);
static int sigmatel_9721_init(struct ac97_codec *codec);
static int sigmatel_9744_init(struct ac97_codec *codec);
-static int enable_eapd(struct ac97_codec *codec);
+static int eapd_control(struct ac97_codec *codec, int);
+static int crystal_digital_control(struct ac97_codec *codec, int mode);
+
+
+/*
+ * AC97 operations.
+ *
+ * If you are adding a codec then you should be able to use
+ * eapd_ops - any codec that supports EAPD amp control (most)
+ * null_ops - any ancient codec that supports nothing
+ *
+ * The three functions are
+ * init - used for non AC97 standard initialisation
+ * amplifier - used to do amplifier control (1=on 0=off)
+ * digital - switch to digital modes (0 = analog)
+ *
+ * Not all codecs support all features, not all drivers use all the
+ * operations yet
+ */
+
+static struct ac97_ops null_ops = { NULL, NULL, NULL };
+static struct ac97_ops default_ops = { NULL, eapd_control, NULL };
+static struct ac97_ops wolfson_ops = { wolfson_init, NULL, NULL };
+static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL };
+static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL };
+static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL };
+static struct ac97_ops sigmatel_9721_ops = { sigmatel_9721_init, NULL, NULL };
+static struct ac97_ops sigmatel_9744_ops = { sigmatel_9744_init, NULL, NULL };
+static struct ac97_ops crystal_digital_ops = { NULL, eapd_control, crystal_digital_control };
/* sorted by vendor/device id */
static const struct {
u32 id;
char *name;
- int (*init) (struct ac97_codec *codec);
+ struct ac97_ops *ops;
} ac97_codec_ids[] = {
- {0x41445303, "Analog Devices AD1819", NULL},
- {0x41445340, "Analog Devices AD1881", NULL},
- {0x41445348, "Analog Devices AD1881A", NULL},
- {0x41445460, "Analog Devices AD1885", enable_eapd},
- {0x414B4D00, "Asahi Kasei AK4540", NULL},
- {0x414B4D01, "Asahi Kasei AK4542", NULL},
- {0x414B4D02, "Asahi Kasei AK4543", NULL},
- {0x414C4710, "ALC200/200P", NULL},
- {0x43525900, "Cirrus Logic CS4297", enable_eapd},
- {0x43525903, "Cirrus Logic CS4297", enable_eapd},
- {0x43525913, "Cirrus Logic CS4297A rev A", enable_eapd},
- {0x43525914, "Cirrus Logic CS4297A rev B", NULL},
- {0x43525923, "Cirrus Logic CS4298", NULL},
- {0x4352592B, "Cirrus Logic CS4294", NULL},
- {0x4352592D, "Cirrus Logic CS4294", NULL},
- {0x43525931, "Cirrus Logic CS4299 rev A", NULL},
- {0x43525933, "Cirrus Logic CS4299 rev C", NULL},
- {0x43525934, "Cirrus Logic CS4299 rev D", NULL},
- {0x45838308, "ESS Allegro ES1988", NULL},
- {0x49434511, "ICE1232", NULL}, /* I hope --jk */
- {0x4e534331, "National Semiconductor LM4549", NULL},
- {0x53494c22, "Silicon Laboratory Si3036", NULL},
- {0x53494c23, "Silicon Laboratory Si3038", NULL},
- {0x545200FF, "TriTech TR?????", tritech_maestro_init},
- {0x54524102, "TriTech TR28022", NULL},
- {0x54524103, "TriTech TR28023", NULL},
- {0x54524106, "TriTech TR28026", NULL},
- {0x54524108, "TriTech TR28028", tritech_init},
- {0x54524123, "TriTech TR?????", NULL},
- {0x574D4C00, "Wolfson WM9704", wolfson_init},
- {0x574D4C03, "Wolfson WM9703/9704", wolfson_init},
- {0x574D4C04, "Wolfson WM9704 (quad)", wolfson_init},
- {0x83847600, "SigmaTel STAC????", NULL},
- {0x83847604, "SigmaTel STAC9701/3/4/5", NULL},
- {0x83847605, "SigmaTel STAC9704", NULL},
- {0x83847608, "SigmaTel STAC9708", sigmatel_9708_init},
- {0x83847609, "SigmaTel STAC9721/23", sigmatel_9721_init},
- {0x83847644, "SigmaTel STAC9744/45", sigmatel_9744_init},
- {0x83847656, "SigmaTel STAC9756/57", sigmatel_9744_init},
- {0x83847684, "SigmaTel STAC9783/84?", NULL},
+ {0x41445303, "Analog Devices AD1819", &null_ops},
+ {0x41445340, "Analog Devices AD1881", &null_ops},
+ {0x41445348, "Analog Devices AD1881A", &null_ops},
+ {0x41445460, "Analog Devices AD1885", &default_ops},
+ {0x414B4D00, "Asahi Kasei AK4540", &null_ops},
+ {0x414B4D01, "Asahi Kasei AK4542", &null_ops},
+ {0x414B4D02, "Asahi Kasei AK4543", &null_ops},
+ {0x414C4710, "ALC200/200P", &null_ops},
+ {0x43525900, "Cirrus Logic CS4297", &default_ops},
+ {0x43525903, "Cirrus Logic CS4297", &default_ops},
+ {0x43525913, "Cirrus Logic CS4297A rev A", &default_ops},
+ {0x43525914, "Cirrus Logic CS4297A rev B", &default_ops},
+ {0x43525923, "Cirrus Logic CS4298", &null_ops},
+ {0x4352592B, "Cirrus Logic CS4294", &null_ops},
+ {0x4352592D, "Cirrus Logic CS4294", &null_ops},
+ {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
+ {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
+ {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
+ {0x45838308, "ESS Allegro ES1988", &null_ops},
+ {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */
+ {0x4e534331, "National Semiconductor LM4549", &null_ops},
+ {0x53494c22, "Silicon Laboratory Si3036", &null_ops},
+ {0x53494c23, "Silicon Laboratory Si3038", &null_ops},
+ {0x545200FF, "TriTech TR?????", &tritech_m_ops},
+ {0x54524102, "TriTech TR28022", &null_ops},
+ {0x54524103, "TriTech TR28023", &null_ops},
+ {0x54524106, "TriTech TR28026", &null_ops},
+ {0x54524108, "TriTech TR28028", &tritech_ops},
+ {0x54524123, "TriTech TR?????", &null_ops},
+ {0x574D4C00, "Wolfson WM9704", &wolfson_ops},
+ {0x574D4C03, "Wolfson WM9703/9704", &wolfson_ops},
+ {0x574D4C04, "Wolfson WM9704 (quad)", &wolfson_ops},
+ {0x83847600, "SigmaTel STAC????", &null_ops},
+ {0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops},
+ {0x83847605, "SigmaTel STAC9704", &null_ops},
+ {0x83847608, "SigmaTel STAC9708", &sigmatel_9708_ops},
+ {0x83847609, "SigmaTel STAC9721/23", &sigmatel_9721_ops},
+ {0x83847644, "SigmaTel STAC9744/45", &sigmatel_9744_ops},
+ {0x83847656, "SigmaTel STAC9756/57", &sigmatel_9744_ops},
+ {0x83847684, "SigmaTel STAC9783/84?", &null_ops},
+ {0x57454301, "Winbond 83971D", &null_ops},
{0,}
};
@@ -145,7 +174,7 @@
/* 24 */ "Wolfson Microelectronics 3D Enhancement",
/* 25 */ "Delta Integration 3D Enhancement",
/* 26 */ "SigmaTel 3D Enhancement",
- /* 27 */ "Reserved 27",
+ /* 27 */ "Winbond 3D Stereo Enhancement",
/* 28 */ "Rockwell 3D Stereo Enhancement",
/* 29 */ "Reserved 29",
/* 30 */ "Reserved 30",
@@ -666,7 +695,7 @@
modem = codec->codec_read(codec, AC97_EXTENDED_MODEM_ID);
codec->name = NULL;
- codec->codec_init = NULL;
+ codec->codec_ops = &null_ops;
id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
@@ -674,7 +703,7 @@
if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
codec->type = ac97_codec_ids[i].id;
codec->name = ac97_codec_ids[i].name;
- codec->codec_init = ac97_codec_ids[i].init;
+ codec->codec_ops = ac97_codec_ids[i].ops;
break;
}
}
@@ -717,8 +746,8 @@
codec->mixer_ioctl = ac97_mixer_ioctl;
/* codec specific initialization for 4-6 channel output or secondary codec stuff */
- if (codec->codec_init != NULL) {
- codec->codec_init(codec);
+ if (codec->codec_ops->init != NULL) {
+ codec->codec_ops->init(codec);
}
/* initialize mixer channel volumes */
@@ -843,17 +872,42 @@
/*
- * External AMP management for EAPD using codecs
- * (CS4279A, AD1885, ...)
+ * This is basically standard AC97. It should work as a default for
+ * almost all modern codecs. Note that some cards wire EAPD *backwards*
+ * That side of it is up to the card driver not us to cope with.
+ *
*/
-static int enable_eapd(struct ac97_codec * codec)
+static int eapd_control(struct ac97_codec * codec, int on)
{
- codec->codec_write(codec, AC97_POWER_CONTROL,
- codec->codec_read(codec, AC97_POWER_CONTROL)|0x8000);
+ if(on)
+ codec->codec_write(codec, AC97_POWER_CONTROL,
+ codec->codec_read(codec, AC97_POWER_CONTROL)|0x8000);
+ else
+ codec->codec_write(codec, AC97_POWER_CONTROL,
+ codec->codec_read(codec, AC97_POWER_CONTROL)&~0x8000);
return 0;
}
+/*
+ * Crystal digital audio control (CS4299
+ */
+
+static int crystal_digital_control(struct ac97_codec *codec, int mode)
+{
+ u16 cv;
+
+ switch(mode)
+ {
+ case 0: cv = 0x0; break; /* SPEN off */
+ case 1: cv = 0x8004; break; /* 48KHz digital */
+ case 2: cv = 0x8104; break; /* 44.1KHz digital */
+ default:
+ return -1; /* Not supported yet(eg AC3) */
+ }
+ codec->codec_write(codec, 0x68, cv);
+ return 0;
+}
/* copied from drivers/sound/maestro.c */
#if 0 /* there has been 1 person on the planet with a pt101 that we
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)