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

Reply via email to