diff options
Diffstat (limited to 'drivers/video/omap2/omapfb/omapfb-main.c')
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 229 |
1 files changed, 153 insertions, 76 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4b4506da96d..04034d410d6 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -157,7 +157,7 @@ static void fill_fb(struct fb_info *fbi) | |||
157 | 157 | ||
158 | static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) | 158 | static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) |
159 | { | 159 | { |
160 | const struct vrfb *vrfb = &ofbi->region.vrfb; | 160 | const struct vrfb *vrfb = &ofbi->region->vrfb; |
161 | unsigned offset; | 161 | unsigned offset; |
162 | 162 | ||
163 | switch (rot) { | 163 | switch (rot) { |
@@ -185,27 +185,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) | |||
185 | static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) | 185 | static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) |
186 | { | 186 | { |
187 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 187 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { |
188 | return ofbi->region.vrfb.paddr[rot] | 188 | return ofbi->region->vrfb.paddr[rot] |
189 | + omapfb_get_vrfb_offset(ofbi, rot); | 189 | + omapfb_get_vrfb_offset(ofbi, rot); |
190 | } else { | 190 | } else { |
191 | return ofbi->region.paddr; | 191 | return ofbi->region->paddr; |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) | 195 | static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) |
196 | { | 196 | { |
197 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | 197 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
198 | return ofbi->region.vrfb.paddr[0]; | 198 | return ofbi->region->vrfb.paddr[0]; |
199 | else | 199 | else |
200 | return ofbi->region.paddr; | 200 | return ofbi->region->paddr; |
201 | } | 201 | } |
202 | 202 | ||
203 | static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) | 203 | static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) |
204 | { | 204 | { |
205 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | 205 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
206 | return ofbi->region.vrfb.vaddr[0]; | 206 | return ofbi->region->vrfb.vaddr[0]; |
207 | else | 207 | else |
208 | return ofbi->region.vaddr; | 208 | return ofbi->region->vaddr; |
209 | } | 209 | } |
210 | 210 | ||
211 | static struct omapfb_colormode omapfb_colormodes[] = { | 211 | static struct omapfb_colormode omapfb_colormodes[] = { |
@@ -450,7 +450,7 @@ static int check_vrfb_fb_size(unsigned long region_size, | |||
450 | static int check_fb_size(const struct omapfb_info *ofbi, | 450 | static int check_fb_size(const struct omapfb_info *ofbi, |
451 | struct fb_var_screeninfo *var) | 451 | struct fb_var_screeninfo *var) |
452 | { | 452 | { |
453 | unsigned long max_frame_size = ofbi->region.size; | 453 | unsigned long max_frame_size = ofbi->region->size; |
454 | int bytespp = var->bits_per_pixel >> 3; | 454 | int bytespp = var->bits_per_pixel >> 3; |
455 | unsigned long line_size = var->xres_virtual * bytespp; | 455 | unsigned long line_size = var->xres_virtual * bytespp; |
456 | 456 | ||
@@ -497,7 +497,7 @@ static int check_fb_size(const struct omapfb_info *ofbi, | |||
497 | static int setup_vrfb_rotation(struct fb_info *fbi) | 497 | static int setup_vrfb_rotation(struct fb_info *fbi) |
498 | { | 498 | { |
499 | struct omapfb_info *ofbi = FB2OFB(fbi); | 499 | struct omapfb_info *ofbi = FB2OFB(fbi); |
500 | struct omapfb2_mem_region *rg = &ofbi->region; | 500 | struct omapfb2_mem_region *rg = ofbi->region; |
501 | struct vrfb *vrfb = &rg->vrfb; | 501 | struct vrfb *vrfb = &rg->vrfb; |
502 | struct fb_var_screeninfo *var = &fbi->var; | 502 | struct fb_var_screeninfo *var = &fbi->var; |
503 | struct fb_fix_screeninfo *fix = &fbi->fix; | 503 | struct fb_fix_screeninfo *fix = &fbi->fix; |
@@ -558,9 +558,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi) | |||
558 | return r; | 558 | return r; |
559 | 559 | ||
560 | /* used by open/write in fbmem.c */ | 560 | /* used by open/write in fbmem.c */ |
561 | fbi->screen_base = ofbi->region.vrfb.vaddr[0]; | 561 | fbi->screen_base = ofbi->region->vrfb.vaddr[0]; |
562 | 562 | ||
563 | fix->smem_start = ofbi->region.vrfb.paddr[0]; | 563 | fix->smem_start = ofbi->region->vrfb.paddr[0]; |
564 | 564 | ||
565 | switch (var->nonstd) { | 565 | switch (var->nonstd) { |
566 | case OMAPFB_COLOR_YUV422: | 566 | case OMAPFB_COLOR_YUV422: |
@@ -599,7 +599,7 @@ void set_fb_fix(struct fb_info *fbi) | |||
599 | struct fb_fix_screeninfo *fix = &fbi->fix; | 599 | struct fb_fix_screeninfo *fix = &fbi->fix; |
600 | struct fb_var_screeninfo *var = &fbi->var; | 600 | struct fb_var_screeninfo *var = &fbi->var; |
601 | struct omapfb_info *ofbi = FB2OFB(fbi); | 601 | struct omapfb_info *ofbi = FB2OFB(fbi); |
602 | struct omapfb2_mem_region *rg = &ofbi->region; | 602 | struct omapfb2_mem_region *rg = ofbi->region; |
603 | 603 | ||
604 | DBG("set_fb_fix\n"); | 604 | DBG("set_fb_fix\n"); |
605 | 605 | ||
@@ -668,8 +668,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
668 | 668 | ||
669 | DBG("check_fb_var %d\n", ofbi->id); | 669 | DBG("check_fb_var %d\n", ofbi->id); |
670 | 670 | ||
671 | if (ofbi->region.size == 0) | 671 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); |
672 | return 0; | ||
673 | 672 | ||
674 | r = fb_mode_to_dss_mode(var, &mode); | 673 | r = fb_mode_to_dss_mode(var, &mode); |
675 | if (r) { | 674 | if (r) { |
@@ -684,13 +683,14 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
684 | } | 683 | } |
685 | } | 684 | } |
686 | 685 | ||
687 | if (var->rotate < 0 || var->rotate > 3) | 686 | if (var->rotate > 3) |
688 | return -EINVAL; | 687 | return -EINVAL; |
689 | 688 | ||
690 | if (check_fb_res_bounds(var)) | 689 | if (check_fb_res_bounds(var)) |
691 | return -EINVAL; | 690 | return -EINVAL; |
692 | 691 | ||
693 | if (check_fb_size(ofbi, var)) | 692 | /* When no memory is allocated ignore the size check */ |
693 | if (ofbi->region->size != 0 && check_fb_size(ofbi, var)) | ||
694 | return -EINVAL; | 694 | return -EINVAL; |
695 | 695 | ||
696 | if (var->xres + var->xoffset > var->xres_virtual) | 696 | if (var->xres + var->xoffset > var->xres_virtual) |
@@ -822,9 +822,43 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var, | |||
822 | return offset; | 822 | return offset; |
823 | } | 823 | } |
824 | 824 | ||
825 | static void omapfb_calc_addr(const struct omapfb_info *ofbi, | ||
826 | const struct fb_var_screeninfo *var, | ||
827 | const struct fb_fix_screeninfo *fix, | ||
828 | int rotation, u32 *paddr, void __iomem **vaddr) | ||
829 | { | ||
830 | u32 data_start_p; | ||
831 | void __iomem *data_start_v; | ||
832 | int offset; | ||
833 | |||
834 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | ||
835 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); | ||
836 | data_start_v = NULL; | ||
837 | } else { | ||
838 | data_start_p = omapfb_get_region_paddr(ofbi); | ||
839 | data_start_v = omapfb_get_region_vaddr(ofbi); | ||
840 | } | ||
841 | |||
842 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | ||
843 | offset = calc_rotation_offset_vrfb(var, fix, rotation); | ||
844 | else | ||
845 | offset = calc_rotation_offset_dma(var, fix, rotation); | ||
846 | |||
847 | data_start_p += offset; | ||
848 | data_start_v += offset; | ||
849 | |||
850 | if (offset) | ||
851 | DBG("offset %d, %d = %d\n", | ||
852 | var->xoffset, var->yoffset, offset); | ||
853 | |||
854 | DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); | ||
855 | |||
856 | *paddr = data_start_p; | ||
857 | *vaddr = data_start_v; | ||
858 | } | ||
825 | 859 | ||
826 | /* setup overlay according to the fb */ | 860 | /* setup overlay according to the fb */ |
827 | static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | 861 | int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, |
828 | u16 posx, u16 posy, u16 outw, u16 outh) | 862 | u16 posx, u16 posy, u16 outw, u16 outh) |
829 | { | 863 | { |
830 | int r = 0; | 864 | int r = 0; |
@@ -832,9 +866,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
832 | struct fb_var_screeninfo *var = &fbi->var; | 866 | struct fb_var_screeninfo *var = &fbi->var; |
833 | struct fb_fix_screeninfo *fix = &fbi->fix; | 867 | struct fb_fix_screeninfo *fix = &fbi->fix; |
834 | enum omap_color_mode mode = 0; | 868 | enum omap_color_mode mode = 0; |
835 | int offset; | 869 | u32 data_start_p = 0; |
836 | u32 data_start_p; | 870 | void __iomem *data_start_v = NULL; |
837 | void __iomem *data_start_v; | ||
838 | struct omap_overlay_info info; | 871 | struct omap_overlay_info info; |
839 | int xres, yres; | 872 | int xres, yres; |
840 | int screen_width; | 873 | int screen_width; |
@@ -842,6 +875,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
842 | int rotation = var->rotate; | 875 | int rotation = var->rotate; |
843 | int i; | 876 | int i; |
844 | 877 | ||
878 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
879 | |||
845 | for (i = 0; i < ofbi->num_overlays; i++) { | 880 | for (i = 0; i < ofbi->num_overlays; i++) { |
846 | if (ovl != ofbi->overlays[i]) | 881 | if (ovl != ofbi->overlays[i]) |
847 | continue; | 882 | continue; |
@@ -861,28 +896,9 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
861 | yres = var->yres; | 896 | yres = var->yres; |
862 | } | 897 | } |
863 | 898 | ||
864 | 899 | if (ofbi->region->size) | |
865 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 900 | omapfb_calc_addr(ofbi, var, fix, rotation, |
866 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); | 901 | &data_start_p, &data_start_v); |
867 | data_start_v = NULL; | ||
868 | } else { | ||
869 | data_start_p = omapfb_get_region_paddr(ofbi); | ||
870 | data_start_v = omapfb_get_region_vaddr(ofbi); | ||
871 | } | ||
872 | |||
873 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | ||
874 | offset = calc_rotation_offset_vrfb(var, fix, rotation); | ||
875 | else | ||
876 | offset = calc_rotation_offset_dma(var, fix, rotation); | ||
877 | |||
878 | data_start_p += offset; | ||
879 | data_start_v += offset; | ||
880 | |||
881 | if (offset) | ||
882 | DBG("offset %d, %d = %d\n", | ||
883 | var->xoffset, var->yoffset, offset); | ||
884 | |||
885 | DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); | ||
886 | 902 | ||
887 | r = fb_mode_to_dss_mode(var, &mode); | 903 | r = fb_mode_to_dss_mode(var, &mode); |
888 | if (r) { | 904 | if (r) { |
@@ -954,12 +970,14 @@ int omapfb_apply_changes(struct fb_info *fbi, int init) | |||
954 | fill_fb(fbi); | 970 | fill_fb(fbi); |
955 | #endif | 971 | #endif |
956 | 972 | ||
973 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
974 | |||
957 | for (i = 0; i < ofbi->num_overlays; i++) { | 975 | for (i = 0; i < ofbi->num_overlays; i++) { |
958 | ovl = ofbi->overlays[i]; | 976 | ovl = ofbi->overlays[i]; |
959 | 977 | ||
960 | DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); | 978 | DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); |
961 | 979 | ||
962 | if (ofbi->region.size == 0) { | 980 | if (ofbi->region->size == 0) { |
963 | /* the fb is not available. disable the overlay */ | 981 | /* the fb is not available. disable the overlay */ |
964 | omapfb_overlay_enable(ovl, 0); | 982 | omapfb_overlay_enable(ovl, 0); |
965 | if (!init && ovl->manager) | 983 | if (!init && ovl->manager) |
@@ -1007,36 +1025,48 @@ err: | |||
1007 | * DO NOT MODIFY PAR */ | 1025 | * DO NOT MODIFY PAR */ |
1008 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | 1026 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) |
1009 | { | 1027 | { |
1028 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1010 | int r; | 1029 | int r; |
1011 | 1030 | ||
1012 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); | 1031 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); |
1013 | 1032 | ||
1033 | omapfb_get_mem_region(ofbi->region); | ||
1034 | |||
1014 | r = check_fb_var(fbi, var); | 1035 | r = check_fb_var(fbi, var); |
1015 | 1036 | ||
1037 | omapfb_put_mem_region(ofbi->region); | ||
1038 | |||
1016 | return r; | 1039 | return r; |
1017 | } | 1040 | } |
1018 | 1041 | ||
1019 | /* set the video mode according to info->var */ | 1042 | /* set the video mode according to info->var */ |
1020 | static int omapfb_set_par(struct fb_info *fbi) | 1043 | static int omapfb_set_par(struct fb_info *fbi) |
1021 | { | 1044 | { |
1045 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1022 | int r; | 1046 | int r; |
1023 | 1047 | ||
1024 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); | 1048 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); |
1025 | 1049 | ||
1050 | omapfb_get_mem_region(ofbi->region); | ||
1051 | |||
1026 | set_fb_fix(fbi); | 1052 | set_fb_fix(fbi); |
1027 | 1053 | ||
1028 | r = setup_vrfb_rotation(fbi); | 1054 | r = setup_vrfb_rotation(fbi); |
1029 | if (r) | 1055 | if (r) |
1030 | return r; | 1056 | goto out; |
1031 | 1057 | ||
1032 | r = omapfb_apply_changes(fbi, 0); | 1058 | r = omapfb_apply_changes(fbi, 0); |
1033 | 1059 | ||
1060 | out: | ||
1061 | omapfb_put_mem_region(ofbi->region); | ||
1062 | |||
1034 | return r; | 1063 | return r; |
1035 | } | 1064 | } |
1036 | 1065 | ||
1037 | static int omapfb_pan_display(struct fb_var_screeninfo *var, | 1066 | static int omapfb_pan_display(struct fb_var_screeninfo *var, |
1038 | struct fb_info *fbi) | 1067 | struct fb_info *fbi) |
1039 | { | 1068 | { |
1069 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1040 | struct fb_var_screeninfo new_var; | 1070 | struct fb_var_screeninfo new_var; |
1041 | int r; | 1071 | int r; |
1042 | 1072 | ||
@@ -1052,23 +1082,31 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var, | |||
1052 | 1082 | ||
1053 | fbi->var = new_var; | 1083 | fbi->var = new_var; |
1054 | 1084 | ||
1085 | omapfb_get_mem_region(ofbi->region); | ||
1086 | |||
1055 | r = omapfb_apply_changes(fbi, 0); | 1087 | r = omapfb_apply_changes(fbi, 0); |
1056 | 1088 | ||
1089 | omapfb_put_mem_region(ofbi->region); | ||
1090 | |||
1057 | return r; | 1091 | return r; |
1058 | } | 1092 | } |
1059 | 1093 | ||
1060 | static void mmap_user_open(struct vm_area_struct *vma) | 1094 | static void mmap_user_open(struct vm_area_struct *vma) |
1061 | { | 1095 | { |
1062 | struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; | 1096 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1063 | 1097 | ||
1064 | atomic_inc(&ofbi->map_count); | 1098 | omapfb_get_mem_region(rg); |
1099 | atomic_inc(&rg->map_count); | ||
1100 | omapfb_put_mem_region(rg); | ||
1065 | } | 1101 | } |
1066 | 1102 | ||
1067 | static void mmap_user_close(struct vm_area_struct *vma) | 1103 | static void mmap_user_close(struct vm_area_struct *vma) |
1068 | { | 1104 | { |
1069 | struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; | 1105 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1070 | 1106 | ||
1071 | atomic_dec(&ofbi->map_count); | 1107 | omapfb_get_mem_region(rg); |
1108 | atomic_dec(&rg->map_count); | ||
1109 | omapfb_put_mem_region(rg); | ||
1072 | } | 1110 | } |
1073 | 1111 | ||
1074 | static struct vm_operations_struct mmap_user_ops = { | 1112 | static struct vm_operations_struct mmap_user_ops = { |
@@ -1080,9 +1118,11 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1080 | { | 1118 | { |
1081 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1119 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1082 | struct fb_fix_screeninfo *fix = &fbi->fix; | 1120 | struct fb_fix_screeninfo *fix = &fbi->fix; |
1121 | struct omapfb2_mem_region *rg; | ||
1083 | unsigned long off; | 1122 | unsigned long off; |
1084 | unsigned long start; | 1123 | unsigned long start; |
1085 | u32 len; | 1124 | u32 len; |
1125 | int r = -EINVAL; | ||
1086 | 1126 | ||
1087 | if (vma->vm_end - vma->vm_start == 0) | 1127 | if (vma->vm_end - vma->vm_start == 0) |
1088 | return 0; | 1128 | return 0; |
@@ -1090,12 +1130,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1090 | return -EINVAL; | 1130 | return -EINVAL; |
1091 | off = vma->vm_pgoff << PAGE_SHIFT; | 1131 | off = vma->vm_pgoff << PAGE_SHIFT; |
1092 | 1132 | ||
1133 | rg = omapfb_get_mem_region(ofbi->region); | ||
1134 | |||
1093 | start = omapfb_get_region_paddr(ofbi); | 1135 | start = omapfb_get_region_paddr(ofbi); |
1094 | len = fix->smem_len; | 1136 | len = fix->smem_len; |
1095 | if (off >= len) | 1137 | if (off >= len) |
1096 | return -EINVAL; | 1138 | goto error; |
1097 | if ((vma->vm_end - vma->vm_start + off) > len) | 1139 | if ((vma->vm_end - vma->vm_start + off) > len) |
1098 | return -EINVAL; | 1140 | goto error; |
1099 | 1141 | ||
1100 | off += start; | 1142 | off += start; |
1101 | 1143 | ||
@@ -1105,13 +1147,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1105 | vma->vm_flags |= VM_IO | VM_RESERVED; | 1147 | vma->vm_flags |= VM_IO | VM_RESERVED; |
1106 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | 1148 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); |
1107 | vma->vm_ops = &mmap_user_ops; | 1149 | vma->vm_ops = &mmap_user_ops; |
1108 | vma->vm_private_data = ofbi; | 1150 | vma->vm_private_data = rg; |
1109 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | 1151 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, |
1110 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 1152 | vma->vm_end - vma->vm_start, |
1111 | return -EAGAIN; | 1153 | vma->vm_page_prot)) { |
1154 | r = -EAGAIN; | ||
1155 | goto error; | ||
1156 | } | ||
1157 | |||
1112 | /* vm_ops.open won't be called for mmap itself. */ | 1158 | /* vm_ops.open won't be called for mmap itself. */ |
1113 | atomic_inc(&ofbi->map_count); | 1159 | atomic_inc(&rg->map_count); |
1160 | |||
1161 | omapfb_put_mem_region(rg); | ||
1162 | |||
1114 | return 0; | 1163 | return 0; |
1164 | |||
1165 | error: | ||
1166 | omapfb_put_mem_region(ofbi->region); | ||
1167 | |||
1168 | return r; | ||
1115 | } | 1169 | } |
1116 | 1170 | ||
1117 | /* Store a single color palette entry into a pseudo palette or the hardware | 1171 | /* Store a single color palette entry into a pseudo palette or the hardware |
@@ -1154,11 +1208,6 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, | |||
1154 | if (r != 0) | 1208 | if (r != 0) |
1155 | break; | 1209 | break; |
1156 | 1210 | ||
1157 | if (regno < 0) { | ||
1158 | r = -EINVAL; | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | if (regno < 16) { | 1211 | if (regno < 16) { |
1163 | u16 pal; | 1212 | u16 pal; |
1164 | pal = ((red >> (16 - var->red.length)) << | 1213 | pal = ((red >> (16 - var->red.length)) << |
@@ -1217,6 +1266,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1217 | int do_update = 0; | 1266 | int do_update = 0; |
1218 | int r = 0; | 1267 | int r = 0; |
1219 | 1268 | ||
1269 | if (!display) | ||
1270 | return -EINVAL; | ||
1271 | |||
1220 | omapfb_lock(fbdev); | 1272 | omapfb_lock(fbdev); |
1221 | 1273 | ||
1222 | switch (blank) { | 1274 | switch (blank) { |
@@ -1300,7 +1352,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi) | |||
1300 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1352 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1301 | struct omapfb2_mem_region *rg; | 1353 | struct omapfb2_mem_region *rg; |
1302 | 1354 | ||
1303 | rg = &ofbi->region; | 1355 | rg = ofbi->region; |
1356 | |||
1357 | WARN_ON(atomic_read(&rg->map_count)); | ||
1304 | 1358 | ||
1305 | if (rg->paddr) | 1359 | if (rg->paddr) |
1306 | if (omap_vram_free(rg->paddr, rg->size)) | 1360 | if (omap_vram_free(rg->paddr, rg->size)) |
@@ -1355,8 +1409,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, | |||
1355 | void __iomem *vaddr; | 1409 | void __iomem *vaddr; |
1356 | int r; | 1410 | int r; |
1357 | 1411 | ||
1358 | rg = &ofbi->region; | 1412 | rg = ofbi->region; |
1359 | memset(rg, 0, sizeof(*rg)); | 1413 | |
1414 | rg->paddr = 0; | ||
1415 | rg->vaddr = NULL; | ||
1416 | memset(&rg->vrfb, 0, sizeof rg->vrfb); | ||
1417 | rg->size = 0; | ||
1418 | rg->type = 0; | ||
1419 | rg->alloc = false; | ||
1420 | rg->map = false; | ||
1360 | 1421 | ||
1361 | size = PAGE_ALIGN(size); | 1422 | size = PAGE_ALIGN(size); |
1362 | 1423 | ||
@@ -1609,7 +1670,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) | |||
1609 | for (i = 0; i < fbdev->num_fbs; i++) { | 1670 | for (i = 0; i < fbdev->num_fbs; i++) { |
1610 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); | 1671 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); |
1611 | struct omapfb2_mem_region *rg; | 1672 | struct omapfb2_mem_region *rg; |
1612 | rg = &ofbi->region; | 1673 | rg = ofbi->region; |
1613 | 1674 | ||
1614 | DBG("region%d phys %08x virt %p size=%lu\n", | 1675 | DBG("region%d phys %08x virt %p size=%lu\n", |
1615 | i, | 1676 | i, |
@@ -1626,7 +1687,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) | |||
1626 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1687 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1627 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1688 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1628 | struct omap_dss_device *display = fb2display(fbi); | 1689 | struct omap_dss_device *display = fb2display(fbi); |
1629 | struct omapfb2_mem_region *rg = &ofbi->region; | 1690 | struct omapfb2_mem_region *rg = ofbi->region; |
1630 | unsigned long old_size = rg->size; | 1691 | unsigned long old_size = rg->size; |
1631 | unsigned long old_paddr = rg->paddr; | 1692 | unsigned long old_paddr = rg->paddr; |
1632 | int old_type = rg->type; | 1693 | int old_type = rg->type; |
@@ -1709,7 +1770,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) | |||
1709 | fbi->flags = FBINFO_FLAG_DEFAULT; | 1770 | fbi->flags = FBINFO_FLAG_DEFAULT; |
1710 | fbi->pseudo_palette = fbdev->pseudo_palette; | 1771 | fbi->pseudo_palette = fbdev->pseudo_palette; |
1711 | 1772 | ||
1712 | if (ofbi->region.size == 0) { | 1773 | if (ofbi->region->size == 0) { |
1713 | clear_fb_info(fbi); | 1774 | clear_fb_info(fbi); |
1714 | return 0; | 1775 | return 0; |
1715 | } | 1776 | } |
@@ -1871,6 +1932,10 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1871 | ofbi->fbdev = fbdev; | 1932 | ofbi->fbdev = fbdev; |
1872 | ofbi->id = i; | 1933 | ofbi->id = i; |
1873 | 1934 | ||
1935 | ofbi->region = &fbdev->regions[i]; | ||
1936 | ofbi->region->id = i; | ||
1937 | init_rwsem(&ofbi->region->lock); | ||
1938 | |||
1874 | /* assign these early, so that fb alloc can use them */ | 1939 | /* assign these early, so that fb alloc can use them */ |
1875 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : | 1940 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : |
1876 | OMAP_DSS_ROT_DMA; | 1941 | OMAP_DSS_ROT_DMA; |
@@ -1900,7 +1965,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1900 | 1965 | ||
1901 | /* setup fb_infos */ | 1966 | /* setup fb_infos */ |
1902 | for (i = 0; i < fbdev->num_fbs; i++) { | 1967 | for (i = 0; i < fbdev->num_fbs; i++) { |
1903 | r = omapfb_fb_init(fbdev, fbdev->fbs[i]); | 1968 | struct fb_info *fbi = fbdev->fbs[i]; |
1969 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1970 | |||
1971 | omapfb_get_mem_region(ofbi->region); | ||
1972 | r = omapfb_fb_init(fbdev, fbi); | ||
1973 | omapfb_put_mem_region(ofbi->region); | ||
1974 | |||
1904 | if (r) { | 1975 | if (r) { |
1905 | dev_err(fbdev->dev, "failed to setup fb_info\n"); | 1976 | dev_err(fbdev->dev, "failed to setup fb_info\n"); |
1906 | return r; | 1977 | return r; |
@@ -1921,20 +1992,19 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1921 | DBG("framebuffers registered\n"); | 1992 | DBG("framebuffers registered\n"); |
1922 | 1993 | ||
1923 | for (i = 0; i < fbdev->num_fbs; i++) { | 1994 | for (i = 0; i < fbdev->num_fbs; i++) { |
1924 | r = omapfb_apply_changes(fbdev->fbs[i], 1); | 1995 | struct fb_info *fbi = fbdev->fbs[i]; |
1996 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1997 | |||
1998 | omapfb_get_mem_region(ofbi->region); | ||
1999 | r = omapfb_apply_changes(fbi, 1); | ||
2000 | omapfb_put_mem_region(ofbi->region); | ||
2001 | |||
1925 | if (r) { | 2002 | if (r) { |
1926 | dev_err(fbdev->dev, "failed to change mode\n"); | 2003 | dev_err(fbdev->dev, "failed to change mode\n"); |
1927 | return r; | 2004 | return r; |
1928 | } | 2005 | } |
1929 | } | 2006 | } |
1930 | 2007 | ||
1931 | DBG("create sysfs for fbs\n"); | ||
1932 | r = omapfb_create_sysfs(fbdev); | ||
1933 | if (r) { | ||
1934 | dev_err(fbdev->dev, "failed to create sysfs entries\n"); | ||
1935 | return r; | ||
1936 | } | ||
1937 | |||
1938 | /* Enable fb0 */ | 2008 | /* Enable fb0 */ |
1939 | if (fbdev->num_fbs > 0) { | 2009 | if (fbdev->num_fbs > 0) { |
1940 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); | 2010 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); |
@@ -1968,11 +2038,11 @@ static int omapfb_mode_to_timings(const char *mode_str, | |||
1968 | #ifdef CONFIG_OMAP2_DSS_VENC | 2038 | #ifdef CONFIG_OMAP2_DSS_VENC |
1969 | if (strcmp(mode_str, "pal") == 0) { | 2039 | if (strcmp(mode_str, "pal") == 0) { |
1970 | *timings = omap_dss_pal_timings; | 2040 | *timings = omap_dss_pal_timings; |
1971 | *bpp = 0; | 2041 | *bpp = 24; |
1972 | return 0; | 2042 | return 0; |
1973 | } else if (strcmp(mode_str, "ntsc") == 0) { | 2043 | } else if (strcmp(mode_str, "ntsc") == 0) { |
1974 | *timings = omap_dss_ntsc_timings; | 2044 | *timings = omap_dss_ntsc_timings; |
1975 | *bpp = 0; | 2045 | *bpp = 24; |
1976 | return 0; | 2046 | return 0; |
1977 | } | 2047 | } |
1978 | #endif | 2048 | #endif |
@@ -2220,6 +2290,13 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2220 | } | 2290 | } |
2221 | } | 2291 | } |
2222 | 2292 | ||
2293 | DBG("create sysfs for fbs\n"); | ||
2294 | r = omapfb_create_sysfs(fbdev); | ||
2295 | if (r) { | ||
2296 | dev_err(fbdev->dev, "failed to create sysfs entries\n"); | ||
2297 | goto cleanup; | ||
2298 | } | ||
2299 | |||
2223 | return 0; | 2300 | return 0; |
2224 | 2301 | ||
2225 | cleanup: | 2302 | cleanup: |