aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-02-20 12:28:40 -0500
committerTom Rini <trini@konsulko.com>2019-02-20 12:28:40 -0500
commit0c41e59a37fbd5b10d4837ae30c288a084997465 (patch)
treed67fad6104715409d83073752a67cea273727249
parent176b32cd4fec52307dd8234ec1c86d2f340e7a36 (diff)
parente2c901c99e2622005f98a9623c4b5339257bfad3 (diff)
downloadu-boot-0c41e59a37fbd5b10d4837ae30c288a084997465.zip
u-boot-0c41e59a37fbd5b10d4837ae30c288a084997465.tar.gz
u-boot-0c41e59a37fbd5b10d4837ae30c288a084997465.tar.bz2
Merge git://git.denx.de/u-boot-x86
- Add support for sound. Albeit the big changeset, changes are pretty limited to x86 only and a few new sound drivers used by x86 so I think it would be good to have this in the next release.
-rw-r--r--arch/Kconfig2
-rw-r--r--arch/sandbox/dts/test.dts5
-rw-r--r--arch/sandbox/include/asm/state.h9
-rw-r--r--arch/sandbox/include/asm/test.h24
-rw-r--r--arch/x86/cpu/broadwell/Makefile1
-rw-r--r--arch/x86/cpu/broadwell/adsp.c156
-rw-r--r--arch/x86/cpu/broadwell/pch.c110
-rw-r--r--arch/x86/cpu/broadwell/pinctrl_broadwell.c3
-rw-r--r--arch/x86/cpu/ivybridge/Kconfig1
-rw-r--r--arch/x86/cpu/ivybridge/bd82x6x.c27
-rw-r--r--arch/x86/cpu/ivybridge/northbridge.c32
-rw-r--r--arch/x86/dts/chromebook_link.dts96
-rw-r--r--arch/x86/dts/chromebook_samus.dts49
-rw-r--r--arch/x86/include/asm/arch-broadwell/adsp.h46
-rw-r--r--arch/x86/include/asm/arch-broadwell/pch.h3
-rw-r--r--arch/x86/include/asm/arch-broadwell/rcb.h2
-rw-r--r--arch/x86/include/asm/arch-broadwell/serialio.h82
-rw-r--r--arch/x86/include/asm/arch-ivybridge/sandybridge.h3
-rw-r--r--arch/x86/include/asm/i8254.h18
-rw-r--r--arch/x86/include/asm/io.h16
-rw-r--r--arch/x86/lib/i8254.c35
-rw-r--r--cmd/gpio.c10
-rw-r--r--common/Kconfig86
-rw-r--r--common/log.c2
-rw-r--r--configs/chromebook_link_defconfig5
-rw-r--r--configs/chromebook_samus_defconfig11
-rw-r--r--configs/coreboot_defconfig3
-rw-r--r--doc/README.log51
-rw-r--r--doc/device-tree-bindings/sound/intel-hda.txt25
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/core/syscon-uclass.c4
-rw-r--r--drivers/i2c/designware_i2c.c29
-rw-r--r--drivers/pch/Kconfig9
-rw-r--r--drivers/pch/Makefile1
-rw-r--r--drivers/pch/pch-uclass.c10
-rw-r--r--drivers/pch/sandbox_pch.c86
-rw-r--r--drivers/pci/pci.c7
-rw-r--r--drivers/sound/Kconfig40
-rw-r--r--drivers/sound/Makefile5
-rw-r--r--drivers/sound/broadwell_i2s.c306
-rw-r--r--drivers/sound/broadwell_i2s.h301
-rw-r--r--drivers/sound/broadwell_sound.c65
-rw-r--r--drivers/sound/hda_codec.c556
-rw-r--r--drivers/sound/i8254_beep.c38
-rw-r--r--drivers/sound/ivybridge_sound.c137
-rw-r--r--drivers/sound/rt5677.c334
-rw-r--r--drivers/sound/rt5677.h1428
-rw-r--r--drivers/sound/sandbox.c71
-rw-r--r--drivers/sound/sound-uclass.c36
-rw-r--r--include/dt-bindings/sound/azalia.h44
-rw-r--r--include/hda_codec.h103
-rw-r--r--include/log.h9
-rw-r--r--include/pch.h51
-rw-r--r--include/pci.h8
-rw-r--r--include/pci_ids.h5
-rw-r--r--include/sound.h46
-rw-r--r--test/dm/Makefile1
-rw-r--r--test/dm/pch.c55
-rw-r--r--test/dm/sound.c21
60 files changed, 4623 insertions, 101 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index 35e2712..d9afe26 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -117,6 +117,7 @@ config SANDBOX
imply VIRTIO_BLK
imply VIRTIO_NET
imply DM_SOUND
+ imply PCH
config SH
bool "SuperH architecture"
@@ -160,6 +161,7 @@ config X86
imply USB_ETHER_ASIX
imply USB_ETHER_SMSC95XX
imply USB_HOST_ETHER
+ imply PCH
config XTENSA
bool "Xtensa architecture"
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 1d011de..d4c708c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -389,6 +389,7 @@
i2s: i2s {
compatible = "sandbox,i2s";
#sound-dai-cells = <1>;
+ sandbox,silent; /* Don't emit sounds while testing */
};
misc-test {
@@ -407,6 +408,10 @@
compatible = "sandbox,mmc";
};
+ pch {
+ compatible = "sandbox,pch";
+ };
+
pci0: pci-controller0 {
compatible = "sandbox,pci";
device_type = "pci";
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index c724827..2d773d3 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -102,6 +102,15 @@ struct sandbox_state {
ulong next_tag; /* Next address tag to allocate */
struct list_head mapmem_head; /* struct sandbox_mapmem_entry */
bool hwspinlock; /* Hardware Spinlock status */
+
+ /*
+ * This struct is getting large.
+ *
+ * Consider putting test data in driver-private structs, like
+ * sandbox_pch.c.
+ *
+ * If you add new members, please put them above this comment.
+ */
};
/* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 74f9618..fc52f47 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -161,4 +161,28 @@ int sandbox_get_setup_called(struct udevice *dev);
*/
int sandbox_get_sound_sum(struct udevice *dev);
+/**
+ * sandbox_set_allow_beep() - Set whether the 'beep' interface is supported
+ *
+ * @dev: Device to update
+ * @allow: true to allow the start_beep() method, false to disallow it
+ */
+void sandbox_set_allow_beep(struct udevice *dev, bool allow);
+
+/**
+ * sandbox_get_beep_frequency() - Get the frequency of the current beep
+ *
+ * @dev: Device to check
+ * @return frequency of beep, if there is an active beep, else 0
+ */
+int sandbox_get_beep_frequency(struct udevice *dev);
+
+/**
+ * sandbox_get_pch_spi_protect() - Get the PCI SPI protection status
+ *
+ * @dev: Device to check
+ * @return 0 if not protected, 1 if protected
+ */
+int sandbox_get_pch_spi_protect(struct udevice *dev);
+
#endif
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile
index a032861..d3785aa 100644
--- a/arch/x86/cpu/broadwell/Makefile
+++ b/arch/x86/cpu/broadwell/Makefile
@@ -2,6 +2,7 @@
#
# Copyright (c) 2016 Google, Inc
+obj-y += adsp.o
obj-y += cpu.o
obj-y += iobp.o
obj-y += lpc.o
diff --git a/arch/x86/cpu/broadwell/adsp.c b/arch/x86/cpu/broadwell/adsp.c
new file mode 100644
index 0000000..2ac8cea
--- /dev/null
+++ b/arch/x86/cpu/broadwell/adsp.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for Intel Application Digital Signal Processor
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot file of the same name
+ */
+
+#define LOG_CATEGORY UCLASS_SYSCON
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/cpu.h>
+#include <asm/intel_regs.h>
+#include <asm/arch/adsp.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/rcb.h>
+
+enum pci_type_t {
+ LYNX_POINT,
+ WILDCAT_POINT,
+};
+
+struct broadwell_adsp_priv {
+ bool adsp_d3_pg_enable;
+ bool adsp_sram_pg_enable;
+ bool sio_acpi_mode;
+};
+
+static int broadwell_adsp_probe(struct udevice *dev)
+{
+ struct broadwell_adsp_priv *priv = dev_get_priv(dev);
+ enum pci_type_t type;
+ u32 bar0, bar1;
+ u32 tmp32;
+
+ /* Find BAR0 and BAR1 */
+ bar0 = dm_pci_read_bar32(dev, 0);
+ if (!bar0)
+ return -EINVAL;
+ bar1 = dm_pci_read_bar32(dev, 1);
+ if (!bar1)
+ return -EINVAL;
+
+ /*
+ * Set LTR value in DSP shim LTR control register to 3ms
+ * SNOOP_REQ[13]=1b SNOOP_SCALE[12:10]=100b (1ms) SNOOP_VAL[9:0]=3h
+ */
+ type = dev_get_driver_data(dev);
+ tmp32 = type == WILDCAT_POINT ? ADSP_SHIM_BASE_WPT : ADSP_SHIM_BASE_LPT;
+ writel(ADSP_SHIM_LTRC_VALUE, bar0 + tmp32);
+
+ /* Program VDRTCTL2 D19:F0:A8[31:0] = 0x00000fff */
+ dm_pci_write_config32(dev, ADSP_PCI_VDRTCTL2, ADSP_VDRTCTL2_VALUE);
+
+ /* Program ADSP IOBP VDLDAT1 to 0x040100 */
+ pch_iobp_write(ADSP_IOBP_VDLDAT1, ADSP_VDLDAT1_VALUE);
+
+ /* Set D3 Power Gating Enable in D19:F0:A0 based on PCH type */
+ dm_pci_read_config32(dev, ADSP_PCI_VDRTCTL0, &tmp32);
+ if (type == WILDCAT_POINT) {
+ if (priv->adsp_d3_pg_enable) {
+ tmp32 &= ~ADSP_VDRTCTL0_D3PGD_WPT;
+ if (priv->adsp_sram_pg_enable)
+ tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_WPT;
+ else
+ tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_WPT;
+ } else {
+ tmp32 |= ADSP_VDRTCTL0_D3PGD_WPT;
+ }
+ } else {
+ if (priv->adsp_d3_pg_enable) {
+ tmp32 &= ~ADSP_VDRTCTL0_D3PGD_LPT;
+ if (priv->adsp_sram_pg_enable)
+ tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_LPT;
+ else
+ tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_LPT;
+ } else {
+ tmp32 |= ADSP_VDRTCTL0_D3PGD_LPT;
+ }
+ }
+ dm_pci_write_config32(dev, ADSP_PCI_VDRTCTL0, tmp32);
+
+ /* Set PSF Snoop to SA, RCBA+0x3350[10]=1b */
+ setbits_le32(RCB_REG(0x3350), 1 << 10);
+
+ /* Set DSP IOBP PMCTL 0x1e0=0x3f */
+ pch_iobp_write(ADSP_IOBP_PMCTL, ADSP_PMCTL_VALUE);
+
+ if (priv->sio_acpi_mode) {
+ /* Configure for ACPI mode */
+ log_info("ADSP: Enable ACPI Mode IRQ3\n");
+
+ /* Set interrupt de-assert/assert opcode override to IRQ3 */
+ pch_iobp_write(ADSP_IOBP_VDLDAT2, ADSP_IOBP_ACPI_IRQ3);
+
+ /* Enable IRQ3 in RCBA */
+ setbits_le32(RCB_REG(ACPIIRQEN), ADSP_ACPI_IRQEN);
+
+ /* Set ACPI Interrupt Enable Bit */
+ pch_iobp_update(ADSP_IOBP_PCICFGCTL, ~ADSP_PCICFGCTL_SPCBAD,
+ ADSP_PCICFGCTL_ACPIIE);
+
+ /* Put ADSP in D3hot */
+ clrbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
+ } else {
+ log_info("ADSP: Enable PCI Mode IRQ23\n");
+
+ /* Configure for PCI mode */
+ dm_pci_write_config32(dev, PCI_INTERRUPT_LINE, ADSP_PCI_IRQ);
+
+ /* Clear ACPI Interrupt Enable Bit */
+ pch_iobp_update(ADSP_IOBP_PCICFGCTL,
+ ~(ADSP_PCICFGCTL_SPCBAD |
+ ADSP_PCICFGCTL_ACPIIE), 0);
+ }
+
+ return 0;
+}
+
+static int broadwell_adsp_ofdata_to_platdata(struct udevice *dev)
+{
+ struct broadwell_adsp_priv *priv = dev_get_priv(dev);
+
+ priv->adsp_d3_pg_enable = dev_read_bool(dev, "intel,adsp-d3-pg-enable");
+ priv->adsp_sram_pg_enable = dev_read_bool(dev,
+ "intel,adsp-sram-pg-enable");
+ priv->sio_acpi_mode = dev_read_bool(dev, "intel,sio-acpi-mode");
+
+ return 0;
+}
+
+static const struct udevice_id broadwell_adsp_ids[] = {
+ { .compatible = "intel,wildcatpoint-adsp", .data = WILDCAT_POINT },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_adsp_drv) = {
+ .name = "adsp",
+ .id = UCLASS_SYSCON,
+ .ofdata_to_platdata = broadwell_adsp_ofdata_to_platdata,
+ .of_match = broadwell_adsp_ids,
+ .bind = dm_scan_fdt_dev,
+ .probe = broadwell_adsp_probe,
+};
+
+static struct pci_device_id broadwell_adsp_supported[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_WILDCATPOINT_ADSP) },
+ { },
+};
+
+U_BOOT_PCI_DEVICE(broadwell_adsp_drv, broadwell_adsp_supported);
diff --git a/arch/x86/cpu/broadwell/pch.c b/arch/x86/cpu/broadwell/pch.c
index 82506ba..73d3d3b 100644
--- a/arch/x86/cpu/broadwell/pch.c
+++ b/arch/x86/cpu/broadwell/pch.c
@@ -20,7 +20,9 @@
#include <asm/arch/pch.h>
#include <asm/arch/pm.h>
#include <asm/arch/rcb.h>
+#include <asm/arch/serialio.h>
#include <asm/arch/spi.h>
+#include <dm/uclass-internal.h>
#define BIOS_CTRL 0xdc
@@ -456,6 +458,111 @@ static void systemagent_init(void)
cpu_set_power_limits(28);
}
+/* Enable LTR Auto Mode for D21:F1-F6 */
+static void serialio_d21_ltr(u32 bar0)
+{
+ /* 1. Program BAR0 + 808h[2] = 0b */
+ clrbits_le32(bar0 + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_LTR_MODE_MASK);
+
+ /* 2. Program BAR0 + 804h[1:0] = 00b */
+ clrbits_le32(bar0 + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
+
+ /* 3. Program BAR0 + 804h[1:0] = 11b */
+ setbits_le32(bar0 + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
+
+ /* 4. Program BAR0 + 814h[31:0] = 00000000h */
+ writel(0, bar0 + SIO_REG_AUTO_LTR);
+}
+
+/* Select I2C voltage of 1.8V or 3.3V */
+static void serialio_i2c_voltage_sel(u32 bar0, uint voltage)
+{
+ clrsetbits_le32(bar0 + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_VOLTAGE_MASK,
+ SIO_REG_PPR_GEN_VOLTAGE(voltage));
+}
+
+/* Put Serial IO D21:F0-F6 device into desired mode */
+static void serialio_d21_mode(int sio_index, int int_pin, bool acpi_mode)
+{
+ u32 portctrl = SIO_IOBP_PORTCTRL_PM_CAP_PRSNT;
+
+ /* Snoop select 1 */
+ portctrl |= SIO_IOBP_PORTCTRL_SNOOP_SELECT(1);
+
+ /* Set interrupt pin */
+ portctrl |= SIO_IOBP_PORTCTRL_INT_PIN(int_pin);
+
+ if (acpi_mode) {
+ /* Enable ACPI interrupt mode */
+ portctrl |= SIO_IOBP_PORTCTRL_ACPI_IRQ_EN;
+ }
+
+ pch_iobp_update(SIO_IOBP_PORTCTRLX(sio_index), 0, portctrl);
+}
+
+/* Init sequence to be run once, done as part of D21:F0 (SDMA) init */
+static void serialio_init_once(bool acpi_mode)
+{
+ if (acpi_mode) {
+ /* Enable ACPI IRQ for IRQ13, IRQ7, IRQ6, IRQ5 in RCBA */
+ setbits_le32(RCB_REG(ACPIIRQEN),
+ 1 << 13 | 1 << 7 | 1 << 6 | 1 << 5);
+ }
+
+ /* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b */
+ pch_iobp_update(SIO_IOBP_GPIODF, ~0x0000131f, 0x0000131f);
+
+ /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
+ pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
+}
+
+/**
+ * pch_serialio_init() - set up serial I/O devices
+ *
+ * @return 0 if OK, -ve on error
+ */
+static int pch_serialio_init(void)
+{
+ struct udevice *dev, *hda;
+ bool acpi_mode = true;
+ u32 bar0, bar1;
+ int ret;
+
+ ret = uclass_find_first_device(UCLASS_I2C, &dev);
+ if (ret)
+ return ret;
+ bar0 = dm_pci_read_bar32(dev, 0);
+ if (!bar0)
+ return -EINVAL;
+ bar1 = dm_pci_read_bar32(dev, 1);
+ if (!bar1)
+ return -EINVAL;
+
+ serialio_init_once(acpi_mode);
+ serialio_d21_mode(SIO_ID_SDMA, SIO_PIN_INTB, acpi_mode);
+
+ serialio_d21_ltr(bar0);
+ serialio_i2c_voltage_sel(bar0, 1); /* Select 1.8V always */
+ serialio_d21_mode(SIO_ID_I2C0, SIO_PIN_INTC, acpi_mode);
+ setbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
+
+ clrbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
+
+ setbits_le32(bar0 + SIO_REG_PPR_CLOCK, SIO_REG_PPR_CLOCK_EN);
+
+ /* Manually find the High-definition audio, to turn it off */
+ ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1b, 0), &hda);
+ if (ret)
+ return -ENOENT;
+ dm_pci_clrset_config8(hda, 0x43, 0, 0x6f);
+
+ /* Route I/O buffers to ADSP function */
+ dm_pci_clrset_config8(hda, 0x42, 0, 1 << 7 | 1 << 6);
+ log_debug("HDA disabled, I/O buffers routed to ADSP\n");
+
+ return 0;
+}
+
static int broadwell_pch_init(struct udevice *dev)
{
int ret;
@@ -482,6 +589,9 @@ static int broadwell_pch_init(struct udevice *dev)
return ret;
pch_pm_init(dev);
pch_cg_init(dev);
+ ret = pch_serialio_init();
+ if (ret)
+ return ret;
systemagent_init();
return 0;
diff --git a/arch/x86/cpu/broadwell/pinctrl_broadwell.c b/arch/x86/cpu/broadwell/pinctrl_broadwell.c
index 914ecfb..aa83abb 100644
--- a/arch/x86/cpu/broadwell/pinctrl_broadwell.c
+++ b/arch/x86/cpu/broadwell/pinctrl_broadwell.c
@@ -16,6 +16,7 @@
#include <asm/arch/gpio.h>
#include <dt-bindings/gpio/x86-gpio.h>
#include <dm/pinctrl.h>
+#include <dm/uclass-internal.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -214,7 +215,7 @@ static int broadwell_pinctrl_probe(struct udevice *dev)
u32 gpiobase;
int ret;
- ret = uclass_first_device(UCLASS_PCH, &pch);
+ ret = uclass_find_first_device(UCLASS_PCH, &pch);
if (ret)
return ret;
if (!pch)
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig
index 5f0e608..2f42393 100644
--- a/arch/x86/cpu/ivybridge/Kconfig
+++ b/arch/x86/cpu/ivybridge/Kconfig
@@ -21,6 +21,7 @@ config NORTHBRIDGE_INTEL_IVYBRIDGE
imply USB_EHCI_HCD
imply USB_XHCI_HCD
imply VIDEO_VESA
+ imply SOUND_IVYBRIDGE
if NORTHBRIDGE_INTEL_IVYBRIDGE
diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c
index a78bb02..ed9bce6 100644
--- a/arch/x86/cpu/ivybridge/bd82x6x.c
+++ b/arch/x86/cpu/ivybridge/bd82x6x.c
@@ -20,8 +20,12 @@
DECLARE_GLOBAL_DATA_PTR;
-#define GPIO_BASE 0x48
-#define BIOS_CTRL 0xdc
+#define GPIO_BASE 0x48
+#define BIOS_CTRL 0xdc
+
+#define RCBA_AUDIO_CONFIG 0x2030
+#define RCBA_AUDIO_CONFIG_HDA BIT(31)
+#define RCBA_AUDIO_CONFIG_MASK 0xfe
#ifndef CONFIG_HAVE_FSP
static int pch_revision_id = -1;
@@ -212,10 +216,29 @@ static int bd82x6x_get_gpio_base(struct udevice *dev, u32 *gbasep)
return 0;
}
+static int bd82x6x_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
+ int size)
+{
+ u32 rcba, val;
+
+ switch (req) {
+ case PCH_REQ_HDA_CONFIG:
+ dm_pci_read_config32(dev, PCH_RCBA, &rcba);
+ val = readl(rcba + RCBA_AUDIO_CONFIG);
+ if (!(val & RCBA_AUDIO_CONFIG_HDA))
+ return -ENOENT;
+
+ return val & RCBA_AUDIO_CONFIG_MASK;
+ default:
+ return -ENOSYS;
+ }
+}
+
static const struct pch_ops bd82x6x_pch_ops = {
.get_spi_base = bd82x6x_pch_get_spi_base,
.set_spi_protect = bd82x6x_set_spi_protect,
.get_gpio_base = bd82x6x_get_gpio_base,
+ .ioctl = bd82x6x_ioctl,
};
static const struct udevice_id bd82x6x_ids[] = {
diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c
index 39bab7b..a809b82 100644
--- a/arch/x86/cpu/ivybridge/northbridge.c
+++ b/arch/x86/cpu/ivybridge/northbridge.c
@@ -177,6 +177,35 @@ static void sandybridge_setup_northbridge_bars(struct udevice *dev)
dm_pci_write_config8(dev, PAM6, 0x33);
}
+/**
+ * sandybridge_init_iommu() - Set up IOMMU so that azalia can be used
+ *
+ * It is not obvious where these values come from. They may be undocumented.
+ */
+static void sandybridge_init_iommu(struct udevice *dev)
+{
+ u32 capid0_a;
+
+ dm_pci_read_config32(dev, 0xe4, &capid0_a);
+ if (capid0_a & (1 << 23)) {
+ log_debug("capid0_a not needed\n");
+ return;
+ }
+
+ /* setup BARs */
+ writel(IOMMU_BASE1 >> 32, MCHBAR_REG(0x5404));
+ writel(IOMMU_BASE1 | 1, MCHBAR_REG(0x5400));
+ writel(IOMMU_BASE2 >> 32, MCHBAR_REG(0x5414));
+ writel(IOMMU_BASE2 | 1, MCHBAR_REG(0x5410));
+
+ /* lock policies */
+ writel(0x80000000, IOMMU_BASE1 + 0xff0);
+
+ /* Enable azalia sound */
+ writel(0x20000000, IOMMU_BASE2 + 0xff0);
+ writel(0xa0000000, IOMMU_BASE2 + 0xff0);
+}
+
static int bd82x6x_northbridge_early_init(struct udevice *dev)
{
const int chipset_type = SANDYBRIDGE_MOBILE;
@@ -197,6 +226,9 @@ static int bd82x6x_northbridge_early_init(struct udevice *dev)
sandybridge_setup_northbridge_bars(dev);
+ /* Setup IOMMU BARs */
+ sandybridge_init_iommu(dev);
+
/* Device Enable */
dm_pci_write_config32(dev, DEVEN, DEVEN_HOST | DEVEN_IGD);
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
index f9f0979..c5653fe 100644
--- a/arch/x86/dts/chromebook_link.dts
+++ b/arch/x86/dts/chromebook_link.dts
@@ -1,6 +1,8 @@
/dts-v1/;
#include <dt-bindings/gpio/x86-gpio.h>
+#include <dt-bindings/sound/azalia.h>
+#include <pci_ids.h>
/include/ "skeleton.dtsi"
/include/ "keyboard.dtsi"
@@ -372,6 +374,32 @@
compatible = "ehci-pci";
};
+ hda@1b,0 {
+ reg = <0x0000d800 0 0 0 0>;
+ compatible = "intel,bd82x6x-hda";
+
+ /* These correspond to the Intel HDA specification */
+ beep-verbs = <
+ 0x00170500 /* power up codec */
+ 0x00270500 /* power up DAC */
+ 0x00b70500 /* power up speaker */
+ 0x00b70740 /* enable speaker out */
+ 0x00b78d00 /* enable EAPD pin */
+ 0x00b70c02 /* set EAPD pin */
+ 0x0143b013>; /* beep volume */
+
+ codecs {
+ creative_codec: creative-ca0132 {
+ vendor-id = <PCI_VENDOR_ID_CREATIVE>;
+ device-id = <PCI_DEVICE_ID_CREATIVE_CA01322>;
+ };
+ intel_hdmi: hdmi {
+ vendor-id = <PCI_VENDOR_ID_INTEL>;
+ device-id = <PCI_DEVICE_ID_INTEL_COUGARPOINT_HDMI>;
+ };
+ };
+ };
+
usb_0: usb@1d,0 {
reg = <0x0000e800 0 0 0 0>;
compatible = "ehci-pci";
@@ -492,3 +520,71 @@
};
};
+
+&creative_codec {
+ verbs = <
+ /**
+ * Malcolm Setup. These correspond to the Intel HDA
+ * specification.
+ */
+ 0x01570d09 0x01570c23 0x01570a01 0x01570df0
+ 0x01570efe 0x01570775 0x015707d3 0x01570709
+ 0x01570753 0x015707d4 0x015707ef 0x01570775
+ 0x015707d3 0x01570709 0x01570702 0x01570737
+ 0x01570778 0x01553cce 0x015575c9 0x01553dce
+ 0x0155b7c9 0x01570de8 0x01570efe 0x01570702
+ 0x01570768 0x01570762 0x01553ace 0x015546c9
+ 0x01553bce 0x0155e8c9 0x01570d49 0x01570c88
+ 0x01570d20 0x01570e19 0x01570700 0x01571a05
+ 0x01571b29 0x01571a04 0x01571b29 0x01570a01
+
+ /* Pin Widget Verb Table */
+
+ /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x144dc0c2 */
+ AZALIA_SUBVENDOR(0x0, 0x144dc0c2)
+
+ /*
+ * Pin Complex (NID 0x0B) Port-G Analog Unknown
+ * Speaker at Int N/A
+ */
+ AZALIA_PIN_CFG(0x0, 0x0b, 0x901700f0)
+
+ /* Pin Complex (NID 0x0C) N/C */
+ AZALIA_PIN_CFG(0x0, 0x0c, 0x70f000f0)
+
+ /* Pin Complex (NID 0x0D) N/C */
+ AZALIA_PIN_CFG(0x0, 0x0d, 0x70f000f0)
+
+ /* Pin Complex (NID 0x0E) N/C */
+ AZALIA_PIN_CFG(0x0, 0x0e, 0x70f000f0)
+
+ /* Pin Complex (NID 0x0F) N/C */
+ AZALIA_PIN_CFG(0x0, 0x0f, 0x70f000f0)
+
+ /* Pin Complex (NID 0x10) Port-D 1/8 Black HP Out at Ext Left */
+ AZALIA_PIN_CFG(0x0, 0x10, 0x032110f0)
+
+ /* Pin Complex (NID 0x11) Port-B Click Mic */
+ AZALIA_PIN_CFG(0x0, 0x11, 0x90a700f0)
+
+ /* Pin Complex (NID 0x12) Port-C Combo Jack Mic or D-Mic */
+ AZALIA_PIN_CFG(0x0, 0x12, 0x03a110f0)
+
+ /* Pin Complex (NID 0x13) What you hear */
+ AZALIA_PIN_CFG(0x0, 0x13, 0x90d600f0)>;
+};
+
+&intel_hdmi {
+ verbs = <
+ /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x80860101 */
+ AZALIA_SUBVENDOR(0x3, 0x80860101)
+
+ /* Pin Complex (NID 0x05) Digital Out at Int HDMI */
+ AZALIA_PIN_CFG(0x3, 0x05, 0x18560010)
+
+ /* Pin Complex (NID 0x06) Digital Out at Int HDMI */
+ AZALIA_PIN_CFG(0x3, 0x06, 0x18560020)
+
+ /* Pin Complex (NID 0x07) Digital Out at Int HDMI */
+ AZALIA_PIN_CFG(0x3, 0x07, 0x18560030)>;
+};
diff --git a/arch/x86/dts/chromebook_samus.dts b/arch/x86/dts/chromebook_samus.dts
index b58936b..ad687ce 100644
--- a/arch/x86/dts/chromebook_samus.dts
+++ b/arch/x86/dts/chromebook_samus.dts
@@ -494,10 +494,20 @@
intel,pre-graphics-delay = <200>;
};
- me@16,0 {
- reg = <0x0000b000 0 0 0 0>;
- compatible = "intel,me";
- u-boot,dm-pre-reloc;
+ adsp@13,0 {
+ reg = <0x00009800 0 0 0 0>;
+ compatible = "intel,wildcatpoint-adsp";
+ intel,adsp-d3-pg-enable = <0>;
+ intel,adsp-sram-pg-enable = <0>;
+ intel,sio-acpi-mode;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2s: shim {
+ compatible = "intel,broadwell-i2s";
+ #sound-dai-cells = <1>;
+ reg = <0xfb000 0xfc000 0xfd000>;
+ };
};
usb_1: usb@14,0 {
@@ -505,6 +515,25 @@
compatible = "xhci-pci";
};
+ i2c0: i2c@15,1 {
+ reg = <0x0000a900 0 0 0 0>;
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rt5677: rt5677@2c {
+ compatible = "realtek,rt5677";
+ #sound-dai-cells = <1>;
+ reg = <0x2c>;
+ };
+ };
+
+ me@16,0 {
+ reg = <0x0000b000 0 0 0 0>;
+ compatible = "intel,me";
+ u-boot,dm-pre-reloc;
+ };
+
usb_0: usb@1d,0 {
status = "disabled";
reg = <0x0000e800 0 0 0 0>;
@@ -626,4 +655,16 @@
};
};
+ sound {
+ compatible = "google,samus-sound";
+ codec-enable-gpio = <&gpio_b 11 GPIO_ACTIVE_HIGH>;
+ cpu {
+ sound-dai = <&i2s 0>;
+ };
+
+ codec {
+ sound-dai = <&rt5677 0>;
+ };
+ };
+
};
diff --git a/arch/x86/include/asm/arch-broadwell/adsp.h b/arch/x86/include/asm/arch-broadwell/adsp.h
new file mode 100644
index 0000000..eb825ce
--- /dev/null
+++ b/arch/x86/include/asm/arch-broadwell/adsp.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Support for Intel Application Digital Signal Processor
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot file of the same name
+ */
+
+#ifndef __ASM_ARCH_BROADWELL_ADSP_H
+#define __ASM_ARCH_BROADWELL_ADSP_H
+
+#define ADSP_PCI_IRQ 23
+#define ADSP_ACPI_IRQ 3
+#define ADSP_ACPI_IRQEN BIT(3)
+
+#define ADSP_SHIM_BASE_LPT 0xe7000
+#define ADSP_SHIM_BASE_WPT 0xfb000
+#define ADSP_SHIM_LTRC 0xe0
+#define ADSP_SHIM_LTRC_VALUE 0x3003
+#define ADSP_SHIM_IMC 0x28
+#define ADSP_SHIM_IPCD 0x40
+
+#define ADSP_PCI_VDRTCTL0 0xa0
+#define ADSP_VDRTCTL0_D3PGD_LPT BIT(1)
+#define ADSP_VDRTCTL0_D3PGD_WPT BIT(0)
+#define ADSP_VDRTCTL0_D3SRAMPGD_LPT BIT(2)
+#define ADSP_VDRTCTL0_D3SRAMPGD_WPT BIT(1)
+#define ADSP_PCI_VDRTCTL1 0xa4
+#define ADSP_PCI_VDRTCTL2 0xa8
+#define ADSP_VDRTCTL2_VALUE 0x00000fff
+
+#define ADSP_IOBP_VDLDAT1 0xd7000624
+#define ADSP_VDLDAT1_VALUE 0x00040100
+#define ADSP_IOBP_VDLDAT2 0xd7000628
+#define ADSP_IOBP_ACPI_IRQ3 0xd9d8
+#define ADSP_IOBP_ACPI_IRQ3I 0xd8d9
+#define ADSP_IOBP_ACPI_IRQ4 0xdbda
+#define ADSP_IOBP_PMCTL 0xd70001e0
+#define ADSP_PMCTL_VALUE 0x3f
+#define ADSP_IOBP_PCICFGCTL 0xd7000500
+#define ADSP_PCICFGCTL_PCICD BIT(0)
+#define ADSP_PCICFGCTL_ACPIIE BIT(1)
+#define ADSP_PCICFGCTL_SPCBAD BIT(7)
+
+#endif /* __ASM_ARCH_BROADWELL_ADSP_H */
diff --git a/arch/x86/include/asm/arch-broadwell/pch.h b/arch/x86/include/asm/arch-broadwell/pch.h
index 23ccd68..23153a0 100644
--- a/arch/x86/include/asm/arch-broadwell/pch.h
+++ b/arch/x86/include/asm/arch-broadwell/pch.h
@@ -109,6 +109,9 @@
#define SATA_DTLE_EDGE_SHIFT 16
/* Power Management */
+#define PCH_PCS 0x84
+#define PCH_PCS_PS_D3HOT 3
+
#define GEN_PMCON_1 0xa0
#define SMI_LOCK (1 << 4)
#define GEN_PMCON_2 0xa2
diff --git a/arch/x86/include/asm/arch-broadwell/rcb.h b/arch/x86/include/asm/arch-broadwell/rcb.h
index e7340c1..b7ce874 100644
--- a/arch/x86/include/asm/arch-broadwell/rcb.h
+++ b/arch/x86/include/asm/arch-broadwell/rcb.h
@@ -6,6 +6,8 @@
#ifndef __asm_arch_rcba_h
#define __asm_arch_rcba_h
+#define ACPIIRQEN 0x31e0 /* 32bit */
+
#define PMSYNC_CONFIG 0x33c4 /* 32bit */
#define PMSYNC_CONFIG2 0x33cc /* 32bit */
diff --git a/arch/x86/include/asm/arch-broadwell/serialio.h b/arch/x86/include/asm/arch-broadwell/serialio.h
new file mode 100644
index 0000000..5e98eaf
--- /dev/null
+++ b/arch/x86/include/asm/arch-broadwell/serialio.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Serial IO defintiions (taken from coreboot file of same name)
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ARCH_BROADWELL_SERIALIO_H_
+#define __ARCH_BROADWELL_SERIALIO_H_
+
+/* Serial IO IOBP Registers */
+#define SIO_IOBP_PORTCTRL0 0xcb000000 /* SDIO D23:F0 */
+#define SIO_IOBP_PORTCTRL0_ACPI_IRQ_EN BIT(5)
+#define SIO_IOBP_PORTCTRL0_PCI_CONF_DIS BIT(4)
+#define SIO_IOBP_PORTCTRL1 0xcb000014 /* SDIO D23:F0 */
+#define SIO_IOBP_PORTCTRL1_SNOOP_SELECT(x) (((x) & 3) << 13)
+#define SIO_IOBP_GPIODF 0xcb000154
+#define SIO_IOBP_GPIODF_SDIO_IDLE_DET_EN BIT(4)
+#define SIO_IOBP_GPIODF_DMA_IDLE_DET_EN BIT(3)
+#define SIO_IOBP_GPIODF_UART_IDLE_DET_EN BIT(2)
+#define SIO_IOBP_GPIODF_I2C_IDLE_DET_EN BIT(1)
+#define SIO_IOBP_GPIODF_SPI_IDLE_DET_EN BIT(0)
+#define SIO_IOBP_GPIODF_UART0_BYTE_ACCESS BIT(10)
+#define SIO_IOBP_GPIODF_UART1_BYTE_ACCESS BIT(11)
+#define SIO_IOBP_PORTCTRL2 0xcb000240 /* DMA D21:F0 */
+#define SIO_IOBP_PORTCTRL3 0xcb000248 /* I2C0 D21:F1 */
+#define SIO_IOBP_PORTCTRL4 0xcb000250 /* I2C1 D21:F2 */
+#define SIO_IOBP_PORTCTRL5 0xcb000258 /* SPI0 D21:F3 */
+#define SIO_IOBP_PORTCTRL6 0xcb000260 /* SPI1 D21:F4 */
+#define SIO_IOBP_PORTCTRL7 0xcb000268 /* UART0 D21:F5 */
+#define SIO_IOBP_PORTCTRL8 0xcb000270 /* UART1 D21:F6 */
+#define SIO_IOBP_PORTCTRLX(x) (0xcb000240 + ((x) * 8))
+/* PORTCTRL 2-8 have the same layout */
+#define SIO_IOBP_PORTCTRL_ACPI_IRQ_EN BIT(21)
+#define SIO_IOBP_PORTCTRL_PCI_CONF_DIS BIT(20)
+#define SIO_IOBP_PORTCTRL_SNOOP_SELECT(x) (((x) & 3) << 18)
+#define SIO_IOBP_PORTCTRL_INT_PIN(x) (((x) & 0xf) << 2)
+#define SIO_IOBP_PORTCTRL_PM_CAP_PRSNT BIT(1)
+#define SIO_IOBP_FUNCDIS0 0xce00aa07 /* DMA D21:F0 */
+#define SIO_IOBP_FUNCDIS1 0xce00aa47 /* I2C0 D21:F1 */
+#define SIO_IOBP_FUNCDIS2 0xce00aa87 /* I2C1 D21:F2 */
+#define SIO_IOBP_FUNCDIS3 0xce00aac7 /* SPI0 D21:F3 */
+#define SIO_IOBP_FUNCDIS4 0xce00ab07 /* SPI1 D21:F4 */
+#define SIO_IOBP_FUNCDIS5 0xce00ab47 /* UART0 D21:F5 */
+#define SIO_IOBP_FUNCDIS6 0xce00ab87 /* UART1 D21:F6 */
+#define SIO_IOBP_FUNCDIS7 0xce00ae07 /* SDIO D23:F0 */
+#define SIO_IOBP_FUNCDIS_DIS BIT(8)
+
+/* Serial IO Devices */
+#define SIO_ID_SDMA 0 /* D21:F0 */
+#define SIO_ID_I2C0 1 /* D21:F1 */
+#define SIO_ID_I2C1 2 /* D21:F2 */
+#define SIO_ID_SPI0 3 /* D21:F3 */
+#define SIO_ID_SPI1 4 /* D21:F4 */
+#define SIO_ID_UART0 5 /* D21:F5 */
+#define SIO_ID_UART1 6 /* D21:F6 */
+#define SIO_ID_SDIO 7 /* D23:F0 */
+
+#define SIO_REG_PPR_CLOCK 0x800
+#define SIO_REG_PPR_CLOCK_EN BIT(0)
+#define SIO_REG_PPR_CLOCK_UPDATE BIT(31)
+#define SIO_REG_PPR_CLOCK_M_DIV 0x25a
+#define SIO_REG_PPR_CLOCK_N_DIV 0x7fff
+#define SIO_REG_PPR_RST 0x804
+#define SIO_REG_PPR_RST_ASSERT 0x3
+#define SIO_REG_PPR_GEN 0x808
+#define SIO_REG_PPR_GEN_LTR_MODE_MASK BIT(2)
+#define SIO_REG_PPR_GEN_VOLTAGE_MASK BIT(3)
+#define SIO_REG_PPR_GEN_VOLTAGE(x) ((x & 1) << 3)
+#define SIO_REG_AUTO_LTR 0x814
+
+#define SIO_REG_SDIO_PPR_GEN 0x1008
+#define SIO_REG_SDIO_PPR_SW_LTR 0x1010
+#define SIO_REG_SDIO_PPR_CMD12 0x3c
+#define SIO_REG_SDIO_PPR_CMD12_B30 BIT(30)
+
+#define SIO_PIN_INTA 1 /* IRQ5 in ACPI mode */
+#define SIO_PIN_INTB 2 /* IRQ6 in ACPI mode */
+#define SIO_PIN_INTC 3 /* IRQ7 in ACPI mode */
+#define SIO_PIN_INTD 4 /* IRQ13 in ACPI mode */
+
+#endif /* __ARCH_BROADWELL_SERIALIO_H_ */
diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
index a96c951..a3a507f 100644
--- a/arch/x86/include/asm/arch-ivybridge/sandybridge.h
+++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
@@ -43,6 +43,9 @@
/* 4 KB per PCIe device */
#define DEFAULT_PCIEXBAR CONFIG_PCIE_ECAM_BASE
+#define IOMMU_BASE1 0xfed90000ULL
+#define IOMMU_BASE2 0xfed91000ULL
+
/* Device 0:0.0 PCI configuration space (Host Bridge) */
#define EPBAR 0x40
#define MCHBAR 0x48
diff --git a/arch/x86/include/asm/i8254.h b/arch/x86/include/asm/i8254.h
index 65c9761..d769daf 100644
--- a/arch/x86/include/asm/i8254.h
+++ b/arch/x86/include/asm/i8254.h
@@ -35,4 +35,22 @@
/* The clock frequency of the i8253/i8254 PIT */
#define PIT_TICK_RATE 1193182
+/**
+ * i8254_enable_beep() - Start a beep using the PCAT timer
+ *
+ * This starts beeping using the legacy i8254 timer. The beep may be silenced
+ * after a delay with i8254_disable_beep().
+ *
+ * @frequency_hz: Frequency of beep in Hz
+ * @return 0 if OK, -EINVAL if frequency_hz is 0
+ */
+int i8254_enable_beep(uint frequency_hz);
+
+/**
+ * i8254_disable_beep() - Disable the bepper
+ *
+ * This stops any existing beep
+ */
+void i8254_disable_beep(void);
+
#endif /* _ASMI386_I8954_H_ */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 81def0a..cf6c33c 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -57,19 +57,19 @@
* memory location directly.
*/
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
-#define readq(addr) (*(volatile unsigned long long *) (addr))
+#define readb(addr) (*(volatile u8 *)(uintptr_t)(addr))
+#define readw(addr) (*(volatile u16 *)(uintptr_t)(addr))
+#define readl(addr) (*(volatile u32 *)(uintptr_t)(addr))
+#define readq(addr) (*(volatile u64 *)(uintptr_t)(addr))
#define __raw_readb readb
#define __raw_readw readw
#define __raw_readl readl
#define __raw_readq readq
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
-#define writeq(b,addr) (*(volatile unsigned long long *) (addr) = (b))
+#define writeb(b, addr) (*(volatile u8 *)(addr) = (b))
+#define writew(b, addr) (*(volatile u16 *)(addr) = (b))
+#define writel(b, addr) (*(volatile u32 *)(addr) = (b))
+#define writeq(b, addr) (*(volatile u64 *)(addr) = (b))
#define __raw_writeb writeb
#define __raw_writew writew
#define __raw_writel writel
diff --git a/arch/x86/lib/i8254.c b/arch/x86/lib/i8254.c
index 1f10124..d022795 100644
--- a/arch/x86/lib/i8254.c
+++ b/arch/x86/lib/i8254.c
@@ -8,8 +8,20 @@
#include <asm/io.h>
#include <asm/i8254.h>
-#define TIMER1_VALUE 18 /* 15.6us */
-#define TIMER2_VALUE 0x0a8e /* 440Hz */
+#define TIMER1_VALUE 18 /* 15.6us */
+#define BEEP_FREQUENCY_HZ 440
+#define SYSCTL_PORTB 0x61
+#define PORTB_BEEP_ENABLE 0x3
+
+static void i8254_set_beep_freq(uint frequency_hz)
+{
+ uint countdown;
+
+ countdown = PIT_TICK_RATE / frequency_hz;
+
+ outb(countdown & 0xff, PIT_BASE + PIT_T2);
+ outb((countdown >> 8) & 0xff, PIT_BASE + PIT_T2);
+}
int i8254_init(void)
{
@@ -29,8 +41,23 @@ int i8254_init(void)
*/
outb(PIT_CMD_CTR2 | PIT_CMD_BOTH | PIT_CMD_MODE3,
PIT_BASE + PIT_COMMAND);
- outb(TIMER2_VALUE & 0xff, PIT_BASE + PIT_T2);
- outb(TIMER2_VALUE >> 8, PIT_BASE + PIT_T2);
+ i8254_set_beep_freq(BEEP_FREQUENCY_HZ);
+
+ return 0;
+}
+
+int i8254_enable_beep(uint frequency_hz)
+{
+ if (!frequency_hz)
+ return -EINVAL;
+
+ i8254_set_beep_freq(frequency_hz);
+ setio_8(SYSCTL_PORTB, PORTB_BEEP_ENABLE);
return 0;
}
+
+void i8254_disable_beep(void)
+{
+ clrio_8(SYSCTL_PORTB, PORTB_BEEP_ENABLE);
+}
diff --git a/cmd/gpio.c b/cmd/gpio.c
index 4ac1f1e..53366f3 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -34,7 +34,7 @@ enum {
};
static void gpio_get_description(struct udevice *dev, const char *bank_name,
- int offset, int *flagsp)
+ int offset, int *flagsp, bool show_all)
{
char buf[80];
int ret;
@@ -42,7 +42,7 @@ static void gpio_get_description(struct udevice *dev, const char *bank_name,
ret = gpio_get_function(dev, offset, NULL);
if (ret < 0)
goto err;
- if (!(*flagsp & FLAG_SHOW_ALL) && ret == GPIOF_UNUSED)
+ if (!show_all && !(*flagsp & FLAG_SHOW_ALL) && ret == GPIOF_UNUSED)
return;
if ((*flagsp & FLAG_SHOW_BANK) && bank_name) {
if (*flagsp & FLAG_SHOW_NEWLINE) {
@@ -90,7 +90,7 @@ static int do_gpio_status(bool all, const char *gpio_name)
banklen = bank_name ? strlen(bank_name) : 0;
if (!gpio_name || !bank_name ||
- !strncmp(gpio_name, bank_name, banklen)) {
+ !strncasecmp(gpio_name, bank_name, banklen)) {
const char *p = NULL;
int offset;
@@ -98,11 +98,11 @@ static int do_gpio_status(bool all, const char *gpio_name)
if (gpio_name && *p) {
offset = simple_strtoul(p, NULL, 10);
gpio_get_description(dev, bank_name, offset,
- &flags);
+ &flags, true);
} else {
for (offset = 0; offset < num_bits; offset++) {
gpio_get_description(dev, bank_name,
- offset, &flags);
+ offset, &flags, false);
}
}
}
diff --git a/common/Kconfig b/common/Kconfig
index 0a14bde..e100c22 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -286,14 +286,16 @@ config LOGLEVEL
All Messages with a loglevel smaller than the console loglevel will
be compiled in. The loglevels are defined as follows:
- 0 (KERN_EMERG) system is unusable
- 1 (KERN_ALERT) action must be taken immediately
- 2 (KERN_CRIT) critical conditions
- 3 (KERN_ERR) error conditions
- 4 (KERN_WARNING) warning conditions
- 5 (KERN_NOTICE) normal but significant condition
- 6 (KERN_INFO) informational
- 7 (KERN_DEBUG) debug-level messages
+ 0 - emergency
+ 1 - alert
+ 2 - critical
+ 3 - error
+ 4 - warning
+ 5 - note
+ 6 - info
+ 7 - debug
+ 8 - debug content
+ 9 - debug hardware I/O
config SPL_LOGLEVEL
int
@@ -482,14 +484,16 @@ config LOG_MAX_LEVEL
higher than this will be ignored. If possible log statements below
this level will be discarded at build time. Levels:
- 0 - panic
- 1 - critical
- 2 - error
- 3 - warning
- 4 - note
- 5 - info
- 6 - detail
+ 0 - emergency
+ 1 - alert
+ 2 - critical
+ 3 - error
+ 4 - warning
+ 5 - note
+ 6 - info
7 - debug
+ 8 - debug content
+ 9 - debug hardware I/O
config SPL_LOG_MAX_LEVEL
int "Maximum log level to record in SPL"
@@ -500,14 +504,16 @@ config SPL_LOG_MAX_LEVEL
higher than this will be ignored. If possible log statements below
this level will be discarded at build time. Levels:
- 0 - panic
- 1 - critical
- 2 - error
- 3 - warning
- 4 - note
- 5 - info
- 6 - detail
+ 0 - emergency
+ 1 - alert
+ 2 - critical
+ 3 - error
+ 4 - warning
+ 5 - note
+ 6 - info
7 - debug
+ 8 - debug content
+ 9 - debug hardware I/O
config TPL_LOG_MAX_LEVEL
int "Maximum log level to record in TPL"
@@ -518,14 +524,36 @@ config TPL_LOG_MAX_LEVEL
higher than this will be ignored. If possible log statements below
this level will be discarded at build time. Levels:
- 0 - panic
- 1 - critical
- 2 - error
- 3 - warning
- 4 - note
- 5 - info
- 6 - detail
+ 0 - emergency
+ 1 - alert
+ 2 - critical
+ 3 - error
+ 4 - warning
+ 5 - note
+ 6 - info
+ 7 - debug
+ 8 - debug content
+ 9 - debug hardware I/O
+
+config LOG_DEFAULT_LEVEL
+ int "Default logging level to display"
+ default 6
+ help
+ This is the default logging level set when U-Boot starts. It can
+ be adjusted later using the 'log level' command. Note that setting
+ this to a value abnove LOG_MAX_LEVEL will be ineffective, since the
+ higher levels are not compiled in to U-Boot.
+
+ 0 - emergency
+ 1 - alert
+ 2 - critical
+ 3 - error
+ 4 - warning
+ 5 - note
+ 6 - info
7 - debug
+ 8 - debug content
+ 9 - debug hardware I/O
config LOG_CONSOLE
bool "Allow log output to the console"
diff --git a/common/log.c b/common/log.c
index ec14644..ffb3cd6 100644
--- a/common/log.c
+++ b/common/log.c
@@ -316,7 +316,7 @@ int log_init(void)
}
gd->flags |= GD_FLG_LOG_READY;
if (!gd->default_log_level)
- gd->default_log_level = LOGL_INFO;
+ gd->default_log_level = CONFIG_LOG_DEFAULT_LEVEL;
gd->log_fmt = LOGF_DEFAULT;
return 0;
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig
index b90aae6..6058dfa 100644
--- a/configs/chromebook_link_defconfig
+++ b/configs/chromebook_link_defconfig
@@ -1,6 +1,6 @@
CONFIG_X86=y
CONFIG_SYS_TEXT_BASE=0xFFF00000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x2400
CONFIG_DEBUG_UART_BOARD_INIT=y
CONFIG_DEBUG_UART_BASE=0x3f8
CONFIG_DEBUG_UART_CLOCK=1843200
@@ -33,6 +33,7 @@ CONFIG_CMD_DHCP=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
+CONFIG_CMD_SOUND=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_CMD_TPM=y
CONFIG_CMD_TPM_TEST=y
@@ -53,6 +54,7 @@ CONFIG_SYS_I2C_INTEL=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_LPC=y
CONFIG_SYS_NS16550=y
+CONFIG_SOUND=y
CONFIG_SPI=y
CONFIG_TPM_TIS_LPC=y
CONFIG_USB_STORAGE=y
@@ -63,3 +65,4 @@ CONFIG_VIDEO_IVYBRIDGE_IGD=y
CONFIG_CONSOLE_SCROLL_LINES=5
CONFIG_CMD_DHRYSTONE=y
CONFIG_TPM=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/chromebook_samus_defconfig b/configs/chromebook_samus_defconfig
index e5483c5..7e2453f 100644
--- a/configs/chromebook_samus_defconfig
+++ b/configs/chromebook_samus_defconfig
@@ -1,6 +1,6 @@
CONFIG_X86=y
CONFIG_SYS_TEXT_BASE=0xFFE00000
-CONFIG_SYS_MALLOC_F_LEN=0x1a00
+CONFIG_SYS_MALLOC_F_LEN=0x1c00
CONFIG_DEBUG_UART_BOARD_INIT=y
CONFIG_DEBUG_UART_BASE=0x3f8
CONFIG_DEBUG_UART_CLOCK=1843200
@@ -17,6 +17,7 @@ CONFIG_BOOTSTAGE_REPORT=y
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_LOG_DEFAULT_LEVEL=7
CONFIG_MISC_INIT_R=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_LAST_STAGE_INIT=y
@@ -24,7 +25,9 @@ CONFIG_HUSH_PARSER=y
CONFIG_CMD_CPU=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
CONFIG_CMD_PART=y
+CONFIG_CMD_SATA=y
CONFIG_CMD_SF=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
@@ -33,6 +36,7 @@ CONFIG_CMD_DHCP=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
+CONFIG_CMD_SOUND=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_CMD_TPM=y
CONFIG_CMD_TPM_TEST=y
@@ -48,9 +52,14 @@ CONFIG_DEFAULT_DEVICE_TREE="chromebook_samus"
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_CPU=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_LPC=y
CONFIG_SYS_NS16550=y
+CONFIG_SOUND=y
+CONFIG_SOUND_I8254=y
+CONFIG_SOUND_RT5677=y
CONFIG_SPI=y
CONFIG_TPM_TIS_LPC=y
CONFIG_USB_STORAGE=y
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig
index ad0b35f..2795fe9 100644
--- a/configs/coreboot_defconfig
+++ b/configs/coreboot_defconfig
@@ -23,6 +23,7 @@ CONFIG_CMD_DHCP=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
+CONFIG_CMD_SOUND=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
@@ -35,4 +36,6 @@ CONFIG_DEFAULT_DEVICE_TREE="coreboot"
CONFIG_REGMAP=y
CONFIG_SYSCON=y
# CONFIG_PCI_PNP is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_I8254=y
CONFIG_CONSOLE_SCROLL_LINES=5
diff --git a/doc/README.log b/doc/README.log
index 2ee1b75..19856d4 100644
--- a/doc/README.log
+++ b/doc/README.log
@@ -69,6 +69,47 @@ If CONFIG_LOG is not set, then no logging will be available.
The above have SPL versions also, e.g. CONFIG_SPL_MAX_LOG_LEVEL.
+Temporary logging within a single file
+--------------------------------------
+
+Sometimes it is useful to turn on logging just in one file. You can use this:
+
+ #define LOG_DEBUG
+
+to enable building in of all logging statements in a single file. Put it at
+the top of the file, before any #includes.
+
+To actually get U-Boot to output this you need to also set the default logging
+level - e.g. set CONFIG_LOG_DEFAULT_LEVEL to 7 (LOGL_DEBUG) or more. Otherwise
+debug output is suppressed and will not be generated.
+
+
+Convenience functions
+---------------------
+
+A number of convenience functions are available to shorten the code needed
+for logging:
+
+ log_err(_fmt...)
+ log_warning(_fmt...)
+ log_notice(_fmt...)
+ log_info(_fmt...)
+ log_debug(_fmt...)
+ log_content(_fmt...)
+ log_io(_fmt...)
+
+With these the log level is implicit in the name. The category is set by
+LOG_CATEGORY, which you can only define once per file, above all #includes:
+
+ #define LOG_CATEGORY LOGC_ALLOC
+
+or
+
+ #define LOG_CATEGORY UCLASS_SPI
+
+Remember that all uclasses IDs are log categories too.
+
+
Log commands
------------
@@ -187,16 +228,6 @@ Convenience functions to support setting the category:
log_core(level, format_string, ...) - category LOGC_CORE
log_dt(level, format_string, ...) - category LOGC_DT
-Convenience functions to support a category defined for a single file, for
-example:
-
- #define LOG_CATEGORY UCLASS_USB
-
-all of these can use LOG_CATEGORY as the category, and a log level
-corresponding to the function name:
-
- logc(level, format_string, ...)
-
More logging destinations:
device - goes to a device (e.g. serial)
diff --git a/doc/device-tree-bindings/sound/intel-hda.txt b/doc/device-tree-bindings/sound/intel-hda.txt
new file mode 100644
index 0000000..fb2ce55
--- /dev/null
+++ b/doc/device-tree-bindings/sound/intel-hda.txt
@@ -0,0 +1,25 @@
+* Intel High-definition Audio
+
+Configuration is set using 'verbs' which are blocks of 16 bytes of data each
+with a different purpose, a little like a simple instruction set.
+
+Top-level node
+--------------
+
+Required properties:
+- compatible: "intel,hd-audio"
+- beep-verbs: list of verbs to send for a beep
+
+Optional properties
+- intel,beep-nid: Node ID to use for beep (will be detected if not provided)
+
+Required subnodes:
+- codecs: Contains a list of codec nodes
+
+
+* Codec nodes
+
+Required properties:
+- vendor-id: 16-bit vendor ID for audio codec
+- device-id: 16-bit device ID for audio codec
+- verbs: List of verbs, each 4 cells in length
diff --git a/drivers/Kconfig b/drivers/Kconfig
index e9fbadd..f24351a 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -64,6 +64,8 @@ source "drivers/nvme/Kconfig"
source "drivers/pci/Kconfig"
+source "drivers/pch/Kconfig"
+
source "drivers/pcmcia/Kconfig"
source "drivers/phy/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index eca023a..a7bba3e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -86,7 +86,8 @@ obj-y += misc/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_NVME) += nvme/
obj-y += pcmcia/
-obj-$(CONFIG_X86) += pch/
+obj-y += dfu/
+obj-$(CONFIG_PCH) += pch/
obj-y += phy/allwinner/
obj-y += phy/marvell/
obj-y += rtc/
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index 3cf9dd9..afac6d6 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -37,6 +37,10 @@ static int syscon_pre_probe(struct udevice *dev)
{
struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
+ /* Special case for PCI devices, which don't have a regmap */
+ if (device_get_uclass_id(dev->parent) == UCLASS_PCI)
+ return 0;
+
/*
* With OF_PLATDATA we really have no way of knowing the format of
* the device-specific platform data. So we assume that it starts with
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index dbc3326..63e4082 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -38,14 +38,16 @@ struct dw_i2c {
};
#ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
-static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
+static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
{
u32 ena = enable ? IC_ENABLE_0B : 0;
writel(ena, &i2c_base->ic_enable);
+
+ return 0;
}
#else
-static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
+static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
{
u32 ena = enable ? IC_ENABLE_0B : 0;
int timeout = 100;
@@ -53,7 +55,7 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
do {
writel(ena, &i2c_base->ic_enable);
if ((readl(&i2c_base->ic_enable_status) & IC_ENABLE_0B) == ena)
- return;
+ return 0;
/*
* Wait 10 times the signaling period of the highest I2C
@@ -62,8 +64,9 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
*/
udelay(25);
} while (timeout--);
-
printf("timeout in %sabling I2C adapter\n", enable ? "en" : "dis");
+
+ return -ETIMEDOUT;
}
#endif
@@ -370,10 +373,14 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr,
*
* Initialization function.
*/
-static void __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
+static int __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
{
+ int ret;
+
/* Disable i2c */
- dw_i2c_enable(i2c_base, false);
+ ret = dw_i2c_enable(i2c_base, false);
+ if (ret)
+ return ret;
writel(IC_CON_SD | IC_CON_RE | IC_CON_SPD_FS | IC_CON_MM,
&i2c_base->ic_con);
@@ -386,7 +393,11 @@ static void __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
#endif
/* Enable i2c */
- dw_i2c_enable(i2c_base, true);
+ ret = dw_i2c_enable(i2c_base, true);
+ if (ret)
+ return ret;
+
+ return 0;
}
#ifndef CONFIG_DM_I2C
@@ -558,9 +569,7 @@ static int designware_i2c_probe(struct udevice *bus)
if (&priv->reset_ctl)
reset_deassert(&priv->reset_ctl);
- __dw_i2c_init(priv->regs, 0, 0);
-
- return 0;
+ return __dw_i2c_init(priv->regs, 0, 0);
}
static int designware_i2c_bind(struct udevice *dev)
diff --git a/drivers/pch/Kconfig b/drivers/pch/Kconfig
new file mode 100644
index 0000000..18f006d
--- /dev/null
+++ b/drivers/pch/Kconfig
@@ -0,0 +1,9 @@
+config PCH
+ bool "Enable Platform-controller Hub (PCH) support"
+ depends on X86 || SANDBOX
+ help
+ Most x86 chips include a PCH which is responsible for handling
+ parts of the system not handled by that CPU. It supersedes the
+ northbridge / southbridge architecture that was previously used. The
+ PCH allows for higher performance since the memory functions are
+ handled in the CPU.
diff --git a/drivers/pch/Makefile b/drivers/pch/Makefile
index 696cdff..8ea6b78 100644
--- a/drivers/pch/Makefile
+++ b/drivers/pch/Makefile
@@ -3,3 +3,4 @@
obj-y += pch-uclass.o
obj-y += pch7.o
obj-y += pch9.o
+obj-$(CONFIG_SANDBOX) += sandbox_pch.o
diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c
index 831b283..caf8b72 100644
--- a/drivers/pch/pch-uclass.c
+++ b/drivers/pch/pch-uclass.c
@@ -51,6 +51,16 @@ int pch_get_io_base(struct udevice *dev, u32 *iobasep)
return ops->get_io_base(dev, iobasep);
}
+int pch_ioctl(struct udevice *dev, ulong req, void *data, int size)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ if (!ops->ioctl)
+ return -ENOSYS;
+
+ return ops->ioctl(dev, req, data, size);
+}
+
UCLASS_DRIVER(pch) = {
.id = UCLASS_PCH,
.name = "pch",
diff --git a/drivers/pch/sandbox_pch.c b/drivers/pch/sandbox_pch.c
new file mode 100644
index 0000000..76f5525
--- /dev/null
+++ b/drivers/pch/sandbox_pch.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pch.h>
+
+struct sandbox_pch_priv {
+ bool protect;
+};
+
+int sandbox_get_pch_spi_protect(struct udevice *dev)
+{
+ struct sandbox_pch_priv *priv = dev_get_priv(dev);
+
+ return priv->protect;
+}
+
+static int sandbox_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
+{
+ *sbasep = 0x10;
+
+ return 0;
+}
+
+static int sandbox_pch_set_spi_protect(struct udevice *dev, bool protect)
+{
+ struct sandbox_pch_priv *priv = dev_get_priv(dev);
+
+ priv->protect = protect;
+
+ return 0;
+}
+
+static int sandbox_pch_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ *gbasep = 0x20;
+
+ return 0;
+}
+
+static int sandbox_pch_get_io_base(struct udevice *dev, u32 *iobasep)
+{
+ *iobasep = 0x30;
+
+ return 0;
+}
+
+int sandbox_pch_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
+ int size)
+{
+ switch (req) {
+ case PCH_REQ_TEST1:
+ return -ENOSYS;
+ case PCH_REQ_TEST2:
+ return *(char *)data;
+ case PCH_REQ_TEST3:
+ *(char *)data = 'x';
+ return 1;
+ default:
+ return -ENOSYS;
+ }
+}
+
+static const struct pch_ops sandbox_pch_ops = {
+ .get_spi_base = sandbox_pch_get_spi_base,
+ .set_spi_protect = sandbox_pch_set_spi_protect,
+ .get_gpio_base = sandbox_pch_get_gpio_base,
+ .get_io_base = sandbox_pch_get_io_base,
+ .ioctl = sandbox_pch_ioctl,
+};
+
+static const struct udevice_id sandbox_pch_ids[] = {
+ { .compatible = "sandbox,pch" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_pch_drv) = {
+ .name = "sandbox-pch",
+ .id = UCLASS_PCH,
+ .of_match = sandbox_pch_ids,
+ .ops = &sandbox_pch_ops,
+ .priv_auto_alloc_size = sizeof(struct sandbox_pch_priv),
+};
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2210545..e219572 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -184,11 +184,8 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
return -1;
}
-int pci_hose_config_device(struct pci_controller *hose,
- pci_dev_t dev,
- unsigned long io,
- pci_addr_t mem,
- unsigned long command)
+static int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev,
+ ulong io, pci_addr_t mem, ulong command)
{
u32 bar_response;
unsigned int old_command;
diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
index 40f4f75..6e9dcef 100644
--- a/drivers/sound/Kconfig
+++ b/drivers/sound/Kconfig
@@ -40,6 +40,37 @@ config I2S_SAMSUNG
option provides an implementation for sound_init() and
sound_play().
+config SOUND_I8254
+ bool "Intel i8254 timer / beeper"
+ depends on SOUND
+ help
+ This enables support for a beeper that uses the i8254 timer chip.
+ This can emit beeps at a fixed frequency. It is possible to control
+ the length of the beeps, by turning a beep on, waiting for a period
+ of time, then turning it off.
+
+ This is quite an old feature, called PIT (Programmable Interval
+ Timer), but is nonetheless still available on modern x86 machines.
+
+config SOUND_INTEL_HDA
+ bool "Intel HDA audio codec"
+ depends on SOUND
+ help
+ Most Intel chips have an HDA (High-definition audio) codec which can
+ be used by U-Boot to play simple beeps. This is also sometimes called
+ Azalia which was the development code-name. It requires setup
+ information in the device tree (see intel-hda.txt).
+
+config SOUND_IVYBRIDGE
+ bool "Intel Ivybridge sound support"
+ depends on SOUND
+ select SOUND_INTEL_HDA
+ help
+ Enable sound output on supported Intel Ivybridge-based boards. This
+ driver uses Intel's High-definition Audio (HDA) architecture,
+ sometimes called Azalia. The audio codec is detected using a
+ semi-automatic mechanism.
+
config SOUND_MAX98088
bool "Support Maxim max98088 audio codec"
depends on I2S
@@ -64,6 +95,15 @@ config SOUND_MAX98095
audio data and I2C for codec control. At present it only works
with the Samsung I2S driver.
+config SOUND_RT5677
+ bool "Support Realtek RT5677 audio codec"
+ depends on SOUND
+ help
+ Enable the Realtek RT5677 audio codec. This is an I2S device used on
+ some Chromebooks from around 2015 ('auron'). It is configured using
+ an I2C interface and supports multiple sound inputs and outputs,
+ including digital microphones.
+
config SOUND_SANDBOX
bool "Support sandbox emulated audio codec"
depends on SANDBOX && SOUND
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 170e06a..e155041 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -15,3 +15,8 @@ obj-$(CONFIG_SOUND_WM8994) += wm8994.o
obj-$(CONFIG_SOUND_MAX98088) += max98088.o maxim_codec.o
obj-$(CONFIG_SOUND_MAX98090) += max98090.o maxim_codec.o
obj-$(CONFIG_SOUND_MAX98095) += max98095.o maxim_codec.o
+obj-$(CONFIG_SOUND_INTEL_HDA) += hda_codec.o
+obj-$(CONFIG_SOUND_I8254) += i8254_beep.o
+obj-$(CONFIG_SOUND_RT5677) += rt5677.o
+obj-$(CONFIG_INTEL_BROADWELL) += broadwell_i2s.o broadwell_sound.o
+obj-$(CONFIG_SOUND_IVYBRIDGE) += ivybridge_sound.o
diff --git a/drivers/sound/broadwell_i2s.c b/drivers/sound/broadwell_i2s.c
new file mode 100644
index 0000000..998792b
--- /dev/null
+++ b/drivers/sound/broadwell_i2s.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Intel Broadwell I2S driver
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Modified from dc i2s/broadwell/broadwell.c
+ */
+
+#define LOG_CATEGORY UCLASS_I2S
+
+#include <common.h>
+#include <dm.h>
+#include <i2s.h>
+#include <asm/io.h>
+#include "broadwell_i2s.h"
+
+enum {
+ BDW_SHIM_START_ADDRESS = 0xfb000,
+ BDW_SSP0_START_ADDRESS = 0xfc000,
+ BDW_SSP1_START_ADDRESS = 0xfd000,
+};
+
+struct broadwell_i2s_priv {
+ enum frame_sync_rel_timing_t rel_timing;
+ enum frame_sync_pol_t sfrm_polarity;
+ enum end_transfer_state_t end_transfer_state;
+ enum clock_mode_t sclk_mode;
+ uint sclk_dummy_stop; /* 0-31 */
+ uint sclk_frame_width; /* 1-38 */
+ struct i2s_shim_regs *shim;
+ struct broadwell_i2s_regs *regs;
+};
+
+static void init_shim_csr(struct broadwell_i2s_priv *priv)
+{
+ /*
+ * Select SSP clock
+ * Turn off low power clock
+ * Set PIO mode
+ * Stall DSP core
+ */
+ clrsetbits_le32(&priv->shim->csr,
+ SHIM_CS_S0IOCS | SHIM_CS_LPCS | SHIM_CS_DCS_MASK,
+ SHIM_CS_S1IOCS | SHIM_CS_SBCS_SSP1_24MHZ |
+ SHIM_CS_SBCS_SSP0_24MHZ | SHIM_CS_SDPM_PIO_SSP1 |
+ SHIM_CS_SDPM_PIO_SSP0 | SHIM_CS_STALL |
+ SHIM_CS_DCS_DSP32_AF32);
+}
+
+static void init_shim_clkctl(struct i2s_uc_priv *uc_priv,
+ struct broadwell_i2s_priv *priv)
+{
+ u32 clkctl = readl(&priv->shim->clkctl);
+
+ /* Set 24Mhz mclk, prevent local clock gating, enable SSP0 clock */
+ clkctl &= SHIM_CLKCTL_RESERVED;
+ clkctl |= SHIM_CLKCTL_MCLK_24MHZ | SHIM_CLKCTL_DCPLCG;
+
+ /* Enable requested SSP interface */
+ if (uc_priv->id)
+ clkctl |= SHIM_CLKCTL_SCOE_SSP1 | SHIM_CLKCTL_SFLCGB_SSP1_CGD;
+ else
+ clkctl |= SHIM_CLKCTL_SCOE_SSP0 | SHIM_CLKCTL_SFLCGB_SSP0_CGD;
+
+ writel(clkctl, &priv->shim->clkctl);
+}
+
+static void init_sscr0(struct i2s_uc_priv *uc_priv,
+ struct broadwell_i2s_priv *priv)
+{
+ u32 sscr0;
+ uint scale;
+
+ /* Set data size based on BPS */
+ if (uc_priv->bitspersample > 16)
+ sscr0 = (uc_priv->bitspersample - 16 - 1) << SSP_SSC0_DSS_SHIFT
+ | SSP_SSC0_EDSS;
+ else
+ sscr0 = (uc_priv->bitspersample - 1) << SSP_SSC0_DSS_SHIFT;
+
+ /* Set network mode, Stereo PSP frame format */
+ sscr0 |= SSP_SSC0_MODE_NETWORK |
+ SSP_SSC0_FRDC_STEREO |
+ SSP_SSC0_FRF_PSP |
+ SSP_SSC0_TIM |
+ SSP_SSC0_RIM |
+ SSP_SSC0_ECS_PCH |
+ SSP_SSC0_NCS_PCH |
+ SSP_SSC0_ACS_PCH;
+
+ /* Scale 24MHz MCLK */
+ scale = uc_priv->audio_pll_clk / uc_priv->samplingrate / uc_priv->bfs;
+ sscr0 |= scale << SSP_SSC0_SCR_SHIFT;
+
+ writel(sscr0, &priv->regs->sscr0);
+}
+
+static void init_sscr1(struct broadwell_i2s_priv *priv)
+{
+ u32 sscr1 = readl(&priv->regs->sscr1);
+
+ sscr1 &= SSP_SSC1_RESERVED;
+
+ /* Set as I2S master */
+ sscr1 |= SSP_SSC1_SCLKDIR_MASTER | SSP_SSC1_SCLKDIR_MASTER;
+
+ /* Enable TXD tristate behavior for PCH */
+ sscr1 |= SSP_SSC1_TTELP | SSP_SSC1_TTE;
+
+ /* Disable DMA Tx/Rx service request */
+ sscr1 |= SSP_SSC1_TSRE | SSP_SSC1_RSRE;
+
+ /* Clock on during transfer */
+ sscr1 |= SSP_SSC1_SCFR;
+
+ /* Set FIFO thresholds */
+ sscr1 |= SSP_FIFO_SIZE << SSP_SSC1_RFT_SHIFT;
+ sscr1 |= SSP_FIFO_SIZE << SSP_SSC1_TFT_SHIFT;
+
+ /* Disable interrupts */
+ sscr1 &= ~(SSP_SSC1_EBCEI | SSP_SSC1_TINTE | SSP_SSC1_PINTE);
+ sscr1 &= ~(SSP_SSC1_LBM | SSP_SSC1_RWOT);
+
+ writel(sscr1, &priv->regs->sscr1);
+}
+
+static void init_sspsp(struct broadwell_i2s_priv *priv)
+{
+ u32 sspsp = readl(&priv->regs->sspsp);
+
+ sspsp &= SSP_PSP_RESERVED;
+ sspsp |= priv->sclk_mode << SSP_PSP_SCMODE_SHIFT;
+ sspsp |= (priv->sclk_dummy_stop << SSP_PSP_DMYSTOP_SHIFT) &
+ SSP_PSP_DMYSTOP_MASK;
+ sspsp |= (priv->sclk_dummy_stop >> 2 << SSP_PSP_EDYMSTOP_SHIFT) &
+ SSP_PSP_EDMYSTOP_MASK;
+ sspsp |= priv->sclk_frame_width << SSP_PSP_SFRMWDTH_SHIFT;
+
+ /* Frame Sync Relative Timing */
+ if (priv->rel_timing == NEXT_FRMS_AFTER_END_OF_T4)
+ sspsp |= SSP_PSP_FSRT;
+ else
+ sspsp &= ~SSP_PSP_FSRT;
+
+ /* Serial Frame Polarity */
+ if (priv->sfrm_polarity == SSP_FRMS_ACTIVE_HIGH)
+ sspsp |= SSP_PSP_SFRMP;
+ else
+ sspsp &= ~SSP_PSP_SFRMP;
+
+ /* End Data Transfer State */
+ if (priv->end_transfer_state == SSP_END_TRANSFER_STATE_LOW)
+ sspsp &= ~SSP_PSP_ETDS;
+ else
+ sspsp |= SSP_PSP_ETDS;
+
+ writel(sspsp, &priv->regs->sspsp);
+}
+
+static void init_ssp_time_slot(struct broadwell_i2s_priv *priv)
+{
+ writel(3, &priv->regs->sstsa);
+ writel(3, &priv->regs->ssrsa);
+}
+
+static int bdw_i2s_init(struct udevice *dev)
+{
+ struct i2s_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct broadwell_i2s_priv *priv = dev_get_priv(dev);
+
+ init_shim_csr(priv);
+ init_shim_clkctl(uc_priv, priv);
+ init_sscr0(uc_priv, priv);
+ init_sscr1(priv);
+ init_sspsp(priv);
+ init_ssp_time_slot(priv);
+
+ return 0;
+}
+
+static void bdw_i2s_enable(struct broadwell_i2s_priv *priv)
+{
+ setbits_le32(&priv->regs->sscr0, SSP_SSC0_SSE);
+ setbits_le32(&priv->regs->sstsa, SSP_SSTSA_EN);
+}
+
+static void bdw_i2s_disable(struct broadwell_i2s_priv *priv)
+{
+ clrbits_le32(&priv->regs->sstsa, SSP_SSTSA_EN);
+ clrbits_le32(&priv->regs->sstsa, SSP_SSTSA_EN);
+}
+
+static int broadwell_i2s_tx_data(struct udevice *dev, void *data,
+ uint data_size)
+{
+ struct broadwell_i2s_priv *priv = dev_get_priv(dev);
+ u32 *ptr = data;
+
+ log_debug("data=%p, data_size=%x\n", data, data_size);
+ if (data_size < SSP_FIFO_SIZE) {
+ log_err("Invalid I2S data size\n");
+ return -ENODATA;
+ }
+
+ /* Enable I2S interface */
+ bdw_i2s_enable(priv);
+
+ /* Transfer data */
+ while (data_size > 0) {
+ ulong start = timer_get_us() + 100000;
+
+ /* Write data if transmit FIFO has room */
+ if (readl(&priv->regs->sssr) & SSP_SSS_TNF) {
+ writel(*ptr++, &priv->regs->ssdr);
+ data_size -= sizeof(*ptr);
+ } else {
+ if ((long)(timer_get_us() - start) > 0) {
+ /* Disable I2S interface */
+ bdw_i2s_disable(priv);
+ log_debug("I2S Transfer Timeout\n");
+ return -ETIMEDOUT;
+ }
+ }
+ }
+
+ /* Disable I2S interface */
+ bdw_i2s_disable(priv);
+ log_debug("done\n");
+
+ return 0;
+}
+
+static int broadwell_i2s_probe(struct udevice *dev)
+{
+ struct i2s_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct broadwell_i2s_priv *priv = dev_get_priv(dev);
+ struct udevice *adsp = dev_get_parent(dev);
+ u32 bar0, offset;
+ int ret;
+
+ bar0 = dm_pci_read_bar32(adsp, 0);
+ if (!bar0) {
+ log_debug("Cannot read adsp bar0\n");
+ return -EINVAL;
+ }
+ offset = dev_read_addr_index(dev, 0);
+ if (offset == FDT_ADDR_T_NONE) {
+ log_debug("Cannot read address index 0\n");
+ return -EINVAL;
+ }
+ uc_priv->base_address = bar0 + offset;
+
+ /*
+ * Hard-code these values. If other settings are required we can add
+ * this to the device tree.
+ */
+ uc_priv->rfs = 64;
+ uc_priv->bfs = 32;
+ uc_priv->audio_pll_clk = 24 * 1000 * 1000;
+ uc_priv->samplingrate = 48000;
+ uc_priv->bitspersample = 16;
+ uc_priv->channels = 2;
+ uc_priv->id = 0;
+
+ priv->shim = (struct i2s_shim_regs *)uc_priv->base_address;
+ priv->sfrm_polarity = SSP_FRMS_ACTIVE_LOW;
+ priv->end_transfer_state = SSP_END_TRANSFER_STATE_LOW;
+ priv->sclk_mode = SCLK_MODE_DDF_DSR_ISL;
+ priv->rel_timing = NEXT_FRMS_WITH_LSB_PREVIOUS_FRM;
+ priv->sclk_dummy_stop = 0;
+ priv->sclk_frame_width = 31;
+
+ offset = dev_read_addr_index(dev, 1 + uc_priv->id);
+ if (offset == FDT_ADDR_T_NONE) {
+ log_debug("Cannot read address index %d\n", 1 + uc_priv->id);
+ return -EINVAL;
+ }
+ log_debug("bar0=%x, uc_priv->base_address=%x, offset=%x\n", bar0,
+ uc_priv->base_address, offset);
+ priv->regs = (struct broadwell_i2s_regs *)(bar0 + offset);
+
+ ret = bdw_i2s_init(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct i2s_ops broadwell_i2s_ops = {
+ .tx_data = broadwell_i2s_tx_data,
+};
+
+static const struct udevice_id broadwell_i2s_ids[] = {
+ { .compatible = "intel,broadwell-i2s" },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_i2s) = {
+ .name = "broadwell_i2s",
+ .id = UCLASS_I2S,
+ .of_match = broadwell_i2s_ids,
+ .probe = broadwell_i2s_probe,
+ .ops = &broadwell_i2s_ops,
+ .priv_auto_alloc_size = sizeof(struct broadwell_i2s_priv),
+};
diff --git a/drivers/sound/broadwell_i2s.h b/drivers/sound/broadwell_i2s.h
new file mode 100644
index 0000000..ba87abf
--- /dev/null
+++ b/drivers/sound/broadwell_i2s.h
@@ -0,0 +1,301 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Intel Broadwell I2S driver
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Modified from dc i2s/broadwell/broadwell.h
+ */
+
+#ifndef __BROADWELL_I2S_H__
+#define __BROADWELL_I2S_H__
+
+enum {
+ SSP_FIFO_SIZE = 7,
+};
+
+enum frame_sync_rel_timing_t {
+ NEXT_FRMS_AFTER_END_OF_T4 = 0,
+ NEXT_FRMS_WITH_LSB_PREVIOUS_FRM,
+};
+
+enum frame_sync_pol_t {
+ SSP_FRMS_ACTIVE_LOW = 0,
+ SSP_FRMS_ACTIVE_HIGH,
+};
+
+enum end_transfer_state_t {
+ SSP_END_TRANSFER_STATE_LOW = 0,
+ SSP_END_TRANSFER_STATE_PEVIOUS_BIT,
+};
+
+enum clock_mode_t {
+ /* Data driven (falling), data sampled (rising), idle state (low) */
+ SCLK_MODE_DDF_DSR_ISL,
+ /* Data driven (rising), data sampled (falling), idle state (low) */
+ SCLK_MODE_DDR_DSF_ISL,
+ /* Data driven (rising), data sampled (falling), idle state (high) */
+ SCLK_MODE_DDR_DSF_ISH,
+ /* Data driven (falling), data sampled (rising), idle state (high) */
+ SCLK_MODE_DDF_DSR_ISH,
+};
+
+struct i2s_shim_regs {
+ u32 csr; /* 0x00 */
+ u32 reserved0[29]; /* 0x14 - 0x77 */
+ u32 clkctl; /* 0x78 */
+ u32 reserved1; /* 0x7c */
+ u32 cs2; /* 0x80 */
+};
+
+struct broadwell_i2s_regs {
+ u32 sscr0; /* 0x00 */
+ u32 sscr1; /* 0x04 */
+ u32 sssr; /* 0x08 */
+ u32 ssitr; /* 0x0c */
+ u32 ssdr; /* 0x10 */
+ u32 reserved0[5]; /* 0x14 - 0x27 */
+ u32 ssto; /* 0x28 */
+ u32 sspsp; /* 0x2c */
+ u32 sstsa; /* 0x30 */
+ u32 ssrsa; /* 0x34 */
+ u32 sstss; /* 0x38 */
+ u32 sscr2; /* 0x40 */
+ u32 sspsp2; /* 0x44 */
+};
+
+/* SHIM Configuration & Status */
+enum {
+ /* Low Power Clock Select */
+ SHIM_CS_LPCS = 1 << 31,
+ /* SSP Force Clock Running */
+ SHIM_CS_SFCR_SSP1 = 1 << 28,
+ SHIM_CS_SFCR_SSP0 = 1 << 27,
+ /* SSP1 IO Clock Select */
+ SHIM_CS_S1IOCS = 1 << 23,
+ /* SSP0 IO Clock Select */
+ SHIM_CS_S0IOCS = 1 << 21,
+ /* Parity Check Enable */
+ SHIM_CS_PCE = 1 << 15,
+ /* SSP DMA or PIO Mode */
+ SHIM_CS_SDPM_PIO_SSP1 = 1 << 12,
+ SHIM_CS_SDPM_DMA_SSP1 = 0 << 12,
+ SHIM_CS_SDPM_PIO_SSP0 = 1 << 11,
+ SHIM_CS_SDPM_DMA_SSP0 = 0 << 11,
+ /* Run / Stall */
+ SHIM_CS_STALL = 1 << 10,
+ /* DSP Clock Select */
+ SHIM_CS_DCS_DSP320_AF80 = 0 << 4,
+ SHIM_CS_DCS_DSP160_AF80 = 1 << 4,
+ SHIM_CS_DCS_DSP80_AF80 = 2 << 4,
+ SHIM_CS_DCS_DSP320_AF160 = 4 << 4,
+ SHIM_CS_DCS_DSP160_AF160 = 5 << 4,
+ SHIM_CS_DCS_DSP32_AF32 = 6 << 4,
+ SHIM_CS_DCS_MASK = 7 << 4,
+ /* SSP Base Clock Select */
+ SHIM_CS_SBCS_SSP0_24MHZ = 1 << 3,
+ SHIM_CS_SBCS_SSP0_32MHZ = 0 << 3,
+ SHIM_CS_SBCS_SSP1_24MHZ = 1 << 2,
+ SHIM_CS_SBCS_SSP1_32MHZ = 0 << 2,
+ /* DSP Core Reset */
+ SHIM_CS_RST = 1 << 1,
+};
+
+/* SHIM Clock Control */
+enum {
+ /* Clock Frequency Change In Progress */
+ SHIM_CLKCTL_CFCIP = 1 << 31,
+ /* SSP MCLK Output Select */
+ SHIM_CLKCTL_MCLK_MASK = 0x3,
+ SHIM_CLKCTL_MCLK_SHIFT = 24,
+ SHIM_CLKCTL_MCLK_DISABLED = 0 << 24,
+ SHIM_CLKCTL_MCLK_6MHZ = 1 << 24,
+ SHIM_CLKCTL_MCLK_12MHZ = 2 << 24,
+ SHIM_CLKCTL_MCLK_24MHZ = 3 << 24,
+ /* DSP Core Prevent Local Clock Gating */
+ SHIM_CLKCTL_DCPLCG = 1 << 18,
+ /* SSP Clock Output Enable */
+ SHIM_CLKCTL_SCOE_SSP1 = 1 << 17,
+ SHIM_CLKCTL_SCOE_SSP0 = 1 << 16,
+ /* DMA Engine Force Local Clock Gating */
+ SHIM_CLKCTL_DEFLCGB_DMA1_CGE = 0 << 6,
+ SHIM_CLKCTL_DEFLCGB_DMA1_CGD = 1 << 6,
+ SHIM_CLKCTL_DEFLCGB_DMA0_CGE = 0 << 5,
+ SHIM_CLKCTL_DEFLCGB_DMA0_CGD = 1 << 5,
+ /* SSP Force Local Clock Gating */
+ SHIM_CLKCTL_SFLCGB_SSP1_CGE = 0 << 1,
+ SHIM_CLKCTL_SFLCGB_SSP1_CGD = 1 << 1,
+ SHIM_CLKCTL_SFLCGB_SSP0_CGE = 0 << 0,
+ SHIM_CLKCTL_SFLCGB_SSP0_CGD = 1 << 0,
+
+ /* Reserved bits: 30:26, 23:19, 15:7, 4:2 */
+ SHIM_CLKCTL_RESERVED = 0x1f << 26 | 0x1f << 19 | 0x1ff << 7 | 0x7 << 2,
+};
+
+/* SSP Status */
+enum {
+ /* Bit Count Error */
+ SSP_SSS_BCE = 1 << 23,
+ /* Clock Sync Statu s*/
+ SSP_SSS_CSS = 1 << 22,
+ /* Transmit FIFO Underrun */
+ SSP_SSS_TUR = 1 << 21,
+ /* End Of Chain */
+ SSP_SSS_EOC = 1 << 20,
+ /* Receiver Time-out Interrupt */
+ SSP_SSS_TINT = 1 << 19,
+ /* Peripheral Trailing Byte Interrupt */
+ SSP_SSS_PINT = 1 << 18,
+ /* Received FIFO Level */
+ SSP_RFL_MASK = 0xf,
+ SSP_RFL_SHIFT = 12,
+ /* Transmit FIFO Level */
+ SSP_TFL_MASK = 0xf,
+ SSP_TFL_SHIFT = 8,
+ /* Receive FIFO Overrun */
+ SSP_SSS_ROR = 1 << 7,
+ /* Receive FIFO Service Request */
+ SSP_SSS_RFS = 1 << 6,
+ /* Transmit FIFO Service Request */
+ SSP_SSS_TFS = 1 << 5,
+ /* SSP Busy */
+ SSP_SSS_BSY = 1 << 4,
+ /* Receive FIFO Not Empty */
+ SSP_SSS_RNE = 1 << 3,
+ /* Transmit FIFO Not Full */
+ SSP_SSS_TNF = 1 << 2,
+};
+
+/* SSP Control 0 */
+enum {
+ /* Mode */
+ SSP_SSC0_MODE_NORMAL = 0 << 31,
+ SSP_SSC0_MODE_NETWORK = 1 << 31,
+ /* Audio Clock Select */
+ SSP_SSC0_ACS_PCH = 0 << 30,
+ /* Frame Rate Divider Control (0-7) */
+ SSP_SSC0_FRDC_MASK = 0x7,
+ SSP_SSC0_FRDC_SHIFT = 24,
+ SSP_SSC0_FRDC_STEREO = 1 << 24,
+ /* Transmit FIFO Underrun Interrupt Mask */
+ SSP_SSC0_TIM = 1 << 23,
+ /* Receive FIFO Underrun Interrupt Mask */
+ SSP_SSC0_RIM = 1 << 22,
+ /* Network Clock Select */
+ SSP_SSC0_NCS_PCH = 0 << 21,
+ /* Extended Data Size Select */
+ SSP_SSC0_EDSS = 1 << 20,
+ /* Serial Clock Rate (0-4095) */
+ SSP_SSC0_SCR_SHIFT = 8,
+ SSP_SSC0_SCR_MASK = 0xfff << SSP_SSC0_SCR_SHIFT,
+ /* Synchronous Serial Port Enable */
+ SSP_SSC0_SSE = 1 << 7,
+ /* External Clock Select */
+ SSP_SSC0_ECS_PCH = 0 << 6,
+ /* Frame Format */
+ SSP_SSC0_FRF_MOTOROLA_SPI = 0 << 4,
+ SSP_SSC0_FRF_TI_SSP = 1 << 4,
+ SSP_SSC0_FRF_NS_MICROWIRE = 2 << 4,
+ SSP_SSC0_FRF_PSP = 3 << 4,
+ /* Data Size Select */
+ SSP_SSC0_DSS_SHIFT = 0,
+ SSP_SSC0_DSS_MASK = 0xf << SSP_SSC0_DSS_SHIFT,
+};
+
+/* SSP Control 1 */
+enum {
+ /* TXD Tristate Enable on Last Phase */
+ SSP_SSC1_TTELP = 1 << 31,
+ /* TXD Tristate Enable */
+ SSP_SSC1_TTE = 1 << 30,
+ /* Enable Bit Count Error Interrupt */
+ SSP_SSC1_EBCEI = 1 << 29,
+ /* Slave Clock Running */
+ SSP_SSC1_SCFR = 1 << 28,
+ /* Enable Clock Request A */
+ SSP_SSC1_ECRA = 1 << 27,
+ /* Enable Clock Request B */
+ SSP_SSC1_ECRB = 1 << 26,
+ /* SSPCLK Direction */
+ SSP_SSC1_SCLKDIR_SLAVE = 1 << 25,
+ SSP_SSC1_SCLKDIR_MASTER = 0 << 25,
+ /* SSPFRM Direction */
+ SSP_SSC1_SFRMDIR_SLAVE = 1 << 24,
+ SSP_SSC1_SFRMDIR_MASTER = 0 << 24,
+ /* Receive without Transmit */
+ SSP_SSC1_RWOT = 1 << 23,
+ /* Trailing Byte */
+ SSP_SSC1_TRAIL = 1 << 22,
+ /* DMA Tx Service Request Enable */
+ SSP_SSC1_TSRE = 1 << 21,
+ /* DMA Rx Service Request Enable */
+ SSP_SSC1_RSRE = 1 << 20,
+ /* Receiver Timeout Interrupt Enable */
+ SSP_SSC1_TINTE = 1 << 19,
+ /* Periph. Trailing Byte Int. Enable */
+ SSP_SSC1_PINTE = 1 << 18,
+ /* Invert Frame Signal */
+ SSP_SSC1_IFS = 1 << 16,
+ /* Select FIFO for EFWR: test mode */
+ SSP_SSC1_STRF = 1 << 15,
+ /* Enable FIFO Write/Read: test mode */
+ SSP_SSC1_EFWR = 1 << 14,
+ /* Receive FIFO Trigger Threshold */
+ SSP_SSC1_RFT_SHIFT = 10,
+ SSP_SSC1_RFT_MASK = 0xf << SSP_SSC1_RFT_SHIFT,
+ /* Transmit FIFO Trigger Threshold */
+ SSP_SSC1_TFT_SHIFT = 6,
+ SSP_SSC1_TFT_MASK = 0xf << SSP_SSC1_TFT_SHIFT,
+ /* Microwire Transmit Data Size */
+ SSP_SSC1_MWDS = 1 << 5,
+ /* Motorola SPI SSPSCLK Phase Setting*/
+ SSP_SSC1_SPH = 1 << 4,
+ /* Motorola SPI SSPSCLK Polarity */
+ SSP_SSC1_SPO = 1 << 3,
+ /* Loopback mode: test mode */
+ SSP_SSC1_LBM = 1 << 2,
+ /* Transmit FIFO Interrupt Enable */
+ SSP_SSC1_TIE = 1 << 1,
+ /* Receive FIFO Interrupt Enable */
+ SSP_SSC1_RIE = 1 << 0,
+
+ SSP_SSC1_RESERVED = 17 << 1,
+};
+
+/* SSP Programmable Serial Protocol */
+enum {
+ /* Extended Dummy Stop (0-31) */
+ SSP_PSP_EDYMSTOP_SHIFT = 26,
+ SSP_PSP_EDMYSTOP_MASK = 0x7 << SSP_PSP_EDYMSTOP_SHIFT,
+ /* Frame Sync Relative Timing */
+ SSP_PSP_FSRT = 1 << 25,
+ /* Dummy Stop low bits */
+ SSP_PSP_DMYSTOP_SHIFT = 23,
+ SSP_PSP_DMYSTOP_MASK = 0x3 << SSP_PSP_DMYSTOP_SHIFT,
+ /* Serial Frame Width */
+ SSP_PSP_SFRMWDTH_SHIFT = 16,
+ SSP_PSP_SFRMWDTH_MASK = 0x3f << SSP_PSP_SFRMWDTH_SHIFT,
+ /* Serial Frame Delay */
+ SSP_PSP_SFRMDLY_MASK = 0x7f,
+ SSP_PSP_SFRMDLY_SHIFT = 9,
+ /* Start Delay */
+ SSP_PSP_STRTDLY_MASK = 0x7,
+ SSP_PSP_STRTDLY_SHIFT = 4,
+ /* End of Transfer Data State */
+ SSP_PSP_ETDS = 1 << 3,
+ /* Serial Frame Polarity */
+ SSP_PSP_SFRMP = 1 << 2,
+ /* Serial Clock Mode */
+ SSP_PSP_SCMODE_SHIFT = 0,
+ SSP_PSP_SCMODE_MASK = 0x3 << SSP_PSP_SCMODE_SHIFT,
+
+ SSP_PSP_RESERVED = 1 << 22,
+};
+
+/* SSP TX Time Slot Active */
+enum {
+ SSP_SSTSA_EN = 1 << 8,
+ SSP_SSTSA_MASK = 0xff,
+};
+
+#endif /* __BROADWELL_I2S_H__ */
diff --git a/drivers/sound/broadwell_sound.c b/drivers/sound/broadwell_sound.c
new file mode 100644
index 0000000..6e083fe
--- /dev/null
+++ b/drivers/sound/broadwell_sound.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sound for broadwell
+ *
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_SOUND
+
+#include <common.h>
+#include <audio_codec.h>
+#include <dm.h>
+#include <i2s.h>
+#include <sound.h>
+
+static int broadwell_sound_probe(struct udevice *dev)
+{
+ return sound_find_codec_i2s(dev);
+}
+
+static int broadwell_sound_setup(struct udevice *dev)
+{
+ struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct i2s_uc_priv *i2c_priv = dev_get_uclass_priv(uc_priv->i2s);
+ int ret;
+
+ if (uc_priv->setup_done)
+ return -EALREADY;
+ ret = audio_codec_set_params(uc_priv->codec, i2c_priv->id,
+ i2c_priv->samplingrate,
+ i2c_priv->samplingrate * i2c_priv->rfs,
+ i2c_priv->bitspersample,
+ i2c_priv->channels);
+ if (ret)
+ return ret;
+ uc_priv->setup_done = true;
+
+ return 0;
+}
+
+static int broadwell_sound_play(struct udevice *dev, void *data, uint data_size)
+{
+ struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ return i2s_tx_data(uc_priv->i2s, data, data_size);
+}
+
+static const struct sound_ops broadwell_sound_ops = {
+ .setup = broadwell_sound_setup,
+ .play = broadwell_sound_play,
+};
+
+static const struct udevice_id broadwell_sound_ids[] = {
+ { .compatible = "google,samus-sound" },
+ { }
+};
+
+U_BOOT_DRIVER(broadwell_sound_drv) = {
+ .name = "broadwell_sound",
+ .id = UCLASS_SOUND,
+ .of_match = broadwell_sound_ids,
+ .probe = broadwell_sound_probe,
+ .ops = &broadwell_sound_ops,
+};
diff --git a/drivers/sound/hda_codec.c b/drivers/sound/hda_codec.c
new file mode 100644
index 0000000..572ef69
--- /dev/null
+++ b/drivers/sound/hda_codec.c
@@ -0,0 +1,556 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Implementation of per-board codec beeping
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * Copyright 2018 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_SOUND
+
+#include <common.h>
+#include <dm.h>
+#include <hda_codec.h>
+#include <pci.h>
+#include <sound.h>
+#include <asm/io.h>
+#include <dt-bindings/sound/azalia.h>
+
+/**
+ * struct hda_regs - HDA registers
+ *
+ * https://wiki.osdev.org/Intel_High_Definition_Audio
+ * https://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html
+ */
+struct hda_regs {
+ u16 gcap;
+ u8 vmin;
+ u8 vmaj;
+ u16 outpay;
+ u16 inpay;
+ u32 gctl;
+ u16 wakeen;
+ u16 statests;
+ u8 reserved[0x50];
+ u32 cmd; /* 0x60 */
+ u32 resp;
+ u32 icii;
+};
+
+enum {
+ HDA_ICII_BUSY = BIT(0),
+ HDA_ICII_VALID = BIT(1),
+
+ /* Common node IDs */
+ HDA_ROOT_NODE = 0x00,
+
+ /* HDA verbs fields */
+ HDA_VERB_NID_S = 20,
+ HDA_VERB_VERB_S = 8,
+ HDA_VERB_PARAM_S = 0,
+
+ HDA_VERB_GET_PARAMS = 0xf00,
+ HDA_VERB_SET_BEEP = 0x70a,
+
+ /* GET_PARAMS parameter IDs */
+ GET_PARAMS_NODE_COUNT = 0x04,
+ GET_PARAMS_AUDIO_GROUP_CAPS = 0x08,
+ GET_PARAMS_AUDIO_WIDGET_CAPS = 0x09,
+
+ /* Sub-node fields */
+ NUM_SUB_NODES_S = 0,
+ NUM_SUB_NODES_M = 0xff << NUM_SUB_NODES_S,
+ FIRST_SUB_NODE_S = 16,
+ FIRST_SUB_NODE_M = 0xff << FIRST_SUB_NODE_S,
+
+ /* Get Audio Function Group Capabilities fields */
+ AUDIO_GROUP_CAPS_BEEP_GEN = 0x10000,
+
+ /* Get Audio Widget Capabilities fields */
+ AUDIO_WIDGET_TYPE_BEEP = 0x7,
+ AUDIO_WIDGET_TYPE_S = 20,
+ AUDIO_WIDGET_TYPE_M = 0xf << AUDIO_WIDGET_TYPE_S,
+
+ BEEP_FREQ_BASE = 12000,
+};
+
+static inline uint hda_verb(uint nid, uint verb, uint param)
+{
+ return nid << HDA_VERB_NID_S | verb << HDA_VERB_VERB_S |
+ param << HDA_VERB_PARAM_S;
+}
+
+int hda_wait_for_ready(struct hda_regs *regs)
+{
+ int timeout = 1000; /* Use a 1msec timeout */
+
+ while (timeout--) {
+ u32 reg32 = readl(&regs->icii);
+
+ if (!(reg32 & HDA_ICII_BUSY))
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int wait_for_response(struct hda_regs *regs, uint *response)
+{
+ int timeout = 1000;
+ u32 reg32;
+
+ /* Send the verb to the codec */
+ setbits_le32(&regs->icii, HDA_ICII_BUSY | HDA_ICII_VALID);
+
+ /* Use a 1msec timeout */
+ while (timeout--) {
+ reg32 = readl(&regs->icii);
+ if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
+ HDA_ICII_VALID) {
+ if (response)
+ *response = readl(&regs->resp);
+ return 0;
+ }
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+int hda_wait_for_valid(struct hda_regs *regs)
+{
+ return wait_for_response(regs, NULL);
+}
+
+static int set_bits(void *port, u32 mask, u32 val)
+{
+ u32 reg32;
+ int count;
+
+ /* Write (val & mask) to port */
+ clrsetbits_le32(port, mask, val);
+
+ /* Wait for readback of register to match what was just written to it */
+ count = 50;
+ do {
+ /* Wait 1ms based on BKDG wait time */
+ mdelay(1);
+ reg32 = readl(port) & mask;
+ } while (reg32 != val && --count);
+
+ /* Timeout occurred */
+ if (!count)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int hda_codec_detect(struct hda_regs *regs)
+{
+ uint reg8;
+
+ /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
+ if (set_bits(&regs->gctl, 1, 1))
+ goto no_codec;
+
+ /* Write back the value once reset bit is set */
+ writew(readw(&regs->gcap), &regs->gcap);
+
+ /* Read in Codec location */
+ reg8 = readb(&regs->statests) & 0xf;
+ if (!reg8)
+ goto no_codec;
+
+ return reg8;
+
+no_codec:
+ /* Codec Not found - put HDA back in reset */
+ set_bits(&regs->gctl, 1, 0);
+ log_debug("No codec\n");
+
+ return 0;
+}
+
+static int find_verb_data(struct udevice *dev, uint id, ofnode *nodep)
+{
+ ofnode parent = dev_read_subnode(dev, "codecs");
+ ofnode node;
+ u32 vendor_id, device_id;
+
+ ofnode_for_each_subnode(node, parent) {
+ if (ofnode_read_u32(node, "vendor-id", &vendor_id) ||
+ ofnode_read_u32(node, "device-id", &device_id)) {
+ log_debug("Cannot get IDs for '%s'\n",
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+ if (id != (vendor_id << 16 | device_id)) {
+ log_debug("Skip codec node '%s' for %08x\n",
+ ofnode_get_name(node), id);
+ continue;
+ }
+
+ log_debug("Found codec node '%s' for %08x\n",
+ ofnode_get_name(node), id);
+ *nodep = node;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int send_verbs(ofnode node, const char *prop_name, struct hda_regs *regs)
+{
+ int ret, verb_size, i;
+ const u32 *verb;
+
+ verb = ofnode_get_property(node, prop_name, &verb_size);
+ if (verb_size < 0) {
+ log_debug("No verb data\n");
+ return -EINVAL;
+ }
+ log_debug("verb_size: %d\n", verb_size);
+
+ for (i = 0; i < verb_size / sizeof(*verb); i++) {
+ ret = hda_wait_for_ready(regs);
+ if (ret) {
+ log_debug(" codec ready timeout\n");
+ return ret;
+ }
+
+ writel(fdt32_to_cpu(verb[i]), &regs->cmd);
+
+ ret = hda_wait_for_valid(regs);
+ if (ret) {
+ log_debug(" codec valid timeout\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int codec_init(struct udevice *dev, struct hda_regs *regs, uint addr)
+{
+ ofnode node;
+ uint id;
+ int ret;
+
+ log_debug("Initializing codec #%d\n", addr);
+ ret = hda_wait_for_ready(regs);
+ if (ret) {
+ log_debug(" codec not ready\n");
+ return ret;
+ }
+
+ /* Read the codec's vendor ID */
+ writel(addr << AZALIA_CODEC_SHIFT |
+ AZALIA_OPCODE_READ_PARAM << AZALIA_VERB_SHIFT |
+ AZALIA_PARAM_VENDOR_ID, &regs->cmd);
+ ret = hda_wait_for_valid(regs);
+ if (ret) {
+ log_debug(" codec not valid\n");
+ return ret;
+ }
+
+ id = readl(&regs->resp);
+ log_debug("codec vid/did: %08x\n", id);
+ ret = find_verb_data(dev, id, &node);
+ if (ret) {
+ log_debug("No verb (err=%d)\n", ret);
+ return ret;
+ }
+ ret = send_verbs(node, "verbs", regs);
+ if (ret) {
+ log_debug("failed to send verbs (err=%d)\n", ret);
+ return ret;
+ }
+ log_debug("verb loaded\n");
+
+ return 0;
+}
+
+int hda_codecs_init(struct udevice *dev, struct hda_regs *regs, u32 codec_mask)
+{
+ int ret;
+ int i;
+
+ for (i = 3; i >= 0; i--) {
+ if (codec_mask & (1 << i)) {
+ ret = codec_init(dev, regs, i);
+ if (ret)
+ return ret;
+ }
+ }
+
+ ret = send_verbs(dev_ofnode(dev), "beep-verbs", regs);
+ if (ret) {
+ log_debug("failed to send beep verbs (err=%d)\n", ret);
+ return ret;
+ }
+ log_debug("beep verbs loaded\n");
+
+ return 0;
+}
+
+/**
+ * exec_verb() - Write a verb to the codec
+ *
+ * @regs: HDA registers
+ * @val: Command to write
+ * @response: Set to response from codec
+ * @return 0 if OK, -ve on error
+ */
+static int exec_verb(struct hda_regs *regs, uint val, uint *response)
+{
+ int ret;
+
+ ret = hda_wait_for_ready(regs);
+ if (ret)
+ return ret;
+
+ writel(val, &regs->cmd);
+
+ return wait_for_response(regs, response);
+}
+
+/**
+ * get_subnode_info() - Get subnode information
+ *
+ * @regs: HDA registers
+ * @nid: Parent node ID to check
+ * @num_sub_nodesp: Returns number of subnodes
+ * @start_sub_node_nidp: Returns start subnode number
+ * @return 0 if OK, -ve on error
+ */
+static int get_subnode_info(struct hda_regs *regs, uint nid,
+ uint *num_sub_nodesp, uint *start_sub_node_nidp)
+{
+ uint response;
+ int ret;
+
+ ret = exec_verb(regs, hda_verb(nid, HDA_VERB_GET_PARAMS,
+ GET_PARAMS_NODE_COUNT),
+ &response);
+ if (ret < 0) {
+ printf("Audio: Error reading sub-node info %d\n", nid);
+ return ret;
+ }
+
+ *num_sub_nodesp = (response & NUM_SUB_NODES_M) >> NUM_SUB_NODES_S;
+ *start_sub_node_nidp = (response & FIRST_SUB_NODE_M) >>
+ FIRST_SUB_NODE_S;
+
+ return 0;
+}
+
+/**
+ * find_beep_node_in_group() - Finds the beeping node
+ *
+ * Searches the audio group for a node that supports beeping
+ *
+ * @regs: HDA registers
+ * @group_nid: Group node ID to check
+ * @return 0 if OK, -ve on error
+ */
+static uint find_beep_node_in_group(struct hda_regs *regs, uint group_nid)
+{
+ uint node_count = 0;
+ uint current_nid = 0;
+ uint response;
+ uint end_nid;
+ int ret;
+
+ ret = get_subnode_info(regs, group_nid, &node_count, &current_nid);
+ if (ret < 0)
+ return 0;
+
+ end_nid = current_nid + node_count;
+ while (current_nid < end_nid) {
+ ret = exec_verb(regs,
+ hda_verb(current_nid, HDA_VERB_GET_PARAMS,
+ GET_PARAMS_AUDIO_WIDGET_CAPS),
+ &response);
+ if (ret < 0) {
+ printf("Audio: Error reading widget caps\n");
+ return 0;
+ }
+
+ if ((response & AUDIO_WIDGET_TYPE_M) >> AUDIO_WIDGET_TYPE_S ==
+ AUDIO_WIDGET_TYPE_BEEP)
+ return current_nid;
+
+ current_nid++;
+ }
+
+ return 0; /* no beep node found */
+}
+
+/**
+ * audio_group_has_beep_node() - Check if group has a beep node
+ *
+ * Checks if the given audio group contains a beep generator
+ * @regs: HDA registers
+ * @nid: Node ID to check
+ * @return 0 if OK, -ve on error
+ */
+static int audio_group_has_beep_node(struct hda_regs *regs, uint nid)
+{
+ uint response;
+ int ret;
+
+ ret = exec_verb(regs, hda_verb(nid, HDA_VERB_GET_PARAMS,
+ GET_PARAMS_AUDIO_GROUP_CAPS),
+ &response);
+ if (ret < 0) {
+ printf("Audio: Error reading audio group caps %d\n", nid);
+ return 0;
+ }
+
+ return !!(response & AUDIO_GROUP_CAPS_BEEP_GEN);
+}
+
+/**
+ * get_hda_beep_nid() - Finds the node ID of the beep node
+ *
+ * Finds the nid of the beep node if it exists. Starts at the root node, for
+ * each sub-node checks if the group contains a beep node. If the group
+ * contains a beep node, polls each node in the group until it is found.
+ *
+ * If the device has a intel,beep-nid property, the value of that is used
+ * instead.
+ *
+ * @dev: Sound device
+ * @return Node ID >0 if found, -ve error code otherwise
+ */
+static int get_hda_beep_nid(struct udevice *dev)
+{
+ struct hda_codec_priv *priv = dev_get_priv(dev);
+ uint current_nid = 0;
+ uint node_count = 0;
+ uint end_nid;
+ int ret;
+
+ /* If the field exists, use the beep nid set in the fdt */
+ ret = dev_read_u32(dev, "intel,beep-nid", &current_nid);
+ if (!ret)
+ return current_nid;
+
+ ret = get_subnode_info(priv->regs, HDA_ROOT_NODE, &node_count,
+ &current_nid);
+ if (ret < 0)
+ return ret;
+
+ end_nid = current_nid + node_count;
+ while (current_nid < end_nid) {
+ if (audio_group_has_beep_node(priv->regs, current_nid))
+ return find_beep_node_in_group(priv->regs,
+ current_nid);
+ current_nid++;
+ }
+ /* no beep node found */
+
+ return -ENOENT;
+}
+
+/**
+ * set_beep_divisor() - Sets the beep divisor to set the pitch
+ *
+ * @priv: Device's private data
+ * @divider: Divider value (0 to disable the beep)
+ * @return 0 if OK, -ve on error
+ */
+static int set_beep_divisor(struct hda_codec_priv *priv, uint divider)
+{
+ return exec_verb(priv->regs,
+ hda_verb(priv->beep_nid, HDA_VERB_SET_BEEP, divider),
+ NULL);
+}
+
+int hda_codec_init(struct udevice *dev)
+{
+ struct hda_codec_priv *priv = dev_get_priv(dev);
+ ulong base_addr;
+
+ base_addr = dm_pci_read_bar32(dev, 0);
+ log_debug("base = %08lx\n", base_addr);
+ if (!base_addr)
+ return -EINVAL;
+
+ priv->regs = (struct hda_regs *)base_addr;
+
+ return 0;
+}
+
+int hda_codec_finish_init(struct udevice *dev)
+{
+ struct hda_codec_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = get_hda_beep_nid(dev);
+ if (ret <= 0) {
+ log_warning("Could not find beep NID (err=%d)\n", ret);
+ return ret ? ret : -ENOENT;
+ }
+ priv->beep_nid = ret;
+
+ return 0;
+}
+
+int hda_codec_start_beep(struct udevice *dev, int frequency_hz)
+{
+ struct hda_codec_priv *priv = dev_get_priv(dev);
+ uint divider_val;
+
+ if (!priv->beep_nid) {
+ log_err("Failed to find a beep-capable node\n");
+ return -ENOENT;
+ }
+
+ if (!frequency_hz)
+ divider_val = 0; /* off */
+ else if (frequency_hz > BEEP_FREQ_BASE)
+ divider_val = 1;
+ else if (frequency_hz < BEEP_FREQ_BASE / 0xff)
+ divider_val = 0xff;
+ else
+ divider_val = 0xff & (BEEP_FREQ_BASE / frequency_hz);
+
+ return set_beep_divisor(priv, divider_val);
+}
+
+int hda_codec_stop_beep(struct udevice *dev)
+{
+ struct hda_codec_priv *priv = dev_get_priv(dev);
+
+ return set_beep_divisor(priv, 0);
+}
+
+static const struct sound_ops hda_codec_ops = {
+ .setup = hda_codec_finish_init,
+ .start_beep = hda_codec_start_beep,
+ .stop_beep = hda_codec_stop_beep,
+};
+
+U_BOOT_DRIVER(hda_codec) = {
+ .name = "hda_codec",
+ .id = UCLASS_SOUND,
+ .ops = &hda_codec_ops,
+ .priv_auto_alloc_size = sizeof(struct hda_codec_priv),
+ .probe = hda_codec_init,
+};
+
+static struct pci_device_id hda_supported[] = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_HDA},
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA},
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_WILDCATPOINT_HDA) },
+
+ /*
+ * Note this driver is not necessarily generic, but it attempts to
+ * support any codec in the hd-audio class
+ */
+ { PCI_DEVICE_CLASS(PCI_CLASS_MULTIMEDIA_HD_AUDIO, 0xffffff) },
+};
+
+U_BOOT_PCI_DEVICE(hda_codec, hda_supported);
diff --git a/drivers/sound/i8254_beep.c b/drivers/sound/i8254_beep.c
new file mode 100644
index 0000000..5572dc4
--- /dev/null
+++ b/drivers/sound/i8254_beep.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sound.h>
+#include <asm/i8254.h>
+
+int i8254_start_beep(struct udevice *dev, int frequency_hz)
+{
+ return i8254_enable_beep(frequency_hz);
+}
+
+int i8254_stop_beep(struct udevice *dev)
+{
+ i8254_disable_beep();
+
+ return 0;
+}
+
+static const struct sound_ops i8254_ops = {
+ .start_beep = i8254_start_beep,
+ .stop_beep = i8254_stop_beep,
+};
+
+static const struct udevice_id i8254_ids[] = {
+ { .compatible = "i8254,beeper" },
+ { }
+};
+
+U_BOOT_DRIVER(i8254_drv) = {
+ .name = "i8254_drv",
+ .id = UCLASS_SOUND,
+ .of_match = i8254_ids,
+ .ops = &i8254_ops,
+};
diff --git a/drivers/sound/ivybridge_sound.c b/drivers/sound/ivybridge_sound.c
new file mode 100644
index 0000000..101046f
--- /dev/null
+++ b/drivers/sound/ivybridge_sound.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel HDA audio (Azalia) for ivybridge
+ *
+ * Originally from coreboot file bd82x6x/azalia.c
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2011 The ChromiumOS Authors.
+ * Copyright 2018 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_SOUND
+
+#include <common.h>
+#include <dm.h>
+#include <hda_codec.h>
+#include <pch.h>
+#include <sound.h>
+
+static int bd82x6x_azalia_probe(struct udevice *dev)
+{
+ struct pci_child_platdata *plat;
+ struct hda_codec_priv *priv;
+ struct udevice *pch;
+ u32 codec_mask;
+ int conf;
+ int ret;
+
+ /* Only init after relocation */
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ ret = hda_codec_init(dev);
+ if (ret) {
+ log_debug("Cannot set up HDA codec (err=%d)\n", ret);
+ return ret;
+ }
+ priv = dev_get_priv(dev);
+
+ ret = uclass_first_device_err(UCLASS_PCH, &pch);
+ log_debug("PCH %p %s\n", pch, pch->name);
+ if (ret)
+ return ret;
+
+ conf = pch_ioctl(pch, PCH_REQ_HDA_CONFIG, NULL, 0);
+ log_debug("conf = %x\n", conf);
+ if (conf >= 0) {
+ dm_pci_clrset_config32(dev, 0x120, 7 << 24 | 0xfe,
+ 1 << 24 | /* 2 << 24 for server */
+ conf);
+
+ dm_pci_clrset_config16(dev, 0x78, 0, 1 << 1);
+ } else {
+ log_debug("V1CTL disabled\n");
+ }
+ dm_pci_clrset_config32(dev, 0x114, 0xfe, 0);
+
+ /* Set VCi enable bit */
+ dm_pci_clrset_config32(dev, 0x120, 0, 1U << 31);
+
+ /* Enable HDMI codec */
+ dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 1);
+ dm_pci_clrset_config8(dev, 0x43, 0, 1 << 6);
+
+ /* Additional programming steps */
+ dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 13);
+ dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 10);
+ dm_pci_clrset_config32(dev, 0xd0, 1U << 31, 0);
+
+ /* Additional step on Panther Point */
+ plat = dev_get_parent_platdata(dev);
+ if (plat->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA)
+ dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 17);
+
+ dm_pci_write_config8(dev, 0x3c, 0xa); /* unused? */
+
+ /* Audio Control: Select Azalia mode */
+ dm_pci_clrset_config8(dev, 0x40, 0, 1);
+ dm_pci_clrset_config8(dev, 0x4d, 1 << 7, 0); /* Docking not supported */
+ codec_mask = hda_codec_detect(priv->regs);
+ log_debug("codec_mask = %02x\n", codec_mask);
+
+ if (codec_mask) {
+ ret = hda_codecs_init(dev, priv->regs, codec_mask);
+ if (ret) {
+ log_err("Codec init failed (err=%d)\n", ret);
+ return ret;
+ }
+ }
+
+ /* Enable dynamic clock gating */
+ dm_pci_clrset_config8(dev, 0x43, 7, BIT(2) | BIT(0));
+
+ ret = hda_codec_finish_init(dev);
+ if (ret) {
+ log_debug("Cannot set up HDA codec (err=%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bd82x6x_azalia_setup(struct udevice *dev)
+{
+ return 0;
+}
+
+int bd82x6x_azalia_start_beep(struct udevice *dev, int frequency_hz)
+{
+ return hda_codec_start_beep(dev, frequency_hz);
+}
+
+int bd82x6x_azalia_stop_beep(struct udevice *dev)
+{
+ return hda_codec_stop_beep(dev);
+}
+
+static const struct sound_ops bd82x6x_azalia_ops = {
+ .setup = bd82x6x_azalia_setup,
+ .start_beep = bd82x6x_azalia_start_beep,
+ .stop_beep = bd82x6x_azalia_stop_beep,
+};
+
+static const struct udevice_id bd82x6x_azalia_ids[] = {
+ { .compatible = "intel,hd-audio" },
+ { }
+};
+
+U_BOOT_DRIVER(bd82x6x_azalia_drv) = {
+ .name = "bd82x6x-hda",
+ .id = UCLASS_SOUND,
+ .of_match = bd82x6x_azalia_ids,
+ .probe = bd82x6x_azalia_probe,
+ .ops = &bd82x6x_azalia_ops,
+ .priv_auto_alloc_size = sizeof(struct hda_codec_priv),
+};
diff --git a/drivers/sound/rt5677.c b/drivers/sound/rt5677.c
new file mode 100644
index 0000000..6477605
--- /dev/null
+++ b/drivers/sound/rt5677.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#define LOG_CATEGORY UCLASS_SOUND
+
+#include <common.h>
+#include <audio_codec.h>
+#include <dm.h>
+#include <i2c.h>
+#include "rt5677.h"
+
+struct rt5677_priv {
+ struct udevice *dev;
+};
+
+/* RT5677 has 256 8-bit register addresses, and 16-bit register data */
+struct rt5677_init_reg {
+ u8 reg;
+ u16 val;
+};
+
+static struct rt5677_init_reg init_list[] = {
+ {RT5677_LOUT1, 0x0800},
+ {RT5677_SIDETONE_CTRL, 0x0000},
+ {RT5677_STO1_ADC_DIG_VOL, 0x3F3F},
+ {RT5677_DAC1_DIG_VOL, 0x9090},
+ {RT5677_STO2_ADC_MIXER, 0xA441},
+ {RT5677_STO1_ADC_MIXER, 0x5480},
+ {RT5677_STO1_DAC_MIXER, 0x8A8A},
+ {RT5677_PWR_DIG1, 0x9800}, /* Power up I2S1 */
+ {RT5677_PWR_ANLG1, 0xE9D5},
+ {RT5677_PWR_ANLG2, 0x2CC0},
+ {RT5677_PWR_DSP2, 0x0C00},
+ {RT5677_I2S2_SDP, 0x0000},
+ {RT5677_CLK_TREE_CTRL1, 0x1111},
+ {RT5677_PLL1_CTRL1, 0x0000},
+ {RT5677_PLL1_CTRL2, 0x0000},
+ {RT5677_DIG_MISC, 0x0029},
+ {RT5677_GEN_CTRL1, 0x00FF},
+ {RT5677_GPIO_CTRL2, 0x0020},
+ {RT5677_PWR_DIG2, 0x9024}, /* Power on ADC Stereo Filters */
+ {RT5677_PDM_OUT_CTRL, 0x0088}, /* Unmute PDM, set stereo1 DAC */
+ {RT5677_PDM_DATA_CTRL1, 0x0001}, /* Sysclk to PDM filter divider 2 */
+};
+
+/**
+ * rt5677_i2c_read() - Read a 16-bit register
+ *
+ * @priv: Private driver data
+ * @reg: Register number to read
+ * @returns data read or -ve on error
+ */
+static int rt5677_i2c_read(struct rt5677_priv *priv, uint reg)
+{
+ u8 buf[2];
+ int ret;
+
+ ret = dm_i2c_read(priv->dev, reg, buf, sizeof(u16));
+ if (ret)
+ return ret;
+ return buf[0] << 8 | buf[1];
+}
+
+/**
+ * rt5677_i2c_write() - Write a 16-bit register
+ *
+ * @priv: Private driver data
+ * @reg: Register number to read
+ * @data: Data to write
+ * @returns 0 if OK, -ve on error
+ */
+static int rt5677_i2c_write(struct rt5677_priv *priv, uint reg, uint data)
+{
+ u8 buf[2];
+
+ buf[0] = (data >> 8) & 0xff;
+ buf[1] = data & 0xff;
+
+ return dm_i2c_write(priv->dev, reg, buf, sizeof(u16));
+}
+
+/**
+ * rt5677_bic_or() - Set and clear bits of a codec register
+ *
+ * @priv: Private driver data
+ * @reg: Register number to update
+ * @bic: Mask of bits to clear
+ * @set: Mask of bits to set
+ * @returns 0 if OK, -ve on error
+ *
+ */
+static int rt5677_bic_or(struct rt5677_priv *priv, uint reg, uint bic,
+ uint set)
+{
+ uint old, new_value;
+ int ret;
+
+ old = rt5677_i2c_read(priv, reg);
+ if (old < 0)
+ return old;
+
+ new_value = (old & ~bic) | (set & bic);
+
+ if (old != new_value) {
+ ret = rt5677_i2c_write(priv, reg, new_value);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * rt5677_reg_init() - Initialise codec regs w/static/base values
+ *
+ * @priv: Private driver data
+ * @returns 0 if OK, -ve on error
+ */
+static int rt5677_reg_init(struct rt5677_priv *priv)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(init_list); i++) {
+ ret = rt5677_i2c_write(priv, init_list[i].reg, init_list[i].val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+#ifdef DEBUG
+static void debug_dump_5677_regs(struct rt5677_priv *priv, int swap)
+{
+ uint i, reg_word;
+
+ /* Show all 16-bit codec regs */
+ for (i = 0; i < RT5677_REG_CNT; i++) {
+ if (i % 8 == 0)
+ log_debug("\nMX%02x: ", i);
+
+ rt5677_i2c_read(priv, (u8)i, &reg_word);
+ if (swap)
+ log_debug("%04x ", swap_bytes16(reg_word));
+ else
+ log_debug("%04x ", reg_word);
+ }
+ log_debug("\n");
+
+ /* Show all 16-bit 'private' codec regs */
+ for (i = 0; i < RT5677_PR_REG_CNT; i++) {
+ if (i % 8 == 0)
+ log_debug("\nPR%02x: ", i);
+
+ rt5677_i2c_write(priv, RT5677_PRIV_INDEX, i);
+ rt5677_i2c_read(priv, RT5677_PRIV_DATA, &reg_word);
+ if (swap)
+ log_debug("%04x ", swap_bytes16(reg_word));
+ else
+ log_debug("%04x ", reg_word);
+ }
+ log_debug("\n");
+}
+#endif /* DEBUG */
+
+static int rt5677_hw_params(struct rt5677_priv *priv, uint bits_per_sample)
+{
+ int ret;
+
+ switch (bits_per_sample) {
+ case 16:
+ ret = rt5677_bic_or(priv, RT5677_I2S1_SDP, RT5677_I2S_DL_MASK,
+ 0);
+ if (ret) {
+ log_debug("Error updating I2S1 Interface Ctrl reg\n");
+ return 1;
+ }
+ break;
+ default:
+ log_err("Illegal bits per sample %d\n", bits_per_sample);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * rt5677_set_fmt() - set rt5677 I2S format
+ *
+ * @priv: Private driver data
+ * @returns 0 if OK, -ve on error
+ */
+static int rt5677_set_fmt(struct rt5677_priv *priv)
+{
+ int ret = 0;
+
+ /*
+ * Set format here: Assumes I2S, NB_NF, CBS_CFS
+ *
+ * CBS_CFS (Codec Bit Slave/Codec Frame Slave)
+ */
+ ret = rt5677_bic_or(priv, RT5677_I2S1_SDP, RT5677_I2S_MS_MASK,
+ RT5677_I2S_MS_S);
+
+ /* NB_NF (Normal Bit/Normal Frame) */
+ ret |= rt5677_bic_or(priv, RT5677_I2S1_SDP, RT5677_I2S_BP_MASK,
+ RT5677_I2S_BP_NOR);
+
+ /* I2S mode */
+ ret |= rt5677_bic_or(priv, RT5677_I2S1_SDP, RT5677_I2S_DF_MASK,
+ RT5677_I2S_DF_I2S);
+
+ /* A44: I2S2 (going to speaker amp) is master */
+ ret |= rt5677_bic_or(priv, RT5677_I2S2_SDP, RT5677_I2S_MS_MASK,
+ RT5677_I2S_MS_M);
+
+ if (ret) {
+ log_err("Error updating I2S1 Interface Ctrl reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * rt5677_reset() - reset the audio codec
+ *
+ * @priv: Private driver data
+ * @returns 0 if OK, -ve on error
+ */
+static int rt5677_reset(struct rt5677_priv *priv)
+{
+ int ret;
+
+ /* Reset the codec registers to their defaults */
+ ret = rt5677_i2c_write(priv, RT5677_RESET, RT5677_SW_RESET);
+ if (ret) {
+ log_err("Error resetting codec\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * Initialise rt5677 codec device
+ *
+ * @priv: Private driver data
+ * @returns 0 if OK, -ve on error
+ */
+int rt5677_device_init(struct rt5677_priv *priv)
+{
+ int ret;
+
+ /* Read status reg */
+ ret = rt5677_i2c_read(priv, RT5677_RESET);
+ if (ret < 0)
+ return ret;
+ log_debug("reg 00h, Software Reset & Status = 0x%04x\n", ret);
+
+ /* Reset the codec/regs */
+ ret = rt5677_reset(priv);
+ if (ret)
+ return ret;
+
+ ret = rt5677_i2c_read(priv, RT5677_VENDOR_ID1);
+ if (ret < 0) {
+ log_err("Error reading vendor ID\n");
+ return 1;
+ }
+ log_debug("Hardware ID: %0xX\n", ret);
+
+ ret = rt5677_i2c_read(priv, RT5677_VENDOR_ID2);
+ if (ret < 0) {
+ log_err("Error reading vendor rev\n");
+ return 1;
+ }
+ log_debug("Hardware revision: %04x\n", ret);
+
+ return 0;
+}
+
+static int rt5677_set_params(struct udevice *dev, int interface, int rate,
+ int mclk_freq, int bits_per_sample,
+ uint channels)
+{
+ struct rt5677_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ /* Initialise codec regs w/static/base values, same as Linux driver */
+ ret = rt5677_reg_init(priv);
+ if (ret)
+ return ret;
+
+ ret = rt5677_hw_params(priv, bits_per_sample);
+ if (ret)
+ return ret;
+
+ ret = rt5677_set_fmt(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rt5677_probe(struct udevice *dev)
+{
+ struct rt5677_priv *priv = dev_get_priv(dev);
+
+ priv->dev = dev;
+
+ return rt5677_device_init(priv);
+}
+
+static const struct audio_codec_ops rt5677_ops = {
+ .set_params = rt5677_set_params,
+};
+
+static const struct udevice_id rt5677_ids[] = {
+ { .compatible = "realtek,rt5677" },
+ { }
+};
+
+U_BOOT_DRIVER(rt5677_drv) = {
+ .name = "rt5677",
+ .id = UCLASS_AUDIO_CODEC,
+ .of_match = rt5677_ids,
+ .ops = &rt5677_ops,
+ .probe = rt5677_probe,
+ .priv_auto_alloc_size = sizeof(struct rt5677_priv),
+};
diff --git a/drivers/sound/rt5677.h b/drivers/sound/rt5677.h
new file mode 100644
index 0000000..1ce3cec
--- /dev/null
+++ b/drivers/sound/rt5677.h
@@ -0,0 +1,1428 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * rt5677.h -- RealTek ALC5677 ALSA SoC Audio driver
+ *
+ * Copyright 2013 Realtek Semiconductor Corp.
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ *
+ * Based on the file by the same name in Chromium OS dc
+ */
+
+#ifndef __DRIVERS_SOUND_RT5677_H__
+#define __DRIVERS_SOUND_RT5677_H__
+
+/*
+ * RT5677 Registers Definition
+ */
+
+/* Info */
+#define RT5677_RESET 0x00
+#define RT5677_VENDOR_ID 0xfd
+#define RT5677_VENDOR_ID1 0xfe
+#define RT5677_VENDOR_ID2 0xff
+
+#define RT5677_REG_CNT (RT5677_VENDOR_ID2 + 1)
+#define RT5677_PR_REG_CNT 255
+
+/* I/O - Output */
+#define RT5677_LOUT1 0x01
+/* I/O - Input */
+#define RT5677_IN1 0x03
+#define RT5677_MICBIAS 0x04
+/* I/O - SLIMBus */
+#define RT5677_SLIMBUS_PARAM 0x07
+#define RT5677_SLIMBUS_RX 0x08
+#define RT5677_SLIMBUS_CTRL 0x09
+/* I/O */
+#define RT5677_SIDETONE_CTRL 0x13
+/* I/O - ADC/DAC */
+#define RT5677_ANA_DAC1_2_3_SRC 0x15
+#define RT5677_IF_DSP_DAC3_4_MIXER 0x16
+#define RT5677_DAC4_DIG_VOL 0x17
+#define RT5677_DAC3_DIG_VOL 0x18
+#define RT5677_DAC1_DIG_VOL 0x19
+#define RT5677_DAC2_DIG_VOL 0x1a
+#define RT5677_IF_DSP_DAC2_MIXER 0x1b
+#define RT5677_STO1_ADC_DIG_VOL 0x1c
+#define RT5677_MONO_ADC_DIG_VOL 0x1d
+#define RT5677_STO1_2_ADC_BST 0x1e
+#define RT5677_STO2_ADC_DIG_VOL 0x1f
+/* Mixer - D-D */
+#define RT5677_ADC_BST_CTRL2 0x20
+#define RT5677_STO3_4_ADC_BST 0x21
+#define RT5677_STO3_ADC_DIG_VOL 0x22
+#define RT5677_STO4_ADC_DIG_VOL 0x23
+#define RT5677_STO4_ADC_MIXER 0x24
+#define RT5677_STO3_ADC_MIXER 0x25
+#define RT5677_STO2_ADC_MIXER 0x26
+#define RT5677_STO1_ADC_MIXER 0x27
+#define RT5677_MONO_ADC_MIXER 0x28
+#define RT5677_ADC_IF_DSP_DAC1_MIXER 0x29
+#define RT5677_STO1_DAC_MIXER 0x2a
+#define RT5677_MONO_DAC_MIXER 0x2b
+#define RT5677_DD1_MIXER 0x2c
+#define RT5677_DD2_MIXER 0x2d
+#define RT5677_IF3_DATA 0x2f
+#define RT5677_IF4_DATA 0x30
+/* Mixer - PDM */
+#define RT5677_PDM_OUT_CTRL 0x31
+#define RT5677_PDM_DATA_CTRL1 0x32
+#define RT5677_PDM_DATA_CTRL2 0x33
+#define RT5677_PDM1_DATA_CTRL2 0x34
+#define RT5677_PDM1_DATA_CTRL3 0x35
+#define RT5677_PDM1_DATA_CTRL4 0x36
+#define RT5677_PDM2_DATA_CTRL2 0x37
+#define RT5677_PDM2_DATA_CTRL3 0x38
+#define RT5677_PDM2_DATA_CTRL4 0x39
+/* TDM */
+#define RT5677_TDM1_CTRL1 0x3b
+#define RT5677_TDM1_CTRL2 0x3c
+#define RT5677_TDM1_CTRL3 0x3d
+#define RT5677_TDM1_CTRL4 0x3e
+#define RT5677_TDM1_CTRL5 0x3f
+#define RT5677_TDM2_CTRL1 0x40
+#define RT5677_TDM2_CTRL2 0x41
+#define RT5677_TDM2_CTRL3 0x42
+#define RT5677_TDM2_CTRL4 0x43
+#define RT5677_TDM2_CTRL5 0x44
+/* I2C_MASTER_CTRL */
+#define RT5677_I2C_MASTER_CTRL1 0x47
+#define RT5677_I2C_MASTER_CTRL2 0x48
+#define RT5677_I2C_MASTER_CTRL3 0x49
+#define RT5677_I2C_MASTER_CTRL4 0x4a
+#define RT5677_I2C_MASTER_CTRL5 0x4b
+#define RT5677_I2C_MASTER_CTRL6 0x4c
+#define RT5677_I2C_MASTER_CTRL7 0x4d
+#define RT5677_I2C_MASTER_CTRL8 0x4e
+/* DMIC */
+#define RT5677_DMIC_CTRL1 0x50
+#define RT5677_DMIC_CTRL2 0x51
+/* Haptic Generator */
+#define RT5677_HAP_GENE_CTRL1 0x56
+#define RT5677_HAP_GENE_CTRL2 0x57
+#define RT5677_HAP_GENE_CTRL3 0x58
+#define RT5677_HAP_GENE_CTRL4 0x59
+#define RT5677_HAP_GENE_CTRL5 0x5a
+#define RT5677_HAP_GENE_CTRL6 0x5b
+#define RT5677_HAP_GENE_CTRL7 0x5c
+#define RT5677_HAP_GENE_CTRL8 0x5d
+#define RT5677_HAP_GENE_CTRL9 0x5e
+#define RT5677_HAP_GENE_CTRL10 0x5f
+/* Power */
+#define RT5677_PWR_DIG1 0x61
+#define RT5677_PWR_DIG2 0x62
+#define RT5677_PWR_ANLG1 0x63
+#define RT5677_PWR_ANLG2 0x64
+#define RT5677_PWR_DSP1 0x65
+#define RT5677_PWR_DSP_ST 0x66
+#define RT5677_PWR_DSP2 0x67
+#define RT5677_ADC_DAC_HPF_CTRL1 0x68
+/* Private Register Control */
+#define RT5677_PRIV_INDEX 0x6a
+#define RT5677_PRIV_DATA 0x6c
+/* Format - ADC/DAC */
+#define RT5677_I2S4_SDP 0x6f
+#define RT5677_I2S1_SDP 0x70
+#define RT5677_I2S2_SDP 0x71
+#define RT5677_I2S3_SDP 0x72
+#define RT5677_CLK_TREE_CTRL1 0x73
+#define RT5677_CLK_TREE_CTRL2 0x74
+#define RT5677_CLK_TREE_CTRL3 0x75
+/* Function - Analog */
+#define RT5677_PLL1_CTRL1 0x7a
+#define RT5677_PLL1_CTRL2 0x7b
+#define RT5677_PLL2_CTRL1 0x7c
+#define RT5677_PLL2_CTRL2 0x7d
+#define RT5677_GLB_CLK1 0x80
+#define RT5677_GLB_CLK2 0x81
+#define RT5677_ASRC_1 0x83
+#define RT5677_ASRC_2 0x84
+#define RT5677_ASRC_3 0x85
+#define RT5677_ASRC_4 0x86
+#define RT5677_ASRC_5 0x87
+#define RT5677_ASRC_6 0x88
+#define RT5677_ASRC_7 0x89
+#define RT5677_ASRC_8 0x8a
+#define RT5677_ASRC_9 0x8b
+#define RT5677_ASRC_10 0x8c
+#define RT5677_ASRC_11 0x8d
+#define RT5677_ASRC_12 0x8e
+#define RT5677_ASRC_13 0x8f
+#define RT5677_ASRC_14 0x90
+#define RT5677_ASRC_15 0x91
+#define RT5677_ASRC_16 0x92
+#define RT5677_ASRC_17 0x93
+#define RT5677_ASRC_18 0x94
+#define RT5677_ASRC_19 0x95
+#define RT5677_ASRC_20 0x97
+#define RT5677_ASRC_21 0x98
+#define RT5677_ASRC_22 0x99
+#define RT5677_ASRC_23 0x9a
+#define RT5677_VAD_CTRL1 0x9c
+#define RT5677_VAD_CTRL2 0x9d
+#define RT5677_VAD_CTRL3 0x9e
+#define RT5677_VAD_CTRL4 0x9f
+#define RT5677_VAD_CTRL5 0xa0
+/* Function - Digital */
+#define RT5677_DSP_INB_CTRL1 0xa3
+#define RT5677_DSP_INB_CTRL2 0xa4
+#define RT5677_DSP_IN_OUTB_CTRL 0xa5
+#define RT5677_DSP_OUTB0_1_DIG_VOL 0xa6
+#define RT5677_DSP_OUTB2_3_DIG_VOL 0xa7
+#define RT5677_DSP_OUTB4_5_DIG_VOL 0xa8
+#define RT5677_DSP_OUTB6_7_DIG_VOL 0xa9
+#define RT5677_ADC_EQ_CTRL1 0xae
+#define RT5677_ADC_EQ_CTRL2 0xaf
+#define RT5677_EQ_CTRL1 0xb0
+#define RT5677_EQ_CTRL2 0xb1
+#define RT5677_EQ_CTRL3 0xb2
+#define RT5677_SOFT_VOL_ZERO_CROSS1 0xb3
+#define RT5677_JD_CTRL1 0xb5
+#define RT5677_JD_CTRL2 0xb6
+#define RT5677_JD_CTRL3 0xb8
+#define RT5677_IRQ_CTRL1 0xbd
+#define RT5677_IRQ_CTRL2 0xbe
+#define RT5677_GPIO_ST 0xbf
+#define RT5677_GPIO_CTRL1 0xc0
+#define RT5677_GPIO_CTRL2 0xc1
+#define RT5677_GPIO_CTRL3 0xc2
+#define RT5677_STO1_ADC_HI_FILTER1 0xc5
+#define RT5677_STO1_ADC_HI_FILTER2 0xc6
+#define RT5677_MONO_ADC_HI_FILTER1 0xc7
+#define RT5677_MONO_ADC_HI_FILTER2 0xc8
+#define RT5677_STO2_ADC_HI_FILTER1 0xc9
+#define RT5677_STO2_ADC_HI_FILTER2 0xca
+#define RT5677_STO3_ADC_HI_FILTER1 0xcb
+#define RT5677_STO3_ADC_HI_FILTER2 0xcc
+#define RT5677_STO4_ADC_HI_FILTER1 0xcd
+#define RT5677_STO4_ADC_HI_FILTER2 0xce
+#define RT5677_MB_DRC_CTRL1 0xd0
+#define RT5677_DRC1_CTRL1 0xd2
+#define RT5677_DRC1_CTRL2 0xd3
+#define RT5677_DRC1_CTRL3 0xd4
+#define RT5677_DRC1_CTRL4 0xd5
+#define RT5677_DRC1_CTRL5 0xd6
+#define RT5677_DRC1_CTRL6 0xd7
+#define RT5677_DRC2_CTRL1 0xd8
+#define RT5677_DRC2_CTRL2 0xd9
+#define RT5677_DRC2_CTRL3 0xda
+#define RT5677_DRC2_CTRL4 0xdb
+#define RT5677_DRC2_CTRL5 0xdc
+#define RT5677_DRC2_CTRL6 0xdd
+#define RT5677_DRC1_HL_CTRL1 0xde
+#define RT5677_DRC1_HL_CTRL2 0xdf
+#define RT5677_DRC2_HL_CTRL1 0xe0
+#define RT5677_DRC2_HL_CTRL2 0xe1
+#define RT5677_DSP_INB1_SRC_CTRL1 0xe3
+#define RT5677_DSP_INB1_SRC_CTRL2 0xe4
+#define RT5677_DSP_INB1_SRC_CTRL3 0xe5
+#define RT5677_DSP_INB1_SRC_CTRL4 0xe6
+#define RT5677_DSP_INB2_SRC_CTRL1 0xe7
+#define RT5677_DSP_INB2_SRC_CTRL2 0xe8
+#define RT5677_DSP_INB2_SRC_CTRL3 0xe9
+#define RT5677_DSP_INB2_SRC_CTRL4 0xea
+#define RT5677_DSP_INB3_SRC_CTRL1 0xeb
+#define RT5677_DSP_INB3_SRC_CTRL2 0xec
+#define RT5677_DSP_INB3_SRC_CTRL3 0xed
+#define RT5677_DSP_INB3_SRC_CTRL4 0xee
+#define RT5677_DSP_OUTB1_SRC_CTRL1 0xef
+#define RT5677_DSP_OUTB1_SRC_CTRL2 0xf0
+#define RT5677_DSP_OUTB1_SRC_CTRL3 0xf1
+#define RT5677_DSP_OUTB1_SRC_CTRL4 0xf2
+#define RT5677_DSP_OUTB2_SRC_CTRL1 0xf3
+#define RT5677_DSP_OUTB2_SRC_CTRL2 0xf4
+#define RT5677_DSP_OUTB2_SRC_CTRL3 0xf5
+#define RT5677_DSP_OUTB2_SRC_CTRL4 0xf6
+
+/* Virtual DSP Mixer Control */
+#define RT5677_DSP_OUTB_0123_MIXER_CTRL 0xf7
+#define RT5677_DSP_OUTB_45_MIXER_CTRL 0xf8
+#define RT5677_DSP_OUTB_67_MIXER_CTRL 0xf9
+
+/* General Control */
+#define RT5677_DIG_MISC 0xfa
+#define RT5677_GEN_CTRL1 0xfb
+#define RT5677_GEN_CTRL2 0xfc
+
+/* DSP Mode I2C Control*/
+#define RT5677_DSP_I2C_OP_CODE 0x00
+#define RT5677_DSP_I2C_ADDR_LSB 0x01
+#define RT5677_DSP_I2C_ADDR_MSB 0x02
+#define RT5677_DSP_I2C_DATA_LSB 0x03
+#define RT5677_DSP_I2C_DATA_MSB 0x04
+
+/* Index of Codec Private Register definition */
+#define RT5677_PR_DRC1_CTRL_1 0x01
+#define RT5677_PR_DRC1_CTRL_2 0x02
+#define RT5677_PR_DRC1_CTRL_3 0x03
+#define RT5677_PR_DRC1_CTRL_4 0x04
+#define RT5677_PR_DRC1_CTRL_5 0x05
+#define RT5677_PR_DRC1_CTRL_6 0x06
+#define RT5677_PR_DRC1_CTRL_7 0x07
+#define RT5677_PR_DRC2_CTRL_1 0x08
+#define RT5677_PR_DRC2_CTRL_2 0x09
+#define RT5677_PR_DRC2_CTRL_3 0x0a
+#define RT5677_PR_DRC2_CTRL_4 0x0b
+#define RT5677_PR_DRC2_CTRL_5 0x0c
+#define RT5677_PR_DRC2_CTRL_6 0x0d
+#define RT5677_PR_DRC2_CTRL_7 0x0e
+#define RT5677_BIAS_CUR1 0x10
+#define RT5677_BIAS_CUR2 0x12
+#define RT5677_BIAS_CUR3 0x13
+#define RT5677_BIAS_CUR4 0x14
+#define RT5677_BIAS_CUR5 0x15
+#define RT5677_VREF_LOUT_CTRL 0x17
+#define RT5677_DIG_VOL_CTRL1 0x1a
+#define RT5677_DIG_VOL_CTRL2 0x1b
+#define RT5677_ANA_ADC_GAIN_CTRL 0x1e
+#define RT5677_VAD_SRAM_TEST1 0x20
+#define RT5677_VAD_SRAM_TEST2 0x21
+#define RT5677_VAD_SRAM_TEST3 0x22
+#define RT5677_VAD_SRAM_TEST4 0x23
+#define RT5677_PAD_DRV_CTRL 0x26
+#define RT5677_DIG_IN_PIN_ST_CTRL1 0x29
+#define RT5677_DIG_IN_PIN_ST_CTRL2 0x2a
+#define RT5677_DIG_IN_PIN_ST_CTRL3 0x2b
+#define RT5677_PLL1_INT 0x38
+#define RT5677_PLL2_INT 0x39
+#define RT5677_TEST_CTRL1 0x3a
+#define RT5677_TEST_CTRL2 0x3b
+#define RT5677_TEST_CTRL3 0x3c
+#define RT5677_CHOP_DAC_ADC 0x3d
+#define RT5677_SOFT_DEPOP_DAC_CLK_CTRL 0x3e
+#define RT5677_CROSS_OVER_FILTER1 0x90
+#define RT5677_CROSS_OVER_FILTER2 0x91
+#define RT5677_CROSS_OVER_FILTER3 0x92
+#define RT5677_CROSS_OVER_FILTER4 0x93
+#define RT5677_CROSS_OVER_FILTER5 0x94
+#define RT5677_CROSS_OVER_FILTER6 0x95
+#define RT5677_CROSS_OVER_FILTER7 0x96
+#define RT5677_CROSS_OVER_FILTER8 0x97
+#define RT5677_CROSS_OVER_FILTER9 0x98
+#define RT5677_CROSS_OVER_FILTER10 0x99
+
+/* global definition */
+#define RT5677_L_MUTE (0x1 << 15)
+#define RT5677_L_MUTE_SFT 15
+#define RT5677_VOL_L_MUTE (0x1 << 14)
+#define RT5677_VOL_L_SFT 14
+#define RT5677_R_MUTE (0x1 << 7)
+#define RT5677_R_MUTE_SFT 7
+#define RT5677_VOL_R_MUTE (0x1 << 6)
+#define RT5677_VOL_R_SFT 6
+#define RT5677_L_VOL_MASK (0x3f << 8)
+#define RT5677_L_VOL_SFT 8
+#define RT5677_R_VOL_MASK (0x3f)
+#define RT5677_R_VOL_SFT 0
+
+/* LOUT1 Control (0x01) */
+#define RT5677_LOUT1_L_MUTE (0x1 << 15)
+#define RT5677_LOUT1_L_MUTE_SFT (15)
+#define RT5677_LOUT1_L_DF (0x1 << 14)
+#define RT5677_LOUT1_L_DF_SFT (14)
+#define RT5677_LOUT2_L_MUTE (0x1 << 13)
+#define RT5677_LOUT2_L_MUTE_SFT (13)
+#define RT5677_LOUT2_L_DF (0x1 << 12)
+#define RT5677_LOUT2_L_DF_SFT (12)
+#define RT5677_LOUT3_L_MUTE (0x1 << 11)
+#define RT5677_LOUT3_L_MUTE_SFT (11)
+#define RT5677_LOUT3_L_DF (0x1 << 10)
+#define RT5677_LOUT3_L_DF_SFT (10)
+#define RT5677_LOUT1_ENH_DRV (0x1 << 9)
+#define RT5677_LOUT1_ENH_DRV_SFT (9)
+#define RT5677_LOUT2_ENH_DRV (0x1 << 8)
+#define RT5677_LOUT2_ENH_DRV_SFT (8)
+#define RT5677_LOUT3_ENH_DRV (0x1 << 7)
+#define RT5677_LOUT3_ENH_DRV_SFT (7)
+
+/* IN1 Control (0x03) */
+#define RT5677_BST_MASK1 (0xf << 12)
+#define RT5677_BST_SFT1 12
+#define RT5677_BST_MASK2 (0xf << 8)
+#define RT5677_BST_SFT2 8
+#define RT5677_IN_DF1 (0x1 << 7)
+#define RT5677_IN_DF1_SFT 7
+#define RT5677_IN_DF2 (0x1 << 6)
+#define RT5677_IN_DF2_SFT 6
+
+/* Micbias Control (0x04) */
+#define RT5677_MICBIAS1_OUTVOLT_MASK (0x1 << 15)
+#define RT5677_MICBIAS1_OUTVOLT_SFT (15)
+#define RT5677_MICBIAS1_OUTVOLT_2_7V (0x0 << 15)
+#define RT5677_MICBIAS1_OUTVOLT_2_25V (0x1 << 15)
+#define RT5677_MICBIAS1_CTRL_VDD_MASK (0x1 << 14)
+#define RT5677_MICBIAS1_CTRL_VDD_SFT (14)
+#define RT5677_MICBIAS1_CTRL_VDD_1_8V (0x0 << 14)
+#define RT5677_MICBIAS1_CTRL_VDD_3_3V (0x1 << 14)
+#define RT5677_MICBIAS1_OVCD_MASK (0x1 << 11)
+#define RT5677_MICBIAS1_OVCD_SHIFT (11)
+#define RT5677_MICBIAS1_OVCD_DIS (0x0 << 11)
+#define RT5677_MICBIAS1_OVCD_EN (0x1 << 11)
+#define RT5677_MICBIAS1_OVTH_MASK (0x3 << 9)
+#define RT5677_MICBIAS1_OVTH_SFT 9
+#define RT5677_MICBIAS1_OVTH_640UA (0x0 << 9)
+#define RT5677_MICBIAS1_OVTH_1280UA (0x1 << 9)
+#define RT5677_MICBIAS1_OVTH_1920UA (0x2 << 9)
+
+/* SLIMbus Parameter (0x07) */
+
+/* SLIMbus Rx (0x08) */
+#define RT5677_SLB_ADC4_MASK (0x3 << 6)
+#define RT5677_SLB_ADC4_SFT 6
+#define RT5677_SLB_ADC3_MASK (0x3 << 4)
+#define RT5677_SLB_ADC3_SFT 4
+#define RT5677_SLB_ADC2_MASK (0x3 << 2)
+#define RT5677_SLB_ADC2_SFT 2
+#define RT5677_SLB_ADC1_MASK (0x3 << 0)
+#define RT5677_SLB_ADC1_SFT 0
+
+/* SLIMBus control (0x09) */
+
+/* Sidetone Control (0x13) */
+#define RT5677_ST_HPF_SEL_MASK (0x7 << 13)
+#define RT5677_ST_HPF_SEL_SFT 13
+#define RT5677_ST_HPF_PATH (0x1 << 12)
+#define RT5677_ST_HPF_PATH_SFT 12
+#define RT5677_ST_SEL_MASK (0x7 << 9)
+#define RT5677_ST_SEL_SFT 9
+#define RT5677_ST_EN (0x1 << 6)
+#define RT5677_ST_EN_SFT 6
+
+/* Analog DAC1/2/3 Source Control (0x15) */
+#define RT5677_ANA_DAC3_SRC_SEL_MASK (0x3 << 4)
+#define RT5677_ANA_DAC3_SRC_SEL_SFT 4
+#define RT5677_ANA_DAC1_2_SRC_SEL_MASK (0x3 << 0)
+#define RT5677_ANA_DAC1_2_SRC_SEL_SFT 0
+
+/* IF/DSP to DAC3/4 Mixer Control (0x16) */
+#define RT5677_M_DAC4_L_VOL (0x1 << 15)
+#define RT5677_M_DAC4_L_VOL_SFT 15
+#define RT5677_SEL_DAC4_L_SRC_MASK (0x7 << 12)
+#define RT5677_SEL_DAC4_L_SRC_SFT 12
+#define RT5677_M_DAC4_R_VOL (0x1 << 11)
+#define RT5677_M_DAC4_R_VOL_SFT 11
+#define RT5677_SEL_DAC4_R_SRC_MASK (0x7 << 8)
+#define RT5677_SEL_DAC4_R_SRC_SFT 8
+#define RT5677_M_DAC3_L_VOL (0x1 << 7)
+#define RT5677_M_DAC3_L_VOL_SFT 7
+#define RT5677_SEL_DAC3_L_SRC_MASK (0x7 << 4)
+#define RT5677_SEL_DAC3_L_SRC_SFT 4
+#define RT5677_M_DAC3_R_VOL (0x1 << 3)
+#define RT5677_M_DAC3_R_VOL_SFT 3
+#define RT5677_SEL_DAC3_R_SRC_MASK (0x7 << 0)
+#define RT5677_SEL_DAC3_R_SRC_SFT 0
+
+/* DAC4 Digital Volume (0x17) */
+#define RT5677_DAC4_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC4_L_VOL_SFT 8
+#define RT5677_DAC4_R_VOL_MASK (0xff)
+#define RT5677_DAC4_R_VOL_SFT 0
+
+/* DAC3 Digital Volume (0x18) */
+#define RT5677_DAC3_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC3_L_VOL_SFT 8
+#define RT5677_DAC3_R_VOL_MASK (0xff)
+#define RT5677_DAC3_R_VOL_SFT 0
+
+/* DAC3 Digital Volume (0x19) */
+#define RT5677_DAC1_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC1_L_VOL_SFT 8
+#define RT5677_DAC1_R_VOL_MASK (0xff)
+#define RT5677_DAC1_R_VOL_SFT 0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5677_DAC2_L_VOL_MASK (0xff << 8)
+#define RT5677_DAC2_L_VOL_SFT 8
+#define RT5677_DAC2_R_VOL_MASK (0xff)
+#define RT5677_DAC2_R_VOL_SFT 0
+
+/* IF/DSP to DAC2 Mixer Control (0x1b) */
+#define RT5677_M_DAC2_L_VOL (0x1 << 7)
+#define RT5677_M_DAC2_L_VOL_SFT 7
+#define RT5677_SEL_DAC2_L_SRC_MASK (0x7 << 4)
+#define RT5677_SEL_DAC2_L_SRC_SFT 4
+#define RT5677_M_DAC2_R_VOL (0x1 << 3)
+#define RT5677_M_DAC2_R_VOL_SFT 3
+#define RT5677_SEL_DAC2_R_SRC_MASK (0x7 << 0)
+#define RT5677_SEL_DAC2_R_SRC_SFT 0
+
+/* Stereo1 ADC Digital Volume Control (0x1c) */
+#define RT5677_STO1_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO1_ADC_L_VOL_SFT 8
+#define RT5677_STO1_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO1_ADC_R_VOL_SFT 0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5677_MONO_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_MONO_ADC_L_VOL_SFT 8
+#define RT5677_MONO_ADC_R_VOL_MASK (0x7f)
+#define RT5677_MONO_ADC_R_VOL_SFT 0
+
+/* Stereo 1/2 ADC Boost Gain Control (0x1e) */
+#define RT5677_STO1_ADC_L_BST_MASK (0x3 << 14)
+#define RT5677_STO1_ADC_L_BST_SFT 14
+#define RT5677_STO1_ADC_R_BST_MASK (0x3 << 12)
+#define RT5677_STO1_ADC_R_BST_SFT 12
+#define RT5677_STO1_ADC_COMP_MASK (0x3 << 10)
+#define RT5677_STO1_ADC_COMP_SFT 10
+#define RT5677_STO2_ADC_L_BST_MASK (0x3 << 8)
+#define RT5677_STO2_ADC_L_BST_SFT 8
+#define RT5677_STO2_ADC_R_BST_MASK (0x3 << 6)
+#define RT5677_STO2_ADC_R_BST_SFT 6
+#define RT5677_STO2_ADC_COMP_MASK (0x3 << 4)
+#define RT5677_STO2_ADC_COMP_SFT 4
+
+/* Stereo2 ADC Digital Volume Control (0x1f) */
+#define RT5677_STO2_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO2_ADC_L_VOL_SFT 8
+#define RT5677_STO2_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO2_ADC_R_VOL_SFT 0
+
+/* ADC Boost Gain Control 2 (0x20) */
+#define RT5677_MONO_ADC_L_BST_MASK (0x3 << 14)
+#define RT5677_MONO_ADC_L_BST_SFT 14
+#define RT5677_MONO_ADC_R_BST_MASK (0x3 << 12)
+#define RT5677_MONO_ADC_R_BST_SFT 12
+#define RT5677_MONO_ADC_COMP_MASK (0x3 << 10)
+#define RT5677_MONO_ADC_COMP_SFT 10
+
+/* Stereo 3/4 ADC Boost Gain Control (0x21) */
+#define RT5677_STO3_ADC_L_BST_MASK (0x3 << 14)
+#define RT5677_STO3_ADC_L_BST_SFT 14
+#define RT5677_STO3_ADC_R_BST_MASK (0x3 << 12)
+#define RT5677_STO3_ADC_R_BST_SFT 12
+#define RT5677_STO3_ADC_COMP_MASK (0x3 << 10)
+#define RT5677_STO3_ADC_COMP_SFT 10
+#define RT5677_STO4_ADC_L_BST_MASK (0x3 << 8)
+#define RT5677_STO4_ADC_L_BST_SFT 8
+#define RT5677_STO4_ADC_R_BST_MASK (0x3 << 6)
+#define RT5677_STO4_ADC_R_BST_SFT 6
+#define RT5677_STO4_ADC_COMP_MASK (0x3 << 4)
+#define RT5677_STO4_ADC_COMP_SFT 4
+
+/* Stereo3 ADC Digital Volume Control (0x22) */
+#define RT5677_STO3_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO3_ADC_L_VOL_SFT 8
+#define RT5677_STO3_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO3_ADC_R_VOL_SFT 0
+
+/* Stereo4 ADC Digital Volume Control (0x23) */
+#define RT5677_STO4_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5677_STO4_ADC_L_VOL_SFT 8
+#define RT5677_STO4_ADC_R_VOL_MASK (0x7f)
+#define RT5677_STO4_ADC_R_VOL_SFT 0
+
+/* Stereo4 ADC Mixer control (0x24) */
+#define RT5677_M_STO4_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO4_ADC_L2_SFT 15
+#define RT5677_M_STO4_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO4_ADC_L1_SFT 14
+#define RT5677_SEL_STO4_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO4_ADC1_SFT 12
+#define RT5677_SEL_STO4_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO4_ADC2_SFT 10
+#define RT5677_SEL_STO4_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO4_DMIC_SFT 8
+#define RT5677_M_STO4_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO4_ADC_R1_SFT 7
+#define RT5677_M_STO4_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO4_ADC_R2_SFT 6
+
+/* Stereo3 ADC Mixer control (0x25) */
+#define RT5677_M_STO3_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO3_ADC_L2_SFT 15
+#define RT5677_M_STO3_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO3_ADC_L1_SFT 14
+#define RT5677_SEL_STO3_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO3_ADC1_SFT 12
+#define RT5677_SEL_STO3_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO3_ADC2_SFT 10
+#define RT5677_SEL_STO3_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO3_DMIC_SFT 8
+#define RT5677_M_STO3_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO3_ADC_R1_SFT 7
+#define RT5677_M_STO3_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO3_ADC_R2_SFT 6
+
+/* Stereo2 ADC Mixer Control (0x26) */
+#define RT5677_M_STO2_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO2_ADC_L2_SFT 15
+#define RT5677_M_STO2_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO2_ADC_L1_SFT 14
+#define RT5677_SEL_STO2_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO2_ADC1_SFT 12
+#define RT5677_SEL_STO2_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO2_ADC2_SFT 10
+#define RT5677_SEL_STO2_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO2_DMIC_SFT 8
+#define RT5677_M_STO2_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO2_ADC_R1_SFT 7
+#define RT5677_M_STO2_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO2_ADC_R2_SFT 6
+#define RT5677_SEL_STO2_LR_MIX_MASK (0x1 << 0)
+#define RT5677_SEL_STO2_LR_MIX_SFT 0
+#define RT5677_SEL_STO2_LR_MIX_L (0x0 << 0)
+#define RT5677_SEL_STO2_LR_MIX_LR (0x1 << 0)
+
+/* Stereo1 ADC Mixer control (0x27) */
+#define RT5677_M_STO1_ADC_L2 (0x1 << 15)
+#define RT5677_M_STO1_ADC_L2_SFT 15
+#define RT5677_M_STO1_ADC_L1 (0x1 << 14)
+#define RT5677_M_STO1_ADC_L1_SFT 14
+#define RT5677_SEL_STO1_ADC1_MASK (0x3 << 12)
+#define RT5677_SEL_STO1_ADC1_SFT 12
+#define RT5677_SEL_STO1_ADC2_MASK (0x3 << 10)
+#define RT5677_SEL_STO1_ADC2_SFT 10
+#define RT5677_SEL_STO1_DMIC_MASK (0x3 << 8)
+#define RT5677_SEL_STO1_DMIC_SFT 8
+#define RT5677_M_STO1_ADC_R1 (0x1 << 7)
+#define RT5677_M_STO1_ADC_R1_SFT 7
+#define RT5677_M_STO1_ADC_R2 (0x1 << 6)
+#define RT5677_M_STO1_ADC_R2_SFT 6
+
+/* Mono ADC Mixer control (0x28) */
+#define RT5677_M_MONO_ADC_L2 (0x1 << 15)
+#define RT5677_M_MONO_ADC_L2_SFT 15
+#define RT5677_M_MONO_ADC_L1 (0x1 << 14)
+#define RT5677_M_MONO_ADC_L1_SFT 14
+#define RT5677_SEL_MONO_ADC_L1_MASK (0x3 << 12)
+#define RT5677_SEL_MONO_ADC_L1_SFT 12
+#define RT5677_SEL_MONO_ADC_L2_MASK (0x3 << 10)
+#define RT5677_SEL_MONO_ADC_L2_SFT 10
+#define RT5677_SEL_MONO_DMIC_L_MASK (0x3 << 8)
+#define RT5677_SEL_MONO_DMIC_L_SFT 8
+#define RT5677_M_MONO_ADC_R1 (0x1 << 7)
+#define RT5677_M_MONO_ADC_R1_SFT 7
+#define RT5677_M_MONO_ADC_R2 (0x1 << 6)
+#define RT5677_M_MONO_ADC_R2_SFT 6
+#define RT5677_SEL_MONO_ADC_R1_MASK (0x3 << 4)
+#define RT5677_SEL_MONO_ADC_R1_SFT 4
+#define RT5677_SEL_MONO_ADC_R2_MASK (0x3 << 2)
+#define RT5677_SEL_MONO_ADC_R2_SFT 2
+#define RT5677_SEL_MONO_DMIC_R_MASK (0x3 << 0)
+#define RT5677_SEL_MONO_DMIC_R_SFT 0
+
+/* ADC/IF/DSP to DAC1 Mixer control (0x29) */
+#define RT5677_M_ADDA_MIXER1_L (0x1 << 15)
+#define RT5677_M_ADDA_MIXER1_L_SFT 15
+#define RT5677_M_DAC1_L (0x1 << 14)
+#define RT5677_M_DAC1_L_SFT 14
+#define RT5677_DAC1_L_SEL_MASK (0x7 << 8)
+#define RT5677_DAC1_L_SEL_SFT 8
+#define RT5677_M_ADDA_MIXER1_R (0x1 << 7)
+#define RT5677_M_ADDA_MIXER1_R_SFT 7
+#define RT5677_M_DAC1_R (0x1 << 6)
+#define RT5677_M_DAC1_R_SFT 6
+#define RT5677_ADDA1_SEL_MASK (0x3 << 0)
+#define RT5677_ADDA1_SEL_SFT 0
+
+/* Stereo1 DAC Mixer L/R Control (0x2a) */
+#define RT5677_M_ST_DAC1_L (0x1 << 15)
+#define RT5677_M_ST_DAC1_L_SFT 15
+#define RT5677_M_DAC1_L_STO_L (0x1 << 13)
+#define RT5677_M_DAC1_L_STO_L_SFT 13
+#define RT5677_DAC1_L_STO_L_VOL_MASK (0x1 << 12)
+#define RT5677_DAC1_L_STO_L_VOL_SFT 12
+#define RT5677_M_DAC2_L_STO_L (0x1 << 11)
+#define RT5677_M_DAC2_L_STO_L_SFT 11
+#define RT5677_DAC2_L_STO_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC2_L_STO_L_VOL_SFT 10
+#define RT5677_M_DAC1_R_STO_L (0x1 << 9)
+#define RT5677_M_DAC1_R_STO_L_SFT 9
+#define RT5677_DAC1_R_STO_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC1_R_STO_L_VOL_SFT 8
+#define RT5677_M_ST_DAC1_R (0x1 << 7)
+#define RT5677_M_ST_DAC1_R_SFT 7
+#define RT5677_M_DAC1_R_STO_R (0x1 << 5)
+#define RT5677_M_DAC1_R_STO_R_SFT 5
+#define RT5677_DAC1_R_STO_R_VOL_MASK (0x1 << 4)
+#define RT5677_DAC1_R_STO_R_VOL_SFT 4
+#define RT5677_M_DAC2_R_STO_R (0x1 << 3)
+#define RT5677_M_DAC2_R_STO_R_SFT 3
+#define RT5677_DAC2_R_STO_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC2_R_STO_R_VOL_SFT 2
+#define RT5677_M_DAC1_L_STO_R (0x1 << 1)
+#define RT5677_M_DAC1_L_STO_R_SFT 1
+#define RT5677_DAC1_L_STO_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC1_L_STO_R_VOL_SFT 0
+
+/* Mono DAC Mixer L/R Control (0x2b) */
+#define RT5677_M_ST_DAC2_L (0x1 << 15)
+#define RT5677_M_ST_DAC2_L_SFT 15
+#define RT5677_M_DAC2_L_MONO_L (0x1 << 13)
+#define RT5677_M_DAC2_L_MONO_L_SFT 13
+#define RT5677_DAC2_L_MONO_L_VOL_MASK (0x1 << 12)
+#define RT5677_DAC2_L_MONO_L_VOL_SFT 12
+#define RT5677_M_DAC2_R_MONO_L (0x1 << 11)
+#define RT5677_M_DAC2_R_MONO_L_SFT 11
+#define RT5677_DAC2_R_MONO_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC2_R_MONO_L_VOL_SFT 10
+#define RT5677_M_DAC1_L_MONO_L (0x1 << 9)
+#define RT5677_M_DAC1_L_MONO_L_SFT 9
+#define RT5677_DAC1_L_MONO_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC1_L_MONO_L_VOL_SFT 8
+#define RT5677_M_ST_DAC2_R (0x1 << 7)
+#define RT5677_M_ST_DAC2_R_SFT 7
+#define RT5677_M_DAC2_R_MONO_R (0x1 << 5)
+#define RT5677_M_DAC2_R_MONO_R_SFT 5
+#define RT5677_DAC2_R_MONO_R_VOL_MASK (0x1 << 4)
+#define RT5677_DAC2_R_MONO_R_VOL_SFT 4
+#define RT5677_M_DAC1_R_MONO_R (0x1 << 3)
+#define RT5677_M_DAC1_R_MONO_R_SFT 3
+#define RT5677_DAC1_R_MONO_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC1_R_MONO_R_VOL_SFT 2
+#define RT5677_M_DAC2_L_MONO_R (0x1 << 1)
+#define RT5677_M_DAC2_L_MONO_R_SFT 1
+#define RT5677_DAC2_L_MONO_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC2_L_MONO_R_VOL_SFT 0
+
+/* DD Mixer 1 Control (0x2c) */
+#define RT5677_M_STO_L_DD1_L (0x1 << 15)
+#define RT5677_M_STO_L_DD1_L_SFT 15
+#define RT5677_STO_L_DD1_L_VOL_MASK (0x1 << 14)
+#define RT5677_STO_L_DD1_L_VOL_SFT 14
+#define RT5677_M_MONO_L_DD1_L (0x1 << 13)
+#define RT5677_M_MONO_L_DD1_L_SFT 13
+#define RT5677_MONO_L_DD1_L_VOL_MASK (0x1 << 12)
+#define RT5677_MONO_L_DD1_L_VOL_SFT 12
+#define RT5677_M_DAC3_L_DD1_L (0x1 << 11)
+#define RT5677_M_DAC3_L_DD1_L_SFT 11
+#define RT5677_DAC3_L_DD1_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC3_L_DD1_L_VOL_SFT 10
+#define RT5677_M_DAC3_R_DD1_L (0x1 << 9)
+#define RT5677_M_DAC3_R_DD1_L_SFT 9
+#define RT5677_DAC3_R_DD1_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC3_R_DD1_L_VOL_SFT 8
+#define RT5677_M_STO_R_DD1_R (0x1 << 7)
+#define RT5677_M_STO_R_DD1_R_SFT 7
+#define RT5677_STO_R_DD1_R_VOL_MASK (0x1 << 6)
+#define RT5677_STO_R_DD1_R_VOL_SFT 6
+#define RT5677_M_MONO_R_DD1_R (0x1 << 5)
+#define RT5677_M_MONO_R_DD1_R_SFT 5
+#define RT5677_MONO_R_DD1_R_VOL_MASK (0x1 << 4)
+#define RT5677_MONO_R_DD1_R_VOL_SFT 4
+#define RT5677_M_DAC3_R_DD1_R (0x1 << 3)
+#define RT5677_M_DAC3_R_DD1_R_SFT 3
+#define RT5677_DAC3_R_DD1_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC3_R_DD1_R_VOL_SFT 2
+#define RT5677_M_DAC3_L_DD1_R (0x1 << 1)
+#define RT5677_M_DAC3_L_DD1_R_SFT 1
+#define RT5677_DAC3_L_DD1_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC3_L_DD1_R_VOL_SFT 0
+
+/* DD Mixer 2 Control (0x2d) */
+#define RT5677_M_STO_L_DD2_L (0x1 << 15)
+#define RT5677_M_STO_L_DD2_L_SFT 15
+#define RT5677_STO_L_DD2_L_VOL_MASK (0x1 << 14)
+#define RT5677_STO_L_DD2_L_VOL_SFT 14
+#define RT5677_M_MONO_L_DD2_L (0x1 << 13)
+#define RT5677_M_MONO_L_DD2_L_SFT 13
+#define RT5677_MONO_L_DD2_L_VOL_MASK (0x1 << 12)
+#define RT5677_MONO_L_DD2_L_VOL_SFT 12
+#define RT5677_M_DAC4_L_DD2_L (0x1 << 11)
+#define RT5677_M_DAC4_L_DD2_L_SFT 11
+#define RT5677_DAC4_L_DD2_L_VOL_MASK (0x1 << 10)
+#define RT5677_DAC4_L_DD2_L_VOL_SFT 10
+#define RT5677_M_DAC4_R_DD2_L (0x1 << 9)
+#define RT5677_M_DAC4_R_DD2_L_SFT 9
+#define RT5677_DAC4_R_DD2_L_VOL_MASK (0x1 << 8)
+#define RT5677_DAC4_R_DD2_L_VOL_SFT 8
+#define RT5677_M_STO_R_DD2_R (0x1 << 7)
+#define RT5677_M_STO_R_DD2_R_SFT 7
+#define RT5677_STO_R_DD2_R_VOL_MASK (0x1 << 6)
+#define RT5677_STO_R_DD2_R_VOL_SFT 6
+#define RT5677_M_MONO_R_DD2_R (0x1 << 5)
+#define RT5677_M_MONO_R_DD2_R_SFT 5
+#define RT5677_MONO_R_DD2_R_VOL_MASK (0x1 << 4)
+#define RT5677_MONO_R_DD2_R_VOL_SFT 4
+#define RT5677_M_DAC4_R_DD2_R (0x1 << 3)
+#define RT5677_M_DAC4_R_DD2_R_SFT 3
+#define RT5677_DAC4_R_DD2_R_VOL_MASK (0x1 << 2)
+#define RT5677_DAC4_R_DD2_R_VOL_SFT 2
+#define RT5677_M_DAC4_L_DD2_R (0x1 << 1)
+#define RT5677_M_DAC4_L_DD2_R_SFT 1
+#define RT5677_DAC4_L_DD2_R_VOL_MASK (0x1 << 0)
+#define RT5677_DAC4_L_DD2_R_VOL_SFT 0
+
+/* IF3 data control (0x2f) */
+#define RT5677_IF3_DAC_SEL_MASK (0x3 << 6)
+#define RT5677_IF3_DAC_SEL_SFT 6
+#define RT5677_IF3_ADC_SEL_MASK (0x3 << 4)
+#define RT5677_IF3_ADC_SEL_SFT 4
+#define RT5677_IF3_ADC_IN_MASK (0xf << 0)
+#define RT5677_IF3_ADC_IN_SFT 0
+
+/* IF4 data control (0x30) */
+#define RT5677_IF4_ADC_IN_MASK (0xf << 4)
+#define RT5677_IF4_ADC_IN_SFT 4
+#define RT5677_IF4_DAC_SEL_MASK (0x3 << 2)
+#define RT5677_IF4_DAC_SEL_SFT 2
+#define RT5677_IF4_ADC_SEL_MASK (0x3 << 0)
+#define RT5677_IF4_ADC_SEL_SFT 0
+
+/* PDM Output Control (0x31) */
+#define RT5677_M_PDM1_L (0x1 << 15)
+#define RT5677_M_PDM1_L_SFT 15
+#define RT5677_SEL_PDM1_L_MASK (0x3 << 12)
+#define RT5677_SEL_PDM1_L_SFT 12
+#define RT5677_M_PDM1_R (0x1 << 11)
+#define RT5677_M_PDM1_R_SFT 11
+#define RT5677_SEL_PDM1_R_MASK (0x3 << 8)
+#define RT5677_SEL_PDM1_R_SFT 8
+#define RT5677_M_PDM2_L (0x1 << 7)
+#define RT5677_M_PDM2_L_SFT 7
+#define RT5677_SEL_PDM2_L_MASK (0x3 << 4)
+#define RT5677_SEL_PDM2_L_SFT 4
+#define RT5677_M_PDM2_R (0x1 << 3)
+#define RT5677_M_PDM2_R_SFT 3
+#define RT5677_SEL_PDM2_R_MASK (0x3 << 0)
+#define RT5677_SEL_PDM2_R_SFT 0
+
+/* PDM I2C / Data Control 1 (0x32) */
+#define RT5677_PDM2_PW_DOWN (0x1 << 7)
+#define RT5677_PDM1_PW_DOWN (0x1 << 6)
+#define RT5677_PDM2_BUSY (0x1 << 5)
+#define RT5677_PDM1_BUSY (0x1 << 4)
+#define RT5677_PDM_PATTERN (0x1 << 3)
+#define RT5677_PDM_GAIN (0x1 << 2)
+#define RT5677_PDM_DIV_MASK (0x3 << 0)
+
+/* PDM I2C / Data Control 2 (0x33) */
+#define RT5677_PDM1_I2C_ID (0xf << 12)
+#define RT5677_PDM1_EXE (0x1 << 11)
+#define RT5677_PDM1_I2C_CMD (0x1 << 10)
+#define RT5677_PDM1_I2C_EXE (0x1 << 9)
+#define RT5677_PDM1_I2C_BUSY (0x1 << 8)
+#define RT5677_PDM2_I2C_ID (0xf << 4)
+#define RT5677_PDM2_EXE (0x1 << 3)
+#define RT5677_PDM2_I2C_CMD (0x1 << 2)
+#define RT5677_PDM2_I2C_EXE (0x1 << 1)
+#define RT5677_PDM2_I2C_BUSY (0x1 << 0)
+
+/* MX3C TDM1 control 1 (0x3c) */
+#define RT5677_IF1_ADC4_MASK (0x3 << 10)
+#define RT5677_IF1_ADC4_SFT 10
+#define RT5677_IF1_ADC3_MASK (0x3 << 8)
+#define RT5677_IF1_ADC3_SFT 8
+#define RT5677_IF1_ADC2_MASK (0x3 << 6)
+#define RT5677_IF1_ADC2_SFT 6
+#define RT5677_IF1_ADC1_MASK (0x3 << 4)
+#define RT5677_IF1_ADC1_SFT 4
+
+/* MX41 TDM2 control 1 (0x41) */
+#define RT5677_IF2_ADC4_MASK (0x3 << 10)
+#define RT5677_IF2_ADC4_SFT 10
+#define RT5677_IF2_ADC3_MASK (0x3 << 8)
+#define RT5677_IF2_ADC3_SFT 8
+#define RT5677_IF2_ADC2_MASK (0x3 << 6)
+#define RT5677_IF2_ADC2_SFT 6
+#define RT5677_IF2_ADC1_MASK (0x3 << 4)
+#define RT5677_IF2_ADC1_SFT 4
+
+/* Digital Microphone Control 1 (0x50) */
+#define RT5677_DMIC_1_EN_MASK (0x1 << 15)
+#define RT5677_DMIC_1_EN_SFT 15
+#define RT5677_DMIC_1_DIS (0x0 << 15)
+#define RT5677_DMIC_1_EN (0x1 << 15)
+#define RT5677_DMIC_2_EN_MASK (0x1 << 14)
+#define RT5677_DMIC_2_EN_SFT 14
+#define RT5677_DMIC_2_DIS (0x0 << 14)
+#define RT5677_DMIC_2_EN (0x1 << 14)
+#define RT5677_DMIC_L_STO1_LH_MASK (0x1 << 13)
+#define RT5677_DMIC_L_STO1_LH_SFT 13
+#define RT5677_DMIC_L_STO1_LH_FALLING (0x0 << 13)
+#define RT5677_DMIC_L_STO1_LH_RISING (0x1 << 13)
+#define RT5677_DMIC_R_STO1_LH_MASK (0x1 << 12)
+#define RT5677_DMIC_R_STO1_LH_SFT 12
+#define RT5677_DMIC_R_STO1_LH_FALLING (0x0 << 12)
+#define RT5677_DMIC_R_STO1_LH_RISING (0x1 << 12)
+#define RT5677_DMIC_L_STO3_LH_MASK (0x1 << 11)
+#define RT5677_DMIC_L_STO3_LH_SFT 11
+#define RT5677_DMIC_L_STO3_LH_FALLING (0x0 << 11)
+#define RT5677_DMIC_L_STO3_LH_RISING (0x1 << 11)
+#define RT5677_DMIC_R_STO3_LH_MASK (0x1 << 10)
+#define RT5677_DMIC_R_STO3_LH_SFT 10
+#define RT5677_DMIC_R_STO3_LH_FALLING (0x0 << 10)
+#define RT5677_DMIC_R_STO3_LH_RISING (0x1 << 10)
+#define RT5677_DMIC_L_STO2_LH_MASK (0x1 << 9)
+#define RT5677_DMIC_L_STO2_LH_SFT 9
+#define RT5677_DMIC_L_STO2_LH_FALLING (0x0 << 9)
+#define RT5677_DMIC_L_STO2_LH_RISING (0x1 << 9)
+#define RT5677_DMIC_R_STO2_LH_MASK (0x1 << 8)
+#define RT5677_DMIC_R_STO2_LH_SFT 8
+#define RT5677_DMIC_R_STO2_LH_FALLING (0x0 << 8)
+#define RT5677_DMIC_R_STO2_LH_RISING (0x1 << 8)
+#define RT5677_DMIC_CLK_MASK (0x7 << 5)
+#define RT5677_DMIC_CLK_SFT 5
+#define RT5677_DMIC_3_EN_MASK (0x1 << 4)
+#define RT5677_DMIC_3_EN_SFT 4
+#define RT5677_DMIC_3_DIS (0x0 << 4)
+#define RT5677_DMIC_3_EN (0x1 << 4)
+#define RT5677_DMIC_R_MONO_LH_MASK (0x1 << 2)
+#define RT5677_DMIC_R_MONO_LH_SFT 2
+#define RT5677_DMIC_R_MONO_LH_FALLING (0x0 << 2)
+#define RT5677_DMIC_R_MONO_LH_RISING (0x1 << 2)
+#define RT5677_DMIC_L_STO4_LH_MASK (0x1 << 1)
+#define RT5677_DMIC_L_STO4_LH_SFT 1
+#define RT5677_DMIC_L_STO4_LH_FALLING (0x0 << 1)
+#define RT5677_DMIC_L_STO4_LH_RISING (0x1 << 1)
+#define RT5677_DMIC_R_STO4_LH_MASK (0x1 << 0)
+#define RT5677_DMIC_R_STO4_LH_SFT 0
+#define RT5677_DMIC_R_STO4_LH_FALLING (0x0 << 0)
+#define RT5677_DMIC_R_STO4_LH_RISING (0x1 << 0)
+
+/* Digital Microphone Control 2 (0x51) */
+#define RT5677_DMIC_4_EN_MASK (0x1 << 15)
+#define RT5677_DMIC_4_EN_SFT 15
+#define RT5677_DMIC_4_DIS (0x0 << 15)
+#define RT5677_DMIC_4_EN (0x1 << 15)
+#define RT5677_DMIC_4L_LH_MASK (0x1 << 7)
+#define RT5677_DMIC_4L_LH_SFT 7
+#define RT5677_DMIC_4L_LH_FALLING (0x0 << 7)
+#define RT5677_DMIC_4L_LH_RISING (0x1 << 7)
+#define RT5677_DMIC_4R_LH_MASK (0x1 << 6)
+#define RT5677_DMIC_4R_LH_SFT 6
+#define RT5677_DMIC_4R_LH_FALLING (0x0 << 6)
+#define RT5677_DMIC_4R_LH_RISING (0x1 << 6)
+#define RT5677_DMIC_3L_LH_MASK (0x1 << 5)
+#define RT5677_DMIC_3L_LH_SFT 5
+#define RT5677_DMIC_3L_LH_FALLING (0x0 << 5)
+#define RT5677_DMIC_3L_LH_RISING (0x1 << 5)
+#define RT5677_DMIC_3R_LH_MASK (0x1 << 4)
+#define RT5677_DMIC_3R_LH_SFT 4
+#define RT5677_DMIC_3R_LH_FALLING (0x0 << 4)
+#define RT5677_DMIC_3R_LH_RISING (0x1 << 4)
+#define RT5677_DMIC_2L_LH_MASK (0x1 << 3)
+#define RT5677_DMIC_2L_LH_SFT 3
+#define RT5677_DMIC_2L_LH_FALLING (0x0 << 3)
+#define RT5677_DMIC_2L_LH_RISING (0x1 << 3)
+#define RT5677_DMIC_2R_LH_MASK (0x1 << 2)
+#define RT5677_DMIC_2R_LH_SFT 2
+#define RT5677_DMIC_2R_LH_FALLING (0x0 << 2)
+#define RT5677_DMIC_2R_LH_RISING (0x1 << 2)
+#define RT5677_DMIC_1L_LH_MASK (0x1 << 1)
+#define RT5677_DMIC_1L_LH_SFT 1
+#define RT5677_DMIC_1L_LH_FALLING (0x0 << 1)
+#define RT5677_DMIC_1L_LH_RISING (0x1 << 1)
+#define RT5677_DMIC_1R_LH_MASK (0x1 << 0)
+#define RT5677_DMIC_1R_LH_SFT 0
+#define RT5677_DMIC_1R_LH_FALLING (0x0 << 0)
+#define RT5677_DMIC_1R_LH_RISING (0x1 << 0)
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5677_PWR_I2S1 (0x1 << 15)
+#define RT5677_PWR_I2S1_BIT 15
+#define RT5677_PWR_I2S2 (0x1 << 14)
+#define RT5677_PWR_I2S2_BIT 14
+#define RT5677_PWR_I2S3 (0x1 << 13)
+#define RT5677_PWR_I2S3_BIT 13
+#define RT5677_PWR_DAC1 (0x1 << 12)
+#define RT5677_PWR_DAC1_BIT 12
+#define RT5677_PWR_DAC2 (0x1 << 11)
+#define RT5677_PWR_DAC2_BIT 11
+#define RT5677_PWR_I2S4 (0x1 << 10)
+#define RT5677_PWR_I2S4_BIT 10
+#define RT5677_PWR_SLB (0x1 << 9)
+#define RT5677_PWR_SLB_BIT 9
+#define RT5677_PWR_DAC3 (0x1 << 7)
+#define RT5677_PWR_DAC3_BIT 7
+#define RT5677_PWR_ADCFED2 (0x1 << 4)
+#define RT5677_PWR_ADCFED2_BIT 4
+#define RT5677_PWR_ADCFED1 (0x1 << 3)
+#define RT5677_PWR_ADCFED1_BIT 3
+#define RT5677_PWR_ADC_L (0x1 << 2)
+#define RT5677_PWR_ADC_L_BIT 2
+#define RT5677_PWR_ADC_R (0x1 << 1)
+#define RT5677_PWR_ADC_R_BIT 1
+#define RT5677_PWR_I2C_MASTER (0x1 << 0)
+#define RT5677_PWR_I2C_MASTER_BIT 0
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5677_PWR_ADC_S1F (0x1 << 15)
+#define RT5677_PWR_ADC_S1F_BIT 15
+#define RT5677_PWR_ADC_MF_L (0x1 << 14)
+#define RT5677_PWR_ADC_MF_L_BIT 14
+#define RT5677_PWR_ADC_MF_R (0x1 << 13)
+#define RT5677_PWR_ADC_MF_R_BIT 13
+#define RT5677_PWR_DAC_S1F (0x1 << 12)
+#define RT5677_PWR_DAC_S1F_BIT 12
+#define RT5677_PWR_DAC_M2F_L (0x1 << 11)
+#define RT5677_PWR_DAC_M2F_L_BIT 11
+#define RT5677_PWR_DAC_M2F_R (0x1 << 10)
+#define RT5677_PWR_DAC_M2F_R_BIT 10
+#define RT5677_PWR_DAC_M3F_L (0x1 << 9)
+#define RT5677_PWR_DAC_M3F_L_BIT 9
+#define RT5677_PWR_DAC_M3F_R (0x1 << 8)
+#define RT5677_PWR_DAC_M3F_R_BIT 8
+#define RT5677_PWR_DAC_M4F_L (0x1 << 7)
+#define RT5677_PWR_DAC_M4F_L_BIT 7
+#define RT5677_PWR_DAC_M4F_R (0x1 << 6)
+#define RT5677_PWR_DAC_M4F_R_BIT 6
+#define RT5677_PWR_ADC_S2F (0x1 << 5)
+#define RT5677_PWR_ADC_S2F_BIT 5
+#define RT5677_PWR_ADC_S3F (0x1 << 4)
+#define RT5677_PWR_ADC_S3F_BIT 4
+#define RT5677_PWR_ADC_S4F (0x1 << 3)
+#define RT5677_PWR_ADC_S4F_BIT 3
+#define RT5677_PWR_PDM1 (0x1 << 2)
+#define RT5677_PWR_PDM1_BIT 2
+#define RT5677_PWR_PDM2 (0x1 << 1)
+#define RT5677_PWR_PDM2_BIT 1
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5677_PWR_VREF1 (0x1 << 15)
+#define RT5677_PWR_VREF1_BIT 15
+#define RT5677_PWR_FV1 (0x1 << 14)
+#define RT5677_PWR_FV1_BIT 14
+#define RT5677_PWR_MB (0x1 << 13)
+#define RT5677_PWR_MB_BIT 13
+#define RT5677_PWR_LO1 (0x1 << 12)
+#define RT5677_PWR_LO1_BIT 12
+#define RT5677_PWR_BG (0x1 << 11)
+#define RT5677_PWR_BG_BIT 11
+#define RT5677_PWR_LO2 (0x1 << 10)
+#define RT5677_PWR_LO2_BIT 10
+#define RT5677_PWR_LO3 (0x1 << 9)
+#define RT5677_PWR_LO3_BIT 9
+#define RT5677_PWR_VREF2 (0x1 << 8)
+#define RT5677_PWR_VREF2_BIT 8
+#define RT5677_PWR_FV2 (0x1 << 7)
+#define RT5677_PWR_FV2_BIT 7
+#define RT5677_LDO2_SEL_MASK (0x7 << 4)
+#define RT5677_LDO2_SEL_SFT 4
+#define RT5677_LDO1_SEL_MASK (0x7 << 0)
+#define RT5677_LDO1_SEL_SFT 0
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5677_PWR_BST1 (0x1 << 15)
+#define RT5677_PWR_BST1_BIT 15
+#define RT5677_PWR_BST2 (0x1 << 14)
+#define RT5677_PWR_BST2_BIT 14
+#define RT5677_PWR_CLK_MB1 (0x1 << 13)
+#define RT5677_PWR_CLK_MB1_BIT 13
+#define RT5677_PWR_SLIM (0x1 << 12)
+#define RT5677_PWR_SLIM_BIT 12
+#define RT5677_PWR_MB1 (0x1 << 11)
+#define RT5677_PWR_MB1_BIT 11
+#define RT5677_PWR_PP_MB1 (0x1 << 10)
+#define RT5677_PWR_PP_MB1_BIT 10
+#define RT5677_PWR_PLL1 (0x1 << 9)
+#define RT5677_PWR_PLL1_BIT 9
+#define RT5677_PWR_PLL2 (0x1 << 8)
+#define RT5677_PWR_PLL2_BIT 8
+#define RT5677_PWR_CORE (0x1 << 7)
+#define RT5677_PWR_CORE_BIT 7
+#define RT5677_PWR_CLK_MB (0x1 << 6)
+#define RT5677_PWR_CLK_MB_BIT 6
+#define RT5677_PWR_BST1_P (0x1 << 5)
+#define RT5677_PWR_BST1_P_BIT 5
+#define RT5677_PWR_BST2_P (0x1 << 4)
+#define RT5677_PWR_BST2_P_BIT 4
+#define RT5677_PWR_IPTV (0x1 << 3)
+#define RT5677_PWR_IPTV_BIT 3
+#define RT5677_PWR_25M_CLK (0x1 << 1)
+#define RT5677_PWR_25M_CLK_BIT 1
+#define RT5677_PWR_LDO1 (0x1 << 0)
+#define RT5677_PWR_LDO1_BIT 0
+
+/* Power Management for DSP (0x65) */
+#define RT5677_PWR_SR7 (0x1 << 10)
+#define RT5677_PWR_SR7_BIT 10
+#define RT5677_PWR_SR6 (0x1 << 9)
+#define RT5677_PWR_SR6_BIT 9
+#define RT5677_PWR_SR5 (0x1 << 8)
+#define RT5677_PWR_SR5_BIT 8
+#define RT5677_PWR_SR4 (0x1 << 7)
+#define RT5677_PWR_SR4_BIT 7
+#define RT5677_PWR_SR3 (0x1 << 6)
+#define RT5677_PWR_SR3_BIT 6
+#define RT5677_PWR_SR2 (0x1 << 5)
+#define RT5677_PWR_SR2_BIT 5
+#define RT5677_PWR_SR1 (0x1 << 4)
+#define RT5677_PWR_SR1_BIT 4
+#define RT5677_PWR_SR0 (0x1 << 3)
+#define RT5677_PWR_SR0_BIT 3
+#define RT5677_PWR_MLT (0x1 << 2)
+#define RT5677_PWR_MLT_BIT 2
+#define RT5677_PWR_DSP (0x1 << 1)
+#define RT5677_PWR_DSP_BIT 1
+#define RT5677_PWR_DSP_CPU (0x1 << 0)
+#define RT5677_PWR_DSP_CPU_BIT 0
+
+/* Power Status for DSP (0x66) */
+#define RT5677_PWR_SR7_RDY (0x1 << 9)
+#define RT5677_PWR_SR7_RDY_BIT 9
+#define RT5677_PWR_SR6_RDY (0x1 << 8)
+#define RT5677_PWR_SR6_RDY_BIT 8
+#define RT5677_PWR_SR5_RDY (0x1 << 7)
+#define RT5677_PWR_SR5_RDY_BIT 7
+#define RT5677_PWR_SR4_RDY (0x1 << 6)
+#define RT5677_PWR_SR4_RDY_BIT 6
+#define RT5677_PWR_SR3_RDY (0x1 << 5)
+#define RT5677_PWR_SR3_RDY_BIT 5
+#define RT5677_PWR_SR2_RDY (0x1 << 4)
+#define RT5677_PWR_SR2_RDY_BIT 4
+#define RT5677_PWR_SR1_RDY (0x1 << 3)
+#define RT5677_PWR_SR1_RDY_BIT 3
+#define RT5677_PWR_SR0_RDY (0x1 << 2)
+#define RT5677_PWR_SR0_RDY_BIT 2
+#define RT5677_PWR_MLT_RDY (0x1 << 1)
+#define RT5677_PWR_MLT_RDY_BIT 1
+#define RT5677_PWR_DSP_RDY (0x1 << 0)
+#define RT5677_PWR_DSP_RDY_BIT 0
+
+/* Power Management for DSP (0x67) */
+#define RT5677_PWR_SLIM_ISO (0x1 << 11)
+#define RT5677_PWR_SLIM_ISO_BIT 11
+#define RT5677_PWR_CORE_ISO (0x1 << 10)
+#define RT5677_PWR_CORE_ISO_BIT 10
+#define RT5677_PWR_DSP_ISO (0x1 << 9)
+#define RT5677_PWR_DSP_ISO_BIT 9
+#define RT5677_PWR_SR7_ISO (0x1 << 8)
+#define RT5677_PWR_SR7_ISO_BIT 8
+#define RT5677_PWR_SR6_ISO (0x1 << 7)
+#define RT5677_PWR_SR6_ISO_BIT 7
+#define RT5677_PWR_SR5_ISO (0x1 << 6)
+#define RT5677_PWR_SR5_ISO_BIT 6
+#define RT5677_PWR_SR4_ISO (0x1 << 5)
+#define RT5677_PWR_SR4_ISO_BIT 5
+#define RT5677_PWR_SR3_ISO (0x1 << 4)
+#define RT5677_PWR_SR3_ISO_BIT 4
+#define RT5677_PWR_SR2_ISO (0x1 << 3)
+#define RT5677_PWR_SR2_ISO_BIT 3
+#define RT5677_PWR_SR1_ISO (0x1 << 2)
+#define RT5677_PWR_SR1_ISO_BIT 2
+#define RT5677_PWR_SR0_ISO (0x1 << 1)
+#define RT5677_PWR_SR0_ISO_BIT 1
+#define RT5677_PWR_MLT_ISO (0x1 << 0)
+#define RT5677_PWR_MLT_ISO_BIT 0
+
+/* I2S1/2/3/4 Audio Serial Data Port Control (0x6f 0x70 0x71 0x72) */
+#define RT5677_I2S_MS_MASK (0x1 << 15)
+#define RT5677_I2S_MS_SFT 15
+#define RT5677_I2S_MS_M (0x0 << 15)
+#define RT5677_I2S_MS_S (0x1 << 15)
+#define RT5677_I2S_O_CP_MASK (0x3 << 10)
+#define RT5677_I2S_O_CP_SFT 10
+#define RT5677_I2S_O_CP_OFF (0x0 << 10)
+#define RT5677_I2S_O_CP_U_LAW (0x1 << 10)
+#define RT5677_I2S_O_CP_A_LAW (0x2 << 10)
+#define RT5677_I2S_I_CP_MASK (0x3 << 8)
+#define RT5677_I2S_I_CP_SFT 8
+#define RT5677_I2S_I_CP_OFF (0x0 << 8)
+#define RT5677_I2S_I_CP_U_LAW (0x1 << 8)
+#define RT5677_I2S_I_CP_A_LAW (0x2 << 8)
+#define RT5677_I2S_BP_MASK (0x1 << 7)
+#define RT5677_I2S_BP_SFT 7
+#define RT5677_I2S_BP_NOR (0x0 << 7)
+#define RT5677_I2S_BP_INV (0x1 << 7)
+#define RT5677_I2S_DL_MASK (0x3 << 2)
+#define RT5677_I2S_DL_SFT 2
+#define RT5677_I2S_DL_16 (0x0 << 2)
+#define RT5677_I2S_DL_20 (0x1 << 2)
+#define RT5677_I2S_DL_24 (0x2 << 2)
+#define RT5677_I2S_DL_8 (0x3 << 2)
+#define RT5677_I2S_DF_MASK (0x3 << 0)
+#define RT5677_I2S_DF_SFT 0
+#define RT5677_I2S_DF_I2S (0x0 << 0)
+#define RT5677_I2S_DF_LEFT (0x1 << 0)
+#define RT5677_I2S_DF_PCM_A (0x2 << 0)
+#define RT5677_I2S_DF_PCM_B (0x3 << 0)
+
+/* Clock Tree Control 1 (0x73) */
+#define RT5677_I2S_PD1_MASK (0x7 << 12)
+#define RT5677_I2S_PD1_SFT 12
+#define RT5677_I2S_PD1_1 (0x0 << 12)
+#define RT5677_I2S_PD1_2 (0x1 << 12)
+#define RT5677_I2S_PD1_3 (0x2 << 12)
+#define RT5677_I2S_PD1_4 (0x3 << 12)
+#define RT5677_I2S_PD1_6 (0x4 << 12)
+#define RT5677_I2S_PD1_8 (0x5 << 12)
+#define RT5677_I2S_PD1_12 (0x6 << 12)
+#define RT5677_I2S_PD1_16 (0x7 << 12)
+#define RT5677_I2S_BCLK_MS2_MASK (0x1 << 11)
+#define RT5677_I2S_BCLK_MS2_SFT 11
+#define RT5677_I2S_BCLK_MS2_32 (0x0 << 11)
+#define RT5677_I2S_BCLK_MS2_64 (0x1 << 11)
+#define RT5677_I2S_PD2_MASK (0x7 << 8)
+#define RT5677_I2S_PD2_SFT 8
+#define RT5677_I2S_PD2_1 (0x0 << 8)
+#define RT5677_I2S_PD2_2 (0x1 << 8)
+#define RT5677_I2S_PD2_3 (0x2 << 8)
+#define RT5677_I2S_PD2_4 (0x3 << 8)
+#define RT5677_I2S_PD2_6 (0x4 << 8)
+#define RT5677_I2S_PD2_8 (0x5 << 8)
+#define RT5677_I2S_PD2_12 (0x6 << 8)
+#define RT5677_I2S_PD2_16 (0x7 << 8)
+#define RT5677_I2S_BCLK_MS3_MASK (0x1 << 7)
+#define RT5677_I2S_BCLK_MS3_SFT 7
+#define RT5677_I2S_BCLK_MS3_32 (0x0 << 7)
+#define RT5677_I2S_BCLK_MS3_64 (0x1 << 7)
+#define RT5677_I2S_PD3_MASK (0x7 << 4)
+#define RT5677_I2S_PD3_SFT 4
+#define RT5677_I2S_PD3_1 (0x0 << 4)
+#define RT5677_I2S_PD3_2 (0x1 << 4)
+#define RT5677_I2S_PD3_3 (0x2 << 4)
+#define RT5677_I2S_PD3_4 (0x3 << 4)
+#define RT5677_I2S_PD3_6 (0x4 << 4)
+#define RT5677_I2S_PD3_8 (0x5 << 4)
+#define RT5677_I2S_PD3_12 (0x6 << 4)
+#define RT5677_I2S_PD3_16 (0x7 << 4)
+#define RT5677_I2S_BCLK_MS4_MASK (0x1 << 3)
+#define RT5677_I2S_BCLK_MS4_SFT 3
+#define RT5677_I2S_BCLK_MS4_32 (0x0 << 3)
+#define RT5677_I2S_BCLK_MS4_64 (0x1 << 3)
+#define RT5677_I2S_PD4_MASK (0x7 << 0)
+#define RT5677_I2S_PD4_SFT 0
+#define RT5677_I2S_PD4_1 (0x0 << 0)
+#define RT5677_I2S_PD4_2 (0x1 << 0)
+#define RT5677_I2S_PD4_3 (0x2 << 0)
+#define RT5677_I2S_PD4_4 (0x3 << 0)
+#define RT5677_I2S_PD4_6 (0x4 << 0)
+#define RT5677_I2S_PD4_8 (0x5 << 0)
+#define RT5677_I2S_PD4_12 (0x6 << 0)
+#define RT5677_I2S_PD4_16 (0x7 << 0)
+
+/* Clock Tree Control 2 (0x74) */
+#define RT5677_I2S_PD5_MASK (0x7 << 12)
+#define RT5677_I2S_PD5_SFT 12
+#define RT5677_I2S_PD5_1 (0x0 << 12)
+#define RT5677_I2S_PD5_2 (0x1 << 12)
+#define RT5677_I2S_PD5_3 (0x2 << 12)
+#define RT5677_I2S_PD5_4 (0x3 << 12)
+#define RT5677_I2S_PD5_6 (0x4 << 12)
+#define RT5677_I2S_PD5_8 (0x5 << 12)
+#define RT5677_I2S_PD5_12 (0x6 << 12)
+#define RT5677_I2S_PD5_16 (0x7 << 12)
+#define RT5677_I2S_PD6_MASK (0x7 << 8)
+#define RT5677_I2S_PD6_SFT 8
+#define RT5677_I2S_PD6_1 (0x0 << 8)
+#define RT5677_I2S_PD6_2 (0x1 << 8)
+#define RT5677_I2S_PD6_3 (0x2 << 8)
+#define RT5677_I2S_PD6_4 (0x3 << 8)
+#define RT5677_I2S_PD6_6 (0x4 << 8)
+#define RT5677_I2S_PD6_8 (0x5 << 8)
+#define RT5677_I2S_PD6_12 (0x6 << 8)
+#define RT5677_I2S_PD6_16 (0x7 << 8)
+#define RT5677_I2S_PD7_MASK (0x7 << 4)
+#define RT5677_I2S_PD7_SFT 4
+#define RT5677_I2S_PD7_1 (0x0 << 4)
+#define RT5677_I2S_PD7_2 (0x1 << 4)
+#define RT5677_I2S_PD7_3 (0x2 << 4)
+#define RT5677_I2S_PD7_4 (0x3 << 4)
+#define RT5677_I2S_PD7_6 (0x4 << 4)
+#define RT5677_I2S_PD7_8 (0x5 << 4)
+#define RT5677_I2S_PD7_12 (0x6 << 4)
+#define RT5677_I2S_PD7_16 (0x7 << 4)
+#define RT5677_I2S_PD8_MASK (0x7 << 0)
+#define RT5677_I2S_PD8_SFT 0
+#define RT5677_I2S_PD8_1 (0x0 << 0)
+#define RT5677_I2S_PD8_2 (0x1 << 0)
+#define RT5677_I2S_PD8_3 (0x2 << 0)
+#define RT5677_I2S_PD8_4 (0x3 << 0)
+#define RT5677_I2S_PD8_6 (0x4 << 0)
+#define RT5677_I2S_PD8_8 (0x5 << 0)
+#define RT5677_I2S_PD8_12 (0x6 << 0)
+#define RT5677_I2S_PD8_16 (0x7 << 0)
+
+/* Clock Tree Control 3 (0x75) */
+#define RT5677_DSP_ASRC_O_MASK (0x3 << 6)
+#define RT5677_DSP_ASRC_O_SFT 6
+#define RT5677_DSP_ASRC_O_1_0 (0x0 << 6)
+#define RT5677_DSP_ASRC_O_1_5 (0x1 << 6)
+#define RT5677_DSP_ASRC_O_2_0 (0x2 << 6)
+#define RT5677_DSP_ASRC_O_3_0 (0x3 << 6)
+#define RT5677_DSP_ASRC_I_MASK (0x3 << 4)
+#define RT5677_DSP_ASRC_I_SFT 4
+#define RT5677_DSP_ASRC_I_1_0 (0x0 << 4)
+#define RT5677_DSP_ASRC_I_1_5 (0x1 << 4)
+#define RT5677_DSP_ASRC_I_2_0 (0x2 << 4)
+#define RT5677_DSP_ASRC_I_3_0 (0x3 << 4)
+#define RT5677_DSP_BUS_PD_MASK (0x7 << 0)
+#define RT5677_DSP_BUS_PD_SFT 0
+#define RT5677_DSP_BUS_PD_1 (0x0 << 0)
+#define RT5677_DSP_BUS_PD_2 (0x1 << 0)
+#define RT5677_DSP_BUS_PD_3 (0x2 << 0)
+#define RT5677_DSP_BUS_PD_4 (0x3 << 0)
+#define RT5677_DSP_BUS_PD_6 (0x4 << 0)
+#define RT5677_DSP_BUS_PD_8 (0x5 << 0)
+#define RT5677_DSP_BUS_PD_12 (0x6 << 0)
+#define RT5677_DSP_BUS_PD_16 (0x7 << 0)
+
+#define RT5677_PLL_INP_MAX 40000000
+#define RT5677_PLL_INP_MIN 2048000
+/* PLL M/N/K Code Control 1 (0x7a 0x7c) */
+#define RT5677_PLL_N_MAX 0x1ff
+#define RT5677_PLL_N_MASK (RT5677_PLL_N_MAX << 7)
+#define RT5677_PLL_N_SFT 7
+#define RT5677_PLL_K_BP (0x1 << 5)
+#define RT5677_PLL_K_BP_SFT 5
+#define RT5677_PLL_K_MAX 0x1f
+#define RT5677_PLL_K_MASK (RT5677_PLL_K_MAX)
+#define RT5677_PLL_K_SFT 0
+
+/* PLL M/N/K Code Control 2 (0x7b 0x7d) */
+#define RT5677_PLL_M_MAX 0xf
+#define RT5677_PLL_M_MASK (RT5677_PLL_M_MAX << 12)
+#define RT5677_PLL_M_SFT 12
+#define RT5677_PLL_M_BP (0x1 << 11)
+#define RT5677_PLL_M_BP_SFT 11
+
+/* Global Clock Control 1 (0x80) */
+#define RT5677_SCLK_SRC_MASK (0x3 << 14)
+#define RT5677_SCLK_SRC_SFT 14
+#define RT5677_SCLK_SRC_MCLK (0x0 << 14)
+#define RT5677_SCLK_SRC_PLL1 (0x1 << 14)
+#define RT5677_SCLK_SRC_RCCLK (0x2 << 14) /* 25MHz */
+#define RT5677_SCLK_SRC_SLIM (0x3 << 14)
+#define RT5677_PLL1_SRC_MASK (0x7 << 11)
+#define RT5677_PLL1_SRC_SFT 11
+#define RT5677_PLL1_SRC_MCLK (0x0 << 11)
+#define RT5677_PLL1_SRC_BCLK1 (0x1 << 11)
+#define RT5677_PLL1_SRC_BCLK2 (0x2 << 11)
+#define RT5677_PLL1_SRC_BCLK3 (0x3 << 11)
+#define RT5677_PLL1_SRC_BCLK4 (0x4 << 11)
+#define RT5677_PLL1_SRC_RCCLK (0x5 << 11)
+#define RT5677_PLL1_SRC_SLIM (0x6 << 11)
+#define RT5677_MCLK_SRC_MASK (0x1 << 10)
+#define RT5677_MCLK_SRC_SFT 10
+#define RT5677_MCLK1_SRC (0x0 << 10)
+#define RT5677_MCLK2_SRC (0x1 << 10)
+#define RT5677_PLL1_PD_MASK (0x1 << 8)
+#define RT5677_PLL1_PD_SFT 8
+#define RT5677_PLL1_PD_1 (0x0 << 8)
+#define RT5677_PLL1_PD_2 (0x1 << 8)
+#define RT5671_DAC_OSR_MASK (0x3 << 6)
+#define RT5671_DAC_OSR_SFT 6
+#define RT5671_DAC_OSR_128 (0x0 << 6)
+#define RT5671_DAC_OSR_64 (0x1 << 6)
+#define RT5671_DAC_OSR_32 (0x2 << 6)
+#define RT5671_ADC_OSR_MASK (0x3 << 4)
+#define RT5671_ADC_OSR_SFT 4
+#define RT5671_ADC_OSR_128 (0x0 << 4)
+#define RT5671_ADC_OSR_64 (0x1 << 4)
+#define RT5671_ADC_OSR_32 (0x2 << 4)
+
+/* Global Clock Control 2 (0x81) */
+#define RT5677_PLL2_PR_SRC_MASK (0x1 << 15)
+#define RT5677_PLL2_PR_SRC_SFT 15
+#define RT5677_PLL2_PR_SRC_MCLK1 (0x0 << 15)
+#define RT5677_PLL2_PR_SRC_MCLK2 (0x1 << 15)
+#define RT5677_PLL2_SRC_MASK (0x7 << 12)
+#define RT5677_PLL2_SRC_SFT 12
+#define RT5677_PLL2_SRC_MCLK (0x0 << 12)
+#define RT5677_PLL2_SRC_BCLK1 (0x1 << 12)
+#define RT5677_PLL2_SRC_BCLK2 (0x2 << 12)
+#define RT5677_PLL2_SRC_BCLK3 (0x3 << 12)
+#define RT5677_PLL2_SRC_BCLK4 (0x4 << 12)
+#define RT5677_PLL2_SRC_RCCLK (0x5 << 12)
+#define RT5677_PLL2_SRC_SLIM (0x6 << 12)
+#define RT5671_DSP_ASRC_O_SRC (0x3 << 10)
+#define RT5671_DSP_ASRC_O_SRC_SFT 10
+#define RT5671_DSP_ASRC_O_MCLK (0x0 << 10)
+#define RT5671_DSP_ASRC_O_PLL1 (0x1 << 10)
+#define RT5671_DSP_ASRC_O_SLIM (0x2 << 10)
+#define RT5671_DSP_ASRC_O_RCCLK (0x3 << 10)
+#define RT5671_DSP_ASRC_I_SRC (0x3 << 8)
+#define RT5671_DSP_ASRC_I_SRC_SFT 8
+#define RT5671_DSP_ASRC_I_MCLK (0x0 << 8)
+#define RT5671_DSP_ASRC_I_PLL1 (0x1 << 8)
+#define RT5671_DSP_ASRC_I_SLIM (0x2 << 8)
+#define RT5671_DSP_ASRC_I_RCCLK (0x3 << 8)
+#define RT5677_DSP_CLK_SRC_MASK (0x1 << 7)
+#define RT5677_DSP_CLK_SRC_SFT 7
+#define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7)
+#define RT5677_DSP_CLK_SRC_BYPASS (0x1 << 7)
+
+/* VAD Function Control 4 (0x9f) */
+#define RT5677_VAD_SRC_MASK (0x7 << 8)
+#define RT5677_VAD_SRC_SFT 8
+
+/* DSP InBound Control (0xa3) */
+#define RT5677_IB01_SRC_MASK (0x7 << 12)
+#define RT5677_IB01_SRC_SFT 12
+#define RT5677_IB23_SRC_MASK (0x7 << 8)
+#define RT5677_IB23_SRC_SFT 8
+#define RT5677_IB45_SRC_MASK (0x7 << 4)
+#define RT5677_IB45_SRC_SFT 4
+#define RT5677_IB6_SRC_MASK (0x7 << 0)
+#define RT5677_IB6_SRC_SFT 0
+
+/* DSP InBound Control (0xa4) */
+#define RT5677_IB7_SRC_MASK (0x7 << 12)
+#define RT5677_IB7_SRC_SFT 12
+#define RT5677_IB8_SRC_MASK (0x7 << 8)
+#define RT5677_IB8_SRC_SFT 8
+#define RT5677_IB9_SRC_MASK (0x7 << 4)
+#define RT5677_IB9_SRC_SFT 4
+
+/* DSP In/OutBound Control (0xa5) */
+#define RT5677_SEL_SRC_OB23 (0x1 << 4)
+#define RT5677_SEL_SRC_OB23_SFT 4
+#define RT5677_SEL_SRC_OB01 (0x1 << 3)
+#define RT5677_SEL_SRC_OB01_SFT 3
+#define RT5677_SEL_SRC_IB45 (0x1 << 2)
+#define RT5677_SEL_SRC_IB45_SFT 2
+#define RT5677_SEL_SRC_IB23 (0x1 << 1)
+#define RT5677_SEL_SRC_IB23_SFT 1
+#define RT5677_SEL_SRC_IB01 (0x1 << 0)
+#define RT5677_SEL_SRC_IB01_SFT 0
+
+/* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */
+#define RT5677_DSP_IB_01_H (0x1 << 15)
+#define RT5677_DSP_IB_01_H_SFT 15
+#define RT5677_DSP_IB_23_H (0x1 << 14)
+#define RT5677_DSP_IB_23_H_SFT 14
+#define RT5677_DSP_IB_45_H (0x1 << 13)
+#define RT5677_DSP_IB_45_H_SFT 13
+#define RT5677_DSP_IB_6_H (0x1 << 12)
+#define RT5677_DSP_IB_6_H_SFT 12
+#define RT5677_DSP_IB_7_H (0x1 << 11)
+#define RT5677_DSP_IB_7_H_SFT 11
+#define RT5677_DSP_IB_8_H (0x1 << 10)
+#define RT5677_DSP_IB_8_H_SFT 10
+#define RT5677_DSP_IB_9_H (0x1 << 9)
+#define RT5677_DSP_IB_9_H_SFT 9
+#define RT5677_DSP_IB_01_L (0x1 << 7)
+#define RT5677_DSP_IB_01_L_SFT 7
+#define RT5677_DSP_IB_23_L (0x1 << 6)
+#define RT5677_DSP_IB_23_L_SFT 6
+#define RT5677_DSP_IB_45_L (0x1 << 5)
+#define RT5677_DSP_IB_45_L_SFT 5
+#define RT5677_DSP_IB_6_L (0x1 << 4)
+#define RT5677_DSP_IB_6_L_SFT 4
+#define RT5677_DSP_IB_7_L (0x1 << 3)
+#define RT5677_DSP_IB_7_L_SFT 3
+#define RT5677_DSP_IB_8_L (0x1 << 2)
+#define RT5677_DSP_IB_8_L_SFT 2
+#define RT5677_DSP_IB_9_L (0x1 << 1)
+#define RT5677_DSP_IB_9_L_SFT 1
+
+#define RT5677_SW_RESET 0x10EC
+
+/* System Clock Source */
+enum {
+ RT5677_SCLK_S_MCLK,
+ RT5677_SCLK_S_PLL1,
+ RT5677_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+ RT5677_PLL1_S_MCLK,
+ RT5677_PLL1_S_BCLK1,
+ RT5677_PLL1_S_BCLK2,
+ RT5677_PLL1_S_BCLK3,
+ RT5677_PLL1_S_BCLK4,
+};
+
+enum {
+ RT5677_AIF1,
+ RT5677_AIF2,
+ RT5677_AIF3,
+ RT5677_AIF4,
+ RT5677_AIF5,
+ RT5677_AIFS,
+};
+
+#endif /* __DRIVERS_SOUND_RT5677_H__ */
diff --git a/drivers/sound/sandbox.c b/drivers/sound/sandbox.c
index b0b07f3..363c687 100644
--- a/drivers/sound/sandbox.c
+++ b/drivers/sound/sandbox.c
@@ -3,6 +3,8 @@
* Copyright (c) 2013 Google, Inc
*/
+#define LOG_CATEGORY UCLASS_SOUND
+
#include <common.h>
#include <audio_codec.h>
#include <dm.h>
@@ -20,11 +22,14 @@ struct sandbox_codec_priv {
struct sandbox_i2s_priv {
int sum; /* Use to sum the provided audio data */
+ bool silent; /* Sound is silent, don't use SDL */
};
struct sandbox_sound_priv {
int setup_called;
- int sum; /* Use to sum the provided audio data */
+ int sum; /* Use to sum the provided audio data */
+ bool allow_beep; /* true to allow the start_beep() interface */
+ int frequency_hz; /* Beep frequency if active, else 0 */
};
void sandbox_get_codec_params(struct udevice *dev, int *interfacep, int *ratep,
@@ -61,6 +66,20 @@ int sandbox_get_sound_sum(struct udevice *dev)
return priv->sum;
}
+void sandbox_set_allow_beep(struct udevice *dev, bool allow)
+{
+ struct sandbox_sound_priv *priv = dev_get_priv(dev);
+
+ priv->allow_beep = allow;
+}
+
+int sandbox_get_beep_frequency(struct udevice *dev)
+{
+ struct sandbox_sound_priv *priv = dev_get_priv(dev);
+
+ return priv->frequency_hz;
+}
+
static int sandbox_codec_set_params(struct udevice *dev, int interface,
int rate, int mclk_freq,
int bits_per_sample, uint channels)
@@ -85,12 +104,21 @@ static int sandbox_i2s_tx_data(struct udevice *dev, void *data,
for (i = 0; i < data_size; i++)
priv->sum += ((uint8_t *)data)[i];
- return sandbox_sdl_sound_play(data, data_size);
+ if (!priv->silent) {
+ int ret;
+
+ ret = sandbox_sdl_sound_play(data, data_size);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static int sandbox_i2s_probe(struct udevice *dev)
{
struct i2s_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct sandbox_i2s_priv *priv = dev_get_priv(dev);
/* Use hard-coded values here */
uc_priv->rfs = 256;
@@ -101,8 +129,15 @@ static int sandbox_i2s_probe(struct udevice *dev)
uc_priv->channels = 2;
uc_priv->id = 1;
- /* Ignore any error here - we'll just have no sound */
- sandbox_sdl_sound_init(uc_priv->samplingrate, uc_priv->channels);
+ priv->silent = dev_read_bool(dev, "sandbox,silent");
+
+ if (priv->silent) {
+ log_warning("Sound is silenced\n");
+ } else if (sandbox_sdl_sound_init(uc_priv->samplingrate,
+ uc_priv->channels)) {
+ /* Ignore any error here - we'll just have no sound */
+ priv->silent = true;
+ }
return 0;
}
@@ -128,6 +163,28 @@ static int sandbox_sound_play(struct udevice *dev, void *data, uint data_size)
return i2s_tx_data(uc_priv->i2s, data, data_size);
}
+int sandbox_sound_start_beep(struct udevice *dev, int frequency_hz)
+{
+ struct sandbox_sound_priv *priv = dev_get_priv(dev);
+
+ if (!priv->allow_beep)
+ return -ENOSYS;
+ priv->frequency_hz = frequency_hz;
+
+ return 0;
+}
+
+int sandbox_sound_stop_beep(struct udevice *dev)
+{
+ struct sandbox_sound_priv *priv = dev_get_priv(dev);
+
+ if (!priv->allow_beep)
+ return -ENOSYS;
+ priv->frequency_hz = 0;
+
+ return 0;
+}
+
static int sandbox_sound_probe(struct udevice *dev)
{
return sound_find_codec_i2s(dev);
@@ -169,8 +226,10 @@ U_BOOT_DRIVER(sandbox_i2s) = {
};
static const struct sound_ops sandbox_sound_ops = {
- .setup = sandbox_sound_setup,
- .play = sandbox_sound_play,
+ .setup = sandbox_sound_setup,
+ .play = sandbox_sound_play,
+ .start_beep = sandbox_sound_start_beep,
+ .stop_beep = sandbox_sound_stop_beep,
};
static const struct udevice_id sandbox_sound_ids[] = {
diff --git a/drivers/sound/sound-uclass.c b/drivers/sound/sound-uclass.c
index 2b83626..d49f29b 100644
--- a/drivers/sound/sound-uclass.c
+++ b/drivers/sound/sound-uclass.c
@@ -16,7 +16,7 @@ int sound_setup(struct udevice *dev)
struct sound_ops *ops = sound_get_ops(dev);
if (!ops->setup)
- return -ENOSYS;
+ return 0;
return ops->setup(dev);
}
@@ -31,10 +31,30 @@ int sound_play(struct udevice *dev, void *data, uint data_size)
return ops->play(dev, data, data_size);
}
+int sound_start_beep(struct udevice *dev, int frequency_hz)
+{
+ struct sound_ops *ops = sound_get_ops(dev);
+
+ if (!ops->start_beep)
+ return -ENOSYS;
+
+ return ops->start_beep(dev, frequency_hz);
+}
+
+int sound_stop_beep(struct udevice *dev)
+{
+ struct sound_ops *ops = sound_get_ops(dev);
+
+ if (!ops->stop_beep)
+ return -ENOSYS;
+
+ return ops->stop_beep(dev);
+}
+
int sound_beep(struct udevice *dev, int msecs, int frequency_hz)
{
struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
- struct i2s_uc_priv *i2s_uc_priv = dev_get_uclass_priv(uc_priv->i2s);
+ struct i2s_uc_priv *i2s_uc_priv;
unsigned short *data;
uint data_size;
int ret;
@@ -43,7 +63,19 @@ int sound_beep(struct udevice *dev, int msecs, int frequency_hz)
if (ret && ret != -EALREADY)
return ret;
+ /* Try using the beep interface if available */
+ ret = sound_start_beep(dev, frequency_hz);
+ if (ret != -ENOSYS) {
+ if (ret)
+ return ret;
+ mdelay(msecs);
+ ret = sound_stop_beep(dev);
+
+ return ret;
+ }
+
/* Buffer length computation */
+ i2s_uc_priv = dev_get_uclass_priv(uc_priv->i2s);
data_size = i2s_uc_priv->samplingrate * i2s_uc_priv->channels;
data_size *= (i2s_uc_priv->bitspersample / SOUND_BITS_IN_BYTE);
data = malloc(data_size);
diff --git a/include/dt-bindings/sound/azalia.h b/include/dt-bindings/sound/azalia.h
new file mode 100644
index 0000000..10ace3e
--- /dev/null
+++ b/include/dt-bindings/sound/azalia.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Intel HDA audio codec config. This is a mechanicm to configure codecs when
+ * using Intel HDA audio.
+ *
+ * Copyright 2018 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __AZALIA_H
+#define __AZALIA_H
+
+#define AZALIA_CODEC_SHIFT 28
+#define AZALIA_NID_SHIFT 20
+#define AZALIA_VERB_SHIFT 8
+
+/* Supported opcodes */
+#define AZALIA_OPCODE_CONFIG_DEFAULT 0x71c
+#define AZALIA_OPCODE_IMPL_ID 0x720
+#define AZALIA_OPCODE_READ_PARAM 0xf00
+
+#define AZALIA_PARAM_VENDOR_ID 0
+
+/* Generate the register value to write a particular byte of a 32-bit value */
+#define AZALIA_SET_BYTE(codec, nid, opcode, val, byte) \
+ ((codec) << AZALIA_CODEC_SHIFT | \
+ (nid) << AZALIA_NID_SHIFT | \
+ ((opcode) + (byte)) << AZALIA_VERB_SHIFT | \
+ (((val) >> ((byte) * 8)) & 0xff))
+
+/* Generate the register value to write all bytes of a 32-bit value */
+#define AZALIA_WORD(codec, nid, opcode, val) \
+ (AZALIA_SET_BYTE(codec, nid, opcode, val, 0) | \
+ AZALIA_SET_BYTE(codec, nid, opcode, val, 1) | \
+ AZALIA_SET_BYTE(codec, nid, opcode, val, 2) | \
+ AZALIA_SET_BYTE(codec, nid, opcode, val, 3))
+
+#define AZALIA_PIN_CFG(codec, nid, val) \
+ AZALIA_WORD(codec, nid, AZALIA_OPCODE_CONFIG_DEFAULT, val)
+
+#define AZALIA_SUBVENDOR(codec, val) \
+ AZALIA_WORD(codec, 1, AZALIA_OPCODE_IMPL_ID, val)
+
+#endif /* __AZALIA_H */
diff --git a/include/hda_codec.h b/include/hda_codec.h
new file mode 100644
index 0000000..56de571
--- /dev/null
+++ b/include/hda_codec.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Support for Intel High-Definition Audio codec
+ *
+ * Copyright 2018 Google LLC
+ *
+ * Taken from coreboot file of the same name
+ */
+
+#ifndef __HDA_CODEC_H_
+#define __HDA_CODEC_H_
+
+struct hda_regs;
+
+/**
+ * struct hda_codec_priv - Private data required by the HDA codec
+ *
+ * @regs: HDA registers
+ * @beep_nid: Node ID of beep node (>0)
+ */
+struct hda_codec_priv {
+ struct hda_regs *regs;
+ uint beep_nid;
+};
+
+/**
+ * hda_wait_for_ready() - Wait for the codec to indicate it is ready
+ *
+ * @regs: HDA registers
+ * @return 0 if OK -ETIMEDOUT if codec did not respond in time
+ */
+int hda_wait_for_ready(struct hda_regs *regs);
+
+/**
+ * hda_wait_for_valid() - Wait for the codec to accept the last command
+ *
+ * @regs: HDA registers
+ * @return 0 if OK -ETIMEDOUT if codec did not respond in time
+ */
+int hda_wait_for_valid(struct hda_regs *regs);
+
+/**
+ * hda_codec_detect() - Detect which codecs are present
+ *
+ * @regs: HDA registers
+ * @return bit mask of active codecs (0 if none)
+ * @return 0 if OK, -ve on error
+ */
+int hda_codec_detect(struct hda_regs *regs);
+
+/**
+ * hda_codecs_init() - Init all codecs
+ *
+ * @dev: Sound device
+ * @regs: HDA registers
+ * @codec_mask: Mask of codecs to init (bits 3:0)
+ * @return 0 if OK, -ve on error
+ */
+int hda_codecs_init(struct udevice *dev, struct hda_regs *regs, u32 codec_mask);
+
+/**
+ * hda_codec_start_beep() - Start beeping
+ *
+ * This tells the sound hardware to start a beep. It will continue until stopped
+ * by sound_stop_beep().
+ *
+ * @dev: Sound device
+ * @frequency_hz: Beep frequency in hertz
+ * @return if OK, -ve on error
+ */
+int hda_codec_start_beep(struct udevice *dev, int frequency_hz);
+
+/**
+ * hda_codec_stop_beep() - Stop beeping
+ *
+ * This tells the sound hardware to stop a previously started beep.
+ *
+ * @dev: Sound device
+ * @return if OK, -ve on error
+ */
+int hda_codec_stop_beep(struct udevice *dev);
+
+/**
+ * hda_codec_init() - Set up the HDA codec base address
+ *
+ * This should be called at the start of the probe() method.
+ *
+ * @dev: Sound device
+ * @return 0 if OK, -ve on error
+ */
+int hda_codec_init(struct udevice *dev);
+
+/**
+ * hda_codec_finish_init() - Finish setting up the HDA codec base address
+ *
+ * This should be called at the end of the probe() method.
+ *
+ * @dev: Sound device
+ * @return 0 if OK, -ve on error
+ */
+int hda_codec_finish_init(struct udevice *dev);
+
+#endif /* __HDA_CODEC_H_ */
diff --git a/include/log.h b/include/log.h
index d7f6471..7566ba7 100644
--- a/include/log.h
+++ b/include/log.h
@@ -14,7 +14,7 @@
/** Log levels supported, ranging from most to least important */
enum log_level_t {
- LOGL_EMERG = 0, /*U-Boot is unstable */
+ LOGL_EMERG = 0, /* U-Boot is unstable */
LOGL_ALERT, /* Action must be taken immediately */
LOGL_CRIT, /* Critical conditions */
LOGL_ERR, /* Error that prevents something from working */
@@ -111,11 +111,16 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
#endif
#if CONFIG_IS_ENABLED(LOG)
+#ifdef LOG_DEBUG
+#define _LOG_DEBUG 1
+#else
+#define _LOG_DEBUG 0
+#endif
/* Emit a log record if the level is less that the maximum */
#define log(_cat, _level, _fmt, _args...) ({ \
int _l = _level; \
- if (CONFIG_IS_ENABLED(LOG) && _l <= _LOG_MAX_LEVEL) \
+ if (CONFIG_IS_ENABLED(LOG) && (_l <= _LOG_MAX_LEVEL || _LOG_DEBUG)) \
_log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \
__func__, \
pr_fmt(_fmt), ##_args); \
diff --git a/include/pch.h b/include/pch.h
index 73994b8..046a5fd 100644
--- a/include/pch.h
+++ b/include/pch.h
@@ -11,7 +11,23 @@
#define BIOS_CTRL_BIOSWE BIT(0)
-/* Operations for the Platform Controller Hub */
+/* All the supported PCH ioctls */
+enum pch_req_t {
+ /* Returns HDA config info if Azalia V1CTL enabled, -ENOENT if not */
+ PCH_REQ_HDA_CONFIG,
+
+ PCH_REQ_TEST1, /* Test requests for sandbox driver */
+ PCH_REQ_TEST2,
+ PCH_REQ_TEST3,
+
+ PCH_REQ_COUNT, /* Number of ioctrls supported */
+};
+
+/**
+ * struct pch_ops - Operations for the Platform Controller Hub
+ *
+ * Consider using ioctl() to add rarely used or driver-specific operations.
+ */
struct pch_ops {
/**
* get_spi_base() - get the address of SPI base
@@ -49,6 +65,23 @@ struct pch_ops {
* @return 0 if OK, -ve on error (e.g. there is no IO base)
*/
int (*get_io_base)(struct udevice *dev, u32 *iobasep);
+
+ /**
+ * ioctl() - perform misc read/write operations
+ *
+ * This is a catch-all operation intended to avoid adding lots of
+ * methods to this uclass, of which few are commonly used. Uncommon
+ * operations that pertain only to a few devices in this uclass should
+ * use this method instead of adding new methods.
+ *
+ * @dev: PCH device to check
+ * @req: PCH request ID
+ * @data: Input/output data
+ * @size: Size of input data (and maximum size of output data)
+ * @return size of output data on sucesss, -ve on error
+ */
+ int (*ioctl)(struct udevice *dev, enum pch_req_t req, void *data,
+ int size);
};
#define pch_get_ops(dev) ((struct pch_ops *)(dev)->driver->ops)
@@ -90,4 +123,20 @@ int pch_get_gpio_base(struct udevice *dev, u32 *gbasep);
*/
int pch_get_io_base(struct udevice *dev, u32 *iobasep);
+/**
+ * pch_ioctl() - perform misc read/write operations
+ *
+ * This is a catch-all operation intended to avoid adding lots of
+ * methods to this uclass, of which few are commonly used. Uncommon
+ * operations that pertain only to a few devices in this uclass should
+ * use this method instead of adding new methods.
+ *
+ * @dev: PCH device to check
+ * @req: PCH request ID
+ * @data: Input/output data
+ * @size: Size of input data (and maximum size of output data)
+ * @return size of output data on sucesss, -ve on error
+ */
+int pch_ioctl(struct udevice *dev, ulong req, void *data, int size);
+
#endif
diff --git a/include/pci.h b/include/pci.h
index 041f8e3..936cfe9 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -735,12 +735,6 @@ extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int
extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index);
pci_dev_t pci_find_class(unsigned int find_class, int index);
-extern int pci_hose_config_device(struct pci_controller *hose,
- pci_dev_t dev,
- unsigned long io,
- pci_addr_t mem,
- unsigned long command);
-
extern int pci_hose_find_capability(struct pci_controller *hose, pci_dev_t dev,
int cap);
extern int pci_hose_find_cap_start(struct pci_controller *hose, pci_dev_t dev,
@@ -828,7 +822,7 @@ struct udevice;
*
* Every device on a PCI bus has this per-child data.
*
- * It can be accessed using dev_get_parent_priv(dev) if dev->parent is a
+ * It can be accessed using dev_get_parent_platdata(dev) if dev->parent is a
* PCI bus (i.e. UCLASS_PCI)
*
* @devfn: Encoded device and function index - see PCI_DEVFN()
diff --git a/include/pci_ids.h b/include/pci_ids.h
index fdda679..bd59578 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -41,6 +41,7 @@
#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402
+#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
#define PCI_BASE_CLASS_MEMORY 0x05
@@ -1363,6 +1364,7 @@
#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
#define PCI_DEVICE_ID_CREATIVE_20K1 0x0005
#define PCI_DEVICE_ID_CREATIVE_20K2 0x000b
+#define PCI_DEVICE_ID_CREATIVE_CA01322 0x0011
#define PCI_SUBDEVICE_ID_CREATIVE_SB0760 0x0024
#define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041
#define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042
@@ -2827,6 +2829,7 @@
#define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd
#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de
#define PCI_DEVICE_ID_INTEL_ICH7_21 0x27df
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_HDMI 0x2806
#define PCI_DEVICE_ID_INTEL_ICH8_0 0x2810
#define PCI_DEVICE_ID_INTEL_ICH8_1 0x2811
#define PCI_DEVICE_ID_INTEL_ICH8_2 0x2812
@@ -3025,6 +3028,8 @@
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_AHCI 0x9c03
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LPC 0x9c45
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_AHCI 0x9c83
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_HDA 0x9ca0
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_ADSP 0x9cb6
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LPC 0x9cc3
#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152
diff --git a/include/sound.h b/include/sound.h
index b7959cc..47de9fa 100644
--- a/include/sound.h
+++ b/include/sound.h
@@ -54,7 +54,7 @@ void sound_create_square_wave(uint sample_rate, unsigned short *data, int size,
/* Operations for sound */
struct sound_ops {
/**
- * setup() - Set up to play a sound
+ * setup() - Set up to play a sound (optional)
*/
int (*setup)(struct udevice *dev);
@@ -67,6 +67,28 @@ struct sound_ops {
* @return 0 if OK, -ve on error
*/
int (*play)(struct udevice *dev, void *data, uint data_size);
+
+ /**
+ * start_beep() - Start beeping (optional)
+ *
+ * This tells the sound hardware to start a beep. It will continue until
+ * stopped by sound_stop_beep().
+ *
+ * @dev: Sound device
+ * @frequency_hz: Beep frequency in hertz
+ * @return if OK, -ENOSYS if not supported, -ve on error
+ */
+ int (*start_beep)(struct udevice *dev, int frequency_hz);
+
+ /**
+ * stop_beep() - Stop beeping (optional)
+ *
+ * This tells the sound hardware to stop a previously started beep.
+ *
+ * @dev: Sound device
+ * @return if OK, -ve on error
+ */
+ int (*stop_beep)(struct udevice *dev);
};
#define sound_get_ops(dev) ((struct sound_ops *)(dev)->driver->ops)
@@ -87,6 +109,28 @@ int sound_setup(struct udevice *dev);
int sound_beep(struct udevice *dev, int msecs, int frequency_hz);
/**
+ * sound_start_beep() - Start beeping
+ *
+ * This tells the sound hardware to start a beep. It will continue until stopped
+ * by sound_stop_beep().
+ *
+ * @dev: Sound device
+ * @frequency_hz: Beep frequency in hertz
+ * @return if OK, -ve on error
+ */
+int sound_start_beep(struct udevice *dev, int frequency_hz);
+
+/**
+ * sound_stop_beep() - Stop beeping
+ *
+ * This tells the sound hardware to stop a previously started beep.
+ *
+ * @dev: Sound device
+ * @return if OK, -ve on error
+ */
+int sound_stop_beep(struct udevice *dev);
+
+/**
* sound_find_codec_i2s() - Called by sound drivers to locate codec and i2s
*
* This finds the audio codec and i2s devices and puts them in the uclass's
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1b08996..49857c5 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -30,6 +30,7 @@ obj-y += ofnode.o
obj-$(CONFIG_OSD) += osd.o
obj-$(CONFIG_DM_VIDEO) += panel.o
obj-$(CONFIG_DM_PCI) += pci.o
+obj-$(CONFIG_PCH) += pch.o
obj-$(CONFIG_PHY) += phy.o
obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
obj-$(CONFIG_DM_PWM) += pwm.o
diff --git a/test/dm/pch.c b/test/dm/pch.c
new file mode 100644
index 0000000..54e33d1
--- /dev/null
+++ b/test/dm/pch.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pch.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that sandbox PCH works correctly */
+static int dm_test_pch_base(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ u32 gbase, iobase;
+ ulong sbase;
+
+ ut_assertok(uclass_first_device_err(UCLASS_PCH, &dev));
+ ut_assertok(pch_get_spi_base(dev, &sbase));
+ ut_asserteq(0x10, sbase);
+
+ ut_asserteq(0, sandbox_get_pch_spi_protect(dev));
+ ut_assertok(pch_set_spi_protect(dev, true));
+ ut_asserteq(1, sandbox_get_pch_spi_protect(dev));
+
+ ut_assertok(pch_get_gpio_base(dev, &gbase));
+ ut_asserteq(0x20, gbase);
+
+ ut_assertok(pch_get_io_base(dev, &iobase));
+ ut_asserteq(0x30, iobase);
+
+ return 0;
+}
+DM_TEST(dm_test_pch_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test sandbox PCH ioctl */
+static int dm_test_pch_ioctl(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ char data;
+
+ ut_assertok(uclass_first_device_err(UCLASS_PCH, &dev));
+
+ ut_asserteq(-ENOSYS, pch_ioctl(dev, PCH_REQ_TEST1, NULL, 0));
+
+ ut_asserteq('a', pch_ioctl(dev, PCH_REQ_TEST2, "a", 1));
+
+ ut_asserteq(1, pch_ioctl(dev, PCH_REQ_TEST3, &data, 1));
+ ut_asserteq('x', data);
+
+ return 0;
+}
+DM_TEST(dm_test_pch_ioctl, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/sound.c b/test/dm/sound.c
index 7d0b36e..3767abb 100644
--- a/test/dm/sound.c
+++ b/test/dm/sound.c
@@ -32,3 +32,24 @@ static int dm_test_sound(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_sound, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test of the 'start beep' operations */
+static int dm_test_sound_beep(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ /* check probe success */
+ ut_assertok(uclass_first_device_err(UCLASS_SOUND, &dev));
+ ut_asserteq(-ENOSYS, sound_start_beep(dev, 100));
+ ut_asserteq(0, sandbox_get_beep_frequency(dev));
+
+ sandbox_set_allow_beep(dev, true);
+ ut_asserteq(0, sound_start_beep(dev, 100));
+ ut_asserteq(100, sandbox_get_beep_frequency(dev));
+
+ ut_asserteq(0, sound_stop_beep(dev));
+ ut_asserteq(0, sandbox_get_beep_frequency(dev));
+
+ return 0;
+}
+DM_TEST(dm_test_sound_beep, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);