aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/ps3fb.c108
1 files changed, 22 insertions, 86 deletions
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 229727a5bc75..b9c5b4e122c7 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -134,42 +134,17 @@ static struct ps3fb_priv ps3fb;
134struct ps3fb_par { 134struct ps3fb_par {
135 u32 pseudo_palette[16]; 135 u32 pseudo_palette[16];
136 int mode_id, new_mode_id; 136 int mode_id, new_mode_id;
137 int res_index;
138 unsigned int num_frames; /* num of frame buffers */ 137 unsigned int num_frames; /* num of frame buffers */
139 unsigned int width; 138 unsigned int width;
140 unsigned int height; 139 unsigned int height;
140 unsigned int ddr_line_length;
141 unsigned int ddr_frame_size;
142 unsigned int xdr_frame_size;
141 unsigned long full_offset; /* start of fullscreen DDR fb */ 143 unsigned long full_offset; /* start of fullscreen DDR fb */
142 unsigned long fb_offset; /* start of actual DDR fb */ 144 unsigned long fb_offset; /* start of actual DDR fb */
143 unsigned long pan_offset; 145 unsigned long pan_offset;
144}; 146};
145 147
146struct ps3fb_res_table {
147 u32 xres;
148 u32 yres;
149 u32 xoff;
150 u32 yoff;
151 u32 type;
152};
153#define PS3FB_RES_FULL 1
154static const struct ps3fb_res_table ps3fb_res[] = {
155 /* res_x,y margin_x,y full */
156 { 720, 480, 72, 48 , 0},
157 { 720, 576, 72, 58 , 0},
158 { 1280, 720, 78, 38 , 0},
159 { 1920, 1080, 116, 58 , 0},
160 /* full mode */
161 { 720, 480, 0, 0 , PS3FB_RES_FULL},
162 { 720, 576, 0, 0 , PS3FB_RES_FULL},
163 { 1280, 720, 0, 0 , PS3FB_RES_FULL},
164 { 1920, 1080, 0, 0 , PS3FB_RES_FULL},
165 /* vesa: normally full mode */
166 { 1280, 768, 0, 0 , 0},
167 { 1280, 1024, 0, 0 , 0},
168 { 1920, 1200, 0, 0 , 0},
169 { 0, 0, 0, 0 , 0} };
170
171/* default resolution */
172#define GPU_RES_INDEX 0 /* 720 x 480 */
173 148
174static const struct fb_videomode ps3fb_modedb[] = { 149static const struct fb_videomode ps3fb_modedb[] = {
175 /* 60 Hz broadcast modes (modes "1" to "5") */ 150 /* 60 Hz broadcast modes (modes "1" to "5") */
@@ -295,37 +270,6 @@ module_param(ps3fb_mode, int, 0);
295 270
296static char *mode_option __devinitdata; 271static char *mode_option __devinitdata;
297 272
298static int ps3fb_get_res_table(u32 xres, u32 yres, int mode)
299{
300 int full_mode;
301 unsigned int i;
302 u32 x, y, f;
303
304 full_mode = (mode & PS3AV_MODE_FULL) ? PS3FB_RES_FULL : 0;
305 for (i = 0;; i++) {
306 x = ps3fb_res[i].xres;
307 y = ps3fb_res[i].yres;
308 f = ps3fb_res[i].type;
309
310 if (!x) {
311 pr_debug("ERROR: ps3fb_get_res_table()\n");
312 return -1;
313 }
314
315 if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL)
316 continue;
317
318 if (x == xres && (yres == 0 || y == yres))
319 break;
320
321 x = x - 2 * ps3fb_res[i].xoff;
322 y = y - 2 * ps3fb_res[i].yoff;
323 if (x == xres && (yres == 0 || y == yres))
324 break;
325 }
326 return i;
327}
328
329static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var, 273static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
330 u32 *ddr_line_length, u32 *xdr_line_length) 274 u32 *ddr_line_length, u32 *xdr_line_length)
331{ 275{
@@ -433,8 +377,7 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
433static int ps3fb_sync(struct fb_info *info, u32 frame) 377static int ps3fb_sync(struct fb_info *info, u32 frame)
434{ 378{
435 struct ps3fb_par *par = info->par; 379 struct ps3fb_par *par = info->par;
436 int i, error = 0; 380 int error = 0;
437 u32 ddr_line_length, xdr_line_length;
438 u64 ddr_base, xdr_base; 381 u64 ddr_base, xdr_base;
439 382
440 if (frame > par->num_frames - 1) { 383 if (frame > par->num_frames - 1) {
@@ -444,16 +387,13 @@ static int ps3fb_sync(struct fb_info *info, u32 frame)
444 goto out; 387 goto out;
445 } 388 }
446 389
447 i = par->res_index; 390 xdr_base = frame * par->xdr_frame_size;
448 xdr_line_length = info->fix.line_length; 391 ddr_base = frame * par->ddr_frame_size;
449 ddr_line_length = ps3fb_res[i].xres * BPP;
450 xdr_base = frame * info->var.yres_virtual * xdr_line_length;
451 ddr_base = frame * ps3fb_res[i].yres * ddr_line_length;
452 392
453 ps3fb_sync_image(info->device, ddr_base + par->full_offset, 393 ps3fb_sync_image(info->device, ddr_base + par->full_offset,
454 ddr_base + par->fb_offset, xdr_base + par->pan_offset, 394 ddr_base + par->fb_offset, xdr_base + par->pan_offset,
455 par->width, par->height, ddr_line_length, 395 par->width, par->height, par->ddr_line_length,
456 xdr_line_length); 396 info->fix.line_length);
457 397
458out: 398out:
459 return error; 399 return error;
@@ -572,8 +512,9 @@ static int ps3fb_set_par(struct fb_info *info)
572{ 512{
573 struct ps3fb_par *par = info->par; 513 struct ps3fb_par *par = info->par;
574 unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; 514 unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
575 int i; 515 unsigned int ddr_xoff, ddr_yoff;
576 unsigned long offset; 516 unsigned long offset;
517 const struct fb_videomode *vmode;
577 u64 dst; 518 u64 dst;
578 519
579 dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n", 520 dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n",
@@ -584,8 +525,7 @@ static int ps3fb_set_par(struct fb_info *info)
584 if (!mode) 525 if (!mode)
585 return -EINVAL; 526 return -EINVAL;
586 527
587 i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode); 528 vmode = ps3fb_default_mode(mode | PS3AV_MODE_FULL);
588 par->res_index = i;
589 529
590 info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); 530 info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
591 info->fix.smem_len = ps3fb.xdr_size; 531 info->fix.smem_len = ps3fb.xdr_size;
@@ -595,9 +535,12 @@ static int ps3fb_set_par(struct fb_info *info)
595 535
596 info->screen_base = (char __iomem *)ps3fb.xdr_ea; 536 info->screen_base = (char __iomem *)ps3fb.xdr_ea;
597 537
538 par->ddr_line_length = ddr_line_length;
539 par->ddr_frame_size = vmode->yres * ddr_line_length;
540 par->xdr_frame_size = info->var.yres_virtual * xdr_line_length;
541
598 par->num_frames = ps3fb.xdr_size / 542 par->num_frames = ps3fb.xdr_size /
599 max(ps3fb_res[i].yres * ddr_line_length, 543 max(par->ddr_frame_size, par->xdr_frame_size);
600 info->var.yres_virtual * xdr_line_length);
601 544
602 /* Keep the special bits we cannot set using fb_var_screeninfo */ 545 /* Keep the special bits we cannot set using fb_var_screeninfo */
603 par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; 546 par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
@@ -606,7 +549,9 @@ static int ps3fb_set_par(struct fb_info *info)
606 par->height = info->var.yres; 549 par->height = info->var.yres;
607 550
608 /* Start of the virtual frame buffer (relative to fullscreen) */ 551 /* Start of the virtual frame buffer (relative to fullscreen) */
609 offset = ps3fb_res[i].yoff * ddr_line_length + ps3fb_res[i].xoff * BPP; 552 ddr_xoff = info->var.left_margin - vmode->left_margin;
553 ddr_yoff = info->var.upper_margin - vmode->upper_margin;
554 offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP;
610 555
611 par->fb_offset = GPU_ALIGN_UP(offset); 556 par->fb_offset = GPU_ALIGN_UP(offset);
612 par->full_offset = par->fb_offset - offset; 557 par->full_offset = par->fb_offset - offset;
@@ -625,13 +570,13 @@ static int ps3fb_set_par(struct fb_info *info)
625 memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size); 570 memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
626 571
627 /* Clear DDR frame buffer memory */ 572 /* Clear DDR frame buffer memory */
628 lines = ps3fb_res[i].yres * par->num_frames; 573 lines = vmode->yres * par->num_frames;
629 if (par->full_offset) 574 if (par->full_offset)
630 lines++; 575 lines++;
631 maxlines = ps3fb.xdr_size / ddr_line_length; 576 maxlines = ps3fb.xdr_size / ddr_line_length;
632 for (dst = 0; lines; dst += maxlines * ddr_line_length) { 577 for (dst = 0; lines; dst += maxlines * ddr_line_length) {
633 unsigned int l = min(lines, maxlines); 578 unsigned int l = min(lines, maxlines);
634 ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l, 579 ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l,
635 ddr_line_length, ddr_line_length); 580 ddr_line_length, ddr_line_length);
636 lines -= l; 581 lines -= l;
637 } 582 }
@@ -1052,14 +997,13 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1052 struct fb_info *info; 997 struct fb_info *info;
1053 struct ps3fb_par *par; 998 struct ps3fb_par *par;
1054 int retval = -ENOMEM; 999 int retval = -ENOMEM;
1055 u32 xres, yres;
1056 u64 ddr_lpar = 0; 1000 u64 ddr_lpar = 0;
1057 u64 lpar_dma_control = 0; 1001 u64 lpar_dma_control = 0;
1058 u64 lpar_driver_info = 0; 1002 u64 lpar_driver_info = 0;
1059 u64 lpar_reports = 0; 1003 u64 lpar_reports = 0;
1060 u64 lpar_reports_size = 0; 1004 u64 lpar_reports_size = 0;
1061 u64 xdr_lpar; 1005 u64 xdr_lpar;
1062 int status, res_index; 1006 int status;
1063 struct task_struct *task; 1007 struct task_struct *task;
1064 unsigned long max_ps3fb_size; 1008 unsigned long max_ps3fb_size;
1065 1009
@@ -1079,13 +1023,6 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1079 ps3fb_mode = ps3av_get_mode(); 1023 ps3fb_mode = ps3av_get_mode();
1080 dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode); 1024 dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode);
1081 1025
1082 if (ps3fb_mode > 0 &&
1083 !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
1084 res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);
1085 dev_dbg(&dev->core, "res_index:%d\n", res_index);
1086 } else
1087 res_index = GPU_RES_INDEX;
1088
1089 atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ 1026 atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
1090 atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ 1027 atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
1091 init_waitqueue_head(&ps3fb.wait_vsync); 1028 init_waitqueue_head(&ps3fb.wait_vsync);
@@ -1158,7 +1095,6 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1158 par = info->par; 1095 par = info->par;
1159 par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ 1096 par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */
1160 par->new_mode_id = ps3fb_mode; 1097 par->new_mode_id = ps3fb_mode;
1161 par->res_index = res_index;
1162 par->num_frames = 1; 1098 par->num_frames = 1;
1163 1099
1164 info->screen_base = (char __iomem *)ps3fb.xdr_ea; 1100 info->screen_base = (char __iomem *)ps3fb.xdr_ea;