瑞芯微Rockchip开发者社区
登录
直播中
663597
12年用户
463经验值
私信
关注
[问答]
rockchip drm驱动的启动流程是怎样的
开启该帖子的消息推送
RK1808
内存
rockchip drm驱动的启动流程是怎样的?有哪几个阶段呢?
回帖
(1)
陈桂英
2022-2-16 09:53:24
rockchip drm驱动的启动流程图:
第一阶段:
mipi_dsi_probe
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取内存资源
dsi->irq = platform_get_irq(pdev, 0); //获取中断资源
dsi->pclk = devm_clk_get(dev, "pclk"); //获取pclk
dsi->regmap = devm_regmap_init_mmio(dev, regs, //初始化内存管理映射
ret = mipi_dphy_attach(dsi); //找到对应的phy
dphy->phy = devm_phy_optional_get(dev, "mipi_dphy"); //根据char找到dphy
ret = mipi_dsi_host_register(&dsi->dsi_host); //注册dsi host
of_mipi_dsi_device_add(host, node); //建立dsi device 结构体
component_add(dev, &dw_mipi_dsi_ops); //将mipi dsi 的componet 添加到list 中,供componet master调用其注册的回调函数dw_mipi_dsi_bind。
总结: mipi_dsi_probe 主要是将设备树中的资源解析出来 建立dsi dev ,最后完成component 框架的支持。
vop_probe
component_add(dev, &vop_component_ops); //将vop的componet添加到list中,供 componet master调用其注册的回调函数vop_bind。
总结: vop_probe 就是添加了对component 框架的支持。
第二阶段:
rockchip_drm_platform_probe
port = of_parse_phandle(np, "ports", i); //遍历subsys 下的ports属性
component_match_add(dev, &match, compare_of, port->parent); //将每个ports属性加入数组中
rockchip_add_endpoints(dev, &match, port); //将ports下的endpoint 属性也加入数组中
component_match_add(dev, &match, compare_of, port); //将backlight属性也加入数组中
component_master_add_with_match(dev, &rockchip_drm_ops, match); //将match数组加入master中
struct master *master; //定义了一个master
master = kzalloc(sizeof(*master), GFP_KERNEL); //为其分配空间
master->dev = dev; //填充master结构体
master->ops = ops; //ops中包括了bind函数
master->match = match; //包括了上面所有ports属性的match数组
try_to_bring_up_master(master, NULL); //尝试初始化该master(调用rockchip_drm_bind)
总结:rockchip_drm_platform_probe 做了以下工作:
1、遍历所有的prots(VOP设备)并加入到match列表中
2、遍历所有prots下的endpoint(display设备)并加入到matc列表中
3、将bcaklight设备加入match例表中
4、创建了master并将上述的match填充进去后尝试通过match列表bind所有设备
。
rockchip_drm_bind
drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);//申请一个drm设备数据结构
ret = drm_dev_set_unique(drm_dev, "%s", dev_name(dev)); //设置drm设备的名字
private->hdmi_pll.pll = devm_clk_get(dev, "hdmi-tmds-pll"); //获取hdmi-tmds-pll clk
private->default_pll.pll = devm_clk_get(dev, "default-vop-pll"); //获取def-vop-pll clk
ret = rockchip_drm_init_iommu(drm_dev); //iommu初始化
drm_mode_config_init(drm_dev); //mode_config 结构体初始化,也是为了drm dev结构体
rockchip_drm_mode_config_init(drm_dev); //宽、高限制
rockchip_drm_create_properties(drm_dev); //创建相关属性 :对应property
ret = component_bind_all(dev, drm_dev); //尝试调用所有子设备的bind函数(vop_bind、mipi_dsi_bind)
rockchip_attach_connector_property(drm_dev);//为connector 的brightnesscontraststaturationhue 属性赋值100
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);//vlank 初始化?
drm_mode_config_reset(drm_dev);//调用所有的reset callback函数
rockchip_drm_set_property_default(drm_dev);
drm_kms_helper_poll_init(drm_dev); //使能kms 轮询机制 主要是connector
rockchip_gem_pool_init(drm_dev); //使能gem 轮询机制
ret = of_reserved_mem_device_init(drm_dev->dev);//将dts配置中预留的memory 分配给device。
ret = rockchip_drm_fbdev_init(drm_dev); //fbdev 初始化
ret = drm_dev_register(drm_dev, 0); //注册drm dev
总结: rockchip_drm_bind 完成了drm dev的初始化,并调用了所有子设备的bind函数一起初始化整个display sys。
vop_bind
vop_data = of_device_get_match_data(dev);
alloc_size = sizeof(*vop) + sizeof(*vop->win) * num_wins; //需要申请内存的size
vop = devm_kzalloc(dev, alloc_size, GFP_KERNEL); //给vop分配内存,返回值为分配的内存区域的起始地址,分配内存区域在驱动卸载后自行释放。
ret = vop_win_init(vop); //初始化vop win
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")//phyaddr
vop->regs = devm_ioremap_resource(dev, res); //映射
vop->hclk = devm_clk_get(vop->dev, "hclk_vop"); //clk获取
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(dev, vop->irq, vop_isr, IRQF_SHARED, dev_name(dev), vop)//中断申请
disable_irq(vop->irq); //关闭中断,上电时开启
ret = vop_create_crtc(vop); //建立crtc
for (i = 0; i < vop->num_wins; i++) //vop可能有好几个
ret = vop_plane_init(vop, win, 0); //初始化plane(primary cursor)
ret = drm_share_plane_init(vop->drm_dev, &win->base, share,
drm_plane_helper_add(&win->base, &plane_helper_funcs);
ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, //建立跟plane相关的crtc(将上述plane结构体加入crtc结构体中)
drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);//crtc相关辅助函数
ret = vop_plane_init(vop, win, possible_crtcs);//初始化plane(overlay)
drm_flip_work_init(&vop->fb_unref_work, "fb_unref", vop_fb_unref_worker);
rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
总结:vob_bind主要完成了plane和crtc结构体的建立
dw_mipi_dsi_bind
ret = dw_mipi_dsi_dual_channel_probe(dsi);//mipi双通道
ret = dw_mipi_dsi_register(drm, dsi);
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm,//为encoder匹配一个crtc
drm_encoder_helper_add(&dsi->encoder, //encoder的辅助函数
ret = drm_encoder_init(drm, &dsi->encoder, //encoder初始化
。。。填充结构体,encoder type = DRM_MODE_ENCODER_DSI
ret = drm_connector_init(drm, &dsi->connector,//connector 初始化
。。。填充结构体
drm_connector_helper_add(connector, //connector的辅助函数
drm_mode_connector_attach_encoder(connector, encoder);将连接器和编码器连接起来(connector 结构体中有个encoderid数组用于匹配)
ret = drm_panel_attach(dsi->panel, &dsi->connector); //将连接器和图层绑定起来
总结:dw_mipi_dsi_bind主要实现了encoder和connector的初始化,并将连接器、编码器、图层三者关联起来。
结束语:
DRM驱动主要就是完成
CRTC
、
PLANE
、
ENCODER
、
CONNECTOR
、
DRM_BUF
几个要素的初始化和连接,最后通过一个drm结构管理整个驱动,在这个过程中为了保证每个成员的启动顺序加入了
component 框架
,为了便于对DRM_BUF的管理加入了
GEM
对其进行分配、释放和映射。
rockchip drm驱动的启动流程图:
第一阶段:
mipi_dsi_probe
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取内存资源
dsi->irq = platform_get_irq(pdev, 0); //获取中断资源
dsi->pclk = devm_clk_get(dev, "pclk"); //获取pclk
dsi->regmap = devm_regmap_init_mmio(dev, regs, //初始化内存管理映射
ret = mipi_dphy_attach(dsi); //找到对应的phy
dphy->phy = devm_phy_optional_get(dev, "mipi_dphy"); //根据char找到dphy
ret = mipi_dsi_host_register(&dsi->dsi_host); //注册dsi host
of_mipi_dsi_device_add(host, node); //建立dsi device 结构体
component_add(dev, &dw_mipi_dsi_ops); //将mipi dsi 的componet 添加到list 中,供componet master调用其注册的回调函数dw_mipi_dsi_bind。
总结: mipi_dsi_probe 主要是将设备树中的资源解析出来 建立dsi dev ,最后完成component 框架的支持。
vop_probe
component_add(dev, &vop_component_ops); //将vop的componet添加到list中,供 componet master调用其注册的回调函数vop_bind。
总结: vop_probe 就是添加了对component 框架的支持。
第二阶段:
rockchip_drm_platform_probe
port = of_parse_phandle(np, "ports", i); //遍历subsys 下的ports属性
component_match_add(dev, &match, compare_of, port->parent); //将每个ports属性加入数组中
rockchip_add_endpoints(dev, &match, port); //将ports下的endpoint 属性也加入数组中
component_match_add(dev, &match, compare_of, port); //将backlight属性也加入数组中
component_master_add_with_match(dev, &rockchip_drm_ops, match); //将match数组加入master中
struct master *master; //定义了一个master
master = kzalloc(sizeof(*master), GFP_KERNEL); //为其分配空间
master->dev = dev; //填充master结构体
master->ops = ops; //ops中包括了bind函数
master->match = match; //包括了上面所有ports属性的match数组
try_to_bring_up_master(master, NULL); //尝试初始化该master(调用rockchip_drm_bind)
总结:rockchip_drm_platform_probe 做了以下工作:
1、遍历所有的prots(VOP设备)并加入到match列表中
2、遍历所有prots下的endpoint(display设备)并加入到matc列表中
3、将bcaklight设备加入match例表中
4、创建了master并将上述的match填充进去后尝试通过match列表bind所有设备
。
rockchip_drm_bind
drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);//申请一个drm设备数据结构
ret = drm_dev_set_unique(drm_dev, "%s", dev_name(dev)); //设置drm设备的名字
private->hdmi_pll.pll = devm_clk_get(dev, "hdmi-tmds-pll"); //获取hdmi-tmds-pll clk
private->default_pll.pll = devm_clk_get(dev, "default-vop-pll"); //获取def-vop-pll clk
ret = rockchip_drm_init_iommu(drm_dev); //iommu初始化
drm_mode_config_init(drm_dev); //mode_config 结构体初始化,也是为了drm dev结构体
rockchip_drm_mode_config_init(drm_dev); //宽、高限制
rockchip_drm_create_properties(drm_dev); //创建相关属性 :对应property
ret = component_bind_all(dev, drm_dev); //尝试调用所有子设备的bind函数(vop_bind、mipi_dsi_bind)
rockchip_attach_connector_property(drm_dev);//为connector 的brightnesscontraststaturationhue 属性赋值100
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);//vlank 初始化?
drm_mode_config_reset(drm_dev);//调用所有的reset callback函数
rockchip_drm_set_property_default(drm_dev);
drm_kms_helper_poll_init(drm_dev); //使能kms 轮询机制 主要是connector
rockchip_gem_pool_init(drm_dev); //使能gem 轮询机制
ret = of_reserved_mem_device_init(drm_dev->dev);//将dts配置中预留的memory 分配给device。
ret = rockchip_drm_fbdev_init(drm_dev); //fbdev 初始化
ret = drm_dev_register(drm_dev, 0); //注册drm dev
总结: rockchip_drm_bind 完成了drm dev的初始化,并调用了所有子设备的bind函数一起初始化整个display sys。
vop_bind
vop_data = of_device_get_match_data(dev);
alloc_size = sizeof(*vop) + sizeof(*vop->win) * num_wins; //需要申请内存的size
vop = devm_kzalloc(dev, alloc_size, GFP_KERNEL); //给vop分配内存,返回值为分配的内存区域的起始地址,分配内存区域在驱动卸载后自行释放。
ret = vop_win_init(vop); //初始化vop win
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")//phyaddr
vop->regs = devm_ioremap_resource(dev, res); //映射
vop->hclk = devm_clk_get(vop->dev, "hclk_vop"); //clk获取
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(dev, vop->irq, vop_isr, IRQF_SHARED, dev_name(dev), vop)//中断申请
disable_irq(vop->irq); //关闭中断,上电时开启
ret = vop_create_crtc(vop); //建立crtc
for (i = 0; i < vop->num_wins; i++) //vop可能有好几个
ret = vop_plane_init(vop, win, 0); //初始化plane(primary cursor)
ret = drm_share_plane_init(vop->drm_dev, &win->base, share,
drm_plane_helper_add(&win->base, &plane_helper_funcs);
ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, //建立跟plane相关的crtc(将上述plane结构体加入crtc结构体中)
drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);//crtc相关辅助函数
ret = vop_plane_init(vop, win, possible_crtcs);//初始化plane(overlay)
drm_flip_work_init(&vop->fb_unref_work, "fb_unref", vop_fb_unref_worker);
rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
总结:vob_bind主要完成了plane和crtc结构体的建立
dw_mipi_dsi_bind
ret = dw_mipi_dsi_dual_channel_probe(dsi);//mipi双通道
ret = dw_mipi_dsi_register(drm, dsi);
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm,//为encoder匹配一个crtc
drm_encoder_helper_add(&dsi->encoder, //encoder的辅助函数
ret = drm_encoder_init(drm, &dsi->encoder, //encoder初始化
。。。填充结构体,encoder type = DRM_MODE_ENCODER_DSI
ret = drm_connector_init(drm, &dsi->connector,//connector 初始化
。。。填充结构体
drm_connector_helper_add(connector, //connector的辅助函数
drm_mode_connector_attach_encoder(connector, encoder);将连接器和编码器连接起来(connector 结构体中有个encoderid数组用于匹配)
ret = drm_panel_attach(dsi->panel, &dsi->connector); //将连接器和图层绑定起来
总结:dw_mipi_dsi_bind主要实现了encoder和connector的初始化,并将连接器、编码器、图层三者关联起来。
结束语:
DRM驱动主要就是完成
CRTC
、
PLANE
、
ENCODER
、
CONNECTOR
、
DRM_BUF
几个要素的初始化和连接,最后通过一个drm结构管理整个驱动,在这个过程中为了保证每个成员的启动顺序加入了
component 框架
,为了便于对DRM_BUF的管理加入了
GEM
对其进行分配、释放和映射。
举报
更多回帖
rotate(-90deg);
回复
相关问答
RK1808
内存
介绍HDMI显示的两套
流程
框架
2022-03-04
1491
Rockchip
的按键
驱动
该
怎样
去使用呢
2022-03-10
3587
rk3568 黑屏
2024-08-06
5018
怎样
从开源的linux源码中扣出
Rockchip
RGA 2D引擎
驱动
呢
2022-03-02
1438
android camera
驱动
流程
是
怎样
的?
2022-03-03
930
Bootrom loader的
启动
流程
是
怎样
的
2022-03-07
1646
基于
DRM
的LCD显示接口如何去开发呢
2022-03-03
2396
怎么实现
DRM
测试接收机设计?
2021-05-26
971
RK3288 Android7.1 uboot部分的MIPI显示
流程
是
怎样
的?
2022-03-03
940
Display
驱动
初始化
流程
是
怎样
的?
2022-03-10
1839
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分