]>
Commit | Line | Data |
---|---|---|
420c34e4 RK |
1 | #include <linux/device.h> |
2 | #include <linux/dma-mapping.h> | |
3 | #include <linux/amba/bus.h> | |
4 | #include <linux/amba/clcd.h> | |
11c32d7b | 5 | #include <linux/platform_data/video-clcd-versatile.h> |
25348160 LW |
6 | #include <linux/of.h> |
7 | #include <linux/of_graph.h> | |
8 | #include <linux/regmap.h> | |
9 | #include <linux/mfd/syscon.h> | |
10 | #include <linux/bitops.h> | |
11 | #include "amba-clcd-versatile.h" | |
420c34e4 RK |
12 | |
13 | static struct clcd_panel vga = { | |
14 | .mode = { | |
15 | .name = "VGA", | |
16 | .refresh = 60, | |
17 | .xres = 640, | |
18 | .yres = 480, | |
19 | .pixclock = 39721, | |
20 | .left_margin = 40, | |
21 | .right_margin = 24, | |
22 | .upper_margin = 32, | |
23 | .lower_margin = 11, | |
24 | .hsync_len = 96, | |
25 | .vsync_len = 2, | |
26 | .sync = 0, | |
27 | .vmode = FB_VMODE_NONINTERLACED, | |
28 | }, | |
29 | .width = -1, | |
30 | .height = -1, | |
31 | .tim2 = TIM2_BCD | TIM2_IPC, | |
32 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | |
33 | .caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888, | |
34 | .bpp = 16, | |
35 | }; | |
36 | ||
37 | static struct clcd_panel xvga = { | |
38 | .mode = { | |
39 | .name = "XVGA", | |
40 | .refresh = 60, | |
41 | .xres = 1024, | |
42 | .yres = 768, | |
43 | .pixclock = 15748, | |
44 | .left_margin = 152, | |
45 | .right_margin = 48, | |
46 | .upper_margin = 23, | |
47 | .lower_margin = 3, | |
48 | .hsync_len = 104, | |
49 | .vsync_len = 4, | |
50 | .sync = 0, | |
51 | .vmode = FB_VMODE_NONINTERLACED, | |
52 | }, | |
53 | .width = -1, | |
54 | .height = -1, | |
55 | .tim2 = TIM2_BCD | TIM2_IPC, | |
56 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | |
57 | .caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888, | |
58 | .bpp = 16, | |
59 | }; | |
60 | ||
61 | /* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */ | |
62 | static struct clcd_panel sanyo_tm38qv67a02a = { | |
63 | .mode = { | |
64 | .name = "Sanyo TM38QV67A02A", | |
65 | .refresh = 116, | |
66 | .xres = 320, | |
67 | .yres = 240, | |
68 | .pixclock = 100000, | |
69 | .left_margin = 6, | |
70 | .right_margin = 6, | |
71 | .upper_margin = 5, | |
72 | .lower_margin = 5, | |
73 | .hsync_len = 6, | |
74 | .vsync_len = 6, | |
75 | .sync = 0, | |
76 | .vmode = FB_VMODE_NONINTERLACED, | |
77 | }, | |
78 | .width = -1, | |
79 | .height = -1, | |
80 | .tim2 = TIM2_BCD, | |
81 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | |
82 | .caps = CLCD_CAP_5551, | |
83 | .bpp = 16, | |
84 | }; | |
85 | ||
86 | static struct clcd_panel sanyo_2_5_in = { | |
87 | .mode = { | |
88 | .name = "Sanyo QVGA Portrait", | |
89 | .refresh = 116, | |
90 | .xres = 240, | |
91 | .yres = 320, | |
92 | .pixclock = 100000, | |
93 | .left_margin = 20, | |
94 | .right_margin = 10, | |
95 | .upper_margin = 2, | |
96 | .lower_margin = 2, | |
97 | .hsync_len = 10, | |
98 | .vsync_len = 2, | |
99 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | |
100 | .vmode = FB_VMODE_NONINTERLACED, | |
101 | }, | |
102 | .width = -1, | |
103 | .height = -1, | |
104 | .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, | |
105 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | |
106 | .caps = CLCD_CAP_5551, | |
107 | .bpp = 16, | |
108 | }; | |
109 | ||
110 | /* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */ | |
111 | static struct clcd_panel epson_l2f50113t00 = { | |
112 | .mode = { | |
113 | .name = "Epson L2F50113T00", | |
114 | .refresh = 390, | |
115 | .xres = 176, | |
116 | .yres = 220, | |
117 | .pixclock = 62500, | |
118 | .left_margin = 3, | |
119 | .right_margin = 2, | |
120 | .upper_margin = 1, | |
121 | .lower_margin = 0, | |
122 | .hsync_len = 3, | |
123 | .vsync_len = 2, | |
124 | .sync = 0, | |
125 | .vmode = FB_VMODE_NONINTERLACED, | |
126 | }, | |
127 | .width = -1, | |
128 | .height = -1, | |
129 | .tim2 = TIM2_BCD | TIM2_IPC, | |
130 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | |
131 | .caps = CLCD_CAP_5551, | |
132 | .bpp = 16, | |
133 | }; | |
134 | ||
135 | static struct clcd_panel *panels[] = { | |
136 | &vga, | |
137 | &xvga, | |
138 | &sanyo_tm38qv67a02a, | |
139 | &sanyo_2_5_in, | |
140 | &epson_l2f50113t00, | |
141 | }; | |
142 | ||
143 | struct clcd_panel *versatile_clcd_get_panel(const char *name) | |
144 | { | |
145 | int i; | |
146 | ||
147 | for (i = 0; i < ARRAY_SIZE(panels); i++) | |
148 | if (strcmp(panels[i]->mode.name, name) == 0) | |
149 | break; | |
150 | ||
151 | if (i < ARRAY_SIZE(panels)) | |
152 | return panels[i]; | |
153 | ||
154 | pr_err("CLCD: couldn't get parameters for panel %s\n", name); | |
155 | ||
156 | return NULL; | |
157 | } | |
158 | ||
159 | int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize) | |
160 | { | |
161 | dma_addr_t dma; | |
162 | ||
f6e45661 LR |
163 | fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, framesize, &dma, |
164 | GFP_KERNEL); | |
420c34e4 RK |
165 | if (!fb->fb.screen_base) { |
166 | pr_err("CLCD: unable to map framebuffer\n"); | |
167 | return -ENOMEM; | |
168 | } | |
169 | ||
170 | fb->fb.fix.smem_start = dma; | |
171 | fb->fb.fix.smem_len = framesize; | |
172 | ||
173 | return 0; | |
174 | } | |
175 | ||
176 | int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma) | |
177 | { | |
f6e45661 LR |
178 | return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base, |
179 | fb->fb.fix.smem_start, fb->fb.fix.smem_len); | |
420c34e4 RK |
180 | } |
181 | ||
182 | void versatile_clcd_remove_dma(struct clcd_fb *fb) | |
183 | { | |
f6e45661 LR |
184 | dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base, |
185 | fb->fb.fix.smem_start); | |
420c34e4 | 186 | } |
25348160 LW |
187 | |
188 | #ifdef CONFIG_OF | |
189 | ||
190 | static struct regmap *versatile_syscon_map; | |
191 | static struct regmap *versatile_ib2_map; | |
192 | ||
193 | /* | |
194 | * We detect the different syscon types from the compatible strings. | |
195 | */ | |
196 | enum versatile_clcd { | |
197 | INTEGRATOR_CLCD_CM, | |
198 | VERSATILE_CLCD, | |
199 | REALVIEW_CLCD_EB, | |
200 | REALVIEW_CLCD_PB1176, | |
201 | REALVIEW_CLCD_PB11MP, | |
202 | REALVIEW_CLCD_PBA8, | |
203 | REALVIEW_CLCD_PBX, | |
204 | }; | |
205 | ||
206 | static const struct of_device_id versatile_clcd_of_match[] = { | |
207 | { | |
208 | .compatible = "arm,core-module-integrator", | |
209 | .data = (void *)INTEGRATOR_CLCD_CM, | |
210 | }, | |
211 | { | |
212 | .compatible = "arm,versatile-sysreg", | |
213 | .data = (void *)VERSATILE_CLCD, | |
214 | }, | |
215 | { | |
216 | .compatible = "arm,realview-eb-syscon", | |
217 | .data = (void *)REALVIEW_CLCD_EB, | |
218 | }, | |
219 | { | |
220 | .compatible = "arm,realview-pb1176-syscon", | |
221 | .data = (void *)REALVIEW_CLCD_PB1176, | |
222 | }, | |
223 | { | |
224 | .compatible = "arm,realview-pb11mp-syscon", | |
225 | .data = (void *)REALVIEW_CLCD_PB11MP, | |
226 | }, | |
227 | { | |
228 | .compatible = "arm,realview-pba8-syscon", | |
229 | .data = (void *)REALVIEW_CLCD_PBA8, | |
230 | }, | |
231 | { | |
232 | .compatible = "arm,realview-pbx-syscon", | |
233 | .data = (void *)REALVIEW_CLCD_PBX, | |
234 | }, | |
235 | {}, | |
236 | }; | |
237 | ||
238 | /* | |
239 | * Core module CLCD control on the Integrator/CP, bits | |
240 | * 8 thru 19 of the CM_CONTROL register controls a bunch | |
241 | * of CLCD settings. | |
242 | */ | |
243 | #define INTEGRATOR_HDR_CTRL_OFFSET 0x0C | |
244 | #define INTEGRATOR_CLCD_LCDBIASEN BIT(8) | |
245 | #define INTEGRATOR_CLCD_LCDBIASUP BIT(9) | |
246 | #define INTEGRATOR_CLCD_LCDBIASDN BIT(10) | |
247 | /* Bits 11,12,13 controls the LCD type */ | |
248 | #define INTEGRATOR_CLCD_LCDMUX_MASK (BIT(11)|BIT(12)|BIT(13)) | |
249 | #define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11) | |
250 | #define INTEGRATOR_CLCD_LCDMUX_VGA565 BIT(12) | |
251 | #define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12)) | |
252 | #define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13) | |
253 | #define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13)) | |
254 | #define INTEGRATOR_CLCD_LCD0_EN BIT(14) | |
255 | #define INTEGRATOR_CLCD_LCD1_EN BIT(15) | |
256 | /* R/L flip on Sharp */ | |
257 | #define INTEGRATOR_CLCD_LCD_STATIC1 BIT(16) | |
258 | /* U/D flip on Sharp */ | |
259 | #define INTEGRATOR_CLCD_LCD_STATIC2 BIT(17) | |
260 | /* No connection on Sharp */ | |
261 | #define INTEGRATOR_CLCD_LCD_STATIC BIT(18) | |
262 | /* 0 = 24bit VGA, 1 = 18bit VGA */ | |
263 | #define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19) | |
264 | ||
9986908d LW |
265 | #define INTEGRATOR_CLCD_MASK (INTEGRATOR_CLCD_LCDBIASEN | \ |
266 | INTEGRATOR_CLCD_LCDBIASUP | \ | |
267 | INTEGRATOR_CLCD_LCDBIASDN | \ | |
268 | INTEGRATOR_CLCD_LCDMUX_MASK | \ | |
25348160 LW |
269 | INTEGRATOR_CLCD_LCD0_EN | \ |
270 | INTEGRATOR_CLCD_LCD1_EN | \ | |
271 | INTEGRATOR_CLCD_LCD_STATIC1 | \ | |
272 | INTEGRATOR_CLCD_LCD_STATIC2 | \ | |
273 | INTEGRATOR_CLCD_LCD_STATIC | \ | |
274 | INTEGRATOR_CLCD_LCD_N24BITEN) | |
275 | ||
276 | static void integrator_clcd_enable(struct clcd_fb *fb) | |
277 | { | |
278 | struct fb_var_screeninfo *var = &fb->fb.var; | |
279 | u32 val; | |
280 | ||
281 | dev_info(&fb->dev->dev, "enable Integrator CLCD connectors\n"); | |
282 | ||
9986908d | 283 | /* FIXME: really needed? */ |
25348160 LW |
284 | val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 | |
285 | INTEGRATOR_CLCD_LCD0_EN | INTEGRATOR_CLCD_LCD1_EN; | |
286 | if (var->bits_per_pixel <= 8 || | |
287 | (var->bits_per_pixel == 16 && var->green.length == 5)) | |
288 | /* Pseudocolor, RGB555, BGR555 */ | |
289 | val |= INTEGRATOR_CLCD_LCDMUX_VGA555; | |
290 | else if (fb->fb.var.bits_per_pixel <= 16) | |
291 | /* truecolor RGB565 */ | |
292 | val |= INTEGRATOR_CLCD_LCDMUX_VGA565; | |
293 | else | |
294 | val = 0; /* no idea for this, don't trust the docs */ | |
295 | ||
296 | regmap_update_bits(versatile_syscon_map, | |
297 | INTEGRATOR_HDR_CTRL_OFFSET, | |
9986908d LW |
298 | INTEGRATOR_CLCD_MASK, |
299 | val); | |
25348160 LW |
300 | } |
301 | ||
302 | /* | |
303 | * This configuration register in the Versatile and RealView | |
304 | * family is uniformly present but appears more and more | |
305 | * unutilized starting with the RealView series. | |
306 | */ | |
307 | #define SYS_CLCD 0x50 | |
308 | #define SYS_CLCD_MODE_MASK (BIT(0)|BIT(1)) | |
309 | #define SYS_CLCD_MODE_888 0 | |
310 | #define SYS_CLCD_MODE_5551 BIT(0) | |
311 | #define SYS_CLCD_MODE_565_R_LSB BIT(1) | |
312 | #define SYS_CLCD_MODE_565_B_LSB (BIT(0)|BIT(1)) | |
313 | #define SYS_CLCD_CONNECTOR_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5)) | |
314 | #define SYS_CLCD_NLCDIOON BIT(2) | |
315 | #define SYS_CLCD_VDDPOSSWITCH BIT(3) | |
316 | #define SYS_CLCD_PWR3V5SWITCH BIT(4) | |
317 | #define SYS_CLCD_VDDNEGSWITCH BIT(5) | |
318 | #define SYS_CLCD_TSNSS BIT(6) /* touchscreen enable */ | |
319 | #define SYS_CLCD_SSPEXP BIT(7) /* SSP expansion enable */ | |
320 | ||
321 | /* The Versatile can detect the connected panel type */ | |
322 | #define SYS_CLCD_CLCDID_MASK (BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)) | |
323 | #define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8) | |
324 | #define SYS_CLCD_ID_SHARP_8_4 (0x01 << 8) | |
325 | #define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8) | |
326 | #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) | |
327 | #define SYS_CLCD_ID_VGA (0x1f << 8) | |
328 | ||
329 | #define SYS_CLCD_TSNDAV BIT(13) /* data ready from TS */ | |
330 | ||
331 | /* IB2 control register for the Versatile daughterboard */ | |
332 | #define IB2_CTRL 0x00 | |
333 | #define IB2_CTRL_LCD_SD BIT(1) /* 1 = shut down LCD */ | |
334 | #define IB2_CTRL_LCD_BL_ON BIT(0) | |
335 | #define IB2_CTRL_LCD_MASK (BIT(0)|BIT(1)) | |
336 | ||
337 | static void versatile_clcd_disable(struct clcd_fb *fb) | |
338 | { | |
339 | dev_info(&fb->dev->dev, "disable Versatile CLCD connectors\n"); | |
340 | regmap_update_bits(versatile_syscon_map, | |
341 | SYS_CLCD, | |
342 | SYS_CLCD_CONNECTOR_MASK, | |
343 | 0); | |
344 | ||
345 | /* If we're on an IB2 daughterboard, turn off display */ | |
346 | if (versatile_ib2_map) { | |
347 | dev_info(&fb->dev->dev, "disable IB2 display\n"); | |
348 | regmap_update_bits(versatile_ib2_map, | |
349 | IB2_CTRL, | |
350 | IB2_CTRL_LCD_MASK, | |
351 | IB2_CTRL_LCD_SD); | |
352 | } | |
353 | } | |
354 | ||
355 | static void versatile_clcd_enable(struct clcd_fb *fb) | |
356 | { | |
357 | struct fb_var_screeninfo *var = &fb->fb.var; | |
358 | u32 val = 0; | |
359 | ||
360 | dev_info(&fb->dev->dev, "enable Versatile CLCD connectors\n"); | |
361 | switch (var->green.length) { | |
362 | case 5: | |
363 | val |= SYS_CLCD_MODE_5551; | |
364 | break; | |
365 | case 6: | |
366 | if (var->red.offset == 0) | |
367 | val |= SYS_CLCD_MODE_565_R_LSB; | |
368 | else | |
369 | val |= SYS_CLCD_MODE_565_B_LSB; | |
370 | break; | |
371 | case 8: | |
372 | val |= SYS_CLCD_MODE_888; | |
373 | break; | |
374 | } | |
375 | ||
376 | /* Set up the MUX */ | |
377 | regmap_update_bits(versatile_syscon_map, | |
378 | SYS_CLCD, | |
379 | SYS_CLCD_MODE_MASK, | |
380 | val); | |
381 | ||
382 | /* Then enable the display */ | |
383 | regmap_update_bits(versatile_syscon_map, | |
384 | SYS_CLCD, | |
385 | SYS_CLCD_CONNECTOR_MASK, | |
386 | SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); | |
387 | ||
388 | /* If we're on an IB2 daughterboard, turn on display */ | |
389 | if (versatile_ib2_map) { | |
390 | dev_info(&fb->dev->dev, "enable IB2 display\n"); | |
391 | regmap_update_bits(versatile_ib2_map, | |
392 | IB2_CTRL, | |
393 | IB2_CTRL_LCD_MASK, | |
394 | IB2_CTRL_LCD_BL_ON); | |
395 | } | |
396 | } | |
397 | ||
398 | static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs) | |
399 | { | |
400 | clcdfb_decode(fb, regs); | |
401 | ||
402 | /* Always clear BGR for RGB565: we do the routing externally */ | |
403 | if (fb->fb.var.green.length == 6) | |
404 | regs->cntl &= ~CNTL_BGR; | |
405 | } | |
406 | ||
407 | static void realview_clcd_disable(struct clcd_fb *fb) | |
408 | { | |
409 | dev_info(&fb->dev->dev, "disable RealView CLCD connectors\n"); | |
410 | regmap_update_bits(versatile_syscon_map, | |
411 | SYS_CLCD, | |
412 | SYS_CLCD_CONNECTOR_MASK, | |
413 | 0); | |
414 | } | |
415 | ||
416 | static void realview_clcd_enable(struct clcd_fb *fb) | |
417 | { | |
418 | dev_info(&fb->dev->dev, "enable RealView CLCD connectors\n"); | |
419 | regmap_update_bits(versatile_syscon_map, | |
420 | SYS_CLCD, | |
421 | SYS_CLCD_CONNECTOR_MASK, | |
422 | SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); | |
423 | } | |
424 | ||
425 | struct versatile_panel { | |
426 | u32 id; | |
427 | char *compatible; | |
428 | bool ib2; | |
429 | }; | |
430 | ||
431 | static const struct versatile_panel versatile_panels[] = { | |
432 | { | |
433 | .id = SYS_CLCD_ID_VGA, | |
434 | .compatible = "VGA", | |
435 | }, | |
436 | { | |
437 | .id = SYS_CLCD_ID_SANYO_3_8, | |
438 | .compatible = "sanyo,tm38qv67a02a", | |
439 | }, | |
440 | { | |
441 | .id = SYS_CLCD_ID_SHARP_8_4, | |
442 | .compatible = "sharp,lq084v1dg21", | |
443 | }, | |
444 | { | |
445 | .id = SYS_CLCD_ID_EPSON_2_2, | |
446 | .compatible = "epson,l2f50113t00", | |
447 | }, | |
448 | { | |
449 | .id = SYS_CLCD_ID_SANYO_2_5, | |
450 | .compatible = "sanyo,alr252rgt", | |
451 | .ib2 = true, | |
452 | }, | |
453 | }; | |
454 | ||
455 | static void versatile_panel_probe(struct device *dev, | |
456 | struct device_node *endpoint) | |
457 | { | |
458 | struct versatile_panel const *vpanel = NULL; | |
459 | struct device_node *panel = NULL; | |
460 | u32 val; | |
461 | int ret; | |
462 | int i; | |
463 | ||
464 | /* | |
465 | * The Versatile CLCD has a panel auto-detection mechanism. | |
466 | * We use this and look for the compatible panel in the | |
467 | * device tree. | |
468 | */ | |
469 | ret = regmap_read(versatile_syscon_map, SYS_CLCD, &val); | |
470 | if (ret) { | |
471 | dev_err(dev, "cannot read CLCD syscon register\n"); | |
472 | return; | |
473 | } | |
474 | val &= SYS_CLCD_CLCDID_MASK; | |
475 | ||
476 | /* First find corresponding panel information */ | |
477 | for (i = 0; i < ARRAY_SIZE(versatile_panels); i++) { | |
478 | vpanel = &versatile_panels[i]; | |
479 | ||
480 | if (val == vpanel->id) { | |
481 | dev_err(dev, "autodetected panel \"%s\"\n", | |
482 | vpanel->compatible); | |
483 | break; | |
484 | } | |
485 | } | |
486 | if (i == ARRAY_SIZE(versatile_panels)) { | |
487 | dev_err(dev, "could not auto-detect panel\n"); | |
488 | return; | |
489 | } | |
490 | ||
491 | panel = of_graph_get_remote_port_parent(endpoint); | |
492 | if (!panel) { | |
493 | dev_err(dev, "could not locate panel in DT\n"); | |
494 | return; | |
495 | } | |
496 | if (!of_device_is_compatible(panel, vpanel->compatible)) | |
497 | dev_err(dev, "panel in DT is not compatible with the " | |
498 | "auto-detected panel, continuing anyway\n"); | |
499 | ||
500 | /* | |
501 | * If we have a Sanyo 2.5" port | |
502 | * that we're running on an IB2 and proceed to look for the | |
503 | * IB2 syscon regmap. | |
504 | */ | |
505 | if (!vpanel->ib2) | |
506 | return; | |
507 | ||
508 | versatile_ib2_map = syscon_regmap_lookup_by_compatible( | |
509 | "arm,versatile-ib2-syscon"); | |
510 | if (IS_ERR(versatile_ib2_map)) { | |
511 | dev_err(dev, "could not locate IB2 control register\n"); | |
512 | versatile_ib2_map = NULL; | |
513 | return; | |
514 | } | |
515 | } | |
516 | ||
517 | int versatile_clcd_init_panel(struct clcd_fb *fb, | |
518 | struct device_node *endpoint) | |
519 | { | |
520 | const struct of_device_id *clcd_id; | |
521 | enum versatile_clcd versatile_clcd_type; | |
522 | struct device_node *np; | |
523 | struct regmap *map; | |
524 | struct device *dev = &fb->dev->dev; | |
525 | ||
526 | np = of_find_matching_node_and_match(NULL, versatile_clcd_of_match, | |
527 | &clcd_id); | |
528 | if (!np) { | |
cfbd950d LW |
529 | /* Vexpress does not have this */ |
530 | return 0; | |
25348160 LW |
531 | } |
532 | versatile_clcd_type = (enum versatile_clcd)clcd_id->data; | |
533 | ||
534 | map = syscon_node_to_regmap(np); | |
763e6366 | 535 | if (IS_ERR(map)) { |
25348160 | 536 | dev_err(dev, "no Versatile syscon regmap\n"); |
763e6366 | 537 | return PTR_ERR(map); |
25348160 LW |
538 | } |
539 | ||
540 | switch (versatile_clcd_type) { | |
541 | case INTEGRATOR_CLCD_CM: | |
542 | versatile_syscon_map = map; | |
543 | fb->board->enable = integrator_clcd_enable; | |
544 | /* Override the caps, we have only these */ | |
545 | fb->board->caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | | |
546 | CLCD_CAP_888; | |
547 | dev_info(dev, "set up callbacks for Integrator PL110\n"); | |
548 | break; | |
549 | case VERSATILE_CLCD: | |
550 | versatile_syscon_map = map; | |
551 | fb->board->enable = versatile_clcd_enable; | |
552 | fb->board->disable = versatile_clcd_disable; | |
553 | fb->board->decode = versatile_clcd_decode; | |
554 | versatile_panel_probe(dev, endpoint); | |
555 | dev_info(dev, "set up callbacks for Versatile\n"); | |
556 | break; | |
557 | case REALVIEW_CLCD_EB: | |
558 | case REALVIEW_CLCD_PB1176: | |
559 | case REALVIEW_CLCD_PB11MP: | |
560 | case REALVIEW_CLCD_PBA8: | |
561 | case REALVIEW_CLCD_PBX: | |
562 | versatile_syscon_map = map; | |
563 | fb->board->enable = realview_clcd_enable; | |
564 | fb->board->disable = realview_clcd_disable; | |
565 | dev_info(dev, "set up callbacks for RealView PL111\n"); | |
566 | break; | |
567 | default: | |
568 | dev_info(dev, "unknown Versatile system controller\n"); | |
569 | break; | |
570 | } | |
571 | ||
572 | return 0; | |
573 | } | |
ffe439d6 | 574 | EXPORT_SYMBOL_GPL(versatile_clcd_init_panel); |
25348160 | 575 | #endif |