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