diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/ps3fb.c | 192 |
1 files changed, 86 insertions, 106 deletions
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index ce0f8735ae08..a74501815333 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -956,73 +956,6 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) | |||
956 | } | 956 | } |
957 | 957 | ||
958 | 958 | ||
959 | static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, | ||
960 | struct device *dev) | ||
961 | { | ||
962 | int error; | ||
963 | |||
964 | dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver); | ||
965 | dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet); | ||
966 | dev_dbg(dev, | ||
967 | "version_gpu: %x memory_size: %x ch: %x core_freq: %d " | ||
968 | "mem_freq:%d\n", | ||
969 | dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel, | ||
970 | dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000); | ||
971 | |||
972 | if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { | ||
973 | dev_err(dev, "%s: version_driver err:%x\n", __func__, | ||
974 | dinfo->version_driver); | ||
975 | return -EINVAL; | ||
976 | } | ||
977 | |||
978 | error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, | ||
979 | &ps3fb.irq_no); | ||
980 | if (error) { | ||
981 | dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error); | ||
982 | return error; | ||
983 | } | ||
984 | |||
985 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, | ||
986 | DEVICE_NAME, dev); | ||
987 | if (error) { | ||
988 | dev_err(dev, "%s: request_irq failed %d\n", __func__, error); | ||
989 | ps3_irq_plug_destroy(ps3fb.irq_no); | ||
990 | return error; | ||
991 | } | ||
992 | |||
993 | dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) | | ||
994 | (1 << GPU_INTR_STATUS_FLIP_1); | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) | ||
999 | { | ||
1000 | int status; | ||
1001 | |||
1002 | status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, | ||
1003 | xdr_lpar, ps3fb_videomemory.size, 0); | ||
1004 | if (status) { | ||
1005 | dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n", | ||
1006 | __func__, status); | ||
1007 | return -ENXIO; | ||
1008 | } | ||
1009 | dev_dbg(dev, "video:%p ioif:%lx lpar:%llx size:%lx\n", | ||
1010 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, | ||
1011 | ps3fb_videomemory.size); | ||
1012 | |||
1013 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | ||
1014 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, | ||
1015 | xdr_lpar, GPU_CMD_BUF_SIZE, | ||
1016 | GPU_IOIF, 0); | ||
1017 | if (status) { | ||
1018 | dev_err(dev, | ||
1019 | "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", | ||
1020 | __func__, status); | ||
1021 | return -ENXIO; | ||
1022 | } | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | static struct fb_ops ps3fb_ops = { | 959 | static struct fb_ops ps3fb_ops = { |
1027 | .fb_open = ps3fb_open, | 960 | .fb_open = ps3fb_open, |
1028 | .fb_release = ps3fb_release, | 961 | .fb_release = ps3fb_release, |
@@ -1048,38 +981,6 @@ static struct fb_fix_screeninfo ps3fb_fix __initdata = { | |||
1048 | .accel = FB_ACCEL_NONE, | 981 | .accel = FB_ACCEL_NONE, |
1049 | }; | 982 | }; |
1050 | 983 | ||
1051 | static int ps3fb_set_sync(struct device *dev) | ||
1052 | { | ||
1053 | int status; | ||
1054 | |||
1055 | #ifdef HEAD_A | ||
1056 | status = lv1_gpu_context_attribute(0x0, | ||
1057 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
1058 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
1059 | if (status) { | ||
1060 | dev_err(dev, | ||
1061 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " | ||
1062 | "%d\n", | ||
1063 | __func__, status); | ||
1064 | return -1; | ||
1065 | } | ||
1066 | #endif | ||
1067 | #ifdef HEAD_B | ||
1068 | status = lv1_gpu_context_attribute(0x0, | ||
1069 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
1070 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
1071 | |||
1072 | if (status) { | ||
1073 | dev_err(dev, | ||
1074 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " | ||
1075 | "%d\n", | ||
1076 | __func__, status); | ||
1077 | return -1; | ||
1078 | } | ||
1079 | #endif | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | 984 | static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) |
1084 | { | 985 | { |
1085 | struct fb_info *info; | 986 | struct fb_info *info; |
@@ -1091,6 +992,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1091 | u64 lpar_reports = 0; | 992 | u64 lpar_reports = 0; |
1092 | u64 lpar_reports_size = 0; | 993 | u64 lpar_reports_size = 0; |
1093 | u64 xdr_lpar; | 994 | u64 xdr_lpar; |
995 | struct gpu_driver_info *dinfo; | ||
1094 | void *fb_start; | 996 | void *fb_start; |
1095 | int status; | 997 | int status; |
1096 | struct task_struct *task; | 998 | struct task_struct *task; |
@@ -1116,7 +1018,31 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1116 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1018 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ |
1117 | init_waitqueue_head(&ps3fb.wait_vsync); | 1019 | init_waitqueue_head(&ps3fb.wait_vsync); |
1118 | 1020 | ||
1119 | ps3fb_set_sync(&dev->core); | 1021 | #ifdef HEAD_A |
1022 | status = lv1_gpu_context_attribute(0x0, | ||
1023 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
1024 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
1025 | if (status) { | ||
1026 | dev_err(&dev->core, | ||
1027 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " | ||
1028 | "%d\n", | ||
1029 | __func__, status); | ||
1030 | goto err; | ||
1031 | } | ||
1032 | #endif | ||
1033 | #ifdef HEAD_B | ||
1034 | status = lv1_gpu_context_attribute(0x0, | ||
1035 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | ||
1036 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | ||
1037 | |||
1038 | if (status) { | ||
1039 | dev_err(&dev->core, | ||
1040 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " | ||
1041 | "%d\n", | ||
1042 | __func__, status); | ||
1043 | goto err; | ||
1044 | } | ||
1045 | #endif | ||
1120 | 1046 | ||
1121 | max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; | 1047 | max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; |
1122 | if (ps3fb_videomemory.size > max_ps3fb_size) { | 1048 | if (ps3fb_videomemory.size > max_ps3fb_size) { |
@@ -1147,23 +1073,76 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1147 | } | 1073 | } |
1148 | 1074 | ||
1149 | /* vsync interrupt */ | 1075 | /* vsync interrupt */ |
1150 | ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); | 1076 | dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); |
1151 | if (!ps3fb.dinfo) { | 1077 | if (!dinfo) { |
1152 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); | 1078 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); |
1153 | goto err_gpu_context_free; | 1079 | goto err_gpu_context_free; |
1154 | } | 1080 | } |
1155 | 1081 | ||
1156 | retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core); | 1082 | ps3fb.dinfo = dinfo; |
1157 | if (retval) | 1083 | dev_dbg(&dev->core, "version_driver:%x\n", dinfo->version_driver); |
1084 | dev_dbg(&dev->core, "irq outlet:%x\n", dinfo->irq.irq_outlet); | ||
1085 | dev_dbg(&dev->core, "version_gpu: %x memory_size: %x ch: %x " | ||
1086 | "core_freq: %d mem_freq:%d\n", dinfo->version_gpu, | ||
1087 | dinfo->memory_size, dinfo->hardware_channel, | ||
1088 | dinfo->nvcore_frequency/1000000, | ||
1089 | dinfo->memory_frequency/1000000); | ||
1090 | |||
1091 | if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { | ||
1092 | dev_err(&dev->core, "%s: version_driver err:%x\n", __func__, | ||
1093 | dinfo->version_driver); | ||
1094 | retval = -EINVAL; | ||
1158 | goto err_iounmap_dinfo; | 1095 | goto err_iounmap_dinfo; |
1096 | } | ||
1097 | |||
1098 | retval = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, | ||
1099 | &ps3fb.irq_no); | ||
1100 | if (retval) { | ||
1101 | dev_err(&dev->core, "%s: ps3_alloc_irq failed %d\n", __func__, | ||
1102 | retval); | ||
1103 | goto err_iounmap_dinfo; | ||
1104 | } | ||
1105 | |||
1106 | retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, | ||
1107 | IRQF_DISABLED, DEVICE_NAME, &dev->core); | ||
1108 | if (retval) { | ||
1109 | dev_err(&dev->core, "%s: request_irq failed %d\n", __func__, | ||
1110 | retval); | ||
1111 | goto err_destroy_plug; | ||
1112 | } | ||
1113 | |||
1114 | dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) | | ||
1115 | (1 << GPU_INTR_STATUS_FLIP_1); | ||
1159 | 1116 | ||
1160 | /* Clear memory to prevent kernel info leakage into userspace */ | 1117 | /* Clear memory to prevent kernel info leakage into userspace */ |
1161 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); | 1118 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); |
1162 | 1119 | ||
1163 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); | 1120 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); |
1164 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); | 1121 | |
1165 | if (retval) | 1122 | status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, |
1123 | xdr_lpar, ps3fb_videomemory.size, 0); | ||
1124 | if (status) { | ||
1125 | dev_err(&dev->core, "%s: lv1_gpu_context_iomap failed: %d\n", | ||
1126 | __func__, status); | ||
1127 | retval = -ENXIO; | ||
1128 | goto err_free_irq; | ||
1129 | } | ||
1130 | |||
1131 | dev_dbg(&dev->core, "video:%p ioif:%lx lpar:%llx size:%lx\n", | ||
1132 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, | ||
1133 | ps3fb_videomemory.size); | ||
1134 | |||
1135 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | ||
1136 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, | ||
1137 | xdr_lpar, GPU_CMD_BUF_SIZE, | ||
1138 | GPU_IOIF, 0); | ||
1139 | if (status) { | ||
1140 | dev_err(&dev->core, | ||
1141 | "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", | ||
1142 | __func__, status); | ||
1143 | retval = -ENXIO; | ||
1166 | goto err_free_irq; | 1144 | goto err_free_irq; |
1145 | } | ||
1167 | 1146 | ||
1168 | info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); | 1147 | info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); |
1169 | if (!info) | 1148 | if (!info) |
@@ -1234,6 +1213,7 @@ err_framebuffer_release: | |||
1234 | framebuffer_release(info); | 1213 | framebuffer_release(info); |
1235 | err_free_irq: | 1214 | err_free_irq: |
1236 | free_irq(ps3fb.irq_no, &dev->core); | 1215 | free_irq(ps3fb.irq_no, &dev->core); |
1216 | err_destroy_plug: | ||
1237 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1217 | ps3_irq_plug_destroy(ps3fb.irq_no); |
1238 | err_iounmap_dinfo: | 1218 | err_iounmap_dinfo: |
1239 | iounmap((u8 __force __iomem *)ps3fb.dinfo); | 1219 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |