updated to version 1.6c

fixed capability checking
no longer set clock rate if codec doesn't support continuous frame rates


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4914 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-10-01 16:55:46 +00:00
parent 44979b77a2
commit 038616df89
6 changed files with 95 additions and 102 deletions
@@ -500,76 +500,77 @@ void
ac97_dump_capabilities(ac97_dev *dev) ac97_dump_capabilities(ac97_dev *dev)
{ {
LOG(("AC97 capabilities:\n")); LOG(("AC97 capabilities:\n"));
if (dev->capabilities & CAP_PCM_MIC) if (ac97_has_capability(dev, CAP_PCM_MIC))
LOG(("CAP_PCM_MIC\n")); LOG(("CAP_PCM_MIC\n"));
if (dev->capabilities & CAP_BASS_TREBLE_CTRL) if (ac97_has_capability(dev, CAP_BASS_TREBLE_CTRL))
LOG(("CAP_BASS_TREBLE_CTRL\n")); LOG(("CAP_BASS_TREBLE_CTRL\n"));
if (dev->capabilities & CAP_SIMULATED_STEREO) if (ac97_has_capability(dev, CAP_SIMULATED_STEREO))
LOG(("CAP_SIMULATED_STEREO\n")); LOG(("CAP_SIMULATED_STEREO\n"));
if (dev->capabilities & CAP_HEADPHONE_OUT) if (ac97_has_capability(dev, CAP_HEADPHONE_OUT))
LOG(("CAP_HEADPHONE_OUT\n")); LOG(("CAP_HEADPHONE_OUT\n"));
if (dev->capabilities & CAP_LAUDNESS) if (ac97_has_capability(dev, CAP_LAUDNESS))
LOG(("CAP_LAUDNESS\n")); LOG(("CAP_LAUDNESS\n"));
if (dev->capabilities & CAP_DAC_18BIT) if (ac97_has_capability(dev, CAP_DAC_18BIT))
LOG(("CAP_DAC_18BIT\n")); LOG(("CAP_DAC_18BIT\n"));
if (dev->capabilities & CAP_DAC_20BIT) if (ac97_has_capability(dev, CAP_DAC_20BIT))
LOG(("CAP_DAC_20BIT\n")); LOG(("CAP_DAC_20BIT\n"));
if (dev->capabilities & CAP_ADC_18BIT) if (ac97_has_capability(dev, CAP_ADC_18BIT))
LOG(("CAP_ADC_18BIT\n")); LOG(("CAP_ADC_18BIT\n"));
if (dev->capabilities & CAP_ADC_20BIT) if (ac97_has_capability(dev, CAP_ADC_20BIT))
LOG(("CAP_ADC_20BIT\n")); LOG(("CAP_ADC_20BIT\n"));
if (dev->capabilities & CAP_3D_ENHANCEMENT) if (ac97_has_capability(dev, CAP_3D_ENHANCEMENT))
LOG(("CAP_3D_ENHANCEMENT\n")); LOG(("CAP_3D_ENHANCEMENT\n"));
if (dev->capabilities & CAP_VARIABLE_PCM) if (ac97_has_capability(dev, CAP_VARIABLE_PCM))
LOG(("CAP_VARIABLE_PCM\n")); LOG(("CAP_VARIABLE_PCM\n"));
if (dev->capabilities & CAP_DOUBLE_PCM) if (ac97_has_capability(dev, CAP_DOUBLE_PCM))
LOG(("CAP_DOUBLE_PCM\n")); LOG(("CAP_DOUBLE_PCM\n"));
if (dev->capabilities & CAP_VARIABLE_MIC) if (ac97_has_capability(dev, CAP_VARIABLE_MIC))
LOG(("CAP_VARIABLE_MIC\n")); LOG(("CAP_VARIABLE_MIC\n"));
if (dev->capabilities & CAP_CENTER_DAC) if (ac97_has_capability(dev, CAP_CENTER_DAC))
LOG(("CAP_CENTER_DAC\n")); LOG(("CAP_CENTER_DAC\n"));
if (dev->capabilities & CAP_SURR_DAC) if (ac97_has_capability(dev, CAP_SURR_DAC))
LOG(("CAP_SURR_DAC\n")); LOG(("CAP_SURR_DAC\n"));
if (dev->capabilities & CAP_LFE_DAC) if (ac97_has_capability(dev, CAP_LFE_DAC))
LOG(("CAP_LFE_DAC\n")); LOG(("CAP_LFE_DAC\n"));
if (dev->capabilities & CAP_AMAP) if (ac97_has_capability(dev, CAP_AMAP))
LOG(("CAP_AMAP\n")); LOG(("CAP_AMAP\n"));
if (dev->capabilities & CAP_REV21) if (ac97_has_capability(dev, CAP_REV21))
LOG(("CAP_REV21\n")); LOG(("CAP_REV21\n"));
if (dev->capabilities & CAP_REV22) if (ac97_has_capability(dev, CAP_REV22))
LOG(("CAP_REV22\n")); LOG(("CAP_REV22\n"));
if (dev->capabilities & CAP_REV23) if (ac97_has_capability(dev, CAP_REV23))
LOG(("CAP_REV23\n")); LOG(("CAP_REV23\n"));
if (dev->capabilities & CAP_PCM_RATE_CONTINUOUS) if (ac97_has_capability(dev, CAP_PCM_RATE_CONTINUOUS))
LOG(("CAP_PCM_RATE_CONTINUOUS\n")); LOG(("CAP_PCM_RATE_CONTINUOUS\n"));
if (dev->capabilities & CAP_PCM_RATE_8000) if (ac97_has_capability(dev, CAP_PCM_RATE_8000))
LOG(("CAP_PCM_RATE_8000\n")); LOG(("CAP_PCM_RATE_8000\n"));
if (dev->capabilities & CAP_PCM_RATE_11025) if (ac97_has_capability(dev, CAP_PCM_RATE_11025))
LOG(("CAP_PCM_RATE_11025\n")); LOG(("CAP_PCM_RATE_11025\n"));
if (dev->capabilities & CAP_PCM_RATE_12000) if (ac97_has_capability(dev, CAP_PCM_RATE_12000))
LOG(("CAP_PCM_RATE_12000\n")); LOG(("CAP_PCM_RATE_12000\n"));
if (dev->capabilities & CAP_PCM_RATE_16000) if (ac97_has_capability(dev, CAP_PCM_RATE_16000))
LOG(("CAP_PCM_RATE_16000\n")); LOG(("CAP_PCM_RATE_16000\n"));
if (dev->capabilities & CAP_PCM_RATE_22050) if (ac97_has_capability(dev, CAP_PCM_RATE_22050))
LOG(("CAP_PCM_RATE_22050\n")); LOG(("CAP_PCM_RATE_22050\n"));
if (dev->capabilities & CAP_PCM_RATE_24000) if (ac97_has_capability(dev, CAP_PCM_RATE_24000))
LOG(("CAP_PCM_RATE_24000\n")); LOG(("CAP_PCM_RATE_24000\n"));
if (dev->capabilities & CAP_PCM_RATE_32000) if (ac97_has_capability(dev, CAP_PCM_RATE_32000))
LOG(("CAP_PCM_RATE_32000\n")); LOG(("CAP_PCM_RATE_32000\n"));
if (dev->capabilities & CAP_PCM_RATE_44100) if (ac97_has_capability(dev, CAP_PCM_RATE_44100))
LOG(("CAP_PCM_RATE_44100\n")); LOG(("CAP_PCM_RATE_44100\n"));
if (dev->capabilities & CAP_PCM_RATE_48000) if (ac97_has_capability(dev, CAP_PCM_RATE_48000))
LOG(("CAP_PCM_RATE_48000\n")); LOG(("CAP_PCM_RATE_48000\n"));
if (dev->capabilities & CAP_PCM_RATE_88200) if (ac97_has_capability(dev, CAP_PCM_RATE_88200))
LOG(("CAP_PCM_RATE_88200\n")); LOG(("CAP_PCM_RATE_88200\n"));
if (dev->capabilities & CAP_PCM_RATE_96000) if (ac97_has_capability(dev, CAP_PCM_RATE_96000))
LOG(("CAP_PCM_RATE_96000\n")); LOG(("CAP_PCM_RATE_96000\n"));
} }
bool bool
ac97_has_capability(ac97_dev *dev, uint64 cap) ac97_has_capability(ac97_dev *dev, uint64 cap)
{ {
return (dev->capabilities & cap); // return (dev->capabilities & cap); // does not work! GCC bug with 64 bit variables?
return (dev->capabilities & cap) != 0;
} }
/************************************************* /*************************************************
@@ -38,8 +38,6 @@
device_config c; device_config c;
device_config *config = &c; device_config *config = &c;
status_t find_pci_pin_irq(uint8 pin, uint8 *irq);
/* /*
* search for the ICH AC97 controller, and initialize the global config * search for the ICH AC97 controller, and initialize the global config
* XXX multiple controllers not supported * XXX multiple controllers not supported
@@ -163,21 +161,13 @@ status_t probe_device(void)
#endif #endif
config->irq = pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x3C, 1); config->irq = pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x3C, 1);
if (config->irq == 0 || config->irq == 0xff) { if (config->irq == 0xff) {
// workaround: even if no irq is configured, we may be able to find the correct one // always 0, not 0xff if no irq assigned
uint8 pin; config->irq = 0;
uint8 irq;
pin = pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x3d, 1);
LOG(("IRQ not assigned to pin %d\n",pin));
LOG(("Searching for IRQ...\n"));
if (B_OK == find_pci_pin_irq(pin, &irq)) {
LOG(("Assigning IRQ %d to pin %d\n",irq,pin));
config->irq = irq;
} else {
config->irq = 0; // always 0, not 0xff if no irq assigned
} }
if (config->irq == 0) {
LOG(("IRQ not assigned to pin %d\n", pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x3d, 1)));
} }
if (config->type & TYPE_ICH4) { if (config->type & TYPE_ICH4) {
// memory mapped access // memory mapped access
config->mmbar = 0xfffffffe & pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x18, 4); config->mmbar = 0xfffffffe & pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x18, 4);
@@ -217,44 +207,3 @@ status_t probe_device(void)
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
return result; return result;
} }
/*
* This is another ugly workaround. If no irq has been assigned
* to our card, we try to find another card that uses the same
* interrupt pin, but has an irq assigned, and use it.
*/
status_t find_pci_pin_irq(uint8 pin, uint8 *irq)
{
pci_module_info *module;
struct pci_info info;
status_t result;
long index;
if (get_module(B_PCI_MODULE_NAME,(module_info **)&module) < 0) {
PRINT(("ERROR: couldn't load pci module\n"));
return B_ERROR;
}
result = B_ERROR;
for (index = 0; B_OK == module->get_nth_pci_info(index, &info); index++) {
uint8 pciirq = module->read_pci_config(info.bus, info.device, info.function, PCI_interrupt_line, 1);
uint8 pcipin = module->read_pci_config(info.bus, info.device, info.function, PCI_interrupt_pin, 1);
LOG(("pin %d, irq %d\n",pcipin,pciirq));
if (pcipin == pin && pciirq != 0 && pciirq != 0xff) {
*irq = pciirq;
result = B_OK;
break;
}
}
#if DEBUG
if (result != B_OK) {
LOG(("Couldn't find IRQ for pin %d\n",pin));
}
#endif
put_module(B_PCI_MODULE_NAME);
return result;
}
@@ -50,7 +50,7 @@ void debug_printf(const char *text,...)
static const char * logfile="/boot/home/ich_ac97.log"; static const char * logfile="/boot/home/ich_ac97.log";
static sem_id loglock; static sem_id loglock;
void log_create() void log_create(void)
{ {
int fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); int fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
const char *text = DRIVER_NAME ", " VERSION "\n"; const char *text = DRIVER_NAME ", " VERSION "\n";
@@ -54,7 +54,7 @@ void debug_printf(const char *text,...);
#define LOG(a) log_printf a #define LOG(a) log_printf a
#define LOG_CREATE() log_create() #define LOG_CREATE() log_create()
#define ASSERT(a) if (a) {} else LOG(("ASSERT failed! file = %s, line = %d\n",__FILE__,__LINE__)) #define ASSERT(a) if (a) {} else LOG(("ASSERT failed! file = %s, line = %d\n",__FILE__,__LINE__))
void log_create(); void log_create(void);
void log_printf(const char *text,...); void log_printf(const char *text,...);
#else #else
#define PRINT(a) debug_printf a #define PRINT(a) debug_printf a
@@ -550,27 +550,27 @@ init_driver(void)
reset = ich_codec_read(0x00); /* access the primary codec */ reset = ich_codec_read(0x00); /* access the primary codec */
if (reset == 0 || reset == 0xFFFF) { if (reset == 0 || reset == 0xFFFF) {
LOG(("primary codec not present\n")); LOG(("primary codec not present\n"));
} //else { } else {
sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM); sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM);
id = 0x02 & (ich_codec_read(0x00 + 0x28) >> 14); id = 0x02 & (ich_codec_read(0x00 + 0x28) >> 14);
LOG(("primary codec id %d is connected to AC_SDIN%d\n", id, sdin)); LOG(("primary codec id %d is connected to AC_SDIN%d\n", id, sdin));
//} }
reset = ich_codec_read(0x80); /* access the secondary codec */ reset = ich_codec_read(0x80); /* access the secondary codec */
if (reset == 0 || reset == 0xFFFF) { if (reset == 0 || reset == 0xFFFF) {
LOG(("secondary codec not present\n")); LOG(("secondary codec not present\n"));
} //else { } else {
sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM); sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM);
id = 0x02 & (ich_codec_read(0x80 + 0x28) >> 14); id = 0x02 & (ich_codec_read(0x80 + 0x28) >> 14);
LOG(("secondary codec id %d is connected to AC_SDIN%d\n", id, sdin)); LOG(("secondary codec id %d is connected to AC_SDIN%d\n", id, sdin));
//} }
reset = ich_codec_read(0x100); /* access the tertiary codec */ reset = ich_codec_read(0x100); /* access the tertiary codec */
if (reset == 0 || reset == 0xFFFF) { if (reset == 0 || reset == 0xFFFF) {
LOG(("tertiary codec not present\n")); LOG(("tertiary codec not present\n"));
} //else { } else {
sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM); sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM);
id = 0x02 & (ich_codec_read(0x100 + 0x28) >> 14); id = 0x02 & (ich_codec_read(0x100 + 0x28) >> 14);
LOG(("tertiary codec id %d is connected to AC_SDIN%d\n", id, sdin)); LOG(("tertiary codec id %d is connected to AC_SDIN%d\n", id, sdin));
//} }
/* XXX this may be wrong */ /* XXX this may be wrong */
ich_reg_write_8(ICH_REG_SDM, (ich_reg_read_8(ICH_REG_SDM) & 0x0F) | 0x08 | 0x90); ich_reg_write_8(ICH_REG_SDM, (ich_reg_read_8(ICH_REG_SDM) & 0x0F) | 0x08 | 0x90);
@@ -668,9 +668,52 @@ init_driver(void)
resume_thread(int_thread_id); resume_thread(int_thread_id);
} }
/* Only if the codec supports continuous sample rates,
try to calibrate the clock... */
if (ac97_has_capability(config->ac97, CAP_PCM_RATE_CONTINUOUS)) {
#if DEBUG
uint32 rate;
if (ac97_get_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, &rate)) {
LOG(("AC97_PCM_FRONT_DAC_RATE was %d\n", rate));
} else {
LOG(("couldn't get current AC97_PCM_FRONT_DAC_RATE rate\n"));
}
start_chan(chan_po);
snooze(23000);
LOG(("codec supports continuous sample rates, clock before calibration is %d\n", ich_clock_get()));
stop_chan(chan_po);
#endif
/* calibrate the clock */ /* calibrate the clock */
ich_clock_calibrate(); ich_clock_calibrate();
#if DEBUG
start_chan(chan_po);
snooze(23000);
LOG(("codec supports continuous sample rates, clock after calibration is %d\n", ich_clock_get()));
stop_chan(chan_po);
if (ac97_get_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, &rate)) {
LOG(("AC97_PCM_FRONT_DAC_RATE is now %d\n", rate));
} else {
LOG(("couldn't get current AC97_PCM_FRONT_DAC_RATE rate\n"));
}
#endif
} else {
#if DEBUG
uint32 rate;
start_chan(chan_po);
snooze(23000);
LOG(("codec doesn't support continuous sample rates, running at clock %d\n", ich_clock_get()));
stop_chan(chan_po);
if (ac97_get_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, &rate)) {
LOG(("current AC97_PCM_FRONT_DAC_RATE is %d\n", rate));
} else {
LOG(("couldn't get current AC97_PCM_FRONT_DAC_RATE rate\n"));
}
#endif
}
LOG(("init_driver finished!\n")); LOG(("init_driver finished!\n"));
return B_OK; return B_OK;
} }
@@ -31,7 +31,7 @@
#include "debug.h" #include "debug.h"
#include "hardware.h" #include "hardware.h"
#define VERSION_NUMBER "1.6b" #define VERSION_NUMBER "1.6c"
#if DEBUG #if DEBUG
#define VERSION_DEBUG " (DEBUG)" #define VERSION_DEBUG " (DEBUG)"