amifb.c 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809
  1. /*
  2. * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
  3. *
  4. * Copyright (C) 1995-2003 Geert Uytterhoeven
  5. *
  6. * with work by Roman Zippel
  7. *
  8. *
  9. * This file is based on the Atari frame buffer device (atafb.c):
  10. *
  11. * Copyright (C) 1994 Martin Schaller
  12. * Roman Hodek
  13. *
  14. * with work by Andreas Schwab
  15. * Guenther Kelleter
  16. *
  17. * and on the original Amiga console driver (amicon.c):
  18. *
  19. * Copyright (C) 1993 Hamish Macdonald
  20. * Greg Harp
  21. * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
  22. *
  23. * with work by William Rucklidge (wjr@cs.cornell.edu)
  24. * Geert Uytterhoeven
  25. * Jes Sorensen (jds@kom.auc.dk)
  26. *
  27. *
  28. * History:
  29. *
  30. * - 24 Jul 96: Copper generates now vblank interrupt and
  31. * VESA Power Saving Protocol is fully implemented
  32. * - 14 Jul 96: Rework and hopefully last ECS bugs fixed
  33. * - 7 Mar 96: Hardware sprite support by Roman Zippel
  34. * - 18 Feb 96: OCS and ECS support by Roman Zippel
  35. * Hardware functions completely rewritten
  36. * - 2 Dec 95: AGA version by Geert Uytterhoeven
  37. *
  38. * This file is subject to the terms and conditions of the GNU General Public
  39. * License. See the file COPYING in the main directory of this archive
  40. * for more details.
  41. */
  42. #include <linux/module.h>
  43. #include <linux/kernel.h>
  44. #include <linux/errno.h>
  45. #include <linux/string.h>
  46. #include <linux/mm.h>
  47. #include <linux/delay.h>
  48. #include <linux/interrupt.h>
  49. #include <linux/fb.h>
  50. #include <linux/init.h>
  51. #include <linux/ioport.h>
  52. #include <linux/platform_device.h>
  53. #include <linux/uaccess.h>
  54. #include <asm/system.h>
  55. #include <asm/irq.h>
  56. #include <asm/amigahw.h>
  57. #include <asm/amigaints.h>
  58. #include <asm/setup.h>
  59. #include "c2p.h"
  60. #define DEBUG
  61. #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
  62. #define CONFIG_FB_AMIGA_OCS /* define at least one fb driver, this will change later */
  63. #endif
  64. #if !defined(CONFIG_FB_AMIGA_OCS)
  65. # define IS_OCS (0)
  66. #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
  67. # define IS_OCS (chipset == TAG_OCS)
  68. #else
  69. # define CONFIG_FB_AMIGA_OCS_ONLY
  70. # define IS_OCS (1)
  71. #endif
  72. #if !defined(CONFIG_FB_AMIGA_ECS)
  73. # define IS_ECS (0)
  74. #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
  75. # define IS_ECS (chipset == TAG_ECS)
  76. #else
  77. # define CONFIG_FB_AMIGA_ECS_ONLY
  78. # define IS_ECS (1)
  79. #endif
  80. #if !defined(CONFIG_FB_AMIGA_AGA)
  81. # define IS_AGA (0)
  82. #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
  83. # define IS_AGA (chipset == TAG_AGA)
  84. #else
  85. # define CONFIG_FB_AMIGA_AGA_ONLY
  86. # define IS_AGA (1)
  87. #endif
  88. #ifdef DEBUG
  89. # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
  90. #else
  91. # define DPRINTK(fmt, args...)
  92. #endif
  93. /*******************************************************************************
  94. Generic video timings
  95. ---------------------
  96. Timings used by the frame buffer interface:
  97. +----------+---------------------------------------------+----------+-------+
  98. | | ^ | | |
  99. | | |upper_margin | | |
  100. | | v | | |
  101. +----------###############################################----------+-------+
  102. | # ^ # | |
  103. | # | # | |
  104. | # | # | |
  105. | # | # | |
  106. | left # | # right | hsync |
  107. | margin # | xres # margin | len |
  108. |<-------->#<---------------+--------------------------->#<-------->|<----->|
  109. | # | # | |
  110. | # | # | |
  111. | # | # | |
  112. | # |yres # | |
  113. | # | # | |
  114. | # | # | |
  115. | # | # | |
  116. | # | # | |
  117. | # | # | |
  118. | # | # | |
  119. | # | # | |
  120. | # | # | |
  121. | # v # | |
  122. +----------###############################################----------+-------+
  123. | | ^ | | |
  124. | | |lower_margin | | |
  125. | | v | | |
  126. +----------+---------------------------------------------+----------+-------+
  127. | | ^ | | |
  128. | | |vsync_len | | |
  129. | | v | | |
  130. +----------+---------------------------------------------+----------+-------+
  131. Amiga video timings
  132. -------------------
  133. The Amiga native chipsets uses another timing scheme:
  134. - hsstrt: Start of horizontal synchronization pulse
  135. - hsstop: End of horizontal synchronization pulse
  136. - htotal: Last value on the line (i.e. line length = htotal + 1)
  137. - vsstrt: Start of vertical synchronization pulse
  138. - vsstop: End of vertical synchronization pulse
  139. - vtotal: Last line value (i.e. number of lines = vtotal + 1)
  140. - hcenter: Start of vertical retrace for interlace
  141. You can specify the blanking timings independently. Currently I just set
  142. them equal to the respective synchronization values:
  143. - hbstrt: Start of horizontal blank
  144. - hbstop: End of horizontal blank
  145. - vbstrt: Start of vertical blank
  146. - vbstop: End of vertical blank
  147. Horizontal values are in color clock cycles (280 ns), vertical values are in
  148. scanlines.
  149. (0, 0) is somewhere in the upper-left corner :-)
  150. Amiga visible window definitions
  151. --------------------------------
  152. Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
  153. make corrections and/or additions.
  154. Within the above synchronization specifications, the visible window is
  155. defined by the following parameters (actual register resolutions may be
  156. different; all horizontal values are normalized with respect to the pixel
  157. clock):
  158. - diwstrt_h: Horizontal start of the visible window
  159. - diwstop_h: Horizontal stop + 1(*) of the visible window
  160. - diwstrt_v: Vertical start of the visible window
  161. - diwstop_v: Vertical stop of the visible window
  162. - ddfstrt: Horizontal start of display DMA
  163. - ddfstop: Horizontal stop of display DMA
  164. - hscroll: Horizontal display output delay
  165. Sprite positioning:
  166. - sprstrt_h: Horizontal start - 4 of sprite
  167. - sprstrt_v: Vertical start of sprite
  168. (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
  169. Horizontal values are in dotclock cycles (35 ns), vertical values are in
  170. scanlines.
  171. (0, 0) is somewhere in the upper-left corner :-)
  172. Dependencies (AGA, SHRES (35 ns dotclock))
  173. -------------------------------------------
  174. Since there are much more parameters for the Amiga display than for the
  175. frame buffer interface, there must be some dependencies among the Amiga
  176. display parameters. Here's what I found out:
  177. - ddfstrt and ddfstop are best aligned to 64 pixels.
  178. - the chipset needs 64 + 4 horizontal pixels after the DMA start before
  179. the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
  180. to display the first pixel on the line too. Increase diwstrt_h for
  181. virtual screen panning.
  182. - the display DMA always fetches 64 pixels at a time (fmode = 3).
  183. - ddfstop is ddfstrt+#pixels - 64.
  184. - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
  185. be 1 more than htotal.
  186. - hscroll simply adds a delay to the display output. Smooth horizontal
  187. panning needs an extra 64 pixels on the left to prefetch the pixels that
  188. `fall off' on the left.
  189. - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
  190. DMA, so it's best to make the DMA start as late as possible.
  191. - you really don't want to make ddfstrt < 128, since this will steal DMA
  192. cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
  193. - I make diwstop_h and diwstop_v as large as possible.
  194. General dependencies
  195. --------------------
  196. - all values are SHRES pixel (35ns)
  197. table 1:fetchstart table 2:prefetch table 3:fetchsize
  198. ------------------ ---------------- -----------------
  199. Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
  200. -------------#------+-----+------#------+-----+------#------+-----+------
  201. Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64
  202. Bus width 2x # 32 | 64 | 128 # 32 | 64 | 64 # 64 | 64 | 128
  203. Bus width 4x # 64 | 128 | 256 # 64 | 64 | 64 # 64 | 128 | 256
  204. - chipset needs 4 pixels before the first pixel is output
  205. - ddfstrt must be aligned to fetchstart (table 1)
  206. - chipset needs also prefetch (table 2) to get first pixel data, so
  207. ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
  208. - for horizontal panning decrease diwstrt_h
  209. - the length of a fetchline must be aligned to fetchsize (table 3)
  210. - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
  211. moved to optimize use of dma (useful for OCS/ECS overscan displays)
  212. - ddfstop is ddfstrt + ddfsize - fetchsize
  213. - If C= didn't change anything for AGA, then at following positions the
  214. dma bus is already used:
  215. ddfstrt < 48 -> memory refresh
  216. < 96 -> disk dma
  217. < 160 -> audio dma
  218. < 192 -> sprite 0 dma
  219. < 416 -> sprite dma (32 per sprite)
  220. - in accordance with the hardware reference manual a hardware stop is at
  221. 192, but AGA (ECS?) can go below this.
  222. DMA priorities
  223. --------------
  224. Since there are limits on the earliest start value for display DMA and the
  225. display of sprites, I use the following policy on horizontal panning and
  226. the hardware cursor:
  227. - if you want to start display DMA too early, you lose the ability to
  228. do smooth horizontal panning (xpanstep 1 -> 64).
  229. - if you want to go even further, you lose the hardware cursor too.
  230. IMHO a hardware cursor is more important for X than horizontal scrolling,
  231. so that's my motivation.
  232. Implementation
  233. --------------
  234. ami_decode_var() converts the frame buffer values to the Amiga values. It's
  235. just a `straightforward' implementation of the above rules.
  236. Standard VGA timings
  237. --------------------
  238. xres yres left right upper lower hsync vsync
  239. ---- ---- ---- ----- ----- ----- ----- -----
  240. 80x25 720 400 27 45 35 12 108 2
  241. 80x30 720 480 27 45 30 9 108 2
  242. These were taken from a XFree86 configuration file, recalculated for a 28 MHz
  243. dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
  244. generic timings.
  245. As a comparison, graphics/monitor.h suggests the following:
  246. xres yres left right upper lower hsync vsync
  247. ---- ---- ---- ----- ----- ----- ----- -----
  248. VGA 640 480 52 112 24 19 112 - 2 +
  249. VGA70 640 400 52 112 27 21 112 - 2 -
  250. Sync polarities
  251. ---------------
  252. VSYNC HSYNC Vertical size Vertical total
  253. ----- ----- ------------- --------------
  254. + + Reserved Reserved
  255. + - 400 414
  256. - + 350 362
  257. - - 480 496
  258. Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
  259. Broadcast video timings
  260. -----------------------
  261. According to the CCIR and RETMA specifications, we have the following values:
  262. CCIR -> PAL
  263. -----------
  264. - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
  265. 736 visible 70 ns pixels per line.
  266. - we have 625 scanlines, of which 575 are visible (interlaced); after
  267. rounding this becomes 576.
  268. RETMA -> NTSC
  269. -------------
  270. - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
  271. 736 visible 70 ns pixels per line.
  272. - we have 525 scanlines, of which 485 are visible (interlaced); after
  273. rounding this becomes 484.
  274. Thus if you want a PAL compatible display, you have to do the following:
  275. - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
  276. timings are to be used.
  277. - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
  278. interlaced, 312 for a non-interlaced and 156 for a doublescanned
  279. display.
  280. - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
  281. SHRES, 908 for a HIRES and 454 for a LORES display.
  282. - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
  283. left_margin + 2 * hsync_len must be greater or equal.
  284. - the upper visible part begins at 48 (interlaced; non-interlaced:24,
  285. doublescanned:12), upper_margin + 2 * vsync_len must be greater or
  286. equal.
  287. - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
  288. of 4 scanlines
  289. The settings for a NTSC compatible display are straightforward.
  290. Note that in a strict sense the PAL and NTSC standards only define the
  291. encoding of the color part (chrominance) of the video signal and don't say
  292. anything about horizontal/vertical synchronization nor refresh rates.
  293. -- Geert --
  294. *******************************************************************************/
  295. /*
  296. * Custom Chipset Definitions
  297. */
  298. #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
  299. /*
  300. * BPLCON0 -- Bitplane Control Register 0
  301. */
  302. #define BPC0_HIRES (0x8000)
  303. #define BPC0_BPU2 (0x4000) /* Bit plane used count */
  304. #define BPC0_BPU1 (0x2000)
  305. #define BPC0_BPU0 (0x1000)
  306. #define BPC0_HAM (0x0800) /* HAM mode */
  307. #define BPC0_DPF (0x0400) /* Double playfield */
  308. #define BPC0_COLOR (0x0200) /* Enable colorburst */
  309. #define BPC0_GAUD (0x0100) /* Genlock audio enable */
  310. #define BPC0_UHRES (0x0080) /* Ultrahi res enable */
  311. #define BPC0_SHRES (0x0040) /* Super hi res mode */
  312. #define BPC0_BYPASS (0x0020) /* Bypass LUT - AGA */
  313. #define BPC0_BPU3 (0x0010) /* AGA */
  314. #define BPC0_LPEN (0x0008) /* Light pen enable */
  315. #define BPC0_LACE (0x0004) /* Interlace */
  316. #define BPC0_ERSY (0x0002) /* External resync */
  317. #define BPC0_ECSENA (0x0001) /* ECS enable */
  318. /*
  319. * BPLCON2 -- Bitplane Control Register 2
  320. */
  321. #define BPC2_ZDBPSEL2 (0x4000) /* Bitplane to be used for ZD - AGA */
  322. #define BPC2_ZDBPSEL1 (0x2000)
  323. #define BPC2_ZDBPSEL0 (0x1000)
  324. #define BPC2_ZDBPEN (0x0800) /* Enable ZD with ZDBPSELx - AGA */
  325. #define BPC2_ZDCTEN (0x0400) /* Enable ZD with palette bit #31 - AGA */
  326. #define BPC2_KILLEHB (0x0200) /* Kill EHB mode - AGA */
  327. #define BPC2_RDRAM (0x0100) /* Color table accesses read, not write - AGA */
  328. #define BPC2_SOGEN (0x0080) /* SOG output pin high - AGA */
  329. #define BPC2_PF2PRI (0x0040) /* PF2 priority over PF1 */
  330. #define BPC2_PF2P2 (0x0020) /* PF2 priority wrt sprites */
  331. #define BPC2_PF2P1 (0x0010)
  332. #define BPC2_PF2P0 (0x0008)
  333. #define BPC2_PF1P2 (0x0004) /* ditto PF1 */
  334. #define BPC2_PF1P1 (0x0002)
  335. #define BPC2_PF1P0 (0x0001)
  336. /*
  337. * BPLCON3 -- Bitplane Control Register 3 (AGA)
  338. */
  339. #define BPC3_BANK2 (0x8000) /* Bits to select color register bank */
  340. #define BPC3_BANK1 (0x4000)
  341. #define BPC3_BANK0 (0x2000)
  342. #define BPC3_PF2OF2 (0x1000) /* Bits for color table offset when PF2 */
  343. #define BPC3_PF2OF1 (0x0800)
  344. #define BPC3_PF2OF0 (0x0400)
  345. #define BPC3_LOCT (0x0200) /* Color register writes go to low bits */
  346. #define BPC3_SPRES1 (0x0080) /* Sprite resolution bits */
  347. #define BPC3_SPRES0 (0x0040)
  348. #define BPC3_BRDRBLNK (0x0020) /* Border blanked? */
  349. #define BPC3_BRDRTRAN (0x0010) /* Border transparent? */
  350. #define BPC3_ZDCLKEN (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
  351. #define BPC3_BRDRSPRT (0x0002) /* Sprites in border? */
  352. #define BPC3_EXTBLKEN (0x0001) /* BLANK programmable */
  353. /*
  354. * BPLCON4 -- Bitplane Control Register 4 (AGA)
  355. */
  356. #define BPC4_BPLAM7 (0x8000) /* bitplane color XOR field */
  357. #define BPC4_BPLAM6 (0x4000)
  358. #define BPC4_BPLAM5 (0x2000)
  359. #define BPC4_BPLAM4 (0x1000)
  360. #define BPC4_BPLAM3 (0x0800)
  361. #define BPC4_BPLAM2 (0x0400)
  362. #define BPC4_BPLAM1 (0x0200)
  363. #define BPC4_BPLAM0 (0x0100)
  364. #define BPC4_ESPRM7 (0x0080) /* 4 high bits for even sprite colors */
  365. #define BPC4_ESPRM6 (0x0040)
  366. #define BPC4_ESPRM5 (0x0020)
  367. #define BPC4_ESPRM4 (0x0010)
  368. #define BPC4_OSPRM7 (0x0008) /* 4 high bits for odd sprite colors */
  369. #define BPC4_OSPRM6 (0x0004)
  370. #define BPC4_OSPRM5 (0x0002)
  371. #define BPC4_OSPRM4 (0x0001)
  372. /*
  373. * BEAMCON0 -- Beam Control Register
  374. */
  375. #define BMC0_HARDDIS (0x4000) /* Disable hardware limits */
  376. #define BMC0_LPENDIS (0x2000) /* Disable light pen latch */
  377. #define BMC0_VARVBEN (0x1000) /* Enable variable vertical blank */
  378. #define BMC0_LOLDIS (0x0800) /* Disable long/short line toggle */
  379. #define BMC0_CSCBEN (0x0400) /* Composite sync/blank */
  380. #define BMC0_VARVSYEN (0x0200) /* Enable variable vertical sync */
  381. #define BMC0_VARHSYEN (0x0100) /* Enable variable horizontal sync */
  382. #define BMC0_VARBEAMEN (0x0080) /* Enable variable beam counters */
  383. #define BMC0_DUAL (0x0040) /* Enable alternate horizontal beam counter */
  384. #define BMC0_PAL (0x0020) /* Set decodes for PAL */
  385. #define BMC0_VARCSYEN (0x0010) /* Enable variable composite sync */
  386. #define BMC0_BLANKEN (0x0008) /* Blank enable (no longer used on AGA) */
  387. #define BMC0_CSYTRUE (0x0004) /* CSY polarity */
  388. #define BMC0_VSYTRUE (0x0002) /* VSY polarity */
  389. #define BMC0_HSYTRUE (0x0001) /* HSY polarity */
  390. /*
  391. * FMODE -- Fetch Mode Control Register (AGA)
  392. */
  393. #define FMODE_SSCAN2 (0x8000) /* Sprite scan-doubling */
  394. #define FMODE_BSCAN2 (0x4000) /* Use PF2 modulus every other line */
  395. #define FMODE_SPAGEM (0x0008) /* Sprite page mode */
  396. #define FMODE_SPR32 (0x0004) /* Sprite 32 bit fetch */
  397. #define FMODE_BPAGEM (0x0002) /* Bitplane page mode */
  398. #define FMODE_BPL32 (0x0001) /* Bitplane 32 bit fetch */
  399. /*
  400. * Tags used to indicate a specific Pixel Clock
  401. *
  402. * clk_shift is the shift value to get the timings in 35 ns units
  403. */
  404. enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
  405. /*
  406. * Tags used to indicate the specific chipset
  407. */
  408. enum { TAG_OCS, TAG_ECS, TAG_AGA };
  409. /*
  410. * Tags used to indicate the memory bandwidth
  411. */
  412. enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
  413. /*
  414. * Clock Definitions, Maximum Display Depth
  415. *
  416. * These depend on the E-Clock or the Chipset, so they are filled in
  417. * dynamically
  418. */
  419. static u_long pixclock[3]; /* SHRES/HIRES/LORES: index = clk_shift */
  420. static u_short maxdepth[3]; /* SHRES/HIRES/LORES: index = clk_shift */
  421. static u_short maxfmode, chipset;
  422. /*
  423. * Broadcast Video Timings
  424. *
  425. * Horizontal values are in 35 ns (SHRES) units
  426. * Vertical values are in interlaced scanlines
  427. */
  428. #define PAL_DIWSTRT_H (360) /* PAL Window Limits */
  429. #define PAL_DIWSTRT_V (48)
  430. #define PAL_HTOTAL (1816)
  431. #define PAL_VTOTAL (625)
  432. #define NTSC_DIWSTRT_H (360) /* NTSC Window Limits */
  433. #define NTSC_DIWSTRT_V (40)
  434. #define NTSC_HTOTAL (1816)
  435. #define NTSC_VTOTAL (525)
  436. /*
  437. * Various macros
  438. */
  439. #define up2(v) (((v) + 1) & -2)
  440. #define down2(v) ((v) & -2)
  441. #define div2(v) ((v)>>1)
  442. #define mod2(v) ((v) & 1)
  443. #define up4(v) (((v) + 3) & -4)
  444. #define down4(v) ((v) & -4)
  445. #define mul4(v) ((v) << 2)
  446. #define div4(v) ((v)>>2)
  447. #define mod4(v) ((v) & 3)
  448. #define up8(v) (((v) + 7) & -8)
  449. #define down8(v) ((v) & -8)
  450. #define div8(v) ((v)>>3)
  451. #define mod8(v) ((v) & 7)
  452. #define up16(v) (((v) + 15) & -16)
  453. #define down16(v) ((v) & -16)
  454. #define div16(v) ((v)>>4)
  455. #define mod16(v) ((v) & 15)
  456. #define up32(v) (((v) + 31) & -32)
  457. #define down32(v) ((v) & -32)
  458. #define div32(v) ((v)>>5)
  459. #define mod32(v) ((v) & 31)
  460. #define up64(v) (((v) + 63) & -64)
  461. #define down64(v) ((v) & -64)
  462. #define div64(v) ((v)>>6)
  463. #define mod64(v) ((v) & 63)
  464. #define upx(x, v) (((v) + (x) - 1) & -(x))
  465. #define downx(x, v) ((v) & -(x))
  466. #define modx(x, v) ((v) & ((x) - 1))
  467. /* if x1 is not a constant, this macro won't make real sense :-) */
  468. #ifdef __mc68000__
  469. #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
  470. "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
  471. #else
  472. /* We know a bit about the numbers, so we can do it this way */
  473. #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
  474. ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
  475. #endif
  476. #define highw(x) ((u_long)(x)>>16 & 0xffff)
  477. #define loww(x) ((u_long)(x) & 0xffff)
  478. #define custom amiga_custom
  479. #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
  480. #define VBlankOff() custom.intena = IF_COPER
  481. /*
  482. * Chip RAM we reserve for the Frame Buffer
  483. *
  484. * This defines the Maximum Virtual Screen Size
  485. * (Setable per kernel options?)
  486. */
  487. #define VIDEOMEMSIZE_AGA_2M (1310720) /* AGA (2MB) : max 1280*1024*256 */
  488. #define VIDEOMEMSIZE_AGA_1M (786432) /* AGA (1MB) : max 1024*768*256 */
  489. #define VIDEOMEMSIZE_ECS_2M (655360) /* ECS (2MB) : max 1280*1024*16 */
  490. #define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */
  491. #define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */
  492. #define SPRITEMEMSIZE (64 * 64 / 4) /* max 64*64*4 */
  493. #define DUMMYSPRITEMEMSIZE (8)
  494. static u_long spritememory;
  495. #define CHIPRAM_SAFETY_LIMIT (16384)
  496. static u_long videomemory;
  497. /*
  498. * This is the earliest allowed start of fetching display data.
  499. * Only if you really want no hardware cursor and audio,
  500. * set this to 128, but let it better at 192
  501. */
  502. static u_long min_fstrt = 192;
  503. #define assignchunk(name, type, ptr, size) \
  504. { \
  505. (name) = (type)(ptr); \
  506. ptr += size; \
  507. }
  508. /*
  509. * Copper Instructions
  510. */
  511. #define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
  512. #define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
  513. #define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
  514. #define CEND (0xfffffffe)
  515. typedef union {
  516. u_long l;
  517. u_short w[2];
  518. } copins;
  519. static struct copdisplay {
  520. copins *init;
  521. copins *wait;
  522. copins *list[2][2];
  523. copins *rebuild[2];
  524. } copdisplay;
  525. static u_short currentcop = 0;
  526. /*
  527. * Hardware Cursor API Definitions
  528. * These used to be in linux/fb.h, but were preliminary and used by
  529. * amifb only anyway
  530. */
  531. #define FBIOGET_FCURSORINFO 0x4607
  532. #define FBIOGET_VCURSORINFO 0x4608
  533. #define FBIOPUT_VCURSORINFO 0x4609
  534. #define FBIOGET_CURSORSTATE 0x460A
  535. #define FBIOPUT_CURSORSTATE 0x460B
  536. struct fb_fix_cursorinfo {
  537. __u16 crsr_width; /* width and height of the cursor in */
  538. __u16 crsr_height; /* pixels (zero if no cursor) */
  539. __u16 crsr_xsize; /* cursor size in display pixels */
  540. __u16 crsr_ysize;
  541. __u16 crsr_color1; /* colormap entry for cursor color1 */
  542. __u16 crsr_color2; /* colormap entry for cursor color2 */
  543. };
  544. struct fb_var_cursorinfo {
  545. __u16 width;
  546. __u16 height;
  547. __u16 xspot;
  548. __u16 yspot;
  549. __u8 data[1]; /* field with [height][width] */
  550. };
  551. struct fb_cursorstate {
  552. __s16 xoffset;
  553. __s16 yoffset;
  554. __u16 mode;
  555. };
  556. #define FB_CURSOR_OFF 0
  557. #define FB_CURSOR_ON 1
  558. #define FB_CURSOR_FLASH 2
  559. /*
  560. * Hardware Cursor
  561. */
  562. static int cursorrate = 20; /* Number of frames/flash toggle */
  563. static u_short cursorstate = -1;
  564. static u_short cursormode = FB_CURSOR_OFF;
  565. static u_short *lofsprite, *shfsprite, *dummysprite;
  566. /*
  567. * Current Video Mode
  568. */
  569. struct amifb_par {
  570. /* General Values */
  571. int xres; /* vmode */
  572. int yres; /* vmode */
  573. int vxres; /* vmode */
  574. int vyres; /* vmode */
  575. int xoffset; /* vmode */
  576. int yoffset; /* vmode */
  577. u_short bpp; /* vmode */
  578. u_short clk_shift; /* vmode */
  579. u_short line_shift; /* vmode */
  580. int vmode; /* vmode */
  581. u_short diwstrt_h; /* vmode */
  582. u_short diwstop_h; /* vmode */
  583. u_short diwstrt_v; /* vmode */
  584. u_short diwstop_v; /* vmode */
  585. u_long next_line; /* modulo for next line */
  586. u_long next_plane; /* modulo for next plane */
  587. /* Cursor Values */
  588. struct {
  589. short crsr_x; /* movecursor */
  590. short crsr_y; /* movecursor */
  591. short spot_x;
  592. short spot_y;
  593. u_short height;
  594. u_short width;
  595. u_short fmode;
  596. } crsr;
  597. /* OCS Hardware Registers */
  598. u_long bplpt0; /* vmode, pan (Note: physical address) */
  599. u_long bplpt0wrap; /* vmode, pan (Note: physical address) */
  600. u_short ddfstrt;
  601. u_short ddfstop;
  602. u_short bpl1mod;
  603. u_short bpl2mod;
  604. u_short bplcon0; /* vmode */
  605. u_short bplcon1; /* vmode */
  606. u_short htotal; /* vmode */
  607. u_short vtotal; /* vmode */
  608. /* Additional ECS Hardware Registers */
  609. u_short bplcon3; /* vmode */
  610. u_short beamcon0; /* vmode */
  611. u_short hsstrt; /* vmode */
  612. u_short hsstop; /* vmode */
  613. u_short hbstrt; /* vmode */
  614. u_short hbstop; /* vmode */
  615. u_short vsstrt; /* vmode */
  616. u_short vsstop; /* vmode */
  617. u_short vbstrt; /* vmode */
  618. u_short vbstop; /* vmode */
  619. u_short hcenter; /* vmode */
  620. /* Additional AGA Hardware Registers */
  621. u_short fmode; /* vmode */
  622. };
  623. /*
  624. * Saved color entry 0 so we can restore it when unblanking
  625. */
  626. static u_char red0, green0, blue0;
  627. #if defined(CONFIG_FB_AMIGA_ECS)
  628. static u_short ecs_palette[32];
  629. #endif
  630. /*
  631. * Latches for Display Changes during VBlank
  632. */
  633. static u_short do_vmode_full = 0; /* Change the Video Mode */
  634. static u_short do_vmode_pan = 0; /* Update the Video Mode */
  635. static short do_blank = 0; /* (Un)Blank the Screen (±1) */
  636. static u_short do_cursor = 0; /* Move the Cursor */
  637. /*
  638. * Various Flags
  639. */
  640. static u_short is_blanked = 0; /* Screen is Blanked */
  641. static u_short is_lace = 0; /* Screen is laced */
  642. /*
  643. * Predefined Video Modes
  644. *
  645. */
  646. static struct fb_videomode ami_modedb[] __initdata = {
  647. /*
  648. * AmigaOS Video Modes
  649. *
  650. * If you change these, make sure to update DEFMODE_* as well!
  651. */
  652. {
  653. /* 640x200, 15 kHz, 60 Hz (NTSC) */
  654. "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
  655. FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  656. }, {
  657. /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
  658. "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
  659. FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  660. }, {
  661. /* 640x256, 15 kHz, 50 Hz (PAL) */
  662. "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
  663. FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  664. }, {
  665. /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
  666. "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
  667. FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  668. }, {
  669. /* 640x480, 29 kHz, 57 Hz */
  670. "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
  671. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  672. }, {
  673. /* 640x960, 29 kHz, 57 Hz interlaced */
  674. "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
  675. 16,
  676. 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  677. }, {
  678. /* 640x200, 15 kHz, 72 Hz */
  679. "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
  680. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  681. }, {
  682. /* 640x400, 15 kHz, 72 Hz interlaced */
  683. "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
  684. 10,
  685. 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  686. }, {
  687. /* 640x400, 29 kHz, 68 Hz */
  688. "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
  689. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  690. }, {
  691. /* 640x800, 29 kHz, 68 Hz interlaced */
  692. "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
  693. 16,
  694. 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  695. }, {
  696. /* 800x300, 23 kHz, 70 Hz */
  697. "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
  698. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  699. }, {
  700. /* 800x600, 23 kHz, 70 Hz interlaced */
  701. "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
  702. 14,
  703. 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  704. }, {
  705. /* 640x200, 27 kHz, 57 Hz doublescan */
  706. "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
  707. 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
  708. }, {
  709. /* 640x400, 27 kHz, 57 Hz */
  710. "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
  711. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  712. }, {
  713. /* 640x800, 27 kHz, 57 Hz interlaced */
  714. "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
  715. 14,
  716. 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  717. }, {
  718. /* 640x256, 27 kHz, 47 Hz doublescan */
  719. "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
  720. 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
  721. }, {
  722. /* 640x512, 27 kHz, 47 Hz */
  723. "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
  724. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  725. }, {
  726. /* 640x1024, 27 kHz, 47 Hz interlaced */
  727. "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
  728. 14,
  729. 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
  730. },
  731. /*
  732. * VGA Video Modes
  733. */
  734. {
  735. /* 640x480, 31 kHz, 60 Hz (VGA) */
  736. "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
  737. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  738. }, {
  739. /* 640x400, 31 kHz, 70 Hz (VGA) */
  740. "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
  741. FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
  742. FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  743. },
  744. #if 0
  745. /*
  746. * A2024 video modes
  747. * These modes don't work yet because there's no A2024 driver.
  748. */
  749. {
  750. /* 1024x800, 10 Hz */
  751. "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
  752. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  753. }, {
  754. /* 1024x800, 15 Hz */
  755. "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
  756. 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
  757. }
  758. #endif
  759. };
  760. #define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb)
  761. static char *mode_option __initdata = NULL;
  762. static int round_down_bpp = 1; /* for mode probing */
  763. /*
  764. * Some default modes
  765. */
  766. #define DEFMODE_PAL 2 /* "pal" for PAL OCS/ECS */
  767. #define DEFMODE_NTSC 0 /* "ntsc" for NTSC OCS/ECS */
  768. #define DEFMODE_AMBER_PAL 3 /* "pal-lace" for flicker fixed PAL (A3000) */
  769. #define DEFMODE_AMBER_NTSC 1 /* "ntsc-lace" for flicker fixed NTSC (A3000) */
  770. #define DEFMODE_AGA 19 /* "vga70" for AGA */
  771. static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
  772. static int amifb_inverse = 0;
  773. static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
  774. static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
  775. static u16 amifb_vfmin __initdata; /* monitor vfreq lower limit (Hz) */
  776. static u16 amifb_vfmax __initdata; /* monitor vfreq upper limit (Hz) */
  777. /*
  778. * Macros for the conversion from real world values to hardware register
  779. * values
  780. *
  781. * This helps us to keep our attention on the real stuff...
  782. *
  783. * Hardware limits for AGA:
  784. *
  785. * parameter min max step
  786. * --------- --- ---- ----
  787. * diwstrt_h 0 2047 1
  788. * diwstrt_v 0 2047 1
  789. * diwstop_h 0 4095 1
  790. * diwstop_v 0 4095 1
  791. *
  792. * ddfstrt 0 2032 16
  793. * ddfstop 0 2032 16
  794. *
  795. * htotal 8 2048 8
  796. * hsstrt 0 2040 8
  797. * hsstop 0 2040 8
  798. * vtotal 1 4096 1
  799. * vsstrt 0 4095 1
  800. * vsstop 0 4095 1
  801. * hcenter 0 2040 8
  802. *
  803. * hbstrt 0 2047 1
  804. * hbstop 0 2047 1
  805. * vbstrt 0 4095 1
  806. * vbstop 0 4095 1
  807. *
  808. * Horizontal values are in 35 ns (SHRES) pixels
  809. * Vertical values are in half scanlines
  810. */
  811. /* bplcon1 (smooth scrolling) */
  812. #define hscroll2hw(hscroll) \
  813. (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
  814. ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
  815. ((hscroll)>>2 & 0x000f))
  816. /* diwstrt/diwstop/diwhigh (visible display window) */
  817. #define diwstrt2hw(diwstrt_h, diwstrt_v) \
  818. (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
  819. #define diwstop2hw(diwstop_h, diwstop_v) \
  820. (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
  821. #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
  822. (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
  823. ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
  824. ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
  825. /* ddfstrt/ddfstop (display DMA) */
  826. #define ddfstrt2hw(ddfstrt) div8(ddfstrt)
  827. #define ddfstop2hw(ddfstop) div8(ddfstop)
  828. /* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
  829. #define hsstrt2hw(hsstrt) (div8(hsstrt))
  830. #define hsstop2hw(hsstop) (div8(hsstop))
  831. #define htotal2hw(htotal) (div8(htotal) - 1)
  832. #define vsstrt2hw(vsstrt) (div2(vsstrt))
  833. #define vsstop2hw(vsstop) (div2(vsstop))
  834. #define vtotal2hw(vtotal) (div2(vtotal) - 1)
  835. #define hcenter2hw(htotal) (div8(htotal))
  836. /* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
  837. #define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
  838. #define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
  839. #define vbstrt2hw(vbstrt) (div2(vbstrt))
  840. #define vbstop2hw(vbstop) (div2(vbstop))
  841. /* colour */
  842. #define rgb2hw8_high(red, green, blue) \
  843. (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
  844. #define rgb2hw8_low(red, green, blue) \
  845. (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
  846. #define rgb2hw4(red, green, blue) \
  847. (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
  848. #define rgb2hw2(red, green, blue) \
  849. (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
  850. /* sprpos/sprctl (sprite positioning) */
  851. #define spr2hw_pos(start_v, start_h) \
  852. (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
  853. #define spr2hw_ctl(start_v, start_h, stop_v) \
  854. (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
  855. ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
  856. ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
  857. ((start_h)>>2 & 0x0001))
  858. /* get current vertical position of beam */
  859. #define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
  860. /*
  861. * Copper Initialisation List
  862. */
  863. #define COPINITSIZE (sizeof(copins) * 40)
  864. enum {
  865. cip_bplcon0
  866. };
  867. /*
  868. * Long Frame/Short Frame Copper List
  869. * Don't change the order, build_copper()/rebuild_copper() rely on this
  870. */
  871. #define COPLISTSIZE (sizeof(copins) * 64)
  872. enum {
  873. cop_wait, cop_bplcon0,
  874. cop_spr0ptrh, cop_spr0ptrl,
  875. cop_diwstrt, cop_diwstop,
  876. cop_diwhigh,
  877. };
  878. /*
  879. * Pixel modes for Bitplanes and Sprites
  880. */
  881. static u_short bplpixmode[3] = {
  882. BPC0_SHRES, /* 35 ns */
  883. BPC0_HIRES, /* 70 ns */
  884. 0 /* 140 ns */
  885. };
  886. static u_short sprpixmode[3] = {
  887. BPC3_SPRES1 | BPC3_SPRES0, /* 35 ns */
  888. BPC3_SPRES1, /* 70 ns */
  889. BPC3_SPRES0 /* 140 ns */
  890. };
  891. /*
  892. * Fetch modes for Bitplanes and Sprites
  893. */
  894. static u_short bplfetchmode[3] = {
  895. 0, /* 1x */
  896. FMODE_BPL32, /* 2x */
  897. FMODE_BPAGEM | FMODE_BPL32 /* 4x */
  898. };
  899. static u_short sprfetchmode[3] = {
  900. 0, /* 1x */
  901. FMODE_SPR32, /* 2x */
  902. FMODE_SPAGEM | FMODE_SPR32 /* 4x */
  903. };
  904. /* --------------------------- Hardware routines --------------------------- */
  905. /*
  906. * Get the video params out of `var'. If a value doesn't fit, round
  907. * it up, if it's too big, return -EINVAL.
  908. */
  909. static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
  910. const struct fb_info *info)
  911. {
  912. u_short clk_shift, line_shift;
  913. u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
  914. u_int htotal, vtotal;
  915. /*
  916. * Find a matching Pixel Clock
  917. */
  918. for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
  919. if (var->pixclock <= pixclock[clk_shift])
  920. break;
  921. if (clk_shift > TAG_LORES) {
  922. DPRINTK("pixclock too high\n");
  923. return -EINVAL;
  924. }
  925. par->clk_shift = clk_shift;
  926. /*
  927. * Check the Geometry Values
  928. */
  929. if ((par->xres = var->xres) < 64)
  930. par->xres = 64;
  931. if ((par->yres = var->yres) < 64)
  932. par->yres = 64;
  933. if ((par->vxres = var->xres_virtual) < par->xres)
  934. par->vxres = par->xres;
  935. if ((par->vyres = var->yres_virtual) < par->yres)
  936. par->vyres = par->yres;
  937. par->bpp = var->bits_per_pixel;
  938. if (!var->nonstd) {
  939. if (par->bpp < 1)
  940. par->bpp = 1;
  941. if (par->bpp > maxdepth[clk_shift]) {
  942. if (round_down_bpp && maxdepth[clk_shift])
  943. par->bpp = maxdepth[clk_shift];
  944. else {
  945. DPRINTK("invalid bpp\n");
  946. return -EINVAL;
  947. }
  948. }
  949. } else if (var->nonstd == FB_NONSTD_HAM) {
  950. if (par->bpp < 6)
  951. par->bpp = 6;
  952. if (par->bpp != 6) {
  953. if (par->bpp < 8)
  954. par->bpp = 8;
  955. if (par->bpp != 8 || !IS_AGA) {
  956. DPRINTK("invalid bpp for ham mode\n");
  957. return -EINVAL;
  958. }
  959. }
  960. } else {
  961. DPRINTK("unknown nonstd mode\n");
  962. return -EINVAL;
  963. }
  964. /*
  965. * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
  966. * checks failed and smooth scrolling is not possible
  967. */
  968. par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
  969. switch (par->vmode & FB_VMODE_MASK) {
  970. case FB_VMODE_INTERLACED:
  971. line_shift = 0;
  972. break;
  973. case FB_VMODE_NONINTERLACED:
  974. line_shift = 1;
  975. break;
  976. case FB_VMODE_DOUBLE:
  977. if (!IS_AGA) {
  978. DPRINTK("double mode only possible with aga\n");
  979. return -EINVAL;
  980. }
  981. line_shift = 2;
  982. break;
  983. default:
  984. DPRINTK("unknown video mode\n");
  985. return -EINVAL;
  986. break;
  987. }
  988. par->line_shift = line_shift;
  989. /*
  990. * Vertical and Horizontal Timings
  991. */
  992. xres_n = par->xres << clk_shift;
  993. yres_n = par->yres << line_shift;
  994. par->htotal = down8((var->left_margin + par->xres + var->right_margin +
  995. var->hsync_len) << clk_shift);
  996. par->vtotal =
  997. down2(((var->upper_margin + par->yres + var->lower_margin +
  998. var->vsync_len) << line_shift) + 1);
  999. if (IS_AGA)
  1000. par->bplcon3 = sprpixmode[clk_shift];
  1001. else
  1002. par->bplcon3 = 0;
  1003. if (var->sync & FB_SYNC_BROADCAST) {
  1004. par->diwstop_h = par->htotal -
  1005. ((var->right_margin - var->hsync_len) << clk_shift);
  1006. if (IS_AGA)
  1007. par->diwstop_h += mod4(var->hsync_len);
  1008. else
  1009. par->diwstop_h = down4(par->diwstop_h);
  1010. par->diwstrt_h = par->diwstop_h - xres_n;
  1011. par->diwstop_v = par->vtotal -
  1012. ((var->lower_margin - var->vsync_len) << line_shift);
  1013. par->diwstrt_v = par->diwstop_v - yres_n;
  1014. if (par->diwstop_h >= par->htotal + 8) {
  1015. DPRINTK("invalid diwstop_h\n");
  1016. return -EINVAL;
  1017. }
  1018. if (par->diwstop_v > par->vtotal) {
  1019. DPRINTK("invalid diwstop_v\n");
  1020. return -EINVAL;
  1021. }
  1022. if (!IS_OCS) {
  1023. /* Initialize sync with some reasonable values for pwrsave */
  1024. par->hsstrt = 160;
  1025. par->hsstop = 320;
  1026. par->vsstrt = 30;
  1027. par->vsstop = 34;
  1028. } else {
  1029. par->hsstrt = 0;
  1030. par->hsstop = 0;
  1031. par->vsstrt = 0;
  1032. par->vsstop = 0;
  1033. }
  1034. if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
  1035. /* PAL video mode */
  1036. if (par->htotal != PAL_HTOTAL) {
  1037. DPRINTK("htotal invalid for pal\n");
  1038. return -EINVAL;
  1039. }
  1040. if (par->diwstrt_h < PAL_DIWSTRT_H) {
  1041. DPRINTK("diwstrt_h too low for pal\n");
  1042. return -EINVAL;
  1043. }
  1044. if (par->diwstrt_v < PAL_DIWSTRT_V) {
  1045. DPRINTK("diwstrt_v too low for pal\n");
  1046. return -EINVAL;
  1047. }
  1048. htotal = PAL_HTOTAL>>clk_shift;
  1049. vtotal = PAL_VTOTAL>>1;
  1050. if (!IS_OCS) {
  1051. par->beamcon0 = BMC0_PAL;
  1052. par->bplcon3 |= BPC3_BRDRBLNK;
  1053. } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
  1054. AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
  1055. par->beamcon0 = BMC0_PAL;
  1056. par->hsstop = 1;
  1057. } else if (amiga_vblank != 50) {
  1058. DPRINTK("pal not supported by this chipset\n");
  1059. return -EINVAL;
  1060. }
  1061. } else {
  1062. /* NTSC video mode
  1063. * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
  1064. * and NTSC activated, so than better let diwstop_h <= 1812
  1065. */
  1066. if (par->htotal != NTSC_HTOTAL) {
  1067. DPRINTK("htotal invalid for ntsc\n");
  1068. return -EINVAL;
  1069. }
  1070. if (par->diwstrt_h < NTSC_DIWSTRT_H) {
  1071. DPRINTK("diwstrt_h too low for ntsc\n");
  1072. return -EINVAL;
  1073. }
  1074. if (par->diwstrt_v < NTSC_DIWSTRT_V) {
  1075. DPRINTK("diwstrt_v too low for ntsc\n");
  1076. return -EINVAL;
  1077. }
  1078. htotal = NTSC_HTOTAL>>clk_shift;
  1079. vtotal = NTSC_VTOTAL>>1;
  1080. if (!IS_OCS) {
  1081. par->beamcon0 = 0;
  1082. par->bplcon3 |= BPC3_BRDRBLNK;
  1083. } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
  1084. AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
  1085. par->beamcon0 = 0;
  1086. par->hsstop = 1;
  1087. } else if (amiga_vblank != 60) {
  1088. DPRINTK("ntsc not supported by this chipset\n");
  1089. return -EINVAL;
  1090. }
  1091. }
  1092. if (IS_OCS) {
  1093. if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
  1094. par->diwstrt_v >= 512 || par->diwstop_v < 256) {
  1095. DPRINTK("invalid position for display on ocs\n");
  1096. return -EINVAL;
  1097. }
  1098. }
  1099. } else if (!IS_OCS) {
  1100. /* Programmable video mode */
  1101. par->hsstrt = var->right_margin << clk_shift;
  1102. par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
  1103. par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
  1104. if (!IS_AGA)
  1105. par->diwstop_h = down4(par->diwstop_h) - 16;
  1106. par->diwstrt_h = par->diwstop_h - xres_n;
  1107. par->hbstop = par->diwstrt_h + 4;
  1108. par->hbstrt = par->diwstop_h + 4;
  1109. if (par->hbstrt >= par->htotal + 8)
  1110. par->hbstrt -= par->htotal;
  1111. par->hcenter = par->hsstrt + (par->htotal >> 1);
  1112. par->vsstrt = var->lower_margin << line_shift;
  1113. par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
  1114. par->diwstop_v = par->vtotal;
  1115. if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
  1116. par->diwstop_v -= 2;
  1117. par->diwstrt_v = par->diwstop_v - yres_n;
  1118. par->vbstop = par->diwstrt_v - 2;
  1119. par->vbstrt = par->diwstop_v - 2;
  1120. if (par->vtotal > 2048) {
  1121. DPRINTK("vtotal too high\n");
  1122. return -EINVAL;
  1123. }
  1124. if (par->htotal > 2048) {
  1125. DPRINTK("htotal too high\n");
  1126. return -EINVAL;
  1127. }
  1128. par->bplcon3 |= BPC3_EXTBLKEN;
  1129. par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
  1130. BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
  1131. BMC0_PAL | BMC0_VARCSYEN;
  1132. if (var->sync & FB_SYNC_HOR_HIGH_ACT)
  1133. par->beamcon0 |= BMC0_HSYTRUE;
  1134. if (var->sync & FB_SYNC_VERT_HIGH_ACT)
  1135. par->beamcon0 |= BMC0_VSYTRUE;
  1136. if (var->sync & FB_SYNC_COMP_HIGH_ACT)
  1137. par->beamcon0 |= BMC0_CSYTRUE;
  1138. htotal = par->htotal>>clk_shift;
  1139. vtotal = par->vtotal>>1;
  1140. } else {
  1141. DPRINTK("only broadcast modes possible for ocs\n");
  1142. return -EINVAL;
  1143. }
  1144. /*
  1145. * Checking the DMA timing
  1146. */
  1147. fconst = 16 << maxfmode << clk_shift;
  1148. /*
  1149. * smallest window start value without turn off other dma cycles
  1150. * than sprite1-7, unless you change min_fstrt
  1151. */
  1152. fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
  1153. fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
  1154. if (fstrt < min_fstrt) {
  1155. DPRINTK("fetch start too low\n");
  1156. return -EINVAL;
  1157. }
  1158. /*
  1159. * smallest window start value where smooth scrolling is possible
  1160. */
  1161. fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
  1162. fsize;
  1163. if (fstrt < min_fstrt)
  1164. par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
  1165. maxfetchstop = down16(par->htotal - 80);
  1166. fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
  1167. fsize = upx(fconst, xres_n +
  1168. modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
  1169. if (fstrt + fsize > maxfetchstop)
  1170. par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
  1171. fsize = upx(fconst, xres_n);
  1172. if (fstrt + fsize > maxfetchstop) {
  1173. DPRINTK("fetch stop too high\n");
  1174. return -EINVAL;
  1175. }
  1176. if (maxfmode + clk_shift <= 1) {
  1177. fsize = up64(xres_n + fconst - 1);
  1178. if (min_fstrt + fsize - 64 > maxfetchstop)
  1179. par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
  1180. fsize = up64(xres_n);
  1181. if (min_fstrt + fsize - 64 > maxfetchstop) {
  1182. DPRINTK("fetch size too high\n");
  1183. return -EINVAL;
  1184. }
  1185. fsize -= 64;
  1186. } else
  1187. fsize -= fconst;
  1188. /*
  1189. * Check if there is enough time to update the bitplane pointers for ywrap
  1190. */
  1191. if (par->htotal - fsize - 64 < par->bpp * 64)
  1192. par->vmode &= ~FB_VMODE_YWRAP;
  1193. /*
  1194. * Bitplane calculations and check the Memory Requirements
  1195. */
  1196. if (amifb_ilbm) {
  1197. par->next_plane = div8(upx(16 << maxfmode, par->vxres));
  1198. par->next_line = par->bpp * par->next_plane;
  1199. if (par->next_line * par->vyres > info->fix.smem_len) {
  1200. DPRINTK("too few video mem\n");
  1201. return -EINVAL;
  1202. }
  1203. } else {
  1204. par->next_line = div8(upx(16 << maxfmode, par->vxres));
  1205. par->next_plane = par->vyres * par->next_line;
  1206. if (par->next_plane * par->bpp > info->fix.smem_len) {
  1207. DPRINTK("too few video mem\n");
  1208. return -EINVAL;
  1209. }
  1210. }
  1211. /*
  1212. * Hardware Register Values
  1213. */
  1214. par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
  1215. if (!IS_OCS)
  1216. par->bplcon0 |= BPC0_ECSENA;
  1217. if (par->bpp == 8)
  1218. par->bplcon0 |= BPC0_BPU3;
  1219. else
  1220. par->bplcon0 |= par->bpp << 12;
  1221. if (var->nonstd == FB_NONSTD_HAM)
  1222. par->bplcon0 |= BPC0_HAM;
  1223. if (var->sync & FB_SYNC_EXT)
  1224. par->bplcon0 |= BPC0_ERSY;
  1225. if (IS_AGA)
  1226. par->fmode = bplfetchmode[maxfmode];
  1227. switch (par->vmode & FB_VMODE_MASK) {
  1228. case FB_VMODE_INTERLACED:
  1229. par->bplcon0 |= BPC0_LACE;
  1230. break;
  1231. case FB_VMODE_DOUBLE:
  1232. if (IS_AGA)
  1233. par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
  1234. break;
  1235. }
  1236. if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
  1237. par->xoffset = var->xoffset;
  1238. par->yoffset = var->yoffset;
  1239. if (par->vmode & FB_VMODE_YWRAP) {
  1240. if (par->xoffset || par->yoffset < 0 ||
  1241. par->yoffset >= par->vyres)
  1242. par->xoffset = par->yoffset = 0;
  1243. } else {
  1244. if (par->xoffset < 0 ||
  1245. par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
  1246. par->yoffset < 0 || par->yoffset > par->vyres - par->yres)
  1247. par->xoffset = par->yoffset = 0;
  1248. }
  1249. } else
  1250. par->xoffset = par->yoffset = 0;
  1251. par->crsr.crsr_x = par->crsr.crsr_y = 0;
  1252. par->crsr.spot_x = par->crsr.spot_y = 0;
  1253. par->crsr.height = par->crsr.width = 0;
  1254. return 0;
  1255. }
  1256. /*
  1257. * Fill the `var' structure based on the values in `par' and maybe
  1258. * other values read out of the hardware.
  1259. */
  1260. static void ami_encode_var(struct fb_var_screeninfo *var,
  1261. struct amifb_par *par)
  1262. {
  1263. u_short clk_shift, line_shift;
  1264. memset(var, 0, sizeof(struct fb_var_screeninfo));
  1265. clk_shift = par->clk_shift;
  1266. line_shift = par->line_shift;
  1267. var->xres = par->xres;
  1268. var->yres = par->yres;
  1269. var->xres_virtual = par->vxres;
  1270. var->yres_virtual = par->vyres;
  1271. var->xoffset = par->xoffset;
  1272. var->yoffset = par->yoffset;
  1273. var->bits_per_pixel = par->bpp;
  1274. var->grayscale = 0;
  1275. var->red.offset = 0;
  1276. var->red.msb_right = 0;
  1277. var->red.length = par->bpp;
  1278. if (par->bplcon0 & BPC0_HAM)
  1279. var->red.length -= 2;
  1280. var->blue = var->green = var->red;
  1281. var->transp.offset = 0;
  1282. var->transp.length = 0;
  1283. var->transp.msb_right = 0;
  1284. if (par->bplcon0 & BPC0_HAM)
  1285. var->nonstd = FB_NONSTD_HAM;
  1286. else
  1287. var->nonstd = 0;
  1288. var->activate = 0;
  1289. var->height = -1;
  1290. var->width = -1;
  1291. var->pixclock = pixclock[clk_shift];
  1292. if (IS_AGA && par->fmode & FMODE_BSCAN2)
  1293. var->vmode = FB_VMODE_DOUBLE;
  1294. else if (par->bplcon0 & BPC0_LACE)
  1295. var->vmode = FB_VMODE_INTERLACED;
  1296. else
  1297. var->vmode = FB_VMODE_NONINTERLACED;
  1298. if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
  1299. var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
  1300. var->right_margin = par->hsstrt>>clk_shift;
  1301. var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
  1302. var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
  1303. var->lower_margin = par->vsstrt>>line_shift;
  1304. var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
  1305. var->sync = 0;
  1306. if (par->beamcon0 & BMC0_HSYTRUE)
  1307. var->sync |= FB_SYNC_HOR_HIGH_ACT;
  1308. if (par->beamcon0 & BMC0_VSYTRUE)
  1309. var->sync |= FB_SYNC_VERT_HIGH_ACT;
  1310. if (par->beamcon0 & BMC0_CSYTRUE)
  1311. var->sync |= FB_SYNC_COMP_HIGH_ACT;
  1312. } else {
  1313. var->sync = FB_SYNC_BROADCAST;
  1314. var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
  1315. var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
  1316. var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
  1317. var->vsync_len = 4>>line_shift;
  1318. var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
  1319. var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
  1320. var->lower_margin - var->vsync_len;
  1321. }
  1322. if (par->bplcon0 & BPC0_ERSY)
  1323. var->sync |= FB_SYNC_EXT;
  1324. if (par->vmode & FB_VMODE_YWRAP)
  1325. var->vmode |= FB_VMODE_YWRAP;
  1326. }
  1327. /*
  1328. * Update hardware
  1329. */
  1330. static void ami_update_par(struct fb_info *info)
  1331. {
  1332. struct amifb_par *par = info->par;
  1333. short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
  1334. clk_shift = par->clk_shift;
  1335. if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
  1336. par->xoffset = upx(16 << maxfmode, par->xoffset);
  1337. fconst = 16 << maxfmode << clk_shift;
  1338. vshift = modx(16 << maxfmode, par->xoffset);
  1339. fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
  1340. fsize = (par->xres + vshift) << clk_shift;
  1341. shift = modx(fconst, fstrt);
  1342. move = downx(2 << maxfmode, div8(par->xoffset));
  1343. if (maxfmode + clk_shift > 1) {
  1344. fstrt = downx(fconst, fstrt) - 64;
  1345. fsize = upx(fconst, fsize);
  1346. fstop = fstrt + fsize - fconst;
  1347. } else {
  1348. mod = fstrt = downx(fconst, fstrt) - fconst;
  1349. fstop = fstrt + upx(fconst, fsize) - 64;
  1350. fsize = up64(fsize);
  1351. fstrt = fstop - fsize + 64;
  1352. if (fstrt < min_fstrt) {
  1353. fstop += min_fstrt - fstrt;
  1354. fstrt = min_fstrt;
  1355. }
  1356. move = move - div8((mod - fstrt)>>clk_shift);
  1357. }
  1358. mod = par->next_line - div8(fsize>>clk_shift);
  1359. par->ddfstrt = fstrt;
  1360. par->ddfstop = fstop;
  1361. par->bplcon1 = hscroll2hw(shift);
  1362. par->bpl2mod = mod;
  1363. if (par->bplcon0 & BPC0_LACE)
  1364. par->bpl2mod += par->next_line;
  1365. if (IS_AGA && (par->fmode & FMODE_BSCAN2))
  1366. par->bpl1mod = -div8(fsize>>clk_shift);
  1367. else
  1368. par->bpl1mod = par->bpl2mod;
  1369. if (par->yoffset) {
  1370. par->bplpt0 = info->fix.smem_start +
  1371. par->next_line * par->yoffset + move;
  1372. if (par->vmode & FB_VMODE_YWRAP) {
  1373. if (par->yoffset > par->vyres - par->yres) {
  1374. par->bplpt0wrap = info->fix.smem_start + move;
  1375. if (par->bplcon0 & BPC0_LACE &&
  1376. mod2(par->diwstrt_v + par->vyres -
  1377. par->yoffset))
  1378. par->bplpt0wrap += par->next_line;
  1379. }
  1380. }
  1381. } else
  1382. par->bplpt0 = info->fix.smem_start + move;
  1383. if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
  1384. par->bplpt0 += par->next_line;
  1385. }
  1386. /*
  1387. * Pan or Wrap the Display
  1388. *
  1389. * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  1390. * in `var'.
  1391. */
  1392. static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
  1393. {
  1394. struct amifb_par *par = info->par;
  1395. par->xoffset = var->xoffset;
  1396. par->yoffset = var->yoffset;
  1397. if (var->vmode & FB_VMODE_YWRAP)
  1398. par->vmode |= FB_VMODE_YWRAP;
  1399. else
  1400. par->vmode &= ~FB_VMODE_YWRAP;
  1401. do_vmode_pan = 0;
  1402. ami_update_par(info);
  1403. do_vmode_pan = 1;
  1404. }
  1405. static void ami_update_display(const struct amifb_par *par)
  1406. {
  1407. custom.bplcon1 = par->bplcon1;
  1408. custom.bpl1mod = par->bpl1mod;
  1409. custom.bpl2mod = par->bpl2mod;
  1410. custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
  1411. custom.ddfstop = ddfstop2hw(par->ddfstop);
  1412. }
  1413. /*
  1414. * Change the video mode (called by VBlank interrupt)
  1415. */
  1416. static void ami_init_display(const struct amifb_par *par)
  1417. {
  1418. int i;
  1419. custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
  1420. custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
  1421. if (!IS_OCS) {
  1422. custom.bplcon3 = par->bplcon3;
  1423. if (IS_AGA)
  1424. custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
  1425. if (par->beamcon0 & BMC0_VARBEAMEN) {
  1426. custom.htotal = htotal2hw(par->htotal);
  1427. custom.hbstrt = hbstrt2hw(par->hbstrt);
  1428. custom.hbstop = hbstop2hw(par->hbstop);
  1429. custom.hsstrt = hsstrt2hw(par->hsstrt);
  1430. custom.hsstop = hsstop2hw(par->hsstop);
  1431. custom.hcenter = hcenter2hw(par->hcenter);
  1432. custom.vtotal = vtotal2hw(par->vtotal);
  1433. custom.vbstrt = vbstrt2hw(par->vbstrt);
  1434. custom.vbstop = vbstop2hw(par->vbstop);
  1435. custom.vsstrt = vsstrt2hw(par->vsstrt);
  1436. custom.vsstop = vsstop2hw(par->vsstop);
  1437. }
  1438. }
  1439. if (!IS_OCS || par->hsstop)
  1440. custom.beamcon0 = par->beamcon0;
  1441. if (IS_AGA)
  1442. custom.fmode = par->fmode;
  1443. /*
  1444. * The minimum period for audio depends on htotal
  1445. */
  1446. amiga_audio_min_period = div16(par->htotal);
  1447. is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
  1448. #if 1
  1449. if (is_lace) {
  1450. i = custom.vposr >> 15;
  1451. } else {
  1452. custom.vposw = custom.vposr | 0x8000;
  1453. i = 1;
  1454. }
  1455. #else
  1456. i = 1;
  1457. custom.vposw = custom.vposr | 0x8000;
  1458. #endif
  1459. custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
  1460. }
  1461. /*
  1462. * (Un)Blank the screen (called by VBlank interrupt)
  1463. */
  1464. static void ami_do_blank(const struct amifb_par *par)
  1465. {
  1466. #if defined(CONFIG_FB_AMIGA_AGA)
  1467. u_short bplcon3 = par->bplcon3;
  1468. #endif
  1469. u_char red, green, blue;
  1470. if (do_blank > 0) {
  1471. custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
  1472. red = green = blue = 0;
  1473. if (!IS_OCS && do_blank > 1) {
  1474. switch (do_blank) {
  1475. case FB_BLANK_VSYNC_SUSPEND:
  1476. custom.hsstrt = hsstrt2hw(par->hsstrt);
  1477. custom.hsstop = hsstop2hw(par->hsstop);
  1478. custom.vsstrt = vsstrt2hw(par->vtotal + 4);
  1479. custom.vsstop = vsstop2hw(par->vtotal + 4);
  1480. break;
  1481. case FB_BLANK_HSYNC_SUSPEND:
  1482. custom.hsstrt = hsstrt2hw(par->htotal + 16);
  1483. custom.hsstop = hsstop2hw(par->htotal + 16);
  1484. custom.vsstrt = vsstrt2hw(par->vsstrt);
  1485. custom.vsstop = vsstrt2hw(par->vsstop);
  1486. break;
  1487. case FB_BLANK_POWERDOWN:
  1488. custom.hsstrt = hsstrt2hw(par->htotal + 16);
  1489. custom.hsstop = hsstop2hw(par->htotal + 16);
  1490. custom.vsstrt = vsstrt2hw(par->vtotal + 4);
  1491. custom.vsstop = vsstop2hw(par->vtotal + 4);
  1492. break;
  1493. }
  1494. if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
  1495. custom.htotal = htotal2hw(par->htotal);
  1496. custom.vtotal = vtotal2hw(par->vtotal);
  1497. custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
  1498. BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
  1499. }
  1500. }
  1501. } else {
  1502. custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
  1503. red = red0;
  1504. green = green0;
  1505. blue = blue0;
  1506. if (!IS_OCS) {
  1507. custom.hsstrt = hsstrt2hw(par->hsstrt);
  1508. custom.hsstop = hsstop2hw(par->hsstop);
  1509. custom.vsstrt = vsstrt2hw(par->vsstrt);
  1510. custom.vsstop = vsstop2hw(par->vsstop);
  1511. custom.beamcon0 = par->beamcon0;
  1512. }
  1513. }
  1514. #if defined(CONFIG_FB_AMIGA_AGA)
  1515. if (IS_AGA) {
  1516. custom.bplcon3 = bplcon3;
  1517. custom.color[0] = rgb2hw8_high(red, green, blue);
  1518. custom.bplcon3 = bplcon3 | BPC3_LOCT;
  1519. custom.color[0] = rgb2hw8_low(red, green, blue);
  1520. custom.bplcon3 = bplcon3;
  1521. } else
  1522. #endif
  1523. #if defined(CONFIG_FB_AMIGA_ECS)
  1524. if (par->bplcon0 & BPC0_SHRES) {
  1525. u_short color, mask;
  1526. int i;
  1527. mask = 0x3333;
  1528. color = rgb2hw2(red, green, blue);
  1529. for (i = 12; i >= 0; i -= 4)
  1530. custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
  1531. mask <<= 2; color >>= 2;
  1532. for (i = 3; i >= 0; i--)
  1533. custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
  1534. } else
  1535. #endif
  1536. custom.color[0] = rgb2hw4(red, green, blue);
  1537. is_blanked = do_blank > 0 ? do_blank : 0;
  1538. }
  1539. static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
  1540. const struct amifb_par *par)
  1541. {
  1542. fix->crsr_width = fix->crsr_xsize = par->crsr.width;
  1543. fix->crsr_height = fix->crsr_ysize = par->crsr.height;
  1544. fix->crsr_color1 = 17;
  1545. fix->crsr_color2 = 18;
  1546. return 0;
  1547. }
  1548. static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
  1549. u_char __user *data,
  1550. const struct amifb_par *par)
  1551. {
  1552. register u_short *lspr, *sspr;
  1553. #ifdef __mc68000__
  1554. register u_long datawords asm ("d2");
  1555. #else
  1556. register u_long datawords;
  1557. #endif
  1558. register short delta;
  1559. register u_char color;
  1560. short height, width, bits, words;
  1561. int size, alloc;
  1562. size = par->crsr.height * par->crsr.width;
  1563. alloc = var->height * var->width;
  1564. var->height = par->crsr.height;
  1565. var->width = par->crsr.width;
  1566. var->xspot = par->crsr.spot_x;
  1567. var->yspot = par->crsr.spot_y;
  1568. if (size > var->height * var->width)
  1569. return -ENAMETOOLONG;
  1570. if (!access_ok(VERIFY_WRITE, data, size))
  1571. return -EFAULT;
  1572. delta = 1 << par->crsr.fmode;
  1573. lspr = lofsprite + (delta << 1);
  1574. if (par->bplcon0 & BPC0_LACE)
  1575. sspr = shfsprite + (delta << 1);
  1576. else
  1577. sspr = NULL;
  1578. for (height = (short)var->height - 1; height >= 0; height--) {
  1579. bits = 0; words = delta; datawords = 0;
  1580. for (width = (short)var->width - 1; width >= 0; width--) {
  1581. if (bits == 0) {
  1582. bits = 16; --words;
  1583. #ifdef __mc68000__
  1584. asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
  1585. : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
  1586. #else
  1587. datawords = (*(lspr + delta) << 16) | (*lspr++);
  1588. #endif
  1589. }
  1590. --bits;
  1591. #ifdef __mc68000__
  1592. asm volatile (
  1593. "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
  1594. "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
  1595. : "=d" (color), "=d" (datawords) : "1" (datawords));
  1596. #else
  1597. color = (((datawords >> 30) & 2)
  1598. | ((datawords >> 15) & 1));
  1599. datawords <<= 1;
  1600. #endif
  1601. put_user(color, data++);
  1602. }
  1603. if (bits > 0) {
  1604. --words; ++lspr;
  1605. }
  1606. while (--words >= 0)
  1607. ++lspr;
  1608. #ifdef __mc68000__
  1609. asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
  1610. : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
  1611. #else
  1612. lspr += delta;
  1613. if (sspr) {
  1614. u_short *tmp = lspr;
  1615. lspr = sspr;
  1616. sspr = tmp;
  1617. }
  1618. #endif
  1619. }
  1620. return 0;
  1621. }
  1622. static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
  1623. u_char __user *data, struct amifb_par *par)
  1624. {
  1625. register u_short *lspr, *sspr;
  1626. #ifdef __mc68000__
  1627. register u_long datawords asm ("d2");
  1628. #else
  1629. register u_long datawords;
  1630. #endif
  1631. register short delta;
  1632. u_short fmode;
  1633. short height, width, bits, words;
  1634. if (!var->width)
  1635. return -EINVAL;
  1636. else if (var->width <= 16)
  1637. fmode = TAG_FMODE_1;
  1638. else if (var->width <= 32)
  1639. fmode = TAG_FMODE_2;
  1640. else if (var->width <= 64)
  1641. fmode = TAG_FMODE_4;
  1642. else
  1643. return -EINVAL;
  1644. if (fmode > maxfmode)
  1645. return -EINVAL;
  1646. if (!var->height)
  1647. return -EINVAL;
  1648. if (!access_ok(VERIFY_READ, data, var->width * var->height))
  1649. return -EFAULT;
  1650. delta = 1 << fmode;
  1651. lofsprite = shfsprite = (u_short *)spritememory;
  1652. lspr = lofsprite + (delta << 1);
  1653. if (par->bplcon0 & BPC0_LACE) {
  1654. if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
  1655. return -EINVAL;
  1656. memset(lspr, 0, (var->height + 4) << fmode << 2);
  1657. shfsprite += ((var->height + 5)&-2) << fmode;
  1658. sspr = shfsprite + (delta << 1);
  1659. } else {
  1660. if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
  1661. return -EINVAL;
  1662. memset(lspr, 0, (var->height + 2) << fmode << 2);
  1663. sspr = NULL;
  1664. }
  1665. for (height = (short)var->height - 1; height >= 0; height--) {
  1666. bits = 16; words = delta; datawords = 0;
  1667. for (width = (short)var->width - 1; width >= 0; width--) {
  1668. unsigned long tdata = 0;
  1669. get_user(tdata, data);
  1670. data++;
  1671. #ifdef __mc68000__
  1672. asm volatile (
  1673. "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
  1674. "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
  1675. : "=d" (datawords)
  1676. : "0" (datawords), "d" (tdata));
  1677. #else
  1678. datawords = ((datawords << 1) & 0xfffefffe);
  1679. datawords |= tdata & 1;
  1680. datawords |= (tdata & 2) << (16 - 1);
  1681. #endif
  1682. if (--bits == 0) {
  1683. bits = 16; --words;
  1684. #ifdef __mc68000__
  1685. asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
  1686. : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
  1687. #else
  1688. *(lspr + delta) = (u_short) (datawords >> 16);
  1689. *lspr++ = (u_short) (datawords & 0xffff);
  1690. #endif
  1691. }
  1692. }
  1693. if (bits < 16) {
  1694. --words;
  1695. #ifdef __mc68000__
  1696. asm volatile (
  1697. "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
  1698. "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
  1699. : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
  1700. #else
  1701. *(lspr + delta) = (u_short) (datawords >> (16 + bits));
  1702. *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
  1703. #endif
  1704. }
  1705. while (--words >= 0) {
  1706. #ifdef __mc68000__
  1707. asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
  1708. : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
  1709. #else
  1710. *(lspr + delta) = 0;
  1711. *lspr++ = 0;
  1712. #endif
  1713. }
  1714. #ifdef __mc68000__
  1715. asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
  1716. : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
  1717. #else
  1718. lspr += delta;
  1719. if (sspr) {
  1720. u_short *tmp = lspr;
  1721. lspr = sspr;
  1722. sspr = tmp;
  1723. }
  1724. #endif
  1725. }
  1726. par->crsr.height = var->height;
  1727. par->crsr.width = var->width;
  1728. par->crsr.spot_x = var->xspot;
  1729. par->crsr.spot_y = var->yspot;
  1730. par->crsr.fmode = fmode;
  1731. if (IS_AGA) {
  1732. par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
  1733. par->fmode |= sprfetchmode[fmode];
  1734. custom.fmode = par->fmode;
  1735. }
  1736. return 0;
  1737. }
  1738. static int ami_get_cursorstate(struct fb_cursorstate *state,
  1739. const struct amifb_par *par)
  1740. {
  1741. state->xoffset = par->crsr.crsr_x;
  1742. state->yoffset = par->crsr.crsr_y;
  1743. state->mode = cursormode;
  1744. return 0;
  1745. }
  1746. static int ami_set_cursorstate(struct fb_cursorstate *state,
  1747. struct amifb_par *par)
  1748. {
  1749. par->crsr.crsr_x = state->xoffset;
  1750. par->crsr.crsr_y = state->yoffset;
  1751. if ((cursormode = state->mode) == FB_CURSOR_OFF)
  1752. cursorstate = -1;
  1753. do_cursor = 1;
  1754. return 0;
  1755. }
  1756. static void ami_set_sprite(const struct amifb_par *par)
  1757. {
  1758. copins *copl, *cops;
  1759. u_short hs, vs, ve;
  1760. u_long pl, ps, pt;
  1761. short mx, my;
  1762. cops = copdisplay.list[currentcop][0];
  1763. copl = copdisplay.list[currentcop][1];
  1764. ps = pl = ZTWO_PADDR(dummysprite);
  1765. mx = par->crsr.crsr_x - par->crsr.spot_x;
  1766. my = par->crsr.crsr_y - par->crsr.spot_y;
  1767. if (!(par->vmode & FB_VMODE_YWRAP)) {
  1768. mx -= par->xoffset;
  1769. my -= par->yoffset;
  1770. }
  1771. if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
  1772. mx > -(short)par->crsr.width && mx < par->xres &&
  1773. my > -(short)par->crsr.height && my < par->yres) {
  1774. pl = ZTWO_PADDR(lofsprite);
  1775. hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
  1776. vs = par->diwstrt_v + (my << par->line_shift);
  1777. ve = vs + (par->crsr.height << par->line_shift);
  1778. if (par->bplcon0 & BPC0_LACE) {
  1779. ps = ZTWO_PADDR(shfsprite);
  1780. lofsprite[0] = spr2hw_pos(vs, hs);
  1781. shfsprite[0] = spr2hw_pos(vs + 1, hs);
  1782. if (mod2(vs)) {
  1783. lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
  1784. shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
  1785. pt = pl; pl = ps; ps = pt;
  1786. } else {
  1787. lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
  1788. shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
  1789. }
  1790. } else {
  1791. lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
  1792. lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
  1793. }
  1794. }
  1795. copl[cop_spr0ptrh].w[1] = highw(pl);
  1796. copl[cop_spr0ptrl].w[1] = loww(pl);
  1797. if (par->bplcon0 & BPC0_LACE) {
  1798. cops[cop_spr0ptrh].w[1] = highw(ps);
  1799. cops[cop_spr0ptrl].w[1] = loww(ps);
  1800. }
  1801. }
  1802. /*
  1803. * Initialise the Copper Initialisation List
  1804. */
  1805. static void __init ami_init_copper(void)
  1806. {
  1807. copins *cop = copdisplay.init;
  1808. u_long p;
  1809. int i;
  1810. if (!IS_OCS) {
  1811. (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
  1812. (cop++)->l = CMOVE(0x0181, diwstrt);
  1813. (cop++)->l = CMOVE(0x0281, diwstop);
  1814. (cop++)->l = CMOVE(0x0000, diwhigh);
  1815. } else
  1816. (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
  1817. p = ZTWO_PADDR(dummysprite);
  1818. for (i = 0; i < 8; i++) {
  1819. (cop++)->l = CMOVE(0, spr[i].pos);
  1820. (cop++)->l = CMOVE(highw(p), sprpt[i]);
  1821. (cop++)->l = CMOVE2(loww(p), sprpt[i]);
  1822. }
  1823. (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
  1824. copdisplay.wait = cop;
  1825. (cop++)->l = CEND;
  1826. (cop++)->l = CMOVE(0, copjmp2);
  1827. cop->l = CEND;
  1828. custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
  1829. custom.copjmp1 = 0;
  1830. }
  1831. static void ami_reinit_copper(const struct amifb_par *par)
  1832. {
  1833. copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
  1834. copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
  1835. }
  1836. /*
  1837. * Rebuild the Copper List
  1838. *
  1839. * We only change the things that are not static
  1840. */
  1841. static void ami_rebuild_copper(const struct amifb_par *par)
  1842. {
  1843. copins *copl, *cops;
  1844. u_short line, h_end1, h_end2;
  1845. short i;
  1846. u_long p;
  1847. if (IS_AGA && maxfmode + par->clk_shift == 0)
  1848. h_end1 = par->diwstrt_h - 64;
  1849. else
  1850. h_end1 = par->htotal - 32;
  1851. h_end2 = par->ddfstop + 64;
  1852. ami_set_sprite(par);
  1853. copl = copdisplay.rebuild[1];
  1854. p = par->bplpt0;
  1855. if (par->vmode & FB_VMODE_YWRAP) {
  1856. if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
  1857. if (par->yoffset > par->vyres - par->yres) {
  1858. for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
  1859. (copl++)->l = CMOVE(highw(p), bplpt[i]);
  1860. (copl++)->l = CMOVE2(loww(p), bplpt[i]);
  1861. }
  1862. line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
  1863. while (line >= 512) {
  1864. (copl++)->l = CWAIT(h_end1, 510);
  1865. line -= 512;
  1866. }
  1867. if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
  1868. (copl++)->l = CWAIT(h_end1, line);
  1869. else
  1870. (copl++)->l = CWAIT(h_end2, line);
  1871. p = par->bplpt0wrap;
  1872. }
  1873. } else
  1874. p = par->bplpt0wrap;
  1875. }
  1876. for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
  1877. (copl++)->l = CMOVE(highw(p), bplpt[i]);
  1878. (copl++)->l = CMOVE2(loww(p), bplpt[i]);
  1879. }
  1880. copl->l = CEND;
  1881. if (par->bplcon0 & BPC0_LACE) {
  1882. cops = copdisplay.rebuild[0];
  1883. p = par->bplpt0;
  1884. if (mod2(par->diwstrt_v))
  1885. p -= par->next_line;
  1886. else
  1887. p += par->next_line;
  1888. if (par->vmode & FB_VMODE_YWRAP) {
  1889. if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
  1890. if (par->yoffset > par->vyres - par->yres + 1) {
  1891. for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
  1892. (cops++)->l = CMOVE(highw(p), bplpt[i]);
  1893. (cops++)->l = CMOVE2(loww(p), bplpt[i]);
  1894. }
  1895. line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
  1896. while (line >= 512) {
  1897. (cops++)->l = CWAIT(h_end1, 510);
  1898. line -= 512;
  1899. }
  1900. if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
  1901. (cops++)->l = CWAIT(h_end1, line);
  1902. else
  1903. (cops++)->l = CWAIT(h_end2, line);
  1904. p = par->bplpt0wrap;
  1905. if (mod2(par->diwstrt_v + par->vyres -
  1906. par->yoffset))
  1907. p -= par->next_line;
  1908. else
  1909. p += par->next_line;
  1910. }
  1911. } else
  1912. p = par->bplpt0wrap - par->next_line;
  1913. }
  1914. for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
  1915. (cops++)->l = CMOVE(highw(p), bplpt[i]);
  1916. (cops++)->l = CMOVE2(loww(p), bplpt[i]);
  1917. }
  1918. cops->l = CEND;
  1919. }
  1920. }
  1921. /*
  1922. * Build the Copper List
  1923. */
  1924. static void ami_build_copper(struct fb_info *info)
  1925. {
  1926. struct amifb_par *par = info->par;
  1927. copins *copl, *cops;
  1928. u_long p;
  1929. currentcop = 1 - currentcop;
  1930. copl = copdisplay.list[currentcop][1];
  1931. (copl++)->l = CWAIT(0, 10);
  1932. (copl++)->l = CMOVE(par->bplcon0, bplcon0);
  1933. (copl++)->l = CMOVE(0, sprpt[0]);
  1934. (copl++)->l = CMOVE2(0, sprpt[0]);
  1935. if (par->bplcon0 & BPC0_LACE) {
  1936. cops = copdisplay.list[currentcop][0];
  1937. (cops++)->l = CWAIT(0, 10);
  1938. (cops++)->l = CMOVE(par->bplcon0, bplcon0);
  1939. (cops++)->l = CMOVE(0, sprpt[0]);
  1940. (cops++)->l = CMOVE2(0, sprpt[0]);
  1941. (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
  1942. (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
  1943. (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
  1944. (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
  1945. if (!IS_OCS) {
  1946. (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
  1947. par->diwstop_h, par->diwstop_v + 1), diwhigh);
  1948. (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
  1949. par->diwstop_h, par->diwstop_v), diwhigh);
  1950. #if 0
  1951. if (par->beamcon0 & BMC0_VARBEAMEN) {
  1952. (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
  1953. (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
  1954. (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
  1955. (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
  1956. (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
  1957. (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
  1958. }
  1959. #endif
  1960. }
  1961. p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
  1962. (copl++)->l = CMOVE(highw(p), cop2lc);
  1963. (copl++)->l = CMOVE2(loww(p), cop2lc);
  1964. p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
  1965. (cops++)->l = CMOVE(highw(p), cop2lc);
  1966. (cops++)->l = CMOVE2(loww(p), cop2lc);
  1967. copdisplay.rebuild[0] = cops;
  1968. } else {
  1969. (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
  1970. (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
  1971. if (!IS_OCS) {
  1972. (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
  1973. par->diwstop_h, par->diwstop_v), diwhigh);
  1974. #if 0
  1975. if (par->beamcon0 & BMC0_VARBEAMEN) {
  1976. (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
  1977. (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
  1978. (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
  1979. }
  1980. #endif
  1981. }
  1982. }
  1983. copdisplay.rebuild[1] = copl;
  1984. ami_update_par(info);
  1985. ami_rebuild_copper(info->par);
  1986. }
  1987. static void __init amifb_setup_mcap(char *spec)
  1988. {
  1989. char *p;
  1990. int vmin, vmax, hmin, hmax;
  1991. /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
  1992. * <V*> vertical freq. in Hz
  1993. * <H*> horizontal freq. in kHz
  1994. */
  1995. if (!(p = strsep(&spec, ";")) || !*p)
  1996. return;
  1997. vmin = simple_strtoul(p, NULL, 10);
  1998. if (vmin <= 0)
  1999. return;
  2000. if (!(p = strsep(&spec, ";")) || !*p)
  2001. return;
  2002. vmax = simple_strtoul(p, NULL, 10);
  2003. if (vmax <= 0 || vmax <= vmin)
  2004. return;
  2005. if (!(p = strsep(&spec, ";")) || !*p)
  2006. return;
  2007. hmin = 1000 * simple_strtoul(p, NULL, 10);
  2008. if (hmin <= 0)
  2009. return;
  2010. if (!(p = strsep(&spec, "")) || !*p)
  2011. return;
  2012. hmax = 1000 * simple_strtoul(p, NULL, 10);
  2013. if (hmax <= 0 || hmax <= hmin)
  2014. return;
  2015. amifb_hfmin = hmin;
  2016. amifb_hfmax = hmax;
  2017. amifb_vfmin = vmin;
  2018. amifb_vfmax = vmax;
  2019. }
  2020. static int __init amifb_setup(char *options)
  2021. {
  2022. char *this_opt;
  2023. if (!options || !*options)
  2024. return 0;
  2025. while ((this_opt = strsep(&options, ",")) != NULL) {
  2026. if (!*this_opt)
  2027. continue;
  2028. if (!strcmp(this_opt, "inverse")) {
  2029. amifb_inverse = 1;
  2030. fb_invert_cmaps();
  2031. } else if (!strcmp(this_opt, "ilbm"))
  2032. amifb_ilbm = 1;
  2033. else if (!strncmp(this_opt, "monitorcap:", 11))
  2034. amifb_setup_mcap(this_opt + 11);
  2035. else if (!strncmp(this_opt, "fstart:", 7))
  2036. min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
  2037. else
  2038. mode_option = this_opt;
  2039. }
  2040. if (min_fstrt < 48)
  2041. min_fstrt = 48;
  2042. return 0;
  2043. }
  2044. static int amifb_check_var(struct fb_var_screeninfo *var,
  2045. struct fb_info *info)
  2046. {
  2047. int err;
  2048. struct amifb_par par;
  2049. /* Validate wanted screen parameters */
  2050. err = ami_decode_var(var, &par, info);
  2051. if (err)
  2052. return err;
  2053. /* Encode (possibly rounded) screen parameters */
  2054. ami_encode_var(var, &par);
  2055. return 0;
  2056. }
  2057. static int amifb_set_par(struct fb_info *info)
  2058. {
  2059. struct amifb_par *par = info->par;
  2060. int error;
  2061. do_vmode_pan = 0;
  2062. do_vmode_full = 0;
  2063. /* Decode wanted screen parameters */
  2064. error = ami_decode_var(&info->var, par, info);
  2065. if (error)
  2066. return error;
  2067. /* Set new videomode */
  2068. ami_build_copper(info);
  2069. /* Set VBlank trigger */
  2070. do_vmode_full = 1;
  2071. /* Update fix for new screen parameters */
  2072. if (par->bpp == 1) {
  2073. info->fix.type = FB_TYPE_PACKED_PIXELS;
  2074. info->fix.type_aux = 0;
  2075. } else if (amifb_ilbm) {
  2076. info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
  2077. info->fix.type_aux = par->next_line;
  2078. } else {
  2079. info->fix.type = FB_TYPE_PLANES;
  2080. info->fix.type_aux = 0;
  2081. }
  2082. info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
  2083. if (par->vmode & FB_VMODE_YWRAP) {
  2084. info->fix.ywrapstep = 1;
  2085. info->fix.xpanstep = 0;
  2086. info->fix.ypanstep = 0;
  2087. info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
  2088. FBINFO_READS_FAST; /* override SCROLL_REDRAW */
  2089. } else {
  2090. info->fix.ywrapstep = 0;
  2091. if (par->vmode & FB_VMODE_SMOOTH_XPAN)
  2092. info->fix.xpanstep = 1;
  2093. else
  2094. info->fix.xpanstep = 16 << maxfmode;
  2095. info->fix.ypanstep = 1;
  2096. info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
  2097. }
  2098. return 0;
  2099. }
  2100. /*
  2101. * Set a single color register. The values supplied are already
  2102. * rounded down to the hardware's capabilities (according to the
  2103. * entries in the var structure). Return != 0 for invalid regno.
  2104. */
  2105. static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  2106. u_int transp, struct fb_info *info)
  2107. {
  2108. const struct amifb_par *par = info->par;
  2109. if (IS_AGA) {
  2110. if (regno > 255)
  2111. return 1;
  2112. } else if (par->bplcon0 & BPC0_SHRES) {
  2113. if (regno > 3)
  2114. return 1;
  2115. } else {
  2116. if (regno > 31)
  2117. return 1;
  2118. }
  2119. red >>= 8;
  2120. green >>= 8;
  2121. blue >>= 8;
  2122. if (!regno) {
  2123. red0 = red;
  2124. green0 = green;
  2125. blue0 = blue;
  2126. }
  2127. /*
  2128. * Update the corresponding Hardware Color Register, unless it's Color
  2129. * Register 0 and the screen is blanked.
  2130. *
  2131. * VBlank is switched off to protect bplcon3 or ecs_palette[] from
  2132. * being changed by ami_do_blank() during the VBlank.
  2133. */
  2134. if (regno || !is_blanked) {
  2135. #if defined(CONFIG_FB_AMIGA_AGA)
  2136. if (IS_AGA) {
  2137. u_short bplcon3 = par->bplcon3;
  2138. VBlankOff();
  2139. custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
  2140. custom.color[regno & 31] = rgb2hw8_high(red, green,
  2141. blue);
  2142. custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
  2143. BPC3_LOCT;
  2144. custom.color[regno & 31] = rgb2hw8_low(red, green,
  2145. blue);
  2146. custom.bplcon3 = bplcon3;
  2147. VBlankOn();
  2148. } else
  2149. #endif
  2150. #if defined(CONFIG_FB_AMIGA_ECS)
  2151. if (par->bplcon0 & BPC0_SHRES) {
  2152. u_short color, mask;
  2153. int i;
  2154. mask = 0x3333;
  2155. color = rgb2hw2(red, green, blue);
  2156. VBlankOff();
  2157. for (i = regno + 12; i >= (int)regno; i -= 4)
  2158. custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
  2159. mask <<= 2; color >>= 2;
  2160. regno = down16(regno) + mul4(mod4(regno));
  2161. for (i = regno + 3; i >= (int)regno; i--)
  2162. custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
  2163. VBlankOn();
  2164. } else
  2165. #endif
  2166. custom.color[regno] = rgb2hw4(red, green, blue);
  2167. }
  2168. return 0;
  2169. }
  2170. /*
  2171. * Blank the display.
  2172. */
  2173. static int amifb_blank(int blank, struct fb_info *info)
  2174. {
  2175. do_blank = blank ? blank : -1;
  2176. return 0;
  2177. }
  2178. /*
  2179. * Pan or Wrap the Display
  2180. *
  2181. * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  2182. */
  2183. static int amifb_pan_display(struct fb_var_screeninfo *var,
  2184. struct fb_info *info)
  2185. {
  2186. if (var->vmode & FB_VMODE_YWRAP) {
  2187. if (var->yoffset < 0 ||
  2188. var->yoffset >= info->var.yres_virtual || var->xoffset)
  2189. return -EINVAL;
  2190. } else {
  2191. /*
  2192. * TODO: There will be problems when xpan!=1, so some columns
  2193. * on the right side will never be seen
  2194. */
  2195. if (var->xoffset + info->var.xres >
  2196. upx(16 << maxfmode, info->var.xres_virtual) ||
  2197. var->yoffset + info->var.yres > info->var.yres_virtual)
  2198. return -EINVAL;
  2199. }
  2200. ami_pan_var(var, info);
  2201. info->var.xoffset = var->xoffset;
  2202. info->var.yoffset = var->yoffset;
  2203. if (var->vmode & FB_VMODE_YWRAP)
  2204. info->var.vmode |= FB_VMODE_YWRAP;
  2205. else
  2206. info->var.vmode &= ~FB_VMODE_YWRAP;
  2207. return 0;
  2208. }
  2209. #if BITS_PER_LONG == 32
  2210. #define BYTES_PER_LONG 4
  2211. #define SHIFT_PER_LONG 5
  2212. #elif BITS_PER_LONG == 64
  2213. #define BYTES_PER_LONG 8
  2214. #define SHIFT_PER_LONG 6
  2215. #else
  2216. #define Please update me
  2217. #endif
  2218. /*
  2219. * Compose two values, using a bitmask as decision value
  2220. * This is equivalent to (a & mask) | (b & ~mask)
  2221. */
  2222. static inline unsigned long comp(unsigned long a, unsigned long b,
  2223. unsigned long mask)
  2224. {
  2225. return ((a ^ b) & mask) ^ b;
  2226. }
  2227. static inline unsigned long xor(unsigned long a, unsigned long b,
  2228. unsigned long mask)
  2229. {
  2230. return (a & mask) ^ b;
  2231. }
  2232. /*
  2233. * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
  2234. */
  2235. static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
  2236. int src_idx, u32 n)
  2237. {
  2238. unsigned long first, last;
  2239. int shift = dst_idx - src_idx, left, right;
  2240. unsigned long d0, d1;
  2241. int m;
  2242. if (!n)
  2243. return;
  2244. shift = dst_idx - src_idx;
  2245. first = ~0UL >> dst_idx;
  2246. last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
  2247. if (!shift) {
  2248. // Same alignment for source and dest
  2249. if (dst_idx + n <= BITS_PER_LONG) {
  2250. // Single word
  2251. if (last)
  2252. first &= last;
  2253. *dst = comp(*src, *dst, first);
  2254. } else {
  2255. // Multiple destination words
  2256. // Leading bits
  2257. if (first) {
  2258. *dst = comp(*src, *dst, first);
  2259. dst++;
  2260. src++;
  2261. n -= BITS_PER_LONG - dst_idx;
  2262. }
  2263. // Main chunk
  2264. n /= BITS_PER_LONG;
  2265. while (n >= 8) {
  2266. *dst++ = *src++;
  2267. *dst++ = *src++;
  2268. *dst++ = *src++;
  2269. *dst++ = *src++;
  2270. *dst++ = *src++;
  2271. *dst++ = *src++;
  2272. *dst++ = *src++;
  2273. *dst++ = *src++;
  2274. n -= 8;
  2275. }
  2276. while (n--)
  2277. *dst++ = *src++;
  2278. // Trailing bits
  2279. if (last)
  2280. *dst = comp(*src, *dst, last);
  2281. }
  2282. } else {
  2283. // Different alignment for source and dest
  2284. right = shift & (BITS_PER_LONG - 1);
  2285. left = -shift & (BITS_PER_LONG - 1);
  2286. if (dst_idx + n <= BITS_PER_LONG) {
  2287. // Single destination word
  2288. if (last)
  2289. first &= last;
  2290. if (shift > 0) {
  2291. // Single source word
  2292. *dst = comp(*src >> right, *dst, first);
  2293. } else if (src_idx + n <= BITS_PER_LONG) {
  2294. // Single source word
  2295. *dst = comp(*src << left, *dst, first);
  2296. } else {
  2297. // 2 source words
  2298. d0 = *src++;
  2299. d1 = *src;
  2300. *dst = comp(d0 << left | d1 >> right, *dst,
  2301. first);
  2302. }
  2303. } else {
  2304. // Multiple destination words
  2305. d0 = *src++;
  2306. // Leading bits
  2307. if (shift > 0) {
  2308. // Single source word
  2309. *dst = comp(d0 >> right, *dst, first);
  2310. dst++;
  2311. n -= BITS_PER_LONG - dst_idx;
  2312. } else {
  2313. // 2 source words
  2314. d1 = *src++;
  2315. *dst = comp(d0 << left | d1 >> right, *dst,
  2316. first);
  2317. d0 = d1;
  2318. dst++;
  2319. n -= BITS_PER_LONG - dst_idx;
  2320. }
  2321. // Main chunk
  2322. m = n % BITS_PER_LONG;
  2323. n /= BITS_PER_LONG;
  2324. while (n >= 4) {
  2325. d1 = *src++;
  2326. *dst++ = d0 << left | d1 >> right;
  2327. d0 = d1;
  2328. d1 = *src++;
  2329. *dst++ = d0 << left | d1 >> right;
  2330. d0 = d1;
  2331. d1 = *src++;
  2332. *dst++ = d0 << left | d1 >> right;
  2333. d0 = d1;
  2334. d1 = *src++;
  2335. *dst++ = d0 << left | d1 >> right;
  2336. d0 = d1;
  2337. n -= 4;
  2338. }
  2339. while (n--) {
  2340. d1 = *src++;
  2341. *dst++ = d0 << left | d1 >> right;
  2342. d0 = d1;
  2343. }
  2344. // Trailing bits
  2345. if (last) {
  2346. if (m <= right) {
  2347. // Single source word
  2348. *dst = comp(d0 << left, *dst, last);
  2349. } else {
  2350. // 2 source words
  2351. d1 = *src;
  2352. *dst = comp(d0 << left | d1 >> right,
  2353. *dst, last);
  2354. }
  2355. }
  2356. }
  2357. }
  2358. }
  2359. /*
  2360. * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
  2361. */
  2362. static void bitcpy_rev(unsigned long *dst, int dst_idx,
  2363. const unsigned long *src, int src_idx, u32 n)
  2364. {
  2365. unsigned long first, last;
  2366. int shift = dst_idx - src_idx, left, right;
  2367. unsigned long d0, d1;
  2368. int m;
  2369. if (!n)
  2370. return;
  2371. dst += (n - 1) / BITS_PER_LONG;
  2372. src += (n - 1) / BITS_PER_LONG;
  2373. if ((n - 1) % BITS_PER_LONG) {
  2374. dst_idx += (n - 1) % BITS_PER_LONG;
  2375. dst += dst_idx >> SHIFT_PER_LONG;
  2376. dst_idx &= BITS_PER_LONG - 1;
  2377. src_idx += (n - 1) % BITS_PER_LONG;
  2378. src += src_idx >> SHIFT_PER_LONG;
  2379. src_idx &= BITS_PER_LONG - 1;
  2380. }
  2381. shift = dst_idx - src_idx;
  2382. first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
  2383. last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
  2384. if (!shift) {
  2385. // Same alignment for source and dest
  2386. if ((unsigned long)dst_idx + 1 >= n) {
  2387. // Single word
  2388. if (last)
  2389. first &= last;
  2390. *dst = comp(*src, *dst, first);
  2391. } else {
  2392. // Multiple destination words
  2393. // Leading bits
  2394. if (first) {
  2395. *dst = comp(*src, *dst, first);
  2396. dst--;
  2397. src--;
  2398. n -= dst_idx + 1;
  2399. }
  2400. // Main chunk
  2401. n /= BITS_PER_LONG;
  2402. while (n >= 8) {
  2403. *dst-- = *src--;
  2404. *dst-- = *src--;
  2405. *dst-- = *src--;
  2406. *dst-- = *src--;
  2407. *dst-- = *src--;
  2408. *dst-- = *src--;
  2409. *dst-- = *src--;
  2410. *dst-- = *src--;
  2411. n -= 8;
  2412. }
  2413. while (n--)
  2414. *dst-- = *src--;
  2415. // Trailing bits
  2416. if (last)
  2417. *dst = comp(*src, *dst, last);
  2418. }
  2419. } else {
  2420. // Different alignment for source and dest
  2421. right = shift & (BITS_PER_LONG - 1);
  2422. left = -shift & (BITS_PER_LONG - 1);
  2423. if ((unsigned long)dst_idx + 1 >= n) {
  2424. // Single destination word
  2425. if (last)
  2426. first &= last;
  2427. if (shift < 0) {
  2428. // Single source word
  2429. *dst = comp(*src << left, *dst, first);
  2430. } else if (1 + (unsigned long)src_idx >= n) {
  2431. // Single source word
  2432. *dst = comp(*src >> right, *dst, first);
  2433. } else {
  2434. // 2 source words
  2435. d0 = *src--;
  2436. d1 = *src;
  2437. *dst = comp(d0 >> right | d1 << left, *dst,
  2438. first);
  2439. }
  2440. } else {
  2441. // Multiple destination words
  2442. d0 = *src--;
  2443. // Leading bits
  2444. if (shift < 0) {
  2445. // Single source word
  2446. *dst = comp(d0 << left, *dst, first);
  2447. dst--;
  2448. n -= dst_idx + 1;
  2449. } else {
  2450. // 2 source words
  2451. d1 = *src--;
  2452. *dst = comp(d0 >> right | d1 << left, *dst,
  2453. first);
  2454. d0 = d1;
  2455. dst--;
  2456. n -= dst_idx + 1;
  2457. }
  2458. // Main chunk
  2459. m = n % BITS_PER_LONG;
  2460. n /= BITS_PER_LONG;
  2461. while (n >= 4) {
  2462. d1 = *src--;
  2463. *dst-- = d0 >> right | d1 << left;
  2464. d0 = d1;
  2465. d1 = *src--;
  2466. *dst-- = d0 >> right | d1 << left;
  2467. d0 = d1;
  2468. d1 = *src--;
  2469. *dst-- = d0 >> right | d1 << left;
  2470. d0 = d1;
  2471. d1 = *src--;
  2472. *dst-- = d0 >> right | d1 << left;
  2473. d0 = d1;
  2474. n -= 4;
  2475. }
  2476. while (n--) {
  2477. d1 = *src--;
  2478. *dst-- = d0 >> right | d1 << left;
  2479. d0 = d1;
  2480. }
  2481. // Trailing bits
  2482. if (last) {
  2483. if (m <= left) {
  2484. // Single source word
  2485. *dst = comp(d0 >> right, *dst, last);
  2486. } else {
  2487. // 2 source words
  2488. d1 = *src;
  2489. *dst = comp(d0 >> right | d1 << left,
  2490. *dst, last);
  2491. }
  2492. }
  2493. }
  2494. }
  2495. }
  2496. /*
  2497. * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
  2498. * accesses
  2499. */
  2500. static void bitcpy_not(unsigned long *dst, int dst_idx,
  2501. const unsigned long *src, int src_idx, u32 n)
  2502. {
  2503. unsigned long first, last;
  2504. int shift = dst_idx - src_idx, left, right;
  2505. unsigned long d0, d1;
  2506. int m;
  2507. if (!n)
  2508. return;
  2509. shift = dst_idx - src_idx;
  2510. first = ~0UL >> dst_idx;
  2511. last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
  2512. if (!shift) {
  2513. // Same alignment for source and dest
  2514. if (dst_idx + n <= BITS_PER_LONG) {
  2515. // Single word
  2516. if (last)
  2517. first &= last;
  2518. *dst = comp(~*src, *dst, first);
  2519. } else {
  2520. // Multiple destination words
  2521. // Leading bits
  2522. if (first) {
  2523. *dst = comp(~*src, *dst, first);
  2524. dst++;
  2525. src++;
  2526. n -= BITS_PER_LONG - dst_idx;
  2527. }
  2528. // Main chunk
  2529. n /= BITS_PER_LONG;
  2530. while (n >= 8) {
  2531. *dst++ = ~*src++;
  2532. *dst++ = ~*src++;
  2533. *dst++ = ~*src++;
  2534. *dst++ = ~*src++;
  2535. *dst++ = ~*src++;
  2536. *dst++ = ~*src++;
  2537. *dst++ = ~*src++;
  2538. *dst++ = ~*src++;
  2539. n -= 8;
  2540. }
  2541. while (n--)
  2542. *dst++ = ~*src++;
  2543. // Trailing bits
  2544. if (last)
  2545. *dst = comp(~*src, *dst, last);
  2546. }
  2547. } else {
  2548. // Different alignment for source and dest
  2549. right = shift & (BITS_PER_LONG - 1);
  2550. left = -shift & (BITS_PER_LONG - 1);
  2551. if (dst_idx + n <= BITS_PER_LONG) {
  2552. // Single destination word
  2553. if (last)
  2554. first &= last;
  2555. if (shift > 0) {
  2556. // Single source word
  2557. *dst = comp(~*src >> right, *dst, first);
  2558. } else if (src_idx + n <= BITS_PER_LONG) {
  2559. // Single source word
  2560. *dst = comp(~*src << left, *dst, first);
  2561. } else {
  2562. // 2 source words
  2563. d0 = ~*src++;
  2564. d1 = ~*src;
  2565. *dst = comp(d0 << left | d1 >> right, *dst,
  2566. first);
  2567. }
  2568. } else {
  2569. // Multiple destination words
  2570. d0 = ~*src++;
  2571. // Leading bits
  2572. if (shift > 0) {
  2573. // Single source word
  2574. *dst = comp(d0 >> right, *dst, first);
  2575. dst++;
  2576. n -= BITS_PER_LONG - dst_idx;
  2577. } else {
  2578. // 2 source words
  2579. d1 = ~*src++;
  2580. *dst = comp(d0 << left | d1 >> right, *dst,
  2581. first);
  2582. d0 = d1;
  2583. dst++;
  2584. n -= BITS_PER_LONG - dst_idx;
  2585. }
  2586. // Main chunk
  2587. m = n % BITS_PER_LONG;
  2588. n /= BITS_PER_LONG;
  2589. while (n >= 4) {
  2590. d1 = ~*src++;
  2591. *dst++ = d0 << left | d1 >> right;
  2592. d0 = d1;
  2593. d1 = ~*src++;
  2594. *dst++ = d0 << left | d1 >> right;
  2595. d0 = d1;
  2596. d1 = ~*src++;
  2597. *dst++ = d0 << left | d1 >> right;
  2598. d0 = d1;
  2599. d1 = ~*src++;
  2600. *dst++ = d0 << left | d1 >> right;
  2601. d0 = d1;
  2602. n -= 4;
  2603. }
  2604. while (n--) {
  2605. d1 = ~*src++;
  2606. *dst++ = d0 << left | d1 >> right;
  2607. d0 = d1;
  2608. }
  2609. // Trailing bits
  2610. if (last) {
  2611. if (m <= right) {
  2612. // Single source word
  2613. *dst = comp(d0 << left, *dst, last);
  2614. } else {
  2615. // 2 source words
  2616. d1 = ~*src;
  2617. *dst = comp(d0 << left | d1 >> right,
  2618. *dst, last);
  2619. }
  2620. }
  2621. }
  2622. }
  2623. }
  2624. /*
  2625. * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
  2626. */
  2627. static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
  2628. {
  2629. unsigned long val = pat;
  2630. unsigned long first, last;
  2631. if (!n)
  2632. return;
  2633. #if BITS_PER_LONG == 64
  2634. val |= val << 32;
  2635. #endif
  2636. first = ~0UL >> dst_idx;
  2637. last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
  2638. if (dst_idx + n <= BITS_PER_LONG) {
  2639. // Single word
  2640. if (last)
  2641. first &= last;
  2642. *dst = comp(val, *dst, first);
  2643. } else {
  2644. // Multiple destination words
  2645. // Leading bits
  2646. if (first) {
  2647. *dst = comp(val, *dst, first);
  2648. dst++;
  2649. n -= BITS_PER_LONG - dst_idx;
  2650. }
  2651. // Main chunk
  2652. n /= BITS_PER_LONG;
  2653. while (n >= 8) {
  2654. *dst++ = val;
  2655. *dst++ = val;
  2656. *dst++ = val;
  2657. *dst++ = val;
  2658. *dst++ = val;
  2659. *dst++ = val;
  2660. *dst++ = val;
  2661. *dst++ = val;
  2662. n -= 8;
  2663. }
  2664. while (n--)
  2665. *dst++ = val;
  2666. // Trailing bits
  2667. if (last)
  2668. *dst = comp(val, *dst, last);
  2669. }
  2670. }
  2671. /*
  2672. * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
  2673. */
  2674. static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
  2675. {
  2676. unsigned long val = pat;
  2677. unsigned long first, last;
  2678. if (!n)
  2679. return;
  2680. #if BITS_PER_LONG == 64
  2681. val |= val << 32;
  2682. #endif
  2683. first = ~0UL >> dst_idx;
  2684. last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
  2685. if (dst_idx + n <= BITS_PER_LONG) {
  2686. // Single word
  2687. if (last)
  2688. first &= last;
  2689. *dst = xor(val, *dst, first);
  2690. } else {
  2691. // Multiple destination words
  2692. // Leading bits
  2693. if (first) {
  2694. *dst = xor(val, *dst, first);
  2695. dst++;
  2696. n -= BITS_PER_LONG - dst_idx;
  2697. }
  2698. // Main chunk
  2699. n /= BITS_PER_LONG;
  2700. while (n >= 4) {
  2701. *dst++ ^= val;
  2702. *dst++ ^= val;
  2703. *dst++ ^= val;
  2704. *dst++ ^= val;
  2705. n -= 4;
  2706. }
  2707. while (n--)
  2708. *dst++ ^= val;
  2709. // Trailing bits
  2710. if (last)
  2711. *dst = xor(val, *dst, last);
  2712. }
  2713. }
  2714. static inline void fill_one_line(int bpp, unsigned long next_plane,
  2715. unsigned long *dst, int dst_idx, u32 n,
  2716. u32 color)
  2717. {
  2718. while (1) {
  2719. dst += dst_idx >> SHIFT_PER_LONG;
  2720. dst_idx &= (BITS_PER_LONG - 1);
  2721. bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
  2722. if (!--bpp)
  2723. break;
  2724. color >>= 1;
  2725. dst_idx += next_plane * 8;
  2726. }
  2727. }
  2728. static inline void xor_one_line(int bpp, unsigned long next_plane,
  2729. unsigned long *dst, int dst_idx, u32 n,
  2730. u32 color)
  2731. {
  2732. while (color) {
  2733. dst += dst_idx >> SHIFT_PER_LONG;
  2734. dst_idx &= (BITS_PER_LONG - 1);
  2735. bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
  2736. if (!--bpp)
  2737. break;
  2738. color >>= 1;
  2739. dst_idx += next_plane * 8;
  2740. }
  2741. }
  2742. static void amifb_fillrect(struct fb_info *info,
  2743. const struct fb_fillrect *rect)
  2744. {
  2745. struct amifb_par *par = info->par;
  2746. int dst_idx, x2, y2;
  2747. unsigned long *dst;
  2748. u32 width, height;
  2749. if (!rect->width || !rect->height)
  2750. return;
  2751. /*
  2752. * We could use hardware clipping but on many cards you get around
  2753. * hardware clipping by writing to framebuffer directly.
  2754. * */
  2755. x2 = rect->dx + rect->width;
  2756. y2 = rect->dy + rect->height;
  2757. x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
  2758. y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
  2759. width = x2 - rect->dx;
  2760. height = y2 - rect->dy;
  2761. dst = (unsigned long *)
  2762. ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
  2763. dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
  2764. dst_idx += rect->dy * par->next_line * 8 + rect->dx;
  2765. while (height--) {
  2766. switch (rect->rop) {
  2767. case ROP_COPY:
  2768. fill_one_line(info->var.bits_per_pixel,
  2769. par->next_plane, dst, dst_idx, width,
  2770. rect->color);
  2771. break;
  2772. case ROP_XOR:
  2773. xor_one_line(info->var.bits_per_pixel, par->next_plane,
  2774. dst, dst_idx, width, rect->color);
  2775. break;
  2776. }
  2777. dst_idx += par->next_line * 8;
  2778. }
  2779. }
  2780. static inline void copy_one_line(int bpp, unsigned long next_plane,
  2781. unsigned long *dst, int dst_idx,
  2782. unsigned long *src, int src_idx, u32 n)
  2783. {
  2784. while (1) {
  2785. dst += dst_idx >> SHIFT_PER_LONG;
  2786. dst_idx &= (BITS_PER_LONG - 1);
  2787. src += src_idx >> SHIFT_PER_LONG;
  2788. src_idx &= (BITS_PER_LONG - 1);
  2789. bitcpy(dst, dst_idx, src, src_idx, n);
  2790. if (!--bpp)
  2791. break;
  2792. dst_idx += next_plane * 8;
  2793. src_idx += next_plane * 8;
  2794. }
  2795. }
  2796. static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
  2797. unsigned long *dst, int dst_idx,
  2798. unsigned long *src, int src_idx, u32 n)
  2799. {
  2800. while (1) {
  2801. dst += dst_idx >> SHIFT_PER_LONG;
  2802. dst_idx &= (BITS_PER_LONG - 1);
  2803. src += src_idx >> SHIFT_PER_LONG;
  2804. src_idx &= (BITS_PER_LONG - 1);
  2805. bitcpy_rev(dst, dst_idx, src, src_idx, n);
  2806. if (!--bpp)
  2807. break;
  2808. dst_idx += next_plane * 8;
  2809. src_idx += next_plane * 8;
  2810. }
  2811. }
  2812. static void amifb_copyarea(struct fb_info *info,
  2813. const struct fb_copyarea *area)
  2814. {
  2815. struct amifb_par *par = info->par;
  2816. int x2, y2;
  2817. u32 dx, dy, sx, sy, width, height;
  2818. unsigned long *dst, *src;
  2819. int dst_idx, src_idx;
  2820. int rev_copy = 0;
  2821. /* clip the destination */
  2822. x2 = area->dx + area->width;
  2823. y2 = area->dy + area->height;
  2824. dx = area->dx > 0 ? area->dx : 0;
  2825. dy = area->dy > 0 ? area->dy : 0;
  2826. x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
  2827. y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
  2828. width = x2 - dx;
  2829. height = y2 - dy;
  2830. if (area->sx + dx < area->dx || area->sy + dy < area->dy)
  2831. return;
  2832. /* update sx,sy */
  2833. sx = area->sx + (dx - area->dx);
  2834. sy = area->sy + (dy - area->dy);
  2835. /* the source must be completely inside the virtual screen */
  2836. if (sx + width > info->var.xres_virtual ||
  2837. sy + height > info->var.yres_virtual)
  2838. return;
  2839. if (dy > sy || (dy == sy && dx > sx)) {
  2840. dy += height;
  2841. sy += height;
  2842. rev_copy = 1;
  2843. }
  2844. dst = (unsigned long *)
  2845. ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
  2846. src = dst;
  2847. dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
  2848. src_idx = dst_idx;
  2849. dst_idx += dy * par->next_line * 8 + dx;
  2850. src_idx += sy * par->next_line * 8 + sx;
  2851. if (rev_copy) {
  2852. while (height--) {
  2853. dst_idx -= par->next_line * 8;
  2854. src_idx -= par->next_line * 8;
  2855. copy_one_line_rev(info->var.bits_per_pixel,
  2856. par->next_plane, dst, dst_idx, src,
  2857. src_idx, width);
  2858. }
  2859. } else {
  2860. while (height--) {
  2861. copy_one_line(info->var.bits_per_pixel,
  2862. par->next_plane, dst, dst_idx, src,
  2863. src_idx, width);
  2864. dst_idx += par->next_line * 8;
  2865. src_idx += par->next_line * 8;
  2866. }
  2867. }
  2868. }
  2869. static inline void expand_one_line(int bpp, unsigned long next_plane,
  2870. unsigned long *dst, int dst_idx, u32 n,
  2871. const u8 *data, u32 bgcolor, u32 fgcolor)
  2872. {
  2873. const unsigned long *src;
  2874. int src_idx;
  2875. while (1) {
  2876. dst += dst_idx >> SHIFT_PER_LONG;
  2877. dst_idx &= (BITS_PER_LONG - 1);
  2878. if ((bgcolor ^ fgcolor) & 1) {
  2879. src = (unsigned long *)
  2880. ((unsigned long)data & ~(BYTES_PER_LONG - 1));
  2881. src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
  2882. if (fgcolor & 1)
  2883. bitcpy(dst, dst_idx, src, src_idx, n);
  2884. else
  2885. bitcpy_not(dst, dst_idx, src, src_idx, n);
  2886. /* set or clear */
  2887. } else
  2888. bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
  2889. if (!--bpp)
  2890. break;
  2891. bgcolor >>= 1;
  2892. fgcolor >>= 1;
  2893. dst_idx += next_plane * 8;
  2894. }
  2895. }
  2896. static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
  2897. {
  2898. struct amifb_par *par = info->par;
  2899. int x2, y2;
  2900. unsigned long *dst;
  2901. int dst_idx;
  2902. const char *src;
  2903. u32 dx, dy, width, height, pitch;
  2904. /*
  2905. * We could use hardware clipping but on many cards you get around
  2906. * hardware clipping by writing to framebuffer directly like we are
  2907. * doing here.
  2908. */
  2909. x2 = image->dx + image->width;
  2910. y2 = image->dy + image->height;
  2911. dx = image->dx;
  2912. dy = image->dy;
  2913. x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
  2914. y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
  2915. width = x2 - dx;
  2916. height = y2 - dy;
  2917. if (image->depth == 1) {
  2918. dst = (unsigned long *)
  2919. ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
  2920. dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
  2921. dst_idx += dy * par->next_line * 8 + dx;
  2922. src = image->data;
  2923. pitch = (image->width + 7) / 8;
  2924. while (height--) {
  2925. expand_one_line(info->var.bits_per_pixel,
  2926. par->next_plane, dst, dst_idx, width,
  2927. src, image->bg_color,
  2928. image->fg_color);
  2929. dst_idx += par->next_line * 8;
  2930. src += pitch;
  2931. }
  2932. } else {
  2933. c2p_planar(info->screen_base, image->data, dx, dy, width,
  2934. height, par->next_line, par->next_plane,
  2935. image->width, info->var.bits_per_pixel);
  2936. }
  2937. }
  2938. /*
  2939. * Amiga Frame Buffer Specific ioctls
  2940. */
  2941. static int amifb_ioctl(struct fb_info *info,
  2942. unsigned int cmd, unsigned long arg)
  2943. {
  2944. union {
  2945. struct fb_fix_cursorinfo fix;
  2946. struct fb_var_cursorinfo var;
  2947. struct fb_cursorstate state;
  2948. } crsr;
  2949. void __user *argp = (void __user *)arg;
  2950. int i;
  2951. switch (cmd) {
  2952. case FBIOGET_FCURSORINFO:
  2953. i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
  2954. if (i)
  2955. return i;
  2956. return copy_to_user(argp, &crsr.fix,
  2957. sizeof(crsr.fix)) ? -EFAULT : 0;
  2958. case FBIOGET_VCURSORINFO:
  2959. i = ami_get_var_cursorinfo(&crsr.var,
  2960. ((struct fb_var_cursorinfo __user *)arg)->data,
  2961. info->par);
  2962. if (i)
  2963. return i;
  2964. return copy_to_user(argp, &crsr.var,
  2965. sizeof(crsr.var)) ? -EFAULT : 0;
  2966. case FBIOPUT_VCURSORINFO:
  2967. if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
  2968. return -EFAULT;
  2969. return ami_set_var_cursorinfo(&crsr.var,
  2970. ((struct fb_var_cursorinfo __user *)arg)->data,
  2971. info->par);
  2972. case FBIOGET_CURSORSTATE:
  2973. i = ami_get_cursorstate(&crsr.state, info->par);
  2974. if (i)
  2975. return i;
  2976. return copy_to_user(argp, &crsr.state,
  2977. sizeof(crsr.state)) ? -EFAULT : 0;
  2978. case FBIOPUT_CURSORSTATE:
  2979. if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
  2980. return -EFAULT;
  2981. return ami_set_cursorstate(&crsr.state, info->par);
  2982. }
  2983. return -EINVAL;
  2984. }
  2985. /*
  2986. * Flash the cursor (called by VBlank interrupt)
  2987. */
  2988. static int flash_cursor(void)
  2989. {
  2990. static int cursorcount = 1;
  2991. if (cursormode == FB_CURSOR_FLASH) {
  2992. if (!--cursorcount) {
  2993. cursorstate = -cursorstate;
  2994. cursorcount = cursorrate;
  2995. if (!is_blanked)
  2996. return 1;
  2997. }
  2998. }
  2999. return 0;
  3000. }
  3001. /*
  3002. * VBlank Display Interrupt
  3003. */
  3004. static irqreturn_t amifb_interrupt(int irq, void *dev_id)
  3005. {
  3006. struct amifb_par *par = dev_id;
  3007. if (do_vmode_pan || do_vmode_full)
  3008. ami_update_display(par);
  3009. if (do_vmode_full)
  3010. ami_init_display(par);
  3011. if (do_vmode_pan) {
  3012. flash_cursor();
  3013. ami_rebuild_copper(par);
  3014. do_cursor = do_vmode_pan = 0;
  3015. } else if (do_cursor) {
  3016. flash_cursor();
  3017. ami_set_sprite(par);
  3018. do_cursor = 0;
  3019. } else {
  3020. if (flash_cursor())
  3021. ami_set_sprite(par);
  3022. }
  3023. if (do_blank) {
  3024. ami_do_blank(par);
  3025. do_blank = 0;
  3026. }
  3027. if (do_vmode_full) {
  3028. ami_reinit_copper(par);
  3029. do_vmode_full = 0;
  3030. }
  3031. return IRQ_HANDLED;
  3032. }
  3033. static struct fb_ops amifb_ops = {
  3034. .owner = THIS_MODULE,
  3035. .fb_check_var = amifb_check_var,
  3036. .fb_set_par = amifb_set_par,
  3037. .fb_setcolreg = amifb_setcolreg,
  3038. .fb_blank = amifb_blank,
  3039. .fb_pan_display = amifb_pan_display,
  3040. .fb_fillrect = amifb_fillrect,
  3041. .fb_copyarea = amifb_copyarea,
  3042. .fb_imageblit = amifb_imageblit,
  3043. .fb_ioctl = amifb_ioctl,
  3044. };
  3045. /*
  3046. * Allocate, Clear and Align a Block of Chip Memory
  3047. */
  3048. static void *aligned_chipptr;
  3049. static inline u_long __init chipalloc(u_long size)
  3050. {
  3051. aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
  3052. if (!aligned_chipptr) {
  3053. pr_err("amifb: No Chip RAM for frame buffer");
  3054. return 0;
  3055. }
  3056. memset(aligned_chipptr, 0, size);
  3057. return (u_long)aligned_chipptr;
  3058. }
  3059. static inline void chipfree(void)
  3060. {
  3061. if (aligned_chipptr)
  3062. amiga_chip_free(aligned_chipptr);
  3063. }
  3064. /*
  3065. * Initialisation
  3066. */
  3067. static int __init amifb_probe(struct platform_device *pdev)
  3068. {
  3069. struct fb_info *info;
  3070. int tag, i, err = 0;
  3071. u_long chipptr;
  3072. u_int defmode;
  3073. #ifndef MODULE
  3074. char *option = NULL;
  3075. if (fb_get_options("amifb", &option)) {
  3076. amifb_video_off();
  3077. return -ENODEV;
  3078. }
  3079. amifb_setup(option);
  3080. #endif
  3081. custom.dmacon = DMAF_ALL | DMAF_MASTER;
  3082. info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
  3083. if (!info) {
  3084. dev_err(&pdev->dev, "framebuffer_alloc failed\n");
  3085. return -ENOMEM;
  3086. }
  3087. strcpy(info->fix.id, "Amiga ");
  3088. info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  3089. info->fix.accel = FB_ACCEL_AMIGABLITT;
  3090. switch (amiga_chipset) {
  3091. #ifdef CONFIG_FB_AMIGA_OCS
  3092. case CS_OCS:
  3093. strcat(info->fix.id, "OCS");
  3094. default_chipset:
  3095. chipset = TAG_OCS;
  3096. maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
  3097. maxdepth[TAG_HIRES] = 4;
  3098. maxdepth[TAG_LORES] = 6;
  3099. maxfmode = TAG_FMODE_1;
  3100. defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
  3101. info->fix.smem_len = VIDEOMEMSIZE_OCS;
  3102. break;
  3103. #endif /* CONFIG_FB_AMIGA_OCS */
  3104. #ifdef CONFIG_FB_AMIGA_ECS
  3105. case CS_ECS:
  3106. strcat(info->fix.id, "ECS");
  3107. chipset = TAG_ECS;
  3108. maxdepth[TAG_SHRES] = 2;
  3109. maxdepth[TAG_HIRES] = 4;
  3110. maxdepth[TAG_LORES] = 6;
  3111. maxfmode = TAG_FMODE_1;
  3112. if (AMIGAHW_PRESENT(AMBER_FF))
  3113. defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
  3114. : DEFMODE_AMBER_NTSC;
  3115. else
  3116. defmode = amiga_vblank == 50 ? DEFMODE_PAL
  3117. : DEFMODE_NTSC;
  3118. if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
  3119. VIDEOMEMSIZE_ECS_2M)
  3120. info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
  3121. else
  3122. info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
  3123. break;
  3124. #endif /* CONFIG_FB_AMIGA_ECS */
  3125. #ifdef CONFIG_FB_AMIGA_AGA
  3126. case CS_AGA:
  3127. strcat(info->fix.id, "AGA");
  3128. chipset = TAG_AGA;
  3129. maxdepth[TAG_SHRES] = 8;
  3130. maxdepth[TAG_HIRES] = 8;
  3131. maxdepth[TAG_LORES] = 8;
  3132. maxfmode = TAG_FMODE_4;
  3133. defmode = DEFMODE_AGA;
  3134. if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
  3135. VIDEOMEMSIZE_AGA_2M)
  3136. info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
  3137. else
  3138. info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
  3139. break;
  3140. #endif /* CONFIG_FB_AMIGA_AGA */
  3141. default:
  3142. #ifdef CONFIG_FB_AMIGA_OCS
  3143. printk("Unknown graphics chipset, defaulting to OCS\n");
  3144. strcat(info->fix.id, "Unknown");
  3145. goto default_chipset;
  3146. #else /* CONFIG_FB_AMIGA_OCS */
  3147. err = -ENODEV;
  3148. goto release;
  3149. #endif /* CONFIG_FB_AMIGA_OCS */
  3150. break;
  3151. }
  3152. /*
  3153. * Calculate the Pixel Clock Values for this Machine
  3154. */
  3155. {
  3156. u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
  3157. pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */
  3158. pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */
  3159. pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */
  3160. }
  3161. /*
  3162. * Replace the Tag Values with the Real Pixel Clock Values
  3163. */
  3164. for (i = 0; i < NUM_TOTAL_MODES; i++) {
  3165. struct fb_videomode *mode = &ami_modedb[i];
  3166. tag = mode->pixclock;
  3167. if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
  3168. mode->pixclock = pixclock[tag];
  3169. }
  3170. }
  3171. if (amifb_hfmin) {
  3172. info->monspecs.hfmin = amifb_hfmin;
  3173. info->monspecs.hfmax = amifb_hfmax;
  3174. info->monspecs.vfmin = amifb_vfmin;
  3175. info->monspecs.vfmax = amifb_vfmax;
  3176. } else {
  3177. /*
  3178. * These are for a typical Amiga monitor (e.g. A1960)
  3179. */
  3180. info->monspecs.hfmin = 15000;
  3181. info->monspecs.hfmax = 38000;
  3182. info->monspecs.vfmin = 49;
  3183. info->monspecs.vfmax = 90;
  3184. }
  3185. info->fbops = &amifb_ops;
  3186. info->flags = FBINFO_DEFAULT;
  3187. info->device = &pdev->dev;
  3188. if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
  3189. NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
  3190. err = -EINVAL;
  3191. goto release;
  3192. }
  3193. fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
  3194. &info->modelist);
  3195. round_down_bpp = 0;
  3196. chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
  3197. DUMMYSPRITEMEMSIZE + COPINITSIZE +
  3198. 4 * COPLISTSIZE);
  3199. if (!chipptr) {
  3200. err = -ENOMEM;
  3201. goto release;
  3202. }
  3203. assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
  3204. assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
  3205. assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
  3206. assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
  3207. assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
  3208. assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
  3209. assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
  3210. assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
  3211. /*
  3212. * access the videomem with writethrough cache
  3213. */
  3214. info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
  3215. videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
  3216. info->fix.smem_len);
  3217. if (!videomemory) {
  3218. dev_warn(&pdev->dev,
  3219. "Unable to map videomem cached writethrough\n");
  3220. info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
  3221. } else
  3222. info->screen_base = (char *)videomemory;
  3223. memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
  3224. /*
  3225. * Make sure the Copper has something to do
  3226. */
  3227. ami_init_copper();
  3228. /*
  3229. * Enable Display DMA
  3230. */
  3231. custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
  3232. DMAF_BLITTER | DMAF_SPRITE;
  3233. err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
  3234. "fb vertb handler", info->par);
  3235. if (err)
  3236. goto disable_dma;
  3237. err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
  3238. if (err)
  3239. goto free_irq;
  3240. dev_set_drvdata(&pdev->dev, info);
  3241. err = register_framebuffer(info);
  3242. if (err)
  3243. goto unset_drvdata;
  3244. printk("fb%d: %s frame buffer device, using %dK of video memory\n",
  3245. info->node, info->fix.id, info->fix.smem_len>>10);
  3246. return 0;
  3247. unset_drvdata:
  3248. dev_set_drvdata(&pdev->dev, NULL);
  3249. fb_dealloc_cmap(&info->cmap);
  3250. free_irq:
  3251. free_irq(IRQ_AMIGA_COPPER, info->par);
  3252. disable_dma:
  3253. custom.dmacon = DMAF_ALL | DMAF_MASTER;
  3254. if (videomemory)
  3255. iounmap((void *)videomemory);
  3256. chipfree();
  3257. release:
  3258. framebuffer_release(info);
  3259. return err;
  3260. }
  3261. static int __exit amifb_remove(struct platform_device *pdev)
  3262. {
  3263. struct fb_info *info = dev_get_drvdata(&pdev->dev);
  3264. unregister_framebuffer(info);
  3265. dev_set_drvdata(&pdev->dev, NULL);
  3266. fb_dealloc_cmap(&info->cmap);
  3267. free_irq(IRQ_AMIGA_COPPER, info->par);
  3268. custom.dmacon = DMAF_ALL | DMAF_MASTER;
  3269. if (videomemory)
  3270. iounmap((void *)videomemory);
  3271. chipfree();
  3272. framebuffer_release(info);
  3273. amifb_video_off();
  3274. return 0;
  3275. }
  3276. static struct platform_driver amifb_driver = {
  3277. .remove = __exit_p(amifb_remove),
  3278. .driver = {
  3279. .name = "amiga-video",
  3280. .owner = THIS_MODULE,
  3281. },
  3282. };
  3283. static int __init amifb_init(void)
  3284. {
  3285. return platform_driver_probe(&amifb_driver, amifb_probe);
  3286. }
  3287. module_init(amifb_init);
  3288. static void __exit amifb_exit(void)
  3289. {
  3290. platform_driver_unregister(&amifb_driver);
  3291. }
  3292. module_exit(amifb_exit);
  3293. MODULE_LICENSE("GPL");
  3294. MODULE_ALIAS("platform:amiga-video");