comparison drivers/radeon/radeonfb.c @ 1914:838bfa146fa3

Merge with Ani Joshi's radeonfb-0.1.0
author nick
date Tue, 18 Sep 2001 16:26:11 +0000
parents 717f46012fce
children 31fdf7bb1a8e
comparison
equal deleted inserted replaced
1913:717f46012fce 1914:838bfa146fa3
9 * 2000-08-03 initial version 0.0.1 9 * 2000-08-03 initial version 0.0.1
10 * 2000-09-10 more bug fixes, public release 0.0.5 10 * 2000-09-10 more bug fixes, public release 0.0.5
11 * 2001-02-19 mode bug fixes, 0.0.7 11 * 2001-02-19 mode bug fixes, 0.0.7
12 * 2001-07-05 fixed scrolling issues, engine initialization, 12 * 2001-07-05 fixed scrolling issues, engine initialization,
13 * and minor mode tweaking, 0.0.9 13 * and minor mode tweaking, 0.0.9
14 * 2001-09-06 console switching fixes, blanking fixes,
15 * 0.1.0
14 * 16 *
15 * 2001-09-07 Radeon VE support 17 * 2001-09-07 Radeon VE support
16 * 2001-09-10 Radeon VE QZ support by Nick Kurshev <nickols_k@mail.ru> 18 * 2001-09-10 Radeon VE QZ support by Nick Kurshev <nickols_k@mail.ru>
17 * (limitations: on dualhead Radeons (VE, M6, M7) 19 * (limitations: on dualhead Radeons (VE, M6, M7)
18 * driver works only on second head (DVI port). 20 * driver works only on second head (DVI port).
19 * TVout is not supported too. M6 & M7 chips 21 * TVout is not supported too. M6 & M7 chips
20 * currently are not supported. Driver has a lot 22 * currently are not supported. Driver has a lot
21 * of other bugs. Probably they can be solved by 23 * of other bugs. Probably they can be solved by
22 * importing XFree86 code, which has ATI's support)., 24 * importing XFree86 code, which has ATI's support).,
23 * 0.0.11 25 * 0.0.11
24 * 26 * 2001-09-13 merge Ani Joshi radeonfb-0.1.0:
27 * console switching fixes, blanking fixes,
28 * 0.1.0-ve.0
25 * 29 *
26 * Special thanks to ATI DevRel team for their hardware donations. 30 * Special thanks to ATI DevRel team for their hardware donations.
27 * 31 *
28 */ 32 */
29 33
30 34
31 #define RADEON_VERSION "0.0.11" 35 #define RADEON_VERSION "0.1.0-ve.0"
32 36
33 37
34 #include <linux/config.h> 38 #include <linux/config.h>
35 #include <linux/module.h> 39 #include <linux/module.h>
36 #include <linux/kernel.h> 40 #include <linux/kernel.h>
171 u32 pix_clock; 175 u32 pix_clock;
172 int xres, yres; 176 int xres, yres;
173 int bpp; 177 int bpp;
174 u32 crtc_gen_cntl; 178 u32 crtc_gen_cntl;
175 u32 crtc_ext_cntl; 179 u32 crtc_ext_cntl;
180 u32 surface_cntl;
176 u32 dac_cntl; 181 u32 dac_cntl;
177 u32 dda_config; 182 u32 dda_config;
178 u32 dda_on_off; 183 u32 dda_on_off;
179 u32 ppll_div_3; 184 u32 ppll_div_3;
180 u32 ppll_ref_div; 185 u32 ppll_ref_div;
215 struct pll_info pll; 220 struct pll_info pll;
216 int pll_output_freq, post_div, fb_div; 221 int pll_output_freq, post_div, fb_div;
217 222
218 struct ram_info ram; 223 struct ram_info ram;
219 224
225 u32 hack_crtc_ext_cntl;
226 u32 hack_crtc_v_sync_strt_wid;
227
220 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) 228 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
221 union { 229 union {
222 #if defined(FBCON_HAS_CFB16) 230 #if defined(FBCON_HAS_CFB16)
223 u_int16_t cfb16[16]; 231 u_int16_t cfb16[16];
224 #endif 232 #endif
233 #if defined(FBCON_HAS_CFB24)
234 u_int32_t cfb24[16];
235 #endif
225 #if defined(FBCON_HAS_CFB32) 236 #if defined(FBCON_HAS_CFB32)
226 u_int32_t cfb32[16]; 237 u_int32_t cfb32[16];
227 #endif 238 #endif
228 } con_cmap; 239 } con_cmap;
229 #endif 240 #endif
336 return DST_8BPP; 347 return DST_8BPP;
337 case 15: 348 case 15:
338 return DST_15BPP; 349 return DST_15BPP;
339 case 16: 350 case 16:
340 return DST_16BPP; 351 return DST_16BPP;
352 case 24:
353 return DST_24BPP;
341 case 32: 354 case 32:
342 return DST_32BPP; 355 return DST_32BPP;
343 default: 356 default:
344 return 0; 357 return 0;
345 } 358 }
458 471
459 static char fontname[40] __initdata; 472 static char fontname[40] __initdata;
460 static char *mode_option __initdata; 473 static char *mode_option __initdata;
461 static char noaccel __initdata = 0; 474 static char noaccel __initdata = 0;
462 475
476 #if 0
463 #ifdef FBCON_HAS_CFB8 477 #ifdef FBCON_HAS_CFB8
464 static struct display_switch fbcon_radeon8; 478 static struct display_switch fbcon_radeon8;
465 #endif 479 #endif
466 480 #endif
467 481
468 /* 482 /*
469 * prototypes 483 * prototypes
470 */ 484 */
471 485
490 static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, 504 static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green,
491 unsigned *blue, unsigned *transp, 505 unsigned *blue, unsigned *transp,
492 struct fb_info *info); 506 struct fb_info *info);
493 static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, 507 static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
494 unsigned blue, unsigned transp, struct fb_info *info); 508 unsigned blue, unsigned transp, struct fb_info *info);
495 static void radeon_set_dispsw (struct radeonfb_info *rinfo); 509 static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp);
496 static void radeon_save_state (struct radeonfb_info *rinfo, 510 static void radeon_save_state (struct radeonfb_info *rinfo,
497 struct radeon_regs *save); 511 struct radeon_regs *save);
498 static void radeon_engine_init (struct radeonfb_info *rinfo); 512 static void radeon_engine_init (struct radeonfb_info *rinfo);
499 static void radeon_load_video_mode (struct radeonfb_info *rinfo, 513 static void radeon_load_video_mode (struct radeonfb_info *rinfo,
500 struct fb_var_screeninfo *mode); 514 struct fb_var_screeninfo *mode);
506 static int radeonfb_pci_register (struct pci_dev *pdev, 520 static int radeonfb_pci_register (struct pci_dev *pdev,
507 const struct pci_device_id *ent); 521 const struct pci_device_id *ent);
508 static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev); 522 static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev);
509 static char *radeon_find_rom(struct radeonfb_info *rinfo); 523 static char *radeon_find_rom(struct radeonfb_info *rinfo);
510 static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg); 524 static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg);
511 525 static void do_install_cmap(int con, struct fb_info *info);
526 static int radeonfb_do_maximize(struct radeonfb_info *rinfo,
527 struct fb_var_screeninfo *var,
528 struct fb_var_screeninfo *v,
529 int nom, int den);
512 530
513 static struct fb_ops radeon_fb_ops = { 531 static struct fb_ops radeon_fb_ops = {
514 fb_get_fix: radeonfb_get_fix, 532 fb_get_fix: radeonfb_get_fix,
515 fb_get_var: radeonfb_get_var, 533 fb_get_var: radeonfb_get_var,
516 fb_set_var: radeonfb_set_var, 534 fb_set_var: radeonfb_set_var,
808 826
809 827
810 828
811 static char *radeon_find_rom(struct radeonfb_info *rinfo) 829 static char *radeon_find_rom(struct radeonfb_info *rinfo)
812 { 830 {
831 #if defined(__i386__)
813 u32 segstart; 832 u32 segstart;
814 char *rom_base; 833 char *rom_base;
815 char *rom; 834 char *rom;
816 int stage; 835 int stage;
817 int i; 836 int i;
818 char aty_rom_sig[] = "761295520"; 837 char aty_rom_sig[] = "761295520";
819 char radeon_sig[] = "RG6"; 838 char radeon_sig[] = "RG6";
820 839
821 #if defined(__i386__)
822 for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { 840 for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
823 stage = 1; 841 stage = 1;
824 842
825 rom_base = (char *)ioremap(segstart, 0x1000); 843 rom_base = (char *)ioremap(segstart, 0x1000);
826 844
996 disp = &rinfo->disp; 1014 disp = &rinfo->disp;
997 1015
998 disp->var = radeonfb_default_var; 1016 disp->var = radeonfb_default_var;
999 info->disp = disp; 1017 info->disp = disp;
1000 1018
1001 radeon_set_dispsw (rinfo); 1019 radeon_set_dispsw (rinfo, disp);
1002 1020
1003 if (noaccel) 1021 if (noaccel)
1004 disp->scrollmode = SCROLL_YREDRAW; 1022 disp->scrollmode = SCROLL_YREDRAW;
1005 else 1023 else
1006 disp->scrollmode = 0; 1024 disp->scrollmode = 0;
1033 1051
1034 return 0; 1052 return 0;
1035 } 1053 }
1036 1054
1037 1055
1038 1056 static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp)
1039 static void radeon_set_dispsw (struct radeonfb_info *rinfo) 1057 {
1040 {
1041 struct display *disp = &rinfo->disp;
1042 int accel; 1058 int accel;
1043 1059
1044 accel = disp->var.accel_flags & FB_ACCELF_TEXT; 1060 accel = disp->var.accel_flags & FB_ACCELF_TEXT;
1045 1061
1046 disp->dispsw_data = NULL; 1062 disp->dispsw_data = NULL;
1055 1071
1056 rinfo->depth = disp->var.bits_per_pixel; 1072 rinfo->depth = disp->var.bits_per_pixel;
1057 switch (disp->var.bits_per_pixel) { 1073 switch (disp->var.bits_per_pixel) {
1058 #ifdef FBCON_HAS_CFB8 1074 #ifdef FBCON_HAS_CFB8
1059 case 8: 1075 case 8:
1060 disp->dispsw = accel ? &fbcon_radeon8 : &fbcon_cfb8; 1076 disp->dispsw = &fbcon_cfb8;
1061 disp->visual = FB_VISUAL_PSEUDOCOLOR; 1077 disp->visual = FB_VISUAL_PSEUDOCOLOR;
1062 disp->line_length = disp->var.xres_virtual; 1078 disp->line_length = disp->var.xres_virtual;
1063 break; 1079 break;
1064 #endif 1080 #endif
1065 #ifdef FBCON_HAS_CFB16 1081 #ifdef FBCON_HAS_CFB16
1066 case 16: 1082 case 16:
1067 disp->dispsw = &fbcon_cfb16; 1083 disp->dispsw = &fbcon_cfb16;
1068 disp->dispsw_data = &rinfo->con_cmap.cfb16; 1084 disp->dispsw_data = &rinfo->con_cmap.cfb16;
1069 disp->visual = FB_VISUAL_DIRECTCOLOR; 1085 disp->visual = FB_VISUAL_DIRECTCOLOR;
1070 disp->line_length = disp->var.xres_virtual * 2; 1086 disp->line_length = disp->var.xres_virtual * 2;
1087 break;
1088 #endif
1089 #ifdef FBCON_HAS_CFB32
1090 case 24:
1091 disp->dispsw = &fbcon_cfb24;
1092 disp->dispsw_data = &rinfo->con_cmap.cfb24;
1093 disp->visual = FB_VISUAL_DIRECTCOLOR;
1094 disp->line_length = disp->var.xres_virtual * 4;
1071 break; 1095 break;
1072 #endif 1096 #endif
1073 #ifdef FBCON_HAS_CFB32 1097 #ifdef FBCON_HAS_CFB32
1074 case 32: 1098 case 32:
1075 disp->dispsw = &fbcon_cfb32; 1099 disp->dispsw = &fbcon_cfb32;
1144 struct fb_info *info) 1168 struct fb_info *info)
1145 { 1169 {
1146 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; 1170 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1147 struct display *disp; 1171 struct display *disp;
1148 struct fb_var_screeninfo v; 1172 struct fb_var_screeninfo v;
1149 int nom, den, i, accel; 1173 int nom, den, accel;
1150 unsigned chgvar = 0; 1174 unsigned chgvar = 0;
1151 static struct {
1152 int xres, yres;
1153 } modes[] = {
1154 {
1155 1600, 1280}, {
1156 1280, 1024}, {
1157 1024, 768}, {
1158 800, 600}, {
1159 640, 480}, {
1160 -1, -1}
1161 };
1162 1175
1163 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; 1176 disp = (con < 0) ? rinfo->info.disp : &fb_display[con];
1164 1177
1165 accel = var->accel_flags & FB_ACCELF_TEXT; 1178 accel = var->accel_flags & FB_ACCELF_TEXT;
1166 1179
1167 if (con >= 0) { 1180 if (con >= 0) {
1168 chgvar = ((disp->var.xres != var->xres) || 1181 chgvar = ((disp->var.xres != var->xres) ||
1169 (disp->var.yres != var->yres) || 1182 (disp->var.yres != var->yres) ||
1170 (disp->var.xres_virtual != var->xres_virtual) || 1183 (disp->var.xres_virtual != var->xres_virtual) ||
1171 (disp->var.yres_virtual != var->yres_virtual) || 1184 (disp->var.yres_virtual != var->yres_virtual) ||
1185 (disp->var.bits_per_pixel != var->bits_per_pixel) ||
1172 memcmp (&disp->var.red, &var->red, sizeof (var->red)) || 1186 memcmp (&disp->var.red, &var->red, sizeof (var->red)) ||
1173 memcmp (&disp->var.green, &var->green, sizeof (var->green)) || 1187 memcmp (&disp->var.green, &var->green, sizeof (var->green)) ||
1174 memcmp (&disp->var.blue, &var->blue, sizeof (var->blue))); 1188 memcmp (&disp->var.blue, &var->blue, sizeof (var->blue)));
1175 } 1189 }
1176 1190
1177 memcpy (&v, var, sizeof (v)); 1191 memcpy (&v, var, sizeof (v));
1178 1192
1179 switch (v.bits_per_pixel) { 1193 switch (v.bits_per_pixel) {
1180 #ifdef FBCON_HAS_CFB8 1194 #ifdef FBCON_HAS_CFB8
1181 case 8: 1195 case 8:
1182 v.bits_per_pixel = 8;
1183 disp->dispsw = accel ? &fbcon_radeon8 : &fbcon_cfb8;
1184 nom = den = 1; 1196 nom = den = 1;
1185 disp->line_length = v.xres_virtual; 1197 disp->line_length = v.xres_virtual;
1186 disp->visual = FB_VISUAL_PSEUDOCOLOR; 1198 disp->visual = FB_VISUAL_PSEUDOCOLOR;
1187 v.red.offset = v.green.offset = v.blue.offset = 0; 1199 v.red.offset = v.green.offset = v.blue.offset = 0;
1188 v.red.length = v.green.length = v.blue.length = 8; 1200 v.red.length = v.green.length = v.blue.length = 8;
1201 v.transp.offset = v.transp.length = 0;
1189 break; 1202 break;
1190 #endif 1203 #endif
1191 1204
1192 #ifdef FBCON_HAS_CFB16 1205 #ifdef FBCON_HAS_CFB16
1193 case 16: 1206 case 16:
1194 v.bits_per_pixel = 16;
1195 disp->dispsw = &fbcon_cfb16;
1196 disp->dispsw_data = &rinfo->con_cmap.cfb16;
1197 nom = 2; 1207 nom = 2;
1198 den = 1; 1208 den = 1;
1199 disp->line_length = v.xres_virtual * 2; 1209 disp->line_length = v.xres_virtual * 2;
1200 disp->visual = FB_VISUAL_DIRECTCOLOR; 1210 disp->visual = FB_VISUAL_DIRECTCOLOR;
1201 v.red.offset = 11; 1211 v.red.offset = 11;
1202 v.green.offset = 5; 1212 v.green.offset = 5;
1203 v.blue.offset = 0; 1213 v.blue.offset = 0;
1204 v.red.length = 5; 1214 v.red.length = 5;
1205 v.green.length = 6; 1215 v.green.length = 6;
1206 v.blue.length = 5; 1216 v.blue.length = 5;
1217 v.transp.offset = v.transp.length = 0;
1207 break; 1218 break;
1208 #endif 1219 #endif
1209 1220
1221 #ifdef FBCON_HAS_CFB24
1222 case 24:
1223 nom = 4;
1224 den = 1;
1225 disp->line_length = v.xres_virtual * 3;
1226 disp->visual = FB_VISUAL_DIRECTCOLOR;
1227 v.red.offset = 16;
1228 v.green.offset = 8;
1229 v.blue.offset = 0;
1230 v.red.length = v.blue.length = v.green.length = 8;
1231 v.transp.offset = v.transp.length = 0;
1232 break;
1233 #endif
1210 #ifdef FBCON_HAS_CFB32 1234 #ifdef FBCON_HAS_CFB32
1211 case 32: 1235 case 32:
1212 v.bits_per_pixel = 32;
1213 disp->dispsw = &fbcon_cfb32;
1214 disp->dispsw_data = rinfo->con_cmap.cfb32;
1215 nom = 4; 1236 nom = 4;
1216 den = 1; 1237 den = 1;
1217 disp->line_length = v.xres_virtual * 4; 1238 disp->line_length = v.xres_virtual * 4;
1218 disp->visual = FB_VISUAL_DIRECTCOLOR; 1239 disp->visual = FB_VISUAL_DIRECTCOLOR;
1219 v.red.offset = 16; 1240 v.red.offset = 16;
1220 v.green.offset = 8; 1241 v.green.offset = 8;
1221 v.blue.offset = 0; 1242 v.blue.offset = 0;
1222 v.red.length = v.blue.length = v.green.length = 8; 1243 v.red.length = v.blue.length = v.green.length = 8;
1244 v.transp.offset = 24;
1245 v.transp.length = 8;
1223 break; 1246 break;
1224 #endif 1247 #endif
1225 default: 1248 default:
1226 printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n", 1249 printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
1227 var->xres, var->yres, var->bits_per_pixel); 1250 var->xres, var->yres, var->bits_per_pixel);
1228 return -EINVAL; 1251 return -EINVAL;
1229 } 1252 }
1230 1253
1231 if (v.xres * nom / den * v.yres > (rinfo->video_ram)) { 1254 if (radeonfb_do_maximize(rinfo, var, &v, nom, den) < 0)
1232 printk ("radeonfb: mode %dx%dx%d rejected, not enough video ram\n", 1255 return -EINVAL;
1233 var->xres, var->yres, var->bits_per_pixel);
1234 return -EINVAL;
1235 }
1236
1237 if (v.xres_virtual == -1 && v.yres_virtual == -1) {
1238 printk ("radeonfb: using maximum available virtual resolution\n");
1239 for (i = 0; modes[i].xres != -1; i++) {
1240 if (modes[i].xres * nom / den * modes[i].yres < (rinfo->video_ram/2))
1241 break;
1242 }
1243 if (modes[i].xres == -1) {
1244 printk ("radeonfb: could not find a virtual res\n");
1245 return -EINVAL;
1246 }
1247 v.xres_virtual = modes[i].xres;
1248 v.yres_virtual = modes[i].yres;
1249
1250 printk ("radeonfb: virtual resolution set to maximum of %dx%d\n",
1251 v.xres_virtual, v.yres_virtual);
1252 }
1253 1256
1254 if (v.xoffset < 0) 1257 if (v.xoffset < 0)
1255 v.xoffset = 0; 1258 v.xoffset = 0;
1256 if (v.yoffset < 0) 1259 if (v.yoffset < 0)
1257 v.yoffset = 0; 1260 v.yoffset = 0;
1274 break; 1277 break;
1275 default: 1278 default:
1276 return -EINVAL; 1279 return -EINVAL;
1277 } 1280 }
1278 1281
1279 disp->type = FB_TYPE_PACKED_PIXELS;
1280
1281 memcpy (&disp->var, &v, sizeof (v)); 1282 memcpy (&disp->var, &v, sizeof (v));
1282 1283
1284 if (chgvar) {
1285 radeon_set_dispsw(rinfo, disp);
1286
1287 if (noaccel)
1288 disp->scrollmode = SCROLL_YREDRAW;
1289 else
1290 disp->scrollmode = 0;
1291
1292 if (info && info->changevar)
1293 info->changevar(con);
1294 }
1295
1283 radeon_load_video_mode (rinfo, &v); 1296 radeon_load_video_mode (rinfo, &v);
1284 1297
1285 if (chgvar && info && info->changevar) 1298 do_install_cmap(con, info);
1286 info->changevar (con); 1299
1287
1288 return 0; 1300 return 0;
1289 } 1301 }
1290 1302
1291 1303
1292 1304
1341 1353
1342 static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, 1354 static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con,
1343 struct fb_info *info) 1355 struct fb_info *info)
1344 { 1356 {
1345 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; 1357 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1346 struct display *disp; 1358 u32 offset, xoffset, yoffset;
1347 unsigned int base; 1359
1348 1360 xoffset = (var->xoffset + 7) & ~7;
1349 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; 1361 yoffset = var->yoffset;
1350 1362
1351 if (var->xoffset > (var->xres_virtual - var->xres)) 1363 if ((xoffset + var->xres > var->xres_virtual) || (yoffset+var->yres >
1352 return -EINVAL; 1364 var->yres_virtual))
1353 if (var->yoffset > (var->yres_virtual - var->yres)) 1365 return -EINVAL;
1354 return -EINVAL; 1366
1355 1367 offset = ((yoffset * var->xres + xoffset) * var->bits_per_pixel) >> 6;
1356 if (var->vmode & FB_VMODE_YWRAP) { 1368
1357 if (var->yoffset < 0 || 1369 OUTREG(CRTC_OFFSET, offset);
1358 var->yoffset >= disp->var.yres_virtual ||
1359 var->xoffset )
1360 return -EINVAL;
1361 } else {
1362 if (var->xoffset + disp->var.xres > disp->var.xres_virtual ||
1363 var->yoffset + disp->var.yres > disp->var.yres_virtual)
1364 return -EINVAL;
1365 }
1366
1367 base = var->yoffset * disp->line_length + var->xoffset;
1368
1369 disp->var.xoffset = var->xoffset;
1370 disp->var.yoffset = var->yoffset;
1371
1372 if (var->vmode & FB_VMODE_YWRAP)
1373 disp->var.vmode |= FB_VMODE_YWRAP;
1374 else
1375 disp->var.vmode &= ~FB_VMODE_YWRAP;
1376 1370
1377 return 0; 1371 return 0;
1378 } 1372 }
1379 1373
1374
1375 static void do_install_cmap(int con, struct fb_info *info)
1376 {
1377 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1378
1379 if (con != rinfo->currcon)
1380 return;
1381
1382 if (fb_display[con].cmap.len)
1383 fb_set_cmap(&fb_display[con].cmap, 1, radeon_setcolreg, info);
1384 else {
1385 int size = fb_display[con].var.bits_per_pixel == 8 ? 256 : 32;
1386 fb_set_cmap(fb_default_cmap(size), 1, radeon_setcolreg, info);
1387 }
1388 }
1389
1390
1391 static int radeonfb_do_maximize(struct radeonfb_info *rinfo,
1392 struct fb_var_screeninfo *var,
1393 struct fb_var_screeninfo *v,
1394 int nom, int den)
1395 {
1396 static struct {
1397 int xres, yres;
1398 } modes[] = {
1399 {1600, 1280},
1400 {1280, 1024},
1401 {1024, 768},
1402 {800, 600},
1403 {640, 480},
1404 {-1, -1}
1405 };
1406 int i;
1407
1408 /* use highest possible virtual resolution */
1409 if (v->xres_virtual == -1 && v->yres_virtual == -1) {
1410 printk("radeonfb: using max availabe virtual resolution\n");
1411 for (i=0; modes[i].xres != -1; i++) {
1412 if (modes[i].xres * nom / den * modes[i].yres <
1413 rinfo->video_ram / 2)
1414 break;
1415 }
1416 if (modes[i].xres == -1) {
1417 printk("radeonfb: could not find virtual resolution that fits into video memory!\n");
1418 return -EINVAL;
1419 }
1420 v->xres_virtual = modes[i].xres;
1421 v->yres_virtual = modes[i].yres;
1422
1423 printk("radeonfb: virtual resolution set to max of %dx%d\n",
1424 v->xres_virtual, v->yres_virtual);
1425 } else if (v->xres_virtual == -1) {
1426 v->xres_virtual = (rinfo->video_ram * den /
1427 (nom * v->yres_virtual * 2)) & ~15;
1428 } else if (v->yres_virtual == -1) {
1429 v->xres_virtual = (v->xres_virtual + 15) & ~15;
1430 v->yres_virtual = rinfo->video_ram * den /
1431 (nom * v->xres_virtual *2);
1432 } else {
1433 if (v->xres_virtual * nom / den * v->yres_virtual >
1434 rinfo->video_ram) {
1435 return -EINVAL;
1436 }
1437 }
1438
1439 if (v->xres_virtual * nom / den >= 8192) {
1440 v->xres_virtual = 8192 * den / nom - 16;
1441 }
1442
1443 if (v->xres_virtual < v->xres)
1444 return -EINVAL;
1445
1446 if (v->yres_virtual < v->yres)
1447 return -EINVAL;
1448
1449 return 0;
1450 }
1380 1451
1381 1452
1382 static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 1453 static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
1383 unsigned long arg, int con, struct fb_info *info) 1454 unsigned long arg, int con, struct fb_info *info)
1384 { 1455 {
1391 { 1462 {
1392 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; 1463 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1393 struct display *disp; 1464 struct display *disp;
1394 struct fb_cmap *cmap; 1465 struct fb_cmap *cmap;
1395 int switchcon = 0; 1466 int switchcon = 0;
1396 1467
1397 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; 1468 disp = (con < 0) ? rinfo->info.disp : &fb_display[con];
1398 1469
1399 if (rinfo->currcon >= 0) { 1470 if (rinfo->currcon >= 0) {
1400 cmap = &(rinfo->currcon_display->cmap); 1471 cmap = &(rinfo->currcon_display->cmap);
1401 if (cmap->len) 1472 if (cmap->len)
1412 rinfo->currcon = con; 1483 rinfo->currcon = con;
1413 rinfo->currcon_display = disp; 1484 rinfo->currcon_display = disp;
1414 disp->var.activate = FB_ACTIVATE_NOW; 1485 disp->var.activate = FB_ACTIVATE_NOW;
1415 1486
1416 radeonfb_set_var (&disp->var, con, info); 1487 radeonfb_set_var (&disp->var, con, info);
1417 radeon_set_dispsw (rinfo); 1488 radeon_set_dispsw (rinfo, disp);
1418 } 1489 do_install_cmap(con, info);
1419 1490 }
1491
1492 /* XXX absurd hack for X to restore console */
1493 {
1494 OUTREG(CRTC_EXT_CNTL, rinfo->hack_crtc_ext_cntl);
1495 OUTREG(CRTC_V_SYNC_STRT_WID, rinfo->hack_crtc_v_sync_strt_wid);
1496 }
1497
1420 return 0; 1498 return 0;
1421 } 1499 }
1422 1500
1423 1501
1424 1502
1433 } 1511 }
1434 1512
1435 static void radeonfb_blank (int blank, struct fb_info *info) 1513 static void radeonfb_blank (int blank, struct fb_info *info)
1436 { 1514 {
1437 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; 1515 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1438 u8 mode = 0; 1516 u32 val = INREG(CRTC_EXT_CNTL);
1517
1518 /* reset it */
1519 val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
1520 CRTC_VSYNC_DIS);
1439 1521
1440 switch (blank) { 1522 switch (blank) {
1441 case 0: 1523 case VESA_NO_BLANKING:
1442 /* unblank */
1443 mode = 0;
1444 break; 1524 break;
1445 case 1: 1525 case VESA_VSYNC_SUSPEND:
1446 /* blank */ 1526 val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
1447 mode = ((INREG8(CRTC_EXT_CNTL + 1) & 3) | 4);
1448 break; 1527 break;
1449 case 2: 1528 case VESA_HSYNC_SUSPEND:
1450 case 3: 1529 val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
1451 case 4:
1452 mode = blank | 4;
1453 break; 1530 break;
1454 } 1531 case VESA_POWERDOWN:
1455 1532 val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
1456 OUTREG8(CRTC_EXT_CNTL + 1, mode); 1533 CRTC_HSYNC_DIS);
1534 break;
1535 }
1536
1537 OUTREG(CRTC_EXT_CNTL, val);
1457 } 1538 }
1458 1539
1459 1540
1460 1541
1461 static int radeon_get_cmap_len (const struct fb_var_screeninfo *var) 1542 static int radeon_get_cmap_len (const struct fb_var_screeninfo *var)
1500 1581
1501 static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, 1582 static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
1502 unsigned blue, unsigned transp, struct fb_info *info) 1583 unsigned blue, unsigned transp, struct fb_info *info)
1503 { 1584 {
1504 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; 1585 struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
1505 u32 pindex, col; 1586 u32 pindex;
1506 1587
1507 if (regno > 255) 1588 if (regno > 255)
1508 return 1; 1589 return 1;
1509 1590
1510 red >>= 8; 1591 red >>= 8;
1515 rinfo->palette[regno].blue = blue; 1596 rinfo->palette[regno].blue = blue;
1516 1597
1517 /* init gamma for hicolor */ 1598 /* init gamma for hicolor */
1518 if ((rinfo->depth > 8) && (regno == 0)) { 1599 if ((rinfo->depth > 8) && (regno == 0)) {
1519 int i; 1600 int i;
1520 u32 tmp;
1521 1601
1522 for (i=0; i<255; i++) { 1602 for (i=0; i<255; i++) {
1523 OUTREG(PALETTE_INDEX, i); 1603 OUTREG(PALETTE_INDEX, i);
1524 tmp = (i << 16) | (i << 8) | i; 1604 OUTREG(PALETTE_DATA, (i << 16) | (i << 8) | i);
1525 radeon_fifo_wait(32);
1526 OUTREG(PALETTE_DATA, tmp);
1527 } 1605 }
1528 } 1606 }
1529 1607
1530 /* default */ 1608 /* default */
1531 pindex = regno; 1609 pindex = regno;
1610
1611 /* XXX actually bpp, fixme */
1612 if (rinfo->depth == 16)
1613 pindex = regno * 8;
1614
1615 if (rinfo->depth == 16) {
1616 OUTREG(PALETTE_INDEX, pindex/2);
1617 OUTREG(PALETTE_DATA, (rinfo->palette[regno/2].red << 16) |
1618 (green << 8) | (rinfo->palette[regno/2].blue));
1619 green = rinfo->palette[regno/2].green;
1620 }
1621
1622 if ((rinfo->depth == 8) || (regno < 32)) {
1623 OUTREG(PALETTE_INDEX, pindex);
1624 OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
1625 }
1626
1627 #if 0
1532 col = (red << 16) | (green << 8) | blue; 1628 col = (red << 16) | (green << 8) | blue;
1533 1629
1534 if (rinfo->depth == 16) { 1630 if (rinfo->depth == 16) {
1535 pindex = regno << 3; 1631 pindex = regno << 3;
1536 1632
1546 } 1642 }
1547 1643
1548 OUTREG8(PALETTE_INDEX, pindex); 1644 OUTREG8(PALETTE_INDEX, pindex);
1549 radeon_fifo_wait(32); 1645 radeon_fifo_wait(32);
1550 OUTREG(PALETTE_DATA, col); 1646 OUTREG(PALETTE_DATA, col);
1647 #endif
1551 1648
1552 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) 1649 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
1553 if (regno < 32) { 1650 if (regno < 32) {
1554 switch (rinfo->depth) { 1651 switch (rinfo->depth) {
1555 #ifdef FBCON_HAS_CFB16 1652 #ifdef FBCON_HAS_CFB16
1556 case 16: 1653 case 16:
1557 rinfo->con_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | 1654 rinfo->con_cmap.cfb16[regno] = (regno << 11) | (regno << 5) |
1558 regno; 1655 regno;
1656 break;
1657 #endif
1658 #ifdef FBCON_HAS_CFB24
1659 case 24:
1660 rinfo->con_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno;
1559 break; 1661 break;
1560 #endif 1662 #endif
1561 #ifdef FBCON_HAS_CFB32 1663 #ifdef FBCON_HAS_CFB32
1562 case 32: { 1664 case 32: {
1563 u32 i; 1665 u32 i;
1630 vsync_wid = vSyncEnd - vSyncStart; 1732 vsync_wid = vSyncEnd - vSyncStart;
1631 if (hsync_wid == 0) 1733 if (hsync_wid == 0)
1632 hsync_wid = 1; 1734 hsync_wid = 1;
1633 else if (hsync_wid > 0x3f) /* max */ 1735 else if (hsync_wid > 0x3f) /* max */
1634 hsync_wid = 0x3f; 1736 hsync_wid = 0x3f;
1635 1737 vsync_wid = mode->vsync_len;
1636 if (vsync_wid == 0) 1738 if (vsync_wid == 0)
1637 vsync_wid = 1; 1739 vsync_wid = 1;
1638 else if (vsync_wid > 0x1f) /* max */ 1740 else if (vsync_wid > 0x1f) /* max */
1639 vsync_wid = 0x1f; 1741 vsync_wid = 0x1f;
1640 1742
1641 if (mode->sync & FB_SYNC_HOR_HIGH_ACT) 1743 hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
1642 hSyncPol = 1; 1744 vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
1643 else
1644 hSyncPol = 0;
1645
1646 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
1647 vSyncPol = 1;
1648 else
1649 vSyncPol = 0;
1650 1745
1651 cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; 1746 cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
1652 1747
1653 switch (mode->bits_per_pixel) { 1748 switch (mode->bits_per_pixel) {
1654 case 8: 1749 case 8:
1682 1777
1683 newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0xffff) | 1778 newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0xffff) |
1684 (((mode->xres / 8) - 1) << 16)); 1779 (((mode->xres / 8) - 1) << 16));
1685 1780
1686 newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | 1781 newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
1687 (hsync_wid << 16) | (hSyncPol << 23)); 1782 (hsync_wid << 16) | (h_sync_pol << 23));
1688 1783
1689 newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) | 1784 newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
1690 ((mode->yres - 1) << 16); 1785 ((mode->yres - 1) << 16);
1691 1786
1692 newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | 1787 newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
1693 (vsync_wid << 16) | (vSyncPol << 23)); 1788 (vsync_wid << 16) | (v_sync_pol << 23));
1694 1789
1695 newmode.crtc_pitch = (mode->xres >> 3); 1790 newmode.crtc_pitch = (mode->xres >> 3);
1791
1792 newmode.surface_cntl = SURF_TRANSLATION_DIS;
1793 #if defined(__BIG_ENDIAN)
1794 switch (mode->bits_per_pixel) {
1795 case 16:
1796 newmode.surface_cntl |= NONSURF_AP0_SWP_16BPP;
1797 break;
1798 case 24:
1799 case 32:
1800 newmode.surface_cntl |= NONSURF_AP0_SWP_32BPP;
1801 break;
1802 }
1803 #endif
1696 1804
1697 rinfo->pitch = ((mode->xres * ((mode->bits_per_pixel + 1) / 8) + 0x3f) 1805 rinfo->pitch = ((mode->xres * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
1698 & ~(0x3f)) / 64; 1806 & ~(0x3f)) / 64;
1699 1807
1700 RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n", 1808 RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n",
1704 1812
1705 newmode.xres = mode->xres; 1813 newmode.xres = mode->xres;
1706 newmode.yres = mode->yres; 1814 newmode.yres = mode->yres;
1707 1815
1708 rinfo->bpp = mode->bits_per_pixel; 1816 rinfo->bpp = mode->bits_per_pixel;
1817 rinfo->hack_crtc_ext_cntl = newmode.crtc_ext_cntl;
1818 rinfo->hack_crtc_v_sync_strt_wid = newmode.crtc_v_sync_strt_wid;
1709 1819
1710 if (freq > rinfo->pll.ppll_max) 1820 if (freq > rinfo->pll.ppll_max)
1711 freq = rinfo->pll.ppll_max; 1821 freq = rinfo->pll.ppll_max;
1712 if (freq*12 < rinfo->pll.ppll_min) 1822 if (freq*12 < rinfo->pll.ppll_min)
1713 freq = rinfo->pll.ppll_min / 12; 1823 freq = rinfo->pll.ppll_min / 12;
1806 OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp); 1916 OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
1807 OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid); 1917 OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
1808 OUTREG(CRTC_OFFSET, 0); 1918 OUTREG(CRTC_OFFSET, 0);
1809 OUTREG(CRTC_OFFSET_CNTL, 0); 1919 OUTREG(CRTC_OFFSET_CNTL, 0);
1810 OUTREG(CRTC_PITCH, mode->crtc_pitch); 1920 OUTREG(CRTC_PITCH, mode->crtc_pitch);
1921 OUTREG(SURFACE_CNTL, mode->surface_cntl);
1811 1922
1812 while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) != 1923 while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) !=
1813 PPLL_DIV_SEL_MASK) { 1924 PPLL_DIV_SEL_MASK) {
1814 OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff); 1925 OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff);
1815 } 1926 }
1842 OUTREG8(CRTC_EXT_CNTL + 1, 0); 1953 OUTREG8(CRTC_EXT_CNTL + 1, 0);
1843 1954
1844 return; 1955 return;
1845 } 1956 }
1846 1957
1847 1958 #if 0
1848 1959
1849 /* 1960 /*
1850 * text console acceleration 1961 * text console acceleration
1851 */ 1962 */
1852 1963
1894 static void fbcon_radeon_clear(struct vc_data *conp, struct display *p, 2005 static void fbcon_radeon_clear(struct vc_data *conp, struct display *p,
1895 int srcy, int srcx, int height, int width) 2006 int srcy, int srcx, int height, int width)
1896 { 2007 {
1897 struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); 2008 struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info);
1898 u32 clr; 2009 u32 clr;
1899 u32 temp;
1900 2010
1901 clr = attr_bgcol_ec(p, conp); 2011 clr = attr_bgcol_ec(p, conp);
1902 clr |= (clr << 8); 2012 clr |= (clr << 8);
1903 clr |= (clr << 16); 2013 clr |= (clr << 16);
1904 2014
1932 revc: fbcon_cfb8_revc, 2042 revc: fbcon_cfb8_revc,
1933 clear_margins: fbcon_cfb8_clear_margins, 2043 clear_margins: fbcon_cfb8_clear_margins,
1934 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) 2044 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1935 }; 2045 };
1936 #endif 2046 #endif
2047
2048 #endif /* 0 */