Blame view
drivers/video/sh_mipi_dsi.c
15.5 KB
9fd04fe34 sh-mobile: add su... |
1 2 3 4 5 6 7 8 9 |
/* * Renesas SH-mobile MIPI DSI support * * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> * * This is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. */ |
26c3d7ac2 fbdev: sh_mipi_ds... |
10 |
#include <linux/bitmap.h> |
9fd04fe34 sh-mobile: add su... |
11 12 13 14 15 |
#include <linux/clk.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> #include <linux/platform_device.h> |
236782a5f fbdev: sh-mobile:... |
16 |
#include <linux/pm_runtime.h> |
9fd04fe34 sh-mobile: add su... |
17 18 19 |
#include <linux/slab.h> #include <linux/string.h> #include <linux/types.h> |
355b200ba video: Add module... |
20 |
#include <linux/module.h> |
9fd04fe34 sh-mobile: add su... |
21 22 23 24 |
#include <video/mipi_display.h> #include <video/sh_mipi_dsi.h> #include <video/sh_mobile_lcdc.h> |
71b146c81 fbdev: sh_mipi_ds... |
25 26 27 28 29 30 31 32 33 34 35 36 |
#define SYSCTRL 0x0000 #define SYSCONF 0x0004 #define TIMSET 0x0008 #define RESREQSET0 0x0018 #define RESREQSET1 0x001c #define HSTTOVSET 0x0020 #define LPRTOVSET 0x0024 #define TATOVSET 0x0028 #define PRTOVSET 0x002c #define DSICTRL 0x0030 #define DSIINTE 0x0060 #define PHYCTRL 0x0070 |
deaba1901 fbdev: sh_mipi_ds... |
37 38 39 40 41 |
/* relative to linkbase */ #define DTCTR 0x0000 #define VMCTR1 0x0020 #define VMCTR2 0x0024 #define VMLEN1 0x0028 |
08750617b fbdev: sh_mipi_ds... |
42 |
#define VMLEN2 0x002c |
deaba1901 fbdev: sh_mipi_ds... |
43 44 |
#define CMTSRTREQ 0x0070 #define CMTSRTCTR 0x00d0 |
9fd04fe34 sh-mobile: add su... |
45 46 47 48 49 50 |
/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ #define MAX_SH_MIPI_DSI 2 struct sh_mipi { void __iomem *base; |
deaba1901 fbdev: sh_mipi_ds... |
51 |
void __iomem *linkbase; |
9fd04fe34 sh-mobile: add su... |
52 |
struct clk *dsit_clk; |
7d9f88b4f fbdev: sh_mipi_ds... |
53 |
struct platform_device *pdev; |
236782a5f fbdev: sh-mobile:... |
54 55 56 57 |
void *next_board_data; void (*next_display_on)(void *board_data, struct fb_info *info); void (*next_display_off)(void *board_data); |
9fd04fe34 sh-mobile: add su... |
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
}; static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; /* Protect the above array */ static DEFINE_MUTEX(array_lock); static struct sh_mipi *sh_mipi_by_handle(int handle) { if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0) return NULL; return mipi_dsi[handle]; } static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd, u8 cmd, u8 param) { u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8); int cnt = 100; /* transmit a short packet to LCD panel */ |
deaba1901 fbdev: sh_mipi_ds... |
80 81 |
iowrite32(1 | data, mipi->linkbase + CMTSRTCTR); iowrite32(1, mipi->linkbase + CMTSRTREQ); |
9fd04fe34 sh-mobile: add su... |
82 |
|
deaba1901 fbdev: sh_mipi_ds... |
83 |
while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt) |
9fd04fe34 sh-mobile: add su... |
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
udelay(1); return cnt ? 0 : -ETIMEDOUT; } #define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \ -EINVAL : (c) - 1) static int sh_mipi_dcs(int handle, u8 cmd) { struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); if (!mipi) return -ENODEV; return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0); } static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param) { struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); if (!mipi) return -ENODEV; return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd, param); } static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable) { /* * enable LCDC data tx, transition to LPS after completion of each HS * packet */ |
deaba1901 fbdev: sh_mipi_ds... |
115 |
iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR); |
9fd04fe34 sh-mobile: add su... |
116 117 118 119 120 121 122 123 |
} static void sh_mipi_shutdown(struct platform_device *pdev) { struct sh_mipi *mipi = platform_get_drvdata(pdev); sh_mipi_dsi_enable(mipi, false); } |
9fd04fe34 sh-mobile: add su... |
124 125 126 127 128 |
static int __init sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) { void __iomem *base = mipi->base; struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; |
f832906a5 fbdev: sh_mipi_ds... |
129 |
u32 pctype, datatype, pixfmt, linelength, vmctr2; |
a2e629715 fbdev: sh_mipi_ds... |
130 |
u32 tmp, top, bottom, delay, div; |
9fd04fe34 sh-mobile: add su... |
131 |
bool yuv; |
08750617b fbdev: sh_mipi_ds... |
132 |
int bpp; |
9fd04fe34 sh-mobile: add su... |
133 |
|
44432407d fbdev: sh_mobile_... |
134 135 136 137 138 |
/* * Select data format. MIPI DSI is not hot-pluggable, so, we just use * the default videomode. If this ever becomes a problem, We'll have to * move this to mipi_display_on() above and use info->var.xres */ |
9fd04fe34 sh-mobile: add su... |
139 140 141 142 143 |
switch (pdata->data_format) { case MIPI_RGB888: pctype = 0; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
44432407d fbdev: sh_mobile_... |
144 |
linelength = ch->lcd_cfg[0].xres * 3; |
9fd04fe34 sh-mobile: add su... |
145 146 147 148 149 150 |
yuv = false; break; case MIPI_RGB565: pctype = 1; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
44432407d fbdev: sh_mobile_... |
151 |
linelength = ch->lcd_cfg[0].xres * 2; |
9fd04fe34 sh-mobile: add su... |
152 153 154 155 156 157 |
yuv = false; break; case MIPI_RGB666_LP: pctype = 2; datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
44432407d fbdev: sh_mobile_... |
158 |
linelength = ch->lcd_cfg[0].xres * 3; |
9fd04fe34 sh-mobile: add su... |
159 160 161 162 163 164 |
yuv = false; break; case MIPI_RGB666: pctype = 3; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; |
44432407d fbdev: sh_mobile_... |
165 |
linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; |
9fd04fe34 sh-mobile: add su... |
166 167 168 169 170 171 |
yuv = false; break; case MIPI_BGR888: pctype = 8; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
44432407d fbdev: sh_mobile_... |
172 |
linelength = ch->lcd_cfg[0].xres * 3; |
9fd04fe34 sh-mobile: add su... |
173 174 175 176 177 178 |
yuv = false; break; case MIPI_BGR565: pctype = 9; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
44432407d fbdev: sh_mobile_... |
179 |
linelength = ch->lcd_cfg[0].xres * 2; |
9fd04fe34 sh-mobile: add su... |
180 181 182 183 184 185 |
yuv = false; break; case MIPI_BGR666_LP: pctype = 0xa; datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
44432407d fbdev: sh_mobile_... |
186 |
linelength = ch->lcd_cfg[0].xres * 3; |
9fd04fe34 sh-mobile: add su... |
187 188 189 190 191 192 |
yuv = false; break; case MIPI_BGR666: pctype = 0xb; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; |
44432407d fbdev: sh_mobile_... |
193 |
linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; |
9fd04fe34 sh-mobile: add su... |
194 195 196 197 198 199 |
yuv = false; break; case MIPI_YUYV: pctype = 4; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
44432407d fbdev: sh_mobile_... |
200 |
linelength = ch->lcd_cfg[0].xres * 2; |
9fd04fe34 sh-mobile: add su... |
201 202 203 204 205 206 |
yuv = true; break; case MIPI_UYVY: pctype = 5; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
44432407d fbdev: sh_mobile_... |
207 |
linelength = ch->lcd_cfg[0].xres * 2; |
9fd04fe34 sh-mobile: add su... |
208 209 210 211 212 213 |
yuv = true; break; case MIPI_YUV420_L: pctype = 6; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; |
44432407d fbdev: sh_mobile_... |
214 |
linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8; |
9fd04fe34 sh-mobile: add su... |
215 216 217 218 219 220 221 |
yuv = true; break; case MIPI_YUV420: pctype = 7; datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; /* Length of U/V line */ |
44432407d fbdev: sh_mobile_... |
222 |
linelength = (ch->lcd_cfg[0].xres + 1) / 2; |
9fd04fe34 sh-mobile: add su... |
223 224 225 226 227 228 229 230 231 |
yuv = true; break; default: return -EINVAL; } if ((yuv && ch->interface_type != YUV422) || (!yuv && ch->interface_type != RGB24)) return -EINVAL; |
26c3d7ac2 fbdev: sh_mipi_ds... |
232 233 |
if (!pdata->lane) return -EINVAL; |
9fd04fe34 sh-mobile: add su... |
234 |
/* reset DSI link */ |
71b146c81 fbdev: sh_mipi_ds... |
235 |
iowrite32(0x00000001, base + SYSCTRL); |
9fd04fe34 sh-mobile: add su... |
236 237 |
/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ udelay(50); |
71b146c81 fbdev: sh_mipi_ds... |
238 |
iowrite32(0x00000000, base + SYSCTRL); |
9fd04fe34 sh-mobile: add su... |
239 240 241 242 |
/* setup DSI link */ /* |
9fd04fe34 sh-mobile: add su... |
243 244 245 246 247 248 |
* T_wakeup = 0x7000 * T_hs-trail = 3 * T_hs-prepare = 3 * T_clk-trail = 3 * T_clk-prepare = 2 */ |
71b146c81 fbdev: sh_mipi_ds... |
249 |
iowrite32(0x70003332, base + TIMSET); |
9fd04fe34 sh-mobile: add su... |
250 |
/* no responses requested */ |
71b146c81 fbdev: sh_mipi_ds... |
251 |
iowrite32(0x00000000, base + RESREQSET0); |
9fd04fe34 sh-mobile: add su... |
252 |
/* request response to packets of type 0x28 */ |
71b146c81 fbdev: sh_mipi_ds... |
253 |
iowrite32(0x00000100, base + RESREQSET1); |
9fd04fe34 sh-mobile: add su... |
254 |
/* High-speed transmission timeout, default 0xffffffff */ |
71b146c81 fbdev: sh_mipi_ds... |
255 |
iowrite32(0x0fffffff, base + HSTTOVSET); |
9fd04fe34 sh-mobile: add su... |
256 |
/* LP reception timeout, default 0xffffffff */ |
71b146c81 fbdev: sh_mipi_ds... |
257 |
iowrite32(0x0fffffff, base + LPRTOVSET); |
9fd04fe34 sh-mobile: add su... |
258 |
/* Turn-around timeout, default 0xffffffff */ |
71b146c81 fbdev: sh_mipi_ds... |
259 |
iowrite32(0x0fffffff, base + TATOVSET); |
9fd04fe34 sh-mobile: add su... |
260 |
/* Peripheral reset timeout, default 0xffffffff */ |
71b146c81 fbdev: sh_mipi_ds... |
261 |
iowrite32(0x0fffffff, base + PRTOVSET); |
9fd04fe34 sh-mobile: add su... |
262 263 264 |
/* Interrupts not used, disable all */ iowrite32(0, base + DSIINTE); /* DSI-Tx bias on */ |
71b146c81 fbdev: sh_mipi_ds... |
265 |
iowrite32(0x00000001, base + PHYCTRL); |
9fd04fe34 sh-mobile: add su... |
266 |
udelay(200); |
5e47431aa fbdev: sh_mipi_ds... |
267 268 |
/* Deassert resets, power on */ iowrite32(0x03070001, base + PHYCTRL); |
9fd04fe34 sh-mobile: add su... |
269 |
|
a2065a368 fbdev: sh_mipi_ds... |
270 271 272 273 274 275 276 277 278 279 |
/* * Default = ULPS enable | * Contention detection enabled | * EoT packet transmission enable | * CRC check enable | * ECC check enable */ bitmap_fill((unsigned long *)&tmp, pdata->lane); tmp |= 0x00003700; iowrite32(tmp, base + SYSCONF); |
9fd04fe34 sh-mobile: add su... |
280 281 282 283 284 285 |
/* setup l-bridge */ /* * Enable transmission of all packets, * transmit LPS after each HS packet completion */ |
deaba1901 fbdev: sh_mipi_ds... |
286 |
iowrite32(0x00000006, mipi->linkbase + DTCTR); |
9fd04fe34 sh-mobile: add su... |
287 |
/* VSYNC width = 2 (<< 17) */ |
14bbb7c61 fbdev: sh_mipi_ds... |
288 289 |
iowrite32((ch->lcd_cfg[0].vsync_len << pdata->vsynw_offset) | (pdata->clksrc << 16) | (pctype << 12) | datatype, |
deaba1901 fbdev: sh_mipi_ds... |
290 |
mipi->linkbase + VMCTR1); |
14bbb7c61 fbdev: sh_mipi_ds... |
291 |
|
9fd04fe34 sh-mobile: add su... |
292 293 294 295 |
/* * Non-burst mode with sync pulses: VSE and HSE are output, * HSA period allowed, no commands in LP */ |
f832906a5 fbdev: sh_mipi_ds... |
296 297 298 299 300 301 302 |
vmctr2 = 0; if (pdata->flags & SH_MIPI_DSI_VSEE) vmctr2 |= 1 << 23; if (pdata->flags & SH_MIPI_DSI_HSEE) vmctr2 |= 1 << 22; if (pdata->flags & SH_MIPI_DSI_HSAE) vmctr2 |= 1 << 21; |
d07a9d2a5 fbdev: sh_mipi_ds... |
303 304 |
if (pdata->flags & SH_MIPI_DSI_BL2E) vmctr2 |= 1 << 17; |
14bbb7c61 fbdev: sh_mipi_ds... |
305 |
if (pdata->flags & SH_MIPI_DSI_HSABM) |
3c2a65993 fbdev: sh_mipi_ds... |
306 |
vmctr2 |= 1 << 5; |
32ba95c69 fbdev: sh_mipi_ds... |
307 |
if (pdata->flags & SH_MIPI_DSI_HBPBM) |
3c2a65993 fbdev: sh_mipi_ds... |
308 |
vmctr2 |= 1 << 4; |
f7b0af68b fbdev: sh_mipi_ds... |
309 310 |
if (pdata->flags & SH_MIPI_DSI_HFPBM) vmctr2 |= 1 << 3; |
14bbb7c61 fbdev: sh_mipi_ds... |
311 |
iowrite32(vmctr2, mipi->linkbase + VMCTR2); |
9fd04fe34 sh-mobile: add su... |
312 |
/* |
08750617b fbdev: sh_mipi_ds... |
313 314 315 316 |
* VMLEN1 = RGBLEN | HSALEN * * see * Video mode - Blanking Packet setting |
9fd04fe34 sh-mobile: add su... |
317 |
*/ |
08750617b fbdev: sh_mipi_ds... |
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
top = linelength << 16; /* RGBLEN */ bottom = 0x00000001; if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10; iowrite32(top | bottom , mipi->linkbase + VMLEN1); /* * VMLEN2 = HBPLEN | HFPLEN * * see * Video mode - Blanking Packet setting */ top = 0x00010000; bottom = 0x00000001; delay = 0; |
a2e629715 fbdev: sh_mipi_ds... |
333 334 335 336 337 |
div = 1; /* HSbyteCLK is calculation base * HS4divCLK = HSbyteCLK/2 * HS6divCLK is not supported for now */ if (pdata->flags & SH_MIPI_DSI_HS4divCLK) div = 2; |
08750617b fbdev: sh_mipi_ds... |
338 339 |
if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin; |
a2e629715 fbdev: sh_mipi_ds... |
340 |
top = ((pdata->lane * top / div) - 10) << 16; |
08750617b fbdev: sh_mipi_ds... |
341 342 343 |
} if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ bottom = ch->lcd_cfg[0].right_margin; |
a2e629715 fbdev: sh_mipi_ds... |
344 |
bottom = (pdata->lane * bottom / div) - 12; |
08750617b fbdev: sh_mipi_ds... |
345 346 347 |
} bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */ |
a2e629715 fbdev: sh_mipi_ds... |
348 |
if ((pdata->lane / div) > bpp) { |
08750617b fbdev: sh_mipi_ds... |
349 350 351 352 353 354 |
tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */ tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */ delay = (pdata->lane * tmp); } iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2); |
9fd04fe34 sh-mobile: add su... |
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
msleep(5); /* setup LCD panel */ /* cf. drivers/video/omap/lcd_mipid.c */ sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE); msleep(120); /* * [7] - Page Address Mode * [6] - Column Address Mode * [5] - Page / Column Address Mode * [4] - Display Device Line Refresh Order * [3] - RGB/BGR Order * [2] - Display Data Latch Data Order * [1] - Flip Horizontal * [0] - Flip Vertical */ sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00); /* cf. set_data_lines() */ sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT, pixfmt << 4); sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); |
97cab4558 fbdev: sh_mipi_ds... |
378 379 |
/* Enable timeout counters */ iowrite32(0x00000f00, base + DSICTRL); |
9fd04fe34 sh-mobile: add su... |
380 381 |
return 0; } |
c2658b70f fbdev: sh_mipi_ds... |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
static void mipi_display_on(void *arg, struct fb_info *info) { struct sh_mipi *mipi = arg; struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; int ret; pm_runtime_get_sync(&mipi->pdev->dev); ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1); if (ret < 0) goto mipi_display_on_fail1; ret = sh_mipi_setup(mipi, pdata); if (ret < 0) goto mipi_display_on_fail2; sh_mipi_dsi_enable(mipi, true); if (mipi->next_display_on) mipi->next_display_on(mipi->next_board_data, info); return; mipi_display_on_fail1: pm_runtime_put_sync(&mipi->pdev->dev); mipi_display_on_fail2: pdata->set_dot_clock(mipi->pdev, mipi->base, 0); } static void mipi_display_off(void *arg) { struct sh_mipi *mipi = arg; struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; if (mipi->next_display_off) mipi->next_display_off(mipi->next_board_data); sh_mipi_dsi_enable(mipi, false); pdata->set_dot_clock(mipi->pdev, mipi->base, 0); pm_runtime_put_sync(&mipi->pdev->dev); } |
9fd04fe34 sh-mobile: add su... |
425 426 427 428 429 |
static int __init sh_mipi_probe(struct platform_device *pdev) { struct sh_mipi *mipi; struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
deaba1901 fbdev: sh_mipi_ds... |
430 |
struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
9fd04fe34 sh-mobile: add su... |
431 432 |
unsigned long rate, f_current; int idx = pdev->id, ret; |
9fd04fe34 sh-mobile: add su... |
433 |
|
deaba1901 fbdev: sh_mipi_ds... |
434 |
if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) |
9fd04fe34 sh-mobile: add su... |
435 |
return -ENODEV; |
5e47431aa fbdev: sh_mipi_ds... |
436 437 |
if (!pdata->set_dot_clock) return -EINVAL; |
9fd04fe34 sh-mobile: add su... |
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
mutex_lock(&array_lock); if (idx < 0) for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) ; if (idx == ARRAY_SIZE(mipi_dsi)) { ret = -EBUSY; goto efindslot; } mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); if (!mipi) { ret = -ENOMEM; goto ealloc; } if (!request_mem_region(res->start, resource_size(res), pdev->name)) { dev_err(&pdev->dev, "MIPI register region already claimed "); ret = -EBUSY; goto ereqreg; } mipi->base = ioremap(res->start, resource_size(res)); if (!mipi->base) { ret = -ENOMEM; goto emap; } |
deaba1901 fbdev: sh_mipi_ds... |
466 467 468 469 470 471 472 473 474 475 476 477 |
if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) { dev_err(&pdev->dev, "MIPI register region 2 already claimed "); ret = -EBUSY; goto ereqreg2; } mipi->linkbase = ioremap(res2->start, resource_size(res2)); if (!mipi->linkbase) { ret = -ENOMEM; goto emap2; } |
7d9f88b4f fbdev: sh_mipi_ds... |
478 |
mipi->pdev = pdev; |
236782a5f fbdev: sh-mobile:... |
479 |
|
9fd04fe34 sh-mobile: add su... |
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); if (IS_ERR(mipi->dsit_clk)) { ret = PTR_ERR(mipi->dsit_clk); goto eclktget; } f_current = clk_get_rate(mipi->dsit_clk); /* 80MHz required by the datasheet */ rate = clk_round_rate(mipi->dsit_clk, 80000000); if (rate > 0 && rate != f_current) ret = clk_set_rate(mipi->dsit_clk, rate); else ret = rate; if (ret < 0) goto esettrate; dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu ", f_current, rate); |
9fd04fe34 sh-mobile: add su... |
498 499 500 |
ret = clk_enable(mipi->dsit_clk); if (ret < 0) goto eclkton; |
9fd04fe34 sh-mobile: add su... |
501 |
mipi_dsi[idx] = mipi; |
236782a5f fbdev: sh-mobile:... |
502 503 |
pm_runtime_enable(&pdev->dev); pm_runtime_resume(&pdev->dev); |
9fd04fe34 sh-mobile: add su... |
504 505 |
mutex_unlock(&array_lock); platform_set_drvdata(pdev, mipi); |
6722a4016 fbdev: sh_mipi_ds... |
506 507 508 509 |
/* Save original LCDC callbacks */ mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data; mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on; mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off; |
9fd04fe34 sh-mobile: add su... |
510 511 512 513 |
/* Set up LCDC callbacks */ pdata->lcd_chan->board_cfg.board_data = mipi; pdata->lcd_chan->board_cfg.display_on = mipi_display_on; pdata->lcd_chan->board_cfg.display_off = mipi_display_off; |
236782a5f fbdev: sh-mobile:... |
514 |
pdata->lcd_chan->board_cfg.owner = THIS_MODULE; |
9fd04fe34 sh-mobile: add su... |
515 516 |
return 0; |
9fd04fe34 sh-mobile: add su... |
517 |
eclkton: |
9fd04fe34 sh-mobile: add su... |
518 519 520 |
esettrate: clk_put(mipi->dsit_clk); eclktget: |
deaba1901 fbdev: sh_mipi_ds... |
521 522 523 524 |
iounmap(mipi->linkbase); emap2: release_mem_region(res2->start, resource_size(res2)); ereqreg2: |
9fd04fe34 sh-mobile: add su... |
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
iounmap(mipi->base); emap: release_mem_region(res->start, resource_size(res)); ereqreg: kfree(mipi); ealloc: efindslot: mutex_unlock(&array_lock); return ret; } static int __exit sh_mipi_remove(struct platform_device *pdev) { struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
deaba1901 fbdev: sh_mipi_ds... |
541 |
struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
9fd04fe34 sh-mobile: add su... |
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
struct sh_mipi *mipi = platform_get_drvdata(pdev); int i, ret; mutex_lock(&array_lock); for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++) ; if (i == ARRAY_SIZE(mipi_dsi)) { ret = -EINVAL; } else { ret = 0; mipi_dsi[i] = NULL; } mutex_unlock(&array_lock); if (ret < 0) return ret; |
236782a5f fbdev: sh-mobile:... |
561 |
pdata->lcd_chan->board_cfg.owner = NULL; |
9fd04fe34 sh-mobile: add su... |
562 563 564 |
pdata->lcd_chan->board_cfg.display_on = NULL; pdata->lcd_chan->board_cfg.display_off = NULL; pdata->lcd_chan->board_cfg.board_data = NULL; |
236782a5f fbdev: sh-mobile:... |
565 |
pm_runtime_disable(&pdev->dev); |
9fd04fe34 sh-mobile: add su... |
566 567 |
clk_disable(mipi->dsit_clk); clk_put(mipi->dsit_clk); |
5e47431aa fbdev: sh_mipi_ds... |
568 |
|
deaba1901 fbdev: sh_mipi_ds... |
569 570 571 |
iounmap(mipi->linkbase); if (res2) release_mem_region(res2->start, resource_size(res2)); |
9fd04fe34 sh-mobile: add su... |
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 |
iounmap(mipi->base); if (res) release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); kfree(mipi); return 0; } static struct platform_driver sh_mipi_driver = { .remove = __exit_p(sh_mipi_remove), .shutdown = sh_mipi_shutdown, .driver = { .name = "sh-mipi-dsi", }, }; static int __init sh_mipi_init(void) { return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe); } module_init(sh_mipi_init); static void __exit sh_mipi_exit(void) { platform_driver_unregister(&sh_mipi_driver); } module_exit(sh_mipi_exit); MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); MODULE_LICENSE("GPL v2"); |