/*
* linux/drivers/video/acornfb.c
*
* Copyright (C) 1998-2001 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/gfp.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/pgtable.h>
#include "acornfb.h"
/*
* 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
static struct 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,
}
};
static struct fb_info fb_info;
static struct acornfb_par current_par;
static struct vidc_timing current_vidc;
extern unsigned int vram_size; /* set by setup.c */
#ifdef HAS_VIDC20
#include <mach/acornfb.h>
#define MAX_SIZE 2*1024*1024
/* 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
*/
static void 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;
memset(&vidc, 0, sizeof(vidc));
vidc.h_sync_width = var->hsync_len - 8;
vidc.h_border_start = vidc.h_sync_width + var->left_margin + 8 - 12;
vidc.h_display_start = vidc.h_border_start + 12 - 18;
vidc.h_display_end = vidc.h_display_start + var->xres;
vidc.h_border_end = vidc.h_display_end + 18 - 12;
vidc.h_cycle = vidc.h_border_end + var->right_margin + 12 - 8;
vidc.h_interlace = vidc.h_cycle / 2;
vidc.v_sync_width = var->vsync_len - 1;
vidc.v_border_start = vidc.v_sync_width + var->upper_margin;
vidc.v_display_start