完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
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对其进行分配、释放和映射。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1523 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
1726 浏览 1 评论
RK3588 GStreamer调试四路鱼眼摄像头四宫格显示报错
4153 浏览 1 评论
【飞凌嵌入式OK3576-C开发板体验】RKNN神经网络-YOLO图像识别
254 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
1336 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-9 09:35 , Processed in 0.633975 second(s), Total 73, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号