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 | ||