diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c index 269c813bc6..a40853e986 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c @@ -29,7 +29,6 @@ #include #include #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); } diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h index dd1e16a24c..1467651690 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.h @@ -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 diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97_multi.c b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97_multi.c index fada63aa6f..3b9514ee31 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97_multi.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97_multi.c @@ -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; } diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/config.h b/src/add-ons/kernel/drivers/audio/ac97/ich/config.h index b3c16d9d88..5a6fdaa9f1 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/config.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/config.h @@ -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; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c index 2c47402620..c152352d88 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c @@ -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); diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h index cb59ff278f..02eb9d2728 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h @@ -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)