blob: ac950c46df91dec89a703420d7e63a123953a86d [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;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010043 u32 reg32;
44
45 /* Find base address */
Angel Ponsf32ae102021-11-03 13:07:14 +010046 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010047 if (!res)
48 return;
49
Martin Roth26f97f92021-10-01 14:53:22 -060050 // NOTE this will break as soon as the Azalia gets a bar above 4G.
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020051 // Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080052 base = res2mmio(res, 0, 0);
Patrick Rudolph819c2062019-11-29 19:27:37 +010053 printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010054
55 if (RCBA32(0x2030) & (1 << 31)) {
56 reg32 = pci_read_config32(dev, 0x120);
57 reg32 &= 0xf8ffff01;
58 reg32 |= (1 << 24); // 2 << 24 for server
59 reg32 |= RCBA32(0x2030) & 0xfe;
60 pci_write_config32(dev, 0x120, reg32);
61
Elyes HAOUASf91538c2022-02-07 08:00:59 +010062 pci_or_config16(dev, 0x78, 1 << 11);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010063 } else
64 printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n");
65
Elyes HAOUASf91538c2022-02-07 08:00:59 +010066 pci_and_config32(dev, 0x114, ~0xfe);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010067
68 // Set VCi enable bit
Elyes HAOUASf91538c2022-02-07 08:00:59 +010069 pci_or_config32(dev, 0x120, 1 << 31);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010070
71 // Enable HDMI codec:
Elyes HAOUASf91538c2022-02-07 08:00:59 +010072 pci_or_config32(dev, 0xc4, 1 << 1);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010073
Elyes HAOUASf91538c2022-02-07 08:00:59 +010074 pci_or_config8(dev, 0x43, 1 << 6);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010075
Elyes HAOUASf91538c2022-02-07 08:00:59 +010076 pci_and_config32(dev, 0xd0, ~(1 << 31));
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010077
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010078 /* Set Bus Master */
Elyes HAOUAS8b6dfde2020-04-28 09:58:21 +020079 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010080
81 pci_write_config8(dev, 0x3c, 0x0a); // unused?
82
83 /* Codec Initialization Programming Sequence */
84
85 /* Take controller out of reset */
Elyes HAOUAS59236d52020-08-03 15:36:52 +020086 reg32 = read32(base + HDA_GCTL_REG);
87 reg32 |= HDA_GCTL_CRST;
88 write32(base + HDA_GCTL_REG, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010089 /* Wait 1ms */
90 udelay(1000);
91
Elyes HAOUASf91538c2022-02-07 08:00:59 +010092 // Select Azalia mode. This needs to be controlled via devicetree.cb
93 pci_or_config8(dev, 0x40, 1); // Audio Control
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010094
Elyes HAOUASf91538c2022-02-07 08:00:59 +010095 // Docking not supported
96 pci_and_config8(dev, 0x4d, (u8)~(1 << 7)); // Docking Status
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010097
98 codec_mask = codec_detect(base);
99
100 if (codec_mask) {
101 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
Angel Ponsaae6b552021-11-10 18:10:38 +0100102 azalia_codecs_init(base, codec_mask);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100103 }
104
105 /* Enable dynamic clock gating */
Elyes HAOUASf91538c2022-02-07 08:00:59 +0100106 pci_update_config8(dev, 0x43, ~0x07, (1 << 2) | (1 << 0));
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100107}
108
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100109static struct device_operations azalia_ops = {
110 .read_resources = pci_dev_read_resources,
111 .set_resources = pci_dev_set_resources,
112 .enable_resources = pci_dev_enable_resources,
113 .init = azalia_init,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200114 .ops_pci = &pci_dev_ops_pci,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100115};
116
Felix Singer838fbc72019-11-21 21:23:32 +0100117static const unsigned short pci_device_ids[] = {
118 0x1c20,
119 0x1e20,
120 PCI_DID_INTEL_IBEXPEAK_AUDIO,
121 0
122};
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100123
124static const struct pci_driver pch_azalia __pci_driver = {
125 .ops = &azalia_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100126 .vendor = PCI_VID_INTEL,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100127 .devices = pci_device_ids,
128};