Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

OLPC: gxfb/lxfb: add DCON panel modes to framebuffer drivers

Since there's no way to autodetect panel modes, we're forced to hardcode them
in the driver and add a big fat #ifdef. The OLPC DCON needs a specific mode
line (at 1200x900). This adds it to both gxfb and lxfb.

(Jordan said: We could probably detect the panel mode, but there isn't any
reason to since the panel timings are well known and won't change. While OFW
detection would be good computer science fu, it would be a wasted effort since
its so easy to hard code them into the table.)

Signed-off-by: Andres Salomon <dilinger@debian.org>
Cc: Jordan Crouse <jordan.crouse@amd.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andres Salomon and committed by
Linus Torvalds
3553a2fa fd967956

+67 -7
+35 -2
drivers/video/geode/gxfb_core.c
··· 41 41 static int vt_switch; 42 42 43 43 /* Modes relevant to the GX (taken from modedb.c) */ 44 - static const struct fb_videomode gx_modedb[] __initdata = { 44 + static struct fb_videomode gx_modedb[] __initdata = { 45 45 /* 640x480-60 VESA */ 46 46 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 47 47 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, ··· 107 107 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 108 108 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 109 109 }; 110 + 111 + #ifdef CONFIG_OLPC 112 + #include <asm/olpc.h> 113 + 114 + static struct fb_videomode gx_dcon_modedb[] __initdata = { 115 + /* The only mode the DCON has is 1200x900 */ 116 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, 117 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 118 + FB_VMODE_NONINTERLACED, 0 } 119 + }; 120 + 121 + static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) 122 + { 123 + if (olpc_has_dcon()) { 124 + *modedb = (struct fb_videomode *) gx_dcon_modedb; 125 + *size = ARRAY_SIZE(gx_dcon_modedb); 126 + } else { 127 + *modedb = (struct fb_videomode *) gx_modedb; 128 + *size = ARRAY_SIZE(gx_modedb); 129 + } 130 + } 131 + 132 + #else 133 + static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) 134 + { 135 + *modedb = (struct fb_videomode *) gx_modedb; 136 + *size = ARRAY_SIZE(gx_modedb); 137 + } 138 + #endif 110 139 111 140 static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 112 141 { ··· 379 350 int ret; 380 351 unsigned long val; 381 352 353 + struct fb_videomode *modedb_ptr; 354 + unsigned int modedb_size; 355 + 382 356 info = gxfb_init_fbinfo(&pdev->dev); 383 357 if (!info) 384 358 return -ENOMEM; ··· 401 369 else 402 370 par->enable_crt = 1; 403 371 372 + get_modedb(&modedb_ptr, &modedb_size); 404 373 ret = fb_find_mode(&info->var, info, mode_option, 405 - gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); 374 + modedb_ptr, modedb_size, NULL, 16); 406 375 if (ret == 0 || ret == 4) { 407 376 dev_err(&pdev->dev, "could not find valid video mode\n"); 408 377 ret = -EINVAL;
+32 -5
drivers/video/geode/lxfb_core.c
··· 36 36 * we try to make it something sane - 640x480-60 is sane 37 37 */ 38 38 39 - static const struct fb_videomode geode_modedb[] __initdata = { 39 + static struct fb_videomode geode_modedb[] __initdata = { 40 40 /* 640x480-60 */ 41 41 { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, 42 42 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, ··· 216 216 { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3, 217 217 0, FB_VMODE_NONINTERLACED, 0 }, 218 218 }; 219 + 220 + #ifdef CONFIG_OLPC 221 + #include <asm/olpc.h> 222 + 223 + static struct fb_videomode olpc_dcon_modedb[] __initdata = { 224 + /* The only mode the DCON has is 1200x900 */ 225 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, 226 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 227 + FB_VMODE_NONINTERLACED, 0 } 228 + }; 229 + 230 + static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) 231 + { 232 + if (olpc_has_dcon()) { 233 + *modedb = (struct fb_videomode *) olpc_dcon_modedb; 234 + *size = ARRAY_SIZE(olpc_dcon_modedb); 235 + } else { 236 + *modedb = (struct fb_videomode *) geode_modedb; 237 + *size = ARRAY_SIZE(geode_modedb); 238 + } 239 + } 240 + 241 + #else 242 + static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) 243 + { 244 + *modedb = (struct fb_videomode *) geode_modedb; 245 + *size = ARRAY_SIZE(geode_modedb); 246 + } 247 + #endif 219 248 220 249 static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 221 250 { ··· 506 477 int ret; 507 478 508 479 struct fb_videomode *modedb_ptr; 509 - int modedb_size; 480 + unsigned int modedb_size; 510 481 511 482 info = lxfb_init_fbinfo(&pdev->dev); 512 483 ··· 531 502 532 503 /* Set up the mode database */ 533 504 534 - modedb_ptr = (struct fb_videomode *) geode_modedb; 535 - modedb_size = ARRAY_SIZE(geode_modedb); 536 - 505 + get_modedb(&modedb_ptr, &modedb_size); 537 506 ret = fb_find_mode(&info->var, info, mode_option, 538 507 modedb_ptr, modedb_size, NULL, 16); 539 508