Commit ef6eba19 authored by Chris Zhong's avatar Chris Zhong Committed by Sean Paul

drm/rockchip/dsi: dw-mipi: support RK3399 mipi dsi

The vopb/vopl switch register of RK3399 mipi is different from RK3288,
the default setting for mipi dsi mode is different too, so add a
of_device_id structure to distinguish them, and make sure set the
correct mode before mipi phy init.
Signed-off-by: default avatarChris Zhong <zyw@rock-chips.com>
Signed-off-by: default avatarMark Yao <mark.yao@rock-chips.com>
Reviewed-by: default avatarSean Paul <seanpaul@chromium.org>
Signed-off-by: default avatarSean Paul <seanpaul@chromium.org>
Link: http://patchwork.freedesktop.org/patch/msgid/1487577744-2855-3-git-send-email-zyw@rock-chips.com
parent 7fea5243
...@@ -29,9 +29,17 @@ ...@@ -29,9 +29,17 @@
#define DRIVER_NAME "dw-mipi-dsi" #define DRIVER_NAME "dw-mipi-dsi"
#define GRF_SOC_CON6 0x025c #define RK3288_GRF_SOC_CON6 0x025c
#define DSI0_SEL_VOP_LIT (1 << 6) #define RK3288_DSI0_SEL_VOP_LIT BIT(6)
#define DSI1_SEL_VOP_LIT (1 << 9) #define RK3288_DSI1_SEL_VOP_LIT BIT(9)
#define RK3399_GRF_SOC_CON19 0x6250
#define RK3399_DSI0_SEL_VOP_LIT BIT(0)
#define RK3399_DSI1_SEL_VOP_LIT BIT(4)
/* disable turnrequest, turndisable, forcetxstopmode, forcerxmode */
#define RK3399_GRF_SOC_CON22 0x6258
#define RK3399_GRF_DSI_MODE 0xffff0000
#define DSI_VERSION 0x00 #define DSI_VERSION 0x00
#define DSI_PWR_UP 0x04 #define DSI_PWR_UP 0x04
...@@ -266,6 +274,11 @@ enum { ...@@ -266,6 +274,11 @@ enum {
}; };
struct dw_mipi_dsi_plat_data { struct dw_mipi_dsi_plat_data {
u32 dsi0_en_bit;
u32 dsi1_en_bit;
u32 grf_switch_reg;
u32 grf_dsi0_mode;
u32 grf_dsi0_mode_reg;
unsigned int max_data_lanes; unsigned int max_data_lanes;
enum drm_mode_status (*mode_valid)(struct drm_connector *connector, enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
struct drm_display_mode *mode); struct drm_display_mode *mode);
...@@ -282,6 +295,7 @@ struct dw_mipi_dsi { ...@@ -282,6 +295,7 @@ struct dw_mipi_dsi {
struct clk *pllref_clk; struct clk *pllref_clk;
struct clk *pclk; struct clk *pclk;
struct clk *phy_cfg_clk;
unsigned int lane_mbps; /* per lane */ unsigned int lane_mbps; /* per lane */
u32 channel; u32 channel;
...@@ -422,6 +436,12 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) ...@@ -422,6 +436,12 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR); dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR);
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR);
ret = clk_prepare_enable(dsi->phy_cfg_clk);
if (ret) {
dev_err(dsi->dev, "Failed to enable phy_cfg_clk\n");
return ret;
}
dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE | dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE |
VCO_RANGE_CON_SEL(vco) | VCO_RANGE_CON_SEL(vco) |
VCO_IN_CAP_CON_LOW | VCO_IN_CAP_CON_LOW |
...@@ -478,17 +498,18 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) ...@@ -478,17 +498,18 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US); val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US);
if (ret < 0) { if (ret < 0) {
dev_err(dsi->dev, "failed to wait for phy lock state\n"); dev_err(dsi->dev, "failed to wait for phy lock state\n");
return ret; goto phy_init_end;
} }
ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
val, val & STOP_STATE_CLK_LANE, 1000, val, val & STOP_STATE_CLK_LANE, 1000,
PHY_STATUS_TIMEOUT_US); PHY_STATUS_TIMEOUT_US);
if (ret < 0) { if (ret < 0)
dev_err(dsi->dev, dev_err(dsi->dev,
"failed to wait for phy clk lane stop state\n"); "failed to wait for phy clk lane stop state\n");
return ret;
} phy_init_end:
clk_disable_unprepare(dsi->phy_cfg_clk);
return ret; return ret;
} }
...@@ -924,6 +945,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) ...@@ -924,6 +945,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
{ {
struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
const struct dw_mipi_dsi_plat_data *pdata = dsi->pdata;
int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder); int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder);
u32 val; u32 val;
int ret; int ret;
...@@ -949,6 +971,10 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) ...@@ -949,6 +971,10 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
dw_mipi_dsi_dphy_interface_config(dsi); dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi); dw_mipi_dsi_clear_err(dsi);
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
pdata->grf_dsi0_mode);
dw_mipi_dsi_phy_init(dsi); dw_mipi_dsi_phy_init(dsi);
dw_mipi_dsi_wait_for_two_frames(mode); dw_mipi_dsi_wait_for_two_frames(mode);
...@@ -962,11 +988,11 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) ...@@ -962,11 +988,11 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
clk_disable_unprepare(dsi->pclk); clk_disable_unprepare(dsi->pclk);
if (mux) if (mux)
val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16); val = pdata->dsi0_en_bit | (pdata->dsi0_en_bit << 16);
else else
val = DSI0_SEL_VOP_LIT << 16; val = pdata->dsi0_en_bit << 16;
regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val); regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
} }
...@@ -1125,14 +1151,29 @@ static enum drm_mode_status rk3288_mipi_dsi_mode_valid( ...@@ -1125,14 +1151,29 @@ static enum drm_mode_status rk3288_mipi_dsi_mode_valid(
} }
static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = { static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3288_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3288_DSI1_SEL_VOP_LIT,
.grf_switch_reg = RK3288_GRF_SOC_CON6,
.max_data_lanes = 4, .max_data_lanes = 4,
.mode_valid = rk3288_mipi_dsi_mode_valid, .mode_valid = rk3288_mipi_dsi_mode_valid,
}; };
static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
.grf_switch_reg = RK3399_GRF_SOC_CON19,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
.max_data_lanes = 4,
};
static const struct of_device_id dw_mipi_dsi_dt_ids[] = { static const struct of_device_id dw_mipi_dsi_dt_ids[] = {
{ {
.compatible = "rockchip,rk3288-mipi-dsi", .compatible = "rockchip,rk3288-mipi-dsi",
.data = &rk3288_mipi_dsi_drv_data, .data = &rk3288_mipi_dsi_drv_data,
}, {
.compatible = "rockchip,rk3399-mipi-dsi",
.data = &rk3399_mipi_dsi_drv_data,
}, },
{ /* sentinel */ } { /* sentinel */ }
}; };
...@@ -1213,6 +1254,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ...@@ -1213,6 +1254,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
clk_disable_unprepare(dsi->pclk); clk_disable_unprepare(dsi->pclk);
} }
dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
if (IS_ERR(dsi->phy_cfg_clk)) {
ret = PTR_ERR(dsi->phy_cfg_clk);
if (ret != -ENOENT) {
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
dsi->phy_cfg_clk = NULL;
dev_dbg(dev, "have not phy_cfg_clk\n");
}
ret = clk_prepare_enable(dsi->pllref_clk); ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) { if (ret) {
dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__); dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment