
Linux 内核 SAA7164 驱动卡列表全解Hauppauge HVR 系列 PCIe 电视卡型号识别与 card 参数实战【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文围绕内核文档 saa7164-cardlist.rst 展开系统梳理 NXP原 PhilipsSAA7164 PCIe 桥接芯片驱动的全部 14 个板卡条目编号 0–13结合 saa7164-cards.c、saa7164.h 与 saa7164-core.c 的源码实现讲清卡编号 → PCI 子系统 ID → 板卡自动识别 → card 参数手动指定的完整链路并深入每块卡的端口DVB/编码器/VBI与处理单元调谐器、解调器、EEPROM硬件拓扑。读完本文你既能读懂内核日志中的板卡识别信息也能在自识别失败时准确使用cardn加载参数还能对照源码理解 HVR2200/HVR2250/HVR2255/HVR2205 各型号的内部差异。SAA7164 驱动与卡列表文档概述SAA7164 是 NXP 面向 PCIe 总线推出的桥接媒体芯片负责将模拟/数字电视前端调谐器、解调器、编码器与主机系统连接起来。在内核中对应驱动位于 drivers/media/pci/saa7164/由saa7164-cards.o、saa7164-core.o、saa7164-i2c.o、saa7164-dvb.o、saa7164-fw.o、saa7164-bus.o、saa7164-cmd.o、saa7164-api.o、saa7164-buffer.o、saa7164-encoder.o、saa7164-vbi.o等对象模块组成见 Makefile覆盖 DVB 前端、MPEG 编码器和 VBI 三类数据通路。卡列表文档是这一类驱动的重要配套资料它把驱动内部板卡编号与板卡名称 PCI 子系统 ID一一对应既是用户识别硬件的速查表也是驱动开发者在新增板卡时维护的核心索引。在内核媒体子系统的 pci-cardlist.rst 中saa7164 与 bttv、cx18、cx23885、cx88、ivtv、saa7134、zoran 等驱动并列共同构成PCI 驱动总览 各驱动卡列表的文档体系。SAA7164 完整卡列表Card 0–13原文档使用 flat-table 给出了驱动支持的全部板卡。为便于检索这里整理为等价表格卡编号 (Card number)卡名称 (Card name)PCI 子系统 ID (PCI subsystem IDs)0Unknown—1Generic Rev2—2Generic Rev3—3Hauppauge WinTV-HVR22500070:8880, 0070:88104Hauppauge WinTV-HVR22000070:89805Hauppauge WinTV-HVR22000070:89006Hauppauge WinTV-HVR22000070:89017Hauppauge WinTV-HVR22500070:8891, 0070:88518Hauppauge WinTV-HVR22500070:88A19Hauppauge WinTV-HVR22000070:894010Hauppauge WinTV-HVR22000070:895311Hauppauge WinTV-HVR2255(proto)0070:f11112Hauppauge WinTV-HVR22550070:f11113Hauppauge WinTV-HVR22050070:f123, 0070:f120其中0070是 Hauppauge 公司的 PCI 子系统厂商 IDsubvendor冒号后的四位十六进制为子系统设备 IDsubdevice。可以看到编号 11 与 12 共用子系统 ID0070:f111但 11 是原型板proto条目源码中该 ID 实际映射到正式板卡 12原型条目仅为文档留档这一点在源码部分会详细说明。卡编号在源码中的枚举定义文档中的卡编号并非随意编号它们直接对应 saa7164.h 中的板卡枚举常量#define SAA7164_BOARD_NOAUTO UNSET #define SAA7164_BOARD_UNKNOWN 0 #define SAA7164_BOARD_UNKNOWN_REV2 1 #define SAA7164_BOARD_UNKNOWN_REV3 2 #define SAA7164_BOARD_HAUPPAUGE_HVR2250 3 #define SAA7164_BOARD_HAUPPAUGE_HVR2200 4 #define SAA7164_BOARD_HAUPPAUGE_HVR2200_2 5 #define SAA7164_BOARD_HAUPPAUGE_HVR2200_3 6 #define SAA7164_BOARD_HAUPPAUGE_HVR2250_2 7 #define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8 #define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9 #define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10 #define SAA7164_BOARD_HAUPPAUGE_HVR2255proto 11 #define SAA7164_BOARD_HAUPPAUGE_HVR2255 12 #define SAA7164_BOARD_HAUPPAUGE_HVR2205 13枚举值与文档编号完全一一对应。需要特别指出的是SAA7164_BOARD_NOAUTO等于UNSET即-1U并不是一张真实板卡而是禁止自动识别、强制手动指定的哨兵值SAA7164_BOARD_UNKNOWN0、SAA7164_BOARD_UNKNOWN_REV21、SAA7164_BOARD_UNKNOWN_REV32则是兜底条目其中 0 号Unknown在 saa7164-cards.c 中连chiprev芯片版本都没有设置源码注释明确说明桥接芯片在不清楚修订版本时加载固件是致命操作因此 0 号条目仅用于占位而 1/2 号Generic Rev2/Generic Rev3分别声明了SAA7164_CHIP_REV2/SAA7164_CHIP_REV3源码注释称其加载 v2 固件并转储描述符用于新板卡 bringup 阶段是硬件调试场景下的通用兜底配置。PCI 子系统 ID 与板卡自动识别机制如何获取 PCI 子系统 IDSAA7164 是 PCIe 设备可以通过标准的lspci工具查看其身份信息。按 pci-cardlist.rst 的说明lspci -nn显示 vendor/device PCI IDlspci -vn的Subsystem:行显示子系统厂商 ID 与子系统设备 ID。例如在一块 HVR2250 上lspci -vn应能看到类似Subsystem: 0070:8880的输出其中0070:8880正是文档第 3 行所列的子系统 ID驱动据此即可自动判定为SAA7164_BOARD_HAUPPAUGE_HVR2250。源码中的 ID 匹配表自动识别的核心数据是 saa7164-cards.c 中的saa7164_subids[]表它把子系统厂商 ID 子系统设备 ID翻译成板卡枚举值struct saa7164_subid saa7164_subids[] { { .subvendor 0x0070, .subdevice 0x8880, .card SAA7164_BOARD_HAUPPAUGE_HVR2250, }, { .subvendor 0x0070, .subdevice 0x8810, .card SAA7164_BOARD_HAUPPAUGE_HVR2250, }, { .subvendor 0x0070, .subdevice 0x8980, .card SAA7164_BOARD_HAUPPAUGE_HVR2200, }, { .subvendor 0x0070, .subdevice 0x8900, .card SAA7164_BOARD_HAUPPAUGE_HVR2200_2, }, { .subvendor 0x0070, .subdevice 0x8901, .card SAA7164_BOARD_HAUPPAUGE_HVR2200_3, }, { .subvendor 0x0070, .subdevice 0x88A1, .card SAA7164_BOARD_HAUPPAUGE_HVR2250_3, }, { .subvendor 0x0070, .subdevice 0x8891, .card SAA7164_BOARD_HAUPPAUGE_HVR2250_2, }, { .subvendor 0x0070, .subdevice 0x8851, .card SAA7164_BOARD_HAUPPAUGE_HVR2250_2, }, { .subvendor 0x0070, .subdevice 0x8940, .card SAA7164_BOARD_HAUPPAUGE_HVR2200_4, }, { .subvendor 0x0070, .subdevice 0x8953, .card SAA7164_BOARD_HAUPPAUGE_HVR2200_5, }, { .subvendor 0x0070, .subdevice 0xf111, .card SAA7164_BOARD_HAUPPAUGE_HVR2255, }, { .subvendor 0x0070, .subdevice 0xf123, .card SAA7164_BOARD_HAUPPAUGE_HVR2205, }, { .subvendor 0x0070, .subdevice 0xf120, .card SAA7164_BOARD_HAUPPAUGE_HVR2205, }, };对比文档可知0070:8880与0070:8810都映射到 HVR2250即 3 号卡0070:8891与0070:8851都映射到 HVR2250_27 号卡而文档中标注为 HVR2255(proto) 的0070:f111在源码中实际映射为正式版SAA7164_BOARD_HAUPPAUGE_HVR225512 号卡原型板条目SAA7164_BOARD_HAUPPAUGE_HVR2255proto11 号在saa7164_subids[]中被注释保留源码注释原文Prototype card left here for documentation purposes.。这说明文档列表保留历史条目但驱动实际行为以saa7164_subids[]表的映射为准。自动识别流程在 saa7164-core.c 中板卡识别的逻辑顺序是若用户通过cardn模块参数指定了合法编号card[dev-nr] saa7164_bcount则优先使用该编号否则遍历saa7164_subids[]将设备上报的pci-subsystem_vendor/pci-subsystem_device与表中条目比对命中即采用对应板卡枚举若既无参数也未命中调用saa7164_card_list()打印错误日志。SAA7164_MAXBOARDS定义为 8saa7164.h即驱动最多支持 8 块卡同时工作card[]数组按dev-nr索引每块卡的参数。card 模块参数手动指定板卡为什么需要手动指定如 pci-cardlist.rst 所述不同产品有时会复用同一个 PCI 子系统 ID导致自动识别可能选错配置此外全新板卡、无有效子系统 ID 的工程板也会导致识别失败。此时需要card参数强制指定。card 的用法加载模块时指定假设目标板是 13 号 HVR2205modprobe saa7164 card13或写入模块参数后重新加载echo options saa7164 card13 /etc/modprobe.d/saa7164.conf modprobe -r saa7164 modprobe saa7164参数无效时的内核提示在 saa7164-cards.c 的saa7164_card_list()中驱动会区分两种失败场景并打印指引设备的子系统厂商 ID 与设备 ID 均为 0无有效子系统 ID时提示板卡无法自动识别请用cardninsmod 参数绕过并建议向厂商反馈子系统 ID 有效但不在saa7164_subids[]中时提示板卡尚未被驱动识别可尝试用cardn挑选现有配置之一或升级到最新内核版本。无论哪种情况驱动都会遍历saa7164_boards[]打印全部可选条目格式为card%d - %s如card13 - Hauppauge WinTV-HVR2205方便用户对照本文的卡列表直接取用编号。板卡最终确认后saa7164-core.c 会打印类似subsystem: 0070:f123, board: Hauppauge WinTV-HVR2205 [card13,autodetected]的日志card[...]括号内会标注是手动指定还是自动识别。板卡定义内部结构端口与处理单元saa7164_boards[]数组saa7164-cards.c是每张卡配置的完整画像由struct saa7164_board描述saa7164.h核心字段包括name板卡显示名porta ~ portf六个硬件端口的类型取值来自enum port_tSAA7164_MPEG_DVB数字电视传输流、SAA7164_MPEG_ENCODERMPEG 编码器、SAA7164_MPEG_VBIVBI 垂直消隐期数据chiprev芯片修订版本SAA7164_CHIP_REV2/SAA7164_CHIP_REV3unit[]最多SAA7164_MAX_UNITS8个处理单元描述。处理单元unit的含义SAA7164 桥接芯片的特殊之处在于主机无法直接访问板上的 I2C 总线saa7164-cards.c 的注释明确指出所有对调谐器、解调器等器件的寄存器访问都必须通过设备固件提供的处理单元接口进行。因此驱动维护了一张单元表每个单元包含类型、唯一 ID、所在虚拟 I2C 总线号与器件地址。单元类型定义于 saa7164.hSAA7164_UNIT_TUNER调谐器、SAA7164_UNIT_DIGITAL_DEMODULATOR数字解调器、SAA7164_UNIT_ANALOG_DEMODULATOR模拟解调器、SAA7164_UNIT_EEPROM板载 EEPROM、SAA7164_UNIT_ENCODER编码器等。单元表还定义了i2c_reg_len寄存器地址宽度REGLEN_0bit/REGLEN_8bit/REGLEN_16bit见 saa7164-cards.c供虚拟 I2C 层在构造 API 命令时判断寄存器宽度。驱动提供saa7164_i2caddr_to_unitid()和saa7164_i2caddr_to_reglen()两个翻译函数saa7164-cards.c把内核标准 I2C 子系统的总线号 器件地址映射回 SAA7164 固件认识的 unit ID 与寄存器宽度从而复用内核现有的 tuner/demod 驱动——这是本驱动架构设计的关键点。三路虚拟 I2C 总线单元表中出现的SAA7164_I2C_BUS_0/SAA7164_I2C_BUS_1/SAA7164_I2C_BUS_2saa7164.h对应桥接芯片内部的三路虚拟 I2C 总线每块卡通常把两个调谐器/解调器对分挂在不同的总线上例如 HVR2250 的 TDA18271-1 挂在 BUS_1、TDA18271-2 挂在 BUS_2。struct saa7164_dev中的i2c_bus[3]saa7164.h即对应这三路总线实例。各型号硬件配置差异从单元表看板卡卡列表中的多张 HVR2200/HVR2250 变体在硬件上并不完全相同差异通过chiprev与unit[]单元表体现以下均出自 saa7164-cards.c 中各板卡定义HVR2200 系列4/5/6/9/10 号DVB-T 平台双 TDA18271 调谐器 双 TDA10048 数字解调器。其中 5 号0070:8900与 6 号0070:8901使用 Rev2 芯片4 号0070:8980、9 号0070:8940使用 Rev3 芯片5/6 号的单元 ID 分配与 4 号略有不同如 5 号 TDA10048-1 的单元 ID 为 0x05、4 号为 0x1e。10 号0070:8953比较特殊它只启用了 porta/portb 两个 DVB 端口且额外挂载了 TDA8290 模拟解调器。HVR2250 系列3/7/8 号ATSC/QAM 平台双 TDA18271 调谐器 双 CX24228/S5H1411 数字解调器每个解调器又分 TOP 与 QAM 两个单元条目。3 号0070:8880/0070:8810使用 Rev3 芯片7 号0070:8891/0070:8851与 8 号0070:88A1在单元 ID 分配上相互错开如 7 号第二个 TDA18271 的单元 ID 为 0x24、8 号为 0x22。HVR225512 号0070:f111ATSC/QAM 平台双 SI2157 调谐器 双 LGDT3306 数字解调器Rev3 芯片。调谐器使用REGLEN_0bit无寄存器地址宽度的直写器件与早期型号的REGLEN_8bit不同。HVR220513 号0070:f123/0070:f120DVB-T/T2/C 平台双 SI2157 调谐器 双 SI2168 数字解调器Rev3 芯片所有 I2C 器件均为REGLEN_0bit。驱动在 saa7164-core.c 中遍历saa7164_boards[dev-board]的六个端口字段按SAA7164_MPEG_DVB/SAA7164_MPEG_ENCODER/SAA7164_MPEG_VBI分别注册 DVB 前端、V4L2 编码器与 VBI 设备因此卡列表中的端口配置直接决定了用户空间可见的/dev/dvb与/dev/video*设备数量。EEPROM 与 GPIO 初始化除单元表外板卡定义还驱动了两类初始化逻辑saa7164_gpio_setup()saa7164-cards.c按板卡类型复位解调器对 HVR2200/HVR2250 使用 GPIO 2/3 复位 s5h1411/tda10048 解调器对 HVR2255 复位 lgdt3306 解调器对 HVR2205 复位 si2168 解调器并额外管理 GPIO 7 上的 Zilog IR Blaster 复位。saa7164_card_setup()saa7164-cards.c读取板载 EEPROM通过saa7164_api_read_eeprom由hauppauge_eeprom()调用tveeprom_hauppauge_analog()解析 Hauppauge 型号并校验支持范围如 HVR2250 对应 88001/88021/88041/88061HVR2200 对应 89519/89609/89619HVR2205 对应 151009/151609HVR2255 对应 151061未知型号会打印警告。驱动构建与模块加载SAA7164 驱动的 Kconfig 条目drivers/media/pci/saa7164/Kconfigconfig VIDEO_SAA7164 tristate NXP SAA7164 support depends on DVB_CORE VIDEO_DEV PCI I2C select I2C_ALGOBIT select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT要点依赖DVB_COREDVB 核心、VIDEO_DEVV4L2 框架、PCI与I2C自动选择I2C_ALGOBIT软件位操作 I2C 算法、FW_LOADER固件加载、VIDEO_TUNER调谐器通用层、VIDEO_TVEEPROMHauppauge EEPROM 解析在MEDIA_SUBDRV_AUTOSELECT开启时自动选择 TDA10048/S5H1411 解调器与 TDA18271 调谐器驱动编译为模块时模块名为saa7164对应 Makefile 中的obj-$(CONFIG_VIDEO_SAA7164) saa7164.o。典型使用场景以手动指定 13 号 HVR2205 为例# 查看硬件是否被识别及当前匹配的板卡 dmesg | grep -i saa7164 # 手动指定卡编号后重新加载 sudo modprobe -r saa7164 sudo modprobe saa7164 card13 # 确认识别结果与可用设备 lspci -vn | grep -A3 -i multimedia ls /dev/dvb/ /dev/video* 2/dev/null排查速查从卡列表定位问题驱动未加载确认内核已启用CONFIG_VIDEO_SAA7164并检查dmesg中是否提示固件缺失驱动依赖FW_LOADER加载器件固件。cardn参数被拒绝确认编号在 0–13 范围内且小于saa7164_bcount板卡表长度由ARRAY_SIZE(saa7164_boards)计算见 saa7164-cards.c。识别到错误型号先用lspci -vn核对子系统 ID 是否与上表匹配若 ID 不在表中按dmesg中saa7164_card_list()打印的card%d - 名称列表挑选功能最接近的条目并通过card指定。同 ID 复用导致误判例如0070:f111在文档中同时出现于 11 号proto与 12 号正式版源码实际映射为 12 号正式板卡遇到此类一 ID 多型号情况应优先以 saa7164-cards.c 的saa7164_subids[]为准必要时用card强制覆盖。设备节点数量不符对照本文各型号的端口配置porta–portf确认 DVB/编码器/VBI 端口数量与预期一致例如 HVR2200/HVR2250 系列为双 DVB 双编码器 双 VBI而 10 号 HVR2200_5 仅启用两个 DVB 端口。结语saa7164-cardlist.rst虽然只是一张 14 行的表格但它是理解整个 SAA7164 驱动板卡支持矩阵的入口卡编号对应 saa7164.h 的枚举、子系统 ID 对应 saa7164-cards.c 的匹配表、而每张卡的深层差异芯片版本、六端口类型、调谐器/解调器单元拓扑、GPIO 复位与 EEPROM 校验都沉淀在saa7164_boards[]的单元表中。掌握这张表就等于同时掌握了读内核日志、用 lspci 对号入座、以 card 参数手动兜底的完整排障三板斧。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考