rewritten AC97 handling

trying to detect real codec rate
support for 44100 Hz is now default


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3183 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-05-08 00:22:14 +00:00
parent bffd89a7fd
commit dd04a5c6eb
6 changed files with 415 additions and 151 deletions
+190 -96
View File
@@ -29,7 +29,6 @@
#include <stdio.h>
#include <MediaDefs.h>
#include "ac97.h"
#include "config.h"
//#define DEBUG 1
@@ -76,16 +75,7 @@ const char * stereo_enhancement_technique[] =
"Unknown (31)"
};
typedef void (* codec_init)(void);
typedef void (* codec_amp_enable)(bool);
typedef struct codec_ops_tag
{
codec_init init;
codec_amp_enable amp_enable;
} codec_ops;
typedef struct codec_table_tag
typedef struct
{
uint32 id;
uint32 mask;
@@ -93,15 +83,17 @@ typedef struct codec_table_tag
const char *info;
} codec_table;
void default_init(void);
void ad1886_init(void);
void default_init(ac97_dev *dev);
void ad1886_init(ac97_dev *dev);
void default_amp_enable(bool);
void cs4299_amp_enable(bool);
void default_amp_enable(ac97_dev *dev, bool onoff);
void cs4299_amp_enable(ac97_dev *dev, bool onoff);
codec_ops default_ops = { default_init, default_amp_enable };
codec_ops ad1886_ops = { ad1886_init, default_amp_enable };
codec_ops cs4299_ops = { default_init, cs4299_amp_enable };
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_table codecs[] =
{
@@ -186,113 +178,215 @@ find_codec_table(uint32 codecid)
return codec;
}
const char *
ac97_get_3d_stereo_enhancement()
void
ac97_attach(ac97_dev **_dev, codec_reg_read reg_read, codec_reg_write reg_write, void *cookie)
{
uint16 data;
data = ich_codec_read(AC97_RESET);
data = (data >> 10) & 31;
return stereo_enhancement_technique[data];
}
int reg;
ac97_dev *dev;
codec_table *codec;
*_dev = dev = (ac97_dev *) malloc(sizeof(ac97_dev));
dev->cookie = cookie;
dev->reg_read = reg_read;
dev->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->clock = 48000; /* default clock on non-broken motherboards */
const char *
ac97_get_vendor_id_description()
{
uint32 id = ac97_get_vendor_id();
codec_table *codec = find_codec_table(id);
char f = (id >> 24) & 0xff;
char s = (id >> 16) & 0xff;
char t = (id >> 8) & 0xff;
if (f == 0) f = '?';
if (s == 0) s = '?';
if (t == 0) t = '?';
LOG(("codec %c%c%c %u\n",f,s,t,id & 0xff));
LOG(("info: %s\n",codec->info));
return codec->info;
}
/* setup register cache */
for (reg = 0; reg <= 0x7e; reg += 2)
dev->reg_cache[reg] = ac97_reg_uncached_read(dev, reg);
uint32
ac97_get_vendor_id()
{
uint16 data1;
uint16 data2;
data1 = ich_codec_read(AC97_VENDOR_ID1);
data2 = ich_codec_read(AC97_VENDOR_ID2);
return (((uint32)data1) << 16) | data2;
/* reset the codec */
LOG(("codec reset\n"));
ac97_reg_uncached_write(dev, AC97_RESET, 0x0000);
snooze(50000); // 50 ms
dev->init(dev);
dev->amp_enable(dev, true);
ac97_reg_update_bits(dev, 0x2a, 1, 1); // enable VRA
dev->codec_3d_stereo_enhancement = stereo_enhancement_technique[(ac97_reg_cached_read(dev, AC97_RESET) >> 10) & 31];
}
void
ac97_amp_enable(bool yesno)
ac97_detach(ac97_dev *dev)
{
codec_table *codec;
LOG(("ac97_amp_enable\n"));
codec = find_codec_table(ac97_get_vendor_id());
codec->ops->amp_enable(yesno);
free(dev);
}
void
ac97_init()
ac97_suspend(ac97_dev *dev)
{
codec_table *codec;
LOG(("ac97_init\n"));
codec = find_codec_table(ac97_get_vendor_id());
codec->ops->init();
dev->amp_enable(dev, false);
}
void default_init(void)
void
ac97_resume(ac97_dev *dev)
{
dev->amp_enable(dev, true);
}
void
ac97_reg_cached_write(ac97_dev *dev, uint8 reg, uint16 value)
{
if (!dev->reg_is_valid(dev, reg))
return;
dev->reg_write(dev->cookie, reg, value);
dev->reg_cache[reg] = value;
}
uint16
ac97_reg_cached_read(ac97_dev *dev, uint8 reg)
{
if (!dev->reg_is_valid(dev, reg))
return 0;
return dev->reg_cache[reg];
}
void
ac97_reg_uncached_write(ac97_dev *dev, uint8 reg, uint16 value)
{
if (!dev->reg_is_valid(dev, reg))
return;
dev->reg_write(dev->cookie, reg, value);
}
uint16
ac97_reg_uncached_read(ac97_dev *dev, uint8 reg)
{
if (!dev->reg_is_valid(dev, reg))
return 0;
return dev->reg_read(dev->cookie, reg);
}
bool
ac97_reg_update(ac97_dev *dev, uint8 reg, uint16 value)
{
if (!dev->reg_is_valid(dev, reg))
return false;
if (ac97_reg_cached_read(dev, reg) == value)
return false;
ac97_reg_cached_write(dev, reg, value);
return true;
}
bool
ac97_reg_update_bits(ac97_dev *dev, uint8 reg, uint16 mask, uint16 value)
{
uint16 old;
if (!dev->reg_is_valid(dev, reg))
return false;
old = ac97_reg_cached_read(dev, reg);
value &= mask;
value |= (old & ~mask);
if (old == value)
return false;
ac97_reg_cached_write(dev, reg, value);
return true;
}
bool
ac97_set_rate(ac97_dev *dev, uint8 reg, uint32 rate)
{
uint32 value;
uint32 old;
value = (rate * dev->clock) / 48000;
LOG(("ac97_set_rate: clock = %d, rate = %d, value = %d\n",dev->clock, rate, value));
if (value > 0xffff)
return false;
old = ac97_reg_cached_read(dev, reg);
ac97_reg_cached_write(dev, reg, value);
if (value != ac97_reg_uncached_read(dev, reg)) {
LOG(("ac97_set_rate failed, new rate %d\n", ac97_reg_uncached_read(dev, reg)));
ac97_reg_cached_write(dev, reg, old);
return false;
}
LOG(("ac97_set_rate done\n"));
return true;
}
void
ac97_set_clock(ac97_dev *dev, uint32 clock)
{
LOG(("ac97_set_clock: clock = %d\n", clock));
dev->clock = clock;
}
/*************************************************
*/
bool
default_reg_is_valid(ac97_dev *dev, uint8 reg)
{
if (reg & 1) return false;
if (reg > 0x7e) return false;
return true;
}
void default_init(ac97_dev *dev)
{
LOG(("default_init\n"));
}
void ad1886_init(void)
{
LOG(("ad1886_init\n"));
LOG(("===\n"));
LOG(("codecoffset = %d\n",config->codecoffset));
LOG(("0x26 = %#04x\n",ich_codec_read(config->codecoffset + 0x26)));
LOG(("0x2A = %#04x\n",ich_codec_read(config->codecoffset + 0x2A)));
LOG(("0x3A = %#04x\n",ich_codec_read(config->codecoffset + 0x3A)));
LOG(("0x72 = %#04x\n",ich_codec_read(config->codecoffset + 0x72)));
LOG(("0x74 = %#04x\n",ich_codec_read(config->codecoffset + 0x74)));
LOG(("0x76 = %#04x\n",ich_codec_read(config->codecoffset + 0x76)));
// ich_codec_write(config->codecoffset + 0x72, 0x0010); // enable software jack sense
// ich_codec_write(config->codecoffset + 0x72, 0x0110); // disable hardware line muting
ich_codec_write(config->codecoffset + 0x72, 0x0230);
LOG(("===\n"));
LOG(("0x26 = %#04x\n",ich_codec_read(config->codecoffset + 0x26)));
LOG(("0x2A = %#04x\n",ich_codec_read(config->codecoffset + 0x2A)));
LOG(("0x3A = %#04x\n",ich_codec_read(config->codecoffset + 0x3A)));
LOG(("0x72 = %#04x\n",ich_codec_read(config->codecoffset + 0x72)));
LOG(("0x74 = %#04x\n",ich_codec_read(config->codecoffset + 0x74)));
LOG(("0x76 = %#04x\n",ich_codec_read(config->codecoffset + 0x76)));
LOG(("===\n"));
}
void default_amp_enable(bool yesno)
void default_amp_enable(ac97_dev *dev, bool yesno)
{
LOG(("default_amp_enable\n"));
LOG(("powerdown register was = %#04x\n",ich_codec_read(config->codecoffset + AC97_POWERDOWN)));
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)
ich_codec_write(config->codecoffset + AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
else
ich_codec_write(config->codecoffset + AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) | 0x8000); /* switch off */
LOG(("powerdown register is = %#04x\n",ich_codec_read(config->codecoffset + AC97_POWERDOWN)));
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)));
}
void cs4299_amp_enable(bool yesno)
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)
{
LOG(("cs4299_amp_enable\n"));
if (yesno)
ich_codec_write(config->codecoffset + 0x68, 0x8004);
ac97_reg_cached_write(dev, 0x68, 0x8004);
else
ich_codec_write(config->codecoffset + 0x68, 0);
ac97_reg_cached_write(dev, 0x68, 0);
}
@@ -49,14 +49,63 @@ enum AC97_REGISTER {
AC97_3D_CONTROL = 0x22,
AC97_PAGING = 0x24,
AC97_POWERDOWN = 0x26,
AC97_PCM_FRONT_DAC_RATE = 0x2C,
AC97_VENDOR_ID1 = 0x7C,
AC97_VENDOR_ID2 = 0x7E
};
const char * ac97_get_3d_stereo_enhancement();
const char * ac97_get_vendor_id_description();
uint32 ac97_get_vendor_id();
void ac97_amp_enable(bool yesno);
void ac97_init();
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 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 {
uint32 capabilities;
uint16 reg_cache[0x7f];
void * cookie;
uint32 codec_id;
const char * codec_info;
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;
};
void ac97_attach(ac97_dev **dev, codec_reg_read reg_read, codec_reg_write reg_write, void *cookie);
void ac97_detach(ac97_dev *dev);
void ac97_suspend(ac97_dev *dev);
void ac97_resume(ac97_dev *dev);
void ac97_reg_cached_write(ac97_dev *dev, uint8 reg, uint16 value);
uint16 ac97_reg_cached_read(ac97_dev *dev, uint8 reg);
void ac97_reg_uncached_write(ac97_dev *dev, uint8 reg, uint16 value);
uint16 ac97_reg_uncached_read(ac97_dev *dev, uint8 reg);
bool ac97_reg_update(ac97_dev *dev, uint8 reg, uint16 value);
bool ac97_reg_update_bits(ac97_dev *dev, uint8 reg, uint16 mask, uint16 value);
bool ac97_set_rate(ac97_dev *dev, uint8 reg, uint32 rate);
void ac97_set_clock(ac97_dev *dev, uint32 clock);
#endif
@@ -35,6 +35,7 @@
#include "debug.h"
#include "ich.h"
#include "util.h"
#include "config.h"
/*
*
@@ -105,10 +106,16 @@ static status_t get_description(multi_description *data)
memcpy(data->channels,&chans,sizeof(chans));
}
data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)) {
data->output_rates = B_SR_44100;
data->input_rates = B_SR_44100;
data->max_cvsr_rate = 44100;
} else {
data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
data->max_cvsr_rate = 48000;
}
data->min_cvsr_rate = 0;
data->max_cvsr_rate = 48000;
data->output_formats = B_FMT_16BIT;
data->input_formats = B_FMT_16BIT;
@@ -143,11 +150,18 @@ static status_t get_global_format(multi_format_info *data)
data->output_latency = 0;
data->input_latency = 0;
data->timecode_kind = 0;
data->input.rate = B_SR_48000;
data->input.cvsr = 48000;
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)) {
data->input.rate = B_SR_44100;
data->input.cvsr = 44100;
data->output.rate = B_SR_44100;
data->output.cvsr = 44100;
} else {
data->input.rate = B_SR_48000;
data->input.cvsr = 48000;
data->output.rate = B_SR_48000;
data->output.cvsr = 48000;
}
data->input.format = B_FMT_16BIT;
data->output.rate = B_SR_48000;
data->output.cvsr = 48000;
data->output.format = B_FMT_16BIT;
return B_OK;
}
@@ -28,6 +28,8 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "ac97.h"
typedef struct
{
const char *name;
@@ -44,6 +46,7 @@ typedef struct
area_id area_mmbar; // ich4
area_id area_mbbar; // ich4
uint32 codecoffset;
ac97_dev *ac97;
} device_config;
extern device_config *config;
+146 -42
View File
@@ -335,6 +335,122 @@ dump_hardware_regs()
LOG(("PO ICH_REG_X_CR = %#x\n",ich_reg_read_8(ICH_REG_X_CR + ICH_REG_PO_BASE)));
}
uint16
ac97_reg_read(void *cookie, uint8 reg)
{
return ich_codec_read(config->codecoffset + reg);
}
void
ac97_reg_write(void *cookie, uint8 reg, uint16 value)
{
ich_codec_write(config->codecoffset + reg, value);
}
uint32
ich_clock_get()
{
uint32 civ1, civ2, picb;
uint32 startframe;
uint32 stopframe;
uint32 rate;
bigtime_t starttime;
bigtime_t stoptime;
do {
civ1 = ich_reg_read_8 (ICH_REG_PO_BASE + ICH_REG_X_CIV);
picb = ich_reg_read_16(ICH_REG_PO_BASE + (config->swap_reg ? ICH_REG_X_SR : ICH_REG_X_PICB));
civ2 = ich_reg_read_8 (ICH_REG_PO_BASE + ICH_REG_X_CIV);
} while (civ1 != civ2);
starttime = system_time();
startframe = (civ1 * (BUFFER_SIZE / 4));
if (picb < (BUFFER_SIZE / 4))
startframe += (BUFFER_SIZE / 4) - picb;
snooze(100000);
do {
civ1 = ich_reg_read_8 (ICH_REG_PO_BASE + ICH_REG_X_CIV);
picb = ich_reg_read_16(ICH_REG_PO_BASE + (config->swap_reg ? ICH_REG_X_SR : ICH_REG_X_PICB));
civ2 = ich_reg_read_8 (ICH_REG_PO_BASE + ICH_REG_X_CIV);
} while (civ1 != civ2);
stoptime = system_time();
stopframe = (civ1 * (BUFFER_SIZE / 4));
if (picb < (BUFFER_SIZE / 4))
stopframe += (BUFFER_SIZE / 4) - picb;
if (stopframe < startframe)
stopframe += ICH_BD_COUNT * (BUFFER_SIZE / 4);
rate = (1000000LL * (stopframe - startframe)) / (stoptime - starttime);
return rate;
}
void
ich_clock_calibrate()
{
int i, j;
#define RATES 20
uint32 rates[RATES];
uint32 rate;
if (!ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000)) {
LOG(("ich_clock_calibrate: can't set default clock rate\n"));
return;
}
if (!chan_po->running)
start_chan(chan_po);
for (i = 0; i < RATES; i++)
rates[i] = ich_clock_get();
// for (i = 0; i < RATES; i++)
// LOG(("ich_clock_calibrate: rate %ld\n", rates[i]));
// LOG(("ich_clock_calibrate: =========\n"));
for (i = 0; i < RATES; i++) {
for (j = 0; j < (RATES - 1); j++) {
if (rates[j] > rates[j + 1]) {
uint32 temp = rates[j];
rates[j] = rates[j + 1];
rates[j + 1] = temp;
}
}
}
for (i = 0; i < RATES; i++)
LOG(("ich_clock_calibrate: rate %ld\n", rates[i]));
rate = 0;
for (i = 3; i < (RATES - 3); i++)
rate += rates[i];
rate /= (RATES - 6);
LOG(("ich_clock_calibrate: finished, rate %ld\n", rate));
if (rate > (44100 - 300) && rate < (44100 + 300)) {
ac97_set_clock(config->ac97, 44100);
LOG(("ich_clock_calibrate: setting clock 44100\n"));
} else if (rate > (48000 - 300) && rate < (48000 + 300)) {
ac97_set_clock(config->ac97, 48000);
LOG(("ich_clock_calibrate: setting clock 48000\n"));
} else if (rate > (41194 - 300) && rate < (41194 + 300)) {
ac97_set_clock(config->ac97, 41194);
LOG(("ich_clock_calibrate: setting clock 41194\n"));
} else if (rate > (55930 - 300) && rate < (55930 + 300)) {
ac97_set_clock(config->ac97, 55930);
LOG(("ich_clock_calibrate: setting clock 55930\n"));
}
if ( !ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)
&& !ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000)) {
LOG(("ich_clock_calibrate: setting rates doesn't work with clock %d\n", config->ac97->clock));
LOG(("ich_clock_calibrate: reset clock\n"));
ac97_set_clock(config->ac97, 48000);
ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000);
}
}
status_t
init_driver(void)
{
@@ -514,18 +630,6 @@ init_driver(void)
chan_po->regbase = ICH_REG_PO_BASE;
chan_mc->regbase = ICH_REG_MC_BASE;
/* reset the codec */
LOG(("codec reset\n"));
ich_codec_write(config->codecoffset + 0x00, 0x0000);
snooze(50000); // 50 ms
ac97_init();
ac97_amp_enable(true);
LOG(("codec vendor id = %#08x\n",ac97_get_vendor_id()));
LOG(("codec descripton = %s\n",ac97_get_vendor_id_description()));
LOG(("codec 3d enhancement = %s\n",ac97_get_3d_stereo_enhancement()));
/* reset all channels */
reset_chan(chan_pi);
reset_chan(chan_po);
@@ -535,7 +639,13 @@ init_driver(void)
init_chan(chan_pi);
init_chan(chan_po);
init_chan(chan_mc);
ac97_attach(&config->ac97, ac97_reg_read, ac97_reg_write, NULL);
LOG(("codec vendor id = %#08x\n", config->ac97->codec_id));
LOG(("codec descripton = %s\n", config->ac97->codec_info));
LOG(("codec 3d enhancement = %s\n", config->ac97->codec_3d_stereo_enhancement));
/* first test if interrupts are working, on some Laptops they don't work :-( */
if (config->irq != 0 && false == interrupt_test()) {
LOG(("interrupt not working, using a kernel thread for polling\n"));
@@ -550,41 +660,33 @@ init_driver(void)
resume_thread(int_thread_id);
}
LOG(("codec master output = %#04x\n",ich_codec_read(config->codecoffset + 0x02)));
LOG(("codec aux output = %#04x\n",ich_codec_read(config->codecoffset + 0x04)));
LOG(("codec mono output = %#04x\n",ich_codec_read(config->codecoffset + 0x06)));
LOG(("codec pcm output = %#04x\n",ich_codec_read(config->codecoffset + 0x18)));
/* calibrate the clock */
ich_clock_calibrate();
LOG(("codec master output = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x02)));
LOG(("codec aux output = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x04)));
LOG(("codec mono output = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x06)));
LOG(("codec cd = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x12)));
LOG(("codec pcm = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x18)));
LOG(("writing codec registers\n"));
/* enable master output */
ich_codec_write(config->codecoffset + 0x02, 0x0000);
ac97_reg_update(config->ac97, 0x02, 0x0000);
/* enable aux output */
ich_codec_write(config->codecoffset + 0x04, 0x0000);
ac97_reg_update(config->ac97, 0x04, 0x0000);
/* enable mono output */
ich_codec_write(config->codecoffset + 0x06, 0x0000);
/* enable pcm output */
ich_codec_write(config->codecoffset + 0x18, 0x0404);
ac97_reg_update(config->ac97, 0x06, 0x0000);
/* enable cd */
ac97_reg_update(config->ac97, 0x12, 0x0808);
/* enable pcm */
ac97_reg_update(config->ac97, 0x18, 0x0808);
LOG(("codec master output = %#04x\n",ich_codec_read(config->codecoffset + 0x02)));
LOG(("codec aux output = %#04x\n",ich_codec_read(config->codecoffset + 0x04)));
LOG(("codec mono output = %#04x\n",ich_codec_read(config->codecoffset + 0x06)));
LOG(("codec pcm output = %#04x\n",ich_codec_read(config->codecoffset + 0x18)));
#if 0
/* enable pcm input */
ich_codec_write(config->codecoffset + 0x10, 0x0000);
/* enable mic input */
/* ich_codec_write(config->codecoffset + 0x0E, 0x0000); */
/* select pcm input record */
ich_codec_write(config->codecoffset + 0x1A, 4 | (4 << 8));
/* enable PCM record */
ich_codec_write(config->codecoffset + 0x1C, 0x0000);
/* enable mic record */
/* ich_codec_write(config->codecoffset + 0x1E, 0x0000); */
#endif
LOG(("codec master output = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x02)));
LOG(("codec aux output = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x04)));
LOG(("codec mono output = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x06)));
LOG(("codec cd = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x12)));
LOG(("codec pcm = %#04x\n", ac97_reg_uncached_read(config->ac97, 0x18)));
LOG(("init_driver finished!\n"));
return B_OK;
@@ -611,6 +713,8 @@ uninit_driver(void)
snooze(50000);
ac97_detach(config->ac97);
/* remove the interrupt handler or thread */
if (config->irq != 0) {
remove_io_interrupt_handler(config->irq,ich_int,0);
@@ -33,7 +33,7 @@
#define VERSION "Version 1.5, Copyright (c) 2002 Marcus Overhagen, compiled on " ## __DATE__ ## " " ## __TIME__
#define DRIVER_NAME "ich_ac97"
#define BUFFER_SIZE 2048
#define BUFFER_SIZE 4096
#define BUFFER_COUNT 2
#define BUFFER_FRAMES_COUNT (BUFFER_SIZE / 4)