// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/video/acornfb.c * * Copyright (C) 1998-2001 Russell King * * Frame buffer code for Acorn platforms * * NOTE: Most of the modes with X!=640 will disappear shortly. * NOTE: Startup setting of HS & VS polarity not supported. * (do we need to support it if we're coming up in 640x480?) * * FIXME: (things broken by the "new improved" FBCON API) * - Blanking 8bpp displays with VIDC
*/
/* * Default resolution. * NOTE that it has to be supported in the table towards * the end of this file.
*/ #define DEFAULT_XRES 640 #define DEFAULT_YRES 480 #define DEFAULT_BPP 4
/* * define this to debug the video mode selection
*/ #undef DEBUG_MODE_SELECTION
/* * Translation from RISC OS monitor types to actual * HSYNC and VSYNC frequency ranges. These are * probably not right, but they're the best info I * have. Allow 1% either way on the nominal for TVs.
*/ #define NR_MONTYPES 6 staticstruct fb_monspecs monspecs[NR_MONTYPES] = {
{ /* TV */
.hfmin = 15469,
.hfmax = 15781,
.vfmin = 49,
.vfmax = 51,
}, { /* Multi Freq */
.hfmin = 0,
.hfmax = 99999,
.vfmin = 0,
.vfmax = 199,
}, { /* Hi-res mono */
.hfmin = 58608,
.hfmax = 58608,
.vfmin = 64,
.vfmax = 64,
}, { /* VGA */
.hfmin = 30000,
.hfmax = 70000,
.vfmin = 60,
.vfmax = 60,
}, { /* SVGA */
.hfmin = 30000,
.hfmax = 70000,
.vfmin = 56,
.vfmax = 75,
}, {
.hfmin = 30000,
.hfmax = 70000,
.vfmin = 60,
.vfmax = 60,
}
};
/* VIDC20 has a different set of rules from the VIDC: * hcr : must be multiple of 4 * hswr : must be even * hdsr : must be even * hder : must be even * vcr : >= 2, (interlace, must be odd) * vswr : >= 1 * vdsr : >= 1 * vder : >= vdsr
*/ staticvoid acornfb_set_timing(struct fb_info *info)
{ struct fb_var_screeninfo *var = &info->var; struct vidc_timing vidc;
u_int vcr, fsize;
u_int ext_ctl, dat_ctl;
u_int words_per_line;
if (current_par.using_vram && info->fix.smem_len == 2048*1024)
words_per_line /= 2;
/* RiscPC doesn't use the VIDC's VRAM control. */
dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
/* The data bus width is dependent on both the type * and amount of video memory. * DRAM 32bit low * 1MB VRAM 32bit * 2MB VRAM 64bit
*/ if (current_par.using_vram && current_par.vram_half_sam == 2048)
dat_ctl |= VIDC20_DCTL_BUS_D63_0; else
dat_ctl |= VIDC20_DCTL_BUS_D31_0;
/* * We have to take note of the VIDC20's 16-bit palette here. * The VIDC20 looks up a 16 bit pixel as follows: * * bits 111111 * 5432109876543210 * red ++++++++ (8 bits, 7 to 0) * green ++++++++ (8 bits, 11 to 4) * blue ++++++++ (8 bits, 15 to 8) * * We use a pixel which looks like: * * bits 111111 * 5432109876543210 * red +++++ (5 bits, 4 to 0) * green +++++ (5 bits, 9 to 5) * blue +++++ (5 bits, 14 to 10)
*/ staticint
acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{ union palette pal;
/* * Now, find a value for yres_virtual which allows * us to do ywrap scrolling. The value of * yres_virtual must be such that the end of the * displayable frame buffer must be aligned with * the start of a font line.
*/
font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
min_size = var->xres * var->yres * var->bits_per_pixel / 8;
/* * If minimum screen size is greater than that we have * available, reject it.
*/ if (min_size > info->fix.smem_len) return -EINVAL;
/* Find int 'y', such that y * fll == s * sam < maxsize * y = s * sam / fll; s = maxsize / sam
*/ for (size = info->fix.smem_len;
nr_y = size / font_line_len, min_size <= size;
size -= sam_size) { if (nr_y * font_line_len == size) break;
}
nr_y *= fontht;
/* * hs(Hz) = 10^12 / (pixclock * xtotal) * vs(Hz) = hs(Hz) / ytotal * * No need to do long long divisions or anything * like that if you factor it correctly
*/
hs = 1953125000 / var->pixclock;
hs = hs * 512 /
(var->xres + var->left_margin + var->right_margin + var->hsync_len);
vs = hs /
(var->yres + var->upper_margin + var->lower_margin + var->vsync_len);
/* * Check to see if the pixel rate is valid.
*/ if (!acornfb_valid_pixrate(var)) return -EINVAL;
/* * Validate and adjust the resolution to * match the video generator hardware.
*/
err = acornfb_adjust_timing(info, var, fontht); if (err) return err;
/* * Validate the timing against the * monitor hardware.
*/ return acornfb_validate_timing(var, &info->monspecs);
}
/* * setup acornfb options: * * mon:hmin-hmax:vmin-vmax:dpms:width:height * Set monitor parameters: * hmin = horizontal minimum frequency (Hz) * hmax = horizontal maximum frequency (Hz) (optional) * vmin = vertical minimum frequency (Hz) * vmax = vertical maximum frequency (Hz) (optional) * dpms = DPMS supported? (optional) * width = width of picture in mm. (optional) * height = height of picture in mm. (optional) * * montype:type * Set RISC-OS style monitor type: * 0 (or tv) - TV frequency * 1 (or multi) - Multi frequency * 2 (or hires) - Hi-res monochrome * 3 (or vga) - VGA * 4 (or svga) - SVGA * auto, or option missing * - try hardware detect * * dram:size * Set the amount of DRAM to use for the frame buffer * (even if you have VRAM). * size can optionally be followed by 'M' or 'K' for * MB or KB respectively.
*/ staticvoid acornfb_parse_mon(char *opt)
{ char *p = opt;
/* * If vram_size is set, we are using VRAM in * a Risc PC. However, if the user has specified * an amount of DRAM then use that instead.
*/ if (vram_size && !current_par.dram_size) {
size = vram_size;
current_par.vram_half_sam = vram_size / 1024;
current_par.using_vram = 1;
} elseif (current_par.dram_size)
size = current_par.dram_size; else
size = MAX_SIZE;
/* * Limit maximum screen size.
*/ if (size > MAX_SIZE)
size = MAX_SIZE;
size = PAGE_ALIGN(size);
#ifdefined(HAS_VIDC20) if (!current_par.using_vram) {
dma_addr_t handle; void *base;
/* * RiscPC needs to allocate the DRAM memory * for the framebuffer if we are not using * VRAM.
*/
base = dma_alloc_wc(current_par.dev, size, &handle,
GFP_KERNEL); if (base == NULL) {
printk(KERN_ERR "acornfb: unable to allocate screen memory\n"); return -ENOMEM;
}
/* * Lookup the timing for this resolution. If we can't * find it, then we can't restore it if we change * the resolution, so we disable this feature.
*/ do {
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
ARRAY_SIZE(modedb),
&acornfb_default_mode, DEFAULT_BPP); /* * If we found an exact match, all ok.
*/ if (rc == 1) break;
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
&acornfb_default_mode, DEFAULT_BPP); /* * If we found an exact match, all ok.
*/ if (rc == 1) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.