soc/mediatek: dsi: Support sending MIPI init commands
For systems with real MIPI panels (8173/oak was using PS8640 eDP bridge), we have to send DCS commands to initialize panel. BUG=b:80501386,b:117254947 TEST=make -j # board = oak and boots Change-Id: Ie7c824873465ac82a95bcb0ed67b8b9866987008 Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/34773 Reviewed-by: Julius Werner <jwerner@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
3b217d5c69
commit
75e4314675
|
@ -234,7 +234,7 @@ static void display_startup(void)
|
|||
edid_set_framebuffer_bits_per_pixel(&edid, 32, 0);
|
||||
|
||||
mtk_ddp_init();
|
||||
ret = mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, &edid);
|
||||
ret = mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, &edid, NULL);
|
||||
if (ret < 0) {
|
||||
printk(BIOS_ERR, "dsi init fail\n");
|
||||
return;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <device/mmio.h>
|
||||
#include <console/console.h>
|
||||
#include <device/mmio.h>
|
||||
|
@ -256,7 +257,124 @@ static void mtk_dsi_start(void)
|
|||
write32(&dsi0->dsi_start, 1);
|
||||
}
|
||||
|
||||
int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid)
|
||||
static bool mtk_dsi_is_read_command(u32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
|
||||
case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
|
||||
case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
|
||||
case MIPI_DSI_DCS_READ:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void mtk_dsi_cmdq(const u8 *data, u8 len, u32 type)
|
||||
{
|
||||
const u8 *tx_buf = data;
|
||||
u32 config;
|
||||
int i, j;
|
||||
|
||||
if (!wait_ms(20, !(read32(&dsi0->dsi_intsta) & DSI_BUSY))) {
|
||||
printk(BIOS_ERR, "%s: cannot get DSI ready for sending commands"
|
||||
" after 20ms and the panel may not work properly.\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
write32(&dsi0->dsi_intsta, 0);
|
||||
|
||||
if (mtk_dsi_is_read_command(type))
|
||||
config = BTA;
|
||||
else
|
||||
config = (len > 2) ? LONG_PACKET : SHORT_PACKET;
|
||||
|
||||
if (len <= 2) {
|
||||
uint32_t val = (type << 8) | config;
|
||||
for (i = 0; i < len; i++)
|
||||
val |= tx_buf[i] << (i + 2) * 8;
|
||||
write32(&dsi0->dsi_cmdq[0], val);
|
||||
write32(&dsi0->dsi_cmdq_size, 1);
|
||||
} else {
|
||||
/* TODO(hungte) Replace by buffer_to_fifo32_prefix */
|
||||
write32(&dsi0->dsi_cmdq[0], (len << 16) | (type << 8) | config);
|
||||
for (i = 0; i < len; i += 4) {
|
||||
uint32_t val = 0;
|
||||
for (j = 0; j < MIN(len - i, 4); j++)
|
||||
val |= tx_buf[i + j] << j * 8;
|
||||
write32(&dsi0->dsi_cmdq[i / 4 + 1], val);
|
||||
}
|
||||
write32(&dsi0->dsi_cmdq_size, 1 + DIV_ROUND_UP(len, 4));
|
||||
}
|
||||
|
||||
mtk_dsi_start();
|
||||
|
||||
if (!wait_us(400, read32(&dsi0->dsi_intsta) & CMD_DONE_INT_FLAG)) {
|
||||
printk(BIOS_ERR, "%s: failed sending DSI command, "
|
||||
"panel may not work.\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_dsi_send_init_commands(const struct lcm_init_command *init)
|
||||
{
|
||||
if (!init)
|
||||
return;
|
||||
|
||||
for (; init->cmd != LCM_END_CMD; init++) {
|
||||
u32 cmd = init->cmd, len = init->len;
|
||||
u32 type;
|
||||
|
||||
switch (cmd) {
|
||||
case LCM_DELAY_CMD:
|
||||
mdelay(len);
|
||||
continue;
|
||||
|
||||
case LCM_DCS_CMD:
|
||||
switch (len) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
type = MIPI_DSI_DCS_SHORT_WRITE;
|
||||
break;
|
||||
case 2:
|
||||
type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
|
||||
break;
|
||||
default:
|
||||
type = MIPI_DSI_DCS_LONG_WRITE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LCM_GENERIC_CMD:
|
||||
switch (len) {
|
||||
case 0:
|
||||
type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
|
||||
break;
|
||||
case 1:
|
||||
type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
|
||||
break;
|
||||
case 2:
|
||||
type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
|
||||
break;
|
||||
default:
|
||||
type = MIPI_DSI_GENERIC_LONG_WRITE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(BIOS_ERR, "%s: Unknown cmd: %d, "
|
||||
"abort panel initialization.\n", __func__, cmd);
|
||||
return;
|
||||
|
||||
}
|
||||
assert(len <= sizeof(init->data));
|
||||
mtk_dsi_cmdq(init->data, len, type);
|
||||
}
|
||||
}
|
||||
|
||||
int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid,
|
||||
const struct lcm_init_command *init_commands)
|
||||
{
|
||||
int data_rate;
|
||||
u32 bits_per_pixel = mtk_dsi_get_bits_per_pixel(format);
|
||||
|
@ -272,9 +390,9 @@ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid)
|
|||
mtk_dsi_rxtx_control(mode_flags, lanes);
|
||||
mtk_dsi_clk_hs_mode_disable();
|
||||
mtk_dsi_config_vdo_timing(mode_flags, format, lanes, edid, &phy_timing);
|
||||
mtk_dsi_set_mode(mode_flags);
|
||||
mtk_dsi_clk_hs_mode_enable();
|
||||
|
||||
mtk_dsi_send_init_commands(init_commands);
|
||||
mtk_dsi_set_mode(mode_flags);
|
||||
mtk_dsi_start();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -85,14 +85,14 @@ struct dsi_regs {
|
|||
u8 reserved4[16];
|
||||
u32 dsi_vm_cmd_con;
|
||||
u8 reserved5[204];
|
||||
u32 dsi_cmdq0;
|
||||
u32 dsi_cmdq[128];
|
||||
};
|
||||
static struct dsi_regs *const dsi0 = (void *)DSI0_BASE;
|
||||
|
||||
check_member(dsi_regs, dsi_phy_lccon, 0x104);
|
||||
check_member(dsi_regs, dsi_phy_timecon3, 0x11c);
|
||||
check_member(dsi_regs, dsi_vm_cmd_con, 0x130);
|
||||
check_member(dsi_regs, dsi_cmdq0, 0x200);
|
||||
check_member(dsi_regs, dsi_cmdq, 0x200);
|
||||
|
||||
/* DSI_INTSTA */
|
||||
enum {
|
||||
|
@ -324,6 +324,18 @@ struct mtk_phy_timing {
|
|||
u32 d_phy;
|
||||
};
|
||||
|
||||
/* Definitions for cmd in lcm_init_command */
|
||||
#define LCM_END_CMD 0
|
||||
#define LCM_DELAY_CMD 1
|
||||
#define LCM_GENERIC_CMD 2
|
||||
#define LCM_DCS_CMD 3
|
||||
|
||||
struct lcm_init_command {
|
||||
u16 cmd;
|
||||
u16 len;
|
||||
u8 data[8];
|
||||
};
|
||||
|
||||
/* Functions that each SOC should provide. */
|
||||
void mtk_dsi_reset(void);
|
||||
void mtk_dsi_configure_mipi_tx(int data_rate, u32 lanes);
|
||||
|
@ -332,7 +344,8 @@ void mtk_dsi_configure_mipi_tx(int data_rate, u32 lanes);
|
|||
void mtk_dsi_override_phy_timing(struct mtk_phy_timing *timing);
|
||||
|
||||
/* Public API provided in common/dsi.c */
|
||||
int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes,
|
||||
const struct edid *edid);
|
||||
int mtk_dsi_bpp_from_format(u32 format);
|
||||
int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid,
|
||||
const struct lcm_init_command *init_commands);
|
||||
|
||||
#endif /* SOC_MEDIATEK_DSI_COMMON_H */
|
||||
|
|
Loading…
Reference in New Issue