[v2,1/2] drm: panel: st7701: Add Hardkernel ODROID-GO Ultra panel support

Message ID 20240222164332.3864716-2-greena88@gmail.com
State New
Headers
Series drm: panel: st7701: Add Hardkernel ODROID-GO Ultra panel support |

Commit Message

Adam Green Feb. 22, 2024, 4:43 p.m. UTC
  The Hardkernel ODROID-GO Ultra is a handheld gaming devices, with
a 5 inch 480x854 display. Add support for the display.

Signed-off-by: Adam Green <greena88@gmail.com>
---
 drivers/gpu/drm/panel/panel-sitronix-st7701.c | 158 +++++++++++++++++-
 1 file changed, 157 insertions(+), 1 deletion(-)
  

Comments

Jessica Zhang Feb. 22, 2024, 5:14 p.m. UTC | #1
On 2/22/2024 8:43 AM, Adam Green wrote:
> The Hardkernel ODROID-GO Ultra is a handheld gaming devices, with
> a 5 inch 480x854 display. Add support for the display.
> 
> Signed-off-by: Adam Green <greena88@gmail.com>
> ---
>   drivers/gpu/drm/panel/panel-sitronix-st7701.c | 158 +++++++++++++++++-
>   1 file changed, 157 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
> index 421eb4592b61..d08e8f4c39dd 100644
> --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c
> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
> @@ -423,6 +423,62 @@ static void kd50t048a_gip_sequence(struct st7701 *st7701)
>   		   0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA);
>   }
>   
> +static void odroid_go_ultra_gip_sequence(struct st7701 *st7701)
> +{
> +	ST7701_DSI(st7701, 0x01);
> +	msleep(20);
> +	ST7701_DSI(st7701, 0x11);
> +	msleep(120);
> +
> +	ST7701_DSI(st7701, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x10);
> +	ST7701_DSI(st7701, 0xC0, 0xE9, 0x03);
> +	ST7701_DSI(st7701, 0xC1, 0x11, 0x02);
> +	ST7701_DSI(st7701, 0xC2, 0x31, 0x08);
> +	ST7701_DSI(st7701, 0xCC, 0x10);
> +	ST7701_DSI(st7701, 0xB0, 0x00, 0x0D, 0x14, 0x0D, 0x10, 0x05, 0x02, 0x08,
> +		   0x08, 0x1E, 0x05, 0x13, 0x11, 0xA3, 0x29, 0x18);
> +	ST7701_DSI(st7701, 0xB1, 0x00, 0x0C, 0x14, 0x0C, 0x10, 0x05, 0x03, 0x08,
> +		   0x07, 0x20, 0x05, 0x13, 0x11, 0xA4, 0x29, 0x18);
> +	ST7701_DSI(st7701, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x11);
> +	ST7701_DSI(st7701, 0xB0, 0x6C);
> +	ST7701_DSI(st7701, 0xB1, 0x43);
> +	ST7701_DSI(st7701, 0xB2, 0x07);
> +	ST7701_DSI(st7701, 0xB3, 0x80);
> +	ST7701_DSI(st7701, 0xB5, 0x47);
> +	ST7701_DSI(st7701, 0xB7, 0x85);
> +	ST7701_DSI(st7701, 0xB8, 0x20);
> +	ST7701_DSI(st7701, 0xB9, 0x10);
> +	ST7701_DSI(st7701, 0xC1, 0x78);
> +	ST7701_DSI(st7701, 0xC3, 0x78);
> +	ST7701_DSI(st7701, 0xD0, 0x88);
> +	msleep(120);
> +
> +	ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
> +	ST7701_DSI(st7701, 0xE1, 0x08, 0x00, 0x0A, 0x00, 0x07, 0x00, 0x09,
> +		   0x00, 0x00, 0x33, 0x33);
> +	ST7701_DSI(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
> +	ST7701_DSI(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33);
> +	ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
> +	ST7701_DSI(st7701, 0xE5, 0x0E, 0x60, 0xA0, 0xA0, 0x10, 0x60, 0xA0,
> +		   0xA0, 0x0A, 0x60, 0xA0, 0xA0, 0x0C, 0x60, 0xA0, 0xA0);
> +	ST7701_DSI(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33);
> +	ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
> +	ST7701_DSI(st7701, 0xE8, 0x0D, 0x60, 0xA0, 0xA0, 0x0F, 0x60, 0xA0,
> +		   0xA0, 0x09, 0x60, 0xA0, 0xA0, 0x0B, 0x60, 0xA0, 0xA0);
> +	ST7701_DSI(st7701, 0xEB, 0x02, 0x01, 0xE4, 0xE4, 0x44, 0x00, 0x40);
> +	ST7701_DSI(st7701, 0xEC, 0x02, 0x01);
> +	ST7701_DSI(st7701, 0xED, 0xAB, 0x89, 0x76, 0x54, 0x01, 0xFF, 0xFF,
> +		   0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA);
> +	ST7701_DSI(st7701, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00);
> +	ST7701_DSI(st7701, 0x3A, 0x70);
> +	ST7701_DSI(st7701, 0x53, 0xEC);
> +	ST7701_DSI(st7701, 0x55, 0xB3);
> +	ST7701_DSI(st7701, 0x5E, 0xFF);
> +	ST7701_DSI(st7701, 0x29);
> +	msleep(50);
> +}
> +
>   static void rg_arc_gip_sequence(struct st7701 *st7701)
>   {
>   	st7701_switch_cmd_bkx(st7701, true, 3);
> @@ -470,7 +526,7 @@ static int st7701_prepare(struct drm_panel *panel)
>   				    st7701->supplies);
>   	if (ret < 0)
>   		return ret;
> -	msleep(20);
> +	msleep(120);

Hi Adam,

Just wondering, why the change to 120 here?

Thanks,

Jessica Zhang

>   
>   	gpiod_set_value(st7701->reset, 1);
>   	msleep(150);
> @@ -875,6 +931,105 @@ static const struct st7701_panel_desc kd50t048a_desc = {
>   	.gip_sequence = kd50t048a_gip_sequence,
>   };
>   
> +static const struct drm_display_mode odroid_go_ultra_mode = {
> +	.clock		= 29170,
> +
> +	.hdisplay	= 480,
> +	.hsync_start	= 480 + 12,
> +	.hsync_end	= 480 + 12 + 12,
> +	.htotal		= 480 + 12 + 12 + 38,
> +
> +	.vdisplay	= 854,
> +	.vsync_start	= 854 + 2,
> +	.vsync_end	= 854 + 2 + 19,
> +	.vtotal		= 854 + 2 + 19 + 22,
> +
> +	.width_mm	= 70,
> +	.height_mm	= 140,
> +
> +	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +};
> +
> +static const struct st7701_panel_desc odroid_go_ultra_desc = {
> +	.mode = &odroid_go_ultra_mode,
> +	.lanes = 2,
> +	.format = MIPI_DSI_FMT_RGB888,
> +	.panel_sleep_delay = 120,
> +
> +	.pv_gamma = {
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
> +
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x2),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
> +
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1e),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
> +
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 2) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x23),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18)
> +	},
> +	.nv_gamma = {
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xc),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xc),
> +
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x3),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
> +
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
> +
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 2) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x24),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29),
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
> +		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18)
> +	},
> +	.nlinv = 1,
> +	.vop_uv = 4887500,
> +	.vcom_uv = 937500,
> +	.vgh_mv = 15000,
> +	.vgl_mv = -9510,
> +	.avdd_mv = 6600,
> +	.avcl_mv = -4400,
> +	.gamma_op_bias = OP_BIAS_MIDDLE,
> +	.input_op_bias = OP_BIAS_MIN,
> +	.output_op_bias = OP_BIAS_MIN,
> +	.t2d_ns = 1600,
> +	.t3d_ns = 10400,
> +	.eot_en = true,
> +	.gip_sequence = odroid_go_ultra_gip_sequence,
> +};
> +
>   static const struct drm_display_mode rg_arc_mode = {
>   	.clock          = 25600,
>   
> @@ -1055,6 +1210,7 @@ static const struct of_device_id st7701_of_match[] = {
>   	{ .compatible = "anbernic,rg-arc-panel", .data = &rg_arc_desc },
>   	{ .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc },
>   	{ .compatible = "elida,kd50t048a", .data = &kd50t048a_desc },
> +	{ .compatible = "hardkernel,odroid-go-ultra-panel", .data = &odroid_go_ultra_desc },
>   	{ .compatible = "techstar,ts8550b", .data = &ts8550b_desc },
>   	{ }
>   };
> -- 
> 2.43.0
>
  
Adam Green Feb. 22, 2024, 5:47 p.m. UTC | #2
On 22/02/2024 17:14, Jessica Zhang wrote:
> Hi Adam,
> 
> Just wondering, why the change to 120 here?
> 
> Thanks,
> 
> Jessica Zhang

Hi,

The 120ms is taken from the datasheet specification for the controller 
as maximum time it takes for the display to reset,

Kind regards,

Adam
  
Jessica Zhang Feb. 26, 2024, 9:29 p.m. UTC | #3
On 2/22/2024 9:47 AM, Adam Green wrote:
> On 22/02/2024 17:14, Jessica Zhang wrote:
>> Hi Adam,
>>
>> Just wondering, why the change to 120 here?
>>
>> Thanks,
>>
>> Jessica Zhang
> 
> Hi,
> 
> The 120ms is taken from the datasheet specification for the controller 
> as maximum time it takes for the display to reset,

Got it. Was the shorter sleep time breaking the display and is it 
required for the new panel to work?

Thanks,

Jessica Zhang

> 
> Kind regards,
> 
> Adam
  
Adam Green Feb. 29, 2024, 5:23 p.m. UTC | #4
On 26/02/2024 21:29, Jessica Zhang wrote:
 > Got it. Was the shorter sleep time breaking the display and is it
 > required for the new panel to work?
 >
 > Thanks,
 >
 > Jessica Zhang

Hi Jessica,

I will be submitting a v3 shortly, the change to the sleep time was not 
necessary for the new panel
to work.

I have been able to re-use the gip sequence from the kd50t048a panel 
used in the Hardkernel Odroid
Go Super as I have been led to believe it is the same elida panel, 
unfortunately the same modes
used by that device do not work for the Odroid Go Ultra and so its still 
necessary to have the
patchset,

Best regards,

Adam
  
Jessica Zhang Feb. 29, 2024, 9:30 p.m. UTC | #5
On 2/29/2024 9:23 AM, Adam Green wrote:
> On 26/02/2024 21:29, Jessica Zhang wrote:
>  > Got it. Was the shorter sleep time breaking the display and is it
>  > required for the new panel to work?
>  >
>  > Thanks,
>  >
>  > Jessica Zhang
> 
> Hi Jessica,
> 
> I will be submitting a v3 shortly, the change to the sleep time was not 
> necessary for the new panel
> to work.

Hi Adam,

Got it. If the panel isn't affected by the 20ms sleep time, I'd prefer 
to keep it since 100ms is a pretty big increase.

> 
> I have been able to re-use the gip sequence from the kd50t048a panel 
> used in the Hardkernel Odroid
> Go Super as I have been led to believe it is the same elida panel, 
> unfortunately the same modes
> used by that device do not work for the Odroid Go Ultra and so its still 
> necessary to have the
> patchset,
Got it. FWIW, I do see the Odroid Go Ultra being described as having the 
kd50t048a panel [1] [2]. Looking forward to seeing the v3 changes.

Thanks,

Jessica Zhang

[1] https://gitlab.com/amlogic-foss/mainline-linux-issues-tracker/-/issues/7

[2] 441e129cbf81 ("dt-bindings: display: panel: sitronix,st7701: Add 
Elida KD50T048A Panel")

> 
> Best regards,
> 
> Adam
  

Patch

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
index 421eb4592b61..d08e8f4c39dd 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
@@ -423,6 +423,62 @@  static void kd50t048a_gip_sequence(struct st7701 *st7701)
 		   0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA);
 }
 
+static void odroid_go_ultra_gip_sequence(struct st7701 *st7701)
+{
+	ST7701_DSI(st7701, 0x01);
+	msleep(20);
+	ST7701_DSI(st7701, 0x11);
+	msleep(120);
+
+	ST7701_DSI(st7701, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x10);
+	ST7701_DSI(st7701, 0xC0, 0xE9, 0x03);
+	ST7701_DSI(st7701, 0xC1, 0x11, 0x02);
+	ST7701_DSI(st7701, 0xC2, 0x31, 0x08);
+	ST7701_DSI(st7701, 0xCC, 0x10);
+	ST7701_DSI(st7701, 0xB0, 0x00, 0x0D, 0x14, 0x0D, 0x10, 0x05, 0x02, 0x08,
+		   0x08, 0x1E, 0x05, 0x13, 0x11, 0xA3, 0x29, 0x18);
+	ST7701_DSI(st7701, 0xB1, 0x00, 0x0C, 0x14, 0x0C, 0x10, 0x05, 0x03, 0x08,
+		   0x07, 0x20, 0x05, 0x13, 0x11, 0xA4, 0x29, 0x18);
+	ST7701_DSI(st7701, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x11);
+	ST7701_DSI(st7701, 0xB0, 0x6C);
+	ST7701_DSI(st7701, 0xB1, 0x43);
+	ST7701_DSI(st7701, 0xB2, 0x07);
+	ST7701_DSI(st7701, 0xB3, 0x80);
+	ST7701_DSI(st7701, 0xB5, 0x47);
+	ST7701_DSI(st7701, 0xB7, 0x85);
+	ST7701_DSI(st7701, 0xB8, 0x20);
+	ST7701_DSI(st7701, 0xB9, 0x10);
+	ST7701_DSI(st7701, 0xC1, 0x78);
+	ST7701_DSI(st7701, 0xC3, 0x78);
+	ST7701_DSI(st7701, 0xD0, 0x88);
+	msleep(120);
+
+	ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
+	ST7701_DSI(st7701, 0xE1, 0x08, 0x00, 0x0A, 0x00, 0x07, 0x00, 0x09,
+		   0x00, 0x00, 0x33, 0x33);
+	ST7701_DSI(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	ST7701_DSI(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33);
+	ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
+	ST7701_DSI(st7701, 0xE5, 0x0E, 0x60, 0xA0, 0xA0, 0x10, 0x60, 0xA0,
+		   0xA0, 0x0A, 0x60, 0xA0, 0xA0, 0x0C, 0x60, 0xA0, 0xA0);
+	ST7701_DSI(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33);
+	ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
+	ST7701_DSI(st7701, 0xE8, 0x0D, 0x60, 0xA0, 0xA0, 0x0F, 0x60, 0xA0,
+		   0xA0, 0x09, 0x60, 0xA0, 0xA0, 0x0B, 0x60, 0xA0, 0xA0);
+	ST7701_DSI(st7701, 0xEB, 0x02, 0x01, 0xE4, 0xE4, 0x44, 0x00, 0x40);
+	ST7701_DSI(st7701, 0xEC, 0x02, 0x01);
+	ST7701_DSI(st7701, 0xED, 0xAB, 0x89, 0x76, 0x54, 0x01, 0xFF, 0xFF,
+		   0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA);
+	ST7701_DSI(st7701, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00);
+	ST7701_DSI(st7701, 0x3A, 0x70);
+	ST7701_DSI(st7701, 0x53, 0xEC);
+	ST7701_DSI(st7701, 0x55, 0xB3);
+	ST7701_DSI(st7701, 0x5E, 0xFF);
+	ST7701_DSI(st7701, 0x29);
+	msleep(50);
+}
+
 static void rg_arc_gip_sequence(struct st7701 *st7701)
 {
 	st7701_switch_cmd_bkx(st7701, true, 3);
@@ -470,7 +526,7 @@  static int st7701_prepare(struct drm_panel *panel)
 				    st7701->supplies);
 	if (ret < 0)
 		return ret;
-	msleep(20);
+	msleep(120);
 
 	gpiod_set_value(st7701->reset, 1);
 	msleep(150);
@@ -875,6 +931,105 @@  static const struct st7701_panel_desc kd50t048a_desc = {
 	.gip_sequence = kd50t048a_gip_sequence,
 };
 
+static const struct drm_display_mode odroid_go_ultra_mode = {
+	.clock		= 29170,
+
+	.hdisplay	= 480,
+	.hsync_start	= 480 + 12,
+	.hsync_end	= 480 + 12 + 12,
+	.htotal		= 480 + 12 + 12 + 38,
+
+	.vdisplay	= 854,
+	.vsync_start	= 854 + 2,
+	.vsync_end	= 854 + 2 + 19,
+	.vtotal		= 854 + 2 + 19 + 22,
+
+	.width_mm	= 70,
+	.height_mm	= 140,
+
+	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct st7701_panel_desc odroid_go_ultra_desc = {
+	.mode = &odroid_go_ultra_mode,
+	.lanes = 2,
+	.format = MIPI_DSI_FMT_RGB888,
+	.panel_sleep_delay = 120,
+
+	.pv_gamma = {
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
+
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x2),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1e),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
+
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 2) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x23),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18)
+	},
+	.nv_gamma = {
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xc),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xc),
+
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x3),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
+
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 2) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x24),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29),
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18)
+	},
+	.nlinv = 1,
+	.vop_uv = 4887500,
+	.vcom_uv = 937500,
+	.vgh_mv = 15000,
+	.vgl_mv = -9510,
+	.avdd_mv = 6600,
+	.avcl_mv = -4400,
+	.gamma_op_bias = OP_BIAS_MIDDLE,
+	.input_op_bias = OP_BIAS_MIN,
+	.output_op_bias = OP_BIAS_MIN,
+	.t2d_ns = 1600,
+	.t3d_ns = 10400,
+	.eot_en = true,
+	.gip_sequence = odroid_go_ultra_gip_sequence,
+};
+
 static const struct drm_display_mode rg_arc_mode = {
 	.clock          = 25600,
 
@@ -1055,6 +1210,7 @@  static const struct of_device_id st7701_of_match[] = {
 	{ .compatible = "anbernic,rg-arc-panel", .data = &rg_arc_desc },
 	{ .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc },
 	{ .compatible = "elida,kd50t048a", .data = &kd50t048a_desc },
+	{ .compatible = "hardkernel,odroid-go-ultra-panel", .data = &odroid_go_ultra_desc },
 	{ .compatible = "techstar,ts8550b", .data = &ts8550b_desc },
 	{ }
 };