diff options
author | Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> | 2008-02-06 04:39:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:17 -0500 |
commit | 633bd111bafa346d0bb5137bd1e71b92cf1ca594 (patch) | |
tree | c7ff676a7ad446d4b4f39e5171b25579d0ee663b | |
parent | 7974f72a21a246051b3dd84d7158974fc4785150 (diff) |
ps3fb: add support for configurable black borders
Allow all video modes where the visible resolution plus the black borders
matches a native resolution
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.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>
-rw-r--r-- | drivers/video/ps3fb.c | 71 |
1 files changed, 50 insertions, 21 deletions
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index be9f70cd0062..b23d64070eef 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -270,32 +270,57 @@ module_param(ps3fb_mode, int, 0); | |||
270 | 270 | ||
271 | static char *mode_option __devinitdata; | 271 | static char *mode_option __devinitdata; |
272 | 272 | ||
273 | static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var, | 273 | static int ps3fb_cmp_mode(const struct fb_videomode *vmode, |
274 | const struct fb_var_screeninfo *var) | ||
275 | { | ||
276 | /* resolution + black border must match a native resolution */ | ||
277 | if (vmode->left_margin + vmode->xres + vmode->right_margin != | ||
278 | var->left_margin + var->xres + var->right_margin || | ||
279 | vmode->upper_margin + vmode->yres + vmode->lower_margin != | ||
280 | var->upper_margin + var->yres + var->lower_margin) | ||
281 | return -1; | ||
282 | |||
283 | /* minimum limits for margins */ | ||
284 | if (vmode->left_margin > var->left_margin || | ||
285 | vmode->right_margin > var->right_margin || | ||
286 | vmode->upper_margin > var->upper_margin || | ||
287 | vmode->lower_margin > var->lower_margin) | ||
288 | return -1; | ||
289 | |||
290 | /* these fields must match exactly */ | ||
291 | if (vmode->pixclock != var->pixclock || | ||
292 | vmode->hsync_len != var->hsync_len || | ||
293 | vmode->vsync_len != var->vsync_len || | ||
294 | vmode->sync != var->sync || | ||
295 | vmode->vmode != (var->vmode & FB_VMODE_MASK)) | ||
296 | return -1; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, | ||
274 | u32 *ddr_line_length, u32 *xdr_line_length) | 302 | u32 *ddr_line_length, u32 *xdr_line_length) |
275 | { | 303 | { |
276 | unsigned int i, fi, mode; | 304 | unsigned int i, mode; |
277 | 305 | ||
278 | for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++) | 306 | for (i = PS3AV_MODE_1080P50; i < ARRAY_SIZE(ps3fb_modedb); i++) |
279 | if (var->xres == ps3fb_modedb[i].xres && | 307 | if (!ps3fb_cmp_mode(&ps3fb_modedb[i], var)) |
280 | var->yres == ps3fb_modedb[i].yres && | ||
281 | var->pixclock == ps3fb_modedb[i].pixclock && | ||
282 | var->hsync_len == ps3fb_modedb[i].hsync_len && | ||
283 | var->vsync_len == ps3fb_modedb[i].vsync_len && | ||
284 | var->left_margin == ps3fb_modedb[i].left_margin && | ||
285 | var->right_margin == ps3fb_modedb[i].right_margin && | ||
286 | var->upper_margin == ps3fb_modedb[i].upper_margin && | ||
287 | var->lower_margin == ps3fb_modedb[i].lower_margin && | ||
288 | var->sync == ps3fb_modedb[i].sync && | ||
289 | (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) | ||
290 | goto found; | 308 | goto found; |
291 | 309 | ||
292 | pr_debug("ps3fb_find_mode: mode not found\n"); | 310 | pr_debug("ps3fb_find_mode: mode not found\n"); |
293 | return 0; | 311 | return 0; |
294 | 312 | ||
295 | found: | 313 | found: |
296 | /* Cropped broadcast modes use the full line length */ | 314 | *ddr_line_length = ps3fb_modedb[i].xres * BPP; |
297 | fi = i < PS3AV_MODE_1080P50 ? i + PS3AV_MODE_WUXGA : i; | 315 | |
298 | *ddr_line_length = ps3fb_modedb[fi].xres * BPP; | 316 | if (!var->xres) { |
317 | var->xres = 1; | ||
318 | var->right_margin--; | ||
319 | } | ||
320 | if (!var->yres) { | ||
321 | var->yres = 1; | ||
322 | var->lower_margin--; | ||
323 | } | ||
299 | 324 | ||
300 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { | 325 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { |
301 | *xdr_line_length = GPU_ALIGN_UP(max(var->xres, | 326 | *xdr_line_length = GPU_ALIGN_UP(max(var->xres, |
@@ -305,10 +330,14 @@ found: | |||
305 | } else | 330 | } else |
306 | *xdr_line_length = *ddr_line_length; | 331 | *xdr_line_length = *ddr_line_length; |
307 | 332 | ||
308 | /* Full broadcast modes have the full mode bit set */ | ||
309 | mode = i+1; | 333 | mode = i+1; |
310 | if (mode > PS3AV_MODE_WUXGA) | 334 | if (mode > PS3AV_MODE_WUXGA) { |
311 | mode = (mode - PS3AV_MODE_WUXGA) | PS3AV_MODE_FULL; | 335 | mode -= PS3AV_MODE_WUXGA; |
336 | /* Full broadcast modes have the full mode bit set */ | ||
337 | if (ps3fb_modedb[i].xres == var->xres && | ||
338 | ps3fb_modedb[i].yres == var->yres) | ||
339 | mode |= PS3AV_MODE_FULL; | ||
340 | } | ||
312 | 341 | ||
313 | pr_debug("ps3fb_find_mode: mode %u\n", mode); | 342 | pr_debug("ps3fb_find_mode: mode %u\n", mode); |
314 | 343 | ||