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