1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <linux/clk.h>
7 #include <linux/mfd/syscon.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/phy/phy.h>
11 #include <linux/regmap.h>
12 
13 #include <drm/drm_of.h>
14 #include <drm/drmP.h>
15 #include <drm/drm_edid.h>
16 #include <drm/drm_probe_helper.h>
17 #include <drm/bridge/dw_hdmi.h>
18 
19 #include "rockchip_drm_drv.h"
20 #include "rockchip_drm_vop.h"
21 
22 #define RK3288_GRF_SOC_CON6		0x025C
23 #define RK3288_HDMI_LCDC_SEL		BIT(4)
24 #define RK3328_GRF_SOC_CON2		0x0408
25 
26 #define RK3328_HDMI_SDAIN_MSK		BIT(11)
27 #define RK3328_HDMI_SCLIN_MSK		BIT(10)
28 #define RK3328_HDMI_HPD_IOE		BIT(2)
29 #define RK3328_GRF_SOC_CON3		0x040c
30 /* need to be unset if hdmi or i2c should control voltage */
31 #define RK3328_HDMI_SDA5V_GRF		BIT(15)
32 #define RK3328_HDMI_SCL5V_GRF		BIT(14)
33 #define RK3328_HDMI_HPD5V_GRF		BIT(13)
34 #define RK3328_HDMI_CEC5V_GRF		BIT(12)
35 #define RK3328_GRF_SOC_CON4		0x0410
36 #define RK3328_HDMI_HPD_SARADC		BIT(13)
37 #define RK3328_HDMI_CEC_5V		BIT(11)
38 #define RK3328_HDMI_SDA_5V		BIT(10)
39 #define RK3328_HDMI_SCL_5V		BIT(9)
40 #define RK3328_HDMI_HPD_5V		BIT(8)
41 
42 #define RK3399_GRF_SOC_CON20		0x6250
43 #define RK3399_HDMI_LCDC_SEL		BIT(6)
44 
45 #define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
46 
47 /**
48  * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips
49  * @lcdsel_grf_reg: grf register offset of lcdc select
50  * @lcdsel_big: reg value of selecting vop big for HDMI
51  * @lcdsel_lit: reg value of selecting vop little for HDMI
52  */
53 struct rockchip_hdmi_chip_data {
54 	int	lcdsel_grf_reg;
55 	u32	lcdsel_big;
56 	u32	lcdsel_lit;
57 };
58 
59 struct rockchip_hdmi {
60 	struct device *dev;
61 	struct regmap *regmap;
62 	struct drm_encoder encoder;
63 	const struct rockchip_hdmi_chip_data *chip_data;
64 	struct clk *vpll_clk;
65 	struct clk *grf_clk;
66 	struct dw_hdmi *hdmi;
67 	struct phy *phy;
68 };
69 
70 #define to_rockchip_hdmi(x)	container_of(x, struct rockchip_hdmi, x)
71 
72 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
73 	{
74 		27000000, {
75 			{ 0x00b3, 0x0000},
76 			{ 0x2153, 0x0000},
77 			{ 0x40f3, 0x0000}
78 		},
79 	}, {
80 		36000000, {
81 			{ 0x00b3, 0x0000},
82 			{ 0x2153, 0x0000},
83 			{ 0x40f3, 0x0000}
84 		},
85 	}, {
86 		40000000, {
87 			{ 0x00b3, 0x0000},
88 			{ 0x2153, 0x0000},
89 			{ 0x40f3, 0x0000}
90 		},
91 	}, {
92 		54000000, {
93 			{ 0x0072, 0x0001},
94 			{ 0x2142, 0x0001},
95 			{ 0x40a2, 0x0001},
96 		},
97 	}, {
98 		65000000, {
99 			{ 0x0072, 0x0001},
100 			{ 0x2142, 0x0001},
101 			{ 0x40a2, 0x0001},
102 		},
103 	}, {
104 		66000000, {
105 			{ 0x013e, 0x0003},
106 			{ 0x217e, 0x0002},
107 			{ 0x4061, 0x0002}
108 		},
109 	}, {
110 		74250000, {
111 			{ 0x0072, 0x0001},
112 			{ 0x2145, 0x0002},
113 			{ 0x4061, 0x0002}
114 		},
115 	}, {
116 		83500000, {
117 			{ 0x0072, 0x0001},
118 		},
119 	}, {
120 		108000000, {
121 			{ 0x0051, 0x0002},
122 			{ 0x2145, 0x0002},
123 			{ 0x4061, 0x0002}
124 		},
125 	}, {
126 		106500000, {
127 			{ 0x0051, 0x0002},
128 			{ 0x2145, 0x0002},
129 			{ 0x4061, 0x0002}
130 		},
131 	}, {
132 		146250000, {
133 			{ 0x0051, 0x0002},
134 			{ 0x2145, 0x0002},
135 			{ 0x4061, 0x0002}
136 		},
137 	}, {
138 		148500000, {
139 			{ 0x0051, 0x0003},
140 			{ 0x214c, 0x0003},
141 			{ 0x4064, 0x0003}
142 		},
143 	}, {
144 		~0UL, {
145 			{ 0x00a0, 0x000a },
146 			{ 0x2001, 0x000f },
147 			{ 0x4002, 0x000f },
148 		},
149 	}
150 };
151 
152 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
153 	/*      pixelclk    bpp8    bpp10   bpp12 */
154 	{
155 		40000000,  { 0x0018, 0x0018, 0x0018 },
156 	}, {
157 		65000000,  { 0x0028, 0x0028, 0x0028 },
158 	}, {
159 		66000000,  { 0x0038, 0x0038, 0x0038 },
160 	}, {
161 		74250000,  { 0x0028, 0x0038, 0x0038 },
162 	}, {
163 		83500000,  { 0x0028, 0x0038, 0x0038 },
164 	}, {
165 		146250000, { 0x0038, 0x0038, 0x0038 },
166 	}, {
167 		148500000, { 0x0000, 0x0038, 0x0038 },
168 	}, {
169 		~0UL,      { 0x0000, 0x0000, 0x0000},
170 	}
171 };
172 
173 static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
174 	/*pixelclk   symbol   term   vlev*/
175 	{ 74250000,  0x8009, 0x0004, 0x0272},
176 	{ 148500000, 0x802b, 0x0004, 0x028d},
177 	{ 297000000, 0x8039, 0x0005, 0x028d},
178 	{ ~0UL,	     0x0000, 0x0000, 0x0000}
179 };
180 
181 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
182 {
183 	struct device_node *np = hdmi->dev->of_node;
184 
185 	hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
186 	if (IS_ERR(hdmi->regmap)) {
187 		DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n");
188 		return PTR_ERR(hdmi->regmap);
189 	}
190 
191 	hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
192 	if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
193 		hdmi->vpll_clk = NULL;
194 	} else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
195 		return -EPROBE_DEFER;
196 	} else if (IS_ERR(hdmi->vpll_clk)) {
197 		DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n");
198 		return PTR_ERR(hdmi->vpll_clk);
199 	}
200 
201 	hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
202 	if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
203 		hdmi->grf_clk = NULL;
204 	} else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
205 		return -EPROBE_DEFER;
206 	} else if (IS_ERR(hdmi->grf_clk)) {
207 		DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n");
208 		return PTR_ERR(hdmi->grf_clk);
209 	}
210 
211 	return 0;
212 }
213 
214 static enum drm_mode_status
215 dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
216 			    const struct drm_display_mode *mode)
217 {
218 	const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
219 	int pclk = mode->clock * 1000;
220 	bool valid = false;
221 	int i;
222 
223 	for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
224 		if (pclk == mpll_cfg[i].mpixelclock) {
225 			valid = true;
226 			break;
227 		}
228 	}
229 
230 	return (valid) ? MODE_OK : MODE_BAD;
231 }
232 
233 static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
234 	.destroy = drm_encoder_cleanup,
235 };
236 
237 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
238 {
239 }
240 
241 static bool
242 dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder,
243 				    const struct drm_display_mode *mode,
244 				    struct drm_display_mode *adj_mode)
245 {
246 	return true;
247 }
248 
249 static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
250 					      struct drm_display_mode *mode,
251 					      struct drm_display_mode *adj_mode)
252 {
253 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
254 
255 	clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
256 }
257 
258 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
259 {
260 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
261 	u32 val;
262 	int ret;
263 
264 	if (hdmi->chip_data->lcdsel_grf_reg < 0)
265 		return;
266 
267 	ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
268 	if (ret)
269 		val = hdmi->chip_data->lcdsel_lit;
270 	else
271 		val = hdmi->chip_data->lcdsel_big;
272 
273 	ret = clk_prepare_enable(hdmi->grf_clk);
274 	if (ret < 0) {
275 		DRM_DEV_ERROR(hdmi->dev, "failed to enable grfclk %d\n", ret);
276 		return;
277 	}
278 
279 	ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val);
280 	if (ret != 0)
281 		DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret);
282 
283 	clk_disable_unprepare(hdmi->grf_clk);
284 	DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n",
285 		      ret ? "LIT" : "BIG");
286 }
287 
288 static int
289 dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
290 				      struct drm_crtc_state *crtc_state,
291 				      struct drm_connector_state *conn_state)
292 {
293 	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
294 
295 	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
296 	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
297 
298 	return 0;
299 }
300 
301 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
302 	.mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
303 	.mode_set   = dw_hdmi_rockchip_encoder_mode_set,
304 	.enable     = dw_hdmi_rockchip_encoder_enable,
305 	.disable    = dw_hdmi_rockchip_encoder_disable,
306 	.atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
307 };
308 
309 static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data,
310 			     struct drm_display_mode *mode)
311 {
312 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
313 
314 	return phy_power_on(hdmi->phy);
315 }
316 
317 static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data)
318 {
319 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
320 
321 	phy_power_off(hdmi->phy);
322 }
323 
324 static enum drm_connector_status
325 dw_hdmi_rk3328_read_hpd(struct dw_hdmi *dw_hdmi, void *data)
326 {
327 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
328 	enum drm_connector_status status;
329 
330 	status = dw_hdmi_phy_read_hpd(dw_hdmi, data);
331 
332 	if (status == connector_status_connected)
333 		regmap_write(hdmi->regmap,
334 			RK3328_GRF_SOC_CON4,
335 			HIWORD_UPDATE(RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V,
336 				      RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V));
337 	else
338 		regmap_write(hdmi->regmap,
339 			RK3328_GRF_SOC_CON4,
340 			HIWORD_UPDATE(0, RK3328_HDMI_SDA_5V |
341 					 RK3328_HDMI_SCL_5V));
342 	return status;
343 }
344 
345 static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data)
346 {
347 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
348 
349 	dw_hdmi_phy_setup_hpd(dw_hdmi, data);
350 
351 	/* Enable and map pins to 3V grf-controlled io-voltage */
352 	regmap_write(hdmi->regmap,
353 		RK3328_GRF_SOC_CON4,
354 		HIWORD_UPDATE(0, RK3328_HDMI_HPD_SARADC | RK3328_HDMI_CEC_5V |
355 				 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V |
356 				 RK3328_HDMI_HPD_5V));
357 	regmap_write(hdmi->regmap,
358 		RK3328_GRF_SOC_CON3,
359 		HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF |
360 				 RK3328_HDMI_HPD5V_GRF |
361 				 RK3328_HDMI_CEC5V_GRF));
362 	regmap_write(hdmi->regmap,
363 		RK3328_GRF_SOC_CON2,
364 		HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK,
365 			      RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK |
366 			      RK3328_HDMI_HPD_IOE));
367 }
368 
369 static struct rockchip_hdmi_chip_data rk3288_chip_data = {
370 	.lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
371 	.lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL),
372 	.lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL),
373 };
374 
375 static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
376 	.mode_valid = dw_hdmi_rockchip_mode_valid,
377 	.mpll_cfg   = rockchip_mpll_cfg,
378 	.cur_ctr    = rockchip_cur_ctr,
379 	.phy_config = rockchip_phy_config,
380 	.phy_data = &rk3288_chip_data,
381 };
382 
383 static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = {
384 	.init		= dw_hdmi_rockchip_genphy_init,
385 	.disable	= dw_hdmi_rockchip_genphy_disable,
386 	.read_hpd	= dw_hdmi_rk3328_read_hpd,
387 	.update_hpd	= dw_hdmi_phy_update_hpd,
388 	.setup_hpd	= dw_hdmi_rk3328_setup_hpd,
389 };
390 
391 static struct rockchip_hdmi_chip_data rk3328_chip_data = {
392 	.lcdsel_grf_reg = -1,
393 };
394 
395 static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
396 	.mode_valid = dw_hdmi_rockchip_mode_valid,
397 	.mpll_cfg = rockchip_mpll_cfg,
398 	.cur_ctr = rockchip_cur_ctr,
399 	.phy_config = rockchip_phy_config,
400 	.phy_data = &rk3328_chip_data,
401 	.phy_ops = &rk3328_hdmi_phy_ops,
402 	.phy_name = "inno_dw_hdmi_phy2",
403 	.phy_force_vendor = true,
404 };
405 
406 static struct rockchip_hdmi_chip_data rk3399_chip_data = {
407 	.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
408 	.lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL),
409 	.lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL),
410 };
411 
412 static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
413 	.mode_valid = dw_hdmi_rockchip_mode_valid,
414 	.mpll_cfg   = rockchip_mpll_cfg,
415 	.cur_ctr    = rockchip_cur_ctr,
416 	.phy_config = rockchip_phy_config,
417 	.phy_data = &rk3399_chip_data,
418 };
419 
420 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
421 	{ .compatible = "rockchip,rk3288-dw-hdmi",
422 	  .data = &rk3288_hdmi_drv_data
423 	},
424 	{ .compatible = "rockchip,rk3328-dw-hdmi",
425 	  .data = &rk3328_hdmi_drv_data
426 	},
427 	{ .compatible = "rockchip,rk3399-dw-hdmi",
428 	  .data = &rk3399_hdmi_drv_data
429 	},
430 	{},
431 };
432 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
433 
434 static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
435 				 void *data)
436 {
437 	struct platform_device *pdev = to_platform_device(dev);
438 	struct dw_hdmi_plat_data *plat_data;
439 	const struct of_device_id *match;
440 	struct drm_device *drm = data;
441 	struct drm_encoder *encoder;
442 	struct rockchip_hdmi *hdmi;
443 	int ret;
444 
445 	if (!pdev->dev.of_node)
446 		return -ENODEV;
447 
448 	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
449 	if (!hdmi)
450 		return -ENOMEM;
451 
452 	match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
453 	plat_data = devm_kmemdup(&pdev->dev, match->data,
454 					     sizeof(*plat_data), GFP_KERNEL);
455 	if (!plat_data)
456 		return -ENOMEM;
457 
458 	hdmi->dev = &pdev->dev;
459 	hdmi->chip_data = plat_data->phy_data;
460 	plat_data->phy_data = hdmi;
461 	encoder = &hdmi->encoder;
462 
463 	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
464 	/*
465 	 * If we failed to find the CRTC(s) which this encoder is
466 	 * supposed to be connected to, it's because the CRTC has
467 	 * not been registered yet.  Defer probing, and hope that
468 	 * the required CRTC is added later.
469 	 */
470 	if (encoder->possible_crtcs == 0)
471 		return -EPROBE_DEFER;
472 
473 	ret = rockchip_hdmi_parse_dt(hdmi);
474 	if (ret) {
475 		DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
476 		return ret;
477 	}
478 
479 	ret = clk_prepare_enable(hdmi->vpll_clk);
480 	if (ret) {
481 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
482 			      ret);
483 		return ret;
484 	}
485 
486 	hdmi->phy = devm_phy_optional_get(dev, "hdmi");
487 	if (IS_ERR(hdmi->phy)) {
488 		ret = PTR_ERR(hdmi->phy);
489 		if (ret != -EPROBE_DEFER)
490 			DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n");
491 		return ret;
492 	}
493 
494 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
495 	drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
496 			 DRM_MODE_ENCODER_TMDS, NULL);
497 
498 	platform_set_drvdata(pdev, hdmi);
499 
500 	hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
501 
502 	/*
503 	 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
504 	 * which would have called the encoder cleanup.  Do it manually.
505 	 */
506 	if (IS_ERR(hdmi->hdmi)) {
507 		ret = PTR_ERR(hdmi->hdmi);
508 		drm_encoder_cleanup(encoder);
509 		clk_disable_unprepare(hdmi->vpll_clk);
510 	}
511 
512 	return ret;
513 }
514 
515 static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
516 				    void *data)
517 {
518 	struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
519 
520 	dw_hdmi_unbind(hdmi->hdmi);
521 	clk_disable_unprepare(hdmi->vpll_clk);
522 }
523 
524 static const struct component_ops dw_hdmi_rockchip_ops = {
525 	.bind	= dw_hdmi_rockchip_bind,
526 	.unbind	= dw_hdmi_rockchip_unbind,
527 };
528 
529 static int dw_hdmi_rockchip_probe(struct platform_device *pdev)
530 {
531 	return component_add(&pdev->dev, &dw_hdmi_rockchip_ops);
532 }
533 
534 static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
535 {
536 	component_del(&pdev->dev, &dw_hdmi_rockchip_ops);
537 
538 	return 0;
539 }
540 
541 struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
542 	.probe  = dw_hdmi_rockchip_probe,
543 	.remove = dw_hdmi_rockchip_remove,
544 	.driver = {
545 		.name = "dwhdmi-rockchip",
546 		.of_match_table = dw_hdmi_rockchip_dt_ids,
547 	},
548 };
549