20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
42 #define DEVICE_NAME "ps3fb"
44 #define GPU_CMD_BUF_SIZE (2 * 1024 * 1024)
45 #define GPU_FB_START (64 * 1024)
46 #define GPU_IOIF (0x0d000000UL)
47 #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64)
48 #define GPU_MAX_LINE_LENGTH (65536 - 64)
50 #define GPU_INTR_STATUS_VSYNC_0 0
51 #define GPU_INTR_STATUS_VSYNC_1 1
52 #define GPU_INTR_STATUS_FLIP_0 3
53 #define GPU_INTR_STATUS_FLIP_1 4
54 #define GPU_INTR_STATUS_QUEUE_0 5
55 #define GPU_INTR_STATUS_QUEUE_1 6
57 #define GPU_DRIVER_INFO_VERSION 0x211
137 #define FIRST_NATIVE_MODE_INDEX 10
143 "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
147 "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
151 "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
155 "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
159 "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
166 "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
170 "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
174 "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
178 "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
182 "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
190 "480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
194 "480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
198 "720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
202 "1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
206 "1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
213 "576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
217 "576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
221 "720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
225 "1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
229 "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
236 "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
241 "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
246 "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
259 static int ps3fb_mode;
326 return &ps3fb_modedb[mode - 1];
329 return ps3fb_native_vmode(mode);
333 u32 *ddr_line_length,
u32 *xdr_line_length)
335 unsigned int id, best_id;
342 pr_debug(
"%s: wanted %u [%u] %u x %u [%u] %u\n", __func__,
346 vmode = ps3fb_native_vmode(
id);
347 diff = ps3fb_cmp_mode(vmode, var);
348 pr_debug(
"%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n",
354 if (diff < best_diff) {
363 pr_debug(
"%s: no suitable mode found\n", __func__);
368 vmode = ps3fb_native_vmode(
id);
370 *ddr_line_length = vmode->
xres *
BPP;
402 pr_debug(
"%s: rounded up H to %u [%u] %u\n", __func__,
413 pr_debug(
"%s: rounded up V to %u [%u] %u\n", __func__,
428 *xdr_line_length = *ddr_line_length;
436 pr_debug(
"%s: mode %u\n", __func__,
id);
448 line_length = dst_line_length;
449 if (src_line_length != dst_line_length)
450 line_length |= (
u64)src_line_length << 32;
455 status = lv1_gpu_fb_blit(ps3fb.context_handle, dst_offset,
458 (width << 16) | height,
463 dev_err(dev,
"%s: lv1_gpu_fb_blit failed: %d\n", __func__,
466 status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
468 dev_err(dev,
"%s: lv1_gpu_display_flip failed: %d\n", __func__,
472 status = lv1_gpu_display_flip(ps3fb.context_handle, 1, frame_offset);
474 dev_err(dev,
"%s: lv1_gpu_display_flip failed: %d\n", __func__,
483 u64 ddr_base, xdr_base;
498 info->
fix.line_length);
504 static int ps3fb_open(
struct fb_info *info,
int user)
510 static int ps3fb_release(
struct fb_info *info,
int user)
537 mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
544 "Horizontal virtual screen size too large\n");
556 var->
red.offset > 16 || var->
green.offset > 8 ||
557 var->
blue.offset > 0 || var->
transp.offset > 24 ||
558 var->
red.length > 8 || var->
green.length > 8 ||
559 var->
blue.length > 8 || var->
transp.length > 8 ||
560 var->
red.msb_right || var->
green.msb_right ||
567 var->
red.offset = 16;
568 var->
green.offset = 8;
569 var->
blue.offset = 0;
572 var->
green.length = 8;
573 var->
blue.length = 8;
575 var->
red.msb_right = 0;
576 var->
green.msb_right = 0;
577 var->
blue.msb_right = 0;
578 var->
transp.msb_right = 0;
602 static int ps3fb_set_par(
struct fb_info *info)
606 unsigned int ddr_xoff, ddr_yoff,
offset;
610 mode = ps3fb_find_mode(&info->
var, &ddr_line_length, &xdr_line_length);
614 vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK);
616 info->
fix.xpanstep = info->
var.xres_virtual > info->
var.xres ? 1 : 0;
617 info->
fix.ypanstep = info->
var.yres_virtual > info->
var.yres ? 1 : 0;
618 info->
fix.line_length = xdr_line_length;
636 offset = ddr_yoff * ddr_line_length + ddr_xoff *
BPP;
658 maxlines = info->
fix.smem_len / ddr_line_length;
659 for (dst = 0; lines; dst += maxlines * ddr_line_length) {
660 unsigned int l =
min(lines, maxlines);
661 ps3fb_sync_image(info->
device, 0, dst, 0, vmode->
xres, l,
662 ddr_line_length, ddr_line_length);
675 static int ps3fb_setcolreg(
unsigned int regno,
unsigned int red,
712 if (offset + size > info->
fix.smem_len)
715 offset += info->
fix.smem_start;
720 dev_dbg(info->
device,
"ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
729 static int ps3fb_blank(
int blank,
struct fb_info *info)
741 ps3fb.is_blanked = 1;
747 ps3fb.is_blanked = 0;
753 static int ps3fb_get_vblank(
struct fb_vblank *vblank)
755 memset(vblank, 0,
sizeof(*vblank));
760 static int ps3fb_wait_for_vsync(
u32 crtc)
765 count = ps3fb.vblank_count;
767 count != ps3fb.vblank_count,
780 static int ps3fb_ioctl(
struct fb_info *info,
unsigned int cmd,
792 retval = ps3fb_get_vblank(&vblank);
808 retval = ps3fb_wait_for_vsync(crt);
821 if (!(val & PS3AV_MODE_MASK)) {
824 val = (val & ~PS3AV_MODE_MASK) |
id;
828 vmode = ps3fb_vmode(val);
857 res.yres = info->
var.yres_virtual;
858 res.xoff = (
res.xres - info->
var.xres) / 2;
859 res.yoff = (
res.yres - info->
var.yres) / 2;
884 retval = ps3fb_sync(info, val);
895 static int ps3fbd(
void *arg)
903 if (ps3fb.is_kicked) {
921 status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
923 dev_err(dev,
"%s: lv1_gpu_context_intr failed: %d\n", __func__,
931 if (ps3fb.task && !ps3fb.is_blanked &&
943 static struct fb_ops ps3fb_ops = {
944 .fb_open = ps3fb_open,
945 .fb_release = ps3fb_release,
948 .fb_check_var = ps3fb_check_var,
949 .fb_set_par = ps3fb_set_par,
950 .fb_setcolreg = ps3fb_setcolreg,
951 .fb_pan_display = ps3fb_pan_display,
955 .fb_mmap = ps3fb_mmap,
956 .fb_blank = ps3fb_blank,
957 .fb_ioctl = ps3fb_ioctl,
958 .fb_compat_ioctl = ps3fb_ioctl
974 u64 lpar_dma_control = 0;
975 u64 lpar_driver_info = 0;
976 u64 lpar_reports = 0;
977 u64 lpar_reports_size = 0;
983 unsigned long max_ps3fb_size;
986 dev_err(&dev->
core,
"%s: Not enough video memory\n", __func__);
992 dev_err(&dev->
core,
"%s: ps3_open_hv_device failed\n",
999 dev_dbg(&dev->
core,
"ps3fb_mode: %d\n", ps3fb_mode);
1008 dev_err(&dev->
core,
"%s: lv1_gpu_display_sync failed: %d\n",
1011 goto err_close_device;
1017 dev_err(&dev->
core,
"%s: lv1_gpu_display_sync failed: %d\n",
1020 goto err_close_device;
1026 dev_info(&dev->
core,
"Limiting ps3fb mem size to %lu bytes\n",
1033 &ps3fb.memory_handle, &ddr_lpar);
1035 dev_err(&dev->
core,
"%s: lv1_gpu_memory_allocate failed: %d\n",
1038 goto err_close_device;
1040 dev_dbg(&dev->
core,
"ddr:lpar:0x%llx\n", ddr_lpar);
1042 status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
1043 &ps3fb.context_handle,
1044 &lpar_dma_control, &lpar_driver_info,
1045 &lpar_reports, &lpar_reports_size);
1048 "%s: lv1_gpu_context_allocate failed: %d\n", __func__,
1051 goto err_gpu_memory_free;
1057 dev_err(&dev->
core,
"%s: ioremap failed\n", __func__);
1059 goto err_gpu_context_free;
1062 ps3fb.dinfo = dinfo;
1065 dev_dbg(&dev->
core,
"version_gpu: %x memory_size: %x ch: %x "
1066 "core_freq: %d mem_freq:%d\n", dinfo->
version_gpu,
1072 dev_err(&dev->
core,
"%s: version_driver err:%x\n", __func__,
1075 goto err_iounmap_dinfo;
1081 dev_err(&dev->
core,
"%s: ps3_alloc_irq failed %d\n", __func__,
1083 goto err_iounmap_dinfo;
1086 retval =
request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
1089 dev_err(&dev->
core,
"%s: request_irq failed %d\n", __func__,
1091 goto err_destroy_plug;
1102 status = lv1_gpu_context_iomap(ps3fb.context_handle,
GPU_IOIF,
1107 dev_err(&dev->
core,
"%s: lv1_gpu_context_iomap failed: %d\n",
1113 dev_dbg(&dev->
core,
"video:%p ioif:%lx lpar:%llx size:%lx\n",
1117 status = lv1_gpu_fb_setup(ps3fb.context_handle, xdr_lpar,
1120 dev_err(&dev->
core,
"%s: lv1_gpu_fb_setup failed: %d\n",
1123 goto err_context_unmap;
1129 goto err_context_fb_close;
1137 info->
fbops = &ps3fb_ops;
1138 info->
fix = ps3fb_fix;
1148 info->
fix.smem_start =
__pa(fb_start);
1157 goto err_framebuffer_release;
1163 goto err_fb_dealloc;
1171 goto err_fb_dealloc;
1173 ps3_system_bus_set_drvdata(dev, info);
1177 info->
fix.smem_len >> 10);
1181 retval = PTR_ERR(task);
1182 goto err_unregister_framebuffer;
1189 err_unregister_framebuffer:
1193 err_framebuffer_release:
1195 err_context_fb_close:
1196 lv1_gpu_fb_close(ps3fb.context_handle);
1198 lv1_gpu_context_iomap(ps3fb.context_handle,
GPU_IOIF, xdr_lpar,
1206 err_gpu_context_free:
1207 lv1_gpu_context_free(ps3fb.context_handle);
1208 err_gpu_memory_free:
1209 lv1_gpu_memory_free(ps3fb.memory_handle);
1218 struct fb_info *info = ps3_system_bus_get_drvdata(dev);
1221 dev_dbg(&dev->
core,
" -> %s:%d\n", __func__, __LINE__);
1224 ps3fb.dinfo->irq.mask = 0;
1239 ps3_system_bus_set_drvdata(dev,
NULL);
1242 lv1_gpu_fb_close(ps3fb.context_handle);
1243 lv1_gpu_context_iomap(ps3fb.context_handle,
GPU_IOIF, xdr_lpar,
1245 lv1_gpu_context_free(ps3fb.context_handle);
1246 lv1_gpu_memory_free(ps3fb.memory_handle);
1248 dev_dbg(&dev->
core,
" <- %s:%d\n", __func__, __LINE__);
1258 .probe = ps3fb_probe,
1259 .remove = ps3fb_shutdown,
1260 .shutdown = ps3fb_shutdown,
1263 static int __init ps3fb_setup(
void)
1274 if (!options || !*options)
1278 char *this_opt =
strsep(&options,
",");
1284 if (!
strncmp(this_opt,
"mode:", 5))
1287 mode_option = this_opt;
1292 static int __init ps3fb_init(
void)
1300 static void __exit ps3fb_exit(
void)
1302 pr_debug(
" -> %s:%d\n", __func__, __LINE__);
1304 pr_debug(
" <- %s:%d\n", __func__, __LINE__);