From c4db02fb9289235a0875c6226fe7fd3dd18adf55 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Fri, 16 Dec 2011 10:37:05 -0800 Subject: Add beep for x86 chormeos. Implement the VbExBeep function so that the DEV screen can beep. Much of this code was coppied from coreboot. BUG=chrome-os-partner:7114 TEST=manual, check that Stumpy beeps on DEV screen timeout and when booting from USB with dev_boot_usb=0. Change-Id: Icd4eabb0b10cc3d226db71e6a2b52d3ed7eb25ef Signed-off-by: Dylan Reid Reviewed-on: https://gerrit.chromium.org/gerrit/13110 Reviewed-by: Stefan Reinauer --- board/chromebook-x86/chromeos/Makefile | 1 + board/chromebook-x86/chromeos/hda_codec.c | 145 ++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 board/chromebook-x86/chromeos/hda_codec.c (limited to 'board') diff --git a/board/chromebook-x86/chromeos/Makefile b/board/chromebook-x86/chromeos/Makefile index a3eb6ec90f..c1e8f71ce0 100644 --- a/board/chromebook-x86/chromeos/Makefile +++ b/board/chromebook-x86/chromeos/Makefile @@ -40,6 +40,7 @@ LIB = $(obj)libchromeos_board.a COBJS-$(CONFIG_CHROMEOS) += cros_gpio.o COBJS-$(CONFIG_CHROMEOS) += power_management.o +COBJS-$(CONFIG_CHROMEOS) += hda_codec.o COBJS := $(COBJS-y) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/chromebook-x86/chromeos/hda_codec.c b/board/chromebook-x86/chromeos/hda_codec.c new file mode 100644 index 0000000000..21a0db5a56 --- /dev/null +++ b/board/chromebook-x86/chromeos/hda_codec.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +/* Implementation of per-board codec beeping */ + +#include +#include +#include +#include +#include + +#define HDA_CMD_REG 0x5C +#define HDA_ICII_REG 0x64 +#define HDA_ICII_BUSY (1 << 0) +#define HDA_ICII_VALID (1 << 1) + +/** + * Wait 50usec for the codec to indicate it is ready + * no response would imply that the codec is non-operative + */ +static int wait_for_ready(uint32_t base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration + */ + + int timeout = 50; + + while (timeout--) { + uint32_t reg32 = readl(base + HDA_ICII_REG); + asm("" ::: "memory"); + if (!(reg32 & HDA_ICII_BUSY)) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Wait 50usec for the codec to indicate that it accepted + * the previous command. No response would imply that the code + * is non-operative + */ +static int wait_for_valid(uint32_t base) +{ + uint32_t reg32; + + /* Send the verb to the codec */ + reg32 = readl(base + HDA_ICII_REG); + reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID; + writel(reg32, base + HDA_ICII_REG); + + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration + */ + + int timeout = 50; + while (timeout--) { + reg32 = readl(base + HDA_ICII_REG); + if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == + HDA_ICII_VALID) + return 0; + udelay(1); + } + + return -1; +} + +/* Wait for the codec to be ready, write the verb, then wait for the + * codec to be valid. + */ +int write_one_verb(uint32_t base, uint32_t val) +{ + if (wait_for_ready(base) == -1) + return -1; + + writel(val, base + HDA_CMD_REG); + + if (wait_for_valid(base) == -1) + return -1; + + return 0; +} + +/* Supported sound devices. + */ +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_HDA}, + {} +}; + +/* Find the base address to talk tot he HDA codec. + */ +static u32 get_hda_base(void) +{ + pci_dev_t devbusfn; + u32 pci_mem_base; + + devbusfn = pci_find_devices(supported, 0); + if (devbusfn < 0) { + printf("Audio: Controller not found !\n"); + return 0; + } + + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base); + pci_mem_base = pci_mem_to_phys(devbusfn, pci_mem_base); + return pci_mem_base; +} + +static const u32 beep_cmd[] = { + 0x00170500, /* power up codec */ + 0x00270500, /* power up DAC */ + 0x00670500, /* power up speaker */ + 0x00670740, /* enable speaker output */ + 0x0023B04B, /* set DAC gain */ + 0x00C70A0C, /* enable beep generator 1 kHz */ +}; + +void enable_beep(void) +{ + uint32_t base; + int i; + + base = get_hda_base(); + for (i = 0; i < sizeof(beep_cmd)/sizeof(beep_cmd[0]); i++) { + if (write_one_verb(base, beep_cmd[i])) + return; + } +} + +void disable_beep(void) +{ + uint32_t base; + + base = get_hda_base(); + write_one_verb(base, 0x00C70A00); /* Disable beep gen */ +} -- cgit v1.2.3