From: WeiYong Bi Date: Wed, 12 Jul 2017 06:20:34 +0000 (+0800) Subject: drm/rockchip: lvds: Add support for rk3366 X-Git-Tag: release-20171130_firefly~4^2~164 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d86682da2cce8b6a4f1ab257a136b7e097dde3db;p=firefly-linux-kernel-4.4.55.git drm/rockchip: lvds: Add support for rk3366 Change-Id: Iaf54c4667042b0b24a9083cb7ca931c1b0603804 Signed-off-by: WeiYong Bi --- diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt new file mode 100644 index 000000000000..1f436f2261ec --- /dev/null +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt @@ -0,0 +1,110 @@ +Rockchip RK3288 LVDS interface +================================ + +Required properties: +- compatible: matching the soc type, one of + - "rockchip,rk3288-lvds"; + - "rockchip,rk3366-lvds"; + - "rockchip,rk3368-lvds"; + +- reg: physical base address of the controller and length + of memory mapped region. +- reg-names: the name to indicate register. example: + - "mipi_lvds_phy": lvds phy register, this's included in the MIPI phy module + - "mipi_lvds_ctl": lvds control register, this's included in the MIPI + controller module +- clocks: must include clock specifiers corresponding to entries in the + clock-names property. +- clock-names: must contain "pclk_lvds" + +- avdd1v0-supply: regulator phandle for 1.0V analog power +- avdd1v8-supply: regulator phandle for 1.8V analog power +- avdd3v3-supply: regulator phandle for 3.3V analog power + +- rockchip,grf: phandle to the general register files syscon + +- rockchip,data-mapping: should be "vesa" or "jeida", + This describes how the color bits are laid out in the + serialized LVDS signal. +- rockchip,data-width : should be <18> or <24>; +- rockchip,output: should be "rgb", "lvds" or "duallvds", + This describes the output face. + +Optional properties +- pinctrl-names: must contain a "default" entry. +- pinctrl-0: pin control group to be used for this controller. +- pinctrl-1: pin control group to be used for gpio. + +Required nodes: + +The lvds has two video ports as described by + Documentation/devicetree/bindings/media/video-interfaces.txt. +Their connections are modeled using the OF graph bindings specified in + Documentation/devicetree/bindings/graph.txt. + +- video port 0 for the VOP inputs +- video port 1 for either a panel or subsequent encoder + +Example: + +For Rockchip RK3288: + + lvds: lvds@ff96c000 { + compatible = "rockchip,rk3288-lvds"; + rockchip,grf = <&grf>; + reg = <0xff96c000 0x4000>; + clocks = <&cru PCLK_LVDS_PHY>; + clock-names = "pclk_lvds"; + avdd1v0-supply = <&vdd10_lcd>; + avdd1v8-supply = <&vcc18_lcd>; + avdd3v3-supply = <&vcca_33>; + rockchip,data-mapping = "jeida"; + rockchip,data-width = <24>; + rockchip,output = "rgb"; + ports { + #address-cells = <1>; + #size-cells = <0>; + + lvds_in: port@0 { + reg = <0>; + + lvds_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_lvds>; + }; + lvds_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_lvds>; + }; + }; + + lvds_out: port@1 { + reg = <1>; + + lvds_out_panel: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + }; + +For Rockchip RK3368: + + lvds: lvds@ff968000 { + compatible = "rockchip,rk3368-lvds"; + reg = <0x0 0xff968000 0x0 0x4000>, <0x0 0xff9600a0 0x0 0x20>; + reg-names = "mipi_lvds_phy", "mipi_lvds_ctl"; + clocks = <&cru PCLK_DPHYTX0>, <&cru PCLK_MIPI_DSI0>; + clock-names = "pclk_lvds", "pclk_lvds_ctl"; + power-domains = <&power RK3368_PD_VIO>; + rockchip,grf = <&grf>; + pinctrl-names = "lcdc", "gpio"; + pinctrl-0 = <&lcdc_lcdc>; + pinctrl-1 = <&lcdc_gpio>; + + ports { + + ... + + }; + }; diff --git a/Documentation/devicetree/bindings/video/rockchip-lvds.txt b/Documentation/devicetree/bindings/video/rockchip-lvds.txt deleted file mode 100644 index 51f4864b8c21..000000000000 --- a/Documentation/devicetree/bindings/video/rockchip-lvds.txt +++ /dev/null @@ -1,109 +0,0 @@ -Rockchip RK3288 LVDS interface -================================ - -Required properties: -- compatible: matching the soc type, one of - - "rockchip,rk3288-lvds"; - - "rockchip,rk33xx-lvds"; - -- reg: physical base address of the controller and length - of memory mapped region. -- reg-names: the name to indicate register. example: - - "mipi_lvds_phy": lvds phy register, this's included in the MIPI phy module - - "mipi_lvds_ctl": lvds control register, this's included in the MIPI - controller module -- clocks: must include clock specifiers corresponding to entries in the - clock-names property. -- clock-names: must contain "pclk_lvds" - -- avdd1v0-supply: regulator phandle for 1.0V analog power -- avdd1v8-supply: regulator phandle for 1.8V analog power -- avdd3v3-supply: regulator phandle for 3.3V analog power - -- rockchip,grf: phandle to the general register files syscon - -- rockchip,data-mapping: should be "vesa" or "jeida", - This describes how the color bits are laid out in the - serialized LVDS signal. -- rockchip,data-width : should be <18> or <24>; -- rockchip,output: should be "rgb", "lvds" or "duallvds", - This describes the output face. - -Optional properties -- pinctrl-names: must contain a "default" entry. -- pinctrl-0: pin control group to be used for this controller. -- pinctrl-1: pin control group to be used for gpio. - -Required nodes: - -The lvds has two video ports as described by - Documentation/devicetree/bindings/media/video-interfaces.txt. -Their connections are modeled using the OF graph bindings specified in - Documentation/devicetree/bindings/graph.txt. - -- video port 0 for the VOP inputs -- video port 1 for either a panel or subsequent encoder - -Example: - -For Rockchip RK3288: - - lvds: lvds@ff96c000 { - compatible = "rockchip,rk3288-lvds"; - rockchip,grf = <&grf>; - reg = <0xff96c000 0x4000>; - clocks = <&cru PCLK_LVDS_PHY>; - clock-names = "pclk_lvds"; - avdd1v0-supply = <&vdd10_lcd>; - avdd1v8-supply = <&vcc18_lcd>; - avdd3v3-supply = <&vcca_33>; - rockchip,data-mapping = "jeida"; - rockchip,data-width = <24>; - rockchip,output = "rgb"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - lvds_in: port@0 { - reg = <0>; - - lvds_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_lvds>; - }; - lvds_in_vopl: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_lvds>; - }; - }; - - lvds_out: port@1 { - reg = <1>; - - lvds_out_panel: endpoint { - remote-endpoint = <&panel_in>; - }; - }; - }; - }; - -For Rockchip RK3368: - - lvds: lvds@ff968000 { - compatible = "rockchip,rk33xx-lvds"; - reg = <0x0 0xff968000 0x0 0x4000>, <0x0 0xff9600a0 0x0 0x20>; - reg-names = "mipi_lvds_phy", "mipi_lvds_ctl"; - clocks = <&cru PCLK_DPHYTX0>, <&cru PCLK_MIPI_DSI0>; - clock-names = "pclk_lvds", "pclk_lvds_ctl"; - power-domains = <&power RK3368_PD_VIO>; - rockchip,grf = <&grf>; - pinctrl-names = "lcdc", "gpio"; - pinctrl-0 = <&lcdc_lcdc>; - pinctrl-1 = <&lcdc_gpio>; - - ports { - - ... - - }; - }; \ No newline at end of file diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 067910d19dc9..f8fd4875722f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -54,6 +54,8 @@ struct rockchip_lvds_soc_data { int grf_soc_con6; int grf_soc_con7; int grf_soc_con15; + + bool has_vop_sel; }; struct rockchip_lvds { @@ -215,7 +217,7 @@ static int rk3288_lvds_poweron(struct rockchip_lvds *lvds) return 0; } -static int rk3368_lvds_poweron(struct rockchip_lvds *lvds) +static int rk336x_lvds_poweron(struct rockchip_lvds *lvds) { u32 delay_times = 20; @@ -255,7 +257,7 @@ static int rk3368_lvds_poweron(struct rockchip_lvds *lvds) return 0; } -static void rk3368_output_ttl(struct rockchip_lvds *lvds) +static void rk336x_output_ttl(struct rockchip_lvds *lvds) { u32 val = 0; @@ -270,10 +272,10 @@ static void rk3368_output_ttl(struct rockchip_lvds *lvds) v_MSB_SEL(1) | v_DIG_INTER_RST(1); lvds_writel(lvds, MIPIPHY_REGE0, val); - rk3368_lvds_poweron(lvds); + rk336x_lvds_poweron(lvds); } -static void rk3368_output_lvds(struct rockchip_lvds *lvds) +static void rk336x_output_lvds(struct rockchip_lvds *lvds) { /* digital internal disable */ lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0)); @@ -289,16 +291,16 @@ static void rk3368_output_lvds(struct rockchip_lvds *lvds) m_MSB_SEL | m_DIG_INTER_RST, v_MSB_SEL(1) | v_DIG_INTER_RST(1)); - rk3368_lvds_poweron(lvds); + rk336x_lvds_poweron(lvds); lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1)); } -static int rk3368_lvds_output(struct rockchip_lvds *lvds) +static int rk336x_lvds_output(struct rockchip_lvds *lvds) { if (lvds->output == DISPLAY_OUTPUT_RGB) - rk3368_output_ttl(lvds); + rk336x_output_ttl(lvds); else - rk3368_output_lvds(lvds); + rk336x_output_lvds(lvds); return 0; } @@ -328,8 +330,8 @@ static int rockchip_lvds_poweron(struct rockchip_lvds *lvds) } if (LVDS_CHIP(lvds) == RK3288_LVDS) rk3288_lvds_poweron(lvds); - else if (LVDS_CHIP(lvds) == RK3368_LVDS) - rk3368_lvds_output(lvds); + else if (LVDS_CHIP(lvds) == RK336X_LVDS) + rk336x_lvds_output(lvds); return 0; } @@ -353,8 +355,8 @@ static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) pm_runtime_put(lvds->dev); if (lvds->pclk) clk_disable(lvds->pclk); - } else if (LVDS_CHIP(lvds) == RK3368_LVDS) { - val = v_RK3368_LVDSMODE_EN(0) | v_RK3368_MIPIPHY_TTL_EN(0); + } else if (LVDS_CHIP(lvds) == RK336X_LVDS) { + val = v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(0); ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); if (ret != 0) { dev_err(lvds->dev, "Could not write to GRF: %d\n", ret); @@ -513,7 +515,7 @@ static void rockchip_lvds_encoder_mode_set(struct drm_encoder *encoder, dev_err(lvds->dev, "Could not write to GRF: %d\n", ret); return; } - } else if (LVDS_CHIP(lvds) == RK3368_LVDS) { + } else if (LVDS_CHIP(lvds) == RK336X_LVDS) { if (lvds->output == DISPLAY_OUTPUT_RGB) { /* iomux to lcdc */ if (lvds->pins && !IS_ERR(lvds->pins->default_state)) @@ -522,10 +524,10 @@ static void rockchip_lvds_encoder_mode_set(struct drm_encoder *encoder, lvds_dsi_writel(lvds, 0x0, 0x4);/*set clock lane enable*/ /* enable lvds mode */ - val = v_RK3368_LVDSMODE_EN(0) | - v_RK3368_MIPIPHY_TTL_EN(1) | - v_RK3368_MIPIPHY_LANE0_EN(1) | - v_RK3368_MIPIDPI_FORCEX_EN(1); + val = v_RK336X_LVDSMODE_EN(0) | + v_RK336X_MIPIPHY_TTL_EN(1) | + v_RK336X_MIPIPHY_LANE0_EN(1) | + v_RK336X_MIPIDPI_FORCEX_EN(1); ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); if (ret != 0) { @@ -533,7 +535,7 @@ static void rockchip_lvds_encoder_mode_set(struct drm_encoder *encoder, "Could not write to GRF: %d\n", ret); return; } - val = v_RK3368_FORCE_JETAG(0); + val = v_RK336X_FORCE_JETAG(0); ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con15, val); if (ret != 0) { @@ -543,13 +545,14 @@ static void rockchip_lvds_encoder_mode_set(struct drm_encoder *encoder, } } else if (lvds->output == DISPLAY_OUTPUT_LVDS) { /* enable lvds mode */ - val = v_RK3368_LVDSMODE_EN(1) | v_RK3368_MIPIPHY_TTL_EN(0); + val = v_RK336X_LVDSMODE_EN(1) | + v_RK336X_MIPIPHY_TTL_EN(0); /* config lvds_format */ - val |= v_RK3368_LVDS_OUTPUT_FORMAT(lvds->format); + val |= v_RK336X_LVDS_OUTPUT_FORMAT(lvds->format); /* LSB receive mode */ - val |= v_RK3368_LVDS_MSBSEL(LVDS_MSB_D7); - val |= v_RK3368_MIPIPHY_LANE0_EN(1) | - v_RK3368_MIPIDPI_FORCEX_EN(1); + val |= v_RK336X_LVDS_MSBSEL(LVDS_MSB_D7); + val |= v_RK336X_MIPIPHY_LANE0_EN(1) | + v_RK336X_MIPIDPI_FORCEX_EN(1); ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); if (ret != 0) { @@ -567,6 +570,9 @@ static int rockchip_lvds_set_vop_source(struct rockchip_lvds *lvds, u32 val; int ret; + if (!lvds->soc_data->has_vop_sel) + return 0; + ret = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder); if (ret < 0) return ret; @@ -581,7 +587,14 @@ 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 (ret) + val = RK3366_LVDS_VOP_SEL_LIT; + else + val = RK3366_LVDS_VOP_SEL_BIG; + regmap_write(lvds->grf, RK3366_GRF_SOC_CON0, val); } + return 0; } @@ -637,14 +650,21 @@ static struct rockchip_lvds_soc_data rk3288_lvds_data = { .chip_type = RK3288_LVDS, .grf_soc_con6 = 0x025c, .grf_soc_con7 = 0x0260, + .has_vop_sel = true, +}; + +static struct rockchip_lvds_soc_data rk3366_lvds_data = { + .chip_type = RK336X_LVDS, + .grf_soc_con7 = RK3366_GRF_SOC_CON5, + .grf_soc_con15 = RK3366_GRF_SOC_CON6, + .has_vop_sel = true, }; -static struct rockchip_lvds_soc_data rk33xx_lvds_data = { - .chip_type = RK3368_LVDS, - .grf_soc_con5 = 0x0414, - .grf_soc_con6 = 0x0418, - .grf_soc_con7 = 0x041c, - .grf_soc_con15 = 0x043c, +static struct rockchip_lvds_soc_data rk3368_lvds_data = { + .chip_type = RK336X_LVDS, + .grf_soc_con7 = RK3368_GRF_SOC_CON7, + .grf_soc_con15 = RK3368_GRF_SOC_CON15, + .has_vop_sel = false, }; static const struct of_device_id rockchip_lvds_dt_ids[] = { @@ -653,8 +673,12 @@ static const struct of_device_id rockchip_lvds_dt_ids[] = { .data = &rk3288_lvds_data }, { - .compatible = "rockchip,rk33xx-lvds", - .data = &rk33xx_lvds_data + .compatible = "rockchip,rk3366-lvds", + .data = &rk3366_lvds_data + }, + { + .compatible = "rockchip,rk3368-lvds", + .data = &rk3368_lvds_data }, {} }; @@ -830,7 +854,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) == RK3368_LVDS) { + } else if (LVDS_CHIP(lvds) == RK336X_LVDS) { /* lvds regs on MIPIPHY_REG */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mipi_lvds_phy"); diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.h b/drivers/gpu/drm/rockchip/rockchip_lvds.h index 803566b37955..28ac030effec 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.h +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.h @@ -89,6 +89,15 @@ #define RK3288_LVDS_SOC_CON6_SEL_VOP_LIT BIT(3) +#define RK3366_GRF_SOC_CON0 0x0400 +#define RK3366_LVDS_VOP_SEL_LIT (BITS_MASK(1, 1, 0) | BITS_EN(1, 0)) +#define RK3366_LVDS_VOP_SEL_BIG (BITS_MASK(0, 1, 0) | BITS_EN(1, 0)) +#define RK3366_GRF_SOC_CON5 0x0414 +#define RK3366_GRF_SOC_CON6 0x0418 + +#define RK3368_GRF_SOC_CON7 0x041c +#define RK3368_GRF_SOC_CON15 0x043c + #define LVDS_FMT_MASK (0x07 << 16) #define LVDS_MSB BIT(3) #define LVDS_DUAL BIT(4) @@ -169,13 +178,13 @@ #define v_LANE1_EN(x) BITS_MASK(x, 1, 6) #define v_LANE0_EN(x) BITS_MASK(x, 1, 7) -#define v_RK3368_LVDS_OUTPUT_FORMAT(x) (BITS_MASK(x, 3, 13) | BITS_EN(3, 13)) -#define v_RK3368_LVDS_MSBSEL(x) (BITS_MASK(x, 1, 11) | BITS_EN(1, 11)) -#define v_RK3368_LVDSMODE_EN(x) (BITS_MASK(x, 1, 12) | BITS_EN(1, 12)) -#define v_RK3368_MIPIPHY_TTL_EN(x) (BITS_MASK(x, 1, 15) | BITS_EN(1, 15)) -#define v_RK3368_MIPIPHY_LANE0_EN(x) (BITS_MASK(x, 1, 5) | BITS_EN(1, 5)) -#define v_RK3368_MIPIDPI_FORCEX_EN(x) (BITS_MASK(x, 1, 6) | BITS_EN(1, 6)) -#define v_RK3368_FORCE_JETAG(x) (BITS_MASK(x, 1, 13) | BITS_EN(1, 13)) +#define v_RK336X_LVDS_OUTPUT_FORMAT(x) (BITS_MASK(x, 3, 13) | BITS_EN(3, 13)) +#define v_RK336X_LVDS_MSBSEL(x) (BITS_MASK(x, 1, 11) | BITS_EN(1, 11)) +#define v_RK336X_LVDSMODE_EN(x) (BITS_MASK(x, 1, 12) | BITS_EN(1, 12)) +#define v_RK336X_MIPIPHY_TTL_EN(x) (BITS_MASK(x, 1, 15) | BITS_EN(1, 15)) +#define v_RK336X_MIPIPHY_LANE0_EN(x) (BITS_MASK(x, 1, 5) | BITS_EN(1, 5)) +#define v_RK336X_MIPIDPI_FORCEX_EN(x) (BITS_MASK(x, 1, 6) | BITS_EN(1, 6)) +#define v_RK336X_FORCE_JETAG(x) (BITS_MASK(x, 1, 13) | BITS_EN(1, 13)) enum { LVDS_MSB_D0 = 0, @@ -184,7 +193,7 @@ enum { enum rockchip_lvds_sub_devtype { RK3288_LVDS, - RK3368_LVDS, + RK336X_LVDS, }; #endif /* _ROCKCHIP_LVDS_ */