summaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_intel.c
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-11-09 02:28:21 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:50:06 -0800
commit26eccd200deede1eb7826747f3a39fa16560e19a (patch)
treeea4ec2d286d771130693f806c2674728e560b0fb /sound/pci/hda/hda_intel.c
parent6191523b8681156b3ff30cc3a667d6203a62bb60 (diff)
ALSA: hda: Add support for Tegra HDA platform driver interface
Bug 872652 Change-Id: I10c18afb496a605d47a09c7c6dc924459b4728eb Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/64335 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Gerrit_Virtual_Submit Rebase-Id: Rbaf53a2382f50c1a552bafd9d54840779160b055
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r--sound/pci/hda/hda_intel.c170
1 files changed, 167 insertions, 3 deletions
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);