changed codec detection and special ICH4 handling
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@793 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
1ddfa2f84e
commit
33d6854bee
@ -29,6 +29,7 @@
|
||||
#include <stdio.h>
|
||||
#include <MediaDefs.h>
|
||||
#include "ac97.h"
|
||||
#include "config.h"
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
@ -114,20 +115,20 @@ ac97_amp_enable(bool yesno)
|
||||
{
|
||||
LOG(("using Cirrus enable"));
|
||||
if (yesno)
|
||||
ich_codec_write(0x68, 0x8004);
|
||||
ich_codec_write(config->codecoffset + 0x68, 0x8004);
|
||||
else
|
||||
ich_codec_write(0x68, 0);
|
||||
ich_codec_write(config->codecoffset + 0x68, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
LOG(("powerdown register was = %#04x\n",ich_codec_read(AC97_POWERDOWN)));
|
||||
LOG(("powerdown register was = %#04x\n",ich_codec_read(config->codecoffset + AC97_POWERDOWN)));
|
||||
if (yesno)
|
||||
ich_codec_write(AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
|
||||
ich_codec_write(config->codecoffset + AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
|
||||
else
|
||||
ich_codec_write(AC97_POWERDOWN, ich_codec_read(AC97_POWERDOWN) | 0x8000); /* switch off */
|
||||
LOG(("powerdown register is = %#04x\n",ich_codec_read(AC97_POWERDOWN)));
|
||||
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)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -140,7 +141,7 @@ ac97_init()
|
||||
{
|
||||
case 0x41445461: /* Analog Devices AD1886 */
|
||||
LOG(("using AD1886 init"));
|
||||
ich_codec_write(0x72, 0x0010);
|
||||
ich_codec_write(config->codecoffset + 0x72, 0x0010);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -82,6 +82,7 @@ status_t probe_device(void)
|
||||
config->log_mbbar = 0;
|
||||
config->area_mmbar = -1;
|
||||
config->area_mbbar = -1;
|
||||
config->codecoffset = 0;
|
||||
|
||||
result = B_ERROR;
|
||||
cookie = 0;
|
||||
|
@ -43,6 +43,7 @@ typedef struct
|
||||
void * log_mbbar; // ich4
|
||||
area_id area_mmbar; // ich4
|
||||
area_id area_mbbar; // ich4
|
||||
uint32 codecoffset;
|
||||
} device_config;
|
||||
|
||||
extern device_config *config;
|
||||
|
@ -33,7 +33,8 @@ enum ICH_GLOBAL_REGISTER
|
||||
{
|
||||
ICH_REG_GLOB_CNT = 0x2C,
|
||||
ICH_REG_GLOB_STA = 0x30,
|
||||
ICH_REG_ACC_SEMA = 0x34
|
||||
ICH_REG_ACC_SEMA = 0x34,
|
||||
ICH_REG_SDM = 0x80
|
||||
};
|
||||
|
||||
enum ICH_X_REGISTER_BASE /* base addresses for the following offsets */
|
||||
@ -94,10 +95,10 @@ enum REG_GLOB_STA_BITS
|
||||
STA_PIINT = 0x00000020, /* PCM In Interrupt */
|
||||
STA_POINT = 0x00000040, /* PCM Out Interrupt */
|
||||
STA_MINT = 0x00000080, /* Mic In Interrupt */
|
||||
STA_PCR = 0x00000100, /* AC_SDIN0 Codec Ready */
|
||||
STA_SCR = 0x00000200, /* AC_SDIN1 Codec Ready */
|
||||
STA_PRI = 0x00000400, /* AC_SDIN0 Resume Interrupt */
|
||||
STA_SRI = 0x00000800, /* AC_SDIN1 Resume Interrupt */
|
||||
STA_S0CR = 0x00000100, /* AC_SDIN0 Codec Ready */
|
||||
STA_S1CR = 0x00000200, /* AC_SDIN1 Codec Ready */
|
||||
STA_S0RI = 0x00000400, /* AC_SDIN0 Resume Interrupt */
|
||||
STA_S1RI = 0x00000800, /* AC_SDIN1 Resume Interrupt */
|
||||
STA_RCS = 0x00008000, /* Read Completition Status */
|
||||
STA_AD3 = 0x00010000,
|
||||
STA_MD3 = 0x00020000,
|
||||
@ -107,7 +108,7 @@ enum REG_GLOB_STA_BITS
|
||||
STA_BCS = 0x08000000, /* Bit Clock Stopped */
|
||||
STA_S2CR = 0x10000000, /* AC_SDIN2 Codec Ready */
|
||||
STA_S2RI = 0x20000000, /* AC_SDIN2 Resume Interrupt */
|
||||
STA_INTMASK = (STA_MIINT | STA_MOINT | STA_PIINT | STA_POINT | STA_MINT | STA_PRI | STA_SRI | STA_M2INT | STA_P2INT | STA_SPINT | STA_S2RI)
|
||||
STA_INTMASK = (STA_MIINT | STA_MOINT | STA_PIINT | STA_POINT | STA_MINT | STA_S0RI | STA_S1RI | STA_M2INT | STA_P2INT | STA_SPINT | STA_S2RI)
|
||||
};
|
||||
|
||||
#define ICH_BD_COUNT 32
|
||||
|
@ -337,6 +337,7 @@ init_driver(void)
|
||||
{
|
||||
status_t rv;
|
||||
bigtime_t start;
|
||||
bool s0cr, s1cr, s2cr;
|
||||
|
||||
LOG_CREATE();
|
||||
|
||||
@ -374,57 +375,87 @@ init_driver(void)
|
||||
LOG(("cold reset failed\n"));
|
||||
}
|
||||
|
||||
/* wait until a codec is ready */
|
||||
/* detect which codecs are ready */
|
||||
s0cr = s1cr = s2cr = false;
|
||||
start = system_time();
|
||||
while ((system_time() - start) < 1000000) {
|
||||
do {
|
||||
rv = ich_reg_read_32(ICH_REG_GLOB_STA);
|
||||
if ((rv & STA_PCR) != 0)
|
||||
break;
|
||||
if (!s0cr && (rv & STA_S0CR)) {
|
||||
s0cr = true;
|
||||
LOG(("AC_SDIN0 codec ready after %Ld us\n",(system_time() - start)));
|
||||
}
|
||||
if (!s1cr && (rv & STA_S1CR)) {
|
||||
s1cr = true;
|
||||
LOG(("AC_SDIN1 codec ready after %Ld us\n",(system_time() - start)));
|
||||
}
|
||||
if (!s2cr && (rv & STA_S2CR)) {
|
||||
s2cr = true;
|
||||
LOG(("AC_SDIN2 codec ready after %Ld us\n",(system_time() - start)));
|
||||
}
|
||||
snooze(50000);
|
||||
} while ((system_time() - start) < 1000000);
|
||||
|
||||
if (!s0cr) {
|
||||
LOG(("AC_SDIN0 codec not ready\n"));
|
||||
}
|
||||
if ((rv & STA_PCR)) {
|
||||
LOG(("primary codec ready after %Ld us\n",(system_time() - start)));
|
||||
} else {
|
||||
LOG(("primary codec not ready after %Ld us\n",(system_time() - start)));
|
||||
if (!s1cr) {
|
||||
LOG(("AC_SDIN1 codec not ready\n"));
|
||||
}
|
||||
while ((system_time() - start) < 1000000) {
|
||||
rv = ich_reg_read_32(ICH_REG_GLOB_STA);
|
||||
if ((rv & STA_SCR) != 0)
|
||||
break;
|
||||
snooze(50000);
|
||||
}
|
||||
if ((rv & STA_SCR)) {
|
||||
LOG(("secondary codec ready after %Ld us\n",(system_time() - start)));
|
||||
} else {
|
||||
LOG(("secondary codec not ready after %Ld us\n",(system_time() - start)));
|
||||
}
|
||||
while ((system_time() - start) < 1000000) {
|
||||
rv = ich_reg_read_32(ICH_REG_GLOB_STA);
|
||||
if ((rv & STA_S2CR) != 0)
|
||||
break;
|
||||
snooze(50000);
|
||||
}
|
||||
if ((rv & STA_S2CR)) {
|
||||
LOG(("tertiary codec ready after %Ld us\n",(system_time() - start)));
|
||||
} else {
|
||||
LOG(("tertiary codec not ready after %Ld us\n",(system_time() - start)));
|
||||
if (!s2cr) {
|
||||
LOG(("AC_SDIN2 codec not ready\n"));
|
||||
}
|
||||
|
||||
dump_hardware_regs();
|
||||
|
||||
if ((rv & (STA_PCR | STA_SCR | STA_S2CR)) == 0) {
|
||||
if (!s0cr && !s1cr && !s2cr) {
|
||||
PRINT(("compatible chipset found, but no codec ready!\n"));
|
||||
unmap_io_memory();
|
||||
return B_ERROR;
|
||||
}
|
||||
if ((rv & STA_PCR) == 0 && (rv & STA_S2CR) != 0) {
|
||||
LOG(("using tertiary codec!\n"));
|
||||
config->nambar += 0x100;
|
||||
config->log_mmbar += 0x100; /* ICH 4 */
|
||||
} else if ((rv & STA_PCR) == 0 && (rv & STA_SCR) != 0) {
|
||||
LOG(("using secondary codec!\n"));
|
||||
config->nambar += 0x80;
|
||||
config->log_mmbar += 0x80; /* ICH 4 */
|
||||
|
||||
if (config->type & TYPE_ICH4) {
|
||||
/* we are using a ICH4 chipset, and assume that the codec beeing ready
|
||||
* is the primary one.
|
||||
*/
|
||||
uint8 sdin;
|
||||
uint16 reset;
|
||||
uint8 id;
|
||||
reset = ich_codec_read(0x00); /* access the primary codec */
|
||||
if (reset == 0 || reset == 0xFFFF) {
|
||||
LOG(("primary codec not present\n"));
|
||||
} //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 {
|
||||
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 {
|
||||
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);
|
||||
} else {
|
||||
/* we are using a pre-ICH4 chipset, that has a fixed mapping of
|
||||
* AC_SDIN0 = primary, AC_SDIN1 = secondary codec.
|
||||
*/
|
||||
if (!s0cr && s2cr) {
|
||||
// is is unknown if this really works, perhaps we should better abort here
|
||||
LOG(("primary codec doesn't seem to be available, using secondary!\n"));
|
||||
config->codecoffset = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
dump_hardware_regs();
|
||||
@ -480,9 +511,9 @@ init_driver(void)
|
||||
chan_po->regbase = ICH_REG_PO_BASE;
|
||||
chan_mc->regbase = ICH_REG_MC_BASE;
|
||||
|
||||
/* reset the (primary?) codec */
|
||||
/* reset the codec */
|
||||
LOG(("codec reset\n"));
|
||||
ich_codec_write(0x00, 0x0000);
|
||||
ich_codec_write(config->codecoffset + 0x00, 0x0000);
|
||||
snooze(50000); // 50 ms
|
||||
|
||||
ac97_init();
|
||||
@ -517,24 +548,24 @@ init_driver(void)
|
||||
}
|
||||
|
||||
/* enable master output */
|
||||
ich_codec_write(0x02, 0x0000);
|
||||
ich_codec_write(config->codecoffset + 0x02, 0x0000);
|
||||
/* enable pcm output */
|
||||
ich_codec_write(0x18, 0x0404);
|
||||
ich_codec_write(config->codecoffset + 0x18, 0x0404);
|
||||
|
||||
#if 0
|
||||
/* enable pcm input */
|
||||
ich_codec_write(0x10, 0x0000);
|
||||
ich_codec_write(config->codecoffset + 0x10, 0x0000);
|
||||
|
||||
/* enable mic input */
|
||||
/* ich_codec_write(0x0E, 0x0000); */
|
||||
/* ich_codec_write(config->codecoffset + 0x0E, 0x0000); */
|
||||
|
||||
/* select pcm input record */
|
||||
ich_codec_write(0x1A, 4 | (4 << 8));
|
||||
ich_codec_write(config->codecoffset + 0x1A, 4 | (4 << 8));
|
||||
/* enable PCM record */
|
||||
ich_codec_write(0x1C, 0x0000);
|
||||
ich_codec_write(config->codecoffset + 0x1C, 0x0000);
|
||||
|
||||
/* enable mic record */
|
||||
/* ich_codec_write(0x1E, 0x0000); */
|
||||
/* ich_codec_write(config->codecoffset + 0x1E, 0x0000); */
|
||||
#endif
|
||||
|
||||
LOG(("init_driver finished!\n"));
|
||||
@ -615,9 +646,9 @@ int32 ich_int(void *unused)
|
||||
if ((sta & STA_INTMASK) == 0)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
|
||||
if (sta & (STA_PRI | STA_SRI)) {
|
||||
if (sta & (STA_S0RI | STA_S1RI | STA_S2RI)) {
|
||||
/* ignore and clear resume interrupt(s) */
|
||||
ich_reg_write_32(ICH_REG_GLOB_STA, sta & (STA_PRI | STA_SRI));
|
||||
ich_reg_write_32(ICH_REG_GLOB_STA, sta & (STA_S0RI | STA_S1RI | STA_S2RI));
|
||||
}
|
||||
|
||||
if (sta & STA_POINT) { // pcm-out
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
#define VERSION "Version 1.3, Copyright (c) 2002 Marcus Overhagen, compiled on " ## __DATE__ ## " " ## __TIME__
|
||||
#define VERSION "Version 1.4, Copyright (c) 2002 Marcus Overhagen, compiled on " ## __DATE__ ## " " ## __TIME__
|
||||
#define DRIVER_NAME "ich_ac97"
|
||||
|
||||
#define BUFFER_SIZE 2048
|
||||
|
Loading…
Reference in New Issue
Block a user