diff options
-rw-r--r-- | drivers/video/aty/radeon_base.c | 118 | ||||
-rw-r--r-- | drivers/video/fbcmap.c | 32 | ||||
-rw-r--r-- | include/linux/fb.h | 3 |
3 files changed, 127 insertions, 26 deletions
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index e8eb124754b1..ee25b9e8db60 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -1057,13 +1057,14 @@ static int radeonfb_blank (int blank, struct fb_info *info) | |||
1057 | return radeon_screen_blank(rinfo, blank, 0); | 1057 | return radeon_screen_blank(rinfo, blank, 0); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, | 1060 | static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, |
1061 | unsigned blue, unsigned transp, struct fb_info *info) | 1061 | unsigned blue, unsigned transp, |
1062 | struct radeonfb_info *rinfo) | ||
1062 | { | 1063 | { |
1063 | struct radeonfb_info *rinfo = info->par; | ||
1064 | u32 pindex; | 1064 | u32 pindex; |
1065 | unsigned int i; | 1065 | unsigned int i; |
1066 | 1066 | ||
1067 | |||
1067 | if (regno > 255) | 1068 | if (regno > 255) |
1068 | return 1; | 1069 | return 1; |
1069 | 1070 | ||
@@ -1078,20 +1079,7 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
1078 | pindex = regno; | 1079 | pindex = regno; |
1079 | 1080 | ||
1080 | if (!rinfo->asleep) { | 1081 | if (!rinfo->asleep) { |
1081 | u32 dac_cntl2, vclk_cntl = 0; | ||
1082 | |||
1083 | radeon_fifo_wait(9); | 1082 | radeon_fifo_wait(9); |
1084 | if (rinfo->is_mobility) { | ||
1085 | vclk_cntl = INPLL(VCLK_ECP_CNTL); | ||
1086 | OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); | ||
1087 | } | ||
1088 | |||
1089 | /* Make sure we are on first palette */ | ||
1090 | if (rinfo->has_CRTC2) { | ||
1091 | dac_cntl2 = INREG(DAC_CNTL2); | ||
1092 | dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL; | ||
1093 | OUTREG(DAC_CNTL2, dac_cntl2); | ||
1094 | } | ||
1095 | 1083 | ||
1096 | if (rinfo->bpp == 16) { | 1084 | if (rinfo->bpp == 16) { |
1097 | pindex = regno * 8; | 1085 | pindex = regno * 8; |
@@ -1101,24 +1089,27 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
1101 | if (rinfo->depth == 15 && regno > 31) | 1089 | if (rinfo->depth == 15 && regno > 31) |
1102 | return 1; | 1090 | return 1; |
1103 | 1091 | ||
1104 | /* For 565, the green component is mixed one order below */ | 1092 | /* For 565, the green component is mixed one order |
1093 | * below | ||
1094 | */ | ||
1105 | if (rinfo->depth == 16) { | 1095 | if (rinfo->depth == 16) { |
1106 | OUTREG(PALETTE_INDEX, pindex>>1); | 1096 | OUTREG(PALETTE_INDEX, pindex>>1); |
1107 | OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) | | 1097 | OUTREG(PALETTE_DATA, |
1108 | (green << 8) | (rinfo->palette[regno>>1].blue)); | 1098 | (rinfo->palette[regno>>1].red << 16) | |
1099 | (green << 8) | | ||
1100 | (rinfo->palette[regno>>1].blue)); | ||
1109 | green = rinfo->palette[regno<<1].green; | 1101 | green = rinfo->palette[regno<<1].green; |
1110 | } | 1102 | } |
1111 | } | 1103 | } |
1112 | 1104 | ||
1113 | if (rinfo->depth != 16 || regno < 32) { | 1105 | if (rinfo->depth != 16 || regno < 32) { |
1114 | OUTREG(PALETTE_INDEX, pindex); | 1106 | OUTREG(PALETTE_INDEX, pindex); |
1115 | OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue); | 1107 | OUTREG(PALETTE_DATA, (red << 16) | |
1108 | (green << 8) | blue); | ||
1116 | } | 1109 | } |
1117 | if (rinfo->is_mobility) | ||
1118 | OUTPLL(VCLK_ECP_CNTL, vclk_cntl); | ||
1119 | } | 1110 | } |
1120 | if (regno < 16) { | 1111 | if (regno < 16) { |
1121 | u32 *pal = info->pseudo_palette; | 1112 | u32 *pal = rinfo->info->pseudo_palette; |
1122 | switch (rinfo->depth) { | 1113 | switch (rinfo->depth) { |
1123 | case 15: | 1114 | case 15: |
1124 | pal[regno] = (regno << 10) | (regno << 5) | regno; | 1115 | pal[regno] = (regno << 10) | (regno << 5) | regno; |
@@ -1138,6 +1129,84 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
1138 | return 0; | 1129 | return 0; |
1139 | } | 1130 | } |
1140 | 1131 | ||
1132 | static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, | ||
1133 | unsigned blue, unsigned transp, | ||
1134 | struct fb_info *info) | ||
1135 | { | ||
1136 | struct radeonfb_info *rinfo = info->par; | ||
1137 | u32 dac_cntl2, vclk_cntl = 0; | ||
1138 | int rc; | ||
1139 | |||
1140 | if (!rinfo->asleep) { | ||
1141 | if (rinfo->is_mobility) { | ||
1142 | vclk_cntl = INPLL(VCLK_ECP_CNTL); | ||
1143 | OUTPLL(VCLK_ECP_CNTL, | ||
1144 | vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); | ||
1145 | } | ||
1146 | |||
1147 | /* Make sure we are on first palette */ | ||
1148 | if (rinfo->has_CRTC2) { | ||
1149 | dac_cntl2 = INREG(DAC_CNTL2); | ||
1150 | dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL; | ||
1151 | OUTREG(DAC_CNTL2, dac_cntl2); | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo); | ||
1156 | |||
1157 | if (!rinfo->asleep && rinfo->is_mobility) | ||
1158 | OUTPLL(VCLK_ECP_CNTL, vclk_cntl); | ||
1159 | |||
1160 | return rc; | ||
1161 | } | ||
1162 | |||
1163 | static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) | ||
1164 | { | ||
1165 | struct radeonfb_info *rinfo = info->par; | ||
1166 | u16 *red, *green, *blue, *transp; | ||
1167 | u32 dac_cntl2, vclk_cntl = 0; | ||
1168 | int i, start, rc = 0; | ||
1169 | |||
1170 | if (!rinfo->asleep) { | ||
1171 | if (rinfo->is_mobility) { | ||
1172 | vclk_cntl = INPLL(VCLK_ECP_CNTL); | ||
1173 | OUTPLL(VCLK_ECP_CNTL, | ||
1174 | vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); | ||
1175 | } | ||
1176 | |||
1177 | /* Make sure we are on first palette */ | ||
1178 | if (rinfo->has_CRTC2) { | ||
1179 | dac_cntl2 = INREG(DAC_CNTL2); | ||
1180 | dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL; | ||
1181 | OUTREG(DAC_CNTL2, dac_cntl2); | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | red = cmap->red; | ||
1186 | green = cmap->green; | ||
1187 | blue = cmap->blue; | ||
1188 | transp = cmap->transp; | ||
1189 | start = cmap->start; | ||
1190 | |||
1191 | for (i = 0; i < cmap->len; i++) { | ||
1192 | u_int hred, hgreen, hblue, htransp = 0xffff; | ||
1193 | |||
1194 | hred = *red++; | ||
1195 | hgreen = *green++; | ||
1196 | hblue = *blue++; | ||
1197 | if (transp) | ||
1198 | htransp = *transp++; | ||
1199 | rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp, | ||
1200 | rinfo); | ||
1201 | if (rc) | ||
1202 | break; | ||
1203 | } | ||
1204 | |||
1205 | if (!rinfo->asleep && rinfo->is_mobility) | ||
1206 | OUTPLL(VCLK_ECP_CNTL, vclk_cntl); | ||
1207 | |||
1208 | return rc; | ||
1209 | } | ||
1141 | 1210 | ||
1142 | static void radeon_save_state (struct radeonfb_info *rinfo, | 1211 | static void radeon_save_state (struct radeonfb_info *rinfo, |
1143 | struct radeon_regs *save) | 1212 | struct radeon_regs *save) |
@@ -1796,6 +1865,7 @@ static struct fb_ops radeonfb_ops = { | |||
1796 | .fb_check_var = radeonfb_check_var, | 1865 | .fb_check_var = radeonfb_check_var, |
1797 | .fb_set_par = radeonfb_set_par, | 1866 | .fb_set_par = radeonfb_set_par, |
1798 | .fb_setcolreg = radeonfb_setcolreg, | 1867 | .fb_setcolreg = radeonfb_setcolreg, |
1868 | .fb_setcmap = radeonfb_setcmap, | ||
1799 | .fb_pan_display = radeonfb_pan_display, | 1869 | .fb_pan_display = radeonfb_pan_display, |
1800 | .fb_blank = radeonfb_blank, | 1870 | .fb_blank = radeonfb_blank, |
1801 | .fb_ioctl = radeonfb_ioctl, | 1871 | .fb_ioctl = radeonfb_ioctl, |
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index c51f8fb5c1de..4e5ce8f7d65e 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c | |||
@@ -222,8 +222,11 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) | |||
222 | transp = cmap->transp; | 222 | transp = cmap->transp; |
223 | start = cmap->start; | 223 | start = cmap->start; |
224 | 224 | ||
225 | if (start < 0 || !info->fbops->fb_setcolreg) | 225 | if (start < 0 || (!info->fbops->fb_setcolreg && |
226 | !info->fbops->fb_setcmap)) | ||
226 | return -EINVAL; | 227 | return -EINVAL; |
228 | if (info->fbops->fb_setcmap) | ||
229 | return info->fbops->fb_setcmap(cmap, info); | ||
227 | for (i = 0; i < cmap->len; i++) { | 230 | for (i = 0; i < cmap->len; i++) { |
228 | hred = *red++; | 231 | hred = *red++; |
229 | hgreen = *green++; | 232 | hgreen = *green++; |
@@ -250,8 +253,33 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) | |||
250 | transp = cmap->transp; | 253 | transp = cmap->transp; |
251 | start = cmap->start; | 254 | start = cmap->start; |
252 | 255 | ||
253 | if (start < 0 || !info->fbops->fb_setcolreg) | 256 | if (start < 0 || (!info->fbops->fb_setcolreg && |
257 | !info->fbops->fb_setcmap)) | ||
254 | return -EINVAL; | 258 | return -EINVAL; |
259 | |||
260 | /* If we can batch, do it */ | ||
261 | if (info->fbops->fb_setcmap && cmap->len > 1) { | ||
262 | struct fb_cmap umap; | ||
263 | int size = cmap->len * sizeof(u16); | ||
264 | int rc; | ||
265 | |||
266 | memset(&umap, 0, sizeof(struct fb_cmap)); | ||
267 | rc = fb_alloc_cmap(&umap, cmap->len, transp != NULL); | ||
268 | if (rc) | ||
269 | return rc; | ||
270 | if (copy_from_user(umap.red, red, size) || | ||
271 | copy_from_user(umap.green, green, size) || | ||
272 | copy_from_user(umap.blue, blue, size) || | ||
273 | (transp && copy_from_user(umap.transp, transp, size))) { | ||
274 | rc = -EFAULT; | ||
275 | } | ||
276 | umap.start = start; | ||
277 | if (rc == 0) | ||
278 | rc = info->fbops->fb_setcmap(&umap, info); | ||
279 | fb_dealloc_cmap(&umap); | ||
280 | return rc; | ||
281 | } | ||
282 | |||
255 | for (i = 0; i < cmap->len; i++, red++, blue++, green++) { | 283 | for (i = 0; i < cmap->len; i++, red++, blue++, green++) { |
256 | if (get_user(hred, red) || | 284 | if (get_user(hred, red) || |
257 | get_user(hgreen, green) || | 285 | get_user(hgreen, green) || |
diff --git a/include/linux/fb.h b/include/linux/fb.h index b45d3e2d711a..b468bf496547 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -563,6 +563,9 @@ struct fb_ops { | |||
563 | int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, | 563 | int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, |
564 | unsigned blue, unsigned transp, struct fb_info *info); | 564 | unsigned blue, unsigned transp, struct fb_info *info); |
565 | 565 | ||
566 | /* set color registers in batch */ | ||
567 | int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); | ||
568 | |||
566 | /* blank display */ | 569 | /* blank display */ |
567 | int (*fb_blank)(int blank, struct fb_info *info); | 570 | int (*fb_blank)(int blank, struct fb_info *info); |
568 | 571 | ||