Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16-rc2 349 lines 8.4 kB view raw
1/* 2 * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device 3 * 4 * (C) 1999 Mihai Spatar 5 * (C) 2000 YAEGASHI Takeshi 6 * (C) 2003, 2004 Paul Mundt 7 * (C) 2003, 2004 Andriy Skulysh 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file COPYING in the main directory of this archive for 11 * more details. 12 */ 13 14#include <linux/config.h> 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/sched.h> 18#include <linux/errno.h> 19#include <linux/string.h> 20#include <linux/mm.h> 21#include <linux/tty.h> 22#include <linux/slab.h> 23#include <linux/delay.h> 24#include <linux/init.h> 25#include <linux/fb.h> 26 27#include <asm/machvec.h> 28#include <asm/uaccess.h> 29#include <asm/pgtable.h> 30#include <asm/io.h> 31#include <asm/hd64461/hd64461.h> 32 33#ifdef MACH_HP600 34#include <asm/cpu/dac.h> 35#include <asm/hp6xx/hp6xx.h> 36#endif 37 38#define WIDTH 640 39 40static struct fb_var_screeninfo hitfb_var __initdata = { 41 .activate = FB_ACTIVATE_NOW, 42 .height = -1, 43 .width = -1, 44 .vmode = FB_VMODE_NONINTERLACED, 45}; 46 47static struct fb_fix_screeninfo hitfb_fix __initdata = { 48 .id = "Hitachi HD64461", 49 .type = FB_TYPE_PACKED_PIXELS, 50 .ypanstep = 8, 51 .accel = FB_ACCEL_NONE, 52}; 53 54static u32 pseudo_palette[16]; 55static struct fb_info fb_info; 56 57static inline void hitfb_accel_wait(void) 58{ 59 while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ; 60} 61 62static inline void hitfb_accel_start(int truecolor) 63{ 64 if (truecolor) { 65 fb_writew(6, HD64461_GRCFGR); 66 } else { 67 fb_writew(7, HD64461_GRCFGR); 68 } 69} 70 71static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy, 72 u16 width, u16 height) 73{ 74 u32 saddr = WIDTH * dy + dx; 75 if (truecolor) 76 saddr <<= 1; 77 78 fb_writew(width, HD64461_BBTDWR); 79 fb_writew(height, HD64461_BBTDHR); 80 81 fb_writew(saddr & 0xffff, HD64461_BBTDSARL); 82 fb_writew(saddr >> 16, HD64461_BBTDSARH); 83 84} 85 86static inline void hitfb_accel_solidfill(int truecolor, u16 dx, u16 dy, 87 u16 width, u16 height, u16 color) 88{ 89 hitfb_accel_set_dest(truecolor, dx, dy, width, height); 90 91 fb_writew(0x00f0, HD64461_BBTROPR); 92 fb_writew(16, HD64461_BBTMDR); 93 fb_writew(color, HD64461_GRSCR); 94 95 hitfb_accel_start(truecolor); 96} 97 98static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx, 99 u16 dy, u16 width, u16 height, u16 rop, 100 u32 mask_addr) 101{ 102 u32 saddr, daddr; 103 u32 maddr = 0; 104 105 fb_writew(rop, HD64461_BBTROPR); 106 if ((sy < dy) || ((sy == dy) && (sx <= dx))) { 107 saddr = WIDTH * (sy + height) + sx + width; 108 daddr = WIDTH * (dy + height) + dx + width; 109 if (mask_addr) { 110 if (truecolor) 111 maddr = ((width >> 3) + 1) * (height + 1) - 1; 112 else 113 maddr = 114 (((width >> 4) + 1) * (height + 1) - 1) * 2; 115 116 fb_writew((1 << 5) | 1, HD64461_BBTMDR); 117 } else 118 fb_writew(1, HD64461_BBTMDR); 119 } else { 120 saddr = WIDTH * sy + sx; 121 daddr = WIDTH * dy + dx; 122 if (mask_addr) { 123 fb_writew((1 << 5), HD64461_BBTMDR); 124 } else { 125 fb_writew(0, HD64461_BBTMDR); 126 } 127 } 128 if (truecolor) { 129 saddr <<= 1; 130 daddr <<= 1; 131 } 132 fb_writew(width, HD64461_BBTDWR); 133 fb_writew(height, HD64461_BBTDHR); 134 fb_writew(saddr & 0xffff, HD64461_BBTSSARL); 135 fb_writew(saddr >> 16, HD64461_BBTSSARH); 136 fb_writew(daddr & 0xffff, HD64461_BBTDSARL); 137 fb_writew(daddr >> 16, HD64461_BBTDSARH); 138 if (mask_addr) { 139 maddr += mask_addr; 140 fb_writew(maddr & 0xffff, HD64461_BBTMARL); 141 fb_writew(maddr >> 16, HD64461_BBTMARH); 142 } 143 hitfb_accel_start(truecolor); 144} 145 146static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) 147{ 148 if (rect->rop != ROP_COPY) 149 cfb_fillrect(p, rect); 150 else { 151 fb_writew(0x00f0, HD64461_BBTROPR); 152 fb_writew(16, HD64461_BBTMDR); 153 154 if (p->var.bits_per_pixel == 16) { 155 fb_writew(((u32 *) (p->pseudo_palette))[rect->color], 156 HD64461_GRSCR); 157 hitfb_accel_set_dest(1, rect->dx, rect->dy, rect->width, 158 rect->height); 159 hitfb_accel_start(1); 160 } else { 161 fb_writew(rect->color, HD64461_GRSCR); 162 hitfb_accel_set_dest(0, rect->dx, rect->dy, rect->width, 163 rect->height); 164 hitfb_accel_start(0); 165 } 166 hitfb_accel_wait(); 167 } 168} 169 170static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 171{ 172 hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy, 173 area->dx, area->dy, area->width, area->height, 174 0x00cc, 0); 175 hitfb_accel_wait(); 176} 177 178static int hitfb_pan_display(struct fb_var_screeninfo *var, 179 struct fb_info *info) 180{ 181 int xoffset = var->xoffset; 182 int yoffset = var->yoffset; 183 184 if (xoffset != 0) 185 return -EINVAL; 186 187 fb_writew(yoffset, HD64461_LCDCBAR); 188 189 return 0; 190} 191 192int hitfb_blank(int blank_mode, struct fb_info *info) 193{ 194 unsigned short v; 195 196 if (blank_mode) { 197#ifdef MACH_HP600 198 sh_dac_disable(DAC_LCD_BRIGHTNESS); 199 v = fb_readw(HD64461_GPBDR); 200 v |= HD64461_GPBDR_LCDOFF; 201 fb_writew(v, HD64461_GPBDR); 202#endif 203 v = fb_readw(HD64461_LDR1); 204 v &= ~HD64461_LDR1_DON; 205 fb_writew(v, HD64461_LDR1); 206 207 v = fb_readw(HD64461_LCDCCR); 208 v |= HD64461_LCDCCR_MOFF; 209 fb_writew(v, HD64461_LCDCCR); 210 211 v = fb_readw(HD64461_STBCR); 212 v |= HD64461_STBCR_SLCDST; 213 fb_writew(v, HD64461_STBCR); 214 } else { 215 v = fb_readw(HD64461_STBCR); 216 v &= ~HD64461_STBCR_SLCDST; 217 fb_writew(v, HD64461_STBCR); 218#ifdef MACH_HP600 219 sh_dac_enable(DAC_LCD_BRIGHTNESS); 220 v = fb_readw(HD64461_GPBDR); 221 v &= ~HD64461_GPBDR_LCDOFF; 222 fb_writew(v, HD64461_GPBDR); 223#endif 224 v = fb_readw(HD64461_LDR1); 225 v |= HD64461_LDR1_DON; 226 fb_writew(v, HD64461_LDR1); 227 228 v = fb_readw(HD64461_LCDCCR); 229 v &= ~HD64461_LCDCCR_MOFF; 230 fb_writew(v, HD64461_LCDCCR); 231 } 232 return 0; 233} 234 235static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green, 236 unsigned blue, unsigned transp, struct fb_info *info) 237{ 238 if (regno >= info->cmap.len) 239 return 1; 240 241 switch (info->var.bits_per_pixel) { 242 case 8: 243 fb_writew(regno << 8, HD64461_CPTWAR); 244 fb_writew(red >> 10, HD64461_CPTWDR); 245 fb_writew(green >> 10, HD64461_CPTWDR); 246 fb_writew(blue >> 10, HD64461_CPTWDR); 247 break; 248 case 16: 249 ((u32 *) (info->pseudo_palette))[regno] = 250 ((red & 0xf800)) | 251 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); 252 break; 253 } 254 return 0; 255} 256 257static struct fb_ops hitfb_ops = { 258 .owner = THIS_MODULE, 259 .fb_setcolreg = hitfb_setcolreg, 260 .fb_blank = hitfb_blank, 261 .fb_pan_display = hitfb_pan_display, 262 .fb_fillrect = hitfb_fillrect, 263 .fb_copyarea = hitfb_copyarea, 264 .fb_imageblit = cfb_imageblit, 265}; 266 267int __init hitfb_init(void) 268{ 269 unsigned short lcdclor, ldr3, ldvndr; 270 int size; 271 272 if (fb_get_options("hitfb", NULL)) 273 return -ENODEV; 274 275 hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000; 276 hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024; 277 278 lcdclor = fb_readw(HD64461_LCDCLOR); 279 ldvndr = fb_readw(HD64461_LDVNDR); 280 ldr3 = fb_readw(HD64461_LDR3); 281 282 switch (ldr3 & 15) { 283 default: 284 case 4: 285 hitfb_var.bits_per_pixel = 8; 286 hitfb_var.xres = lcdclor; 287 break; 288 case 8: 289 hitfb_var.bits_per_pixel = 16; 290 hitfb_var.xres = lcdclor / 2; 291 break; 292 } 293 hitfb_fix.line_length = lcdclor; 294 hitfb_fix.visual = (hitfb_var.bits_per_pixel == 8) ? 295 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 296 hitfb_var.yres = ldvndr + 1; 297 hitfb_var.xres_virtual = hitfb_var.xres; 298 hitfb_var.yres_virtual = hitfb_fix.smem_len / lcdclor; 299 switch (hitfb_var.bits_per_pixel) { 300 case 8: 301 hitfb_var.red.offset = 0; 302 hitfb_var.red.length = 8; 303 hitfb_var.green.offset = 0; 304 hitfb_var.green.length = 8; 305 hitfb_var.blue.offset = 0; 306 hitfb_var.blue.length = 8; 307 hitfb_var.transp.offset = 0; 308 hitfb_var.transp.length = 0; 309 break; 310 case 16: /* RGB 565 */ 311 hitfb_var.red.offset = 11; 312 hitfb_var.red.length = 5; 313 hitfb_var.green.offset = 5; 314 hitfb_var.green.length = 6; 315 hitfb_var.blue.offset = 0; 316 hitfb_var.blue.length = 5; 317 hitfb_var.transp.offset = 0; 318 hitfb_var.transp.length = 0; 319 break; 320 } 321 322 fb_info.fbops = &hitfb_ops; 323 fb_info.var = hitfb_var; 324 fb_info.fix = hitfb_fix; 325 fb_info.pseudo_palette = pseudo_palette; 326 fb_info.flags = FBINFO_DEFAULT; 327 328 fb_info.screen_base = (void *)hitfb_fix.smem_start; 329 330 size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16; 331 fb_alloc_cmap(&fb_info.cmap, size, 0); 332 333 if (register_framebuffer(&fb_info) < 0) 334 return -EINVAL; 335 336 printk(KERN_INFO "fb%d: %s frame buffer device\n", 337 fb_info.node, fb_info.fix.id); 338 return 0; 339} 340 341static void __exit hitfb_exit(void) 342{ 343 unregister_framebuffer(&fb_info); 344} 345 346module_init(hitfb_init); 347module_exit(hitfb_exit); 348 349MODULE_LICENSE("GPL");