diff options
| author | Kuogee Hsieh <khsieh@codeaurora.org> | 2015-01-21 15:58:51 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:37:42 -0700 |
| commit | 3c235789a79cfe557e4e88c232c05ff532d1995e (patch) | |
| tree | 96dbcfad65fe93bfdc9de22470b21ac290efa213 /drivers/video/fbdev | |
| parent | b685d84bf97030a3a17d61b59525de95e9d29eb8 (diff) | |
msm: mdss: add thulium dsi phy support
Add dsi phy related supporting functions to configure
timing registers of both data and clock lanes of phy
interface.
Change-Id: I185c26ff2b9f11d9b30f4fee42bc730b69098f0f
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 33 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_host.c | 25 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 11 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 14 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 15 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 239 |
7 files changed, 288 insertions, 52 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index d9a7c7c5e18b..f6f26dceb0ff 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -641,6 +641,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) * to be restored to allow dcs command be * sent to panel */ + mdss_dsi_read_hw_revision(ctrl_pdata); mdss_dsi_restore_intr_mask(ctrl_pdata); pr_debug("%s: panel already on\n", __func__); goto end; @@ -664,6 +665,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) */ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); mdss_dsi_sw_reset(ctrl_pdata, true); + mdss_dsi_read_hw_revision(ctrl_pdata); /* * Issue hardware reset line after enabling the DSI clocks and data @@ -1813,27 +1815,29 @@ int dsi_panel_device_register(struct device_node *pan_node, data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-strength-ctrl", &len); - if ((!data) || (len != 2)) { + if (!data) { pr_err("%s:%d, Unable to read Phy Strength ctrl settings\n", __func__, __LINE__); return -EINVAL; + } else { + pinfo->mipi.dsi_phy_db.strength_len = len; + for (i = 0; i < len; i++) + pinfo->mipi.dsi_phy_db.strength[i] = data[i]; } - pinfo->mipi.dsi_phy_db.strength[0] = data[0]; - pinfo->mipi.dsi_phy_db.strength[1] = data[1]; pinfo->mipi.dsi_phy_db.reg_ldo_mode = of_property_read_bool( ctrl_pdev->dev.of_node, "qcom,regulator-ldo-mode"); data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-regulator-settings", &len); - if ((!data) || (len != 7)) { + if (!data) { pr_err("%s:%d, Unable to read Phy regulator settings\n", __func__, __LINE__); return -EINVAL; - } - for (i = 0; i < len; i++) { - pinfo->mipi.dsi_phy_db.regulator[i] - = data[i]; + } else { + pinfo->mipi.dsi_phy_db.regulator_len = len; + for (i = 0; i < len; i++) + pinfo->mipi.dsi_phy_db.regulator[i] = data[i]; } data = of_get_property(ctrl_pdev->dev.of_node, @@ -1844,20 +1848,19 @@ int dsi_panel_device_register(struct device_node *pan_node, return -EINVAL; } for (i = 0; i < len; i++) { - pinfo->mipi.dsi_phy_db.bistctrl[i] - = data[i]; + pinfo->mipi.dsi_phy_db.bistctrl[i] = data[i]; } data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-lane-config", &len); - if ((!data) || (len != 45)) { + if (!data) { pr_err("%s:%d, Unable to read Phy lane configure settings\n", __func__, __LINE__); return -EINVAL; - } - for (i = 0; i < len; i++) { - pinfo->mipi.dsi_phy_db.lanecfg[i] = - data[i]; + } else { + pinfo->mipi.dsi_phy_db.lanecfg_len = len; + for (i = 0; i < len; i++) + pinfo->mipi.dsi_phy_db.lanecfg[i] = data[i]; } rc = of_property_read_u32(ctrl_pdev->dev.of_node, diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 22eac8623751..2f2d9ab9eb8b 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -53,6 +53,7 @@ #define MDSS_DSI_HW_REV_102 0x10020000 /* 8084 */ #define MDSS_DSI_HW_REV_103 0x10030000 /* 8994 */ #define MDSS_DSI_HW_REV_103_1 0x10030001 /* 8916/8936 */ +#define MDSS_DSI_HW_REV_104 0x10040000 /* thulium */ #define NONE_PANEL "none" @@ -297,6 +298,7 @@ struct mdss_dsi_ctrl_pdata { void (*switch_mode) (struct mdss_panel_data *pdata, int mode); struct mdss_panel_data panel_data; unsigned char *ctrl_base; + u32 hw_rev; struct dss_io_data ctrl_io; struct dss_io_data mmss_misc_io; struct dss_io_data phy_io; @@ -408,6 +410,7 @@ struct dsi_status_data { struct msm_fb_data_type *mfd; }; +void mdss_dsi_read_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); int dsi_panel_device_register(struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata); diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index b947cadb1364..b7b584b4e9b7 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -242,6 +242,15 @@ void mdss_dsi_cmd_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl) MIPI_OUTP((ctrl->ctrl_base) + 0x015c, 0x0); } +void mdss_dsi_read_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl) +{ + /* clock must be on */ + ctrl->hw_rev = MIPI_INP(ctrl->ctrl_base); + + pr_debug("%s: ndx=%d hw_rev=%x\n", __func__, + ctrl->ndx, ctrl->hw_rev); +} + void mdss_dsi_host_init(struct mdss_panel_data *pdata) { u32 dsi_ctrl, intr_ctrl; @@ -1293,7 +1302,6 @@ int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, int short_response, diff, pkt_size, ret = 0; struct dsi_buf *tp, *rp; char cmd; - u32 ctrl_rev; struct mdss_dsi_ctrl_pdata *mctrl = NULL; @@ -1331,7 +1339,6 @@ int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, } do_send: - ctrl_rev = MIPI_INP(ctrl->ctrl_base); ctrl->cmd_cfg_restore = __mdss_dsi_cmd_mode_config(ctrl, 1); if (rlen <= 2) { @@ -1393,7 +1400,7 @@ do_send: goto end; } - if (ctrl_rev >= MDSS_DSI_HW_REV_101) { + if (ctrl->hw_rev >= MDSS_DSI_HW_REV_101) { /* clear the RDBK_DATA registers */ MIPI_OUTP(ctrl->ctrl_base + 0x01d4, 0x1); wmb(); /* make sure the RDBK registers are cleared */ @@ -1593,7 +1600,7 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *rp, int rx_byte) { - u32 *lp, *temp, data, ctrl_rev; + u32 *lp, *temp, data; int i, j = 0, off, cnt; bool ack_error = false; char reg[16]; @@ -1605,12 +1612,10 @@ static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl, cnt += 3; cnt >>= 2; - ctrl_rev = MIPI_INP(ctrl->ctrl_base); - if (cnt > 4) cnt = 4; /* 4 x 32 bits registers only */ - if (ctrl_rev >= MDSS_DSI_HW_REV_101) { + if (ctrl->hw_rev >= MDSS_DSI_HW_REV_101) { rp->read_cnt = (MIPI_INP((ctrl->ctrl_base) + 0x01d4) >> 16); pr_debug("%s: bytes read:%d\n", __func__, rp->read_cnt); @@ -1958,7 +1963,6 @@ static int dsi_event_thread(void *data) struct sched_param param; u32 todo = 0, ln_status; int ret; - u32 ctrl_rev; param.sched_priority = 16; ret = sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m); @@ -2006,7 +2010,6 @@ static int dsi_event_thread(void *data) mdss_dsi_sw_reset(ctrl, true); if (todo & DSI_EV_DLNx_FIFO_OVERFLOW) { - ctrl_rev = MIPI_INP(ctrl->ctrl_base); mutex_lock(&dsi_mtx); /* * For targets other than msm8994, @@ -2018,7 +2021,7 @@ static int dsi_event_thread(void *data) pr_debug("%s: lane_status: 0x%x\n", __func__, ln_status); if (ctrl->recovery - && (ctrl_rev != MDSS_DSI_HW_REV_103) + && (ctrl->hw_rev != MDSS_DSI_HW_REV_103) && (ln_status & DSI_DATA_LANES_STOP_STATE) && !(ln_status @@ -2031,7 +2034,7 @@ static int dsi_event_thread(void *data) DSI_INTR_ERROR_MASK, 1); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); } else if (ctrl->recovery - && (ctrl_rev + && (ctrl->hw_rev == MDSS_DSI_HW_REV_103)) { pr_debug("%s: Handle overflow->Rev_103\n", __func__); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 514ee605b574..62cd76a844fa 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1695,6 +1695,15 @@ static int mdss_panel_parse_dt(struct device_node *np, for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.timing[i] = data[i]; + data = of_get_property(np, "qcom,mdss-dsi-panel-timings-thulium", &len); + if ((!data) || (len != 40)) { + pr_debug("%s:%d, Unable to read thulium Phy lane timing settings", + __func__, __LINE__); + } else { + for (i = 0; i < len; i++) + pinfo->mipi.dsi_phy_db.timing_thulium[i] = data[i]; + } + pinfo->mipi.lp11_init = of_property_read_bool(np, "qcom,mdss-dsi-lp11-init"); rc = of_property_read_u32(np, "qcom,mdss-dsi-init-delay-us", &tmp); diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index d3f4d709e402..0b8f65abe569 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -2986,13 +2986,19 @@ static int mdss_fb_check_var(struct fb_var_screeninfo *var, return -EINVAL; if (mfd->panel_info) { - struct mdss_panel_info panel_info; + struct mdss_panel_info *pinfo; int rc; - memcpy(&panel_info, mfd->panel_info, sizeof(panel_info)); - mdss_fb_var_to_panelinfo(var, &panel_info); + pinfo = kmalloc(sizeof(struct mdss_panel_info), GFP_KERNEL); + if (!pinfo) { + pr_err("unable to allocate memory for pinfo\n"); + return -ENOMEM; + } + memcpy(pinfo, mfd->panel_info, sizeof(*pinfo)); + mdss_fb_var_to_panelinfo(var, pinfo); rc = mdss_fb_send_panel_event(mfd, MDSS_EVENT_CHECK_PARAMS, - &panel_info); + pinfo); + kfree(pinfo); if (IS_ERR_VALUE(rc)) return rc; mfd->panel_reconfig = rc; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 7d4152057de2..d58e23bf40d3 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -231,14 +231,19 @@ struct lcd_panel_info { /* DSI PHY configuration */ struct mdss_dsi_phy_ctrl { - uint32_t regulator[7]; - uint32_t timing[12]; - uint32_t ctrl[4]; - uint32_t strength[2]; + char regulator[7]; /* thulium, 1 * 5 */ + char timing[12]; + char ctrl[4]; + char strength[10]; /* thulium, 2 * 5 */ char bistctrl[6]; uint32_t pll[21]; - char lanecfg[45]; + char lanecfg[45]; /* thulium, 4 * 5 */ bool reg_ldo_mode; + + char timing_thulium[40];/* thulium, 8 * 5 */ + char regulator_len; + char strength_len; + char lanecfg_len; }; struct mipi_panel_info { diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 461ccbe587ce..285e24c70642 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -40,11 +40,20 @@ #define SW_RESET_PLL BIT(0) #define PWRDN_B BIT(7) +/* thulium */ +#define DATALANE_OFFSET_FROM_BASE_THULIUM 0x100 +#define DATALANE_SIZE_THULIUM 0x80 + +#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018 +#define DSIPHY_CMN_CTRL_0 0x001c +#define DSIPHY_CMN_CTRL_1 0x0020 +#define DSIPHY_CMN_LDO_CNTRL 0x004c +#define DSIPHY_PLL_CLKBUFLR_EN 0x041c + static struct dsi_clk_desc dsi_pclk; static void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) { - u32 ctrl_rev; if (ctrl == NULL) { pr_err("%s: Invalid input data\n", __func__); return; @@ -64,8 +73,7 @@ static void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) * Need to turn off the PLL1 to avoid current leakage issues */ if (ctrl->ndx == DSI_CTRL_1) { - ctrl_rev = MIPI_INP(ctrl->ctrl_base); - if (ctrl_rev == MDSS_DSI_HW_REV_103) { + if (ctrl->hw_rev == MDSS_DSI_HW_REV_103) { pr_debug("Turn off PLL 1 registers\n"); clk_set_rate(ctrl->vco_clk, 1); } @@ -74,10 +82,32 @@ static void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl) static void mdss_dsi_phy_regulator_disable(struct mdss_dsi_ctrl_pdata *ctrl) { + if (!ctrl) { + pr_err("%s: Invalid input data\n", __func__); + return; + } + + if (ctrl->hw_rev == MDSS_DSI_HW_REV_104) + return; + MIPI_OUTP(ctrl->shared_ctrl_data->phy_regulator_io.base + 0x018, 0x000); } +static void mdss_dsi_phy_lane_shutdown(struct mdss_dsi_ctrl_pdata *ctrl) +{ + if (!ctrl) { + pr_err("%s: Invalid input data\n", __func__); + return; + } + + if (ctrl->hw_rev == MDSS_DSI_HW_REV_104) + MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, 0x0000); + else + MIPI_OUTP(ctrl->phy_io.base + MDSS_DSI_DSIPHY_CTRL_0, 0x000); + +} + void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl) { struct mdss_dsi_ctrl_pdata *other_ctrl; @@ -98,10 +128,9 @@ void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl) other_ctrl = mdss_dsi_get_other_ctrl(ctrl); if (other_ctrl) - MIPI_OUTP(other_ctrl->phy_io.base + - MDSS_DSI_DSIPHY_CTRL_0, 0x000); + mdss_dsi_phy_lane_shutdown(other_ctrl); - MIPI_OUTP(ctrl->phy_io.base + MDSS_DSI_DSIPHY_CTRL_0, 0x000); + mdss_dsi_phy_lane_shutdown(ctrl); mdss_dsi_phy_regulator_disable(ctrl); @@ -125,6 +154,14 @@ void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl) { struct mdss_dsi_phy_ctrl *pd; + if (!ctrl) { + pr_err("%s: Invalid input data\n", __func__); + return; + } + + if (ctrl->hw_rev == MDSS_DSI_HW_REV_104) + return; + pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db); /* Strength ctrl 1, LP Rx + CD Rxcontention detection */ @@ -200,7 +237,6 @@ static void mdss_dsi_28nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { struct mdss_dsi_phy_ctrl *pd; int i, off, ln, offset; - u32 ctrl_rev; if (!ctrl_pdata) { pr_err("%s: Invalid input data\n", __func__); @@ -244,11 +280,9 @@ static void mdss_dsi_28nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata) MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f); wmb(); - ctrl_rev = MIPI_INP(ctrl_pdata->ctrl_base); - /* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */ if (((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) || - (ctrl_rev == MDSS_DSI_HW_REV_103_1)) + (ctrl_pdata->hw_rev == MDSS_DSI_HW_REV_103_1)) MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01); else MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x00); @@ -272,6 +306,11 @@ static void mdss_dsi_20nm_phy_regulator_enable(struct mdss_dsi_ctrl_pdata pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db); phy_io_base = ctrl_pdata->shared_ctrl_data->phy_regulator_io.base; + if (pd->regulator_len != 7) { + pr_err("%s: wrong regulator settings\n", __func__); + return; + } + if (pd->reg_ldo_mode) { MIPI_OUTP(phy_io_base + MDSS_DSI_DSIPHY_LDO_CNTRL, 0x1d); } else { @@ -298,12 +337,22 @@ static void mdss_dsi_20nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata) pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db); + if (pd->strength_len != 2) { + pr_err("%s: wrong strength ctrl\n", __func__); + return; + } + MIPI_OUTP((ctrl_pdata->phy_io.base) + MDSS_DSI_DSIPHY_STRENGTH_CTRL_0, pd->strength[0]); MIPI_OUTP((ctrl_pdata->phy_io.base) + MDSS_DSI_DSIPHY_GLBL_TEST_CTRL, 0x00); + if (pd->lanecfg_len != 45) { + pr_err("%s: wrong lane cfg\n", __func__); + return; + } + /* 4 lanes + clk lane configuration */ /* lane config n * (0 - 4) & DataPath setup */ for (ln = 0; ln < 5; ln++) { @@ -331,6 +380,150 @@ static void mdss_dsi_20nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata) MIPI_OUTP((ctrl_pdata->phy_io.base) + MDSS_DSI_DSIPHY_CTRL_0, 0x7f); } +static void mdss_dsi_thulium_pll_source_standalone( + struct mdss_dsi_ctrl_pdata *ctrl) +{ + u32 data; + + /* + * pll right output enabled + * bit clk select from left + */ + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_CLKBUFLR_EN, 0x01); + data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL); + data &= ~BIT(2); + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data); +} + +static void mdss_dsi_thulium_pll_source_from_right( + struct mdss_dsi_ctrl_pdata *ctrl) +{ + u32 data; + + /* + * pll left + right output disabled + * bit clk select from right + */ + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_CLKBUFLR_EN, 0x00); + data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL); + data |= BIT(2); + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data); +} + +static void mdss_dsi_thulium_pll_source_from_left( + struct mdss_dsi_ctrl_pdata *ctrl) +{ + u32 data; + + /* + * pll left + right output enabled + * bit clk select from left + */ + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_PLL_CLKBUFLR_EN, 0x03); + data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL); + data &= ~BIT(2); + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data); +} + +static void mdss_dsi_thulium_phy_config(struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct mdss_dsi_phy_ctrl *pd; + int j, off, ln, cnt, ln_off; + u32 data; + char *ip; + void __iomem *base; + + pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db); + + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_LDO_CNTRL, 0x1c); + + /* clk_en */ + data = MIPI_INP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL); + data |= BIT(0); + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data); + + if (pd->lanecfg_len != 20) { + pr_err("%s: wrong lane cfg\n", __func__); + return; + } + + if (pd->strength_len != 10) { + pr_err("%s: wrong strength ctrl\n", __func__); + return; + } + + if (pd->regulator_len != 5) { + pr_err("%s: wrong regulator setting\n", __func__); + return; + } + + /* 4 lanes + clk lane configuration */ + for (ln = 0; ln < 5; ln++) { + /* + * data lane offset frome base: 0x100 + * data lane size: 0x80 + */ + base = ctrl->phy_io.base + + DATALANE_OFFSET_FROM_BASE_THULIUM; + base += (ln * DATALANE_SIZE_THULIUM); /* lane base */ + + /* lane cfg, 4 * 5 */ + cnt = 4; + ln_off = cnt * ln; + ip = &pd->lanecfg[ln_off]; + off = 0x0; + for (j = 0; j < cnt; j++) { + MIPI_OUTP(base + off, *ip++); + off += 4; + } + + /* test str */ + MIPI_OUTP(base + 0x14, 0x0088); /* fixed */ + + /* phy timing, 8 * 5 */ + cnt = 8; + ln_off = cnt * ln; + ip = &pd->timing_thulium[ln_off]; + off = 0x18; + for (j = 0; j < cnt; j++, off += 4) + MIPI_OUTP(base + off, *ip++); + + /* strength, 2 * 5 */ + cnt = 2; + ln_off = cnt * ln; + ip = &pd->strength[ln_off]; + off = 0x38; + for (j = 0; j < cnt; j++, off += 4) + MIPI_OUTP(base + off, *ip++); + + /* vreg ctrl, 1 * 5 */ + cnt = 1; + ln_off = cnt * ln; + ip = &pd->regulator[ln_off]; + off = 0x64; + for (j = 0; j < cnt; j++, off += 4) + MIPI_OUTP(base + off, *ip++); + } + + wmb(); /* make sure registers committed */ + + /* reset digital block */ + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_CTRL_1, 0x80); + udelay(100); + MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_CTRL_1, 0x00); + + if (mdss_dsi_sync_wait_enable(ctrl)) { + if (mdss_dsi_is_left_ctrl(ctrl)) + mdss_dsi_thulium_pll_source_from_left(ctrl); + else + mdss_dsi_thulium_pll_source_from_right(ctrl); + } else { + mdss_dsi_thulium_pll_source_standalone(ctrl); + } + + wmb(); /* make sure registers committed */ +} + static void mdss_dsi_20nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { if (!ctrl_pdata) { @@ -343,20 +536,34 @@ static void mdss_dsi_20nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata) mdss_dsi_20nm_phy_config(ctrl_pdata); } -static void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl) +static void mdss_dsi_thulium_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { - u32 ctrl_rev; + if (!ctrl_pdata) { + pr_err("%s: Invalid input data\n", __func__); + return; + } + + mdss_dsi_thulium_phy_config(ctrl_pdata); +} +static void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl) +{ if (!ctrl) { pr_err("%s: Invalid input data\n", __func__); return; } - ctrl_rev = MIPI_INP(ctrl->ctrl_base); - if (ctrl_rev == MDSS_DSI_HW_REV_103) + switch (ctrl->hw_rev) { + case MDSS_DSI_HW_REV_104: + mdss_dsi_thulium_phy_init(ctrl); + break; + case MDSS_DSI_HW_REV_103: mdss_dsi_20nm_phy_init(ctrl); - else + break; + default: mdss_dsi_28nm_phy_init(ctrl); + break; + } } int mdss_dsi_clk_init(struct platform_device *pdev, |
