Author: hailfinger
Date: 2009-02-05 03:18:42 +0100 (Thu, 05 Feb 2009)
New Revision: 3930
Modified:
trunk/coreboot-v2/src/southbridge/amd/sb600/sb600_hda.c
Log:
Use the correct device for switching on HDA.
Reorder HDA (HD Audio) init:
The reordering was based on what order things happen in the BIOS
Developers guide, RPR, and SATA driver. I fixed the order of the devices
that didn't matter to clean up the change log.
1. Enable the Chip
2. Setup the SMBus registers
3. Setup the Device Registers
4. Look for Codec
5. Init Codec
The codec init was changed to match the description in the RRG pg 235.
Mem Reg: Base + 08h Bit 0. There were unneeded things happening.
Added 1ms delay to match the BKDG while waiting for BAR+0xe to set its
bits.
Signed-off-by: Dan Lykowski <lykowdk(a)gmail.com>
Tested on AMD DBM690T and AMD Pistachio by Maggie Li. Works.
Tested on Asus M2A-VM by Carl-Daniel Hailfinger. Improves the situation,
but some warnings remain.
Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006(a)gmx.net>
Modified: trunk/coreboot-v2/src/southbridge/amd/sb600/sb600_hda.c
===================================================================
--- trunk/coreboot-v2/src/southbridge/amd/sb600/sb600_hda.c 2009-02-03 22:37:22 UTC (rev 3929)
+++ trunk/coreboot-v2/src/southbridge/amd/sb600/sb600_hda.c 2009-02-05 02:18:42 UTC (rev 3930)
@@ -35,23 +35,27 @@
u32 dword;
int count;
+ /* Write (val & ~mask) to port */
val &= mask;
dword = readl(port);
dword &= ~mask;
dword |= val;
writel(dword, port);
+ /* Wait for readback of register to
+ * match what was just written to it
+ */
count = 50;
do {
+ /* Wait 1ms based on BKDG wait time */
+ mdelay(1);
dword = readl(port);
dword &= mask;
- udelay(100);
} while ((dword != val) && --count);
+ /* Timeout occured */
if (!count)
return -1;
-
- udelay(540);
return 0;
}
@@ -59,32 +63,31 @@
{
u32 dword;
- /* 1 */
- set_bits(base + 0x08, 1, 1);
+ /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
+ if (set_bits(base + 0x08, 1, 0) == -1)
+ goto no_codec;
- /* 2 */
- dword = readl(base + 0x0e);
- dword |= 7;
- writel(dword, base + 0x0e);
+ /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
+ if (set_bits(base + 0x08, 1, 1) == -1)
+ goto no_codec;
- /* 3 */
- set_bits(base + 0x08, 1, 0);
+ /* Delay for 1 ms since the BKDG does */
+ mdelay(1);
- /* 4 */
- set_bits(base + 0x08, 1, 1);
-
- /* 5 */
+ /* Read in Codec location (BAR + 0xe)[3..0]*/
dword = readl(base + 0xe);
- dword &= 7;
-
- /* 6 */
- if (!dword) {
- set_bits(base + 0x08, 1, 0);
- printk_debug("No codec!\n");
- return 0;
- }
+ dword &= 0x0F;
+ if (!dword)
+ goto no_codec;
+
return dword;
+no_codec:
+ /* Codec Not found */
+ /* Put HDA back in reset (BAR + 0x8) [0] */
+ set_bits(base + 0x08, 1, 0);
+ printk_debug("No codec!\n");
+ return 0;
}
static u32 cim_verb_data[] = {
@@ -262,20 +265,38 @@
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 - PM_io 0x59[4], disable ac97 - PM_io 0x59[1..0] */
+ pm_iowrite(0x59, 0xB);
+
+ /* Find the SMBus */
+ /* FIXME: Need to find out why the call below crashes. */
+ /*sm_dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_ATI_SB600_SM, 0);*/
+ sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
- /* SM Setting */
+ /* Set routing pin - SMBus ExtFunc (0xf8/0xfc) */
+ pci_write_config32(sm_dev, 0xf8, 0x00);
+ pci_write_config8(sm_dev, 0xfc, 0xAA);
+ /* Set INTA - SMBus 0x63 [2..0] */
+ byte = pci_read_config8(sm_dev, 0x63);
+ byte &= ~0x7;
+ byte |= 0x0; /* INTA:0x0 - INTH:0x7 */
+ 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);
+ /* Program the 2C to 0x437b1002 */
+ dword = 0x437b1002;
+ pci_write_config32(dev, 0x2c, dword);
+ /* Read in BAR */
+ /* Is this right? HDA allows for a 64-bit BAR
+ * but this is only setup for a 32-bit one
+ */
res = find_resource(dev, 0x10);
if (!res)
return;