aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/ps3fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/ps3fb.c')
-rw-r--r--drivers/video/ps3fb.c116
1 files changed, 60 insertions, 56 deletions
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index b23d64070eef..d61e321dc90b 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -146,6 +146,8 @@ struct ps3fb_par {
146}; 146};
147 147
148 148
149#define FIRST_NATIVE_MODE_INDEX 10
150
149static const struct fb_videomode ps3fb_modedb[] = { 151static const struct fb_videomode ps3fb_modedb[] = {
150 /* 60 Hz broadcast modes (modes "1" to "5") */ 152 /* 60 Hz broadcast modes (modes "1" to "5") */
151 { 153 {
@@ -193,24 +195,7 @@ static const struct fb_videomode ps3fb_modedb[] = {
193 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED 195 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
194 }, 196 },
195 197
196 /* VESA modes (modes "11" to "13") */ 198 [FIRST_NATIVE_MODE_INDEX] =
197 {
198 /* WXGA */
199 "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
200 0, FB_VMODE_NONINTERLACED,
201 FB_MODE_IS_VESA
202 }, {
203 /* SXGA */
204 "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
205 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
206 FB_MODE_IS_VESA
207 }, {
208 /* WUXGA */
209 "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
210 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
211 FB_MODE_IS_VESA
212 },
213
214 /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ 199 /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
215 { 200 {
216 /* 480if */ 201 /* 480if */
@@ -255,6 +240,24 @@ static const struct fb_videomode ps3fb_modedb[] = {
255 /* 1080pf */ 240 /* 1080pf */
256 "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, 241 "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
257 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED 242 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
243 },
244
245 /* VESA modes (modes "11" to "13") */
246 {
247 /* WXGA */
248 "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
249 0, FB_VMODE_NONINTERLACED,
250 FB_MODE_IS_VESA
251 }, {
252 /* SXGA */
253 "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
254 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
255 FB_MODE_IS_VESA
256 }, {
257 /* WUXGA */
258 "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
259 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
260 FB_MODE_IS_VESA
258 } 261 }
259}; 262};
260 263
@@ -298,20 +301,43 @@ static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
298 return 0; 301 return 0;
299} 302}
300 303
304static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id)
305{
306 return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1];
307}
308
309static const struct fb_videomode *ps3fb_vmode(int id)
310{
311 u32 mode = id & PS3AV_MODE_MASK;
312
313 if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA)
314 return NULL;
315
316 if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) {
317 /* Non-fullscreen broadcast mode */
318 return &ps3fb_modedb[mode - 1];
319 }
320
321 return ps3fb_native_vmode(mode);
322}
323
301static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, 324static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var,
302 u32 *ddr_line_length, u32 *xdr_line_length) 325 u32 *ddr_line_length, u32 *xdr_line_length)
303{ 326{
304 unsigned int i, mode; 327 unsigned int id;
328 const struct fb_videomode *vmode;
305 329
306 for (i = PS3AV_MODE_1080P50; i < ARRAY_SIZE(ps3fb_modedb); i++) 330 for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) {
307 if (!ps3fb_cmp_mode(&ps3fb_modedb[i], var)) 331 vmode = ps3fb_native_vmode(id);
332 if (!ps3fb_cmp_mode(vmode, var))
308 goto found; 333 goto found;
334 }
309 335
310 pr_debug("ps3fb_find_mode: mode not found\n"); 336 pr_debug("%s: mode not found\n", __func__);
311 return 0; 337 return 0;
312 338
313found: 339found:
314 *ddr_line_length = ps3fb_modedb[i].xres * BPP; 340 *ddr_line_length = vmode->xres * BPP;
315 341
316 if (!var->xres) { 342 if (!var->xres) {
317 var->xres = 1; 343 var->xres = 1;
@@ -330,36 +356,14 @@ found:
330 } else 356 } else
331 *xdr_line_length = *ddr_line_length; 357 *xdr_line_length = *ddr_line_length;
332 358
333 mode = i+1; 359 if (vmode->sync & FB_SYNC_BROADCAST) {
334 if (mode > PS3AV_MODE_WUXGA) {
335 mode -= PS3AV_MODE_WUXGA;
336 /* Full broadcast modes have the full mode bit set */ 360 /* Full broadcast modes have the full mode bit set */
337 if (ps3fb_modedb[i].xres == var->xres && 361 if (vmode->xres == var->xres && vmode->yres == var->yres)
338 ps3fb_modedb[i].yres == var->yres) 362 id |= PS3AV_MODE_FULL;
339 mode |= PS3AV_MODE_FULL;
340 }
341
342 pr_debug("ps3fb_find_mode: mode %u\n", mode);
343
344 return mode;
345}
346
347static const struct fb_videomode *ps3fb_default_mode(int id)
348{
349 u32 mode = id & PS3AV_MODE_MASK;
350 u32 flags;
351
352 if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA)
353 return NULL;
354
355 flags = id & ~PS3AV_MODE_MASK;
356
357 if (mode <= PS3AV_MODE_1080P50 && flags & PS3AV_MODE_FULL) {
358 /* Full broadcast mode */
359 return &ps3fb_modedb[mode + PS3AV_MODE_WUXGA - 1];
360 } 363 }
361 364
362 return &ps3fb_modedb[mode - 1]; 365 pr_debug("%s: mode %u\n", __func__, id);
366 return id;
363} 367}
364 368
365static void ps3fb_sync_image(struct device *dev, u64 frame_offset, 369static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
@@ -553,7 +557,7 @@ static int ps3fb_set_par(struct fb_info *info)
553 if (!mode) 557 if (!mode)
554 return -EINVAL; 558 return -EINVAL;
555 559
556 vmode = ps3fb_default_mode(mode | PS3AV_MODE_FULL); 560 vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK);
557 561
558 info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); 562 info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
559 info->fix.smem_len = ps3fb.xdr_size; 563 info->fix.smem_len = ps3fb.xdr_size;
@@ -767,7 +771,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
767 case PS3FB_IOCTL_SETMODE: 771 case PS3FB_IOCTL_SETMODE:
768 { 772 {
769 struct ps3fb_par *par = info->par; 773 struct ps3fb_par *par = info->par;
770 const struct fb_videomode *mode; 774 const struct fb_videomode *vmode;
771 struct fb_var_screeninfo var; 775 struct fb_var_screeninfo var;
772 776
773 if (copy_from_user(&val, argp, sizeof(val))) 777 if (copy_from_user(&val, argp, sizeof(val)))
@@ -780,10 +784,10 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
780 } 784 }
781 dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); 785 dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
782 retval = -EINVAL; 786 retval = -EINVAL;
783 mode = ps3fb_default_mode(val); 787 vmode = ps3fb_vmode(val);
784 if (mode) { 788 if (vmode) {
785 var = info->var; 789 var = info->var;
786 fb_videomode_to_var(&var, mode); 790 fb_videomode_to_var(&var, vmode);
787 acquire_console_sem(); 791 acquire_console_sem();
788 info->flags |= FBINFO_MISC_USEREVENT; 792 info->flags |= FBINFO_MISC_USEREVENT;
789 /* Force, in case only special bits changed */ 793 /* Force, in case only special bits changed */
@@ -1141,7 +1145,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1141 1145
1142 if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, 1146 if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
1143 ARRAY_SIZE(ps3fb_modedb), 1147 ARRAY_SIZE(ps3fb_modedb),
1144 ps3fb_default_mode(par->new_mode_id), 32)) { 1148 ps3fb_vmode(par->new_mode_id), 32)) {
1145 retval = -EINVAL; 1149 retval = -EINVAL;
1146 goto err_fb_dealloc; 1150 goto err_fb_dealloc;
1147 } 1151 }