blob: 0679b389a808f6661a68cc5b443156a868863ddd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
3 *
4 * Copyright (C) 1995 Jay Estabrook
5 * Copyright (C) 1997 Geert Uytterhoeven
6 * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
7 * Copyright (C) 2002 Richard Henderson
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/module.h>
15#include <linux/kernel.h>
16#include <linux/sched.h>
17#include <linux/errno.h>
18#include <linux/string.h>
19#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/slab.h>
21#include <linux/delay.h>
22#include <linux/init.h>
23#include <linux/fb.h>
24#include <linux/pci.h>
25#include <linux/selection.h>
Akinobu Mita1c667682006-12-08 02:36:26 -080026#include <linux/bitrev.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/io.h>
28#include <video/tgafb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
30/*
31 * Local functions.
32 */
33
34static int tgafb_check_var(struct fb_var_screeninfo *, struct fb_info *);
35static int tgafb_set_par(struct fb_info *);
36static void tgafb_set_pll(struct tga_par *, int);
37static int tgafb_setcolreg(unsigned, unsigned, unsigned, unsigned,
38 unsigned, struct fb_info *);
39static int tgafb_blank(int, struct fb_info *);
40static void tgafb_init_fix(struct fb_info *);
41
42static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
43static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
44static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
45
46static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070047static void tgafb_pci_unregister(struct pci_dev *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49static const char *mode_option = "640x480@60";
50
51
52/*
53 * Frame buffer operations
54 */
55
56static struct fb_ops tgafb_ops = {
57 .owner = THIS_MODULE,
58 .fb_check_var = tgafb_check_var,
59 .fb_set_par = tgafb_set_par,
60 .fb_setcolreg = tgafb_setcolreg,
61 .fb_blank = tgafb_blank,
62 .fb_fillrect = tgafb_fillrect,
63 .fb_copyarea = tgafb_copyarea,
64 .fb_imageblit = tgafb_imageblit,
Linus Torvalds1da177e2005-04-16 15:20:36 -070065};
66
67
68/*
69 * PCI registration operations
70 */
71
72static struct pci_device_id const tgafb_pci_table[] = {
73 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, PCI_ANY_ID, PCI_ANY_ID,
74 0, 0, 0 }
75};
76
77static struct pci_driver tgafb_driver = {
78 .name = "tgafb",
79 .id_table = tgafb_pci_table,
80 .probe = tgafb_pci_register,
81 .remove = __devexit_p(tgafb_pci_unregister),
82};
83
84
85/**
86 * tgafb_check_var - Optional function. Validates a var passed in.
87 * @var: frame buffer variable screen structure
88 * @info: frame buffer structure that represents a single frame buffer
89 */
90static int
91tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
92{
93 struct tga_par *par = (struct tga_par *)info->par;
94
95 if (par->tga_type == TGA_TYPE_8PLANE) {
96 if (var->bits_per_pixel != 8)
97 return -EINVAL;
98 } else {
99 if (var->bits_per_pixel != 32)
100 return -EINVAL;
101 }
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800102 var->red.length = var->green.length = var->blue.length = 8;
103 if (var->bits_per_pixel == 32) {
104 var->red.offset = 16;
105 var->green.offset = 8;
106 var->blue.offset = 0;
107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
110 return -EINVAL;
111 if (var->nonstd)
112 return -EINVAL;
113 if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ)
114 return -EINVAL;
115 if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
116 return -EINVAL;
117
118 /* Some of the acceleration routines assume the line width is
119 a multiple of 64 bytes. */
120 if (var->xres * (par->tga_type == TGA_TYPE_8PLANE ? 1 : 4) % 64)
121 return -EINVAL;
122
123 return 0;
124}
125
126/**
127 * tgafb_set_par - Optional function. Alters the hardware state.
128 * @info: frame buffer structure that represents a single frame buffer
129 */
130static int
131tgafb_set_par(struct fb_info *info)
132{
133 static unsigned int const deep_presets[4] = {
134 0x00014000,
135 0x0001440d,
136 0xffffffff,
137 0x0001441d
138 };
139 static unsigned int const rasterop_presets[4] = {
140 0x00000003,
141 0x00000303,
142 0xffffffff,
143 0x00000303
144 };
145 static unsigned int const mode_presets[4] = {
Maciej W. Rozyckic7488ce2007-02-12 00:54:55 -0800146 0x00000000,
147 0x00000300,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 0xffffffff,
Maciej W. Rozyckic7488ce2007-02-12 00:54:55 -0800149 0x00000300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 };
151 static unsigned int const base_addr_presets[4] = {
152 0x00000000,
153 0x00000001,
154 0xffffffff,
155 0x00000001
156 };
157
158 struct tga_par *par = (struct tga_par *) info->par;
159 u32 htimings, vtimings, pll_freq;
160 u8 tga_type;
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800161 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163 /* Encode video timings. */
164 htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
165 | (((info->var.xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB));
166 vtimings = (info->var.yres & TGA_VERT_ACTIVE);
167 htimings |= ((info->var.right_margin/4) << 9) & TGA_HORIZ_FP;
168 vtimings |= (info->var.lower_margin << 11) & TGA_VERT_FP;
169 htimings |= ((info->var.hsync_len/4) << 14) & TGA_HORIZ_SYNC;
170 vtimings |= (info->var.vsync_len << 16) & TGA_VERT_SYNC;
171 htimings |= ((info->var.left_margin/4) << 21) & TGA_HORIZ_BP;
172 vtimings |= (info->var.upper_margin << 22) & TGA_VERT_BP;
173
174 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
175 htimings |= TGA_HORIZ_POLARITY;
176 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
177 vtimings |= TGA_VERT_POLARITY;
178
179 par->htimings = htimings;
180 par->vtimings = vtimings;
181
182 par->sync_on_green = !!(info->var.sync & FB_SYNC_ON_GREEN);
183
184 /* Store other useful values in par. */
185 par->xres = info->var.xres;
186 par->yres = info->var.yres;
187 par->pll_freq = pll_freq = 1000000000 / info->var.pixclock;
188 par->bits_per_pixel = info->var.bits_per_pixel;
189
190 tga_type = par->tga_type;
191
192 /* First, disable video. */
193 TGA_WRITE_REG(par, TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
194
195 /* Write the DEEP register. */
196 while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
197 continue;
198 mb();
199 TGA_WRITE_REG(par, deep_presets[tga_type], TGA_DEEP_REG);
200 while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
201 continue;
202 mb();
203
204 /* Write some more registers. */
205 TGA_WRITE_REG(par, rasterop_presets[tga_type], TGA_RASTEROP_REG);
206 TGA_WRITE_REG(par, mode_presets[tga_type], TGA_MODE_REG);
207 TGA_WRITE_REG(par, base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
208
209 /* Calculate & write the PLL. */
210 tgafb_set_pll(par, pll_freq);
211
212 /* Write some more registers. */
213 TGA_WRITE_REG(par, 0xffffffff, TGA_PLANEMASK_REG);
214 TGA_WRITE_REG(par, 0xffffffff, TGA_PIXELMASK_REG);
215
216 /* Init video timing regs. */
217 TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
218 TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
219
220 /* Initalise RAMDAC. */
221 if (tga_type == TGA_TYPE_8PLANE) {
222
223 /* Init BT485 RAMDAC registers. */
224 BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
225 BT485_CMD_0);
226 BT485_WRITE(par, 0x01, BT485_ADDR_PAL_WRITE);
227 BT485_WRITE(par, 0x14, BT485_CMD_3); /* cursor 64x64 */
228 BT485_WRITE(par, 0x40, BT485_CMD_1);
229 BT485_WRITE(par, 0x20, BT485_CMD_2); /* cursor off, for now */
230 BT485_WRITE(par, 0xff, BT485_PIXEL_MASK);
231
232 /* Fill palette registers. */
233 BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
234 TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
235
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800236#ifdef CONFIG_HW_CONSOLE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 for (i = 0; i < 16; i++) {
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800238 int j = color_table[i];
239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8),
241 TGA_RAMDAC_REG);
242 TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8),
243 TGA_RAMDAC_REG);
244 TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8),
245 TGA_RAMDAC_REG);
246 }
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800247 for (i = 0; i < 240 * 3; i += 4) {
248#else
249 for (i = 0; i < 256 * 3; i += 4) {
250#endif
251 TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 TGA_RAMDAC_REG);
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800253 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 TGA_RAMDAC_REG);
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800255 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 TGA_RAMDAC_REG);
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800257 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 TGA_RAMDAC_REG);
259 }
260
261 } else { /* 24-plane or 24plusZ */
262
263 /* Init BT463 registers. */
264 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
265 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
266 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
267 (par->sync_on_green ? 0x80 : 0x40));
268
269 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
270 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
271 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
272 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
273
274 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
275 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
276 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
277 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
278
279 /* Fill the palette. */
280 BT463_LOAD_ADDR(par, 0x0000);
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800281 TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800283#ifdef CONFIG_HW_CONSOLE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 for (i = 0; i < 16; i++) {
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800285 int j = color_table[i];
286
287 TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
288 TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
289 TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 }
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800291 for (i = 0; i < 512 * 3; i += 4) {
292#else
293 for (i = 0; i < 528 * 3; i += 4) {
294#endif
295 TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
296 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
297 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
298 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 }
300
301 /* Fill window type table after start of vertical retrace. */
302 while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
303 continue;
304 TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
305 mb();
306 while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
307 continue;
308 TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
309
310 BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800311 TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
313 for (i = 0; i < 16; i++) {
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800314 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
315 TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
316 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 }
318
319 }
320
321 /* Finally, enable video scan (and pray for the monitor... :-) */
322 TGA_WRITE_REG(par, TGA_VALID_VIDEO, TGA_VALID_REG);
323
324 return 0;
325}
326
327#define DIFFCHECK(X) \
328do { \
329 if (m <= 0x3f) { \
330 int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
331 if (delta < 0) \
332 delta = -delta; \
333 if (delta < min_diff) \
334 min_diff = delta, vm = m, va = a, vr = r; \
335 } \
336} while (0)
337
338static void
339tgafb_set_pll(struct tga_par *par, int f)
340{
341 int n, shift, base, min_diff, target;
342 int r,a,m,vm = 34, va = 1, vr = 30;
343
344 for (r = 0 ; r < 12 ; r++)
345 TGA_WRITE_REG(par, !r, TGA_CLOCK_REG);
346
347 if (f > TGA_PLL_MAX_FREQ)
348 f = TGA_PLL_MAX_FREQ;
349
350 if (f >= TGA_PLL_MAX_FREQ / 2)
351 shift = 0;
352 else if (f >= TGA_PLL_MAX_FREQ / 4)
353 shift = 1;
354 else
355 shift = 2;
356
357 TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG);
358 TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG);
359
360 for (r = 0 ; r < 10 ; r++)
361 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
362
363 if (f <= 120000) {
364 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
365 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
366 }
367 else if (f <= 200000) {
368 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
369 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
370 }
371 else {
372 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
373 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
374 }
375
376 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
377 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
378 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
379 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
380 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
381 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
382
383 target = (f << shift) / TGA_PLL_BASE_FREQ;
384 min_diff = TGA_PLL_MAX_FREQ;
385
386 r = 7 / target;
387 if (!r) r = 1;
388
389 base = target * r;
390 while (base < 449) {
391 for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
392 m = ((n + 3) / 7) - 1;
393 a = 0;
394 DIFFCHECK((m + 1) * 7);
395 m++;
396 DIFFCHECK((m + 1) * 7);
397 m = (n / 6) - 1;
398 if ((a = n % 6))
399 DIFFCHECK(n);
400 }
401 r++;
402 base += target;
403 }
404
405 vr--;
406
407 for (r = 0; r < 8; r++)
408 TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG);
409 for (r = 0; r < 8 ; r++)
410 TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG);
411 for (r = 0; r < 7 ; r++)
412 TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG);
413 TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);
414}
415
416
417/**
418 * tgafb_setcolreg - Optional function. Sets a color register.
419 * @regno: boolean, 0 copy local, 1 get_user() function
420 * @red: frame buffer colormap structure
421 * @green: The green value which can be up to 16 bits wide
422 * @blue: The blue value which can be up to 16 bits wide.
423 * @transp: If supported the alpha value which can be up to 16 bits wide.
424 * @info: frame buffer info structure
425 */
426static int
427tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
428 unsigned transp, struct fb_info *info)
429{
430 struct tga_par *par = (struct tga_par *) info->par;
431
432 if (regno > 255)
433 return 1;
434 red >>= 8;
435 green >>= 8;
436 blue >>= 8;
437
438 if (par->tga_type == TGA_TYPE_8PLANE) {
439 BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
440 TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
441 TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
442 TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
443 TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
Maciej W. Rozyckibe601182007-02-12 00:54:54 -0800444 } else {
445 if (regno < 16) {
446 u32 value = (regno << 16) | (regno << 8) | regno;
447 ((u32 *)info->pseudo_palette)[regno] = value;
448 }
449 BT463_LOAD_ADDR(par, regno);
450 TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
451 TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
452 TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
453 TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 }
455
456 return 0;
457}
458
459
460/**
461 * tgafb_blank - Optional function. Blanks the display.
462 * @blank_mode: the blank mode we want.
463 * @info: frame buffer structure that represents a single frame buffer
464 */
465static int
466tgafb_blank(int blank, struct fb_info *info)
467{
468 struct tga_par *par = (struct tga_par *) info->par;
469 u32 vhcr, vvcr, vvvr;
470 unsigned long flags;
471
472 local_irq_save(flags);
473
474 vhcr = TGA_READ_REG(par, TGA_HORIZ_REG);
475 vvcr = TGA_READ_REG(par, TGA_VERT_REG);
476 vvvr = TGA_READ_REG(par, TGA_VALID_REG);
477 vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
478
479 switch (blank) {
480 case FB_BLANK_UNBLANK: /* Unblanking */
481 if (par->vesa_blanked) {
482 TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG);
483 TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG);
484 par->vesa_blanked = 0;
485 }
486 TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
487 break;
488
489 case FB_BLANK_NORMAL: /* Normal blanking */
490 TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK,
491 TGA_VALID_REG);
492 break;
493
494 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
495 TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
496 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
497 par->vesa_blanked = 1;
498 break;
499
500 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
501 TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
502 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
503 par->vesa_blanked = 1;
504 break;
505
506 case FB_BLANK_POWERDOWN: /* Poweroff */
507 TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
508 TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
509 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
510 par->vesa_blanked = 1;
511 break;
512 }
513
514 local_irq_restore(flags);
515 return 0;
516}
517
518
519/*
520 * Acceleration.
521 */
522
523/**
524 * tgafb_imageblit - REQUIRED function. Can use generic routines if
525 * non acclerated hardware and packed pixel based.
526 * Copies a image from system memory to the screen.
527 *
528 * @info: frame buffer structure that represents a single frame buffer
529 * @image: structure defining the image.
530 */
531static void
532tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
533{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 struct tga_par *par = (struct tga_par *) info->par;
535 u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
536 unsigned long rincr, line_length, shift, pos, is8bpp;
537 unsigned long i, j;
538 const unsigned char *data;
539 void __iomem *regs_base;
540 void __iomem *fb_base;
541
542 dx = image->dx;
543 dy = image->dy;
544 width = image->width;
545 height = image->height;
546 vxres = info->var.xres_virtual;
547 vyres = info->var.yres_virtual;
548 line_length = info->fix.line_length;
549 rincr = (width + 7) / 8;
550
551 /* Crop the image to the screen. */
552 if (dx > vxres || dy > vyres)
553 return;
554 if (dx + width > vxres)
555 width = vxres - dx;
556 if (dy + height > vyres)
557 height = vyres - dy;
558
559 /* For copies that aren't pixel expansion, there's little we
560 can do better than the generic code. */
561 /* ??? There is a DMA write mode; I wonder if that could be
562 made to pull the data from the image buffer... */
563 if (image->depth > 1) {
564 cfb_imageblit(info, image);
565 return;
566 }
567
568 regs_base = par->tga_regs_base;
569 fb_base = par->tga_fb_base;
570 is8bpp = info->var.bits_per_pixel == 8;
571
572 /* Expand the color values to fill 32-bits. */
573 /* ??? Would be nice to notice colour changes elsewhere, so
574 that we can do this only when necessary. */
575 fgcolor = image->fg_color;
576 bgcolor = image->bg_color;
577 if (is8bpp) {
578 fgcolor |= fgcolor << 8;
579 fgcolor |= fgcolor << 16;
580 bgcolor |= bgcolor << 8;
581 bgcolor |= bgcolor << 16;
582 } else {
583 if (fgcolor < 16)
584 fgcolor = ((u32 *)info->pseudo_palette)[fgcolor];
585 if (bgcolor < 16)
586 bgcolor = ((u32 *)info->pseudo_palette)[bgcolor];
587 }
588 __raw_writel(fgcolor, regs_base + TGA_FOREGROUND_REG);
589 __raw_writel(bgcolor, regs_base + TGA_BACKGROUND_REG);
590
591 /* Acquire proper alignment; set up the PIXELMASK register
592 so that we only write the proper character cell. */
593 pos = dy * line_length;
594 if (is8bpp) {
595 pos += dx;
596 shift = pos & 3;
597 pos &= -4;
598 } else {
599 pos += dx * 4;
600 shift = (pos & 7) >> 2;
601 pos &= -8;
602 }
603
604 data = (const unsigned char *) image->data;
605
606 /* Enable opaque stipple mode. */
607 __raw_writel((is8bpp
608 ? TGA_MODE_SBM_8BPP | TGA_MODE_OPAQUE_STIPPLE
609 : TGA_MODE_SBM_24BPP | TGA_MODE_OPAQUE_STIPPLE),
610 regs_base + TGA_MODE_REG);
611
612 if (width + shift <= 32) {
613 unsigned long bwidth;
614
615 /* Handle common case of imaging a single character, in
616 a font less than 32 pixels wide. */
617
618 pixelmask = (1 << width) - 1;
619 pixelmask <<= shift;
620 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
621 wmb();
622
623 bwidth = (width + 7) / 8;
624
625 for (i = 0; i < height; ++i) {
626 u32 mask = 0;
627
628 /* The image data is bit big endian; we need
629 little endian. */
630 for (j = 0; j < bwidth; ++j)
Akinobu Mita1c667682006-12-08 02:36:26 -0800631 mask |= bitrev8(data[j]) << (j * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633 __raw_writel(mask << shift, fb_base + pos);
634
635 pos += line_length;
636 data += rincr;
637 }
638 wmb();
639 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
640 } else if (shift == 0) {
641 unsigned long pos0 = pos;
642 const unsigned char *data0 = data;
643 unsigned long bincr = (is8bpp ? 8 : 8*4);
644 unsigned long bwidth;
645
646 /* Handle another common case in which accel_putcs
647 generates a large bitmap, which happens to be aligned.
648 Allow the tail to be misaligned. This case is
649 interesting because we've not got to hold partial
650 bytes across the words being written. */
651
652 wmb();
653
654 bwidth = (width / 8) & -4;
655 for (i = 0; i < height; ++i) {
656 for (j = 0; j < bwidth; j += 4) {
657 u32 mask = 0;
Akinobu Mita1c667682006-12-08 02:36:26 -0800658 mask |= bitrev8(data[j+0]) << (0 * 8);
659 mask |= bitrev8(data[j+1]) << (1 * 8);
660 mask |= bitrev8(data[j+2]) << (2 * 8);
661 mask |= bitrev8(data[j+3]) << (3 * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 __raw_writel(mask, fb_base + pos + j*bincr);
663 }
664 pos += line_length;
665 data += rincr;
666 }
667 wmb();
668
669 pixelmask = (1ul << (width & 31)) - 1;
670 if (pixelmask) {
671 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
672 wmb();
673
674 pos = pos0 + bwidth*bincr;
675 data = data0 + bwidth;
676 bwidth = ((width & 31) + 7) / 8;
677
678 for (i = 0; i < height; ++i) {
679 u32 mask = 0;
680 for (j = 0; j < bwidth; ++j)
Akinobu Mita1c667682006-12-08 02:36:26 -0800681 mask |= bitrev8(data[j]) << (j * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 __raw_writel(mask, fb_base + pos);
683 pos += line_length;
684 data += rincr;
685 }
686 wmb();
687 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
688 }
689 } else {
690 unsigned long pos0 = pos;
691 const unsigned char *data0 = data;
692 unsigned long bincr = (is8bpp ? 8 : 8*4);
693 unsigned long bwidth;
694
695 /* Finally, handle the generic case of misaligned start.
696 Here we split the write into 16-bit spans. This allows
697 us to use only one pixel mask, instead of four as would
698 be required by writing 24-bit spans. */
699
700 pixelmask = 0xffff << shift;
701 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
702 wmb();
703
704 bwidth = (width / 8) & -2;
705 for (i = 0; i < height; ++i) {
706 for (j = 0; j < bwidth; j += 2) {
707 u32 mask = 0;
Akinobu Mita1c667682006-12-08 02:36:26 -0800708 mask |= bitrev8(data[j+0]) << (0 * 8);
709 mask |= bitrev8(data[j+1]) << (1 * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 mask <<= shift;
711 __raw_writel(mask, fb_base + pos + j*bincr);
712 }
713 pos += line_length;
714 data += rincr;
715 }
716 wmb();
717
718 pixelmask = ((1ul << (width & 15)) - 1) << shift;
719 if (pixelmask) {
720 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
721 wmb();
722
723 pos = pos0 + bwidth*bincr;
724 data = data0 + bwidth;
725 bwidth = (width & 15) > 8;
726
727 for (i = 0; i < height; ++i) {
Akinobu Mita1c667682006-12-08 02:36:26 -0800728 u32 mask = bitrev8(data[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 if (bwidth)
Akinobu Mita1c667682006-12-08 02:36:26 -0800730 mask |= bitrev8(data[1]) << 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 mask <<= shift;
732 __raw_writel(mask, fb_base + pos);
733 pos += line_length;
734 data += rincr;
735 }
736 wmb();
737 }
738 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
739 }
740
741 /* Disable opaque stipple mode. */
742 __raw_writel((is8bpp
743 ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
744 : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
745 regs_base + TGA_MODE_REG);
746}
747
748/**
749 * tgafb_fillrect - REQUIRED function. Can use generic routines if
750 * non acclerated hardware and packed pixel based.
751 * Draws a rectangle on the screen.
752 *
753 * @info: frame buffer structure that represents a single frame buffer
754 * @rect: structure defining the rectagle and operation.
755 */
756static void
757tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
758{
759 struct tga_par *par = (struct tga_par *) info->par;
760 int is8bpp = info->var.bits_per_pixel == 8;
761 u32 dx, dy, width, height, vxres, vyres, color;
762 unsigned long pos, align, line_length, i, j;
763 void __iomem *regs_base;
764 void __iomem *fb_base;
765
766 dx = rect->dx;
767 dy = rect->dy;
768 width = rect->width;
769 height = rect->height;
770 vxres = info->var.xres_virtual;
771 vyres = info->var.yres_virtual;
772 line_length = info->fix.line_length;
773 regs_base = par->tga_regs_base;
774 fb_base = par->tga_fb_base;
775
776 /* Crop the rectangle to the screen. */
777 if (dx > vxres || dy > vyres || !width || !height)
778 return;
779 if (dx + width > vxres)
780 width = vxres - dx;
781 if (dy + height > vyres)
782 height = vyres - dy;
783
784 pos = dy * line_length + dx * (is8bpp ? 1 : 4);
785
786 /* ??? We could implement ROP_XOR with opaque fill mode
787 and a RasterOp setting of GXxor, but as far as I can
788 tell, this mode is not actually used in the kernel.
789 Thus I am ignoring it for now. */
790 if (rect->rop != ROP_COPY) {
791 cfb_fillrect(info, rect);
792 return;
793 }
794
795 /* Expand the color value to fill 8 pixels. */
796 color = rect->color;
797 if (is8bpp) {
798 color |= color << 8;
799 color |= color << 16;
800 __raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
801 __raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
802 } else {
803 if (color < 16)
804 color = ((u32 *)info->pseudo_palette)[color];
805 __raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
806 __raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
807 __raw_writel(color, regs_base + TGA_BLOCK_COLOR2_REG);
808 __raw_writel(color, regs_base + TGA_BLOCK_COLOR3_REG);
809 __raw_writel(color, regs_base + TGA_BLOCK_COLOR4_REG);
810 __raw_writel(color, regs_base + TGA_BLOCK_COLOR5_REG);
811 __raw_writel(color, regs_base + TGA_BLOCK_COLOR6_REG);
812 __raw_writel(color, regs_base + TGA_BLOCK_COLOR7_REG);
813 }
814
815 /* The DATA register holds the fill mask for block fill mode.
816 Since we're not stippling, this is all ones. */
817 __raw_writel(0xffffffff, regs_base + TGA_DATA_REG);
818
819 /* Enable block fill mode. */
820 __raw_writel((is8bpp
821 ? TGA_MODE_SBM_8BPP | TGA_MODE_BLOCK_FILL
822 : TGA_MODE_SBM_24BPP | TGA_MODE_BLOCK_FILL),
823 regs_base + TGA_MODE_REG);
824 wmb();
825
826 /* We can fill 2k pixels per operation. Notice blocks that fit
827 the width of the screen so that we can take advantage of this
828 and fill more than one line per write. */
829 if (width == line_length)
830 width *= height, height = 1;
831
832 /* The write into the frame buffer must be aligned to 4 bytes,
833 but we are allowed to encode the offset within the word in
834 the data word written. */
835 align = (pos & 3) << 16;
836 pos &= -4;
837
838 if (width <= 2048) {
839 u32 data;
840
841 data = (width - 1) | align;
842
843 for (i = 0; i < height; ++i) {
844 __raw_writel(data, fb_base + pos);
845 pos += line_length;
846 }
847 } else {
848 unsigned long Bpp = (is8bpp ? 1 : 4);
849 unsigned long nwidth = width & -2048;
850 u32 fdata, ldata;
851
852 fdata = (2048 - 1) | align;
853 ldata = ((width & 2047) - 1) | align;
854
855 for (i = 0; i < height; ++i) {
856 for (j = 0; j < nwidth; j += 2048)
857 __raw_writel(fdata, fb_base + pos + j*Bpp);
858 if (j < width)
859 __raw_writel(ldata, fb_base + pos + j*Bpp);
860 pos += line_length;
861 }
862 }
863 wmb();
864
865 /* Disable block fill mode. */
866 __raw_writel((is8bpp
867 ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
868 : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
869 regs_base + TGA_MODE_REG);
870}
871
872/**
873 * tgafb_copyarea - REQUIRED function. Can use generic routines if
874 * non acclerated hardware and packed pixel based.
875 * Copies on area of the screen to another area.
876 *
877 * @info: frame buffer structure that represents a single frame buffer
878 * @area: structure defining the source and destination.
879 */
880
881/* Handle the special case of copying entire lines, e.g. during scrolling.
882 We can avoid a lot of needless computation in this case. In the 8bpp
883 case we need to use the COPY64 registers instead of mask writes into
884 the frame buffer to achieve maximum performance. */
885
886static inline void
887copyarea_line_8bpp(struct fb_info *info, u32 dy, u32 sy,
888 u32 height, u32 width)
889{
890 struct tga_par *par = (struct tga_par *) info->par;
891 void __iomem *tga_regs = par->tga_regs_base;
892 unsigned long dpos, spos, i, n64;
893
894 /* Set up the MODE and PIXELSHIFT registers. */
895 __raw_writel(TGA_MODE_SBM_8BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
896 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
897 wmb();
898
899 n64 = (height * width) / 64;
900
Maciej W. Rozycki36f71402007-02-12 00:54:53 -0800901 if (sy < dy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 spos = (sy + height) * width;
903 dpos = (dy + height) * width;
904
905 for (i = 0; i < n64; ++i) {
906 spos -= 64;
907 dpos -= 64;
908 __raw_writel(spos, tga_regs+TGA_COPY64_SRC);
909 wmb();
910 __raw_writel(dpos, tga_regs+TGA_COPY64_DST);
911 wmb();
912 }
913 } else {
914 spos = sy * width;
915 dpos = dy * width;
916
917 for (i = 0; i < n64; ++i) {
918 __raw_writel(spos, tga_regs+TGA_COPY64_SRC);
919 wmb();
920 __raw_writel(dpos, tga_regs+TGA_COPY64_DST);
921 wmb();
922 spos += 64;
923 dpos += 64;
924 }
925 }
926
927 /* Reset the MODE register to normal. */
928 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
929}
930
931static inline void
932copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
933 u32 height, u32 width)
934{
935 struct tga_par *par = (struct tga_par *) info->par;
936 void __iomem *tga_regs = par->tga_regs_base;
937 void __iomem *tga_fb = par->tga_fb_base;
938 void __iomem *src;
939 void __iomem *dst;
940 unsigned long i, n16;
941
942 /* Set up the MODE and PIXELSHIFT registers. */
943 __raw_writel(TGA_MODE_SBM_24BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
944 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
945 wmb();
946
947 n16 = (height * width) / 16;
948
Maciej W. Rozycki36f71402007-02-12 00:54:53 -0800949 if (sy < dy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 src = tga_fb + (sy + height) * width * 4;
951 dst = tga_fb + (dy + height) * width * 4;
952
953 for (i = 0; i < n16; ++i) {
954 src -= 64;
955 dst -= 64;
956 __raw_writel(0xffff, src);
957 wmb();
958 __raw_writel(0xffff, dst);
959 wmb();
960 }
961 } else {
962 src = tga_fb + sy * width * 4;
963 dst = tga_fb + dy * width * 4;
964
965 for (i = 0; i < n16; ++i) {
966 __raw_writel(0xffff, src);
967 wmb();
968 __raw_writel(0xffff, dst);
969 wmb();
970 src += 64;
971 dst += 64;
972 }
973 }
974
975 /* Reset the MODE register to normal. */
976 __raw_writel(TGA_MODE_SBM_24BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
977}
978
979/* The general case of forward copy in 8bpp mode. */
980static inline void
981copyarea_foreward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
982 u32 height, u32 width, u32 line_length)
983{
984 struct tga_par *par = (struct tga_par *) info->par;
985 unsigned long i, copied, left;
986 unsigned long dpos, spos, dalign, salign, yincr;
987 u32 smask_first, dmask_first, dmask_last;
988 int pixel_shift, need_prime, need_second;
989 unsigned long n64, n32, xincr_first;
990 void __iomem *tga_regs;
991 void __iomem *tga_fb;
992
993 yincr = line_length;
994 if (dy > sy) {
995 dy += height - 1;
996 sy += height - 1;
997 yincr = -yincr;
998 }
999
1000 /* Compute the offsets and alignments in the frame buffer.
1001 More than anything else, these control how we do copies. */
1002 dpos = dy * line_length + dx;
1003 spos = sy * line_length + sx;
1004 dalign = dpos & 7;
1005 salign = spos & 7;
1006 dpos &= -8;
1007 spos &= -8;
1008
1009 /* Compute the value for the PIXELSHIFT register. This controls
1010 both non-co-aligned source and destination and copy direction. */
1011 if (dalign >= salign)
1012 pixel_shift = dalign - salign;
1013 else
1014 pixel_shift = 8 - (salign - dalign);
1015
1016 /* Figure out if we need an additional priming step for the
1017 residue register. */
1018 need_prime = (salign > dalign);
1019 if (need_prime)
1020 dpos -= 8;
1021
1022 /* Begin by copying the leading unaligned destination. Copy enough
1023 to make the next destination address 32-byte aligned. */
1024 copied = 32 - (dalign + (dpos & 31));
1025 if (copied == 32)
1026 copied = 0;
1027 xincr_first = (copied + 7) & -8;
1028 smask_first = dmask_first = (1ul << copied) - 1;
1029 smask_first <<= salign;
1030 dmask_first <<= dalign + need_prime*8;
1031 if (need_prime && copied > 24)
1032 copied -= 8;
1033 left = width - copied;
1034
1035 /* Care for small copies. */
1036 if (copied > width) {
1037 u32 t;
1038 t = (1ul << width) - 1;
1039 t <<= dalign + need_prime*8;
1040 dmask_first &= t;
1041 left = 0;
1042 }
1043
1044 /* Attempt to use 64-byte copies. This is only possible if the
1045 source and destination are co-aligned at 64 bytes. */
1046 n64 = need_second = 0;
1047 if ((dpos & 63) == (spos & 63)
1048 && (height == 1 || line_length % 64 == 0)) {
1049 /* We may need a 32-byte copy to ensure 64 byte alignment. */
1050 need_second = (dpos + xincr_first) & 63;
1051 if ((need_second & 32) != need_second)
1052 printk(KERN_ERR "tgafb: need_second wrong\n");
1053 if (left >= need_second + 64) {
1054 left -= need_second;
1055 n64 = left / 64;
1056 left %= 64;
1057 } else
1058 need_second = 0;
1059 }
1060
1061 /* Copy trailing full 32-byte sections. This will be the main
1062 loop if the 64 byte loop can't be used. */
1063 n32 = left / 32;
1064 left %= 32;
1065
1066 /* Copy the trailing unaligned destination. */
1067 dmask_last = (1ul << left) - 1;
1068
1069 tga_regs = par->tga_regs_base;
1070 tga_fb = par->tga_fb_base;
1071
1072 /* Set up the MODE and PIXELSHIFT registers. */
1073 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1074 __raw_writel(pixel_shift, tga_regs+TGA_PIXELSHIFT_REG);
1075 wmb();
1076
1077 for (i = 0; i < height; ++i) {
1078 unsigned long j;
1079 void __iomem *sfb;
1080 void __iomem *dfb;
1081
1082 sfb = tga_fb + spos;
1083 dfb = tga_fb + dpos;
1084 if (dmask_first) {
1085 __raw_writel(smask_first, sfb);
1086 wmb();
1087 __raw_writel(dmask_first, dfb);
1088 wmb();
1089 sfb += xincr_first;
1090 dfb += xincr_first;
1091 }
1092
1093 if (need_second) {
1094 __raw_writel(0xffffffff, sfb);
1095 wmb();
1096 __raw_writel(0xffffffff, dfb);
1097 wmb();
1098 sfb += 32;
1099 dfb += 32;
1100 }
1101
1102 if (n64 && (((unsigned long)sfb | (unsigned long)dfb) & 63))
1103 printk(KERN_ERR
1104 "tgafb: misaligned copy64 (s:%p, d:%p)\n",
1105 sfb, dfb);
1106
1107 for (j = 0; j < n64; ++j) {
1108 __raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
1109 wmb();
1110 __raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
1111 wmb();
1112 sfb += 64;
1113 dfb += 64;
1114 }
1115
1116 for (j = 0; j < n32; ++j) {
1117 __raw_writel(0xffffffff, sfb);
1118 wmb();
1119 __raw_writel(0xffffffff, dfb);
1120 wmb();
1121 sfb += 32;
1122 dfb += 32;
1123 }
1124
1125 if (dmask_last) {
1126 __raw_writel(0xffffffff, sfb);
1127 wmb();
1128 __raw_writel(dmask_last, dfb);
1129 wmb();
1130 }
1131
1132 spos += yincr;
1133 dpos += yincr;
1134 }
1135
1136 /* Reset the MODE register to normal. */
1137 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1138}
1139
1140/* The (almost) general case of backward copy in 8bpp mode. */
1141static inline void
1142copyarea_backward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
1143 u32 height, u32 width, u32 line_length,
1144 const struct fb_copyarea *area)
1145{
1146 struct tga_par *par = (struct tga_par *) info->par;
1147 unsigned long i, left, yincr;
1148 unsigned long depos, sepos, dealign, sealign;
1149 u32 mask_first, mask_last;
1150 unsigned long n32;
1151 void __iomem *tga_regs;
1152 void __iomem *tga_fb;
1153
1154 yincr = line_length;
1155 if (dy > sy) {
1156 dy += height - 1;
1157 sy += height - 1;
1158 yincr = -yincr;
1159 }
1160
1161 /* Compute the offsets and alignments in the frame buffer.
1162 More than anything else, these control how we do copies. */
1163 depos = dy * line_length + dx + width;
1164 sepos = sy * line_length + sx + width;
1165 dealign = depos & 7;
1166 sealign = sepos & 7;
1167
1168 /* ??? The documentation appears to be incorrect (or very
1169 misleading) wrt how pixel shifting works in backward copy
1170 mode, i.e. when PIXELSHIFT is negative. I give up for now.
1171 Do handle the common case of co-aligned backward copies,
1172 but frob everything else back on generic code. */
1173 if (dealign != sealign) {
1174 cfb_copyarea(info, area);
1175 return;
1176 }
1177
1178 /* We begin the copy with the trailing pixels of the
1179 unaligned destination. */
1180 mask_first = (1ul << dealign) - 1;
1181 left = width - dealign;
1182
1183 /* Care for small copies. */
1184 if (dealign > width) {
1185 mask_first ^= (1ul << (dealign - width)) - 1;
1186 left = 0;
1187 }
1188
1189 /* Next copy full words at a time. */
1190 n32 = left / 32;
1191 left %= 32;
1192
1193 /* Finally copy the unaligned head of the span. */
1194 mask_last = -1 << (32 - left);
1195
1196 tga_regs = par->tga_regs_base;
1197 tga_fb = par->tga_fb_base;
1198
1199 /* Set up the MODE and PIXELSHIFT registers. */
1200 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1201 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1202 wmb();
1203
1204 for (i = 0; i < height; ++i) {
1205 unsigned long j;
1206 void __iomem *sfb;
1207 void __iomem *dfb;
1208
1209 sfb = tga_fb + sepos;
1210 dfb = tga_fb + depos;
1211 if (mask_first) {
1212 __raw_writel(mask_first, sfb);
1213 wmb();
1214 __raw_writel(mask_first, dfb);
1215 wmb();
1216 }
1217
1218 for (j = 0; j < n32; ++j) {
1219 sfb -= 32;
1220 dfb -= 32;
1221 __raw_writel(0xffffffff, sfb);
1222 wmb();
1223 __raw_writel(0xffffffff, dfb);
1224 wmb();
1225 }
1226
1227 if (mask_last) {
1228 sfb -= 32;
1229 dfb -= 32;
1230 __raw_writel(mask_last, sfb);
1231 wmb();
1232 __raw_writel(mask_last, dfb);
1233 wmb();
1234 }
1235
1236 sepos += yincr;
1237 depos += yincr;
1238 }
1239
1240 /* Reset the MODE register to normal. */
1241 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1242}
1243
1244static void
1245tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1246{
1247 unsigned long dx, dy, width, height, sx, sy, vxres, vyres;
1248 unsigned long line_length, bpp;
1249
1250 dx = area->dx;
1251 dy = area->dy;
1252 width = area->width;
1253 height = area->height;
1254 sx = area->sx;
1255 sy = area->sy;
1256 vxres = info->var.xres_virtual;
1257 vyres = info->var.yres_virtual;
1258 line_length = info->fix.line_length;
1259
1260 /* The top left corners must be in the virtual screen. */
1261 if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)
1262 return;
1263
1264 /* Clip the destination. */
1265 if (dx + width > vxres)
1266 width = vxres - dx;
1267 if (dy + height > vyres)
1268 height = vyres - dy;
1269
1270 /* The source must be completely inside the virtual screen. */
1271 if (sx + width > vxres || sy + height > vyres)
1272 return;
1273
1274 bpp = info->var.bits_per_pixel;
1275
1276 /* Detect copies of the entire line. */
1277 if (width * (bpp >> 3) == line_length) {
1278 if (bpp == 8)
1279 copyarea_line_8bpp(info, dy, sy, height, width);
1280 else
1281 copyarea_line_32bpp(info, dy, sy, height, width);
1282 }
1283
1284 /* ??? The documentation is unclear to me exactly how the pixelshift
1285 register works in 32bpp mode. Since I don't have hardware to test,
1286 give up for now and fall back on the generic routines. */
1287 else if (bpp == 32)
1288 cfb_copyarea(info, area);
1289
1290 /* Detect overlapping source and destination that requires
1291 a backward copy. */
1292 else if (dy == sy && dx > sx && dx < sx + width)
1293 copyarea_backward_8bpp(info, dx, dy, sx, sy, height,
1294 width, line_length, area);
1295 else
1296 copyarea_foreward_8bpp(info, dx, dy, sx, sy, height,
1297 width, line_length);
1298}
1299
1300
1301/*
1302 * Initialisation
1303 */
1304
1305static void
1306tgafb_init_fix(struct fb_info *info)
1307{
1308 struct tga_par *par = (struct tga_par *)info->par;
1309 u8 tga_type = par->tga_type;
1310 const char *tga_type_name;
1311
1312 switch (tga_type) {
1313 case TGA_TYPE_8PLANE:
1314 tga_type_name = "Digital ZLXp-E1";
1315 break;
1316 case TGA_TYPE_24PLANE:
1317 tga_type_name = "Digital ZLXp-E2";
1318 break;
1319 case TGA_TYPE_24PLUSZ:
1320 tga_type_name = "Digital ZLXp-E3";
1321 break;
1322 default:
1323 tga_type_name = "Unknown";
1324 break;
1325 }
1326
1327 strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
1328
1329 info->fix.type = FB_TYPE_PACKED_PIXELS;
1330 info->fix.type_aux = 0;
1331 info->fix.visual = (tga_type == TGA_TYPE_8PLANE
1332 ? FB_VISUAL_PSEUDOCOLOR
Maciej W. Rozyckibe601182007-02-12 00:54:54 -08001333 : FB_VISUAL_DIRECTCOLOR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
1336 info->fix.smem_start = (size_t) par->tga_fb_base;
1337 info->fix.smem_len = info->fix.line_length * par->yres;
1338 info->fix.mmio_start = (size_t) par->tga_regs_base;
1339 info->fix.mmio_len = 512;
1340
1341 info->fix.xpanstep = 0;
1342 info->fix.ypanstep = 0;
1343 info->fix.ywrapstep = 0;
1344
1345 info->fix.accel = FB_ACCEL_DEC_TGA;
1346}
1347
1348static __devinit int
1349tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
1350{
1351 static unsigned int const fb_offset_presets[4] = {
1352 TGA_8PLANE_FB_OFFSET,
1353 TGA_24PLANE_FB_OFFSET,
1354 0xffffffff,
1355 TGA_24PLUSZ_FB_OFFSET
1356 };
1357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 void __iomem *mem_base;
1359 unsigned long bar0_start, bar0_len;
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001360 struct fb_info *info;
1361 struct tga_par *par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 u8 tga_type;
1363 int ret;
1364
1365 /* Enable device in PCI config. */
1366 if (pci_enable_device(pdev)) {
1367 printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
1368 return -ENODEV;
1369 }
1370
1371 /* Allocate the fb and par structures. */
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001372 info = framebuffer_alloc(sizeof(struct tga_par), &pdev->dev);
1373 if (!info) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 printk(KERN_ERR "tgafb: Cannot allocate memory\n");
1375 return -ENOMEM;
1376 }
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001377
1378 par = info->par;
1379 pci_set_drvdata(pdev, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
1381 /* Request the mem regions. */
1382 bar0_start = pci_resource_start(pdev, 0);
1383 bar0_len = pci_resource_len(pdev, 0);
1384 ret = -ENODEV;
1385 if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
1386 printk(KERN_ERR "tgafb: cannot reserve FB region\n");
1387 goto err0;
1388 }
1389
1390 /* Map the framebuffer. */
1391 mem_base = ioremap(bar0_start, bar0_len);
1392 if (!mem_base) {
1393 printk(KERN_ERR "tgafb: Cannot map MMIO\n");
1394 goto err1;
1395 }
1396
1397 /* Grab info about the card. */
1398 tga_type = (readl(mem_base) >> 12) & 0x0f;
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001399 par->pdev = pdev;
1400 par->tga_mem_base = mem_base;
1401 par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
1402 par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
1403 par->tga_type = tga_type;
1404 pci_read_config_byte(pdev, PCI_REVISION_ID, &par->tga_chip_rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
1406 /* Setup framebuffer. */
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001407 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
1408 FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
1409 info->fbops = &tgafb_ops;
1410 info->screen_base = par->tga_fb_base;
1411 info->pseudo_palette = (void *)(par + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413 /* This should give a reasonable default video mode. */
1414
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001415 ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 tga_type == TGA_TYPE_8PLANE ? 8 : 32);
1417 if (ret == 0 || ret == 4) {
1418 printk(KERN_ERR "tgafb: Could not find valid video mode\n");
1419 ret = -EINVAL;
1420 goto err1;
1421 }
1422
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001423 if (fb_alloc_cmap(&info->cmap, 256, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 printk(KERN_ERR "tgafb: Could not allocate color map\n");
1425 ret = -ENOMEM;
1426 goto err1;
1427 }
1428
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001429 tgafb_set_par(info);
1430 tgafb_init_fix(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001432 if (register_framebuffer(info) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 printk(KERN_ERR "tgafb: Could not register framebuffer\n");
1434 ret = -EINVAL;
1435 goto err1;
1436 }
1437
1438 printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001439 par->tga_chip_rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
1441 pdev->bus->number, PCI_SLOT(pdev->devfn),
1442 PCI_FUNC(pdev->devfn));
1443 printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001444 info->node, info->fix.id, bar0_start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
1446 return 0;
1447
1448 err1:
Amol Lade4bf0512006-12-08 02:40:04 -08001449 if (mem_base)
1450 iounmap(mem_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 release_mem_region(bar0_start, bar0_len);
1452 err0:
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001453 framebuffer_release(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 return ret;
1455}
1456
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457static void __exit
1458tgafb_pci_unregister(struct pci_dev *pdev)
1459{
1460 struct fb_info *info = pci_get_drvdata(pdev);
1461 struct tga_par *par = info->par;
1462
1463 if (!info)
1464 return;
1465 unregister_framebuffer(info);
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001466 fb_dealloc_cmap(&info->cmap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 iounmap(par->tga_mem_base);
1468 release_mem_region(pci_resource_start(pdev, 0),
1469 pci_resource_len(pdev, 0));
Maciej W. Rozyckiee9a25e2007-02-12 00:54:52 -08001470 framebuffer_release(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471}
1472
Adrian Bunk62b56fa2005-04-21 14:09:42 -07001473#ifdef MODULE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474static void __exit
1475tgafb_exit(void)
1476{
1477 pci_unregister_driver(&tgafb_driver);
1478}
1479#endif /* MODULE */
1480
1481#ifndef MODULE
1482int __init
1483tgafb_setup(char *arg)
1484{
1485 char *this_opt;
1486
1487 if (arg && *arg) {
1488 while ((this_opt = strsep(&arg, ","))) {
1489 if (!*this_opt)
1490 continue;
1491 if (!strncmp(this_opt, "mode:", 5))
1492 mode_option = this_opt+5;
1493 else
1494 printk(KERN_ERR
1495 "tgafb: unknown parameter %s\n",
1496 this_opt);
1497 }
1498 }
1499
1500 return 0;
1501}
1502#endif /* !MODULE */
1503
1504int __init
1505tgafb_init(void)
1506{
1507#ifndef MODULE
1508 char *option = NULL;
1509
1510 if (fb_get_options("tgafb", &option))
1511 return -ENODEV;
1512 tgafb_setup(option);
1513#endif
1514 return pci_register_driver(&tgafb_driver);
1515}
1516
1517/*
1518 * Modularisation
1519 */
1520
1521module_init(tgafb_init);
1522
1523#ifdef MODULE
1524module_exit(tgafb_exit);
1525#endif
1526
1527MODULE_DESCRIPTION("framebuffer driver for TGA chipset");
1528MODULE_LICENSE("GPL");