尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux cx88 驱动深度解析:Conexant cx2388x 电视采集卡的支持机制与新增显卡适配实战

Linux cx88 驱动深度解析:Conexant cx2388x 电视采集卡的支持机制与新增显卡适配实战 Linux cx88 驱动深度解析Conexant cx2388x 电视采集卡的支持机制与新增显卡适配实战【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文围绕 Linux 内核Documentation/admin-guide/media/cx88.rst展开系统讲解 cx88 驱动cx2388x 芯片的 V4L2 电视卡驱动的功能现状、板卡自动识别机制以及当你的电视卡被识别为 UNKNOWN/GENERIC 时如何利用 PCI 子系统 ID、cx88-cards.c板卡表和 insmod 参数为驱动添加新板卡支持的完整流程。读完后你将能够独立排查 cx88 电视卡的识别问题并编写提交自己的板卡配置。一、cx88 驱动是什么cx88 是面向 Conexant原 Conexant2388x 系列电视采集芯片的 V4L2 设备驱动由 Gerd Hoffmann 创建模块名为cx8800。cx2388x 是 bt878 芯片的后续产品广泛出现在各类模拟/数字电视卡、DVB-T 卡和 MPEG 编码卡上。驱动源码位于 drivers/media/pci/cx88/核心文件包括cx88-core.c驱动核心负责 PCI 资源获取、板卡识别与初始化cx88-cards.c板卡配置表与子系统 ID 匹配表是新增板卡支持的关键文件cx88-video.c视频捕获V4L2cx88-alsa.c音频 DMA 捕获ALSAcx88-vbi.cVBI垂直消隐间隔如 VPS/TELETEXT 数据捕获cx88-dvb.c、cx88-blackbird.cDVB/ATSC 前端与 Blackbird MPEG 编码参考设计支持。1.1 功能现状官方文档结论根据 cx88.rst 的 Current status 章节驱动各功能的支持情况如下功能状态说明video可用overlay 不支持audio可用TV 制式检测由驱动软件完成因为硬件自动检测存在缺陷不经回环线缆的音频 DMA 录制通过cx88-alsa支持vbi可用无特殊限制其中一条值得注意的工程细节音频制式NTSC/PAL 等的自动检测硬件本身有 bug所以由驱动在软件层面代为检测——这意味着不同电视制式的板卡在音频路径上行为可能不同调试时若遇到制式问题应把目光投向驱动而非硬件。音频 DMA 支持由独立的cx88-alsa模块提供。从 Kconfig 可见其前提条件config VIDEO_CX88_ALSA依赖VIDEO_CX88 SND且注释明确指出only works with boards with function 01 enabled即板卡 PCI function 01 必须存在——用lspci -n应能看到14f1:8801或14f1:8811设备。从 cx88-alsa.c 源码看该模块基于 ALSA 的 dummy 卡框架实现了一个 PCM 捕获子流音频数据经芯片 RISC DMA 引擎搬运到内核缓冲区。1.2 编译选项构建时相关 Kconfig 选项见 Kconfig选项模块名作用CONFIG_VIDEO_CX88cx8800cx2388x 驱动主体依赖VIDEO_DEV、PCI、I2C、RC_CORECONFIG_VIDEO_CX88_ALSAcx88-alsa音频 DMA 支持需 PCI function 01CONFIG_VIDEO_CX88_BLACKBIRDcx88-blackbirdcx2388x cx23416 的 MPEG 编码卡CONFIG_VIDEO_CX88_DVBcx88-dvbDVB/ATSC 前端支持自动选入大量 demodulator/PLL 子驱动二、板卡识别机制驱动如何认出你的电视卡文档指出驱动需要板卡配置信息才能正确工作这些信息全部存放在cx88-cards.c中。理解这套识别机制是后续添加新板卡的前提。2.1 识别输出的解读设备初始化时内核日志dmesg会打印一行形如cx8800[0]: subsystem: 0070:3400, board: Hauppauge WinTV 34xxx models [card1,autodetected]当前源码中的打印点位于 cx88-cards.c较新内核额外附带前端数量信息pr_info(subsystem: %04x:%04x, board: %s [card%d,%s], frontend(s): %d\n, pci-subsystem_vendor, pci-subsystem_device, core-board.name, core-boardnr, card[core-nr] core-boardnr ? insmod option : autodetected, core-board.num_frontends);由此可以精确解读每个字段subsystem: 0070:3400该卡的 PCI 子系统厂商/设备 ID来自pci-subsystem_vendor/subsystem_deviceboard: ...匹配到的板卡表条目的namecard1板卡在cx88_boards[]数组中的索引号autodetected或insmod option区分板卡是按子系统 ID 自动匹配还是由cardn参数手动指定——日志会如实标注两者中的哪一种。2.2 匹配逻辑的源码走读板卡识别发生在核心初始化中cx88-cards.c/* board config */ core-boardnr UNSET; if (card[core-nr] ARRAY_SIZE(cx88_boards)) core-boardnr card[core-nr]; for (i 0; core-boardnr UNSET i ARRAY_SIZE(cx88_subids); i) if (pci-subsystem_vendor cx88_subids[i].subvendor pci-subsystem_device cx88_subids[i].subdevice) core-boardnr cx88_subids[i].card; if (core-boardnr UNSET) { core-boardnr CX88_BOARD_UNKNOWN; cx88_card_list(core, pci); }优先级非常清晰cardninsmod 参数优先若通过card[core-nr]指定了合法索引直接采用子系统 ID 自动匹配遍历cx88_subids[]表比较subvendor/subdevice命中则取对应card编号全部落空则回退置为CX88_BOARD_UNKNOWN即文档说的board: UNKNOWN/GENERIC并调用cx88_card_list()向内核日志输出所有合法cardn取值列表。两张数据表同样位于 cx88-cards.ccx88_boards[]第 51 行起每个条目描述一块板的调谐器类型tuner_type、调谐器/收音的 I2C 地址、各路视频输入电视、复合、S-Video的 GPIO 映射、收音功能、MPEG 能力CX88_MPEG_DVB等。未知板的兜底条目是[CX88_BOARD_UNKNOWN] { .name UNKNOWN/GENERIC, .tuner_type UNSET, ... };cx88_subids[]第 2347 行起PCI 子系统 ID 到板卡索引的映射表。文档示例中的0070:3400正好对应表首条目{ .subvendor 0x0070, .subdevice 0x3400, .card CX88_BOARD_HAUPPAUGE, },即board: Hauppauge WinTV 34xxx models [card1,...]中的card1来源。2.3 识别失败时的内核日志当板卡未知时cx88_card_list()cx88-cards.c会打印两种典型错误之一Your board has no valid PCI Subsystem ID and thus cant be autodetected. Please pass cardn insmod option to workaround that. Redirect complaints to the vendor of the TV cardYour board isnt known (yet) to the driver. You can try to pick one of the existing card configs via cardn insmod option. Updating to the latest version might help as well.随后附上完整候选列表Here is a list of valid choices for the cardn insmod option: card0 - UNKNOWN/GENERIC card1 - Hauppauge WinTV 34xxx models card2 - GDI Black Gold ...注意第一种情况部分廉价卡甚至没有烧写 PCI 子系统 ID此时自动检测在原理上就不可能成功只能用cardn参数绕过——这也是向驱动提交新板卡前必须先用参数验证某条既有配置是否可用的原因。三、新增板卡支持的完整流程这是文档 How to add support for new cards 章节的核心内容下面将其与源码逐条对应展开。3.1 第 0 步确认驱动是否真的不认识你的卡dmesg | grep cx88 # 关注: subsystem: xxxx:xxxx, board: ... [cardn,...]若board:后面是UNKNOWN/GENERIC或出现 2.3 节的错误日志进入下面的流程若识别到了板卡但功能异常无声、调谐失败等问题更可能出在tuner_type、I2C 地址或 GPIO 映射上同样需要修改对应板卡条目。3.2 第 1 步升级内核文档第一条建议先升级到最新的内核版本再试maybe it has been added meanwhile——新板卡的子系统 ID 可能已被上游合入。3.3 第 2 步自行编写板卡条目若确认未收录参照 cx88-cards.c 中现有条目为自己板卡添加配置。一条完整的板卡条目长这样以CX88_BOARD_HAUPPAUGE为例[CX88_BOARD_HAUPPAUGE] { .name Hauppauge WinTV 34xxx models, .tuner_type UNSET, .radio_type UNSET, .tuner_addr ADDR_UNSET, .radio_addr ADDR_UNSET, .tda9887_conf TDA9887_PRESENT, .input { { .type CX88_VMUX_TELEVISION, .vmux 0, .gpio0 0xff00, // internal decoder }, { .type CX88_VMUX_COMPOSITE1, .vmux 1, .gpio0 0xff02, }, { .type CX88_VMUX_SVIDEO, .vmux 2, .gpio0 0xff02, } }, .radio { .type CX88_RADIO, .gpio0 0xff01, }, },编写条目时各字段的含义字段含义取值来源name板卡显示名出现在 dmesg 中板卡型号tuner_type/radio_type调谐器芯片类型板上调谐器型号对照调谐器驱动类型定义tuner_addr/radio_addr调谐器/收音芯片 I2C 地址ADDR_UNSET表示使用默认探测input[]各路视频输入的类型、vmux 号与 GPIO 开关值板卡硬件设计通常需试错验证mpegMPEG 能力如CX88_MPEG_DVB表示 DVB 前端板卡是否带数字前端若板卡没有子系统 ID或需要同时注册 ID 映射则应在cx88_subids[]表中追加{ .subvendor 0x0070, .subdevice 0x3400, .card CX88_BOARD_HAUPPAUGE, },文档要求修改验证有效后以 unified diffdiff -u的形式提交。3.4 第 3 步提交板卡配置信息若不方便自行修改代码文档要求至少提供两项信息PCI 子系统 ID——即 dmesg 中subsystem:后面的0070:3400lspci -v输出也可找 Subsystem ID 一行板卡使用的调谐器类型——若不确定可用tunerninsmod 参数逐个尝试trial-and-error。对应模块参数定义在 cx88-cards.cstatic unsigned int tuner[] {[0 ... (CX88_MAXBOARDS - 1)] UNSET }; static unsigned int radio[] {[0 ... (CX88_MAXBOARDS - 1)] UNSET }; static unsigned int card[] {[0 ... (CX88_MAXBOARDS - 1)] UNSET }; module_param_array(tuner, int, NULL, 0444); module_param_array(radio, int, NULL, 0444); module_param_array(card, int, NULL, 0444);注意这是数组参数多卡按设备序号cx8800[0]、cx8800[1]……依次取值。关于文档提到的CARDLIST.tuner参考文件在当前的内核树中该独立清单已不存在调谐器类型编号的权威来源是cx88_boards[]中各条目使用的tuner_type取值以及各调谐器驱动如tuner-*系列模块自身定义的类型常量——试错时应优先参考与板卡硬件资料匹配的既有板卡条目所用编号。3.5 可用的 insmod 参数速查综合 cx88-cards.c 与 cx88-core.c 中的module_param定义调试板卡时最常用的参数参数定义位置作用cardn[,n...]cx88-cards.c强制指定板卡条目索引绕过自动检测tunern[,n...]cx88-cards.c强制指定调谐器类型按设备序号radion[,n...]cx88-cards.c强制指定收音调谐器类型latencyncx88-cards.cPCI 延迟定时器disable_ir0/1cx88-cards.c禁用红外接收nicam0/1cx88-core.c声明电视音频为 NICAM 制式nocomb0/1cx88-core.c禁用梳状滤波器core_debugncx88-core.c打开 core 子系统的调试日志示例加载时强制指定板卡与调谐器——insmod cx8800 card5 tuner3加载后再次查看dmesg若[card5,insmod option]且视频/音频正常说明选中的条目正确即可按 3.3 节把该配置固化为正式的板卡条目。四、底层实现要点RISC DMA 引擎与捕获路径理解数据通路有助于判断识别成功但捕获失败类问题的边界。cx2388x 内置一个 RISCRISC-likeDMA 引擎由驱动软件预先写好指令块instruction list硬件按指令搬运每一行视频数据——这一机制与经典的 bt878 驱动一脉相承。从 cx88-core.c 的cx88_risc_field()可以看到指令生成细节RISC_RESYNC同步指令标记字段起点RISC_WRITE按扫描线写入目标缓冲区支持单条指令跨多个 scatterlist 页即一行数据可能跨越非连续 DMA 页代码中显式处理了 scanline needs to be split 分支RISC_SOL | RISC_IRQ1可选的 lpilines per IRQ机制每传输若干行触发一次中断用于把 DMA 完成通知粒度控制在合适范围RISC_JUMP跳转指令用于环形缓冲复用。音频路径cx88-alsa复用同一套 RISC 基础设施cx88-alsa.c 中的cx88_audio_dev结构持有struct cx88_dmaqueue q与 ALSAsnd_pcm_substream芯片 PCI function 01 的 DMA 数据经 RISC 指令搬入cx88_audio_buffer的 scatterlist 缓冲区再以 PCM 子流形式暴露给用户空间。这正是文档所述audio data dma (i.e. recording without loopback cable to the sound card) is supported via cx88-alsa的源码对应。而TV standard detection is made by the driver这一点从 cx88-core.c 的初始化注释也可得到旁证/* * Note: Setting initial standard here would cause first call to * cx88_set_tvnorm() to return without programming any registers. * Leave it blank for at this point and it will get set later in * cx8800_initdev() */ core-tvnorm 0;初始制式被刻意留空留待后续由软件逻辑显式设置——这与文档硬件自动检测有缺陷、由驱动代为检测的表述相互印证。五、小结cx88 驱动对 cx2388x 电视卡的 video/audio/vbi 三大功能均已可用overlay 除外音频 DMA 需要板卡具备 PCI function 0114f1:8801/14f1:8811并启用cx88-alsa模块板卡识别遵循cardn参数 → PCI 子系统 ID 自动匹配 →UNKNOWN/GENERIC回退的三级优先级关键数据表是cx88_boards[]与cx88_subids[]均在 cx88-cards.c新增板卡支持的最小信息集是PCI 子系统 ID 调谐器类型可用tunern参数试错获得验证通过后以diff -u提交板卡条目数据面基于芯片内 RISC DMA 引擎cx88-core.c中的cx88_risc_field()/cx88_risc_buffer()负责指令块生成视频与音频cx88-alsa共用该基础设施。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表