OMAPDSS: DPI: Store dpi_data pointer in the DT port's data
[firefly-linux-kernel-4.4.55.git] / drivers / video / fbdev / omap2 / dss / dpi.c
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
35 #include <video/omapdss.h>
36
37 #include "dss.h"
38 #include "dss_features.h"
39
40 struct dpi_data {
41         struct platform_device *pdev;
42
43         struct regulator *vdds_dsi_reg;
44         struct platform_device *dsidev;
45
46         struct mutex lock;
47
48         struct omap_video_timings timings;
49         struct dss_lcd_mgr_config mgr_config;
50         int data_lines;
51
52         struct omap_dss_device output;
53
54         bool port_initialized;
55 };
56
57 static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
58 {
59         return container_of(dssdev, struct dpi_data, output);
60 }
61
62 /* only used in non-DT mode */
63 static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
64 {
65         return dev_get_drvdata(&pdev->dev);
66 }
67
68 static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
69 {
70         /*
71          * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
72          * would also be used for DISPC fclk. Meaning, when the DPI output is
73          * disabled, DISPC clock will be disabled, and TV out will stop.
74          */
75         switch (omapdss_get_version()) {
76         case OMAPDSS_VER_OMAP24xx:
77         case OMAPDSS_VER_OMAP34xx_ES1:
78         case OMAPDSS_VER_OMAP34xx_ES3:
79         case OMAPDSS_VER_OMAP3630:
80         case OMAPDSS_VER_AM35xx:
81         case OMAPDSS_VER_AM43xx:
82                 return NULL;
83
84         case OMAPDSS_VER_OMAP4430_ES1:
85         case OMAPDSS_VER_OMAP4430_ES2:
86         case OMAPDSS_VER_OMAP4:
87                 switch (channel) {
88                 case OMAP_DSS_CHANNEL_LCD:
89                         return dsi_get_dsidev_from_id(0);
90                 case OMAP_DSS_CHANNEL_LCD2:
91                         return dsi_get_dsidev_from_id(1);
92                 default:
93                         return NULL;
94                 }
95
96         case OMAPDSS_VER_OMAP5:
97                 switch (channel) {
98                 case OMAP_DSS_CHANNEL_LCD:
99                         return dsi_get_dsidev_from_id(0);
100                 case OMAP_DSS_CHANNEL_LCD3:
101                         return dsi_get_dsidev_from_id(1);
102                 default:
103                         return NULL;
104                 }
105
106         default:
107                 return NULL;
108         }
109 }
110
111 static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
112 {
113         switch (channel) {
114         case OMAP_DSS_CHANNEL_LCD:
115                 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
116         case OMAP_DSS_CHANNEL_LCD2:
117                 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
118         case OMAP_DSS_CHANNEL_LCD3:
119                 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
120         default:
121                 /* this shouldn't happen */
122                 WARN_ON(1);
123                 return OMAP_DSS_CLK_SRC_FCK;
124         }
125 }
126
127 struct dpi_clk_calc_ctx {
128         struct platform_device *dsidev;
129
130         /* inputs */
131
132         unsigned long pck_min, pck_max;
133
134         /* outputs */
135
136         struct dsi_clock_info dsi_cinfo;
137         unsigned long fck;
138         struct dispc_clock_info dispc_cinfo;
139 };
140
141 static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
142                 unsigned long pck, void *data)
143 {
144         struct dpi_clk_calc_ctx *ctx = data;
145
146         /*
147          * Odd dividers give us uneven duty cycle, causing problem when level
148          * shifted. So skip all odd dividers when the pixel clock is on the
149          * higher side.
150          */
151         if (ctx->pck_min >= 100000000) {
152                 if (lckd > 1 && lckd % 2 != 0)
153                         return false;
154
155                 if (pckd > 1 && pckd % 2 != 0)
156                         return false;
157         }
158
159         ctx->dispc_cinfo.lck_div = lckd;
160         ctx->dispc_cinfo.pck_div = pckd;
161         ctx->dispc_cinfo.lck = lck;
162         ctx->dispc_cinfo.pck = pck;
163
164         return true;
165 }
166
167
168 static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
169                 void *data)
170 {
171         struct dpi_clk_calc_ctx *ctx = data;
172
173         /*
174          * Odd dividers give us uneven duty cycle, causing problem when level
175          * shifted. So skip all odd dividers when the pixel clock is on the
176          * higher side.
177          */
178         if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 100000000)
179                 return false;
180
181         ctx->dsi_cinfo.regm_dispc = regm_dispc;
182         ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
183
184         return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
185                         dpi_calc_dispc_cb, ctx);
186 }
187
188
189 static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
190                 unsigned long pll,
191                 void *data)
192 {
193         struct dpi_clk_calc_ctx *ctx = data;
194
195         ctx->dsi_cinfo.regn = regn;
196         ctx->dsi_cinfo.regm = regm;
197         ctx->dsi_cinfo.fint = fint;
198         ctx->dsi_cinfo.clkin4ddr = pll;
199
200         return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
201                         dpi_calc_hsdiv_cb, ctx);
202 }
203
204 static bool dpi_calc_dss_cb(unsigned long fck, void *data)
205 {
206         struct dpi_clk_calc_ctx *ctx = data;
207
208         ctx->fck = fck;
209
210         return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
211                         dpi_calc_dispc_cb, ctx);
212 }
213
214 static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck,
215                 struct dpi_clk_calc_ctx *ctx)
216 {
217         unsigned long clkin;
218         unsigned long pll_min, pll_max;
219
220         clkin = dsi_get_pll_clkin(dpi->dsidev);
221
222         memset(ctx, 0, sizeof(*ctx));
223         ctx->dsidev = dpi->dsidev;
224         ctx->pck_min = pck - 1000;
225         ctx->pck_max = pck + 1000;
226         ctx->dsi_cinfo.clkin = clkin;
227
228         pll_min = 0;
229         pll_max = 0;
230
231         return dsi_pll_calc(dpi->dsidev, clkin,
232                         pll_min, pll_max,
233                         dpi_calc_pll_cb, ctx);
234 }
235
236 static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
237 {
238         int i;
239
240         /*
241          * DSS fck gives us very few possibilities, so finding a good pixel
242          * clock may not be possible. We try multiple times to find the clock,
243          * each time widening the pixel clock range we look for, up to
244          * +/- ~15MHz.
245          */
246
247         for (i = 0; i < 25; ++i) {
248                 bool ok;
249
250                 memset(ctx, 0, sizeof(*ctx));
251                 if (pck > 1000 * i * i * i)
252                         ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
253                 else
254                         ctx->pck_min = 0;
255                 ctx->pck_max = pck + 1000 * i * i * i;
256
257                 ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx);
258                 if (ok)
259                         return ok;
260         }
261
262         return false;
263 }
264
265
266
267 static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
268                 unsigned long pck_req, unsigned long *fck, int *lck_div,
269                 int *pck_div)
270 {
271         struct dpi_clk_calc_ctx ctx;
272         int r;
273         bool ok;
274
275         ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx);
276         if (!ok)
277                 return -EINVAL;
278
279         r = dsi_pll_set_clock_div(dpi->dsidev, &ctx.dsi_cinfo);
280         if (r)
281                 return r;
282
283         dss_select_lcd_clk_source(channel,
284                         dpi_get_alt_clk_src(channel));
285
286         dpi->mgr_config.clock_info = ctx.dispc_cinfo;
287
288         *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
289         *lck_div = ctx.dispc_cinfo.lck_div;
290         *pck_div = ctx.dispc_cinfo.pck_div;
291
292         return 0;
293 }
294
295 static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
296                 unsigned long *fck, int *lck_div, int *pck_div)
297 {
298         struct dpi_clk_calc_ctx ctx;
299         int r;
300         bool ok;
301
302         ok = dpi_dss_clk_calc(pck_req, &ctx);
303         if (!ok)
304                 return -EINVAL;
305
306         r = dss_set_fck_rate(ctx.fck);
307         if (r)
308                 return r;
309
310         dpi->mgr_config.clock_info = ctx.dispc_cinfo;
311
312         *fck = ctx.fck;
313         *lck_div = ctx.dispc_cinfo.lck_div;
314         *pck_div = ctx.dispc_cinfo.pck_div;
315
316         return 0;
317 }
318
319 static int dpi_set_mode(struct dpi_data *dpi)
320 {
321         struct omap_dss_device *out = &dpi->output;
322         struct omap_overlay_manager *mgr = out->manager;
323         struct omap_video_timings *t = &dpi->timings;
324         int lck_div = 0, pck_div = 0;
325         unsigned long fck = 0;
326         unsigned long pck;
327         int r = 0;
328
329         if (dpi->dsidev)
330                 r = dpi_set_dsi_clk(dpi, mgr->id, t->pixelclock, &fck,
331                                 &lck_div, &pck_div);
332         else
333                 r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
334                                 &lck_div, &pck_div);
335         if (r)
336                 return r;
337
338         pck = fck / lck_div / pck_div;
339
340         if (pck != t->pixelclock) {
341                 DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
342                         t->pixelclock, pck);
343
344                 t->pixelclock = pck;
345         }
346
347         dss_mgr_set_timings(mgr, t);
348
349         return 0;
350 }
351
352 static void dpi_config_lcd_manager(struct dpi_data *dpi)
353 {
354         struct omap_dss_device *out = &dpi->output;
355         struct omap_overlay_manager *mgr = out->manager;
356
357         dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
358
359         dpi->mgr_config.stallmode = false;
360         dpi->mgr_config.fifohandcheck = false;
361
362         dpi->mgr_config.video_port_width = dpi->data_lines;
363
364         dpi->mgr_config.lcden_sig_polarity = 0;
365
366         dss_mgr_set_lcd_config(mgr, &dpi->mgr_config);
367 }
368
369 static int dpi_display_enable(struct omap_dss_device *dssdev)
370 {
371         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
372         struct omap_dss_device *out = &dpi->output;
373         int r;
374
375         mutex_lock(&dpi->lock);
376
377         if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) {
378                 DSSERR("no VDSS_DSI regulator\n");
379                 r = -ENODEV;
380                 goto err_no_reg;
381         }
382
383         if (out == NULL || out->manager == NULL) {
384                 DSSERR("failed to enable display: no output/manager\n");
385                 r = -ENODEV;
386                 goto err_no_out_mgr;
387         }
388
389         if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
390                 r = regulator_enable(dpi->vdds_dsi_reg);
391                 if (r)
392                         goto err_reg_enable;
393         }
394
395         r = dispc_runtime_get();
396         if (r)
397                 goto err_get_dispc;
398
399         r = dss_dpi_select_source(out->manager->id);
400         if (r)
401                 goto err_src_sel;
402
403         if (dpi->dsidev) {
404                 r = dsi_runtime_get(dpi->dsidev);
405                 if (r)
406                         goto err_get_dsi;
407
408                 r = dsi_pll_init(dpi->dsidev, 0, 1);
409                 if (r)
410                         goto err_dsi_pll_init;
411         }
412
413         r = dpi_set_mode(dpi);
414         if (r)
415                 goto err_set_mode;
416
417         dpi_config_lcd_manager(dpi);
418
419         mdelay(2);
420
421         r = dss_mgr_enable(out->manager);
422         if (r)
423                 goto err_mgr_enable;
424
425         mutex_unlock(&dpi->lock);
426
427         return 0;
428
429 err_mgr_enable:
430 err_set_mode:
431         if (dpi->dsidev)
432                 dsi_pll_uninit(dpi->dsidev, true);
433 err_dsi_pll_init:
434         if (dpi->dsidev)
435                 dsi_runtime_put(dpi->dsidev);
436 err_get_dsi:
437 err_src_sel:
438         dispc_runtime_put();
439 err_get_dispc:
440         if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
441                 regulator_disable(dpi->vdds_dsi_reg);
442 err_reg_enable:
443 err_no_out_mgr:
444 err_no_reg:
445         mutex_unlock(&dpi->lock);
446         return r;
447 }
448
449 static void dpi_display_disable(struct omap_dss_device *dssdev)
450 {
451         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
452         struct omap_overlay_manager *mgr = dpi->output.manager;
453
454         mutex_lock(&dpi->lock);
455
456         dss_mgr_disable(mgr);
457
458         if (dpi->dsidev) {
459                 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
460                 dsi_pll_uninit(dpi->dsidev, true);
461                 dsi_runtime_put(dpi->dsidev);
462         }
463
464         dispc_runtime_put();
465
466         if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
467                 regulator_disable(dpi->vdds_dsi_reg);
468
469         mutex_unlock(&dpi->lock);
470 }
471
472 static void dpi_set_timings(struct omap_dss_device *dssdev,
473                 struct omap_video_timings *timings)
474 {
475         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
476
477         DSSDBG("dpi_set_timings\n");
478
479         mutex_lock(&dpi->lock);
480
481         dpi->timings = *timings;
482
483         mutex_unlock(&dpi->lock);
484 }
485
486 static void dpi_get_timings(struct omap_dss_device *dssdev,
487                 struct omap_video_timings *timings)
488 {
489         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
490
491         mutex_lock(&dpi->lock);
492
493         *timings = dpi->timings;
494
495         mutex_unlock(&dpi->lock);
496 }
497
498 static int dpi_check_timings(struct omap_dss_device *dssdev,
499                         struct omap_video_timings *timings)
500 {
501         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
502         struct omap_overlay_manager *mgr = dpi->output.manager;
503         int lck_div, pck_div;
504         unsigned long fck;
505         unsigned long pck;
506         struct dpi_clk_calc_ctx ctx;
507         bool ok;
508
509         if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
510                 return -EINVAL;
511
512         if (timings->pixelclock == 0)
513                 return -EINVAL;
514
515         if (dpi->dsidev) {
516                 ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx);
517                 if (!ok)
518                         return -EINVAL;
519
520                 fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
521         } else {
522                 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
523                 if (!ok)
524                         return -EINVAL;
525
526                 fck = ctx.fck;
527         }
528
529         lck_div = ctx.dispc_cinfo.lck_div;
530         pck_div = ctx.dispc_cinfo.pck_div;
531
532         pck = fck / lck_div / pck_div;
533
534         timings->pixelclock = pck;
535
536         return 0;
537 }
538
539 static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
540 {
541         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
542
543         mutex_lock(&dpi->lock);
544
545         dpi->data_lines = data_lines;
546
547         mutex_unlock(&dpi->lock);
548 }
549
550 static int dpi_verify_dsi_pll(struct platform_device *dsidev)
551 {
552         int r;
553
554         /* do initial setup with the PLL to see if it is operational */
555
556         r = dsi_runtime_get(dsidev);
557         if (r)
558                 return r;
559
560         r = dsi_pll_init(dsidev, 0, 1);
561         if (r) {
562                 dsi_runtime_put(dsidev);
563                 return r;
564         }
565
566         dsi_pll_uninit(dsidev, true);
567         dsi_runtime_put(dsidev);
568
569         return 0;
570 }
571
572 static int dpi_init_regulator(struct dpi_data *dpi)
573 {
574         struct regulator *vdds_dsi;
575
576         if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
577                 return 0;
578
579         if (dpi->vdds_dsi_reg)
580                 return 0;
581
582         vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
583         if (IS_ERR(vdds_dsi)) {
584                 if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
585                         DSSERR("can't get VDDS_DSI regulator\n");
586                 return PTR_ERR(vdds_dsi);
587         }
588
589         dpi->vdds_dsi_reg = vdds_dsi;
590
591         return 0;
592 }
593
594 static void dpi_init_pll(struct dpi_data *dpi)
595 {
596         struct platform_device *dsidev;
597
598         if (dpi->dsidev)
599                 return;
600
601         dsidev = dpi_get_dsidev(dpi->output.dispc_channel);
602         if (!dsidev)
603                 return;
604
605         if (dpi_verify_dsi_pll(dsidev)) {
606                 DSSWARN("DSI PLL not operational\n");
607                 return;
608         }
609
610         dpi->dsidev = dsidev;
611 }
612
613 /*
614  * Return a hardcoded channel for the DPI output. This should work for
615  * current use cases, but this can be later expanded to either resolve
616  * the channel in some more dynamic manner, or get the channel as a user
617  * parameter.
618  */
619 static enum omap_channel dpi_get_channel(void)
620 {
621         switch (omapdss_get_version()) {
622         case OMAPDSS_VER_OMAP24xx:
623         case OMAPDSS_VER_OMAP34xx_ES1:
624         case OMAPDSS_VER_OMAP34xx_ES3:
625         case OMAPDSS_VER_OMAP3630:
626         case OMAPDSS_VER_AM35xx:
627         case OMAPDSS_VER_AM43xx:
628                 return OMAP_DSS_CHANNEL_LCD;
629
630         case OMAPDSS_VER_OMAP4430_ES1:
631         case OMAPDSS_VER_OMAP4430_ES2:
632         case OMAPDSS_VER_OMAP4:
633                 return OMAP_DSS_CHANNEL_LCD2;
634
635         case OMAPDSS_VER_OMAP5:
636                 return OMAP_DSS_CHANNEL_LCD3;
637
638         default:
639                 DSSWARN("unsupported DSS version\n");
640                 return OMAP_DSS_CHANNEL_LCD;
641         }
642 }
643
644 static int dpi_connect(struct omap_dss_device *dssdev,
645                 struct omap_dss_device *dst)
646 {
647         struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
648         struct omap_overlay_manager *mgr;
649         int r;
650
651         r = dpi_init_regulator(dpi);
652         if (r)
653                 return r;
654
655         dpi_init_pll(dpi);
656
657         mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
658         if (!mgr)
659                 return -ENODEV;
660
661         r = dss_mgr_connect(mgr, dssdev);
662         if (r)
663                 return r;
664
665         r = omapdss_output_set_device(dssdev, dst);
666         if (r) {
667                 DSSERR("failed to connect output to new device: %s\n",
668                                 dst->name);
669                 dss_mgr_disconnect(mgr, dssdev);
670                 return r;
671         }
672
673         return 0;
674 }
675
676 static void dpi_disconnect(struct omap_dss_device *dssdev,
677                 struct omap_dss_device *dst)
678 {
679         WARN_ON(dst != dssdev->dst);
680
681         if (dst != dssdev->dst)
682                 return;
683
684         omapdss_output_unset_device(dssdev);
685
686         if (dssdev->manager)
687                 dss_mgr_disconnect(dssdev->manager, dssdev);
688 }
689
690 static const struct omapdss_dpi_ops dpi_ops = {
691         .connect = dpi_connect,
692         .disconnect = dpi_disconnect,
693
694         .enable = dpi_display_enable,
695         .disable = dpi_display_disable,
696
697         .check_timings = dpi_check_timings,
698         .set_timings = dpi_set_timings,
699         .get_timings = dpi_get_timings,
700
701         .set_data_lines = dpi_set_data_lines,
702 };
703
704 static void dpi_init_output(struct platform_device *pdev)
705 {
706         struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
707         struct omap_dss_device *out = &dpi->output;
708
709         out->dev = &pdev->dev;
710         out->id = OMAP_DSS_OUTPUT_DPI;
711         out->output_type = OMAP_DISPLAY_TYPE_DPI;
712         out->name = "dpi.0";
713         out->dispc_channel = dpi_get_channel();
714         out->ops.dpi = &dpi_ops;
715         out->owner = THIS_MODULE;
716
717         omapdss_register_output(out);
718 }
719
720 static void __exit dpi_uninit_output(struct platform_device *pdev)
721 {
722         struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
723         struct omap_dss_device *out = &dpi->output;
724
725         omapdss_unregister_output(out);
726 }
727
728 static void dpi_init_output_port(struct platform_device *pdev,
729         struct device_node *port)
730 {
731         struct dpi_data *dpi = port->data;
732         struct omap_dss_device *out = &dpi->output;
733
734         out->dev = &pdev->dev;
735         out->id = OMAP_DSS_OUTPUT_DPI;
736         out->output_type = OMAP_DISPLAY_TYPE_DPI;
737         out->dispc_channel = dpi_get_channel();
738         out->ops.dpi = &dpi_ops;
739         out->owner = THIS_MODULE;
740
741         omapdss_register_output(out);
742 }
743
744 static void __exit dpi_uninit_output_port(struct device_node *port)
745 {
746         struct dpi_data *dpi = port->data;
747         struct omap_dss_device *out = &dpi->output;
748
749         omapdss_unregister_output(out);
750 }
751
752 static int omap_dpi_probe(struct platform_device *pdev)
753 {
754         struct dpi_data *dpi;
755
756         dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
757         if (!dpi)
758                 return -ENOMEM;
759
760         dpi->pdev = pdev;
761
762         dev_set_drvdata(&pdev->dev, dpi);
763
764         mutex_init(&dpi->lock);
765
766         dpi_init_output(pdev);
767
768         return 0;
769 }
770
771 static int __exit omap_dpi_remove(struct platform_device *pdev)
772 {
773         dpi_uninit_output(pdev);
774
775         return 0;
776 }
777
778 static struct platform_driver omap_dpi_driver = {
779         .probe          = omap_dpi_probe,
780         .remove         = __exit_p(omap_dpi_remove),
781         .driver         = {
782                 .name   = "omapdss_dpi",
783                 .owner  = THIS_MODULE,
784                 .suppress_bind_attrs = true,
785         },
786 };
787
788 int __init dpi_init_platform_driver(void)
789 {
790         return platform_driver_register(&omap_dpi_driver);
791 }
792
793 void __exit dpi_uninit_platform_driver(void)
794 {
795         platform_driver_unregister(&omap_dpi_driver);
796 }
797
798 int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
799 {
800         struct dpi_data *dpi;
801         struct device_node *ep;
802         u32 datalines;
803         int r;
804
805         dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
806         if (!dpi)
807                 return -ENOMEM;
808
809         ep = omapdss_of_get_next_endpoint(port, NULL);
810         if (!ep)
811                 return 0;
812
813         r = of_property_read_u32(ep, "data-lines", &datalines);
814         if (r) {
815                 DSSERR("failed to parse datalines\n");
816                 goto err_datalines;
817         }
818
819         dpi->data_lines = datalines;
820
821         of_node_put(ep);
822
823         dpi->pdev = pdev;
824         port->data = dpi;
825
826         mutex_init(&dpi->lock);
827
828         dpi_init_output_port(pdev, port);
829
830         dpi->port_initialized = true;
831
832         return 0;
833
834 err_datalines:
835         of_node_put(ep);
836
837         return r;
838 }
839
840 void __exit dpi_uninit_port(struct device_node *port)
841 {
842         struct dpi_data *dpi = port->data;
843
844         if (!dpi->port_initialized)
845                 return;
846
847         dpi_uninit_output_port(port);
848 }