1 /*
2  * Rockchip SoC DP (Display Port) interface driver.
3  *
4  * Copyright (C) Fuzhou Rockchip Electronics Co., Ltd.
5  * Author: Andy Yan <andy.yan@rock-chips.com>
6  *         Yakir Yang <ykk@rock-chips.com>
7  *         Jeff Chen <jeff.chen@rock-chips.com>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2 of the License, or (at your
12  * option) any later version.
13  */
14 
15 #include <linux/component.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/of_device.h>
18 #include <linux/of_graph.h>
19 #include <linux/regmap.h>
20 #include <linux/reset.h>
21 #include <linux/clk.h>
22 
23 #include <drm/drmP.h>
24 #include <drm/drm_crtc_helper.h>
25 #include <drm/drm_dp_helper.h>
26 #include <drm/drm_of.h>
27 #include <drm/drm_panel.h>
28 
29 #include <video/of_videomode.h>
30 #include <video/videomode.h>
31 
32 #include <drm/bridge/analogix_dp.h>
33 
34 #include "rockchip_drm_drv.h"
35 #include "rockchip_drm_vop.h"
36 
37 #define RK3288_GRF_SOC_CON6		0x25c
38 #define RK3288_EDP_LCDC_SEL		BIT(5)
39 
40 #define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
41 
42 #define to_dp(nm)	container_of(nm, struct rockchip_dp_device, nm)
43 
44 /**
45  * struct rockchip_dp_chip_data - splite the grf setting of kind of chips
46  * @lcdsel_grf_reg: grf register offset of lcdc select
47  * @lcdsel_big: reg value of selecting vop big for eDP
48  * @lcdsel_lit: reg value of selecting vop little for eDP
49  * @chip_type: specific chip type
50  */
51 struct rockchip_dp_chip_data {
52 	u32	lcdsel_grf_reg;
53 	u32	lcdsel_big;
54 	u32	lcdsel_lit;
55 	u32	chip_type;
56 };
57 
58 struct rockchip_dp_device {
59 	struct drm_device        *drm_dev;
60 	struct device            *dev;
61 	struct drm_encoder       encoder;
62 	struct drm_display_mode  mode;
63 
64 	struct clk               *pclk;
65 	struct regmap            *grf;
66 	struct reset_control     *rst;
67 
68 	const struct rockchip_dp_chip_data *data;
69 
70 	struct analogix_dp_plat_data plat_data;
71 };
72 
73 static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
74 {
75 	reset_control_assert(dp->rst);
76 	usleep_range(10, 20);
77 	reset_control_deassert(dp->rst);
78 
79 	return 0;
80 }
81 
82 static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
83 {
84 	struct rockchip_dp_device *dp = to_dp(plat_data);
85 	int ret;
86 
87 	ret = clk_prepare_enable(dp->pclk);
88 	if (ret < 0) {
89 		dev_err(dp->dev, "failed to enable pclk %d\n", ret);
90 		return ret;
91 	}
92 
93 	ret = rockchip_dp_pre_init(dp);
94 	if (ret < 0) {
95 		dev_err(dp->dev, "failed to dp pre init %d\n", ret);
96 		return ret;
97 	}
98 
99 	return 0;
100 }
101 
102 static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
103 {
104 	struct rockchip_dp_device *dp = to_dp(plat_data);
105 
106 	clk_disable_unprepare(dp->pclk);
107 
108 	return 0;
109 }
110 
111 static bool
112 rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder,
113 				   const struct drm_display_mode *mode,
114 				   struct drm_display_mode *adjusted_mode)
115 {
116 	/* do nothing */
117 	return true;
118 }
119 
120 static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder,
121 					     struct drm_display_mode *mode,
122 					     struct drm_display_mode *adjusted)
123 {
124 	/* do nothing */
125 }
126 
127 static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
128 {
129 	struct rockchip_dp_device *dp = to_dp(encoder);
130 	int ret;
131 	u32 val;
132 
133 	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
134 	if (ret < 0)
135 		return;
136 
137 	if (ret)
138 		val = dp->data->lcdsel_lit;
139 	else
140 		val = dp->data->lcdsel_big;
141 
142 	dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
143 
144 	ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val);
145 	if (ret != 0) {
146 		dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
147 		return;
148 	}
149 }
150 
151 static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
152 {
153 	/* do nothing */
154 }
155 
156 static int
157 rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
158 				      struct drm_crtc_state *crtc_state,
159 				      struct drm_connector_state *conn_state)
160 {
161 	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
162 
163 	/*
164 	 * FIXME(Yakir): driver should configure the CRTC output video
165 	 * mode with the display information which indicated the monitor
166 	 * support colorimetry.
167 	 *
168 	 * But don't know why the CRTC driver seems could only output the
169 	 * RGBaaa rightly. For example, if connect the "innolux,n116bge"
170 	 * eDP screen, EDID would indicated that screen only accepted the
171 	 * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP
172 	 * screen would show a blue picture (RGB888 show a green picture).
173 	 * But if I configure CTRC to RGBaaa, and eDP driver still keep
174 	 * RGB666 input video mode, then screen would works prefect.
175 	 */
176 	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
177 	s->output_type = DRM_MODE_CONNECTOR_eDP;
178 
179 	return 0;
180 }
181 
182 static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
183 	.mode_fixup = rockchip_dp_drm_encoder_mode_fixup,
184 	.mode_set = rockchip_dp_drm_encoder_mode_set,
185 	.enable = rockchip_dp_drm_encoder_enable,
186 	.disable = rockchip_dp_drm_encoder_nop,
187 	.atomic_check = rockchip_dp_drm_encoder_atomic_check,
188 };
189 
190 static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
191 {
192 	drm_encoder_cleanup(encoder);
193 }
194 
195 static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
196 	.destroy = rockchip_dp_drm_encoder_destroy,
197 };
198 
199 static int rockchip_dp_init(struct rockchip_dp_device *dp)
200 {
201 	struct device *dev = dp->dev;
202 	struct device_node *np = dev->of_node;
203 	int ret;
204 
205 	dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
206 	if (IS_ERR(dp->grf)) {
207 		dev_err(dev, "failed to get rockchip,grf property\n");
208 		return PTR_ERR(dp->grf);
209 	}
210 
211 	dp->pclk = devm_clk_get(dev, "pclk");
212 	if (IS_ERR(dp->pclk)) {
213 		dev_err(dev, "failed to get pclk property\n");
214 		return PTR_ERR(dp->pclk);
215 	}
216 
217 	dp->rst = devm_reset_control_get(dev, "dp");
218 	if (IS_ERR(dp->rst)) {
219 		dev_err(dev, "failed to get dp reset control\n");
220 		return PTR_ERR(dp->rst);
221 	}
222 
223 	ret = clk_prepare_enable(dp->pclk);
224 	if (ret < 0) {
225 		dev_err(dp->dev, "failed to enable pclk %d\n", ret);
226 		return ret;
227 	}
228 
229 	ret = rockchip_dp_pre_init(dp);
230 	if (ret < 0) {
231 		dev_err(dp->dev, "failed to pre init %d\n", ret);
232 		return ret;
233 	}
234 
235 	return 0;
236 }
237 
238 static int rockchip_dp_drm_create_encoder(struct rockchip_dp_device *dp)
239 {
240 	struct drm_encoder *encoder = &dp->encoder;
241 	struct drm_device *drm_dev = dp->drm_dev;
242 	struct device *dev = dp->dev;
243 	int ret;
244 
245 	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
246 							     dev->of_node);
247 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
248 
249 	ret = drm_encoder_init(drm_dev, encoder, &rockchip_dp_encoder_funcs,
250 			       DRM_MODE_ENCODER_TMDS, NULL);
251 	if (ret) {
252 		DRM_ERROR("failed to initialize encoder with drm\n");
253 		return ret;
254 	}
255 
256 	drm_encoder_helper_add(encoder, &rockchip_dp_encoder_helper_funcs);
257 
258 	return 0;
259 }
260 
261 static int rockchip_dp_bind(struct device *dev, struct device *master,
262 			    void *data)
263 {
264 	struct rockchip_dp_device *dp = dev_get_drvdata(dev);
265 	const struct rockchip_dp_chip_data *dp_data;
266 	struct drm_device *drm_dev = data;
267 	int ret;
268 
269 	/*
270 	 * Just like the probe function said, we don't need the
271 	 * device drvrate anymore, we should leave the charge to
272 	 * analogix dp driver, set the device drvdata to NULL.
273 	 */
274 	dev_set_drvdata(dev, NULL);
275 
276 	dp_data = of_device_get_match_data(dev);
277 	if (!dp_data)
278 		return -ENODEV;
279 
280 	ret = rockchip_dp_init(dp);
281 	if (ret < 0)
282 		return ret;
283 
284 	dp->data = dp_data;
285 	dp->drm_dev = drm_dev;
286 
287 	ret = rockchip_dp_drm_create_encoder(dp);
288 	if (ret) {
289 		DRM_ERROR("failed to create drm encoder\n");
290 		return ret;
291 	}
292 
293 	dp->plat_data.encoder = &dp->encoder;
294 
295 	dp->plat_data.dev_type = dp->data->chip_type;
296 	dp->plat_data.power_on = rockchip_dp_poweron;
297 	dp->plat_data.power_off = rockchip_dp_powerdown;
298 
299 	return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
300 }
301 
302 static void rockchip_dp_unbind(struct device *dev, struct device *master,
303 			       void *data)
304 {
305 	return analogix_dp_unbind(dev, master, data);
306 }
307 
308 static const struct component_ops rockchip_dp_component_ops = {
309 	.bind = rockchip_dp_bind,
310 	.unbind = rockchip_dp_unbind,
311 };
312 
313 static int rockchip_dp_probe(struct platform_device *pdev)
314 {
315 	struct device *dev = &pdev->dev;
316 	struct device_node *panel_node, *port, *endpoint;
317 	struct rockchip_dp_device *dp;
318 	struct drm_panel *panel;
319 
320 	port = of_graph_get_port_by_id(dev->of_node, 1);
321 	if (!port) {
322 		dev_err(dev, "can't find output port\n");
323 		return -EINVAL;
324 	}
325 
326 	endpoint = of_get_child_by_name(port, "endpoint");
327 	of_node_put(port);
328 	if (!endpoint) {
329 		dev_err(dev, "no output endpoint found\n");
330 		return -EINVAL;
331 	}
332 
333 	panel_node = of_graph_get_remote_port_parent(endpoint);
334 	of_node_put(endpoint);
335 	if (!panel_node) {
336 		dev_err(dev, "no output node found\n");
337 		return -EINVAL;
338 	}
339 
340 	panel = of_drm_find_panel(panel_node);
341 	if (!panel) {
342 		DRM_ERROR("failed to find panel\n");
343 		of_node_put(panel_node);
344 		return -EPROBE_DEFER;
345 	}
346 
347 	of_node_put(panel_node);
348 
349 	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
350 	if (!dp)
351 		return -ENOMEM;
352 
353 	dp->dev = dev;
354 
355 	dp->plat_data.panel = panel;
356 
357 	/*
358 	 * We just use the drvdata until driver run into component
359 	 * add function, and then we would set drvdata to null, so
360 	 * that analogix dp driver could take charge of the drvdata.
361 	 */
362 	platform_set_drvdata(pdev, dp);
363 
364 	return component_add(dev, &rockchip_dp_component_ops);
365 }
366 
367 static int rockchip_dp_remove(struct platform_device *pdev)
368 {
369 	component_del(&pdev->dev, &rockchip_dp_component_ops);
370 
371 	return 0;
372 }
373 
374 static const struct dev_pm_ops rockchip_dp_pm_ops = {
375 #ifdef CONFIG_PM_SLEEP
376 	.suspend = analogix_dp_suspend,
377 	.resume_early = analogix_dp_resume,
378 #endif
379 };
380 
381 static const struct rockchip_dp_chip_data rk3288_dp = {
382 	.lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
383 	.lcdsel_big = HIWORD_UPDATE(0, RK3288_EDP_LCDC_SEL),
384 	.lcdsel_lit = HIWORD_UPDATE(RK3288_EDP_LCDC_SEL, RK3288_EDP_LCDC_SEL),
385 	.chip_type = RK3288_DP,
386 };
387 
388 static const struct of_device_id rockchip_dp_dt_ids[] = {
389 	{.compatible = "rockchip,rk3288-dp", .data = &rk3288_dp },
390 	{}
391 };
392 MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
393 
394 static struct platform_driver rockchip_dp_driver = {
395 	.probe = rockchip_dp_probe,
396 	.remove = rockchip_dp_remove,
397 	.driver = {
398 		   .name = "rockchip-dp",
399 		   .owner = THIS_MODULE,
400 		   .pm = &rockchip_dp_pm_ops,
401 		   .of_match_table = of_match_ptr(rockchip_dp_dt_ids),
402 	},
403 };
404 
405 module_platform_driver(rockchip_dp_driver);
406 
407 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
408 MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>");
409 MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension");
410 MODULE_LICENSE("GPL v2");
411