rk3288 开机动态切换lvds屏幕显示(二)uboot修改设备树

上一篇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!\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_phandle(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

猜你喜欢

转载自blog.csdn.net/qq_32645109/article/details/121351903