FrikoAnPulento Posted September 21, 2020 Posted September 21, 2020 Hello, I'm trying to writing a patch for /gpu/drm/panel/panel-simple.c in order to make my 3.5" ampire works with my Olimex's A13 som board. I've correctly set display frequencies and parameters, and the image is displayed correctly... ...except for some random pixel wich sometimes changes color. I dig out with my oscilloscope and find that RGB data changes on clock's rising edge. Display's datasheet request data to be changed on falling edge insted. So, I've tryied to set the property, but nothing changed: data still changes on rising edge. Here's the core of my patch: diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c +static const struct display_timing ampire_am320240l9tnqw_00h_timing = { + .pixelclock = { 6500000, 6500000, 6500000 }, + .hactive = { 320, 320, 320 }, + .hfront_porch = { 20, 20, 20 }, + .hback_porch = { 68, 68, 68 }, + .hsync_len = { 10, 10, 10 }, + .vactive = { 240, 240, 240 }, + .vfront_porch = { 4, 4, 4 }, + .vback_porch = { 18, 18, 18 }, + .vsync_len = { 1, 1, 1 }, + .flags = DISPLAY_FLAGS_PIXDATA_NEGEDGE, +}; + +static const struct panel_desc ampire_am320240l9tnqw_00h = { + .timings = &ire_am320240l9tnqw_00h_timing, + .num_timings = 1, + .size = { + .width = 70, + .height = 53, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_PIXDATA_NEGEDGE, +}; + I've tryied many combination of flags, but nothing changes. I've tryied changing other parameters (like porches) and I can see the changes, so I know that driver loads this timings. Can someone please help me find out what I'm doing wrong? ### armbian-release: # PLEASE DO NOT EDIT THIS FILE BOARD=olimex-som-a13 BOARD_NAME="SOM-A13" BOARDFAMILY=sun5i BUILD_REPOSITORY_URL=https://github.com/olimex/build BUILD_REPOSITORY_COMMIT=65b71245 VERSION=5.92 LINUXFAMILY=sunxi BRANCH=next ARCH=arm IMAGE_TYPE=user-built BOARD_TYPE=csc INITRD_ARCH=arm KERNEL_IMAGE_TYPE=zImage uname -r 5.0.21-sunxi P.s. I know this is not the last version, but is the only one that seem to work with olimex's patches.
FrikoAnPulento Posted September 22, 2020 Author Posted September 22, 2020 I've dig in. It seems that my problem is related to (so called in drivers/manuals) "clock phase": at address 0x01C0C088 (read with devmem2 0x01C0C088) I found that bits 28:29 are set to 00, which A13's manual says: used DCLK0(normal phase offset) I've manually edit that bits with devmem2 0x01C0C088 w 0x20000000 first (used DCLK2(2/3 phase offset)), and find that the image now is stable. I've check the clock, but data is changing on higher clock state. Still not changing on falling edge. So, I've set register to devmem2 0x01C0C088 w 0x10000000 And finally data seems changing during clock's falling edge. So, I changed my patch with this +static const struct display_timing ampire_am320240l9tnqw_00h_timing = { + .pixelclock = { 6500000, 6500000, 6500000 }, + .hactive = { 320, 320, 320 }, + .hfront_porch = { 20, 20, 20 }, + .hback_porch = { 68, 68, 68 }, + .hsync_len = { 10, 10, 10 }, + .vactive = { 240, 240, 240 }, + .vfront_porch = { 4, 4, 4 }, + .vback_porch = { 18, 18, 18 }, + .vsync_len = { 1, 1, 1 }, +}; + +static const struct panel_desc ampire_am320240l9tnqw_00h = { + .timings = &ire_am320240l9tnqw_00h_timing, + .num_timings = 1, + .size = { + .width = 70, + .height = 53, + }, + .bus_format = MEDIA_BUS_FMT_RGB666_1X18, + .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, +}; + And now is working! ...to be continued
FrikoAnPulento Posted September 22, 2020 Author Posted September 22, 2020 I've checked sun4i drm driver sources. The reason because I was setting DRM_BUS_FLAG_PIXDATA_NEGEDGE was because, in file include/drm/drm_connector.h is written: /* drive data on pos. edge */ #define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2) /* drive data on neg. edge */ #define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3) (in kernel 5.9 is a bit different, but concept is still the same). I need to drive data in negative edge, so I've set DRM_BUS_FLAG_PIXDATA_NEGEDGE. Then, in file drivers/gpu/drm/sun4i/sun4i_tcon.c is written: /* * On A20 and similar SoCs, the only way to achieve Positive Edge * (Rising Edge), is setting dclk clock phase to 2/3(240°). * By default TCON works in Negative Edge(Falling Edge), * this is why phase is set to 0 in that case. * Unfortunately there's no way to logically invert dclk through * IO_POL register. * The only acceptable way to work, triple checked with scope, * is using clock phase set to 0° for Negative Edge and set to 240° * for Positive Edge. * On A33 and similar SoCs there would be a 90° phase option, * but it divides also dclk by 2. * Following code is a way to avoid quirks all around TCON * and DOTCLOCK drivers. */ if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) clk_set_phase(tcon->dclk, 240); if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) clk_set_phase(tcon->dclk, 0); So, setting NEGEDGE seemed to me the only reasonable option. I don't have an A20 to check if it's true or not, but seems like on A13 it works in the opposite way! (still same in kernel 5.9) Default il positive edge and 120 (not 240, but it works anyway, because data is stable when display is sampling) is negative edge. Can someone experienced with A20 tell me if this comment is right? (so I can know if is worth submit a patch to linux mainteiners?)
Recommended Posts