diff options
Diffstat (limited to 'drivers/video/sh_mipi_dsi.c')
-rw-r--r-- | drivers/video/sh_mipi_dsi.c | 129 |
1 files changed, 101 insertions, 28 deletions
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 3f3d431033ca..24640c8458ab 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/pm_runtime.h> | ||
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/string.h> | 18 | #include <linux/string.h> |
18 | #include <linux/types.h> | 19 | #include <linux/types.h> |
@@ -21,18 +22,40 @@ | |||
21 | #include <video/sh_mipi_dsi.h> | 22 | #include <video/sh_mipi_dsi.h> |
22 | #include <video/sh_mobile_lcdc.h> | 23 | #include <video/sh_mobile_lcdc.h> |
23 | 24 | ||
24 | #define CMTSRTCTR 0x80d0 | 25 | #define SYSCTRL 0x0000 |
25 | #define CMTSRTREQ 0x8070 | 26 | #define SYSCONF 0x0004 |
26 | 27 | #define TIMSET 0x0008 | |
28 | #define RESREQSET0 0x0018 | ||
29 | #define RESREQSET1 0x001c | ||
30 | #define HSTTOVSET 0x0020 | ||
31 | #define LPRTOVSET 0x0024 | ||
32 | #define TATOVSET 0x0028 | ||
33 | #define PRTOVSET 0x002c | ||
34 | #define DSICTRL 0x0030 | ||
27 | #define DSIINTE 0x0060 | 35 | #define DSIINTE 0x0060 |
36 | #define PHYCTRL 0x0070 | ||
37 | |||
38 | /* relative to linkbase */ | ||
39 | #define DTCTR 0x0000 | ||
40 | #define VMCTR1 0x0020 | ||
41 | #define VMCTR2 0x0024 | ||
42 | #define VMLEN1 0x0028 | ||
43 | #define CMTSRTREQ 0x0070 | ||
44 | #define CMTSRTCTR 0x00d0 | ||
28 | 45 | ||
29 | /* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ | 46 | /* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ |
30 | #define MAX_SH_MIPI_DSI 2 | 47 | #define MAX_SH_MIPI_DSI 2 |
31 | 48 | ||
32 | struct sh_mipi { | 49 | struct sh_mipi { |
33 | void __iomem *base; | 50 | void __iomem *base; |
51 | void __iomem *linkbase; | ||
34 | struct clk *dsit_clk; | 52 | struct clk *dsit_clk; |
35 | struct clk *dsip_clk; | 53 | struct clk *dsip_clk; |
54 | struct device *dev; | ||
55 | |||
56 | void *next_board_data; | ||
57 | void (*next_display_on)(void *board_data, struct fb_info *info); | ||
58 | void (*next_display_off)(void *board_data); | ||
36 | }; | 59 | }; |
37 | 60 | ||
38 | static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; | 61 | static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; |
@@ -55,10 +78,10 @@ static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd, | |||
55 | int cnt = 100; | 78 | int cnt = 100; |
56 | 79 | ||
57 | /* transmit a short packet to LCD panel */ | 80 | /* transmit a short packet to LCD panel */ |
58 | iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */ | 81 | iowrite32(1 | data, mipi->linkbase + CMTSRTCTR); |
59 | iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */ | 82 | iowrite32(1, mipi->linkbase + CMTSRTREQ); |
60 | 83 | ||
61 | while ((ioread32(mipi->base + 0x8070) & 1) && --cnt) | 84 | while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt) |
62 | udelay(1); | 85 | udelay(1); |
63 | 86 | ||
64 | return cnt ? 0 : -ETIMEDOUT; | 87 | return cnt ? 0 : -ETIMEDOUT; |
@@ -90,7 +113,7 @@ static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable) | |||
90 | * enable LCDC data tx, transition to LPS after completion of each HS | 113 | * enable LCDC data tx, transition to LPS after completion of each HS |
91 | * packet | 114 | * packet |
92 | */ | 115 | */ |
93 | iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */ | 116 | iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR); |
94 | } | 117 | } |
95 | 118 | ||
96 | static void sh_mipi_shutdown(struct platform_device *pdev) | 119 | static void sh_mipi_shutdown(struct platform_device *pdev) |
@@ -104,14 +127,22 @@ static void mipi_display_on(void *arg, struct fb_info *info) | |||
104 | { | 127 | { |
105 | struct sh_mipi *mipi = arg; | 128 | struct sh_mipi *mipi = arg; |
106 | 129 | ||
130 | pm_runtime_get_sync(mipi->dev); | ||
107 | sh_mipi_dsi_enable(mipi, true); | 131 | sh_mipi_dsi_enable(mipi, true); |
132 | |||
133 | if (mipi->next_display_on) | ||
134 | mipi->next_display_on(mipi->next_board_data, info); | ||
108 | } | 135 | } |
109 | 136 | ||
110 | static void mipi_display_off(void *arg) | 137 | static void mipi_display_off(void *arg) |
111 | { | 138 | { |
112 | struct sh_mipi *mipi = arg; | 139 | struct sh_mipi *mipi = arg; |
113 | 140 | ||
141 | if (mipi->next_display_off) | ||
142 | mipi->next_display_off(mipi->next_board_data); | ||
143 | |||
114 | sh_mipi_dsi_enable(mipi, false); | 144 | sh_mipi_dsi_enable(mipi, false); |
145 | pm_runtime_put(mipi->dev); | ||
115 | } | 146 | } |
116 | 147 | ||
117 | static int __init sh_mipi_setup(struct sh_mipi *mipi, | 148 | static int __init sh_mipi_setup(struct sh_mipi *mipi, |
@@ -119,8 +150,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
119 | { | 150 | { |
120 | void __iomem *base = mipi->base; | 151 | void __iomem *base = mipi->base; |
121 | struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; | 152 | struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; |
122 | u32 pctype, datatype, pixfmt; | 153 | u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000; |
123 | u32 linelength; | ||
124 | bool yuv; | 154 | bool yuv; |
125 | 155 | ||
126 | /* | 156 | /* |
@@ -223,10 +253,10 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
223 | return -EINVAL; | 253 | return -EINVAL; |
224 | 254 | ||
225 | /* reset DSI link */ | 255 | /* reset DSI link */ |
226 | iowrite32(0x00000001, base); /* SYSCTRL */ | 256 | iowrite32(0x00000001, base + SYSCTRL); |
227 | /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ | 257 | /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ |
228 | udelay(50); | 258 | udelay(50); |
229 | iowrite32(0x00000000, base); /* SYSCTRL */ | 259 | iowrite32(0x00000000, base + SYSCTRL); |
230 | 260 | ||
231 | /* setup DSI link */ | 261 | /* setup DSI link */ |
232 | 262 | ||
@@ -238,7 +268,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
238 | * ECC check enable | 268 | * ECC check enable |
239 | * additionally enable first two lanes | 269 | * additionally enable first two lanes |
240 | */ | 270 | */ |
241 | iowrite32(0x00003703, base + 0x04); /* SYSCONF */ | 271 | iowrite32(0x00003703, base + SYSCONF); |
242 | /* | 272 | /* |
243 | * T_wakeup = 0x7000 | 273 | * T_wakeup = 0x7000 |
244 | * T_hs-trail = 3 | 274 | * T_hs-trail = 3 |
@@ -246,28 +276,28 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
246 | * T_clk-trail = 3 | 276 | * T_clk-trail = 3 |
247 | * T_clk-prepare = 2 | 277 | * T_clk-prepare = 2 |
248 | */ | 278 | */ |
249 | iowrite32(0x70003332, base + 0x08); /* TIMSET */ | 279 | iowrite32(0x70003332, base + TIMSET); |
250 | /* no responses requested */ | 280 | /* no responses requested */ |
251 | iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */ | 281 | iowrite32(0x00000000, base + RESREQSET0); |
252 | /* request response to packets of type 0x28 */ | 282 | /* request response to packets of type 0x28 */ |
253 | iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */ | 283 | iowrite32(0x00000100, base + RESREQSET1); |
254 | /* High-speed transmission timeout, default 0xffffffff */ | 284 | /* High-speed transmission timeout, default 0xffffffff */ |
255 | iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */ | 285 | iowrite32(0x0fffffff, base + HSTTOVSET); |
256 | /* LP reception timeout, default 0xffffffff */ | 286 | /* LP reception timeout, default 0xffffffff */ |
257 | iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */ | 287 | iowrite32(0x0fffffff, base + LPRTOVSET); |
258 | /* Turn-around timeout, default 0xffffffff */ | 288 | /* Turn-around timeout, default 0xffffffff */ |
259 | iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */ | 289 | iowrite32(0x0fffffff, base + TATOVSET); |
260 | /* Peripheral reset timeout, default 0xffffffff */ | 290 | /* Peripheral reset timeout, default 0xffffffff */ |
261 | iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */ | 291 | iowrite32(0x0fffffff, base + PRTOVSET); |
262 | /* Enable timeout counters */ | 292 | /* Enable timeout counters */ |
263 | iowrite32(0x00000f00, base + 0x30); /* DSICTRL */ | 293 | iowrite32(0x00000f00, base + DSICTRL); |
264 | /* Interrupts not used, disable all */ | 294 | /* Interrupts not used, disable all */ |
265 | iowrite32(0, base + DSIINTE); | 295 | iowrite32(0, base + DSIINTE); |
266 | /* DSI-Tx bias on */ | 296 | /* DSI-Tx bias on */ |
267 | iowrite32(0x00000001, base + 0x70); /* PHYCTRL */ | 297 | iowrite32(0x00000001, base + PHYCTRL); |
268 | udelay(200); | 298 | udelay(200); |
269 | /* Deassert resets, power on, set multiplier */ | 299 | /* Deassert resets, power on, set multiplier */ |
270 | iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */ | 300 | iowrite32(0x03070b01, base + PHYCTRL); |
271 | 301 | ||
272 | /* setup l-bridge */ | 302 | /* setup l-bridge */ |
273 | 303 | ||
@@ -275,20 +305,28 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
275 | * Enable transmission of all packets, | 305 | * Enable transmission of all packets, |
276 | * transmit LPS after each HS packet completion | 306 | * transmit LPS after each HS packet completion |
277 | */ | 307 | */ |
278 | iowrite32(0x00000006, base + 0x8000); /* DTCTR */ | 308 | iowrite32(0x00000006, mipi->linkbase + DTCTR); |
279 | /* VSYNC width = 2 (<< 17) */ | 309 | /* VSYNC width = 2 (<< 17) */ |
280 | iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */ | 310 | iowrite32((ch->lcd_cfg[0].vsync_len << pdata->vsynw_offset) | |
311 | (pdata->clksrc << 16) | (pctype << 12) | datatype, | ||
312 | mipi->linkbase + VMCTR1); | ||
313 | |||
281 | /* | 314 | /* |
282 | * Non-burst mode with sync pulses: VSE and HSE are output, | 315 | * Non-burst mode with sync pulses: VSE and HSE are output, |
283 | * HSA period allowed, no commands in LP | 316 | * HSA period allowed, no commands in LP |
284 | */ | 317 | */ |
285 | iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ | 318 | if (pdata->flags & SH_MIPI_DSI_HSABM) |
319 | vmctr2 |= 0x20; | ||
320 | if (pdata->flags & SH_MIPI_DSI_HSPBM) | ||
321 | vmctr2 |= 0x10; | ||
322 | iowrite32(vmctr2, mipi->linkbase + VMCTR2); | ||
323 | |||
286 | /* | 324 | /* |
287 | * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see | 325 | * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see |
288 | * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default | 326 | * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default |
289 | * (unused, since VMCTR2[HSABM] = 0) | 327 | * (unused if VMCTR2[HSABM] = 0) |
290 | */ | 328 | */ |
291 | iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ | 329 | iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1); |
292 | 330 | ||
293 | msleep(5); | 331 | msleep(5); |
294 | 332 | ||
@@ -321,11 +359,12 @@ static int __init sh_mipi_probe(struct platform_device *pdev) | |||
321 | struct sh_mipi *mipi; | 359 | struct sh_mipi *mipi; |
322 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | 360 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; |
323 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 361 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
362 | struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
324 | unsigned long rate, f_current; | 363 | unsigned long rate, f_current; |
325 | int idx = pdev->id, ret; | 364 | int idx = pdev->id, ret; |
326 | char dsip_clk[] = "dsi.p_clk"; | 365 | char dsip_clk[] = "dsi.p_clk"; |
327 | 366 | ||
328 | if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) | 367 | if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) |
329 | return -ENODEV; | 368 | return -ENODEV; |
330 | 369 | ||
331 | mutex_lock(&array_lock); | 370 | mutex_lock(&array_lock); |
@@ -356,6 +395,20 @@ static int __init sh_mipi_probe(struct platform_device *pdev) | |||
356 | goto emap; | 395 | goto emap; |
357 | } | 396 | } |
358 | 397 | ||
398 | if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) { | ||
399 | dev_err(&pdev->dev, "MIPI register region 2 already claimed\n"); | ||
400 | ret = -EBUSY; | ||
401 | goto ereqreg2; | ||
402 | } | ||
403 | |||
404 | mipi->linkbase = ioremap(res2->start, resource_size(res2)); | ||
405 | if (!mipi->linkbase) { | ||
406 | ret = -ENOMEM; | ||
407 | goto emap2; | ||
408 | } | ||
409 | |||
410 | mipi->dev = &pdev->dev; | ||
411 | |||
359 | mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); | 412 | mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); |
360 | if (IS_ERR(mipi->dsit_clk)) { | 413 | if (IS_ERR(mipi->dsit_clk)) { |
361 | ret = PTR_ERR(mipi->dsit_clk); | 414 | ret = PTR_ERR(mipi->dsit_clk); |
@@ -405,6 +458,9 @@ static int __init sh_mipi_probe(struct platform_device *pdev) | |||
405 | 458 | ||
406 | mipi_dsi[idx] = mipi; | 459 | mipi_dsi[idx] = mipi; |
407 | 460 | ||
461 | pm_runtime_enable(&pdev->dev); | ||
462 | pm_runtime_resume(&pdev->dev); | ||
463 | |||
408 | ret = sh_mipi_setup(mipi, pdata); | 464 | ret = sh_mipi_setup(mipi, pdata); |
409 | if (ret < 0) | 465 | if (ret < 0) |
410 | goto emipisetup; | 466 | goto emipisetup; |
@@ -412,15 +468,22 @@ static int __init sh_mipi_probe(struct platform_device *pdev) | |||
412 | mutex_unlock(&array_lock); | 468 | mutex_unlock(&array_lock); |
413 | platform_set_drvdata(pdev, mipi); | 469 | platform_set_drvdata(pdev, mipi); |
414 | 470 | ||
471 | /* Save original LCDC callbacks */ | ||
472 | mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data; | ||
473 | mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on; | ||
474 | mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off; | ||
475 | |||
415 | /* Set up LCDC callbacks */ | 476 | /* Set up LCDC callbacks */ |
416 | pdata->lcd_chan->board_cfg.board_data = mipi; | 477 | pdata->lcd_chan->board_cfg.board_data = mipi; |
417 | pdata->lcd_chan->board_cfg.display_on = mipi_display_on; | 478 | pdata->lcd_chan->board_cfg.display_on = mipi_display_on; |
418 | pdata->lcd_chan->board_cfg.display_off = mipi_display_off; | 479 | pdata->lcd_chan->board_cfg.display_off = mipi_display_off; |
480 | pdata->lcd_chan->board_cfg.owner = THIS_MODULE; | ||
419 | 481 | ||
420 | return 0; | 482 | return 0; |
421 | 483 | ||
422 | emipisetup: | 484 | emipisetup: |
423 | mipi_dsi[idx] = NULL; | 485 | mipi_dsi[idx] = NULL; |
486 | pm_runtime_disable(&pdev->dev); | ||
424 | clk_disable(mipi->dsip_clk); | 487 | clk_disable(mipi->dsip_clk); |
425 | eclkpon: | 488 | eclkpon: |
426 | clk_disable(mipi->dsit_clk); | 489 | clk_disable(mipi->dsit_clk); |
@@ -431,6 +494,10 @@ eclkpget: | |||
431 | esettrate: | 494 | esettrate: |
432 | clk_put(mipi->dsit_clk); | 495 | clk_put(mipi->dsit_clk); |
433 | eclktget: | 496 | eclktget: |
497 | iounmap(mipi->linkbase); | ||
498 | emap2: | ||
499 | release_mem_region(res2->start, resource_size(res2)); | ||
500 | ereqreg2: | ||
434 | iounmap(mipi->base); | 501 | iounmap(mipi->base); |
435 | emap: | 502 | emap: |
436 | release_mem_region(res->start, resource_size(res)); | 503 | release_mem_region(res->start, resource_size(res)); |
@@ -447,6 +514,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev) | |||
447 | { | 514 | { |
448 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | 515 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; |
449 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 516 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
517 | struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
450 | struct sh_mipi *mipi = platform_get_drvdata(pdev); | 518 | struct sh_mipi *mipi = platform_get_drvdata(pdev); |
451 | int i, ret; | 519 | int i, ret; |
452 | 520 | ||
@@ -467,14 +535,19 @@ static int __exit sh_mipi_remove(struct platform_device *pdev) | |||
467 | if (ret < 0) | 535 | if (ret < 0) |
468 | return ret; | 536 | return ret; |
469 | 537 | ||
538 | pdata->lcd_chan->board_cfg.owner = NULL; | ||
470 | pdata->lcd_chan->board_cfg.display_on = NULL; | 539 | pdata->lcd_chan->board_cfg.display_on = NULL; |
471 | pdata->lcd_chan->board_cfg.display_off = NULL; | 540 | pdata->lcd_chan->board_cfg.display_off = NULL; |
472 | pdata->lcd_chan->board_cfg.board_data = NULL; | 541 | pdata->lcd_chan->board_cfg.board_data = NULL; |
473 | 542 | ||
543 | pm_runtime_disable(&pdev->dev); | ||
474 | clk_disable(mipi->dsip_clk); | 544 | clk_disable(mipi->dsip_clk); |
475 | clk_disable(mipi->dsit_clk); | 545 | clk_disable(mipi->dsit_clk); |
476 | clk_put(mipi->dsit_clk); | 546 | clk_put(mipi->dsit_clk); |
477 | clk_put(mipi->dsip_clk); | 547 | clk_put(mipi->dsip_clk); |
548 | iounmap(mipi->linkbase); | ||
549 | if (res2) | ||
550 | release_mem_region(res2->start, resource_size(res2)); | ||
478 | iounmap(mipi->base); | 551 | iounmap(mipi->base); |
479 | if (res) | 552 | if (res) |
480 | release_mem_region(res->start, resource_size(res)); | 553 | release_mem_region(res->start, resource_size(res)); |