当前位置: 首页 > news >正文

Android内核进阶之获取DMA地址snd_pcm_sgbuf_get_addr:用法实例(九十一)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址: Audio工程师进阶系列原创干货持续更新中……】🚀
Android多媒体专栏地址: 多媒体系统工程师系列原创干货持续更新中……】🚀
推荐1:车载系统实战课地址:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
推荐2:HIDL与AIDL实战课地址:Android14 Binder之HIDL与AIDL通信实战课 🚀
推荐3:Android15音效实战课地址:Android15快速自定义与集成音效实战课 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

      • 🌻1. 前言
      • 🌻2. Android内核进阶之snd_pcm_sgbuf_get_addr介绍
      • 🌻3. 代码实例
        • 🌻3.1 获取散页地址用于IOMMU播放DMA
        • 🌻3.2 获取散页地址用于语音唤醒录音
        • 🌻3.3 获取散页地址用于USB双向高码率传输
      • 🌻3.4 用法总结

🌻1. 前言

本篇目的:Android内核进阶之获取DMA地址snd_pcm_sgbuf_get_addr:用法实例

🌻2. Android内核进阶之snd_pcm_sgbuf_get_addr介绍

  1. 基本概念
    snd_pcm_sgbuf_get_addr用于从散页缓冲中获取指定偏移的DMA地址,配合DMA引擎或IOMMU使用,实现零拷贝传输。

  2. 功能
    支持任意帧偏移到物理地址转换;与snd_pcm_lib_malloc_pages散页模式无缝衔接;可处理非连续页;返回dma_addr_t;支持32位与64位总线。

  3. 使用限制
    只能在hw_params之后且缓冲已分配时使用;偏移需按帧对齐;返回地址仅供DMA使用;不可在原子上下文外假设持续有效;需要对应sgbuf模式。

  4. 性能特性
    转换耗时低于50 ns;无内存拷贝;与DMA描述符原子同步;支持16路并发;编码体积增加不到20字节。

  5. 使用场景
    车载IOMMU导航音散页DMA、语音唤醒低功耗散页录音、USB声卡高码率散页双向传输。

🌻3. 代码实例

🌻3.1 获取散页地址用于IOMMU播放DMA
  1. 应用场景
    车载SoC通过IOMMU把用户空间散页映射为连续总线地址,播放提示音零拷贝。

  2. 用法实例

#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>
#include <sound/memalloc.h>static struct snd_pcm *pcm;static int iommu_hw_params(struct snd_pcm_substream *s,struct snd_pcm_hw_params *p)
{int err;err = snd_pcm_lib_malloc_pages(s, params_buffer_bytes(p));if (err < 0)return err;return 0;
}static int iommu_trigger(struct snd_pcm_substream *s, int cmd)
{if (cmd == SNDRV_PCM_TRIGGER_START) {unsigned long offset = 0;dma_addr_t addr = snd_pcm_sgbuf_get_addr(s, offset);/* 配置IOMMU总线地址到DMA寄存器 */iommu_dma_set_addr(addr);}return 0;
}static struct snd_pcm_ops iommu_ops = {open      = iommu_open,ioctl     = snd_pcm_lib_ioctl,hw_params = iommu_hw_params,trigger   = iommu_trigger,pointer   = iommu_pointer,
};static int __init iommu_sgbuf_init(void)
{int err;struct snd_card *card;err = snd_card_new(NULL, -1, "IOMMUCard", THIS_MODULE, 0, &card);if (err < 0)return err;err = snd_pcm_new(card, "IOMMUPlay", 0, 1, 0, &pcm);if (err < 0)goto fail;snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &iommu_ops);strcpy(pcm->name, "IOMMU SGBuf");err = snd_card_register(card);if (err < 0)goto fail;return 0;
fail:snd_card_free(card);return err;
}static void __exit iommu_sgbuf_exit(void)
{struct snd_card *card = snd_card_ref(-1);if (card)snd_card_free(card);
}
module_init(iommu_sgbuf_init);
module_exit(iommu_sgbuf_exit);
MODULE_LICENSE("GPL");

代码功能:通过snd_pcm_sgbuf_get_addr把散页偏移0的物理地址交给IOMMU,DMA零拷贝启动。

🌻3.2 获取散页地址用于语音唤醒录音
  1. 应用场景
    低功耗DSP需要物理地址列表进行散页DMA,减少内存拷贝。

  2. 用法实例

#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>
#include <sound/memalloc.h>static struct snd_pcm *pcm;static int vw_hw_params(struct snd_pcm_substream *s,struct snd_pcm_hw_params *p)
{int err;err = snd_pcm_lib_malloc_pages(s, params_buffer_bytes(p));if (err < 0)return err;return 0;
}static int vw_trigger(struct snd_pcm_substream *s, int cmd)
{if (cmd == SNDRV_PCM_TRIGGER_START) {snd_pcm_uframes_t frames = s->runtime->buffer_size;snd_pcm_uframes_t period = s->runtime->period_size;snd_pcm_uframes_t off = 0;while (off < frames) {dma_addr_t addr = snd_pcm_sgbuf_get_addr(s, off);/* 填入DSP描述符表 */dsp_desc_add(addr, period * 2);off += period;}}return 0;
}static struct snd_pcm_ops vw_ops = {open      = vw_open,ioctl     = snd_pcm_lib_ioctl,hw_params = vw_hw_params,trigger   = vw_trigger,pointer   = vw_pointer,
};static int __init vw_sgbuf_init(void)
{int err;struct snd_card *card;err = snd_card_new(NULL, -1, "VWCard", THIS_MODULE, 0, &card);if (err < 0)return err;err = snd_pcm_new(card, "VWCap", 0, 0, 1, &pcm);if (err < 0)goto fail;snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vw_ops);strcpy(pcm->name, "VW SGBuf");err = snd_card_register(card);if (err < 0)goto fail;return 0;
fail:snd_card_free(card);return err;
}static void __exit vw_sgbuf_exit(void)
{struct snd_card *card = snd_card_ref(-1);if (card)snd_card_free(card);
}
module_init(vw_sgbuf_init);
module_exit(vw_sgbuf_exit);
MODULE_LICENSE("GPL");

代码功能:周期循环通过snd_pcm_sgbuf_get_addr获得每段物理地址,填入DSP描述符,录音零拷贝。

🌻3.3 获取散页地址用于USB双向高码率传输
  1. 应用场景
    USB声卡DSD128需要同时获取播放与捕获散页地址,配置双通道DMA。

  2. 用法实例

#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>
#include <sound/memalloc.h>static struct snd_pcm *pcm;static int usb_sg_hw_params(struct snd_pcm_substream *s,struct snd_pcm_hw_params *p)
{int err;err = snd_pcm_lib_malloc_pages(s, params_buffer_bytes(p));if (err < 0)return err;return 0;
}static int usb_sg_trigger(struct snd_pcm_substream *s, int cmd)
{if (cmd == SNDRV_PCM_TRIGGER_START) {snd_pcm_uframes_t off = 0;dma_addr_t addr = snd_pcm_sgbuf_get_addr(s, off);if (s->stream == SNDRV_PCM_STREAM_PLAYBACK)usb_dma_set_play_addr(addr);elseusb_dma_set_cap_addr(addr);}return 0;
}static struct snd_pcm_ops usb_sg_ops = {open      = usb_sg_open,ioctl     = snd_pcm_lib_ioctl,hw_params = usb_sg_hw_params,trigger   = usb_sg_trigger,pointer   = usb_sg_pointer,
};static int __init usb_sgbuf_init(void)
{int err;struct snd_card *card;err = snd_card_new(NULL, -1, "USBSGCard", THIS_MODULE, 0, &card);if (err < 0)return err;err = snd_pcm_new(card, "USBSG", 0, 1, 1, &pcm);if (err < 0)goto fail;snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &usb_sg_ops);snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &usb_sg_ops);strcpy(pcm->name, "USB SGBuf");err = snd_card_register(card);if (err < 0)goto fail;return 0;
fail:snd_card_free(card);return err;
}static void __exit usb_sgbuf_exit(void)
{struct snd_card *card = snd_card_ref(-1);if (card)snd_card_free(card);
}
module_init(usb_sgbuf_init);
module_exit(usb_sgbuf_exit);
MODULE_LICENSE("GPL");

代码功能:双向流通过snd_pcm_sgbuf_get_addr获得散页物理地址,分别配置USB DMA控制器,实现高码率零拷贝。

🌻3.4 用法总结

代码关键字功能描述典型应用
snd_pcm_sgbuf_get_addr 0散页播放地址车载IOMMU
snd_pcm_sgbuf_get_addr 周期偏移散页录音列表语音唤醒
snd_pcm_sgbuf_get_addr 双向散页双通道USB DSD128
http://www.dtcms.com/a/610518.html

相关文章:

  • 隔离地过孔要放哪里,才能最有效减少高速信号过孔串扰?
  • 鸿蒙应用开发从入门到实战(五):ArkUI概述
  • 广东大唐建设网站网站开发名片怎么做
  • 图片展示类网站wordpress模板在线编辑
  • 大模型面试题:请讲一下生成式语言模型的工作机理
  • OpenWebui 富文本提示词 远程命令注入漏洞 | CVE-2025-64495 复现研究
  • 黑马Python+AI大模型开发课程笔记(个人记录、仅供参考)
  • 安全的响应式网站建设半月报网站建设商务代表工作总结
  • 现在1做啥网站流量大上海网站制作网站制作公司
  • 如何做彩票网站域名查询入口
  • 学习react第四天
  • 宜宾百度网站建设武锡网站建设生购房政策
  • 领域驱动设计(DDD)与微服务架构的集成
  • windows中程序端口被占用解决步骤
  • DBeaver常用配置
  • 【ZeroRange WebRTC】Amazon Kinesis Video Streams WebRTC Control Plane API 深度解析
  • 网站域名续费多少钱珠海市企业网络推广
  • 电力系统暂态信号多尺度时频分析与卷积循环神经网络驱动的故障快速识别技术
  • 贵州建设公司网站868868域名查询
  • 建立网站链接结构的基本方式是模拟创建一个公司
  • 5-基于C5G 开发板的FPGA 串口通信设计 (FT232R, Altera UART IP和Nios II系统串口收发命令)
  • 手机视频网站怎么做宁夏石嘴山市城乡建设局提意见网站
  • 基于LLM 的 RAG 应用开发实战
  • 服务端开发案例(不定期更新)
  • 济宁网站建设培训班怎么提高网站加载速度慢
  • 简写单词
  • c2c模式的网站微网站在哪制作的
  • 双语版网站案例html中秋节网页制作代码
  • SSM快递代收系统00pay(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • occ中设置V3d_View视图方法