blob: af6148ef7240324af603f8f164c79898bacb5011 [file] [log] [blame]
Simon Glass2ca47132019-02-16 20:24:55 -07001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Implementation of per-board codec beeping
4 * Copyright (c) 2011 The Chromium OS Authors.
5 * Copyright 2018 Google LLC
6 */
7
8#define LOG_CATEGORY UCLASS_SOUND
9
10#include <common.h>
11#include <dm.h>
12#include <hda_codec.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060013#include <log.h>
Simon Glass2ca47132019-02-16 20:24:55 -070014#include <pci.h>
15#include <sound.h>
16#include <asm/io.h>
17#include <dt-bindings/sound/azalia.h>
Simon Glasscd93d622020-05-10 11:40:13 -060018#include <linux/bitops.h>
Simon Glassc05ed002020-05-10 11:40:11 -060019#include <linux/delay.h>
Simon Glass2ca47132019-02-16 20:24:55 -070020
21/**
22 * struct hda_regs - HDA registers
23 *
24 * https://wiki.osdev.org/Intel_High_Definition_Audio
25 * https://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html
26 */
27struct hda_regs {
28 u16 gcap;
29 u8 vmin;
30 u8 vmaj;
31 u16 outpay;
32 u16 inpay;
33 u32 gctl;
34 u16 wakeen;
35 u16 statests;
36 u8 reserved[0x50];
37 u32 cmd; /* 0x60 */
38 u32 resp;
39 u32 icii;
40};
41
42enum {
43 HDA_ICII_BUSY = BIT(0),
44 HDA_ICII_VALID = BIT(1),
45
46 /* Common node IDs */
47 HDA_ROOT_NODE = 0x00,
48
49 /* HDA verbs fields */
50 HDA_VERB_NID_S = 20,
51 HDA_VERB_VERB_S = 8,
52 HDA_VERB_PARAM_S = 0,
53
54 HDA_VERB_GET_PARAMS = 0xf00,
55 HDA_VERB_SET_BEEP = 0x70a,
56
57 /* GET_PARAMS parameter IDs */
58 GET_PARAMS_NODE_COUNT = 0x04,
59 GET_PARAMS_AUDIO_GROUP_CAPS = 0x08,
60 GET_PARAMS_AUDIO_WIDGET_CAPS = 0x09,
61
62 /* Sub-node fields */
63 NUM_SUB_NODES_S = 0,
64 NUM_SUB_NODES_M = 0xff << NUM_SUB_NODES_S,
65 FIRST_SUB_NODE_S = 16,
66 FIRST_SUB_NODE_M = 0xff << FIRST_SUB_NODE_S,
67
68 /* Get Audio Function Group Capabilities fields */
69 AUDIO_GROUP_CAPS_BEEP_GEN = 0x10000,
70
71 /* Get Audio Widget Capabilities fields */
72 AUDIO_WIDGET_TYPE_BEEP = 0x7,
73 AUDIO_WIDGET_TYPE_S = 20,
74 AUDIO_WIDGET_TYPE_M = 0xf << AUDIO_WIDGET_TYPE_S,
75
76 BEEP_FREQ_BASE = 12000,
77};
78
79static inline uint hda_verb(uint nid, uint verb, uint param)
80{
81 return nid << HDA_VERB_NID_S | verb << HDA_VERB_VERB_S |
82 param << HDA_VERB_PARAM_S;
83}
84
85int hda_wait_for_ready(struct hda_regs *regs)
86{
87 int timeout = 1000; /* Use a 1msec timeout */
88
89 while (timeout--) {
90 u32 reg32 = readl(&regs->icii);
91
92 if (!(reg32 & HDA_ICII_BUSY))
93 return 0;
94 udelay(1);
95 }
96
97 return -ETIMEDOUT;
98}
99
100static int wait_for_response(struct hda_regs *regs, uint *response)
101{
102 int timeout = 1000;
103 u32 reg32;
104
105 /* Send the verb to the codec */
106 setbits_le32(&regs->icii, HDA_ICII_BUSY | HDA_ICII_VALID);
107
108 /* Use a 1msec timeout */
109 while (timeout--) {
110 reg32 = readl(&regs->icii);
111 if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
112 HDA_ICII_VALID) {
113 if (response)
114 *response = readl(&regs->resp);
115 return 0;
116 }
117 udelay(1);
118 }
119
120 return -ETIMEDOUT;
121}
122
123int hda_wait_for_valid(struct hda_regs *regs)
124{
125 return wait_for_response(regs, NULL);
126}
127
128static int set_bits(void *port, u32 mask, u32 val)
129{
130 u32 reg32;
131 int count;
132
133 /* Write (val & mask) to port */
134 clrsetbits_le32(port, mask, val);
135
136 /* Wait for readback of register to match what was just written to it */
137 count = 50;
138 do {
139 /* Wait 1ms based on BKDG wait time */
140 mdelay(1);
141 reg32 = readl(port) & mask;
142 } while (reg32 != val && --count);
143
144 /* Timeout occurred */
145 if (!count)
146 return -ETIMEDOUT;
147
148 return 0;
149}
150
151int hda_codec_detect(struct hda_regs *regs)
152{
153 uint reg8;
154
155 /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
156 if (set_bits(&regs->gctl, 1, 1))
157 goto no_codec;
158
159 /* Write back the value once reset bit is set */
160 writew(readw(&regs->gcap), &regs->gcap);
161
162 /* Read in Codec location */
163 reg8 = readb(&regs->statests) & 0xf;
164 if (!reg8)
165 goto no_codec;
166
167 return reg8;
168
169no_codec:
170 /* Codec Not found - put HDA back in reset */
171 set_bits(&regs->gctl, 1, 0);
172 log_debug("No codec\n");
173
174 return 0;
175}
176
177static int find_verb_data(struct udevice *dev, uint id, ofnode *nodep)
178{
179 ofnode parent = dev_read_subnode(dev, "codecs");
180 ofnode node;
181 u32 vendor_id, device_id;
182
183 ofnode_for_each_subnode(node, parent) {
184 if (ofnode_read_u32(node, "vendor-id", &vendor_id) ||
185 ofnode_read_u32(node, "device-id", &device_id)) {
186 log_debug("Cannot get IDs for '%s'\n",
187 ofnode_get_name(node));
188 return -EINVAL;
189 }
190 if (id != (vendor_id << 16 | device_id)) {
191 log_debug("Skip codec node '%s' for %08x\n",
192 ofnode_get_name(node), id);
193 continue;
194 }
195
196 log_debug("Found codec node '%s' for %08x\n",
197 ofnode_get_name(node), id);
198 *nodep = node;
199 return 0;
200 }
201
202 return -ENOENT;
203}
204
205static int send_verbs(ofnode node, const char *prop_name, struct hda_regs *regs)
206{
207 int ret, verb_size, i;
208 const u32 *verb;
209
210 verb = ofnode_get_property(node, prop_name, &verb_size);
211 if (verb_size < 0) {
212 log_debug("No verb data\n");
213 return -EINVAL;
214 }
215 log_debug("verb_size: %d\n", verb_size);
216
217 for (i = 0; i < verb_size / sizeof(*verb); i++) {
218 ret = hda_wait_for_ready(regs);
219 if (ret) {
220 log_debug(" codec ready timeout\n");
221 return ret;
222 }
223
224 writel(fdt32_to_cpu(verb[i]), &regs->cmd);
225
226 ret = hda_wait_for_valid(regs);
227 if (ret) {
228 log_debug(" codec valid timeout\n");
229 return ret;
230 }
231 }
232
233 return 0;
234}
235
236static int codec_init(struct udevice *dev, struct hda_regs *regs, uint addr)
237{
238 ofnode node;
239 uint id;
240 int ret;
241
242 log_debug("Initializing codec #%d\n", addr);
243 ret = hda_wait_for_ready(regs);
244 if (ret) {
245 log_debug(" codec not ready\n");
246 return ret;
247 }
248
249 /* Read the codec's vendor ID */
250 writel(addr << AZALIA_CODEC_SHIFT |
251 AZALIA_OPCODE_READ_PARAM << AZALIA_VERB_SHIFT |
252 AZALIA_PARAM_VENDOR_ID, &regs->cmd);
253 ret = hda_wait_for_valid(regs);
254 if (ret) {
255 log_debug(" codec not valid\n");
256 return ret;
257 }
258
259 id = readl(&regs->resp);
260 log_debug("codec vid/did: %08x\n", id);
261 ret = find_verb_data(dev, id, &node);
262 if (ret) {
263 log_debug("No verb (err=%d)\n", ret);
264 return ret;
265 }
266 ret = send_verbs(node, "verbs", regs);
267 if (ret) {
268 log_debug("failed to send verbs (err=%d)\n", ret);
269 return ret;
270 }
271 log_debug("verb loaded\n");
272
273 return 0;
274}
275
276int hda_codecs_init(struct udevice *dev, struct hda_regs *regs, u32 codec_mask)
277{
278 int ret;
279 int i;
280
281 for (i = 3; i >= 0; i--) {
282 if (codec_mask & (1 << i)) {
283 ret = codec_init(dev, regs, i);
284 if (ret)
285 return ret;
286 }
287 }
288
289 ret = send_verbs(dev_ofnode(dev), "beep-verbs", regs);
290 if (ret) {
291 log_debug("failed to send beep verbs (err=%d)\n", ret);
292 return ret;
293 }
294 log_debug("beep verbs loaded\n");
295
296 return 0;
297}
298
299/**
300 * exec_verb() - Write a verb to the codec
301 *
302 * @regs: HDA registers
303 * @val: Command to write
304 * @response: Set to response from codec
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100305 * Return: 0 if OK, -ve on error
Simon Glass2ca47132019-02-16 20:24:55 -0700306 */
307static int exec_verb(struct hda_regs *regs, uint val, uint *response)
308{
309 int ret;
310
311 ret = hda_wait_for_ready(regs);
312 if (ret)
313 return ret;
314
315 writel(val, &regs->cmd);
316
317 return wait_for_response(regs, response);
318}
319
320/**
321 * get_subnode_info() - Get subnode information
322 *
323 * @regs: HDA registers
324 * @nid: Parent node ID to check
325 * @num_sub_nodesp: Returns number of subnodes
326 * @start_sub_node_nidp: Returns start subnode number
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100327 * Return: 0 if OK, -ve on error
Simon Glass2ca47132019-02-16 20:24:55 -0700328 */
329static int get_subnode_info(struct hda_regs *regs, uint nid,
330 uint *num_sub_nodesp, uint *start_sub_node_nidp)
331{
332 uint response;
333 int ret;
334
335 ret = exec_verb(regs, hda_verb(nid, HDA_VERB_GET_PARAMS,
336 GET_PARAMS_NODE_COUNT),
337 &response);
338 if (ret < 0) {
339 printf("Audio: Error reading sub-node info %d\n", nid);
340 return ret;
341 }
342
343 *num_sub_nodesp = (response & NUM_SUB_NODES_M) >> NUM_SUB_NODES_S;
344 *start_sub_node_nidp = (response & FIRST_SUB_NODE_M) >>
345 FIRST_SUB_NODE_S;
346
347 return 0;
348}
349
350/**
351 * find_beep_node_in_group() - Finds the beeping node
352 *
353 * Searches the audio group for a node that supports beeping
354 *
355 * @regs: HDA registers
356 * @group_nid: Group node ID to check
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100357 * Return: 0 if OK, -ve on error
Simon Glass2ca47132019-02-16 20:24:55 -0700358 */
359static uint find_beep_node_in_group(struct hda_regs *regs, uint group_nid)
360{
361 uint node_count = 0;
362 uint current_nid = 0;
363 uint response;
364 uint end_nid;
365 int ret;
366
367 ret = get_subnode_info(regs, group_nid, &node_count, &current_nid);
368 if (ret < 0)
369 return 0;
370
371 end_nid = current_nid + node_count;
372 while (current_nid < end_nid) {
373 ret = exec_verb(regs,
374 hda_verb(current_nid, HDA_VERB_GET_PARAMS,
375 GET_PARAMS_AUDIO_WIDGET_CAPS),
376 &response);
377 if (ret < 0) {
378 printf("Audio: Error reading widget caps\n");
379 return 0;
380 }
381
382 if ((response & AUDIO_WIDGET_TYPE_M) >> AUDIO_WIDGET_TYPE_S ==
383 AUDIO_WIDGET_TYPE_BEEP)
384 return current_nid;
385
386 current_nid++;
387 }
388
389 return 0; /* no beep node found */
390}
391
392/**
393 * audio_group_has_beep_node() - Check if group has a beep node
394 *
395 * Checks if the given audio group contains a beep generator
396 * @regs: HDA registers
397 * @nid: Node ID to check
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100398 * Return: 0 if OK, -ve on error
Simon Glass2ca47132019-02-16 20:24:55 -0700399 */
400static int audio_group_has_beep_node(struct hda_regs *regs, uint nid)
401{
402 uint response;
403 int ret;
404
405 ret = exec_verb(regs, hda_verb(nid, HDA_VERB_GET_PARAMS,
406 GET_PARAMS_AUDIO_GROUP_CAPS),
407 &response);
408 if (ret < 0) {
409 printf("Audio: Error reading audio group caps %d\n", nid);
410 return 0;
411 }
412
413 return !!(response & AUDIO_GROUP_CAPS_BEEP_GEN);
414}
415
416/**
417 * get_hda_beep_nid() - Finds the node ID of the beep node
418 *
419 * Finds the nid of the beep node if it exists. Starts at the root node, for
420 * each sub-node checks if the group contains a beep node. If the group
421 * contains a beep node, polls each node in the group until it is found.
422 *
423 * If the device has a intel,beep-nid property, the value of that is used
424 * instead.
425 *
426 * @dev: Sound device
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100427 * Return: Node ID >0 if found, -ve error code otherwise
Simon Glass2ca47132019-02-16 20:24:55 -0700428 */
429static int get_hda_beep_nid(struct udevice *dev)
430{
431 struct hda_codec_priv *priv = dev_get_priv(dev);
432 uint current_nid = 0;
433 uint node_count = 0;
434 uint end_nid;
435 int ret;
436
437 /* If the field exists, use the beep nid set in the fdt */
438 ret = dev_read_u32(dev, "intel,beep-nid", &current_nid);
439 if (!ret)
440 return current_nid;
441
442 ret = get_subnode_info(priv->regs, HDA_ROOT_NODE, &node_count,
443 &current_nid);
444 if (ret < 0)
445 return ret;
446
447 end_nid = current_nid + node_count;
448 while (current_nid < end_nid) {
449 if (audio_group_has_beep_node(priv->regs, current_nid))
450 return find_beep_node_in_group(priv->regs,
451 current_nid);
452 current_nid++;
453 }
454 /* no beep node found */
455
456 return -ENOENT;
457}
458
459/**
460 * set_beep_divisor() - Sets the beep divisor to set the pitch
461 *
462 * @priv: Device's private data
463 * @divider: Divider value (0 to disable the beep)
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100464 * Return: 0 if OK, -ve on error
Simon Glass2ca47132019-02-16 20:24:55 -0700465 */
466static int set_beep_divisor(struct hda_codec_priv *priv, uint divider)
467{
468 return exec_verb(priv->regs,
469 hda_verb(priv->beep_nid, HDA_VERB_SET_BEEP, divider),
470 NULL);
471}
472
473int hda_codec_init(struct udevice *dev)
474{
475 struct hda_codec_priv *priv = dev_get_priv(dev);
476 ulong base_addr;
477
478 base_addr = dm_pci_read_bar32(dev, 0);
479 log_debug("base = %08lx\n", base_addr);
480 if (!base_addr)
481 return -EINVAL;
482
483 priv->regs = (struct hda_regs *)base_addr;
484
485 return 0;
486}
487
488int hda_codec_finish_init(struct udevice *dev)
489{
490 struct hda_codec_priv *priv = dev_get_priv(dev);
491 int ret;
492
493 ret = get_hda_beep_nid(dev);
494 if (ret <= 0) {
495 log_warning("Could not find beep NID (err=%d)\n", ret);
496 return ret ? ret : -ENOENT;
497 }
498 priv->beep_nid = ret;
499
500 return 0;
501}
502
503int hda_codec_start_beep(struct udevice *dev, int frequency_hz)
504{
505 struct hda_codec_priv *priv = dev_get_priv(dev);
506 uint divider_val;
507
508 if (!priv->beep_nid) {
509 log_err("Failed to find a beep-capable node\n");
510 return -ENOENT;
511 }
512
513 if (!frequency_hz)
514 divider_val = 0; /* off */
515 else if (frequency_hz > BEEP_FREQ_BASE)
516 divider_val = 1;
517 else if (frequency_hz < BEEP_FREQ_BASE / 0xff)
518 divider_val = 0xff;
519 else
520 divider_val = 0xff & (BEEP_FREQ_BASE / frequency_hz);
521
522 return set_beep_divisor(priv, divider_val);
523}
524
525int hda_codec_stop_beep(struct udevice *dev)
526{
527 struct hda_codec_priv *priv = dev_get_priv(dev);
528
529 return set_beep_divisor(priv, 0);
530}
531
532static const struct sound_ops hda_codec_ops = {
533 .setup = hda_codec_finish_init,
534 .start_beep = hda_codec_start_beep,
535 .stop_beep = hda_codec_stop_beep,
536};
537
538U_BOOT_DRIVER(hda_codec) = {
539 .name = "hda_codec",
540 .id = UCLASS_SOUND,
541 .ops = &hda_codec_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700542 .priv_auto = sizeof(struct hda_codec_priv),
Simon Glass2ca47132019-02-16 20:24:55 -0700543 .probe = hda_codec_init,
544};
545
546static struct pci_device_id hda_supported[] = {
547 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_HDA},
548 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA},
549 { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
550 PCI_DEVICE_ID_INTEL_WILDCATPOINT_HDA) },
551
552 /*
553 * Note this driver is not necessarily generic, but it attempts to
554 * support any codec in the hd-audio class
555 */
556 { PCI_DEVICE_CLASS(PCI_CLASS_MULTIMEDIA_HD_AUDIO, 0xffffff) },
557};
558
559U_BOOT_PCI_DEVICE(hda_codec, hda_supported);