1 /*
2 * linux/drivers/video/omap2/dss/dss.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 */
23 #define DSS_SUBSYS_NAME "DSS"
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/io.h>
28 #include <linux/export.h>
29 #include <linux/err.h>
30 #include <linux/delay.h>
31 #include <linux/seq_file.h>
32 #include <linux/clk.h>
33 #include <linux/platform_device.h>
34 #include <linux/pm_runtime.h>
35 #include <linux/gfp.h>
36 #include <linux/sizes.h>
37 #include <linux/mfd/syscon.h>
38 #include <linux/regmap.h>
39 #include <linux/of.h>
41 #include <video/omapdss.h>
43 #include "dss.h"
44 #include "dss_features.h"
46 #define DSS_SZ_REGS SZ_512
48 struct dss_reg {
49 u16 idx;
50 };
52 #define DSS_REG(idx) ((const struct dss_reg) { idx })
54 #define DSS_REVISION DSS_REG(0x0000)
55 #define DSS_SYSCONFIG DSS_REG(0x0010)
56 #define DSS_SYSSTATUS DSS_REG(0x0014)
57 #define DSS_CONTROL DSS_REG(0x0040)
58 #define DSS_SDI_CONTROL DSS_REG(0x0044)
59 #define DSS_PLL_CONTROL DSS_REG(0x0048)
60 #define DSS_SDI_STATUS DSS_REG(0x005C)
62 #define REG_GET(idx, start, end) \
63 FLD_GET(dss_read_reg(idx), start, end)
65 #define REG_FLD_MOD(idx, val, start, end) \
66 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
68 struct dss_features {
69 u8 fck_div_max;
70 u8 dss_fck_multiplier;
71 const char *parent_clk_name;
72 enum omap_display_type *ports;
73 int num_ports;
74 int (*dpi_select_source)(int id, enum omap_channel channel);
75 bool pll_ext_ctrl;
76 bool video1_pll, video2_pll;
77 };
79 static struct {
80 struct platform_device *pdev;
81 void __iomem *base;
82 struct regmap *syscon;
84 struct clk *parent_clk;
85 struct clk *dss_clk;
86 unsigned long dss_clk_rate;
88 unsigned long cache_req_pck;
89 unsigned long cache_prate;
90 struct dispc_clock_info cache_dispc_cinfo;
92 enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
93 enum omap_dss_clk_source dispc_clk_source;
94 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
96 bool ctx_valid;
97 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
99 const struct dss_features *feat;
100 } dss;
102 static const char * const dss_generic_clk_source_names[] = {
103 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
104 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
105 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
106 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
107 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
108 };
110 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
111 {
112 __raw_writel(val, dss.base + idx.idx);
113 }
115 static inline u32 dss_read_reg(const struct dss_reg idx)
116 {
117 return __raw_readl(dss.base + idx.idx);
118 }
120 #define SR(reg) \
121 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
122 #define RR(reg) \
123 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
125 static void dss_save_context(void)
126 {
127 DSSDBG("dss_save_context\n");
129 SR(CONTROL);
131 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
132 OMAP_DISPLAY_TYPE_SDI) {
133 SR(SDI_CONTROL);
134 SR(PLL_CONTROL);
135 }
137 dss.ctx_valid = true;
139 DSSDBG("context saved\n");
140 }
142 static void dss_restore_context(void)
143 {
144 DSSDBG("dss_restore_context\n");
146 if (!dss.ctx_valid)
147 return;
149 RR(CONTROL);
151 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
152 OMAP_DISPLAY_TYPE_SDI) {
153 RR(SDI_CONTROL);
154 RR(PLL_CONTROL);
155 }
157 DSSDBG("context restored\n");
158 }
160 #undef SR
161 #undef RR
163 #define CTRL_CORE_DSS_PLL_CONTROL_OFF 0x538
165 void dss_ctrl_pll_enable(int pll_id, bool enable)
166 {
167 if (!dss.syscon)
168 return;
170 regmap_update_bits(dss.syscon, CTRL_CORE_DSS_PLL_CONTROL_OFF,
171 1 << pll_id, (!enable) << pll_id);
172 }
174 void dss_ctrl_hdmi_pll_enable(bool enable)
175 {
176 if (!dss.syscon)
177 return;
179 regmap_update_bits(dss.syscon, CTRL_CORE_DSS_PLL_CONTROL_OFF,
180 1 << 2, (!enable) << 2);
181 }
183 void dss_ctrl_pll_set_control_mux(int pll_id, enum omap_channel channel)
184 {
185 u8 shift, val;
187 if (!dss.syscon)
188 return;
190 switch (channel) {
191 case OMAP_DSS_CHANNEL_LCD:
192 shift = 3;
194 switch (pll_id) {
195 case 0:
196 val = 0; break;
197 case 2:
198 val = 1; break;
199 default:
200 DSSERR("error in PLL mux config for LCD\n");
201 return;
202 }
204 break;
205 case OMAP_DSS_CHANNEL_LCD2:
206 shift = 5;
208 switch (pll_id) {
209 case 0:
210 val = 0; break;
211 case 1:
212 val = 1; break;
213 case 2:
214 val = 2; break;
215 default:
216 DSSERR("error in PLL mux config for LCD2\n");
217 return;
218 }
220 break;
221 case OMAP_DSS_CHANNEL_LCD3:
222 shift = 7;
224 switch (pll_id) {
225 case 0:
226 val = 1; break;
227 case 1:
228 val = 0; break;
229 case 2:
230 val = 2; break;
231 default:
232 DSSERR("error in PLL mux config for LCD3\n");
233 return;
234 }
236 break;
237 default:
238 DSSERR("error in PLL mux config\n");
239 return;
240 }
242 regmap_update_bits(dss.syscon, CTRL_CORE_DSS_PLL_CONTROL_OFF,
243 0x3 << shift, val << shift);
244 }
246 void dss_sdi_init(int datapairs)
247 {
248 u32 l;
250 BUG_ON(datapairs > 3 || datapairs < 1);
252 l = dss_read_reg(DSS_SDI_CONTROL);
253 l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
254 l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
255 l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
256 dss_write_reg(DSS_SDI_CONTROL, l);
258 l = dss_read_reg(DSS_PLL_CONTROL);
259 l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
260 l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
261 l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
262 dss_write_reg(DSS_PLL_CONTROL, l);
263 }
265 int dss_sdi_enable(void)
266 {
267 unsigned long timeout;
269 dispc_pck_free_enable(1);
271 /* Reset SDI PLL */
272 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
273 udelay(1); /* wait 2x PCLK */
275 /* Lock SDI PLL */
276 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
278 /* Waiting for PLL lock request to complete */
279 timeout = jiffies + msecs_to_jiffies(500);
280 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
281 if (time_after_eq(jiffies, timeout)) {
282 DSSERR("PLL lock request timed out\n");
283 goto err1;
284 }
285 }
287 /* Clearing PLL_GO bit */
288 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
290 /* Waiting for PLL to lock */
291 timeout = jiffies + msecs_to_jiffies(500);
292 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
293 if (time_after_eq(jiffies, timeout)) {
294 DSSERR("PLL lock timed out\n");
295 goto err1;
296 }
297 }
299 dispc_lcd_enable_signal(1);
301 /* Waiting for SDI reset to complete */
302 timeout = jiffies + msecs_to_jiffies(500);
303 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
304 if (time_after_eq(jiffies, timeout)) {
305 DSSERR("SDI reset timed out\n");
306 goto err2;
307 }
308 }
310 return 0;
312 err2:
313 dispc_lcd_enable_signal(0);
314 err1:
315 /* Reset SDI PLL */
316 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
318 dispc_pck_free_enable(0);
320 return -ETIMEDOUT;
321 }
323 void dss_sdi_disable(void)
324 {
325 dispc_lcd_enable_signal(0);
327 dispc_pck_free_enable(0);
329 /* Reset SDI PLL */
330 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
331 }
333 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
334 {
335 return dss_generic_clk_source_names[clk_src];
336 }
338 void dss_dump_clocks(struct seq_file *s)
339 {
340 const char *fclk_name, *fclk_real_name;
341 unsigned long fclk_rate;
343 if (dss_runtime_get())
344 return;
346 seq_printf(s, "- DSS -\n");
348 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
349 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
350 fclk_rate = clk_get_rate(dss.dss_clk);
352 seq_printf(s, "%s (%s) = %lu\n",
353 fclk_name, fclk_real_name,
354 fclk_rate);
356 dss_runtime_put();
357 }
359 static void dss_dump_regs(struct seq_file *s)
360 {
361 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
363 if (dss_runtime_get())
364 return;
366 DUMPREG(DSS_REVISION);
367 DUMPREG(DSS_SYSCONFIG);
368 DUMPREG(DSS_SYSSTATUS);
369 DUMPREG(DSS_CONTROL);
371 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
372 OMAP_DISPLAY_TYPE_SDI) {
373 DUMPREG(DSS_SDI_CONTROL);
374 DUMPREG(DSS_PLL_CONTROL);
375 DUMPREG(DSS_SDI_STATUS);
376 }
378 dss_runtime_put();
379 #undef DUMPREG
380 }
382 static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
383 {
384 int b;
385 u8 start, end;
387 switch (clk_src) {
388 case OMAP_DSS_CLK_SRC_FCK:
389 b = 0;
390 break;
391 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
392 b = 1;
393 break;
394 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
395 b = 2;
396 break;
397 default:
398 BUG();
399 return;
400 }
402 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
404 REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */
406 dss.dispc_clk_source = clk_src;
407 }
409 void dss_select_dsi_clk_source(int dsi_module,
410 enum omap_dss_clk_source clk_src)
411 {
412 int b, pos;
414 switch (clk_src) {
415 case OMAP_DSS_CLK_SRC_FCK:
416 b = 0;
417 break;
418 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
419 BUG_ON(dsi_module != 0);
420 b = 1;
421 break;
422 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
423 BUG_ON(dsi_module != 1);
424 b = 1;
425 break;
426 default:
427 BUG();
428 return;
429 }
431 pos = dsi_module == 0 ? 1 : 10;
432 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */
434 dss.dsi_clk_source[dsi_module] = clk_src;
435 }
437 void dss_select_lcd_clk_source(enum omap_channel channel,
438 enum omap_dss_clk_source clk_src)
439 {
440 int b, ix, pos;
442 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
443 dss_select_dispc_clk_source(clk_src);
444 return;
445 }
447 switch (clk_src) {
448 case OMAP_DSS_CLK_SRC_FCK:
449 b = 0;
450 break;
451 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
452 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
453 b = 1;
454 break;
455 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
456 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
457 channel != OMAP_DSS_CHANNEL_LCD3);
458 b = 1;
459 break;
460 default:
461 BUG();
462 return;
463 }
465 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
466 (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
467 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
469 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
470 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
471 dss.lcd_clk_source[ix] = clk_src;
472 }
474 enum omap_dss_clk_source dss_get_dispc_clk_source(void)
475 {
476 return dss.dispc_clk_source;
477 }
479 enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
480 {
481 return dss.dsi_clk_source[dsi_module];
482 }
484 enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
485 {
486 if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
487 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
488 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
489 return dss.lcd_clk_source[ix];
490 } else {
491 /* LCD_CLK source is the same as DISPC_FCLK source for
492 * OMAP2 and OMAP3 */
493 return dss.dispc_clk_source;
494 }
495 }
497 bool dss_div_calc(unsigned long pck, unsigned long fck_min,
498 dss_div_calc_func func, void *data)
499 {
500 int fckd, fckd_start, fckd_stop;
501 unsigned long fck;
502 unsigned long fck_hw_max;
503 unsigned long fckd_hw_max;
504 unsigned long prate;
505 unsigned m;
507 fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
509 if (dss.parent_clk == NULL) {
510 unsigned pckd;
512 pckd = fck_hw_max / pck;
514 fck = pck * pckd;
516 fck = clk_round_rate(dss.dss_clk, fck);
518 return func(fck, data);
519 }
521 fckd_hw_max = dss.feat->fck_div_max;
523 m = dss.feat->dss_fck_multiplier;
524 prate = clk_get_rate(dss.parent_clk);
526 fck_min = fck_min ? fck_min : 1;
528 fckd_start = min(prate * m / fck_min, fckd_hw_max);
529 fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
531 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
532 fck = DIV_ROUND_UP(prate, fckd) * m;
534 if (func(fck, data))
535 return true;
536 }
538 return false;
539 }
541 int dss_set_fck_rate(unsigned long rate)
542 {
543 int r;
545 DSSDBG("set fck to %lu\n", rate);
547 r = clk_set_rate(dss.dss_clk, rate);
548 if (r)
549 return r;
551 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
553 WARN_ONCE(dss.dss_clk_rate != rate,
554 "clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
555 rate);
557 return 0;
558 }
560 unsigned long dss_get_dispc_clk_rate(void)
561 {
562 return dss.dss_clk_rate;
563 }
565 static int dss_setup_default_clock(void)
566 {
567 unsigned long max_dss_fck, prate;
568 unsigned long fck;
569 unsigned fck_div;
570 int r;
572 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
574 if (dss.parent_clk == NULL) {
575 fck = clk_round_rate(dss.dss_clk, max_dss_fck);
576 } else {
577 prate = clk_get_rate(dss.parent_clk);
579 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
580 max_dss_fck);
581 fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
582 }
584 r = dss_set_fck_rate(fck);
585 if (r)
586 return r;
588 return 0;
589 }
591 void dss_set_venc_output(enum omap_dss_venc_type type)
592 {
593 int l = 0;
595 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
596 l = 0;
597 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
598 l = 1;
599 else
600 BUG();
602 /* venc out selection. 0 = comp, 1 = svideo */
603 REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
604 }
606 void dss_set_dac_pwrdn_bgz(bool enable)
607 {
608 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
609 }
611 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
612 {
613 enum omap_display_type dp;
614 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
616 /* Complain about invalid selections */
617 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
618 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
620 /* Select only if we have options */
621 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
622 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
623 }
625 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
626 {
627 enum omap_display_type displays;
629 displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
630 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
631 return DSS_VENC_TV_CLK;
633 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
634 return DSS_HDMI_M_PCLK;
636 return REG_GET(DSS_CONTROL, 15, 15);
637 }
639 static int dss_dpi_select_source_omap2_omap3(int id, enum omap_channel channel)
640 {
641 if (channel != OMAP_DSS_CHANNEL_LCD)
642 return -EINVAL;
644 return 0;
645 }
647 static int dss_dpi_select_source_omap4(int id, enum omap_channel channel)
648 {
649 int val;
651 switch (channel) {
652 case OMAP_DSS_CHANNEL_LCD2:
653 val = 0;
654 break;
655 case OMAP_DSS_CHANNEL_DIGIT:
656 val = 1;
657 break;
658 default:
659 return -EINVAL;
660 }
662 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
664 return 0;
665 }
667 static int dss_dpi_select_source_omap5(int id, enum omap_channel channel)
668 {
669 int val;
671 switch (channel) {
672 case OMAP_DSS_CHANNEL_LCD:
673 val = 1;
674 break;
675 case OMAP_DSS_CHANNEL_LCD2:
676 val = 2;
677 break;
678 case OMAP_DSS_CHANNEL_LCD3:
679 val = 3;
680 break;
681 case OMAP_DSS_CHANNEL_DIGIT:
682 val = 0;
683 break;
684 default:
685 return -EINVAL;
686 }
688 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
690 return 0;
691 }
693 static int dss_dpi_select_source_dra7xx(int id, enum omap_channel channel)
694 {
695 switch (id) {
696 case 0:
697 return dss_dpi_select_source_omap5(id, channel);
698 case 1:
699 if (channel != OMAP_DSS_CHANNEL_LCD2)
700 return -EINVAL;
701 break;
702 case 2:
703 if (channel != OMAP_DSS_CHANNEL_LCD3)
704 return -EINVAL;
705 break;
706 default:
707 return -EINVAL;
708 }
710 return 0;
711 }
713 int dss_dpi_select_source(int id, enum omap_channel channel)
714 {
715 return dss.feat->dpi_select_source(id, channel);
716 }
718 static int dss_get_clocks(void)
719 {
720 struct clk *clk;
722 clk = devm_clk_get(&dss.pdev->dev, "fck");
723 if (IS_ERR(clk)) {
724 DSSERR("can't get clock fck\n");
725 return PTR_ERR(clk);
726 }
728 dss.dss_clk = clk;
730 if (dss.feat->parent_clk_name) {
731 clk = clk_get(NULL, dss.feat->parent_clk_name);
732 if (IS_ERR(clk)) {
733 DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
734 return PTR_ERR(clk);
735 }
736 } else {
737 clk = NULL;
738 }
740 dss.parent_clk = clk;
742 return 0;
743 }
745 static void dss_put_clocks(void)
746 {
747 if (dss.parent_clk)
748 clk_put(dss.parent_clk);
749 }
751 int dss_runtime_get(void)
752 {
753 int r;
755 DSSDBG("dss_runtime_get\n");
757 r = pm_runtime_get_sync(&dss.pdev->dev);
758 WARN_ON(r < 0);
759 return r < 0 ? r : 0;
760 }
762 void dss_runtime_put(void)
763 {
764 int r;
766 DSSDBG("dss_runtime_put\n");
768 r = pm_runtime_put_sync(&dss.pdev->dev);
769 WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
770 }
772 /* DEBUGFS */
773 #if defined(CONFIG_OMAP2_DSS_DEBUGFS)
774 void dss_debug_dump_clocks(struct seq_file *s)
775 {
776 dss_dump_clocks(s);
777 dispc_dump_clocks(s);
778 #ifdef CONFIG_OMAP2_DSS_DSI
779 dsi_dump_clocks(s);
780 #endif
781 }
782 #endif
785 static enum omap_display_type omap2plus_ports[] = {
786 OMAP_DISPLAY_TYPE_DPI,
787 };
789 static enum omap_display_type omap34xx_ports[] = {
790 OMAP_DISPLAY_TYPE_DPI,
791 OMAP_DISPLAY_TYPE_SDI,
792 };
794 static enum omap_display_type dra7xx_ports[] = {
795 OMAP_DISPLAY_TYPE_DPI,
796 OMAP_DISPLAY_TYPE_DPI,
797 OMAP_DISPLAY_TYPE_DPI,
798 };
800 static const struct dss_features omap24xx_dss_feats __initconst = {
801 /*
802 * fck div max is really 16, but the divider range has gaps. The range
803 * from 1 to 6 has no gaps, so let's use that as a max.
804 */
805 .fck_div_max = 6,
806 .dss_fck_multiplier = 2,
807 .parent_clk_name = "core_ck",
808 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
809 .ports = omap2plus_ports,
810 .num_ports = ARRAY_SIZE(omap2plus_ports),
811 .pll_ext_ctrl = false,
812 };
814 static const struct dss_features omap34xx_dss_feats __initconst = {
815 .fck_div_max = 16,
816 .dss_fck_multiplier = 2,
817 .parent_clk_name = "dpll4_ck",
818 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
819 .ports = omap34xx_ports,
820 .num_ports = ARRAY_SIZE(omap34xx_ports),
821 .pll_ext_ctrl = false,
822 .video1_pll = false,
823 .video2_pll = false,
824 };
826 static const struct dss_features omap3630_dss_feats __initconst = {
827 .fck_div_max = 32,
828 .dss_fck_multiplier = 1,
829 .parent_clk_name = "dpll4_ck",
830 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
831 .ports = omap2plus_ports,
832 .num_ports = ARRAY_SIZE(omap2plus_ports),
833 .pll_ext_ctrl = false,
834 .video1_pll = false,
835 .video2_pll = false,
836 };
838 static const struct dss_features omap44xx_dss_feats __initconst = {
839 .fck_div_max = 32,
840 .dss_fck_multiplier = 1,
841 .parent_clk_name = "dpll_per_x2_ck",
842 .dpi_select_source = &dss_dpi_select_source_omap4,
843 .ports = omap2plus_ports,
844 .num_ports = ARRAY_SIZE(omap2plus_ports),
845 .pll_ext_ctrl = false,
846 .video1_pll = false,
847 .video2_pll = false,
848 };
850 static const struct dss_features omap54xx_dss_feats __initconst = {
851 .fck_div_max = 64,
852 .dss_fck_multiplier = 1,
853 .parent_clk_name = "dpll_per_x2_ck",
854 .dpi_select_source = &dss_dpi_select_source_omap5,
855 .ports = omap2plus_ports,
856 .num_ports = ARRAY_SIZE(omap2plus_ports),
857 .pll_ext_ctrl = false,
858 .video1_pll = false,
859 .video2_pll = false,
860 };
862 static const struct dss_features am43xx_dss_feats __initconst = {
863 .fck_div_max = 0,
864 .dss_fck_multiplier = 0,
865 .parent_clk_name = NULL,
866 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
867 .ports = omap2plus_ports,
868 .num_ports = ARRAY_SIZE(omap2plus_ports),
869 .pll_ext_ctrl = false,
870 .video1_pll = false,
871 .video2_pll = false,
872 };
874 static const struct dss_features dra74x_dss_feats __initconst = {
875 .fck_div_max = 64,
876 .dss_fck_multiplier = 1,
877 .parent_clk_name = "dpll_per_x2_ck",
878 .dpi_select_source = &dss_dpi_select_source_dra7xx,
879 .ports = dra7xx_ports,
880 .num_ports = ARRAY_SIZE(dra7xx_ports),
881 .pll_ext_ctrl = true,
882 .video1_pll = true,
883 .video2_pll = true,
884 };
886 static const struct dss_features dra72x_dss_feats __initconst = {
887 .fck_div_max = 64,
888 .dss_fck_multiplier = 1,
889 .parent_clk_name = "dpll_per_x2_ck",
890 .dpi_select_source = &dss_dpi_select_source_dra7xx,
891 .ports = dra7xx_ports,
892 .num_ports = ARRAY_SIZE(dra7xx_ports),
893 .pll_ext_ctrl = true,
894 .video1_pll = true,
895 .video2_pll = false,
896 };
898 static int __init dss_init_features(struct platform_device *pdev)
899 {
900 const struct dss_features *src;
901 struct dss_features *dst;
903 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
904 if (!dst) {
905 dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
906 return -ENOMEM;
907 }
909 switch (omapdss_get_version()) {
910 case OMAPDSS_VER_OMAP24xx:
911 src = &omap24xx_dss_feats;
912 break;
914 case OMAPDSS_VER_OMAP34xx_ES1:
915 case OMAPDSS_VER_OMAP34xx_ES3:
916 case OMAPDSS_VER_AM35xx:
917 src = &omap34xx_dss_feats;
918 break;
920 case OMAPDSS_VER_OMAP3630:
921 src = &omap3630_dss_feats;
922 break;
924 case OMAPDSS_VER_OMAP4430_ES1:
925 case OMAPDSS_VER_OMAP4430_ES2:
926 case OMAPDSS_VER_OMAP4:
927 src = &omap44xx_dss_feats;
928 break;
930 case OMAPDSS_VER_OMAP5:
931 src = &omap54xx_dss_feats;
932 break;
934 case OMAPDSS_VER_AM43xx:
935 src = &am43xx_dss_feats;
936 break;
938 case OMAPDSS_VER_DRA74xx:
939 src = &dra74x_dss_feats;
940 break;
942 case OMAPDSS_VER_DRA72xx:
943 src = &dra72x_dss_feats;
944 break;
946 default:
947 return -ENODEV;
948 }
950 memcpy(dst, src, sizeof(*dst));
951 dss.feat = dst;
953 return 0;
954 }
956 static int __init dss_init_ports(struct platform_device *pdev)
957 {
958 struct device_node *parent = pdev->dev.of_node;
959 struct device_node *port;
960 int r;
962 if (parent == NULL)
963 return 0;
965 port = omapdss_of_get_next_port(parent, NULL);
966 if (!port)
967 return 0;
969 if (dss.feat->num_ports == 0)
970 return 0;
972 do {
973 enum omap_display_type port_type;
974 u32 reg;
976 r = of_property_read_u32(port, "reg", ®);
977 if (r)
978 reg = 0;
980 if (reg >= dss.feat->num_ports)
981 continue;
983 port_type = dss.feat->ports[reg];
985 switch (port_type) {
986 case OMAP_DISPLAY_TYPE_DPI:
987 dpi_init_port(pdev, port);
988 break;
989 case OMAP_DISPLAY_TYPE_SDI:
990 sdi_init_port(pdev, port);
991 break;
992 default:
993 break;
994 }
995 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
997 return 0;
998 }
1000 static void __exit dss_uninit_ports(struct platform_device *pdev)
1001 {
1002 struct device_node *parent = pdev->dev.of_node;
1003 struct device_node *port;
1004 int r;
1006 if (parent == NULL)
1007 return;
1009 port = omapdss_of_get_next_port(parent, NULL);
1010 if (!port)
1011 return;
1013 if (dss.feat->num_ports == 0)
1014 return;
1016 do {
1017 enum omap_display_type port_type;
1018 u32 reg;
1020 r = of_property_read_u32(port, "reg", ®);
1021 if (r)
1022 reg = 0;
1024 if (reg >= dss.feat->num_ports)
1025 continue;
1027 port_type = dss.feat->ports[reg];
1029 switch (port_type) {
1030 case OMAP_DISPLAY_TYPE_DPI:
1031 dpi_uninit_port(port);
1032 break;
1033 case OMAP_DISPLAY_TYPE_SDI:
1034 sdi_uninit_port(port);
1035 break;
1036 default:
1037 break;
1038 }
1039 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
1040 }
1042 /* DSS HW IP initialisation */
1043 static int __init omap_dsshw_probe(struct platform_device *pdev)
1044 {
1045 struct resource *dss_mem;
1046 struct device_node *np = pdev->dev.of_node;
1047 u32 rev;
1048 int r;
1050 dss.pdev = pdev;
1052 r = dss_init_features(dss.pdev);
1053 if (r)
1054 return r;
1056 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
1057 if (!dss_mem) {
1058 DSSERR("can't get IORESOURCE_MEM DSS\n");
1059 return -EINVAL;
1060 }
1062 dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
1063 resource_size(dss_mem));
1064 if (!dss.base) {
1065 DSSERR("can't ioremap DSS\n");
1066 return -ENOMEM;
1067 }
1069 r = dss_get_clocks();
1070 if (r)
1071 return r;
1073 r = dss_setup_default_clock();
1074 if (r)
1075 goto err_setup_clocks;
1077 pm_runtime_enable(&pdev->dev);
1078 pm_runtime_irq_safe(&pdev->dev);
1080 r = dss_runtime_get();
1081 if (r)
1082 goto err_runtime_get;
1084 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
1086 /* Select DPLL */
1087 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
1089 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
1091 #ifdef CONFIG_OMAP2_DSS_VENC
1092 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
1093 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
1094 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
1095 #endif
1096 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
1097 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
1098 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
1099 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
1100 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
1102 dss_init_ports(pdev);
1104 if (dss.feat->pll_ext_ctrl) {
1105 dss.syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
1106 if (!dss.syscon) {
1107 dev_err(&pdev->dev, "failed to get regmap\n");
1108 return -ENODEV;
1109 }
1110 }
1112 if (dss.feat->video1_pll) {
1113 r = dss_dpll_init(pdev, 0);
1114 if (r)
1115 goto err_runtime_get;
1116 }
1118 if (dss.feat->video2_pll) {
1119 r = dss_dpll_init(pdev, 1);
1120 if (r)
1121 goto err_runtime_get;
1122 }
1124 rev = dss_read_reg(DSS_REVISION);
1125 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
1126 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1128 dss_runtime_put();
1130 dss_debugfs_create_file("dss", dss_dump_regs);
1132 return 0;
1134 err_runtime_get:
1135 pm_runtime_disable(&pdev->dev);
1136 err_setup_clocks:
1137 dss_put_clocks();
1138 return r;
1139 }
1141 static int __exit omap_dsshw_remove(struct platform_device *pdev)
1142 {
1143 dss_uninit_ports(pdev);
1145 pm_runtime_disable(&pdev->dev);
1147 dss_put_clocks();
1149 return 0;
1150 }
1152 static int dss_runtime_suspend(struct device *dev)
1153 {
1154 dss_save_context();
1155 dss_set_min_bus_tput(dev, 0);
1157 pinctrl_pm_select_sleep_state(dev);
1159 return 0;
1160 }
1162 static int dss_runtime_resume(struct device *dev)
1163 {
1164 int r;
1166 pinctrl_pm_select_default_state(dev);
1168 /*
1169 * Set an arbitrarily high tput request to ensure OPP100.
1170 * What we should really do is to make a request to stay in OPP100,
1171 * without any tput requirements, but that is not currently possible
1172 * via the PM layer.
1173 */
1175 r = dss_set_min_bus_tput(dev, 1000000000);
1176 if (r)
1177 return r;
1179 dss_restore_context();
1180 return 0;
1181 }
1183 static const struct dev_pm_ops dss_pm_ops = {
1184 .runtime_suspend = dss_runtime_suspend,
1185 .runtime_resume = dss_runtime_resume,
1186 };
1188 static const struct of_device_id dss_of_match[] = {
1189 { .compatible = "ti,omap2-dss", },
1190 { .compatible = "ti,omap3-dss", },
1191 { .compatible = "ti,omap4-dss", },
1192 { .compatible = "ti,omap5-dss", },
1193 { .compatible = "ti,dra7-dss", },
1194 {},
1195 };
1197 MODULE_DEVICE_TABLE(of, dss_of_match);
1199 static struct platform_driver omap_dsshw_driver = {
1200 .remove = __exit_p(omap_dsshw_remove),
1201 .driver = {
1202 .name = "omapdss_dss",
1203 .owner = THIS_MODULE,
1204 .pm = &dss_pm_ops,
1205 .of_match_table = dss_of_match,
1206 },
1207 };
1209 int __init dss_init_platform_driver(void)
1210 {
1211 return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
1212 }
1214 void dss_uninit_platform_driver(void)
1215 {
1216 platform_driver_unregister(&omap_dsshw_driver);
1217 }