20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
24 #include <linux/ctype.h>
33 #include <mach/hardware.h>
36 #include <asm/pgtable.h>
44 #undef FBCON_HAS_CFB16
45 #undef FBCON_HAS_CFB32
53 #define DEFAULT_XRES 640
54 #define DEFAULT_YRES 480
60 #undef DEBUG_MODE_SELECTION
111 #define MAX_SIZE 480*1024
134 static struct pixclock arc_clocks[] = {
136 { 123750, 126250, VIDC_CTRL_DIV3, VID_CTL_24MHz },
137 { 82500, 84167, VIDC_CTRL_DIV2, VID_CTL_24MHz },
138 { 61875, 63125, VIDC_CTRL_DIV1_5, VID_CTL_24MHz },
139 { 41250, 42083, VIDC_CTRL_DIV1, VID_CTL_24MHz },
142 static struct pixclock *
152 if (pixclock > arc_clocks[i].min_clock &&
153 pixclock < arc_clocks[i].max_clock)
154 return arc_clocks +
i;
174 struct pixclock *pclk;
176 u_int horiz_correction;
177 u_int sync_len, display_start, display_end, cycle;
179 u_int vid_ctl, vidc_ctl;
182 memset(&vidc, 0,
sizeof(vidc));
184 pclk = acornfb_valid_pixrate(var);
185 vidc_ctl = pclk->vidc_ctl;
186 vid_ctl = pclk->vid_ctl;
190 if (bandwidth > 143500)
191 vidc_ctl |= VIDC_CTRL_FIFO_3_7;
192 else if (bandwidth > 71750)
193 vidc_ctl |= VIDC_CTRL_FIFO_2_6;
194 else if (bandwidth > 35875)
195 vidc_ctl |= VIDC_CTRL_FIFO_1_5;
197 vidc_ctl |= VIDC_CTRL_FIFO_0_4;
201 horiz_correction = 19;
202 vidc_ctl |= VIDC_CTRL_1BPP;
206 horiz_correction = 11;
207 vidc_ctl |= VIDC_CTRL_2BPP;
211 horiz_correction = 7;
212 vidc_ctl |= VIDC_CTRL_4BPP;
217 horiz_correction = 5;
218 vidc_ctl |= VIDC_CTRL_8BPP;
223 vidc_ctl |= VIDC_CTRL_CSYNC;
226 vid_ctl |= VID_CTL_HS_NHSYNC;
229 vid_ctl |= VID_CTL_VS_NVSYNC;
234 display_end = display_start + var->
xres;
241 vidc_ctl |= VIDC_CTRL_INTERLACE;
248 vidc.h_cycle = (cycle - 2) / 2;
249 vidc.h_sync_width = (sync_len - 2) / 2;
250 vidc.h_border_start = (display_start - 1) / 2;
251 vidc.h_display_start = (display_start - horiz_correction) / 2;
252 vidc.h_display_end = (display_end - horiz_correction) / 2;
253 vidc.h_border_end = (display_end - 1) / 2;
254 vidc.h_interlace = (vidc.h_cycle + 1) / 2;
258 display_end = display_start + var->
yres;
262 cycle = (cycle - 3) / 2;
266 vidc.v_cycle = cycle;
267 vidc.v_sync_width = sync_len - 1;
268 vidc.v_border_start = display_start - 1;
269 vidc.v_display_start = vidc.v_border_start;
270 vidc.v_display_end = display_end - 1;
271 vidc.v_border_end = vidc.v_display_end;
273 if (machine_is_a5k())
276 if (
memcmp(¤t_vidc, &vidc,
sizeof(vidc))) {
281 vidc_writel(0x84000000 | (vidc.h_sync_width << 14));
282 vidc_writel(0x88000000 | (vidc.h_border_start << 14));
283 vidc_writel(0x8c000000 | (vidc.h_display_start << 14));
284 vidc_writel(0x90000000 | (vidc.h_display_end << 14));
285 vidc_writel(0x94000000 | (vidc.h_border_end << 14));
287 vidc_writel(0x9c000000 | (vidc.h_interlace << 14));
289 vidc_writel(0xa4000000 | (vidc.v_sync_width << 14));
290 vidc_writel(0xa8000000 | (vidc.v_border_start << 14));
291 vidc_writel(0xac000000 | (vidc.v_display_start << 14));
292 vidc_writel(0xb0000000 | (vidc.v_display_end << 14));
293 vidc_writel(0xb4000000 | (vidc.v_border_end << 14));
297 #ifdef DEBUG_MODE_SELECTION
324 if (regno >= current_par.palette_size)
328 pal.vidc.reg = regno;
329 pal.vidc.red = red >> 12;
330 pal.vidc.green = green >> 12;
331 pal.vidc.blue = blue >> 12;
333 current_par.palette[regno] =
pal;
344 #define MAX_SIZE 2*1024*1024
356 static void acornfb_set_timing(
struct fb_info *info)
361 u_int ext_ctl, dat_ctl;
362 u_int words_per_line;
364 memset(&vidc, 0,
sizeof(vidc));
367 vidc.h_border_start = vidc.h_sync_width + var->
left_margin + 8 - 12;
368 vidc.h_display_start = vidc.h_border_start + 12 - 18;
369 vidc.h_display_end = vidc.h_display_start + var->
xres;
370 vidc.h_border_end = vidc.h_display_end + 18 - 12;
371 vidc.h_cycle = vidc.h_border_end + var->
right_margin + 12 - 8;
372 vidc.h_interlace = vidc.h_cycle / 2;
374 vidc.v_border_start = vidc.v_sync_width + var->
upper_margin;
375 vidc.v_display_start = vidc.v_border_start;
376 vidc.v_display_end = vidc.v_display_start + var->
yres;
377 vidc.v_border_end = vidc.v_display_end;
384 vidc.v_cycle = (vcr - 3) / 2;
385 vidc.control |= VIDC20_CTRL_INT;
387 vidc.v_cycle = vcr - 2;
390 case 1: vidc.control |= VIDC20_CTRL_1BPP;
break;
391 case 2: vidc.control |= VIDC20_CTRL_2BPP;
break;
392 case 4: vidc.control |= VIDC20_CTRL_4BPP;
break;
394 case 8: vidc.control |= VIDC20_CTRL_8BPP;
break;
395 case 16: vidc.control |= VIDC20_CTRL_16BPP;
break;
396 case 32: vidc.control |= VIDC20_CTRL_32BPP;
break;
399 acornfb_vidc20_find_rates(&vidc, var);
402 if (
memcmp(¤t_vidc, &vidc,
sizeof(vidc))) {
430 ext_ctl |= VIDC20_ECTL_HS_NCSYNC | VIDC20_ECTL_VS_NCSYNC;
433 ext_ctl |= VIDC20_ECTL_HS_HSYNC;
435 ext_ctl |= VIDC20_ECTL_HS_NHSYNC;
438 ext_ctl |= VIDC20_ECTL_VS_VSYNC;
440 ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
447 if (current_par.using_vram && info->
fix.smem_len == 2048*1024)
451 dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
459 if (current_par.using_vram && current_par.vram_half_sam == 2048)
460 dat_ctl |= VIDC20_DCTL_BUS_D63_0;
462 dat_ctl |= VIDC20_DCTL_BUS_D31_0;
466 #ifdef DEBUG_MODE_SELECTION
514 if (regno >= current_par.palette_size)
520 pseudo_val = regno << info->
var.red.offset;
521 pseudo_val |= regno << info->
var.green.offset;
522 pseudo_val |= regno << info->
var.blue.offset;
528 pal.vidc20.red = red >> 8;
529 pal.vidc20.green = green >> 8;
530 pal.vidc20.blue = blue >> 8;
532 current_par.palette[regno] =
pal;
534 if (info->
var.bits_per_pixel == 16) {
539 for (i = 0; i < 256; i += 1) {
540 pal.vidc20.red = current_par.palette[ i & 31].vidc20.red;
541 pal.vidc20.green = current_par.palette[(i >> 1) & 31].
vidc20.green;
542 pal.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
562 u_int font_line_len, sam_size, min_size,
size, nr_y;
573 if (current_par.using_vram)
574 sam_size = current_par.vram_half_sam * 2;
592 if (min_size > info->
fix.smem_len)
598 for (size = info->
fix.smem_len;
599 nr_y = size / font_line_len, min_size <= size;
601 if (nr_y * font_line_len == size)
607 if (min_size > size) {
611 size = info->
fix.smem_len;
618 current_par.screen_end = info->
fix.smem_start +
size;
646 #elif defined(HAS_VIDC20)
668 unsigned long hs, vs;
683 return (vs >= monspecs->
vfmin && vs <= monspecs->vfmax &&
684 hs >= monspecs->
hfmin && hs <= monspecs->hfmax) ? 0 : -
EINVAL;
692 #if defined(HAS_MEMC)
694 #elif defined(HAS_IOMD)
710 var->
red.msb_right = 0;
711 var->
green.msb_right = 0;
712 var->
blue.msb_right = 0;
713 var->
transp.msb_right = 0;
716 case 1:
case 2:
case 4:
case 8:
729 var->
green.offset = 5;
730 var->
green.length = 5;
731 var->
blue.offset = 10;
732 var->
blue.length = 5;
740 var->
green.offset = 8;
741 var->
green.length = 8;
742 var->
blue.offset = 16;
743 var->
blue.length = 8;
755 if (!acornfb_valid_pixrate(var))
762 err = acornfb_adjust_timing(info, var, fontht);
770 return acornfb_validate_timing(var, &info->
monspecs);
773 static int acornfb_set_par(
struct fb_info *info)
775 switch (info->
var.bits_per_pixel) {
777 current_par.palette_size = 2;
781 current_par.palette_size = 4;
785 current_par.palette_size = 16;
789 current_par.palette_size = VIDC_PALETTE_SIZE;
798 current_par.palette_size = 32;
802 current_par.palette_size = VIDC_PALETTE_SIZE;
810 info->
fix.line_length = (info->
var.xres * info->
var.bits_per_pixel) / 8;
812 #if defined(HAS_MEMC)
819 #elif defined(HAS_IOMD)
824 start = info->
fix.smem_start;
825 size = current_par.screen_end;
827 if (current_par.using_vram) {
828 size -= current_par.vram_half_sam;
829 control =
DMA_CR_E | (current_par.vram_half_sam / 256);
841 acornfb_update_dma(info, &info->
var);
842 acornfb_set_timing(info);
853 y_bottom += info->
var.yres;
855 if (y_bottom > info->
var.yres_virtual)
858 acornfb_update_dma(info, var);
863 static struct fb_ops acornfb_ops = {
865 .fb_check_var = acornfb_check_var,
866 .fb_set_par = acornfb_set_par,
867 .fb_setcolreg = acornfb_setcolreg,
868 .fb_pan_display = acornfb_pan_display,
879 NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2,
883 NULL, 50, 640, 250, 62500, 185, 123, 38, 21, 76, 3,
887 NULL, 50, 640, 256, 62500, 185, 123, 35, 18, 76, 3,
891 NULL, 50, 640, 512, 41667, 113, 87, 18, 1, 56, 3,
895 NULL, 70, 640, 250, 39722, 48, 16, 109, 88, 96, 2,
899 NULL, 70, 640, 256, 39722, 48, 16, 106, 85, 96, 2,
903 NULL, 70, 640, 352, 39722, 48, 16, 58, 37, 96, 2,
907 NULL, 60, 640, 480, 39722, 48, 16, 32, 11, 96, 2,
911 NULL, 56, 800, 600, 27778, 101, 23, 22, 1, 100, 2,
915 NULL, 60, 896, 352, 41667, 59, 27, 9, 0, 118, 3,
919 NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
923 NULL, 60, 1280, 1024, 9090, 186, 96, 38, 1, 160, 3,
929 static struct fb_videomode acornfb_default_mode __devinitdata = {
945 static void __devinit acornfb_init_fbinfo(
void)
947 static int first = 1;
971 #if defined(HAS_VIDC20)
974 #elif defined(HAS_VIDC)
987 current_par.dram_size = 0;
988 current_par.montype = -1;
989 current_par.dpms = 0;
1025 current_par.montype = -2;
1065 current_par.montype = -1;
1068 static void __devinit acornfb_parse_montype(
char *opt)
1070 current_par.montype = -2;
1072 if (
strncmp(opt,
"tv", 2) == 0) {
1074 current_par.montype = 0;
1075 }
else if (
strncmp(opt,
"multi", 5) == 0) {
1077 current_par.montype = 1;
1078 }
else if (
strncmp(opt,
"hires", 5) == 0) {
1080 current_par.montype = 2;
1081 }
else if (
strncmp(opt,
"vga", 3) == 0) {
1083 current_par.montype = 3;
1084 }
else if (
strncmp(opt,
"svga", 4) == 0) {
1086 current_par.montype = 4;
1087 }
else if (
strncmp(opt,
"auto", 4) == 0) {
1089 current_par.montype = -1;
1093 if (current_par.montype == -2 ||
1097 current_par.montype = -1;
1100 if (
strcmp(opt,
",dpms") == 0)
1101 current_par.dpms = 1;
1104 "acornfb: unknown monitor option: %s\n",
1109 static void __devinit acornfb_parse_dram(
char *opt)
1128 current_par.dram_size =
size;
1134 } opt_table[] __devinitdata = {
1135 {
"mon", acornfb_parse_mon },
1136 {
"montype", acornfb_parse_montype },
1137 {
"dram", acornfb_parse_dram },
1143 struct options *optp;
1146 if (!options || !*options)
1149 acornfb_init_fbinfo();
1151 while ((opt =
strsep(&options,
",")) !=
NULL) {
1155 for (optp = opt_table; optp->name; optp++) {
1158 optlen =
strlen(optp->name);
1160 if (
strncmp(opt, optp->name, optlen) == 0 &&
1161 opt[optlen] ==
':') {
1162 optp->parse(opt + optlen + 1);
1178 static int __devinit acornfb_detect_monitortype(
void)
1189 free_unused_pages(
unsigned int virtual_start,
unsigned int virtual_end)
1199 while (virtual_start < virtual_end) {
1208 ClearPageReserved(page);
1209 init_page_count(page);
1216 printk(
"acornfb: freed %dK memory\n", mb_freed);
1222 u_int h_sync, v_sync;
1228 acornfb_setup(option);
1230 acornfb_init_fbinfo();
1232 current_par.dev = &dev->
dev;
1234 if (current_par.montype == -1)
1235 current_par.montype = acornfb_detect_monitortype();
1237 if (current_par.montype == -1 || current_par.montype >
NR_MONTYPES)
1238 current_par.montype = 4;
1240 if (current_par.montype >= 0) {
1251 hs = modedb[
i].refresh *
1252 (modedb[
i].yres + modedb[
i].upper_margin +
1253 modedb[
i].lower_margin + modedb[
i].vsync_len);
1260 acornfb_default_mode = modedb[
i];
1267 current_par.using_vram = 0;
1274 if (
vram_size && !current_par.dram_size) {
1276 current_par.vram_half_sam =
vram_size / 1024;
1277 current_par.using_vram = 1;
1278 }
else if (current_par.dram_size)
1279 size = current_par.dram_size;
1291 #if defined(HAS_VIDC20)
1292 if (!current_par.using_vram) {
1313 #if defined(HAS_VIDC)
1322 current_par.palette_size = VIDC_PALETTE_SIZE;
1362 printk(
"Acornfb: no valid mode found\n");
1373 "%d.%03dkHz, %dHz\n",
1375 current_par.using_vram ?
'V' :
'D',
1377 h_sync / 1000, h_sync % 1000, v_sync);
1394 .probe = acornfb_probe,
1400 static int __init acornfb_init(
void)