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

Takashi Iwai tiwai at suse.de
Wed Apr 9 09:43:22 CEST 2014


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"?

> +	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.

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