summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/rockchip/common/include/soc/vop.h6
-rw-r--r--src/soc/rockchip/common/vop.c9
-rw-r--r--src/soc/rockchip/rk3399/chip.h16
-rw-r--r--src/soc/rockchip/rk3399/display.c58
-rw-r--r--src/soc/rockchip/rk3399/include/soc/addressmap.h3
-rw-r--r--src/soc/rockchip/rk3399/include/soc/display.h5
-rw-r--r--src/soc/rockchip/rk3399/include/soc/mipi.h24
-rw-r--r--src/soc/rockchip/rk3399/mipi.c227
8 files changed, 217 insertions, 131 deletions
diff --git a/src/soc/rockchip/common/include/soc/vop.h b/src/soc/rockchip/common/include/soc/vop.h
index c5c542583d..69d11845c0 100644
--- a/src/soc/rockchip/common/include/soc/vop.h
+++ b/src/soc/rockchip/common/include/soc/vop.h
@@ -120,6 +120,7 @@ enum vop_modes {
VOP_MODE_EDP = 0,
VOP_MODE_HDMI,
VOP_MODE_MIPI,
+ VOP_MODE_DUAL_MIPI,
VOP_MODE_NONE,
VOP_MODE_AUTO_DETECT,
VOP_MODE_UNKNOWN,
@@ -139,7 +140,9 @@ enum vop_modes {
#define M_EDP_OUT_EN (1 << 14)
#define M_HDMI_OUT_EN (1 << 13)
#define M_RGB_OUT_EN (1 << 12)
-#define M_ALL_OUT_EN (M_MIPI_OUT_EN | M_EDP_OUT_EN | M_HDMI_OUT_EN | M_RGB_OUT_EN)
+#define M_DUAL_MIPI_OUT_EN (1 << 3)
+#define M_ALL_OUT_EN (M_MIPI_OUT_EN | M_EDP_OUT_EN | M_HDMI_OUT_EN |\
+ M_RGB_OUT_EN | M_DUAL_MIPI_OUT_EN)
#define M_EDPI_WMS_FS (1 << 10)
#define M_EDPI_WMS_MODE (1 << 9)
#define M_EDPI_HALT_EN (1 << 8)
@@ -154,6 +157,7 @@ enum vop_modes {
#define V_MMU_EN(x) (((x) & 1) << 20)
#define V_DMA_BURST_LENGTH(x) (((x) & 3) << 18)
#define V_MIPI_OUT_EN(x) (((x) & 1) << 15)
+#define V_DUAL_MIPI_EN(x) (((x) & 1) << 3)
#define V_EDP_OUT_EN(x) (((x) & 1) << 14)
#define V_HDMI_OUT_EN(x) (((x) & 1) << 13)
#define V_RGB_OUT_EN(x) (((x) & 1) << 12)
diff --git a/src/soc/rockchip/common/vop.c b/src/soc/rockchip/common/vop.c
index 70d59bd6a8..463159182a 100644
--- a/src/soc/rockchip/common/vop.c
+++ b/src/soc/rockchip/common/vop.c
@@ -119,8 +119,13 @@ void rkvop_mode_set(u32 vop_id, const struct edid *edid, u32 mode)
dsp_out_mode = 15;
break;
case VOP_MODE_MIPI:
- clrsetbits_le32(&preg->sys_ctrl,
- M_ALL_OUT_EN, V_MIPI_OUT_EN(1));
+ clrsetbits_le32(&preg->sys_ctrl, M_ALL_OUT_EN,
+ V_MIPI_OUT_EN(1));
+ dsp_out_mode = 0;
+ break;
+ case VOP_MODE_DUAL_MIPI:
+ clrsetbits_le32(&preg->sys_ctrl, M_ALL_OUT_EN,
+ V_MIPI_OUT_EN(1) | V_DUAL_MIPI_EN(1));
dsp_out_mode = 0;
break;
case VOP_MODE_EDP:
diff --git a/src/soc/rockchip/rk3399/chip.h b/src/soc/rockchip/rk3399/chip.h
index 4b2ccc5b52..b4b3e75605 100644
--- a/src/soc/rockchip/rk3399/chip.h
+++ b/src/soc/rockchip/rk3399/chip.h
@@ -20,24 +20,8 @@
#include <soc/vop.h> /* for vop_modes enum used in devicetree.cb */
struct soc_rockchip_rk3399_config {
- gpio_t lcd_bl_pwm_gpio;
- gpio_t lcd_bl_en_gpio;
- u32 bl_power_on_udelay;
- u32 bl_pwm_to_enable_udelay;
u32 framebuffer_bits_per_pixel;
u32 vop_mode;
- u32 panel_pixel_clock; /* below only be considered for MIPI displays */
- u32 panel_refresh;
- u32 panel_ha;
- u32 panel_hbl;
- u32 panel_hso;
- u32 panel_hspw;
- u32 panel_va;
- u32 panel_vbl;
- u32 panel_vso;
- u32 panel_vspw;
- u32 panel_display_on_mdelay;
- u32 panel_video_mode_mdelay;
};
#endif /* __SOC_ROCKCHIP_RK3399_CHIP_H__ */
diff --git a/src/soc/rockchip/rk3399/display.c b/src/soc/rockchip/rk3399/display.c
index 379e1bfec8..cc265b2edb 100644
--- a/src/soc/rockchip/rk3399/display.c
+++ b/src/soc/rockchip/rk3399/display.c
@@ -48,27 +48,13 @@ static void reset_edp(void)
printk(BIOS_WARNING, "Retrying epd initialization.\n");
}
-static void rk_get_mipi_mode(struct edid *edid, device_t dev)
-{
- struct soc_rockchip_rk3399_config *conf = dev->chip_info;
-
- edid->mode.pixel_clock = conf->panel_pixel_clock;
- edid->mode.refresh = conf->panel_refresh;
- edid->mode.ha = conf->panel_ha;
- edid->mode.hbl = conf->panel_hbl;
- edid->mode.hso = conf->panel_hso;
- edid->mode.hspw = conf->panel_hspw;
- edid->mode.va = conf->panel_va;
- edid->mode.vbl = conf->panel_vbl;
- edid->mode.vso = conf->panel_vso;
- edid->mode.vspw = conf->panel_vspw;
-}
void rk_display_init(device_t dev)
{
struct edid edid;
struct soc_rockchip_rk3399_config *conf = dev->chip_info;
enum vop_modes detected_mode = VOP_MODE_UNKNOWN;
int retry_count = 0;
+ const struct mipi_panel_data *panel_data = NULL;
/* let's use vop0 in rk3399 */
uint32_t vop_id = 0;
@@ -111,13 +97,42 @@ retry_edp:
rkclk_configure_mipi();
rkclk_configure_vop_aclk(vop_id, 200 * MHz);
- /* disable turnrequest turndisable forcetxstop forcerxmode */
+ /*
+ * disable tx0 turnrequest, turndisable,
+ * forcetxstop, forcerxmode
+ */
write32(&rk3399_grf->soc_con22, RK_CLRBITS(0xffff));
- /* select mipi-dsi0 signal from vop0 */
- write32(&rk3399_grf->soc_con20, RK_CLRBITS(1 << 0));
- rk_get_mipi_mode(&edid, dev);
- detected_mode = VOP_MODE_MIPI;
+ /* disable tx1 turndisable, forcetxstop, forcerxmode */
+ write32(&rk3399_grf->soc_con23, RK_CLRBITS(0xfff0));
+
+ /*
+ * enable dphy_tx1rx1_masterslavez,
+ * clear dphy_tx1rx1_enableclk,
+ * clear dphy_tx1rx1_basedir,
+ * disable tx1 turnrequest
+ */
+ write32(&rk3399_grf->soc_con24,
+ RK_CLRSETBITS(1 << 7 | 1 << 6 | 1 << 5 | 0xf,
+ 1 << 7 | 0 << 6 | 0 << 5 | 0 << 0));
+
+ /* dphy_tx1rx1_enable */
+ write32(&rk3399_grf->soc_con23, RK_SETBITS(0xf));
+
+ /* select mipi-dsi0 and mipi-dsi1 signal from vop0 */
+ write32(&rk3399_grf->soc_con20,
+ RK_CLRBITS((1 << 0) | (1 << 4)));
+
+ panel_data = mainboard_get_mipi_mode(&edid);
+ if (panel_data) {
+ if (panel_data->mipi_num > 1)
+ detected_mode = VOP_MODE_DUAL_MIPI;
+ else
+ detected_mode = VOP_MODE_MIPI;
+ } else {
+ printk(BIOS_WARNING, "Can not get mipi panel data\n");
+ return;
+ }
break;
default:
printk(BIOS_WARNING, "Unsupported vop_mode, aborting.\n");
@@ -138,7 +153,8 @@ retry_edp:
switch (detected_mode) {
case VOP_MODE_MIPI:
- rk_mipi_prepare(&edid, conf->panel_display_on_mdelay, conf->panel_video_mode_mdelay);
+ case VOP_MODE_DUAL_MIPI:
+ rk_mipi_prepare(&edid, panel_data);
break;
case VOP_MODE_EDP:
/* will enable edp in depthcharge */
diff --git a/src/soc/rockchip/rk3399/include/soc/addressmap.h b/src/soc/rockchip/rk3399/include/soc/addressmap.h
index 7a365adb86..5dca6bb84e 100644
--- a/src/soc/rockchip/rk3399/include/soc/addressmap.h
+++ b/src/soc/rockchip/rk3399/include/soc/addressmap.h
@@ -59,7 +59,8 @@
#define SARADC_BASE 0xff100000
#define RK_PWM_BASE 0xff420000
#define EDP_BASE 0xff970000
-#define MIPI_BASE 0xff960000
+#define MIPI0_BASE 0xff960000
+#define MIPI1_BASE 0xff968000
#define VOP_BIG_BASE 0xff900000 /* corresponds to vop_id 0 */
#define VOP_LIT_BASE 0xff8f0000 /* corresponds to vop_id 1 */
diff --git a/src/soc/rockchip/rk3399/include/soc/display.h b/src/soc/rockchip/rk3399/include/soc/display.h
index c10f1b9f04..bf90f651a6 100644
--- a/src/soc/rockchip/rk3399/include/soc/display.h
+++ b/src/soc/rockchip/rk3399/include/soc/display.h
@@ -16,9 +16,12 @@
#ifndef __SOC_ROCKCHIP_RK3399_DISPLAY_H__
#define __SOC_ROCKCHIP_RK3399_DISPLAY_H__
+#include <edid.h>
+#include <soc/mipi.h>
+
#define REF_CLK_24M (0x1 << 0)
void rk_display_init(device_t dev);
void mainboard_power_on_backlight(void);
-
+const struct mipi_panel_data *mainboard_get_mipi_mode(struct edid *edid);
#endif
diff --git a/src/soc/rockchip/rk3399/include/soc/mipi.h b/src/soc/rockchip/rk3399/include/soc/mipi.h
index 09285cf51c..933ea89bd4 100644
--- a/src/soc/rockchip/rk3399/include/soc/mipi.h
+++ b/src/soc/rockchip/rk3399/include/soc/mipi.h
@@ -263,8 +263,9 @@ check_member(rk_mipi_regs, dsi_int_msk1, 0xc8);
#define GEN_PLD_R_FULL BIT(5)
#define GEN_RD_CMD_BUSY BIT(6)
-#define MIPI_DSI_DCS_SHORT_WRITE 0x05
-#define MIPI_DSI_DCS_LONG_WRITE 0x39
+#define MIPI_DSI_DCS_SHORT_WRITE 0x05
+#define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23
+#define MIPI_DSI_DCS_LONG_WRITE 0x39
enum mipi_dsi_pixel_format {
MIPI_DSI_FMT_RGB888,
@@ -314,6 +315,7 @@ struct dphy_pll_parameter_map {
};
struct rk_mipi_dsi {
+ struct rk_mipi_regs *mipi_regs;
u64 lane_bps; /* per lane */
u32 lanes;
u32 format;
@@ -321,5 +323,21 @@ struct rk_mipi_dsi {
u16 feedback_div;
};
-void rk_mipi_prepare(const struct edid *edid, u32 display_on_mdelay, u32 video_mode_mdelay);
+struct panel_init_command {
+ u8 cmd;
+ u8 data;
+};
+
+struct mipi_panel_data {
+ u8 mipi_num;
+ enum mipi_dsi_pixel_format format;
+ u8 lanes;
+ u32 display_on_udelay;
+ u32 video_mode_udelay;
+ u32 num_init_commands;
+ struct panel_init_command *init_cmd;
+};
+
+void rk_mipi_prepare(const struct edid *edid,
+ const struct mipi_panel_data *panel_data);
#endif
diff --git a/src/soc/rockchip/rk3399/mipi.c b/src/soc/rockchip/rk3399/mipi.c
index 3f1ddb3664..825eb72366 100644
--- a/src/soc/rockchip/rk3399/mipi.c
+++ b/src/soc/rockchip/rk3399/mipi.c
@@ -30,8 +30,10 @@
#include <soc/soc.h>
#include <timer.h>
-static struct rk_mipi_dsi rk_mipi;
-static struct rk_mipi_regs *mipi_regs = (void *)MIPI_BASE;
+static struct rk_mipi_dsi rk_mipi[2] = {
+ { .mipi_regs = (void *)MIPI0_BASE},
+ { .mipi_regs = (void *)MIPI1_BASE}
+};
/*
* The controller should generate 2 frames before
@@ -110,17 +112,20 @@ static void rk_mipi_dsi_phy_write(struct rk_mipi_dsi *dsi,
* is latched internally as the current test code. Test data is
* programmed internally by rising edge on TESTCLK.
*/
- write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_TESTCLK | PHY_UNTESTCLR);
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl0,
+ PHY_TESTCLK | PHY_UNTESTCLR);
- write32(&mipi_regs->dsi_phy_tst_ctrl1, PHY_TESTEN | PHY_TESTDOUT(0) |
- PHY_TESTDIN(test_code));
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl1,
+ PHY_TESTEN | PHY_TESTDOUT(0) | PHY_TESTDIN(test_code));
- write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_UNTESTCLK | PHY_UNTESTCLR);
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl0,
+ PHY_UNTESTCLK | PHY_UNTESTCLR);
- write32(&mipi_regs->dsi_phy_tst_ctrl1, PHY_UNTESTEN | PHY_TESTDOUT(0) |
- PHY_TESTDIN(test_data));
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl1,
+ PHY_UNTESTEN | PHY_TESTDOUT(0) | PHY_TESTDIN(test_data));
- write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_TESTCLK | PHY_UNTESTCLR);
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl0,
+ PHY_TESTCLK | PHY_UNTESTCLR);
}
/* bytes_per_ns - Nanoseconds to byte clock cycles */
@@ -142,7 +147,7 @@ static int rk_mipi_dsi_wait_phy_lock(struct rk_mipi_dsi *dsi)
stopwatch_init_msecs_expire(&sw, 20);
do {
- val = read32(&mipi_regs->dsi_phy_status);
+ val = read32(&dsi->mipi_regs->dsi_phy_status);
if (val & LOCK)
return 0;
} while (!stopwatch_expired(&sw));
@@ -166,9 +171,9 @@ static int rk_mipi_dsi_phy_init(struct rk_mipi_dsi *dsi)
}
/* Start by clearing PHY state */
- write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_UNTESTCLR);
- write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_TESTCLR);
- write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_UNTESTCLR);
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl0, PHY_UNTESTCLR);
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl0, PHY_TESTCLR);
+ write32(&dsi->mipi_regs->dsi_phy_tst_ctrl0, PHY_UNTESTCLR);
rk_mipi_dsi_phy_write(dsi, PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL,
BYPASS_VCO_RANGE |
@@ -244,8 +249,9 @@ static int rk_mipi_dsi_phy_init(struct rk_mipi_dsi *dsi)
rk_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL,
BIT(5) | bytes_per_ns(dsi, 100));
- write32(&mipi_regs->dsi_phy_rstz, PHY_ENFORCEPLL | PHY_ENABLECLK |
- PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
+ write32(&dsi->mipi_regs->dsi_phy_rstz,
+ PHY_ENFORCEPLL | PHY_ENABLECLK |
+ PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
if (rk_mipi_dsi_wait_phy_lock(dsi)) {
printk(BIOS_ERR, "failed to wait for phy lock state\n");
@@ -254,7 +260,7 @@ static int rk_mipi_dsi_phy_init(struct rk_mipi_dsi *dsi)
stopwatch_init_msecs_expire(&sw, 20);
do {
- val = read32(&mipi_regs->dsi_phy_status);
+ val = read32(&dsi->mipi_regs->dsi_phy_status);
if (val & STOP_STATE_CLK_LANE)
return 0;
} while (!stopwatch_expired(&sw));
@@ -281,7 +287,8 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
}
static int rk_mipi_dsi_get_lane_bps(struct rk_mipi_dsi *dsi,
- const struct edid *edid)
+ const struct edid *edid,
+ const struct mipi_panel_data *panel_data)
{
u64 pclk, target_bps;
u32 max_bps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps * MHz;
@@ -302,7 +309,7 @@ static int rk_mipi_dsi_get_lane_bps(struct rk_mipi_dsi *dsi,
pclk = edid->mode.pixel_clock * MSECS_PER_SEC;
/* take 1 / 0.8, since mbps must bigger than bandwidth of RGB */
- target_bps = pclk / dsi->lanes * bpp / 8 * 10;
+ target_bps = pclk / panel_data->lanes * bpp / 8 * 10;
if (target_bps >= max_bps) {
printk(BIOS_DEBUG, "DPHY clock frequency is out of range\n");
return -1;
@@ -381,38 +388,48 @@ static void rk_mipi_dsi_dpi_config(struct rk_mipi_dsi *dsi)
break;
}
- write32(&mipi_regs->dsi_dpi_vcid, 0);
- write32(&mipi_regs->dsi_dpi_color_coding, color);
+ write32(&dsi->mipi_regs->dsi_dpi_vcid, 0);
+ write32(&dsi->mipi_regs->dsi_dpi_color_coding, color);
- write32(&mipi_regs->dsi_dpi_cfg_pol, 0);
+ write32(&dsi->mipi_regs->dsi_dpi_cfg_pol, 0);
- write32(&mipi_regs->dsi_dpi_lp_cmd_tim, OUTVACT_LPCMD_TIME(4) |
- INVACT_LPCMD_TIME(4));
+ write32(&dsi->mipi_regs->dsi_dpi_lp_cmd_tim,
+ OUTVACT_LPCMD_TIME(4) | INVACT_LPCMD_TIME(4));
}
static void rk_mipi_dsi_packet_handler_config(struct rk_mipi_dsi *dsi)
{
- write32(&mipi_regs->dsi_pckhdl_cfg, EN_CRC_RX | EN_ECC_RX | EN_BTA);
+ write32(&dsi->mipi_regs->dsi_pckhdl_cfg,
+ EN_CRC_RX | EN_ECC_RX | EN_BTA);
}
static void rk_mipi_dsi_video_mode_config(struct rk_mipi_dsi *dsi)
{
- write32(&mipi_regs->dsi_vid_mode_cfg,
+ write32(&dsi->mipi_regs->dsi_vid_mode_cfg,
VID_MODE_TYPE_BURST_SYNC_PULSES | ENABLE_LOW_POWER);
}
-static void rk_mipi_dsi_video_packet_config(struct rk_mipi_dsi *dsi)
+static void rk_mipi_dsi_video_packet_config(struct rk_mipi_dsi *dsi,
+ const struct edid *edid,
+ const struct mipi_panel_data *panel_data)
{
- write32(&mipi_regs->dsi_vid_pkt_size, VID_PKT_SIZE(0x300));
+ int pkt_size;
+
+ if (panel_data->mipi_num > 1)
+ pkt_size = VID_PKT_SIZE(edid->mode.ha / 2 + 4);
+ else
+ pkt_size = VID_PKT_SIZE(edid->mode.ha);
+
+ write32(&dsi->mipi_regs->dsi_vid_pkt_size, pkt_size);
}
static void rk_mipi_dsi_command_mode_config(struct rk_mipi_dsi *dsi)
{
- write32(&mipi_regs->dsi_to_cnt_cfg,
+ write32(&dsi->mipi_regs->dsi_to_cnt_cfg,
HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
- write32(&mipi_regs->dsi_bta_to_cnt, 0xd00);
- write32(&mipi_regs->dsi_cmd_mode_cfg, CMD_MODE_ALL_LP);
- write32(&mipi_regs->dsi_mode_cfg, ENABLE_CMD_MODE);
+ write32(&dsi->mipi_regs->dsi_bta_to_cnt, 0xd00);
+ write32(&dsi->mipi_regs->dsi_cmd_mode_cfg, CMD_MODE_ALL_LP);
+ write32(&dsi->mipi_regs->dsi_mode_cfg, ENABLE_CMD_MODE);
}
/* Get lane byte clock cycles. */
@@ -439,12 +456,12 @@ static void rk_mipi_dsi_line_timer_config(struct rk_mipi_dsi *dsi,
hbp = edid->mode.hbl - edid->mode.hso - edid->mode.hspw;
lbcc = rk_mipi_dsi_get_hcomponent_lbcc(dsi, htotal, edid);
- write32(&mipi_regs->dsi_vid_hline_time, lbcc);
+ write32(&dsi->mipi_regs->dsi_vid_hline_time, lbcc);
lbcc = rk_mipi_dsi_get_hcomponent_lbcc(dsi, hsa, edid);
- write32(&mipi_regs->dsi_vid_hsa_time, lbcc);
+ write32(&dsi->mipi_regs->dsi_vid_hsa_time, lbcc);
lbcc = rk_mipi_dsi_get_hcomponent_lbcc(dsi, hbp, edid);
- write32(&mipi_regs->dsi_vid_hbp_time, lbcc);
+ write32(&dsi->mipi_regs->dsi_vid_hbp_time, lbcc);
}
static void rk_mipi_dsi_vertical_timing_config(struct rk_mipi_dsi *dsi,
@@ -457,10 +474,10 @@ static void rk_mipi_dsi_vertical_timing_config(struct rk_mipi_dsi *dsi,
vfp = edid->mode.vso;
vbp = edid->mode.vbl - edid->mode.vso - edid->mode.vspw;
- write32(&mipi_regs->dsi_vid_vactive_lines, vactive);
- write32(&mipi_regs->dsi_vid_vsa_lines, vsa);
- write32(&mipi_regs->dsi_vid_vfp_lines, vfp);
- write32(&mipi_regs->dsi_vid_vbp_lines, vbp);
+ write32(&dsi->mipi_regs->dsi_vid_vactive_lines, vactive);
+ write32(&dsi->mipi_regs->dsi_vid_vsa_lines, vsa);
+ write32(&dsi->mipi_regs->dsi_vid_vfp_lines, vfp);
+ write32(&dsi->mipi_regs->dsi_vid_vbp_lines, vbp);
}
static void rk_mipi_dsi_dphy_timing_config(struct rk_mipi_dsi *dsi)
@@ -469,40 +486,40 @@ static void rk_mipi_dsi_dphy_timing_config(struct rk_mipi_dsi *dsi)
* HS-PREPARE: 40ns + 4 * UI ~ 85ns + 6 * UI
* HS-EXIT: 100ns
*/
- write32(&mipi_regs->dsi_phy_tmr_cfg, PHY_HS2LP_TIME(0x40) |
+ write32(&dsi->mipi_regs->dsi_phy_tmr_cfg, PHY_HS2LP_TIME(0x40) |
PHY_LP2HS_TIME(0x40) |
MAX_RD_TIME(10000));
- write32(&mipi_regs->dsi_phy_tmr_lpclk_cfg, PHY_CLKHS2LP_TIME(0x40) |
- PHY_CLKLP2HS_TIME(0x40));
+ write32(&dsi->mipi_regs->dsi_phy_tmr_lpclk_cfg,
+ PHY_CLKHS2LP_TIME(0x40) | PHY_CLKLP2HS_TIME(0x40));
}
static void rk_mipi_dsi_clear_err(struct rk_mipi_dsi *dsi)
{
- read32(&mipi_regs->dsi_int_st0);
- read32(&mipi_regs->dsi_int_st1);
- write32(&mipi_regs->dsi_int_msk0, 0);
- write32(&mipi_regs->dsi_int_msk1, 0);
+ read32(&dsi->mipi_regs->dsi_int_st0);
+ read32(&dsi->mipi_regs->dsi_int_st1);
+ write32(&dsi->mipi_regs->dsi_int_msk0, 0);
+ write32(&dsi->mipi_regs->dsi_int_msk1, 0);
}
static void rk_mipi_dsi_dphy_interface_config(struct rk_mipi_dsi *dsi)
{
- write32(&mipi_regs->dsi_phy_if_cfg, PHY_STOP_WAIT_TIME(0x20) |
+ write32(&dsi->mipi_regs->dsi_phy_if_cfg, PHY_STOP_WAIT_TIME(0x20) |
N_LANES(dsi->lanes));
}
static void rk_mipi_dsi_set_mode(struct rk_mipi_dsi *dsi,
enum rk_mipi_dsi_mode mode)
{
- write32(&mipi_regs->dsi_pwr_up, RESET);
+ write32(&dsi->mipi_regs->dsi_pwr_up, RESET);
if (mode == MIPI_DSI_CMD_MODE) {
- write32(&mipi_regs->dsi_mode_cfg, ENABLE_CMD_MODE);
+ write32(&dsi->mipi_regs->dsi_mode_cfg, ENABLE_CMD_MODE);
} else {
- write32(&mipi_regs->dsi_mode_cfg, ENABLE_VIDEO_MODE);
+ write32(&dsi->mipi_regs->dsi_mode_cfg, ENABLE_VIDEO_MODE);
rk_mipi_dsi_video_mode_config(dsi);
- write32(&mipi_regs->dsi_lpclk_ctrl, PHY_TXREQUESTCLKHS);
+ write32(&dsi->mipi_regs->dsi_lpclk_ctrl, PHY_TXREQUESTCLKHS);
}
- write32(&mipi_regs->dsi_pwr_up, POWERUP);
+ write32(&dsi->mipi_regs->dsi_pwr_up, POWERUP);
}
static void rk_mipi_dsi_init(struct rk_mipi_dsi *dsi)
@@ -515,20 +532,21 @@ static void rk_mipi_dsi_init(struct rk_mipi_dsi *dsi)
* which is:
* (lane_mbps >> 3) / 20 > esc_clk_division
*/
- u32 esc_clk_division = div_round_up(dsi->lane_bps, 8 * 20 * USECS_PER_SEC);
+ u32 esc_clk_division = div_round_up(dsi->lane_bps,
+ 8 * 20 * USECS_PER_SEC);
- write32(&mipi_regs->dsi_pwr_up, RESET);
- write32(&mipi_regs->dsi_phy_rstz, PHY_DISFORCEPLL | PHY_DISABLECLK |
- PHY_RSTZ | PHY_SHUTDOWNZ);
- write32(&mipi_regs->dsi_clk_cfg,
+ write32(&dsi->mipi_regs->dsi_pwr_up, RESET);
+ write32(&dsi->mipi_regs->dsi_phy_rstz,
+ PHY_DISFORCEPLL | PHY_DISABLECLK | PHY_RSTZ | PHY_SHUTDOWNZ);
+ write32(&dsi->mipi_regs->dsi_clk_cfg,
TO_CLK_DIVIDSION(10) |
TX_ESC_CLK_DIVIDSION(esc_clk_division));
}
static void rk_mipi_message_config(struct rk_mipi_dsi *dsi)
{
- write32(&mipi_regs->dsi_lpclk_ctrl, 0);
- write32(&mipi_regs->dsi_cmd_mode_cfg, CMD_MODE_ALL_LP);
+ write32(&dsi->mipi_regs->dsi_lpclk_ctrl, 0);
+ write32(&dsi->mipi_regs->dsi_cmd_mode_cfg, CMD_MODE_ALL_LP);
}
static int rk_mipi_dsi_check_cmd_fifo(struct rk_mipi_dsi *dsi)
@@ -538,7 +556,7 @@ static int rk_mipi_dsi_check_cmd_fifo(struct rk_mipi_dsi *dsi)
stopwatch_init_msecs_expire(&sw, 20);
do {
- val = read32(&mipi_regs->dsi_cmd_pkt_status);
+ val = read32(&dsi->mipi_regs->dsi_cmd_pkt_status);
if (!(val & GEN_CMD_FULL))
return 0 ;
} while (!stopwatch_expired(&sw));
@@ -557,12 +575,12 @@ static int rk_mipi_dsi_gen_pkt_hdr_write(struct rk_mipi_dsi *dsi, u32 hdr_val)
return -1;
}
- write32(&mipi_regs->dsi_gen_hdr, hdr_val);
+ write32(&dsi->mipi_regs->dsi_gen_hdr, hdr_val);
mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY;
stopwatch_init_msecs_expire(&sw, 20);
do {
- val = read32(&mipi_regs->dsi_cmd_pkt_status);
+ val = read32(&dsi->mipi_regs->dsi_cmd_pkt_status);
if ((val & mask) == mask)
return 0 ;
} while (!stopwatch_expired(&sw));
@@ -582,37 +600,74 @@ static int rk_mipi_dsi_dcs_cmd(struct rk_mipi_dsi *dsi, u8 cmd)
return rk_mipi_dsi_gen_pkt_hdr_write(dsi, val);
}
-void rk_mipi_prepare(const struct edid *edid, u32 display_on_mdelay, u32 video_mode_mdelay)
+static int rk_mipi_dsi_dci_cmd_arg(struct rk_mipi_dsi *dsi, u8 cmd, u8 arg)
{
- rk_mipi.lanes = 4;
- rk_mipi.format = MIPI_DSI_FMT_RGB888;
- if (rk_mipi_dsi_get_lane_bps(&rk_mipi, edid) < 0)
- return;
+ u32 val;
+ u16 data;
- rk_mipi_dsi_init(&rk_mipi);
- rk_mipi_dsi_dpi_config(&rk_mipi);
- rk_mipi_dsi_packet_handler_config(&rk_mipi);
- rk_mipi_dsi_video_mode_config(&rk_mipi);
- rk_mipi_dsi_video_packet_config(&rk_mipi);
- rk_mipi_dsi_command_mode_config(&rk_mipi);
- rk_mipi_dsi_line_timer_config(&rk_mipi, edid);
- rk_mipi_dsi_vertical_timing_config(&rk_mipi, edid);
- rk_mipi_dsi_dphy_timing_config(&rk_mipi);
- rk_mipi_dsi_dphy_interface_config(&rk_mipi);
- rk_mipi_dsi_clear_err(&rk_mipi);
- if (rk_mipi_dsi_phy_init(&rk_mipi) < 0)
- return;
- rk_mipi_dsi_wait_for_two_frames(&rk_mipi, edid);
+ rk_mipi_message_config(dsi);
- rk_mipi_dsi_set_mode(&rk_mipi, MIPI_DSI_CMD_MODE);
+ data = cmd | (arg << 8);
+ val = GEN_HDATA(data) | GEN_HTYPE(MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM);
- if (rk_mipi_dsi_dcs_cmd(&rk_mipi, MIPI_DCS_EXIT_SLEEP_MODE) < 0)
+ return rk_mipi_dsi_gen_pkt_hdr_write(dsi, val);
+}
+
+static void rk_mipi_enable(struct rk_mipi_dsi *dsi,
+ const struct edid *edid,
+ const struct mipi_panel_data *panel_data)
+{
+ if (rk_mipi_dsi_get_lane_bps(dsi, edid, panel_data) < 0)
return;
- mdelay(display_on_mdelay);
- if (rk_mipi_dsi_dcs_cmd(&rk_mipi, MIPI_DCS_SET_DISPLAY_ON) < 0)
+ rk_mipi_dsi_init(dsi);
+ rk_mipi_dsi_dpi_config(dsi);
+ rk_mipi_dsi_packet_handler_config(dsi);
+ rk_mipi_dsi_video_mode_config(dsi);
+ rk_mipi_dsi_video_packet_config(dsi, edid, panel_data);
+ rk_mipi_dsi_command_mode_config(dsi);
+ rk_mipi_dsi_line_timer_config(dsi, edid);
+ rk_mipi_dsi_vertical_timing_config(dsi, edid);
+ rk_mipi_dsi_dphy_timing_config(dsi);
+ rk_mipi_dsi_dphy_interface_config(dsi);
+ rk_mipi_dsi_clear_err(dsi);
+ if (rk_mipi_dsi_phy_init(dsi) < 0)
return;
- mdelay(video_mode_mdelay);
+ rk_mipi_dsi_wait_for_two_frames(dsi, edid);
- rk_mipi_dsi_set_mode(&rk_mipi, MIPI_DSI_VID_MODE);
+ rk_mipi_dsi_set_mode(dsi, MIPI_DSI_CMD_MODE);
+}
+
+void rk_mipi_prepare(const struct edid *edid,
+ const struct mipi_panel_data *panel_data)
+{
+ int i, num;
+
+ for (i = 0; i < panel_data->mipi_num; i++) {
+ rk_mipi[i].lanes = panel_data->lanes / panel_data->mipi_num;
+ rk_mipi[i].format = panel_data->format;
+ rk_mipi_enable(&rk_mipi[i], edid, panel_data);
+ }
+
+ for (num = 0; num < panel_data->num_init_commands; num++) {
+ for (i = 0; i < panel_data->mipi_num; i++)
+ rk_mipi_dsi_dci_cmd_arg(&rk_mipi[i],
+ panel_data->init_cmd[num].cmd,
+ panel_data->init_cmd[num].data);
+ }
+
+ for (i = 0; i < panel_data->mipi_num; i++) {
+ if (rk_mipi_dsi_dcs_cmd(&rk_mipi[i],
+ MIPI_DCS_EXIT_SLEEP_MODE) < 0)
+ return;
+ }
+ udelay(panel_data->display_on_udelay);
+ for (i = 0; i < panel_data->mipi_num; i++) {
+ if (rk_mipi_dsi_dcs_cmd(&rk_mipi[i],
+ MIPI_DCS_SET_DISPLAY_ON) < 0)
+ return;
+ }
+ udelay(panel_data->video_mode_udelay);
+ for (i = 0; i < panel_data->mipi_num; i++)
+ rk_mipi_dsi_set_mode(&rk_mipi[i], MIPI_DSI_VID_MODE);
}