aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c3732
-rw-r--r--drivers/video/atmel_lcdfb.c41
-rw-r--r--drivers/video/cirrusfb.c268
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/display/Kconfig24
-rw-r--r--drivers/video/display/Makefile6
-rw-r--r--drivers/video/display/display-sysfs.c219
-rw-r--r--drivers/video/mxsfb.c13
-rw-r--r--drivers/video/nuc900fb.c13
-rw-r--r--drivers/video/omap/lcd_mipid.c1
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c1
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c1
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c1
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c1
-rw-r--r--drivers/video/pxa168fb.c12
-rw-r--r--drivers/video/pxa3xx-gcu.c15
-rw-r--r--drivers/video/s3c-fb.c91
-rw-r--r--drivers/video/s3c2410fb.c29
-rw-r--r--drivers/video/sbuslib.c2
-rw-r--r--drivers/video/sh7760fb.c13
-rw-r--r--drivers/video/sh_mipi_dsi.c218
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c15
-rw-r--r--drivers/video/sh_mobile_meram.c13
-rw-r--r--drivers/video/sm501fb.c13
-rw-r--r--drivers/video/vt8500lcdfb.c13
-rw-r--r--drivers/video/w100fb.c13
-rw-r--r--drivers/video/wm8505fb.c13
-rw-r--r--drivers/video/wmt_ge_rops.c13
-rw-r--r--drivers/video/xilinxfb.c20
31 files changed, 2199 insertions, 2620 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d83e967e4e15..dcf0a828f66e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2413,7 +2413,6 @@ source "drivers/video/omap/Kconfig"
2413source "drivers/video/omap2/Kconfig" 2413source "drivers/video/omap2/Kconfig"
2414 2414
2415source "drivers/video/backlight/Kconfig" 2415source "drivers/video/backlight/Kconfig"
2416source "drivers/video/display/Kconfig"
2417 2416
2418if VT 2417if VT
2419 source "drivers/video/console/Kconfig" 2418 source "drivers/video/console/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9b9d8fff7732..142606814d98 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -13,7 +13,7 @@ fb-objs := $(fb-y)
13 13
14obj-$(CONFIG_VT) += console/ 14obj-$(CONFIG_VT) += console/
15obj-$(CONFIG_LOGO) += logo/ 15obj-$(CONFIG_LOGO) += logo/
16obj-y += backlight/ display/ 16obj-y += backlight/
17 17
18obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o 18obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
19obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o 19obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 5ea6596dd824..f23cae094f1b 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -152,10 +152,10 @@
152 152
153 - hsstrt: Start of horizontal synchronization pulse 153 - hsstrt: Start of horizontal synchronization pulse
154 - hsstop: End of horizontal synchronization pulse 154 - hsstop: End of horizontal synchronization pulse
155 - htotal: Last value on the line (i.e. line length = htotal+1) 155 - htotal: Last value on the line (i.e. line length = htotal + 1)
156 - vsstrt: Start of vertical synchronization pulse 156 - vsstrt: Start of vertical synchronization pulse
157 - vsstop: End of vertical synchronization pulse 157 - vsstop: End of vertical synchronization pulse
158 - vtotal: Last line value (i.e. number of lines = vtotal+1) 158 - vtotal: Last line value (i.e. number of lines = vtotal + 1)
159 - hcenter: Start of vertical retrace for interlace 159 - hcenter: Start of vertical retrace for interlace
160 160
161 You can specify the blanking timings independently. Currently I just set 161 You can specify the blanking timings independently. Currently I just set
@@ -184,7 +184,7 @@
184 clock): 184 clock):
185 185
186 - diwstrt_h: Horizontal start of the visible window 186 - diwstrt_h: Horizontal start of the visible window
187 - diwstop_h: Horizontal stop+1(*) of the visible window 187 - diwstop_h: Horizontal stop + 1(*) of the visible window
188 - diwstrt_v: Vertical start of the visible window 188 - diwstrt_v: Vertical start of the visible window
189 - diwstop_v: Vertical stop of the visible window 189 - diwstop_v: Vertical stop of the visible window
190 - ddfstrt: Horizontal start of display DMA 190 - ddfstrt: Horizontal start of display DMA
@@ -193,7 +193,7 @@
193 193
194 Sprite positioning: 194 Sprite positioning:
195 195
196 - sprstrt_h: Horizontal start-4 of sprite 196 - sprstrt_h: Horizontal start - 4 of sprite
197 - sprstrt_v: Vertical start of sprite 197 - sprstrt_v: Vertical start of sprite
198 198
199 (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1. 199 (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
@@ -212,21 +212,21 @@
212 display parameters. Here's what I found out: 212 display parameters. Here's what I found out:
213 213
214 - ddfstrt and ddfstop are best aligned to 64 pixels. 214 - ddfstrt and ddfstop are best aligned to 64 pixels.
215 - the chipset needs 64+4 horizontal pixels after the DMA start before the 215 - the chipset needs 64 + 4 horizontal pixels after the DMA start before
216 first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to 216 the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
217 display the first pixel on the line too. Increase diwstrt_h for virtual 217 to display the first pixel on the line too. Increase diwstrt_h for
218 screen panning. 218 virtual screen panning.
219 - the display DMA always fetches 64 pixels at a time (fmode = 3). 219 - the display DMA always fetches 64 pixels at a time (fmode = 3).
220 - ddfstop is ddfstrt+#pixels-64. 220 - ddfstop is ddfstrt+#pixels - 64.
221 - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1 221 - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
222 more than htotal. 222 be 1 more than htotal.
223 - hscroll simply adds a delay to the display output. Smooth horizontal 223 - hscroll simply adds a delay to the display output. Smooth horizontal
224 panning needs an extra 64 pixels on the left to prefetch the pixels that 224 panning needs an extra 64 pixels on the left to prefetch the pixels that
225 `fall off' on the left. 225 `fall off' on the left.
226 - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane 226 - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
227 DMA, so it's best to make the DMA start as late as possible. 227 DMA, so it's best to make the DMA start as late as possible.
228 - you really don't want to make ddfstrt < 128, since this will steal DMA 228 - you really don't want to make ddfstrt < 128, since this will steal DMA
229 cycles from the other DMA channels (audio, floppy and Chip RAM refresh). 229 cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
230 - I make diwstop_h and diwstop_v as large as possible. 230 - I make diwstop_h and diwstop_v as large as possible.
231 231
232 General dependencies 232 General dependencies
@@ -234,8 +234,8 @@
234 234
235 - all values are SHRES pixel (35ns) 235 - all values are SHRES pixel (35ns)
236 236
237 table 1:fetchstart table 2:prefetch table 3:fetchsize 237 table 1:fetchstart table 2:prefetch table 3:fetchsize
238 ------------------ ---------------- ----------------- 238 ------------------ ---------------- -----------------
239 Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES 239 Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
240 -------------#------+-----+------#------+-----+------#------+-----+------ 240 -------------#------+-----+------#------+-----+------#------+-----+------
241 Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64 241 Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64
@@ -245,21 +245,21 @@
245 - chipset needs 4 pixels before the first pixel is output 245 - chipset needs 4 pixels before the first pixel is output
246 - ddfstrt must be aligned to fetchstart (table 1) 246 - ddfstrt must be aligned to fetchstart (table 1)
247 - chipset needs also prefetch (table 2) to get first pixel data, so 247 - chipset needs also prefetch (table 2) to get first pixel data, so
248 ddfstrt = ((diwstrt_h-4) & -fetchstart) - prefetch 248 ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
249 - for horizontal panning decrease diwstrt_h 249 - for horizontal panning decrease diwstrt_h
250 - the length of a fetchline must be aligned to fetchsize (table 3) 250 - the length of a fetchline must be aligned to fetchsize (table 3)
251 - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit 251 - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
252 moved to optimize use of dma (useful for OCS/ECS overscan displays) 252 moved to optimize use of dma (useful for OCS/ECS overscan displays)
253 - ddfstop is ddfstrt+ddfsize-fetchsize 253 - ddfstop is ddfstrt + ddfsize - fetchsize
254 - If C= didn't change anything for AGA, then at following positions the 254 - If C= didn't change anything for AGA, then at following positions the
255 dma bus is already used: 255 dma bus is already used:
256 ddfstrt < 48 -> memory refresh 256 ddfstrt < 48 -> memory refresh
257 < 96 -> disk dma 257 < 96 -> disk dma
258 < 160 -> audio dma 258 < 160 -> audio dma
259 < 192 -> sprite 0 dma 259 < 192 -> sprite 0 dma
260 < 416 -> sprite dma (32 per sprite) 260 < 416 -> sprite dma (32 per sprite)
261 - in accordance with the hardware reference manual a hardware stop is at 261 - in accordance with the hardware reference manual a hardware stop is at
262 192, but AGA (ECS?) can go below this. 262 192, but AGA (ECS?) can go below this.
263 263
264 DMA priorities 264 DMA priorities
265 -------------- 265 --------------
@@ -269,7 +269,7 @@
269 the hardware cursor: 269 the hardware cursor:
270 270
271 - if you want to start display DMA too early, you lose the ability to 271 - if you want to start display DMA too early, you lose the ability to
272 do smooth horizontal panning (xpanstep 1 -> 64). 272 do smooth horizontal panning (xpanstep 1 -> 64).
273 - if you want to go even further, you lose the hardware cursor too. 273 - if you want to go even further, you lose the hardware cursor too.
274 274
275 IMHO a hardware cursor is more important for X than horizontal scrolling, 275 IMHO a hardware cursor is more important for X than horizontal scrolling,
@@ -286,8 +286,8 @@
286 Standard VGA timings 286 Standard VGA timings
287 -------------------- 287 --------------------
288 288
289 xres yres left right upper lower hsync vsync 289 xres yres left right upper lower hsync vsync
290 ---- ---- ---- ----- ----- ----- ----- ----- 290 ---- ---- ---- ----- ----- ----- ----- -----
291 80x25 720 400 27 45 35 12 108 2 291 80x25 720 400 27 45 35 12 108 2
292 80x30 720 480 27 45 30 9 108 2 292 80x30 720 480 27 45 30 9 108 2
293 293
@@ -297,8 +297,8 @@
297 297
298 As a comparison, graphics/monitor.h suggests the following: 298 As a comparison, graphics/monitor.h suggests the following:
299 299
300 xres yres left right upper lower hsync vsync 300 xres yres left right upper lower hsync vsync
301 ---- ---- ---- ----- ----- ----- ----- ----- 301 ---- ---- ---- ----- ----- ----- ----- -----
302 302
303 VGA 640 480 52 112 24 19 112 - 2 + 303 VGA 640 480 52 112 24 19 112 - 2 +
304 VGA70 640 400 52 112 27 21 112 - 2 - 304 VGA70 640 400 52 112 27 21 112 - 2 -
@@ -309,10 +309,10 @@
309 309
310 VSYNC HSYNC Vertical size Vertical total 310 VSYNC HSYNC Vertical size Vertical total
311 ----- ----- ------------- -------------- 311 ----- ----- ------------- --------------
312 + + Reserved Reserved 312 + + Reserved Reserved
313 + - 400 414 313 + - 400 414
314 - + 350 362 314 - + 350 362
315 - - 480 496 315 - - 480 496
316 316
317 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992 317 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
318 318
@@ -326,33 +326,34 @@
326 ----------- 326 -----------
327 327
328 - a scanline is 64 µs long, of which 52.48 µs are visible. This is about 328 - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
329 736 visible 70 ns pixels per line. 329 736 visible 70 ns pixels per line.
330 - we have 625 scanlines, of which 575 are visible (interlaced); after 330 - we have 625 scanlines, of which 575 are visible (interlaced); after
331 rounding this becomes 576. 331 rounding this becomes 576.
332 332
333 RETMA -> NTSC 333 RETMA -> NTSC
334 ------------- 334 -------------
335 335
336 - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about 336 - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
337 736 visible 70 ns pixels per line. 337 736 visible 70 ns pixels per line.
338 - we have 525 scanlines, of which 485 are visible (interlaced); after 338 - we have 525 scanlines, of which 485 are visible (interlaced); after
339 rounding this becomes 484. 339 rounding this becomes 484.
340 340
341 Thus if you want a PAL compatible display, you have to do the following: 341 Thus if you want a PAL compatible display, you have to do the following:
342 342
343 - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast 343 - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
344 timings are to be used. 344 timings are to be used.
345 - make sure upper_margin+yres+lower_margin+vsync_len = 625 for an 345 - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
346 interlaced, 312 for a non-interlaced and 156 for a doublescanned 346 interlaced, 312 for a non-interlaced and 156 for a doublescanned
347 display. 347 display.
348 - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES, 348 - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
349 908 for a HIRES and 454 for a LORES display. 349 SHRES, 908 for a HIRES and 454 for a LORES display.
350 - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90), 350 - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
351 left_margin+2*hsync_len must be greater or equal. 351 left_margin + 2 * hsync_len must be greater or equal.
352 - the upper visible part begins at 48 (interlaced; non-interlaced:24, 352 - the upper visible part begins at 48 (interlaced; non-interlaced:24,
353 doublescanned:12), upper_margin+2*vsync_len must be greater or equal. 353 doublescanned:12), upper_margin + 2 * vsync_len must be greater or
354 equal.
354 - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync 355 - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
355 of 4 scanlines 356 of 4 scanlines
356 357
357 The settings for a NTSC compatible display are straightforward. 358 The settings for a NTSC compatible display are straightforward.
358 359
@@ -361,7 +362,7 @@
361 anything about horizontal/vertical synchronization nor refresh rates. 362 anything about horizontal/vertical synchronization nor refresh rates.
362 363
363 364
364 -- Geert -- 365 -- Geert --
365 366
366*******************************************************************************/ 367*******************************************************************************/
367 368
@@ -540,45 +541,45 @@ static u_short maxfmode, chipset;
540 * Various macros 541 * Various macros
541 */ 542 */
542 543
543#define up2(v) (((v)+1) & -2) 544#define up2(v) (((v) + 1) & -2)
544#define down2(v) ((v) & -2) 545#define down2(v) ((v) & -2)
545#define div2(v) ((v)>>1) 546#define div2(v) ((v)>>1)
546#define mod2(v) ((v) & 1) 547#define mod2(v) ((v) & 1)
547 548
548#define up4(v) (((v)+3) & -4) 549#define up4(v) (((v) + 3) & -4)
549#define down4(v) ((v) & -4) 550#define down4(v) ((v) & -4)
550#define mul4(v) ((v)<<2) 551#define mul4(v) ((v) << 2)
551#define div4(v) ((v)>>2) 552#define div4(v) ((v)>>2)
552#define mod4(v) ((v) & 3) 553#define mod4(v) ((v) & 3)
553 554
554#define up8(v) (((v)+7) & -8) 555#define up8(v) (((v) + 7) & -8)
555#define down8(v) ((v) & -8) 556#define down8(v) ((v) & -8)
556#define div8(v) ((v)>>3) 557#define div8(v) ((v)>>3)
557#define mod8(v) ((v) & 7) 558#define mod8(v) ((v) & 7)
558 559
559#define up16(v) (((v)+15) & -16) 560#define up16(v) (((v) + 15) & -16)
560#define down16(v) ((v) & -16) 561#define down16(v) ((v) & -16)
561#define div16(v) ((v)>>4) 562#define div16(v) ((v)>>4)
562#define mod16(v) ((v) & 15) 563#define mod16(v) ((v) & 15)
563 564
564#define up32(v) (((v)+31) & -32) 565#define up32(v) (((v) + 31) & -32)
565#define down32(v) ((v) & -32) 566#define down32(v) ((v) & -32)
566#define div32(v) ((v)>>5) 567#define div32(v) ((v)>>5)
567#define mod32(v) ((v) & 31) 568#define mod32(v) ((v) & 31)
568 569
569#define up64(v) (((v)+63) & -64) 570#define up64(v) (((v) + 63) & -64)
570#define down64(v) ((v) & -64) 571#define down64(v) ((v) & -64)
571#define div64(v) ((v)>>6) 572#define div64(v) ((v)>>6)
572#define mod64(v) ((v) & 63) 573#define mod64(v) ((v) & 63)
573 574
574#define upx(x,v) (((v)+(x)-1) & -(x)) 575#define upx(x, v) (((v) + (x) - 1) & -(x))
575#define downx(x,v) ((v) & -(x)) 576#define downx(x, v) ((v) & -(x))
576#define modx(x,v) ((v) & ((x)-1)) 577#define modx(x, v) ((v) & ((x) - 1))
577 578
578/* if x1 is not a constant, this macro won't make real sense :-) */ 579/* if x1 is not a constant, this macro won't make real sense :-) */
579#ifdef __mc68000__ 580#ifdef __mc68000__
580#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \ 581#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
581 "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;}) 582 "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
582#else 583#else
583/* We know a bit about the numbers, so we can do it this way */ 584/* We know a bit about the numbers, so we can do it this way */
584#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \ 585#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
@@ -607,7 +608,7 @@ static u_short maxfmode, chipset;
607#define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */ 608#define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */
608#define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */ 609#define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */
609 610
610#define SPRITEMEMSIZE (64*64/4) /* max 64*64*4 */ 611#define SPRITEMEMSIZE (64 * 64 / 4) /* max 64*64*4 */
611#define DUMMYSPRITEMEMSIZE (8) 612#define DUMMYSPRITEMEMSIZE (8)
612static u_long spritememory; 613static u_long spritememory;
613 614
@@ -634,9 +635,9 @@ static u_long min_fstrt = 192;
634 * Copper Instructions 635 * Copper Instructions
635 */ 636 */
636 637
637#define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val)) 638#define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
638#define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val)) 639#define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
639#define CWAIT(x, y) (((y) & 0x1fe)<<23 | ((x) & 0x7f0)<<13 | 0x0001fffe) 640#define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
640#define CEND (0xfffffffe) 641#define CEND (0xfffffffe)
641 642
642 643
@@ -709,7 +710,7 @@ static u_short *lofsprite, *shfsprite, *dummysprite;
709 * Current Video Mode 710 * Current Video Mode
710 */ 711 */
711 712
712static struct amifb_par { 713struct amifb_par {
713 714
714 /* General Values */ 715 /* General Values */
715 716
@@ -772,15 +773,6 @@ static struct amifb_par {
772 /* Additional AGA Hardware Registers */ 773 /* Additional AGA Hardware Registers */
773 774
774 u_short fmode; /* vmode */ 775 u_short fmode; /* vmode */
775} currentpar;
776
777
778static struct fb_info fb_info = {
779 .fix = {
780 .id = "Amiga ",
781 .visual = FB_VISUAL_PSEUDOCOLOR,
782 .accel = FB_ACCEL_AMIGABLITT
783 }
784}; 776};
785 777
786 778
@@ -820,116 +812,123 @@ static u_short is_lace = 0; /* Screen is laced */
820 812
821static struct fb_videomode ami_modedb[] __initdata = { 813static struct fb_videomode ami_modedb[] __initdata = {
822 814
823 /* 815 /*
824 * AmigaOS Video Modes 816 * AmigaOS Video Modes
825 * 817 *
826 * If you change these, make sure to update DEFMODE_* as well! 818 * If you change these, make sure to update DEFMODE_* as well!
827 */ 819 */
828 820
829 { 821 {
830 /* 640x200, 15 kHz, 60 Hz (NTSC) */ 822 /* 640x200, 15 kHz, 60 Hz (NTSC) */
831 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2, 823 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
832 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 824 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
833 }, { 825 }, {
834 /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ 826 /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
835 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4, 827 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
836 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 828 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
837 }, { 829 }, {
838 /* 640x256, 15 kHz, 50 Hz (PAL) */ 830 /* 640x256, 15 kHz, 50 Hz (PAL) */
839 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2, 831 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
840 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 832 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
841 }, { 833 }, {
842 /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ 834 /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
843 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4, 835 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
844 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 836 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
845 }, { 837 }, {
846 /* 640x480, 29 kHz, 57 Hz */ 838 /* 640x480, 29 kHz, 57 Hz */
847 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8, 839 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
848 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 840 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
849 }, { 841 }, {
850 /* 640x960, 29 kHz, 57 Hz interlaced */ 842 /* 640x960, 29 kHz, 57 Hz interlaced */
851 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16, 843 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
852 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 844 16,
853 }, { 845 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
854 /* 640x200, 15 kHz, 72 Hz */ 846 }, {
855 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5, 847 /* 640x200, 15 kHz, 72 Hz */
856 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 848 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
857 }, { 849 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
858 /* 640x400, 15 kHz, 72 Hz interlaced */ 850 }, {
859 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10, 851 /* 640x400, 15 kHz, 72 Hz interlaced */
860 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 852 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
861 }, { 853 10,
862 /* 640x400, 29 kHz, 68 Hz */ 854 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
863 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8, 855 }, {
864 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 856 /* 640x400, 29 kHz, 68 Hz */
865 }, { 857 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
866 /* 640x800, 29 kHz, 68 Hz interlaced */ 858 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
867 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16, 859 }, {
868 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 860 /* 640x800, 29 kHz, 68 Hz interlaced */
869 }, { 861 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
870 /* 800x300, 23 kHz, 70 Hz */ 862 16,
871 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7, 863 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
872 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 864 }, {
873 }, { 865 /* 800x300, 23 kHz, 70 Hz */
874 /* 800x600, 23 kHz, 70 Hz interlaced */ 866 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
875 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14, 867 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
876 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 868 }, {
877 }, { 869 /* 800x600, 23 kHz, 70 Hz interlaced */
878 /* 640x200, 27 kHz, 57 Hz doublescan */ 870 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
879 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4, 871 14,
880 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 872 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
881 }, { 873 }, {
882 /* 640x400, 27 kHz, 57 Hz */ 874 /* 640x200, 27 kHz, 57 Hz doublescan */
883 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7, 875 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
884 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 876 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
885 }, { 877 }, {
886 /* 640x800, 27 kHz, 57 Hz interlaced */ 878 /* 640x400, 27 kHz, 57 Hz */
887 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14, 879 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
888 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 880 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
889 }, { 881 }, {
890 /* 640x256, 27 kHz, 47 Hz doublescan */ 882 /* 640x800, 27 kHz, 57 Hz interlaced */
891 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4, 883 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
892 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 884 14,
893 }, { 885 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
894 /* 640x512, 27 kHz, 47 Hz */ 886 }, {
895 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7, 887 /* 640x256, 27 kHz, 47 Hz doublescan */
896 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 888 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
897 }, { 889 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
898 /* 640x1024, 27 kHz, 47 Hz interlaced */ 890 }, {
899 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14, 891 /* 640x512, 27 kHz, 47 Hz */
900 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 892 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
901 }, 893 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
902 894 }, {
903 /* 895 /* 640x1024, 27 kHz, 47 Hz interlaced */
904 * VGA Video Modes 896 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
905 */ 897 14,
906 898 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
907 { 899 },
908 /* 640x480, 31 kHz, 60 Hz (VGA) */ 900
909 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2, 901 /*
910 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 902 * VGA Video Modes
911 }, { 903 */
912 /* 640x400, 31 kHz, 70 Hz (VGA) */ 904
913 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2, 905 {
914 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 906 /* 640x480, 31 kHz, 60 Hz (VGA) */
915 }, 907 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
908 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
909 }, {
910 /* 640x400, 31 kHz, 70 Hz (VGA) */
911 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
912 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
913 FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
914 },
916 915
917#if 0 916#if 0
918 917
919 /* 918 /*
920 * A2024 video modes 919 * A2024 video modes
921 * These modes don't work yet because there's no A2024 driver. 920 * These modes don't work yet because there's no A2024 driver.
922 */ 921 */
923 922
924 { 923 {
925 /* 1024x800, 10 Hz */ 924 /* 1024x800, 10 Hz */
926 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 925 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
927 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 926 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
928 }, { 927 }, {
929 /* 1024x800, 15 Hz */ 928 /* 1024x800, 15 Hz */
930 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 929 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
931 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 930 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
932 } 931 }
933#endif 932#endif
934}; 933};
935 934
@@ -953,6 +952,11 @@ static int round_down_bpp = 1; /* for mode probing */
953static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ 952static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
954static int amifb_inverse = 0; 953static int amifb_inverse = 0;
955 954
955static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
956static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
957static u16 amifb_vfmin __initdata; /* monitor vfreq lower limit (Hz) */
958static u16 amifb_vfmax __initdata; /* monitor vfreq upper limit (Hz) */
959
956 960
957 /* 961 /*
958 * Macros for the conversion from real world values to hardware register 962 * Macros for the conversion from real world values to hardware register
@@ -992,19 +996,20 @@ static int amifb_inverse = 0;
992/* bplcon1 (smooth scrolling) */ 996/* bplcon1 (smooth scrolling) */
993 997
994#define hscroll2hw(hscroll) \ 998#define hscroll2hw(hscroll) \
995 (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \ 999 (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
996 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f)) 1000 ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
1001 ((hscroll)>>2 & 0x000f))
997 1002
998/* diwstrt/diwstop/diwhigh (visible display window) */ 1003/* diwstrt/diwstop/diwhigh (visible display window) */
999 1004
1000#define diwstrt2hw(diwstrt_h, diwstrt_v) \ 1005#define diwstrt2hw(diwstrt_h, diwstrt_v) \
1001 (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff)) 1006 (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1002#define diwstop2hw(diwstop_h, diwstop_v) \ 1007#define diwstop2hw(diwstop_h, diwstop_v) \
1003 (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff)) 1008 (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1004#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \ 1009#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1005 (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \ 1010 (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
1006 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \ 1011 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1007 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007)) 1012 ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1008 1013
1009/* ddfstrt/ddfstop (display DMA) */ 1014/* ddfstrt/ddfstop (display DMA) */
1010 1015
@@ -1015,38 +1020,39 @@ static int amifb_inverse = 0;
1015 1020
1016#define hsstrt2hw(hsstrt) (div8(hsstrt)) 1021#define hsstrt2hw(hsstrt) (div8(hsstrt))
1017#define hsstop2hw(hsstop) (div8(hsstop)) 1022#define hsstop2hw(hsstop) (div8(hsstop))
1018#define htotal2hw(htotal) (div8(htotal)-1) 1023#define htotal2hw(htotal) (div8(htotal) - 1)
1019#define vsstrt2hw(vsstrt) (div2(vsstrt)) 1024#define vsstrt2hw(vsstrt) (div2(vsstrt))
1020#define vsstop2hw(vsstop) (div2(vsstop)) 1025#define vsstop2hw(vsstop) (div2(vsstop))
1021#define vtotal2hw(vtotal) (div2(vtotal)-1) 1026#define vtotal2hw(vtotal) (div2(vtotal) - 1)
1022#define hcenter2hw(htotal) (div8(htotal)) 1027#define hcenter2hw(htotal) (div8(htotal))
1023 1028
1024/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */ 1029/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
1025 1030
1026#define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff)) 1031#define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1027#define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff)) 1032#define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1028#define vbstrt2hw(vbstrt) (div2(vbstrt)) 1033#define vbstrt2hw(vbstrt) (div2(vbstrt))
1029#define vbstop2hw(vbstop) (div2(vbstop)) 1034#define vbstop2hw(vbstop) (div2(vbstop))
1030 1035
1031/* colour */ 1036/* colour */
1032 1037
1033#define rgb2hw8_high(red, green, blue) \ 1038#define rgb2hw8_high(red, green, blue) \
1034 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1039 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1035#define rgb2hw8_low(red, green, blue) \ 1040#define rgb2hw8_low(red, green, blue) \
1036 (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f)) 1041 (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
1037#define rgb2hw4(red, green, blue) \ 1042#define rgb2hw4(red, green, blue) \
1038 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1043 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1039#define rgb2hw2(red, green, blue) \ 1044#define rgb2hw2(red, green, blue) \
1040 (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4)) 1045 (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1041 1046
1042/* sprpos/sprctl (sprite positioning) */ 1047/* sprpos/sprctl (sprite positioning) */
1043 1048
1044#define spr2hw_pos(start_v, start_h) \ 1049#define spr2hw_pos(start_v, start_h) \
1045 (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff)) 1050 (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
1046#define spr2hw_ctl(start_v, start_h, stop_v) \ 1051#define spr2hw_ctl(start_v, start_h, stop_v) \
1047 (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \ 1052 (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
1048 ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \ 1053 ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
1049 ((start_h)>>2&0x0001)) 1054 ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
1055 ((start_h)>>2 & 0x0001))
1050 1056
1051/* get current vertical position of beam */ 1057/* get current vertical position of beam */
1052#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe)) 1058#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
@@ -1055,7 +1061,7 @@ static int amifb_inverse = 0;
1055 * Copper Initialisation List 1061 * Copper Initialisation List
1056 */ 1062 */
1057 1063
1058#define COPINITSIZE (sizeof(copins)*40) 1064#define COPINITSIZE (sizeof(copins) * 40)
1059 1065
1060enum { 1066enum {
1061 cip_bplcon0 1067 cip_bplcon0
@@ -1066,7 +1072,7 @@ enum {
1066 * Don't change the order, build_copper()/rebuild_copper() rely on this 1072 * Don't change the order, build_copper()/rebuild_copper() rely on this
1067 */ 1073 */
1068 1074
1069#define COPLISTSIZE (sizeof(copins)*64) 1075#define COPLISTSIZE (sizeof(copins) * 64)
1070 1076
1071enum { 1077enum {
1072 cop_wait, cop_bplcon0, 1078 cop_wait, cop_bplcon0,
@@ -1108,82 +1114,1199 @@ static u_short sprfetchmode[3] = {
1108}; 1114};
1109 1115
1110 1116
1117/* --------------------------- Hardware routines --------------------------- */
1118
1111 /* 1119 /*
1112 * Interface used by the world 1120 * Get the video params out of `var'. If a value doesn't fit, round
1121 * it up, if it's too big, return -EINVAL.
1113 */ 1122 */
1114 1123
1115int amifb_setup(char*); 1124static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
1125 const struct fb_info *info)
1126{
1127 u_short clk_shift, line_shift;
1128 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
1129 u_int htotal, vtotal;
1116 1130
1117static int amifb_check_var(struct fb_var_screeninfo *var, 1131 /*
1118 struct fb_info *info); 1132 * Find a matching Pixel Clock
1119static int amifb_set_par(struct fb_info *info); 1133 */
1120static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,
1121 unsigned blue, unsigned transp,
1122 struct fb_info *info);
1123static int amifb_blank(int blank, struct fb_info *info);
1124static int amifb_pan_display(struct fb_var_screeninfo *var,
1125 struct fb_info *info);
1126static void amifb_fillrect(struct fb_info *info,
1127 const struct fb_fillrect *rect);
1128static void amifb_copyarea(struct fb_info *info,
1129 const struct fb_copyarea *region);
1130static void amifb_imageblit(struct fb_info *info,
1131 const struct fb_image *image);
1132static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
1133 1134
1135 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
1136 if (var->pixclock <= pixclock[clk_shift])
1137 break;
1138 if (clk_shift > TAG_LORES) {
1139 DPRINTK("pixclock too high\n");
1140 return -EINVAL;
1141 }
1142 par->clk_shift = clk_shift;
1134 1143
1135 /* 1144 /*
1136 * Interface to the low level console driver 1145 * Check the Geometry Values
1137 */ 1146 */
1138 1147
1139static void amifb_deinit(struct platform_device *pdev); 1148 if ((par->xres = var->xres) < 64)
1149 par->xres = 64;
1150 if ((par->yres = var->yres) < 64)
1151 par->yres = 64;
1152 if ((par->vxres = var->xres_virtual) < par->xres)
1153 par->vxres = par->xres;
1154 if ((par->vyres = var->yres_virtual) < par->yres)
1155 par->vyres = par->yres;
1156
1157 par->bpp = var->bits_per_pixel;
1158 if (!var->nonstd) {
1159 if (par->bpp < 1)
1160 par->bpp = 1;
1161 if (par->bpp > maxdepth[clk_shift]) {
1162 if (round_down_bpp && maxdepth[clk_shift])
1163 par->bpp = maxdepth[clk_shift];
1164 else {
1165 DPRINTK("invalid bpp\n");
1166 return -EINVAL;
1167 }
1168 }
1169 } else if (var->nonstd == FB_NONSTD_HAM) {
1170 if (par->bpp < 6)
1171 par->bpp = 6;
1172 if (par->bpp != 6) {
1173 if (par->bpp < 8)
1174 par->bpp = 8;
1175 if (par->bpp != 8 || !IS_AGA) {
1176 DPRINTK("invalid bpp for ham mode\n");
1177 return -EINVAL;
1178 }
1179 }
1180 } else {
1181 DPRINTK("unknown nonstd mode\n");
1182 return -EINVAL;
1183 }
1140 1184
1141 /* 1185 /*
1142 * Internal routines 1186 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
1187 * checks failed and smooth scrolling is not possible
1143 */ 1188 */
1144 1189
1145static int flash_cursor(void); 1190 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
1146static irqreturn_t amifb_interrupt(int irq, void *dev_id); 1191 switch (par->vmode & FB_VMODE_MASK) {
1147static u_long chipalloc(u_long size); 1192 case FB_VMODE_INTERLACED:
1148static void chipfree(void); 1193 line_shift = 0;
1194 break;
1195 case FB_VMODE_NONINTERLACED:
1196 line_shift = 1;
1197 break;
1198 case FB_VMODE_DOUBLE:
1199 if (!IS_AGA) {
1200 DPRINTK("double mode only possible with aga\n");
1201 return -EINVAL;
1202 }
1203 line_shift = 2;
1204 break;
1205 default:
1206 DPRINTK("unknown video mode\n");
1207 return -EINVAL;
1208 break;
1209 }
1210 par->line_shift = line_shift;
1149 1211
1150 /* 1212 /*
1151 * Hardware routines 1213 * Vertical and Horizontal Timings
1152 */ 1214 */
1153 1215
1154static int ami_decode_var(struct fb_var_screeninfo *var, 1216 xres_n = par->xres << clk_shift;
1155 struct amifb_par *par); 1217 yres_n = par->yres << line_shift;
1156static int ami_encode_var(struct fb_var_screeninfo *var, 1218 par->htotal = down8((var->left_margin + par->xres + var->right_margin +
1157 struct amifb_par *par); 1219 var->hsync_len) << clk_shift);
1158static void ami_pan_var(struct fb_var_screeninfo *var); 1220 par->vtotal =
1159static int ami_update_par(void); 1221 down2(((var->upper_margin + par->yres + var->lower_margin +
1160static void ami_update_display(void); 1222 var->vsync_len) << line_shift) + 1);
1161static void ami_init_display(void);
1162static void ami_do_blank(void);
1163static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
1164static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1165static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1166static int ami_get_cursorstate(struct fb_cursorstate *state);
1167static int ami_set_cursorstate(struct fb_cursorstate *state);
1168static void ami_set_sprite(void);
1169static void ami_init_copper(void);
1170static void ami_reinit_copper(void);
1171static void ami_build_copper(void);
1172static void ami_rebuild_copper(void);
1173 1223
1224 if (IS_AGA)
1225 par->bplcon3 = sprpixmode[clk_shift];
1226 else
1227 par->bplcon3 = 0;
1228 if (var->sync & FB_SYNC_BROADCAST) {
1229 par->diwstop_h = par->htotal -
1230 ((var->right_margin - var->hsync_len) << clk_shift);
1231 if (IS_AGA)
1232 par->diwstop_h += mod4(var->hsync_len);
1233 else
1234 par->diwstop_h = down4(par->diwstop_h);
1235
1236 par->diwstrt_h = par->diwstop_h - xres_n;
1237 par->diwstop_v = par->vtotal -
1238 ((var->lower_margin - var->vsync_len) << line_shift);
1239 par->diwstrt_v = par->diwstop_v - yres_n;
1240 if (par->diwstop_h >= par->htotal + 8) {
1241 DPRINTK("invalid diwstop_h\n");
1242 return -EINVAL;
1243 }
1244 if (par->diwstop_v > par->vtotal) {
1245 DPRINTK("invalid diwstop_v\n");
1246 return -EINVAL;
1247 }
1248
1249 if (!IS_OCS) {
1250 /* Initialize sync with some reasonable values for pwrsave */
1251 par->hsstrt = 160;
1252 par->hsstop = 320;
1253 par->vsstrt = 30;
1254 par->vsstop = 34;
1255 } else {
1256 par->hsstrt = 0;
1257 par->hsstop = 0;
1258 par->vsstrt = 0;
1259 par->vsstop = 0;
1260 }
1261 if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
1262 /* PAL video mode */
1263 if (par->htotal != PAL_HTOTAL) {
1264 DPRINTK("htotal invalid for pal\n");
1265 return -EINVAL;
1266 }
1267 if (par->diwstrt_h < PAL_DIWSTRT_H) {
1268 DPRINTK("diwstrt_h too low for pal\n");
1269 return -EINVAL;
1270 }
1271 if (par->diwstrt_v < PAL_DIWSTRT_V) {
1272 DPRINTK("diwstrt_v too low for pal\n");
1273 return -EINVAL;
1274 }
1275 htotal = PAL_HTOTAL>>clk_shift;
1276 vtotal = PAL_VTOTAL>>1;
1277 if (!IS_OCS) {
1278 par->beamcon0 = BMC0_PAL;
1279 par->bplcon3 |= BPC3_BRDRBLNK;
1280 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1281 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1282 par->beamcon0 = BMC0_PAL;
1283 par->hsstop = 1;
1284 } else if (amiga_vblank != 50) {
1285 DPRINTK("pal not supported by this chipset\n");
1286 return -EINVAL;
1287 }
1288 } else {
1289 /* NTSC video mode
1290 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
1291 * and NTSC activated, so than better let diwstop_h <= 1812
1292 */
1293 if (par->htotal != NTSC_HTOTAL) {
1294 DPRINTK("htotal invalid for ntsc\n");
1295 return -EINVAL;
1296 }
1297 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
1298 DPRINTK("diwstrt_h too low for ntsc\n");
1299 return -EINVAL;
1300 }
1301 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
1302 DPRINTK("diwstrt_v too low for ntsc\n");
1303 return -EINVAL;
1304 }
1305 htotal = NTSC_HTOTAL>>clk_shift;
1306 vtotal = NTSC_VTOTAL>>1;
1307 if (!IS_OCS) {
1308 par->beamcon0 = 0;
1309 par->bplcon3 |= BPC3_BRDRBLNK;
1310 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1311 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1312 par->beamcon0 = 0;
1313 par->hsstop = 1;
1314 } else if (amiga_vblank != 60) {
1315 DPRINTK("ntsc not supported by this chipset\n");
1316 return -EINVAL;
1317 }
1318 }
1319 if (IS_OCS) {
1320 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
1321 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
1322 DPRINTK("invalid position for display on ocs\n");
1323 return -EINVAL;
1324 }
1325 }
1326 } else if (!IS_OCS) {
1327 /* Programmable video mode */
1328 par->hsstrt = var->right_margin << clk_shift;
1329 par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
1330 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
1331 if (!IS_AGA)
1332 par->diwstop_h = down4(par->diwstop_h) - 16;
1333 par->diwstrt_h = par->diwstop_h - xres_n;
1334 par->hbstop = par->diwstrt_h + 4;
1335 par->hbstrt = par->diwstop_h + 4;
1336 if (par->hbstrt >= par->htotal + 8)
1337 par->hbstrt -= par->htotal;
1338 par->hcenter = par->hsstrt + (par->htotal >> 1);
1339 par->vsstrt = var->lower_margin << line_shift;
1340 par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
1341 par->diwstop_v = par->vtotal;
1342 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1343 par->diwstop_v -= 2;
1344 par->diwstrt_v = par->diwstop_v - yres_n;
1345 par->vbstop = par->diwstrt_v - 2;
1346 par->vbstrt = par->diwstop_v - 2;
1347 if (par->vtotal > 2048) {
1348 DPRINTK("vtotal too high\n");
1349 return -EINVAL;
1350 }
1351 if (par->htotal > 2048) {
1352 DPRINTK("htotal too high\n");
1353 return -EINVAL;
1354 }
1355 par->bplcon3 |= BPC3_EXTBLKEN;
1356 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
1357 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
1358 BMC0_PAL | BMC0_VARCSYEN;
1359 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1360 par->beamcon0 |= BMC0_HSYTRUE;
1361 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1362 par->beamcon0 |= BMC0_VSYTRUE;
1363 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
1364 par->beamcon0 |= BMC0_CSYTRUE;
1365 htotal = par->htotal>>clk_shift;
1366 vtotal = par->vtotal>>1;
1367 } else {
1368 DPRINTK("only broadcast modes possible for ocs\n");
1369 return -EINVAL;
1370 }
1371
1372 /*
1373 * Checking the DMA timing
1374 */
1375
1376 fconst = 16 << maxfmode << clk_shift;
1377
1378 /*
1379 * smallest window start value without turn off other dma cycles
1380 * than sprite1-7, unless you change min_fstrt
1381 */
1382
1383
1384 fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
1385 fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
1386 if (fstrt < min_fstrt) {
1387 DPRINTK("fetch start too low\n");
1388 return -EINVAL;
1389 }
1390
1391 /*
1392 * smallest window start value where smooth scrolling is possible
1393 */
1394
1395 fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
1396 fsize;
1397 if (fstrt < min_fstrt)
1398 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1399
1400 maxfetchstop = down16(par->htotal - 80);
1401
1402 fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
1403 fsize = upx(fconst, xres_n +
1404 modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
1405 if (fstrt + fsize > maxfetchstop)
1406 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1407
1408 fsize = upx(fconst, xres_n);
1409 if (fstrt + fsize > maxfetchstop) {
1410 DPRINTK("fetch stop too high\n");
1411 return -EINVAL;
1412 }
1413
1414 if (maxfmode + clk_shift <= 1) {
1415 fsize = up64(xres_n + fconst - 1);
1416 if (min_fstrt + fsize - 64 > maxfetchstop)
1417 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1418
1419 fsize = up64(xres_n);
1420 if (min_fstrt + fsize - 64 > maxfetchstop) {
1421 DPRINTK("fetch size too high\n");
1422 return -EINVAL;
1423 }
1424
1425 fsize -= 64;
1426 } else
1427 fsize -= fconst;
1428
1429 /*
1430 * Check if there is enough time to update the bitplane pointers for ywrap
1431 */
1432
1433 if (par->htotal - fsize - 64 < par->bpp * 64)
1434 par->vmode &= ~FB_VMODE_YWRAP;
1435
1436 /*
1437 * Bitplane calculations and check the Memory Requirements
1438 */
1439
1440 if (amifb_ilbm) {
1441 par->next_plane = div8(upx(16 << maxfmode, par->vxres));
1442 par->next_line = par->bpp * par->next_plane;
1443 if (par->next_line * par->vyres > info->fix.smem_len) {
1444 DPRINTK("too few video mem\n");
1445 return -EINVAL;
1446 }
1447 } else {
1448 par->next_line = div8(upx(16 << maxfmode, par->vxres));
1449 par->next_plane = par->vyres * par->next_line;
1450 if (par->next_plane * par->bpp > info->fix.smem_len) {
1451 DPRINTK("too few video mem\n");
1452 return -EINVAL;
1453 }
1454 }
1455
1456 /*
1457 * Hardware Register Values
1458 */
1459
1460 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
1461 if (!IS_OCS)
1462 par->bplcon0 |= BPC0_ECSENA;
1463 if (par->bpp == 8)
1464 par->bplcon0 |= BPC0_BPU3;
1465 else
1466 par->bplcon0 |= par->bpp << 12;
1467 if (var->nonstd == FB_NONSTD_HAM)
1468 par->bplcon0 |= BPC0_HAM;
1469 if (var->sync & FB_SYNC_EXT)
1470 par->bplcon0 |= BPC0_ERSY;
1471
1472 if (IS_AGA)
1473 par->fmode = bplfetchmode[maxfmode];
1474
1475 switch (par->vmode & FB_VMODE_MASK) {
1476 case FB_VMODE_INTERLACED:
1477 par->bplcon0 |= BPC0_LACE;
1478 break;
1479 case FB_VMODE_DOUBLE:
1480 if (IS_AGA)
1481 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
1482 break;
1483 }
1484
1485 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
1486 par->xoffset = var->xoffset;
1487 par->yoffset = var->yoffset;
1488 if (par->vmode & FB_VMODE_YWRAP) {
1489 if (par->xoffset || par->yoffset < 0 ||
1490 par->yoffset >= par->vyres)
1491 par->xoffset = par->yoffset = 0;
1492 } else {
1493 if (par->xoffset < 0 ||
1494 par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
1495 par->yoffset < 0 || par->yoffset > par->vyres - par->yres)
1496 par->xoffset = par->yoffset = 0;
1497 }
1498 } else
1499 par->xoffset = par->yoffset = 0;
1500
1501 par->crsr.crsr_x = par->crsr.crsr_y = 0;
1502 par->crsr.spot_x = par->crsr.spot_y = 0;
1503 par->crsr.height = par->crsr.width = 0;
1504
1505 return 0;
1506}
1507
1508 /*
1509 * Fill the `var' structure based on the values in `par' and maybe
1510 * other values read out of the hardware.
1511 */
1512
1513static void ami_encode_var(struct fb_var_screeninfo *var,
1514 struct amifb_par *par)
1515{
1516 u_short clk_shift, line_shift;
1517
1518 memset(var, 0, sizeof(struct fb_var_screeninfo));
1519
1520 clk_shift = par->clk_shift;
1521 line_shift = par->line_shift;
1522
1523 var->xres = par->xres;
1524 var->yres = par->yres;
1525 var->xres_virtual = par->vxres;
1526 var->yres_virtual = par->vyres;
1527 var->xoffset = par->xoffset;
1528 var->yoffset = par->yoffset;
1529
1530 var->bits_per_pixel = par->bpp;
1531 var->grayscale = 0;
1532
1533 var->red.offset = 0;
1534 var->red.msb_right = 0;
1535 var->red.length = par->bpp;
1536 if (par->bplcon0 & BPC0_HAM)
1537 var->red.length -= 2;
1538 var->blue = var->green = var->red;
1539 var->transp.offset = 0;
1540 var->transp.length = 0;
1541 var->transp.msb_right = 0;
1542
1543 if (par->bplcon0 & BPC0_HAM)
1544 var->nonstd = FB_NONSTD_HAM;
1545 else
1546 var->nonstd = 0;
1547 var->activate = 0;
1548
1549 var->height = -1;
1550 var->width = -1;
1551
1552 var->pixclock = pixclock[clk_shift];
1553
1554 if (IS_AGA && par->fmode & FMODE_BSCAN2)
1555 var->vmode = FB_VMODE_DOUBLE;
1556 else if (par->bplcon0 & BPC0_LACE)
1557 var->vmode = FB_VMODE_INTERLACED;
1558 else
1559 var->vmode = FB_VMODE_NONINTERLACED;
1560
1561 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
1562 var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
1563 var->right_margin = par->hsstrt>>clk_shift;
1564 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1565 var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
1566 var->lower_margin = par->vsstrt>>line_shift;
1567 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
1568 var->sync = 0;
1569 if (par->beamcon0 & BMC0_HSYTRUE)
1570 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1571 if (par->beamcon0 & BMC0_VSYTRUE)
1572 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1573 if (par->beamcon0 & BMC0_CSYTRUE)
1574 var->sync |= FB_SYNC_COMP_HIGH_ACT;
1575 } else {
1576 var->sync = FB_SYNC_BROADCAST;
1577 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
1578 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
1579 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1580 var->vsync_len = 4>>line_shift;
1581 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
1582 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
1583 var->lower_margin - var->vsync_len;
1584 }
1585
1586 if (par->bplcon0 & BPC0_ERSY)
1587 var->sync |= FB_SYNC_EXT;
1588 if (par->vmode & FB_VMODE_YWRAP)
1589 var->vmode |= FB_VMODE_YWRAP;
1590}
1591
1592
1593 /*
1594 * Update hardware
1595 */
1596
1597static void ami_update_par(struct fb_info *info)
1598{
1599 struct amifb_par *par = info->par;
1600 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
1601
1602 clk_shift = par->clk_shift;
1603
1604 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
1605 par->xoffset = upx(16 << maxfmode, par->xoffset);
1606
1607 fconst = 16 << maxfmode << clk_shift;
1608 vshift = modx(16 << maxfmode, par->xoffset);
1609 fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
1610 fsize = (par->xres + vshift) << clk_shift;
1611 shift = modx(fconst, fstrt);
1612 move = downx(2 << maxfmode, div8(par->xoffset));
1613 if (maxfmode + clk_shift > 1) {
1614 fstrt = downx(fconst, fstrt) - 64;
1615 fsize = upx(fconst, fsize);
1616 fstop = fstrt + fsize - fconst;
1617 } else {
1618 mod = fstrt = downx(fconst, fstrt) - fconst;
1619 fstop = fstrt + upx(fconst, fsize) - 64;
1620 fsize = up64(fsize);
1621 fstrt = fstop - fsize + 64;
1622 if (fstrt < min_fstrt) {
1623 fstop += min_fstrt - fstrt;
1624 fstrt = min_fstrt;
1625 }
1626 move = move - div8((mod - fstrt)>>clk_shift);
1627 }
1628 mod = par->next_line - div8(fsize>>clk_shift);
1629 par->ddfstrt = fstrt;
1630 par->ddfstop = fstop;
1631 par->bplcon1 = hscroll2hw(shift);
1632 par->bpl2mod = mod;
1633 if (par->bplcon0 & BPC0_LACE)
1634 par->bpl2mod += par->next_line;
1635 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
1636 par->bpl1mod = -div8(fsize>>clk_shift);
1637 else
1638 par->bpl1mod = par->bpl2mod;
1639
1640 if (par->yoffset) {
1641 par->bplpt0 = info->fix.smem_start +
1642 par->next_line * par->yoffset + move;
1643 if (par->vmode & FB_VMODE_YWRAP) {
1644 if (par->yoffset > par->vyres - par->yres) {
1645 par->bplpt0wrap = info->fix.smem_start + move;
1646 if (par->bplcon0 & BPC0_LACE &&
1647 mod2(par->diwstrt_v + par->vyres -
1648 par->yoffset))
1649 par->bplpt0wrap += par->next_line;
1650 }
1651 }
1652 } else
1653 par->bplpt0 = info->fix.smem_start + move;
1654
1655 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
1656 par->bplpt0 += par->next_line;
1657}
1658
1659
1660 /*
1661 * Pan or Wrap the Display
1662 *
1663 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1664 * in `var'.
1665 */
1666
1667static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
1668{
1669 struct amifb_par *par = info->par;
1670
1671 par->xoffset = var->xoffset;
1672 par->yoffset = var->yoffset;
1673 if (var->vmode & FB_VMODE_YWRAP)
1674 par->vmode |= FB_VMODE_YWRAP;
1675 else
1676 par->vmode &= ~FB_VMODE_YWRAP;
1677
1678 do_vmode_pan = 0;
1679 ami_update_par(info);
1680 do_vmode_pan = 1;
1681}
1682
1683
1684static void ami_update_display(const struct amifb_par *par)
1685{
1686 custom.bplcon1 = par->bplcon1;
1687 custom.bpl1mod = par->bpl1mod;
1688 custom.bpl2mod = par->bpl2mod;
1689 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
1690 custom.ddfstop = ddfstop2hw(par->ddfstop);
1691}
1692
1693 /*
1694 * Change the video mode (called by VBlank interrupt)
1695 */
1696
1697static void ami_init_display(const struct amifb_par *par)
1698{
1699 int i;
1700
1701 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
1702 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
1703 if (!IS_OCS) {
1704 custom.bplcon3 = par->bplcon3;
1705 if (IS_AGA)
1706 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
1707 if (par->beamcon0 & BMC0_VARBEAMEN) {
1708 custom.htotal = htotal2hw(par->htotal);
1709 custom.hbstrt = hbstrt2hw(par->hbstrt);
1710 custom.hbstop = hbstop2hw(par->hbstop);
1711 custom.hsstrt = hsstrt2hw(par->hsstrt);
1712 custom.hsstop = hsstop2hw(par->hsstop);
1713 custom.hcenter = hcenter2hw(par->hcenter);
1714 custom.vtotal = vtotal2hw(par->vtotal);
1715 custom.vbstrt = vbstrt2hw(par->vbstrt);
1716 custom.vbstop = vbstop2hw(par->vbstop);
1717 custom.vsstrt = vsstrt2hw(par->vsstrt);
1718 custom.vsstop = vsstop2hw(par->vsstop);
1719 }
1720 }
1721 if (!IS_OCS || par->hsstop)
1722 custom.beamcon0 = par->beamcon0;
1723 if (IS_AGA)
1724 custom.fmode = par->fmode;
1725
1726 /*
1727 * The minimum period for audio depends on htotal
1728 */
1729
1730 amiga_audio_min_period = div16(par->htotal);
1731
1732 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
1733#if 1
1734 if (is_lace) {
1735 i = custom.vposr >> 15;
1736 } else {
1737 custom.vposw = custom.vposr | 0x8000;
1738 i = 1;
1739 }
1740#else
1741 i = 1;
1742 custom.vposw = custom.vposr | 0x8000;
1743#endif
1744 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
1745}
1746
1747 /*
1748 * (Un)Blank the screen (called by VBlank interrupt)
1749 */
1750
1751static void ami_do_blank(const struct amifb_par *par)
1752{
1753#if defined(CONFIG_FB_AMIGA_AGA)
1754 u_short bplcon3 = par->bplcon3;
1755#endif
1756 u_char red, green, blue;
1757
1758 if (do_blank > 0) {
1759 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
1760 red = green = blue = 0;
1761 if (!IS_OCS && do_blank > 1) {
1762 switch (do_blank) {
1763 case FB_BLANK_VSYNC_SUSPEND:
1764 custom.hsstrt = hsstrt2hw(par->hsstrt);
1765 custom.hsstop = hsstop2hw(par->hsstop);
1766 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1767 custom.vsstop = vsstop2hw(par->vtotal + 4);
1768 break;
1769 case FB_BLANK_HSYNC_SUSPEND:
1770 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1771 custom.hsstop = hsstop2hw(par->htotal + 16);
1772 custom.vsstrt = vsstrt2hw(par->vsstrt);
1773 custom.vsstop = vsstrt2hw(par->vsstop);
1774 break;
1775 case FB_BLANK_POWERDOWN:
1776 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1777 custom.hsstop = hsstop2hw(par->htotal + 16);
1778 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1779 custom.vsstop = vsstop2hw(par->vtotal + 4);
1780 break;
1781 }
1782 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
1783 custom.htotal = htotal2hw(par->htotal);
1784 custom.vtotal = vtotal2hw(par->vtotal);
1785 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
1786 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
1787 }
1788 }
1789 } else {
1790 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
1791 red = red0;
1792 green = green0;
1793 blue = blue0;
1794 if (!IS_OCS) {
1795 custom.hsstrt = hsstrt2hw(par->hsstrt);
1796 custom.hsstop = hsstop2hw(par->hsstop);
1797 custom.vsstrt = vsstrt2hw(par->vsstrt);
1798 custom.vsstop = vsstop2hw(par->vsstop);
1799 custom.beamcon0 = par->beamcon0;
1800 }
1801 }
1802#if defined(CONFIG_FB_AMIGA_AGA)
1803 if (IS_AGA) {
1804 custom.bplcon3 = bplcon3;
1805 custom.color[0] = rgb2hw8_high(red, green, blue);
1806 custom.bplcon3 = bplcon3 | BPC3_LOCT;
1807 custom.color[0] = rgb2hw8_low(red, green, blue);
1808 custom.bplcon3 = bplcon3;
1809 } else
1810#endif
1811#if defined(CONFIG_FB_AMIGA_ECS)
1812 if (par->bplcon0 & BPC0_SHRES) {
1813 u_short color, mask;
1814 int i;
1815
1816 mask = 0x3333;
1817 color = rgb2hw2(red, green, blue);
1818 for (i = 12; i >= 0; i -= 4)
1819 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1820 mask <<= 2; color >>= 2;
1821 for (i = 3; i >= 0; i--)
1822 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1823 } else
1824#endif
1825 custom.color[0] = rgb2hw4(red, green, blue);
1826 is_blanked = do_blank > 0 ? do_blank : 0;
1827}
1828
1829static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
1830 const struct amifb_par *par)
1831{
1832 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
1833 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
1834 fix->crsr_color1 = 17;
1835 fix->crsr_color2 = 18;
1836 return 0;
1837}
1838
1839static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
1840 u_char __user *data,
1841 const struct amifb_par *par)
1842{
1843 register u_short *lspr, *sspr;
1844#ifdef __mc68000__
1845 register u_long datawords asm ("d2");
1846#else
1847 register u_long datawords;
1848#endif
1849 register short delta;
1850 register u_char color;
1851 short height, width, bits, words;
1852 int size, alloc;
1853
1854 size = par->crsr.height * par->crsr.width;
1855 alloc = var->height * var->width;
1856 var->height = par->crsr.height;
1857 var->width = par->crsr.width;
1858 var->xspot = par->crsr.spot_x;
1859 var->yspot = par->crsr.spot_y;
1860 if (size > var->height * var->width)
1861 return -ENAMETOOLONG;
1862 if (!access_ok(VERIFY_WRITE, data, size))
1863 return -EFAULT;
1864 delta = 1 << par->crsr.fmode;
1865 lspr = lofsprite + (delta << 1);
1866 if (par->bplcon0 & BPC0_LACE)
1867 sspr = shfsprite + (delta << 1);
1868 else
1869 sspr = NULL;
1870 for (height = (short)var->height - 1; height >= 0; height--) {
1871 bits = 0; words = delta; datawords = 0;
1872 for (width = (short)var->width - 1; width >= 0; width--) {
1873 if (bits == 0) {
1874 bits = 16; --words;
1875#ifdef __mc68000__
1876 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1877 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
1878#else
1879 datawords = (*(lspr + delta) << 16) | (*lspr++);
1880#endif
1881 }
1882 --bits;
1883#ifdef __mc68000__
1884 asm volatile (
1885 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1886 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1887 : "=d" (color), "=d" (datawords) : "1" (datawords));
1888#else
1889 color = (((datawords >> 30) & 2)
1890 | ((datawords >> 15) & 1));
1891 datawords <<= 1;
1892#endif
1893 put_user(color, data++);
1894 }
1895 if (bits > 0) {
1896 --words; ++lspr;
1897 }
1898 while (--words >= 0)
1899 ++lspr;
1900#ifdef __mc68000__
1901 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1902 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
1903#else
1904 lspr += delta;
1905 if (sspr) {
1906 u_short *tmp = lspr;
1907 lspr = sspr;
1908 sspr = tmp;
1909 }
1910#endif
1911 }
1912 return 0;
1913}
1914
1915static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
1916 u_char __user *data, struct amifb_par *par)
1917{
1918 register u_short *lspr, *sspr;
1919#ifdef __mc68000__
1920 register u_long datawords asm ("d2");
1921#else
1922 register u_long datawords;
1923#endif
1924 register short delta;
1925 u_short fmode;
1926 short height, width, bits, words;
1927
1928 if (!var->width)
1929 return -EINVAL;
1930 else if (var->width <= 16)
1931 fmode = TAG_FMODE_1;
1932 else if (var->width <= 32)
1933 fmode = TAG_FMODE_2;
1934 else if (var->width <= 64)
1935 fmode = TAG_FMODE_4;
1936 else
1937 return -EINVAL;
1938 if (fmode > maxfmode)
1939 return -EINVAL;
1940 if (!var->height)
1941 return -EINVAL;
1942 if (!access_ok(VERIFY_READ, data, var->width * var->height))
1943 return -EFAULT;
1944 delta = 1 << fmode;
1945 lofsprite = shfsprite = (u_short *)spritememory;
1946 lspr = lofsprite + (delta << 1);
1947 if (par->bplcon0 & BPC0_LACE) {
1948 if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
1949 return -EINVAL;
1950 memset(lspr, 0, (var->height + 4) << fmode << 2);
1951 shfsprite += ((var->height + 5)&-2) << fmode;
1952 sspr = shfsprite + (delta << 1);
1953 } else {
1954 if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
1955 return -EINVAL;
1956 memset(lspr, 0, (var->height + 2) << fmode << 2);
1957 sspr = NULL;
1958 }
1959 for (height = (short)var->height - 1; height >= 0; height--) {
1960 bits = 16; words = delta; datawords = 0;
1961 for (width = (short)var->width - 1; width >= 0; width--) {
1962 unsigned long tdata = 0;
1963 get_user(tdata, data);
1964 data++;
1965#ifdef __mc68000__
1966 asm volatile (
1967 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1968 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1969 : "=d" (datawords)
1970 : "0" (datawords), "d" (tdata));
1971#else
1972 datawords = ((datawords << 1) & 0xfffefffe);
1973 datawords |= tdata & 1;
1974 datawords |= (tdata & 2) << (16 - 1);
1975#endif
1976 if (--bits == 0) {
1977 bits = 16; --words;
1978#ifdef __mc68000__
1979 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1980 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
1981#else
1982 *(lspr + delta) = (u_short) (datawords >> 16);
1983 *lspr++ = (u_short) (datawords & 0xffff);
1984#endif
1985 }
1986 }
1987 if (bits < 16) {
1988 --words;
1989#ifdef __mc68000__
1990 asm volatile (
1991 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1992 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1993 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
1994#else
1995 *(lspr + delta) = (u_short) (datawords >> (16 + bits));
1996 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
1997#endif
1998 }
1999 while (--words >= 0) {
2000#ifdef __mc68000__
2001 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
2002 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
2003#else
2004 *(lspr + delta) = 0;
2005 *lspr++ = 0;
2006#endif
2007 }
2008#ifdef __mc68000__
2009 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2010 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
2011#else
2012 lspr += delta;
2013 if (sspr) {
2014 u_short *tmp = lspr;
2015 lspr = sspr;
2016 sspr = tmp;
2017 }
2018#endif
2019 }
2020 par->crsr.height = var->height;
2021 par->crsr.width = var->width;
2022 par->crsr.spot_x = var->xspot;
2023 par->crsr.spot_y = var->yspot;
2024 par->crsr.fmode = fmode;
2025 if (IS_AGA) {
2026 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
2027 par->fmode |= sprfetchmode[fmode];
2028 custom.fmode = par->fmode;
2029 }
2030 return 0;
2031}
2032
2033static int ami_get_cursorstate(struct fb_cursorstate *state,
2034 const struct amifb_par *par)
2035{
2036 state->xoffset = par->crsr.crsr_x;
2037 state->yoffset = par->crsr.crsr_y;
2038 state->mode = cursormode;
2039 return 0;
2040}
2041
2042static int ami_set_cursorstate(struct fb_cursorstate *state,
2043 struct amifb_par *par)
2044{
2045 par->crsr.crsr_x = state->xoffset;
2046 par->crsr.crsr_y = state->yoffset;
2047 if ((cursormode = state->mode) == FB_CURSOR_OFF)
2048 cursorstate = -1;
2049 do_cursor = 1;
2050 return 0;
2051}
2052
2053static void ami_set_sprite(const struct amifb_par *par)
2054{
2055 copins *copl, *cops;
2056 u_short hs, vs, ve;
2057 u_long pl, ps, pt;
2058 short mx, my;
2059
2060 cops = copdisplay.list[currentcop][0];
2061 copl = copdisplay.list[currentcop][1];
2062 ps = pl = ZTWO_PADDR(dummysprite);
2063 mx = par->crsr.crsr_x - par->crsr.spot_x;
2064 my = par->crsr.crsr_y - par->crsr.spot_y;
2065 if (!(par->vmode & FB_VMODE_YWRAP)) {
2066 mx -= par->xoffset;
2067 my -= par->yoffset;
2068 }
2069 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
2070 mx > -(short)par->crsr.width && mx < par->xres &&
2071 my > -(short)par->crsr.height && my < par->yres) {
2072 pl = ZTWO_PADDR(lofsprite);
2073 hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
2074 vs = par->diwstrt_v + (my << par->line_shift);
2075 ve = vs + (par->crsr.height << par->line_shift);
2076 if (par->bplcon0 & BPC0_LACE) {
2077 ps = ZTWO_PADDR(shfsprite);
2078 lofsprite[0] = spr2hw_pos(vs, hs);
2079 shfsprite[0] = spr2hw_pos(vs + 1, hs);
2080 if (mod2(vs)) {
2081 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2082 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
2083 pt = pl; pl = ps; ps = pt;
2084 } else {
2085 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
2086 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
2087 }
2088 } else {
2089 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
2090 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2091 }
2092 }
2093 copl[cop_spr0ptrh].w[1] = highw(pl);
2094 copl[cop_spr0ptrl].w[1] = loww(pl);
2095 if (par->bplcon0 & BPC0_LACE) {
2096 cops[cop_spr0ptrh].w[1] = highw(ps);
2097 cops[cop_spr0ptrl].w[1] = loww(ps);
2098 }
2099}
2100
2101
2102 /*
2103 * Initialise the Copper Initialisation List
2104 */
2105
2106static void __init ami_init_copper(void)
2107{
2108 copins *cop = copdisplay.init;
2109 u_long p;
2110 int i;
2111
2112 if (!IS_OCS) {
2113 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
2114 (cop++)->l = CMOVE(0x0181, diwstrt);
2115 (cop++)->l = CMOVE(0x0281, diwstop);
2116 (cop++)->l = CMOVE(0x0000, diwhigh);
2117 } else
2118 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
2119 p = ZTWO_PADDR(dummysprite);
2120 for (i = 0; i < 8; i++) {
2121 (cop++)->l = CMOVE(0, spr[i].pos);
2122 (cop++)->l = CMOVE(highw(p), sprpt[i]);
2123 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
2124 }
2125
2126 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
2127 copdisplay.wait = cop;
2128 (cop++)->l = CEND;
2129 (cop++)->l = CMOVE(0, copjmp2);
2130 cop->l = CEND;
2131
2132 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
2133 custom.copjmp1 = 0;
2134}
2135
2136static void ami_reinit_copper(const struct amifb_par *par)
2137{
2138 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
2139 copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
2140}
2141
2142
2143 /*
2144 * Rebuild the Copper List
2145 *
2146 * We only change the things that are not static
2147 */
2148
2149static void ami_rebuild_copper(const struct amifb_par *par)
2150{
2151 copins *copl, *cops;
2152 u_short line, h_end1, h_end2;
2153 short i;
2154 u_long p;
2155
2156 if (IS_AGA && maxfmode + par->clk_shift == 0)
2157 h_end1 = par->diwstrt_h - 64;
2158 else
2159 h_end1 = par->htotal - 32;
2160 h_end2 = par->ddfstop + 64;
2161
2162 ami_set_sprite(par);
2163
2164 copl = copdisplay.rebuild[1];
2165 p = par->bplpt0;
2166 if (par->vmode & FB_VMODE_YWRAP) {
2167 if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
2168 if (par->yoffset > par->vyres - par->yres) {
2169 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2170 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2171 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2172 }
2173 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
2174 while (line >= 512) {
2175 (copl++)->l = CWAIT(h_end1, 510);
2176 line -= 512;
2177 }
2178 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2179 (copl++)->l = CWAIT(h_end1, line);
2180 else
2181 (copl++)->l = CWAIT(h_end2, line);
2182 p = par->bplpt0wrap;
2183 }
2184 } else
2185 p = par->bplpt0wrap;
2186 }
2187 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2188 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2189 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2190 }
2191 copl->l = CEND;
2192
2193 if (par->bplcon0 & BPC0_LACE) {
2194 cops = copdisplay.rebuild[0];
2195 p = par->bplpt0;
2196 if (mod2(par->diwstrt_v))
2197 p -= par->next_line;
2198 else
2199 p += par->next_line;
2200 if (par->vmode & FB_VMODE_YWRAP) {
2201 if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
2202 if (par->yoffset > par->vyres - par->yres + 1) {
2203 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2204 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2205 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2206 }
2207 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
2208 while (line >= 512) {
2209 (cops++)->l = CWAIT(h_end1, 510);
2210 line -= 512;
2211 }
2212 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2213 (cops++)->l = CWAIT(h_end1, line);
2214 else
2215 (cops++)->l = CWAIT(h_end2, line);
2216 p = par->bplpt0wrap;
2217 if (mod2(par->diwstrt_v + par->vyres -
2218 par->yoffset))
2219 p -= par->next_line;
2220 else
2221 p += par->next_line;
2222 }
2223 } else
2224 p = par->bplpt0wrap - par->next_line;
2225 }
2226 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2227 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2228 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2229 }
2230 cops->l = CEND;
2231 }
2232}
2233
2234
2235 /*
2236 * Build the Copper List
2237 */
2238
2239static void ami_build_copper(struct fb_info *info)
2240{
2241 struct amifb_par *par = info->par;
2242 copins *copl, *cops;
2243 u_long p;
2244
2245 currentcop = 1 - currentcop;
2246
2247 copl = copdisplay.list[currentcop][1];
2248
2249 (copl++)->l = CWAIT(0, 10);
2250 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
2251 (copl++)->l = CMOVE(0, sprpt[0]);
2252 (copl++)->l = CMOVE2(0, sprpt[0]);
2253
2254 if (par->bplcon0 & BPC0_LACE) {
2255 cops = copdisplay.list[currentcop][0];
2256
2257 (cops++)->l = CWAIT(0, 10);
2258 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
2259 (cops++)->l = CMOVE(0, sprpt[0]);
2260 (cops++)->l = CMOVE2(0, sprpt[0]);
2261
2262 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
2263 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
2264 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2265 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2266 if (!IS_OCS) {
2267 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
2268 par->diwstop_h, par->diwstop_v + 1), diwhigh);
2269 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2270 par->diwstop_h, par->diwstop_v), diwhigh);
2271#if 0
2272 if (par->beamcon0 & BMC0_VARBEAMEN) {
2273 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2274 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
2275 (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
2276 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2277 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2278 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2279 }
2280#endif
2281 }
2282 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
2283 (copl++)->l = CMOVE(highw(p), cop2lc);
2284 (copl++)->l = CMOVE2(loww(p), cop2lc);
2285 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
2286 (cops++)->l = CMOVE(highw(p), cop2lc);
2287 (cops++)->l = CMOVE2(loww(p), cop2lc);
2288 copdisplay.rebuild[0] = cops;
2289 } else {
2290 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2291 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2292 if (!IS_OCS) {
2293 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2294 par->diwstop_h, par->diwstop_v), diwhigh);
2295#if 0
2296 if (par->beamcon0 & BMC0_VARBEAMEN) {
2297 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2298 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2299 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2300 }
2301#endif
2302 }
2303 }
2304 copdisplay.rebuild[1] = copl;
2305
2306 ami_update_par(info);
2307 ami_rebuild_copper(info->par);
2308}
1174 2309
1175static struct fb_ops amifb_ops = {
1176 .owner = THIS_MODULE,
1177 .fb_check_var = amifb_check_var,
1178 .fb_set_par = amifb_set_par,
1179 .fb_setcolreg = amifb_setcolreg,
1180 .fb_blank = amifb_blank,
1181 .fb_pan_display = amifb_pan_display,
1182 .fb_fillrect = amifb_fillrect,
1183 .fb_copyarea = amifb_copyarea,
1184 .fb_imageblit = amifb_imageblit,
1185 .fb_ioctl = amifb_ioctl,
1186};
1187 2310
1188static void __init amifb_setup_mcap(char *spec) 2311static void __init amifb_setup_mcap(char *spec)
1189{ 2312{
@@ -1216,13 +2339,13 @@ static void __init amifb_setup_mcap(char *spec)
1216 if (hmax <= 0 || hmax <= hmin) 2339 if (hmax <= 0 || hmax <= hmin)
1217 return; 2340 return;
1218 2341
1219 fb_info.monspecs.vfmin = vmin; 2342 amifb_hfmin = hmin;
1220 fb_info.monspecs.vfmax = vmax; 2343 amifb_hfmax = hmax;
1221 fb_info.monspecs.hfmin = hmin; 2344 amifb_vfmin = vmin;
1222 fb_info.monspecs.hfmax = hmax; 2345 amifb_vfmax = vmax;
1223} 2346}
1224 2347
1225int __init amifb_setup(char *options) 2348static int __init amifb_setup(char *options)
1226{ 2349{
1227 char *this_opt; 2350 char *this_opt;
1228 2351
@@ -1238,9 +2361,9 @@ int __init amifb_setup(char *options)
1238 } else if (!strcmp(this_opt, "ilbm")) 2361 } else if (!strcmp(this_opt, "ilbm"))
1239 amifb_ilbm = 1; 2362 amifb_ilbm = 1;
1240 else if (!strncmp(this_opt, "monitorcap:", 11)) 2363 else if (!strncmp(this_opt, "monitorcap:", 11))
1241 amifb_setup_mcap(this_opt+11); 2364 amifb_setup_mcap(this_opt + 11);
1242 else if (!strncmp(this_opt, "fstart:", 7)) 2365 else if (!strncmp(this_opt, "fstart:", 7))
1243 min_fstrt = simple_strtoul(this_opt+7, NULL, 0); 2366 min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
1244 else 2367 else
1245 mode_option = this_opt; 2368 mode_option = this_opt;
1246 } 2369 }
@@ -1259,7 +2382,8 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
1259 struct amifb_par par; 2382 struct amifb_par par;
1260 2383
1261 /* Validate wanted screen parameters */ 2384 /* Validate wanted screen parameters */
1262 if ((err = ami_decode_var(var, &par))) 2385 err = ami_decode_var(var, &par, info);
2386 if (err)
1263 return err; 2387 return err;
1264 2388
1265 /* Encode (possibly rounded) screen parameters */ 2389 /* Encode (possibly rounded) screen parameters */
@@ -1270,16 +2394,19 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
1270 2394
1271static int amifb_set_par(struct fb_info *info) 2395static int amifb_set_par(struct fb_info *info)
1272{ 2396{
1273 struct amifb_par *par = (struct amifb_par *)info->par; 2397 struct amifb_par *par = info->par;
2398 int error;
1274 2399
1275 do_vmode_pan = 0; 2400 do_vmode_pan = 0;
1276 do_vmode_full = 0; 2401 do_vmode_full = 0;
1277 2402
1278 /* Decode wanted screen parameters */ 2403 /* Decode wanted screen parameters */
1279 ami_decode_var(&info->var, par); 2404 error = ami_decode_var(&info->var, par, info);
2405 if (error)
2406 return error;
1280 2407
1281 /* Set new videomode */ 2408 /* Set new videomode */
1282 ami_build_copper(); 2409 ami_build_copper(info);
1283 2410
1284 /* Set VBlank trigger */ 2411 /* Set VBlank trigger */
1285 do_vmode_full = 1; 2412 do_vmode_full = 1;
@@ -1295,20 +2422,20 @@ static int amifb_set_par(struct fb_info *info)
1295 info->fix.type = FB_TYPE_PLANES; 2422 info->fix.type = FB_TYPE_PLANES;
1296 info->fix.type_aux = 0; 2423 info->fix.type_aux = 0;
1297 } 2424 }
1298 info->fix.line_length = div8(upx(16<<maxfmode, par->vxres)); 2425 info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
1299 2426
1300 if (par->vmode & FB_VMODE_YWRAP) { 2427 if (par->vmode & FB_VMODE_YWRAP) {
1301 info->fix.ywrapstep = 1; 2428 info->fix.ywrapstep = 1;
1302 info->fix.xpanstep = 0; 2429 info->fix.xpanstep = 0;
1303 info->fix.ypanstep = 0; 2430 info->fix.ypanstep = 0;
1304 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP | 2431 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
1305 FBINFO_READS_FAST; /* override SCROLL_REDRAW */ 2432 FBINFO_READS_FAST; /* override SCROLL_REDRAW */
1306 } else { 2433 } else {
1307 info->fix.ywrapstep = 0; 2434 info->fix.ywrapstep = 0;
1308 if (par->vmode & FB_VMODE_SMOOTH_XPAN) 2435 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
1309 info->fix.xpanstep = 1; 2436 info->fix.xpanstep = 1;
1310 else 2437 else
1311 info->fix.xpanstep = 16<<maxfmode; 2438 info->fix.xpanstep = 16 << maxfmode;
1312 info->fix.ypanstep = 1; 2439 info->fix.ypanstep = 1;
1313 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 2440 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1314 } 2441 }
@@ -1317,6 +2444,95 @@ static int amifb_set_par(struct fb_info *info)
1317 2444
1318 2445
1319 /* 2446 /*
2447 * Set a single color register. The values supplied are already
2448 * rounded down to the hardware's capabilities (according to the
2449 * entries in the var structure). Return != 0 for invalid regno.
2450 */
2451
2452static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2453 u_int transp, struct fb_info *info)
2454{
2455 const struct amifb_par *par = info->par;
2456
2457 if (IS_AGA) {
2458 if (regno > 255)
2459 return 1;
2460 } else if (par->bplcon0 & BPC0_SHRES) {
2461 if (regno > 3)
2462 return 1;
2463 } else {
2464 if (regno > 31)
2465 return 1;
2466 }
2467 red >>= 8;
2468 green >>= 8;
2469 blue >>= 8;
2470 if (!regno) {
2471 red0 = red;
2472 green0 = green;
2473 blue0 = blue;
2474 }
2475
2476 /*
2477 * Update the corresponding Hardware Color Register, unless it's Color
2478 * Register 0 and the screen is blanked.
2479 *
2480 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
2481 * being changed by ami_do_blank() during the VBlank.
2482 */
2483
2484 if (regno || !is_blanked) {
2485#if defined(CONFIG_FB_AMIGA_AGA)
2486 if (IS_AGA) {
2487 u_short bplcon3 = par->bplcon3;
2488 VBlankOff();
2489 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2490 custom.color[regno & 31] = rgb2hw8_high(red, green,
2491 blue);
2492 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2493 BPC3_LOCT;
2494 custom.color[regno & 31] = rgb2hw8_low(red, green,
2495 blue);
2496 custom.bplcon3 = bplcon3;
2497 VBlankOn();
2498 } else
2499#endif
2500#if defined(CONFIG_FB_AMIGA_ECS)
2501 if (par->bplcon0 & BPC0_SHRES) {
2502 u_short color, mask;
2503 int i;
2504
2505 mask = 0x3333;
2506 color = rgb2hw2(red, green, blue);
2507 VBlankOff();
2508 for (i = regno + 12; i >= (int)regno; i -= 4)
2509 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2510 mask <<= 2; color >>= 2;
2511 regno = down16(regno) + mul4(mod4(regno));
2512 for (i = regno + 3; i >= (int)regno; i--)
2513 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2514 VBlankOn();
2515 } else
2516#endif
2517 custom.color[regno] = rgb2hw4(red, green, blue);
2518 }
2519 return 0;
2520}
2521
2522
2523 /*
2524 * Blank the display.
2525 */
2526
2527static int amifb_blank(int blank, struct fb_info *info)
2528{
2529 do_blank = blank ? blank : -1;
2530
2531 return 0;
2532}
2533
2534
2535 /*
1320 * Pan or Wrap the Display 2536 * Pan or Wrap the Display
1321 * 2537 *
1322 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 2538 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
@@ -1327,18 +2543,19 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
1327{ 2543{
1328 if (var->vmode & FB_VMODE_YWRAP) { 2544 if (var->vmode & FB_VMODE_YWRAP) {
1329 if (var->yoffset < 0 || 2545 if (var->yoffset < 0 ||
1330 var->yoffset >= info->var.yres_virtual || var->xoffset) 2546 var->yoffset >= info->var.yres_virtual || var->xoffset)
1331 return -EINVAL; 2547 return -EINVAL;
1332 } else { 2548 } else {
1333 /* 2549 /*
1334 * TODO: There will be problems when xpan!=1, so some columns 2550 * TODO: There will be problems when xpan!=1, so some columns
1335 * on the right side will never be seen 2551 * on the right side will never be seen
1336 */ 2552 */
1337 if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) || 2553 if (var->xoffset + info->var.xres >
1338 var->yoffset+info->var.yres > info->var.yres_virtual) 2554 upx(16 << maxfmode, info->var.xres_virtual) ||
2555 var->yoffset + info->var.yres > info->var.yres_virtual)
1339 return -EINVAL; 2556 return -EINVAL;
1340 } 2557 }
1341 ami_pan_var(var); 2558 ami_pan_var(var, info);
1342 info->var.xoffset = var->xoffset; 2559 info->var.xoffset = var->xoffset;
1343 info->var.yoffset = var->yoffset; 2560 info->var.yoffset = var->yoffset;
1344 if (var->vmode & FB_VMODE_YWRAP) 2561 if (var->vmode & FB_VMODE_YWRAP)
@@ -1360,10 +2577,10 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
1360#endif 2577#endif
1361 2578
1362 2579
1363 /* 2580 /*
1364 * Compose two values, using a bitmask as decision value 2581 * Compose two values, using a bitmask as decision value
1365 * This is equivalent to (a & mask) | (b & ~mask) 2582 * This is equivalent to (a & mask) | (b & ~mask)
1366 */ 2583 */
1367 2584
1368static inline unsigned long comp(unsigned long a, unsigned long b, 2585static inline unsigned long comp(unsigned long a, unsigned long b,
1369 unsigned long mask) 2586 unsigned long mask)
@@ -1379,29 +2596,29 @@ static inline unsigned long xor(unsigned long a, unsigned long b,
1379} 2596}
1380 2597
1381 2598
1382 /* 2599 /*
1383 * Unaligned forward bit copy using 32-bit or 64-bit memory accesses 2600 * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
1384 */ 2601 */
1385 2602
1386static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, 2603static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1387 int src_idx, u32 n) 2604 int src_idx, u32 n)
1388{ 2605{
1389 unsigned long first, last; 2606 unsigned long first, last;
1390 int shift = dst_idx-src_idx, left, right; 2607 int shift = dst_idx - src_idx, left, right;
1391 unsigned long d0, d1; 2608 unsigned long d0, d1;
1392 int m; 2609 int m;
1393 2610
1394 if (!n) 2611 if (!n)
1395 return; 2612 return;
1396 2613
1397 shift = dst_idx-src_idx; 2614 shift = dst_idx - src_idx;
1398 first = ~0UL >> dst_idx; 2615 first = ~0UL >> dst_idx;
1399 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 2616 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1400 2617
1401 if (!shift) { 2618 if (!shift) {
1402 // Same alignment for source and dest 2619 // Same alignment for source and dest
1403 2620
1404 if (dst_idx+n <= BITS_PER_LONG) { 2621 if (dst_idx + n <= BITS_PER_LONG) {
1405 // Single word 2622 // Single word
1406 if (last) 2623 if (last)
1407 first &= last; 2624 first &= last;
@@ -1413,7 +2630,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1413 *dst = comp(*src, *dst, first); 2630 *dst = comp(*src, *dst, first);
1414 dst++; 2631 dst++;
1415 src++; 2632 src++;
1416 n -= BITS_PER_LONG-dst_idx; 2633 n -= BITS_PER_LONG - dst_idx;
1417 } 2634 }
1418 2635
1419 // Main chunk 2636 // Main chunk
@@ -1439,17 +2656,17 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1439 } else { 2656 } else {
1440 // Different alignment for source and dest 2657 // Different alignment for source and dest
1441 2658
1442 right = shift & (BITS_PER_LONG-1); 2659 right = shift & (BITS_PER_LONG - 1);
1443 left = -shift & (BITS_PER_LONG-1); 2660 left = -shift & (BITS_PER_LONG - 1);
1444 2661
1445 if (dst_idx+n <= BITS_PER_LONG) { 2662 if (dst_idx + n <= BITS_PER_LONG) {
1446 // Single destination word 2663 // Single destination word
1447 if (last) 2664 if (last)
1448 first &= last; 2665 first &= last;
1449 if (shift > 0) { 2666 if (shift > 0) {
1450 // Single source word 2667 // Single source word
1451 *dst = comp(*src >> right, *dst, first); 2668 *dst = comp(*src >> right, *dst, first);
1452 } else if (src_idx+n <= BITS_PER_LONG) { 2669 } else if (src_idx + n <= BITS_PER_LONG) {
1453 // Single source word 2670 // Single source word
1454 *dst = comp(*src << left, *dst, first); 2671 *dst = comp(*src << left, *dst, first);
1455 } else { 2672 } else {
@@ -1467,7 +2684,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1467 // Single source word 2684 // Single source word
1468 *dst = comp(d0 >> right, *dst, first); 2685 *dst = comp(d0 >> right, *dst, first);
1469 dst++; 2686 dst++;
1470 n -= BITS_PER_LONG-dst_idx; 2687 n -= BITS_PER_LONG - dst_idx;
1471 } else { 2688 } else {
1472 // 2 source words 2689 // 2 source words
1473 d1 = *src++; 2690 d1 = *src++;
@@ -1475,7 +2692,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1475 first); 2692 first);
1476 d0 = d1; 2693 d0 = d1;
1477 dst++; 2694 dst++;
1478 n -= BITS_PER_LONG-dst_idx; 2695 n -= BITS_PER_LONG - dst_idx;
1479 } 2696 }
1480 2697
1481 // Main chunk 2698 // Main chunk
@@ -1519,40 +2736,40 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1519} 2736}
1520 2737
1521 2738
1522 /* 2739 /*
1523 * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses 2740 * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
1524 */ 2741 */
1525 2742
1526static void bitcpy_rev(unsigned long *dst, int dst_idx, 2743static void bitcpy_rev(unsigned long *dst, int dst_idx,
1527 const unsigned long *src, int src_idx, u32 n) 2744 const unsigned long *src, int src_idx, u32 n)
1528{ 2745{
1529 unsigned long first, last; 2746 unsigned long first, last;
1530 int shift = dst_idx-src_idx, left, right; 2747 int shift = dst_idx - src_idx, left, right;
1531 unsigned long d0, d1; 2748 unsigned long d0, d1;
1532 int m; 2749 int m;
1533 2750
1534 if (!n) 2751 if (!n)
1535 return; 2752 return;
1536 2753
1537 dst += (n-1)/BITS_PER_LONG; 2754 dst += (n - 1) / BITS_PER_LONG;
1538 src += (n-1)/BITS_PER_LONG; 2755 src += (n - 1) / BITS_PER_LONG;
1539 if ((n-1) % BITS_PER_LONG) { 2756 if ((n - 1) % BITS_PER_LONG) {
1540 dst_idx += (n-1) % BITS_PER_LONG; 2757 dst_idx += (n - 1) % BITS_PER_LONG;
1541 dst += dst_idx >> SHIFT_PER_LONG; 2758 dst += dst_idx >> SHIFT_PER_LONG;
1542 dst_idx &= BITS_PER_LONG-1; 2759 dst_idx &= BITS_PER_LONG - 1;
1543 src_idx += (n-1) % BITS_PER_LONG; 2760 src_idx += (n - 1) % BITS_PER_LONG;
1544 src += src_idx >> SHIFT_PER_LONG; 2761 src += src_idx >> SHIFT_PER_LONG;
1545 src_idx &= BITS_PER_LONG-1; 2762 src_idx &= BITS_PER_LONG - 1;
1546 } 2763 }
1547 2764
1548 shift = dst_idx-src_idx; 2765 shift = dst_idx - src_idx;
1549 first = ~0UL << (BITS_PER_LONG-1-dst_idx); 2766 first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
1550 last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG))); 2767 last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
1551 2768
1552 if (!shift) { 2769 if (!shift) {
1553 // Same alignment for source and dest 2770 // Same alignment for source and dest
1554 2771
1555 if ((unsigned long)dst_idx+1 >= n) { 2772 if ((unsigned long)dst_idx + 1 >= n) {
1556 // Single word 2773 // Single word
1557 if (last) 2774 if (last)
1558 first &= last; 2775 first &= last;
@@ -1564,7 +2781,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1564 *dst = comp(*src, *dst, first); 2781 *dst = comp(*src, *dst, first);
1565 dst--; 2782 dst--;
1566 src--; 2783 src--;
1567 n -= dst_idx+1; 2784 n -= dst_idx + 1;
1568 } 2785 }
1569 2786
1570 // Main chunk 2787 // Main chunk
@@ -1590,17 +2807,17 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1590 } else { 2807 } else {
1591 // Different alignment for source and dest 2808 // Different alignment for source and dest
1592 2809
1593 right = shift & (BITS_PER_LONG-1); 2810 right = shift & (BITS_PER_LONG - 1);
1594 left = -shift & (BITS_PER_LONG-1); 2811 left = -shift & (BITS_PER_LONG - 1);
1595 2812
1596 if ((unsigned long)dst_idx+1 >= n) { 2813 if ((unsigned long)dst_idx + 1 >= n) {
1597 // Single destination word 2814 // Single destination word
1598 if (last) 2815 if (last)
1599 first &= last; 2816 first &= last;
1600 if (shift < 0) { 2817 if (shift < 0) {
1601 // Single source word 2818 // Single source word
1602 *dst = comp(*src << left, *dst, first); 2819 *dst = comp(*src << left, *dst, first);
1603 } else if (1+(unsigned long)src_idx >= n) { 2820 } else if (1 + (unsigned long)src_idx >= n) {
1604 // Single source word 2821 // Single source word
1605 *dst = comp(*src >> right, *dst, first); 2822 *dst = comp(*src >> right, *dst, first);
1606 } else { 2823 } else {
@@ -1618,7 +2835,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1618 // Single source word 2835 // Single source word
1619 *dst = comp(d0 << left, *dst, first); 2836 *dst = comp(d0 << left, *dst, first);
1620 dst--; 2837 dst--;
1621 n -= dst_idx+1; 2838 n -= dst_idx + 1;
1622 } else { 2839 } else {
1623 // 2 source words 2840 // 2 source words
1624 d1 = *src--; 2841 d1 = *src--;
@@ -1626,7 +2843,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1626 first); 2843 first);
1627 d0 = d1; 2844 d0 = d1;
1628 dst--; 2845 dst--;
1629 n -= dst_idx+1; 2846 n -= dst_idx + 1;
1630 } 2847 }
1631 2848
1632 // Main chunk 2849 // Main chunk
@@ -1670,30 +2887,30 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1670} 2887}
1671 2888
1672 2889
1673 /* 2890 /*
1674 * Unaligned forward inverting bit copy using 32-bit or 64-bit memory 2891 * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
1675 * accesses 2892 * accesses
1676 */ 2893 */
1677 2894
1678static void bitcpy_not(unsigned long *dst, int dst_idx, 2895static void bitcpy_not(unsigned long *dst, int dst_idx,
1679 const unsigned long *src, int src_idx, u32 n) 2896 const unsigned long *src, int src_idx, u32 n)
1680{ 2897{
1681 unsigned long first, last; 2898 unsigned long first, last;
1682 int shift = dst_idx-src_idx, left, right; 2899 int shift = dst_idx - src_idx, left, right;
1683 unsigned long d0, d1; 2900 unsigned long d0, d1;
1684 int m; 2901 int m;
1685 2902
1686 if (!n) 2903 if (!n)
1687 return; 2904 return;
1688 2905
1689 shift = dst_idx-src_idx; 2906 shift = dst_idx - src_idx;
1690 first = ~0UL >> dst_idx; 2907 first = ~0UL >> dst_idx;
1691 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 2908 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1692 2909
1693 if (!shift) { 2910 if (!shift) {
1694 // Same alignment for source and dest 2911 // Same alignment for source and dest
1695 2912
1696 if (dst_idx+n <= BITS_PER_LONG) { 2913 if (dst_idx + n <= BITS_PER_LONG) {
1697 // Single word 2914 // Single word
1698 if (last) 2915 if (last)
1699 first &= last; 2916 first &= last;
@@ -1705,7 +2922,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1705 *dst = comp(~*src, *dst, first); 2922 *dst = comp(~*src, *dst, first);
1706 dst++; 2923 dst++;
1707 src++; 2924 src++;
1708 n -= BITS_PER_LONG-dst_idx; 2925 n -= BITS_PER_LONG - dst_idx;
1709 } 2926 }
1710 2927
1711 // Main chunk 2928 // Main chunk
@@ -1731,17 +2948,17 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1731 } else { 2948 } else {
1732 // Different alignment for source and dest 2949 // Different alignment for source and dest
1733 2950
1734 right = shift & (BITS_PER_LONG-1); 2951 right = shift & (BITS_PER_LONG - 1);
1735 left = -shift & (BITS_PER_LONG-1); 2952 left = -shift & (BITS_PER_LONG - 1);
1736 2953
1737 if (dst_idx+n <= BITS_PER_LONG) { 2954 if (dst_idx + n <= BITS_PER_LONG) {
1738 // Single destination word 2955 // Single destination word
1739 if (last) 2956 if (last)
1740 first &= last; 2957 first &= last;
1741 if (shift > 0) { 2958 if (shift > 0) {
1742 // Single source word 2959 // Single source word
1743 *dst = comp(~*src >> right, *dst, first); 2960 *dst = comp(~*src >> right, *dst, first);
1744 } else if (src_idx+n <= BITS_PER_LONG) { 2961 } else if (src_idx + n <= BITS_PER_LONG) {
1745 // Single source word 2962 // Single source word
1746 *dst = comp(~*src << left, *dst, first); 2963 *dst = comp(~*src << left, *dst, first);
1747 } else { 2964 } else {
@@ -1759,7 +2976,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1759 // Single source word 2976 // Single source word
1760 *dst = comp(d0 >> right, *dst, first); 2977 *dst = comp(d0 >> right, *dst, first);
1761 dst++; 2978 dst++;
1762 n -= BITS_PER_LONG-dst_idx; 2979 n -= BITS_PER_LONG - dst_idx;
1763 } else { 2980 } else {
1764 // 2 source words 2981 // 2 source words
1765 d1 = ~*src++; 2982 d1 = ~*src++;
@@ -1767,7 +2984,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1767 first); 2984 first);
1768 d0 = d1; 2985 d0 = d1;
1769 dst++; 2986 dst++;
1770 n -= BITS_PER_LONG-dst_idx; 2987 n -= BITS_PER_LONG - dst_idx;
1771 } 2988 }
1772 2989
1773 // Main chunk 2990 // Main chunk
@@ -1811,9 +3028,9 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1811} 3028}
1812 3029
1813 3030
1814 /* 3031 /*
1815 * Unaligned 32-bit pattern fill using 32/64-bit memory accesses 3032 * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
1816 */ 3033 */
1817 3034
1818static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 3035static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1819{ 3036{
@@ -1828,9 +3045,9 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1828#endif 3045#endif
1829 3046
1830 first = ~0UL >> dst_idx; 3047 first = ~0UL >> dst_idx;
1831 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 3048 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1832 3049
1833 if (dst_idx+n <= BITS_PER_LONG) { 3050 if (dst_idx + n <= BITS_PER_LONG) {
1834 // Single word 3051 // Single word
1835 if (last) 3052 if (last)
1836 first &= last; 3053 first &= last;
@@ -1841,7 +3058,7 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1841 if (first) { 3058 if (first) {
1842 *dst = comp(val, *dst, first); 3059 *dst = comp(val, *dst, first);
1843 dst++; 3060 dst++;
1844 n -= BITS_PER_LONG-dst_idx; 3061 n -= BITS_PER_LONG - dst_idx;
1845 } 3062 }
1846 3063
1847 // Main chunk 3064 // Main chunk
@@ -1867,9 +3084,9 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1867} 3084}
1868 3085
1869 3086
1870 /* 3087 /*
1871 * Unaligned 32-bit pattern xor using 32/64-bit memory accesses 3088 * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
1872 */ 3089 */
1873 3090
1874static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 3091static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1875{ 3092{
@@ -1884,9 +3101,9 @@ static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1884#endif 3101#endif
1885 3102
1886 first = ~0UL >> dst_idx; 3103 first = ~0UL >> dst_idx;
1887 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 3104 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1888 3105
1889 if (dst_idx+n <= BITS_PER_LONG) { 3106 if (dst_idx + n <= BITS_PER_LONG) {
1890 // Single word 3107 // Single word
1891 if (last) 3108 if (last)
1892 first &= last; 3109 first &= last;
@@ -1897,7 +3114,7 @@ static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1897 if (first) { 3114 if (first) {
1898 *dst = xor(val, *dst, first); 3115 *dst = xor(val, *dst, first);
1899 dst++; 3116 dst++;
1900 n -= BITS_PER_LONG-dst_idx; 3117 n -= BITS_PER_LONG - dst_idx;
1901 } 3118 }
1902 3119
1903 // Main chunk 3120 // Main chunk
@@ -1924,12 +3141,12 @@ static inline void fill_one_line(int bpp, unsigned long next_plane,
1924{ 3141{
1925 while (1) { 3142 while (1) {
1926 dst += dst_idx >> SHIFT_PER_LONG; 3143 dst += dst_idx >> SHIFT_PER_LONG;
1927 dst_idx &= (BITS_PER_LONG-1); 3144 dst_idx &= (BITS_PER_LONG - 1);
1928 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n); 3145 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1929 if (!--bpp) 3146 if (!--bpp)
1930 break; 3147 break;
1931 color >>= 1; 3148 color >>= 1;
1932 dst_idx += next_plane*8; 3149 dst_idx += next_plane * 8;
1933 } 3150 }
1934} 3151}
1935 3152
@@ -1939,12 +3156,12 @@ static inline void xor_one_line(int bpp, unsigned long next_plane,
1939{ 3156{
1940 while (color) { 3157 while (color) {
1941 dst += dst_idx >> SHIFT_PER_LONG; 3158 dst += dst_idx >> SHIFT_PER_LONG;
1942 dst_idx &= (BITS_PER_LONG-1); 3159 dst_idx &= (BITS_PER_LONG - 1);
1943 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n); 3160 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1944 if (!--bpp) 3161 if (!--bpp)
1945 break; 3162 break;
1946 color >>= 1; 3163 color >>= 1;
1947 dst_idx += next_plane*8; 3164 dst_idx += next_plane * 8;
1948 } 3165 }
1949} 3166}
1950 3167
@@ -1952,7 +3169,7 @@ static inline void xor_one_line(int bpp, unsigned long next_plane,
1952static void amifb_fillrect(struct fb_info *info, 3169static void amifb_fillrect(struct fb_info *info,
1953 const struct fb_fillrect *rect) 3170 const struct fb_fillrect *rect)
1954{ 3171{
1955 struct amifb_par *par = (struct amifb_par *)info->par; 3172 struct amifb_par *par = info->par;
1956 int dst_idx, x2, y2; 3173 int dst_idx, x2, y2;
1957 unsigned long *dst; 3174 unsigned long *dst;
1958 u32 width, height; 3175 u32 width, height;
@@ -1972,23 +3189,23 @@ static void amifb_fillrect(struct fb_info *info,
1972 height = y2 - rect->dy; 3189 height = y2 - rect->dy;
1973 3190
1974 dst = (unsigned long *) 3191 dst = (unsigned long *)
1975 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 3192 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
1976 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 3193 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
1977 dst_idx += rect->dy*par->next_line*8+rect->dx; 3194 dst_idx += rect->dy * par->next_line * 8 + rect->dx;
1978 while (height--) { 3195 while (height--) {
1979 switch (rect->rop) { 3196 switch (rect->rop) {
1980 case ROP_COPY: 3197 case ROP_COPY:
1981 fill_one_line(info->var.bits_per_pixel, 3198 fill_one_line(info->var.bits_per_pixel,
1982 par->next_plane, dst, dst_idx, width, 3199 par->next_plane, dst, dst_idx, width,
1983 rect->color); 3200 rect->color);
1984 break; 3201 break;
1985 3202
1986 case ROP_XOR: 3203 case ROP_XOR:
1987 xor_one_line(info->var.bits_per_pixel, par->next_plane, 3204 xor_one_line(info->var.bits_per_pixel, par->next_plane,
1988 dst, dst_idx, width, rect->color); 3205 dst, dst_idx, width, rect->color);
1989 break; 3206 break;
1990 } 3207 }
1991 dst_idx += par->next_line*8; 3208 dst_idx += par->next_line * 8;
1992 } 3209 }
1993} 3210}
1994 3211
@@ -1998,14 +3215,14 @@ static inline void copy_one_line(int bpp, unsigned long next_plane,
1998{ 3215{
1999 while (1) { 3216 while (1) {
2000 dst += dst_idx >> SHIFT_PER_LONG; 3217 dst += dst_idx >> SHIFT_PER_LONG;
2001 dst_idx &= (BITS_PER_LONG-1); 3218 dst_idx &= (BITS_PER_LONG - 1);
2002 src += src_idx >> SHIFT_PER_LONG; 3219 src += src_idx >> SHIFT_PER_LONG;
2003 src_idx &= (BITS_PER_LONG-1); 3220 src_idx &= (BITS_PER_LONG - 1);
2004 bitcpy(dst, dst_idx, src, src_idx, n); 3221 bitcpy(dst, dst_idx, src, src_idx, n);
2005 if (!--bpp) 3222 if (!--bpp)
2006 break; 3223 break;
2007 dst_idx += next_plane*8; 3224 dst_idx += next_plane * 8;
2008 src_idx += next_plane*8; 3225 src_idx += next_plane * 8;
2009 } 3226 }
2010} 3227}
2011 3228
@@ -2015,14 +3232,14 @@ static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2015{ 3232{
2016 while (1) { 3233 while (1) {
2017 dst += dst_idx >> SHIFT_PER_LONG; 3234 dst += dst_idx >> SHIFT_PER_LONG;
2018 dst_idx &= (BITS_PER_LONG-1); 3235 dst_idx &= (BITS_PER_LONG - 1);
2019 src += src_idx >> SHIFT_PER_LONG; 3236 src += src_idx >> SHIFT_PER_LONG;
2020 src_idx &= (BITS_PER_LONG-1); 3237 src_idx &= (BITS_PER_LONG - 1);
2021 bitcpy_rev(dst, dst_idx, src, src_idx, n); 3238 bitcpy_rev(dst, dst_idx, src, src_idx, n);
2022 if (!--bpp) 3239 if (!--bpp)
2023 break; 3240 break;
2024 dst_idx += next_plane*8; 3241 dst_idx += next_plane * 8;
2025 src_idx += next_plane*8; 3242 src_idx += next_plane * 8;
2026 } 3243 }
2027} 3244}
2028 3245
@@ -2030,7 +3247,7 @@ static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2030static void amifb_copyarea(struct fb_info *info, 3247static void amifb_copyarea(struct fb_info *info,
2031 const struct fb_copyarea *area) 3248 const struct fb_copyarea *area)
2032{ 3249{
2033 struct amifb_par *par = (struct amifb_par *)info->par; 3250 struct amifb_par *par = info->par;
2034 int x2, y2; 3251 int x2, y2;
2035 u32 dx, dy, sx, sy, width, height; 3252 u32 dx, dy, sx, sy, width, height;
2036 unsigned long *dst, *src; 3253 unsigned long *dst, *src;
@@ -2065,16 +3282,16 @@ static void amifb_copyarea(struct fb_info *info,
2065 rev_copy = 1; 3282 rev_copy = 1;
2066 } 3283 }
2067 dst = (unsigned long *) 3284 dst = (unsigned long *)
2068 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 3285 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2069 src = dst; 3286 src = dst;
2070 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 3287 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2071 src_idx = dst_idx; 3288 src_idx = dst_idx;
2072 dst_idx += dy*par->next_line*8+dx; 3289 dst_idx += dy * par->next_line * 8 + dx;
2073 src_idx += sy*par->next_line*8+sx; 3290 src_idx += sy * par->next_line * 8 + sx;
2074 if (rev_copy) { 3291 if (rev_copy) {
2075 while (height--) { 3292 while (height--) {
2076 dst_idx -= par->next_line*8; 3293 dst_idx -= par->next_line * 8;
2077 src_idx -= par->next_line*8; 3294 src_idx -= par->next_line * 8;
2078 copy_one_line_rev(info->var.bits_per_pixel, 3295 copy_one_line_rev(info->var.bits_per_pixel,
2079 par->next_plane, dst, dst_idx, src, 3296 par->next_plane, dst, dst_idx, src,
2080 src_idx, width); 3297 src_idx, width);
@@ -2084,8 +3301,8 @@ static void amifb_copyarea(struct fb_info *info,
2084 copy_one_line(info->var.bits_per_pixel, 3301 copy_one_line(info->var.bits_per_pixel,
2085 par->next_plane, dst, dst_idx, src, 3302 par->next_plane, dst, dst_idx, src,
2086 src_idx, width); 3303 src_idx, width);
2087 dst_idx += par->next_line*8; 3304 dst_idx += par->next_line * 8;
2088 src_idx += par->next_line*8; 3305 src_idx += par->next_line * 8;
2089 } 3306 }
2090 } 3307 }
2091} 3308}
@@ -2095,34 +3312,35 @@ static inline void expand_one_line(int bpp, unsigned long next_plane,
2095 unsigned long *dst, int dst_idx, u32 n, 3312 unsigned long *dst, int dst_idx, u32 n,
2096 const u8 *data, u32 bgcolor, u32 fgcolor) 3313 const u8 *data, u32 bgcolor, u32 fgcolor)
2097{ 3314{
2098 const unsigned long *src; 3315 const unsigned long *src;
2099 int src_idx; 3316 int src_idx;
2100 3317
2101 while (1) { 3318 while (1) {
2102 dst += dst_idx >> SHIFT_PER_LONG; 3319 dst += dst_idx >> SHIFT_PER_LONG;
2103 dst_idx &= (BITS_PER_LONG-1); 3320 dst_idx &= (BITS_PER_LONG - 1);
2104 if ((bgcolor ^ fgcolor) & 1) { 3321 if ((bgcolor ^ fgcolor) & 1) {
2105 src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1)); 3322 src = (unsigned long *)
2106 src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8; 3323 ((unsigned long)data & ~(BYTES_PER_LONG - 1));
2107 if (fgcolor & 1) 3324 src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
2108 bitcpy(dst, dst_idx, src, src_idx, n); 3325 if (fgcolor & 1)
2109 else 3326 bitcpy(dst, dst_idx, src, src_idx, n);
2110 bitcpy_not(dst, dst_idx, src, src_idx, n); 3327 else
2111 /* set or clear */ 3328 bitcpy_not(dst, dst_idx, src, src_idx, n);
2112 } else 3329 /* set or clear */
2113 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n); 3330 } else
2114 if (!--bpp) 3331 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
2115 break; 3332 if (!--bpp)
2116 bgcolor >>= 1; 3333 break;
2117 fgcolor >>= 1; 3334 bgcolor >>= 1;
2118 dst_idx += next_plane*8; 3335 fgcolor >>= 1;
2119 } 3336 dst_idx += next_plane * 8;
3337 }
2120} 3338}
2121 3339
2122 3340
2123static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) 3341static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2124{ 3342{
2125 struct amifb_par *par = (struct amifb_par *)info->par; 3343 struct amifb_par *par = info->par;
2126 int x2, y2; 3344 int x2, y2;
2127 unsigned long *dst; 3345 unsigned long *dst;
2128 int dst_idx; 3346 int dst_idx;
@@ -2145,17 +3363,17 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2145 3363
2146 if (image->depth == 1) { 3364 if (image->depth == 1) {
2147 dst = (unsigned long *) 3365 dst = (unsigned long *)
2148 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 3366 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2149 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 3367 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2150 dst_idx += dy*par->next_line*8+dx; 3368 dst_idx += dy * par->next_line * 8 + dx;
2151 src = image->data; 3369 src = image->data;
2152 pitch = (image->width+7)/8; 3370 pitch = (image->width + 7) / 8;
2153 while (height--) { 3371 while (height--) {
2154 expand_one_line(info->var.bits_per_pixel, 3372 expand_one_line(info->var.bits_per_pixel,
2155 par->next_plane, dst, dst_idx, width, 3373 par->next_plane, dst, dst_idx, width,
2156 src, image->bg_color, 3374 src, image->bg_color,
2157 image->fg_color); 3375 image->fg_color);
2158 dst_idx += par->next_line*8; 3376 dst_idx += par->next_line * 8;
2159 src += pitch; 3377 src += pitch;
2160 } 3378 }
2161 } else { 3379 } else {
@@ -2182,45 +3400,119 @@ static int amifb_ioctl(struct fb_info *info,
2182 int i; 3400 int i;
2183 3401
2184 switch (cmd) { 3402 switch (cmd) {
2185 case FBIOGET_FCURSORINFO: 3403 case FBIOGET_FCURSORINFO:
2186 i = ami_get_fix_cursorinfo(&crsr.fix); 3404 i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
2187 if (i) 3405 if (i)
2188 return i; 3406 return i;
2189 return copy_to_user(argp, &crsr.fix, 3407 return copy_to_user(argp, &crsr.fix,
2190 sizeof(crsr.fix)) ? -EFAULT : 0; 3408 sizeof(crsr.fix)) ? -EFAULT : 0;
2191 3409
2192 case FBIOGET_VCURSORINFO: 3410 case FBIOGET_VCURSORINFO:
2193 i = ami_get_var_cursorinfo(&crsr.var, 3411 i = ami_get_var_cursorinfo(&crsr.var,
2194 ((struct fb_var_cursorinfo __user *)arg)->data); 3412 ((struct fb_var_cursorinfo __user *)arg)->data,
2195 if (i) 3413 info->par);
2196 return i; 3414 if (i)
2197 return copy_to_user(argp, &crsr.var, 3415 return i;
2198 sizeof(crsr.var)) ? -EFAULT : 0; 3416 return copy_to_user(argp, &crsr.var,
2199 3417 sizeof(crsr.var)) ? -EFAULT : 0;
2200 case FBIOPUT_VCURSORINFO: 3418
2201 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) 3419 case FBIOPUT_VCURSORINFO:
2202 return -EFAULT; 3420 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
2203 return ami_set_var_cursorinfo(&crsr.var, 3421 return -EFAULT;
2204 ((struct fb_var_cursorinfo __user *)arg)->data); 3422 return ami_set_var_cursorinfo(&crsr.var,
2205 3423 ((struct fb_var_cursorinfo __user *)arg)->data,
2206 case FBIOGET_CURSORSTATE: 3424 info->par);
2207 i = ami_get_cursorstate(&crsr.state); 3425
2208 if (i) 3426 case FBIOGET_CURSORSTATE:
2209 return i; 3427 i = ami_get_cursorstate(&crsr.state, info->par);
2210 return copy_to_user(argp, &crsr.state, 3428 if (i)
2211 sizeof(crsr.state)) ? -EFAULT : 0; 3429 return i;
2212 3430 return copy_to_user(argp, &crsr.state,
2213 case FBIOPUT_CURSORSTATE: 3431 sizeof(crsr.state)) ? -EFAULT : 0;
2214 if (copy_from_user(&crsr.state, argp, 3432
2215 sizeof(crsr.state))) 3433 case FBIOPUT_CURSORSTATE:
2216 return -EFAULT; 3434 if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
2217 return ami_set_cursorstate(&crsr.state); 3435 return -EFAULT;
3436 return ami_set_cursorstate(&crsr.state, info->par);
2218 } 3437 }
2219 return -EINVAL; 3438 return -EINVAL;
2220} 3439}
2221 3440
2222 3441
2223 /* 3442 /*
3443 * Flash the cursor (called by VBlank interrupt)
3444 */
3445
3446static int flash_cursor(void)
3447{
3448 static int cursorcount = 1;
3449
3450 if (cursormode == FB_CURSOR_FLASH) {
3451 if (!--cursorcount) {
3452 cursorstate = -cursorstate;
3453 cursorcount = cursorrate;
3454 if (!is_blanked)
3455 return 1;
3456 }
3457 }
3458 return 0;
3459}
3460
3461 /*
3462 * VBlank Display Interrupt
3463 */
3464
3465static irqreturn_t amifb_interrupt(int irq, void *dev_id)
3466{
3467 struct amifb_par *par = dev_id;
3468
3469 if (do_vmode_pan || do_vmode_full)
3470 ami_update_display(par);
3471
3472 if (do_vmode_full)
3473 ami_init_display(par);
3474
3475 if (do_vmode_pan) {
3476 flash_cursor();
3477 ami_rebuild_copper(par);
3478 do_cursor = do_vmode_pan = 0;
3479 } else if (do_cursor) {
3480 flash_cursor();
3481 ami_set_sprite(par);
3482 do_cursor = 0;
3483 } else {
3484 if (flash_cursor())
3485 ami_set_sprite(par);
3486 }
3487
3488 if (do_blank) {
3489 ami_do_blank(par);
3490 do_blank = 0;
3491 }
3492
3493 if (do_vmode_full) {
3494 ami_reinit_copper(par);
3495 do_vmode_full = 0;
3496 }
3497 return IRQ_HANDLED;
3498}
3499
3500
3501static struct fb_ops amifb_ops = {
3502 .owner = THIS_MODULE,
3503 .fb_check_var = amifb_check_var,
3504 .fb_set_par = amifb_set_par,
3505 .fb_setcolreg = amifb_setcolreg,
3506 .fb_blank = amifb_blank,
3507 .fb_pan_display = amifb_pan_display,
3508 .fb_fillrect = amifb_fillrect,
3509 .fb_copyarea = amifb_copyarea,
3510 .fb_imageblit = amifb_imageblit,
3511 .fb_ioctl = amifb_ioctl,
3512};
3513
3514
3515 /*
2224 * Allocate, Clear and Align a Block of Chip Memory 3516 * Allocate, Clear and Align a Block of Chip Memory
2225 */ 3517 */
2226 3518
@@ -2250,6 +3542,7 @@ static inline void chipfree(void)
2250 3542
2251static int __init amifb_probe(struct platform_device *pdev) 3543static int __init amifb_probe(struct platform_device *pdev)
2252{ 3544{
3545 struct fb_info *info;
2253 int tag, i, err = 0; 3546 int tag, i, err = 0;
2254 u_long chipptr; 3547 u_long chipptr;
2255 u_int defmode; 3548 u_int defmode;
@@ -2265,71 +3558,80 @@ static int __init amifb_probe(struct platform_device *pdev)
2265#endif 3558#endif
2266 custom.dmacon = DMAF_ALL | DMAF_MASTER; 3559 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2267 3560
3561 info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
3562 if (!info) {
3563 dev_err(&pdev->dev, "framebuffer_alloc failed\n");
3564 return -ENOMEM;
3565 }
3566
3567 strcpy(info->fix.id, "Amiga ");
3568 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3569 info->fix.accel = FB_ACCEL_AMIGABLITT;
3570
2268 switch (amiga_chipset) { 3571 switch (amiga_chipset) {
2269#ifdef CONFIG_FB_AMIGA_OCS 3572#ifdef CONFIG_FB_AMIGA_OCS
2270 case CS_OCS: 3573 case CS_OCS:
2271 strcat(fb_info.fix.id, "OCS"); 3574 strcat(info->fix.id, "OCS");
2272default_chipset: 3575default_chipset:
2273 chipset = TAG_OCS; 3576 chipset = TAG_OCS;
2274 maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ 3577 maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
2275 maxdepth[TAG_HIRES] = 4; 3578 maxdepth[TAG_HIRES] = 4;
2276 maxdepth[TAG_LORES] = 6; 3579 maxdepth[TAG_LORES] = 6;
2277 maxfmode = TAG_FMODE_1; 3580 maxfmode = TAG_FMODE_1;
2278 defmode = amiga_vblank == 50 ? DEFMODE_PAL 3581 defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
2279 : DEFMODE_NTSC; 3582 info->fix.smem_len = VIDEOMEMSIZE_OCS;
2280 fb_info.fix.smem_len = VIDEOMEMSIZE_OCS; 3583 break;
2281 break;
2282#endif /* CONFIG_FB_AMIGA_OCS */ 3584#endif /* CONFIG_FB_AMIGA_OCS */
2283 3585
2284#ifdef CONFIG_FB_AMIGA_ECS 3586#ifdef CONFIG_FB_AMIGA_ECS
2285 case CS_ECS: 3587 case CS_ECS:
2286 strcat(fb_info.fix.id, "ECS"); 3588 strcat(info->fix.id, "ECS");
2287 chipset = TAG_ECS; 3589 chipset = TAG_ECS;
2288 maxdepth[TAG_SHRES] = 2; 3590 maxdepth[TAG_SHRES] = 2;
2289 maxdepth[TAG_HIRES] = 4; 3591 maxdepth[TAG_HIRES] = 4;
2290 maxdepth[TAG_LORES] = 6; 3592 maxdepth[TAG_LORES] = 6;
2291 maxfmode = TAG_FMODE_1; 3593 maxfmode = TAG_FMODE_1;
2292 if (AMIGAHW_PRESENT(AMBER_FF)) 3594 if (AMIGAHW_PRESENT(AMBER_FF))
2293 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL 3595 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
2294 : DEFMODE_AMBER_NTSC; 3596 : DEFMODE_AMBER_NTSC;
2295 else 3597 else
2296 defmode = amiga_vblank == 50 ? DEFMODE_PAL 3598 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2297 : DEFMODE_NTSC; 3599 : DEFMODE_NTSC;
2298 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 3600 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
2299 VIDEOMEMSIZE_ECS_2M) 3601 VIDEOMEMSIZE_ECS_2M)
2300 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; 3602 info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
2301 else 3603 else
2302 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; 3604 info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
2303 break; 3605 break;
2304#endif /* CONFIG_FB_AMIGA_ECS */ 3606#endif /* CONFIG_FB_AMIGA_ECS */
2305 3607
2306#ifdef CONFIG_FB_AMIGA_AGA 3608#ifdef CONFIG_FB_AMIGA_AGA
2307 case CS_AGA: 3609 case CS_AGA:
2308 strcat(fb_info.fix.id, "AGA"); 3610 strcat(info->fix.id, "AGA");
2309 chipset = TAG_AGA; 3611 chipset = TAG_AGA;
2310 maxdepth[TAG_SHRES] = 8; 3612 maxdepth[TAG_SHRES] = 8;
2311 maxdepth[TAG_HIRES] = 8; 3613 maxdepth[TAG_HIRES] = 8;
2312 maxdepth[TAG_LORES] = 8; 3614 maxdepth[TAG_LORES] = 8;
2313 maxfmode = TAG_FMODE_4; 3615 maxfmode = TAG_FMODE_4;
2314 defmode = DEFMODE_AGA; 3616 defmode = DEFMODE_AGA;
2315 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 3617 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
2316 VIDEOMEMSIZE_AGA_2M) 3618 VIDEOMEMSIZE_AGA_2M)
2317 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; 3619 info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
2318 else 3620 else
2319 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; 3621 info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
2320 break; 3622 break;
2321#endif /* CONFIG_FB_AMIGA_AGA */ 3623#endif /* CONFIG_FB_AMIGA_AGA */
2322 3624
2323 default: 3625 default:
2324#ifdef CONFIG_FB_AMIGA_OCS 3626#ifdef CONFIG_FB_AMIGA_OCS
2325 printk("Unknown graphics chipset, defaulting to OCS\n"); 3627 printk("Unknown graphics chipset, defaulting to OCS\n");
2326 strcat(fb_info.fix.id, "Unknown"); 3628 strcat(info->fix.id, "Unknown");
2327 goto default_chipset; 3629 goto default_chipset;
2328#else /* CONFIG_FB_AMIGA_OCS */ 3630#else /* CONFIG_FB_AMIGA_OCS */
2329 err = -ENODEV; 3631 err = -ENODEV;
2330 goto amifb_error; 3632 goto release;
2331#endif /* CONFIG_FB_AMIGA_OCS */ 3633#endif /* CONFIG_FB_AMIGA_OCS */
2332 break; 3634 break;
2333 } 3635 }
2334 3636
2335 /* 3637 /*
@@ -2356,42 +3658,44 @@ default_chipset:
2356 } 3658 }
2357 } 3659 }
2358 3660
2359 /* 3661 if (amifb_hfmin) {
2360 * These monitor specs are for a typical Amiga monitor (e.g. A1960) 3662 info->monspecs.hfmin = amifb_hfmin;
2361 */ 3663 info->monspecs.hfmax = amifb_hfmax;
2362 if (fb_info.monspecs.hfmin == 0) { 3664 info->monspecs.vfmin = amifb_vfmin;
2363 fb_info.monspecs.hfmin = 15000; 3665 info->monspecs.vfmax = amifb_vfmax;
2364 fb_info.monspecs.hfmax = 38000; 3666 } else {
2365 fb_info.monspecs.vfmin = 49; 3667 /*
2366 fb_info.monspecs.vfmax = 90; 3668 * These are for a typical Amiga monitor (e.g. A1960)
3669 */
3670 info->monspecs.hfmin = 15000;
3671 info->monspecs.hfmax = 38000;
3672 info->monspecs.vfmin = 49;
3673 info->monspecs.vfmax = 90;
2367 } 3674 }
2368 3675
2369 fb_info.fbops = &amifb_ops; 3676 info->fbops = &amifb_ops;
2370 fb_info.par = &currentpar; 3677 info->flags = FBINFO_DEFAULT;
2371 fb_info.flags = FBINFO_DEFAULT; 3678 info->device = &pdev->dev;
2372 fb_info.device = &pdev->dev;
2373 3679
2374 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, 3680 if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
2375 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { 3681 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
2376 err = -EINVAL; 3682 err = -EINVAL;
2377 goto amifb_error; 3683 goto release;
2378 } 3684 }
2379 3685
2380 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, 3686 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
2381 &fb_info.modelist); 3687 &info->modelist);
2382 3688
2383 round_down_bpp = 0; 3689 round_down_bpp = 0;
2384 chipptr = chipalloc(fb_info.fix.smem_len+ 3690 chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
2385 SPRITEMEMSIZE+ 3691 DUMMYSPRITEMEMSIZE + COPINITSIZE +
2386 DUMMYSPRITEMEMSIZE+ 3692 4 * COPLISTSIZE);
2387 COPINITSIZE+
2388 4*COPLISTSIZE);
2389 if (!chipptr) { 3693 if (!chipptr) {
2390 err = -ENOMEM; 3694 err = -ENOMEM;
2391 goto amifb_error; 3695 goto release;
2392 } 3696 }
2393 3697
2394 assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); 3698 assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
2395 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); 3699 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
2396 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE); 3700 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
2397 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE); 3701 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
@@ -2403,1398 +3707,78 @@ default_chipset:
2403 /* 3707 /*
2404 * access the videomem with writethrough cache 3708 * access the videomem with writethrough cache
2405 */ 3709 */
2406 fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory); 3710 info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
2407 videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start, 3711 videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
2408 fb_info.fix.smem_len); 3712 info->fix.smem_len);
2409 if (!videomemory) { 3713 if (!videomemory) {
2410 printk("amifb: WARNING! unable to map videomem cached writethrough\n"); 3714 dev_warn(&pdev->dev,
2411 fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); 3715 "Unable to map videomem cached writethrough\n");
3716 info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
2412 } else 3717 } else
2413 fb_info.screen_base = (char *)videomemory; 3718 info->screen_base = (char *)videomemory;
2414 3719
2415 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); 3720 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
2416 3721
2417 /* 3722 /*
2418 * Enable Display DMA
2419 */
2420
2421 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2422 DMAF_BLITTER | DMAF_SPRITE;
2423
2424 /*
2425 * Make sure the Copper has something to do 3723 * Make sure the Copper has something to do
2426 */ 3724 */
2427
2428 ami_init_copper(); 3725 ami_init_copper();
2429 3726
2430 if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
2431 "fb vertb handler", &currentpar)) {
2432 err = -EBUSY;
2433 goto amifb_error;
2434 }
2435
2436 err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
2437 if (err)
2438 goto amifb_error;
2439
2440 if (register_framebuffer(&fb_info) < 0) {
2441 err = -EINVAL;
2442 goto amifb_error;
2443 }
2444
2445 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2446 fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
2447
2448 return 0;
2449
2450amifb_error:
2451 amifb_deinit(pdev);
2452 return err;
2453}
2454
2455static void amifb_deinit(struct platform_device *pdev)
2456{
2457 if (fb_info.cmap.len)
2458 fb_dealloc_cmap(&fb_info.cmap);
2459 fb_dealloc_cmap(&fb_info.cmap);
2460 chipfree();
2461 if (videomemory)
2462 iounmap((void*)videomemory);
2463 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2464}
2465
2466
2467 /*
2468 * Blank the display.
2469 */
2470
2471static int amifb_blank(int blank, struct fb_info *info)
2472{
2473 do_blank = blank ? blank : -1;
2474
2475 return 0;
2476}
2477
2478 /*
2479 * Flash the cursor (called by VBlank interrupt)
2480 */
2481
2482static int flash_cursor(void)
2483{
2484 static int cursorcount = 1;
2485
2486 if (cursormode == FB_CURSOR_FLASH) {
2487 if (!--cursorcount) {
2488 cursorstate = -cursorstate;
2489 cursorcount = cursorrate;
2490 if (!is_blanked)
2491 return 1;
2492 }
2493 }
2494 return 0;
2495}
2496
2497 /*
2498 * VBlank Display Interrupt
2499 */
2500
2501static irqreturn_t amifb_interrupt(int irq, void *dev_id)
2502{
2503 if (do_vmode_pan || do_vmode_full)
2504 ami_update_display();
2505
2506 if (do_vmode_full)
2507 ami_init_display();
2508
2509 if (do_vmode_pan) {
2510 flash_cursor();
2511 ami_rebuild_copper();
2512 do_cursor = do_vmode_pan = 0;
2513 } else if (do_cursor) {
2514 flash_cursor();
2515 ami_set_sprite();
2516 do_cursor = 0;
2517 } else {
2518 if (flash_cursor())
2519 ami_set_sprite();
2520 }
2521
2522 if (do_blank) {
2523 ami_do_blank();
2524 do_blank = 0;
2525 }
2526
2527 if (do_vmode_full) {
2528 ami_reinit_copper();
2529 do_vmode_full = 0;
2530 }
2531 return IRQ_HANDLED;
2532}
2533
2534/* --------------------------- Hardware routines --------------------------- */
2535
2536 /*
2537 * Get the video params out of `var'. If a value doesn't fit, round
2538 * it up, if it's too big, return -EINVAL.
2539 */
2540
2541static int ami_decode_var(struct fb_var_screeninfo *var,
2542 struct amifb_par *par)
2543{
2544 u_short clk_shift, line_shift;
2545 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
2546 u_int htotal, vtotal;
2547
2548 /*
2549 * Find a matching Pixel Clock
2550 */
2551
2552 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
2553 if (var->pixclock <= pixclock[clk_shift])
2554 break;
2555 if (clk_shift > TAG_LORES) {
2556 DPRINTK("pixclock too high\n");
2557 return -EINVAL;
2558 }
2559 par->clk_shift = clk_shift;
2560
2561 /*
2562 * Check the Geometry Values
2563 */
2564
2565 if ((par->xres = var->xres) < 64)
2566 par->xres = 64;
2567 if ((par->yres = var->yres) < 64)
2568 par->yres = 64;
2569 if ((par->vxres = var->xres_virtual) < par->xres)
2570 par->vxres = par->xres;
2571 if ((par->vyres = var->yres_virtual) < par->yres)
2572 par->vyres = par->yres;
2573
2574 par->bpp = var->bits_per_pixel;
2575 if (!var->nonstd) {
2576 if (par->bpp < 1)
2577 par->bpp = 1;
2578 if (par->bpp > maxdepth[clk_shift]) {
2579 if (round_down_bpp && maxdepth[clk_shift])
2580 par->bpp = maxdepth[clk_shift];
2581 else {
2582 DPRINTK("invalid bpp\n");
2583 return -EINVAL;
2584 }
2585 }
2586 } else if (var->nonstd == FB_NONSTD_HAM) {
2587 if (par->bpp < 6)
2588 par->bpp = 6;
2589 if (par->bpp != 6) {
2590 if (par->bpp < 8)
2591 par->bpp = 8;
2592 if (par->bpp != 8 || !IS_AGA) {
2593 DPRINTK("invalid bpp for ham mode\n");
2594 return -EINVAL;
2595 }
2596 }
2597 } else {
2598 DPRINTK("unknown nonstd mode\n");
2599 return -EINVAL;
2600 }
2601
2602 /*
2603 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
2604 * checks failed and smooth scrolling is not possible
2605 */
2606
2607 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
2608 switch (par->vmode & FB_VMODE_MASK) {
2609 case FB_VMODE_INTERLACED:
2610 line_shift = 0;
2611 break;
2612 case FB_VMODE_NONINTERLACED:
2613 line_shift = 1;
2614 break;
2615 case FB_VMODE_DOUBLE:
2616 if (!IS_AGA) {
2617 DPRINTK("double mode only possible with aga\n");
2618 return -EINVAL;
2619 }
2620 line_shift = 2;
2621 break;
2622 default:
2623 DPRINTK("unknown video mode\n");
2624 return -EINVAL;
2625 break;
2626 }
2627 par->line_shift = line_shift;
2628
2629 /*
2630 * Vertical and Horizontal Timings
2631 */
2632
2633 xres_n = par->xres<<clk_shift;
2634 yres_n = par->yres<<line_shift;
2635 par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
2636 par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
2637
2638 if (IS_AGA)
2639 par->bplcon3 = sprpixmode[clk_shift];
2640 else
2641 par->bplcon3 = 0;
2642 if (var->sync & FB_SYNC_BROADCAST) {
2643 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
2644 if (IS_AGA)
2645 par->diwstop_h += mod4(var->hsync_len);
2646 else
2647 par->diwstop_h = down4(par->diwstop_h);
2648
2649 par->diwstrt_h = par->diwstop_h - xres_n;
2650 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
2651 par->diwstrt_v = par->diwstop_v - yres_n;
2652 if (par->diwstop_h >= par->htotal+8) {
2653 DPRINTK("invalid diwstop_h\n");
2654 return -EINVAL;
2655 }
2656 if (par->diwstop_v > par->vtotal) {
2657 DPRINTK("invalid diwstop_v\n");
2658 return -EINVAL;
2659 }
2660
2661 if (!IS_OCS) {
2662 /* Initialize sync with some reasonable values for pwrsave */
2663 par->hsstrt = 160;
2664 par->hsstop = 320;
2665 par->vsstrt = 30;
2666 par->vsstop = 34;
2667 } else {
2668 par->hsstrt = 0;
2669 par->hsstop = 0;
2670 par->vsstrt = 0;
2671 par->vsstop = 0;
2672 }
2673 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
2674 /* PAL video mode */
2675 if (par->htotal != PAL_HTOTAL) {
2676 DPRINTK("htotal invalid for pal\n");
2677 return -EINVAL;
2678 }
2679 if (par->diwstrt_h < PAL_DIWSTRT_H) {
2680 DPRINTK("diwstrt_h too low for pal\n");
2681 return -EINVAL;
2682 }
2683 if (par->diwstrt_v < PAL_DIWSTRT_V) {
2684 DPRINTK("diwstrt_v too low for pal\n");
2685 return -EINVAL;
2686 }
2687 htotal = PAL_HTOTAL>>clk_shift;
2688 vtotal = PAL_VTOTAL>>1;
2689 if (!IS_OCS) {
2690 par->beamcon0 = BMC0_PAL;
2691 par->bplcon3 |= BPC3_BRDRBLNK;
2692 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2693 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2694 par->beamcon0 = BMC0_PAL;
2695 par->hsstop = 1;
2696 } else if (amiga_vblank != 50) {
2697 DPRINTK("pal not supported by this chipset\n");
2698 return -EINVAL;
2699 }
2700 } else {
2701 /* NTSC video mode
2702 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
2703 * and NTSC activated, so than better let diwstop_h <= 1812
2704 */
2705 if (par->htotal != NTSC_HTOTAL) {
2706 DPRINTK("htotal invalid for ntsc\n");
2707 return -EINVAL;
2708 }
2709 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
2710 DPRINTK("diwstrt_h too low for ntsc\n");
2711 return -EINVAL;
2712 }
2713 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
2714 DPRINTK("diwstrt_v too low for ntsc\n");
2715 return -EINVAL;
2716 }
2717 htotal = NTSC_HTOTAL>>clk_shift;
2718 vtotal = NTSC_VTOTAL>>1;
2719 if (!IS_OCS) {
2720 par->beamcon0 = 0;
2721 par->bplcon3 |= BPC3_BRDRBLNK;
2722 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2723 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2724 par->beamcon0 = 0;
2725 par->hsstop = 1;
2726 } else if (amiga_vblank != 60) {
2727 DPRINTK("ntsc not supported by this chipset\n");
2728 return -EINVAL;
2729 }
2730 }
2731 if (IS_OCS) {
2732 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
2733 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
2734 DPRINTK("invalid position for display on ocs\n");
2735 return -EINVAL;
2736 }
2737 }
2738 } else if (!IS_OCS) {
2739 /* Programmable video mode */
2740 par->hsstrt = var->right_margin<<clk_shift;
2741 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
2742 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
2743 if (!IS_AGA)
2744 par->diwstop_h = down4(par->diwstop_h) - 16;
2745 par->diwstrt_h = par->diwstop_h - xres_n;
2746 par->hbstop = par->diwstrt_h + 4;
2747 par->hbstrt = par->diwstop_h + 4;
2748 if (par->hbstrt >= par->htotal + 8)
2749 par->hbstrt -= par->htotal;
2750 par->hcenter = par->hsstrt + (par->htotal >> 1);
2751 par->vsstrt = var->lower_margin<<line_shift;
2752 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
2753 par->diwstop_v = par->vtotal;
2754 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
2755 par->diwstop_v -= 2;
2756 par->diwstrt_v = par->diwstop_v - yres_n;
2757 par->vbstop = par->diwstrt_v - 2;
2758 par->vbstrt = par->diwstop_v - 2;
2759 if (par->vtotal > 2048) {
2760 DPRINTK("vtotal too high\n");
2761 return -EINVAL;
2762 }
2763 if (par->htotal > 2048) {
2764 DPRINTK("htotal too high\n");
2765 return -EINVAL;
2766 }
2767 par->bplcon3 |= BPC3_EXTBLKEN;
2768 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
2769 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
2770 BMC0_PAL | BMC0_VARCSYEN;
2771 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
2772 par->beamcon0 |= BMC0_HSYTRUE;
2773 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
2774 par->beamcon0 |= BMC0_VSYTRUE;
2775 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
2776 par->beamcon0 |= BMC0_CSYTRUE;
2777 htotal = par->htotal>>clk_shift;
2778 vtotal = par->vtotal>>1;
2779 } else {
2780 DPRINTK("only broadcast modes possible for ocs\n");
2781 return -EINVAL;
2782 }
2783
2784 /*
2785 * Checking the DMA timing
2786 */
2787
2788 fconst = 16<<maxfmode<<clk_shift;
2789
2790 /*
2791 * smallest window start value without turn off other dma cycles
2792 * than sprite1-7, unless you change min_fstrt
2793 */
2794
2795
2796 fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
2797 fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
2798 if (fstrt < min_fstrt) {
2799 DPRINTK("fetch start too low\n");
2800 return -EINVAL;
2801 }
2802
2803 /*
2804 * smallest window start value where smooth scrolling is possible
2805 */
2806
2807 fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
2808 if (fstrt < min_fstrt)
2809 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2810
2811 maxfetchstop = down16(par->htotal - 80);
2812
2813 fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
2814 fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
2815 if (fstrt + fsize > maxfetchstop)
2816 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2817
2818 fsize = upx(fconst, xres_n);
2819 if (fstrt + fsize > maxfetchstop) {
2820 DPRINTK("fetch stop too high\n");
2821 return -EINVAL;
2822 }
2823
2824 if (maxfmode + clk_shift <= 1) {
2825 fsize = up64(xres_n + fconst - 1);
2826 if (min_fstrt + fsize - 64 > maxfetchstop)
2827 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2828
2829 fsize = up64(xres_n);
2830 if (min_fstrt + fsize - 64 > maxfetchstop) {
2831 DPRINTK("fetch size too high\n");
2832 return -EINVAL;
2833 }
2834
2835 fsize -= 64;
2836 } else
2837 fsize -= fconst;
2838
2839 /*
2840 * Check if there is enough time to update the bitplane pointers for ywrap
2841 */
2842
2843 if (par->htotal-fsize-64 < par->bpp*64)
2844 par->vmode &= ~FB_VMODE_YWRAP;
2845
2846 /*
2847 * Bitplane calculations and check the Memory Requirements
2848 */
2849
2850 if (amifb_ilbm) {
2851 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
2852 par->next_line = par->bpp*par->next_plane;
2853 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
2854 DPRINTK("too few video mem\n");
2855 return -EINVAL;
2856 }
2857 } else {
2858 par->next_line = div8(upx(16<<maxfmode, par->vxres));
2859 par->next_plane = par->vyres*par->next_line;
2860 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
2861 DPRINTK("too few video mem\n");
2862 return -EINVAL;
2863 }
2864 }
2865
2866 /*
2867 * Hardware Register Values
2868 */
2869
2870 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
2871 if (!IS_OCS)
2872 par->bplcon0 |= BPC0_ECSENA;
2873 if (par->bpp == 8)
2874 par->bplcon0 |= BPC0_BPU3;
2875 else
2876 par->bplcon0 |= par->bpp<<12;
2877 if (var->nonstd == FB_NONSTD_HAM)
2878 par->bplcon0 |= BPC0_HAM;
2879 if (var->sync & FB_SYNC_EXT)
2880 par->bplcon0 |= BPC0_ERSY;
2881
2882 if (IS_AGA)
2883 par->fmode = bplfetchmode[maxfmode];
2884
2885 switch (par->vmode & FB_VMODE_MASK) {
2886 case FB_VMODE_INTERLACED:
2887 par->bplcon0 |= BPC0_LACE;
2888 break;
2889 case FB_VMODE_DOUBLE:
2890 if (IS_AGA)
2891 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
2892 break;
2893 }
2894
2895 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
2896 par->xoffset = var->xoffset;
2897 par->yoffset = var->yoffset;
2898 if (par->vmode & FB_VMODE_YWRAP) {
2899 if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
2900 par->xoffset = par->yoffset = 0;
2901 } else {
2902 if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
2903 par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
2904 par->xoffset = par->yoffset = 0;
2905 }
2906 } else
2907 par->xoffset = par->yoffset = 0;
2908
2909 par->crsr.crsr_x = par->crsr.crsr_y = 0;
2910 par->crsr.spot_x = par->crsr.spot_y = 0;
2911 par->crsr.height = par->crsr.width = 0;
2912
2913 return 0;
2914}
2915
2916 /*
2917 * Fill the `var' structure based on the values in `par' and maybe
2918 * other values read out of the hardware.
2919 */
2920
2921static int ami_encode_var(struct fb_var_screeninfo *var,
2922 struct amifb_par *par)
2923{
2924 u_short clk_shift, line_shift;
2925
2926 memset(var, 0, sizeof(struct fb_var_screeninfo));
2927
2928 clk_shift = par->clk_shift;
2929 line_shift = par->line_shift;
2930
2931 var->xres = par->xres;
2932 var->yres = par->yres;
2933 var->xres_virtual = par->vxres;
2934 var->yres_virtual = par->vyres;
2935 var->xoffset = par->xoffset;
2936 var->yoffset = par->yoffset;
2937
2938 var->bits_per_pixel = par->bpp;
2939 var->grayscale = 0;
2940
2941 var->red.offset = 0;
2942 var->red.msb_right = 0;
2943 var->red.length = par->bpp;
2944 if (par->bplcon0 & BPC0_HAM)
2945 var->red.length -= 2;
2946 var->blue = var->green = var->red;
2947 var->transp.offset = 0;
2948 var->transp.length = 0;
2949 var->transp.msb_right = 0;
2950
2951 if (par->bplcon0 & BPC0_HAM)
2952 var->nonstd = FB_NONSTD_HAM;
2953 else
2954 var->nonstd = 0;
2955 var->activate = 0;
2956
2957 var->height = -1;
2958 var->width = -1;
2959
2960 var->pixclock = pixclock[clk_shift];
2961
2962 if (IS_AGA && par->fmode & FMODE_BSCAN2)
2963 var->vmode = FB_VMODE_DOUBLE;
2964 else if (par->bplcon0 & BPC0_LACE)
2965 var->vmode = FB_VMODE_INTERLACED;
2966 else
2967 var->vmode = FB_VMODE_NONINTERLACED;
2968
2969 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
2970 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
2971 var->right_margin = par->hsstrt>>clk_shift;
2972 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2973 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
2974 var->lower_margin = par->vsstrt>>line_shift;
2975 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
2976 var->sync = 0;
2977 if (par->beamcon0 & BMC0_HSYTRUE)
2978 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2979 if (par->beamcon0 & BMC0_VSYTRUE)
2980 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2981 if (par->beamcon0 & BMC0_CSYTRUE)
2982 var->sync |= FB_SYNC_COMP_HIGH_ACT;
2983 } else {
2984 var->sync = FB_SYNC_BROADCAST;
2985 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
2986 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
2987 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2988 var->vsync_len = 4>>line_shift;
2989 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
2990 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
2991 var->lower_margin - var->vsync_len;
2992 }
2993
2994 if (par->bplcon0 & BPC0_ERSY)
2995 var->sync |= FB_SYNC_EXT;
2996 if (par->vmode & FB_VMODE_YWRAP)
2997 var->vmode |= FB_VMODE_YWRAP;
2998
2999 return 0;
3000}
3001
3002
3003 /* 3727 /*
3004 * Pan or Wrap the Display 3728 * Enable Display DMA
3005 *
3006 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
3007 * in `var'.
3008 */
3009
3010static void ami_pan_var(struct fb_var_screeninfo *var)
3011{
3012 struct amifb_par *par = &currentpar;
3013
3014 par->xoffset = var->xoffset;
3015 par->yoffset = var->yoffset;
3016 if (var->vmode & FB_VMODE_YWRAP)
3017 par->vmode |= FB_VMODE_YWRAP;
3018 else
3019 par->vmode &= ~FB_VMODE_YWRAP;
3020
3021 do_vmode_pan = 0;
3022 ami_update_par();
3023 do_vmode_pan = 1;
3024}
3025
3026 /*
3027 * Update hardware
3028 */
3029
3030static int ami_update_par(void)
3031{
3032 struct amifb_par *par = &currentpar;
3033 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
3034
3035 clk_shift = par->clk_shift;
3036
3037 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
3038 par->xoffset = upx(16<<maxfmode, par->xoffset);
3039
3040 fconst = 16<<maxfmode<<clk_shift;
3041 vshift = modx(16<<maxfmode, par->xoffset);
3042 fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
3043 fsize = (par->xres+vshift)<<clk_shift;
3044 shift = modx(fconst, fstrt);
3045 move = downx(2<<maxfmode, div8(par->xoffset));
3046 if (maxfmode + clk_shift > 1) {
3047 fstrt = downx(fconst, fstrt) - 64;
3048 fsize = upx(fconst, fsize);
3049 fstop = fstrt + fsize - fconst;
3050 } else {
3051 mod = fstrt = downx(fconst, fstrt) - fconst;
3052 fstop = fstrt + upx(fconst, fsize) - 64;
3053 fsize = up64(fsize);
3054 fstrt = fstop - fsize + 64;
3055 if (fstrt < min_fstrt) {
3056 fstop += min_fstrt - fstrt;
3057 fstrt = min_fstrt;
3058 }
3059 move = move - div8((mod-fstrt)>>clk_shift);
3060 }
3061 mod = par->next_line - div8(fsize>>clk_shift);
3062 par->ddfstrt = fstrt;
3063 par->ddfstop = fstop;
3064 par->bplcon1 = hscroll2hw(shift);
3065 par->bpl2mod = mod;
3066 if (par->bplcon0 & BPC0_LACE)
3067 par->bpl2mod += par->next_line;
3068 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
3069 par->bpl1mod = -div8(fsize>>clk_shift);
3070 else
3071 par->bpl1mod = par->bpl2mod;
3072
3073 if (par->yoffset) {
3074 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
3075 if (par->vmode & FB_VMODE_YWRAP) {
3076 if (par->yoffset > par->vyres-par->yres) {
3077 par->bplpt0wrap = fb_info.fix.smem_start + move;
3078 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
3079 par->bplpt0wrap += par->next_line;
3080 }
3081 }
3082 } else
3083 par->bplpt0 = fb_info.fix.smem_start + move;
3084
3085 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
3086 par->bplpt0 += par->next_line;
3087
3088 return 0;
3089}
3090
3091
3092 /*
3093 * Set a single color register. The values supplied are already
3094 * rounded down to the hardware's capabilities (according to the
3095 * entries in the var structure). Return != 0 for invalid regno.
3096 */
3097
3098static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3099 u_int transp, struct fb_info *info)
3100{
3101 if (IS_AGA) {
3102 if (regno > 255)
3103 return 1;
3104 } else if (currentpar.bplcon0 & BPC0_SHRES) {
3105 if (regno > 3)
3106 return 1;
3107 } else {
3108 if (regno > 31)
3109 return 1;
3110 }
3111 red >>= 8;
3112 green >>= 8;
3113 blue >>= 8;
3114 if (!regno) {
3115 red0 = red;
3116 green0 = green;
3117 blue0 = blue;
3118 }
3119
3120 /*
3121 * Update the corresponding Hardware Color Register, unless it's Color
3122 * Register 0 and the screen is blanked.
3123 *
3124 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
3125 * being changed by ami_do_blank() during the VBlank.
3126 */
3127
3128 if (regno || !is_blanked) {
3129#if defined(CONFIG_FB_AMIGA_AGA)
3130 if (IS_AGA) {
3131 u_short bplcon3 = currentpar.bplcon3;
3132 VBlankOff();
3133 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3134 custom.color[regno&31] = rgb2hw8_high(red, green, blue);
3135 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3136 custom.color[regno&31] = rgb2hw8_low(red, green, blue);
3137 custom.bplcon3 = bplcon3;
3138 VBlankOn();
3139 } else
3140#endif
3141#if defined(CONFIG_FB_AMIGA_ECS)
3142 if (currentpar.bplcon0 & BPC0_SHRES) {
3143 u_short color, mask;
3144 int i;
3145
3146 mask = 0x3333;
3147 color = rgb2hw2(red, green, blue);
3148 VBlankOff();
3149 for (i = regno+12; i >= (int)regno; i -= 4)
3150 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3151 mask <<=2; color >>= 2;
3152 regno = down16(regno)+mul4(mod4(regno));
3153 for (i = regno+3; i >= (int)regno; i--)
3154 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3155 VBlankOn();
3156 } else
3157#endif
3158 custom.color[regno] = rgb2hw4(red, green, blue);
3159 }
3160 return 0;
3161}
3162
3163static void ami_update_display(void)
3164{
3165 struct amifb_par *par = &currentpar;
3166
3167 custom.bplcon1 = par->bplcon1;
3168 custom.bpl1mod = par->bpl1mod;
3169 custom.bpl2mod = par->bpl2mod;
3170 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
3171 custom.ddfstop = ddfstop2hw(par->ddfstop);
3172}
3173
3174 /*
3175 * Change the video mode (called by VBlank interrupt)
3176 */
3177
3178static void ami_init_display(void)
3179{
3180 struct amifb_par *par = &currentpar;
3181 int i;
3182
3183 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
3184 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
3185 if (!IS_OCS) {
3186 custom.bplcon3 = par->bplcon3;
3187 if (IS_AGA)
3188 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3189 if (par->beamcon0 & BMC0_VARBEAMEN) {
3190 custom.htotal = htotal2hw(par->htotal);
3191 custom.hbstrt = hbstrt2hw(par->hbstrt);
3192 custom.hbstop = hbstop2hw(par->hbstop);
3193 custom.hsstrt = hsstrt2hw(par->hsstrt);
3194 custom.hsstop = hsstop2hw(par->hsstop);
3195 custom.hcenter = hcenter2hw(par->hcenter);
3196 custom.vtotal = vtotal2hw(par->vtotal);
3197 custom.vbstrt = vbstrt2hw(par->vbstrt);
3198 custom.vbstop = vbstop2hw(par->vbstop);
3199 custom.vsstrt = vsstrt2hw(par->vsstrt);
3200 custom.vsstop = vsstop2hw(par->vsstop);
3201 }
3202 }
3203 if (!IS_OCS || par->hsstop)
3204 custom.beamcon0 = par->beamcon0;
3205 if (IS_AGA)
3206 custom.fmode = par->fmode;
3207
3208 /*
3209 * The minimum period for audio depends on htotal
3210 */
3211
3212 amiga_audio_min_period = div16(par->htotal);
3213
3214 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
3215#if 1
3216 if (is_lace) {
3217 i = custom.vposr >> 15;
3218 } else {
3219 custom.vposw = custom.vposr | 0x8000;
3220 i = 1;
3221 }
3222#else
3223 i = 1;
3224 custom.vposw = custom.vposr | 0x8000;
3225#endif
3226 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
3227}
3228
3229 /*
3230 * (Un)Blank the screen (called by VBlank interrupt)
3231 */ 3729 */
3730 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3731 DMAF_BLITTER | DMAF_SPRITE;
3232 3732
3233static void ami_do_blank(void) 3733 err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
3234{ 3734 "fb vertb handler", info->par);
3235 struct amifb_par *par = &currentpar; 3735 if (err)
3236#if defined(CONFIG_FB_AMIGA_AGA) 3736 goto disable_dma;
3237 u_short bplcon3 = par->bplcon3;
3238#endif
3239 u_char red, green, blue;
3240
3241 if (do_blank > 0) {
3242 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3243 red = green = blue = 0;
3244 if (!IS_OCS && do_blank > 1) {
3245 switch (do_blank) {
3246 case FB_BLANK_VSYNC_SUSPEND:
3247 custom.hsstrt = hsstrt2hw(par->hsstrt);
3248 custom.hsstop = hsstop2hw(par->hsstop);
3249 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3250 custom.vsstop = vsstop2hw(par->vtotal+4);
3251 break;
3252 case FB_BLANK_HSYNC_SUSPEND:
3253 custom.hsstrt = hsstrt2hw(par->htotal+16);
3254 custom.hsstop = hsstop2hw(par->htotal+16);
3255 custom.vsstrt = vsstrt2hw(par->vsstrt);
3256 custom.vsstop = vsstrt2hw(par->vsstop);
3257 break;
3258 case FB_BLANK_POWERDOWN:
3259 custom.hsstrt = hsstrt2hw(par->htotal+16);
3260 custom.hsstop = hsstop2hw(par->htotal+16);
3261 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3262 custom.vsstop = vsstop2hw(par->vtotal+4);
3263 break;
3264 }
3265 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
3266 custom.htotal = htotal2hw(par->htotal);
3267 custom.vtotal = vtotal2hw(par->vtotal);
3268 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
3269 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
3270 }
3271 }
3272 } else {
3273 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
3274 red = red0;
3275 green = green0;
3276 blue = blue0;
3277 if (!IS_OCS) {
3278 custom.hsstrt = hsstrt2hw(par->hsstrt);
3279 custom.hsstop = hsstop2hw(par->hsstop);
3280 custom.vsstrt = vsstrt2hw(par->vsstrt);
3281 custom.vsstop = vsstop2hw(par->vsstop);
3282 custom.beamcon0 = par->beamcon0;
3283 }
3284 }
3285#if defined(CONFIG_FB_AMIGA_AGA)
3286 if (IS_AGA) {
3287 custom.bplcon3 = bplcon3;
3288 custom.color[0] = rgb2hw8_high(red, green, blue);
3289 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3290 custom.color[0] = rgb2hw8_low(red, green, blue);
3291 custom.bplcon3 = bplcon3;
3292 } else
3293#endif
3294#if defined(CONFIG_FB_AMIGA_ECS)
3295 if (par->bplcon0 & BPC0_SHRES) {
3296 u_short color, mask;
3297 int i;
3298
3299 mask = 0x3333;
3300 color = rgb2hw2(red, green, blue);
3301 for (i = 12; i >= 0; i -= 4)
3302 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3303 mask <<=2; color >>= 2;
3304 for (i = 3; i >= 0; i--)
3305 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3306 } else
3307#endif
3308 custom.color[0] = rgb2hw4(red, green, blue);
3309 is_blanked = do_blank > 0 ? do_blank : 0;
3310}
3311
3312static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
3313{
3314 struct amifb_par *par = &currentpar;
3315
3316 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
3317 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
3318 fix->crsr_color1 = 17;
3319 fix->crsr_color2 = 18;
3320 return 0;
3321}
3322
3323static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3324{
3325 struct amifb_par *par = &currentpar;
3326 register u_short *lspr, *sspr;
3327#ifdef __mc68000__
3328 register u_long datawords asm ("d2");
3329#else
3330 register u_long datawords;
3331#endif
3332 register short delta;
3333 register u_char color;
3334 short height, width, bits, words;
3335 int size, alloc;
3336
3337 size = par->crsr.height*par->crsr.width;
3338 alloc = var->height*var->width;
3339 var->height = par->crsr.height;
3340 var->width = par->crsr.width;
3341 var->xspot = par->crsr.spot_x;
3342 var->yspot = par->crsr.spot_y;
3343 if (size > var->height*var->width)
3344 return -ENAMETOOLONG;
3345 if (!access_ok(VERIFY_WRITE, data, size))
3346 return -EFAULT;
3347 delta = 1<<par->crsr.fmode;
3348 lspr = lofsprite + (delta<<1);
3349 if (par->bplcon0 & BPC0_LACE)
3350 sspr = shfsprite + (delta<<1);
3351 else
3352 sspr = NULL;
3353 for (height = (short)var->height-1; height >= 0; height--) {
3354 bits = 0; words = delta; datawords = 0;
3355 for (width = (short)var->width-1; width >= 0; width--) {
3356 if (bits == 0) {
3357 bits = 16; --words;
3358#ifdef __mc68000__
3359 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
3360 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
3361#else
3362 datawords = (*(lspr+delta) << 16) | (*lspr++);
3363#endif
3364 }
3365 --bits;
3366#ifdef __mc68000__
3367 asm volatile (
3368 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
3369 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
3370 : "=d" (color), "=d" (datawords) : "1" (datawords));
3371#else
3372 color = (((datawords >> 30) & 2)
3373 | ((datawords >> 15) & 1));
3374 datawords <<= 1;
3375#endif
3376 put_user(color, data++);
3377 }
3378 if (bits > 0) {
3379 --words; ++lspr;
3380 }
3381 while (--words >= 0)
3382 ++lspr;
3383#ifdef __mc68000__
3384 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3385 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3386#else
3387 lspr += delta;
3388 if (sspr) {
3389 u_short *tmp = lspr;
3390 lspr = sspr;
3391 sspr = tmp;
3392 }
3393#endif
3394 }
3395 return 0;
3396}
3397
3398static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3399{
3400 struct amifb_par *par = &currentpar;
3401 register u_short *lspr, *sspr;
3402#ifdef __mc68000__
3403 register u_long datawords asm ("d2");
3404#else
3405 register u_long datawords;
3406#endif
3407 register short delta;
3408 u_short fmode;
3409 short height, width, bits, words;
3410 3737
3411 if (!var->width) 3738 err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
3412 return -EINVAL; 3739 if (err)
3413 else if (var->width <= 16) 3740 goto free_irq;
3414 fmode = TAG_FMODE_1;
3415 else if (var->width <= 32)
3416 fmode = TAG_FMODE_2;
3417 else if (var->width <= 64)
3418 fmode = TAG_FMODE_4;
3419 else
3420 return -EINVAL;
3421 if (fmode > maxfmode)
3422 return -EINVAL;
3423 if (!var->height)
3424 return -EINVAL;
3425 if (!access_ok(VERIFY_READ, data, var->width*var->height))
3426 return -EFAULT;
3427 delta = 1<<fmode;
3428 lofsprite = shfsprite = (u_short *)spritememory;
3429 lspr = lofsprite + (delta<<1);
3430 if (par->bplcon0 & BPC0_LACE) {
3431 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
3432 return -EINVAL;
3433 memset(lspr, 0, (var->height+4)<<fmode<<2);
3434 shfsprite += ((var->height+5)&-2)<<fmode;
3435 sspr = shfsprite + (delta<<1);
3436 } else {
3437 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
3438 return -EINVAL;
3439 memset(lspr, 0, (var->height+2)<<fmode<<2);
3440 sspr = NULL;
3441 }
3442 for (height = (short)var->height-1; height >= 0; height--) {
3443 bits = 16; words = delta; datawords = 0;
3444 for (width = (short)var->width-1; width >= 0; width--) {
3445 unsigned long tdata = 0;
3446 get_user(tdata, data);
3447 data++;
3448#ifdef __mc68000__
3449 asm volatile (
3450 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
3451 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
3452 : "=d" (datawords)
3453 : "0" (datawords), "d" (tdata));
3454#else
3455 datawords = ((datawords << 1) & 0xfffefffe);
3456 datawords |= tdata & 1;
3457 datawords |= (tdata & 2) << (16-1);
3458#endif
3459 if (--bits == 0) {
3460 bits = 16; --words;
3461#ifdef __mc68000__
3462 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
3463 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
3464#else
3465 *(lspr+delta) = (u_short) (datawords >> 16);
3466 *lspr++ = (u_short) (datawords & 0xffff);
3467#endif
3468 }
3469 }
3470 if (bits < 16) {
3471 --words;
3472#ifdef __mc68000__
3473 asm volatile (
3474 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
3475 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
3476 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
3477#else
3478 *(lspr+delta) = (u_short) (datawords >> (16+bits));
3479 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
3480#endif
3481 }
3482 while (--words >= 0) {
3483#ifdef __mc68000__
3484 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
3485 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
3486#else
3487 *(lspr+delta) = 0;
3488 *lspr++ = 0;
3489#endif
3490 }
3491#ifdef __mc68000__
3492 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3493 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3494#else
3495 lspr += delta;
3496 if (sspr) {
3497 u_short *tmp = lspr;
3498 lspr = sspr;
3499 sspr = tmp;
3500 }
3501#endif
3502 }
3503 par->crsr.height = var->height;
3504 par->crsr.width = var->width;
3505 par->crsr.spot_x = var->xspot;
3506 par->crsr.spot_y = var->yspot;
3507 par->crsr.fmode = fmode;
3508 if (IS_AGA) {
3509 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
3510 par->fmode |= sprfetchmode[fmode];
3511 custom.fmode = par->fmode;
3512 }
3513 return 0;
3514}
3515 3741
3516static int ami_get_cursorstate(struct fb_cursorstate *state) 3742 dev_set_drvdata(&pdev->dev, info);
3517{
3518 struct amifb_par *par = &currentpar;
3519 3743
3520 state->xoffset = par->crsr.crsr_x; 3744 err = register_framebuffer(info);
3521 state->yoffset = par->crsr.crsr_y; 3745 if (err)
3522 state->mode = cursormode; 3746 goto unset_drvdata;
3523 return 0;
3524}
3525 3747
3526static int ami_set_cursorstate(struct fb_cursorstate *state) 3748 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
3527{ 3749 info->node, info->fix.id, info->fix.smem_len>>10);
3528 struct amifb_par *par = &currentpar;
3529 3750
3530 par->crsr.crsr_x = state->xoffset;
3531 par->crsr.crsr_y = state->yoffset;
3532 if ((cursormode = state->mode) == FB_CURSOR_OFF)
3533 cursorstate = -1;
3534 do_cursor = 1;
3535 return 0; 3751 return 0;
3536}
3537
3538static void ami_set_sprite(void)
3539{
3540 struct amifb_par *par = &currentpar;
3541 copins *copl, *cops;
3542 u_short hs, vs, ve;
3543 u_long pl, ps, pt;
3544 short mx, my;
3545
3546 cops = copdisplay.list[currentcop][0];
3547 copl = copdisplay.list[currentcop][1];
3548 ps = pl = ZTWO_PADDR(dummysprite);
3549 mx = par->crsr.crsr_x-par->crsr.spot_x;
3550 my = par->crsr.crsr_y-par->crsr.spot_y;
3551 if (!(par->vmode & FB_VMODE_YWRAP)) {
3552 mx -= par->xoffset;
3553 my -= par->yoffset;
3554 }
3555 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
3556 mx > -(short)par->crsr.width && mx < par->xres &&
3557 my > -(short)par->crsr.height && my < par->yres) {
3558 pl = ZTWO_PADDR(lofsprite);
3559 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
3560 vs = par->diwstrt_v + (my<<par->line_shift);
3561 ve = vs + (par->crsr.height<<par->line_shift);
3562 if (par->bplcon0 & BPC0_LACE) {
3563 ps = ZTWO_PADDR(shfsprite);
3564 lofsprite[0] = spr2hw_pos(vs, hs);
3565 shfsprite[0] = spr2hw_pos(vs+1, hs);
3566 if (mod2(vs)) {
3567 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3568 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
3569 pt = pl; pl = ps; ps = pt;
3570 } else {
3571 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
3572 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
3573 }
3574 } else {
3575 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
3576 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3577 }
3578 }
3579 copl[cop_spr0ptrh].w[1] = highw(pl);
3580 copl[cop_spr0ptrl].w[1] = loww(pl);
3581 if (par->bplcon0 & BPC0_LACE) {
3582 cops[cop_spr0ptrh].w[1] = highw(ps);
3583 cops[cop_spr0ptrl].w[1] = loww(ps);
3584 }
3585}
3586
3587
3588 /*
3589 * Initialise the Copper Initialisation List
3590 */
3591
3592static void __init ami_init_copper(void)
3593{
3594 copins *cop = copdisplay.init;
3595 u_long p;
3596 int i;
3597
3598 if (!IS_OCS) {
3599 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3600 (cop++)->l = CMOVE(0x0181, diwstrt);
3601 (cop++)->l = CMOVE(0x0281, diwstop);
3602 (cop++)->l = CMOVE(0x0000, diwhigh);
3603 } else
3604 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
3605 p = ZTWO_PADDR(dummysprite);
3606 for (i = 0; i < 8; i++) {
3607 (cop++)->l = CMOVE(0, spr[i].pos);
3608 (cop++)->l = CMOVE(highw(p), sprpt[i]);
3609 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
3610 }
3611
3612 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
3613 copdisplay.wait = cop;
3614 (cop++)->l = CEND;
3615 (cop++)->l = CMOVE(0, copjmp2);
3616 cop->l = CEND;
3617
3618 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
3619 custom.copjmp1 = 0;
3620}
3621 3752
3622static void ami_reinit_copper(void) 3753unset_drvdata:
3623{ 3754 dev_set_drvdata(&pdev->dev, NULL);
3624 struct amifb_par *par = &currentpar; 3755 fb_dealloc_cmap(&info->cmap);
3625 3756free_irq:
3626 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0; 3757 free_irq(IRQ_AMIGA_COPPER, info->par);
3627 copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4); 3758disable_dma:
3759 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3760 if (videomemory)
3761 iounmap((void *)videomemory);
3762 chipfree();
3763release:
3764 framebuffer_release(info);
3765 return err;
3628} 3766}
3629 3767
3630 /*
3631 * Build the Copper List
3632 */
3633
3634static void ami_build_copper(void)
3635{
3636 struct amifb_par *par = &currentpar;
3637 copins *copl, *cops;
3638 u_long p;
3639
3640 currentcop = 1 - currentcop;
3641
3642 copl = copdisplay.list[currentcop][1];
3643
3644 (copl++)->l = CWAIT(0, 10);
3645 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
3646 (copl++)->l = CMOVE(0, sprpt[0]);
3647 (copl++)->l = CMOVE2(0, sprpt[0]);
3648
3649 if (par->bplcon0 & BPC0_LACE) {
3650 cops = copdisplay.list[currentcop][0];
3651
3652 (cops++)->l = CWAIT(0, 10);
3653 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
3654 (cops++)->l = CMOVE(0, sprpt[0]);
3655 (cops++)->l = CMOVE2(0, sprpt[0]);
3656
3657 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
3658 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
3659 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3660 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3661 if (!IS_OCS) {
3662 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
3663 par->diwstop_h, par->diwstop_v+1), diwhigh);
3664 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3665 par->diwstop_h, par->diwstop_v), diwhigh);
3666#if 0
3667 if (par->beamcon0 & BMC0_VARBEAMEN) {
3668 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3669 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
3670 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
3671 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3672 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3673 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3674 }
3675#endif
3676 }
3677 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
3678 (copl++)->l = CMOVE(highw(p), cop2lc);
3679 (copl++)->l = CMOVE2(loww(p), cop2lc);
3680 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
3681 (cops++)->l = CMOVE(highw(p), cop2lc);
3682 (cops++)->l = CMOVE2(loww(p), cop2lc);
3683 copdisplay.rebuild[0] = cops;
3684 } else {
3685 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3686 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3687 if (!IS_OCS) {
3688 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3689 par->diwstop_h, par->diwstop_v), diwhigh);
3690#if 0
3691 if (par->beamcon0 & BMC0_VARBEAMEN) {
3692 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3693 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3694 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3695 }
3696#endif
3697 }
3698 }
3699 copdisplay.rebuild[1] = copl;
3700
3701 ami_update_par();
3702 ami_rebuild_copper();
3703}
3704
3705 /*
3706 * Rebuild the Copper List
3707 *
3708 * We only change the things that are not static
3709 */
3710
3711static void ami_rebuild_copper(void)
3712{
3713 struct amifb_par *par = &currentpar;
3714 copins *copl, *cops;
3715 u_short line, h_end1, h_end2;
3716 short i;
3717 u_long p;
3718
3719 if (IS_AGA && maxfmode + par->clk_shift == 0)
3720 h_end1 = par->diwstrt_h-64;
3721 else
3722 h_end1 = par->htotal-32;
3723 h_end2 = par->ddfstop+64;
3724
3725 ami_set_sprite();
3726
3727 copl = copdisplay.rebuild[1];
3728 p = par->bplpt0;
3729 if (par->vmode & FB_VMODE_YWRAP) {
3730 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
3731 if (par->yoffset > par->vyres-par->yres) {
3732 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3733 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3734 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3735 }
3736 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
3737 while (line >= 512) {
3738 (copl++)->l = CWAIT(h_end1, 510);
3739 line -= 512;
3740 }
3741 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3742 (copl++)->l = CWAIT(h_end1, line);
3743 else
3744 (copl++)->l = CWAIT(h_end2, line);
3745 p = par->bplpt0wrap;
3746 }
3747 } else p = par->bplpt0wrap;
3748 }
3749 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3750 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3751 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3752 }
3753 copl->l = CEND;
3754
3755 if (par->bplcon0 & BPC0_LACE) {
3756 cops = copdisplay.rebuild[0];
3757 p = par->bplpt0;
3758 if (mod2(par->diwstrt_v))
3759 p -= par->next_line;
3760 else
3761 p += par->next_line;
3762 if (par->vmode & FB_VMODE_YWRAP) {
3763 if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
3764 if (par->yoffset > par->vyres-par->yres+1) {
3765 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3766 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3767 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3768 }
3769 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
3770 while (line >= 512) {
3771 (cops++)->l = CWAIT(h_end1, 510);
3772 line -= 512;
3773 }
3774 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3775 (cops++)->l = CWAIT(h_end1, line);
3776 else
3777 (cops++)->l = CWAIT(h_end2, line);
3778 p = par->bplpt0wrap;
3779 if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
3780 p -= par->next_line;
3781 else
3782 p += par->next_line;
3783 }
3784 } else p = par->bplpt0wrap - par->next_line;
3785 }
3786 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3787 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3788 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3789 }
3790 cops->l = CEND;
3791 }
3792}
3793 3768
3794static int __exit amifb_remove(struct platform_device *pdev) 3769static int __exit amifb_remove(struct platform_device *pdev)
3795{ 3770{
3796 unregister_framebuffer(&fb_info); 3771 struct fb_info *info = dev_get_drvdata(&pdev->dev);
3797 amifb_deinit(pdev); 3772
3773 unregister_framebuffer(info);
3774 dev_set_drvdata(&pdev->dev, NULL);
3775 fb_dealloc_cmap(&info->cmap);
3776 free_irq(IRQ_AMIGA_COPPER, info->par);
3777 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3778 if (videomemory)
3779 iounmap((void *)videomemory);
3780 chipfree();
3781 framebuffer_release(info);
3798 amifb_video_off(); 3782 amifb_video_off();
3799 return 0; 3783 return 0;
3800} 3784}
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 63409c122ae8..ced4419e56e2 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -100,8 +100,11 @@ static int atmel_bl_update_status(struct backlight_device *bl)
100 brightness = 0; 100 brightness = 0;
101 101
102 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); 102 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
103 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 103 if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
104 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
104 brightness ? contrast_ctr : 0); 105 brightness ? contrast_ctr : 0);
106 else
107 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
105 108
106 bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; 109 bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
107 110
@@ -397,7 +400,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
397 var->lower_margin = min_t(u32, var->lower_margin, 400 var->lower_margin = min_t(u32, var->lower_margin,
398 ATMEL_LCDC_VFP); 401 ATMEL_LCDC_VFP);
399 var->right_margin = min_t(u32, var->right_margin, 402 var->right_margin = min_t(u32, var->right_margin,
400 (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1); 403 (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 2);
401 var->hsync_len = min_t(u32, var->hsync_len, 404 var->hsync_len = min_t(u32, var->hsync_len,
402 (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1); 405 (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
403 var->left_margin = min_t(u32, var->left_margin, 406 var->left_margin = min_t(u32, var->left_margin,
@@ -582,7 +585,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
582 lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); 585 lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
583 586
584 /* Horizontal timing */ 587 /* Horizontal timing */
585 value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; 588 value = (info->var.right_margin - 2) << ATMEL_LCDC_HFP_OFFSET;
586 value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; 589 value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
587 value |= (info->var.left_margin - 1); 590 value |= (info->var.left_margin - 1);
588 dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); 591 dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
@@ -682,14 +685,30 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
682 685
683 case FB_VISUAL_PSEUDOCOLOR: 686 case FB_VISUAL_PSEUDOCOLOR:
684 if (regno < 256) { 687 if (regno < 256) {
685 val = ((red >> 11) & 0x001f); 688 if (cpu_is_at91sam9261() || cpu_is_at91sam9263()
686 val |= ((green >> 6) & 0x03e0); 689 || cpu_is_at91sam9rl()) {
687 val |= ((blue >> 1) & 0x7c00); 690 /* old style I+BGR:555 */
688 691 val = ((red >> 11) & 0x001f);
689 /* 692 val |= ((green >> 6) & 0x03e0);
690 * TODO: intensity bit. Maybe something like 693 val |= ((blue >> 1) & 0x7c00);
691 * ~(red[10] ^ green[10] ^ blue[10]) & 1 694
692 */ 695 /*
696 * TODO: intensity bit. Maybe something like
697 * ~(red[10] ^ green[10] ^ blue[10]) & 1
698 */
699 } else {
700 /* new style BGR:565 / RGB:565 */
701 if (sinfo->lcd_wiring_mode ==
702 ATMEL_LCDC_WIRING_RGB) {
703 val = ((blue >> 11) & 0x001f);
704 val |= ((red >> 0) & 0xf800);
705 } else {
706 val = ((red >> 11) & 0x001f);
707 val |= ((blue >> 0) & 0xf800);
708 }
709
710 val |= ((green >> 5) & 0x07e0);
711 }
693 712
694 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 713 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
695 ret = 0; 714 ret = 0;
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 6df7c54db0a3..6ea505c6f0c8 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -280,52 +280,74 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
280#endif /* CONFIG_PCI */ 280#endif /* CONFIG_PCI */
281 281
282#ifdef CONFIG_ZORRO 282#ifdef CONFIG_ZORRO
283static const struct zorro_device_id cirrusfb_zorro_table[] = { 283struct zorrocl {
284 enum cirrus_board type; /* Board type */
285 u32 regoffset; /* Offset of registers in first Zorro device */
286 u32 ramsize; /* Size of video RAM in first Zorro device */
287 /* If zero, use autoprobe on RAM device */
288 u32 ramoffset; /* Offset of video RAM in first Zorro device */
289 zorro_id ramid; /* Zorro ID of RAM device */
290 zorro_id ramid2; /* Zorro ID of optional second RAM device */
291};
292
293static const struct zorrocl zcl_sd64 __devinitconst = {
294 .type = BT_SD64,
295 .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
296};
297
298static const struct zorrocl zcl_piccolo __devinitconst = {
299 .type = BT_PICCOLO,
300 .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
301};
302
303static const struct zorrocl zcl_picasso __devinitconst = {
304 .type = BT_PICASSO,
305 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
306};
307
308static const struct zorrocl zcl_spectrum __devinitconst = {
309 .type = BT_SPECTRUM,
310 .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
311};
312
313static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
314 .type = BT_PICASSO4,
315 .regoffset = 0x00600000,
316 .ramsize = 4 * MB_,
317 .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
318};
319
320static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
321 .type = BT_PICASSO4,
322 .regoffset = 0x10000,
323 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
324 .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
325};
326
327
328static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
284 { 329 {
285 .id = ZORRO_PROD_HELFRICH_SD64_RAM, 330 .id = ZORRO_PROD_HELFRICH_SD64_REG,
286 .driver_data = BT_SD64, 331 .driver_data = (unsigned long)&zcl_sd64,
287 }, { 332 }, {
288 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 333 .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
289 .driver_data = BT_PICCOLO, 334 .driver_data = (unsigned long)&zcl_piccolo,
290 }, { 335 }, {
291 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 336 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
292 .driver_data = BT_PICASSO, 337 .driver_data = (unsigned long)&zcl_picasso,
293 }, { 338 }, {
294 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 339 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
295 .driver_data = BT_SPECTRUM, 340 .driver_data = (unsigned long)&zcl_spectrum,
296 }, { 341 }, {
297 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 342 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
298 .driver_data = BT_PICASSO4, 343 .driver_data = (unsigned long)&zcl_picasso4_z3,
344 }, {
345 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
346 .driver_data = (unsigned long)&zcl_picasso4_z2,
299 }, 347 },
300 { 0 } 348 { 0 }
301}; 349};
302MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); 350MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
303
304static const struct {
305 zorro_id id2;
306 unsigned long size;
307} cirrusfb_zorro_table2[] = {
308 [BT_SD64] = {
309 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
310 .size = 0x400000
311 },
312 [BT_PICCOLO] = {
313 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
314 .size = 0x200000
315 },
316 [BT_PICASSO] = {
317 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
318 .size = 0x200000
319 },
320 [BT_SPECTRUM] = {
321 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
322 .size = 0x200000
323 },
324 [BT_PICASSO4] = {
325 .id2 = 0,
326 .size = 0x400000
327 }
328};
329#endif /* CONFIG_ZORRO */ 351#endif /* CONFIG_ZORRO */
330 352
331#ifdef CIRRUSFB_DEBUG 353#ifdef CIRRUSFB_DEBUG
@@ -1956,16 +1978,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info)
1956 struct cirrusfb_info *cinfo = info->par; 1978 struct cirrusfb_info *cinfo = info->par;
1957 struct zorro_dev *zdev = to_zorro_dev(info->device); 1979 struct zorro_dev *zdev = to_zorro_dev(info->device);
1958 1980
1959 zorro_release_device(zdev); 1981 if (info->fix.smem_start > 16 * MB_)
1960
1961 if (cinfo->btype == BT_PICASSO4) {
1962 cinfo->regbase -= 0x600000;
1963 iounmap((void *)cinfo->regbase);
1964 iounmap(info->screen_base); 1982 iounmap(info->screen_base);
1965 } else { 1983 if (info->fix.mmio_start > 16 * MB_)
1966 if (zorro_resource_start(zdev) > 0x01000000) 1984 iounmap(cinfo->regbase);
1967 iounmap(info->screen_base); 1985
1968 } 1986 zorro_release_device(zdev);
1969} 1987}
1970#endif /* CONFIG_ZORRO */ 1988#endif /* CONFIG_ZORRO */
1971 1989
@@ -2222,115 +2240,116 @@ static struct pci_driver cirrusfb_pci_driver = {
2222static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, 2240static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2223 const struct zorro_device_id *ent) 2241 const struct zorro_device_id *ent)
2224{ 2242{
2225 struct cirrusfb_info *cinfo;
2226 struct fb_info *info; 2243 struct fb_info *info;
2244 int error;
2245 const struct zorrocl *zcl;
2227 enum cirrus_board btype; 2246 enum cirrus_board btype;
2228 struct zorro_dev *z2 = NULL; 2247 unsigned long regbase, ramsize, rambase;
2229 unsigned long board_addr, board_size, size; 2248 struct cirrusfb_info *cinfo;
2230 int ret;
2231
2232 btype = ent->driver_data;
2233 if (cirrusfb_zorro_table2[btype].id2)
2234 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2235 size = cirrusfb_zorro_table2[btype].size;
2236 2249
2237 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 2250 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2238 if (!info) { 2251 if (!info) {
2239 printk(KERN_ERR "cirrusfb: could not allocate memory\n"); 2252 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2240 ret = -ENOMEM; 2253 return -ENOMEM;
2241 goto err_out; 2254 }
2255
2256 zcl = (const struct zorrocl *)ent->driver_data;
2257 btype = zcl->type;
2258 regbase = zorro_resource_start(z) + zcl->regoffset;
2259 ramsize = zcl->ramsize;
2260 if (ramsize) {
2261 rambase = zorro_resource_start(z) + zcl->ramoffset;
2262 if (zorro_resource_len(z) == 64 * MB_) {
2263 /* Quirk for 64 MiB Picasso IV */
2264 rambase += zcl->ramoffset;
2265 }
2266 } else {
2267 struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
2268 if (!ram || !zorro_resource_len(ram)) {
2269 dev_err(info->device, "No video RAM found\n");
2270 error = -ENODEV;
2271 goto err_release_fb;
2272 }
2273 rambase = zorro_resource_start(ram);
2274 ramsize = zorro_resource_len(ram);
2275 if (zcl->ramid2 &&
2276 (ram = zorro_find_device(zcl->ramid2, NULL))) {
2277 if (zorro_resource_start(ram) != rambase + ramsize) {
2278 dev_warn(info->device,
2279 "Skipping non-contiguous RAM at %pR\n",
2280 &ram->resource);
2281 } else {
2282 ramsize += zorro_resource_len(ram);
2283 }
2284 }
2242 } 2285 }
2243 2286
2244 dev_info(info->device, "%s board detected\n", 2287 dev_info(info->device,
2245 cirrusfb_board_info[btype].name); 2288 "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
2246 2289 cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
2247 cinfo = info->par; 2290 rambase);
2248 cinfo->btype = btype;
2249
2250 assert(z);
2251 assert(btype != BT_NONE);
2252
2253 board_addr = zorro_resource_start(z);
2254 board_size = zorro_resource_len(z);
2255 info->screen_size = size;
2256 2291
2257 if (!zorro_request_device(z, "cirrusfb")) { 2292 if (!zorro_request_device(z, "cirrusfb")) {
2258 dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 2293 dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
2259 board_addr); 2294 error = -EBUSY;
2260 ret = -EBUSY;
2261 goto err_release_fb; 2295 goto err_release_fb;
2262 } 2296 }
2263 2297
2264 ret = -EIO; 2298 cinfo = info->par;
2265 2299 cinfo->btype = btype;
2266 if (btype == BT_PICASSO4) {
2267 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2268
2269 /* To be precise, for the P4 this is not the */
2270 /* begin of the board, but the begin of RAM. */
2271 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2272 /* (note the ugly hardcoded 16M number) */
2273 cinfo->regbase = ioremap(board_addr, 16777216);
2274 if (!cinfo->regbase)
2275 goto err_release_region;
2276
2277 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2278 cinfo->regbase);
2279 cinfo->regbase += 0x600000;
2280 info->fix.mmio_start = board_addr + 0x600000;
2281
2282 info->fix.smem_start = board_addr + 16777216;
2283 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2284 if (!info->screen_base)
2285 goto err_unmap_regbase;
2286 } else {
2287 dev_info(info->device, " REG at $%lx\n",
2288 (unsigned long) z2->resource.start);
2289
2290 info->fix.smem_start = board_addr;
2291 if (board_addr > 0x01000000)
2292 info->screen_base = ioremap(board_addr, board_size);
2293 else
2294 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2295 if (!info->screen_base)
2296 goto err_release_region;
2297 2300
2298 /* set address for REG area of board */ 2301 info->fix.mmio_start = regbase;
2299 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); 2302 cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
2300 info->fix.mmio_start = z2->resource.start; 2303 : (caddr_t)ZTWO_VADDR(regbase);
2304 if (!cinfo->regbase) {
2305 dev_err(info->device, "Cannot map registers\n");
2306 error = -EIO;
2307 goto err_release_dev;
2308 }
2301 2309
2302 dev_dbg(info->device, "Virtual address for board set to: $%p\n", 2310 info->fix.smem_start = rambase;
2303 cinfo->regbase); 2311 info->screen_size = ramsize;
2312 info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
2313 : (caddr_t)ZTWO_VADDR(rambase);
2314 if (!info->screen_base) {
2315 dev_err(info->device, "Cannot map video RAM\n");
2316 error = -EIO;
2317 goto err_unmap_reg;
2304 } 2318 }
2319
2305 cinfo->unmap = cirrusfb_zorro_unmap; 2320 cinfo->unmap = cirrusfb_zorro_unmap;
2306 2321
2307 dev_info(info->device, 2322 dev_info(info->device,
2308 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", 2323 "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
2309 board_size / MB_, board_addr); 2324 ramsize / MB_, rambase);
2310
2311 zorro_set_drvdata(z, info);
2312 2325
2313 /* MCLK select etc. */ 2326 /* MCLK select etc. */
2314 if (cirrusfb_board_info[btype].init_sr1f) 2327 if (cirrusfb_board_info[btype].init_sr1f)
2315 vga_wseq(cinfo->regbase, CL_SEQR1F, 2328 vga_wseq(cinfo->regbase, CL_SEQR1F,
2316 cirrusfb_board_info[btype].sr1f); 2329 cirrusfb_board_info[btype].sr1f);
2317 2330
2318 ret = cirrusfb_register(info); 2331 error = cirrusfb_register(info);
2319 if (!ret) 2332 if (error) {
2320 return 0; 2333 dev_err(info->device, "Failed to register device, error %d\n",
2334 error);
2335 goto err_unmap_ram;
2336 }
2321 2337
2322 if (btype == BT_PICASSO4 || board_addr > 0x01000000) 2338 zorro_set_drvdata(z, info);
2339 return 0;
2340
2341err_unmap_ram:
2342 if (rambase > 16 * MB_)
2323 iounmap(info->screen_base); 2343 iounmap(info->screen_base);
2324 2344
2325err_unmap_regbase: 2345err_unmap_reg:
2326 if (btype == BT_PICASSO4) 2346 if (regbase > 16 * MB_)
2327 iounmap(cinfo->regbase - 0x600000); 2347 iounmap(cinfo->regbase);
2328err_release_region: 2348err_release_dev:
2329 release_region(board_addr, board_size); 2349 zorro_release_device(z);
2330err_release_fb: 2350err_release_fb:
2331 framebuffer_release(info); 2351 framebuffer_release(info);
2332err_out: 2352 return error;
2333 return ret;
2334} 2353}
2335 2354
2336void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) 2355void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
@@ -2338,6 +2357,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2338 struct fb_info *info = zorro_get_drvdata(z); 2357 struct fb_info *info = zorro_get_drvdata(z);
2339 2358
2340 cirrusfb_cleanup(info); 2359 cirrusfb_cleanup(info);
2360 zorro_set_drvdata(z, NULL);
2341} 2361}
2342 2362
2343static struct zorro_driver cirrusfb_zorro_driver = { 2363static struct zorro_driver cirrusfb_zorro_driver = {
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 7b2c40abae15..0c189b32a4c5 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -420,7 +420,7 @@ static int __init init_control(struct fb_info_control *p)
420 420
421 /* Try to pick a video mode out of NVRAM if we have one. */ 421 /* Try to pick a video mode out of NVRAM if we have one. */
422#ifdef CONFIG_NVRAM 422#ifdef CONFIG_NVRAM
423 if (default_cmode == CMODE_NVRAM){ 423 if (default_cmode == CMODE_NVRAM) {
424 cmode = nvram_read_byte(NV_CMODE); 424 cmode = nvram_read_byte(NV_CMODE);
425 if(cmode < CMODE_8 || cmode > CMODE_32) 425 if(cmode < CMODE_8 || cmode > CMODE_32)
426 cmode = CMODE_8; 426 cmode = CMODE_8;
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
deleted file mode 100644
index f99af931d4f8..000000000000
--- a/drivers/video/display/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
1#
2# Display drivers configuration
3#
4
5menu "Display device support"
6
7config DISPLAY_SUPPORT
8 tristate "Display panel/monitor support"
9 ---help---
10 This framework adds support for low-level control of a display.
11 This includes support for power.
12
13 Enable this to be able to choose the drivers for controlling the
14 physical display panel/monitor on some platforms. This not only
15 covers LCD displays for PDAs but also other types of displays
16 such as CRT, TVout etc.
17
18 To have support for your specific display panel you will have to
19 select the proper drivers which depend on this option.
20
21comment "Display hardware drivers"
22 depends on DISPLAY_SUPPORT
23
24endmenu
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
deleted file mode 100644
index c0ea832bf171..000000000000
--- a/drivers/video/display/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
1# Display drivers
2
3display-objs := display-sysfs.o
4
5obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
6
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
deleted file mode 100644
index 0c647d7af0ee..000000000000
--- a/drivers/video/display/display-sysfs.c
+++ /dev/null
@@ -1,219 +0,0 @@
1/*
2 * display-sysfs.c - Display output driver sysfs interface
3 *
4 * Copyright (C) 2007 James Simmons <jsimmons@infradead.org>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24#include <linux/module.h>
25#include <linux/display.h>
26#include <linux/ctype.h>
27#include <linux/idr.h>
28#include <linux/err.h>
29#include <linux/kdev_t.h>
30#include <linux/slab.h>
31
32static ssize_t display_show_name(struct device *dev,
33 struct device_attribute *attr, char *buf)
34{
35 struct display_device *dsp = dev_get_drvdata(dev);
36 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
37}
38
39static ssize_t display_show_type(struct device *dev,
40 struct device_attribute *attr, char *buf)
41{
42 struct display_device *dsp = dev_get_drvdata(dev);
43 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
44}
45
46static ssize_t display_show_contrast(struct device *dev,
47 struct device_attribute *attr, char *buf)
48{
49 struct display_device *dsp = dev_get_drvdata(dev);
50 ssize_t rc = -ENXIO;
51
52 mutex_lock(&dsp->lock);
53 if (likely(dsp->driver) && dsp->driver->get_contrast)
54 rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp));
55 mutex_unlock(&dsp->lock);
56 return rc;
57}
58
59static ssize_t display_store_contrast(struct device *dev,
60 struct device_attribute *attr,
61 const char *buf, size_t count)
62{
63 struct display_device *dsp = dev_get_drvdata(dev);
64 ssize_t ret = -EINVAL, size;
65 int contrast;
66 char *endp;
67
68 contrast = simple_strtoul(buf, &endp, 0);
69 size = endp - buf;
70
71 if (isspace(*endp))
72 size++;
73
74 if (size != count)
75 return ret;
76
77 mutex_lock(&dsp->lock);
78 if (likely(dsp->driver && dsp->driver->set_contrast)) {
79 pr_debug("display: set contrast to %d\n", contrast);
80 dsp->driver->set_contrast(dsp, contrast);
81 ret = count;
82 }
83 mutex_unlock(&dsp->lock);
84 return ret;
85}
86
87static ssize_t display_show_max_contrast(struct device *dev,
88 struct device_attribute *attr,
89 char *buf)
90{
91 struct display_device *dsp = dev_get_drvdata(dev);
92 ssize_t rc = -ENXIO;
93
94 mutex_lock(&dsp->lock);
95 if (likely(dsp->driver))
96 rc = sprintf(buf, "%d\n", dsp->driver->max_contrast);
97 mutex_unlock(&dsp->lock);
98 return rc;
99}
100
101static struct device_attribute display_attrs[] = {
102 __ATTR(name, S_IRUGO, display_show_name, NULL),
103 __ATTR(type, S_IRUGO, display_show_type, NULL),
104 __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast),
105 __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL),
106};
107
108static int display_suspend(struct device *dev, pm_message_t state)
109{
110 struct display_device *dsp = dev_get_drvdata(dev);
111
112 mutex_lock(&dsp->lock);
113 if (likely(dsp->driver->suspend))
114 dsp->driver->suspend(dsp, state);
115 mutex_unlock(&dsp->lock);
116 return 0;
117};
118
119static int display_resume(struct device *dev)
120{
121 struct display_device *dsp = dev_get_drvdata(dev);
122
123 mutex_lock(&dsp->lock);
124 if (likely(dsp->driver->resume))
125 dsp->driver->resume(dsp);
126 mutex_unlock(&dsp->lock);
127 return 0;
128};
129
130static struct mutex allocated_dsp_lock;
131static DEFINE_IDR(allocated_dsp);
132static struct class *display_class;
133
134struct display_device *display_device_register(struct display_driver *driver,
135 struct device *parent, void *devdata)
136{
137 struct display_device *new_dev = NULL;
138 int ret = -EINVAL;
139
140 if (unlikely(!driver))
141 return ERR_PTR(ret);
142
143 mutex_lock(&allocated_dsp_lock);
144 ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
145 mutex_unlock(&allocated_dsp_lock);
146 if (!ret)
147 return ERR_PTR(ret);
148
149 new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL);
150 if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
151 // Reserve the index for this display
152 mutex_lock(&allocated_dsp_lock);
153 ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
154 mutex_unlock(&allocated_dsp_lock);
155
156 if (!ret) {
157 new_dev->dev = device_create(display_class, parent,
158 MKDEV(0, 0), new_dev,
159 "display%d", new_dev->idx);
160 if (!IS_ERR(new_dev->dev)) {
161 new_dev->parent = parent;
162 new_dev->driver = driver;
163 mutex_init(&new_dev->lock);
164 return new_dev;
165 }
166 mutex_lock(&allocated_dsp_lock);
167 idr_remove(&allocated_dsp, new_dev->idx);
168 mutex_unlock(&allocated_dsp_lock);
169 ret = -EINVAL;
170 }
171 }
172 kfree(new_dev);
173 return ERR_PTR(ret);
174}
175EXPORT_SYMBOL(display_device_register);
176
177void display_device_unregister(struct display_device *ddev)
178{
179 if (!ddev)
180 return;
181 // Free device
182 mutex_lock(&ddev->lock);
183 device_unregister(ddev->dev);
184 mutex_unlock(&ddev->lock);
185 // Mark device index as available
186 mutex_lock(&allocated_dsp_lock);
187 idr_remove(&allocated_dsp, ddev->idx);
188 mutex_unlock(&allocated_dsp_lock);
189 kfree(ddev);
190}
191EXPORT_SYMBOL(display_device_unregister);
192
193static int __init display_class_init(void)
194{
195 display_class = class_create(THIS_MODULE, "display");
196 if (IS_ERR(display_class)) {
197 printk(KERN_ERR "Failed to create display class\n");
198 display_class = NULL;
199 return -EINVAL;
200 }
201 display_class->dev_attrs = display_attrs;
202 display_class->suspend = display_suspend;
203 display_class->resume = display_resume;
204 mutex_init(&allocated_dsp_lock);
205 return 0;
206}
207
208static void __exit display_class_exit(void)
209{
210 class_destroy(display_class);
211}
212
213module_init(display_class_init);
214module_exit(display_class_exit);
215
216MODULE_DESCRIPTION("Display Hardware handling");
217MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>");
218MODULE_LICENSE("GPL");
219
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index d837d63c456f..18742c26463b 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -902,18 +902,7 @@ static struct platform_driver mxsfb_driver = {
902 }, 902 },
903}; 903};
904 904
905static int __init mxsfb_init(void) 905module_platform_driver(mxsfb_devtype);
906{
907 return platform_driver_register(&mxsfb_driver);
908}
909
910static void __exit mxsfb_exit(void)
911{
912 platform_driver_unregister(&mxsfb_driver);
913}
914
915module_init(mxsfb_init);
916module_exit(mxsfb_exit);
917 906
918MODULE_DESCRIPTION("Freescale mxs framebuffer driver"); 907MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
919MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 908MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d1fbbd888cf4..e10f551ade21 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -762,18 +762,7 @@ static struct platform_driver nuc900fb_driver = {
762 }, 762 },
763}; 763};
764 764
765int __devinit nuc900fb_init(void) 765module_platform_driver(nuc900fb_driver);
766{
767 return platform_driver_register(&nuc900fb_driver);
768}
769
770static void __exit nuc900fb_cleanup(void)
771{
772 platform_driver_unregister(&nuc900fb_driver);
773}
774
775module_init(nuc900fb_init);
776module_exit(nuc900fb_cleanup);
777 766
778MODULE_DESCRIPTION("Framebuffer driver for the NUC900"); 767MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
779MODULE_LICENSE("GPL"); 768MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index eb381db7fe51..8d546dd55e81 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -603,7 +603,6 @@ static int mipid_spi_remove(struct spi_device *spi)
603static struct spi_driver mipid_spi_driver = { 603static struct spi_driver mipid_spi_driver = {
604 .driver = { 604 .driver = {
605 .name = MIPID_MODULE_NAME, 605 .name = MIPID_MODULE_NAME,
606 .bus = &spi_bus_type,
607 .owner = THIS_MODULE, 606 .owner = THIS_MODULE,
608 }, 607 },
609 .probe = mipid_spi_probe, 608 .probe = mipid_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index dbd59b8e5b36..51a87e149e24 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -803,7 +803,6 @@ static int acx565akm_spi_remove(struct spi_device *spi)
803static struct spi_driver acx565akm_spi_driver = { 803static struct spi_driver acx565akm_spi_driver = {
804 .driver = { 804 .driver = {
805 .name = "acx565akm", 805 .name = "acx565akm",
806 .bus = &spi_bus_type,
807 .owner = THIS_MODULE, 806 .owner = THIS_MODULE,
808 }, 807 },
809 .probe = acx565akm_spi_probe, 808 .probe = acx565akm_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 150e8bae35a1..dc9408dc93d1 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -708,7 +708,6 @@ static int mipid_spi_remove(struct spi_device *spi)
708static struct spi_driver mipid_spi_driver = { 708static struct spi_driver mipid_spi_driver = {
709 .driver = { 709 .driver = {
710 .name = "lcd_mipid", 710 .name = "lcd_mipid",
711 .bus = &spi_bus_type,
712 .owner = THIS_MODULE, 711 .owner = THIS_MODULE,
713 }, 712 },
714 .probe = mipid_spi_probe, 713 .probe = mipid_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 2ba9d0ca187c..8365e77e09ff 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -303,7 +303,6 @@ static struct spi_driver nec_8048_spi_driver = {
303 .resume = nec_8048_spi_resume, 303 .resume = nec_8048_spi_resume,
304 .driver = { 304 .driver = {
305 .name = "nec_8048_spi", 305 .name = "nec_8048_spi",
306 .bus = &spi_bus_type,
307 .owner = THIS_MODULE, 306 .owner = THIS_MODULE,
308 }, 307 },
309}; 308};
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 2462b9ec6662..e6649aa89591 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -512,7 +512,6 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
512static struct spi_driver tpo_td043_spi_driver = { 512static struct spi_driver tpo_td043_spi_driver = {
513 .driver = { 513 .driver = {
514 .name = "tpo_td043mtea1_panel_spi", 514 .name = "tpo_td043mtea1_panel_spi",
515 .bus = &spi_bus_type,
516 .owner = THIS_MODULE, 515 .owner = THIS_MODULE,
517 }, 516 },
518 .probe = tpo_td043_spi_probe, 517 .probe = tpo_td043_spi_probe,
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 18ead6f0184d..8384b941f6ba 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -832,17 +832,7 @@ static struct platform_driver pxa168fb_driver = {
832 .remove = __devexit_p(pxa168fb_remove), 832 .remove = __devexit_p(pxa168fb_remove),
833}; 833};
834 834
835static int __init pxa168fb_init(void) 835module_platform_driver(pxa168fb_driver);
836{
837 return platform_driver_register(&pxa168fb_driver);
838}
839module_init(pxa168fb_init);
840
841static void __exit pxa168fb_exit(void)
842{
843 platform_driver_unregister(&pxa168fb_driver);
844}
845module_exit(pxa168fb_exit);
846 836
847MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " 837MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
848 "Green Wan <gwan@marvell.com>"); 838 "Green Wan <gwan@marvell.com>");
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 1ed8b366618d..1d71c08a818f 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -747,20 +747,7 @@ static struct platform_driver pxa3xx_gcu_driver = {
747 }, 747 },
748}; 748};
749 749
750static int __init 750module_platform_driver(pxa3xx_gcu_driver);
751pxa3xx_gcu_init(void)
752{
753 return platform_driver_register(&pxa3xx_gcu_driver);
754}
755
756static void __exit
757pxa3xx_gcu_exit(void)
758{
759 platform_driver_unregister(&pxa3xx_gcu_driver);
760}
761
762module_init(pxa3xx_gcu_init);
763module_exit(pxa3xx_gcu_exit);
764 751
765MODULE_DESCRIPTION("PXA3xx graphics controller unit driver"); 752MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
766MODULE_LICENSE("GPL"); 753MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 0753b1cfcb8b..e84677e6f5ed 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -621,7 +621,8 @@ static int s3c_fb_set_par(struct fb_info *info)
621 } else if (var->transp.length == 1) 621 } else if (var->transp.length == 1)
622 data |= WINCON1_BPPMODE_25BPP_A1888 622 data |= WINCON1_BPPMODE_25BPP_A1888
623 | WINCON1_BLD_PIX; 623 | WINCON1_BLD_PIX;
624 else if (var->transp.length == 4) 624 else if ((var->transp.length == 4) ||
625 (var->transp.length == 8))
625 data |= WINCON1_BPPMODE_28BPP_A4888 626 data |= WINCON1_BPPMODE_28BPP_A4888
626 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; 627 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
627 else 628 else
@@ -1589,77 +1590,9 @@ static int s3c_fb_resume(struct device *dev)
1589 1590
1590 return 0; 1591 return 0;
1591} 1592}
1592
1593static int s3c_fb_runtime_suspend(struct device *dev)
1594{
1595 struct platform_device *pdev = to_platform_device(dev);
1596 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1597 struct s3c_fb_win *win;
1598 int win_no;
1599
1600 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
1601 win = sfb->windows[win_no];
1602 if (!win)
1603 continue;
1604
1605 /* use the blank function to push into power-down */
1606 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1607 }
1608
1609 if (!sfb->variant.has_clksel)
1610 clk_disable(sfb->lcd_clk);
1611
1612 clk_disable(sfb->bus_clk);
1613 return 0;
1614}
1615
1616static int s3c_fb_runtime_resume(struct device *dev)
1617{
1618 struct platform_device *pdev = to_platform_device(dev);
1619 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1620 struct s3c_fb_platdata *pd = sfb->pdata;
1621 struct s3c_fb_win *win;
1622 int win_no;
1623
1624 clk_enable(sfb->bus_clk);
1625
1626 if (!sfb->variant.has_clksel)
1627 clk_enable(sfb->lcd_clk);
1628
1629 /* setup gpio and output polarity controls */
1630 pd->setup_gpio();
1631 writel(pd->vidcon1, sfb->regs + VIDCON1);
1632
1633 /* zero all windows before we do anything */
1634 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1635 s3c_fb_clear_win(sfb, win_no);
1636
1637 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1638 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1639
1640 regs += (win_no * 8);
1641 writel(0xffffff, regs + WKEYCON0);
1642 writel(0xffffff, regs + WKEYCON1);
1643 }
1644
1645 /* restore framebuffers */
1646 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1647 win = sfb->windows[win_no];
1648 if (!win)
1649 continue;
1650
1651 dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
1652 s3c_fb_set_par(win->fbinfo);
1653 }
1654
1655 return 0;
1656}
1657
1658#else 1593#else
1659#define s3c_fb_suspend NULL 1594#define s3c_fb_suspend NULL
1660#define s3c_fb_resume NULL 1595#define s3c_fb_resume NULL
1661#define s3c_fb_runtime_suspend NULL
1662#define s3c_fb_runtime_resume NULL
1663#endif 1596#endif
1664 1597
1665 1598
@@ -1984,12 +1917,7 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1984}; 1917};
1985MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1918MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1986 1919
1987static const struct dev_pm_ops s3cfb_pm_ops = { 1920static UNIVERSAL_DEV_PM_OPS(s3cfb_pm_ops, s3c_fb_suspend, s3c_fb_resume, NULL);
1988 .suspend = s3c_fb_suspend,
1989 .resume = s3c_fb_resume,
1990 .runtime_suspend = s3c_fb_runtime_suspend,
1991 .runtime_resume = s3c_fb_runtime_resume,
1992};
1993 1921
1994static struct platform_driver s3c_fb_driver = { 1922static struct platform_driver s3c_fb_driver = {
1995 .probe = s3c_fb_probe, 1923 .probe = s3c_fb_probe,
@@ -2002,18 +1930,7 @@ static struct platform_driver s3c_fb_driver = {
2002 }, 1930 },
2003}; 1931};
2004 1932
2005static int __init s3c_fb_init(void) 1933module_platform_driver(s3c_fb_driver);
2006{
2007 return platform_driver_register(&s3c_fb_driver);
2008}
2009
2010static void __exit s3c_fb_cleanup(void)
2011{
2012 platform_driver_unregister(&s3c_fb_driver);
2013}
2014
2015module_init(s3c_fb_init);
2016module_exit(s3c_fb_cleanup);
2017 1934
2018MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 1935MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
2019MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); 1936MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ee4c0df217f7..77f34c614c86 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -26,8 +26,8 @@
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/cpufreq.h> 28#include <linux/cpufreq.h>
29#include <linux/io.h>
29 30
30#include <asm/io.h>
31#include <asm/div64.h> 31#include <asm/div64.h>
32 32
33#include <asm/mach/map.h> 33#include <asm/mach/map.h>
@@ -45,10 +45,10 @@
45#ifdef CONFIG_FB_S3C2410_DEBUG 45#ifdef CONFIG_FB_S3C2410_DEBUG
46static int debug = 1; 46static int debug = 1;
47#else 47#else
48static int debug = 0; 48static int debug;
49#endif 49#endif
50 50
51#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); } 51#define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg);
52 52
53/* useful functions */ 53/* useful functions */
54 54
@@ -567,11 +567,10 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
567 567
568 tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; 568 tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
569 569
570 if (blank_mode == FB_BLANK_POWERDOWN) { 570 if (blank_mode == FB_BLANK_POWERDOWN)
571 s3c2410fb_lcd_enable(fbi, 0); 571 s3c2410fb_lcd_enable(fbi, 0);
572 } else { 572 else
573 s3c2410fb_lcd_enable(fbi, 1); 573 s3c2410fb_lcd_enable(fbi, 1);
574 }
575 574
576 if (blank_mode == FB_BLANK_UNBLANK) 575 if (blank_mode == FB_BLANK_UNBLANK)
577 writel(0x0, tpal_reg); 576 writel(0x0, tpal_reg);
@@ -812,7 +811,7 @@ static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
812#endif 811#endif
813 812
814 813
815static char driver_name[] = "s3c2410fb"; 814static const char driver_name[] = "s3c2410fb";
816 815
817static int __devinit s3c24xxfb_probe(struct platform_device *pdev, 816static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
818 enum s3c_drv_type drv_type) 817 enum s3c_drv_type drv_type)
@@ -881,7 +880,10 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
881 goto release_mem; 880 goto release_mem;
882 } 881 }
883 882
884 info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); 883 if (drv_type == DRV_S3C2412)
884 info->irq_base = info->io + S3C2412_LCDINTBASE;
885 else
886 info->irq_base = info->io + S3C2410_LCDINTBASE;
885 887
886 dprintk("devinit\n"); 888 dprintk("devinit\n");
887 889
@@ -927,7 +929,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
927 clk_enable(info->clk); 929 clk_enable(info->clk);
928 dprintk("got and enabled clock\n"); 930 dprintk("got and enabled clock\n");
929 931
930 msleep(1); 932 usleep_range(1000, 1000);
931 933
932 info->clk_rate = clk_get_rate(info->clk); 934 info->clk_rate = clk_get_rate(info->clk);
933 935
@@ -975,9 +977,8 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
975 977
976 /* create device files */ 978 /* create device files */
977 ret = device_create_file(&pdev->dev, &dev_attr_debug); 979 ret = device_create_file(&pdev->dev, &dev_attr_debug);
978 if (ret) { 980 if (ret)
979 printk(KERN_ERR "failed to add debug attribute\n"); 981 printk(KERN_ERR "failed to add debug attribute\n");
980 }
981 982
982 printk(KERN_INFO "fb%d: %s frame buffer device\n", 983 printk(KERN_INFO "fb%d: %s frame buffer device\n",
983 fbinfo->node, fbinfo->fix.id); 984 fbinfo->node, fbinfo->fix.id);
@@ -1027,7 +1028,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
1027 s3c2410fb_cpufreq_deregister(info); 1028 s3c2410fb_cpufreq_deregister(info);
1028 1029
1029 s3c2410fb_lcd_enable(info, 0); 1030 s3c2410fb_lcd_enable(info, 0);
1030 msleep(1); 1031 usleep_range(1000, 1000);
1031 1032
1032 s3c2410fb_unmap_video_memory(fbinfo); 1033 s3c2410fb_unmap_video_memory(fbinfo);
1033 1034
@@ -1064,7 +1065,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
1064 * the LCD DMA engine is not going to get back on the bus 1065 * the LCD DMA engine is not going to get back on the bus
1065 * before the clock goes off again (bjd) */ 1066 * before the clock goes off again (bjd) */
1066 1067
1067 msleep(1); 1068 usleep_range(1000, 1000);
1068 clk_disable(info->clk); 1069 clk_disable(info->clk);
1069 1070
1070 return 0; 1071 return 0;
@@ -1076,7 +1077,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
1076 struct s3c2410fb_info *info = fbinfo->par; 1077 struct s3c2410fb_info *info = fbinfo->par;
1077 1078
1078 clk_enable(info->clk); 1079 clk_enable(info->clk);
1079 msleep(1); 1080 usleep_range(1000, 1000);
1080 1081
1081 s3c2410fb_init_registers(fbinfo); 1082 s3c2410fb_init_registers(fbinfo);
1082 1083
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 37d764ad56b0..3c1de981a18c 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -76,7 +76,7 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map,
76 map_offset = (physbase + map[i].poff) & POFF_MASK; 76 map_offset = (physbase + map[i].poff) & POFF_MASK;
77 break; 77 break;
78 } 78 }
79 if (!map_size){ 79 if (!map_size) {
80 page += PAGE_SIZE; 80 page += PAGE_SIZE;
81 continue; 81 continue;
82 } 82 }
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index 45e47d847163..83b16e237a0e 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -585,18 +585,7 @@ static struct platform_driver sh7760_lcdc_driver = {
585 .remove = __devexit_p(sh7760fb_remove), 585 .remove = __devexit_p(sh7760fb_remove),
586}; 586};
587 587
588static int __init sh7760fb_init(void) 588module_platform_driver(sh7760_lcdc_driver);
589{
590 return platform_driver_register(&sh7760_lcdc_driver);
591}
592
593static void __exit sh7760fb_exit(void)
594{
595 platform_driver_unregister(&sh7760_lcdc_driver);
596}
597
598module_init(sh7760fb_init);
599module_exit(sh7760fb_exit);
600 589
601MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss"); 590MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
602MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller"); 591MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 72ee96bc6b3e..05151b82f40f 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -8,6 +8,7 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <linux/bitmap.h>
11#include <linux/clk.h> 12#include <linux/clk.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <linux/init.h> 14#include <linux/init.h>
@@ -41,6 +42,7 @@
41#define VMCTR1 0x0020 42#define VMCTR1 0x0020
42#define VMCTR2 0x0024 43#define VMCTR2 0x0024
43#define VMLEN1 0x0028 44#define VMLEN1 0x0028
45#define VMLEN2 0x002c
44#define CMTSRTREQ 0x0070 46#define CMTSRTREQ 0x0070
45#define CMTSRTCTR 0x00d0 47#define CMTSRTCTR 0x00d0
46 48
@@ -51,8 +53,7 @@ struct sh_mipi {
51 void __iomem *base; 53 void __iomem *base;
52 void __iomem *linkbase; 54 void __iomem *linkbase;
53 struct clk *dsit_clk; 55 struct clk *dsit_clk;
54 struct clk *dsip_clk; 56 struct platform_device *pdev;
55 struct device *dev;
56 57
57 void *next_board_data; 58 void *next_board_data;
58 void (*next_display_on)(void *board_data, struct fb_info *info); 59 void (*next_display_on)(void *board_data, struct fb_info *info);
@@ -124,35 +125,15 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
124 sh_mipi_dsi_enable(mipi, false); 125 sh_mipi_dsi_enable(mipi, false);
125} 126}
126 127
127static void mipi_display_on(void *arg, struct fb_info *info)
128{
129 struct sh_mipi *mipi = arg;
130
131 pm_runtime_get_sync(mipi->dev);
132 sh_mipi_dsi_enable(mipi, true);
133
134 if (mipi->next_display_on)
135 mipi->next_display_on(mipi->next_board_data, info);
136}
137
138static void mipi_display_off(void *arg)
139{
140 struct sh_mipi *mipi = arg;
141
142 if (mipi->next_display_off)
143 mipi->next_display_off(mipi->next_board_data);
144
145 sh_mipi_dsi_enable(mipi, false);
146 pm_runtime_put(mipi->dev);
147}
148
149static int __init sh_mipi_setup(struct sh_mipi *mipi, 128static int __init sh_mipi_setup(struct sh_mipi *mipi,
150 struct sh_mipi_dsi_info *pdata) 129 struct sh_mipi_dsi_info *pdata)
151{ 130{
152 void __iomem *base = mipi->base; 131 void __iomem *base = mipi->base;
153 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; 132 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
154 u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000; 133 u32 pctype, datatype, pixfmt, linelength, vmctr2;
134 u32 tmp, top, bottom, delay, div;
155 bool yuv; 135 bool yuv;
136 int bpp;
156 137
157 /* 138 /*
158 * Select data format. MIPI DSI is not hot-pluggable, so, we just use 139 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
@@ -253,6 +234,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
253 (!yuv && ch->interface_type != RGB24)) 234 (!yuv && ch->interface_type != RGB24))
254 return -EINVAL; 235 return -EINVAL;
255 236
237 if (!pdata->lane)
238 return -EINVAL;
239
256 /* reset DSI link */ 240 /* reset DSI link */
257 iowrite32(0x00000001, base + SYSCTRL); 241 iowrite32(0x00000001, base + SYSCTRL);
258 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ 242 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
@@ -262,15 +246,6 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
262 /* setup DSI link */ 246 /* setup DSI link */
263 247
264 /* 248 /*
265 * Default = ULPS enable |
266 * Contention detection enabled |
267 * EoT packet transmission enable |
268 * CRC check enable |
269 * ECC check enable
270 * additionally enable first two lanes
271 */
272 iowrite32(0x00003703, base + SYSCONF);
273 /*
274 * T_wakeup = 0x7000 249 * T_wakeup = 0x7000
275 * T_hs-trail = 3 250 * T_hs-trail = 3
276 * T_hs-prepare = 3 251 * T_hs-prepare = 3
@@ -290,15 +265,24 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
290 iowrite32(0x0fffffff, base + TATOVSET); 265 iowrite32(0x0fffffff, base + TATOVSET);
291 /* Peripheral reset timeout, default 0xffffffff */ 266 /* Peripheral reset timeout, default 0xffffffff */
292 iowrite32(0x0fffffff, base + PRTOVSET); 267 iowrite32(0x0fffffff, base + PRTOVSET);
293 /* Enable timeout counters */
294 iowrite32(0x00000f00, base + DSICTRL);
295 /* Interrupts not used, disable all */ 268 /* Interrupts not used, disable all */
296 iowrite32(0, base + DSIINTE); 269 iowrite32(0, base + DSIINTE);
297 /* DSI-Tx bias on */ 270 /* DSI-Tx bias on */
298 iowrite32(0x00000001, base + PHYCTRL); 271 iowrite32(0x00000001, base + PHYCTRL);
299 udelay(200); 272 udelay(200);
300 /* Deassert resets, power on, set multiplier */ 273 /* Deassert resets, power on */
301 iowrite32(0x03070b01, base + PHYCTRL); 274 iowrite32(0x03070001, base + PHYCTRL);
275
276 /*
277 * Default = ULPS enable |
278 * Contention detection enabled |
279 * EoT packet transmission enable |
280 * CRC check enable |
281 * ECC check enable
282 */
283 bitmap_fill((unsigned long *)&tmp, pdata->lane);
284 tmp |= 0x00003700;
285 iowrite32(tmp, base + SYSCONF);
302 286
303 /* setup l-bridge */ 287 /* setup l-bridge */
304 288
@@ -316,18 +300,68 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
316 * Non-burst mode with sync pulses: VSE and HSE are output, 300 * Non-burst mode with sync pulses: VSE and HSE are output,
317 * HSA period allowed, no commands in LP 301 * HSA period allowed, no commands in LP
318 */ 302 */
303 vmctr2 = 0;
304 if (pdata->flags & SH_MIPI_DSI_VSEE)
305 vmctr2 |= 1 << 23;
306 if (pdata->flags & SH_MIPI_DSI_HSEE)
307 vmctr2 |= 1 << 22;
308 if (pdata->flags & SH_MIPI_DSI_HSAE)
309 vmctr2 |= 1 << 21;
310 if (pdata->flags & SH_MIPI_DSI_BL2E)
311 vmctr2 |= 1 << 17;
319 if (pdata->flags & SH_MIPI_DSI_HSABM) 312 if (pdata->flags & SH_MIPI_DSI_HSABM)
320 vmctr2 |= 0x20; 313 vmctr2 |= 1 << 5;
321 if (pdata->flags & SH_MIPI_DSI_HSPBM) 314 if (pdata->flags & SH_MIPI_DSI_HBPBM)
322 vmctr2 |= 0x10; 315 vmctr2 |= 1 << 4;
316 if (pdata->flags & SH_MIPI_DSI_HFPBM)
317 vmctr2 |= 1 << 3;
323 iowrite32(vmctr2, mipi->linkbase + VMCTR2); 318 iowrite32(vmctr2, mipi->linkbase + VMCTR2);
324 319
325 /* 320 /*
326 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 321 * VMLEN1 = RGBLEN | HSALEN
327 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default 322 *
328 * (unused if VMCTR2[HSABM] = 0) 323 * see
324 * Video mode - Blanking Packet setting
325 */
326 top = linelength << 16; /* RGBLEN */
327 bottom = 0x00000001;
328 if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
329 bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10;
330 iowrite32(top | bottom , mipi->linkbase + VMLEN1);
331
332 /*
333 * VMLEN2 = HBPLEN | HFPLEN
334 *
335 * see
336 * Video mode - Blanking Packet setting
329 */ 337 */
330 iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1); 338 top = 0x00010000;
339 bottom = 0x00000001;
340 delay = 0;
341
342 div = 1; /* HSbyteCLK is calculation base
343 * HS4divCLK = HSbyteCLK/2
344 * HS6divCLK is not supported for now */
345 if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
346 div = 2;
347
348 if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
349 top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin;
350 top = ((pdata->lane * top / div) - 10) << 16;
351 }
352 if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
353 bottom = ch->lcd_cfg[0].right_margin;
354 bottom = (pdata->lane * bottom / div) - 12;
355 }
356
357 bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */
358 if ((pdata->lane / div) > bpp) {
359 tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */
360 tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */
361 delay = (pdata->lane * tmp);
362 }
363
364 iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
331 365
332 msleep(5); 366 msleep(5);
333 367
@@ -352,9 +386,56 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
352 pixfmt << 4); 386 pixfmt << 4);
353 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); 387 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
354 388
389 /* Enable timeout counters */
390 iowrite32(0x00000f00, base + DSICTRL);
391
355 return 0; 392 return 0;
356} 393}
357 394
395static void mipi_display_on(void *arg, struct fb_info *info)
396{
397 struct sh_mipi *mipi = arg;
398 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
399 int ret;
400
401 pm_runtime_get_sync(&mipi->pdev->dev);
402
403 ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
404 if (ret < 0)
405 goto mipi_display_on_fail1;
406
407 ret = sh_mipi_setup(mipi, pdata);
408 if (ret < 0)
409 goto mipi_display_on_fail2;
410
411 sh_mipi_dsi_enable(mipi, true);
412
413 if (mipi->next_display_on)
414 mipi->next_display_on(mipi->next_board_data, info);
415
416 return;
417
418mipi_display_on_fail1:
419 pm_runtime_put_sync(&mipi->pdev->dev);
420mipi_display_on_fail2:
421 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
422}
423
424static void mipi_display_off(void *arg)
425{
426 struct sh_mipi *mipi = arg;
427 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
428
429 if (mipi->next_display_off)
430 mipi->next_display_off(mipi->next_board_data);
431
432 sh_mipi_dsi_enable(mipi, false);
433
434 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
435
436 pm_runtime_put_sync(&mipi->pdev->dev);
437}
438
358static int __init sh_mipi_probe(struct platform_device *pdev) 439static int __init sh_mipi_probe(struct platform_device *pdev)
359{ 440{
360 struct sh_mipi *mipi; 441 struct sh_mipi *mipi;
@@ -363,11 +444,13 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
363 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 444 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
364 unsigned long rate, f_current; 445 unsigned long rate, f_current;
365 int idx = pdev->id, ret; 446 int idx = pdev->id, ret;
366 char dsip_clk[] = "dsi.p_clk";
367 447
368 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) 448 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
369 return -ENODEV; 449 return -ENODEV;
370 450
451 if (!pdata->set_dot_clock)
452 return -EINVAL;
453
371 mutex_lock(&array_lock); 454 mutex_lock(&array_lock);
372 if (idx < 0) 455 if (idx < 0)
373 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) 456 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
@@ -408,7 +491,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
408 goto emap2; 491 goto emap2;
409 } 492 }
410 493
411 mipi->dev = &pdev->dev; 494 mipi->pdev = pdev;
412 495
413 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); 496 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
414 if (IS_ERR(mipi->dsit_clk)) { 497 if (IS_ERR(mipi->dsit_clk)) {
@@ -428,44 +511,15 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
428 511
429 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); 512 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
430 513
431 sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
432 mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
433 if (IS_ERR(mipi->dsip_clk)) {
434 ret = PTR_ERR(mipi->dsip_clk);
435 goto eclkpget;
436 }
437
438 f_current = clk_get_rate(mipi->dsip_clk);
439 /* Between 10 and 50MHz */
440 rate = clk_round_rate(mipi->dsip_clk, 24000000);
441 if (rate > 0 && rate != f_current)
442 ret = clk_set_rate(mipi->dsip_clk, rate);
443 else
444 ret = rate;
445 if (ret < 0)
446 goto esetprate;
447
448 dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
449
450 msleep(10);
451
452 ret = clk_enable(mipi->dsit_clk); 514 ret = clk_enable(mipi->dsit_clk);
453 if (ret < 0) 515 if (ret < 0)
454 goto eclkton; 516 goto eclkton;
455 517
456 ret = clk_enable(mipi->dsip_clk);
457 if (ret < 0)
458 goto eclkpon;
459
460 mipi_dsi[idx] = mipi; 518 mipi_dsi[idx] = mipi;
461 519
462 pm_runtime_enable(&pdev->dev); 520 pm_runtime_enable(&pdev->dev);
463 pm_runtime_resume(&pdev->dev); 521 pm_runtime_resume(&pdev->dev);
464 522
465 ret = sh_mipi_setup(mipi, pdata);
466 if (ret < 0)
467 goto emipisetup;
468
469 mutex_unlock(&array_lock); 523 mutex_unlock(&array_lock);
470 platform_set_drvdata(pdev, mipi); 524 platform_set_drvdata(pdev, mipi);
471 525
@@ -482,16 +536,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
482 536
483 return 0; 537 return 0;
484 538
485emipisetup:
486 mipi_dsi[idx] = NULL;
487 pm_runtime_disable(&pdev->dev);
488 clk_disable(mipi->dsip_clk);
489eclkpon:
490 clk_disable(mipi->dsit_clk);
491eclkton: 539eclkton:
492esetprate:
493 clk_put(mipi->dsip_clk);
494eclkpget:
495esettrate: 540esettrate:
496 clk_put(mipi->dsit_clk); 541 clk_put(mipi->dsit_clk);
497eclktget: 542eclktget:
@@ -542,10 +587,9 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
542 pdata->lcd_chan->board_cfg.board_data = NULL; 587 pdata->lcd_chan->board_cfg.board_data = NULL;
543 588
544 pm_runtime_disable(&pdev->dev); 589 pm_runtime_disable(&pdev->dev);
545 clk_disable(mipi->dsip_clk);
546 clk_disable(mipi->dsit_clk); 590 clk_disable(mipi->dsit_clk);
547 clk_put(mipi->dsit_clk); 591 clk_put(mipi->dsit_clk);
548 clk_put(mipi->dsip_clk); 592
549 iounmap(mipi->linkbase); 593 iounmap(mipi->linkbase);
550 if (res2) 594 if (res2)
551 release_mem_region(res2->start, resource_size(res2)); 595 release_mem_region(res2->start, resource_size(res2));
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index facffc254976..a264ebf971a0 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -420,7 +420,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
420 tmp = ((display_var->xres & 7) << 24) | 420 tmp = ((display_var->xres & 7) << 24) |
421 ((display_h_total & 7) << 16) | 421 ((display_h_total & 7) << 16) |
422 ((display_var->hsync_len & 7) << 8) | 422 ((display_var->hsync_len & 7) << 8) |
423 hsync_pos; 423 (hsync_pos & 7);
424 lcdc_write_chan(ch, LDHAJR, tmp); 424 lcdc_write_chan(ch, LDHAJR, tmp);
425} 425}
426 426
@@ -1709,18 +1709,7 @@ static struct platform_driver sh_mobile_lcdc_driver = {
1709 .remove = sh_mobile_lcdc_remove, 1709 .remove = sh_mobile_lcdc_remove,
1710}; 1710};
1711 1711
1712static int __init sh_mobile_lcdc_init(void) 1712module_platform_driver(sh_mobile_lcdc_driver);
1713{
1714 return platform_driver_register(&sh_mobile_lcdc_driver);
1715}
1716
1717static void __exit sh_mobile_lcdc_exit(void)
1718{
1719 platform_driver_unregister(&sh_mobile_lcdc_driver);
1720}
1721
1722module_init(sh_mobile_lcdc_init);
1723module_exit(sh_mobile_lcdc_exit);
1724 1713
1725MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); 1714MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
1726MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 1715MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 4d63490209cd..f45d83ecfd21 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -679,18 +679,7 @@ static struct platform_driver sh_mobile_meram_driver = {
679 .remove = sh_mobile_meram_remove, 679 .remove = sh_mobile_meram_remove,
680}; 680};
681 681
682static int __init sh_mobile_meram_init(void) 682module_platform_driver(sh_mobile_meram_driver);
683{
684 return platform_driver_register(&sh_mobile_meram_driver);
685}
686
687static void __exit sh_mobile_meram_exit(void)
688{
689 platform_driver_unregister(&sh_mobile_meram_driver);
690}
691
692module_init(sh_mobile_meram_init);
693module_exit(sh_mobile_meram_exit);
694 683
695MODULE_DESCRIPTION("SuperH Mobile MERAM driver"); 684MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
696MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama"); 685MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index a78254cf8e83..3690effbedcc 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -2230,18 +2230,7 @@ static struct platform_driver sm501fb_driver = {
2230 }, 2230 },
2231}; 2231};
2232 2232
2233static int __devinit sm501fb_init(void) 2233module_platform_driver(sm501fb_driver);
2234{
2235 return platform_driver_register(&sm501fb_driver);
2236}
2237
2238static void __exit sm501fb_cleanup(void)
2239{
2240 platform_driver_unregister(&sm501fb_driver);
2241}
2242
2243module_init(sm501fb_init);
2244module_exit(sm501fb_cleanup);
2245 2234
2246module_param_named(mode, fb_mode, charp, 0); 2235module_param_named(mode, fb_mode, charp, 0);
2247MODULE_PARM_DESC(mode, 2236MODULE_PARM_DESC(mode,
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 777c21dd7a6b..2a5fe6ede845 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -457,18 +457,7 @@ static struct platform_driver vt8500lcd_driver = {
457 }, 457 },
458}; 458};
459 459
460static int __init vt8500lcd_init(void) 460module_platform_driver(vt8500lcd_driver);
461{
462 return platform_driver_register(&vt8500lcd_driver);
463}
464
465static void __exit vt8500lcd_exit(void)
466{
467 platform_driver_unregister(&vt8500lcd_driver);
468}
469
470module_init(vt8500lcd_init);
471module_exit(vt8500lcd_exit);
472 461
473MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 462MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
474MODULE_DESCRIPTION("LCD controller driver for VIA VT8500"); 463MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2375e5bbf572..90a2e30272ad 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -1620,18 +1620,7 @@ static struct platform_driver w100fb_driver = {
1620 }, 1620 },
1621}; 1621};
1622 1622
1623int __init w100fb_init(void) 1623module_platform_driver(w100fb_driver);
1624{
1625 return platform_driver_register(&w100fb_driver);
1626}
1627
1628void __exit w100fb_cleanup(void)
1629{
1630 platform_driver_unregister(&w100fb_driver);
1631}
1632
1633module_init(w100fb_init);
1634module_exit(w100fb_cleanup);
1635 1624
1636MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver"); 1625MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1637MODULE_LICENSE("GPL"); 1626MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 96e34a569169..c8703bd61b74 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -404,18 +404,7 @@ static struct platform_driver wm8505fb_driver = {
404 }, 404 },
405}; 405};
406 406
407static int __init wm8505fb_init(void) 407module_platform_driver(wm8505fb_driver);
408{
409 return platform_driver_register(&wm8505fb_driver);
410}
411
412static void __exit wm8505fb_exit(void)
413{
414 platform_driver_unregister(&wm8505fb_driver);
415}
416
417module_init(wm8505fb_init);
418module_exit(wm8505fb_exit);
419 408
420MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); 409MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
421MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); 410MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
index 45832b7ef7d2..55be3865015b 100644
--- a/drivers/video/wmt_ge_rops.c
+++ b/drivers/video/wmt_ge_rops.c
@@ -167,18 +167,7 @@ static struct platform_driver wmt_ge_rops_driver = {
167 }, 167 },
168}; 168};
169 169
170static int __init wmt_ge_rops_init(void) 170module_platform_driver(wmt_ge_rops_driver);
171{
172 return platform_driver_register(&wmt_ge_rops_driver);
173}
174
175static void __exit wmt_ge_rops_exit(void)
176{
177 platform_driver_unregister(&wmt_ge_rops_driver);
178}
179
180module_init(wmt_ge_rops_init);
181module_exit(wmt_ge_rops_exit);
182 171
183MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); 172MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
184MODULE_DESCRIPTION("Accelerators for raster operations using " 173MODULE_DESCRIPTION("Accelerators for raster operations using "
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index fcb6cd90f64d..18084525402a 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -511,25 +511,7 @@ static struct platform_driver xilinxfb_of_driver = {
511 }, 511 },
512}; 512};
513 513
514 514module_platform_driver(xilinxfb_of_driver);
515/* ---------------------------------------------------------------------
516 * Module setup and teardown
517 */
518
519static int __init
520xilinxfb_init(void)
521{
522 return platform_driver_register(&xilinxfb_of_driver);
523}
524
525static void __exit
526xilinxfb_cleanup(void)
527{
528 platform_driver_unregister(&xilinxfb_of_driver);
529}
530
531module_init(xilinxfb_init);
532module_exit(xilinxfb_cleanup);
533 515
534MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); 516MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
535MODULE_DESCRIPTION("Xilinx TFT frame buffer driver"); 517MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");