162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/drivers/video/q40fb.c -- Q40 frame buffer device 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2001 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Richard Zidlicky <rz@linux-m68k.org> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 962306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 1062306a36Sopenharmony_ci * more details. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/errno.h> 1562306a36Sopenharmony_ci#include <linux/string.h> 1662306a36Sopenharmony_ci#include <linux/mm.h> 1762306a36Sopenharmony_ci#include <linux/delay.h> 1862306a36Sopenharmony_ci#include <linux/interrupt.h> 1962306a36Sopenharmony_ci#include <linux/platform_device.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/uaccess.h> 2262306a36Sopenharmony_ci#include <asm/setup.h> 2362306a36Sopenharmony_ci#include <asm/q40_master.h> 2462306a36Sopenharmony_ci#include <linux/fb.h> 2562306a36Sopenharmony_ci#include <linux/module.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define Q40_PHYS_SCREEN_ADDR 0xFE800000 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic struct fb_fix_screeninfo q40fb_fix = { 3062306a36Sopenharmony_ci .id = "Q40", 3162306a36Sopenharmony_ci .smem_len = 1024*1024, 3262306a36Sopenharmony_ci .type = FB_TYPE_PACKED_PIXELS, 3362306a36Sopenharmony_ci .visual = FB_VISUAL_TRUECOLOR, 3462306a36Sopenharmony_ci .line_length = 1024*2, 3562306a36Sopenharmony_ci .accel = FB_ACCEL_NONE, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic const struct fb_var_screeninfo q40fb_var = { 3962306a36Sopenharmony_ci .xres = 1024, 4062306a36Sopenharmony_ci .yres = 512, 4162306a36Sopenharmony_ci .xres_virtual = 1024, 4262306a36Sopenharmony_ci .yres_virtual = 512, 4362306a36Sopenharmony_ci .bits_per_pixel = 16, 4462306a36Sopenharmony_ci .red = {6, 5, 0}, 4562306a36Sopenharmony_ci .green = {11, 5, 0}, 4662306a36Sopenharmony_ci .blue = {0, 6, 0}, 4762306a36Sopenharmony_ci .activate = FB_ACTIVATE_NOW, 4862306a36Sopenharmony_ci .height = 230, 4962306a36Sopenharmony_ci .width = 300, 5062306a36Sopenharmony_ci .vmode = FB_VMODE_NONINTERLACED, 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green, 5462306a36Sopenharmony_ci unsigned blue, unsigned transp, 5562306a36Sopenharmony_ci struct fb_info *info) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci /* 5862306a36Sopenharmony_ci * Set a single color register. The values supplied have a 16 bit 5962306a36Sopenharmony_ci * magnitude. 6062306a36Sopenharmony_ci * Return != 0 for invalid regno. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (regno > 255) 6462306a36Sopenharmony_ci return 1; 6562306a36Sopenharmony_ci red>>=11; 6662306a36Sopenharmony_ci green>>=11; 6762306a36Sopenharmony_ci blue>>=10; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (regno < 16) { 7062306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = ((red & 31) <<6) | 7162306a36Sopenharmony_ci ((green & 31) << 11) | 7262306a36Sopenharmony_ci (blue & 63); 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci return 0; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic const struct fb_ops q40fb_ops = { 7862306a36Sopenharmony_ci .owner = THIS_MODULE, 7962306a36Sopenharmony_ci FB_DEFAULT_IOMEM_OPS, 8062306a36Sopenharmony_ci .fb_setcolreg = q40fb_setcolreg, 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic int q40fb_probe(struct platform_device *dev) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct fb_info *info; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (!MACH_IS_Q40) 8862306a36Sopenharmony_ci return -ENXIO; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* mapped in q40/config.c */ 9162306a36Sopenharmony_ci q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); 9462306a36Sopenharmony_ci if (!info) 9562306a36Sopenharmony_ci return -ENOMEM; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci info->var = q40fb_var; 9862306a36Sopenharmony_ci info->fix = q40fb_fix; 9962306a36Sopenharmony_ci info->fbops = &q40fb_ops; 10062306a36Sopenharmony_ci info->pseudo_palette = info->par; 10162306a36Sopenharmony_ci info->par = NULL; 10262306a36Sopenharmony_ci info->screen_base = (char *) q40fb_fix.smem_start; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 10562306a36Sopenharmony_ci framebuffer_release(info); 10662306a36Sopenharmony_ci return -ENOMEM; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci master_outb(3, DISPLAY_CONTROL_REG); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (register_framebuffer(info) < 0) { 11262306a36Sopenharmony_ci printk(KERN_ERR "Unable to register Q40 frame buffer\n"); 11362306a36Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 11462306a36Sopenharmony_ci framebuffer_release(info); 11562306a36Sopenharmony_ci return -EINVAL; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci fb_info(info, "Q40 frame buffer alive and kicking !\n"); 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic struct platform_driver q40fb_driver = { 12362306a36Sopenharmony_ci .probe = q40fb_probe, 12462306a36Sopenharmony_ci .driver = { 12562306a36Sopenharmony_ci .name = "q40fb", 12662306a36Sopenharmony_ci }, 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic struct platform_device q40fb_device = { 13062306a36Sopenharmony_ci .name = "q40fb", 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int __init q40fb_init(void) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci int ret = 0; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (fb_get_options("q40fb", NULL)) 13862306a36Sopenharmony_ci return -ENODEV; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci ret = platform_driver_register(&q40fb_driver); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (!ret) { 14362306a36Sopenharmony_ci ret = platform_device_register(&q40fb_device); 14462306a36Sopenharmony_ci if (ret) 14562306a36Sopenharmony_ci platform_driver_unregister(&q40fb_driver); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci return ret; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cimodule_init(q40fb_init); 15162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 152