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:
@@ -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;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -668,9 +668,52 @@ init_driver(void)
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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)"
|
||||
|
||||
Reference in New Issue
Block a user