完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
0 前言
刚买的HDMI没有配DSI接口的屏幕,大多数情况下使用的是HDMI屏幕,所以搞清楚HDMI驱动对后面的学习很有必要。 1 HDMI驱动相关代码查询 要想找到HDMI驱动位置,先编译一遍kernel,然后找相关的.o文件: zhu@zhu-VirtualBox:~/Work/Projects/rk3399/srcs/Android-8.1/android/kernel/drivers$ find -name *hdmi*.o ./gpu/drm/rockchip/dw_hdmi-rockchip.o ./gpu/drm/rockchip/inno_hdmi.o ./gpu/drm/bridge/synopsys/dw-hdmi-hdcp.o ./gpu/drm/bridge/synopsys/dw-hdmi.o ./gpu/drm/bridge/synopsys/dw-hdmi-cec.o ./gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.o ./video/hdmi.o ./video/hdmi-notifier.o ./phy/rockchip/phy-rockchip-inno-hdmi-phy.o 2 驱动接口分析 不管是HDMI还是DSI接口的屏,最后都会使用DRM框架的crtc来操作,先grep下file_operations结构体: 2.1 在./gpu/drm/rockchip/下grep rockchip_drm_drv.c:1658:static const struct file_operations rockchip_drm_driver_fops = { 进去看看其对应的驱动设备,这应该就是DRM驱动接口,里面的ioctl是给libdrm使用的,填图刷图在里面。 static const struct file_operations rockchip_drm_driver_fops = { .owner = THIS_MODULE, .open = drm_open, .mmap = rockchip_gem_mmap, .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif .release = drm_release, }; 一个DRM驱动一定有一个drm_driver结构体: static struct drm_driver rockchip_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC | DRIVER_RENDER, // 告诉 DRM Core 当前驱动支持 modeset/gem等操作 .preclose = rockchip_drm_preclose, .lastclose = rockchip_drm_lastclose, .get_vblank_counter = drm_vblank_no_hw_counter, .open = rockchip_drm_open, .postclose = rockchip_drm_postclose, .enable_vblank = rockchip_drm_crtc_enable_vblank, .disable_vblank = rockchip_drm_crtc_disable_vblank, .gem_vm_ops = &rockchip_drm_vm_ops, .gem_free_object = rockchip_gem_free_object, .dumb_create = rockchip_gem_dumb_create, // 创建buffer .dumb_map_offset = rockchip_gem_dumb_map_offset, // mmap buffer .dumb_destroy = drm_gem_dumb_destroy, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = drm_gem_prime_import, .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table, .gem_prime_vmap = rockchip_gem_prime_vmap, .gem_prime_vunmap = rockchip_gem_prime_vunmap, .gem_prime_mmap = rockchip_gem_mmap_buf, .gem_prime_begin_cpu_access = rockchip_gem_prime_begin_cpu_access, .gem_prime_end_cpu_access = rockchip_gem_prime_end_cpu_access, #ifdef CONFIG_DEBUG_FS .debugfs_init = rockchip_drm_debugfs_init, .debugfs_cleanup = rockchip_drm_debugfs_cleanup, #endif .ioctls = rockchip_ioctls, .num_ioctls = ARRAY_SIZE(rockchip_ioctls), .fops = &rockchip_drm_driver_fops, // 对应上面的fops .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, }; DRM初始化过程: rockchip_drm_platform_probe // 驱动入口 @kernel/drivers/gpu/drm/rockchip/rockchip_drm_drv.c |-->component_master_add_with_match(dev, &rockchip_drm_ops, match) // @kernel-4.14/drivers/base/component.c |-->try_to_bring_up_master |-->master->ops->bind(master->dev) |-->rockchip_drm_bind // @kernel/drivers/gpu/drm/rockchip/rockchip_drm_drv.c |-->drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev) // struct drm_device * drm_dev @kernel/drivers/gpu/drm/drm_drv.c 分配并初始化一个DRM设备 // drm_dev->driver = rockchip_drm_driver |-->rockchip_drm_init_iommu |-->drm_mode_config_init(drm_dev) // @kernel/drivers/gpu/drm/drm_crtc.c | |-->drm_mode_create_standard_properties(dev) // 创建DRM属性 |-->rockchip_drm_mode_config_init(drm_dev) // 设置fb的最大最小宽高 |-->rockchip_drm_create_properties(drm_dev) // 创建CABC等属性 |-->component_bind_all(dev, drm_dev) //Try to bind all sub drivers |-->rockchip_attach_connector_property(drm_dev) // 对于每个connector, 亮度、饱和度、对比度、色调都设置为100 |-->drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc) // 初始化vblank |-->drm_mode_config_reset(drm_dev) |-->rockchip_drm_set_property_default(drm_dev) // 对于每个connector, 亮度、饱和度、对比度、色调都设置为50 |-->drm_dev->irq_enabled = true // 可以使用vblank feature |-->drm_kms_helper_poll_init(drm_dev) |-->drm_dev->vblank_disable_allowed = true // vblank中断disable |-->rockchip_gem_pool_init(drm_dev) |-->of_reserved_mem_device_init(drm_dev->dev) |-->rockchip_drm_fbdev_init(drm_dev) |-->drm_dev_register(drm_dev, 0) // 注册drm设备 |-->drm_minor_register(dev, DRM_MINOR_CONTROL) |-->drm_minor_register(dev, DRM_MINOR_RENDER) |-->drm_minor_register(dev, DRM_MINOR_PRIMARY) |-->dev->driver->load(dev, flags) 还有1个很重要的结构体: static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { .fb_create = rockchip_user_fb_create, // 创建buffer .output_poll_changed = rockchip_drm_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = rockchip_drm_atomic_commit, // 属性生效 }; 2.2 在./gpu/drm/bridge/synopsys/下grep dw-hdmi.c:3264:static const struct file_operations dw_hdmi_status_fops = { dw-hdmi.c:3354:static const struct file_operations dw_hdmi_ctrl_fops = { dw-hdmi.c:3404:static const struct file_operations dw_hdmi_phy_fops = { 以上三个fops都是debugfs文件节点操作函数:在/d/dw-hdmi/status、/d/dw-hdmi/ctrl和/d/dw-hdmi/phy 所以他们应该是用来调试的,其中dw_hdmi_ctrl_fops中的write可以用来写寄存器: static ssize_t dw_hdmi_ctrl_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct dw_hdmi *hdmi = ((struct seq_file *)file->private_data)->private; u32 reg, val; char kbuf[25]; if (hdmi->dev_type == RK3228_HDMI) return -EFAULT; if (copy_from_user(kbuf, buf, count)) return -EFAULT; if (sscanf(kbuf, "%x%x", ®, &val) == -1) return -EFAULT; if ((reg < 0) || (reg > HDMI_I2CM_FS_SCL_LCNT_0_ADDR)) { dev_err(hdmi->dev, "it is no a hdmi registern"); return count; } dev_info(hdmi->dev, "/**********hdmi register config******/"); dev_info(hdmi->dev, "n reg=%x val=%xn", reg, val); hdmi_writeb(hdmi, val, reg); return count; } dw_hdmi_phy_fops中的write可以用来写寄存器: static ssize_t dw_hdmi_phy_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct dw_hdmi *hdmi = ((struct seq_file *)file->private_data)->private; u32 reg, val; char kbuf[25]; if (copy_from_user(kbuf, buf, count)) return -EFAULT; if (sscanf(kbuf, "%x%x", ®, &val) == -1) return -EFAULT; if ((reg < 0) || (reg > 0x100)) { dev_err(hdmi->dev, "it is not a hdmi phy registern"); return count; } dev_info(hdmi->dev, "/*******hdmi phy register config******/"); dev_info(hdmi->dev, "n reg=%x val=%xn", reg, val); dw_hdmi_phy_i2c_write(hdmi, val, reg); return count; } 那么上面写的HDMI相关寄存器到底是啥?
#define HDMI_FC_DRM_UP 0x1167 #define HDMI_FC_DRM_HB0 0x1168 #define HDMI_FC_DRM_HB1 0x1169 #define HDMI_FC_DRM_PB0 0x116a #define HDMI_FC_DRM_PB1 0x116b #define HDMI_FC_DRM_PB2 0x116c #define HDMI_FC_DRM_PB3 0x116d #define HDMI_FC_DRM_PB4 0x116e #define HDMI_FC_DRM_PB5 0x116f #define HDMI_FC_DRM_PB6 0x1170 #define HDMI_FC_DRM_PB7 0x1171 #define HDMI_FC_DRM_PB8 0x1172 #define HDMI_FC_DRM_PB9 0x1173 #define HDMI_FC_DRM_PB10 0x1174 #define HDMI_FC_DRM_PB11 0x1175 #define HDMI_FC_DRM_PB12 0x1176 #define HDMI_FC_DRM_PB13 0x1177 #define HDMI_FC_DRM_PB14 0x1178 #define HDMI_FC_DRM_PB15 0x1179 #define HDMI_FC_DRM_PB16 0x117a #define HDMI_FC_DRM_PB17 0x117b #define HDMI_FC_DRM_PB18 0x117c #define HDMI_FC_DRM_PB19 0x117d #define HDMI_FC_DRM_PB20 0x117e #define HDMI_FC_DRM_PB21 0x117f #define HDMI_FC_DRM_PB22 0x1180 #define HDMI_FC_DRM_PB23 0x1181 #define HDMI_FC_DRM_PB24 0x1182 #define HDMI_FC_DRM_PB25 0x1183 #define HDMI_FC_DRM_PB26 0x1184 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1906 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
2382 浏览 1 评论
RK3588 GStreamer调试四路鱼眼摄像头四宫格显示报错
5175 浏览 1 评论
【飞凌嵌入式OK3576-C开发板体验】RKNN神经网络-YOLO图像识别
254 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
1336 浏览 0 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 02:02 , Processed in 0.630776 second(s), Total 71, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号