2 * linux/drivers/video/omap2/dss/dss.c
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 * Some code and ideas taken from drivers/video/omap/ driver
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.
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
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/>.
23 #define DSS_SUBSYS_NAME "DSS"
25 #include <linux/kernel.h>
27 #include <linux/export.h>
28 #include <linux/err.h>
29 #include <linux/delay.h>
30 #include <linux/seq_file.h>
31 #include <linux/clk.h>
32 #include <linux/platform_device.h>
33 #include <linux/pm_runtime.h>
34 #include <linux/gfp.h>
35 #include <linux/sizes.h>
37 #include <video/omapdss.h>
40 #include "dss_features.h"
42 #define DSS_SZ_REGS SZ_512
48 #define DSS_REG(idx) ((const struct dss_reg) { idx })
50 #define DSS_REVISION DSS_REG(0x0000)
51 #define DSS_SYSCONFIG DSS_REG(0x0010)
52 #define DSS_SYSSTATUS DSS_REG(0x0014)
53 #define DSS_CONTROL DSS_REG(0x0040)
54 #define DSS_SDI_CONTROL DSS_REG(0x0044)
55 #define DSS_PLL_CONTROL DSS_REG(0x0048)
56 #define DSS_SDI_STATUS DSS_REG(0x005C)
58 #define REG_GET(idx, start, end) \
59 FLD_GET(dss_read_reg(idx), start, end)
61 #define REG_FLD_MOD(idx, val, start, end) \
62 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
64 static int dss_runtime_get(void);
65 static void dss_runtime_put(void);
69 u8 dss_fck_multiplier
;
70 const char *parent_clk_name
;
71 int (*dpi_select_source
)(enum omap_channel channel
);
75 struct platform_device
*pdev
;
78 struct clk
*parent_clk
;
80 unsigned long dss_clk_rate
;
82 unsigned long cache_req_pck
;
83 unsigned long cache_prate
;
84 struct dispc_clock_info cache_dispc_cinfo
;
86 enum omap_dss_clk_source dsi_clk_source
[MAX_NUM_DSI
];
87 enum omap_dss_clk_source dispc_clk_source
;
88 enum omap_dss_clk_source lcd_clk_source
[MAX_DSS_LCD_MANAGERS
];
91 u32 ctx
[DSS_SZ_REGS
/ sizeof(u32
)];
93 const struct dss_features
*feat
;
96 static const char * const dss_generic_clk_source_names
[] = {
97 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
] = "DSI_PLL_HSDIV_DISPC",
98 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
] = "DSI_PLL_HSDIV_DSI",
99 [OMAP_DSS_CLK_SRC_FCK
] = "DSS_FCK",
100 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
] = "DSI_PLL2_HSDIV_DISPC",
101 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI
] = "DSI_PLL2_HSDIV_DSI",
104 static inline void dss_write_reg(const struct dss_reg idx
, u32 val
)
106 __raw_writel(val
, dss
.base
+ idx
.idx
);
109 static inline u32
dss_read_reg(const struct dss_reg idx
)
111 return __raw_readl(dss
.base
+ idx
.idx
);
115 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
117 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
119 static void dss_save_context(void)
121 DSSDBG("dss_save_context\n");
125 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD
) &
126 OMAP_DISPLAY_TYPE_SDI
) {
131 dss
.ctx_valid
= true;
133 DSSDBG("context saved\n");
136 static void dss_restore_context(void)
138 DSSDBG("dss_restore_context\n");
145 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD
) &
146 OMAP_DISPLAY_TYPE_SDI
) {
151 DSSDBG("context restored\n");
157 int dss_get_ctx_loss_count(void)
159 struct platform_device
*core_pdev
= dss_get_core_pdev();
160 struct omap_dss_board_info
*board_data
= core_pdev
->dev
.platform_data
;
163 if (!board_data
->get_context_loss_count
)
166 cnt
= board_data
->get_context_loss_count(&dss
.pdev
->dev
);
168 WARN_ONCE(cnt
< 0, "get_context_loss_count failed: %d\n", cnt
);
173 void dss_sdi_init(int datapairs
)
177 BUG_ON(datapairs
> 3 || datapairs
< 1);
179 l
= dss_read_reg(DSS_SDI_CONTROL
);
180 l
= FLD_MOD(l
, 0xf, 19, 15); /* SDI_PDIV */
181 l
= FLD_MOD(l
, datapairs
-1, 3, 2); /* SDI_PRSEL */
182 l
= FLD_MOD(l
, 2, 1, 0); /* SDI_BWSEL */
183 dss_write_reg(DSS_SDI_CONTROL
, l
);
185 l
= dss_read_reg(DSS_PLL_CONTROL
);
186 l
= FLD_MOD(l
, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
187 l
= FLD_MOD(l
, 0xb, 16, 11); /* SDI_PLL_REGN */
188 l
= FLD_MOD(l
, 0xb4, 10, 1); /* SDI_PLL_REGM */
189 dss_write_reg(DSS_PLL_CONTROL
, l
);
192 int dss_sdi_enable(void)
194 unsigned long timeout
;
196 dispc_pck_free_enable(1);
199 REG_FLD_MOD(DSS_PLL_CONTROL
, 1, 18, 18); /* SDI_PLL_SYSRESET */
200 udelay(1); /* wait 2x PCLK */
203 REG_FLD_MOD(DSS_PLL_CONTROL
, 1, 28, 28); /* SDI_PLL_GOBIT */
205 /* Waiting for PLL lock request to complete */
206 timeout
= jiffies
+ msecs_to_jiffies(500);
207 while (dss_read_reg(DSS_SDI_STATUS
) & (1 << 6)) {
208 if (time_after_eq(jiffies
, timeout
)) {
209 DSSERR("PLL lock request timed out\n");
214 /* Clearing PLL_GO bit */
215 REG_FLD_MOD(DSS_PLL_CONTROL
, 0, 28, 28);
217 /* Waiting for PLL to lock */
218 timeout
= jiffies
+ msecs_to_jiffies(500);
219 while (!(dss_read_reg(DSS_SDI_STATUS
) & (1 << 5))) {
220 if (time_after_eq(jiffies
, timeout
)) {
221 DSSERR("PLL lock timed out\n");
226 dispc_lcd_enable_signal(1);
228 /* Waiting for SDI reset to complete */
229 timeout
= jiffies
+ msecs_to_jiffies(500);
230 while (!(dss_read_reg(DSS_SDI_STATUS
) & (1 << 2))) {
231 if (time_after_eq(jiffies
, timeout
)) {
232 DSSERR("SDI reset timed out\n");
240 dispc_lcd_enable_signal(0);
243 REG_FLD_MOD(DSS_PLL_CONTROL
, 0, 18, 18); /* SDI_PLL_SYSRESET */
245 dispc_pck_free_enable(0);
250 void dss_sdi_disable(void)
252 dispc_lcd_enable_signal(0);
254 dispc_pck_free_enable(0);
257 REG_FLD_MOD(DSS_PLL_CONTROL
, 0, 18, 18); /* SDI_PLL_SYSRESET */
260 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src
)
262 return dss_generic_clk_source_names
[clk_src
];
265 void dss_dump_clocks(struct seq_file
*s
)
267 const char *fclk_name
, *fclk_real_name
;
268 unsigned long fclk_rate
;
270 if (dss_runtime_get())
273 seq_printf(s
, "- DSS -\n");
275 fclk_name
= dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK
);
276 fclk_real_name
= dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK
);
277 fclk_rate
= clk_get_rate(dss
.dss_clk
);
279 seq_printf(s
, "%s (%s) = %lu\n",
280 fclk_name
, fclk_real_name
,
286 static void dss_dump_regs(struct seq_file
*s
)
288 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
290 if (dss_runtime_get())
293 DUMPREG(DSS_REVISION
);
294 DUMPREG(DSS_SYSCONFIG
);
295 DUMPREG(DSS_SYSSTATUS
);
296 DUMPREG(DSS_CONTROL
);
298 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD
) &
299 OMAP_DISPLAY_TYPE_SDI
) {
300 DUMPREG(DSS_SDI_CONTROL
);
301 DUMPREG(DSS_PLL_CONTROL
);
302 DUMPREG(DSS_SDI_STATUS
);
309 static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src
)
311 struct platform_device
*dsidev
;
316 case OMAP_DSS_CLK_SRC_FCK
:
319 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
321 dsidev
= dsi_get_dsidev_from_id(0);
322 dsi_wait_pll_hsdiv_dispc_active(dsidev
);
324 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
:
326 dsidev
= dsi_get_dsidev_from_id(1);
327 dsi_wait_pll_hsdiv_dispc_active(dsidev
);
334 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH
, &start
, &end
);
336 REG_FLD_MOD(DSS_CONTROL
, b
, start
, end
); /* DISPC_CLK_SWITCH */
338 dss
.dispc_clk_source
= clk_src
;
341 void dss_select_dsi_clk_source(int dsi_module
,
342 enum omap_dss_clk_source clk_src
)
344 struct platform_device
*dsidev
;
348 case OMAP_DSS_CLK_SRC_FCK
:
351 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
:
352 BUG_ON(dsi_module
!= 0);
354 dsidev
= dsi_get_dsidev_from_id(0);
355 dsi_wait_pll_hsdiv_dsi_active(dsidev
);
357 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI
:
358 BUG_ON(dsi_module
!= 1);
360 dsidev
= dsi_get_dsidev_from_id(1);
361 dsi_wait_pll_hsdiv_dsi_active(dsidev
);
368 pos
= dsi_module
== 0 ? 1 : 10;
369 REG_FLD_MOD(DSS_CONTROL
, b
, pos
, pos
); /* DSIx_CLK_SWITCH */
371 dss
.dsi_clk_source
[dsi_module
] = clk_src
;
374 void dss_select_lcd_clk_source(enum omap_channel channel
,
375 enum omap_dss_clk_source clk_src
)
377 struct platform_device
*dsidev
;
380 if (!dss_has_feature(FEAT_LCD_CLK_SRC
)) {
381 dss_select_dispc_clk_source(clk_src
);
386 case OMAP_DSS_CLK_SRC_FCK
:
389 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
390 BUG_ON(channel
!= OMAP_DSS_CHANNEL_LCD
);
392 dsidev
= dsi_get_dsidev_from_id(0);
393 dsi_wait_pll_hsdiv_dispc_active(dsidev
);
395 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
:
396 BUG_ON(channel
!= OMAP_DSS_CHANNEL_LCD2
&&
397 channel
!= OMAP_DSS_CHANNEL_LCD3
);
399 dsidev
= dsi_get_dsidev_from_id(1);
400 dsi_wait_pll_hsdiv_dispc_active(dsidev
);
407 pos
= channel
== OMAP_DSS_CHANNEL_LCD
? 0 :
408 (channel
== OMAP_DSS_CHANNEL_LCD2
? 12 : 19);
409 REG_FLD_MOD(DSS_CONTROL
, b
, pos
, pos
); /* LCDx_CLK_SWITCH */
411 ix
= channel
== OMAP_DSS_CHANNEL_LCD
? 0 :
412 (channel
== OMAP_DSS_CHANNEL_LCD2
? 1 : 2);
413 dss
.lcd_clk_source
[ix
] = clk_src
;
416 enum omap_dss_clk_source
dss_get_dispc_clk_source(void)
418 return dss
.dispc_clk_source
;
421 enum omap_dss_clk_source
dss_get_dsi_clk_source(int dsi_module
)
423 return dss
.dsi_clk_source
[dsi_module
];
426 enum omap_dss_clk_source
dss_get_lcd_clk_source(enum omap_channel channel
)
428 if (dss_has_feature(FEAT_LCD_CLK_SRC
)) {
429 int ix
= channel
== OMAP_DSS_CHANNEL_LCD
? 0 :
430 (channel
== OMAP_DSS_CHANNEL_LCD2
? 1 : 2);
431 return dss
.lcd_clk_source
[ix
];
433 /* LCD_CLK source is the same as DISPC_FCLK source for
435 return dss
.dispc_clk_source
;
439 bool dss_div_calc(unsigned long pck
, unsigned long fck_min
,
440 dss_div_calc_func func
, void *data
)
442 int fckd
, fckd_start
, fckd_stop
;
444 unsigned long fck_hw_max
;
445 unsigned long fckd_hw_max
;
449 fck_hw_max
= dss_feat_get_param_max(FEAT_PARAM_DSS_FCK
);
451 if (dss
.parent_clk
== NULL
) {
454 pckd
= fck_hw_max
/ pck
;
458 fck
= clk_round_rate(dss
.dss_clk
, fck
);
460 return func(fck
, data
);
463 fckd_hw_max
= dss
.feat
->fck_div_max
;
465 m
= dss
.feat
->dss_fck_multiplier
;
466 prate
= clk_get_rate(dss
.parent_clk
);
468 fck_min
= fck_min
? fck_min
: 1;
470 fckd_start
= min(prate
* m
/ fck_min
, fckd_hw_max
);
471 fckd_stop
= max(DIV_ROUND_UP(prate
* m
, fck_hw_max
), 1ul);
473 for (fckd
= fckd_start
; fckd
>= fckd_stop
; --fckd
) {
474 fck
= prate
/ fckd
* m
;
483 int dss_set_fck_rate(unsigned long rate
)
487 DSSDBG("set fck to %lu\n", rate
);
489 r
= clk_set_rate(dss
.dss_clk
, rate
);
493 dss
.dss_clk_rate
= clk_get_rate(dss
.dss_clk
);
495 WARN_ONCE(dss
.dss_clk_rate
!= rate
,
496 "clk rate mismatch: %lu != %lu", dss
.dss_clk_rate
,
502 unsigned long dss_get_dispc_clk_rate(void)
504 return dss
.dss_clk_rate
;
507 static int dss_setup_default_clock(void)
509 unsigned long max_dss_fck
, prate
;
514 max_dss_fck
= dss_feat_get_param_max(FEAT_PARAM_DSS_FCK
);
516 if (dss
.parent_clk
== NULL
) {
517 fck
= clk_round_rate(dss
.dss_clk
, max_dss_fck
);
519 prate
= clk_get_rate(dss
.parent_clk
);
521 fck_div
= DIV_ROUND_UP(prate
* dss
.feat
->dss_fck_multiplier
,
523 fck
= prate
/ fck_div
* dss
.feat
->dss_fck_multiplier
;
526 r
= dss_set_fck_rate(fck
);
533 void dss_set_venc_output(enum omap_dss_venc_type type
)
537 if (type
== OMAP_DSS_VENC_TYPE_COMPOSITE
)
539 else if (type
== OMAP_DSS_VENC_TYPE_SVIDEO
)
544 /* venc out selection. 0 = comp, 1 = svideo */
545 REG_FLD_MOD(DSS_CONTROL
, l
, 6, 6);
548 void dss_set_dac_pwrdn_bgz(bool enable
)
550 REG_FLD_MOD(DSS_CONTROL
, enable
, 5, 5); /* DAC Power-Down Control */
553 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src
)
555 enum omap_display_type dp
;
556 dp
= dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT
);
558 /* Complain about invalid selections */
559 WARN_ON((src
== DSS_VENC_TV_CLK
) && !(dp
& OMAP_DISPLAY_TYPE_VENC
));
560 WARN_ON((src
== DSS_HDMI_M_PCLK
) && !(dp
& OMAP_DISPLAY_TYPE_HDMI
));
562 /* Select only if we have options */
563 if ((dp
& OMAP_DISPLAY_TYPE_VENC
) && (dp
& OMAP_DISPLAY_TYPE_HDMI
))
564 REG_FLD_MOD(DSS_CONTROL
, src
, 15, 15); /* VENC_HDMI_SWITCH */
567 enum dss_hdmi_venc_clk_source_select
dss_get_hdmi_venc_clk_source(void)
569 enum omap_display_type displays
;
571 displays
= dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT
);
572 if ((displays
& OMAP_DISPLAY_TYPE_HDMI
) == 0)
573 return DSS_VENC_TV_CLK
;
575 if ((displays
& OMAP_DISPLAY_TYPE_VENC
) == 0)
576 return DSS_HDMI_M_PCLK
;
578 return REG_GET(DSS_CONTROL
, 15, 15);
581 static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel
)
583 if (channel
!= OMAP_DSS_CHANNEL_LCD
)
589 static int dss_dpi_select_source_omap4(enum omap_channel channel
)
594 case OMAP_DSS_CHANNEL_LCD2
:
597 case OMAP_DSS_CHANNEL_DIGIT
:
604 REG_FLD_MOD(DSS_CONTROL
, val
, 17, 17);
609 static int dss_dpi_select_source_omap5(enum omap_channel channel
)
614 case OMAP_DSS_CHANNEL_LCD
:
617 case OMAP_DSS_CHANNEL_LCD2
:
620 case OMAP_DSS_CHANNEL_LCD3
:
623 case OMAP_DSS_CHANNEL_DIGIT
:
630 REG_FLD_MOD(DSS_CONTROL
, val
, 17, 16);
635 int dss_dpi_select_source(enum omap_channel channel
)
637 return dss
.feat
->dpi_select_source(channel
);
640 static int dss_get_clocks(void)
644 clk
= devm_clk_get(&dss
.pdev
->dev
, "fck");
646 DSSERR("can't get clock fck\n");
652 if (dss
.feat
->parent_clk_name
) {
653 clk
= clk_get(NULL
, dss
.feat
->parent_clk_name
);
655 DSSERR("Failed to get %s\n", dss
.feat
->parent_clk_name
);
662 dss
.parent_clk
= clk
;
667 static void dss_put_clocks(void)
670 clk_put(dss
.parent_clk
);
673 static int dss_runtime_get(void)
677 DSSDBG("dss_runtime_get\n");
679 r
= pm_runtime_get_sync(&dss
.pdev
->dev
);
681 return r
< 0 ? r
: 0;
684 static void dss_runtime_put(void)
688 DSSDBG("dss_runtime_put\n");
690 r
= pm_runtime_put_sync(&dss
.pdev
->dev
);
691 WARN_ON(r
< 0 && r
!= -ENOSYS
&& r
!= -EBUSY
);
695 #if defined(CONFIG_OMAP2_DSS_DEBUGFS)
696 void dss_debug_dump_clocks(struct seq_file
*s
)
699 dispc_dump_clocks(s
);
700 #ifdef CONFIG_OMAP2_DSS_DSI
706 static const struct dss_features omap24xx_dss_feats __initconst
= {
708 * fck div max is really 16, but the divider range has gaps. The range
709 * from 1 to 6 has no gaps, so let's use that as a max.
712 .dss_fck_multiplier
= 2,
713 .parent_clk_name
= "core_ck",
714 .dpi_select_source
= &dss_dpi_select_source_omap2_omap3
,
717 static const struct dss_features omap34xx_dss_feats __initconst
= {
719 .dss_fck_multiplier
= 2,
720 .parent_clk_name
= "dpll4_ck",
721 .dpi_select_source
= &dss_dpi_select_source_omap2_omap3
,
724 static const struct dss_features omap3630_dss_feats __initconst
= {
726 .dss_fck_multiplier
= 1,
727 .parent_clk_name
= "dpll4_ck",
728 .dpi_select_source
= &dss_dpi_select_source_omap2_omap3
,
731 static const struct dss_features omap44xx_dss_feats __initconst
= {
733 .dss_fck_multiplier
= 1,
734 .parent_clk_name
= "dpll_per_x2_ck",
735 .dpi_select_source
= &dss_dpi_select_source_omap4
,
738 static const struct dss_features omap54xx_dss_feats __initconst
= {
740 .dss_fck_multiplier
= 1,
741 .parent_clk_name
= "dpll_per_x2_ck",
742 .dpi_select_source
= &dss_dpi_select_source_omap5
,
745 static int __init
dss_init_features(struct platform_device
*pdev
)
747 const struct dss_features
*src
;
748 struct dss_features
*dst
;
750 dst
= devm_kzalloc(&pdev
->dev
, sizeof(*dst
), GFP_KERNEL
);
752 dev_err(&pdev
->dev
, "Failed to allocate local DSS Features\n");
756 switch (omapdss_get_version()) {
757 case OMAPDSS_VER_OMAP24xx
:
758 src
= &omap24xx_dss_feats
;
761 case OMAPDSS_VER_OMAP34xx_ES1
:
762 case OMAPDSS_VER_OMAP34xx_ES3
:
763 case OMAPDSS_VER_AM35xx
:
764 src
= &omap34xx_dss_feats
;
767 case OMAPDSS_VER_OMAP3630
:
768 src
= &omap3630_dss_feats
;
771 case OMAPDSS_VER_OMAP4430_ES1
:
772 case OMAPDSS_VER_OMAP4430_ES2
:
773 case OMAPDSS_VER_OMAP4
:
774 src
= &omap44xx_dss_feats
;
777 case OMAPDSS_VER_OMAP5
:
778 src
= &omap54xx_dss_feats
;
785 memcpy(dst
, src
, sizeof(*dst
));
791 /* DSS HW IP initialisation */
792 static int __init
omap_dsshw_probe(struct platform_device
*pdev
)
794 struct resource
*dss_mem
;
800 r
= dss_init_features(dss
.pdev
);
804 dss_mem
= platform_get_resource(dss
.pdev
, IORESOURCE_MEM
, 0);
806 DSSERR("can't get IORESOURCE_MEM DSS\n");
810 dss
.base
= devm_ioremap(&pdev
->dev
, dss_mem
->start
,
811 resource_size(dss_mem
));
813 DSSERR("can't ioremap DSS\n");
817 r
= dss_get_clocks();
821 r
= dss_setup_default_clock();
823 goto err_setup_clocks
;
825 pm_runtime_enable(&pdev
->dev
);
827 r
= dss_runtime_get();
829 goto err_runtime_get
;
831 dss
.dss_clk_rate
= clk_get_rate(dss
.dss_clk
);
834 REG_FLD_MOD(DSS_CONTROL
, 0, 0, 0);
836 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK
);
838 #ifdef CONFIG_OMAP2_DSS_VENC
839 REG_FLD_MOD(DSS_CONTROL
, 1, 4, 4); /* venc dac demen */
840 REG_FLD_MOD(DSS_CONTROL
, 1, 3, 3); /* venc clock 4x enable */
841 REG_FLD_MOD(DSS_CONTROL
, 0, 2, 2); /* venc clock mode = normal */
843 dss
.dsi_clk_source
[0] = OMAP_DSS_CLK_SRC_FCK
;
844 dss
.dsi_clk_source
[1] = OMAP_DSS_CLK_SRC_FCK
;
845 dss
.dispc_clk_source
= OMAP_DSS_CLK_SRC_FCK
;
846 dss
.lcd_clk_source
[0] = OMAP_DSS_CLK_SRC_FCK
;
847 dss
.lcd_clk_source
[1] = OMAP_DSS_CLK_SRC_FCK
;
849 rev
= dss_read_reg(DSS_REVISION
);
850 printk(KERN_INFO
"OMAP DSS rev %d.%d\n",
851 FLD_GET(rev
, 7, 4), FLD_GET(rev
, 3, 0));
855 dss_debugfs_create_file("dss", dss_dump_regs
);
860 pm_runtime_disable(&pdev
->dev
);
866 static int __exit
omap_dsshw_remove(struct platform_device
*pdev
)
868 pm_runtime_disable(&pdev
->dev
);
875 static int dss_runtime_suspend(struct device
*dev
)
878 dss_set_min_bus_tput(dev
, 0);
882 static int dss_runtime_resume(struct device
*dev
)
886 * Set an arbitrarily high tput request to ensure OPP100.
887 * What we should really do is to make a request to stay in OPP100,
888 * without any tput requirements, but that is not currently possible
892 r
= dss_set_min_bus_tput(dev
, 1000000000);
896 dss_restore_context();
900 static const struct dev_pm_ops dss_pm_ops
= {
901 .runtime_suspend
= dss_runtime_suspend
,
902 .runtime_resume
= dss_runtime_resume
,
905 static struct platform_driver omap_dsshw_driver
= {
906 .remove
= __exit_p(omap_dsshw_remove
),
908 .name
= "omapdss_dss",
909 .owner
= THIS_MODULE
,
914 int __init
dss_init_platform_driver(void)
916 return platform_driver_probe(&omap_dsshw_driver
, omap_dsshw_probe
);
919 void dss_uninit_platform_driver(void)
921 platform_driver_unregister(&omap_dsshw_driver
);