1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/bitrev.h>
16#include <linux/compiler.h>
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/errno.h>
20#include <linux/fb.h>
21#include <linux/init.h>
22#include <linux/ioport.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/module.h>
26#include <linux/pci.h>
27#include <linux/selection.h>
28#include <linux/slab.h>
29#include <linux/string.h>
30#include <linux/tc.h>
31
32#include <asm/io.h>
33
34#include <video/tgafb.h>
35
36#ifdef CONFIG_PCI
37#define TGA_BUS_PCI(dev) (dev->bus == &pci_bus_type)
38#else
39#define TGA_BUS_PCI(dev) 0
40#endif
41
42#ifdef CONFIG_TC
43#define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type)
44#else
45#define TGA_BUS_TC(dev) 0
46#endif
47
48
49
50
51
52static int tgafb_check_var(struct fb_var_screeninfo *, struct fb_info *);
53static int tgafb_set_par(struct fb_info *);
54static void tgafb_set_pll(struct tga_par *, int);
55static int tgafb_setcolreg(unsigned, unsigned, unsigned, unsigned,
56 unsigned, struct fb_info *);
57static int tgafb_blank(int, struct fb_info *);
58static void tgafb_init_fix(struct fb_info *);
59
60static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
61static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
62static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
63static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
64
65static int __devinit tgafb_register(struct device *dev);
66static void __devexit tgafb_unregister(struct device *dev);
67
68static const char *mode_option;
69static const char *mode_option_pci = "640x480@60";
70static const char *mode_option_tc = "1280x1024@72";
71
72
73static struct pci_driver tgafb_pci_driver;
74static struct tc_driver tgafb_tc_driver;
75
76
77
78
79
80static struct fb_ops tgafb_ops = {
81 .owner = THIS_MODULE,
82 .fb_check_var = tgafb_check_var,
83 .fb_set_par = tgafb_set_par,
84 .fb_setcolreg = tgafb_setcolreg,
85 .fb_blank = tgafb_blank,
86 .fb_pan_display = tgafb_pan_display,
87 .fb_fillrect = tgafb_fillrect,
88 .fb_copyarea = tgafb_copyarea,
89 .fb_imageblit = tgafb_imageblit,
90};
91
92
93#ifdef CONFIG_PCI
94
95
96
97static int __devinit tgafb_pci_register(struct pci_dev *,
98 const struct pci_device_id *);
99static void __devexit tgafb_pci_unregister(struct pci_dev *);
100
101static struct pci_device_id const tgafb_pci_table[] = {
102 { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
103 { }
104};
105MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
106
107static struct pci_driver tgafb_pci_driver = {
108 .name = "tgafb",
109 .id_table = tgafb_pci_table,
110 .probe = tgafb_pci_register,
111 .remove = __devexit_p(tgafb_pci_unregister),
112};
113
114static int __devinit
115tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
116{
117 return tgafb_register(&pdev->dev);
118}
119
120static void __devexit
121tgafb_pci_unregister(struct pci_dev *pdev)
122{
123 tgafb_unregister(&pdev->dev);
124}
125#endif
126
127#ifdef CONFIG_TC
128
129
130
131static int __devinit tgafb_tc_register(struct device *);
132static int __devexit tgafb_tc_unregister(struct device *);
133
134static struct tc_device_id const tgafb_tc_table[] = {
135 { "DEC ", "PMAGD-AA" },
136 { "DEC ", "PMAGD " },
137 { }
138};
139MODULE_DEVICE_TABLE(tc, tgafb_tc_table);
140
141static struct tc_driver tgafb_tc_driver = {
142 .id_table = tgafb_tc_table,
143 .driver = {
144 .name = "tgafb",
145 .bus = &tc_bus_type,
146 .probe = tgafb_tc_register,
147 .remove = __devexit_p(tgafb_tc_unregister),
148 },
149};
150
151static int __devinit
152tgafb_tc_register(struct device *dev)
153{
154 int status = tgafb_register(dev);
155 if (!status)
156 get_device(dev);
157 return status;
158}
159
160static int __devexit
161tgafb_tc_unregister(struct device *dev)
162{
163 put_device(dev);
164 tgafb_unregister(dev);
165 return 0;
166}
167#endif
168
169
170
171
172
173
174
175static int
176tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
177{
178 struct tga_par *par = (struct tga_par *)info->par;
179
180 if (par->tga_type == TGA_TYPE_8PLANE) {
181 if (var->bits_per_pixel != 8)
182 return -EINVAL;
183 } else {
184 if (var->bits_per_pixel != 32)
185 return -EINVAL;
186 }
187 var->red.length = var->green.length = var->blue.length = 8;
188 if (var->bits_per_pixel == 32) {
189 var->red.offset = 16;
190 var->green.offset = 8;
191 var->blue.offset = 0;
192 }
193
194 if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
195 return -EINVAL;
196 if (var->nonstd)
197 return -EINVAL;
198 if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ)
199 return -EINVAL;
200 if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
201 return -EINVAL;
202
203
204
205 if (var->xres * (par->tga_type == TGA_TYPE_8PLANE ? 1 : 4) % 64)
206 return -EINVAL;
207
208 return 0;
209}
210
211
212
213
214
215static int
216tgafb_set_par(struct fb_info *info)
217{
218 static unsigned int const deep_presets[4] = {
219 0x00004000,
220 0x0000440d,
221 0xffffffff,
222 0x0000441d
223 };
224 static unsigned int const rasterop_presets[4] = {
225 0x00000003,
226 0x00000303,
227 0xffffffff,
228 0x00000303
229 };
230 static unsigned int const mode_presets[4] = {
231 0x00000000,
232 0x00000300,
233 0xffffffff,
234 0x00000300
235 };
236 static unsigned int const base_addr_presets[4] = {
237 0x00000000,
238 0x00000001,
239 0xffffffff,
240 0x00000001
241 };
242
243 struct tga_par *par = (struct tga_par *) info->par;
244 int tga_bus_pci = TGA_BUS_PCI(par->dev);
245 int tga_bus_tc = TGA_BUS_TC(par->dev);
246 u32 htimings, vtimings, pll_freq;
247 u8 tga_type;
248 int i;
249
250
251 htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
252 | (((info->var.xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB));
253 vtimings = (info->var.yres & TGA_VERT_ACTIVE);
254 htimings |= ((info->var.right_margin/4) << 9) & TGA_HORIZ_FP;
255 vtimings |= (info->var.lower_margin << 11) & TGA_VERT_FP;
256 htimings |= ((info->var.hsync_len/4) << 14) & TGA_HORIZ_SYNC;
257 vtimings |= (info->var.vsync_len << 16) & TGA_VERT_SYNC;
258 htimings |= ((info->var.left_margin/4) << 21) & TGA_HORIZ_BP;
259 vtimings |= (info->var.upper_margin << 22) & TGA_VERT_BP;
260
261 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
262 htimings |= TGA_HORIZ_POLARITY;
263 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
264 vtimings |= TGA_VERT_POLARITY;
265
266 par->htimings = htimings;
267 par->vtimings = vtimings;
268
269 par->sync_on_green = !!(info->var.sync & FB_SYNC_ON_GREEN);
270
271
272 par->xres = info->var.xres;
273 par->yres = info->var.yres;
274 par->pll_freq = pll_freq = 1000000000 / info->var.pixclock;
275 par->bits_per_pixel = info->var.bits_per_pixel;
276
277 tga_type = par->tga_type;
278
279
280 TGA_WRITE_REG(par, TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
281
282
283 while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1)
284 continue;
285 mb();
286 TGA_WRITE_REG(par, deep_presets[tga_type] |
287 (par->sync_on_green ? 0x0 : 0x00010000),
288 TGA_DEEP_REG);
289 while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1)
290 continue;
291 mb();
292
293
294 TGA_WRITE_REG(par, rasterop_presets[tga_type], TGA_RASTEROP_REG);
295 TGA_WRITE_REG(par, mode_presets[tga_type], TGA_MODE_REG);
296 TGA_WRITE_REG(par, base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
297
298
299 tgafb_set_pll(par, pll_freq);
300
301
302 TGA_WRITE_REG(par, 0xffffffff, TGA_PLANEMASK_REG);
303 TGA_WRITE_REG(par, 0xffffffff, TGA_PIXELMASK_REG);
304
305
306 TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
307 TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
308
309
310 if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
311
312
313 BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
314 BT485_CMD_0);
315 BT485_WRITE(par, 0x01, BT485_ADDR_PAL_WRITE);
316 BT485_WRITE(par, 0x14, BT485_CMD_3);
317 BT485_WRITE(par, 0x40, BT485_CMD_1);
318 BT485_WRITE(par, 0x20, BT485_CMD_2);
319 BT485_WRITE(par, 0xff, BT485_PIXEL_MASK);
320
321
322 BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
323 TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
324
325 for (i = 0; i < 256 * 3; i += 4) {
326 TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
327 TGA_RAMDAC_REG);
328 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
329 TGA_RAMDAC_REG);
330 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
331 TGA_RAMDAC_REG);
332 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
333 TGA_RAMDAC_REG);
334 }
335
336 } else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
337
338
339 BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40);
340 BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00);
341 BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2,
342 (par->sync_on_green ? 0xc0 : 0x40));
343
344 BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00);
345
346
347 BT459_LOAD_ADDR(par, 0x0000);
348 TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
349
350 for (i = 0; i < 256 * 3; i += 4) {
351 TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
352 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
353 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
354 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
355 }
356
357 } else {
358
359
360 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
361 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
362 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
363 (par->sync_on_green ? 0xc0 : 0x40));
364
365 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
366 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
367 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
368 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
369
370 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
371 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
372 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
373 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
374
375
376 BT463_LOAD_ADDR(par, 0x0000);
377 TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
378
379#ifdef CONFIG_HW_CONSOLE
380 for (i = 0; i < 16; i++) {
381 int j = color_table[i];
382
383 TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
384 TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
385 TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
386 }
387 for (i = 0; i < 512 * 3; i += 4) {
388#else
389 for (i = 0; i < 528 * 3; i += 4) {
390#endif
391 TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
392 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
393 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
394 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
395 }
396
397
398 while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
399 continue;
400 TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
401 mb();
402 while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
403 continue;
404 TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
405
406 BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
407 TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
408
409 for (i = 0; i < 16; i++) {
410 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
411 TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
412 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
413 }
414
415 }
416
417
418 TGA_WRITE_REG(par, TGA_VALID_VIDEO, TGA_VALID_REG);
419
420 return 0;
421}
422
423#define DIFFCHECK(X) \
424do { \
425 if (m <= 0x3f) { \
426 int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
427 if (delta < 0) \
428 delta = -delta; \
429 if (delta < min_diff) \
430 min_diff = delta, vm = m, va = a, vr = r; \
431 } \
432} while (0)
433
434static void
435tgafb_set_pll(struct tga_par *par, int f)
436{
437 int n, shift, base, min_diff, target;
438 int r,a,m,vm = 34, va = 1, vr = 30;
439
440 for (r = 0 ; r < 12 ; r++)
441 TGA_WRITE_REG(par, !r, TGA_CLOCK_REG);
442
443 if (f > TGA_PLL_MAX_FREQ)
444 f = TGA_PLL_MAX_FREQ;
445
446 if (f >= TGA_PLL_MAX_FREQ / 2)
447 shift = 0;
448 else if (f >= TGA_PLL_MAX_FREQ / 4)
449 shift = 1;
450 else
451 shift = 2;
452
453 TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG);
454 TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG);
455
456 for (r = 0 ; r < 10 ; r++)
457 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
458
459 if (f <= 120000) {
460 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
461 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
462 }
463 else if (f <= 200000) {
464 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
465 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
466 }
467 else {
468 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
469 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
470 }
471
472 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
473 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
474 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
475 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
476 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
477 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
478
479 target = (f << shift) / TGA_PLL_BASE_FREQ;
480 min_diff = TGA_PLL_MAX_FREQ;
481
482 r = 7 / target;
483 if (!r) r = 1;
484
485 base = target * r;
486 while (base < 449) {
487 for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
488 m = ((n + 3) / 7) - 1;
489 a = 0;
490 DIFFCHECK((m + 1) * 7);
491 m++;
492 DIFFCHECK((m + 1) * 7);
493 m = (n / 6) - 1;
494 if ((a = n % 6))
495 DIFFCHECK(n);
496 }
497 r++;
498 base += target;
499 }
500
501 vr--;
502
503 for (r = 0; r < 8; r++)
504 TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG);
505 for (r = 0; r < 8 ; r++)
506 TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG);
507 for (r = 0; r < 7 ; r++)
508 TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG);
509 TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);
510}
511
512
513
514
515
516
517
518
519
520
521
522static int
523tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
524 unsigned transp, struct fb_info *info)
525{
526 struct tga_par *par = (struct tga_par *) info->par;
527 int tga_bus_pci = TGA_BUS_PCI(par->dev);
528 int tga_bus_tc = TGA_BUS_TC(par->dev);
529
530 if (regno > 255)
531 return 1;
532 red >>= 8;
533 green >>= 8;
534 blue >>= 8;
535
536 if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
537 BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
538 TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
539 TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
540 TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
541 TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
542 } else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
543 BT459_LOAD_ADDR(par, regno);
544 TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
545 TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
546 TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
547 TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
548 } else {
549 if (regno < 16) {
550 u32 value = (regno << 16) | (regno << 8) | regno;
551 ((u32 *)info->pseudo_palette)[regno] = value;
552 }
553 BT463_LOAD_ADDR(par, regno);
554 TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
555 TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
556 TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
557 TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
558 }
559
560 return 0;
561}
562
563
564
565
566
567
568
569static int
570tgafb_blank(int blank, struct fb_info *info)
571{
572 struct tga_par *par = (struct tga_par *) info->par;
573 u32 vhcr, vvcr, vvvr;
574 unsigned long flags;
575
576 local_irq_save(flags);
577
578 vhcr = TGA_READ_REG(par, TGA_HORIZ_REG);
579 vvcr = TGA_READ_REG(par, TGA_VERT_REG);
580 vvvr = TGA_READ_REG(par, TGA_VALID_REG);
581 vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
582
583 switch (blank) {
584 case FB_BLANK_UNBLANK:
585 if (par->vesa_blanked) {
586 TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG);
587 TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG);
588 par->vesa_blanked = 0;
589 }
590 TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
591 break;
592
593 case FB_BLANK_NORMAL:
594 TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK,
595 TGA_VALID_REG);
596 break;
597
598 case FB_BLANK_VSYNC_SUSPEND:
599 TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
600 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
601 par->vesa_blanked = 1;
602 break;
603
604 case FB_BLANK_HSYNC_SUSPEND:
605 TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
606 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
607 par->vesa_blanked = 1;
608 break;
609
610 case FB_BLANK_POWERDOWN:
611 TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
612 TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
613 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
614 par->vesa_blanked = 1;
615 break;
616 }
617
618 local_irq_restore(flags);
619 return 0;
620}
621
622
623
624
625
626
627static void
628tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
629{
630 struct tga_par *par = (struct tga_par *) info->par;
631 u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
632 unsigned long rincr, line_length, shift, pos, is8bpp;
633 unsigned long i, j;
634 const unsigned char *data;
635 void __iomem *regs_base;
636 void __iomem *fb_base;
637
638 is8bpp = info->var.bits_per_pixel == 8;
639
640 dx = image->dx;
641 dy = image->dy;
642 width = image->width;
643 height = image->height;
644 vxres = info->var.xres_virtual;
645 vyres = info->var.yres_virtual;
646 line_length = info->fix.line_length;
647 rincr = (width + 7) / 8;
648
649
650 if (unlikely(width == 0))
651 return;
652
653 if (dx > vxres || dy > vyres)
654 return;
655 if (dx + width > vxres)
656 width = vxres - dx;
657 if (dy + height > vyres)
658 height = vyres - dy;
659
660 regs_base = par->tga_regs_base;
661 fb_base = par->tga_fb_base;
662
663
664
665
666 fgcolor = image->fg_color;
667 bgcolor = image->bg_color;
668 if (is8bpp) {
669 fgcolor |= fgcolor << 8;
670 fgcolor |= fgcolor << 16;
671 bgcolor |= bgcolor << 8;
672 bgcolor |= bgcolor << 16;
673 } else {
674 if (fgcolor < 16)
675 fgcolor = ((u32 *)info->pseudo_palette)[fgcolor];
676 if (bgcolor < 16)
677 bgcolor = ((u32 *)info->pseudo_palette)[bgcolor];
678 }
679 __raw_writel(fgcolor, regs_base + TGA_FOREGROUND_REG);
680 __raw_writel(bgcolor, regs_base + TGA_BACKGROUND_REG);
681
682
683
684 pos = dy * line_length;
685 if (is8bpp) {
686 pos += dx;
687 shift = pos & 3;
688 pos &= -4;
689 } else {
690 pos += dx * 4;
691 shift = (pos & 7) >> 2;
692 pos &= -8;
693 }
694
695 data = (const unsigned char *) image->data;
696
697
698 __raw_writel((is8bpp
699 ? TGA_MODE_SBM_8BPP | TGA_MODE_OPAQUE_STIPPLE
700 : TGA_MODE_SBM_24BPP | TGA_MODE_OPAQUE_STIPPLE),
701 regs_base + TGA_MODE_REG);
702
703 if (width + shift <= 32) {
704 unsigned long bwidth;
705
706
707
708
709
710 pixelmask = (2ul << (width - 1)) - 1;
711 pixelmask <<= shift;
712 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
713 wmb();
714
715 bwidth = (width + 7) / 8;
716
717 for (i = 0; i < height; ++i) {
718 u32 mask = 0;
719
720
721
722 for (j = 0; j < bwidth; ++j)
723 mask |= bitrev8(data[j]) << (j * 8);
724
725 __raw_writel(mask << shift, fb_base + pos);
726
727 pos += line_length;
728 data += rincr;
729 }
730 wmb();
731 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
732 } else if (shift == 0) {
733 unsigned long pos0 = pos;
734 const unsigned char *data0 = data;
735 unsigned long bincr = (is8bpp ? 8 : 8*4);
736 unsigned long bwidth;
737
738
739
740
741
742
743
744 wmb();
745
746 bwidth = (width / 8) & -4;
747 for (i = 0; i < height; ++i) {
748 for (j = 0; j < bwidth; j += 4) {
749 u32 mask = 0;
750 mask |= bitrev8(data[j+0]) << (0 * 8);
751 mask |= bitrev8(data[j+1]) << (1 * 8);
752 mask |= bitrev8(data[j+2]) << (2 * 8);
753 mask |= bitrev8(data[j+3]) << (3 * 8);
754 __raw_writel(mask, fb_base + pos + j*bincr);
755 }
756 pos += line_length;
757 data += rincr;
758 }
759 wmb();
760
761 pixelmask = (1ul << (width & 31)) - 1;
762 if (pixelmask) {
763 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
764 wmb();
765
766 pos = pos0 + bwidth*bincr;
767 data = data0 + bwidth;
768 bwidth = ((width & 31) + 7) / 8;
769
770 for (i = 0; i < height; ++i) {
771 u32 mask = 0;
772 for (j = 0; j < bwidth; ++j)
773 mask |= bitrev8(data[j]) << (j * 8);
774 __raw_writel(mask, fb_base + pos);
775 pos += line_length;
776 data += rincr;
777 }
778 wmb();
779 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
780 }
781 } else {
782 unsigned long pos0 = pos;
783 const unsigned char *data0 = data;
784 unsigned long bincr = (is8bpp ? 8 : 8*4);
785 unsigned long bwidth;
786
787
788
789
790
791
792 pixelmask = 0xffff << shift;
793 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
794 wmb();
795
796 bwidth = (width / 8) & -2;
797 for (i = 0; i < height; ++i) {
798 for (j = 0; j < bwidth; j += 2) {
799 u32 mask = 0;
800 mask |= bitrev8(data[j+0]) << (0 * 8);
801 mask |= bitrev8(data[j+1]) << (1 * 8);
802 mask <<= shift;
803 __raw_writel(mask, fb_base + pos + j*bincr);
804 }
805 pos += line_length;
806 data += rincr;
807 }
808 wmb();
809
810 pixelmask = ((1ul << (width & 15)) - 1) << shift;
811 if (pixelmask) {
812 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
813 wmb();
814
815 pos = pos0 + bwidth*bincr;
816 data = data0 + bwidth;
817 bwidth = (width & 15) > 8;
818
819 for (i = 0; i < height; ++i) {
820 u32 mask = bitrev8(data[0]);
821 if (bwidth)
822 mask |= bitrev8(data[1]) << 8;
823 mask <<= shift;
824 __raw_writel(mask, fb_base + pos);
825 pos += line_length;
826 data += rincr;
827 }
828 wmb();
829 }
830 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
831 }
832
833
834 __raw_writel((is8bpp
835 ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
836 : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
837 regs_base + TGA_MODE_REG);
838}
839
840static void
841tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image)
842{
843 struct tga_par *par = (struct tga_par *) info->par;
844 u32 color, dx, dy, width, height, vxres, vyres;
845 u32 *palette = ((u32 *)info->pseudo_palette);
846 unsigned long pos, line_length, i, j;
847 const unsigned char *data;
848 void __iomem *regs_base, *fb_base;
849
850 dx = image->dx;
851 dy = image->dy;
852 width = image->width;
853 height = image->height;
854 vxres = info->var.xres_virtual;
855 vyres = info->var.yres_virtual;
856 line_length = info->fix.line_length;
857
858
859 if (dx > vxres || dy > vyres)
860 return;
861 if (dx + width > vxres)
862 width = vxres - dx;
863 if (dy + height > vyres)
864 height = vyres - dy;
865
866 regs_base = par->tga_regs_base;
867 fb_base = par->tga_fb_base;
868
869 pos = dy * line_length + (dx * 4);
870 data = image->data;
871
872
873 for (i = 0; i < height; i++) {
874 for (j = 0; j < width; j++) {
875 color = palette[*data++];
876 __raw_writel(color, fb_base + pos + j*4);
877 }
878 pos += line_length;
879 }
880}
881
882
883
884
885
886
887
888
889
890static void
891tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
892{
893 unsigned int is8bpp = info->var.bits_per_pixel == 8;
894
895
896 if (image->depth == 1) {
897 tgafb_mono_imageblit(info, image);
898 return;
899 }
900
901
902
903
904
905 if (image->depth == info->var.bits_per_pixel) {
906 cfb_imageblit(info, image);
907 return;
908 }
909
910
911 if (!is8bpp && image->depth == 8) {
912 tgafb_clut_imageblit(info, image);
913 return;
914 }
915
916
917}
918
919
920
921
922
923
924
925
926
927static void
928tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
929{
930 struct tga_par *par = (struct tga_par *) info->par;
931 int is8bpp = info->var.bits_per_pixel == 8;
932 u32 dx, dy, width, height, vxres, vyres, color;
933 unsigned long pos, align, line_length, i, j;
934 void __iomem *regs_base;
935 void __iomem *fb_base;
936
937 dx = rect->dx;
938 dy = rect->dy;
939 width = rect->width;
940 height = rect->height;
941 vxres = info->var.xres_virtual;
942 vyres = info->var.yres_virtual;
943 line_length = info->fix.line_length;
944 regs_base = par->tga_regs_base;
945 fb_base = par->tga_fb_base;
946
947
948 if (dx > vxres || dy > vyres || !width || !height)
949 return;
950 if (dx + width > vxres)
951 width = vxres - dx;
952 if (dy + height > vyres)
953 height = vyres - dy;
954
955 pos = dy * line_length + dx * (is8bpp ? 1 : 4);
956
957
958
959
960
961 if (rect->rop != ROP_COPY) {
962 cfb_fillrect(info, rect);
963 return;
964 }
965
966
967 color = rect->color;
968 if (is8bpp) {
969 color |= color << 8;
970 color |= color << 16;
971 __raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
972 __raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
973 } else {
974 if (color < 16)
975 color = ((u32 *)info->pseudo_palette)[color];
976 __raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
977 __raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
978 __raw_writel(color, regs_base + TGA_BLOCK_COLOR2_REG);
979 __raw_writel(color, regs_base + TGA_BLOCK_COLOR3_REG);
980 __raw_writel(color, regs_base + TGA_BLOCK_COLOR4_REG);
981 __raw_writel(color, regs_base + TGA_BLOCK_COLOR5_REG);
982 __raw_writel(color, regs_base + TGA_BLOCK_COLOR6_REG);
983 __raw_writel(color, regs_base + TGA_BLOCK_COLOR7_REG);
984 }
985
986
987
988 __raw_writel(0xffffffff, regs_base + TGA_DATA_REG);
989
990
991 __raw_writel((is8bpp
992 ? TGA_MODE_SBM_8BPP | TGA_MODE_BLOCK_FILL
993 : TGA_MODE_SBM_24BPP | TGA_MODE_BLOCK_FILL),
994 regs_base + TGA_MODE_REG);
995 wmb();
996
997
998
999
1000 if (width == line_length)
1001 width *= height, height = 1;
1002
1003
1004
1005
1006 align = (pos & 3) << 16;
1007 pos &= -4;
1008
1009 if (width <= 2048) {
1010 u32 data;
1011
1012 data = (width - 1) | align;
1013
1014 for (i = 0; i < height; ++i) {
1015 __raw_writel(data, fb_base + pos);
1016 pos += line_length;
1017 }
1018 } else {
1019 unsigned long Bpp = (is8bpp ? 1 : 4);
1020 unsigned long nwidth = width & -2048;
1021 u32 fdata, ldata;
1022
1023 fdata = (2048 - 1) | align;
1024 ldata = ((width & 2047) - 1) | align;
1025
1026 for (i = 0; i < height; ++i) {
1027 for (j = 0; j < nwidth; j += 2048)
1028 __raw_writel(fdata, fb_base + pos + j*Bpp);
1029 if (j < width)
1030 __raw_writel(ldata, fb_base + pos + j*Bpp);
1031 pos += line_length;
1032 }
1033 }
1034 wmb();
1035
1036
1037 __raw_writel((is8bpp
1038 ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
1039 : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
1040 regs_base + TGA_MODE_REG);
1041}
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057static inline void
1058copyarea_line_8bpp(struct fb_info *info, u32 dy, u32 sy,
1059 u32 height, u32 width)
1060{
1061 struct tga_par *par = (struct tga_par *) info->par;
1062 void __iomem *tga_regs = par->tga_regs_base;
1063 unsigned long dpos, spos, i, n64;
1064
1065
1066 __raw_writel(TGA_MODE_SBM_8BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1067 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1068 wmb();
1069
1070 n64 = (height * width) / 64;
1071
1072 if (sy < dy) {
1073 spos = (sy + height) * width;
1074 dpos = (dy + height) * width;
1075
1076 for (i = 0; i < n64; ++i) {
1077 spos -= 64;
1078 dpos -= 64;
1079 __raw_writel(spos, tga_regs+TGA_COPY64_SRC);
1080 wmb();
1081 __raw_writel(dpos, tga_regs+TGA_COPY64_DST);
1082 wmb();
1083 }
1084 } else {
1085 spos = sy * width;
1086 dpos = dy * width;
1087
1088 for (i = 0; i < n64; ++i) {
1089 __raw_writel(spos, tga_regs+TGA_COPY64_SRC);
1090 wmb();
1091 __raw_writel(dpos, tga_regs+TGA_COPY64_DST);
1092 wmb();
1093 spos += 64;
1094 dpos += 64;
1095 }
1096 }
1097
1098
1099 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1100}
1101
1102static inline void
1103copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
1104 u32 height, u32 width)
1105{
1106 struct tga_par *par = (struct tga_par *) info->par;
1107 void __iomem *tga_regs = par->tga_regs_base;
1108 void __iomem *tga_fb = par->tga_fb_base;
1109 void __iomem *src;
1110 void __iomem *dst;
1111 unsigned long i, n16;
1112
1113
1114 __raw_writel(TGA_MODE_SBM_24BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1115 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1116 wmb();
1117
1118 n16 = (height * width) / 16;
1119
1120 if (sy < dy) {
1121 src = tga_fb + (sy + height) * width * 4;
1122 dst = tga_fb + (dy + height) * width * 4;
1123
1124 for (i = 0; i < n16; ++i) {
1125 src -= 64;
1126 dst -= 64;
1127 __raw_writel(0xffff, src);
1128 wmb();
1129 __raw_writel(0xffff, dst);
1130 wmb();
1131 }
1132 } else {
1133 src = tga_fb + sy * width * 4;
1134 dst = tga_fb + dy * width * 4;
1135
1136 for (i = 0; i < n16; ++i) {
1137 __raw_writel(0xffff, src);
1138 wmb();
1139 __raw_writel(0xffff, dst);
1140 wmb();
1141 src += 64;
1142 dst += 64;
1143 }
1144 }
1145
1146
1147 __raw_writel(TGA_MODE_SBM_24BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1148}
1149
1150
1151static inline void
1152copyarea_foreward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
1153 u32 height, u32 width, u32 line_length)
1154{
1155 struct tga_par *par = (struct tga_par *) info->par;
1156 unsigned long i, copied, left;
1157 unsigned long dpos, spos, dalign, salign, yincr;
1158 u32 smask_first, dmask_first, dmask_last;
1159 int pixel_shift, need_prime, need_second;
1160 unsigned long n64, n32, xincr_first;
1161 void __iomem *tga_regs;
1162 void __iomem *tga_fb;
1163
1164 yincr = line_length;
1165 if (dy > sy) {
1166 dy += height - 1;
1167 sy += height - 1;
1168 yincr = -yincr;
1169 }
1170
1171
1172
1173 dpos = dy * line_length + dx;
1174 spos = sy * line_length + sx;
1175 dalign = dpos & 7;
1176 salign = spos & 7;
1177 dpos &= -8;
1178 spos &= -8;
1179
1180
1181
1182 if (dalign >= salign)
1183 pixel_shift = dalign - salign;
1184 else
1185 pixel_shift = 8 - (salign - dalign);
1186
1187
1188
1189 need_prime = (salign > dalign);
1190 if (need_prime)
1191 dpos -= 8;
1192
1193
1194
1195 copied = 32 - (dalign + (dpos & 31));
1196 if (copied == 32)
1197 copied = 0;
1198 xincr_first = (copied + 7) & -8;
1199 smask_first = dmask_first = (1ul << copied) - 1;
1200 smask_first <<= salign;
1201 dmask_first <<= dalign + need_prime*8;
1202 if (need_prime && copied > 24)
1203 copied -= 8;
1204 left = width - copied;
1205
1206
1207 if (copied > width) {
1208 u32 t;
1209 t = (1ul << width) - 1;
1210 t <<= dalign + need_prime*8;
1211 dmask_first &= t;
1212 left = 0;
1213 }
1214
1215
1216
1217 n64 = need_second = 0;
1218 if ((dpos & 63) == (spos & 63)
1219 && (height == 1 || line_length % 64 == 0)) {
1220
1221 need_second = (dpos + xincr_first) & 63;
1222 if ((need_second & 32) != need_second)
1223 printk(KERN_ERR "tgafb: need_second wrong\n");
1224 if (left >= need_second + 64) {
1225 left -= need_second;
1226 n64 = left / 64;
1227 left %= 64;
1228 } else
1229 need_second = 0;
1230 }
1231
1232
1233
1234 n32 = left / 32;
1235 left %= 32;
1236
1237
1238 dmask_last = (1ul << left) - 1;
1239
1240 tga_regs = par->tga_regs_base;
1241 tga_fb = par->tga_fb_base;
1242
1243
1244 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1245 __raw_writel(pixel_shift, tga_regs+TGA_PIXELSHIFT_REG);
1246 wmb();
1247
1248 for (i = 0; i < height; ++i) {
1249 unsigned long j;
1250 void __iomem *sfb;
1251 void __iomem *dfb;
1252
1253 sfb = tga_fb + spos;
1254 dfb = tga_fb + dpos;
1255 if (dmask_first) {
1256 __raw_writel(smask_first, sfb);
1257 wmb();
1258 __raw_writel(dmask_first, dfb);
1259 wmb();
1260 sfb += xincr_first;
1261 dfb += xincr_first;
1262 }
1263
1264 if (need_second) {
1265 __raw_writel(0xffffffff, sfb);
1266 wmb();
1267 __raw_writel(0xffffffff, dfb);
1268 wmb();
1269 sfb += 32;
1270 dfb += 32;
1271 }
1272
1273 if (n64 && (((unsigned long)sfb | (unsigned long)dfb) & 63))
1274 printk(KERN_ERR
1275 "tgafb: misaligned copy64 (s:%p, d:%p)\n",
1276 sfb, dfb);
1277
1278 for (j = 0; j < n64; ++j) {
1279 __raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
1280 wmb();
1281 __raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
1282 wmb();
1283 sfb += 64;
1284 dfb += 64;
1285 }
1286
1287 for (j = 0; j < n32; ++j) {
1288 __raw_writel(0xffffffff, sfb);
1289 wmb();
1290 __raw_writel(0xffffffff, dfb);
1291 wmb();
1292 sfb += 32;
1293 dfb += 32;
1294 }
1295
1296 if (dmask_last) {
1297 __raw_writel(0xffffffff, sfb);
1298 wmb();
1299 __raw_writel(dmask_last, dfb);
1300 wmb();
1301 }
1302
1303 spos += yincr;
1304 dpos += yincr;
1305 }
1306
1307
1308 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1309}
1310
1311
1312static inline void
1313copyarea_backward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
1314 u32 height, u32 width, u32 line_length,
1315 const struct fb_copyarea *area)
1316{
1317 struct tga_par *par = (struct tga_par *) info->par;
1318 unsigned long i, left, yincr;
1319 unsigned long depos, sepos, dealign, sealign;
1320 u32 mask_first, mask_last;
1321 unsigned long n32;
1322 void __iomem *tga_regs;
1323 void __iomem *tga_fb;
1324
1325 yincr = line_length;
1326 if (dy > sy) {
1327 dy += height - 1;
1328 sy += height - 1;
1329 yincr = -yincr;
1330 }
1331
1332
1333
1334 depos = dy * line_length + dx + width;
1335 sepos = sy * line_length + sx + width;
1336 dealign = depos & 7;
1337 sealign = sepos & 7;
1338
1339
1340
1341
1342
1343
1344 if (dealign != sealign) {
1345 cfb_copyarea(info, area);
1346 return;
1347 }
1348
1349
1350
1351 mask_first = (1ul << dealign) - 1;
1352 left = width - dealign;
1353
1354
1355 if (dealign > width) {
1356 mask_first ^= (1ul << (dealign - width)) - 1;
1357 left = 0;
1358 }
1359
1360
1361 n32 = left / 32;
1362 left %= 32;
1363
1364
1365 mask_last = -1 << (32 - left);
1366
1367 tga_regs = par->tga_regs_base;
1368 tga_fb = par->tga_fb_base;
1369
1370
1371 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1372 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1373 wmb();
1374
1375 for (i = 0; i < height; ++i) {
1376 unsigned long j;
1377 void __iomem *sfb;
1378 void __iomem *dfb;
1379
1380 sfb = tga_fb + sepos;
1381 dfb = tga_fb + depos;
1382 if (mask_first) {
1383 __raw_writel(mask_first, sfb);
1384 wmb();
1385 __raw_writel(mask_first, dfb);
1386 wmb();
1387 }
1388
1389 for (j = 0; j < n32; ++j) {
1390 sfb -= 32;
1391 dfb -= 32;
1392 __raw_writel(0xffffffff, sfb);
1393 wmb();
1394 __raw_writel(0xffffffff, dfb);
1395 wmb();
1396 }
1397
1398 if (mask_last) {
1399 sfb -= 32;
1400 dfb -= 32;
1401 __raw_writel(mask_last, sfb);
1402 wmb();
1403 __raw_writel(mask_last, dfb);
1404 wmb();
1405 }
1406
1407 sepos += yincr;
1408 depos += yincr;
1409 }
1410
1411
1412 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1413}
1414
1415static void
1416tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1417{
1418 unsigned long dx, dy, width, height, sx, sy, vxres, vyres;
1419 unsigned long line_length, bpp;
1420
1421 dx = area->dx;
1422 dy = area->dy;
1423 width = area->width;
1424 height = area->height;
1425 sx = area->sx;
1426 sy = area->sy;
1427 vxres = info->var.xres_virtual;
1428 vyres = info->var.yres_virtual;
1429 line_length = info->fix.line_length;
1430
1431
1432 if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)
1433 return;
1434
1435
1436 if (dx + width > vxres)
1437 width = vxres - dx;
1438 if (dy + height > vyres)
1439 height = vyres - dy;
1440
1441
1442 if (sx + width > vxres || sy + height > vyres)
1443 return;
1444
1445 bpp = info->var.bits_per_pixel;
1446
1447
1448 if (width * (bpp >> 3) == line_length) {
1449 if (bpp == 8)
1450 copyarea_line_8bpp(info, dy, sy, height, width);
1451 else
1452 copyarea_line_32bpp(info, dy, sy, height, width);
1453 }
1454
1455
1456
1457
1458 else if (bpp == 32)
1459 cfb_copyarea(info, area);
1460
1461
1462
1463 else if (dy == sy && dx > sx && dx < sx + width)
1464 copyarea_backward_8bpp(info, dx, dy, sx, sy, height,
1465 width, line_length, area);
1466 else
1467 copyarea_foreward_8bpp(info, dx, dy, sx, sy, height,
1468 width, line_length);
1469}
1470
1471
1472
1473
1474
1475
1476static void
1477tgafb_init_fix(struct fb_info *info)
1478{
1479 struct tga_par *par = (struct tga_par *)info->par;
1480 int tga_bus_pci = TGA_BUS_PCI(par->dev);
1481 int tga_bus_tc = TGA_BUS_TC(par->dev);
1482 u8 tga_type = par->tga_type;
1483 const char *tga_type_name = NULL;
1484
1485 switch (tga_type) {
1486 case TGA_TYPE_8PLANE:
1487 if (tga_bus_pci)
1488 tga_type_name = "Digital ZLXp-E1";
1489 if (tga_bus_tc)
1490 tga_type_name = "Digital ZLX-E1";
1491 break;
1492 case TGA_TYPE_24PLANE:
1493 if (tga_bus_pci)
1494 tga_type_name = "Digital ZLXp-E2";
1495 if (tga_bus_tc)
1496 tga_type_name = "Digital ZLX-E2";
1497 break;
1498 case TGA_TYPE_24PLUSZ:
1499 if (tga_bus_pci)
1500 tga_type_name = "Digital ZLXp-E3";
1501 if (tga_bus_tc)
1502 tga_type_name = "Digital ZLX-E3";
1503 break;
1504 default:
1505 tga_type_name = "Unknown";
1506 break;
1507 }
1508
1509 strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
1510
1511 info->fix.type = FB_TYPE_PACKED_PIXELS;
1512 info->fix.type_aux = 0;
1513 info->fix.visual = (tga_type == TGA_TYPE_8PLANE
1514 ? FB_VISUAL_PSEUDOCOLOR
1515 : FB_VISUAL_DIRECTCOLOR);
1516
1517 info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
1518 info->fix.smem_start = (size_t) par->tga_fb_base;
1519 info->fix.smem_len = info->fix.line_length * par->yres;
1520 info->fix.mmio_start = (size_t) par->tga_regs_base;
1521 info->fix.mmio_len = 512;
1522
1523 info->fix.xpanstep = 0;
1524 info->fix.ypanstep = 0;
1525 info->fix.ywrapstep = 0;
1526
1527 info->fix.accel = FB_ACCEL_DEC_TGA;
1528
1529
1530
1531
1532
1533 if (tga_type != TGA_TYPE_8PLANE) {
1534 info->var.red.length = 8;
1535 info->var.green.length = 8;
1536 info->var.blue.length = 8;
1537 info->var.red.offset = 16;
1538 info->var.green.offset = 8;
1539 info->var.blue.offset = 0;
1540 }
1541}
1542
1543static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1544{
1545
1546 tgafb_set_par(info);
1547 return 0;
1548}
1549
1550static int __devinit
1551tgafb_register(struct device *dev)
1552{
1553 static const struct fb_videomode modedb_tc = {
1554
1555 "1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,
1556 FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED
1557 };
1558
1559 static unsigned int const fb_offset_presets[4] = {
1560 TGA_8PLANE_FB_OFFSET,
1561 TGA_24PLANE_FB_OFFSET,
1562 0xffffffff,
1563 TGA_24PLUSZ_FB_OFFSET
1564 };
1565
1566 const struct fb_videomode *modedb_tga = NULL;
1567 resource_size_t bar0_start = 0, bar0_len = 0;
1568 const char *mode_option_tga = NULL;
1569 int tga_bus_pci = TGA_BUS_PCI(dev);
1570 int tga_bus_tc = TGA_BUS_TC(dev);
1571 unsigned int modedbsize_tga = 0;
1572 void __iomem *mem_base;
1573 struct fb_info *info;
1574 struct tga_par *par;
1575 u8 tga_type;
1576 int ret = 0;
1577
1578
1579 if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) {
1580 printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
1581 return -ENODEV;
1582 }
1583
1584
1585 info = framebuffer_alloc(sizeof(struct tga_par), dev);
1586 if (!info) {
1587 printk(KERN_ERR "tgafb: Cannot allocate memory\n");
1588 return -ENOMEM;
1589 }
1590
1591 par = info->par;
1592 dev_set_drvdata(dev, info);
1593
1594
1595 ret = -ENODEV;
1596 if (tga_bus_pci) {
1597 bar0_start = pci_resource_start(to_pci_dev(dev), 0);
1598 bar0_len = pci_resource_len(to_pci_dev(dev), 0);
1599 }
1600 if (tga_bus_tc) {
1601 bar0_start = to_tc_dev(dev)->resource.start;
1602 bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
1603 }
1604 if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
1605 printk(KERN_ERR "tgafb: cannot reserve FB region\n");
1606 goto err0;
1607 }
1608
1609
1610 mem_base = ioremap_nocache(bar0_start, bar0_len);
1611 if (!mem_base) {
1612 printk(KERN_ERR "tgafb: Cannot map MMIO\n");
1613 goto err1;
1614 }
1615
1616
1617 tga_type = (readl(mem_base) >> 12) & 0x0f;
1618 par->dev = dev;
1619 par->tga_mem_base = mem_base;
1620 par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
1621 par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
1622 par->tga_type = tga_type;
1623 if (tga_bus_pci)
1624 par->tga_chip_rev = (to_pci_dev(dev))->revision;
1625 if (tga_bus_tc)
1626 par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
1627
1628
1629 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
1630 FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
1631 info->fbops = &tgafb_ops;
1632 info->screen_base = par->tga_fb_base;
1633 info->pseudo_palette = par->palette;
1634
1635
1636 if (tga_bus_pci) {
1637 mode_option_tga = mode_option_pci;
1638 }
1639 if (tga_bus_tc) {
1640 mode_option_tga = mode_option_tc;
1641 modedb_tga = &modedb_tc;
1642 modedbsize_tga = 1;
1643 }
1644 ret = fb_find_mode(&info->var, info,
1645 mode_option ? mode_option : mode_option_tga,
1646 modedb_tga, modedbsize_tga, NULL,
1647 tga_type == TGA_TYPE_8PLANE ? 8 : 32);
1648 if (ret == 0 || ret == 4) {
1649 printk(KERN_ERR "tgafb: Could not find valid video mode\n");
1650 ret = -EINVAL;
1651 goto err1;
1652 }
1653
1654 if (fb_alloc_cmap(&info->cmap, 256, 0)) {
1655 printk(KERN_ERR "tgafb: Could not allocate color map\n");
1656 ret = -ENOMEM;
1657 goto err1;
1658 }
1659
1660 tgafb_set_par(info);
1661 tgafb_init_fix(info);
1662
1663 if (register_framebuffer(info) < 0) {
1664 printk(KERN_ERR "tgafb: Could not register framebuffer\n");
1665 ret = -EINVAL;
1666 goto err2;
1667 }
1668
1669 if (tga_bus_pci) {
1670 pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
1671 par->tga_chip_rev);
1672 pr_info("tgafb: at PCI bus %d, device %d, function %d\n",
1673 to_pci_dev(dev)->bus->number,
1674 PCI_SLOT(to_pci_dev(dev)->devfn),
1675 PCI_FUNC(to_pci_dev(dev)->devfn));
1676 }
1677 if (tga_bus_tc)
1678 pr_info("tgafb: SFB+ detected, rev=0x%02x\n",
1679 par->tga_chip_rev);
1680 pr_info("fb%d: %s frame buffer device at 0x%lx\n",
1681 info->node, info->fix.id, (long)bar0_start);
1682
1683 return 0;
1684
1685 err2:
1686 fb_dealloc_cmap(&info->cmap);
1687 err1:
1688 if (mem_base)
1689 iounmap(mem_base);
1690 release_mem_region(bar0_start, bar0_len);
1691 err0:
1692 framebuffer_release(info);
1693 return ret;
1694}
1695
1696static void __devexit
1697tgafb_unregister(struct device *dev)
1698{
1699 resource_size_t bar0_start = 0, bar0_len = 0;
1700 int tga_bus_pci = TGA_BUS_PCI(dev);
1701 int tga_bus_tc = TGA_BUS_TC(dev);
1702 struct fb_info *info = NULL;
1703 struct tga_par *par;
1704
1705 info = dev_get_drvdata(dev);
1706 if (!info)
1707 return;
1708
1709 par = info->par;
1710 unregister_framebuffer(info);
1711 fb_dealloc_cmap(&info->cmap);
1712 iounmap(par->tga_mem_base);
1713 if (tga_bus_pci) {
1714 bar0_start = pci_resource_start(to_pci_dev(dev), 0);
1715 bar0_len = pci_resource_len(to_pci_dev(dev), 0);
1716 }
1717 if (tga_bus_tc) {
1718 bar0_start = to_tc_dev(dev)->resource.start;
1719 bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
1720 }
1721 release_mem_region(bar0_start, bar0_len);
1722 framebuffer_release(info);
1723}
1724
1725static void __devexit
1726tgafb_exit(void)
1727{
1728 tc_unregister_driver(&tgafb_tc_driver);
1729 pci_unregister_driver(&tgafb_pci_driver);
1730}
1731
1732#ifndef MODULE
1733static int __devinit
1734tgafb_setup(char *arg)
1735{
1736 char *this_opt;
1737
1738 if (arg && *arg) {
1739 while ((this_opt = strsep(&arg, ","))) {
1740 if (!*this_opt)
1741 continue;
1742 if (!strncmp(this_opt, "mode:", 5))
1743 mode_option = this_opt+5;
1744 else
1745 printk(KERN_ERR
1746 "tgafb: unknown parameter %s\n",
1747 this_opt);
1748 }
1749 }
1750
1751 return 0;
1752}
1753#endif
1754
1755static int __devinit
1756tgafb_init(void)
1757{
1758 int status;
1759#ifndef MODULE
1760 char *option = NULL;
1761
1762 if (fb_get_options("tgafb", &option))
1763 return -ENODEV;
1764 tgafb_setup(option);
1765#endif
1766 status = pci_register_driver(&tgafb_pci_driver);
1767 if (!status)
1768 status = tc_register_driver(&tgafb_tc_driver);
1769 return status;
1770}
1771
1772
1773
1774
1775
1776module_init(tgafb_init);
1777module_exit(tgafb_exit);
1778
1779MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset");
1780MODULE_LICENSE("GPL");
1781