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.c272
1 files changed, 115 insertions, 157 deletions
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index e00c1dff55de..c0af638fe702 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -32,25 +32,16 @@
32#include <linux/init.h> 32#include <linux/init.h>
33 33
34#include <asm/abs_addr.h> 34#include <asm/abs_addr.h>
35#include <asm/iommu.h>
35#include <asm/lv1call.h> 36#include <asm/lv1call.h>
36#include <asm/ps3av.h> 37#include <asm/ps3av.h>
37#include <asm/ps3fb.h> 38#include <asm/ps3fb.h>
38#include <asm/ps3.h> 39#include <asm/ps3.h>
40#include <asm/ps3gpu.h>
39 41
40 42
41#define DEVICE_NAME "ps3fb" 43#define DEVICE_NAME "ps3fb"
42 44
43#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x101
44#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x102
45#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP 0x600
46#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601
47#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC 0x602
48
49#define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION (1ULL << 32)
50
51#define L1GPU_DISPLAY_SYNC_HSYNC 1
52#define L1GPU_DISPLAY_SYNC_VSYNC 2
53
54#define GPU_CMD_BUF_SIZE (2 * 1024 * 1024) 45#define GPU_CMD_BUF_SIZE (2 * 1024 * 1024)
55#define GPU_FB_START (64 * 1024) 46#define GPU_FB_START (64 * 1024)
56#define GPU_IOIF (0x0d000000UL) 47#define GPU_IOIF (0x0d000000UL)
@@ -462,33 +453,27 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
462 src_offset += GPU_FB_START; 453 src_offset += GPU_FB_START;
463 454
464 mutex_lock(&ps3_gpu_mutex); 455 mutex_lock(&ps3_gpu_mutex);
465 status = lv1_gpu_context_attribute(ps3fb.context_handle, 456 status = lv1_gpu_fb_blit(ps3fb.context_handle, dst_offset,
466 L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 457 GPU_IOIF + src_offset,
467 dst_offset, GPU_IOIF + src_offset, 458 L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
468 L1GPU_FB_BLIT_WAIT_FOR_COMPLETION | 459 (width << 16) | height,
469 (width << 16) | height, 460 line_length);
470 line_length);
471 mutex_unlock(&ps3_gpu_mutex); 461 mutex_unlock(&ps3_gpu_mutex);
472 462
473 if (status) 463 if (status)
474 dev_err(dev, 464 dev_err(dev, "%s: lv1_gpu_fb_blit failed: %d\n", __func__,
475 "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", 465 status);
476 __func__, status);
477#ifdef HEAD_A 466#ifdef HEAD_A
478 status = lv1_gpu_context_attribute(ps3fb.context_handle, 467 status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
479 L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
480 0, frame_offset, 0, 0);
481 if (status) 468 if (status)
482 dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n", 469 dev_err(dev, "%s: lv1_gpu_display_flip failed: %d\n", __func__,
483 __func__, status); 470 status);
484#endif 471#endif
485#ifdef HEAD_B 472#ifdef HEAD_B
486 status = lv1_gpu_context_attribute(ps3fb.context_handle, 473 status = lv1_gpu_display_flip(ps3fb.context_handle, 1, frame_offset);
487 L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
488 1, frame_offset, 0, 0);
489 if (status) 474 if (status)
490 dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n", 475 dev_err(dev, "%s: lv1_gpu_display_flip failed: %d\n", __func__,
491 __func__, status); 476 status);
492#endif 477#endif
493} 478}
494 479
@@ -956,73 +941,6 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
956} 941}
957 942
958 943
959static 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
998static 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
1026static struct fb_ops ps3fb_ops = { 944static struct fb_ops ps3fb_ops = {
1027 .fb_open = ps3fb_open, 945 .fb_open = ps3fb_open,
1028 .fb_release = ps3fb_release, 946 .fb_release = ps3fb_release,
@@ -1048,49 +966,18 @@ static struct fb_fix_screeninfo ps3fb_fix __initdata = {
1048 .accel = FB_ACCEL_NONE, 966 .accel = FB_ACCEL_NONE,
1049}; 967};
1050 968
1051static 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
1083static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) 969static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1084{ 970{
1085 struct fb_info *info; 971 struct fb_info *info;
1086 struct ps3fb_par *par; 972 struct ps3fb_par *par;
1087 int retval = -ENOMEM; 973 int retval;
1088 u64 ddr_lpar = 0; 974 u64 ddr_lpar = 0;
1089 u64 lpar_dma_control = 0; 975 u64 lpar_dma_control = 0;
1090 u64 lpar_driver_info = 0; 976 u64 lpar_driver_info = 0;
1091 u64 lpar_reports = 0; 977 u64 lpar_reports = 0;
1092 u64 lpar_reports_size = 0; 978 u64 lpar_reports_size = 0;
1093 u64 xdr_lpar; 979 u64 xdr_lpar;
980 struct gpu_driver_info *dinfo;
1094 void *fb_start; 981 void *fb_start;
1095 int status; 982 int status;
1096 struct task_struct *task; 983 struct task_struct *task;
@@ -1101,8 +988,8 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1101 return -ENOMEM; 988 return -ENOMEM;
1102 } 989 }
1103 990
1104 status = ps3_open_hv_device(dev); 991 retval = ps3_open_hv_device(dev);
1105 if (status) { 992 if (retval) {
1106 dev_err(&dev->core, "%s: ps3_open_hv_device failed\n", 993 dev_err(&dev->core, "%s: ps3_open_hv_device failed\n",
1107 __func__); 994 __func__);
1108 goto err; 995 goto err;
@@ -1116,7 +1003,24 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1116 atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ 1003 atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
1117 init_waitqueue_head(&ps3fb.wait_vsync); 1004 init_waitqueue_head(&ps3fb.wait_vsync);
1118 1005
1119 ps3fb_set_sync(&dev->core); 1006#ifdef HEAD_A
1007 status = lv1_gpu_display_sync(0x0, 0, L1GPU_DISPLAY_SYNC_VSYNC);
1008 if (status) {
1009 dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d\n",
1010 __func__, status);
1011 retval = -ENODEV;
1012 goto err_close_device;
1013 }
1014#endif
1015#ifdef HEAD_B
1016 status = lv1_gpu_display_sync(0x0, 1, L1GPU_DISPLAY_SYNC_VSYNC);
1017 if (status) {
1018 dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d\n",
1019 __func__, status);
1020 retval = -ENODEV;
1021 goto err_close_device;
1022 }
1023#endif
1120 1024
1121 max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; 1025 max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;
1122 if (ps3fb_videomemory.size > max_ps3fb_size) { 1026 if (ps3fb_videomemory.size > max_ps3fb_size) {
@@ -1131,7 +1035,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1131 if (status) { 1035 if (status) {
1132 dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n", 1036 dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
1133 __func__, status); 1037 __func__, status);
1134 goto err; 1038 goto err_close_device;
1135 } 1039 }
1136 dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar); 1040 dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
1137 1041
@@ -1141,33 +1045,85 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1141 &lpar_reports, &lpar_reports_size); 1045 &lpar_reports, &lpar_reports_size);
1142 if (status) { 1046 if (status) {
1143 dev_err(&dev->core, 1047 dev_err(&dev->core,
1144 "%s: lv1_gpu_context_attribute failed: %d\n", __func__, 1048 "%s: lv1_gpu_context_allocate failed: %d\n", __func__,
1145 status); 1049 status);
1146 goto err_gpu_memory_free; 1050 goto err_gpu_memory_free;
1147 } 1051 }
1148 1052
1149 /* vsync interrupt */ 1053 /* vsync interrupt */
1150 ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); 1054 dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
1151 if (!ps3fb.dinfo) { 1055 if (!dinfo) {
1152 dev_err(&dev->core, "%s: ioremap failed\n", __func__); 1056 dev_err(&dev->core, "%s: ioremap failed\n", __func__);
1153 goto err_gpu_context_free; 1057 goto err_gpu_context_free;
1154 } 1058 }
1155 1059
1156 retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core); 1060 ps3fb.dinfo = dinfo;
1157 if (retval) 1061 dev_dbg(&dev->core, "version_driver:%x\n", dinfo->version_driver);
1062 dev_dbg(&dev->core, "irq outlet:%x\n", dinfo->irq.irq_outlet);
1063 dev_dbg(&dev->core, "version_gpu: %x memory_size: %x ch: %x "
1064 "core_freq: %d mem_freq:%d\n", dinfo->version_gpu,
1065 dinfo->memory_size, dinfo->hardware_channel,
1066 dinfo->nvcore_frequency/1000000,
1067 dinfo->memory_frequency/1000000);
1068
1069 if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
1070 dev_err(&dev->core, "%s: version_driver err:%x\n", __func__,
1071 dinfo->version_driver);
1072 retval = -EINVAL;
1073 goto err_iounmap_dinfo;
1074 }
1075
1076 retval = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
1077 &ps3fb.irq_no);
1078 if (retval) {
1079 dev_err(&dev->core, "%s: ps3_alloc_irq failed %d\n", __func__,
1080 retval);
1158 goto err_iounmap_dinfo; 1081 goto err_iounmap_dinfo;
1082 }
1083
1084 retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
1085 IRQF_DISABLED, DEVICE_NAME, &dev->core);
1086 if (retval) {
1087 dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
1088 retval);
1089 goto err_destroy_plug;
1090 }
1091
1092 dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
1093 (1 << GPU_INTR_STATUS_FLIP_1);
1159 1094
1160 /* Clear memory to prevent kernel info leakage into userspace */ 1095 /* Clear memory to prevent kernel info leakage into userspace */
1161 memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); 1096 memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size);
1162 1097
1163 xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); 1098 xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
1164 retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); 1099
1165 if (retval) 1100 status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
1101 xdr_lpar, ps3fb_videomemory.size,
1102 CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
1103 CBE_IOPTE_M);
1104 if (status) {
1105 dev_err(&dev->core, "%s: lv1_gpu_context_iomap failed: %d\n",
1106 __func__, status);
1107 retval = -ENXIO;
1166 goto err_free_irq; 1108 goto err_free_irq;
1109 }
1110
1111 dev_dbg(&dev->core, "video:%p ioif:%lx lpar:%llx size:%lx\n",
1112 ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
1113 ps3fb_videomemory.size);
1114
1115 status = lv1_gpu_fb_setup(ps3fb.context_handle, xdr_lpar,
1116 GPU_CMD_BUF_SIZE, GPU_IOIF);
1117 if (status) {
1118 dev_err(&dev->core, "%s: lv1_gpu_fb_setup failed: %d\n",
1119 __func__, status);
1120 retval = -ENXIO;
1121 goto err_context_unmap;
1122 }
1167 1123
1168 info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); 1124 info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
1169 if (!info) 1125 if (!info)
1170 goto err_free_irq; 1126 goto err_context_fb_close;
1171 1127
1172 par = info->par; 1128 par = info->par;
1173 par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ 1129 par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */
@@ -1210,7 +1166,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1210 if (retval < 0) 1166 if (retval < 0)
1211 goto err_fb_dealloc; 1167 goto err_fb_dealloc;
1212 1168
1213 dev->core.driver_data = info; 1169 ps3_system_bus_set_drvdata(dev, info);
1214 1170
1215 dev_info(info->device, "%s %s, using %u KiB of video memory\n", 1171 dev_info(info->device, "%s %s, using %u KiB of video memory\n",
1216 dev_driver_string(info->dev), dev_name(info->dev), 1172 dev_driver_string(info->dev), dev_name(info->dev),
@@ -1232,8 +1188,14 @@ err_fb_dealloc:
1232 fb_dealloc_cmap(&info->cmap); 1188 fb_dealloc_cmap(&info->cmap);
1233err_framebuffer_release: 1189err_framebuffer_release:
1234 framebuffer_release(info); 1190 framebuffer_release(info);
1191err_context_fb_close:
1192 lv1_gpu_fb_close(ps3fb.context_handle);
1193err_context_unmap:
1194 lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
1195 ps3fb_videomemory.size, CBE_IOPTE_M);
1235err_free_irq: 1196err_free_irq:
1236 free_irq(ps3fb.irq_no, &dev->core); 1197 free_irq(ps3fb.irq_no, &dev->core);
1198err_destroy_plug:
1237 ps3_irq_plug_destroy(ps3fb.irq_no); 1199 ps3_irq_plug_destroy(ps3fb.irq_no);
1238err_iounmap_dinfo: 1200err_iounmap_dinfo:
1239 iounmap((u8 __force __iomem *)ps3fb.dinfo); 1201 iounmap((u8 __force __iomem *)ps3fb.dinfo);
@@ -1241,14 +1203,16 @@ err_gpu_context_free:
1241 lv1_gpu_context_free(ps3fb.context_handle); 1203 lv1_gpu_context_free(ps3fb.context_handle);
1242err_gpu_memory_free: 1204err_gpu_memory_free:
1243 lv1_gpu_memory_free(ps3fb.memory_handle); 1205 lv1_gpu_memory_free(ps3fb.memory_handle);
1206err_close_device:
1207 ps3_close_hv_device(dev);
1244err: 1208err:
1245 return retval; 1209 return retval;
1246} 1210}
1247 1211
1248static int ps3fb_shutdown(struct ps3_system_bus_device *dev) 1212static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
1249{ 1213{
1250 int status; 1214 struct fb_info *info = ps3_system_bus_get_drvdata(dev);
1251 struct fb_info *info = dev->core.driver_data; 1215 u64 xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
1252 1216
1253 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); 1217 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
1254 1218
@@ -1268,20 +1232,14 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
1268 unregister_framebuffer(info); 1232 unregister_framebuffer(info);
1269 fb_dealloc_cmap(&info->cmap); 1233 fb_dealloc_cmap(&info->cmap);
1270 framebuffer_release(info); 1234 framebuffer_release(info);
1271 info = dev->core.driver_data = NULL; 1235 ps3_system_bus_set_drvdata(dev, NULL);
1272 } 1236 }
1273 iounmap((u8 __force __iomem *)ps3fb.dinfo); 1237 iounmap((u8 __force __iomem *)ps3fb.dinfo);
1274 1238 lv1_gpu_fb_close(ps3fb.context_handle);
1275 status = lv1_gpu_context_free(ps3fb.context_handle); 1239 lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
1276 if (status) 1240 ps3fb_videomemory.size, CBE_IOPTE_M);
1277 dev_dbg(&dev->core, "lv1_gpu_context_free failed: %d\n", 1241 lv1_gpu_context_free(ps3fb.context_handle);
1278 status); 1242 lv1_gpu_memory_free(ps3fb.memory_handle);
1279
1280 status = lv1_gpu_memory_free(ps3fb.memory_handle);
1281 if (status)
1282 dev_dbg(&dev->core, "lv1_gpu_memory_free failed: %d\n",
1283 status);
1284
1285 ps3_close_hv_device(dev); 1243 ps3_close_hv_device(dev);
1286 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 1244 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
1287 1245