I'm trying to adapt the st7701 driver for my small 480x480 fascontek, fs040wx017' square display.
The panel is a 20 pin 2 lane MIPI DSI panel with a st7701S Controller IC.
Kernel Verison
Linux raspberrypi 6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt3 (2024-10-08) aarch64 GNU/Linux
Board
Raspberry Pi CM4 + IO Board
Driver I'm trying to adapt is panel-sitronix-st7701:
https://github.com/raspberrypi/linux/bl ... x-st7701.c
I have physically done the following
Matched the DSI pinouts of the CM4 IO board, and the panel (except the reset pin which im still stuck on how to tackle)
Matched the voltages of the panel Interface IO Vin (1.8V)
Matched the voltages of the panel Digital Supply IO Vin (3.3V)
Matched the Voltage/Current for the backlight Annode and Kathode (which is the onlything currently working) (18.63V, 0.updatethislaterA).
Tested the current draw of the panel Digital Vin (which is currently lower than expected).
My current software workflow: (Becuase In about a week now of searching forums and chatGPTing my mind down avenues, haven't found found a start to end process for this)
I found cross compiling a little too difficult, and my CM4 only has 8GB eMMc storage, so as for space and helpfully back-up I use a USB SSD as storage do the following.
Pull the Raspberry Pi Kernel:
git clone https://github.com/raspberrypi/linux.git
Install build requirements
sudo apt install -y raspberrypi-kernel-headers build-essential bc git bison flex libssl-dev
Find the driver that (possibly) best suit my usecase
linux/drivers/gpu/drm/panel/panel-sitronix-st7701c)
Add the panle specific codes
initialisation sequence,
gip sequence
panel description (which I just copied from another panel, and added the values i have from the panel manufacturer)
default display mode
build the modules in ../panel/*
(I'll update this cmd later for poential helping reference)
insert the module
sudo insmod panel-sitronix-st7701.ko
grab a random dts from the raspberry pi forum and hope it does something
Making sure to change the .compatible reference to hopefully load the module with my panel.
compatible = "fascontek,fs040wx017", "sitronix,st7701";
Reboot and check dmesg for any changes labelled with dsi in the log
dmesg | grep dsi
I've been given the initialisation code from the manufacturer, and have tried to adapt this (in a slightly ugly brute force way) to the existing driver.
My implementations are as follows:
Does this appear like a reasonable approach to initialising the panel correctly?
I have been testing by compiling this dts:
When I manually insert the module after boot:And also copying the module to /lib/modules/<kernelVerison>/..
I get the following:But otherwise the module doesn't appear to load on boot:
vanity@raspberrypi:~ $ dmesg | grep dsi
[ 0.048998] platform fe101000.cprman: Fixed dependency cycle(s) with /soc/dsi@7e700000
[ 0.051247] platform fe101000.cprman: Fixed dependency cycle(s) with /soc/dsi@7e700000
[ 0.051338] platform fe700000.dsi: Fixed dependency cycle(s) with /soc/dsi@7e700000/tplcd@0
[ 0.051380] platform fe700000.dsi: Fixed dependency cycle(s) with /soc/cprman@7e101000
[ 6.704216] vc4_dsi fe700000.dsi: Fixed dependency cycle(s) with /soc/dsi@7e700000/tplcd@0
[ 6.704369] mipi-dsi fe700000.dsi.0: Fixed dependency cycle(s) with /soc/dsi@7e700000
My question is:
I'm not sure if my approach is correct.
I've started designing an adapter board for this, and if all goes well would like to share this board, follow this drivers neat implementation and potentially add this panel to the kernel.
Thank you very much if you've read to the end of this, and an even greater thank you if you can help in some way.
William
The panel is a 20 pin 2 lane MIPI DSI panel with a st7701S Controller IC.
Kernel Verison
Linux raspberrypi 6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt3 (2024-10-08) aarch64 GNU/Linux
Board
Raspberry Pi CM4 + IO Board
Driver I'm trying to adapt is panel-sitronix-st7701:
https://github.com/raspberrypi/linux/bl ... x-st7701.c
I have physically done the following
Matched the DSI pinouts of the CM4 IO board, and the panel (except the reset pin which im still stuck on how to tackle)
Matched the voltages of the panel Interface IO Vin (1.8V)
Matched the voltages of the panel Digital Supply IO Vin (3.3V)
Matched the Voltage/Current for the backlight Annode and Kathode (which is the onlything currently working) (18.63V, 0.updatethislaterA).
Tested the current draw of the panel Digital Vin (which is currently lower than expected).
My current software workflow: (Becuase In about a week now of searching forums and chatGPTing my mind down avenues, haven't found found a start to end process for this)
I found cross compiling a little too difficult, and my CM4 only has 8GB eMMc storage, so as for space and helpfully back-up I use a USB SSD as storage do the following.
Pull the Raspberry Pi Kernel:
git clone https://github.com/raspberrypi/linux.git
Install build requirements
sudo apt install -y raspberrypi-kernel-headers build-essential bc git bison flex libssl-dev
Find the driver that (possibly) best suit my usecase
linux/drivers/gpu/drm/panel/panel-sitronix-st7701c)
Add the panle specific codes
initialisation sequence,
gip sequence
panel description (which I just copied from another panel, and added the values i have from the panel manufacturer)
default display mode
build the modules in ../panel/*
(I'll update this cmd later for poential helping reference)
insert the module
sudo insmod panel-sitronix-st7701.ko
grab a random dts from the raspberry pi forum and hope it does something
Making sure to change the .compatible reference to hopefully load the module with my panel.
compatible = "fascontek,fs040wx017", "sitronix,st7701";
Reboot and check dmesg for any changes labelled with dsi in the log
dmesg | grep dsi
I've been given the initialisation code from the manufacturer, and have tried to adapt this (in a slightly ugly brute force way) to the existing driver.
My implementations are as follows:
Code:
static void fs040wx017_init_sequence(struct st7701 *st7701){// const struct st7701_panel_desc *desc = st7701->desc;// const struct drm_display_mode *mode = desc->mode;// const u8 linecount8 = mode->vdisplay / 8;// const u8 linecountrem2 = (mode->vdisplay % 8) / 2;ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00);ST7701_DSI(st7701, 0x11);//Display Standbymsleep(120);//Switch to Page 1 maybe use "st7701_switch_cmd_bkx"ST7701_DSI(st7701, 0xFF, 0x77,0x01,0x00,0x00,0x10);ST7701_DSI(st7701, 0xC0, 0x77,0x3B,0x00);//Display Line Setting ST7701_DSI(st7701, 0xC1, 0x0D, 0x02);//Porch Control ST7701_DSI(st7701, 0xC2, 0x37, 0x05);// Inversion setST7701_DSI(st7701, 0xB0, 0x00,0x11,0x18,0x0,0x11,0x06,0x07,0x08,0x07,0x22,0x04,0x12,0x0F,0xAA,0x31,0x18);//Positive Voltage Gamma ControlST7701_DSI(st7701, 0xB1, 0x00,0x11,0x19,0x0E,0x12,0x07,0x08,0x08,0x08,0x22,0x04,0x11,0x11,0xA9,0x32,0x18);//Negative Voltage Gamma Control//Switch to Page 2ST7701_DSI(st7701, 0xFF, 0x77,0x01,0x00,0x00,0x11);ST7701_DSI(st7701, 0xB0, 0x60); //Vop Amplitude setting | Vop=4.7375vST7701_DSI(st7701, 0xB1, 0x26);//VCOM amplitude setting | VCOM=32ST7701_DSI(st7701, 0xB2, 0x07); //VGH Voltage setting | VGH=15vST7701_DSI(st7701, 0xB3, 0x80); //TEST Command SettingST7701_DSI(st7701, 0xB4, 0x49); //VGL Voltage setting | VGL=-10.17vST7701_DSI(st7701, 0xB5, 0x85); //Power Control 1 ST7701_DSI(st7701, 0xB7, 0x21); //Power Control 2 | AVDD=6.6 & AVCL=-4.6ST7701_DSI(st7701, 0xB8, 0x78); //Source pre_drive timing set1 ST7701_DSI(st7701, 0xC1, 0x78); //Source EQ2 Setting}static void fs040wx017_gip_sequence(struct st7701 *st7701){ST7701_DSI(st7701, 0xE0, 0x00, 0x1B, 0x02);ST7701_DSI(st7701, 0xE1, 0x08,0xA0,0x00,0x00,0x07,0xA0,0x00,0x00,0x00,0x44,0x44);ST7701_DSI(st7701, 0xE2, 0x11,0x11,0x44,0x44,0xED,0xA0,0x00,0x00,0xEC,0xA0,0x00,0x00);ST7701_DSI(st7701, 0xE3, 0x00,0x00,0x11,0x11);ST7701_DSI(st7701, 0xE4, 0x44,0x44);ST7701_DSI(st7701, 0xE5, 0x0A,0xE9,0xD8,0xA0,0x0C,0xEB,0xD8,0xA0,0x0E,0xED,0xD8,0xA0,0x10,0xEF,0xD8,0xA0);ST7701_DSI(st7701, 0xE6, 0x00,0x00,0x11,0x11);ST7701_DSI(st7701, 0xE7, 0x44,0x44);ST7701_DSI(st7701, 0xE8, 0x09,0xE8,0xD8,0xA0,0x0B,0xEA,0xD8,0xA0,0x0D,0xEC,0xD8,0xA0,0x0F,0xEE,0xD8,0xA0);ST7701_DSI(st7701, 0xEB, 0x02,0x00,0xE4,0xE4,0x88,0x00,0x40);ST7701_DSI(st7701, 0xEC, 0x3C,0x00);ST7701_DSI(st7701, 0xED ,0xAB,0x89,0x76,0x54,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x20,0x45,0x67,0x98,0xBA);}static const struct drm_display_mode fs040wx017_mode = { .clock = 220000, // PLL_CLOCK is 220 MHz .hdisplay = 480, .hsync_start = 480 + 50, // hdisplay + horizontal_backporch .hsync_end = 480 + 50 + 8, // hsync_start + horizontal_sync_active .htotal = 480 + 50 + 8 + 10, // hsync_end + horizontal_frontporch .vdisplay = 480, .vsync_start = 480 + 20, // vdisplay + vertical_backporch .vsync_end = 480 + 20 + 4, // vsync_start + vertical_sync_active .vtotal = 480 + 20 + 4 + 10, // vsync_end + vertical_frontporch .width_mm = 69, // Adjust to the panel's physical dimensions in millimeters .height_mm = 69, // Update to square dimensions, as the resolution suggests .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,};static const struct st7701_panel_desc fs040wx017_desc = {.mode = &fs040wx017_mode,.lanes = 2,.format = MIPI_DSI_FMT_RGB888,//Test This.panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */.init_sequence = fs040wx017_init_sequence,.conn_type = DRM_MODE_CONNECTOR_DSI,.interface = ST7701_CTRL_DSI,//And Test All Of These (copied from ).pv_gamma = {CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x8),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x23),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2b),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)},.nv_gamma = {CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x2) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x13),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x7),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x9),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x10),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)},.nlinv = 7,.vop_uv = 4737500,.vcom_uv = 300000,.vgh_mv = 15000,.vgl_mv = -1017,.avdd_mv = 6600,.avcl_mv = -4600,.gamma_op_bias = OP_BIAS_MAX,.input_op_bias = OP_BIAS_MIN,.output_op_bias = OP_BIAS_MIN,.t2d_ns = 1600,.t3d_ns = 10400,.eot_en = true,.gip_sequence = fs040wx017_gip_sequence,};
I have been testing by compiling this dts:
Code:
/dts-v1/;/plugin/;/ { compatible = "brcm,bcm2835"; fragment@0 { target = <&dsi1>; __overlay__ { status = "okay"; #address-cells = <1>; #size-cells = <0>; port { dsi_out: endpoint { remote-endpoint = <&panel_in>; }; }; tplcd: tplcd@0 { compatible = "fascontek,fs040wx017", "sitronix,st7701"; status = "okay"; reg = <0>;//fixme VCC-supply = <&fixedregulator_5v0>;//fixme IOVCC-supply = <&fixedregulator_3v3>;//fixme reset-gpios = <&gpio 6 1 GPIO_ACTIVE_LOW>; fps = <60>; debug = <1>; port { panel_in: endpoint { remote-endpoint = <&dsi_out>; }; }; }; }; }; __overrides__ { fps = <&tplcd>,"fps:0"; debug = <&tplcd>,"debug:0"; };};
When I manually insert the module after boot:
Code:
sudo insmod panel-sitronix-st7701.ko
I get the following:
Code:
[ 289.893564] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 291.013528] vc4_dsi fe700000.dsi: transfer interrupt wait timeout[ 291.013539] vc4_dsi fe700000.dsi: instat: 0x00000000, stat: 0x00000000[ 291.013548] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 292.133557] vc4_dsi fe700000.dsi: transfer interrupt wait timeout[ 292.133568] vc4_dsi fe700000.dsi: instat: 0x00000000, stat: 0x00000000[ 292.133578] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 293.253541] vc4_dsi fe700000.dsi: transfer interrupt wait timeout[ 293.253554] vc4_dsi fe700000.dsi: instat: 0x00000000, stat: 0x00000000[ 293.253565] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 294.373557] vc4_dsi fe700000.dsi: transfer interrupt wait timeout[ 294.373569] vc4_dsi fe700000.dsi: instat: 0x00000000, stat: 0x00000000[ 294.373579] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 295.493565] vc4_dsi fe700000.dsi: transfer interrupt wait timeout[ 295.493577] vc4_dsi fe700000.dsi: instat: 0x00000000, stat: 0x00000000[ 295.493587] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 296.613564] vc4_dsi fe700000.dsi: transfer interrupt wait timeout[ 296.613576] vc4_dsi fe700000.dsi: instat: 0x00000000, stat: 0x00000000[ 296.613586] [drm:vc4_dsi_transfer [vc4]] *ERROR* DSI transfer failed, resetting: -110[ 297.125576] [drm:vc4_dsi_host_transfer [vc4]] *ERROR* DSI transfer failed whilst in HS mode stat: 0x05000800
vanity@raspberrypi:~ $ dmesg | grep dsi
[ 0.048998] platform fe101000.cprman: Fixed dependency cycle(s) with /soc/dsi@7e700000
[ 0.051247] platform fe101000.cprman: Fixed dependency cycle(s) with /soc/dsi@7e700000
[ 0.051338] platform fe700000.dsi: Fixed dependency cycle(s) with /soc/dsi@7e700000/tplcd@0
[ 0.051380] platform fe700000.dsi: Fixed dependency cycle(s) with /soc/cprman@7e101000
[ 6.704216] vc4_dsi fe700000.dsi: Fixed dependency cycle(s) with /soc/dsi@7e700000/tplcd@0
[ 6.704369] mipi-dsi fe700000.dsi.0: Fixed dependency cycle(s) with /soc/dsi@7e700000
My question is:
I'm not sure if my approach is correct.
I've started designing an adapter board for this, and if all goes well would like to share this board, follow this drivers neat implementation and potentially add this panel to the kernel.
Thank you very much if you've read to the end of this, and an even greater thank you if you can help in some way.
William
Statistics: Posted by DHWill — Fri Jan 24, 2025 6:18 pm — Replies 0 — Views 22