SA8155平台GPU驱动与MDP通路调试实战 - 第3节
3.1 Adreno GPU 架构概览
Adreno GPU 是高通骁龙/Snapdragon 平台的核心图形处理器,在 SA8155 中集成 Adreno 640/650 系列。其架构采用统一着色器模型与 Tile-Based 渲染管线,兼顾高性能与低功耗。
架构要点: Adreno 采用分层结构:应用层通过 OpenGL ES / Vulkan 驱动提交命令 → 内核态 KGSL 驱动管理上下文与内存 → 硬件前端调度器分发到多个着色器核心簇(Shader Core Cluster),每个簇包含 ALU、纹理单元与 L1 缓存,最终通过渲染后端(RB)输出到帧缓冲。
3.1.1 Tile-Based 渲染与 GMEM
Adreno 使用 Tile-Based 渲染,将帧缓冲划分为 16×16 或 32×32 像素的 Tile,在片内 GMEM(通用内存)中完成深度测试与颜色混合,减少对外部 DDR 的带宽消耗。
| 特性 | 说明 |
|---|---|
| Tile 尺寸 | 16×16 / 32×32 像素(可配置) |
| GMEM 容量 | Adreno 640 约 1MB,Adreno 650 约 1.5MB |
| 带宽节省 | 相比直接渲染节省 40%~60% 外部内存访问 |
| 适用场景 | 高分辨率 UI、游戏渲染、合成 |
3.2 内核驱动模块加载流程
SA8155 平台 GPU 驱动以内核模块形式加载,主要涉及 KGSL(Kernel Graphics Support Layer)与 DRM 显示驱动。加载流程遵循标准 Linux 设备驱动模型:设备树匹配 → probe → 资源申请 → 初始化 → 注册。
3.2.1 关键函数调用链
// 驱动入口
module_init(kgsl_driver_init);
module_exit(kgsl_driver_exit);
// probe 流程简化
static int kgsl_device_probe(struct platform_device *pdev) {
// 1. 从设备树获取寄存器基址、中断号
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
// 2. 映射寄存器空间
device->reg_base = devm_ioremap_resource(&pdev->dev, res);
// 3. 获取时钟与电源域
device->gpu_clk = clk_get(&pdev->dev, "core_clk");
// 4. 初始化 MMU 与 GMEM
kgsl_mmu_init(device);
// 5. 加载 GPU 微码
kgsl_fw_load(device, "a650_sqe.fw");
// 6. 注册 misc 设备
misc_register(&device->miscdev);
// 7. 注册 devfreq 调频
devfreq_add_device(&device->dev, &kgsl_devfreq_profile, "kgsl-3d0", NULL);
return 0;
}
3.3 设备树配置解析
SA8155 平台通过设备树(Device Tree)描述 GPU 硬件资源。设备树节点位于 arch/arm64/boot/dts/qcom/sa8155.dtsi,核心节点为 qcom,kgsl-3d0。
3.3.1 关键属性说明
| 属性名 | 类型 | 说明 |
|---|---|---|
| compatible | string | "qcom,adreno-650.0", "qcom,kgsl-3d0" |
| reg | address-cells × 2 | 寄存器基址与大小(GMEM + 核心寄存器) |
| interrupts | u32 | GPU 中断号(通常为 0~3) |
| clocks | phandle list | 核心时钟、总线时钟、内存时钟 |
| qcom,gpu-model | string | "adreno650v2" |
| qcom,initial-pwrlevel | u32 | 初始电源等级 |
| qcom,gmu | phandle | GMU(Graphics Management Unit)节点引用 |
3.3.2 典型设备树片段
&gpu {
compatible = "qcom,adreno-650.0", "qcom,kgsl-3d0";
reg = <0 0x3d00000 0 0x40000>,
<0 0x3d9c000 0 0x10000>;
reg-names = "kgsl_3d0_reg_memory", "kgsl_3d0_gmem";
interrupts = <0 300 0>;
clocks = <&gpucc GPU_CC_GX_GFX3D_CLK>,
<&gpucc GPU_CC_CX_GMU_CLK>;
clock-names = "core_clk", "gmu_clk";
qcom,gpu-model = "adreno650v2";
qcom,initial-pwrlevel = <5>;
qcom,gmu = <&gmu>;
status = "okay";
};
调试提示: 在 SA8155 开发板上,可通过
cat /sys/kernel/debug/kgsl-3d0/registers 查看 GPU 寄存器状态,确认设备树映射是否正确。若 reg 地址错误,会导致 probe 失败,dmesg 中可见 kgsl: failed to ioremap 错误。
3.3.3 电源与调频配置
设备树中通过 qcom,gpu-pwrlevels 子节点定义 GPU 频率/电压等级,驱动根据负载动态切换。
qcom,gpu-pwrlevels {
#address-cells = <1>;
#size-cells = <0>;
compatible = "qcom,gpu-pwrlevels";
qcom,gpu-pwrlevel@0 {
reg = <0>;
qcom,initial-freq = <670000000>; // 670 MHz
qcom,min-freq = <200000000>;
qcom,max-freq = <670000000>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
qcom,initial-freq = <500000000>;
qcom,min-freq = <200000000>;
qcom,max-freq = <500000000>;
};
};
3.4 本章小结
- Adreno 架构:统一着色器 + Tile-Based 渲染 + GMEM,核心簇与渲染后端流水线清晰。
- 驱动加载:设备树匹配 → probe → 资源获取 → 硬件初始化 → 注册,关键函数
kgsl_device_probe()。 - 设备树:
qcom,kgsl-3d0节点定义寄存器、中断、时钟、电源等级,是驱动与硬件之间的桥梁。
常见踩坑: 设备树中
qcom,gmu 节点引用错误会导致 GMU 固件加载失败,GPU 无法进入低功耗状态。务必检查 dmesg | grep gmu 确认 GMU 初始化是否正常。