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