blob: 17db6583335eb8ab0d4d6b9237d1906deb3e81ea [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +01002
3#include <console/console.h>
4#include <device/device.h>
5#include <device/pci.h>
6#include <device/pci_ids.h>
7#include <device/pci_ops.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +01009#include <delay.h>
Vladimir Serbinenko75c83872014-09-05 01:01:31 +020010#include <device/azalia_device.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010011#include "pch.h"
12
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080013static int codec_detect(u8 *base)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010014{
15 u8 reg8;
16
Angel Pons7f839f62020-12-05 19:02:14 +010017 if (azalia_exit_reset(base) < 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010018 goto no_codec;
19
20 /* Write back the value once reset bit is set. */
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020021 write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG));
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010022
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020023 /* Read in Codec location (BAR + 0xe)[2..0] */
Elyes HAOUAS59236d52020-08-03 15:36:52 +020024 reg8 = read8(base + HDA_STATESTS_REG);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010025 reg8 &= 0x0f;
26 if (!reg8)
27 goto no_codec;
28
29 return reg8;
30
31no_codec:
Angel Pons2e0053b2020-12-05 19:06:55 +010032 /* Codec not found, put HDA back in reset */
33 azalia_enter_reset(base);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010034 printk(BIOS_DEBUG, "Azalia: No codec!\n");
35 return 0;
36}
37
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010038static void azalia_init(struct device *dev)
39{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080040 u8 *base;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010041 struct resource *res;
42 u32 codec_mask;
43 u8 reg8;
44 u16 reg16;
45 u32 reg32;
46
47 /* Find base address */
Angel Ponsf32ae102021-11-03 13:07:14 +010048 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010049 if (!res)
50 return;
51
Martin Roth26f97f92021-10-01 14:53:22 -060052 // NOTE this will break as soon as the Azalia gets a bar above 4G.
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020053 // Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080054 base = res2mmio(res, 0, 0);
Patrick Rudolph819c2062019-11-29 19:27:37 +010055 printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010056
57 if (RCBA32(0x2030) & (1 << 31)) {
58 reg32 = pci_read_config32(dev, 0x120);
59 reg32 &= 0xf8ffff01;
60 reg32 |= (1 << 24); // 2 << 24 for server
61 reg32 |= RCBA32(0x2030) & 0xfe;
62 pci_write_config32(dev, 0x120, reg32);
63
64 reg16 = pci_read_config16(dev, 0x78);
65 reg16 |= (1 << 11);
66 pci_write_config16(dev, 0x78, reg16);
67 } else
68 printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n");
69
70 reg32 = pci_read_config32(dev, 0x114);
71 reg32 &= ~0xfe;
72 pci_write_config32(dev, 0x114, reg32);
73
74 // Set VCi enable bit
75 reg32 = pci_read_config32(dev, 0x120);
76 reg32 |= (1 << 31);
77 pci_write_config32(dev, 0x120, reg32);
78
79 // Enable HDMI codec:
80 reg32 = pci_read_config32(dev, 0xc4);
81 reg32 |= (1 << 1);
82 pci_write_config32(dev, 0xc4, reg32);
83
84 reg8 = pci_read_config8(dev, 0x43);
85 reg8 |= (1 << 6);
86 pci_write_config8(dev, 0x43, reg8);
87
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010088 reg32 = pci_read_config32(dev, 0xd0);
89 reg32 &= ~(1 << 31);
90 pci_write_config32(dev, 0xd0, reg32);
91
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010092 /* Set Bus Master */
Elyes HAOUAS8b6dfde2020-04-28 09:58:21 +020093 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010094
95 pci_write_config8(dev, 0x3c, 0x0a); // unused?
96
97 /* Codec Initialization Programming Sequence */
98
99 /* Take controller out of reset */
Elyes HAOUAS59236d52020-08-03 15:36:52 +0200100 reg32 = read32(base + HDA_GCTL_REG);
101 reg32 |= HDA_GCTL_CRST;
102 write32(base + HDA_GCTL_REG, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100103 /* Wait 1ms */
104 udelay(1000);
105
106 //
107 reg8 = pci_read_config8(dev, 0x40); // Audio Control
108 reg8 |= 1; // Select Azalia mode. This needs to be controlled via devicetree.cb
109 pci_write_config8(dev, 0x40, reg8);
110
111 reg8 = pci_read_config8(dev, 0x4d); // Docking Status
112 reg8 &= ~(1 << 7); // Docking not supported
113 pci_write_config8(dev, 0x4d, reg8);
114
115 codec_mask = codec_detect(base);
116
117 if (codec_mask) {
118 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
Angel Ponsaae6b552021-11-10 18:10:38 +0100119 azalia_codecs_init(base, codec_mask);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100120 }
121
122 /* Enable dynamic clock gating */
123 reg8 = pci_read_config8(dev, 0x43);
124 reg8 &= ~0x7;
125 reg8 |= (1 << 2) | (1 << 0);
126 pci_write_config8(dev, 0x43, reg8);
127}
128
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100129static struct device_operations azalia_ops = {
130 .read_resources = pci_dev_read_resources,
131 .set_resources = pci_dev_set_resources,
132 .enable_resources = pci_dev_enable_resources,
133 .init = azalia_init,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200134 .ops_pci = &pci_dev_ops_pci,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100135};
136
Felix Singer838fbc72019-11-21 21:23:32 +0100137static const unsigned short pci_device_ids[] = {
138 0x1c20,
139 0x1e20,
140 PCI_DID_INTEL_IBEXPEAK_AUDIO,
141 0
142};
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100143
144static const struct pci_driver pch_azalia __pci_driver = {
145 .ops = &azalia_ops,
146 .vendor = PCI_VENDOR_ID_INTEL,
147 .devices = pci_device_ids,
148};