亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

ACTIONS S900 uboot階段顯示模塊分析!

2019-11-08 00:26:46
字體:
來源:轉載
供稿:網友

首先,顯示子系統的相關代碼在/u-boot/drivers/video/owl目錄下,分析從owl_fb.c開始。

void *video_hw_init(void){	owl_pwm_init(gd->fdt_blob);	owl_dss_init(gd->fdt_blob);	if (owl_fb_init(&g_owl_fb) < 0)		return NULL;	owl_fb_display_on(&g_owl_fb);	return &g_owl_fb.gd;}

video_hw_init無法追蹤到上一級,應該是直接在匯編中特定的地址位置來調用。owl_pwm_init(gd->fdt_blob)先點背光,這里不深入分析。

owl_dss_init(gd->fdt_blob)進入顯示子系統初始化函數:

void owl_dss_init(const void *blob){	/*	 * core init	 */	owl_ctrl_init();	owl_panel_init();	/*	 * de_xxx init	 */#ifdef CONFIG_VIDEO_OWL_DE_S900	owl_de_s900_init(blob);#endif	/*	 * controllers init	 */#ifdef CONFIG_VIDEO_OWL_DSI	owl_dsic_init(blob);#endif	/*	 * panels init	 */#ifdef CONFIG_VIDEO_OWL_DSI	owl_panel_ls055r3sx01_init(blob);#endif}

上面代碼去掉了一些兼容性的代碼,只針對S900平臺mipi dsi的屏來分析。這部分代碼結構還是比較清晰的,分四部分:

第一歩:owl_ctrl_init在ctrl.c文件中,初始化控制器,但還不是具體使用到的控制器,例如dsic控制器用于mipi dsi,這里只是相對于一個所有控制器的管理中心。

owl_panel_init在panel.c文件中,這里是屏終端管理中心。整個這一部分相當于屏和對應控制器的管理中心。

第二歩:owl_de_s900_init,顯示引擎初始化,在de_s900.c文件中。

int owl_de_s900_init(const void *blob){	……	owl_de_s9009.blob = blob;  //數據和節點賦值給s900顯示引擎	owl_de_s9009.node = node;  	owl_de_register(&owl_de_s9009); //注冊s900 顯示引擎	……}這里涉及到顯示引擎的管理中心de.c這個文件,核心是owl_de_register引擎注冊函數:

int owl_de_register(struct owl_de_device *de){	debug("%s/n", __func__);	int tmp, i;	if (de == NULL) {   //注冊的顯示引擎不能為空		error("de is NULL/n");		return -1;	}	if (cur_de != NULL) {  //不能同時注冊多個顯示引擎		error("another de is already registered/n");		return -1;	}	cur_de = de;	cur_de->base = fdtdec_get_addr(cur_de->blob, cur_de->node, "reg");	if (cur_de->base == FDT_ADDR_T_NONE) {		error("Cannot find reg address/n");		return -1;	} //獲取顯示引擎的寄存器地址	debug("%s: base is 0x%llx/n", __func__, cur_de->base);	/* init de gamma state, parse 'gamma_adjust_needed' from DTS */	tmp = fdtdec_get_int(cur_de->blob, cur_de->node, "gamma_adjust_needed", 0);	for (i = 0; i < cur_de->num_paths; i++)		cur_de->paths[i].info.gamma_adjust_needed = tmp; 	/* result check, TODO */	if (cur_de->ops && cur_de->ops->power_on)		cur_de->ops->power_on(cur_de);  // 顯示引擎上電	/* result check, TODO */	if (cur_de->ops && cur_de->ops->init)		cur_de->ops->init(cur_de);  //顯示引擎初始化	return 0;}通過de.c引擎管理中心的調用,實際執行代碼在de_s900.c中(這里就是函數指針的魅力,提升代碼的層次性)。下面是s900 de的結構體:

static struct owl_de_device owl_de_s9009 = {	.hw_id			= DE_HW_ID_S900,	.num_paths		= 2,   //支持兩個通路同時輸出,lcd和	.paths			= de_s900_paths,  	.num_videos		= 2,	.videos			= de_s900_videos,	.ops			= &de_s900_device_ops,};
static struct owl_de_path de_s900_paths[] = {	{		.id			= 0,		.name			= "digit",		.supported_displays	= OWL_DISPLAY_TYPE_HDMI,		.ops			= &de_s900_path_ops,	},	{		.id			= 1,		.name			= "lcd",		.supported_displays	= OWL_DISPLAY_TYPE_LCD					| OWL_DISPLAY_TYPE_DSI					| OWL_DISPLAY_TYPE_EDP					| OWL_DISPLAY_TYPE_DUMMY,		.ops			= &de_s900_path_ops,	},};
static struct owl_de_video de_s900_videos[] = {	{		.id			= 0,		.name			= "video0",		.supported_colors	= ATM9009_SUPPORTED_COLORS,		.ops			= &de_s900_video_ops,	},	{		.id			= 1,		.name			= "video1",		.supported_colors	= ATM9009_SUPPORTED_COLORS,		.ops			= &de_s900_video_ops,	},};
static struct owl_de_device_ops de_s900_device_ops = {	.power_on = de_s900_device_power_on,	.init = de_s900_device_init,	.dump_regs = de_s900_device_dump_regs,};
static struct owl_de_path_ops de_s900_path_ops = {	.enable = de_s900_path_enable,	.apply_info = de_s900_path_apply_info,	.set_go = de_s900_path_set_go,	.set_gamma_table = de_s900_path_set_gamma_table,	.get_gamma_table = de_s900_path_get_gamma_table,	.gamma_enable = de_s900_path_gamma_enable,};
static struct owl_de_video_ops de_s900_video_ops = {	.enable = de_s900_video_enable,	.apply_info = de_s900_video_apply_info,};這段結構體代碼有點長,但是很關鍵,所以全貼出來了。由de管理中心可知,首先是s900 de 上電(這里不分析,不然后面收不回來),然后初始化。
static int de_s900_device_init(struct owl_de_device *de){	uint32_t val;	val = readl(SHARESRAM_CTL); /* share mem */	val |= 0x3;  /* tshi, ebox hdmi use 1 bit, pad edp use 0 bit. */	writel(val, SHARESRAM_CTL);	……}特意把初始化貼出來,是因為發現一個問題 val |= 0x3; 這里初始化的時候,寄存器同時打開了hdmi和mipi/edp,像這種地方要特意找很難找到,所以分析問題的時候,還是要思路清晰,系統的分析,這部分理論上方案公司是不需要修改的。

第三歩:owl_dsic_init(blob);   具體控制器的初始化,在dsic.c文件中。

int owl_dsic_init(const void *blob){	……	dsic->dma_channel = owl_dma_request();	if (!dsic->dma_channel) {		error("%s, owl_dma_request failed!/n", __func__);		return -1;	}//DMA通道申請,傳送長包的時候需要用到	dsic->base = fdtdec_get_addr(blob, node, "reg");	if (dsic->base == FDT_ADDR_T_NONE) {		error("Cannot find dsic reg address/n");		return -1;	}	debug("%s: base is 0x%llx/n", __func__, dsic->base);	ret = dsic_parse_config(blob, node, dsic);	if (ret < 0)		goto err_parse_config;	dsic->ctrl = &owl_dsi_ctrl;	owl_ctrl_set_drvdata(&owl_dsi_ctrl, dsic);	ret = owl_ctrl_register(&owl_dsi_ctrl);	if (ret < 0)		goto err_ctrl_register;	return 0;        ……}關鍵部分為注冊dsi控制器owl_ctrl_register(&owl_dsi_ctrl);

struct owl_display_ctrl_ops owl_dsi_ctrl_ops = {	.enable = owl_dsic_enable,	.disable = owl_dsic_disable,	.power_on = owl_dsic_power_on,	.power_off = owl_dsic_power_off,	.aux_read = owl_dsic_aux_read,	.aux_write = owl_dsic_aux_write,};static struct owl_display_ctrl owl_dsi_ctrl = {	.name = "dsi_ctrl",	.type = OWL_DISPLAY_TYPE_DSI,	.ops = &owl_dsi_ctrl_ops,};結構體是靈魂,這是肯定要貼的??刂破髯院瘮涤只氐絚trl.c控制器管理中心。

這部分沒有特別的,可以注冊4個控制器。目前分析的代碼中由于edp的宏沒關,所有注冊了2個控制器,dsic和edpc。

第四歩:owl_panel_ls055r3sx01_init(blob); 具體屏驅動的初始化。

屏驅動這部分就是大家最熟悉的了,簡單介紹一下:

在init部分注冊屏驅動到panel.c 屏終端管理中心,owl_panel_register(&owl_panel_mipi);

struct owl_panel_ops owl_panel_ls055r3sx01_ops = {	.power_on = panel_ls055r3sx01_power_on,	.power_off = panel_ls055r3sx01_power_off,	.enable = panel_ls055r3sx01_enable,	.disable = panel_ls055r3sx01_disable,};static struct owl_panel owl_panel_mipi = {	.desc = {		.name = "mipi_panel",		.type = OWL_DISPLAY_TYPE_DSI,		.ops = &owl_panel_ls055r3sx01_ops,	},};到這里,owl_dss_init顯示子系統的初始化函數分析完畢!通過分析這個過程,把相關的東西都有涉及進來了。后面的分析,也是圍繞這些東西,主要就是疏通整個工作流程了。

第二部分:owl_fb_init(&g_owl_fb),framebuffer的初始化。

static int owl_fb_init(struct owl_fb *fb){	debug("%s/n", __func__);	/*	 * PRimary panel	 */	fb->panel = owl_panel_get_primary_panel();	if (fb->panel == NULL) {		error("no primary panel/n");		return -ENODEV;	} // 首先獲取主屏,在dts中配置	debug("%s: primary panel type is %d/n", __func__,	      owl_panel_get_type(fb->panel));	fb->path = owl_de_path_get_by_type(owl_panel_get_type(fb->panel));	if (fb->path == NULL) {		error("can not get de path for primary panel/n");		return -EINVAL;	}  //根據panel類型(在屏驅動獲?。﹣矶@示引擎的通道	fb->video = owl_de_video_get_by_id(0);	if (fb->video == NULL) {		error("can not get de video for primary panel/n");		return -EINVAL;	}// 默認0為主通道,獲取顯示引擎的video	__owl_fb_init(fb, true);	/*	 * second panel	 */	fb->second_panel = owl_panel_get_second_panel();	fb->second_path		= owl_de_path_get_by_type(owl_panel_get_type(fb->second_panel));#if defined(CONFIG_VIDEO_OWL_DE_S700) && !defined(CONFIG_VIDEO_OWL_DE_S700_OTT)	fb->second_video = owl_de_video_get_by_id(3);#else	fb->second_video = owl_de_video_get_by_id(1);#endif	if (fb->second_panel != NULL && fb->second_path != NULL &&	    fb->second_video != NULL) {		__owl_fb_init(fb, false);	} else {		debug("no valid second display device/n");		fb->second_panel = NULL;	}	/*	 * fill to graphic_device	 */	owl_panel_get_draw_size(fb->panel, (int *)&fb->gd.winSizeX,				(int *)&fb->gd.winSizeY);	fb->gd.gdfIndex = owl_color_mode_to_gdf_mode(OWLFB_COLOR_MODE);	fb->gd.gdfBytesPP = owl_dss_get_color_bpp(OWLFB_COLOR_MODE) / 8;	fb->gd.frameAdrs = OWLFB_BUF_ADDR;	debug("%s: pGD info---/n", __func__);	debug("%dx%d, gdfIndex %d, gdfBytesPP %d, frameAdrs %x/n",	      fb->gd.winSizeX, fb->gd.winSizeY, fb->gd.gdfIndex,	      fb->gd.gdfBytesPP, fb->gd.frameAdrs);	return 0;}

static void __owl_fb_init(struct owl_fb *fb, bool is_primary){	struct owl_panel *panel;	struct owl_de_path *path;	struct owl_de_video *video;	struct owl_de_path_info p_info;	struct owl_de_video_info v_info;	debug("%s: is_primary %d/n", __func__, is_primary);	if (is_primary) {		panel = fb->panel;		path = fb->path;		video = fb->video;	} else {		panel = fb->second_panel;		path = fb->second_path;		video = fb->second_video;	}	owl_de_video_set_path(video, path); //根據framebuffer的path來設置DE的video path	/*	 * init path info	 */	owl_de_path_get_info(path, &p_info);  //初始化通道信息	p_info.type = owl_panel_get_type(panel); //獲取屏幕類型	owl_panel_get_resolution(panel, (int *)&p_info.width,				 (int *)&p_info.height);  //獲取屏幕的分辨率	p_info.vmode = owl_panel_get_vmode(panel);	switch (owl_panel_get_bpp(panel)) {	case 16:		p_info.dither_mode = DITHER_24_TO_16;		break;	case 18:		p_info.dither_mode = DITHER_24_TO_18;		break;	default:		p_info.dither_mode = DITHER_DISABLE;		break;	}	owl_panel_get_gamma(panel, &p_info.gamma_r_val, &p_info.gamma_g_val,				&p_info.gamma_b_val);	owl_de_path_set_info(path, &p_info); //設置DE通道信息	/*	 * init video info	 */	owl_de_video_get_info(video, &v_info);  //初始化video信息	v_info.color_mode = OWLFB_COLOR_MODE;	v_info.blending = OWL_BLENDING_NONE;	v_info.alpha = 0xff;	v_info.xoff = 0;	v_info.yoff = 0;	/* input size is equal to primary panel's draw size */	owl_panel_get_draw_size(fb->panel, (int *)&v_info.width,				(int *)&v_info.height);	v_info.pos_x = 0;	v_info.pos_y = 0;	/* output size is equal to panel's resolution */	owl_panel_get_resolution(panel, (int *)&v_info.out_width,				 (int *)&v_info.out_height);	v_info.addr[0] = OWLFB_BUF_ADDR;	v_info.offset[0] = 0;	v_info.pitch[0] = (owl_dss_get_color_bpp(v_info.color_mode) / 8)			* v_info.width;	owl_de_video_set_info(video, &v_info);  //設置video信息}從framebuffer的init過程,我們可以清楚的了解到顯示子系統的一個工作流程:

framebuffer——>de——>path——>video——>panel

細節太多繁雜,不過大部分修改的內容可能都在其中,在這篇文章不發散,不好發散,只能針對問題點分析,我們這篇文章的主要目的是搞清楚流程,然后學習它的設計思路。

第三部分:顯示部分owl_fb_display_on(&g_owl_fb);

static void owl_fb_display_on(struct owl_fb *fb){	debug("%s/n", __func__);	debug("%s(primay panel)/n", __func__);	owl_panel_enable(fb->panel);	owl_de_video_enable(fb->video, true);	owl_de_path_enable(fb->path, true);	owl_de_path_set_go(fb->path);	if (fb->second_panel != NULL) {		debug("%s(secondary panel)/n", __func__);		owl_panel_enable(fb->second_panel);		owl_de_video_enable(fb->second_video, true);		owl_de_path_enable(fb->second_path, true);		owl_de_path_set_go(fb->second_path);	}}主要也就是使能panel video path,使能的順序剛好和數據流的順序相反。這里不知道順序有沒有影響,沒驗證過。

OVER,總的來說,這種設計符合我的思維邏輯,太高級了我看不懂,哈哈。

MTK的確實復雜些,看得沒這么順利,但是MTK的用得順手,這可能就是差距吧。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美午夜无遮挡| 91色视频在线观看| 亚洲国产成人精品一区二区| 久久夜色精品国产| 亚洲高清一二三区| 精品久久久久久亚洲国产300| 亚洲中国色老太| 国产成人avxxxxx在线看| 国产亚洲精品成人av久久ww| xxxx欧美18另类的高清| 亚洲精品久久久久久久久| 久久久久久久久久久人体| 亚州欧美日韩中文视频| 人人爽久久涩噜噜噜网站| 欧美在线观看一区二区三区| 91精品国产综合久久香蕉922| 国产精品美女午夜av| 亚洲国产日韩欧美在线99| 九九热最新视频//这里只有精品| 最近2019中文字幕第三页视频| 亚洲精品国产成人| 国产美女高潮久久白浆| 久99九色视频在线观看| 国产精品久久久久久久久久免费| 欧美视频在线观看免费网址| 精品香蕉在线观看视频一| 国产成人综合精品在线| 亚洲伊人一本大道中文字幕| 色爱av美腿丝袜综合粉嫩av| 美女国内精品自产拍在线播放| 91亚洲精品在线观看| 欧美电影在线观看网站| 激情亚洲一区二区三区四区| 欧美日韩国产影院| 亚洲综合在线中文字幕| 国产精品美女在线观看| 中文字幕欧美专区| 最近的2019中文字幕免费一页| 一区二区三区四区在线观看视频| 欧美亚洲视频一区二区| 欧美极品第一页| 91情侣偷在线精品国产| 一区二区三区视频免费在线观看| 亚洲男女自偷自拍图片另类| 日韩视频―中文字幕| 亚洲性猛交xxxxwww| 国产成人精彩在线视频九色| 亚洲性夜色噜噜噜7777| 久久这里只有精品99| 一区二区三区久久精品| 国产精品视频导航| 最近2019年日本中文免费字幕| 色无极影院亚洲| 欧美成人免费一级人片100| 日韩成人xxxx| 欧美激情视频一区二区三区不卡| 久久久久免费视频| 国产精品夜色7777狼人| www欧美日韩| 91国产美女视频| www国产精品com| 97香蕉久久夜色精品国产| 免费不卡在线观看av| 人人做人人澡人人爽欧美| 亚洲第一视频网| 国内偷自视频区视频综合| 91av视频在线观看| 成人网在线免费观看| 亚洲欧美国产精品| 亚洲精品国产精品国自产在线| 中文精品99久久国产香蕉| 欧美精品电影在线| 国产在线精品成人一区二区三区| 亚洲国产精品va在线看黑人| 日韩视频免费在线观看| 国产成人一区三区| 免费av一区二区| 亚洲国产精品久久久久秋霞蜜臀| 亚洲影院色无极综合| 国产成人精品一区二区在线| 日韩精品中文字幕视频在线| 日韩一区二区三区xxxx| 久久伊人精品一区二区三区| 最新日韩中文字幕| 色噜噜国产精品视频一区二区| 日韩在线www| 国产乱人伦真实精品视频| 91在线观看免费高清完整版在线观看| 亚洲视频在线观看| 国产成人avxxxxx在线看| 久久综合88中文色鬼| 国产黑人绿帽在线第一区| 欧美精品情趣视频| 久久99热精品| 91国产视频在线播放| 亚洲人成伊人成综合网久久久| 国产精品高潮呻吟久久av无限| 亚洲综合色av| 欧美视频一区二区三区…| 亚洲欧洲黄色网| 日韩精品免费在线播放| 欧美视频在线观看免费| 性欧美在线看片a免费观看| 亚洲精品久久久久| 日韩精品免费看| 色悠久久久久综合先锋影音下载| 欧美亚洲第一页| 26uuu另类亚洲欧美日本老年| 久久99热这里只有精品国产| 一二美女精品欧洲| 日韩激情片免费| 日韩av电影在线免费播放| 久久这里有精品| 欧美黑人视频一区| 国产日韩中文字幕| 国产精品视频导航| 亚洲丝袜一区在线| 欧美日韩中国免费专区在线看| 日韩视频精品在线| 亚洲人成伊人成综合网久久久| 欧美日韩国产一中文字不卡| 日韩中文字幕在线免费观看| 亚洲国内精品视频| 国产精品色午夜在线观看| www高清在线视频日韩欧美| 91牛牛免费视频| 91免费看片网站| 日韩精品在线观看视频| 欧美日韩国产中字| 国产精品免费一区豆花| 精品国产一区二区三区久久狼5月| 国产欧美一区二区三区四区| 亚洲级视频在线观看免费1级| 欧美孕妇与黑人孕交| 亚洲国产天堂久久综合网| 亚洲一区二区三区成人在线视频精品| 国产精品嫩草影院久久久| 91久久综合亚洲鲁鲁五月天| 国内伊人久久久久久网站视频| 日本国产欧美一区二区三区| 色噜噜狠狠狠综合曰曰曰88av| 成人h视频在线| 国产欧美日韩视频| 日韩免费视频在线观看| 91精品国产乱码久久久久久久久| 在线观看视频亚洲| 亚洲人成网站999久久久综合| 国产999视频| 中文字幕亚洲字幕| 日韩欧美国产视频| 色婷婷综合成人| 久久久噜噜噜久噜久久| 午夜精品久久久99热福利| 一区二区三区精品99久久| 欧美另类69精品久久久久9999| 91成品人片a无限观看| 成人做爽爽免费视频| 91夜夜未满十八勿入爽爽影院| 97人人模人人爽人人喊中文字| 国产综合视频在线观看| 亚洲欧美另类在线观看| 久久久国产91| 欧美大片在线免费观看| 中文字幕日韩av综合精品|