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 aea60e681c..51a4903929 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ac97.c @@ -500,76 +500,77 @@ void ac97_dump_capabilities(ac97_dev *dev) { LOG(("AC97 capabilities:\n")); - if (dev->capabilities & CAP_PCM_MIC) + if (ac97_has_capability(dev, CAP_PCM_MIC)) 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")); - if (dev->capabilities & CAP_SIMULATED_STEREO) + if (ac97_has_capability(dev, CAP_SIMULATED_STEREO)) LOG(("CAP_SIMULATED_STEREO\n")); - if (dev->capabilities & CAP_HEADPHONE_OUT) + if (ac97_has_capability(dev, CAP_HEADPHONE_OUT)) LOG(("CAP_HEADPHONE_OUT\n")); - if (dev->capabilities & CAP_LAUDNESS) + if (ac97_has_capability(dev, CAP_LAUDNESS)) LOG(("CAP_LAUDNESS\n")); - if (dev->capabilities & CAP_DAC_18BIT) + if (ac97_has_capability(dev, CAP_DAC_18BIT)) LOG(("CAP_DAC_18BIT\n")); - if (dev->capabilities & CAP_DAC_20BIT) + if (ac97_has_capability(dev, CAP_DAC_20BIT)) LOG(("CAP_DAC_20BIT\n")); - if (dev->capabilities & CAP_ADC_18BIT) + if (ac97_has_capability(dev, CAP_ADC_18BIT)) LOG(("CAP_ADC_18BIT\n")); - if (dev->capabilities & CAP_ADC_20BIT) + if (ac97_has_capability(dev, CAP_ADC_20BIT)) LOG(("CAP_ADC_20BIT\n")); - if (dev->capabilities & CAP_3D_ENHANCEMENT) + if (ac97_has_capability(dev, CAP_3D_ENHANCEMENT)) LOG(("CAP_3D_ENHANCEMENT\n")); - if (dev->capabilities & CAP_VARIABLE_PCM) + if (ac97_has_capability(dev, CAP_VARIABLE_PCM)) LOG(("CAP_VARIABLE_PCM\n")); - if (dev->capabilities & CAP_DOUBLE_PCM) + if (ac97_has_capability(dev, CAP_DOUBLE_PCM)) LOG(("CAP_DOUBLE_PCM\n")); - if (dev->capabilities & CAP_VARIABLE_MIC) + if (ac97_has_capability(dev, CAP_VARIABLE_MIC)) LOG(("CAP_VARIABLE_MIC\n")); - if (dev->capabilities & CAP_CENTER_DAC) + if (ac97_has_capability(dev, CAP_CENTER_DAC)) LOG(("CAP_CENTER_DAC\n")); - if (dev->capabilities & CAP_SURR_DAC) + if (ac97_has_capability(dev, CAP_SURR_DAC)) LOG(("CAP_SURR_DAC\n")); - if (dev->capabilities & CAP_LFE_DAC) + if (ac97_has_capability(dev, CAP_LFE_DAC)) LOG(("CAP_LFE_DAC\n")); - if (dev->capabilities & CAP_AMAP) + if (ac97_has_capability(dev, CAP_AMAP)) LOG(("CAP_AMAP\n")); - if (dev->capabilities & CAP_REV21) + if (ac97_has_capability(dev, CAP_REV21)) LOG(("CAP_REV21\n")); - if (dev->capabilities & CAP_REV22) + if (ac97_has_capability(dev, CAP_REV22)) LOG(("CAP_REV22\n")); - if (dev->capabilities & CAP_REV23) + if (ac97_has_capability(dev, CAP_REV23)) 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")); - if (dev->capabilities & CAP_PCM_RATE_8000) + if (ac97_has_capability(dev, CAP_PCM_RATE_8000)) 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")); - if (dev->capabilities & CAP_PCM_RATE_12000) + if (ac97_has_capability(dev, CAP_PCM_RATE_12000)) 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")); - if (dev->capabilities & CAP_PCM_RATE_22050) + if (ac97_has_capability(dev, CAP_PCM_RATE_22050)) 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")); - if (dev->capabilities & CAP_PCM_RATE_32000) + if (ac97_has_capability(dev, CAP_PCM_RATE_32000)) 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")); - if (dev->capabilities & CAP_PCM_RATE_48000) + if (ac97_has_capability(dev, CAP_PCM_RATE_48000)) 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")); - if (dev->capabilities & CAP_PCM_RATE_96000) + if (ac97_has_capability(dev, CAP_PCM_RATE_96000)) LOG(("CAP_PCM_RATE_96000\n")); } bool 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; } /************************************************* diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/config.c b/src/add-ons/kernel/drivers/audio/ac97/ich/config.c index 70b2c237f8..f2559423d3 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/config.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/config.c @@ -38,8 +38,6 @@ device_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 * XXX multiple controllers not supported @@ -163,21 +161,13 @@ status_t probe_device(void) #endif config->irq = pcimodule->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x3C, 1); - if (config->irq == 0 || config->irq == 0xff) { - // workaround: even if no irq is configured, we may be able to find the correct one - uint8 pin; - 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 == 0xff) { + // always 0, not 0xff if no irq assigned + config->irq = 0; + } + 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) { // memory mapped access 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); 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; -} - diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c index 4d1ae3575a..6b9f979e8c 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.c @@ -50,7 +50,7 @@ void debug_printf(const char *text,...) static const char * logfile="/boot/home/ich_ac97.log"; static sem_id loglock; -void log_create() +void log_create(void) { int fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); const char *text = DRIVER_NAME ", " VERSION "\n"; diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h index 564ab0acba..04c9f25a03 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/debug.h @@ -54,7 +54,7 @@ void debug_printf(const char *text,...); #define LOG(a) log_printf a #define LOG_CREATE() log_create() #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,...); #else #define PRINT(a) debug_printf a 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 dc57eb8311..664023d215 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.c @@ -550,27 +550,27 @@ init_driver(void) reset = ich_codec_read(0x00); /* access the primary codec */ if (reset == 0 || reset == 0xFFFF) { LOG(("primary codec not present\n")); - } //else { + } else { sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM); id = 0x02 & (ich_codec_read(0x00 + 0x28) >> 14); LOG(("primary codec id %d is connected to AC_SDIN%d\n", id, sdin)); - //} + } reset = ich_codec_read(0x80); /* access the secondary codec */ if (reset == 0 || reset == 0xFFFF) { LOG(("secondary codec not present\n")); - } //else { + } else { sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM); id = 0x02 & (ich_codec_read(0x80 + 0x28) >> 14); LOG(("secondary codec id %d is connected to AC_SDIN%d\n", id, sdin)); - //} + } reset = ich_codec_read(0x100); /* access the tertiary codec */ if (reset == 0 || reset == 0xFFFF) { LOG(("tertiary codec not present\n")); - } //else { + } else { sdin = 0x02 & ich_reg_read_8(ICH_REG_SDM); id = 0x02 & (ich_codec_read(0x100 + 0x28) >> 14); LOG(("tertiary codec id %d is connected to AC_SDIN%d\n", id, sdin)); - //} + } /* XXX this may be wrong */ ich_reg_write_8(ICH_REG_SDM, (ich_reg_read_8(ICH_REG_SDM) & 0x0F) | 0x08 | 0x90); @@ -662,14 +662,57 @@ init_driver(void) /* install interrupt or polling thread */ if (config->irq != 0) { - install_io_interrupt_handler(config->irq,ich_int,0,0); + install_io_interrupt_handler(config->irq, ich_int, 0, 0); } else { int_thread_id = spawn_kernel_thread(int_thread, "ich_ac97 interrupt poller", B_REAL_TIME_PRIORITY, 0); resume_thread(int_thread_id); } - /* calibrate the clock */ - ich_clock_calibrate(); + /* 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 */ + 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")); return B_OK; 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 5b89ea57c7..8d936c794b 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/ich.h @@ -31,7 +31,7 @@ #include "debug.h" #include "hardware.h" -#define VERSION_NUMBER "1.6b" +#define VERSION_NUMBER "1.6c" #if DEBUG #define VERSION_DEBUG " (DEBUG)"