[alsa-devel] [PATCH 2/2] ALSA: hda - Add driver for Tegra SoC HDA

Dylan Reid dgreid at chromium.org
Thu Apr 10 06:20:24 CEST 2014


On Wed, Apr 9, 2014 at 12:43 AM, Takashi Iwai <tiwai at suse.de> wrote:
> At Tue,  8 Apr 2014 12:15:33 -0700,
> Dylan Reid wrote:
>>
>> diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
>> index ac17c3f..4f6ee6b 100644
>> --- a/sound/pci/hda/Kconfig
>> +++ b/sound/pci/hda/Kconfig
>> @@ -20,6 +20,20 @@ config SND_HDA_INTEL
>>         To compile this driver as a module, choose M here: the module
>>         will be called snd-hda-intel.
>>
>> +config SND_HDA_TEGRA
>> +     tristate "Tegra HD Audio"
>> +     select SND_HDA
>
> Does (or should) this be build generically?  Or any arch-specific
> dependency, or maybe at least "depends on OF"?

Thanks Takashi,

Yes I think it should depend on OF and ARCH_TEGRA.

>
>> +     help
>> +       Say Y here to support the HDA controller present in Nvidia
>> +       Tegra SoCs
>> +
>> +       This options enables support for the HD Audio controller
>> +       present in some Nvidia Tegra SoCs, used to communicate audio
>> +       to the HDMI output.
>> +
>> +       To compile this driver as a module, choose M here: the module
>> +       will be called snd-hda-tegra.
>> +
>>  if SND_HDA
>>
>>  config SND_HDA_DSP_LOADER
>> diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
>> index d0d0c19..194f3093 100644
>> --- a/sound/pci/hda/Makefile
>> +++ b/sound/pci/hda/Makefile
>> @@ -1,5 +1,6 @@
>>  snd-hda-intel-objs := hda_intel.o
>>  snd-hda-controller-objs := hda_controller.o
>> +snd-hda-tegra-objs := hda_tegra.o
>>  # for haswell power well
>>  snd-hda-intel-$(CONFIG_SND_HDA_I915) +=      hda_i915.o
>>
>> @@ -47,3 +48,4 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
>>  # otherwise the codec patches won't be hooked before the PCI probe
>>  # when built in kernel
>>  obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
>> +obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o
>> diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
>> new file mode 100644
>> index 0000000..c36bbca
>> --- /dev/null
>> +++ b/sound/pci/hda/hda_tegra.c
>> @@ -0,0 +1,695 @@
>> +/*
>> + *
>> + *  Implementation of primary alsa driver code base for Tegra HDA.
>> + *
>> + *  This program is free software; you can redistribute it and/or modify it
>> + *  under the terms of the GNU General Public License as published by the Free
>> + *  Software Foundation; either version 2 of the License, or (at your option)
>> + *  any later version.
>> + *
>> + *  This program is distributed in the hope that it will be useful, but WITHOUT
>> + *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + *  more details.
>> + *
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/clocksource.h>
>> +#include <linux/delay.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/dma-mapping.h>
>> +#include <linux/moduleparam.h>
>> +#include <linux/init.h>
>> +#include <linux/slab.h>
>> +#include <linux/mutex.h>
>> +#include <linux/reboot.h>
>> +#include <linux/io.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/of_device.h>
>> +#include <linux/time.h>
>> +#include <linux/completion.h>
>> +
>> +#include <sound/core.h>
>> +#include <sound/initval.h>
>> +#include <linux/firmware.h>
>> +#include "hda_codec.h"
>> +#include "hda_controller.h"
>> +#include "hda_priv.h"
>> +
>> +#define DRV_NAME "tegra-hda"
>> +
>> +/* 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)
>> +
>> +struct hda_tegra_data {
>> +     struct azx chip;
>> +     struct platform_device *pdev;
>> +     struct clk **platform_clks;
>> +     int platform_clk_count;
>> +     void __iomem *remap_config_addr;
>> +};
>> +
>> +static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
>> +module_param_array(probe_mask, int, NULL, 0444);
>> +MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
>> +
>> +static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
>> +static int *power_save_addr = &power_save;
>> +module_param(power_save, bint, 0644);
>> +MODULE_PARM_DESC(power_save,
>> +              "Automatic power-saving timeout (in seconds, 0 = disable).");
>> +
>> +/*
>> + * DMA page allocation ops.
>> + */
>> +static int dma_alloc_pages(struct azx *chip,
>> +                        int type,
>> +                        size_t size,
>> +                        struct snd_dma_buffer *buf)
>> +{
>> +     return snd_dma_alloc_pages(type,
>> +                                chip->card->dev,
>> +                                size, buf);
>> +}
>> +
>> +static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf)
>> +{
>> +     snd_dma_free_pages(buf);
>> +}
>> +
>> +static int substream_alloc_pages(struct azx *chip,
>> +                              struct snd_pcm_substream *substream,
>> +                              size_t size)
>> +{
>> +     struct azx_dev *azx_dev = get_azx_dev(substream);
>> +
>> +     azx_dev->bufsize = 0;
>> +     azx_dev->period_bytes = 0;
>> +     azx_dev->format_val = 0;
>> +     return snd_pcm_lib_malloc_pages(substream, size);
>> +}
>> +
>> +static int substream_free_pages(struct azx *chip,
>> +                             struct snd_pcm_substream *substream)
>> +{
>> +     return snd_pcm_lib_free_pages(substream);
>> +}
>> +
>> +/*
>> + * Register access ops. Tegra HDA register access is DWORD only.
>> + */
>> +#define MASK_LONG_ALIGN              0x3UL
>> +#define SHIFT_BYTE           3
>> +#define SHIFT_BITS(addr)     \
>> +     (((unsigned int)(addr) & MASK_LONG_ALIGN) << SHIFT_BYTE)
>> +#define ADDR_ALIGN_L(addr)   \
>> +     (void *)((unsigned int)(addr) & ~MASK_LONG_ALIGN)
>> +#define MASK(bits)           (BIT(bits) - 1)
>> +#define MASK_REG(addr, bits) (MASK(bits) << SHIFT_BITS(addr))
>
> This results in lots of compile warnings on 64bit machines.

Yes it does, thanks for checking, I'll fix that up.

>
> sound/pci/hda/hda_tegra.c: In function ‘tegra_hda_writew’:
> sound/pci/hda/hda_tegra.c:128:4: warning: cast from pointer to integer
> of different size [-Wpointer-to-int-cast]
>   (((unsigned int)(addr) & MASK_LONG_ALIGN) << SHIFT_BYTE)
>
>
> thanks,
>
> Takashi


More information about the Alsa-devel mailing list