/*
 *  linux/drivers/video/vsfb.c
 *
 *  Copyright (C) 2003 Ian Molton
 *
 * Based on acornfb by 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 Simple platforms
 *
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/ioport.h>

#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>

#undef FBCON_HAS_CFB8
#undef FBCON_HAS_CFB2
#undef FBCON_HAS_CFB4
#undef FBCON_HAS_CFB32

#define DEFAULT_XRES	480
#define DEFAULT_YRES	640
#define DEFAULT_BPP	16
//#define SCREEN_BASE	(0x0c100000 + ( 69*480 + 160))
#define SCREEN_BASE	(0x08800000)
#define SCREEN_SIZE	(2*DEFAULT_XRES*DEFAULT_YRES)

static struct fb_info fb_info;
static u32 colreg[17]; // Copied from other driver - but is 17 correct?


static int
vsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
		  u_int trans, struct fb_info *info)
{
        if (regno > 16)
                return 1;
        
        ((u32 *)(info->pseudo_palette))[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);

	return 0;
}

static struct fb_ops vsfb_ops = {
	.owner		= THIS_MODULE,
	.fb_setcolreg	= vsfb_setcolreg,
	.fb_fillrect	= cfb_fillrect,
	.fb_copyarea	= cfb_copyarea,
	.fb_imageblit	= cfb_imageblit,
	.fb_cursor	= soft_cursor,
};

static struct fb_var_screeninfo vsfb_var = {
        .xres           = DEFAULT_XRES,
        .yres           = DEFAULT_YRES,
        .xres_virtual   = DEFAULT_XRES,
        .yres_virtual   = DEFAULT_YRES,
        .bits_per_pixel = DEFAULT_BPP,
        .red            = { 11, 5, 0 },
        .green          = {  5, 6, 0 },
        .blue           = {  0, 5, 0 },
        .activate       = FB_ACTIVATE_NOW,
        .height         = -1,
        .width          = -1,
        .vmode          = FB_VMODE_DOUBLE,
};

static struct fb_fix_screeninfo vsfb_fix = {
        .id             = "VSFB",
        .smem_start     = SCREEN_BASE,
        .smem_len       = SCREEN_SIZE,
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_TRUECOLOR,
        .line_length    = DEFAULT_XRES*2,        // For gods sake fix this
        .accel          = FB_ACCEL_NONE,
};

// extern int ian_init_done;

int __init vsfb_init(void) {
	int i;

	printk( KERN_NOTICE "vsfb: starting...\n" );

        fb_info.fix = vsfb_fix;
        fb_info.var = vsfb_var;

        fb_info.fbops           = &vsfb_ops;
        fb_info.flags           = FBINFO_DEFAULT;
        // fb_info.currcon         = -1;
        fb_info.pseudo_palette  = colreg;
        fb_alloc_cmap(&fb_info.cmap, 16, 0);
                                                                                 
	/* Try to grab our phys memory space... */
	if (!(request_mem_region(fb_info.fix.smem_start, fb_info.fix.smem_len, "vsfb"))){
                return -ENOMEM;
	}

	/* Try to map this so we can access it */
	fb_info.screen_base    = ioremap(fb_info.fix.smem_start, fb_info.fix.smem_len);
	if (!fb_info.screen_base) {
		release_mem_region(fb_info.fix.smem_start, fb_info.fix.smem_len);
		return -EIO;
	}

	//fb_info.screen_base = (0xf0000000 + ( 69*480 + 160));
	for(i = 0 ; i < 480*640; i++)
		(unsigned short *)(fb_info.screen_base)[i] = 0x8080;

	printk(KERN_INFO "vsfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", fb_info.fix.smem_start, fb_info.screen_base, fb_info.fix.smem_len/1024);

	if (register_framebuffer(&fb_info) < 0){
		iounmap(fb_info.screen_base);
		release_mem_region(fb_info.fix.smem_start, fb_info.fix.smem_len);

		return -EINVAL;
	}
// ian_init_done = 0;

	return 0;
}

module_init( vsfb_init );

MODULE_AUTHOR("Ian Molton (based on acornfb by RMK and parts of anakinfb)");
MODULE_DESCRIPTION("Very Simple framebuffer driver");
MODULE_LICENSE("GPL");

