kernel5.4版本gpu DRM驱动入门--Apple的学习笔记

一,前言

昨天的framebuffer驱动qemu仿真调试--Apple的学习笔记中我提及到vxpress v9仿真使用的是drm不是framebuffer,所以今天来说说drm。

二,DRM框架

关于mesa,opengl和vulkan的3D绘图我之前都做过。大总结:嵌入式3D动画学习步骤总结--Apple的学习笔记里面有好几篇drm相关的。但是没有从内核驱动角度去分析,我当时主要学习的是3D应用编程。所以我先查了下内核help文档,并且网上搜索了下drm源码分析的资料,大概了解了下框架及drm_driver和相关主要函数。
之前学习framebuffer,我直接用下图左边的mmap操控显示。以前学习opengl等的时候使用的是下图右边绿色的通路操控显示。这就是区别,然后除了drm还有KMS,但是KMS我还不太清楚,所以先忽略。
自己先画一个层次图,理清下模块关系。

image.png

我现在理解DRM相关模块含义
1.framebuffer依然是画布。
2.CRTC是显示模式[等价于fb_info构造的fbdev](panel是显示区 域)。
3.Decoder是解码算法(比如yuv,rgb等)
4.Connector是连接接口转换波形用的(比如HDMI或DVI,他们的接口及显示时序不同吧!)

三,drm源码分析(Kernel 5.4.61)

搜索从设备树来定位使用的驱动代码sil,sii9022,立即搜索可以定位到sii902x_dt_ids.c而sii9022是HDMI解码芯片,它是一个i2c总线设备,不看具体内容,从框架角度来理解是比较容易的。
看了下设备树中endpoint的帮助,通过帮助还了解到了cma大容量内存设置也在设备树完成。
但是问题来了搜索关键字arm,pl111的时候,是在pl111_vexpress_clcd_init(pl111_vexpress.c)函数内,对应的c文件都没有probe函数的,感觉不太对呢!自己大概的看下相关c代码,我猜测应该会进入pl111_amba_probe(pl111_drv.c)函数。然后看到了,经过一路我不太熟悉的API调用后,会调用到register_framebuffer函数
drm_fb_helper_initial_config
-->__drm_fb_helper_initial_config_and_unlock
---->register_framebuffer
还是调试下吧!主要是看看probe是怎么进入的。
因为pl111_drv.c中只看到match table,而且没有name,只有id。

static const struct amba_id pl111_id_table[] = {
    {
        .id = 0x00041110,
        .mask = 0x000fffff,
        .data = (void *)&pl110_variant,
    },
    {
        .id = 0x00180110,
        .mask = 0x00fffffe,
        .data = (void *)&pl110_nomadik_variant,
    },
    {
        .id = 0x00041111,
        .mask = 0x000fffff,
        .data = (void *)&pl111_variant,
    },
    {0, 0},
};

四,drm驱动调试

果然可以进入pl111_amba_probe函数,我猜测正确,但是如何match的呢?

image.png

关于match函数一般都在bus相关的函数中,我找到了amba bus注册amba_driver_register,然后看到了关键函数amba_match

struct bus_type amba_bustype = {
    .name       = "amba",
    .dev_groups = amba_dev_groups,
    .match      = amba_match,
    .uevent     = amba_uevent,
    .dma_configure  = platform_dma_configure,
    .pm     = &amba_pm,
};

match函数中会调用amba_lookup,然后我看到了table->id和table->mask,我觉得和pl111_drv.c中的pl111_id_table对应上了,但是periphid是怎么来的呢?

static const struct amba_id *
amba_lookup(const struct amba_id *table, struct amba_device *dev)
{
    while (table->mask) {
        if (((dev->periphid & table->mask) == table->id) &&
            ((dev->cid != CORESIGHT_CID) ||
             (amba_cs_uci_id_match(table, dev))))
            return table;
        table++;
    }
    return NULL;
}

源码中搜索了下关键字periphid,猜测就是通过如下赋值的。

static int amba_device_try_add(struct amba_device *dev, struct resource *parent)
{
......
        /*
         * Read pid and cid based on size of resource
         * they are located at end of region
         */
        for (pid = 0, i = 0; i < 4; i++)
            pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) <<
                (i * 8);
        for (cid = 0, i = 0; i < 4; i++)
            cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
                (i * 8);

        if (cid == CORESIGHT_CID) {
            /* set the base to the start of the last 4k block */
            void __iomem *csbase = tmp + size - 4096;

            dev->uci.devarch =
                readl(csbase + UCI_REG_DEVARCH_OFFSET);
            dev->uci.devtype =
                readl(csbase + UCI_REG_DEVTYPE_OFFSET) & 0xff;
        }

        amba_put_disable_pclk(dev);

        if (cid == AMBA_CID || cid == CORESIGHT_CID) {
            dev->periphid = pid;  //periphid是在此处赋值的
            dev->cid = cid;
        }
}

然后调试验证下,谜底揭开了。果然是在此处赋值的,每次都是赋值新的值。通过函数内的注释大概了解到这些数值是资源的地址范围。此款芯片我不了解,暂时也不去下载datasheet查看,本次目的主要是顺便学习内核drm子系统框架,至于具体的drm内核API及详细代码将来有空再研究。


image.png

五,总结

了解了drm框架中的主要模块及关系。验证了pl111 LCDC驱动的probe是通过id经过mask匹配资源地址成功后进入的。另外了解下基于drm的设备树的关键字,今天算是drm驱动入门了。

你可能感兴趣的:(kernel5.4版本gpu DRM驱动入门--Apple的学习笔记)