xref: /linux/drivers/gpu/drm/omapdrm/dss/dpi.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2009 Nokia Corporation
4  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
5  *
6  * Some code and ideas taken from drivers/video/omap/ driver
7  * by Imre Deak.
8  */
9 
10 #define DSS_SUBSYS_NAME "DPI"
11 
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <linux/err.h>
15 #include <linux/errno.h>
16 #include <linux/export.h>
17 #include <linux/kernel.h>
18 #include <linux/of.h>
19 #include <linux/of_graph.h>
20 #include <linux/platform_device.h>
21 #include <linux/regulator/consumer.h>
22 #include <linux/string.h>
23 #include <linux/sys_soc.h>
24 
25 #include <drm/drm_atomic_state_helper.h>
26 #include <drm/drm_bridge.h>
27 
28 #include "dss.h"
29 #include "omapdss.h"
30 
31 struct dpi_data {
32 	struct platform_device *pdev;
33 	enum dss_model dss_model;
34 	struct dss_device *dss;
35 	unsigned int id;
36 
37 	struct regulator *vdds_dsi_reg;
38 	enum dss_clk_source clk_src;
39 	struct dss_pll *pll;
40 
41 	struct dss_lcd_mgr_config mgr_config;
42 	unsigned long pixelclock;
43 	int data_lines;
44 
45 	struct omap_dss_device output;
46 	struct drm_bridge bridge;
47 };
48 
49 #define drm_bridge_to_dpi(bridge) container_of(bridge, struct dpi_data, bridge)
50 
51 /* -----------------------------------------------------------------------------
52  * Clock Handling and PLL
53  */
54 
55 static enum dss_clk_source dpi_get_clk_src_dra7xx(struct dpi_data *dpi,
56 						  enum omap_channel channel)
57 {
58 	/*
59 	 * Possible clock sources:
60 	 * LCD1: FCK/PLL1_1/HDMI_PLL
61 	 * LCD2: FCK/PLL1_3/HDMI_PLL (DRA74x: PLL2_3)
62 	 * LCD3: FCK/PLL1_3/HDMI_PLL (DRA74x: PLL2_1)
63 	 */
64 
65 	switch (channel) {
66 	case OMAP_DSS_CHANNEL_LCD:
67 	{
68 		if (dss_pll_find_by_src(dpi->dss, DSS_CLK_SRC_PLL1_1))
69 			return DSS_CLK_SRC_PLL1_1;
70 		break;
71 	}
72 	case OMAP_DSS_CHANNEL_LCD2:
73 	{
74 		if (dss_pll_find_by_src(dpi->dss, DSS_CLK_SRC_PLL1_3))
75 			return DSS_CLK_SRC_PLL1_3;
76 		if (dss_pll_find_by_src(dpi->dss, DSS_CLK_SRC_PLL2_3))
77 			return DSS_CLK_SRC_PLL2_3;
78 		break;
79 	}
80 	case OMAP_DSS_CHANNEL_LCD3:
81 	{
82 		if (dss_pll_find_by_src(dpi->dss, DSS_CLK_SRC_PLL2_1))
83 			return DSS_CLK_SRC_PLL2_1;
84 		if (dss_pll_find_by_src(dpi->dss, DSS_CLK_SRC_PLL1_3))
85 			return DSS_CLK_SRC_PLL1_3;
86 		break;
87 	}
88 	default:
89 		break;
90 	}
91 
92 	return DSS_CLK_SRC_FCK;
93 }
94 
95 static enum dss_clk_source dpi_get_clk_src(struct dpi_data *dpi)
96 {
97 	enum omap_channel channel = dpi->output.dispc_channel;
98 
99 	/*
100 	 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
101 	 * would also be used for DISPC fclk. Meaning, when the DPI output is
102 	 * disabled, DISPC clock will be disabled, and TV out will stop.
103 	 */
104 	switch (dpi->dss_model) {
105 	case DSS_MODEL_OMAP2:
106 	case DSS_MODEL_OMAP3:
107 		return DSS_CLK_SRC_FCK;
108 
109 	case DSS_MODEL_OMAP4:
110 		switch (channel) {
111 		case OMAP_DSS_CHANNEL_LCD:
112 			return DSS_CLK_SRC_PLL1_1;
113 		case OMAP_DSS_CHANNEL_LCD2:
114 			return DSS_CLK_SRC_PLL2_1;
115 		default:
116 			return DSS_CLK_SRC_FCK;
117 		}
118 
119 	case DSS_MODEL_OMAP5:
120 		switch (channel) {
121 		case OMAP_DSS_CHANNEL_LCD:
122 			return DSS_CLK_SRC_PLL1_1;
123 		case OMAP_DSS_CHANNEL_LCD3:
124 			return DSS_CLK_SRC_PLL2_1;
125 		case OMAP_DSS_CHANNEL_LCD2:
126 		default:
127 			return DSS_CLK_SRC_FCK;
128 		}
129 
130 	case DSS_MODEL_DRA7:
131 		return dpi_get_clk_src_dra7xx(dpi, channel);
132 
133 	default:
134 		return DSS_CLK_SRC_FCK;
135 	}
136 }
137 
138 struct dpi_clk_calc_ctx {
139 	struct dpi_data *dpi;
140 	unsigned int clkout_idx;
141 
142 	/* inputs */
143 
144 	unsigned long pck_min, pck_max;
145 
146 	/* outputs */
147 
148 	struct dss_pll_clock_info pll_cinfo;
149 	unsigned long fck;
150 	struct dispc_clock_info dispc_cinfo;
151 };
152 
153 static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
154 		unsigned long pck, void *data)
155 {
156 	struct dpi_clk_calc_ctx *ctx = data;
157 
158 	/*
159 	 * Odd dividers give us uneven duty cycle, causing problem when level
160 	 * shifted. So skip all odd dividers when the pixel clock is on the
161 	 * higher side.
162 	 */
163 	if (ctx->pck_min >= 100000000) {
164 		if (lckd > 1 && lckd % 2 != 0)
165 			return false;
166 
167 		if (pckd > 1 && pckd % 2 != 0)
168 			return false;
169 	}
170 
171 	ctx->dispc_cinfo.lck_div = lckd;
172 	ctx->dispc_cinfo.pck_div = pckd;
173 	ctx->dispc_cinfo.lck = lck;
174 	ctx->dispc_cinfo.pck = pck;
175 
176 	return true;
177 }
178 
179 
180 static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
181 		void *data)
182 {
183 	struct dpi_clk_calc_ctx *ctx = data;
184 
185 	ctx->pll_cinfo.mX[ctx->clkout_idx] = m_dispc;
186 	ctx->pll_cinfo.clkout[ctx->clkout_idx] = dispc;
187 
188 	return dispc_div_calc(ctx->dpi->dss->dispc, dispc,
189 			      ctx->pck_min, ctx->pck_max,
190 			      dpi_calc_dispc_cb, ctx);
191 }
192 
193 
194 static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
195 		unsigned long clkdco,
196 		void *data)
197 {
198 	struct dpi_clk_calc_ctx *ctx = data;
199 
200 	ctx->pll_cinfo.n = n;
201 	ctx->pll_cinfo.m = m;
202 	ctx->pll_cinfo.fint = fint;
203 	ctx->pll_cinfo.clkdco = clkdco;
204 
205 	return dss_pll_hsdiv_calc_a(ctx->dpi->pll, clkdco,
206 		ctx->pck_min, dss_get_max_fck_rate(ctx->dpi->dss),
207 		dpi_calc_hsdiv_cb, ctx);
208 }
209 
210 static bool dpi_calc_dss_cb(unsigned long fck, void *data)
211 {
212 	struct dpi_clk_calc_ctx *ctx = data;
213 
214 	ctx->fck = fck;
215 
216 	return dispc_div_calc(ctx->dpi->dss->dispc, fck,
217 			      ctx->pck_min, ctx->pck_max,
218 			      dpi_calc_dispc_cb, ctx);
219 }
220 
221 static bool dpi_pll_clk_calc(struct dpi_data *dpi, unsigned long pck,
222 		struct dpi_clk_calc_ctx *ctx)
223 {
224 	unsigned long clkin;
225 
226 	memset(ctx, 0, sizeof(*ctx));
227 	ctx->dpi = dpi;
228 	ctx->clkout_idx = dss_pll_get_clkout_idx_for_src(dpi->clk_src);
229 
230 	clkin = clk_get_rate(dpi->pll->clkin);
231 
232 	if (dpi->pll->hw->type == DSS_PLL_TYPE_A) {
233 		unsigned long pll_min, pll_max;
234 
235 		ctx->pck_min = pck - 1000;
236 		ctx->pck_max = pck + 1000;
237 
238 		pll_min = 0;
239 		pll_max = 0;
240 
241 		return dss_pll_calc_a(ctx->dpi->pll, clkin,
242 				pll_min, pll_max,
243 				dpi_calc_pll_cb, ctx);
244 	} else { /* DSS_PLL_TYPE_B */
245 		dss_pll_calc_b(dpi->pll, clkin, pck, &ctx->pll_cinfo);
246 
247 		ctx->dispc_cinfo.lck_div = 1;
248 		ctx->dispc_cinfo.pck_div = 1;
249 		ctx->dispc_cinfo.lck = ctx->pll_cinfo.clkout[0];
250 		ctx->dispc_cinfo.pck = ctx->dispc_cinfo.lck;
251 
252 		return true;
253 	}
254 }
255 
256 static bool dpi_dss_clk_calc(struct dpi_data *dpi, unsigned long pck,
257 			     struct dpi_clk_calc_ctx *ctx)
258 {
259 	int i;
260 
261 	/*
262 	 * DSS fck gives us very few possibilities, so finding a good pixel
263 	 * clock may not be possible. We try multiple times to find the clock,
264 	 * each time widening the pixel clock range we look for, up to
265 	 * +/- ~15MHz.
266 	 */
267 
268 	for (i = 0; i < 25; ++i) {
269 		bool ok;
270 
271 		memset(ctx, 0, sizeof(*ctx));
272 		ctx->dpi = dpi;
273 		if (pck > 1000 * i * i * i)
274 			ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
275 		else
276 			ctx->pck_min = 0;
277 		ctx->pck_max = pck + 1000 * i * i * i;
278 
279 		ok = dss_div_calc(dpi->dss, pck, ctx->pck_min,
280 				  dpi_calc_dss_cb, ctx);
281 		if (ok)
282 			return ok;
283 	}
284 
285 	return false;
286 }
287 
288 
289 
290 static int dpi_set_pll_clk(struct dpi_data *dpi, unsigned long pck_req)
291 {
292 	struct dpi_clk_calc_ctx ctx;
293 	int r;
294 	bool ok;
295 
296 	ok = dpi_pll_clk_calc(dpi, pck_req, &ctx);
297 	if (!ok)
298 		return -EINVAL;
299 
300 	r = dss_pll_set_config(dpi->pll, &ctx.pll_cinfo);
301 	if (r)
302 		return r;
303 
304 	dss_select_lcd_clk_source(dpi->dss, dpi->output.dispc_channel,
305 				  dpi->clk_src);
306 
307 	dpi->mgr_config.clock_info = ctx.dispc_cinfo;
308 
309 	return 0;
310 }
311 
312 static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req)
313 {
314 	struct dpi_clk_calc_ctx ctx;
315 	int r;
316 	bool ok;
317 
318 	ok = dpi_dss_clk_calc(dpi, pck_req, &ctx);
319 	if (!ok)
320 		return -EINVAL;
321 
322 	r = dss_set_fck_rate(dpi->dss, ctx.fck);
323 	if (r)
324 		return r;
325 
326 	dpi->mgr_config.clock_info = ctx.dispc_cinfo;
327 
328 	return 0;
329 }
330 
331 static int dpi_set_mode(struct dpi_data *dpi)
332 {
333 	int r;
334 
335 	if (dpi->pll)
336 		r = dpi_set_pll_clk(dpi, dpi->pixelclock);
337 	else
338 		r = dpi_set_dispc_clk(dpi, dpi->pixelclock);
339 
340 	return r;
341 }
342 
343 static void dpi_config_lcd_manager(struct dpi_data *dpi)
344 {
345 	dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
346 
347 	dpi->mgr_config.stallmode = false;
348 	dpi->mgr_config.fifohandcheck = false;
349 
350 	dpi->mgr_config.video_port_width = dpi->data_lines;
351 
352 	dpi->mgr_config.lcden_sig_polarity = 0;
353 
354 	dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
355 }
356 
357 static int dpi_clock_update(struct dpi_data *dpi, unsigned long *clock)
358 {
359 	int lck_div, pck_div;
360 	unsigned long fck;
361 	struct dpi_clk_calc_ctx ctx;
362 
363 	if (dpi->pll) {
364 		if (!dpi_pll_clk_calc(dpi, *clock, &ctx))
365 			return -EINVAL;
366 
367 		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
368 	} else {
369 		if (!dpi_dss_clk_calc(dpi, *clock, &ctx))
370 			return -EINVAL;
371 
372 		fck = ctx.fck;
373 	}
374 
375 	lck_div = ctx.dispc_cinfo.lck_div;
376 	pck_div = ctx.dispc_cinfo.pck_div;
377 
378 	*clock = fck / lck_div / pck_div;
379 
380 	return 0;
381 }
382 
383 static int dpi_verify_pll(struct dss_pll *pll)
384 {
385 	int r;
386 
387 	/* do initial setup with the PLL to see if it is operational */
388 
389 	r = dss_pll_enable(pll);
390 	if (r)
391 		return r;
392 
393 	dss_pll_disable(pll);
394 
395 	return 0;
396 }
397 
398 static void dpi_init_pll(struct dpi_data *dpi)
399 {
400 	struct dss_pll *pll;
401 
402 	if (dpi->pll)
403 		return;
404 
405 	dpi->clk_src = dpi_get_clk_src(dpi);
406 
407 	pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
408 	if (!pll)
409 		return;
410 
411 	if (dpi_verify_pll(pll)) {
412 		DSSWARN("PLL not operational\n");
413 		return;
414 	}
415 
416 	dpi->pll = pll;
417 }
418 
419 /* -----------------------------------------------------------------------------
420  * DRM Bridge Operations
421  */
422 
423 static int dpi_bridge_attach(struct drm_bridge *bridge,
424 			     struct drm_encoder *encoder,
425 			     enum drm_bridge_attach_flags flags)
426 {
427 	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
428 
429 	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
430 		return -EINVAL;
431 
432 	dpi_init_pll(dpi);
433 
434 	return drm_bridge_attach(encoder, dpi->output.next_bridge,
435 				 bridge, flags);
436 }
437 
438 static enum drm_mode_status
439 dpi_bridge_mode_valid(struct drm_bridge *bridge,
440 		       const struct drm_display_info *info,
441 		       const struct drm_display_mode *mode)
442 {
443 	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
444 	unsigned long clock = mode->clock * 1000;
445 	int ret;
446 
447 	if (mode->hdisplay % 8 != 0)
448 		return MODE_BAD_WIDTH;
449 
450 	if (mode->clock == 0)
451 		return MODE_NOCLOCK;
452 
453 	ret = dpi_clock_update(dpi, &clock);
454 	if (ret < 0)
455 		return MODE_CLOCK_RANGE;
456 
457 	return MODE_OK;
458 }
459 
460 static bool dpi_bridge_mode_fixup(struct drm_bridge *bridge,
461 				   const struct drm_display_mode *mode,
462 				   struct drm_display_mode *adjusted_mode)
463 {
464 	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
465 	unsigned long clock = mode->clock * 1000;
466 	int ret;
467 
468 	ret = dpi_clock_update(dpi, &clock);
469 	if (ret < 0)
470 		return false;
471 
472 	adjusted_mode->clock = clock / 1000;
473 
474 	return true;
475 }
476 
477 static void dpi_bridge_mode_set(struct drm_bridge *bridge,
478 				 const struct drm_display_mode *mode,
479 				 const struct drm_display_mode *adjusted_mode)
480 {
481 	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
482 
483 	dpi->pixelclock = adjusted_mode->clock * 1000;
484 }
485 
486 static void dpi_bridge_enable(struct drm_bridge *bridge,
487 			      struct drm_atomic_commit *commit)
488 {
489 	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
490 	int r;
491 
492 	if (dpi->vdds_dsi_reg) {
493 		r = regulator_enable(dpi->vdds_dsi_reg);
494 		if (r)
495 			return;
496 	}
497 
498 	r = dispc_runtime_get(dpi->dss->dispc);
499 	if (r)
500 		goto err_get_dispc;
501 
502 	r = dss_dpi_select_source(dpi->dss, dpi->id, dpi->output.dispc_channel);
503 	if (r)
504 		goto err_src_sel;
505 
506 	if (dpi->pll) {
507 		r = dss_pll_enable(dpi->pll);
508 		if (r)
509 			goto err_pll_init;
510 	}
511 
512 	r = dpi_set_mode(dpi);
513 	if (r)
514 		goto err_set_mode;
515 
516 	dpi_config_lcd_manager(dpi);
517 
518 	mdelay(2);
519 
520 	r = dss_mgr_enable(&dpi->output);
521 	if (r)
522 		goto err_mgr_enable;
523 
524 	return;
525 
526 err_mgr_enable:
527 err_set_mode:
528 	if (dpi->pll)
529 		dss_pll_disable(dpi->pll);
530 err_pll_init:
531 err_src_sel:
532 	dispc_runtime_put(dpi->dss->dispc);
533 err_get_dispc:
534 	if (dpi->vdds_dsi_reg)
535 		regulator_disable(dpi->vdds_dsi_reg);
536 }
537 
538 static void dpi_bridge_disable(struct drm_bridge *bridge,
539 			       struct drm_atomic_commit *commit)
540 {
541 	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
542 
543 	dss_mgr_disable(&dpi->output);
544 
545 	if (dpi->pll) {
546 		dss_select_lcd_clk_source(dpi->dss, dpi->output.dispc_channel,
547 					  DSS_CLK_SRC_FCK);
548 		dss_pll_disable(dpi->pll);
549 	}
550 
551 	dispc_runtime_put(dpi->dss->dispc);
552 
553 	if (dpi->vdds_dsi_reg)
554 		regulator_disable(dpi->vdds_dsi_reg);
555 }
556 
557 static const struct drm_bridge_funcs dpi_bridge_funcs = {
558 	.atomic_create_state = drm_atomic_helper_bridge_create_state,
559 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
560 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
561 	.attach = dpi_bridge_attach,
562 	.mode_valid = dpi_bridge_mode_valid,
563 	.mode_fixup = dpi_bridge_mode_fixup,
564 	.mode_set = dpi_bridge_mode_set,
565 	.atomic_enable = dpi_bridge_enable,
566 	.atomic_disable = dpi_bridge_disable,
567 };
568 
569 static void dpi_bridge_init(struct dpi_data *dpi)
570 {
571 	dpi->bridge.of_node = dpi->pdev->dev.of_node;
572 	dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;
573 
574 	drm_bridge_add(&dpi->bridge);
575 }
576 
577 static void dpi_bridge_cleanup(struct dpi_data *dpi)
578 {
579 	drm_bridge_remove(&dpi->bridge);
580 }
581 
582 /* -----------------------------------------------------------------------------
583  * Initialisation and Cleanup
584  */
585 
586 /*
587  * Return a hardcoded channel for the DPI output. This should work for
588  * current use cases, but this can be later expanded to either resolve
589  * the channel in some more dynamic manner, or get the channel as a user
590  * parameter.
591  */
592 static enum omap_channel dpi_get_channel(struct dpi_data *dpi)
593 {
594 	switch (dpi->dss_model) {
595 	case DSS_MODEL_OMAP2:
596 	case DSS_MODEL_OMAP3:
597 		return OMAP_DSS_CHANNEL_LCD;
598 
599 	case DSS_MODEL_DRA7:
600 		switch (dpi->id) {
601 		case 2:
602 			return OMAP_DSS_CHANNEL_LCD3;
603 		case 1:
604 			return OMAP_DSS_CHANNEL_LCD2;
605 		case 0:
606 		default:
607 			return OMAP_DSS_CHANNEL_LCD;
608 		}
609 
610 	case DSS_MODEL_OMAP4:
611 		return OMAP_DSS_CHANNEL_LCD2;
612 
613 	case DSS_MODEL_OMAP5:
614 		return OMAP_DSS_CHANNEL_LCD3;
615 
616 	default:
617 		DSSWARN("unsupported DSS version\n");
618 		return OMAP_DSS_CHANNEL_LCD;
619 	}
620 }
621 
622 static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
623 {
624 	struct omap_dss_device *out = &dpi->output;
625 	u32 port_num = 0;
626 	int r;
627 
628 	dpi_bridge_init(dpi);
629 
630 	of_property_read_u32(port, "reg", &port_num);
631 	dpi->id = port_num <= 2 ? port_num : 0;
632 
633 	switch (port_num) {
634 	case 2:
635 		out->name = "dpi.2";
636 		break;
637 	case 1:
638 		out->name = "dpi.1";
639 		break;
640 	case 0:
641 	default:
642 		out->name = "dpi.0";
643 		break;
644 	}
645 
646 	out->dev = &dpi->pdev->dev;
647 	out->id = OMAP_DSS_OUTPUT_DPI;
648 	out->type = OMAP_DISPLAY_TYPE_DPI;
649 	out->dispc_channel = dpi_get_channel(dpi);
650 	out->of_port = port_num;
651 
652 	r = omapdss_device_init_output(out, &dpi->bridge);
653 	if (r < 0) {
654 		dpi_bridge_cleanup(dpi);
655 		return r;
656 	}
657 
658 	omapdss_device_register(out);
659 
660 	return 0;
661 }
662 
663 static void dpi_uninit_output_port(struct device_node *port)
664 {
665 	struct dpi_data *dpi = port->data;
666 	struct omap_dss_device *out = &dpi->output;
667 
668 	omapdss_device_unregister(out);
669 	omapdss_device_cleanup_output(out);
670 
671 	dpi_bridge_cleanup(dpi);
672 }
673 
674 /* -----------------------------------------------------------------------------
675  * Initialisation and Cleanup
676  */
677 
678 static const struct soc_device_attribute dpi_soc_devices[] = {
679 	{ .machine = "OMAP3[456]*" },
680 	{ .machine = "[AD]M37*" },
681 	{ /* sentinel */ }
682 };
683 
684 static int dpi_init_regulator(struct dpi_data *dpi)
685 {
686 	struct regulator *vdds_dsi;
687 
688 	/*
689 	 * The DPI uses the DSI VDDS on OMAP34xx, OMAP35xx, OMAP36xx, AM37xx and
690 	 * DM37xx only.
691 	 */
692 	if (!soc_device_match(dpi_soc_devices))
693 		return 0;
694 
695 	vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
696 	if (IS_ERR(vdds_dsi)) {
697 		if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
698 			DSSERR("can't get VDDS_DSI regulator\n");
699 		return PTR_ERR(vdds_dsi);
700 	}
701 
702 	dpi->vdds_dsi_reg = vdds_dsi;
703 
704 	return 0;
705 }
706 
707 int dpi_init_port(struct dss_device *dss, struct platform_device *pdev,
708 		  struct device_node *port, enum dss_model dss_model)
709 {
710 	struct dpi_data *dpi;
711 	struct device_node *ep;
712 	u32 datalines;
713 	int r;
714 
715 	dpi = devm_drm_bridge_alloc(&pdev->dev, struct dpi_data, bridge, &dpi_bridge_funcs);
716 	if (IS_ERR(dpi))
717 		return PTR_ERR(dpi);
718 
719 	ep = of_graph_get_next_port_endpoint(port, NULL);
720 	if (!ep)
721 		return 0;
722 
723 	r = of_property_read_u32(ep, "data-lines", &datalines);
724 	of_node_put(ep);
725 	if (r) {
726 		DSSERR("failed to parse datalines\n");
727 		return r;
728 	}
729 
730 	dpi->data_lines = datalines;
731 
732 	dpi->pdev = pdev;
733 	dpi->dss_model = dss_model;
734 	dpi->dss = dss;
735 	port->data = dpi;
736 
737 	r = dpi_init_regulator(dpi);
738 	if (r)
739 		return r;
740 
741 	return dpi_init_output_port(dpi, port);
742 }
743 
744 void dpi_uninit_port(struct device_node *port)
745 {
746 	struct dpi_data *dpi = port->data;
747 
748 	if (!dpi)
749 		return;
750 
751 	dpi_uninit_output_port(port);
752 }
753