ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux 内核 Si470x FM 收音机驱动完全指南:USB/I2C 架构、模块参数与 v4l2 实战

Linux 内核 Si470x FM 收音机驱动完全指南:USB/I2C 架构、模块参数与 v4l2 实战 Linux 内核 Si470x FM 收音机驱动完全指南USB/I2C 架构、模块参数与 v4l2 实战【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读本文基于 Linux 内核文档 Documentation/admin-guide/media/si470x.rst 编写全面解析 Silicon Labs Si470x 系列 FM 收音机芯片在内核中的驱动实现。文章覆盖从受支持芯片/USB 设备清单、内核 Kconfig 配置、模块参数到 v4l2-ctl 调频实操、音频重定向命令的完整链路并结合 drivers/media/radio/si470x/ 目录下的源码深入讲解其 16 个内部寄存器、USB HID 报告机制与 RDS 数据处理流程。读完本文你将掌握如何在 Linux 上配置、加载并实际收听 Si470x USB 收音机也能理解该驱动在内核 V4L2 子系统中的实现原理。背景Silicon Labs 的收音机芯片与 USB 参考设计Si470x 系列是 Silicon LaboratoriesSiLabs推出的 FM 收音机接收芯片曾被广泛用于手机等移动设备中通常通过I2C 总线连接主控。除了裸芯片方案SiLabs 还提供了一套 USB 参考设计将 Si470x 芯片与一颗小型微控制器C8051F321集成组成一个即插即用的 USB 收音机。该参考设计附带二进制与源码形式的收音机应用并支持自动将固件升级到最新版本。这套参考设计使内核驱动得以用USB 设备 V4L2 无线电接口的方式呈现收音机这也是本驱动最早的切入点。内核侧的驱动代码位于 drivers/media/radio/si470x/由 Tobias Lorenz 于 2009 年编写见 radio-si470x.h 头部版权注释后续由 Hans de Goede、Alexey Klimov、Mark Lord、Rick Bronson 等人持续完善。受支持的 Si470x 芯片系列文档列出驱动或计划支持的芯片型号它们拥有非常相似的寄存器集型号特性Si4700FM 收音机接收器Si4701FM 收音机接收器支持 RDSSi4702FM 收音机接收器Si4703FM 收音机接收器支持 RDSSi4704FM 收音机接收器无需外部天线Si4705FM 收音机接收器无需外部天线RDS 支持数字 I/OSi4706增强型 FM RDS/TMC 收音机无需外部天线RDS 支持Si4707专用气象波段收音机带 SAME 解码器RDS 支持Si4708最小尺寸 FM 接收器Si4709最小尺寸 FM 接收器RDS 支持从源码看驱动在 probe 阶段会读取芯片的 DEVICEID寄存器 0与 CHIPID寄存器 1并通过日志输出例如 radio-si470x-usb.c 中dev_info(intf-dev, DeviceID0x%4.4hx ChipID0x%4.4hx\n, ...)。CHIPID 寄存器低 9 位SI_CHIPID_FIRMWARE保存固件版本号驱动要求固件版本不低于RADIO_FW_VERSION值为 12定义见 radio-si470x.h否则会打印警告并建议向 linux-media 邮件列表反馈问题。已知可用的 USB 收音机设备文档与 radio-si470x-usb.c 中的si470x_usb_driver_id_table均列出了驱动声明支持的 USB 设备vendor:productUSB ID设备10c4:818aSilicon Labs USB FM Radio Reference Design06e1:a155ADS/Tech FM Radio Receiver前身 Instant FM MusicRDX-155-EF1b80:d700KWorld USB FM Radio SnapMusic Mobile 700FM70010c5:819aSanei Electric FM USB Radio即 DealExtreme.com 销售的 PCear12cf:7111Axentia ALERT FM USB Receiver源码中新增的条目这些设备在 USB 层面均以HID 类接口呈现USB_CLASS_HID因此驱动通过 HID 报告report机制与硬件通信详见下文USB HID 报告协议一节。需要特别注意的是SiLabs 参考设计10c4:818a与基于 si4734 的 Thankos Raremono 收音机共用同一组 USB ID因此驱动在 probe 时会额外读取寄存器做鉴别设备 ID 的低 12 位应为 0x0242否则返回-ENODEV提示 this is not a si470x device.见 radio-si470x-usb.c。内核配置与模块加载驱动在 drivers/media/radio/si470x/Kconfig 中提供三个配置项层级关系清晰RADIO_SI470Xtristate依赖VIDEO_DEV基础支持编译为模块时名为radio-si470x-common。USB_SI470Xtristate依赖USB RADIO_SI470XUSB 总线支持模块名为radio-usb-si470x。Kconfig 提示声音由 ALSA USB Audio/MIDI 驱动提供若不仅要收 RDS 还要出声建议同时开启SND_USB_AUDIO。I2C_SI470Xtristate依赖I2C RADIO_SI470XI2C 总线支持模块名为radio-i2c-si470x由 Samsung 的 Joonyoung Shim 于 2009 年贡献见 radio-si470x-i2c.c 头部注释。典型的配置方式CONFIG_RADIO_SI470Xm CONFIG_USB_SI470Xm CONFIG_SND_USB_AUDIOm加载与卸载modprobe radio-usb-si470x modprobe snd-usb-audio # 卸载 modprobe -r radio-usb-si470x设备插入后驱动会注册一个 V4L2 radio 设备节点通常为/dev/radio0。probe 流程见si470x_usb_driver_probe依次完成分配私有数据结构、查找中断 IN 端点、注册 v4l2_device、注册 V4L2 控制mute/volume、读取全部寄存器与 scratch 页获取软硬件版本、分配 RDS 缓冲、启动收音机、将初始频率设为 87.5 MHzsi470x_set_freq(radio, 87.5 * FREQ_MUL)该频率在所有地区均可用、最后以VFL_TYPE_RADIO类型注册 video 设备。设备能力位device_caps包括V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE即支持硬件频率搜索、直接读写、调谐器、RADIO 类型以及 RDS 捕获。用户空间软件与 v4l2-ctl 实操文档建议在 Debian/testing 环境下使用以下应用进行测试fmtools管理 FM 调谐卡的工具gnomeradioGNOME 桌面的 FM 收音机调谐器gradioGTK FM 收音机调谐器kradioKDE 的收音机应用radio基于 ncurses 的收音机应用mplayerLinux 下的多媒体播放器v4l2-ctlv4l2 命令行工具集属于 v4l-utils其中v4l2-ctl是最直接、最便于脚本化的方式文档给出的示例v4l2-ctl -d /dev/radio0 --set-ctrlvolume10,mute0 --set-freq95.21 --all参数含义-d /dev/radio0指定设备节点--set-ctrlvolume10,mute0设置音量驱动 V4L2 音量控制范围为 0~15见下文V4L2 控制并解除静音--set-freq95.21把频率调到 95.21 MHzv4l2-ctl 对 radio 设备自动以 MHz 解析频率值--all打印当前设备的所有参数与状态便于确认调谐结果。文档还提到 libv4l 库——其计划提供频率搜索seek函数既可以直接使用 radio-si470x 的硬件 seek 能力也可以在各应用中以软件方式实现。文中提及 rdsd 项目http://rdsd.berlios.de/用于处理 RDS 信息并指出当时尚无把 TMC 报文转成人类可读文本的项目。V4L2 控制与频段能力在 radio-si470x-usb.c 中驱动注册了两个标准 V4L2 控件V4L2_CID_AUDIO_MUTE范围 0~1步长 1默认 1默认静音V4L2_CID_AUDIO_VOLUME范围 0~15步长 1默认 15最大音量。这与芯片 SYSCONFIG2 寄存器中的 4 位音量字段SYSCONFIG2_VOLUMEbits 3..0直接对应。频段定义在 radio-si470x-common.c 的bands[]数组中默认radio-band 1即 76~108 MHz 全球通用频段另有 87.5~108 MHz 与日本 76~90 MHz 等频段条目。每个频段都声明了V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP等能力调制方式为 FM。频率换算方面驱动以 62.5 Hz 为最小频率单元FREQ_MUL 1000000 / 62.5 16000定义见 radio-si470x.h因为芯片支持 50/100/200 kHz 三种信道间隔用更细的 62.5 Hz 单元可以无损表达所有间隔。音频输出把收音机声音重定向到声卡Si470x USB 参考设计的音频流由ALSA 的 snd_usb_audio 模块提供因此收听前必须确保SND_USB_AUDIO已开启/加载。收音机的 USB 音频设备默认是一个独立的 ALSA 声卡需要把它的音频重定向到主声卡才能听到声音。文档给出了针对不同音频栈的命令请按实际设备调整音频设备名/dev/dsp*与hw:x,x。最简单测试音质很差用 cat 直接搬运 OSS 设备cat /dev/dsp1 /dev/dsp使用 sox OSSsox -2 --endian little -r 96000 -t oss /dev/dsp1 -t oss /dev/dsp使用 sox ALSAsox --endian little -c 2 -S -r 96000 -t alsa hw:1 -t alsa -r 96000 hw:0使用 artsaRts 声音服务器arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -使用 mplayerradio 捕获模式mplayer -radio adevicehw1.0:arate96000 \ -rawaudio rate96000 \ radio://frequency/capture注意以上命令中的采样率 96000、双声道、S16_LE 格式均来自 USB 音频端点实际请以arecord -l/cat /proc/asound/cards看到的设备为准。模块参数详解sysfs 可调加载模块后多数参数可通过 sysfs 查看或修改挂载于/sys/module/radio_si470x/parameters。文档特别说明只读文件权限 0444的内容不会更新——即使通过私有 video 控制改变了 space、band、de 等值这些文件仍保持加载时的值其余参数支持运行时修改。综合 USB 与公共部分源码完整的模块参数如下参数默认值权限说明radio_nr-10444指定 radio 设备编号-1 表示由内核自动分配usb_timeout5000644USB 控制传输超时毫秒仅 USB 驱动rds_buf1000444RDS 缓冲条目数每条 3 字节见 RDS 数据格式max_rds_errors10644RDS 允许的最大块错误级别00 个错误11~2 个错误需纠错原 USBRadio.exe 所用23~5 个错误需纠错36 个以上错误或校验字错误、无法纠正space20444信道间隔0200 kHz美国、澳洲1100 kHz欧洲、日本250 kHzde10444去加重075 µs美国150 µs欧洲、澳洲、日本tune_timeout30000644调谐超时毫秒seek_timeout50000644频率搜索超时毫秒其中space、de、tune_timeout、seek_timeout定义于 radio-si470x-common.c第 108~131 行radio_nr、usb_timeout、rds_buf、max_rds_errors定义于两个总线驱动文件USB 版见 radio-si470x-usb.cI2C 版见 radio-si470x-i2c.c。示例加载时指定编号与超时modprobe radio-usb-si470x radio_nr1 usb_timeout1000运行中调整0644 参数echo 1000 /sys/module/radio_si470x/parameters/tune_timeoutspace与de的取值会映射到 SYSCONFIG2 的SYSCONFIG2_SPACEbits 5..4与 SYSCONFIG1 的SYSCONFIG1_DEbit 11寄存器位最终由si470x_start写入芯片。错误排查文档给出的排障建议若频繁遇到-EIO错误增大tune_timeout调谐超时或到达频段边界时hw_freq_seek会返回-EAGAIN从代码看这对应 STATUSRSSI 寄存器中STATUSRSSI_SFSeek Fail/Band Limit位的处理路径若收到任何来自snd_usb_audio的错误请向 ALSA 社区反馈。此外从源码可以补充两点probe 阶段若 USB 控制传输失败si470x_get_report/si470x_set_report会打印usb_control_msg returned %d警告见 radio-si470x-usb.c如果设备固件版本低于 12 或硬件版本低于 1驱动会打印版本警告并建议向 linux-mediavger.kernel.org 反馈。源码深潜寄存器映射与驱动架构16 个内部寄存器Si470x 芯片内部有16 个 16 位寄存器DEVICEID 到 RDSD完整位定义见 radio-si470x.h寄存器索引关键字段DEVICEID0Part Numberbits 15..12、Manufacturer IDbits 11..0SI_CHIPID1Chip Version、Device、Firmware Version低 9 位POWERCFG2DSMUTE、DMUTE、MONO、RDSM、SKMODE、SEEKUP、SEEK、DISABLE、ENABLECHANNEL3TUNEbit 15、CHANbits 9..0信道选择SYSCONFIG14RDSIEN、STCIEN、RDS、DE、AGCD、BLNDADJ、GPIO3/2/1SYSCONFIG25SEEKTHRSSI 搜索阈值、BAND、SPACE、VOLUMESYSCONFIG36SMUTER软静音速率、SMUTEA、SKSNR、SKCNTTEST17AHIZEN音频高阻使能TEST2 / BOOTCONFIG8 / 9仅保留位STATUSRSSI10RDSR、STC、SF、AFCRL、RDSS、BLERA、ST立体声指示、RSSI8 位信号强度READCHAN11BLERB/C/D、READCHAN当前信道RDSA/RDSB/RDSC/RDSD12~15RDS 块 A/B/C/D 数据调谐流程围绕CHANNEL寄存器置位CHANNEL_TUNE并写入目标信道值触发调谐随后轮询 STATUSRSSI 的STATUSRSSI_STCSeek/Tune Complete位配合completion等待调谐完成——USB 驱动的中断回调中一旦发现 STC 置位就complete(radio-completion)见 radio-si470x-usb.c。USB HID 报告协议USB 参考设计把 Si470x 的寄存器访问封装成了 HID 报告报告号与寄存器地址一一对应定义见 radio-si470x-usb.c报告 1~16通过端点 0 的 GET_REPORT/SET_REPORT 直接读写对应的 16 个寄存器REGISTER_REPORT(reg) reg 1报告 17一次读写全部 16 个寄存器的整幅映射ENTIRE_REPORT报告 18把最低 6 个寄存器STATUSRSSI~RDSD经 HID 中断端点 1 每 20 毫秒上报一次用于 RDS 与状态轮询报告 19LED 状态LED_COMMAND 0x35与音频流STREAM_COMMAND 0x36控制报告 2063 字节 scratch 页存放软件/硬件版本号报告 19~22C8051F321 的 flash 升级通道写、擦除、CRC、响应命令。寄存器读写通过usb_control_msg完成si470x_get_register发 GET_REPORT 并解析大端 16 位数据si470x_set_register发 SET_REPORT 写入。驱动还实现了si470x_get_all_registers报告 17 一次读全。RDS 数据则由中断端点持续推送回调函数si470x_int_in_callback在收到报告 18 后更新 RDS 相关寄存器并依次取出块 A~D按每块 3 字节2 字节数据 1 字节块号/错误标志写入环形缓冲最终通过read()或 V4L2 RDS API 交付给用户态。块错误级别超过max_rds_errors时置0x80不可纠正低于阈值但非零时置0x40已纠正该逻辑与上文的max_rds_errors参数一一对应。I2C 总线路由I2C 版本radio-si470x-i2c.c走经典 I2C 批量读写写操作从寄存器 0x02 的高字节开始连续写 8 个寄存器读操作从 0x0a 开始读全部 16 个寄存器再按READ_INDEX做环形偏移换算到本地索引。它同样支持 RDS 中断通过 GPIO 复位引脚gpio_reset与中断处理并可通过设备树/ACPI 描述挂接。已知问题与未来方向文档列出的未解决问题从代码中也能看到对应痕迹V4L2 次设备号分配与参数设置不够完美解决方案仍在讨论中。probe 中确实存在先注册 v4l2_device、后注册 video 设备的多步骤流程且radio_nr参数直接透传给video_register_device。固件升级接口芯片存在下载/上传新固件的 USB 接口可在内核中借助request_firmware机制实现。USB 驱动源码头部注释radio-si470x-usb.c第 11~14 行至今保留着 add firmware download/update support 的 ToDo且报告 19~22 的 bootloader 命令GET_SW_VERSION、SET_PAGE、ERASE_PAGE、WRITE_PAGE、CRC_ON_PAGE、RESET_DEVICE 等已全部定义好只待接入。RDS 中断模式驱动已用与中断相同的接口轮询 RDS 信息但未启用真正的 RDS 中断模式。从版本历史看1.0.10 已改为中断端点驱动 RDSinterrupt mode for RDS endpoint, instead of polling文档措辞反映的是更早状态SYSCONFIG1 的RDSIENRDS 中断使能与GPIO2_INT使能 STC/RDS 中断位均已定义说明硬件与代码层面都为中断模式留有接口。LED 接口芯片有可覆盖固件 LED 控制的接口未来可借助内核 LED 支持暴露出来。USB 驱动中si470x_set_led_state已实现并通过报告 19 下发probe 成功时会设置BLINK_GREEN_LED连接状态但尚未接入内核 LED class 框架。小结Si470x 驱动是 Linux V4L2 无线电框架中一个结构清晰、覆盖 USB 与 I2C 两种总线的典型范例芯片侧是统一的 16 寄存器模型总线侧分别以 HID 报告与 I2C 批量读写实现寄存器访问用户态则通过标准的 radio 设备节点、V4L2 控制与 ALSA 音频协同工作。无论是用v4l2-ctl快速调台收听还是想理解内核如何用 HID 报告驱动一块收音机芯片本文所述的文档与源码都是很好的起点。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表