GNU Linux-libre 6.7.9-gnu
[releases.git] / arch / arm / mach-omap2 / display.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * OMAP2plus display device setup / initialization.
4  *
5  * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
6  *      Senthilvadivu Guruswamy
7  *      Sumit Semwal
8  */
9
10 #include <linux/string.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/platform_device.h>
14 #include <linux/io.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
17 #include <linux/delay.h>
18 #include <linux/of.h>
19 #include <linux/of_platform.h>
20 #include <linux/slab.h>
21 #include <linux/mfd/syscon.h>
22 #include <linux/regmap.h>
23
24 #include <linux/platform_data/omapdss.h>
25 #include "omap_hwmod.h"
26 #include "omap_device.h"
27 #include "common.h"
28
29 #include "soc.h"
30 #include "iomap.h"
31 #include "control.h"
32 #include "display.h"
33 #include "prm.h"
34
35 #define DISPC_CONTROL           0x0040
36 #define DISPC_CONTROL2          0x0238
37 #define DISPC_CONTROL3          0x0848
38 #define DISPC_IRQSTATUS         0x0018
39
40 #define DSS_CONTROL             0x40
41 #define DSS_SDI_CONTROL         0x44
42 #define DSS_PLL_CONTROL         0x48
43
44 #define LCD_EN_MASK             (0x1 << 0)
45 #define DIGIT_EN_MASK           (0x1 << 1)
46
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
53
54 /*
55  * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
56  *     reset before deciding that something has gone wrong
57  */
58 #define FRAMEDONE_IRQ_TIMEOUT           100
59
60 #if defined(CONFIG_FB_OMAP2)
61 static struct platform_device omap_display_device = {
62         .name          = "omapdss",
63         .id            = -1,
64         .dev            = {
65                 .platform_data = NULL,
66         },
67 };
68
69 #define OMAP4_DSIPHY_SYSCON_OFFSET              0x78
70
71 static struct regmap *omap4_dsi_mux_syscon;
72
73 static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
74 {
75         u32 enable_mask, enable_shift;
76         u32 pipd_mask, pipd_shift;
77         u32 reg;
78         int ret;
79
80         if (dsi_id == 0) {
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;
90         } else {
91                 return -ENODEV;
92         }
93
94         ret = regmap_read(omap4_dsi_mux_syscon,
95                                           OMAP4_DSIPHY_SYSCON_OFFSET,
96                                           &reg);
97         if (ret)
98                 return ret;
99
100         reg &= ~enable_mask;
101         reg &= ~pipd_mask;
102
103         reg |= (lanes << enable_shift) & enable_mask;
104         reg |= (lanes << pipd_shift) & pipd_mask;
105
106         regmap_write(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, reg);
107
108         return 0;
109 }
110
111 static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
112 {
113         if (cpu_is_omap44xx())
114                 return omap4_dsi_mux_pads(dsi_id, lane_mask);
115
116         return 0;
117 }
118
119 static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
120 {
121         if (cpu_is_omap44xx())
122                 omap4_dsi_mux_pads(dsi_id, 0);
123 }
124
125 static enum omapdss_version __init omap_display_get_version(void)
126 {
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;
134                 } else {
135                         if (omap_rev() < OMAP3430_REV_ES3_0)
136                                 return OMAPDSS_VER_OMAP34xx_ES1;
137                         else
138                                 return OMAPDSS_VER_OMAP34xx_ES3;
139                 }
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;
154         else
155                 return OMAPDSS_VER_UNKNOWN;
156 }
157
158 static int __init omapdss_init_fbdev(void)
159 {
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,
163         };
164         struct device_node *node;
165         int r;
166
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");
170                 return -ENODEV;
171         }
172
173         omap_display_device.dev.platform_data = &board_data;
174
175         r = platform_device_register(&omap_display_device);
176         if (r < 0) {
177                 pr_err("Unable to register omapdss device\n");
178                 return r;
179         }
180
181         /* create vrfb device */
182         r = omap_init_vrfb();
183         if (r < 0) {
184                 pr_err("Unable to register omapvrfb device\n");
185                 return r;
186         }
187
188         /* create FB device */
189         r = omap_init_fb();
190         if (r < 0) {
191                 pr_err("Unable to register omapfb device\n");
192                 return r;
193         }
194
195         /* create V4L2 display device */
196         r = omap_init_vout();
197         if (r < 0) {
198                 pr_err("Unable to register omap_vout device\n");
199                 return r;
200         }
201
202         /* add DSI info for omap4 */
203         node = of_find_node_by_name(NULL, "omap4_padconf_global");
204         if (node)
205                 omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
206         of_node_put(node);
207
208         return 0;
209 }
210
211 static const char * const omapdss_compat_names[] __initconst = {
212         "ti,omap2-dss",
213         "ti,omap3-dss",
214         "ti,omap4-dss",
215         "ti,omap5-dss",
216         "ti,dra7-dss",
217 };
218
219 static struct device_node * __init omapdss_find_dss_of_node(void)
220 {
221         struct device_node *node;
222         int i;
223
224         for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
225                 node = of_find_compatible_node(NULL, NULL,
226                         omapdss_compat_names[i]);
227                 if (node)
228                         return node;
229         }
230
231         return NULL;
232 }
233
234 static int __init omapdss_init_of(void)
235 {
236         int r;
237         struct device_node *node;
238         struct platform_device *pdev;
239
240         /* only create dss helper devices if dss is enabled in the .dts */
241
242         node = omapdss_find_dss_of_node();
243         if (!node)
244                 return 0;
245
246         if (!of_device_is_available(node)) {
247                 of_node_put(node);
248                 return 0;
249         }
250
251         pdev = of_find_device_by_node(node);
252
253         if (!pdev) {
254                 pr_err("Unable to find DSS platform device\n");
255                 of_node_put(node);
256                 return -ENODEV;
257         }
258
259         r = of_platform_populate(node, NULL, NULL, &pdev->dev);
260         put_device(&pdev->dev);
261         of_node_put(node);
262         if (r) {
263                 pr_err("Unable to populate DSS submodule devices\n");
264                 return r;
265         }
266
267         return omapdss_init_fbdev();
268 }
269 omap_device_initcall(omapdss_init_of);
270 #endif /* CONFIG_FB_OMAP2 */
271
272 static void dispc_disable_outputs(void)
273 {
274         u32 v, irq_mask = 0;
275         bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false;
276         int i;
277         struct omap_dss_dispc_dev_attr *da;
278         struct omap_hwmod *oh;
279
280         oh = omap_hwmod_lookup("dss_dispc");
281         if (!oh) {
282                 WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
283                 return;
284         }
285
286         if (!oh->dev_attr) {
287                 pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
288                 return;
289         }
290
291         da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
292
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;
297
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;
302         }
303
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;
308         }
309
310         if (!(lcd_en | digit_en | lcd2_en | lcd3_en))
311                 return; /* no managers currently enabled */
312
313         /*
314          * If any manager was enabled, we need to disable it before
315          * DSS clocks are disabled or DISPC module is reset
316          */
317         if (lcd_en)
318                 irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
319
320         if (digit_en) {
321                 if (da->has_framedonetv_irq) {
322                         irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
323                 } else {
324                         irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
325                                 1 << EVSYNC_ODD_IRQ_SHIFT;
326                 }
327         }
328
329         if (lcd2_en)
330                 irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
331         if (lcd3_en)
332                 irq_mask |= 1 << FRAMEDONE3_IRQ_SHIFT;
333
334         /*
335          * clear any previous FRAMEDONE, FRAMEDONETV,
336          * EVSYNC_EVEN/ODD, FRAMEDONE2 or FRAMEDONE3 interrupts
337          */
338         omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
339
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);
344
345         /* disable LCD2 manager */
346         if (da->manager_count > 2) {
347                 v = omap_hwmod_read(oh, DISPC_CONTROL2);
348                 v &= ~LCD_EN_MASK;
349                 omap_hwmod_write(v, oh, DISPC_CONTROL2);
350         }
351
352         /* disable LCD3 manager */
353         if (da->manager_count > 3) {
354                 v = omap_hwmod_read(oh, DISPC_CONTROL3);
355                 v &= ~LCD_EN_MASK;
356                 omap_hwmod_write(v, oh, DISPC_CONTROL3);
357         }
358
359         i = 0;
360         while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
361                irq_mask) {
362                 i++;
363                 if (i > FRAMEDONE_IRQ_TIMEOUT) {
364                         pr_err("didn't get FRAMEDONE1/2/3 or TV interrupt\n");
365                         break;
366                 }
367                 mdelay(1);
368         }
369 }
370
371 int omap_dss_reset(struct omap_hwmod *oh)
372 {
373         struct omap_hwmod_opt_clk *oc;
374         int c = 0;
375         int i, r;
376
377         if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
378                 pr_err("dss_core: hwmod data doesn't contain reset data\n");
379                 return -EINVAL;
380         }
381
382         for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
383                 clk_prepare_enable(oc->_clk);
384
385         dispc_disable_outputs();
386
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);
391         }
392
393         /*
394          * clear DSS_CONTROL register to switch DSS clock sources to
395          * PRCM clock, if any
396          */
397         omap_hwmod_write(0x0, oh, DSS_CONTROL);
398
399         omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
400                                 & SYSS_RESETDONE_MASK),
401                         MAX_MODULE_SOFTRESET_WAIT, c);
402
403         if (c == MAX_MODULE_SOFTRESET_WAIT)
404                 pr_warn("dss_core: waiting for reset to finish failed\n");
405         else
406                 pr_debug("dss_core: softreset done\n");
407
408         for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
409                 clk_disable_unprepare(oc->_clk);
410
411         r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
412
413         return r;
414 }