aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/ps3fb.c71
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
271static char *mode_option __devinitdata; 271static char *mode_option __devinitdata;
272 272
273static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var, 273static 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
301static 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
295found: 313found:
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