Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4862

Interfacing (DSI, CSI, I2C, etc.) • CM4: DSI1 init. commands rarely fail

$
0
0
Hi everyone

I am having issues with CM4 when sending commands via DSI1 to a ST7703 controlled LCD (3,5" 640x480).
In 80% of the cases the LCD is initialized properly and works for days without any issue, but in 20% initializing does not work properly (LCD stays dark and I see errors regarding DSI-communication in dmesg).
I am building a Yocto Poky (Scarthgap) based system, using latest RPI 6.6 kernel (6.6.58).
I took the original panel-sitronix-st7703.c and added my init-codes and accordingly the compatible strings.
The rpi bootfiles stamp is 20240319.

Tested on two different HW-setups with many different CM4s connected:
1.) CM4 IO-Board (with intermediate PCB to match the pinning. Overall length from CM4IO to LCD controller 130mm)
2.) My custom-made board (impedance-controlled, pair- and inter-pair-length matched). Overall length of the FFC (from board-connector to LCD controller): 50mm. For EMC I added common mode chokes to DSI clock and data lines (Murata P0NSC900HL2L / DLP0NSN900HL2L / DLM0NSN900HY2 / DLM0NSM900HY2) that work properly on way faster HDMI implementations.

Tested with two different ST7703 LCDs:
1.) Startek KD035VGFID251 (.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM)
2.) TSONT H35C302-00W (custom made; .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM)

I do NOT think that the electrical connection is the problem, as the situation does not get worse when adding additional 500mm standard (no impedance matching!!) FFC!

I see the following problems during initialization (no matter if it is a power-cycle or the "reboot" command) of the panel (I added some additional output to the driver to see which functions are called):

1.)

Code:

[    3.698613] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_probe ...[    3.698661] panel-sitronix-st7703 fe700000.dsi.0: supply vcc not found, using dummy regulator[    3.698751] panel-sitronix-st7703 fe700000.dsi.0: supply iovcc not found, using dummy regulator[    4.003699] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_prepare ...[    4.042555] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_enable ...[    4.042566] panel-sitronix-st7703 fe700000.dsi.0: Sending init code for TSONT H35C302_00W ...[    4.547329] panel-sitronix-st7703 fe700000.dsi.0: sending command 0xe9 failed: -110[    4.547343] panel-sitronix-st7703 fe700000.dsi.0: Panel init sequence failed: -110[    4.597282] panel-sitronix-st7703 fe700000.dsi.0: 640x480@60 24bpp dsi 2dl - ready
Sometimes it is looking like this, but this just means that sending of a command AFTER the init code does not work, so to me thats the same failure as above...:

Code:

[    3.881886] panel-sitronix-st7703 fe700000.dsi.0: Sending init code for TSONT H35C302_00W ...[    4.476200] panel-sitronix-st7703 fe700000.dsi.0: Failed to exit sleep mode: -110[    4.526171] panel-sitronix-st7703 fe700000.dsi.0: 640x480@60 24bpp dsi 2dl - ready
2.)

Code:

[    4.087125] panel-sitronix-st7703 fe700000.dsi.0: Sending init code for TSONT H35C302_00W ...[    4.592052] [drm:vc4_dsi_host_transfer] *ERROR* DSI transfer failed whilst in HS mode stat: 0x00020803[    4.592086] panel-sitronix-st7703 fe700000.dsi.0: sending command 0xb4 failed: -110[    4.592100] panel-sitronix-st7703 fe700000.dsi.0: Panel init sequence failed: -110[    4.662052] panel-sitronix-st7703 fe700000.dsi.0: 640x480@60 24bpp dsi 2dl - ready
3.) After being properly initialized a blanking/unblanking via the console ALWAYS FAILS (not only in 20% of all cases!!) like this (note that also in this case RESET and LP11 is OK before sending init code - thus I do not really understand the different behaviour to a "reboot" command which fails just "seldom"):
echo 2 > /sys/class/graphics/fb0/blank

Code:

[   27.051655] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_disable ...[   27.182124] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_unprepare ...
echo 0 > /sys/class/graphics/fb0/blank

Code:

[   34.402469] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_prepare ...[   34.447529] panel-sitronix-st7703 fe700000.dsi.0: Called st7703_enable ...[   34.447539] panel-sitronix-st7703 fe700000.dsi.0: Sending init code for TSONT H35C302_00W ...[   34.952123] [drm:vc4_dsi_host_transfer] *ERROR* DSI transfer failed whilst in HS mode stat: 0x05020003[   34.952155] panel-sitronix-st7703 fe700000.dsi.0: sending command 0xba failed: -110[   34.952169] panel-sitronix-st7703 fe700000.dsi.0: Panel init sequence failed: -110
RESET-signal and entering LP11 before releasing RESET looks OK (Pic is taken after cold-start; #1=D0_P. #2=D0_N, DigitalChannel D0=RESET):
RESET_Sequence.jpg
Overlay:

Code:

dts-v1/;/plugin/;/ {        compatible = "brcm,bcm2835";        fragment@0 {                target = <&dsi1>;                __overlay__  {                        #address-cells = <1>;                        #size-cells = <0>;                        status = "okay";                        port {                                dsi_out: endpoint {                                        remote-endpoint = <&panel_in>;                                };                        };                        dsi_panel: dsi_panel@0 {                                reg = <0>;                                compatible = "tsont,h35c302-00w";                                // Add a regulator if you have one                                //power-supply = <&reg_display>;                                // Add a backlight controller  if you have one                                //backlight = <&backlight>;                // Add reset pin                reset-gpios = <&gpio 22 1>; /* GPIO PIN 22, active Low */                                port {                                        panel_in: endpoint {                                                remote-endpoint = <&dsi_out>;                                        };                                };                        };                };        };};
My driver, I deleted all unnecessary functions to keep it small...

Code:

#include <linux/debugfs.h>#include <linux/delay.h>#include <linux/gpio/consumer.h>#include <linux/media-bus-format.h>#include <linux/mod_devicetable.h>#include <linux/module.h>#include <linux/of.h>#include <linux/regulator/consumer.h>#include <video/display_timing.h>#include <video/mipi_display.h>#include <drm/drm_mipi_dsi.h>#include <drm/drm_modes.h>#include <drm/drm_panel.h>#define DRV_NAME "panel-sitronix-st7703"/* Manufacturer specific Commands send via DSI */#define ST7703_CMD_ALL_PIXEL_OFF 0x22#define ST7703_CMD_ALL_PIXEL_ON 0x23#define ST7703_CMD_SETAPID 0xB1#define ST7703_CMD_SETDISP 0xB2#define ST7703_CMD_SETRGBIF 0xB3#define ST7703_CMD_SETCYC 0xB4#define ST7703_CMD_SETBGP 0xB5#define ST7703_CMD_SETVCOM 0xB6#define ST7703_CMD_SETOTP 0xB7#define ST7703_CMD_SETPOWER_EXT 0xB8#define ST7703_CMD_SETEXTC 0xB9#define ST7703_CMD_SETMIPI 0xBA#define ST7703_CMD_SETVDC 0xBC#define ST7703_CMD_UNKNOWN_BF 0xBF#define ST7703_CMD_SETSCR 0xC0#define ST7703_CMD_SETPOWER 0xC1#define ST7703_CMD_SETECO 0xC6#define ST7703_CMD_SETIO 0xC7#define ST7703_CMD_SETCABC 0xC8#define ST7703_CMD_SETPANEL 0xCC#define ST7703_CMD_SETGAMMA 0xE0#define ST7703_CMD_SETEQ 0xE3#define ST7703_CMD_SETGIP1 0xE9#define ST7703_CMD_SETGIP2 0xEA#define ST7703_CMD_UNKNOWN_EF 0xEFstruct st7703 {struct device *dev;struct drm_panel panel;struct gpio_desc *reset_gpio;struct regulator *vcc;struct regulator *iovcc;bool prepared;struct dentry *debugfs;const struct st7703_panel_desc *desc;enum drm_panel_orientation orientation;};struct st7703_panel_desc {const struct drm_display_mode *mode;unsigned int lanes;unsigned long mode_flags;enum mipi_dsi_pixel_format format;int (*init_sequence)(struct st7703 *ctx);};static inline struct st7703 *panel_to_st7703(struct drm_panel *panel){return container_of(panel, struct st7703, panel);}static int kd035vgfid251_init_sequence (struct st7703 *ctx){struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);/* * Init sequence was supplied by the panel vendor. Panel will not * respond to commands until it is brought out of sleep mode first. */dev_info(ctx->dev, "Sending init code for STARTEK KD035VGFID251 ...\n");/* Magic sequence to unlock user commands below. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xDA, 0x80);/* Set display resolution. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,       0x00, /* 480 */       0x13, /* 640 */       0x70);/* RGB I/F porch timing */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,       0x10, /* VBP_RGB_GEN */       0x10, /* VFP_RGB_GEN */       0x28, /* DE_BP_RGB_GEN */       0x28, /* DE_FP_RGB_GEN */       /* The rest is undocumented in ST7703 datasheet */       0x03, 0xFF, 0x00, 0x00, 0x00, 0x00);/* Zig-Zag Type C column inversion. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x82);/* Reference voltage. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,       0x07, /* VREF_SEL */       0x07  /* NVREF_SEL */);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,       0x9C, /* VCOMDC_F */       0x9C  /* VCOMDC_B */);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x2A, 0x62, 0xF0, 0x60);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,       0x31, /* VC_main = 0, Lane_Number = 2 */       0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */       0x05, /* IHSRX = x6 (Low High Speed driving ability) */       0xF9, /* TX_CLK_SEL = fDSICLK/16 */       0x0E, /* HFP_OSC (min. HFP number in DSI mode) */       0x0E, /* HBP_OSC (min. HBP number in DSI mode) */       /* The rest is undocumented in ST7703 datasheet */       0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x44, 0x25, 0x00, 0x90, 0x0A, 0x00, 0x00, 0x01,       0x4F, 0x01, 0x00, 0x00, 0x37);/* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);/* Undocumented command. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);/* Source driving settings. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,       0x73, /* N_POPON */       0x73, /* N_NOPON */       0x50, /* I_POPON */       0x50, /* I_NOPON */       0x00, /* SCR[31,24] */       0x00, /* SCR[23,16] */       0x12, /* SCR[15,8] */       0x70, /* SCR[7,0] */       0x00  /* Undocumented */);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,       0x25, /* VBTHS, VBTLS*/       0xC0, /* FBOFF_VGH, FBOFF_VGL  */       0x32, /* VRP  */       0x32, /* VRN */       0x77, /* reserved */       0xE4, /* APS = 1 (small),      * VGL_DET_EN = 1, VGH_DET_EN = 1,      * VGL_TURBO = 1, VGH_TURBO = 1      */       0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */       0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */       0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */       0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */       0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */       0x77  /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xBF, 0xFF, 0x00, 0xFF);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xB8, 0x00, 0x0A, 0x00, 0x00, 0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1E, 0x02);/* * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan) * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR) */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);/* Adjust the gamma characteristics of the panel. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,       0x00, 0x07, 0x0D, 0x37, 0x35, 0x3F, 0x41, 0x44,       0x06, 0x0C, 0x0D, 0x0F, 0x11, 0x10, 0x12, 0x14,       0x1A, 0x00, 0x07, 0x0D, 0x37, 0x35, 0x3F, 0x41,       0x44, 0x06, 0x0C, 0x0D, 0x0F, 0x11, 0x10, 0x12,       0x14, 0x1A);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,       0x07, /* PNOEQ */       0x07, /* NNOEQ */       0x0B, /* PEQGND */       0x0B, /* NEQGND */       0x0B, /* PEQVCI */       0x0B, /* NEQVCI */       0x00, /* PEQVCI1 */       0x00, /* NEQVCI1 */       0x00, /* reserved */       0x00, /* reserved */       0xFF, /* reserved */       0x00, /* reserved */       0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */       0x10  /* SLPIN_OPTION = 1 (no need vsync after sleep-in)      * VEDIO_NO_CHECK_EN = 0      * ESD_WHITE_GND_EN = 0      * ESD_DET_TIME_SEL = 0 frames      */);/* This command is to set forward GIP timing. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,       0xC8, 0x10, 0x0A, 0x00, 0x00, 0xF0, 0x08, 0x12,       0x31, 0x23, 0x4F, 0x86, 0xF0, 0x08, 0x47, 0x08,       0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,       0x10, 0x00, 0x00, 0x00, 0x88, 0x88, 0x08, 0xF8,       0xF4, 0x46, 0x60, 0x02, 0x28, 0x88, 0x88, 0x88,       0x88, 0x18, 0xF8, 0xF5, 0x57, 0x71, 0x13, 0x38,       0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);/* This command is to set backward GIP timing. */mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,       0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x00, 0x00, 0x88, 0xF8, 0x18, 0xF8,       0x83, 0x31, 0x17, 0x75, 0x58, 0x88, 0x88, 0x88,       0xF8, 0x08, 0xF8, 0x82, 0x20, 0x06, 0x64, 0x48,       0x88, 0x88, 0x23, 0x00, 0x00, 0x03, 0xF0, 0x00,       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x00, 0x00, 0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xFF, 0xFF, 0x01);/* The lines below are done in st7703_enable()mipi_dsi_dcs_exit_sleep_mode(dsi);msleep(150);mipi_dsi_dcs_set_display_on(dsi);*/return 0;}static const struct drm_display_mode kd035vgfid251_mode = {.hdisplay    = 640,// H resolution.hsync_start = 640 + 26,// resolution + front porch.hsync_end   = 640 + 26 + 4,// resolution + front porch + sync pulse.htotal     = 640 + 26 + 4 + 10,// resolution + front porch + sync pulse + back porch = 680px.vdisplay    = 480,// V resolution.vsync_start = 480 + 16,// resolution + front porch.vsync_end   = 480 + 16 + 4,// resolution + front porch + sync pulse.vtotal     = 480 + 16 + 4 + 14,// resolution + front porch + sync pulse + back porch = 514px.clock     = 20972,// 60Hz.flags     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,.width_mm    = 70,.height_mm   = 53,};static const struct st7703_panel_desc kd035vgfid251_desc = {.mode = &kd035vgfid251_mode,.lanes = 2,.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET,.format = MIPI_DSI_FMT_RGB888,.init_sequence = kd035vgfid251_init_sequence,};static int h35c302_00w_init_sequence(struct st7703 *ctx){struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);/* * Init sequence was supplied by the panel vendor. Panel will not * respond to commands until it is brought out of sleep mode first. */dev_info(ctx->dev, "Sending init code for TSONT H35C302_00W ...\n");mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9,       0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00,       0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x26);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a,       0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,       0x00, 0x00, 0x08, 0x70, 0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,       0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,       0xc0, 0x10);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e,       0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33,       0x33);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x10, 0x10);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x6c, 0x7c);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00,       0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10,       0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,       0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,       0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,       0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,       0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,       0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,       0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,       0x88, 0x88, 0x88, 0xB1, 0x88, 0xba, 0x06, 0x42,       0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10,       0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       0x00);mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b,       0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b,       0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07,       0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a,       0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18);return 0;}static const struct drm_display_mode h35c302_00w_mode = {.hdisplay= 640,.hsync_start= 640 + 40,.hsync_end= 640 + 40 + 2,.htotal= 640 + 40 + 2 + 80,.vdisplay= 480,.vsync_start= 480 + 17,.vsync_end= 480 + 17 + 5,.vtotal= 480 + 17 + 5 + 13,.clock= 23546,.flags= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,.width_mm= 71,.height_mm= 53,};static const struct st7703_panel_desc h35c302_00w_desc = {.mode = &h35c302_00w_mode,.lanes = 2,.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |      MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,.format = MIPI_DSI_FMT_RGB888,.init_sequence = h35c302_00w_init_sequence,};static int st7703_enable(struct drm_panel *panel){struct st7703 *ctx = panel_to_st7703(panel);struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);int ret;dev_info(ctx->dev, "Called st7703_enable ..."); //###ret = ctx->desc->init_sequence(ctx);if (ret < 0) {dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);return ret;}msleep(50); //### increased from 20 by MWret = mipi_dsi_dcs_exit_sleep_mode(dsi);if (ret < 0) {dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);return ret;}/* It takes the controller 120 msec to wake up after sleep. */msleep(150);ret = mipi_dsi_dcs_set_display_on(dsi);if (ret)return ret;dev_dbg(ctx->dev, "Panel init sequence done\n");return 0;}static int st7703_disable(struct drm_panel *panel){struct st7703 *ctx = panel_to_st7703(panel);struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);int ret;dev_info(ctx->dev, "Called st7703_disable ..."); //###ret = mipi_dsi_dcs_set_display_off(dsi);if (ret < 0)dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);ret = mipi_dsi_dcs_enter_sleep_mode(dsi);if (ret < 0)dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);/* It takes the controller 120 msec to enter sleep mode. */msleep(120);return 0;}static int st7703_unprepare(struct drm_panel *panel){struct st7703 *ctx = panel_to_st7703(panel);dev_info(ctx->dev, "Called st7703_unprepare ..."); //###if (!ctx->prepared)return 0;gpiod_set_value_cansleep(ctx->reset_gpio, 1);regulator_disable(ctx->iovcc);regulator_disable(ctx->vcc);ctx->prepared = false;return 0;}static int st7703_prepare(struct drm_panel *panel){struct st7703 *ctx = panel_to_st7703(panel);int ret;dev_info(ctx->dev, "Called st7703_prepare ..."); //###if (ctx->prepared)return 0;dev_dbg(ctx->dev, "Resetting the panel\n");gpiod_set_value_cansleep(ctx->reset_gpio, 1);ret = regulator_enable(ctx->iovcc);if (ret < 0) {dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);return ret;}ret = regulator_enable(ctx->vcc);if (ret < 0) {dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);regulator_disable(ctx->iovcc);return ret;}/* Give power supplies time to stabilize before deasserting reset. */usleep_range(10000, 20000);gpiod_set_value_cansleep(ctx->reset_gpio, 0);usleep_range(20000, 25000);//###increasing to 120-150ms does not help herectx->prepared = true;return 0;}static const u32 mantix_bus_formats[] = {MEDIA_BUS_FMT_RGB888_1X24,};static int st7703_get_modes(struct drm_panel *panel,    struct drm_connector *connector){struct st7703 *ctx = panel_to_st7703(panel);struct drm_display_mode *mode;mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);if (!mode) {dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,drm_mode_vrefresh(ctx->desc->mode));return -ENOMEM;}drm_mode_set_name(mode);mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;connector->display_info.width_mm = mode->width_mm;connector->display_info.height_mm = mode->height_mm;drm_mode_probed_add(connector, mode);drm_display_info_set_bus_formats(&connector->display_info, mantix_bus_formats, ARRAY_SIZE(mantix_bus_formats));return 1;}static enum drm_panel_orientation st7703_get_orientation(struct drm_panel *panel){struct st7703 *st7703 = panel_to_st7703(panel);return st7703->orientation;}static const struct drm_panel_funcs st7703_drm_funcs = {.disable   = st7703_disable,.unprepare = st7703_unprepare,.prepare   = st7703_prepare,.enable   = st7703_enable,.get_modes = st7703_get_modes,.get_orientation = st7703_get_orientation,};static int allpixelson_set(void *data, u64 val){struct st7703 *ctx = data;struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);dev_info(ctx->dev, "Setting all pixels on\n");mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);msleep(val * 1000);/* Reset the panel to get video back */drm_panel_disable(&ctx->panel);drm_panel_unprepare(&ctx->panel);drm_panel_prepare(&ctx->panel);drm_panel_enable(&ctx->panel);return 0;}DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,allpixelson_set, "%llu\n");static void st7703_debugfs_init(struct st7703 *ctx){ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,    &allpixelson_fops);}static void st7703_debugfs_remove(struct st7703 *ctx){debugfs_remove_recursive(ctx->debugfs);ctx->debugfs = NULL;}static int st7703_probe(struct mipi_dsi_device *dsi){struct device *dev = &dsi->dev;struct st7703 *ctx;int ret;dev_info(dev, "Called st7703_probe ..."); //###ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);if (!ctx)return -ENOMEM;ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);if (IS_ERR(ctx->reset_gpio))return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");mipi_dsi_set_drvdata(dsi, ctx);ctx->dev = dev;ctx->desc = of_device_get_match_data(dev);dsi->mode_flags = ctx->desc->mode_flags;dsi->format = ctx->desc->format;dsi->lanes = ctx->desc->lanes;ctx->vcc = devm_regulator_get(dev, "vcc");if (IS_ERR(ctx->vcc))return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");ctx->iovcc = devm_regulator_get(dev, "iovcc");if (IS_ERR(ctx->iovcc))return dev_err_probe(dev, PTR_ERR(ctx->iovcc),     "Failed to request iovcc regulator\n");ret = of_drm_get_panel_orientation(dsi->dev.of_node, &ctx->orientation);if (ret < 0)return dev_err_probe(&dsi->dev, ret, "Failed to get orientation\n");drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,       DRM_MODE_CONNECTOR_DSI);ret = drm_panel_of_backlight(&ctx->panel);if (ret)return ret;ctx->panel.prepare_prev_first = true;//### ADDED by MW, otherwise LP11 is not set before reset/init of the paneldrm_panel_add(&ctx->panel);msleep(10); //### ADDED by MW, sometimes below mipi_dsi_attach does not work properly as "host not ready"ret = mipi_dsi_attach(dsi);if (ret < 0) {dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);drm_panel_remove(&ctx->panel);return ret;}dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, drm_mode_vrefresh(ctx->desc->mode), mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);st7703_debugfs_init(ctx);return 0;}static void st7703_shutdown(struct mipi_dsi_device *dsi){struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);int ret;dev_info(&dsi->dev, "Called st7703_shutdown ..."); //###ret = drm_panel_unprepare(&ctx->panel);if (ret < 0)dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);ret = drm_panel_disable(&ctx->panel);if (ret < 0)dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);}static void st7703_remove(struct mipi_dsi_device *dsi){struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);int ret;st7703_shutdown(dsi);dev_info(&dsi->dev, "Called st7703_remove ..."); //###ret = mipi_dsi_detach(dsi);if (ret < 0)dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);drm_panel_remove(&ctx->panel);st7703_debugfs_remove(ctx);}static const struct of_device_id st7703_of_match[] = {{ .compatible = "startek,kd035vgfid251", .data = &kd035vgfid251_desc },{ .compatible = "tsont,h35c302-00w", .data = &h35c302_00w_desc },{ /* sentinel */ }};MODULE_DEVICE_TABLE(of, st7703_of_match);static struct mipi_dsi_driver st7703_driver = {.probe= st7703_probe,.remove = st7703_remove,.shutdown = st7703_shutdown,.driver = {.name = DRV_NAME,.of_match_table = st7703_of_match,},};module_mipi_dsi_driver(st7703_driver);

I am curious why video-data is shown properly over days but sending commands does sometimes fail...
AND why it does not fail at the very first command sent (would be 0xB9 IIRC), but at a (random) command during the whole init sequence ..

Any help to where to look at is appreciated - THANKS in advance!

Statistics: Posted by RinaMat — Tue Nov 12, 2024 10:48 am



Viewing all articles
Browse latest Browse all 4862

Trending Articles