1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#define DSS_SUBSYS_NAME "DSS"
24
25#include <linux/debugfs.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/io.h>
29#include <linux/export.h>
30#include <linux/err.h>
31#include <linux/delay.h>
32#include <linux/seq_file.h>
33#include <linux/clk.h>
34#include <linux/pinctrl/consumer.h>
35#include <linux/platform_device.h>
36#include <linux/pm_runtime.h>
37#include <linux/gfp.h>
38#include <linux/sizes.h>
39#include <linux/mfd/syscon.h>
40#include <linux/regmap.h>
41#include <linux/of.h>
42#include <linux/of_device.h>
43#include <linux/of_graph.h>
44#include <linux/regulator/consumer.h>
45#include <linux/suspend.h>
46#include <linux/component.h>
47#include <linux/sys_soc.h>
48
49#include "omapdss.h"
50#include "dss.h"
51
52#define DSS_SZ_REGS SZ_512
53
54struct dss_reg {
55 u16 idx;
56};
57
58#define DSS_REG(idx) ((const struct dss_reg) { idx })
59
60#define DSS_REVISION DSS_REG(0x0000)
61#define DSS_SYSCONFIG DSS_REG(0x0010)
62#define DSS_SYSSTATUS DSS_REG(0x0014)
63#define DSS_CONTROL DSS_REG(0x0040)
64#define DSS_SDI_CONTROL DSS_REG(0x0044)
65#define DSS_PLL_CONTROL DSS_REG(0x0048)
66#define DSS_SDI_STATUS DSS_REG(0x005C)
67
68#define REG_GET(idx, start, end) \
69 FLD_GET(dss_read_reg(idx), start, end)
70
71#define REG_FLD_MOD(idx, val, start, end) \
72 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
73
74struct dss_ops {
75 int (*dpi_select_source)(int port, enum omap_channel channel);
76 int (*select_lcd_source)(enum omap_channel channel,
77 enum dss_clk_source clk_src);
78};
79
80struct dss_features {
81 enum dss_model model;
82 u8 fck_div_max;
83 unsigned int fck_freq_max;
84 u8 dss_fck_multiplier;
85 const char *parent_clk_name;
86 const enum omap_display_type *ports;
87 int num_ports;
88 const enum omap_dss_output_id *outputs;
89 const struct dss_ops *ops;
90 struct dss_reg_field dispc_clk_switch;
91 bool has_lcd_clk_src;
92};
93
94static struct {
95 struct platform_device *pdev;
96 void __iomem *base;
97 struct regmap *syscon_pll_ctrl;
98 u32 syscon_pll_ctrl_offset;
99
100 struct clk *parent_clk;
101 struct clk *dss_clk;
102 unsigned long dss_clk_rate;
103
104 unsigned long cache_req_pck;
105 unsigned long cache_prate;
106 struct dispc_clock_info cache_dispc_cinfo;
107
108 enum dss_clk_source dsi_clk_source[MAX_NUM_DSI];
109 enum dss_clk_source dispc_clk_source;
110 enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
111
112 bool ctx_valid;
113 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
114
115 const struct dss_features *feat;
116
117 struct dss_pll *video1_pll;
118 struct dss_pll *video2_pll;
119} dss;
120
121static const char * const dss_generic_clk_source_names[] = {
122 [DSS_CLK_SRC_FCK] = "FCK",
123 [DSS_CLK_SRC_PLL1_1] = "PLL1:1",
124 [DSS_CLK_SRC_PLL1_2] = "PLL1:2",
125 [DSS_CLK_SRC_PLL1_3] = "PLL1:3",
126 [DSS_CLK_SRC_PLL2_1] = "PLL2:1",
127 [DSS_CLK_SRC_PLL2_2] = "PLL2:2",
128 [DSS_CLK_SRC_PLL2_3] = "PLL2:3",
129 [DSS_CLK_SRC_HDMI_PLL] = "HDMI PLL",
130};
131
132static inline void dss_write_reg(const struct dss_reg idx, u32 val)
133{
134 __raw_writel(val, dss.base + idx.idx);
135}
136
137static inline u32 dss_read_reg(const struct dss_reg idx)
138{
139 return __raw_readl(dss.base + idx.idx);
140}
141
142#define SR(reg) \
143 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
144#define RR(reg) \
145 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
146
147static void dss_save_context(void)
148{
149 DSSDBG("dss_save_context\n");
150
151 SR(CONTROL);
152
153 if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
154 SR(SDI_CONTROL);
155 SR(PLL_CONTROL);
156 }
157
158 dss.ctx_valid = true;
159
160 DSSDBG("context saved\n");
161}
162
163static void dss_restore_context(void)
164{
165 DSSDBG("dss_restore_context\n");
166
167 if (!dss.ctx_valid)
168 return;
169
170 RR(CONTROL);
171
172 if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
173 RR(SDI_CONTROL);
174 RR(PLL_CONTROL);
175 }
176
177 DSSDBG("context restored\n");
178}
179
180#undef SR
181#undef RR
182
183void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
184{
185 unsigned shift;
186 unsigned val;
187
188 if (!dss.syscon_pll_ctrl)
189 return;
190
191 val = !enable;
192
193 switch (pll_id) {
194 case DSS_PLL_VIDEO1:
195 shift = 0;
196 break;
197 case DSS_PLL_VIDEO2:
198 shift = 1;
199 break;
200 case DSS_PLL_HDMI:
201 shift = 2;
202 break;
203 default:
204 DSSERR("illegal DSS PLL ID %d\n", pll_id);
205 return;
206 }
207
208 regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
209 1 << shift, val << shift);
210}
211
212static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src,
213 enum omap_channel channel)
214{
215 unsigned shift, val;
216
217 if (!dss.syscon_pll_ctrl)
218 return -EINVAL;
219
220 switch (channel) {
221 case OMAP_DSS_CHANNEL_LCD:
222 shift = 3;
223
224 switch (clk_src) {
225 case DSS_CLK_SRC_PLL1_1:
226 val = 0; break;
227 case DSS_CLK_SRC_HDMI_PLL:
228 val = 1; break;
229 default:
230 DSSERR("error in PLL mux config for LCD\n");
231 return -EINVAL;
232 }
233
234 break;
235 case OMAP_DSS_CHANNEL_LCD2:
236 shift = 5;
237
238 switch (clk_src) {
239 case DSS_CLK_SRC_PLL1_3:
240 val = 0; break;
241 case DSS_CLK_SRC_PLL2_3:
242 val = 1; break;
243 case DSS_CLK_SRC_HDMI_PLL:
244 val = 2; break;
245 default:
246 DSSERR("error in PLL mux config for LCD2\n");
247 return -EINVAL;
248 }
249
250 break;
251 case OMAP_DSS_CHANNEL_LCD3:
252 shift = 7;
253
254 switch (clk_src) {
255 case DSS_CLK_SRC_PLL2_1:
256 val = 0; break;
257 case DSS_CLK_SRC_PLL1_3:
258 val = 1; break;
259 case DSS_CLK_SRC_HDMI_PLL:
260 val = 2; break;
261 default:
262 DSSERR("error in PLL mux config for LCD3\n");
263 return -EINVAL;
264 }
265
266 break;
267 default:
268 DSSERR("error in PLL mux config\n");
269 return -EINVAL;
270 }
271
272 regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
273 0x3 << shift, val << shift);
274
275 return 0;
276}
277
278void dss_sdi_init(int datapairs)
279{
280 u32 l;
281
282 BUG_ON(datapairs > 3 || datapairs < 1);
283
284 l = dss_read_reg(DSS_SDI_CONTROL);
285 l = FLD_MOD(l, 0xf, 19, 15);
286 l = FLD_MOD(l, datapairs-1, 3, 2);
287 l = FLD_MOD(l, 2, 1, 0);
288 dss_write_reg(DSS_SDI_CONTROL, l);
289
290 l = dss_read_reg(DSS_PLL_CONTROL);
291 l = FLD_MOD(l, 0x7, 25, 22);
292 l = FLD_MOD(l, 0xb, 16, 11);
293 l = FLD_MOD(l, 0xb4, 10, 1);
294 dss_write_reg(DSS_PLL_CONTROL, l);
295}
296
297int dss_sdi_enable(void)
298{
299 unsigned long timeout;
300
301 dispc_pck_free_enable(1);
302
303
304 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18);
305 udelay(1);
306
307
308 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28);
309
310
311 timeout = jiffies + msecs_to_jiffies(500);
312 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
313 if (time_after_eq(jiffies, timeout)) {
314 DSSERR("PLL lock request timed out\n");
315 goto err1;
316 }
317 }
318
319
320 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
321
322
323 timeout = jiffies + msecs_to_jiffies(500);
324 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
325 if (time_after_eq(jiffies, timeout)) {
326 DSSERR("PLL lock timed out\n");
327 goto err1;
328 }
329 }
330
331 dispc_lcd_enable_signal(1);
332
333
334 timeout = jiffies + msecs_to_jiffies(500);
335 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
336 if (time_after_eq(jiffies, timeout)) {
337 DSSERR("SDI reset timed out\n");
338 goto err2;
339 }
340 }
341
342 return 0;
343
344 err2:
345 dispc_lcd_enable_signal(0);
346 err1:
347
348 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18);
349
350 dispc_pck_free_enable(0);
351
352 return -ETIMEDOUT;
353}
354
355void dss_sdi_disable(void)
356{
357 dispc_lcd_enable_signal(0);
358
359 dispc_pck_free_enable(0);
360
361
362 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18);
363}
364
365const char *dss_get_clk_source_name(enum dss_clk_source clk_src)
366{
367 return dss_generic_clk_source_names[clk_src];
368}
369
370void dss_dump_clocks(struct seq_file *s)
371{
372 const char *fclk_name;
373 unsigned long fclk_rate;
374
375 if (dss_runtime_get())
376 return;
377
378 seq_printf(s, "- DSS -\n");
379
380 fclk_name = dss_get_clk_source_name(DSS_CLK_SRC_FCK);
381 fclk_rate = clk_get_rate(dss.dss_clk);
382
383 seq_printf(s, "%s = %lu\n",
384 fclk_name,
385 fclk_rate);
386
387 dss_runtime_put();
388}
389
390static void dss_dump_regs(struct seq_file *s)
391{
392#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
393
394 if (dss_runtime_get())
395 return;
396
397 DUMPREG(DSS_REVISION);
398 DUMPREG(DSS_SYSCONFIG);
399 DUMPREG(DSS_SYSSTATUS);
400 DUMPREG(DSS_CONTROL);
401
402 if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
403 DUMPREG(DSS_SDI_CONTROL);
404 DUMPREG(DSS_PLL_CONTROL);
405 DUMPREG(DSS_SDI_STATUS);
406 }
407
408 dss_runtime_put();
409#undef DUMPREG
410}
411
412static int dss_get_channel_index(enum omap_channel channel)
413{
414 switch (channel) {
415 case OMAP_DSS_CHANNEL_LCD:
416 return 0;
417 case OMAP_DSS_CHANNEL_LCD2:
418 return 1;
419 case OMAP_DSS_CHANNEL_LCD3:
420 return 2;
421 default:
422 WARN_ON(1);
423 return 0;
424 }
425}
426
427static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
428{
429 int b;
430
431
432
433
434
435 if (WARN_ON(dss.feat->has_lcd_clk_src && clk_src != DSS_CLK_SRC_FCK))
436 return;
437
438 switch (clk_src) {
439 case DSS_CLK_SRC_FCK:
440 b = 0;
441 break;
442 case DSS_CLK_SRC_PLL1_1:
443 b = 1;
444 break;
445 case DSS_CLK_SRC_PLL2_1:
446 b = 2;
447 break;
448 default:
449 BUG();
450 return;
451 }
452
453 REG_FLD_MOD(DSS_CONTROL, b,
454 dss.feat->dispc_clk_switch.start,
455 dss.feat->dispc_clk_switch.end);
456
457 dss.dispc_clk_source = clk_src;
458}
459
460void dss_select_dsi_clk_source(int dsi_module,
461 enum dss_clk_source clk_src)
462{
463 int b, pos;
464
465 switch (clk_src) {
466 case DSS_CLK_SRC_FCK:
467 b = 0;
468 break;
469 case DSS_CLK_SRC_PLL1_2:
470 BUG_ON(dsi_module != 0);
471 b = 1;
472 break;
473 case DSS_CLK_SRC_PLL2_2:
474 BUG_ON(dsi_module != 1);
475 b = 1;
476 break;
477 default:
478 BUG();
479 return;
480 }
481
482 pos = dsi_module == 0 ? 1 : 10;
483 REG_FLD_MOD(DSS_CONTROL, b, pos, pos);
484
485 dss.dsi_clk_source[dsi_module] = clk_src;
486}
487
488static int dss_lcd_clk_mux_dra7(enum omap_channel channel,
489 enum dss_clk_source clk_src)
490{
491 const u8 ctrl_bits[] = {
492 [OMAP_DSS_CHANNEL_LCD] = 0,
493 [OMAP_DSS_CHANNEL_LCD2] = 12,
494 [OMAP_DSS_CHANNEL_LCD3] = 19,
495 };
496
497 u8 ctrl_bit = ctrl_bits[channel];
498 int r;
499
500 if (clk_src == DSS_CLK_SRC_FCK) {
501
502 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
503 return -EINVAL;
504 }
505
506 r = dss_ctrl_pll_set_control_mux(clk_src, channel);
507 if (r)
508 return r;
509
510 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
511
512 return 0;
513}
514
515static int dss_lcd_clk_mux_omap5(enum omap_channel channel,
516 enum dss_clk_source clk_src)
517{
518 const u8 ctrl_bits[] = {
519 [OMAP_DSS_CHANNEL_LCD] = 0,
520 [OMAP_DSS_CHANNEL_LCD2] = 12,
521 [OMAP_DSS_CHANNEL_LCD3] = 19,
522 };
523 const enum dss_clk_source allowed_plls[] = {
524 [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
525 [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK,
526 [OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1,
527 };
528
529 u8 ctrl_bit = ctrl_bits[channel];
530
531 if (clk_src == DSS_CLK_SRC_FCK) {
532
533 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
534 return -EINVAL;
535 }
536
537 if (WARN_ON(allowed_plls[channel] != clk_src))
538 return -EINVAL;
539
540 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
541
542 return 0;
543}
544
545static int dss_lcd_clk_mux_omap4(enum omap_channel channel,
546 enum dss_clk_source clk_src)
547{
548 const u8 ctrl_bits[] = {
549 [OMAP_DSS_CHANNEL_LCD] = 0,
550 [OMAP_DSS_CHANNEL_LCD2] = 12,
551 };
552 const enum dss_clk_source allowed_plls[] = {
553 [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
554 [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1,
555 };
556
557 u8 ctrl_bit = ctrl_bits[channel];
558
559 if (clk_src == DSS_CLK_SRC_FCK) {
560
561 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
562 return 0;
563 }
564
565 if (WARN_ON(allowed_plls[channel] != clk_src))
566 return -EINVAL;
567
568 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
569
570 return 0;
571}
572
573void dss_select_lcd_clk_source(enum omap_channel channel,
574 enum dss_clk_source clk_src)
575{
576 int idx = dss_get_channel_index(channel);
577 int r;
578
579 if (!dss.feat->has_lcd_clk_src) {
580 dss_select_dispc_clk_source(clk_src);
581 dss.lcd_clk_source[idx] = clk_src;
582 return;
583 }
584
585 r = dss.feat->ops->select_lcd_source(channel, clk_src);
586 if (r)
587 return;
588
589 dss.lcd_clk_source[idx] = clk_src;
590}
591
592enum dss_clk_source dss_get_dispc_clk_source(void)
593{
594 return dss.dispc_clk_source;
595}
596
597enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
598{
599 return dss.dsi_clk_source[dsi_module];
600}
601
602enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
603{
604 if (dss.feat->has_lcd_clk_src) {
605 int idx = dss_get_channel_index(channel);
606 return dss.lcd_clk_source[idx];
607 } else {
608
609
610 return dss.dispc_clk_source;
611 }
612}
613
614bool dss_div_calc(unsigned long pck, unsigned long fck_min,
615 dss_div_calc_func func, void *data)
616{
617 int fckd, fckd_start, fckd_stop;
618 unsigned long fck;
619 unsigned long fck_hw_max;
620 unsigned long fckd_hw_max;
621 unsigned long prate;
622 unsigned m;
623
624 fck_hw_max = dss.feat->fck_freq_max;
625
626 if (dss.parent_clk == NULL) {
627 unsigned pckd;
628
629 pckd = fck_hw_max / pck;
630
631 fck = pck * pckd;
632
633 fck = clk_round_rate(dss.dss_clk, fck);
634
635 return func(fck, data);
636 }
637
638 fckd_hw_max = dss.feat->fck_div_max;
639
640 m = dss.feat->dss_fck_multiplier;
641 prate = clk_get_rate(dss.parent_clk);
642
643 fck_min = fck_min ? fck_min : 1;
644
645 fckd_start = min(prate * m / fck_min, fckd_hw_max);
646 fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
647
648 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
649 fck = DIV_ROUND_UP(prate, fckd) * m;
650
651 if (func(fck, data))
652 return true;
653 }
654
655 return false;
656}
657
658int dss_set_fck_rate(unsigned long rate)
659{
660 int r;
661
662 DSSDBG("set fck to %lu\n", rate);
663
664 r = clk_set_rate(dss.dss_clk, rate);
665 if (r)
666 return r;
667
668 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
669
670 WARN_ONCE(dss.dss_clk_rate != rate,
671 "clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
672 rate);
673
674 return 0;
675}
676
677unsigned long dss_get_dispc_clk_rate(void)
678{
679 return dss.dss_clk_rate;
680}
681
682unsigned long dss_get_max_fck_rate(void)
683{
684 return dss.feat->fck_freq_max;
685}
686
687enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel)
688{
689 return dss.feat->outputs[channel];
690}
691
692static int dss_setup_default_clock(void)
693{
694 unsigned long max_dss_fck, prate;
695 unsigned long fck;
696 unsigned fck_div;
697 int r;
698
699 max_dss_fck = dss.feat->fck_freq_max;
700
701 if (dss.parent_clk == NULL) {
702 fck = clk_round_rate(dss.dss_clk, max_dss_fck);
703 } else {
704 prate = clk_get_rate(dss.parent_clk);
705
706 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
707 max_dss_fck);
708 fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
709 }
710
711 r = dss_set_fck_rate(fck);
712 if (r)
713 return r;
714
715 return 0;
716}
717
718void dss_set_venc_output(enum omap_dss_venc_type type)
719{
720 int l = 0;
721
722 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
723 l = 0;
724 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
725 l = 1;
726 else
727 BUG();
728
729
730 REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
731}
732
733void dss_set_dac_pwrdn_bgz(bool enable)
734{
735 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5);
736}
737
738void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
739{
740 enum omap_dss_output_id outputs;
741
742 outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
743
744
745 WARN_ON((src == DSS_VENC_TV_CLK) && !(outputs & OMAP_DSS_OUTPUT_VENC));
746 WARN_ON((src == DSS_HDMI_M_PCLK) && !(outputs & OMAP_DSS_OUTPUT_HDMI));
747
748
749 if ((outputs & OMAP_DSS_OUTPUT_VENC) &&
750 (outputs & OMAP_DSS_OUTPUT_HDMI))
751 REG_FLD_MOD(DSS_CONTROL, src, 15, 15);
752}
753
754enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
755{
756 enum omap_dss_output_id outputs;
757
758 outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
759 if ((outputs & OMAP_DSS_OUTPUT_HDMI) == 0)
760 return DSS_VENC_TV_CLK;
761
762 if ((outputs & OMAP_DSS_OUTPUT_VENC) == 0)
763 return DSS_HDMI_M_PCLK;
764
765 return REG_GET(DSS_CONTROL, 15, 15);
766}
767
768static int dss_dpi_select_source_omap2_omap3(int port, enum omap_channel channel)
769{
770 if (channel != OMAP_DSS_CHANNEL_LCD)
771 return -EINVAL;
772
773 return 0;
774}
775
776static int dss_dpi_select_source_omap4(int port, enum omap_channel channel)
777{
778 int val;
779
780 switch (channel) {
781 case OMAP_DSS_CHANNEL_LCD2:
782 val = 0;
783 break;
784 case OMAP_DSS_CHANNEL_DIGIT:
785 val = 1;
786 break;
787 default:
788 return -EINVAL;
789 }
790
791 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
792
793 return 0;
794}
795
796static int dss_dpi_select_source_omap5(int port, enum omap_channel channel)
797{
798 int val;
799
800 switch (channel) {
801 case OMAP_DSS_CHANNEL_LCD:
802 val = 1;
803 break;
804 case OMAP_DSS_CHANNEL_LCD2:
805 val = 2;
806 break;
807 case OMAP_DSS_CHANNEL_LCD3:
808 val = 3;
809 break;
810 case OMAP_DSS_CHANNEL_DIGIT:
811 val = 0;
812 break;
813 default:
814 return -EINVAL;
815 }
816
817 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
818
819 return 0;
820}
821
822static int dss_dpi_select_source_dra7xx(int port, enum omap_channel channel)
823{
824 switch (port) {
825 case 0:
826 return dss_dpi_select_source_omap5(port, channel);
827 case 1:
828 if (channel != OMAP_DSS_CHANNEL_LCD2)
829 return -EINVAL;
830 break;
831 case 2:
832 if (channel != OMAP_DSS_CHANNEL_LCD3)
833 return -EINVAL;
834 break;
835 default:
836 return -EINVAL;
837 }
838
839 return 0;
840}
841
842int dss_dpi_select_source(int port, enum omap_channel channel)
843{
844 return dss.feat->ops->dpi_select_source(port, channel);
845}
846
847static int dss_get_clocks(void)
848{
849 struct clk *clk;
850
851 clk = devm_clk_get(&dss.pdev->dev, "fck");
852 if (IS_ERR(clk)) {
853 DSSERR("can't get clock fck\n");
854 return PTR_ERR(clk);
855 }
856
857 dss.dss_clk = clk;
858
859 if (dss.feat->parent_clk_name) {
860 clk = clk_get(NULL, dss.feat->parent_clk_name);
861 if (IS_ERR(clk)) {
862 DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
863 return PTR_ERR(clk);
864 }
865 } else {
866 clk = NULL;
867 }
868
869 dss.parent_clk = clk;
870
871 return 0;
872}
873
874static void dss_put_clocks(void)
875{
876 if (dss.parent_clk)
877 clk_put(dss.parent_clk);
878}
879
880int dss_runtime_get(void)
881{
882 int r;
883
884 DSSDBG("dss_runtime_get\n");
885
886 r = pm_runtime_get_sync(&dss.pdev->dev);
887 WARN_ON(r < 0);
888 return r < 0 ? r : 0;
889}
890
891void dss_runtime_put(void)
892{
893 int r;
894
895 DSSDBG("dss_runtime_put\n");
896
897 r = pm_runtime_put_sync(&dss.pdev->dev);
898 WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
899}
900
901
902#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
903static void dss_debug_dump_clocks(struct seq_file *s)
904{
905 dss_dump_clocks(s);
906 dispc_dump_clocks(s);
907#ifdef CONFIG_OMAP2_DSS_DSI
908 dsi_dump_clocks(s);
909#endif
910}
911
912static int dss_debug_show(struct seq_file *s, void *unused)
913{
914 void (*func)(struct seq_file *) = s->private;
915
916 func(s);
917 return 0;
918}
919
920static int dss_debug_open(struct inode *inode, struct file *file)
921{
922 return single_open(file, dss_debug_show, inode->i_private);
923}
924
925static const struct file_operations dss_debug_fops = {
926 .open = dss_debug_open,
927 .read = seq_read,
928 .llseek = seq_lseek,
929 .release = single_release,
930};
931
932static struct dentry *dss_debugfs_dir;
933
934static int dss_initialize_debugfs(void)
935{
936 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
937 if (IS_ERR(dss_debugfs_dir)) {
938 int err = PTR_ERR(dss_debugfs_dir);
939
940 dss_debugfs_dir = NULL;
941 return err;
942 }
943
944 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
945 &dss_debug_dump_clocks, &dss_debug_fops);
946
947 return 0;
948}
949
950static void dss_uninitialize_debugfs(void)
951{
952 if (dss_debugfs_dir)
953 debugfs_remove_recursive(dss_debugfs_dir);
954}
955
956int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
957{
958 struct dentry *d;
959
960 d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
961 write, &dss_debug_fops);
962
963 return PTR_ERR_OR_ZERO(d);
964}
965#else
966static inline int dss_initialize_debugfs(void)
967{
968 return 0;
969}
970static inline void dss_uninitialize_debugfs(void)
971{
972}
973#endif
974
975static const struct dss_ops dss_ops_omap2_omap3 = {
976 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
977};
978
979static const struct dss_ops dss_ops_omap4 = {
980 .dpi_select_source = &dss_dpi_select_source_omap4,
981 .select_lcd_source = &dss_lcd_clk_mux_omap4,
982};
983
984static const struct dss_ops dss_ops_omap5 = {
985 .dpi_select_source = &dss_dpi_select_source_omap5,
986 .select_lcd_source = &dss_lcd_clk_mux_omap5,
987};
988
989static const struct dss_ops dss_ops_dra7 = {
990 .dpi_select_source = &dss_dpi_select_source_dra7xx,
991 .select_lcd_source = &dss_lcd_clk_mux_dra7,
992};
993
994static const enum omap_display_type omap2plus_ports[] = {
995 OMAP_DISPLAY_TYPE_DPI,
996};
997
998static const enum omap_display_type omap34xx_ports[] = {
999 OMAP_DISPLAY_TYPE_DPI,
1000 OMAP_DISPLAY_TYPE_SDI,
1001};
1002
1003static const enum omap_display_type dra7xx_ports[] = {
1004 OMAP_DISPLAY_TYPE_DPI,
1005 OMAP_DISPLAY_TYPE_DPI,
1006 OMAP_DISPLAY_TYPE_DPI,
1007};
1008
1009static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
1010
1011 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
1012
1013
1014 OMAP_DSS_OUTPUT_VENC,
1015};
1016
1017static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
1018
1019 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
1020 OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
1021
1022
1023 OMAP_DSS_OUTPUT_VENC,
1024};
1025
1026static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
1027
1028 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
1029 OMAP_DSS_OUTPUT_DSI1,
1030
1031
1032 OMAP_DSS_OUTPUT_VENC,
1033};
1034
1035static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = {
1036
1037 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
1038};
1039
1040static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
1041
1042 OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
1043
1044
1045 OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
1046
1047
1048 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
1049 OMAP_DSS_OUTPUT_DSI2,
1050};
1051
1052static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
1053
1054 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
1055 OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
1056
1057
1058 OMAP_DSS_OUTPUT_HDMI,
1059
1060
1061 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
1062 OMAP_DSS_OUTPUT_DSI1,
1063
1064
1065 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
1066 OMAP_DSS_OUTPUT_DSI2,
1067};
1068
1069static const struct dss_features omap24xx_dss_feats = {
1070 .model = DSS_MODEL_OMAP2,
1071
1072
1073
1074
1075 .fck_div_max = 6,
1076 .fck_freq_max = 133000000,
1077 .dss_fck_multiplier = 2,
1078 .parent_clk_name = "core_ck",
1079 .ports = omap2plus_ports,
1080 .num_ports = ARRAY_SIZE(omap2plus_ports),
1081 .outputs = omap2_dss_supported_outputs,
1082 .ops = &dss_ops_omap2_omap3,
1083 .dispc_clk_switch = { 0, 0 },
1084 .has_lcd_clk_src = false,
1085};
1086
1087static const struct dss_features omap34xx_dss_feats = {
1088 .model = DSS_MODEL_OMAP3,
1089 .fck_div_max = 16,
1090 .fck_freq_max = 173000000,
1091 .dss_fck_multiplier = 2,
1092 .parent_clk_name = "dpll4_ck",
1093 .ports = omap34xx_ports,
1094 .outputs = omap3430_dss_supported_outputs,
1095 .num_ports = ARRAY_SIZE(omap34xx_ports),
1096 .ops = &dss_ops_omap2_omap3,
1097 .dispc_clk_switch = { 0, 0 },
1098 .has_lcd_clk_src = false,
1099};
1100
1101static const struct dss_features omap3630_dss_feats = {
1102 .model = DSS_MODEL_OMAP3,
1103 .fck_div_max = 32,
1104 .fck_freq_max = 173000000,
1105 .dss_fck_multiplier = 1,
1106 .parent_clk_name = "dpll4_ck",
1107 .ports = omap2plus_ports,
1108 .num_ports = ARRAY_SIZE(omap2plus_ports),
1109 .outputs = omap3630_dss_supported_outputs,
1110 .ops = &dss_ops_omap2_omap3,
1111 .dispc_clk_switch = { 0, 0 },
1112 .has_lcd_clk_src = false,
1113};
1114
1115static const struct dss_features omap44xx_dss_feats = {
1116 .model = DSS_MODEL_OMAP4,
1117 .fck_div_max = 32,
1118 .fck_freq_max = 186000000,
1119 .dss_fck_multiplier = 1,
1120 .parent_clk_name = "dpll_per_x2_ck",
1121 .ports = omap2plus_ports,
1122 .num_ports = ARRAY_SIZE(omap2plus_ports),
1123 .outputs = omap4_dss_supported_outputs,
1124 .ops = &dss_ops_omap4,
1125 .dispc_clk_switch = { 9, 8 },
1126 .has_lcd_clk_src = true,
1127};
1128
1129static const struct dss_features omap54xx_dss_feats = {
1130 .model = DSS_MODEL_OMAP5,
1131 .fck_div_max = 64,
1132 .fck_freq_max = 209250000,
1133 .dss_fck_multiplier = 1,
1134 .parent_clk_name = "dpll_per_x2_ck",
1135 .ports = omap2plus_ports,
1136 .num_ports = ARRAY_SIZE(omap2plus_ports),
1137 .outputs = omap5_dss_supported_outputs,
1138 .ops = &dss_ops_omap5,
1139 .dispc_clk_switch = { 9, 7 },
1140 .has_lcd_clk_src = true,
1141};
1142
1143static const struct dss_features am43xx_dss_feats = {
1144 .model = DSS_MODEL_OMAP3,
1145 .fck_div_max = 0,
1146 .fck_freq_max = 200000000,
1147 .dss_fck_multiplier = 0,
1148 .parent_clk_name = NULL,
1149 .ports = omap2plus_ports,
1150 .num_ports = ARRAY_SIZE(omap2plus_ports),
1151 .outputs = am43xx_dss_supported_outputs,
1152 .ops = &dss_ops_omap2_omap3,
1153 .dispc_clk_switch = { 0, 0 },
1154 .has_lcd_clk_src = true,
1155};
1156
1157static const struct dss_features dra7xx_dss_feats = {
1158 .model = DSS_MODEL_DRA7,
1159 .fck_div_max = 64,
1160 .fck_freq_max = 209250000,
1161 .dss_fck_multiplier = 1,
1162 .parent_clk_name = "dpll_per_x2_ck",
1163 .ports = dra7xx_ports,
1164 .num_ports = ARRAY_SIZE(dra7xx_ports),
1165 .outputs = omap5_dss_supported_outputs,
1166 .ops = &dss_ops_dra7,
1167 .dispc_clk_switch = { 9, 7 },
1168 .has_lcd_clk_src = true,
1169};
1170
1171static int dss_init_ports(struct platform_device *pdev)
1172{
1173 struct device_node *parent = pdev->dev.of_node;
1174 struct device_node *port;
1175 int i;
1176
1177 for (i = 0; i < dss.feat->num_ports; i++) {
1178 port = of_graph_get_port_by_id(parent, i);
1179 if (!port)
1180 continue;
1181
1182 switch (dss.feat->ports[i]) {
1183 case OMAP_DISPLAY_TYPE_DPI:
1184 dpi_init_port(pdev, port, dss.feat->model);
1185 break;
1186 case OMAP_DISPLAY_TYPE_SDI:
1187 sdi_init_port(pdev, port);
1188 break;
1189 default:
1190 break;
1191 }
1192 }
1193
1194 return 0;
1195}
1196
1197static void dss_uninit_ports(struct platform_device *pdev)
1198{
1199 struct device_node *parent = pdev->dev.of_node;
1200 struct device_node *port;
1201 int i;
1202
1203 for (i = 0; i < dss.feat->num_ports; i++) {
1204 port = of_graph_get_port_by_id(parent, i);
1205 if (!port)
1206 continue;
1207
1208 switch (dss.feat->ports[i]) {
1209 case OMAP_DISPLAY_TYPE_DPI:
1210 dpi_uninit_port(port);
1211 break;
1212 case OMAP_DISPLAY_TYPE_SDI:
1213 sdi_uninit_port(port);
1214 break;
1215 default:
1216 break;
1217 }
1218 }
1219}
1220
1221static int dss_video_pll_probe(struct platform_device *pdev)
1222{
1223 struct device_node *np = pdev->dev.of_node;
1224 struct regulator *pll_regulator;
1225 int r;
1226
1227 if (!np)
1228 return 0;
1229
1230 if (of_property_read_bool(np, "syscon-pll-ctrl")) {
1231 dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
1232 "syscon-pll-ctrl");
1233 if (IS_ERR(dss.syscon_pll_ctrl)) {
1234 dev_err(&pdev->dev,
1235 "failed to get syscon-pll-ctrl regmap\n");
1236 return PTR_ERR(dss.syscon_pll_ctrl);
1237 }
1238
1239 if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
1240 &dss.syscon_pll_ctrl_offset)) {
1241 dev_err(&pdev->dev,
1242 "failed to get syscon-pll-ctrl offset\n");
1243 return -EINVAL;
1244 }
1245 }
1246
1247 pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video");
1248 if (IS_ERR(pll_regulator)) {
1249 r = PTR_ERR(pll_regulator);
1250
1251 switch (r) {
1252 case -ENOENT:
1253 pll_regulator = NULL;
1254 break;
1255
1256 case -EPROBE_DEFER:
1257 return -EPROBE_DEFER;
1258
1259 default:
1260 DSSERR("can't get DPLL VDDA regulator\n");
1261 return r;
1262 }
1263 }
1264
1265 if (of_property_match_string(np, "reg-names", "pll1") >= 0) {
1266 dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator);
1267 if (IS_ERR(dss.video1_pll))
1268 return PTR_ERR(dss.video1_pll);
1269 }
1270
1271 if (of_property_match_string(np, "reg-names", "pll2") >= 0) {
1272 dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator);
1273 if (IS_ERR(dss.video2_pll)) {
1274 dss_video_pll_uninit(dss.video1_pll);
1275 return PTR_ERR(dss.video2_pll);
1276 }
1277 }
1278
1279 return 0;
1280}
1281
1282
1283static const struct of_device_id dss_of_match[] = {
1284 { .compatible = "ti,omap2-dss", .data = &omap24xx_dss_feats },
1285 { .compatible = "ti,omap3-dss", .data = &omap3630_dss_feats },
1286 { .compatible = "ti,omap4-dss", .data = &omap44xx_dss_feats },
1287 { .compatible = "ti,omap5-dss", .data = &omap54xx_dss_feats },
1288 { .compatible = "ti,dra7-dss", .data = &dra7xx_dss_feats },
1289 {},
1290};
1291MODULE_DEVICE_TABLE(of, dss_of_match);
1292
1293static const struct soc_device_attribute dss_soc_devices[] = {
1294 { .machine = "OMAP3430/3530", .data = &omap34xx_dss_feats },
1295 { .machine = "AM35??", .data = &omap34xx_dss_feats },
1296 { .family = "AM43xx", .data = &am43xx_dss_feats },
1297 { }
1298};
1299
1300static int dss_bind(struct device *dev)
1301{
1302 struct platform_device *pdev = to_platform_device(dev);
1303 struct resource *dss_mem;
1304 u32 rev;
1305 int r;
1306
1307 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
1308 dss.base = devm_ioremap_resource(&pdev->dev, dss_mem);
1309 if (IS_ERR(dss.base))
1310 return PTR_ERR(dss.base);
1311
1312 r = dss_get_clocks();
1313 if (r)
1314 return r;
1315
1316 r = dss_setup_default_clock();
1317 if (r)
1318 goto err_setup_clocks;
1319
1320 r = dss_video_pll_probe(pdev);
1321 if (r)
1322 goto err_pll_init;
1323
1324 r = dss_init_ports(pdev);
1325 if (r)
1326 goto err_init_ports;
1327
1328 pm_runtime_enable(&pdev->dev);
1329
1330 r = dss_runtime_get();
1331 if (r)
1332 goto err_runtime_get;
1333
1334 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
1335
1336
1337 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
1338
1339 dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
1340
1341#ifdef CONFIG_OMAP2_DSS_VENC
1342 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);
1343 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);
1344 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);
1345#endif
1346 dss.dsi_clk_source[0] = DSS_CLK_SRC_FCK;
1347 dss.dsi_clk_source[1] = DSS_CLK_SRC_FCK;
1348 dss.dispc_clk_source = DSS_CLK_SRC_FCK;
1349 dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
1350 dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
1351
1352 rev = dss_read_reg(DSS_REVISION);
1353 pr_info("OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1354
1355 dss_runtime_put();
1356
1357 r = component_bind_all(&pdev->dev, NULL);
1358 if (r)
1359 goto err_component;
1360
1361 dss_debugfs_create_file("dss", dss_dump_regs);
1362
1363 pm_set_vt_switch(0);
1364
1365 omapdss_gather_components(dev);
1366 omapdss_set_is_initialized(true);
1367
1368 return 0;
1369
1370err_component:
1371err_runtime_get:
1372 pm_runtime_disable(&pdev->dev);
1373 dss_uninit_ports(pdev);
1374err_init_ports:
1375 if (dss.video1_pll)
1376 dss_video_pll_uninit(dss.video1_pll);
1377
1378 if (dss.video2_pll)
1379 dss_video_pll_uninit(dss.video2_pll);
1380err_pll_init:
1381err_setup_clocks:
1382 dss_put_clocks();
1383 return r;
1384}
1385
1386static void dss_unbind(struct device *dev)
1387{
1388 struct platform_device *pdev = to_platform_device(dev);
1389
1390 omapdss_set_is_initialized(false);
1391
1392 component_unbind_all(&pdev->dev, NULL);
1393
1394 if (dss.video1_pll)
1395 dss_video_pll_uninit(dss.video1_pll);
1396
1397 if (dss.video2_pll)
1398 dss_video_pll_uninit(dss.video2_pll);
1399
1400 dss_uninit_ports(pdev);
1401
1402 pm_runtime_disable(&pdev->dev);
1403
1404 dss_put_clocks();
1405}
1406
1407static const struct component_master_ops dss_component_ops = {
1408 .bind = dss_bind,
1409 .unbind = dss_unbind,
1410};
1411
1412static int dss_component_compare(struct device *dev, void *data)
1413{
1414 struct device *child = data;
1415 return dev == child;
1416}
1417
1418static int dss_add_child_component(struct device *dev, void *data)
1419{
1420 struct component_match **match = data;
1421
1422
1423
1424
1425
1426
1427
1428 if (strstr(dev_name(dev), "rfbi"))
1429 return 0;
1430
1431 component_match_add(dev->parent, match, dss_component_compare, dev);
1432
1433 return 0;
1434}
1435
1436static int dss_probe(struct platform_device *pdev)
1437{
1438 const struct soc_device_attribute *soc;
1439 struct component_match *match = NULL;
1440 int r;
1441
1442 dss.pdev = pdev;
1443
1444
1445
1446
1447
1448 soc = soc_device_match(dss_soc_devices);
1449 if (soc)
1450 dss.feat = soc->data;
1451 else
1452 dss.feat = of_match_device(dss_of_match, &pdev->dev)->data;
1453
1454 r = dss_initialize_debugfs();
1455 if (r)
1456 return r;
1457
1458
1459 device_for_each_child(&pdev->dev, &match, dss_add_child_component);
1460
1461 r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
1462 if (r) {
1463 dss_uninitialize_debugfs();
1464 return r;
1465 }
1466
1467 return 0;
1468}
1469
1470static int dss_remove(struct platform_device *pdev)
1471{
1472 component_master_del(&pdev->dev, &dss_component_ops);
1473
1474 dss_uninitialize_debugfs();
1475
1476 return 0;
1477}
1478
1479static void dss_shutdown(struct platform_device *pdev)
1480{
1481 struct omap_dss_device *dssdev = NULL;
1482
1483 DSSDBG("shutdown\n");
1484
1485 for_each_dss_dev(dssdev) {
1486 if (!dssdev->driver)
1487 continue;
1488
1489 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
1490 dssdev->driver->disable(dssdev);
1491 }
1492}
1493
1494static int dss_runtime_suspend(struct device *dev)
1495{
1496 dss_save_context();
1497 dss_set_min_bus_tput(dev, 0);
1498
1499 pinctrl_pm_select_sleep_state(dev);
1500
1501 return 0;
1502}
1503
1504static int dss_runtime_resume(struct device *dev)
1505{
1506 int r;
1507
1508 pinctrl_pm_select_default_state(dev);
1509
1510
1511
1512
1513
1514
1515
1516
1517 r = dss_set_min_bus_tput(dev, 1000000000);
1518 if (r)
1519 return r;
1520
1521 dss_restore_context();
1522 return 0;
1523}
1524
1525static const struct dev_pm_ops dss_pm_ops = {
1526 .runtime_suspend = dss_runtime_suspend,
1527 .runtime_resume = dss_runtime_resume,
1528};
1529
1530static struct platform_driver omap_dsshw_driver = {
1531 .probe = dss_probe,
1532 .remove = dss_remove,
1533 .shutdown = dss_shutdown,
1534 .driver = {
1535 .name = "omapdss_dss",
1536 .pm = &dss_pm_ops,
1537 .of_match_table = dss_of_match,
1538 .suppress_bind_attrs = true,
1539 },
1540};
1541
1542int __init dss_init_platform_driver(void)
1543{
1544 return platform_driver_register(&omap_dsshw_driver);
1545}
1546
1547void dss_uninit_platform_driver(void)
1548{
1549 platform_driver_unregister(&omap_dsshw_driver);
1550}
1551