aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/aty/radeon_base.c118
-rw-r--r--drivers/video/fbcmap.c32
-rw-r--r--include/linux/fb.h3
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
1060static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, 1060static 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
1132static 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
1163static 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
1142static void radeon_save_state (struct radeonfb_info *rinfo, 1211static 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