HDA Driver分析

Linux ALSA音频框架分析五:HDA Driver分析
一 概述
HDA(High Definition Audio)是intel设计的用来取代AC97的音频标准,硬件架构上由hda dodec和hda controller组成见图1:在这里插入图片描述
二 Stream 的概念
HAD 引入了 Streams 的概念来组织数据,并通过 HDA Link 总线进行数据传输。Stream 是一个在系统内存缓冲区和 codec 之间创建的逻辑的或虚拟的连接用以来呈现数据,该连接由单个 DMA 通道通过 Link总线驱动。一个 Stream 包含一个或多个相关的组件或数据 channels,每个 channel 都被动态绑定到 codec 中的一个单一 converter 上来呈现。例如,一个立体声 Stream 包括两个 channels:左和右,在此 Stream 中的每一个采样点应该包括两个采样数据:左和右。这些采样在缓冲区中和在链路上传输的时候是组合在一起的,但是却在 codec 中连接不同的DA 转换器。

三 HDA driver 分析

3.1重要结构体azx

azx 是hda controller的结构体,其中struct hda_bus bus、struct snd_card *card、struct pci_dev *pci是三个重要结构体,分别表示总线、卡、设备。其kernel4.6版的结构体见下:

struct azx {
struct hda_bus bus;

struct snd_card *card;
struct pci_dev *pci;
int dev_index;

/* chip type specific */
int driver_type;
unsigned int driver_caps;
int playback_streams;
int playback_index_offset;
int capture_streams;
int capture_index_offset;
int num_streams;
const int *jackpoll_ms; /* per-card jack poll interval */

/* Register interaction. */
const struct hda_controller_ops *ops;

/* position adjustment callbacks */
azx_get_pos_callback_t get_position[2];
azx_get_delay_callback_t get_delay[2];

/* locks */
struct mutex open_mutex; /* Prevents concurrent open/close operations */

/* PCM */
struct list_head pcm_list; /* azx_pcm list */

/* HD codec */
int  codec_probe_mask; /* copied from probe_mask option */
unsigned int beep_mode;

#ifdef CONFIG_SND_HDA_PATCH_LOADER
const struct firmware *fw;
#endif

/* flags */
int bdl_pos_adj;
int poll_count;
unsigned int running:1;
unsigned int single_cmd:1;
unsigned int polling_mode:1;
unsigned int msi:1;
unsigned int probing:1; /* codec probing phase */
unsigned int snoop:1;
unsigned int align_buffer_size:1;
unsigned int region_requested:1;
unsigned int disabled:1; /* disabled by vga_switcheroo */

#ifdef CONFIG_SND_HDA_DSP_LOADER
struct azx_dev saved_azx_dev;
#endif
};

3.2 hda dirver需要实现的操作功能函数

操作函数主要有两类,一个是IO级操作函数,即寄存器读写;一个是功能级操作函数;

IO级操作:

struct hdac_io_ops {
/* mapped register accesses */
void (*reg_writel)(u32 value, u32 __iomem *addr);
u32 (*reg_readl)(u32 __iomem *addr);
void (*reg_writew)(u16 value, u16 __iomem *addr);
u16 (*reg_readw)(u16 __iomem *addr);
void (*reg_writeb)(u8 value, u8 __iomem *addr);
u8 (*reg_readb)(u8 __iomem addr);
/
Allocation ops */
int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size,
struct snd_dma_buffer *buf);
void (*dma_free_pages)(struct hdac_bus *bus,
struct snd_dma_buffer *buf);
};

功能级操作:

struct hda_controller_ops {
/* Disable msi if supported, PCI only */
int (*disable_msi_reset_irq)(struct azx *);
int (*substream_alloc_pages)(struct azx *chip,
struct snd_pcm_substream *substream,
size_t size);
int (*substream_free_pages)(struct azx *chip,
struct snd_pcm_substream *substream);
void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream,
struct vm_area_struct area);
/
Check if current position is acceptable */
int (*position_check)(struct azx *chip, struct azx_dev azx_dev);
/
enable/disable the link power */
int (*link_power)(struct azx *chip, bool enable);
};

3.3 HDA dirver初始化流程

hda dirver的初始化流程见图2:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值