Mercurial > mplayer.hg
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 */ |