背景
这一系列的总结本来应该伴随着项目及时的整理的,但是对于显卡驱动而言,本身能够参考的资料就非常的少,只能自己从内核代码中去不对揣摩推敲。项目的目的其实非常的简单粗暴,为什么这么说呢,因为要做的工作包含在嵌入式设备上实现一个2D硬件加速器,能够支持Mesa开源3D图形库,egl,DLX以及DRM模块。最后达到一个类桌面环境下的基于硬件加速的3D应用开发环境和显示平台。本篇文章是依据GPU内核代码,也就是DRM代码来从底层介绍显卡驱动的初始化过程,显卡类型是AMD的radeon r600以后的系列显卡。
基本的过程就是驱动载入,硬件初始化,设置硬件独立的模块(如内存管理器),设置显示(分辨率等);
radeon_driver_load_kms()
这个函数是在radeon_kms.c文件中定义的,也是所有和GPU初始化相关的内容的起始点。分别调用radeon_device_init()来初始化非显示设备的硬件,而调用radeon_modeset_init()来初始化显示设备相关的硬件(CRTC,connector, encoder等)。
radeon_device_init()
驱动初始化主要的工作都是由radeon_device_init()来完成,这个函数是在radeon_device.c中定义。首先我们会初始化一大堆的驱动需要使用的结构。然后调用radeon_asic_init(). 这个函数用于设置电路相关的一些函数指针,比如睡眠/恢复调用,硬件重置,设置和处理中断请求,设置和获取时钟等等。通用代码就会通过这些注册的函数指针来调用这些和电路相关的函数获得相应的功能。例如,使能和处理一中断在RV100和在RV700上是不一样的。由于不同generation的显卡不断的变化,对于多个asic families会有多个不同的处理方式。这也就让我们需要相容以及匹配针对不同的芯片编程相关的函数。例如,R1XX和R3xx芯片使用相同的中断处理模式,但是他们有不同的初始化路径(r100_init()和r300_init());
为驱动设置DMA掩码
这个步骤是让内核能够知道这个显卡能够处理什么样的大小的地址空间。对于radeon系列,这个被用于GPU访问图形缓冲,graphic buffer是存储在系统内存上,GPU通过GART表来访问这块系统内存。AGP以及更老的片上GART机制限制在32位。新的一些片上GART机制有更大的地址空间。