diff options
9 files changed, 161 insertions, 64 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt index 4f2ba8c13d92..4a0f4f7682ad 100644 --- a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt +++ b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt | |||
@@ -5,6 +5,7 @@ Required properties for dp-controller: | |||
5 | platform specific such as: | 5 | platform specific such as: |
6 | * "samsung,exynos5-dp" | 6 | * "samsung,exynos5-dp" |
7 | * "rockchip,rk3288-dp" | 7 | * "rockchip,rk3288-dp" |
8 | * "rockchip,rk3399-edp" | ||
8 | -reg: | 9 | -reg: |
9 | physical base address of the controller and length | 10 | physical base address of the controller and length |
10 | of memory mapped region. | 11 | of memory mapped region. |
diff --git a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt index e832ff98fd61..01cced1c2a18 100644 --- a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt | |||
@@ -2,7 +2,8 @@ Rockchip RK3288 specific extensions to the Analogix Display Port | |||
2 | ================================ | 2 | ================================ |
3 | 3 | ||
4 | Required properties: | 4 | Required properties: |
5 | - compatible: "rockchip,rk3288-edp"; | 5 | - compatible: "rockchip,rk3288-dp", |
6 | "rockchip,rk3399-edp"; | ||
6 | 7 | ||
7 | - reg: physical base address of the controller and length | 8 | - reg: physical base address of the controller and length |
8 | 9 | ||
@@ -27,6 +28,12 @@ Required properties: | |||
27 | Port 0: contained 2 endpoints, connecting to the output of vop. | 28 | Port 0: contained 2 endpoints, connecting to the output of vop. |
28 | Port 1: contained 1 endpoint, connecting to the input of panel. | 29 | Port 1: contained 1 endpoint, connecting to the input of panel. |
29 | 30 | ||
31 | Optional property for different chips: | ||
32 | - clocks: from common clock binding: handle to grf_vio clock. | ||
33 | |||
34 | - clock-names: from common clock binding: | ||
35 | Required elements: "grf" | ||
36 | |||
30 | For the below properties, please refer to Analogix DP binding document: | 37 | For the below properties, please refer to Analogix DP binding document: |
31 | * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt | 38 | * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt |
32 | - phys (required) | 39 | - phys (required) |
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 7699597070a1..32715daf73cb 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | |||
@@ -938,7 +938,7 @@ int analogix_dp_get_modes(struct drm_connector *connector) | |||
938 | num_modes += drm_panel_get_modes(dp->plat_data->panel); | 938 | num_modes += drm_panel_get_modes(dp->plat_data->panel); |
939 | 939 | ||
940 | if (dp->plat_data->get_modes) | 940 | if (dp->plat_data->get_modes) |
941 | num_modes += dp->plat_data->get_modes(dp->plat_data); | 941 | num_modes += dp->plat_data->get_modes(dp->plat_data, connector); |
942 | 942 | ||
943 | return num_modes; | 943 | return num_modes; |
944 | } | 944 | } |
@@ -1208,6 +1208,7 @@ static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp) | |||
1208 | 1208 | ||
1209 | switch (dp->plat_data->dev_type) { | 1209 | switch (dp->plat_data->dev_type) { |
1210 | case RK3288_DP: | 1210 | case RK3288_DP: |
1211 | case RK3399_EDP: | ||
1211 | /* | 1212 | /* |
1212 | * Like Rk3288 DisplayPort TRM indicate that "Main link | 1213 | * Like Rk3288 DisplayPort TRM indicate that "Main link |
1213 | * containing 4 physical lanes of 2.7/1.62 Gbps/lane". | 1214 | * containing 4 physical lanes of 2.7/1.62 Gbps/lane". |
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index f09275d40f70..b45638043ec4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | |||
@@ -127,10 +127,10 @@ enum analog_power_block { | |||
127 | }; | 127 | }; |
128 | 128 | ||
129 | enum dp_irq_type { | 129 | enum dp_irq_type { |
130 | DP_IRQ_TYPE_HP_CABLE_IN, | 130 | DP_IRQ_TYPE_HP_CABLE_IN = BIT(0), |
131 | DP_IRQ_TYPE_HP_CABLE_OUT, | 131 | DP_IRQ_TYPE_HP_CABLE_OUT = BIT(1), |
132 | DP_IRQ_TYPE_HP_CHANGE, | 132 | DP_IRQ_TYPE_HP_CHANGE = BIT(2), |
133 | DP_IRQ_TYPE_UNKNOWN, | 133 | DP_IRQ_TYPE_UNKNOWN = BIT(3), |
134 | }; | 134 | }; |
135 | 135 | ||
136 | struct video_info { | 136 | struct video_info { |
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 49205ef02be3..48030f0cf497 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | |||
@@ -74,8 +74,12 @@ void analogix_dp_init_analog_param(struct analogix_dp_device *dp) | |||
74 | reg = SEL_24M | TX_DVDD_BIT_1_0625V; | 74 | reg = SEL_24M | TX_DVDD_BIT_1_0625V; |
75 | writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2); | 75 | writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2); |
76 | 76 | ||
77 | if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) { | 77 | if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) { |
78 | writel(REF_CLK_24M, dp->reg_base + ANALOGIX_DP_PLL_REG_1); | 78 | reg = REF_CLK_24M; |
79 | if (dp->plat_data->dev_type == RK3288_DP) | ||
80 | reg ^= REF_CLK_MASK; | ||
81 | |||
82 | writel(reg, dp->reg_base + ANALOGIX_DP_PLL_REG_1); | ||
79 | writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2); | 83 | writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2); |
80 | writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3); | 84 | writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3); |
81 | writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4); | 85 | writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4); |
@@ -244,7 +248,7 @@ void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, | |||
244 | u32 reg; | 248 | u32 reg; |
245 | u32 phy_pd_addr = ANALOGIX_DP_PHY_PD; | 249 | u32 phy_pd_addr = ANALOGIX_DP_PHY_PD; |
246 | 250 | ||
247 | if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) | 251 | if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) |
248 | phy_pd_addr = ANALOGIX_DP_PD; | 252 | phy_pd_addr = ANALOGIX_DP_PD; |
249 | 253 | ||
250 | switch (block) { | 254 | switch (block) { |
@@ -448,7 +452,7 @@ void analogix_dp_init_aux(struct analogix_dp_device *dp) | |||
448 | analogix_dp_reset_aux(dp); | 452 | analogix_dp_reset_aux(dp); |
449 | 453 | ||
450 | /* Disable AUX transaction H/W retry */ | 454 | /* Disable AUX transaction H/W retry */ |
451 | if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) | 455 | if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) |
452 | reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) | | 456 | reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) | |
453 | AUX_HW_RETRY_COUNT_SEL(3) | | 457 | AUX_HW_RETRY_COUNT_SEL(3) | |
454 | AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; | 458 | AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; |
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index 337912b0aeab..cdcc6c5add5e 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h | |||
@@ -163,8 +163,9 @@ | |||
163 | #define HSYNC_POLARITY_CFG (0x1 << 0) | 163 | #define HSYNC_POLARITY_CFG (0x1 << 0) |
164 | 164 | ||
165 | /* ANALOGIX_DP_PLL_REG_1 */ | 165 | /* ANALOGIX_DP_PLL_REG_1 */ |
166 | #define REF_CLK_24M (0x1 << 1) | 166 | #define REF_CLK_24M (0x1 << 0) |
167 | #define REF_CLK_27M (0x0 << 1) | 167 | #define REF_CLK_27M (0x0 << 0) |
168 | #define REF_CLK_MASK (0x1 << 0) | ||
168 | 169 | ||
169 | /* ANALOGIX_DP_LANE_MAP */ | 170 | /* ANALOGIX_DP_LANE_MAP */ |
170 | #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) | 171 | #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) |
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index 4c1fb3f8b5a6..4f0850585b8e 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c | |||
@@ -67,10 +67,10 @@ static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data) | |||
67 | return exynos_dp_crtc_clock_enable(plat_data, false); | 67 | return exynos_dp_crtc_clock_enable(plat_data, false); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data) | 70 | static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data, |
71 | struct drm_connector *connector) | ||
71 | { | 72 | { |
72 | struct exynos_dp_device *dp = to_dp(plat_data); | 73 | struct exynos_dp_device *dp = to_dp(plat_data); |
73 | struct drm_connector *connector = dp->connector; | ||
74 | struct drm_display_mode *mode; | 74 | struct drm_display_mode *mode; |
75 | int num_modes = 0; | 75 | int num_modes = 0; |
76 | 76 | ||
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index c120172add5c..e81e19a660ad 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/component.h> | 15 | #include <linux/component.h> |
16 | #include <linux/mfd/syscon.h> | 16 | #include <linux/mfd/syscon.h> |
17 | #include <linux/of_device.h> | ||
17 | #include <linux/of_graph.h> | 18 | #include <linux/of_graph.h> |
18 | #include <linux/regmap.h> | 19 | #include <linux/regmap.h> |
19 | #include <linux/reset.h> | 20 | #include <linux/reset.h> |
@@ -33,13 +34,28 @@ | |||
33 | #include "rockchip_drm_drv.h" | 34 | #include "rockchip_drm_drv.h" |
34 | #include "rockchip_drm_vop.h" | 35 | #include "rockchip_drm_vop.h" |
35 | 36 | ||
37 | #define RK3288_GRF_SOC_CON6 0x25c | ||
38 | #define RK3288_EDP_LCDC_SEL BIT(5) | ||
39 | #define RK3399_GRF_SOC_CON20 0x6250 | ||
40 | #define RK3399_EDP_LCDC_SEL BIT(5) | ||
41 | |||
42 | #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) | ||
43 | |||
36 | #define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm) | 44 | #define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm) |
37 | 45 | ||
38 | /* dp grf register offset */ | 46 | /** |
39 | #define GRF_SOC_CON6 0x025c | 47 | * struct rockchip_dp_chip_data - splite the grf setting of kind of chips |
40 | #define GRF_EDP_LCD_SEL_MASK BIT(5) | 48 | * @lcdsel_grf_reg: grf register offset of lcdc select |
41 | #define GRF_EDP_SEL_VOP_LIT BIT(5) | 49 | * @lcdsel_big: reg value of selecting vop big for eDP |
42 | #define GRF_EDP_SEL_VOP_BIG 0 | 50 | * @lcdsel_lit: reg value of selecting vop little for eDP |
51 | * @chip_type: specific chip type | ||
52 | */ | ||
53 | struct rockchip_dp_chip_data { | ||
54 | u32 lcdsel_grf_reg; | ||
55 | u32 lcdsel_big; | ||
56 | u32 lcdsel_lit; | ||
57 | u32 chip_type; | ||
58 | }; | ||
43 | 59 | ||
44 | struct rockchip_dp_device { | 60 | struct rockchip_dp_device { |
45 | struct drm_device *drm_dev; | 61 | struct drm_device *drm_dev; |
@@ -48,9 +64,12 @@ struct rockchip_dp_device { | |||
48 | struct drm_display_mode mode; | 64 | struct drm_display_mode mode; |
49 | 65 | ||
50 | struct clk *pclk; | 66 | struct clk *pclk; |
67 | struct clk *grfclk; | ||
51 | struct regmap *grf; | 68 | struct regmap *grf; |
52 | struct reset_control *rst; | 69 | struct reset_control *rst; |
53 | 70 | ||
71 | const struct rockchip_dp_chip_data *data; | ||
72 | |||
54 | struct analogix_dp_plat_data plat_data; | 73 | struct analogix_dp_plat_data plat_data; |
55 | }; | 74 | }; |
56 | 75 | ||
@@ -92,6 +111,23 @@ static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) | |||
92 | return 0; | 111 | return 0; |
93 | } | 112 | } |
94 | 113 | ||
114 | static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data, | ||
115 | struct drm_connector *connector) | ||
116 | { | ||
117 | struct drm_display_info *di = &connector->display_info; | ||
118 | /* VOP couldn't output YUV video format for eDP rightly */ | ||
119 | u32 mask = DRM_COLOR_FORMAT_YCRCB444 | DRM_COLOR_FORMAT_YCRCB422; | ||
120 | |||
121 | if ((di->color_formats & mask)) { | ||
122 | DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n"); | ||
123 | di->color_formats &= ~mask; | ||
124 | di->color_formats |= DRM_COLOR_FORMAT_RGB444; | ||
125 | di->bpc = 8; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
95 | static bool | 131 | static bool |
96 | rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder, | 132 | rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder, |
97 | const struct drm_display_mode *mode, | 133 | const struct drm_display_mode *mode, |
@@ -119,17 +155,23 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) | |||
119 | return; | 155 | return; |
120 | 156 | ||
121 | if (ret) | 157 | if (ret) |
122 | val = GRF_EDP_SEL_VOP_LIT | (GRF_EDP_LCD_SEL_MASK << 16); | 158 | val = dp->data->lcdsel_lit; |
123 | else | 159 | else |
124 | val = GRF_EDP_SEL_VOP_BIG | (GRF_EDP_LCD_SEL_MASK << 16); | 160 | val = dp->data->lcdsel_big; |
125 | 161 | ||
126 | dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); | 162 | dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); |
127 | 163 | ||
128 | ret = regmap_write(dp->grf, GRF_SOC_CON6, val); | 164 | ret = clk_prepare_enable(dp->grfclk); |
129 | if (ret != 0) { | 165 | if (ret < 0) { |
130 | dev_err(dp->dev, "Could not write to GRF: %d\n", ret); | 166 | dev_err(dp->dev, "failed to enable grfclk %d\n", ret); |
131 | return; | 167 | return; |
132 | } | 168 | } |
169 | |||
170 | ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val); | ||
171 | if (ret != 0) | ||
172 | dev_err(dp->dev, "Could not write to GRF: %d\n", ret); | ||
173 | |||
174 | clk_disable_unprepare(dp->grfclk); | ||
133 | } | 175 | } |
134 | 176 | ||
135 | static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder) | 177 | static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder) |
@@ -143,22 +185,29 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder, | |||
143 | struct drm_connector_state *conn_state) | 185 | struct drm_connector_state *conn_state) |
144 | { | 186 | { |
145 | struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); | 187 | struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); |
188 | struct rockchip_dp_device *dp = to_dp(encoder); | ||
189 | int ret; | ||
146 | 190 | ||
147 | /* | 191 | /* |
148 | * FIXME(Yakir): driver should configure the CRTC output video | 192 | * The hardware IC designed that VOP must output the RGB10 video |
149 | * mode with the display information which indicated the monitor | 193 | * format to eDP controller, and if eDP panel only support RGB8, |
150 | * support colorimetry. | 194 | * then eDP controller should cut down the video data, not via VOP |
151 | * | 195 | * controller, that's why we need to hardcode the VOP output mode |
152 | * But don't know why the CRTC driver seems could only output the | 196 | * to RGA10 here. |
153 | * RGBaaa rightly. For example, if connect the "innolux,n116bge" | ||
154 | * eDP screen, EDID would indicated that screen only accepted the | ||
155 | * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP | ||
156 | * screen would show a blue picture (RGB888 show a green picture). | ||
157 | * But if I configure CTRC to RGBaaa, and eDP driver still keep | ||
158 | * RGB666 input video mode, then screen would works prefect. | ||
159 | */ | 197 | */ |
198 | |||
160 | s->output_mode = ROCKCHIP_OUT_MODE_AAAA; | 199 | s->output_mode = ROCKCHIP_OUT_MODE_AAAA; |
161 | s->output_type = DRM_MODE_CONNECTOR_eDP; | 200 | s->output_type = DRM_MODE_CONNECTOR_eDP; |
201 | if (dp->data->chip_type == RK3399_EDP) { | ||
202 | /* | ||
203 | * For RK3399, VOP Lit must code the out mode to RGB888, | ||
204 | * VOP Big must code the out mode to RGB10. | ||
205 | */ | ||
206 | ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, | ||
207 | encoder); | ||
208 | if (ret > 0) | ||
209 | s->output_mode = ROCKCHIP_OUT_MODE_P888; | ||
210 | } | ||
162 | 211 | ||
163 | return 0; | 212 | return 0; |
164 | } | 213 | } |
@@ -192,6 +241,16 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) | |||
192 | return PTR_ERR(dp->grf); | 241 | return PTR_ERR(dp->grf); |
193 | } | 242 | } |
194 | 243 | ||
244 | dp->grfclk = devm_clk_get(dev, "grf"); | ||
245 | if (PTR_ERR(dp->grfclk) == -ENOENT) { | ||
246 | dp->grfclk = NULL; | ||
247 | } else if (PTR_ERR(dp->grfclk) == -EPROBE_DEFER) { | ||
248 | return -EPROBE_DEFER; | ||
249 | } else if (IS_ERR(dp->grfclk)) { | ||
250 | dev_err(dev, "failed to get grf clock\n"); | ||
251 | return PTR_ERR(dp->grfclk); | ||
252 | } | ||
253 | |||
195 | dp->pclk = devm_clk_get(dev, "pclk"); | 254 | dp->pclk = devm_clk_get(dev, "pclk"); |
196 | if (IS_ERR(dp->pclk)) { | 255 | if (IS_ERR(dp->pclk)) { |
197 | dev_err(dev, "failed to get pclk property\n"); | 256 | dev_err(dev, "failed to get pclk property\n"); |
@@ -246,6 +305,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, | |||
246 | void *data) | 305 | void *data) |
247 | { | 306 | { |
248 | struct rockchip_dp_device *dp = dev_get_drvdata(dev); | 307 | struct rockchip_dp_device *dp = dev_get_drvdata(dev); |
308 | const struct rockchip_dp_chip_data *dp_data; | ||
249 | struct drm_device *drm_dev = data; | 309 | struct drm_device *drm_dev = data; |
250 | int ret; | 310 | int ret; |
251 | 311 | ||
@@ -256,10 +316,15 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, | |||
256 | */ | 316 | */ |
257 | dev_set_drvdata(dev, NULL); | 317 | dev_set_drvdata(dev, NULL); |
258 | 318 | ||
319 | dp_data = of_device_get_match_data(dev); | ||
320 | if (!dp_data) | ||
321 | return -ENODEV; | ||
322 | |||
259 | ret = rockchip_dp_init(dp); | 323 | ret = rockchip_dp_init(dp); |
260 | if (ret < 0) | 324 | if (ret < 0) |
261 | return ret; | 325 | return ret; |
262 | 326 | ||
327 | dp->data = dp_data; | ||
263 | dp->drm_dev = drm_dev; | 328 | dp->drm_dev = drm_dev; |
264 | 329 | ||
265 | ret = rockchip_dp_drm_create_encoder(dp); | 330 | ret = rockchip_dp_drm_create_encoder(dp); |
@@ -270,9 +335,10 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, | |||
270 | 335 | ||
271 | dp->plat_data.encoder = &dp->encoder; | 336 | dp->plat_data.encoder = &dp->encoder; |
272 | 337 | ||
273 | dp->plat_data.dev_type = RK3288_DP; | 338 | dp->plat_data.dev_type = dp->data->chip_type; |
274 | dp->plat_data.power_on = rockchip_dp_poweron; | 339 | dp->plat_data.power_on = rockchip_dp_poweron; |
275 | dp->plat_data.power_off = rockchip_dp_powerdown; | 340 | dp->plat_data.power_off = rockchip_dp_powerdown; |
341 | dp->plat_data.get_modes = rockchip_dp_get_modes; | ||
276 | 342 | ||
277 | return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); | 343 | return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); |
278 | } | 344 | } |
@@ -292,38 +358,33 @@ static int rockchip_dp_probe(struct platform_device *pdev) | |||
292 | { | 358 | { |
293 | struct device *dev = &pdev->dev; | 359 | struct device *dev = &pdev->dev; |
294 | struct device_node *panel_node, *port, *endpoint; | 360 | struct device_node *panel_node, *port, *endpoint; |
361 | struct drm_panel *panel = NULL; | ||
295 | struct rockchip_dp_device *dp; | 362 | struct rockchip_dp_device *dp; |
296 | struct drm_panel *panel; | ||
297 | 363 | ||
298 | port = of_graph_get_port_by_id(dev->of_node, 1); | 364 | port = of_graph_get_port_by_id(dev->of_node, 1); |
299 | if (!port) { | 365 | if (port) { |
300 | dev_err(dev, "can't find output port\n"); | 366 | endpoint = of_get_child_by_name(port, "endpoint"); |
301 | return -EINVAL; | 367 | of_node_put(port); |
302 | } | 368 | if (!endpoint) { |
303 | 369 | dev_err(dev, "no output endpoint found\n"); | |
304 | endpoint = of_get_child_by_name(port, "endpoint"); | 370 | return -EINVAL; |
305 | of_node_put(port); | 371 | } |
306 | if (!endpoint) { | 372 | |
307 | dev_err(dev, "no output endpoint found\n"); | 373 | panel_node = of_graph_get_remote_port_parent(endpoint); |
308 | return -EINVAL; | 374 | of_node_put(endpoint); |
309 | } | 375 | if (!panel_node) { |
310 | 376 | dev_err(dev, "no output node found\n"); | |
311 | panel_node = of_graph_get_remote_port_parent(endpoint); | 377 | return -EINVAL; |
312 | of_node_put(endpoint); | 378 | } |
313 | if (!panel_node) { | 379 | |
314 | dev_err(dev, "no output node found\n"); | 380 | panel = of_drm_find_panel(panel_node); |
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | panel = of_drm_find_panel(panel_node); | ||
319 | if (!panel) { | ||
320 | DRM_ERROR("failed to find panel\n"); | ||
321 | of_node_put(panel_node); | 381 | of_node_put(panel_node); |
322 | return -EPROBE_DEFER; | 382 | if (!panel) { |
383 | DRM_ERROR("failed to find panel\n"); | ||
384 | return -EPROBE_DEFER; | ||
385 | } | ||
323 | } | 386 | } |
324 | 387 | ||
325 | of_node_put(panel_node); | ||
326 | |||
327 | dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); | 388 | dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); |
328 | if (!dp) | 389 | if (!dp) |
329 | return -ENOMEM; | 390 | return -ENOMEM; |
@@ -356,8 +417,23 @@ static const struct dev_pm_ops rockchip_dp_pm_ops = { | |||
356 | #endif | 417 | #endif |
357 | }; | 418 | }; |
358 | 419 | ||
420 | static const struct rockchip_dp_chip_data rk3399_edp = { | ||
421 | .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, | ||
422 | .lcdsel_big = HIWORD_UPDATE(0, RK3399_EDP_LCDC_SEL), | ||
423 | .lcdsel_lit = HIWORD_UPDATE(RK3399_EDP_LCDC_SEL, RK3399_EDP_LCDC_SEL), | ||
424 | .chip_type = RK3399_EDP, | ||
425 | }; | ||
426 | |||
427 | static const struct rockchip_dp_chip_data rk3288_dp = { | ||
428 | .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, | ||
429 | .lcdsel_big = HIWORD_UPDATE(0, RK3288_EDP_LCDC_SEL), | ||
430 | .lcdsel_lit = HIWORD_UPDATE(RK3288_EDP_LCDC_SEL, RK3288_EDP_LCDC_SEL), | ||
431 | .chip_type = RK3288_DP, | ||
432 | }; | ||
433 | |||
359 | static const struct of_device_id rockchip_dp_dt_ids[] = { | 434 | static const struct of_device_id rockchip_dp_dt_ids[] = { |
360 | {.compatible = "rockchip,rk3288-dp",}, | 435 | {.compatible = "rockchip,rk3288-dp", .data = &rk3288_dp }, |
436 | {.compatible = "rockchip,rk3399-edp", .data = &rk3399_edp }, | ||
361 | {} | 437 | {} |
362 | }; | 438 | }; |
363 | MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids); | 439 | MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids); |
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index 25afb31f0389..261b86d20e77 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h | |||
@@ -16,8 +16,14 @@ | |||
16 | enum analogix_dp_devtype { | 16 | enum analogix_dp_devtype { |
17 | EXYNOS_DP, | 17 | EXYNOS_DP, |
18 | RK3288_DP, | 18 | RK3288_DP, |
19 | RK3399_EDP, | ||
19 | }; | 20 | }; |
20 | 21 | ||
22 | static inline bool is_rockchip(enum analogix_dp_devtype type) | ||
23 | { | ||
24 | return type == RK3288_DP || type == RK3399_EDP; | ||
25 | } | ||
26 | |||
21 | struct analogix_dp_plat_data { | 27 | struct analogix_dp_plat_data { |
22 | enum analogix_dp_devtype dev_type; | 28 | enum analogix_dp_devtype dev_type; |
23 | struct drm_panel *panel; | 29 | struct drm_panel *panel; |
@@ -28,7 +34,8 @@ struct analogix_dp_plat_data { | |||
28 | int (*power_off)(struct analogix_dp_plat_data *); | 34 | int (*power_off)(struct analogix_dp_plat_data *); |
29 | int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *, | 35 | int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *, |
30 | struct drm_connector *); | 36 | struct drm_connector *); |
31 | int (*get_modes)(struct analogix_dp_plat_data *); | 37 | int (*get_modes)(struct analogix_dp_plat_data *, |
38 | struct drm_connector *); | ||
32 | }; | 39 | }; |
33 | 40 | ||
34 | int analogix_dp_resume(struct device *dev); | 41 | int analogix_dp_resume(struct device *dev); |