diff options
Diffstat (limited to 'drivers/video/ps3fb.c')
| -rw-r--r-- | drivers/video/ps3fb.c | 272 |
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 | ||
| 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 = { | 944 | static 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 | ||
| 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) | 969 | static 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); |
| 1233 | err_framebuffer_release: | 1189 | err_framebuffer_release: |
| 1234 | framebuffer_release(info); | 1190 | framebuffer_release(info); |
| 1191 | err_context_fb_close: | ||
| 1192 | lv1_gpu_fb_close(ps3fb.context_handle); | ||
| 1193 | err_context_unmap: | ||
| 1194 | lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar, | ||
| 1195 | ps3fb_videomemory.size, CBE_IOPTE_M); | ||
| 1235 | err_free_irq: | 1196 | err_free_irq: |
| 1236 | free_irq(ps3fb.irq_no, &dev->core); | 1197 | free_irq(ps3fb.irq_no, &dev->core); |
| 1198 | err_destroy_plug: | ||
| 1237 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1199 | ps3_irq_plug_destroy(ps3fb.irq_no); |
| 1238 | err_iounmap_dinfo: | 1200 | err_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); |
| 1242 | err_gpu_memory_free: | 1204 | err_gpu_memory_free: |
| 1243 | lv1_gpu_memory_free(ps3fb.memory_handle); | 1205 | lv1_gpu_memory_free(ps3fb.memory_handle); |
| 1206 | err_close_device: | ||
| 1207 | ps3_close_hv_device(dev); | ||
| 1244 | err: | 1208 | err: |
| 1245 | return retval; | 1209 | return retval; |
| 1246 | } | 1210 | } |
| 1247 | 1211 | ||
| 1248 | static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | 1212 | static 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 | ||
