blob: d6d0751f389febd42f00fd4780af20208466020c [file] [log] [blame]
Yakir Yang9e32e162016-03-29 09:57:30 +08001/*
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>
Yakir Yangd9c900b2016-06-29 17:15:01 +080017#include <linux/of_device.h>
Yakir Yang9e32e162016-03-29 09:57:30 +080018#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"
Yakir Yang8f0ac5c2016-07-24 14:57:52 +080035#include "rockchip_drm_psr.h"
Yakir Yang9e32e162016-03-29 09:57:30 +080036#include "rockchip_drm_vop.h"
37
Yakir Yangd9c900b2016-06-29 17:15:01 +080038#define RK3288_GRF_SOC_CON6 0x25c
39#define RK3288_EDP_LCDC_SEL BIT(5)
Yakir Yang82872e42016-06-29 17:15:26 +080040#define RK3399_GRF_SOC_CON20 0x6250
41#define RK3399_EDP_LCDC_SEL BIT(5)
Yakir Yangd9c900b2016-06-29 17:15:01 +080042
43#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
44
Yakir Yang8f0ac5c2016-07-24 14:57:52 +080045#define PSR_SET_DELAY_TIME msecs_to_jiffies(10)
46#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS 100
47
Yakir Yang9e32e162016-03-29 09:57:30 +080048#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm)
49
Yakir Yangd9c900b2016-06-29 17:15:01 +080050/**
51 * struct rockchip_dp_chip_data - splite the grf setting of kind of chips
52 * @lcdsel_grf_reg: grf register offset of lcdc select
53 * @lcdsel_big: reg value of selecting vop big for eDP
54 * @lcdsel_lit: reg value of selecting vop little for eDP
55 * @chip_type: specific chip type
56 */
57struct rockchip_dp_chip_data {
58 u32 lcdsel_grf_reg;
59 u32 lcdsel_big;
60 u32 lcdsel_lit;
61 u32 chip_type;
62};
Yakir Yang9e32e162016-03-29 09:57:30 +080063
64struct rockchip_dp_device {
65 struct drm_device *drm_dev;
66 struct device *dev;
67 struct drm_encoder encoder;
68 struct drm_display_mode mode;
69
70 struct clk *pclk;
Yakir Yangdc1c93b2016-06-29 17:16:05 +080071 struct clk *grfclk;
Yakir Yang9e32e162016-03-29 09:57:30 +080072 struct regmap *grf;
73 struct reset_control *rst;
74
Yakir Yang8f0ac5c2016-07-24 14:57:52 +080075 struct delayed_work psr_work;
76 unsigned int psr_state;
77
Yakir Yangd9c900b2016-06-29 17:15:01 +080078 const struct rockchip_dp_chip_data *data;
79
Yakir Yang9e32e162016-03-29 09:57:30 +080080 struct analogix_dp_plat_data plat_data;
81};
82
Yakir Yang8f0ac5c2016-07-24 14:57:52 +080083static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
84{
85 struct rockchip_dp_device *dp = to_dp(encoder);
86
87 dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
88
89 if (enabled)
90 dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
91 else
92 dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
93
94 schedule_delayed_work(&dp->psr_work, PSR_SET_DELAY_TIME);
95}
96
97static void analogix_dp_psr_work(struct work_struct *work)
98{
99 struct rockchip_dp_device *dp =
100 container_of(work, typeof(*dp), psr_work.work);
101 struct drm_crtc *crtc = dp->encoder.crtc;
102 int psr_state = dp->psr_state;
103 int vact_end;
104 int ret;
105
106 if (!crtc)
107 return;
108
109 vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay;
110
111 ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
112 PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
113 if (ret) {
114 dev_err(dp->dev, "line flag interrupt did not arrive\n");
115 return;
116 }
117
118 if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
119 analogix_dp_enable_psr(dp->dev);
120 else
121 analogix_dp_disable_psr(dp->dev);
122}
123
Yakir Yang9e32e162016-03-29 09:57:30 +0800124static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
125{
126 reset_control_assert(dp->rst);
127 usleep_range(10, 20);
128 reset_control_deassert(dp->rst);
129
130 return 0;
131}
132
133static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
134{
135 struct rockchip_dp_device *dp = to_dp(plat_data);
136 int ret;
137
138 ret = clk_prepare_enable(dp->pclk);
139 if (ret < 0) {
140 dev_err(dp->dev, "failed to enable pclk %d\n", ret);
141 return ret;
142 }
143
144 ret = rockchip_dp_pre_init(dp);
145 if (ret < 0) {
146 dev_err(dp->dev, "failed to dp pre init %d\n", ret);
Wei Yongjun3694c5c2016-07-19 11:32:43 +0000147 clk_disable_unprepare(dp->pclk);
Yakir Yang9e32e162016-03-29 09:57:30 +0800148 return ret;
149 }
150
151 return 0;
152}
153
154static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
155{
156 struct rockchip_dp_device *dp = to_dp(plat_data);
157
158 clk_disable_unprepare(dp->pclk);
159
160 return 0;
161}
162
Yakir Yangdb8a9ae2016-06-29 17:15:39 +0800163static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data,
164 struct drm_connector *connector)
165{
166 struct drm_display_info *di = &connector->display_info;
167 /* VOP couldn't output YUV video format for eDP rightly */
168 u32 mask = DRM_COLOR_FORMAT_YCRCB444 | DRM_COLOR_FORMAT_YCRCB422;
169
170 if ((di->color_formats & mask)) {
171 DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n");
172 di->color_formats &= ~mask;
173 di->color_formats |= DRM_COLOR_FORMAT_RGB444;
174 di->bpc = 8;
175 }
176
177 return 0;
178}
179
Yakir Yang9e32e162016-03-29 09:57:30 +0800180static bool
181rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder,
182 const struct drm_display_mode *mode,
183 struct drm_display_mode *adjusted_mode)
184{
185 /* do nothing */
186 return true;
187}
188
189static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder,
190 struct drm_display_mode *mode,
191 struct drm_display_mode *adjusted)
192{
193 /* do nothing */
194}
195
196static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
197{
198 struct rockchip_dp_device *dp = to_dp(encoder);
199 int ret;
200 u32 val;
201
Yakir Yang9e32e162016-03-29 09:57:30 +0800202 ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
203 if (ret < 0)
204 return;
205
206 if (ret)
Yakir Yangd9c900b2016-06-29 17:15:01 +0800207 val = dp->data->lcdsel_lit;
Yakir Yang9e32e162016-03-29 09:57:30 +0800208 else
Yakir Yangd9c900b2016-06-29 17:15:01 +0800209 val = dp->data->lcdsel_big;
Yakir Yang9e32e162016-03-29 09:57:30 +0800210
211 dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
212
Yakir Yangdc1c93b2016-06-29 17:16:05 +0800213 ret = clk_prepare_enable(dp->grfclk);
214 if (ret < 0) {
215 dev_err(dp->dev, "failed to enable grfclk %d\n", ret);
Yakir Yang9e32e162016-03-29 09:57:30 +0800216 return;
217 }
Yakir Yangdc1c93b2016-06-29 17:16:05 +0800218
219 ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val);
220 if (ret != 0)
221 dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
222
223 clk_disable_unprepare(dp->grfclk);
Yakir Yang9e32e162016-03-29 09:57:30 +0800224}
225
226static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
227{
228 /* do nothing */
229}
230
Mark Yao4e257d92016-04-20 10:41:42 +0800231static int
232rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
233 struct drm_crtc_state *crtc_state,
234 struct drm_connector_state *conn_state)
235{
236 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
Yakir Yang82872e42016-06-29 17:15:26 +0800237 struct rockchip_dp_device *dp = to_dp(encoder);
238 int ret;
Mark Yao4e257d92016-04-20 10:41:42 +0800239
240 /*
Yakir Yangd698f0e2016-06-29 17:15:44 +0800241 * The hardware IC designed that VOP must output the RGB10 video
242 * format to eDP controller, and if eDP panel only support RGB8,
243 * then eDP controller should cut down the video data, not via VOP
244 * controller, that's why we need to hardcode the VOP output mode
245 * to RGA10 here.
Mark Yao4e257d92016-04-20 10:41:42 +0800246 */
Yakir Yang82872e42016-06-29 17:15:26 +0800247
Mark Yao4e257d92016-04-20 10:41:42 +0800248 s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
249 s->output_type = DRM_MODE_CONNECTOR_eDP;
Yakir Yang82872e42016-06-29 17:15:26 +0800250 if (dp->data->chip_type == RK3399_EDP) {
251 /*
252 * For RK3399, VOP Lit must code the out mode to RGB888,
253 * VOP Big must code the out mode to RGB10.
254 */
255 ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
256 encoder);
257 if (ret > 0)
258 s->output_mode = ROCKCHIP_OUT_MODE_P888;
259 }
Mark Yao4e257d92016-04-20 10:41:42 +0800260
261 return 0;
262}
263
Yakir Yang9e32e162016-03-29 09:57:30 +0800264static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
265 .mode_fixup = rockchip_dp_drm_encoder_mode_fixup,
266 .mode_set = rockchip_dp_drm_encoder_mode_set,
267 .enable = rockchip_dp_drm_encoder_enable,
268 .disable = rockchip_dp_drm_encoder_nop,
Mark Yao4e257d92016-04-20 10:41:42 +0800269 .atomic_check = rockchip_dp_drm_encoder_atomic_check,
Yakir Yang9e32e162016-03-29 09:57:30 +0800270};
271
272static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
273{
274 drm_encoder_cleanup(encoder);
275}
276
277static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
278 .destroy = rockchip_dp_drm_encoder_destroy,
279};
280
281static int rockchip_dp_init(struct rockchip_dp_device *dp)
282{
283 struct device *dev = dp->dev;
284 struct device_node *np = dev->of_node;
285 int ret;
286
287 dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
288 if (IS_ERR(dp->grf)) {
289 dev_err(dev, "failed to get rockchip,grf property\n");
290 return PTR_ERR(dp->grf);
291 }
292
Yakir Yangdc1c93b2016-06-29 17:16:05 +0800293 dp->grfclk = devm_clk_get(dev, "grf");
294 if (PTR_ERR(dp->grfclk) == -ENOENT) {
295 dp->grfclk = NULL;
296 } else if (PTR_ERR(dp->grfclk) == -EPROBE_DEFER) {
297 return -EPROBE_DEFER;
298 } else if (IS_ERR(dp->grfclk)) {
299 dev_err(dev, "failed to get grf clock\n");
300 return PTR_ERR(dp->grfclk);
301 }
302
Yakir Yang9e32e162016-03-29 09:57:30 +0800303 dp->pclk = devm_clk_get(dev, "pclk");
304 if (IS_ERR(dp->pclk)) {
305 dev_err(dev, "failed to get pclk property\n");
306 return PTR_ERR(dp->pclk);
307 }
308
309 dp->rst = devm_reset_control_get(dev, "dp");
310 if (IS_ERR(dp->rst)) {
311 dev_err(dev, "failed to get dp reset control\n");
312 return PTR_ERR(dp->rst);
313 }
314
315 ret = clk_prepare_enable(dp->pclk);
316 if (ret < 0) {
317 dev_err(dp->dev, "failed to enable pclk %d\n", ret);
318 return ret;
319 }
320
321 ret = rockchip_dp_pre_init(dp);
322 if (ret < 0) {
323 dev_err(dp->dev, "failed to pre init %d\n", ret);
Wei Yongjun3694c5c2016-07-19 11:32:43 +0000324 clk_disable_unprepare(dp->pclk);
Yakir Yang9e32e162016-03-29 09:57:30 +0800325 return ret;
326 }
327
328 return 0;
329}
330
331static int rockchip_dp_drm_create_encoder(struct rockchip_dp_device *dp)
332{
333 struct drm_encoder *encoder = &dp->encoder;
334 struct drm_device *drm_dev = dp->drm_dev;
335 struct device *dev = dp->dev;
336 int ret;
337
338 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
339 dev->of_node);
340 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
341
342 ret = drm_encoder_init(drm_dev, encoder, &rockchip_dp_encoder_funcs,
343 DRM_MODE_ENCODER_TMDS, NULL);
344 if (ret) {
345 DRM_ERROR("failed to initialize encoder with drm\n");
346 return ret;
347 }
348
349 drm_encoder_helper_add(encoder, &rockchip_dp_encoder_helper_funcs);
350
351 return 0;
352}
353
354static int rockchip_dp_bind(struct device *dev, struct device *master,
355 void *data)
356{
357 struct rockchip_dp_device *dp = dev_get_drvdata(dev);
Yakir Yangd9c900b2016-06-29 17:15:01 +0800358 const struct rockchip_dp_chip_data *dp_data;
Yakir Yang9e32e162016-03-29 09:57:30 +0800359 struct drm_device *drm_dev = data;
360 int ret;
361
362 /*
363 * Just like the probe function said, we don't need the
364 * device drvrate anymore, we should leave the charge to
365 * analogix dp driver, set the device drvdata to NULL.
366 */
367 dev_set_drvdata(dev, NULL);
368
Yakir Yangd9c900b2016-06-29 17:15:01 +0800369 dp_data = of_device_get_match_data(dev);
370 if (!dp_data)
371 return -ENODEV;
372
Yakir Yang9e32e162016-03-29 09:57:30 +0800373 ret = rockchip_dp_init(dp);
374 if (ret < 0)
375 return ret;
376
Yakir Yangd9c900b2016-06-29 17:15:01 +0800377 dp->data = dp_data;
Yakir Yang9e32e162016-03-29 09:57:30 +0800378 dp->drm_dev = drm_dev;
379
380 ret = rockchip_dp_drm_create_encoder(dp);
381 if (ret) {
382 DRM_ERROR("failed to create drm encoder\n");
383 return ret;
384 }
385
386 dp->plat_data.encoder = &dp->encoder;
387
Yakir Yangd9c900b2016-06-29 17:15:01 +0800388 dp->plat_data.dev_type = dp->data->chip_type;
Yakir Yang9e32e162016-03-29 09:57:30 +0800389 dp->plat_data.power_on = rockchip_dp_poweron;
390 dp->plat_data.power_off = rockchip_dp_powerdown;
Yakir Yangdb8a9ae2016-06-29 17:15:39 +0800391 dp->plat_data.get_modes = rockchip_dp_get_modes;
Yakir Yang9e32e162016-03-29 09:57:30 +0800392
Yakir Yang8f0ac5c2016-07-24 14:57:52 +0800393 dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
394 INIT_DELAYED_WORK(&dp->psr_work, analogix_dp_psr_work);
395
396 rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
397
Yakir Yang9e32e162016-03-29 09:57:30 +0800398 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
399}
400
401static void rockchip_dp_unbind(struct device *dev, struct device *master,
402 void *data)
403{
Yakir Yang8f0ac5c2016-07-24 14:57:52 +0800404 struct rockchip_dp_device *dp = dev_get_drvdata(dev);
405
406 rockchip_drm_psr_unregister(&dp->encoder);
407
Yakir Yang9e32e162016-03-29 09:57:30 +0800408 return analogix_dp_unbind(dev, master, data);
409}
410
411static const struct component_ops rockchip_dp_component_ops = {
412 .bind = rockchip_dp_bind,
413 .unbind = rockchip_dp_unbind,
414};
415
416static int rockchip_dp_probe(struct platform_device *pdev)
417{
418 struct device *dev = &pdev->dev;
419 struct device_node *panel_node, *port, *endpoint;
Yakir Yangeb87c912016-06-29 17:15:30 +0800420 struct drm_panel *panel = NULL;
Yakir Yang9e32e162016-03-29 09:57:30 +0800421 struct rockchip_dp_device *dp;
Yakir Yang9e32e162016-03-29 09:57:30 +0800422
423 port = of_graph_get_port_by_id(dev->of_node, 1);
Yakir Yangeb87c912016-06-29 17:15:30 +0800424 if (port) {
425 endpoint = of_get_child_by_name(port, "endpoint");
426 of_node_put(port);
427 if (!endpoint) {
428 dev_err(dev, "no output endpoint found\n");
429 return -EINVAL;
430 }
Yakir Yang9e32e162016-03-29 09:57:30 +0800431
Yakir Yangeb87c912016-06-29 17:15:30 +0800432 panel_node = of_graph_get_remote_port_parent(endpoint);
433 of_node_put(endpoint);
434 if (!panel_node) {
435 dev_err(dev, "no output node found\n");
436 return -EINVAL;
437 }
Yakir Yang9e32e162016-03-29 09:57:30 +0800438
Yakir Yangeb87c912016-06-29 17:15:30 +0800439 panel = of_drm_find_panel(panel_node);
Yakir Yang9e32e162016-03-29 09:57:30 +0800440 of_node_put(panel_node);
Yakir Yangeb87c912016-06-29 17:15:30 +0800441 if (!panel) {
442 DRM_ERROR("failed to find panel\n");
443 return -EPROBE_DEFER;
444 }
Yakir Yang9e32e162016-03-29 09:57:30 +0800445 }
446
Yakir Yang9e32e162016-03-29 09:57:30 +0800447 dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
448 if (!dp)
449 return -ENOMEM;
450
451 dp->dev = dev;
452
453 dp->plat_data.panel = panel;
454
455 /*
456 * We just use the drvdata until driver run into component
457 * add function, and then we would set drvdata to null, so
458 * that analogix dp driver could take charge of the drvdata.
459 */
460 platform_set_drvdata(pdev, dp);
461
462 return component_add(dev, &rockchip_dp_component_ops);
463}
464
465static int rockchip_dp_remove(struct platform_device *pdev)
466{
467 component_del(&pdev->dev, &rockchip_dp_component_ops);
468
469 return 0;
470}
471
Yakir Yang9e32e162016-03-29 09:57:30 +0800472static const struct dev_pm_ops rockchip_dp_pm_ops = {
Tomeu Vizosofe64ba52016-06-06 16:53:33 +0200473#ifdef CONFIG_PM_SLEEP
474 .suspend = analogix_dp_suspend,
475 .resume_early = analogix_dp_resume,
476#endif
Yakir Yang9e32e162016-03-29 09:57:30 +0800477};
478
Yakir Yang82872e42016-06-29 17:15:26 +0800479static const struct rockchip_dp_chip_data rk3399_edp = {
480 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
481 .lcdsel_big = HIWORD_UPDATE(0, RK3399_EDP_LCDC_SEL),
482 .lcdsel_lit = HIWORD_UPDATE(RK3399_EDP_LCDC_SEL, RK3399_EDP_LCDC_SEL),
483 .chip_type = RK3399_EDP,
484};
485
Yakir Yangd9c900b2016-06-29 17:15:01 +0800486static const struct rockchip_dp_chip_data rk3288_dp = {
487 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
488 .lcdsel_big = HIWORD_UPDATE(0, RK3288_EDP_LCDC_SEL),
489 .lcdsel_lit = HIWORD_UPDATE(RK3288_EDP_LCDC_SEL, RK3288_EDP_LCDC_SEL),
490 .chip_type = RK3288_DP,
491};
492
Yakir Yang9e32e162016-03-29 09:57:30 +0800493static const struct of_device_id rockchip_dp_dt_ids[] = {
Yakir Yangd9c900b2016-06-29 17:15:01 +0800494 {.compatible = "rockchip,rk3288-dp", .data = &rk3288_dp },
Yakir Yang82872e42016-06-29 17:15:26 +0800495 {.compatible = "rockchip,rk3399-edp", .data = &rk3399_edp },
Yakir Yang9e32e162016-03-29 09:57:30 +0800496 {}
497};
498MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
499
500static struct platform_driver rockchip_dp_driver = {
501 .probe = rockchip_dp_probe,
502 .remove = rockchip_dp_remove,
503 .driver = {
504 .name = "rockchip-dp",
505 .owner = THIS_MODULE,
506 .pm = &rockchip_dp_pm_ops,
507 .of_match_table = of_match_ptr(rockchip_dp_dt_ids),
508 },
509};
510
511module_platform_driver(rockchip_dp_driver);
512
513MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
514MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>");
515MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension");
516MODULE_LICENSE("GPL v2");