mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
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:
@@ -25,6 +25,10 @@ Required properties:
|
|||||||
|
|
||||||
- rockchip,grf: phandle to the general register files syscon
|
- 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
|
Optional properties
|
||||||
- pinctrl-names: must contain a "lcdc" entry.
|
- pinctrl-names: must contain a "lcdc" entry.
|
||||||
- pinctrl-0: pin control group to be used for this controller.
|
- 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:
|
For Rockchip RK3288:
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,10 @@ struct rockchip_lvds {
|
|||||||
|
|
||||||
struct mutex suspend_lock;
|
struct mutex suspend_lock;
|
||||||
int suspend;
|
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;
|
struct drm_display_mode mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -228,6 +231,21 @@ static int rk336x_lvds_poweron(struct rockchip_lvds *lvds)
|
|||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
if (lvds->output == DISPLAY_OUTPUT_RGB) {
|
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 */
|
/* enable lane */
|
||||||
lvds_writel(lvds, MIPIPHY_REG0, 0x7f);
|
lvds_writel(lvds, MIPIPHY_REG0, 0x7f);
|
||||||
val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) |
|
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)
|
if (LVDS_CHIP(lvds) == RK3288_LVDS)
|
||||||
rk3288_lvds_poweron(lvds);
|
rk3288_lvds_poweron(lvds);
|
||||||
else if ((LVDS_CHIP(lvds) == RK336X_LVDS) ||
|
else
|
||||||
(LVDS_CHIP(lvds) == RK3126_LVDS))
|
|
||||||
rk336x_lvds_poweron(lvds);
|
rk336x_lvds_poweron(lvds);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -525,9 +542,9 @@ static void rockchip_lvds_grf_config(struct drm_encoder *encoder,
|
|||||||
|
|
||||||
/* iomux to LCD data/sync mode */
|
/* iomux to LCD data/sync mode */
|
||||||
if (lvds->output == DISPLAY_OUTPUT_RGB)
|
if (lvds->output == DISPLAY_OUTPUT_RGB)
|
||||||
if (lvds->pins && !IS_ERR(lvds->pins->default_state))
|
if (lvds->pins_lcdc)
|
||||||
pinctrl_select_state(lvds->pins->p,
|
pinctrl_select_state(lvds->pinctrl, lvds->pins_lcdc);
|
||||||
lvds->pins->default_state);
|
|
||||||
if (LVDS_CHIP(lvds) == RK3288_LVDS) {
|
if (LVDS_CHIP(lvds) == RK3288_LVDS) {
|
||||||
val = lvds->format;
|
val = lvds->format;
|
||||||
if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS)
|
if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS)
|
||||||
@@ -640,6 +657,14 @@ static void rockchip_lvds_grf_config(struct drm_encoder *encoder,
|
|||||||
return;
|
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);
|
ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con6, val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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 {
|
} else {
|
||||||
if (ret)
|
if (ret)
|
||||||
val = RK3366_LVDS_VOP_SEL_LIT;
|
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,
|
.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 = {
|
static struct rockchip_lvds_soc_data rk3126_lvds_data = {
|
||||||
.chip_type = RK3126_LVDS,
|
.chip_type = RK3126_LVDS,
|
||||||
.grf_soc_con7 = RK3126_GRF_LVDS_CON0,
|
.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[] = {
|
static const struct of_device_id rockchip_lvds_dt_ids[] = {
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,px30-lvds",
|
||||||
|
.data = &px30_lvds_data
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.compatible = "rockchip,rk3126-lvds",
|
.compatible = "rockchip,rk3126-lvds",
|
||||||
.data = &rk3126_lvds_data
|
.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);
|
lvds->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(lvds->regs))
|
if (IS_ERR(lvds->regs))
|
||||||
return PTR_ERR(lvds->regs);
|
return PTR_ERR(lvds->regs);
|
||||||
} else if ((LVDS_CHIP(lvds) == RK336X_LVDS) ||
|
} else {
|
||||||
(LVDS_CHIP(lvds) == RK3126_LVDS)) {
|
|
||||||
/* lvds regs on MIPIPHY_REG */
|
/* lvds regs on MIPIPHY_REG */
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||||
"mipi_lvds_phy");
|
"mipi_lvds_phy");
|
||||||
@@ -1041,23 +1081,27 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(lvds->pclk);
|
return PTR_ERR(lvds->pclk);
|
||||||
}
|
}
|
||||||
|
|
||||||
lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
|
lvds->pinctrl = devm_pinctrl_get(dev);
|
||||||
GFP_KERNEL);
|
if (IS_ERR_OR_NULL(lvds->pinctrl)) {
|
||||||
if (!lvds->pins)
|
dev_info(dev, "no pinctrl handle\n");
|
||||||
return -ENOMEM;
|
lvds->pinctrl = NULL;
|
||||||
|
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
lvds->pins->default_state =
|
lvds->pins_lcdc = pinctrl_lookup_state(lvds->pinctrl, "lcdc");
|
||||||
pinctrl_lookup_state(lvds->pins->p, "lcdc");
|
if (IS_ERR(lvds->pins_lcdc)) {
|
||||||
if (IS_ERR(lvds->pins->default_state)) {
|
dev_info(dev, "no lcdc pinctrl state\n");
|
||||||
dev_info(lvds->dev, "no lcdc pinctrl state\n");
|
lvds->pins_lcdc = NULL;
|
||||||
devm_kfree(lvds->dev, lvds->pins);
|
}
|
||||||
lvds->pins = 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,15 @@
|
|||||||
#define RK3126_GRF_LVDS_CON0 0x0150
|
#define RK3126_GRF_LVDS_CON0 0x0150
|
||||||
#define RK3126_GRF_CON1 0x0144
|
#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_FMT_MASK (0x07 << 16)
|
||||||
#define LVDS_MSB BIT(3)
|
#define LVDS_MSB BIT(3)
|
||||||
#define LVDS_DUAL BIT(4)
|
#define LVDS_DUAL BIT(4)
|
||||||
@@ -215,6 +224,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum rockchip_lvds_sub_devtype {
|
enum rockchip_lvds_sub_devtype {
|
||||||
|
PX30_LVDS,
|
||||||
RK3126_LVDS,
|
RK3126_LVDS,
|
||||||
RK3288_LVDS,
|
RK3288_LVDS,
|
||||||
RK336X_LVDS,
|
RK336X_LVDS,
|
||||||
|
|||||||
Reference in New Issue
Block a user