6b5bc77c9b
Stefan thinks they don't add value. Command used: sed -i -e '/file is part of /d' $(git grep "file is part of " |egrep ":( */\*.*\*/\$|#|;#|-- | *\* )" | cut -d: -f1 |grep -v crossgcc |grep -v gcov | grep -v /elf.h |grep -v nvramtool) The exceptions are for: - crossgcc (patch file) - gcov (imported from gcc) - elf.h (imported from GNU's libc) - nvramtool (more complicated header) The removed lines are: - fmt.Fprintln(f, "/* This file is part of the coreboot project. */") -# This file is part of a set of unofficial pre-commit hooks available -/* This file is part of coreboot */ -# This file is part of msrtool. -/* This file is part of msrtool. */ - * This file is part of ncurses, designed to be appended after curses.h.in -/* This file is part of pgtblgen. */ - * This file is part of the coreboot project. - /* This file is part of the coreboot project. */ -# This file is part of the coreboot project. -# This file is part of the coreboot project. -## This file is part of the coreboot project. --- This file is part of the coreboot project. -/* This file is part of the coreboot project */ -/* This file is part of the coreboot project. */ -;## This file is part of the coreboot project. -# This file is part of the coreboot project. It originated in the - * This file is part of the coreinfo project. -## This file is part of the coreinfo project. - * This file is part of the depthcharge project. -/* This file is part of the depthcharge project. */ -/* This file is part of the ectool project. */ - * This file is part of the GNU C Library. - * This file is part of the libpayload project. -## This file is part of the libpayload project. -/* This file is part of the Linux kernel. */ -## This file is part of the superiotool project. -/* This file is part of the superiotool project */ -/* This file is part of uio_usbdebug */ Change-Id: I82d872b3b337388c93d5f5bf704e9ee9e53ab3a9 Signed-off-by: Patrick Georgi <pgeorgi@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41194 Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
247 lines
5.4 KiB
C
247 lines
5.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#include <console/console.h>
|
|
#include <device/mmio.h>
|
|
#include <delay.h>
|
|
#include "hda_verb.h"
|
|
|
|
/*
|
|
* Set bits in a register and wait for status
|
|
*/
|
|
static int set_bits(void *port, u32 mask, u32 val)
|
|
{
|
|
u32 reg32;
|
|
int count;
|
|
|
|
/* Write (val & mask) to port */
|
|
val &= mask;
|
|
reg32 = read32(port);
|
|
reg32 &= ~mask;
|
|
reg32 |= val;
|
|
write32(port, reg32);
|
|
|
|
/* 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);
|
|
reg32 = read32(port);
|
|
reg32 &= mask;
|
|
} while ((reg32 != val) && --count);
|
|
|
|
/* Timeout occurred */
|
|
if (!count)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Probe for supported codecs
|
|
*/
|
|
int hda_codec_detect(u8 *base)
|
|
{
|
|
u8 reg8;
|
|
|
|
/* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
|
|
if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST) < 0)
|
|
goto no_codec;
|
|
|
|
/* Write back the value once reset bit is set. */
|
|
write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG));
|
|
|
|
/* Clear the "State Change Status Register" STATESTS bits
|
|
* for each of the "SDIN Stat Change Status Flag"
|
|
*/
|
|
write8(base + HDA_STATESTS_REG, 0xf);
|
|
|
|
/* Turn off the link and poll RESET# bit until it reads back as 0 */
|
|
if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, ~HDA_GCTL_CRST) < 0)
|
|
goto no_codec;
|
|
|
|
/* Turn on the link and poll RESET# bit until it reads back as 1 */
|
|
if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST) < 0)
|
|
goto no_codec;
|
|
|
|
/* Read in Codec location (BAR + 0xe)[2..0]*/
|
|
reg8 = read8(base + HDA_STATESTS_REG);
|
|
reg8 &= 0x0f;
|
|
if (!reg8)
|
|
goto no_codec;
|
|
|
|
return reg8;
|
|
|
|
no_codec:
|
|
/* Codec Not found */
|
|
/* Put HDA back in reset (BAR + 0x8) [0] */
|
|
set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, 0);
|
|
printk(BIOS_DEBUG, "HDA: No codec!\n");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Wait 50usec for the codec to indicate it is ready
|
|
* no response would imply that the codec is non-operative
|
|
*/
|
|
static int hda_wait_for_ready(u8 *base)
|
|
{
|
|
/* Use a 50 usec timeout - the Linux kernel uses the
|
|
* same duration */
|
|
|
|
int timeout = 50;
|
|
|
|
while (timeout--) {
|
|
u32 reg32 = read32(base + HDA_ICII_REG);
|
|
if (!(reg32 & HDA_ICII_BUSY))
|
|
return 0;
|
|
udelay(1);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Wait 50usec for the codec to indicate that it accepted
|
|
* the previous command. No response would imply that the code
|
|
* is non-operative
|
|
*/
|
|
static int hda_wait_for_valid(u8 *base)
|
|
{
|
|
u32 reg32;
|
|
|
|
/* Send the verb to the codec */
|
|
reg32 = read32(base + HDA_ICII_REG);
|
|
reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
|
|
write32(base + HDA_ICII_REG, reg32);
|
|
|
|
/* Use a 50 usec timeout - the Linux kernel uses the
|
|
* same duration */
|
|
|
|
int timeout = 50;
|
|
while (timeout--) {
|
|
reg32 = read32(base + HDA_ICII_REG);
|
|
if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
|
|
HDA_ICII_VALID)
|
|
return 0;
|
|
udelay(1);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Find a specific entry within a verb table
|
|
*
|
|
* @param verb_table_bytes: verb table size in bytes
|
|
* @param verb_table_data: verb table data
|
|
* @param viddid: vendor/device to search for
|
|
* @param verb: pointer to entry within table
|
|
*
|
|
* Returns size of the entry within the verb table,
|
|
* Returns 0 if the entry is not found
|
|
*
|
|
* The HDA verb table is composed of dwords. A set of 4 dwords is
|
|
* grouped together to form a "jack" descriptor.
|
|
* Bits 31:28 - Codec Address
|
|
* Bits 27:20 - NID
|
|
* Bits 19:8 - Verb ID
|
|
* Bits 7:0 - Payload
|
|
*
|
|
* coreboot groups different codec verb tables into a single table
|
|
* and prefixes each with a specific header consisting of 3
|
|
* dword entries:
|
|
* 1 - Codec Vendor/Device ID
|
|
* 2 - Subsystem ID
|
|
* 3 - Number of jacks (groups of 4 dwords) for this codec
|
|
*/
|
|
static u32 hda_find_verb(u32 verb_table_bytes,
|
|
const u32 *verb_table_data,
|
|
u32 viddid, const u32 **verb)
|
|
{
|
|
int idx = 0;
|
|
|
|
while (idx < (verb_table_bytes / sizeof(u32))) {
|
|
u32 verb_size = 4 * verb_table_data[idx+2]; // in u32
|
|
if (verb_table_data[idx] != viddid) {
|
|
idx += verb_size + 3; // skip verb + header
|
|
continue;
|
|
}
|
|
*verb = &verb_table_data[idx+3];
|
|
return verb_size;
|
|
}
|
|
|
|
/* Not all codecs need to load another verb */
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Write a supplied verb table
|
|
*/
|
|
int hda_codec_write(u8 *base, u32 size, const u32 *data)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
if (hda_wait_for_ready(base) < 0)
|
|
return -1;
|
|
|
|
write32(base + HDA_IC_REG, data[i]);
|
|
|
|
if (hda_wait_for_valid(base) < 0)
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Initialize codec, then find the verb table and write it
|
|
*/
|
|
int hda_codec_init(u8 *base, int addr, int verb_size, const u32 *verb_data)
|
|
{
|
|
const u32 *verb;
|
|
u32 reg32, size;
|
|
int rc;
|
|
|
|
printk(BIOS_DEBUG, "HDA: Initializing codec #%d\n", addr);
|
|
|
|
if (!verb_size || !verb_data) {
|
|
printk(BIOS_DEBUG, "HDA: No verb list!\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 1 */
|
|
if (hda_wait_for_ready(base) < 0) {
|
|
printk(BIOS_DEBUG, " codec not ready.\n");
|
|
return -1;
|
|
}
|
|
|
|
reg32 = (addr << 28) | 0x000f0000;
|
|
write32(base + HDA_IC_REG, reg32);
|
|
|
|
if (hda_wait_for_valid(base) < 0) {
|
|
printk(BIOS_DEBUG, " codec not valid.\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 2 */
|
|
reg32 = read32(base + HDA_IR_REG);
|
|
printk(BIOS_DEBUG, "HDA: codec viddid: %08x\n", reg32);
|
|
|
|
size = hda_find_verb(verb_size, verb_data, reg32, &verb);
|
|
if (!size) {
|
|
printk(BIOS_DEBUG, "HDA: No verb table entry found\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 3 */
|
|
rc = hda_codec_write(base, size, verb);
|
|
|
|
if (rc < 0)
|
|
printk(BIOS_DEBUG, "HDA: verb not loaded\n");
|
|
else
|
|
printk(BIOS_DEBUG, "HDA: verb loaded.\n");
|
|
|
|
return rc;
|
|
}
|