Lines Matching +full:int +full:- +full:clock +full:- +full:stable +full:- +full:broken
1 // SPDX-License-Identifier: GPL-2.0-only
9 * Copyright (c) 2001 - 2008 Paul Mundt <lethal@linux-sh.org>
13 * here are some hacked-up formulas:
19 * values, I could just add mode- specific offsets to get the correct mode
22 * left_margin = diwstart_h - borderstart_h;
23 * right_margin = borderstop_h - (diwstart_h + xres);
24 * upper_margin = diwstart_v - borderstart_v;
25 * lower_margin = borderstop_v - (diwstart_h + yres);
27 * hsync_len = borderstart_h + (hsync_total - borderstop_h);
28 * vsync_len = borderstart_v + (vsync_total - borderstop_v);
38 * borderstop_h = borderstart_h + hsync_total - hsync_len;
40 * diwstart_v = borderstart_v - upper_margin;
43 * the benefit of being fully researched, so some modes may be broken.
63 #include <mach-dreamcast/mach/sysasic.h>
82 #define DISP_BASE par->mmio_base
101 /* This is for 60Hz - the VTOTAL is doubled for interlaced modes */
116 struct pvr2_params { unsigned int val; char *name; };
130 unsigned int hsync_total; /* Clocks/line */
131 unsigned int vsync_total; /* Lines/field */
132 unsigned int borderstart_h;
133 unsigned int borderstop_h;
134 unsigned int borderstart_v;
135 unsigned int borderstop_v;
136 unsigned int diwstart_h; /* Horizontal offset of the display field */
137 unsigned int diwstart_v; /* Vertical offset of the display field, for
142 unsigned char is_lowres; /* Is horizontal pixel-doubling enabled? */
169 .height = -1,
170 .width = -1,
174 static int cable_type = CT_VGA;
175 static int video_output = VO_VGA;
177 static int nopan = 0;
178 static int nowrap = 1;
183 static unsigned int do_vmode_full = 0; /* Change the video mode */
184 static unsigned int do_vmode_pan = 0; /* Update the video mode */
187 static unsigned int is_blanked = 0; /* Is the screen blanked? */
194 static unsigned int shdma = PVR2_CASCADE_CHAN;
195 static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
201 * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
211 /* XXX: Broken! Don't use... */
227 static int defmode = DEFMODE_NTSC;
230 static inline void pvr2fb_set_pal_type(unsigned int type) in pvr2fb_set_pal_type()
232 struct pvr2fb_par *par = (struct pvr2fb_par *)fb_info->par; in pvr2fb_set_pal_type()
234 fb_writel(type, par->mmio_base + 0x108); in pvr2fb_set_pal_type()
238 unsigned int regno, in pvr2fb_set_pal_entry()
239 unsigned int val) in pvr2fb_set_pal_entry()
241 fb_writel(val, par->mmio_base + 0x1000 + (4 * regno)); in pvr2fb_set_pal_entry()
244 static int pvr2fb_blank(int blank, struct fb_info *info) in pvr2fb_blank()
246 do_blank = blank ? blank : -1; in pvr2fb_blank()
250 static inline unsigned long get_line_length(int xres_virtual, int bpp) in get_line_length()
257 switch (var->bits_per_pixel) { in set_color_bitfields()
260 var->red.offset = 11; var->red.length = 5; in set_color_bitfields()
261 var->green.offset = 5; var->green.length = 6; in set_color_bitfields()
262 var->blue.offset = 0; var->blue.length = 5; in set_color_bitfields()
263 var->transp.offset = 0; var->transp.length = 0; in set_color_bitfields()
266 var->red.offset = 16; var->red.length = 8; in set_color_bitfields()
267 var->green.offset = 8; var->green.length = 8; in set_color_bitfields()
268 var->blue.offset = 0; var->blue.length = 8; in set_color_bitfields()
269 var->transp.offset = 0; var->transp.length = 0; in set_color_bitfields()
273 var->red.offset = 16; var->red.length = 8; in set_color_bitfields()
274 var->green.offset = 8; var->green.length = 8; in set_color_bitfields()
275 var->blue.offset = 0; var->blue.length = 8; in set_color_bitfields()
276 var->transp.offset = 24; var->transp.length = 8; in set_color_bitfields()
281 static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, in pvr2fb_setcolreg()
282 unsigned int green, unsigned int blue, in pvr2fb_setcolreg()
283 unsigned int transp, struct fb_info *info) in pvr2fb_setcolreg()
285 struct pvr2fb_par *par = (struct pvr2fb_par *)info->par; in pvr2fb_setcolreg()
286 unsigned int tmp; in pvr2fb_setcolreg()
288 if (regno > info->cmap.len) in pvr2fb_setcolreg()
296 switch (info->var.bits_per_pixel) { in pvr2fb_setcolreg()
315 pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel); in pvr2fb_setcolreg()
320 ((u32*)(info->pseudo_palette))[regno] = tmp; in pvr2fb_setcolreg()
334 static int pvr2_init_cable(void) in pvr2_init_cable()
355 static int pvr2fb_set_par(struct fb_info *info) in pvr2fb_set_par()
357 struct pvr2fb_par *par = (struct pvr2fb_par *)info->par; in pvr2fb_set_par()
358 struct fb_var_screeninfo *var = &info->var; in pvr2fb_set_par()
360 unsigned int vtotal; in pvr2fb_set_par()
364 * type in hardware (i.e. switch from VGA<->composite), then change in pvr2fb_set_par()
373 var->vmode &= FB_VMODE_MASK; in pvr2fb_set_par()
374 if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA) in pvr2fb_set_par()
375 par->is_interlaced = 1; in pvr2fb_set_par()
380 if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA) in pvr2fb_set_par()
381 par->is_doublescan = 1; in pvr2fb_set_par()
383 par->hsync_total = var->left_margin + var->xres + var->right_margin + in pvr2fb_set_par()
384 var->hsync_len; in pvr2fb_set_par()
385 par->vsync_total = var->upper_margin + var->yres + var->lower_margin + in pvr2fb_set_par()
386 var->vsync_len; in pvr2fb_set_par()
388 if (var->sync & FB_SYNC_BROADCAST) { in pvr2fb_set_par()
389 vtotal = par->vsync_total; in pvr2fb_set_par()
390 if (par->is_interlaced) in pvr2fb_set_par()
394 /* XXX: Check hardware for PAL-compatibility */ in pvr2fb_set_par()
395 par->borderstart_h = 116; in pvr2fb_set_par()
396 par->borderstart_v = 44; in pvr2fb_set_par()
399 par->borderstart_h = 126; in pvr2fb_set_par()
400 par->borderstart_v = 18; in pvr2fb_set_par()
409 par->borderstart_h = 126; in pvr2fb_set_par()
410 par->borderstart_v = 40; in pvr2fb_set_par()
414 par->diwstart_h = par->borderstart_h + var->left_margin; in pvr2fb_set_par()
415 par->diwstart_v = par->borderstart_v + var->upper_margin; in pvr2fb_set_par()
416 par->borderstop_h = par->diwstart_h + var->xres + in pvr2fb_set_par()
417 var->right_margin; in pvr2fb_set_par()
418 par->borderstop_v = par->diwstart_v + var->yres + in pvr2fb_set_par()
419 var->lower_margin; in pvr2fb_set_par()
421 if (!par->is_interlaced) in pvr2fb_set_par()
422 par->borderstop_v /= 2; in pvr2fb_set_par()
423 if (info->var.xres < 640) in pvr2fb_set_par()
424 par->is_lowres = 1; in pvr2fb_set_par()
426 line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); in pvr2fb_set_par()
427 par->disp_start = info->fix.smem_start + (line_length * var->yoffset) * line_length; in pvr2fb_set_par()
428 info->fix.line_length = line_length; in pvr2fb_set_par()
432 static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) in pvr2fb_check_var()
434 struct pvr2fb_par *par = (struct pvr2fb_par *)info->par; in pvr2fb_check_var()
435 unsigned int vtotal, hsync_total; in pvr2fb_check_var()
438 if (var->pixclock != TV_CLK && var->pixclock != VGA_CLK) { in pvr2fb_check_var()
439 pr_debug("Invalid pixclock value %d\n", var->pixclock); in pvr2fb_check_var()
440 return -EINVAL; in pvr2fb_check_var()
443 if (var->xres < 320) in pvr2fb_check_var()
444 var->xres = 320; in pvr2fb_check_var()
445 if (var->yres < 240) in pvr2fb_check_var()
446 var->yres = 240; in pvr2fb_check_var()
447 if (var->xres_virtual < var->xres) in pvr2fb_check_var()
448 var->xres_virtual = var->xres; in pvr2fb_check_var()
449 if (var->yres_virtual < var->yres) in pvr2fb_check_var()
450 var->yres_virtual = var->yres; in pvr2fb_check_var()
452 if (var->bits_per_pixel <= 16) in pvr2fb_check_var()
453 var->bits_per_pixel = 16; in pvr2fb_check_var()
454 else if (var->bits_per_pixel <= 24) in pvr2fb_check_var()
455 var->bits_per_pixel = 24; in pvr2fb_check_var()
456 else if (var->bits_per_pixel <= 32) in pvr2fb_check_var()
457 var->bits_per_pixel = 32; in pvr2fb_check_var()
461 if (var->vmode & FB_VMODE_YWRAP) { in pvr2fb_check_var()
462 if (var->xoffset || var->yoffset >= var->yres_virtual) { in pvr2fb_check_var()
463 var->xoffset = var->yoffset = 0; in pvr2fb_check_var()
465 if (var->xoffset > var->xres_virtual - var->xres || in pvr2fb_check_var()
466 var->yoffset > var->yres_virtual - var->yres) in pvr2fb_check_var()
467 var->xoffset = var->yoffset = 0; in pvr2fb_check_var()
470 var->xoffset = var->yoffset = 0; in pvr2fb_check_var()
477 if (var->yres < 480 && video_output == VO_VGA) in pvr2fb_check_var()
478 var->vmode |= FB_VMODE_DOUBLE; in pvr2fb_check_var()
481 var->sync |= FB_SYNC_BROADCAST; in pvr2fb_check_var()
482 var->vmode |= FB_VMODE_INTERLACED; in pvr2fb_check_var()
484 var->sync &= ~FB_SYNC_BROADCAST; in pvr2fb_check_var()
485 var->vmode &= ~FB_VMODE_INTERLACED; in pvr2fb_check_var()
486 var->vmode |= FB_VMODE_NONINTERLACED; in pvr2fb_check_var()
489 if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_TEST) { in pvr2fb_check_var()
490 var->right_margin = par->borderstop_h - in pvr2fb_check_var()
491 (par->diwstart_h + var->xres); in pvr2fb_check_var()
492 var->left_margin = par->diwstart_h - par->borderstart_h; in pvr2fb_check_var()
493 var->hsync_len = par->borderstart_h + in pvr2fb_check_var()
494 (par->hsync_total - par->borderstop_h); in pvr2fb_check_var()
496 var->upper_margin = par->diwstart_v - par->borderstart_v; in pvr2fb_check_var()
497 var->lower_margin = par->borderstop_v - in pvr2fb_check_var()
498 (par->diwstart_v + var->yres); in pvr2fb_check_var()
499 var->vsync_len = par->borderstop_v + in pvr2fb_check_var()
500 (par->vsync_total - par->borderstop_v); in pvr2fb_check_var()
503 hsync_total = var->left_margin + var->xres + var->right_margin + in pvr2fb_check_var()
504 var->hsync_len; in pvr2fb_check_var()
505 vtotal = var->upper_margin + var->yres + var->lower_margin + in pvr2fb_check_var()
506 var->vsync_len; in pvr2fb_check_var()
508 if (var->sync & FB_SYNC_BROADCAST) { in pvr2fb_check_var()
509 if (var->vmode & FB_VMODE_INTERLACED) in pvr2fb_check_var()
516 return -EINVAL; in pvr2fb_check_var()
522 return -EINVAL; in pvr2fb_check_var()
528 line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); in pvr2fb_check_var()
529 if (line_length * var->yres_virtual > info->fix.smem_len) in pvr2fb_check_var()
530 return -ENOMEM; in pvr2fb_check_var()
537 struct pvr2fb_par *par = (struct pvr2fb_par *) info->par; in pvr2_update_display()
538 struct fb_var_screeninfo *var = &info->var; in pvr2_update_display()
541 fb_writel(par->disp_start, DISP_DIWADDRL); in pvr2_update_display()
542 fb_writel(par->disp_start + in pvr2_update_display()
543 get_line_length(var->xoffset+var->xres, var->bits_per_pixel), in pvr2_update_display()
549 * very stable. It's probably due to the fact that a lot of the 2D video
555 struct pvr2fb_par *par = (struct pvr2fb_par *) info->par; in pvr2_init_display()
556 struct fb_var_screeninfo *var = &info->var; in pvr2_init_display()
557 unsigned int diw_height, diw_width, diw_modulo = 1; in pvr2_init_display()
558 unsigned int bytesperpixel = var->bits_per_pixel >> 3; in pvr2_init_display()
561 fb_writel((par->vsync_total << 16) | par->hsync_total, DISP_SYNCSIZE); in pvr2_init_display()
566 if (video_output != VO_VGA && par->is_interlaced) in pvr2_init_display()
567 diw_modulo += info->fix.line_length / 4; in pvr2_init_display()
568 diw_height = (par->is_interlaced ? var->yres / 2 : var->yres); in pvr2_init_display()
569 diw_width = get_line_length(var->xres, var->bits_per_pixel) / 4; in pvr2_init_display()
570 fb_writel((diw_modulo << 20) | (--diw_height << 10) | --diw_width, in pvr2_init_display()
574 fb_writel(par->disp_start, DISP_DIWADDRL); in pvr2_init_display()
575 fb_writel(par->disp_start + in pvr2_init_display()
576 get_line_length(var->xoffset+var->xres, var->bits_per_pixel), in pvr2_init_display()
580 fb_writel((par->borderstart_h << 16) | par->borderstop_h, DISP_BRDRHORZ); in pvr2_init_display()
581 fb_writel((par->borderstart_v << 16) | par->borderstop_v, DISP_BRDRVERT); in pvr2_init_display()
585 fb_writel(par->diwstart_h, DISP_DIWHSTRT); in pvr2_init_display()
586 fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT); in pvr2_init_display()
589 fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF); in pvr2_init_display()
591 /* clock doubler (for VGA), scan doubler, display enable */ in pvr2_init_display()
593 (par->is_doublescan << 1) | 1, DISP_DIWMODE); in pvr2_init_display()
596 fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE); in pvr2_init_display()
601 fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF); in pvr2_init_display()
622 static irqreturn_t __maybe_unused pvr2fb_interrupt(int irq, void *dev_id) in pvr2fb_interrupt()
646 unsigned int nr_pages; in pvr2fb_write()
648 int ret, i; in pvr2fb_write()
650 if (!info->screen_base) in pvr2fb_write()
651 return -ENODEV; in pvr2fb_write()
653 nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT; in pvr2fb_write()
657 return -ENOMEM; in pvr2fb_write()
665 * -errno value was returned from GUP. in pvr2fb_write()
671 * Use -EINVAL to represent a mildly desperate guess at in pvr2fb_write()
675 ret = -EINVAL; in pvr2fb_write()
682 dst = (unsigned long)fb_info->screen_base + *ppos; in pvr2fb_write()
687 /* Half-assed contig check */ in pvr2fb_write()
690 if ((*ppos + len) > fb_info->fix.smem_len) { in pvr2fb_write()
691 ret = -ENOSPC; in pvr2fb_write()
702 /* Not contiguous, writeout per-page instead.. */ in pvr2fb_write()
704 if ((*ppos + (i << PAGE_SHIFT)) > fb_info->fix.smem_len) { in pvr2fb_write()
705 ret = -ENOSPC; in pvr2fb_write()
743 static int pvr2_get_param_val(const struct pvr2_params *p, const char *s, in pvr2_get_param_val()
744 int size) in pvr2_get_param_val()
746 int i; in pvr2_get_param_val()
752 return -1; in pvr2_get_param_val()
756 static char *pvr2_get_param_name(const struct pvr2_params *p, int val, in pvr2_get_param_name()
757 int size) in pvr2_get_param_name()
759 int i; in pvr2_get_param_name()
774 * registration. It's expected that the board-specific init code has
778 * default from the modedb. For board-specific modelines, simply define
779 * a per-board modedb.
782 * always going to be VGA for the PCI-based PVR2 boards, but we leave this
783 * in for flexibility anyways. Who knows, maybe someone has tv-out on a
784 * PCI-based version of these things ;-)
786 static int __maybe_unused pvr2fb_common_init(void) in pvr2fb_common_init()
791 fb_info->screen_base = ioremap(pvr2_fix.smem_start, in pvr2fb_common_init()
794 if (!fb_info->screen_base) { in pvr2fb_common_init()
799 par->mmio_base = ioremap(pvr2_fix.mmio_start, in pvr2fb_common_init()
801 if (!par->mmio_base) { in pvr2fb_common_init()
806 fb_memset_io(fb_info->screen_base, 0, pvr2_fix.smem_len); in pvr2fb_common_init()
811 fb_info->fbops = &pvr2fb_ops; in pvr2fb_common_init()
812 fb_info->fix = pvr2_fix; in pvr2fb_common_init()
813 fb_info->par = currentpar; in pvr2fb_common_init()
814 fb_info->pseudo_palette = currentpar->palette; in pvr2fb_common_init()
815 fb_info->flags = FBINFO_HWACCEL_YPAN; in pvr2fb_common_init()
823 if (!fb_find_mode(&fb_info->var, fb_info, mode_option, pvr2_modedb, in pvr2fb_common_init()
825 fb_info->var = pvr2_var; in pvr2fb_common_init()
827 fb_alloc_cmap(&fb_info->cmap, 256, 0); in pvr2fb_common_init()
831 /*Must write PIXDEPTH to register before anything is displayed - so force init */ in pvr2fb_common_init()
834 modememused = get_line_length(fb_info->var.xres_virtual, in pvr2fb_common_init()
835 fb_info->var.bits_per_pixel); in pvr2fb_common_init()
836 modememused *= fb_info->var.yres_virtual; in pvr2fb_common_init()
838 rev = fb_readl(par->mmio_base + 0x04); in pvr2fb_common_init()
841 fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f, in pvr2fb_common_init()
843 (unsigned long)(fb_info->fix.smem_len >> 10)); in pvr2fb_common_init()
844 fb_info(fb_info, "Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", in pvr2fb_common_init()
845 fb_info->var.xres, fb_info->var.yres, in pvr2fb_common_init()
846 fb_info->var.bits_per_pixel, in pvr2fb_common_init()
847 get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), in pvr2fb_common_init()
854 pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len, in pvr2fb_common_init()
855 fb_info->fix.id, PAGE_SHARED); in pvr2fb_common_init()
864 if (fb_info->screen_base) in pvr2fb_common_init()
865 iounmap(fb_info->screen_base); in pvr2fb_common_init()
866 if (par->mmio_base) in pvr2fb_common_init()
867 iounmap(par->mmio_base); in pvr2fb_common_init()
869 return -ENXIO; in pvr2fb_common_init()
873 static int __init pvr2fb_dc_init(void) in pvr2fb_dc_init()
876 return -ENXIO; in pvr2fb_dc_init()
880 fb_info->monspecs.hfmin = 30000; in pvr2fb_dc_init()
881 fb_info->monspecs.hfmax = 70000; in pvr2fb_dc_init()
882 fb_info->monspecs.vfmin = 60; in pvr2fb_dc_init()
883 fb_info->monspecs.vfmax = 60; in pvr2fb_dc_init()
886 fb_info->monspecs.hfmin = 15469; in pvr2fb_dc_init()
887 fb_info->monspecs.hfmax = 15781; in pvr2fb_dc_init()
888 fb_info->monspecs.vfmin = 49; in pvr2fb_dc_init()
889 fb_info->monspecs.vfmax = 51; in pvr2fb_dc_init()
914 return -EBUSY; in pvr2fb_dc_init()
920 return -EBUSY; in pvr2fb_dc_init()
929 if (fb_info->screen_base) { in pvr2fb_dc_exit()
930 iounmap(fb_info->screen_base); in pvr2fb_dc_exit()
931 fb_info->screen_base = NULL; in pvr2fb_dc_exit()
933 if (currentpar->mmio_base) { in pvr2fb_dc_exit()
934 iounmap(currentpar->mmio_base); in pvr2fb_dc_exit()
935 currentpar->mmio_base = NULL; in pvr2fb_dc_exit()
946 static int pvr2fb_pci_probe(struct pci_dev *pdev, in pvr2fb_pci_probe()
949 int ret; in pvr2fb_pci_probe()
976 fb_info->device = &pdev->dev; in pvr2fb_pci_probe()
983 if (fb_info->screen_base) { in pvr2fb_pci_remove()
984 iounmap(fb_info->screen_base); in pvr2fb_pci_remove()
985 fb_info->screen_base = NULL; in pvr2fb_pci_remove()
987 if (currentpar->mmio_base) { in pvr2fb_pci_remove()
988 iounmap(currentpar->mmio_base); in pvr2fb_pci_remove()
989 currentpar->mmio_base = NULL; in pvr2fb_pci_remove()
1010 static int __init pvr2fb_pci_init(void) in pvr2fb_pci_init()
1027 * <xres>x<yres>[-<bpp>][@<refresh>] or,
1028 * <name>[-<bpp>][@<refresh>] Startup using this video mode
1032 static int __init pvr2fb_setup(char *options) in pvr2fb_setup()
1071 int (*init)(void);
1084 static int __init pvr2fb_init(void) in pvr2fb_init()
1086 int i, ret = -ENODEV; in pvr2fb_init()
1093 return -ENODEV; in pvr2fb_init()
1097 return -ENODEV; in pvr2fb_init()
1103 return -ENOMEM; in pvr2fb_init()
1105 currentpar = fb_info->par; in pvr2fb_init()
1110 if (!pvr_board->init) in pvr2fb_init()
1113 ret = pvr_board->init(); in pvr2fb_init()
1117 pvr_board->name); in pvr2fb_init()
1128 int i; in pvr2fb_exit()
1133 if (pvr_board->exit) in pvr2fb_exit()
1134 pvr_board->exit(); in pvr2fb_exit()
1148 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");