1 // SPDX-License-Identifier: GPL-2.0-only
3 * OMAP2plus display device setup / initialization.
5 * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
6 * Senthilvadivu Guruswamy
10 #include <linux/string.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/platform_device.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
17 #include <linux/delay.h>
19 #include <linux/of_platform.h>
20 #include <linux/slab.h>
21 #include <linux/mfd/syscon.h>
22 #include <linux/regmap.h>
24 #include <linux/platform_data/omapdss.h>
25 #include "omap_hwmod.h"
26 #include "omap_device.h"
35 #define DISPC_CONTROL 0x0040
36 #define DISPC_CONTROL2 0x0238
37 #define DISPC_CONTROL3 0x0848
38 #define DISPC_IRQSTATUS 0x0018
40 #define DSS_CONTROL 0x40
41 #define DSS_SDI_CONTROL 0x44
42 #define DSS_PLL_CONTROL 0x48
44 #define LCD_EN_MASK (0x1 << 0)
45 #define DIGIT_EN_MASK (0x1 << 1)
47 #define FRAMEDONE_IRQ_SHIFT 0
48 #define EVSYNC_EVEN_IRQ_SHIFT 2
49 #define EVSYNC_ODD_IRQ_SHIFT 3
50 #define FRAMEDONE2_IRQ_SHIFT 22
51 #define FRAMEDONE3_IRQ_SHIFT 30
52 #define FRAMEDONETV_IRQ_SHIFT 24
55 * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
56 * reset before deciding that something has gone wrong
58 #define FRAMEDONE_IRQ_TIMEOUT 100
60 #if defined(CONFIG_FB_OMAP2)
61 static struct platform_device omap_display_device
= {
65 .platform_data
= NULL
,
69 #define OMAP4_DSIPHY_SYSCON_OFFSET 0x78
71 static struct regmap
*omap4_dsi_mux_syscon
;
73 static int omap4_dsi_mux_pads(int dsi_id
, unsigned lanes
)
75 u32 enable_mask
, enable_shift
;
76 u32 pipd_mask
, pipd_shift
;
81 enable_mask
= OMAP4_DSI1_LANEENABLE_MASK
;
82 enable_shift
= OMAP4_DSI1_LANEENABLE_SHIFT
;
83 pipd_mask
= OMAP4_DSI1_PIPD_MASK
;
84 pipd_shift
= OMAP4_DSI1_PIPD_SHIFT
;
85 } else if (dsi_id
== 1) {
86 enable_mask
= OMAP4_DSI2_LANEENABLE_MASK
;
87 enable_shift
= OMAP4_DSI2_LANEENABLE_SHIFT
;
88 pipd_mask
= OMAP4_DSI2_PIPD_MASK
;
89 pipd_shift
= OMAP4_DSI2_PIPD_SHIFT
;
94 ret
= regmap_read(omap4_dsi_mux_syscon
,
95 OMAP4_DSIPHY_SYSCON_OFFSET
,
103 reg
|= (lanes
<< enable_shift
) & enable_mask
;
104 reg
|= (lanes
<< pipd_shift
) & pipd_mask
;
106 regmap_write(omap4_dsi_mux_syscon
, OMAP4_DSIPHY_SYSCON_OFFSET
, reg
);
111 static int omap_dsi_enable_pads(int dsi_id
, unsigned lane_mask
)
113 if (cpu_is_omap44xx())
114 return omap4_dsi_mux_pads(dsi_id
, lane_mask
);
119 static void omap_dsi_disable_pads(int dsi_id
, unsigned lane_mask
)
121 if (cpu_is_omap44xx())
122 omap4_dsi_mux_pads(dsi_id
, 0);
125 static enum omapdss_version __init
omap_display_get_version(void)
127 if (cpu_is_omap24xx())
128 return OMAPDSS_VER_OMAP24xx
;
129 else if (cpu_is_omap3630())
130 return OMAPDSS_VER_OMAP3630
;
131 else if (cpu_is_omap34xx()) {
132 if (soc_is_am35xx()) {
133 return OMAPDSS_VER_AM35xx
;
135 if (omap_rev() < OMAP3430_REV_ES3_0
)
136 return OMAPDSS_VER_OMAP34xx_ES1
;
138 return OMAPDSS_VER_OMAP34xx_ES3
;
140 } else if (omap_rev() == OMAP4430_REV_ES1_0
)
141 return OMAPDSS_VER_OMAP4430_ES1
;
142 else if (omap_rev() == OMAP4430_REV_ES2_0
||
143 omap_rev() == OMAP4430_REV_ES2_1
||
144 omap_rev() == OMAP4430_REV_ES2_2
)
145 return OMAPDSS_VER_OMAP4430_ES2
;
146 else if (cpu_is_omap44xx())
147 return OMAPDSS_VER_OMAP4
;
148 else if (soc_is_omap54xx())
149 return OMAPDSS_VER_OMAP5
;
150 else if (soc_is_am43xx())
151 return OMAPDSS_VER_AM43xx
;
152 else if (soc_is_dra7xx())
153 return OMAPDSS_VER_DRA7xx
;
155 return OMAPDSS_VER_UNKNOWN
;
158 static int __init
omapdss_init_fbdev(void)
160 static struct omap_dss_board_info board_data
= {
161 .dsi_enable_pads
= omap_dsi_enable_pads
,
162 .dsi_disable_pads
= omap_dsi_disable_pads
,
164 struct device_node
*node
;
167 board_data
.version
= omap_display_get_version();
168 if (board_data
.version
== OMAPDSS_VER_UNKNOWN
) {
169 pr_err("DSS not supported on this SoC\n");
173 omap_display_device
.dev
.platform_data
= &board_data
;
175 r
= platform_device_register(&omap_display_device
);
177 pr_err("Unable to register omapdss device\n");
181 /* create vrfb device */
182 r
= omap_init_vrfb();
184 pr_err("Unable to register omapvrfb device\n");
188 /* create FB device */
191 pr_err("Unable to register omapfb device\n");
195 /* create V4L2 display device */
196 r
= omap_init_vout();
198 pr_err("Unable to register omap_vout device\n");
202 /* add DSI info for omap4 */
203 node
= of_find_node_by_name(NULL
, "omap4_padconf_global");
205 omap4_dsi_mux_syscon
= syscon_node_to_regmap(node
);
211 static const char * const omapdss_compat_names
[] __initconst
= {
219 static struct device_node
* __init
omapdss_find_dss_of_node(void)
221 struct device_node
*node
;
224 for (i
= 0; i
< ARRAY_SIZE(omapdss_compat_names
); ++i
) {
225 node
= of_find_compatible_node(NULL
, NULL
,
226 omapdss_compat_names
[i
]);
234 static int __init
omapdss_init_of(void)
237 struct device_node
*node
;
238 struct platform_device
*pdev
;
240 /* only create dss helper devices if dss is enabled in the .dts */
242 node
= omapdss_find_dss_of_node();
246 if (!of_device_is_available(node
)) {
251 pdev
= of_find_device_by_node(node
);
254 pr_err("Unable to find DSS platform device\n");
259 r
= of_platform_populate(node
, NULL
, NULL
, &pdev
->dev
);
260 put_device(&pdev
->dev
);
263 pr_err("Unable to populate DSS submodule devices\n");
267 return omapdss_init_fbdev();
269 omap_device_initcall(omapdss_init_of
);
270 #endif /* CONFIG_FB_OMAP2 */
272 static void dispc_disable_outputs(void)
275 bool lcd_en
, digit_en
, lcd2_en
= false, lcd3_en
= false;
277 struct omap_dss_dispc_dev_attr
*da
;
278 struct omap_hwmod
*oh
;
280 oh
= omap_hwmod_lookup("dss_dispc");
282 WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
287 pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
291 da
= (struct omap_dss_dispc_dev_attr
*)oh
->dev_attr
;
293 /* store value of LCDENABLE and DIGITENABLE bits */
294 v
= omap_hwmod_read(oh
, DISPC_CONTROL
);
295 lcd_en
= v
& LCD_EN_MASK
;
296 digit_en
= v
& DIGIT_EN_MASK
;
298 /* store value of LCDENABLE for LCD2 */
299 if (da
->manager_count
> 2) {
300 v
= omap_hwmod_read(oh
, DISPC_CONTROL2
);
301 lcd2_en
= v
& LCD_EN_MASK
;
304 /* store value of LCDENABLE for LCD3 */
305 if (da
->manager_count
> 3) {
306 v
= omap_hwmod_read(oh
, DISPC_CONTROL3
);
307 lcd3_en
= v
& LCD_EN_MASK
;
310 if (!(lcd_en
| digit_en
| lcd2_en
| lcd3_en
))
311 return; /* no managers currently enabled */
314 * If any manager was enabled, we need to disable it before
315 * DSS clocks are disabled or DISPC module is reset
318 irq_mask
|= 1 << FRAMEDONE_IRQ_SHIFT
;
321 if (da
->has_framedonetv_irq
) {
322 irq_mask
|= 1 << FRAMEDONETV_IRQ_SHIFT
;
324 irq_mask
|= 1 << EVSYNC_EVEN_IRQ_SHIFT
|
325 1 << EVSYNC_ODD_IRQ_SHIFT
;
330 irq_mask
|= 1 << FRAMEDONE2_IRQ_SHIFT
;
332 irq_mask
|= 1 << FRAMEDONE3_IRQ_SHIFT
;
335 * clear any previous FRAMEDONE, FRAMEDONETV,
336 * EVSYNC_EVEN/ODD, FRAMEDONE2 or FRAMEDONE3 interrupts
338 omap_hwmod_write(irq_mask
, oh
, DISPC_IRQSTATUS
);
340 /* disable LCD and TV managers */
341 v
= omap_hwmod_read(oh
, DISPC_CONTROL
);
342 v
&= ~(LCD_EN_MASK
| DIGIT_EN_MASK
);
343 omap_hwmod_write(v
, oh
, DISPC_CONTROL
);
345 /* disable LCD2 manager */
346 if (da
->manager_count
> 2) {
347 v
= omap_hwmod_read(oh
, DISPC_CONTROL2
);
349 omap_hwmod_write(v
, oh
, DISPC_CONTROL2
);
352 /* disable LCD3 manager */
353 if (da
->manager_count
> 3) {
354 v
= omap_hwmod_read(oh
, DISPC_CONTROL3
);
356 omap_hwmod_write(v
, oh
, DISPC_CONTROL3
);
360 while ((omap_hwmod_read(oh
, DISPC_IRQSTATUS
) & irq_mask
) !=
363 if (i
> FRAMEDONE_IRQ_TIMEOUT
) {
364 pr_err("didn't get FRAMEDONE1/2/3 or TV interrupt\n");
371 int omap_dss_reset(struct omap_hwmod
*oh
)
373 struct omap_hwmod_opt_clk
*oc
;
377 if (!(oh
->class->sysc
->sysc_flags
& SYSS_HAS_RESET_STATUS
)) {
378 pr_err("dss_core: hwmod data doesn't contain reset data\n");
382 for (i
= oh
->opt_clks_cnt
, oc
= oh
->opt_clks
; i
> 0; i
--, oc
++)
383 clk_prepare_enable(oc
->_clk
);
385 dispc_disable_outputs();
387 /* clear SDI registers */
388 if (cpu_is_omap3430()) {
389 omap_hwmod_write(0x0, oh
, DSS_SDI_CONTROL
);
390 omap_hwmod_write(0x0, oh
, DSS_PLL_CONTROL
);
394 * clear DSS_CONTROL register to switch DSS clock sources to
397 omap_hwmod_write(0x0, oh
, DSS_CONTROL
);
399 omap_test_timeout((omap_hwmod_read(oh
, oh
->class->sysc
->syss_offs
)
400 & SYSS_RESETDONE_MASK
),
401 MAX_MODULE_SOFTRESET_WAIT
, c
);
403 if (c
== MAX_MODULE_SOFTRESET_WAIT
)
404 pr_warn("dss_core: waiting for reset to finish failed\n");
406 pr_debug("dss_core: softreset done\n");
408 for (i
= oh
->opt_clks_cnt
, oc
= oh
->opt_clks
; i
> 0; i
--, oc
++)
409 clk_disable_unprepare(oc
->_clk
);
411 r
= (c
== MAX_MODULE_SOFTRESET_WAIT
) ? -ETIMEDOUT
: 0;