1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | |
3 | /* |
4 | * Versatile family (ARM reference designs) handling for the PL11x. |
5 | * This is based on code and know-how in the previous frame buffer |
6 | * driver in drivers/video/fbdev/amba-clcd.c: |
7 | * Copyright (C) 2001 ARM Limited, by David A Rusling |
8 | * Updated to 2.5 by Deep Blue Solutions Ltd. |
9 | * Major contributions and discoveries by Russell King. |
10 | */ |
11 | |
12 | #include <linux/bitops.h> |
13 | #include <linux/device.h> |
14 | #include <linux/mfd/syscon.h> |
15 | #include <linux/module.h> |
16 | #include <linux/of.h> |
17 | #include <linux/of_platform.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/vexpress.h> |
21 | |
22 | #include <drm/drm_fourcc.h> |
23 | |
24 | #include "pl111_versatile.h" |
25 | #include "pl111_drm.h" |
26 | |
27 | static struct regmap *versatile_syscon_map; |
28 | |
29 | /* |
30 | * We detect the different syscon types from the compatible strings. |
31 | */ |
32 | enum versatile_clcd { |
33 | INTEGRATOR_IMPD1, |
34 | INTEGRATOR_CLCD_CM, |
35 | VERSATILE_CLCD, |
36 | REALVIEW_CLCD_EB, |
37 | REALVIEW_CLCD_PB1176, |
38 | REALVIEW_CLCD_PB11MP, |
39 | REALVIEW_CLCD_PBA8, |
40 | REALVIEW_CLCD_PBX, |
41 | VEXPRESS_CLCD_V2M, |
42 | }; |
43 | |
44 | static const struct of_device_id versatile_clcd_of_match[] = { |
45 | { |
46 | .compatible = "arm,core-module-integrator" , |
47 | .data = (void *)INTEGRATOR_CLCD_CM, |
48 | }, |
49 | { |
50 | .compatible = "arm,versatile-sysreg" , |
51 | .data = (void *)VERSATILE_CLCD, |
52 | }, |
53 | { |
54 | .compatible = "arm,realview-eb-syscon" , |
55 | .data = (void *)REALVIEW_CLCD_EB, |
56 | }, |
57 | { |
58 | .compatible = "arm,realview-pb1176-syscon" , |
59 | .data = (void *)REALVIEW_CLCD_PB1176, |
60 | }, |
61 | { |
62 | .compatible = "arm,realview-pb11mp-syscon" , |
63 | .data = (void *)REALVIEW_CLCD_PB11MP, |
64 | }, |
65 | { |
66 | .compatible = "arm,realview-pba8-syscon" , |
67 | .data = (void *)REALVIEW_CLCD_PBA8, |
68 | }, |
69 | { |
70 | .compatible = "arm,realview-pbx-syscon" , |
71 | .data = (void *)REALVIEW_CLCD_PBX, |
72 | }, |
73 | { |
74 | .compatible = "arm,vexpress-muxfpga" , |
75 | .data = (void *)VEXPRESS_CLCD_V2M, |
76 | }, |
77 | {}, |
78 | }; |
79 | |
80 | static const struct of_device_id impd1_clcd_of_match[] = { |
81 | { |
82 | .compatible = "arm,im-pd1-syscon" , |
83 | .data = (void *)INTEGRATOR_IMPD1, |
84 | }, |
85 | {}, |
86 | }; |
87 | |
88 | /* |
89 | * Core module CLCD control on the Integrator/CP, bits |
90 | * 8 thru 19 of the CM_CONTROL register controls a bunch |
91 | * of CLCD settings. |
92 | */ |
93 | #define INTEGRATOR_HDR_CTRL_OFFSET 0x0C |
94 | #define INTEGRATOR_CLCD_LCDBIASEN BIT(8) |
95 | #define INTEGRATOR_CLCD_LCDBIASUP BIT(9) |
96 | #define INTEGRATOR_CLCD_LCDBIASDN BIT(10) |
97 | /* Bits 11,12,13 controls the LCD or VGA bridge type */ |
98 | #define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11) |
99 | #define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12)) |
100 | #define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13) |
101 | #define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13)) |
102 | #define INTEGRATOR_CLCD_LCD0_EN BIT(14) |
103 | #define INTEGRATOR_CLCD_LCD1_EN BIT(15) |
104 | /* R/L flip on Sharp */ |
105 | #define INTEGRATOR_CLCD_LCD_STATIC1 BIT(16) |
106 | /* U/D flip on Sharp */ |
107 | #define INTEGRATOR_CLCD_LCD_STATIC2 BIT(17) |
108 | /* No connection on Sharp */ |
109 | #define INTEGRATOR_CLCD_LCD_STATIC BIT(18) |
110 | /* 0 = 24bit VGA, 1 = 18bit VGA */ |
111 | #define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19) |
112 | |
113 | #define INTEGRATOR_CLCD_MASK GENMASK(19, 8) |
114 | |
115 | static void pl111_integrator_enable(struct drm_device *drm, u32 format) |
116 | { |
117 | u32 val; |
118 | |
119 | dev_info(drm->dev, "enable Integrator CLCD connectors\n" ); |
120 | |
121 | /* FIXME: really needed? */ |
122 | val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 | |
123 | INTEGRATOR_CLCD_LCD0_EN | INTEGRATOR_CLCD_LCD1_EN; |
124 | |
125 | switch (format) { |
126 | case DRM_FORMAT_XBGR8888: |
127 | case DRM_FORMAT_XRGB8888: |
128 | /* 24bit formats */ |
129 | val |= INTEGRATOR_CLCD_LCDMUX_VGA24; |
130 | break; |
131 | case DRM_FORMAT_XBGR1555: |
132 | case DRM_FORMAT_XRGB1555: |
133 | /* Pseudocolor, RGB555, BGR555 */ |
134 | val |= INTEGRATOR_CLCD_LCDMUX_VGA555; |
135 | break; |
136 | default: |
137 | dev_err(drm->dev, "unhandled format on Integrator 0x%08x\n" , |
138 | format); |
139 | break; |
140 | } |
141 | |
142 | regmap_update_bits(map: versatile_syscon_map, |
143 | INTEGRATOR_HDR_CTRL_OFFSET, |
144 | INTEGRATOR_CLCD_MASK, |
145 | val); |
146 | } |
147 | |
148 | #define IMPD1_CTRL_OFFSET 0x18 |
149 | #define IMPD1_CTRL_DISP_LCD (0 << 0) |
150 | #define IMPD1_CTRL_DISP_VGA (1 << 0) |
151 | #define IMPD1_CTRL_DISP_LCD1 (2 << 0) |
152 | #define IMPD1_CTRL_DISP_ENABLE (1 << 2) |
153 | #define IMPD1_CTRL_DISP_MASK (7 << 0) |
154 | |
155 | static void pl111_impd1_enable(struct drm_device *drm, u32 format) |
156 | { |
157 | u32 val; |
158 | |
159 | dev_info(drm->dev, "enable IM-PD1 CLCD connectors\n" ); |
160 | val = IMPD1_CTRL_DISP_VGA | IMPD1_CTRL_DISP_ENABLE; |
161 | |
162 | regmap_update_bits(map: versatile_syscon_map, |
163 | IMPD1_CTRL_OFFSET, |
164 | IMPD1_CTRL_DISP_MASK, |
165 | val); |
166 | } |
167 | |
168 | static void pl111_impd1_disable(struct drm_device *drm) |
169 | { |
170 | dev_info(drm->dev, "disable IM-PD1 CLCD connectors\n" ); |
171 | |
172 | regmap_update_bits(map: versatile_syscon_map, |
173 | IMPD1_CTRL_OFFSET, |
174 | IMPD1_CTRL_DISP_MASK, |
175 | val: 0); |
176 | } |
177 | |
178 | /* |
179 | * This configuration register in the Versatile and RealView |
180 | * family is uniformly present but appears more and more |
181 | * unutilized starting with the RealView series. |
182 | */ |
183 | #define SYS_CLCD 0x50 |
184 | #define SYS_CLCD_MODE_MASK (BIT(0)|BIT(1)) |
185 | #define SYS_CLCD_MODE_888 0 |
186 | #define SYS_CLCD_MODE_5551 BIT(0) |
187 | #define SYS_CLCD_MODE_565_R_LSB BIT(1) |
188 | #define SYS_CLCD_MODE_565_B_LSB (BIT(0)|BIT(1)) |
189 | #define SYS_CLCD_CONNECTOR_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5)) |
190 | #define SYS_CLCD_NLCDIOON BIT(2) |
191 | #define SYS_CLCD_VDDPOSSWITCH BIT(3) |
192 | #define SYS_CLCD_PWR3V5SWITCH BIT(4) |
193 | #define SYS_CLCD_VDDNEGSWITCH BIT(5) |
194 | |
195 | static void pl111_versatile_disable(struct drm_device *drm) |
196 | { |
197 | dev_info(drm->dev, "disable Versatile CLCD connectors\n" ); |
198 | regmap_update_bits(map: versatile_syscon_map, |
199 | SYS_CLCD, |
200 | SYS_CLCD_CONNECTOR_MASK, |
201 | val: 0); |
202 | } |
203 | |
204 | static void pl111_versatile_enable(struct drm_device *drm, u32 format) |
205 | { |
206 | u32 val = 0; |
207 | |
208 | dev_info(drm->dev, "enable Versatile CLCD connectors\n" ); |
209 | |
210 | switch (format) { |
211 | case DRM_FORMAT_ABGR8888: |
212 | case DRM_FORMAT_XBGR8888: |
213 | case DRM_FORMAT_ARGB8888: |
214 | case DRM_FORMAT_XRGB8888: |
215 | val |= SYS_CLCD_MODE_888; |
216 | break; |
217 | case DRM_FORMAT_BGR565: |
218 | val |= SYS_CLCD_MODE_565_R_LSB; |
219 | break; |
220 | case DRM_FORMAT_RGB565: |
221 | val |= SYS_CLCD_MODE_565_B_LSB; |
222 | break; |
223 | case DRM_FORMAT_ABGR1555: |
224 | case DRM_FORMAT_XBGR1555: |
225 | case DRM_FORMAT_ARGB1555: |
226 | case DRM_FORMAT_XRGB1555: |
227 | val |= SYS_CLCD_MODE_5551; |
228 | break; |
229 | default: |
230 | dev_err(drm->dev, "unhandled format on Versatile 0x%08x\n" , |
231 | format); |
232 | break; |
233 | } |
234 | |
235 | /* Set up the MUX */ |
236 | regmap_update_bits(map: versatile_syscon_map, |
237 | SYS_CLCD, |
238 | SYS_CLCD_MODE_MASK, |
239 | val); |
240 | |
241 | /* Then enable the display */ |
242 | regmap_update_bits(map: versatile_syscon_map, |
243 | SYS_CLCD, |
244 | SYS_CLCD_CONNECTOR_MASK, |
245 | SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); |
246 | } |
247 | |
248 | static void pl111_realview_clcd_disable(struct drm_device *drm) |
249 | { |
250 | dev_info(drm->dev, "disable RealView CLCD connectors\n" ); |
251 | regmap_update_bits(map: versatile_syscon_map, |
252 | SYS_CLCD, |
253 | SYS_CLCD_CONNECTOR_MASK, |
254 | val: 0); |
255 | } |
256 | |
257 | static void pl111_realview_clcd_enable(struct drm_device *drm, u32 format) |
258 | { |
259 | dev_info(drm->dev, "enable RealView CLCD connectors\n" ); |
260 | regmap_update_bits(map: versatile_syscon_map, |
261 | SYS_CLCD, |
262 | SYS_CLCD_CONNECTOR_MASK, |
263 | SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); |
264 | } |
265 | |
266 | /* PL110 pixel formats for Integrator, vanilla PL110 */ |
267 | static const u32 pl110_integrator_pixel_formats[] = { |
268 | DRM_FORMAT_ABGR8888, |
269 | DRM_FORMAT_XBGR8888, |
270 | DRM_FORMAT_ARGB8888, |
271 | DRM_FORMAT_XRGB8888, |
272 | DRM_FORMAT_ABGR1555, |
273 | DRM_FORMAT_XBGR1555, |
274 | DRM_FORMAT_ARGB1555, |
275 | DRM_FORMAT_XRGB1555, |
276 | }; |
277 | |
278 | /* Extended PL110 pixel formats for Integrator and Versatile */ |
279 | static const u32 pl110_versatile_pixel_formats[] = { |
280 | DRM_FORMAT_ABGR8888, |
281 | DRM_FORMAT_XBGR8888, |
282 | DRM_FORMAT_ARGB8888, |
283 | DRM_FORMAT_XRGB8888, |
284 | DRM_FORMAT_BGR565, /* Uses external PLD */ |
285 | DRM_FORMAT_RGB565, /* Uses external PLD */ |
286 | DRM_FORMAT_ABGR1555, |
287 | DRM_FORMAT_XBGR1555, |
288 | DRM_FORMAT_ARGB1555, |
289 | DRM_FORMAT_XRGB1555, |
290 | }; |
291 | |
292 | static const u32 pl111_realview_pixel_formats[] = { |
293 | DRM_FORMAT_ABGR8888, |
294 | DRM_FORMAT_XBGR8888, |
295 | DRM_FORMAT_ARGB8888, |
296 | DRM_FORMAT_XRGB8888, |
297 | DRM_FORMAT_BGR565, |
298 | DRM_FORMAT_RGB565, |
299 | DRM_FORMAT_ABGR1555, |
300 | DRM_FORMAT_XBGR1555, |
301 | DRM_FORMAT_ARGB1555, |
302 | DRM_FORMAT_XRGB1555, |
303 | DRM_FORMAT_ABGR4444, |
304 | DRM_FORMAT_XBGR4444, |
305 | DRM_FORMAT_ARGB4444, |
306 | DRM_FORMAT_XRGB4444, |
307 | }; |
308 | |
309 | /* |
310 | * The Integrator variant is a PL110 with a bunch of broken, or not |
311 | * yet implemented features |
312 | */ |
313 | static const struct pl111_variant_data pl110_integrator = { |
314 | .name = "PL110 Integrator" , |
315 | .is_pl110 = true, |
316 | .broken_clockdivider = true, |
317 | .broken_vblank = true, |
318 | .formats = pl110_integrator_pixel_formats, |
319 | .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), |
320 | .fb_depth = 16, |
321 | }; |
322 | |
323 | /* |
324 | * The IM-PD1 variant is a PL110 with a bunch of broken, or not |
325 | * yet implemented features |
326 | */ |
327 | static const struct pl111_variant_data pl110_impd1 = { |
328 | .name = "PL110 IM-PD1" , |
329 | .is_pl110 = true, |
330 | .broken_clockdivider = true, |
331 | .broken_vblank = true, |
332 | .formats = pl110_integrator_pixel_formats, |
333 | .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), |
334 | .fb_depth = 15, |
335 | }; |
336 | |
337 | /* |
338 | * This is the in-between PL110 variant found in the ARM Versatile, |
339 | * supporting RGB565/BGR565 |
340 | */ |
341 | static const struct pl111_variant_data pl110_versatile = { |
342 | .name = "PL110 Versatile" , |
343 | .is_pl110 = true, |
344 | .external_bgr = true, |
345 | .formats = pl110_versatile_pixel_formats, |
346 | .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats), |
347 | .fb_depth = 16, |
348 | }; |
349 | |
350 | /* |
351 | * RealView PL111 variant, the only real difference from the vanilla |
352 | * PL111 is that we select 16bpp framebuffer by default to be able |
353 | * to get 1024x768 without saturating the memory bus. |
354 | */ |
355 | static const struct pl111_variant_data pl111_realview = { |
356 | .name = "PL111 RealView" , |
357 | .formats = pl111_realview_pixel_formats, |
358 | .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), |
359 | .fb_depth = 16, |
360 | }; |
361 | |
362 | /* |
363 | * Versatile Express PL111 variant, again we just push the maximum |
364 | * BPP to 16 to be able to get 1024x768 without saturating the memory |
365 | * bus. The clockdivider also seems broken on the Versatile Express. |
366 | */ |
367 | static const struct pl111_variant_data pl111_vexpress = { |
368 | .name = "PL111 Versatile Express" , |
369 | .formats = pl111_realview_pixel_formats, |
370 | .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), |
371 | .fb_depth = 16, |
372 | .broken_clockdivider = true, |
373 | }; |
374 | |
375 | #define VEXPRESS_FPGAMUX_MOTHERBOARD 0x00 |
376 | #define VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 0x01 |
377 | #define VEXPRESS_FPGAMUX_DAUGHTERBOARD_2 0x02 |
378 | |
379 | static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np, |
380 | struct pl111_drm_dev_private *priv) |
381 | { |
382 | struct platform_device *pdev; |
383 | struct device_node *root; |
384 | struct device_node *child; |
385 | struct device_node *ct_clcd = NULL; |
386 | struct regmap *map; |
387 | bool has_coretile_clcd = false; |
388 | bool has_coretile_hdlcd = false; |
389 | bool mux_motherboard = true; |
390 | u32 val; |
391 | int ret; |
392 | |
393 | if (!IS_ENABLED(CONFIG_VEXPRESS_CONFIG)) |
394 | return -ENODEV; |
395 | |
396 | /* |
397 | * Check if we have a CLCD or HDLCD on the core tile by checking if a |
398 | * CLCD or HDLCD is available in the root of the device tree. |
399 | */ |
400 | root = of_find_node_by_path(path: "/" ); |
401 | if (!root) |
402 | return -EINVAL; |
403 | |
404 | for_each_available_child_of_node(root, child) { |
405 | if (of_device_is_compatible(device: child, "arm,pl111" )) { |
406 | has_coretile_clcd = true; |
407 | ct_clcd = child; |
408 | of_node_put(node: child); |
409 | break; |
410 | } |
411 | if (of_device_is_compatible(device: child, "arm,hdlcd" )) { |
412 | has_coretile_hdlcd = true; |
413 | of_node_put(node: child); |
414 | break; |
415 | } |
416 | } |
417 | |
418 | of_node_put(node: root); |
419 | |
420 | /* |
421 | * If there is a coretile HDLCD and it has a driver, |
422 | * do not mux the CLCD on the motherboard to the DVI. |
423 | */ |
424 | if (has_coretile_hdlcd && IS_ENABLED(CONFIG_DRM_HDLCD)) |
425 | mux_motherboard = false; |
426 | |
427 | /* |
428 | * On the Vexpress CA9 we let the CLCD on the coretile |
429 | * take precedence, so also in this case do not mux the |
430 | * motherboard to the DVI. |
431 | */ |
432 | if (has_coretile_clcd) |
433 | mux_motherboard = false; |
434 | |
435 | if (mux_motherboard) { |
436 | dev_info(dev, "DVI muxed to motherboard CLCD\n" ); |
437 | val = VEXPRESS_FPGAMUX_MOTHERBOARD; |
438 | } else if (ct_clcd == dev->of_node) { |
439 | dev_info(dev, |
440 | "DVI muxed to daughterboard 1 (core tile) CLCD\n" ); |
441 | val = VEXPRESS_FPGAMUX_DAUGHTERBOARD_1; |
442 | } else { |
443 | dev_info(dev, "core tile graphics present\n" ); |
444 | dev_info(dev, "this device will be deactivated\n" ); |
445 | return -ENODEV; |
446 | } |
447 | |
448 | /* Call into deep Vexpress configuration API */ |
449 | pdev = of_find_device_by_node(np); |
450 | if (!pdev) { |
451 | dev_err(dev, "can't find the sysreg device, deferring\n" ); |
452 | return -EPROBE_DEFER; |
453 | } |
454 | |
455 | map = devm_regmap_init_vexpress_config(dev: &pdev->dev); |
456 | if (IS_ERR(ptr: map)) { |
457 | platform_device_put(pdev); |
458 | return PTR_ERR(ptr: map); |
459 | } |
460 | |
461 | ret = regmap_write(map, reg: 0, val); |
462 | platform_device_put(pdev); |
463 | if (ret) { |
464 | dev_err(dev, "error setting DVI muxmode\n" ); |
465 | return -ENODEV; |
466 | } |
467 | |
468 | priv->variant = &pl111_vexpress; |
469 | dev_info(dev, "initializing Versatile Express PL111\n" ); |
470 | |
471 | return 0; |
472 | } |
473 | |
474 | int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) |
475 | { |
476 | const struct of_device_id *clcd_id; |
477 | enum versatile_clcd versatile_clcd_type; |
478 | struct device_node *np; |
479 | struct regmap *map; |
480 | |
481 | np = of_find_matching_node_and_match(NULL, matches: versatile_clcd_of_match, |
482 | match: &clcd_id); |
483 | if (!np) { |
484 | /* Non-ARM reference designs, just bail out */ |
485 | return 0; |
486 | } |
487 | |
488 | versatile_clcd_type = (enum versatile_clcd)clcd_id->data; |
489 | |
490 | /* Versatile Express special handling */ |
491 | if (versatile_clcd_type == VEXPRESS_CLCD_V2M) { |
492 | int ret = pl111_vexpress_clcd_init(dev, np, priv); |
493 | of_node_put(node: np); |
494 | if (ret) |
495 | dev_err(dev, "Versatile Express init failed - %d" , ret); |
496 | return ret; |
497 | } |
498 | |
499 | /* |
500 | * On the Integrator, check if we should use the IM-PD1 instead, |
501 | * if we find it, it will take precedence. This is on the Integrator/AP |
502 | * which only has this option for PL110 graphics. |
503 | */ |
504 | if (versatile_clcd_type == INTEGRATOR_CLCD_CM) { |
505 | np = of_find_matching_node_and_match(NULL, matches: impd1_clcd_of_match, |
506 | match: &clcd_id); |
507 | if (np) |
508 | versatile_clcd_type = (enum versatile_clcd)clcd_id->data; |
509 | } |
510 | |
511 | map = syscon_node_to_regmap(np); |
512 | of_node_put(node: np); |
513 | if (IS_ERR(ptr: map)) { |
514 | dev_err(dev, "no Versatile syscon regmap\n" ); |
515 | return PTR_ERR(ptr: map); |
516 | } |
517 | |
518 | switch (versatile_clcd_type) { |
519 | case INTEGRATOR_CLCD_CM: |
520 | versatile_syscon_map = map; |
521 | priv->variant = &pl110_integrator; |
522 | priv->variant_display_enable = pl111_integrator_enable; |
523 | dev_info(dev, "set up callbacks for Integrator PL110\n" ); |
524 | break; |
525 | case INTEGRATOR_IMPD1: |
526 | versatile_syscon_map = map; |
527 | priv->variant = &pl110_impd1; |
528 | priv->variant_display_enable = pl111_impd1_enable; |
529 | priv->variant_display_disable = pl111_impd1_disable; |
530 | dev_info(dev, "set up callbacks for IM-PD1 PL110\n" ); |
531 | break; |
532 | case VERSATILE_CLCD: |
533 | versatile_syscon_map = map; |
534 | /* This can do RGB565 with external PLD */ |
535 | priv->variant = &pl110_versatile; |
536 | priv->variant_display_enable = pl111_versatile_enable; |
537 | priv->variant_display_disable = pl111_versatile_disable; |
538 | /* |
539 | * The Versatile has a variant halfway between PL110 |
540 | * and PL111 where these two registers have already been |
541 | * swapped. |
542 | */ |
543 | priv->ienb = CLCD_PL111_IENB; |
544 | priv->ctrl = CLCD_PL111_CNTL; |
545 | dev_info(dev, "set up callbacks for Versatile PL110\n" ); |
546 | break; |
547 | case REALVIEW_CLCD_EB: |
548 | case REALVIEW_CLCD_PB1176: |
549 | case REALVIEW_CLCD_PB11MP: |
550 | case REALVIEW_CLCD_PBA8: |
551 | case REALVIEW_CLCD_PBX: |
552 | versatile_syscon_map = map; |
553 | priv->variant = &pl111_realview; |
554 | priv->variant_display_enable = pl111_realview_clcd_enable; |
555 | priv->variant_display_disable = pl111_realview_clcd_disable; |
556 | dev_info(dev, "set up callbacks for RealView PL111\n" ); |
557 | break; |
558 | default: |
559 | dev_info(dev, "unknown Versatile system controller\n" ); |
560 | break; |
561 | } |
562 | |
563 | return 0; |
564 | } |
565 | EXPORT_SYMBOL_GPL(pl111_versatile_init); |
566 | |