coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
hda_verb.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <device/azalia_device.h>
5 #include <device/mmio.h>
6 #include <delay.h>
7 
8 #include "hda_verb.h"
9 
11 {
12  u8 reg8;
13 
14  /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
15  if (azalia_exit_reset(base) < 0)
16  goto no_codec;
17 
18  /* Write back the value once reset bit is set. */
20 
21  /*
22  * Clear the "State Change Status Register" STATESTS bits
23  * for each of the "SDIN Stat Change Status Flag"
24  */
26 
27  /* Turn off the link and poll RESET# bit until it reads back as 0 */
28  if (azalia_enter_reset(base) < 0)
29  goto no_codec;
30 
31  /* Turn on the link and poll RESET# bit until it reads back as 1 */
32  if (azalia_exit_reset(base) < 0)
33  goto no_codec;
34 
35  /* Read in Codec location (BAR + 0xe)[2..0] */
36  reg8 = read8(base + HDA_STATESTS_REG);
37  reg8 &= 0x0f;
38  if (!reg8)
39  goto no_codec;
40 
41  return reg8;
42 
43 no_codec:
44  /* Codec not found, put HDA back in reset */
46  printk(BIOS_DEBUG, "HDA: No codec!\n");
47  return 0;
48 }
49 
50 /*
51  * Wait 50usec for the codec to indicate it is ready.
52  * No response would imply that the codec is non-operative.
53  */
55 {
56  /* Use a 50 usec timeout - the Linux kernel uses the same duration */
57  int timeout = 50;
58 
59  while (timeout--) {
60  u32 reg32 = read32(base + HDA_ICII_REG);
61  if (!(reg32 & HDA_ICII_BUSY))
62  return 0;
63  udelay(1);
64  }
65 
66  return -1;
67 }
68 
69 /*
70  * Wait 50usec for the codec to indicate that it accepted the previous command.
71  * No response would imply that the code is non-operative.
72  */
74 {
75  u32 reg32;
76  /* Use a 50 usec timeout - the Linux kernel uses the same duration */
77  int timeout = 50;
78 
79  /* Send the verb to the codec */
80  reg32 = read32(base + HDA_ICII_REG);
81  reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
82  write32(base + HDA_ICII_REG, reg32);
83 
84  while (timeout--) {
85  reg32 = read32(base + HDA_ICII_REG);
86  if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)
87  return 0;
88  udelay(1);
89  }
90 
91  return -1;
92 }
93 
94 int hda_codec_write(u8 *base, u32 size, const u32 *data)
95 {
96  int i;
97 
98  for (i = 0; i < size; i++) {
99  if (hda_wait_for_ready(base) < 0)
100  return -1;
101 
102  write32(base + HDA_IC_REG, data[i]);
103 
104  if (hda_wait_for_valid(base) < 0)
105  return -1;
106  }
107 
108  return 0;
109 }
110 
111 int hda_codec_init(u8 *base, int addr, int verb_size, const u32 *verb_data)
112 {
113  const u32 *verb;
114  u32 reg32, size;
115  int rc;
116 
117  printk(BIOS_DEBUG, "HDA: Initializing codec #%d\n", addr);
118 
119  if (!verb_size || !verb_data) {
120  printk(BIOS_DEBUG, "HDA: No verb list!\n");
121  return -1;
122  }
123 
124  /* 1 */
125  if (hda_wait_for_ready(base) < 0) {
126  printk(BIOS_DEBUG, " codec not ready.\n");
127  return -1;
128  }
129 
130  reg32 = (addr << 28) | 0x000f0000;
131  write32(base + HDA_IC_REG, reg32);
132 
133  if (hda_wait_for_valid(base) < 0) {
134  printk(BIOS_DEBUG, " codec not valid.\n");
135  return -1;
136  }
137 
138  /* 2 */
139  reg32 = read32(base + HDA_IR_REG);
140  printk(BIOS_DEBUG, "HDA: codec viddid: %08x\n", reg32);
141 
142  size = azalia_find_verb(verb_data, verb_size, reg32, &verb);
143  if (!size) {
144  printk(BIOS_DEBUG, "HDA: No verb table entry found\n");
145  return -1;
146  }
147 
148  /* 3 */
149  rc = hda_codec_write(base, size, verb);
150 
151  if (rc < 0)
152  printk(BIOS_DEBUG, "HDA: verb not loaded\n");
153  else
154  printk(BIOS_DEBUG, "HDA: verb loaded.\n");
155 
156  return rc;
157 }
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint16_t read16(const void *addr)
Definition: mmio.h:17
static uint32_t read32(const void *addr)
Definition: mmio.h:22
static uint8_t read8(const void *addr)
Definition: mmio.h:12
static void write16(void *addr, uint16_t val)
Definition: mmio.h:35
int azalia_enter_reset(u8 *base)
Definition: azalia_device.c:38
int azalia_exit_reset(u8 *base)
Definition: azalia_device.c:44
u32 azalia_find_verb(const u32 *verb_table, u32 verb_table_bytes, u32 viddid, const u32 **verb)
#define HDA_ICII_BUSY
Definition: azalia_device.h:18
#define HDA_IR_REG
Definition: azalia_device.h:16
#define HDA_ICII_VALID
Definition: azalia_device.h:19
#define HDA_STATESTS_REG
Definition: azalia_device.h:14
#define HDA_GCAP_REG
Definition: azalia_device.h:11
#define HDA_ICII_REG
Definition: azalia_device.h:17
#define HDA_IC_REG
Definition: azalia_device.h:15
static u32 addr
Definition: cirrus.c:14
#define printk(level,...)
Definition: stdlib.h:16
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
uintptr_t base
Definition: uart.c:17
static int hda_wait_for_valid(u8 *base)
Definition: hda_verb.c:73
int hda_codec_write(u8 *base, u32 size, const u32 *data)
Definition: hda_verb.c:94
static int hda_wait_for_ready(u8 *base)
Definition: hda_verb.c:54
int hda_codec_detect(u8 *base)
Definition: hda_verb.c:10
int hda_codec_init(u8 *base, int addr, int verb_size, const u32 *verb_data)
Definition: hda_verb.c:111
uint32_t u32
Definition: stdint.h:51
uint8_t u8
Definition: stdint.h:45
void udelay(uint32_t us)
Definition: udelay.c:15