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