mirror of
https://github.com/CTCaer/hekate.git
synced 2024-11-23 02:16:41 +00:00
bdk: di: make dsi normal/vblank writes more robust
This commit is contained in:
parent
dd2bb0f555
commit
6ae4904c8f
1 changed files with 33 additions and 48 deletions
|
@ -246,23 +246,32 @@ int display_dsi_vblank_read(u8 cmd, u32 len, void *data)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
void display_dsi_write(u8 cmd, u32 len, void *data)
|
||||||
{
|
{
|
||||||
|
static u8 *fifo8 = NULL;
|
||||||
static u32 *fifo32 = NULL;
|
static u32 *fifo32 = NULL;
|
||||||
u8 *fifo8;
|
|
||||||
u32 host_control;
|
u32 host_control;
|
||||||
|
|
||||||
// Allocate fifo buffer.
|
// Allocate fifo buffer.
|
||||||
if (!fifo32)
|
if (!fifo32)
|
||||||
|
{
|
||||||
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
||||||
|
fifo8 = (u8 *)fifo32;
|
||||||
|
}
|
||||||
|
|
||||||
// Enable host cmd packets during video and save host control.
|
// Prepare data for long write.
|
||||||
if (video_enabled)
|
if (len >= 2)
|
||||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
|
{
|
||||||
|
memcpy(&fifo8[5], data, len);
|
||||||
|
memset(&fifo8[5] + len, 0, len % sizeof(u32));
|
||||||
|
len++; // Increase length by CMD.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save host control.
|
||||||
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
|
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
|
||||||
|
|
||||||
// Enable host transfer trigger.
|
// Enable host transfer trigger.
|
||||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control | DSI_HOST_CONTROL_TX_TRIG_HOST;
|
DSI(_DSIREG(DSI_HOST_CONTROL)) = (host_control & ~(DSI_HOST_CONTROL_TX_TRIG_MASK)) | DSI_HOST_CONTROL_TX_TRIG_HOST;
|
||||||
|
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
|
@ -275,13 +284,10 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
memset(fifo32, 0, DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
|
||||||
fifo8 = (u8 *)fifo32;
|
|
||||||
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
|
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
|
||||||
fifo8[4] = cmd;
|
fifo8[4] = cmd;
|
||||||
memcpy(&fifo8[5], data, len);
|
len += sizeof(u32); // Increase length by length word and DCS CMD.
|
||||||
len += 4 + 1; // Increase length by CMD/length word and DCS CMD.
|
for (u32 i = 0; i < (ALIGN(len, sizeof(u32)) / sizeof(u32)); i++)
|
||||||
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
|
|
||||||
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
||||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||||
break;
|
break;
|
||||||
|
@ -290,31 +296,31 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||||
// Wait for the write to happen.
|
// Wait for the write to happen.
|
||||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST);
|
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST);
|
||||||
|
|
||||||
// Disable host cmd packets during video and restore host control.
|
// Restore host control.
|
||||||
if (video_enabled)
|
|
||||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
|
|
||||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
|
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
|
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
|
||||||
{
|
{
|
||||||
|
static u8 *fifo8 = NULL;
|
||||||
static u32 *fifo32 = NULL;
|
static u32 *fifo32 = NULL;
|
||||||
u8 *fifo8;
|
|
||||||
|
|
||||||
// Allocate fifo buffer.
|
// Allocate fifo buffer.
|
||||||
if (!fifo32)
|
if (!fifo32)
|
||||||
|
{
|
||||||
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
||||||
|
fifo8 = (u8 *)fifo32;
|
||||||
|
}
|
||||||
|
|
||||||
// Enable vblank interrupt.
|
// Prepare data for long write.
|
||||||
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT;
|
if (len >= 2)
|
||||||
|
{
|
||||||
|
memcpy(&fifo8[5], data, len);
|
||||||
|
memset(&fifo8[5] + len, 0, len % sizeof(u32));
|
||||||
|
len++; // Increase length by CMD.
|
||||||
|
}
|
||||||
|
|
||||||
// Use the 4th line to transmit the host cmd packet.
|
_display_dsi_wait_vblank(true);
|
||||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE | DSI_DSI_LINE_TYPE(4);
|
|
||||||
|
|
||||||
// Wait for vblank before starting the transfer.
|
|
||||||
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))
|
|
||||||
;
|
|
||||||
|
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
|
@ -327,36 +333,15 @@ void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
memset(fifo32, 0, DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
|
||||||
fifo8 = (u8 *)fifo32;
|
|
||||||
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
|
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
|
||||||
fifo8[4] = cmd;
|
fifo8[4] = cmd;
|
||||||
memcpy(&fifo8[5], data, len);
|
len += sizeof(u32); // Increase length by length word and DCS CMD.
|
||||||
len += 4 + 1; // Increase length by CMD/length word and DCS CMD.
|
for (u32 i = 0; i < (ALIGN(len, sizeof(u32)) / sizeof(u32)); i++)
|
||||||
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
|
|
||||||
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for vblank before reseting sync points.
|
_display_dsi_wait_vblank(false);
|
||||||
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))
|
|
||||||
;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_init()
|
void display_init()
|
||||||
|
|
Loading…
Reference in a new issue