mirror of
https://github.com/CTCaer/hekate.git
synced 2024-11-26 11:42:09 +00:00
bdk: di: split normal and vblank dsi reads
And also make vblank reads more robust
This commit is contained in:
parent
8f540b2543
commit
0b8cdaf0ea
2 changed files with 125 additions and 52 deletions
172
bdk/display/di.c
172
bdk/display/di.c
|
@ -57,34 +57,10 @@ static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
|
||||||
usleep(wait);
|
usleep(wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _display_dsi_read_rx_fifo(u32 *data)
|
static void _display_dsi_wait_vblank(bool enable)
|
||||||
{
|
{
|
||||||
u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE;
|
if (enable)
|
||||||
for (u32 i = 0; i < fifo_count; i++)
|
|
||||||
{
|
{
|
||||||
// Read or Drain RX FIFO.
|
|
||||||
if (data)
|
|
||||||
data[i] = DSI(_DSIREG(DSI_RD_DATA));
|
|
||||||
else
|
|
||||||
(void)DSI(_DSIREG(DSI_RD_DATA));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
u32 host_control = 0;
|
|
||||||
u32 cmd_timeout = video_enabled ? 0 : 250000;
|
|
||||||
u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
|
|
||||||
|
|
||||||
// Drain RX FIFO.
|
|
||||||
_display_dsi_read_rx_fifo(NULL);
|
|
||||||
|
|
||||||
// Save host control and enable host cmd packets during video.
|
|
||||||
if (video_enabled)
|
|
||||||
{
|
|
||||||
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
|
|
||||||
|
|
||||||
// Enable vblank interrupt.
|
// Enable vblank interrupt.
|
||||||
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT;
|
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT;
|
||||||
|
|
||||||
|
@ -96,18 +72,67 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Wait for vblank before reseting sync points.
|
||||||
|
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
|
||||||
|
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
||||||
|
;
|
||||||
|
usleep(14);
|
||||||
|
|
||||||
|
// Reset all states of syncpt block.
|
||||||
|
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
|
||||||
|
usleep(300); // Stabilization delay.
|
||||||
|
|
||||||
|
// Clear syncpt block reset.
|
||||||
|
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
|
||||||
|
usleep(300); // Stabilization delay.
|
||||||
|
|
||||||
|
// Restore video mode and host control.
|
||||||
|
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
|
||||||
|
|
||||||
|
// Disable and clear vblank interrupt.
|
||||||
|
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0;
|
||||||
|
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _display_dsi_read_rx_fifo(u32 *data)
|
||||||
|
{
|
||||||
|
u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE;
|
||||||
|
if (fifo_count)
|
||||||
|
DSI(_DSIREG(DSI_TRIGGER)) = 0;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < fifo_count; i++)
|
||||||
|
{
|
||||||
|
// Read or Drain RX FIFO.
|
||||||
|
if (data)
|
||||||
|
data[i] = DSI(_DSIREG(DSI_RD_DATA));
|
||||||
|
else
|
||||||
|
(void)DSI(_DSIREG(DSI_RD_DATA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int display_dsi_read(u8 cmd, u32 len, void *data)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
|
||||||
|
|
||||||
|
// Drain RX FIFO.
|
||||||
|
_display_dsi_read_rx_fifo(NULL);
|
||||||
|
|
||||||
// Set reply size.
|
// Set reply size.
|
||||||
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
|
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
|
||||||
_display_dsi_wait(cmd_timeout, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||||
|
|
||||||
// Request register read.
|
// Request register read.
|
||||||
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0);
|
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0);
|
||||||
_display_dsi_wait(cmd_timeout, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||||
|
|
||||||
// Transfer bus control to device for transmitting the reply.
|
// Transfer bus control to device for transmitting the reply.
|
||||||
u32 high_speed = video_enabled ? DSI_HOST_CONTROL_HS : 0;
|
DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_IMM_BTA;
|
||||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC | high_speed;
|
|
||||||
|
// Wait for reply to complete. DSI_HOST_CONTROL_IMM_BTA bit acts as a DSI host read busy.
|
||||||
_display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
|
_display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
|
||||||
|
|
||||||
// Wait a bit for the reply.
|
// Wait a bit for the reply.
|
||||||
|
@ -146,30 +171,77 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||||
else
|
else
|
||||||
res = 1;
|
res = 1;
|
||||||
|
|
||||||
// Disable host cmd packets during video and restore host control.
|
return res;
|
||||||
if (video_enabled)
|
}
|
||||||
|
|
||||||
|
int display_dsi_vblank_read(u8 cmd, u32 len, void *data)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
u32 host_control = 0;
|
||||||
|
u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
|
||||||
|
|
||||||
|
// Drain RX FIFO.
|
||||||
|
_display_dsi_read_rx_fifo(NULL);
|
||||||
|
|
||||||
|
// Save host control and enable host cmd packets during video.
|
||||||
|
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
|
||||||
|
|
||||||
|
_display_dsi_wait_vblank(true);
|
||||||
|
|
||||||
|
// Set reply size.
|
||||||
|
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
|
||||||
|
_display_dsi_wait(0, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||||
|
|
||||||
|
// Request register read.
|
||||||
|
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0);
|
||||||
|
_display_dsi_wait(0, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||||
|
|
||||||
|
_display_dsi_wait_vblank(false);
|
||||||
|
|
||||||
|
// Transfer bus control to device for transmitting the reply.
|
||||||
|
DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_IMM_BTA;
|
||||||
|
|
||||||
|
// Wait for reply to complete. DSI_HOST_CONTROL_IMM_BTA bit acts as a DSI host read busy.
|
||||||
|
_display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
|
||||||
|
|
||||||
|
// Wait a bit for the reply.
|
||||||
|
usleep(5000);
|
||||||
|
|
||||||
|
// Read RX FIFO.
|
||||||
|
_display_dsi_read_rx_fifo(fifo);
|
||||||
|
|
||||||
|
// Parse packet and copy over the data.
|
||||||
|
if ((fifo[0] & 0xFF) == DSI_ESCAPE_CMD)
|
||||||
{
|
{
|
||||||
// Wait for vblank before reseting sync points.
|
// Act based on reply type.
|
||||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
|
switch (fifo[1] & 0xFF)
|
||||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
{
|
||||||
;
|
case GEN_LONG_RD_RES:
|
||||||
|
case DCS_LONG_RD_RES:
|
||||||
|
memcpy(data, &fifo[2], MIN((fifo[1] >> 8) & 0xFFFF, len));
|
||||||
|
break;
|
||||||
|
|
||||||
// Reset all states of syncpt block.
|
case GEN_1_BYTE_SHORT_RD_RES:
|
||||||
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
|
case DCS_1_BYTE_SHORT_RD_RES:
|
||||||
usleep(300); // Stabilization delay.
|
memcpy(data, &fifo[2], 1);
|
||||||
|
break;
|
||||||
|
|
||||||
// Clear syncpt block reset.
|
case GEN_2_BYTE_SHORT_RD_RES:
|
||||||
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
|
case DCS_2_BYTE_SHORT_RD_RES:
|
||||||
usleep(300); // Stabilization delay.
|
memcpy(data, &fifo[2], 2);
|
||||||
|
break;
|
||||||
|
|
||||||
// Restore video mode and host control.
|
case ACK_ERROR_RES:
|
||||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
|
default:
|
||||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
|
res = 1;
|
||||||
|
break;
|
||||||
// Disable and clear vblank interrupt.
|
|
||||||
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0;
|
|
||||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = 1;
|
||||||
|
|
||||||
|
// Restore host control.
|
||||||
|
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -425,7 +497,7 @@ void display_init()
|
||||||
_display_id = 0xCCCCCC;
|
_display_id = 0xCCCCCC;
|
||||||
for (u32 i = 0; i < 3; i++)
|
for (u32 i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED))
|
if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2021 CTCaer
|
* Copyright (c) 2018-2022 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
@ -737,7 +737,8 @@ void display_init_cursor(void *crs_fb, u32 size);
|
||||||
void display_set_pos_cursor(u32 x, u32 y);
|
void display_set_pos_cursor(u32 x, u32 y);
|
||||||
void display_deinit_cursor();
|
void display_deinit_cursor();
|
||||||
|
|
||||||
|
int display_dsi_read(u8 cmd, u32 len, void *data);
|
||||||
|
int display_dsi_vblank_read(u8 cmd, u32 len, void *data);
|
||||||
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled);
|
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled);
|
||||||
int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue