These changes allow the SB600 HDA to detect the codec correctly. I haven't had
time to test the sound output, but Linux now detects it correctly. I don't see
why it wouldn't work. Feel free to give it a whirl and let me know if more work
is needed.
Signed-off-by: Dan Lykowski<[email protected]>
Index: src/southbridge/amd/sb600/sb600_hda.c
===================================================================
--- src/southbridge/amd/sb600/sb600_hda.c (revision 3921)
+++ src/southbridge/amd/sb600/sb600_hda.c (working copy)
@@ -30,61 +30,61 @@
#define HDA_ICII_BUSY (1 << 0)
#define HDA_ICII_VALID (1 << 1)
-static int set_bits(u8 * port, u32 mask, u32 val)
+static u32 codec_detect(u8 * base)
{
u32 dword;
- int count;
+ u32 count;
- val &= mask;
- dword = readl(port);
- dword &= ~mask;
- dword |= val;
- writel(dword, port);
+ /* Set Bit0 to 0 to enter reset state */
+ dword = readl( base + 0x08 );
+ dword &= ~0x1;
+ writel( dword, base + 0x08 );
- count = 50;
+ // Wait for bit to transition
+ count = 10;
do {
- dword = readl(port);
- dword &= mask;
- udelay(100);
- } while ((dword != val) && --count);
+ /* Wait 1ms */
+ mdelay(1);
- if (!count)
- return -1;
+ dword = readl( base + 0x08 );
+ if( dword & 0x1 == 0 ) break;
+ } while( count-- > 0 );
+ if( count == 0 ) goto no_codec;
- udelay(540);
- return 0;
-}
+ /* Set Bit 0 to 1 to exit reset state */
+ dword = readl( base + 0x08 );
+ dword |= 0x1;
+ writel( dword, base + 0x08 );
-static u32 codec_detect(u8 * base)
-{
- u32 dword;
+ /* Wait for bit to transition */
+ count = 10;
+ do {
+ /* Wait 1ms */
+ mdelay(1);
- /* 1 */
- set_bits(base + 0x08, 1, 1);
+ dword = readl( base + 0x08 );
+ if( dword & 0x1 ) break;
+ } while( count-- > 0 );
+ if( count == 0 ) goto no_codec;
- /* 2 */
- dword = readl(base + 0x0e);
- dword |= 7;
- writel(dword, base + 0x0e);
+ /* Read in Codec location */
+ dword = readl( base + 0xe );
+ dword &= 7;
- /* 3 */
- set_bits(base + 0x08, 1, 0);
+ if( !dword ) goto no_codec;
- /* 4 */
- set_bits(base + 0x08, 1, 1);
+ return dword;
- /* 5 */
- dword = readl(base + 0xe);
- dword &= 7;
+no_codec:
- /* 6 */
- if (!dword) {
- set_bits(base + 0x08, 1, 0);
- printk_debug("No codec!\n");
- return 0;
- }
- return dword;
+ /* Codec Not found */
+ /* Put HDA back in reset */
+ dword = readl( base + 0x08 );
+ dword &= ~0x1;
+ writel( dword, base + 0x08 );
+ printk_debug("No codec!\n");
+ return 0;
}
static u32 cim_verb_data[] = {
@@ -262,26 +262,39 @@
static void hda_init(struct device *dev)
{
+ u8 byte;
+ u32 dword;
u8 *base;
struct resource *res;
u32 codec_mask;
-
+ device_t sm_dev;
+
+ /* Enable azalia, disable ac97 */
+ pm_iowrite(0x59, 0xB);
+
/* SM Setting */
+ sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
+ /* Set INTG */
+ byte = pci_read_config8( sm_dev, 0x63 );
+ byte |= 0x6;
+ pci_write_config8(sm_dev, 0x63, byte);
+
/* Set routing pin */
- pci_write_config32(dev, 0xf8, 0x0);
- pci_write_config8(dev, 0xfc, 0xAA);
- /* Set INTA */
- pci_write_config8(dev, 0x63, 0x0);
- /* Enable azalia, disable ac97 */
- pm_iowrite(0x59, 0xB);
+ pci_write_config32(sm_dev, 0xf8, 0x00);
+ pci_write_config8(sm_dev, 0xfc, 0xAA);
+ /* Program the 2C to 0x437b1002 */
+ dword = 0x437b1002;
+ pci_write_config32(dev, 0x2c, dword);
+
+ /* Read in BAR */
res = find_resource(dev, 0x10);
- if (!res)
- return;
-
+ if (!res) return;
base = (u8 *) ((u32)res->base);
printk_debug("base = %08x\n", base);
+
+ /* Detect Codec */
codec_mask = codec_detect(base);
if (codec_mask) {
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot