diff options
-rw-r--r-- | drivers/video/ps3fb.c | 116 |
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 | |||
149 | static const struct fb_videomode ps3fb_modedb[] = { | 151 | static 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 | ||
304 | static 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 | |||
309 | static 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 | |||
301 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, | 324 | static 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 | ||
313 | found: | 339 | found: |
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 | |||
347 | static 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 | ||
365 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | 369 | static 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 | } |