1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近,RK 的显示屏是在 dts 里面的一个屏幕相关的配置,而 RK 的显示屏是一个屏幕相关的配置,需要直接写一个 Edp 的屏幕显示。获取来,从中获取任何相关配置信息,然后从屏幕上掉下来。
1. 部分修改 Edp EDID 在调试阶段,可以在打印驱动程序/video/fbmon.c 直接将DEBUG打开,然后在内核里面输出EDID1信息。1. 修改获取dc驱动的屏幕是Edp类型的就E屏的最佳选择3从EDID中提取出来,然后rk_从中的屏幕中删除屏幕,然后配置液晶屏。 diff --git a/common/cmd_bootrk.c b/common/cmd_bootrk.c index 87b1a85..f156977 100755 --- a/common/cmd_bootrk.c +++ b/common/cmd_bootrk.c @@ -465,6 +465,11 @@ static void rk_commandline_setenv(const char *boot_name, rk_boot_img_hdr *hdr, b } #endif /* CONFIG_RK_FB_DDREND */ +#if defined(CONFIG_RK_EDP_EDID) + snprintf(command_line, sizeof(command_line), + "%s edp.edid=%d", command_line, 1); +#endif + snprintf(command_line, sizeof(command_line), "%s loader.timestamp=%s", command_line, U_BOOT_TIMESTAMP); diff --git a/drivers/video/rk32_dp.c b/drivers/video/rk32_dp.c index 49c0df6..d9b241c 100755 --- a/drivers/video/rk32_dp.c +++ b/drivers/video/rk32_dp.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include "edid.h" #include "rk32_dp.h" #if defined(CONFIG_OF) @@ -21,6 +23,8 @@ #include #endif +DECLARE_GLOBAL_DATA_PTR; + //#define EDP_BIST_MODE #define RUN_IN_UBOOT @@ -137,10 +141,610 @@ static int rk32_edp_detect_hpd(struct rk32_edp *edp) return 0; } +#endif + +const struct fb_videomode vesa_modes[] = { + /* 0 640x350-85 VESA */ + { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3, + FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1 640x400-85 VESA */ + { NULL, 85, 640, 400, 31746, 96, 32, 41, 01, 64, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 2 720x400-85 VESA */ + { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 3 640x480-60 VESA */ + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 4 640x480-72 VESA */ + { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 5 640x480-75 VESA */ + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 6 640x480-85 VESA */ + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 7 800x600-56 VESA */ + { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 8 800x600-60 VESA */ + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 9 800x600-72 VESA */ + { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 10 800x600-75 VESA */ + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 11 800x600-85 VESA */ + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 12 1024x768i-43 VESA */ + { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_INTERLACED, FB_MODE_IS_VESA }, + /* 13 1024x768-60 VESA */ + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 14 1024x768-70 VESA */ + { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 15 1024x768-75 VESA */ + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 16 1024x768-85 VESA */ + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 17 1152x864-75 VESA */ + { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 18 1280x960-60 VESA */ + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 19 1280x960-85 VESA */ + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 20 1280x1024-60 VESA */ + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 21 1280x1024-75 VESA */ + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 22 1280x1024-85 VESA */ + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 23 1600x1200-60 VESA */ + { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 24 1600x1200-65 VESA */ + { NULL, 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 25 1600x1200-70 VESA */ + { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 26 1600x1200-75 VESA */ + { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 27 1600x1200-85 VESA */ + { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 28 1792x1344-60 VESA */ + { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 29 1792x1344-75 VESA */ + { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 30 1856x1392-60 VESA */ + { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 31 1856x1392-75 VESA */ + { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 32 1920x1440-60 VESA */ + { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 33 1920x1440-75 VESA */ + { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, +}; + +#define EDP_EDID_LENGTH 128 +static int edid_checksum(unsigned char *edid) +{ + unsigned char csum = 0, all_null = 0; + int i, err = 0; + + for (i = 0; i < EDP_EDID_LENGTH; i++) { + csum += edid; + all_null |= edid; + } + + if (csum == 0x00 && all_null) { + /* checksum passed, everything's good */ + err = 1; + } + + return err; +} + +static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs) +{ + specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@'; + specs->manufacturer[1] = ((block[0] & 0x03) << 3) + + ((block[1] & 0xe0) >> 5) + '@'; + specs->manufacturer[2] = (block[1] & 0x1f) + '@'; + specs->manufacturer[3] = 0; + specs->model = block[2] + (block[3] << 8); + specs->serial = block[4] + (block[5] << 8) + + (block[6] << 16) + (block[7] << 24); + specs->year = block[9] + 1990; + specs->week = block[8]; + debug(" Manufacturer: %sn", specs->manufacturer); + debug(" Model: %xn", specs->model); + debug(" Serial#: %un", specs->serial); + debug(" Year: %u Week %un", specs->year, specs->week); +} + +static void calc_mode_timings(int xres, int yres, int refresh, + struct fb_videomode *mode) +{ + struct fb_var_screeninfo *var; + + var = malloc(sizeof(struct fb_var_screeninfo)); + + if (var) { + var->xres = xres; + var->yres = yres; + //fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, + // refresh, var, NULL); + mode->xres = xres; + mode->yres = yres; + mode->pixclock = var->pixclock; + mode->refresh = refresh; + mode->left_margin = var->left_margin; + mode->right_margin = var->right_margin; + mode->upper_margin = var->upper_margin; + mode->lower_margin = var->lower_margin; + mode->hsync_len = var->hsync_len; + mode->vsync_len = var->vsync_len; + mode->vmode = 0; + mode->sync = 0; + free(var); + } +} + |
|
|
|
+static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
+{ + int num = 0; + unsigned char c; + + c = block[0]; + if (c&0x80) { + calc_mode_timings(720, 400, 70, &mode[num]); + mode[num++].flag = FB_MODE_IS_CALCULATED; + debug(" 720x400@70Hzn"); + } + if (c&0x40) { + calc_mode_timings(720, 400, 88, &mode[num]); + mode[num++].flag = FB_MODE_IS_CALCULATED; + debug(" 720x400@88Hzn"); + } + if (c&0x20) { + mode[num++] = vesa_modes[3]; + debug(" 640x480@60Hzn"); + } + if (c&0x10) { + calc_mode_timings(640, 480, 67, &mode[num]); + mode[num++].flag = FB_MODE_IS_CALCULATED; + debug(" 640x480@67Hzn"); + } + if (c&0x08) { + mode[num++] = vesa_modes[4]; + debug(" 640x480@72Hzn"); + } + if (c&0x04) { + mode[num++] = vesa_modes[5]; + debug(" 640x480@75Hzn"); + } + if (c&0x02) { + mode[num++] = vesa_modes[7]; + debug(" 800x600@56Hzn"); + } + if (c&0x01) { + mode[num++] = vesa_modes[8]; + debug(" 800x600@60Hzn"); + } + + c = block[1]; + if (c&0x80) { + mode[num++] = vesa_modes[9]; + debug(" 800x600@72Hzn"); + } + if (c&0x40) { + mode[num++] = vesa_modes[10]; + debug(" 800x600@75Hzn"); + } + if (c&0x20) { + calc_mode_timings(832, 624, 75, &mode[num]); + mode[num++].flag = FB_MODE_IS_CALCULATED; + debug(" 832x624@75Hzn"); + } + if (c&0x10) { + mode[num++] = vesa_modes[12]; + debug(" 1024x768@87Hz Interlacedn"); + } + if (c&0x08) { + mode[num++] = vesa_modes[13]; + debug(" 1024x768@60Hzn"); + } + if (c&0x04) { + mode[num++] = vesa_modes[14]; + debug(" 1024x768@70Hzn"); + } + if (c&0x02) { + mode[num++] = vesa_modes[15]; + debug(" 1024x768@75Hzn"); + } + if (c&0x01) { + mode[num++] = vesa_modes[21]; + debug(" 1280x1024@75Hzn"); + } + c = block[2]; + if (c&0x80) { + mode[num++] = vesa_modes[17]; + debug(" 1152x870@75Hzn"); + } + debug(" Manufacturer's mask: %xn",c&0x7F); + return num; +} + +#define VESA_MODEDB_SIZE 34 + +static int get_std_timing(unsigned char *block, struct fb_videomode *mode, + int ver, int rev) +{ + int xres, yres = 0, refresh, ratio, i; + + xres = (block[0] + 31) * 8; + if (xres <= 256) + return 0; + + ratio = (block[1] & 0xc0) >> 6; + switch (ratio) { + case 0: + /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */ + if (ver < 1 || (ver == 1 && rev < 3)) + yres = xres; + else + yres = (xres * 10)/16; + break; + case 1: + yres = (xres * 3)/4; + break; + case 2: + yres = (xres * 4)/5; + break; + case 3: + yres = (xres * 9)/16; + break; + } + refresh = (block[1] & 0x3f) + 60; + + printf(" %dx%d@%dHzn", xres, yres, refresh); + for (i = 0; i < VESA_MODEDB_SIZE; i++) { + if (vesa_modes.xres == xres && + vesa_modes.yres == yres && + vesa_modes.refresh == refresh) { + *mode = vesa_modes; + mode->flag |= FB_MODE_IS_STANDARD; + return 1; + } + } + calc_mode_timings(xres, yres, refresh, mode); + return 1; +} + +static int get_dst_timing(unsigned char *block, + struct fb_videomode *mode, int ver, int rev) +{ + int j, num = 0; + + for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) + num += get_std_timing(block, &mode[num], ver, rev); + + return num; +} + +static void get_detailed_timing(unsigned char *block, + struct fb_videomode *mode) +{ + mode->xres = H_ACTIVE; + mode->yres = V_ACTIVE; + mode->pixclock = PIXEL_CLOCK; + mode->pixclock /= 1000; + mode->pixclock = KHZ2PICOS(mode->pixclock); + mode->right_margin = H_SYNC_OFFSET; + mode->left_margin = (H_ACTIVE + H_BLANKING) - + (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); + mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - + V_SYNC_WIDTH; + mode->lower_margin = V_SYNC_OFFSET; + mode->hsync_len = H_SYNC_WIDTH; + mode->vsync_len = V_SYNC_WIDTH; + if (HSYNC_POSITIVE) + mode->sync |= FB_SYNC_HOR_HIGH_ACT; + if (VSYNC_POSITIVE) + mode->sync |= FB_SYNC_VERT_HIGH_ACT; + mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) * + (V_ACTIVE + V_BLANKING)); + if (INTERLACED) { + mode->yres *= 2; + mode->upper_margin *= 2; + mode->lower_margin *= 2; + mode->vsync_len *= 2; + mode->vmode |= FB_VMODE_INTERLACED; + } + mode->flag = FB_MODE_IS_DETAILED; + + debug(" %d MHz ", PIXEL_CLOCK/1000000); + debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET, + H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING); + debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET, + V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING); + debug("%sHSync %sVSyncnn", (HSYNC_POSITIVE) ? "+" : "-", + (VSYNC_POSITIVE) ? "+" : "-"); +} + |
|
|
|
+static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{ + struct fb_videomode *mode, *m; + unsigned char *block; + int num = 0, i, first = 1; + int ver, rev; + + ver = edid[EDID_STRUCT_VERSION]; + rev = edid[EDID_STRUCT_REVISION]; + + mode = malloc(50 * sizeof(struct fb_videomode)); + if (mode == NULL) + return NULL; + + if (edid == NULL || !edid_checksum(edid)) { + free(mode); + return NULL; + } + + *dbsize = 0; + + debug(" Detailed Timingsn"); + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { + if (!(block[0] == 0x00 && block[1] == 0x00)) { + get_detailed_timing(block, &mode[num]); + if (first) { + mode[num].flag |= FB_MODE_IS_FIRST; + first = 0; + } + num++; + } + } + + debug(" Supported VESA Modesn"); + block = edid + ESTABLISHED_TIMING_1; + num += get_est_timing(block, &mode[num]); + + debug(" Standard Timingsn"); + block = edid + STD_TIMING_DESCRIPTIONS_START; + for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) + num += get_std_timing(block, &mode[num], ver, rev); + + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { + if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) + num += get_dst_timing(block + 5, &mode[num], ver, rev); + } + + /* Yikes, EDID data is totally useless */ + if (!num) { + free(mode); + return NULL; + } + + *dbsize = num; + m = malloc(num * sizeof(struct fb_videomode)); + if (!m) + return mode; + memmove(m, mode, num * sizeof(struct fb_videomode)); + free(mode); + return m; +} + +static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs) +{ + unsigned char c, *block; + + block = edid + EDID_STRUCT_DISPLAY; + + c = block[0] & 0x80; + specs->input = 0; + if (c) { + specs->input |= FB_DISP_DDI; + debug(" Digital Display Input"); + } else { + debug(" Analog Display Input: Input Voltage - "); + switch ((block[0] & 0x60) >> 5) { + case 0: + debug("0.700V/0.300V"); + specs->input |= FB_DISP_ANA_700_300; + break; + case 1: + debug("0.714V/0.286V"); + specs->input |= FB_DISP_ANA_714_286; + break; + case 2: + debug("1.000V/0.400V"); + specs->input |= FB_DISP_ANA_1000_400; + break; + case 3: + debug("0.700V/0.000V"); + specs->input |= FB_DISP_ANA_700_000; + break; + } + } + debug("n Sync: "); + c = block[0] & 0x10; + if (c) + debug(" Configurable signal leveln"); + c = block[0] & 0x0f; + specs->signal = 0; + if (c & 0x10) { + debug("Blank to Blank "); + specs->signal |= FB_SIGNAL_BLANK_BLANK; + } + if (c & 0x08) { + debug("Separate "); + specs->signal |= FB_SIGNAL_SEPARATE; + } + if (c & 0x04) { + debug("Composite "); + specs->signal |= FB_SIGNAL_COMPOSITE; + } + if (c & 0x02) { + debug("Sync on Green "); + specs->signal |= FB_SIGNAL_SYNC_ON_GREEN; + } + if (c & 0x01) { + debug("Serration on "); + specs->signal |= FB_SIGNAL_SERRATION_ON; + } + debug("n"); + specs->max_x = block[1]; + specs->max_y = block[2]; + debug(" Max H-size in cm: "); + if (specs->max_x) + debug("%dn", specs->max_x); + else + debug("variablen"); + debug(" Max V-size in cm: "); + if (specs->max_y) + debug("%dn", specs->max_y); + else + debug("variablen"); + + c = block[3]; + specs->gamma = c+100; + debug(" Gamma: "); + debug("%d.%dn", specs->gamma/100, specs->gamma % 100); + + switch ((block[4] & 0x18) >> 3) { + case 0: + debug(" Monochrome/Grayscalen"); + specs->input |= FB_DISP_MONO; + break; + case 1: + debug(" RGB Color Displayn"); + specs->input |= FB_DISP_RGB; + break; + case 2: + debug(" Non-RGB Multicolor Displayn"); + specs->input |= FB_DISP_MULTI; + break; + default: + debug(" Unknownn"); + specs->input |= FB_DISP_UNKNOWN; + break; + } + + specs->misc = 0; + c = block[4] & 0x7; + if (c & 0x04) { + debug(" Default color format is primaryn"); + specs->misc |= FB_MISC_PRIM_COLOR; + } + if (c & 0x02) { + debug(" First DETAILED Timing is preferredn"); + specs->misc |= FB_MISC_1ST_DETAIL; + } + if (c & 0x01) { + debug(" Display is GTF capablen"); + specs->gtf = 1; + } +} + +void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) +{ + int i, found = 0; + + if (edid == NULL) + return; + + if (!(edid_checksum(edid))) + return; + + memset(specs, 0, sizeof(struct fb_monspecs)); + + specs->version = edid[EDID_STRUCT_VERSION]; + specs->revision = edid[EDID_STRUCT_REVISION]; + + debug("EDID Version %d.%dn", (int) specs->version, + (int) specs->revision); + + parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs); + + get_monspecs(edid, specs); + + specs->modedb = fb_create_modedb(edid, (int *)&specs->modedb_len); + + /* + * Workaround for buggy EDIDs that sets that the first + * detailed timing is preferred but has not detailed + * timing specified + */ + for (i = 0; i < specs->modedb_len; i++) { + if (specs->modedb.flag & FB_MODE_IS_DETAILED) { + found = 1; + break; + } + } + + if (!found) + specs->misc &= ~FB_MISC_1ST_DETAIL; + +} + +static unsigned char inline rk32_edp_calc_edid_check_sum(unsigned char *edid_data) +{ + int i; + unsigned char sum = 0; + + for (i = 0; i < EDP_EDID_LENGTH; i++) + sum = sum + edid_data; + + return sum; +} static int rk32_edp_read_edid(struct rk32_edp *edp) { - unsigned char edid[EDID_LENGTH * 2]; + unsigned char edid[EDP_EDID_LENGTH * 2]; unsigned int extend_block = 0; unsigned char sum; unsigned char test_vector; @@ -165,25 +769,25 @@ static int |
|
|
|
rk32_edp_read_edid(struct rk32_edp *edp)
/* Read EDID data */ retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDID_HEADER, - EDID_LENGTH, &edid[EDID_HEADER]); + EDP_EDID_LENGTH, &edid[EDID_HEADER]); if (retval != 0) { debug( "EDID Read failed!n"); return -EIO; } - sum = edp_calc_edid_check_sum(edid); + sum = rk32_edp_calc_edid_check_sum(edid); if (sum != 0) { debug( "EDID bad checksum!n"); return 0; } /* Read additional EDID data */ - retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDID_LENGTH, - EDID_LENGTH, &edid[EDID_LENGTH]); + retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDP_EDID_LENGTH, + EDP_EDID_LENGTH, &edid[EDP_EDID_LENGTH]); if (retval != 0) { debug( "EDID Read failed!n"); return -EIO; } - sum = edp_calc_edid_check_sum(&edid[EDID_LENGTH]); + sum = rk32_edp_calc_edid_check_sum(&edid[EDP_EDID_LENGTH]); if (sum != 0) { debug( "EDID bad checksum!n"); return 0; @@ -199,7 +803,7 @@ static int rk32_edp_read_edid(struct rk32_edp *edp) if (test_vector & DPCD_TEST_EDID_READ) { retval = rk32_edp_write_byte_to_dpcd(edp, DPCD_TEST_EDID_CHECKSUM, - edid[EDID_LENGTH + EDID_CHECKSUM]); + edid[EDP_EDID_LENGTH + EDID_CHECKSUM]); if (retval < 0) { debug( "DPCD EDID Write failed!n"); return retval; @@ -217,12 +821,12 @@ static int rk32_edp_read_edid(struct rk32_edp *edp) /* Read EDID data */ retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDID_HEADER, - EDID_LENGTH, &edid[EDID_HEADER]); + EDP_EDID_LENGTH, &edid[EDID_HEADER]); if (retval != 0) { debug( "EDID Read failed!n"); return -EIO; } - sum = edp_calc_edid_check_sum(edid); + sum = rk32_edp_calc_edid_check_sum(edid); if (sum != 0) { debug( "EDID bad checksum!n"); return 0; @@ -253,7 +857,7 @@ static int rk32_edp_read_edid(struct rk32_edp *edp) } } fb_edid_to_monspecs(edid, &edp->specs); - printf( "EDID Read success!n"); + debug( "EDID Read success!n"); return 0; } @@ -269,7 +873,7 @@ static int rk32_edp_handle_edid(struct rk32_edp *edp) return retval; for (i=0 ;i < 12; i++) - printf( "%d:>>0x%02xn", i, buf); + debug( "%d:>>0x%02xn", i, buf); /* Read EDID */ for (i = 0; i < 3; i++) { retval = rk32_edp_read_edid(edp); @@ -308,6 +912,7 @@ static int rk32_edp_enable_rx_to_enhanced_mode(struct rk32_edp *edp, return retval; } +#ifndef RUN_IN_UBOOT void rk32_edp_rx_control(struct rk32_edp *edp, bool enable) { /*rk32_edp_write_byte_to_dpcd(edp, DPCD_ADDR_USER_DEFINED1,0); @@ -1065,7 +1670,6 @@ static int rk32_edp_config_video(struct rk32_edp *edp, return retval; } -#ifndef RUN_IN_UBOOT static int rk32_edp_enable_scramble(struct rk32_edp *edp, bool enable) { u8 data; @@ -1103,7 +1707,60 @@ static int rk32_edp_enable_scramble(struct rk32_edp *edp, bool enable) return 0; } -#endif /* #ifndef RUN_IN_UBOOT */ + +static struct fb_videomode *rk32_edp_get_preferred_mode(struct fb_monspecs *spec) +{ + int i; + + if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL)) + return NULL; + + for (i = 0; i < spec->modedb_len; i++) { + if (spec->modedb.flag & FB_MODE_IS_FIRST && + spec->modedb.flag & FB_MODE_IS_DETAILED) + return &spec->modedb; + } + + return NULL; +} + +int rk32_edp_get_screen_info_from_edid(struct rk_screen *screen) +{ + struct rk32_edp *edp = &rk32_edp; + + int ret = rk32_edp_handle_edid(edp); + if (ret) { + printf("unable to handle edidn"); + return -1; + } + + printf("EDID Version %d.%dn", (int) edp->specs.version, (int) edp->specs.revision); + printf(" Manufacturer: %s, Model: %xn", edp->specs.manufacturer, edp->specs.model); + printf(" Year: %u Week %un", edp->specs.year, edp->specs.week); + + struct fb_videomode *preferred_mode = rk32_edp_get_preferred_mode(&edp->specs); + + if(preferred_mode!=NULL){ + printf(" Preferred Timing: %ld MHzn", PICOS2KHZ(preferred_mode->pixclock)/1000); + + screen->mode.xres = preferred_mode->xres; + screen->mode.yres = preferred_mode->yres; + screen->mode.pixclock = PICOS2KHZ(preferred_mode->pixclock)*1000; + screen->mode.left_margin = preferred_mode->left_margin; + screen->mode.right_margin = preferred_mode->right_margin; + screen->mode.upper_margin = preferred_mode->upper_margin; + screen->mode.lower_margin = preferred_mode->lower_margin; + screen->mode.hsync_len = preferred_mode->hsync_len; + screen->mode.vsync_len = preferred_mode->vsync_len; + screen->mode.sync = preferred_mode->sync; + + screen->width = edp->specs.max_x*10; + screen->height= edp->specs.max_y*10; + return 0; + } + printf("EDID preferred mode not found!n"); + return -1; +} int rk32_edp_enable(vidinfo_t *vid) { @@ -1124,7 +1781,28 @@ int rk32_edp_enable(vidinfo_t *vid) rk32_edp_clk_enable(edp); rk32_edp_pre_init(); rk32_edp_init_edp(edp); - + + if (gd->fdt_blob) { + int node = fdt_path_offset(gd->fdt_blob, "/edp"); + if(fdtdec_get_bool(gd->fdt_blob, node, "scramble-enable")){ + debug("edp scramble enable.n"); + ret = rk32_edp_enable_scramble(edp, true); + if (ret) { + printf("unable to set scramblen"); + } + } + + if(fdtdec_get_bool(gd->fdt_blob, node, "enhanced-mode")){ + debug("edp enhanced mode.n"); + + ret = rk32_edp_enable_rx_to_enhanced_mode(edp, true); + if (ret) { + printf("unable to set rx enhanced moden"); + } + rk32_edp_enable_enhanced_mode(edp, true); + } + } + ret = rk32_edp_set_link_train(edp); if (ret) printf( "link train failed!n"); diff --git a/drivers/video/rk32_dp.h b/drivers/video/rk32_dp.h index 0ff0137..ea0de91 100755 --- a/drivers/video/rk32_dp.h +++ b/drivers/video/rk32_dp.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "dpcd_edid.h" #define DP_VERSION 0x10 @@ -527,6 +528,7 @@ struct rk32_edp { vidinfo_t * vid; struct link_train link_train; struct video_info video_info; + struct fb_monspecs specs; }; diff --git a/drivers/video/rk3368_lcdc.c b/drivers/video/rk3368_lcdc.c index 9bf6752..e105c96 100755 --- a/drivers/video/rk3368_lcdc.c +++ b/drivers/video/rk3368_lcdc.c @@ -5,6 +5,7 @@ */ #include "rk3368_lcdc.h" + /*******************register definition**********************/ struct lcdc_device rk33_lcdc; extern struct rockchip_fb rockchip_fb; @@ -13,6 +14,7 @@ int lcdEnstatus=-1; #define EARLY_TIME 500 /*us*/ extern int rk31xx_lvds_enable(vidinfo_t * vid); extern int rk32_edp_enable(vidinfo_t * vid); +extern int rk32_edp_get_screen_info_from_edid(struct rk_screen *screen); extern int rk32_mipi_enable(vidinfo_t * vid); extern int rk32_dsi_enable(void); extern int rk32_dsi_disable(void); @@ -998,6 +1000,36 @@ static void rk3368_lcdc_bcsh_path_sel(struct lcdc_device *lcdc_dev) } } +void rk3368_lcdc_get_vidinfo_from_edid(vidinfo_t *vid) +{ + rk32_edp_enable(vid); + + struct rk_screen screen; + + if(rk32_edp_get_screen_info_from_edid(&screen)!=0){ + return; + } + + vid->vl_freq = screen.mode.pixclock; + + vid->vl_hspw = screen.mode.hsync_len; + vid->vl_hbpd = screen.mode.left_margin; + vid->vl_col = screen.mode.xres; + vid->vl_hfpd = screen.mode.right_margin; + + vid->vl_vspw = screen.mode.vsync_len; + vid->vl_vbpd = screen.mode.upper_margin; + vid->vl_row = screen.mode.yres; + vid->vl_vfpd = screen.mode.lower_margin; + + vid->vl_hsp = screen.mode.sync & FB_SYNC_HOR_HIGH_ACT ? 1 : 0; + vid->vl_vsp = screen.mode.sync & FB_SYNC_VERT_HIGH_ACT ? 1 : 0; + + vid->vl_width = screen.width; + vid->vl_height= screen.height; +} + + |
|
|
|
int rk_lcdc_load_screen(vidinfo_t *vid)
{ struct lcdc_device *lcdc_dev = &rk33_lcdc; diff --git a/drivers/video/rockchip_fb.c b/drivers/video/rockchip_fb.c index 6e35e10..e846d42 100755 --- a/drivers/video/rockchip_fb.c +++ b/drivers/video/rockchip_fb.c @@ -487,6 +487,18 @@ void lcd_ctrl_init(void *lcdbase) panel_info.logo_rgb_mode = RGB565; rk_fb_pwr_enable(fb); + +#if defined(CONFIG_RK_EDP_EDID) + //get EDID for eDP panel. + if(panel_info.screen_type == SCREEN_EDP){ + rk3368_lcdc_get_vidinfo_from_edid(&panel_info); + if(panel_info.vl_freq >= 1000*1000){ + panel_info.vl_freq = panel_info.vl_freq/(1000*1000); + panel_info.vl_freq *= 1000*1000; + } + } +#endif + panel_info.real_freq = rkclk_lcdc_clk_set(panel_info.lcdc_id, panel_info.vl_freq); rk_lcdc_init(panel_info.lcdc_id); 2.2 在config中添加Edp配置 diff --git a/include/configs/rk_default_config.h b/include/configs/rk_default_config.h index 5583559..1bd3767 100755 --- a/include/configs/rk_default_config.h +++ b/include/configs/rk_default_config.h @@ -438,5 +438,6 @@ #endif /* CONFIG_LCD */ +#define CONFIG_RK_EDP_EDID #endif /* __RK_DEFAULT_CONFIG_H */ |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
569 浏览 0 评论
839 浏览 1 评论
737 浏览 1 评论
1957 浏览 1 评论
3204 浏览 1 评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 08:18 , Processed in 0.754976 second(s), Total 78, Slave 62 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号