2026/6/20 8:11:42
网站建设
项目流程
建设俄语网站,商城是什么平台,免费申请com网站,外贸网站建设 广州1. 重构数据结构支持多种分辨率/*** struct lvds_panel_config* brief LVDS面板配置数据结构* * 存储特定尺寸面板的所有配置参数*/
struct lvds_panel_config {char name[32]; /** 面板名称 */u32 width; /** 面板宽度…1. 重构数据结构支持多种分辨率/** * struct lvds_panel_config * brief LVDS面板配置数据结构 * * 存储特定尺寸面板的所有配置参数 */ struct lvds_panel_config { char name[32]; /** 面板名称 */ u32 width; /** 面板宽度(mm) */ u32 height; /** 面板高度(mm) */ /* 显示时序参数 */ struct drm_display_mode mode; /** DRM显示模式 */ struct videomode vm; /** 视频模式 */ /* LVDS配置 */ u32 format; /** LVDS格式 */ u32 bus_format; /** 总线格式 */ u32 bpc; /** 每颜色位数 */ bool dual_channel; /** 是否双通道 */ bool data_swap; /** 是否数据交换 */ /* 电源时序 */ u32 power_on_delay; /** 上电延迟(ms) */ u32 reset_delay; /** 复位延迟(ms) */ u32 init_delay; /** 初始化延迟(ms) */ /* GPIO极性 */ bool enable_active_high; /** 使能引脚高有效 */ bool reset_active_high; /** 复位引脚高有效 */ bool bl_active_high; /** 背光引脚高有效 */ /* 背光配置 */ u32 max_brightness; /** 最大亮度 */ u32 default_brightness; /** 默认亮度 */ u32 pwm_period; /** PWM周期(ns) */ }; /** * struct rk3568_lvds * brief RK3568 LVDS驱动主数据结构 */ struct rk3568_lvds { struct device *dev; struct drm_device *drm_dev; struct drm_panel panel; struct drm_bridge bridge; struct drm_connector connector; struct drm_encoder *encoder; /* 硬件资源 */ struct regmap *grf; void __iomem *regs; struct phy *phy; struct clk *pclk; struct clk *hclk; struct reset_control *reset; /* GPIO控制 */ struct regulator *vcc_supply; struct regulator *vccio_supply; struct gpio_desc *enable_gpio; struct gpio_desc *reset_gpio; struct gpio_desc *bl_enable_gpio; struct backlight_device *backlight; struct pwm_device *pwm; /* 面板配置 */ struct lvds_panel_config *config; /** 当前面板配置 */ struct lvds_panel_config *configs; /** 支持的面板配置数组 */ int num_configs; /** 配置数量 */ int current_config_idx; /** 当前配置索引 */ /* 状态标志 */ bool prepared; bool enabled; bool phy_enabled; /* 工作队列 */ struct work_struct reset_work; struct delayed_work enable_work; /* 调试信息 */ struct dentry *debugfs_dir; }; /* 常用面板配置数据库 */ static struct lvds_panel_config common_panels[] { /* 7寸 1280x800 通用LVDS屏 */ { .name 7-inch-1280x800, .width 154, .height 85, .mode { .clock 72000, .hdisplay 1280, .hsync_start 1280 48, .hsync_end 1280 48 32, .htotal 1280 48 32 80, .vdisplay 800, .vsync_start 800 3, .vsync_end 800 3 6, .vtotal 800 3 6 14, .flags DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, .type DRM_MODE_TYPE_DRIVER, }, .format LVDS_8BIT_MODE_FORMAT_1, .bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bpc 8, .dual_channel false, .data_swap false, .power_on_delay 20, .reset_delay 10, .init_delay 120, .enable_active_high true, .reset_active_high false, .bl_active_high true, .max_brightness 255, .default_brightness 200, .pwm_period 25000, }, /* 10.1寸 1280x800 LVDS屏 */ { .name 10.1-inch-1280x800, .width 216, .height 135, .mode { .clock 71000, .hdisplay 1280, .hsync_start 1280 64, .hsync_end 1280 64 128, .htotal 1280 64 128 192, .vdisplay 800, .vsync_start 800 3, .vsync_end 800 3 10, .vtotal 800 3 10 20, .flags DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, .type DRM_MODE_TYPE_DRIVER, }, .format LVDS_8BIT_MODE_FORMAT_1, .bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bpc 8, .dual_channel false, .data_swap false, .power_on_delay 25, .reset_delay 15, .init_delay 150, .enable_active_high true, .reset_active_high false, .bl_active_high true, .max_brightness 255, .default_brightness 200, .pwm_period 25000, }, /* 10.1寸 1024x600 LVDS屏 */ { .name 10.1-inch-1024x600, .width 216, .height 135, .mode { .clock 50000, .hdisplay 1024, .hsync_start 1024 160, .hsync_end 1024 160 70, .htotal 1024 160 70 160, .vdisplay 600, .vsync_start 600 12, .vsync_end 600 12 13, .vtotal 600 12 13 12, .flags DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, .type DRM_MODE_TYPE_DRIVER, }, .format LVDS_8BIT_MODE_FORMAT_1, .bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bpc 8, .dual_channel false, .data_swap false, .power_on_delay 20, .reset_delay 10, .init_delay 120, .enable_active_high true, .reset_active_high false, .bl_active_high true, .max_brightness 255, .default_brightness 200, .pwm_period 25000, }, /* 19寸 1280x1024 LVDS屏 */ { .name 19-inch-1280x1024, .width 376, .height 301, .mode { .clock 108000, .hdisplay 1280, .hsync_start 1280 48, .hsync_end 1280 48 112, .htotal 1280 48 112 248, .vdisplay 1024, .vsync_start 1024 1, .vsync_end 1024 1 3, .vtotal 1024 1 3 38, .flags DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC, .type DRM_MODE_TYPE_DRIVER, }, .format LVDS_8BIT_MODE_FORMAT_1, .bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bpc 8, .dual_channel false, .data_swap false, .power_on_delay 30, .reset_delay 20, .init_delay 200, .enable_active_high true, .reset_active_high true, .bl_active_high true, .max_brightness 255, .default_brightness 180, .pwm_period 25000, }, /* 19寸 1440x900 LVDS屏 */ { .name 19-inch-1440x900, .width 408, .height 255, .mode { .clock 106500, .hdisplay 1440, .hsync_start 1440 80, .hsync_end 1440 80 152, .htotal 1440 80 152 232, .vdisplay 900, .vsync_start 900 1, .vsync_end 900 1 3, .vtotal 900 1 3 28, .flags DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, .type DRM_MODE_TYPE_DRIVER, }, .format LVDS_8BIT_MODE_FORMAT_1, .bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bpc 8, .dual_channel false, .data_swap false, .power_on_delay 30, .reset_delay 20, .init_delay 200, .enable_active_high true, .reset_active_high false, .bl_active_high true, .max_brightness 255, .default_brightness 180, .pwm_period 25000, }, /* 21.5寸 1920x1080 LVDS屏 */ { .name 21.5-inch-1920x1080, .width 476, .height 268, .mode { .clock 148500, .hdisplay 1920, .hsync_start 1920 88, .hsync_end 1920 88 44, .htotal 1920 88 44 148, .vdisplay 1080, .vsync_start 1080 4, .vsync_end 1080 4 5, .vtotal 1080 4 5 36, .flags DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC, .type DRM_MODE_TYPE_DRIVER, }, .format LVDS_8BIT_MODE_FORMAT_1, .bus_format MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bpc 8, .dual_channel true, /* 高分辨率需要双通道 */ .data_swap false, .power_on_delay 50, .reset_delay 30, .init_delay 250, .enable_active_high true, .reset_active_high true, .bl_active_high true, .max_brightness 255, .default_brightness 150, .pwm_period 25000, }, };2. 面板自动检测函数/** * brief 根据EDID自动检测面板类型 * param lvds LVDS驱动私有数据 * param edid EDID数据 * return 成功返回配置索引失败返回-1 * * 通过读取EDID信息自动识别连接的显示器型号 */ static int rk3568_lvds_detect_panel_by_edid(struct rk3568_lvds *lvds, const struct edid *edid) { u32 width_mm, height_mm; u32 hdisplay, vdisplay; int i; if (!edid) { LVDS_ERROR(EDID数据为空\n); return -1; } /* 从EDID获取显示器尺寸 */ width_mm edid-width_cm * 10; height_mm edid-height_cm * 10; /* 从首选时序获取分辨率 */ hdisplay edid-detailed_timings[0].data.hactive_lo | ((edid-detailed_timings[0].data.hactive_hi 0xf0) 4); vdisplay edid-detailed_timings[0].data.vactive_lo | ((edid-detailed_timings[0].data.vactive_hi 0xf0) 4); LVDS_INFO(EDID检测: %dx%d mm, %dx%d pixels\n, width_mm, height_mm, hdisplay, vdisplay); /* 在配置数据库中查找匹配的面板 */ for (i 0; i lvds-num_configs; i) { struct lvds_panel_config *cfg lvds-configs[i]; /* 检查分辨率匹配 */ if (cfg-mode.hdisplay hdisplay cfg-mode.vdisplay vdisplay) { /* 检查尺寸匹配允许±10%误差 */ int width_diff abs((int)cfg-width - (int)width_mm); int height_diff abs((int)cfg-height - (int)height_mm); if (width_diff cfg-width * 0.1 height_diff cfg-height * 0.1) { LVDS_INFO(自动检测到面板: %s\n, cfg-name); return i; } } } LVDS_WARN(未找到精确匹配的面板使用最接近的配置\n); /* 查找最接近的分辨率 */ int best_match -1; int min_diff INT_MAX; for (i 0; i lvds-num_configs; i) { struct lvds_panel_config *cfg lvds-configs[i]; int diff abs((int)cfg-mode.hdisplay - (int)hdisplay) abs((int)cfg-mode.vdisplay - (int)vdisplay); if (diff min_diff) { min_diff diff; best_match i; } } if (best_match 0) { LVDS_INFO(使用最接近的面板: %s\n, lvds-configs[best_match].name); } return best_match; } /** * brief 根据GPIO检测面板类型 * param lvds LVDS驱动私有数据 * return 成功返回配置索引失败返回-1 * * 通过检测GPIO电平或使用跳线识别面板类型 */ static int rk3568_lvds_detect_panel_by_gpio(struct rk3568_lvds *lvds) { struct device *dev lvds-dev; struct device_node *np dev-of_node; int panel_id_gpios[4]; int panel_id 0; int num_gpios 0; int i, ret; /* 从设备树读取面板ID GPIO */ for (i 0; i 4; i) { char prop_name[32]; snprintf(prop_name, sizeof(prop_name), panel-id-gpios%d, i); ret of_get_named_gpio(np, prop_name, 0); if (ret 0) { panel_id_gpios[num_gpios] ret; num_gpios; } } if (num_gpios 0) { LVDS_DEBUG(1, 未找到面板ID GPIO\n); return -1; } /* 读取GPIO状态 */ for (i 0; i num_gpios; i) { int value; ret gpio_request(panel_id_gpios[i], panel-id); if (ret) { LVDS_ERROR(无法请求GPIO%d: %d\n, panel_id_gpios[i], ret); continue; } ret gpio_direction_input(panel_id_gpios[i]); if (ret) { LVDS_ERROR(无法设置GPIO%d为输入: %d\n, panel_id_gpios[i], ret); gpio_free(panel_id_gpios[i]); continue; } value gpio_get_value(panel_id_gpios[i]); panel_id | (value i); gpio_free(panel_id_gpios[i]); LVDS_DEBUG(2, 面板ID GPIO%d: %d\n, i, value); } LVDS_INFO(面板ID检测: 0x%x (使用%d个GPIO)\n, panel_id, num_gpios); /* 根据ID选择配置 */ if (panel_id lvds-num_configs) { LVDS_INFO(根据GPIO ID选择面板: %s\n, lvds-configs[panel_id].name); return panel_id; } LVDS_WARN(面板ID超出范围使用默认配置\n); return 0; } /** * brief 从设备树解析面板配置 * param lvds LVDS驱动私有数据 * return 成功返回0失败返回错误码 */ static int rk3568_lvds_parse_panel_config(struct rk3568_lvds *lvds) { struct device *dev lvds-dev; struct device_node *np dev-of_node; struct device_node *panel_np; const char *panel_name; int ret, i; LVDS_DEBUG(1, 解析面板配置\n); /* 查找面板子节点 */ panel_np of_get_child_by_name(np, panel); if (!panel_np) { LVDS_DEBUG(1, 无面板子节点使用通用配置\n); /* 使用通用配置数据库 */ lvds-configs common_panels; lvds-num_configs ARRAY_SIZE(common_panels); /* 尝试自动检测面板 */ lvds-current_config_idx rk3568_lvds_detect_panel_by_gpio(lvds); if (lvds-current_config_idx 0) { /* 使用第一个配置作为默认 */ lvds-current_config_idx 0; LVDS_INFO(使用默认面板: %s\n, lvds-configs[0].name); } lvds-config lvds-configs[lvds-current_config_idx]; return 0; } /* 从设备树读取面板名称 */ ret of_property_read_string(panel_np, panel-name, panel_name); if (ret) { LVDS_WARN(未指定面板名称使用默认\n); panel_name default; } /* 分配配置数组 */ lvds-num_configs 1; lvds-configs devm_kzalloc(dev, sizeof(struct lvds_panel_config), GFP_KERNEL); if (!lvds-configs) return -ENOMEM; lvds-config lvds-configs[0]; /* 设置面板名称 */ strncpy(lvds-config-name, panel_name, sizeof(lvds-config-name) - 1); /* 解析面板尺寸 */ ret of_property_read_u32(panel_np, width-mm, lvds-config-width); if (ret) { LVDS_WARN(未指定面板宽度使用默认值\n); lvds-config-width 154; /* 7寸默认 */ } ret of_property_read_u32(panel_np, height-mm, lvds-config-height); if (ret) { LVDS_WARN(未指定面板高度使用默认值\n); lvds-config-height 85; /* 7寸默认 */ } /* 解析显示时序 */ ret of_get_drm_display_mode(panel_np, lvds-config-mode, OF_USE_NATIVE_MODE, NULL); if (ret) { LVDS_ERROR(无法解析显示模式\n); return ret; } /* 设置模式名称 */ snprintf(lvds-config-mode.name, DRM_DISPLAY_MODE_LEN, %dx%d, lvds-config-mode.hdisplay, lvds-config-mode.vdisplay); /* 转换为videomode */ drm_display_mode_to_videomode(lvds-config-mode, lvds-config-vm); /* 解析LVDS配置 */ const char *format_str; ret of_property_read_string(panel_np, format, format_str); if (!ret) { if (!strcmp(format_str, jeida-24)) lvds-config-format LVDS_8BIT_MODE_FORMAT_1; else if (!strcmp(format_str, vesa-24)) lvds-config-format LVDS_8BIT_MODE_FORMAT_2; else if (!strcmp(format_str, jeida-18)) lvds-config-format LVDS_6BIT_MODE; else lvds-config-format LVDS_8BIT_MODE_FORMAT_1; } lvds-config-dual_channel of_property_read_bool(panel_np, dual-channel); lvds-config-data_swap of_property_read_bool(panel_np, data-swap); /* 解析电源时序 */ of_property_read_u32(panel_np, power-on-delay-ms, lvds-config-power_on_delay); of_property_read_u32(panel_np, reset-delay-ms, lvds-config-reset_delay); of_property_read_u32(panel_np, init-delay-ms, lvds-config-init_delay); /* 设置默认值 */ if (!lvds-config-power_on_delay) lvds-config-power_on_delay 20; if (!lvds-config-reset_delay) lvds-config-reset_delay 10; if (!lvds-config-init_delay) lvds-config-init_delay 120; /* 解析GPIO极性 */ lvds-config-enable_active_high !of_property_read_bool(panel_np, enable-active-low); lvds-config-reset_active_high !of_property_read_bool(panel_np, reset-active-low); lvds-config-bl_active_high !of_property_read_bool(panel_np, bl-active-low); /* 解析背光配置 */ of_property_read_u32(panel_np, max-brightness, lvds-config-max_brightness); of_property_read_u32(panel_np, default-brightness, lvds-config-default_brightness); of_property_read_u32(panel_np, pwm-period-ns, lvds-config-pwm_period); /* 设置背光默认值 */ if (!lvds-config-max_brightness) lvds-config-max_brightness 255; if (!lvds-config-default_brightness) lvds-config-default_brightness 200; if (!lvds-config-pwm_period) lvds-config-pwm_period 25000; LVDS_INFO(面板配置: %s, %dx%d, %dx%d mm\n, lvds-config-name, lvds-config-mode.hdisplay, lvds-config-mode.vdisplay, lvds-config-width, lvds-config-height); of_node_put(panel_np); return 0; }3. 动态分辨率切换支持/** * brief 应用面板配置 * param lvds LVDS驱动私有数据 * param config_idx 配置索引 * return 成功返回0失败返回错误码 * * 应用指定面板配置到硬件 */ static int rk3568_lvds_apply_panel_config(struct rk3568_lvds *lvds, int config_idx) { struct lvds_panel_config *cfg; if (config_idx 0 || config_idx lvds-num_configs) { LVDS_ERROR(无效的配置索引: %d\n, config_idx); return -EINVAL; } cfg lvds-configs[config_idx]; lvds-config cfg; lvds-current_config_idx config_idx; LVDS_INFO(应用面板配置: %s\n, cfg-name); /* 更新DRM显示模式 */ memcpy(lvds-mode, cfg-mode, sizeof(struct drm_display_mode)); memcpy(lvds-vm, cfg-vm, sizeof(struct videomode)); /* 更新LVDS配置 */ lvds-format cfg-format; lvds-bus_format cfg-bus_format; lvds-bpc cfg-bpc; lvds-dual_channel cfg-dual_channel; lvds-data_swap cfg-data_swap; /* 重新配置硬件 */ if (lvds-prepared) { int ret; /* 先禁用显示 */ rk3568_lvds_panel_disable(lvds-panel); /* 重新配置寄存器 */ ret rk3568_lvds_registers_config(lvds); if (ret) { LVDS_ERROR(重新配置寄存器失败: %d\n, ret); return ret; } /* 重新使能显示 */ rk3568_lvds_panel_enable(lvds-panel); } return 0; } /** * brief 获取支持的面板列表 * param lvds LVDS驱动私有数据 * param buf 输出缓冲区 * param size 缓冲区大小 * return 写入的字节数 */ static ssize_t rk3568_lvds_list_panels(struct rk3568_lvds *lvds, char *buf, size_t size) { ssize_t len 0; int i; len snprintf(buf len, size - len, 支持的LVDS面板列表:\n \n); for (i 0; i lvds-num_configs; i) { struct lvds_panel_config *cfg lvds-configs[i]; const char *current (i lvds-current_config_idx) ? * : ; len snprintf(buf len, size - len, %s [%d] %s\n 分辨率: %dx%d %d Hz\n 尺寸: %dx%d mm\n 格式: %s, %s通道\n 当前: %s\n\n, current, i, cfg-name, cfg-mode.hdisplay, cfg-mode.vdisplay, drm_mode_vrefresh(cfg-mode), cfg-width, cfg-height, (cfg-format LVDS_8BIT_MODE_FORMAT_1) ? JEIDA-24 : (cfg-format LVDS_8BIT_MODE_FORMAT_2) ? VESA-24 : JEIDA-18, cfg-dual_channel ? 双 : 单, (i lvds-current_config_idx) ? 是 : 否); } return len; } /** * brief 切换面板配置 * param lvds LVDS驱动私有数据 * param panel_name 面板名称 * return 成功返回0失败返回错误码 */ static int rk3568_lvds_switch_panel(struct rk3568_lvds *lvds, const char *panel_name) { int i; if (!panel_name || !panel_name[0]) { LVDS_ERROR(面板名称不能为空\n); return -EINVAL; } /* 查找匹配的面板 */ for (i 0; i lvds-num_configs; i) { if (strcmp(lvds-configs[i].name, panel_name) 0) { LVDS_INFO(切换到面板: %s\n, panel_name); return rk3568_lvds_apply_panel_config(lvds, i); } } /* 尝试按索引切换 */ if (isdigit(panel_name[0])) { int idx simple_strtol(panel_name, NULL, 10); if (idx 0 idx lvds-num_configs) { LVDS_INFO(按索引切换到面板[%d]\n, idx); return rk3568_lvds_apply_panel_config(lvds, idx); } } LVDS_ERROR(未找到面板: %s\n, panel_name); return -ENODEV; }4. 设备树多面板配置示例// rk3568-lvds-multi-panel.dts // 支持多种面板的设备树配置 / { compatible rockchip,rk3568; lvds_panels: lvds-panels { compatible rockchip,lvds-panels; // 面板选择GPIO可选 panel-id-gpios0 gpio0 RK_PC0 GPIO_ACTIVE_HIGH; panel-id-gpios1 gpio0 RK_PC1 GPIO_ACTIVE_HIGH; // 默认面板 default-panel panel_7inch; // 7寸面板配置 panel_7inch: panel-7inch { panel-name 7-inch-1280x800; width-mm 154; height-mm 85; panel-timing { clock-frequency 72000000; hactive 1280; vactive 800; hfront-porch 48; hback-porch 80; hsync-len 32; vfront-porch 3; vback-porch 14; vsync-len 6; hsync-active 0; vsync-active 0; }; format jeida-24; bus-format rgb888; bpc 8; power-on-delay-ms 20; reset-delay-ms 10; init-delay-ms 120; enable-active-high; reset-active-low; bl-active-high; max-brightness 255; default-brightness 200; pwm-period-ns 25000; }; // 10.1寸面板配置 panel_10inch: panel-10inch { panel-name 10.1-inch-1280x800; width-mm 216; height-mm 135; panel-timing { clock-frequency 71000; hactive 1280; vactive 800; hfront-porch 64; hback-porch 192; hsync-len 128; vfront-porch 3; vback-porch 20; vsync-len 10; hsync-active 0; vsync-active 0; }; format jeida-24; bus-format rgb888; bpc 8; power-on-delay-ms 25; reset-delay-ms 15; init-delay-ms 150; enable-active-high; reset-active-low; bl-active-high; max-brightness 255; default-brightness 200; pwm-period-ns 25000; }; // 19寸面板配置 panel_19inch: panel-19inch { panel-name 19-inch-1280x1024; width-mm 376; height-mm 301; panel-timing { clock-frequency 108000; hactive 1280; vactive 1024; hfront-porch 48; hback-porch 248; hsync-len 112; vfront-porch 1; vback-porch 38; vsync-len 3; hsync-active 1; vsync-active 1; }; format jeida-24; bus-format rgb888; bpc 8; dual-channel; power-on-delay-ms 30; reset-delay-ms 20; init-delay-ms 200; enable-active-high; reset-active-high; bl-active-high; max-brightness 255; default-brightness 180; pwm-period-ns 25000; }; }; lvds: lvdsfdfc0000 { compatible rockchip,rk3568-lvds; reg 0x0 0xfdfc0000 0x0 0x10000; clocks cru PCLK_LVDS, cru HCLK_LVDS; clock-names pclk, hclk; resets cru SRST_P_LVDS, cru SRST_H_LVDS; reset-names reset, reset-h; phys video_phy; phy-names dphy; rockchip,grf grf; status okay; ports { port1 { reg 1; lvds_out_panel: endpoint { remote-endpoint panel_in; }; }; }; }; vop: vopfe040000 { compatible rockchip,rk3568-vop; reg 0x0 0xfe040000 0x0 0x3000; interrupts GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH; clocks cru ACLK_VOP, cru HCLK_VOP, cru DCLK_VOP0; clock-names aclk, hclk, dclk_vop0; resets cru SRST_A_VOP, cru SRST_H_VOP, cru SRST_D_VOP0; reset-names axi, ahb, dclk; iommus vop_mmu; status okay; vop_out: ports { #address-cells 1; #size-cells 0; port0 { reg 0; #address-cells 1; #size-cells 0; vop_out_lvds: endpoint0 { reg 0; remote-endpoint lvds_in_vop; }; }; }; }; video_phy: video-phyfdfb0000 { compatible rockchip,rk3568-video-phy; reg 0x0 0xfdfb0000 0x0 0x10000; clocks cru PCLK_VIDEO_PHY; clock-names pclk; #phy-cells 0; status okay; }; };5. 增强的调试接口/** * brief 调试面板切换操作 * param file 文件 * param user_buf 用户缓冲区 * param count 字节数 * param ppos 文件位置 * return 读取的字节数 */ static ssize_t rk3568_lvds_panel_switch_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct rk3568_lvds *lvds file-private_data; char buf[64]; char *panel_name; int ret; if (count sizeof(buf)) return -EINVAL; if (copy_from_user(buf, user_buf, count)) return -EFAULT; buf[count] \0; /* 去除换行符 */ panel_name strim(buf); if (strlen(panel_name) 0) { /* 显示当前面板 */ char info[256]; ssize_t len; len snprintf(info, sizeof(info), 当前面板: %s [%d]\n 分辨率: %dx%d %d Hz\n 像素时钟: %d kHz\n 双通道: %s\n, lvds-config-name, lvds-current_config_idx, lvds-config-mode.hdisplay, lvds-config-mode.vdisplay, drm_mode_vrefresh(lvds-config-mode), lvds-config-mode.clock, lvds-config-dual_channel ? 是 : 否); return simple_read_from_buffer(user_buf, count, ppos, info, len); } /* 切换面板 */ ret rk3568_lvds_switch_panel(lvds, panel_name); if (ret) { char err_msg[128]; ssize_t len; len snprintf(err_msg, sizeof(err_msg), 切换面板失败: %s\n, panel_name); return simple_read_from_buffer(user_buf, count, ppos, err_msg, len); } return count; } /** * brief 调试面板列表读取 * param file 文件 * param user_buf 用户缓冲区 * param count 字节数 * param ppos 文件位置 * return 读取的字节数 */ static ssize_t rk3568_lvds_panels_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct rk3568_lvds *lvds file-private_data; char *buf; ssize_t len; buf kzalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; len rk3568_lvds_list_panels(lvds, buf, PAGE_SIZE); if (len 0) { kfree(buf); return len; } len simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return len; } /* 创建更多调试文件 */ static void rk3568_lvds_debugfs_init(struct rk3568_lvds *lvds) { struct dentry *root; root debugfs_create_dir(rk3568_lvds, NULL); if (IS_ERR(root)) return; lvds-debugfs_dir root; /* 面板列表 */ debugfs_create_file(panels, 0444, root, lvds, rk3568_lvds_panels_fops); /* 面板切换 */ debugfs_create_file(panel_switch, 0644, root, lvds, rk3568_lvds_panel_switch_fops); /* 当前配置 */ debugfs_create_u32(current_panel, 0444, root, lvds-current_config_idx); /* 时序参数 */ debugfs_create_x32(hdisplay, 0444, root, (u32 *)lvds-config-mode.hdisplay); debugfs_create_x32(vdisplay, 0444, root, (u32 *)lvds-config-mode.vdisplay); debugfs_create_x32(clock, 0444, root, (u32 *)lvds-config-mode.clock); /* LVDS配置 */ debugfs_create_x32(format, 0444, root, lvds-format); debugfs_create_bool(dual_channel, 0444, root, lvds-dual_channel); debugfs_create_bool(data_swap, 0444, root, lvds-data_swap); } /* 文件操作结构 */ static const struct file_operations rk3568_lvds_panels_fops { .owner THIS_MODULE, .read rk3568_lvds_panels_read, .llseek default_llseek, }; static const struct file_operations rk3568_lvds_panel_switch_fops { .owner THIS_MODULE, .write rk3568_lvds_panel_switch_write, .llseek default_llseek, };6. 使用方法示例#!/bin/bash # 多面板使用示例 echo RK3568 LVDS多面板驱动使用 # 1. 检查当前面板 echo 1. 检查当前面板: cat /sys/kernel/debug/rk3568_lvds/panels # 2. 查看当前配置 echo 2. 当前配置: cat /sys/kernel/debug/rk3568_lvds/panel_switch # 3. 切换面板通过名称 echo 3. 切换到10.1寸面板: echo 10.1-inch-1280x800 /sys/kernel/debug/rk3568_lvds/panel_switch # 4. 切换面板通过索引 echo 4. 切换到19寸面板索引2: echo 2 /sys/kernel/debug/rk3568_lvds/panel_switch # 5. 重启显示服务应用新配置 echo 5. 重启显示服务: systemctl restart lvds.service # 6. 验证新配置 echo 6. 验证配置: cat /sys/class/drm/card0-LVDS-1/modes cat /sys/class/backlight/*/actual_brightness第六部分总结重构了数据结构支持多种尺寸和分辨率的面板实现了7寸、10.1寸、19寸、21.5寸等多种常用面板的配置添加了面板自动检测功能EDID/GPIO实现了动态面板切换功能提供了完整的设备树多面板配置示例增强了调试接口支持面板列表查看和切换现在驱动可以支持7寸 1280x80010.1寸 1280x80010.1寸 1024x60019寸 1280x102419寸 1440x90021.5寸 1920x1080并且可以轻松扩展支持更多面板型号。