From 26eccd200deede1eb7826747f3a39fa16560e19a Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Wed, 9 Nov 2011 02:28:21 +0530 Subject: ALSA: hda: Add support for Tegra HDA platform driver interface Bug 872652 Change-Id: I10c18afb496a605d47a09c7c6dc924459b4728eb Signed-off-by: Sumit Bhattacharya Reviewed-on: http://git-master/r/64335 Reviewed-by: Bharat Nihalani Tested-by: Gerrit_Virtual_Submit Rebase-Id: Rbaf53a2382f50c1a552bafd9d54840779160b055 --- sound/pci/hda/Kconfig | 7 ++ sound/pci/hda/hda_intel.c | 170 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 3 deletions(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 083731dcea9c..522c4fd958dc 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -91,6 +91,13 @@ config SND_HDA_PLATFORM_DRIVER This interface can be used by platforms which have an Azalia controller not installed on a PCI bus. +config SND_HDA_PLATFORM_NVIDIA_TEGRA + bool "Build NVIDIA Tegra platform driver interface for HD-audio driver" + depends on SND_HDA_PLATFORM_DRIVER + help + Say Y here to build NVIDIA Tegra platform driver interface for + HD-audio driver. + config SND_HDA_CODEC_REALTEK bool "Build Realtek HD-audio codec support" default y diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d1cfd80bc17b..7b7fc90b1f0c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -322,6 +322,32 @@ enum { #define NVIDIA_HDA_OSTRM_COH 0x4c #define NVIDIA_HDA_ENABLE_COHBIT 0x01 +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA +/* Defines for Nvidia Tegra HDA support */ +#define NVIDIA_TEGRA_HDA_BAR0_OFFSET 0x8000 + +#define NVIDIA_TEGRA_HDA_CFG_CMD_OFFSET 0x1004 +#define NVIDIA_TEGRA_HDA_CFG_BAR0_OFFSET 0x1010 + +#define NVIDIA_TEGRA_HDA_ENABLE_IO_SPACE (1 << 0) +#define NVIDIA_TEGRA_HDA_ENABLE_MEM_SPACE (1 << 1) +#define NVIDIA_TEGRA_HDA_ENABLE_BUS_MASTER (1 << 2) +#define NVIDIA_TEGRA_HDA_ENABLE_SERR (1 << 8) +#define NVIDIA_TEGRA_HDA_DISABLE_INTR (1 << 10) +#define NVIDIA_TEGRA_HDA_BAR0_INIT_PROGRAM 0xFFFFFFFF +#define NVIDIA_TEGRA_HDA_BAR0_FINAL_PROGRAM (1 << 14) + +/* IPFS */ +#define NVIDIA_TEGRA_HDA_IPFS_CONFIG 0x180 +#define NVIDIA_TEGRA_HDA_IPFS_EN_FPCI 0x1 + +#define NVIDIA_TEGRA_HDA_IPFS_FPCI_BAR0 0x80 +#define NVIDIA_TEGRA_HDA_FPCI_BAR0_START 0x40 + +#define NVIDIA_TEGRA_HDA_IPFS_INTR_MASK 0x188 +#define NVIDIA_TEGRA_HDA_IPFS_EN_INTR (1 << 16) +#endif /* CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA */ + /* Defines for Intel SCH HDA snoop control */ #define INTEL_SCH_HDA_DEVC 0x78 #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) @@ -406,6 +432,9 @@ struct azx { /* pci resources */ unsigned long addr; void __iomem *remap_addr; +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA + void __iomem *remap_config_addr; +#endif int irq; #ifdef CONFIG_SND_HDA_PLATFORM_DRIVER @@ -470,6 +499,7 @@ enum { AZX_DRIVER_SIS, AZX_DRIVER_ULI, AZX_DRIVER_NVIDIA, + AZX_DRIVER_NVIDIA_TEGRA, AZX_DRIVER_TERA, AZX_DRIVER_CTX, AZX_DRIVER_GENERIC, @@ -515,6 +545,7 @@ static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_SIS] = "HDA SIS966", [AZX_DRIVER_ULI] = "HDA ULI M5461", [AZX_DRIVER_NVIDIA] = "HDA NVidia", + [AZX_DRIVER_NVIDIA_TEGRA] = "HDA NVIDIA Tegra", [AZX_DRIVER_TERA] = "HDA Teradici", [AZX_DRIVER_CTX] = "HDA Creative", [AZX_DRIVER_GENERIC] = "HD-Audio Generic", @@ -523,6 +554,48 @@ static char *driver_short_names[] __devinitdata = { /* * macros for easy use */ +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA +#define MASK_LONG_ALIGN 0x3UL +#define SHIFT_BYTE 3 +#define SHIFT_BITS(reg) ((reg & MASK_LONG_ALIGN) << SHIFT_BYTE) +#define ADDR_ALIGN_L(base, reg) (base + (reg & ~MASK_LONG_ALIGN)) +#define MASK(bits) (BIT(bits) - 1) +#define MASK_REG(reg, bits) (MASK(bits) << SHIFT_BITS(reg)) + +#define tegra_write(base, reg, val, bits) \ + writel((readl(ADDR_ALIGN_L(base, reg)) & ~MASK_REG(reg, bits)) | \ + ((val) << SHIFT_BITS(reg)), ADDR_ALIGN_L(base, reg)) + +#define tegra_read(base, reg, bits) \ + ((readl(ADDR_ALIGN_L(base, reg)) >> SHIFT_BITS(reg)) & MASK(bits)) + +#define azx_writel(chip, reg, value) \ + writel(value, (chip)->remap_addr + ICH6_REG_##reg) +#define azx_readl(chip, reg) \ + readl((chip)->remap_addr + ICH6_REG_##reg) +#define azx_writew(chip, reg, value) \ + tegra_write((chip)->remap_addr, ICH6_REG_##reg, value, 16) +#define azx_readw(chip, reg) \ + tegra_read((chip)->remap_addr, ICH6_REG_##reg, 16) +#define azx_writeb(chip, reg, value) \ + tegra_write((chip)->remap_addr, ICH6_REG_##reg, value, 8) +#define azx_readb(chip, reg) \ + tegra_read((chip)->remap_addr, ICH6_REG_##reg, 8) + +#define azx_sd_writel(dev, reg, value) \ + writel(value, (dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_readl(dev, reg) \ + readl((dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_writew(dev, reg, value) \ + tegra_write((dev)->sd_addr, ICH6_REG_##reg, value, 16) +#define azx_sd_readw(dev, reg) \ + tegra_read((dev)->sd_addr, ICH6_REG_##reg, 16) +#define azx_sd_writeb(dev, reg, value) \ + tegra_write((dev)->sd_addr, ICH6_REG_##reg, value, 8) +#define azx_sd_readb(dev, reg) \ + tegra_read((dev)->sd_addr, ICH6_REG_##reg, 8) + +#else /* CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA */ #define azx_writel(chip,reg,value) \ writel(value, (chip)->remap_addr + ICH6_REG_##reg) #define azx_readl(chip,reg) \ @@ -549,6 +622,8 @@ static char *driver_short_names[] __devinitdata = { #define azx_sd_readb(dev,reg) \ readb((dev)->sd_addr + ICH6_REG_##reg) +#endif /* CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA */ + /* for pcm support */ #define get_azx_dev(substream) (substream->runtime->private_data) @@ -1142,9 +1217,57 @@ static void azx_init_pci(struct azx *chip) } #ifdef CONFIG_SND_HDA_PLATFORM_DRIVER -/* Platform driver specific initiallization */ +/* + * initialize the platform specific registers + */ +static void reg_update_bits(void __iomem *base, unsigned int reg, + unsigned int mask, unsigned int val) +{ + unsigned int data; + + data = readl(base + reg); + data &= ~mask; + data |= (val & mask); + writel(data, base + reg); +} + static void azx_init_platform(struct azx *chip) { + switch (chip->driver_type) { +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA + case AZX_DRIVER_NVIDIA_TEGRA: + /*Enable the PCI access */ + reg_update_bits(chip->remap_config_addr, + NVIDIA_TEGRA_HDA_IPFS_CONFIG, + NVIDIA_TEGRA_HDA_IPFS_EN_FPCI, + NVIDIA_TEGRA_HDA_IPFS_EN_FPCI); + /* Enable MEM/IO space and bus master */ + reg_update_bits(chip->remap_config_addr, + NVIDIA_TEGRA_HDA_CFG_CMD_OFFSET, 0x507, + NVIDIA_TEGRA_HDA_ENABLE_MEM_SPACE | + NVIDIA_TEGRA_HDA_ENABLE_IO_SPACE | + NVIDIA_TEGRA_HDA_ENABLE_BUS_MASTER | + NVIDIA_TEGRA_HDA_ENABLE_SERR); + reg_update_bits(chip->remap_config_addr, + NVIDIA_TEGRA_HDA_CFG_BAR0_OFFSET, 0xFFFFFFFF, + NVIDIA_TEGRA_HDA_BAR0_INIT_PROGRAM); + reg_update_bits(chip->remap_config_addr, + NVIDIA_TEGRA_HDA_CFG_BAR0_OFFSET, 0xFFFFFFFF, + NVIDIA_TEGRA_HDA_BAR0_FINAL_PROGRAM); + reg_update_bits(chip->remap_config_addr, + NVIDIA_TEGRA_HDA_IPFS_FPCI_BAR0, 0xFFFFFFFF, + NVIDIA_TEGRA_HDA_FPCI_BAR0_START); + reg_update_bits(chip->remap_config_addr, + NVIDIA_TEGRA_HDA_IPFS_INTR_MASK, + NVIDIA_TEGRA_HDA_IPFS_EN_INTR, + NVIDIA_TEGRA_HDA_IPFS_EN_INTR); + break; +#endif + default: + break; + } + + return; } static void azx_platform_enable_clocks(struct azx *chip) @@ -2611,6 +2734,14 @@ static void __devinit check_msi(struct azx *chip) } } +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA +static const char *tegra_clk_names[] __initdata = { + "hda", + "hda2codec", + "hda2hdmi", +}; +static struct clk *tegra_clks[ARRAY_SIZE(tegra_clk_names)]; +#endif /* * constructor @@ -2710,6 +2841,26 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, if (chip->pdev) { struct resource *res, *region; + /* Do platform specific initialization */ + switch (chip->driver_type) { +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA + case AZX_DRIVER_NVIDIA_TEGRA: + chip->platform_clk_count = ARRAY_SIZE(tegra_clk_names); + for (i = 0; i < chip->platform_clk_count; i++) { + tegra_clks[i] = clk_get(&pdev->dev, + tegra_clk_names[i]); + if (IS_ERR_OR_NULL(tegra_clks[i])) { + err = PTR_ERR(tegra_clks[i]); + goto errout; + } + } + chip->platform_clks = tegra_clks; + break; +#endif + default: + break; + } + azx_platform_enable_clocks(chip); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2728,7 +2879,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } chip->addr = res->start; - chip->remap_addr = devm_ioremap(chip->dev, res->start, + chip->remap_addr = devm_ioremap(chip->dev, + res->start, resource_size(res)); if (chip->remap_addr == NULL) { snd_printk(KERN_ERR SFX "ioremap error\n"); @@ -2736,9 +2888,17 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA + if (chip->driver_type == AZX_DRIVER_NVIDIA_TEGRA) { + chip->remap_config_addr = chip->remap_addr; + chip->remap_addr += NVIDIA_TEGRA_HDA_BAR0_OFFSET; + chip->addr += NVIDIA_TEGRA_HDA_BAR0_OFFSET; + } +#endif + azx_init_platform(chip); } -#endif +#endif /* CONFIG_SND_HDA_PLATFORM_DRIVER */ if (azx_acquire_irq(chip, 0) < 0) { err = -EBUSY; @@ -3132,6 +3292,10 @@ static int __devexit azx_remove_platform(struct platform_device *pdev) } static const struct platform_device_id azx_platform_ids[] = { +#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA + { "tegra30-hda", + .driver_data = AZX_DRIVER_NVIDIA_TEGRA | AZX_DCAPS_RIRB_DELAY }, +#endif { }, }; MODULE_DEVICE_TABLE(platform, azx_platform_ids); -- cgit v1.2.3