Simplified initialization.
More support for proplematic codecs, special inits (patches) still need to be written after checking datasheets. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3185 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5bf06a9e02
commit
e301acb039
@ -29,16 +29,16 @@
|
||||
#include <stdio.h>
|
||||
#include <MediaDefs.h>
|
||||
#include "ac97.h"
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
#define REVERSE_EAMP_POLARITY 0
|
||||
|
||||
#include "debug.h"
|
||||
#include "io.h"
|
||||
|
||||
#define B_UTF8_REGISTERED "\xC2\xAE"
|
||||
|
||||
bool ac97_reg_is_valid(ac97_dev *dev, uint8 reg);
|
||||
void ac97_amp_enable(ac97_dev *dev, bool onoff);
|
||||
void ac97_dump_capabilities(ac97_dev *dev);
|
||||
void ac97_detect_capabilities(ac97_dev *dev);
|
||||
void ac97_detect_rates(ac97_dev *dev);
|
||||
|
||||
const char * stereo_enhancement_technique[] =
|
||||
{
|
||||
"No 3D Stereo Enhancement",
|
||||
@ -75,93 +75,94 @@ const char * stereo_enhancement_technique[] =
|
||||
"Unknown (31)"
|
||||
};
|
||||
|
||||
void default_init(ac97_dev *dev);
|
||||
void ad1819_init(ac97_dev *dev);
|
||||
void ad1881_init(ac97_dev *dev);
|
||||
void ad1885_init(ac97_dev *dev);
|
||||
void ad1886_init(ac97_dev *dev);
|
||||
void ad1980_init(ac97_dev *dev);
|
||||
void alc650_init(ac97_dev *dev);
|
||||
void stac9708_init(ac97_dev *dev);
|
||||
void stac9721_init(ac97_dev *dev);
|
||||
void stac9744_init(ac97_dev *dev);
|
||||
void stac9756_init(ac97_dev *dev);
|
||||
void tr28028_init(ac97_dev *dev);
|
||||
void wm9701_init(ac97_dev *dev);
|
||||
void wm9703_init(ac97_dev *dev);
|
||||
void wm9704_init(ac97_dev *dev);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 id;
|
||||
uint32 mask;
|
||||
codec_ops *ops;
|
||||
codec_init init;
|
||||
const char *info;
|
||||
} codec_table;
|
||||
|
||||
void default_init(ac97_dev *dev);
|
||||
void ad1886_init(ac97_dev *dev);
|
||||
void alc650_init(ac97_dev *dev);
|
||||
|
||||
void default_amp_enable(ac97_dev *dev, bool onoff);
|
||||
void cs4299_amp_enable(ac97_dev *dev, bool onoff);
|
||||
|
||||
bool default_reg_is_valid(ac97_dev *dev, uint8 reg);
|
||||
|
||||
codec_ops default_ops = { default_init, default_amp_enable, default_reg_is_valid };
|
||||
codec_ops ad1886_ops = { ad1886_init, default_amp_enable, default_reg_is_valid };
|
||||
codec_ops cs4299_ops = { default_init, cs4299_amp_enable, default_reg_is_valid };
|
||||
codec_ops alc650_ops = { alc650_init, default_amp_enable, default_reg_is_valid };
|
||||
|
||||
codec_table codecs[] =
|
||||
{
|
||||
/* Vendor ID and description imported from FreeBSD src/sys/dev/sound/pcm/ac97.c */
|
||||
{ 0x414b4d00, 0xffffffff, &default_ops, "Asahi Kasei AK4540" },
|
||||
{ 0x414b4d01, 0xffffffff, &default_ops, "Asahi Kasei AK4542" },
|
||||
{ 0x414b4d02, 0xffffffff, &default_ops, "Asahi Kasei AK4543" },
|
||||
{ 0x43525900, 0xffffffff, &default_ops, "Cirrus Logic CS4297" },
|
||||
{ 0x43525903, 0xffffffff, &default_ops, "Cirrus Logic CS4297" },
|
||||
{ 0x43525913, 0xffffffff, &default_ops, "Cirrus Logic CS4297A" },
|
||||
{ 0x43525914, 0xffffffff, &default_ops, "Cirrus Logic CS4297B" },
|
||||
{ 0x43525923, 0xffffffff, &default_ops, "Cirrus Logic CS4294C" },
|
||||
{ 0x4352592b, 0xffffffff, &default_ops, "Cirrus Logic CS4298C" },
|
||||
{ 0x43525931, 0xffffffff, &cs4299_ops, "Cirrus Logic CS4299A" },
|
||||
{ 0x43525933, 0xffffffff, &cs4299_ops, "Cirrus Logic CS4299C" },
|
||||
{ 0x43525934, 0xffffffff, &cs4299_ops, "Cirrus Logic CS4299D" },
|
||||
{ 0x43525941, 0xffffffff, &default_ops, "Cirrus Logic CS4201A" },
|
||||
{ 0x43525951, 0xffffffff, &default_ops, "Cirrus Logic CS4205A" },
|
||||
{ 0x43525961, 0xffffffff, &default_ops, "Cirrus Logic CS4291A" },
|
||||
{ 0x45838308, 0xffffffff, &default_ops, "ESS Technology ES1921" },
|
||||
{ 0x49434511, 0xffffffff, &default_ops, "ICEnsemble ICE1232" },
|
||||
{ 0x4e534331, 0xffffffff, &default_ops, "National Semiconductor LM4549" },
|
||||
{ 0x83847600, 0xffffffff, &default_ops, "SigmaTel STAC9700/9783/9784" },
|
||||
{ 0x83847604, 0xffffffff, &default_ops, "SigmaTel STAC9701/9703/9704/9705" },
|
||||
{ 0x83847605, 0xffffffff, &default_ops, "SigmaTel STAC9704" },
|
||||
{ 0x83847608, 0xffffffff, &default_ops, "SigmaTel STAC9708/9711" },
|
||||
{ 0x83847609, 0xffffffff, &default_ops, "SigmaTel STAC9721/9723" },
|
||||
{ 0x83847644, 0xffffffff, &default_ops, "SigmaTel STAC9744" },
|
||||
{ 0x83847656, 0xffffffff, &default_ops, "SigmaTel STAC9756/9757" },
|
||||
{ 0x53494c22, 0xffffffff, &default_ops, "Silicon Laboratory Si3036" },
|
||||
{ 0x53494c23, 0xffffffff, &default_ops, "Silicon Laboratory Si3038" },
|
||||
{ 0x54524103, 0xffffffff, &default_ops, "TriTech TR?????" },
|
||||
{ 0x54524106, 0xffffffff, &default_ops, "TriTech TR28026" },
|
||||
{ 0x54524108, 0xffffffff, &default_ops, "TriTech TR28028" },
|
||||
{ 0x54524123, 0xffffffff, &default_ops, "TriTech TR28602" },
|
||||
{ 0x574d4c00, 0xffffffff, &default_ops, "Wolfson WM9701A" },
|
||||
{ 0x574d4c03, 0xffffffff, &default_ops, "Wolfson WM9703/9704" },
|
||||
{ 0x574d4c04, 0xffffffff, &default_ops, "Wolfson WM9704 (quad)" },
|
||||
/* Assembled from datasheets: */
|
||||
{ 0x41445303, 0xffffffff, &default_ops, "Analog Devices AD1819B SoundPort"B_UTF8_REGISTERED },
|
||||
{ 0x41445340, 0xffffffff, &default_ops, "Analog Devices AD1881 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445348, 0xffffffff, &default_ops, "Analog Devices AD1881A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445360, 0xffffffff, &default_ops, "Analog Devices AD1885 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445361, 0xffffffff, &ad1886_ops, "Analog Devices AD1886 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445362, 0xffffffff, &default_ops, "Analog Devices AD1887 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445363, 0xffffffff, &ad1886_ops, "Analog Devices AD1886A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445371, 0xffffffff, &default_ops, "Analog Devices AD1981A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445372, 0xffffffff, &default_ops, "Analog Devices AD1981A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x414c4320, 0xfffffff0, &default_ops, "Avance Logic (Realtek) ALC100/ALC100P, RL5383/RL5522" },
|
||||
{ 0x414c4730, 0xffffffff, &default_ops, "Avance Logic (Realtek) ALC101" },
|
||||
{ 0x414c4710, 0xffffffff, &default_ops, "Avance Logic (Realtek) ALC200/ALC200A, ALC201/ALC201A" }, /* 0x4710 = ALC201 */
|
||||
{ 0x414c4720, 0xffffffff, &alc650_ops, "Avance Logic (Realtek) ALC650" }, /* 0x4720 = ALC650 */
|
||||
{ 0x414c4740, 0xffffffff, &default_ops, "Avance Logic (Realtek) ALC202/ALC202A" },
|
||||
{ CODEC_ID_AD1819, 0xffffffff, ad1819_init, "Analog Devices AD1819B SoundPort"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AD1881, 0xffffffff, ad1881_init, "Analog Devices AD1881 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AD1881A, 0xffffffff, ad1881_init, "Analog Devices AD1881A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AD1885, 0xffffffff, ad1885_init, "Analog Devices AD1885 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AD1886, 0xffffffff, ad1886_init, "Analog Devices AD1886 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AD1886A, 0xffffffff, ad1881_init, "Analog Devices AD1886A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AD1887, 0xffffffff, ad1881_init, "Analog Devices AD1887 SoundMAX"B_UTF8_REGISTERED },
|
||||
{ 0x41445370, 0xffffffff, ad1980_init, "ad?" },
|
||||
{ 0x41445371, 0xffffffff, default_init, "ad?" },
|
||||
{ 0x41445372, 0xffffffff, ad1881_init, "Analog Devices AD1981A SoundMAX"B_UTF8_REGISTERED },
|
||||
{ CODEC_ID_AK4540, 0xffffffff, default_init, "Asahi Kasei AK4540" },
|
||||
{ CODEC_ID_AK4542, 0xffffffff, default_init, "Asahi Kasei AK4542" },
|
||||
{ 0x414b4d02, 0xffffffff, default_init, "Asahi Kasei AK4543" },
|
||||
{ 0x414c4320, 0xfffffff0, default_init, "Avance Logic (Realtek) ALC100/ALC100P, RL5383/RL5522" },
|
||||
{ 0x414c4730, 0xffffffff, default_init, "Avance Logic (Realtek) ALC101" },
|
||||
{ CODEC_ID_ALC201A, 0xffffffff, default_init, "Avance Logic (Realtek) ALC200/ALC200A, ALC201/ALC201A" }, /* 0x4710 = ALC201A */
|
||||
{ 0x414c4720, 0xffffffff, alc650_init, "Avance Logic (Realtek) ALC650" }, /* 0x4720 = ALC650 */
|
||||
{ 0x414c4740, 0xffffffff, default_init, "Avance Logic (Realtek) ALC202/ALC202A" },
|
||||
{ 0x43525900, 0xffffffff, default_init, "Cirrus Logic CS4297" },
|
||||
{ 0x43525903, 0xffffffff, default_init, "Cirrus Logic CS4297" },
|
||||
{ 0x43525913, 0xffffffff, default_init, "Cirrus Logic CS4297A" },
|
||||
{ 0x43525914, 0xffffffff, default_init, "Cirrus Logic CS4297B" },
|
||||
{ 0x43525923, 0xffffffff, default_init, "Cirrus Logic CS4294C" },
|
||||
{ 0x4352592b, 0xffffffff, default_init, "Cirrus Logic CS4298C" },
|
||||
{ CODEC_ID_CS4299A, 0xffffffff, default_init, "Cirrus Logic CS4299A" },
|
||||
{ CODEC_ID_CS4299C, 0xffffffff, default_init, "Cirrus Logic CS4299C" },
|
||||
{ CODEC_ID_CS4299D, 0xffffffff, default_init, "Cirrus Logic CS4299D" },
|
||||
{ 0x43525941, 0xffffffff, default_init, "Cirrus Logic CS4201A" },
|
||||
{ 0x43525951, 0xffffffff, default_init, "Cirrus Logic CS4205A" },
|
||||
{ 0x43525961, 0xffffffff, default_init, "Cirrus Logic CS4291A" },
|
||||
{ 0x45838308, 0xffffffff, default_init, "ESS Technology ES1921" },
|
||||
{ 0x49434511, 0xffffffff, default_init, "ICEnsemble ICE1232" },
|
||||
{ 0x4e534331, 0xffffffff, default_init, "National Semiconductor LM4549" },
|
||||
{ CODEC_ID_STAC9700,0xffffffff, default_init, "SigmaTel STAC9700/9783/9784" },
|
||||
{ CODEC_ID_STAC9705,0xffffffff, default_init, "SigmaTel STAC9701/9703/9704/9705" },
|
||||
{ CODEC_ID_STAC9704,0xffffffff, default_init, "SigmaTel STAC9704" },
|
||||
{ CODEC_ID_STAC9708,0xffffffff, stac9708_init, "SigmaTel STAC9708/9711" },
|
||||
{ CODEC_ID_STAC9721,0xffffffff, stac9721_init, "SigmaTel STAC9721/9723" },
|
||||
{ CODEC_ID_STAC9744,0xffffffff, stac9744_init, "SigmaTel STAC9744" },
|
||||
{ CODEC_ID_STAC9756,0xffffffff, stac9756_init, "SigmaTel STAC9756/9757" },
|
||||
{ 0x53494c22, 0xffffffff, default_init, "Silicon Laboratory Si3036" },
|
||||
{ 0x53494c23, 0xffffffff, default_init, "Silicon Laboratory Si3038" },
|
||||
{ 0x54524103, 0xffffffff, default_init, "TriTech TR?????" },
|
||||
{ 0x54524106, 0xffffffff, default_init, "TriTech TR28026" },
|
||||
{ 0x54524108, 0xffffffff, tr28028_init, "TriTech TR28028" },
|
||||
{ 0x54524123, 0xffffffff, default_init, "TriTech TR28602" },
|
||||
{ 0x574d4c00, 0xffffffff, wm9701_init, "Wolfson WM9701A" },
|
||||
{ 0x574d4c03, 0xffffffff, wm9703_init, "Wolfson WM9703/9704" },
|
||||
{ 0x574d4c04, 0xffffffff, wm9704_init, "Wolfson WM9704 (quad)" },
|
||||
/* Vendors only: */
|
||||
{ 0x41445300, 0xffffff00, &default_ops, "Analog Devices" },
|
||||
{ 0x414b4d00, 0xffffff00, &default_ops, "Asahi Kasei" },
|
||||
{ 0x414c4700, 0xffffff00, &default_ops, "Avance Logic (Realtek)" },
|
||||
{ 0x43525900, 0xffffff00, &default_ops, "Cirrus Logic" },
|
||||
{ 0x45838300, 0xffffff00, &default_ops, "ESS Technology" },
|
||||
{ 0x49434500, 0xffffff00, &default_ops, "ICEnsemble" },
|
||||
{ 0x4e534300, 0xffffff00, &default_ops, "National Semiconductor" },
|
||||
{ 0x83847600, 0xffffff00, &default_ops, "SigmaTel" },
|
||||
{ 0x53494c00, 0xffffff00, &default_ops, "Silicon Laboratory" },
|
||||
{ 0x54524100, 0xffffff00, &default_ops, "TriTech" },
|
||||
{ 0x574d4c00, 0xffffff00, &default_ops, "Wolfson" },
|
||||
{ 0x00000000, 0x00000000, &default_ops, "Unknown" } /* must be last one, matches every codec */
|
||||
{ 0x41445300, 0xffffff00, default_init, "Analog Devices" },
|
||||
{ 0x414b4d00, 0xffffff00, default_init, "Asahi Kasei" },
|
||||
{ 0x414c4700, 0xffffff00, default_init, "Avance Logic (Realtek)" },
|
||||
{ 0x43525900, 0xffffff00, default_init, "Cirrus Logic" },
|
||||
{ 0x45838300, 0xffffff00, default_init, "ESS Technology" },
|
||||
{ 0x49434500, 0xffffff00, default_init, "ICEnsemble" },
|
||||
{ 0x4e534300, 0xffffff00, default_init, "National Semiconductor" },
|
||||
{ 0x83847600, 0xffffff00, default_init, "SigmaTel" },
|
||||
{ 0x53494c00, 0xffffff00, default_init, "Silicon Laboratory" },
|
||||
{ 0x54524100, 0xffffff00, default_init, "TriTech" },
|
||||
{ 0x574d4c00, 0xffffff00, default_init, "Wolfson" },
|
||||
{ 0x00000000, 0x00000000, default_init, "Unknown" } /* must be last one, matches every codec */
|
||||
};
|
||||
|
||||
codec_table *
|
||||
@ -188,10 +189,9 @@ ac97_attach(ac97_dev **_dev, codec_reg_read reg_read, codec_reg_write reg_write,
|
||||
dev->codec_id = (reg_read(cookie, AC97_VENDOR_ID1) << 16) | reg_read(cookie, AC97_VENDOR_ID2);
|
||||
codec = find_codec_table(dev->codec_id);
|
||||
dev->codec_info = codec->info;
|
||||
dev->init = codec->ops->init;
|
||||
dev->amp_enable = codec->ops->amp_enable;
|
||||
dev->reg_is_valid = codec->ops->reg_is_valid;
|
||||
dev->init = codec->init;
|
||||
dev->clock = 48000; /* default clock on non-broken motherboards */
|
||||
dev->reversed_eamp_polarity = false;
|
||||
|
||||
/* setup register cache */
|
||||
for (reg = 0; reg <= 0x7e; reg += 2)
|
||||
@ -201,7 +201,6 @@ ac97_attach(ac97_dev **_dev, codec_reg_read reg_read, codec_reg_write reg_write,
|
||||
LOG(("codec reset\n"));
|
||||
ac97_reg_uncached_write(dev, AC97_RESET, 0x0000);
|
||||
snooze(50000); // 50 ms
|
||||
|
||||
|
||||
dev->codec_3d_stereo_enhancement = stereo_enhancement_technique[(ac97_reg_cached_read(dev, AC97_RESET) >> 10) & 31];
|
||||
dev->capabilities = 0;
|
||||
@ -211,16 +210,17 @@ ac97_attach(ac97_dev **_dev, codec_reg_read reg_read, codec_reg_write reg_write,
|
||||
ac97_detect_capabilities(dev);
|
||||
|
||||
dev->init(dev);
|
||||
dev->amp_enable(dev, true);
|
||||
ac97_amp_enable(dev, true);
|
||||
|
||||
/* set defaults, PCM-out and CD-out enabled */
|
||||
ac97_reg_update(dev, AC97_CENTER_LFE_VOLUME, 0x0000); /* set LFE & center volume 0dB */
|
||||
ac97_reg_update(dev, AC97_SURR_VOLUME, 0x0000); /* set surround volume 0dB */
|
||||
ac97_reg_update(dev, AC97_MASTER_VOLUME, 0x0000); /* set master output 0dB */
|
||||
ac97_reg_update(dev, AC97_AUX_OUT_VOLUME, 0x0000); /* set aux output 0dB */
|
||||
ac97_reg_update(dev, AC97_MONO_VOLUME, 0x0000); /* set mono output 0dB */
|
||||
ac97_reg_update(dev, AC97_CD_VOLUME, 0x0808); /* enable cd */
|
||||
ac97_reg_update(dev, AC97_PCM_OUT_VOLUME, 0x0808); /* enable pcm */
|
||||
/* set mixer defaults, enabled Line-out sources are PCM-out, CD-in, Line-in */
|
||||
ac97_reg_update(dev, AC97_CENTER_LFE_VOLUME, 0x0000); /* set LFE & center volume 0dB */
|
||||
ac97_reg_update(dev, AC97_SURR_VOLUME, 0x0000); /* set surround volume 0dB */
|
||||
ac97_reg_update(dev, AC97_MASTER_VOLUME, 0x0000); /* set master output 0dB */
|
||||
ac97_reg_update(dev, AC97_AUX_OUT_VOLUME, 0x0000); /* set aux output 0dB */
|
||||
ac97_reg_update(dev, AC97_MONO_VOLUME, 0x0000); /* set mono output 0dB */
|
||||
ac97_reg_update(dev, AC97_PCM_OUT_VOLUME, 0x0808); /* enable pcm-out */
|
||||
ac97_reg_update(dev, AC97_CD_VOLUME, 0x0808); /* enable cd-in */
|
||||
ac97_reg_update(dev, AC97_LINE_IN_VOLUME, 0x0808); /* enable line-in */
|
||||
|
||||
ac97_dump_capabilities(dev);
|
||||
}
|
||||
@ -234,19 +234,19 @@ ac97_detach(ac97_dev *dev)
|
||||
void
|
||||
ac97_suspend(ac97_dev *dev)
|
||||
{
|
||||
dev->amp_enable(dev, false);
|
||||
ac97_amp_enable(dev, false);
|
||||
}
|
||||
|
||||
void
|
||||
ac97_resume(ac97_dev *dev)
|
||||
{
|
||||
dev->amp_enable(dev, true);
|
||||
ac97_amp_enable(dev, true);
|
||||
}
|
||||
|
||||
void
|
||||
ac97_reg_cached_write(ac97_dev *dev, uint8 reg, uint16 value)
|
||||
{
|
||||
if (!dev->reg_is_valid(dev, reg))
|
||||
if (!ac97_reg_is_valid(dev, reg))
|
||||
return;
|
||||
dev->reg_write(dev->cookie, reg, value);
|
||||
dev->reg_cache[reg] = value;
|
||||
@ -255,7 +255,7 @@ ac97_reg_cached_write(ac97_dev *dev, uint8 reg, uint16 value)
|
||||
uint16
|
||||
ac97_reg_cached_read(ac97_dev *dev, uint8 reg)
|
||||
{
|
||||
if (!dev->reg_is_valid(dev, reg))
|
||||
if (!ac97_reg_is_valid(dev, reg))
|
||||
return 0;
|
||||
return dev->reg_cache[reg];
|
||||
}
|
||||
@ -263,7 +263,7 @@ ac97_reg_cached_read(ac97_dev *dev, uint8 reg)
|
||||
void
|
||||
ac97_reg_uncached_write(ac97_dev *dev, uint8 reg, uint16 value)
|
||||
{
|
||||
if (!dev->reg_is_valid(dev, reg))
|
||||
if (!ac97_reg_is_valid(dev, reg))
|
||||
return;
|
||||
dev->reg_write(dev->cookie, reg, value);
|
||||
}
|
||||
@ -271,7 +271,7 @@ ac97_reg_uncached_write(ac97_dev *dev, uint8 reg, uint16 value)
|
||||
uint16
|
||||
ac97_reg_uncached_read(ac97_dev *dev, uint8 reg)
|
||||
{
|
||||
if (!dev->reg_is_valid(dev, reg))
|
||||
if (!ac97_reg_is_valid(dev, reg))
|
||||
return 0;
|
||||
return dev->reg_read(dev->cookie, reg);
|
||||
}
|
||||
@ -279,7 +279,7 @@ ac97_reg_uncached_read(ac97_dev *dev, uint8 reg)
|
||||
bool
|
||||
ac97_reg_update(ac97_dev *dev, uint8 reg, uint16 value)
|
||||
{
|
||||
if (!dev->reg_is_valid(dev, reg))
|
||||
if (!ac97_reg_is_valid(dev, reg))
|
||||
return false;
|
||||
if (ac97_reg_cached_read(dev, reg) == value)
|
||||
return false;
|
||||
@ -291,7 +291,7 @@ bool
|
||||
ac97_reg_update_bits(ac97_dev *dev, uint8 reg, uint16 mask, uint16 value)
|
||||
{
|
||||
uint16 old;
|
||||
if (!dev->reg_is_valid(dev, reg))
|
||||
if (!ac97_reg_is_valid(dev, reg))
|
||||
return false;
|
||||
old = ac97_reg_cached_read(dev, reg);
|
||||
value &= mask;
|
||||
@ -515,14 +515,85 @@ ac97_dump_capabilities(ac97_dev *dev)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* Codec specific initialization, etc.
|
||||
*/
|
||||
|
||||
bool
|
||||
default_reg_is_valid(ac97_dev *dev, uint8 reg)
|
||||
ac97_reg_is_valid(ac97_dev *dev, uint8 reg)
|
||||
{
|
||||
if (reg & 1) return false;
|
||||
if (reg > 0x7e) return false;
|
||||
return true;
|
||||
if (reg & 1)
|
||||
return false;
|
||||
if (reg > 0x7e)
|
||||
return false;
|
||||
|
||||
switch (dev->codec_id) {
|
||||
case CODEC_ID_ALC201A:
|
||||
if (reg != 0x56)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
case CODEC_ID_AK4540:
|
||||
case CODEC_ID_AK4542:
|
||||
if (reg < 0x1e || reg == 0x20 || reg == 0x26 || reg > 0x7a)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
case CODEC_ID_AD1819:
|
||||
case CODEC_ID_AD1881:
|
||||
case CODEC_ID_AD1881A:
|
||||
if (reg < 0x3a || reg > 0x6e)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
case CODEC_ID_AD1885:
|
||||
case CODEC_ID_AD1886:
|
||||
case CODEC_ID_AD1886A:
|
||||
case CODEC_ID_AD1887:
|
||||
if (reg < 0x3c || reg == 0x5a || reg > 0x6e)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
case CODEC_ID_STAC9700:
|
||||
case CODEC_ID_STAC9704:
|
||||
case CODEC_ID_STAC9705:
|
||||
case CODEC_ID_STAC9708:
|
||||
case CODEC_ID_STAC9721:
|
||||
case CODEC_ID_STAC9744:
|
||||
case CODEC_ID_STAC9756:
|
||||
if (reg < 0x3c || reg > 0x58)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ac97_amp_enable(ac97_dev *dev, bool yesno)
|
||||
{
|
||||
switch (dev->codec_id) {
|
||||
case CODEC_ID_CS4299A:
|
||||
case CODEC_ID_CS4299C:
|
||||
case CODEC_ID_CS4299D:
|
||||
LOG(("cs4299_amp_enable\n"));
|
||||
if (yesno)
|
||||
ac97_reg_cached_write(dev, 0x68, 0x8004);
|
||||
else
|
||||
ac97_reg_cached_write(dev, 0x68, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(("ac97_amp_enable, reverse eamp = %d\n", dev->reversed_eamp_polarity));
|
||||
LOG(("powerdown register was = %#04x\n", ac97_reg_uncached_read(dev, AC97_POWERDOWN)));
|
||||
if (dev->reversed_eamp_polarity)
|
||||
yesno = !yesno;
|
||||
if (yesno)
|
||||
ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
|
||||
else
|
||||
ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) | 0x8000); /* switch off */
|
||||
LOG(("powerdown register is = %#04x\n", ac97_reg_uncached_read(dev, AC97_POWERDOWN)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void default_init(ac97_dev *dev)
|
||||
@ -530,66 +601,84 @@ void default_init(ac97_dev *dev)
|
||||
LOG(("default_init\n"));
|
||||
}
|
||||
|
||||
void default_amp_enable(ac97_dev *dev, bool yesno)
|
||||
void ad1819_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("default_amp_enable\n"));
|
||||
LOG(("powerdown register was = %#04x\n", ac97_reg_uncached_read(dev, AC97_POWERDOWN)));
|
||||
#if REVERSE_EAMP_POLARITY
|
||||
yesno = !yesno;
|
||||
LOG(("using reverse eamp polarity\n"));
|
||||
#endif
|
||||
if (yesno)
|
||||
ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
|
||||
else
|
||||
ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) | 0x8000); /* switch off */
|
||||
LOG(("powerdown register is = %#04x\n", ac97_reg_uncached_read(dev, AC97_POWERDOWN)));
|
||||
LOG(("ad1819_init\n"));
|
||||
}
|
||||
|
||||
void ad1881_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("ad1881_init\n"));
|
||||
}
|
||||
|
||||
void ad1885_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("ad1885_init\n"));
|
||||
}
|
||||
|
||||
void ad1886_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("ad1886_init\n"));
|
||||
|
||||
LOG(("===\n"));
|
||||
LOG(("0x26 = %#04x\n", ac97_reg_uncached_read(dev, 0x26)));
|
||||
LOG(("0x2A = %#04x\n", ac97_reg_uncached_read(dev, 0x2A)));
|
||||
LOG(("0x3A = %#04x\n", ac97_reg_uncached_read(dev, 0x3A)));
|
||||
LOG(("0x72 = %#04x\n", ac97_reg_uncached_read(dev, 0x72)));
|
||||
LOG(("0x74 = %#04x\n", ac97_reg_uncached_read(dev, 0x74)));
|
||||
LOG(("0x76 = %#04x\n", ac97_reg_uncached_read(dev, 0x76)));
|
||||
|
||||
// ich_codec_write(config->codecoffset + 0x72, 0x0010); // enable software jack sense
|
||||
// ich_codec_write(config->codecoffset + 0x72, 0x0110); // disable hardware line muting
|
||||
|
||||
ac97_reg_cached_write(dev, 0x72, 0x0230);
|
||||
|
||||
LOG(("===\n"));
|
||||
LOG(("0x26 = %#04x\n", ac97_reg_uncached_read(dev, 0x26)));
|
||||
LOG(("0x2A = %#04x\n", ac97_reg_uncached_read(dev, 0x2A)));
|
||||
LOG(("0x3A = %#04x\n", ac97_reg_uncached_read(dev, 0x3A)));
|
||||
LOG(("0x72 = %#04x\n", ac97_reg_uncached_read(dev, 0x72)));
|
||||
LOG(("0x74 = %#04x\n", ac97_reg_uncached_read(dev, 0x74)));
|
||||
LOG(("0x76 = %#04x\n", ac97_reg_uncached_read(dev, 0x76)));
|
||||
|
||||
LOG(("===\n"));
|
||||
}
|
||||
|
||||
void cs4299_amp_enable(ac97_dev *dev, bool yesno)
|
||||
void ad1980_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("cs4299_amp_enable\n"));
|
||||
if (yesno)
|
||||
ac97_reg_cached_write(dev, 0x68, 0x8004);
|
||||
else
|
||||
ac97_reg_cached_write(dev, 0x68, 0);
|
||||
LOG(("ad1980_init\n"));
|
||||
}
|
||||
|
||||
|
||||
void alc650_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("alc650_init\n"));
|
||||
/* Surround, LFE and Center downmixed into Line-out,
|
||||
* Surround-out is duplicated Line-out.
|
||||
|
||||
/* Enable Surround, LFE and Center downmix into Line-out,
|
||||
* Set Surround-out as duplicated Line-out.
|
||||
*/
|
||||
ac97_reg_cached_write(dev, AC97_ALC650_MULTI_CHAN_CTRL, 0x0007);
|
||||
|
||||
/* Set Surround DAC Volume to 0dB
|
||||
* Set Center/LFE DAC Volume to 0dB
|
||||
* (but both should already be set, as these are hardware reset defaults)
|
||||
*/
|
||||
ac97_reg_cached_write(dev, AC97_ALC650_SURR_VOLUME, 0x0808);
|
||||
ac97_reg_cached_write(dev, AC97_ALC650_CEN_LFE_VOLUME, 0x0808);
|
||||
}
|
||||
|
||||
void stac9708_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("stac9708_init\n"));
|
||||
}
|
||||
|
||||
void stac9721_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("stac9721_init\n"));
|
||||
}
|
||||
|
||||
void stac9744_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("stac9744_init\n"));
|
||||
}
|
||||
|
||||
void stac9756_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("stac9756_init\n"));
|
||||
}
|
||||
|
||||
void tr28028_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("tr28028_init\n"));
|
||||
}
|
||||
|
||||
void wm9701_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("wm9701_init\n"));
|
||||
}
|
||||
|
||||
void wm9703_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("wm9703_init\n"));
|
||||
}
|
||||
|
||||
void wm9704_init(ac97_dev *dev)
|
||||
{
|
||||
LOG(("wm9704_init\n"));
|
||||
}
|
||||
|
@ -99,6 +99,30 @@ enum {
|
||||
EXID_ID1 = 0x8000
|
||||
};
|
||||
|
||||
// some codec_ids
|
||||
enum {
|
||||
CODEC_ID_ALC201A = 0x414c4710,
|
||||
CODEC_ID_AK4540 = 0x414b4d00,
|
||||
CODEC_ID_AK4542 = 0x414b4d01,
|
||||
CODEC_ID_AD1819 = 0x41445303,
|
||||
CODEC_ID_AD1881 = 0x41445340,
|
||||
CODEC_ID_AD1881A = 0x41445348,
|
||||
CODEC_ID_AD1885 = 0x41445360,
|
||||
CODEC_ID_AD1886 = 0x41445361,
|
||||
CODEC_ID_AD1886A = 0x41445363,
|
||||
CODEC_ID_AD1887 = 0x41445362,
|
||||
CODEC_ID_CS4299A = 0x43525931,
|
||||
CODEC_ID_CS4299C = 0x43525933,
|
||||
CODEC_ID_CS4299D = 0x43525934,
|
||||
CODEC_ID_STAC9700 = 0x83847600, // TODO: verify all SigmaTel IDs and descriptions
|
||||
CODEC_ID_STAC9704 = 0x83847605,
|
||||
CODEC_ID_STAC9705 = 0x83847604,
|
||||
CODEC_ID_STAC9708 = 0x83847608,
|
||||
CODEC_ID_STAC9721 = 0x83847609,
|
||||
CODEC_ID_STAC9744 = 0x83847644,
|
||||
CODEC_ID_STAC9756 = 0x83847656,
|
||||
};
|
||||
|
||||
// capabilities
|
||||
enum {
|
||||
CAP_PCM_MIC = 0x0000000000000001ULL, /* dedicated mic PCM channel */
|
||||
@ -144,19 +168,10 @@ enum {
|
||||
struct ac97_dev;
|
||||
typedef struct ac97_dev ac97_dev;
|
||||
|
||||
typedef void (* codec_init)(ac97_dev * /*dev*/);
|
||||
typedef void (* codec_amp_enable)(ac97_dev */*dev*/, bool /*onoff*/);
|
||||
typedef bool (* codec_reg_is_valid)(ac97_dev */*dev*/, uint8 /*reg*/);
|
||||
typedef void (* codec_init)(ac97_dev * dev);
|
||||
typedef uint16 (* codec_reg_read)(void * /*cookie*/, uint8 /*reg*/);
|
||||
typedef void (* codec_reg_write)(void * /*cookie*/, uint8 /*reg*/, uint16 /*value*/);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
codec_init init;
|
||||
codec_amp_enable amp_enable;
|
||||
codec_reg_is_valid reg_is_valid;
|
||||
} codec_ops;
|
||||
|
||||
struct ac97_dev {
|
||||
uint16 reg_cache[0x7f];
|
||||
|
||||
@ -167,14 +182,12 @@ struct ac97_dev {
|
||||
const char * codec_3d_stereo_enhancement;
|
||||
|
||||
codec_init init;
|
||||
codec_amp_enable amp_enable;
|
||||
codec_reg_is_valid reg_is_valid;
|
||||
codec_reg_read reg_read;
|
||||
codec_reg_write reg_write;
|
||||
|
||||
uint32 clock;
|
||||
uint64 capabilities;
|
||||
|
||||
bool reversed_eamp_polarity;
|
||||
};
|
||||
|
||||
|
||||
@ -196,9 +209,4 @@ bool ac97_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate);
|
||||
|
||||
void ac97_set_clock(ac97_dev *dev, uint32 clock);
|
||||
|
||||
void ac97_dump_capabilities(ac97_dev *dev);
|
||||
|
||||
void ac97_detect_capabilities(ac97_dev *dev);
|
||||
void ac97_detect_rates(ac97_dev *dev);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user