上一篇lcdservice中间,会带lvds_parameter=8_800_写入480类似的屏幕标志misc分区指定位置,重启系统后uboot会从misc分区中读出lvds_parameter=8_800_480标志,然后在设备树中找到与标志对应的标志lvds屏幕配置节点,并配置相应的节点。
1、uboot读取misc分区指定数据
u-boot/drivers/video/rockchip_display.c
#if 1 extern const disk_partition_t* get_disk_partition(const char *name); extern int StorageReadLba(uint32 LBA, void *pbuf, uint32 nSec); #define CUSTOM_PARTITION_NAME "misc" #define LCD_PARAM_MAX_COUNT 25 int lcdParam[LCD_PARAM_MAX_COUNT]; char param_buf_temp[100] = {0}; int get_lcdparam_info_from_custom_partition() { const disk_partition_t *ptn1 = get_disk_partition(CUSTOM_PARTITION_NAME); int i; if (!ptn1) { printf("OEM partition not found!\n"); return -1; } printf("block num: %lu, name %s ,type %s,block size :%lu\n",ptn1->size,ptn1->name,ptn1->type,ptn1->blksz); if (StorageReadLba(ptn1->start 2, param_buf_temp, DIV_ROUND_UP(sizeof(param_buf_temp), RK_BLK_SIZE)) != 0) { printf("failed to read oem!= 0) { printf("failed to read oem!\n"); return -1; } printf("%s \n",param_buf_temp); return 0; } #endif
需要注意ptn1->start指针一次偏移512个字节。
2.验证屏幕标志,获取设备树屏节点
u-boot/drivers/video/rockchip_display.c
static char *get_screen_para(void *blob, int parent_node, char *screen_buf,int len) { if((screen_buf == NULL) || (len <= 0) || (parent_node <= 0)) return NULL; memset(screen_buf,'\0',len); if(strstr(param_buf_temp, "7_800_480_18") || strstr(param_buf_temp, "7_800_480_24")) { strcpy(screen_buf,"inch8rgb"); } else if(strstr(param_buf_temp, "10_4_1024_768")) { strcpy(screen_buf,"g104x1-l04"); } else if(strstr(param_buf_temp, "15_1024_768")) { strcpy(screen_buf,"ldb15xga"); } else if(strstr(param_buf_temp, "17_1280_1024")) { strcpy(screen_buf,"M170ETN01"); } else if(strstr(param_buf_temp, "19_1440_900")) { strcpy(screen_buf,"M190PW01"); } else if(strstr(param_buf_temp, "21_5_1920_1080")) { strcpy(screen_buf,"t215hvn01"); } else if(strstr(param_buf_temp, "32_1920_1080")) { strcpy(screen_buf,"LD320DUE"); } else if(strstr(param_buf_temp, "10_1_1280_800")) { strcpy(screen_buf,"g101ice"); } else { printf("no find screen\n"); return NULL; } int i = 0,ret = 0; char *output = NULL; for (i=parent_node;i>=0;i ) { output = (char *)fdt_getprop_by_offset(blob, i, NULL, &ret); if (output != NULL) { if((strncmp(output, "duallvds", 8)==0) || (strncmp(output, "lvds", 4)==0)) { printf("****output: %s -- offset : %d\n",output,i); break; } } } return screen_buf; }
3.在设备树中找到屏幕配置节点,并修改为新设置节点
u-boot/drivers/video/rockchip_display.c
static int fdt_fixup_display_sub_route(void *blob, const char *name, enum fdt_status status) { int route, phandle, connect, connector, panel, dt, timing; char path[64]; int ret; int offset = 0; int len; char *screen_node = NULL; char screen_buf[20] = {0}; char *screen_name = NULL; sprintf(path, "/display-subsystem/route/route-%s", name); route = fdt_path_offset(blob, path); if (route < 0) return route; /* fixup route status */ ret = fdt_fixup_node_status(blob, route, status); if (ret < 0) return ret; phandle = fdt_getprop_u32_default_node(blob, route, 0, "connect", -1); if (phandle < 0) return phandle; connect = fdt_node_offset_by_phandle(blob, phandle); if (connect < 0) return connect; connector = find_connector_node(blob, connect); if (connector < 0) return connector; /* fixup connector status */ ret = fdt_fixup_node_status(blob, connector, status); if (ret < 0) return ret; if (status != FDT_STATUS_OKAY) return 0; panel = get_panel_node(blob, connector); if (panel < 0) return panel; dt = fdt_subnode_offset(blob, panel, "display-timings"); if (dt < 0) return dt; timing = fdt_subnode_offset(blob, dt, "timing"); if (timing < 0) { phandle = fdt_getprop_u32_default_node(blob, dt, 0, "native-mode", -1); if (phandle < 0) return phandle; timing = fdt_node_offset_by_phandle_node(blob, dt, phandle); if (timing < 0) return timing; } screen_name = get_screen_para(blob,panel,screen_buf,sizeof(screen_buf)); if(screen_name == NULL) { return -1; } else{ ret = fdt_set_phandle(blob,timing,0); } for(offset = dt;(offset >=0);(offset = fdt_next_node(blob, offset,&len))) { screen_node = fdt_get_name(blob,offset,&len); printf("name = %s -- offset = %d\n",screen_node,offset); if (screen_node != NULL) { if(strncmp(screen_buf,screen_node,strlen(screen_node)) == 0) { printf("offset = %d -- name = %s\n", offset, fdt_get_name(blob,offset,&len)); break; } } } fdt_set_phandl(blob,offset,phandle);
uint32_t screen_7_18 = 18;
uint32_t screen_7_24 = 24;
if(strstr(param_buf_temp, "7_800_480_18")) {
fdt_setprop_u32(blob,panel,"rockchip,data-width",screen_7_18);
} else {
fdt_setprop_u32(blob,panel,"rockchip,data-width",screen_7_24);
}
if((strcmp(screen_buf,"inch8rgb")==0) || (strcmp(screen_buf,"g104x1-l04")==0) || (strcmp(screen_buf,"g101ice")==0) || (strcmp(screen_buf,"ldb15xga")==0)) {
fdt_setprop_string(blob,panel,"rockchip,output","lvds");
} else if ((strcmp(screen_buf,"M170ETN01")==0) || (strcmp(screen_buf,"M190PW01")==0) || (strcmp(screen_buf,"t215hvn01")==0) || (strcmp(screen_buf,"LD320DUE")==0)) {
fdt_setprop_string(blob,panel,"rockchip,output","duallvds");
}
int i = 0;
char *output = NULL;
for (i=panel;i>=0;i++)
{
output = (char *)fdt_getprop_by_offset(blob, i, NULL, &ret);
if (output != NULL) {
if((strncmp(output, "duallvds", 8)==0) || (strncmp(output, "lvds", 4)==0)) {
printf("output: %s -- offset : %d\n",output,i);
break;
}
}
}
return 0;
}
设备树修改完成后,uboot正常引导内核启动,内核加载新的设备树,启动后会按照新的屏幕显示。
注意事项:lvds屏幕默认电压不一致,有时可能会出现电压过高烧屏问题,建议在修改屏幕参数时接hdmi屏幕或使用adb投屏方式
adb投屏软件:
链接:https://pan.baidu.com/s/1fYxbAhyBsM-ugB6WqiIeww 提取码:xite