blob: 31827e6de997b5363c54bcc5689a01a384ad97c1 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer679c9f92009-01-20 22:54:59 +00002
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>
Stefan Reinauer679c9f92009-01-20 22:54:59 +00009#include <delay.h>
Vladimir Serbinenko75c83872014-09-05 01:01:31 +020010#include <device/azalia_device.h>
Arthur Heymans028b94b2021-07-02 10:06:55 +020011#include <stdint.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030012#include "chip.h"
Stefan Reinauer679c9f92009-01-20 22:54:59 +000013#include "i82801gx.h"
14
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080015static int codec_detect(u8 *base)
Stefan Reinauer679c9f92009-01-20 22:54:59 +000016{
Stefan Reinauera8e11682009-03-11 14:54:18 +000017 u32 reg32;
Stefan Reinauer679c9f92009-01-20 22:54:59 +000018
Angel Pons2e0053b2020-12-05 19:06:55 +010019 if (azalia_enter_reset(base) < 0)
Stefan Reinauera8e11682009-03-11 14:54:18 +000020 goto no_codec;
Stefan Reinauer679c9f92009-01-20 22:54:59 +000021
Angel Pons7f839f62020-12-05 19:02:14 +010022 if (azalia_exit_reset(base) < 0)
Stefan Reinauera8e11682009-03-11 14:54:18 +000023 goto no_codec;
Stefan Reinauer679c9f92009-01-20 22:54:59 +000024
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020025 /* Read in Codec location (BAR + 0xe)[2..0] */
Elyes HAOUASf1da9092020-08-03 15:35:16 +020026 reg32 = read32(base + HDA_STATESTS_REG);
Stefan Reinauera8e11682009-03-11 14:54:18 +000027 reg32 &= 0x0f;
28 if (!reg32)
29 goto no_codec;
Stefan Reinauer109ab312009-08-12 16:08:05 +000030
Stefan Reinauera8e11682009-03-11 14:54:18 +000031 return reg32;
32
33no_codec:
Angel Pons2e0053b2020-12-05 19:06:55 +010034 /* Codec not found, put HDA back in reset */
35 azalia_enter_reset(base);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000036 printk(BIOS_DEBUG, "Azalia: No codec!\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +000037 return 0;
Stefan Reinauer679c9f92009-01-20 22:54:59 +000038}
39
Stefan Reinauer679c9f92009-01-20 22:54:59 +000040static void azalia_init(struct device *dev)
41{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080042 u8 *base;
Stefan Reinauer679c9f92009-01-20 22:54:59 +000043 struct resource *res;
44 u32 codec_mask;
Stefan Reinauera8e11682009-03-11 14:54:18 +000045 u8 reg8;
Stefan Reinauer679c9f92009-01-20 22:54:59 +000046
Stefan Reinauera8e11682009-03-11 14:54:18 +000047 // ESD
Angel Ponsd19332c2020-06-08 12:32:54 +020048 pci_update_config32(dev, 0x134, ~(0xff << 16), 2 << 16);
Stefan Reinauera8e11682009-03-11 14:54:18 +000049
50 // Link1 description
Angel Ponsd19332c2020-06-08 12:32:54 +020051 pci_update_config32(dev, 0x140, ~(0xff << 16), 2 << 16);
Stefan Reinauera8e11682009-03-11 14:54:18 +000052
53 // Port VC0 Resource Control Register
Angel Ponsd19332c2020-06-08 12:32:54 +020054 pci_update_config32(dev, 0x114, ~(0xff << 0), 1);
Stefan Reinauera8e11682009-03-11 14:54:18 +000055
56 // VCi traffic class
Angel Ponsd19332c2020-06-08 12:32:54 +020057 pci_or_config8(dev, 0x44, 7 << 0); // TC7
Stefan Reinauera8e11682009-03-11 14:54:18 +000058
59 // VCi Resource Control
Angel Ponsd19332c2020-06-08 12:32:54 +020060 pci_or_config32(dev, 0x120, (1 << 31) | (1 << 24) | (0x80 << 0)); /* VCi ID and map */
Stefan Reinauera8e11682009-03-11 14:54:18 +000061
62 /* Set Bus Master */
Elyes HAOUAS12349252020-04-27 05:08:26 +020063 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER);
Stefan Reinauera8e11682009-03-11 14:54:18 +000064
65 pci_write_config8(dev, 0x3c, 0x0a); // unused?
66
67 // TODO Actually check if we're AC97 or HDA instead of hardcoding this
Stefan Reinauer38f147e2010-02-08 12:20:50 +000068 // here, in devicetree.cb and/or romstage.c.
Stefan Reinauera8e11682009-03-11 14:54:18 +000069 reg8 = pci_read_config8(dev, 0x40);
70 reg8 |= (1 << 3); // Clear Clock Detect Bit
71 pci_write_config8(dev, 0x40, reg8);
72 reg8 &= ~(1 << 3); // Keep CLKDETCLR from clearing the bit over and over
73 pci_write_config8(dev, 0x40, reg8);
74 reg8 |= (1 << 2); // Enable clock detection
75 pci_write_config8(dev, 0x40, reg8);
76 mdelay(1);
77 reg8 = pci_read_config8(dev, 0x40);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000078 printk(BIOS_DEBUG, "Azalia: codec type: %s\n", (reg8 & (1 << 1))?"Azalia":"AC97");
Stefan Reinauera8e11682009-03-11 14:54:18 +000079
Angel Ponsd19332c2020-06-08 12:32:54 +020080 // Select Azalia mode. This needs to be controlled via devicetree.cb
81 pci_or_config8(dev, 0x40, 1); // Audio Control
Stefan Reinauera8e11682009-03-11 14:54:18 +000082
Angel Ponsd19332c2020-06-08 12:32:54 +020083 // Docking not supported
84 pci_and_config8(dev, 0x4d, (u8)~(1 << 7)); // Docking Status
Stefan Reinauer679c9f92009-01-20 22:54:59 +000085
Angel Ponsf32ae102021-11-03 13:07:14 +010086 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
Stefan Reinauer679c9f92009-01-20 22:54:59 +000087 if (!res)
88 return;
89
Martin Roth26f97f92021-10-01 14:53:22 -060090 // NOTE this will break as soon as the Azalia gets a bar above 4G.
Elyes HAOUAS6ea24ff2020-08-11 09:21:24 +020091 // Is there anything we can do about it?
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080092 base = res2mmio(res, 0, 0);
Arthur Heymans028b94b2021-07-02 10:06:55 +020093 printk(BIOS_DEBUG, "Azalia: base = %08x\n", (u32)(uintptr_t)base);
Stefan Reinauer679c9f92009-01-20 22:54:59 +000094 codec_mask = codec_detect(base);
95
96 if (codec_mask) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000097 printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask);
Angel Ponsaae6b552021-11-10 18:10:38 +010098 azalia_codecs_init(base, codec_mask);
Stefan Reinauer679c9f92009-01-20 22:54:59 +000099 }
100}
101
102static struct device_operations azalia_ops = {
103 .read_resources = pci_dev_read_resources,
104 .set_resources = pci_dev_set_resources,
105 .enable_resources = pci_dev_enable_resources,
106 .init = azalia_init,
Stefan Reinauer679c9f92009-01-20 22:54:59 +0000107 .enable = i82801gx_enable,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200108 .ops_pci = &pci_dev_ops_pci,
Stefan Reinauer679c9f92009-01-20 22:54:59 +0000109};
110
111/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
112static const struct pci_driver i82801gx_azalia __pci_driver = {
113 .ops = &azalia_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100114 .vendor = PCI_VID_INTEL,
Stefan Reinauer679c9f92009-01-20 22:54:59 +0000115 .device = 0x27d8,
116};