drm/sun4i: Allwinner MIPI-DSI Burst mode support
Subsystems (7)
Jagan Teki
maintainerv2 cover drm/sun4i: Allwinner MIPI-DSI Burst mode support
This series support MIPI-DSI Burst mode on Allwinner platform, which is tested in burst supported panel in Pine64-LTS board.
Series fixed few code changes commented in previous version[1] and it depends on A64 MIPI-DSI series[2]
Changes for v2:
- add separate function for setup_inst_delay computation
- moved instruction loop seletion below delay compuation
- add separate function for dsi_get_timings and call for non-burst mode
- simplify burst mode timings compuatation
- add new patches, for tcon0 probing during dsi_bind
- add code to get the tcon0 divider value
- add multiple functions to get line_num, edge0, edge1
- squash 'enable burst mode' patch into 'Setup burst mode'
- fixed commit message of 'Enable burst mode HBP, HSA_HSE' s/enable/disable
- collect Rob R-b tag on panel dt-bindings patch
- panel driver changes,
- dropped unneeded include files
- s/fy07024di26a30d/feiyang function, variable names
- use DRM_DEV_ERROR in panel driver
- add set_display_on .enable
- moved regulator enablement to .prepare
- handle erro statements and release them properly during probe
- remove panel if mipi_dsi_attach failed
- fixed MODULE_LICENSE
- update MAINTAINERS file about the panel
- add comments on dts about exact regulators used in schematics
[1] https://patchwork.kernel.org/cover/10666597/
[2] https://patchwork.kernel.org/cover/10680247/
Any inputs,
Jagan.
Jagan Teki (12):
drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction
delay
drm/sun4i: sun6i_mipi_dsi: Support instruction loop selection drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
drm/sun4i: sun6i_mipi_dsi: Simplify drq set to support all modes drm/sun4i: tcon: Export get tcon0 routine
drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
drm/sun4i: sun6i_mipi_dsi: Setup burst mode
drm/sun4i: sun6i_mipi_dsi: Enable 2byte trail for 4-lane burst mode drm/sun4i: sun6i_mipi_dsi: Enable burst mode HBP, HSA_HSE
dt-bindings: panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
[DO NOT MERGE] arm64: allwinner: a64: pine64-lts: Enable Feiyang FY07024DI26A30-D DSI
panel
.../display/panel/feiyang,fy07024di26a30d.txt | 20 ++ MAINTAINERS | 6 + .../dts/allwinner/sun50i-a64-pine64-lts.dts | 37 +++ drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 +- drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 + drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 264 ++++++++++++---- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 + 10 files changed, 567 insertions(+), 61 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerPATCH v2 1/12 drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((mode->htotal - mode->hdisplay) * 150) /
((mode->clock / 1000) * 8)) - 50;
So use the similar computation for loop N1 delay.
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +19 -1
@@ -379,6 +379,24 @@ static u16 sun6i_dsi_get_timings_vblk(struct sun6i_dsi *dsi,return vblk; } +static u16 sun6i_dsi_setup_inst_delay (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +u32 hsync_porch, dclk; +u16 delay; + + hsync_porch = (mode->htotal - mode->hdisplay); + dclk = (mode->clock /1000 ); + +if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + delay = ((hsync_porch *150 ) / (dclk *8 )) -50 ; +else + delay =50 -1 ; + +return delay; +} +static u16 sun6i_dsi_get_video_start_delay (struct sun6i_dsi *dsi,struct drm_display_mode *mode) {
@@ -418,7 +436,7 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_inst_loop (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -u16 delay =50 -1 ; +u16 delay =sun6i_dsi_setup_inst_delay (dsi, mode); regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0), SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
Signature · 1 line
2.18.0.321.gffc6fa0e3
Re: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Quoted 6 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
Quoted 8 lines
dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;So use the similar computation for loop N1 delay.
*why* are you doing this? What is it fixing? on which devices?
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Quoted 13 lines · Maxime Ripard
Quoted 11 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;
Quoted 5 lines
Quoted 3 lines
So use the similar computation for loop N1 delay.
Signed-off-by Jagan Teki <[email protected]>*why* are you doing this? What is it fixing? on which devices?
You mentioned the separate function to compute the delay for all modes [1], ie what I did. did I missing anything?
Re: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Quoted 14 lines · Jagan Teki
Quoted 13 lines · Maxime Ripard
Quoted 11 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
So use the similar computation for loop N1 delay.
*why* are you doing this? What is it fixing? on which devices?
You mentioned the separate function to compute the delay for all modes [1], ie what I did. did I missing anything?
You're missing that you are never explaining why that patch is needed in the first place. Or answering the question I asked a couple of lines above.
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Quoted 20 lines · Maxime Ripard
Quoted 18 lines · Jagan Teki
Quoted 17 lines · Maxime Ripard
Quoted 14 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;So use the similar computation for loop N1 delay.
Signed-off-by Jagan Teki <[email protected]>
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
*why* are you doing this? What is it fixing? on which devices?
You mentioned the separate function to compute the delay for all modes [1], ie what I did. did I missing anything?
You're missing that you are never explaining why that patch is needed in the first place. Or answering the question I asked a couple of lines above.
OK.
The instruction delay varies between video and burst mode. for burst mode panels it is computed based on the panel clock along with horizontal sync+porch timings.
Got it, the same I need to update on commit, since you asked about separate delay route I thought you get the proper details.
Re: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Quoted 30 lines · Jagan Teki
Quoted 20 lines · Maxime Ripard
Quoted 18 lines · Jagan Teki
Quoted 17 lines · Maxime Ripard
Quoted 14 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;So use the similar computation for loop N1 delay.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
*why* are you doing this? What is it fixing? on which devices?
You mentioned the separate function to compute the delay for all modes [1], ie what I did. did I missing anything?
You're missing that you are never explaining why that patch is needed in the first place. Or answering the question I asked a couple of lines above.
Quoted 5 lines
OK.
The instruction delay varies between video and burst mode. for burst mode panels it is computed based on the panel clock along with horizontal sync+porch timings.
You're still stating a fact. What issue, that you experienced, are you trying to solve here?
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Re: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
Quoted 32 lines · Maxime Ripard
Quoted 30 lines · Jagan Teki
Quoted 28 lines · Maxime Ripard
Quoted 14 lines · Jagan Teki
Quoted 13 lines · Maxime Ripard
Quoted 11 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
So use the similar computation for loop N1 delay.
Signed-off-by Jagan Teki <[email protected]>*why* are you doing this? What is it fixing? on which devices?
You mentioned the separate function to compute the delay for all modes [1], ie what I did. did I missing anything?
You're missing that you are never explaining why that patch is needed in the first place. Or answering the question I asked a couple of lines above.
Quoted 8 lines
Quoted 5 lines
OK.
The instruction delay varies between video and burst mode. for burst mode panels it is computed based on the panel clock along with horizontal sync+porch timings.
You're still stating a fact. What issue, that you experienced, are you trying to solve here?
IIRC that's what BSP driver does. Otherwise panels that use burst mode just don't work.
Quoted 6 lines
Maxime
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 01/12] drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction delay
In reply to Maxime RipardQuoted 32 lines · Maxime Ripard
Quoted 30 lines · Jagan Teki
Quoted 28 lines · Maxime Ripard
Quoted 14 lines · Jagan Teki
Quoted 13 lines · Maxime Ripard
Quoted 11 lines · Jagan Teki
Loop N1 instruction delay for burst mode lcd panel are computed as per BSP code.
Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1= (panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50; => (((
mode->htotal-mode->hdisplay) * 150) /((mode->clock / 1000) * 8)) - 50;Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
So use the similar computation for loop N1 delay.
Signed-off-by Jagan Teki <[email protected]>*why* are you doing this? What is it fixing? on which devices?
You mentioned the separate function to compute the delay for all modes [1], ie what I did. did I missing anything?
You're missing that you are never explaining why that patch is needed in the first place. Or answering the question I asked a couple of lines above.
Quoted 8 lines
Quoted 5 lines
OK.
The instruction delay varies between video and burst mode. for burst mode panels it is computed based on the panel clock along with horizontal sync+porch timings.
You're still stating a fact. What issue, that you experienced, are you trying to solve here?
This change is specific for burst mode instruction delay. for non-burst it is 50 - 1 and for burst mode it is computed as mentioned in commit message. Both things are available in BSP code. and without this burst mode panels not working with existing (50 - 1)
Jagan Teki
maintainerPATCH v2 2/12 drm/sun4i: sun6i_mipi_dsi: Support instruction loop selection
In reply to Jagan TekiInstruction loop selection would require before writing loop number registers, so enable idle, LP11 bits on loop selection register.
Reference code available in BSP (from linux-sunxi/ drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
(dsi_dev[sel]->dsi_inst_loop_sel.dwval = 2<<(4*DSI_INST_ID_LP11) |
3<<(4*DSI_INST_ID_DLY);
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3 -0
@@ -438,6 +438,9 @@ static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi, {u16 delay =sun6i_dsi_setup_inst_delay (dsi, mode); +regmap_write (dsi->regs,SUN6I_DSI_INST_LOOP_SEL_REG , +DSI_INST_ID_HSC << (4 *DSI_INST_ID_LP11 ) | +DSI_INST_ID_HSD << (4 *DSI_INST_ID_DLY ));regmap_write (dsi->regs,SUN6I_DSI_INST_LOOP_NUM_REG (0 ),SUN6I_DSI_INST_LOOP_NUM_N0 (50 -1 ) |SUN6I_DSI_INST_LOOP_NUM_N1 (delay));
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerPATCH v2 3/12 drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
In reply to Jagan TekiBurst mode display timings are different from convectional video mode so update the horizontal and vertical timings.
Reference code taken from BSP (from linux-sunxi/ drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
dsi_hsa = 0;dsi_hbp = 0;dsi_hact = x*dsi_pixel_bits[format]/8;dsi_hblk = dsi_hact;dsi_hfp = 0;dsi_vblk = 0;
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 128 +++++++++++++++---------- 1 file changed, 80 insertions(+), 48 deletions(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +80 -48
@@ -153,6 +153,14 @@#define SUN6I_DSI_CMD_TX_REG (n) (0x300 + (n) * 0x04) +struct sun6i_dsi_timings { +u16 hsa; +u16 hbp; +u16 hblk; +u16 hfp; +u16 vblk; +}; +enum sun6i_dsi_start_inst {DSI_START_LPRX ,DSI_START_LPTX ,
@@ -379,6 +387,60 @@ static u16 sun6i_dsi_get_timings_vblk(struct sun6i_dsi *dsi,return vblk; } +static void sun6i_dsi_get_timings (struct sun6i_dsi *dsi, +struct drm_display_mode *mode, +struct sun6i_dsi_timings *timings) +{ +struct mipi_dsi_device *device = dsi->device; +unsigned int Bpp =mipi_dsi_pixel_format_to_bpp (device->format) /8 ; +u16 hsa, hbp, hblk, hfp, vblk; + +/* +* A sync period is composed of a blanking packet (4 bytes + +* payload + 2 bytes) and a sync event packet (4 bytes). +* Its minimal size is therefore 10 bytes +*/ +#define HSA_PACKET_OVERHEAD 10 + hsa =max ((unsigned int )HSA_PACKET_OVERHEAD , + (mode->hsync_end - mode->hsync_start) * Bpp - +HSA_PACKET_OVERHEAD ); + +/* +* The backporch is set using a blanking packet (4 bytes + +* payload + 2 bytes). Its minimal size is therefore 6 bytes +*/ +#define HBP_PACKET_OVERHEAD 6 + hbp =max ((unsigned int )HBP_PACKET_OVERHEAD , + (mode->htotal - mode->hsync_end) * Bpp -HBP_PACKET_OVERHEAD ); + +/* +* hblk seems to be the line + porches length. +* The blank is set using a blanking packet (4 bytes + 4 bytes +* + payload + 2 bytes). So minimal size is 10 bytes +*/ +#define HBLK_PACKET_OVERHEAD 10 + hblk =max ((unsigned int )HBLK_PACKET_OVERHEAD , + (mode->htotal - (mode->hsync_end - mode->hsync_start)) * + Bpp -HBLK_PACKET_OVERHEAD ); + +/* +* The frontporch is set using a blanking packet (4 bytes + +* payload + 2 bytes). Its minimal size is therefore 6 bytes +*/ +#define HFP_PACKET_OVERHEAD 6 + hfp =max ((unsigned int )HFP_PACKET_OVERHEAD , + (mode->hsync_start - mode->hdisplay) * Bpp - +HFP_PACKET_OVERHEAD ); + + vblk =sun6i_dsi_get_timings_vblk (dsi, mode, hblk); + + timings->hsa = hsa; + timings->hbp = hbp; + timings->hblk = hblk; + timings->hfp = hfp; + timings->vblk = vblk; +} +static u16 sun6i_dsi_setup_inst_delay (struct sun6i_dsi *dsi,struct drm_display_mode *mode) {
@@ -506,52 +568,22 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, {struct mipi_dsi_device *device = dsi->device;unsigned int Bpp =mipi_dsi_pixel_format_to_bpp (device->format) /8 ; -u16 hbp, hfp, hsa, hblk, vblk; +struct sun6i_dsi_timings timings;size_t bytes;u8 *buffer;/* Do all timing calculations up front to allocate buffer space */ -/* -* A sync period is composed of a blanking packet (4 bytes + -* payload + 2 bytes) and a sync event packet (4 bytes). Its -* minimal size is therefore 10 bytes -*/ -#define HSA_PACKET_OVERHEAD 10 - hsa =max ((unsigned int )HSA_PACKET_OVERHEAD , - (mode->hsync_end - mode->hsync_start) * Bpp -HSA_PACKET_OVERHEAD ); +memset (&timings,0 ,sizeof (timings)); -/* -* The backporch is set using a blanking packet (4 bytes + -* payload + 2 bytes). Its minimal size is therefore 6 bytes -*/ -#define HBP_PACKET_OVERHEAD 6 - hbp =max ((unsigned int )HBP_PACKET_OVERHEAD , - (mode->htotal - mode->hsync_end) * Bpp -HBP_PACKET_OVERHEAD ); - -/* -* The frontporch is set using a blanking packet (4 bytes + -* payload + 2 bytes). Its minimal size is therefore 6 bytes -*/ -#define HFP_PACKET_OVERHEAD 6 - hfp =max ((unsigned int )HFP_PACKET_OVERHEAD , - (mode->hsync_start - mode->hdisplay) * Bpp - -HFP_PACKET_OVERHEAD ); - -/* -* hblk seems to be the line + porches length. -* The blank is set using a blanking packet (4 bytes + 4 bytes + -* payload + 2 bytes). So minimal size is 10 bytes -*/ -#define HBLK_PACKET_OVERHEAD 10 - hblk =max ((unsigned int )HBLK_PACKET_OVERHEAD , - (mode->htotal - (mode->hsync_end - mode->hsync_start)) * - Bpp -HBLK_PACKET_OVERHEAD ); - - vblk =sun6i_dsi_get_timings_vblk (dsi, mode, hblk); +if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + timings.hblk = (mode->hdisplay * Bpp); +else +sun6i_dsi_get_timings (dsi, mode, &timings);/* How many bytes do we need to send all payloads? */ - bytes =max_t (size_t,max (max (hfp, hblk),max (hsa, hbp)), vblk); + bytes =max_t (size_t,max (max (timings.hfp, timings.hblk), +max (timings.hsa, timings.hbp)), timings.vblk); buffer =kmalloc (bytes,GFP_KERNEL );if (WARN_ON (!buffer))return ;
@@ -590,33 +622,33 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,/* sync */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HSA0_REG , -sun6i_dsi_build_blk0_pkt (device->channel, hsa)); +sun6i_dsi_build_blk0_pkt (device->channel, timings.hsa));regmap_write (dsi->regs,SUN6I_DSI_BLK_HSA1_REG , -sun6i_dsi_build_blk1_pkt (0 , buffer, hsa)); +sun6i_dsi_build_blk1_pkt (0 , buffer, timings.hsa));/* backporch */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HBP0_REG , -sun6i_dsi_build_blk0_pkt (device->channel, hbp)); +sun6i_dsi_build_blk0_pkt (device->channel, timings.hbp));regmap_write (dsi->regs,SUN6I_DSI_BLK_HBP1_REG , -sun6i_dsi_build_blk1_pkt (0 , buffer, hbp)); +sun6i_dsi_build_blk1_pkt (0 , buffer, timings.hbp));/* frontporch */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HFP0_REG , -sun6i_dsi_build_blk0_pkt (device->channel, hfp)); +sun6i_dsi_build_blk0_pkt (device->channel, timings.hfp));regmap_write (dsi->regs,SUN6I_DSI_BLK_HFP1_REG , -sun6i_dsi_build_blk1_pkt (0 , buffer, hfp)); +sun6i_dsi_build_blk1_pkt (0 , buffer, timings.hfp));/* hblk */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HBLK0_REG , -sun6i_dsi_build_blk0_pkt (device->channel, hblk)); +sun6i_dsi_build_blk0_pkt (device->channel, timings.hblk));regmap_write (dsi->regs,SUN6I_DSI_BLK_HBLK1_REG , -sun6i_dsi_build_blk1_pkt (0 , buffer, hblk)); +sun6i_dsi_build_blk1_pkt (0 , buffer, timings.hblk));/* vblk */ regmap_write (dsi->regs,SUN6I_DSI_BLK_VBLK0_REG , -sun6i_dsi_build_blk0_pkt (device->channel, vblk)); +sun6i_dsi_build_blk0_pkt (device->channel, timings.vblk));regmap_write (dsi->regs,SUN6I_DSI_BLK_VBLK1_REG , -sun6i_dsi_build_blk1_pkt (0 , buffer, vblk)); +sun6i_dsi_build_blk1_pkt (0 , buffer, timings.vblk));kfree (buffer); }
Signature · 1 line
2.18.0.321.gffc6fa0e3
Re: [PATCH v2 03/12] drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
Quoted 6 lines · Jagan Teki
Burst mode display timings are different from convectional video mode so update the horizontal and vertical timings.
Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
Quoted 8 lines
dsi_hsa= 0;dsi_hbp= 0;dsi_hact= x*dsi_pixel_bits[format]/8;dsi_hblk=dsi_hact;dsi_hfp= 0;dsi_vblk= 0;
How is that matching the code you have in the rest of your patch?
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 03/12] drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
Quoted 15 lines · Maxime Ripard
Quoted 13 lines · Jagan Teki
Burst mode display timings are different from convectional video mode so update the horizontal and vertical timings.
Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
dsi_hsa= 0;dsi_hbp= 0;dsi_hact= x*dsi_pixel_bits[format]/8;dsi_hblk=dsi_hact;dsi_hfp= 0;dsi_vblk= 0;
Quoted 3 lines
Quoted 1 line
How is that matching the code you have in the rest of your patch?
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ timings.hblk = (mode->hdisplay * Bpp);
+ else
+ sun6i_dsi_get_timings(dsi, mode, &timings);
It's again your request to "keep the couple of function to make more readable"
Re: [PATCH v2 03/12] drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
Quoted 25 lines · Jagan Teki
Quoted 18 lines · Maxime Ripard
Quoted 6 lines · Jagan Teki
Burst mode display timings are different from convectional video mode so update the horizontal and vertical timings.
Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)Quoted 8 lines
dsi_hsa= 0;dsi_hbp= 0;dsi_hact= x*dsi_pixel_bits[format]/8;dsi_hblk=dsi_hact;dsi_hfp= 0;dsi_vblk= 0;How is that matching the code you have in the rest of your patch?
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +4
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + timings.hblk = (mode->hdisplay * Bpp); +else +sun6i_dsi_get_timings (dsi, mode, &timings);
Quoted 2 lines
It's again your request to "keep the couple of function to make more readable"
That function in particular doesn't make it much more readable, but more importantly, your commit log doesn't match what you code does.
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 03/12] drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
Quoted 27 lines · Maxime Ripard
Quoted 25 lines · Jagan Teki
Quoted 18 lines · Maxime Ripard
Quoted 6 lines · Jagan Teki
Burst mode display timings are different from convectional video mode so update the horizontal and vertical timings.
Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)Quoted 8 lines
dsi_hsa= 0;dsi_hbp= 0;dsi_hact= x*dsi_pixel_bits[format]/8;dsi_hblk=dsi_hact;dsi_hfp= 0;dsi_vblk= 0;How is that matching the code you have in the rest of your patch?
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +4
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + timings.hblk = (mode->hdisplay * Bpp); +else +sun6i_dsi_get_timings (dsi, mode, &timings);
Quoted 5 lines
Quoted 2 lines
It's again your request to "keep the couple of function to make more readable"
That function in particular doesn't make it much more readable, but more importantly, your commit log doesn't match what you code does.
May be I can update the commit message if the function is OK. for burst most of the timings are 0 so I used structure with memset to keep not assigning 0's explicitly. otherwise do you have any suggestions, please let me know.
Re: [PATCH v2 03/12] drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
Quoted 31 lines · Jagan Teki
Quoted 30 lines · Maxime Ripard
Quoted 27 lines · Jagan Teki
Quoted 18 lines · Maxime Ripard
Quoted 6 lines · Jagan Teki
Burst mode display timings are different from convectional video mode so update the horizontal and vertical timings.
Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)Quoted 8 lines
dsi_hsa= 0;dsi_hbp= 0;dsi_hact= x*dsi_pixel_bits[format]/8;dsi_hblk=dsi_hact;dsi_hfp= 0;dsi_vblk= 0;How is that matching the code you have in the rest of your patch?
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +4
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + timings.hblk = (mode->hdisplay * Bpp); +else +sun6i_dsi_get_timings (dsi, mode, &timings);It's again your request to "keep the couple of function to make more readable"
Quoted 7 lines
Quoted 2 lines
That function in particular doesn't make it much more readable, but more importantly, your commit log doesn't match what you code does.
May be I can update the commit message if the function is OK. for burst most of the timings are 0 so I used structure with memset to keep not assigning 0's explicitly. otherwise do you have any suggestions, please let me know.
Drop the part that move the timings setup to another function in this patch.
Thanks!
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerPATCH v2 4/12 drm/sun4i: sun6i_mipi_dsi: Simplify drq set to support all modes
In reply to Jagan TekiAllwinner MIPI DSI DRQ set value can be varied with respective video modes.
- burst mode the set value is always 0
- video modes whose front porch greater than 20, the set value can be computed based front porch and bpp.
- video modes whose front porch is not greater than 20, the set value is simply 0
This patch simplifies existing drq set value code by grouping into sun6i_dsi_get_drq and support all video modes.
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +23 -15
@@ -363,6 +363,26 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, SUN6I_DSI_INST_JUMP_CFG_NUM(1)); }; +static int sun6i_dsi_get_drq (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +int drq =0 ; + +if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +return drq; + +if ((mode->hsync_start - mode->hdisplay) >20 ) { +/* Maaaaaagic */ +u16 drq = (mode->hsync_start - mode->hdisplay) -20 ; + + drq *=mipi_dsi_pixel_format_to_bpp (device->format); + drq /=32 ; + } + +return drq; +} +static u16 sun6i_dsi_get_timings_vblk (struct sun6i_dsi *dsi,struct drm_display_mode *mode,u16 hblk) {
@@ -478,21 +498,9 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_burst (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -struct mipi_dsi_device *device = dsi->device; -u32 val =0 ; - -if ((mode->hsync_start - mode->hdisplay) >20 ) { -/* Maaaaaagic */ -u16 drq = (mode->hsync_start - mode->hdisplay) -20 ; - - drq *=mipi_dsi_pixel_format_to_bpp (device->format); - drq /=32 ; - - val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE | -SUN6I_DSI_TCON_DRQ_SET (drq)); - } - -regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , val); +regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , +SUN6I_DSI_TCON_DRQ_ENABLE_MODE | +SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode))); } static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
Signature · 1 line
2.18.0.321.gffc6fa0e3
Re: [PATCH v2 04/12] drm/sun4i: sun6i_mipi_dsi: Simplify drq set to support all modes
Quoted 21 lines · Jagan Teki
Allwinner MIPI DSI DRQ set value can be varied with respective video modes.
- burst mode the set value is always 0
- video modes whose front porch greater than 20, the set value can be computed based front porch and bpp.
- video modes whose front porch is not greater than 20, the set value is simply 0This patch simplifies existing drq set value code by grouping into
sun6i_dsi_get_drqand support all video modes.--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +0
-0
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 370
Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0@@ -363,6 +363,26 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, SUN6I_DSI_INST_JUMP_CFG_NUM(1)); }; +static int sun6i_dsi_get_drq (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +int drq =0 ;
So, here, you declaring a variable called drq, set to 0.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 372
Quoted 2 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +return drq;
That you return here. You could just return 0, to be clearer.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 377
Quoted 3 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-0+if ((mode->hsync_start - mode->hdisplay) >20 ) { +/* Maaaaaagic */ +u16 drq = (mode->hsync_start - mode->hdisplay) -20 ;
You re-declare a variable with the same name here, but a different type....
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 383
Quoted 5 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0+ drq *=mipi_dsi_pixel_format_to_bpp (device->format); + drq /=32 ; + } + +return drq;
And then return the first one? How is that even working?
Quoted 16 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +1
-8+static u16 sun6i_dsi_get_timings_vblk (struct sun6i_dsi *dsi,struct drm_display_mode *mode,u16 hblk) {@@ -478,21 +498,9 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_burst (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -struct mipi_dsi_device *device = dsi->device; -u32 val =0 ; - -if ((mode->hsync_start - mode->hdisplay) >20 ) { -/* Maaaaaagic */ -u16 drq = (mode->hsync_start - mode->hdisplay) -20 ; - - drq *=mipi_dsi_pixel_format_to_bpp (device->format);
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi, · line 503
Quoted 10 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-7- drq /=32 ; - - val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE | -SUN6I_DSI_TCON_DRQ_SET (drq)); - } - -regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , val); +regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , +SUN6I_DSI_TCON_DRQ_ENABLE_MODE | +SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode)));
On top of that, you now enable the DRQ stuff all the time, while it was conditional before.
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 04/12] drm/sun4i: sun6i_mipi_dsi: Simplify drq set to support all modes
Quoted 46 lines · Maxime Ripard
Quoted 21 lines · Jagan Teki
Allwinner MIPI DSI DRQ set value can be varied with respective video modes.
- burst mode the set value is always 0
- video modes whose front porch greater than 20, the set value can be computed based front porch and bpp.
- video modes whose front porch is not greater than 20, the set value is simply 0This patch simplifies existing drq set value code by grouping into
sun6i_dsi_get_drqand support all video modes.Signed-off-by Jagan Teki <[email protected]>--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +0
-0drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 370
Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0@@ -363,6 +363,26 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, SUN6I_DSI_INST_JUMP_CFG_NUM(1)); }; +static int sun6i_dsi_get_drq (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +int drq =0 ;So, here, you declaring a variable called drq, set to 0.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 372
Quoted 2 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +return drq;That you return here. You could just return 0, to be clearer.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 377
Quoted 3 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-0+if ((mode->hsync_start - mode->hdisplay) >20 ) { +/* Maaaaaagic */ +u16 drq = (mode->hsync_start - mode->hdisplay) -20 ;You re-declare a variable with the same name here, but a different type....
Quoted 7 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 383
Quoted 5 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0+ drq *=mipi_dsi_pixel_format_to_bpp (device->format); + drq /=32 ; + } + +return drq;And then return the first one? How is that even working?
Will fix this.
Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +1
-12+static u16 sun6i_dsi_get_timings_vblk (struct sun6i_dsi *dsi,struct drm_display_mode *mode,u16 hblk) {@@ -478,21 +498,9 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_burst (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -struct mipi_dsi_device *device = dsi->device; -u32 val =0 ; - -if ((mode->hsync_start - mode->hdisplay) >20 ) { -/* Maaaaaagic */ -u16 drq = (mode->hsync_start - mode->hdisplay) -20 ; - - drq *=mipi_dsi_pixel_format_to_bpp (device->format); - drq /=32 ; - - val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE | -SUN6I_DSI_TCON_DRQ_SET (drq));
Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi, · line 503
Quoted 6 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-3- } - -regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , val); +regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , +SUN6I_DSI_TCON_DRQ_ENABLE_MODE | +SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode)));On top of that, you now enable the DRQ stuff all the time, while it
Earlier the val value is ENABLE_MODE ORed with drq value. for the condition drq is computed in if block otherwise the val is 0. So as I explained in commit message the drq value is 0
- for video modes whose front porch is not greater than 20 and
- for burst mode the val
ie reason I mode it common.
Re: [PATCH v2 04/12] drm/sun4i: sun6i_mipi_dsi: Simplify drq set to support all modes
Quoted 53 lines · Jagan Teki
Quoted 52 lines · Maxime Ripard
Quoted 21 lines · Jagan Teki
Allwinner MIPI DSI DRQ set value can be varied with respective video modes.
- burst mode the set value is always 0
- video modes whose front porch greater than 20, the set value can be computed based front porch and bpp.
- video modes whose front porch is not greater than 20, the set value is simply 0This patch simplifies existing drq set value code by grouping into
sun6i_dsi_get_drqand support all video modes.--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +0
-0drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 370
Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0@@ -363,6 +363,26 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, SUN6I_DSI_INST_JUMP_CFG_NUM(1)); }; +static int sun6i_dsi_get_drq (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +int drq =0 ;So, here, you declaring a variable called drq, set to 0.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 372
Quoted 2 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +return drq;That you return here. You could just return 0, to be clearer.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 377
Quoted 3 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-0+if ((mode->hsync_start - mode->hdisplay) >20 ) { +/* Maaaaaagic */ +u16 drq = (mode->hsync_start - mode->hdisplay) -20 ;You re-declare a variable with the same name here, but a different type....
Quoted 5 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0+ drq *=mipi_dsi_pixel_format_to_bpp (device->format); + drq /=32 ; + } + +return drq;
Quoted 3 lines
Quoted 1 line
And then return the first one? How is that even working?
Will fix this.
I don't want you to only fix this, I also want you to contribute code that is A) useful, B) tested.
Quoted 28 lines
Quoted 19 lines
Quoted 19 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +0
-12static u16 sun6i_dsi_get_timings_vblk (struct sun6i_dsi *dsi,struct drm_display_mode *mode,u16 hblk) {@@ -478,21 +498,9 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_burst (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -struct mipi_dsi_device *device = dsi->device; -u32 val =0 ; - -if ((mode->hsync_start - mode->hdisplay) >20 ) { -/* Maaaaaagic */ -u16 drq = (mode->hsync_start - mode->hdisplay) -20 ; - - drq *=mipi_dsi_pixel_format_to_bpp (device->format); - drq /=32 ; - - val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE | -SUN6I_DSI_TCON_DRQ_SET (drq));Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi, · line 503
Quoted 6 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-3- } - -regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , val); +regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , +SUN6I_DSI_TCON_DRQ_ENABLE_MODE | +SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode)));On top of that, you now enable the DRQ stuff all the time, while it
Quoted 7 lines
Earlier the val value is
ENABLE_MODEORed with drq value. for the condition drq is computed in if block otherwise the val is 0. So as I explained in commit message the drq value is 0
- for video modes whose front porch is not greater than 20 and
- for burst mode the valie reason I mode it common.
The previous code was enabling it if the front porch was larger than 20 only. You enable it all the time now, and you never explain why.
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 04/12] drm/sun4i: sun6i_mipi_dsi: Simplify drq set to support all modes
Quoted 55 lines · Maxime Ripard
Quoted 53 lines · Jagan Teki
Quoted 52 lines · Maxime Ripard
Quoted 21 lines · Jagan Teki
Allwinner MIPI DSI DRQ set value can be varied with respective video modes.
- burst mode the set value is always 0
- video modes whose front porch greater than 20, the set value can be computed based front porch and bpp.
- video modes whose front porch is not greater than 20, the set value is simply 0This patch simplifies existing drq set value code by grouping into
sun6i_dsi_get_drqand support all video modes.--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 38 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +0
-0drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 370
Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0@@ -363,6 +363,26 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, SUN6I_DSI_INST_JUMP_CFG_NUM(1)); }; +static int sun6i_dsi_get_drq (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +int drq =0 ;So, here, you declaring a variable called drq, set to 0.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 372
Quoted 2 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0+if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +return drq;That you return here. You could just return 0, to be clearer.
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, · line 377
Quoted 3 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-0+if ((mode->hsync_start - mode->hdisplay) >20 ) { +/* Maaaaaagic */ +u16 drq = (mode->hsync_start - mode->hdisplay) -20 ;You re-declare a variable with the same name here, but a different type....
Quoted 5 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +5
-0+ drq *=mipi_dsi_pixel_format_to_bpp (device->format); + drq /=32 ; + } + +return drq;
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
And then return the first one? How is that even working?
Will fix this.
I don't want you to only fix this, I also want you to contribute code that is A) useful, B) tested.
It was tested in burst mode panel, the same added in the series. It worked because burst mode need 0 drq rate.
Quoted 35 lines
Quoted 35 lines
Quoted 20 lines
Quoted 20 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +0
-12static u16 sun6i_dsi_get_timings_vblk (struct sun6i_dsi *dsi,struct drm_display_mode *mode,u16 hblk) {@@ -478,21 +498,9 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_burst (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -struct mipi_dsi_device *device = dsi->device; -u32 val =0 ; - -if ((mode->hsync_start - mode->hdisplay) >20 ) { -/* Maaaaaagic */ -u16 drq = (mode->hsync_start - mode->hdisplay) -20 ; - - drq *=mipi_dsi_pixel_format_to_bpp (device->format); - drq /=32 ; - - val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE | -SUN6I_DSI_TCON_DRQ_SET (drq));Quoted 8 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi, · line 503
Quoted 6 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +3
-3- } - -regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , val); +regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , +SUN6I_DSI_TCON_DRQ_ENABLE_MODE | +SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode)));On top of that, you now enable the DRQ stuff all the time, while it
Earlier the val value is
ENABLE_MODEORed with drq value. for the condition drq is computed in if block otherwise the val is 0. So as I explained in commit message the drq value is 0
- for video modes whose front porch is not greater than 20 and
- for burst mode the val
Quoted 4 lines
Quoted 1 line
ie reason I mode it common.
The previous code was enabling it if the front porch was larger than 20 only. You enable it all the time now, and you never explain why.
Got it. Loo like I was confused to test these two separate series in separate panels and missed something. Is it Ok to combine all dsi changes together and send it in next version.
Jagan Teki
maintainerPATCH v2 5/12 drm/sun4i: tcon: Export get tcon0 routine
In reply to Jagan TekiSometimes tcon attributes like tcon divider, clock rate etc are needed in interface drivers like DSI. So for such cases interface driver must probe the respective tcon and get the attributes. Instead of probing tcon explictly, better export the existing sun5i_get_tcon0 so-that the relevant interface can reuse.
--- drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 ++- drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/sun4i/sun4i_tcon.c +2 -1
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(sun4i_tcon_enable_vblank);* are located in TCON0. This helper returns a pointer to TCON0's * sun4i_tcon structure, or NULL if not found. */ -static struct sun4i_tcon *sun4i_get_tcon0 (struct drm_device *drm) +struct sun4i_tcon *sun4i_get_tcon0 (struct drm_device *drm) {struct sun4i_drv *drv = drm->dev_private;struct sun4i_tcon *tcon;
@@ -235,6 +235,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)return NULL ; } +EXPORT_SYMBOL (sun4i_get_tcon0);void sun4i_tcon_set_mux (struct sun4i_tcon *tcon,int channel,const struct drm_encoder *encoder)
drivers/gpu/drm/sun4i/sun4i_tcon.h +1 -0
@@ -273,6 +273,7 @@ struct sun4i_tcon {struct drm_bridge *sun4i_tcon_find_bridge (struct device_node *node);struct drm_panel *sun4i_tcon_find_panel (struct device_node *node); +struct sun4i_tcon *sun4i_get_tcon0 (struct drm_device *drm);void sun4i_tcon_enable_vblank (struct sun4i_tcon *tcon,bool enable); void sun4i_tcon_mode_set(struct sun4i_tcon *tcon, const struct drm_encoder *encoder,
Signature · 1 line
2.18.0.321.gffc6fa0e3
Re: [PATCH v2 05/12] drm/sun4i: tcon: Export get tcon0 routine
Quoted 5 lines · Jagan Teki
Sometimes tcon attributes like tcon divider, clock rate etc are needed in interface drivers like DSI. So for such cases interface driver must probe the respective tcon and get the attributes. Instead of probing tcon explictly, better export the existing
sun5i_get_tcon0so-that the relevant interface can reuse.
That's not the name of the function you export.
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerPATCH v2 6/12 drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
In reply to Jagan TekiProbe tcon0 during dsi_bind, so-that the tcon attributes like divider value, clock rate can get whenever it need.
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++ drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 + 2 files changed, 8 insertions(+)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +7 -0
@@ -25,6 +25,7 @@#include <drm/drm_panel.h> #include "sun4i_drv.h" +#include "sun4i_tcon.h" #include "sun6i_mipi_dsi.h" #include <video/mipi_display.h>
@@ -1007,6 +1008,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,struct drm_device *drm = data;struct sun4i_drv *drv = drm->dev_private;struct sun6i_dsi *dsi =dev_get_drvdata (dev); +struct sun4i_tcon *tcon0 =sun4i_get_tcon0 (drm);int ret;if (!dsi->panel)
@@ -1014,6 +1016,11 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master, dsi->drv = drv; +if (!tcon0) +return -EPROBE_DEFER ; + + dsi->tcon = tcon0; +drm_encoder_helper_add (&dsi->encoder, &sun6i_dsi_enc_helper_funcs); ret = drm_encoder_init(drm,
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h +1 -0
@@ -40,6 +40,7 @@ struct sun6i_dsi {struct device *dev;struct sun4i_drv *drv; +struct sun4i_tcon *tcon;struct mipi_dsi_device *device;struct drm_panel *panel;const struct sun6i_dsi_variant *variant;
Signature · 1 line
2.18.0.321.gffc6fa0e3
Re: [PATCH v2 06/12] drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
Quoted 30 lines · Jagan Teki
Probe tcon0 during
dsi_bind, so-that the tcon attributes like divider value, clock rate can get whenever it need.--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++ drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 + 2 files changed, 8 insertions(+)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0@@ -25,6 +25,7 @@#include <drm/drm_panel.h> #include "sun4i_drv.h" +#include "sun4i_tcon.h" #include "sun6i_mipi_dsi.h" #include <video/mipi_display.h> @@ -1007,6 +1008,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,struct drm_device *drm = data;struct sun4i_drv *drv = drm->dev_private;struct sun6i_dsi *dsi =dev_get_drvdata (dev); +struct sun4i_tcon *tcon0 =sun4i_get_tcon0 (drm);int ret;if (!dsi->panel)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static int sun6i_dsi_bind(struct device *dev, struct device *master, · line 1020
Quoted 5 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0@@ -1014,6 +1016,11 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master, dsi->drv = drv; +if (!tcon0) +return -EPROBE_DEFER ;
You can't fall in that condition. The component framework won't call bind unless every components have been probed.
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerRe: [PATCH v2 06/12] drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
Quoted 33 lines · Maxime Ripard
Quoted 31 lines · Jagan Teki
Probe tcon0 during
dsi_bind, so-that the tcon attributes like divider value, clock rate can get whenever it need.--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++ drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 + 2 files changed, 8 insertions(+)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0@@ -25,6 +25,7 @@#include <drm/drm_panel.h> #include "sun4i_drv.h" +#include "sun4i_tcon.h" #include "sun6i_mipi_dsi.h" #include <video/mipi_display.h> @@ -1007,6 +1008,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,struct drm_device *drm = data;struct sun4i_drv *drv = drm->dev_private;struct sun6i_dsi *dsi =dev_get_drvdata (dev); +struct sun4i_tcon *tcon0 =sun4i_get_tcon0 (drm);int ret;if (!dsi->panel)@@ -1014,6 +1016,11 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,
Quoted 7 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static int sun6i_dsi_bind(struct device *dev, struct device *master, · line 1020
Quoted 4 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0dsi->drv = drv; +if (!tcon0) +return -EPROBE_DEFER ;You can't fall in that condition. The component framework won't call bind unless every components have been probed.
Since tcon0 is already probed is it? if so I can return -EINVAL is it ok?
Re: [PATCH v2 06/12] drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
Quoted 36 lines · Jagan Teki
Quoted 35 lines · Maxime Ripard
Quoted 33 lines · Jagan Teki
Probe tcon0 during
dsi_bind, so-that the tcon attributes like divider value, clock rate can get whenever it need.--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++ drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 + 2 files changed, 8 insertions(+)drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0@@ -25,6 +25,7 @@#include <drm/drm_panel.h> #include "sun4i_drv.h" +#include "sun4i_tcon.h" #include "sun6i_mipi_dsi.h" #include <video/mipi_display.h> @@ -1007,6 +1008,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,struct drm_device *drm = data;struct sun4i_drv *drv = drm->dev_private;struct sun6i_dsi *dsi =dev_get_drvdata (dev); +struct sun4i_tcon *tcon0 =sun4i_get_tcon0 (drm);int ret;if (!dsi->panel)@@ -1014,6 +1016,11 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master, dsi->drv = drv;
Quoted 7 lines
Quoted 5 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c static int sun6i_dsi_bind(struct device *dev, struct device *master, · line 1020
Quoted 2 lines
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +2
-0+if (!tcon0) +return -EPROBE_DEFER ;You can't fall in that condition. The component framework won't call bind unless every components have been probed.
Since tcon0 is already probed is it? if so I can return
-EINVALis it ok?
Sounds good yes.
Maxime
Signature · 3 lines
Maxime Ripard, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Jagan Teki
maintainerPATCH v2 7/12 drm/sun4i: sun6i_mipi_dsi: Setup burst mode
In reply to Jagan TekiSetting up burst mode display would require to compute
- Horizontal timing edge values to fill burst drq register
- Line, sync values to fill burst line register
Since there is no direct documentation for these computations the edge and line formulas are taken from BSP code (from linux-sunxi/ drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
line_num = panel->lcd_ht*dsi_pixel_bits[panel->lcd_dsi_format]/
(8*panel->lcd_dsi_lane); edge1 = sync_point+(panel->lcd_x+panel->lcd_hbp+20)* dsi_pixel_bits[panel->lcd_dsi_format] /(8*panel->lcd_dsi_lane);
edge1 = (edge1>line_num)?line_num:edge1;
edge0 = edge1+(panel->lcd_x+40)*tcon_div/8;
edge0 = (edge0>line_num)?(edge0-line_num):1;
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 72 ++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +68 -4
@@ -364,6 +364,41 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi, SUN6I_DSI_INST_JUMP_CFG_NUM(1)); }; +static u32 sun6i_dsi_get_edge1 (struct sun6i_dsi *dsi, +struct drm_display_mode *mode,u32 sync_point) +{ +struct mipi_dsi_device *device = dsi->device; +unsigned int bpp =mipi_dsi_pixel_format_to_bpp (device->format); +u32 hact_sync_bp; + +/* Horizontal timings duration excluding front porch */ + hact_sync_bp = (mode->hdisplay + mode->htotal - mode->hsync_start); + +return (sync_point + ((hact_sync_bp +20 ) * bpp / (8 * device->lanes))); +} + +static u32 sun6i_dsi_get_edge0 (struct sun6i_dsi *dsi, +struct drm_display_mode *mode,u32 edge1) +{ +struct sun4i_tcon *tcon = dsi->tcon; +unsigned long dclk_rate, dclk_parent_rate, tcon0_div; + + dclk_rate =clk_get_rate (tcon->dclk); + dclk_parent_rate =clk_get_rate (clk_get_parent (tcon->dclk)); + tcon0_div = dclk_parent_rate / dclk_rate; + +return (edge1 + (mode->hdisplay +40 ) * tcon0_div /8 ); +} + +static u32 sun6i_dsi_get_line_num (struct sun6i_dsi *dsi, +struct drm_display_mode *mode) +{ +struct mipi_dsi_device *device = dsi->device; +unsigned int bpp =mipi_dsi_pixel_format_to_bpp (device->format); + +return (mode->htotal * bpp / (8 * device->lanes)); +} +static int sun6i_dsi_get_drq (struct sun6i_dsi *dsi,struct drm_display_mode *mode) {
@@ -499,9 +534,32 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,static void sun6i_dsi_setup_burst (struct sun6i_dsi *dsi,struct drm_display_mode *mode) { -regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , -SUN6I_DSI_TCON_DRQ_ENABLE_MODE | -SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode))); +struct mipi_dsi_device *device = dsi->device; +u32 sync_point =40 ; +u32 line_num =sun6i_dsi_get_line_num (dsi, mode); +u32 edge1 =sun6i_dsi_get_edge1 (dsi, mode, sync_point); +u32 edge0 =sun6i_dsi_get_edge0 (dsi, mode, edge1); +u32 val; + +if (edge1 > line_num) + edge1 = line_num; + +if (edge0 > line_num) + edge0 -= line_num; +else + edge0 =1 ; + +regmap_write (dsi->regs,SUN6I_DSI_BURST_DRQ_REG , +SUN6I_DSI_BURST_DRQ_EDGE1 (edge1) | +SUN6I_DSI_BURST_DRQ_EDGE0 (edge0)); +regmap_write (dsi->regs,SUN6I_DSI_BURST_LINE_REG , +SUN6I_DSI_BURST_LINE_NUM (line_num) | +SUN6I_DSI_BURST_LINE_SYNC_POINT (sync_point)); + +/* enable burst mode */ +regmap_read (dsi->regs,SUN6I_DSI_BASIC_CTL_REG , &val); + val |=SUN6I_DSI_BASIC_CTL_VIDEO_BURST ; +regmap_write (dsi->regs,SUN6I_DSI_BASIC_CTL_REG , val); } static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
@@ -726,7 +784,13 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION | SUN6I_DSI_BASIC_CTL1_VIDEO_MODE); -sun6i_dsi_setup_burst (dsi, mode); +regmap_write (dsi->regs,SUN6I_DSI_TCON_DRQ_REG , +SUN6I_DSI_TCON_DRQ_ENABLE_MODE | +SUN6I_DSI_TCON_DRQ_SET (sun6i_dsi_get_drq (dsi, mode))); + +if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +sun6i_dsi_setup_burst (dsi, mode); +sun6i_dsi_setup_inst_loop (dsi, mode);sun6i_dsi_setup_format (dsi, mode);sun6i_dsi_setup_timings (dsi, mode);
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerPATCH v2 8/12 drm/sun4i: sun6i_mipi_dsi: Enable 2byte trail for 4-lane burst mode
In reply to Jagan TekiFor 4-lane, burst mode panels would need to enable 2byte trail_fill along with filling trail_env in dsi base control register.
Similar reference code avialable in BSP (from linux-sunxi/ drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
if (panel->lcd_dsi_lane == 4)
{
dsi_dev[sel]->dsi_basic_ctl.bits.trail_inv = 0xc;
dsi_dev[sel]->dsi_basic_ctl.bits.trail_fill = 1;
}
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +6 -0
@@ -34,6 +34,8 @@#define SUN6I_DSI_CTL_EN BIT(0)#define SUN6I_DSI_BASIC_CTL_REG 0x00c +#define SUN6I_DSI_BASIC_CTL_TRAIL_INV (n) (((n) & 0xf) << 4) +#define SUN6I_DSI_BASIC_CTL_TRAIL_FILL BIT(3)#define SUN6I_DSI_BASIC_CTL_HBP_DIS BIT(2)#define SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS BIT(1)#define SUN6I_DSI_BASIC_CTL_VIDEO_BURST BIT(0)
@@ -559,6 +561,10 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,/* enable burst mode */ regmap_read (dsi->regs,SUN6I_DSI_BASIC_CTL_REG , &val); val |=SUN6I_DSI_BASIC_CTL_VIDEO_BURST ; +if (device->lanes ==4 ) { + val |=SUN6I_DSI_BASIC_CTL_TRAIL_INV (0xc ); + val |=SUN6I_DSI_BASIC_CTL_TRAIL_FILL ; + }regmap_write (dsi->regs,SUN6I_DSI_BASIC_CTL_REG , val); }
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerPATCH v2 9/12 drm/sun4i: sun6i_mipi_dsi: Enable burst mode HBP, HSA_HSE
In reply to Jagan TekiHorizontal back porch, sync active and sync end bits are needed to disable for burst mode panel operations.
So, disable them via dsi base control register.
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +9 -3
@@ -644,15 +644,21 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,struct sun6i_dsi_timings timings;size_t bytes;u8 *buffer; +u32 val =0 ;/* Do all timing calculations up front to allocate buffer space */ memset (&timings,0 ,sizeof (timings)); -if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) +if (device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) { timings.hblk = (mode->hdisplay * Bpp); -else + +regmap_read (dsi->regs,SUN6I_DSI_BASIC_CTL_REG , &val); + val |=SUN6I_DSI_BASIC_CTL_HBP_DIS ; + val |=SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS ; + }else {sun6i_dsi_get_timings (dsi, mode, &timings); + }/* How many bytes do we need to send all payloads? */ bytes = max_t(size_t, max(max(timings.hfp, timings.hblk),
@@ -661,7 +667,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,if (WARN_ON (!buffer))return ; -regmap_write (dsi->regs,SUN6I_DSI_BASIC_CTL_REG ,0 ); +regmap_write (dsi->regs,SUN6I_DSI_BASIC_CTL_REG , val); regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG, sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_START,
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerPATCH v2 10/12 dt-bindings: panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
In reply to Jagan TekiFeiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add dt-bingings for it.
--- .../display/panel/feiyang,fy07024di26a30d.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt
Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt new file +20 -0
@@ -0,0 +1,20 @@ +Feiyang FY07024DI26A30-D 7" MIPI-DSI LCD Panel + +Required properties: +- compatible: must be "feiyang,fy07024di26a30d" +- reg: DSI virtual channel used by that screen +- avdd-supply: analog regulator dc1 switch +- dvdd-supply: 3v3 digital regulator +- reset-gpios: a GPIO phandle for the reset pin + +Optional properties: +- backlight: phandle for the backlight control. + +panel@0 { + compatible = "feiyang,fy07024di26a30d"; + reg = <0>; + avdd-supply = <®_dc1sw>; + dvdd-supply = <®_dldo2>; + reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD24 */ + backlight = <&backlight>; +};
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerPATCH v2 11/12 drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
In reply to Jagan TekiFeiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
MAINTAINERS +6 -0
@@ -4620,6 +4620,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc S: Maintained F: drivers/gpu/drm/tve200/ +DRM DRIVER FOR FEIYANG FY07024DI26A30-D MIPI-DSI LCD PANELS +M: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org> +S: Maintained +F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt + DRM DRIVER FOR ILITEK ILI9225 PANELS M: David Lechner <david-nq/r/kbU++upp/[email protected]> S: Maintained
drivers/gpu/drm/panel/Kconfig +9 -0
@@ -47,6 +47,15 @@ config DRM_PANEL_SIMPLE that it can be automatically turned off when the panel goes into a low power state. +config DRM_PANEL_FEIYANG_FY07024DI26A30D + tristate "Feiyang FY07024DI26A30-D MIPI-DSI LCD panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Feiyang FY07024DI26A30-D MIPI-DSI interface. + config DRM_PANEL_ILITEK_IL9322 tristate "Ilitek ILI9322 320x240 QVGA panels" depends on OF && SPI
drivers/gpu/drm/panel/Makefile +1 -0
@@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o obj-$(CONFIG_DRM_PANEL_BANANAPI_S070WV20_ICN6211) += panel-bananapi-s070wv20-icn6211.o obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o +obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +286 -0
286 lines not on this page · raw message
Signature · 1 line
2.18.0.321.gffc6fa0e3
Jagan Teki
maintainerRe: [PATCH v2 11/12] drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
Hi Thierry and David,
Quoted 38 lines · Jagan Teki
Feiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.cMAINTAINERS +6
-0@@ -4620,6 +4620,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc S: Maintained F: drivers/gpu/drm/tve200/ +DRM DRIVER FOR FEIYANG FY07024DI26A30-D MIPI-DSI LCD PANELS +M: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org> +S: Maintained +F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt + DRM DRIVER FOR ILITEK ILI9225 PANELS M: David Lechner <david-nq/r/kbU++upp/[email protected]> S: Maintaineddrivers/gpu/drm/panel/Kconfig +0
-0@@ -47,6 +47,15 @@ config DRM_PANEL_SIMPLE that it can be automatically turned off when the panel goes into a low power state.
drivers/gpu/drm/panel/Kconfig config DRM_PANEL_SIMPLE · line 58
Quoted 10 lines
drivers/gpu/drm/panel/Kconfig +9
-0+config DRM_PANEL_FEIYANG_FY07024DI26A30D + tristate "Feiyang FY07024DI26A30-D MIPI-DSI LCD panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Feiyang FY07024DI26A30-D MIPI-DSI interface. +
Any comments on this?
Re: [PATCH v2 11/12] drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
In reply to Jagan TekiQuoted 109 lines · Jagan Teki
Feiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
Signed-off-by Jagan Teki <[email protected]>--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.cMAINTAINERS +6
-0@@ -4620,6 +4620,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc S: Maintained F: drivers/gpu/drm/tve200/ +DRM DRIVER FOR FEIYANG FY07024DI26A30-D MIPI-DSI LCD PANELS +M: Jagan Teki <[email protected]> +S: Maintained +F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt + DRM DRIVER FOR ILITEK ILI9225 PANELS M: David Lechner <[email protected]> S: Maintaineddrivers/gpu/drm/panel/Kconfig +9
-0@@ -47,6 +47,15 @@ config DRM_PANEL_SIMPLE that it can be automatically turned off when the panel goes into a low power state. +config DRM_PANEL_FEIYANG_FY07024DI26A30D + tristate "Feiyang FY07024DI26A30-D MIPI-DSI LCD panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Feiyang FY07024DI26A30-D MIPI-DSI interface. + config DRM_PANEL_ILITEK_IL9322 tristate "Ilitek ILI9322 320x240 QVGA panels" depends on OF && SPIdrivers/gpu/drm/panel/Makefile +1
-0@@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o obj-$(CONFIG_DRM_PANEL_BANANAPI_S070WV20_ICN6211) += panel-bananapi-s070wv20-icn6211.o obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o +obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.odrivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +41
-0@@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Amarula Solutions +* Author: Jagan Teki <[email protected]> +*/ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_device.h> + +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> + +#include <drm/drmP.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> + +struct feiyang { +struct drm_panel panel; +struct mipi_dsi_device *dsi; + +struct backlight_device *backlight; +struct regulator *dvdd; +struct regulator *avdd; +struct gpio_desc *reset; +}; + +static inline struct feiyang *panel_to_feiyang (struct drm_panel *panel) +{ + return container_of(panel, struct feiyang, panel); +} + +struct feiyang_init_cmd { +size_t len; +const char *data; +}; + +#define FY07024DI26A30D (...) { \ + .len = sizeof((char[]){__VA_ARGS__}), \ + .data = (char[]){__VA_ARGS__} }
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 51
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+ +static const struct feiyang_init_cmd feiyang_init_cmds[] = { +FY07024DI26A30D (0x80 ,0x58 ), +FY07024DI26A30D (0x81 ,0x47 ), +FY07024DI26A30D (0x82 ,0xD4 ), +FY07024DI26A30D (0x83 ,0x88 ), +FY07024DI26A30D (0x84 ,0xA9 ), +FY07024DI26A30D (0x85 ,0xC3 ), +FY07024DI26A30D (0x86 ,0x82 ), +};
These init cmds don't have to be so complicated. You've only got len == 2, so just hardcode it in and avoid the macro:
#define FEIYANG_INIT_CMD_LEN 2
struct feiyang_init_cmd {
u8 data[FEIYANG_INIT_CMD];
};static const struct feiyang_init_cmd feiyang_init_cmds[] = {
{ .data = { 0x80, 0x58 } },
...
};drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 64
Quoted 13 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +13
-0+ +static int feiyang_prepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +unsigned int i; +int ret; + + ret =regulator_enable (ctx->dvdd); +if (ret) +return ret; + +msleep (100 );
nit: You should do your best to correlate the sleeps with the timing parameters from the datasheet with a comment.
ie:
/* T1: > 100ms */
msleep(100);Quoted 11 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +11
-0+ + ret =regulator_enable (ctx->avdd); +if (ret) +return ret; + +msleep (20 ); + +gpiod_set_value (ctx->reset,1 ); +msleep (50 ); + +gpiod_set_value (ctx->reset,0 );
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 85
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+msleep (20 ); + +gpiod_set_value (ctx->reset,1 ); +msleep (200 ); + +for (i =0 ; i <ARRAY_SIZE (feiyang_init_cmds); i++) { +const struct feiyang_init_cmd *cmd = + &feiyang_init_cmds[i]; + + ret =mipi_dsi_dcs_write_buffer (dsi, cmd->data, cmd->len);
ret = mipi_dsi_dcs_write_buffer(dsi, cmd->data,
FEIYANG_INIT_CMD_LEN);Quoted 15 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +15
-0+if (ret <0 ) +return ret; + } + +return 0 ; +} + +static int feiyang_enable (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); + +msleep (120 ); + +mipi_dsi_dcs_set_display_on (ctx->dsi); +backlight_enable (ctx->backlight);
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 110
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+ +return 0 ; +} + +static int feiyang_disable (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); + +backlight_disable (ctx->backlight); +return mipi_dsi_dcs_set_display_on (ctx->dsi);
set_display_on? You probably want set_display_off here :)
Quoted 18 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +18
-0+} + +static int feiyang_unprepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +int ret; + + ret =mipi_dsi_dcs_set_display_off (ctx->dsi); +if (ret <0 ) +DRM_DEV_ERROR (panel->dev,"failed to set display off: %d\n" , + ret); + + ret =mipi_dsi_dcs_enter_sleep_mode (ctx->dsi); +if (ret <0 ) +DRM_DEV_ERROR (panel->dev,"failed to enter sleep mode: %d\n" , + ret); + +msleep (100 );
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 138
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+ +regulator_disable (ctx->avdd); + +regulator_disable (ctx->dvdd); + +gpiod_set_value (ctx->reset,0 ); + +gpiod_set_value (ctx->reset,1 ); + +gpiod_set_value (ctx->reset,0 );
Presumably this reset line toggle isn't needed since the rails are already disabled?
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 145
Quoted 7 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +7
-0+ +return 0 ; +} + +static const struct drm_display_mode feiyang_default_mode = { + .clock =55000 , + .vrefresh =60 ,
This doesn't add up correctly. The pixel clock should be equal to:
(htotal * vtotal * vrefresh) / 1000
For this reason, we usually don't specify the refresh rate since it can be misleading. Your actual refresh rate with the pixel clock you specified is actually going to be 56.2Hz instead of the 60 you want.
If you can only generate a 55MHz pixel clock, consider reducing your blanking periods so the calculation above matches.
Quoted 20 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +20
-0+ + .hdisplay = 1024, + .hsync_start = 1024 + 396, + .hsync_end = 1024 + 396 + 20, + .htotal = 1024 + 396 + 20 + 100, + + .vdisplay = 600, + .vsync_start = 600 + 12, + .vsync_end = 600 + 12 + 2, + .vtotal = 600 + 12 + 2 + 21, +}; + +static int feiyang_get_modes (struct drm_panel *panel) +{ +struct drm_connector *connector = panel->connector; +struct feiyang *ctx =panel_to_feiyang (panel); +struct drm_display_mode *mode; + + mode =drm_mode_duplicate (panel->drm, &feiyang_default_mode); +if (!mode) {
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 175
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+DRM_DEV_ERROR (&ctx->dsi->dev,"failed to add mode %ux%ux@%u\n" , + feiyang_default_mode.hdisplay, + feiyang_default_mode.vdisplay, + feiyang_default_mode.vrefresh); +return -ENOMEM ; + } + +drm_mode_set_name (mode); + + mode->type =DRM_MODE_TYPE_DRIVER |DRM_MODE_TYPE_PREFERRED ;
Just set these above.
Quoted 114 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +111
-0+drm_mode_probed_add (connector, mode); + +return 1 ; +} + +static const struct drm_panel_funcs feiyang_funcs = { + .disable = feiyang_disable, + .unprepare = feiyang_unprepare, + .prepare = feiyang_prepare, + .enable = feiyang_enable, + .get_modes = feiyang_get_modes, +}; + +static int feiyang_dsi_probe (struct mipi_dsi_device *dsi) +{ +struct device_node *np; +struct feiyang *ctx; +int ret; + + ctx =devm_kzalloc (&dsi->dev,sizeof (*ctx),GFP_KERNEL ); +if (!ctx) +return -ENOMEM ; +mipi_dsi_set_drvdata (dsi, ctx); + ctx->dsi = dsi; + +drm_panel_init (&ctx->panel); + ctx->panel.dev = &dsi->dev; + ctx->panel.funcs = &feiyang_funcs; + + ctx->dvdd =devm_regulator_get (&dsi->dev,"dvdd" ); +if (IS_ERR (ctx->dvdd)) { +DRM_DEV_ERROR (&dsi->dev,"Couldn't get dvdd regulator\n" ); +return PTR_ERR (ctx->dvdd); + } + + ctx->avdd =devm_regulator_get (&dsi->dev,"avdd" ); +if (IS_ERR (ctx->avdd)) { +DRM_DEV_ERROR (&dsi->dev,"Couldn't get avdd regulator\n" ); +return PTR_ERR (ctx->avdd); + } + + ctx->reset =devm_gpiod_get (&dsi->dev,"reset" ,GPIOD_OUT_LOW ); +if (IS_ERR (ctx->reset)) { +DRM_DEV_ERROR (&dsi->dev,"Couldn't get our reset GPIO\n" ); +return PTR_ERR (ctx->reset); + } + + np =of_parse_phandle (dsi->dev.of_node,"backlight" ,0 ); +if (np) { + ctx->backlight =of_find_backlight_by_node (np); +of_node_put (np); + +if (!ctx->backlight) +return -EPROBE_DEFER ; + } + + ret =drm_panel_add (&ctx->panel); +if (ret <0 ) + goto put_backlight; + + dsi->mode_flags =MIPI_DSI_MODE_VIDEO_BURST ; + dsi->format =MIPI_DSI_FMT_RGB888 ; + dsi->lanes =4 ; + + ret =mipi_dsi_attach (dsi); +if (ret <0 ) + goto panel_remove; + +return ret; + +panel_remove: +drm_panel_remove (&ctx->panel); +put_backlight: +if (ctx->backlight) +put_device (&ctx->backlight->dev); + +return ret; +} + +static int feiyang_dsi_remove (struct mipi_dsi_device *dsi) +{ +struct feiyang *ctx =mipi_dsi_get_drvdata (dsi); + +mipi_dsi_detach (dsi); +drm_panel_remove (&ctx->panel); + +if (ctx->backlight) +put_device (&ctx->backlight->dev); + +return 0 ; +} + +static const struct of_device_id feiyang_of_match[] = { + { .compatible ="feiyang,fy07024di26a30d" , }, + { } +}; +MODULE_DEVICE_TABLE (of, feiyang_of_match); + +static struct mipi_dsi_driver feiyang_driver = { + .probe = feiyang_dsi_probe, + .remove = feiyang_dsi_remove, + .driver = { + .name ="feiyang-fy07024di26a30d" , + .of_match_table = feiyang_of_match, + }, +}; +module_mipi_dsi_driver (feiyang_driver); + +MODULE_AUTHOR ("Jagan Teki <[email protected]>" ); +MODULE_DESCRIPTION ("Feiyang FY07024DI26A30-D MIPI-DSI LCD panel" ); +MODULE_LICENSE ("GPL" );Signature · 1 line
2.18.0.321.gffc6fa0e3
Signature · 5 lines
Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Jagan Teki
maintainerRe: [PATCH v2 11/12] drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
Quoted 153 lines · Sean Paul
Quoted 109 lines · Jagan Teki
Feiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
Signed-off-by Jagan Teki <[email protected]>--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.cMAINTAINERS +6
-0@@ -4620,6 +4620,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc S: Maintained F: drivers/gpu/drm/tve200/ +DRM DRIVER FOR FEIYANG FY07024DI26A30-D MIPI-DSI LCD PANELS +M: Jagan Teki <[email protected]> +S: Maintained +F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt + DRM DRIVER FOR ILITEK ILI9225 PANELS M: David Lechner <[email protected]> S: Maintaineddrivers/gpu/drm/panel/Kconfig +9
-0@@ -47,6 +47,15 @@ config DRM_PANEL_SIMPLE that it can be automatically turned off when the panel goes into a low power state. +config DRM_PANEL_FEIYANG_FY07024DI26A30D + tristate "Feiyang FY07024DI26A30-D MIPI-DSI LCD panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Feiyang FY07024DI26A30-D MIPI-DSI interface. + config DRM_PANEL_ILITEK_IL9322 tristate "Ilitek ILI9322 320x240 QVGA panels" depends on OF && SPIdrivers/gpu/drm/panel/Makefile +1
-0@@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o obj-$(CONFIG_DRM_PANEL_BANANAPI_S070WV20_ICN6211) += panel-bananapi-s070wv20-icn6211.o obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o +obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.odrivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +41
-0@@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Amarula Solutions +* Author: Jagan Teki <[email protected]> +*/ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_device.h> + +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> + +#include <drm/drmP.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> + +struct feiyang { +struct drm_panel panel; +struct mipi_dsi_device *dsi; + +struct backlight_device *backlight; +struct regulator *dvdd; +struct regulator *avdd; +struct gpio_desc *reset; +}; + +static inline struct feiyang *panel_to_feiyang (struct drm_panel *panel) +{ + return container_of(panel, struct feiyang, panel); +} + +struct feiyang_init_cmd { +size_t len; +const char *data; +}; + +#define FY07024DI26A30D (...) { \ + .len = sizeof((char[]){__VA_ARGS__}), \ + .data = (char[]){__VA_ARGS__} }drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 51
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+ +static const struct feiyang_init_cmd feiyang_init_cmds[] = { +FY07024DI26A30D (0x80 ,0x58 ), +FY07024DI26A30D (0x81 ,0x47 ), +FY07024DI26A30D (0x82 ,0xD4 ), +FY07024DI26A30D (0x83 ,0x88 ), +FY07024DI26A30D (0x84 ,0xA9 ), +FY07024DI26A30D (0x85 ,0xC3 ), +FY07024DI26A30D (0x86 ,0x82 ), +};These init cmds don't have to be so complicated. You've only got len == 2, so just hardcode it in and avoid the macro:
#define
FEIYANG_INIT_CMD_LEN2struct feiyang_init_cmd { u8 data[FEIYANG_INIT_CMD]; };static const struct feiyang_init_cmd feiyang_init_cmds[] = { { .data = { 0x80, 0x58 } }, ... };drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 64
Quoted 13 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +13
-0+ +static int feiyang_prepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +unsigned int i; +int ret; + + ret =regulator_enable (ctx->dvdd); +if (ret) +return ret; + +msleep (100 );nit: You should do your best to correlate the sleeps with the timing parameters from the datasheet with a comment.
Quoted 3 lines
ie:
/* T1: > 100ms */ msleep(100);
Sorry, what does this mean?
Quoted 77 lines
Quoted 12 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +11
-0+ + ret =regulator_enable (ctx->avdd); +if (ret) +return ret; + +msleep (20 ); + +gpiod_set_value (ctx->reset,1 ); +msleep (50 ); + +gpiod_set_value (ctx->reset,0 );drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 85
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+msleep (20 ); + +gpiod_set_value (ctx->reset,1 ); +msleep (200 ); + +for (i =0 ; i <ARRAY_SIZE (feiyang_init_cmds); i++) { +const struct feiyang_init_cmd *cmd = + &feiyang_init_cmds[i]; + + ret =mipi_dsi_dcs_write_buffer (dsi, cmd->data, cmd->len);ret = mipi_dsi_dcs_write_buffer(dsi, cmd->data, FEIYANG_INIT_CMD_LEN);Quoted 15 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +15
-0+if (ret <0 ) +return ret; + } + +return 0 ; +} + +static int feiyang_enable (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); + +msleep (120 ); + +mipi_dsi_dcs_set_display_on (ctx->dsi); +backlight_enable (ctx->backlight);drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 110
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+ +return 0 ; +} + +static int feiyang_disable (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); + +backlight_disable (ctx->backlight); +return mipi_dsi_dcs_set_display_on (ctx->dsi);
set_display_on? You probably wantset_display_offhere :)Quoted 23 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +23
-0+} + +static int feiyang_unprepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +int ret; + + ret =mipi_dsi_dcs_set_display_off (ctx->dsi); +if (ret <0 ) +DRM_DEV_ERROR (panel->dev,"failed to set display off: %d\n" , + ret); + + ret =mipi_dsi_dcs_enter_sleep_mode (ctx->dsi); +if (ret <0 ) +DRM_DEV_ERROR (panel->dev,"failed to enter sleep mode: %d\n" , + ret); + +msleep (100 ); + +regulator_disable (ctx->avdd); + +regulator_disable (ctx->dvdd); +
Quoted 8 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 134
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +5
-0+gpiod_set_value (ctx->reset,0 ); + +gpiod_set_value (ctx->reset,1 ); + +gpiod_set_value (ctx->reset,0 );Presumably this reset line toggle isn't needed since the rails are already disabled?
Yes, rails need to reset and turn off. will swap.
Quoted 11 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 145
Quoted 8 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +7
-0+ +return 0 ; +} + +static const struct drm_display_mode feiyang_default_mode = { + .clock =55000 , + .vrefresh =60 ,This doesn't add up correctly. The pixel clock should be equal to:
Quoted 5 lines
(htotal * vtotal * vrefresh) / 1000For this reason, we usually don't specify the refresh rate since it can be misleading. Your actual refresh rate with the pixel clock you specified is actually going to be 56.2Hz instead of the 60 you want.
The actual BSP do work 55MHz[1], I do specify refresh rate unnecessarily.
Re: [PATCH v2 11/12] drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
Quoted 7 lines · Jagan Teki
Quoted 6 lines · Sean Paul
Quoted 4 lines · Jagan Teki
Feiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Signed-off-by Jagan Teki <[email protected]>--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
/snip
Quoted 5 lines
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +0
-0
/snip
Quoted 16 lines
Quoted 16 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 64
Quoted 12 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +12
-0+static int feiyang_prepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +unsigned int i; +int ret; + + ret =regulator_enable (ctx->dvdd); +if (ret) +return ret; + +msleep (100 );nit: You should do your best to correlate the sleeps with the timing parameters from the datasheet with a comment.
Quoted 5 lines
Quoted 3 lines
ie:
/* T1: > 100ms */ msleep(100);Sorry, what does this mean?
On page 9 of the datasheet you sent me [1], it has the delays required to safely power up the panel. This delay is the time between dvdd going high and avdd going high. On the figure in the datasheet, this would be T2 (T1 is dvdd rise time and should be handled in the regulator subsystem (iirc)). Also according to the datasheet, T2 just needs to be > 0, so you don't even need this delay. You could replace this with a comment like:
/* T1 (dvdd rise time) + T2 (dvdd->avdd) > 0 */
So for all of the msleeps below you should get the delays from the datasheet and add a comment referencing them.
Sean
[1] - http://files.pine64.org/doc/datasheet/pine64/FY07024DI26A30-D_feiyang_LCD_panel.pdf
Quoted 100 lines
Quoted 78 lines
Quoted 13 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +11
-0+ + ret =regulator_enable (ctx->avdd); +if (ret) +return ret; + +msleep (20 ); + +gpiod_set_value (ctx->reset,1 ); +msleep (50 ); + +gpiod_set_value (ctx->reset,0 );drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 85
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+msleep (20 ); + +gpiod_set_value (ctx->reset,1 ); +msleep (200 ); + +for (i =0 ; i <ARRAY_SIZE (feiyang_init_cmds); i++) { +const struct feiyang_init_cmd *cmd = + &feiyang_init_cmds[i]; + + ret =mipi_dsi_dcs_write_buffer (dsi, cmd->data, cmd->len);ret = mipi_dsi_dcs_write_buffer(dsi, cmd->data, FEIYANG_INIT_CMD_LEN);Quoted 15 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +15
-0+if (ret <0 ) +return ret; + } + +return 0 ; +} + +static int feiyang_enable (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); + +msleep (120 ); + +mipi_dsi_dcs_set_display_on (ctx->dsi); +backlight_enable (ctx->backlight);drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 110
Quoted 10 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +10
-0+ +return 0 ; +} + +static int feiyang_disable (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); + +backlight_disable (ctx->backlight); +return mipi_dsi_dcs_set_display_on (ctx->dsi);
set_display_on? You probably wantset_display_offhere :)Quoted 23 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +23
-0+} + +static int feiyang_unprepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +int ret; + + ret =mipi_dsi_dcs_set_display_off (ctx->dsi); +if (ret <0 ) +DRM_DEV_ERROR (panel->dev,"failed to set display off: %d\n" , + ret); + + ret =mipi_dsi_dcs_enter_sleep_mode (ctx->dsi); +if (ret <0 ) +DRM_DEV_ERROR (panel->dev,"failed to enter sleep mode: %d\n" , + ret); + +msleep (100 ); + +regulator_disable (ctx->avdd); + +regulator_disable (ctx->dvdd); +Quoted 8 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 134
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +5
-0+gpiod_set_value (ctx->reset,0 ); + +gpiod_set_value (ctx->reset,1 ); + +gpiod_set_value (ctx->reset,0 );Presumably this reset line toggle isn't needed since the rails are already disabled?
Yes, rails need to reset and turn off. will swap.
Quoted 11 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 145
Quoted 8 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +7
-0+ +return 0 ; +} + +static const struct drm_display_mode feiyang_default_mode = { + .clock =55000 , + .vrefresh =60 ,This doesn't add up correctly. The pixel clock should be equal to:
Quoted 7 lines
Quoted 5 lines
(htotal * vtotal * vrefresh) / 1000For this reason, we usually don't specify the refresh rate since it can be misleading. Your actual refresh rate with the pixel clock you specified is actually going to be 56.2Hz instead of the 60 you want.
The actual BSP do work 55MHz[1], I do specify refresh rate unnecessarily.
Well, the BSP has a bug in it then :) You either want the refresh rate to be 60Hz or you want the pixel clock to be 55MHz, you can't have both with the timing you have now. You'll need to alter the pixel clock or porches to get 60Hz.
Sean
Quoted 2 lines
Signature · 1 line
Sean Paul, Software Engineer, Google / Chromium OS
Jagan Teki
maintainerRe: [PATCH v2 11/12] drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
Quoted 49 lines · Sean Paul
Quoted 7 lines · Jagan Teki
Quoted 6 lines · Sean Paul
Quoted 4 lines · Jagan Teki
Feiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c/snip
Quoted 5 lines
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +0
-0/snip
Quoted 20 lines
Quoted 19 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 64
Quoted 12 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +12
-0+static int feiyang_prepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +unsigned int i; +int ret; + + ret =regulator_enable (ctx->dvdd); +if (ret) +return ret; + +msleep (100 );nit: You should do your best to correlate the sleeps with the timing parameters from the datasheet with a comment.
ie:
/* T1: > 100ms */ msleep(100);
Quoted 5 lines
Quoted 1 line
Sorry, what does this mean?
On page 9 of the datasheet you sent me [1], it has the delays required to safely power up the panel. This delay is the time between dvdd going high and avdd going high. On the figure in the datasheet, this would be T2 (T1 is dvdd rise
time between dvdd going high and avdd going high is T1 + T3 right?
T2 > 0ms
T3 > 20ms
In this case the delay can be msleep(20) ?
Quoted 8 lines
time and should be handled in the regulator subsystem (iirc)). Also according to the datasheet, T2 just needs to be > 0, so you don't even need this delay. You could replace this with a comment like:
/* T1 (dvdd rise time) + T2 (dvdd->avdd) > 0 */So for all of the msleeps below you should get the delays from the datasheet and add a comment referencing them.
T5 and T6 are delay between avdd to reset enable it can be 10 + 10 => 20ms and finally T12 which is 200 after reset.
What about the delay between resets, I need to understand it a bit.
Re: [PATCH v2 11/12] drm/panel: Add Feiyang FY07024DI26A30-D MIPI-DSI LCD panel
Quoted 56 lines · Jagan Teki
Quoted 49 lines · Sean Paul
Quoted 7 lines · Jagan Teki
Quoted 6 lines · Sean Paul
Quoted 4 lines · Jagan Teki
Feiyang FY07024DI26A30-D is 1024x600, 4-lane MIPI-DSI LCD panel.
Add panel driver for it.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Signed-off-by Jagan Teki <[email protected]>--- MAINTAINERS | 6 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + .../drm/panel/panel-feiyang-fy07024di26a30d.c | 286 ++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c/snip
Quoted 5 lines
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
Quoted 5 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +0
-0/snip
Quoted 20 lines
Quoted 19 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c line 64
Quoted 12 lines
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c new file +12
-0+static int feiyang_prepare (struct drm_panel *panel) +{ +struct feiyang *ctx =panel_to_feiyang (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +unsigned int i; +int ret; + + ret =regulator_enable (ctx->dvdd); +if (ret) +return ret; + +msleep (100 );nit: You should do your best to correlate the sleeps with the timing parameters from the datasheet with a comment.
ie:
/* T1: > 100ms */ msleep(100);Quoted 5 lines
Quoted 1 line
Sorry, what does this mean?
On page 9 of the datasheet you sent me [1], it has the delays required to safely power up the panel. This delay is the time between dvdd going high and avdd going high. On the figure in the datasheet, this would be T2 (T1 is dvdd rise
Quoted 6 lines
time between dvdd going high and avdd going high is T1 + T3 right?
T2 > 0ms
T3 > 20msIn this case the delay can be msleep(20) ?
Hmm, yeah, I didn't notice that T3 was > 20ms, that's kind of confusing. So I think you're right, this should be T2 + T3 > 20ms (T1 is covered in the regulator_enable of dvdd).
Quoted 7 lines
Quoted 7 lines
time and should be handled in the regulator subsystem (iirc)). Also according to the datasheet, T2 just needs to be > 0, so you don't even need this delay. You could replace this with a comment like:
/* T1 (dvdd rise time) + T2 (dvdd->avdd) > 0 */
Quoted 7 lines
Quoted 2 lines
So for all of the msleeps below you should get the delays from the datasheet and add a comment referencing them.
T5 and T6 are delay between avdd to reset enable it can be 10 + 10 => 20ms and finally T12 which is 200 after reset.
What about the delay between resets, I need to understand it a bit.
These are usually accounted for at the end of disable. Take a look at the sleep parameters in panel-simple for an example.
Sean
Signature · 5 lines
Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Jagan Teki
maintainerPATCH v2 12/12 arm64: allwinner: a64: pine64-lts: Enable Feiyang FY07024DI26A30-D DSI panel
In reply to Jagan TekiFeiyang FY07024DI26A30-D MIPI_DSI panel is desiged to attach with DSI connector on pine64 boards, enable the same for pine64 LTS.
DSI panel connected via board DSI port with,
- DC1SW as AVDD supply
- DLDO2 as DVDD supply
- DLDO1 as VCC-DSI supply
- PD24 gpio for reset pin
- PH10 gpio for backlight enable pin
--- .../dts/allwinner/sun50i-a64-pine64-lts.dts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+)
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts +37 -0
@@ -5,9 +5,46 @@ */ #include "sun50i-a64-sopine-baseboard.dts" +#include <dt-bindings/pwm/pwm.h> / { model = "Pine64 LTS"; compatible = "pine64,pine64-lts", "allwinner,sun50i-r18", "allwinner,sun50i-a64"; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&r_pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <1 2 4 8 16 32 64 128 512>; + default-brightness-level = <8>; + enable-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PH10 */ + }; +}; + +&de { + status = "okay"; +}; + +&dphy { + status = "okay"; +}; + +&dsi { + vcc-dsi-supply = <®_dldo1>; /* VCC3V3-DSI */ + status = "okay"; + + panel@0 { + compatible = "feiyang,fy07024di26a30d"; + reg = <0>; + avdd-supply = <®_dc1sw>; /* VCC-LCD */ + dvdd-supply = <®_dldo2>; /* VCC-MIPI */ + reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD24 */ + backlight = <&backlight>; + }; +}; + +&r_pwm { + pinctrl-names = "default"; + pinctrl-0 = <&r_pwm_pin>; + status = "okay"; };
Signature · 1 line
2.18.0.321.gffc6fa0e3