1 // SPDX-License-Identifier: GPL-2.0
3 * Intel HDA audio (Azalia) for ivybridge
5 * Originally from coreboot file bd82x6x/azalia.c
7 * Copyright (C) 2008 Advanced Micro Devices, Inc.
8 * Copyright (C) 2008-2009 coresystems GmbH
9 * Copyright (C) 2011 The ChromiumOS Authors.
10 * Copyright 2018 Google LLC
13 #define LOG_CATEGORY UCLASS_SOUND
17 #include <hda_codec.h>
21 #include <linux/bitops.h>
22 #include <asm/global_data.h>
24 static int bd82x6x_azalia_probe(struct udevice *dev)
26 struct pci_child_plat *plat;
27 struct hda_codec_priv *priv;
33 /* Only init after relocation */
34 if (!(gd->flags & GD_FLG_RELOC))
37 ret = hda_codec_init(dev);
39 log_debug("Cannot set up HDA codec (err=%d)\n", ret);
42 priv = dev_get_priv(dev);
44 ret = uclass_first_device_err(UCLASS_PCH, &pch);
45 log_debug("PCH %p %s\n", pch, pch->name);
49 conf = pch_ioctl(pch, PCH_REQ_HDA_CONFIG, NULL, 0);
50 log_debug("conf = %x\n", conf);
52 dm_pci_clrset_config32(dev, 0x120, 7 << 24 | 0xfe,
53 1 << 24 | /* 2 << 24 for server */
56 dm_pci_clrset_config16(dev, 0x78, 0, 1 << 1);
58 log_debug("V1CTL disabled\n");
60 dm_pci_clrset_config32(dev, 0x114, 0xfe, 0);
62 /* Set VCi enable bit */
63 dm_pci_clrset_config32(dev, 0x120, 0, 1U << 31);
65 /* Enable HDMI codec */
66 dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 1);
67 dm_pci_clrset_config8(dev, 0x43, 0, 1 << 6);
69 /* Additional programming steps */
70 dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 13);
71 dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 10);
72 dm_pci_clrset_config32(dev, 0xd0, 1U << 31, 0);
74 /* Additional step on Panther Point */
75 plat = dev_get_parent_plat(dev);
76 if (plat->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA)
77 dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 17);
79 dm_pci_write_config8(dev, 0x3c, 0xa); /* unused? */
81 /* Audio Control: Select Azalia mode */
82 dm_pci_clrset_config8(dev, 0x40, 0, 1);
83 dm_pci_clrset_config8(dev, 0x4d, 1 << 7, 0); /* Docking not supported */
84 codec_mask = hda_codec_detect(priv->regs);
85 log_debug("codec_mask = %02x\n", codec_mask);
88 ret = hda_codecs_init(dev, priv->regs, codec_mask);
90 log_err("Codec init failed (err=%d)\n", ret);
95 /* Enable dynamic clock gating */
96 dm_pci_clrset_config8(dev, 0x43, 7, BIT(2) | BIT(0));
98 ret = hda_codec_finish_init(dev);
100 log_debug("Cannot set up HDA codec (err=%d)\n", ret);
107 static int bd82x6x_azalia_setup(struct udevice *dev)
112 int bd82x6x_azalia_start_beep(struct udevice *dev, int frequency_hz)
114 return hda_codec_start_beep(dev, frequency_hz);
117 int bd82x6x_azalia_stop_beep(struct udevice *dev)
119 return hda_codec_stop_beep(dev);
122 static const struct sound_ops bd82x6x_azalia_ops = {
123 .setup = bd82x6x_azalia_setup,
124 .start_beep = bd82x6x_azalia_start_beep,
125 .stop_beep = bd82x6x_azalia_stop_beep,
128 static const struct udevice_id bd82x6x_azalia_ids[] = {
129 { .compatible = "intel,hd-audio" },
133 U_BOOT_DRIVER(bd82x6x_azalia_drv) = {
134 .name = "bd82x6x-hda",
136 .of_match = bd82x6x_azalia_ids,
137 .probe = bd82x6x_azalia_probe,
138 .ops = &bd82x6x_azalia_ops,
139 .priv_auto = sizeof(struct hda_codec_priv),