drm/rockchip: lvds: Add support for PX30

Change-Id: I353e76f1afdac02edd2ec78b5d107d6431c4a7d8
Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
Wyon Bi 2018-01-22 17:39:00 +08:00
commit 35cd525521
3 changed files with 97 additions and 24 deletions

View file

@ -25,6 +25,10 @@ Required properties:
- rockchip,grf: phandle to the general register files syscon
For px30 rgb output:
- pinctrl-names: must contain a "m0" or "m1" entry.
- pinctrl-0: pin control group to be used for this controller.
Optional properties
- pinctrl-names: must contain a "lcdc" entry.
- pinctrl-0: pin control group to be used for this controller.
@ -67,6 +71,21 @@ lvds_panel: lvds-panel {
};
};
For Rockchip PX30:
RGB Output Pinctrl Example:
&lvds {
pinctrl-names = "m0";
pinctrl-0 = <&lcdc_rgb_dclk_pin &lcdc_rgb_m0_den_pin &lcdc_rgb_m0_hsync_pin &lcdc_rgb_m0_vsync_pin &lcdc_rgb666_m0_data_pins>;
};
Or
&lvds {
pinctrl-names = "m1";
pinctrl-0 = <&lcdc_rgb_dclk_pin &lcdc_rgb666_m1_data_pins>;
};
For Rockchip RK3288:

View file

@ -81,7 +81,10 @@ struct rockchip_lvds {
struct mutex suspend_lock;
int suspend;
struct dev_pin_info *pins;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_lcdc;
struct pinctrl_state *pins_m0;
struct pinctrl_state *pins_m1;
struct drm_display_mode mode;
};
@ -228,6 +231,21 @@ static int rk336x_lvds_poweron(struct rockchip_lvds *lvds)
u32 val;
if (lvds->output == DISPLAY_OUTPUT_RGB) {
if (LVDS_CHIP(lvds) == PX30_LVDS) {
if (lvds->pins_m0) {
pinctrl_select_state(lvds->pinctrl,
lvds->pins_m0);
return 0;
} else if (lvds->pins_m1) {
pinctrl_select_state(lvds->pinctrl,
lvds->pins_m1);
} else {
dev_err(lvds->dev,
"Can't find pinctrl state m0/m1\n");
WARN_ON(1);
}
}
/* enable lane */
lvds_writel(lvds, MIPIPHY_REG0, 0x7f);
val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) |
@ -330,8 +348,7 @@ static int rockchip_lvds_poweron(struct rockchip_lvds *lvds)
}
if (LVDS_CHIP(lvds) == RK3288_LVDS)
rk3288_lvds_poweron(lvds);
else if ((LVDS_CHIP(lvds) == RK336X_LVDS) ||
(LVDS_CHIP(lvds) == RK3126_LVDS))
else
rk336x_lvds_poweron(lvds);
return 0;
@ -525,9 +542,9 @@ static void rockchip_lvds_grf_config(struct drm_encoder *encoder,
/* iomux to LCD data/sync mode */
if (lvds->output == DISPLAY_OUTPUT_RGB)
if (lvds->pins && !IS_ERR(lvds->pins->default_state))
pinctrl_select_state(lvds->pins->p,
lvds->pins->default_state);
if (lvds->pins_lcdc)
pinctrl_select_state(lvds->pinctrl, lvds->pins_lcdc);
if (LVDS_CHIP(lvds) == RK3288_LVDS) {
val = lvds->format;
if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS)
@ -640,6 +657,14 @@ static void rockchip_lvds_grf_config(struct drm_encoder *encoder,
return;
}
}
} else if (LVDS_CHIP(lvds) == PX30_LVDS) {
val = 0;
if (lvds->output == DISPLAY_OUTPUT_RGB && lvds->pins_m1)
val |= PX30_DPHY_FORCERXMODE(1);
else if (lvds->output == DISPLAY_OUTPUT_LVDS)
val |= PX30_LVDS_OUTPUT_FORMAT(lvds->format) |
PX30_LVDS_MSBSEL(LVDS_MSB_D7);
regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, val);
}
}
@ -666,6 +691,13 @@ static int rockchip_lvds_set_vop_source(struct rockchip_lvds *lvds,
ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con6, val);
if (ret < 0)
return ret;
} else if (LVDS_CHIP(lvds) == PX30_LVDS) {
val = 0;
if (lvds->output == DISPLAY_OUTPUT_RGB)
val |= PX30_RGB_VOP_SEL(ret);
else if (lvds->output == DISPLAY_OUTPUT_LVDS)
val |= PX30_LVDS_VOP_SEL(ret);
regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1, val);
} else {
if (ret)
val = RK3366_LVDS_VOP_SEL_LIT;
@ -753,6 +785,11 @@ static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs = {
.destroy = rockchip_lvds_encoder_destroy,
};
static const struct rockchip_lvds_soc_data px30_lvds_data = {
.chip_type = PX30_LVDS,
.has_vop_sel = true,
};
static struct rockchip_lvds_soc_data rk3126_lvds_data = {
.chip_type = RK3126_LVDS,
.grf_soc_con7 = RK3126_GRF_LVDS_CON0,
@ -782,6 +819,10 @@ static struct rockchip_lvds_soc_data rk3368_lvds_data = {
};
static const struct of_device_id rockchip_lvds_dt_ids[] = {
{
.compatible = "rockchip,px30-lvds",
.data = &px30_lvds_data
},
{
.compatible = "rockchip,rk3126-lvds",
.data = &rk3126_lvds_data
@ -1004,8 +1045,7 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
lvds->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(lvds->regs))
return PTR_ERR(lvds->regs);
} else if ((LVDS_CHIP(lvds) == RK336X_LVDS) ||
(LVDS_CHIP(lvds) == RK3126_LVDS)) {
} else {
/* lvds regs on MIPIPHY_REG */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"mipi_lvds_phy");
@ -1041,23 +1081,27 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
return PTR_ERR(lvds->pclk);
}
lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
GFP_KERNEL);
if (!lvds->pins)
return -ENOMEM;
lvds->pins->p = devm_pinctrl_get(lvds->dev);
if (IS_ERR(lvds->pins->p)) {
dev_info(lvds->dev, "no pinctrl handle\n");
devm_kfree(lvds->dev, lvds->pins);
lvds->pins = NULL;
lvds->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR_OR_NULL(lvds->pinctrl)) {
dev_info(dev, "no pinctrl handle\n");
lvds->pinctrl = NULL;
} else {
lvds->pins->default_state =
pinctrl_lookup_state(lvds->pins->p, "lcdc");
if (IS_ERR(lvds->pins->default_state)) {
dev_info(lvds->dev, "no lcdc pinctrl state\n");
devm_kfree(lvds->dev, lvds->pins);
lvds->pins = NULL;
lvds->pins_lcdc = pinctrl_lookup_state(lvds->pinctrl, "lcdc");
if (IS_ERR(lvds->pins_lcdc)) {
dev_info(dev, "no lcdc pinctrl state\n");
lvds->pins_lcdc = NULL;
}
lvds->pins_m0 = pinctrl_lookup_state(lvds->pinctrl, "m0");
if (IS_ERR(lvds->pins_m0)) {
dev_info(dev, "no m0 pinctrl state\n");
lvds->pins_m0 = NULL;
}
lvds->pins_m1 = pinctrl_lookup_state(lvds->pinctrl, "m1");
if (IS_ERR(lvds->pins_m1)) {
dev_info(dev, "no m1 pinctrl state\n");
lvds->pins_m1 = NULL;
}
}

View file

@ -102,6 +102,15 @@
#define RK3126_GRF_LVDS_CON0 0x0150
#define RK3126_GRF_CON1 0x0144
#define PX30_GRF_PD_VO_CON0 0x0434
#define PX30_GRF_PD_VO_CON1 0x0438
#define PX30_LVDS_OUTPUT_FORMAT(x) (BITS_MASK(x, 0x3, 13) | BITS_EN(0x3, 13))
#define PX30_LVDS_PHY_MODE(x) (BITS_MASK(x, 0x1, 12) | BITS_EN(0x1, 12))
#define PX30_LVDS_MSBSEL(x) (BITS_MASK(x, 0x1, 11) | BITS_EN(0x1, 11))
#define PX30_DPHY_FORCERXMODE(x) (BITS_MASK(x, 0x1, 6) | BITS_EN(0x1, 6))
#define PX30_RGB_VOP_SEL(x) (BITS_MASK(x, 0x1, 2) | BITS_EN(0x1, 2))
#define PX30_LVDS_VOP_SEL(x) (BITS_MASK(x, 0x1, 1) | BITS_EN(0x1, 1))
#define LVDS_FMT_MASK (0x07 << 16)
#define LVDS_MSB BIT(3)
#define LVDS_DUAL BIT(4)
@ -215,6 +224,7 @@ enum {
};
enum rockchip_lvds_sub_devtype {
PX30_LVDS,
RK3126_LVDS,
RK3288_LVDS,
RK336X_LVDS,