云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > 音频设备驱动

音频设备驱动

  • 62 次阅读
  • 3 次下载
  • 2025/5/4 13:02:02

3 int (*open)(struct snd_pcm_substream *substream);//打开 4 int (*close)(struct snd_pcm_substream *substream);//关闭 5 int (*ioctl)(struct snd_pcm_substream * substream, 6 unsigned int cmd, void *arg);//io 控制

7 int (*hw_params)(struct snd_pcm_substream *substream, 8 struct snd_pcm_hw_params *params);//硬件参数

9 int (*hw_free)(struct snd_pcm_substream *substream); //资源释放 10 int (*prepare)(struct snd_pcm_substream *substream);//准备 11 //在PCM 被开始、停止或暂停时调用

12 int (*trigger)(struct snd_pcm_substream *substream, int cmd);

13 snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);// 当前缓冲区的硬件位置 14 //缓冲区拷贝

15 int (*copy)(struct snd_pcm_substream *substream, int channel, 16 snd_pcm_uframes_t pos,

17 void __user *buf, snd_pcm_uframes_t count);

18 int (*silence)(struct snd_pcm_substream *substream, int channel, 19 snd_pcm_uframes_t pos, snd_pcm_uframes_t count);

20 struct page *(*page)(struct snd_pcm_substream *substream, 21 unsigned long offset);

22 int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); 23 int (*ack)(struct snd_pcm_substream *substream); 24 };

snd_pcm_ops 中的所有操作都需事先通过snd_pcm_substream_chip()获得xxxchip 指针,例如: int xxx() {

struct xxxchip *chip = snd_pcm_substream_chip(substream); ... }

当1 个PCM 子流被打开时,snd_pcm_ops 中的open()函数将被调用,在这个函数中,至少需要初始化

runtime->hw 字段,代码清单17.9 给出了open()函数的范例。 代码清单17.9 snd_pcm_ops 结构体中open()函数

1 static int snd_xxx_open(struct snd_pcm_substream *substream) 2 {

3 //从子流获得xxxchip 指针

4 struct xxxchip *chip = snd_pcm_substream_chip(substream); 5 //获得PCM 运行时信息指针

6 struct snd_pcm_runtime *runtime = substream->runtime; 7 ...

8 //初始化runtime->hw

9 runtime->hw = snd_xxxchip_playback_hw; 10 return 0;

11 }

上述代码中的snd_xxxchip_playback_hw 是预先定义的硬件描述。在open()函数中,可以分配1 段私有数

据。如果硬件配置需要更多的限制,也需设置硬件限制。

当PCM 子流被关闭时,close()函数将被调用。如果open()函数中分配了私有数据,则在close()函数中应

该释放substream 的私有数据,代码清单17.10 给出了close()函数的范例。 代码清单17.10 snd_pcm_ops 结构体中close()函数

1 static int snd_xxx_close(struct snd_pcm_substream *substream) 2 {

3 //释放子流私有数据

4 kfree(substream->runtime->private_data); 5 //... 6 }

驱动中通常可以给snd_pcm_ops 的ioctl()成员函数传递通用的snd_pcm_lib_ioctl()函数。 snd_pcm_ops 的hw_params()成员函数将在应用程序设置硬件参数(PCM 子流的周期大小、缓冲区大小和格

式等)的时候被调用,它的形式如下:

static int snd_xxx_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *hw_params);

在这个函数中,将完成大量硬件设置,甚至包括缓冲区分配,这时可调用如下辅助函数: snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); 仅当DMA 缓冲区已被预先分配的情况下,上述调用才可成立。

与hw_params()对应的函数是hw_free(),它释放由hw_params()分配的资源,例如,通过如下调用释放

snd_pcm_lib_malloc_pages()缓冲区: snd_pcm_lib_free_pages(substream);

当PCM 被“准备”时,prepare()函数将被调用,在其中可以设置采样率、格式等。prepare()函数与

hw_params()函数的不同在于对prepare()的调用发生在snd_pcm_prepare()每次被调用的时候。prepare() 的形式如下:

static int snd_xxx_prepare(struct snd_pcm_substream *substream);

trigger()成员函数在PCM 被开始、停止或暂停时调用,函数的形式如下: static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);

cmd 参数定义了具体的行为, 在trigger() 成员函数中至少要处理SNDRV_PCM_TRIGGER_START 和

SNDRV_PCM_TRIGGER_STOP 命令,如果PCM 支持暂停,还应处理SNDRV_PCM_TRIGGER_PAUSE_PUSH 和

SNDRV_PCM_TRIGGER_PAUSE_RELEASE 命令。如果设备支持挂起/恢复,当能量管理状态发生变化时将处理

SNDRV_PCM_TRIGGER_SUSPEND 和SNDRV_PCM_TRIGGER_RESUME 这2 个命令。注意trigger()函数是原子的,

中途不能睡眠。代码清单17.11 给出了1 个trigger()函数的范例。 代码清单17.11 snd_pcm_ops 结构体中trigger()函数

1 static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd) 2 {

3 switch (cmd) 4 {

5 case SNDRV_PCM_TRIGGER_START: 6 // 开启PCM 引擎 7 break;

8 case SNDRV_PCM_TRIGGER_STOP: 9 // 停止PCM 引擎 10 break;

11 ...//其它命令 12 default:

13 return - EINVAL; 14 } 15 }

pointer()函数用于PCM 中间层查询目前缓冲区的硬件位置,该函数以帧的形式返回0~buffer_size – 1

的位置(ALSA 0.5.x 中为字节形式),此函数也是原子的。 copy()和silence()函数一般可以省略,但是,当硬件缓冲区不处于常规内存中时需要。例如,一些设备

有自己的不能被映射的硬件缓冲区,这种情况下,我们不得不将数据从内存缓冲区拷贝到硬件缓冲区。例

外,当内存缓冲区在物理和虚拟地址上都不连续时,这2 个函数也必须被实现。 3、分配缓冲区

分配缓冲区的最简单方法是调用如下函数:

int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, int type, void *data, size_t size, size_t max);

type 参数是缓冲区的类型,包含SNDRV_DMA_TYPE_UNKNOWN(未知)、SNDRV_DMA_TYPE_CONTINUOUS(连续

的非DMA 内存)、SNDRV_DMA_TYPE_DEV (连续的通用设备),SNDRV_DMA_TYPE_DEV_SG(通用设备SG-buffer) 和SNDRV_DMA_TYPE_SBUS(连续的SBUS)。如下代码将分配64KB 的缓冲区: snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),64*1024, 64*1024); 4、设置标志

在构造PCM 实例、设置操作集并分配缓冲区之后,如果有需要,应设置PCM 的信息标志,例如,如果PCM

设备只支持半双工,则这样定义标志:

pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; 5、PCM 实例析构

PCM 实例的“析构函数”并非是必须的,因为PCM 实例会被PCM 中间层代码自动释放,如果驱动中分配了

一些特别的内存空间,则必须定义“析构函数”,代码清单17.x 给出了PCM“析构函数”与对应的“构造

函数”,“析构函数”会释放“构造函数”中创建的xxx_private_pcm_data。 代码清单17.12 PCM 设备“析构函数”

1 static void xxxchip_pcm_free(struct snd_pcm *pcm) 2 {

3 /* 从pcm 实例得到chip */

4 struct xxxchip *chip = snd_pcm_chip(pcm); 5 /* 释放自定义用途的内存 */

6 kfree(chip->xxx_private_pcm_data); 7 ... 8 } 9

10 static int __devinit snd_xxxchip_new_pcm(struct xxxchip *chip) 11 {

12 struct snd_pcm *pcm; 13 ...

14 /* 分配自定义用途的内存 */

15 chip->xxx_private_pcm_data = kmalloc(...); 16 pcm->private_data = chip; 17 /* 设置“析构函数” */

18 pcm->private_free = xxxchip_pcm_free; 19 ... 20 }

上述代码第4 行的snd_pcm_chip()从PCM 实例指针获得xxxchip 指针,实际上它就是返回第16 行给PCM

实例赋予的xxxchip 指针。 6、PCM 信息运行时指针

当PCM 子流被打开后,PCM 运行时实例(定义为结构体snd_pcm_runtime,如代码清单17.13)将被分配给

这个子流,这个指针通过substream->runtime 获得。运行时指针包含各种各样的信息:hw_params 及

sw_params 配置的拷贝、缓冲区指针、mmap 记录、自旋锁等,几乎要控制PCM 的所有信息均能从中取得。

代码清单17.13 snd_pcm_runtime 结构体 1 struct snd_pcm_runtime 2 {

3 /* 状态 */

4 struct snd_pcm_substream *trigger_master;

5 snd_timestamp_t trigger_tstamp; /* 触发时间戳 */ 6 int overrange;

7 snd_pcm_uframes_t avail_max;

8 snd_pcm_uframes_t hw_ptr_base; /* 缓冲区复位时的位置 */ 9 snd_pcm_uframes_t hw_ptr_interrupt; /* 中断时的位置*/

搜索更多关于: 音频设备驱动 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

3 int (*open)(struct snd_pcm_substream *substream);//打开 4 int (*close)(struct snd_pcm_substream *substream);//关闭 5 int (*ioctl)(struct snd_pcm_substream * substream, 6 unsigned int cmd, void *arg);//io 控制 7 int (*hw_params)(struct snd_pcm_substream *substream, 8 struct snd_pcm_hw_params *params);//硬件参数 9 int (*hw_free)(struct snd_pcm_substream *substream); //资源释放 10 int (*prepare)

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com