forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/drivers/video/fbdev/core/fbmem.c
....@@ -28,13 +28,13 @@
2828 #include <linux/seq_file.h>
2929 #include <linux/console.h>
3030 #include <linux/kmod.h>
31
-#include <linux/dma-buf.h>
3231 #include <linux/err.h>
3332 #include <linux/device.h>
3433 #include <linux/efi.h>
3534 #include <linux/fb.h>
3635 #include <linux/fbcon.h>
3736 #include <linux/mem_encrypt.h>
37
+#include <linux/pci.h>
3838
3939 #include <asm/fb.h>
4040
....@@ -52,6 +52,10 @@
5252
5353 int num_registered_fb __read_mostly;
5454 EXPORT_SYMBOL(num_registered_fb);
55
+
56
+bool fb_center_logo __read_mostly;
57
+
58
+int fb_logo_count __read_mostly = -1;
5559
5660 static struct fb_info *get_fb_info(unsigned int idx)
5761 {
....@@ -76,17 +80,6 @@
7680 if (fb_info->fbops->fb_destroy)
7781 fb_info->fbops->fb_destroy(fb_info);
7882 }
79
-
80
-int lock_fb_info(struct fb_info *info)
81
-{
82
- mutex_lock(&info->lock);
83
- if (!info->fbops) {
84
- mutex_unlock(&info->lock);
85
- return 0;
86
- }
87
- return 1;
88
-}
89
-EXPORT_SYMBOL(lock_fb_info);
9083
9184 /*
9285 * Helpers
....@@ -509,8 +502,24 @@
509502 fb_set_logo(info, logo, logo_new, fb_logo.depth);
510503 }
511504
512
- image.dx = 0;
513
- image.dy = y;
505
+ if (fb_center_logo) {
506
+ int xres = info->var.xres;
507
+ int yres = info->var.yres;
508
+
509
+ if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) {
510
+ xres = info->var.yres;
511
+ yres = info->var.xres;
512
+ }
513
+
514
+ while (n && (n * (logo->width + 8) - 8 > xres))
515
+ --n;
516
+ image.dx = (xres - (n * (logo->width + 8) - 8)) / 2;
517
+ image.dy = y ?: (yres - logo->height) / 2;
518
+ } else {
519
+ image.dx = 0;
520
+ image.dy = y;
521
+ }
522
+
514523 image.width = logo->width;
515524 image.height = logo->height;
516525
....@@ -528,7 +537,7 @@
528537 info->pseudo_palette = saved_pseudo_palette;
529538 kfree(logo_new);
530539 kfree(logo_rotate);
531
- return logo->height;
540
+ return image.dy + logo->height;
532541 }
533542
534543
....@@ -580,8 +589,8 @@
580589 unsigned int i;
581590
582591 for (i = 0; i < fb_logo_ex_num; i++)
583
- y += fb_show_logo_line(info, rotate,
584
- fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
592
+ y = fb_show_logo_line(info, rotate,
593
+ fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
585594
586595 return y;
587596 }
....@@ -607,11 +616,12 @@
607616 {
608617 int depth = fb_get_color_depth(&info->var, &info->fix);
609618 unsigned int yres;
619
+ int height;
610620
611621 memset(&fb_logo, 0, sizeof(struct logo_data));
612622
613623 if (info->flags & FBINFO_MISC_TILEBLITTING ||
614
- info->fbops->owner)
624
+ info->fbops->owner || !fb_logo_count)
615625 return 0;
616626
617627 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
....@@ -653,30 +663,38 @@
653663 fb_logo.depth = 1;
654664
655665
656
- if (fb_logo.depth > 4 && depth > 4) {
657
- switch (info->fix.visual) {
658
- case FB_VISUAL_TRUECOLOR:
659
- fb_logo.needs_truepalette = 1;
660
- break;
661
- case FB_VISUAL_DIRECTCOLOR:
662
- fb_logo.needs_directpalette = 1;
663
- fb_logo.needs_cmapreset = 1;
664
- break;
665
- case FB_VISUAL_PSEUDOCOLOR:
666
- fb_logo.needs_cmapreset = 1;
667
- break;
668
- }
669
- }
666
+ if (fb_logo.depth > 4 && depth > 4) {
667
+ switch (info->fix.visual) {
668
+ case FB_VISUAL_TRUECOLOR:
669
+ fb_logo.needs_truepalette = 1;
670
+ break;
671
+ case FB_VISUAL_DIRECTCOLOR:
672
+ fb_logo.needs_directpalette = 1;
673
+ fb_logo.needs_cmapreset = 1;
674
+ break;
675
+ case FB_VISUAL_PSEUDOCOLOR:
676
+ fb_logo.needs_cmapreset = 1;
677
+ break;
678
+ }
679
+ }
670680
671
- return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
681
+ height = fb_logo.logo->height;
682
+ if (fb_center_logo)
683
+ height += (yres - fb_logo.logo->height) / 2;
684
+
685
+ return fb_prepare_extra_logos(info, height, yres);
672686 }
673687
674688 int fb_show_logo(struct fb_info *info, int rotate)
675689 {
690
+ unsigned int count;
676691 int y;
677692
678
- y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
679
- num_online_cpus());
693
+ if (!fb_logo_count)
694
+ return 0;
695
+
696
+ count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count;
697
+ y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count);
680698 y = fb_show_extra_logos(info, y, rotate);
681699
682700 return y;
....@@ -759,7 +777,7 @@
759777
760778 if (info->fbops->fb_read)
761779 return info->fbops->fb_read(info, buf, count, ppos);
762
-
780
+
763781 total_size = info->screen_size;
764782
765783 if (total_size == 0)
....@@ -824,7 +842,7 @@
824842
825843 if (info->fbops->fb_write)
826844 return info->fbops->fb_write(info, buf, count, ppos);
827
-
845
+
828846 total_size = info->screen_size;
829847
830848 if (total_size == 0)
....@@ -919,16 +937,13 @@
919937 static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
920938 u32 activate)
921939 {
922
- struct fb_event event;
923940 struct fb_blit_caps caps, fbcaps;
924941 int err = 0;
925942
926943 memset(&caps, 0, sizeof(caps));
927944 memset(&fbcaps, 0, sizeof(fbcaps));
928945 caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
929
- event.info = info;
930
- event.data = &caps;
931
- fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
946
+ fbcon_get_requirement(info, &caps);
932947 info->fbops->fb_get_caps(info, &fbcaps, var);
933948
934949 if (((fbcaps.x ^ caps.x) & caps.x) ||
....@@ -942,8 +957,12 @@
942957 int
943958 fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
944959 {
945
- int flags = info->flags;
946960 int ret = 0;
961
+ u32 activate;
962
+ struct fb_var_screeninfo old_var;
963
+ struct fb_videomode mode;
964
+ struct fb_event event;
965
+ u32 unused;
947966
948967 if (var->activate & FB_ACTIVATE_INV_MODE) {
949968 struct fb_videomode mode1, mode2;
....@@ -952,182 +971,144 @@
952971 fb_var_to_videomode(&mode2, &info->var);
953972 /* make sure we don't delete the videomode of current var */
954973 ret = fb_mode_is_equal(&mode1, &mode2);
955
-
956974 if (!ret) {
957
- struct fb_event event;
958
-
959
- event.info = info;
960
- event.data = &mode1;
961
- ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event);
975
+ ret = fbcon_mode_deleted(info, &mode1);
976
+ if (!ret)
977
+ fb_delete_videomode(&mode1, &info->modelist);
962978 }
963979
964
- if (!ret)
965
- fb_delete_videomode(&mode1, &info->modelist);
966
-
967
-
968
- ret = (ret) ? -EINVAL : 0;
969
- goto done;
980
+ return ret ? -EINVAL : 0;
970981 }
971982
972
- if ((var->activate & FB_ACTIVATE_FORCE) ||
973
- memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
974
- u32 activate = var->activate;
975
- u32 unused;
983
+ if (!(var->activate & FB_ACTIVATE_FORCE) &&
984
+ !memcmp(&info->var, var, sizeof(struct fb_var_screeninfo)))
985
+ return 0;
976986
977
- /* When using FOURCC mode, make sure the red, green, blue and
978
- * transp fields are set to 0.
979
- */
980
- if ((info->fix.capabilities & FB_CAP_FOURCC) &&
981
- var->grayscale > 1) {
982
- if (var->red.offset || var->green.offset ||
983
- var->blue.offset || var->transp.offset ||
984
- var->red.length || var->green.length ||
985
- var->blue.length || var->transp.length ||
986
- var->red.msb_right || var->green.msb_right ||
987
- var->blue.msb_right || var->transp.msb_right)
988
- return -EINVAL;
989
- }
987
+ activate = var->activate;
990988
991
- if (!info->fbops->fb_check_var) {
992
- *var = info->var;
993
- goto done;
994
- }
995
-
996
- /* bitfill_aligned() assumes that it's at least 8x8 */
997
- if (var->xres < 8 || var->yres < 8)
989
+ /* When using FOURCC mode, make sure the red, green, blue and
990
+ * transp fields are set to 0.
991
+ */
992
+ if ((info->fix.capabilities & FB_CAP_FOURCC) &&
993
+ var->grayscale > 1) {
994
+ if (var->red.offset || var->green.offset ||
995
+ var->blue.offset || var->transp.offset ||
996
+ var->red.length || var->green.length ||
997
+ var->blue.length || var->transp.length ||
998
+ var->red.msb_right || var->green.msb_right ||
999
+ var->blue.msb_right || var->transp.msb_right)
9981000 return -EINVAL;
1001
+ }
9991002
1000
- /* Too huge resolution causes multiplication overflow. */
1001
- if (check_mul_overflow(var->xres, var->yres, &unused) ||
1002
- check_mul_overflow(var->xres_virtual, var->yres_virtual, &unused))
1003
- return -EINVAL;
1003
+ if (!info->fbops->fb_check_var) {
1004
+ *var = info->var;
1005
+ return 0;
1006
+ }
10041007
1005
- ret = info->fbops->fb_check_var(var, info);
1008
+ /* bitfill_aligned() assumes that it's at least 8x8 */
1009
+ if (var->xres < 8 || var->yres < 8)
1010
+ return -EINVAL;
1011
+
1012
+ /* Too huge resolution causes multiplication overflow. */
1013
+ if (check_mul_overflow(var->xres, var->yres, &unused) ||
1014
+ check_mul_overflow(var->xres_virtual, var->yres_virtual, &unused))
1015
+ return -EINVAL;
1016
+
1017
+ ret = info->fbops->fb_check_var(var, info);
1018
+
1019
+ if (ret)
1020
+ return ret;
1021
+
1022
+ /* verify that virtual resolution >= physical resolution */
1023
+ if (var->xres_virtual < var->xres ||
1024
+ var->yres_virtual < var->yres) {
1025
+ pr_warn("WARNING: fbcon: Driver '%s' missed to adjust virtual screen size (%ux%u vs. %ux%u)\n",
1026
+ info->fix.id,
1027
+ var->xres_virtual, var->yres_virtual,
1028
+ var->xres, var->yres);
1029
+ return -EINVAL;
1030
+ }
1031
+
1032
+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
1033
+ return 0;
1034
+
1035
+ if (info->fbops->fb_get_caps) {
1036
+ ret = fb_check_caps(info, var, activate);
10061037
10071038 if (ret)
1008
- goto done;
1039
+ return ret;
1040
+ }
10091041
1010
- if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
1011
- struct fb_var_screeninfo old_var;
1012
- struct fb_videomode mode;
1042
+ old_var = info->var;
1043
+ info->var = *var;
10131044
1014
- if (info->fbops->fb_get_caps) {
1015
- ret = fb_check_caps(info, var, activate);
1045
+ if (info->fbops->fb_set_par) {
1046
+ ret = info->fbops->fb_set_par(info);
10161047
1017
- if (ret)
1018
- goto done;
1019
- }
1020
-
1021
- old_var = info->var;
1022
- info->var = *var;
1023
-
1024
- if (info->fbops->fb_set_par) {
1025
- ret = info->fbops->fb_set_par(info);
1026
-
1027
- if (ret) {
1028
- info->var = old_var;
1029
- printk(KERN_WARNING "detected "
1030
- "fb_set_par error, "
1031
- "error code: %d\n", ret);
1032
- goto done;
1033
- }
1034
- }
1035
-
1036
- fb_pan_display(info, &info->var);
1037
- fb_set_cmap(&info->cmap, info);
1038
- fb_var_to_videomode(&mode, &info->var);
1039
-
1040
- if (info->modelist.prev && info->modelist.next &&
1041
- !list_empty(&info->modelist))
1042
- ret = fb_add_videomode(&mode, &info->modelist);
1043
-
1044
- if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
1045
- struct fb_event event;
1046
- int evnt = (activate & FB_ACTIVATE_ALL) ?
1047
- FB_EVENT_MODE_CHANGE_ALL :
1048
- FB_EVENT_MODE_CHANGE;
1049
-
1050
- info->flags &= ~FBINFO_MISC_USEREVENT;
1051
- event.info = info;
1052
- event.data = &mode;
1053
- fb_notifier_call_chain(evnt, &event);
1054
- }
1048
+ if (ret) {
1049
+ info->var = old_var;
1050
+ printk(KERN_WARNING "detected "
1051
+ "fb_set_par error, "
1052
+ "error code: %d\n", ret);
1053
+ return ret;
10551054 }
10561055 }
10571056
1058
- done:
1059
- return ret;
1057
+ fb_pan_display(info, &info->var);
1058
+ fb_set_cmap(&info->cmap, info);
1059
+ fb_var_to_videomode(&mode, &info->var);
1060
+
1061
+ if (info->modelist.prev && info->modelist.next &&
1062
+ !list_empty(&info->modelist))
1063
+ ret = fb_add_videomode(&mode, &info->modelist);
1064
+
1065
+ if (ret)
1066
+ return ret;
1067
+
1068
+ event.info = info;
1069
+ event.data = &mode;
1070
+ fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event);
1071
+
1072
+ return 0;
10601073 }
10611074 EXPORT_SYMBOL(fb_set_var);
10621075
10631076 int
10641077 fb_blank(struct fb_info *info, int blank)
1065
-{
1078
+{
10661079 struct fb_event event;
1067
- int ret = -EINVAL, early_ret;
1080
+ int ret = -EINVAL;
10681081
1069
- if (blank > FB_BLANK_POWERDOWN)
1070
- blank = FB_BLANK_POWERDOWN;
1082
+ if (blank > FB_BLANK_POWERDOWN)
1083
+ blank = FB_BLANK_POWERDOWN;
10711084
10721085 event.info = info;
10731086 event.data = &blank;
10741087
1075
- early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
1076
-
10771088 if (info->fbops->fb_blank)
1078
- ret = info->fbops->fb_blank(blank, info);
1089
+ ret = info->fbops->fb_blank(blank, info);
10791090
10801091 if (!ret)
10811092 fb_notifier_call_chain(FB_EVENT_BLANK, &event);
1082
- else {
1083
- /*
1084
- * if fb_blank is failed then revert effects of
1085
- * the early blank event.
1086
- */
1087
- if (!early_ret)
1088
- fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
1089
- }
10901093
1091
- return ret;
1094
+ return ret;
10921095 }
10931096 EXPORT_SYMBOL(fb_blank);
1094
-
1095
-static int fb_get_dmabuf(struct fb_info *info, int flags)
1096
-{
1097
-#ifdef CONFIG_DMA_SHARED_BUFFER
1098
- struct dma_buf *dmabuf;
1099
-
1100
- if (!info->fbops->fb_dmabuf_export)
1101
- return -ENOTTY;
1102
-
1103
- dmabuf = info->fbops->fb_dmabuf_export(info);
1104
- if (IS_ERR(dmabuf))
1105
- return PTR_ERR(dmabuf);
1106
-
1107
- return dma_buf_fd(dmabuf, flags);
1108
-#else
1109
- return -ENOTTY;
1110
-#endif
1111
-}
11121097
11131098 static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
11141099 unsigned long arg)
11151100 {
1116
- struct fb_ops *fb;
1101
+ const struct fb_ops *fb;
11171102 struct fb_var_screeninfo var;
11181103 struct fb_fix_screeninfo fix;
1119
- struct fb_con2fbmap con2fb;
11201104 struct fb_cmap cmap_from;
11211105 struct fb_cmap_user cmap;
1122
- struct fb_event event;
1123
- struct fb_dmabuf_export dmaexp;
11241106 void __user *argp = (void __user *)arg;
11251107 long ret = 0;
11261108
11271109 switch (cmd) {
11281110 case FBIOGET_VSCREENINFO:
1129
- if (!lock_fb_info(info))
1130
- return -ENODEV;
1111
+ lock_fb_info(info);
11311112 var = info->var;
11321113 unlock_fb_info(info);
11331114
....@@ -1136,23 +1117,25 @@
11361117 case FBIOPUT_VSCREENINFO:
11371118 if (copy_from_user(&var, argp, sizeof(var)))
11381119 return -EFAULT;
1120
+ /* only for kernel-internal use */
1121
+ var.activate &= ~FB_ACTIVATE_KD_TEXT;
11391122 console_lock();
1140
- if (!lock_fb_info(info)) {
1141
- console_unlock();
1142
- return -ENODEV;
1143
- }
1144
- info->flags |= FBINFO_MISC_USEREVENT;
1145
- ret = fb_set_var(info, &var);
1146
- info->flags &= ~FBINFO_MISC_USEREVENT;
1123
+ lock_fb_info(info);
1124
+ ret = fbcon_modechange_possible(info, &var);
1125
+ if (!ret)
1126
+ ret = fb_set_var(info, &var);
1127
+ if (!ret)
1128
+ fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
11471129 unlock_fb_info(info);
11481130 console_unlock();
11491131 if (!ret && copy_to_user(argp, &var, sizeof(var)))
11501132 ret = -EFAULT;
11511133 break;
11521134 case FBIOGET_FSCREENINFO:
1153
- if (!lock_fb_info(info))
1154
- return -ENODEV;
1135
+ lock_fb_info(info);
11551136 memcpy(&fix, &info->fix, sizeof(fix));
1137
+ if (info->flags & FBINFO_HIDE_SMEM_START)
1138
+ fix.smem_start = 0;
11561139 unlock_fb_info(info);
11571140
11581141 ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
....@@ -1165,8 +1148,7 @@
11651148 case FBIOGETCMAP:
11661149 if (copy_from_user(&cmap, argp, sizeof(cmap)))
11671150 return -EFAULT;
1168
- if (!lock_fb_info(info))
1169
- return -ENODEV;
1151
+ lock_fb_info(info);
11701152 cmap_from = info->cmap;
11711153 unlock_fb_info(info);
11721154 ret = fb_cmap_to_user(&cmap_from, &cmap);
....@@ -1175,10 +1157,7 @@
11751157 if (copy_from_user(&var, argp, sizeof(var)))
11761158 return -EFAULT;
11771159 console_lock();
1178
- if (!lock_fb_info(info)) {
1179
- console_unlock();
1180
- return -ENODEV;
1181
- }
1160
+ lock_fb_info(info);
11821161 ret = fb_pan_display(info, &var);
11831162 unlock_fb_info(info);
11841163 console_unlock();
....@@ -1189,73 +1168,22 @@
11891168 ret = -EINVAL;
11901169 break;
11911170 case FBIOGET_CON2FBMAP:
1192
- if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
1193
- return -EFAULT;
1194
- if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
1195
- return -EINVAL;
1196
- con2fb.framebuffer = -1;
1197
- event.data = &con2fb;
1198
- if (!lock_fb_info(info))
1199
- return -ENODEV;
1200
- event.info = info;
1201
- fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
1202
- unlock_fb_info(info);
1203
- ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
1171
+ ret = fbcon_get_con2fb_map_ioctl(argp);
12041172 break;
12051173 case FBIOPUT_CON2FBMAP:
1206
- if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
1207
- return -EFAULT;
1208
- if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
1209
- return -EINVAL;
1210
- if (con2fb.framebuffer >= FB_MAX)
1211
- return -EINVAL;
1212
- if (!registered_fb[con2fb.framebuffer])
1213
- request_module("fb%d", con2fb.framebuffer);
1214
- if (!registered_fb[con2fb.framebuffer]) {
1215
- ret = -EINVAL;
1216
- break;
1217
- }
1218
- event.data = &con2fb;
1219
- console_lock();
1220
- if (!lock_fb_info(info)) {
1221
- console_unlock();
1222
- return -ENODEV;
1223
- }
1224
- event.info = info;
1225
- ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
1226
- unlock_fb_info(info);
1227
- console_unlock();
1174
+ ret = fbcon_set_con2fb_map_ioctl(argp);
12281175 break;
12291176 case FBIOBLANK:
12301177 console_lock();
1231
- if (!lock_fb_info(info)) {
1232
- console_unlock();
1233
- return -ENODEV;
1234
- }
1235
- info->flags |= FBINFO_MISC_USEREVENT;
1178
+ lock_fb_info(info);
12361179 ret = fb_blank(info, arg);
1237
- info->flags &= ~FBINFO_MISC_USEREVENT;
1180
+ /* might again call into fb_blank */
1181
+ fbcon_fb_blanked(info, arg);
12381182 unlock_fb_info(info);
12391183 console_unlock();
12401184 break;
1241
- case FBIOGET_DMABUF:
1242
- if (copy_from_user(&dmaexp, argp, sizeof(dmaexp)))
1243
- return -EFAULT;
1244
-
1245
- if (!lock_fb_info(info))
1246
- return -ENODEV;
1247
- ret = fb_get_dmabuf(info, dmaexp.flags);
1248
- unlock_fb_info(info);
1249
-
1250
- if (ret < 0)
1251
- return ret;
1252
- dmaexp.fd = ret;
1253
-
1254
- ret = copy_to_user(argp, &dmaexp, sizeof(dmaexp)) ? -EFAULT : 0;
1255
- break;
12561185 default:
1257
- if (!lock_fb_info(info))
1258
- return -ENODEV;
1186
+ lock_fb_info(info);
12591187 fb = info->fbops;
12601188 if (fb->fb_ioctl)
12611189 ret = fb->fb_ioctl(info, cmd, arg);
....@@ -1375,9 +1303,10 @@
13751303 {
13761304 struct fb_fix_screeninfo fix;
13771305
1378
- if (!lock_fb_info(info))
1379
- return -ENODEV;
1306
+ lock_fb_info(info);
13801307 fix = info->fix;
1308
+ if (info->flags & FBINFO_HIDE_SMEM_START)
1309
+ fix.smem_start = 0;
13811310 unlock_fb_info(info);
13821311 return do_fscreeninfo_to_user(&fix, compat_ptr(arg));
13831312 }
....@@ -1386,7 +1315,7 @@
13861315 unsigned long arg)
13871316 {
13881317 struct fb_info *info = file_fb_info(file);
1389
- struct fb_ops *fb;
1318
+ const struct fb_ops *fb;
13901319 long ret = -ENOIOCTLCMD;
13911320
13921321 if (!info)
....@@ -1398,9 +1327,8 @@
13981327 case FBIOPAN_DISPLAY:
13991328 case FBIOGET_CON2FBMAP:
14001329 case FBIOPUT_CON2FBMAP:
1401
- case FBIOGET_DMABUF:
14021330 arg = (unsigned long) compat_ptr(arg);
1403
- /* fall through */
1331
+ fallthrough;
14041332 case FBIOBLANK:
14051333 ret = do_fb_ioctl(info, cmd, arg);
14061334 break;
....@@ -1427,18 +1355,23 @@
14271355 fb_mmap(struct file *file, struct vm_area_struct * vma)
14281356 {
14291357 struct fb_info *info = file_fb_info(file);
1430
- struct fb_ops *fb;
1358
+ int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
14311359 unsigned long mmio_pgoff;
14321360 unsigned long start;
14331361 u32 len;
14341362
14351363 if (!info)
14361364 return -ENODEV;
1437
- fb = info->fbops;
1438
- if (!fb)
1439
- return -ENODEV;
14401365 mutex_lock(&info->mm_lock);
1441
- if (fb->fb_mmap) {
1366
+
1367
+ fb_mmap_fn = info->fbops->fb_mmap;
1368
+
1369
+#if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
1370
+ if (info->fbdefio)
1371
+ fb_mmap_fn = fb_deferred_io_mmap;
1372
+#endif
1373
+
1374
+ if (fb_mmap_fn) {
14421375 int res;
14431376
14441377 /*
....@@ -1446,7 +1379,7 @@
14461379 * SME protection is removed ahead of the call
14471380 */
14481381 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
1449
- res = fb->fb_mmap(info, vma);
1382
+ res = fb_mmap_fn(info, vma);
14501383 mutex_unlock(&info->mm_lock);
14511384 return res;
14521385 }
....@@ -1500,7 +1433,7 @@
15001433 if (IS_ERR(info))
15011434 return PTR_ERR(info);
15021435
1503
- mutex_lock(&info->lock);
1436
+ lock_fb_info(info);
15041437 if (!try_module_get(info->fbops->owner)) {
15051438 res = -ENODEV;
15061439 goto out;
....@@ -1516,24 +1449,24 @@
15161449 fb_deferred_io_open(info, inode, file);
15171450 #endif
15181451 out:
1519
- mutex_unlock(&info->lock);
1452
+ unlock_fb_info(info);
15201453 if (res)
15211454 put_fb_info(info);
15221455 return res;
15231456 }
15241457
1525
-static int
1458
+static int
15261459 fb_release(struct inode *inode, struct file *file)
15271460 __acquires(&info->lock)
15281461 __releases(&info->lock)
15291462 {
15301463 struct fb_info * const info = file->private_data;
15311464
1532
- mutex_lock(&info->lock);
1465
+ lock_fb_info(info);
15331466 if (info->fbops->fb_release)
15341467 info->fbops->fb_release(info,1);
15351468 module_put(info->fbops->owner);
1536
- mutex_unlock(&info->lock);
1469
+ unlock_fb_info(info);
15371470 put_fb_info(info);
15381471 return 0;
15391472 }
....@@ -1638,13 +1571,13 @@
16381571 return false;
16391572 }
16401573
1641
-static int do_unregister_framebuffer(struct fb_info *fb_info);
1574
+static void do_unregister_framebuffer(struct fb_info *fb_info);
16421575
16431576 #define VGA_FB_PHYS 0xA0000
1644
-static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
1645
- const char *name, bool primary)
1577
+static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
1578
+ const char *name, bool primary)
16461579 {
1647
- int i, ret;
1580
+ int i;
16481581
16491582 /* check all firmware fbs and kick off if the base addr overlaps */
16501583 for_each_registered_fb(i) {
....@@ -1658,15 +1591,11 @@
16581591 (primary && gen_aper && gen_aper->count &&
16591592 gen_aper->ranges[0].base == VGA_FB_PHYS)) {
16601593
1661
- printk(KERN_INFO "fb: switching to %s from %s\n",
1662
- name, registered_fb[i]->fix.id);
1663
- ret = do_unregister_framebuffer(registered_fb[i]);
1664
- if (ret)
1665
- return ret;
1594
+ printk(KERN_INFO "fb%d: switching to %s from %s\n",
1595
+ i, name, registered_fb[i]->fix.id);
1596
+ do_unregister_framebuffer(registered_fb[i]);
16661597 }
16671598 }
1668
-
1669
- return 0;
16701599 }
16711600
16721601 static bool lockless_register_fb;
....@@ -1677,17 +1606,14 @@
16771606 static int do_register_framebuffer(struct fb_info *fb_info)
16781607 {
16791608 int i, ret;
1680
- struct fb_event event;
16811609 struct fb_videomode mode;
16821610
16831611 if (fb_check_foreignness(fb_info))
16841612 return -ENOSYS;
16851613
1686
- ret = do_remove_conflicting_framebuffers(fb_info->apertures,
1687
- fb_info->fix.id,
1688
- fb_is_primary_device(fb_info));
1689
- if (ret)
1690
- return ret;
1614
+ do_remove_conflicting_framebuffers(fb_info->apertures,
1615
+ fb_info->fix.id,
1616
+ fb_is_primary_device(fb_info));
16911617
16921618 if (num_registered_fb == FB_MAX)
16931619 return -ENXIO;
....@@ -1719,7 +1645,7 @@
17191645 fb_info->pixmap.access_align = 32;
17201646 fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
17211647 }
1722
- }
1648
+ }
17231649 fb_info->pixmap.offset = 0;
17241650
17251651 if (!fb_info->pixmap.blit_x)
....@@ -1740,20 +1666,22 @@
17401666 fb_add_videomode(&mode, &fb_info->modelist);
17411667 registered_fb[i] = fb_info;
17421668
1743
- event.info = fb_info;
1669
+#ifdef CONFIG_GUMSTIX_AM200EPD
1670
+ {
1671
+ struct fb_event event;
1672
+ event.info = fb_info;
1673
+ fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
1674
+ }
1675
+#endif
1676
+
17441677 if (!lockless_register_fb)
17451678 console_lock();
17461679 else
17471680 atomic_inc(&ignore_console_lock_warning);
1748
- if (!lock_fb_info(fb_info)) {
1749
- ret = -ENODEV;
1750
- goto unlock_console;
1751
- }
1752
- ret = 0;
1753
-
1754
- fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
1681
+ lock_fb_info(fb_info);
1682
+ ret = fbcon_fb_registered(fb_info);
17551683 unlock_fb_info(fb_info);
1756
-unlock_console:
1684
+
17571685 if (!lockless_register_fb)
17581686 console_unlock();
17591687 else
....@@ -1761,44 +1689,43 @@
17611689 return ret;
17621690 }
17631691
1764
-static int unbind_console(struct fb_info *fb_info)
1692
+static void unbind_console(struct fb_info *fb_info)
17651693 {
1766
- struct fb_event event;
1767
- int ret;
17681694 int i = fb_info->node;
17691695
1770
- if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
1771
- return -EINVAL;
1696
+ if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
1697
+ return;
17721698
17731699 console_lock();
1774
- if (!lock_fb_info(fb_info)) {
1775
- console_unlock();
1776
- return -ENODEV;
1777
- }
1778
-
1779
- event.info = fb_info;
1780
- ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
1700
+ lock_fb_info(fb_info);
1701
+ fbcon_fb_unbind(fb_info);
17811702 unlock_fb_info(fb_info);
17821703 console_unlock();
1783
-
1784
- return ret;
17851704 }
17861705
1787
-static int __unlink_framebuffer(struct fb_info *fb_info);
1788
-
1789
-static int do_unregister_framebuffer(struct fb_info *fb_info)
1706
+static void unlink_framebuffer(struct fb_info *fb_info)
17901707 {
1791
- struct fb_event event;
1792
- int ret;
1708
+ int i;
17931709
1794
- ret = unbind_console(fb_info);
1710
+ i = fb_info->node;
1711
+ if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
1712
+ return;
17951713
1796
- if (ret)
1797
- return -EINVAL;
1714
+ if (!fb_info->dev)
1715
+ return;
1716
+
1717
+ device_destroy(fb_class, MKDEV(FB_MAJOR, i));
17981718
17991719 pm_vt_switch_unregister(fb_info->dev);
18001720
1801
- __unlink_framebuffer(fb_info);
1721
+ unbind_console(fb_info);
1722
+
1723
+ fb_info->dev = NULL;
1724
+}
1725
+
1726
+static void do_unregister_framebuffer(struct fb_info *fb_info)
1727
+{
1728
+ unlink_framebuffer(fb_info);
18021729 if (fb_info->pixmap.addr &&
18031730 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
18041731 kfree(fb_info->pixmap.addr);
....@@ -1806,58 +1733,104 @@
18061733 registered_fb[fb_info->node] = NULL;
18071734 num_registered_fb--;
18081735 fb_cleanup_device(fb_info);
1809
- event.info = fb_info;
1736
+#ifdef CONFIG_GUMSTIX_AM200EPD
1737
+ {
1738
+ struct fb_event event;
1739
+ event.info = fb_info;
1740
+ fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
1741
+ }
1742
+#endif
18101743 console_lock();
1811
- fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
1744
+ fbcon_fb_unregistered(fb_info);
18121745 console_unlock();
18131746
18141747 /* this may free fb info */
18151748 put_fb_info(fb_info);
1816
- return 0;
18171749 }
18181750
1819
-static int __unlink_framebuffer(struct fb_info *fb_info)
1820
-{
1821
- int i;
1822
-
1823
- i = fb_info->node;
1824
- if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
1825
- return -EINVAL;
1826
-
1827
- if (fb_info->dev) {
1828
- device_destroy(fb_class, MKDEV(FB_MAJOR, i));
1829
- fb_info->dev = NULL;
1830
- }
1831
-
1832
- return 0;
1833
-}
1834
-
1835
-int unlink_framebuffer(struct fb_info *fb_info)
1836
-{
1837
- int ret;
1838
-
1839
- ret = __unlink_framebuffer(fb_info);
1840
- if (ret)
1841
- return ret;
1842
-
1843
- unbind_console(fb_info);
1844
-
1845
- return 0;
1846
-}
1847
-EXPORT_SYMBOL(unlink_framebuffer);
1848
-
1751
+/**
1752
+ * remove_conflicting_framebuffers - remove firmware-configured framebuffers
1753
+ * @a: memory range, users of which are to be removed
1754
+ * @name: requesting driver name
1755
+ * @primary: also kick vga16fb if present
1756
+ *
1757
+ * This function removes framebuffer devices (initialized by firmware/bootloader)
1758
+ * which use memory range described by @a. If @a is NULL all such devices are
1759
+ * removed.
1760
+ */
18491761 int remove_conflicting_framebuffers(struct apertures_struct *a,
18501762 const char *name, bool primary)
18511763 {
1852
- int ret;
1764
+ bool do_free = false;
1765
+
1766
+ if (!a) {
1767
+ a = alloc_apertures(1);
1768
+ if (!a)
1769
+ return -ENOMEM;
1770
+
1771
+ a->ranges[0].base = 0;
1772
+ a->ranges[0].size = ~0;
1773
+ do_free = true;
1774
+ }
18531775
18541776 mutex_lock(&registration_lock);
1855
- ret = do_remove_conflicting_framebuffers(a, name, primary);
1777
+ do_remove_conflicting_framebuffers(a, name, primary);
18561778 mutex_unlock(&registration_lock);
18571779
1858
- return ret;
1780
+ if (do_free)
1781
+ kfree(a);
1782
+
1783
+ return 0;
18591784 }
18601785 EXPORT_SYMBOL(remove_conflicting_framebuffers);
1786
+
1787
+/**
1788
+ * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
1789
+ * @pdev: PCI device
1790
+ * @name: requesting driver name
1791
+ *
1792
+ * This function removes framebuffer devices (eg. initialized by firmware)
1793
+ * using memory range configured for any of @pdev's memory bars.
1794
+ *
1795
+ * The function assumes that PCI device with shadowed ROM drives a primary
1796
+ * display and so kicks out vga16fb.
1797
+ */
1798
+int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
1799
+{
1800
+ struct apertures_struct *ap;
1801
+ bool primary = false;
1802
+ int err, idx, bar;
1803
+
1804
+ for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
1805
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
1806
+ continue;
1807
+ idx++;
1808
+ }
1809
+
1810
+ ap = alloc_apertures(idx);
1811
+ if (!ap)
1812
+ return -ENOMEM;
1813
+
1814
+ for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
1815
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
1816
+ continue;
1817
+ ap->ranges[idx].base = pci_resource_start(pdev, bar);
1818
+ ap->ranges[idx].size = pci_resource_len(pdev, bar);
1819
+ pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
1820
+ (unsigned long)pci_resource_start(pdev, bar),
1821
+ (unsigned long)pci_resource_end(pdev, bar));
1822
+ idx++;
1823
+ }
1824
+
1825
+#ifdef CONFIG_X86
1826
+ primary = pdev->resource[PCI_ROM_RESOURCE].flags &
1827
+ IORESOURCE_ROM_SHADOW;
1828
+#endif
1829
+ err = remove_conflicting_framebuffers(ap, name, primary);
1830
+ kfree(ap);
1831
+ return err;
1832
+}
1833
+EXPORT_SYMBOL(remove_conflicting_pci_framebuffers);
18611834
18621835 /**
18631836 * register_framebuffer - registers a frame buffer device
....@@ -1897,16 +1870,12 @@
18971870 * that the driver implements fb_open() and fb_release() to
18981871 * check that no processes are using the device.
18991872 */
1900
-int
1873
+void
19011874 unregister_framebuffer(struct fb_info *fb_info)
19021875 {
1903
- int ret;
1904
-
19051876 mutex_lock(&registration_lock);
1906
- ret = do_unregister_framebuffer(fb_info);
1877
+ do_unregister_framebuffer(fb_info);
19071878 mutex_unlock(&registration_lock);
1908
-
1909
- return ret;
19101879 }
19111880 EXPORT_SYMBOL(unregister_framebuffer);
19121881
....@@ -1921,15 +1890,14 @@
19211890 */
19221891 void fb_set_suspend(struct fb_info *info, int state)
19231892 {
1924
- struct fb_event event;
1893
+ WARN_CONSOLE_UNLOCKED();
19251894
1926
- event.info = info;
19271895 if (state) {
1928
- fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
1896
+ fbcon_suspended(info);
19291897 info->state = FBINFO_STATE_SUSPENDED;
19301898 } else {
19311899 info->state = FBINFO_STATE_RUNNING;
1932
- fb_notifier_call_chain(FB_EVENT_RESUME, &event);
1900
+ fbcon_resumed(info);
19331901 }
19341902 }
19351903 EXPORT_SYMBOL(fb_set_suspend);
....@@ -1997,12 +1965,11 @@
19971965
19981966 int fb_new_modelist(struct fb_info *info)
19991967 {
2000
- struct fb_event event;
20011968 struct fb_var_screeninfo var = info->var;
20021969 struct list_head *pos, *n;
20031970 struct fb_modelist *modelist;
20041971 struct fb_videomode *m, mode;
2005
- int err = 1;
1972
+ int err;
20061973
20071974 list_for_each_safe(pos, n, &info->modelist) {
20081975 modelist = list_entry(pos, struct fb_modelist, list);
....@@ -2017,14 +1984,12 @@
20171984 }
20181985 }
20191986
2020
- err = 1;
1987
+ if (list_empty(&info->modelist))
1988
+ return 1;
20211989
2022
- if (!list_empty(&info->modelist)) {
2023
- event.info = info;
2024
- err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
2025
- }
1990
+ fbcon_new_modelist(info);
20261991
2027
- return err;
1992
+ return 0;
20281993 }
20291994
20301995 MODULE_LICENSE("GPL");