11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/video/q40fb.c -- Q40 frame buffer device 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Richard Zidlicky <rz@linux-m68k.org> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file COPYING in the main directory of this archive for 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * more details. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 19d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/q40_master.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Q40_PHYS_SCREEN_ADDR 0xFE800000 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3048c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_fix_screeninfo q40fb_fix = { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id = "Q40", 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .smem_len = 1024*1024, 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .type = FB_TYPE_PACKED_PIXELS, 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .visual = FB_VISUAL_TRUECOLOR, 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .line_length = 1024*2, 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accel = FB_ACCEL_NONE, 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3948c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_var_screeninfo q40fb_var = { 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 1024, 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres = 512, 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres_virtual = 1024, 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres_virtual = 512, 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bits_per_pixel = 16, 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .red = {6, 5, 0}, 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green = {11, 5, 0}, 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .blue = {0, 6, 0}, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .activate = FB_ACTIVATE_NOW, 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .height = 230, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .width = 300, 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vmode = FB_VMODE_NONINTERLACED, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green, 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned blue, unsigned transp, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_info *info) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set a single color register. The values supplied have a 16 bit 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * magnitude. 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return != 0 for invalid regno. 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regno > 255) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds red>>=11; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds green>>=11; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blue>>=10; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regno < 16) { 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((u32 *)info->pseudo_palette)[regno] = ((red & 31) <<6) | 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((green & 31) << 11) | 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (blue & 63); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_ops q40fb_ops = { 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_setcolreg = q40fb_setcolreg, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_fillrect = cfb_fillrect, 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_copyarea = cfb_copyarea, 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_imageblit = cfb_imageblit, 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8648c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int q40fb_probe(struct platform_device *dev) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_info *info; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MACH_IS_Q40) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mapped in q40/config.c */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 96ce303c076baad1b7d8d41d1b98c373843eb820ccAntonino A. Daplas info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!info) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->var = q40fb_var; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->fix = q40fb_fix; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->fbops = &q40fb_ops; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->flags = FBINFO_DEFAULT; /* not as module for now */ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->pseudo_palette = info->par; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->par = NULL; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->screen_base = (char *) q40fb_fix.smem_start; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framebuffer_release(info); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds master_outb(3, DISPLAY_CONTROL_REG); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (register_framebuffer(info) < 0) { 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Unable to register Q40 frame buffer\n"); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fb_dealloc_cmap(&info->cmap); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framebuffer_release(info); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12231b6780c15a4e3a90fe260e977f5186772ce7afbJoe Perches fb_info(info, "Q40 frame buffer alive and kicking !\n"); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1263ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver q40fb_driver = { 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = q40fb_probe, 1283ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 1293ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = "q40fb", 1303ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct platform_device q40fb_device = { 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "q40fb", 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init q40fb_init(void) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fb_get_options("q40fb", NULL)) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1443ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King ret = platform_driver_register(&q40fb_driver); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = platform_device_register(&q40fb_device); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 1493ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_unregister(&q40fb_driver); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(q40fb_init); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 156