diff --git a/sys/contrib/dev/drm2/radeonkmsfw/ARUBA_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/ARUBA_me.bin.uu new file mode 100644 index 00000000000..d897ff204cb --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/ARUBA_me.bin.uu @@ -0,0 +1,197 @@ +begin 644 ARUBA_me.bin +MQ`@`,<`.``'`$``'F(``#`04!``$&```V```3=@!H-K8`:#9"1```=@``$W- +ME:'T!50$``68``&9`/_[?$"``8P``/Q!0` +M"95```+90:*DQ!L`*M@``%;-@`!4P#X`!,P!H?3,/2`$Q#T``\P``$?80`!6 +MV$``7H````_$#``*!#P`(Y3```+/P:*DQ!L`*]@``%;-@`!5P#X`!,P!H?/, +M/2`$Q#T``\P``$G80`!6V$``7H````\$/``CS\&BI,P``$O8``!5S$``8X`` +M``_,``!&S```2\Q!(F3,02)ES$$B9LQ!HMU\0(`!S(``38@```#,0`!&S``` +M2XP`!:3,02)DS$$B9S4&@VL0@`#*6 +M```3V$``4\0X``K80`!=Q#P`+"?\``*7P/_^EX```P0\`"//P:*DQ#\`*\_` +M`%7`/@`$S`&A\\P](`3$/0`#S```2=A``%[-0:#:F8```LP``$+-0`!A@``` +M#]@``$A\0,`!Q"0`,234`/^:0``#V```5-@``$?$(``RE@``!-A``%/8``!5 +MV```2=A``&3-0`!A@```#WQ`P`$8T`'H&-0`,!C8`#0%*`%T?$(``7Q"0`&5 +M```'AH```(```8Z```6@@``!LH``!:"```&$$50`$'X6``K,@`!-U&$``)6` +M_I'`.@`$S#DA0,0Y``-\0(`!B````!%4`!!2)``@?B8`&LU``%C48@``E8#^ +MAL0@`!R:`/__?$"``8@```#<.@``F4``&R><``&5P``-"[@``0`0)9`__[, +MP2%US0$A=L0@`!.6`/__%B@``9J```/,``!.@```#\P``$[,P2%U@``!SGQ` +MP`%\00`!S```1``*```'YP"(`!'X6``K,(0``Q!T``WQ"0`%\ +M0H`!F,```\WE``"````/SD$A:` +M`!TF9`#_@``"7W\;@`X4I``(EX``&"9D`/^```)??QN`#!2D``B;@``3)F0` +M_X```E]_&X`-%*0`")N```XF9`#_@``"7W\;@`\4I``(FX``"29D`/^```)? +M?QN`#A2D``B;@``$)F0`_X```E\4I``()F0`_S)H`#P4[``(FH#]O7Q#0`%\ +M0X`!?$/````$5%``2P"(``L`F``250``$P"?_ +M^WTE``G`)@``?=*`"7X2P`E])0`*?$%``7Q!@`',P2%IS0$A:IJ```?-02%K +MS8$A;);`_9C$,``5EP#__X````_(%``455@`(,U!(6O-@2%LEL#]D(```GA\ +M00`!?$%````8S\`#X<^``^(2L``"?S\` +M`<\``^-\@,`!@``$CWQ`P`$8T`'H!2@"GY4```B&@```@``"J(```K:```*\ +M@``"PH```L>```+-S,&BI(````_`$@@`?$%``7Q"``%]#,`*P!(`!!58``,5 +M7``-?='`"1(@`!-^'D`*?DZ`"LZ!HJ3-@:'^@```#P00(1C$%``0E4#__]11 +M``#,P:*D@```#P00(0;$%``1E4#__]11``#,P:*D@```#]A``!;,P:*DQ!`` +M%ID`__^````/!!`A`,04`!*50/__U%$``,S!HJ2````/)-@``7Q!``%\04`! +M?$(``96```81F``0Q!P`"L0\`">7P/__@``"VQ&8`!#$'``)Q#P`*)?`__\5 +M:``=?5E`"A'D``J:@``#?B8`"LW``%S-`2%8S4$A6````/)'0` +M`21X``+$#``?FT```HP``WO$%``A!!``$)N```*,``.5S,&B4,T!H%`$&`0` +MC``#1,P``%G$/``CQ!``'XP``U3$'``E)=P``<@X`":5P``%Q#P`(T>X!5#, +M``!8S_H``,0D`!V:0/__!#```<0H`!D^J``$Q"P`&GZN@`J:@/_\SP``45#8 +M``@4W``8*=R``,V!(8#-P2&!42``"!4D`!@3,``>?G)`"LX!(8+.02&#S4$A +MA'Q`@`',@`!-B````"1T``$D>``"Q`P`()M```*,``-[Q!0`(@00`!";@``" +MC``#EFD#__\0H`!D^J``$Q"P`&WZN +M@`J:@/_\!#```H```Q(%F,``$-P`"!3@`!C-V0``Q!P`&,W9``'$)``8?F)` +M"LY9``+$'``8Q"``&,0D`!C-V0`#SAD`!,Y9``>0````&_@`\,`V"`#`,`"` +MEX```I````#8``!=Q#@`+">X``&7@/_^P"H`!,08`"_/02%\SP$A?\V!(6W-P2%NQ!H``H``!'M\0,`!Q!,#X,07`^/$&P/A +MQ!\#XLV!(6G-P2%JS,$A:\P!(6P$(``$?:&``7V60`S-@`/AED#[="4H``/` +M+?``$1@`"'VM@`E]J8`*S8`#X8````\DC/__U$T``'Q`@`',@`!-B````'Q` +MP`$8U``P&-`!Z!C\`#0DS``/!.@$L7Q!@`%\0<`!E,``,H:```"```2Z@``% +MH(``!,6```31@``$MU'<`"!]G@`:@``$\\V!(6W-P2%N!9@`!,0B``*50``U +MS8$A;6P``#S```08`` +M!.@$+```!#```)K```27```#S```08``!.@$+```!#```)K```.7```"S``` +M08``!.@YK`<&/;`'`,0T`!>:P``#EP```LP``$'`.@`$?;F`"LP9```%F``! +MQ"$``Y5```7,&0``Q"4``U)D`"!^)@`:ST``%\R``$T%*`3X?$&``7Q!P`&5 +M```'AH```(``!2Z```6@@``%.8``!1&```4B.:P'!CVP!P#$-``7FL```Y<` +M``+,``!!SAD``)5```0%F``!5B0`(,Y9``"7P``$P#H`!,PY(4#$.0`#ST`` +M%WQ`@`',@`!-B````#&L"`#$-``7EL```\P``$&```4$!"P```0P``":P``$ +MEP```\P``$&```4$!"P```0P``":P``#EP```LP``$&```4$49P`('V=@!K8 +M``!8SAH``)5```0%F``$5B0`(,Y:``";P`!@?$"``LT!(7[`*@`$)53__SEP``-!7``"FP```@0<`$`)W``! +MF<#__\PI(7_$)0`#%FP`'T%<``+,@`!-FL#_^13\`!_8``!>F\#ZD\00`#', +M$`/W@```#WQ`P`%\00`!%1@`'U$4`"`9'``QF8``",T``%A]34`:U%8``)7` +M^H;$(``@6``'P$C@!]!9D`?@6<``\%H``/!:`` +M#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@``\%H``/ +M!:``#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@``\% +MH``/!:``#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@ +M``\%H``/!:``#P6@``\%H``/!:``#P6@``\%H``/!:``#P6@``\%H``/!:`` +3#P6@``\%H``/!:``#P6@``\%H``` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/ARUBA_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/ARUBA_pfp.bin.uu new file mode 100644 index 00000000000..14a086f84ec --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/ARUBA_pfp.bin.uu @@ -0,0 +1,197 @@ +begin 644 ARUBA_pfp.bin +M?$"``8@```#,@`!`U$``0'Q`@`&(````$$P``220``)\04`!4%@`('V5P!J8 +MP``#T<``&(````"9```#T<``&8````#1P``:@````"2,``+,@`!`S$``0)C` +M``/,``!2@``$(B7@``$V$`# +M]\0X`_>;@/__Q!P`$YG`__\B4P``"!50`!B@0``%]%0`$?9&`"8```,N90/_X +MQ!P`!9 +M`/YBQ!P`!LP``%3-P`!`S```0(````+$%``/Q!P`!)E`_EK,``!2S<``0,P` +M`$#$)``^FD#^57Q`P`%04``@?0U`&M%``!?,``!B@````,`W__\@B`!P@``! +MN'Q#0`'('``7Q!@`%L]#HIY\04`!?5C`!'S?$#``7Q!``%\04`!S,.A^LT#H?G- +M0Z*=S,``0,T``$#-0`!`S$``0'Q`@`&(````?$#``230``',PZ*?V$``%I4` +M``+8@``6S(``0,S``$"`````?$#````2\P``$Z```0AS```39K```+,``!.EX#]5`NX``'$ +M/P`#FX#__8````#,``!.ED```\P``$*```0AV@``0L0+``/$#P`#Q!,``\07 +M``/$&P`#Q!\``\0G``/$*P`#%?P`'Q:P`!]_\\`)%/``'W_SP`D5<``??_/` +M"7V(@`)]S,`"E\``#'Y1``)^E4`"?)"`#'S4P`Q\CT`)FL```BRT``',``!- +MFT`!4F0``!/5@``IF`__[,``!= +M*1R``,S!(87-P2&&%10`'\Q!(8?,02&(S$$AB95`_,_$%``>F4#__X````#, +M@`!`S,``0,T``$#40`!`@````,0H`"S8:`/WS(``0,Q``$#&CP/WF,#__WQ` +M@`&(````Q"@`+,0L`!'$,``O?O+`"IJ```?$,``/FP``!<0T``3,``!2ST`` +M0,P``$":P``%Q#0`!LP``%3/0`!`S```0'Q`P`'8:`/WS(``0,S``$#40`!` +M%-``'YD``,F```,^S(``0,Q``$#,0`!`S$``0'Q`P`',P``5S,``0-1``$#8 +M``/V@````'Q`P`$4W``=&-@`/,R``$"9P``%S,``0)F`_);,``!A@``$(F0``!``!\0@`!?$)``7Q!@`%]Y<`)?>*`#T&L``*:@/PO!NP` +M`PKL``&:P/__)-P`$)G```/%'0``@``#SL4>``"```/.S(``0,S``$#40`!` +M@````,0<``3-P`!`S```0,R``$#40`!`?$"``8@```#$'``%S<``0,P``$#, +M@`!`U$``0'Q`@`&(````?$#``230``8Q$``&Q!0`#YD```C,``!2Q"0`/I9` +M`#&90``$Q!P`!,W``$#,``!`S(``0,S``$#40`!`@````'Q`P`%\00`!%1@` +M'\T``%I1%``@F8```]1-``"`````?4U`&AD<`#'45@``Q"``'Y7`^_?$(``? +MF@#__X````!\0,`!%-``'R34`/^5```#S%0#`(````#,@`!`S,``0,Q``$"` +M````Q"``+'Q`P`'$TP,`S(``0,S``$#,``!:S2$A08````#40`!_@````,0D +M`#Z60``#?$"``8@```"```0E```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````P/?``0#Y@`%`?(`!@$9``68P`/J +M(`@``2J,`>3((`)!?.#`!IC`!!H@"``!S(```X```IH`````B`````````#` +M"```A``"9P````#(#`!Y',S__\`()-6(`````````,@)/3;(#3TWE,`"L@`` +M``#($3TXR!4].<@=/3K((3T[R"4]-02H`##.@3V"S,$]@\T!/83-03V%S<$] +MALX!/8<0B``#!(P`&,B6`#R50`*AR-(`*'TE``$)5``!!,P`*)D`__L````` +MR)(`.`40`$!]"L``R-8`!,`<``3(X@`4R.8`),X*`4S.;@%,",P`!`B(``0* +M[``$"=P``9G`__@`````S0H!8,P*`63-03U'@``"]`````"(`````````(`` +M!*#`,`'!R"@`!9:``2@`````(`@``H0``?(P````"(`````````,^<`!;-@``.R?``&7\X@`R4@/_^`````(@````` +M````R#@"0P>X``'+B```P`PA@(````?4%`"\C4```$S``!!B```1U8`/]]D8`2?9V``WR9@!&5 +M@``U'5C_`!68``A]D8`2?9V``WR9@`^5@``O`````!54`!"60``#`````!54 +M``@=5`#_B`````````#`,/__R(P``'SQ``:5`/\X!(@``$```G<``<)W``$("```#X8`!"5@/_#`````(`` +M`/D@%`!`R"@``9:`_P``````(`@````[8@"``` +MS``"`,P``@'`-`.1(!```"`(``/--0``P#`AC2`,``',\0``P#`ACB#,/__, +M\0``!1```0B(``&8@/_WP#`AML`*%`#,L0``S#4``,@(`$````&% +M1(@`!,P``@.$``!]$;@`'X```:0`````R"@`*I:``RL`````S8``#H0``5X` +M````@``!I"`8``',```.S```#B`H`<,@'```R`@"!7^+@`?("`(!E(`!10`` +M``"```(\`````,@(`B[(B```?`F`!R`<```@+```P"``!I5``!1\KT`$?.Z` +M!!]T``%_:T`&?2Z`!!ZH``$JJ```?VM`!I=```<`````(#```7\O``-]L8`( +M"50``07<``$*(``!!NP``9H`_^X`````R"`"+H@```#-H```P`@#((0``],` +M````R`@"&WU(@!#,@`(DS4`"&X0``IX`````R`@"''U(@!#,@`(EB````,U` +M`AS)(0``'BC__Q8@`!!^HH``B`````````#("`(`E(#_Q`````#(*`!`P"X( +M`'ZN@`:6@/^_(!@``<@H`"R6@/\E`````,@H`'C.@`(L@``!#2`8``&(```` +M`````(@`````````(`P``,`0``8```/`.``0SX``1\@(`@"4@``/ +MR`@"`92```T`````R`@`"I2```H`````S8``#L@X`&G(-`!JSWD``,NU``#` +M.`_LSWD``,P```X@'```R`@"`92``>4`````R"@``):``>(@"``!S8``#L@, +M`"#,@```'!P``"J(`;N4@``R`````(``!$4`````P`PCFLR-``#`#".8B``` +M`,R-``#`,"`#S[$``(@```#+.0``'0P!`)3``-3`,#VORPT``!S,``*4P`#0 +MP#`]-,L-``"8P`)W``````````#("`)$!(@``R`P"'<@0`AY\T4`1F4```P`` +M``!]`,`'A``$8LS``B.(`````````"`X``'/@``#S``"`<@(`!R4@/],```` +M`,V```X`````(`P``X0``'T0^``>A```<"`X``+,,0``R`@"`)B```0````` +MA``$,@````"$``)L(#@```_M;(.`)"FX``!`````"$``3/`````,@X`$X +M``0$B``!RXX``,S(``!'N``$!(@``QW<``&9P``.R"`"),@D`B5^)<`'R"`"&\@D +M`B8>:/__?BJ`$'WIP`?((`(<%F@`$'XJ0!!]Y<`'F<``&"`<`$!]S,`!?-G` +M$A7<``;((`(U?Z(`$)8``!'((`(U?Z(``7WA0!"90``#`````'W"``?`%`(I +MS4`"+L@,`A?($`!Z'1#__R`4``2$``&N`````,`X``+/@`(AB`````````#( +M#`(#E,``"P`````@#``!A```?1#X`!Z$``5-(`P``80``FP@.```FX#^S``` +M``"$``!]$;@`'X0``FP@.``!A``%32`,``#`,`'`RSD``"`X``"5P/UYSX`` +M`WW!P`:$``!](#@``(```:3/@``#(`P``X0``'T0^``>A``";"`X``+()`)` +MFD#_$`````"$``.C(`@"2(```TL`````R"@``I:`_.<@"``!S8``#LR```*` +M``*:`````,P``"G-@`(#A```?2`X``"```&E`````,G,`@.4P`"C(`@``,`, +M(;;(T0``P`H4`'T)``:9``"=(`@``"`,``&$``!]$/@`'H0``FP@.``"EX`` +MEB`(``#()`)`FD#\TP````"$``#[(`@"2(```3,`````*-``0)D`_['(.`(A +M.-P`0)7`_X=_@8`'",P`0'S9P!(5W``&R"`"'WXZ``'(#`(7P!0"*`__T`````B``````` +M``"(`````````,`0(`O`%```P!;``,U1``#)%0``P##__\B.``!\\0`&E0#] +M.T2(``3(E@``S5$``!3,`!!\\0`&E0#]-42(``3(E@``S5$``(``!+%$B``$ +MP`@AH,B-```4S``6',P``9C`__T`````B`````````#(*``KEH#_'0````#- +M@``.A```.`````"```&D(!@``<@X`$B;@/[K4[@`"(@`````````'J@`_\S` +M``O.@``,B`````````#+B@``P`PA@#P3,``',C`('P`I@8""(*!X$S``!S(P" +M!\`*8&`@B#(H!,P```3,``',C`('P`K_ +M_R"(@'T$S``!S(P"!\`*`$`@B``0S(`")LP``BW`"``"S(`"-@``V@I``-H +M+0`#P00``\$5``-IZ``#:>P``^@```/HT``",$\``VCD``/!W@`",$\``VD$ +M``-`+``#_P```K0"``)$!```HA8``TG6``*U$``"1%L``Z1&``"B&``"H$X` +M`_`#``(T:@`#]````<#%``/T```!TW(``T`.``#R0``#Z/```Z"V``-)U0`` +M^A$``K$/``)"%P`"I2```_`!``#Z0``"0QL``J4C``/P`0``\A$``T````-` +M+@`"MA```K0,```J0``"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`! +M``/HP```XA```T`(``*T````>A$``J`D``/P00`"L@@``J#^``/P00`"L@0` +M`K0_``)")```DB@``TJ4``/_```#8&P``T````/_```"M$```D0$``/P`P`# +MZ````((_``(B^@`#0````_\```*T0``"1!0``_`"``#R/P`"(OH``T````/_ +M```"M$```D04``/P`0`"+FX``TJ4``/_```#8'```T````/_```"M`(``D0D +M``/P`P`#Z````((_``(C,0`#0````_\```*T`@`"1#0``_`"``#R/P`"(S$` +M`TJ4``/_```#830``C-L``-````#_P```_\```)$#@`#\`,``^@```""/P`" +M)%H``C-L``-````#_P```_\```)$'@`#\`(``/(_``(D6@`"+JD``TJ4``/_ +M```#8'0``K````""*P`#0````_\```*T`@`"1$```_`#``/H````@C\``B89 +M``-*E``#_P```V!X``-````#_P```K0$``)$0``#\`,``^@```""/P`"*)P` +M`TJ4``/_```#8'P``T````/_```"M!```D1```/P#``#Z````((_``(I;``` +M`@T``_\```/_```"I`X``_`$``#R#@`"*6P``^@```""#@`#2I0``_\```-@ +MK``#0````_\```*T(``"1$```_`#``/H````@C\``BN$``-*E``#_P```V"P +M``/H````@C\``K#_``*Q_P`#P2```VA@``-H:``#0````_\```*T$``"1$`` +M`_!"``/T```"`8\``T`-``-`)@`"L4```K(0``*S"``"010``Z$:``)")``# +MHB0``F(A``)#.``#HS```F(C``"2*P`"I!X``_`)``-)/0`"LH```\`B``)$ +M0@`"*6P``TD]``/_```"LH```F1"```"$``#_P```K0!``)$!``#\`0``^@` +M``""/P`#P?X``BQ&```"$``#_P```K0"``)$!``#\`0``^@```""/P`#Z/`` +M`BQ&``-````#_P```_\```)$+@`#\`,``^@```""/P`"-7<``T````/_```" +MM!```D0D``/P`P`#Z````((_``(VJ0`#^`,``TJ4``/_```#8+0``K````"" +M*P`#0````_\```*T`@`"1$$``_`"``#R/P`")AD``TJ4``/_```#8+@``T`` +M``/_```"M`0``D1!``/P`@``\C\``BB<``-*E``#_P```V"\``-````#_P`` +M`K00``)$00`#\`L``/(_``(I;````@T``_\```/_```"I`X``_`$``#R#@`" +M*6P``^@```""#@`#2I0``_\```-@[``#0````_\```*T(``"1$$``_`"``#R +M/P`"*X0``TJ4``/_```#8/```/(_``*P_P`"L?\``\$@``-H8``#:&@``T`` +M``/_```"M!```D1!``/P0@`#]````@(.``-`#0`#0"8``K%```*R$``"LP@` +M`D$4``.A&@`"0B0``Z(D``)B(0`"0S@``Z,P``)B(P``DBL``J0>``/P"0`# +M23T``K*```/`(@`"1$(``BEL``-)/0`#_P```K*```)D0@```A```_\```*T +M!``"1`0``_`#``#R/P`#P?X``BQ&```"$``#_P```K0(``)$!``#\`,``/(_ +M``/H\``"+$8``T````/_```#_P```D0^``/P`@``\C\``C5W``-````#_P`` +M`K00``)$-``#\`(``/(_``(VJ0`#2I0``_\```-@]``#^`,```(8``/_```# +M_P```J`.``/P0@`#]````@)L``-`+``#_P```K0@``)`0``"H`0``_!(``/H +M````@C\``C((``(R30``\C\``C((``(R30`",N0``T````/_```"M`@``D0$ +M``/P#``#2`@``_\```*T0``"8`0``V@(``-)F``"M/T``D$4``-IF``#Z#`` +M`\$N``-H,``",O@``^@```/H$``#Z#```K(#``-H,``#0````_\```*U"``" +M114``_`!``(TUP`#2I0``_\```-@^````D```_\```/_```"H0X``_`"``/H +M````@A0``BZI``-(```#2`4```HT```".```$C,``"HZ```Z-@`#_P```V@` +M``-H!0`#2!```TG=```*-P``*CD``_\```-H$``#:=T``TEQ``*R`0`#Z#`` +M`\$&``/!%P`#:#```TEL``*U%@`"H%$``<*?``*PSP`"L04``K(!``*S```# +M:#```C+X``*PM``#:#```C+X``*PO``#:#```C+X``*PN``#:#```C+X``*P +MRP`#:#```C+X``*PC``#:#```C+X``*PT0`#:#```C+X``/H```#Z!```K(# +M``*S```#:#````(8``/_```#_P```J`.``/P0@`#]````<`````!]``#0!(` +M`T`5```*&P`"H`X``_`"``/T```!PL\``L$>``"*&P`":[H``F5;``+&;@`# +M\$$``L=^``-@%0`"L@\``D1"``*E%``#\`<``^B@``/HL``#8!(``^@```"! +M]``#]````P`#P?```BY[``/!\``"+GL``T`@``/_```# +M_P```L`.``/P10`"P1X``_!#``+"+@`#\$$``L,^``-@(``",VP``TE(``*T +M/P`"M8```D,T``)C-0`#:4@``D,T``-I2``#]````<````-`!```:C\``^B` +M``/HD``#Z*```^BP``*U$``"1!4``_`&``*@W@`#\`,``V2J``/T```#\$$` +M`V3J``/X`0`"M0@``D0%``(#'```8?@``J#>``/P`P`#Z$```_0```/P00`# +MA.H``]A```/?<``_@#``/4G@`#^P```P_^``(#&``#^`$``X7D``)$ +M%0`"`R\``"'Y``*@W@`#\`,``&'Q``/T```#\$$``&'P``*_"``#W$```]C` +M``/X`P`#U)X``_L```,/_@`"`RL``_@#``/L`````A0```I```!J/P`#_P`` +M`D`!``*@#@`#\`$``^P```-).``"H-X``_!!``-*7``"N/X``D(H``*@W@`# +M\`,``VDX``/T```#\$$``VI<``-)T``"M`0``F$4``*R`0`"LQ(``J#>``/P +M00`"LQ$``V@P``-)<0`"N.\``KD$``/!!@`"87D``D,X``-H,``#2`D``KC] +M``)$2``#:`D``BY_``-)H``"M!$``\$D``*Q#P`#::```TI$``*T_@`"81X` +M`VI$``)!%``#:D0``J#>``/P`P`#0F$``_0```/P00`#0ET``_\```/_```# +MZ&```VFE``-H:P`"N@P``KC```/<@0`#V*$``K#X``*Q!P`#Z"```^@P``/^ +M```#U!\``VAK``/H\``"(_\``B/B``(D'``"H?X``_!!``-B>@`#0G@``_\` +M``/_```"H(```<.3``*@D0`!PY,``J"B``'#DP`"H+,``<.3``+/_@`"O`P` +M`J'\``/P0@`#]````<-]``#Z!``#Z/```B/B``(C_P`")!P``T)X``/_```# +M_P```J"```'#J0`"H)$``<.I``*@H@`!PZD``J"S``'#J0`"S_X``KP,``*A +M_``#\$(``_0```'#E@``8@0``/H#``/_```"I<\``<.Y``*E_``!P[0``^CP +M``/HP``#]````<.\``,,SP`#K,```^CP``/T```!P[P``P_\``.O\``#Z,`` +M`B/_``/!_``"(^(``TDX``*@W@`#\$$``TI<``/_```"8BX``J#>``/P`P`# +M:3@``_0```/P00`#:EP``TG0``*T^P`"010``K(!``*S$@`"H-X``_!!``*S +M$0`#:#```TEQ``*X[P`"N?L``\$&``)!>0`"0S@``V@P``-("0`"N/T``D1( +M``-H"0`"L!@``B1```/L```#1+D``J#>``/P00`#1/D``\$/``/!'P`#P2\` +M`\$_``/!3P`#P5\``J#>``/P!0`#9+```V2T``-DN0`#]````_!#``-D\``# +M9/0``V3Y``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P```-$ +MN0`"H-X``_!!``-$^0`#P0\``\$?``/!+P`#P3\``\%O``/!?P`"H-X``_`% +M``-DK``#9+P``V2Y``/T```#\$,``V3L``-D_``#9/D``TC(``*T\P`"M00` +M`D`$``)@!0`#:,@``D`$``-HR``#[````K`0``(D0``",O@``C+X``(R^``" +M,O@``C+X``-*'``")$P``\&,``-*(``")$P``XS&``)HC``#2B0``B1,``/! +MG``#2B@``B1,``.,Q@`":9P``THL``(D3``#P:P``THP``(D3``#C,8``FJL +M``-*-``")$P``\&\``-*.``")$P``XS&``)KO``#[````VAK``*Y"``"N,`` +M`]R```/8D``#Z!```^@@``/H,``#_@```]0>``-H:P`#[````^C```.'/``# +MIW8``X8L``.F:``#A1P``Z5:``.$#``#I$P``FS'``)LQ@`";,4``FS$``/L +M````(@\``T`D``/_```"1$X``Z`&``*A#@`#\`$``(('``-)I``#2:$``&H_ +M``.+Z@`#P*L``D6E``*@W@`#\`,``D.C``/T```#\$$``F.S``-II``#::$` +M`K+_``*Q_P`"L'\``VA@``/H```#Z"```^@P``*@W@`#\`,```H)``/T```# +M\$$```H(``*XP``#:&L``]@```/<@``#U!X``K\"``(N>P`#@.```(($``"" +M`P`#Z````(("``""`0``\@```TA4``*@W@`#\`,``X3H``/T```#\$$``X3J +M``)B)``#:%0``TF8``.(Y0`#P3X``J#>``/P`0`#@S```\$N``)@"``#:#`` +M`TEU``.(Y@`"8&@``\$7``/!+@`#P3X``J#>``/P`0`#@S```V@P``-(5``" +MH-X``_`#``.$Z``#]````_!!``.$Z@`#P$0``D(D``-H5``"OP(``BY[```" +M&``#_P```_\```*@#@`#\`(``_0```($UP`",&$``^AP``.$Y@`"1DL``J!D +M``/P3P`#2=(``^A@``.*L@`#JJH``X2F``)D2@`#P50``J#>``/P`P`#:.4` +M`_0```/P00`#:04``_0```'%@@`"OP@``D_Y``.O]``#B[(``ZN\``(EI@`# +M]````@6"``-`#``#_P```K\(``)/\``#\$(``_0```'$]``"OP```KL!``(E +MI@```A$``_\```/_```"H`X``_!"``/T```!Q8(``K$"``*P$0`"Q$```L50 +M``*@W@`#\`,``VCE``/T```#\$$``VD%``,!'@`"!.D``/("``#R`0`"H-X` +M`_`#``!Z!@`#]````_!!``!Z!0`#C>(``]S0``/8\``#B>8``FF>``#Q\@`` +M0@<``^C0``./X``#P:@``XSM``#A]@``XCX``B_*``*W`0``0@<``^B@``#1 +M\@`"H'X``_`!``.H@``##]\``\'9``/!J``#C.T``.'V``#B/@`"+\H``C`+ +M``/!!``#P28``V)P``*_`0`#0!$``XC@``*@_@`#\`0``D1(``/P`@`#]``` +M`@5H``*W`0``0@<``_\```*@?@`#\`$``ZB```/HT``#C^```\&H``.,[0`` +MX?8``.(^``(OR@`",`L``T)P``.,ZP`#C.H``^CP``+(0``#J(```"H6``+* +M8@`#JJ```J9>``(%10``:C\``/(6``/!6``#P7H``V)Q``/T```"!/\``J%> +M``/P#@``:C\``\&1``/!LP`"H-X``_`#``-A+@`#]````_!!``-A,@`"P($` +M`Z@```+"HP`#JB```X50``"J%@`#@>```P"$``/P)``"H80``_`!``+$00`# +M!$X``\%4``,"I@`#\"0``J&F``/P`0`"QF$``P9N``/!=@`#U%X``F`"``(% +M5P``:C\``K\"``(N>P`#27$``X'D``/!!@`#HFP``J`N``(%@@`"87$``\$N +M``/!/@`"H-X``_`!``.#,``#AF```_!'``-H,``#C^T``BY[``./[0`"+GL` +M`X_M``(N>P`#C^T``BY[``-)=0`#P2X``\$&``/!%P`#P3X``J#>``/P`0`# +M@S```V@P``-)F``#_P```\$^``*@W@`#\`$``X,P``/!+@`#:#````H/```! +M]``#_P```D$>``/P`0`#[````J4.``/P2``#0!$``J#>``/P`P`"9FX``_0` +M``/P00`"9WX``V`1``/H````@?0``^P```(R^``#2D```$(```!*!```4@,` +M`KPS``)$#``"11P``F1%``)&+``"1SP``F9G``)D1@`"H4X``_`!``*T`0`" +MH(X``_`%``*D20`#\$,``J1+``/P00``\@(``*($``*\S``"1`P``D4<``)& +M+``"1SP``F1%``)D1@`"9$<``J%.``/P`0`"M`$``J".``/P!0`"I$H``_!# +M``*D2P`#\$$``/(!``"B`P`#Z$```*(```-#*0`"H-X``_!!``-#:0```@(` +M`!(!``*Q#P`"LP<``J7^``(%_``"H`X``_`&``*\#P`"I$$``_`!``*\"0`# +MP4P``\%<``*@+@`#\`8``KP/``*D80`#\`$``KP)``/!;``#P7P``J#>``/P +M`P`#8RD``_0```/P00`#8VD``DP"``*@S@`#\`8``L_^``*\"0`"I?P``_`" +M``/T```!Q:8``TCE``*@W@`#\$$``TD%``*X$0`"H`X``_`!``+$2``"24$` +M`J23``/P`0``\@(``J`N``/P`0`"Q5@``DE1``*DDP`#\`$``/(!``*@W@`# +M\`,``VCE``/T```#\$$``VD%``)``@`"H`X``@6F``/L````:C\``^@```(P +M.P`#29@``K@/``*U]0`"LP$``J#>``/P`0`#@S```\$N``)@"``"014``V@P +M``*_```"+GL``/'_``/H````@?X``T`,``-`+0`"N!```KD(``)*&``#JJ8` +M`DM)``.KM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*$0`" +ML$```D!```/P00`#Z#```D$>``/P`0`#Z#```)G]``(N?P`"O`$``J#>``/P +M"0`#2"$``XS&``.&9@`#IF8``F9L``-H(0`#:HD``_0```/P1P`#2"4``XS& +M``.&9@`#IF8``F9L``-H)0`#:HT``K`!``/H$``#Z"```^@P``-J8``"OP,` +M`C'5``-("``#A.H``('U``)@!``#:`@``K]D``(N>P``:C\``_\```/_```" +MH-X``_`#``*[```#]````_!!``*[0```V>\``\$.``/!'@`#@18``F$>``." +MY@`#:D0``\$>``.!%@`#Z"```VI$``/H```#P````\$0``*R_0`#:&```TI@ +M``*_]P`"L1,``D`/``)@#@`#:F```#(,```Z"P`"O`@``K_^``.&:@`"8B8` +M`J1^``/P`0`"LP0``D`/``)@#``#:F```X_A``(N>P`#:&L``_\```/^```` +M8CT``%H\``/_```#V,$``]RQ``./XP`"+GL``]`?``.,[P`#C^0``F_^``)` +M`0`"0B,``D`"``),P``#^P$``]`?``,/_@`"!J(``J#>``/P`P`#2"$``_0` +M``/P00`#2"4``\#,``(&S@`#C.8``L9L``/P00`"QWX``J#>``/P!``#:"$` +M`VJ)``/T```#\$(``V@E``-JC0`"I7X``_`"``/T```!QG$``T`1``*P"``` +M\?0``J#>``/P`P`"9F```_0```/P00`"9W```V`1``/T```""(,``X#A``.! +M!@`"81X``X+G``-J1``#@08``^@@``-J1``"L`$``^@0``/H(``#Z#```VI@ +M``-`+```6BL``K0$``/H\``"1$```_`!``*_`0`"I+X``_`!``*_!``",=4` +M`/(G``#R)0`"L/\``K&_``/!(``#:&```K`!``/H$``#Z"```^@P``-J8``` +M"CL``!(,```:"P`"L`(``J#>``/P00`"L`0``X(J``*D/@`#\`$``K,$``.! +M%@`"8`$``K$S``-J8``#0`H``K`!``*Q`@`"L@```K,!``*@*P`#\`(``^@@ +M``/!.P`#:F@``\$.```20@`"0`D``_`!``/H(``"L!,``K$"``.")@`#Z#`` +M`VIP``-`+0``8A$``!(H``*_0``"3T\``_`#``*@S@`#\`$``K((``*P(0`" +ML0(``K,!``-J=```"BL``K`!``/_```"I!X``_`%``*Q!``"L@```K,"``/T +M!``#\`,``K$"``*R#P`"LP$``VIX``-*?``#_P```K`!``*Q`@`"LP0``VI\ +M```!_@`#_P```_\```+`#@``@?X``C'0```")P`#0`H``T`-``*@#@`#\`4` +M`K`!``)`!0`#@`8``_0$``/P`P`"L`0``D`)``.``@`"L0,``F@!```"*P`# +M_P```_\```*D#@`#\`L``!(H``*P(P`"L0,``K,!``-J=``#2GP``_\```*P +M`0`"L00``K,$``-J?``#2F0``K2````1[P`"0`0``F`(``.B(@`"LP$``VID +M``(PE0`",*(```'_``/_```#_P```J`.``/P3@`#0"P``KP$``/``/P`0`#Z/```]CP``*\"0`"OS\``DL?``(O"P`#Z/```/G_```!_@`# +M_P```_\```+`#@``@?X``T`E```:$``"L@0``D(@``*@W@`#\$$``Z,R``*Y +M`@`"29,``F(I``*Y@``"294``F(I``*YA@`#Z(```J`I``/P00`#P8X``,': +M```)_0`#0"X``_\```*@`0`"!Z(``K`!``)!"``#\`4```)```/_```#_P`` +M`J`.``('H@`#2G0``'HH``/_```#_P```\$O``-J=``",=````(G``-`"@`# +M0`T``J`.``/P!0`"L`0``D`%``.``@`#]`0``_`"``*P$``"0`D``'G:``*Q +M0P`#_P```J#^``/P00`"L2,``F@!```"*P`#_P```_\```*@#@`"!]0``!(H +M``*P0P`"L00``K,!``-J=``#2GP``_\```*P`0`"L04``K,$``-J?``#2F0` +M`K2````1[P`"0`0``F`(``*X(``"8`@``KB_``)`"``#HB(``\$^``-J9``# +M]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``/!/@`#:F0``C"5``(P +MH@``0A```K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```'']0`#0`X``K`0 +M``/_```"00D``J`0``(']0```B<``_\```/_```"P`X``((G``*Q`@`"I`$` +M`@``/P1@`#Z/```K$D``+(@0`#V(```L`!``/8 +M@0`",(P```'^``/_```#_P```L`.``"!_@``>=H``C'0``*@_@`#\$4``K`/ +M``/!$``#P2```\$P``-J@``#0`H``K!```/_```"0`D``Z`"``*Q`P`":`$` +M``(K``/_```#_P```J0.``/P"P``$B@``K!#``*Q!0`"LP$``VIT``-*?``# +M_P```K`!``*Q!@`"LP0``VI\``-*9``"M(```!'O``)`!``"8`@``Z(B``*S +M`0`#:F0``C"5``(PH@`#0"4``$(0``*P(``"0`4``_!(``*P`@`"H-X``_!! +M``.``@`"0`@``_`"``/T```!R&4``!'^``*P@``"LP,``J`C``/P0P`"0`4` +M`_`!``(QE@`#0"X``_\```*P"``"00@``J`0``((90`"L(```D$(``/P!0`` +M`D```_\```/_```"H`X``@AE```")0`#_P```_\```/H$```BB4``J0.``(' +M=P```>\``$'Y``/_```#_P```]@```/<@```>D(``K````/8`0`"L`$``]P! +M``-`#0`"O2```_\```)-U0`"IMX``_`#``(O*P`#]`0``_`*``*P?P`"L?\` +M`K+_``-H8``#:&L``!'E``*SP``#Z-```V!,``(O9@`"L`$``^@0``/H(``# +MZ#```VI@``-*9``"M(```D`$``-J9```(?4``_\```-("``#_P```\$$``-H +M"``#[````^@```/H$``"H-X``_`#``-I'``#]`0``_`!``-I-``#[````&H_ +M``/_```#_P```J#>``/P`P`"NV(``_0```/P00`"NV@``_\```/_````V?P` +M`C*.``/H```",#L``KL"``#:/@`#2`$``K"_``)$0``#:`$``TF8``*T#P`" +MM?T``F`$``)!%0`#P2X``\$^``*@W@`#\`$``X,P``-H,``#2`@``K1```"! +M]0`"8`0``V@(``/H```"L6```^@@``/H,``#::```^@```*Q$``#Z"```^@P +M``-J1``"L`$``^@0``/H(``#Z#```VI@``*_`@`",=4``^@```/````#P1`` +M`K+]``-H8```"CL``!(,```:"P`"L`H``J#>``/P00`"L`P``X$6``)@`0`# +M@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+GL``VAK``/_ +M```#_@```C'^``-*8```,@P``#H+``*T]@`"M0,``X9J``)B)@`"I'X``_`! +M``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``#:F@` +M`K"````20@`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`" +ML0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`@`"L0(``K,$``-J?``"L/\``K&_``/!(``#:&```^AP``-*9``"M(```D`$ +M``/H(``#Z#```VID``-*9``"M(```!'\``)`!``"M`,``F`$``*S$``#:F0` +M`C"5``-*9``"M`@``D1```)G=``"I7X``@E<``/H```",#L``J#>``/P`P`# +M2"(``_0```/P00`#2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H +M(@`#:HH``_0```/P0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R2$``T`2 +M``#Q]``"OP0``J#>``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R5P` +M`K`!``/H$``#Z"```^@P``-J8``#2F0``K2```)`!``#:F0``"'U``/_```# +M2`@``_\```/!!``#:`@``^P```!J/P``\?\``^@```""$P`#0`@``T`M``*X +M0``"N0@``DH(``.JJ@`"2TD``ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`! +M``*S!@`#0"T```H1``*P0``"0$```_!!``/H,``"01X``_`!``/H,```FA(` +M`"'T``/H4``#_P```*(9``"I]```:C\``_\```/_```"H-X``_`#``!9\0`# +M]````_!#``!9\``#_P```_\```#9[P`#2````X3J``/`1``#_P```D`$``-H +M```#2`0``\!^``/_```#_P```D,W``-H!``#0"P``%HK``*T!``#Z/```D1` +M``/P`0`"OP$``DN^``*@O@`#\`,``C#]``/T```!R;4``K_+``(S00``\B8` +M`/(E``*P_P`"L;\``\$@``-H8``"L`$``^@0``/H(``#Z#```VI@```*.P`` +M$@P``!H+``*P`@`"H-X``_!!``*P!``#@18``F`!``-`%0`#@BH``K&```)B +M(0`"I#X``_`!``*S!``"MO```D1&``*Q"``"810``VI@``-`"@`"L`$``K$" +M``*R```"LP$``J`K``/P`@`#Z"```\$[``-J:``"L`$``!)!``)`"0`#\`$` +M`^@@``*P$P`"L0(``X(F``/H,``#:G```T`M``!B$0``$B@``K]```)/3P`# +M\`,``J#.``/P`0`"L@@``K`A``*Q`@`"LP$``VIT```**P`"L`$``_\```)! +M$``"I!X``_`%``*Q!``"L@```K,"``/T!``#\`,``K$"``*R#P`"LP$``VIX +M``-*?``#_P```K`!``*Q`@`"LP0``VI\```**P`#_P```_\```)!'@`"I!X` +M`@I4```"$P`#_P```_\```+`#@``@A,``C'0```")@`#0`H``T`-``*@#@`# +M\`4``K`"``)`!0`#@`0``_0$``/P`P`"L`@``D`)``.````"L0,``F@!```" +M*P`#_P```_\```)`#@`"I`X``_`+```2*``"L",``K$#``*S`0`#:G0``TI\ +M``/_```"L`$``K$$``*S!``#:GP``TID``*T@```$>\``D`$``)@"``#HB(` +M`K,!``-J9``",)4``C"B```!_P`#_P```_\```*@#@`#\$X``T`L``*\!``# +MW,```K_```*@W@`#\`$``K^```/8\``#C.0``K\_``)+'P`"+PL``^CP``#Y +M_P```A,``_\```/_```"P`X``((3``!:*P``>B4``K@(``)*O@`"H*X``B@``_\```/_```#P2\``VIT +M``(QT````B8``T`*``-`#0`"H`X``_`%``*P"``"0`4``X````/T!``#\`,` +M`K`@``)`"0`#H````K%#``)H`0```BL``_\```/_```"0`X``J`.``(*O``` +M$B@``K!#``*Q!``"LP$``VIT``-*?``#_P```K`!``*Q!0`"LP0``VI\``-* +M9``"M(```!'O``)`!``"8`@``K@@``)@"``"N+\``D`(``.B(@`"L00``\$^ +M``-J9``#]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``*S`0`#:F0` +M`C"5``(PH@``6BL``KH!``/_```"2[H``J"Z``/P0@`#]``````/P00`#@`(``D`(``/P`@`#]````\``D`$ +M``)@"``#HB(``K,!``*Q```#:F0``C"5``(PH@``6BL``KH#``*Y`0`#_P`` +M`DBZ``*DB0`!RU<``KD$``/_```"2+H``J"*``'+.0```B4``K((``*S```# +M_P```J0"``'+5P`"H`X``_!#``":)0`#]````D$``K````/8`0`"L`$``]P!``-`#0`"O4```_\` +M``)-U0`"IMX``_`#``(O*P`#]`0``_`*``*P?P`"L?\``K+_``-H8``#:&L` +M`!'E``*SP``#Z-```V!,``(O9@`"L`$``^@0``/H(``#Z#```VI@``(QT``# +M[````&H_``/_```#_P```J#>``/P`P`"NU,``_0```/P00`"NUL``_\```/_ +M````V?P``T`0``*[#P`#2"D``J#>``/P00`#2"T``K\$``)`"P`#JP(``P_[ +M``.,]@`";,\``X_V``-)Z``"HTP``_`$``,$3``#!5\``_0```/P10`#A.8` +M`X56``.E5@`"950``F1.``/!!``#P14``J#>``/P!``#:"D``VGH``/T```# +M\$(``V@M``-I[``#Z````C!/``-(`0`"L+\``D1```-H`0`#Z````K%```/H +M(``#Z#```VI$``*P`0`#Z!```^@@``/H,``#:F```K\"``(QU0``"CL``!(, +M```:"P`"L`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&$``)B(0`"I#X` +M`_`!``*S!``"L1@``VI@``-`"@`"L`$``K$"``*R$@`#Z#```VIH``*P@``` +M$D$``D`(``/P`0`#Z"```K`3``*Q`@`#@B8``^@P``-J<``"L"$``K$"``*R +M`0`"LP$``VIT``*P`0`"L0(``K(/``*S`0`#:G@``TI\``/_```"L`(``K$" +M``*S!``#:GP``^@```/````"L;\``\$@``-H8``#Z'```TID``*T@``"0`0` +M`VID``-*9``"M(```!'\``)`!``"M`,``F`$``*S$``#:F0``C"5``-*9``" +MM`@``D1```)G=``"I7X``@P\``/H```",$\``J#>``/P!``#2"H``TGH``/T +M```#\$(``T@N``-)[``"O!$``K\0``+)GP`"R(P``\$(``/!&0`"H-X``_`$ +M``-H*@`#:>@``_0```/P0@`#:"X``VGL``*[`0``VCX``^AP``.+Y0`#B[8` +M`J6+``/P`@`#]````\``K#_``*QOP`#P2`` +M`VA@``*P`0`#Z!```^@@``/H,``#:F````H[```2#```&@L``K`"``*@W@`# +M\$$``K`$``.!%@`"8`$``X(J``*Q@``"8B$``J0^``/P`0`"LP0``T`5``*Q +M"``"MO```D1&``)A%``#:F```K`!``*Q`@`"L@```K,"``-J:```$?L``K`3 +M``*Q`@`#@B8``^@P``-J<```$B@``K`A``*Q`@`"LP$``VIT``*P`0`"L0(` +M`K(/``*S`0`#:G@``TI\``/_```"L`$``K$"``*S!``#:GP``KP$``/>\``&'[``*[&``#V/```B\+```!V0`#0"4``K\0``+`#@``@=D``D]?``/P +M`P`"+6@``_0```',J0`"OP@``J`.``/P`0`#P?X``C,+``-*@``"H/X``_!! +M``-JA```8>\``K"```/H\``"H<```_!!``/!_@`"+1L``C'0```1[P`#Z!`` +M`K`C``.B(@`"LP$``VID``(PE0``8=D```'O```)^0`#0"8``K(0``/8```# +MW!```'G[``*P```#V`$``K`!``/<`0`"0BD``_!%``.O\``"H,X``_`"``/[ +M```#^P$``]">``/[```"I2X``_`!``/[```#U)\``_L!``*E+@`#\`$``_L! +M``,/_@`"#,L```'9``/_```#_P```L`.``"!V0``8>\``K"```/!_@`"H<`` +M`_!!``/H\``"+1L``C'0```1[P`"L`,``^@0``.B(@`"LP$``VID``(PE0`" +M,*(``T`E```!V0`"L0,``K((``*S$``"0S4``_`"``)")0`#\`(``J4!``', +ME@``8?D``%GO``/_```#W,```]BP``*P```#V`$``K`!``/<`0``>?L``T`- +M``*]0``#_P```DW5``*FW@`#\`,``B\K``/T!``#\`H``K!_``*Q_P`"LO\` +M`VA@``-H:P``$>4``K/```/HT``#8$P``B]F``*P`0`#Z!```^@@``/H,``# +M:F```C'0``/L```"O!$``J#>``/P!``#2,P``TC1``/T```#\$(``TCL``-( +M\0`"+5,``J#>``/P!``#:,P``VC1``/T```#\$(``VCL``-H\0`"H-X``_`$ +M``-(U``#2-D``_0```/P0@`#2/0``TCY``(M4P`"H-X``_`$``-HU``#:-D` +M`_0```/P0@`#:/0``VCY``*@W@`#\`,``TC<``/T```#\$$``TC\``*@_@`# +M\`0``L`,``+!'``#]````_!"``,`#``#`1P``J#>``/P`P`#:-P``_0```/P +M00`#:/P``^P```*@_@`#\`H``L`,``+!'``"PBP``L,\``+$3``"Q5P``L9L +M``+'?``#]````_!(``,`#``#`1P``P(L``,#/``#!$P``P5<``,&;``#!WP` +M`^P```*P?P`"L?\``K+_``-H8``#:&L```GE``/H```#H`,``]P```/8$``# +M0#$``K\#``*\`@`"IOP``_!!``/!!P`"H/P``_!!``/!!@`"H/X``_!!``/! +M!0`"H?X``_!!``/!!``#P1```\$@``/!,``#_@```]0>``-H:P`#^P```P_^ +M``(-=0`#0#4``K\#``/_```"IOP``_!!``/!!P`"H/P``_!!``/!!@`"H/X` +M`_!!``/!!0`"H?X``_!!``/!!``#P1```\$@``/!,``#_@```]0>``-H:P`# +M^P```P_^``(-C0`#0#@``T`]``/_```#:H0``VJ!``/L```#85```V%5``-A +M6@`#85\``TA4``/_```#Z#```Z,S``-H5``#:&L``TA5``/H```#Z'```K+O +M``*Q_P`"L+\``VA@``-H:P`#27P``K0$``)A%``#:7P``TD\``/_```"81X` +M`VD\``-*E``#03D``_\```/_```"IC<``_`'``*F)@`#\`4``J85``/P`P`" +MI00``_`!``-A.``#8/P``_\```/^```#_P```TAD``*T$``"0B0``J`D``/P +M0P`"+A4``_0```'-T``"L/\``K'_``*R_P`"L_\``VJ0``-)/``#P$X``D$4 +M``-I/``#2%0``K4_``)#4P`#:%0``^@```"!]```@AH``((;``-(9``#C.H` +M`/(5``),#``#\$@``T@T``/_```#@`@``Z`,``*@#@`#^`$``@WQ``""%0`# +M^`,``TA5``/H```#AP<``VA5``-)/0`"OQ```D1/``/P!``"O_\``BY[``*_ +M4``"+GL``Z=P``,'?@`"#@<``\`@``/`$``#P````VA@``-H:P`#H!```VA@ +M``-!4``#054``T%:``-!7P`#[````_@#``-)T``"N`@``DDX``*@F``"#F@` +M`TG4``*T$``"0S0``J`T``(.1``#2`@``K@(``)@"``#:`@``T@H``*X(``" +M8S@``T@M``-H*``#:>@``F=X``-H+0`#:>T``TC(``*X^P`"0B@``VC(``-( +MF``"N"```F`(``-(L0`#:)@``F1(``-HL0`#P0X``\$>``/!+@`#P3X``V,P +M``-C<``#8S0``V-T``-C.``#8W@``_0```'.:``#2`@``KCW``)`"``#:`@` +M`T@H``*XWP`"0S@``T@M``-H*``#:>@``D=X``-H+0`#:>T``TC(``*X!``" +M8B@``VC(``-(F``"N-\``D`(``-(L0`#:)@``D1(``-HL0`"L`,``\$0``/! +M(``#P3```V,P``-C<``#8S0``V-T``/!+@`#P3X``V,X``-C>``#27P``K3[ +M``)!%``#:7P``VAK``/L```#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(` +M`VC*``)H(0`#:,H``\&"``-HR@`#[````_@#``,/_@`"#GP``^P```/H```# +MP!```\`@``.@$``#:&```VAK``/!#@`#Z!```^@@``/H,``#I!,``]@0``/< +M0``#_@```]0>``-H:P`#::0``^@```/^```#U!X``VAK``-II``"H-X``_`# +M``-"8``#]````_!!``-"7``#0ED``J#>``-II``#\`,``T)H``/T```#\$$` +M`T)D``-IH0`#_@```]0>``-H:P`#:&L``^P```/H```#P"```\`0``.@$``# +M:&```VAK``-"5@`#P0X``^@0``/H(``#Z#```Z03``/8$``#W$```]0>``*_ +M`@`"+GL``VAK``-II``#::(``^@```/_```#U!X``K\"``(N>P`#:&L``VFD +M``/H```#P"```\`0``/````#:&```VAK``/L```#:&L``K!_``*Q_P`"LO\` +M`VA@``*Q#``#Z````Z`#``/<```#V!```^@```/H$``#Z"```^@P``/^```# +MU!X``VAK``/[```#^P```XCC``/X`P`#_@```]0>``-H:P`#^P```PB.``(. +MX``#[````"'Z``/H4``#Z&```^AP``*Y"``"N,```]R!``/8D0`#0E```_@# +M``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`#:&L``K09``/^```#U%\` +M`VAK``-)I0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``# +M"9X``@\'``-II0`#[````J&^``/P"@`#T!X``P^^``/X`P`#``X``P$>``," +M+@`#`SX``]0>``,/_@`"#Q```_L```,,S@`"#PL``^P```*AO@`#\`H``]`> +M``,/O@`#^`,``L`.``+!'@`"PBX``L,^``/4'@`##_X``@\@``/[```##,X` +M`@\;``/L```#T)X``]`?``*\/P`"2(P``DF<``)*K``"2[P``D0,``)%'``" +M1BP``D<\``*\(``"P(0``Z````*C2``#\$$``L`,``+!E0`#H1```J-9``/P +M00`"P1P``L*F``.B(``"HVH``_!!``+"+``"P[<``Z,P``*C>P`#\$$``L,\ +M``/HT``#C.D``P2```+HC0`#!9$``NF=``,&H@`"ZJT``P>S``+KO0`#8FX` +M`DB,``))G``"2JP``DN\``/4G@`#0FX``F1%``)D1@`"9$<``@]-``!J/P`# +M^P```_L!``,/_@`"#RL``^P```/0G@`#T!\``KP_``)(C``"29P``DJL``)+ +MO``"1`P``D4<``)&+``"1SP``KP@``+`A``#H````J-(``/P00`"P`P``L&5 +M``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`#\$$``L(L``+#MP`#HS`` +M`J-[``/P00`"PSP``KP'``*CW``#\$X``W!,``-03@`#_P```_\```/^```# +MU!X``VAK``/[```#<$X``U!,``/_```#_P```_0$``/P"``"O`@``J3<``/P +M`0`#:H0``KP)``*DW``#\`$``VJ```*P_P`"L;\``K+_``-H8``#^P```_L! +M``+-W@`"IM\``@]F``-*9``"M(```D`$``-J9``"L````K$```*R```"LP$` +M`VIT``*P,0`"L08``K($``*S```#:G@``TI\``/_```"L`$``K$!``*S```# +M:GP``TID``*T@``"0`0``K0#``)@!``#:F0``C"5``-*9``"M(```D`$``-J +M9```:C\``C-L``/L````6?8``&(^``/_```"H;X``_!"``#Q]``#[````J'. +M``/P00`#"[X``PS.``#9]@``XCX``TI```!:%@`#_P```_\```*@O@`#\$(` +M`Z````.B(``#T%X``&(*``!9\@`#H@(``D`)``)"*0`"I8X``@_U``,(C@`" +MH`T``_`+``!"!P`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$ +M3P`#P50``J6N``(0!0`#"JX``J`M``/P"P``4@<``L9O``/!=@`"H+X``_!& +M``/47@`"QF\``\%V``/47@`"QF\``\%V``/47@`##,X``A`&``)KB@`"#\H` +M`^P```-"<```4A8``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``" +MH6@``_!!``+&:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,& +M:``#`B@``P,X``,*K@`"$!D``\%4``/!=@`#U%X``V)P``/L```#P6(``P9N +M``/<$``#V````]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X` +M`_L```,&;@`"$"X``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``# +M:1```VD4``-I&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I +M-``#[````\$0``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC< +M``/T```#\$4``VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4` +M`D$#``-)T@`#_P```D`*``-)P@`"I1```_`!``-)Q@`#[````K!_``*Q_P`" +MLO\``VA@``-H:P`#Z````^@0``/!+@`"LS```VFD``/H```"L3```^@@``/H +M,``#Z$```Z5#``/80``#W%```_X```/4'@`#:&L``_L```/[```"L!(``^@0 +M``/^```#U!X``VAK``,(C@`"$(8``^P```/0G@`#^P```_\```/_```#U)\` +M`_L!``,/_@`"$(P``^P```/X`0`"OP0``TID``/_```#_P```D$/``(0EP`# +M^`,``VAK``/_```#_P```_X```/L```#2F0``_\```*_"``"00\``J`?``(0 +MPP`#0!(``K40``*E)0`#\`0``K\"``)JKP`#]````=#```+$50`"I20``_`$ +M``*_`@`":[\``_0```'0P``"Q$4``J4D``/P!``"OQ```FJO``/T```!T,`` +M`K\0``)KOP``\?0``V`2``(PQ``#[````TIP``/_```#P<(``T`N``*P`0`# +M:J@``_\```/_```#_P```TJL``*T`@`#:JD``\````/`$0`#P"(``\`S``-* +MK0`"OY```J#/``/P!0`#P$0``K\/``)/3P`#]````_!!``/`]``"H-X``_`+ +M``-`&0`#_P```_\```)D0``"95$``F9B``)G4``K#```/<```#V!```J#^``/P!``#Z````^@0``/H(``#Z#```J#^ +M``/P1``"L%4``\$0``/!(``#P3```J#^``/P!``"M/\``\%4``/!9``#P70` +M`J#^``/P1``"M*H``\%4``/!9``#P70``KP'``*C_@`"$7D``$(-``/_```# +M_P```J".``(1/P`"H-X``_`#``-`0@`#]`0``_`!``-`1@``ZC\``&H.``*D +MW@`#\`0``\"(``/`F0`#P*H``\"[``)@"``"81D``F(J``)C.P`"9$@``F59 +M``)F:@`"9WL``&H_``/_```#_P```_X```/4'@`#:&L``_L```,,S@`#_@`` +M`]1>``-H:P`#^P```PS.``(1/P``0@T``&(.``/_```"H(X``A%D``-`2@`" +MI,X``_`$``/`B``#P)D``\"J``/`NP`"I-X``_`"``/!B@`#P9L``KH/``)* +MJ``#BZ8``FJK``*[\``"2[@``Z>V``)KMP`#]`0``_`#``/H8``#Z*```^BP +M``*T\``"8$H``\$0``/!(``#P3```VJ$``*@_@`#\`,``K3P``/T!``#\`$` +M`K0/``)@2P`#P1```\$@``/!,``#:H```^P```/^```#U!X``VAK``/[```# +M#,X``KD#``*@^0`#\$0``^A```/H4``#Z&```^AP``/^```#U%X``VAK``/[ +M```##,X``A&%``*P\``"L?\``J#Y``/P0@`#Z````^@0``/!(0`#P3$``VJ$ +M``-J@``#[````K!_``*Q_P`"LO\``VA@``-H:P``">4``K#```/<```#V!`` +M`K3_``/!9``#P70``KP'``/^```"M?\``]1>``-H:P`#^P```PS.``/^```" +MM>\``]1>``-H:P`#^P```PS.``(1HP`"M?\``VJ%``*P\``#P1```\$@``/! +M,``#:H```TIB``(QT``#Z/```C'<``-J8@``">4``K#```/<```#V!```K3_ +M``/!5``#P60``\%T``*\!P`#_@```]1>``-H:P`#^P```PS.``(1Q0`"L/\` +M`K&_``/!(``#:&```^P```-*9``"M(```D`$``-J9``#[````K`$``*@\``# +M\`,``C#]``/T!``#\`$``BUH``/H```#P````\$0``*R_0`#:&````H[```R +M#```&@L``K`*``*@W@`#\$$``K`,``.!%@`"8`$``K$6``*D/@`#\`$``K,$ +M``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`"L@0``F(F``-J8``#C^$` +M`BY[``-H:P`#_P```_X```/L```#2F```_\```/H,``"8`X``VI@``-*9``" +MM/(``D`$``-J9``#[````&H_``-`!``#_P```K@$``)%X``"H%X``_!$``*@ +MW@`#\$(``T`D``/_````8?@``_\```/_```#W,```X_J``*@W@`#\`$``^CP +M``/8\``#C.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<` +M`D`(``/P0P`"+PL``_0```/P00`"+QL``D1N``/P"0`#Z,```ZMB``.E8``" +M15X``_!#``(O"P`#]````_!!``(O&P`#[````TC```-(Q0`#Z!```^A0``*@ +MW@`#\`@``VC````",0``"C```_\```/_```#:,```_0```/P1@`#:,4``"(O +M```J+@`#_P```_\```-HQ0`#[````&H_``/_```#_P```%'Y``*@W@`#\`,` +M`%GQ``/T```#\$$``%GP``/_```#W*```]BP``-`!@`#_P```_\```)`Z``# +M\`,``J#>``/P00`#0"8``_\```/_```#24$``J`.``/P0P`"H-X``_!!``/! +M10`"14X``_!#``.,Y``#]````_!!``.,XP`#B9@``ZJ<``*@K@`#\`,``B\+ +M``/T```#\$$``B\;``-`!@`#_P```_\```-)00`"0(X``J`.``/P0P`"H-X` +M`_!!``/!10`#Z,```ZM"``)%3@`#\`<``Z5```)%7@`#\$,``B\+``/T```# +M\$$``B\;``/L```"H-X``_`#``-((0`#]````_!!``-()0`#_P```KL!``.B +M9@`#@68``Z$6``.'=@`"8"<``P`+``.G!@`#@@8``F8A``*@W@`#\`0``V@A +M``-JB0`#]````_!"``-H)0`#:HT``^P```./[0`"+GL``^@P``."X``#Z!`` +M`^@```-H,``#C^T``BY[``/H\``#27```^AP``*V`0`#P5$``\%```-H,0`" +MN/P``\%3``/!0@`"15@``TET``(R^``#:#$``\%1``/!0``",O@``V@Q``/! +M4P`#P4(``TF8``(R^``#:#$``\%1``/!0``",O@``V@Q``/!4P`#P4(``TF< +M``(R^``#:#$``\%1``/!0``",O@``V@Q``/!4P`#P4(``TCH``(R^``#:#$` +M`\%1``/!0``"MQ```C+X``-H,0`#P5,``\%"``(R^``#:#$``^P```-)/0`" +ML`@``D`$``/P!0`#2J0``_\```/_```"L@,``VJD``*P!``"000``J`0``/P +M1@`#2,```TC%``*Q`P`"M0,``VC```-HQ0`#[````_\```/_```#_P```^P` +M``-A2``#84$``V%&``-B?P`#P0X``^@0``/H(``#Z#```VCH``/H```#_P`` +M`VCH``-!2``#_P```^P```*P?P`"L?\``K+_``-H8``#:&L```GE``/H```# +MH`,``]P```/8$``"O`,``K#W``*@_@`#\$$``K!_``/!$``#P2```\$P``*T +M_P`#P50``\%D``/!=``#_@```]0>``-H:P`#H`$``Z$1``.B(0`#HS$``_L` +M``/^```#U%X``VAK``/[```##,X``A,A``*P_P`"O`@``\$0``/!(``#P3`` +M`VJ```*D_@`!TSL``J#\``/P`@`#:H0``^P```*P]P`#H0$``Z(1``.C(0`# +M:H0``^P```-)/0`#_P```KB```)D2``#:3T``K`!``*Q`@`"LC\``D(O``*S +M```#:F@``K````*Q```"L@```K,"``-J=``"L0$``K((``*S```#:G@``K`! +M``*R```#:GP``!'O``*PP``"0`\``Z`"``)@#@`"L0```Z(B``*S`0`#:F0` +M`K#_``*QOP`#P2```VA@``/_```#_P```C"5``*X?P`"1$@``VD]``/L```# +MZ````^@0``*R`P`"LP```V@P``/L```#Z````((_``(B^@``\C\``B+Z``(S +MJ``"+FX``TF8``*T]P`"010``VF8``/!+@`#Z#```V@P```"%P`#@>```^A` +M``*@`0`#\`$``\%.``(TL@`#2`@``KC^``)!&``#:`@``^@```""/P`")%H` +M`/(_``(D6@```A<``X'@``/_```"I!```_`"``/!3@`"-+(``C0"``-`+``" +MN$```KF```*[_P`#2J4``D@8``/P`0`"N\\``DD9``/P`@`"NC\``DNZ``)% +M6P`#:J4``_0```'";``#2=$``KA```)$>``#A$```TB<``.%X@`"8`0``F`% +M``-HG``#:*```VBT``-HN``#23@``X7A``/`50`"0B4``VDX``-J7``#H.$` +M`X'A``/H,``#@N@``X7E``(P*@`#0Z8``X#H``/_```"2(4``FB```/!F``# +MP:@``\&X``-CI@`#8^8``^@```/HT``",#L``\'>``(P.P`",&$``X3B``/! +MR0`#Z````X'A``.#Y``"PC$``P(N``+#/@`"1$D``_`!``.#Y0`#Z%```C`J +M``.`Z@`","H``XCE``.$X``"1$P``_`"``.(Y``"R(X``\&8``/!J``#P;@` +M`V,J``-C:@`",&$``X'B``.@X0`#HY8``X+D``+"+@`#Z%```C`J``.@XP`" +M,"H``C!A``.`Y0`"0*```\$0``/!(``#P3```V2H``-DZ``#@.```H((``)" +M`@`#@B0``)'C``/L```",&$``TEP``)$C@`#\$,``K7S``)")0`#:7```^AP +M``/!;@`#P5,``\%"``-H,0`"1)X``_`&``-)G``#I.$``F(D``/!4P`#P4(` +M`V@Q``)$C@`#\$T``TF<``.$Y0`#I><``D`$``)!%0`#I(@``X1```.%1@`" +M8`4``F$4``/H,``#P2X``V@P``-#I```(>,``K4/``/_```"0`4``F`$``/! +M$``#P2```\$P``-CI``#8^0``X&$``.@&``#@@8``F`"``/HT``",$\``\'> +M``(P3P`#2)```Z2Z``.EYP`"014``F$4``-HD``#:*@``VB4``-HK``#H*8` +M`\$0``/!(``#P3```V0D``-D9``#BK8``T@A``*X`P`"9F@``KD/``*[_@`" +M1FD``F9J``)'>P`#:"$``VJ)``-H)0`#:HT``T@(``-((0`"81X``V@(``-( +MR``"N$```KD_``)@"``#:,@``D`)``-HR``"95X``V@A``-JB0`#:"4``VJ- +M``)%6P`#:"$``VJ)``-H)0`#:HT``^P```-`+``"N$```KF```/HL``#2J4` +M`D@8``/P`0`"NS```DD9``/P`@`"NL```FNZ``)E6P`#:J4``TB<``-(H0`" +MO'L``D`,``)$3``#:)P``VBA``-(M``#2+D``D`,``)$3``#:+0``VBY``-( +MD``#A.(``Z7G``)!%0`"810``VB0``-HJ``#:)0``VBL``-).``#A>$``F(E +M``-I.``#:EP``Z#A``.!X0`#@^@``X+H``.%Y0`","H``^@```.!X0`#@^0` +M`L(Q``/H,``#Z%```C`J``.`Z@`","H``T@(``-((0`#J.T``D$8``-H"``# +MJ.L``D9H``/`/@`"15,``V@A``-JB0`#:"4``VJ-``/H0``"-+(``^P```-) +M=``#P6X``^AP``.(2``#P%X``X59``)")0`"8B@``VET``/!0@`#P5,``V@Q +M``/L```#2`@``KC^``)!&``#:`@``TA4``*\8``"8BP``VA4``-)=@`"O!`` +M`F2L``/!6P`#P6X``^AP``-H,0`",O@``TA4``*\GP`"0BP``VA4``/!2@`# +M:#$``C14``/L````\=X``/'=``/!_0`#P4``_0$``(5&```T=\``J#>``(5 +M/@``T>```LW>``/T!``"%.\``$'@``/_```#_P```J"H``(590`"H:@``_!( +M``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@``VGE``-()0`#`Z@``X,P``)G``#8!$``\'?``-) +MF``#A>(``\!5``)!%0`#:9@``^@P``/!+@`#:#```T@(``/_```#A,@``F`$ +M``-H"``#^`,``^P```/_```#_P```&H_``/H````@AD``('<``*P`0`"L1$` +M`K(0``-J1``"L1```^@@``-J1``#0"0``J#>``/P`P`"NU,``_0```/P00`" +MNUL``-G\``)`#@`#\$L``T`0``*\!``#W,```X_J``*@W@`#\`$``^CP``/8 +M\``"O`D``\&Q``(O"P`#0"0``_\```*\`@`"0`P``_!+``-`$``"O`0``]S` +M``*_P``"H-X``_`!``*_@``#V/```XSD``/!L0`"+PL``TF8``.(Y0`"M?T` +M`\$^``*@W@`#\`$``X,P``/!+@`"8`@``D$5``-H,``#2`@``K1```"!]0`" +M8`0``V@(``-(`0`"L+\``D1```-H`0`#Z````K%```/H(``#Z#```VI$``-` +M+@`"L`$``^@0``/H(``#Z#```VI@``(M:``"L`$``K$"``*R!@`#Z#```VIH +M```200`"L!,``K$"``.")@`#Z#```VIP``*P(0`"L0(``K($``*S`0`#:G0` +M`K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P```"L0```K,$``-J?``" +MOQ@``C91``(V?@`"OP```C'5``-*<``#_P```_\```*RD``#:G```K\3``(V +M40`"-GX``T`D``/_```#_P```D`.``/P2P`#0!```KP$``/ +M``/P`0`#Z/```]CP``*\"0`#BQ```B\;``-`)``#_P```KP"``)`#``#\$L` +M`T`0``*\!``#W,```K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(O&P`# +M2G```_\```/_```"LH```VIP``*_&``"-E$``C9^``*_```",=4``TIP``/_ +M```#_P```K*0``-J<``"OQ,``C91``(V?@`#0"0``_\```/_```"0`X``_!+ +M``-`$``"O`0``]S```./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+PL` +M`T`D``/_```"O`(``D`,``/P2P`#0!(``KP$``/``/P`0`" +MOX```]CP``.,Y``#P;D``B\+``*P`0`#Z!```^@@``/H,``#:F```TID``*T +M@``"0`0``VID```A]0`#_P```T@(``/_```#P00``V@(``/L```#Z````\`` +M``*QOP`#P2```VA@``*P`0`#Z!```^@@``/H,``#:F```TID``*T@``"0`0` +M`VID```*.P``$@P``!H+``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`" +ML80``F(A``*D/@`#\`$``K,$``/!'P`#:F```TID``*T@```$?P``D`$``*T +M`P`"8`0``K,0``-J9``",)4``K\(``)/\``#\`$``/(9``/L`````AD``_\` +M``/_```"I0X``_`!``/L```#Z````((9``-`$@`#_P```_\```)$C@`"H$X` +M`_`!``#Q]``"OT```J#>``/P`P`":J\``_0```/P00`":[\``V`2``(PQ``` +M>=P``_\```-`*``"H/X``_!!``/L```"H-X``_`%``+`#@`#\$$``L$>``/T +M```#\$,``L(N``/P00`"PSX``V`H``#QW``#[`````(4```*0```:C\``_\` +M``)``0`"H`X``_`!``/L```#2)P``TBA``-*2@`"H-X``_!#``-(M``#2+D` +M`TI.``*\$``"8BX``F9N``)HC``":9P``J#>``/P!0`#:)P``VBA``-J2@`# +M]````_!#``-HM``#:+D``VI.``/HP```X=L``K`0``*Q```"LA```K,```-B +M=``"L(```]@!``*P```#W`$``K`2``*Q`@`"LA(``K,"``-B=``"L!```K$2 +M``*R$``"LQ(``V)P``-B1``"L0(``K,"``-B3``#8D@``T`L``/_```#_P`` +M`^@@``/H,``#8"P``^@```/H$```8=L``V`8``-@'``#P8P``\&<``/!K``# +MP;P``C=S``(U=P``8=L``_\```*P```#W````K!```./P@`"P`\``]@```-` +M&``"H-X``_!!``-`'``#0"T``_\```/4'@`#U%\``K\```/<\``"O\```XC" +M``+/^``#V/```\0```/$$0`#Q"(``\0S``*U#P`"1&4``Z5F``*@W@`#\$,` +M`K4/``)$=0`#I78``Z9"``.$2@`#IU(``X5:``/$1``#Q&8``L`!``+`!``" +MPB,``L(F``/$%0`#Q#<``]0>``-"=0`#0G(``K\0``*A!``#\$8``J4)``/P +M!``#P8P``\&0``/!K``#P;```J,)``/P0@`#P:P``\&P``-B<@`#0D8``J$F +M``/P1@`"I2D``_`$``/!C``#P9(``\&L``/!L@`"HRD``_!"``/!K``#P;(` +M`V)&``-"3@`"H14``_!&``*E&0`#\`0``\&,``/!D0`#P:P``\&Q``*C&0`# +M\$(``\&L``/!L0`#8DX``T)*``*A-P`#\$8``J4Y``/P!``#P8P``\&3``/! +MK``#P;,``J,Y``/P0@`#P:P``\&S``-B2@`#8G0``_L!``*Q$``"S,X``.'; +M``*@P0`!UN(``T)P``-"10`#_P```L@"``.H@``"RD8``ZJ@``-"3``#0DD` +M`_\```+)`@`#J9```LM&``.KL``"-W,``^P```-(G``#2*$``J#>``/P0@`# +M2+0``TBY``/!&``#P5H``XF6``.+M@`"81D``F5;``*@W@`#\`0``VB<``-H +5H0`#]````_!"``-HM``#:+D``^P` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/BARTS_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/BARTS_me.bin.uu new file mode 100644 index 00000000000..9bf84808a22 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/BARTS_me.bin.uu @@ -0,0 +1,126 @@ +begin 644 BARTS_me.bin +M?$"``*````#,@`!-@````-1``'\``!ET``*@>X`62?@````````(```71_&X`. +M@``!>'\;@`^```%\?QN`#(```8!_&X`-@``!A'\;@!&```&(?QN`$(```8T4 +MI``(FX``&12D``B```&='F0`_YN``!44I``(@``!G1YD`/^;@``1%*0`"(`` +M`9T>9`#_FX``#12D``B```&='F0`_YN```D4I``(@``!G1YD`/^;@``%%*0` +M"(```9T>9`#_%*0`"!YD`/\J:``\FH#^<13L``A\0T``?$.``'Q#P`"6P``' +MS```3<]!(6G/@2%JS\$A:X````#,`2%L@````,_U``#,``!9A``$G2IH`#R: +M@``$R"@`%X````#40`!_EH#_JWX"0`"$``*6P`X``LP``$&```&KS,$P2I0` +M``#(/``@1*``!E0``$`:H`@F>@````````(```B'`$@@`@``"+\@4`!&```(VR!0` +M$H```CW,P:*D@``"1ASH`#^```)N?,&`"QS0`#\I*``&*2P`%GZN@`?('``3 +MFH``/004`"Z`````S,&BI,`2"`!\04``?0S`!\`2``@56``#%5P`#'Q"``!] +MT<`&$B``%'X>0`=^3H`'SH&BI(````#-@:'^R!0`$000(1B50```R!0`$=11 +M``"`````S,&BI,@4`!($$"$&E4```,@4`!+440``@````,S!HJ3,P:*D!!`` +M`5P``)R#0`,<@X`##(/``M4W0`('^W@"='N`50S``` +M8L_Z``":0```R"0`)\@H`",ZJ``"FH#__\@H`"/`,``!R"@`))J```#(*``D +MSP``6U#8``@4W``8P#X0`"'<@`!]_<`'S8$A@,W!(8'`'@`@42``"!4D`!A^ +M?D`'$S``'GYR0`=]74`'S@$A@LY!(8/-02&$?$"``*````#,@`!-A``$G1QT +M``$<>``"FT```\@,`"J$``-"R!0`+)N```,$$``0A``#4LS!HF#-`:!@A``# +M#P08"8"$``2=S```9,@\`"Z$``,=R!``*L@<`"\=W``!R"0`*)7```G(-``Q +MR#@`,,@\`"Y3=``@?[>`)T>X!53,``!BS_H``)I```#()``HR"@`(SJH``*: +M@/__R"@`(\@H`"6:@```R"@`)8```M#`,``"!9C``!#<``@4X``8S=D``,@< +M`"+()``B'=P/_\W9``%^8D`'SED``M@840/8&%$$B````-@840<;^`#PP#8( +M`)>```/`,`"`B````,`J``3/02%\SP$A?7`!YG`__[('``E@````7Q`@`!\0,``?$$``!DH`#"6@``( +MR"@`)\@D`"B:0```R"0`)YI```#()``HS``#X'Q!0`!\08``%1P`'\S``,?- +M``#(E<```\`<@`#-P2`0X8,```5<(`#,``!-@````-P?00!\0,``?$$``'Q! +M0`!\08``S,``R`!#(#``I +M4-``"!!4``*```05?16`(,`>`"#(#``J4-``"`A4!``15``"?5&`(,W``&+4 +M6@``?$"``*````#,@`!-?$#``!S0``,1*``!E0``"@:H!!^>@```?$&``(`` +M!"U\0<``@``$,WQ!P`"```0Y?$'``'Q!@`!\0<``%-0`$`54H`"`````S94` +M`,`B``0%F*``?:&`!\P9``"```0IR!@`!,`B``3-@276(B`EU\PA``"```0I +MR!@`!,V!(6W-P2%N@``$*<@8``-\0,``@````,Q,`^`@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8` +M#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/ +.!)8`#P26``\$E@`/!)8` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/BARTS_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/BARTS_pfp.bin.uu new file mode 100644 index 00000000000..a410bd76bb0 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/BARTS_pfp.bin.uu @@ -0,0 +1,103 @@ +begin 644 BARTS_pfp.bin +M?$"``*`````$*``!@````.`#``#,@`!`U$``0'Q`@`"@````!"@``1!,``&8 +MP``%')```LQ``"F```-?S$``*ID```4`````S$``*X```U_,0``LS$``+8`` +M`U_,0``N'(P``LR``$"8P``$S$``0(```U_,``!2@``#7\P``%2`````S$`# +M_<@0`"[(#``M41``('S0P"=\Q0`@510`(,T``$/-0`!#T,``0\R``$#,``!` +MS$``0'Q`@`"@````!"@``<@0`"S(#``K41``('S0P"=\Q0`@510`(,T``$+- +M0`!"T0``0GQ`P`#(&``#R!P``\@@``.5@/_"R"0``Y7`_\#(*``=FH``!,P` +M`%78``/`S```0,@H`!;`+@`$R#``#1JH`"=^\L`'SL``0,P``$#-@`!`S<`` +M0,X``$"6@``#SD``0-"``%S,@`!`S```0,S``$!\0(``H`````0H``'($``L +MR`P`*U$0`"!\T,`G?,4`(%44`"#-``!"S4``0M%``$)\0,``R!@``\@<``/( +M(``#R"0``Y6`_YG(*``#E<#_E\@L`_U^+P`1EP```W[BP`%\`L`&SL.BGLP` +M`&S-``!MS4``;<@P`!V;```$S```5=@``\#,``!`R"P`%L`R``7(-``-&NP` +M)W\W``?/``!`T$``0,V``$#-P`!`S@``0,Y``$"6P``#SH``0-"``%S,@`!` +MS```0,S``$!\0(``H`````0H``'(&``5'9@``7Q"0`"5@`+.?$*``,@<`"#` +M-\``?$#``'Q!``!\M(`&P#8``QJX`>B7@``'T$`#X(0``V+,``!_R#@#X)N` +M``#(.`/@F<```,@<`"!\M(`'$-0``GUE0`#-0`!#SH``0\T``$/,@`!`SD`` +M0,Z``$#,P`!`X#H``)>`_U3-``!`?$#``(```*)\00``'(P``IC```G($``< +MF0``!,@<``:$``-ES```4L@8`!6```".'9@``L@0`!Z9`/_\R!P`"(0``V7, +M``!4R!@`%8```(X=F``"'(P``L@0`!V8P``.R!0`29D```3('``'A``#9@%5``&(!```7T5``.```".?9&`!IE`__C('``'S<`` +M0,P``$"```#+S```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/T +MS0`#]LT``_?-``/X@```!5`/_WR!0`19E```3(&``* +MS8``0,P``$"```%$V``(0'Q`P`#($`!'F0#__`````#,@`!`S,``0-1``$!\ +M0(``H`````0H``'($`!&V``'0,T``$"$``%;S0``0,@,`$.4P``*R!0`2(`` +M`50$$``#R!``1M@`!\#-``!`A``!6\T``$#(%`!(G4```,P``&K(*``6'J@` +M`9J```/`*0`!B````,`L`5;.@`! +ME,``",@4`!R9```*R!P`"(0``V7,``!4@``!='`)WU8P`-\W,`@5-`` +M((```97,@`!`?$&``,R``$"```&2S8``0,`9___,@`!`S8.BGGQ`P`!\00`` +M?$%``,S#H?K-`Z'YS4.BG9P/]C`````-```_J`````?$#``,R``$"`````U$``0'Q`P`!\ +M00``?$.``'Q#P``$'``"SX``0L_``$+-P`!"!!P`(,S``$+-``!"S<``0@0< +M``<$(``!?`)``,@4``/(&``#49@`('U90"?(*``#R"P``\@P``/(-``#4NP` +M('ZN@"=3=``@?S<`)W\K0"%^=D`@5J@`/UT`G?65`(%58`"#,``!;S78``,VV``#((`!!F@```,@@`$&` +M```!?$"``'Q`P`!\00``S,`#_LT``__,P`!"S0``0A44`!\9&`#P)UP``7UV +M``:9@``%?5Y`!LP``$*```-?S```3168``$5+``(F8``,1[L``&6```$%3`` +M#(```U_,``!"!!0`(,U``$(?,``!("@``00X`"`$/``'R!0``\@8``/('``# +MR"```WU=0`U]H<`-?5U`!Q80`!\5G``??1T`!GT70`9^DH`&FT``$@NX``2; +MP/_R"_P``<@,`_Z:@``)R!`#_YL``0;,``!-!!0`(,S``$+-``!"@``"0\U` +M`$*6P`#_S```38```U_,``!.FL```\P``$W,``!.EX#]F>.#``"`````W`,! +M_Y9```3,``!.@``#7\P``$+2``!"R`@``\@,``/($``#R!0``\@8``/('``# +MR"0``\@H``,5_``?%K``'W_SP`84\``??_/`!A5P`!]_\\`&?8B``9?```U] +MS,`!?E$``7Z50`%\D(`,?-3`#)K```-\CT`&)+0``9M``-;,``!-@``#7\P` +M`$[(#`/^R!`#_\S``$*```)OS0``0GQ`P`!\00``?$+``'Q#``#`.P`??$-` +M`'^W@`;`/A``EX#]9GT]``=_/P`'&10`.\P``%N50``3R!0`0#%8``*5@/__ +MR!0`0,P``&,A'(``S,$AA +MA``#8LP``%W((``??$#``,`V_P#($``AP#`__WSU0`9]48`&?8&`"IF```A\ +M\X`&XX,``,^@`$^$``-BS```7H````#40`!_@``#7\P``%Z$``-B?$#``!3< +M``B5P``9'-P`$'Q!``"9P``$4%0`((```QW)'0``?14`)\D>``!\0@``?$)` +M`'Q!@`!]Y<`&?>*`$9J`_-Y!K``%FL````KL``$<`(@+L`","_0`G`8P`'P'Y`"`"*0`H`:X`*0%[`"H!H``K +M`9``+P&I`#(!S0`T`S\`-0%_`#D!]@`\`Q$`/P&[`$$"D@!"`KD`0P+#`$0" +MT`!*`MX`50,S`%8#.@!@`(P`80"Q`&(`V0!C`,,`9`##`&4`PP!F`,,`9P## +M`&@`Y@!I`.\`:@$_`&L!#0!L`0T`;0$-`&X!#0!O`0T`<`$2`',`^P!T`/L` +M=0%F`'L#3`````4````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +9!0````4````%````!0````4````%````!0`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/BTC_rlc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/BTC_rlc.bin.uu new file mode 100644 index 00000000000..6b0c5ef8fba --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/BTC_rlc.bin.uu @@ -0,0 +1,72 @@ +begin 644 BTC_rlc.bin +M(#@`$".X``#/@``2S```A008``'-@``.S8``@\P``(+-@`"!S```"X```"`` +M````R"@``Y:``,T`````S8``#BJ,`>68P`!\(`@``X!0,XN +M`43.;@%(SJX!3,C>``C(X@`,R.8`$,CJ`!3-R@%`S@H!1,Y*`4C.B@%,S0H! +M4,P*`53-03U'@```@0`````JB`&\F(``MP````"5``",`````,@H``*6@``& +M(`@````%8@#``-P#`@"@``V@I``-H +M+0`#P00``\$5``-IZ``#:>P``^@```/HT``",$\``VCD``/!W@`",$\``VD$ +M``-`+``#_P```K0"``)$!```HA8``TG6``*U$``"1%L``Z1&``"B&``"H$X` +M`_`#``(T:@`#]````<#%``/T```!TW(``T`.``#R0``#Z/```Z"V``-)U0`` +M^A$``K$/``)"%P`"I2```_`!``#Z0``"0QL``J4C``/P`0``\A$``T````-` +M+@`"MA```K0,```J0``"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`! +M``/HP```XA```T`(``*T````>A$``J`D``/P00`"L@@``J#^``/P00`"L@0` +M`K0_``)")```DB@``TJ4``/_```#8&P``T````/_```"M$```D0$``/P`P`# +MZ````((_``(B^@`#0````_\```*T0``"1!0``_`"``#R/P`"(OH``T````/_ +M```"M$```D04``/P`0`"+FX``TJ4``/_```#8'```T````/_```"M`(``D0D +M``/P`P`#Z````((_``(C,0`#0````_\```*T`@`"1#0``_`"``#R/P`"(S$` +M`TJ4``/_```#830``C-L``-````#_P```_\```)$#@`#\`,``^@```""/P`" +M)%H``C-L``-````#_P```_\```)$'@`#\`(``/(_``(D6@`"+JD``TJ4``/_ +M```#8'0``K````""*P`#0````_\```*T`@`"1$```_`#``/H````@C\``B89 +M``-*E``#_P```V!X``-````#_P```K0$``)$0``#\`,``^@```""/P`"*)P` +M`TJ4``/_```#8'P``T````/_```"M!```D1```/P#``#Z````((_``(I;``` +M`@T``_\```/_```"I`X``_`$``#R#@`"*6P``^@```""#@`#2I0``_\```-@ +MK``#0````_\```*T(``"1$```_`#``/H````@C\``BN$``-*E``#_P```V"P +M``/H````@C\``K#_``*Q_P`#P2```VA@``-H:``#0````_\```*T$``"1$`` +M`_!"``/T```"`8\``T`-``-`)@`"L4```K(0``*S"``"010``Z$:``)")``# +MHB0``F(A``)#.``#HS```F(C``"2*P`"I!X``_`)``-)/0`"LH```\`B``)$ +M0@`"*6P``TD]``/_```"LH```F1"```"$``#_P```K0!``)$!``#\`0``^@` +M``""/P`#P?X``BQ&```"$``#_P```K0"``)$!``#\`0``^@```""/P`#Z/`` +M`BQ&``-````#_P```_\```)$+@`#\`,``^@```""/P`"-7<``T````/_```" +MM!```D0D``/P`P`#Z````((_``(VJ0`#^`,``TJ4``/_```#8+0``K````"" +M*P`#0````_\```*T`@`"1$$``_`"``#R/P`")AD``TJ4``/_```#8+@``T`` +M``/_```"M`0``D1!``/P`@``\C\``BB<``-*E``#_P```V"\``-````#_P`` +M`K00``)$00`#\`L``/(_``(I;````@T``_\```/_```"I`X``_`$``#R#@`" +M*6P``^@```""#@`#2I0``_\```-@[``#0````_\```*T(``"1$$``_`"``#R +M/P`"*X0``TJ4``/_```#8/```/(_``*P_P`"L?\``\$@``-H8``#:&@``T`` +M``/_```"M!```D1!``/P0@`#]````@(.``-`#0`#0"8``K%```*R$``"LP@` +M`D$4``.A&@`"0B0``Z(D``)B(0`"0S@``Z,P``)B(P``DBL``J0>``/P"0`# +M23T``K*```/`(@`"1$(``BEL``-)/0`#_P```K*```)D0@```A```_\```*T +M!``"1`0``_`#``#R/P`#P?X``BQ&```"$``#_P```K0(``)$!``#\`,``/(_ +M``/H\``"+$8``T````/_```#_P```D0^``/P`@``\C\``C5W``-````#_P`` +M`K00``)$-``#\`(``/(_``(VJ0`#2I0``_\```-@]``#^`,```(8``/_```# +M_P```J`.``/P0@`#]````@)L``-`+``#_P```K0@``)`0``"H`0``_!(``/H +M````@C\``C((``(R30``\C\``C((``(R30`",N0``T````/_```"M`@``D0$ +M``/P#``#2`@``_\```*T0``"8`0``V@(``-)F``"M/T``D$4``-IF``#Z#`` +M`\$N``-H,``",O@``^@```/H$``#Z#```K(#``-H,``#0````_\```*U"``" +M114``_`!``(TUP`#2I0``_\```-@^````D```_\```/_```"H0X``_`"``/H +M````@A0``BZI``-(```#2`4```HT```".```$C,``"HZ```Z-@`#_P```V@` +M``-H!0`#2!```TG=```*-P``*CD``_\```-H$``#:=T``TEQ``*R`0`#Z#`` +M`\$&``/!%P`#:#```TEL``*U%@`"H%$``<*?``*PSP`"L04``K(!``*S```# +M:#```C+X``*PM``#:#```C+X``*PO``#:#```C+X``*PN``#:#```C+X``*P +MRP`#:#```C+X``*PC``#:#```C+X``*PT0`#:#```C+X``/H```#Z!```K(# +M``*S```#:#````(8``/_```#_P```J`.``/P0@`#]````<`````!]``#0!(` +M`T`5```*&P`"H`X``_`"``/T```!PL\``L$>``"*&P`":[H``F5;``+&;@`# +M\$$``L=^``-@%0`"L@\``D1"``*E%``#\`<``^B@``/HL``#8!(``^@```"! +M]``#]````P`#P?```BY[``/!\``"+GL``T`@``/_```# +M_P```L`.``/P10`"P1X``_!#``+"+@`#\$$``L,^``-@(``",VP``TE(``*T +M/P`"M8```D,T``)C-0`#:4@``D,T``-I2``#]````<````-`!```:C\``^B` +M``/HD``#Z*```^BP``*U$``"1!4``_`&``*@W@`#\`,``V2J``/T```#\$$` +M`V3J``/X`0`"M0@``D0%``(#'```8?@``J#>``/P`P`#Z$```_0```/P00`# +MA.H``]A```/?<``_@#``/4G@`#^P```P_^``(#&``#^`$``X7D``)$ +M%0`"`R\``"'Y``*@W@`#\`,``&'Q``/T```#\$$``&'P``*_"``#W$```]C` +M``/X`P`#U)X``_L```,/_@`"`RL``_@#``/L`````A0```I```!J/P`#_P`` +M`D`!``*@#@`#\`$``^P```-).``"H-X``_!!``-*7``"N/X``D(H``*@W@`# +M\`,``VDX``/T```#\$$``VI<``-)T``"M`0``F$4``*R`0`"LQ(``J#>``/P +M00`"LQ$``V@P``-)<0`"N.\``KD$``/!!@`"87D``D,X``-H,``#2`D``KC] +M``)$2``#:`D``BY_``-)H``"M!$``\$D``*Q#P`#::```TI$``*T_@`"81X` +M`VI$``)!%``#:D0``J#>``/P`P`#0F$``_0```/P00`#0ET``_\```/_```# +MZ&```VFE``-H:P`"N@P``KC```/<@0`#V*$``K#X``*Q!P`#Z"```^@P``/^ +M```#U!\``VAK``/H\``"(_\``B/B``(D'``"H?X``_!!``-B>@`#0G@``_\` +M``/_```"H(```<.3``*@D0`!PY,``J"B``'#DP`"H+,``<.3``+/_@`"O`P` +M`J'\``/P0@`#]````<-]``#Z!``#Z/```B/B``(C_P`")!P``T)X``/_```# +M_P```J"```'#J0`"H)$``<.I``*@H@`!PZD``J"S``'#J0`"S_X``KP,``*A +M_``#\$(``_0```'#E@``8@0``/H#``/_```"I<\``<.Y``*E_``!P[0``^CP +M``/HP``#]````<.\``,,SP`#K,```^CP``/T```!P[P``P_\``.O\``#Z,`` +M`B/_``/!_``"(^(``TDX``*@W@`#\$$``TI<``/_```"8BX``J#>``/P`P`# +M:3@``_0```/P00`#:EP``TG0``*T^P`"010``K(!``*S$@`"H-X``_!!``*S +M$0`#:#```TEQ``*X[P`"N?L``\$&``)!>0`"0S@``V@P``-("0`"N/T``D1( +M``-H"0`"L!@``B1```/L```#1+D``J#>``/P00`#1/D``\$/``/!'P`#P2\` +M`\$_``/!3P`#P5\``J#>``/P!0`#9+```V2T``-DN0`#]````_!#``-D\``# +M9/0``V3Y``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P```-$ +MN0`"H-X``_!!``-$^0`#P0\``\$?``/!+P`#P3\``\%O``/!?P`"H-X``_`% +M``-DK``#9+P``V2Y``/T```#\$,``V3L``-D_``#9/D``TC(``*T\P`"M00` +M`D`$``)@!0`#:,@``D`$``-HR``#[````K`0``(D0``",O@``C+X``(R^``" +M,O@``C+X``-*'``")$P``\&,``-*(``")$P``XS&``)HC``#2B0``B1,``/! +MG``#2B@``B1,``.,Q@`":9P``THL``(D3``#P:P``THP``(D3``#C,8``FJL +M``-*-``")$P``\&\``-*.``")$P``XS&``)KO``#[````VAK``*Y"``"N,`` +M`]R```/8D``#Z!```^@@``/H,``#_@```]0>``-H:P`#[````^C```.'/``# +MIW8``X8L``.F:``#A1P``Z5:``.$#``#I$P``FS'``)LQ@`";,4``FS$``/L +M````(@\``T`D``/_```"1$X``Z`&``*A#@`#\`$``(('``-)I``#2:$``&H_ +M``.+Z@`#P*L``D6E``*@W@`#\`,``D.C``/T```#\$$``F.S``-II``#::$` +M`K+_``*Q_P`"L'\``VA@``/H```#Z"```^@P``*@W@`#\`,```H)``/T```# +M\$$```H(``*XP``#:&L``]@```/<@``#U!X``K\"``(N>P`#@.```(($``"" +M`P`#Z````(("``""`0``\@```TA4``*@W@`#\`,``X3H``/T```#\$$``X3J +M``)B)``#:%0``TF8``.(Y0`#P3X``J#>``/P`0`#@S```\$N``)@"``#:#`` +M`TEU``.(Y@`"8&@``\$7``/!+@`#P3X``J#>``/P`0`#@S```V@P``-(5``" +MH-X``_`#``.$Z``#]````_!!``.$Z@`#P$0``D(D``-H5``"OP(``BY[```" +M&``#_P```_\```*@#@`#\`(``_0```($UP`",&$``^AP``.$Y@`"1DL``J!D +M``/P3P`#2=(``^A@``.*L@`#JJH``X2F``)D2@`#P50``J#>``/P`P`#:.4` +M`_0```/P00`#:04``_0```'%@@`"OP@``D_Y``.O]``#B[(``ZN\``(EI@`# +M]````@6"``-`#``#_P```K\(``)/\``#\$(``_0```'$]``"OP```KL!``(E +MI@```A$``_\```/_```"H`X``_!"``/T```!Q8(``K$"``*P$0`"Q$```L50 +M``*@W@`#\`,``VCE``/T```#\$$``VD%``,!'@`"!.D``/("``#R`0`"H-X` +M`_`#``!Z!@`#]````_!!``!Z!0`#C>(``]S0``/8\``#B>8``FF>``#Q\@`` +M0@<``^C0``./X``#P:@``XSM``#A]@``XCX``B_*``*W`0``0@<``^B@``#1 +M\@`"H'X``_`!``.H@``##]\``\'9``/!J``#C.T``.'V``#B/@`"+\H``C`+ +M``/!!``#P28``V)P``*_`0`#0!$``XC@``*@_@`#\`0``D1(``/P`@`#]``` +M`@5H``*W`0``0@<``_\```*@?@`#\`$``ZB```/HT``#C^```\&H``.,[0`` +MX?8``.(^``(OR@`",`L``T)P``.,ZP`#C.H``^CP``+(0``#J(```"H6``+* +M8@`#JJ```J9>``(%10``:C\``/(6``/!6``#P7H``V)Q``/T```"!/\``J%> +M``/P#@``:C\``\&1``/!LP`"H-X``_`#``-A+@`#]````_!!``-A,@`"P($` +M`Z@```+"HP`#JB```X50``"J%@`#@>```P"$``/P)``"H80``_`!``+$00`# +M!$X``\%4``,"I@`#\"0``J&F``/P`0`"QF$``P9N``/!=@`#U%X``F`"``(% +M5P``:C\``K\"``(N>P`#27$``X'D``/!!@`#HFP``J`N``(%@@`"87$``\$N +M``/!/@`"H-X``_`!``.#,``#AF```_!'``-H,``#C^T``BY[``./[0`"+GL` +M`X_M``(N>P`#C^T``BY[``-)=0`#P2X``\$&``/!%P`#P3X``J#>``/P`0`# +M@S```V@P``-)F``#_P```\$^``*@W@`#\`$``X,P``/!+@`#:#````H/```! +M]``#_P```D$>``/P`0`#[````J4.``/P2``#0!$``J#>``/P`P`"9FX``_0` +M``/P00`"9WX``V`1``/H````@?0``^P```(R^``#2D```$(```!*!```4@,` +M`KPS``)$#``"11P``F1%``)&+``"1SP``F9G``)D1@`"H4X``_`!``*T`0`" +MH(X``_`%``*D20`#\$,``J1+``/P00``\@(``*($``*\S``"1`P``D4<``)& +M+``"1SP``F1%``)D1@`"9$<``J%.``/P`0`"M`$``J".``/P!0`"I$H``_!# +M``*D2P`#\$$``/(!``"B`P`#Z$```*(```-#*0`"H-X``_!!``-#:0```@(` +M`!(!``*Q#P`"LP<``J7^``(%_``"H`X``_`&``*\#P`"I$$``_`!``*\"0`# +MP4P``\%<``*@+@`#\`8``KP/``*D80`#\`$``KP)``/!;``#P7P``J#>``/P +M`P`#8RD``_0```/P00`#8VD``DP"``*@S@`#\`8``L_^``*\"0`"I?P``_`" +M``/T```!Q:8``TCE``*@W@`#\$$``TD%``*X$0`"H`X``_`!``+$2``"24$` +M`J23``/P`0``\@(``J`N``/P`0`"Q5@``DE1``*DDP`#\`$``/(!``*@W@`# +M\`,``VCE``/T```#\$$``VD%``)``@`"H`X``@6F``/L````:C\``^@```(P +M.P`#29@``K@/``*U]0`"LP$``J#>``/P`0`#@S```\$N``)@"``"014``V@P +M``*_```"+GL``/'_``/H````@?X``T`,``-`+0`"N!```KD(``)*&``#JJ8` +M`DM)``.KM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*$0`" +ML$```D!```/P00`#Z#```D$>``/P`0`#Z#```)G]``(N?P`"O`$``J#>``/P +M"0`#2"$``XS&``.&9@`#IF8``F9L``-H(0`#:HD``_0```/P1P`#2"4``XS& +M``.&9@`#IF8``F9L``-H)0`#:HT``K`!``/H$``#Z"```^@P``-J8``"OP,` +M`C'5``-("``#A.H``('U``)@!``#:`@``K]D``(N>P``:C\``_\```/_```" +MH-X``_`#``*[```#]````_!!``*[0```V>\``\$.``/!'@`#@18``F$>``." +MY@`#:D0``\$>``.!%@`#Z"```VI$``/H```#P````\$0``*R_0`#:&```TI@ +M``*_]P`"L1,``D`/``)@#@`#:F```#(,```Z"P`"O`@``K_^``.&:@`"8B8` +M`J1^``/P`0`"LP0``D`/``)@#``#:F```X_A``(N>P`#:&L``_\```/^```` +M8CT``%H\``/_```#V,$``]RQ``./XP`"+GL``]`?``.,[P`#C^0``F_^``)` +M`0`"0B,``D`"``),P``#^P$``]`?``,/_@`"!J(``J#>``/P`P`#2"$``_0` +M``/P00`#2"4``\#,``(&S@`#C.8``L9L``/P00`"QWX``J#>``/P!``#:"$` +M`VJ)``/T```#\$(``V@E``-JC0`"I7X``_`"``/T```!QG$``T`1``*P"``` +M\?0``J#>``/P`P`"9F```_0```/P00`"9W```V`1``/T```""(,``X#A``.! +M!@`"81X``X+G``-J1``#@08``^@@``-J1``"L`$``^@0``/H(``#Z#```VI@ +M``-`+```6BL``K0$``/H\``"1$```_`!``*_`0`"I+X``_`!``*_!``",=4` +M`/(G``#R)0`"L/\``K&_``/!(``#:&```K`!``/H$``#Z"```^@P``-J8``` +M"CL``!(,```:"P`"L`(``J#>``/P00`"L`0``X(J``*D/@`#\`$``K,$``.! +M%@`"8`$``K$S``-J8``#0`H``K`!``*Q`@`"L@```K,!``*@*P`#\`(``^@@ +M``/!.P`#:F@``\$.```20@`"0`D``_`!``/H(``"L!,``K$"``.")@`#Z#`` +M`VIP``-`+0``8A$``!(H``*_0``"3T\``_`#``*@S@`#\`$``K((``*P(0`" +ML0(``K,!``-J=```"BL``K`!``/_```"I!X``_`%``*Q!``"L@```K,"``/T +M!``#\`,``K$"``*R#P`"LP$``VIX``-*?``#_P```K`!``*Q`@`"LP0``VI\ +M```!_@`#_P```_\```+`#@``@?X``C'0```")P`#0`H``T`-``*@#@`#\`4` +M`K`!``)`!0`#@`8``_0$``/P`P`"L`0``D`)``.``@`"L0,``F@!```"*P`# +M_P```_\```*D#@`#\`L``!(H``*P(P`"L0,``K,!``-J=``#2GP``_\```*P +M`0`"L00``K,$``-J?``#2F0``K2````1[P`"0`0``F`(``.B(@`"LP$``VID +M``(PE0`",*(```'_``/_```#_P```J`.``/P3@`#0"P``KP$``/``/P`0`#Z/```]CP``*\"0`"OS\``DL?``(O"P`#Z/```/G_```!_@`# +M_P```_\```+`#@``@?X``T`E```:$``"L@0``D(@``*@W@`#\$$``Z,R``*Y +M`@`"29,``F(I``*Y@``"294``F(I``*YA@`#Z(```J`I``/P00`#P8X``,': +M```)_0`#0"X``_\```*@`0`"!Z(``K`!``)!"``#\`4```)```/_```#_P`` +M`J`.``('H@`#2G0``'HH``/_```#_P```\$O``-J=``",=````(G``-`"@`# +M0`T``J`.``/P!0`"L`0``D`%``.``@`#]`0``_`"``*P$``"0`D``'G:``*Q +M0P`#_P```J#^``/P00`"L2,``F@!```"*P`#_P```_\```*@#@`"!]0``!(H +M``*P0P`"L00``K,!``-J=``#2GP``_\```*P`0`"L04``K,$``-J?``#2F0` +M`K2````1[P`"0`0``F`(``*X(``"8`@``KB_``)`"``#HB(``\$^``-J9``# +M]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``/!/@`#:F0``C"5``(P +MH@``0A```K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```'']0`#0`X``K`0 +M``/_```"00D``J`0``(']0```B<``_\```/_```"P`X``((G``*Q`@`"I`$` +M`@``/P1@`#Z/```K$D``+(@0`#V(```L`!``/8 +M@0`",(P```'^``/_```#_P```L`.``"!_@``>=H``C'0``*@_@`#\$4``K`/ +M``/!$``#P2```\$P``-J@``#0`H``K!```/_```"0`D``Z`"``*Q`P`":`$` +M``(K``/_```#_P```J0.``/P"P``$B@``K!#``*Q!0`"LP$``VIT``-*?``# +M_P```K`!``*Q!@`"LP0``VI\``-*9``"M(```!'O``)`!``"8`@``Z(B``*S +M`0`#:F0``C"5``(PH@`#0"4``$(0``*P(``"0`4``_!(``*P`@`"H-X``_!! +M``.``@`"0`@``_`"``/T```!R&4``!'^``*P@``"LP,``J`C``/P0P`"0`4` +M`_`!``(QE@`#0"X``_\```*P"``"00@``J`0``((90`"L(```D$(``/P!0`` +M`D```_\```/_```"H`X``@AE```")0`#_P```_\```/H$```BB4``J0.``(' +M=P```>\``$'Y``/_```#_P```]@```/<@```>D(``K````/8`0`"L`$``]P! +M``-`#0`"O2```_\```)-U0`"IMX``_`#``(O*P`#]`0``_`*``*P?P`"L?\` +M`K+_``-H8``#:&L``!'E``*SP``#Z-```V!,``(O9@`"L`$``^@0``/H(``# +MZ#```VI@``-*9``"M(```D`$``-J9```(?4``_\```-("``#_P```\$$``-H +M"``#[````^@```/H$``"H-X``_`#``-I'``#]`0``_`!``-I-``#[````&H_ +M``/_```#_P```J#>``/P`P`"NV(``_0```/P00`"NV@``_\```/_````V?P` +M`C*.``/H```",#L``KL"``#:/@`#2`$``K"_``)$0``#:`$``TF8``*T#P`" +MM?T``F`$``)!%0`#P2X``\$^``*@W@`#\`$``X,P``-H,``#2`@``K1```"! +M]0`"8`0``V@(``/H```"L6```^@@``/H,``#::```^@```*Q$``#Z"```^@P +M``-J1``"L`$``^@0``/H(``#Z#```VI@``*_`@`",=4``^@```/````#P1`` +M`K+]``-H8```"CL``!(,```:"P`"L`H``J#>``/P00`"L`P``X$6``)@`0`# +M@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+GL``VAK``/_ +M```#_@```C'^``-*8```,@P``#H+``*T]@`"M0,``X9J``)B)@`"I'X``_`! +M``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``#:F@` +M`K"````20@`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`" +ML0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`@`"L0(``K,$``-J?``"L/\``K&_``/!(``#:&```^AP``-*9``"M(```D`$ +M``/H(``#Z#```VID``-*9``"M(```!'\``)`!``"M`,``F`$``*S$``#:F0` +M`C"5``-*9``"M`@``D1```)G=``"I7X``@E<``/H```",#L``J#>``/P`P`# +M2"(``_0```/P00`#2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H +M(@`#:HH``_0```/P0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R2$``T`2 +M``#Q]``"OP0``J#>``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R5P` +M`K`!``/H$``#Z"```^@P``-J8``#2F0``K2```)`!``#:F0``"'U``/_```# +M2`@``_\```/!!``#:`@``^P```!J/P``\?\``^@```""$P`#0`@``T`M``*X +M0``"N0@``DH(``.JJ@`"2TD``ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`! +M``*S!@`#0"T```H1``*P0``"0$```_!!``/H,``"01X``_`!``/H,```FA(` +M`"'T``/H4``#_P```*(9``"I]```:C\``_\```/_```"H-X``_`#``!9\0`# +M]````_!#``!9\``#_P```_\```#9[P`#2````X3J``/`1``#_P```D`$``-H +M```#2`0``\!^``/_```#_P```D,W``-H!``#0"P``%HK``*T!``#Z/```D1` +M``/P`0`"OP$``DN^``*@O@`#\`,``C#]``/T```!R;4``K_+``(S00``\B8` +M`/(E``*P_P`"L;\``\$@``-H8``"L`$``^@0``/H(``#Z#```VI@```*.P`` +M$@P``!H+``*P`@`"H-X``_!!``*P!``#@18``F`!``-`%0`#@BH``K&```)B +M(0`"I#X``_`!``*S!``"MO```D1&``*Q"``"810``VI@``-`"@`"L`$``K$" +M``*R```"LP$``J`K``/P`@`#Z"```\$[``-J:``"L`$``!)!``)`"0`#\`$` +M`^@@``*P$P`"L0(``X(F``/H,``#:G```T`M``!B$0``$B@``K]```)/3P`# +M\`,``J#.``/P`0`"L@@``K`A``*Q`@`"LP$``VIT```**P`"L`$``_\```)! +M$``"I!X``_`%``*Q!``"L@```K,"``/T!``#\`,``K$"``*R#P`"LP$``VIX +M``-*?``#_P```K`!``*Q`@`"LP0``VI\```**P`#_P```_\```)!'@`"I!X` +M`@I4```"$P`#_P```_\```+`#@``@A,``C'0```")@`#0`H``T`-``*@#@`# +M\`4``K`"``)`!0`#@`0``_0$``/P`P`"L`@``D`)``.````"L0,``F@!```" +M*P`#_P```_\```)`#@`"I`X``_`+```2*``"L",``K$#``*S`0`#:G0``TI\ +M``/_```"L`$``K$$``*S!``#:GP``TID``*T@```$>\``D`$``)@"``#HB(` +M`K,!``-J9``",)4``C"B```!_P`#_P```_\```*@#@`#\$X``T`L``*\!``# +MW,```K_```*@W@`#\`$``K^```/8\``#C.0``K\_``)+'P`"+PL``^CP``#Y +M_P```A,``_\```/_```"P`X``((3``!:*P``>B4``K@(``)*O@`"H*X``B@``_\```/_```#P2\``VIT +M``(QT````B8``T`*``-`#0`"H`X``_`%``*P"``"0`4``X````/T!``#\`,` +M`K`@``)`"0`#H````K%#``)H`0```BL``_\```/_```"0`X``J`.``(*O``` +M$B@``K!#``*Q!``"LP$``VIT``-*?``#_P```K`!``*Q!0`"LP0``VI\``-* +M9``"M(```!'O``)`!``"8`@``K@@``)@"``"N+\``D`(``.B(@`"L00``\$^ +M``-J9``#]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``*S`0`#:F0` +M`C"5``(PH@``6BL``KH!``/_```"2[H``J"Z``/P0@`#]``````/P00`#@`(``D`(``/P`@`#]````\``D`$ +M``)@"``#HB(``K,!``*Q```#:F0``C"5``(PH@``6BL``KH#``*Y`0`#_P`` +M`DBZ``*DB0`!RU<``KD$``/_```"2+H``J"*``'+.0```B4``K((``*S```# +M_P```J0"``'+5P`"H`X``_!#``":)0`#]````D$``K````/8`0`"L`$``]P!``-`#0`"O4```_\` +M``)-U0`"IMX``_`#``(O*P`#]`0``_`*``*P?P`"L?\``K+_``-H8``#:&L` +M`!'E``*SP``#Z-```V!,``(O9@`"L`$``^@0``/H(``#Z#```VI@``(QT``# +M[````&H_``/_```#_P```J#>``/P`P`"NU,``_0```/P00`"NUL``_\```/_ +M````V?P``T`0``*[#P`#2"D``J#>``/P00`#2"T``K\$``)`"P`#JP(``P_[ +M``.,]@`";,\``X_V``-)Z``"HTP``_`$``,$3``#!5\``_0```/P10`#A.8` +M`X56``.E5@`"950``F1.``/!!``#P14``J#>``/P!``#:"D``VGH``/T```# +M\$(``V@M``-I[``#Z````C!/``-(`0`"L+\``D1```-H`0`#Z````K%```/H +M(``#Z#```VI$``*P`0`#Z!```^@@``/H,``#:F```K\"``(QU0``"CL``!(, +M```:"P`"L`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&$``)B(0`"I#X` +M`_`!``*S!``"L1@``VI@``-`"@`"L`$``K$"``*R$@`#Z#```VIH``*P@``` +M$D$``D`(``/P`0`#Z"```K`3``*Q`@`#@B8``^@P``-J<``"L"$``K$"``*R +M`0`"LP$``VIT``*P`0`"L0(``K(/``*S`0`#:G@``TI\``/_```"L`(``K$" +M``*S!``#:GP``^@```/````"L;\``\$@``-H8``#Z'```TID``*T@``"0`0` +M`VID``-*9``"M(```!'\``)`!``"M`,``F`$``*S$``#:F0``C"5``-*9``" +MM`@``D1```)G=``"I7X``@P\``/H```",$\``J#>``/P!``#2"H``TGH``/T +M```#\$(``T@N``-)[``"O!$``K\0``+)GP`"R(P``\$(``/!&0`"H-X``_`$ +M``-H*@`#:>@``_0```/P0@`#:"X``VGL``*[`0``VCX``^AP``.+Y0`#B[8` +M`J6+``/P`@`#]````\``K#_``*QOP`#P2`` +M`VA@``*P`0`#Z!```^@@``/H,``#:F````H[```2#```&@L``K`"``*@W@`# +M\$$``K`$``.!%@`"8`$``X(J``*Q@``"8B$``J0^``/P`0`"LP0``T`5``*Q +M"``"MO```D1&``)A%``#:F```K`!``*Q`@`"L@```K,"``-J:```$?L``K`3 +M``*Q`@`#@B8``^@P``-J<```$B@``K`A``*Q`@`"LP$``VIT``*P`0`"L0(` +M`K(/``*S`0`#:G@``TI\``/_```"L`$``K$"``*S!``#:GP``KP$``/>\``&'[``*[&``#V/```B\+```!V0`#0"4``K\0``+`#@``@=D``D]?``/P +M`P`"+6@``_0```',J0`"OP@``J`.``/P`0`#P?X``C,+``-*@``"H/X``_!! +M``-JA```8>\``K"```/H\``"H<```_!!``/!_@`"+1L``C'0```1[P`#Z!`` +M`K`C``.B(@`"LP$``VID``(PE0``8=D```'O```)^0`#0"8``K(0``/8```# +MW!```'G[``*P```#V`$``K`!``/<`0`"0BD``_!%``.O\``"H,X``_`"``/[ +M```#^P$``]">``/[```"I2X``_`!``/[```#U)\``_L!``*E+@`#\`$``_L! +M``,/_@`"#,L```'9``/_```#_P```L`.``"!V0``8>\``K"```/!_@`"H<`` +M`_!!``/H\``"+1L``C'0```1[P`"L`,``^@0``.B(@`"LP$``VID``(PE0`" +M,*(``T`E```!V0`"L0,``K((``*S$``"0S4``_`"``)")0`#\`(``J4!``', +ME@``8?D``%GO``/_```#W,```]BP``*P```#V`$``K`!``/<`0``>?L``T`- +M``*]0``#_P```DW5``*FW@`#\`,``B\K``/T!``#\`H``K!_``*Q_P`"LO\` +M`VA@``-H:P``$>4``K/```/HT``#8$P``B]F``*P`0`#Z!```^@@``/H,``# +M:F```C'0``/L```"O!$``J#>``/P!``#2,P``TC1``/T```#\$(``TCL``-( +M\0`"+5,``J#>``/P!``#:,P``VC1``/T```#\$(``VCL``-H\0`"H-X``_`$ +M``-(U``#2-D``_0```/P0@`#2/0``TCY``(M4P`"H-X``_`$``-HU``#:-D` +M`_0```/P0@`#:/0``VCY``*@W@`#\`,``TC<``/T```#\$$``TC\``*@_@`# +M\`0``L`,``+!'``#]````_!"``,`#``#`1P``J#>``/P`P`#:-P``_0```/P +M00`#:/P``^P```*@_@`#\`H``L`,``+!'``"PBP``L,\``+$3``"Q5P``L9L +M``+'?``#]````_!(``,`#``#`1P``P(L``,#/``#!$P``P5<``,&;``#!WP` +M`^P```*P?P`"L?\``K+_``-H8``#:&L```GE``/H```#H`,``]P```/8$``# +M0#$``K\#``*\`@`"IOP``_!!``/!!P`"H/P``_!!``/!!@`"H/X``_!!``/! +M!0`"H?X``_!!``/!!``#P1```\$@``/!,``#_@```]0>``-H:P`#^P```P_^ +M``(-=0`#0#4``K\#``/_```"IOP``_!!``/!!P`"H/P``_!!``/!!@`"H/X` +M`_!!``/!!0`"H?X``_!!``/!!``#P1```\$@``/!,``#_@```]0>``-H:P`# +M^P```P_^``(-C0`#0#@``T`]``/_```#:H0``VJ!``/L```#85```V%5``-A +M6@`#85\``TA4``/_```#Z#```Z,S``-H5``#:&L``TA5``/H```#Z'```K+O +M``*Q_P`"L+\``VA@``-H:P`#27P``K0$``)A%``#:7P``TD\``/_```"81X` +M`VD\``-*E``#03D``_\```/_```"IC<``_`'``*F)@`#\`4``J85``/P`P`" +MI00``_`!``-A.``#8/P``_\```/^```#_P```TAD``*T$``"0B0``J`D``/P +M0P`"+A4``_0```'-T``"L/\``K'_``*R_P`"L_\``VJ0``-)/``#P$X``D$4 +M``-I/``#2%0``K4_``)#4P`#:%0``^@```"!]```@AH``((;``-(9``#C.H` +M`/(5``),#``#\$@``T@T``/_```#@`@``Z`,``*@#@`#^`$``@WQ``""%0`# +M^`,``TA5``/H```#AP<``VA5``-)/0`"OQ```D1/``/P!``"O_\``BY[``*_ +M4``"+GL``Z=P``,'?@`"#@<``\`@``/`$``#P````VA@``-H:P`#H!```VA@ +M``-!4``#054``T%:``-!7P`#[````_@#``-)T``"N`@``DDX``*@F``"#F@` +M`TG4``*T$``"0S0``J`T``(.1``#2`@``K@(``)@"``#:`@``T@H``*X(``" +M8S@``T@M``-H*``#:>@``F=X``-H+0`#:>T``TC(``*X^P`"0B@``VC(``-( +MF``"N"```F`(``-(L0`#:)@``F1(``-HL0`#P0X``\$>``/!+@`#P3X``V,P +M``-C<``#8S0``V-T``-C.``#8W@``_0```'.:``#2`@``KCW``)`"``#:`@` +M`T@H``*XWP`"0S@``T@M``-H*``#:>@``D=X``-H+0`#:>T``TC(``*X!``" +M8B@``VC(``-(F``"N-\``D`(``-(L0`#:)@``D1(``-HL0`"L`,``\$0``/! +M(``#P3```V,P``-C<``#8S0``V-T``/!+@`#P3X``V,X``-C>``#27P``K3[ +M``)!%``#:7P``VAK``/L```#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(` +M`VC*``)H(0`#:,H``\&"``-HR@`#[````_@#``,/_@`"#GP``^P```/H```# +MP!```\`@``.@$``#:&```VAK``/!#@`#Z!```^@@``/H,``#I!,``]@0``/< +M0``#_@```]0>``-H:P`#::0``^@```/^```#U!X``VAK``-II``"H-X``_`# +M``-"8``#]````_!!``-"7``#0ED``J#>``-II``#\`,``T)H``/T```#\$$` +M`T)D``-IH0`#_@```]0>``-H:P`#:&L``^P```/H```#P"```\`0``.@$``# +M:&```VAK``-"5@`#P0X``^@0``/H(``#Z#```Z03``/8$``#W$```]0>``*_ +M`@`"+GL``VAK``-II``#::(``^@```/_```#U!X``K\"``(N>P`#:&L``VFD +M``/H```#P"```\`0``/````#:&```VAK``/L```#:&L``K!_``*Q_P`"LO\` +M`VA@``*Q#``#Z````Z`#``/<```#V!```^@```/H$``#Z"```^@P``/^```# +MU!X``VAK``/[```#^P```XCC``/X`P`#_@```]0>``-H:P`#^P```PB.``(. +MX``#[````"'Z``/H4``#Z&```^AP``*Y"``"N,```]R!``/8D0`#0E```_@# +M``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`#:&L``K09``/^```#U%\` +M`VAK``-)I0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``# +M"9X``@\'``-II0`#[````J&^``/P"@`#T!X``P^^``/X`P`#``X``P$>``," +M+@`#`SX``]0>``,/_@`"#Q```_L```,,S@`"#PL``^P```*AO@`#\`H``]`> +M``,/O@`#^`,``L`.``+!'@`"PBX``L,^``/4'@`##_X``@\@``/[```##,X` +M`@\;``/L```#T)X``]`?``*\/P`"2(P``DF<``)*K``"2[P``D0,``)%'``" +M1BP``D<\``*\(``"P(0``Z````*C2``#\$$``L`,``+!E0`#H1```J-9``/P +M00`"P1P``L*F``.B(``"HVH``_!!``+"+``"P[<``Z,P``*C>P`#\$$``L,\ +M``/HT``#C.D``P2```+HC0`#!9$``NF=``,&H@`"ZJT``P>S``+KO0`#8FX` +M`DB,``))G``"2JP``DN\``/4G@`#0FX``F1%``)D1@`"9$<``@]-``!J/P`# +M^P```_L!``,/_@`"#RL``^P```/0G@`#T!\``KP_``)(C``"29P``DJL``)+ +MO``"1`P``D4<``)&+``"1SP``KP@``+`A``#H````J-(``/P00`"P`P``L&5 +M``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`#\$$``L(L``+#MP`#HS`` +M`J-[``/P00`"PSP``KP'``*CW``#\$X``W!,``-03@`#_P```_\```/^```# +MU!X``VAK``/[```#<$X``U!,``/_```#_P```_0$``/P"``"O`@``J3<``/P +M`0`#:H0``KP)``*DW``#\`$``VJ```*P_P`"L;\``K+_``-H8``#^P```_L! +M``+-W@`"IM\``@]F``-*9``"M(```D`$``-J9``"L````K$```*R```"LP$` +M`VIT``*P,0`"L08``K($``*S```#:G@``TI\``/_```"L`$``K$!``*S```# +M:GP``TID``*T@``"0`0``K0#``)@!``#:F0``C"5``-*9``"M(```D`$``-J +M9```:C\``C-L``/L````6?8``&(^``/_```"H;X``_!"``#Q]``#[````J'. +M``/P00`#"[X``PS.``#9]@``XCX``TI```!:%@`#_P```_\```*@O@`#\$(` +M`Z````.B(``#T%X``&(*``!9\@`#H@(``D`)``)"*0`"I8X``@_U``,(C@`" +MH`T``_`+``!"!P`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$ +M3P`#P50``J6N``(0!0`#"JX``J`M``/P"P``4@<``L9O``/!=@`"H+X``_!& +M``/47@`"QF\``\%V``/47@`"QF\``\%V``/47@`##,X``A`&``)KB@`"#\H` +M`^P```-"<```4A8``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``" +MH6@``_!!``+&:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,& +M:``#`B@``P,X``,*K@`"$!D``\%4``/!=@`#U%X``V)P``/L```#P6(``P9N +M``/<$``#V````]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X` +M`_L```,&;@`"$"X``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``# +M:1```VD4``-I&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I +M-``#[````\$0``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC< +M``/T```#\$4``VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4` +M`D$#``-)T@`#_P```D`*``-)P@`"I1```_`!``-)Q@`#[````K!_``*Q_P`" +MLO\``VA@``-H:P`#Z````^@0``/!+@`"LS```VFD``/H```"L3```^@@``/H +M,``#Z$```Z5#``/80``#W%```_X```/4'@`#:&L``_L```/[```"L!(``^@0 +M``/^```#U!X``VAK``,(C@`"$(8``^P```/0G@`#^P```_\```/_```#U)\` +M`_L!``,/_@`"$(P``^P```/X`0`"OP0``TID``/_```#_P```D$/``(0EP`# +M^`,``VAK``/_```#_P```_X```/L```#2F0``_\```*_"``"00\``J`?``(0 +MPP`#0!(``K40``*E)0`#\`0``K\"``)JKP`#]````=#```+$50`"I20``_`$ +M``*_`@`":[\``_0```'0P``"Q$4``J4D``/P!``"OQ```FJO``/T```!T,`` +M`K\0``)KOP``\?0``V`2``(PQ``#[````TIP``/_```#P<(``T`N``*P`0`# +M:J@``_\```/_```#_P```TJL``*T`@`#:JD``\````/`$0`#P"(``\`S``-* +MK0`"OY```J#/``/P!0`#P$0``K\/``)/3P`#]````_!!``/`]``"H-X``_`+ +M``-`&0`#_P```_\```)D0``"95$``F9B``)G4``K#```/<```#V!```J#^``/P!``#Z````^@0``/H(``#Z#```J#^ +M``/P1``"L%4``\$0``/!(``#P3```J#^``/P!``"M/\``\%4``/!9``#P70` +M`J#^``/P1``"M*H``\%4``/!9``#P70``KP'``*C_@`"$7D``$(-``/_```# +M_P```J".``(1/P`"H-X``_`#``-`0@`#]`0``_`!``-`1@``ZC\``&H.``*D +MW@`#\`0``\"(``/`F0`#P*H``\"[``)@"``"81D``F(J``)C.P`"9$@``F59 +M``)F:@`"9WL``&H_``/_```#_P```_X```/4'@`#:&L``_L```,,S@`#_@`` +M`]1>``-H:P`#^P```PS.``(1/P``0@T``&(.``/_```"H(X``A%D``-`2@`" +MI,X``_`$``/`B``#P)D``\"J``/`NP`"I-X``_`"``/!B@`#P9L``KH/``)* +MJ``#BZ8``FJK``*[\``"2[@``Z>V``)KMP`#]`0``_`#``/H8``#Z*```^BP +M``*T\``"8$H``\$0``/!(``#P3```VJ$``*@_@`#\`,``K3P``/T!``#\`$` +M`K0/``)@2P`#P1```\$@``/!,``#:H```^P```/^```#U!X``VAK``/[```# +M#,X``KD#``*@^0`#\$0``^A```/H4``#Z&```^AP``/^```#U%X``VAK``/[ +M```##,X``A&%``*P\``"L?\``J#Y``/P0@`#Z````^@0``/!(0`#P3$``VJ$ +M``-J@``#[````K!_``*Q_P`"LO\``VA@``-H:P``">4``K#```/<```#V!`` +M`K3_``/!9``#P70``KP'``/^```"M?\``]1>``-H:P`#^P```PS.``/^```" +MM>\``]1>``-H:P`#^P```PS.``(1HP`"M?\``VJ%``*P\``#P1```\$@``/! +M,``#:H```TIB``(QT``#Z/```C'<``-J8@``">4``K#```/<```#V!```K3_ +M``/!5``#P60``\%T``*\!P`#_@```]1>``-H:P`#^P```PS.``(1Q0`"L/\` +M`K&_``/!(``#:&```^P```-*9``"M(```D`$``-J9``#[````K`$``*@\``# +M\`,``C#]``/T!``#\`$``BUH``/H```#P````\$0``*R_0`#:&````H[```R +M#```&@L``K`*``*@W@`#\$$``K`,``.!%@`"8`$``K$6``*D/@`#\`$``K,$ +M``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`"L@0``F(F``-J8``#C^$` +M`BY[``-H:P`#_P```_X```/L```#2F```_\```/H,``"8`X``VI@``-*9``" +MM/(``D`$``-J9``#[````&H_``-`!``#_P```K@$``)%X``"H%X``_!$``*@ +MW@`#\$(``T`D``/_````8?@``_\```/_```#W,```X_J``*@W@`#\`$``^CP +M``/8\``#C.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<` +M`D`(``/P0P`"+PL``_0```/P00`"+QL``D1N``/P"0`#Z,```ZMB``.E8``" +M15X``_!#``(O"P`#]````_!!``(O&P`#[````TC```-(Q0`#Z!```^A0``*@ +MW@`#\`@``VC````",0``"C```_\```/_```#:,```_0```/P1@`#:,4``"(O +M```J+@`#_P```_\```-HQ0`#[````&H_``/_```#_P```%'Y``*@W@`#\`,` +M`%GQ``/T```#\$$``%GP``/_```#W*```]BP``-`!@`#_P```_\```)`Z``# +M\`,``J#>``/P00`#0"8``_\```/_```#24$``J`.``/P0P`"H-X``_!!``/! +M10`"14X``_!#``.,Y``#]````_!!``.,XP`#B9@``ZJ<``*@K@`#\`,``B\+ +M``/T```#\$$``B\;``-`!@`#_P```_\```-)00`"0(X``J`.``/P0P`"H-X` +M`_!!``/!10`#Z,```ZM"``)%3@`#\`<``Z5```)%7@`#\$,``B\+``/T```# +M\$$``B\;``/L```"H-X``_`#``-((0`#]````_!!``-()0`#_P```KL!``.B +M9@`#@68``Z$6``.'=@`"8"<``P`+``.G!@`#@@8``F8A``*@W@`#\`0``V@A +M``-JB0`#]````_!"``-H)0`#:HT``^P```./[0`"+GL``^@P``."X``#Z!`` +M`^@```-H,``#C^T``BY[``/H\``#27```^AP``*V`0`#P5$``\%```-H,0`" +MN/P``\%3``/!0@`"15@``TET``(R^``#:#$``\%1``/!0``",O@``V@Q``/! +M4P`#P4(``TF8``(R^``#:#$``\%1``/!0``",O@``V@Q``/!4P`#P4(``TF< +M``(R^``#:#$``\%1``/!0``",O@``V@Q``/!4P`#P4(``TCH``(R^``#:#$` +M`\%1``/!0``"MQ```C+X``-H,0`#P5,``\%"``(R^``#:#$``^P```-)/0`" +ML`@``D`$``/P!0`#2J0``_\```/_```"L@,``VJD``*P!``"000``J`0``/P +M1@`#2,```TC%``*Q`P`"M0,``VC```-HQ0`#[````_\```/_```#_P```^P` +M``-A2``#84$``V%&``-B?P`#P0X``^@0``/H(``#Z#```VCH``/H```#_P`` +M`VCH``-!2``#_P```^P```*P?P`"L?\``K+_``-H8``#:&L```GE``/H```# +MH`,``]P```/8$``"O`,``K#W``*@_@`#\$$``K!_``/!$``#P2```\$P``*T +M_P`#P50``\%D``/!=``#_@```]0>``-H:P`#H`$``Z$1``.B(0`#HS$``_L` +M``/^```#U%X``VAK``/[```##,X``A,A``*P_P`"O`@``\$0``/!(``#P3`` +M`VJ```*D_@`!TSL``J#\``/P`@`#:H0``^P```*P]P`#H0$``Z(1``.C(0`# +M:H0``^P```-)/0`#_P```KB```)D2``#:3T``K`!``*Q`@`"LC\``D(O``*S +M```#:F@``K````*Q```"L@```K,"``-J=``"L0$``K((``*S```#:G@``K`! +M``*R```#:GP``!'O``*PP``"0`\``Z`"``)@#@`"L0```Z(B``*S`0`#:F0` +M`K#_``*QOP`#P2```VA@``/_```#_P```C"5``*X?P`"1$@``VD]``/L```# +MZ````^@0``*R`P`"LP```V@P``/L```#Z````((_``(B^@``\C\``B+Z``(S +MJ``"+FX``TF8``*T]P`"010``VF8``/!+@`#Z#```V@P```"%P`#@>```^A` +M``*@`0`#\`$``\%.``(TL@`#2`@``KC^``)!&``#:`@``^@```""/P`")%H` +M`/(_``(D6@```A<``X'@``/_```"I!```_`"``/!3@`"-+(``C0"``-`+``" +MN$```KF```*[_P`#2J4``D@8``/P`0`"N\\``DD9``/P`@`"NC\``DNZ``)% +M6P`#:J4``_0```'";``#2=$``KA```)$>``#A$```TB<``.%X@`"8`0``F`% +M``-HG``#:*```VBT``-HN``#23@``X7A``/`50`"0B4``VDX``-J7``#H.$` +M`X'A``/H,``#@N@``X7E``(P*@`#0Z8``X#H``/_```"2(4``FB```/!F``# +MP:@``\&X``-CI@`#8^8``^@```/HT``",#L``\'>``(P.P`",&$``X3B``/! +MR0`#Z````X'A``.#Y``"PC$``P(N``+#/@`"1$D``_`!``.#Y0`#Z%```C`J +M``.`Z@`","H``XCE``.$X``"1$P``_`"``.(Y``"R(X``\&8``/!J``#P;@` +M`V,J``-C:@`",&$``X'B``.@X0`#HY8``X+D``+"+@`#Z%```C`J``.@XP`" +M,"H``C!A``.`Y0`"0*```\$0``/!(``#P3```V2H``-DZ``#@.```H((``)" +M`@`#@B0``)'C``/L```",&$``TEP``)$C@`#\$,``K7S``)")0`#:7```^AP +M``/!;@`#P5,``\%"``-H,0`"1)X``_`&``-)G``#I.$``F(D``/!4P`#P4(` +M`V@Q``)$C@`#\$T``TF<``.$Y0`#I><``D`$``)!%0`#I(@``X1```.%1@`" +M8`4``F$4``/H,``#P2X``V@P``-#I```(>,``K4/``/_```"0`4``F`$``/! +M$``#P2```\$P``-CI``#8^0``X&$``.@&``#@@8``F`"``/HT``",$\``\'> +M``(P3P`#2)```Z2Z``.EYP`"014``F$4``-HD``#:*@``VB4``-HK``#H*8` +M`\$0``/!(``#P3```V0D``-D9``#BK8``T@A``*X`P`"9F@``KD/``*[_@`" +M1FD``F9J``)'>P`#:"$``VJ)``-H)0`#:HT``T@(``-((0`"81X``V@(``-( +MR``"N$```KD_``)@"``#:,@``D`)``-HR``"95X``V@A``-JB0`#:"4``VJ- +M``)%6P`#:"$``VJ)``-H)0`#:HT``^P```-`+``"N$```KF```/HL``#2J4` +M`D@8``/P`0`"NS```DD9``/P`@`"NL```FNZ``)E6P`#:J4``TB<``-(H0`" +MO'L``D`,``)$3``#:)P``VBA``-(M``#2+D``D`,``)$3``#:+0``VBY``-( +MD``#A.(``Z7G``)!%0`"810``VB0``-HJ``#:)0``VBL``-).``#A>$``F(E +M``-I.``#:EP``Z#A``.!X0`#@^@``X+H``.%Y0`","H``^@```.!X0`#@^0` +M`L(Q``/H,``#Z%```C`J``.`Z@`","H``T@(``-((0`#J.T``D$8``-H"``# +MJ.L``D9H``/`/@`"15,``V@A``-JB0`#:"4``VJ-``/H0``"-+(``^P```-) +M=``#P6X``^AP``.(2``#P%X``X59``)")0`"8B@``VET``/!0@`#P5,``V@Q +M``/L```#2`@``KC^``)!&``#:`@``TA4``*\8``"8BP``VA4``-)=@`"O!`` +M`F2L``/!6P`#P6X``^AP``-H,0`",O@``TA4``*\GP`"0BP``VA4``/!2@`# +M:#$``C14``/L````\=X``/'=``/!_0`#P4``_0$``(5&```T=\``J#>``(5 +M/@``T>```LW>``/T!``"%.\``$'@``/_```#_P```J"H``(590`"H:@``_!( +M``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@``VGE``-()0`#`Z@``X,P``)G``#8!$``\'?``-) +MF``#A>(``\!5``)!%0`#:9@``^@P``/!+@`#:#```T@(``/_```#A,@``F`$ +M``-H"``#^`,``^P```/_```#_P```&H_``/H````@AD``('<``*P`0`"L1$` +M`K(0``-J1``"L1```^@@``-J1``#0"0``J#>``/P`P`"NU,``_0```/P00`" +MNUL``-G\``)`#@`#\$L``T`0``*\!``#W,```X_J``*@W@`#\`$``^CP``/8 +M\``"O`D``\&Q``(O"P`#0"0``_\```*\`@`"0`P``_!+``-`$``"O`0``]S` +M``*_P``"H-X``_`!``*_@``#V/```XSD``/!L0`"+PL``TF8``.(Y0`"M?T` +M`\$^``*@W@`#\`$``X,P``/!+@`"8`@``D$5``-H,``#2`@``K1```"!]0`" +M8`0``V@(``-(`0`"L+\``D1```-H`0`#Z````K%```/H(``#Z#```VI$``-` +M+@`"L`$``^@0``/H(``#Z#```VI@``(M:``"L`$``K$"``*R!@`#Z#```VIH +M```200`"L!,``K$"``.")@`#Z#```VIP``*P(0`"L0(``K($``*S`0`#:G0` +M`K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P```"L0```K,$``-J?``" +MOQ@``C91``(V?@`"OP```C'5``-*<``#_P```_\```*RD``#:G```K\3``(V +M40`"-GX``T`D``/_```#_P```D`.``/P2P`#0!```KP$``/ +M``/P`0`#Z/```]CP``*\"0`#BQ```B\;``-`)``#_P```KP"``)`#``#\$L` +M`T`0``*\!``#W,```K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(O&P`# +M2G```_\```/_```"LH```VIP``*_&``"-E$``C9^``*_```",=4``TIP``/_ +M```#_P```K*0``-J<``"OQ,``C91``(V?@`#0"0``_\```/_```"0`X``_!+ +M``-`$``"O`0``]S```./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+PL` +M`T`D``/_```"O`(``D`,``/P2P`#0!(``KP$``/``/P`0`" +MOX```]CP``.,Y``#P;D``B\+``*P`0`#Z!```^@@``/H,``#:F```TID``*T +M@``"0`0``VID```A]0`#_P```T@(``/_```#P00``V@(``/L```#Z````\`` +M``*QOP`#P2```VA@``*P`0`#Z!```^@@``/H,``#:F```TID``*T@``"0`0` +M`VID```*.P``$@P``!H+``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`" +ML80``F(A``*D/@`#\`$``K,$``/!'P`#:F```TID``*T@```$?P``D`$``*T +M`P`"8`0``K,0``-J9``",)4``K\(``)/\``#\`$``/(9``/L`````AD``_\` +M``/_```"I0X``_`!``/L```#Z````((9``-`$@`#_P```_\```)$C@`"H$X` +M`_`!``#Q]``"OT```J#>``/P`P`":J\``_0```/P00`":[\``V`2``(PQ``` +M>=P``_\```-`*``"H/X``_!!``/L```"H-X``_`%``+`#@`#\$$``L$>``/T +M```#\$,``L(N``/P00`"PSX``V`H``#QW``#[`````(4```*0```:C\``_\` +M``)``0`"H`X``_`!``/L```#2)P``TBA``-*2@`"H-X``_!#``-(M``#2+D` +M`TI.``*\$``"8BX``F9N``)HC``":9P``J#>``/P!0`#:)P``VBA``-J2@`# +M]````_!#``-HM``#:+D``VI.``/HP```X=L``K`0``*Q```"LA```K,```-B +M=``"L(```]@!``*P```#W`$``K`2``*Q`@`"LA(``K,"``-B=``"L!```K$2 +M``*R$``"LQ(``V)P``-B1``"L0(``K,"``-B3``#8D@``T`L``/_```#_P`` +M`^@@``/H,``#8"P``^@```/H$```8=L``V`8``-@'``#P8P``\&<``/!K``# +MP;P``C=S``(U=P``8=L``_\```*P```#W````K!```./P@`"P`\``]@```-` +M&``"H-X``_!!``-`'``#0"T``_\```/4'@`#U%\``K\```/<\``"O\```XC" +M``+/^``#V/```\0```/$$0`#Q"(``\0S``*U#P`"1&4``Z5F``*@W@`#\$,` +M`K4/``)$=0`#I78``Z9"``.$2@`#IU(``X5:``/$1``#Q&8``L`!``+`!``" +MPB,``L(F``/$%0`#Q#<``]0>``-"=0`#0G(``K\0``*A!``#\$8``J4)``/P +M!``#P8P``\&0``/!K``#P;```J,)``/P0@`#P:P``\&P``-B<@`#0D8``J$F +M``/P1@`"I2D``_`$``/!C``#P9(``\&L``/!L@`"HRD``_!"``/!K``#P;(` +M`V)&``-"3@`"H14``_!&``*E&0`#\`0``\&,``/!D0`#P:P``\&Q``*C&0`# +M\$(``\&L``/!L0`#8DX``T)*``*A-P`#\$8``J4Y``/P!``#P8P``\&3``/! +MK``#P;,``J,Y``/P0@`#P:P``\&S``-B2@`#8G0``_L!``*Q$``"S,X``.'; +M``*@P0`!UN(``T)P``-"10`#_P```L@"``.H@``"RD8``ZJ@``-"3``#0DD` +M`_\```+)`@`#J9```LM&``.KL``"-W,``^P```-(G``#2*$``J#>``/P0@`# +M2+0``TBY``/!&``#P5H``XF6``.+M@`"81D``F5;``*@W@`#\`0``VB<``-H +5H0`#]````_!"``-HM``#:+D``^P` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CAICOS_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CAICOS_me.bin.uu new file mode 100644 index 00000000000..0bf5708c168 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CAICOS_me.bin.uu @@ -0,0 +1,126 @@ +begin 644 CAICOS_me.bin +M?$"``*````#,@`!-@````-1``'\``!ET``*@>X`62?@````````(```71_&X`. +M@``!>'\;@`^```%\?QN`#(```8!_&X`-@``!A'\;@!&```&(?QN`$(```8T4 +MI``(FX``&12D``B```&='F0`_YN``!44I``(@``!G1YD`/^;@``1%*0`"(`` +M`9T>9`#_FX``#12D``B```&='F0`_YN```D4I``(@``!G1YD`/^;@``%%*0` +M"(```9T>9`#_%*0`"!YD`/\J:``\FH#^<13L``A\0T``?$.``'Q#P`"6P``' +MS```3<]!(6G/@2%JS\$A:X````#,`2%L@````,_U``#,``!9A``$G2IH`#R: +M@``$R"@`%X````#40`!_EH#_JWX"0`"$``*6P`X``LP``$&```&KS,$P2I0` +M``#(/``@1*``!E0``$`:H`@F>@````````(```B'`$@@`@``"+\@4`!&```(VR!0` +M$H```CW,P:*D@``"1ASH`#^```)N?,&`"QS0`#\I*``&*2P`%GZN@`?('``3 +MFH``/004`"Z`````S,&BI,`2"`!\04``?0S`!\`2``@56``#%5P`#'Q"``!] +MT<`&$B``%'X>0`=^3H`'SH&BI(````#-@:'^R!0`$000(1B50```R!0`$=11 +M``"`````S,&BI,@4`!($$"$&E4```,@4`!+440``@````,S!HJ3,P:*D!!`` +M`5P``)R#0`,<@X`##(/``M4W0`('^W@"='N`50S``` +M8L_Z``":0```R"0`)\@H`",ZJ``"FH#__\@H`"/`,``!R"@`))J```#(*``D +MSP``6U#8``@4W``8P#X0`"'<@`!]_<`'S8$A@,W!(8'`'@`@42``"!4D`!A^ +M?D`'$S``'GYR0`=]74`'S@$A@LY!(8/-02&$?$"``*````#,@`!-A``$G1QT +M``$<>``"FT```\@,`"J$``-"R!0`+)N```,$$``0A``#4LS!HF#-`:!@A``# +M#P08"8"$``2=S```9,@\`"Z$``,=R!``*L@<`"\=W``!R"0`*)7```G(-``Q +MR#@`,,@\`"Y3=``@?[>`)T>X!53,``!BS_H``)I```#()``HR"@`(SJH``*: +M@/__R"@`(\@H`"6:@```R"@`)8```M#`,``"!9C``!#<``@4X``8S=D``,@< +M`"+()``B'=P/_\W9``%^8D`'SED``M@840/8&%$$B````-@840<;^`#PP#8( +M`)>```/`,`"`B````,`J``3/02%\SP$A?7`!YG`__[('``E@````7Q`@`!\0,``?$$``!DH`#"6@``( +MR"@`)\@D`"B:0```R"0`)YI```#()``HS``#X'Q!0`!\08``%1P`'\S``,?- +M``#(E<```\`<@`#-P2`0X8,```5<(`#,``!-@````-P?00!\0,``?$$``'Q! +M0`!\08``S,``R`!#(#``I +M4-``"!!4``*```05?16`(,`>`"#(#``J4-``"`A4!``15``"?5&`(,W``&+4 +M6@``?$"``*````#,@`!-?$#``!S0``,1*``!E0``"@:H!!^>@```?$&``(`` +M!"U\0<``@``$,WQ!P`"```0Y?$'``'Q!@`!\0<``%-0`$`54H`"`````S94` +M`,`B``0%F*``?:&`!\P9``"```0IR!@`!,`B``3-@276(B`EU\PA``"```0I +MR!@`!,V!(6W-P2%N@``$*<@8``-\0,``@````,Q,`^`@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8` +M#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/ +.!)8`#P26``\$E@`/!)8` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CAICOS_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CAICOS_pfp.bin.uu new file mode 100644 index 00000000000..004b4fa083b --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CAICOS_pfp.bin.uu @@ -0,0 +1,103 @@ +begin 644 CAICOS_pfp.bin +M?$"``*`````$*``!@````.`#``#,@`!`U$``0'Q`@`"@````!"@``1!,``&8 +MP``%')```LQ``"F```-?S$``*ID```4`````S$``*X```U_,0``LS$``+8`` +M`U_,0``N'(P``LR``$"8P``$S$``0(```U_,``!2@``#7\P``%2`````S$`# +M_<@0`"[(#``M41``('S0P"=\Q0`@510`(,T``$/-0`!#T,``0\R``$#,``!` +MS$``0'Q`@`"@````!"@``<@0`"S(#``K41``('S0P"=\Q0`@510`(,T``$+- +M0`!"T0``0GQ`P`#(&``#R!P``\@@``.5@/_"R"0``Y7`_\#(*``=FH``!,P` +M`%78``/`S```0,@H`!;`+@`$R#``#1JH`"=^\L`'SL``0,P``$#-@`!`S<`` +M0,X``$"6@``#SD``0-"``%S,@`!`S```0,S``$!\0(``H`````0H``'($``L +MR`P`*U$0`"!\T,`G?,4`(%44`"#-``!"S4``0M%``$)\0,``R!@``\@<``/( +M(``#R"0``Y6`_YG(*``#E<#_E\@L`_U^+P`1EP```W[BP`%\`L`&SL.BGLP` +M`&S-``!MS4``;<@P`!V;```$S```5=@``\#,``!`R"P`%L`R``7(-``-&NP` +M)W\W``?/``!`T$``0,V``$#-P`!`S@``0,Y``$"6P``#SH``0-"``%S,@`!` +MS```0,S``$!\0(``H`````0H``'(&``5'9@``7Q"0`"5@`+.?$*``,@<`"#` +M-\``?$#``'Q!``!\M(`&P#8``QJX`>B7@``'T$`#X(0``V+,``!_R#@#X)N` +M``#(.`/@F<```,@<`"!\M(`'$-0``GUE0`#-0`!#SH``0\T``$/,@`!`SD`` +M0,Z``$#,P`!`X#H``)>`_U3-``!`?$#``(```*)\00``'(P``IC```G($``< +MF0``!,@<``:$``-ES```4L@8`!6```".'9@``L@0`!Z9`/_\R!P`"(0``V7, +M``!4R!@`%8```(X=F``"'(P``L@0`!V8P``.R!0`29D```3('``'A``#9@%5``&(!```7T5``.```".?9&`!IE`__C('``'S<`` +M0,P``$"```#+S```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/T +MS0`#]LT``_?-``/X@```!5`/_WR!0`19E```3(&``* +MS8``0,P``$"```%$V``(0'Q`P`#($`!'F0#__`````#,@`!`S,``0-1``$!\ +M0(``H`````0H``'($`!&V``'0,T``$"$``%;S0``0,@,`$.4P``*R!0`2(`` +M`50$$``#R!``1M@`!\#-``!`A``!6\T``$#(%`!(G4```,P``&K(*``6'J@` +M`9J```/`*0`!B````,`L`5;.@`! +ME,``",@4`!R9```*R!P`"(0``V7,``!4@``!='`)WU8P`-\W,`@5-`` +M((```97,@`!`?$&``,R``$"```&2S8``0,`9___,@`!`S8.BGGQ`P`!\00`` +M?$%``,S#H?K-`Z'YS4.BG9P/]C`````-```_J`````?$#``,R``$"`````U$``0'Q`P`!\ +M00``?$.``'Q#P``$'``"SX``0L_``$+-P`!"!!P`!,S``$+-``!"S<``0@0< +M```$(``!?`)``,@4``/(&``#49@`('U90"?(*``#R"P``\@P``/(-``#4NP` +M('ZN@"=3=``@?S<`)W\K0"%^=D`@5J@`/UT`G?65`(%58`"#,``!;S78``,VV``#((`!!F@```,@@`$&` +M```!?$"``'Q`P`!\00``S,`#_LT``__,P`!"S0``0A44`!\9&`#P)UP``7UV +M``:9@``%?5Y`!LP``$*```-?S```3168``$5+``(F8``,1[L``&6```$%3`` +M#(```U_,``!"!!0`!,U``$(?,``!("@``00X``0$/```R!0``\@8``/('``# +MR"```WU=0`U]H<`-?5U`!Q80`!\5G``??1T`!GT70`9^DH`&FT``$@NX``2; +MP/_R"_P``<@,`_Z:@``)R!`#_YL``0;,``!-!!0`!,S``$+-``!"@``"0\U` +M`$*6P`#_S```38```U_,``!.FL```\P``$W,``!.EX#]F>.#``"`````W`,! +M_Y9```3,``!.@``#7\P``$+2``!"R`@``\@,``/($``#R!0``\@8``/('``# +MR"0``\@H``,5_``?%K``'W_SP`84\``??_/`!A5P`!]_\\`&?8B``9?```U] +MS,`!?E$``7Z50`%\D(`,?-3`#)K```-\CT`&)+0``9M``-;,``!-@``#7\P` +M`$[(#`/^R!`#_\S``$*```)OS0``0GQ`P`!\00``?$+``'Q#``#`.P`??$-` +M`'^W@`;`/A``EX#]9GT]``=_/P`'&10`.\P``%N50``3R!0`0#%8``*5@/__ +MR!0`0,P``&,A'(``S,$AA +MA``#8LP``%W((``??$#``,`V_P#($``AP#`__WSU0`9]48`&?8&`"IF```A\ +M\X`&XX,``,^@`$^$``-BS```7H````#40`!_@``#7\P``%Z$``-B?$#``!3< +M``B5P``9'-P`$'Q!``"9P``$4%0`((```QW)'0``?14`)\D>``!\0@``?$)` +M`'Q!@`!]Y<`&?>*`$9J`_-Y!K``%FL````KL``$<`(@+L`","_0`G`8P`'P'Y`"`"*0`H`:X`*0%[`"H!H``K +M`9``+P&I`#(!S0`T`S\`-0%_`#D!]@`\`Q$`/P&[`$$"D@!"`KD`0P+#`$0" +MT`!*`MX`50,S`%8#.@!@`(P`80"Q`&(`V0!C`,,`9`##`&4`PP!F`,,`9P## +M`&@`Y@!I`.\`:@$_`&L!#0!L`0T`;0$-`&X!#0!O`0T`<`$2`',`^P!T`/L` +M=0%F`'L#3`````4````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +9!0````4````%````!0````4````%````!0`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_mc.bin.uu new file mode 100644 index 00000000000..e2caf01f5b8 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_mc.bin.uu @@ -0,0 +1,540 @@ +begin 644 CAYMAN_mc.bin +M``/HX``"O@$```(4``/_```#_P```J`.``'`'``#Z````^@0``/H(``#Z#`` +M`V`@``-@*``",SX``K#_``*Q_P`"LO\``K/_``-A.``#26P``_\```.O"@`" +MM`0``F_T``#Z.P`"M`\``D\4``#Z%P`#0"0``K1```*U#P`#2J8``D1!``/P +M`@`"294``VJF``(M;@`#2$(``TG4```R0P``(A@``#H5``*U$```FD,``D53 +M``/P"``"H'X``_!&``*@8P`#\$0``/(/``(TL``#]````<`D``/H````@@\` +M`T`D``*T0``"M?```TJF``)$00`#\`(``FF5``-JI@`#0````_\```/X`0`# +MQ$```\11``+&10`"`````T`0``/_```#_P```^@@``/H,``#8!```_@#``(S +M.``",G0``T@(``*TGP`"0`0``V@(``-((0`"L\$``D=S``-H(0`#:HD``T@E +M``*SP0`"1W,``V@E``-JC0`#2,```TC&``"",0``BC```,(O``#*+@`#Z!`` +M`^B0``-HP``#:,8``TJD``/H0``#_P```D(D``-JI``#2````T@%``*[/P`" +MO+\``K_O``"2,P``BC0``((X``"Z-@``JCH``D$;``*[^P`"0BL``D`,``-H +M```"15\``V@%``-($``#2=T``KOQ``*\`@``BC<``*HY``)!&P`"81P``V@0 +M``)%6P`"95P``VG=``-`#0`#_P```_\```.A3```B@T``K,"``)#-``#HS`` +M`)H,``*S!``"0S0``Z,R``":"P`"L`@``()!``*P"0``@D(``T@I``-)<``" +MOP<``D`/``.````#``X``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H +M+0`#P00``\$5``-IZ``#:>P``^@```/HT``",!4``VCD``/!W@`",!4``VD$ +M``-`+``#_P```K0"``)$!```HA8``TG6``*U$``"1%L``Z1&``"B&``"H$X` +M`_`#``(T6P`#]````<#%``/T```!TTD``T`.``#R0``#Z/```Z"V``-)U0`` +M^A$``K$/``)"%P`"I2```_`!``#Z0``"0QL``J4C``/P`0``\A$``T````-` +M+@`"MA```K0,```J0``"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`! +M``/HP```XA```T`(``*T````>A$``J`D``/P00`"L@@``J#^``/P00`"L@0` +M`K0_``)")```DB@``TJ4``/_```#8&P``T````/_```"M$```D0$``/P`P`# +MZ````((_``(B^@`#0````_\```*T0``"1!0``_`"``#R/P`"(OH``T````/_ +M```"M$```D04``/P`0`"+C0``TJ4``/_```#8'```T````/_```"M`(``D0D +M``/P`P`#Z````((_``(C,0`#0````_\```*T`@`"1#0``_`"``#R/P`"(S$` +M`TJ4``/_```#830``C,X``-````#_P```_\```)$#@`#\`,``^@```""/P`" +M)%H``C,X``-````#_P```_\```)$'@`#\`(``/(_``(D6@`"+F\``TJ4``/_ +M```#8'0``K````""*P`#0````_\```*T`@`"1$```_`#``/H````@C\``B88 +M``-*E``#_P```V!X``-````#_P```K0$``)$0``#\`,``^@```""/P`"*(P` +M`TJ4``/_```#8'P``T````/_```"M!```D1```/P#``#Z````((_``(I4``` +M`@T``_\```/_```"I`X``_`$``#R#@`"*5```^@```""#@`#2I0``_\```-@ +MK``#0````_\```*T(``"1$```_`#``/H````@C\``BM@``-*E``#_P```V"P +M``/H````@C\``K#_``*Q_P`#P2```VA@``-H:``#0````_\```*T$``"1$`` +M`_!"``/T```"`8\``T`-``-`)@`"L4```K(0``*S"``"010``Z$:``)")``# +MHB0``F(A``)#.``#HS```F(C``"2*P`"I!X``_`)``-)/0`"LH```\`B``)$ +M0@`"*5```TD]``/_```"LH```F1"```"$``#_P```K0!``)$!``#\`0``^@` +M``""/P`#P?X``BP4```"$``#_P```K0"``)$!``#\`0``^@```""/P`#Z/`` +M`BP4``-````#_P```_\```)$+@`#\`,``^@```""/P`"-9X``T````/_```" +MM!```D0D``/P`P`#Z````((_``(VOP`#^`,``TJ4``/_```#8+0``K````"" +M*P`#0````_\```*T`@`"1$$``_`"``#R/P`")A@``TJ4``/_```#8+@``T`` +M``/_```"M`0``D1!``/P`@``\C\``BB,``-*E``#_P```V"\``-````#_P`` +M`K00``)$00`#\`L``/(_``(I4````@T``_\```/_```"I`X``_`$``#R#@`" +M*5```^@```""#@`#2I0``_\```-@[``#0````_\```*T(``"1$$``_`"``#R +M/P`"*V```TJ4``/_```#8/```/(_``*P_P`"L?\``\$@``-H8``#:&@``T`` +M``/_```"M!```D1!``/P0@`#]````@(.``-`#0`#0"8``K%```*R$``"LP@` +M`D$4``.A&@`"0B0``Z(D``)B(0`"0S@``Z,P``)B(P``DBL``J0>``/P"0`# +M23T``K*```/`(@`"1$(``BE0``-)/0`#_P```K*```)D0@```A```_\```*T +M!``"1`0``_`#``#R/P`#P?X``BP4```"$``#_P```K0(``)$!``#\`,``/(_ +M``/H\``"+!0``T````/_```#_P```D0^``/P`@``\C\``C6>``-````#_P`` +M`K00``)$-``#\`(``/(_``(VOP`#2I0``_\```-@]``#^`,```(8``/_```# +M_P```J`.``/P0@`#]````@)L``-`+``#_P```K0@``)`0``"H`0``_!(``/H +M````@C\``C'4``(R&0``\C\``C'4``(R&0`",K```T````/_```"M`@``D0$ +M``/P#``#2`@``_\```*T0``"8`0``V@(``-)F``"M/T``D$4``-IF``#Z#`` +M`\$N``-H,``",L0``^@```/H$``#Z#```K(#``-H,``#0````_\```*U"``" +M114``_`!``(T_@`#2I0``_\```-@^````D```_\```/_```"H0X``_`"``/H +M````@A0``BYO``-(```#2`4```HT```".```$C,``"HZ```Z-@`#_P```V@` +M``-H!0`#2!```TG=```*-P``*CD``_\```-H$``#:=T``TEQ``*R`0`#Z#`` +M`\$&``/!%P`#:#```TEL``*U%@`"H%$``<*?``*PSP`"L04``K(!``*S```# +M:#```C+$``*PM``#:#```C+$``*PO``#:#```C+$``*PN``#:#```C+$``*P +MRP`#:#```C+$``*PC``#:#```C+$``*PT0`#:#```C+$``/H```#Z!```K(# +M``*S```#:#````(8``/_```#_P```J`.``/P0@`#]````<`````!]``#0!(` +M`T`5```*&P`"H`X``_`"``/T```!PL\``L$>``"*&P`":[H``F5;``+&;@`# +M\$$``L=^``-@%0`"L@\``D1"``*E%``#\`<``^B@``/HL``#8!(``^@```"! +M]``#]``````/P`P`#Z$```_0```/P00`# +MA.H``]A```/?<``_@#``/4G@`#^P```P_^``(#&``#^`$``X7D``)$ +M%0`"`R\``"'Y``*@W@`#\`,``&'Q``/T```#\$$``&'P``*_"``#W$```]C` +M``/X`P`#U)X``_L```,/_@`"`RL``_@#``/L`````A0```I```!J/P`#_P`` +M`D`!``*@#@`#\`$``^P```-).``"H-X``_!!``-*7``"N/X``D(H``*@W@`# +M\`,``VDX``/T```#\$$``VI<``-)T``"M`0``F$4``*R`0`"LQ(``J#>``/P +M00`"LQ$``V@P``-)<0`"N.\``KD$``/!!@`"87D``D,X``-H,``#2`D``KC] +M``)$2``#:`D``BY%``-)H``"M!$``\$D``*Q#P`#::```TI$``*T_@`"81X` +M`VI$``)!%``#:D0``J#>``/P`P`#0F$``_0```/P00`#0ET``_\```/_```# +MZ&```VFE``-H:P`"N@P``KC```/<@0`#V*$``K#X``*Q!P`#Z"```^@P``/^ +M```#U!\``VAK``/H\``"(_\``B/B``(D'``"H?X``_!!``-B>@`#0G@``_\` +M``/_```"H(```<.3``*@D0`!PY,``J"B``'#DP`"H+,``<.3``+/_@`"O`P` +M`J'\``/P0@`#]````<-]``#Z!``#Z/```B/B``(C_P`")!P``T)X``/_```# +M_P```J"```'#J0`"H)$``<.I``*@H@`!PZD``J"S``'#J0`"S_X``KP,``*A +M_``#\$(``_0```'#E@``8@0``/H#``/_```"I<\``<.Y``*E_``!P[0``^CP +M``/HP``#]````<.\``,,SP`#K,```^CP``/T```!P[P``P_\``.O\``#Z,`` +M`B/_``/!_``"(^(``TDX``*@W@`#\$$``TI<``/_```"8BX``J#>``/P`P`# +M:3@``_0```/P00`#:EP``TG0``*T^P`"010``K(!``*S$@`"H-X``_!!``*S +M$0`#:#```TEQ``*X[P`"N?L``\$&``)!>0`"0S@``V@P``-("0`"N/T``D1( +M``-H"0`"L!@``B1```/L```#1+D``J#>``/P00`#1/D``\$/``/!'P`#P2\` +M`\$_``/!3P`#P5\``J#>``/P!0`#9+```V2T``-DN0`#]````_!#``-D\``# +M9/0``V3Y``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P```-$ +MN0`"H-X``_!!``-$^0`#P0\``\$?``/!+P`#P3\``\%O``/!?P`"H-X``_`% +M``-DK``#9+P``V2Y``/T```#\$,``V3L``-D_``#9/D``TC(``*T\P`"M00` +M`D`$``)@!0`#:,@``D`$``-HR``#[````K`0``(D0``",L0``C+$``(RQ``" +M,L0``C+$``-*'``")$P``\&,``-*(``")$P``XS&``)HC``#2B0``B1,``/! +MG``#2B@``B1,``.,Q@`":9P``THL``(D3``#P:P``THP``(D3``#C,8``FJL +M``-*-``")$P``\&\``-*.``")$P``XS&``)KO``#[````VAK``*Y"``"N,`` +M`]R```/8D``#Z!```^@@``/H,``#_@```]0>``-H:P`#[````^C```.'/``# +MIW8``X8L``.F:``#A1P``Z5:``.$#``#I$P``FS'``)LQ@`";,4``FS$``/L +M```#0"0``_\```/_```#H`8``J$.``/P`0``@@<``TFD``-)H0``:C\``XOJ +M``/`JP`"1:4``J#>``/P`P`"0Z,``_0```/P00`"8[,``VFD``-IH0`"LO\` +M`K'_``*P?P`#:&```^@```/H(``#Z#```J#>``/P`P``"@D``_0```/P00`` +M"@@``KC```-H:P`#V````]R```/4'@`"OP(``BY!``.`X```@@0``((#``/H +M````@@(``((!``#R```#2%0``J#>``/P`P`#A.@``_0```/P00`#A.H``F(D +M``-H5``#29@``XCE``/!/@`"H-X``_`!``.#,``#P2X``F`(``-H,``#274` +M`XCF``)@:``#P1<``\$N``/!/@`"H-X``_`!``.#,``#:#```TA4``*@W@`# +M\`,``X3H``/T```#\$$``X3J``/`1``"0B0``VA4``*_`@`"+D$```(8``/_ +M```#_P```J`.``/P`@`#]````@36``(P)P`#Z'```X3F``)&2P`"H&0``_!/ +M``-)T@`#Z&```XJR``.JJ@`#A*8``F1*``/!5``"H-X``_`#``-HY0`#]``` +M`_!!``-I!0`#]````<6!``*_"``"3_D``Z_T``.+L@`#J[P``B6E``/T```" +M!8$``T`,``/_```"OP@``D_P``/P0@`#]````<3S``*_```"NP$``B6E```" +M$0`#_P```_\```*@#@`#\$(``_0```'%@0`"L0(``K`1``+$0``"Q5```J#> +M``/P`P`#:.4``_0```/P00`#:04``P$>``($Z```\@(``/(!``*@W@`#\`,` +M`'H&``/T```#\$$``'H%``.-X@`#W-```]CP``.)Y@`":9X``/'R``!"!P`# +MZ-```X_@``/!J``#C.T``.'V``#B/@`"+Y```K@`#8G$``_0```($_@`"H5X``_`. +M``!J/P`#P9$``\&S``*@W@`#\`,``V$N``/T```#\$$``V$R``+`@0`#J``` +M`L*C``.J(``#A5```*H6``.!X``#`(0``_`D``*AA``#\`$``L1!``,$3@`# +MP50``P*F``/P)``"H:8``_`!``+&80`#!FX``\%V``/47@`"8`(``@56``!J +M/P`"OP(``BY!``-)<0`#@>0``\$&``.B;``"H"X``@6!``)A<0`#P2X``\$^ +M``*@W@`#\`$``X,P``.&8``#\$<``V@P``./[0`"+D$``X_M``(N00`#C^T` +M`BY!``./[0`"+D$``TEU``/!+@`#P08``\$7``/!/@`"H-X``_`!``.#,``# +M:#```TF8``/_```#P3X``J#>``/P`0`#@S```\$N``-H,```"@\```'T``/_ +M```"01X``_`!``/L```"I0X``_!(``-`$0`"H-X``_`#``)F;@`#]````_!! +M``)G?@`#8!$``^@```"!]``#[````C+$``-*0```0@```$H$``!2`P`"O#,` +M`D0,``)%'``"9$4``D8L``)'/``"9F<``F1&``*A3@`#\`$``K0!``*@C@`# +M\`4``J1)``/P0P`"I$L``_!!``#R`@``H@0``KS,``)$#``"11P``D8L``)' +M/``"9$4``F1&``)D1P`"H4X``_`!``*T`0`"H(X``_`%``*D2@`#\$,``J1+ +M``/P00``\@$``*(#``/H0```H@```T,I``*@W@`#\$$``T-I```"`@``$@$` +M`K$/``*S!P`"I?X``@7[``*@#@`#\`8``KP/``*D00`#\`$``KP)``/!3``# +MP5P``J`N``/P!@`"O`\``J1A``/P`0`"O`D``\%L``/!?``"H-X``_`#``-C +M*0`#]````_!!``-C:0`"3`(``J#.``/P!@`"S_X``KP)``*E_``#\`(``_0` +M``'%I0`#2.4``J#>``/P00`#204``K@1``*@#@`#\`$``L1(``))00`"I),` +M`_`!``#R`@`"H"X``_`!``+%6``"25$``J23``/P`0``\@$``J#>``/P`P`# +M:.4``_0```/P00`#:04``D`"``*@#@`"!:4``^P```!J/P`#Z````C`!``-) +MF``"N`\``K7U``*S`0`"H-X``_`!``.#,``#P2X``F`(``)!%0`#:#```K\` +M``(N00``\?\``^@```"!_@`#0`P``T`M``*X$``"N0@``DH8``.JI@`"2TD` +M`ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`!``*S!@`#0"T```H1``*P0``" +M0$```_!!``/H,``"01X``_`!``/H,```F?T``BY%``*\`0`"H-X``_`)``-( +M(0`#C,8``X9F``.F9@`"9FP``V@A``-JB0`#]````_!'``-()0`#C,8``X9F +M``.F9@`"9FP``V@E``-JC0`",9L``K\#``(QH0`#2`@``X3J``"!]0`"8`0` +M`V@(``*_9``"+D$``&H_``/_```#_P```J#>``/P`P`"NP```_0```/P00`" +MNT```-GO``/!#@`#P1X``X$6``)A'@`#@N8``VI$``/!'@`#@18``^@@``-J +M1``#Z````\````/!$``"LOT``VA@``-*8``"O_<``K$3``)`#P`"8`X``VI@ +M```R#```.@L``KP(``*__@`#AFH``F(F``*D?@`#\`$``K,$``)`#P`"8`P` +M`VI@``./X0`"+D$``VAK``/_```#_@```&(]``!:/``#_P```]C!``/``."YP`#:D0``X$&``/H +M(``#:D0``C&;``-`+```6BL``K0$``/H\``"1$```_`!``*_`0`"I+X``_`! +M``*_!``",:$``/(G``#R)0`"L/\``K&_``/!(``#:&```K`!``/H$``#Z"`` +M`^@P``-J8```"CL``!(,```:"P`"L`(``J#>``/P00`"L`0``X(J``*D/@`# +M\`$``K,$``.!%@`"8`$``K$S``-J8``#0`H``K`!``*Q`@`"L@```K,!``*@ +M*P`#\`(``^@@``/!.P`#:F@``\$.```20@`"0`D``_`!``/H(``"L!,``K$" +M``.")@`#Z#```VIP``-`+0``8A$``!(H``*_0``"3T\``_`#``*@S@`#\`$` +M`K((``*P(0`"L0(``K,!``-J=```"BL``K`!``/_```"I!X``_`%``*Q!``" +ML@```K,"``/T!``#\`,``K$"``*R#P`"LP$``VIX``-*?``#_P```K`!``*Q +M`@`"LP0``VI\```!_@`#_P```_\```+`#@``@?X``C&6```")P`#0`H``T`- +M``*@#@`#\`4``K`!``)`!0`#@`8``_0$``/P`P`"L`0``D`)``.``@`"L0,` +M`F@!```"*P`#_P```_\```*D#@`#\`L``!(H``*P(P`"L0,``K,!``-J=``# +M2GP``_\```*P`0`"L00``K,$``-J?``#2F0``K2````1[P`"0`0``F`(``.B +M(@`"LP$``VID``(P6P`",&@```'_``/_```#_P```J`.``/P3@`#0"P``KP$ +M``/``/P`0`#Z/```]CP``*\"0`"OS\``DL?``(NT0`#Z/`` +M`/G_```!_@`#_P```_\```+`#@``@?X``T`E```:$``"L@0``D(@``*@W@`# +M\$$``Z,R``*Y`@`"29,``F(I``*Y@``"294``F(I``*YA@`#Z(```J`I``/P +M00`#P8X``,':```)_0`#0"X``_\```*@`0`"!YD``K`!``)!"``#\`4```)` +M``/_```#_P```J`.``('F0`#2G0``'HH``/_```#_P```\$O``-J=``",98` +M``(G``-`"@`#0`T``J`.``/P!0`"L`0``D`%``.``@`#]`0``_`"``*P$``" +M0`D``'G:``*Q0P`#_P```J#^``/P00`"L2,``F@!```"*P`#_P```_\```*@ +M#@`"!\L``!(H``*P0P`"L00``K,!``-J=``#2GP``_\```*P`0`"L04``K,$ +M``-J?``#2F0``K2````1[P`"0`0``F`(``*X(``"8`@``KB_``)`"``#HB(` +M`\$^``-J9``#]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``/!/@`# +M:F0``C!;``(P:```0A```K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```'' +M[``#0`X``K`0``/_```"00D``J`0``('[````B<``_\```/_```"P`X``((G +M``*Q`@`"I`$``@``/P1@`#Z/```K$D``+(@0`# +MV(```L`!``/8@0`",%(```'^``/_```#_P```L`.``"!_@``>=H``C&6``*@ +M_@`#\$4``K`/``/!$``#P2```\$P``-J@``#0`H``K!```/_```"0`D``Z`" +M``*Q`P`":`$```(K``/_```#_P```J0.``/P"P``$B@``K!#``*Q!0`"LP$` +M`VIT``-*?``#_P```K`!``*Q!@`"LP0``VI\``-*9``"M(```!'O``)`!``" +M8`@``Z(B``*S`0`#:F0``C!;``(P:``#0"4``$(0``*P(``"0`4``_!(``*P +M`@`"H-X``_!!``.``@`"0`@``_`"``/T```!R%P``!'^``*P@``"LP,``J`C +M``/P0P`"0`4``_`!``(Q7``#0"X``_\```*P"``"00@``J`0``((7``"L(`` +M`D$(``/P!0```D```_\```/_```"H`X``@A<```")0`#_P```_\```/H$``` +MBB4``J0.``(';@```>\``$'Y``/_```#_P```]@```/<@```>D(``K````/8 +M`0`"L`$``]P!``-`#0`"O2```_\```)-U0`"IMX``_`#``(N\0`#]`0``_`* +M``*P?P`"L?\``K+_``-H8``#:&L``!'E``*SP``#Z-```V!,``(O+``",9L` +M`C&6```A]0`#_P```T@(``/_```#P00``V@(``/L```#Z````^@0``*@W@`# +M\`,``VD<``/T!``#\`$``VDT``/L````:C\``_\```/_```"H-X``_`#``*[ +M8@`#]````_!!``*[:``#_P```_\```#9_``",EH``^@```(P`0`"NP(``-H^ +M``-(`0`"L+\``D1```-H`0`#29@``K0/``*U_0`"8`0``D$5``/!+@`#P3X` +M`J#>``/P`0`#@S```V@P``-("``"M$```('U``)@!``#:`@``^@```*Q8``# +MZ"```^@P``-IH``#Z````K$0``/H(``#Z#```VI$``*P`0`#Z!```^@@``/H +M,``#:F```K\"``(QH0`#Z````\````/!$``"LOT``VA@```*.P``$@P``!H+ +M``*P"@`"H-X``_!!``*P#``#@18``F`!``."*@`"L0P``F(A``*D/@`#\`$` +M`K,$``*Q%@`#:F```X_A``(N00`#:&L``_\```/^```", +M``/P`P`#2"(``_0```/P00`#2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X` +M`_`$``-H(@`#:HH``_0```/P0@`#:"8``VJ.``/H<``"IKX``_`"``/T```! +MR1$``T`2``#Q]``"OP0``J#>``/P`P`":J\``_0```/P00`":[\``V`2``/T +M```!R4<``C&;``(QE@``(?4``_\```-("``#_P```\$$``-H"``#[````&H_ +M``#Q_P`#Z````((3``-`"``#0"T``KA```*Y"``"2@@``ZJJ``)+20`#J[0` +M`K,$``)OJP`#\$$``K,"``)/JP`#\`$``K,&``-`+0``"A$``K!```)`0``# +M\$$``^@P``)!'@`#\`$``^@P``":$@``(?0``^A0``/_````HAD``*GT``!J +M/P`#_P```_\```*@W@`#\`,``%GQ``/T```#\$,``%GP``/_```#_P```-GO +M``-(```#A.H``\!$``/_```"0`0``V@```-(!``#P'X``_\```/_```"0S<` +M`V@$``-`+```6BL``K0$``/H\``"1$```_`!``*_`0`"2[X``J"^``/P`P`" +M,,,``_0```')F0`"O\L``C,-``#R)@``\B4``K#_``*QOP`#P2```VA@``(Q +MFP``"CL``!(,```:"P`"L`(``J#>``/P00`"L`0``X$6``)@`0`#0!4``X(J +M``*Q@``"8B$``J0^``/P`0`"LP0``K;P``)$1@`"L0@``F$4``-J8``#0`H` +M`K`!``*Q`@`"L@```K,!``*@*P`#\`(``^@@``/!.P`#:F@``K`!```200`" +M0`D``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``-`+0``8A$``!(H``*_ +M0``"3T\``_`#``*@S@`#\`$``K((``*P(0`"L0(``K,!``-J=```"BL``K`! +M``/_```"01```J0>``/P!0`"L00``K(```*S`@`#]`0``_`#``*Q`@`"L@\` +M`K,!``-J>``#2GP``_\```*P`0`"L0(``K,$``-J?```"BL``_\```/_```" +M01X``J0>``(*-````A,``_\```/_```"P`X``((3``(QE@```B8``T`*``-` +M#0`"H`X``_`%``*P`@`"0`4``X`$``/T!``#\`,``K`(``)`"0`#@````K$# +M``)H`0```BL``_\```/_```"0`X``J0.``/P"P``$B@``K`C``*Q`P`"LP$` +M`VIT``-*?``#_P```K`!``*Q!``"LP0``VI\``-*9``"M(```!'O``)`!``" +M8`@``Z(B``*S`0`#:F0``C!;``(P:````?\``_\```/_```"H`X``_!.``-` +M+``"O`0``]S```*_P``"H-X``_`!``*_@``#V/```XSD``*_/P`"2Q\``B[1 +M``/H\```^?\```(3``/_```#_P```L`.``""$P``6BL``'HE``*X"``"2KX` +M`J"N``'*6``#JK```DJN``/P0P`"+2X``_0```'*5``#2G```KJ(``*Y<``" +MH/@``_!#``/!*@`#]``````/P00`#@`(` +M`D`(``/P`@`#]````\``_\```/``/P`P`"+O$``_0$``/P"@`"L'\``K'_``*R_P`# +M:&```VAK```1Y0`"L\```^C0``-@3``"+RP``C&;``(QE@`#[````&H_``/_ +M```#_P```J#>``/P`P`"NU,``_0```/P00`"NUL``_\```/_````V?P``T`0 +M``*[#P`#2"D``J#>``/P00`#2"T``K\$``)`"P`#JP(``P_[``.,]@`";,\` +M`X_V``-)Z``"HTP``_`$``,$3``#!5\``_0```/P10`#A.8``X56``.E5@`" +M950``F1.``/!!``#P14``J#>``/P!``#:"D``VGH``/T```#\$(``V@M``-I +M[``#Z````C`5``-(`0`"L+\``D1```-H`0`#Z````K%```/H(``#Z#```VI$ +M``(QFP`"OP(``C&A```*.P``$@P``!H+``*P`@`"H-X``_!!``*P!``#@18` +M`F`!``."*@`"L80``F(A``*D/@`#\`$``K,$``*Q&``#:F```T`*``*P`0`" +ML0(``K(2``/H,``#:F@``K"````200`"0`@``_`!``/H(``"L!,``K$"``." +M)@`#Z#```VIP``*P(0`"L0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,! +M``-J>``#2GP``_\```*P`@`"L0(``K,$``-J?``#Z````\````*QOP`#P2`` +M`VA@``/H<``",98``TID``*T@```$?P``D`$``*T`P`"8`0``K,0``-J9``" +M,%L``TID``*T"``"1$```F=T``*E?@`"#!$``^@```(P%0`"H-X``_`$``-( +M*@`#2>@``_0```/P0@`#2"X``TGL``*\$0`"OQ```LF?``+(C``#P0@``\$9 +M``*@W@`#\`0``V@J``-IZ``#]````_!"``-H+@`#:>P``KL!``#:/@`#Z'`` +M`XOE``.+M@`"I8L``_`"``/T```!R]0``T`2``#Q]``"OR```J#>``/P`P`" +M:J\``_0```/P00`":[\``V`2``/T```!S!$``C&;``(QE@`#[````&H_``/H +M````@=D``K`(``"!^P`"H-X``_`#``!9\0`#]````_!!``!9\``"L'\``J'^ +M``/P00`"2[```-GO``*P_P`"L;\``\$@``-H8``",9L```H[```2#```&@L` +M`K`"``*@W@`#\$$``K`$``.!%@`"8`$``X(J``*Q@``"8B$``J0^``/P`0`" +MLP0``T`5``*Q"``"MO```D1&``)A%``#:F```K`!``*Q`@`"L@```K,"``-J +M:```$?L``K`3``*Q`@`#@B8``^@P``-J<```$B@``K`A``*Q`@`"LP$``VIT +M``*P`0`"L0(``K(/``*S`0`#:G@``TI\``/_```"L`$``K$"``*S!``#:GP` +M`KP$``/>\``&'[``*[&``#V/```B[1```!V0`#0"4``K\0``+`#@`` +M@=D``D]?``/P`P`"+2X``_0```',\``K"```/H\``"H<```_!!``/!_@`"+.$``C&6 +M```1[P`#Z!```K`C``.B(@`"LP$``VID``(P6P``8=D```'O```)^0`#0"8` +M`K(0``/8```#W!```'G[``*P```#V`$``K`!``/<`0`"0BD``_!%``.O\``" +MH,X``_`"``/[```#^P$``]">``/[```"I2X``_`!``/[```#U)\``_L!``*E +M+@`#\`$``_L!``,/_@`"#)4```'9``/_```#_P```L`.``"!V0``8>\``K"` +M``/!_@`"H<```_!!``/H\``"+.$``C&6```1[P`"L`,``^@0``.B(@`"LP$` +M`VID``(P6P`",&@``T`E```!V0`"L0,``K((``*S$``"0S4``_`"``)")0`# +M\`(``J4!``',8```8?D``%GO``/_```#W,```]BP``*P```#V`$``K`!``/< +M`0``>?L``T`-``*]0``#_P```DW5``*FW@`#\`,``B[Q``/T!``#\`H``K!_ +M``*Q_P`"LO\``VA@``-H:P``$>4``K/```/HT``#8$P``B\L``(QFP`",98` +M`^P```*\$0`"H-X``_`$``-(S``#2-$``_0```/P0@`#2.P``TCQ``(M&0`" +MH-X``_`$``-HS``#:-$``_0```/P0@`#:.P``VCQ``*@W@`#\`0``TC4``-( +MV0`#]````_!"``-(]``#2/D``BT9``*@W@`#\`0``VC4``-HV0`#]````_!" +M``-H]``#:/D``J#>``/P`P`#2-P``_0```/P00`#2/P``J#^``/P!``"P`P` +M`L$<``/T```#\$(``P`,``,!'``"H-X``_`#``-HW``#]````_!!``-H_``# +M[````J#^``/P"@`"P`P``L$<``+"+``"PSP``L1,``+%7``"QFP``L=\``/T +M```#\$@``P`,``,!'``#`BP``P,\``,$3``#!5P``P9L``,'?``#[````K!_ +M``*Q_P`"LO\``VA@``-H:P``">4``^@```.@`P`#W````]@0``-`,0`"OP,` +M`KP"``*F_``#\$$``\$'``*@_``#\$$``\$&``*@_@`#\$$``\$%``*A_@`# +M\$$``\$$``/!$``#P2```\$P``/^```#U!X``VAK``/[```##_X``@T[``-` +M-0`"OP,``_\```*F_``#\$$``\$'``*@_``#\$$``\$&``*@_@`#\$$``\$% +M``*A_@`#\$$``\$$``/!$``#P2```\$P``/^```#U!X``VAK``/[```##_X` +M`@U3``-`.``#0#T``_\```-JA``#:H$``^P```-A4``#854``V%:``-A7P`# +M2%0``_\```/H,``#HS,``VA4``-H:P`#2%4``^@```/H<``"LN\``K'_``*P +MOP`#:&```VAK``-)?``"M`0``F$4``-I?``#23P``_\```)A'@`#:3P``TJ4 +M``-!.0`#_P```_\```*F-P`#\`<``J8F``/P!0`"IA4``_`#``*E!``#\`$` +M`V$X``-@_``#_P```_X```/_```#2&0``K00``)")``"H"0``_!#``(MVP`# +M]``````#]``````-J1``#_@```]1?``-H:P`"M!D``_X```/47P`#:&L``TFE +M``/_```#_P```\$$``/!%0`#@N```F(F``/!-P`#::0``KD(``,)G@`"#LT` +M`VFE``/L```"H;X``_`*``/0'@`##[X``_@#``,`#@`#`1X``P(N``,#/@`# +MU!X``P_^``(.U@`#^P```PS.``(.T0`#[````J&^``/P"@`#T!X``P^^``/X +M`P`"P`X``L$>``+"+@`"PSX``]0>``,/_@`"#N8``_L```,,S@`"#N$``^P` +M``/0G@`#T!\``KP_``)(C``"29P``DJL``)+O``"1`P``D4<``)&+``"1SP` +M`KP@``+`A``#H````J-(``/P00`"P`P``L&5``.A$``"HUD``_!!``+!'``" +MPJ8``Z(@``*C:@`#\$$``L(L``+#MP`#HS```J-[``/P00`"PSP``^C0``., +MZ0`#!(```NB-``,%D0`"Z9T``P:B``+JK0`#![,``NN]``-B;@`"2(P``DF< +M``)*K``"2[P``]2>``-";@`"9$4``F1&``)D1P`"#Q,``&H_``/[```#^P$` +M`P_^``(.\0`#[````]">``/0'P`"O#\``DB,``))G``"2JP``DN\``)$#``" +M11P``D8L``)'/``"O"```L"$``.@```"HT@``_!!``+`#``"P94``Z$0``*C +M60`#\$$``L$<``+"I@`#HB```J-J``/P00`"PBP``L.W``.C,``"HWL``_!! +M``+#/``"O`<``J/<``/P3@`#<$P``U!.``/_```#_P```_X```/4'@`#:&L` +M`_L```-P3@`#4$P``_\```/_```#]`0``_`(``*\"``"I-P``_`!``-JA``" +MO`D``J3<``/P`0`#:H```K#_``*QOP`"LO\``VA@``/[```#^P$``LW>``*F +MWP`"#RP``TID``*T@``"0`0``VID``*P```"L0```K(```*S`0`#:G0``K`Q +M``*Q!@`"L@0``K,```-J>``#2GP``_\```*P`0`"L0$``K,```-J?``#2F0` +M`K2```)`!``"M`,``F`$``-J9``",%L``TID``*T@``"0`0``VID``!J/P`" +M,S@``^P```!9]@``8CX``_\```*AO@`#\$(``/'T``/L```"H``+& +M;P`#P78``]1>``+&;P`#P78``]1>``,,S@`"#\P``FN*``(/D``#[````T)P +M``!2%@`#C^P``XCJ``.JH``"I*X``_`&``*A2``#\$$``L1(``*A:``#\$$` +M`L9H``.*X``"ID\``_!#``,$2``#``@``P$8``*F;P`#\$,``P9H``,"*``# +M`S@``PJN``(/WP`#P50``\%V``/47@`#8G```^P```/!8@`#!FX``]P0``/8 +M```#T)X``_\```/_```"2(4``FB#``/!F``#P:@``\&X``/4G@`#^P```P9N +M``(/]``#[````\$0``/!(``#P3```J#>``/P"``#:0@``VD,``-I$``#:10` +M`VD8``-I'``#]````_!&``-I(``#:20``VDH``-I+``#:3```VDT``/L```# +MP1```\$@``/!,``"H-X``_`'``-HS``#:-```VC4``-HV``#:-P``_0```/P +M10`#:.P``VCP``-H]``#:/@``VC\``/L```#2=0``_\```.`Y0`"00,``TG2 +M``/_```"0`H``TG"``*E$``#\`$``TG&``/L```"L'\``K'_``*R_P`#:&`` +M`VAK``/H```#Z!```\$N``*S,``#::0``^@```*Q,``#Z"```^@P``/H0``# +MI4,``]A```/<4``#_@```]0>``-H:P`#^P```_L```*P$@`#Z!```_X```/4 +M'@`#:&L``PB.``(03``#[````]">``/[```#_P```_\```/4GP`#^P$``P_^ +M``(04@`#[````_@!``*_!``#2F0``_\```/_```"00\``A!=``/X`P`#:&L` +M`_\```/_```#_@```^P```-*9``#_P```K\(``)!#P`"H!\``A")``-`$@`" +MM1```J4E``/P!``"OP(``FJO``/T```!T(8``L15``*E)``#\`0``K\"``)K +MOP`#]````="&``+$10`"I20``_`$``*_$``":J\``_0```'0A@`"OQ```FN_ +M``#Q]``#8!(``C"*``/L```#2G```_\```/!P@`#0"X``K`!``-JJ``#_P`` +M`_\```/_```#2JP``K0"``-JJ0`#P````\`1``/`(@`#P#,``TJM``*_D``" +MH,\``_`%``/`1``"OP\``D]/``/T```#\$$``\#T``*@W@`#\`L``T`9``/_ +M```#_P```F1```)E40`"9F(``F=S``-@&0`":J\``_0```/P20`#0!T``_\` +M``/_```"9$```F51``)F8@`"9W,``V`=``)KOP`#8"X``^P```+$1@`#:JD` +M`_\```/_```#_P```TJL``/L```"L'\``K'_``*R_P`#:&```VAK```)Y0`" +ML,```]P```/8$``"H/X``_`$``/H```#Z!```^@@``/H,``"H/X``_!$``*P +M50`#P1```\$@``/!,``"H/X``_`$``*T_P`#P50``\%D``/!=``"H/X``_!$ +M``*TJ@`#P50``\%D``/!=``"O`<``J/^``(1/P``0@T``_\```/_```"H(X` +M`A$%``*@W@`#\`,``T!"``/T!``#\`$``T!&``#J/P``:@X``J3>``/P!``# +MP(@``\"9``/`J@`#P+L``F`(``)A&0`"8BH``F,[``)D2``"95D``F9J``)G +M>P``:C\``_\```/_```#_@```]0>``-H:P`#^P```PS.``/^```#U%X``VAK +M``/[```##,X``A$%``!"#0``8@X``_\```*@C@`"$2H``T!*``*DS@`#\`0` +M`\"(``/`F0`#P*H``\"[``*DW@`#\`(``\&*``/!FP`"N@\``DJH``.+I@`" +M:JL``KOP``)+N``#I[8``FNW``/T!``#\`,``^A@``/HH``#Z+```K3P``)@ +M2@`#P1```\$@``/!,``#:H0``J#^``/P`P`"M/```_0$``/P`0`"M`\``F!+ +M``/!$``#P2```\$P``-J@``#[````_X```/4'@`#:&L``_L```,,S@`"N0,` +M`J#Y``/P1``#Z$```^A0``/H8``#Z'```_X```/47@`#:&L``_L```,,S@`" +M$4L``K#P``*Q_P`"H/D``_!"``/H```#Z!```\$A``/!,0`#:H0``VJ```/L +M```"L'\``K'_``*R_P`#:&```VAK```)Y0`"L,```]P```/8$``"M/\``\%D +M``/!=``"O`<``_X```*U_P`#U%X``VAK``/[```##,X``_X```*U[P`#U%X` +M`VAK``/[```##,X``A%I``*U_P`#:H4``K#P``/!$``#P2```\$P``-J@``# +M2F(``C&6``/H\``",:@``VIB```)Y0`"L,```]P```/8$``"M/\``\%4``/! +M9``#P70``KP'``/^```#U%X``VAK``/[```##,X``A&+``*P_P`"L;\``\$@ +M``-H8``#[````TID``*T@``"0`0``VID``/L```"L`$``^@0``/H(``#Z#`` +M`VI@``/L```"L`0``J#P``/P`P`",,,``_0$``/P`0`"+2X``^@```/````# +MP1```K+]``-H8```"CL``#(,```:"P`"L`H``J#>``/P00`"L`P``X$6``)@ +M`0`"L18``J0^``/P`0`"LP0``X9J``*R`@`"M`0``J/^``/P`P`"H/0``_`! +M``*R!``"8B8``VI@``./X0`"+D$``VAK``/_```#_@```^P```-*8``#_P`` +M`^@P``)@#@`#:F```TID``*T\@`"0`0``VID``/L````:C\``T`$``/_```" +MN`0``D7@``*@7@`#\$0``J#>``/P0@`#0"0``_\```!A^``#_P```_\```/< +MP``#C^H``J#>``/P`0`#Z/```]CP``.,Y``#P;(``TD]``*@W@`#\$$``TE! +M``/_```"1&X``_`!``*\!P`"0`@``_!#``(NT0`#]````_!!``(NX0`"1&X` +M`_`)``/HP``#JV(``Z5@``)%7@`#\$,``B[1``/T```#\$$``B[A``/L```# +M2,```TC%``/H$``#Z%```J#>``/P"``#:,````(Q```*,``#_P```_\```-H +MP``#]````_!&``-HQ0``(B\``"HN``/_```#_P```VC%``/L````:C\``_\` +M``/_````4?D``J#>``/P`P``6?$``_0```/P00``6?```_\```/``/P0P`"+M$``_0```/P00`"+N$``^P```*@W@`#\`,``T@A``/T```# +M\$$``T@E``/_```"NP$``Z)F``.!9@`#H18``X=V``)@)P`#``L``Z<&``." +M!@`"9B$``J#>``/P!``#:"$``VJ)``/T```#\$(``V@E``-JC0`#[````X_M +M``(N00`#Z#```X+@``/H$``#Z````V@P``./[0`"+D$``^CP``-)<``#Z'`` +M`K8!``/!40`#P4```V@Q``*X_``#P5,``\%"``)%6``#270``C+$``-H,0`# +MP5$``\%```(RQ``#:#$``\%3``/!0@`#29@``C+$``-H,0`#P5$``\%```(R +MQ``#:#$``\%3``/!0@`#29P``C+$``-H,0`#P5$``\%```(RQ``#:#$``\%3 +M``/!0@`#2.@``C+$``-H,0`#P5$``\%```*W$``",L0``V@Q``/!4P`#P4(` +M`C+$``-H,0`#[````TD]``*P"``"0`0``_`%``-*I``#_P```_\```*R`P`# +M:J0``K`$``)!!``"H!```_!&``-(P``#2,4``K$#``*U`P`#:,```VC%``/L +M```#_P```_\```/_```#[````V%(``-A00`#848``V)_``/!#@`#Z!```^@@ +M``/H,``#:.@``^@```/_```#:.@``T%(``/_```#[````K!_``*Q_P`"LO\` +M`VA@``-H:P``">4``^@```.@`P`#W````]@0``*\`P`"L/<``J#^``/P00`" +ML'\``\$0``/!(``#P3```K3_``/!5``#P60``\%T``/^```#U!X``VAK``.@ +M`0`#H1$``Z(A``.C,0`#^P```_X```/47@`#:&L``_L```,,S@`"$NT``K#_ +M``*\"``#P1```\$@``/!,``#:H```J3^``'3!P`"H/P``_`"``-JA``#[``` +M`K#W``.A`0`#HA$``Z,A``-JA``#[````TD]``/_```"N(```F1(``-I/0`" +ML`$``K$"``*R/P`"0B\``K,```-J:``"L````K$```*R```"LP(``VIT``*Q +M`0`"L@@``K,```-J>``"L`$``K(```-J?```$>\``K#```)`#P`#H`(``F`. +M``*Q```#HB(``K,!``-J9``"L/\``K&_``/!(``#:&```_\```/_```",%L` +M`KA_``)$2``#:3T``^P```/H```#Z!```K(#``*S```#:#```^P```-`+``# +M_P```_\```/H(``#Z#```V`L``/H```#Z!```V`8``-@'``#[````^@```"" +M/P`"(OH``/(_``(B^@`",X\``BXT``-)F``"M/<``K4/``)!%``"8`4``VF8 +M``/!+@`#Z#```V@P```"%P`#@>```^A```*@`0`#\`$``\%.``(THP`#2`@` +M`KC^``)!&``#:`@``^@```""/P`")%H``/(_``(D6@```A<``X'@``/_```" +MI!```_`"``/!3@`"-*,``C/S``-````"O"```_\```)"+``#\`(``KT```(T +MR``#0````KP@``/_```"0SP``_`"``*]`0`"-,@``T`L``*X0``"N8```KO_ +M``-*I0`"2!@``_`!``*[SP`"21D``_`"``*Z/P`"2[H``D5;``-JI0`#]``` +M`<)L``-)T0`"N$```D1X``.$0``#2)P``TBB``.%X@`"8`0``F`%``)HA``" +M:(4``VB<``-HH@`#2+0``TBZ``.%X@`"8`0``F`%``)HA``":(4``VBT``-H +MN@`#23@``X7A``/`50`"0B4``VDX``-J7``#H.$``X'A``/H,``#@N@``X7E +M``(O\``#0Z8``X#H``/_```"2(4``FB```/!F``#P:@``\&X``-CI@`#8^8` +M`^@```/HT``",`$``\'>``(P`0`","<``X3B``/!R0`#Z````X'A``.#Y``" +MPC$``P(N``+#/@`"1$D``_`!``.#Y0`#Z%```B_P``.`Z@`"+_```XCE``.$ +MX``"1$P``_`"``.(Y``"R(X``\&8``/!J``#P;@``V,J``-C:@`","<``X'B +M``.@X0`#HY8``X+D``+"+@`#Z%```B_P``.@XP`"+_```C`G``.`Y0`"0*`` +M`\$0``/!(``#P3```V2H``-DZ``#@.```H((``)"`@`#@B0``)'C``/L```" +M,"<``TEP``)$C@`#\$,``K7S``)")0`#:7```^AP``/!;@`#P5,``\%"``-H +M,0`"1)X``_`&``-)G``#I.$``F(D``/!4P`#P4(``V@Q``)$C@`#\$T``TF< +M``.$Y0`#I><``D`$``)!%0`#I(@``X1```.%1@`"8`4``F$4``/H,``#P2X` +M`V@P``-#I```(>,``K4/``/_```"0`4``F`$``/!$``#P2```\$P``-CI``# +M8^0``X&$``.@&``#@@8``F`"``/HT``",!4``\'>``(P%0`#2)```Z2Z``.E +MYP`"014``F$4``-HD``#:*@``VB4``-HK``#H*8``\$0``/!(``#P3```V0D +M``-D9``#BK8``T@A``*X`P`"9F@``KD/``*[_@`"1FD``F9J``)'>P`#:"$` +M`VJ)``-H)0`#:HT``T@(``-((0`"81X``V@(``-(R``"N$```KD_``)@"``# +M:,@``D`)``-HR``"95X``V@A``-JB0`#:"4``VJ-``)%6P`#:"$``VJ)``-H +M)0`#:HT``^P```-`+``"N$```KF```/HL``#2J4``D@8``/P`0`"NS```DD9 +M``/P`@`"NL```FNZ``)E6P`#:J4``TB<``-(H0`"O'L``D`,``)$3``#:)P` +M`VBA``-(M``#2+D``D`,``)$3``#:+0``VBY``-(D``#A.(``Z7G``)!%0`" +M810``VB0``-HJ``#:)0``VBL``-).``#A>$``F(E``-I.``#:EP``Z#A``.! +MX0`#@^@``X+H``.%Y0`"+_```^@```.!X0`#@^0``L(Q``/H,``#Z%```B_P +M``.`Z@`"+_```T@(``-((0`#J.T``D$8``-H"``#J.L``D9H``/`/@`"15,` +M`V@A``-JB0`#:"4``VJ-``/H0``"-*,``^P```-)=``#P6X``^AP``.(2``# +MP%X``X59``)")0`"8B@``VET``/!0@`#P5,``V@Q``/L```#2`@``KC^``)! +M&``#:`@``TA4``*_8``"8B\``VA4``-)=@`"OQ```F2O``/!6P`#P6X``^AP +M``-H,0`",L0``TA4``*_GP`"0B\``VA4``/!2@`#:#$``C1%``/L```"+D4` +M`C&;``(M+@`"-I\``^C```#B$``#P3P``C3U``(S/@`"+C0``C2P``*_&``" +M-D<``C"*``!B$``"L````]P```*P```#W`$``X_"``*P0``"P`\``]@```*P +M@``"P`\``]@!``-`&``"H-X``_!!``-`'``#0"T``_\```/4'@`#U%\``K`0 +M``+,S@``XA```J7```(4S@`","<``Z.6``(T]0`",9L``C&6``/L```"L00` +M`K"```*@W@`#\$$``K#```*R"0`#Z%```B_P``/L````\=X``/'=``/!_0`# +MP``+*K@`"L"```J"@``/P00`#Z*`` +M`J"K``(5A@`#2!D``K+@``)&8@`"9FH``V@9``-)Y0`#_P```D9B``)F:@`# +M:>4``_0$``(5/P``T=\``J#>``(590``T>```LW>``/T!``"%18``$'@``/_ +M```#_P```J"H``(5C``"H:@``_!(``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@` +M`VGE``-()0`#`Z@``X,P``)G``#8!$``\'?``-)F``#A>(``\!5``)!%0`#:9@``^@P``/! +M+@`#:#```T@(``/_```#A,@``F`$``-H"``#^`,``^P```/_```#_P```&H_ +M``/H````@AD``('<``*P`0`"L1$``K(0``-J1``"L1```^@@``-J1``#0"0` +M`J#>``/P`P`"NU,``_0```/P00`"NUL``-G\``)`#@`#\$L``T`0``*\!``# +MW,```X_J``*@W@`#\`$``^CP``/8\``"O`D``\&Q``(NT0`#0"0``_\```*\ +M`@`"0`P``_!+``-`$``"O`0``]S```*_P``"H-X``_`!``*_@``#V/```XSD +M``/!L0`"+M$``T@(``*T0```@?4``F`$``-H"``#2`$``K"_``)$0``#:`$` +M`^@```*Q0``#Z"```^@P``-J1``",9L``BTN``(VGP`"OQ@``C9'``(V=``" +MOP```C&A``-*<``#_P```_\```*RD``#:G```K\3``(V1P`"-G0``T`D``/_ +M```#_P```D`.``/P2P`#0!```KP$``/``/P`0`#Z/```]CP +M``*\"0`#BQ```B[A``-`)``#_P```KP"``)`#``#\$L``T`0``*\!``#W,`` +M`K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(NX0`#2G```_\```/_```" +MLH```VIP``*_&``"-D<``C9T``*_```",:$``TIP``/_```#_P```K*0``-J +M<``"OQ,``C9'``(V=``#0"0``_\```/_```"0`X``_!+``-`$``"O`0``]S` +M``./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+M$``T`D``/_```"O`(` +M`D`,``/P2P`#0!(``KP$``/``/P`0`"OX```]CP``.,Y``# +MP;D``B[1``(QFP`",98``"'U``/_```#2`@``_\```/!!``#:`@``^P```/H +M```#P````K&_``/!(``#:&```K`!``/H$``#Z"```^@P``-J8``#2F0``K2` +M``)`!``#:F0```H[```2#```&@L``K`"``*@W@`#\$$``K`$``.!%@`"8`$` +M`X(J``*QA``"8B$``J0^``/P`0`"LP0``\$?``-J8``#2F0``K2````1_``" +M0`0``K0#``)@!``"LQ```VID``(P6P`"OP@``D_P``/P`0``\AD``^P````" +M&0`#_P```_\```*E#@`#\`$``^P```/H````@AD``T`2``/_```#_P```D2. +M``*@3@`#\`$``/'T``*_0``"H-X``_`#``)JKP`#]````_!!``)KOP`#8!(` +M`C"*``!YW``#_P```T`H``*@_@`#\$$``^P```*@W@`#\`4``L`.``/P00`" +MP1X``_0```/P0P`"PBX``_!!``+#/@`#8"@``/'<``/L```"L`$``K$"``*R +M!@`#Z#```VIH```200`"L!,``K$"``.")@`#Z#```VIP``-`!0`"L"$``K$" +M``*R!``"M`,``D54``,")0`"LP$``VIT``*P`0`"L0(``K(/``*S`0`#:G@` +M`TI\``/_```"L````K$```*S!``#:GP``^P````"%```"D```&H_``/_```" +M0`$``J`.``/P`0`#[````TB<``-(H0`#2DH``J#>``/P0P`#2+0``TBY``-* +M3@`"O!```F(N``)F;@`":(P``FF<``*@W@`#\`4``VB<``-HH0`#:DH``_0` +M``/P0P`#:+0``VBY``-J3@`#Z,```.';``*P$``"L0```K(0``*S```#8G0` +M`K"```/8`0`"L````]P!``*P$@`"L0(``K(2``*S`@`#8G0``K`0``*Q$@`" +MLA```K,2``-B<``#8D0``K$"``*S`@`#8DP``V)(``(S/@``8=L``\&,``/! +MG``#P:P``\&\``(W@``"-9X``&';``/_```"L````]P```*P0``#C\(``L`/ +M``/8```#0!@``J#>``/P00`#0!P``T`M``/_```#U!X``]1?``*_```#W/`` +M`K_```.(P@`"S_@``]CP``/$```#Q!$``\0B``/$,P`"M0\``D1E``.E9@`" +MH-X``_!#``*U#P`"1'4``Z5V``.F0@`#A$H``Z=2``.%6@`#Q$0``\1F``+` +M`0`"P`0``L(C``+")@`#Q!4``\0W``/4'@`#0G4``T)R``*_$``"H00``_!& +M``*E"0`#\`0``\&,``/!D``#P:P``\&P``*C"0`#\$(``\&L``/!L``#8G(` +M`T)&``*A)@`#\$8``J4I``/P!``#P8P``\&2``/!K``#P;(``J,I``/P0@`# +MP:P``\&R``-B1@`#0DX``J$5``/P1@`"I1D``_`$``/!C``#P9$``\&L``/! +ML0`"HQD``_!"``/!K``#P;$``V).``-"2@`"H3<``_!&``*E.0`#\`0``\&, +M``/!DP`#P:P``\&S``*C.0`#\$(``\&L``/!LP`#8DH``V)T``/[`0`"L1`` +M`LS.``#AVP`"H,$``=;X``-"<``#0D4``_\```+(`@`#J(```LI&``.JH``# +M0DP``T))``/_```"R0(``ZF0``++1@`#J[```C>```/L```#2)P``TBA``*@ +MW@`#\$(``TBT``-(N0`#P1@``\%:``.)E@`#B[8``F$9``)E6P`"H-X``_`$ +<``-HG``#:*$``_0```/P0@`#:+0``VBY``/L```` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_me.bin.uu new file mode 100644 index 00000000000..82b8244e2a8 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_me.bin.uu @@ -0,0 +1,197 @@ +begin 644 CAYMAN_me.bin +M?$"``8P``/Q!0`"95```+90:*DQ!L`*M@` +M`%;-@`!4P#X`!,P!H?3,/2`$Q#T``\P``$?80`!6V$``7H````#$#``*!#P` +M(Y3```+/P:*DQ!L`*]@``%;-@`!5P#X`!,P!H?/,/2`$Q#T``\P``$G80`!6 +MV$``7H`````$/``CS\&BI,P``$O8``!5S$``8X````#,``!&S```2\Q!(F3, +M02)ES$$B9LQ!HMU\0(`!S(``38@```#,0`!&S```2XP`!4;,02)DS$$B9@8U``P&-@`-`4H`3U\0@`! +M?$)``94```>&@```@``!5X``!4*```%[@``%0H```4T15``0?A8`"LR``$W4 +M80``E8#^N<`Z``3,.2%`Q#D``WQ`@`&(````$50`$%(D`"!^)@`:S4``6-1B +M``"5@/ZNQ"``')H`__]\0(`!B````-PZ``"90``;)YP``97```T+N``!S@$A +M:``%\0@`!",P``08D +M``$&*``"SAVA_4``(````#.02%ISH$A:LW!(6O,`2%L@````'Q`P`%\ +M00`!?$%``7Q!@`%\0<`!&*0?Z#)H`#P$(``!EH``"'Q"``$Z,``#0B```IL` +M``($(`!`!"0``8```=U^`D`!"F0``9I`__\D[``0S```39K```G`*@`$Q"P` +M%WZ2@`K,``!!S"D``,[``!?$,0`#@``!['@```@``!^8```?Z```(#@``""(```@V```(2@``"%W\;@`\4 +MI``(EX``'29D`/^```(H?QN`#A2D``B7@``8)F0`_X```BA_&X`,%*0`")N` +M`!,F9`#_@``"*'\;@`T4I``(FX``#B9D`/^```(H?QN`#Q2D``B;@``))F0` +M_X```BA_&X`.%*0`")N```0F9`#_@``"*!2D``@F9`#_,F@`/!3L``B:@/WE +M?$-``7Q#@`%\0\`!S```39;```;/02%ISX$A:L_!(6O,`2%L@````,_U``"` +M````,F@`/)J`_[340`!_@````'Q`P`%\00`!P!X``144`!+`(@`"P"8`!)5` +M``3`)__[?24`"<`F``!]TH`)?A+`"7TE``I\04`!?$&``@%*`)EE0``"(:```"```)N@``"?(```H*```*(@``" +MC8```I/,P:*D@````,`2"`!\04`!?$(``7T,P`K`$@`$%5@``Q5<``U]T<`) +M$B``$WX>0`I^3H`*SH&BI,V!H?Z`````!!`A&,04`!"50/__U%$``,S!HJ2` +M````!!`A!L04`!&50/__U%$``,S!HJ2`````V$``%LS!HJ3$$``6F0#__X`` +M```$$"$`Q!0`$I5`___440``S,&BI(`````DV``!?$$``7Q!0`%\0@`!E8`` +M!A&8`!#$'``*Q#P`)Y?`__^```*A$9@`$,0<``G$/``HE\#__Q5H`!U]64`* +M$>0`"IJ```-^)@`*S<``7,T!(5C-02%9S@$A6LS!HJ2`````?$#``130`!T4 +MU````"Q`P`()M```*,``-"Q!0`(@00`!";@``"C``# +M7,S!HF#-`:!@!!@)@(P``PO,``!:Q#P`),00`"",``,;Q!P`)27<``'(.``F +ME<``!<0\`"1'N`54S```6,_Z``#$)``>FD#__\0H`!D^J``$Q"P`&WZN@`J: +M@/_\!#```H```M@%F,``$-P`"!3@`!C-V0``Q!P`&,W9``'$)``8?F)`"LY9 +M``+$'``8Q"``&,0D`!C-V0`#SAD`!,Y9``>0````&_@`\,`V"`#`,`"`EX`` +M`I````#8``!=Q#@`+">X``&7@/_^P"H`!,08`"_/02%\SP$A?,``5&W8,```5,``5&W8,```5<\`#470`` +M@``%3GQ`P`%04``@?-#`&GQ!0`%\08`!T,`!#96`_!N,``5&W8,```5<\_S4 +M70``@``%3M1#(`!\0(`!S(``38@```#40Z``?$"``'Q!@`%\0<`!E,``(8:```"```2!@``%0H`` +M!(R```5"@``$?E'<`"!]G@`:@``$J`````?$#``7Q!``$5 +M&``?410`(!D<`#&9@``(S0``6'U-0!K45@``E<#ZU<0@`!R:`/__@````-PZ +M``#`)@`$S,$A:7TE``K-`2%J"[@``LQ!(6O,02%LFX#__P`K`'X`+0"%`"X`C``O`)4`,`"7`#(!%``T`*P`-0!^ +M`#B7@``$V$`#]\0X`_>;@/__Q!P`$YG`__\B4P``"!50`!B@0``%]%0`$ +M?9&`"8```'690/_XQ!P`!9`/ZYQ!P`!LP``%3-P`!`S```0(````+$%``/Q!P`!)E` +M_K',``!2S<``0,P``$#$)``^FD#^K'Q`P`%04``@?0U`&M%``!?,``!B@``` +M`,`W__\@B`!P@``!87Q#0`'('``7Q!@`%L]#HIY\04`!?5C`!'S?$#``7Q!``%\ +M04`!S,.A^LT#H?G-0Z*=S,``0,T``$#-0`!`S$``0'Q`@`&(````?$#``230 +M``',PZ*?V$``%I4```+8@``6S(``0,S``$"`````?$#````2\P``$Z```.^S```39K```+,``!. +MEX#]MPNX``'$/P`#FX#__8````#,``!.ED```\P``$*```.^V@``0L0+``/$ +M#P`#Q!,``\07``/$&P`#Q!\``\0G``/$*P`#%?P`'Q:P`!]_\\`)%/``'W_S +MP`D5<``??_/`"7V(@`)]S,`"E\``#'Y1``)^E4`"?)"`#'S4P`Q\CT`)FL`` +M`BRT``',``!-FT`!4F0``!/5@` +M`IF`__[,``!=*1R``,S!(87-P2&&%10`'\Q!(8?,02&(S$$AB95`_3+$%``> +MF4#__X````#,@`!`S,``0,T``$#40`!`@````,0H`"S8:`/WS(``0,Q``$#& +MCP/WF,#__WQ`@`&(````Q"@`+,0L`!'$,``O?O+`"IJ```?$,``/FP``!<0T +M``3,``!2ST``0,P``$":P``%Q#0`!LP``%3/0`!`S```0'Q`P`'8:`/WS(`` +M0,S``$#40`!`%-``'YD``,F```+;S(``0,Q``$#,0`!`S$``0'Q`P`',P``5 +MS,``0-1``$#8``/V@````'Q`P`$4W``=&-@`/,R``$"9P``%S,``0)F`_/G, +M``!A@``#OLV``%[,``!AS,``0(```[Y\0,`!4%``((P``QU\T,`:Q"``%,36 +M``!\0X`!F4``!M^#``#/H`!/C``#(=1``'^`````C``#(8````#8```=Q!0` +M'9E`__^0````V$``'<04`!V50/__D````(P``QW$(``4?$#``<`V_P#$$``5 +MP#`__WSU0`E]48`)?8&`'7SS@`F9@``&WX,``,^@`$^,``,AU$``?X````", +M``,A@````'Q`P`$4T``>F0``!``!\0@`!?$)``7Q!@`%]Y<`)?>*`#T&L +M``*:@/R2!NP``PKL``&:P/__)-P`$)G```/%'0``@``#:\4>``"```-KS(`` +M0,S``$#40`!`@````,0<``3-P`!`S```0,R``$#40`!`?$"``8@```#$'``% +MS<``0,P``$#,@`!`U$``0'Q`@`&(````?$#``230``8Q$``&Q!0`#YD```C, +M``!2Q"0`/I9``#&90``$Q!P`!,W``$#,``!`S(``0,S``$#40`!`@````'Q` +MP`%\00`!%1@`'\T``%I1%``@F8```]1-``"`````?4U`&AD<`#'45@``Q"`` +M'Y7`_%K$(``?F@#__X````!\0,`!%-``'R34`/^5```#S%0#`(````#,@`!` +MS,``0,Q``$"`````Q"``+'Q`P`'$TP,`S(``0,S``$#,``!:S2$A08````#4 +M0`!_@````,0D`#Z60``#?$"``8@```"```/"```````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````P-\``0#@P`%`9@`!@#"``<`S0`(`-L`"0#)``H`P``+`,L`#`#[``T! +M"0`.`2$`#P$M`!`#O``1``8`$@`3`!,`'``4`!X`%@`B`"0`*P`E`$T`)@%7 +M`!`&P`W@!M`-X`;@#>`&\`W@!P`.(`P.:`'T#J@!^`[0````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````"`````@````(````"`````@````(````"`````@````(````"```` +M`@````(````"`````@````(````"`````@````(````"`````@````(````" +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +3```"`````@````(````"`````@`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_rlc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_rlc.bin.uu new file mode 100644 index 00000000000..33c15106e59 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CAYMAN_rlc.bin.uu @@ -0,0 +1,95 @@ +begin 644 CAYMAN_rlc.bin +M(#@`$".X``#/@``2S```A008``'-@``.S8``@\P``(+-@`"!S```"X0``;T` +M````@```F0`````@#```P!``#!R4``$)$``!?-3``)D`__T4B``!B``````` +M```@'```F<``#L@@`*3()`"E?B7`!\@@`)O()`"F'FC__WXJ@!!]Z<`'R"`` +MG!9H`!!^*D`0?>7`!YG``",@'`!`?$``!S`````'_?P`'/P`"BP`P@"\`2P`"(````S0T``,^Q``#-@``.RSD` +M`!>X``0?N``/EX#__0````"(`````````,`(`Y'`#``#S,D``(0``&4````` +MR`@`IP2(``',@`"G,(P`!)C```0`````A``#)-```*?`"`.1B````,P)``#` +M"`,@A```QP````#("`";?4B`$,R``*3-0`";A``!&P````#("`"4P`(P`````,@1 +M/3C(%3TYR!T].L@A/3O()3TU!*@`,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$] +MAQ"(``,$C``8R)8`/)5``A_(T@`H?24``0E4``$$S``HF0#_^P````#(D@`X +M!1``0'T*P`#(U@`$P!P`!,CB`!3(Y@`DS@H!3,YN`4P(S``$"(@`!`KL``0) +MW``!F<#_^`````#-"@%@S`H!9,U!/4>```++`````"`4```@'```P`P@"\`2 +MP`#-#0``P!`CF,R1``#`$".:S)$``,`0(YS,D0``(!@``,`20`#-#0``P!`C +MF80``EP`````?6E``,`0(YN$``)<`````'UI0`#`$".=A``"7`````!]:4`` +MF8`!5R`8``&```#4P!)``<@H`"N6@`(H`````,V```Z$``,8`````,@@`*G( +M)`"J@``!LR`8``&$``(B`````,`((E3(B0``%(@`$,`,(E7(S0``%,P`$'R- +M0`=]44`'B````"54__^$``%]`````(```;,`````A``"NP````#`,"`(A``! +M4"`X___`,"`(S#$``,LY``#`,`.8A``!4"`X`0#`,`.8S#$``,L)``#`,"&V +MB````,PQ``!^HL`/EL```P````!\*@`'?>*``7ZFP`^6P``#`````'PJ0`>( +M`````````,`,)-3`$"36P`@@"\`:P`#-B0``(!P``#P3,``',C`"'P`I`0""(*!X$S``!S(P`A\`*0$`@ +MB#(H!,P```3,``',C`"'P`K__R"(@'T$ +MS``!S(P`A\`*`(`@B``@S(``ILP``)B(````S```EYG``!+(,`!`(S```L\` +M`$"$``#_(#@``\@P`$`?,`/]SP``0(```N3,``!6R"@``I:`_H(@"``!S8`` +M#LR```*```#[`````,@P`$`C,`!`SP``0(0``IH@.``!R#``0!\P`[_/``!` +M@``"Y,P``%;`,"`#S[$``(@```#+.0``P`@CB,B)``#`#".)R,T``'R,@`;` +M#"-FR,T``'R,@`;`#".*R,T``,`0(V?)$0``?-#`!L`1``!\T,`'?(R`!A2, +M`!`*/__%B``$'ZB +M@`"(`````````,@(`(90B``((`P`AR`4`!#(D@``S0P```E4``&90/_]!,P` +M`8@`````````S```*?-%`$9E```,`````?0#`!X0``2[,P`"CB`````````#`#"`+P!+` +M`,T-``#`#".:S(T``,`,(YS,C0``P`PCF(@```#,C0``S```@X0``5@1N``? +M@``!LP````#(U```!,P``08@``$@&`#_?96`!GV1@!)]G8`#?)F`$96`_Q8@ +M&/\`?96`!A68``A]D8`2?9V``WR9@`^5@/\/`````!54`!"60``#`````!54 +M``@@&`#_?95`!H@`````````P#`#D,LY``#`"__^?XN`!A#,`!!_CX`'S[$` +M`(@```#+.0`````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +!```` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CEDAR_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CEDAR_me.bin.uu new file mode 100644 index 00000000000..4c73530a517 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CEDAR_me.bin.uu @@ -0,0 +1,126 @@ +begin 644 CEDAR_me.bin +M?$"``*````#,@`!-@````-1``'\`````S\&BU,`N``1_+P`' +MS#$``,@L``3`,``&?O-`(\`P`"!_:X`@B````'^SP"3,``!"@````,Q``!]\ +M0,``?$$``!D4`#V90``3!!0`+H0`!,4$&``IA``"6L@<`!,$%``JA``$Q008 +M`"W-0:*DR!P`$Y7```#('``3S,$A`,T!(0',P2$"S0$A`X``!,+-@:*D'1@0 +M`)6```7('``3*>0`0)9`___('``3S,$A=4``,Y!(6G.@2%JS<$A:X````#,`2%L?$#``'Q!``!\04``?$&``'Q!P``8 +MI!_H*F@`/):```I\`@``?$(``#HP``/,``!8FP```T(@``4$(`!`@``!4WP" +M0`!^`D``FD````ID``$<[``0FL``"LP``$W`*@`$R"P`('Z2@`?,``!!S"D` +M`,[``!Z```%CR#``!,T!(6W-02%NR#```W\?``8<]``'$W@``9=``"H'N`%H +MGX````````"```%X?QN`#H```7Q_&X`/@``!@'\;@`R```&$?QN`#8```8A_ +M&X`1@``!C'\;@!"```&1%*0`")N``!D4I``(@``!H1YD`/^;@``5%*0`"(`` +M`:$>9`#_FX``$12D``B```&A'F0`_YN```T4I``(@``!H1YD`/^;@``)%*0` +M"(```:$>9`#_FX``!12D``B```&A'F0`_Q2D``@>9`#_*F@`/)J`_FT4[``( +M?$-``'Q#@`!\0\``EL``!\P``$W/02%ISX$A:L_!(6N`````S`$A;(````#/ +M]0``S```680`!,4J:``\FH``!,@H`!>`````U$``?Y:`_ZM^`D``A``"C,`. +M``+,``!!@``!K\S!,$J4````R#P`''Q`P`!\00``P!X``14D`!+`(@`"ED`` +M!<`F``3`)__[?24`!L`F``!]TH`&?A+`!GTE``=\04``?$&``,S!(6F:@``, +MS0$A:LU!(6N6P/X\S8$A;(0`!,7,``!_R#``&I<```#(,``:@````7Q`@`"$ +M``3%S```?\@4`!7(&``6S4$A:Y;`_B[-@2%L@``!QLP``'_,``/ER"P`(,`. +M("0$$#``(,PB:P04,`',``!!T!$``,S5``#.P``>R`P`"9C```#(#``)?$$` +M`'Q!0`#,0`!#S$``1,`.@`!\0D``?$*``!:L`!^6P/X5P#7P`,Y``^$>>``# +M$GP`"'_WP`9_^\`'%G@`&,_``^+/@`/C$K```G\_``#/``/D@``$47R`P`!\ +M0,``&-`!Z!$H``&5```0!J@!_YZ`````````@``"%\`2"`"```(ER!0`$8`` +M`BS(%``2@``",\S!HJ2```(\'.@`/X```F1\P8`+'-``/RDH``8I+``6?JZ` +M!\@<`!.:@``]!!0`+H````#,P:*DP!((`'Q!0`!]#,`'P!(`"!58``,57``, +M?$(``'W1P`82(``4?AY`!WY.@`?.@:*D@````,V!H?[(%``1!!`A&)5```#( +M%``1U%$``(````#,P:*DR!0`$@00(0:50```R!0`$M11``"`````S,&BI,S! +MHJ0$$``!S0``&80`!,7,``!_R!``&YD```#($``;@````7Q`@``JH``$*J0` +M%'XF``<$%``NE@``"`08`"F$``):R!P`$P04`"J$``3%!`P`+:@``$$>0`"GXF``?-P`!FS0$A6,U!(5G.`2%:S,&BI)J``D(% +M$``$!"P``1+P`!U]<4`'$N``$"(@``S-`2%8S4$A6``"FT```\@,`"F$``-- +MR!0`*YN```,$$``0A``#9,S!HE#-`:!0A``"_@08!`"$``3%S```8\@\`"V$ +M``,,R!``*<@<`"\=W``!R"0`)Y7```G(-``QR#@`,,@\`"U3=``@?[>`)T>X +M!5#,``!BS_H``)I```#()``GR"@`(SJH``*:@/__R"@`(\`P``'(*``DFH`` +M`,@H`"3/``!;4-@`"!3<`!@AW(``S8$A@,W!(8%1(``(%20`&,X!(8+.02&# +MS4$AA'Q`@`"@````S(``380`!,4<=``!''@``IM```/(#``JA``#3<@4`"R; +M@``#!!``$(0``V3,P:)@S0&@8(0``OX$&`F`A``$Q7`!YG`__[( +M'``E@````7Q`@`!\0,``?$$``!DH`#"6@``(R"@`)\@D`"B:0```R"0`)YI` +M``#()``HS``#X'Q!0`!\08``%1P`'\S``,?-``#(E<```\`<@`#-P2`0X8,` +M``5<(`#,``!-@````-P?00!\0,``?$$``'Q!0`!\08``S,``R``#()`/]?>:`$9:```-^7L`!?`+`!L[#HIY5%``@ +MS```;,T``&W-0`!MS0``0\U``$/('``=T4``0YG```7,``!5R"``']@``\#, +M``!`R"@`%M@`!L`:J``GEH```\R``$#0@`!@%5``&(!```7T5``.```!T?9&`!IE`__C((``?A``#/<@<``>` +M``"SS```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/TS0`#]LT` +M`_?-``/X@```!$``,]S```4\@,`"_,@`!`S$``0,Q``$#,0`!` +M?,3``,S``$#40`!`?$"``*`````$*``!F4#_]<@@`!^$``,]R!P`!X```0G, +M``!N?$#``,@0`$>9```+R!0`1)E```3(&``)S8``0,P``$"```$SS(``0'Q` +MP`#($`!'E0#_]\@4`$690``$R!@`"LV``$#,``!`@``!,]@`"$!\0,``R!`` +M1YD`__P`````S(``0,S``$#40`!`?$"``*`````$*``!R!``1M@`!T#-``!` +MA``!2LT``$#(#`!#E,``"L@4`$B```%#!!```\@0`$;8``?`S0``0(0``4K- +M``!`R!0`2)U```#,``!JR"@`%AZH``&:@``#P"D``8@```#`+`%6SH``7-@` +M",#.P`!`B````,P``$`?$%``%(@`"!]X<`G?5C``WS?$#``'Q!``!\04``S,.A^LT#H?G-0Z*=S,`` +M0,T``$#-0`!`S$``0'Q`@`"@````!"@``7Q`P``5 +M@``%S@``6,R@`$:`````S6``1LR@`$2`````S6``1(```S?,0`!JS(``0(`` +M``#40`!`?$#``'Q!``!\0X``?$/```0<``+/@`!"S\``0LW``$($'``@S,`` +M0LT``$+-P`!"!!P`!P0@``%\`D``R!0``\@8``-1F``@?5E`)\@H``/(+``# +MR#```\@T``-2[``@?JZ`)U-T`"!_-P`G?RM`(7YV0"!6J``_5S``/WZR@`9^ +M*@`&F<#_\@G<``&6@/_A4_0`('][0"=]94`@55@`(,P``%O-=@``S;8``,@@ +M`$&:````R"``08````%\0(``?$#``'Q!``#,P`/^S0`#_\S``$+-``!"%10` +M'QD8`/`G7``!?78`!IF```5]7D`&S```0H```S?,``!-%9@``14L``B9@``Q +M'NP``98```05,``,@``#-\P``$($%``@S4``0A\P``$@*``!!#@`(`0\``?( +M%``#R!@``\@<``/((``#?5U`#7VAP`U]74`'%A``'Q6<`!]]'0`&?1=`!GZ2 +M@`:;0``2"[@`!)O`__(+_``!R`P#_IJ```G($`/_FP``_@````-1``'^```,WS```7H0` +M`SI\0,``%-P`")7``!D``#,@`!`S,``0(````#40`!`R"``']@``T#, +M``!`S(``0-1``$!\0(``H`````0H``'((``?V``#P,P``$#,@`!`U$``0'Q` +M@`"@````!"@``7Q`P````H`TP`+`.(`#`$: +M``T!)``.`3@`#P%"`!`#-0`1``H`$@`8`!,`(``6`"(`)``Q`"4`3``F`6<` +M%P''`!@!U0`B`L$`(P+2`";@``P(!P``2`<``#("`"!E(#_V0`` +M``#(*```EH#_UB`(``'-@``.S(```!P<```JB`&[E(#_RP````"```#3```` +M`!ZH`/_.@``,B`````````#(,`!`(S``0,\``$"$``"F(#@``<@P`$`?,`._ +MSP``0(```&?,``!6A```$`````#`,"`(A```N2`X___`,"`(S#$``,LY``#` +M,`.8A```N2`X`0#`,`.8S#$``,L)``#`,"&VB````,PQ``"9P/_ER#``0",P +M``+/``!`A```BB`X``/(,`!`'S`#_<\``$"```!GS```5H0``!``````(#@` +M`<`P`YB$``"Y$[@`%,P``%?`,`.8S#$``(@```#+"0``S[$``,V```[+.0`` +M%[@`!)>`__X`````B`````````#/L0``RSD``"`(`!^8@```"(@``4P/\[`````,@1/3C(%3TYR!T] +M.L@A/3O()3TU!*@`,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$]AQ"(``,$C``8 +MR)8`/)5`_RK(T@`H?24``0E4``$$S``HF0#_^P````#(D@`X!1``0'T*P`#( +MU@`$P!P`!,CB`!3(Y@`DS@H!3,YN`4P(S``$"(@`!`KL``0)W``!F<#_^``` +M``#-"@%@S`H!9,U!/4>````Y`````,@H``&6@/[[`````"`(``'-@``.S(`` +M`8```!@````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +,```````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_me.bin.uu new file mode 100644 index 00000000000..ac9b3cf31c0 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_me.bin.uu @@ -0,0 +1,126 @@ +begin 644 CYPRESS_me.bin +M?$"``*````#,@`!-@````-1``'\`````S\&BU,`N``1_+P`' +MS#$``,@L``3`,``&?O-`(\`P`"!_:X`@B````'^SP"3,``!"@````,Q``!]\ +M0,``?$$``!D4`#V90``3!!0`+H0`!-H$&``IA``"6L@<`!,$%``JA``$V@08 +M`"W-0:*DR!P`$Y7```#('``3S,$A`,T!(0',P2$"S0$A`X``!-?-@:*D'1@0 +M`)6```7('``3*>0`0)9`___('``3S,$A=4``,Y!(6G.@2%JS<$A:X````#,`2%L?$#``'Q!``!\04``?$&``'Q!P``8 +MI!_H*F@`/):```I\`@``?$(``#HP``/,``!8FP```T(@``4$(`!`@``!4WP" +M0`!^`D``FD````ID``$<[``0FL``"LP``$W`*@`$R"P`('Z2@`?,``!!S"D` +M`,[``!Z```%CR#``!,T!(6W-02%NR#```W\?``8<]``'$W@``9=``"H'N`%H +MGX````````"```%X?QN`#H```7Q_&X`/@``!@'\;@`R```&$?QN`#8```8A_ +M&X`1@``!C'\;@!"```&1%*0`")N``!D4I``(@``!H1YD`/^;@``5%*0`"(`` +M`:$>9`#_FX``$12D``B```&A'F0`_YN```T4I``(@``!H1YD`/^;@``)%*0` +M"(```:$>9`#_FX``!12D``B```&A'F0`_Q2D``@>9`#_*F@`/)J`_FT4[``( +M?$-``'Q#@`!\0\``EL``!\P``$W/02%ISX$A:L_!(6N`````S`$A;(````#/ +M]0``S```680`!-HJ:``\FH``!,@H`!>`````U$``?Y:`_ZM^`D``A``"C,`. +M``+,``!!@``!K\S!,$J4````R#P`''Q`P`!\00``P!X``14D`!+`(@`"ED`` +M!<`F``3`)__[?24`!L`F``!]TH`&?A+`!GTE``=\04``?$&``,S!(6F:@``, +MS0$A:LU!(6N6P/X\S8$A;(0`!-K,``!_R#``&I<```#(,``:@````7Q`@`"$ +M``3:S```?\@4`!7(&``6S4$A:Y;`_B[-@2%L@``!QLP``'_,``/ER"P`(,`. +M("0$$#``(,PB:P04,`',``!!T!$``,S5``#.P``>R`P`"9C```#(#``)?$$` +M`'Q!0`#,0`!#S$``1,`.@`!\0D``?$*``!:L`!^6P/X5P#7P`,Y``^$>>``# +M$GP`"'_WP`9_^\`'%G@`&,_``^+/@`/C$K```G\_``#/``/D@``$8WR`P`!\ +M0,``&-`!Z!$H``&5```0!J@!_YZ`````````@``"%\`2"`"```(ER!0`$8`` +M`BS(%``2@``",\S!HJ2```(\'.@`/X```F1\P8`+'-``/RDH``8I+``6?JZ` +M!\@<`!.:@``]!!0`+H````#,P:*DP!((`'Q!0`!]#,`'P!(`"!58``,57``, +M?$(``'W1P`82(``4?AY`!WY.@`?.@:*D@````,V!H?[(%``1!!`A&)5```#( +M%``1U%$``(````#,P:*DR!0`$@00(0:50```R!0`$M11``"`````S,&BI,S! +MHJ0$$``!S0``&80`!-K,``!_R!``&YD```#($``;@````7Q`@``JH``$*J0` +M%'XF``<$%``NE@``"`08`"F$``):R!P`$P04`"J$``3:!`P`+:@``$$>0`"GXF``?-P`!FS0$A6,U!(5G.`2%:S,&BI)J``E<% +M$``$!"P``1+P`!U]<4`'$N``$"(@``S-`2%8S4$A65P``,R#0`,<@X`##(/``M%_P`$!/\ +M`!!_U\`'4W0`('^W@"='N`50S```8L_Z``":0```R"0`)\`P``'(*``DFH`` +M`,@H`"3/``!;4-@`"!3<`!@AW(``S8$A@,W!(8%1(``(%20`&,X!(8+.02&# +MS4$AA'Q`@`"@````S(``380`!-I\04``'70``1QX``*;0``#R`P`*H0``TT5 +M5``0FX```P00`!"$``-QS,&B8,T!H&"$``+^!!@)@(0`!-K,``!DR#P`+H0` +M`PS($``JR!P`+QW<``'()``HE<``#,@T`#'(.``PR#P`+A?\`!`3_``0?]?` +M!U-T`"!_MX`G1[@%5,P``&+/^@``FD```,@D`"C(*``EFH```,@H`"6```+& +MP#```@68P``0W``(%.``&,W9``#('``BR"0`(AW<#__-V0`!?F)`!\Y9``+8 +M&%$#V!A1!(@```#8&%$'&_@`\,`V"`"7@``#P#``@(@```#`*@`$ST$A?,\! +M(7W-`2%^(J@A?P0D``B:0```"F0``7`!YG`__[('``E@````7Q`@`!\0,``?$$``'Q!0`!\08``%1P` +M'\S``,?-``#(E<```\`<@`#-P2`0X8,```5<(`#,``!-@````-P?00!\0,`` +M?$$``'Q!0`!\08``S,``R;@/_\R"@`)\T``&)]34`G +MU%8``)7`^T#((``FF@```,@@`":````!?$"``.`Z``#`)@`$S,$A:7TE``?- +M`2%J"[@``LQ!(6N;@/_^S$$A;)G`_/?,``!_@````7Q`@`#`#@$`S```0``#()`/]?>:`$9:```-^7L`!?`+`!L[#HIY5%``@ +MS```;,T``&W-0`!MS0``0\U``$/('``=T4``0YG```7,``!5R"``']@``\#, +M``!`R"@`%M@`!L`:J``GEH```\R``$#0@`!@%5``&(!```7T5``.```"(?9&`!IE`__C((``?A``#L\@< +M``>```"_S```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/TS0`# +M]LT``_?-``/X@```!$``.SS```4\@,`"_,@`!`S$``0,Q``$#, +M0`!`?,3``,S``$#40`!`?$"``*`````$*``!F4#_]<@@`!^$``.SR!P`!X`` +M`17,``!N?$#``,@0`$< +MP`-^PL`+?FY`!LY8`_$$&```!!P``(0``<')Y`/QA``!P0# +M\80``<')Y`/Q?2$`!]@`!T#-``!`A``!MLT``$#(#`!#E,``(L@4`$B```&7 +M!!```\@0`$;(&`/U!9@``1V8``_-@`/U'9P``QF8`&+)I`/V$=P``P0L`/]^ +MWL`#?L+`"WYN0`;.6`/V!!@```0<``"$``'!R>0#]H0``<')Y`/VA``!P0#]GTA``?8``?`S0``0(0``;;-``!`R!0`2)U```#,``!JR"@` +M%AZH``&:@``#P"D``8@```#`+`%6SH``7-@`",#.P`!`B````,P``$`>:`#_ +M?IO`$)?```,:;!_H?H&``'[;P!"7P``#&G`?\'[!@`!_&\`0E\```QIT'_A_ +M`8``?UO`$)?```,%W``!?T&``!&@``6(````$B``$!R,``+($``>R"``'Y3` +M``C(%``7,@`!`F4``!,@<``:$``.SS``` +M4LR``$"`````U$``0,Q``"?,0``H@``#K4P``%?$$``-@@`L:```(OSB``1LP``$B```)%`````,@@`!]\08`` +M"B```0`;,``!"@``#K[``!E@``!!4P``R```.MS```0@04`"#-0`!"'S```2`H``&$``*L +MR!0``YM``"L$.``A``#L,P``%W((``??$#` +M`,`V_P#($``AP#`__WSU0`9]48`&?8&`"IF```A\\X`&XX,``,^@`$^$``.P +MS```7H````#40`!_@``#K``!\0@``?$)``'Q!@`!]Y<`&?>*`$9J` +M_)-!K``%FL````KL``$<` +M%P)'`!@"50`B`S<`(P-(`"`"D!ZP`J`A``*P(``"\"&0`R +M`CT`-`.,`#4![P`Y`E<`/`-<`#X#JP`_`BL`00+?`$("^P!#`P4`1`,2`$H# +M*0!5`W\`5@.'`&``A@!A`*,`8@#-`&,`M@!D`+8`90"V`&8`M@!G`+8`:`#: +M`&D`Y0!J`58`:P$'`&P!!P!M`0<`;@$'`&\!!P!P`0P`P.:````!0````4````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +9!0````4````%````!0````4````%````!0`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_rlc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_rlc.bin.uu new file mode 100644 index 00000000000..a5c3e20f0a9 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_rlc.bin.uu @@ -0,0 +1,72 @@ +begin 644 CYPRESS_rlc.bin +M(#@`$".X``#/@``2S```A008``'-@``.S8``@\P``(+-@`"!S```"X```/P` +M````P#`@`\^Q``"(````RSD``,^<`!;-@``.R?``&'\X@`R4@/_^`````(@` +M````````A```?`````"```#%`````,GX`(.;@``$`````(```,4`````S!P` +M@X0``-@1N``?@```Q0````#(*``#EH``M`````#-@``.*HP!Y9C``"0@"``! +MS(```X```!@`````(#@``<^```/($`""S```@<@(`!J4@``R`````,V```X` +M````A```T2`X``+,,0``A```#"`X``'-@`"!A```\R`,``"```#%`````"J( +M`;R8@/_8`````)4`_](`````R"@``I:``.$@"``!S8``#LR```*````8```` +M`,G,`(.4P`"3`````(0``/,@#``!A```#"`X``"7@`"-(`P`#<`P(`G,\0`` +MP#`@"L`T&!@3=``((W08&,L-``!\],`&R`@`&IB``((@'``!E,#_^P````"` +M```P?<'`!L@X`%:;@``S(!P``,@X`%>;@``P(!P``2`<``#("`"!E(#_V0`` +M``#(*```EH#_UB`(``'-@``.S(```!P<```JB`&[E(#_RP````"```#3```` +M`!ZH`/_.@``,B`````````#(,`!`(S``0,\``$"$``"F(#@``<@P`$`?,`._ +MSP``0(```&?,``!6A```$`````#`,"`(A```N2`X___`,"`(S#$``,LY``#` +M,`.8A```N2`X`0#`,`.8S#$``,L)``#`,"&VB````,PQ``"9P/_ER#``0",P +M``+/``!`A```BB`X``/(,`!`'S`#_<\``$"```!GS```5H0``!``````(#@` +M`<`P`YB$``"Y$[@`%,P``%?`,`.8S#$``(@```#+"0``S[$``,V```[+.0`` +M%[@`!)>`__X`````B`````````#/L0``RSD``"`(`!^8@```"(@``4P/\[`````,@1/3C(%3TYR!T] +M.L@A/3O()3TU!*@`,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$]AQ"(``,$C``8 +MR)8`/)5`_RK(T@`H?24``0E4``$$S``HF0#_^P````#(D@`X!1``0'T*P`#( +MU@`$P!P`!,CB`!3(Y@`DS@H!3,YN`4P(S``$"(@`!`KL``0)W``!F<#_^``` +M``#-"@%@S`H!9,U!/4>````Y`````,@H``&6@/[[`````"`(``'-@``.S(`` +M`8```!@````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +,```````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_uvd.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_uvd.bin.uu new file mode 100644 index 00000000000..5de4827fdfc --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/CYPRESS_uvd.bin.uu @@ -0,0 +1,2575 @@ +begin 644 CYPRESS_uvd.bin +M0O6*8M!!U)"E$$SW91/,Z?E1+LSP8-,\=S+YH&JT,]A'V"RYW\6L-6]*JKKE +M/6:`'G93]@````"`P0$`!`````@```'FU#H=(5XCD!7/QQ-TKX:Y+*_^@?@^ +MTZ>'PO:`MNK<<#UG_)0)```!S(88]CE^DV9B^?L(V<61^O':T!PF`BPF0FPF@JPFPNPD`-0`````````````````````````` +M````#```Y!,``!,``1,``A,``Q,`!!,`!1,0(```21,`2!,0(```:!,`@!,` +M@1,`D!,`D1,`H!,`H1,P(```L1,`LA,`LQ,`PA,`PQ,`T1,`TA,`TQ,`Z!,` +MZA,`\!,`\1,`\A,,\B#F$Q`@`$P"#`-V@@[2

G!^=$@``,P`0,IX3GQ(`(#,`,#(F$0,F$1(.8#,+$#(F$2,F$3 +M;`,P(A`K(B#F$Q+1`1+!@!`@`!`1(!4%`!+!@#(A$2(A$#`#$R`"$SCQ*.$P +M`1,@`!,B(1(R(1,@YA,PL1,0(`#XT>C!V+'(H;B1J(&8<8AA>%%H05@Q2"$X +M$2@!$M$!$L&``#`````V`0$@80!`X@-0Y`,A,`-01!`@1!!61``@;P`=\##T +M0!SR,#+``!-`03$#0$.PG&,,$@`BH2#C$R(D`&(D`19"_-`"`(;O_P`@\`,@ +M\!,H!&@4%@+[T`(`ANK_`#8A`##J`RHS,/`3'?`````V(0#VP@E1,0-0(K`Y +M`DD2'?`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````"*L#L9E_P`` +M````````````````````````````````(JP8QEW_```````````````````` +M```````````````0-````````````````````````````````````````!+! +M@"D!(.@#9D("1E#_*`$2T0$2P8`BK!=&2/\`````(JP6QD7_```V(0!`;P`P +MY`,@,R`PY!-`YA,0(``=\``V(0!`;P`PY`,@,R`@,S`PY!-`YA,0(``=\``` +M`````"*L%<8U_P``-B$`(.H#'?`V(0`@\!,`(``=\``V(0`@\`,=\``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``"`P0%@````````````````T0$``!$!``#1`0``T0$``-$!```1`0``=P$` +M`-$!``#1`0``=P$``-$!``#1`0``T0$``!$"``#_`0``T0$``-$!``#1`0`` +MT0$``-$!``#=`0``````````````````7````"\````_`@``!P(``-D!``!5 +M`0``TP````````` <#10<(!0<("4<("4J"@X4&`X4&!L4&!L>&!L>(@`! +M!`@%`@,&"0P-"@<+#@\``0@0"0(#"A$8(!D2"P0%#!,:(2@P*2(;%`T&!PX5 +M'",J,3@Y,BLD'18/%QXE+#,Z.S0M)A\G+C4\/38O-SX_-`D``#0)``#4"0`` +MQ`D``,0)``#5!@``U08``-4&``#5!@``U08``-4&``#$"0``M`D``*0)``#5 +M!@``U08``-4&``#5!@``U08``-4&``#5!@``I`D``)0)``"$"0``U08``-4& +M``#5!@``U08``-4&``#5!@``U08``'0)``!T"0``9`D``-4&``#5!@``U08` +M`-4&``#5!@``U08``-4&``!4"0``1`D```````#$````JP(``(\"``!S`@`` +M5P(``#L"```P`@``%`(``/@!``#<`0``P`$``*0!``"(`0``;`$``%`!```T +M`0``&`$``/P```#@```````````!`@,$!08'"`D*"PP-#@\0$1(3%!46%Q@9 +M&AL<'1T>'R`@(2(B(R,D)"4E)28F)B)!8H +M&28F*2D`````$````"`````/````'P```"\```````````````(!`P,$!P4/ +M"!\"`@,&!`X%'@<^````````````````'T`?01]"'T,?6Q]<'UT?7@!`@`%! +M@0)"@@-#@P1$A`5%A09&A@='APA(B`E)B0I*B@M+BPQ,C`U-C0Y.C@]/CQ!0 +MD!%1D1)2DA-3DQ14E!55E196EA=7EQA8F!E9F1I:FAM;FQQGA]? +MGR!@H"%AH2)BHB-CHR1DI"5EI29FIB=GIRAHJ"EIJ2IJJ@`````````````` +M``````("`@```@```0$!`P,!`P.`5:I`P#-FF(&"@X````-SQ_)\4 +M)_V?T?\'`)#!`6"T"````/+\GX;W`P``]OR?````"/__'P`````!%"``8``` +M`@`X(`!@U!\`8(@3`````&````@``````@+___\_`````@#N_)^`EI@``"[\ +MG_T)_/\``#`#`/[[GP```("'$P``____`0```,#__U\`>_C]_^0-``````!B +M`O8#`(0'`@#____]`!\```!```#_?_#_`(`)`/^___\```B`__#__P```X`` +M``*````&@````8````,````,````,````,``/0``0#R=`6````2````-@``` +M#(````6``!@``/_G__\-``!``/K\GP#^_)\@3@``````X````/````"@.&L` +M`!1K``!L#```@`P``*`G`&`8*@!@W!$``````$#___^_____`-1H``#4#P`` +M`#__`("I`P#DJ@!@W`\``.QH````_P#_^!T``/#_``!`"```(#__``(@```W +MS4+]9KCTC(OQ3P=D:@``L`D``!`(`&",,`!@Z&@``#`*`````"0`+5T``*@, +M``#4#```6!$``!0)``#`"@``@`H``/___W_<$P``E%H``-0(``#P:```2`H` +M`.`Z```X.P``2#D``-@8```P&0``H`H``'`(`&"43`!@4`H``,`(``!4"0`` +ME`D``.P/``#___^```#P#ZP)```7```("`T``&`-``!H$```Q#@``+0/```" +M"```:&H```````3,"0``V`\``#QH``#`#P``-`P``+1;```46P``N`\``/QJ +M````"0!@R&L`8#$,````4@(````X!`#@A@(``,P```!X``!X:0``=B\``-@; +M``#L#0``1@4`>E\``'Q?```Z8```/&```)@*``#D$0``\`\``/QH``!,"@`` +MT`\``(`8```L70``__^__ZQ;`````$``N`@``$D*``"07```'%T``-A:``#< +M6@``;`H``&QJ```L"@``_*(`8!2C`&"4:```__\#^/\!_/\``/P'`/X#`.`/ +M``"(.@``Q&@````__P$#"```L`D`8%2K`&#\VP!@9,\`8"3W`&#$`@%@P,4` +M8)BX`&`LT`!@\,<`8&#@`&#`Z@!@>`,!8"C[`&"(N0!@Q*\`8)CK`&"0X@!@ +M``H`8`"``````!#X``!`^``+`&````#X```P^`B``````.`!```@^!,``0`; +M``"`&P``0!L``!`;``"0&P``4!L``"`;``"@&P``8!L``#`;``"P&P``_)\```$`P/\```#B_)\? +MH0<`B)(!8!"5`6````"$``"`````"`````0`___S_____/__`/__````@P`` +M`!@````,````$````(8`\/____]___\/`/\````*````#@````8````<```` +M%#;!$K$R`^+1"0P"HM$)#`D,"(D!F7J1,P,IFB$T`_(IJOD1R!&)#HNA(,P@ +MPFFJ@FG$I=<:)3,!30IE"Q$]"B6@&"$U`^$S`X$V`S"40F)F:*AP&4;_Z*A@++1"-%"`Y+1"3$S +M`PP.B"%RT0EX!_@QZ2'I,<(CQ/F)@FD*T,P@PFLPLBLPLF/$I1;_@M$)B*@6 +MR`:RT0G2T0CB(B_!0P,,3_#N(.)B+\(L0\)M,)(M,`P*J9OW>0)&S/^R+3"P +ML4&V^QO"H0"WO`*&+``6!T_8!]+-_Q9]3`P>XF))!MS_]BL"ABX`MCL"QCD` +M%@=@^`<+_Q;O60P8@F))AM3_````DM$)F(D6*1&H8<+1"0P+N9P;JJEAC&?8 +M!]+-_A8-[PP>XF(N!LK_^%$;__E1C&>(!X+(_1:X.I+1"9AY%CEPLM$(TM$) +MV'T,"L(B/]`D:C`!:7:N@'"^X6#F@,'_)B2<:K +M_Q:+7K8K`H:9_Q:G5(@'"X@6&%`,&9)B20:E_Z+;_E;JY!8G=+@'"[L6VV\, +M',)B20:?_]++_59MXQ8G<^@'"^X6?G`,'_)B20:9_Z*@^[@W'/F(][++^K": +M@Y>8`PPLR0<,'=)B24:/_XQGZ`?BSOP6SM\,'_)B20:-_Y+1"9B9HM$)C0D; +MF9F:AS8"!HC_HB(O?+NPJA"B8B^&A/\``,`@`,+1"0Q/@B`<,"8(G,ZT'DF(NX`@`PM$) +MJ5R@Z@.I/**@067D_M@WTLWZ5GT7=H`:XM$(@B/G@FX]\BX]\/`4\FX]XBX] +MXL[]%LX0AO?_````HBPW&[JR;#>G.0O2(^?"T0B11`-7;>CQ10,,'N)O3>)B +M248+_P```(*B`H"+P%:HOA8G99@'"YD6F6(,&J)B208&_\%#`_%(`^(L1.)M +M,,(L1>(M,`P;^N[";H"R8DE&_OX`#!^10P,,"++3!*(I1*D+DBE%F1*"8_^) +M!_)B20;T_@#!0P/"+$3";3"8<18I2;(M,)"[P+"R0<`@`-+1"/+1"?A_#`SB +M(CWP^Z#I#\)M-48#`````)(K-1NIHFLUES@+PB/GLM$(@40#5VSH\44##![2 +MT0G8?>)O3>)B28AQ#`_BT0F`WX/9?D;;_@"10P.B*42B9QZ2*4629QV"(CV" +M9Q\&Q?ZR(ZR2(B"PP`2PT`1631_`(``,*(")(()B(.(B('S?\.X0XF(@=H`7 +MDM$(TB/GTFD^HBD^H*`4HFD^DBD^)CD$1OC_``#`(`",'+)CK.+1"/(CJO)N +M/_$T`^(N/X+1"7D(\.X@XF.JP"``HJ=0L4D#PB<2I6\`?0H62B`,`Y@'9QD) +M&S,,&B7#`%>3\*%*`S>Z.G+1"7@'#!L,/,D'LF(N!JK^`)CWD(($5OBRH4,# +M#$S`R2#)][(J1+)G%*(J1:)G$\:3_@P=TF))QJ'^#`^2T0F"T0F(6)A)F1>) +M)_DWZ$R(ARYIZ(C\JFWDB/SF<>"(_&)U_(C]?)G +M#N(C]N)G#](C]-)G$,(CZ\)G$;(C[+)G$J(CI*)G$Y(CHY)G%((B5()G%?(B +M5?)G%N(B5N)G%](B5])G&,(CZL)G&;(CHK)G&J(C]Z)G&\`@`'+1"7@'#!@, +M.9D'@F(NAFS^F/>0@P16B*6A0P,,C,#)(,GWLBI$LF<6HBI%HF<5AE;^F/>0 +MT0167:_A0P,,*(")((GW\BY$\FP4L# +MN7&PLT'`NQ"R8A;")Q[13`,,`\#`)-#,H-+1"`<,&PP\R0>R8BZ&+O[A0P,]\.(N1.)M,,`@ +M`,+1",(L,**G4+%)`\+<`>5+`'%/`PP#\M$)HF\+@M$)B+B("'>8"1LS#!KE +MG@!7D^NBIU"Q20/"T0C"+#`0$2#E2``,`]+1":G-XM$)Z,[B+@!W'@LRPP&B +MH`'EFP!7D^CQ2@,WOW*"T0F("(QXHM$)J`H,.9D*#!NR8DF&#?Z8]Y#&!%9L +ME]%#`TP/\/D@^??B+43B9QK2+4729QE&]?T`#!B"8DD&`_ZBIUCA0P.Q3`/" +MT0CB+D3B;##2+##9<<(L,*5``/+1":E_P"``QC3^,3,#P"``1G7^@M$)B,@Q +M,P.(&'+1"7@'%F@+@M$)B,B(&`N(%@@?DM$)F,F8&9+)_HP9ANO]#`N+D:*@ +M"G:J%<+1"PP+!M3^#`F+L0RLXM$(TB.JTFXT=JP*^'N"H-R,OQN9BKL, +M&9)B24:[_0"BT0FHRJ@JJ7LFF>H,#0P^PM$)R,SI:])K%:AX7H5(#DM$(DBDTH)D@ +MDF.J!O/_#!V11@/XSH+1"((H-`P,#$Z0B!""8ZJ8KY)K$HA_B?OXC_)K$,FK +MZ6:;#Y+1"0P(#!JB8DF)"49;_0`,.,*@W,#+@HNARJJ) +M:@P,PFH5>$&2T0F!4`-P>X+2T0B*=W)J%/A!PFHG\FH1XB.JXFTRX4X#TBTR +MJ=D,:^#=$-)CJLF*N9JBRAA]"J7;%]+1".(CJN)M,^%2`](M,[+1";C;X-T@ +MTF.JQ@,`PLOV%KSTPJ#`>B:<;)`AWP`*@!B`_14P.@B"")`>@!Z0_2:<8=\``` +M`#9!`**@@&5@_I%#`\`@``P:J0*"*4.":4/`(`"BH(!E7?X=\#9!`**A`"5> +M_L`@`)$S`PP:@3H#J1*":<;`(`"BH0`E6_X=\#9!`&T"*`.,U%*OP"+"/U`B +M$&I260,=\&J"B0,=\```-D$`#`>!/@.10P-A2P-`4T&:DF`E$")I0':`"J(I +M0*<2"1MWAQ<$AOO_``"Q30-W.P=`("0P(J`=\`P"'?```#9A``P.\3,#T50# +MK0+"+^HA0P.2*A30S!#)`<%5`X@!@F_JXF)'TB_FV1&($>%6`\"(((D1V!'! +M5P/@W1#9$8@1P(@@B1'H$>)OYKT##"W0F2#!-0/`(`"!6`/H$8#N$.D1V!'2 +M;^;H`0P8T38#@.X@XF_JTF_:DFQ*@BH3D5D#@(!TD(@@@F^FDB_ETBHAXJ\/ +MX)D0T-PUP-T1T)D@DF_E@BH@D5L#X5H#@(!TD(@@@F^FDB_ETBHAX)D0T-PU +M@-T1T)D@DF_E@BH@D4D#@(!TD(@@@F^FXBH@@5P#X.!T@.X@XF^FTBH@X5T# +MT-!TX-T@TF^FDBH5T5X#D)!TT)D@DF^F@B,?DBH6%F@+XB,@FN[B;$_2(R&" +M*A;:B()L6N(C(M(J%NK=TFQ;@B,CXBH6BN[B;%R"*Q:";$S`(`!17P-A8`.1 +M80/18@,RI!*"*C1Q8P-R;$Y"*QYR*Q_B*QTP1!&`=Q'@[A%P[B!`[B`P[B#B +M;_!R*R0R*R1"*R3B*R1P>20P-B2@=P'0=Q#`,P%`0R3@X"3@1`&0,Q!P,R!@ +M1!``[A%0[A!`[B`P[B#B8E?2*QS2;%*2*P:2;_C@"``=\```@B,@FHB";$_B +M(R+2*A;JW=)L6\;6_P``-F$`4B(.HJ!`93;^P"``#`JQ9`/-!249_@P:937^ +MP3,#854#L50#HBSJX4,##`BPJA"I`9@!DFSJ@FY'1'X$=%6`V#_(/D1 +MN!&A5P/0NQ"Y$9@1H)D@F1&($8)LYM$U`PP;P"``<5@#:!%P9A!I$?(A`?)L +MYJ(A`+"J(*)LZI(C'J(C'X(C'3"9$8"J$>"($:"(()"(()*D$I"((()L\(%B +M`W(C)/(C)&(C)'!Y)+(C)*!W`8!W$(%A`_#V),#_`8#_$'#_('%@`V!C).!F +M`7!F$'%?`["P)`"[$7"[$&"[(/"[(+)N5Z(B%[%9`Z"@=+"J(*)LII(B(*%E +M`Y"0=*"9())LIH(B()%F`X"`=)"((()LIG(B%8%G`W!P=(!W(')LIF(B('%= +M`V!@='!F(&)LIO(B&V%H`_#P=&#_(/)LIN(B%?%>`^#@=/#N(.)LII(LK+(M +M()"@!`=I".*O_N#I$.)LK,`@`.%I`X%J`^#K(.)M(/(M((#_$/)M(':`$+(L +MY[DAB"&`@!2)(?@A)C\#!OK_`,`@`(P:DFRL@B(TD6L#3`KA.`/B;-JR(ABR +M;4JB;4R]`ZT"DFU.217@"``=\```-D$`O0*!;`.1;0,6E@?8!A;-!@P&K/UB +MH`#"H`!VG2?B*(.B*$-"*,-R*4,H.>"J(*!$('`B($`B(+PB#`R,0_(#`"8O +M1QMF8-W`#`+"H`!A,P-"K_[0)(-V@#^B)N>@H!0F.B_"`P`F+#0,#,;Z_QO, +M#*['OL8,'0P"AO/_``#1;@,&Y/\``-%N`P;B_PP=?/+&[?\;S`ROQS\#1N[_ +M`*%O`^@5H.X@XFA"V%6@W2#2:4+(-:#,(,)HPDA%87`#H$0@22FH)1;K!6#Z +M(/)H@M@ETFB"R!7":$*X5;)I0J@UHFC"2$5)*;@5R%78->A%J"5V@!Q"*((R +M*$)2*4)B*,+X*4>:[C>;ZU>=Y?<>`@;W_PPL`#RFL!"F#`E\^J)H@2`I +M@QWPT@,`)CT(8.H@XFB"QN7_\7$#\/H@\FB"QN+_-D$`,6T#@34#06P#?/(B +M:($B9$$B9($B9,$I$R)C01WP````-D$`4.H#,J&0,"*"/?!V@`A`Z@-01,`G +MM`*&^_\=\``V00!"H?1VI`18`C<5_QWP-D$`+`-VHQV"<@2"`2">$2">(2">,0BT@(=\#9!`"%R`QWP-F$`30*]`0P,#`V(XJ%S`XD! +M94\(/0JQ?I +M$=@1T-`4V1&($28X`@;Z_\`@`(P#_'?```#:! +M`#*D<%CB#`=R80`Z-8(#DR9H`G)#DX%[`PPJ06P#\7T#P7P#8@.3^O7B+W]\ +M_0-R0YQR0YMR0Y+2;()R;(.R))BY`:)DF)(DF(D!Z`'),<%Z +M`_#N(.)DFM(DFK(A`)%^`\"[$+)DFJ(DFI)D@H(D@L`@`&78_ZT%:2%EA@`, +M&1R+;0K(,<`@`(+*Z!8X%+(L>W)B-K)B-:(E[9(3,@P?H*#T"YFGF0_2)>S" +M$S70T/0+S-><`0P/?/<,"@P,T7@#LJ4,\.\1XF(VNK4,#MK59;[_D3,#X34# +MP6T#@7`#@F2"\B2"1QR;$%R9$%R;H&B*:S2+B"@L`0':@=\[_#Z +M$/)IK,`@``PH@(T@@FX@@BX@?-_PB!"";B!V@!#R*>?Y$>@1X.`4Z1'8$28] +M`@;Z_\`@`(P;HFFL#/<,N*(#G`RMDB5AHLK^H&V#&YF296&'%G2RQND6.PCB +MQNH6+@CRQO86+P@+AA88"*+&^`R)+0>@*8,FDC61?P-V@"`+F8(D@_@\XBQ# +MLB1#@/\@\.X@X+L@C*L6B06B`YPF*@4&]O\6R02R`YRRR_ZP+8,F@A,FDC1W +M$@D<',<20AQ-UQ(##`(=\`P2'?`<0D;J_Y)L@[#JP`P)5@[KF4$&"0`<0@;E +M_QP2QN/_``PB'?`<0D;A_PPIDD.PB0MDDP].9'")"VR`_.B)"VYC)(#]I)*/((D+7(# +M].(D+7F8T@/ULB0MV:["(SJB)"W2KW^")"VHZL##!)#,$="J$,"J(*GKLJ/H +MDB,Z.>0D@1PF1&@=Q"0=R!YZ-(C.L(D+;JSN(D+=(;BL(D+;(;FJ(D +M+8)I<@P),F=SHBIR.)'2;G2R;'7"H_"RKW^L2@P-RJ-V@!D;F8(D+7(:9^(D +M+=J(>Y!,;W_P``HB0MHBIS#`FL2@P-RJ-V@!D;F8(D+7(: +M=^(D+=J(>Y!,;W_P``HB0MHBIT#`FL2@P-RJ-V@!D;F8(D +M+7(:A^(D+=J(>Y!,;W_P``HB0MHBIU#`FL*LJC#`QV@!D; +MF8(D+>(:E](D+Y`L;W_PP*DB0N@@/\+.$.EAV5'*NV9MP@P'@J#T#`F9$8J#B2&=!RP(PJ"T,+>` +MP+N`=J@;@B0NH@NP&\DKNYJ(HDC`@B0NH@NO*YG*B*)(P-@1Z"%RQT"=!^+. +M0!O=V1'I(68MP((D+8B(J)I>8(7\8"(D("!(8)I>X(D+?(7ZN(D+0O_ +M\E@6TA?KPB2FLB,<"]W27A>R7`*B`_"B9T^R(SJ2I"B:E;"P!+))V:(G3R8: +M#XA9@LC^%C@BJ%FBROT6"B#"%_#`P4'"5_*R%_&PL4&R5_/R)"[R+Q,,'@P- +M\/$$\-Z#TDG8PB,[P,`$PDG6L@/Z`+LCLF='H@/[`*HCHF=(@B.*@FZ")GX,!S%L`Q8("Z(D+:(*/:+*OA9:$[(D+;(+/K>\#,()V8QLV''2+8D6 +M71<,&J))YJ$S`^@BDBK=!VX*?._P^1#R:MT&`P!\NPP8@(D@L(@0@FK=\88# +M#.22TP2"H/ZAA0.QA`,A;0/1>`/!@P-R8E/:U<)B2`P,LF.`HF/`LJ4,NK6) +M"0P*0F)`\F(XXB:#XF/"#`XE3_\=\-(D+=(-/E:]]?(96^*F5/<^`L8]`*(D +M+2R8@DH^!M'_`+($S5:+])F!>0$,&LCBR3&E9_VA1P-E2/WAAP/B8X+2(X+` +M(``,"M&(`RP,=JPF`#VF@!"FH)!$B0&(`0`90+@!D)S``(BA``E`L)"1@(D@ +MB0&(`:JHJ4&M`F5M_PP*L8`#R#%E1/T,&J5@_?&)`ZA!F($<[/<:#H&*`X<: +M"+&+`["ZP%9[[.AQ#!W2;HE&K_\,"@:W_P"")"V22#U&E/ZR&5RR65ZB&5VB +M65]&@/_2)"U,+,)-/<:-_@#R&5SP\4'R65[B&5WB65_&>/\``)(D+8*@9()) +M/8:%_K(D+4S:HDL]QH+^``PJAJ'_TB0MPDT^AI/_```V80!\_4+2`0P(,J1$ +M48P#.C*"9-Q:4M)E(X(#OYP8@@._@LC]%D@.D@._)FD#'"(=\`PVD6P#<8T# +M#!P,&'IRHB>ZJ0&B*88,#Z"F=:#X@Q8/!PR&LB4>)@L5\B2MXA-(&__WGEF2 +M)*R"$TL;F9>83J(DW!8*"+T"PD.^V>.B)T-E90"B0[_")[O"9T.R)2(@NZ"R +MVP2X6YR+XB4B#`T@[J#BW@32;AWR)"$M!AO_\F0A'?#R)"$M!AO_\F0A'?`< +M@AWPK0*EP`(,''S]"XH6J!62`\CL.28J(:@!H@H`X8\#'%NW.@*&.0"QC@.P +MNJ"X"^J[H`L``"T&'?#B`\@6+@T,I@P_\D._!M+_``RB'?"")2.2`\@6R14,I@PZHD._#`NR +M0\$:@2T& +M'?``K0)ELP(,''S]#`_R92.&V?\`D@.H@J`@E[@"AB0`(*(@Y0L`H&H@#!Q\ +M_4;2_QQVAHC_``"B`\A6FO3&VO^R)T.XZU?K`H;9_^(E'B8.%8(DK?(32!N( +MAY]_HB2LDA-+&ZJGF70,"[)DW*(G0[T"I48`HD._\B>[\F=#XB4B(.Z@XMX$ +MZ%X,''S]C/Z2)2(,"**D1""9H*"9@()I#*(#OZ+*^A;ZVK(D(1N[LF0AAK__ +M#'(=\`!6R>H,+,)#R*5[!PP@1=XX:F!%@F2"29=V" +M)=V)$?@1DJ/HT/\0\F7=QO3_PB7GR2&X(;"P%+DAJ"%F.NX,HAWP5OKY8DN+ +MY6@'?-T&Y?\`@@N+5ECUJ6&&"```\DN!#`B"2XJ"2XN""W.I81:8%J(.818Z +M%O(NTO+/_O)NQ/&1`X(+<_KR%F@6##,R2XR"+XXR#WVB+XXY>((NYC(OCHDZ +MH@MTHD,A@@MTC'@R+XZB"W6B0R*B+XZ"+M\R+XZ)2J(+=Z)#(((+=XQX@B^. +M,B[@,F@&HB\AJ)JLRH(O(8B89AA(,B2!@J$THB^.(#.PBC,R(ZXY&J(D@3(O +MCB"JL(JJHBJOJ2.&"`"B)($RH32"+XX@JJ`ZJJ(JU*E8@B2!HB^.((B@.HB" +M**R)"OAA9B\4HBZ?,BZ@@9(#@*H1H#,@@#,@,FE,Z`+B+@('[G7A?P,]\`ON +M@BR#2#DR*4/R+$.`1"!`,R`P_R`63P<63@>B"XOBSO]F*MSB)>?I,<@QP,`4 +MR3&X,68[[I*CZ/(EW?E!1@4`C*FB)=VI08A!"YDW:/&X09*CZ'>+&?A!8/\@ +M\F7=XB7=Z4'(0=#,$,)EW<;T_P``HB7GJ5&849"0%)E1B%%F..XH81WP\B[2 +M"_]&IO]6/OEB2XOE3@=\W0;B_P`R+Y@P,'1&I/\````V00`,#9&3`Q:$`"84 +M*28D.B8T1\##$H."*!^2 +MTPJ9,18(1J(I+:CJF3&@K@06.D72);NRH-2PW8(,#-K3TMT+PFTDHB6[L*J" +ML9@#JJ.ZJN6^`*(EN[*@U+"J@K&8`ZJCNJJEQ@#B);NBH-2@[H+120/JX^+> +M"M)N,,CBL9@#-VP;DB6[#!B@F8(,#YJ3DMD*\FDQ@D(U^6*&!0```.(ENPP, +MH.Z"?/WJX^+>"M)N,<)"-9CR"_D6CS6"R?X6*#5ZHPP)#%S)`9)*@9CBD-$$ +M5CT,D.@$%MX+D/0$5G\+PJ#4HB6[DB6[@B6[P*J"P)F"P(B"JJ.:DZ+:"J(* +MRXJ#DMD*D@G,@M@*@@C*H)G`EQ@"!A\`#`IRTVH,#':`0>(EN]*@U-#N@NKC +MZNQ*[N(N;^(.%)*@U!NJG"[R);O0_X+Z\_K\2O_R+V_R#Q6<7X(G.Y"(@HJ# +M:HB""$E+S*(EN](ENZ*@U*#N@J#=@NKCVM/BW@KB#LG2 +MW0K2#I`@;2`*@1H@K[%HH:TB6[XJ#4 +MX-V"VM.ZW<(-"0O,PDT)@B<[\B<[DJ#4D(B"D/^"BH/Z\VJ(@@A):O_R#TB` +M_\!6?PB8XH?INJ(G.\*@U,"J@JJC:JJB"DD,#!;J+@P*T9H#?/]V@$:");OB +MH-3@B(**@XJ*2HB"*&^(*->H$Y(EN^"9@IJ3FII*F9(I;Y()$ISIXB<[@J#4 +M@.Z"ZN-J[N(.24NJ&\SG/`)&TO\]\(;L_P#2);O@W8+:T]K:2MW2+6_]#-@M +M1O+_````09@#HB6[LB6[PJ#4P*J"P+N"JJ.BV@JB"LG-`[JSL*J@O0*BV@JB +M*C2EH0"X\A;;$?*@U,(EN](EN^(EN_#,@O#=@O#N@LK#VM/"W`K"#,G2W0OJ +MX^#,H,+<"L(L-,)M)-(EN[*@U+#=@MK32MW"#0D;S,)-":(EN["J@JJC2JKE +MB0"B);NRH-2PJH*JHTJJY9$`\J#4XB6[TB6[PB6[\.Z"\-V"\,R"ZN/:T^+> +M"N(.R\K#TMT*T@W*PMP*P@S,ZMW7K'4H$0P/\D+[*`$=\)"(!!;8RY"D!!9Z +MRZT"O0,E#@&QF`.&*O^M`R7=`+&8`P:8_\(ENZ*@U*#,@LK#PMP+PBPD%FP8 +MXB6[H.Z"ZN/BW@OB+B3X0N@^>M/WGA\,"()-@9CR"_D6CQ>BR?X6&B"8X@QL +MR0'&'/\`*`$=\.(-@18N%0QO^0&8XL87_P"2);NBH-2@F8(,")J3DMD+@FDD +MQK[_,*,@(F$$Y6@`(B6[PJ#4P"*"XJ``*B,BT@OB8B3R);O`_X+Z\_+?"N)/ +MRM(EN\#=@G+3:MK3TMT*XDW+LB<[P+N"NK-JN[(+2`P"%IL&#`F9(:(ENS"J +MH*+::Z@:L9L#H**`H*JP,*J@NJJEZP&2);O((=*@U-"9@IJ3FIQ*F:)I;X(E +MN]"(@@P.BH.*C$J(XFA_\B6[T/^"^O/Z_$K_XF^/LB<[T+N"&R*ZLVJ[L@M( +M2\S)(;((KIX)I>8(KIX)I>H(KIX)I>X(KIX)I?((KIX)I?8(KIX)I?C"/H)*B +M5!O_\/!TFHCB:']F+ZK&H_X@HB`PLR`E10&@*B`=\)CB#&JI`4;%_@Q<#![B +M38')`0:I__(ENZ#_@OKS\M\+\B\D\@\3\L_^5O_FF.*0B`06^`BB);O"H-3` +MJH*JHZ+:"Z(J)*(*%A:*Y:(EN\T#LJ#4L*J"O0*JHZ+:"Z(J)"5U`*(EN[*@ +MU+"J@K&8`ZJC/?"ZJJ5A`*(EN[*@U+"J@K&8`ZJCL*J`96D`TB6[#%+BH-3@ +MW8(,#-K3TMT+PFTD'?``\B6[@J#4@/^"^O/RWPOR+R3R#Q,+_Q;O]ICB1GC_ +M``"B);O"H-3`JH*JHZ+:"Z(J)*(*%E:*W`;;_P``-F$`XJ#4#!LI$9T"HJ00 +M0M-GPB3[#`;]!C#,H*K,:1R(^5(D^R&8`X+(_CI5JE6`^X/R1>S2)/O")/N" +M)/O@W8+@S(+@B(+:T\K#TMT*T@W+BH/"W`K"#,R"V`J"",I1F0/0S,#`B,!6 +MR$`,#G+3:@P,T9T#=H`7``$#```3`L`8`M`#``$3`"````(#`L`!\B3[LJ#4 +ML/^"^O/Z_-K_\B]_\@\4HJ#4&^Z<+X(D^["(@HJ#BHS:B((H?X((%9QHDB<[ +MH)F"FI-:F9()24O,YSD"!K0`!AH`HB3[L*J"JJ.@K(#0JH"B*G\0$2`EF@#R +M)/N"H-2`_X+Z\RK_X@\)#`T6_C?Y`:T/#`QV@!<``0,``!,"P*X"T`,``1,` +M(````@,"P`$H2I("$QO=2ZJRR?U6NR>X8HCKA^@"1IP`1IH`TB3[PB3[XJ#4 +MX-V"X,R"VM/*P]+="M(-R<+<"L(,R-><"#"C(!`1("7Z`/(G.^(G.X*@U(#_ +M@H#N@OKSZN-:__(/25KNX@Y(]YY0HJ00JJ.R"ONI(>*@U+P[TB3[X-V"VM,J +MW<(-"0O,PDT)@B<[\B<[DJ#4D(B"D/^"BH/Z\UJ(@@A)6O_R#TB''\,&`P"M +M`Q`1(*67`*@AQO/_6!'BH-3")/O2)/NB)/NR)/O@S(+@W8+@JH+*P\+<"L(, +MR>"[@MK3T,R@PMP*PBPTJJ.BV@I9;*(*R;JSL*J@HMH*HBHT@J#_@DH1DB3[ +MHB3[X)F"X*J"FI.2V0J2""N(N--A%V3[")/O2)/N` +MS(*`W8+*P\+<"L(,R=K3T,R@PMP*PBPTL@4VLDP2HB3[@*J"JJ,JJI(*"1N9 +MDDH)\B3[@/^"^O,J_^(/"0P-%OX2K0_P7R`,#':`,BA*&]V2`A.BR@2R(@8F +M.24':0VR(@>"*PZ':`2""S6]78;Q_XCKAVC4 +M@@LU5NC\&\PB911+5>(/"4;X_SWP1C+_@@LUK$@':0VR(@>"*PZ':`2""S6< +M.!=I"YB"N.F""36':P&,2.>]>,9,_Y@!&\PB:13B#PE+F9D!!OK_``"B#PC" +M3PJGO!7PK*!V@`QB:A2R#P@;S$NJM[P"!OO_\J#4XB3[TB3[PB3[\.Z"\-V" +M\,R"ZN/:T^+>"N(.R\K#TMT*T@W*PMP*P@S,ZMW7+`,,4AWP#%(,'O*D$/KS +MXD_['?`AF`."#PC"3PJ'/`)&.?_PK*!V@!%B:A22#P@;S$NJESP"QC/_/?#& +M^?\``'+3:H8P_PP,1MG_``P,1O'_````-F$`@M)JB0&"*#MAF0.2H-20B(*1 +MG@.*@FJ(@@A)#`20(G +M?T&?`_*@U/#N@NKB2N[B#H%0,H`67@""`_L6R`22)W^BH-2@F8*:DDJ9DBDB +MXJ#4P4D#C+FR)W\@NZ!:N[@;%KL$TB=_X-V"VM)*W<)M'AWPFG)&Y?^M`J6[ +M`!;Z^?(#^Q8?_X;E_P```""B(&5>`((G?Y*@U)"(@H""@$"(@(((@19X^:(# +M^Q;J_8;C__(G?Z#_@OKR2O_R+R(,#N)/$<(G?Z#,@K%)`\K"2LRR;!X=\``` +M`#9!`((""0P'%N@'70*]`@P*=H`R:$5RQP%"!A-2Q022)@8F-"0'9`R8=C(I +M#L()-8=C`9SL%V0+2(;8Y.($-8=M`8S^A[<=AO'_^.DR"36';])6\_P;JF)K +M%$N[@@()1OC_````0@((HD(*1[H9;0H@6J`,!W:`#')E%((""!MF2U6'M@(& +M^_\=\`P*1O7_`#9!`((""0P'%B@(70*M`I*@`':`+6A%&W="!A-2Q02R)@8F +M-"`'9"NR)@Y&6T)(%F@#`=V@`QR +M922"`@@;9DM5A[8"!OO_'?`,"4;U_P`V00"B`S2B0A&8\PP;%ID&"XD6J`HF +M*0RH0ZDRD@,VDD(2'?``.8*B0S22`A/2`A8,*J"9()"0=))"$[CCP@(4H-T@ +MAVL=TD(6H,P@PD(4L@,U\@(5D@(3C(N@_R#R0A7H8^D2@LG]%E@*N`.Y(JA# +MJ3*2`S:20A(=\`PY.6*B0S220A/(X]T#AVP0DD(6DD(4T@,U%BT`DD(5V&)` +MM"`@HB#"H`#B(Q7R(Q3R;13B;16E"`"H0ZDRD@,VDD(2'?`YABJ7+2!8#" +M!8`,*K(>$I#,@I#=@LK#2LS"+'3:TTK=8,P@PFUT\@6`PAX3TAX4D/^"XAX5 +M^O.`_X`E2P&I@N(%@-(%@%R/\-V"\.Z"VM-*W=(MBNKC2NY@W2#2;HKX8KAR +MF`^9"YDBX@\TR"^8'X@_B3N(/^)+--(/-,DJTDHTR0K2KO_)*YD:F1OHZKB" +MB3KX[YART.X0\/@$@/\1\.X@Z>J(ZARPJ(`V&WR3C79:]ENV1*8ZXARV(+`F2"9Z^CMR.CRK?_@Z03PS!!P[A'@ +MS"#H8LGHN.V8[GSLP+L0D)`$L)D@F>VXZ)"0!,"[$+"9()GH@FX0^(+R;A'B +M:!+R:!&";Q#B;Q(=\/(%@%R(@/^"@:,##!KZ\XK_I3L!@:0#7(F]"NAB#"JY +M$](>%+(>$I#_@N(>%?KSBO\E.0&I@L:^_S9!``P*0:0#7(C(D\Z3G9&MD9N2JY+-CJB.P,"_#=$(=H!XCI +MAV@"LJ`!F(*PX`2X#=(-GJP@LU#`J,;(()-0P?@*^3R&*@T'323#6L +MC=*M_ZCLX@DT^!+Y;+)L$))L$>),--"J$(B"Z&*I[.)H$OARXF\2'?```/*M +M_^CL@@DT@DPTDFP1LFP0\.X0V(*(8NGL@FT2J'*":A(=\#9!`$("$U*N_XB" +M!V0-0B('..10,Q`R9`Y"`A,79`E(Z%!$$$GH0@(3)C0'#`B"0A0=\`#X&)@F1"9ZHCG4D=20A120A4= +M\#9!`.+2:H(N.\&9`Z*@U*"(@I&>`XJ"RHB""$GQF`,,"Q98&YI"#`I1F@-B +MK_\QG0-V@$*")'_2H-30B(**@HJ*.HB"*'^(*%>H%)(D?]"9@IJ2FIHPF8"2 +M*7^2"1*(+(D?]"[@KJRL+:@.KNR*W\@ +MHB`,/+(+$:6U_J&-`_&8`^(D?[*@U+#N@NKBZNR1]KF +MW0)V@!Y0W:"878AIF4V<:(AYG*C8B1O,K`U"!0DJW`N$A[TAAO;_`((N?XEJ +MQO?_DBY_F7J834;V_P``TBY_V8I&]?\``)PT4)2@^3GB!0E0CJ"(.`ON,D@1 +MXD4)-QL)K0;"H`+EGOX=\!WPF&J,:GXZ)B*P/\0^>B(Z?AJP(@0B>GX[PP9\/L$5N_Q@M8% +MDD@+'?`````V80`I(=(B$R+39X(B^PP.DJ00,(B@FHCI&!9]!D&9`W&7`YJ# +MHM-JJ3&)$<8-`+@APB+[TJ#4J`'0S(+1F`.H"LK#VLREG@"B(ONRH-2PJH*Q +MF`.JH["J@"5P_]@!R"'87=)L$YQ]J$WQI@/9`?9ZZH&G`_#ZH/@/BO^@#P`` +M`)*D$`P.@B+[,(B@FHB(&!88(J@A0J/X2D/I>NE*Z0KI-*(J#Q9*'8+*_Q:H +M'9+*_A;)&ZT#)5C_LB+[PJ#4P+N"P:@#NK/*N[(K(*($]*)+$1WPHB$"HBH/ +M4BT"%DH;O04,'-@A#`[]`]A-)5@`B"'X`0P9DD@U^"_Y:.(B^Y*@U/&H`Y#N +M@M*@U.KC^N[B#GRQJ`,,&A9N&:(B^Y"J@JJCNJJB"GS"(ONR(OO0S(+0NX+1 +MJ`/*P[JSVKNR"WK:S,(,>^@1#!W*N[&BO_R(OLP_Z#B;_&&A_^R(OO"H-3` +MNX+!F`-0I2"PLX#`NX"E,P"&C_\`AIS_`!WP```V80#BTFJ"+CO1F0.2H-20 +MB(**@MJ(@@A)/0(,"A;8!D&>`PP+P9T#2D)V@!<``0,``!,"P&D"T`$``1,` +M(````@,"P`'R)'^2H-20_X+Z\_K[RO_R+W_R#Q*<;_(D?Y"?@IJ3D)N`RIF2 +M*7^""13R"1.+,$!9N$&E`V<;7_("$XS_ZH/2*'_98I(H?YER@BA_B8(,#=)"$])"%=)"%-)"%O(, +M"9A'F0$+CX^&F(>9E.5N\&\B=_^6*&&0"( +M:8CH@(@$5OCQAM#_`)ABC&GXM`\*@`B5. +M_@P"9Q4"'?``\B1_@J00,/^@BO_X'PP>\"Z3'?`V00`,"'("*@P)=I06>E)2 +M!0@;1RPF-Q4.?0D;B&>T`7T$/?`,$AWP#`(=\#9!`$("*C("*T`CP$>S!"+" +M(AWP'?```#9!`)CRLJ#_H:D#%OD((9X#0J1X*B,F&1YF*322(G^"(G\,+#J( +M2HB""'4ZF4J9P(@@@DEU!@8`TB)_PB)_#!XZS$K,P@QU.MU*W>#,(,)-=>(B +M?SKN2N[B#G5F/CN@4X#R)7_R#S2W'QJR)7^M`\*@`K(+-*5`_K(E?ZT###RR +M"S3E/_Y*P^(B?PP-#%(Z[DKNTDYU(DR+'?`,8AWPJE/R)7_R#S3P(`"W'QFR +M)7^M`PPLL@LTI3S^LB5_K0,,/+(+-.4[_@Q2'?```#9!`)(#"PP(%ID';0.R +MKO\,"G:`17(F)!N(2!=+9E('$R>4,P=E$9AW4BD.HDDU/?"P51!9Z5('$Q=E +M#\B'F.RB3#6PF1"2;`Y2!Q,F-0ZB1Q6B1Q22`PN7N"G&[/]8=TCEHD4U^(>P +M1!!)Y>COHD\UV&>P[A#I[\CMHDTUL,P0R>U&\O\=\``V@0"]`TDA:0%9$*ACJ(@BA_B!BWF,XF'&1F+,B2)/OBH-3@F8*:EYJ6.IF2*7^2"16I49+) +M_1;Y&?(D^^#_@OKW^O8Z__(O?_(/%:E1B"'RS_X6?QI6B!SR)/O@_X*8`?KW +M^O8Z__(O?ZE1&XGX/Y")LX"!(8#_P!:?]H:-`)(D^^"9@IJ7FI8ZF9(I?Y() +M%:E1)CE#\B3[X/^"^O?Z]CK_\B]_\@\5J5&((28?3E;X!O(D^^#_@I@!^O?Z +M]CK_\B]_J5$;B?@_D(FS@($A@/_`%D_T1C<```"B)/O),>"J@KE!JJ>JICJJ +MHBI_Y4W_J%&X0=&K`\@Q1L?_``"B)/O),>"J@KE!JJ>JICJJHBI_I4O_J%&X +M0=&K`\@Q1K[_``#R)/O@_X+Z]]K_\B]_J5$6[P62)/N")/O@F8+@B(*:EXJ' +MVIF2*7^*ACJ(@BA_J5&7F!CR)/O@_X+Z]]K_\B]_B!'X/ZE1@/_`%K_JHB3[ +MN4&RH-2PJH+),:JGJJ8ZJJ(J?V5$_ZA1N$'1JP/(,8:A_Z(D^\DQX*J"N4&J +MIZ"F@#JJHBI_)4+_J%&X0=&K`\@QQIC_HB3[R3'@JH*Y0:JGJJ8ZJJ(J?R5` +M_ZA1N$'1JP/(,4:0_P``HB3[R3'@JH*Y0:JGJJ8ZJJ(J?^4]_[A!R#'1JP.H +M449Z_P``HB3[R3'@JH*Y0:JGJJ8ZJJ(J?Z4[_[A!R#'1JP.H449Q_P``\B3[ +MX/^"^O?:__(O?ZE1%N\%DB3[@B3[X)F"X(B"FI>*A]J9DBE_BH8ZB((H?ZE1 +MEY@8\B3[X/^"^O?:__(O?X@1^#^I48#_P!9_UZ(D^[E!LJ#4L*J"R3&JIZJF +M.JJB*G]E-/^X0<@QT:L#J%&&5/^B)/O),>"J@KE!JJ>@IH`ZJJ(J?R4R_[A! +MR#'1JP.H4<9+_Z(D^\DQX*J"N4&JIZJF.JJB*G\E,/^X0<@QT:L#J%%&0_\= +M\#9!``P'@@,+"T))$Q:8!RT#HJ[_#`EV@$5B(B18$[@6&W=+(K>E-%(&$]AV +M!V4,R.V2336@S!#)[5(&$Q=E$.B&TBX.DDXUH-T0TFX.4@83)C4.DD85DD84 +M@@,+A[M(Y9)%-?AFH$002>7H[Y)/-:#N$.GO +M1O+_'?``-D$`\J[_#"78AZ!^@$F$[7&2D7:PRR"A47ZP:XBNA+UQX]2T0=\`!F._>""A68 +M:E;X_IA)UYGJY1K_'?#8[O#=$-GNP@H44,P0PDH4HB04L@H39CO.B&KHZ/#N +M$.GH'?#(Z_#,$,GKD@H4D)`$DDH4HB04@@H39CBJZ&K8[O#=$-GN'?```#9! +M`*($"PP)%@H2?032KO\,#.*@`G:`/8(G)%CS8@@4&YF\-0=F$+((%0=K"KAX +M\BL%(/_`%O\(%V804@@5:(@790BR)@4@N\`62PM+=Z5XF(($ZAX!V8/8BH.PDHU/?#09A!IZF(($Q=F#[B(J.O" +M2S70JA"B:PYB"!-F-B2X>*CKPDLU:(C0JA"IZUCFPD8U^&C051!9YKCOPD\U +MT+L0LF\.PD@5PD@4H@0+QN#_F.O"2S6")R30F1"9ZU((%.!5$%)(%%(G)"(% +M%>`B$")%%2(G)/("$V8_.*ABN.K"2C70NQ"YZAWPB.;"1C52)R30B!")YB(% +M%"`@!")%%"(G)/("%?#P!/)"%2(G).("$R8^`1WPF&*HZ<))-="J$*GI'?`V +M80#AG@.=`KCTR'0AF`,66QGRU6J"+SO1F0.RH-2PB(+P?!&*A=J(@@A*&W<, +M#!9H"9D!#`JQEP/J99#GP.+._W:`@((F?R*@U""(@HJ%BHJZB((H?X((%`=H +M%Y(F?R"9@IJ5FIJZF9(I?Y(I!Y(I!.<9-((F?R*@U""(@HJ%BHJZB((H?X(( +M%!O,%V@ADB9_()F"FI6:FKJ9DBE_F(F82>>9"PPJA@H`#!I&"0```((O.Y*@ +MU)"(@HJ%VHB""$I+JH>\#`;>_P"9`>IED.?`"^X,"KT#PJ``TJ``_05EE_^X +M]"&8`Z(F?\*@U,"J@JJE*JJ2"@H6RQ3H`0O+#!@,#\#X@^#GP`ON=ID;LBH4 +MP@L4V'L';`2"#36,R!=L!KB+D@LUO,E+JAWPB$WGF.P,'CEM.1OB337"*A3P +M@Y")7;(,%>"[(+),%;(J%)(+%68YU=AK#!S"3362*A28:3E9.6D=\(A+YYB\ +MPBH4B(P,&3EKN&BY'))(-<(J%/#CD.E8L@P5#"W0NR"R3!6R*A22"Q5F.9+X +M:PP>XD\UTBH4V&TY73EM'?``ZF7R)G]RH-1P_X*9`?KU*O_2#PM]#`P,%BWR +MK0\BKO\,#G:`2K(J)!O,B!M+JI(+$S>8,P=I$=A[DBT.XDTU/?`@F1"9[9(+ +M$Q=I#XB+V.CB2#4@W1#2:`Z2"Q,F.13B2Q7B2Q32#PO7/`+&(P`]\(;K_P#8 +M>YCMXDTUB(L@F1"9[=CHXD@UF&L@W1#9Z(CIXDDU((@0B>G&\/\```#H`>#G +MP.+._W:9#+(J%/(+%,AK)C\#2ZH=\((,-598_YA,YYGP^(N8>PP>.6\Y:3EL +M.1LY7SE9.5SB3S72*A28C=A]D@DUDDTU@BH4^'B(:/(/-?)(->(J%`P]TDX5 +M'?"X]"&8`\:-_P``-D$`#`,R0A,R0A0R0A4R0A8R0A(Y8CER.8(=\#9!`#)7 +M$H*N_Z*@_Y*@`!92`$!!]&!A04)7$U)7%&)7%9E'F7>99YE7DD_28T3"8T*R8T/!/P-R1H^B8NJB*7\\&,"J(*)I?Y+)6':H%X(I +M?[(IE:+)6,"((,"[(()I?[)IE9+*6*&U`Y*@_\*D:K*B-+JRRL*23("JHE)J +M@4)K?W)J?7)J?Y),@4)K@')J?G)J@%)J@AWP```V80`,2`P50M(,0B0F60%9 +M$0`XIC`0IB$S`S)A`7:`$*(BYZDAF"&0D!29(8@A)C@"!OK_R!')`;@!)AL& +M60$H`1WP`#&V`P`SIB`0I@P-*0'X`>@!V0$H`?#U%/)$`>#@1.)$`!WP`#9! +M`%+2#%(E)L&V`V+2!%(%`5)F+``\IM`0IC&W`]#F!-#05#HRXD-\TD-]`#RF +ML!"F`#RF4!"FX+L14(,D4&($4*84L*H@HE,_DA,_4%$$DF,A@D.`8D.!4D." +M(@."(F,C#`(=\```-F$`48P#HJ$H0M(*TB2F#!P,"](-`#*D$#HRTLW[T+R# +MLD/HDB2FJJ):4I()`9)JXH(E(IP(@@6`X@/H\J``@/R#\.X@XD/H#`8`-J;` +M$*:2HVR:> +M7[(*;@P9%@L(TB/&PB,8UQP:XB0MX@X]XLZ^%CX)@B,8\B/&AS]]HB/&HF,8 +M`#:FP!"FK0SVG$"V7`*BS/LF.F(DI`#_$;(#Y_#,("#N$>"[ +M(,"[(``VIL`0IL)G$Y(G$QN9DF<3@@/?X;@#@LC_%@A*PB0NPBP3@B<3DJ`! +MP,$$]B@"DJ``\(D1\B<4P,@@#!GV+P$,"8(7M.#Y$8"($?"((,"((()MC/(G +M$X%M`^#_$?#[(.#_(/F8D@/?)AD"8F<4L@/?)BM(XB<3\@/DPB4BLJ#4L,R" +M&__*PL+<"L(,R``/0.#@D>>\`@:)`/(G%((#Y.(E(K#N@H+(`>#B@.+>"N(. +MR``(0/#PD?>^`@:6`/(DI!8?/%@#\%41@@/?\;D#PJ9N@LC^%N@X`#JFL!"F +MLD2ND@2N%OE+RK(,">*DJ`N%@F$`X.*``#:FH!"FFL+ZS*),8*"@=+9J`D8D +M`/8J&@`VIL`0IH@!PEN?P,#TQ[@J#!S"0_N&'@```"8J""9*$69:%\8"```V +MIH`0IH)N'@8"```VIL`0IL)NX1N9*[M+[H+*_1:H/+;9FPP:HD/[L@/?HJ$" +M"[L6"SRVV34,',)#^T8+````.J;@$*;B0^72`^4673`,'P`ZIK`0IK)#YI(# +MY@PHD/B3\F2DQEW_#!S"0_OB)"[B+A,,&5=N!/(#WYP?@B0N@B@1%G@`H@/? +M/?`F&@$,"9)#Y[(D+K(K$U=K!\(#WSWP%KPIXB0NXBX1XL[_%GXH\B=1%A\! +M(*(@Y5$!T6P#%EH`+0H=\```@B0N@B@3%V@?D@/?)BD9`#:FL!"FLF=3HB=3 +MMCH-#&(,',)#^QWP``!B9U,,&@`ZIJ`0II(D+I@)/#ZJF9+)&I>^`L:3`))G +M$,(G$,)G[;(D+K(K$["W!!:;#``VIO`0IO)CQ>(CQ;8^`H;2`((CQ0N(%C@U +M#!P`/*:P$*:R8T*B(T)\J9>J`H;(`.(C0J9^`D;&``P:`#JF@!"F@F-#\B-# +MER\(LB-#YGL"1B$`#&(,',)#^QWP``QB#!W20_L=\`Q28F<3#![B0_L=\/(D +M+?CO\/<$5G_(#!P`/*:0$*:R)2+"HVP@N[#*NY)K(((D+H(H$X"$!!9HR-(# +MY58-R`P8`#BFX!"F\B4B@J-L(/^PBO_B;R'&&?\,4F)G%`P9DD/['?!B8T.R +M(T.R8T*B(T*B8\6B)VN2)VR")^Z@H#20D#2C]A:3]AJ#]AYB9VOB%[;R`^4` +M#T#@X+'B5[?"%[>R%[3`NX*R5[B"%[BB`^61?P,`&D``B*&"5[GR)S3B%[3" +M%[>P_P$+[@O,P.X1\.X@0,P1X,P@X6T#"YG";DFR+<,6:Q`6:1#"`_P+F68L +M[@P.'`\BH&!,&()MRN)MRY(D+O+/$`SXZIF2"6"2;#_$?#[((#_ +M((%M`^#_(/F8QM#^]MD"A@W_A@O_`#JFL!"FLD2O@@2O%OC"#`GBI:BRIFX+ +MQC"))KB`[7PJL"R))K(/((#M;(+ +M(=#,P`P=P,V3X+O`H*V3#!ZPO9/`JB"PJB"O*!?@.28Q"A20.B9LB";X/R+X/R9H+HPXS>PB0MP@P_5EP` +MDF,,LD/"T@/"9ATAO0+BK__B8P^B)"_E^ORB0\/R`\,,&R9O"+)#PPQR'?`` +M`((#PR9X1R"B("4C`1;*`:`J(!WPH@/"9AH7PB46G!S2H`#20\(EV_N&`0`` +MXJ``XF,,(*(@DB.ZDF7&@B71B5'R)='Y0:77`8QJ#&(=\`QR'?"M`J42`XPJ +M#&(=\*(#M!8*$[(CNO"[$;GSPB74!VP'#!W216D&`0`,#N)%:?(#R19_$8(# +MS(PH#&(=\)(D+I(I$Q=I"0QK`#NF/?"@$*;"`Z\+S!;,$@S]V3'`(`"1?P,A +M;0,,)PN9XB)#%IX/%ID/\@/,"YEF+^Z(,<(#M`SY\-@1T,P@PF94LB74PB6A +MHB6B`+L1@,P1P*H@L*H@HF9(EQ@.\B$$XB$%(/\1\.X@XF9'LB2DH@2LD@.T +MT+L1L*H@H)D1H)D@DF)*@B0NB,@,"LRHTB0MT@T_PJ`!T*R#H/H1D7\#PB7C +MTB.XX@.T"YG`S!&"!*R`W1&R)=70[A'@B"``NQ'0B"#`B""P_R"`_R#R9HWB +M`[3B9LB")H/X,N(B0](F0X#_(/#N(.#=(!8=!!89!*(#S`N99BK=#`(=\``` +MLB.ZN?.&L__")"W"##]6[.WR)=32)=$,'O#=P-#>D])#PH:R_U;9\')#S*47 +M!`;!_U99_')#S.46!`P"'?````""`[6RTEVX>YSXTB2DR/O7'!CHZY=N$_(K +M$((DI)(K$0N(@)^#%FD/D+D@DB2D%MD$F.N7:1FY80?I`@8B`,A1##JI,?#, +M$O-[(32JA1 +M\+L1I5H5J0&R$TJH4>56%=@!PA-*N&$,3M#,@NDQRLK)408/``#R)"_X#[EA +M\/S`UR_'LA-*J%'PNQ$E5Q6I$;(32JA195,5N&'H$=(33L(32@Q?^3'@S(+0 +MT?3*RMK,R5&(48E!1IS_``"2)"]660"B)*>B9"_"*Q%67`#2)*?2:Q'B*Q#, +M3O(DI_)K$`SX#!F20\N),0:0_](D+]@-T-G`QL[_`#;A`$&\`Z*C4#+2:+(C +MNZI2@A7$(+N@2KNR*WIBI"1Q;`.WF$;2([O"%<(@W:!*W=(M?-#,P%9L:/(C +MN^(E.R#_H$K_\B]^@M(*B?'WGB&2([N"*"T@F:"""#Q*F9(I@)>8#6J2F>'& +MV@```++2"KGQK0(E:?T,#I&]`X*@U`PJFI*B25O2([N909&8`X#=@GP/VM*: +MW?<=(K(-",T-=IL:N$R<.XAK%A@`Z6N(>XPHZ7NX3(B+C`CIBTO,XDT-PB.[ +MLJ#4L,R"RL+"W`KB3,V"([NPB()H\8J"@M@*XDC(8B8MTB.TPB.[L,R"RL+" +MW`K"#,UB!CR\+,(CN["\@KJRD+N`]QLB\@L(L,L@=I\9F$R<*8AI^'F,".EI +MC"_I>9A,B(F,".F)2\SB2PV8\9(IFI()(PN9%IE3N/&R*YJR"R.RR_X6NU(, +M#TJBPBJ%%AQ<@B.[DJ#4D(B"BH*"V`J"",AGN`ZR([N0NX*PLH"RVPIB2\C" +M([N"H-2`S(+*PL+<"F),S(CQ@BB:DJ_`@@@CLJ"`8;X#@LC^%N@OB/&"*)J" +M"",6."^H\:(JFL*D)*(*(\K"R>&BROT6NEBRTFJR81&2([O2H-30F8*:DI+9 +M"N))R8(CN]"(@HJ"@M@+XF@D0B.[T$2"2D)"U`KB1,KR([O0_X+"(1'Z\O+? +M"N)/R\(L.]#,@M&9`\K"VLS"#$A9,0P$%AP'#`5QEP-AFP.B([L@JJ"BVFNH +M&JJDH*JP(*J@8*J`Y=7^@B.[PJ#4P(B"BH**A7J(HFAO\B.[P/^"#`[Z\OKU +M>O_B;W_2([O`W8*R(1':TMK5>MWB;8^R*SO`NX+!F0.ZLLJ[L@M(&T1+5;((F&H)I>8(F&H)I>H(F&H)I>X(F&H)I?((F&H)I?8(F +M&H)I?@Q(XF]_*IM*F4O_IY^R@B.[PJ#4P(B"\4D#BH*"V`KR:##2([ORHU`@ +MW:#ZW>)M,;(CN\"[@@P:NK*RVPJB2\V2([5\"("9$))GQ/(CM=(5Q(#_$,#= +M`?#=(/%M`])O1L(CN_&\`[(5Q"#,H/K,LFQZHB.[DA7"(*J@^JJ2:GR"([O( +M\=(E.R"(H/J(TFA^TB.[PBPM(-V@^MW"##S";8"R([L;N_8K'I'``R"+H`PJ +ML*K`D(B`=IH-XFA\XFA^XFB`XFB"2XC")3O"9XNR)3NB%,XBXNT@WEXBX3#`)`W1'@Z`3@W2#29\<=\`""I"2* +M@HGA@@CJ"X@62$*(X8((ZO*@8("_@[FQR/'"+"W"##VRH'7'NQWR([NX)$B16*'2)'_"(1"M!U"P=-#,@,)D@&56_.(A +M$>(N+TM$&U7G-=[R(0_R+YKR#R-2(0-Q;`,6#Q3!P0.2K__848(CMD(CM;(C +MNZ(CNX!$@B"[H`N-D(@PRKM*3<*@U,"J@LAAJJ*BV@JB"L@+1(!$$,JJH*2" +M#!PEDP.XP<"[$;JR:KNB:WVB(1&8H:(J+PP.I[ETW0EV@!7R*WW"(1'Z]/)K +M@<(L+QO=LLL0Q[U9#`Y&^/\`R/&RH8#R+"V2+"V"+"W"+"WR#SZ8Z8(8%O+/ +M]\(<%Y"9!("(D)"($1O,NHB`S((,&)"HD\"Z@BR\Q[\DD<(#H<,#D)^@F`FJ +MF:`)`*+2"JGQ!FK^R/'"+)H,&[),(T:[_AP*@B.[LJ#4L(B"BH*"V`J"",@< +M#_#Z8Q;X'Y(CN["9@IJ2DMD*D@G(]SD"1I'^N/&R*YH,#@PZHDLCAHW^`((C +MN\(CNY*@U)#,@I"(@LK"PMP*P@S(BH*"V`I@S&/"2,P&D_[X\?(OF@P.#$W2 +M3R.&GOX`0B.[@J#4@$2"@@SJ2D)"U`I"!,@+B!M$0$!T%B@"N(.R("J@H*O +MP*+*/^#OP("J$."J@N5[`\&[`[B!X<0#F.'RRC\JU**OP)(97:#_$.K=L)F" +M(+2@RKN2R3^@F1#R:W]"37_R(1(;I*EQ&^_GNE*M"]DA21%`S\#)`0=L%$NK +M&XV)(8(K?\AQR1&*B8)K@$)-@+@AR!'="8@!G0JM#("!07:8'8(I?QO**[N* +MC8)I@*)+?H(I@"NJBYF*C8)I?\)+?TQ=@6T##`G(0<"T$;JR:KOB3)_"*WV9 +MZ-G8TJ_`PLP_T,P0PFM]V%&B([:2([4+C:"9@GSZH(@PFMT+W8#=$/:T!(%M +M`\GXF'$]\.>Y)@P+0*_`=IH>2LO`C!&*@FJ(XBA]&[L;S.KMXFB!]KP$D6T# +MZ?D]\,(CN]*@U-#,@KCQRL+"W`KR3,BR*YH,#@P:HDLC1CO^`.*@P.FQQO?^ +MJ.'(L:(:7;EAP*J"V5&BRC^0JA"&'/\`PB.[L,R"#`[*PL+<"O),R(81_@#X +MX0P+#`[I7X(?7;G!#!NPB!&"R#^0B!""8[[X7_)J@^)CP0;T_ME1PJ#`R8'& +MC__94:'%`^6\%-A1#`[&9/\`V5&AQ@/ENQ3840P.QF#_`-E1H<<#Y;H4V%$, +M#L9<_P#94:'(`^6Y%-A1#`[&6/\`V5&A8@/EN!3840P.QE3_`-E1H<,8AWP``#= +M(]);'P`VIM`0ICWPART"INT'8D7G#&(=\```/2,R6]\&!``R)2(,#=);WP`3 +M0`#6H=);'QON*[MKF>(B[FMW&__GOP+&T__R!G*0DH``/*:@$*:@H'06^@T`-J:@$*:'J@+&.0"FZ@)&.```NB.R5Q\` +M-J:@$*:'J@+&-0"FZ@)&-```VB/25]^]"0`\IJ`0IN*@`#*@`J"@=':C4;R: +M`#:FT!"F/?"'+0*F[0=B1><,8AWP``#=(]);'P`VIM`0ICWPART"INT'8D7G +M#&(=\```/2,R6]\&!``R)2(,#=);WP`30`#6H=);'QON*[MKF>(B[VMW&__G +MOP*&T__&"`!B1><,8AWP`&)%YPQB'?``HB4A#`NR5]\`&D``-J$R5Q\&IO\, +M`AWP8D7G#&(=\`!B1><,8AWP`.(E(0P#,E??`!Y``-:ATE<,8AWP`#9A`)+2"H(II:'3`YQ(H#*`=H`,PB-_R%S"8W^R*:6,&P;[ +M_T*D@DI"T@1VDJ$"G&T`.::@$*:B1'<`.::`$*8,`H)$>!WP````.:;`$*;" +M1'FR!'D6NP@,!1P\8=0#T=4#JC)J8MHB5SQ\&U4O_";W_B)'S0[H*X`>KBZN5Z[L)NC[(K.]"[@M&9 +M`[JRVKNR"T@;,TM5MR.9H=<##`TRHE3AG`.2H".@\H"0G8(,2""9H.J9=J@R +M@B^4DLD@@FEW@B^4@FEX@B^4@FEY@B^4@FEZ@B^4@FE[@B^4@FE\@B^4@FE] +M@B^4@FE^((V@+#D;W3J(PFA_T-!T9BVMDM(%PDD#'?```#9A`,*D$,I2@@7H +MDJ``%B@`DD7S0=@#2D*R)(%BT@D6&R>")FV(Z(".!!9H)I(%WV8I!2"B(&7I +M_S+2:J(E*'+2`Q;J`,(C.[(G46#D>R!>86JT7"(SL@S*#"+//"9T'B +M(SO2)T$@[J#2;O>&$@"R(SNB)S4@NZ"B:_&2(SN")S8@F:"":?/R!>46WT7" +M!>86?$32(SL@W:#2+?/29T&2(SN")T$@F:"":??R(SOB)W,@_Z#RWP3B;R>B +M!?,6*C;"H'4,#Z(%W`P8B1&@JI"B1>*2)N3B!>+2)FV2R?Z0^(/2#3WZ[ND! +MUSP,LB9MLBM^]BL##`S)$5R(^`&B)N2R%6C"%6F`_X+2%6J!V0/B%6OZ\HK_ +MI0+^P@7 +M,(';`SWP@,P0PFWP\@7<@B1^P/\1^O*Z__(O'[%M`XK_\FM$XB,UPA5D?`F0 +M[A#`S`'@S"#":T:"(S7!;`.0B!"";,3R(SOR:A3B`^KB:A6B9F^8M8(F;^(F +M;T"9`?(F;8(8$J(%\>(>$_CO(*H!D(@@`.X1@.X@\/D$,/\!\*H@X*H@J8N2 +M)FZ2*1,,&E=I!((%WXS8DB9NDBD1/?`+F1:9*0P*\BGR!>B2)F]\V)CI +M\/`$\/\1@)D0\)D@\B9OF>J"!>FB)F]\N:CJ@(`$X(@1D*H0@*H@@B9OJ>^2 +M!>KR)F]\>OCOD)`$T)D1H/\0D/\@DB9O^>BB!>N")F]L_XCHH*`$P*H1\(@0 +MH(@@\B9OHB;EB>FB;Q/29N6")F^2)F_R!>28Z7SJ\/`$H)D0HB9OD/\@^>B2 +M)2^")F^92E(E+Y(F;UEX\B;D#`J")F_PKH-PJA'BK?^(Z/(F;U(F;>"($*"( +M(.(F;TQ:B>GH[ECE@J^_@.X04%D$H%414.X@Z>_9ZZG;DB,O#`6L6:'<`ZJB +M=H`9+`U7/0GR*G_B)'[Z[NG[@B,OHLH0&U6'M03&]_\``.(D?](D?NK=TFM' +MHB1_DB1^#`*JF9)LQ1WP``#R(SA6;\FAE`,]\*JB)8;[HD7)G04;H_@#R(SN"(SL@ +M_Z#R+_$@B*""*/.`_T/R9T%&X?X`@B,[((B@@BCQ@F=!!NW^`)(C.Z(C.R"9 +MH)(I\2"JH*(J\Z"90Y)G00;F_@"BH`"B1?(@HB#EF0(62J\BH`8=\+(%WSWP +MLLO^5@O8K0(EE_\&M_X`\@7<#`SAV@/`_Q'Z\NK_PD^`T@7M(F*@>239\,8AWP`&JB@@K\4M)G +MLM(!%M@A\FOI@B7[((B@RHCY"((E^R"(H$J(^0B")?L@B*#JB/D(\FO!@BT8 +M%C@=DDV?#&(=\`!JHI(*_%+29Q;)-H(E^R"(H/)H_](E^R#=H-+=!/)M(Y(E +M^](E^R"9H"#=H&J9DBDB:MW2+237N5?2)?N")?L@W:`@B*!JW=(M)&J(@B@B +ML/%!@-W`]STX\B7[(/^@:O_X#[J_QAX``&JR@@O\4M)GHM(!%E@S\FKI@B7[ +M>M(@B+#R:/N"+1@6&!R239\,8AWPTB7[DB7[(-V@()F@:MW2+2)JF9(I)->Y +M+H(E^Y(E^R"(H""9H&J(@B@B:IF2*22P\4&0B,"'OP^2)?L@F:!JF9@)L+G` +M1@(`LB7[(+N@:KNX"](*^1;M,N(*^A;.,((E^_(E^R#_H&K_\B\B((B@RHCZ +M^_D(^2K")?N2*@(@S*"2;/>")?N2*C0@B*!@B(""*"B7&!'B)?O2T@32+3,@ +M[J#BW@32;B?B*BVL'H(E^Y(E^R"(H(+8!""9H)+9!((H(8)I(_(E^SWP(/^@ +MLF__DB7[H9H#()F@:IF8V:<9`PP"'?"R)?NBT@2H&B"[H`P"LML$J#>2#8H6:37R +M)?O"*\$@_Z#J_\D/TB7[(-V@PFWSPB7[LBHT(,R@:LRR;"B2)?N"*BH@F:!J +MF8DY1MW_``"")?L@B*""V`2(6)Q8@B7[((B@@M@$\F@GDB7[()F@DMD$^2GR +M)?N2*_,@_Z#RWP3R+R?W.0*&V/^2)?N"*\0@F:"2V028*9J(@FOIAM;_`-(E +M^SWP(-V@TMT$V"W2:NGR(W_R+P,6[R&"*O/R*NF`_X"2*RT622'2(W_8/:E! +M%BTATM(*@BTMB#@,"KDQ%O@N#`L,!':`%H(C?X@(&ZJ2+2VZB(@(F#E+NTI( +ME[H"AOC_N#&H0:E!N3$6;P:R(W\+KZD!N#MEX!.I$<(E^[(C?\DAJ`&X.R7< +M$[@1PJ/,#`Y`NX)((0P-\M)J($2@0M0$HF0E2#&B(01V@!V2(W^"+SL;[I@) +M((B@@M@$VIF8"8(H)4O=NKGG.`(&]O_BH]P&`0``30L,"](D+HB"")`6B!O2)?L@W:#R;?^2)?L@F:"2V03R +M:2,&'?\`@B7[((B@@M@$B%B<6-(E^R#=H-+=!/DMDB7[()F@DMD$\FDG@B7[ +M\BKS((B@@M@$@B@GAS\"AI7_TB7[DBK$(-V@TMT$V"W:F9)JZ0:4_P#R)?OB +M)?L@[J!J[N(N(B#_H$K_ZNOI#^DJQCO_DB7[PB7[()F@DMD$DBDA(,R@FIN2 +M;/&")?O")?N2)?L@B*""*/$@S*#"+/D@F:#*B()I\Y(E^_(E^X+2!,(E^R#_ +MH/(O\2#,H,(L\R"9H.J9P/]#^0GY&`8E_P`,#P9Y_Q9_W@O_AGC_#`3&AO\` +M`-(E^\(E^^*CQ"#,L,(L^R#=H.K=NLS)#<)JP8:I_P``@B7[DB7[((BP@BC[ +M()F@NHB":?'R)?O")?N")?L@_["2(W\@S*#"+/&8*?(O_""(H,J9FO_R://R +M)?O2)?N")?L@W:#2+?$@B*""*/,@_Z#J_X#=0]D/TFK!QI'_"_GR:\$&)__" +M)?N"*\$@S*#JS(D,DB7[()F@@FGQ1BG_``"2)?O2*\$@F:#JF=D)@B7[((B@ +MRHC9"/(E^R#_H-)O\08@_P"")?L@B*#R:/_2)?N")?L@W:#2+?$@B*""V`32 +M:".&K/ZH00P$1DO_-F$$H=X#70*JHI(J?W&9`V+2:IB)#!Z"*GY+F0`90`!. +MH1;H8[(J?F8;`H8]`IT.#`/")CO2H-30S(+*Q7K,P@Q*#`T6W!'"H`"RU0$B +MH-3R)CL@_X+Z]?K\\M\+^$_R#Q0;W18?#O(F.R#_@OKU^OSRWPOX3X(K\_@_ +M][@I\B8[@B8[(/^"((B"^O6*A8J,@M@+B$CZ_/+?"X@X^$]`B,")#\8(```` +M\B8[@B8[(/^"((B"^O6*A?K\\M\+BHR"V`N(2/A/B#B)#X(F.R*@U""(@HJ% +MBHR"V`N(2(((%`=H)O(F.X(F.R#_@B"(@OKU^OR*A8J,\M\+^$^"V`N(2/@/ +MB'@P_Y#Y2((F.R*@U""(@HJ%BHR"V`N(2(((%!=H)_(F.X(F.R#_@B"(@OKU +M^OR*A8J,\M\+^$^"V`N(2/@/B(B0_Y#R:`2")CORH-3PB(**A7J(@@A*PLP$ +M(J#4A[T"AKK_(M4$@@+O#`]F*`*&0`*"`N^QWP,62%""*GX6:&;R8A3B8A6R +M)CO"H-3`NX*ZM7J[L@M*W0_,&P9N`@P+S0$,!':`6/(F.^*@U.#_@OKU^OOR +MWPOX3_(/$QO=K)_R)CO@_X+Z]?K[\M\+^$^($O@O]R@4@B8[X(B"&T2*A8J+ +M@M@+B$B)#$O,XB8[\J#4\.Z"ZN5Z[N(.2DN[Y[T"!NC_HF%LDF&`0F%VK0&] +M!`Q\Y0H"DB8[HJ#4H)F"FI5ZF9()2NT!#`L6:0;"(78,">#,H':`6/(F.]*@ +MU-#_@OKU^OGRWPOX3_(/$QN[K)^B)CO0JH*JI:JIHMH+J$J($J@JIZ@4\B8[ +MT/^"&T3Z]?KY\M\+^$_Y#$O,@B8[HJ#4H(B"BH5ZB(((2DN9A[L"!NC_HB%V +M0F%X#&R@1,"]!."JH*)AJ)"KGZHLI`DLE`PB%X,F%_ +MQ[YKHB%S0-`TDM$!DLD@=IT'N`JY"4NJ2YG-"4"$09T*K0QVF$6(";@9N1JX +M*;DJN#FY.KA)N4JX6;E:N&FY:KAYN7JXB;F*N)FYFKBIV,G(N;FJR;JXV=G* +MV.FYVKCYV>J)"KGZHLI`DLE`,F%_0B%_O0'"(7C1X`.B(6SBI%`,#_)B%/)B +M%>KEXF%PHBI^#`_:U=)A=^6&`<(A>`P/(F&!T>$#HB%LXJ14LM$!LLL@X.6` +MXF%UHBI^T-6`TF%T980!XB8[\J#4\.Z"ZN5Z[N(.2Y(A@`P"%CX,LJ``PL%_ +MPLP1=H"TXB8[TB8[,J#4,.Z",-V"ZN7:U>KKXMX+VMO2W0OB+A3I#-(M%-(- +M%0=M*^(F._(F.S#N@C#_@NKE^O7JZ^+>"^(N%/K[\M\+Z'[R+Q3H;OA_0.Z0 +MXF\%\B8[,J#4,/^"^O7Z^_+?"_(O%-*@U/(/%4O,&R(7;RN")CNB)CLPB((P +MJH**A:JEBHN"V`N"*!2JJZ+:"XB(HBH4B&BHBI"(D()J!:(F.]"J@JJE>JJB +M"DM+NZ>R`@;1_W(A;$(A<+T"PJ`#HL%_HLH1)=\![032(7>B)W[-`@P?LL%_ +MLLL1)70!S0+2(73B(76B)WX,'[+!?[++$:5R`2(A@0P>DB(4PB(5EYQGMBED +M%CECD>(#PM4$PBP4#`N0E8#`\!1VGPWR*9'2*6Y+F?#=P-"^DTT.P")!/?!V +MDC*"*9&B*6["*9+2*6_B*9/R*7`B*90R*7&2R1"`BL#`K<#@S\`@T\"`M).@ +MM)/`M)/0M),6&UV")CL6.``,`AWPHB7NLM4!PBO4TBO5P*ICHFO4DB7O+`S0 +MF6.2:]46BD[VREO1G`-0FJ#:F:#((J;8)I>8(J;8)I>H(J;8)I>X(J;8)I?((J +M;8)I?8(J;8)I?I(KU;T)%DE.MLD"1MS_H>(#4)F@JIFAXP.PO,"P\"2JI7:? +M!\(JD,)ID4N9L(-!/?!VF#*"*I"2R2"":8F"*I"":8J"*I"":8N"*I"":8R" +M*I"":8V"*I"":8Z"*I"":8^"*I"":9`,`AWP`-(F._*@U/#=@MK2>MW2#4H, +M#!9M%I+2`0P+QB(`@BI^%LA-LB8[PJ#4P+N"NK5ZN[(+2MT/S!M&KP(,"Q#! +M(`P$=H!)@B8[\J#4\(B"BH6*BX+8"XA(@@@4&]V<6((F._"(@AM$BH6*BX+8 +M"XA(@FP`PLP$\B8[@J#4@/^"^O5Z__(/2DN[]ST"QHX`/?#&Z__2)CORH-3P +MW8+:U7K=T@U*2[O7/`*&-`"")CO2H-30B(**A8J+@M@+B$B""!,;S&8XS?(F +M.]#_@OKU^OORWPOX3_AO^.^';[>")CO0B(**A8J+@M@+B$B(:(((-58(^H(F +M.]"(@HJ%BHN"V`N(2/(I\X@XA[\H@B8[\B8[T(B"T/^"BH7Z]?K[\M\+^$^* +MBX+8"_@_B$A`_\#Y"(8(``"")COR)CO0B(+0_X**A?KUBHN"V`OZ^_+?"_A/ +MB$CX/_D(\B8[TB8[@J#4@/^"@-V"^O7Z^]K5VMORWPOX3]+="]A-^&_8#=E/ +M!L7_#`D,`T9?_@``@@+X%MA!?0I-#Z(F.YT$0F%Z%BK0T@;IXM4*S!W&$0+R +M+BWR+W(,"()A>Q9?!T)A?O'B`PP#4-2@^MV2)W\ZF9(I=J*@U*"9@IJ5L(F` +M@@B`DMD(=I@*HBFTP@H3)CP:2YF"+BWR(7M+,X(H8SL)M;H(IM!M$2]V""!&"3#1&[_^B+BVB +M*G,,`Q:Z!PP-\>(#HJ#44,F@^LS"87F2)W_:F9(I>*"9@IJ5NHF""("2V0AV +MF`JB*;3""A,F/!1+F?(N+4O=\B]SHJ#4&S/W,\Q�#(:H(L%18H_H(F._@J +M4(B@@BCWAY_4\B%Y@B%ZPF^1&XB"87JB*;1+__)A>:(*$:),-,;M_P`,'I(A +M>J+5`4)JU))JU<;V_CT.#`E&P?VB86R288"M`;T$#"PR87]EF`'-!`P/T>`# +MHB%LXJ10#`NR8A3JY>)A<+T!HBI^VM7287=E+`'R)CM"H-1`_X*2(8#Z]7K_ +M\@]+LB%_#`06/PP,##+!?S+#$7:`M-(F.X(F.Z*@U*#=@J"(@MK5BH7:W-+= +M"XJ,@M@+TBT4V0."*!2""!4':"S2)COB)CN@W8*@[H+:U>KEVMS2W0O2+13J +M[.+>"]A]XBX4V&WB+@>PW9#2;@7B)CNBH-2@[H+JY>KLXMX+XBX4X@X52S,; +M1!=N*O(F.X(F.Z#_@J"(@OKUBH7Z_/+?"_(O%(J,@M@+^(^"*!3X;XB(D/^0 +M^5B")CNBH-2@B(**A7J(@@A+2\R'M`,&T?\`4;`0P>#`_"U0'R;-6&HOXM#\+5`?)LU/)L +MU1WP``"VR@+&V_[1X@-0FJ"@K,#:F:#0)':=!^(G@>)I;DN9H(-!/?!VF#*" +M)X&2R2"":6:")X&":6>")X&":6B")X&":6F")X&":6J")X&":6N")X&":6R" +M)X&":6V2*]5&Q?ZVR0(&H_ZAX@-0F:"JF;"LP*#P)':?![(G@;)ID4N9H(-! +M/?!VF#*")X&2R2"":8F")X&":8J")X&":8N")X&":8R")X&":8V")X&":8Z" +M)X&":8^")X&":9`,`AWP`-'C`]K5PBV0XBV1XFV0PFV11H;^#`2B86R288"& +MJ?T`@@+XPM4!%JA??0I-#Y(F.Q:)[Z(&Z>+5"A:*>M(N+=(M<@P(@F%Q%JT$ +M#`.!X@/"86U0U*"`W8"2)W\ZF9(I=J*@U*"9@IJ5L*F`H@J`DMD(=IH*HBFT +MP@H3)CPB2YF"+BWR(7%+,X(HIF2"4K-#Q:I>-'B`PP)0J``T-6`=H`P\B8[,J#4,/^"^O7Z^?+?"_(O +M!/(/$\+,`28_%X(F._*@U/"(@HJ%>HB""$I+F8>\?@;R_X(F.S"(@HJ%BHF" +MV`N(2(AHB.B':-'R)CLP_X+Z]?KY\M\+^$_X;_(/-5:O^X(F._(F.S#_@OKU +M^OGRWPOX3_AO4(B@@BCW^`_W*)OR)CLP_X+Z]?KY\M\+^$_X;_)M;H(F.S"( +M@HJ%BHF"V`N(2!M$2]V""!&"3S3&VO^B86P]!*'@`[T$#%RJI653`<(F.]*@ +MU-#,@LK%>LS"#$H,"Q;L"^'B`PP)4-2@X-V`=H`P\B8[PJ#4P/^"^O7Z^?+? +M"_(O!/(/$[++`28_%X(F.Z*@U*"(@HJ%>HB""$I+F8>[?P;R_^(F.\#N@NKE +MZNGBW@OH3NANZ.Z';M'R)CO`_X+Z]?KY\M\+^$_X;_(/-5:O^X(F.Z(F.\"J +M@JJEJJFBV@NH2JAJ4(B@@BCWJ`JGJ)OR)CO`_X+Z]?KY\M\+^$_X;_)M;N(F +M.\#N@NKEZNGBW@OH3AM$2]WB#A'B3S3&VO\`0F%]PJ`$T>`#,+3`4*.@HF%N +MLF%\T*J`940!PB%]TB%\%H,(,+,@D>(#,/`T4*V@FJJ:E7:O">(I;N)JD4N9 +M2ZJPA"%VJ&6"*6ZR*6^R:I*R*7"R:I.R*7&R:I2R*7*R:I6R*7.R:I:R*72R +M:I>R*76R:IBR*7:R:IFR*7>R:IJR*7BR:INR*7FR:IRR*7JR:IVR*7NR:IZR +M*7RR:I^R*7VR:J"":I&BRD"2R4#',P*&(@"AG`.2(6ZJF:'B`[T-T/`TJJ5V +MGPG2*7_2:I%+F4NJL(1!=IAE@BE_LBF`LFJ2LBF!LFJ3LBF"LFJ4LBF#LFJ5 +MLBF$LFJ6LBF%LFJ7LBF&LFJ8LBF'LFJ9LBF(LFJ:LBF)LFJ;LBF*LFJLBF-LFJ?LBF.LFJ@@FJ1HLI`DLE`DM4!PFG5PFG4\B8[@J#4 +M@/^"#`[Z]7K_\@]+DF%MG0P6[P[QX@,,"5#`<(A;;'?`PP>0FS50FS4 +MANC]`-(N+=(M=`P/\F%R%ET'0F%^\>(##`-0U*#ZW9(G?SJ9DBEZHJ#4H)F" +MFI6PB8"""("2V0AVF`JB*;3""A,F/!I+F8(N+?(A9(G?]J9DBE\H)F"FI6ZB8(( +M@)+9"':8"J(IM,(*$R8\%$N9\BXM2]WR+W6BH-0;,_'G]3R(7F"(7K";Y$;B()A>J(IM$O_\F%YH@H1HDPTQNW_ +M``P$HF%LDF&`AO+]`)(F.]*@U-"9@IJ5>IF2"4H]#Q9Y(PP)T>(##`3"86W: +MU08%`/(F.X*@U(#_@OKU>O_R#TI+F?>S=L(F._*@U/#,@LK%RLG"W`O(3,(, +M$QLS9CS0@B8[\(B"BH6*B8+8"XA(B&B(Z(=HNL(F._#,@LK%RLG"W`O(3,AL +MP@PU5CSZPB8[\,R"RL7*R<+<"\A,R&S";6Z")COPB(**A8J)@M@+B$@;1$O= +M@@@1@DPTQMS_HF%LH>`#O00,#*"E@.7_`-(A;4)MU+(F.\*@U,"[@KJU>KNR +M"TN=!`P.%NL+#`GQX@.RH-10U*#ZW88&`((F.Z*@U*"(@HJ%>HB""$M+F;*@ +MU(<^`L8B`,(F.[#,@LK%RLG"W`O"+!3"#!,;[F8\S/(F.[#_@OKU^OGRWPOR +M+Q3X;_(/-19/^_(F.\(F.[#_@K#,@OKURL7Z^?+?"\K)PMP+PBP4\B\4R&SX +M;\ALR5^B)CNPJH*JI:JIHMH+HBH4J&JB;6Z")CNPB(**A8J)@M@+@B@4&T1+ +MW8(($8)*-(;6_P``DB%M/?"2*=1R(6RQX`,,'%"IH+"J@)"TP.7P`+'?`\(A +M;0P>#`]";-0&$OX`TBXMTBUT#`_R86\6'8H,`_'B`\)A;5#4H/K=DB=_.IF2 +M*7JBH-2@F8*:E;")@(((@)+9"':8"J(IM,(*$R8\&DN9@BXM\B%O2S."*'0; +M__)A;X<_Q<(A;085_LAJ\BP5%L_]\B8[B"I0_Z#R+_?WF,[";6Z"*;0;1$O= +M@@@1@DPT1N__#`2B86Q&2_X,!,)A;:)A;(:6_S9A`#*D$#IB:1%B!M]1D0,< +MA"8F4UJ"@@A^C+BM`@P+)44`C"H,8AWPF!&2"=FBT@&B80`6"3^R(NZB*M2W +MNB"QG`,@FJ"PF8!V@`_2*7]"333"(NX;JDN9Q[H$1OK_``#X`>(OKN)OU`N& +M%F@KTM(!P9X#RL*2+'_AX@,L!!;I#/(MU:(MKK(MKX(MU/"[8X"J8Z)MU+)M +MU1;*+/;*5J#TP"":H)+96O"P).JB=IL'LBINLFFD2YGP@T$]\':8,H(J;I+) +M(()IG((J;H)IG8(J;H)IGH(J;H)IGX(J;H)IH((J;H)IH8(J;H)IHH(J;H)I +MH[(MU1;[+/;+4^JBL/3`()N@DME:\(`D=I@'LBJ1LFG'2YGP@T$]\':8,H(J +MD9+)(()IOX(JD8)IP((JD8)IP8(JD8)IPH(JD8)IPX(JD8)IQ((JD8)IQ8(J +MD8)IQI(MU!;I!_%M`Z+26MD!=H!5XBJD8BJEBZK2#C6X_N(.-)#=$;"[$289 +M/Y+)_G(&-`P$@J#_@%?`4'2#@([`2/:`=Q%B!C4P1!%`=R`09A%P9B`,!X#G +M@[!>(%!=(&!5(%)O%4O_G%G&Z/\,":*@_Z"NP*#I@[".(("-(()O%=@!X>(# +M+`22+=46J0?Q;0.BTEIV@%7B*L=B*LB+JM(.-;C^X@XTD-T1L+L1)AD_DLG^ +M<@8T#`2"H/^`5\!0=(.`CL!(]H!W$6(&-3!$$4!W(!!F$7!F(`P'@.>#L%X@ +M4%T@8%4@4F\E2_^<6<;H_PP)HJ#_H*[`H.F#L(X@@(T@@F\EX>(#+`21;0.B +MT@),/=G9#`W2:0ZR*I2\:^#R@':`+H(O;E(L?[@8(%6@.E58A5"[P+GYLBQ_ +MB"@@NZ`ZN[B+L(C`B?E2*I0;W4O_5[T"AO+_2>F"*I4,#;QXZN)V@"[R+I&R +M+'^('R"[H#J[N(NPB,")^8(L?_@O((B@.HB(B(#_P/GYLBJ5&]U+[K>]!(;R +M_P``TBQ_*MTZW=(-VN*@_^<=:*@1HBH0O/H+NJ"[$;)I..(L?]*@_RKN#`(Z +M[M).VAWPXBQ_TJ#_*NX,`CKNTD[:'?!:\O(/?Q8_$*T"#!LE%``6F@\,8AWP +M`*@1HBH1%OK\"[J@NQ&R:3CB+'_2H/\J[@P".N[23MH=\`P"P88#PFDX'?`` +M`+;*`H9A_Z#TP"":H)+96O"`)%JB=I@'LBHCLFFD2YGP@T$]\':8,H(J(Y+) +M(()IG((J(X)IG8(J(X)IGH(J(X)IGX(J(X)IH((J(X)IH8(J(X)IHH(J(X)I +MH[(MU5;[TK;+`@9@_UJBL/3`()N@DME:\(`D=I@'LBHCLFG'2YGP@T$]\':8 +M,H(J(Y+)(()IOX(J(X)IP((J(X)IP8(J(X)IPH(J(X)IPX(J(X)IQ((J(X)I +MQ8(J(X)IQD9*_P``PB+NPFK4Q@W_Z!'B#MG2T@&LSO(B[Z(MU?>Z&R":H)+9 +M6G:`#\(IQT),-+(B[QNJ2YFWN@)&^O_B+:_B;=7&`?_R(N_R;=6&__X``#;A +M`/T"8:\#XJ)8ZM)J8A93.J'A`Y'D`X(M?[(F0C*F(%*G+%I2.C*R)D(+B)J2 +MJJ*I,9EAB8'")KD6+#J"+6Y"+9WPB!&)4?!$$1M$22&1Y0,,!(@A*&&)<4G! +M(@(`FI^R"7VBPOT6NC-9\3G109T#@9D##`M*3XJ/B0%)$8B!2#&YX1O(HM3^ +MJ9')L4"(H(E!#`Q"Q/Q)H<)A$,8Y``"B)KDB*2`P(H(QF`,J+SHB0@(*,B:\ +M=I0@@B(4<@@42R*R*`A""S6L-#WPO0.&"```9C?T +MN&A""S56Q/Y82\>5YX8#``!(2\>4TT8!``!82\>5U4CA4B$0J+&"(1`;55)A +M$*>X$BB!.$&`(L`;(G:2!B@#,L/\*2.HH4M$B)%)X4BQLFB`2ZJIH4N(B9%7 +M-"BX,:B!*.&PA:!0JL`KJKHB(M+^=IH2:`D;7_\(A$%BAJ.&"9(!+1$F12ZI+51O, +MPF$06:&IX<>[`@;/_Z@QN($HX:",H,"[P"N[JB(BTOYVFQ%R(H!+(HQW0B<4 +MK!1Y"$N(/?!&Q/\``((B?XAHHB@5%DKYLBUKJ`BWFHR&X_\``$(I(,@'\$2@ +MZD1")&%''-!&\O\`6"')<3*@U,G^*=T('"\(FO+@+=I0IHBLC@=H"RAZ0@(UC#184K<5,A=H"RB*@@(UC#BH4K<:+#WPXJ)8?0S&"0`` +M`&8X\"AJ0@(U%H3^6%*WE>-]`N*B6$8#`'T"XJ)81@$``'T"XJ)82.%2(1"H +ML8(A$!M54F$0I[@2*($X08`BP!LB=I(&*`,RP_PI(ZBA2T2(D4GA2+%R:(!+ +MJJFA2XB)D5>T`D:`_T@QJ($HX4"%H%"JP"NJ2B(BTOYVFB%R(H!+(L<7%T(' +M-8S44B<%MY4(0BD@HB<41QH#>0A+B#WPAG'_"\)&M_\,`AWP#&*2WP4,&()) +M"QWP``#!X`.QY@.B+7Z")D(RI2!2IZQ:4CHR0B9""ZJZLLK"R3&Y8:F!AA7_ +MHBUNJ5&2+9V9(488_P```#9A`%DQ@><#4>@#G0)P6(,F$EEF(E2F%%$,`CDA +M20$P-*`,!)@!ER0"1D,`>"%P=*"&.``;(DMW-Q""Q,':/"B*P?@!0`6 +M>OX;(J@'N`;(,:AZ&YO`NZ"B:P"29@#8`=@!YR3`'?"F%/H,`ID1.2%) +M`3`TH`P$^`'WHC5X(7!RH(8!`!LB2WAN;P+N@J0N29@#8`=>D,G@A<'2@A@$`&T1+=S<7([@'@@L3 +M%VCPJ(O@!0`6BOX;1*@'N`;(,:B*&YO`NZ"I"Y)F`-@!UR*,UR2$^!'RS_Y6 +MK_;7H@)&Q__7I`+&Q__&UO\`&T1+=S<7(K@'H@L3%VKPJ(O@!0`6BOX;1,@' +MV`;H,D#@@;JJJ>I00N(%F@E#$@,B9)&[))&[8)&[J(JT[JWN5$6 +MRB@JQ\DQT@;+^%$,#M+-_Q;M(^)A`J(O0Y(&T((&SZ(J$7"($9"J$:"9()"( +M()%M`\A1B:GR+T/AT`.)`?(O$0P)@B$$%E\`L@;+)AL4PBQ#PBP3P,4$%@P3 +MT@;+TLW^%GT20>P#4>T#^%&B!LO2**6"**;R+T,+JHD1\B\1@J`!H)B#\L_^ +M%@\MZI?Q;0-,&B'J`ZG?.>\QZP-VG4V"F1ZBF1^RF2#"F=[2F=_BF>!KF8"` +MA'"J$>"[`<#`A'#=$>#N`3"($%"J$$"[$##,$%#=$$#N$("*(,"M(""($""J +M$("+(*"N((G_J?\AZ@,QZP-![`-1[0.1T@/Q;0-,"H@1J>^0EX!VF$V"F1ZB +MF1^RF2#"F=[2F=_BF>!KF8"`A'"J$>"[`<#`A'#=$>#N`3"($%"J$$"[$##, +M$%#=$$#N$("*(,"M(""($""J$("+(*"N((G_J?_(0>A1\BSBPBSAXBY#P/\1 +MT@;0L@;/\,P1XBX1\,P@<+L1D.X1X-T@T+L@P+L@P6T#N:R(,>A1LBB6HBY$ +MDJ$D<+N@J!J:N[(KP_%M`["JP*)O$((HEN(N1'"(H.@NFHB"*,.`[L#B;Q'2 +M!LMF'53((:@!N.SR##78_+#I!-#_$?"J(+"P!.#N$>#=(,"[$="[(-%M`^@Q +ML*H@HFT4DBZ6\J0DB!QPF:#ZF9@YD(C`@FT2XBZ6R"QP[J#Z[N@^X,S`PFT3 +MZ$%\_=)NP,(&Y0P(^$&,3()/L@;(^%$,#7"[H/(O +MN2J[PA9=\L_^\-Z#T,R"LBMIP,J"0BEZP,%!RKNZ1$)H3I(&[Y)H1L`@`$8K +M_P```!:YTJA!#%GX$2P"\-T1(-UC\(\1DFKADFKB(/AC^1$6;03JAP=M$R)8 +M(")8'R)8'C)8X#)8WS)8WFN(T+%!/?!VFR4B6"`B6!\B6!XR6.`R6-\R6-XB +M6",B6"(B6"$R6.,R6.(R6.'+B+@1%@O,@=(#G0N*AP=K$R)8(")8'R)8'C)8 +MX#)8WS)8WFN(D+%!/?!VFR4B6"`B6!\B6!XR6.`R6-\R6-XB6",B6"(B6"$R +M6.,R6.(R6.'+B$8<_P``HA98L@;L99D1HD;OQJ'_`**@P,:W_P``LBEZHBQI +MNJJB:$[&PO\``%9(Y(A1@BB\!H__`#9!`*8C0@P*"]-]`@P8#`F@P\`+O':K +M#Q;$!B84529$/B94)QN(2W<;JI<;$B!LH"")H%@(8M;^0A29G]]`@P8 +M#`G7FL8=\`#H%R#YH/@/Z`[X#_>NR9T(!O'_`&@7(%F@6`5H!E@%9Z6UG0@& +M[/\`Z!<@::!H!NA>:%;GIJ&="`;G_P#H%R#YH/@/Z$[X3_>NC9T(!N+_`#9! +M`*8C0@P*"]-]`@P8#`F@P\`+O':K#R8D;"8T529D/B9T)QN(2W<;JI<;$B!L +MH"")H%@(8M;^0A29G]]`@P8#`G7FL8=\`#H%R#YH/@/Z"[X+_>NR9T( +M!O'_`&@7(%F@6`5H)E@E9Z6UG0@&[/\`Z!<@::!H!N@>:!;GIJ&="`;G_P#H +M%R#YH/@/Z`[X#_>NC9T(!N+_`#:!``P,89X#\J/P4J),:F)")G\R)G_B)G\@ +M1+`@,[!:1$(D:"#NL%HS,B-I^N[)#M(F?R#=L%K=PFUHHB9_(*J@6JJB*HI: +M4K(E<1NJ9781LJ1J?0J2):!)(3D1D(K`%F@6ND*AW@,QM`.9`:JBJ3$,">(F +M?QP,T@2"*NZZ[M).@':L$UR/\/F"^O(Z__(O?Z=O!SN9D)!TDJ#_DD2(H@2( +MPJ#_P*K`%MH4H@2(D@2(LJ0`7(B`F8*`JH*:DCJ9DBE_JJ(ZJK"9())J?[(4 +M.\(4/-(4/>(4/O($B(#_@H'O`PP*^O**_Z4:^ZE!>4IY>L*A`/*B`.CJ#!V" +MH/^"2C322C;P[B#`OB"YZFS\P+L0N>JH,7)EH*(J?ZB:C,H@HB`E6/V,2@QB +M'?```/(F?ZA!PJ),(/^@RO_R+U[Y&N(F?R#NH,KNXBY@Z2K2)G\@W:#*W=(M +M9-DZLB9_DJ#_(+N@RKNR*V2Y"I)*-+T"I3[Y@B9_&Z>2HDP@B*":B')HBK(E +M<>5J$9@!LJ1J?0J0FL!6R>V2)G^BI&J"!((JF:J9@DF`\B9_Z"'2HDP@_[#: +M_^)O:,(F?[@1J`$@S+`,`MK,LFQIHF6@'?#R)G^ZXN(.@BK_NO_B3X#2)G_" +MHDP@W;#*W4)M:*(F?R"JL`P"RJHR:FF29:`=\`QB'?`V00"Q\`.PLH"B*W^2 +MT@6"H`*BR@&B:W^"20QE```=\#9!`**@`66Q]66I]X'Q`[%M`Y%L`\%M`PP* +MHFF`HFG`J0RB:T"":8(=\```-D$`?0(H`YPD?/8+15HB8$0P"R)`(A!Z0DD# +M'?!Z@HD#'?``-D$`#`5"H/\QM@-A\@.&!@`,J)T%&U67N`*&*```-J:@$*:@ +MH'2BRH`6^@@`,Z:P$*8,#+#0=+"P=$>;%G:`$``SIN`0IAO,X-!TX.!T1YX" +M!OK_`#.FL!"F#`JPL'1'FQ5V@`T`,Z:P$*8;JK"P=$>;!,;Z_P``@.H1H.[` +MZKN`K!$_W:`#P`S +MIL`0I@N[YAL"AEK_/?!&^O_F&P+&5_]V@`\`,Z;0$*8+N^8;`H93_SWP1OK_ +M`#9!`%T#,;8#`#.F0!"F#`=BI'!J8G)F&`PH@JR"#_Q'YJ>(CK=BI(.Z@XBYIX_T4 +MV:D&V_\`\?L#\F+H!M?_@F+HAM7_`*()R]'^`Q8Z!+()RR8;-,']`\)BZ-)C +MJ4;H_P#A_P/B8NA&V?_Q``3R8N@&U_\``($!!()BZ`;@_Z$"!*)BZ,;=_P`` +ML0,$LF+HQO'_P00$PF+HAN__```VH0`RT@&"(],`.*8,#4*D&$I"D@3=TF,4 +MDD.+TD.,V4.P$*:"(\FPH72PF70;B!880Z)B[9)B[*(CR;"1Y0P<%DI#F?.R +M(\D+N[)CR<)#DM)C$F%L`U%M`W%)`\)#BN(C$K$%!#PZ[-Z1!@2"(_*:B``X +MIO`0II%_`_)C(':`$\(F@PN9%EP8%DD8T@3TTLW^%HT81OG_`/(B4N*A+/9/ +M`L88`8(C$K9H`L9A`((C$@P?#`Z"R/N`[X/B0Y2"H`B"8Q(`/:;P$*;R8Q0` +M/::V3P+"1//@$*;B8Q4`/::V3@+"1//@$*:V3@7"1//BH`#B8Q8`/::V3@+" +M1//P$*:"(_+B(Q/2(Q3C^`C3^!#B(Q72(Q;R8Q?C^!33^!CS^!P`.*:V3P+" +M1/,I@5F1::'`$*;"8R#R(R#B(R#2(R#"(R#P\!3R8Q@B(R#@XA3B8QE2(R#0 +MU!328QIB(R#`QA3"8QN"(R`@*!0B8QPI05!:%%E14F,=8&P4*(%I86)C'H". +M%(EQ@F,?@@3F6)%HH19X!8($Z?DQ%HA@#!_9(R(ZL\.LJ[EEM9MRH"!E`` +M+'O&4```S+D,+=)$]*62_SPZL04$#+X`/J;2(\?"(ZO:S):,0L>J1RQ]QA$` +M\B)2ML\"1O0`@B,2@LCA%EACHB,2HLKZ5LH*#,W28Q*R!.866PR"H0(`.*;P +M$*;R0XSB`XP6/@O"8Q0,Z9)C$@8J`+K)F5L(D0+CSXB.KRKOC^P0L?.$'!-/["L/[ +M$+)F5<(CK:(CK)(#EX@SH_P(D_P1>OSJS(/_%/)FR(CX"#_H.)O +M9QWP````P04$RKNR"P#2(\C"(ZO:S)8,1,>J!2Q\!@(``-$%!-K,P@P`D3@# +MXB,@@@3=\@.,FNZ#_A3S_AGB9E;2)$"8\Z(CJ]J9H_D$H0@$L_D*P_D0DF95 +MDB.M@B.L\@.7Z#.#^0CS^1%ZV:J9X_T4K0+29LD,3IG%G0*((CX"#_H.)O9QWP`,A)N#G`P-2PL.3#^P^YQ8AI^%F` +M@-3P\.2#_P_YQ>B)V'G@X-30T.3C_0_9Q<;J_^A)V#G@X-30T.3C_0_9Q4;F +M_XAI^%F`@-3P\.2#_P_YQ<;A_P`]IJ)CK9)CK,`0IL)CR4;P_@```#VF?/B9 +M\])#DH)CR?`0IO)C$^(C$QONXF,2!N_^NIR!N`/"(R#R!-WB`XR*S//\%./\ +M&<)F5K(D0(CSHB.KD@D`NHBC^`2A!P33^`J3^!""9E6"(ZWR(ZSB`Y?(,_/X +M"./X$7JXJHC#^Q2R9LF)Q<(CK?(CK.(#E_/\"./\$L)E3+(CK:(CX""[H*)K +M9QWPLB0LPB)3X**`HF$`P_L(`#NFD!"FDFH5K0)E@P8,&KT"Y:@&J`&X%,(J +MH,J[ELLI/#VWK08L?$8"````P04$RLO"#`#2*J"X)-J[ECLH/#ZWK@0L><8! +M`)$%!)J;D@D`@BH5Z'K2!-VR"F#C^!73^!2S^!F"9E;R*OO82N(JH/K=X_T$ +MX0@$P_T*D_T0TF95\BJBLBJAD@IK@B)#L_\(D_\1ZN]Z_X/_%/)FR>G%TB)' +MV<6R(DNYQ:@2F"*R(E*@H.20D-0+NQ9;*/(B4O+/_A9/()/Z#ZG%B*+XDH"` +MU/#PY(/_#_G%PB.MXB.LT@.7X_P(T_P2PF5,LB.M@B/@(+N@@FMG'?``PD3S +MPF)2TF)3LB0LPB)3X**`HF$`P_L(`#NFTDIGD!"FDFH5K0(E<@8,&KT"I9<& +MJ`&X%,(JH,J[EIL(#C(K,\_P4 +MX_P9PF96LB1`B/.B(ZL,";J(H_@$H0<$T_@*D_@0@F95@B.M\B.LX@.7R#/S +M^`CC^!%ZN*J(P_L4LF;)B<7"(ZWR(ZSB`Y?S_`CC_!+"94RR(ZVB(^`@NZ"B +M:V<=\`#!!03*R\(,`-(JH+@DVKN6VQ,\/K>N!"QYQ@$`D04$FIN2"0""*A7H +M>M($W;(*8./X%=/X%+/X&8)F5O(J^]A*XBJ@^MWC_03A"`3#_0J3_1#29E7R +M*J*R*J&2"FN"(D.S_PB3_Q'J[WK_@_\4\F;)Z<72(D?9Q;(B2[G%J!*8(K(B +M4J"@Y)"0U`N[%AL5\B)2\L_^%M\+D_H/J<6(HOB2@(#4\/#D@_\/^<7"(ZWB +M(ZS2`Y?C_`C3_!+"94RR(ZV"(^`@NZ"":V<=\``,"\;L_@P,AO+^Z&$,#(AQ +M#!\,#8#?@^#/@]#,$-A1#`F(0="?@](#B@P.@.^#X-T0T)D0P)D0DD.*QH3^ +M#`Q&7/\,"09B_P"3^@^IQ;(B$H(B$;"PU("`Y+/X#XG%TB.M\B.LX@.7\_T( +MX_T2TF5,PB.MLB/@(,R@LFQG'?`,#`:N_P`,"8:S_Y/Z#ZG%PB(2LB(1P,#4 +ML+#DP_L/N<7B(ZV"(ZSR`Y>#_@CS_A+B94S2(ZW"(^`@W:#";6<=\`"3^@^I +MQ?(CK;(CK((#E[/_"(/_$O)E3.(CK=(CX"#NH-)N9QWP(*(@PJ`/PF,2Y6T" +M\B.MDB.L@@.7D_\(@_\2\F5,XB.MTB/@(.Z@TFYGD`````"3^@^IQ=(CK?(C +MK.(#E_/]"./]$M)E3,(CK;(CX"#,H+)L9QWP````-D$`4J$86D*B!'\RI!PZ +M,ANJHD1_D@/T@@1_EY@%@J``@D1_LB36LLL!LF36HB36DA-@H)G`%CD(XB,8 +MXLX!XF,8TB,8PA-@UQQXH7\#L6P#=H`2@@1_\BM-"ZJ'7PJ,FI(#\"8I#(;Y +M_\QJ#"JB0_"E'_\,?=)DS9(DS<(DV0P;#`K`JX.C^0^29,WR),V"!'^#_Q'R +M9,WB)*?2),T@[J!:[N(N(^/]%-)DS<`0IK(#[\P[X@/PG!X,,AWP\!"F#"(= +M\"`0I@PR'?``#%D`.::`$*:<&*(#TR8J"+@CIAL##`(=\`PR'?`,`AWP```` +M-H$`,M(!@B/3`#BF#`Y"I(1*0I($<>)C%))#B^)#C.E#L!"F@B/)L*%TL)ET +M&X@6F!^B8NV28NRB(\FPD>4,'Q;*'YGSLB/)"[NR8\GR0Y+B8Q/B8Q(,R]($ +M>M)#BL(C$F%M`QQEQ[5>DB,2+/B7.%:B(Q(:`L8L`O(C$H$)!/+/Z/#R +M08#_H/@/^4/B(Q(,W>+.Z.#@%.)#F=)C$JT"IJ!"Q\Q@$`P04$ +MRLO"#`"R):#:NY;+);>J!"QYQ@$`D04$FIN2"0#R)16X=:($<8(%8+/_%:/_ +M%(/_&?)G5N(E^[A%TB6@ZKO3^P3#^PJ3^Q"R9U7R):*B):&2!6OA"`2C_PB3 +M_Q&120."(D/J[YK_@_\4\F?)Z<;2(D?9QK(B2[G&HB)2DB)8"ZH6VA["(E+" +MS/X63%X6V6\+V1;-=&8I`@;A`9(B6X`O)$A[`0IK)C%@`^I@S)M[D"\D2'@!"F@F,7 +MDB/RLB,3XB,54B,4L_D(LB,64_D0X_D4L_D8@_D<`#FF#,6'M0+R1($%!?$(!5$%)#BJT"I4X%#!J] +M`N4F!K(CQZ(CJ[JJEAIM/#RG+`(&+@`L>\8N``P,AF;_#`E&:_\``!;)>F89 +M`H;U`=+)_E;=XN@BV!+@X-30T.3C_0_9QL(B(K(B(<#`U+"PY,/[#[G&@B.M +MHB.LD@.7H_@(D_@2@F9,\B.MXB/@(/^@XF]G'?``\B/RDB,3@@.2D_\(@_\/ +M`#^FD!"FDF,@XF,2@@1]@D.*\B/)EN]_D7\#"YGB)X,6+EP6*5SR!(@+F68O +M[@RX`#BFXB/'LB.KZKN6:V*W+`)&XP`L?D;C`+$%!+JZL@L`PB/(HB.KRJJ6 +M*F`\/:>M!"Q\Q@$`P04$RLK"#`"=`M$X`_(C((($<5(#C-K_@_\44_\9\F=6 +MXB0EB//2(ZNM`NJ(T_@$L_@*P_@0@F=5@B.M4B.LX@.7#$]3^`CC^!%1"`3A +M20/8,UI8ZHC3^!2"9\E9QNASZ<;8L]G&1@(```"BRB!+F19/T+(I7`O_%OLE +M"^L6[AN"R_X6R!%F.^&R*5@6.PT+RQ9L"&8KT]@JR!K0T-3`P.33_`_)QK(J +M(H(J(;"PU("`Y+/X#XG&Z$K8.N#@U-#0Y./]#]G&PBHDLBHCP,#4L+#DP_L/ +MN<:(:NA:@(#4X.#D@_X/Z<;2*B;"*B70T-3`P.33_`_)QKB*B'JPL-2`@.2S +M^`^)QN(J*-(J)^#@U-#0Y./]#]G&!M3_`+(J(H(J(;"PU("`Y+/X#XG&XBHD +MTBHCX.#4T-#DX_T/V<;"*B:R*B7`P-2PL.3#^P^YQH(J*.(J)X"`U.#@Y(/^ +M#^G&!L+_`.@JV!K@X-30T.3C_0_9QLA*N#K`P-2PL.3#^P^YQHAJZ%J`@-3@ +MX.2#_@_IQMB*R'K0T-3`P.33_`_)Q@:R_P"R*5@6*P#@U-#0Y./]#]G&1G;_``#B*B+2 +M*B'@X-30T.3C_0_9QL(J)K(J)<#`U+"PY,/[#[G&AFS_V"K(&M#0U,#`Y-/\ +M#\G&N&J(6K"PU("`Y+/X#XG&1F3_``"R*5B\ZR8;*.++_E8>V-@JR!K0T-3` +MP.33_`_)QK(J(H(J(;"PU("`Y+/X#XG&AE?_@BHBXBHA@(#4X.#D@_X/Z<:& +M4O_(*K@:P,#4L+#DP_L/N<8&3O\`##[B8E)&5?X660L+^18_.8+)_E:8"\@B +MN!+`P-2PL.3#^P^YQJ(B(I(B(:"@U)"0Y*/Y#YG&AB4`VNOB#@#R(\BR(ZOZ +MNY9[*+./_"H/_$($*!/)G5?(CK=(CK,(#E[@ST_\(P_\1JI^*_[/Y%))GR?G& +MLB.MTB.LP@.7T_L(P_L2LF9,DB.M@B/@()F@@FEG'?```/@BZ!+P\-3@X.3S +M_@_IQI(B6A8I-`N)%@@WHLG^5CJ6LB(2HB(1L+#4H*#DL_H/J<:2(C*"(C&0 +MD-2`@.23^`^)QM(CK?(CK.(#E_/]"./]$M)F3,(CK;(CX"#,H+)L9QWP`-@B +MR!+0T-3`P.33_`_)QH8^_NBBV)+@X-30T.3C_0_9QL(B*K(B*<#`U+"PY,/[ +M#[G&@B.MHB.LD@.7H_@(D_@2@F9,\B.MXB/@(/^@XF]G'?```((B(O(B(8"` +MU/#PY(/_#_G&!BG^LF,2D@1ZS!D&V?W"H0(`/*:P$*:R0XRB`XS,&@;4_?)C +M%`SMTF,21M']F"*($I"0U("`Y)/X#XG&\B(BXB(A\/#4X.#D\_X/Z<;&%?Z" +M(R#R`Y+"!'&2`XSS^!K#^!23^!F"9U;R)"7(\X(CJ_K,VOOR#P"#_`3C_`KS +M_!#"9U7R(ZV2(ZR"`Y?(,Y/_"(/_$8$*!*J?P_D4DF?)BO_YQH(CK<(CK)(# +ME\/X")/X$H)F3/(CK<(CX"#_H,)O9QWP`%9)I+)$B&5X_J%)`SP\T04$QHS^ +MZ*+8DN#@U-#0Y./]#]G&HB.MPB.LL@.7P_H(L_H2HF9,DB.M@B/@()F@@FEG +M'?#2(BK"(BG0T-3`P.33_`_)QI(CK;(CK*(#E[/Y"*/Y$I)F3((CK?(CX""( +MH/)H9QWP#`M&?/X,#$:"_@`,#@9;_X(C(,(#DK($<9(#C,/X&K/X%)/X&8)G +M5O(D)=CS@B.K^MV#_00,#^/]"O/]$/$*!-)G5=(CK<(CK+(#EY@SP_T(L_T1 +MJHWZW9/X%()GR=G&DB.MPB.LL@.7P_D(L_D2DF9,@B.M\B/@((B@\FAG'?`, +M!;A!#`@,'@P)\)Z#L(Z#N#&0B!"8(;!>@PP+D+Z#D@.*L)D0D%40@%404D.* +M1AG^(*(@PJ`/PF)2XF)$Y:K!"Q^!@$`RNKB#@"B(ZL, +M"=JJEKH'IZL$+'D&`0#*FI()`+(C(/($==(C$L(#C//[%/%L`]/[%(,\/Z"+/Z$<$+ +M!+%M`]K:@_T4TF_)RJJIRQWP`*DSAM#_K0(EG@5&U_\````,#D;>_T;C_S:! +M``P,@B)",M(!#'Z"R/X6"$62`Y46^4.R`XVR0XNB(D:=#`P$%FI/#!L,"I/^ +M"O(#B](CWY(#E?/^"X(#E_(CK="K@Z/^#R#_H/(O:9/^$(/^$?/^%``^IL)C +M%,)#C,E#D!"FTB/)D+%TD*ET&]T6S3NR8ZVB8ZP,'H(CR?*A`I"AY18(-=(C +MR0O=TF/)XD.2PF,3PF,2J?.R(\D6.SJ0@`2"0XMA;`-!;0-Q20-2I!A04H"B +M!>:B0XJ2(Q*Q!02BH#,6F3J"(E+2H`BV2`B"(E+VR`*&7P#R(E*VSPCB1?/B +M8Q+"8Q."(E/R`XN#_0CS_0X`/:;B(NSB8E#"(NW"8E&"`XL6"`+B(Z[P[A'B +M8Z[2(Z_PW1'28Z_"`Y46C`#R(ZSRS__R8Q"`$*:M`H)B8*4_!0P:O0(E907" +M(NNX%3PZRKN6BT6WJ@0L?,8!`,$%!,K+P@P`TB+KN"7:NY8[1+>J!BQY1@(` +M``"1!02:FY()`-(B8((#B_(B4N(#C(/]%//]%>/]&=)F5K(B3X(E0*(BZ[J( +MH_@$P_@*D_@0@F95@0@$XB+M\@.5T@.7LB)0HB)#\_X0T_X1>IZS^0BC^122 +M9LGR(NR*[O/^".G$TB)'V<2R(DNYQ*@2F"*R(E*@H.20D-0+NQ:+/;(B4K++ +M_A9K.Y/Z#ZG$V*+(DM#0U,#`Y-/\#\G$\B,1HB,0D@.5@@.7H_\(D_\0@_\2 +M\F1,X@.+%JX>DB+ND)%!DF+N@B+O@(%!@F+O^$/Y4^(C$NECT@.+TD.-PB,1 +MLB/@(,R@LFQG'?```((C$K9H`L:?`)(C$H*@`?*@`)+)^Y#X@_)#E-)C$@`\ +MII`0II)C%``\IK9)`N)%\_`0IO)C%0`\IK9/`N)%\X`0IH)C%@`\IK9(`N)% +M\Y`0II)C%_(C$\(#BX(C%//]",/]#O(C%<(C%H/]$//]%,/]&)/]'``]IH(C +MK()C$/(CK?)C$<(#BYS)C'N(C("`J%")C'>#N%.)C +M'X(%YBDQ*%$6^`2"!>GI$198/`P>V0$F/`;8,0P,T.R3B`$,'28X!H@A#`R` +MW),,'"8Y!HA!#`F`R9,,&28_!H@1#`^`GY/R`XJ0C!`]\/#]$/#^$(#_$/)# +MBJT"92@$#!J]`N4\!;(CQZ(CJ[JJELHU/#RG+`)&?@`L>P9_`-(#E8R=@@.5 +M/?`6:"\6-"\`/Z:0$*:20XL`/*:I\X`0IH)C$](C$QO=TF,2LB/)"[NR8\G" +M0Y+&)/_80]E3PB,2R6.R`XNR0XVB(Q&2(^`@JJ"2:F<=\```/*:R8ZVB8ZS@ +M$*;B8\F&#?\``((#E598Q:*A`P`ZII`0II)#BP83_\)#BTT,#!E&\?X`G0P, +M!+(#B;)#B\;M_H(#B_$,!(/_#@`_IN(CK.)C$-(CK=)C$<(#BYSB(Q*B +MROH6ZB#B(Q+RVP'BSOG@XD'P[J#H#NE#TB,2PJ`-TLWYT-`4TD.9PF,2K0*E +M"P$&.O\,&0P41L#^`+K08!`+JM!RQZA@(`````P04$RJJB"@#A.`.2(R#2 +M`XO"`XSJF=/Y%,/Y&9)F5H(E0.CS\B.KBN[S_@2S_@JC_A#B9E62(ZW2`Y7" +M`Y>"(Q#3^1#X,]$(!,/Y$7KI@_X(\_X4XF;)PB.L#$[:F#@U-#0Y./]#]G$R(FX><#`U+"PY,/[ +M#[G$1O+_R$FX.<#`U+"PY,/[#[G$QNW_Z&G86>#@U-#0Y./]#]G$1NG_``"0 +M@`2"0XO&0O]6"=X,*9)%]&7"_3PZL04$!G3_#`W&B_\,"8:0_PS+LF,2H@7F +M%JK@`#^FT!"FTD.,P@.,%KS?XF,4#._R8Q(&?/\`#`O&J?\,"H:P_PP)^$$, +M#`P8#`W@V(/PR(/X,=#,$-@A\)B##`_0^(/2`XKPW1#0F1#`F1"20XH&%/\` +M``"M`@SX@F,296X"1J7^`#9!`#*A&#HRH@-_LJ1(NB*BR@&B0W^2`LB"`W^7 +MF`0,"()#?[(CUAN[LF/6HB/6DA)*IQE+Z-(;[NG2TB(-PA)*UQQ#H7\#L6P# +M0J`!=H`2@@-_\BM-"ZJ'7PJ,FI("Q"8I#(;Y_\QJ#"JB0L0EL_W`$*:R`L/, +M.]("Q)P=##(=\.`0I@PB'?#P$*8,,AWP``Q9`#FF@!"FG,BB`J2`_5#_PN"`_="(\7`JX.C_P\@1*!Z1$(D09/_$(/_$4/_%``_IM)C+-)# +M[-)C')`0IL(CX9"Q=)"I=!O,%DPQLF+MHF+L#!^"(^'"H0*0H>46."GB(^$+ +M[N)CX?)#\M)C*])C*J)C)[(CX9"`!!9K+X)#ZPS.0J082D*B!.:B0^J2(RI1 +M;0,<:I0+B(RKQ"03BSNC@XD'P +M[J#H#N)C'-(C*@S +MX@/KXD/MTB,IPB/X(-V@<-V`PFT_D```86P#XJ`(@B,JH4D#PJ`S@LCJ%B@F +M@B)2/`F7F`+&6P*"(RH6&'>"(E(\#8<]`H9A`/)$\_)C*O)C*Y(B4X(#ZY/^ +M"(/^#@`^IO(B[/)B4-(B[=)B49(#ZYSI\B/&\/\1\F/&XB/'\.X1XF/'T@/U +M%GT`@B/$"XB"8RB0$*:M`I)B8"59!`P:O0*EU@3"(NNX%#PZRKN6&S:WJ@0L +M?,8!`,$%!,K+P@P`TB+KN"3:NY;;-+>J!BQY1@(```"1!02:FY()`-(B8*(# +MZX(B4O(#\N(#[*/]%(/]%?/]&N/]&=)F5K(B3X(D0*(BZ[J(H_@$P_@*D_@0 +M@F95D4D#@0@$XB+M\@/UT@/WLB)0HB)#\_X0T_X1FIZS^0BC^1229LGR(NR* +M[O/^".G%TB)'V<6R(DNYQ:(B4I(B6`NJ%FHLLB)2LLO^%DMNK*EF&0)&_`%F +M*3'X(N@2\/#4X.#D\_X/Z<72(B+"(B'0T-3`P.33_`_)Q88#`)@BB!*0D-2` +M@.23^`^)Q9(B61:Y>689`@;Q`:+)_E9:X>BBV)+@X-30T.3C_0_9Q<@CN!/` +MP-2PL.3#^P^YQ09]_P""(RKV2&'R8RI&G?^R`_6,FX(#]3WP%FAV%CYV`#RF +MD!"FDD/K`#VFHF,G@!"F@F,JXB,JXF,KLB/A"[NR8^'20_*&5/_2(QS28QW" +M(RK"8QZR`^NR0^VB(RF2(_@@JJ!ZJI)J/QWP`/(C*O#P!%:/7PPH@F,J!H+_ +M`#VFLF/%HF/$P!"FPF/AAC?_`.(#]58NT)*A`P`YIH`0IH)#ZX8]_])#Z^T- +M#!G&&O\`G0T,#J(#Z:)#ZT87_YT-#`Z&%?_B8RH`/:8]\)`0II)C+``]I@S( +ME[@"\D3SD!"FDF,M`#VF#,B7N`+R1/.0$*:28RX`/::"H`R7N`+R1/.0$*;2 +M(RN"`^L]\-/^"-(C+(/^#H(C+=/^$-(C+I)C+X/^%-/^&)/^'``^I@S(E[@" +M\D3S@B/$@F,H\B/%\F,IX@/KG-[B(\;P[A'B8\;2(\?PW1'28\>2`_6,:?(C +MQ`O_\F,H*7%9@6F1D!"FDF,X\B,XXB,XTB,XDB,X\/`4\F,P(B,XX.(4XF,Q +M4B,XT-04TF,R8B,XD)84DF,S@B,X("@4(F,T*3%06A1905)C-6!L%"AQ:5%B +M8S:`CA2)88)C-X($YEB!:)$6B`6"!.GY(18X90P?V1&9`28^!MA!#`G0^9.( +M(0P>)C@&V#$,"=#IDX@1#!TF.`>(49*@`(#9DX@!#!DF.`J(82EQ#`*`DI,H +M<8(#ZH#N$)"-$.#O$(#N$.)#ZJT"Y<@##!J]`B6A!+(CWZ(CP[JJECID81``P,!BK_``P)AB__%@E<"]D6+6#BR?Y6CKFH(I@2H*#4D)#DH_D/ +MF<6"(B+R(B&`@-3P\.2#_P_YQ4;=_@``L04$NJJB"@#"(^"R(\/*NY;;5CP] +MMZT$+'O&`0#!!03*N[(+`)T"P3@#XB,X@@/K\@/LRNZ#_A3S_AGB9E;2)$"" +M(R?"(\/M`MJ(P_@$H_@*L_@0@F95@B/%\@/UT@/WPB,H\_@0LB,;\4D#T_@1 +MT0@$^OC#_PBS_Q3R9LG"(\3:B`Q+P_@(B<7R(Q_YQ=(C(]G%1@(```#BSB!+ +MF18[K:(I7`N[%OHE"]H6[1ORROX6SQ%F.N&B*5@6.@T+BA9H"&8JTZ@NB!Z@ +MH-2`@.2C^`^)Q?(N(M(N(?#PU-#0Y//]#]G%R$ZH/L#`U*"@Y,/Z#ZG%@BXD +M\BXC@(#4\/#D@_\/^<78;LA>T-#4P,#DT_P/R<6B+B:"+B6@H-2`@.2C^`^) +MQ?B.V'[P\-30T.3S_0_9Q<(N**(N)\#`U*"@Y,/Z#ZG%!M3_`/(N(M(N(?#P +MU-#0Y//]#]G%PBXDHBXCP,#4H*#DP_H/J<6"+B;R+B6`@-3P\.2#_P_YQ=(N +M*,(N)]#0U,#`Y-/\#\G%!L+_`,@NJ![`P-2@H.3#^@^IQ8A.^#Z`@-3P\.2# +M_P_YQ=ANR%[0T-3`P.33_`_)Q:B.B'Z@H-2`@.2C^`^)Q0:R_P"B*5@6*@NH+H@>H*#4@(#DH_@/B<7R+B+2+B'P\-30T.3S_0_9QT-#4P,#DT_P/R<6B +M+B*"+B&@H-2`@.2C^`^)Q?ANV%[P\-30T.3S_0_9Q<(N)J(N)<#`U*"@Y,/Z +M#ZG%1G;_``#"+B*B+B'`P-2@H.3#^@^IQ8(N)O(N)8"`U/#PY(/_#_G%AFS_ +MJ"Z('J"@U("`Y*/X#XG%^&[87O#PU-#0Y//]#]G%1F3_``"B*5B\ZB8:*,+* +M_E8@(#4\/#D@_\/^<4&3O\`TF,J\@3I\D/JLB,K +MD@/K@@/RL_X(D_X.@_X/`#ZF\B/$\F,HLB/%LF,ID@/KG/FR(\;PNQ&R8\:2 +M(\?PF1&28\>"`_46B`#2(\32S?_28RCP$*;R8SCB(^&6WB:1?P,+F8(F@Q88 +M&A89&K($]`N99BON#+T`/:;2(]^R(\/:NY8[&K>L/RQ[AA``##_R8RK&`_X` +M`!89"PN)%C@@HLG^5EH+Z"+8$N#@U-#0Y./]#]G%PB(BLB(AP,#4L+#DP_L/ +MN<6&)`#1!03:N[(+`.(CX-(CP^K=ECT5UZP$+'G&`0"1!02:G9()`-(C.((# +MZ_(#\N(#[(/]%//]&N/]&=)F5L(D0/(C)X(CP\K_@_\$L_\*D_\0\F95@B/% +MX@/UT@/WPB,HX_@0\B,;T_@1T0H$JNC#_@CS_A3B9LG"(\3:B,/X"(G%!K/] +M``"H(I@2H*#4D)#DH_D/F<62(EH6V1(+N18+%28I`H:J_?(B$N(B$?#PU.#@ +MY//^#^G%TB(RPB(QT-#4P,#DT_P/R<5&H?V8HHB2D)#4@(#DD_@/B<7&G/V0 +ML`2R0^O&)O[2(B+"(B'0T-3`P.33_`_)Q88+_O(B*N(B*?#PU.#@Y//^#^G% +MAI#]XF,J@@3FS!A&C/T`/*:@$*:B0^R2`^S,&0:(_?)C+`SKLF,J1H7]K0(, +M_,)B4M)B1"6R`<:"_0!66>8,+=)$]"7]_*%)`SP\1I7_#`J&H?X,"X:G_@P+ +M1JC_``P)AJW_^"+H$O#PU.#@Y//^#^G%!G3]`-A1#`GX80P>#`OPOH/0GH.P +MF1"X00P(^#&PCH.R`^H,#?#>@]"[$+"($)"($()#ZD9R_@"2(B*"(B&0D-2` +M@.23^`^)Q<9A_;(B$J(B$;"PU*"@Y+/Z#ZG%QES]TB(BPB(AT-#4P,#DT_P/ +MR<7&J/_R(C+B(C'P\-3@X.3S_@_IQ<92_0``HJ`!(+(@I3@$H4D#PJ`SAF;_ +M-D$`#`LRT@$,'PQU@B)"0J1$2D*"R/X66!>2`Y4,&A99%M(#C=)#B\(B1IT+ +MP)J##`V3]0J"`XOHY,(#E:(#EX/U"X(CK>#?@]/U#R"(H((H:R8Q+2(Q+28Q/B +M!+J,KO)#BH(C$H+(]!9X#9(C$J"9P!8I"R"B(&4/`,%M`[(C$?(C$.(#E=(# +ME_/["./[$-/[$K)L3*(#BQ8:!N(CKN#A0>)CKM(CK]#10=)CK\(C!,)C!;(C +M$KECH@.+HD.-DB,1B/0@F:"":6<=\((C$A8X"9(C$N$)!,>9`D8@`-(C$@O= +MT-)!X-V@V`W90\(C$@O,P,`4PD.9LF,2!M?_J$.I4Y(C$IEC@@.+@D.-\B,1 +MZ/0@_Z#B;V<=\````#6FP!"FPD.+AK[_K0)EC`&&TO^R0XL,&<:G_YT+T@.) +MTD.+!J7_```UIH`0IH)#C.(#C`SI%F[Q\F,4DF,21L/_``"B8Q(&O?\,R[)C +M$@:[_P``-D$`PB)4#(OR(E,RT@'B`XO2`Y+S^PCC^P[3^P_#^Q``.Z:B(ZRB +M8Q"2(ZV28Q&"`XN@8!`-JJH@H`PBPMP@P]XJ!DYYP8XB/(PB.K#`GJS)8,"<(#E8$+!-(#E^/_$.(C$-/_$;J_V#.*_^/["-/[%+)L +MR;(CK(%M`[/_"/G('?``F3.&S/^M`B4K!(;1_P````P*1M?_VIR2"0`&W_]& +MWO\V00!"H.Q*0J(D][(B4[/Z"``ZII`0IH(DSC%L`Y*DA-;(`I`B@)%_`W:` +M#H(C@PN9C)B,F:("B"8J#(;Z_\QI#"NR0HAEN?P,O``\ID8``)HBD0T$XB0E +M@@)Q\@2@FNZ#_A2!20/S_AGB8U;2(B7")!3Q#@3A;0/:S,)C5=(DLK(DL:($ +MJYB$L_T(H_T1BHWZW9/X%()CR=G.'?`V00!"H.Q*0J(D][(B4[/Z"``ZII`0 +MIH(DSC%L`Y*DA-;(`I`B@)%_`W:`#H(C@PN9C)B,F:("B"8J#(;Z_\QI#"NR +M0HBEK_P,O``\ID8``)HBD0T$XB0E@@)Q\@2@FNZ#_A2!20/S_AGB8U;2(B7" +M)!3Q#@3A;0/:S,)C5=(DLK(DL:($JYB$L_T(H_T1BHWZW9/X%()CR=G.'?`V +M00!"I"Q*0IB$`#FF#`\RT@&"!,F"0XOR8Q3R0XSY0]`0IAQ>\D.2`#ZFT+'E +MT,ETT-%TTF.MPF.LN?.@$*8,^PS1;0.S^`BC^!*":4SR(ZWB)!4@_Z#B;V<=\.(C$A8^!_(C$MC_PB.M\B.LX@.7 +MT6T#\_P(X_P2PFU,LB.MHB05(+N@HFMG'?`B(ZO"H#/B(\BPJH"6 +M^@BGK`0L>P8!`-JZL@L`HB.K#`GJJI;:!Z>L!2QY1@$``-J:D@D`PB,@\@1U +MXB,2T@.,\_P4\6P#X_P5T_P9PF]6HB0FZ/."(ZNJ[H/^!+/^"I/^$.)O5>%) +M`Z(CK=(CK,(#EX@ST_H(P_H1T0L$P6T#ZNJ#_A3B;\G:JJG,'?`,"(DSAM'_ +MK0+E_`-&U_\````,"\;=_P;C_S:A`&*A+&IB@B;(`#BF#`U"I!A*0O($W?)& +M7])&8-)B5-)B1*`0IAP^`#ZFH+ETH,%TPF+MLF+LH*'EHF)/D!"FDD9F@@9F +M,M(!%@@_TF,2TF,3TF/)46P#<6T#H4D##!S"1EZ"(E+Q!00\.^S(X08$TB/R +MZMT`/:;`$*:1?P/"8R!V@!.")8,+F18H&!89&,($],+,_A:,&$;Y_^(C$O9. +M`H8)`8(B4K9H`D9C`!P=XB,2#(D,".+.^^",@X)#E))C$@`]IN`0IN)C%``] +MIK9.`L)$\X`0IH)C%0`]IK9(`L)$\^`0IN)C%@`]IK9.`L)$\X`0IM(C$^(# +MB]/Y"./Y#M(#DN(C%-/Y#^/Y$.(C%=(C%H)C%^/Y%-/Y&(/Y'``YIK9(`L)$ +M\R)A!U)A"&F1D!"FDF,@XB,@TB,@PB,@DB,@X.`4XF,8(B,@T-(4TF,94B,@ +MP,04PF,:8B,@D)84DF,;@B,@("@4(F,<*3%06A1905)C'6!L%"AQ:5%B8QZ` +MCA2)88)C'X($YEB!:)$6J`6"!.GI(1:H6`P>R1&9`28]!\A!DJ``P.F3B"$, +M'28X!L@Q#`G`V9.($0P<)C@&B%$,"8#)DX@!#!DF.`J(82EQ#`*`DI,H<8(# +MBCWP@-T0D(P0T-X0@-T0TD.*K0*EM0*M`J7``\(CQZ(CJSP[RJJ6:E&G*P(& +MA0`L>L:%`,SI#"W21/3E9?RA20,\._$%!`R^`#ZFTB/'PB.KVLR6K#O'JT@L +M?082````@B,2@LCA%LA9XB)2MLX"AMD`@B,2@LCZ5L@*#,JB8Q*2!.8660P< +M?@`^IM`0IM)#C+(#C!9+"\)C%`SO\F,21BH`^MS2#0#B(\C"(ZOJS)9<-L2(NW"(NRR +M!FO#^0BS^1*29TR"(NWR)M4@B*#R:&<=\`""(Q*2WP&"R/F`@D&0B*"("(E# +MXB,2#-WBSOG@X!3B0YG28Q*M`N6\_[(B[=(B[,(&:]/[",/[$K)G3*(B[9(F +MU2"JH))J9QWPT04$VLS"#`#1.`."(R"R!-V2`XS:B+/X%)/X&8)E5O(D0-CS +MXB.K^MWC_03Q20/A"`2C_0K#_1#29572(ZVR(ZR2`Y>(,[/]")/]$?K]@_\4 +MZMT,2/)ER=G'N'.YQYBSO0*29PP@DB!VJ!.B*5Q+F19Z!28:2"8J.28Z(K++ +M(+(B[=(B[,(&:]/[",/[$K)G3*(B[9(FU2"JH))J9QWPJ!NIQX@[BL!"Q[Q@$`L04$NKJR"P#" +M)J"H),JJENHD/#VGK00L><8!`)$%!)J:D@D`\B85R':B!-V"!F##_Q6C_Q2# +M_QGR95;B)OO(1M(FH.K,T_P$L_P*D_P0PF55\B:BHB:AD@9KX0@$H_\(D_\1 +MD4D#@B)#ZN^:_X/_%/)ER>G'TB)'V"(NVR(NRB!FNS^`BC^!*"9TSR(NWB)M4@_Z#B;V<=\,)$\\)F +M!])F".(D+/B&\_X(`#ZFT!"FK0+29A7E:`.M`J6"`[(FH*@4NJJ6BAH\/*>L +M>RQ[AA\`#`T&)/\``/&X`[(C(.($W<(#C/J[X_L4P_L9LF56@B1`Z//R(ZL, +M"8KN\_X$T_X*D_X0XF55LB.MPB.L@@.7^#/#^PC!!P2#^Q&JZ_/^%.)ERM!"QYQ@$`D04$FIJ2"0#R)A7(=J($W8(&8,/_%:/_%(/_ +M&?)E5N(F^\A&TB:@ZLS3_`2S_`J3_!#"957R)J*B)J&2!FOA"`2C_PB3_Q&1 +M20."(D/J[YK_@_\4\F7)Z(FU2#_H.)O9QWP#`J&0?\, +M#(8+_XAA#`S840P>#`G0GH.`SH/800P(P)D0R#'0CH,,#<#>@\(#BM#,$,"( +M$)"($()#B@:E_@P+AFG_#`E&;_\`F(B[-(&:^/\"-/\$L)G +M3+(B[:(FU2"[H*)K9QWP``P+AK;_#`E&O/^9Q^(B$>G'LB+MTB+LP@9KT_L( +MP_L2LF=,HB+M@B;5(*J@@FIG'?"9QZ(B[<(B[+(&:\/Z"+/Z$J)G3((B[?(F +MU2"(H/)H9QWP````K0(,_=)B4J54_X(B[:(B[)(&:Z/X")/X$H)G3/(B[>(F +MU2#_H.)O9QWPF<>R(NW2(NS"!FO3^PC#^Q*R9TRB(NV2)M4@JJ"2:F<=\``` +M-D$`8J$8:D*B!'\RI$@Z,ANJHD1_D@/(@@1_70(,`I>8`B)$?Z(DUANJHF36 +MDB36@A-*D(C`%O@'V-,;W=G3R-.R$TK'&WBA?P.Q;`-V@!+R!'_B*TT+JO=> +M"HR:@@/$)B@,AOG_S&H,*9)#Q&7]^PQ\PF3-@B3-LB39#!H,";":@Y/X#X)D +MS>(DS?($?_/^$>)DS=(DI\(DS5#=H&K=TBTCT_P4PF3-L!"FH@/#S#K2`\2< +M'0PR'?#@$*8,(AWP\!"F##(=\``<"@`ZII`0I@PXD"B3'?``-L$`,J$L.C*" +M(\@`.*9"I!A*0N($W>)#7PP.XD-@XF)$XF)4H!"F'#T`/::@N72@P73"8NVR +M8NR@H>6B8D^0$*:20V:"`V8<7\+2`18((.)L$N)L$^)LR0PK86P#46T#<4D# +MD@3FDD->@B)2T04$/#H6N"J"+!*'/P[(]DQVXF)2!B$```""(E(,SX+( +MZA:(0I(L$BSXE[@"!EL`HBP2''FBRNG,&@8#`O(L$H+=`?+/Z/#R08#_H/@/ +M\FP$XBP2#-OBSNC@X!3B3)FR;!*M`N51_Z(B[<(B[+(#:\/Z"+/Z$J)E3)(B +M[8(CU2"9H()I9QWP``#B(E('[@<,+_)B4D8!`(*@`X)B4J(D++(C"+/Z"``Z +MII`0IJT"DF,5Y>,"K0(E/0/"(Z"X%#PZRKN66S&WJ@0L?,8!`,$%!,K+P@P` +MTB.@N"3:NY8;,+>J!BQY1@(```"1!02:FY()`/(C%;ASH@3=@@-@L_\5H_\4 +M@_\9\F96XB/[N$/2(Z#JN^$(!-/[!,/["I/[$+)F5?(CHJ(CH9(#:X(B0Z/_ +M")/_$>KO>O^#_Q3R9LGIQ=(B1]G%LB)+N<6B(E*2(E@+JA8:*<(B4L+,_A;\ +M118I;@O9%@TNXLG^%FXMDB)9%OEW\LG_%N\C@LG^%O@@LB+MTB+LP@-KT_L( +MP_L2LF5,HB+MDB/5(*J@DFIG'?#R(E+RS]`6[W;"H`'"1//"8P?)@Z(D++B# +ML_H(`#JFD!"F(*(@DF,5I=("K0+E*P.R(Z"H%+JJENII/#RGK!PL>\8'```_ +MII`0IGS]DFP2@BP2@FP3TFS)!GS_`+$%!+JZL@L`PB.@J"3*JI9:9CP]IZT$ +M+'G&`0"1!02:FI()`.(C%:AS@@3=\@-@H_X5@_X4\_X9XF96TB/[J$/"(Z#: +MJM$(!,/Z!+/Z"I/Z$*)F5>(CHI(CH8(#:_(B0Y/^"(/^$=K>>N[S_A3B9LG9 +MQ<(B1\G%HB)+J<62(E@6*6T+N18;;\+)_E9L[[@2N<6B(B&IQ?(B[9(B[((# +M:Y/_"(/_$O)E3.(B[=(CU2#NH-)N9QWP``#R+/*2+!."#)*3_PB#_P\`/Z:0 +M$*:2;"#B;!*"!.F"3(KR+,F6[W21?P,+F>(F@Q:N5!:I5/($]`N99B_N#+@` +M.*;B+,>R+*OJNY;+5[>J!"Q^!@$`VNOB#@#R+,BR+*OZNY:K5K./_"H/_$($* +M!/)F5?(LK=(LK+(,EZ@\T_\(L_\1>I^*_Z/Y%))FR?G%HB+MTB+LL@-KT_H( +ML_H2HF5,DB+M@B/5()F@@FEG'?``Z)+IQ<(B*#(F2;!(`/J:` +M$*:";!0`/J:'OP7RH`'R1/.0$*:2;!4`/J8,R)>X!?*@`?)$\Y`0II)L%@`^ +MI@S(E[@%XJ`!XD3SD!"FXBSR@BP3\BP4@_X(\_X0@BP5\BP6DFP7@_X4\_X8 +MD_X<`#ZF#,B7N`0,&9)$\R)A"C)A"UG!:=&0$*:2;"`B+""2+"#R+"#B+"`@ +M(!0B;!@I@3(L()"2%))L&5(L(/#T%"BA\FP:8BP@X.84XFP;@BP@,#@4,FP< +M.4%06A1945)L'6!L%#BQ:6%B;!Z`CA2)<8)L'X($YEC!:-$6&`:"!.F9,1;8 +M1@P9B#'Y(>D1)C@&^%$,#O">DXB!#!^9`28X!NA!#`G@^9.((0P>)C@(B&$, +M"3WP@.F3B!$,&28X"HAQ*:$,`H"2DRBA@@R*@(\0^`')D8#_$)".$(#_$/), +MBLF1K0+E/@*M`J7N`JB1PBK'LBJKRKN6BSX\/;(B[-(#:^/\"-/\$L)E +M3+(B[:(CU2"[H*)K9QWPVINB+"#R!-W2#(RR#)+S^A33^AFS^AJB9E:")$#8 +M_/(LJY()`(K=\_T$X_T*D_T0TF95HBRMLBRL@@R7^#RS^@BQ"@2#^A%ZVO/] +M%-)FR;JJJ<72(NV"(NSR`VN#_0CS_1+294RR(NVB(]4@NZ"B:V<=\,$%!,J[ +ML@L`TBK(PBJKVLR6S"X\/L>N!"Q]Q@$`T04$VMS2#0"1.`/B*B""!-WR"HR: +M[H/^%//^&>)F5L(D0(CZDBJKRHB3^`2S^`K3^!""9E7B*JWR*JS""I>8.O/^ +M"/$(!,/^$7J.D_@4@F;)^NX,3^G%R'K)Q9BZS0*9Q9T"!@P```!F*B/8'-G% +MLBPAN<6H/*G%@BPCB<7H7.G%TBPEV<6X?+G%HBPGJ<7"S"!+F1:_HJ(I7`O_ +M%OH*)AIP)BHU9CKFHBE8G(IF&K>R+"&YQ:(L(ZG%@BPEB<7B+"?IQ<;Q_Z@< +MJ<6(/(G%Z%SIQ=A\V<4&[?\`HBE8K&HF&A=F*JB('(G%XBPAZ<78/-G%LBPC +MN<7&Y/^R+"&YQ:(L(ZG%AN'_Z!SIQ=@\V<7&WO^B*5BLJB8:&X+*_E;8]N@< +MZ<72+"'9Q;A\X(L`8)E#*(L(:G%QLC_N!RYQ0;'_P``5LFKR9&R1/1E +M;/L\.LB1T04$AJK^R!+)Q09(_O)L$M($YA;M@``YIO`0IO),C.(,C,P>1O_] +M#.@,&9)L%()L$@;\_0P)AFG^#`M&8?X,#H:B_@"B+"#R!-W2#(RR#)+S^A33 +M^AFS^AJB9E:")$#8_/(LJPP)BMWS_03C_0J3_1#29E6B+*VR+*R"#)?X/+/Z +M"+$*!(/Z$7K:\_T4TF;)NJJIQ=(B[8(B[/(#:X/]"//]$M)E3+(B[:(CU2"[ +MH*)K9QWP^)+YQ<(B[>(B[-(#:^/\"-/\$L)E3+(B[:(CU2"[H*)K9QWPK0(, +M^()B4N)B1.6I_K(B[=(B[,(#:]/[",/[$K)E3*(B[9(CU2"JH))J9QWPZ!+I +MQ?(B(?G%!A__B!*)Q;(B[=(B[,(#:]/[",/[$K)E3*(B[9(CU2"JH))J9QWP +MXB(AZ<6R(NW2(NS"`VO3^PC#^Q*R94RB(NV2(]4@JJ"2:F<=\`P+!D+_``P- +MQD?_^!+YQ48(_[AQ#`^(80P9#`Z`Z8.P^8.(40P+\.X0^$&`N8,,"/")@_(, +MBLF1@/\0\+L0X+L0LDR*ANW^F!*9Q>(B[8(B[/(#:X/^"//^$N)E3-(B[<(C +MU2#=H,)M9QWP\B(1^<7"(NWB(NS2`VOC_`C3_!+"94RR(NVB(]4@NZ"B:V<= +M\,)A"2"B(*6E`J*@,]$%!,B1QBW^```V00`,B^(B4T+2`=($B\($DN/["-/[ +M#L/[#P`[IJ(DK*)D$)(DK9)D$8($BYS8DB2N\)D1DF2N@B2O\(@1@F2O\@25 +MC&^B)*P+JJ)D$,`0IK(DR3%L`Y*DC-:[`IHBD7\#=H`.TB.#"YF,G8R9X@*` +M)BX,AOK_S&D,+_)"@"5$^PRX`#BF1@``FB*")""R!(NB)!*2!(RS^!2C^!63 +M^!F"8U;R(B/H]+%)`_KNXF-5DB2MT@25H0X$P@27T_D0TB00P_D1NKG(-*J9 +MT_L(P_L4LF/)LB2LH6T#L_D(FX(#BZ/["JCD@_L+X@.5#`C2`Y?" +M(ZV@CX.#^P\@S*#"+&GC^Q#3^Q'#^Q0`.Z:28Q220XR90Z`0IJ"`!()#B^(# +ME=PNP@.5'$T`S!'0S"``/*:P$*:R0XL<70`]IJ"Y=*#!=,)CK;)CK*"AY:GS +MDD.2@!"F#/J"8Q+B(Q+B8Q/2(Q(,VQR.%JT.@B,2T0D$ASXAPB,2"\S`PD'0 +MS*#(#,E#DB,2"YF0D!220YFR8Q*&!0```-(C$M+-YQ:M#?)$Q[)C$H(C$H)C +M$Y($NHS)\D.*LB,2/?"RR_06^PG"(Q(]\*<<<2"B(*4+`/%M`^(C$:(C$)(# +ME8(#EZ/^")/^$(/^$N)O3-(#BQ;M`I(CKI"109)CKH(CKX"!08)CK_(C!/E3 +MXB,2Z6/2`XO20XW"(Q&X]"#,H+)L9QWPZ$/I4](C$MECP@.+PD.-LB,1J/0@ +MNZ"B:V<=\*T"I1D`QN+_````DD.+#!J&I/^M"?(#B?)#B\:A_PS(@F,2!M/_ +M''P`/*:P$*:R0XR2`XP,[1;)]/)C%-)C$L;0_Z)C$H;*_P``-D$`PB)4#(OR +M(E,RT@'B`XO2`Y+S^PCC^P[3^P_#^Q``.Z:B(ZRB8Q"2(ZV28Q&"`XNL!2Q[1@$``-JZL@L` +MHB.K#`GJJN%L`Y9:"*>L!"QY!@$`VIJ2"0#R(R#"`XNB(Q*"`XS#_Q2C_Q6# +M_QGR;E;2)".H\\(CJ]JJT4D#P_H$L_H*D_H0HFY5HB.M@@.5P0L$\@.7@_H0 +M@B,0\_H1VMKX,\JJ@_T(\_T4TF[)TB.LP6T#T_H(J6@F7063#GB8Q+B8Q/B8\F2 +M8ZRY\\*@"&%L`W%)`[$%!%($ME)#BO(C$J*@,U%M`Q;_.H(B4K9("/(B4O;/ +M`L9<`((B4K;("-)$P])C$N)C$X(B5/(B4^(#B](#DO/\"./\#M/\#X/\$``\ +MIO(B[/)B4.(B[>)B4=(#BQ8M`M(CKO#=$=)CKL(CK_#,$<)CKX(#E1:H`.(C +MK#WPXL[_XF,0\!"F(*(@\F)@Y2("K0*E/`+"(NNR(\<\.LJ[ENM%MZH$+'S& +M`0#!!03*R\(,`-(BZ[(CR-J[EHM$MZH%+'D&`@``D04$FIN2"0#2(F""`XOR +M(E+B`XR#_13S_17C_1G29E:R(D^")#2B(NNZB*/X!,/X"I/X$()F58$(!.(B +M[?(#E=(#E[(B4*(B0_/^$-/^$7J>L_D(H_D4DF;)\B+LBN[S_@CIQ=(B1]G% +MLB)+N<6B(E*8$@NJ%FH]HB)2HLK^%CH\F<6XDKG%TB,1@B,0\@.5X@.7@_T( +M\_T0X_T2TF5,P@.+%KP<\B+N\/%!\F+NXB+OX.%!XF+OV$/94\(C$LECL@.+ +MLD.-HB,1F.0@JJ"2:F<=\((C$K9H`L:H`!P?DB,2#!CBH`"2R?N0Z(/B0Y3" +M8Q(`/Z:0$*:28Q0`/Z:V20+21,/@$*;B8Q4`/Z:V3@+21,.`$*:"8Q8`/Z:V +M2`+21,/M#)`0IO(C$X(#B_/^"/(C%(/^#H(C%?/^$/(C%I)C%X/^%//^&)/^ +M'``^IK9)`M)$P](CK-)C$)(CK9)C$8(#BQ8(`H(CKO"($8)CKO(CK_#_$?)C +MK^(#E1:.`)(CK)+)_Y)C$"F!69%IH9`0II)C(/(C(.(C(-(C()(C(/#P%/)C +M&"(C(.#B%.)C&5(C(-#4%-)C&F(C()"6%))C&X(C("`H%")C'"DQ4%H464%2 +M8QU@;!0H@6E18F,>@(X4B6&"8Q^"!+98D6BA%K@%@@2Y^2$62#<,']D1F0$F +M/@;800P)T/F3B"$,'B8X!M@Q#`G0Z9.($0P=)C@&B%$,"8#9DX@!#!DF.`J( +M82F!#`*`DI,H@8(#BLEQ/?"`[A"0C1#@[Q"`[A#B0XK)<:T")0D!K0(E%`+" +M(\>R(ZNH<0`L>X9Z`*A#J5.2(Q*98X(#BX)#C?(C$>CD +M(/^@XF]G'?```-(#E1P_`-T1\-T@`#VFDF.MP!"FPD.2A@#_``"2`Y(,#Y#] +M@U;OP$8(`!Q?`#^F?/R28ZRY\\)CR:`0IJ)C$X(C$QN(@F,2!A;_#`F@@`2" +M0XN&_O[B0XL,&0;<_K(#B;)#BT;Z_IT.P@.)PD.+!M?^@B,4XB,3T@.+D@.2 +MX_P(T_P.D_P/@_P0`#RF\B.L\F,0XB.MXF,1T@.+G.V2(Z[PF1&28ZZ"(Z_P +MB!&"8Z_R`Y6,?\(CK,+,_\)C$-`0II%_`])C(`N9XB:#%FX>%FD>\@3$"YEF +M+^X,O@`^IM(CQ\(CJ]K,ENP=QZI$+'T&$0""(Q(<[X>_`@9H`)(C$I+)^A;) +M(-(C$N+;`=+-^=#20>#=H-@-V4/"(Q(,VL+,^<#`%,)#F:)C$JT")83_AC'_ +MNMS2#0#B(\C"(ZOJS):\&,>J!"QY!@$`NIR2"0"R(R#R`XOB`Y+"`XSS^Q3C +M^QK#^QFR9E:B)#3X\X(CJ\$'!*K_@_\$T_\*D_\0\F95HB.MX@.5L@.7@B,0 +M^#/C^A"S^A%ZZH/^"//^%.)FR;(CK,JJL_H(J<4&$_\`#`S&ZOX,"8;P_IG% +M@B(1B<7&#?^9Q88,_\$%!,J[L@L`TB/(PB.KVLR6_`\\/L>N!BQ\1@(```#1 +M!03:S,(,`-(C(/(#B^(#C//]%*/]%>/]&=)F5I(D-/CS@B.KFO^#_P2S_PK# +M_Q#R9E6B(ZWB`Y72`Y>2(Q#C^A"(,^$(!-/Z$7KZD_\(@_\4\F;)TB.L#$_J +MJM/Z"*G%F'.M`IG%G0*(LXG%=J\2LBE<2YF\>R8;*28K&R8[!:+*($;C_M@: +MV<7(.LG%N%JYQ8AZB<6&^?_X&OG%Z#KIQ<;V_[@:N<6(6HG%!O3_`,@:R<4& +M\O\``-(C$M+-X58=M:T"#/_R8Q(E@?\&T?X``%8)X@PH@D3$Y8OZ/#JQ!00& +MA/\,#0::_PP)QI[_#`M&O?\`#`R&P__H80P(F%$,'0P/D/V#X(V#F$$,#H#_ +M$(@QD.V##`F`G8."`XK)<9"($(#N$/#N$.)#BD8J_PS(@F,2\@2V%K_@''L` +M.Z:@$*:B0XR2`XP6J=_28Q0,[,)C$L9[_P```#9!`#*A&#HRH@-_LJ1`NB(; +MJJ)#?Y("T((#?T*@`)>8`D)#?ZC"&ZJIPIC"@A).EQA.TB/9TLT!TF/9PB/9 +MLA).QQM7H7\#L6P#4J`!=H`2\@-_XBM-"ZKW7@J,FH("S"8H#(;Y_\QJ#"F2 +M0LPE??JP$*:B`LO,.L("S(R<##(=\-`0I@PB'?#B`WV$N2)"HL^)>X`L9X +M`+(D*AQZIYL"QAT"\04$XB0J\M\!XL[HX.)!\.Z@Z`[B9!S2)"H,W-+-Z-#0 +M%-)$^<)D*JT"I3__QDX`@B0J!^@'#"F29"I&`0#"H`/"9"KB(PC"`U^8D^/] +M",/]#I/]$``]IH(CH8E3\B.B^6/B`U^K +M!BQ]1@(```#1!03:W-(-`.(CO<(CH.K,EMP[QZL%+'D&`@``D04$FIR2"0#" +M(Q6"`U_X<^(#8(/\%//\%>/\&<)F5K(C^_A#@B+KNO^#_P2!20/3_PJ3_Q#R +M9E7R(NWB!/7"!/>R(E"2(D/C_Q##_Q&*C[/X")/X%()FR8(B[*K_@_\(^<7B +M(D?IQ<(B2\G%LB)2DB)8"[L62S2B(E*BROX6FD\6"6\+N1:[;\+)_A9<<)(B +M619Y;M+)_Q8=;^+)_A;^;XACN%.B`VF2`VNS^`BC^!"3^!*"94SR`U^\#Z(D +MQJ"A0:)DQI(DQY"109)DQX(B1()B1?AS\F)&X@-?XD-AV&/"(]4@W:!ZW<)M +M'!WP\B)$\F)%Z'/B8D;2`U_20V'(8[(CU2#,H'K,LFP<'?"((#7YS. +MXB.C\.X1XF.CTB.D\-T1TF.DP@-IC%SR(Z$+__E3@!"FK0*"8F`E/P&M`F68 +M`<(BZ[(CO*$(!,J[EDME/#VWK58L?$86````@@-I'#P`B!'`B"``.*:28Z+P +M$*;R0V8&*_\``)(#9@P+D+^#5IO+!@<`````.:9\^*)CH;E#@F.^T!"FV7/( +M<\F#!D7_#`F@L`2R0U_&*O_!!03*R\(,`-(BZ[(CO=J[EJM>/#ZWK@0L><8! +M`)$%!)J;D@D`LB)@\@-?XB)2T@-@\_L4X_L5T_L9LF96@B/[XB)/\B+KBN[S +M_@3Q20/#_@J3_A#B9E7B(NW2`VFR`VN2(E""(D/3_A"S_A'Z_I/_"(/_%/)F +MR?(B[*KN\_X(Z<72(D?9Q;(B2[G%DB)8%BE7"XD6&%BBR?Y6>N+($LG%LB(A +MN<7&AO_B0U\,&4;=_M(#7=)#7X;\_IT.\@-=\D-?1MC^XF0J@B0K\@3KD@3R +M@_T(@B0L\_T.D_T/@_T0`#VF\B3$\F0HDB3%DF0I@@3KG/CB),;P[A'B9,;2 +M),?PW1'29,>2!/46B0#R),3RS__R9"B0$*:29#B").&6V%>1?P,+F=(F@Q9= +M11991>(,A`N99B[N#+\`/Z;B)-_2),/JW99=3->K!BQ]1@(```#A!03JW=(- +M`/(DX.(DP_KNEMY*YZL%+'D&`@``D04$FIZ2"0"")#CR!.OB!/*R!.SS^!3C +M^!JS^!F"9E;R)">R+"3B),/ZN^/[!-/["I/[$+)F5?(DQ8($]>($][(D*(/_ +M$./_$8(D&ZKOL_X(L0H$@_X4XF;)@B3$NO^#_PCYQ08\_P`,#88-_PP)1A/_ +M```6:44+B1:(1:+)_E9:S<@2R<6R(B&YQ48R_QP>TF0J`#ZF/?"0$*:29"P` +M/J8,R)>X`O),@Y`0II)D+0`^I@S(E[@"\DR#D!"FDF0N`#ZF@J`,E[@"\DR# +MG0V`$*;B)"OC^0CB!.OC^0[B!/+C^0_B)"SC^1#B)"WC^13B)"Z"9"\]\./Y +M&(/Y'``YI@S.A[X"\DR#DB3$DF0H@B3%@F0I\@3K%O\!@B3&\(@1@F3&\B3' +M\/\1\F3'X@3U%GX`DB3$"YF29"@IL3G!6=%IX9`0II)D."(D.)(D./(D..(D +M."`@%")D,"F!,B0XD)(4DF0Q4B0X\/04*+'R9#)B)#C@YA3B9#.")#@P.!0R +M9#0Y05!:%%E14F0U8&P4.,%I86)D-H".%(EQ@F0W@@QV6-%HX188!H(,>9DQ +M%D@T#!F(,?DAZ1$F.`;X40P.\)Z3B($,'YD!)C@&Z$$,">#YDX@A#!XF.`:( +M80P)@.F3B!$,&28X"HAQ*;$,`H"2DRBQ@@3J@(\0^`'9H"*"22),.JB)/X!-/X"L/X +M$()F5:(DQ?($]>($]\%)`_/Z$./Z$?(D*.(D&\K*\_P(X_P4PF;)PB3$NJK# +M^@@,3*G%DB0?K0*9Q9T"@B0CB<4&#````&8K(]@:V<6R*B&YQ8@ZB<7R*B/Y +MQ>A:Z<72*B79Q;AZN<6"*B>)Q:+*($N9%GRBLBE<"\P6^PHF&W`F*S5F.^:R +M*5B(J)^G%QO'_B!J)Q?@Z^<7H6NG%V'K9 +MQ0;M_P"R*5BL:R8;%V8KJ/@:^<7B*B'IQ=@ZV<6R*B.YQ<;D_[(J(;G%@BHC +MB<6&X?_H&NG%V#K9Q<;>_[(I6*RK)AL;\LO^5M_VZ!KIQ=(J(=G%N%JYQ8(J +M)8G%!M;_`((J(8G%\BHE^<6&TO_8&MG%N%JYQ<;/_[(I6)S;)AL3XLO^5A[S +MB!J)Q?(J(?G%1LG_``"R*B&YQ<;&_]@:V<4&Q?\``%89N\F1#"[B3(0EX/FA +M20,\.\B11N?^B!*)Q89$_@"8DIG%!D?^`*(B(:G%1D#^LB(IN<7&0O[8$MG% +MPB(AR<5&._[XDOG%Z!3IQ08]_@`,R9)D*H(,=LP8ANC]`#JFP!"FPD3LL@3L +MS!M&Y/WR9"P,[=)D*H;A_0P,1H+^#`E&B/X`Z!+IQ08N_@`,#8;1_@P)1M?^ +M``#R(B'YQ<8H_JT"#/B"8E+B8D1ERO[&)/X,#89J_PP,AG#_F!*9Q88@_J(B +M(:G%AA[^LB(1N<6&'/["(B')Q897_](B,=G%AAC^B&$,#^AQ*;$,&0P"X"F# +M@/F##`Z(42#_$"A!@.F##`@@B8,B!.K9H7*2(AN2R?T6:>@`-*:P$*:HF,!"F.3(&R_\``#>F@!"FB;(&T_\``#>FD!"FDF(3QMK_`#>FT!"F +MV3(`-J;`$*:Q'`3)4@`[IJ`0IJER1KW_````-Z90$*99L@`VIC`0IO$=!#G2 +M`#^FX!"FZ?)&P/\````WIK`0IK)B$P`VIJ`0II$>!*)B%0`YIH`0IH)B%X;" +M_\(B6"8\#!R>`#ZF/?#0$*;29!'R)",F/Q2!'P0`.*90$*8R)!&@51%0,R`R +M9!&2)"0F.1;!(`0`/*:P$*:B)!$]\$"[$;"J(*)D$=(D)=+-_18]XS$A!``S +MIO`0IN(D$>#_`?#N(.)D$<:&_P`UIH`0IH)B'1WP`#:FD!"FDF(;'?``-D$` +MF@!"FB24`-Z8P$*8Y-0`W +MIO`0IOE%`#>FX!"FZ54`-Z;0$*;990`WIL`0ILEU`#>FL!"FN84&%@```#>F +MT!"FV14`-Z;`$*;))0`WIK`0IKDU`#>FH!"FJ44�```#>F@!"FB14`-Z8P +M$*8Y)0`WIO`0IOE5`#>FX!"FZ64&!````#>FH!"FJ14`-Z:0$*:9)5+%($M$ +M30(,2W:KT%(B6!95#,+%_1;\"U(B7!95"B85>B8E4-+%_5;="@`WIL`0IL)D +M(0`WIK`0IK)D(@`WIJ`0IJ)D(P`WII`0II)D)``WIH`0IH)D)0`WIC`0IC)D +M)@`WIO`0IO)D)P`WIN`0IN)D*(88```WIC`0IC)D(0`WIO`0IO)D(@`WIN`0 +MIN)D(P`WIM`0IM)D),8.```WIK`0IK)D(0`WIJ`0IJ)D(@`WII`0II)D)0`W +MIH`0IH)D)@8%````-Z;0$*;29"$`-Z8]\,`0IL)D(D+$($LB'?``)A01)C0. +M`#:FX!"FX.!TX.?`XF)'0B)9)A0<)C09`#:F,!"F\B)'/?`P,'0P-\"@,Q$P +M_R#R8D="(EHF%!HF-!<`-J:`$*9"(D>`@'2`A\!`B!&`1"!"8D="(EL+E!89 +MV*+$_1:ZUP`VIL`0IK(B1\#`=,#'P.#,`<"[(+)B1P98_YPD)C00`#:FT!"F +M/?#0T'30U\#28DM"(EF)C<;0(8!D#@@`#.F +M\!"F^15R)%P+YQ9.""8G<28W2AMF4L4@2T1-`@P%',BQ)021)@2A)P0,3':L +M*V(B6)SF)C8<0'4!@/<@`#^FX!"FXF0A8B)<"]86S0@F)GDF-DX;54+$($LB +M'?```+`X(``SIO`0IJ#H(/DU`#ZFT!"FP'@@V54`-Z8P$*8Y=0;D_[#H(``^ +MIM`0IMDUAN#_``"@."``,Z;P$*;Y58;<_P``H#<@`#.F\!"FD.<@\F0C`#ZF +MT!"FL,<@TF0E`#RF8!"F8F0G1N+_`*#7(``]IL`0IL)D(T;>_P"0]R``/Z;@ +M$*;B9"5&VO\`-D$`#!6"H0(,!S(B4G)B1W)B2PLS%K,FH!"F8B)9HF)' +M)A84`#>FP!"FLB)'\"``H,P1P+L@LF)'0B)8TB+OMBTQXB+OXL[^%AXAC)0` +M-Z8]\/`0IO)B2S(B69PC`#>F@!"F0B)+/?"@B!&`1"!"8DM"(E@F%!``-::@ +M$*:I$@`UII`0II)B`K(B628;$0`UIM`0IM)B"0`UIL`0IL)B"N(B6)P.`#6F +M,!"F,F(A`#6F\!"F\F(B@B)9%B@/`#6FH!"FHF(I`#6FD!"FDF(J'?!"(F!B +M(F"R(NY`0!1"8EA@9!1B8EJV*S*2(NZ2R?X6Z1DF%`L`-Z:@$*:B8D=B(EHF +M%A0`-Z;`$*:R(D?P(`!`S!'`NR"R8D="(EC2(N^V+3'B(N_BSOX6KAF,E``W +MICWP\!"F\F)+,B):G",`-Z:`$*9"(DL]\$"($8!$($)B2T(B6"84$``UIJ`0 +MIJD2`#6FD!"FDF("LB):)AL1`#6FT!"FTF(1`#6FP!"FPF(2XB)8G`X`-:8P +M$*8R8B$`-:;P$*;R8B*"(EJ<*``UIJ`0IJ)B,0`UII`0II)B,AWP'?```$(B +M8+(B[D!`%$)B6+8K%Y(B[I+)_A:Y$B84"P`WIJ`0IJ)B1T(B6+(B[[8K%L(B +M[\+,_A:<$HRD`#>FT!"FTF)+0B)8)A04`#6F\!"F\F(!`#6FX!"FXF("0B)8 +M%L3Y`#6F@!"F@F(A`#6F,!"F,F(B'?``)A01`#BFD!"F8B)9D)!TD)7`DF)' +M"Z86:M\`.*;`$*:R(D?`P'3`Q<"@S!'`NR"R8D?&=O^,]``XIM`0ICWPT-!T +MT-7`TF)+XB)9%J[?`#BF,!"F\B)+,#!T,#7`H#,1,/\@\F)+QG?_)A01`#BF +MD!"F8B):D)!TD)7`DF)'"Z86VN8`.*;`$*:R(D?`P'3`Q& +ME/^,U``XIM`0IM#0=-#5P-)B2^(B6A8^YP`XIC`0IO(B2S`P=#`UP$`S$3#_ +M(/)B2P:6_PN4%MGM`#BFH!"F0B)8H*!TH*7`HF)'!K+_```6!.X`.*:P$*9" +M(EBPL'2PM<"R8DO&LO\V00`FH!"FHF)'DB):)AD6T2`$`#VFP!"FLB)' +M/?!`S!'`NR"R8D="(ECB(N^V+BF,=``XIO`0IO)B2S(B6IQ3D2,$`#FF@!"F +M0B)+/?!`B!&`1"!"8DM"(E@F%`@`-::@$*:B8@&R(EK1%00F&PH`/:8]\,`0 +MIL)B$>(B6(R>`#:F/?#P$*;R8B$R(EH68PZ1*`0`.::`$*:"8C$=\*(B[O8J +M`H8Y```WIL`0IL)B1P`UIK`0IKD2'?"2(F#2(NZ0DA228EFV+2LF%`T`-Z8] +M\*`0IJ)B1Y(B6289%-$?!``]IL`0IK(B1Z#,$<"[(+)B1T(B6.(B[[8N*HQT +M`#BF\!"F\F)+,B)9G&.1(@0`.::`$*9"(DOP(`"@B!&`1"!"8DM"(E@F%`@` +M-::@$*:B8@&R(EDF&PK1$@0`/:;`$*;)DN(B6!:.```VIO`0IO)B(3(B69SC +MD2D$`#FF@!"F@F(I'?``HB+O]BH-`#:FL!"FLF(A'?`=\```.*;0$*;28DL` +M-J;`$*;"8B$=\``UIN`0IND2'?```#9!``Q&#!62H0(,"$*@W#(B4DI"@F)' +M)A-MHB)2HLK^%@H*LB+NMBLCPB+NPLS^%IP/`#BF\!"F\F)'`#BFX!"FTB)' +MH.X1X-T@TF)'`#6F8D2\P!"FR1(`-:921+>P$*:Y(@`UIJ(B8*"@%*)B6)`0 +MIIF2`#6F@B)@@((4@F)9,!"F.:(=\`#2(N[V+0*&,0#B(N[BSOX6[@T`.*:@ +M$*:B8D<`-:9B1+R0$*:9$@`UIC(D*5)$MS`P%#)D(?`0IODB'?"R(NZV*R7" +M(N["S/X67`T`.*;P$*;R8D<`.*;@$*;2(D<]\$#N$>#=(-)B1P`UIF)$O,`0 +MILD2`#6F4D2WL!"FN2(`-::B(F"@H!2B8EB0$*:28A$`-::"(F"`A!2"8EHP +M$*8R8A(=\``YIO`0IO#P=/#UP/)B1P`YIN`0IM(B1^#@=.#EP*#N$>#=(-)B +M1X:]_P```#6F8D2\D!"FF1(`-::")"E21+>`@!2"9"$P$*8Y(AWP`#FFT!"F +MT-!TT-7`TF)'`#6F8D2\P!"FR1(`-::R)"E21+>PL!2R9"&@$*:I(AWP`#FF +M,!"F,#!T,#7`,F)'`#FF\!"FXB)'\/!T\/7`0/\1\.X@XF)'!L?_`#9!`#(B +M[@P$0F)'MB,6')H`.J:0$*:"(E*28DX`M)#Y^AC()J0P2H$ +MX.Z0L.X1ZLS*F9()`))D$8(#VKS(\B0?C$^")!^V2`J2)!\6B0FB!+ZL:L(D +M'PSNYQP?\B0?)J\9DB01#/B7"!&B`]H6N@#BH0(`/J;`$*;"1,#R)!&LSP`] +MIJ`0IJGDF.0P6R9+B1 +M?P.A;`-V@`ZR*H,+F8R;O&G"`^@F+`2&^O^LN=(#Z(P='?``@B01\@3`#+Z# +M_@GS_@@`/J8=\`"2`\L+F5;I]:(#W5;:]4;5_PPKLD/H9:CXQO'_PLLTPF2X +M1NC_````-D$`'(DRT@&R(NL`.::`$*9"I'Z)0TI"@@2`O*BB(Q(66@#"(Q*V +M3`K2(Q(6C0WB`XJL/O(C$@SHAQ\=D-(CW-)L?\;A_XA#\@.,#+Z#_@GS_@@`/J8=\``` +MD@1Q"YE6Z?&B!(-6VO%&Q?\,*[)$CF65^,;F_\++-,)CJP;=_P```#9!``P< +MHB+K`#RFL!"FLF)!DB)!')B7*"#2(D%L;N#=(``]IAWP#"[B0X"EC/@&]_\`\LHT\F+K!NS_```` +M-D$`'"XRH+S!*P2A;`.R(NO`PH#2*HZ"+(`P,H#0T&06R`4`/J:`$*:"8Q+" +M(Q(O"9++S))CO(8!``"62P>R8[R1?P.R +MI(RZ(G:`#\(J@PN9C+P6&072`H`F+09&^O\`%DD$X@*`K.X=\`#R+']F#Z7Q +M+`22*IOPF1``/J:`$*:"8Q*"*IOPB!"0B,"'G8?2(^W2;'^&W__B(Q4,OW#N +M$?#N(``^IAWP#"_R0H!E?_C&Z_^"RS2"8[P&X?\````V00`A+00=\#9!`+*@ +M_GSY"X3[HZ"D09"(,!NJL#H0^Y*0E$$PJ8*@R1'*Q*"ZD`O,H*H1D+L1P,@0 +MRG>ZM*JD"ZH+N["X$*"H$+"[D+IWD+D1NK0+N["X$+"JD*IWE[,2P"D1*B0+ +M(B`H$"`B\"HG'?```,`C$2HD"R(@*!`@(O`J)QWP````-D$`(2T$'?`V00`X +MXDP:I2;NK0.Q+02!+P21+@228C."8C2ER0E1A0-AA`-Q,@22H/_A,01!,`0I +M`\+3`_(,'0P;C0N0_Q%`_R#R8Q)!,P0<[^)C$^)C%-(,(`P.X_@(H@P?T_@, +M#&VC^`V3^!2"8Q5R8Q'B8Q`,-V)C&6$&!%)C&D)C&WSU#"3R8QRR8Q_RTPCB +M8R#28QW1-0.R8QZ2(B&RH/@B8\"B(B*B8\&28\*1K0.(PH)CP^),'8&P`^), +M'^),(')CR7%M`V)<%&)<%6)<%F)<%U),,%),,>),,N),,^),-&)<'&)<'6)< +M'F)<'U),0%),0>),0N),0^),1&)<)&)<)6)<)F)<)^),4%),4>),4E%L`^), +M4^),5.),:D),:T%P`^G?LFV"HB,2LJ,>NK-`JB"B98*299H,&H)EA6(C%&DG +M\B,3\F7"XB,1XF5"XL-8TB,2TF6"P@P=TL-`9?7O0F6"#`(=\#9A``P*L30$ +M2.)B(SI2(SO-!*7Q[0P:Y0WN##D,'&"Q!!&#D!&#U!((C.**BI*JD@LC^ +M%L@5PDI08(8$8)<$DDI1@DI24)4%4(0%\DI3XDI44/,%#`[22E50T"6R2E;B +M2E>22EB"2EGR2EK22ENR"E!0>P109P2RR_T6RQ'88\#=$=):&K(:&K):)IAS +MP)D1DEH;@AH;@EHG\B,6T/\1\F2DLB02+`W0NR"R9!)0@`10D110LP10U`10 +M]03B2CA0-@3B2CEB2CI0:10R2COR2CQ0.`10_"722CVR2CY0V"50OP622C^" +M2D!0FP6"H(!R2D%B2D(R2D/R2D322D6R2D;2I%2Q,P.22D?:U()KJ(*A`'(* +M1S(*16(*1O(*1(!W$8!W$'`S$8$U!,!F$;#_$8`S$'`S(!P'<&80D`Q;`.R)1*R8X)B1(YV@`C"(X;`QE7V3`(&_/\,;P`_ +MIN`0IFFE:;5IQ=($9'*D3-+-_5:]*GIUP@22L;8##$T,O@S?HJ*(JJ4`/::0 +M$*86:3BV.0(&X```.Z:0$*:0B$&,>`QZJ4$&H````.")P!;8&8+)]!;(#_") +MP%98.%9\.9($DJD1R5%6B3EB9PAB9RIB9TQB9VYB9Y!B9[)B9]2B(0&RH%`E +M?PEB18JM!>5,`RNZ%BL\5OHWK05B1#:R!#CED@,KRA9,/%9Z.*T%):T!EDH\ +M:=5IY6GUX@0XXD1$T@0X)DU)\@0J)B]S8D6+##B"1))0I2"R!$2E3`3"!%/" +M1$"R!%2R1$&B!%"B1$+P(`!0I2"2!%&21$/EJP!0I2!ER0"M!25B`5;*-48O +M``"M!0PM8D6+XJ`#XD22TD0PTD0Q8D1`8D1!8D1"8D1#I:@`4*4@)<8`K06E +MD0$&(P`,3Z($(`P9#`B@B8."18OR1)*&W_^"!)*I$4^!%"E(*6?`*T% +M9;T`K04E5@%6NB?"!-E6K">QM@/(4:@1#$V"!)(,O@S?@LC[5OCC#!J&E?\` +M`)($DB8Y#H($DB9(")($DI+)^E8Y()$W!``YIH`0IHDQG0B`B4%66!\6B2*" +M!8J9(188"8(EHY@QA[D"1GT`@B6C@)G`@B6CDF$"ASD"!GH`B"&)U9*A`@`Y +MII`0IK8I`H9V`*D1R5&LN:T%)3`#*[H6JQ]6>AL,'N)$-K($.<($.-(%BE"E +M(-"\@V5U`_+*`A8/'U9Z&ZT%Y9(`K06E2`&M!65)`58*&H($DN98"I($DCWP +MICD"QLC_H@22HLKZ5AH;QL7_DB6CB#&7.((,*H9@_ZT%I8D%J4%Z=0P:P@2- +MTL5`XL58LJ,>NK6EF>],&L%P`\)C@N6T[>(G]N)B-=($DIQM\@22YE\%@@22 +MYC@8D@22)ED%H@22)FH,N*46^PL,+,D!*`$=\-($H7S\`-TCG,WB!*$`[B-F +M'B/R!-B"H/V`_Q#R1-C"1*%&!`````"2!-BBH/Z@F1"21-C"1*&R!*!WZVFR +M!*#2)"4`NR/7NRN2I]>PB[!0B*":B&)(@.($VV)(?X*BD.#P=/KUBO^R3]S2 +M!-H;OK"P=+>=$PP9#"*H0<)$H&)$DJ+*^J`IDQWP#!D,(JA!LD3;PD2@8D22 +MHLKZH"F3'?`,:H8A_P``8D22R$$,&PPBPLSZP"N3'?#B):/8M>#=P%9-\PP/ +M^0$H`1WP#"K&%O^B!-N"!-J@B,!6N+X,$AWP#"J&$?\,*D80_P`,*L8._PPJ +MA@W_#'I&#/\`#"K&"O\,*H8)_PPJ1@C_``PJQ@;_#"J&!?\,>D8$_P`,*L8" +M_PPJA@'_#"I&`/\`#"K&_OX,*H;]_@P:1OS^``QZQOK^#'J&^?X,>D;X_@`, +M&L;V_@PJAO7^#'I&]/X`#'K&\OX,2H;Q_@``-D$`#!K"HIS*4J)%S3(%E#`W +M!%8C"H(BR4(%E'SWDJ?7`$0CAR0"AB,`#`AB!90,3;$X!`!F(V!FL"!FH+IF +MTD8>@D8<@D8=L@4LXJ#^TJ#]"[L6&Q.R!2RRR_T6BQ+R!:1W[S:R!:0R(LD` +MNR,WNRJP^[`@_Z":_X)/@#(%SX)/?S!`=$I"P$2`LD30\@7.LL,!L+!TMQ\" +MLD7/,@6U`#,CG'.R!;4`NR-F&QKB!R54\R%5@R55#R%5GR55'B!;0`[B/B1:1R1:72!;;2 +M1::R!;>R1:R!9BR1;@R!:1WXQEB!:3B)2(`9B/G +MM@U@1K`@1*":1*($@!:Z"J$&!*)51J)51Z)52*)527)%E')%E8)%EH)%EX)% +MF)(E'PP"&YF291\=\`"R!:1WZQEB!:3R)2(`9B/WM@U@1K`@1*":1*($@!:Z +M#6(%E*(E(@!F(Z>V#V!&L"!$H)I$H@2`/?`6N@F2!94`F2,6:0BB!94`JB-F +M&H:R!B54BB54ER191R196"19:"19>"19B2)1\, +M`AN9DF4?'?"R!<^"1'^PT'3:TLK=8DW0T@7.&[NPL'2PW<`67?.R1<_Q!@3R +M54;R54?R54CR54ER191R196"19:"19>"19CB)1\,`AONXF4?'?`R!LF4XH@>ZHLK^%DH.#`D,7IF5,F5% +M\@?4#`;2H/CRS_X67PY)`4>S7`P/,$3`1@$``!O_1Q],@B*B#`H6*/\ZSP8# +M````LF5,DB*B&ZJ7NN"]"L/["(T+X_@4T_@8B<5B90R2(J*"H`B7.-F1.01V +M@`V")4,+F8"`%!:(_!99_,;Z_P!(`9(G(YN\@?4H_L2D_L4P@?T@_L5"__PWH/3^QW#^QZR93@=\(("BK$& +M!*%5`[QXP@>PP+J3G0N&P?\``!9C\9(G(@N#"YF#^0CC^133^1B9Q6G%\BPP*N3G0I&L_\`-H$`K0+E.P'150-!;0,L +M&S%L`VSZ##Y1,P,,!L*B<,K"_0:2)?!C_P'C_P.@F1"29?""(\*)$7(,0Z(, +M7Y(,8W/_!;/_!H(,/G(,A*/_$I/_%(/_%7/_'O)D.-F48F0\HB(5L@R$#)>S +M^@BB9$*2(L6"(L+Q.@2M!IJ(@F1'\F1(LB*BTB*CX_H#"[L+W<"[$=/[#+)D +M2:)D2I(B())D4V)D68(B'X)D6``WIO`0IN$[!.)B$=(B$=)C0HALJ'RX?)AL +ML)F"H_@(D_@0@F-3<@SA=^<:X@SA\J)PTBPF`.XC(.Z@\.Z`XBXZX-V`TF-2 +MH@S!LJ)P@BPF`*HC(*J@NJJB*CJJB()C3OCBZ&R]!MCR\.Z"'.KC^Q#3^PBR +M8TBB8U2(;`P;@(`D@F-&^'SY(6G"8D(.8D(/%N\3R6$,#_E1!@0`B%&R0@Z8 +M(1N(B5&0B,`6*!)B0@_"(J(,"A8\_NT&#+UC_0JS_@9C_@>S_1%C_15C_@SI +M,=E!!@4``(C"&XB`@"2)PK)"#_(BHANJ][JQF,+!.00`&4``VZ%V@`GB(TT+ +MS.<-!(P(BH@R)YSD7D3D$=H`+TB1#"YG0T!2,;8Q)1OO_````^,+S_!+" +M9$S@$*9V@!/")>?)`9@!D)`4F0&(`8+(_1:8\$;Y_P#(87(A`=(L!N(L!ZT" +M"]T+[N/]"+/]$K/]%=)D3.42`=%O`V)D17)CPN(B%.DDPB(5T,P@PF1"LB1" +MHB(5HF1"DB1":<)B0@YB0@_R)?`<"(#_(/)E\!WP-D$`DM(",@FZ#`T6XPK2 +M8@:"`HUBH`$6&`VB"<_Q/`2L*K()SS%"!+++_Q9K%<()SZ%$!,+,_A9<%>() +MSX%#!.+._18^%/ERC0(,"@P;,J!^=J-@P@*-?0I-"A: +MG,8R";["";[B";YJS`O,:N[C]0``'$``^Z$P_\#S]00;9IQT,@F_\@F_2C,S +M]0P+,P`30`#KH?#NP./U$`R$9[0$&Z=BH`!2:"1+B!WP``P%QNK_V7*""_^(>?UT-X_4`&T065@#R%W_S]1"V9`4;9BMW +M#`128B1+(AWP#`7&]_\Y_X%*!(EBQMS_H4L$J6+&VO^Q3`2Y +M8L;8_\%-!,EBQM;_````-L$`,6T##`=1;`/2(A+"HG#*0M)E@K($8*($89T' +ML_D!H_D#DF6+@B(A@F6,\@1D8@1(X@1+T@0\8_\#L@1,H@1&X_\&T_\(D@1' +M@@1)L_\8H_\98@1:D_\;@_\=8_\>\F6-XB(3XF7">.2(LFB +MH`"<^=*F/-#2@':`%((BPI(M?XJ9F?."(LD;JM+-)(>Z`@;Y_W)C$')C$7)C +M$G)C$W)C%)(4'-$&!*QYHA0<C^!"3^`B"94CR!&0+_Q:/ +M#ASLPF54^&3P\"3R94;H`N(N`@?N"X($9"88-I($9"8Y,+$U`X+5!*(B&:)E +M@)(B&I)EP/(B&_D(XB(HFN`'?"R!$J,2\(" +MBA8\_.($>E;>^_($>U9_^YAD#(B7N+#"+=T,3I+5!.#,(,)MW;(B&;)E@+$U +M`Z(B&J)EP((B&XD)\B(<\F-`XB(?XF-8PB(=PF5`HB(>HFN`'?``@@1Z5MCC +M@@1[5GCC@@1*%E@`@@**%@A1H=T#H)D@1HG_T@1D5HW>@@*.%GA-H@*+#!F@ +MJ9.C]@0&=?\`#,JB951R94<&Q/\`L@3A=^L5\@3AXB0F`/\C(/^@RO_R+SKZ +M[N)E4I($P8(D)@"9(R"9H,J9DBDZFHB"94Y&KO^B!&06RC_2!&0+W19-0(($ +M9(+(_1:X/Y($9)+)_!8I/@P*H_81QOS^HJ,HJJ(6:LMB&@"""@@IH7G!6;%R +M&@%2&@,B"@P`B".`@$0C^`4B&@(I08)C%6)C%G)C%WC!(F,84F,9@@1***%8 +ML5:(QX(*#!8HQXA!:3&`AL`6B,:2(A5B!(1C^0B28T*""@B2(L(`B".`B+`@ +MB*#JB((H@:D!FHB"8T1B*WV(DI@Q\&80@_848F-&:)/7F06"(037&!.YD:T" +MY5O_N)'"HG#1!@3BIC1\#Z@!DJ-(:9/26@#26@+28Q:B&@*B8QA&_OX``**C +M**JB%OK`8AH`@@H(><%9L2FA4AH#(@H,5$`B".`@$0C^`4B&@&"8QIR +M8QMXP5)C'&)C'2)C'H($2EBQ**%6&+V""@P6N+R(46DA@(;`%AB\DB(58@2$ +M8_D(DF-"@@H(DB+"`(@C@(BP((B@ZHB"*(&I`9J(@F-$8BM]B)*8(?!F$(/V +M%&)C1FB3UYD%@B$%UQ@4N9$@HB!E3_^XD<*B<-$&!.*F-'P/J`&2HTAID]): +M`-):`M)C':(:`J)C&T;4_@``HJ,HJJ(6>K9B&@"""@@IH7G!6;%R&@%2&@,B +M"@P`B".`@$0C^`4B&@(I88)C)6)C)G)C)WC!(F,H4F,I@@1***%8L5:8LH(* +M#!8XLHAA:1&`AL`6F+&2(A5B!(1C^0B28T*""@B2(L(`B".`B+`@B*#JB((H +M@:D!FHB"8T1B*WV(DI@1\&80@_848F-&:)/7F06"(0;7&!2YD2"B(.5"_[B1 +MPJ)PT08$XJ8T?`^H`9*C2&F3TEH`TEH"TF,6HAH"HF,81JK^``"BHRBJHA;Z +MJV(:`I(*#((*"%FQ*:%2&@,B&@$`B".`@$23^`62&@""8RIB8RM28RR28RTB +M8RZ"!$I8L2BA5GBH@@H,%ABHF7%I@6")P!9XIY(B%6($A&/Y"))C0H(*")(B +MP@"((X"(L""(H.J(@BB!J0&:B()C1&(K?8B2F''P9A"#]A1B8T9HD]>9!(B! +MUQ@3N9&M`N4V_[B1PJ)PT08$XJ8T?`^8`6F3TED`TED"TF,=DAD"DF,;!H/^ +M``PZ1K[^FJ+&.?^:HD9J_P":HL::_YJBALO_``#R`HOPZX.M#L:U_@""%%R" +MV(`6:`NB5%T&2?X`DA1>T)G`%ND*HE1?1E#^`(($T**C.*JB@(<$%KC)FJ*& +M)?\`@@30HJ,XJJ*`AP06Z-2:HD92_P""!-"BHSBJHH"'!!8HX)JB1G__`(($ +MT**C.*JB@(<$%FCKFJ)&K/\`@A1LUQA^HE1MQBW^DA1NUQEYHE1O!C;^@A1D +MUQAUHE1EQB?^DA1FUQEQHE1G!C#^T@3BH@3"UYHF#`H&!/\``)($XH($TI>8 +M)PP*!@#_``"B5%Q&&_X``*)47H8D_@``H@3")HH%T@3B)HU5#"I&]_Z2!.*" +M!,*7&"FB!,(FBD<,*D;R_J)4;`8._@"B5&Z&%_X``*)49$8*_@``HE1FAA/^ +M``#2!.(FC06"!-(FB",,*D;F_M("BPP9#`K0J8.&R/X,&L;A_@""!.(FB+$, +M&L;>_@`,&D;=_J"9$,9%_@`V00`,F``XIB`0IAWP````-D$`F-*(L@P&ES@" +M!IH`::*XTJBRM[H<(*(@LJ``PB(+V,(E-@"IPNBR&^[ILMC2R++7/.(,%V)" +M!&)"!6)"!F)"!V)""&)""6)""F)""V)"#&)"#6)"#F)"#V)"$((BH_BR06T# +MLJ)8AS\"!I``NE(Q;`/XLA8O)9C5B+(;B)#%@`.*:0$*8+^1;_(Z+)_A::(ZT" +MN+*EO`2R!78':PS"!57"0@IB0@L&`P``X@*(XD(*T@*)TD(+8D(/::*"(J+X +MHCWPAS\"QED`F,*Q.00`&4``IZ%V@`G"(TT+NZ<,!(P;QOO_F*+(LKC"H@(. +MP_D(L_D1H_D9DF(8B%*M`N`(`%8*&[$Y!`R*@@(/\@(.X@(0TB(,@_H(\_H) +MX_H*T_H1=H`(DB.#"[N,.8P;!OS_#+X`.J8,&PP)T@((P@()@@(*\@(+PLS] +MP)N#D_T&P@(.L@(/@_T'\_T,D@($P_T3L_T4@@('\@(%D_T5@_T6R**XLO/] +M%Y("![/\"(("!OC"D_P0@_P1\_P<<_P?L!"FD@((@@()\@(*D_X*@_X1\_X5 +M`#ZFTF-5PF/)N,4,B;BB*^[W/A.B!787:@VR!56R0@IB0@M&`P```-("B-)""L(" +MB<)""_`0II$U`^(IP>#@9%;>!((%QE9X!,C"&\S`P"3)PG)"#[BB&[NYHJ(B +MHIBBI[D"QJ7_::+XLAO_^;)R0@[B(J/8LN>]`L9__X8.``"8LHC2ES@"AFS_ +M?,(=\````&5`[J(B$J)C@B"B(.4N`+(%RB8[?\(%RB9,2-(%RB9M)D3(;Q_P#R!7;P\@06/]J"!56"0HAB +M0HF&;__E.NZ2(A*28X(&Z?\,`@Q:HD7*'?```,'R`P`\IK`0IJT+G0NPN$$6 +MBP"@D'32H`C28X'BR8!6/MH,`AWPK0)B1@])+ +MB,(%5,)+B9(%59)+BH)52H)52X)53()536)%G')%G4(%5$)%GC(%53)%GR(% +M)B)%H"T&'?!\\AWP#!<&R_\`#`>&R?^B1=1&W/\`DD74AMK_``"21=2&V/]\ +M\AWP```V80`Q.01A;0-!;`,]\':C'*(D0W(F0Y(DPX(D@U@VH'<@D(@@@%4@ +M<%4@%O7_N`*R*P(A,P,'ZUMV@!#B(N?I`=@!T-`4V0'(`28\`@;Z_WS6#"4, +MA_(BW?D1!@$`.!%W@S&H$5"J(*)BW9(BW9)A`8(A`4*CZ&"($()BW7:`#L(B +MWL":(#BB8:&PP"#!NR0XVR +M0Y<=\'SB'?```+)#C$;J_WSB'?`,`K)#C;)#EQWP?.(=\`Q,PD.,QN/_-D$` +M0M(",@3C#/@,`A8#!**E`I($XV*C`@P7)AD]L@3C)BL##`(=\')$S8)$SG)$ +MNP`VIB`0IK:"`H8@`,+"^18,"-($K"K=#`(;W=)$K1WP(D2M(D3-(D3.'?#" +MH0(`/*:0$*:V*0-\XAWPDD2[%ED&LJ("`#NF4!"F]DE5#+F28R*WSB'?``.J8@$*;VP@8B1*T, +M`AWP?.(=\.)$S2)$SL;2_P``4D3-TD3.!M#_TD3-4D3.QLW_#"W21,U21,X& +MR_^21,TB1,[&R/\``/)$S7)$S@;&_PP^XD3-\D3.1L/_#$\,2H0+VQ6@, +MA`P84%B#5S05`#FF0!"F(M("]B160D*U("YE)"K&)"QW)"Q/("]&8_%#("]9*B`HRS`#FF +M@!"F?.*V2`$=\`P"'?!\XAWP?.(=\`R+5SLY4D*L8D+'"0L1&[O\`.:9`$*8,'0P,]B0X4D*L0,V#P&J38D+'PD+$AN;_`!S.5SX. +M\L7]\D*LHD+'@D+$1N'_'-9G%1@2H_":@H(H'U*A`B88-ZBB*JJ:FI()A#%M`YR)P5$$LB(8K0(]\,"[ +M(+G#91\!%DH$?-(=\`"(8JT"O0'@"`",RBT*'?```#6FD!"FQO'_D@(-PJ`_ +ML5($%FD"H@(,)EI!PB(8(*(@L+P@N<-E&P$6N@1\TAWPK0+E'P$,`AWP```` +MT@(,TLW[%DT)XB(8(*(@L.X@XF,,I1@!%LH)(J_]'?``(*(@8D()PD((\B(8 +M\F,,Y18!%AH$(J_]'?``(*(@LB$`PB$!)2`!@A0R`#BFD!"F/?#VV0%M"6)" +M$""B(+*@"J4C`9($D;:9CB"B(&4)`19:^"T*'?```#6FD!"FMBD#?.(=\))" +M!J(4,@`ZII`0ICWP]MD!;0EB0A!&\?\@HB!B0@G"0@BR(ABR8PPE#P$62@%\ +MTAWP`""B(+(A`,(A`648`0P"'?#"!)&VG`T@HB`E`P$62@"@*B`=\``UII`0 +MIO8I!I)"!@P"'?!\XAWP-F$`#`I"HCQ*0J)"!J)"$*)"")($F9)"!X(DKE*A +M`K*D.`N(%D@*F*(JF;J9D@G$,6T#NL(6"08,-W)""=C<"]T6#0EHHBIFNF9B +M!CSLQH(4,J"Z(``XII`0IO;9`;T)H5,$LD(0DB(8H)D@F<,@HB#E`P$6B@9\ +MTAWP``#!5`2R(A@@HB#`NR"R8PPE`@$6F@8BK_T=\```XJ`!XD()TBP-TLW_ +M%GT-:*(J9KIF8@8\%K8)D5$$@B(8K0*0B"")P^7^`!:*$WS2'?```#6FD!"F +MAM;_`#6F8!"FAMO_``"B`A!AN`-7:BN(8B"B(!"Q(.`(`!8:"2T*'?``(*(@ +M90`!K0+E_P"M`J7_`*T"9?\`#`(=\*T"Y?X`D@(01VD0B&*M`KT!X`@`%HH2 +M+0H=\``@HB#E_`"2`A`W:2*"(@8@HB"]`>`(`!8*%BT*'?``B&*M`KT!X`@` +M%CH2+0H=\""B("7Z`)("$#*@!"=I1((B!JT"O0'@"``6.AS/2`@@,K-#20=:.H_(""`RX\/)!AQ\4@@((@()! +M)JB/D@((D))!YKD"H@((L@((<+L@LD((QMW_P@(-S,S2`A#BH.\]\.#=$-)" +M$/("#/+/^Q8_"B"B(+(A`,(A`>7M`(:M_X("#=*@/\%2!!;("I("#)+)^Q8I +M#*(B&,"J(*)C#""B(.7@`!8J#GS2'?``L@(-S*O"`A#2H/?0S!#"0A#B`@PF +M7F&M`K@!R!'EZ`"&I?\`(*(@)=0`%JKPH"H@D````/("""P(@/\@\D((:<-& +MBO^2`@W,J:("$+*@^["J$*)"$,("#"9<;*T"N`'($:7D`&T*1JG_T@(('`[@ +MW2#20@AIPT:$__(""`R(@/\@\D((:<,&C/]\XAWPD@(,DLG[%KD*HB(8P*H@ +MJ<,@HB`EU@`6*@M\TAWP`""B(,*@`,)""=)""+(B&+)C#&74`!9Z!7S2'?#2 +M`@BM`C#=(-)"""75`&T*QHS_````K0*X`<(A`67<`.(4,@P,`#ZFD!"F]MD! +MS0G"0A`@HB"RH`KEWP#R!)$]\/:?`D:2_ZT"9<4`%AKD+0H=\```-::0$*:V +M*0-\XAWPDD(&@A0R#`L`.*:0$*;VV0&]";)"$$;P_PP*HD()K0+20@B2(AB9 +MPR7+`)Q*?-(=\""B(+(A`,(A`:74``P"'?```+($D;:;#2"B("6_`!9*`*`J +M(!WP`#6FD!"F]BD&DD(&#`(=\'SB'?`V80""T@4,&0P%4D(&4D('4D(04D(( +MDD()@B@?0J$""X@6>`R8HBJ9DMD%D@F$HJ/PJK*R*Q\+NQ:;"\BB*LRJS,(, +MA#%M`Z*B.!:I!IQ\X54$TB(8K0+@W2#28PPEP0`6J@E\TAWP`*I"\A0T4,4@ +M`#^FD!"F]MD"D,D@PD(0(*(@LJ`+9@`@8A`$*B.$I"\@1V=^\-@5@$`#BFD!"FA@(```"15P0`.::0 +M$*:,V289<:+)_A:Z";+)_19;#WSR'?!9PPP"'?!9PPP"'?```,("#$*B.$I" +MPLS[%MP2@@1V=^@+D5@$`#FFD!"F!@(`H5<$`#JFD!"FC/D+N1;[',+)_A8L +M'M+)_18-%WSR'?!20@FB0@@`-*:0$*:V*61\XAWP`.(4-,T%`#ZFD!"F]MD! +MS0G"0A"M`K*@#.6R`/($E?:?`L8>`*T"I9@`%CH'+0H=\((4-,T%`#BFD!"F +M]MD!S0G"0A`@HB"RH`WEKP"2!)6VF68@HB"EE0`6V@4M"AWP`))"!D*B.$I" +MHA0TS04`.J:0$*;VV0'-"<)"$(($E;:84B"B(*62`!::!*`J()```(ABK0*+ +ML>`(`!9Z!BT*'?"2(A@@HB!PF2"28PSEF0`6F@DBK_T=\```L5P$HB(8L*H@ +MHF,,(*(@)9@`%AH*(J_]'?``(*(@PB(8PF,,Y98`%FK?(J_]'?!20@FB0@C2 +M!)6VG4<@HB"EBP`6Z@.@*B"0````X@(-%BX'\A0T4,4@`#^FD!"F]MD"D,D@ +MPD(0(*(@LJ`.):(`@@25MIA.(*(@Y8<`%EH$+0H=\`"2H0(`.::P$*:V*TM\ +MXAWPN`&H$0P"L_H,J<,=\,(B&""B(&#,(,)C#&6.`!8J!R*O_1WPZ`'8$0P" +MX_T,V<,=\/(B&""B(&#_(/)C#"6,`!;:!2*O_1WP(*(@LD(&@B(8@F,,I8H` +M%CK3(J_]'?``DB(8(*(@<)D@DF,,)8D`%EH$(J_]'?```+%@1#`+S +M_@SIPQWP`*@!F!$,`J/Y#)G#'?#(`;@1#`+#^PRYPQWP```V00!"H99*0E(4 +M?P`UIG`0I@P90A2`#`@;9T>W4"Q%9[4)DD(-8L?6L2GSB'?```&!! +M05`H=4HB!V8"("!@(""T*1,,`AWP`"D3#`(=\```((!T()B$F0.)$PP"'?`` +M`#9!`$*AEDI"4A1_`#6F"0@P@5J!2)20,)U`@=+SR@)(1<)D@`#FF8!"F``)`?.)@@)&< +MB!WP+#JG%D,,6[)"#(D#B1,,`AWP?/(=\```4$AT8"%!2B('9@(@(&`@(-0I +M`U`@=19B!("2$7"9(``YIF`0I@`"0'SB8("1G'@=\+%>!()"#``[IB`0IB"C +MQ:Q*?.(=\```8$%!4"AU2B('9@(@(&`@(+0I$PP"'?``*1,,`AWP```@@(0@ +MF929`XD3#`(=\```-D$`0J&62D)2%'\`-:9P$*8,&4(4@`P(&V='MU`L16>U +M"9)"#6+'W,8```""0@TL*6!WPL5\$ +M@D(,`#NF(!"F(*:5K$I\XAWP``!@04%0*'5*(@=F`B`@8"`@M"D3#`(=\``I +M$PP"'?```""`E"":M)D#B1,,`AWP```V00!"H99*0E(4?P`UIG`0I@P90A2` +M#`@;9T>W4"Q%9[4)DD(-8L?U +M"9)"#6+'W,8```""0@TL*61WPP5T$ +M@D(,`#RF(!"F(+'EK$M\XAWP``!02'6`)A!*(@=F`B`@8"`@M"D3#`(=\``I +M$PP"'?```+*C_B"G0?""$9*A_@P"D(@0L*H0J0.)$QWP```V00!"H99*0E(4 +M?P`UIG`0I@P90A2`#`@;9T>W4BQ%9[4)DD(-8L?("9#%E!)%F!.<]"0`SIO`0 +MIAWP'?``.::`$*8=\+%G!``[IJ`0IAWP`#9!``P6,M("HA-LHE-2DA-MDE-3 +M@@/W#`5"H0(6"`4`-*:0$*;V*4,6208`-*:0$*;V*4$6&0K"H`+"0[JR$U.P +ML4&R4U,@HB`E?OYRH@+B`[K1M@/!:`06'@;R`[HF'VJ"`[HF*!0,`AWP`'SB +M'?!20[K&\_]\XAWP``"2HP(`.::0$*:Q:02VB0Q\XAWP`%)#NL;K_P``L+F0 +MP@L`PD/(L@L!LD/)H@/X%JH'`#VFP!"FP,A!%NP&?.(=\``\II`0IK99&7SR +M'?`````\II`0IK99+GSR'?!B0[J&V?\`DD/(4D/)X@/()DYO\@/X%I\&`#VF +M@!"F@(A!%M@%?.(=\```DD/(4D/)H@/()DIOL@/X%IL&`#VFP!"FP,A!%MP% +M?.(=\```8D.P4D.QT@/Z%GT:X@/V%IX;`#>FD!"FMDD"QF,`DD.T\@/>%D\& +MK0*E*``6R@4M"AWP`&)#L%)#L8(#]XQ(D@/Z%JD:H@/V%HH8`#>FD!"FMDE, +M?.(=\&)#L%)#L;(#^A9[%\(#]A9L&@`WII`0IK9)`D94`))#M-(#WA;-"ZT" +M)2,`%DH++0H=\`#B`\@F3DT`-Z:0$*:V235\XAWP``"20[3R`]X6WP`@HB!E +M(``62@`M"AWP`((#R(+(_!;X#``TII`0IO8I`H8E`'SB'?"0H`20L02R0[.B +M0[)20Z_"`\@+S!9\%=(#R-+-_1;M%.(#WQ:.&/(#R`O_%L\2@@/(@LC]%C@2 +M`#>FH!"FMDH"1D\`MCH<#"H`-*:P$*:V*P(&50"BR@&2H!"GN0*&50!62_ZB +M0H\,`AWP`*(#R*+*_!::WP`WII`0IK9)`H8U``P"D+`$D,$$PD.SLD.R4D.O +M'?"20[/2`_<6+1,`-*:0$*:V*0(&/P"20[+B`_D6GA(`-*:0$*:V*0)&/P"2 +M0Z_R`\@+_U9?VI%J!``YIJ`0IAQ(IS@"1CD`?/(=\'SB'?```*(#]A9JY@`W +MII`0IK9)5'SB'?``?.(=\%)#M(:3_P``4D.T1K+_``"R`_86:^D`-Z:0$*:V +M26Q\XAWP`,(#]A;0:B`J`6J@4B`EX;(@`XID`0IE%M!$`Q0284"0P)?.(P*8,=\`!!;`0]\':B +M*P`TIB`0IB`BU2HC`#2F,!"F,#+5.B(`-:8P$*8P/D$Z(@`UIC`0IC`^03HR +M#`E\XC`I@QWP#!(&Z?\``*("H`PKC)K"`EL,,L`K@P;D_PPBQN+_`#9A``P\ +M#"H,!G%P!+T#70)"U0*"!+HQ;@0A;P2\F`P=@@2Z<7$$(7($)AA8%@L("XL6 +MN`KV2P6V*P(&-``,`F)$P&)$P6)$PF)$PV)$Q6)45&)451WP````%CLPR0$+ +MFQ8),O9+!;8K`D:(``P"HD3`HD3!8D3"8D3#8D3%8E148E15'?`6NQP+BQ8H +M(O9+!;8K`L:8``P"8D3`8D3!8D3"8D3#8D3%8E148E15'?``8D3"8D3#8D3% +M8E148E15D@6*%KDBL@2P/?`6JR'21,"B1,&M!:5<_A9*!2T*'?``8D3%8E14 +M8E15X@6*%LXC\@2P"_\63R+"1,#21,&B1,*B1,.M!:59_KQ*+0H=\*T%8D3` +M8D3!8D3"8D3#8D3%8E148E15I5?^%DHB+0H=\`""H0(`.*:0$*:V*6]\XAWP +M#!JB18V2!.(6R2T`,Z:0$*:V20(&E`"21,^R!.<6.S,`,J:0$*:V20+&J`#2 +MH`&0P`20X03B1+[`S9/"1+^"!*P,SX<_`H9L`)%S!``YIL`0IK9,`H9L`,)$ +MS%"E(+*@!>5O`A8*2BT*'?``DD6-%EDO#`S"18ZB!.(6ZBP`,Z:0$*:V20*& +MD`"21,^R!.<6FSX`,J:0$*:V20+&DP`,'9#`!)#A!.)$OL#-D\)$OX($K`S/ +MAS\"1FP`D7`$`#FFP!"FMEP"1FP`PD3,H@3,HLK\%FI$HJ,"`#JFD!"FMHD" +MQO@`L@3,LLO]%NM+T70$#&S0V9#2'0#25$S"5$WB!8T6ODL`.J:0$*;VB0+& +MJ0!\XAWP8D3"8D3#8D3%8E148E158D6-8D6.\@6*%M\D@@2P"X@66"+)`:)$ +MP-)$P:T%Y4'^%HH3+0H=\````*T%8D3`8D3!8D3"8D3#8D3%8E148E15I3_^ +M%@HH+0H=\`!B1,5B5%1B5%5B18UB18ZB1,R2!8H6.2ZR!+`+NQ:[),)$P-)$ +MP:)$PJ)$PZT%)3S^%OH2+0H=\*)$P-)$P49X_Z)$P*)$P09V_ZT%8D3`8D3! +M8D3"8D3#8D3%8E148E15Y3C^%EHO+0H=\`#21,#"1,&B1,*B1,/&=?\`PD3` +MPD3!HD3"HD3#QG'_`,%U!``\IL`0IO9,`@:3_WSR'?``4*4@97\`%NHHH"H@ +MD````*T%#"W21,#21,%B1,)B1,-B1,5B5%1B5%5E,OX6BA0M"AWP`*T%#"[" +M1,#"1,'B1,+B1,-B1,5B5%1B5%4E,/X6VAPM"AWP`'SR'?"!;P0`.*;`$*;V +M7`)&D_]\\AWP`)($XA89+@`SII`0IK9)`D:$`))$SZ($YQ:*+P`RII`0IK9) +M`@:O``PD])$OY*A`@`YIH`0IO8H`H:5`'SB'?```&)$ST9._P``8D2^ +M8D2_!CC_R0'21,"B1,&&=?^BH0(`.J;`$*:V+`(&@@#"18Z&/?_)`:)$P*)$ +MP89M_[($XA:K,0`SII`0IK9)`D:4`))$S]($K`S,USP"QDP``#>FP!"F]EP" +MQDP`?/(=\/%V!.*@?O#YD/(?`/)42N)42P`ZII`0IO:)`H8K`'SB'?```-)$ +MP,)$P:)$PJ)$PP9L_P!0I2"E80`6*@N@*B"0````J`$,*Y"K@Z)$S(*A`@`X +MII`0IK8I`H9S`!;)'^$&!.)45-%W!``]II`0II#,019L''SB'?#R!.(6CR<` +M,Z:0$*:V20(&:P"21,^"H0(`.*:0$*:V*0*&B@`6B2H,*9)$S*T%#"OE+P(6 +M2BLM"AWP`,)$P,)$P:)$PJ)$PP9(_P!B1+YB1+]&"O]PN9"R&P"R5%"B!,QF +M.B/"H@(`/*:0$*:V20M\XAWP?/(=\`P"'?#1>`30V9#2'0#25$]0I2`E20`6 +M:OZ@*B"0````?.(=\`"M!0QKY2@"%JHA+0H=\```,J;`$*:V7`+&LO_BS/P6 +M'AW"1,SR!,QF/WA0I2"RH`$E)@(6R@8M"AWP`)$W!``YII`0II")019($7SB +M'?``L@2L#,JWNE_!03"1,P`/::0$*:V.0+&7``6>2,+ +MZ1:>(9$&!))458%W!``XII`0II#\01:/'7SB'?``?/(=\&)$SX9)_P``K04E +MU/T6^O(M"AWP?/(=\'SB'?"A=00`.J;`$*:V3)]\\AWP8D2^8D2_AD;_K04, +M*^4;`A;J&BT*'?``P7H$#(O`R9#"'`#"5$RR5$U&S_[2H@(`/::0$*:V20*& +M.@#Q>P1,CO#YD/(?`/)42N)42X9Y_P!\XAWP?/(=\'SR'?!\\AWPPA14D-94 +MT,P@PE14HA14D+!4@+L1L*H@HE14@A14@E15K04,"V44`A:*#BT*'?``8D3/ +M1CK_``#B!,R0IB3BSOT6#A:!=`0,;X"*D((8`()43/)43<*@?I#3))"P).%V +M!'"[D+(;`.#=D-(=`-)42L)42[)44*($S&8Z'_*B`@`_II`0IK9)!WSB'?!\ +MXAWP@7@$@(F0@A@`@E1/4*4@I2L`%NK@H"H@D````&)$OF)$OT8C_V)$ST8[ +M_P!B1,_&8_]\\AWP?.(=\```L08$LE14H@2L#,FGN5G!`2PYQ2PDA3Q>P2PQ"1PS)#"'`"BSS"@F9#P +M[I!0I2"2&0"P\!3B'@#B5$J`_Y#R'P#25$O"5%"25$[R5$\E`P`6>K@M"AWP +ML7X$#/BPNI"R&P"R5$R"5$U&I/_1?@0,_-#9D-(=`-)43,)43<;B_S9!`*T" +MY:7]C$HM"AWP``"BHDFJHH(*FPP,DJ$"%K@&`#FFL!"F?.*V*P$=\+)*<-(* +M<.*B`A;M!@`^IK`0IGSB]DM-LDJ!`#FFL!"F?.+V*S6,NP`YIK`0IGSB]BM% +M&[NR2FT`.::P$*8,CWSBMBL"'?``LDIO@@ICAS\6#`+"2H+"2HP=\``=\``` +MPDJ!!NW_'?"2"IP,`@P;G!FR2H*R2HP=\!WP``Q-TDJ!AN7_#`+"2H+"2HP= +M\```-D$`K0(,.R75`8PJ+0H=\,*B2R8N))(*A9)"![(*?;:;#*T" +MI<_^C$HM"AWP``#1;0/"(A@,`LG-'?#B+"\F'A:8HBJ9NIF2"<3&\O\````] +MII`0IL;K_P`]II`0IL;M_P``-D$`#`D\^J)""))""9*G()J"@B@?TJ$")AAD +MJ*(JJIJ:D@F$L8D$DD($`#NFD!"FPJ70RK*VV0-\\AWPDD(0Z-LF'E>8HBJ9 +MRIF2"3R20@:BHE"JHN(*>R8N+9(*A9)"![(*?;:;#*T")<7^C$HM"AWP``#1 +M;0/"(A@,`LG-'?``/::0$*:&YO_B*R\F'A68HBJ9RIF2"<2&\/\``#VFD!"F +MQNG_`#VFD!"FQNO_```V00"2H_":@H(H'ST"LJ$")AADJ*(JJIJ:D@F$#!H, +M`E%M`T*B.$I#K%F1400B0P0B0P4B0P:R!)VR0P)A@:F*,ZF:J9D@F`G'FQ502B(Q@,`K"J(*G% +M'?```#^FT!"F5FW^ZO/R#WH`_R/PLK,`.Z:0$*9\\IP)@LG_%K@5HLG^%IH7 +MLLG]%OL*'?#J0\)#!L)#!\)#$,)#")(4,@`YIN`0IH(4,W&*!(<^#GSR'?`` +M```_II`0I@;4_WKNX@X`X)0$X'4$X(`4@D,)(# +M!;(C&,#=`#_(#$(R?K0,EBOZ,*BT*'?`,`AWP +M``"!600B(QB`(B`IQ0P"R<7)Q1WP```_II`0IE9I^:($>@"J(Z"RLP`[II`0 +MIA9)#K9)`H8W``PFH8L$)AD+LLG^%ML1@LG]%N@6D@,%%LD0`#^F\!"FMB\" +M!CP`)VX1LA0V`#NFD!"F]MD"D,D@PD,0P@,)PLS^5NP)D@,%T_H6@B,8D_H8 +M\_H:H(@@B<7B%#0`/J90$*;V10+&6`!\\AWPL5$$HB,8#`*PJB"IQ+)_A;>$_+)_1:O +M#I%6!((B&)"((()G##?D)PP"'?``L5($DB(8K0*PF2"9QXAR0,($#!O@"`", +M6BT*'?`````W9-?"$S8`/*:0$*8]\/;9`5T)4D(0T@.9MIV^X@(0%H[[K0)E +M+_X6"OLM"AWP`#SX@D((\@.9MI\\K0+E+?Z\2BT*'?`````VII`0IH;3_Z(3 +M-0`ZIF`0IO:V5!;Y!L%3!+(B&,"[(+G'K0*E-/X6R@=\TAWP```VII`0IK8I +M!WSB'?!\\AWPDD(&-V09TA,V`#VFD!"F]MD!70E20A#B(ACIQPP"'?#B(ACI +MQPP"'?!\\AWP``"!6P3R(AB`_R#YQP`VIF`0IK8F$7SB'?"ACP22(AB@F2"9 +MQP;C_ZT"B'(,&T#"!.`(`+QZ+0H=\*T"#!N(<@R,P,80X`@`O&HM"AWP`+%< +M!)(B&*T"L)D@F<>(G)B%S(`-J9`$*92%S." +MQ+E7M"H66`L@9*!B)B1@3#1@(#06P@B`LA&0NR``.Z:`$*8``D!\XH"@D19Z +M!AWP?/(=\`P"06T#]B,%*<0,`AWPPJ$#`#RF8!"F,6P#X3D$MB8&#`8,C=)C +M@6/R&RG$(J``=JX3@B.88B.84B.8\B.88B0[&R('Y@,,`AWP%V80HJ$"`#JF +MD!"FMBD$?.(=\``,`AWP8%1T@"%!6B(':`(@(&"\A("T$9"[(``[IH`0I@`$ +M0("@D9QJ?.(=\-%=!``]ID`0ID#!Y:S,?.(=\```8%#5@$%!6D0':`)`0&"" +M!YP]\/8H!?`B$?!$$2"0U$`@M)/R#,;._T`HA$!`=`;W_P```#9!``PI%E0$ +MG)B%S(`-J9`$*92%S."Q+E7M"H66`L@9*!B)B1@3#1@(#06P@B`LA&0 +MNR``.Z:`$*8``D!\XH"@D19Z!AWP?/(=\`P"06T#]B,%*<0,`AWPPJ$#`#RF +M8!"F,6P#X3D$MB8&#`8,C=)C@6/R&RG$(J``=JX3@B.88B.84B.8\B.88B0[ +M&R('Y@,,`AWP%V80HJ$"`#JFD!"FMBD$?.(=\``,`AWP8%1T@"%!6B(':`(@ +M(&"\A("T$9"[(``[IH`0I@`$0("@D9QJ?.(=\-%>!``]ID`0ID##Q:S,?.(= +M\```8%#5@$%!6D0':`)`0&""!YP]\/8H!?`B$?!$$2"0U$`@M)/R#,;._T`I +ME$!`A`;W_P```#9!``PI%E0$G)B%S(`-J9`$*92%S."Q+E7M"H66`L@ +M9*!B)B1@3#1@(#06P@B`LA&0NR``.Z:`$*8``D!\XH"@D19Z!AWP?/(=\`P" +M06T#]B,%*<0,`AWPPJ$#`#RF8!"F,6P#X3D$MB8&#`8,C=)C@6/R&RG$(J`` +M=JX3@B.88B.84B.8\B.88B0[&R('Y@,,`AWP%V80HJ$"`#JFD!"FMBD$?.(= +M\``,`AWP8%1T@"%!6B(':`(@(&"\A("T$9"[(``[IH`0I@`$0("@D9QJ?.(= +M\-%?!``]ID`0ID#&E:S,?.(=\```8%#5@$%!6D0':`)`0&""!YP]\/8H!?`B +M$?!$$2"0U$`@M)/R#,;._T`JM$!`E`;W_P```#9!``PI%E0$G)B%S(` +M-J9`$*92%S."Q+E7M"H66`L@9*!B)B1@3#1@(#06P@B`LA&0NR``.Z:`$*8` +M`D!\XH"@D19Z!AWP?/(=\`P"06T#]B,%*<0,`AWPPJ$#`#RF8!"F,6P#X3D$ +MMB8&#`8,C=)C@6/R&RG$(J``=JX3@B.88B.84B.8\B.88B0[&R('Y@,,`AWP +M%V80HJ$"`#JFD!"FMBD$?.(=\``,`AWP8%1T@"%!6B(':`(@(&"\A("T$9"[ +M(``[IH`0I@`$0("@D9QJ?.(=\-%@!``]ID`0ID#(=:S,?.(=\```8%#5@$%! +M6D0':`)`0&""!YP]\/8H!?`B$?!$$2"0U$`@M)/R#,;._T`KQ$!`I`;W_P`` +M`#9!``PI%K0%G)B%S(`-J9`$*92%S."H'Q7M$!'."H@9*!B)B1@C@5@ +M3#1@(#06D@>`PA&0S"``/*:@$*8``D!\XJ"PD19+!1WPX5T$`#ZF0!"F?.)` +MT>6<[1WP`'SR'?`,`@P(06T#C&,+\Q8?"R8C5BG$#`(=\```0"B$0%%D0(`$ +M6DB2!YSV*07P(A'P1!$@H-1`(+2C\@S&\?]@5'2@(4%:(@=J`B`@8!9D_8"T +M$9"[(``[II`0I@`$0)"@D19J!GSB'?```,*A`P`\IF`0IC%L`^$Y!+8F!@P& +M#(W28X%C\AN#\APB9`PBH`!VKA."(YAB(YA2(YCR(YAB)#L;(@?F`PP"'?`7 +M9A"BH0(`.J:0$*:V*01\XAWP``P"'?"#\APIQ`P"'?!@4-6004%:1`?I`@;3 +M_T!`8(;1_P```#9!``PI%K0%G)B%S(`-J9`$*92%S."H'Q7M$!'."H@ +M9*!B)B1@C@5@3#1@(#06D@>`PA&0S"``/*:@$*8``D!\XJ"PD19+!1WPX5X$ +M`#ZF0!"F?.)`T\6<[1WP`'SR'?`,`@P(06T#C&,+\Q8?"R8C5BG$#`(=\``` +M0"F40%%T0(`$6DB2!YSV*07P(A'P1!$@H-1`(+2C\@S&\?]@5'2@(4%:(@=J +M`B`@8!9D_8"T$9"[(``[II`0I@`$0)"@D19J!GSB'?```,*A`P`\IF`0IC%L +M`^$Y!+8F!@P&#(W28X%C\AN#\APB9`PBH`!VKA."(YAB(YA2(YCR(YAB)#L; +M(@?F`PP"'?`79A"BH0(`.J:0$*:V*01\XAWP``P"'?"#\APIQ`P"'?!@4-60 +M04%:1`?I`@;3_T!`8(;1_P```#9!``PI%K0%G)B%S(`-J9`$*92%S." +MH'Q7M$!'."H@9*!B)B1@C@5@3#1@(#06D@>`PA&0S"``/*:@$*8``D!\XJ"P +MD19+!1WPX5\$`#ZF0!"F?.)`UI6<[1WP`'SR'?`,`@P(06T#C&,+\Q8?"R8C +M5BG$#`(=\```0"JT0%&$0(`$6DB2!YSV*07P(A'P1!$@H-1`(+2C\@S&\?]@ +M5'2@(4%:(@=J`B`@8!9D_8"T$9"[(``[II`0I@`$0)"@D19J!GSB'?```,*A +M`P`\IF`0IC%L`^$Y!+8F!@P&#(W28X%C\AN#\APB9`PBH`!VKA."(YAB(YA2 +M(YCR(YAB)#L;(@?F`PP"'?`79A"BH0(`.J:0$*:V*01\XAWP``P"'?"#\API +MQ`P"'?!@4-6004%:1`?I`@;3_T!`8(;1_P```#9!``PI%K0%G)B%S(` +M-J9`$*92%S."H'Q7M$!'."H@9*!B)B1@C@5@3#1@(#06D@>`PA&0S"``/*:@ +M$*8``D!\XJ"PD19+!1WPX6`$`#ZF0!"F?.)`V'6<[1WP`'SR'?`,`@P(06T# +MC&,+\Q8?"R8C5BG$#`(=\```0"O$0%&40(`$6DB2!YSV*07P(A'P1!$@H-1` +M(+2C\@S&\?]@5'2@(4%:(@=J`B`@8!9D_8"T$9"[(``[II`0I@`$0)"@D19J +M!GSB'?```,*A`P`\IF`0IC%L`^$Y!+8F!@P&#(W28X%C\AN#\APB9`PBH`!V +MKA."(YAB(YA2(YCR(YAB)#L;(@?F`PP"'?`79A"BH0(`.J:0$*:V*01\XAWP +M``P"'?"#\APIQ`P"'?!@4-6004%:1`?I`@;3_T!`8(;1_P```#9!`%P+#`4R +MHH@Z,JT#4F.]4F.;4F-Y0B*DY<\###9"8J22(J2"I``,))*R`T"R0TQ20HM9TF)# +MFJ(#0*+*_!;Z$L(#0)S,T@-`"]T6W0[B`T#F3@_R`T"F+PF!D`2)4L8#```` +MD@-$DLG]%FD,H8$$J5*M`N(#6^)#2-(#7-)#2<(#6,)#2K(#6;)#2V7T^JT" +M)1+[K0+EJOOR`YH,&/+/_19/"Y(#X0PBD"B3'?``DD,U%BD)'`S"0V#"0V$` +M.Z:0$*:V*01\Z@;"_PP7"]D6C0GB`W<6K@<`.Z:0$*:V*2I\ZD:[_P!20S7" +M0V#"0V%&\O^M`D)#.((3*()3#O(3*?)3#^4)_`P*QK'_%OD*0D-`P@-`%BP, +MT@-`"]T6O0SB`T"2IP(F+G7R`T`F/W\,"L:G_X&#!(E21LW_D88$F5)&R_\, +M0AWPPD-@PD-AQMK_``!"0T`&[O^M`F6>^I(#X0P8#"*0*),=\`!20T`&Z/^M +M`D)#.$)#.5)#2%)#25)#2E)#2^7D^JT"I0+[(*(@YR`V216B`V0]\*+*_19Z$\(3*,)3#K(3 +M*;)3#ZT")=[[K0)20T520T;E&_Q6&L#2`R0,C->\`D8Y`,9H`%)#1\:H_P!2 +M0T<&KO\```"20V2<"=+)_Q;]'>+)_A8N(/+)_19_'I(3*))3#H(3*8)3#ZT" +MY=C[K0)20T520T:E%OQ6VKKB`R0,C>>]`D8X`(9B`*T"I=K[5GJYT@*,%DT= +M!EP```!20V2R$RBR4PZB$RFB4P]&L_\``%)#1T;%_P``4D-'!LK_``#2$RC0 +MT4'24P["$RG"4P]&E?\``/(3*/#Q0?)3#N(3*>#A0>)3#X:/_Y(3*))3#H(3 +M*8"!08)3#P:+_P!20V2R$RBR4PZB$RFB4P]&UO\``%)#1,:,_P``X@-=%JX+ +M_\`P08$PE,0L@,D#,JWNEG1)3#T:)_P``DA,HD)%!DE,.@A,I@(%!@E,/AH/_ +MLA,HLE,.HA,IH*%!HE,/!G__`')#*W)"C(;#_O(3$)"&5(#_(/)3$-(3$)#@ +M5(#N$>#=(-)3$$9#_P`V00`QB00,!#SX@D((0D()`#.F0!"FDJ$"MM0#?/(= +M\$)"$``YID`0IK%M`\+2`K8D!7SB'?```$)"!L(,U<)"!Z(B&*G+#`(=\``` +M-F$`G)"!YX,&M*B<)P4DJ$"`#FF@!"F]B@"AC,`?.(=\+$Y!%%L`SWP +M=JL%PB5#%OS_LB(ALF6,\B<8@B<9DB<90B<88J``X3D$D$2"@_\(0_\0\F53 +MHF57=JX'PB57&V8F'/\,[@`^IF`0I@PX]G90MC81\L;]%B\)]F8"]D8%0L;Z +M%I0*@J"(@(."#"F*@MJ(DFA_HD>=HF57@BB`8BE!JJ.Z +ML]K3V2&Y`:)A`8`S@%)#WY)D/((#EX)D/*(#F#WP)BHX4D.4`#:FD!"FZG]HB$%94KZJ%$E:/JH4>4`^JA16:I2:@NEU?D,*()#F$8% +M``"H467_^:(A!5)J"EFZ)=3Y#"F20Y@FDA"BPO46*B2RPO06"Q4,W,<2$0PB +M#!T<3N)D/%)#F-)#WX:D_QQYDF0\@@.8@F0\\@.8YB\+H@.8EEH`##*&G?\` +M#!JX(=@QZ$'"`YC"`Y/E3>G8`:@17`M2;1E2;3M2;5U2;7]2;:%2;<-2;>4E +M#`.H45)*BN79_(RJ*_H,C@PR\"Z#!HS_J%%20SRR`SZE'_TL"()D/*)D/(RZ +M*[H,B0PRL"F#QH/_`*A1Y3C[UIH`##((#)@P=#`O@O8.R3(MB0Y@&`P````"(40P_ +M4DB+\D.8HB$%L@-*Y=+]P@-9PD-&L@-:LD-'H@-6HD-(J%&2`U>20TEE,OJB +M(07E3_JH4:7H^@PB!E;_'&_R9#SB`YCB9#S2`YCF/06"`YC6^`&2`YB2R?T6 +M*0NB`YCF:@>R`Y@]\.9+$,(#F,+,^A:\"0PR!D?_````T@.89DT$J%&EX_D, +M&K@AP@.3V#'H0:4WZ0P:B%$,:[)#F%FH6;A9R%G86>A9^*)(BO(#)@P9K0CP +M^9/R2(OB`S_B0TI20SRR`S\E"OW\2J(A!?(#6?)#1N(#6N)#1](#5M)#2,(# +M5\)#2;(#/R7%_:A1)2;ZHB$%I4/ZJ%%EW/H,(@8E_RN:#(@,,I`H@P8B_P`` +M`*A1Y=KYJ%%9JE)J"Z6O^0PR#"JB0Y@&&_\<7=)D/,(#F,)D/+(#F.8[!>(# +MF-9.#?(#F.9?!8(#F.8X$9(#F)+)^Q;Y"Z(#F*+*^E9J"\$W!``\IO`0ILT/ +M\+E!C#L,@H8(_\Q/##+&!O\`V%'2#8K,O>A1XBZCYS\D##*&`?^(48(HHX>_ +M!`PR1O[^F%'"*:.2*:/`S\"7/`0,,H;Y_KA1R=NBH0(`.J:0$*:V*00,@D;T +M_KR)J%&ELOR,JBO:#(P,,M`L@P;O_JA1#!B"0SRR`S_B`S[R"HKPOH.E]_R, +MVBNZ#(D,,K`I@P;F_@```*A1Y13ZHB$%9(C($@`"F +MC)AV@`2@`*:,&@;]__`0IOGEX!"FZ?70$*;291#`$*;"91$]\/`@`+``IHR; +M=H`$@`"FC!@&_?_0$*;291+`$*;"91.P$*:R912@$*:B914]\#WPD`"FC)EV +M@`3@`*:,'@;]_[`0IK)E%J`0IJ)E%Y`0II)E&(`0ICWP/?#P`*:,GW:`!,`` +MIHP(%2Q8^$?';`_#\$/)D\!R+PJ"` +MHB>*J272`^#BJ__@JA#0T`3293E@W1'0JB#`JB!@JB"PJB"0FB"9)8(C-9=H +M!_*F`/#Y(/DEL@/ALF4XDB>$3`J@F2"29X2"!4G2%1N`@!0F.`CPW1'0T/32 +M51N]`<*@`:(5&N*OP/(B(="J@O)A`*"JD*"A(:+*/^"J$/"J$27`Z*EU=H`0 +MTB3GV1'($<#`%,D1N!$F.P(&^O^2)*S1-0.0H`2R+2`':0=\[N#I$.)DK,`@ +M``PLP,L@PFT@\BT@?-B`_Q#R;2!V@!#R).?Y(>@AX.`4Z2'8(28]`@;Z_\`@ +M`(P:DF2L=H`0HB3GJ3&8,9"0%)DQB#$F.`(&^O^Q.`.R9-H=\-(%3`O=5CWN +M\=T#Z`7P_"#R9/#H+N#@!%:>[8(5(/:(`@:T_PQ*H*L@HF3=1K'_`#8!`3(B +M#B"R()(C.H*@`()A%A8I7M(#3!OY\F,Z%KU>T6H##!(,#\$U`_)C,")C+N(L +M(.D!J`'R814A,P/0JA"B;""2(SBADP32$QJ0D!22:H.((X)JBN@SP98$'`_P +M[B#I#-)B^)ACDFJ)B#.`@!1F&!&"$QF`D,2`@4$`B!&0B""";!7R$QOB$QD` +M_Q'P[B#B;!>H@Z)L&)B3DFP9B*.";!KXL_)L&^(#2:(3&I(3(>#@%.+._1:> +M81N9T)D1D)J"V'.B`TOBK\#2S3_@W1#9(=#9D-+-/^#=$-E!VMG2S3_@W1#9 +M8=#9D-+-/^#=$-F!VMG2S3_@W1#9,=#9D-+-/^#=$-E1VMG2S3_@W1#9<=#9 +MD-+-/^#=$-)A"28:5-$U`Y(BK#WPTBT@D*`$!VD'?.[@Z1#B8JS`(`"!-0/R +MH0#P_2#R:"#R*"#BKO\]\.#_$/)H(':`$.(BY^FAV*'0T!39H8BA)C@"!OK_ +MP"``C!J28JR2(S*+H:"9H)@)F9R"(S+2P1#0B*"("(F\\B,RXL$8X/^@^`_Y +MK*(C,I&6!/+!(/"JH*@*J(K +M`!;._O@#^"\]\`?O6W:`$+(BY[G!F,&0D!29P8C!)C@"!OK_?-O"(MW)T88! +M`-C1#([GC3.8T0PLP)D@DF+=@B+=@F$-\B$-DJ/HL/\0\F+==H`.XB+=Z='8 +MT0N9-^W-%JG\AOK_````=H`0DB+GF>&(X8"`%(GA^.$F/P,&^O\`PB$6L6D# +MQ[I2P34#DB*LPBP@D*`$!VD'?.W0V1#28JS`(`#Q-0.!:@.PW"#2;R#B+R"` +M[A#B;R!V@!""(N>)\?CQ\/`4^?'H\28^`@;Z_\`@`!8J.I)BK`Q"'?"($^%3 +M`_(A%?D(TB+$X-T0V0'(`<)BQ)(C-E;9(]$U`Y(BK-(M()#`!`=I!WSNX.D0 +MXF*LP"``@34#X6H#L/T@\F@@\B@@X/\0\F@@=H`7XB+GXF$0TB$0T-`4TF$0 +M@B$0@LC]%@@E1OC_``"@$*:B8R60$*:28R:`$*:"8R?P$*;R8RBB$Q@F%@VR +M(RX,;/`@`,"[$+)C+F>:"](C+N*@`N#=(-)C+N(%"\(%"I(%#X(%#;(5!-(% +M#*(%#K#V5(K=FJKJS)(A%=K,RJJB8R^(%9)C*Y)C+8"(=8)A%Q;O);#&!+#K +M!+#:!+#Y!.K=L.@$^NZP]P3ZS.K,VLS'N@ORH`B"H`&"8ROR8K"2(1<,&ZT) +MH*N3HF,LG(G2%0'"(RW0T`30S"#,K.*@!/*@`?)C*^)BL((C,)(C*9)C*HQ( +MHB,M5FH`K0.]!64Y`'(A%QMWO#<,!(QD@A4`&XB"50"2$QBB(1?P(`!GF1", +M&J>4"\(C+M*@!-#,(,)C+JT#O06E/0`;1'>4S.(A$I(#2QP(+`\+F9#X@_I5 +M5YX"4B$38B$4HA,88L8!8F$48L8!9[H"!E+_@B,V5BC4DB$34)G`5CGLH`"F +MC)IV@`2P`*:,&P;]_X`0IH)C&?`0IO)C&N`0IN)C&]`0IM)C'#WP/?#``*:, +MG':`!)``IHP9!OW_X!"FXF,=T!"FTF,>P!"FPF,?L!"FLF,@/?`]\*``IHR: +M=H`$\`"FC!\&_?_`$*;"8R&P$*:R8R*@$*:B8R.0$*:28R0]\#WP@`"F%NCA +M=H`%T`"F%EWAQOS_``"1-0/B(14,&()I+B(C-@P_(.^3+0X=\`"B`TL+JA9* +MH<$U`PP"#!NR;"X=\-(#2=#0%"8]!^(#2@ON%GX0HB,R#!B2$QR`JC"B8S(P +MJJ"2:C3R(S*`_S#R8S.&>/[`(`",'))BK`P-#`SA20/&`0``_0T;W?80I(C,@N$%F@) +MH/F@^`_YW.(C,M#NH.@.Z?R&OOX,0AWPDB,R@A,<,)F@DBDTD(C`%HB.#`(= +M\``,&J)C+<92_PP2'?`F%&V2(S*@F:"8"9G<@B,RT(B@B`B)_)(C,^"9H)@) +MF>R"(S/PB*"("()L$`:I_@"2(S.@F:"8"9G<@B,ST(B@B`B)_)(C,^"9H)@) +MF>R"(S/PB*"("()L$,:=_N#9H-@-V>RB(S+PJJ"H"J)L$(:8_I(C,Z"9H)@) +MF=R"(S/0B*"("(G\DB,RX)F@F`F9[((C,O"(H(@(@FP0AHW^````-D$`(J#L +M'?`V80"BH.R]`0P,B.*)`>4TZ$T*LJ#LY30"?/FAF00I!+&8!+)B-*)B,Y)D +M*9)D*I)D-))D-0P"'?`````V80!,&N6-YI&3!`P=P"``#.OR(C?28C;H$AO_ +M\F(WV0["*83)`;D1J!&(`:"((()IA,`@`!WP`#9!`&(B+D(B+5T"8&`4G*2` +M(*:,F':`!)`@IHP9!OW_`#:F#`)B92D=\```@A,!H@)0#(>`D`3@F1&`@D%P +M>!"09B!P9B"L:I("49"0%,"9$9!F('(E+Y&\`X(3!'!PI$!W$9"($(!F('!F +M(`;H_P`\"J"H$*!F(`;V_P`VH0$,1:$X`^%)`\%6!$@R\9H$T8L$0$`4C/0+ +MA!8($*+$_@P)?/*@*8,=\+(B+F(3`$%"`X(B+6#O@T!.((#DDTT.)VL"H$X@ +M4A,!X9L$D=T#4+`D%LL7)V4"X$0@%V4"D$0@4(`$@F$F!V4"T$0@5V4"P$0@ +MT9P$<@))P9T$J8]\,!@IHQ, +M\&"F5I__`':F/?"`8*:,2*!@IE::_P![ICWPP&"FC$SP8*96G_\`?:8]\(!@ +MIHQ(H&"F5IK_`'.F/?"P8*:,2\!@IE:<_P!^IALI'?`,`AWPD$0@!J+_`,"$ +M(++'_=!$(+!(D\:J_P`,#&&B!.&X`[$V`_%@`]&C!"&D!(+'_1;8$@N'%H@/ +MDL?^%BD/#`X,`PP-#`L,!@P*#`(,#PP)1K+_``"@8*:,2K!@IE:;_P!_ICWP +MP&"FC$S08*96G?\`.V2(BM6&>UB$P"R(BY@[X--#B=K +M`J!.(%(3`3WP!V4"T$0@T@))9CT"QMP$(A(@K08;(KT")0H"/0H@LB!@IB#E +M!`*!H`2@D'2`F1&`A!"0B"`P0'22KP"0B!"`1"`&H_\``(&E!*!)`8!$((:? +M_[!@IHQ+P&"F5IS_`'^F/?#08*:,3>!@IE:>_P!RICWP\&"FC$^`8*96F/\` +M>J8]\+!@IHQ+P&"F5IS_`':F&RD=\```@9T$\'00AY<"!B4`D9P$D)?`%JD, +M\(?`%F@0#`8,"@P"#`\,"0P.#`,,#0P+QF[_D6(#D(00@F$CEX0T#`X,#0PI +M8:8$P/H1(B$E#`KP\+3`(A$@,;0@(K1`,Q&P,R!`(A$,"V`S$##_(`P&#`.& +M7O^!G`3P=!"`A\`6*"F1G020E\`6&2SPA\`6."\,#@P##`T,"PP&#`H,`@P/ +M#`F&4O^18@/QW0.0E!"282/PF<`6F66!FP3R(2.`_\`6'W3Q8@.2(2/WF0(& +MC@(,!@P*#`(,#PP)#`X,`PP-#`O&0O^!8@.1W0.`A!""82.0B,#,&`8$`O&; +M!)(A(_>9`L;Z`HT)D6(#EY@"1G8##`X,`PP-#`L,!@P*#`(,#PP)QC+_```, +M'Y&G!('=`R(A))!$$(!$(`PH@"(0@I,)G0*0GY."81_]"Y)A&)#]DX"1(8"9 +M(Y)A(O"9$9<8!8%"`X#_()*3"))A(9!Q(8!W(_"'$8<9!X$X`SWP@/\@#!8, +M!9*3"Y)A'B!6@R&H!&(A)5)A%U"]DY"!(8"((XDA4B$BP&81("\0:E504+1` +M51%0(B!1I@38(?"($5`B$,!:$5KW\/"T(/\@+0N'&04A0@,@*R""DPJ"82"` +ML2&`NR/PFQ&7&`6!.`.`(B"B(1^2(2(;BH"!(:")LZ&H!&J=D)"T0)D1H*(0 +M(:8$D*H@DB$8(*H06BL@(+2@(B"M#)"NDX"1(?"9$9<8!9%"`Y"J()(A(6)A +M$AN)@($AD(>S@)$A\)D1EQ@(D3@#8F$2D*H@4%$A,B$ADB$78B$?&X.0SI.` +M@2$PA[,R(2(;EI"1(6"3LV&H!#(A$I"1(6!J$#`Q09J3@*$AD)"T0)D1D&8@ +MD:8$JJ6@H+209A!@JB!B(1X;AH"!(6"-LVT,@)$A\)D1EQ@%84(#8&P@PB$@ +M@LP!@($AP(NS@)$A\)D1EQ@%D3@#D&8@XB$@@:@$&YZ`AA"0D2'@F[/B(1Z0 +M82$,21O.P,$AX,VSP,$ARL/`P+1`S!'`B"#!I@1J96!@M,"($(!F(`9%_X'= +M`_(A(X>?`L;Z`_&;!)(A(_>9`@8[!(T)D6(#EY@"!O<$#`8,"@P"#`\,"0P. +M#`,,#0P+QJC^@=T#\B$CAY\"!G0$\9L$DB$C]YD"!FP%C0F18@.7F`)&[@4, +M#@P##`T,"PP&#`H,`@P/#`G&FOXAJ02P^R!QW0.!IP22DPF281^`1!!P1""" +MDPB"82&0<01P\I.0D2&280V`<2&`=R/PEQ&7&`61.`.0_R!B(1\AJ`1"82=2 +M(25!I@0@+Q#`51%@8B%IX5"!08)A&H!F@&!@M$!F$6`B(,!J$4`B$*&J!$*3 +M"V#W@/#PM$)A'B#_("T-0)$ADF$10$$$0"J3DI,*DF$@0B$GD($A@(@C@F$= +M\(@1AQD%@3@#@"(@DI,-8F$('#3DY<8!8$X`X#=()C!B*$;>7!Q(9!XLY(A'7!P!((A('#CDW(A +M$1LX,#$A@#FSF'$;AX"!(7")LW&H!)(A$W!]$(#1(=J9@:8$,-$AD)"T,B$6 +MVM5`F1&0=R#0T+2`=Q!PW2!X81N#@($A,(>SX#X@@)$A\)D1EQ@%,3@#,#X@ +M0F$GX4(#0B$6(F$I@B$0&Y20D2%`E[-(@1LH("$A@"2S("`$(,Z3XB$90B$; +M&XZ`@2'@A+-(P>BA&R0@(2%`+K/B(1-!J`0@(2$J[D!#$"(A*>#@M)`Q(3HU +M0.X1@)$AX$0@X:8$\)D1,#"TX$000#,@[0Q"(2>7&`7A.`/@["#"(1DB82F2 +M(1LB(1`;C("!(<")L\B!&Y*`@2&0D2$@G+,AJ`2*A<(A$R`N$)#A(>K,D:8$ +M@."TP,"T0,P1P"(@D"(0(.X@#(DB(2E&N/T```!0;`22DPF281]@O9/]"Y"! +M(8"((X)A(O"($8<9!?%"`_#[((*3"()A(8!Q(8!W(_"7$9<8!8$X`X#_(&#. +MDX(A(M(A'R&H!+(A)1N=("\0P+L1NCC`^A&0D2'0F+/R81PP,+3Z]T`S$9#1 +M(3`B(#&F!/#=$?#PM#`B$"#_("T,UQD%(4(#("P@HB$A@LH!@($AH(>S@)$A +M\)D1EQ@%D3@#D"(@HB$APB$?8:@$&YH;C)"1(:"7LZ(A(F!B$("!(<"*L["A +M08"!(:J(@("T0(@1@&8@@:8$D"$A@&80@B$<#"D,"H"!(8HB(""T8"(@#`8& +M-?X`4-T$XI,+P:P$XF$>X+$A@+LCT&R38/8@\(L1AQX%\4(#\/8@@I,**3&" +M82"`D2&`F2.281WPF1&7&`?!.`,I,<#_((&M!"@QDB$>PB$E,:@$&^G`S!$P +M/Q#0*)/R(1W`BX"`@+1`B!&`,R"!I@3@X2&0Z[.`,Q#`BA&"81R*__#PM##_ +M(."!(2`R(/"($8<>!2%"`R`C(-(A(*(A'1N-@($AT(JS@)$A\)D1EQ@%D3@# +MD"(@TB$@8:@$HB$=&YV0D2'0FK.B(1Y@8A`;BH"!(:"+L\"A08"!(:J(@("T +M0(@1@&8@@:8$D"$A@&80@B$<#"D,"H"!(8HB(""T8"(@#`;&\_U0+`2P>R"" +MDPF"81\@?9-P]R"`D2&`F2.282+PF1&7&`7Q0@/P]R""DP@IL8)A(8!Q(8!W +M(_"7$9<8!X$X`SWP@/\@@B$B(:@$4&X$DI,-DF$5:0%@O9,@+Q!B(27`^A'R +M81S`9A%JB("`M$"($8`B((&F!/KW\/"T@"(0(/\@D($AL"L@@(@C@F$/\(@1 +MAQD%(4(#("L@LI,,L-$A@-TC\(T1AQL%@3@#@"(@,:@$HB$?DB$B,#(0&XJ` +M@2$B(1R@B;.1I@2H\2HM(""T:JJ+JJ"@M$"J$:`S(*BQD#,0,"(@@)$A\)D1 +M/0R@/I.M`Y<8!:%"`Z"C()(A(3(A`&)A$H+)`8"!(9"'LX"1(?"9$9<8")$X +M`V)A$I"J(%(A$C#.DY(A(>(A'U!101MI8&$A&XZ09[.2(2)281J`@2'@B;.8 +M\>(A%8"!(8I54%"T&XZ`@2'@B;/AJ`1`51&1I@3@ZA!@H2%0[B!M#)#N$%(A +M'("1(?"9$5!1(:"E@*"@M."J()<8!6%"`V!L(,(A&K)A%MEAXB$5&XN`@2&P +MC;.`D2'PF1&7&`N1.`/280:R81:09B#888&H!#(A%AN^L+$A&Y.`AA"0D2$P +MG;,,`Y!A(=CQ#$EJ96!@M."]L["Q(;J\2[NPL+1`NQ&PB""QI@0,#@P-L(@0 +M@&8@#`L&NOP`4/P$@I,)@F$?^;'PO9/]"X"1(8"9(Y)A(O"9$9<8!?%"`_#[ +M((*3""DQ@F$A@'$A@'S +MDB$B&X.`@2$PB;.2(1XQJ`2`@2&*55!0M#`Z$$!5$6"A(6T.4#,@&XE1I@2` +M@2&0C;-0,Q!2(1R`D2'PF1%042&JI:"@M#"J()<8!6%"`V!N(,(A(+(A'1N, +M@($AP(NS@)$A\)D1EQ@%D3@#D&8@@B$@LB$>XB$=&Y@;R\#!(9"1(8">L[#- +MLX&H!+(A&L#!(8"&$,J[D&$AL+"T0+L1#$FPB""QI@1J96!@M+"($(!F($;Z +M_`!0[03QK`32DPO-!M)A'M"Q(8"[(_"+$>#/D_T,AQT%\4(#\/P@@I,**3&" +M82"`D2&`F2.281WPF1&7&`?!.`,I,<#_(-@Q(:@$PB$E4'\$@I,/@F$4>1%1 +MK`3`S!$@+Q!P99/R(1W*6X!Q(5!0M$!5$5`B(%&F!(!W(_"7$5`B$,!:$5K_ +M4F$<\/"T(/\@+0:7&`4A0@,@)B""DPZ"81F`D2&`F2.281OPF1&7&`6A.`.@ +M(B`QJ`3*AXN(@("T0(@1,#(0@#,@@:8$(B$;@#,0@B$`YDY(A'JT#@LD!@($AD(NS@)$A\)D1EQ@%H4(#H*,@DB$@XB$=&XF`@2&0 +MCK/B(0&`D2'PF1&7&`61.`.0JB!2(2"!K022(1T;9>#8DV!A(5!IL\!109(A +M'L&H!%)A&AN)P,H0@($A8*$AD(NS;0V`@2&2(12*55!0M$!5$5#,(%&F!!N) +M@($AD(>S4,P04B$<@)$A\)D14%$AJJ6@H+3`JB"7&`5A0@-@;2#"(1FR(1L; +MC("!(<"+LX"1(?"9$9<8!9$X`Y!F(`P#TB$;@:@$XB$9LB$4@(80&YX;R\#! +M(9"1(>"=L[#'LPP.#`VR(1J082'`P2$,2!.`,I,8#_("&H!((A)9(A(B`O +M$,#X$8&F!/)A$OJ9D)"TP/H10)D1D"(@\F$!))A`)"]DX`B()*3#:T+DF$5D($A@(@C@F$/\(@1 +MAQD%H4(#H*L@LI,,LF$6L-$A@-TC\(T1AQL%@3@#@*H@4+\$4:@$@:P$DB$2 +M4%H0L&B3HB$S@B$B4%$A,F$:T%BSTB$>4%$A6C,P,+18(1N-@($AT(6ST:@$ +M4B$<0#,1T-L04%$AD+$A,-T@F$$QI@2ZM;"PM##=$-"[(#@QT:T$D#V3W0.` +MD2'PF1&7&`710@/0TR!R(2`R(1V"QP&`@2%P@[,R(0)X`8"1(?"9$9<8!9$X +M`Y#=(")A*2(A'AN2D)$A().S(B$50F$G2/$;@H"!(2"$LR(A('#.DT(A'1LR +M,#$A(#2S0B$:(:@$D)$AD$2`("T0@)$A,-$A0$"T/0Q`1!'PF1%`(B!!I@30 +MU8#0T+1`(A`@W2!"(20B!"2(1_P\+2`_R#6*0`&X0+2(2*M#=#1(="[@+"P!+#.D\`L +M(*#A(?#N$><:!8%"`X`B(+(A(1N;D)$AL)>SD*$A\*H1IQD'H3@#/?"@(B"R +M(2$;FY"1(;"7L[(A'V&H!((A(ANKH*$AL*BS@B$:8&(0H*$AJHB`@;1`B!&` +M9B"!I@20(2&`9A""(1P,*0P*@($ABB(@(+1@(B`,!@;*^P#QK`3"DPO2(27" +M81[`L2'`W1'281*`NR/PZQ':V]"`!(!ODV#V(.<K8T-`$ +MT"R3H($A\(@1AQH%D4(#D"(@XB$@TB$=&ZZ@H2'@K;.@P2'PS!''&@7!.`/` +M(B#"(1UAJ`2"(1[2(2!@8A`;J!N=H*$A@*NS@B$:D)$AH*$AJHB`@;1`B!&` +M9B"!I@30G+.0(2&`9A""(1P,*0P*@($ABB(@(+1@(B`,!L:%^WT+4/P$@I,) +M@F$?^;'P?9/]!X"1(9G1%V@%\4(#\/<@@I,(@F$A@'$A@'1.`.YH9!F(`P# +MN*'B(1:!J`3881N>@(80D)$AX)VSV,&082$,#@Q)&\W`P2'0R[.R(1-J9<#! +M(`\/"T@/\@\(L1AQD% +M(4(#("8@@I,*@F$@@)$A@)DCDF$=\)D1EQ@%H3@#H"(@@:@$T)&T0)D1@((0 +MD(@@D:8$(B$=D(@0DB$SX($A +M\(@1AQX'@3@#/?"`JB#2(1K!J`12(2&2(1_`RA`;A1OI@($A4(>S4B$BX.$A +M@*$AD.6SDB$>4B$T-$AK0.`@B&0V+,';06A0@.@HR"" +M(2#B(1T;N+"Q(8"^L[#1(?#=$=<;!=$X`]"J(%(A';@1D:T$:#$;W.(A'L(A +M$M#1(>#B(<#"0;!ID[&H!)(A(,)A$["Z$!N)@($AD(6S@*$A4B$1@B$4DB$0 +M4-ZS@((A4B$!.`,I,8#_()*3"R(A)9"!(<`B$8)A$8(A'R)A$B`A08""(2)A&HGA +M*H@AJ`2281X@+Q"`\+1`_Q'P(B"!I@3`^A&AK`2`(A#R81Q0C03Z]_#PM(E! +M(/\@8"8@@"J3%VD%@4(#@"(@DI,*DF$@D*$A@*HCHF$=\*H1IQD%@3@#@"(@ +MDB$>HB$:@:@$D)(AF7&`@A"JF9"0M$"9$9"(()&F!"(A'9"($)(A')HB(""T +M4)X$F0&0O9.`(B"2DPVM"Y)A%9"!(8G!%VD%H4(#H*L@LI,,LF$6L-$A@-TC +MTF$&\-T1UQL%@3@#@*H@L:@$T:P$4%\$61%0;9/2(16PNA!2(1K0TB'9H5K= +MT-"T0-T1T+L@T:8$DI,/J&'0NQ#2(1R2811=!MJJH*"TL*H@D+$ALF$0%VD% +M84(#8&4@@I,.@F$9@)$A@)DCDF$;\)D1EQ@%L3@#L&8@DB$4LB$:@:@$D)(A +MF8&`AA"ZF9"0M$"9$9"(()&F!&(A&Y"($)(A')IF8&"TF-&`9B"(L3T,&]F` +M/I."(0[0T2$PLR"0V+,';06Q0@.PLR"2(2$;V=#1(9#7L]"!(?"($8<=!X$X +M`SWP@+L@,B$2DB$AV-$P,D$;B1M=@($AD(>SF.%042$R81/06;/2(1%042%: +M,S`PM%AQ&YV0D2'0E;/1J`12(1Q`,Q'0VQ!042&`L2$PW2"(03&F!+JUL+"T +M,-T0T+L@.#'1K02`/9/=`P=I!=%"`]#3()(A(")A*2(A'8+)`8"!(9""LR(A +M*8"1(?"9$9<8!9$X`Y#=()C!0F$G2*$;B8"!(9"$LT(A(")A*2(A'1LT,#$A +M0#*S(B$12'$;DI"1(2"4LT(A$R&H!)"1(9I$("T0F`%`0+0PT2':U4!$$4`B +M(-#0M$&F!)#.DST,0"(0(-T@0B$G(B$I!V@%,4(#,#P@XB$6R&$;CH"!(>", +MLX"1(?"9$9<8!9$X`Y`S(")A*2(A$,(A%NB!&X*`@2$@CK,H81N%"`^#L()(A&<(A&QN)@($AD(RS +M@)$A\)D1EQ@'D3@#/?"0[B#"(1DB82F2(1LB(1`;C("!(<")L\B!&Y*`@2&0 +MD2$@G+,AJ`2*A<(A$R`N$)#A(>K,D:8$@."TP,"T0,P1P"(@D"(0(.X@#(DB +M(2E&N/<;J9(A&J"A(:"Q(;J9D)`$D,Z3+0R&'?T``,&M!!NNH*$AH.$AZMC0 +MT`30+).&6_T;V((A&M#1(="1(9J(@(`$@,Z3K0R&+OX``.&M!&@Q@B$:&]G0 +MT2'0D2&:B("`!(!NDX9*_@`V00`,!"!0%)P5#$=0=\`P=V-P,\!VEP1"0@`; +M(C!R03WP=I<#20)+(C`P%#WP=I,$0D(`&R(=\#9!`+8C)U#R0$#S0$>U%E!$ +MP``40``SH3WP=I0(-S(","+`,#%!-S(","+`'?`,`AWP```V00"V(SEM`E#R +M0$#S0$>U)%!$P``40``SH2*@`':4#3@8U``P&-@`-`4H`$1\0@`!?$)``94` +M``>&@```@``!4(```5"```%0@``!4(```%(15``0?A8`"LU``!'480``E8#_ +MLL0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``!'48@``E8#_J<0@``Z:`/__ +M?$"``8@```!\0,`!%-``'C$4``*50`#K&-0`,!C0`>@8_``T),P`#P3H`&A\ +M08`!?$'``93``!*&@```@``` +M`!J```!_4=P`('V=@!J90``#Q:(``(```'_)H@``@```?\6A``"50``%!9@` +M`<6E``!29``@?B8`&@4H`(-\08`!?$'``94```>&@```@``!4(```5"```%0 +M@``!4(```)/8```1SAD``)5```0%F``!5B``(,X9``"7P/]QQ#DA0'Q`@`&( +M````4=P`('V=@!K8```1SAH``)5```0%F``$5B``(,X:``";P/^]?$"``8@` +M``#8``/VV``#]=@``_38``/SV``#\M@``_'8``/PV``#[]@``^[,0`!_S$`` +M?\Q``']\0,`!S,```=1``'^`````?$#``5!0`"",``#+?-#`&L0@``O$U@`` +M?$.``<0D`!.:```)V&0#],9K`_&:@/__QFL#[@:H``'.I`/NS60#Z]@D`_29 +M0``)WX,``,^@``Z,``#/U$``?YH`_SS&

?16`#IF```_80``IR!``'7U1@!)]C<`/F<#__=@``"E0X``! +M?A9`#II```1]8H`2TH``(X````#0```C@````-B``"G$/`!_S```(-A``"C$ +M#``V$``'8````#,```@V$``*,0, +M`!R8P/__V```*-```![0```?V$``'7Q!``&`````?$#``7Q!``$5&``?S0`` +M$5$4`""9@``#U$T``(````!]34`:&1P`,=16``#$(``.E<#^R,0@``Z:`/__ +M@````'Q`P`%\08`!%-``'C$0``(DU`#_E0#^O\V4`P"`````Q"``$WQ`P`'$ +MTP,`S```$`(0`]@"'`/D`B`$"`(D!%P!]`3P`?@%$`'\!+``B`*X`BP$B +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````"`````@````(````"`````@````(````"`````@````(````"```` +M`@````(````"`````@````(````"`````@````(````"`````@````(````" +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +:``(````"`````@````(````"`````@````(` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/HAINAN_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/HAINAN_mc.bin.uu new file mode 100644 index 00000000000..5e43a2c7178 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/HAINAN_mc.bin.uu @@ -0,0 +1,702 @@ +begin 644 HAINAN_mc.bin +M``/HX``"O@$```('``/_```#_P```J`.``'`&0`#Z````^@0``/H(``#Z#`` +M`V`@``-A2``",A(``TEL``-("@`#KPH``K0$``)O]```^BT``K0/``)/%``` +M^@H``ZB,``#"`0`#0"0``K1```*U#P`#2J8``D1!``/P`@`"294``VJF``-* +M40`#0"0``K@"``*Y_@`"1)0``DB!``.H@``"9$@``VI1``-`)@`"OX```KP$ +M``))^0`#\$(``_0```'`00`"OX```TA4``*X#P`"N?```D$8``)"*0`#:%0` +M`TMI``/`C``"9$P``VMI``)$2``#:VD``F$?``)B+``#:%0``BQE``-+3``# +M_P```V%$``-+'``#0"H``K3\``-A0``"0S0``F$>``-K'``"2JX``_!&``-) +MU0`"O!```DS'``/P0@`"O"T``_\```-`)``"M$```K7P``-*I@`"1$$``_`" +M``)IE0`#:J8``T````/_```#^`$``\1```/$40`"QD4``@````-`$``#_P`` +M`_\```/H(``#Z#```V`0``"1Y0``D@T``_@#``(Q&0`",@P``T@(``*TGP`" +M0`0``V@(``-(P``#2,8``K3\``*U#P`"010``DF4``)")0`"2J4``D,U``)+ +MM0`#:,```VC&``-(```#2`4``KL_``*\OP`"O^\``)(E``"*)@``@BH``+HH +M``"J+``"01L``KO[``)`#``#:````KS^``)%7P`"1WP``V@%``-($``#2=T` +M`KOQ``*\`@``BBD``*HK``)!&P`"81P``V@0``)%6P`"95P``VG=``-`#0`# +M_P```_\```.A3```B?\``K,"``)#-``#HS```)G^``*S!``"0S0``Z,R``"9 +M_0`#0"D``T````*\(```N<<``D(L``/P!P`"L````((Q``(ZG0`#Z````('E +M``/T```!PF```T````*\(```\C$``D,\``/P!0`".IT``^@```"!Y0`#]``` +M`<)@``-((0`"L\$``D=S``-H(0`#:HD``T@E``*SP0`"1W,``V@E``-JC0`# +M2"D``TEP``-`$@`"OP<``D`/``.````#``X``Z^(``-)U@`"O!```DS+``/P +M00`"P`\``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H+0`#P00``\$5 +M``-IZ``#:>P``TK"``*_P``"2(\``VK"``-JQ@`#Z````^C0``(N\``#:.0` +M`\'>``(N\``#:00``^A```*]```",EP``KT!``(R7``#0"P``_\```*T`@`" +M1`0``*()``-)U@`"M1```D1;``.D1@``H@L``J!.``/P`P`"-!<``_0```'! +M!0`#]````=+=``-+8``#_P```F`.``-K8``"O````C*7``-`#@``\C(``^CP +M``.@M@`#2=4``/H$``*Q#P`"0A<``J4@``/P`0``^C(``D,;``*E(P`#\`$` +M`/($``-````#0"X``K80``*T#```*C(``D(D``.B(@`"0S0``FPC``)&:``# +M\`,``J!>``/P`0`#Z,```.(#``-`"``"M````'H$``*@)``#\$$``K((``*@ +M_@`#\$$``K($``*T/P`"0B0``)(:``-*E``#_P```V&```-````#_P```K1` +M``)$!``#\`,``^@```"",0`"(O,``T````/_```"M$```D04``/P`@``\C$` +M`B+S``-````#_P```K1```)A$``"1!0``_`!``(M40`#2I0``_\```-AA``# +M0````_\```*T`@`"1"0``_`#``/H````@C$``B,?``-````#_P```K0"``)$ +M-``#\`(``/(Q``(C'P`#2I0``_\```-AB``",@P``T````/_```#_P```D0. +M``/P`P`#Z````((Q``(D2``",@P``T````/_```#_P```D0>``/P`@``\C$` +M`B1(``(MB``#2I0``_\```-AC``#0````_\```*T`@`"1$```_`+``/H```` +M@C$``B8[``-`+``#_P```K0@``)$0``#\`,``^@```"",0`",8,``TJ4``/_ +M```#89```T````/_```"M`0``D1```/P`P`#Z````((Q``(H#``#2I0``_\` +M``-AE``#0````_\```*T$``"1$```_`,``/H````@C$``BBS```!_P`#_P`` +M`_\```*D#@`#\`0``/(```(HLP`#Z````((```-*E``#_P```V&8``-````# +M_P```K0@``)$0``#\`,``^@```"",0`"*D```TJ4``/_```#89P```(#``/_ +M```"M`$``D0$``/P!``#Z````((Q``/!_@`"*O(```(#``/_```"M`(``D0$ +M``/P!``#Z````((Q``/H\``"*O(``T````/_```#_P```D0N``/P`P`#Z``` +M`((Q``(X.P`#0````_\```*T$``"1"0``_`#``/H````@C$``CE?``/X`P`# +M2I0``_\```-A8``#0````_\```*T`@`"1$$``_`*``#R,0`")CL``T`L``/_ +M```"M"```D1```/P`@``\C$``C&#``-*E``#_P```V%D``-````#_P```K0$ +M``)$00`#\`(``/(Q``(H#``#2I0``_\```-A:``#0````_\```*T$``"1$$` +M`_`+``#R,0`"*+,```'_``/_```#_P```J0.``/P!```\@```BBS``/H```` +M@@```TJ4``/_```#86P``T````/_```"M"```D1!``/P`@``\C$``BI```-* +ME``#_P```V%P```"`P`#_P```K0$``)$!``#\`,``/(Q``/!_@`"*O(```(# +M``/_```"M`@``D0$``/P`P``\C$``^CP``(J\@`#0````_\```/_```"1#X` +M`_`"``#R,0`".#L``T````/_```"M!```D0T``/P`@``\C$``CE?``-*E``# +M_P```V%T``/X`P`#0````_\```*T"``"8`$``D0$``/P#``#2`@``_\```*T +M0``"8`0``V@(``-)F``"M/T``D$4``-IF``#Z#```\$N``-H,``",9X``^@` +M``/H$``#Z#```K(#``-H,``#0````_\```*U@``"81```D45``/P`0`"-YH` +M`TJ4``/_```#87@``KP!``(REP```C(``_\```/_```"H0X``_`"``/H```` +M@@<``BV(``-(```#2`4```HF```"*@``$B4``"HL```Z*``#_P```V@```-H +M!0`#2!```TG=```**0``*BL``_\```-H$``#:=T``TEQ``*R`0`#Z#```\$& +M``/!%P`#:#```C&>``/H```#Z!```K(#``*S```#:#````(+``/_```#_P`` +M`J`.``("A@`"(N<``_0```'``````>4``T`2``-`%0``"@T``J`.``/P`@`# +M]````<*A``+!'@``B@T``FNZ``)E6P`"QFX``_!!``,&;@`#8!4``K(/``)$ +M0@`"I10``_`'``/HH``#Z+```V`2``/H````@>4``_0```'`:P`#0"P``_\` +M``*T(``"0$```_`"``/T```!PK4``T@(``*TOP`"0`0``V@(``/H````@C$` +M`C&#``#R,0`",8,``T@(``*T0``"8`0``V@(``/H````@C$``C"X``#R,0`" +M,+@``TD]``-(P``"M@@``D9D``/P`@`"M3```F(E``-HP``#:,0``B+G``-` +M(``#_P```_\```+"+@`#\$0``L,^``/P0@`"LO\``K/_``-@(``",@P``TM@ +M``/`C@`"0`@``VM@``-)2``#0"H``K0_``*U@``"MD```D9H``/P10`"0S0` +M`F,U``-I2``"0S0``VE(``/H```#Z!```^@@``/H,``#9*0``V3D``/T```! +MP````TL=``-`*``"O!```K\$``),P``#\`4``F=^``-K'0`",9X``F=_``-K +M'0`#[````T`$``!J,0`#Z(```^B0``/HH``#Z+```J#>``/P`P`#9*H``_0` +M``/P00`#9.H``&'I``*@W@`#\`,``^A```/T```#\$$``X3J``/80``#W,`` +M`'GH``/X`P`#U)X``_L```,/_@`"`PH``"'#``*@W@`#\`,``&'"``/T```# +M\$$``&'!``*_"``#W$```]C```/X`P`#U)X``_L```,/_@`"`QD``_@#``/L +M`````C(``&HQ``/_```"H`X``_`!``/L```#23@``J#>``/P00`#23@``KC^ +M``)"*``#:3@``TG0``*T!``"810``K(!``*S$@`"H-X``_!!``*S$0`#:#`` +M`TEQ``*X[P`"N00``\$&``)A>0`"0S@``V@P``-("0`"N/T``D1(``-H"0`" +MM`$``B/J``(M8@`#2:```K01``/!)``"L0\``VF@``*@W@`#\`,``T)A``/T +M```#\$$``T)=``/_```#_P```^A@``-II0`#:&L``KH,``*XP``#W($``]BA +M``*P^``"L0<``^@@``/H,``#_@```]0?``-H:P`#Z/```B/3``(CPP`")`4` +M`J'^``/P00`#8GH``T)X``/_```#_P```J"```'#=@`"H)$``<-V``*@H@`! +MPW8``J"S``'#=@`"S_X``KP,``*A_``#\$(``_0```'#8```^``#_P```_\```*@@``!PXP``J"1``'#C``"H*(``<., +M``*@LP`!PXP``L_^``*\#``"H?P``_!"``/T```!PWD``&'.``#YQ0`#_P`` +M`J7/``'#G``"I?P``<.7``/H\``#Z,```_0```'#GP`##,\``ZS```/H\``# +M]````<.?``,/_``#K_```^C```(CTP`#P?P``B/#``*P&``")"0``K0```(C +MZ@`#23@``J#>``/P00`#23@``_\```)B+@`#:3@``TG0``*T^P`"010``K(! +M``*S$@`"H-X``_!!``*S$0`#:#```TEQ``*X[P`"N?L``\$&``)!>0`"0S@` +M`V@P``-("0`"N`(``F1(``-H"0`"+8@``^P```/!#P`#P1\``\$O``/!/P`" +MH-X``_`%``-DL``#9+0``V2X``/T```#\$,``V3P``-D]``#9/@``B/A``/L +M```#P0\``\$?``/!+P`#P3\``J#>``/P!``#9*P``V2\``/T```#\$(``V3L +M``-D_``"(^$``^P```-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@` +M`^P```)-W@`#\$,``T +M``/!^``#[````^C```.'/``#IW8``X8L``.F:``#A1P``Z5:``.$#``#I$P` +M`FS'``)LQ@`";,4``FS$``/L```#0"0``&HQ``/_```#H`8``J$.``/P`0`` +M@?D``TFA``-)I``"NT```KJ_``)%I0`"H-X``_`#``)#HP`#]````_!!``)C +MLP`#::0``VFA``(RN@`#Z````^@@``/H,``"H-X``_`#```)^P`#]````_!! +M```)^@`"N,```VAK``/8```#W(```]0>``*_"``"+5X``X#@``"!]@``@?4` +M`^@```"!]```@?,``/'R``-(5``"H-X``_`#``.$Z``#]````_!!``.$Z@`" +M8B0``VA4``-)=0`#B.8``F!H``/!%P`#P2X``\$^``*@W@`#\`$``X,P``-H +M,``#2%0``J#>``/P`P`#A.@``_0```/P00`#A.H``\!$``)")``#:%0``&(+ +M``*_`@`"+5X``J#.``/P`@`#]````@2P``(O`@`#Z'```X3F``)&2P`"H&0` +M`_!*``-)T@`#Z&```XJR``.JJ@`"H:X``_`"``,!K@`")BL``_0```'%5@`" +MOP@``D_Y``.O]``#B[(``ZN\``(E;P`#]````<56``-`$``#_P```K\"``)/ +M\``#\`(``_0```'%5@`#0`P``_\```*_"``"3_```_!"``/T```!Q,@``K\` +M``*[`0`")6\```($``/_```#_P```J`.``/P0@`#]````<56``#Q]```\?,` +M`J#>``/P`P``>?@``_0```/P00``>?<``XWB``/,``$'Y``/HT``#C^```\&H``.,[0``X><``.(P``(N:P`"MP$``$'Y``/H +MH```T>,``J!^``/P`0`#J(```P_?``/!V0`#P:@``XSM``#AYP``XC```BYK +M``(NK``#P00``\$F``-B<``"OP$``T`1``.(X``"H/X``_`$``)$2``#\`(` +M`_0```(%/``"MP$``$'Y``/_```"H'X``_`!``.H@``#Z-```X_@``/!J``# +MC.T``.'G``#B,``"+FL``BZL``-"<``#C.L``XSJ``/H\``"R$```ZB````J +M"0`"RF(``ZJ@``*F7@`"!1D``&HQ``#R"0`#P5@``\%Z``-B<0`#]````@33 +M``*A7@`#\`X``&HQ``/!D0`#P;,``J#>``/P`P`#82X``_0```/P00`#83(` +M`L"!``.H```"PJ,``ZH@``.%4```J@D``X'@``,`A``#\"0``J&$``/P`0`" +MQ$$``P1.``/!5``#`J8``_`D``*AI@`#\`$``L9A``,&;@`#P78``]1>``)@ +M`@`"!2L``&HQ``*_`@`"+5X``TEQ``.!Y``#P08``Z)L``*@+@`"!58``F%Q +M``/!+@`#P3X``J#>``/P`0`#@S```X9@``/P1P`#:#```X_M``(M7@`#C^T` +M`BU>``./[0`"+5X``X_M``(M7@`#274``\$N``/!!@`#P1<``\$^``*@W@`# +M\`$``X,P``-H,````>4``_\```/_```"I0X``_!(``-`$0`"H-X``_`#``)F +M;@`#]````_!!``)G?@`#8!$``^@```"!Y0`#[````J#^``'%>P`"L`\``K$/ +M``*R#P`"LP\``J#>``/P`P`#8R@``_0```/P00`#8V@``C&>``-*0```0?(` +M`$GV``!1]0`"O#,``D0,``)%'``"9$4``D8L``)'/``"9F<``F1&``*A3@`# +M\`$``K0!``*@C@`#\`4``J1)``/P0P`"I$L``_!!``#Q]```H?8``KS,``)$ +M#``"11P``D8L``)'/``"9$4``F1&``)D1P`"H4X``_`!``*T`0`"H(X``_`% +M``*D2@`#\$,``J1+``/P00``\?,``*'U``/H0```H?(```'T```1\P`"L0\` +M`K,%``*E_@`"!=$``J#^``/P00`#Z/```J`.``/P`0`"S_X``K$0``*@+@`# +M\`$``L_Q``*SD``"IO,``_!"``#QY0`#[````D,"``/P0P`")A$``_0```'% +M>P`"M!$``P_T``*@W@`#\`,``/GQ``/T!``#\`$``/GP``-#*0`"H-X``_!! +M``-#:0`"OW<``B7P``/L```#2.4``J#>``/P00`#204``K@1``*@#@`#\`$` +M`L1(``))00`"I),``_`!``#Q]``"H"X``_`!``+%6``"25$``J23``/P`0`` +M\?,``J#>``/P`P`#:.4``_0```/P00`#:04``D`"``*@#@`"!7L``K$"``(F +M*P`#[````J'^``/P00`#[````Z'V``./]@`#H/8``J$.``/P!P`"O`D``J!, +M``/P00`"O`\``\%,``/!7``#``X``J$>``/P!P`"O`D``J!L``/P00`"O`\` +M`\%L``/!?``#`1X``J#>``/P`P`#8RD``_0```/P00`#8VD``F(!``(%]@`# +M[````T,I``*@W@`#\$$``T-I``*@#@`#\`4``K0/``),_@`#\`$``K0)``/! +M5``"H"X``_`&``*V#P`#K/8``DS.``/P`0`"M@D``\%V``*@W@`#\`,``V,I +M``/T```#\$$``V-I``/L```#2.4``J#>``/P00`#204``K`1``+$0``"Q5`` +M`J#>``/P`P`#:.4``_0```/P00`#:04``P$>``(&+P`#[````&HQ``/H```" +M+MP``/'O``/H````@>X``T`,``-`+0`"N!```KD(``)*&``#JJ8``DM)``.K +MM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!` +M``/P00`#Z#```D$>``/P`0`#Z#```)GM``(M8@`"N!```KG^``*@W@`#\`D` +M`T@A``*Z#P`"1FH``D=Y``)F:``#:"$``VJ)``/T```#\$<``T@E``*Z#P`" +M1FH``D=Y``)F:``#:"4``VJ-``(P@@`"OP,``C!.``*_9``"+5X``&HQ``/_ +M```#_P```J#>``/P`P`"NP```_0```/P00`"NT```-G@``/!#@`"L1$``K(0 +M``-J1``"L1```^@@``-J1``"L/\``K'_``*R_0`"L_\``VA@``-*8``"O_<` +M`K$3``)`#P`"8`X``VI@```Q_@``.?T``KP(``*__@`#AFH``F(F``*D?@`# +M\`$``K,$``)`#P`"8`P``VI@``./X0`"+5X``VAK``/_```#_@```&(O``!: +M+@`#_P```]C!``/``/0'P`#C.\``X_D``)O_@`"0`$``D(C +M``)``@`"3,```_L!``/0'P`##_X``@:L``*@W@`#\`,``T@A``/T```#\$$` +M`T@E``/`S``"!M@``XSF``+&;``#\$$``L=^``*@W@`#\`0``V@A``-JB0`# +M]````_!"``-H)0`#:HT``J5^``/P`@`#]````<9^``-`$0`"L`@``/'E``*@ +MW@`#\`,``F9@``/T```#\$$``F=P``-@$0`#]````@@*``.`X0`#@08``F$> +M``."YP`#:D0``X$&``/H(``#:D0``C""``-`+```6AT``K0$``/H\``"1$`` +M`_`!``*_`0`"I+X``_`!``*_!``",$X``/(9``#R%P`",K0``C""```*+0`` +M$?X``!G]``*P`@`"H-X``_!!``*P!``#@BH``J0^``/P`0`"LP0``X$6``)@ +M`0`"L3,``VI@``-`"@`"L`$``K$"``*R```"LP$``J`K``/P`@`#Z"```\$[ +M``-J:``#P0X``K()``)`"0`#\`$``^@@``*P$P`"L0(``X(F``/H,``#:G`` +M`&($```2&@`"H,X``_!!``*R!``"L"$``K$"``*S`0`#:G0```H=``*P`0`# +M_P```J0>``/P!0`"L00``K(```*S`@`#]`0``_`#``*Q`@`"L@\``K,!``-J +M>``#2GP``_\```*P`0`"L0(``K,$``-J?````>X``_\```/_```"P`X``('N +M``(P20```AD``T`*``-`#0`"H`X``_`%``*P`0`"0`4``X`&``/T!``#\`,` +M`K`$``)`"0`#@`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`" +MLP$``VID``(O%P`"+R0```'O``/_```#_P```J`.``/P3@`#0"P``KP$``/< +MP``#C^H``J#>``/P`0`#Z/```]CP``*\"0`"OS\``DL?``(MY0`#Z/```/GO +M```![@`#_P```_\```+`#@``@>X```GM``-`+@`#_P```J`!``('@P`"L`$` +M`D$(``/P!0```C(``_\```/_```"H`X``@>#``-*=``#23T``_\```.B5``# +M@B```T`)``*E+@`#\`$``K((``)%7@`#\`$``!(:``/_```#_P```VIT``(P +M20```AD``T`*``-`#0`"H`X``_`%``*P!``"0`4``X`"``/T!``#\`(``K`0 +M``)`"0`"L4,``F@!``-*9``"M(```!'@``)`!``"8`@``Z(B``/!/@`#:F0` +M`B\7``(O)```0@,``K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```''LP`# +M0`X``K`0``/_```"00D``J`0``('LP```AD``_\```/_```"P`X``((9``*Q +M`@`"I`$``@X``C!)``-`"@`"L$`` +M`_\```)`"0`#H`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`" +MLP$``VID``(O%P`"+R0``T`E``!"`P`"L"```D`%``/P2``"L`(``J#>``/P +M00`#@`(``D`(``/P`@`#]``````#[````&HQ``/_```#_P```J#>``/P`P`"NV(``_0```/P00`"NV@``_\` +M``/_````V>P``C#_``/H```"+MP``KL"``#:,``#Z````K%@``/H(``#Z#`` +M`VF@``/H```"L1```^@@``/H,``#:D0``C""``*_`@`",$X``K#_``*Q_P`" +MLOT``K/_``-H8```"BT``!'^```9_0`"L`H``J#>``/P00`"L`P``X$6``)@ +M`0`#@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+5X``VAK +M``/_```#_@```C!X``-*8```,?X``#G]``*T]@`"M0,``X9J``)B)@`"I'X` +M`_`!``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``# +M:F@``K"```*R"0`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P +M(0`"L0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\` +M``*P`@`"L0(``K,$``-J?``",K0``^AP``-*9``"M(```D`$``/H(``#Z#`` +M`VID``-*9``"M(```!'L``)`!``"M`,``F`$``*S$``#:F0``B\7``-*9``" +MM`@``D1```)G=``"I7X``@BQ``/H```"+MP``J#>``/P`P`#2"(``_0```/P +M00`#2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H(@`#:HH``_0` +M``/P0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R'8``T`2``#QY0`"OP0` +M`J#>``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R+$``C!X``/L```` +M:C$``/'O``/H````@@8``T`(``-`+0`"N$```KD(``)*"``#JJH``DM)``.K +MM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!` +M``/P00`#Z#```D$>``/P`0`#Z#```)H%```AY0`#Z%```_\```"B#```J>4` +M`&HQ``/_```#_P```J#>``/P`P``6<(``_0```/P0P``6<$``_\```/_```` +MV>```T`L``!:'0`"M`0``^CP``)$0``#\`$``K\!``)+O@`"H+X``_`#``(O +M?P`#]````0``/(8``#R%P`",K0``C""```*+0``$?X``!G] +M``*P`@`"H-X``_!!``*P!``#@18``F`!``-`%0`#@BH``K&```)B(0`"I#X` +M`_`!``*S!``"MO```D1&``*Q"``"810``VI@``-`"@`"L`$``K$"``*R```" +MLP$``J`K``/P`@`#Z"```\$[``-J:``"L`$``K((``)`"0`#\`$``^@@``*P +M$P`"L0(``X(F``/H,``#:G```&($```2&@`#_P```J#.``/P00`"L@0``K`A +M``*Q`@`"LP$``VIT```*'0`"L`$``_\```)!$``"I!X``_`%``*Q!``"L@`` +M`K,"``/T!``#\`,``K$"``*R#P`"LP$``VIX``-*?``#_P```K`!``*Q`@`" +MLP0``VI\```*'0`#_P```_\```)!'@`"I!X``@F%```"!@`#_P```_\```+` +M#@``@@8``C!)```"&``#0`H``T`-``*@#@`#\`4``K`"``)`!0`#@`0``_0$ +M``/P`P`"L`@``D`)``.````"L0,``F@!```"'0`#_P```_\```)`#@`"I`X` +M`_`+```2&@`"L",``K$#``*S`0`#:G0``TI\``/_```"L`$``K$$``*S!``# +M:GP``TID``*T@```$>```D`$``)@"``#HB(``K,!``-J9``"+Q<``B\D```! +M[P`#_P```_\```*@#@`#\$X``T`L``*\!``#W,```K_```*@W@`#\`$``K^` +M``/8\``#C.0``K\_``)+'P`"+>4``^CP``#Y[P```@8``_\```/_```"P`X` +M`((&``!:'0``>A<``K@(``)*O@`"H*X``AH` +M`_\```/_```#P2\``VIT``(P20```A@``T`*``-`#0`"H`X``_`%``*P"``" +M0`4``X````/T!``#\`,``K`@``)`"0`#H````K%#``)H`0`#2F0``K2````1 +MX``"0`0``F`(``.B(@`"LP$``VID``(O%P`"+R0``$(#``*P`0`"H-X``_!! +M``.``@`"0`@``_`"``/T```!R>L``T`*``/_```"L$```D$(``*@$``"">L` +M``(8``/_```#_P```L`.``""&``"L0(``J0!``()0@```>```$'#``/_```# +M_P```]@```/<@``"OP@``K#```/8`0`"L````]P!``(O#@```@8``_\```/_ +M```"P`X``((&``(P20`#0`H``K"```/_```"0`D``Z`$``*Q`P`":`$``TID +M``*T@```$>```D`$``)@"``#HB(``K,!``*Q```#:F0``B\7``(O)```0@,` +M`K`!``*@W@`#\$$``X`"``)`"``#\`(``_0```'*+0`#0"X``_\```*P"``" +M00@``J`0``(*+0`"L(```D$(``/P!0```C(``_\```/_```"H`X``@HM```" +M%P`#_P```_\```/H$```BA<``J0.``()A0``8<,``%G@``/_```#W,```]BP +M``*_"``"L,```]@!``*P```#W`$``C*Z``-H:P``$=8``K/```/HT``#8G0` +M`BX-``(P>``#[````&HQ``/_```#_P```J#>``/P`P`"NU,``_0```/P00`" +MNUL``_\```/_````V>P``T`0``*['P`#2"D``J#>``/P00`#2"T``D`+``.O +M`@`#C/8``FS/``./]@`#2>@``J-,``/P!``#!$P``P5?``/T```#\$(``P3$ +M``,%]0`#P00``\$5``*@W@`#\`0``V@I``-IZ``#]````_!"``-H+0`#:>P` +M`^@```(N\``#Z````K%```/H(``#Z#```VI$``(P@@`"OP(``B]_```*+0`` +M$?X``!G]``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`"L80``F(A``*D +M/@`#\`$``K,$``*Q&``#:F```T`*``*P`0`"L0(``K(*``/H,``#:F@``K"` +M``*R"``"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`"L0(` +M`K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P`@`" +ML0(``K,$``-J?``",K0``^AP``(P20`#2F0``K2````1[``"0`0``K0#``)@ +M!``"LQ```VID``(O%P`#2F0``K0(``)$0``"9W0``J5^``(*[P`#Z````B[P +M``*@W@`#\`0``T@J``-)Z``#]````_!"``-(+@`#2>P``KP1``*_$``"R9\` +M`LB,``/P00`#Z(```\$(``/!&0`"H-X``_`$``-H*@`#:>@``_0```/P0@`# +M:"X``VGL``-*P``"OP<``DW>``/P`0`"OS@``J&.``/P0P`"8`\``VK```-J +MQ``"NP$``-HP``/H<``"3_```_`#``*[_P`"H(L``_`"``/T```!RJ<``T`2 +M``#QY0`"OR```J#>``/P`P`":J\``_0```/P00`":[\``V`2``(P@@`",$D` +M`^P```!J,0`#Z````(',``""#``"H-X``_`#``!9P@`#]````_!!``!9P0`" +ML'\``J'^``/P00`"2[```-G@``(RM``",((```HM```1_@``&?T``K`"``*@ +MW@`#\$$``K`$``.!%@`"8`$``X(J``*Q@``"8B$``J0^``/P`0`"LP0``T`5 +M``*Q"``"MO```D1&``)A%``#:F```K`!``*Q`@`"L@```K,"``-J:``"L@@` +M`K`3``*Q`@`#@B8``^@P``-J<```$AH``K`A``*Q`@`"LP$``VIT``*P`0`" +ML0(``K(/``*S`0`#:G@``TI\``/_```"L`$``K$"``*S!``#:GP``KP$``/< +MP```>>```KP(``*[&``#V/```BWE```!S``#0"4``K\0``+`#@``@```K"```/H\``"H<```_!!``/!_@`"*[8``C!)```1X``# +MZ!```K`C``.B(@`"LP$``VID``(O%P``8``/[```"I2X``_`!``/[```#U)\``_L!``*E+@`#\`$` +M`_L!``,/_@`""V\```',``/_```#_P```L`.``"!S```8>```K"```/!_@`" +MH<```_!!``/H\``"*[8``C!)```1X``"L`,``^@0``.B(@`"LP$``VID``(O +M%P`"+R0``T`E```!S``"L0,``K((``*S$``"0S4``_`"``)")0`#\`(``J4! +M``'+.@``8<,``%G@``/_```#W,```]BP``*PP``#V`$``K````/<`0`"OP@` +M`C*Z``-H:P``$=8``K/```/HT``#8G0``BX-```"#``#0!$``K&```)`#@`# +M\`,``F9A``-@$0``@>4``C!X``/L```"O!$``J#>``/P!``#2,P``TC1``/T +M```#\$(``TCL``-(\0`"*^X``J#>``/P!``#:,P``VC1``/T```#\$(``VCL +M``-H\0`"H-X``_`$``-(U``#2-D``_0```/P0@`#2/0``TCY``(K[@`"H-X` +M`_`$``-HU``#:-D``_0```/P0@`#:/0``VCY``*@W@`#\`,``TC<``/T```# +M\$$``TC\``*@_@`#\`0``L`,``+!'``#]````_!"``,`#``#`1P``J#>``/P +M`P`#:-P``_0```/P00`#:/P``^P```*@_@`#\`D``L`,``+!'``"PBP``L,\ +M``+$3``"Q5P``L9L``+'?``#[````P`,``,!'``#`BP``P,\``,$3``#!5P` +M`P9L``,'?``#[````K@/``*Y\``"2@@``DL)``(L'0`"2A@``DL9``(L'0`" +M2B@``DLI``(L'0`"2C@``DLY``(L'0`"2D@``DM)``(L'0`"2E@``DM9``(L +M'0`"2F@``DMI``(L'0`"2G@``DMY``(L'0`#[````J&N``/P00``\@P``J&^ +M``/P00``\@P``^P```*P?P`"L?\``K+_``*S_P`#:&```VAK```)U@`#Z``` +M`Z`#``/<```#V!```T`Q``*_`P`"O`(``J;\``/P00`#P0<``J#\``/P00`# +MP08``J#^``/P00`#P04``J'^``/P00`#P00``\$0``/!(``#P3```_X```/4 +M'@`#:&L``_L```,/_@`"##(``T`U``*_`P`#_P```J;\``/P00`#P0<``J#\ +M``/P00`#P08``J#^``/P00`#P04``J'^``/P00`#P00``\$0``/!(``#P3`` +M`_X```/4'@`#:&L``_L```,/_@`"#$H``T`X``-`/0`#_P```VJ$``-J@0`# +M[````TA5``/_```"M\```VA5``-H:P`#2`H``K]_``)H^``"LN\``Z"!``*_ +MPP`"0`\``T`E``*S_P`"L?\``D]>``/P`@`"N?,``D(I``*\`@`"3%P``_`! +M``*S^P`#:&```TA```./\@`"O/L``D$<``)A'P`#:$```VAK``-)?``"M`0` +M`F$4``-I?``#2I0``_\```-A?``#:&L``C&>``/_```#_@```_\```-!20`# +MZ/```]SP``-(9``#B$0``ZB```*\0``"S,@``]C```/4'@`",L```V%)``-( +M9``"M!```D8D``/P`@`#]``````*_ +M4``"+5X``K\(``(M7@`#]``````#:"T``VGM``-(R``"N/L``D(H``-HR``#2)@``K@@``)@"``# +M2+$``VB8``)D2``#:+$``\$.``/!'@`#P2X``\$^``-C,``#8W```V,T``-C +M=``#8S@``V-X``/T```!S4H``T@(``*X]P`"0`@``V@(``-(*``"N-\``D,X +M``-(+0`#:"@``VGH``)'>``#:"T``VGM``-(R``"N`0``F(H``-HR``#2)@` +M`KC?``)`"``#2+$``VB8``)$2``#:+$``K`#``/!$``#P2```\$P``-C,``# +M8W```V,T``-C=``#8S@``V-X``-)?``"M/L``D$4``-I?``#:&L``_0```', +MBP`#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(``VC*``)H(0`#:,H``\&" +M``-HR@`#[````_@#``,/_@`"#5\``^P```(RN@`#:&L``\$.``/H$``#Z"`` +M`^@P``.D$P`#V!```]Q```/^```#U!X``VAK``-II``#Z````_X```/4'@`# +M:&L``VFD``*@W@`#\`,``T)@``/T```#\$$``T)<``-"60`"H-X``VFD``/P +M`P`#0F@``_0```/P00`#0F0``VFA``/^```#U!X``VAK``-H:P`#[````C*Z +M``-H:P`#0E8``\$.``/H$``#Z"```^@P``.D$P`#V!```]Q```/4'@`"OP(` +M`BU>``-H:P`#::0``VFB``/H```#_P```]0>``*_`@`"+5X``VAK``-II``" +M,KH``VAK``/L```#:&L``C*Z``*Q#``#Z````Z`#``/<```#V!```^@```/H +M$``#Z"```^@P``/^```#U!X``VAK``/[```#^P```XCC``/X`P`#_@```]0> +M``-H:P`#^P```PB.``(-M``#[````"'K``/H4``#Z&```^AP``*Y"``"N,`` +M`]R!``/8D0`#0E```_@#``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`# +M:&L``\&/``*_$``"+5X``K09``/^```#U%\``VAK``*_$``"+5X``\'X``-) +MI0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``#"9X``@WA +M``-II0`#[````J&^``/P#@`#T!X``P^^``*Z/P`#``X``D`*``,!'@`"01H` +M`P(N``)"*@`#`SX``D,Z``/4'@`##_X``@WJ``/[```##,X``@WE``/L```" +MH;X``_`.``/0'@`##[X``KH_``+`#@`"0`H``L$>``)!&@`"PBX``D(J``+# +M/@`"0SH``]0>``,/_@`"#?X``_L```,,S@`"#?D``^P```/0G@`#T!\``KP_ +M``)(C``"29P``DJL``)+O``"1`P``D4<``)&+``"1SP``KP@``+`A``#H``` +M`J-(``/P00`"P`P``L&5``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`# +M\$$``L(L``+#MP`#HS```J-[``/P00`"PSP``KP'``*CW``#\$X``W)T``-2 +M=@`#_P```_\```/^```#U!X``VAK``/[```#<``&(P``/_```"H;X``_!"``#QY0`#[````J'.``/P00`#"[X` +M`PS.``#9YP``XC```TI```!:"0`#_P```_\```*@O@`#\$(``Z````.B(``# +MT%X``&'\``!9XP`#H@(``D`)``)"*0`"I8X``@Z6``,(C@`"H`T``_`+``!! +M^0`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$3P`#P50``J6N +M``(.I@`#"JX``J`M``/P"P``4?D``L9O``/!=@`"H+X``_!&``/47@`"QF\` +M`\%V``/47@`"QF\``\%V``/47@`##,X``@ZG``)KB@`"#FL``^P```-"<``` +M4@D``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``"H6@``_!!``+& +M:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,&:``#`B@``P,X +M``,*K@`"#KH``\%4``/!=@`#U%X``V)P``/L```#P6(``P9N``/<$``#V``` +M`]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X``_L```,&;@`" +M#L\``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``#:1```VD4``-I +M&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I-``#[````\$0 +M``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC<``/T```#\$4` +M`VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4``D$#``-)T@`# +M_P```D`*``-)P@`"I1```_`!``-)Q@`#[````]">``/[```#_P```_\```/4 +MGP`#^P$``P_^``(/#@`#[````_@!``*_!``#2F0``_\```/_```"00\``@\9 +M``/X`P`#:&L``_\```/_```#_@```^P```-*9``#_P```K\(``)!#P`"H!\` +M`@]%``-`$@`"M1```J4E``/P!``"OP(``FJO``/T```!ST(``L15``*E)``# +M\`0``K\"``)KOP`#]````<]"``+$10`"I20``_`$``*_$``":J\``_0```'/ +M0@`"OQ```FN_``#QY0`#8!(``B]&``/L```#2G```_\```/!P@`#0"X``K`! +M``-JJ``#_P```_\```/_```#2JP``K0"``-JJ0`#P````\`1``/`(@`#P#,` +M`TJM``*_D``"H,\``_`%``/`1``"OP\``D]/``/T```#\$$``\#T``*@W@`# +M\`L``T`9``/_```#_P```F1```)E40`"9F(``F=S``-@&0`":J\``_0```/P +M20`#0!T``_\```/_```"9$```F51``)F8@`"9W,``V`=``)KOP`#8"X``^P` +M``+$1@`#:JD``_\```/_```#_P```TJL``/L```",KH``VAK```)U@`"L,`` +M`]P```/8$``"H/X``_`$``/H```#Z!```^@@``/H,``"H/X``_!$``*P50`# +MP1```\$@``/!,``"H/X``_`$``*T_P`#P50``\%D``/!=``"H/X``_!$``*T +MJ@`#P50``\%D``/!=``"O`<``J/^``(/^```0?\``_\```/_```"H(X``@^^ +M``*@W@`#\`,``T!"``/T!``#\`$``T!&``#J,0``:@```J3>``/P!``#P(@` +M`\"9``/`J@`#P+L``F`(``)A&0`"8BH``F,[``)D2``"95D``F9J``)G>P`` +M:C$``_\```/_```#_@```]0>``-H:P`#^P```PS.``/^```#U%X``VAK``/[ +M```##,X``@^^``!!_P``8@```_\```*@C@`"#^,``T!*``*DS@`#\`0``\"( +M``/`F0`#P*H``\"[``*DW@`#\`(``\&*``/!FP`"N@\``DJH``.+I@`":JL` +M`KOP``)+N``#I[8``FNW``/T!``#\`,``^A@``/HH``#Z+```K3P``)@2@`# +MP1```\$@``/!,``#:H0``J#^``/P`P`"M/```_0$``/P`0`"M`\``F!+``/! +M$``#P2```\$P``-J@``#[````_X```/4'@`#:&L``_L```,,S@`"N0,``J#Y +M``/P1``#Z$```^A0``/H8``#Z'```_X```/47@`#:&L``_L```,,S@`"$`0` +M`K#P``*Q_P`"H/D``_!"``/H```#Z!```\$A``/!,0`#:H0``VJ```/L```" +M,KH``VAK```)U@`"L,```]P```/8$``"M/\``\%D``/!=``"O`<``_X```*U +M_P`#U%X``VAK``/[```##,X``_X```*U[P`#U%X``VAK``/[```##,X``A`? +M``*U_P`#:H4``K#P``/!$``#P2```\$P``-J@``#2F(``C!)``/H\``",%4` +M`VIB```)U@`"L,```]P```/8$``"M/\``\%4``/!9``#P70``KP'``/^```# +MU%X``VAK``/[```##,X``A!!``(RM``#[````TID``*T@``"0`0``VID``/L +M```"L`0``J#P``/P`P`"+W\``_0$``/P`0`"+"0``^@```/````#P1```K+] +M``*S_P`#:&````HM```Q_@``&?T``K`*``*@W@`#\$$``K`,``.!%@`"8`$` +M`K$6``*D/@`#\`$``K,$``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`" +ML@0``F(F``-J8``#C^$``BU>``-H:P`#_P```_X```/L```#2F```_\```/H +M,``"8`X``VI@``-*9``"M/(``D`$``-J9``#[````K`!``/H$``#Z"```^@P +M``-J8``#[````&HQ``-`!``#_P```K@$``)%X``"H%X``_!$``*@W@`#\$(` +M`T`D``/_````8>D``_\```/_```#W,```X_J``*@W@`#\`$``^CP``/8\``# +MC.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<``D`(``/P +M0P`"+>4``_0```/P00`"+?D``D1N``/P"0`#Z,```ZMB``.E8``"15X``_!# +M``(MY0`#]````_!!``(M^0`#[````&HQ``-`*``#0"$``KA```)(@``#\`,` +M`D9N``/P`0`#[````%'#``*@W@`#\`,``%G"``/T```#\$$``%G!``/_```# +MW*```]BP``-`!@`#_P```_\```)`Z``#\`,``J#>``/P00`#0"8``_\```/_ +M```#24$``J`.``/P0P`"H-X``_!!``/!10`"14X``_!#``.,Y``#]````_!! +M``.,XP`#B9@``ZJ<``*@K@`#\`,``BWE``/T```#\$$``BWY``-`!@`#_P`` +M`_\```-)00`"0(X``J`.``/P0P`"H-X``_!!``/!10`#Z,```ZM"``)%3@`# +M\`<``Z5```)%7@`#\$,``BWE``/T```#\$$``BWY``/L```"H-X``_`#``-( +M(0`#]````_!!``-()0`#_P```KL!``.B9@`#@68``Z$6``.'=@`"8"<``P`+ +M``.G!@`#@@8``F8A``*@W@`#\`0``V@A``-JB0`#]````_!"``-H)0`#:HT` +M`^P```./[0`"+5X``^@P``."X``#Z!```^@```-H,``#C^T``BU>``-)G``# +M2=4``T`J``*T$``"1$<``K4"``)%6@`#A50``D1%``.D0``"MO<``D(F``)B +M)``#:9P``^CP``-)<``#Z'```K8!``/!40`#P4```V@Q``*X_``#P5,``\%" +M``)%6``#270``C&>``-H,0`#P5$``\%```(QG@`#:#$``\%3``/!0@`#29@` +M`C&>``-H,0`#P5$``\%```(QG@`#:#$``\%3``/!0@`#29P``C&>``-H,0`# +MP5$``\%```(QG@`#:#$``\%3``/!0@`#2.@``C&>``-H,0`#P5$``\%```*W +M$``",9X``V@Q``/!4P`#P4(``C&>``-H,0`#[````KP#``-)/0`#2,```J#> +M``/P00`#2,0``K8$``)&9``#\`0``X;*``/!?``"8B8``F$7``*@W@`#\`,` +M`VC```/T```#\$$``VC$``-`*@`"M@@``X?&``)&:``#\`$``F,W``*@W@`# +M\`,``VC```/T```#\$$``VC$``/L```",(@``TD]``-`*``"OP@``KP$``)/ +M#P`"3$P``F#\``/P00`#[````K0!``(R7``",6,``J'^``/P"0`",AT``C"" +M``-`*``"O`@``_\```)"+``#\$(``_0```/P0@`#Z$```C)<``/L```#_P`` +M`_\```/_```#[````V%(``-A00`#848``V)_``/!#@`#Z!```^@@``/H,``# +M:.@``^@```/_```#:.@``T%(``/_```#[````C*Z``-H:P``"=8``^@```.@ +M`P`#W````]@0``*\`P`"L/<``J#^``/P00`"L'\``\$0``/!(``#P3```K3_ +M``/!5``#P60``\%T``/^```#U!X``VAK``.@`0`#H1$``Z(A``.C,0`#^P`` +M`_X```/47@`#:&L``_L```,,S@`"$<0``K#_``*\"``#P1```\$@``/!,``# +M:H```J3^``'1W@`"H/P``_`"``-JA``#[````K#W``.A`0`#HA$``Z,A``-J +MA``#[````TD]``/_```"N(```F1(``-I/0`"L`$``K$"``*R/P`"0B\``K,` +M``-J:``"L````K$```*R```"LP(``VIT``*Q`0`"L@@``K,```-J>``"L`$` +M`K(```-J?```$>```K#```)`#P`#H`(``F`.``*Q```#HB(``K,!``-J9``" +M,K0``_\```/_```"+Q<``KA_``)$2``#:3T``^P```/H```#Z!```K(#``*S +M```#:#```^P```-`+``#_P```_\```/H(``#Z#```V`L``/H```#Z!```V`8 +M``-@'``#[````&HQ``*P`0`#Z!```^@@``/H,``#:F```K\!``(P3@`"OQ`` +M`BU>``*\%``#2F```K_W``*Q$P`"0`\``F`.``-J8```,?X``#G]``*\B``" +MM?X``X9J``)B)@`"I'X``_`!``*S!``"0`4``F`,``-J8``#2I8``T`I``*\ +M!P`#_P```D1,``.%1``"Q5X``\'%``/H0``#Z&```^AP``-JD0`"M/\``K5_ +M``*V_P`"M_\``VAA``-H:P`#_P```_X```,)G``#\$4``\"9``,*K@`#\$(` +M`\"J``,+O@`#:I(``X````.@```#:F```K\0``(M7@`#[````T`J``-'+``" +MH-X``_!!``-';``"MG\``X5,``)`!@`"29X``_`!``)@!0`#P1```\$@``/! +M,``"H-X``_!$``-G+``#9S```_0```/P0@`#9VP``V=P``-'-``"H-X``_!! +M``-'=``"MM\``X5(``)`!@`"8`4``\$0``/!(``#P3```J#>``/P1``#9S0` +M`V``#2,```J#>``/P00`#2,0``K8_``)")@`" +MML```J!.``/P`0`#Z&```F(F``*@W@`#\`,``VC```/T```#\$$``VC$``/L +M```#29@``K@/``*Y]0`#Z#```\$N``*@S@`#\`(``F`(``)!&0`#:#```T@( +M``*X0``"H,X``_`"``)@"``#:`@``^P```-A4``#854``V%:``-A7P`"+&4` +M`T%0``-!50`#05H``T%?``/_```#_P```^P```*P_P`"L;\``K+_``*S_P`# +M:&```^P```*P?P`"L?\``K+_``*S_P`#:&```^P```+$3@`#\$H``L5>``/P +M2``"QFX``_!&``+'?@`#\$0``K3_``*U_P`"MO\``K?_``/L```"H``/_```#_P```PS.``(2T``#[````K#_``*Q_P`"LO\` +M`K/_``-JD``#[````^@```"",0`"(O,``/(Q``(B\P`",U@``BU1``-)F``" +MM/,``K4/``)!%``"8`4``VF8``/!+@`#Z#```V@P```""@`#@>```^A```*@ +M`0`#\`$``\%.``(TN@`#2`@``KC^``)!&``#:`@``KP```(T90`"-)8``T`! +M``/H````@C$``D1.``/P`0`")$@``T`!``/_````\C$``D5>``/P`0`")$@` +M``(*``.!X``#_P```J00``/P`@`#P4X``C2Z``*\`0`"-&4``C26``*_`P`" +M-T```C.E``(O`@`"OQ```D_[``'30```>``(NW``"+P(``X3B``/! +MR0`#Z````K$#``*R"@`"LRT``D1)``/P`0`"LR\``^A0``(NRP`#@.H``B[+ +M``*X+P`"M`(``D1,``/P`0`"N"T``\&8``/!J``#P;@``V,J``-C:@`"+P(` +M`X'B``.@X0`#HY8``X+D``+"+@`#Z%```B[+``.@XP`"+LL``B\"``.`Y0`" +M0*```\$0``/!(``#P3```V2H``-DZ``#@.```H((``)"`@`#@B0``)'4``/L +M```"+P(``TEP``)$C@`#\$,``K7S``)")0`#:7```^AP``/!;@`#P5,``\%" +M``-H,0`"1)X``_`&``-)G``#I.$``F(D``/!4P`#P4(``V@Q``)$C@`#\$T` +M`TF<``.$Y0`#I><``D`$``)!%0`#I(@``X1```.%1@`"8`4``F$4``/H,``# +MP2X``V@P``-#I```(=0``K7/``)`!0`"8`0``\$0``/!(``#P3```V.D``-C +MY``"1$0``_`!``(W.P`#@80``Z`8``."!@`"8`(``^C0``(N\``#P=X``B[P +M``-)T0`"+P(``^A@``*E$``#\`$``K9```)&=@`#IFH``TB0``.DN@`"H$X` +M`_!!``*T!``"M0,``J!%``/P00`"M`$``K7P``)!%0`"810``K?^``)`!P`" +M8`8``VB0``-HJ``#:)0``VBL``.@I@`#P1```\$@``/!,``#9"0``V1D``.* +MM@`#2"$``K@#``)F:``"N0\``KO^``)&:0`"9FH``D=[``-H(0`#:HD``V@E +M``-JC0`#2`@``T@A``)A'@`#:`@``TC(``*X0``"N3\``F`(``-HR``"0`D` +M`VC(``/L```#0"P``KA```*Y@``#Z+```TJE``)(&``#\`$``KLP``))&0`# +M\`(``KK```)KN@`"95L``VJE``-(G``"O'L``D`,``-HG``#:*```VBT``-H +MN``#2)```X3B``.EYP`"014``F$4``*U_@`"0`4``VB0``-HJ``#:)0``VBL +M``-).``"M0,``F(E``*U\P`"0B4``VDX``/HP``"-&4``C26``/H```"L0,` +M`K()``/H,``#Z%```B[+``.`Z@`"+LL``K`$``/!$``#P2```\$P``-C)``# +M8V0``K`@``/!$``#P2```\$P``-C*``#8V@``C<[``-("``#2"$``ZCM``)! +M&``#:`@``ZCK``)&:``#P#X``D53``-H(0`#:HD``V@E``-JC0`#Z$```C2Z +M``/L```#0"D``_\```*X*@`"0EX``_`!``*X9``"H,X``_!!``*X$``#P9@` +M`\&H``/!N``#9RX``V``/`%``#H1P``X$4``*P +M]P`"2(```FB!``-HG@`#:*(``VBV``-HN@`#2NH``K#[``.!(@`"2J```FJA +M``-JZ@`#:NX``VKR``-J]@`#[````T`I``-'-@`"L`<``K$(``)"7@`#\`$` +M`K$8``*@S@`#\$$``K$```)(@``":($``\&8``/!J``#P;@``V@,``_\```*AB0`!U4@``P_^``*P$``"S_```^@` +M``"!Y0`#]````=4&``+/_@``^@,``,(&``/T```!U08``^C```#B`P`#Z#`` +M`C;'``/``/_```# +M^P```P_^``(560`"-K,``&(#``*P```#W````]P!``./P@`"L$```L`/``/8 +M```"L#\``D$/``*PP``"P`$``]@!``/47@`#T!\``K\0``*ASP`!U7H``J#> +M``/P`P`#P0H``_0$``/P`0`#P0L``]0?``/T```!U8$``J#>``/P`P`#P2H` +M`_0$``/P`0`#P2L``]0?``(V:P`#0`8``K`?``*Q(``#P2X``D$8``/P`0`" +MPBX``LS"``#B`P`"I<```A5>``-*E``#_P```V"\``-`!``#W.```K\(``/8 +M\``#W.$``K\L``/8\0`"OP@``ZP6``*ESP`#\$,``\#,``)LSP`"S,X``K\( +M``/0'@`#T%\``\&)``/!F@`#P:L``L1```.@0``"P`P``\&P``+%40`#H5`` +M`L$<``*F&P`#\`$``\&Q``+&8@`#HF```L(L``*F*P`#\`$``\&R``+'@`#!P<``_0$ +M``/P`@`#!WH``L=P``/47P`#^P```_L!``/07@`#"(X``A8%``*X`0`#P0$` +M`\$2``/!(P`#"9X``A8%``-$J``"H-X``_!!``-$Z``"H4P``_!%``/`1``" +M1$H``P0$``/T!``#\`(``P1*``+$0``"H5P``_!%``/`50`"15H``P45``/T +M!``#\`(``P5:``+%40`"H6P``_!%``/`9@`"1FH``P8F``/T!``#\`(``P9J +M``+&8@`"H7P``_!%``/`=P`"1WH``P``/!D``"H<\``_`!``/!D@`#8G4``,G.``/``/0GP`"00X``_!$``*@0@`#\$$``\%,``/!C``# +MH````D$.``/P1``"H%(``_!!``/!7``#P9P``Z````)!#@`#\$0``J!B``/P +M00`#P6P``\&L``.@```"00X``_!$``*@<@`#\$$``\%\``/!O``#U%X``]2? +M``/[```#^P$``Z````,/_@`"%HX``^P```*S$``"I<,``_`&``/`/``#@S8` +M`Z,V``(VT``#]````=;```*S#P`"S,X``D,\``(VQP`",A(``BU1``(TQP`" +MOQ@``CC&``(O1@`#[````K$$``*P@``"H-X``_!!``*PP``"L@D``^A0``(N +MRP`#[````\$#``/!$P`#P2,``J#>``/P`P`#9*@``_0$``/P`0`#9.@``^P` +M``-`!``"O(```_\```),P``!UOH``T$!``*@W@`#\$$``T$%``*Q!``"L(`` +M`J#>``/P00`"L,```]P0``/8```#P80``C<7``/!A0`"-Q<``\&&``(W%P`# +MP8<``C<7``*@W@`#\`,``V2A``/T!``#\`$``V3A``/T```!UQ0``K$$``*P +M@``"H-X``_!!``*PP``#W!$``]@!``*Q`0`"L`@``J#>``/P00`"L"P``]P0 +M``/8```"OP@``B\.``-!`0`"H-X``_!!``-!!0`"H-X``_`#``-DJ0`#]`0` +M`_`!``-DZ0`"+5$``C3'``/L```#P9@``\&H``/!N``"L@$``]2>``/[```# +M`BX``A<;``/L```"L00``K"```*@W@`#\$$``K#```/<$``#V````K$!``*P +M"``"H-X``_!!``*P+``#W!$``]@!``*_"``"+PX``T2H``*@W@`#\$$``T3H +M``*@W@`#\`,``V$```/T!``#\`$``V$$``/L```#2PP``K7\``)!%0`#:PP` +M`^P```-+#@`#P,\``FJO``-K#@`"2JP``TG5``*\"``#CW8``Z_T``+/_``" +M+5X``VL.``/L```#2PX``\#/``)JKP`#:PX``C&>``)*K``#:PX``^P```*_ +M`P`"-T```TG```-)U0`"3`X``_!"``/T```!UY(``TG```.'=@`"IG```_!" +M``/!$@`#Z````Z(6``.!%@`#H18``TB1``*\\``"15P``F52``*\!``"0PP` +M`Z,R``*\_@`"1$P``F1#``-HD0`#:)4``VBI``-HK0`#P4$``\%1``/!80`# +MP7$``V0A``-D)0`#9&$``V1E``*\`@`"0@P``X(J``-(G0`"LW\``D1#``)D +M0@`#:)T``VBA``-HM0`#:+D``J$.``/P`@`"-SL``K`0``/!$``#P2```\$P +M``-CH``#8Z0``V/@``-CY``"+5$``TE\``*T^P`"010``VE\``-H:P`#]``` +M`4``\&K``(M8@`"+;L``K0/``(QG@`#2D```_@!``*D0``#\`8``J1! +M``/P!``"I$(``_`"``*@0P`"&````LJN``*P(``"H*```_!!``/HH``"H*L` +M`A@J``-(&0`"LN```D9B``)F:@`#:!D``TGE``/_```"1F(``F9J``-IY0`# +M]`0``A?@``*C_@`"�``-'0``*@W@`"&`D``-'1``+-W@`#]`0``A>_``!! +MT0`#_P```_\```*@J``"�``J&H``/P2``#2"$``P.*``.#,``"9W,``V@A +M``-JB0`#]`0``A@T``-(&0`"LN```D9B``)F:``#:!D``TGE``/_```"1F(` +M`F9H``-IY0`#2"4``P.H``.#,``"9W,``V@E``-JC0`#]`0``A@T``-`$0`# +MZ,```/'E``*X@``"9W@``V`1``-)F``"M00``F$5``-IF``#2`@``_\```.$ +MR``"8`0``V@(``/X`P`#[````&HQ``/H````@@P``('/``(Y-``#0"0``_\` +M``/_```"0`X``_!+``-`$``"O`0``]S```./Z@`"H-X``_`!``/H\``#V/`` +M`KP)``/!L0`"+>4``T`D``/_```"O`(``D`,``/P2P`#0!```KP$``/``/P`0`"OX```]CP``.,Y``#P;$``BWE``(L)``"M`8``K4(``*V +M!``".1@``K\8``(XQ@`"..T``K\```(P3@`#2G```_\```/_```"LI```VIP +M``*_$P`".,8``CCM``-`)``#_P```_\```)`#@`#\$L``T`0``*\!``#W,`` +M`X_J``*@W@`#\`$``^CP``/8\``"O`D``XL0``(M^0`#0"0``_\```*\`@`" +M0`P``_!+``-`$``"O`0``]S```*_P``"H-X``_`!``*_@``#V/```XSD``.+ +M$``"+?D``TIP``/_```#_P```K*```-J<``"OQ@``CC&``(X[0`"OP```C!. +M``-*<``#_P```_\```*RD``#:G```K\3``(XQ@`"..T``T`D``/_```#_P`` +M`D`.``/P2P`#0!```KP$``/``/P`0`#Z/```]CP``*\"0`# +MP;$``BWE``-`)``#_P```KP"``)`#``#\$L``T`2``*\!``#W,```K_```*@ +MW@`#\`$``K^```/8\``#C.0``\&Y``(MY0`".58``^P```/H```#P````K&_ +M``/!(``"L_\``VA@``(P@@`",$D```HM```1_@``&?T``K`"``*@W@`#\$$` +M`K`$``.!%@`"8`$``X(J``*QA``"8B$``J0^``/P`0`"LP0``\$?``-J8``# +M2F0``K2````1[``"0`0``K0#``)@!``"LQ```VID``(O%P`"OP@``D_P``/P +M`0``\@P``^P````"#``#_P```_\```*E#@`#\`$``^P```/H````@@P``T`2 +M``/_```#_P```D2.``*@3@`#\`$``/'E``*_0``"H-X``_`#``)JKP`#]``` +M`_!!``)KOP`#8!(``B]&``!YSP`#_P```T`@``*@_@`#\$$``^P```*@W@`# +M\`4``L`.``/P00`"L/\``_0```/P0P`"P1X``_!!``*Q_P`#8"```/'/``/L +M```"L`$``K$"``/!)``#Z#```VIH``/!)0`"L!,``K$"``.")@`#Z#```VIP +M``*P(0`"L0(``\$F``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP` +M`_\```*P```"L0```K,$``-J?``#[````K`!``*Q$0`"LA```VI$``*Q$``# +MZ"```VI$``*@W@`#\`,``KM3``/T```#\$$``KM;``#9[``#2`@``K1```"! +MY@`"8`0``V@(``-(`0`"L+\``D1```-H`0`#Z````K%```/H(``#Z#```VI$ +M``*P`0`#Z!```^@@``/H,``#:F```^P```(P@@`",$D``"'F``/_```#2`@` +M`_\```/!!``#:`@``^P````*,@``:C$``_\```)`'@`#\$$``^P```(Y-``" +MOP```C!.```R&@`#_P```K4)``.F8@`"QFX``L1N``(Y&``#0"@``^CP``*@ +MW@`#\$$``K]```#YX``#H`P``('%``-`&``#0!T``T`N``!AY0`#_P```_\` +M``-A4``#854``V%:``#AQP`#0!```'G@``*\!``#W,```]CP``*\"0`#P;$` +M`BWE``/HP```X``/47P`"OP$``]SP``*_```#B,(``L_X``/8\``# +MQ````\01``/$(@`#Q#,``J#>``/P00`#P6<``K41``)$90`#Q$0``L`$``*U +M(@`"1&4``\1$``+!%``"M40``D1E``/$1``"PB0``K6(``)$90`#Q$0``L,T +M``/4'@``><4``T)U``-"<@`"3_X``_!"``+``0`"PB,``J$$``/P1@`"I0D` +M`_`$``/!C``#P9```\&L``/!L``"HPD``_!"``/!K``#P;```V)R``-"1@`" +MH28``_!&``*E*0`#\`0``\&,``/!D@`#P:P``\&R``*C*0`#\$(``\&L``/! +ML@`#8D8``J#^``':&``#0DX``J$5``/P1@`"I1D``_`$``/!C``#P9$``\&L +M``/!L0`"HQD``_!"``/!K``#P;$``V).``-"2@`"H3<``_!&``*E.0`#\`0` +M`\&,``/!DP`#P:P``\&S``*C.0`#\$(``\&L``/!LP`#8DH``V)T``/[`0`" +ML1```LS.``#AS@`"H,$``=FA``-"<``#0D4``_\```+(`@`#J(```LI&``.J +MH``#0DP``T))``/_```"R0(``ZF0``++1@`#J[```CI%``-`$```>>```KP$ +M``/4``^P```*[(0`"NQ````'%``/_```# +M_P```D`.``':?0`#J80``ZND``*\#P`#B(```DB,``.*H``"2JP``TB<``-( +MH0`"H-X``_!"``-(M``#2+D``\$8``/!6@`#C!8``X]6``)A'``"95\``J#> +M``/P!``#:)P``VBA``/T```#\$(``VBT``-HN0`#2N@``TKM``*@W@`#\$(` +M`TKP``-*]0`"O.X``D`,``)$3``#B)8``FR8``)@#``#BK8``FRZ``)D3``" +MH-X``_`$``-JZ``#:NT``_0```/P0@`#:O```VKU``/L```"OP4``KP```*@ +MW@`#\$$``KQ```/<\``#V,```KR```)HC``":9P``FJL``)KO``#P0@``CJ5 +M``/!"0`".I4``\$*``(ZE0`#P0L``CJ5``/4G@`#^P```]2>``/L```#P1`` +M`\$@``/!,``#U!X``_L```/4'@`#^P```^P```!J,0`"+6(``^@```*Q8``# +MZ"```^@P``-IH``#29@``K@/``*U]0`"LP```\$N``)@"``"014``V@P``*_ +M`0`"+5X``CDT``(P@@`#0"P``K\$``/_```"3_```Z_R``/H\``",$X``#(: +M``/_```"M0D``L1N``(Y&``#Z/```J#>``/P00`"OT```/G@``!9QP``>>`` +M`KP$``/<8``]1?``/[`0`#T%X``KL"``*A_@`#\$$``\%* +M``*@_@`#\$$``\%:``*@^P`#\$$``\%J``*F^P`#\$$``\%Z``/47@`#^P`` +M`K`0``+,S@`"I<```_`&``#AS@`#P8P``\&L``(Z10`#]````=K5``*Q!``" +MS_X``/G&``*A\0`!VQ```^BP``#9S@`#P8L``\&K``(Z10``>>```KP$``/< +MP``#V/```KP)``/!O@`"+>4``]S@``*[0``#V+```_0```':U0`".58``K@( +M``*Z"``".D4``%G'``!YX``"O`0``]S```/8\``"O`,``LN\``*\"0`"+?D` +M`T@(``*T8``"8`0``V@(``-)F``#_P```K(!``/H,``#:#```^P```*T!``" +M1C0``J!D``';,@`"OP,``CX_``-H:P`#0DD``C+```-B20`#[````T)-``(R +MP``#8DT``TAD``/X`0`"O0P``DG2``*@V0`#\$8``K\#``([D0`"OP,``KT` +M``([<@`#[````KT$``))T@`#\`8``K\!``([D0`"OP$``KT```([<@`#[``` +M`KT(``))T@`#\`8``K\"``([D0`"OP(``KT```([<@`#[````KU@``))T@`" +MH-D``_!'``*_`P`"/!```K\#``*]`0`"O`$``CMR``/L```"O2```DG2``/P +M!P`"OP$``CP0``*_`0`"O0$``KP!``([<@`#[````KU```))T@`#\`<``K\" +M``(\$``"OP(``KT!``*\`0`".W(``^P```-(8@`"3,X``AN$``.`\@`#P``` +M`X'X``/`$0`"3=X``_!%``/````":J```DJA``/T!``#\`,``\`1``)*H``" +M:J$``VAB``*P\@`":J```J`*``/P1P`#2$```K0(``*U]P`"810``VA```)! +M%0`#:$```VAK``/L```#2%0``^B```*Y`P`"2_X``_`!``)HB0`"N@(``KD, +M``)+^@`#\`$``FB)``)C.``#:%0``^B0``*T!``"2_X``_`!``)IF@`"2_H` +M`_`!``)IE``#26```VAK``/_```#_P```TAE``/_```"2]8``J"]``'<"@`" +M2Y,``=NF``-`*``#A/```*("``.B)@`",9X``P(N``';M0`#2`0``K3O``"* +M+``"010``V@$``(^,P`"M@0``V@Q``-"20`#Z(```]R```-*E``#B$8``ZB" +M``*\P``"S,@``]C```/4'@`#0"D``C+7``)%6@`"&_,``$H!``/_```"N(`` +M`\"9``.)G``"3/X``_`&``-)/``#2)D``F,X``)D20`#:3P``VB9``),^@`# +M\`8``TE```-(L0`"8S@``F1)``-I0``#:+$``DS^``/P!@`#2)```TB5``)@ +M"``"9$@``VB0``-HE0`"3/H``_`&``-(J``#2*T``F`(``)D2``#:*@``VBM +M``-`*``#_P```K@$``)!&``#\`$``CS)``-`*``#_P```K@(``)!&``#\`$` +M`CV#``-(0``"N(```DO^``/P`0`"81@``DOZ``/P`0`"8B@``VA```*\`0`# +M[````TA4``/`B``"0S@``VA4``*\```#[````T`H``#YNP`"N`@``D$8``/P +M`0`"/9H``T`H``/_```"N`0``D$8``/P`0`"/1@``T`H``/_```"N`(``D$8 +M``(<1P`"2_X``APJ``-)/``#2)D``KA_``)#.``"1$@``VD\``-HF0`"O`(` +M`DO\``(<-``#24```TBQ``*X?P`"0S@``D1(``-I0``#:+$``DO^``(<``T@$```B+``#_P`` +M`_\```/!%``#:`0``'F[``*X```"O`(``TA4``)+_@`#\`$``K@#``)+_``# +M\`(``KP,``)HC``#P(@``D,X``-H5``#@/@``(("``-"20`",L```V))``/L +M```#2`@``K@0``)!&``!W-H``DO^``/P!``#2E0``K0/``)@!``#:E0``KL" +M``)+^P`#\`0``TI8``*T#P`"8`0``VI8``)+_@`#\`0``TI4``*T\``"8`0` +M`VI4``*[`@`"2_L``_`$``-*6``"M/```F`$``-J6``#2`@``K@0``)!&``! +MW/@``DO^``/P!``#2E0``K0/``)A%``#:E0``KL"``)+^P`#\`0``TI8``*T +M#P`"810``VI8``)+_@`#\`0``TI4``*T\``"810``VI4``*[`@`"2_L``_`$ +M``-*6``"M/```F$4``-J6``#2`@``K@0``)!&``#\`$``^P```)+_@`#\`0` +M`TI4``*T`0`"8B0``VI4``*[`@`"2_L``_`$``-*6``"M`$``F(D``-J6``# +M[````T@(``*X$``"01@``=TI``)+_@`#\`0``TI4``*T_@`"0B0``VI4``*\ +M`@`"2_P``ATI``-*6``"M/X``D(D``-J6``"2_X``_`$``-*5``"M`\``D$4 +M``-J5``"O`(``DO\``(=-@`#2E@``K0/``)!%``#:E@``T@(``*X$``#_P`` +M`D$8``'=2``"2_X``_`$``-*5``"M/```D$4``-J5``"O`(``DO\``(=2``# +M2E@``K3P``)!%``#:E@``DO^``/P!``#2E0``K0/``)`!``#:E0``KP"``)+ +M_``"'54``TI8``*T#P`"0`0``VI8``-("``"N!```D$8``'=9@`"2_X``_`$ +M``-*5``"M/```D`$``-J5``"O`(``DO\``/P!``#2E@``K3P``)`!``#:E@` +M`KP(``(]YP`"M40``CUL``(^/P`#[````K?\``*V,P`"M````TC(``*@_@`# +M\$$``K0"``*\`@`"H/P``_!!``*T`0`"810``VC(``)@!0`#:,@``_\```)` +M!@`#:,@``KP"``(]YP`"01<``VC(``/L```#2`@``K@0``)!&``!W90``DO^ +M``/P!``#2)@``K1_``)")``#:)@``KL"``)+OP`#\`0``TBP``*T?P`"0B0` +M`VBP``-).``#A/(``\!$``)")``#:3@``^P```-).``#A/(``F(D``-I.``# +M2`@``K@0``)!&``#\`$``^P```)+_@`#\`0``TB8``*T@``"8B0``VB8``*[ +M`@`"2[\``_`$``-(L``"M(```F(D``-HL``#[````CWJ``-(5``#C/@``F(L +M``-H5``#270``KS?``)$+``#P5,``CXS``-H,0`",9X``KP0``)D3``#:#$` +M`C&>``-(5``"O)\``D(L``-H5``#270``_\```/!0@`#P5,``CXS``-H,0`" +M/@```K5```(];``"/=```^P```*[_``"2OX``_`(``-((0`#_P```F5>``-H +M(0`#:HD``D5;``-H(0`#:HD``KH"``)*KP`#\`@``T@E``/_```"95X``V@E +M``-JC0`"15L``V@E``-JC0`#[````PS.``'=YP`#[````D'^``(=]``#0ZX` +M`K#O``/_```"2[```DJP``))L``"2+```V.N``*Q`@`"0?$``AVR``-#[@`" +ML.\``_\```)+L``"2K```DFP``)(L``#8^X``^P```)!_@`"'@H``T.N``*P +M$``#_P```FNP``)JL``":;```FBP``-CK@`"L0(``D'Q``(>%0`#0^X``K`0 +M``/_```":[```FJP``)IL``":+```V/N``/L```"/C,``K8"``-H,0`"M@$` +M`TF>``*\$``"9*P``\%;``-H,0`#29H``KP"``)DK``#P5L``V@Q``/_```# +M270``KP0``)D+``#P5,``V@Q``(QG@`#P,P``D1,``-H,0`",9X``\%*``/! +M6P`#:#$``^P```/!;@`"MP,``DW^``/P`@`"O0(``D=]``*]`@`"3?T``_`" +M``*]`0`"1WT``^P```*X```"N0```KH```*[```#2L$``KR```/!;P`#Z'`` +M`VK!``-B@@`#0P```F9L``*WZ``#:L$``V,```-#*``"M_<``VK!``-C*``# +M0RP``KQ_``)&;``"MQ\``VK!``-C+``#Z&```^AP``-JP0`"L@(``K$#``*P +MK``"0_X``_`!``(^J``"L.P``D/R``/P`0`"/J@``K(/``*Q!``"L````D/^ +M``/P`0`"/J@``K,"``*P0``"0_,``_`!``(^J``"L@\``K$$``*P@``"0_X` +M`_`!``(^J``"LP(``K#```)#\P`#\`$``CZH``)/_@`#\`4``T``/!P@`# +J_P```]1>``/[```#T%X``PS.``'>K0`#[````_\```/_```#_P```_\` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/HAINAN_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/HAINAN_me.bin.uu new file mode 100644 index 00000000000..330ab5f2b0f --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/HAINAN_me.bin.uu @@ -0,0 +1,194 @@ +begin 644 HAINAN_me.bin +M?$"``8@```#40`!_?$"``8@```!\0,`!S$``*,Q``"E\0(`!B````-A``![$ +M$``A)1```I4`__Y\00`!Q!P`)L0@`"38```50``"V4&BI,0;``+8```;S8``&L`^``3,`:'TS#T@!,0]``',```%V$`` +M&]A``!]\0(`!B````,Q!+@',02X"S$$N`\Q!+@!\0(`!B````'Q`P`&,``5Y +MS$$N`'`&GQ"``$E)``! +MS,``(]%``"31@``ET<``)MA``">60``,Q"@`+)J`___()``M?EZ`#)J`_YP2 +M+``&!NP``0KL``&:P/__V$``)X```&#$*``LFH#__WQ`@`&(````?$#``<00 +M`##,027,?04``@8U``P +M&-@`-`4H`6U\0@`!?$)``94```>&@```@``!AX```:N```'!@``%=8```7T1 +M5``0?A8`"LR```O480``E8#^B<`Z``3,.2%`Q#D``7Q`@`&(````$50`$%)D +M`"!^)@`:S4``'=1B``"5@/Y^Q"``'9H`__]\0(`!B````-PZ``"90``;)YP` +M`97```T+N``!S@$A:``$6(``"S@$EQ]1I)'Q`P`%\00`!0-0``\U!(ES-`:'\P!X``7Q"``$(S``!!B0``08H``+. +M':']SEVA_4``(````#.02%ISH$A:LW!(6O,`2%L?$"``8@```!\0,`! +M?$$``7Q!0`%\08`!?$'``1BD'^@R:``\!"```9:```A\0@`!.C```T(@``*; +M```"!"``0`0D``&```(L?@)``0ID``',``!_FD#__B3L`!#,@``+FL``"<`J +M``3$+``0?I*`"LP```',*0``SL``$,0Q``&```(^(50`,,T!(6W-02%NQ#(` +M`'\?``DD]``'!W@"0I=``">'@```@``"2H```D^```)4@``"68```EZ```)C +M@``":'\;@`\4I``(EX``'29D`/^```)Y?QN`#A2D``B7@``8)F0`_X```GE_ +M&X`,%*0`")N``!,F9`#_@``">7\;@`T4I``(FX``#B9D`/^```)Y?QN`#Q2D +M``B;@``))F0`_X```GE_&X`.%*0`")N```0F9`#_@``">12D``@F9`#_,F@` +M/!3L``B:@/V4?$-``7Q#@`%\0\`!S```"Y;```;/02%ISX$A:L_!(6O,`2%L +M@````,_U``"`````,F@`/)J`_['40`!_@````'Q`P`%\00`!P!X``144`!+` +M(@`"P"8`!)5```3`)__[?24`"<`F``!]TH`)?A+`"7TE``I\04`!?$&``Q#P`(2?\``*7P/_^S(``"]E!HJ3$ +M/P`"S\``&L`^``3,`:'TS#T@!,0]``',```%V$``'Y````!\0,`!!#P`(LR` +M``O/P:*DS```!GQ`@`&(````P!(``7Q10`K,@``+U%4``'Q`@`&(````?$#` +M`5!0`"!\T,`:51P`/WQ!0`%\08`!S(``"]#``(.5P``=Q#P`"9O```*,``-< +MV```'L0@`"$F(``!E@#__L`F`"@J9'_#S(``"\Y!(7S`)___SD$A?<0H`"3. +M@2%ZS`$A?L`J``0$+``(?L,``0LP``&;`/__S(``"\PI(7_$-0`!%W@`'W[# +M``&;@/_YV```'Y6`_&.,``5YW8,```5<(`#,```+U%T``(``!8%\0,`!4%`` +M('S0P!I\04`!?$&``=1#H`"```6!)(S__\R```O430``?$"``.:P*W#VP"MF:P``#EP```LP` +M``&```1>4=P`('V=@!K8```=SAH``)5```0%F``$5B``(,X:``";P`"0?$"` +M`8@```"50``"(=P`,E8D`"#-@2%IS<$A:LX!(6O.02%LF\#^`WQ`@`&(```` +M4=P`('V=@!K1@``KS@``+)5```-6)``@SD``+-A``"V,``6&E\#[9<0X`"^; +M@/__?$"``8@```#$'``PP"H``7V=@`$5F``"S8$EQ\XI)Q`P`(23, +M``&4P/_^QB<#Y'Q`P`',@``+S,$A?,Q!(7W$&``D?$$``7Q!0`&60``"S8$A +M>LT!(7[`-@#`P"H`!']/0`D17``!!=P``9=``!3,*2%_Q"4``1IL`#Z6P``' +M$5P``07<``$)W``!F<#__\R```N```3H%W0`%R@L`&";0``"*"P`0,[``"/8 +M0``GQ#0`+)M`__^```4`"=P``9G`___,@``+S"DA?\0E``$6;``?$5P``07< +M``&:P/_X%/P`']@``!^;P/KZQ!``)LP0`_=\0(`!B````'Q`P`%\00`!%1@` +M'U$4`"`9'``QF8``",T``!U]34`:U%8``)7`^NS$(``=F@#__X````#<.@`` +MP"8`!,S!(6E])0`*S0$A:@NX``+,02%KS$$A;)N`__V9P/UQ?$"``8@````D +M3`#_S$P#`'Q`@`&(````Q"``)L1/`P#,@``+S.$A18````#,@``+VL&BI'Q` +MP`%\0(`!B````,0,`!J8P``#V$``+X``!3+80``P?$$``7T!0`$55``!)50` +M`9E```DE$``!E0#ZP\@4`#250``%R!@`&Y6```-]E<`.E<#ZO<@@`#/2```R +MV```'L0@`"$F(``!E@#__L`F"$#,@``+SD$A?,P!(7W$*``DSH$A>LP!(7[` +M*@`$!!0`"'U!P`$H+`!`SL``(]A``"<)W``!F<#__\R```O,*2%_Q"4``19L +M`!]]0<`!FL#_^<0T`"R;0/__V```'WQ`@`&(````Q`P`$S#0``&5```#S(`` +M"]L!HJ3,0``.Q`P`$L00`!,PU```/1@``7U9P`K80``QF<#_^MA``!/0```R +M?$"``8@```#`#@$`S````Q!@`""68``%\0D`!?$*``96``N52K``@?N;`&GQ`P`%\00`! +MQ!P`$9G`__\@8U``P&-@`-`4H`>5\0@`!?$)` +M`94```>&@```@``#]8```_6```/U@``#]8```?,15``0?A8`"LU``"'480`` +ME8#^$<0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``"'48@``E8#^",0@`!.: +M`/__?$"``8@```!\0,`!?$$``7Q#@`%\0\`!41``(%/\`"!_OX`:?-#`&@0< +M``33@``"V(```M#```+-P``"!!P``00@``%\`D`!Q!<``\0;``-1F``@?5E` +M&L0K``/$+P`#Q#,``\0W``,)W``!4NP`('ZN@!I3=``@?S<`&G\K0!)^=D`1 +M5J@`/U0`F9@``$S``` +M`LP```V```/Q%9@``14L``@F[``!F8``,Q4P``R6```#S````H```_$$%``$ +MS4```B`_8\+N``!Q#\``YN`__V````` +MS```#I9```/,```"@``#\=H```+$"P`#Q`\``\03``/$%P`#Q!L``\0?``/$ +M)P`#Q"L``Q7\`!\6L``??_/`"13P`!]_\\`)%7``'W_SP`E]B(`"?`` +M`IH```?%8P/KF@``!=^#``#/I``/C``#7=1``'\)W``!S=0#[M@4`_&,``-= +M?$"``8@```#8```>Q#P`'IO``)J0````V$``'L0\`!Z7P`"6D````(P``UG$ +M(``5?$#``<`V_P#$$``6P#`__WSU0`E]48`)?8&`'7SS@`F9@``&WX,``,^@ +M``^,``-=U$``?X````",``-=?$"``8@```!\0,`!%-P`")G```7,@```S,`` +M`-1```"`````?$$``5!4`"!\08`!?$'``7Q"``$Z,``#$B```IL```($(``( +M!"0``8```X=^`D`!"F0```_&.```.M?QN`#I>`_&"```.M?QN`#)N`_%V```.M?QN` +M#9N`_%J```.M?QN`#YN`_%>```.M?QN`#IN`_%1^`D`!@``#A\0<``3-P``` +MS````,R```#40```?$"``8@```!\0,`!)-``!C$0``;$%``/F0``",P``!+$ +M)`!^ED``.)E```3$'``$S<```,P```#,@```S,```-1```!\0(`!B````'Q` +MP`%\00`!%1@`'\T``"%1%``@F8```]1-``"`````?4U`&AD<`#'45@``E<#\ +M+L0@`!.:`/__?$"``8@```!\0,`!?$$``134`!XQ6``")-P`_Y5```29@/PC +MS1P#`(````#,@```S,```,T```!\0(`!B````,0@`"1\0,`!Q-,#`,R```#, +MP```S```(T``!+L`!@F[`#_P"0``(P` +M`6?,```2D````"@,``&,``$<*#@``8P``2DH.```C``!)9>```[`.#$!Q[D` +M`!>X`!`GK`?_EL```\`D``",``%GS8```L00``.5`/__S```$,`X``&0```` +MQ`P`$93```4H.```C``!*2@,``",``$T``!+L +M`!@F[`#_P"0``<`@``",``%GS8``$I````#$"``3E(#__\P```+$"``/Q!`` +M`YD`___`+#$>QNT``,`D``",``%G*#@``(P``2DH.``!C``!)2@,``",``$< +MS8``$)````#$"``,^Q``"0````EX``!,`0,1G%'0``F<#_ +M_I=```3`$#$:Q1T``)G`__Z0````C``!+,`4,17/E0``P!0Q%L]5``#`%#$8 +MSQ4``,`0,1W%$0``)1```9D```3`%#$7S]4``)`````GT`#_,1``_YD```3` +M%#$7S]4``)````"0````S8``#L03`![`#"35C``!4,P#``Z0````)10`_\`* +MB`!\C(`*S4D``)````#`$```P`J(`'R,@`K$E0``)50`'WT5``J0````P`P` +M'\`*B`!]R0`*Q14``!54`!!]04`>?4Z`"7Z"@![$%P`"?I:`"9````"6P``, +M*NP``<[``#"60``%Q"``')8```/,```PD````,0<`#.5P/_ZS```,,`@``"0 +M````EL``$W[!``K`'##0S9T``,`<,,[%U0``%2P`!);```2,``%GE@```I`` +M``#`'##0S9T``,`<,,[%W0``?=7``GW1P`^5P/_V?0+`"I`````FN``?%IP` +M""7<`!\1W``%?Y^`"A:<`!`E]``?%=P`""7<`!\1W``%?U]`"I````",``&H +MS```#L0(`#?$"``SE(```\V```Z,``)5Q`@`*I2```/-@``.C``!],0(`"N4 +M@``"S8``#L0(`"B4@/_RS8``#HP``F:,``+I@``!E<`8``',`P`.P`W__\S# +M`![,PP!AP`@%`"@,``#,CP!!P`H@("B(#P4$S``!S(\`0<`*,#`HB!X/!,P` +M`',$S``!S(\` +M0<`*P,`HB'UX!,P``B`",``*E +M?!<`"I`````IR")OQ(D``"G,(G#$S0``?(U`"GU!0!X55``0D````#",`$"8 +MP``G.(P`0)3```X(B`!`?*W`$!7<``:,``*A?H*`'GZR@`F,``+6)HP`_W\! +M0`J,``(&?!I`"LY#`&&```+5P`PQ"<3-```DT``!F0``!\0/`%W$$P!>Q!<` +M57U1``Y\T0`*F0``#L`<`$!]R(`"?*W`$!7<``9]PL`*C``"UL`L,0O&[0`` +M)M``_W\!0`J,``(8?!J`"LZ#`&&0````P#```":(`/^,``'^?,&`"I;```J, +M``+EE4``"#%(``&4@``$!S```0F8``&```+B"NP``8```MJ0````?8#`"L`4 +M``!]@4`-D````,0+`![$#P!A?(T`#)D```3,PP`>P!@```````S\&BU,`N``1_+P`' +MS#$``,@L``3`,``&?O-`(\`P`"!_:X`@B````'^SP"3,``!"@````,Q``!]\ +M0,``?$$``!D4`#V90``3!!0`+H0`!-H$&``IA``"6L@<`!,$%``JA``$V@08 +M`"W-0:*DR!P`$Y7```#('``3S,$A`,T!(0',P2$"S0$A`X``!-?-@:*D'1@0 +M`)6```7('``3*>0`0)9`___('``3S,$A=4``,Y!(6G.@2%JS<$A:X````#,`2%L?$#``'Q!``!\04``?$&``'Q!P``8 +MI!_H*F@`/):```I\`@``?$(``#HP``/,``!8FP```T(@``4$(`!`@``!4WP" +M0`!^`D``FD````ID``$<[``0FL``"LP``$W`*@`$R"P`('Z2@`?,``!!S"D` +M`,[``!Z```%CR#``!,T!(6W-02%NR#```W\?``8<]``'$W@``9=``"H'N`%H +MGX````````"```%X?QN`#H```7Q_&X`/@``!@'\;@`R```&$?QN`#8```8A_ +M&X`1@``!C'\;@!"```&1%*0`")N``!D4I``(@``!H1YD`/^;@``5%*0`"(`` +M`:$>9`#_FX``$12D``B```&A'F0`_YN```T4I``(@``!H1YD`/^;@``)%*0` +M"(```:$>9`#_FX``!12D``B```&A'F0`_Q2D``@>9`#_*F@`/)J`_FT4[``( +M?$-``'Q#@`!\0\``EL``!\P``$W/02%ISX$A:L_!(6N`````S`$A;(````#/ +M]0``S```680`!-HJ:``\FH``!,@H`!>`````U$``?Y:`_ZM^`D``A``"C,`. +M``+,``!!@``!K\S!,$J4````R#P`''Q`P`!\00``P!X``14D`!+`(@`"ED`` +M!<`F``3`)__[?24`!L`F``!]TH`&?A+`!GTE``=\04``?$&``,S!(6F:@``, +MS0$A:LU!(6N6P/X\S8$A;(0`!-K,``!_R#``&I<```#(,``:@````7Q`@`"$ +M``3:S```?\@4`!7(&``6S4$A:Y;`_B[-@2%L@``!QLP``'_,``/ER"P`(,`. +M("0$$#``(,PB:P04,`',``!!T!$``,S5``#.P``>R`P`"9C```#(#``)?$$` +M`'Q!0`#,0`!#S$``1,`.@`!\0D``?$*``!:L`!^6P/X5P#7P`,Y``^$>>``# +M$GP`"'_WP`9_^\`'%G@`&,_``^+/@`/C$K```G\_``#/``/D@``$8WR`P`!\ +M0,``&-`!Z!$H``&5```0!J@!_YZ`````````@``"%\`2"`"```(ER!0`$8`` +M`BS(%``2@``",\S!HJ2```(\'.@`/X```F1\P8`+'-``/RDH``8I+``6?JZ` +M!\@<`!.:@``]!!0`+H````#,P:*DP!((`'Q!0`!]#,`'P!(`"!58``,57``, +M?$(``'W1P`82(``4?AY`!WY.@`?.@:*D@````,V!H?[(%``1!!`A&)5```#( +M%``1U%$``(````#,P:*DR!0`$@00(0:50```R!0`$M11``"`````S,&BI,S! +MHJ0$$``!S0``&80`!-K,``!_R!``&YD```#($``;@````7Q`@``JH``$*J0` +M%'XF``<$%``NE@``"`08`"F$``):R!P`$P04`"J$``3:!`P`+:@``$$>0`"GXF``?-P`!FS0$A6,U!(5G.`2%:S,&BI)J``E<% +M$``$!"P``1+P`!U]<4`'$N``$"(@``S-`2%8S4$A65P``,R#0`,<@X`##(/``M%_P`$!/\ +M`!!_U\`'4W0`('^W@"='N`50S```8L_Z``":0```R"0`)\`P``'(*``DFH`` +M`,@H`"3/``!;4-@`"!3<`!@AW(``S8$A@,W!(8%1(``(%20`&,X!(8+.02&# +MS4$AA'Q`@`"@````S(``380`!-I\04``'70``1QX``*;0``#R`P`*H0``TT5 +M5``0FX```P00`!"$``-QS,&B8,T!H&"$``+^!!@)@(0`!-K,``!DR#P`+H0` +M`PS($``JR!P`+QW<``'()``HE<``#,@T`#'(.``PR#P`+A?\`!`3_``0?]?` +M!U-T`"!_MX`G1[@%5,P``&+/^@``FD```,@D`"C(*``EFH```,@H`"6```+& +MP#```@68P``0W``(%.``&,W9``#('``BR"0`(AW<#__-V0`!?F)`!\Y9``+8 +M&%$#V!A1!(@```#8&%$'&_@`\,`V"`"7@``#P#``@(@```#`*@`$ST$A?,\! +M(7W-`2%^(J@A?P0D``B:0```"F0``7`!YG`__[('``E@````7Q`@`!\0,``?$$``'Q!0`!\08``%1P` +M'\S``,?-``#(E<```\`<@`#-P2`0X8,```5<(`#,``!-@````-P?00!\0,`` +M?$$``'Q!0`!\08``S,``R;@/_\R"@`)\T``&)]34`G +MU%8``)7`^T#((``FF@```,@@`":````!?$"``.`Z``#`)@`$S,$A:7TE``?- +M`2%J"[@``LQ!(6N;@/_^S$$A;)G`_/?,``!_@````7Q`@`#`#@$`S```0``#()`/]?>:`$9:```-^7L`!?`+`!L[#HIY5%``@ +MS```;,T``&W-0`!MS0``0\U``$/('``=T4``0YG```7,``!5R"``']@``\#, +M``!`R"@`%M@`!L`:J``GEH```\R``$#0@`!@%5``&(!```7T5``.```"(?9&`!IE`__C((``?A``#L\@< +M``>```"_S```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/TS0`# +M]LT``_?-``/X@```!$``.SS```4\@,`"_,@`!`S$``0,Q``$#, +M0`!`?,3``,S``$#40`!`?$"``*`````$*``!F4#_]<@@`!^$``.SR!P`!X`` +M`17,``!N?$#``,@0`$< +MP`-^PL`+?FY`!LY8`_$$&```!!P``(0``<')Y`/QA``!P0# +M\80``<')Y`/Q?2$`!]@`!T#-``!`A``!MLT``$#(#`!#E,``(L@4`$B```&7 +M!!```\@0`$;(&`/U!9@``1V8``_-@`/U'9P``QF8`&+)I`/V$=P``P0L`/]^ +MWL`#?L+`"WYN0`;.6`/V!!@```0<``"$``'!R>0#]H0``<')Y`/VA``!P0#]GTA``?8``?`S0``0(0``;;-``!`R!0`2)U```#,``!JR"@` +M%AZH``&:@``#P"D``8@```#`+`%6SH``7-@`",#.P`!`B````,P``$`>:`#_ +M?IO`$)?```,:;!_H?H&``'[;P!"7P``#&G`?\'[!@`!_&\`0E\```QIT'_A_ +M`8``?UO`$)?```,%W``!?T&``!&@``6(````$B``$!R,``+($``>R"``'Y3` +M``C(%``7,@`!`F4``!,@<``:$``.SS``` +M4LR``$"`````U$``0,Q``"?,0``H@``#K4P``%?$$``-@@`L:```(OSB``1LP``$B```)%`````,@@`!]\08`` +M"B```0`;,``!"@``#K[``!E@``!!4P``R```.MS```0@04`"#-0`!"'S```2`H``&$``*L +MR!0``YM``"L$.``A``#L,P``%W((``??$#` +M`,`V_P#($``AP#`__WSU0`9]48`&?8&`"IF```A\\X`&XX,``,^@`$^$``.P +MS```7H````#40`!_@``#K``!\0@``?$)``'Q!@`!]Y<`&?>*`$9J` +M_)-!K``%FL````KL``$<` +M%P)'`!@"50`B`S<`(P-(`"`"D!ZP`J`A``*P(``"\"&0`R +M`CT`-`.,`#4![P`Y`E<`/`-<`#X#JP`_`BL`00+?`$("^P!#`P4`1`,2`$H# +M*0!5`W\`5@.'`&``A@!A`*,`8@#-`&,`M@!D`+8`90"V`&8`M@!G`+8`:`#: +M`&D`Y0!J`58`:P$'`&P!!P!M`0<`;@$'`&\!!P!P`0P`P.:````!0````4````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +9!0````4````%````!0````4````%````!0`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/JUNIPER_rlc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/JUNIPER_rlc.bin.uu new file mode 100644 index 00000000000..7aef7d39f82 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/JUNIPER_rlc.bin.uu @@ -0,0 +1,72 @@ +begin 644 JUNIPER_rlc.bin +M(#@`$".X``#/@``2S```A008``'-@``.S8``@\P``(+-@`"!S```"X```/P` +M````P#`@`\^Q``"(````RSD``,^<`!;-@``.R?``&'\X@`R4@/_^`````(@` +M````````A```?`````"```#%`````,GX`(.;@``$`````(```,4`````S!P` +M@X0``-@1N``?@```Q0````#(*``#EH``M`````#-@``.*HP!Y9C``"0@"``! +MS(```X```!@`````(#@``<^```/($`""S```@<@(`!J4@``R`````,V```X` +M````A```T2`X``+,,0``A```#"`X``'-@`"!A```\R`,``"```#%`````"J( +M`;R8@/_8`````)4`_](`````R"@``I:``.$@"``!S8``#LR```*````8```` +M`,G,`(.4P`"3`````(0``/,@#``!A```#"`X``"7@`"-(`P`#<`P(`G,\0`` +MP#`@"L`T&!@3=``((W08&,L-``!\],`&R`@`&IB``((@'``!E,#_^P````"` +M```P?<'`!L@X`%:;@``S(!P``,@X`%>;@``P(!P``2`<``#("`"!E(#_V0`` +M``#(*```EH#_UB`(``'-@``.S(```!P<```JB`&[E(#_RP````"```#3```` +M`!ZH`/_.@``,B`````````#(,`!`(S``0,\``$"$``"F(#@``<@P`$`?,`._ +MSP``0(```&?,``!6A```$`````#`,"`(A```N2`X___`,"`(S#$``,LY``#` +M,`.8A```N2`X`0#`,`.8S#$``,L)``#`,"&VB````,PQ``"9P/_ER#``0",P +M``+/``!`A```BB`X``/(,`!`'S`#_<\``$"```!GS```5H0``!``````(#@` +M`<`P`YB$``"Y$[@`%,P``%?`,`.8S#$``(@```#+"0``S[$``,V```[+.0`` +M%[@`!)>`__X`````B`````````#/L0``RSD``"`(`!^8@```"(@``4P/\[`````,@1/3C(%3TYR!T] +M.L@A/3O()3TU!*@`,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$]AQ"(``,$C``8 +MR)8`/)5`_RK(T@`H?24``0E4``$$S``HF0#_^P````#(D@`X!1``0'T*P`#( +MU@`$P!P`!,CB`!3(Y@`DS@H!3,YN`4P(S``$"(@`!`KL``0)W``!F<#_^``` +M``#-"@%@S`H!9,U!/4>````Y`````,@H``&6@/[[`````"`(``'-@``.S(`` +M`8```!@````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +,```````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/LICENSE.radeon b/sys/contrib/dev/drm2/radeonkmsfw/LICENSE.radeon new file mode 100644 index 00000000000..0d1894f8a88 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/LICENSE.radeon @@ -0,0 +1,51 @@ +Copyright (C) 2009-2013 Advanced Micro Devices, Inc. All rights reserved. + +REDISTRIBUTION: Permission is hereby granted, free of any license fees, +to any person obtaining a copy of this microcode (the "Software"), to +install, reproduce, copy and distribute copies, in binary form only, of +the Software and to permit persons to whom the Software is provided to +do the same, provided that the following conditions are met: + +No reverse engineering, decompilation, or disassembly of this Software +is permitted. + +Redistributions must reproduce the above copyright notice, this +permission notice, and the following disclaimers and notices in the +Software documentation and/or other materials provided with the +Software. + +DISCLAIMER: THE USE OF THE SOFTWARE IS AT YOUR SOLE RISK. THE SOFTWARE +IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND AND COPYRIGHT +HOLDER AND ITS LICENSORS EXPRESSLY DISCLAIM ALL WARRANTIES, EXPRESS AND +IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +COPYRIGHT HOLDER AND ITS LICENSORS DO NOT WARRANT THAT THE SOFTWARE WILL +MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF THE SOFTWARE WILL BE +UNINTERRUPTED OR ERROR-FREE. THE ENTIRE RISK ASSOCIATED WITH THE USE OF +THE SOFTWARE IS ASSUMED BY YOU. FURTHERMORE, COPYRIGHT HOLDER AND ITS +LICENSORS DO NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE +OR THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +ACCURACY, RELIABILITY, CURRENTNESS, OR OTHERWISE. + +DISCLAIMER: UNDER NO CIRCUMSTANCES INCLUDING NEGLIGENCE, SHALL COPYRIGHT +HOLDER AND ITS LICENSORS OR ITS DIRECTORS, OFFICERS, EMPLOYEES OR AGENTS +("AUTHORIZED REPRESENTATIVES") BE LIABLE FOR ANY INCIDENTAL, INDIRECT, +SPECIAL OR CONSEQUENTIAL DAMAGES (INCLUDING DAMAGES FOR LOSS OF BUSINESS +PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, AND THE +LIKE) ARISING OUT OF THE USE, MISUSE OR INABILITY TO USE THE SOFTWARE, +BREACH OR DEFAULT, INCLUDING THOSE ARISING FROM INFRINGEMENT OR ALLEGED +INFRINGEMENT OF ANY PATENT, TRADEMARK, COPYRIGHT OR OTHER INTELLECTUAL +PROPERTY RIGHT EVEN IF COPYRIGHT HOLDER AND ITS AUTHORIZED +REPRESENTATIVES HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN +NO EVENT SHALL COPYRIGHT HOLDER OR ITS AUTHORIZED REPRESENTATIVES TOTAL +LIABILITY FOR ALL DAMAGES, LOSSES, AND CAUSES OF ACTION (WHETHER IN +CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE) EXCEED THE AMOUNT OF +US$10. + +Notice: The Software is subject to United States export laws and +regulations. You agree to comply with all domestic and international +export laws and regulations that apply to the Software, including but +not limited to the Export Administration Regulations administered by the +U.S. Department of Commerce and International Traffic in Arm Regulations +administered by the U.S. Department of State. These laws include +restrictions on destinations, end users and end use. diff --git a/sys/contrib/dev/drm2/radeonkmsfw/Makefile b/sys/contrib/dev/drm2/radeonkmsfw/Makefile new file mode 100644 index 00000000000..44fbf9ec6e8 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +all: + rm -f *.uu + for file in *.bin; do \ + uuencode -o $$file.uu $$file $$file; \ + rm $$file; \ + done diff --git a/sys/contrib/dev/drm2/radeonkmsfw/OLAND_ce.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/OLAND_ce.bin.uu new file mode 100644 index 00000000000..6af378ba58e --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/OLAND_ce.bin.uu @@ -0,0 +1,194 @@ +begin 644 OLAND_ce.bin +M?$"``8@```#40`!_?$"``8@```#$(``+Q@P`!93``"0D4``/,10``I5```3, +M0``DS$``)8`````Q%``#E4`!.\Q``";,0``G@````,0@``O,(``%?$$``5!4 +M`"!\08`!!B0``@8U``P&-@`-`4H`$1\0@`!?$)``94` +M``>&@```@``!4(```5"```%0@``!4(```%(15``0?A8`"LU``!'480``E8#_ +MLL0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``!'48@``E8#_J<0@``Z:`/__ +M?$"``8@```!\0,`!%-``'C$4``*50`#K&-0`,!C0`>@8_``T),P`#P3H`&A\ +M08`!?$'``93``!*&@```@``` +M`!J```!_4=P`('V=@!J90``#Q:(``(```'_)H@``@```?\6A``"50``%!9@` +M`<6E``!29``@?B8`&@4H`(-\08`!?$'``94```>&@```@``!4(```5"```%0 +M@``!4(```)/8```1SAD``)5```0%F``!5B``(,X9``"7P/]QQ#DA0'Q`@`&( +M````4=P`('V=@!K8```1SAH``)5```0%F``$5B``(,X:``";P/^]?$"``8@` +M``#8``/VV``#]=@``_38``/SV``#\M@``_'8``/PV``#[]@``^[,0`!_S$`` +M?\Q``']\0,`!S,```=1``'^`````?$#``5!0`"",``#+?-#`&L0@``O$U@`` +M?$.``<0D`!.:```)V&0#],9K`_&:@/__QFL#[@:H``'.I`/NS60#Z]@D`_29 +M0``)WX,``,^@``Z,``#/U$``?YH`_SS&

?16`#IF```_80``IR!``'7U1@!)]C<`/F<#__=@``"E0X``! +M?A9`#II```1]8H`2TH``(X````#0```C@````-B``"G$/`!_S```(-A``"C$ +M#``V$``'8````#,```@V$``*,0, +M`!R8P/__V```*-```![0```?V$``'7Q!``&`````?$#``7Q!``$5&``?S0`` +M$5$4`""9@``#U$T``(````!]34`:&1P`,=16``#$(``.E<#^R,0@``Z:`/__ +M@````'Q`P`%\08`!%-``'C$0``(DU`#_E0#^O\V4`P"`````Q"``$WQ`P`'$ +MTP,`S```$`(0`]@"'`/D`B`$"`(D!%P!]`3P`?@%$`'\!+``B`*X`BP$B +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````"`````@````(````"`````@````(````"`````@````(````"```` +M`@````(````"`````@````(````"`````@````(````"`````@````(````" +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +:``(````"`````@````(````"`````@````(` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/OLAND_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/OLAND_mc.bin.uu new file mode 100644 index 00000000000..5964aec1e64 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/OLAND_mc.bin.uu @@ -0,0 +1,702 @@ +begin 644 OLAND_mc.bin +M``/HX``"O@$```('``/_```#_P```J`.``'`&0`#Z````^@0``/H(``#Z#`` +M`V`@``-A2``",A(``TEL``-("@`#KPH``K0$``)O]```^BT``K0/``)/%``` +M^@H``ZB,``#"`0`#0"0``K1```*U#P`#2J8``D1!``/P`@`"294``VJF``-* +M40`#0"0``K@"``*Y_@`"1)0``DB!``.H@``"9$@``VI1``-`)@`"OX```KP$ +M``))^0`#\$(``_0```'`00`"OX```TA4``*X#P`"N?```D$8``)"*0`#:%0` +M`TMI``/`C``"9$P``VMI``)$2``#:VD``F$?``)B+``#:%0``BQE``-+3``# +M_P```V%$``-+'``#0"H``K3\``-A0``"0S0``F$>``-K'``"2JX``_!&``-) +MU0`"O!```DS'``/P0@`"O"T``_\```-`)``"M$```K7P``-*I@`"1$$``_`" +M``)IE0`#:J8``T````/_```#^`$``\1```/$40`"QD4``@````-`$``#_P`` +M`_\```/H(``#Z#```V`0``"1Y0``D@T``_@#``(Q&0`",@P``T@(``*TGP`" +M0`0``V@(``-(P``#2,8``K3\``*U#P`"010``DF4``)")0`"2J4``D,U``)+ +MM0`#:,```VC&``-(```#2`4``KL_``*\OP`"O^\``)(E``"*)@``@BH``+HH +M``"J+``"01L``KO[``)`#``#:````KS^``)%7P`"1WP``V@%``-($``#2=T` +M`KOQ``*\`@``BBD``*HK``)!&P`"81P``V@0``)%6P`"95P``VG=``-`#0`# +M_P```_\```.A3```B?\``K,"``)#-``#HS```)G^``*S!``"0S0``Z,R``"9 +M_0`#0"D``T````*\(```N<<``D(L``/P!P`"L````((Q``(ZG0`#Z````('E +M``/T```!PF```T````*\(```\C$``D,\``/P!0`".IT``^@```"!Y0`#]``` +M`<)@``-((0`"L\$``D=S``-H(0`#:HD``T@E``*SP0`"1W,``V@E``-JC0`# +M2"D``TEP``-`$@`"OP<``D`/``.````#``X``Z^(``-)U@`"O!```DS+``/P +M00`"P`\``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H+0`#P00``\$5 +M``-IZ``#:>P``TK"``*_P``"2(\``VK"``-JQ@`#Z````^C0``(N\``#:.0` +M`\'>``(N\``#:00``^A```*]```",EP``KT!``(R7``#0"P``_\```*T`@`" +M1`0``*()``-)U@`"M1```D1;``.D1@``H@L``J!.``/P`P`"-!<``_0```'! +M!0`#]````=+=``-+8``#_P```F`.``-K8``"O````C*7``-`#@``\C(``^CP +M``.@M@`#2=4``/H$``*Q#P`"0A<``J4@``/P`0``^C(``D,;``*E(P`#\`$` +M`/($``-````#0"X``K80``*T#```*C(``D(D``.B(@`"0S0``FPC``)&:``# +M\`,``J!>``/P`0`#Z,```.(#``-`"``"M````'H$``*@)``#\$$``K((``*@ +M_@`#\$$``K($``*T/P`"0B0``)(:``-*E``#_P```V&```-````#_P```K1` +M``)$!``#\`,``^@```"",0`"(O,``T````/_```"M$```D04``/P`@``\C$` +M`B+S``-````#_P```K1```)A$``"1!0``_`!``(M40`#2I0``_\```-AA``# +M0````_\```*T`@`"1"0``_`#``/H````@C$``B,?``-````#_P```K0"``)$ +M-``#\`(``/(Q``(C'P`#2I0``_\```-AB``",@P``T````/_```#_P```D0. +M``/P`P`#Z````((Q``(D2``",@P``T````/_```#_P```D0>``/P`@``\C$` +M`B1(``(MB``#2I0``_\```-AC``#0````_\```*T`@`"1$```_`+``/H```` +M@C$``B8[``-`+``#_P```K0@``)$0``#\`,``^@```"",0`",8,``TJ4``/_ +M```#89```T````/_```"M`0``D1```/P`P`#Z````((Q``(H#``#2I0``_\` +M``-AE``#0````_\```*T$``"1$```_`,``/H````@C$``BBS```!_P`#_P`` +M`_\```*D#@`#\`0``/(```(HLP`#Z````((```-*E``#_P```V&8``-````# +M_P```K0@``)$0``#\`,``^@```"",0`"*D```TJ4``/_```#89P```(#``/_ +M```"M`$``D0$``/P!``#Z````((Q``/!_@`"*O(```(#``/_```"M`(``D0$ +M``/P!``#Z````((Q``/H\``"*O(``T````/_```#_P```D0N``/P`P`#Z``` +M`((Q``(X.P`#0````_\```*T$``"1"0``_`#``/H````@C$``CE?``/X`P`# +M2I0``_\```-A8``#0````_\```*T`@`"1$$``_`*``#R,0`")CL``T`L``/_ +M```"M"```D1```/P`@``\C$``C&#``-*E``#_P```V%D``-````#_P```K0$ +M``)$00`#\`(``/(Q``(H#``#2I0``_\```-A:``#0````_\```*T$``"1$$` +M`_`+``#R,0`"*+,```'_``/_```#_P```J0.``/P!```\@```BBS``/H```` +M@@```TJ4``/_```#86P``T````/_```"M"```D1!``/P`@``\C$``BI```-* +ME``#_P```V%P```"`P`#_P```K0$``)$!``#\`,``/(Q``/!_@`"*O(```(# +M``/_```"M`@``D0$``/P`P``\C$``^CP``(J\@`#0````_\```/_```"1#X` +M`_`"``#R,0`".#L``T````/_```"M!```D0T``/P`@``\C$``CE?``-*E``# +M_P```V%T``/X`P`#0````_\```*T"``"8`$``D0$``/P#``#2`@``_\```*T +M0``"8`0``V@(``-)F``"M/T``D$4``-IF``#Z#```\$N``-H,``",9X``^@` +M``/H$``#Z#```K(#``-H,``#0````_\```*U@``"81```D45``/P`0`"-YH` +M`TJ4``/_```#87@``KP!``(REP```C(``_\```/_```"H0X``_`"``/H```` +M@@<``BV(``-(```#2`4```HF```"*@``$B4``"HL```Z*``#_P```V@```-H +M!0`#2!```TG=```**0``*BL``_\```-H$``#:=T``TEQ``*R`0`#Z#```\$& +M``/!%P`#:#```C&>``/H```#Z!```K(#``*S```#:#````(+``/_```#_P`` +M`J`.``("A@`"(N<``_0```'``````>4``T`2``-`%0``"@T``J`.``/P`@`# +M]````<*A``+!'@``B@T``FNZ``)E6P`"QFX``_!!``,&;@`#8!4``K(/``)$ +M0@`"I10``_`'``/HH``#Z+```V`2``/H````@>4``_0```'`:P`#0"P``_\` +M``*T(``"0$```_`"``/T```!PK4``T@(``*TOP`"0`0``V@(``/H````@C$` +M`C&#``#R,0`",8,``T@(``*T0``"8`0``V@(``/H````@C$``C"X``#R,0`" +M,+@``TD]``-(P``"M@@``D9D``/P`@`"M3```F(E``-HP``#:,0``B+G``-` +M(``#_P```_\```+"+@`#\$0``L,^``/P0@`"LO\``K/_``-@(``",@P``TM@ +M``/`C@`"0`@``VM@``-)2``#0"H``K0_``*U@``"MD```D9H``/P10`"0S0` +M`F,U``-I2``"0S0``VE(``/H```#Z!```^@@``/H,``#9*0``V3D``/T```! +MP````TL=``-`*``"O!```K\$``),P``#\`4``F=^``-K'0`",9X``F=_``-K +M'0`#[````T`$``!J,0`#Z(```^B0``/HH``#Z+```J#>``/P`P`#9*H``_0` +M``/P00`#9.H``&'I``*@W@`#\`,``^A```/T```#\$$``X3J``/80``#W,`` +M`'GH``/X`P`#U)X``_L```,/_@`"`PH``"'#``*@W@`#\`,``&'"``/T```# +M\$$``&'!``*_"``#W$```]C```/X`P`#U)X``_L```,/_@`"`QD``_@#``/L +M`````C(``&HQ``/_```"H`X``_`!``/L```#23@``J#>``/P00`#23@``KC^ +M``)"*``#:3@``TG0``*T!``"810``K(!``*S$@`"H-X``_!!``*S$0`#:#`` +M`TEQ``*X[P`"N00``\$&``)A>0`"0S@``V@P``-("0`"N/T``D1(``-H"0`" +MM`$``B/J``(M8@`#2:```K01``/!)``"L0\``VF@``*@W@`#\`,``T)A``/T +M```#\$$``T)=``/_```#_P```^A@``-II0`#:&L``KH,``*XP``#W($``]BA +M``*P^``"L0<``^@@``/H,``#_@```]0?``-H:P`#Z/```B/3``(CPP`")`4` +M`J'^``/P00`#8GH``T)X``/_```#_P```J"```'#=@`"H)$``<-V``*@H@`! +MPW8``J"S``'#=@`"S_X``KP,``*A_``#\$(``_0```'#8```^``#_P```_\```*@@``!PXP``J"1``'#C``"H*(``<., +M``*@LP`!PXP``L_^``*\#``"H?P``_!"``/T```!PWD``&'.``#YQ0`#_P`` +M`J7/``'#G``"I?P``<.7``/H\``#Z,```_0```'#GP`##,\``ZS```/H\``# +M]````<.?``,/_``#K_```^C```(CTP`#P?P``B/#``*P&``")"0``K0```(C +MZ@`#23@``J#>``/P00`#23@``_\```)B+@`#:3@``TG0``*T^P`"010``K(! +M``*S$@`"H-X``_!!``*S$0`#:#```TEQ``*X[P`"N?L``\$&``)!>0`"0S@` +M`V@P``-("0`"N`(``F1(``-H"0`"+8@``^P```/!#P`#P1\``\$O``/!/P`" +MH-X``_`%``-DL``#9+0``V2X``/T```#\$,``V3P``-D]``#9/@``B/A``/L +M```#P0\``\$?``/!+P`#P3\``J#>``/P!``#9*P``V2\``/T```#\$(``V3L +M``-D_``"(^$``^P```-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@` +M`^P```)-W@`#\$,``T +M``/!^``#[````^C```.'/``#IW8``X8L``.F:``#A1P``Z5:``.$#``#I$P` +M`FS'``)LQ@`";,4``FS$``/L```#0"0``&HQ``/_```#H`8``J$.``/P`0`` +M@?D``TFA``-)I``"NT```KJ_``)%I0`"H-X``_`#``)#HP`#]````_!!``)C +MLP`#::0``VFA``(RN@`#Z````^@@``/H,``"H-X``_`#```)^P`#]````_!! +M```)^@`"N,```VAK``/8```#W(```]0>``*_"``"+5X``X#@``"!]@``@?4` +M`^@```"!]```@?,``/'R``-(5``"H-X``_`#``.$Z``#]````_!!``.$Z@`" +M8B0``VA4``-)=0`#B.8``F!H``/!%P`#P2X``\$^``*@W@`#\`$``X,P``-H +M,``#2%0``J#>``/P`P`#A.@``_0```/P00`#A.H``\!$``)")``#:%0``&(+ +M``*_`@`"+5X``J#.``/P`@`#]````@2P``(O`@`#Z'```X3F``)&2P`"H&0` +M`_!*``-)T@`#Z&```XJR``.JJ@`"H:X``_`"``,!K@`")BL``_0```'%5@`" +MOP@``D_Y``.O]``#B[(``ZN\``(E;P`#]````<56``-`$``#_P```K\"``)/ +M\``#\`(``_0```'%5@`#0`P``_\```*_"``"3_```_!"``/T```!Q,@``K\` +M``*[`0`")6\```($``/_```#_P```J`.``/P0@`#]````<56``#Q]```\?,` +M`J#>``/P`P``>?@``_0```/P00``>?<``XWB``/,``$'Y``/HT``#C^```\&H``.,[0``X><``.(P``(N:P`"MP$``$'Y``/H +MH```T>,``J!^``/P`0`#J(```P_?``/!V0`#P:@``XSM``#AYP``XC```BYK +M``(NK``#P00``\$F``-B<``"OP$``T`1``.(X``"H/X``_`$``)$2``#\`(` +M`_0```(%/``"MP$``$'Y``/_```"H'X``_`!``.H@``#Z-```X_@``/!J``# +MC.T``.'G``#B,``"+FL``BZL``-"<``#C.L``XSJ``/H\``"R$```ZB````J +M"0`"RF(``ZJ@``*F7@`"!1D``&HQ``#R"0`#P5@``\%Z``-B<0`#]````@33 +M``*A7@`#\`X``&HQ``/!D0`#P;,``J#>``/P`P`#82X``_0```/P00`#83(` +M`L"!``.H```"PJ,``ZH@``.%4```J@D``X'@``,`A``#\"0``J&$``/P`0`" +MQ$$``P1.``/!5``#`J8``_`D``*AI@`#\`$``L9A``,&;@`#P78``]1>``)@ +M`@`"!2L``&HQ``*_`@`"+5X``TEQ``.!Y``#P08``Z)L``*@+@`"!58``F%Q +M``/!+@`#P3X``J#>``/P`0`#@S```X9@``/P1P`#:#```X_M``(M7@`#C^T` +M`BU>``./[0`"+5X``X_M``(M7@`#274``\$N``/!!@`#P1<``\$^``*@W@`# +M\`$``X,P``-H,````>4``_\```/_```"I0X``_!(``-`$0`"H-X``_`#``)F +M;@`#]````_!!``)G?@`#8!$``^@```"!Y0`#[````J#^``'%>P`"L`\``K$/ +M``*R#P`"LP\``J#>``/P`P`#8R@``_0```/P00`#8V@``C&>``-*0```0?(` +M`$GV``!1]0`"O#,``D0,``)%'``"9$4``D8L``)'/``"9F<``F1&``*A3@`# +M\`$``K0!``*@C@`#\`4``J1)``/P0P`"I$L``_!!``#Q]```H?8``KS,``)$ +M#``"11P``D8L``)'/``"9$4``F1&``)D1P`"H4X``_`!``*T`0`"H(X``_`% +M``*D2@`#\$,``J1+``/P00``\?,``*'U``/H0```H?(```'T```1\P`"L0\` +M`K,%``*E_@`"!=$``J#^``/P00`#Z/```J`.``/P`0`"S_X``K$0``*@+@`# +M\`$``L_Q``*SD``"IO,``_!"``#QY0`#[````D,"``/P0P`")A$``_0```'% +M>P`"M!$``P_T``*@W@`#\`,``/GQ``/T!``#\`$``/GP``-#*0`"H-X``_!! +M``-#:0`"OW<``B7P``/L```#2.4``J#>``/P00`#204``K@1``*@#@`#\`$` +M`L1(``))00`"I),``_`!``#Q]``"H"X``_`!``+%6``"25$``J23``/P`0`` +M\?,``J#>``/P`P`#:.4``_0```/P00`#:04``D`"``*@#@`"!7L``K$"``(F +M*P`#[````J'^``/P00`#[````Z'V``./]@`#H/8``J$.``/P!P`"O`D``J!, +M``/P00`"O`\``\%,``/!7``#``X``J$>``/P!P`"O`D``J!L``/P00`"O`\` +M`\%L``/!?``#`1X``J#>``/P`P`#8RD``_0```/P00`#8VD``F(!``(%]@`# +M[````T,I``*@W@`#\$$``T-I``*@#@`#\`4``K0/``),_@`#\`$``K0)``/! +M5``"H"X``_`&``*V#P`#K/8``DS.``/P`0`"M@D``\%V``*@W@`#\`,``V,I +M``/T```#\$$``V-I``/L```#2.4``J#>``/P00`#204``K`1``+$0``"Q5`` +M`J#>``/P`P`#:.4``_0```/P00`#:04``P$>``(&+P`#[````&HQ``/H```" +M+MP``/'O``/H````@>X``T`,``-`+0`"N!```KD(``)*&``#JJ8``DM)``.K +MM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!` +M``/P00`#Z#```D$>``/P`0`#Z#```)GM``(M8@`"N!```KG^``*@W@`#\`D` +M`T@A``*Z#P`"1FH``D=Y``)F:``#:"$``VJ)``/T```#\$<``T@E``*Z#P`" +M1FH``D=Y``)F:``#:"4``VJ-``(P@@`"OP,``C!.``*_9``"+5X``&HQ``/_ +M```#_P```J#>``/P`P`"NP```_0```/P00`"NT```-G@``/!#@`"L1$``K(0 +M``-J1``"L1```^@@``-J1``"L/\``K'_``*R_0`"L_\``VA@``-*8``"O_<` +M`K$3``)`#P`"8`X``VI@```Q_@``.?T``KP(``*__@`#AFH``F(F``*D?@`# +M\`$``K,$``)`#P`"8`P``VI@``./X0`"+5X``VAK``/_```#_@```&(O``!: +M+@`#_P```]C!``/``/0'P`#C.\``X_D``)O_@`"0`$``D(C +M``)``@`"3,```_L!``/0'P`##_X``@:L``*@W@`#\`,``T@A``/T```#\$$` +M`T@E``/`S``"!M@``XSF``+&;``#\$$``L=^``*@W@`#\`0``V@A``-JB0`# +M]````_!"``-H)0`#:HT``J5^``/P`@`#]````<9^``-`$0`"L`@``/'E``*@ +MW@`#\`,``F9@``/T```#\$$``F=P``-@$0`#]````@@*``.`X0`#@08``F$> +M``."YP`#:D0``X$&``/H(``#:D0``C""``-`+```6AT``K0$``/H\``"1$`` +M`_`!``*_`0`"I+X``_`!``*_!``",$X``/(9``#R%P`",K0``C""```*+0`` +M$?X``!G]``*P`@`"H-X``_!!``*P!``#@BH``J0^``/P`0`"LP0``X$6``)@ +M`0`"L3,``VI@``-`"@`"L`$``K$"``*R```"LP$``J`K``/P`@`#Z"```\$[ +M``-J:``#P0X``K()``)`"0`#\`$``^@@``*P$P`"L0(``X(F``/H,``#:G`` +M`&($```2&@`"H,X``_!!``*R!``"L"$``K$"``*S`0`#:G0```H=``*P`0`# +M_P```J0>``/P!0`"L00``K(```*S`@`#]`0``_`#``*Q`@`"L@\``K,!``-J +M>``#2GP``_\```*P`0`"L0(``K,$``-J?````>X``_\```/_```"P`X``('N +M``(P20```AD``T`*``-`#0`"H`X``_`%``*P`0`"0`4``X`&``/T!``#\`,` +M`K`$``)`"0`#@`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`" +MLP$``VID``(O%P`"+R0```'O``/_```#_P```J`.``/P3@`#0"P``KP$``/< +MP``#C^H``J#>``/P`0`#Z/```]CP``*\"0`"OS\``DL?``(MY0`#Z/```/GO +M```![@`#_P```_\```+`#@``@>X```GM``-`+@`#_P```J`!``('@P`"L`$` +M`D$(``/P!0```C(``_\```/_```"H`X``@>#``-*=``#23T``_\```.B5``# +M@B```T`)``*E+@`#\`$``K((``)%7@`#\`$``!(:``/_```#_P```VIT``(P +M20```AD``T`*``-`#0`"H`X``_`%``*P!``"0`4``X`"``/T!``#\`(``K`0 +M``)`"0`"L4,``F@!``-*9``"M(```!'@``)`!``"8`@``Z(B``/!/@`#:F0` +M`B\7``(O)```0@,``K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```''LP`# +M0`X``K`0``/_```"00D``J`0``('LP```AD``_\```/_```"P`X``((9``*Q +M`@`"I`$``@X``C!)``-`"@`"L$`` +M`_\```)`"0`#H`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`" +MLP$``VID``(O%P`"+R0``T`E``!"`P`"L"```D`%``/P2``"L`(``J#>``/P +M00`#@`(``D`(``/P`@`#]``````#[````&HQ``/_```#_P```J#>``/P`P`"NV(``_0```/P00`"NV@``_\` +M``/_````V>P``C#_``/H```"+MP``KL"``#:,``#Z````K%@``/H(``#Z#`` +M`VF@``/H```"L1```^@@``/H,``#:D0``C""``*_`@`",$X``K#_``*Q_P`" +MLOT``K/_``-H8```"BT``!'^```9_0`"L`H``J#>``/P00`"L`P``X$6``)@ +M`0`#@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+5X``VAK +M``/_```#_@```C!X``-*8```,?X``#G]``*T]@`"M0,``X9J``)B)@`"I'X` +M`_`!``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``# +M:F@``K"```*R"0`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P +M(0`"L0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\` +M``*P`@`"L0(``K,$``-J?``",K0``^AP``-*9``"M(```D`$``/H(``#Z#`` +M`VID``-*9``"M(```!'L``)`!``"M`,``F`$``*S$``#:F0``B\7``-*9``" +MM`@``D1```)G=``"I7X``@BQ``/H```"+MP``J#>``/P`P`#2"(``_0```/P +M00`#2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H(@`#:HH``_0` +M``/P0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R'8``T`2``#QY0`"OP0` +M`J#>``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R+$``C!X``/L```` +M:C$``/'O``/H````@@8``T`(``-`+0`"N$```KD(``)*"``#JJH``DM)``.K +MM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!` +M``/P00`#Z#```D$>``/P`0`#Z#```)H%```AY0`#Z%```_\```"B#```J>4` +M`&HQ``/_```#_P```J#>``/P`P``6<(``_0```/P0P``6<$``_\```/_```` +MV>```T`L``!:'0`"M`0``^CP``)$0``#\`$``K\!``)+O@`"H+X``_`#``(O +M?P`#]````0``/(8``#R%P`",K0``C""```*+0``$?X``!G] +M``*P`@`"H-X``_!!``*P!``#@18``F`!``-`%0`#@BH``K&```)B(0`"I#X` +M`_`!``*S!``"MO```D1&``*Q"``"810``VI@``-`"@`"L`$``K$"``*R```" +MLP$``J`K``/P`@`#Z"```\$[``-J:``"L`$``K((``)`"0`#\`$``^@@``*P +M$P`"L0(``X(F``/H,``#:G```&($```2&@`#_P```J#.``/P00`"L@0``K`A +M``*Q`@`"LP$``VIT```*'0`"L`$``_\```)!$``"I!X``_`%``*Q!``"L@`` +M`K,"``/T!``#\`,``K$"``*R#P`"LP$``VIX``-*?``#_P```K`!``*Q`@`" +MLP0``VI\```*'0`#_P```_\```)!'@`"I!X``@F%```"!@`#_P```_\```+` +M#@``@@8``C!)```"&``#0`H``T`-``*@#@`#\`4``K`"``)`!0`#@`0``_0$ +M``/P`P`"L`@``D`)``.````"L0,``F@!```"'0`#_P```_\```)`#@`"I`X` +M`_`+```2&@`"L",``K$#``*S`0`#:G0``TI\``/_```"L`$``K$$``*S!``# +M:GP``TID``*T@```$>```D`$``)@"``#HB(``K,!``-J9``"+Q<``B\D```! +M[P`#_P```_\```*@#@`#\$X``T`L``*\!``#W,```K_```*@W@`#\`$``K^` +M``/8\``#C.0``K\_``)+'P`"+>4``^CP``#Y[P```@8``_\```/_```"P`X` +M`((&``!:'0``>A<``K@(``)*O@`"H*X``AH` +M`_\```/_```#P2\``VIT``(P20```A@``T`*``-`#0`"H`X``_`%``*P"``" +M0`4``X````/T!``#\`,``K`@``)`"0`#H````K%#``)H`0`#2F0``K2````1 +MX``"0`0``F`(``.B(@`"LP$``VID``(O%P`"+R0``$(#``*P`0`"H-X``_!! +M``.``@`"0`@``_`"``/T```!R>L``T`*``/_```"L$```D$(``*@$``"">L` +M``(8``/_```#_P```L`.``""&``"L0(``J0!``()0@```>```$'#``/_```# +M_P```]@```/<@``"OP@``K#```/8`0`"L````]P!``(O#@```@8``_\```/_ +M```"P`X``((&``(P20`#0`H``K"```/_```"0`D``Z`$``*Q`P`":`$``TID +M``*T@```$>```D`$``)@"``#HB(``K,!``*Q```#:F0``B\7``(O)```0@,` +M`K`!``*@W@`#\$$``X`"``)`"``#\`(``_0```'*+0`#0"X``_\```*P"``" +M00@``J`0``(*+0`"L(```D$(``/P!0```C(``_\```/_```"H`X``@HM```" +M%P`#_P```_\```/H$```BA<``J0.``()A0``8<,``%G@``/_```#W,```]BP +M``*_"``"L,```]@!``*P```#W`$``C*Z``-H:P``$=8``K/```/HT``#8G0` +M`BX-``(P>``#[````&HQ``/_```#_P```J#>``/P`P`"NU,``_0```/P00`" +MNUL``_\```/_````V>P``T`0``*['P`#2"D``J#>``/P00`#2"T``D`+``.O +M`@`#C/8``FS/``./]@`#2>@``J-,``/P!``#!$P``P5?``/T```#\$(``P3$ +M``,%]0`#P00``\$5``*@W@`#\`0``V@I``-IZ``#]````_!"``-H+0`#:>P` +M`^@```(N\``#Z````K%```/H(``#Z#```VI$``(P@@`"OP(``B]_```*+0`` +M$?X``!G]``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`"L80``F(A``*D +M/@`#\`$``K,$``*Q&``#:F```T`*``*P`0`"L0(``K(*``/H,``#:F@``K"` +M``*R"``"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`"L0(` +M`K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P`@`" +ML0(``K,$``-J?``",K0``^AP``(P20`#2F0``K2````1[``"0`0``K0#``)@ +M!``"LQ```VID``(O%P`#2F0``K0(``)$0``"9W0``J5^``(*[P`#Z````B[P +M``*@W@`#\`0``T@J``-)Z``#]````_!"``-(+@`#2>P``KP1``*_$``"R9\` +M`LB,``/P00`#Z(```\$(``/!&0`"H-X``_`$``-H*@`#:>@``_0```/P0@`# +M:"X``VGL``-*P``"OP<``DW>``/P`0`"OS@``J&.``/P0P`"8`\``VK```-J +MQ``"NP$``-HP``/H<``"3_```_`#``*[_P`"H(L``_`"``/T```!RJ<``T`2 +M``#QY0`"OR```J#>``/P`P`":J\``_0```/P00`":[\``V`2``(P@@`",$D` +M`^P```!J,0`#Z````(',``""#``"H-X``_`#``!9P@`#]````_!!``!9P0`" +ML'\``J'^``/P00`"2[```-G@``(RM``",((```HM```1_@``&?T``K`"``*@ +MW@`#\$$``K`$``.!%@`"8`$``X(J``*Q@``"8B$``J0^``/P`0`"LP0``T`5 +M``*Q"``"MO```D1&``)A%``#:F```K`!``*Q`@`"L@```K,"``-J:``"L@@` +M`K`3``*Q`@`#@B8``^@P``-J<```$AH``K`A``*Q`@`"LP$``VIT``*P`0`" +ML0(``K(/``*S`0`#:G@``TI\``/_```"L`$``K$"``*S!``#:GP``KP$``/< +MP```>>```KP(``*[&``#V/```BWE```!S``#0"4``K\0``+`#@``@```K"```/H\``"H<```_!!``/!_@`"*[8``C!)```1X``# +MZ!```K`C``.B(@`"LP$``VID``(O%P``8``/[```"I2X``_`!``/[```#U)\``_L!``*E+@`#\`$` +M`_L!``,/_@`""V\```',``/_```#_P```L`.``"!S```8>```K"```/!_@`" +MH<```_!!``/H\``"*[8``C!)```1X``"L`,``^@0``.B(@`"LP$``VID``(O +M%P`"+R0``T`E```!S``"L0,``K((``*S$``"0S4``_`"``)")0`#\`(``J4! +M``'+.@``8<,``%G@``/_```#W,```]BP``*PP``#V`$``K````/<`0`"OP@` +M`C*Z``-H:P``$=8``K/```/HT``#8G0``BX-```"#``#0!$``K&```)`#@`# +M\`,``F9A``-@$0``@>4``C!X``/L```"O!$``J#>``/P!``#2,P``TC1``/T +M```#\$(``TCL``-(\0`"*^X``J#>``/P!``#:,P``VC1``/T```#\$(``VCL +M``-H\0`"H-X``_`$``-(U``#2-D``_0```/P0@`#2/0``TCY``(K[@`"H-X` +M`_`$``-HU``#:-D``_0```/P0@`#:/0``VCY``*@W@`#\`,``TC<``/T```# +M\$$``TC\``*@_@`#\`0``L`,``+!'``#]````_!"``,`#``#`1P``J#>``/P +M`P`#:-P``_0```/P00`#:/P``^P```*@_@`#\`D``L`,``+!'``"PBP``L,\ +M``+$3``"Q5P``L9L``+'?``#[````P`,``,!'``#`BP``P,\``,$3``#!5P` +M`P9L``,'?``#[````K@/``*Y\``"2@@``DL)``(L'0`"2A@``DL9``(L'0`" +M2B@``DLI``(L'0`"2C@``DLY``(L'0`"2D@``DM)``(L'0`"2E@``DM9``(L +M'0`"2F@``DMI``(L'0`"2G@``DMY``(L'0`#[````J&N``/P00``\@P``J&^ +M``/P00``\@P``^P```*P?P`"L?\``K+_``*S_P`#:&```VAK```)U@`#Z``` +M`Z`#``/<```#V!```T`Q``*_`P`"O`(``J;\``/P00`#P0<``J#\``/P00`# +MP08``J#^``/P00`#P04``J'^``/P00`#P00``\$0``/!(``#P3```_X```/4 +M'@`#:&L``_L```,/_@`"##(``T`U``*_`P`#_P```J;\``/P00`#P0<``J#\ +M``/P00`#P08``J#^``/P00`#P04``J'^``/P00`#P00``\$0``/!(``#P3`` +M`_X```/4'@`#:&L``_L```,/_@`"#$H``T`X``-`/0`#_P```VJ$``-J@0`# +M[````TA5``/_```"M\```VA5``-H:P`#2`H``K]_``)H^``"LN\``Z"!``*_ +MPP`"0`\``T`E``*S_P`"L?\``D]>``/P`@`"N?,``D(I``*\`@`"3%P``_`! +M``*S^P`#:&```TA```./\@`"O/L``D$<``)A'P`#:$```VAK``-)?``"M`0` +M`F$4``-I?``#2I0``_\```-A?``#:&L``C&>``/_```#_@```_\```-!20`# +MZ/```]SP``-(9``#B$0``ZB```*\0``"S,@``]C```/4'@`",L```V%)``-( +M9``"M!```D8D``/P`@`#]``````*_ +M4``"+5X``K\(``(M7@`#]``````#:"T``VGM``-(R``"N/L``D(H``-HR``#2)@``K@@``)@"``# +M2+$``VB8``)D2``#:+$``\$.``/!'@`#P2X``\$^``-C,``#8W```V,T``-C +M=``#8S@``V-X``/T```!S4H``T@(``*X]P`"0`@``V@(``-(*``"N-\``D,X +M``-(+0`#:"@``VGH``)'>``#:"T``VGM``-(R``"N`0``F(H``-HR``#2)@` +M`KC?``)`"``#2+$``VB8``)$2``#:+$``K`#``/!$``#P2```\$P``-C,``# +M8W```V,T``-C=``#8S@``V-X``-)?``"M/L``D$4``-I?``#:&L``_0```', +MBP`#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(``VC*``)H(0`#:,H``\&" +M``-HR@`#[````_@#``,/_@`"#5\``^P```(RN@`#:&L``\$.``/H$``#Z"`` +M`^@P``.D$P`#V!```]Q```/^```#U!X``VAK``-II``#Z````_X```/4'@`# +M:&L``VFD``*@W@`#\`,``T)@``/T```#\$$``T)<``-"60`"H-X``VFD``/P +M`P`#0F@``_0```/P00`#0F0``VFA``/^```#U!X``VAK``-H:P`#[````C*Z +M``-H:P`#0E8``\$.``/H$``#Z"```^@P``.D$P`#V!```]Q```/4'@`"OP(` +M`BU>``-H:P`#::0``VFB``/H```#_P```]0>``*_`@`"+5X``VAK``-II``" +M,KH``VAK``/L```#:&L``C*Z``*Q#``#Z````Z`#``/<```#V!```^@```/H +M$``#Z"```^@P``/^```#U!X``VAK``/[```#^P```XCC``/X`P`#_@```]0> +M``-H:P`#^P```PB.``(-M``#[````"'K``/H4``#Z&```^AP``*Y"``"N,`` +M`]R!``/8D0`#0E```_@#``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`# +M:&L``\&/``*_$``"+5X``K09``/^```#U%\``VAK``*_$``"+5X``\'X``-) +MI0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``#"9X``@WA +M``-II0`#[````J&^``/P#@`#T!X``P^^``*Z/P`#``X``D`*``,!'@`"01H` +M`P(N``)"*@`#`SX``D,Z``/4'@`##_X``@WJ``/[```##,X``@WE``/L```" +MH;X``_`.``/0'@`##[X``KH_``+`#@`"0`H``L$>``)!&@`"PBX``D(J``+# +M/@`"0SH``]0>``,/_@`"#?X``_L```,,S@`"#?D``^P```/0G@`#T!\``KP_ +M``)(C``"29P``DJL``)+O``"1`P``D4<``)&+``"1SP``KP@``+`A``#H``` +M`J-(``/P00`"P`P``L&5``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`# +M\$$``L(L``+#MP`#HS```J-[``/P00`"PSP``KP'``*CW``#\$X``W)T``-2 +M=@`#_P```_\```/^```#U!X``VAK``/[```#<``&(P``/_```"H;X``_!"``#QY0`#[````J'.``/P00`#"[X` +M`PS.``#9YP``XC```TI```!:"0`#_P```_\```*@O@`#\$(``Z````.B(``# +MT%X``&'\``!9XP`#H@(``D`)``)"*0`"I8X``@Z6``,(C@`"H`T``_`+``!! +M^0`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$3P`#P50``J6N +M``(.I@`#"JX``J`M``/P"P``4?D``L9O``/!=@`"H+X``_!&``/47@`"QF\` +M`\%V``/47@`"QF\``\%V``/47@`##,X``@ZG``)KB@`"#FL``^P```-"<``` +M4@D``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``"H6@``_!!``+& +M:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,&:``#`B@``P,X +M``,*K@`"#KH``\%4``/!=@`#U%X``V)P``/L```#P6(``P9N``/<$``#V``` +M`]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X``_L```,&;@`" +M#L\``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``#:1```VD4``-I +M&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I-``#[````\$0 +M``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC<``/T```#\$4` +M`VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4``D$#``-)T@`# +M_P```D`*``-)P@`"I1```_`!``-)Q@`#[````]">``/[```#_P```_\```/4 +MGP`#^P$``P_^``(/#@`#[````_@!``*_!``#2F0``_\```/_```"00\``@\9 +M``/X`P`#:&L``_\```/_```#_@```^P```-*9``#_P```K\(``)!#P`"H!\` +M`@]%``-`$@`"M1```J4E``/P!``"OP(``FJO``/T```!ST(``L15``*E)``# +M\`0``K\"``)KOP`#]````<]"``+$10`"I20``_`$``*_$``":J\``_0```'/ +M0@`"OQ```FN_``#QY0`#8!(``B]&``/L```#2G```_\```/!P@`#0"X``K`! +M``-JJ``#_P```_\```/_```#2JP``K0"``-JJ0`#P````\`1``/`(@`#P#,` +M`TJM``*_D``"H,\``_`%``/`1``"OP\``D]/``/T```#\$$``\#T``*@W@`# +M\`L``T`9``/_```#_P```F1```)E40`"9F(``F=S``-@&0`":J\``_0```/P +M20`#0!T``_\```/_```"9$```F51``)F8@`"9W,``V`=``)KOP`#8"X``^P` +M``+$1@`#:JD``_\```/_```#_P```TJL``/L```",KH``VAK```)U@`"L,`` +M`]P```/8$``"H/X``_`$``/H```#Z!```^@@``/H,``"H/X``_!$``*P50`# +MP1```\$@``/!,``"H/X``_`$``*T_P`#P50``\%D``/!=``"H/X``_!$``*T +MJ@`#P50``\%D``/!=``"O`<``J/^``(/^```0?\``_\```/_```"H(X``@^^ +M``*@W@`#\`,``T!"``/T!``#\`$``T!&``#J,0``:@```J3>``/P!``#P(@` +M`\"9``/`J@`#P+L``F`(``)A&0`"8BH``F,[``)D2``"95D``F9J``)G>P`` +M:C$``_\```/_```#_@```]0>``-H:P`#^P```PS.``/^```#U%X``VAK``/[ +M```##,X``@^^``!!_P``8@```_\```*@C@`"#^,``T!*``*DS@`#\`0``\"( +M``/`F0`#P*H``\"[``*DW@`#\`(``\&*``/!FP`"N@\``DJH``.+I@`":JL` +M`KOP``)+N``#I[8``FNW``/T!``#\`,``^A@``/HH``#Z+```K3P``)@2@`# +MP1```\$@``/!,``#:H0``J#^``/P`P`"M/```_0$``/P`0`"M`\``F!+``/! +M$``#P2```\$P``-J@``#[````_X```/4'@`#:&L``_L```,,S@`"N0,``J#Y +M``/P1``#Z$```^A0``/H8``#Z'```_X```/47@`#:&L``_L```,,S@`"$`0` +M`K#P``*Q_P`"H/D``_!"``/H```#Z!```\$A``/!,0`#:H0``VJ```/L```" +M,KH``VAK```)U@`"L,```]P```/8$``"M/\``\%D``/!=``"O`<``_X```*U +M_P`#U%X``VAK``/[```##,X``_X```*U[P`#U%X``VAK``/[```##,X``A`? +M``*U_P`#:H4``K#P``/!$``#P2```\$P``-J@``#2F(``C!)``/H\``",%4` +M`VIB```)U@`"L,```]P```/8$``"M/\``\%4``/!9``#P70``KP'``/^```# +MU%X``VAK``/[```##,X``A!!``(RM``#[````TID``*T@``"0`0``VID``/L +M```"L`0``J#P``/P`P`"+W\``_0$``/P`0`"+"0``^@```/````#P1```K+] +M``*S_P`#:&````HM```Q_@``&?T``K`*``*@W@`#\$$``K`,``.!%@`"8`$` +M`K$6``*D/@`#\`$``K,$``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`" +ML@0``F(F``-J8``#C^$``BU>``-H:P`#_P```_X```/L```#2F```_\```/H +M,``"8`X``VI@``-*9``"M/(``D`$``-J9``#[````K`!``/H$``#Z"```^@P +M``-J8``#[````&HQ``-`!``#_P```K@$``)%X``"H%X``_!$``*@W@`#\$(` +M`T`D``/_````8>D``_\```/_```#W,```X_J``*@W@`#\`$``^CP``/8\``# +MC.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<``D`(``/P +M0P`"+>4``_0```/P00`"+?D``D1N``/P"0`#Z,```ZMB``.E8``"15X``_!# +M``(MY0`#]````_!!``(M^0`#[````&HQ``-`*``#0"$``KA```)(@``#\`,` +M`D9N``/P`0`#[````%'#``*@W@`#\`,``%G"``/T```#\$$``%G!``/_```# +MW*```]BP``-`!@`#_P```_\```)`Z``#\`,``J#>``/P00`#0"8``_\```/_ +M```#24$``J`.``/P0P`"H-X``_!!``/!10`"14X``_!#``.,Y``#]````_!! +M``.,XP`#B9@``ZJ<``*@K@`#\`,``BWE``/T```#\$$``BWY``-`!@`#_P`` +M`_\```-)00`"0(X``J`.``/P0P`"H-X``_!!``/!10`#Z,```ZM"``)%3@`# +M\`<``Z5```)%7@`#\$,``BWE``/T```#\$$``BWY``/L```"H-X``_`#``-( +M(0`#]````_!!``-()0`#_P```KL!``.B9@`#@68``Z$6``.'=@`"8"<``P`+ +M``.G!@`#@@8``F8A``*@W@`#\`0``V@A``-JB0`#]````_!"``-H)0`#:HT` +M`^P```./[0`"+5X``^@P``."X``#Z!```^@```-H,``#C^T``BU>``-)G``# +M2=4``T`J``*T$``"1$<``K4"``)%6@`#A50``D1%``.D0``"MO<``D(F``)B +M)``#:9P``^CP``-)<``#Z'```K8!``/!40`#P4```V@Q``*X_``#P5,``\%" +M``)%6``#270``C&>``-H,0`#P5$``\%```(QG@`#:#$``\%3``/!0@`#29@` +M`C&>``-H,0`#P5$``\%```(QG@`#:#$``\%3``/!0@`#29P``C&>``-H,0`# +MP5$``\%```(QG@`#:#$``\%3``/!0@`#2.@``C&>``-H,0`#P5$``\%```*W +M$``",9X``V@Q``/!4P`#P4(``C&>``-H,0`#[````KP#``-)/0`#2,```J#> +M``/P00`#2,0``K8$``)&9``#\`0``X;*``/!?``"8B8``F$7``*@W@`#\`,` +M`VC```/T```#\$$``VC$``-`*@`"M@@``X?&``)&:``#\`$``F,W``*@W@`# +M\`,``VC```/T```#\$$``VC$``/L```",(@``TD]``-`*``"OP@``KP$``)/ +M#P`"3$P``F#\``/P00`#[````K0!``(R7``",6,``J'^``/P"0`",AT``C"" +M``-`*``"O`@``_\```)"+``#\$(``_0```/P0@`#Z$```C)<``/L```#_P`` +M`_\```/_```#[````V%(``-A00`#848``V)_``/!#@`#Z!```^@@``/H,``# +M:.@``^@```/_```#:.@``T%(``/_```#[````C*Z``-H:P``"=8``^@```.@ +M`P`#W````]@0``*\`P`"L/<``J#^``/P00`"L'\``\$0``/!(``#P3```K3_ +M``/!5``#P60``\%T``/^```#U!X``VAK``.@`0`#H1$``Z(A``.C,0`#^P`` +M`_X```/47@`#:&L``_L```,,S@`"$<0``K#_``*\"``#P1```\$@``/!,``# +M:H```J3^``'1W@`"H/P``_`"``-JA``#[````K#W``.A`0`#HA$``Z,A``-J +MA``#[````TD]``/_```"N(```F1(``-I/0`"L`$``K$"``*R/P`"0B\``K,` +M``-J:``"L````K$```*R```"LP(``VIT``*Q`0`"L@@``K,```-J>``"L`$` +M`K(```-J?```$>```K#```)`#P`#H`(``F`.``*Q```#HB(``K,!``-J9``" +M,K0``_\```/_```"+Q<``KA_``)$2``#:3T``^P```/H```#Z!```K(#``*S +M```#:#```^P```-`+``#_P```_\```/H(``#Z#```V`L``/H```#Z!```V`8 +M``-@'``#[````&HQ``*P`0`#Z!```^@@``/H,``#:F```K\!``(P3@`"OQ`` +M`BU>``*\%``#2F```K_W``*Q$P`"0`\``F`.``-J8```,?X``#G]``*\B``" +MM?X``X9J``)B)@`"I'X``_`!``*S!``"0`4``F`,``-J8``#2I8``T`I``*\ +M!P`#_P```D1,``.%1``"Q5X``\'%``/H0``#Z&```^AP``-JD0`"M/\``K5_ +M``*V_P`"M_\``VAA``-H:P`#_P```_X```,)G``#\$4``\"9``,*K@`#\$(` +M`\"J``,+O@`#:I(``X````.@```#:F```K\0``(M7@`#[````T`J``-'+``" +MH-X``_!!``-';``"MG\``X5,``)`!@`"29X``_`!``)@!0`#P1```\$@``/! +M,``"H-X``_!$``-G+``#9S```_0```/P0@`#9VP``V=P``-'-``"H-X``_!! +M``-'=``"MM\``X5(``)`!@`"8`4``\$0``/!(``#P3```J#>``/P1``#9S0` +M`V``#2,```J#>``/P00`#2,0``K8_``)")@`" +MML```J!.``/P`0`#Z&```F(F``*@W@`#\`,``VC```/T```#\$$``VC$``/L +M```#29@``K@/``*Y]0`#Z#```\$N``*@S@`#\`(``F`(``)!&0`#:#```T@( +M``*X0``"H,X``_`"``)@"``#:`@``^P```-A4``#854``V%:``-A7P`"+&4` +M`T%0``-!50`#05H``T%?``/_```#_P```^P```*P_P`"L;\``K+_``*S_P`# +M:&```^P```*P?P`"L?\``K+_``*S_P`#:&```^P```+$3@`#\$H``L5>``/P +M2``"QFX``_!&``+'?@`#\$0``K3_``*U_P`"MO\``K?_``/L```"H``/_```#_P```PS.``(2T``#[````K#_``*Q_P`"LO\` +M`K/_``-JD``#[````^@```"",0`"(O,``/(Q``(B\P`",U@``BU1``-)F``" +MM/,``K4/``)!%``"8`4``VF8``/!+@`#Z#```V@P```""@`#@>```^A```*@ +M`0`#\`$``\%.``(TN@`#2`@``KC^``)!&``#:`@``KP```(T90`"-)8``T`! +M``/H````@C$``D1.``/P`0`")$@``T`!``/_````\C$``D5>``/P`0`")$@` +M``(*``.!X``#_P```J00``/P`@`#P4X``C2Z``*\`0`"-&4``C26``*_`P`" +M-T```C.E``(O`@`"OQ```D_[``'30```>``(NW``"+P(``X3B``/! +MR0`#Z````K$#``*R"@`"LRT``D1)``/P`0`"LR\``^A0``(NRP`#@.H``B[+ +M``*X+P`"M`(``D1,``/P`0`"N"T``\&8``/!J``#P;@``V,J``-C:@`"+P(` +M`X'B``.@X0`#HY8``X+D``+"+@`#Z%```B[+``.@XP`"+LL``B\"``.`Y0`" +M0*```\$0``/!(``#P3```V2H``-DZ``#@.```H((``)"`@`#@B0``)'4``/L +M```"+P(``TEP``)$C@`#\$,``K7S``)")0`#:7```^AP``/!;@`#P5,``\%" +M``-H,0`"1)X``_`&``-)G``#I.$``F(D``/!4P`#P4(``V@Q``)$C@`#\$T` +M`TF<``.$Y0`#I><``D`$``)!%0`#I(@``X1```.%1@`"8`4``F$4``/H,``# +MP2X``V@P``-#I```(=0``K7/``)`!0`"8`0``\$0``/!(``#P3```V.D``-C +MY``"1$0``_`!``(W.P`#@80``Z`8``."!@`"8`(``^C0``(N\``#P=X``B[P +M``-)T0`"+P(``^A@``*E$``#\`$``K9```)&=@`#IFH``TB0``.DN@`"H$X` +M`_!!``*T!``"M0,``J!%``/P00`"M`$``K7P``)!%0`"810``K?^``)`!P`" +M8`8``VB0``-HJ``#:)0``VBL``.@I@`#P1```\$@``/!,``#9"0``V1D``.* +MM@`#2"$``K@#``)F:``"N0\``KO^``)&:0`"9FH``D=[``-H(0`#:HD``V@E +M``-JC0`#2`@``T@A``)A'@`#:`@``TC(``*X0``"N3\``F`(``-HR``"0`D` +M`VC(``/L```#0"P``KA```*Y@``#Z+```TJE``)(&``#\`$``KLP``))&0`# +M\`(``KK```)KN@`"95L``VJE``-(G``"O'L``D`,``-HG``#:*```VBT``-H +MN``#2)```X3B``.EYP`"014``F$4``*U_@`"0`4``VB0``-HJ``#:)0``VBL +M``-).``"M0,``F(E``*U\P`"0B4``VDX``/HP``"-&4``C26``/H```"L0,` +M`K()``/H,``#Z%```B[+``.`Z@`"+LL``K`$``/!$``#P2```\$P``-C)``# +M8V0``K`@``/!$``#P2```\$P``-C*``#8V@``C<[``-("``#2"$``ZCM``)! +M&``#:`@``ZCK``)&:``#P#X``D53``-H(0`#:HD``V@E``-JC0`#Z$```C2Z +M``/L```#0"D``_\```*X*@`"0EX``_`!``*X9``"H,X``_!!``*X$``#P9@` +M`\&H``/!N``#9RX``V``/`%``#H1P``X$4``*P +M]P`"2(```FB!``-HG@`#:*(``VBV``-HN@`#2NH``K#[``.!(@`"2J```FJA +M``-JZ@`#:NX``VKR``-J]@`#[````T`I``-'-@`"L`<``K$(``)"7@`#\`$` +M`K$8``*@S@`#\$$``K$```)(@``":($``\&8``/!J``#P;@``V@,``_\```*AB0`!U4@``P_^``*P$``"S_```^@` +M``"!Y0`#]````=4&``+/_@``^@,``,(&``/T```!U08``^C```#B`P`#Z#`` +M`C;'``/``/_```# +M^P```P_^``(560`"-K,``&(#``*P```#W````]P!``./P@`"L$```L`/``/8 +M```"L#\``D$/``*PP``"P`$``]@!``/47@`#T!\``K\0``*ASP`!U7H``J#> +M``/P`P`#P0H``_0$``/P`0`#P0L``]0?``/T```!U8$``J#>``/P`P`#P2H` +M`_0$``/P`0`#P2L``]0?``(V:P`#0`8``K`?``*Q(``#P2X``D$8``/P`0`" +MPBX``LS"``#B`P`"I<```A5>``-*E``#_P```V"\``-`!``#W.```K\(``/8 +M\``#W.$``K\L``/8\0`"OP@``ZP6``*ESP`#\$,``\#,``)LSP`"S,X``K\( +M``/0'@`#T%\``\&)``/!F@`#P:L``L1```.@0``"P`P``\&P``+%40`#H5`` +M`L$<``*F&P`#\`$``\&Q``+&8@`#HF```L(L``*F*P`#\`$``\&R``+'@`#!P<``_0$ +M``/P`@`#!WH``L=P``/47P`#^P```_L!``/07@`#"(X``A8%``*X`0`#P0$` +M`\$2``/!(P`#"9X``A8%``-$J``"H-X``_!!``-$Z``"H4P``_!%``/`1``" +M1$H``P0$``/T!``#\`(``P1*``+$0``"H5P``_!%``/`50`"15H``P45``/T +M!``#\`(``P5:``+%40`"H6P``_!%``/`9@`"1FH``P8F``/T!``#\`(``P9J +M``+&8@`"H7P``_!%``/`=P`"1WH``P``/!D``"H<\``_`!``/!D@`#8G4``,G.``/``/0GP`"00X``_!$``*@0@`#\$$``\%,``/!C``# +MH````D$.``/P1``"H%(``_!!``/!7``#P9P``Z````)!#@`#\$0``J!B``/P +M00`#P6P``\&L``.@```"00X``_!$``*@<@`#\$$``\%\``/!O``#U%X``]2? +M``/[```#^P$``Z````,/_@`"%HX``^P```*S$``"I<,``_`&``/`/``#@S8` +M`Z,V``(VT``#]````=;```*S#P`"S,X``D,\``(VQP`",A(``BU1``(TQP`" +MOQ@``CC&``(O1@`#[````K$$``*P@``"H-X``_!!``*PP``"L@D``^A0``(N +MRP`#[````\$#``/!$P`#P2,``J#>``/P`P`#9*@``_0$``/P`0`#9.@``^P` +M``-`!``"O(```_\```),P``!UOH``T$!``*@W@`#\$$``T$%``*Q!``"L(`` +M`J#>``/P00`"L,```]P0``/8```#P80``C<7``/!A0`"-Q<``\&&``(W%P`# +MP8<``C<7``*@W@`#\`,``V2A``/T!``#\`$``V3A``/T```!UQ0``K$$``*P +M@``"H-X``_!!``*PP``#W!$``]@!``*Q`0`"L`@``J#>``/P00`"L"P``]P0 +M``/8```"OP@``B\.``-!`0`"H-X``_!!``-!!0`"H-X``_`#``-DJ0`#]`0` +M`_`!``-DZ0`"+5$``C3'``/L```#P9@``\&H``/!N``"L@$``]2>``/[```# +M`BX``A<;``/L```"L00``K"```*@W@`#\$$``K#```/<$``#V````K$!``*P +M"``"H-X``_!!``*P+``#W!$``]@!``*_"``"+PX``T2H``*@W@`#\$$``T3H +M``*@W@`#\`,``V$```/T!``#\`$``V$$``/L```#2PP``K7\``)!%0`#:PP` +M`^P```-+#@`#P,\``FJO``-K#@`"2JP``TG5``*\"``#CW8``Z_T``+/_``" +M+5X``VL.``/L```#2PX``\#/``)JKP`#:PX``C&>``)*K``#:PX``^P```*_ +M`P`"-T```TG```-)U0`"3`X``_!"``/T```!UY(``TG```.'=@`"IG```_!" +M``/!$@`#Z````Z(6``.!%@`#H18``TB1``*\\``"15P``F52``*\!``"0PP` +M`Z,R``*\_@`"1$P``F1#``-HD0`#:)4``VBI``-HK0`#P4$``\%1``/!80`# +MP7$``V0A``-D)0`#9&$``V1E``*\`@`"0@P``X(J``-(G0`"LW\``D1#``)D +M0@`#:)T``VBA``-HM0`#:+D``J$.``/P`@`"-SL``K`0``/!$``#P2```\$P +M``-CH``#8Z0``V/@``-CY``"+5$``TE\``*T^P`"010``VE\``-H:P`#]``` +M`4``\&K``(M8@`"+;L``K0/``(QG@`#2D```_@!``*D0``#\`8``J1! +M``/P!``"I$(``_`"``*@0P`"&````LJN``*P(``"H*```_!!``/HH``"H*L` +M`A@J``-(&0`"LN```D9B``)F:@`#:!D``TGE``/_```"1F(``F9J``-IY0`# +M]`0``A?@``*C_@`"�``-'0``*@W@`"&`D``-'1``+-W@`#]`0``A>_``!! +MT0`#_P```_\```*@J``"�``J&H``/P2``#2"$``P.*``.#,``"9W,``V@A +M``-JB0`#]`0``A@T``-(&0`"LN```D9B``)F:``#:!D``TGE``/_```"1F(` +M`F9H``-IY0`#2"4``P.H``.#,``"9W,``V@E``-JC0`#]`0``A@T``-`$0`# +MZ,```/'E``*X@``"9W@``V`1``-)F``"M00``F$5``-IF``#2`@``_\```.$ +MR``"8`0``V@(``/X`P`#[````&HQ``/H````@@P``('/``(Y-``#0"0``_\` +M``/_```"0`X``_!+``-`$``"O`0``]S```./Z@`"H-X``_`!``/H\``#V/`` +M`KP)``/!L0`"+>4``T`D``/_```"O`(``D`,``/P2P`#0!```KP$``/``/P`0`"OX```]CP``.,Y``#P;$``BWE``(L)``"M`8``K4(``*V +M!``".1@``K\8``(XQ@`"..T``K\```(P3@`#2G```_\```/_```"LI```VIP +M``*_$P`".,8``CCM``-`)``#_P```_\```)`#@`#\$L``T`0``*\!``#W,`` +M`X_J``*@W@`#\`$``^CP``/8\``"O`D``XL0``(M^0`#0"0``_\```*\`@`" +M0`P``_!+``-`$``"O`0``]S```*_P``"H-X``_`!``*_@``#V/```XSD``.+ +M$``"+?D``TIP``/_```#_P```K*```-J<``"OQ@``CC&``(X[0`"OP```C!. +M``-*<``#_P```_\```*RD``#:G```K\3``(XQ@`"..T``T`D``/_```#_P`` +M`D`.``/P2P`#0!```KP$``/``/P`0`#Z/```]CP``*\"0`# +MP;$``BWE``-`)``#_P```KP"``)`#``#\$L``T`2``*\!``#W,```K_```*@ +MW@`#\`$``K^```/8\``#C.0``\&Y``(MY0`".58``^P```/H```#P````K&_ +M``/!(``"L_\``VA@``(P@@`",$D```HM```1_@``&?T``K`"``*@W@`#\$$` +M`K`$``.!%@`"8`$``X(J``*QA``"8B$``J0^``/P`0`"LP0``\$?``-J8``# +M2F0``K2````1[``"0`0``K0#``)@!``"LQ```VID``(O%P`"OP@``D_P``/P +M`0``\@P``^P````"#``#_P```_\```*E#@`#\`$``^P```/H````@@P``T`2 +M``/_```#_P```D2.``*@3@`#\`$``/'E``*_0``"H-X``_`#``)JKP`#]``` +M`_!!``)KOP`#8!(``B]&``!YSP`#_P```T`@``*@_@`#\$$``^P```*@W@`# +M\`4``L`.``/P00`"L/\``_0```/P0P`"P1X``_!!``*Q_P`#8"```/'/``/L +M```"L`$``K$"``/!)``#Z#```VIH``/!)0`"L!,``K$"``.")@`#Z#```VIP +M``*P(0`"L0(``\$F``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP` +M`_\```*P```"L0```K,$``-J?``#[````K`!``*Q$0`"LA```VI$``*Q$``# +MZ"```VI$``*@W@`#\`,``KM3``/T```#\$$``KM;``#9[``#2`@``K1```"! +MY@`"8`0``V@(``-(`0`"L+\``D1```-H`0`#Z````K%```/H(``#Z#```VI$ +M``*P`0`#Z!```^@@``/H,``#:F```^P```(P@@`",$D``"'F``/_```#2`@` +M`_\```/!!``#:`@``^P````*,@``:C$``_\```)`'@`#\$$``^P```(Y-``" +MOP```C!.```R&@`#_P```K4)``.F8@`"QFX``L1N``(Y&``#0"@``^CP``*@ +MW@`#\$$``K]```#YX``#H`P``('%``-`&``#0!T``T`N``!AY0`#_P```_\` +M``-A4``#854``V%:``#AQP`#0!```'G@``*\!``#W,```]CP``*\"0`#P;$` +M`BWE``/HP```X``/47P`"OP$``]SP``*_```#B,(``L_X``/8\``# +MQ````\01``/$(@`#Q#,``J#>``/P00`#P6<``K41``)$90`#Q$0``L`$``*U +M(@`"1&4``\1$``+!%``"M40``D1E``/$1``"PB0``K6(``)$90`#Q$0``L,T +M``/4'@``><4``T)U``-"<@`"3_X``_!"``+``0`"PB,``J$$``/P1@`"I0D` +M`_`$``/!C``#P9```\&L``/!L``"HPD``_!"``/!K``#P;```V)R``-"1@`" +MH28``_!&``*E*0`#\`0``\&,``/!D@`#P:P``\&R``*C*0`#\$(``\&L``/! +ML@`#8D8``J#^``':&``#0DX``J$5``/P1@`"I1D``_`$``/!C``#P9$``\&L +M``/!L0`"HQD``_!"``/!K``#P;$``V).``-"2@`"H3<``_!&``*E.0`#\`0` +M`\&,``/!DP`#P:P``\&S``*C.0`#\$(``\&L``/!LP`#8DH``V)T``/[`0`" +ML1```LS.``#AS@`"H,$``=FA``-"<``#0D4``_\```+(`@`#J(```LI&``.J +MH``#0DP``T))``/_```"R0(``ZF0``++1@`#J[```CI%``-`$```>>```KP$ +M``/4``^P```*[(0`"NQ````'%``/_```# +M_P```D`.``':?0`#J80``ZND``*\#P`#B(```DB,``.*H``"2JP``TB<``-( +MH0`"H-X``_!"``-(M``#2+D``\$8``/!6@`#C!8``X]6``)A'``"95\``J#> +M``/P!``#:)P``VBA``/T```#\$(``VBT``-HN0`#2N@``TKM``*@W@`#\$(` +M`TKP``-*]0`"O.X``D`,``)$3``#B)8``FR8``)@#``#BK8``FRZ``)D3``" +MH-X``_`$``-JZ``#:NT``_0```/P0@`#:O```VKU``/L```"OP4``KP```*@ +MW@`#\$$``KQ```/<\``#V,```KR```)HC``":9P``FJL``)KO``#P0@``CJ5 +M``/!"0`".I4``\$*``(ZE0`#P0L``CJ5``/4G@`#^P```]2>``/L```#P1`` +M`\$@``/!,``#U!X``_L```/4'@`#^P```^P```!J,0`"+6(``^@```*Q8``# +MZ"```^@P``-IH``#29@``K@/``*U]0`"LP```\$N``)@"``"014``V@P``*_ +M`0`"+5X``CDT``(P@@`#0"P``K\$``/_```"3_```Z_R``/H\``",$X``#(: +M``/_```"M0D``L1N``(Y&``#Z/```J#>``/P00`"OT```/G@``!9QP``>>`` +M`KP$``/<8``]1?``/[`0`#T%X``KL"``*A_@`#\$$``\%* +M``*@_@`#\$$``\%:``*@^P`#\$$``\%J``*F^P`#\$$``\%Z``/47@`#^P`` +M`K`0``+,S@`"I<```_`&``#AS@`#P8P``\&L``(Z10`#]````=K5``*Q!``" +MS_X``/G&``*A\0`!VQ```^BP``#9S@`#P8L``\&K``(Z10``>>```KP$``/< +MP``#V/```KP)``/!O@`"+>4``]S@``*[0``#V+```_0```':U0`".58``K@( +M``*Z"``".D4``%G'``!YX``"O`0``]S```/8\``"O`,``LN\``*\"0`"+?D` +M`T@(``*T8``"8`0``V@(``-)F``#_P```K(!``/H,``#:#```^P```*T!``" +M1C0``J!D``';,@`"OP,``CX_``-H:P`#0DD``C+```-B20`#[````T)-``(R +MP``#8DT``TAD``/X`0`"O0P``DG2``*@V0`#\$8``K\#``([D0`"OP,``KT` +M``([<@`#[````KT$``))T@`#\`8``K\!``([D0`"OP$``KT```([<@`#[``` +M`KT(``))T@`#\`8``K\"``([D0`"OP(``KT```([<@`#[````KU@``))T@`" +MH-D``_!'``*_`P`"/!```K\#``*]`0`"O`$``CMR``/L```"O2```DG2``/P +M!P`"OP$``CP0``*_`0`"O0$``KP!``([<@`#[````KU```))T@`#\`<``K\" +M``(\$``"OP(``KT!``*\`0`".W(``^P```-(8@`"3,X``AN$``.`\@`#P``` +M`X'X``/`$0`"3=X``_!%``/````":J```DJA``/T!``#\`,``\`1``)*H``" +M:J$``VAB``*P\@`":J```J`*``/P1P`#2$```K0(``*U]P`"810``VA```)! +M%0`#:$```VAK``/L```#2%0``^B```*Y`P`"2_X``_`!``)HB0`"N@(``KD, +M``)+^@`#\`$``FB)``)C.``#:%0``^B0``*T!``"2_X``_`!``)IF@`"2_H` +M`_`!``)IE``#26```VAK``/_```#_P```TAE``/_```"2]8``J"]``'<"@`" +M2Y,``=NF``-`*``#A/```*("``.B)@`",9X``P(N``';M0`#2`0``K3O``"* +M+``"010``V@$``(^,P`"M@0``V@Q``-"20`#Z(```]R```-*E``#B$8``ZB" +M``*\P``"S,@``]C```/4'@`#0"D``C+7``)%6@`"&_,``$H!``/_```"N(`` +M`\"9``.)G``"3/X``_`&``-)/``#2)D``F,X``)D20`#:3P``VB9``),^@`# +M\`8``TE```-(L0`"8S@``F1)``-I0``#:+$``DS^``/P!@`#2)```TB5``)@ +M"``"9$@``VB0``-HE0`"3/H``_`&``-(J``#2*T``F`(``)D2``#:*@``VBM +M``-`*``#_P```K@$``)!&``#\`$``CS)``-`*``#_P```K@(``)!&``#\`$` +M`CV#``-(0``"N(```DO^``/P`0`"81@``DOZ``/P`0`"8B@``VA```*\`0`# +M[````TA4``/`B``"0S@``VA4``*\```#[````T`H``#YNP`"N`@``D$8``/P +M`0`"/9H``T`H``/_```"N`0``D$8``/P`0`"/1@``T`H``/_```"N`(``D$8 +M``(<1P`"2_X``APJ``-)/``#2)D``KA_``)#.``"1$@``VD\``-HF0`"O`(` +M`DO\``(<-``#24```TBQ``*X?P`"0S@``D1(``-I0``#:+$``DO^``(<``T@$```B+``#_P`` +M`_\```/!%``#:`0``'F[``*X```"O`(``TA4``)+_@`#\`$``K@#``)+_``# +M\`(``KP,``)HC``#P(@``D,X``-H5``#@/@``(("``-"20`",L```V))``/L +M```#2`@``K@0``)!&``!W-H``DO^``/P!``#2E0``K0/``)@!``#:E0``KL" +M``)+^P`#\`0``TI8``*T#P`"8`0``VI8``)+_@`#\`0``TI4``*T\``"8`0` +M`VI4``*[`@`"2_L``_`$``-*6``"M/```F`$``-J6``#2`@``K@0``)!&``! +MW/@``DO^``/P!``#2E0``K0/``)A%``#:E0``KL"``)+^P`#\`0``TI8``*T +M#P`"810``VI8``)+_@`#\`0``TI4``*T\``"810``VI4``*[`@`"2_L``_`$ +M``-*6``"M/```F$4``-J6``#2`@``K@0``)!&``#\`$``^P```)+_@`#\`0` +M`TI4``*T`0`"8B0``VI4``*[`@`"2_L``_`$``-*6``"M`$``F(D``-J6``# +M[````T@(``*X$``"01@``=TI``)+_@`#\`0``TI4``*T_@`"0B0``VI4``*\ +M`@`"2_P``ATI``-*6``"M/X``D(D``-J6``"2_X``_`$``-*5``"M`\``D$4 +M``-J5``"O`(``DO\``(=-@`#2E@``K0/``)!%``#:E@``T@(``*X$``#_P`` +M`D$8``'=2``"2_X``_`$``-*5``"M/```D$4``-J5``"O`(``DO\``(=2``# +M2E@``K3P``)!%``#:E@``DO^``/P!``#2E0``K0/``)`!``#:E0``KP"``)+ +M_``"'54``TI8``*T#P`"0`0``VI8``-("``"N!```D$8``'=9@`"2_X``_`$ +M``-*5``"M/```D`$``-J5``"O`(``DO\``/P!``#2E@``K3P``)`!``#:E@` +M`KP(``(]YP`"M40``CUL``(^/P`#[````K?\``*V,P`"M````TC(``*@_@`# +M\$$``K0"``*\`@`"H/P``_!!``*T`0`"810``VC(``)@!0`#:,@``_\```)` +M!@`#:,@``KP"``(]YP`"01<``VC(``/L```#2`@``K@0``)!&``!W90``DO^ +M``/P!``#2)@``K1_``)")``#:)@``KL"``)+OP`#\`0``TBP``*T?P`"0B0` +M`VBP``-).``#A/(``\!$``)")``#:3@``^P```-).``#A/(``F(D``-I.``# +M2`@``K@0``)!&``#\`$``^P```)+_@`#\`0``TB8``*T@``"8B0``VB8``*[ +M`@`"2[\``_`$``-(L``"M(```F(D``-HL``#[````CWJ``-(5``#C/@``F(L +M``-H5``#270``KS?``)$+``#P5,``CXS``-H,0`",9X``KP0``)D3``#:#$` +M`C&>``-(5``"O)\``D(L``-H5``#270``_\```/!0@`#P5,``CXS``-H,0`" +M/@```K5```(];``"/=```^P```*[_``"2OX``_`(``-((0`#_P```F5>``-H +M(0`#:HD``D5;``-H(0`#:HD``KH"``)*KP`#\`@``T@E``/_```"95X``V@E +M``-JC0`"15L``V@E``-JC0`#[````PS.``'=YP`#[````D'^``(=]``#0ZX` +M`K#O``/_```"2[```DJP``))L``"2+```V.N``*Q`@`"0?$``AVR``-#[@`" +ML.\``_\```)+L``"2K```DFP``)(L``#8^X``^P```)!_@`"'@H``T.N``*P +M$``#_P```FNP``)JL``":;```FBP``-CK@`"L0(``D'Q``(>%0`#0^X``K`0 +M``/_```":[```FJP``)IL``":+```V/N``/L```"/C,``K8"``-H,0`"M@$` +M`TF>``*\$``"9*P``\%;``-H,0`#29H``KP"``)DK``#P5L``V@Q``/_```# +M270``KP0``)D+``#P5,``V@Q``(QG@`#P,P``D1,``-H,0`",9X``\%*``/! +M6P`#:#$``^P```/!;@`"MP,``DW^``/P`@`"O0(``D=]``*]`@`"3?T``_`" +M``*]`0`"1WT``^P```*X```"N0```KH```*[```#2L$``KR```/!;P`#Z'`` +M`VK!``-B@@`#0P```F9L``*WZ``#:L$``V,```-#*``"M_<``VK!``-C*``# +M0RP``KQ_``)&;``"MQ\``VK!``-C+``#Z&```^AP``-JP0`"L@(``K$#``*P +MK``"0_X``_`!``(^J``"L.P``D/R``/P`0`"/J@``K(/``*Q!``"L````D/^ +M``/P`0`"/J@``K,"``*P0``"0_,``_`!``(^J``"L@\``K$$``*P@``"0_X` +M`_`!``(^J``"LP(``K#```)#\P`#\`$``CZH``)/_@`#\`4``T``/!P@`# +J_P```]1>``/[```#T%X``PS.``'>K0`#[````_\```/_```#_P```_\` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/OLAND_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/OLAND_me.bin.uu new file mode 100644 index 00000000000..13f177cb143 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/OLAND_me.bin.uu @@ -0,0 +1,194 @@ +begin 644 OLAND_me.bin +M?$"``8@```#40`!_?$"``8@```!\0,`!S$``*,Q``"E\0(`!B````-A``![$ +M$``A)1```I4`__Y\00`!Q!P`)L0@`"38```50``"V4&BI,0;``+8```;S8``&L`^``3,`:'TS#T@!,0]``',```%V$`` +M&]A``!]\0(`!B````,Q!+@',02X"S$$N`\Q!+@!\0(`!B````'Q`P`&,``5Y +MS$$N`'`&GQ"``$E)``! +MS,``(]%``"31@``ET<``)MA``">60``,Q"@`+)J`___()``M?EZ`#)J`_YP2 +M+``&!NP``0KL``&:P/__V$``)X```&#$*``LFH#__WQ`@`&(````?$#``<00 +M`##,027,?04``@8U``P +M&-@`-`4H`6U\0@`!?$)``94```>&@```@``!AX```:N```'!@``%=8```7T1 +M5``0?A8`"LR```O480``E8#^B<`Z``3,.2%`Q#D``7Q`@`&(````$50`$%)D +M`"!^)@`:S4``'=1B``"5@/Y^Q"``'9H`__]\0(`!B````-PZ``"90``;)YP` +M`97```T+N``!S@$A:``$6(``"S@$EQ]1I)'Q`P`%\00`!0-0``\U!(ES-`:'\P!X``7Q"``$(S``!!B0``08H``+. +M':']SEVA_4``(````#.02%ISH$A:LW!(6O,`2%L?$"``8@```!\0,`! +M?$$``7Q!0`%\08`!?$'``1BD'^@R:``\!"```9:```A\0@`!.C```T(@``*; +M```"!"``0`0D``&```(L?@)``0ID``',``!_FD#__B3L`!#,@``+FL``"<`J +M``3$+``0?I*`"LP```',*0``SL``$,0Q``&```(^(50`,,T!(6W-02%NQ#(` +M`'\?``DD]``'!W@"0I=``">'@```@``"2H```D^```)4@``"68```EZ```)C +M@``":'\;@`\4I``(EX``'29D`/^```)Y?QN`#A2D``B7@``8)F0`_X```GE_ +M&X`,%*0`")N``!,F9`#_@``">7\;@`T4I``(FX``#B9D`/^```)Y?QN`#Q2D +M``B;@``))F0`_X```GE_&X`.%*0`")N```0F9`#_@``">12D``@F9`#_,F@` +M/!3L``B:@/V4?$-``7Q#@`%\0\`!S```"Y;```;/02%ISX$A:L_!(6O,`2%L +M@````,_U``"`````,F@`/)J`_['40`!_@````'Q`P`%\00`!P!X``144`!+` +M(@`"P"8`!)5```3`)__[?24`"<`F``!]TH`)?A+`"7TE``I\04`!?$&``Q#P`(2?\``*7P/_^S(``"]E!HJ3$ +M/P`"S\``&L`^``3,`:'TS#T@!,0]``',```%V$``'Y````!\0,`!!#P`(LR` +M``O/P:*DS```!GQ`@`&(````P!(``7Q10`K,@``+U%4``'Q`@`&(````?$#` +M`5!0`"!\T,`:51P`/WQ!0`%\08`!S(``"]#``(.5P``=Q#P`"9O```*,``-< +MV```'L0@`"$F(``!E@#__L`F`"@J9'_#S(``"\Y!(7S`)___SD$A?<0H`"3. +M@2%ZS`$A?L`J``0$+``(?L,``0LP``&;`/__S(``"\PI(7_$-0`!%W@`'W[# +M``&;@/_YV```'Y6`_&.,``5YW8,```5<(`#,```+U%T``(``!8%\0,`!4%`` +M('S0P!I\04`!?$&``=1#H`"```6!)(S__\R```O430``?$"``.:P*W#VP"MF:P``#EP```LP` +M``&```1>4=P`('V=@!K8```=SAH``)5```0%F``$5B``(,X:``";P`"0?$"` +M`8@```"50``"(=P`,E8D`"#-@2%IS<$A:LX!(6O.02%LF\#^`WQ`@`&(```` +M4=P`('V=@!K1@``KS@``+)5```-6)``@SD``+-A``"V,``6&E\#[9<0X`"^; +M@/__?$"``8@```#$'``PP"H``7V=@`$5F``"S8$EQ\XI)Q`P`(23, +M``&4P/_^QB<#Y'Q`P`',@``+S,$A?,Q!(7W$&``D?$$``7Q!0`&60``"S8$A +M>LT!(7[`-@#`P"H`!']/0`D17``!!=P``9=``!3,*2%_Q"4``1IL`#Z6P``' +M$5P``07<``$)W``!F<#__\R```N```3H%W0`%R@L`&";0``"*"P`0,[``"/8 +M0``GQ#0`+)M`__^```4`"=P``9G`___,@``+S"DA?\0E``$6;``?$5P``07< +M``&:P/_X%/P`']@``!^;P/KZQ!``)LP0`_=\0(`!B````'Q`P`%\00`!%1@` +M'U$4`"`9'``QF8``",T``!U]34`:U%8``)7`^NS$(``=F@#__X````#<.@`` +MP"8`!,S!(6E])0`*S0$A:@NX``+,02%KS$$A;)N`__V9P/UQ?$"``8@````D +M3`#_S$P#`'Q`@`&(````Q"``)L1/`P#,@``+S.$A18````#,@``+VL&BI'Q` +MP`%\0(`!B````,0,`!J8P``#V$``+X``!3+80``P?$$``7T!0`$55``!)50` +M`9E```DE$``!E0#ZP\@4`#250``%R!@`&Y6```-]E<`.E<#ZO<@@`#/2```R +MV```'L0@`"$F(``!E@#__L`F"$#,@``+SD$A?,P!(7W$*``DSH$A>LP!(7[` +M*@`$!!0`"'U!P`$H+`!`SL``(]A``"<)W``!F<#__\R```O,*2%_Q"4``19L +M`!]]0<`!FL#_^<0T`"R;0/__V```'WQ`@`&(````Q`P`$S#0``&5```#S(`` +M"]L!HJ3,0``.Q`P`$L00`!,PU```/1@``7U9P`K80``QF<#_^MA``!/0```R +M?$"``8@```#`#@$`S````Q!@`""68``%\0D`!?$*``96``N52K``@?N;`&GQ`P`%\00`! +MQ!P`$9G`__\@8U``P&-@`-`4H`>5\0@`!?$)` +M`94```>&@```@``#]8```_6```/U@``#]8```?,15``0?A8`"LU``"'480`` +ME8#^$<0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``"'48@``E8#^",0@`!.: +M`/__?$"``8@```!\0,`!?$$``7Q#@`%\0\`!41``(%/\`"!_OX`:?-#`&@0< +M``C3@``"V(```M#```+-P``"!!P``@0@``%\`D`!Q!<``\0;``-1F``@?5E` +M&L0K``/$+P`#Q#,``\0W``,)W``!4NP`('ZN@!I3=``@?S<`&G\K0!)^=D`1 +M5J@`/U0`F9@``$S``` +M`LP```V```/Q%9@``14L``@F[``!F8``,Q4P``R6```#S````H```_$$%``( +MS4```B`_8\+N``!Q#\``YN`__V````` +MS```#I9```/,```"@``#\=H```+$"P`#Q`\``\03``/$%P`#Q!L``\0?``/$ +M)P`#Q"L``Q7\`!\6L``??_/`"13P`!]_\\`)%7``'W_SP`E]B(`"?`` +M`IH```?%8P/KF@``!=^#``#/I``/C``#7=1``'\)W``!S=0#[M@4`_&,``-= +M?$"``8@```#8```>Q#P`'IO``)J0````V$``'L0\`!Z7P`"6D````(P``UG$ +M(``5?$#``<`V_P#$$``6P#`__WSU0`E]48`)?8&`'7SS@`F9@``&WX,``,^@ +M``^,``-=U$``?X````",``-=?$"``8@```!\0,`!%-P`")G```7,@```S,`` +M`-1```"`````?$$``5!4`"!\08`!?$'``7Q"``$Z,``#$B```IL```($(``( +M!"0``8```X=^`D`!"F0```_&.```.M?QN`#I>`_&"```.M?QN`#)N`_%V```.M?QN` +M#9N`_%J```.M?QN`#YN`_%>```.M?QN`#IN`_%1^`D`!@``#A\0<``3-P``` +MS````,R```#40```?$"``8@```!\0,`!)-``!C$0``;$%``/F0``",P``!+$ +M)`!^ED``.)E```3$'``$S<```,P```#,@```S,```-1```!\0(`!B````'Q` +MP`%\00`!%1@`'\T``"%1%``@F8```]1-``"`````?4U`&AD<`#'45@``E<#\ +M+L0@`!.:`/__?$"``8@```!\0,`!?$$``134`!XQ6``")-P`_Y5```29@/PC +MS1P#`(````#,@```S,```,T```!\0(`!B````,0@`"1\0,`!Q-,#`,R```#, +MP```S```(B`",``!(?!<`"I````#`'H@`C``"8WP4@`I\%H`*C``" +M^7P.P`K.@P!:D````"@X``",``!Z*#@``8P``QDH#```C``#$,P``"V```+- +MC```<<`4,17/E0``P!0Q%L]5``#`%#$8SQ4``,`0,1W%$0``)1```9D``+K` +M%#$7S]4``)`````FJ`#_%.0`!!)D``@DW``/?ES`"LS``"/.@``,@``"S244 +M`/_`"H@`?(R`"LU)``"0````*<@B;\2)```IS")PQ,T``'R-0`I]04`>%50` +M$)````#`"IP`*(@DU,`,``',R0``P`J,`"B()-;$C0``)-#__Y````#`'##0 +MS9T``,`<,,[%W0``?=7``GW1P`^5P`*I?0+`"I````#$*P`.EH`":HP``:B` +M``+-S`,`5O,```PD````,0(`!R4@`)!S8,``(```FC$"``/E(#__\0K``*, +M``$=P`Z``'^/@`K`#@``?T]`"B@\`)`3_``0*_P`_XP``"W`'#$%Q>T``!+L +M`!@F[`#_P"0``<`@``",``"#S8``$I````#`&``!S`,`#L`-___,PP`>S,,` +M8<`(!0`H#```S(\`0<`*("`HB`\%!,P``#P3,``',CP!! +MP`I`0"B(*!X$S``!S(\`0<`*0$`HB#(H!,P```3,``',CP!!P`K__RB(@'T$S``!S(\`0<`(`(#,@P!>P`@#_\R``##, +M`P!5S`,`7?4Z`"7Z"@![$%P`"?I:`"9````#$ +M#``QNT``,`D``",``"#*#@``(P``'HH.``!C``#&2@,``", +M``,0S8``$)````#$'P!@"=P`!R@@`!":``#>*!0`0(```C_`&"35Q9D``'T! +M`!Y]D,`)*!P``"@D``#`(``&E4``#"3(``&4@``%?*2`!'V)@`L)5``!!=P` +M`0H@``$4S``!!F0``9H`__8EF``_D````(```LTH%``??)3`!23,``&8P``# +M"50``9E`__R0````Q"L``HP``1W`#H``?X^`"L`.``!_3T`**#P`H!/\`!`K +M_`#_C```+<`<,07%[0``$NP`&";L`/_`)```C```@\P``!*0````@``!?8P` +M`*3,```.Q`@`-\0(`#.4@``#S8``#HP``D#$"``JE(```\V```Z,``!FQ`@` +M*Y2```+-@``.Q`@`*)2`__+-@``.C```]XP``O&```%_P`J<`"B,(YC`$``' +MS0T``,`*C``HC".9Q/$``"B,(YK$]0``*(PCF\3Y```HC".P`PDU8P` +M`$/,`P`.D````,@)/3;(#3TWE,``R,@1/3C(%3TYR!T].L@A/3O()3TU!*@` +M,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$]AQ"(``,$C``8R)8`/)5``+C(T@`H +M?24``@E4``$$S``HF0#_^\B2`#@%$`!`?0K``,`P +M```FB`#_C``"^7S!@`J6P/\4C```?95`_Q(Q2``!E(#^H0LV#``"```)HP!```,`*B`!\C(`* +MQ)4``"54`#]]%0`*D````,0G``"60/YNS`,``(```M?`##$)Q,T``"30``&9 +M```'Q`\`7<03`%[$%P!5?5$`#GS1``J9```.P!P`0'W(@`)\K<`0%=P`!GW" +MP`J,``'8P"PQ"\;M```FT`#_?P%`"HP``4]\&H`*SH,`89`````H#``!C``# +M$"@X``&,``!Z*#@``(P``QF7@/^+P#@Q`<>Y```7N``0)ZP'_Y;```/`)``` +MC```@\V```+$$``#E0#__\P``!#`.``!D````(```B.,``(/EX```\0,`!"4 +MP/[RS8,``(```LW$UP``!,P``0H@``$H&`#_?96`"7V1@!!]G8`$?)F`#Y6` +M_QHH&/\`?96`"168``A]D8`0?9V`!'R9@`Z9@/\3%50`$)9```(55``(*!@` +M_WV50`F0````P`@Q"<2-```DT``!F0``#230`/[$%P!?!50````!ET``*@>X`62?@````````(```71_&X`. +M@``!>'\;@`^```%\?QN`#(```8!_&X`-@``!A'\;@!&```&(?QN`$(```8T4 +MI``(FX``&12D``B```&='F0`_YN``!44I``(@``!G1YD`/^;@``1%*0`"(`` +M`9T>9`#_FX``#12D``B```&='F0`_YN```D4I``(@``!G1YD`/^;@``%%*0` +M"(```9T>9`#_%*0`"!YD`/\J:``\FH#^<13L``A\0T``?$.``'Q#P`"6P``' +MS```3<]!(6G/@2%JS\$A:X````#,`2%L@````,_U``#,``!9A``$PRIH`#R: +M@``$R"@`%X````#40`!_EH#_JWX"0`"$``*(P`X``LP``$&```&KS,$P2I0` +M``#(/````8 +MS\`#XL^``^,2L``"?S\``,\``^2```1/?(#``'Q`P``8T`'H$2@``94``!`& +MJ`'[GH````````"```(3P!((`(```B'(%``1@``"*,@4`!*```(OS,&BI(`` +M`C@``"FT```\@,`"J$``-,R!0`+)N```,$ +M$``0A``#8\S!HF#-`:!@A``"_008"8"$``3#S```9,@\`"Z$``,+R!``*L@< +M`"\=W``!R"0`*)7```G(-``QR#@`,,@\`"Y3=``@?[>`)T>X!53,``!BS_H` +M`)I```#()``HR"@`(SJH``*:@/__R"@`(\@H`"6:@```R"@`)8```L+`,``" +M!9C``!#<``@4X``8S=D``,@<`"+()``B'=P/_\W9``%^8D`'SED``M@840/8 +M&%$$B````-@840<;^`#PP#8(`)>```/`,`"`B````,`J``3/02%\SP$A?:0/_VP#X`!-```_Q\00``@````7Q`@`"$``-,?$#``'Q`@`"@````S(`` +M3<@\``Z7P``#TP`#YH@````$/``FS\&BI,@\`^8+_``!S\`#YIO`__O,``!- +M!#P`!<_!HJ3,`:'TA``$P\P``$>(````S```?X0``V-\0,``?$"``*````#, +M@`!-!#P`(L_!HJ2$``3#S```2(@```#,``!_A``#;GQ`P`!\0(``H````,R` +M`$T$/``CS\&BI,P!H?.$``3#S```28@```#,``!_@````'Q`P`"`````?$#` +M`,`2``%\44`'@````-15``#,0`!ER#@`+<@\`"[`->``P#(`!'^W@`9_]\`& +M([@0`"/\$`#/@2%4S\$A5`````S8`#XGQ`P`"````` +MS$P#X!R,___430``?$"``*````#,@`!-R!0`(S%8``25@/__R!0`(\P``%O, +M02&`($R``,S!(8$4T``?S$$A@LQ!(8.5`/N*S$$AA,@4`".90/__R!0`(X`` +M``%\0(``P!8`!"%4(4#,50``R!@`!(````#,``/@?$#``!C0`#C`%@"`E0`` +M`\`J``1\U,`'S,$A?,Q!(7W,02%^?$&``!3\`!\=F/__.;```R*@(7^;```# +M09P`!00<`$"9P```"=P``F0#__,@<``B$ +M``-KS```5,@8`!6```".'9@``AR,``+($``=F,``#L@4`$F9```$R!P`!X0` +M`VO,``!3R!@`%93```,8E`'H!50`!B`0``%]%0`#@```CGV1@`:90/_XR!P` +M!\W``$#,``!`@```S,P``&[`#H"`S```9P30@(#,``!HS0`#\$ +M``-KS```4\@,`"_,@`!`S$``0,Q``$#,0`!`?,3``,S``$#40`!`?$"``*`` +M```$*``!F4#_]<@<``?-P`!`S```0(```1O,``!N?$#``,@0`$>9```+R!0` +M1)E```3(&``)S8``0,P``$"```%%S(``0'Q`P`#($`!'E0#_]\@4`$690``$ +MR!@`"LV``$#,``!`@``!1=@`"$!\0,``R!``1YD`__P`````S(``0,S``$#4 +M0`!`?$"``*`````$*``!R!``1M@`!T#-``!`A``!7,T``$#(#`!#E,``"L@4 +M`$B```%5!!```\@0`$;8``?`S0``0(0``5S-``!`R!0`2)U```#,``!JR"@` +M%AZH``&:@``#P"D``8@```#`+`%6SH``7-@`",#.P`!`B````,P``$`9P/]>`````-```_J` +M````?$#``,R``$"`````U$``0'Q`P`!\00``?$.``'Q#P``$'``"SX``0L_` +M`$+-P`!"!!P`!,S``$+-``!"S<``0@0<```$(``!?`)``,@4``/(&``#49@` +M('U90"?(*``#R"P``\@P``/(-``#4NP`('ZN@"=3=``@?S<`)W\K0"%^=D`@ +M5J@`/UT`G?65`(%58`"#, +M``!;S78``,VV``#((`!!F@```,@@`$&````!?$"``'Q`P`!\00``S,`#_LT` +M`__,P`!"S0``0A44`!\9&`#P)UP``7UV``:9@``%?5Y`!LP``$*```-ES``` +M3168``$5+``(F8``,1[L``&6```$%3``#(```V7,``!"!!0`!,U``$(?,``! +M("@``00X``0$/```R!0``\@8``/('``#R"```WU=0`U]H<`-?5U`!Q80`!\5 +MG``??1T`!GT70`9^DH`&FT``$@NX``2;P/_R"_P``<@,`_Z:@``)R!`#_YL` +M`0;,``!-!!0`!,S``$+-``!"@``"2A``#:,P``%W((``??$#``,`V_P#( +M$``AP#`__WSU0`9]48`&?8&`"IF```A\\X`&XX,``,^@`$^$``-HS```7H`` +M``#40`!_@``#9``!\0@``?$)``'Q!@`!]Y<`&?>*`$9J`_-A!K``% +MFL````KL``$T`(@+R`",#`P`G`8T`'P'_`"`"+P`H`:\`*0%\`"H!H0`K +M`9$`+P&J`#(!TP`T`T4`-0&``#D!_``\`Q<`/@&_`#\!P0!!`I@`0@*_`$," +MR0!$`M8`2@+D`%4#.0!6`T``8`",`&$`L@!B`-H`8P#$`&0`Q`!E`,0`9@#$ +M`&<`Q`!H`.<`:0#P`&H!0`!K`0X`;`$.`&T!#@!N`0X`;P$.`'`!$P!S`/P` +M=`#\`'4!9P![`U(````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +9!0````4````%````!0````4````%````!0`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_ce.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_ce.bin.uu new file mode 100644 index 00000000000..42fe4299691 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_ce.bin.uu @@ -0,0 +1,194 @@ +begin 644 PITCAIRN_ce.bin +M?$"``8@```#40`!_?$"``8@```#$(``+Q@P`!93``"0D4``/,10``I5```3, +M0``DS$``)8`````Q%``#E4`!.\Q``";,0``G@````,0@``O,(``%?$$``5!4 +M`"!\08`!!B0``@8U``P&-@`-`4H`$1\0@`!?$)``94` +M``>&@```@``!4(```5"```%0@``!4(```%(15``0?A8`"LU``!'480``E8#_ +MLL0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``!'48@``E8#_J<0@``Z:`/__ +M?$"``8@```!\0,`!%-``'C$4``*50`#K&-0`,!C0`>@8_``T),P`#P3H`&A\ +M08`!?$'``93``!*&@```@``` +M`!J```!_4=P`('V=@!J90``#Q:(``(```'_)H@``@```?\6A``"50``%!9@` +M`<6E``!29``@?B8`&@4H`(-\08`!?$'``94```>&@```@``!4(```5"```%0 +M@``!4(```)/8```1SAD``)5```0%F``!5B``(,X9``"7P/]QQ#DA0'Q`@`&( +M````4=P`('V=@!K8```1SAH``)5```0%F``$5B``(,X:``";P/^]?$"``8@` +M``#8``/VV``#]=@``_38``/SV``#\M@``_'8``/PV``#[]@``^[,0`!_S$`` +M?\Q``']\0,`!S,```=1``'^`````?$#``5!0`"",``#+?-#`&L0@``O$U@`` +M?$.``<0D`!.:```)V&0#],9K`_&:@/__QFL#[@:H``'.I`/NS60#Z]@D`_29 +M0``)WX,``,^@``Z,``#/U$``?YH`_SS&

?16`#IF```_80``IR!``'7U1@!)]C<`/F<#__=@``"E0X``! +M?A9`#II```1]8H`2TH``(X````#0```C@````-B``"G$/`!_S```(-A``"C$ +M#``V$``'8````#,```@V$``*,0, +M`!R8P/__V```*-```![0```?V$``'7Q!``&`````?$#``7Q!``$5&``?S0`` +M$5$4`""9@``#U$T``(````!]34`:&1P`,=16``#$(``.E<#^R,0@``Z:`/__ +M@````'Q`P`%\08`!%-``'C$0``(DU`#_E0#^O\V4`P"`````Q"``$WQ`P`'$ +MTP,`S```$`(0`]@"'`/D`B`$"`(D!%P!]`3P`?@%$`'\!+``B`*X`BP$B +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````"`````@````(````"`````@````(````"`````@````(````"```` +M`@````(````"`````@````(````"`````@````(````"`````@````(````" +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +:``(````"`````@````(````"`````@````(` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_mc.bin.uu new file mode 100644 index 00000000000..2eaedb6b2dd --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_mc.bin.uu @@ -0,0 +1,694 @@ +begin 644 PITCAIRN_mc.bin +M``/HX``"O@$```('``/_```#_P```J`.``'`&0`#Z````^@0``/H(``#Z#`` +M`V`@``-A2``",;@``TEL``-("@`#KPH``K0$``)O]```^BT``K0/``)/%``` +M^@H``ZB,``#"`0`#0"0``K1```*U#P`#2J8``D1!``/P`@`"294``VJF``-* +M40`#0"0``K@"``*Y_@`"1)0``DB!``.H@``"9$@``VI1``-`)@`"OX```KP$ +M``))^0`#\$(``_0```'`00`"OX```TA4``*X#P`"N?```D$8``)"*0`#:%0` +M`TMI``/`C``"9$P``VMI``)$2``#:VD``F$?``)B+``#:%0``BP%``-+3``# +M_P```V%$``-+'``#0"H``K3\``-A0``"0S0``F$>``-K'``"2JX``_!&``-) +MU0`"O!```DS'``/P0@`"O"T``C)S``-`)``"M$```K7P``-*I@`"1$$``_`" +M``)IE0`#:J8``T````/_```#^`$``\1```/$40`"QD4``@````-`$``#_P`` +M`_\```/H(``#Z#```V`0``"1Y0``D@T``_@#``(POP`",;(``T@(``*TGP`" +M0`0``V@(``-(P``#2,8``K3\``*U#P`"010``DF4``)")0`"2J4``D,U``)+ +MM0`#:,```VC&``-(```#2`4``KL_``*\OP`"O^\``)(E``"*)@``@BH``+HH +M``"J+``"01L``KO[``)`#``#:````KS^``)%7P`"1WP``V@%``-($``#2=T` +M`KOQ``*\`@``BBD``*HK``)!&P`"81P``V@0``)%6P`"95P``VG=``-`#0`# +M_P```_\```.A3```B?\``K,"``)#-``#HS```)G^``*S!``"0S0``Z,R``"9 +M_0`#0"D``T````*\(```N<<``D(L``/P!P`"L````((Q``(Z,P`#Z````('E +M``/T```!PEP``T````*\(```\C$``D,\``/P!0`".C,``^@```"!Y0`#]``` +M`<)<``-((0`"L\$``D=S``-H(0`#:HD``T@E``*SP0`"1W,``V@E``-JC0`# +M2"D``TEP``-`$@`"OP<``D`/``.````#``X``Z^(``-)U@`"O!```DS+``/P +M00`"P`\``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H+0`#P00``\$5 +M``-IZ``#:>P``TK"``*_P``"2(\``VK"``-JQ@`#Z````^C0``(NE@`#:.0` +M`\'>``(NE@`#:00``^A```*]```",@(``KT!``(R`@`#0"P``_\```*T`@`" +M1`0``*()``-)U@`"M1```D1;``.D1@``H@L``J!.``/P`P`",[<``_0```'! +M!0`#]````=)]``*\```",CT``T`.``#R,@`#Z/```Z"V``-)U0``^@0``K$/ +M``)"%P`"I2```_`!``#Z,@`"0QL``J4C``/P`0``\@0``T````-`+@`"MA`` +M`K0,```J,@`"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`!``/HP``` +MX@,``T`(``*T````>@0``J`D``/P00`"L@@``J#^``/P00`"L@0``K0_``)" +M)```DAH``TJ4``/_```#88```T````/_```"M$```D0$``/P`P`#Z````((Q +M``(BX``#0````_\```*T0``"1!0``_`"``#R,0`"(N```T````/_```"M$`` +M`F$0``)$%``#\`$``BSW``-*E``#_P```V&$``-````#_P```K0"``)$)``# +M\`,``^@```"",0`"(PP``T````/_```"M`(``D0T``/P`@``\C$``B,,``-* +ME``#_P```V&(``(QL@`#0````_\```/_```"1`X``_`#``/H````@C$``B0; +M``(QL@`#0````_\```/_```"1!X``_`"``#R,0`")!L``BTN``-*E``#_P`` +M`V&,``-````#_P```K0"``)$0``#\`L``^@```"",0`")@<``T`L``/_```" +MM"```D1```/P`P`#Z````((Q``(Q*0`#2I0``_\```-AD``#0````_\```*T +M!``"1$```_`#``/H````@C$``B?3``-*E``#_P```V&4``-````#_P```K00 +M``)$0``#\`P``^@```"",0`"*'H```'_``/_```#_P```J0.``/P!```\@`` +M`BAZ``/H````@@```TJ4``/_```#89@``T````/_```"M"```D1```/P`P`# +MZ````((Q``(J"@`#2I0``_\```-AG````@,``_\```*T`0`"1`0``_`$``/H +M````@C$``\'^``(JO````@,``_\```*T`@`"1`0``_`$``/H````@C$``^CP +M``(JO``#0````_\```/_```"1"X``_`#``/H````@C$``C?1``-````#_P`` +M`K00``)$)``#\`,``^@```"",0`"./4``_@#``-*E``#_P```V%@``-````# +M_P```K0"``)$00`#\`H``/(Q``(F!P`#0"P``_\```*T(``"1$```_`"``#R +M,0`",2D``TJ4``/_```#860``T````/_```"M`0``D1!``/P`@``\C$``B?3 +M``-*E``#_P```V%H``-````#_P```K00``)$00`#\`L``/(Q``(H>@```?\` +M`_\```/_```"I`X``_`$``#R```"*'H``^@```""```#2I0``_\```-A;``# +M0````_\```*T(``"1$$``_`"``#R,0`"*@H``TJ4``/_```#87````(#``/_ +M```"M`0``D0$``/P`P``\C$``\'^``(JO````@,``_\```*T"``"1`0``_`# +M``#R,0`#Z/```BJ\``-````#_P```_\```)$/@`#\`(``/(Q``(WT0`#0``` +M`_\```*T$``"1#0``_`"``#R,0`"./4``TJ4``/_```#870``_@#``-````# +M_P```K0(``)@`0`"1`0``_`,``-("``#_P```K1```)@!``#:`@``TF8``*T +M_0`"010``VF8``/H,``#P2X``V@P``(Q1``#Z````^@0``/H,``"L@,``V@P +M``-````#_P```K6```)A$``"114``_`!``(W,``#2I0``_\```-A>``"O`$` +M`C(]```",@`#_P```_\```*A#@`#\`(``^@```""!P`"+2X``T@```-(!0`` +M"B8```(J```2)0``*BP``#HH``/_```#:````V@%``-($``#2=T```HI```J +M*P`#_P```V@0``-IW0`#27$``K(!``/H,``#P08``\$7``-H,``",40``^@` +M``/H$``"L@,``K,```-H,````@L``_\```/_```"H`X``@*!``/T```!P``` +M``'E``-`$@`#0!4```H-``*@#@`#\`(``_0```'"G``"P1X``(H-``)KN@`" +M95L``L9N``/P00`#!FX``V`5``*R#P`"1$(``J44``/P!P`#Z*```^BP``-@ +M$@`#Z````('E``/T```!P&L``T`L``/_```"M"```D!```/P`@`#]````<*H +M``/H````@C$``C$I``#R,0`",2D``^@```"",0`",%X``/(Q``(P7@`#23T` +M`TC```*V"``"1F0``_`"``*U,``"8B4``VC```-HQ``#2QT``T`H``*\$``" +MOP0``DS```/P!0`"9W\``VL=``(Q1``"9WX``VL=``-`(``#_P```_\```+" +M+@`#\$0``L,^``/P0@`"LO\``K/_``-@(``",;(``TE(``-`*@`"M#\``K6` +M``*V0``"1F@``_!%``)#-``"8S4``VE(``)#-``#:4@``^@```/H$``#Z"`` +M`^@P``-DI``#9.0``_0```'````#0`0``&HQ``/H@``#Z)```^B@``/HL``" +MH-X``_`#``-DJ@`#]````_!!``-DZ@``8>D``J#>``/P`P`#Z$```_0```/P +M00`#A.H``]A```/>@``_@#``/4G@`#^P```P_^``("]P``(<,``J#> +M``/P`P``8<(``_0```/P00``8<$``K\(``/<0``#V,```_@#``/4G@`#^P`` +M`P_^``(#!@`#^`,``^P````",@``:C$``_\```*@#@`#\`$``^P```-).``" +MH-X``_!!``-).``"N/X``D(H``-I.``#2=```K0$``)A%``"L@$``K,2``*@ +MW@`#\$$``K,1``-H,``#27$``KCO``*Y!``#P08``F%Y``)#.``#:#```T@) +M``*X_0`"1$@``V@)``(M"``#2:```K01``/!)``"L0\``VF@``-*1``"M/X` +M`F$>``-J1``"010``VI$``*@W@`#\`,``T)A``/T```#\$$``T)=``/_```# +M_P```^A@``-II0`#:&L``KH,``*XP``#W($``]BA``*P^``"L0<``^@@``/H +M,``#_@```]0?``-H:P`#Z/```B/)``(CL@`"(]X``J'^``/P00`#8GH``T)X +M``/_```#_P```J"```'#9P`"H)$``<-G``*@H@`!PV<``J"S``'#9P`"S_X` +M`KP,``*A_``#\$(``_0```'#40``^``-">``# +M_P```_\```*@@``!PWT``J"1``'#?0`"H*(``<-]``*@LP`!PWT``L_^``*\ +M#``"H?P``_!"``/T```!PVH``&'.``#YQ0`#_P```J7/``'#C0`"I?P``<.( +M``/H\``#Z,```_0```'#D``##,\``ZS```/H\``#]````<.0``,/_``#K_`` +M`^C```(CR0`#P?P``B.R``-).``"H-X``_!!``-).``#_P```F(N``-I.``# +M2=```K3[``)!%``"L@$``K,2``*@W@`#\$$``K,1``-H,``#27$``KCO``*Y +M^P`#P08``D%Y``)#.``#:#```T@)``*X_0`"1$@``V@)``*P&``"(_T``BTN +M``/L```#P0\``\$?``/!+P`#P3\``J#>``/P!0`#9+```V2T``-DN``#]``` +M`_!#``-D\``#9/0``V3X``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``# +M:,@``^P```/!#P`#P1\``\$O``/!/P`"H-X``_`$``-DK``#9+P``_0```/P +M0@`#9.P``V3\``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P` +M``*P$``"(_T``TH<``(D#0`#P8P``TH@``(D#0`#C,8``FB,``-*)``")`T` +M`\&<``-**``")`T``XS&``)IG``#2BP``B0-``/!K``#2C```B0-``.,Q@`" +M:JP``THT``(D#0`#P;P``THX``(D#0`#C,8``FN\``/L```#:&L``KD(``*X +MP``#W(```]B0``/H$``#Z"```^@P``/^```#U!X``VAK``/!CP`"OQ```BT$ +M``/!^``#[````^C```.'/``#IW8``X8L``.F:``#A1P``Z5:``.$#``#I$P` +M`FS'``)LQ@`";,4``FS$``/L```#0"0``&HQ``/_```#H`8``J$.``/P`0`` +M@?D``TFA``-)I``"NT```KJ_``)%I0`"H-X``_`#``)#HP`#]````_!!``)C +MLP`#::0``VFA``(R8``#Z````^@@``/H,``"H-X``_`#```)^P`#]````_!! +M```)^@`"N,```VAK``/8```#W(```]0>``*_"``"+00``X#@``"!]@``@?4` +M`^@```"!]```@?,``/'R``-(5``"H-X``_`#``.$Z``#]````_!!``.$Z@`" +M8B0``VA4``-)=0`#B.8``F!H``/!%P`#P2X``\$^``*@W@`#\`$``X,P``-H +M,``#2%0``J#>``/P`P`#A.@``_0```/P00`#A.H``\!$``)")``#:%0``&(+ +M``*_`@`"+00``J#.``/P`@`#]````@2#``(NJ``#Z'```X3F``)&2P`"H&0` +M`_!*``-)T@`#Z&```XJR``.JJ@`"H:X``_`"``,!K@`")?<``_0```'%(@`" +MOP@``D_Y``.O]``#B[(``ZN\``(E.P`#]````<4B``-`#``#_P```K\(``)/ +M\``#\$(``_0```'$E``"OP```KL!``(E.P```@0``_\```/_```"H`X``_!" +M``/T```!Q2(``/'T``#Q\P`"H-X``_`#``!Y^``#]````_!!``!Y]P`#C>(` +M`]S0``/8\``#B>8``FF>``#QXP``0?D``^C0``./X``#P:@``XSM``#AYP`` +MXC```BX1``*W`0``0?D``^B@``#1XP`"H'X``_`!``.H@``##]\``\'9``/! +MJ``#C.T``.'G``#B,``"+A$``BY2``/!!``#P28``V)P``*_`0`#0!$``XC@ +M``*@_@`#\`0``D1(``/P`@`#]````@4(``*W`0``0?D``_\```*@?@`#\`$` +M`ZB```/HT``#C^```\&H``.,[0``X><``.(P``(N$0`"+E(``T)P``.,ZP`# +MC.H``^CP``+(0``#J(```"H)``+*8@`#JJ```J9>``($Y0``:C$``/()``/! +M6``#P7H``V)Q``/T```"!)\``J%>``/P#@``:C$``\&1``/!LP`"H-X``_`# +M``-A+@`#]````_!!``-A,@`"P($``Z@```+"HP`#JB```X50``"J"0`#@>`` +M`P"$``/P)``"H80``_`!``+$00`#!$X``\%4``,"I@`#\"0``J&F``/P`0`" +MQF$``P9N``/!=@`#U%X``F`"``($]P``:C$``K\"``(M!``#27$``X'D``/! +M!@`#HFP``J`N``(%(@`"87$``\$N``/!/@`"H-X``_`!``.#,``#AF```_!' +M``-H,``#C^T``BT$``./[0`"+00``X_M``(M!``#C^T``BT$``-)=0`#P2X` +M`\$&``/!%P`#P3X``J#>``/P`0`#@S```V@P```!Y0`#_P```_\```*E#@`# +M\$@``T`1``*@W@`#\`,``F9N``/T```#\$$``F=^``-@$0`#Z````('E``/L +M```"H/X``<5'``*P#P`"L0\``K(/``*S#P`"H-X``_`#``-C*``#]````_!! +M``-C:``",40``TI```!!\@``2?8``%'U``*\,P`"1`P``D4<``)D10`"1BP` +M`D<\``)F9P`"9$8``J%.``/P`0`"M`$``J".``/P!0`"I$D``_!#``*D2P`# +M\$$``/'T``"A]@`"O,P``D0,``)%'``"1BP``D<\``)D10`"9$8``F1'``*A +M3@`#\`$``K0!``*@C@`#\`4``J1*``/P0P`"I$L``_!!``#Q\P``H?4``^A` +M``"A\@```?0``!'S``*Q#P`"LP4``J7^``(%G0`"H/X``_!!``/H\``"H`X` +M`_`!``+/_@`"L1```J`N``/P`0`"S_$``K.0``*F\P`#\$(``/'E``/L```" +M0P(``_!#``(EW0`#]````<5'``*T$0`##_0``J#>``/P`P``^?$``_0$``/P +M`0``^?```T,I``*@W@`#\$$``T-I``*_=P`");P``^P```-(Y0`"H-X``_!! +M``-)!0`"N!$``J`.``/P`0`"Q$@``DE!``*DDP`#\`$``/'T``*@+@`#\`$` +M`L58``))40`"I),``_`!``#Q\P`"H-X``_`#``-HY0`#]````_!!``-I!0`" +M0`(``J`.``(%1P`"L0(``B7W``/L```"H?X``_!!``/L```#H?8``X_V``.@ +M]@`"H0X``_`'``*\"0`"H$P``_!!``*\#P`#P4P``\%<``,`#@`"H1X``_`' +M``*\"0`"H&P``_!!``*\#P`#P6P``\%\``,!'@`"H-X``_`#``-C*0`#]``` +M`_!!``-C:0`"8@$``@7"``/L```#0RD``J#>``/P00`#0VD``J`.``/P!0`" +MM`\``DS^``/P`0`"M`D``\%4``*@+@`#\`8``K8/``.L]@`"3,X``_`!``*V +M"0`#P78``J#>``/P`P`#8RD``_0```/P00`#8VD``^P```-(Y0`"H-X``_!! +M``-)!0`"L!$``L1```+%4``"H-X``_`#``-HY0`#]````_!!``-I!0`#`1X` +M`@7[``/L````:C$``^@```(N@@``\>\``^@```"![@`#0`P``T`M``*X$``" +MN0@``DH8``.JI@`"2TD``ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`!``*S +M!@`#0"T```H$``*P0``"0$```_!!``/H,``"01X``_`!``/H,```F>T``BT( +M``*X$``"N?X``J#>``/P"0`#2"$``KH/``)&:@`"1WD``F9H``-H(0`#:HD` +M`_0```/P1P`#2"4``KH/``)&:@`"1WD``F9H``-H)0`#:HT``C`H``*_`P`" +M+_0``K]D``(M!```:C$``_\```/_```"H-X``_`#``*[```#]````_!!``*[ +M0```V>```\$.``*Q$0`"LA```VI$``*Q$``#Z"```VI$``*P_P`"L?\``K+] +M``*S_P`#:&```TI@``*_]P`"L1,``D`/``)@#@`#:F```#'^```Y_0`"O`@` +M`K_^``.&:@`"8B8``J1^``/P`0`"LP0``D`/``)@#``#:F```X_A``(M!``# +M:&L``_\```/^````8B\``%HN``/_```#V,$``]RQ``./XP`"+00``]`?``., +M[P`#C^0``F_^``)``0`"0B,``D`"``),P``#^P$``]`?``,/_@`"!G@``J#> +M``/P`P`#2"$``_0```/P00`#2"4``\#,``(&I``#C.8``L9L``/P00`"QWX` +M`J#>``/P!``#:"$``VJ)``/T```#\$(``V@E``-JC0`"I7X``_`"``/T```! +MQDH``T`1``*P"```\>4``J#>``/P`P`"9F```_0```/P00`"9W```V`1``/T +M```"!]$``X#A``.!!@`"81X``X+G``-J1``#@08``^@@``-J1``","@``T`L +M``!:'0`"M`0``^CP``)$0``#\`$``K\!``*DO@`#\`$``K\$``(O]```\AD` +M`/(7``(R6@`","@```HM```1_@``&?T``K`"``*@W@`#\$$``K`$``."*@`" +MI#X``_`!``*S!``#@18``F`!``*Q,P`#:F```T`*``*P`0`"L0(``K(```*S +M`0`"H"L``_`"``/H(``#P3L``VIH``/!#@`"L@D``D`)``/P`0`#Z"```K`3 +M``*Q`@`#@B8``^@P``-J<``#0"T``&($```2&@`"OT```D]/``/P`P`"H,X` +M`_`!``*R"``"L"$``K$"``*S`0`#:G0```H=``*P`0`#_P```J0>``/P!0`" +ML00``K(```*S`@`#]`0``_`#``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`0`"L0(``K,$``-J?````>X``_\```/_```"P`X``('N``(O[P```AD``T`* +M``-`#0`"H`X``_`%``*P`0`"0`4``X`&``/T!``#\`,``K`$``)`"0`#@`(` +M`K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`"LP$``VID``(NO0`" +M+LH```'O``/_```#_P```J`.``/P3@`#0"P``KP$``/``/P +M`0`#Z/```]CP``*\"0`"OS\``DL?``(MBP`#Z/```/GO```![@`#_P```_\` +M``+`#@``@>X```GM``-`+@`#_P```J`!``('2@`"L`$``D$(``/P!0```C(` +M`_\```/_```"H`X``@=*``-*=```>AH``_\```/_```#P2\``VIT``(O[P`` +M`AD``T`*``-`#0`"H`X``_`%``*P!``"0`4``X`"``/T!``#\`(``K`0``)` +M"0`"L4,``F@!``-*9``"M(```!'@``)`!``"8`@``Z(B``/!/@`#:F0``BZ] +M``(NR@``0@,``K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```''>@`#0`X` +M`K`0``/_```"00D``J`0``('>@```AD``_\```/_```"P`X``((9``*Q`@`" +MI`$``@<```!!X````<,``_\```/_```#V(```]P```*_"0`"L````]P!``*P +MP``#V`$``BZT```![@`#_P```_\```+`#@``@>X``B_O``-`"@`"L$```_\` +M``)`"0`#H`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`"LP$` +M`VID``(NO0`"+LH``T`E``!"`P`"L"```D`%``/P2``"L`(``J#>``/P00`# +M@`(``D`(``/P`@`#]````<>_``-`+@`#_P```K`(``)!"``"H!```@>_``*P +M@``"00@``_`%```",@`#_P```_\```*@#@`"![\```(7``/_```#_P```^@0 +M``"*%P`"I`X``@``/P`P`"NV(``_0```/P00`"NV@``_\```/_ +M````V>P``C"E``/H```"+H(``KL"``#:,``#Z````K%@``/H(``#Z#```VF@ +M``/H```"L1```^@@``/H,``#:D0``C`H``*_`@`"+_0``K#_``*Q_P`"LOT` +M`K/_``-H8```"BT``!'^```9_0`"L`H``J#>``/P00`"L`P``X$6``)@`0`# +M@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+00``VAK``/_ +M```#_@```C`>``-*8```,?X``#G]``*T]@`"M0,``X9J``)B)@`"I'X``_`! +M``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``#:F@` +M`K"```*R"0`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`" +ML0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`@`"L0(``K,$``-J?``",EH``^AP``-*9``"M(```D`$``/H(``#Z#```VID +M``-*9``"M(```!'L``)`!``"M`,``F`$``*S$``#:F0``BZ]``-*9``"M`@` +M`D1```)G=``"I7X``@AX``/H```"+H(``J#>``/P`P`#2"(``_0```/P00`# +M2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H(@`#:HH``_0```/P +M0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R#T``T`2``#QY0`"OP0``J#> +M``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R'@``C`>``/L````:C$` +M`/'O``/H````@@8``T`(``-`+0`"N$```KD(``)*"``#JJH``DM)``.KM``" +MLP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!```/P +M00`#Z#```D$>``/P`0`#Z#```)H%```AY0`#Z%```_\```"B#```J>4``&HQ +M``/_```#_P```J#>``/P`P``6<(``_0```/P0P``6<$``_\```/_````V>`` +M`T`L``!:'0`"M`0``^CP``)$0``#\`$``K\!``)+O@`"H+X``_`#``(O)0`# +M]```````D`$``)@"``#HB(``K,!``-J9``" +M+KT``B[*```![P`#_P```_\```*@#@`#\$X``T`L``*\!``#W,```K_```*@ +MW@`#\`$``K^```/8\``#C.0``K\_``)+'P`"+8L``^CP``#Y[P```@8``_\` +M``/_```"P`X``((&``!:'0``>A<``K@(``)*O@`"H*X``AH``_\```/_```#P2\``VIT``(O[P```A@``T`*``-`#0`"H`X` +M`_`%``*P"``"0`4``X````/T!``#\`,``K`@``)`"0`#H````K%#``)H`0`# +M2F0``K2````1X``"0`0``F`(``.B(@`"LP$``VID``(NO0`"+LH``$(#``*P +M`0`"H-X``_!!``.``@`"0`@``_`"``/T```!R;4``T`*``/_```"L$```D$( +M``*@$``"";4```(8``/_```#_P```L`.``""&``"L0(``J0!``()#````>`` +M`$'#``/_```#_P```]@```/<@``"OP@``K#```/8`0`"L````]P!``(NM``` +M`@8``_\```/_```"P`X``((&``(O[P`#0`H``K"```/_```"0`D``Z`$``*Q +M`P`":`$``TID``*T@```$>```D`$``)@"``#HB(``K,!``*Q```#:F0``BZ] +M``(NR@``0@,``K`!``*@W@`#\$$``X`"``)`"``#\`(``_0```')]P`#0"X` +M`_\```*P"``"00@``J`0``()]P`"L(```D$(``/P!0```C(``_\```/_```" +MH`X``@GW```"%P`#_P```_\```/H$```BA<``J0.``()3P``8<,``%G@``/_ +M```#W,```]BP``*_"``"L,```]@!``*P```#W`$``C)@``-H:P``$=8``K/` +M``/HT``#8G0``BVS``(P'@`#[````&HQ``/_```#_P```J#>``/P`P`"NU,` +M`_0```/P00`"NUL``_\```/_````V>P``T`0``*['P`#2"D``J#>``/P00`# +M2"T``D`+``.O`@`#C/8``FS/``./]@`#2>@``J-,``/P!``#!$P``P5?``/T +M```#\$(``P3$``,%]0`#P00``\$5``*@W@`#\`0``V@I``-IZ``#]````_!" +M``-H+0`#:>P``^@```(NE@`#Z````K%```/H(``#Z#```VI$``(P*``"OP(` +M`B\E```*+0``$?X``!G]``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`" +ML80``F(A``*D/@`#\`$``K,$``*Q&``#:F```T`*``*P`0`"L0(``K(*``/H +M,``#:F@``K"```*R"``"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP +M``*P(0`"L0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP` +M`_\```*P`@`"L0(``K,$``-J?``",EH``^AP``(O[P`#2F0``K2````1[``" +M0`0``K0#``)@!``"LQ```VID``(NO0`#2F0``K0(``)$0``"9W0``J5^``(* +MN0`#Z````BZ6``*@W@`#\`0``T@J``-)Z``#]````_!"``-(+@`#2>P``KP1 +M``*_$``"R9\``LB,``/P00`#Z(```\$(``/!&0`"H-X``_`$``-H*@`#:>@` +M`_0```/P0@`#:"X``VGL``-*P``"OP<``DW>``/P`0`"OS@``J&.``/P0P`" +M8`\``VK```-JQ``"NP$``-HP``/H<``"3_```_`#``*[_P`"H(L``_`"``/T +M```!RG$``T`2``#QY0`"OR```J#>``/P`P`":J\``_0```/P00`":[\``V`2 +M``(P*``"+^\``^P```!J,0`#Z````(',``*@W@`#\`,``%G"``/T```#\$$` +M`%G!``*P?P`"H?X``_!!``)+L```V>```C):``(P*```"BT``!'^```9_0`" +ML`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&```)B(0`"I#X``_`!``*S +M!``#0!4``K$(``*V\``"1$8``F$4``-J8``"L`$``K$"``*R```"LP(``VIH +M``*R"``"L!,``K$"``.")@`#Z#```VIP```2&@`"L"$``K$"``*S`0`#:G0` +M`K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P`0`"L0(``K,$``-J?``" +MO`0``]S```!YX``"O`@``KL8``/8\``"+8L```',``-`)0`"OQ```L`.``"! +MS``"3U\``_`#``(KQ``#]````````G#``-`)@`" +MLA```]@```/<$``"OP@``K#```/8`0`"L````]P!``)"*0`#\$4``Z_P``*@ +MS@`#\`(``_L```/[`0`#T)X``_L```*E+@`#\`$``_L```/4GP`#^P$``J4N +M``/P`0`#^P$``P_^``(+.```````_\```/``/L```"O!$` +M`J#>``/P!``#2,P``TC1``/T```#\$(``TCL``-(\0`"*Z\``J#>``/P!``# +M:,P``VC1``/T```#\$(``VCL``-H\0`"H-X``_`$``-(U``#2-D``_0```/P +M0@`#2/0``TCY``(KKP`"H-X``_`$``-HU``#:-D``_0```/P0@`#:/0``VCY +M``*@W@`#\`,``TC<``/T```#\$$``TC\``*@_@`#\`0``L`,``+!'``#]``` +M`_!"``,`#``#`1P``J#>``/P`P`#:-P``_0```/P00`#:/P``^P```*@_@`# +M\`H``L`,``+!'``"PBP``L,\``+$3``"Q5P``L9L``+'?``#]````_!(``,` +M#``#`1P``P(L``,#/``#!$P``P5<``,&;``#!WP``^P```*P?P`"L?\``K+_ +M``*S_P`#:&```VAK```)U@`#Z````Z`#``/<```#V!```T`Q``*_`P`"O`(` +M`J;\``/P00`#P0<``J#\``/P00`#P08``J#^``/P00`#P04``J'^``/P00`# +MP00``\$0``/!(``#P3```_X```/4'@`#:&L``_L```,/_@`""](``T`U``*_ +M`P`#_P```J;\``/P00`#P0<``J#\``/P00`#P08``J#^``/P00`#P04``J'^ +M``/P00`#P00``\$0``/!(``#P3```_X```/4'@`#:&L``_L```,/_@`""^H` +M`T`X``-`/0`#_P```VJ$``-J@0`#[````TA5``/_```"M\```VA5``-H:P`# +M2`H``K]_``)H^``"LN\``Z"!``*_PP`"0`\``T`E``*S_P`"L?\``D]>``/P +M`@`"N?,``D(I``*\`@`"3%P``_`!``*S^P`#:&```TA```./\@`"O/L``D$< +M``)A'P`#:$```VAK``-)?``"M`0``F$4``-I?``#2I0``_\```-A?``#:&L` +M`C%$``/_```#_@```_\```-!20`#_P```_\```-(9``#B$0``ZB```/H\``# +MW/```KQ```+,R``#V,```]0>``(R9@`#84D``TAD``*T$``"1B0``_`"``/T +M```!S)D``TAD``-(-@`"M$```K4$``)$0``"15@``F1%``',60`"M#P``D1` +M``/P0P`".KT``_0```',*P`#0!0``_\```/_```"PSX``_!!``,#/@`#8!0` +M`K#_``*Q_P`"LO\``K/_``-JD``#^`,``TAD``.,Z@``\@@``DP,``',=0`# +M2#0``KP$``),P``"#&0``.((``-)/0`"OQ```D1/``/P!``"O_\``BT$``*_ +M4``"+00``K\(``(M!``#]``````#:"T``VGM``-(R``"N/L``D(H``-HR``#2)@``K@@``)@"``# +M2+$``VB8``)D2``#:+$``\$.``/!'@`#P2X``\$^``-C,``#8W```V,T``-C +M=``#8S@``V-X``/T```!S/```T@(``*X]P`"0`@``V@(``-(*``"N-\``D,X +M``-(+0`#:"@``VGH``)'>``#:"T``VGM``-(R``"N`0``F(H``-HR``#2)@` +M`KC?``)`"``#2+$``VB8``)$2``#:+$``K`#``/!$``#P2```\$P``-C,``# +M8W```V,T``-C=``#8S@``V-X``-)?``"M/L``D$4``-I?``#:&L``_0```', +M*P`#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(``VC*``)H(0`#:,H``\&" +M``-HR@`#[````_@#``,/_@`"#04``^P```(R8``#:&L``\$.``/H$``#Z"`` +M`^@P``.D$P`#V!```]Q```/^```#U!X``VAK``-II``#Z````_X```/4'@`# +M:&L``VFD``*@W@`#\`,``T)@``/T```#\$$``T)<``-"60`"H-X``VFD``/P +M`P`#0F@``_0```/P00`#0F0``VFA``/^```#U!X``VAK``-H:P`#[````C)@ +M``-H:P`#0E8``\$.``/H$``#Z"```^@P``.D$P`#V!```]Q```/4'@`"OP(` +M`BT$``-H:P`#::0``VFB``/H```#_P```]0>``*_`@`"+00``VAK``-II``" +M,F```VAK``/L```#:&L``C)@``*Q#``#Z````Z`#``/<```#V!```^@```/H +M$``#Z"```^@P``/^```#U!X``VAK``/[```#^P```XCC``/X`P`#_@```]0> +M``-H:P`#^P```PB.``(-6@`#[````"'K``/H4``#Z&```^AP``*Y"``"N,`` +M`]R!``/8D0`#0E```_@#``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`# +M:&L``\&/``*_$``"+00``K09``/^```#U%\``VAK``*_$``"+00``\'X``-) +MI0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``#"9X``@V' +M``-II0`#[````J&^``/P#@`#T!X``P^^``*Z/P`#``X``D`*``,!'@`"01H` +M`P(N``)"*@`#`SX``D,Z``/4'@`##_X``@V0``/[```##,X``@V+``/L```" +MH;X``_`.``/0'@`##[X``KH_``+`#@`"0`H``L$>``)!&@`"PBX``D(J``+# +M/@`"0SH``]0>``,/_@`"#:0``_L```,,S@`"#9\``^P```/0G@`#T!\``KP_ +M``)(C``"29P``DJL``)+O``"1`P``D4<``)&+``"1SP``KP@``+`A``#H``` +M`J-(``/P00`"P`P``L&5``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`# +M\$$``L(L``+#MP`#HS```J-[``/P00`"PSP``KP'``*CW``#\$X``W)T``-2 +M=@`#_P```_\```/^```#U!X``VAK``/[```#<``&(P``/_```"H;X``_!"``#QY0`#[````J'.``/P00`#"[X` +M`PS.``#9YP``XC```TI```!:"0`#_P```_\```*@O@`#\$(``Z````.B(``# +MT%X``&'\``!9XP`#H@(``D`)``)"*0`"I8X``@X\``,(C@`"H`T``_`+``!! +M^0`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$3P`#P50``J6N +M``(.3``#"JX``J`M``/P"P``4?D``L9O``/!=@`"H+X``_!&``/47@`"QF\` +M`\%V``/47@`"QF\``\%V``/47@`##,X``@Y-``)KB@`"#A$``^P```-"<``` +M4@D``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``"H6@``_!!``+& +M:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,&:``#`B@``P,X +M``,*K@`"#F```\%4``/!=@`#U%X``V)P``/L```#P6(``P9N``/<$``#V``` +M`]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X``_L```,&;@`" +M#G4``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``#:1```VD4``-I +M&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I-``#[````\$0 +M``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC<``/T```#\$4` +M`VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4``D$#``-)T@`# +M_P```D`*``-)P@`"I1```_`!``-)Q@`#[````]">``/[```#_P```_\```/4 +MGP`#^P$``P_^``(.M``#[````_@!``*_!``#2F0``_\```/_```"00\``@Z_ +M``/X`P`#:&L``_\```/_```#_@```^P```-*9``#_P```K\(``)!#P`"H!\` +M`@[K``-`$@`"M1```J4E``/P!``"OP(``FJO``/T```!SN@``L15``*E)``# +M\`0``K\"``)KOP`#]````<[H``+$10`"I20``_`$``*_$``":J\``_0```'. +MZ``"OQ```FN_``#QY0`#8!(``B[L``/L```#2G```_\```/!P@`#0"X``K`! +M``-JJ``#_P```_\```/_```#2JP``K0"``-JJ0`#P````\`1``/`(@`#P#,` +M`TJM``*_D``"H,\``_`%``/`1``"OP\``D]/``/T```#\$$``\#T``*@W@`# +M\`L``T`9``/_```#_P```F1```)E40`"9F(``F=S``-@&0`":J\``_0```/P +M20`#0!T``_\```/_```"9$```F51``)F8@`"9W,``V`=``)KOP`#8"X``^P` +M``+$1@`#:JD``_\```/_```#_P```TJL``/L```",F```VAK```)U@`"L,`` +M`]P```/8$``"H/X``_`$``/H```#Z!```^@@``/H,``"H/X``_!$``*P50`# +MP1```\$@``/!,``"H/X``_`$``*T_P`#P50``\%D``/!=``"H/X``_!$``*T +MJ@`#P50``\%D``/!=``"O`<``J/^``(/G@``0?\``_\```/_```"H(X``@]D +M``*@W@`#\`,``T!"``/T!``#\`$``T!&``#J,0``:@```J3>``/P!``#P(@` +M`\"9``/`J@`#P+L``F`(``)A&0`"8BH``F,[``)D2``"95D``F9J``)G>P`` +M:C$``_\```/_```#_@```]0>``-H:P`#^P```PS.``/^```#U%X``VAK``/[ +M```##,X``@]D``!!_P``8@```_\```*@C@`"#XD``T!*``*DS@`#\`0``\"( +M``/`F0`#P*H``\"[``*DW@`#\`(``\&*``/!FP`"N@\``DJH``.+I@`":JL` +M`KOP``)+N``#I[8``FNW``/T!``#\`,``^A@``/HH``#Z+```K3P``)@2@`# +MP1```\$@``/!,``#:H0``J#^``/P`P`"M/```_0$``/P`0`"M`\``F!+``/! +M$``#P2```\$P``-J@``#[````_X```/4'@`#:&L``_L```,,S@`"N0,``J#Y +M``/P1``#Z$```^A0``/H8``#Z'```_X```/47@`#:&L``_L```,,S@`"#ZH` +M`K#P``*Q_P`"H/D``_!"``/H```#Z!```\$A``/!,0`#:H0``VJ```/L```" +M,F```VAK```)U@`"L,```]P```/8$``"M/\``\%D``/!=``"O`<``_X```*U +M_P`#U%X``VAK``/[```##,X``_X```*U[P`#U%X``VAK``/[```##,X``@_% +M``*U_P`#:H4``K#P``/!$``#P2```\$P``-J@``#2F(``B_O``/H\``"+_L` +M`VIB```)U@`"L,```]P```/8$``"M/\``\%4``/!9``#P70``KP'``/^```# +MU%X``VAK``/[```##,X``@_G``(R6@`#[````TID``*T@``"0`0``VID``/L +M```"L`0``J#P``/P`P`"+R4``_0$``/P`0`"*\0``^@```/````#P1```K+] +M``*S_P`#:&````HM```Q_@``&?T``K`*``*@W@`#\$$``K`,``.!%@`"8`$` +M`K$6``*D/@`#\`$``K,$``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`" +ML@0``F(F``-J8``#C^$``BT$``-H:P`#_P```_X```/L```#2F```_\```/H +M,``"8`X``VI@``-*9``"M/(``D`$``-J9``#[````K`!``/H$``#Z"```^@P +M``-J8``#[````&HQ``-`!``#_P```K@$``)%X``"H%X``_!$``*@W@`#\$(` +M`T`D``/_````8>D``_\```/_```#W,```X_J``*@W@`#\`$``^CP``/8\``# +MC.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<``D`(``/P +M0P`"+8L``_0```/P00`"+9\``D1N``/P"0`#Z,```ZMB``.E8``"15X``_!# +M``(MBP`#]````_!!``(MGP`#[````&HQ``-`*``#0"$``KA```)(@``#\`,` +M`D9N``/P`0`#[````%'#``*@W@`#\`,``%G"``/T```#\$$``%G!``/_```# +MW*```]BP``-`!@`#_P```_\```)`Z``#\`,``J#>``/P00`#0"8``_\```/_ +M```#24$``J`.``/P0P`"H-X``_!!``/!10`"14X``_!#``.,Y``#]````_!! +M``.,XP`#B9@``ZJ<``*@K@`#\`,``BV+``/T```#\$$``BV?``-`!@`#_P`` +M`_\```-)00`"0(X``J`.``/P0P`"H-X``_!!``/!10`#Z,```ZM"``)%3@`# +M\`<``Z5```)%7@`#\$,``BV+``/T```#\$$``BV?``/L```"H-X``_`#``-( +M(0`#]````_!!``-()0`#_P```KL!``.B9@`#@68``Z$6``.'=@`"8"<``P`+ +M``.G!@`#@@8``F8A``*@W@`#\`0``V@A``-JB0`#]````_!"``-H)0`#:HT` +M`^P```./[0`"+00``^@P``."X``#Z!```^@```-H,``#C^T``BT$``-)G``# +M2=4``T`J``*T$``"1$<``K4"``)%6@`#A50``D1%``.D0``"MO<``D(F``)B +M)``#:9P``^CP``-)<``#Z'```K8!``/!40`#P4```V@Q``*X_``#P5,``\%" +M``)%6``#270``C%$``-H,0`#P5$``\%```(Q1``#:#$``\%3``/!0@`#29@` +M`C%$``-H,0`#P5$``\%```(Q1``#:#$``\%3``/!0@`#29P``C%$``-H,0`# +MP5$``\%```(Q1``#:#$``\%3``/!0@`#2.@``C%$``-H,0`#P5$``\%```*W +M$``",40``V@Q``/!4P`#P4(``C%$``-H,0`#[````KP#``-)/0`#2,```J#> +M``/P00`#2,0``K8$``)&9``#\`0``X;*``/!?``"8B8``F$7``*@W@`#\`,` +M`VC```/T```#\$$``VC$``-`*@`"M@@``X?&``)&:``#\`$``F,W``*@W@`# +M\`,``VC```/T```#\$$``VC$``/L```","X``TD]``-`*``"OP@``KP$``)/ +M#P`"3$P``F#\``/P00`#[````K0!``(R`@`",0D``J'^``/P"0`",<,``C`H +M``-`*``"O`@``_\```)"+``#\$(``_0```/P0@`#Z$```C("``/L```#_P`` +M`_\```/_```#[````V%(``-A00`#848``V)_``/!#@`#Z!```^@@``/H,``# +M:.@``^@```/_```#:.@``T%(``/_```#[````C)@``-H:P``"=8``^@```.@ +M`P`#W````]@0``*\`P`"L/<``J#^``/P00`"L'\``\$0``/!(``#P3```K3_ +M``/!5``#P60``\%T``/^```#U!X``VAK``.@`0`#H1$``Z(A``.C,0`#^P`` +M`_X```/47@`#:&L``_L```,,S@`"$6H``K#_``*\"``#P1```\$@``/!,``# +M:H```J3^``'1A``"H/P``_`"``-JA``#[````K#W``.A`0`#HA$``Z,A``-J +MA``#[````TD]``/_```"N(```F1(``-I/0`"L`$``K$"``*R/P`"0B\``K,` +M``-J:``"L````K$```*R```"LP(``VIT``*Q`0`"L@@``K,```-J>``"L`$` +M`K(```-J?```$>```K#```)`#P`#H`(``F`.``*Q```#HB(``K,!``-J9``" +M,EH``_\```/_```"+KT``KA_``)$2``#:3T``^P```/H```#Z!```K(#``*S +M```#:#```^P```-`+``#_P```_\```/H(``#Z#```V`L``/H```#Z!```V`8 +M``-@'``#[````&HQ``*P`0`#Z!```^@@``/H,``#:F```K\!``(O]``"OQ`` +M`BT$``*\%``#2F```K_W``*Q$P`"0`\``F`.``-J8```,?X``#G]``*\B``" +MM?X``X9J``)B)@`"I'X``_`!``*S!``"0`4``F`,``-J8``#2I8``T`I``*\ +M!P`#_P```D1,``.%1``"Q5X``\'%``/H0``#Z&```^AP``-JD0`"M/\``K5_ +M``*V_P`"M_\``VAA``-H:P`#_P```_X```,)G``#\$4``\"9``,*K@`#\$(` +M`\"J``,+O@`#:I(``X````.@```#:F```K\0``(M!``#[````T`J``-'+``" +MH-X``_!!``-';``"MG\``X5,``)`!@`"29X``_`!``)@!0`#P1```\$@``/! +M,``"H-X``_!$``-G+``#9S```_0```/P0@`#9VP``V=P``-'-``"H-X``_!! +M``-'=``"MM\``X5(``)`!@`"8`4``\$0``/!(``#P3```J#>``/P1``#9S0` +M`V``#2,```J#>``/P00`#2,0``K8_``)")@`" +MML```J!.``/P`0`#Z&```F(F``*@W@`#\`,``VC```/T```#\$$``VC$``/L +M```#29@``K@/``*Y]0`#Z#```\$N``*@S@`#\`(``F`(``)!&0`#:#```T@( +M``*X0``"H,X``_`"``)@"``#:`@``^P```-A4``#854``V%:``-A7P`"+`4` +M`T%0``-!50`#05H``T%?``/_```#_P```^P```*P_P`"L;\``K+_``*S_P`# +M:&```^P```*P?P`"L?\``K+_``*S_P`#:&```^P```+$3@`#\$H``L5>``/P +M2``"QFX``_!&``+'?@`#\$0``K3_``*U_P`"MO\``K?_``/L```"H```^A```*@`0`#\`$``\%.``(T7@`#2`@``KC^``)! +M&``#:`@``KP```(T"0`"-#H``T`!``/H````@C$``D1.``/P`0`")!L``T`! +M``/_````\C$``D5>``/P`0`")!L```(*``.!X``#_P```J00``/P`@`#P4X` +M`C1>``*\`0`"-`D``C0Z``*_`P`"-N0``C-%``(NJ``"OQ```D_[``'2X``` +M>``(N@@`"+J@``X3B``/!R0`#Z````K$#``*R"@`"LRT``D1)``/P +M`0`"LR\``^A0``(N<0`#@.H``BYQ``*X+P`"M`(``D1,``/P`0`"N"T``\&8 +M``/!J``#P;@``V,J``-C:@`"+J@``X'B``.@X0`#HY8``X+D``+"+@`#Z%`` +M`BYQ``.@XP`"+G$``BZH``.`Y0`"0*```\$0``/!(``#P3```V2H``-DZ``# +M@.```H((``)"`@`#@B0``)'4``/L```"+J@``TEP``)$C@`#\$,``K7S``)" +M)0`#:7```^AP``/!;@`#P5,``\%"``-H,0`"1)X``_`&``-)G``#I.$``F(D +M``/!4P`#P4(``V@Q``)$C@`#\$T``TF<``.$Y0`#I><``D`$``)!%0`#I(@` +M`X1```.%1@`"8`4``F$4``/H,``#P2X``V@P``-#I```(=0``K7/``)`!0`" +M8`0``\$0``/!(``#P3```V.D``-CY``"1$0``_`!``(VWP`#@80``Z`8``." +M!@`"8`(``^C0``(NE@`#P=X``BZ6``-)T0`"+J@``^A@``*E$``#\`$``K9` +M``)&=@`#IFH``TB0``.DN@`"H$X``_!!``*T!``"M0,``J!%``/P00`"M`$` +M`K7P``)!%0`"810``K?^``)`!P`"8`8``VB0``-HJ``#:)0``VBL``.@I@`# +MP1```\$@``/!,``#9"0``V1D``.*M@`#2"$``K@#``)F:``"N0\``KO^``)& +M:0`"9FH``D=[``-H(0`#:HD``V@E``-JC0`#2`@``T@A``)A'@`#:`@``TC( +M``*X0``"N3\``F`(``-HR``"0`D``VC(``/L```#0"P``KA```*Y@``#Z+`` +M`TJE``)(&``#\`$``KLP``))&0`#\`(``KK```)KN@`"95L``VJE``-(G``" +MO'L``D`,``-HG``#:*```VBT``-HN``#2)```X3B``.EYP`"014``F$4``*U +M_@`"0`4``VB0``-HJ``#:)0``VBL``-).``"M0,``F(E``*U\P`"0B4``VDX +M``/HP``"-`D``C0Z``/H```"L0,``K()``/H,``#Z%```BYQ``.`Z@`"+G$` +M`K`$``/!$``#P2```\$P``-C)``#8V0``K`@``/!$``#P2```\$P``-C*``# +M8V@``C;?``-("``#2"$``ZCM``)!&``#:`@``ZCK``)&:``#P#X``D53``-H +M(0`#:HD``V@E``-JC0`#Z$```C1>``/H\``"/B(``K\!``(^(@`#[````T`I +M``/_```"N"H``D)>``/P`0`"N&0``J#.``/P00`"N!```\&8``/!J``#P;@` +M`V@`# +M0[(``K`'``*Q*``"0EX``_`!``*Q.``"H,X``_!!``*Q```"2(```FB!``/! +MF``#P:@``\&X``-CL@`#8_(``^P```-)=``#P6X``^AP``.(2``#P%X``X59 +M``)")0`"8B@``VET``/!0@`#P5,``V@Q``/L```"OP,``C;D``-("``"N/X` +M`D$8``-H"``#0"@``KP$``*_`P`"3,(``_`#``(]RP`#]````=2+``-(5``" +MO&```F(L``-H5``#278``KP0``)DK``#P5L``\%N``/H<``#:#$``C%$``-( +M5``"O)\``D(L``-H5``#P4H``V@Q``(SJP`#0D4``C)F``-B10`#[````&HQ +M``(M"```\>4``C`H``(KQ``#0`0``T`*``*\`P`"OP0``D$<``,&\0`"0`\` +M`_`!``/!:@`"Q&X``K4(``(XK@`#0`0``^CP``#Z!@`"LD```D(@``'4\0`# +MCP0``Z_X``#Z`P`#2<$``KP/``)(SP`#J(```XF"``*ZXP`"1$H``F1)``)) +M_@`#B9(``KK[``)%6@`"95D``VG!``.!A@`"8($``BZ6``/H```"H-X``_!! +M``*P0``"L0,``K()``*S"0`"1.\``_`!``*S#P`#Z%```BYQ``*C_``!U/$` +M`^C```#AS@``X>X``C97``-`&``"H-X``_!!``-`'```0>X``&'.``)@`0`" +M8`(``F`#``*A#@`#\$(``LB.``#![@`"N@(``KL?``+,R@``X4``_0` +M``'4J@`"S_X``/H#``#"!@`#]````=2J``/HP```X@,``^@P``(V:P`#W.`` +M`K\(``/8\``"L"```\$0``/!(``#P3```K\1``/4'@`#_P```_L```,/_@`" +M%/T``C97``!B`P`"L````]P```/<`0`#C\(``K!```+`#P`#V````K`_``)! +M#P`"L,```L`!``/8`0`#U%X``]`?``*_$``"H<\``=4>``*@W@`#\`,``\$* +M``/T!``#\`$``\$+``/4'P`#]````=4E``*@W@`#\`,``\$J``/T!``#\`$` +M`\$K``/4'P`"-@\``T`&``*P'P`"L2```\$N``)!&``#\`$``L(N``+,P@`` +MX@,``J7```(5`@`#2I0``_\```-@O``#0`0``]S@``*_"``#V/```]SA``*_ +M+``#V/$``K\(``.L%@`"I<\``_!#``/`S``";,\``LS.``*_"``#T!X``]!? +M``/!B0`#P9H``\&K``+$0``#H$```L`,``/!L``"Q5$``Z%0``+!'``"IAL` +M`_`!``/!L0`"QF(``Z)@``+"+``"IBL``_`!``/!L@`"QW,``Z-P``+#/``" +MICL``_`!``/!LP`#U!X``]2?``/[```#^P$``P_^``(50P`#03@``T%)``-! +M*@`"O`X``J,!``/P`0`#P0$``J,"``/P`0`#P0(``J,#``/P`0`#P0,``J,( +M``/P`0`#P0@``J,)``/P`0`#P0D``^@0``*F#``#\`,``\````.`!@`#H08` +M`\$!``*C10`#\`$``\%%``*C1@`#\`$``\%&``*C1P`#\`$``\%'``*C2@`# +M\`$``\%*``*C2P`#\`$``\%+``/H(``"IDP``_`#``/`1``#A$8``Z)&``/! +M,@`"H-X``_`#``-DJ``#]`0``_`!``-DZ``#W.```K\(``/8\``#T%X``K\$ +M``/<\0`"OX```J#>``/P00`"O\```]CQ``*\$``"N`$``KD#``*Z#P`"H4P` +M`_!%``/`1``"1$H``P0$``/T!``#\`(``P1*``+$0``"H5P``_!%``/`50`" +M15H``P4%``/T!``#\`(``P5:``+%4``"H6P``_!%``/`9@`"1FH``P8&``/T +M!``#\`(``P9J``+&8``"H7P``_!%``/`=P`"1WH``P<'``/T!``#\`(``P=Z +M``+'<``#U%\``_L```/[`0`#T%X``PB.``(5J0`"N`$``\$!``/!$@`#P2,` +M`PF>``(5J0`#1*@``J#>``/P00`#1.@``J%,``/P10`#P$0``D1*``,$!``# +M]`0``_`"``,$2@`"Q$```J%<``/P10`#P%4``D5:``,%%0`#]`0``_`"``,% +M6@`"Q5$``J%L``/P10`#P&8``D9J``,&)@`#]`0``_`"``,&:@`"QF(``J%\ +M``/P10`#P'<``D=Z``,'-P`#]`0``_`"``,'>@`"QW,``]1?``(L]P`"-&L` +M`C`H``(O[P`#[````BZH``.CE@`"-FL``X#E``)#H``"-G0``_0```'6`@`# +MP9```J'/``/P`0`#P9(``V)U``#)S@`#W.```K\(``/8\``#W.$``K\L``/8 +M\0`"OP$``\$$``(V,0`#0G4``K\!``/_```#P04``C8Q``-"=0`"OP$``_\` +M``/!!@`"-C$``T)U``*_`0`#_P```\$'``(V,0`````/4GP`#^P```_L! +M``.@```##_X``A8R``/L```"LQ```J7#``/P!@`#P#P``X,V``.C-@`"-G0` +M`_0```'69``"LP\``LS.``)#/``"-FL``C&X``(L]P`"-&L``K\8``(X7``" +M+NP``^P```*Q!``"L(```J#>``/P00`"L,```K()``/H4``"+G$``^P```/! +M`P`#P1,``\$C``*@W@`#\`,``V2H``/T!``#\`$``V3H``/L```#0`0``KR` +M``/_```"3,```=:>``-!`0`"H-X``_!!``-!!0`"L00``K"```*@W@`#\$$` +M`K#```/<$``#V````\&$``(VNP`#P84``C:[``/!A@`"-KL``\&'``(VNP`" +MH-X``_`#``-DH0`#]`0``_`!``-DX0`#]````=:X``*Q!``"L(```J#>``/P +M00`"L,```]P1``/8`0`"L0$``K`(``*@W@`#\$$``K`L``/<$``#V````K\( +M``(NM``#00$``J#>``/P00`#004``J#>``/P`P`#9*D``_0$``/P`0`#9.D` +M`BSW``(T:P`#[````\&8``/!J``#P;@``K(!``/4G@`#^P```P(N``(6OP`# +M[````K$$``*P@``"H-X``_!!``*PP``#W!```]@```*Q`0`"L`@``J#>``/P +M00`"L"P``]P1``/8`0`"OP@``BZT``-$J``"H-X``_!!``-$Z``"H-X``_`# +M``-A```#]`0``_`!``-A!``#[````TL,``*U_``"014``VL,``/L```#2PX` +M`\#/``)JKP`#:PX``C%$``)*K``#:PX``^P```*_`P`"-N0``TG```-)U0`" +M3`X``_!"``/T```!URD``TG```.'=@`"IG```_!"``/!$@`#Z````Z(6``.! +M%@`#H18``TB1``*\\``"15P``F52``*\!``"0PP``Z,R``*\_@`"1$P``F1# +M``-HD0`#:)4``VBI``-HK0`#P4$``\%1``/!80`#P7$``V0A``-D)0`#9&$` +M`V1E``*\`@`"0@P``X(J``-(G0`"LW\``D1#``)D0@`#:)T``VBA``-HM0`# +M:+D``J$.``/P`@`"-M\``K`0``/!$``#P2```\$P``-CH``#8Z0``V/@``-C +MY``#27P``K3[``)!%``#:7P``VAK``/T```!S`4``C`H``(O[P`#0````_\` +M``/_```#H`P``Z$<``.!$``"81```P\>``/HT``"H/X``_!!``*]`0`#P4``_\```)&8@`"9FH``VGE``/T!``"%W8``J/^``(7R@``T=`` +M`J#>``(7GP``T=$``LW>``/T!``"%U4``$'1``/_```#_P```J"H``(7R@`" +MH:@``_!(``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@``VGE``-()0`#`Z@``X,P +M``)G4``KB```)G>``#8!$` +M`TF8``*U!``"814``VF8``-("``#_P```X3(``)@!``#:`@``_@#``/L```` +M:C$``^@```""#```@<\``CC*``-`)``#_P```_\```)`#@`#\$L``T`0``*\ +M!``#W,```X_J``*@W@`#\`$``^CP``/8\``"O`D``\&Q``(MBP`#0"0``_\` +M``*\`@`"0`P``_!+``-`$``"O`0``]S```*_P``"H-X``_`!``*_@``#V/`` +M`XSD``/!L0`"+8L``BO$``*T!@`"M0@``K8$``(XK@`"OQ@``CA<``(X@P`" +MOP```B_T``-*<``#_P```_\```*RD``#:G```K\3``(X7``".(,``T`D``/_ +M```#_P```D`.``/P2P`#0!```KP$``/``/P`0`#Z/```]CP +M``*\"0`#BQ```BV?``-`)``#_P```KP"``)`#``#\$L``T`0``*\!``#W,`` +M`K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(MGP`#2G```_\```/_```" +MLH```VIP``*_&``".%P``CB#``*_```"+_0``TIP``/_```#_P```K*0``-J +M<``"OQ,``CA<``(X@P`#0"0``_\```/_```"0`X``_!+``-`$``"O`0``]S` +M``./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+8L``T`D``/_```"O`(` +M`D`,``/P2P`#0!(``KP$``/``/P`0`"OX```]CP``.,Y``# +MP;D``BV+``(X[``#[````^@```/````"L;\``\$@``*S_P`#:&```C`H``(O +M[P``"BT``!'^```9_0`"L`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&$ +M``)B(0`"I#X``_`!``*S!``#P1\``VI@``-*9``"M(```!'L``)`!``"M`,` +M`F`$``*S$``#:F0``BZ]``*_"``"3_```_`!``#R#``#[`````(,``/_```# +M_P```J4.``/P`0`#[````^@```""#``#0!(``_\```/_```"1(X``J!.``/P +M`0``\>4``K]```*@W@`#\`,``FJO``/T```#\$$``FN_``-@$@`"+NP``'G/ +M``/_```#0"```J#^``/P00`#[````J#>``/P!0`"P`X``_!!``*P_P`#]``` +M`_!#``+!'@`#\$$``K'_``-@(```\<\``^P```*P`0`"L0(``\$D``/H,``# +M:F@``\$E``*P$P`"L0(``X(F``/H,``#:G```K`A``*Q`@`#P28``K,!``-J +M=``"L`$``K$"``*R#P`"LP$``VIX``-*?``#_P```K````*Q```"LP0``VI\ +M``/L```"L`$``K$1``*R$``#:D0``K$0``/H(``#:D0``J#>``/P`P`"NU,` +M`_0```/P00`"NUL``-GL``-("``"M$```('F``)@!``#:`@``T@!``*POP`" +M1$```V@!``/H```"L4```^@@``/H,``#:D0``K`!``/H$``#Z"```^@P``-J +M8``#[````C`H``(O[P``(>8``_\```-("``#_P```\$$``-H"``#[`````HR +M``!J,0`#_P```D`>``/P00`#[````CC*``*_```"+_0``#(:``/_```"M0D` +M`Z9B``+&;@`"Q&X``CBN``-`*``#Z/```J#>``/P00`"OT```/G@``.@#``` +M@<4``T`8``-`'0`#0"X``&'E``/_```#_P```V%0``-A50`#85H``.''``-` +M$```>>```KP$``/``/P00`#0!P``T`M``/_```#U!X``]1? +M``*_`0`#W/```K\```.(P@`"S_@``]CP``/$```#Q!$``\0B``/$,P`"H-X` +M`_!!``/!9P`"M1$``D1E``/$1``"P`0``K4B``)$90`#Q$0``L$4``*U1``" +M1&4``\1$``+")``"M8@``D1E``/$1``"PS0``]0>``!YQ0`#0G4``T)R``)/ +M_@`#\$(``L`!``+"(P`"H00``_!&``*E"0`#\`0``\&,``/!D``#P:P``\&P +M``*C"0`#\$(``\&L``/!L``#8G(``T)&``*A)@`#\$8``J4I``/P!``#P8P` +M`\&2``/!K``#P;(``J,I``/P0@`#P:P``\&R``-B1@`"H/X``=FN``-"3@`" +MH14``_!&``*E&0`#\`0``\&,``/!D0`#P:P``\&Q``*C&0`#\$(``\&L``/! +ML0`#8DX``T)*``*A-P`#\$8``J4Y``/P!``#P8P``\&3``/!K``#P;,``J,Y +M``/P0@`#P:P``\&S``-B2@`#8G0``_L!``*Q$``"S,X``.'.``*@P0`!V3<` +M`T)P``-"10`#_P```L@"``.H@``"RD8``ZJ@``-"3``#0DD``_\```+)`@`# +MJ9```LM&``.KL``".=L``T`0``!YX``"O`0``]S```/8\``"O`D``\&Q``(M +MGP`","@``B_O``-!4``#054``T%:``!AQP`#_P```_\```-@&``#8!T``V`N +M``#AY0`#[````KLA``*[$````<4``_\```/_```"0`X``=H3``.IA``#JZ0` +M`KP/``.(@``"2(P``XJ@``)*K``#2)P``TBA``*@W@`#\$(``TBT``-(N0`# +MP1@``\%:``.,%@`#CU8``F$<``)E7P`"H-X``_`$``-HG``#:*$``_0```/P +M0@`#:+0``VBY``-*Z``#2NT``J#>``/P0@`#2O```TKU``*\[@`"0`P``D1, +M``.(E@`";)@``F`,``.*M@`";+H``F1,``*@W@`#\`0``VKH``-J[0`#]``` +M`_!"``-J\``#:O4``^P```*_!0`"O````J#>``/P00`"O$```]SP``/8P``" +MO(```FB,``)IG``":JP``FN\``/!"``".BL``\$)``(Z*P`#P0H``CHK``/! +M"P`".BL``]2>``/[```#U)X``^P```/!$``#P2```\$P``/4'@`#^P```]0> +M``/[```#[````&HQ``(M"``#Z````K%@``/H(``#Z#```VF@``-)F``"N`\` +M`K7U``*S```#P2X``F`(``)!%0`#:#```K\!``(M!``".,H``C`H``-`+``" +MOP0``_\```)/\``#K_(``^CP``(O]```,AH``_\```*U"0`"Q&X``CBN``/H +M\``"H-X``_!!``*_0```^>```%G'``!YX``"O`0``]S```/8\``"O`D``BV+ +M``/HP```X``/P00`#P:L``&'.``!YQ@`# +MU%\``_L!``/07@`"NP(``J'^``/P00`#P4H``J#^``/P00`#P5H``J#[``/P +M00`#P6H``J;[``/P00`#P7H``]1>``/[```"L!```LS.``*EP``#\`8``.'. +M``/!C``#P:P``CG;``/T```!VFL``K$$``+/_@``^<8``J'Q``':I@`#Z+`` +M`-G.``/!BP`#P:L``CG;``!YX``"O`0``]S```/8\``"O`D``\&^``(MBP`# +MW.```KM```/8L``#]````=IK``(X[``"N`@``KH(``(YVP``6<<``'G@``*\ +M!``#W,```]CP``*\`P`"R[P``KP)``(MGP`#2`@``K1@``)@!``#:`@``TF8 +M``/_```"L@$``^@P``-H,``#[````K0$``)&-``"H&0``=K*``/H\``"/?0` +M`K\!``(]]``#:&L``T))``(R9@`#8DD``^P```-"30`",F8``V)-``-(9``# +M^`$``KT,``))T@`"H-D``_!&``*_`P`".RD``K\#``*]```".PH``^P```*] +M!``"2=(``_`&``*_`0`".RD``K\!``*]```".PH``^P```*]"``"2=(``_`& +M``*_`@`".RD``K\"``*]```".PH``^P```*]8``"2=(``J#9``/P1P`"OP,` +M`CNP``*_`P`"O0$``KP!``(["@`#[````KT@``))T@`#\`<``K\!``([L``" +MOP$``KT!``*\`0`".PH``^P```*]0``"2=(``_`'``*_`@`".[```K\"``*] +M`0`"O`$``CL*``/L```#2&(``DS.``(;'``#@/(``\````.!^``#P!$``DW> +M``/P10`#P````FJ@``)*H0`#]`0``_`#``/`$0`"2J```FJA``-H8@`"L/(` +M`FJ@``*@"@`#\$<``TA```*T"``"M?<``F$4``-H0``"014``VA```-H:P`# +M[````TA4``/H@``"N0,``DO^``/P`0`":(D``KH"``*Y#``"2_H``_`!``)H +MB0`"8S@``VA4``/HD``"M`0``DO^``/P`0`":9H``DOZ``/P`0`":90``TE@ +M``-H:P`#_P```_\```-(90`#_P```DO6``*@O0`!VZ<``DN3``';/@`#0"@` +M`X3P``"B`@`#HB8``C%$``,"+@`!VTT``T@$``*T[P``BBP``D$4``-H!``" +MM8```DO^``/P!0`#2)@``K2_``)#-``"8S4``VB8``)+^@`#\`4``TBP``*T +MOP`"0S0``F,U``-HL``"/>@``K8$``-H,0`#0"@``C%$``)!&@`"&Y```$H! +M``/_```"N(```\"9``.)G``"2_X``_`&``-)/``#2)D``F,X``)D20`#:3P` +M`VB9``)+^@`#\`8``TE```-(L0`"8S@``F1)``-I0``#:+$``DO^``/P!@`# +M2)```TB5``)@"``"9$@``VB0``-HE0`"2_H``_`&``-(J``#2*T``F`(``)D +M2``#:*@``VBM``-`*``#_P```K@$``)!&``#\`$``CQH``-`*``#_P```K@( +M``)!&``#\`$``CTJ``-(0``"N(```DO^``/P`0`"81@``DOZ``/P`0`"8B@` +M`VA```*\`0`#[````TA4``/`B``"0S@``VA4``-"20`",F8``V))``*\```# +M[````T`H``#YNP`"N`@``D$8``/P`0`"/4$``T`H``/_```"N`0``D$8``/P +M`0`"/+<``T`H``/_```"N`(``D$8``(;YP`"2_X``AO*``-)/``#2)D``KA_ +M``)#.``"1$@``VD\``-HF0`"O`(``DO\``(;U``#24```TBQ``*X?P`"0S@` +M`D1(``-I0``#:+$``DO^``(;W0`#2)```TB5``*X?P`"0`@``D1(``-HD``# +M:)4``KP"``)+_``"&^<``TBH``-(K0`"N'\``D`(``)$2``#:*@``VBM``-` +M*``#_P```K@.``)!&``"'`<``CT4``)!%P`#:,@``T@(``*X$``"01@``=P' +M``)+_@`"&_P``T@@``*T`0`"M?P``F$4``-H(``"014``V@@``*\`@`"2_P` +M`AP&``-()``"M`$``K7\``)A%``#:"0``D$5``-H)``"-N0``DO^``(<#@`# +M2)@``K3```)C-``"0S0``VB8``*\`@`"2_P``AP6``-(L``"M,```F,T``)# +M-``#:+```KP#``(]R``#2$```KA_``)+_@`#\`$``D(H``*\`@`"2_P``_`! +M``)!&``#:$```T@(``*X$``"01@``=PQ``-`*``"O`0``_\```),P@`#\`,` +M`CU8``/T```#\$$``CW+``).[@`!W#,``KP(``(]R```>;L``_\```/_```" +M2_X``_`$``-(F``"M#\``D,T``-HF``"O`(``DO\``/P!``#2+```K0_``)# +M-``#:+```TA```*X(``"2($``AQ*``(]Z``"M@(``V@Q``-)?``"N`(``DB` +M``(<40`#27$``CWH``-H,0`#2`0``"(L``/_```#_P```\$4``-H!```>;L` +M`K@```*\`@`#2%0``DO^``/P`0`"N`,``DO\``/P`@`"O`P``FB,``/`B``" +M0S@``VA4``.`^```@@(``^P```-("``"N!```D$8``'<>0`"2_X``_`$``-* +M5``"M`\``F`$``-J5``"NP(``DO[``/P!``#2E@``K0/``)@!``#:E@``DO^ +M``/P!``#2E0``K3P``)@!``#:E0``KL"``)+^P`#\`0``TI8``*T\``"8`0` +M`VI8``-("``"N!```D$8``'``/P`@`"OP`` +M`CWT``*\`@`"2]P``_`"``*_`0`"/?0``\']``/L```"M_P``K8S``*U1``" +MM````TC(``*@_@`#\$$``K0!``*\`@`"H/P``_!!``*T`@`"810``VC(``)@ +M!0`#:,@``_\```)`!@`#:,@``KP"``(]R``#[````T@(``*X$``"01@``=T[ +M``)+_@`#\`0``TB8``*T?P`"0B0``VB8``*[`@`"2[\``_`$``-(L``"M'\` +M`D(D``-HL``#23@``X3R``/`1``"0B0``VDX``/L```#23@``X3R``)B)``# +M:3@``T@(``*X$``"01@``_`!``/L```"2_X``_`$``-(F``"M(```F(D``-H +MF``"NP(``DN_``/P!``#2+```K2```)B)``#:+```^P```-"20`",F8``V)) +M``)!_@`"'64``T.N``*P[P`#_P```DNP``)*L``"2;```DBP``-CK@`"L0(` +M`D'Q``(=<``#0^X``K#O``/_```"2[```DJP``))L``"2+```V/N``-(5``# +MC/@``F(L``-H5``#270``KS?``)$+``#P5,``CWH``-H,0`",40``KP0``)D +M3``#:#$``C%$``-(5``"O)\``D(L``-H5``#270``_\```/!0@`#P5,``CWH +M``-H,0`"0?X``AV3``-#K@`"L!```_\```)KL``":K```FFP``)HL``#8ZX` +M`K$"``)!\0`"'9X``T/N``*P$``#_P```FNP``)JL``":;```FBP``-C[@`" +MO`(``D?^``),_``";,<``K<#``*@?P`#\$$``^C```-(R``"N$```KD_``)@ +M"``"81P``VC(``)`"0`#:,@``\#,``)!'``#:,@``KO\``)*_@`#\`@``T@A +M``/_```"95X``V@A``-JB0`"15L``V@A``-JB0`"N@(``DJO``/P"``#2"4` +M`_\```)E7@`#:"4``VJ-``)%6P`#:"4``VJ-``/L```##,X``=W(``/L```" +M/>@``K8"``-H,0`"M@$``TF>``*\$``"9*P``\%;``-H,0`#29H``KP"``)D +MK``#P5L``V@Q``/_```#270``KP0``)D+``#P5,``V@Q``(Q1``#P,P``D1, +M``-H,0`",40``\%*``/!6P`#:#$``^P```/!;@`"MP,``DW^``/P`@`"O0(` +M`D=]``*]`@`"3?T``_`"``*]`0`"1WT``^P```*X!``"L0(``K"```)/_@`# +M\`$``K#```(^0@`"L0,``K````)/_@`#\`$``K!```(^0@`"L0,``K"```)/ +M_@`#\`$``K#```(^0@`"L00``K````)/_@`#\`$``K!```(^0@`"L00``K"` +M``)/_@`#\`$``K#```(^0@`"3_X``_!'``-'-``#1SD``_\```-G-``#9SD` +M`_0$``/P!0`#1W0``T=Y``/_```#9W0``V=Y``/L```"N`0``^@```/H$``# +MZ"```^@P``)/_@`"'C```V4L``-E,``#930``V4X``-E/``#]````=XU``-E +M;``#97```V5T``-E>``#97P``K$&``*P```"3_X``_`!``*P0``"/D(``K$& +M``*P@``"3_X``_`!``*PP``"/D(``^P```+""``#W!```]@```/<$0`#V"$` +M`]`>``/07P`"O`<``]0>``/47P`#^P```_L```/[`0`#^P$``]`>``/07P`# +:#,X``=Y*``/L```#_P```_\```/_```#_P`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_me.bin.uu new file mode 100644 index 00000000000..37f13559719 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_me.bin.uu @@ -0,0 +1,194 @@ +begin 644 PITCAIRN_me.bin +M?$"``8@```#40`!_?$"``8@```!\0,`!S$``*,Q``"E\0(`!B````-A``![$ +M$``A)1```I4`__Y\00`!Q!P`)L0@`"38```50``"V4&BI,0;``+8```;S8``&L`^``3,`:'TS#T@!,0]``',```%V$`` +M&]A``!]\0(`!B````,Q!+@',02X"S$$N`\Q!+@!\0(`!B````'Q`P`&,``4B +MS$$N`'`&GQ"``$E)``! +MS,``(]%``"31@``ET<``)MA``">60``,Q"@`+)J`___()``M?EZ`#)J`_YP2 +M+``&!NP``0KL``&:P/__V$``)X```&#$*``LFH#__WQ`@`&(````?$#``<00 +M`##,027,?04```````ET```\Z!HKN````` +MEX```\Z!HK^`````SH&BPX`````$&```@``!0P08``'$)``F?$#``<9K`^08 +MT``P)-0`_P:H``'.I`/DFD``$L0X``?80``>Q#P`(2?\``*7P/_^S(``"Y>` +M``+90:*DQ#\``L_``!K`/@`$S`&A],P](`3$.0`!S```!=A``!_-0:#:S(`` +M"\U!+A29@``"S````LU```A\0(`!B````'Q`P`$8T`'H&-0`,!C8`#0%*`%K +M?$(``7Q"0`&5```'AH```(```86```&I@``!OX``!1Z```%[$50`$'X6``K, +M@``+U&$``)6`_HO`.@`$S#DA0,0Y``%\0(`!B````!%4`!!29``@?B8`&LU` +M`!W48@``E8#^@,0@`!V:`/__?$"``8@```#<.@``F4``&R><``&5P``-"[@` +M```%\0@`!",P``08D``$&*``"SAVA_``"```(.P"(`!'X6``K,(0``Q!T``7Q"0`%\0H`!F,`` +M`\WE``"`````SD$A:'@```@``"1X```DR```)1@``"5H```EN```)@@``"97\;@`\4I``( +MEX``'29D`/^```)V?QN`#A2D``B7@``8)F0`_X```G9_&X`,%*0`")N``!,F +M9`#_@``"=G\;@`T4I``(FX``#B9D`/^```)V?QN`#Q2D``B;@``))F0`_X`` +M`G9_&X`.%*0`")N```0F9`#_@``"=A2D``@F9`#_,F@`/!3L``B:@/V7?$-` +M`7Q#@`%\0\`!S```"Y;```;/02%ISX$A:L_!(6O,`2%L@````,_U``"````` +M,F@`/)J`_[/40`!_@````'Q`P`%\00`!P!X``144`!+`(@`"P"8`!)5```3` +M)__[?24`"<`F``!]TH`)?A+`"7TE``I\04`!?$&``@%*`*I',S^",R```N5```)AH```(```K2```+#@``"RH```M&` +M``+7@``"XX```P',P:*D?$"``8@```#`$@@`?$%``7Q"``%]#,`*P!(`!!58 +M``,57``-?='`"1(@`!-^'D`*?DZ`"LZ!HJ3-@:'^?$"``8@````$$"$8Q!0` +M"Y5`___440``S,&BI'Q`@`&(````!!`A!L04``R50/__U%$``,S!HJ1\0(`! +MB````-A```_,P:*DQ!``#YD`__]\0(`!B````!C0`#01%``4Q"0`#99`___, +M02$`?45`"LU!(0',02$"S$$A`\S!HJ1\0(`!B````"38``%\00`!?$%``1&< +M`!!\0@`!?5U`"A5D`!TF9``"E8``"<0\`!^7P/__FD``#<0H`#`6J``"?BH` +M`@``#L8```[2```.V@``#N(```[J```.\ +M4=P`('V>`!J```/]R"``+8```_W((``6@``#_<@@`!>```/]R"``&(```_W( +M(``R@``#_9E```,AW``P@``#PB'<`%#-@2%MS<$A;L@B``"```/]4=P`('V= +M@!K8```CT8``)-A``"?$*``LFH#__\@@`"Z```/]Q!P`,,`R``1]G8`!%9@` +M`LV!)<+,,27#E4```\R```O,,27#Q"$``95``"3$)0`!4F0`('XF`!J```/] +M,:P(`,0T`!"6P``#S````8```_`YK`I\/;`*=YK```27```#S````8```_`Y +MK`K&@```@``$,H``!#R```1*@``$%8``!"?$-``0S(``"\X9``"50``$ +M!9@``58@`"#.&0``E\#[\L`Z``3,.2%`Q#D``<]``!!\0(`!B````#&L"`#$ +M-``0EL```\P```&```0(.:P*?#VP"G?$-``0FL``!)<```/,```!@``$"#FL +M"MP]L`K9FL```Y<```+,```!@``$"%'<`"!]G8`:V```'LP!(7[`*@`$!!0`!$%<``@H+`!`SL``(]A``"<)W``!F<#__\R` +M``O,*2%_Q"4``19L`!]!7``"FL#_^<0T`"R;0/__V```'WQ`@`&(````Q`P` +M$S#0``&5```#S(``"]L!HJ3,0``.Q`P`$L00`!,PU```/1@``7U9P`K80``Q +MF<#_^MA``!/0```R?$"``8@```#`#@$`S````@`_`4`` +M0`.=`$$$60!"!'0`0P1\`$0"F`!%`AD`1@*C`$<"HP!(`J,`2@,3`%(#&@!3 +M`RT`5P,T`%\#60!@`SH`80-,`&@#9@!I`VH`<@-R`',#CP!V`VX`=P-N`'H$ +MM0!]!,X`?@32`(4$UP"&!-P`B@4-`(L%#0`/!1X`#P4>``\%'@`/!1X`#P4> +M``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X` +M#P4>``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/ +:!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_pfp.bin.uu new file mode 100644 index 00000000000..9099262364f --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/PITCAIRN_pfp.bin.uu @@ -0,0 +1,194 @@ +begin 644 PITCAIRN_pfp.bin +M?$"``8@```#,@```U$```'Q`@`&(````S(```,S```#40```?$"``8@````D +M3``/,.@``B20``*:@``,?$%``5!8`"!]E<`:F,```]'``!F`````F0```]'` +M`!J`````T<``&X````#$(``5QB0`"I9``6-\00`!?$%``S,.A^LT#H?G-0Z*=S4`` +M`,Q```!\0(`!B````'Q#0`$ +MS,.A^LT#H?G-0Z*=S4```,Q```!\0(`!B````'Q`P`$DT``!S,.BG]A``!>5 +M```"V(``%\R```#,P```?$"``8@```!\0,`!S(```,S#HJ+,P```?$"``8@` +M``!\0,`!%-0`'\R```!\00`!E4```LS``!\5&``?S,```,T```"5@``"S0`` +M(,P``'^```.*(`@`?B"(!^C$(``5'*@`$,Z@``1\00`!4%0`('Q!@`$&)``! +MSD``%16<`!A]%0`:S>``"T`:?65`$558`"#,```AS78``,VV``#$(``3F@#__WQ`@`&(````Q"`` +M)'Q`P`%\00`!S.`#_F\``?Y````#80``>Q#P`'I?` +M`'N0````C``##<0@`!5\0,`!P#;_`,00`!;`,#__?/5`"7U1@`E]@8`=?/.` +M"9F```;?@P``SZ``#XP``Q'40`!_@````(P``Q%\0(`!B````'Q`P`$4W``( +ME<``&23<`!!\00`!4%0`()G```/%'0``@``#,WT5`!K%'@``?$(``7Q"0`%\ +M08`!?>7`"7WB@`]!K``"FH#\QP;L``,*[``!FL#__R3<`!"9P``#Q1T``(`` +M`S;%'@``@``#-LR```#,P```U$```'Q`@`&(````Q!P`!,W```#,````S(`` +M`-1```!\0(`!B````'Q`P`$DT``&,1``!L04``^9```(S```$L0D`'Z60``X +MF4``!,0<``3-P```S````,R```#,P```U$```'Q`@`&(````?$#``7Q!``$5 +M&``?S0``(5$4`""9@``#U$T``(````!]34`:&1P`,=16``"5P/R5Q"``$YH` +M__]\0(`!B````'Q`P`%\00`!%-0`'C%8``(DW`#_E4``!)F`_(K-'`,`@``` +M`,R```#,P```S0```'Q`@`&(````Q"``)'Q`P`'$TP,`S(```,S```#,```A +MS2$A07Q`@`&(````U$``?WQ`@`&(````Q"0`?I9```-\0(`!B````(```XX` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````P-(``4!7P`&`.P`!P#S``@!`0`)`0@`$`.'`!$`"P`2`"<`$P`K`!8` +M+@`D`#<`)0!Q`"8!&0`7`8$`(@+H`",#%0`G`3,`'P&S`"`!XP`H`5(`*@%" +M`"P`4``O`4P`,0.'`#(!>0`S`X<`-`-/`#4!(``X`)(`-P&/`#P#*``_`6$` +M0`)5`$$"F`!"`KP`0P+$`$0"U`!*`MX`50-+`%\`WP!@`+L`80#6`&D`[P!S +M`/8`=@$$`'Q`\`87R-``R9```&Q!$Q"WS0P`K,PP`> +MP!@``S,,`8<`(!0`H#```S(\`0<`*("`HB`\%!,P``#P3,``',CP!!P`I`0"B(*!X$S``!S(\`0<`*0$`HB#(H!,P` +M``3,``',CP!!P`K__RB(@'T$S``!S(\` +M0<`(`(#,@P!>P`@#_\R``##,`P!5S`,`7B0",```8?!2`"A%4`!!^EH`*C``!NG[.P`'`'HE`C```&'P4 +M@`H15``8?I:`"HP``;I^SL`!SH,`6I`````H%``??)3`!23,``&8P``#"50` +M`9E`__R0````)K@`'Q:<``@EW``?$=P`!7^?@`H6G``0)?0`'Q7<``@EW``? +M$=P`!7]?0`J0````Q!P`,Y7`_L?,```PP"```)````#`,"`#S[$``,,``)/Q`L`57T(@`[,@P!=S0,`5B$",``0,%J@`"":,`/]\U,`+ +MP!0``<`*B$",``&G$9@`"'Y:0`K`'HD`C``$#!:H``@FC`#_?-3`"\`4``'` +M"HD`C``!IQ&8`!!^6D`*P!Z)0(P`!`P6J``()HP`_WS4P`O`%``!P`J)0(P` +M`:<1F``8?EI`"I````",``&8P!0Q%<^5``#`%#$6SU4``,`4,1C/%0``P!`Q +M'<41```E$``!F0#_Q\`4,1?/U0``D````,`,`!_`"H@`??4U`"1%4`!A^EH`*P`J)0'W)``K%%0``%50`$'U! +M0!Y]34`)$50`&'Z6@`I^@H`>Q!<``GZ6@`F0````P`PDU<03`!Z,``+RQ!<` +M)9E```>,```(E4``!<`,)-5^`0`*S0,`'HP``O+,`P`.D````"@X``",``/Y +M*#@``8P``7`H#```C```'L!_^6P``#P"0``(P``##-@``"Q!```Y4` +M___,```0P#@``9````#`,#$!QPD``"2<``*5P/Y-C``#-98`_DO-@P``@``# +M6B44`/_`"H@`?(R`"L2A``#-20``%10`""54`/_`"HA`?(R`"L2=```1W``( +M?>(`"LU)```5%``0)50`_\`*B0!\C(`*Q)T``!'<`!!]X@`*S4D``!44`!@E +M5`#_P`J)0'R,@`K$G0``$=P`&'WB``K-20``D````,`*G``HC".8P!``!\T- +M``#`"HP`*(PCF<3Q```HC".:Q/4``"B,(YO$^0``*(PCG,3]``#`"HT`*(PC +MF<31``!],P`!*(PCFL31``!]-T`!*(PCF\31``!].X`!*(PCG,31``!]/\`! +MD````(```RO`'##0S9T``,`<,,[%W0``?=7``GW1P`^5P/\9?0+`"I````#$ +M"``/E(#__\0K``*,``%?P`Z``'^/@`K`#H``?T]`"B@\`)`3_``0*_P`_XP` +M`I#`'#$%Q>T``!+L`!@F[`#_P"0``<`@``",```PS8``$I````#`"``!S(,` +M8L\#`&7/0P!CSX,`9L_#`&03H``$?BX`"LX#`&<3X``$?BX`"LX#`&B,``)G +MSD,`8<`8``&0````S8``#LV``"W$"``2E(```HP``8;$"``0F(```HP``73$ +M)P``FD#_:X```_#$UP``!,P``0H@``$H&`#_?96`"7V1@!!]G8`$?)F`#Y6` +M_SH,` +M(GZ"P`K`'")PC``"GLZ#`"-^KH`*SH,``<`,,0S$S0``S,,`!<0/``+`$#$# +MS-$``,S#``_,`P`-P!```,P3`!#,$P`4S!,`&`40``$Q#``$E,#_^\0-,0/$ +M#``ZS```+<0(``.8@/__S8``$,V``!',```2S```#L0(`#;$*``!EH#\WLV` +M``XH"``!Q`P`(,^Q``"0````C``"UI>```/$#``0E,#\ +M%S`,`:<0M,0O`"H@`)M`` +M_\`4``&,``"4?!J`"L`*B$`6[``()M``_\`4``&,``"4$9@`"'Z:@`K`"HD` +M%NP`"";0`/_`%``!C```E!&8`!!^FH`*P`J)0!;L``@FT`#_P!0``8P``)01 +MF``8?IJ`"GZ"0`J0```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +"```` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R100_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R100_cp.bin.uu new file mode 100644 index 00000000000..38fb0606832 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R100_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 R100_cp.bin +M`````"$`<```````(`!P``````0```"T````!````+@`````;UM-3`````!, +M3$)_`````%M6BI(`````3*"<;0````"M3$Q,`````$SAKST`````V*^OKP`` +M``#63$S<`````$S1#1`````6``\````````V+R0M````!````!(````6``\` +M```````V+R@M`````@`#@.<````"!``LEP```!8`#P`!`````#,Z-S`````" +M``!W[P````(`!A``````&@```"$````>``!```````(`!A``````&@```"$` +M```>``!```````(`!A``````&@```"$````>``!```````0````7`````@`# +M@"L````"!`!GX`````0````7`````@``=^`````"``90``````(``#?A```` +M!@0`9^$````"``!WX`````(``'?A````!@``=^$`````_____P`````0```` +M`````@`#@"L````&!`!GX`````(``'9U`````@``=G8````"``!V=P````8` +M`'9X`````@`#@"P````"!``F=@````(``'9W````!@``=G@````8````+P`` +M`!@````O````!@`````````8````,````!@````P````!@`````````"`6!0 +M``````(`!E```````@`)@``````"``80``````1DP&`^`````@`#@.8````" +M!``EQ0```!8`"``````````````````"!``E'0````(``'6``````@`&=8$` +M```"!``E@`````(`!G6!````!````$D```````!0``````(``X#F`````@0` +M)<4````"``80``````(``'4.`````@`!D``````4``$050```!(```!5```` +M`@0`)0\````$``!03P````(``X#F`````@0`)<4````"``!U90````(``'5F +M````!````%@````"``.`Y@````($`"7%`````@'F5;0````"1`&PY`````(! +MP1#D````&"9F<&8````"!`PE90```!@```!F`````@0`)60````"``!U9@`` +M``0```!=````"`!`$&D````"`!`0``````(`#8#_````"`"``&P````"``^0 +M``````(`#@#_````!@`````````8````CP````0```!;`````@`#@.8````" +M!``EQ0````(``'5V`````@`&4``````"``"0``````(`!!```````@P`-0X` +M```"``20``````(`!1```````@'GA?@````"`"````````P`8`!^`````@`` +M=6,````A`&!U\`````0@`'!S````!```4',````"``.`Y@````($`"7%```` +M`@``=78````"``!U=P````(``'4.`````@``=0\````"`*!0``````P`8`"# +M````(0!@=?`````"``!U^`````0```"#`````@`*=0X````"``.`Y@````($ +M`"7%`````@`@=0\````$`&``A@````(``'5P`````@``=7$````&``!U<@`` +M``(``X#F`````@0`)<4````"``!0``````(`H%```````@``=6@````"``80 +M``````P```"5`````@`%@``````"#&!U8@````0```"7`````@`#@.8````" +M!``EQ0````0`8`"6`````$``<.4````"``.`Y@````($`"7%`````@`#@.4` +M```<````J````!@`!E"J`````@0`);L````8``80JP`````$`'6\`````@`` +M=;L```````!UO`````8`"0```````@`)```````&``V``@````(``'@R```` +M`@``4``````"``.`YP````($`"R7`````@``>"`````"``!X(0```````'@` +M`````@$@```````"(`=P``````(!(````````B``<``````"``80``````(! +M('4;`````H!`=0H````"@$!U"P````(`$0```````@`#@.4````<````Q@`` +M`!@`!A"K`````H1`=;T````8``80J@````*$`'6[````&``&$*L````"A$!U +MO`````0```#)`````H!`=;T````"@`!UNP````*`0'6\`````@`0@``````" +M`4````````P`8`#-````("#`<``````2````SP````8`@```````!@"`=1T` +M``````````````(``'=<`````@"@4``````"`&80`````"`$8"==```````` +M0``````"`>`(,``````A`'```````&1D84T`````:6AT(`````````!S```` +M```````````"``!0``````(``X#0`````@0`)>````````!UX0`````````! +M`````@`#@.`````"!``CE````````%`````````````````````````````` +M```(``````````0````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R200_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R200_cp.bin.uu new file mode 100644 index 00000000000..a3b40b16141 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R200_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 R200_cp.bin +M`````"$`<```````(`!P``````0```"_````!````,,`````>FA>70````!= +M756(`````&AED9<`````7:&?>`````!=75U=`````%WN75``````\JRLK``` +M``#G7?GI`````+'=#A$`````XJ^OKP```!8`#P```````$4O(RT````$```` +M$P```!8`#P```````$4O)RT````6``\``0`````^34HW`````@``=^\````" +M``80`````!H````@````'@``0``````"``80`````!H````@````'@``0``` +M```"``80`````!H````@````'@``0``````$````%@````(``X`J`````@0` +M9^`````$````%@````(``'?@`````@`&4``````"```WX0````8$`&?A```` +M`@``=^`````"``!WX0````8``'?A`````/____\`````$``````````'\`?P +M`````@`#@"H````&!`!GX`````(``X`L`````@0`)T$````"!``G00````($ +M`"=#`````@``=G4````"``!V=@````(``'9W````!@``=G@````"``.`+``` +M``($`"=!`````@0`)T$````"!``G0P````(``'9V`````@``=G<````&``!V +M>`````(``X`K`````@0`)G8````"``!V=P````(``X`L`````@0`)T$````" +M!``G0P````8``'9X`````@`#@"P````"!``G00````($`"=!`````@0`)T,` +M```&``!V>````!@````O````&````"\````&`````````!@````W````&``` +M`#<````&``````````(!8%```````@`&4``````"``F```````(`!A`````` +M!&3`8%$````6``@``````````````````@0`)1T````"``!U@`````(`!G6! +M`````@0`)8`````"``9U@0````0```!:````````4``````"``80``````(` +M`'4.`````@`!D``````4``$09````!(```!D`````@0`)0\````$``!07@`` +M``(``'5E`````@``=68````$````90````(!YE6T`````D0!L/`````"`<$0 +M\````!@F9G!Q`````@0,)64````8````<0````($`"5D`````@``=68````$ +M````:`````@`0!!T`````@`0$``````"``V`_P````@`@`!W`````@`/D``` +M```"``X`_P````8`````````&````)0````$````:`````(``'5V`````@`& +M4``````"``"0``````(`!!```````@P`-0X````"``20``````(`!1`````` +M`@'GA?@````"`"````````P`8`"'`````@``=6,````A`&!U\`````0@`'!\ +M````!```4'P````"``!U=@````(``'5W`````@``=0X````"``!U#P````(` +MH%``````#`!@`(H````A`&!U\`````(``'7X````!````(H````"``IU#@`` +M``(`('4/````!`!@`(T````"``!U<`````(``'5Q````!@``=7(````"``!0 +M``````(`H%```````@``=6@````"``80``````P```"8`````@`%@``````" +M#&!U8@````0```":````!`!@`)D`````0`!P\0````(``X#Q````'````*<` +M```8``90J0````($`"6[````&``&$*H`````!`!UO`````(``'6[```````` +M=;P````&``D```````(`"0``````!@`-@`(````"``!0``````(``'@A```` +M````>``````"``!X(0```````'@``````@%F4``````"``H```````(`!G', +M`````@*&\,4````"``!XQ@````(``'DD`````@``>24````" +M``!Y)@````0```#R`````@``>20````"``!Y)0````(``'DF````!````/D` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R300_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R300_cp.bin.uu new file mode 100644 index 00000000000..175b69cf4a3 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R300_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 R300_cp.bin +M`````$(`X```````0`#@``````@```"N````"````+(`````9U5+2@````!* +M2D1U`````%52?8,`````2HR+90````!*[TKV`````$KA2DH`````Y)>7EP`` +M``#;2NO=`````)S,2DH`````T9B8F`````!*#YK6````!``,H``````X``T` +M$@````0``.BT````.``-`!0````$``#HM@```#@`#0`6````!```Z%0````X +M``T`&`````0``.A5````.``-`!H````$``#H5@```#@`#0`<````!```Z%<` +M```X``T`'@````0``.@D````.``-`"`````$``#H)0```#@`#0`B````!``` +MZ#`````X``T`)`````0``/#`````.``-`"8````$``#PP0```#@`#0`H```` +M!```\$$````X``T`*@````0``/&$````.``-`"P````$``#QA0```#@`#0`N +M````!```\88````X``T`,`````0``/&'````.``-`#(````$``#Q@````#@` +M#0`T````!```\Y,````X``T`-@````0``/.*````.``-`#@````$``#SC@`` +M``0``.@A````!`%`H``````8````0P````0`S.@`````!``;``$````$"`!( +M``````0`&P`!````!`@`2``````$`!L``0````0(`$@`````"````#H````` +M``"@``````0@`$4=````!```Y8`````$``SE@0````0(`$6`````!``,Y8$` +M```(````1P```````*``````!``,(``````$``#E#@````0``R``````*``" +M(%$````D````40````0(`$4/````"```H$L````$``#E90````0``.5F```` +M"````%(````$`\REM`````0%0R``````!``"(``````P3,S@7@````0()T5E +M````,````%X````$"`!%9`````0``.5F````"````%4````0`(`@80````0` +M("``````!``;`/\````0`0``9`````0`'R``````!``<`/\````,```````` +M`#````"`````"````%4````$``#E=@````0`#*``````!``!(``````$``@@ +M``````08`&4.````!``)(``````$``H@``````0`#P``````!`!````````8 +M````=`````0``.5C````P@#`Y?D````(````:0````@``*!I````!```Y78` +M```$``#E=P````0``.4.````!```Y0\````$`4"@`````!@```!W````P@#` +MY?D````(````=P````0`%.4.````!`!`Y0\````(`,``>@````0``.5P```` +M!```Y7$````,``#E<@````0``*``````!`%`H``````$``#E:`````0`#"`` +M````&````(0````$``L```````08P.5B````"````(8````(`,``A0````0` +M!P#C````.````)(````P``R@E`````0(`$6[````,``,()4`````"`#EO``` +M``0``.6[````````Y;P````,`!(```````0`$@``````#``;``(````$``"@ +M``````0``.@A````````Z``````$``#H(0```````.@N````!`+,H``````$ +M`!0```````0`#.',````!`4-X````````#EX0`````````! +M````!``'`.``````"`#CE```````````````!```Z,0````$``#HQ0````0` +M`.C&````!```Z2@````$``#I*0````0``.DJ````"````.0````$``#I*``` +M``0``.DI````!```Z2H````(````ZP````0"P"``````!``&```````T```` +M\P````@```#P````!```@```````P`#@````````````````!``,(``````$ +M`!T`&`````0`&@`!````-````/L````(````2@````@%`*!*```````````` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R420_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R420_cp.bin.uu new file mode 100644 index 00000000000..a78f40fcf25 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R420_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 R420_cp.bin +M`````$(`X```````0`#@``````@```"9````"````)T`````2E5+2@````!* +M2D1G`````%52;W4`````2GY]90````#9T]_V`````$K%2DH`````R(*"@@`` +M``"_2L_!`````(>P2DH`````M8.#@P````!*#X6Z````!``,H``````X``T` +M$@````0``.BT````.``-`!0````$``#HM@```#@`#0`6````!```Z%0````X +M``T`&`````0``.A5````.``-`!H````$``#H5@```#@`#0`<````!```Z%<` +M```X``T`'@````0``.@D````.``-`"`````$``#H)0```#@`#0`B````!``` +MZ#`````X``T`)`````0``/#`````.``-`"8````$``#PP0```#@`#0`H```` +M!```\$$````X``T`*@````0``/&$````.``-`"P````$``#QA0```#@`#0`N +M````!```\88````X``T`,`````0``/&'````.``-`#(````$``#Q@````#@` +M#0`T````!```\Y,````X``T`-@````0``/.*````.``-`#@````$``#SC@`` +M``0``.@A````!`%`H``````8````0P````0`S.@`````!``;``$````$"`!( +M``````0`&P`!````!`@`2``````$`!L``0````0(`$@`````"````#H````` +M``"@``````0@`$4=````!```Y8`````$``SE@0````0(`$6`````!``,Y8$` +M```(````1P```````*``````!``,(``````$``#E#@````0``R``````*``" +M(%$````D````40````0(`$4/````"```H$L````$``#E90````0``.5F```` +M"````%(````$`\REM`````0%0R``````!``"(``````P3,S@7@````0()T5E +M````,````%X````$"`!%9`````0``.5F````"````%4````0`(`@80````0` +M("``````!``;`/\````0`0``9`````0`'R``````!``<`/\````,```````` +M`#````!R````"````%4````$``#E=@````0``.5W````!```Y0X````$``#E +M#P````0!0*``````&````&D```#"`,#E^0````@```!I````!``4Y0X````$ +M`$#E#P````@`P`!L````!```Y7`````$``#E<0````P``.5R````!```H``` +M```$`4"@``````0``.5H````!``,(``````8````=@````0`"P``````!!C` +MY6(````(````>`````@`P`!W````!``'`,<````X````@`````0``.6[```` +M````Y;P````$``"@``````0``.@A````````Z``````$``#H(0```````.@N +M````!`+,H``````$`!0```````0`#.',````!`4-X$````````` +M`0````0`!P#$``````@`XY0```````````````0``.C$````!```Z,4````$ +M``#HQ@````0``.DH````!```Z2D````$``#I*@````@```#(````!```Z2@` +M```$``#I*0````0``.DJ````"````,\````$`L`@``````0`!@``````-``` +M`-<````(````U`````0``(```````,``X``````$``#AS`````0%`.'-```` +M!``,H``````T````W@````@```#:````````H``````$`!GAS`````0`&P`! +M````!`4`H``````$"`!!S0````0`#*``````-````/L````(````2@`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````!``,(``````$ +M`!T`&`````0`&@`!````-````/L````(````2@````@%`*!*```````````` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R520_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R520_cp.bin.uu new file mode 100644 index 00000000000..e703f7cc894 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R520_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 R520_cp.bin +M`````$(`X```````0`#@``````@```"9````"````)T`````2E5+2@````!* +M2D1G`````%52;W4`````2GY]90````#@VN;V`````$K%2DH`````R(*"@@`` +M``"_2L_!`````(>P2M4`````M8.#@P````!*#X6Z````!``,H``````X``T` +M$@````0``.BT````.``-`!0````$``#HM@```#@`#0`6````!```Z%0````X +M``T`&`````0``.A5````.``-`!H````$``#H5@```#@`#0`<````!```Z%<` +M```X``T`'@````0``.@D````.``-`"`````$``#H)0```#@`#0`B````!``` +MZ#`````X``T`)`````0``/#`````.``-`"8````$``#PP0```#@`#0`H```` +M!```X``````X``T`*@````0``.``````.``-`"P````$``#@`````#@`#0`N +M````!```X``````X``T`,`````0``.``````.``-`#(````$``#Q@````#@` +M#0`T````!```\Y,````X``T`-@````0``/.*````.``-`#@````$``#SC@`` +M``0``.@A````!`%`H``````8````0P````0`S.@`````!``;``$````$"`!( +M``````0`&P`!````!`@`2``````$`!L``0````0(`$@`````"````#H````` +M``"@``````0@`$4=````!```Y8`````$``SE@0````0(`$6`````!``,Y8$` +M```(````1P```````*``````!``,(``````$``#E#@````0``R``````*``" +M(%$````D````40````0(`$4/````"```H$L````$``#E90````0``.5F```` +M"````%(````$`\REM`````0%0R``````!``"(``````P3,S@7@````0()T5E +M````,````%X````$"`!%9`````0``.5F````"````%4````0`(`@80````0` +M("``````!``;`/\````0`0``9`````0`'R``````!``<`/\````,```````` +M`#````!R````"````%4````$``#E=@````0``.5W````!```Y0X````$``#E +M#P````0!0*``````&````&D```#"`,#E^0````@```!I````!``4Y0X````$ +M`$#E#P````@`P`!L````!```Y7`````$``#E<0````P``.5R````!```H``` +M```$`4"@``````0``.5H````!``,(``````8````=@````0`"P``````!!C` +MY6(````(````>`````@`P`!W````!``'`,<````X````@`````0``.6[```` +M````Y;P````$``"@``````0``.@A````````Z``````$``#H(0```````.@N +M````!`+,H``````$`!0```````0`#.',````!`4-X$````````` +M`0````0`!P#$``````@`XY0```````````````0``.C$````!```Z,4````$ +M``#HQ@````0``.DH````!```Z2D````$``#I*@````@```#(````!```Z2@` +M```$``#I*0````0``.DJ````"````,\`````WJV^[P````````$6````!``' +M`-,````$"`!0YP````0`!P#4````!`@`0!P```````#@'0````0"P"`````` +M!``&```````T````W@````@```#;````!```@```````P`#@``````0``.', +M````!`4`X',````!``;``$````$!0"@``````0(`$'-````!``,H``````T````^P`` +M``@```!*```````````````````````````````````````````````````` +M````````````````````````````````````````````````!``,(``````$ +M`!T`&`````0`&@`!````-````/L````(````2@````@%`*!*```````````` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R600_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R600_me.bin.uu new file mode 100644 index 00000000000..a43b5fbfe18 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R600_me.bin.uu @@ -0,0 +1,481 @@ +begin 644 R600_me.bin +M`````,`@!`````````````"@``H```````#__P`H1B$``````````-D`2``` +M`````````,`@!`````````````"@``H```````````#@``````````$``,`I +M1B```````````-D`2````````````,`@!`````````````"@``H`````@0`` +M```@1!$``````````0`@2!$```````0@!`!@1!$```84``````!@``````6R +M``````!@``````7%`````,`@"``````````/```H%B(`````````"``A%B4` +M````````(``@-B4`````C0`````@1!$`````````!``O`B4```````````S@ +M```````8`$$@``!`2!$````9`$(@```@2!$`````C@`````@1!$````````` +M,0`@2BT`````D``````@1!$````````````@2`4`````````#``A%B(````` +M`````P`H%B4`````````&0`A&B(`````````!``H&B8````````````I%,4` +M````````(0`@-B4````````````Z%`(`````````%@`A%B4``````````P`H +M%B4`````````'0`@#BT`````_____``H#B,````````````I%*,````````` +M'0`@-B4```````"````H#B(`````````!P`B#B,````````````I.&X````` +M(``````H#B(`````````!@`A#B,````````````I.&X````````````B`B(` +M`````````!3@```````X`````"[@```````U`````"S@```````W``````!` +M#BT````Y````"``@#BT`````````"0!`$BT```!&`````0!`#BT````Y```` +M`,`@#````````#___``H$B,``````````@`B$B0`````````'P`A'B,````` +M`````!3@```````^````"`!`'!$```!!````#0`@'BT`````````#P`H'B<` +M`````````P`B'B<`````?\`````H&B,`````````%``A&B8``````````0`S +M&B8`````````"``B&B8````````````I#,<`````````,``@-B0```````!_ +M```H$B$````````4```O`B0```````````S@``````!+`````0`I#B,````` +M````$``@-B,```````#@```@1!$`````__@````I2B,````````````Z+`(` +M`````````@`B#BL`````_``````H#B,`````````$0`@-B,````````?_P`I +M2B,`````````,``@2BT````````````@2!$`````````,@`@#BT`````!@H" +M```I2B,````````````@2!$````````````@2!$``````````0`A`B(````` +M`````!3@``````!A`````"[@``````!?`````"S@``````!>``````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````+0`@%BT````````````O`*,```````````S````` +M``"`````+@`@%BT````````````O`*0```````````S```````"!``````!` +M``````"'````+0`@-B,`````````+@`@-B0`````````'0`@'BT````````` +M`@`A`B<``````````!3@``````"'``````!@``````7M``````!@``````7A +M`````@`A#B(``````````!3```````"*````&,!`-B````"0`````"[@```` +M``".`````"S@``````"-`````@!`#BT```"/`````P!`#BT```"/````#``@ +M#BT`````````&``@-B,``````````P`A#B(``````````!3```````"5``"@ +M#``@1!$``````````,`@2````````````,!`2`````"=``"@#``@1!$````` +M```````@2!$``````````"[@``````";`````"S@``````":`````@!`#BT` +M``"<`````P!`#BT```"<````#``@#BT````````````@2`,````````````Z +M#`(``````#\````H#B,`````````$``A#B,`````````$P`@-B,````````` +M'@`A`BL``````````!3```````"D````',`@-B``````````'P`A`BL````` +M`````!3```````"G````&\`@-B``````````"``A#BL`````````?P`H#B,` +M```````````O`B,```````````S@``````#;`````"<```````````````!@ +M``````*,@0`````@1!$`````````!@`@2!$`````````#``B'C``````F8`` +M```@1!$`````````!``@$BT`````````"``B$B0`````````$``@&!$````` +M```````I'.0```````````!@2`<```$HFP`````@1!$````````````@2`(` +M````G``````@1!$````````````S%&\``````````0`S/B,``````````-D` +M2``````````````@/`4`````@0`````@1!$`````````#@`@2!$````````` +M```@$!````````#@!P`@1!$`````````#P`A`BL``````````!3```````#% +M`/C_"``@2!$`````F`````!`2!$```#6````\``H#B(`````````H``O`B,` +M``````````S```````#4````$P`@#BT``````````0`O`B,```````````S@ +M``````#/`````@`O`B,```````````S@``````#.```_``!`#!$```#0```? +M``!`#!$```#0```/```@#!$``````#@`"0`I2B,`````/P`````H#BL````` +M`````@`B#B,`````````!P!)2B,```#6`#@/"0`@2!$`````:```!P`@2!$` +M````````"``A2B<````````````@2!$`````!@H"```I2B0````````````@ +M2!$````````````@2!$```````"B`@`@1!$``````/\````H2B(````````` +M,``@#BT`````````+@`@$BT````````````O`(,```````````S@``````#C +M``````!@``````7G``````!```````#D``````!@``````7J````!P`@(BT` +M````````!0`B#B(``````!`````H#B,````````````I(&@````````````Z +M#`(`````````[P`H#B,````````````I(&@`````````'0`@#BT````````` +M`P`A`B,``````````!3@``````#Q````"P`A`B@``````````!3```````#Q +M```$```I(B@`````````&@`@-B@`````````'``A#B(``````````!3````` +M``#V``"C#``@1!$````````````@2!$`````````'@`A#B(``````````!3` +M``````$$``"C#P`@1!$`````````$P`@#BT``````````0`O`B,````````` +M``S```````#]_____P!`2!$```$$`````@`O`B,```````````S```````$` +M``#__P!`2!$```$$````!``O`B,```````````S```````$#````_P!`2!$` +M``$$`````0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3` +M``````$+````$$`A#B``````````&0`@-B,`````````&$`B2B`````````` +M$,!"2B````$-```````@#!$`````````&0`@-B,````````````@2!$````` +M```````@2!$`````````"@`@$!$````````````O`B0```````````S@```` +M``$4```````@2!$``````````0!3$B0```$0_[___P`H.BX`````````&P`A +M`B(``````````!3```````$G@0`````@1!$`````````#0`@2!$````````` +M&``B#C``````_``````H#B,`````@0`````@1!$`````````#@`@2!$````` +M```````@$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,` +M````````)``@'BT`````````"``A2B<````````````@2!$`````!@H"```I +M2B0````````````@2!$````````````@2!$```````````"`````````@0`` +M```@1!$``````````0`@2!$````````A?``@1!$``````(`````@2!$````` +M```````@2`8`````````"``A2B<``````````!<```````````0A?P!@1!$` +M``84````'P`A`C```````````!3```````83````!`!`3!$```$N``````!@ +M```````+``````!@!!$```+^```````@!!$```````````!@"!$```&?```` +M``!@``````%1``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*D``&A_0!@1!$` +M``+)```__P`O`B\```````````S```````$X`````,!`!``````!``````!@ +M```````+``````!@!!$```+^```````@!!$```````````!@"!$```&?```_ +M_P`O`B\```````````S@``````````````!@``````%1````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*D``&A_0!@1!$` +M``+)```__P`O`B\```````````S```````%)`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````%\``````!@``````&-```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&) +M``````!@``````*D`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*,E0`````@1!$````````````O +M`B$```````````S@``````%S`````,`@2````````````0!3!B$```%OD@`` +M```@1!$``````````,!@2`````&$``&A_0`@1!$`````````$P`@!BT````` +M``````!X!"H```+D```````@*`D````````__P`O`B\```````````S````` +M``%E`````,!`!``````!```"$`!@!!$```+^```__P`O`B\```````````S@ +M``````&!````&\`@-B``````````',`@-B``````/X`````@!!$`````1@`` +M``!@"!$```&?``````"```````````"A_``@1!$````````__P`O`B\````` +M``````S```````&(`````0"`2!$`````````(0"`2!$```````#__T`H#B`` +M````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`````@ +M1!$`````````!@`@2!$`````````"``B'C``````````,@`@&BT```````#@ +M```@1!$`````__O_"0`@2!$`````````$0`@(BT````````?_P`I2B@````` +M````!@`@(BT````````````I(.@````````````@2`@````````````@2!$` +M````!@H"```I2B8````````````@2!$````````````@2!$````````!```@ +M&!$`````````"`!B'B@```$H````"`""(B@```````+````@1!$````````` +M&P!@#BT```&J````'`!@#BT```&J``#`"``@1!$`````````'0`@#BT````` +M`````!3```````&F```````@!!$````````````@2`$`````.0`````@2!$` +M```````````@2!$```````````"`2`(`````````(``@+BT````````````[ +M#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````````` +M``"`2`,```````````!@```````+```0``!@!!$```+^```````@!!$````` +M``````!@"!$```&?````!P`A!B\`````````&0`@"BT``````````0`@+!$` +M``````#__T`H(B``````````#P`F(B@`````````$$`A)B``````````#P`F +M)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````````` +M```O`B$```````````S@``````'-```B7``@1!$`````````@0`@2!$````` +M``"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O`B<` +M``````````S@``````')``````!@``````'6`````0!3'B<```'%`````0`@ +M+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```&^```B +M7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$````` +M`````0`P'B\````````````O`B<```````````S@``````````````!@```` +M``'6`````0!3'B<```'2``#__T`H#B``````````#P`F#B,`````````$,`A +M$B``````````#P`F$B0````````````@%!$```````````!@&!$```*D``&A +M_0`@1!$````````````O`BL```````````S@``````'E````$``B%B@````` +M__\````H%B4```````#__P`H&BD````````````I2,4````````````@2`H` +M```````````@+!$`````````$``B%B,`````__\````H%B4```````#__P`H +M&B0````````````I2,4```````````!S%0,```'R```````@&`4````````` +M``!S%20```'R```````M%,4````````````P"*(````````````@2`(````` +M```````@*`(````````````@(`,```````````"`)`0`````````#P`A`B4` +M`````````!3```````83```````K%`4``````````0"0%B4```````````!@ +M```````+``````!@!!$```+^```````@!!$```````````!@"!$```&?```B +M5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\````` +M``````S@`````````````,`@!``````````B7``@1!$``````````P`X2B$` +M``````"A_``@1!$``````````0`@2!$```````#__T`H$B``````````$,`A +M&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*D``&A +M_0!@1!$```+)`````0`S!B$````````````O`B$```````````S```````(& +M```__P`O`B\```````````S```````'_`````,!`!``````!``````!@```` +M``7%``````!`!`\```(```````!@``````6R``````!@``````7%```"$`!@ +M!!$```+^``````!@``````&-``````!@``````&)``````!@``````*D```` +M``!@``````*,DX`````@1!$````````````@2`@`````E0`````@1!$````` +M```````O`B\```````````S@``````(?`````,!`2`````(````%P!`2!$```)?````&0`@2!$```````"A_``@ +M1!$``````````0`@2!$```````&A_0!@1!$```+2```__P`O`B\````````` +M``S```````(_`````,!`!``````!````$$`A!B````````#__\`H"B`````` +M````$$`A#B````````#__\`H$B``````````$$`A%B````````#__\"(&B`` +M````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```84``````!@ +M``````6R`````,!@``````*,````!0`@"BT`````````"``B"B(````````` +M-``@&BT`````````)``@'BT```````!P```H'B<````````````Q'.8````` +M````,P`@&BT`````````#``B&B8````````````O`.8```````````;@```` +M``)[```````@'!$````````````@#!$`````````-``@-B,`````````$``@ +M&!$```````````!I'.(```$HDX`````@1!$````````````@2`<`````E0`` +M```@1!$````````````O`B\```````````S@``````*&`````0`S/B\````` +M`````-D`2```````D@`````@1!$``````````,`@2```````````)`!`-B<` +M````````#,`B"B``````````,@`@-B(`````````, +M``````!```````+'``````!@``````*>``````!@``````7D``````!````` +M``+'``````!@``````*0``````!```````+'````(@`@'BT`````````(P"` +M(BT`````````$``B'B,````````````I2(<````````````Q'*,````````` +M$``B'B<````````````I2(<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@```````````")20<`````````$``B'B,````````````I2(<` +M````````$``B'B$````````````I2$<````````````Q'*,`````````$``B +M'B<````````````I2(<````````````Q'*$`````````$``B'B<````````` +M```I2$<`````````$``B'B,````````````Q(,0```````#__P`H(B@````` +M```````I20<`````````$``B'B$````````````Q(,(```````#__P`H(B@` +M``````````")20<`````````$``B'B,````````````I2(<``````````0`B +M"B$````````````S"*(`````````$``B'B(`````````$``A(B(````````` +M```I20<````````````Q'*,`````````$``B'B<````````````I2(<````` +M`````0`B"B$````````````P"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<````````````X",4````````````P"$$````````` +M`0`B"B(````````````S"*(`````````$``B'B(`````````$``A(B(````` +M``````")20<`````````'0`@(BT``````````!3```````,!____[P`H!B$` +M````````&@`@(BT```````#XX``@1!$````````````I20$```````````") +M20$````````````@2!$````````````@2!$`````!@H"``"`2!$````````` +M`,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@1!$````` +M```````@2!$````````B7``@1!$``````````,`@2`````````"A_``@1!$` +M`````````,`@2````````````,`@!`````````````"@``H`````EP`````@ +M1!$````````````@2!$`````B@`````@1!$````````````@2!$````````B +M7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@2``````` +M`````,`@!`````````````"@``H`````EP`````@1!$````````````@2!$` +M````B@`````@1!$````````````@2!$````````B7``@1!$``````````,`@ +M2`````````"A_``@1!$``````````,`@2`````````&A_0`@1!$````````` +M`-D`2````````````,`@!`````````````"@``H````````B5P`@1!$````` +M`````\!(2B`````````B70`@1!$``````````,!`2`````````````!@```` +M``7%`````,`@"``````````B7``@1!$``````````P`X2B(```````"A_``@ +M1!$``````````,`@2`````````&A_0`@1!$````````````O`B(````````` +M``S@`````````````$`@2````````````4`P2B```````````L`P2B`````` +M`````0!3"B(```,T````/\`H"B``````@0`````@1!$``````````0`@2!$` +M```````A^``@1!$`````````%P`@2!$```````0A^0!@1!$```84````$0`A +M`C```````````!3@``````,]````%``O`B(```````````S```````-1```@ +M$``@1!$```````"````@2!$```````&BI``@1!$````````````@2!$````` +M````%@!@2!$```->```A```@1!$``````````,`@2````````````,`@2``` +M`````````,`@2````````````,`@2`````````&BI``@1!$````````````@ +M2!$```````````!`2`(`````````!``O`B(```````````S```````-5```@ +M$``@1!$```````"```!`2!$```-)````*``O`B(```````````S@``````-) +M```A!``@1!$``````````,`@2````````````,`@2````````````,`@2``` +M`````````,`@2`````````"BI``@1!$```````````!`2`(`````````-0`@ +M-B8`````````20`@&!$````````````@2!$``````````0`S&B8````````` +M```O`B8```````````S```````-@````-0"`&BT`````````/\`H"B`````` +M````%0`O`B(```````````S@``````-V````'@`O`B(```````````S@```` +M``.`````(``O`B(```````````S@``````.,````#P`O`B(```````````S@ +M``````.8````$``O`B(```````````S@``````.8````!@`O`B(````````` +M``S@``````.:````%@`O`B(```````````S@``````.?``"BI``@1!$````` +M``````!`2`(`````"``````I"B(``````````T`A#B``````````#,`A$B`` +M``````@````H$B0`````````%,`B%B`````````````I%*0```````"BI``@ +M1!$````````````I2*(```````"A_@`@1!$```````````!`2`,`````@0`` +M```@1!$``````````0`@2!$````````A^``@1!$`````````%0`@2!$````` +M``0A^0!@1!$```84````%0`A`C```````````!3@``````."```A#@`@1!$` +M`````````,`@2````````````,`@2`````````"BI``@1!$```````````!` +M2`(`````@0`````@1!$``````````0`@2!$````````A^``@1!$````````` +M%@`@2!$```````0A^0!@1!$```84`````P`A`C```````````!3@``````.. +M```A"``@1!$``````````,`@2````````````,`@2`````````"BI``@1!$` +M``````````!`2`(````````@$``@1!$```````"```!`2!$````````@$``@ +M1!$```````"````@2!$```````&BI``@1!$````````````@2!$````````` +M!@!`2!$````````@$``@1!$```````"````@2!$```````&BI``@1!$````` +M```````@2!$`````````%@!@2!$```->````%@!`2!$``````````,`@"``` +M`````````,`@#```````````'0`A`B,``````````!3@``````.Y@0`````@ +M1!$``````````0`@2!$````````A^``@1!$`````````%P`@2!$```````0A +M^0!@1!$```84````$0`A`C```````````!3@``````.K```A```@1!$````` +M```````@2`(````````````@2`,`````NK[*_@`@2!$`````ROZZO@`@2!$` +M```````@$``@1!$```````"````@2!$```````"BI``@1!$`````````!`!` +M2!$````````A<``@1!$````````````@2`(````````````@2`,`````@0`` +M```@1!$`````````"@`@2!$````````````@`!```````````!3```````.^ +MC``````@1!$`````ROZZO@!`2!$`````@0`````@1!$``````````0`@2!$` +M```````__T`H"B``````@````$`H#B``````0````,`H$B````````0```!I +M1B(```84```````@%!`````````````O`B,```````````S```````/,```` +M`,!`&`````//```__\`H&B````````0```!I1B8```84```````@&!`````` +M```````O`B0```````````S```````/2`````,!`'`````/5```__\`H'B`` +M``````0```!I1B<```84```````@'!`````````````@1`(````````````H +M(,4```````````!)2.@`````I8`````@"!$````````@```@#!$`````@P`` +M``!@1!$```/]```````@1`(``````````,`@2````````````$`@2``````` +M````'\`A`B```````````!3```````/B```@$``@1!$```````"````@2!$` +M``````#__\!($B````/JIX`````@"!$```````"@```@#!$`````@P````!@ +M1!$```/]```````@1`(``````````,`@2````````````,`@2`````````#_ +M_\`H$B``````@P`````@1!$````````````P2(,`````A``````@1!$````` +M`````,`@2````````````!T`````````@P````!@1!$```/]`````,!`!``` +M```!J8`````@"!$```````#```!`#!$```/EJX`````@"!$```````#XX`!` +M#!$```/EK8`````@"!$```````#X@`!`#!$```/ELX`````@"!$```````#S +M_`!`#!$```/EKX`````@"!$```````#@``!`#!$```/EL8`````@"!$````` +M``#P``!`#!$```/E@P`````@1!$````````A2``@2!$`````A``````@1!$` +M`````````,`@2````````````!T```````````````"``````````!@@`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H``````!B@ +M`,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M`!C``,`P1B```````````-D`2````````````,`@!`````````````"@``H` +M`````!CXX,`P1B```````````-D`2````````````,`@!`````````````"@ +M``H``````!CX@,`P1B```````````-D`2````````````,`@!``````````` +M``"@``H``````!C@`,`P1B```````````-D`2````````````,`@!``````` +M``````"@``H``````!CP`,`P1B```````````-D`2````````````,`@!``` +M``````````"@``H``````!CS_,`P1B```````````-D`2````````````,`@ +M!`````````````"@``H`````A@`````@1!$```````````!`2`$`````A0`` +M```@1!$```````````!`2`$````````A?``@1!$``````````,`@2``````` +M`````,`@2````````````,`@2```````@0`````@1!$``````````0`@2!$` +M`````````,`@"````````````!<```````````0A?P!@1!$```84````'P`A +M`C```````````!3```````````````!`3`(```0N`````,`@#``````````` +M`,`@$````````````,`@%````````````,`@&````````````,`@'``````` +M``!_```H"B$```````!%```O`B(```````````S@``````0\`````,`@(``` +M`````````!<`````````````$``H"B,`````````$``O`B(```````````S@ +M``````1$@0`````@1!$``````````0`@2!$```````0```!I1B0```84```` +M``!```````1-@0`````@1!$````````````@2!$````````A;0`@1!$````` +M```````@2`0````````````@2`4``````````!K```````1)G@`````@1!$` +M````ROZZO@`@2!$``````````!K@``````1,```````H)/``````````!P`H +M"B,``````````0`O`B(```````````K@``````14```````O`,D````````` +M``3@``````1M``````!```````1Z`````@`O`B(```````````K@``````19 +M```````O`,D```````````+@``````1M``````!```````1Z`````P`O`B(` +M``````````K@``````1>```````O`,D```````````S@``````1M``````!` +M``````1Z````!``O`B(```````````K@``````1C```````O`,D````````` +M``K@``````1M``````!```````1Z````!0`O`B(```````````K@``````1H +M```````O`,D```````````;@``````1M``````!```````1Z````!@`O`B(` +M``````````K@``````1M```````O`,D```````````C@``````1M``````!` +M``````1Z``!_```H"B$```````!%```O`B(```````````K@```````````` +M"``A"B,``````````!3```````1W```A:0`@1!$``````````,`@2``````` +M`````,`@2````````````,`@2```````ROZZO@!`2!$``````````,`@1``` +M`````````,`@`````````````,!`2`````````!_```H"B$```````!%```O +M`B(```````````K@``````2``````,`@`````````````,`@```````````` +M`,!```````````````!`3`@```0\`````,`@"```````````$$`A#B`````` +M````$4`A$B``````````$D`A%B`````````A:0`@1!$````````````@2`(` +M```````````A`B4``````````!3@``````2*``0``,!)2B````2+__O__\`H +M2B`````````````A`B,``````````!3@``````27`````,`@2``````````` +M`,`@2``````````````A`B0``````````!3`````````@0`````@1!$````` +M````#``@2!$````````````@`!```````````!3```````23H``````@1!$` +M````ROZZO@!`2!$`````@0`````@1!$`````````!``@2!$````````A:P`@ +M1!$``````````,`@2!``````@0`````@1!$`````````!0`@2!$````````A +M;``@1!$``````````,`@2!`````````````O`B0```````````S@```````` +M``````!```````21`````,`A"B```````````!3```````2N@0`````@1!$` +M```````````@2!$````````A;0`@1!$``````````,`@2````````````,`@ +M2````````````!K```````2IG@`````@1!$`````ROZZO@`@2!$````````` +M`!K@``````2L``````!```````2R@0`````@1!$``````````0`@2!$````` +M``0``,`I1B```````````,!@``````84`````0`A`B(``````````!3````` +M``2Y```A:0`@1!$``````````,`@2````````````,`@2``````````````@ +M2!``````ROZZO@!`2!$``````````,`@1````````````,!`2!``````@0`` +M```@1!$``````````0`@2!$````````A^``@1!$`````````#0`@2!$````` +M``0A^0!@1!$```84```````A`C```````````!3```````2[```A@``@1!$` +M`````````,`@2````````````,`@`````````````,`@2````````````,`@ +M`````````````,!`2````````````P`S/B\``````````0`A`B$````````` +M`!3@``````3K````-0`@"BT```````0``!C@#!$```3:`````0`S/B\````` +M```A:0`@1!$````````````@2`(````````````@2`,`````````"``P"B(` +M`````````,`@2````````````,`@2``````````A:0`@1!$````````````@ +M2`(````````````@2`,`````````"``P"B(``````````,`@2``````````` +M`-C`2`````3.```A:0`@1!$````````````@2`(````````````@2`,````` +M````"``P"B(``````````,`@2````````````,`@2```````````-@`@$BT` +M```````````I#(,````````A:0`@1!$````````````@2`(````````````@ +M2`,`````````"``P"B(``````````,`@2````````````,`@2``````````` +M$0`A`B0``````````!3```````````````!```````21````-<`@-B`````` +M````-L!`-B`````````P2@`@1!$`````X````,!(2B``````````#P`A`B$` +M`````````!3```````3R``````!@```````+`````-D``````````````,!` +M!``````!@0`````@1!$``````````@`@2!$`````````_P`H#C`````````` +M```O`B,```````````S```````3V`````,`@"````````````!3```````4+ +M```````@#!$`````````)``@-B,`````````-``@-B,`````````,@`@-B,` +M````````,0`@-B,`````````'0`@-B,`````````+0`@-B,`````````+@`@ +M-B,`````````&P`@-B,`````````'``@-B,`````___@```@#!$````````` +M*0`@-B,`````````*@`@-B,````````?_P`@#!$`````````*P`@-B,````` +M````+``@-B,`````\?___P`H.BX`````````&L`B#B`````````````I.&X` +M````@0`````@1!$`````````!@`@2!$`````````,T`@-B``````AP`````@ +M1!$``````````,`@2`````````"A]``@1!$````````````@2!``````G0`` +M```@1!$`````````'T`A2B``````E@`````@1!$``````````,`@2``````` +M`````,`@#````````````,`@$```````````'P`A%B0``````````!3````` +M````````)0`@-B,``````````P`H'B,`````````"``B(B,`````___P```H +M(B@````````````I(.@`````````)P`@-B@`````````&``A'B,````````` +M*``@-B<``````````@`B%B0````````````P%*@`````````)@`@-B4````` +M`````P`A&B0`````$``````H&B8`````[____P`H.BX```````````!).,X` +M``8"`````4`H"B``````````!D`H#B`````````#`,`H$B``````````"``A +M$B0``````````,`@%B```````````,`@&B`````````````A`B(````````` +M`!3```````5!@0`````@1!$``````````0`@2!$````````B6``P"B0````` +M``0```!I1B(```84```A:0`@1!$````````````@2`4```````(````I2B8` +M```````````@2!``````ROZZO@`@2!$``````````@`O`B,```````````S` +M``````5)`````,`@'!```````````,!```````5;`````@`O`B,````````` +M``S```````5)@0`````@1!$``````````0`@2!$````````B6``P"B0````` +M``0```!I1B(```84`````,`@'!```````````,!```````5;```````O`B,` +M``````````S```````5-`````,`@'````````````,!```````5;````!``O +M`B,```````````S```````59@0`````@1!$````````````@2!$````````A +M;0`@1!$``````````,`@2````````````,`@2````````````!K```````54 +MG@`````@1!$`````ROZZO@`@2!$``````````!K@``````57``````!`'!`` +M``5;`````,`@`````````````,!```````````````[@``````5=``````!@ +M``````6D```````O`B0```````````S```````5M``"BMP`@1!$````````` +M```@2`<`````@0`````@1!$``````````0`@2!$```````2BM@!@1!$```84 +M````&@`A(C``````````!@`B)C````````"BQ``@1!$````````````P2.D` +M``````````#@``````5K``"BT0`@1!$```````````!`2`@```````"BT0`@ +M1!$``````````0!02B@``````````0`O`B0```````````S```````5]``"B +MNP`@1!$````````````@2`<`````@0`````@1!$``````````0`@2!$````` +M``2BN@!@1!$```84````&@`A(C``````````!@`B)C````````"BQ0`@1!$` +M```````````P2.D```````````#@``````5[``"BT@`@1!$```````````!` +M2`@```````"BT@`@1!$``````````0!02B@``````````@`O`B0````````` +M``S```````6-``"BOP`@1!$````````````@2`<`````@0`````@1!$````` +M`````0`@2!$```````2BO@!@1!$```84````&@`A(C``````````!@`B)C`` +M``````"BQ@`@1!$````````````P2.D```````````#@``````6+``"BTP`@ +M1!$```````````!`2`@```````"BTP`@1!$``````````0!02B@```````"B +MPP`@1!$````````````@2`<`````@0`````@1!$``````````0`@2!$````` +M``2BP@!@1!$```84````&@`A(C``````````!@`B)C````````"BQP`@1!$` +M```````````P2.D```````````#@``````69``"BU``@1!$```````````!` +M2`@```````"BU``@1!$``````````0!02B@`````A0`````@1!$````````` +M```@2`$````````P2@`@1!$``````0`````@2!$```````````!```````6? +MI````,`@1!$``````````,!`2````````````,!@``````6D`````,!`!``` +M```!``&BI``@1!$````````````@2!$````````````@2!$````````````@ +M2!$````````````@2!$`````````!0`@2!$```````"A]``@1!$````````` +M```@2!$`````B``````@1!$``````````0`@2!$`````_P`````@1!$````` +M```````@2!$``````````0`@2!$``````````@"`2!$```````````[@```` +M``6W```0```@"!$`````````-``@-B(```````````!@``````6[``````!@ +M``````6DF``````@1!$```````````"`2!$``````````,!@``````6[```` +M`,!`!``````!``"BI``@1!$`````````(@`@2!$`````B0`````@1!$````` +M`````0`@2!$`````_P`````@1!$````````````@2!$``````````0`@2!$` +M`````````@"`2!$````````A>L`@1!$```````````!`2!$`````EP`````@ +M1!$````````````@2!$`````B@`````@1!$````````````@2!$`````_P`` +M```@1!$````````````@2!$``````````0`@2!$``````````@"`2!$````` +M``````!@``````7A```@$``@1!$```````"````@2!$```````&BI,`@1!$` +M```````````@2!$`````````%@!@2!$```->````%@`@2!$````````@$``@ +M1!$```````$````@2!$`````@0`````@1!$``````````0`@2!$````````A +M?``@1!$`````"8`````@2!$`````_____P`@2!$````````````@2!$````` +M`````!<```````````0A?P!@1!$```84````'P`A`C```````````!3````` +M````````!`!`3!$```7<````'0`@'BT`````````!``I'B<`````````'0"` +M-B<`````````'0`@'BT`````____^P`H'B<`````````'0"`-B<````````` +M'0`@'BT`````````"``I'B<`````````'0"`-B<`````````'0`@'BT````` +M____]P`H'B<`````````'0"`-B<````````@$``@1!$```````"````@2!$` +M``````&BI``@1!$````````````@2!$`````````%@!@2!$```->````%@`@ +M2!$````````@$``@1!$```````$````@2!$````````A?``@1!$``````8`` +M```@2!$``````/___P`@2!$````````````@2!$``````````!<````````` +M@0`````@1!$``````````0`@2!$```````0A?P!@1!$```84```````@`!`` +M`````````!3```````83````$`!`3!$```7Y`````,`@!````````````#C` +M````````````)0`@"BT`````````)@`@#BT`````````)P`@$BT````````` +M*``@%BT````````A:0`@1!$````````````@2`0````````````@2`4````` +M```````@2`$`````ROZZO@`@2!$`````````!``P$B0````````````O`&0` +M``````````S```````82`````P`H&B(`````````"``B$B(`````___P```H +M$B0````````````I$,0`````````)P!`-B0```````````"````````````` +M`!K```````84GP`````@1!$`````ROZZO@`@2!$``````````!K@``````87 +M``````"```````````````!@```````+```0``!@!!$```+^```````@!!$` +M``````````!@"!$```&?```B7``@1!$``````````P`@2!$````````B5@`@ +M1!$`````````&P`@2!$```````"A_``@1!$``````````0`@2!$```````&A +M_<`@1!$`````````*0`@'BT`````````$``B'B<`````````+``@(BT````` +M``#__P`H(B@````````````I20<````````````@2!$`````````*@`@(BT` +M``````#__P`H(B@````````````I20<````````````@2!$`````````*P`@ +M'BT`````````$``B'B<````````````I20<```````````!`2!$````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````3,$[P6;`CD``````;`!600E!9L``````A(! +M]@(Y`4(``````A`"+@*)`BH``````\(%FP6;!9L`````!`,H$``"@```` +M?H*+`,08.`#*)```RB@``)6!J`#$'#H`P\```,H(``#*#```?'1+`,(`!0"9 +MP```Q!PZ`'QT3`#`__``!"P$`#"0`@!])0``-10"`'TU"P`E5`,`?-6``"6< +M`P"5P`0`U0`;`'[=P0!]G8``UH`;`-6`&P#40!X`U4`>`-9`'@#6@!X`U(`> +M`-3`'@"7@]0`U<`>`,H(``"``!L`R@P``.0!'@#4`!X`@``-`,08.`#D`3X` +MU``>`(``#0#$&#@`U$`>`.X`'@#*!```H````'Z"BP#D`1X`U``>`-1`'@#N +M`!X`R@0``*````!^@HL`Y`$^`-0`'@#40!X`[@`>`,H$``"@````?H*+`,H8 +M``#40!X`U8`>`(``5`#4`',`U$`>`,H(``#*#```RA```-2`&0#4P!@`U0`7 +M`-2`'@#4P!X`U0`>`.(`'@#*!```H````'Z"BP#*"```U(!@`-1`'@"```(` +MU(`>`,H(``#4@&$`U$`>`(```@#4@!X`R@@``,H,``#40!X`U(`6`-3`%@#4 +M@!X`@`&Y`-3`'@#&"#X`R@P``,H0``"4@`0`RA0``.0@\P#4(!,`U6!E`-3@ +M'`#5(!P`U6`<`(```@`&(`$`Q@@^`,H,``#*$```E(/W`,H4``#D(/,`@`!Z +M`-0@$P#&"#X`R@P``,H0``"8@^\`RA0``-0`9`"``(X``````,04,@#&&#X` +MQ`@O`)5`!0#$##``U$`>`(```@#N`!X`E8/U`,00,0#40#,`U2!E`-2@'`#4 +MX!P`U2`<`-0``(`!N0`&(`$`"B`!`-8`=`#$"#8`QA!``)B` +M!P#,.#4`E0$/`-0`'P#48&(`@``"`-0@8@#,%#,`A`&\`-0`<`#50!X`@``" +M`.X`'@#*#```RA```-3`&@"$`;P`U0`:`,P$0P`U$!\`+)0!`'T)BP"80`4` +M?17+`-0`&@"``;D`U`!M`#1$`0#,#$0`F$`Z`,PL1@"5@`0`S`1%`(`!N0#4 +M`!H`U,`:`"@H`0"$`/,`S!`#`)B`&P`$.`P`A`#S`,P0`P"8@!<`!#@(`(0` +M\P#,$`,`F(`3``0X!`"$`/,`S!`#`)B`%`#,$$<`FH`)`,P42`"80-H`U`!M +M`,P81`#5`!H`U4`:`(``S`#5@!H`EL#3`-0`;0"``;D`U`!N`)K``P#4`&T` +MU`!N`(```@#L`'\`FL#*`-0`;0"``;D`U`!N`,P4`P#,&`,`S!P#`'V1`P!] +MU8,`?1D,`#7,'P`U`.0! +M'@#4`!X`R@@``,H,``#*$```U$`>`,H4``#4@!X`U,`>`-4`'@#50!X`U4`T +M`(```@#N`!X`*`0$`.(`&@#B`!H`U$`:`,HX``#,"`,`S`P#`,P,`P#,#`,` +MF(*\``````"$`;P`UX!O`(```@#N`!\`R@0``,+_``#,"#0`P3__`'QTRP!\ +MR0L`?0$/`)D"KP!\`;P"```(`[@`?`,H(```H&0``?8F+`)6` +M%``H%`0`R@P``,H0``#*'```RB0``.(`'P#4P!H`U0`:`-5`&@#,&`,`S"P# +M`,PL`P#,+`,`?:6+`'V<1P"80I8``````(`!9`#4P!H`U$`>`-2`'@"```(` +M[@`>`.0!'@#4`!X`U$`>`.X`'@#*!```H````'Z"BP#D`3X`U``>`-1`'@#N +M`!X`R@0``*````!^@HL`R@@``"2,!@`,S`8`F,`&`,P020"9``0`U`!Q`.0! +M'@#4`!X`U$`>`-2`'@"```(`[@`>`,H(``#*#```--`8`"40`0"5`!\`P7__ +M`,H0``#*%```RA@``-2`'0#4P!T`?;&+`,%"`@#"P`$`U8`=`#3<#@!]74P` +M?W-,`-=`'@#5`!X`U4`>`,%"``#"P```"9P!`#'<$`!_7TP`?W-,`'V#@`#5 +M@&\`U8!F`-=`'@#L`%X`R"0"`(`!N0#6`'0`U$`>`-2`'@#4P!X`@``"`.X` +M'@"```(`[@`?`-0`'P"```(`U``?`-0`'P"(````U``?```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0%T``(!>P`#`)``!`"```4`!0`& +M`$``!P`S``@!+P`)`$<`"@`W`!`!MP`7`*0`(@$]`",!3``@`+4`)`$H`"<` +M3@`H`&L`*@!A`"L`4P`O`&8`,@"(`#0!@@`\`5D`/P!S`$$!CP!$`3$`50%V +M`%8!?0!@``P`80`U`&(`.0!C`#D`9``Y`&4`.0!F`#D`9P`Y`&@`.P!I`$(` +M:@!)`&L`20!L`$D`;0!)`&X`20!O`$D`0`$&`$`U8!Z`-0`=`#4`',`U``+`(0"L@`QA!\` +MA`(_`"@$`0#4``X`*"`$`,@0=`#(!#8`F$+0`"@IW@#(!'D`F$`(``````#( +M*`H`EH`%```````H*=\`@`"(`-6`#@#(*```EH`I`"@(`0#4@```#HF[`)2` +M"0#*Q`$`E0#]`#!$#`#02`0`E(#Q`"@@`0"``2H```````Z)O`"8@-P`*"`& +M`)4!^P`.B;X`E(`$``````#5@'D`@``-``Z)O0"4@`0``````-0`>0"```T` +M#HFT`)B`\0`H(`0`%HFW`)B![``>B;H`F('J```````.B;H`E(#I`"@@!``H +M(`(`@`$J``````#(*`(`EH`7`"@(`0#4@`(`E0'>`":$`0"80`,``````"@@ +M```BB<@`&HW=`'R,BP"8@-@`(HF8`!J-FP!\C(L`F(#4`"*)J``:C:L`?(R+ +M`)B`T```````@`(H``````#(*`$`EH`+`"@(`0#4@`$`E0'&``Z)Z`"8@,8` +M#HGJ`)B`Q```````@`(H``````#(*`,`EH`'``Z-Y0"8P/T`*`@!`-2``P"` +M`B@``````,@H!`"6@`D`*`@!`-2`!`"5`;(`#HGB`)B`L@``````@`(H```` +M``#(*`4`EH.3`"@(`0#4@`4`E0&H``Z)D@"8@*@`#HF4`)2!I```````@`$J +M`"@@`@"$`+T`*"`#`,K$```D1`(`E$`&``````#(!'@`U$!W`(`!+@`````` +MA`*R`#&$'P#*Q```)$0!`)A`/P``````R`1Z`-0`>@#("'T`RLP+`'R,@@"4 +M0`8``````)2`"P``````@`"G``````"4@(L``````(`"E0``````A`*R`#&$ +M'P"``I4`R`1]`,@(?P!\2$(`F$`$``````"$`K4``````,K$`0`P1`P`T$@` +M`"2(`0"8@04``````(0"!```````A`+(``````"``I4``````,@$(0`P1`@` +M*`A``,@0(@"5`TP``````-4`>`#4`'<`?`#```3,#``)$`$`F0/^``````#0 +M4```U0@```C,`0"4P`8```````1$!``$B`$`@`#*``````"(````*"Q``-6` +M=`#*Y`L`RMP"`-9`?P#60'T`-F0$`-9`"P#60"T`UP#*Q```)$00`)A#*0``````A`(W`"@$`0`,1`(`F$&8`"@%\0!]P$P` +M?<",`(0"3P``````A`(W`"@$`P`,1`(`F$&/`"@%\`"$`C<`*`0"``Q$`@"8 +M08H`*`7P`(0"-P`H!`0`#$0"`)A!A0`H!?(`A`(Y`"@$`@"$`DH``````,$! +M\``H!```V'```(``#0``````R`1Z`)A`!```````@``-``````#4`'H`R`1W +M``A$`0#40'<`A`*R`#&$'P"``IX``````,K$`0`P1`P`W`0``,@$=P`$1`$` +MU$!W``;L#`#("'@`?$B"`)2#D@``````"NP,`-6`>@"$`K(`*`0``)4!>P`` +M````@`*5``````#*Q`$`,$0,`-V$``#(!'<`!$0!`-1`=P`&[`P`A`*.```` +M``"$`CT`*`0``(0"-P`H!`$`#$0"`)1`!0``````*"`$`"@I\0``````R`1W +M`,@(>`!\2((`E(!C``````"$`F``*"`%`(0"+```````R"@*`):#_P`H(`,` +M*"G?`(0`O0`H(`,`RL0+`,@(?0!\2((`U(!S`)2`4P``````A`("``````"$ +M`C<`*`0$``Q$`@"802T`*`7R`,@$P#(#'T`?.#,`-S(``#(#"X`W,@$`,@,+P#0"$`C<`*`0!`,@(?@#( +M!'P`A`)/``````"$`C<`*`0#``Q$`@"80Y4``````(0"-P`H!`0`#$0"`)A# +MD``H!?(`*"`$`(0"8```````A`(L``````#()'\`UD!]`#9D!`#60`L`UD`M +,`(``#0#4`#8````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/R700_rlc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/R700_rlc.bin.uu new file mode 100644 index 00000000000..39dcd1585ed --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/R700_rlc.bin.uu @@ -0,0 +1,95 @@ +begin 644 R700_rlc.bin +M-#@`$#>X``#/@``2S```T\P``-T$&``!S!@`T\P``,G,&`#)S8``UT``#`,/__RXX`!#0(``0PS``/?,C` +M`IC``@L`````RXH`#$>X``1\L,`+E,`"!@````#(T0``S3H`#`>X``0HB``0 +ME(`"``````#(D0``S3H`#(```"0'N``$R>P`V<@0`,O)^``)S!P`TYG``#L` +M````A``!W0````"$``%]`````(```PS-G`#5R#``0#`__T`````B`````````"(```````` +M`(```PDT(``(P#`T`,LY``#/L0``@``#"0`````RJ`#_SH``#(@````````` +MRP@`1"2(``C,G`#7:(@`(,R<`,;,,`!'?`#`#,L4`$9E5``@RP@`17R4@"S, +MR@``A```E`````"(`````````(```$3`,`'!A``!P`````"$``%]`````(`` +M`2``````A``!P`````"$``%]`````(```PS-G`#5`````,@X`%P`V8```-/-@``.A```/P````"( +M`````````,@X``T+N``!FX#__@````"(`````````#0X``'/@``#R!``R\`P +M`<'+.0``*[@`!)N`__X`````S```R`````#("``:E(`!N9`/]6`````$2(``S,G`#7:(@`(,R<`,;,\`!'S-8``(```&$````` +MR```*J```` +M`,V<`-69P``$`````(0``=,T.```E0`!*0````"```$Y`````(0``!@````` +M@``!(`````#*\``&SQP`V\P<`-65P`(S`````,`P-`#,,0``@``#?@`````. +MB`&\F(``SP````"5``#>``````Z(`;Z4@`#5`````,V``-.```);`````,V` +M`,O*Y``&SEP`WLY<`-LJ9``$SD``"X0``@9_`P`+SG``3`````(```PD`````*YP`'RNX`!`SJ`#_S```S(```NXT(``$R#``0#,P +M`_W/``!`B`````````#-@``.?!R`#,`P!1V```!$?Q\`((0``8(`````B``` +M``````#("3TVR`T]-Y3`_QL`````R!$].,@5/3G('3TZR"$].\@E/34$J``P +MSH$]@LS!/8/-`3V$S4$]AX``S+ +MC@`$-,@`!'R,P`+,'`#5F,``5`````"$``,?`````(0``8*8@`"S-"```@Z(`?:8@`"P-"``!@Z( +M`?.8@/Y)-"```0Z(`>&8@``$`````(```B<`````R`@`0#"(`""4@/\W```` +M`,GL`-G)^`#-R<@`Q&2(`"!_BX`L9HP`$'S@P`S,^@`$A```D`````#("`!` +M,(@`$)B``)$`````F<#_`0````"$``'=`````(```@,`````90`WC((``&8@`!2`````(`` +M`V/.7`#;A``!?0````#-G`#5A``!RP````"```,)`````,`P-!B(````S#$` +M`,`P!15_'P`@RO@`!<^Q``#`,`50?Q\`(,KX``+/L0``P#`%6'\?`"#*^``# +MS[$``,`P!6!_'P`@RO@`!,^Q``#+.0``B```````````````R>P`V`_IP`````RS@`06>X``@T-``'S```%X``3*S``&?,B``I2`_I``````F<#]=S0@``/(*``)-"@! +MWX```-/-@``.SYP`%LV```[)\``8?SB``I2`__X`````B`````````#(*``! +MEH#];``````P'```-`@``X``S`,/__RXH`!,N*``Q'N``$ +M?+#`"Y3`_4?+D@`,S0T``$>X``0HB``0E(#]0LN2``S-"0``@``#@D>X``29 +MP/YJ-`@`'S0X``.```'[SYP`%H0``!@`````F<``"`````#`,"&2RPD```=T +M``C,M@`,!W0`+,RV``R$``'+`````(```AL`````P#`T&,VQ``"```)>```` +M`,G(`,F8@/ZW`````,@(`,B4@/Z%`````,@H``"6@/Z"-`@```````S\&BU,`N``1_+P`' +MS#$``,@L``3`,``&?O-`(\`P`"!_:X`@B````'^SP"3,``!"@````,Q``!]\ +M0,``?$$``!D4`#V90``3!!0`+H0`!,$$&``IA``"6L@<`!,$%``JA``$P008 +M`"W-0:*DR!P`$Y7```#('``3S,$A`,T!(0',P2$"S0$A`X``!+[-@:*D'1@0 +M`)6```7('``3*>0`0)9`___('``3S,$A=4``,Y!(6G.@2%JS<$A:X````#,`2%L?$#``'Q!``!\04``?$&``'Q!P``8 +MI!_H*F@`/):```I\`@``?$(``#HP``/,``!8FP```T(@``4$(`!`@``!4WP" +M0`!^`D``FD````ID``$<[``0FL``"LP``$W`*@`$R"P`('Z2@`?,``!!S"D` +M`,[``!Z```%CR#``!,T!(6W-02%NR#```W\?``8<]``'$W@``9=``"H'N`%H +MGX````````"```%X?QN`#H```7Q_&X`/@``!@'\;@`R```&$?QN`#8```8A_ +M&X`1@``!C'\;@!"```&1%*0`")N``!D4I``(@``!H1YD`/^;@``5%*0`"(`` +M`:$>9`#_FX``$12D``B```&A'F0`_YN```T4I``(@``!H1YD`/^;@``)%*0` +M"(```:$>9`#_FX``!12D``B```&A'F0`_Q2D``@>9`#_*F@`/)J`_FT4[``( +M?$-``'Q#@`!\0\``EL``!\P``$W/02%ISX$A:L_!(6N`````S`$A;(````#/ +M]0``S```680`!,$J:``\FH``!,@H`!>`````U$``?Y:`_ZM^`D``A``"C,`. +M``+,``!!@``!K\S!,$J4````R#P`''Q`P`!\00``P!X``14D`!+`(@`"ED`` +M!<`F``3`)__[?24`!L`F``!]TH`&?A+`!GTE``=\04``?$&``,S!(6F:@``, +MS0$A:LU!(6N6P/X\S8$A;(0`!,',``!_R#``&I<```#(,``:@````7Q`@`"$ +M``3!S```?\@4`!7(&``6S4$A:Y;`_B[-@2%L@``!QLP``'_,``/ER"P`(,`. +M("0$$#``(,PB:P04,`',``!!T!$``,S5``#.P``>R`P`"9C```#(#``)?$$` +M`'Q!0`#,0`!#S$``1,`.@`!\0D``?$*``!:L`!^6P/X5P#7P`,Y``^$>>``# +M$GP`"'_WP`9_^\`'%G@`&,_``^+/@`/C$K```G\_``#/``/D@``$47R`P`!\ +M0,``&-`!Z!$H``&5```0!J@!_YZ`````````@``"%\`2"`"```(ER!0`$8`` +M`BS(%``2@``",\S!HJ2```(\'.@`/X```F1\P8`+'-``/RDH``8I+``6?JZ` +M!\@<`!.:@``]!!0`+H````#,P:*DP!((`'Q!0`!]#,`'P!(`"!58``,57``, +M?$(``'W1P`82(``4?AY`!WY.@`?.@:*D@````,V!H?[(%``1!!`A&)5```#( +M%``1U%$``(````#,P:*DR!0`$@00(0:50```R!0`$M11``"`````S,&BI,S! +MHJ0$$``!S0``&80`!,',``!_R!``&YD```#($``;@````7Q`@``JH``$*J0` +M%'XF``<$%``NE@``"`08`"F$``):R!P`$P04`"J$``3!!`P`+:@``$$>0`"GXF``?-P`!FS0$A6,U!(5G.`2%:S,&BI)J``CX% +M$``$!"P``1+P`!U]<4`'$N``$"(@``S-`2%8S4$A6``"FT```\@,`"F$``-- +MR!0`*YN```,$$``0A``#9,S!HE#-`:!0A``"_@08!`"$``3!S```8\@\`"V$ +M``,,R!``*<@<`"\=W``!R"0`)Y7```G(-``QR#@`,,@\`"U3=``@?[>`)T>X +M!5#,``!BS_H``)I```#()``GR"@`(SJH``*:@/__R"@`(\`P``'(*``DFH`` +M`,@H`"3/``!;4-@`"!3<`!@AW(``S8$A@,W!(8%1(``(%20`&,X!(8+.02&# +MS4$AA'Q`@`"@````S(``380`!,$<=``!''@``IM```/(#``JA``#3<@4`"R; +M@``#!!``$(0``V3,P:)@S0&@8(0``OX$&`F`A``$P7`!YG`__[( +M'``E@````7Q`@`!\0,``?$$``!DH`#"6@``(R"@`)\@D`"B:0```R"0`)YI` +M``#()``HS``#X'Q!0`!\08``%1P`'\S``,?-``#(E<```\`<@`#-P2`0X8,` +M``5<(`#,``!-@````-P?00!\0,``?$$``'Q!0`!\08``S,``R``#()`/]?>:`$9:```-^7L`!?`+`!L[#HIY5%``@ +MS```;,T``&W-0`!MS0``0\U``$/('``=T4``0YG```7,``!5R"``']@``\#, +M``!`R"@`%M@`!L`:J``GEH```\R``$#0@`!@%5``&(!```7T5``.```!T?9&`!IE`__C((``?A``#/<@<``>` +M``"SS```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/TS0`#]LT` +M`_?-``/X@```!$``,]S```4\@,`"_,@`!`S$``0,Q``$#,0`!` +M?,3``,S``$#40`!`?$"``*`````$*``!F4#_]<@@`!^$``,]R!P`!X```0G, +M``!N?$#``,@0`$>9```+R!0`1)E```3(&``)S8``0,P``$"```$SS(``0'Q` +MP`#($`!'E0#_]\@4`$690``$R!@`"LV``$#,``!`@``!,]@`"$!\0,``R!`` +M1YD`__P`````S(``0,S``$#40`!`?$"``*`````$*``!R!``1M@`!T#-``!` +MA``!2LT``$#(#`!#E,``"L@4`$B```%#!!```\@0`$;8``?`S0``0(0``4K- +M``!`R!0`2)U```#,``!JR"@`%AZH``&:@``#P"D``8@```#`+`%6SH``7-@` +M",#.P`!`B````,P``$`?$%``%(@`"!]X<`G?5C``WS?$#``'Q!``!\04``S,.A^LT#H?G-0Z*=S,`` +M0,T``$#-0`!`S$``0'Q`@`"@````!"@``7Q`P``5 +M@``%S@``6,R@`$:`````S6``1LR@`$2`````S6``1(```S?,0`!JS(``0(`` +M``#40`!`?$#``'Q!``!\0X``?$/```0<``+/@`!"S\``0LW``$($'``@S,`` +M0LT``$+-P`!"!!P`!P0@``%\`D``R!0``\@8``-1F``@?5E`)\@H``/(+``# +MR#```\@T``-2[``@?JZ`)U-T`"!_-P`G?RM`(7YV0"!6J``_5S``/WZR@`9^ +M*@`&F<#_\@G<``&6@/_A4_0`('][0"=]94`@55@`(,P``%O-=@``S;8``,@@ +M`$&:````R"``08````%\0(``?$#``'Q!``#,P`/^S0`#_\S``$+-``!"%10` +M'QD8`/`G7``!?78`!IF```5]7D`&S```0H```S?,``!-%9@``14L``B9@``Q +M'NP``98```05,``,@``#-\P``$($%``@S4``0A\P``$@*``!!#@`(`0\``?( +M%``#R!@``\@<``/((``#?5U`#7VAP`U]74`'%A``'Q6<`!]]'0`&?1=`!GZ2 +M@`:;0``2"[@`!)O`__(+_``!R`P#_IJ```G($`/_FP``_@````-1``'^```,WS```7H0` +M`SI\0,``%-P`")7``!D``#,@`!`S,``0(````#40`!`R"``']@``T#, +M``!`S(``0-1``$!\0(``H`````0H``'((``?V``#P,P``$#,@`!`U$``0'Q` +M@`"@````!"@``7Q`P````H`TP`+`.(`#`$: +M``T!)``.`3@`#P%"`!`#-0`1``H`$@`8`!,`(``6`"(`)``Q`"4`3``F`6<` +M%P''`!@!U0`B`L$`(P+2`";@``P(!P``2`<``#("`"!E(#_V0`` +M``#(*```EH#_UB`(``'-@``.S(```!P<```JB`&[E(#_RP````"```#3```` +M`!ZH`/_.@``,B`````````#(,`!`(S``0,\``$"$``"F(#@``<@P`$`?,`._ +MSP``0(```&?,``!6A```$`````#`,"`(A```N2`X___`,"`(S#$``,LY``#` +M,`.8A```N2`X`0#`,`.8S#$``,L)``#`,"&VB````,PQ``"9P/_ER#``0",P +M``+/``!`A```BB`X``/(,`!`'S`#_<\``$"```!GS```5H0``!``````(#@` +M`<`P`YB$``"Y$[@`%,P``%?`,`.8S#$``(@```#+"0``S[$``,V```[+.0`` +M%[@`!)>`__X`````B`````````#/L0``RSD``"`(`!^8@```"(@``4P/\[`````,@1/3C(%3TYR!T] +M.L@A/3O()3TU!*@`,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$]AQ"(``,$C``8 +MR)8`/)5`_RK(T@`H?24``0E4``$$S``HF0#_^P````#(D@`X!1``0'T*P`#( +MU@`$P!P`!,CB`!3(Y@`DS@H!3,YN`4P(S``$"(@`!`KL``0)W``!F<#_^``` +M``#-"@%@S`H!9,U!/4>````Y`````,@H``&6@/[[`````"`(``'-@``.S(`` +M`8```!@````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +,```````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RS600_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RS600_cp.bin.uu new file mode 100644 index 00000000000..a4f620a7fdf --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RS600_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 RS600_cp.bin +M`````$(`X```````0`#@``````@```"@````"````*0`````2E5+2@````!* +M2D1G`````%52;W4`````2GY]90````!*YTKV`````$K32DH`````UHF)B0`` +M``#-2MW/`````(Z^2N(`````PXJ*B@````!*#XS(````!``,H``````X``T` +M$@````0``.BT````.``-`!0````$``#HM@```#@`#0`6````!```Z%0````X +M``T`&`````0``.A5````.``-`!H````$``#H5@```#@`#0`<````!```Z%<` +M```X``T`'@````0``.@D````.``-`"`````$``#H)0```#@`#0`B````!``` +MZ#`````X``T`)`````0``/#`````.``-`"8````$``#PP0```#@`#0`H```` +M!```\$$````X``T`*@````0``/&$````.``-`"P````$``#QA0```#@`#0`N +M````!```\88````X``T`,`````0``/&'````.``-`#(````$``#Q@````#@` +M#0`T````!```\Y,````X``T`-@````0``/.*````.``-`#@````$``#SC@`` +M``0``.@A````!`%`H``````8````0P````0`S.@`````!``;``$````$"`!( +M``````0`&P`!````!`@`2``````$`!L``0````0(`$@`````"````#H````` +M``"@``````0@`$4=````!```Y8`````$``SE@0````0(`$6`````!``,Y8$` +M```(````1P```````*``````!``,(``````$``#E#@````0``R``````*``" +M(%$````D````40````0(`$4/````"```H$L````$``#E90````0``.5F```` +M"````%(````$`\REM`````0%0R``````!``"(``````P3,S@7@````0()T5E +M````,````%X````$"`!%9`````0``.5F````"````%4````0`(`@80````0` +M("``````!``;`/\````0`0``9`````0`'R``````!``<`/\````,```````` +M`#````!R````"````%4````$``#E=@````0``.5W````!```Y0X````$``#E +M#P````0!0*``````&````&D```#"`,#E^0````@```!I````!``4Y0X````$ +M`$#E#P````@`P`!L````!```Y7`````$``#E<0````P``.5R````!```H``` +M```$`4"@``````0``.5H````!``,(``````8````=@````0`"P``````!!C` +MY6(````(````>`````@`P`!W````!``'`-4````X````A````#``#*"&```` +M!`@`1;L````P``P@AP`````(`.6\````!```Y;L```````#EO`````P`$@`` +M````!``2```````,`!L``@````0``*``````!```Z"$```````#H``````0` +M`.@A````````Z"X````$`LR@``````0`%```````!``,X````````@``````$`\`(,`````!"`.``````!```H``` +M```$(`!%X````````.7A``````````$````$``<`T@`````(`..4```````` +M```````$``#HQ`````0``.C%````!```Z,8````$``#I*`````0``.DI```` +M!```Z2H````(````U@````0``.DH````!```Z2D````$``#I*@````@```#= +M``````#@`18````$``<`X0````0(`$`<````!"``4.<````$``#@'0````@` +M``#D````!`+`(``````$``8``````#0```#K````"````.@````$``"````` +M``#``.`````````````````````````````````````````````````````` +M````````````````````````````````````````````````!``,(``````$ +M`!T`&`````0`&@`!````-````/L````(````2@````@%`*!*```````````` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RS690_cp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RS690_cp.bin.uu new file mode 100644 index 00000000000..8ac379b3f02 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RS690_cp.bin.uu @@ -0,0 +1,49 @@ +begin 644 RS690_cp.bin +M````"````-T````(````WP````@```"@````"````*0`````2E5+2@````!* +M2D1G`````%52;W4`````2GY]90````!*UTKV`````$K)2DH`````S(F)B0`` +M``##2M/%`````(Y*2DH`````2HJ*B@````!*#XQ*````!``,H``````X``T` +M$@````0``.BT````.``-`!0````$``#HM@```#@`#0`6````!```Z%0````X +M``T`&`````0``.A5````.``-`!H````$``#H5@```#@`#0`<````!```Z%<` +M```X``T`'@````0``.@D````.``-`"`````$``#H)0```#@`#0`B````!``` +MZ#`````X``T`)`````0``/#`````.``-`"8````$``#PP0```#@`#0`H```` +M!```\$$````X``T`*@````0``/&$````.``-`"P````$``#QA0```#@`#0`N +M````!```\88````X``T`,`````0``/&'````.``-`#(````$``#Q@````#@` +M#0`T````!```\Y,````X``T`-@````0``/.*````.``-`#@````$``#SC@`` +M``0``.@A````!`%`H``````8````0P````0`S.@`````!``;``$````$"`!( +M``````0`&P`!````!`@`2``````$`!L``0````0(`$@`````"````#H````` +M``"@``````0@`$4=````!```Y8`````$``SE@0````0(`$6`````!``,Y8$` +M```(````1P```````*``````!``,(``````$``#E#@````0``R``````*``" +M(%$````D````40````0(`$4/````"```H$L````$``#E90````0``.5F```` +M"````%(````$`\REM`````0%0R``````!``"(``````P3,S@7@````0()T5E +M````,````%X````$"`!%9`````0``.5F````"````%4````0`(`@80````0` +M("``````!``;`/\````0`0``9`````0`'R``````!``<`/\````,```````` +M`#````!R````"````%4````$``#E=@````0``.5W````!```Y0X````$``#E +M#P````0!0*``````&````&D```#"`,#E^0````@```!I````!``4Y0X````$ +M`$#E#P````@`P`!L````!```Y7`````$``#E<0````P``.5R````!```H``` +M```$`4"@``````0``.5H````!``,(``````8````=@````0`"P``````!!C` +MY6(````(````>`````@`P`!W````!``'`,L````X````A````#``#*"&```` +M!`@`1;L````P``P@AP`````(`.6\````!```Y;L```````#EO`````P`$@`` +M````!``2```````,`!L``@````0``*``````!```Z"$```````#H``````0` +M`.@A````````Z"X````$`LR@``````0`%```````!``,X````````#EX0`````````!````!``'`,@````` +M"`#CE```````````````!```Z,0````$``#HQ0````0``.C&````!```Z2@` +M```$``#I*0````0``.DJ````"````,P````$``#I*`````0``.DI````!``` +MZ2H````(````TP````0"P"``````!``&```````T````VP````@```#8```` +M!```@```````P`#@`````#````#A`````$(`X``````P````X0````!``.`` +M````!``E`!L````$`",```````0`)0`%````-````.8````,``````````0` +M)$``````!`@`1<@````$`"0`!0````P(`$T+```````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````!``,(``````$ +M`!T`&`````0`&@`!````-````/L````(````2@````@%`*!*```````````` +7```````````````````````````````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RS780_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RS780_me.bin.uu new file mode 100644 index 00000000000..0a6b8c10b9f --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RS780_me.bin.uu @@ -0,0 +1,481 @@ +begin 644 RS780_me.bin +M`````,`@!`````````````"@``H```````#__P`H1B$``````````-D`2``` +M`````````,`@!`````````````"@``H```````````#@``````````$``,`I +M1B```````````-D`2````````````,`@!`````````````"@``H`````@0`` +M```@1!$``````````0`@2!$```````0@!`!@1!$```8B``````!@``````71 +M``````!@``````7>`````,`@"``````````/```H%B(`````````"``A%B4` +M````````&``@-B4`````C0`````@1!$`````````!``O`B4```````````S@ +M```````8`$$@``!`2!$````9`$(@```@2!$`````C@`````@1!$````````` +M*``@2BT`````D``````@1!$````````````@2`4`````````#``A%B(````` +M`````P`H%B4`````````&0`A&B(`````````!``H&B8````````````I%,4` +M````````&0`@-B4````````````Z%`(`````````%@`A%B4``````````P`H +M%B4`````````%P`@#BT`````_____``H#B,````````````I%*,````````` +M%P`@-B4```````"````H#B(`````````!P`B#B,````````````I.&X````` +M(``````H#B(`````````!@`A#B,````````````I.&X````````````B`B(` +M`````````!3@```````X`````"[@```````U`````"S@```````W``````!` +M#BT````Y````"``@#BT`````````"0!`$BT```!&`````0!`#BT````Y```` +M`,`@#````````#___``H$B,``````````@`B$B0`````````'P`A'B,````` +M`````!3@```````^````"`!`'!$```!!````#0`@'BT`````````#P`H'B<` +M`````````P`B'B<`````?\`````H&B,`````````%``A&B8``````````0`S +M&B8`````````"``B&B8````````````I#,<`````````)P`@-B0```````!_ +M```H$B$````````4```O`B0```````````S@``````!+`````0`I#B,````` +M````#@`@-B,```````#@```@1!$`````__@````I2B,````````````Z+`(` +M`````````@`B#BL`````_``````H#B,`````````#P`@-B,````````?_P`I +M2B,`````````)P`@2BT````````````@2!$`````````*0`@#BT`````!@H" +M```I2B,````````````@2!$````````````@2!$``````````0`A`B(````` +M`````!3@``````!A`````"[@``````!?`````"S@``````!>``````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````,``@%BT``````````@`I%B4`````````,``@-B4` +M````````)0`@%BT````````````O`*,```````````S```````"#````)@`@ +M%BT````````````O`*0```````````S```````"$``````!```````"*```` +M)0`@-B,`````````)@`@-B0`````````%P`@'BT``````````@`A`B<````` +M`````!3@``````"*``````!@``````7_``````!@``````7S`````@`A#B(` +M`````````!3```````"-````$L!`-B````"3`````"[@``````"1`````"S@ +M``````"0`````@!`#BT```"2`````P!`#BT```"2````#``@#BT````````` +M$@`@-B,``````````P`A#B(``````````!3```````"8``"@#``@1!$````` +M`````,`@2````````````,!`2`````"@``"@#``@1!$````````````@2!$` +M`````````"[@``````">`````"S@``````"=`````@!`#BT```"?`````P!` +M#BT```"?````#``@#BT````````````@2`,````````````Z#`(``````#\` +M```H#B,`````````$``A#B,`````````$0`@-B,`````````'@`A`BL````` +M`````!3```````"G````%L`@-B``````````'P`A`BL``````````!3````` +M``"J````%<`@-B``````````"``A#BL`````````?P`H#B,````````````O +M`B,```````````S@``````#A`````"<```````````````!@``````*C```` +M`0`O`B,```````````K@``````"S``````!@``````$Z@0`````@1!$````` +M````!@`@2!$`````````#``B'C``````F8`````@1!$`````````!``@$BT` +M````````"``B$B0`````````$``@&!$````````````I'.0```````````!@ +M2`<```$OFP`````@1!$````````````@2`(`````G``````@1!$````````` +M```S%&\``````````0`S/B,``````````-D`2``````````````@/`4````` +M@0`````@1!$`````````#@`@2!$````````````@$!````````#@!P`@1!$` +M````````#P`A`BL``````````!3```````#+`/C_"``@2!$`````F`````!` +M2!$```#<````\``H#B(`````````H``O`B,```````````S```````#:```` +M$0`@#BT``````````0`O`B,```````````S@``````#5`````@`O`B,````` +M``````S@``````#4```_``!`#!$```#6```?``!`#!$```#6```/```@#!$` +M`````#@`"0`I2B,`````/P`````H#BL``````````@`B#B,`````````!P!) +M2B,```#<`#@/"0`@2!$`````:```!P`@2!$`````````"``A2B<````````` +M```@2!$`````!@H"```I2B0````````````@2!$````````````@2!$````` +M``"B`@`@1!$``````/\````H#B(`````````@``I2B,`````````)P`@#BT` +M````````)@`@$BT````````````O`(,```````````S@``````#J``````!@ +M``````7Y``````!```````#K``````!@``````7\````!P`@(BT````````` +M!0`B#B(``````!`````H#B,````````````I(&@````````````Z#`(````` +M````[P`H#B,````````````I(&@`````````%P`@#BT``````````P`A`B,` +M`````````!3@``````#X````"P`A`B@``````````!3```````#X```$```I +M(B@`````````%``@-B@`````````'``A#B(``````````!3```````#]``"C +M#``@1!$````````````@2!$`````````'@`A#B(``````````!3```````$+ +M``"C#P`@1!$`````````$0`@#BT``````````0`O`B,```````````S````` +M``$$_____P!`2!$```$+`````@`O`B,```````````S```````$'``#__P!` +M2!$```$+````!``O`B,```````````S```````$*````_P!`2!$```$+```` +M`0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3```````$2 +M````$$`A#B``````````$P`@-B,`````````&$`B2B``````````$,!"2B`` +M``$4```````@#!$`````````$P`@-B,````````````@2!$````````````@ +M2!$`````````"@`@$!$````````````O`B0```````````S@``````$;```` +M```@2!$``````````0!3$B0```$7_[___P`H.BX`````````&P`A`B(````` +M`````!3```````$N@0`````@1!$`````````#0`@2!$`````````&``B#C`` +M````_``````H#B,`````@0`````@1!$`````````#@`@2!$````````````@ +M$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,````````` +M'``@'BT`````````"``A2B<````````````@2!$`````!@H"```I2B0````` +M```````@2!$````````````@2!$```````````"`````````@0`````@1!$` +M`````````0`@2!$````````A?``@1!$``````(`````@2!$````````````@ +M2`8`````````"``A2B<``````````!<```````````0A?P!@1!$```8B```` +M'P`A`C```````````!3```````8A````!`!`3!$```$U@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````'``@2!$```````0A^0!@1!$` +M``8B````$0`A`C```````````!3@``````$\``````"```````````````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```` +M``!@``````%@``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%'`````,!`!``````!``````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```_ +M_P`O`B\```````````S@``````````````!@``````%@````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%8`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````&/``````!@``````&@```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&< +M``````!@``````*[`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*C```````O`B$```````````K@ +M``````&!``````!@``````$Z``````!```````&&E0`````@1!$````````` +M```O`B$```````````S@``````&&`````,`@2````````````0!3!B$```&" +MD@`````@1!$``````````,!@2`````&7``&A_0`@1!$`````````$0`@!BT` +M``````````!X!"H```+[```````@*`D````````__P`O`B\```````````S` +M``````%T`````,!`!``````!```"$`!@!!$```,5```__P`O`B\````````` +M``S@``````&4````%<`@-B``````````%L`@-B``````/X`````@!!$````` +M1@````!@"!$```&R``````"```````````"A_``@1!$````````__P`O`B\` +M``````````S```````&;`````0"`2!$`````````(0"`2!$```````#__T`H +M#B``````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`` +M```@1!$`````````!@`@2!$`````````"``B'C``````````*0`@&BT````` +M``#@```@1!$`````__O_"0`@2!$`````````#P`@(BT````````?_P`I2B@` +M````````!@`@(BT````````````I(.@````````````@2`@````````````@ +M2!$`````!@H"```I2B8````````````@2!$````````````@2!$````````! +M```@&!$`````````"`!B'B@```$O````"`""(B@```````+````@1!$````` +M````%0!@#BT```&]````%@!@#BT```&]``#`"``@1!$`````````%P`@#BT` +M`````````!3```````&Y```````@!!$````````````@2`$`````.0`````@ +M2!$````````````@2!$```````````"`2`(`````````&``@+BT````````` +M```[#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````` +M``````"`2`,```````````!@```````+```0``!@!!$```,5```````@!!$` +M``````````!@"!$```&R````!P`A!B\`````````$P`@"BT``````````0`@ +M+!$```````#__T`H(B``````````#P`F(B@`````````$$`A)B`````````` +M#P`F)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````` +M```````O`B$```````````S@``````'@```B7``@1!$`````````@0`@2!$` +M``````"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O +M`B<```````````S@``````'<``````!@``````'I`````0!3'B<```'8```` +M`0`@+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```'1 +M```B7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$` +M`````````0`P'B\````````````O`B<```````````S@``````````````!@ +M``````'I`````0!3'B<```'E``#__T`H#B``````````#P`F#B,````````` +M$,`A$B``````````#P`F$B0````````````@%!$```````````!@&!$```*[ +M``&A_0`@1!$````````````O`BL```````````S@``````'X````$``B%B@` +M````__\````H%B4```````#__P`H&BD````````````I2,4````````````@ +M2`H````````````@+!$`````````$``B%B,`````__\````H%B4```````#_ +M_P`H&B0````````````I2,4```````````!S%0,```(%```````@&`4````` +M``````!S%20```(%```````M%,4````````````P"*(````````````@2`(` +M```````````@*`(````````````@(`,```````````"`)`0`````````#P`A +M`B4``````````!3```````8A```````K%`4``````````0"0%B4````````` +M``!@```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R +M```B5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\` +M``````````S@`````````````,`@!``````````B7``@1!$``````````P`X +M2B$```````"A_``@1!$``````````0`@2!$```````#__T`H$B`````````` +M$,`A&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*[ +M``&A_0!@1!$```+@`````0`S!B$````````````O`B$```````````S````` +M``(9```__P`O`B\```````````S```````(2`````,!`!``````!``````!@ +M``````7>``````!`!`\```(3``````!@``````71``````!@``````7>```" +M$`!@!!$```,5``````!@``````&@``````!@``````&<``````!@``````*[ +M``````!@``````*CDX`````@1!$````````````@2`@````````````O`B\` +M``````````K@``````(R``````!@``````$Z``````!```````(VE0`````@ +M1!$````````````O`B\```````````S@``````(V`````,!`2`````(SD@`` +M```@1!$``````````,`@2``````````B5@`@1!$`````````%@`@2!$````` +M```B7``@1!$``````````P`@2!$```````"A_``@1!$``````````0`@2!$` +M``````&A_0`@1!$```````````!@!!$```+[`````,!`!``````!``````!@ +M``````71``"@#``@1!$``````````,`@2````````````,!`2``````````` +M``!@```````+````&$`A"B```````````P`O`B(```````````K@``````), +M````%``@(BT```````@!`0`I(B@`````````%``@-B@```````"C#``@1!$` +M`````````,`@2````````````,`@2````````````,!`2`````)1``````!@ +M```````+````$`!@!!$```,5/X`````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$```````````!@``````)\````%P`@'BT````` +M`````0`A'B<``````````!3@``````)J````$@`@'BT```````#__P`H'B<` +M```````````T'"<``````````!+```````)?```````@'!$````````````O +M`.4```````````C```````)B```````@%`<`````````$@`@'BT````````` +M$``A'B<````````````T'$<``````````!+```````)G```````@'!$````` +M```````O`.8```````````C```````)J```````@&`<```````````!@```` +M``+!```B5@`@1!$````````````T(",``````````!+```````)R```````T +M($0``````````!+```````)Q````%@!`2!$```)V````&`!`2!$```)V```` +M```T($0``````````!+```````)U````%P!`2!$```)V````&0`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_0!@1!$```+I```__P`O`B\` +M``````````S```````)6`````,!`!``````!````$$`A!B````````#__\`H +M"B``````````$$`A#B````````#__\`H$B``````````$$`A%B````````#_ +M_\"(&B``````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```8B +M``````!@``````71`````,!@``````*C````!0`@"BT`````````"``B"B(` +M````````*P`@&BT`````````'``@'BT```````!P```H'B<````````````Q +M'.8`````````*@`@&BT`````````#``B&B8````````````O`.8````````` +M``;@``````*2```````@'!$````````````@#!$`````````*P`@-B,````` +M````$``@&!$```````````!I'.(```$ODX`````@1!$````````````@2`<` +M````E0`````@1!$````````````O`B\```````````S@``````*=`````0`S +M/B\``````````-D`2```````D@`````@1!$``````````,`@2``````````` +M'`!`-B<`````````#,`B"B``````````*0`@-B(`````````*,!`-B`````` +M``"BI``@1!$`````````"0`@2!$`````H0`````@1!$``````````0"`2!$` +M````````(0`@'BT````````````L'.,`````````(0`@-B<`````````(@`@ +M'BT````````````L'.0`````````(@`@-B<`````````(P`@'BT````````` +M```Q(*,````````````M'0<`````````(P`@-B<`````````)``@'BT````` +M```````Q(,0````````````M'0<`````````)`"`-B<`````````(0`@-B,` +M````````(@`@-B0````````````Q'*,`````````(P`@-B<````````````Q +M',0`````````)`"`-B<`````````&@`@-B<`````````&P`@-B@````````` +M%P`@'BT``````````@`A`B<``````````!3```````+<``````!```````+9 +M````&@`@-B<`````````&P`@-B@`````````%P`@'BT``````````@`A`B<` +M`````````!3@``````+9`````P`A`B<``````````!3@``````+<````(P`@ +M'BT````````````N`.$```````````+```````+<````(0`@'BT````````` +M```Q(*$````````````N`.@```````````;```````+<````)``@'BT````` +M```````N`.(```````````+```````+<````(@`@'BT````````````Q(,(` +M```````````N`.@```````````;```````+<``````!@``````7_``````!@ +M``````*U``````!```````+>``````!@``````*U``````!@``````7V```` +M``!```````+>``````!@``````*G``````!```````+>````&@`@'BT````` +M````&P"`(BT`````````$``B'B,````````````I2(<````````````Q'*,` +M````````$``B'B<````````````I2(<`````````$``B'B,````````````Q +M(,0```````#__P`H(B@```````````")20<`````````$``B'B,````````` +M```I2(<`````````$``B'B$````````````I2$<````````````Q'*,````` +M````$``B'B<````````````I2(<````````````Q'*$`````````$``B'B<` +M```````````I2$<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<`````````$``B'B$````````````Q(,(```````#_ +M_P`H(B@```````````")20<`````````$``B'B,````````````I2(<````` +M`````0`B"B$````````````S"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<````````````Q'*,`````````$``B'B<````````````I +M2(<``````````0`B"B$````````````P"*(`````````$``B'B(````````` +M$``A(B(````````````I20<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@````````````I20<````````````X",4````````````P"$$` +M`````````0`B"B(````````````S"*(`````````$``B'B(`````````$``A +M(B(```````````")20<`````````%P`@(BT``````````!3```````,8____ +M[P`H!B$`````````%``@(BT```````#XX``@1!$````````````I20$````` +M``````")20$````````````@2!$````````````@2!$`````!@H"``"`2!$` +M`````````,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2````````````,`@!`````````````"@``H````` +MEP```,`@1!$``````````,`@2!$`````B@```,`@1!$````````````@2!$` +M```````B7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@ +M2````````````,`@!`````````````"@``H`````EP`````@1!$````````` +M```@2!$`````B@`````@1!$````````````@2!$````````B7``@1!$````` +M`````,`@2`````````"A_``@1!$``````````,`@2````````````,`@!``` +M``````````"@``H`````EP`````@1!$````````````@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2`````````&A_0`@1!$``````````-D`2``````` +M`````,`@!`````````````"@``H````````B5P`@1!$``````````\!(2B`` +M```````B70`@1!$``````````,!`2`````````````!@``````7>`````,`@ +M"``````````B7``@1!$``````````P`X2B(```````"A_``@1!$````````` +M`,`@2`````````&A_0`@1!$````````````O`B(```````````S@```````` +M`````$`@2````````````4`P2B```````````L`P2B```````````0!3"B(` +M``-5````/\`H"B``````@0`````@1!$``````````0`@2!$````````A^``@ +M1!$`````````&``@2!$```````0A^0!@1!$```8B````$0`A`C`````````` +M`!3@``````->````%``O`B(```````````S```````-L``&BI``@1!$````` +M``````!@2`(```-T```A```@1!$``````````,`@2````````````,`@2``` +M`````````,`@2````````````,!`2```````````!``O`B(```````````S` +M``````-P``&BI``@1!$```````````!`2`(```-G````*``O`B(````````` +M``S```````6Z``&BI``@1!$```````````!`2`(```-G````+``@-B8````` +M````20`@&!$`````````/P`@2!$``````````0`S&B8````````````O`B8` +M``````````S```````-V````+`"`&BT`````````/\`H"B``````````%0`O +M`B(```````````S@``````.,````!@`O`B(```````````S@``````.W```` +M%@`O`B(```````````S@``````.Y````(``O`B(```````````S@``````.B +M````#P`O`B(```````````S@``````.N````$``O`B(```````````S@```` +M``.N````'@`O`B(```````````S@``````.6``"BI``@1!$```````````!` +M2`(`````"``````I"B(``````````T`A#B``````````#,`A$B````````@` +M```H$B0`````````%,`B%B`````````````I%*0```````"BI``@1!$````` +M```````I2*(```````"A_@`@1!$```````````!`2`,`````@0`````@1!$` +M`````````0`@2!$````````A^``@1!$`````````%@`@2!$```````0A^0!@ +M1!$```8B````%0`A`C```````````!3@``````.8```A#@`@1!$````````` +M`,`@2````````````,`@2`````````"BI``@1!$```````````!`2`(````` +M@0`````@1!$``````````0`@2!$````````A^``@1!$`````````%P`@2!$` +M``````0A^0!@1!$```8B`````P`A`C```````````!3@``````.D```A"``@ +M1!$``````````,`@2````````````,`@2`````````"BI``@1!$````````` +M``!`2`(```````"BI``@1!$````````````@2`(`````@``````@1!$````` +M```````@2!$`````@0`````@1!$`````````$``@2!$````````````@`!`` +M`````````!3```````.T``````!```````````&BI``@1!$`````````!@!` +M2!$```````&BI``@1!$`````````%@!@2!$```-T``````!````````````` +M`,`@"````````````,`@#```````````'0`A`B,``````````!3@``````/. +M@0`````@1!$``````````0`@2!$````````A^``@1!$`````````&``@2!$` +M``````0A^0!@1!$```8B````$0`A`C```````````!3@``````/"```A```@ +M1!$````````````@2`(````````````@2`,`````NK[*_@`@2!$`````ROZZ +MO@`@2!$```````"BI``@1!$`````````!`!`2!$````````A<``@1!$````` +M```````@2`(````````````@2`,`````@0`````@1!$`````````"@`@2!$` +M```````````@`!```````````!3```````/3C``````@1!$`````ROZZO@!` +M2!$`````@0`````@1!$``````````0`@2!$````````__T`H"B``````@``` +M`$`H#B``````0````,`H$B````````0```!I1B(```8B```````@%!`````` +M```````O`B,```````````S```````/A`````,!`&`````/D```__\`H&B`` +M``````0```!I1B8```8B```````@&!`````````````O`B0```````````S` +M``````/G`````,!`'`````/J```__\`H'B````````0```!I1B<```8B```` +M```@'!`````````````@1`(````````````H(,4```````````!)2.@````` +MI8`````@"!$````````@```@#!$`````@P````!@1!$```02```````@1`(` +M`````````,`@2````````````$`@2```````````'\`A`B```````````!3` +M``````/W```@$``@1!$```````"````@2!$```````#__\!($B````/_IX`` +M```@"!$```````"@```@#!$`````@P````!@1!$```02```````@1`(````` +M`````,`@2````````````,`@2`````````#__\`H$B``````@P`````@1!$` +M```````````P2(,`````A``````@1!$``````````,`@2````````````!T` +M````````@P````!@1!$```02`````,!`!``````!J8`````@"!$```````#` +M``!`#!$```/ZJX`````@"!$```````#XX`!`#!$```/ZK8`````@"!$````` +M``#X@`!`#!$```/ZLX`````@"!$```````#S_`!`#!$```/ZKX`````@"!$` +M``````#@``!`#!$```/ZL8`````@"!$```````#P``!`#!$```/Z@P`````@ +M1!$````````A2``@2!$`````A``````@1!$``````````,`@2``````````` +M`!T```````````````"``````````1@@`,`P1B```````````-D`2``````` +M`````,`@!`````````````"@``H``````AB@`,`P1B```````````-D`2``` +M`````````,`@!`````````````"@``H``````QC``,`P1B```````````-D` +M2````````````,`@!`````````````"@``H`````!!CXX,`P1B`````````` +M`-D`2````````````,`@!`````````````"@``H`````!1CX@,`P1B`````` +M`````-D`2````````````,`@!`````````````"@``H`````!AC@`,`P1B`` +M`````````-D`2````````````,`@!`````````````"@``H`````!QCP`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H`````"!CS +M_,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M````,\`P"B```````````,!`-$``````````,``@"BT``````````,`I#$`` +M````````,``@-B,``````````,`@!`````````````"@``H`````A@`````@ +M1!$```````````!`2`$`````A0```,`@1!$```````````!`2`$````````A +M?``@1!$`````````&$`A`B```````````!3```````1'`(```,!)2B````1( +M`````,`@2````````````,`@2````````````,`@2```````@0`````@1!$` +M`````````0`@2!$``````````,`@"```````````!``O`B(```````````;@ +M``````10````!``@"!$``````````!<```````````0A?P!@1!$```8B```` +M'P`A`C```````````!3```````````````!`3`(```10`````,`@#``````` +M`````,`@$````````````,`@%````````````,`@&````````````,`@'``` +M``````!_```H"B$```````!%```O`B(```````````S@``````1A`````,`@ +M(```````````!``O`B@```````````;@``````1A````!``@(!$````````` +M`!<`````````````$``H"B,`````````$``O`B(```````````S@``````1I +M@0`````@1!$``````````0`@2!$```````0```!I1B0```8B``````!````` +M``1N@0`````@1!$````````````@2!$````````A;0`@1!$````````````@ +M2`0```````````!@2`4```8G```````H)/``````````!P`H"B,````````` +M`0`O`B(```````````K@``````1U```````O`,D```````````3@``````2. +M``````!```````2;`````@`O`B(```````````K@``````1Z```````O`,D` +M``````````+@``````2.``````!```````2;`````P`O`B(```````````K@ +M``````1_```````O`,D```````````S@``````2.``````!```````2;```` +M!``O`B(```````````K@``````2$```````O`,D```````````K@``````2. +M``````!```````2;````!0`O`B(```````````K@``````2)```````O`,D` +M``````````;@``````2.``````!```````2;````!@`O`B(```````````K@ +M``````2.```````O`,D```````````C@``````2.``````!```````2;``!_ +M```H"B$```````!%```O`B(```````````K@````````````"``A"B,````` +M`````!3```````28```A:0`@1!$``````````,`@2````````````,`@2``` +M`````````,`@2```````ROZZO@!`2!$``````````,`@1````````````,`@ +M`````````````,!`2`````````!_```H"B$```````!%```O`B(````````` +M``K@``````2A`````,`@`````````````,`@`````````````,!````````` +M``````!`3`@```1A`````,`@"```````````$$`A#B``````````$4`A$B`` +M````````$D`A%B`````````A:0`@1!$````````````@2`(````````````A +M`B4``````````!3@``````2K``0``,!)2B````2L__O__\`H2B`````````` +M```A`B,``````````!3@``````2X`````,`@2````````````,`@2``````` +M```````A`B0``````````!3`````````@0`````@1!$`````````#``@2!$` +M```````````@`!```````````!3```````2TH``````@1!$`````ROZZO@!` +M2!$`````@0`````@1!$`````````!``@2!$````````A:P`@1!$````````` +M`,`@2!``````@0`````@1!$`````````!0`@2!$````````A;``@1!$````` +M`````,`@2!`````````````O`B0```````````S@``````````````!````` +M``2R`````,`A"B```````````!3```````3+@0`````@1!$````````````@ +M2!$````````A;0`@1!$``````````,`@2````````````,!@2`````8G```` +M``!```````3/@0`````@1!$``````````0`@2!$```````0``,`I1B`````` +M`````,!@``````8B`````0`A`B(``````````!3```````36```A:0`@1!$` +M`````````,`@2````````````,`@2``````````````@2!``````ROZZO@!` +M2!$``````````,`@1````````````,!`2!``````@0`````@1!$````````` +M`0`@2!$````````A^``@1!$`````````#@`@2!$```````0A^0!@1!$```8B +M```````A`C```````````!3```````38```A@``@1!$``````````,`@2``` +M`````````,`@`````````````,`@2````````````,`@`````````````,!` +M2````````````P`S/B\``````````0`A`B$``````````!3@``````4(```` +M+``@"BT```````0``!C@#!$```3W`````0`S/B\````````A:0`@1!$````` +M```````@2`(````````````@2`,`````````"``P"B(``````````,`@2``` +M`````````,`@2``````````A:0`@1!$````````````@2`(````````````@ +M2`,`````````"``P"B(``````````,`@2````````````-C`2`````3K```A +M:0`@1!$````````````@2`(````````````@2`,`````````"``P"B(````` +M`````,`@2````````````,`@2```````````+0`@$BT````````````I#(,` +M```````A:0`@1!$````````````@2`(````````````@2`,`````````"``P +M"B(``````````,`@2````````````,`@2```````````$0`A`B0````````` +M`!3```````````````!```````2R````+,`@-B``````````+``"B +MT@`@1!$```````````!`2`@```````"BT@`@1!$``````````0!02B@````` +M`````@`O`B0```````````S```````6N``"BOP`@1!$````````````@2`<` +M````````-0`@)BT`````````&@`A(BD`````````!@`B)BD```````"BQ@`@ +M1!$````````````P2.D```````````#@``````6L``"BTP`@1!$````````` +M``!`2`@```````"BTP`@1!$``````````0!02B@```````"BPP`@1!$````` +M```````@2`<`````````-@`@)BT`````````&@`A(BD`````````!@`B)BD` +M``````"BQP`@1!$````````````P2.D```````````#@``````6X``"BU``@ +M1!$```````````!`2`@```````"BU``@1!$``````````0!02B@`````A0`` +M```@1!$````````````@2`$````````P2@`@1!$``````0`````@2!$````` +M``````!```````6^I````,`@1!$``````````,!`2````````````,!@```` +M``7#`````,!`!``````!``&BI``@1!$`````````/P`@2!$`````````/P`@ +M2!$`````````/P`@2!$`````````/P`@2!$`````````!0`@2!$```````"A +M]``@1!$````````````@2!$`````B``````@1!$``````````0`@2!$````` +M_P`````@1!$````````````@2!$``````````0`@2!$``````````@"`2!$` +M``````````[@``````76```0```@"!$`````````*P`@-B(```````````!@ +M``````7:``````!@``````7#F``````@1!$```````````"`2!$````````` +M`,!@``````7:`````,!`!``````!``"BI``@1!$`````````(@`@2!$````` +MB0`````@1!$``````````0!`2!$```7-EP`````@1!$````````````@2!$` +M````B@`````@1!$```````````!`2!$```7-``````!@``````7S``&BI,`@ +M1!$`````````%@!@2!$```-T```@$``@1!$```````$````@2!$`````@0`` +M```@1!$``````````0`@2!$````````A?``@1!$`````"8`````@2!$````` +M_____P`@2!$````````````@2!$``````````!<```````````0A?P!@1!$` +M``8B````'P`A`C```````````!3`````````````!`!`3!$```7M``````!` +M````````````%P`@'BT`````````!``I'B<`````````%P"`-B<````````` +M%P`@'BT`````____^P`H'B<`````````%P"`-B<`````````%P`@'BT````` +M````"``I'B<`````````%P"`-B<`````````%P`@'BT`````____]P`H'B<` +M````````%P"`-B<```````&BI``@1!$`````````%@!@2!$```-T```@$``@ +M1!$```````$````@2!$````````A?``@1!$``````8`````@2!$`````____ +M_P`@2!$````````````@2!$``````````!<`````````@0`````@1!$````` +M`````0`@2!$```````0A?P!@1!$```8B````'P`A`C```````````!3````` +M``8A````$`!`3!$```8'`````,`@!````````````#C`````````````'0`@ +M"BT`````````'@`@#BT`````````'P`@$BT`````````(``@%BT````````A +M:0`@1!$````````````@2`0````````````@2`4````````````@2`$````` +MROZZO@`@2!$`````````!``P$B0````````````O`&0```````````S````` +M``8@`````P`H&B(`````````"``B$B(`````___P```H$B0````````````I +M$,0`````````'P!`-B0```````````"``````````````!K```````8BGP`` +M```@1!$`````ROZZO@`@2!$``````````!K@``````8E``````"````````` +M`````!K```````8GG@`````@1!$`````ROZZO@`@2!$``````````!K@```` +M``8J``````"```````````````!@```````+```0``!@!!$```,5```````@ +M!!$```````````!@"!$```&R```B7``@1!$``````````P`@2!$````````B +M5@`@1!$`````````&P`@2!$```````"A_``@1!$``````````0`@2!$````` +M``&A_<`@1!$`````````(0`@'BT`````````$``B'B<`````````)``@(BT` +M``````#__P`H(B@````````````I20<````````````@2!$`````````(@`@ +M(BT```````#__P`H(B@````````````I20<````````````@2!$````````` +M(P`@'BT`````````$``B'B<````````````I20<```````````!`2!$````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````4(%"@6Z`E```````<,!:`1!!;H``````B4" +M"0)0`5$``````B,"10*@`D$``````]<%N@6Z!;H`````!>(%XP,?!;H````` +M`R`%OP,@`TH``````S0"@@-,`SX`````!;H%N@6Z!;H`````!;H%5P6Z`RH` +M`````[P%N@3#`TX`````!*($500_!;H`````!-@%N@1#!.4`````!%4%#P-; +M`WL`````!;H%N@6Z!;H`````!;H%N@6Z!;H`````!;H%N@78!<$`````!;H% +MN@`'!;H`````!;H%N@6Z!;H`````!;H%N@6Z!;H``````_@#[00(!`8````` +M!`X$"@0,!!``````!!P$&`0D!"``````!"P$*`0T!#``````!;H%N@0Z!#@` +G````!;H%N@6Z!;H`````!;H%N@6Z!;H```````(&#@8L``8````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RS780_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RS780_pfp.bin.uu new file mode 100644 index 00000000000..754b9593ae8 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RS780_pfp.bin.uu @@ -0,0 +1,55 @@ +begin 644 RS780_pfp.bin +M`,H$``"@````?H*+`'P#BP"``=L`?`.+`-1`'@#N`!X`R@0``*````!^@HL` +MQ!@X`,HD``#**```E8'+`,0<.@##P```R@@``,H,``!\=$L`P@`%`)G```#$ +M'#H`?'1,`,#_X``$+`@`,)`"`'TE```U%`(`?34+`"54!P!\U8``)9P'`)7` +M!`#5`!L`?MW!`'V=@`#6@!L`U8`;`-1`'@#50!X`UD`>`-:`'@#4@!X`U,`> +M`)>#TP#5P!X`R@@``(``&@#*#```Y`$>`-0`'@"```P`Q!@X`.0!/@#4`!X` +M@``,`,08.`#40!X`[@`>`,H$``"@````?H*+`.0!'@#4`!X`U$`>`.X`'@#* +M!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^@HL`R@@``,H, +M``"``=L`U(`D`,H(``!\`,``R!0E`,@8)`!\E(@`?)B``,(``P#4`'4`?'1, +M`(``9`#40!X`RA@``-1`'@#5@!X`@`!B`-0`=0#40!X`R@@``,H,``#*$``` +MU(`9`-3`&`#5`!<`U(`>`-3`'@#5`!X`X@`>`,H$``"@````?H*+`-0`=0#4 +M0!X`R@@``,H,``#*$```U(`9`-3`&`#5`!<`U(`>`-3`'@#5`!X`[@`>`,H$ +M``"@````?H*+`,H(```DC`$`U(!@`)3``P`$$`$`!!`"`-4`)0#40!X`@``` +M`-2`'@#*"```U(!A`-1`'@"`````U(`>`,H(``#*#```U$`>`-2`%@#4P!8` +MU(`>`(`!VP#4P!X`Q@A#`,H,``#*$```E(`$`,H4``#D(/,`U"`3`-5@90#4 +MX!P`U2`<`-5@'`"`````!B`!`,8(0P#*#```RA```)2#]P#*%```Y"#S`(`` +MG`#4(!,`Q@A#`,H,``#*$```F(/O`,H4``#4`&0`@`"P``````#$%#(`QAA# +M`,0(+P"50`4`Q`PP`-1`'@"`````[@`>`)6#]0#$$#$`U$`S`-4@90#4H!P` +MU.`<`-4@'`#D`5X`U``>`(`````&(`$`RA@```H@`0#6`'8`Q`@V`)B`!P#& +M$$4`E0$0`-0`'P#48&(`@````-0@8@#,.#4`S!0S`(0!W@#4`'(`U4`>`(`` +M``#N`!X`X@`:`(0!W@#B`!H`S!!+`,P$1P`LE`$`?0F+`)A`!0!]%`-0`;0"80)P`U`!N`,P(3`#,#$T`S!!(`-2`&@#4P!H` +M@`$D`-4`&@#,"#(`U``R`)2"M@#*#```U$`>`(````#4`!X`Y`$>`-0`'@#* +M"```R@P``,H0``#40!X`RA0``-2`'@#4P!X`U0`>`-5`'@#50#0`@````.X` +M'@`H!`0`X@`:`.(`&@#40!H`RC@``,P(`P#,#`,`S`P#`,P,`P"8@IH````` +M`(0!W@#7H&\`@````.X`'P#*!```PO\``,P(-`#!/_\`?'3+`'S)"P!]`0\` +MF0*-`'QSBP"$`=X`UZ!O`(````#N`!\`R@@``"@9``!]B8L`E8`4`"@4!`#* +M#```RA```,H<``#*)```X@`?`-3`&@#5`!H`U4`:`,P8`P#,+`,`S"P#`,PL +M`P!]I8L`?9Q'`)A"=```````@`&$`-3`&@#40!X`U(`>`(````#N`!X`Y`$> +M`-0`'@#40!X`[@`>`,H$``"@````?H*+`.0!/@#4`!X`U$`>`.X`'@#*!``` +MH````'Z"BP#*"```)(P&``S,!@"8P`8`S!!.`)D`!`#4`',`Y`$>`-0`'@#4 +M0!X`U(`>`(````#N`!X`R@@``,H,```TT!@`)1`!`)4`(0#!?_\`RA```,H4 +M``#*&```U(`=`-3`'0!]L8L`P4("`,+``0#5@!T`--P.`'U=3`!_ +M`-4`'@#50!X`P4(``,+````)G`$`,=P0`']?3`!_`(````#N +M`!X`@````.X`'P#4`!\`@````-0`'P#4`!\`B````-0`'P`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0&4``(!FP`#`+(`!`"B``4``P`& +M`#\`!P`R``@!3P`)`$8`"@`V`!`!V0`7`,4`(@%=`",!;``@`-<`)`%(`"8` +M30`G`%P`*`"-`"D`40`J`'X`*P!A`"\`B``R`*H`-`&B`#8`;P`\`7D`/P"5 +M`$$!KP!$`5$`50&6`%8!G0!@``L`80`T`&(`.`!C`#@`9``X`&4`.`!F`#@` +M9P`X`&@`.@!I`$$`:@!(`&L`2`!L`$@`;0!(`&X`2`!O`$@```````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````,``@%BT``````````@`I%B4`````````,``@-B4` +M````````)0`@%BT````````````O`*,```````````S```````"#````)@`@ +M%BT````````````O`*0```````````S```````"$``````!```````"*```` +M)0`@-B,`````````)@`@-B0`````````%P`@'BT``````````@`A`B<````` +M`````!3@``````"*``````!@``````9H``````!@``````9<`````@`A#B(` +M`````````!3```````"-````$L!`-B````"3`````"[@``````"1`````"S@ +M``````"0`````@!`#BT```"2`````P!`#BT```"2````#``@#BT````````` +M$@`@-B,``````````P`A#B(``````````!3```````"8``"@#``@1!$````` +M`````,`@2````````````,!`2`````"@``"@#``@1!$````````````@2!$` +M`````````"[@``````">`````"S@``````"=`````@!`#BT```"?`````P!` +M#BT```"?````#``@#BT````````````@2`,````````````Z#`(``````#\` +M```H#B,`````````$``A#B,`````````$0`@-B,`````````'@`A`BL````` +M`````!3```````"G````%L`@-B``````````'P`A`BL``````````!3````` +M``"J````%<`@-B``````````"``A#BL`````````?P`H#B,````````````O +M`B,```````````S@``````#A`````"<```````````````!@``````*C```` +M`0`O`B,```````````K@``````"S``````!@``````$Z@0`````@1!$````` +M````!@`@2!$`````````#``B'C``````F8`````@1!$`````````!``@$BT` +M````````"``B$B0`````````$``@&!$````````````I'.0```````````!@ +M2`<```$OFP`````@1!$````````````@2`(`````G``````@1!$````````` +M```S%&\``````````0`S/B,``````````-D`2``````````````@/`4````` +M@0`````@1!$`````````#@`@2!$````````````@$!````````#@!P`@1!$` +M````````#P`A`BL``````````!3```````#+`/C_"``@2!$`````F`````!` +M2!$```#<````\``H#B(`````````H``O`B,```````````S```````#:```` +M$0`@#BT``````````0`O`B,```````````S@``````#5`````@`O`B,````` +M``````S@``````#4```_``!`#!$```#6```?``!`#!$```#6```/```@#!$` +M`````#@`"0`I2B,`````/P`````H#BL``````````@`B#B,`````````!P!) +M2B,```#<`#@/"0`@2!$`````:```!P`@2!$`````````"``A2B<````````` +M```@2!$`````!@H"```I2B0````````````@2!$````````````@2!$````` +M``"B`@`@1!$``````/\````H#B(`````````@``I2B,`````````)P`@#BT` +M````````)@`@$BT````````````O`(,```````````S@``````#J``````!@ +M``````9B``````!```````#K``````!@``````9E````!P`@(BT````````` +M!0`B#B(``````!`````H#B,````````````I(&@````````````Z#`(````` +M````[P`H#B,````````````I(&@`````````%P`@#BT``````````P`A`B,` +M`````````!3@``````#X````"P`A`B@``````````!3```````#X```$```I +M(B@`````````%``@-B@`````````'``A#B(``````````!3```````#]``"C +M#``@1!$````````````@2!$`````````'@`A#B(``````````!3```````$+ +M``"C#P`@1!$`````````$0`@#BT``````````0`O`B,```````````S````` +M``$$_____P!`2!$```$+`````@`O`B,```````````S```````$'``#__P!` +M2!$```$+````!``O`B,```````````S```````$*````_P!`2!$```$+```` +M`0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3```````$2 +M````$$`A#B``````````$P`@-B,`````````&$`B2B``````````$,!"2B`` +M``$4```````@#!$`````````$P`@-B,````````````@2!$````````````@ +M2!$`````````"@`@$!$````````````O`B0```````````S@``````$;```` +M```@2!$``````````0!3$B0```$7_[___P`H.BX`````````&P`A`B(````` +M`````!3```````$N@0`````@1!$`````````#0`@2!$`````````&``B#C`` +M````_``````H#B,`````@0`````@1!$`````````#@`@2!$````````````@ +M$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,````````` +M'``@'BT`````````"``A2B<````````````@2!$`````!@H"```I2B0````` +M```````@2!$````````````@2!$```````````"`````````@0`````@1!$` +M`````````0`@2!$````````A?``@1!$``````(`````@2!$````````````@ +M2`8`````````"``A2B<``````````!<```````````0A?P!@1!$```:-```` +M'P`A`C```````````!3```````:,````!`!`3!$```$U@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````'``@2!$```````0A^0!@1!$` +M``:-````$0`A`C```````````!3@``````$\``````"```````````````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```` +M``!@``````%@``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%'`````,!`!``````!``````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```_ +M_P`O`B\```````````S@``````````````!@``````%@````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%8`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````&/``````!@``````&@```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&< +M``````!@``````*[`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*C```````O`B$```````````K@ +M``````&!``````!@``````$Z``````!```````&&E0`````@1!$````````` +M```O`B$```````````S@``````&&`````,`@2````````````0!3!B$```&" +MD@`````@1!$``````````,!@2`````&7``&A_0`@1!$`````````$0`@!BT` +M``````````!X!"H```+[```````@*`D````````__P`O`B\```````````S` +M``````%T`````,!`!``````!```"$`!@!!$```,5```__P`O`B\````````` +M``S@``````&4````%<`@-B``````````%L`@-B``````/X`````@!!$````` +M1@````!@"!$```&R``````"```````````"A_``@1!$````````__P`O`B\` +M``````````S```````&;`````0"`2!$`````````(0"`2!$```````#__T`H +M#B``````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`` +M```@1!$`````````!@`@2!$`````````"``B'C``````````*0`@&BT````` +M``#@```@1!$`````__O_"0`@2!$`````````#P`@(BT````````?_P`I2B@` +M````````!@`@(BT````````````I(.@````````````@2`@````````````@ +M2!$`````!@H"```I2B8````````````@2!$````````````@2!$````````! +M```@&!$`````````"`!B'B@```$O````"`""(B@```````+````@1!$````` +M````%0!@#BT```&]````%@!@#BT```&]``#`"``@1!$`````````%P`@#BT` +M`````````!3```````&Y```````@!!$````````````@2`$`````.0`````@ +M2!$````````````@2!$```````````"`2`(`````````&``@+BT````````` +M```[#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````` +M``````"`2`,```````````!@```````+```0``!@!!$```,5```````@!!$` +M``````````!@"!$```&R````!P`A!B\`````````$P`@"BT``````````0`@ +M+!$```````#__T`H(B``````````#P`F(B@`````````$$`A)B`````````` +M#P`F)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````` +M```````O`B$```````````S@``````'@```B7``@1!$`````````@0`@2!$` +M``````"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O +M`B<```````````S@``````'<``````!@``````'I`````0!3'B<```'8```` +M`0`@+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```'1 +M```B7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$` +M`````````0`P'B\````````````O`B<```````````S@``````````````!@ +M``````'I`````0!3'B<```'E``#__T`H#B``````````#P`F#B,````````` +M$,`A$B``````````#P`F$B0````````````@%!$```````````!@&!$```*[ +M``&A_0`@1!$````````````O`BL```````````S@``````'X````$``B%B@` +M````__\````H%B4```````#__P`H&BD````````````I2,4````````````@ +M2`H````````````@+!$`````````$``B%B,`````__\````H%B4```````#_ +M_P`H&B0````````````I2,4```````````!S%0,```(%```````@&`4````` +M``````!S%20```(%```````M%,4````````````P"*(````````````@2`(` +M```````````@*`(````````````@(`,```````````"`)`0`````````#P`A +M`B4``````````!3```````:,```````K%`4``````````0"0%B4````````` +M``!@```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R +M```B5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\` +M``````````S@`````````````,`@!``````````B7``@1!$``````````P`X +M2B$```````"A_``@1!$``````````0`@2!$```````#__T`H$B`````````` +M$,`A&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*[ +M``&A_0!@1!$```+@`````0`S!B$````````````O`B$```````````S````` +M``(9```__P`O`B\```````````S```````(2`````,!`!``````!``````!@ +M``````9%``````!`!`\```(3``````!@``````8Q``````!@``````9%```" +M$`!@!!$```,5``````!@``````&@``````!@``````&<``````!@``````*[ +M``````!@``````*CDX`````@1!$````````````@2`@````````````O`B\` +M``````````K@``````(R``````!@``````$Z``````!```````(VE0`````@ +M1!$````````````O`B\```````````S@``````(V`````,!`2`````(SD@`` +M```@1!$``````````,`@2``````````B5@`@1!$`````````%@`@2!$````` +M```B7``@1!$``````````P`@2!$```````"A_``@1!$``````````0`@2!$` +M``````&A_0`@1!$```````````!@!!$```+[`````,!`!``````!``````!@ +M``````8Q``"@#``@1!$``````````,`@2````````````,!`2``````````` +M``!@```````+````&$`A"B```````````P`O`B(```````````K@``````), +M````%``@(BT```````@!`0`I(B@`````````%``@-B@```````"C#``@1!$` +M`````````,`@2````````````,`@2````````````,!`2`````)1``````!@ +M```````+````$`!@!!$```,5/X`````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$```````````!@``````)\````%P`@'BT````` +M`````0`A'B<``````````!3@``````)J````$@`@'BT```````#__P`H'B<` +M```````````T'"<``````````!+```````)?```````@'!$````````````O +M`.4```````````C```````)B```````@%`<`````````$@`@'BT````````` +M$``A'B<````````````T'$<``````````!+```````)G```````@'!$````` +M```````O`.8```````````C```````)J```````@&`<```````````!@```` +M``+!```B5@`@1!$````````````T(",``````````!+```````)R```````T +M($0``````````!+```````)Q````%@!`2!$```)V````&`!`2!$```)V```` +M```T($0``````````!+```````)U````%P!`2!$```)V````&0`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_0!@1!$```+I```__P`O`B\` +M``````````S```````)6`````,!`!``````!````$$`A!B````````#__\`H +M"B``````````$$`A#B````````#__\`H$B``````````$$`A%B````````#_ +M_\"(&B``````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```:- +M``````!@``````8Q`````,!@``````*C````!0`@"BT`````````"``B"B(` +M````````*P`@&BT`````````'``@'BT```````!P```H'B<````````````Q +M'.8`````````*@`@&BT`````````#``B&B8````````````O`.8````````` +M``;@``````*2```````@'!$````````````@#!$`````````*P`@-B,````` +M````$``@&!$```````````!I'.(```$ODX`````@1!$````````````@2`<` +M````E0`````@1!$````````````O`B\```````````S@``````*=`````0`S +M/B\``````````-D`2```````D@`````@1!$``````````,`@2``````````` +M'`!`-B<`````````#,`B"B``````````*0`@-B(`````````*,!`-B`````` +M``"BI``@1!$`````````"0`@2!$`````H0`````@1!$``````````0"`2!$` +M````````(0`@'BT````````````L'.,`````````(0`@-B<`````````(@`@ +M'BT````````````L'.0`````````(@`@-B<`````````(P`@'BT````````` +M```Q(*,````````````M'0<`````````(P`@-B<`````````)``@'BT````` +M```````Q(,0````````````M'0<`````````)`"`-B<`````````(0`@-B,` +M````````(@`@-B0````````````Q'*,`````````(P`@-B<````````````Q +M',0`````````)`"`-B<`````````&@`@-B<`````````&P`@-B@````````` +M%P`@'BT``````````@`A`B<``````````!3```````+<``````!```````+9 +M````&@`@-B<`````````&P`@-B@`````````%P`@'BT``````````@`A`B<` +M`````````!3@``````+9`````P`A`B<``````````!3@``````+<````(P`@ +M'BT````````````N`.$```````````+```````+<````(0`@'BT````````` +M```Q(*$````````````N`.@```````````;```````+<````)``@'BT````` +M```````N`.(```````````+```````+<````(@`@'BT````````````Q(,(` +M```````````N`.@```````````;```````+<``````!@``````9H``````!@ +M``````*U``````!```````+>``````!@``````*U``````!@``````9?```` +M``!```````+>``````!@``````*G``````!```````+>````&@`@'BT````` +M````&P"`(BT`````````$``B'B,````````````I2(<````````````Q'*,` +M````````$``B'B<````````````I2(<`````````$``B'B,````````````Q +M(,0```````#__P`H(B@```````````")20<`````````$``B'B,````````` +M```I2(<`````````$``B'B$````````````I2$<````````````Q'*,````` +M````$``B'B<````````````I2(<````````````Q'*$`````````$``B'B<` +M```````````I2$<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<`````````$``B'B$````````````Q(,(```````#_ +M_P`H(B@```````````")20<`````````$``B'B,````````````I2(<````` +M`````0`B"B$````````````S"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<````````````Q'*,`````````$``B'B<````````````I +M2(<``````````0`B"B$````````````P"*(`````````$``B'B(````````` +M$``A(B(````````````I20<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@````````````I20<````````````X",4````````````P"$$` +M`````````0`B"B(````````````S"*(`````````$``B'B(`````````$``A +M(B(```````````")20<`````````%P`@(BT``````````!3```````,8____ +M[P`H!B$`````````%``@(BT```````#XX``@1!$````````````I20$````` +M``````")20$````````````@2!$````````````@2!$`````!@H"``"`2!$` +M`````````,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2````````````,`@!`````````````"@``H````` +MEP`````@1!$````````````@2!$`````B@`````@1!$````````````@2!$` +M```````B7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@ +M2````````````,`@!`````````````"@``H`````EP`````@1!$````````` +M```@2!$`````B@`````@1!$````````````@2!$````````B7``@1!$````` +M`````,`@2`````````"A_``@1!$``````````,`@2`````````&A_0`@1!$` +M`````````-D`2````````````,`@!`````````````"@``H````````B5P`@ +M1!$``````````\!(2B`````````B70`@1!$``````````,!`2``````````` +M``!@``````9%`````,`@"``````````B7``@1!$``````````P`X2B(````` +M``"A_``@1!$``````````,`@2`````````&A_0`@1!$````````````O`B(` +M``````````S@`````````````$`@2````````````4`P2B```````````L`P +M2B```````````0!3"B(```-+````/\`H"B``````@0`````@1!$````````` +M`0`@2!$````````A^``@1!$`````````&``@2!$```````0A^0!@1!$```:- +M````$0`A`C```````````!3@``````-4````%``O`B(```````````S````` +M``-D```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!@ +M2`(```-N```A```@1!$``````````,`@2````````````,`@2``````````` +M`,`@2````````````,!`2```````````!``O`B(```````````S```````-J +M```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!`2`(` +M``-?````*``O`B(```````````S```````7```&BI``@1!$```````````!` +M2`(```-?````+``@-B8`````````20`@&!$`````````/P`@2!$````````` +M`0`S&B8````````````O`B8```````````S```````-P````+`"`&BT````` +M````/\`H"B``````````%0`O`B(```````````S@``````.&````!@`O`B(` +M``````````S@``````.Q````%@`O`B(```````````S@``````.U````(``O +M`B(```````````S@``````.<````#P`O`B(```````````S@``````.H```` +M$``O`B(```````````S@``````.H````'@`O`B(```````````S@``````.0 +M``"BI``@1!$```````````!`2`(`````"``````I"B(``````````T`A#B`` +M````````#,`A$B````````@````H$B0`````````%,`B%B`````````````I +M%*0```````"BI``@1!$````````````I2*(```````"A_@`@1!$````````` +M``!`2`,`````@0`````@1!$``````````0`@2!$````````A^``@1!$````` +M````%@`@2!$```````0A^0!@1!$```:-````%0`A`C```````````!3@```` +M``.2```A#@`@1!$``````````,`@2````````````,`@2`````````"BI``@ +M1!$```````````!`2`(`````@0`````@1!$``````````0`@2!$````````A +M^``@1!$`````````%P`@2!$```````0A^0!@1!$```:-`````P`A`C`````` +M`````!3@``````.>```A"``@1!$``````````,`@2````````````,`@2``` +M``````"BI``@1!$```````````!`2`(```````"BI``@1!$````````````@ +M2`(`````@``````@1!$````````````@2!$`````@0`````@1!$````````` +M$``@2!$````````````@`!```````````!3```````.N``````!````````` +M```@$``@1!$```````"````@2!$```````&BI``@1!$`````````!@!`2!$` +M```````@$``@1!$```````"````@2!$```````&BI``@1!$`````````%@!@ +M2!$```-N``````!``````````````,`@"````````````,`@#``````````` +M'0`A`B,``````````!3@``````/.@0`````@1!$``````````0`@2!$````` +M```A^``@1!$`````````&``@2!$```````0A^0!@1!$```:-````$0`A`C`` +M`````````!3@``````/````A```@1!$````````````@2`(````````````@ +M2`,`````NK[*_@`@2!$`````ROZZO@`@2!$````````@$``@1!$```````"` +M```@2!$```````"BI``@1!$`````````!`!`2!$````````A<``@1!$````` +M```````@2`(````````````@2`,`````@0`````@1!$`````````"@`@2!$` +M```````````@`!```````````!3```````/3C``````@1!$`````ROZZO@!` +M2!$`````@0`````@1!$``````````0`@2!$````````__T`H"B``````@``` +M`$`H#B``````0````,`H$B````````0```!I1B(```:-```````@%!`````` +M```````O`B,```````````S```````/A`````,!`&`````/D```__\`H&B`` +M``````0```!I1B8```:-```````@&!`````````````O`B0```````````S` +M``````/G`````,!`'`````/J```__\`H'B````````0```!I1B<```:-```` +M```@'!`````````````@1`(````````````H(,4```````````!)2.@````` +MI8`````@"!$````````@```@#!$`````@P````!@1!$```02```````@1`(` +M`````````,`@2````````````$`@2```````````'\`A`B```````````!3` +M``````/W```@$``@1!$```````"````@2!$```````#__\!($B````/_IX`` +M```@"!$```````"@```@#!$`````@P````!@1!$```02```````@1`(````` +M`````,`@2````````````,`@2`````````#__\`H$B``````@P`````@1!$` +M```````````P2(,`````A``````@1!$``````````,`@2````````````!T` +M````````@P````!@1!$```02`````,!`!``````!J8`````@"!$```````#` +M``!`#!$```/ZJX`````@"!$```````#XX`!`#!$```/ZK8`````@"!$````` +M``#X@`!`#!$```/ZLX`````@"!$```````#S_`!`#!$```/ZKX`````@"!$` +M``````#@``!`#!$```/ZL8`````@"!$```````#P``!`#!$```/Z@P`````@ +M1!$````````A2``@2!$`````A``````@1!$``````````,`@2``````````` +M`!T```````````````"``````````1@@`,`P1B```````````-D`2``````` +M`````,`@!`````````````"@``H``````AB@`,`P1B```````````-D`2``` +M`````````,`@!`````````````"@``H``````QC``,`P1B```````````-D` +M2````````````,`@!`````````````"@``H`````!!CXX,`P1B`````````` +M`-D`2````````````,`@!`````````````"@``H`````!1CX@,`P1B`````` +M`````-D`2````````````,`@!`````````````"@``H`````!AC@`,`P1B`` +M`````````-D`2````````````,`@!`````````````"@``H`````!QCP`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H`````"!CS +M_,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M````,``@"BT``````````,`I#$``````````,``@-B,``````````,`@!``` +M``````````"@``H`````A@`````@1!$```````````!`2`$`````A0```,`@ +M1!$```````````!`2`$````````A?``@1!$`````````&$`A`B`````````` +M`!3```````1%`(```,!)2B````1&`````,`@2````````````,`@2``````` +M`````,`@2```````@0`````@1!$``````````0`@2!$``````````,`@"``` +M`````````!<```````````0A?P!@1!$```:-````'P`A`C```````````!3` +M``````````````!`3`(```1+`````,`@#````````````,`@$``````````` +M`,`@%````````````,`@&````````````,`@'`````````!_```H"B$````` +M``!%```O`B(```````````S@``````19`````,`@(````````````!<````` +M````````$``H"B,`````````$``O`B(```````````S@``````1A@0`````@ +M1!$``````````0`@2!$```````0```!I1B0```:-``````!```````1F@0`` +M```@1!$````````````@2!$````````A;0`@1!$````````````@2`0````` +M``````!@2`4```:2```````H)/``````````!P`H"B,``````````0`O`B(` +M``````````K@``````1M```````O`,D```````````3@``````2&``````!` +M``````23`````@`O`B(```````````K@``````1R```````O`,D````````` +M``+@``````2&``````!```````23`````P`O`B(```````````K@``````1W +M```````O`,D```````````S@``````2&``````!```````23````!``O`B(` +M``````````K@``````1\```````O`,D```````````K@``````2&``````!` +M``````23````!0`O`B(```````````K@``````2!```````O`,D````````` +M``;@``````2&``````!```````23````!@`O`B(```````````K@``````2& +M```````O`,D```````````C@``````2&``````!```````23``!_```H"B$` +M``````!%```O`B(```````````K@````````````"``A"B,``````````!3` +M``````20```A:0`@1!$``````````,`@2````````````,`@2``````````` +M`,`@2```````ROZZO@!`2!$``````````,`@1````````````,`@```````` +M`````,!`2`````````!_```H"B$```````!%```O`B(```````````K@```` +M``29`````,`@`````````````,`@`````````````,!```````````````!` +M3`@```19`````,`@"```````````$$`A#B``````````$4`A$B`````````` +M$D`A%B`````````A:0`@1!$````````````@2`(````````````A`B4````` +M`````!3@``````2C``0``,!)2B````2D__O__\`H2B`````````````A`B,` +M`````````!3@``````2P`````,`@2````````````,`@2``````````````A +M`B0``````````!3`````````@0`````@1!$`````````#``@2!$````````` +M```@`!```````````!3```````2LH``````@1!$`````ROZZO@!`2!$````` +M@0`````@1!$`````````!``@2!$````````A:P`@1!$``````````,`@2!`` +M````@0`````@1!$`````````!0`@2!$````````A;``@1!$``````````,`@ +M2!`````````````O`B0```````````S@``````````````!```````2J```` +M`,`A"B```````````!3```````3#@0`````@1!$````````````@2!$````` +M```A;0`@1!$``````````,`@2````````````,!@2`````:2``````!````` +M``3'@0`````@1!$``````````0`@2!$```````0``,`I1B```````````,!@ +M``````:-`````0`A`B(``````````!3```````3.```A:0`@1!$````````` +M`,`@2````````````,`@2``````````````@2!``````ROZZO@!`2!$````` +M`````,`@1````````````,!`2!``````@0`````@1!$``````````0`@2!$` +M```````A^``@1!$`````````#@`@2!$```````0A^0!@1!$```:-```````A +M`C```````````!3```````30```A@``@1!$``````````,`@2``````````` +M`,`@`````````````,`@2````````````,`@`````````````,!`2``````` +M`````P`S/B\``````````0`A`B$``````````!3@``````4`````+``@"BT` +M``````0``!C@#!$```3O`````0`S/B\````````A:0`@1!$````````````@ +M2`(````````````@2`,`````````"``P"B(``````````,`@2``````````` +M`,`@2``````````A:0`@1!$````````````@2`(````````````@2`,````` +M````"``P"B(``````````,`@2````````````-C`2`````3C```A:0`@1!$` +M```````````@2`(````````````@2`,`````````"``P"B(``````````,`@ +M2````````````,`@2```````````+0`@$BT````````````I#(,````````A +M:0`@1!$````````````@2`(````````````@2`,`````````"``P"B(````` +M`````,`@2````````````,`@2```````````$0`A`B0``````````!3````` +M``````````!```````2J````+,`@-B``````````+``"B +MT@`@1!$```````````!`2`@```````"BT@`@1!$``````````0!02B@````` +M`````@`O`B0```````````S```````6Q``"BOP`@1!$````````````@2`<` +M````@0`````@1!$``````````0`@2!$```````2BO@!@1!$```:-````&@`A +M(C``````````!@`B)C````````0@!`!@1!$```:-``"BQ@`@1!$````````` +M```P2.D```````````#@``````6O``"BTP`@1!$```````````!`2`@````` +M``"BTP`@1!$``````````0!02B@```````"BPP`@1!$````````````@2`<` +M````@0`````@1!$``````````0`@2!$```````2BP@!@1!$```:-````&@`A +M(C``````````!@`B)C````````0@!`!@1!$```:-``"BQP`@1!$````````` +M```P2.D```````````#@``````6^``"BU``@1!$```````````!`2`@````` +M``"BU``@1!$``````````0!02B@`````A0`````@1!$````````````@2`$` +M```````P2@`@1!$``````0`````@2!$```````````!```````7$I````,`@ +M1!$``````````,!`2````````````,!@``````7)`````,!`!``````!```` +M+``@-B$`````@0`````@1!$`````````!@`@2!$````````````O`C`````` +M``````S```````70```````@!!$`````````,`!`-B$```7C````,``@!BT` +M``````!^```H!B$````````````O`B$```````````S@``````7C@0`````@ +M1!$``````````0`@2!$```````2@D@!@1!$```:-````,0`@-C````````2@ +MDP!@1!$```:-````,@`@-C````````2BM@!@1!$```:-````,P`@-C`````` +M``2BN@!@1!$```:-````-``@-C````````2BO@!@1!$```:-````-0`@-C`` +M``````2BP@!@1!$```:-````-@`@-C````````0@!`!@1!$```:-``&BI``@ +M1!$`````````/P`@2!$`````````/P`@2!$`````````/P`@2!$````````` +M/P`@2!$`````````!0`@2!$```````"A]``@1!$````````````@2!$````` +MB``````@1!$``````````0`@2!$`````@0`````@1!$`````````!@`@2!$` +M`````````0`O`C````````````S@``````8L````,``@!BT````````````O +M`B$```````````S@``````8L@0`````@1!$``````````0`@2!$```````!^ +M```H!B$````````````O`B$```````````S@``````8%``"@D@`@1!$````` +M````,0`@2BT```````"@DP`@1!$`````````,@`@2BT```````"BM@`@1!$` +M````````,P`@2BT```````"BN@`@1!$`````````-``@2BT```````"BO@`@ +M1!$`````````-0`@2BT```````"BP@`@1!$`````````-@`@2BT````````` +M,``@!BT````````!_P`H!B$````````````O`B$```````````S@``````8K +M```````A`B$``````````!3```````8.``2@`P!@1!$```:-``"@`P`@1!$` +M```````````@2!```````````0`A!B$``````````!3```````83``2@$`!@ +M1!$```:-``"@$``@1!$````````````@2!```````````0`A!B$````````` +M```O`B$```````````S@``````8K``2@$0!@1!$```:-``"@$0`@1!$````` +M```````@2!````````2@$@!@1!$```:-``"@$@`@1!$````````````@2!`` +M``````2@$P!@1!$```:-``"@$P`@1!$````````````@2!````````2@%`!@ +M1!$```:-``"@%``@1!$````````````@2!````````2@%0!@1!$```:-``"@ +M%0`@1!$````````````@2!````````2@%@!@1!$```:-``"@%@`@1!$````` +M```````@2!````````2@%P!@1!$```:-``"@%P`@1!$````````````@2!`` +M``````0@!`!@1!$```:-````+`"`!BT`````_P`````@1!$````````````@ +M2!$``````````0`@2!$``````````@"`2!$```````````[@``````8]```` +M,``@!BT``````````@`H!B$````````````O`B$```````````S@``````8[ +M@0`````@1!$``````````0`@2!$```````0@!`!@1!$```:-```0```@"!$` +M````````*P`@-B(```````````!@``````9!``````!@``````7)F``````@ +M1!$```````````"`2!$``````````,!@``````9!`````,!`!``````!``"B +MI``@1!$`````````(@`@2!$`````B0`````@1!$``````````0!`2!$```8M +MEP`````@1!$````````````@2!$`````B@`````@1!$```````````!`2!$` +M``8M``````!@``````9<```@$``@1!$```````"````@2!$```````&BI,`@ +M1!$`````````%@!@2!$```-N```@$``@1!$```````$````@2!$`````@0`` +M```@1!$``````````0`@2!$````````A?``@1!$`````"8`````@2!$````` +M_____P`@2!$````````````@2!$``````````!<```````````0A?P!@1!$` +M``:-````'P`A`C```````````!3`````````````!`!`3!$```96``````!` +M````````````%P`@'BT`````````!``I'B<`````````%P"`-B<````````` +M%P`@'BT`````____^P`H'B<`````````%P"`-B<`````````%P`@'BT````` +M````"``I'B<`````````%P"`-B<`````````%P`@'BT`````____]P`H'B<` +M````````%P"`-B<````````@$``@1!$```````"````@2!$```````&BI``@ +M1!$`````````%@!@2!$```-N```@$``@1!$```````$````@2!$````````A +M?``@1!$``````8`````@2!$`````_____P`@2!$````````````@2!$````` +M`````!<`````````@0`````@1!$``````````0`@2!$```````0A?P!@1!$` +M``:-````'P`A`C```````````!3```````:,````$`!`3!$```9R`````,`@ +M!````````````#C`````````````'0`@"BT`````````'@`@#BT````````` +M'P`@$BT`````````(``@%BT````````A:0`@1!$````````````@2`0````` +M```````@2`4````````````@2`$`````ROZZO@`@2!$`````````!``P$B0` +M```````````O`&0```````````S```````:+`````P`H&B(`````````"``B +M$B(`````___P```H$B0````````````I$,0`````````'P!`-B0````````` +M``"``````````````!K```````:-GP`````@1!$`````ROZZO@`@2!$````` +M`````!K@``````:0``````"``````````````!K```````:2G@`````@1!$` +M````ROZZO@`@2!$``````````!K@``````:5``````"```````````````!@ +M```````+```0``!@!!$```,5```````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$````````B5@`@1!$`````````&P`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_<`@1!$`````````(0`@'BT` +M````````$``B'B<`````````)``@(BT```````#__P`H(B@````````````I +M20<````````````@2!$`````````(@`@(BT```````#__P`H(B@````````` +M```I20<````````````@2!$`````````(P`@'BT`````````$``B'B<````` +M```````I20<```````````!`2!$````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````4(%`@7``E```````<,!:`0_!<```````B4" +M"0)0`5$``````B,"10*@`D$``````]<%P`7`!<``````!DD&2@,?!<`````` +M!<`%Q0,@`T```````RH"@@-"`S0`````!<`%P`7`!<``````!<`%407`!<`` +M`````[H%P`2[`T0`````!)H$4`0]!<``````!-`%P`1!!-T`````!%`%!P-1 +M`W4`````!<`%P`7`!<``````!<`%P`7`!<``````!<`%P`8_!<<`````!<`% +MP``'!<``````!<`%P`7`!<``````!<`%P`7`!<```````_@#[00(!`8````` +M!`X$"@0,!!``````!!P$&`0D!"``````!"P$*`0T!#``````!<`%P`0X!<`` +G````!<`%P`7`!<``````!<`%P`7`!<````````(&>0:7``8````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV610_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV610_pfp.bin.uu new file mode 100644 index 00000000000..eb33b723c34 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV610_pfp.bin.uu @@ -0,0 +1,55 @@ +begin 644 RV610_pfp.bin +M`,H$``"@````?H*+`'P#BP"``;@`?`.+`-1`'@#N`!X`R@0``*````!^@HL` +MQ!@X`,HD``#**```E8&H`,0<.@##P```R@@``,H,``!\=$L`P@`%`)G```#$ +M'#H`?'1,`,#_\``$+`0`,)`"`'TE```U%`(`?34+`"54`P!\U8``)9P#`)7` +M!`#5`!L`?MW!`'V=@`#6@!L`U8`;`-1`'@#50!X`UD`>`-:`'@#4@!X`U,`> +M`)>#TP#5P!X`R@@``(``&@#*#```Y`$>`-0`'@"```P`Q!@X`.0!/@#4`!X` +M@``,`,08.`#40!X`[@`>`,H$``"@````?H*+`.0!'@#4`!X`U$`>`.X`'@#* +M!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^@HL`RA@``-1` +M'@#5@!X`@`!3`-0`=0#40!X`R@@``,H,``#*$```U(`9`-3`&`#5`!<`U(`> +M`-3`'@#5`!X`X@`>`,H$``"@````?H*+`,H(``#4@&``U$`>`(````#4@!X` +MR@@``-2`80#40!X`@````-2`'@#*"```R@P``-1`'@#4@!8`U,`6`-2`'@"` +M`;@`U,`>`,8(0P#*#```RA```)2`!`#*%```Y"#S`-0@$P#58&4`U.`<`-4@ +M'`#58!P`@`````8@`0#&"$,`R@P``,H0``"4@_<`RA0``.0@\P"``'D`U"`3 +M`,8(0P#*#```RA```)B#[P#*%```U`!D`(``C0``````Q!0R`,880P#$""\` +ME4`%`,0,,`#40!X`@````.X`'@"5@_4`Q!`Q`-1`,P#5(&4`U*`<`-3@'`#5 +M(!P`Y`%>`-0`'@"`````!B`!`,H8```*(`$`U@!V`,0(-@"8@`<`QA!%`)4! +M$`#4`!\`U&!B`(````#4(&(`S#@U`,P4,P"$`;L`U`!R`-5`'@"`````[@`> +M`.(`&@"$`;L`X@`:`,P02P#,!$<`+)0!`'T)BP"80`4`?17+`-0`&@"``;@` +MU`!M`#1$`0#,#$@`F$`Z`,PL2@"5@`0`S`1)`(`!N`#4`!H`U,`:`"@H`0"$ +M`/``S!`#`)B`&P`$.`P`A`#P`,P0`P"8@!<`!#@(`(0`\`#,$`,`F(`3``0X +M!`"$`/``S!`#`)B`%`#,$$P`FH`)`,P430"80-P`U`!M`,P82`#5`!H`U4`: +M`(``R0#5@!H`EL#5`-0`;0"``;@`U`!N`)K``P#4`&T`U`!N`(````#L`'\` +MFL#,`-0`;0"``;@`U`!N`,P4`P#,&`,`S!P#`'V1`P!]U8,`?1D,`#7,'P`U +M`.0!'@#4`!X`R@@``,H, +M``#*$```U$`>`,H4``#4@!X`U,`>`-4`'@#50!X`U4`T`(````#N`!X`*`0$ +M`.(`&@#B`!H`U$`:`,HX``#,"`,`S`P#`,P,`P#,#`,`F(*]``````"$`;L` +MUZ!O`(````#N`!\`R@0``,+_``#,"#0`P3__`'QTRP!\R0L`?0$/`)D"L`!\ +M@;P"`````[@`?`,H(```H&0``?8F+`)6`%``H%`0`R@P``,H0 +M``#*'```RB0``.(`'P#4P!H`U0`:`-5`&@#,&`,`S"P#`,PL`P#,+`,`?:6+ +M`'V<1P"80I<``````(`!80#4P!H`U$`>`-2`'@"`````[@`>`.0!'@#4`!X` +MU$`>`.X`'@#*!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^ +M@HL`R@@``"2,!@`,S`8`F,`&`,P03@"9``0`U`!S`.0!'@#4`!X`U$`>`-2` +M'@"`````[@`>`,H(``#*#```--`8`"40`0"5`"$`P7__`,H0``#*%```RA@` +M`-2`'0#4P!T`?;&+`,%"`@#"P`$`U8`=`#3<#@!]74P`?W-,`-=`'@#5`!X` +MU4`>`,%"``#"P```"9P!`#'<$`!_7TP`?W-,``0H`@!]@X``U:AO`-6`9@#7 +M0!X`[`!>`,@D`@#()`(`@`&X`-8`=@#40!X`U(`>`-3`'@"`````[@`>`(`` +M``#N`!\`U``?`(````#4`!\`U``?`(@```#4`!\````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0%Q``(!>``#`(\`!`!_``4``P`& +M`#\`!P`R``@!+``)`$8`"@`V`!`!M@`7`*(`(@$Z`",!20`@`+0`)`$E`"<` +M30`H`&H`*@!@`"L`4@`O`&4`,@"'`#0!?P`\`58`/P!R`$$!C`!$`2X`50%S +M`%8!>@!@``L`80`T`&(`.`!C`#@`9``X`&4`.`!F`#@`9P`X`&@`.@!I`$$` +M:@!(`&L`2`!L`$@`;0!(`&X`2`!O`$@````&````!@````8````&````!@`` +M``8````&````!@````8````&````!@````8````&````!@````8````&```` +)!@````8````& +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV620_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV620_me.bin.uu new file mode 100644 index 00000000000..fa545b4931e --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV620_me.bin.uu @@ -0,0 +1,481 @@ +begin 644 RV620_me.bin +M`````,`@!`````````````"@``H```````#__P`H1B$``````````-D`2``` +M`````````,`@!`````````````"@``H```````````#@``````````$``,`I +M1B```````````-D`2````````````,`@!`````````````"@``H`````@0`` +M```@1!$``````````0`@2!$```````0@!`!@1!$```:-``````!@``````8Q +M``````!@``````9%`````,`@"``````````/```H%B(`````````"``A%B4` +M````````&``@-B4`````C0`````@1!$`````````!``O`B4```````````S@ +M```````8`$$@``!`2!$````9`$(@```@2!$`````C@`````@1!$````````` +M*``@2BT`````D``````@1!$````````````@2`4`````````#``A%B(````` +M`````P`H%B4`````````&0`A&B(`````````!``H&B8````````````I%,4` +M````````&0`@-B4````````````Z%`(`````````%@`A%B4``````````P`H +M%B4`````````%P`@#BT`````_____``H#B,````````````I%*,````````` +M%P`@-B4```````"````H#B(`````````!P`B#B,````````````I.&X````` +M(``````H#B(`````````!@`A#B,````````````I.&X````````````B`B(` +M`````````!3@```````X`````"[@```````U`````"S@```````W``````!` +M#BT````Y````"``@#BT`````````"0!`$BT```!&`````0!`#BT````Y```` +M`,`@#````````#___``H$B,``````````@`B$B0`````````'P`A'B,````` +M`````!3@```````^````"`!`'!$```!!````#0`@'BT`````````#P`H'B<` +M`````````P`B'B<`````?\`````H&B,`````````%``A&B8``````````0`S +M&B8`````````"``B&B8````````````I#,<`````````)P`@-B0```````!_ +M```H$B$````````4```O`B0```````````S@``````!+`````0`I#B,````` +M````#@`@-B,```````#@```@1!$`````__@````I2B,````````````Z+`(` +M`````````@`B#BL`````_``````H#B,`````````#P`@-B,````````?_P`I +M2B,`````````)P`@2BT````````````@2!$`````````*0`@#BT`````!@H" +M```I2B,````````````@2!$````````````@2!$``````````0`A`B(````` +M`````!3@``````!A`````"[@``````!?`````"S@``````!>``````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````,``@%BT``````````@`I%B4`````````,``@-B4` +M````````)0`@%BT````````````O`*,```````````S```````"#````)@`@ +M%BT````````````O`*0```````````S```````"$``````!```````"*```` +M)0`@-B,`````````)@`@-B0`````````%P`@'BT``````````@`A`B<````` +M`````!3@``````"*``````!@``````9H``````!@``````9<`````@`A#B(` +M`````````!3```````"-````$L!`-B````"3`````"[@``````"1`````"S@ +M``````"0`````@!`#BT```"2`````P!`#BT```"2````#``@#BT````````` +M$@`@-B,``````````P`A#B(``````````!3```````"8``"@#``@1!$````` +M`````,`@2````````````,!`2`````"@``"@#``@1!$````````````@2!$` +M`````````"[@``````">`````"S@``````"=`````@!`#BT```"?`````P!` +M#BT```"?````#``@#BT````````````@2`,````````````Z#`(``````#\` +M```H#B,`````````$``A#B,`````````$0`@-B,`````````'@`A`BL````` +M`````!3```````"G````%L`@-B``````````'P`A`BL``````````!3````` +M``"J````%<`@-B``````````"``A#BL`````````?P`H#B,````````````O +M`B,```````````S@``````#A`````"<```````````````!@``````*C```` +M`0`O`B,```````````K@``````"S``````!@``````$Z@0`````@1!$````` +M````!@`@2!$`````````#``B'C``````F8`````@1!$`````````!``@$BT` +M````````"``B$B0`````````$``@&!$````````````I'.0```````````!@ +M2`<```$OFP`````@1!$````````````@2`(`````G``````@1!$````````` +M```S%&\``````````0`S/B,``````````-D`2``````````````@/`4````` +M@0`````@1!$`````````#@`@2!$````````````@$!````````#@!P`@1!$` +M````````#P`A`BL``````````!3```````#+`/C_"``@2!$`````F`````!` +M2!$```#<````\``H#B(`````````H``O`B,```````````S```````#:```` +M$0`@#BT``````````0`O`B,```````````S@``````#5`````@`O`B,````` +M``````S@``````#4```_``!`#!$```#6```?``!`#!$```#6```/```@#!$` +M`````#@`"0`I2B,`````/P`````H#BL``````````@`B#B,`````````!P!) +M2B,```#<`#@/"0`@2!$`````:```!P`@2!$`````````"``A2B<````````` +M```@2!$`````!@H"```I2B0````````````@2!$````````````@2!$````` +M``"B`@`@1!$``````/\````H#B(`````````@``I2B,`````````)P`@#BT` +M````````)@`@$BT````````````O`(,```````````S@``````#J``````!@ +M``````9B``````!```````#K``````!@``````9E````!P`@(BT````````` +M!0`B#B(``````!`````H#B,````````````I(&@````````````Z#`(````` +M````[P`H#B,````````````I(&@`````````%P`@#BT``````````P`A`B,` +M`````````!3@``````#X````"P`A`B@``````````!3```````#X```$```I +M(B@`````````%``@-B@`````````'``A#B(``````````!3```````#]``"C +M#``@1!$````````````@2!$`````````'@`A#B(``````````!3```````$+ +M``"C#P`@1!$`````````$0`@#BT``````````0`O`B,```````````S````` +M``$$_____P!`2!$```$+`````@`O`B,```````````S```````$'``#__P!` +M2!$```$+````!``O`B,```````````S```````$*````_P!`2!$```$+```` +M`0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3```````$2 +M````$$`A#B``````````$P`@-B,`````````&$`B2B``````````$,!"2B`` +M``$4```````@#!$`````````$P`@-B,````````````@2!$````````````@ +M2!$`````````"@`@$!$````````````O`B0```````````S@``````$;```` +M```@2!$``````````0!3$B0```$7_[___P`H.BX`````````&P`A`B(````` +M`````!3```````$N@0`````@1!$`````````#0`@2!$`````````&``B#C`` +M````_``````H#B,`````@0`````@1!$`````````#@`@2!$````````````@ +M$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,````````` +M'``@'BT`````````"``A2B<````````````@2!$`````!@H"```I2B0````` +M```````@2!$````````````@2!$```````````"`````````@0`````@1!$` +M`````````0`@2!$````````A?``@1!$``````(`````@2!$````````````@ +M2`8`````````"``A2B<``````````!<```````````0A?P!@1!$```:-```` +M'P`A`C```````````!3```````:,````!`!`3!$```$U@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````'``@2!$```````0A^0!@1!$` +M``:-````$0`A`C```````````!3@``````$\``````"```````````````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```` +M``!@``````%@``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%'`````,!`!``````!``````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```_ +M_P`O`B\```````````S@``````````````!@``````%@````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%8`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````&/``````!@``````&@```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&< +M``````!@``````*[`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*C```````O`B$```````````K@ +M``````&!``````!@``````$Z``````!```````&&E0`````@1!$````````` +M```O`B$```````````S@``````&&`````,`@2````````````0!3!B$```&" +MD@`````@1!$``````````,!@2`````&7``&A_0`@1!$`````````$0`@!BT` +M``````````!X!"H```+[```````@*`D````````__P`O`B\```````````S` +M``````%T`````,!`!``````!```"$`!@!!$```,5```__P`O`B\````````` +M``S@``````&4````%<`@-B``````````%L`@-B``````/X`````@!!$````` +M1@````!@"!$```&R``````"```````````"A_``@1!$````````__P`O`B\` +M``````````S```````&;`````0"`2!$`````````(0"`2!$```````#__T`H +M#B``````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`` +M```@1!$`````````!@`@2!$`````````"``B'C``````````*0`@&BT````` +M``#@```@1!$`````__O_"0`@2!$`````````#P`@(BT````````?_P`I2B@` +M````````!@`@(BT````````````I(.@````````````@2`@````````````@ +M2!$`````!@H"```I2B8````````````@2!$````````````@2!$````````! +M```@&!$`````````"`!B'B@```$O````"`""(B@```````+````@1!$````` +M````%0!@#BT```&]````%@!@#BT```&]``#`"``@1!$`````````%P`@#BT` +M`````````!3```````&Y```````@!!$````````````@2`$`````.0`````@ +M2!$````````````@2!$```````````"`2`(`````````&``@+BT````````` +M```[#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````` +M``````"`2`,```````````!@```````+```0``!@!!$```,5```````@!!$` +M``````````!@"!$```&R````!P`A!B\`````````$P`@"BT``````````0`@ +M+!$```````#__T`H(B``````````#P`F(B@`````````$$`A)B`````````` +M#P`F)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````` +M```````O`B$```````````S@``````'@```B7``@1!$`````````@0`@2!$` +M``````"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O +M`B<```````````S@``````'<``````!@``````'I`````0!3'B<```'8```` +M`0`@+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```'1 +M```B7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$` +M`````````0`P'B\````````````O`B<```````````S@``````````````!@ +M``````'I`````0!3'B<```'E``#__T`H#B``````````#P`F#B,````````` +M$,`A$B``````````#P`F$B0````````````@%!$```````````!@&!$```*[ +M``&A_0`@1!$````````````O`BL```````````S@``````'X````$``B%B@` +M````__\````H%B4```````#__P`H&BD````````````I2,4````````````@ +M2`H````````````@+!$`````````$``B%B,`````__\````H%B4```````#_ +M_P`H&B0````````````I2,4```````````!S%0,```(%```````@&`4````` +M``````!S%20```(%```````M%,4````````````P"*(````````````@2`(` +M```````````@*`(````````````@(`,```````````"`)`0`````````#P`A +M`B4``````````!3```````:,```````K%`4``````````0"0%B4````````` +M``!@```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R +M```B5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\` +M``````````S@`````````````,`@!``````````B7``@1!$``````````P`X +M2B$```````"A_``@1!$``````````0`@2!$```````#__T`H$B`````````` +M$,`A&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*[ +M``&A_0!@1!$```+@`````0`S!B$````````````O`B$```````````S````` +M``(9```__P`O`B\```````````S```````(2`````,!`!``````!``````!@ +M``````9%``````!`!`\```(3``````!@``````8Q``````!@``````9%```" +M$`!@!!$```,5``````!@``````&@``````!@``````&<``````!@``````*[ +M``````!@``````*CDX`````@1!$````````````@2`@````````````O`B\` +M``````````K@``````(R``````!@``````$Z``````!```````(VE0`````@ +M1!$````````````O`B\```````````S@``````(V`````,!`2`````(SD@`` +M```@1!$``````````,`@2``````````B5@`@1!$`````````%@`@2!$````` +M```B7``@1!$``````````P`@2!$```````"A_``@1!$``````````0`@2!$` +M``````&A_0`@1!$```````````!@!!$```+[`````,!`!``````!``````!@ +M``````8Q``"@#``@1!$``````````,`@2````````````,!`2``````````` +M``!@```````+````&$`A"B```````````P`O`B(```````````K@``````), +M````%``@(BT```````@!`0`I(B@`````````%``@-B@```````"C#``@1!$` +M`````````,`@2````````````,`@2````````````,!`2`````)1``````!@ +M```````+````$`!@!!$```,5/X`````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$```````````!@``````)\````%P`@'BT````` +M`````0`A'B<``````````!3@``````)J````$@`@'BT```````#__P`H'B<` +M```````````T'"<``````````!+```````)?```````@'!$````````````O +M`.4```````````C```````)B```````@%`<`````````$@`@'BT````````` +M$``A'B<````````````T'$<``````````!+```````)G```````@'!$````` +M```````O`.8```````````C```````)J```````@&`<```````````!@```` +M``+!```B5@`@1!$````````````T(",``````````!+```````)R```````T +M($0``````````!+```````)Q````%@!`2!$```)V````&`!`2!$```)V```` +M```T($0``````````!+```````)U````%P!`2!$```)V````&0`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_0!@1!$```+I```__P`O`B\` +M``````````S```````)6`````,!`!``````!````$$`A!B````````#__\`H +M"B``````````$$`A#B````````#__\`H$B``````````$$`A%B````````#_ +M_\"(&B``````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```:- +M``````!@``````8Q`````,!@``````*C````!0`@"BT`````````"``B"B(` +M````````*P`@&BT`````````'``@'BT```````!P```H'B<````````````Q +M'.8`````````*@`@&BT`````````#``B&B8````````````O`.8````````` +M``;@``````*2```````@'!$````````````@#!$`````````*P`@-B,````` +M````$``@&!$```````````!I'.(```$ODX`````@1!$````````````@2`<` +M````E0`````@1!$````````````O`B\```````````S@``````*=`````0`S +M/B\``````````-D`2```````D@`````@1!$``````````,`@2``````````` +M'`!`-B<`````````#,`B"B``````````*0`@-B(`````````*,!`-B`````` +M``"BI``@1!$`````````"0`@2!$`````H0`````@1!$``````````0"`2!$` +M````````(0`@'BT````````````L'.,`````````(0`@-B<`````````(@`@ +M'BT````````````L'.0`````````(@`@-B<`````````(P`@'BT````````` +M```Q(*,````````````M'0<`````````(P`@-B<`````````)``@'BT````` +M```````Q(,0````````````M'0<`````````)`"`-B<`````````(0`@-B,` +M````````(@`@-B0````````````Q'*,`````````(P`@-B<````````````Q +M',0`````````)`"`-B<`````````&@`@-B<`````````&P`@-B@````````` +M%P`@'BT``````````@`A`B<``````````!3```````+<``````!```````+9 +M````&@`@-B<`````````&P`@-B@`````````%P`@'BT``````````@`A`B<` +M`````````!3@``````+9`````P`A`B<``````````!3@``````+<````(P`@ +M'BT````````````N`.$```````````+```````+<````(0`@'BT````````` +M```Q(*$````````````N`.@```````````;```````+<````)``@'BT````` +M```````N`.(```````````+```````+<````(@`@'BT````````````Q(,(` +M```````````N`.@```````````;```````+<``````!@``````9H``````!@ +M``````*U``````!```````+>``````!@``````*U``````!@``````9?```` +M``!```````+>``````!@``````*G``````!```````+>````&@`@'BT````` +M````&P"`(BT`````````$``B'B,````````````I2(<````````````Q'*,` +M````````$``B'B<````````````I2(<`````````$``B'B,````````````Q +M(,0```````#__P`H(B@```````````")20<`````````$``B'B,````````` +M```I2(<`````````$``B'B$````````````I2$<````````````Q'*,````` +M````$``B'B<````````````I2(<````````````Q'*$`````````$``B'B<` +M```````````I2$<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<`````````$``B'B$````````````Q(,(```````#_ +M_P`H(B@```````````")20<`````````$``B'B,````````````I2(<````` +M`````0`B"B$````````````S"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<````````````Q'*,`````````$``B'B<````````````I +M2(<``````````0`B"B$````````````P"*(`````````$``B'B(````````` +M$``A(B(````````````I20<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@````````````I20<````````````X",4````````````P"$$` +M`````````0`B"B(````````````S"*(`````````$``B'B(`````````$``A +M(B(```````````")20<`````````%P`@(BT``````````!3```````,8____ +M[P`H!B$`````````%``@(BT```````#XX``@1!$````````````I20$````` +M``````")20$````````````@2!$````````````@2!$`````!@H"``"`2!$` +M`````````,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2````````````,`@!`````````````"@``H````` +MEP`````@1!$````````````@2!$`````B@`````@1!$````````````@2!$` +M```````B7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@ +M2````````````,`@!`````````````"@``H`````EP`````@1!$````````` +M```@2!$`````B@`````@1!$````````````@2!$````````B7``@1!$````` +M`````,`@2`````````"A_``@1!$``````````,`@2`````````&A_0`@1!$` +M`````````-D`2````````````,`@!`````````````"@``H````````B5P`@ +M1!$``````````\!(2B`````````B70`@1!$``````````,!`2``````````` +M``!@``````9%`````,`@"``````````B7``@1!$``````````P`X2B(````` +M``"A_``@1!$``````````,`@2`````````&A_0`@1!$````````````O`B(` +M``````````S@`````````````$`@2````````````4`P2B```````````L`P +M2B```````````0!3"B(```-+````/\`H"B``````@0`````@1!$````````` +M`0`@2!$````````A^``@1!$`````````&``@2!$```````0A^0!@1!$```:- +M````$0`A`C```````````!3@``````-4````%``O`B(```````````S````` +M``-D```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!@ +M2`(```-N```A```@1!$``````````,`@2````````````,`@2``````````` +M`,`@2````````````,!`2```````````!``O`B(```````````S```````-J +M```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!`2`(` +M``-?````*``O`B(```````````S```````7```&BI``@1!$```````````!` +M2`(```-?````+``@-B8`````````20`@&!$`````````/P`@2!$````````` +M`0`S&B8````````````O`B8```````````S```````-P````+`"`&BT````` +M````/\`H"B``````````%0`O`B(```````````S@``````.&````!@`O`B(` +M``````````S@``````.Q````%@`O`B(```````````S@``````.U````(``O +M`B(```````````S@``````.<````#P`O`B(```````````S@``````.H```` +M$``O`B(```````````S@``````.H````'@`O`B(```````````S@``````.0 +M``"BI``@1!$```````````!`2`(`````"``````I"B(``````````T`A#B`` +M````````#,`A$B````````@````H$B0`````````%,`B%B`````````````I +M%*0```````"BI``@1!$````````````I2*(```````"A_@`@1!$````````` +M``!`2`,`````@0`````@1!$``````````0`@2!$````````A^``@1!$````` +M````%@`@2!$```````0A^0!@1!$```:-````%0`A`C```````````!3@```` +M``.2```A#@`@1!$``````````,`@2````````````,`@2`````````"BI``@ +M1!$```````````!`2`(`````@0`````@1!$``````````0`@2!$````````A +M^``@1!$`````````%P`@2!$```````0A^0!@1!$```:-`````P`A`C`````` +M`````!3@``````.>```A"``@1!$``````````,`@2````````````,`@2``` +M``````"BI``@1!$```````````!`2`(```````"BI``@1!$````````````@ +M2`(`````@``````@1!$````````````@2!$`````@0`````@1!$````````` +M$``@2!$````````````@`!```````````!3```````.N``````!````````` +M```@$``@1!$```````"````@2!$```````&BI``@1!$`````````!@!`2!$` +M```````@$``@1!$```````"````@2!$```````&BI``@1!$`````````%@!@ +M2!$```-N``````!``````````````,`@"````````````,`@#``````````` +M'0`A`B,``````````!3@``````/.@0`````@1!$``````````0`@2!$````` +M```A^``@1!$`````````&``@2!$```````0A^0!@1!$```:-````$0`A`C`` +M`````````!3@``````/````A```@1!$````````````@2`(````````````@ +M2`,`````NK[*_@`@2!$`````ROZZO@`@2!$````````@$``@1!$```````"` +M```@2!$```````"BI``@1!$`````````!`!`2!$````````A<``@1!$````` +M```````@2`(````````````@2`,`````@0`````@1!$`````````"@`@2!$` +M```````````@`!```````````!3```````/3C``````@1!$`````ROZZO@!` +M2!$`````@0`````@1!$``````````0`@2!$````````__T`H"B``````@``` +M`$`H#B``````0````,`H$B````````0```!I1B(```:-```````@%!`````` +M```````O`B,```````````S```````/A`````,!`&`````/D```__\`H&B`` +M``````0```!I1B8```:-```````@&!`````````````O`B0```````````S` +M``````/G`````,!`'`````/J```__\`H'B````````0```!I1B<```:-```` +M```@'!`````````````@1`(````````````H(,4```````````!)2.@````` +MI8`````@"!$````````@```@#!$`````@P````!@1!$```02```````@1`(` +M`````````,`@2````````````$`@2```````````'\`A`B```````````!3` +M``````/W```@$``@1!$```````"````@2!$```````#__\!($B````/_IX`` +M```@"!$```````"@```@#!$`````@P````!@1!$```02```````@1`(````` +M`````,`@2````````````,`@2`````````#__\`H$B``````@P`````@1!$` +M```````````P2(,`````A``````@1!$``````````,`@2````````````!T` +M````````@P````!@1!$```02`````,!`!``````!J8`````@"!$```````#` +M``!`#!$```/ZJX`````@"!$```````#XX`!`#!$```/ZK8`````@"!$````` +M``#X@`!`#!$```/ZLX`````@"!$```````#S_`!`#!$```/ZKX`````@"!$` +M``````#@``!`#!$```/ZL8`````@"!$```````#P``!`#!$```/Z@P`````@ +M1!$````````A2``@2!$`````A``````@1!$``````````,`@2``````````` +M`!T```````````````"``````````1@@`,`P1B```````````-D`2``````` +M`````,`@!`````````````"@``H``````AB@`,`P1B```````````-D`2``` +M`````````,`@!`````````````"@``H``````QC``,`P1B```````````-D` +M2````````````,`@!`````````````"@``H`````!!CXX,`P1B`````````` +M`-D`2````````````,`@!`````````````"@``H`````!1CX@,`P1B`````` +M`````-D`2````````````,`@!`````````````"@``H`````!AC@`,`P1B`` +M`````````-D`2````````````,`@!`````````````"@``H`````!QCP`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H`````"!CS +M_,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M````,``@"BT``````````,`I#$``````````,``@-B,``````````,`@!``` +M``````````"@``H`````A@`````@1!$```````````!`2`$`````A0```,`@ +M1!$```````````!`2`$````````A?``@1!$`````````&$`A`B`````````` +M`!3```````1%`(```,!)2B````1&`````,`@2````````````,`@2``````` +M`````,`@2```````@0`````@1!$``````````0`@2!$``````````,`@"``` +M`````````!<```````````0A?P!@1!$```:-````'P`A`C```````````!3` +M``````````````!`3`(```1+`````,`@#````````````,`@$``````````` +M`,`@%````````````,`@&````````````,`@'`````````!_```H"B$````` +M``!%```O`B(```````````S@``````19`````,`@(````````````!<````` +M````````$``H"B,`````````$``O`B(```````````S@``````1A@0`````@ +M1!$``````````0`@2!$```````0```!I1B0```:-``````!```````1F@0`` +M```@1!$````````````@2!$````````A;0`@1!$````````````@2`0````` +M``````!@2`4```:2```````H)/``````````!P`H"B,``````````0`O`B(` +M``````````K@``````1M```````O`,D```````````3@``````2&``````!` +M``````23`````@`O`B(```````````K@``````1R```````O`,D````````` +M``+@``````2&``````!```````23`````P`O`B(```````````K@``````1W +M```````O`,D```````````S@``````2&``````!```````23````!``O`B(` +M``````````K@``````1\```````O`,D```````````K@``````2&``````!` +M``````23````!0`O`B(```````````K@``````2!```````O`,D````````` +M``;@``````2&``````!```````23````!@`O`B(```````````K@``````2& +M```````O`,D```````````C@``````2&``````!```````23``!_```H"B$` +M``````!%```O`B(```````````K@````````````"``A"B,``````````!3` +M``````20```A:0`@1!$``````````,`@2````````````,`@2``````````` +M`,`@2```````ROZZO@!`2!$``````````,`@1````````````,`@```````` +M`````,!`2`````````!_```H"B$```````!%```O`B(```````````K@```` +M``29`````,`@`````````````,`@`````````````,!```````````````!` +M3`@```19`````,`@"```````````$$`A#B``````````$4`A$B`````````` +M$D`A%B`````````A:0`@1!$````````````@2`(````````````A`B4````` +M`````!3@``````2C``0``,!)2B````2D__O__\`H2B`````````````A`B,` +M`````````!3@``````2P`````,`@2````````````,`@2``````````````A +M`B0``````````!3`````````@0`````@1!$`````````#``@2!$````````` +M```@`!```````````!3```````2LH``````@1!$`````ROZZO@!`2!$````` +M@0`````@1!$`````````!``@2!$````````A:P`@1!$``````````,`@2!`` +M````@0`````@1!$`````````!0`@2!$````````A;``@1!$``````````,`@ +M2!`````````````O`B0```````````S@``````````````!```````2J```` +M`,`A"B```````````!3```````3#@0`````@1!$````````````@2!$````` +M```A;0`@1!$``````````,`@2````````````,!@2`````:2``````!````` +M``3'@0`````@1!$``````````0`@2!$```````0``,`I1B```````````,!@ +M``````:-`````0`A`B(``````````!3```````3.```A:0`@1!$````````` +M`,`@2````````````,`@2``````````````@2!``````ROZZO@!`2!$````` +M`````,`@1````````````,!`2!``````@0`````@1!$``````````0`@2!$` +M```````A^``@1!$`````````#@`@2!$```````0A^0!@1!$```:-```````A +M`C```````````!3```````30```A@``@1!$``````````,`@2``````````` +M`,`@`````````````,`@2````````````,`@`````````````,!`2``````` +M`````P`S/B\``````````0`A`B$``````````!3@``````4`````+``@"BT` +M``````0``!C@#!$```3O`````0`S/B\````````A:0`@1!$````````````@ +M2`(````````````@2`,`````````"``P"B(``````````,`@2``````````` +M`,`@2``````````A:0`@1!$````````````@2`(````````````@2`,````` +M````"``P"B(``````````,`@2````````````-C`2`````3C```A:0`@1!$` +M```````````@2`(````````````@2`,`````````"``P"B(``````````,`@ +M2````````````,`@2```````````+0`@$BT````````````I#(,````````A +M:0`@1!$````````````@2`(````````````@2`,`````````"``P"B(````` +M`````,`@2````````````,`@2```````````$0`A`B0``````````!3````` +M``````````!```````2J````+,`@-B``````````+``"B +MT@`@1!$```````````!`2`@```````"BT@`@1!$``````````0!02B@````` +M`````@`O`B0```````````S```````6Q``"BOP`@1!$````````````@2`<` +M````@0`````@1!$``````````0`@2!$```````2BO@!@1!$```:-````&@`A +M(C``````````!@`B)C````````0@!`!@1!$```:-``"BQ@`@1!$````````` +M```P2.D```````````#@``````6O``"BTP`@1!$```````````!`2`@````` +M``"BTP`@1!$``````````0!02B@```````"BPP`@1!$````````````@2`<` +M````@0`````@1!$``````````0`@2!$```````2BP@!@1!$```:-````&@`A +M(C``````````!@`B)C````````0@!`!@1!$```:-``"BQP`@1!$````````` +M```P2.D```````````#@``````6^``"BU``@1!$```````````!`2`@````` +M``"BU``@1!$``````````0!02B@`````A0`````@1!$````````````@2`$` +M```````P2@`@1!$``````0`````@2!$```````````!```````7$I````,`@ +M1!$``````````,!`2````````````,!@``````7)`````,!`!``````!```` +M+``@-B$`````@0`````@1!$`````````!@`@2!$````````````O`C`````` +M``````S```````70```````@!!$`````````,`!`-B$```7C````,``@!BT` +M``````!^```H!B$````````````O`B$```````````S@``````7C@0`````@ +M1!$``````````0`@2!$```````2@D@!@1!$```:-````,0`@-C````````2@ +MDP!@1!$```:-````,@`@-C````````2BM@!@1!$```:-````,P`@-C`````` +M``2BN@!@1!$```:-````-``@-C````````2BO@!@1!$```:-````-0`@-C`` +M``````2BP@!@1!$```:-````-@`@-C````````0@!`!@1!$```:-``&BI``@ +M1!$`````````/P`@2!$`````````/P`@2!$`````````/P`@2!$````````` +M/P`@2!$`````````!0`@2!$```````"A]``@1!$````````````@2!$````` +MB``````@1!$``````````0`@2!$`````@0`````@1!$`````````!@`@2!$` +M`````````0`O`C````````````S@``````8L````,``@!BT````````````O +M`B$```````````S@``````8L@0`````@1!$``````````0`@2!$```````!^ +M```H!B$````````````O`B$```````````S@``````8%``"@D@`@1!$````` +M````,0`@2BT```````"@DP`@1!$`````````,@`@2BT```````"BM@`@1!$` +M````````,P`@2BT```````"BN@`@1!$`````````-``@2BT```````"BO@`@ +M1!$`````````-0`@2BT```````"BP@`@1!$`````````-@`@2BT````````` +M,``@!BT````````!_P`H!B$````````````O`B$```````````S@``````8K +M```````A`B$``````````!3```````8.``2@`P!@1!$```:-``"@`P`@1!$` +M```````````@2!```````````0`A!B$``````````!3```````83``2@$`!@ +M1!$```:-``"@$``@1!$````````````@2!```````````0`A!B$````````` +M```O`B$```````````S@``````8K``2@$0!@1!$```:-``"@$0`@1!$````` +M```````@2!````````2@$@!@1!$```:-``"@$@`@1!$````````````@2!`` +M``````2@$P!@1!$```:-``"@$P`@1!$````````````@2!````````2@%`!@ +M1!$```:-``"@%``@1!$````````````@2!````````2@%0!@1!$```:-``"@ +M%0`@1!$````````````@2!````````2@%@!@1!$```:-``"@%@`@1!$````` +M```````@2!````````2@%P!@1!$```:-``"@%P`@1!$````````````@2!`` +M``````0@!`!@1!$```:-````+`"`!BT`````_P`````@1!$````````````@ +M2!$``````````0`@2!$``````````@"`2!$```````````[@``````8]```` +M,``@!BT``````````@`H!B$````````````O`B$```````````S@``````8[ +M@0`````@1!$``````````0`@2!$```````0@!`!@1!$```:-```0```@"!$` +M````````*P`@-B(```````````!@``````9!``````!@``````7)F``````@ +M1!$```````````"`2!$``````````,!@``````9!`````,!`!``````!``"B +MI``@1!$`````````(@`@2!$`````B0`````@1!$``````````0!`2!$```8M +MEP`````@1!$````````````@2!$`````B@`````@1!$```````````!`2!$` +M``8M``````!@``````9<```@$``@1!$```````"````@2!$```````&BI,`@ +M1!$`````````%@!@2!$```-N```@$``@1!$```````$````@2!$`````@0`` +M```@1!$``````````0`@2!$````````A?``@1!$`````"8`````@2!$````` +M_____P`@2!$````````````@2!$``````````!<```````````0A?P!@1!$` +M``:-````'P`A`C```````````!3`````````````!`!`3!$```96``````!` +M````````````%P`@'BT`````````!``I'B<`````````%P"`-B<````````` +M%P`@'BT`````____^P`H'B<`````````%P"`-B<`````````%P`@'BT````` +M````"``I'B<`````````%P"`-B<`````````%P`@'BT`````____]P`H'B<` +M````````%P"`-B<````````@$``@1!$```````"````@2!$```````&BI``@ +M1!$`````````%@!@2!$```-N```@$``@1!$```````$````@2!$````````A +M?``@1!$``````8`````@2!$`````_____P`@2!$````````````@2!$````` +M`````!<`````````@0`````@1!$``````````0`@2!$```````0A?P!@1!$` +M``:-````'P`A`C```````````!3```````:,````$`!`3!$```9R`````,`@ +M!````````````#C`````````````'0`@"BT`````````'@`@#BT````````` +M'P`@$BT`````````(``@%BT````````A:0`@1!$````````````@2`0````` +M```````@2`4````````````@2`$`````ROZZO@`@2!$`````````!``P$B0` +M```````````O`&0```````````S```````:+`````P`H&B(`````````"``B +M$B(`````___P```H$B0````````````I$,0`````````'P!`-B0````````` +M``"``````````````!K```````:-GP`````@1!$`````ROZZO@`@2!$````` +M`````!K@``````:0``````"``````````````!K```````:2G@`````@1!$` +M````ROZZO@`@2!$``````````!K@``````:5``````"```````````````!@ +M```````+```0``!@!!$```,5```````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$````````B5@`@1!$`````````&P`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_<`@1!$`````````(0`@'BT` +M````````$``B'B<`````````)``@(BT```````#__P`H(B@````````````I +M20<````````````@2!$`````````(@`@(BT```````#__P`H(B@````````` +M```I20<````````````@2!$`````````(P`@'BT`````````$``B'B<````` +M```````I20<```````````!`2!$````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````4(%`@7``E```````<,!:`0_!<```````B4" +M"0)0`5$``````B,"10*@`D$``````]<%P`7`!<``````!DD&2@,?!<`````` +M!<`%Q0,@`T```````RH"@@-"`S0`````!<`%P`7`!<``````!<`%407`!<`` +M`````[H%P`2[`T0`````!)H$4`0]!<``````!-`%P`1!!-T`````!%`%!P-1 +M`W4`````!<`%P`7`!<``````!<`%P`7`!<``````!<`%P`8_!<<`````!<`% +MP``'!<``````!<`%P`7`!<``````!<`%P`7`!<```````_@#[00(!`8````` +M!`X$"@0,!!``````!!P$&`0D!"``````!"P$*`0T!#``````!<`%P`0X!<`` +G````!<`%P`7`!<``````!<`%P`7`!<````````(&>0:7``8````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV620_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV620_pfp.bin.uu new file mode 100644 index 00000000000..2afc25ce1bd --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV620_pfp.bin.uu @@ -0,0 +1,55 @@ +begin 644 RV620_pfp.bin +M`,H$``"@````?H*+`'P#BP"``;@`?`.+`-1`'@#N`!X`R@0``*````!^@HL` +MQ!@X`,HD``#**```E8&H`,0<.@##P```R@@``,H,``!\=$L`P@`%`)G```#$ +M'#H`?'1,`,#_\``$+`0`,)`"`'TE```U%`(`?34+`"54`P!\U8``)9P#`)7` +M!`#5`!L`?MW!`'V=@`#6@!L`U8`;`-1`'@#50!X`UD`>`-:`'@#4@!X`U,`> +M`)>#TP#5P!X`R@@``(``&@#*#```Y`$>`-0`'@"```P`Q!@X`.0!/@#4`!X` +M@``,`,08.`#40!X`[@`>`,H$``"@````?H*+`.0!'@#4`!X`U$`>`.X`'@#* +M!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^@HL`RA@``-1` +M'@#5@!X`@`!3`-0`=0#40!X`R@@``,H,``#*$```U(`9`-3`&`#5`!<`U(`> +M`-3`'@#5`!X`X@`>`,H$``"@````?H*+`,H(``#4@&``U$`>`(````#4@!X` +MR@@``-2`80#40!X`@````-2`'@#*"```R@P``-1`'@#4@!8`U,`6`-2`'@"` +M`;@`U,`>`,8(0P#*#```RA```)2`!`#*%```Y"#S`-0@$P#58&4`U.`<`-4@ +M'`#58!P`@`````8@`0#&"$,`R@P``,H0``"4@_<`RA0``.0@\P"``'D`U"`3 +M`,8(0P#*#```RA```)B#[P#*%```U`!D`(``C0``````Q!0R`,880P#$""\` +ME4`%`,0,,`#40!X`@````.X`'@"5@_4`Q!`Q`-1`,P#5(&4`U*`<`-3@'`#5 +M(!P`Y`%>`-0`'@"`````!B`!`,H8```*(`$`U@!V`,0(-@"8@`<`QA!%`)4! +M$`#4`!\`U&!B`(````#4(&(`S#@U`,P4,P"$`;L`U`!R`-5`'@"`````[@`> +M`.(`&@"$`;L`X@`:`,P02P#,!$<`+)0!`'T)BP"80`4`?17+`-0`&@"``;@` +MU`!M`#1$`0#,#$@`F$`Z`,PL2@"5@`0`S`1)`(`!N`#4`!H`U,`:`"@H`0"$ +M`/``S!`#`)B`&P`$.`P`A`#P`,P0`P"8@!<`!#@(`(0`\`#,$`,`F(`3``0X +M!`"$`/``S!`#`)B`%`#,$$P`FH`)`,P430"80-P`U`!M`,P82`#5`!H`U4`: +M`(``R0#5@!H`EL#5`-0`;0"``;@`U`!N`)K``P#4`&T`U`!N`(````#L`'\` +MFL#,`-0`;0"``;@`U`!N`,P4`P#,&`,`S!P#`'V1`P!]U8,`?1D,`#7,'P`U +M`.0!'@#4`!X`R@@``,H, +M``#*$```U$`>`,H4``#4@!X`U,`>`-4`'@#50!X`U4`T`(````#N`!X`*`0$ +M`.(`&@#B`!H`U$`:`,HX``#,"`,`S`P#`,P,`P#,#`,`F(*]``````"$`;L` +MUZ!O`(````#N`!\`R@0``,+_``#,"#0`P3__`'QTRP!\R0L`?0$/`)D"L`!\ +M@;P"`````[@`?`,H(```H&0``?8F+`)6`%``H%`0`R@P``,H0 +M``#*'```RB0``.(`'P#4P!H`U0`:`-5`&@#,&`,`S"P#`,PL`P#,+`,`?:6+ +M`'V<1P"80I<``````(`!80#4P!H`U$`>`-2`'@"`````[@`>`.0!'@#4`!X` +MU$`>`.X`'@#*!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^ +M@HL`R@@``"2,!@`,S`8`F,`&`,P03@"9``0`U`!S`.0!'@#4`!X`U$`>`-2` +M'@"`````[@`>`,H(``#*#```--`8`"40`0"5`"$`P7__`,H0``#*%```RA@` +M`-2`'0#4P!T`?;&+`,%"`@#"P`$`U8`=`#3<#@!]74P`?W-,`-=`'@#5`!X` +MU4`>`,%"``#"P```"9P!`#'<$`!_7TP`?W-,``0H`@!]@X``U:AO`-6`9@#7 +M0!X`[`!>`,@D`@#()`(`@`&X`-8`=@#40!X`U(`>`-3`'@"`````[@`>`(`` +M``#N`!\`U``?`(````#4`!\`U``?`(@```#4`!\````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0%Q``(!>``#`(\`!`!_``4``P`& +M`#\`!P`R``@!+``)`$8`"@`V`!`!M@`7`*(`(@$Z`",!20`@`+0`)`$E`"<` +M30`H`&H`*@!@`"L`4@`O`&4`,@"'`#0!?P`\`58`/P!R`$$!C`!$`2X`50%S +M`%8!>@!@``L`80`T`&(`.`!C`#@`9``X`&4`.`!F`#@`9P`X`&@`.@!I`$$` +M:@!(`&L`2`!L`$@`;0!(`&X`2`!O`$@````&````!@````8````&````!@`` +M``8````&````!@````8````&````!@````8````&````!@````8````&```` +)!@````8````& +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV630_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV630_me.bin.uu new file mode 100644 index 00000000000..a3e9bde9f97 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV630_me.bin.uu @@ -0,0 +1,481 @@ +begin 644 RV630_me.bin +M`````,`@!`````````````"@``H```````#__P`H1B$``````````-D`2``` +M`````````,`@!`````````````"@``H```````````#@``````````$``,`I +M1B```````````-D`2````````````,`@!`````````````"@``H`````@0`` +M```@1!$``````````0`@2!$```````0@!`!@1!$```:*``````!@``````8N +M``````!@``````9"`````,`@"``````````/```H%B(`````````"``A%B4` +M````````&``@-B4`````C0`````@1!$`````````!``O`B4```````````S@ +M```````8`$$@``!`2!$````9`$(@```@2!$`````C@`````@1!$````````` +M*``@2BT`````D``````@1!$````````````@2`4`````````#``A%B(````` +M`````P`H%B4`````````&0`A&B(`````````!``H&B8````````````I%,4` +M````````&0`@-B4````````````Z%`(`````````%@`A%B4``````````P`H +M%B4`````````%P`@#BT`````_____``H#B,````````````I%*,````````` +M%P`@-B4```````"````H#B(`````````!P`B#B,````````````I.&X````` +M(``````H#B(`````````!@`A#B,````````````I.&X````````````B`B(` +M`````````!3@```````X`````"[@```````U`````"S@```````W``````!` +M#BT````Y````"``@#BT`````````"0!`$BT```!&`````0!`#BT````Y```` +M`,`@#````````#___``H$B,``````````@`B$B0`````````'P`A'B,````` +M`````!3@```````^````"`!`'!$```!!````#0`@'BT`````````#P`H'B<` +M`````````P`B'B<`````?\`````H&B,`````````%``A&B8``````````0`S +M&B8`````````"``B&B8````````````I#,<`````````)P`@-B0```````!_ +M```H$B$````````4```O`B0```````````S@``````!+`````0`I#B,````` +M````#@`@-B,```````#@```@1!$`````__@````I2B,````````````Z+`(` +M`````````@`B#BL`````_``````H#B,`````````#P`@-B,````````?_P`I +M2B,`````````)P`@2BT````````````@2!$`````````*0`@#BT`````!@H" +M```I2B,````````````@2!$````````````@2!$``````````0`A`B(````` +M`````!3@``````!A`````"[@``````!?`````"S@``````!>``````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````,``@%BT``````````@`I%B4`````````,``@-B4` +M````````)0`@%BT````````````O`*,```````````S```````"#````)@`@ +M%BT````````````O`*0```````````S```````"$``````!```````"*```` +M)0`@-B,`````````)@`@-B0`````````%P`@'BT``````````@`A`B<````` +M`````!3@``````"*``````!@``````9E``````!@``````99`````@`A#B(` +M`````````!3```````"-````$L!`-B````"3`````"[@``````"1`````"S@ +M``````"0`````@!`#BT```"2`````P!`#BT```"2````#``@#BT````````` +M$@`@-B,``````````P`A#B(``````````!3```````"8``"@#``@1!$````` +M`````,`@2````````````,!`2`````"@``"@#``@1!$````````````@2!$` +M`````````"[@``````">`````"S@``````"=`````@!`#BT```"?`````P!` +M#BT```"?````#``@#BT````````````@2`,````````````Z#`(``````#\` +M```H#B,`````````$``A#B,`````````$0`@-B,`````````'@`A`BL````` +M`````!3```````"G````%L`@-B``````````'P`A`BL``````````!3````` +M``"J````%<`@-B``````````"``A#BL`````````?P`H#B,````````````O +M`B,```````````S@``````#A`````"<```````````````!@``````*C```` +M`0`O`B,```````````K@``````"S``````!@``````$Z@0`````@1!$````` +M````!@`@2!$`````````#``B'C``````F8`````@1!$`````````!``@$BT` +M````````"``B$B0`````````$``@&!$````````````I'.0```````````!@ +M2`<```$OFP`````@1!$````````````@2`(`````G``````@1!$````````` +M```S%&\``````````0`S/B,``````````-D`2``````````````@/`4````` +M@0`````@1!$`````````#@`@2!$````````````@$!````````#@!P`@1!$` +M````````#P`A`BL``````````!3```````#+`/C_"``@2!$`````F`````!` +M2!$```#<````\``H#B(`````````H``O`B,```````````S```````#:```` +M$0`@#BT``````````0`O`B,```````````S@``````#5`````@`O`B,````` +M``````S@``````#4```_``!`#!$```#6```?``!`#!$```#6```/```@#!$` +M`````#@`"0`I2B,`````/P`````H#BL``````````@`B#B,`````````!P!) +M2B,```#<`#@/"0`@2!$`````:```!P`@2!$`````````"``A2B<````````` +M```@2!$`````!@H"```I2B0````````````@2!$````````````@2!$````` +M``"B`@`@1!$``````/\````H#B(`````````@``I2B,`````````)P`@#BT` +M````````)@`@$BT````````````O`(,```````````S@``````#J``````!@ +M``````9?``````!```````#K``````!@``````9B````!P`@(BT````````` +M!0`B#B(``````!`````H#B,````````````I(&@````````````Z#`(````` +M````[P`H#B,````````````I(&@`````````%P`@#BT``````````P`A`B,` +M`````````!3@``````#X````"P`A`B@``````````!3```````#X```$```I +M(B@`````````%``@-B@`````````'``A#B(``````````!3```````#]``"C +M#``@1!$````````````@2!$`````````'@`A#B(``````````!3```````$+ +M``"C#P`@1!$`````````$0`@#BT``````````0`O`B,```````````S````` +M``$$_____P!`2!$```$+`````@`O`B,```````````S```````$'``#__P!` +M2!$```$+````!``O`B,```````````S```````$*````_P!`2!$```$+```` +M`0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3```````$2 +M````$$`A#B``````````$P`@-B,`````````&$`B2B``````````$,!"2B`` +M``$4```````@#!$`````````$P`@-B,````````````@2!$````````````@ +M2!$`````````"@`@$!$````````````O`B0```````````S@``````$;```` +M```@2!$``````````0!3$B0```$7_[___P`H.BX`````````&P`A`B(````` +M`````!3```````$N@0`````@1!$`````````#0`@2!$`````````&``B#C`` +M````_``````H#B,`````@0`````@1!$`````````#@`@2!$````````````@ +M$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,````````` +M'``@'BT`````````"``A2B<````````````@2!$`````!@H"```I2B0````` +M```````@2!$````````````@2!$```````````"`````````@0`````@1!$` +M`````````0`@2!$````````A?``@1!$``````(`````@2!$````````````@ +M2`8`````````"``A2B<``````````!<```````````0A?P!@1!$```:*```` +M'P`A`C```````````!3```````:)````!`!`3!$```$U@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````'``@2!$```````0A^0!@1!$` +M``:*````$0`A`C```````````!3@``````$\``````"```````````````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```` +M``!@``````%@``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%'`````,!`!``````!``````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```_ +M_P`O`B\```````````S@``````````````!@``````%@````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%8`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````&/``````!@``````&@```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&< +M``````!@``````*[`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*C```````O`B$```````````K@ +M``````&!``````!@``````$Z``````!```````&&E0`````@1!$````````` +M```O`B$```````````S@``````&&`````,`@2````````````0!3!B$```&" +MD@`````@1!$``````````,!@2`````&7``&A_0`@1!$`````````$0`@!BT` +M``````````!X!"H```+[```````@*`D````````__P`O`B\```````````S` +M``````%T`````,!`!``````!```"$`!@!!$```,5```__P`O`B\````````` +M``S@``````&4````%<`@-B``````````%L`@-B``````/X`````@!!$````` +M1@````!@"!$```&R``````"```````````"A_``@1!$````````__P`O`B\` +M``````````S```````&;`````0"`2!$`````````(0"`2!$```````#__T`H +M#B``````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`` +M```@1!$`````````!@`@2!$`````````"``B'C``````````*0`@&BT````` +M``#@```@1!$`````__O_"0`@2!$`````````#P`@(BT````````?_P`I2B@` +M````````!@`@(BT````````````I(.@````````````@2`@````````````@ +M2!$`````!@H"```I2B8````````````@2!$````````````@2!$````````! +M```@&!$`````````"`!B'B@```$O````"`""(B@```````+````@1!$````` +M````%0!@#BT```&]````%@!@#BT```&]``#`"``@1!$`````````%P`@#BT` +M`````````!3```````&Y```````@!!$````````````@2`$`````.0`````@ +M2!$````````````@2!$```````````"`2`(`````````&``@+BT````````` +M```[#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````` +M``````"`2`,```````````!@```````+```0``!@!!$```,5```````@!!$` +M``````````!@"!$```&R````!P`A!B\`````````$P`@"BT``````````0`@ +M+!$```````#__T`H(B``````````#P`F(B@`````````$$`A)B`````````` +M#P`F)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````` +M```````O`B$```````````S@``````'@```B7``@1!$`````````@0`@2!$` +M``````"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O +M`B<```````````S@``````'<``````!@``````'I`````0!3'B<```'8```` +M`0`@+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```'1 +M```B7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$` +M`````````0`P'B\````````````O`B<```````````S@``````````````!@ +M``````'I`````0!3'B<```'E``#__T`H#B``````````#P`F#B,````````` +M$,`A$B``````````#P`F$B0````````````@%!$```````````!@&!$```*[ +M``&A_0`@1!$````````````O`BL```````````S@``````'X````$``B%B@` +M````__\````H%B4```````#__P`H&BD````````````I2,4````````````@ +M2`H````````````@+!$`````````$``B%B,`````__\````H%B4```````#_ +M_P`H&B0````````````I2,4```````````!S%0,```(%```````@&`4````` +M``````!S%20```(%```````M%,4````````````P"*(````````````@2`(` +M```````````@*`(````````````@(`,```````````"`)`0`````````#P`A +M`B4``````````!3```````:)```````K%`4``````````0"0%B4````````` +M``!@```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R +M```B5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\` +M``````````S@`````````````,`@!``````````B7``@1!$``````````P`X +M2B$```````"A_``@1!$``````````0`@2!$```````#__T`H$B`````````` +M$,`A&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*[ +M``&A_0!@1!$```+@`````0`S!B$````````````O`B$```````````S````` +M``(9```__P`O`B\```````````S```````(2`````,!`!``````!``````!@ +M``````9"``````!`!`\```(3``````!@``````8N``````!@``````9"```" +M$`!@!!$```,5``````!@``````&@``````!@``````&<``````!@``````*[ +M``````!@``````*CDX`````@1!$````````````@2`@````````````O`B\` +M``````````K@``````(R``````!@``````$Z``````!```````(VE0`````@ +M1!$````````````O`B\```````````S@``````(V`````,!`2`````(SD@`` +M```@1!$``````````,`@2``````````B5@`@1!$`````````%@`@2!$````` +M```B7``@1!$``````````P`@2!$```````"A_``@1!$``````````0`@2!$` +M``````&A_0`@1!$```````````!@!!$```+[`````,!`!``````!``````!@ +M``````8N``"@#``@1!$``````````,`@2````````````,!`2``````````` +M``!@```````+````&$`A"B```````````P`O`B(```````````K@``````), +M````%``@(BT```````@!`0`I(B@`````````%``@-B@```````"C#``@1!$` +M`````````,`@2````````````,`@2````````````,!`2`````)1``````!@ +M```````+````$`!@!!$```,5/X`````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$```````````!@``````)\````%P`@'BT````` +M`````0`A'B<``````````!3@``````)J````$@`@'BT```````#__P`H'B<` +M```````````T'"<``````````!+```````)?```````@'!$````````````O +M`.4```````````C```````)B```````@%`<`````````$@`@'BT````````` +M$``A'B<````````````T'$<``````````!+```````)G```````@'!$````` +M```````O`.8```````````C```````)J```````@&`<```````````!@```` +M``+!```B5@`@1!$````````````T(",``````````!+```````)R```````T +M($0``````````!+```````)Q````%@!`2!$```)V````&`!`2!$```)V```` +M```T($0``````````!+```````)U````%P!`2!$```)V````&0`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_0!@1!$```+I```__P`O`B\` +M``````````S```````)6`````,!`!``````!````$$`A!B````````#__\`H +M"B``````````$$`A#B````````#__\`H$B``````````$$`A%B````````#_ +M_\"(&B``````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```:* +M``````!@``````8N`````,!@``````*C````!0`@"BT`````````"``B"B(` +M````````*P`@&BT`````````'``@'BT```````!P```H'B<````````````Q +M'.8`````````*@`@&BT`````````#``B&B8````````````O`.8````````` +M``;@``````*2```````@'!$````````````@#!$`````````*P`@-B,````` +M````$``@&!$```````````!I'.(```$ODX`````@1!$````````````@2`<` +M````E0`````@1!$````````````O`B\```````````S@``````*=`````0`S +M/B\``````````-D`2```````D@`````@1!$``````````,`@2``````````` +M'`!`-B<`````````#,`B"B``````````*0`@-B(`````````*,!`-B`````` +M``"BI``@1!$`````````"0`@2!$`````H0`````@1!$``````````0"`2!$` +M````````(0`@'BT````````````L'.,`````````(0`@-B<`````````(@`@ +M'BT````````````L'.0`````````(@`@-B<`````````(P`@'BT````````` +M```Q(*,````````````M'0<`````````(P`@-B<`````````)``@'BT````` +M```````Q(,0````````````M'0<`````````)`"`-B<`````````(0`@-B,` +M````````(@`@-B0````````````Q'*,`````````(P`@-B<````````````Q +M',0`````````)`"`-B<`````````&@`@-B<`````````&P`@-B@````````` +M%P`@'BT``````````@`A`B<``````````!3```````+<``````!```````+9 +M````&@`@-B<`````````&P`@-B@`````````%P`@'BT``````````@`A`B<` +M`````````!3@``````+9`````P`A`B<``````````!3@``````+<````(P`@ +M'BT````````````N`.$```````````+```````+<````(0`@'BT````````` +M```Q(*$````````````N`.@```````````;```````+<````)``@'BT````` +M```````N`.(```````````+```````+<````(@`@'BT````````````Q(,(` +M```````````N`.@```````````;```````+<``````!@``````9E``````!@ +M``````*U``````!```````+>``````!@``````*U``````!@``````9<```` +M``!```````+>``````!@``````*G``````!```````+>````&@`@'BT````` +M````&P"`(BT`````````$``B'B,````````````I2(<````````````Q'*,` +M````````$``B'B<````````````I2(<`````````$``B'B,````````````Q +M(,0```````#__P`H(B@```````````")20<`````````$``B'B,````````` +M```I2(<`````````$``B'B$````````````I2$<````````````Q'*,````` +M````$``B'B<````````````I2(<````````````Q'*$`````````$``B'B<` +M```````````I2$<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<`````````$``B'B$````````````Q(,(```````#_ +M_P`H(B@```````````")20<`````````$``B'B,````````````I2(<````` +M`````0`B"B$````````````S"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<````````````Q'*,`````````$``B'B<````````````I +M2(<``````````0`B"B$````````````P"*(`````````$``B'B(````````` +M$``A(B(````````````I20<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@````````````I20<````````````X",4````````````P"$$` +M`````````0`B"B(````````````S"*(`````````$``B'B(`````````$``A +M(B(```````````")20<`````````%P`@(BT``````````!3```````,8____ +M[P`H!B$`````````%``@(BT```````#XX``@1!$````````````I20$````` +M``````")20$````````````@2!$````````````@2!$`````!@H"``"`2!$` +M`````````,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2````````````,`@!`````````````"@``H````` +MEP`````@1!$````````````@2!$`````B@`````@1!$````````````@2!$` +M```````B7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@ +M2````````````,`@!`````````````"@``H`````EP`````@1!$````````` +M```@2!$`````B@`````@1!$````````````@2!$````````B7``@1!$````` +M`````,`@2`````````"A_``@1!$``````````,`@2`````````&A_0`@1!$` +M`````````-D`2````````````,`@!`````````````"@``H````````B5P`@ +M1!$``````````\!(2B`````````B70`@1!$``````````,!`2``````````` +M``!@``````9"`````,`@"``````````B7``@1!$``````````P`X2B(````` +M``"A_``@1!$``````````,`@2`````````&A_0`@1!$````````````O`B(` +M``````````S@`````````````$`@2````````````4`P2B```````````L`P +M2B```````````0!3"B(```-+````/\`H"B``````@0`````@1!$````````` +M`0`@2!$````````A^``@1!$`````````&``@2!$```````0A^0!@1!$```:* +M````$0`A`C```````````!3@``````-4````%``O`B(```````````S````` +M``-D```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!@ +M2`(```-N```A```@1!$``````````,`@2````````````,`@2``````````` +M`,`@2````````````,!`2```````````!``O`B(```````````S```````-J +M```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!`2`(` +M``-?````*``O`B(```````````S```````6]``&BI``@1!$```````````!` +M2`(```-?````+``@-B8`````````20`@&!$`````````/P`@2!$````````` +M`0`S&B8````````````O`B8```````````S```````-P````+`"`&BT````` +M````/\`H"B``````````%0`O`B(```````````S@``````.&````!@`O`B(` +M``````````S@``````.Q````%@`O`B(```````````S@``````.U````(``O +M`B(```````````S@``````.<````#P`O`B(```````````S@``````.H```` +M$``O`B(```````````S@``````.H````'@`O`B(```````````S@``````.0 +M``"BI``@1!$```````````!`2`(`````"``````I"B(``````````T`A#B`` +M````````#,`A$B````````@````H$B0`````````%,`B%B`````````````I +M%*0```````"BI``@1!$````````````I2*(```````"A_@`@1!$````````` +M``!`2`,`````@0`````@1!$``````````0`@2!$````````A^``@1!$````` +M````%@`@2!$```````0A^0!@1!$```:*````%0`A`C```````````!3@```` +M``.2```A#@`@1!$``````````,`@2````````````,`@2`````````"BI``@ +M1!$```````````!`2`(`````@0`````@1!$``````````0`@2!$````````A +M^``@1!$`````````%P`@2!$```````0A^0!@1!$```:*`````P`A`C`````` +M`````!3@``````.>```A"``@1!$``````````,`@2````````````,`@2``` +M``````"BI``@1!$```````````!`2`(```````"BI``@1!$````````````@ +M2`(`````@``````@1!$````````````@2!$`````@0`````@1!$````````` +M$``@2!$````````````@`!```````````!3```````.N``````!````````` +M```@$``@1!$```````"````@2!$```````&BI``@1!$`````````!@!`2!$` +M```````@$``@1!$```````"````@2!$```````&BI``@1!$`````````%@!@ +M2!$```-N``````!``````````````,`@"````````````,`@#``````````` +M'0`A`B,``````````!3@``````/.@0`````@1!$``````````0`@2!$````` +M```A^``@1!$`````````&``@2!$```````0A^0!@1!$```:*````$0`A`C`` +M`````````!3@``````/````A```@1!$````````````@2`(````````````@ +M2`,`````NK[*_@`@2!$`````ROZZO@`@2!$````````@$``@1!$```````"` +M```@2!$```````"BI``@1!$`````````!`!`2!$````````A<``@1!$````` +M```````@2`(````````````@2`,`````@0`````@1!$`````````"@`@2!$` +M```````````@`!```````````!3```````/3C``````@1!$`````ROZZO@!` +M2!$`````@0`````@1!$``````````0`@2!$````````__T`H"B``````@``` +M`$`H#B``````0````,`H$B````````0```!I1B(```:*```````@%!`````` +M```````O`B,```````````S```````/A`````,!`&`````/D```__\`H&B`` +M``````0```!I1B8```:*```````@&!`````````````O`B0```````````S` +M``````/G`````,!`'`````/J```__\`H'B````````0```!I1B<```:*```` +M```@'!`````````````@1`(````````````H(,4```````````!)2.@````` +MI8`````@"!$````````@```@#!$`````@P````!@1!$```02```````@1`(` +M`````````,`@2````````````$`@2```````````'\`A`B```````````!3` +M``````/W```@$``@1!$```````"````@2!$```````#__\!($B````/_IX`` +M```@"!$```````"@```@#!$`````@P````!@1!$```02```````@1`(````` +M`````,`@2````````````,`@2`````````#__\`H$B``````@P`````@1!$` +M```````````P2(,`````A``````@1!$``````````,`@2````````````!T` +M````````@P````!@1!$```02`````,!`!``````!J8`````@"!$```````#` +M``!`#!$```/ZJX`````@"!$```````#XX`!`#!$```/ZK8`````@"!$````` +M``#X@`!`#!$```/ZLX`````@"!$```````#S_`!`#!$```/ZKX`````@"!$` +M``````#@``!`#!$```/ZL8`````@"!$```````#P``!`#!$```/Z@P`````@ +M1!$````````A2``@2!$`````A``````@1!$``````````,`@2``````````` +M`!T```````````````"``````````1@@`,`P1B```````````-D`2``````` +M`````,`@!`````````````"@``H``````AB@`,`P1B```````````-D`2``` +M`````````,`@!`````````````"@``H``````QC``,`P1B```````````-D` +M2````````````,`@!`````````````"@``H`````!!CXX,`P1B`````````` +M`-D`2````````````,`@!`````````````"@``H`````!1CX@,`P1B`````` +M`````-D`2````````````,`@!`````````````"@``H`````!AC@`,`P1B`` +M`````````-D`2````````````,`@!`````````````"@``H`````!QCP`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H`````"!CS +M_,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M````,``@"BT``````````,`I#$``````````,``@-B,``````````,`@!``` +M``````````"@``H`````A@`````@1!$```````````!`2`$`````A0```,`@ +M1!$```````````!`2`$````````A?``@1!$``````````,`@2``````````` +M`,`@2````````````,`@2```````@0`````@1!$``````````0`@2!$````` +M`````,`@"````````````!<```````````0A?P!@1!$```:*````'P`A`C`` +M`````````!3```````````````!`3`(```1(`````,`@#````````````,`@ +M$````````````,`@%````````````,`@&````````````,`@'`````````!_ +M```H"B$```````!%```O`B(```````````S@``````16`````,`@(``````` +M`````!<`````````````$``H"B,`````````$``O`B(```````````S@```` +M``1>@0`````@1!$``````````0`@2!$```````0```!I1B0```:*``````!` +M``````1C@0`````@1!$````````````@2!$````````A;0`@1!$````````` +M```@2`0```````````!@2`4```:/```````H)/``````````!P`H"B,````` +M`````0`O`B(```````````K@``````1J```````O`,D```````````3@```` +M``2#``````!```````20`````@`O`B(```````````K@``````1O```````O +M`,D```````````+@``````2#``````!```````20`````P`O`B(````````` +M``K@``````1T```````O`,D```````````S@``````2#``````!```````20 +M````!``O`B(```````````K@``````1Y```````O`,D```````````K@```` +M``2#``````!```````20````!0`O`B(```````````K@``````1^```````O +M`,D```````````;@``````2#``````!```````20````!@`O`B(````````` +M``K@``````2#```````O`,D```````````C@``````2#``````!```````20 +M``!_```H"B$```````!%```O`B(```````````K@````````````"``A"B,` +M`````````!3```````2-```A:0`@1!$``````````,`@2````````````,`@ +M2````````````,`@2```````ROZZO@!`2!$``````````,`@1``````````` +M`,`@`````````````,!`2`````````!_```H"B$```````!%```O`B(````` +M``````K@``````26`````,`@`````````````,`@`````````````,!````` +M``````````!`3`@```16`````,`@"```````````$$`A#B``````````$4`A +M$B``````````$D`A%B`````````A:0`@1!$````````````@2`(````````` +M```A`B4``````````!3@``````2@``0``,!)2B````2A__O__\`H2B`````` +M```````A`B,``````````!3@``````2M`````,`@2````````````,`@2``` +M```````````A`B0``````````!3`````````@0`````@1!$`````````#``@ +M2!$````````````@`!```````````!3```````2IH``````@1!$`````ROZZ +MO@!`2!$`````@0`````@1!$`````````!``@2!$````````A:P`@1!$````` +M`````,`@2!``````@0`````@1!$`````````!0`@2!$````````A;``@1!$` +M`````````,`@2!`````````````O`B0```````````S@``````````````!` +M``````2G`````,`A"B```````````!3```````3`@0`````@1!$````````` +M```@2!$````````A;0`@1!$``````````,`@2````````````,!@2`````:/ +M``````!```````3$@0`````@1!$``````````0`@2!$```````0``,`I1B`` +M`````````,!@``````:*`````0`A`B(``````````!3```````3+```A:0`@ +M1!$``````````,`@2````````````,`@2``````````````@2!``````ROZZ +MO@!`2!$``````````,`@1````````````,!`2!``````@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````#@`@2!$```````0A^0!@1!$` +M``:*```````A`C```````````!3```````3-```A@``@1!$``````````,`@ +M2````````````,`@`````````````,`@2````````````,`@```````````` +M`,!`2````````````P`S/B\``````````0`A`B$``````````!3@``````3] +M````+``@"BT```````0``!C@#!$```3L`````0`S/B\````````A:0`@1!$` +M```````````@2`(````````````@2`,`````````"``P"B(``````````,`@ +M2````````````,`@2``````````A:0`@1!$````````````@2`(````````` +M```@2`,`````````"``P"B(``````````,`@2````````````-C`2`````3@ +M```A:0`@1!$````````````@2`(````````````@2`,`````````"``P"B(` +M`````````,`@2````````````,`@2```````````+0`@$BT````````````I +M#(,````````A:0`@1!$````````````@2`(````````````@2`,````````` +M"``P"B(``````````,`@2````````````,`@2```````````$0`A`B0````` +M`````!3```````````````!```````2G````+,`@-B``````````+`-:`'@#4@!X`U,`> +M`)>#TP#5P!X`R@@``(``&@#*#```Y`$>`-0`'@"```P`Q!@X`.0!/@#4`!X` +M@``,`,08.`#40!X`[@`>`,H$``"@````?H*+`.0!'@#4`!X`U$`>`.X`'@#* +M!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^@HL`RA@``-1` +M'@#5@!X`@`!3`-0`=0#40!X`R@@``,H,``#*$```U(`9`-3`&`#5`!<`U(`> +M`-3`'@#5`!X`X@`>`,H$``"@````?H*+`,H(``#4@&``U$`>`(````#4@!X` +MR@@``-2`80#40!X`@````-2`'@#*"```R@P``-1`'@#4@!8`U,`6`-2`'@"` +M`;@`U,`>`,8(0P#*#```RA```)2`!`#*%```Y"#S`-0@$P#58&4`U.`<`-4@ +M'`#58!P`@`````8@`0#&"$,`R@P``,H0``"4@_<`RA0``.0@\P"``'D`U"`3 +M`,8(0P#*#```RA```)B#[P#*%```U`!D`(``C0``````Q!0R`,880P#$""\` +ME4`%`,0,,`#40!X`@````.X`'@"5@_4`Q!`Q`-1`,P#5(&4`U*`<`-3@'`#5 +M(!P`Y`%>`-0`'@"`````!B`!`,H8```*(`$`U@!V`,0(-@"8@`<`QA!%`)4! +M$`#4`!\`U&!B`(````#4(&(`S#@U`,P4,P"$`;L`U`!R`-5`'@"`````[@`> +M`.(`&@"$`;L`X@`:`,P02P#,!$<`+)0!`'T)BP"80`4`?17+`-0`&@"``;@` +MU`!M`#1$`0#,#$@`F$`Z`,PL2@"5@`0`S`1)`(`!N`#4`!H`U,`:`"@H`0"$ +M`/``S!`#`)B`&P`$.`P`A`#P`,P0`P"8@!<`!#@(`(0`\`#,$`,`F(`3``0X +M!`"$`/``S!`#`)B`%`#,$$P`FH`)`,P430"80-P`U`!M`,P82`#5`!H`U4`: +M`(``R0#5@!H`EL#5`-0`;0"``;@`U`!N`)K``P#4`&T`U`!N`(````#L`'\` +MFL#,`-0`;0"``;@`U`!N`,P4`P#,&`,`S!P#`'V1`P!]U8,`?1D,`#7,'P`U +M`.0!'@#4`!X`R@@``,H, +M``#*$```U$`>`,H4``#4@!X`U,`>`-4`'@#50!X`U4`T`(````#N`!X`*`0$ +M`.(`&@#B`!H`U$`:`,HX``#,"`,`S`P#`,P,`P#,#`,`F(*]``````"$`;L` +MUZ!O`(````#N`!\`R@0``,+_``#,"#0`P3__`'QTRP!\R0L`?0$/`)D"L`!\ +M@;P"`````[@`?`,H(```H&0``?8F+`)6`%``H%`0`R@P``,H0 +M``#*'```RB0``.(`'P#4P!H`U0`:`-5`&@#,&`,`S"P#`,PL`P#,+`,`?:6+ +M`'V<1P"80I<``````(`!80#4P!H`U$`>`-2`'@"`````[@`>`.0!'@#4`!X` +MU$`>`.X`'@#*!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^ +M@HL`R@@``"2,!@`,S`8`F,`&`,P03@"9``0`U`!S`.0!'@#4`!X`U$`>`-2` +M'@"`````[@`>`,H(``#*#```--`8`"40`0"5`"$`P7__`,H0``#*%```RA@` +M`-2`'0#4P!T`?;&+`,%"`@#"P`$`U8`=`#3<#@!]74P`?W-,`-=`'@#5`!X` +MU4`>`,%"``#"P```"9P!`#'<$`!_7TP`?W-,``0H`@!]@X``U:AO`-6`9@#7 +M0!X`[`!>`,@D`@#()`(`@`&X`-8`=@#40!X`U(`>`-3`'@"`````[@`>`(`` +M``#N`!\`U``?`(````#4`!\`U``?`(@```#4`!\````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0%Q``(!>``#`(\`!`!_``4``P`& +M`#\`!P`R``@!+``)`$8`"@`V`!`!M@`7`*(`(@$Z`",!20`@`+0`)`$E`"<` +M30`H`&H`*@!@`"L`4@`O`&4`,@"'`#0!?P`\`58`/P!R`$$!C`!$`2X`50%S +M`%8!>@!@``L`80`T`&(`.`!C`#@`9``X`&4`.`!F`#@`9P`X`&@`.@!I`$$` +M:@!(`&L`2`!L`$@`;0!(`&X`2`!O`$@````&````!@````8````&````!@`` +M``8````&````!@````8````&````!@````8````&````!@````8````&```` +)!@````8````& +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV635_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV635_me.bin.uu new file mode 100644 index 00000000000..4156a1ed475 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV635_me.bin.uu @@ -0,0 +1,481 @@ +begin 644 RV635_me.bin +M`````,`@!`````````````"@``H```````#__P`H1B$``````````-D`2``` +M`````````,`@!`````````````"@``H```````````#@``````````$``,`I +M1B```````````-D`2````````````,`@!`````````````"@``H`````@0`` +M```@1!$``````````0`@2!$```````0@!`!@1!$```:*``````!@``````8N +M``````!@``````9"`````,`@"``````````/```H%B(`````````"``A%B4` +M````````&``@-B4`````C0`````@1!$`````````!``O`B4```````````S@ +M```````8`$$@``!`2!$````9`$(@```@2!$`````C@`````@1!$````````` +M*``@2BT`````D``````@1!$````````````@2`4`````````#``A%B(````` +M`````P`H%B4`````````&0`A&B(`````````!``H&B8````````````I%,4` +M````````&0`@-B4````````````Z%`(`````````%@`A%B4``````````P`H +M%B4`````````%P`@#BT`````_____``H#B,````````````I%*,````````` +M%P`@-B4```````"````H#B(`````````!P`B#B,````````````I.&X````` +M(``````H#B(`````````!@`A#B,````````````I.&X````````````B`B(` +M`````````!3@```````X`````"[@```````U`````"S@```````W``````!` +M#BT````Y````"``@#BT`````````"0!`$BT```!&`````0!`#BT````Y```` +M`,`@#````````#___``H$B,``````````@`B$B0`````````'P`A'B,````` +M`````!3@```````^````"`!`'!$```!!````#0`@'BT`````````#P`H'B<` +M`````````P`B'B<`````?\`````H&B,`````````%``A&B8``````````0`S +M&B8`````````"``B&B8````````````I#,<`````````)P`@-B0```````!_ +M```H$B$````````4```O`B0```````````S@``````!+`````0`I#B,````` +M````#@`@-B,```````#@```@1!$`````__@````I2B,````````````Z+`(` +M`````````@`B#BL`````_``````H#B,`````````#P`@-B,````````?_P`I +M2B,`````````)P`@2BT````````````@2!$`````````*0`@#BT`````!@H" +M```I2B,````````````@2!$````````````@2!$``````````0`A`B(````` +M`````!3@``````!A`````"[@``````!?`````"S@``````!>``````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````,``@%BT``````````@`I%B4`````````,``@-B4` +M````````)0`@%BT````````````O`*,```````````S```````"#````)@`@ +M%BT````````````O`*0```````````S```````"$``````!```````"*```` +M)0`@-B,`````````)@`@-B0`````````%P`@'BT``````````@`A`B<````` +M`````!3@``````"*``````!@``````9E``````!@``````99`````@`A#B(` +M`````````!3```````"-````$L!`-B````"3`````"[@``````"1`````"S@ +M``````"0`````@!`#BT```"2`````P!`#BT```"2````#``@#BT````````` +M$@`@-B,``````````P`A#B(``````````!3```````"8``"@#``@1!$````` +M`````,`@2````````````,!`2`````"@``"@#``@1!$````````````@2!$` +M`````````"[@``````">`````"S@``````"=`````@!`#BT```"?`````P!` +M#BT```"?````#``@#BT````````````@2`,````````````Z#`(``````#\` +M```H#B,`````````$``A#B,`````````$0`@-B,`````````'@`A`BL````` +M`````!3```````"G````%L`@-B``````````'P`A`BL``````````!3````` +M``"J````%<`@-B``````````"``A#BL`````````?P`H#B,````````````O +M`B,```````````S@``````#A`````"<```````````````!@``````*C```` +M`0`O`B,```````````K@``````"S``````!@``````$Z@0`````@1!$````` +M````!@`@2!$`````````#``B'C``````F8`````@1!$`````````!``@$BT` +M````````"``B$B0`````````$``@&!$````````````I'.0```````````!@ +M2`<```$OFP`````@1!$````````````@2`(`````G``````@1!$````````` +M```S%&\``````````0`S/B,``````````-D`2``````````````@/`4````` +M@0`````@1!$`````````#@`@2!$````````````@$!````````#@!P`@1!$` +M````````#P`A`BL``````````!3```````#+`/C_"``@2!$`````F`````!` +M2!$```#<````\``H#B(`````````H``O`B,```````````S```````#:```` +M$0`@#BT``````````0`O`B,```````````S@``````#5`````@`O`B,````` +M``````S@``````#4```_``!`#!$```#6```?``!`#!$```#6```/```@#!$` +M`````#@`"0`I2B,`````/P`````H#BL``````````@`B#B,`````````!P!) +M2B,```#<`#@/"0`@2!$`````:```!P`@2!$`````````"``A2B<````````` +M```@2!$`````!@H"```I2B0````````````@2!$````````````@2!$````` +M``"B`@`@1!$``````/\````H#B(`````````@``I2B,`````````)P`@#BT` +M````````)@`@$BT````````````O`(,```````````S@``````#J``````!@ +M``````9?``````!```````#K``````!@``````9B````!P`@(BT````````` +M!0`B#B(``````!`````H#B,````````````I(&@````````````Z#`(````` +M````[P`H#B,````````````I(&@`````````%P`@#BT``````````P`A`B,` +M`````````!3@``````#X````"P`A`B@``````````!3```````#X```$```I +M(B@`````````%``@-B@`````````'``A#B(``````````!3```````#]``"C +M#``@1!$````````````@2!$`````````'@`A#B(``````````!3```````$+ +M``"C#P`@1!$`````````$0`@#BT``````````0`O`B,```````````S````` +M``$$_____P!`2!$```$+`````@`O`B,```````````S```````$'``#__P!` +M2!$```$+````!``O`B,```````````S```````$*````_P!`2!$```$+```` +M`0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3```````$2 +M````$$`A#B``````````$P`@-B,`````````&$`B2B``````````$,!"2B`` +M``$4```````@#!$`````````$P`@-B,````````````@2!$````````````@ +M2!$`````````"@`@$!$````````````O`B0```````````S@``````$;```` +M```@2!$``````````0!3$B0```$7_[___P`H.BX`````````&P`A`B(````` +M`````!3```````$N@0`````@1!$`````````#0`@2!$`````````&``B#C`` +M````_``````H#B,`````@0`````@1!$`````````#@`@2!$````````````@ +M$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,````````` +M'``@'BT`````````"``A2B<````````````@2!$`````!@H"```I2B0````` +M```````@2!$````````````@2!$```````````"`````````@0`````@1!$` +M`````````0`@2!$````````A?``@1!$``````(`````@2!$````````````@ +M2`8`````````"``A2B<``````````!<```````````0A?P!@1!$```:*```` +M'P`A`C```````````!3```````:)````!`!`3!$```$U@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````'``@2!$```````0A^0!@1!$` +M``:*````$0`A`C```````````!3@``````$\``````"```````````````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```` +M``!@``````%@``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%'`````,!`!``````!``````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```_ +M_P`O`B\```````````S@``````````````!@``````%@````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%8`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````&/``````!@``````&@```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&< +M``````!@``````*[`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*C```````O`B$```````````K@ +M``````&!``````!@``````$Z``````!```````&&E0`````@1!$````````` +M```O`B$```````````S@``````&&`````,`@2````````````0!3!B$```&" +MD@`````@1!$``````````,!@2`````&7``&A_0`@1!$`````````$0`@!BT` +M``````````!X!"H```+[```````@*`D````````__P`O`B\```````````S` +M``````%T`````,!`!``````!```"$`!@!!$```,5```__P`O`B\````````` +M``S@``````&4````%<`@-B``````````%L`@-B``````/X`````@!!$````` +M1@````!@"!$```&R``````"```````````"A_``@1!$````````__P`O`B\` +M``````````S```````&;`````0"`2!$`````````(0"`2!$```````#__T`H +M#B``````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`` +M```@1!$`````````!@`@2!$`````````"``B'C``````````*0`@&BT````` +M``#@```@1!$`````__O_"0`@2!$`````````#P`@(BT````````?_P`I2B@` +M````````!@`@(BT````````````I(.@````````````@2`@````````````@ +M2!$`````!@H"```I2B8````````````@2!$````````````@2!$````````! +M```@&!$`````````"`!B'B@```$O````"`""(B@```````+````@1!$````` +M````%0!@#BT```&]````%@!@#BT```&]``#`"``@1!$`````````%P`@#BT` +M`````````!3```````&Y```````@!!$````````````@2`$`````.0`````@ +M2!$````````````@2!$```````````"`2`(`````````&``@+BT````````` +M```[#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````` +M``````"`2`,```````````!@```````+```0``!@!!$```,5```````@!!$` +M``````````!@"!$```&R````!P`A!B\`````````$P`@"BT``````````0`@ +M+!$```````#__T`H(B``````````#P`F(B@`````````$$`A)B`````````` +M#P`F)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````` +M```````O`B$```````````S@``````'@```B7``@1!$`````````@0`@2!$` +M``````"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O +M`B<```````````S@``````'<``````!@``````'I`````0!3'B<```'8```` +M`0`@+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```'1 +M```B7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$` +M`````````0`P'B\````````````O`B<```````````S@``````````````!@ +M``````'I`````0!3'B<```'E``#__T`H#B``````````#P`F#B,````````` +M$,`A$B``````````#P`F$B0````````````@%!$```````````!@&!$```*[ +M``&A_0`@1!$````````````O`BL```````````S@``````'X````$``B%B@` +M````__\````H%B4```````#__P`H&BD````````````I2,4````````````@ +M2`H````````````@+!$`````````$``B%B,`````__\````H%B4```````#_ +M_P`H&B0````````````I2,4```````````!S%0,```(%```````@&`4````` +M``````!S%20```(%```````M%,4````````````P"*(````````````@2`(` +M```````````@*`(````````````@(`,```````````"`)`0`````````#P`A +M`B4``````````!3```````:)```````K%`4``````````0"0%B4````````` +M``!@```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R +M```B5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\` +M``````````S@`````````````,`@!``````````B7``@1!$``````````P`X +M2B$```````"A_``@1!$``````````0`@2!$```````#__T`H$B`````````` +M$,`A&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*[ +M``&A_0!@1!$```+@`````0`S!B$````````````O`B$```````````S````` +M``(9```__P`O`B\```````````S```````(2`````,!`!``````!``````!@ +M``````9"``````!`!`\```(3``````!@``````8N``````!@``````9"```" +M$`!@!!$```,5``````!@``````&@``````!@``````&<``````!@``````*[ +M``````!@``````*CDX`````@1!$````````````@2`@````````````O`B\` +M``````````K@``````(R``````!@``````$Z``````!```````(VE0`````@ +M1!$````````````O`B\```````````S@``````(V`````,!`2`````(SD@`` +M```@1!$``````````,`@2``````````B5@`@1!$`````````%@`@2!$````` +M```B7``@1!$``````````P`@2!$```````"A_``@1!$``````````0`@2!$` +M``````&A_0`@1!$```````````!@!!$```+[`````,!`!``````!``````!@ +M``````8N``"@#``@1!$``````````,`@2````````````,!`2``````````` +M``!@```````+````&$`A"B```````````P`O`B(```````````K@``````), +M````%``@(BT```````@!`0`I(B@`````````%``@-B@```````"C#``@1!$` +M`````````,`@2````````````,`@2````````````,!`2`````)1``````!@ +M```````+````$`!@!!$```,5/X`````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$```````````!@``````)\````%P`@'BT````` +M`````0`A'B<``````````!3@``````)J````$@`@'BT```````#__P`H'B<` +M```````````T'"<``````````!+```````)?```````@'!$````````````O +M`.4```````````C```````)B```````@%`<`````````$@`@'BT````````` +M$``A'B<````````````T'$<``````````!+```````)G```````@'!$````` +M```````O`.8```````````C```````)J```````@&`<```````````!@```` +M``+!```B5@`@1!$````````````T(",``````````!+```````)R```````T +M($0``````````!+```````)Q````%@!`2!$```)V````&`!`2!$```)V```` +M```T($0``````````!+```````)U````%P!`2!$```)V````&0`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_0!@1!$```+I```__P`O`B\` +M``````````S```````)6`````,!`!``````!````$$`A!B````````#__\`H +M"B``````````$$`A#B````````#__\`H$B``````````$$`A%B````````#_ +M_\"(&B``````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```:* +M``````!@``````8N`````,!@``````*C````!0`@"BT`````````"``B"B(` +M````````*P`@&BT`````````'``@'BT```````!P```H'B<````````````Q +M'.8`````````*@`@&BT`````````#``B&B8````````````O`.8````````` +M``;@``````*2```````@'!$````````````@#!$`````````*P`@-B,````` +M````$``@&!$```````````!I'.(```$ODX`````@1!$````````````@2`<` +M````E0`````@1!$````````````O`B\```````````S@``````*=`````0`S +M/B\``````````-D`2```````D@`````@1!$``````````,`@2``````````` +M'`!`-B<`````````#,`B"B``````````*0`@-B(`````````*,!`-B`````` +M``"BI``@1!$`````````"0`@2!$`````H0`````@1!$``````````0"`2!$` +M````````(0`@'BT````````````L'.,`````````(0`@-B<`````````(@`@ +M'BT````````````L'.0`````````(@`@-B<`````````(P`@'BT````````` +M```Q(*,````````````M'0<`````````(P`@-B<`````````)``@'BT````` +M```````Q(,0````````````M'0<`````````)`"`-B<`````````(0`@-B,` +M````````(@`@-B0````````````Q'*,`````````(P`@-B<````````````Q +M',0`````````)`"`-B<`````````&@`@-B<`````````&P`@-B@````````` +M%P`@'BT``````````@`A`B<``````````!3```````+<``````!```````+9 +M````&@`@-B<`````````&P`@-B@`````````%P`@'BT``````````@`A`B<` +M`````````!3@``````+9`````P`A`B<``````````!3@``````+<````(P`@ +M'BT````````````N`.$```````````+```````+<````(0`@'BT````````` +M```Q(*$````````````N`.@```````````;```````+<````)``@'BT````` +M```````N`.(```````````+```````+<````(@`@'BT````````````Q(,(` +M```````````N`.@```````````;```````+<``````!@``````9E``````!@ +M``````*U``````!```````+>``````!@``````*U``````!@``````9<```` +M``!```````+>``````!@``````*G``````!```````+>````&@`@'BT````` +M````&P"`(BT`````````$``B'B,````````````I2(<````````````Q'*,` +M````````$``B'B<````````````I2(<`````````$``B'B,````````````Q +M(,0```````#__P`H(B@```````````")20<`````````$``B'B,````````` +M```I2(<`````````$``B'B$````````````I2$<````````````Q'*,````` +M````$``B'B<````````````I2(<````````````Q'*$`````````$``B'B<` +M```````````I2$<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<`````````$``B'B$````````````Q(,(```````#_ +M_P`H(B@```````````")20<`````````$``B'B,````````````I2(<````` +M`````0`B"B$````````````S"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<````````````Q'*,`````````$``B'B<````````````I +M2(<``````````0`B"B$````````````P"*(`````````$``B'B(````````` +M$``A(B(````````````I20<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@````````````I20<````````````X",4````````````P"$$` +M`````````0`B"B(````````````S"*(`````````$``B'B(`````````$``A +M(B(```````````")20<`````````%P`@(BT``````````!3```````,8____ +M[P`H!B$`````````%``@(BT```````#XX``@1!$````````````I20$````` +M``````")20$````````````@2!$````````````@2!$`````!@H"``"`2!$` +M`````````,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2````````````,`@!`````````````"@``H````` +MEP`````@1!$````````````@2!$`````B@`````@1!$````````````@2!$` +M```````B7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@ +M2````````````,`@!`````````````"@``H`````EP`````@1!$````````` +M```@2!$`````B@`````@1!$````````````@2!$````````B7``@1!$````` +M`````,`@2`````````"A_``@1!$``````````,`@2`````````&A_0`@1!$` +M`````````-D`2````````````,`@!`````````````"@``H````````B5P`@ +M1!$``````````\!(2B`````````B70`@1!$``````````,!`2``````````` +M``!@``````9"`````,`@"``````````B7``@1!$``````````P`X2B(````` +M``"A_``@1!$``````````,`@2`````````&A_0`@1!$````````````O`B(` +M``````````S@`````````````$`@2````````````4`P2B```````````L`P +M2B```````````0!3"B(```-+````/\`H"B``````@0`````@1!$````````` +M`0`@2!$````````A^``@1!$`````````&``@2!$```````0A^0!@1!$```:* +M````$0`A`C```````````!3@``````-4````%``O`B(```````````S````` +M``-D```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!@ +M2`(```-N```A```@1!$``````````,`@2````````````,`@2``````````` +M`,`@2````````````,!`2```````````!``O`B(```````````S```````-J +M```@$``@1!$```````"````@2!$```````&BI``@1!$```````````!`2`(` +M``-?````*``O`B(```````````S```````6]``&BI``@1!$```````````!` +M2`(```-?````+``@-B8`````````20`@&!$`````````/P`@2!$````````` +M`0`S&B8````````````O`B8```````````S```````-P````+`"`&BT````` +M````/\`H"B``````````%0`O`B(```````````S@``````.&````!@`O`B(` +M``````````S@``````.Q````%@`O`B(```````````S@``````.U````(``O +M`B(```````````S@``````.<````#P`O`B(```````````S@``````.H```` +M$``O`B(```````````S@``````.H````'@`O`B(```````````S@``````.0 +M``"BI``@1!$```````````!`2`(`````"``````I"B(``````````T`A#B`` +M````````#,`A$B````````@````H$B0`````````%,`B%B`````````````I +M%*0```````"BI``@1!$````````````I2*(```````"A_@`@1!$````````` +M``!`2`,`````@0`````@1!$``````````0`@2!$````````A^``@1!$````` +M````%@`@2!$```````0A^0!@1!$```:*````%0`A`C```````````!3@```` +M``.2```A#@`@1!$``````````,`@2````````````,`@2`````````"BI``@ +M1!$```````````!`2`(`````@0`````@1!$``````````0`@2!$````````A +M^``@1!$`````````%P`@2!$```````0A^0!@1!$```:*`````P`A`C`````` +M`````!3@``````.>```A"``@1!$``````````,`@2````````````,`@2``` +M``````"BI``@1!$```````````!`2`(```````"BI``@1!$````````````@ +M2`(`````@``````@1!$````````````@2!$`````@0`````@1!$````````` +M$``@2!$````````````@`!```````````!3```````.N``````!````````` +M```@$``@1!$```````"````@2!$```````&BI``@1!$`````````!@!`2!$` +M```````@$``@1!$```````"````@2!$```````&BI``@1!$`````````%@!@ +M2!$```-N``````!``````````````,`@"````````````,`@#``````````` +M'0`A`B,``````````!3@``````/.@0`````@1!$``````````0`@2!$````` +M```A^``@1!$`````````&``@2!$```````0A^0!@1!$```:*````$0`A`C`` +M`````````!3@``````/````A```@1!$````````````@2`(````````````@ +M2`,`````NK[*_@`@2!$`````ROZZO@`@2!$````````@$``@1!$```````"` +M```@2!$```````"BI``@1!$`````````!`!`2!$````````A<``@1!$````` +M```````@2`(````````````@2`,`````@0`````@1!$`````````"@`@2!$` +M```````````@`!```````````!3```````/3C``````@1!$`````ROZZO@!` +M2!$`````@0`````@1!$``````````0`@2!$````````__T`H"B``````@``` +M`$`H#B``````0````,`H$B````````0```!I1B(```:*```````@%!`````` +M```````O`B,```````````S```````/A`````,!`&`````/D```__\`H&B`` +M``````0```!I1B8```:*```````@&!`````````````O`B0```````````S` +M``````/G`````,!`'`````/J```__\`H'B````````0```!I1B<```:*```` +M```@'!`````````````@1`(````````````H(,4```````````!)2.@````` +MI8`````@"!$````````@```@#!$`````@P````!@1!$```02```````@1`(` +M`````````,`@2````````````$`@2```````````'\`A`B```````````!3` +M``````/W```@$``@1!$```````"````@2!$```````#__\!($B````/_IX`` +M```@"!$```````"@```@#!$`````@P````!@1!$```02```````@1`(````` +M`````,`@2````````````,`@2`````````#__\`H$B``````@P`````@1!$` +M```````````P2(,`````A``````@1!$``````````,`@2````````````!T` +M````````@P````!@1!$```02`````,!`!``````!J8`````@"!$```````#` +M``!`#!$```/ZJX`````@"!$```````#XX`!`#!$```/ZK8`````@"!$````` +M``#X@`!`#!$```/ZLX`````@"!$```````#S_`!`#!$```/ZKX`````@"!$` +M``````#@``!`#!$```/ZL8`````@"!$```````#P``!`#!$```/Z@P`````@ +M1!$````````A2``@2!$`````A``````@1!$``````````,`@2``````````` +M`!T```````````````"``````````1@@`,`P1B```````````-D`2``````` +M`````,`@!`````````````"@``H``````AB@`,`P1B```````````-D`2``` +M`````````,`@!`````````````"@``H``````QC``,`P1B```````````-D` +M2````````````,`@!`````````````"@``H`````!!CXX,`P1B`````````` +M`-D`2````````````,`@!`````````````"@``H`````!1CX@,`P1B`````` +M`````-D`2````````````,`@!`````````````"@``H`````!AC@`,`P1B`` +M`````````-D`2````````````,`@!`````````````"@``H`````!QCP`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H`````"!CS +M_,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M````,``@"BT``````````,`I#$``````````,``@-B,``````````,`@!``` +M``````````"@``H`````A@`````@1!$```````````!`2`$`````A0```,`@ +M1!$```````````!`2`$````````A?``@1!$``````````,`@2``````````` +M`,`@2````````````,`@2```````@0`````@1!$``````````0`@2!$````` +M`````,`@"````````````!<```````````0A?P!@1!$```:*````'P`A`C`` +M`````````!3```````````````!`3`(```1(`````,`@#````````````,`@ +M$````````````,`@%````````````,`@&````````````,`@'`````````!_ +M```H"B$```````!%```O`B(```````````S@``````16`````,`@(``````` +M`````!<`````````````$``H"B,`````````$``O`B(```````````S@```` +M``1>@0`````@1!$``````````0`@2!$```````0```!I1B0```:*``````!` +M``````1C@0`````@1!$````````````@2!$````````A;0`@1!$````````` +M```@2`0```````````!@2`4```:/```````H)/``````````!P`H"B,````` +M`````0`O`B(```````````K@``````1J```````O`,D```````````3@```` +M``2#``````!```````20`````@`O`B(```````````K@``````1O```````O +M`,D```````````+@``````2#``````!```````20`````P`O`B(````````` +M``K@``````1T```````O`,D```````````S@``````2#``````!```````20 +M````!``O`B(```````````K@``````1Y```````O`,D```````````K@```` +M``2#``````!```````20````!0`O`B(```````````K@``````1^```````O +M`,D```````````;@``````2#``````!```````20````!@`O`B(````````` +M``K@``````2#```````O`,D```````````C@``````2#``````!```````20 +M``!_```H"B$```````!%```O`B(```````````K@````````````"``A"B,` +M`````````!3```````2-```A:0`@1!$``````````,`@2````````````,`@ +M2````````````,`@2```````ROZZO@!`2!$``````````,`@1``````````` +M`,`@`````````````,!`2`````````!_```H"B$```````!%```O`B(````` +M``````K@``````26`````,`@`````````````,`@`````````````,!````` +M``````````!`3`@```16`````,`@"```````````$$`A#B``````````$4`A +M$B``````````$D`A%B`````````A:0`@1!$````````````@2`(````````` +M```A`B4``````````!3@``````2@``0``,!)2B````2A__O__\`H2B`````` +M```````A`B,``````````!3@``````2M`````,`@2````````````,`@2``` +M```````````A`B0``````````!3`````````@0`````@1!$`````````#``@ +M2!$````````````@`!```````````!3```````2IH``````@1!$`````ROZZ +MO@!`2!$`````@0`````@1!$`````````!``@2!$````````A:P`@1!$````` +M`````,`@2!``````@0`````@1!$`````````!0`@2!$````````A;``@1!$` +M`````````,`@2!`````````````O`B0```````````S@``````````````!` +M``````2G`````,`A"B```````````!3```````3`@0`````@1!$````````` +M```@2!$````````A;0`@1!$``````````,`@2````````````,!@2`````:/ +M``````!```````3$@0`````@1!$``````````0`@2!$```````0``,`I1B`` +M`````````,!@``````:*`````0`A`B(``````````!3```````3+```A:0`@ +M1!$``````````,`@2````````````,`@2``````````````@2!``````ROZZ +MO@!`2!$``````````,`@1````````````,!`2!``````@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````#@`@2!$```````0A^0!@1!$` +M``:*```````A`C```````````!3```````3-```A@``@1!$``````````,`@ +M2````````````,`@`````````````,`@2````````````,`@```````````` +M`,!`2````````````P`S/B\``````````0`A`B$``````````!3@``````3] +M````+``@"BT```````0``!C@#!$```3L`````0`S/B\````````A:0`@1!$` +M```````````@2`(````````````@2`,`````````"``P"B(``````````,`@ +M2````````````,`@2``````````A:0`@1!$````````````@2`(````````` +M```@2`,`````````"``P"B(``````````,`@2````````````-C`2`````3@ +M```A:0`@1!$````````````@2`(````````````@2`,`````````"``P"B(` +M`````````,`@2````````````,`@2```````````+0`@$BT````````````I +M#(,````````A:0`@1!$````````````@2`(````````````@2`,````````` +M"``P"B(``````````,`@2````````````,`@2```````````$0`A`B0````` +M`````!3```````````````!```````2G````+,`@-B``````````+`-:`'@#4@!X`U,`> +M`)>#TP#5P!X`R@@``(``&@#*#```Y`$>`-0`'@"```P`Q!@X`.0!/@#4`!X` +M@``,`,08.`#40!X`[@`>`,H$``"@````?H*+`.0!'@#4`!X`U$`>`.X`'@#* +M!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^@HL`RA@``-1` +M'@#5@!X`@`!3`-0`=0#40!X`R@@``,H,``#*$```U(`9`-3`&`#5`!<`U(`> +M`-3`'@#5`!X`X@`>`,H$``"@````?H*+`,H(``#4@&``U$`>`(````#4@!X` +MR@@``-2`80#40!X`@````-2`'@#*"```R@P``-1`'@#4@!8`U,`6`-2`'@"` +M`;@`U,`>`,8(0P#*#```RA```)2`!`#*%```Y"#S`-0@$P#58&4`U.`<`-4@ +M'`#58!P`@`````8@`0#&"$,`R@P``,H0``"4@_<`RA0``.0@\P"``'D`U"`3 +M`,8(0P#*#```RA```)B#[P#*%```U`!D`(``C0``````Q!0R`,880P#$""\` +ME4`%`,0,,`#40!X`@````.X`'@"5@_4`Q!`Q`-1`,P#5(&4`U*`<`-3@'`#5 +M(!P`Y`%>`-0`'@"`````!B`!`,H8```*(`$`U@!V`,0(-@"8@`<`QA!%`)4! +M$`#4`!\`U&!B`(````#4(&(`S#@U`,P4,P"$`;L`U`!R`-5`'@"`````[@`> +M`.(`&@"$`;L`X@`:`,P02P#,!$<`+)0!`'T)BP"80`4`?17+`-0`&@"``;@` +MU`!M`#1$`0#,#$@`F$`Z`,PL2@"5@`0`S`1)`(`!N`#4`!H`U,`:`"@H`0"$ +M`/``S!`#`)B`&P`$.`P`A`#P`,P0`P"8@!<`!#@(`(0`\`#,$`,`F(`3``0X +M!`"$`/``S!`#`)B`%`#,$$P`FH`)`,P430"80-P`U`!M`,P82`#5`!H`U4`: +M`(``R0#5@!H`EL#5`-0`;0"``;@`U`!N`)K``P#4`&T`U`!N`(````#L`'\` +MFL#,`-0`;0"``;@`U`!N`,P4`P#,&`,`S!P#`'V1`P!]U8,`?1D,`#7,'P`U +M`.0!'@#4`!X`R@@``,H, +M``#*$```U$`>`,H4``#4@!X`U,`>`-4`'@#50!X`U4`T`(````#N`!X`*`0$ +M`.(`&@#B`!H`U$`:`,HX``#,"`,`S`P#`,P,`P#,#`,`F(*]``````"$`;L` +MUZ!O`(````#N`!\`R@0``,+_``#,"#0`P3__`'QTRP!\R0L`?0$/`)D"L`!\ +M@;P"`````[@`?`,H(```H&0``?8F+`)6`%``H%`0`R@P``,H0 +M``#*'```RB0``.(`'P#4P!H`U0`:`-5`&@#,&`,`S"P#`,PL`P#,+`,`?:6+ +M`'V<1P"80I<``````(`!80#4P!H`U$`>`-2`'@"`````[@`>`.0!'@#4`!X` +MU$`>`.X`'@#*!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^ +M@HL`R@@``"2,!@`,S`8`F,`&`,P03@"9``0`U`!S`.0!'@#4`!X`U$`>`-2` +M'@"`````[@`>`,H(``#*#```--`8`"40`0"5`"$`P7__`,H0``#*%```RA@` +M`-2`'0#4P!T`?;&+`,%"`@#"P`$`U8`=`#3<#@!]74P`?W-,`-=`'@#5`!X` +MU4`>`,%"``#"P```"9P!`#'<$`!_7TP`?W-,``0H`@!]@X``U:AO`-6`9@#7 +M0!X`[`!>`,@D`@#()`(`@`&X`-8`=@#40!X`U(`>`-3`'@"`````[@`>`(`` +M``#N`!\`U``?`(````#4`!\`U``?`(@```#4`!\````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0%Q``(!>``#`(\`!`!_``4``P`& +M`#\`!P`R``@!+``)`$8`"@`V`!`!M@`7`*(`(@$Z`",!20`@`+0`)`$E`"<` +M30`H`&H`*@!@`"L`4@`O`&4`,@"'`#0!?P`\`58`/P!R`$$!C`!$`2X`50%S +M`%8!>@!@``L`80`T`&(`.`!C`#@`9``X`&4`.`!F`#@`9P`X`&@`.@!I`$$` +M:@!(`&L`2`!L`$@`;0!(`&X`2`!O`$@````&````!@````8````&````!@`` +M``8````&````!@````8````&````!@````8````&````!@````8````&```` +)!@````8````& +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV670_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV670_me.bin.uu new file mode 100644 index 00000000000..ded47c21d9e --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV670_me.bin.uu @@ -0,0 +1,481 @@ +begin 644 RV670_me.bin +M`````,`@!`````````````"@``H```````#__P`H1B$``````````-D`2``` +M`````````,`@!`````````````"@``H```````````#@``````````$``,`I +M1B```````````-D`2````````````,`@!`````````````"@``H`````@0`` +M```@1!$``````````0`@2!$```````0@!`!@1!$```9\``````!@``````8D +M``````!@``````8X`````,`@"``````````/```H%B(`````````"``A%B4` +M````````&``@-B4`````C0`````@1!$`````````!``O`B4```````````S@ +M```````8`$$@``!`2!$````9`$(@```@2!$`````C@`````@1!$````````` +M*``@2BT`````D``````@1!$````````````@2`4`````````#``A%B(````` +M`````P`H%B4`````````&0`A&B(`````````!``H&B8````````````I%,4` +M````````&0`@-B4````````````Z%`(`````````%@`A%B4``````````P`H +M%B4`````````%P`@#BT`````_____``H#B,````````````I%*,````````` +M%P`@-B4```````"````H#B(`````````!P`B#B,````````````I.&X````` +M(``````H#B(`````````!@`A#B,````````````I.&X````````````B`B(` +M`````````!3@```````X`````"[@```````U`````"S@```````W``````!` +M#BT````Y````"``@#BT`````````"0!`$BT```!&`````0!`#BT````Y```` +M`,`@#````````#___``H$B,``````````@`B$B0`````````'P`A'B,````` +M`````!3@```````^````"`!`'!$```!!````#0`@'BT`````````#P`H'B<` +M`````````P`B'B<`````?\`````H&B,`````````%``A&B8``````````0`S +M&B8`````````"``B&B8````````````I#,<`````````)P`@-B0```````!_ +M```H$B$````````4```O`B0```````````S@``````!+`````0`I#B,````` +M````#@`@-B,```````#@```@1!$`````__@````I2B,````````````Z+`(` +M`````````@`B#BL`````_``````H#B,`````````#P`@-B,````````?_P`I +M2B,`````````)P`@2BT````````````@2!$`````````*0`@#BT`````!@H" +M```I2B,````````````@2!$````````````@2!$``````````0`A`B(````` +M`````!3@``````!A`````"[@``````!?`````"S@``````!>``````!`#BT` +M``!B`````0!`#BT```!B````"@`@#BT`````````"P!`$BT```!J`````,`@ +M#````````#___``H$B,``````````@`B$B0`````?\`````H%B,````````` +M%``A%B4``````````0`S%B4`````@``````H#B,````````````I#*,````` +M/__\```I#B,`````````'P`A'B,``````````!3@``````!M```!``!`'!$` +M``!P````#0`@'BT`````````\``H'B<`````````!``B'B<`````@0`````@ +M1!$`````````#0`@2!$`````___P_P`H&C````````"@*``@1!$````````` +M```I2.8```````"@&``@1!$`````/____P`H2B,```````"@$``@1!$````` +M```````@2`0`````````,``@%BT``````````@`I%B4`````````,``@-B4` +M````````)0`@%BT````````````O`*,```````````S```````"#````)@`@ +M%BT````````````O`*0```````````S```````"$``````!```````"*```` +M)0`@-B,`````````)@`@-B0`````````%P`@'BT``````````@`A`B<````` +M`````!3@``````"*``````!@``````99``````!@``````9-`````@`A#B(` +M`````````!3```````"-````$L!`-B````"3`````"[@``````"1`````"S@ +M``````"0`````@!`#BT```"2`````P!`#BT```"2````#``@#BT````````` +M$@`@-B,``````````P`A#B(``````````!3```````"8``"@#``@1!$````` +M`````,`@2````````````,!`2`````"@``"@#``@1!$````````````@2!$` +M`````````"[@``````">`````"S@``````"=`````@!`#BT```"?`````P!` +M#BT```"?````#``@#BT````````````@2`,````````````Z#`(``````#\` +M```H#B,`````````$``A#B,`````````$0`@-B,`````````'@`A`BL````` +M`````!3```````"G````%L`@-B``````````'P`A`BL``````````!3````` +M``"J````%<`@-B``````````"``A#BL`````````?P`H#B,````````````O +M`B,```````````S@``````#A`````"<```````````````!@``````*C```` +M`0`O`B,```````````K@``````"S``````!@``````$Z@0`````@1!$````` +M````!@`@2!$`````````#``B'C``````F8`````@1!$`````````!``@$BT` +M````````"``B$B0`````````$``@&!$````````````I'.0```````````!@ +M2`<```$OFP`````@1!$````````````@2`(`````G``````@1!$````````` +M```S%&\``````````0`S/B,``````````-D`2``````````````@/`4````` +M@0`````@1!$`````````#@`@2!$````````````@$!````````#@!P`@1!$` +M````````#P`A`BL``````````!3```````#+`/C_"``@2!$`````F`````!` +M2!$```#<````\``H#B(`````````H``O`B,```````````S```````#:```` +M$0`@#BT``````````0`O`B,```````````S@``````#5`````@`O`B,````` +M``````S@``````#4```_``!`#!$```#6```?``!`#!$```#6```/```@#!$` +M`````#@`"0`I2B,`````/P`````H#BL``````````@`B#B,`````````!P!) +M2B,```#<`#@/"0`@2!$`````:```!P`@2!$`````````"``A2B<````````` +M```@2!$`````!@H"```I2B0````````````@2!$````````````@2!$````` +M``"B`@`@1!$``````/\````H#B(`````````@``I2B,`````````)P`@#BT` +M````````)@`@$BT````````````O`(,```````````S@``````#J``````!@ +M``````93``````!```````#K``````!@``````96````!P`@(BT````````` +M!0`B#B(``````!`````H#B,````````````I(&@````````````Z#`(````` +M````[P`H#B,````````````I(&@`````````%P`@#BT``````````P`A`B,` +M`````````!3@``````#X````"P`A`B@``````````!3```````#X```$```I +M(B@`````````%``@-B@`````````'``A#B(``````````!3```````#]``"C +M#``@1!$````````````@2!$`````````'@`A#B(``````````!3```````$+ +M``"C#P`@1!$`````````$0`@#BT``````````0`O`B,```````````S````` +M``$$_____P!`2!$```$+`````@`O`B,```````````S```````$'``#__P!` +M2!$```$+````!``O`B,```````````S```````$*````_P!`2!$```$+```` +M`0`@2!$```````+$```@1!$`````````'P`A#B(``````````!3```````$2 +M````$$`A#B``````````$P`@-B,`````````&$`B2B``````````$,!"2B`` +M``$4```````@#!$`````````$P`@-B,````````````@2!$````````````@ +M2!$`````````"@`@$!$````````````O`B0```````````S@``````$;```` +M```@2!$``````````0!3$B0```$7_[___P`H.BX`````````&P`A`B(````` +M`````!3```````$N@0`````@1!$`````````#0`@2!$`````````&``B#C`` +M````_``````H#B,`````@0`````@1!$`````````#@`@2!$````````````@ +M$!````````#@#@`@1!$`````!_C_"``@2!$````````````I2B,````````` +M'``@'BT`````````"``A2B<````````````@2!$`````!@H"```I2B0````` +M```````@2!$````````````@2!$```````````"`````````@0`````@1!$` +M`````````0`@2!$````````A?``@1!$``````(`````@2!$````````````@ +M2`8`````````"``A2B<``````````!<```````````0A?P!@1!$```9\```` +M'P`A`C```````````!3```````9[````!`!`3!$```$U@0`````@1!$````` +M`````0`@2!$````````A^``@1!$`````````'``@2!$```````0A^0!@1!$` +M``9\````$0`A`C```````````!3@``````$\``````"```````````````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```` +M``!@``````%@``#__T`H#B``````````$,`A$B````````#__T`H!B`````` +M````$,`A"B`````````````T%&$```````````!T&((```*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%'`````,!`!``````!``````!@ +M```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R```_ +M_P`O`B\```````````S@``````````````!@``````%@````$$`A#B`````` +M``#__\`H$B``````````$$`A%B````````#__\!H&B````*[``&A_0!@1!$` +M``+@```__P`O`B\```````````S```````%8`````,!`!``````!```B7``@ +M1!$``````````0`P"B\``````````0`A"B(``````````P`X2B(````````B +M5@`@1!$`````````&@`@2!$```````"A_``@1!$``````````0"`2!$````` +M``````!@```````+``````!@``````&/``````!@``````&@```__P`O`B\` +M``````````S@```````````````@+`@````````````@)!$````````````@ +M*!$````````B5@`@1!$`````````%@`@2!$````````B7``@1!$````````` +M`P`@2!$`````DX`````@1!$``````````@`B'BD```````````!P2.L```&< +M``````!@``````*[`````4`S!B```````````,`P)`D````````__P`O`B\` +M``````````S@``````````````!@``````*C```````O`B$```````````K@ +M``````&!``````!@``````$Z``````!```````&&E0`````@1!$````````` +M```O`B$```````````S@``````&&`````,`@2````````````0!3!B$```&" +MD@`````@1!$``````````,!@2`````&7``&A_0`@1!$`````````$0`@!BT` +M``````````!X!"H```+[```````@*`D````````__P`O`B\```````````S` +M``````%T`````,!`!``````!```"$`!@!!$```,5```__P`O`B\````````` +M``S@``````&4````%<`@-B``````````%L`@-B``````/X`````@!!$````` +M1@````!@"!$```&R``````"```````````"A_``@1!$````````__P`O`B\` +M``````````S```````&;`````0"`2!$`````````(0"`2!$```````#__T`H +M#B``````````$,`A$B````````#__T`H%B``````````$,"!&B``````@0`` +M```@1!$`````````!@`@2!$`````````"``B'C``````````*0`@&BT````` +M``#@```@1!$`````__O_"0`@2!$`````````#P`@(BT````````?_P`I2B@` +M````````!@`@(BT````````````I(.@````````````@2`@````````````@ +M2!$`````!@H"```I2B8````````````@2!$````````````@2!$````````! +M```@&!$`````````"`!B'B@```$O````"`""(B@```````+````@1!$````` +M````%0!@#BT```&]````%@!@#BT```&]``#`"``@1!$`````````%P`@#BT` +M`````````!3```````&Y```````@!!$````````````@2`$`````.0`````@ +M2!$````````````@2!$```````````"`2`(`````````&``@+BT````````` +M```[#6,`````````"``B2B,`````````$``B2B,`````````&``B2B,````` +M``````"`2`,```````````!@```````+```0``!@!!$```,5```````@!!$` +M``````````!@"!$```&R````!P`A!B\`````````$P`@"BT``````````0`@ +M+!$```````#__T`H(B``````````#P`F(B@`````````$$`A)B`````````` +M#P`F)BD````````````@*`(````````B5@`@1!$`````````&P`@2!$````` +M```````O`B$```````````S@``````'@```B7``@1!$`````````@0`@2!$` +M``````"A_``@1!$``````````0`@2!$`````````@``@'!$````````````O +M`B<```````````S@``````'<``````!@``````'I`````0!3'B<```'8```` +M`0`@+!$`````````'P`H"B(`````````'P`H*BH``````````0!3!B$```'1 +M```B7``@1!$``````````@`P2B\```````"A_``@1!$``````````0`@2!$` +M`````````0`P'B\````````````O`B<```````````S@``````````````!@ +M``````'I`````0!3'B<```'E``#__T`H#B``````````#P`F#B,````````` +M$,`A$B``````````#P`F$B0````````````@%!$```````````!@&!$```*[ +M``&A_0`@1!$````````````O`BL```````````S@``````'X````$``B%B@` +M````__\````H%B4```````#__P`H&BD````````````I2,4````````````@ +M2`H````````````@+!$`````````$``B%B,`````__\````H%B4```````#_ +M_P`H&B0````````````I2,4```````````!S%0,```(%```````@&`4````` +M``````!S%20```(%```````M%,4````````````P"*(````````````@2`(` +M```````````@*`(````````````@(`,```````````"`)`0`````````#P`A +M`B4``````````!3```````9[```````K%`4``````````0"0%B4````````` +M``!@```````+``````!@!!$```,5```````@!!$```````````!@"!$```&R +M```B5@`@1!$`````````&@`I2B(``````````,`@```````````__P`O`B\` +M``````````S@`````````````,`@!``````````B7``@1!$``````````P`X +M2B$```````"A_``@1!$``````````0`@2!$```````#__T`H$B`````````` +M$,`A&B````````#__T`H#B``````````$,`A%B````````````!T%&4```*[ +M``&A_0!@1!$```+@`````0`S!B$````````````O`B$```````````S````` +M``(9```__P`O`B\```````````S```````(2`````,!`!``````!``````!@ +M``````8X``````!`!`\```(3``````!@``````8D``````!@``````8X```" +M$`!@!!$```,5``````!@``````&@``````!@``````&<``````!@``````*[ +M``````!@``````*CDX`````@1!$````````````@2`@````````````O`B\` +M``````````K@``````(R``````!@``````$Z``````!```````(VE0`````@ +M1!$````````````O`B\```````````S@``````(V`````,!`2`````(SD@`` +M```@1!$``````````,`@2``````````B5@`@1!$`````````%@`@2!$````` +M```B7``@1!$``````````P`@2!$```````"A_``@1!$``````````0`@2!$` +M``````&A_0`@1!$```````````!@!!$```+[`````,!`!``````!``````!@ +M``````8D``"@#``@1!$``````````,`@2````````````,!`2``````````` +M``!@```````+````&$`A"B```````````P`O`B(```````````K@``````), +M````%``@(BT```````@!`0`I(B@`````````%``@-B@```````"C#``@1!$` +M`````````,`@2````````````,`@2````````````,!`2`````)1``````!@ +M```````+````$`!@!!$```,5/X`````@!!$```````````!@"!$```&R```B +M7``@1!$``````````P`@2!$```````````!@``````)\````%P`@'BT````` +M`````0`A'B<``````````!3@``````)J````$@`@'BT```````#__P`H'B<` +M```````````T'"<``````````!+```````)?```````@'!$````````````O +M`.4```````````C```````)B```````@%`<`````````$@`@'BT````````` +M$``A'B<````````````T'$<``````````!+```````)G```````@'!$````` +M```````O`.8```````````C```````)J```````@&`<```````````!@```` +M``+!```B5@`@1!$````````````T(",``````````!+```````)R```````T +M($0``````````!+```````)Q````%@!`2!$```)V````&`!`2!$```)V```` +M```T($0``````````!+```````)U````%P!`2!$```)V````&0`@2!$````` +M``"A_``@1!$``````````0`@2!$```````&A_0!@1!$```+I```__P`O`B\` +M``````````S```````)6`````,!`!``````!````$$`A!B````````#__\`H +M"B``````````$$`A#B````````#__\`H$B``````````$$`A%B````````#_ +M_\"(&B``````@0`````@1!$``````````0`@2!$```````0@!`!@1!$```9\ +M``````!@``````8D`````,!@``````*C````!0`@"BT`````````"``B"B(` +M````````*P`@&BT`````````'``@'BT```````!P```H'B<````````````Q +M'.8`````````*@`@&BT`````````#``B&B8````````````O`.8````````` +M``;@``````*2```````@'!$````````````@#!$`````````*P`@-B,````` +M````$``@&!$```````````!I'.(```$ODX`````@1!$````````````@2`<` +M````E0`````@1!$````````````O`B\```````````S@``````*=`````0`S +M/B\``````````-D`2```````D@`````@1!$``````````,`@2``````````` +M'`!`-B<`````````#,`B"B``````````*0`@-B(`````````*,!`-B`````` +M``"BI``@1!$`````````"0`@2!$`````H0`````@1!$``````````0"`2!$` +M````````(0`@'BT````````````L'.,`````````(0`@-B<`````````(@`@ +M'BT````````````L'.0`````````(@`@-B<`````````(P`@'BT````````` +M```Q(*,````````````M'0<`````````(P`@-B<`````````)``@'BT````` +M```````Q(,0````````````M'0<`````````)`"`-B<`````````(0`@-B,` +M````````(@`@-B0````````````Q'*,`````````(P`@-B<````````````Q +M',0`````````)`"`-B<`````````&@`@-B<`````````&P`@-B@````````` +M%P`@'BT``````````@`A`B<``````````!3```````+<``````!```````+9 +M````&@`@-B<`````````&P`@-B@`````````%P`@'BT``````````@`A`B<` +M`````````!3@``````+9`````P`A`B<``````````!3@``````+<````(P`@ +M'BT````````````N`.$```````````+```````+<````(0`@'BT````````` +M```Q(*$````````````N`.@```````````;```````+<````)``@'BT````` +M```````N`.(```````````+```````+<````(@`@'BT````````````Q(,(` +M```````````N`.@```````````;```````+<``````!@``````99``````!@ +M``````*U``````!```````+>``````!@``````*U``````!@``````90```` +M``!```````+>``````!@``````*G``````!```````+>````&@`@'BT````` +M````&P"`(BT`````````$``B'B,````````````I2(<````````````Q'*,` +M````````$``B'B<````````````I2(<`````````$``B'B,````````````Q +M(,0```````#__P`H(B@```````````")20<`````````$``B'B,````````` +M```I2(<`````````$``B'B$````````````I2$<````````````Q'*,````` +M````$``B'B<````````````I2(<````````````Q'*$`````````$``B'B<` +M```````````I2$<`````````$``B'B,````````````Q(,0```````#__P`H +M(B@````````````I20<`````````$``B'B$````````````Q(,(```````#_ +M_P`H(B@```````````")20<`````````$``B'B,````````````I2(<````` +M`````0`B"B$````````````S"*(`````````$``B'B(`````````$``A(B(` +M```````````I20<````````````Q'*,`````````$``B'B<````````````I +M2(<``````````0`B"B$````````````P"*(`````````$``B'B(````````` +M$``A(B(````````````I20<`````````$``B'B,````````````Q(,0````` +M``#__P`H(B@````````````I20<````````````X",4````````````P"$$` +M`````````0`B"B(````````````S"*(`````````$``B'B(`````````$``A +M(B(```````````")20<`````````%P`@(BT``````````!3```````,8____ +M[P`H!B$`````````%``@(BT```````#XX``@1!$````````````I20$````` +M``````")20$````````````@2!$````````````@2!$`````!@H"``"`2!$` +M`````````,`@````````EP```,`@1!$``````````,`@2!$`````B@`````@ +M1!$````````````@2!$````````B7``@1!$``````````,`@2`````````"A +M_``@1!$``````````,`@2````````````,`@!`````````````"@``H````` +MEP`````@1!$````````````@2!$`````B@`````@1!$````````````@2!$` +M```````B7``@1!$``````````,`@2`````````"A_``@1!$``````````,`@ +M2````````````,`@!`````````````"@``H`````EP`````@1!$````````` +M```@2!$`````B@`````@1!$````````````@2!$````````B7``@1!$````` +M`````,`@2`````````"A_``@1!$``````````,`@2`````````&A_0`@1!$` +M`````````-D`2````````````,`@!`````````````"@``H````````B5P`@ +M1!$``````````\!(2B`````````B70`@1!$``````````,!`2``````````` +M``!@``````8X`````,`@"``````````B7``@1!$``````````P`X2B(````` +M``"A_``@1!$``````````,`@2`````````&A_0`@1!$````````````O`B(` +M``````````S@`````````````$`@2````````````4`P2B```````````L`P +M2B```````````0!3"B(```-+````/\`H"B``````@0`````@1!$````````` +M`0`@2!$````````A^``@1!$`````````&``@2!$```````0A^0!@1!$```9\ +M````$0`A`C```````````!3@``````-4````%``O`B(```````````S````` +M``-B``&BI``@1!$```````````!@2`(```-J```A```@1!$``````````,`@ +M2````````````,`@2````````````,`@2````````````,!`2``````````` +M!``O`B(```````````S```````-F``&BI``@1!$```````````!`2`(```-= +M````*``O`B(```````````S```````6S``&BI``@1!$```````````!`2`(` +M``-=````+``@-B8`````````20`@&!$`````````/P`@2!$``````````0`S +M&B8````````````O`B8```````````S```````-L````+`"`&BT````````` +M/\`H"B``````````%0`O`B(```````````S@``````."````!@`O`B(````` +M``````S@``````.M````%@`O`B(```````````S@``````.O````(``O`B(` +M``````````S@``````.8````#P`O`B(```````````S@``````.D````$``O +M`B(```````````S@``````.D````'@`O`B(```````````S@``````.,``"B +MI``@1!$```````````!`2`(`````"``````I"B(``````````T`A#B`````` +M````#,`A$B````````@````H$B0`````````%,`B%B`````````````I%*0` +M``````"BI``@1!$````````````I2*(```````"A_@`@1!$```````````!` +M2`,`````@0`````@1!$``````````0`@2!$````````A^``@1!$````````` +M%@`@2!$```````0A^0!@1!$```9\````%0`A`C```````````!3@``````.. +M```A#@`@1!$``````````,`@2````````````,`@2`````````"BI``@1!$` +M``````````!`2`(`````@0`````@1!$``````````0`@2!$````````A^``@ +M1!$`````````%P`@2!$```````0A^0!@1!$```9\`````P`A`C`````````` +M`!3@``````.:```A"``@1!$``````````,`@2````````````,`@2``````` +M``"BI``@1!$```````````!`2`(```````"BI``@1!$````````````@2`(` +M````@``````@1!$````````````@2!$`````@0`````@1!$`````````$``@ +M2!$````````````@`!```````````!3```````.J``````!```````````&B +MI``@1!$`````````!@!`2!$```````&BI``@1!$`````````%@!@2!$```-J +M``````!``````````````,`@"````````````,`@#```````````'0`A`B,` +M`````````!3@``````/$@0`````@1!$``````````0`@2!$````````A^``@ +M1!$`````````&``@2!$```````0A^0!@1!$```9\````$0`A`C`````````` +M`!3@``````.X```A```@1!$````````````@2`(````````````@2`,````` +MNK[*_@`@2!$`````ROZZO@`@2!$```````"BI``@1!$`````````!`!`2!$` +M```````A<``@1!$````````````@2`(````````````@2`,`````@0`````@ +M1!$`````````"@`@2!$````````````@`!```````````!3```````/)C``` +M```@1!$`````ROZZO@!`2!$`````@0`````@1!$``````````0`@2!$````` +M```__T`H"B``````@````$`H#B``````0````,`H$B````````0```!I1B(` +M``9\```````@%!`````````````O`B,```````````S```````/7`````,!` +M&`````/:```__\`H&B````````0```!I1B8```9\```````@&!`````````` +M```O`B0```````````S```````/=`````,!`'`````/@```__\`H'B`````` +M``0```!I1B<```9\```````@'!`````````````@1`(````````````H(,4` +M``````````!)2.@`````I8`````@"!$````````@```@#!$`````@P````!@ +M1!$```0(```````@1`(``````````,`@2````````````$`@2``````````` +M'\`A`B```````````!3```````/M```@$``@1!$```````"````@2!$````` +M``#__\!($B````/UIX`````@"!$```````"@```@#!$`````@P````!@1!$` +M``0(```````@1`(``````````,`@2````````````,`@2`````````#__\`H +M$B``````@P`````@1!$````````````P2(,`````A``````@1!$````````` +M`,`@2````````````!T`````````@P````!@1!$```0(`````,!`!``````! +MJ8`````@"!$```````#```!`#!$```/PJX`````@"!$```````#XX`!`#!$` +M``/PK8`````@"!$```````#X@`!`#!$```/PLX`````@"!$```````#S_`!` +M#!$```/PKX`````@"!$```````#@``!`#!$```/PL8`````@"!$```````#P +M``!`#!$```/P@P`````@1!$````````A2``@2!$`````A``````@1!$````` +M`````,`@2````````````!T```````````````"``````````1@@`,`P1B`` +M`````````-D`2````````````,`@!`````````````"@``H``````AB@`,`P +M1B```````````-D`2````````````,`@!`````````````"@``H``````QC` +M`,`P1B```````````-D`2````````````,`@!`````````````"@``H````` +M!!CXX,`P1B```````````-D`2````````````,`@!`````````````"@``H` +M````!1CX@,`P1B```````````-D`2````````````,`@!`````````````"@ +M``H`````!AC@`,`P1B```````````-D`2````````````,`@!``````````` +M``"@``H`````!QCP`,`P1B```````````-D`2````````````,`@!``````` +M``````"@``H`````"!CS_,`P1B```````````-D`2````````````,`@!``` +M``````````"@``H`````````,``@"BT``````````,`I#$``````````,``@ +M-B,``````````,`@!`````````````"@``H`````A@`````@1!$````````` +M``!`2`$`````A0```,`@1!$```````````!`2`$````````A?``@1!$````` +M`````,`@2````````````,`@2````````````,`@2```````@0`````@1!$` +M`````````0`@2!$``````````,`@"````````````!<```````````0A?P!@ +M1!$```9\````'P`A`C```````````!3```````````````!`3`(```0^```` +M`,`@#````````````,`@$````````````,`@%````````````,`@&``````` +M`````,`@'`````````!_```H"B$```````!%```O`B(```````````S@```` +M``1,`````,`@(````````````!<`````````````$``H"B,`````````$``O +M`B(```````````S@``````14@0`````@1!$``````````0`@2!$```````0` +M``!I1B0```9\``````!```````19@0`````@1!$````````````@2!$````` +M```A;0`@1!$````````````@2`0```````````!@2`4```:!```````H)/`` +M````````!P`H"B,``````````0`O`B(```````````K@``````1@```````O +M`,D```````````3@``````1Y``````!```````2&`````@`O`B(````````` +M``K@``````1E```````O`,D```````````+@``````1Y``````!```````2& +M`````P`O`B(```````````K@``````1J```````O`,D```````````S@```` +M``1Y``````!```````2&````!``O`B(```````````K@``````1O```````O +M`,D```````````K@``````1Y``````!```````2&````!0`O`B(````````` +M``K@``````1T```````O`,D```````````;@``````1Y``````!```````2& +M````!@`O`B(```````````K@``````1Y```````O`,D```````````C@```` +M``1Y``````!```````2&``!_```H"B$```````!%```O`B(```````````K@ +M````````````"``A"B,``````````!3```````2#```A:0`@1!$````````` +M`,`@2````````````,`@2````````````,`@2```````ROZZO@!`2!$````` +M`````,`@1````````````,`@`````````````,!`2`````````!_```H"B$` +M``````!%```O`B(```````````K@``````2,`````,`@`````````````,`@ +M`````````````,!```````````````!`3`@```1,`````,`@"``````````` +M$$`A#B``````````$4`A$B``````````$D`A%B`````````A:0`@1!$````` +M```````@2`(````````````A`B4``````````!3@``````26``0``,!)2B`` +M``27__O__\`H2B`````````````A`B,``````````!3@``````2C`````,`@ +M2````````````,`@2``````````````A`B0``````````!3`````````@0`` +M```@1!$`````````#``@2!$````````````@`!```````````!3```````2? +MH``````@1!$`````ROZZO@!`2!$`````@0`````@1!$`````````!``@2!$` +M```````A:P`@1!$``````````,`@2!``````@0`````@1!$`````````!0`@ +M2!$````````A;``@1!$``````````,`@2!`````````````O`B0````````` +M``S@``````````````!```````2=`````,`A"B```````````!3```````2V +M@0`````@1!$````````````@2!$````````A;0`@1!$``````````,`@2``` +M`````````,!@2`````:!``````!```````2Z@0`````@1!$``````````0`@ +M2!$```````0``,`I1B```````````,!@``````9\`````0`A`B(````````` +M`!3```````3!```A:0`@1!$``````````,`@2````````````,`@2``````` +M```````@2!``````ROZZO@!`2!$``````````,`@1````````````,!`2!`` +M````@0`````@1!$``````````0`@2!$````````A^``@1!$`````````#@`@ +M2!$```````0A^0!@1!$```9\```````A`C```````````!3```````3#```A +M@``@1!$``````````,`@2````````````,`@`````````````,`@2``````` +M`````,`@`````````````,!`2````````````P`S/B\``````````0`A`B$` +M`````````!3@``````3S````+``@"BT```````0``!C@#!$```3B`````0`S +M/B\````````A:0`@1!$````````````@2`(````````````@2`,````````` +M"``P"B(``````````,`@2````````````,`@2``````````A:0`@1!$````` +M```````@2`(````````````@2`,`````````"``P"B(``````````,`@2``` +M`````````-C`2`````36```A:0`@1!$````````````@2`(````````````@ +M2`,`````````"``P"B(``````````,`@2````````````,`@2``````````` +M+0`@$BT````````````I#(,````````A:0`@1!$````````````@2`(````` +M```````@2`,`````````"``P"B(``````````,`@2````````````,`@2``` +M````````$0`A`B0``````````!3```````````````!```````2=````+,`@ +M-B``````````+```````A`B$``````````!3````` +M``8!``2@`P!@1!$```9\``"@`P`@1!$````````````@2!```````````0`A +M!B$``````````!3```````8&``2@$`!@1!$```9\``"@$``@1!$````````` +M```@2!```````````0`A!B$````````````O`B$```````````S@``````8> +M``2@$0!@1!$```9\``"@$0`@1!$````````````@2!````````2@$@!@1!$` +M``9\``"@$@`@1!$````````````@2!````````2@$P!@1!$```9\``"@$P`@ +M1!$````````````@2!````````2@%`!@1!$```9\``"@%``@1!$````````` +M```@2!````````2@%0!@1!$```9\``"@%0`@1!$````````````@2!`````` +M``2@%@!@1!$```9\``"@%@`@1!$````````````@2!````````2@%P!@1!$` +M``9\``"@%P`@1!$````````````@2!````````0@!`!@1!$```9\````+`"` +M!BT`````_P`````@1!$````````````@2!$``````````0`@2!$````````` +M`@"`2!$```````````[@``````8P````,``@!BT``````````@`H!B$````` +M```````O`B$```````````S@``````8N@0`````@1!$``````````0`@2!$` +M``````0@!`!@1!$```9\```0```@"!$`````````*P`@-B(```````````!@ +M``````8T``````!@``````6\F``````@1!$```````````"`2!$````````` +M`,!@``````8T`````,!`!``````!``"BI``@1!$`````````(@`@2!$````` +MB0`````@1!$``````````0!`2!$```8@EP`````@1!$````````````@2!$` +M````B@`````@1!$```````````!`2!$```8@``````!@``````9-``&BI,`@ +M1!$`````````%@!@2!$```-J```@$``@1!$```````$````@2!$`````@0`` +M```@1!$``````````0`@2!$````````A?``@1!$`````"8`````@2!$````` +M_____P`@2!$````````````@2!$``````````!<```````````0A?P!@1!$` +M``9\````'P`A`C```````````!3`````````````!`!`3!$```9'``````!` +M````````````%P`@'BT`````````!``I'B<`````````%P"`-B<````````` +M%P`@'BT`````____^P`H'B<`````````%P"`-B<`````````%P`@'BT````` +M````"``I'B<`````````%P"`-B<`````````%P`@'BT`````____]P`H'B<` +M````````%P"`-B<```````&BI``@1!$`````````%@!@2!$```-J```@$``@ +M1!$```````$````@2!$````````A?``@1!$``````8`````@2!$`````____ +M_P`@2!$````````````@2!$``````````!<`````````@0`````@1!$````` +M`````0`@2!$```````0A?P!@1!$```9\````'P`A`C```````````!3````` +M``9[````$`!`3!$```9A`````,`@!````````````#C`````````````'0`@ +M"BT`````````'@`@#BT`````````'P`@$BT`````````(``@%BT````````A +M:0`@1!$````````````@2`0````````````@2`4````````````@2`$````` +MROZZO@`@2!$`````````!``P$B0````````````O`&0```````````S````` +M``9Z`````P`H&B(`````````"``B$B(`````___P```H$B0````````````I +M$,0`````````'P!`-B0```````````"``````````````!K```````9\GP`` +M```@1!$`````ROZZO@`@2!$``````````!K@``````9_``````"````````` +M`````!K```````:!G@`````@1!$`````ROZZO@`@2!$``````````!K@```` +M``:$``````"```````````````!@```````+```0``!@!!$```,5```````@ +M!!$```````````!@"!$```&R```B7``@1!$``````````P`@2!$````````B +M5@`@1!$`````````&P`@2!$```````"A_``@1!$``````````0`@2!$````` +M``&A_<`@1!$`````````(0`@'BT`````````$``B'B<`````````)``@(BT` +M``````#__P`H(B@````````````I20<````````````@2!$`````````(@`@ +M(BT```````#__P`H(B@````````````I20<````````````@2!$````````` +M(P`@'BT`````````$``B'B<````````````I20<```````````!`2!$````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````4($]06S`E```````<,!:`0U!;,``````B4" +M"0)0`5$``````B,"10*@`D$``````\T%LP6S!;,`````!CP&/0,?!;,````` +M!;,%N`,@`T```````RH"@@-"`S0`````!;,%LP6S!;,`````!;,%1`6S!;,` +M`````[(%LP2N`T0`````!(T$0P0S!;,`````!,,%LP0W!-``````!$,$^@-1 +M`W$`````!;,%LP6S!;,`````!;,%LP6S!;,`````!;,%LP8R!;H`````!;,% +MLP`'!;,`````!;,%LP6S!;,`````!;,%LP6S!;,``````^X#XP/^`_P````` +M!`0$``0"!`8`````!!($#@0:!!8`````!"($'@0J!"8`````!;,%LP0N!;,` +G````!;,%LP6S!;,`````!;,%LP6S!;,```````(&:`:&``8````` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV670_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV670_pfp.bin.uu new file mode 100644 index 00000000000..cb6a852738e --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV670_pfp.bin.uu @@ -0,0 +1,55 @@ +begin 644 RV670_pfp.bin +M`,H$``"@````?H*+`'P#BP"``;@`?`.+`-1`'@#N`!X`R@0``*````!^@HL` +MQ!@X`,HD``#**```E8&H`,0<.@##P```R@@``,H,``!\=$L`P@`%`)G```#$ +M'#H`?'1,`,#_\``$+`0`,)`"`'TE```U%`(`?34+`"54`P!\U8``)9P#`)7` +M!`#5`!L`?MW!`'V=@`#6@!L`U8`;`-1`'@#50!X`UD`>`-:`'@#4@!X`U,`> +M`)>#TP#5P!X`R@@``(``&@#*#```Y`$>`-0`'@"```P`Q!@X`.0!/@#4`!X` +M@``,`,08.`#40!X`[@`>`,H$``"@````?H*+`.0!'@#4`!X`U$`>`.X`'@#* +M!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^@HL`RA@``-1` +M'@#5@!X`@`!3`-0`=0#40!X`R@@``,H,``#*$```U(`9`-3`&`#5`!<`U(`> +M`-3`'@#5`!X`X@`>`,H$``"@````?H*+`,H(``#4@&``U$`>`(````#4@!X` +MR@@``-2`80#40!X`@````-2`'@#*"```R@P``-1`'@#4@!8`U,`6`-2`'@"` +M`;@`U,`>`,8(0P#*#```RA```)2`!`#*%```Y"#S`-0@$P#58&4`U.`<`-4@ +M'`#58!P`@`````8@`0#&"$,`R@P``,H0``"4@_<`RA0``.0@\P"``'D`U"`3 +M`,8(0P#*#```RA```)B#[P#*%```U`!D`(``C0``````Q!0R`,880P#$""\` +ME4`%`,0,,`#40!X`@````.X`'@"5@_4`Q!`Q`-1`,P#5(&4`U*`<`-3@'`#5 +M(!P`Y`%>`-0`'@"`````!B`!`,H8```*(`$`U@!V`,0(-@"8@`<`QA!%`)4! +M$`#4`!\`U&!B`(````#4(&(`S#@U`,P4,P"$`;L`U`!R`-5`'@"`````[@`> +M`.(`&@"$`;L`X@`:`,P02P#,!$<`+)0!`'T)BP"80`4`?17+`-0`&@"``;@` +MU`!M`#1$`0#,#$@`F$`Z`,PL2@"5@`0`S`1)`(`!N`#4`!H`U,`:`"@H`0"$ +M`/``S!`#`)B`&P`$.`P`A`#P`,P0`P"8@!<`!#@(`(0`\`#,$`,`F(`3``0X +M!`"$`/``S!`#`)B`%`#,$$P`FH`)`,P430"80-P`U`!M`,P82`#5`!H`U4`: +M`(``R0#5@!H`EL#5`-0`;0"``;@`U`!N`)K``P#4`&T`U`!N`(````#L`'\` +MFL#,`-0`;0"``;@`U`!N`,P4`P#,&`,`S!P#`'V1`P!]U8,`?1D,`#7,'P`U +M`.0!'@#4`!X`R@@``,H, +M``#*$```U$`>`,H4``#4@!X`U,`>`-4`'@#50!X`U4`T`(````#N`!X`*`0$ +M`.(`&@#B`!H`U$`:`,HX``#,"`,`S`P#`,P,`P#,#`,`F(*]``````"$`;L` +MUZ!O`(````#N`!\`R@0``,+_``#,"#0`P3__`'QTRP!\R0L`?0$/`)D"L`!\ +M@;P"`````[@`?`,H(```H&0``?8F+`)6`%``H%`0`R@P``,H0 +M``#*'```RB0``.(`'P#4P!H`U0`:`-5`&@#,&`,`S"P#`,PL`P#,+`,`?:6+ +M`'V<1P"80I<``````(`!80#4P!H`U$`>`-2`'@"`````[@`>`.0!'@#4`!X` +MU$`>`.X`'@#*!```H````'Z"BP#D`3X`U``>`-1`'@#N`!X`R@0``*````!^ +M@HL`R@@``"2,!@`,S`8`F,`&`,P03@"9``0`U`!S`.0!'@#4`!X`U$`>`-2` +M'@"`````[@`>`,H(``#*#```--`8`"40`0"5`"$`P7__`,H0``#*%```RA@` +M`-2`'0#4P!T`?;&+`,%"`@#"P`$`U8`=`#3<#@!]74P`?W-,`-=`'@#5`!X` +MU4`>`,%"``#"P```"9P!`#'<$`!_7TP`?W-,``0H`@!]@X``U:AO`-6`9@#7 +M0!X`[`!>`,@D`@#()`(`@`&X`-8`=@#40!X`U(`>`-3`'@"`````[@`>`(`` +M``#N`!\`U``?`(````#4`!\`U``?`(@```#4`!\````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````0%Q``(!>``#`(\`!`!_``4``P`& +M`#\`!P`R``@!+``)`$8`"@`V`!`!M@`7`*(`(@$Z`",!20`@`+0`)`$E`"<` +M30`H`&H`*@!@`"L`4@`O`&4`,@"'`#0!?P`\`58`/P!R`$$!C`!$`2X`50%S +M`%8!>@!@``L`80`T`&(`.`!C`#@`9``X`&4`.`!F`#@`9P`X`&@`.@!I`$$` +M:@!(`&L`2`!L`$@`;0!(`&X`2`!O`$@````&````!@````8````&````!@`` +M``8````&````!@````8````&````!@````8````&````!@````8````&```` +)!@````8````& +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV710_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV710_me.bin.uu new file mode 100644 index 00000000000..ee8a241cba6 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV710_me.bin.uu @@ -0,0 +1,124 @@ +begin 644 RV710_me.bin +MS``#Z@0(``/,@`!#?$"``*````#,@`!B@````]!``'^````#S$``07Q`P`#` +M%@`$,-`__WT5``S,$0``*-@`'C&8``$HW``?R"``!)7```9\0D``S```8GY6 +M@`S,*0``R"0`!'XF``N5@``&?$+``,P``&)^UP`,S#$``,@L``1^+@`,S``` +M8C$0/_^````#SA$``'Q`P`"````#S$``0(````/,02)7?$&``,Q``$7,0`!( +MS$$B7,Q!H?Q\0(``H````,R``&+,0`!%S$``2'Q`P`#,02)````#S\&BU(````/,0`!"?$#``'Q!```I%``= +M,50``9E```PQ&!``R!P`$97```#('``1S,$A`,T!(0',P2$"S0$A`P08``2` +M``-^S8&BI,`J``25@``(-J@AH\PI``#(*``$R!P`$0WD`$"60/__R!P`$``$I)``2P"(``I9```7` +M)@`$P"?_^WTE``O`)@``?=*`"WX2P`M])0`,?$%``'Q!@`#,P2%IFH``"LT! +M(6K-02%KEL#^@\V!(6S(,``8EP```,@P`!B````#S```&(0``X',``!_R!0` +M$\@8`!3-02%KEL#^=\V!(6R```&#R#``&,@,``B8P```R`P`"'Q!``"5```" +M`````'Q!0`#((``)S$``0\X!H?3,0`!$P`Z``'Q"0`!\0H``*JP`'Y;`_F3` +M-?``SD`#XC)X``,F?``(?_?`"W_[P`PJ>``8S\`#X\^``^0FL``"?S\``,\` +M`^6```,??(#``'Q`P``HT``(,1``#Y4```\E*``!!J@!M)Z`````````@``! +MU<`2"`"```'CR!0`#X```>K(%``0@``!\#2@`()J``",-)``/#2@`$'YJ@`R:@``F#2``!`TD`!0- +M*``H?F)`#'ZF@`R:@``JR!0`$8````/,P:*DP!((`'Q!0`!]#,`,P!(`""E8 +M``,I7``,?$(``'W1P`LF(``4?AY`#'Y.@`S.@:*D@````\V!H?[(%``/!!`A +M#I5```#(%``/T%$``(````/,P:*DR!0`$`00(0B50```R!0`$-!1``"````# +MS,&BI,S!HJ0$$``!S0``&80``X',``!_R!``&9D```#($``9@```!'Q`@``$ +M$"$`E4```,@4`!'040``@``#?LS!HJ1\0,``S$``#93`_@',0``.?$$``)4` +M``4(S``!R!0`!9E``!0`````F,#_^WQ!``"````$?0"``,@4``5\0,``F4`` +M#,@8``Q\00``E8#]\,@@``[('``-9B``('X>`"PE)``"?F)`((````/,Y@`` +M?$$``,P``&S,``!MR!@`'\@<`!YEF``@?=G`+'S4P`S,W@``1=P`!,@H`!>6 +M@``/P`X``2AH``@JK``6,J@`_PZP`$E_+P`+EP``!@````#(%``%?$#``(`` +M`B-\00``@``")M!``'^$``([S```0````$?$"``,@8`^J9@/UY?$#``)3` +M``/($``6F0``!,S``&B````$?$"``(0``CO`%(``S```0``\#>@`/`WH`#P-Z``\# +M>@`/`WH`#P-Z``\#>@`/`WH`#P-Z``\#>@`/`WH`#P-Z``\#>@`/`WH`#P-Z +H``\#>@`/`WH`#P-Z``\#>@`/`WH`#P-Z``\#>@`/`WH`#P-Z``\#>@`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV710_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV710_pfp.bin.uu new file mode 100644 index 00000000000..4c9b3f87a07 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV710_pfp.bin.uu @@ -0,0 +1,79 @@ +begin 644 RV710_pfp.bin +M?$"``*````!^@H`+@````-P#``#,@`!`T$``0'Q`@`"@````?H*`"\@8``XQ +MF``!?$)``)6``CI\0H``R!P`',`WP`!\0,``?$$``'RT@`O`-@`#F<```,@< +M`!Q\M(`,)-0``GUE0`#-0`!#SH``0\T``$/,@`!`SD``0,Z``$#,P`!`W#H` +M`)>`_][-``!`?$#``(```!A\00``U``#0-0`#\#4``^BR!@`#H````PQF``" +MU``#P-0`#\#4``^BR!@`#BB,``@PS``/-!```7T-``B````,?9&`"\R``$#0 +M0`!`?$"``*````!^@H`+U``#0-0`#\#4``^BS(``0-!``$!\0(``H````'Z" +M@`O4``/`U``/P-0`#Z+,@`!`T$``0'Q`@`"@````?H*`"\Q``_F```))S$`# +M^,`W__]\04``ST&BGL@@`_C('`/Y9B``(,@8`_M]X<`L?5C`"'S0`$'``!ST``0,W``$#/``/Z?`,``,H,`!!\00``E,``!'Q!0`#4(`+$ +MS>``1)L```M\08``S```2\V@`$G-(`!!S6``00`$'``!ST``0,W``$#/``/Z?`,``(```+5\ +M04``S```2(```.X`````R"``%\@<`",.)``"F<``%7Q!@``*(``!S@``5M0` +M!$#,``!`P#;``,H4`!.60``'-W1Y`,]``$#,``!`R#`#^H```0//```BS``` +M(I5``4;,``!_S*``1H````#,(`!&@``"2``#,@`!`S,``0-!``$#(#``E +ME,#]Y,@0``C-``!`U``/P(````#4``^BU``#0-0`#\#4``^BS(``0-!``$!\ +M0(``H````'Z"@`O4``/`U``/P-0`#Z+,@`!`T$``0'Q`@`"@````?H*`"WQ` +MP``PT````!ID```?(%``5F4``!",M```````PP$``P````4``` R*/0\4)5RV-&X_9[I?._+<26U!2 +M5'^T?M%/IAVT`HN*X&0&```!3BP=ZCHAXU=5P(F7P;.%:,D*3%\Y>/$#]=+E +M.^)3?5T,`6])!P```5R3S4UW)*C3;]-\7M#KZ;Y2LX0NH'ZYV-K\XY>':B`U +M+)//L@`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````,5)$-5)(.5),/5)`#0``-S_`&'0 +M_P!A$``!82\`!`"Y#`1@``````````````````````````````````````#% +M"1#5"2#E"3#U"0`U```````````````````````````````````````````` +M````````````````````````R4D`T0D0V4D@Z4DP^4E`@$E0D$E@H$EPL$D` +M-````````````````````````````````````````````````,D)$-D)(.D) +M<-$),/D)0(<)4)<)8*<)<+<)`#4````````````````````````````````` +M``````````````#-20#1"1#=22#M23#]24!`25!026!@27!P28"`29"02:"@ +M2;"P20`T````````````````````````````````S0D0W0D@[0FPT0DP_0E` +M2PE06PE@:PEP>PF`BPF0FPF@JPFPNPD`-0`````````````````````````` +M````#```Y!,``!,``1,``A,``Q,`!!,`!1,0(```21,`2!,0(```:!,`@!,` +M@1,`D!,`D1,`H!,`H1,P(```L1,`LA,`LQ,`PA,`PQ,`T1,`TA,`TQ,`Z!,` +MZA,`\!,`\1,`\A,,\B#F$Q`@`$P"#`-V@@[2

G!^=$@``,P`0,IX3GQ(`(#,`,#(F$0,F$1(.8#,+$#(F$2,F$3 +M;`,P(A`K(B#F$Q+1`1+!@!`@`!`1(!4%`!+!@#(A$2(A$#`#$R`"$SCQ*.$P +M`1,@`!,B(1(R(1,@YA,PL1,0(`#XT>C!V+'(H;B1J(&8<8AA>%%H05@Q2"$X +M$2@!$M$!$L&``#`````V`0$@80!`X@-0Y`,A,`-01!`@1!!61``@;P`=\##T +M0!SR,#+``!-`03$#0$.PG&,,$@`BH2#C$R(D`&(D`19"_-`"`(;O_P`@\`,@ +M\!,H!&@4%@+[T`(`ANK_`#8A`##J`RHS,/`3'?`````V(0#VP@E1,0-0(K`Y +M`DD2'?`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````"*L#L9E_P`` +M````````````````````````````````(JP8QEW_```````````````````` +M```````````````0-````````````````````````````````````````!+! +M@"D!(.@#9D("1E#_*`$2T0$2P8`BK!=&2/\`````(JP6QD7_```V(0!`;P`P +MY`,@,R`PY!-`YA,0(``=\``V(0!`;P`PY`,@,R`@,S`PY!-`YA,0(``=\``` +M`````"*L%<8U_P``-B$`(.H#'?`V(0`@\!,`(``=\``V(0`@\`,=\``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````PP%@````````````````T0$``!$!``#1`0``T0$``-$!```1`0``=P$` +M`-$!``#1`0``=P$``-$!``#1`0``T0$``!$"``#_`0``T0$``-$!``#1`0`` +MT0$``-$!``#=`0``````````````````7````"\````_`@``!P(``-D!``!5 +M`0``TP````````` <#10<(!0<("4<("4J"@X4&`X4&!L4&!L>&!L>(@`! +M!`@%`@,&"0P-"@<+#@\``0@0"0(#"A$8(!D2"P0%#!,:(2@P*2(;%`T&!PX5 +M'",J,3@Y,BLD'18/%QXE+#,Z.S0M)A\G+C4\/38O-SX_-`D``#0)``#4"0`` +MQ`D``,0)``#5!@``U08``-4&``#5!@``U08``-4&``#$"0``M`D``*0)``#5 +M!@``U08``-4&``#5!@``U08``-4&``#5!@``I`D``)0)``"$"0``U08``-4& +M``#5!@``U08``-4&``#5!@``U08``'0)``!T"0``9`D``-4&``#5!@``U08` +M`-4&``#5!@``U08``-4&``!4"0``1`D```````#$````JP(``(\"``!S`@`` +M5P(``#L"```P`@``%`(``/@!``#<`0``P`$``*0!``"(`0``;`$``%`!```T +M`0``&`$``/P```#@```````````!`@,$!08'"`D*"PP-#@\0$1(3%!46%Q@9 +M&AL<'1T>'R`@(2(B(R,D)"4E)28F)B)!8H +M&28F*2D`````$````"`````/````'P```"\```````````````(!`P,$!P4/ +M"!\"`@,&!`X%'@<^````````````````'T`?01]"'T,?6Q]<'UT?7@!`@`%! +M@0)"@@-#@P1$A`5%A09&A@='APA(B`E)B0I*B@M+BPQ,C`U-C0Y.C@]/CQ!0 +MD!%1D1)2DA-3DQ14E!55E196EA=7EQA8F!E9F1I:FAM;FQQGA]? +MGR!@H"%AH2)BHB-CHR1DI"5EI29FIB=GIRAHJ"EIJ2IJJ@`````````````` +M``````("`@```@```0$!`P,!`P.`5:I`P#-FF(&"@X````-SQ_)\4 +M)_V?T?\'`!##`6"T"````/+\G\0?`&``]OR?````"/__'P````"`Z!\`8(0? +M`&"($P````!@```(``````("____/P````(`[OR?@):8```N_)\``#`#`/[[ +MGX<3``#___\!````P/__7P#D#0``````8O____T```(``!\```!```#_?_#_ +M```*`/^___\```B`__#__P```X````*````&@````8`]``!`P)X!8```!(`` +M``V````,@```!8``&```_^?__P````$-``!``/K\GP#^_)\@3@``````X``` +M`/````"@.&L``!1K``!L#```@`P``+`F`&``*0!@W!$``````$#___^_U&@` +M`-0/``#___\``#__````8`8`J0!@@*D#`-P/``#L:````/\`__@=``#P_P`` +M0`@``"`__P`"(```-\U"_6:X](R+\4\'9&H``+`)```0"`!@6"\`8.AH```P +M"@`````D`"U=``"H#```U`P``%@1```4"0``P`H``(`*``#___]_W!,``)1: +M``#4"```\&@``$@*``#@.@``.#L``$@Y``#8&```,!D``*`*``!P"`!@1$H` +M8%`*``#`"```5`D``)0)``#L#P``____@```\`^L"0``%P``"`@-``!@#0`` +M:!```,0X``"T#P``#R<```((``!H:@``````!,P)``#8#P``/&@``,`/```T +M#```M%L``!1;``"X#P``_&H````)`&"4:0!@,0P```!2`@```#@$`."&`@`` +MS````,````!X``!X:0``=B\``-@;``#L#0``1@4`>E\``'Q?```Z8```/&`` +M`)@*``#D$0``\`\``/QH``!,"@``T`\``(`8```L70``K%L``+@(``!)"@`` +MD%P``!Q=``#86@``W%H``&P*``!L:@``+`H``!BA`&`PH0!@E&@``/__`_C_ +M`?S_``#\!P#^`P#@#P``B#H``,1H````/_\!`P@``+`)`&!PJ0!@&-H`8(#- +M`&!`]0!@X``!8-S#`&"TM@!@2,X`8`S&`&!\W@!@W.@`8)0!`6!$^0!@I+<` +M8."M`&"TZ0!@K.``8``*`&``@``````0^```0/@`"P!@````^```,/@(@``` +M``#@`0``(/@3``$`&P``@!L``$`;```0&P``D!L``%`;```@&P``H!L``&`; +M```P&P``L!L``'`;``#P&P``P!L``-`;``#@&0``$!D``"`9```P&@``$!H` +M`"`:```P'```P!P``(`<``!`'```(!P``!!`"@!@____!^!H``"D"```""H! +M8&@G`6`!/_\``0#P#T$`\`]$_A\`5$`_R#R +M;2_2+2_2;J+E#/^BH`BQ.0/"P0@E#/\,:K$Z`\T!90O_HJ&`I2?_43L#03P# +M83T#\3,#TM$)D3X#DF_$@B_`PM$(#"NPB""";##B+##B;\"B(B_"+#');;"J +M(*)B+P89``#"+3#A/P/`P4'@O!#GC`(&2@#BR_\63B#RR_P6#T."R_L6J$:\ +M-\(B+[+1"0Q-T,P@PF(OF`<,"JF;G&GBR?\6SAORR?X6[R*"R?T62""BR?P6 +MJD$,&[D'LF))#`WBT0EY#MF>HJ'`I1[_\M$(D4`#,3,##`KBT0G8(7+1"7@' +MN#'9KJDAJ3&"(\2R;@BBH8"0B""";S#R+S#R8\3E&?^"T0F(J!;(!K+1"=+1 +M".(B+\%!`PQ/\.X@XF(OPBQ#PFTPDBTP#`JIF_=Y`D;,_[(M,+"Q0;;[&\*A +M`+>\`H8L`!9'3]@'TLW_%KU,#![B8DD&W/_V*P*&+@"V.P+&.0`61V#X!PO_ +M%B]:#!B"8DF&U/\```"2T0F8B18I$:AAPM$)#`NYG!NJJ6&,9]@'TLW^%@WO +M#![B8BX&RO_X41O_^5&,9X@'@LC]%O@ZDM$)F'D6N7"RT0C2T0G8?0P*PB(] +MR0VB:S:Q0@-V@!/B(^>2T0A7[@[R*38;CX)I-O<[`X;X_P"Q0P,,&J)K3:)B +M28:T_P``PJ(!QSLUTJ(!M[T"1J0`%O=JZ`<+[A9^:`P?\F))QJO_%@M?MBL" +MAIG_%N=4B`<+B!984`P9DF))!J7_HMO^5NKD%J=TN`<+NQ9;<`P`<,"8(G,ZT'DF(NX`@`PM$)J5R@ +MZ@.I/**@067G_M@WTLWZ5GT7=H`:XM$(@B/G@FX]\BX]\/`4\FX]XBX]XL[] +M%LX0AO?_````HBPW&[JR;#>G.0O2(^?"T0B10@-7;>CQ0P,,'N)O3>)B248* +M_P```(*B`H"+P%9HOA;'8I@'"YD6.6`,&J)B208%_\%!`_%%`^(L1.)M,,(L +M1>(M,`P;^N[";H"R8DE&_?X`#!^100,,"++3!*(I1*D+DBE%F1*"8_^)!_)B +M20;S_@#!00/"+$3";3"8<1992;(M,)"[P+"R0<`@`-+1"/+1"?A_#`SB(CWP +M^Z#I#\)M-48#`````)(K-1NIHFLUES@+PB/GLM$(@4(#5VSH\4,##![2T0G8 +M?>)O3>)B28AQ#`_BT0F`WX/9?D;:_@"100.B*42B9QZ2*4629QV"(CV"9Q\& +MQ/ZR(ZR2(B"PP`2PT`1631_`(``,*(")(()B(.(B('S?\.X0XF(@=H`7DM$( +MTB/GTFD^HBD^H*`4HFD^DBD^)CD$1OC_``#`(`",'+)CK(+1">+1"/(CJO)N +M/^(N/WD(#&_P[B#B8ZK`(`"BIU"Q.`/")Q*E;0!]"A::(#*@`)@'9QD)&S,, +M&B6X`%>3\*%&`S>Z.G+1"7@'#!L,/,D'LF(N!JG^`)CWD(($5KBRH4$##$S` +MR2#)][(J1+)G%*(J1:)G$\:2_@P=TF))QJ#^#`^2T0F"T0F(6)A)F1>))_DW +MZ$R(ARYIZ(C\JFWDB/SF<>"(_&)U_(C]?)G#N(C +M]N)G#](C]-)G$,(CZ\)G$;(C[+)G$J(CI*)G$Y(CHY)G%((B5()G%?(B5?)G +M%N(B5N)G%](B5])G&,(CZL)G&;(CHK)G&J(C]Z)G&\`@`'+1"7@'#!@,.9D' +M@F(NAFO^F/>0@P162*6A00,,C,#)(,GWLBI$LF<6HBI%HF<5AE7^F/>0T016 +M':_A00,,*(")((GW\BY$\FP4<#N7&P +MLT'`NQ"R8A;")Q[12`,,`\#`)-#,H-+1"+1">C.Z`YW'@LRPP&B +MH`&ED`!7D^GQ1@,WOW."T0F("(QXHM$)J`H,.9D*#!NR8DG&"_Z8]Y#&!%;\ +MEM%!`TP/\/D@^??B+43B9QK2+4729QF&\_T,&()B288!_@``HJ=8X4$#L4@# +MPM$(XBY$XFPPTBPPV7'"+#!E/@#RT0FI?\`@`,8R_C$S`\`@`$9S_H+1"8C( +M,3,#B!ART0EX!Q9H"X+1"8C(B!@+B!9H')+1"9C)F!F2R?Z,&8;I_0P+BY&B +MH`IVJA7"T0G(S-AYR"S0S,`6S"H;N]*@W-J9#![B8DF&W_V8]Y#U!%8?CX%! +M`RP+L+D@N?>B*$2B9QB"*$6"9Q=&Q_T`F/>0Q`16?([100,<#N#I(.GWTBU$ +MTF<21L#]``P?\F))!L[]#!B"8DD&S/VBIUB2+3#!1P.Q2`.0DT'`F1"28A;" +M+3`E,0"RT0FI>PP+1M/^``P)B[$,K.+1"-(CJM)N-':L"OA[@J#P)D0\)D@ +MDF.JR*C":Q*8>)G[B(C9J_G+Z9O2:RB":Q`E?Q"&Y_\`F/>0IP16.I^Q00/2 +MH(#0V2#9]\(K1,)G'+(K1;)G&X9M_0P>XF))AGO]#`R+L?*@"G:O%8+1"8C( +MF'N(*)>8`@8I`!O,DJ#6:;#Y+1"0P(#!JB8DF)"49C_0#2T0@,.,*@ +MW,#+@HNARJJ):@P,PFH5>$&2T0F!2P-P>X*IV8IWRT0FXV\8#`&:<`L;6 +M_]*@W-#<@HNQVKN8:ZPI)DD@)CD=XM$)#!_R8DEY#D9"_0"2T0D,"`P:HF)) +MB0E&/OT`<+1";)B2;+)&*(CJJ)H,H(H,KD,#&J@B"""8ZJ&*_T``#9A`$P*96G^ +MD3,#H4`#P"``LBG%N0&(`0P<\MD$EW@'HFG&R0(=\`"H`8@/T4P#H(@@B0'H +M`>D/TFG&'?`````V00"BH(!E9?Z100/`(``,&JD"@BE#@FE#P"``HJ"`96+^ +M'?`V00"BH0`E8_[`(`"1,P,,&H%-`ZD2@FG&P"``HJ$`)6#^'?`V00!M`B@# +MC-12K\`BPC]0(A!J4ED#'?!J@HD#'?```#9!``P'@3P#D4$#84<#0%-!FI)@ +M)1`B:4!V@`JB*4"G$@D;=X<7!(;[_P``L4D#=SL'0"`D,"*@'?`,`AWP```V +M80#A,P.!00/!3@/2+NH,#Y(B%,#=$-D!R`'";NK!3P/R:$?2+N;9$8@1\5`# +MP(@@B1'8$<%1`_#=$-D1B!&M`L"(((D1^!'R;N:]`PPMT)D@P34#P"``@5(# +M^!&`_Q#Y$=@1TF[F^`$,&-$V`X#_(/)NZM)NVI)L2H(B$Y%3`X"`=)"((()N +MII(NY=(B(?*O#_"9$-#<-<#=$="9())NY8(B()%5`_%4`X"`=)"((()NII(N +MY=(B(?"9$-#<-8#=$="9())NY8(B()$X`X"`=)"((()NIO(B((%6`_#P=(#_ +M(/)NIM(B(/%7`]#0=/#=(-)NII(B%=%8`Y"0=-"9())NIH(C'Y(B%A;H!M(C +M()K=TFQ/@B,A\B(6BO_R;%K2(R*"(A;:B()L6_(C(](B%OK=TFQDBL?\BL=,(@1@)D1X/\1D/\@@/\@@J02@/\@@BHT\F[P +MTBL#=(-D1 +MN!&R;.8,']$U`\`@`*%2`Y@1H)D0F1&($8)LYN(A`**D$O#N(.)LZK(C'N(C +M'Y(C'3"[$8#N$>"9$>"9(+"9(*"9())L\((B%Y%3`X"`=)"((()LIO(B((%; +M`_#P=(#_(/)LIN(B(/%<`^#@=/#N(.)LIK(B%>%=`["P=."[(+)LIJ(B(+%7 +M`Z"@=+"J(*)LII(B&Z%>`Y"0=*"9())LIH(B%9%8`X"`=)"((()LII(LK+(M +M()"@!`=I".*O_N#I$.)LK,`@`.%?`X%@`^#K(.)M(/(M((#_$/)M(#WP=H`0 +MLBSGN2&((8"`%(DA^"$F/P*&^?_`(`",&I)LK((B-)%B`TP*X6$#XFS:LB(8 +MLFU*HFU,O0.M`I)M3DD5X`@`'?```#9!`+T"@6,#D60#%I8'V`86S08,!JS] +M8J``PJ``=ITGXBB#HBA#0BC#7W'@(&]_\,+``\IK`0I@P)?/JB:($@ +M*8,=\-(#`"8]"&#J(.)H@L;E__%H`_#Z(/)H@L;B_S9!`#%D`X$U`T%C`WSR +M(FB!(F1!(F2!(F3!*1,B8T$=\````#9!`%#J`S*AD#`B@CWP=H`(0.H#4$3` +M)[0"AOO_'?``-D$`0J'T=J0$6`(W%?\=\#9!`"P#=J,=@G($@G)$@G*$@G+$ +M@M(!@G@$@GA$@GB$@GC$(M("'?`V00`A:0,=\#9A`$T"O0$,#`P-B.*A:@.) +M`24_"#T*L6H#9<@9*0/"TP+R(B'R;*_H`>)LL-(LL+BR4M,*HM,-VKNR;+&B +M9::2):8,!@R+8DD&HB6F)<49@6L#+$N*@X)EFJ(EFB7$&:T#I3X#D6X#H6T# +M#"N!;`/RTUT,$HJ#(DA38D@P#`+B)"'2):;")9KB;RIB70*R3".B9#.29#0= +M\````#9A``P,#`[1;P.RI0PXX@P*J0&PLX#0TX`EV/^1,P.A-0/19`/Q8P-\ +M_(%G`X)O@N(O@L)O@<)OPX(@0@FH@=H`0@BGGB1'H$>#@%.D1V!$F/0(& +M^O_`(`",'+)IK.%P`\(B%)%9`[+3:D#,(,)J2K(K,;)J3))J3H(OFHD!V`&Q +M<0/@W2#2;YK"+YJH`;"J$*)OFI(OFJ7A_QWP`#:!`#*D<%CB#`=R80`Z-8(# +MDR9H`G)#DX%T`T%C`_%S`\%R`V(#D_KUXB]_?/W*Q1ONXF]_:5JA!#!EH +MXI)J@PP:)>W]H78#:2&ES?UA=0.M`F7H_PP*R"%B9(*R)(*Q=P,ES?UH(0P: +M)>G]K0;8,<*D0,K&TDS#>=#Y(E[((3-9"0]`N(EY@!#`]\]PP*#`S1;P.R +MI0SP[Q'B8C:ZM0P.T-6`);K_D3,#\34#H60#L6<#LF2"@B2"1IR +M:D%R9$%R;X&R*:SB+R"PP`0':P=\[=#;$-)IK`PMP"``T"X@(F\@(B\@?-B` +M(A`B;R!V@!#R*>?Y$>@1X.`4Z1&($28X`@;Z_\`@`(PX(F?NE!0M4*%MA9@B,X%OA:HB,X"ZH6.EVR(SBR +MR_X6ZUO")"V23#W2)"W"`_.R)"W)C:(#]J)+/)(D+8(#]'(D+8F9\@/UTB0M +M^:?B(SK")"WRKW^B)"W([.#C!)#N$?#,$.#,(.*CZ,GMLB,ZDB0MPJW_@B0M +MF.FPL@1PNQ'`F1"PF2"9ZG(C.O(D+>KCDJO_^.]P<01@=Q&0_Q!P_R!R)"WY +MZ/(N,L(D+?)G?K(>:J(D+9(>>H(D+7(>BO(D+>(>FM(D+;)L.(N +MN(N="NJ2]WGN0+&]_^B)"VB*G4,":Q*P*.`PJ``=H`9&YGR)"WB&I?2)"W* +M_^)O?-(M=2NJ2\S7N0+&]_^")"[R`_SB)"[YR-(#_L(D+MG^H@/_@B0NHFP0 +M\@/X#`GB)"X`_R/Y"/(C.](D+GS8PB0NTBT3\/@$\/\1@-T0\-T@TFX3HB,[ +MF3&2)"Z@I!2B;!&B(SN")"YL_.(D+H(H$Z"G!,"J$<"($*"((()I$X(C.](D +M+I*OW\(D+M(M$X"&!+"($9#=$(#=(-)N$](C.Y(D+@P/HB0NDBD3T-,$D-T1 +M<)D0G/"H+2"*!.@H01PJA&PB!`ZOZ"((()I$\J[\)\@@J`(V#%RQQ#RSQ!V +MJ!N")"ZB"U`;R2N[FHBB2&"")"ZB"T\KF)7ZMAST-1!TE?LHA?LPB,Z#"O`P@3`N\!E +M7!FB5^OR%^SB%^KP[H+B5^_2%^K`W1'25_#"%^R80:*A`,#,$<)7\;(7\+)I +M>J)I>8(7\8"(D("!(8)I>X(D+?(7ZN(D+0O_\E@6TA?KPB2FLB,<"]W27A>R +M7`*B`_"B9T^R(SJ2I"B:E;"P!+))V:(G3R8:#XA9@LC^%G@@J%FBROT62A[" +M%_#`P4'"5_*R%_&PL4&R5_/R)"[R+Q,,'@P-\/$$\-Z#TDG8PB,[P,`$PDG6 +ML@/Z`+LCLF='H@/[`*HCHF=(@B.*@F>]!GAA/#G& +M`0"2(SEX89"0=+(D+9)+/J(F?ASL%DH+@B0MDB,Z\B0MH5(#XB0M^.^0E@0@ +MF1&@_Q"0_R#YZ/(C.M(D+8*N_](M#O#U!(#_$8#=$/#=(-)N#H(F?@P),6,# +M%@@)HB0MH@H]HLJ^%GH6LB0ML@L^M[P,P@?9C&S80=(MB19M%0P2\7X#LM,$ +MHJ#^P7T#T7P#@60#X7L#(D?FDFA3XFA(#.G28X#1;P/"8\"I"PP,#`JRI0S: +MU9)H0+JU\F@XXB:#XF/"XJ``I53_'?```/(D+?(//E:_]Y(76X*F5)_VA1`/E6_V1?P.28X*" +M(X+`(``,"M&``RP,=JPF`#VF@!"FH)!$B0&(`0`90+@!D)S``(BA``E`L)"1 +M@(D@B0&(`:JHJ5&M`N5R_RA1HJ``L7<#PB$"I5?]#!KE<_VA@0,,"1SLIQ(. +ML8(#MQ((T8,#T-+`5EWN^$$,'N)OB<:V_X(D+9)(/4:=_K(97+)97J(97:)9 +M7T:'_](D+4PLPDT]QI;^`/(97/#Q0?)97N(97>)97\9__P``DB0M@J!D@DD] +MAH[^LB0M3-JB2SW&B_X`#`*&JO\,(D:I_P``TB0MPDT^QIK_````-F$`?/U" +MT@$,"#*D1%&$`SHR@F3<6E+292."`[^<&((#OX+(_19(#I(#OR9I`QPB'?`, +M-I%C`W&%`PP<#!AZ(3 +M2!O_]YY9DB2L@A-+&YF7F$ZB)-P6"@B]`L)#OMGCHB=#I5,`HD._PB>[PF=# +MLB4B(+N@LML$N%N`/A8P/Q +M9`,+F:(N@X@_\B]#XBY#H(@@@/\@\.X@%HX5%HD5@@/(9BC7D@/(%LD5#*8, +M.J)#OPP+LD/!'([G%GWR`\<]\!;_"H(#R(R8#*8,.9)#OT:P_P"Q8P/BH`#B +M0\>R*X&BH`BPNP2P:I-F)@)&(P#R`[_RS_L6S^F"`[\+B!9(Z:(#OY%C`PP8 +MHLK]5FKGQJ#_'"(=\,)#O@PVQIW_(*(@9:4"(*(@I0\`PJ`!?/UM"AR+#`[B +M0\&WFH$M!AWP`*T"9:,"#!Q\_0P/\F4CAMG_`)(#J(*@()>X`H8D`""B(.4+ +M`*!J(`P??Z(DK)(32QNJIYET#`NR9-RB)T.]`N4T`*)#O_(GN_)G0^(E +M(B#NH.+>!.A>#!Q\_8S^DB4B#`BBI$0@F:"@F8"":0RB`[^BROH6^MJR)"$; +MN[)D(8:__PQR'?``5LGJ#"S"0\BE<`<,''S]1J?_`""B(&4!`*!J(,*@`7S] +M!J;_'((=\````#9A`*T"I9L"##.,JB+*^B"C@RT*'?```$&(`TI"@B1^?/F, +M^*T"I2(#G`J"ROJ`HX,M"AWPDF1]!OK_``"M`B7M!B"B(&6B![*D++JRTBL5 +M/?`;W=)K%<(+WY$S`U*A*)S#@%.D!V`%F +M/>X=\((+X%:H_88(``P-#![B2];22]_22^#""\@6_`A:\O(/;19_",(K%,+, +M_LEKP8D#T@O(RL(6S0<,/=)+X>(LCH(,??(LCHE^XBLH@BR.Z3_R"\GR2"'B +M"\F,?H(LCO(+RO)((M(LCH(K(?(LCHE-X@O,XD\@T@O,C(WR+(Y:XN(NX^EO +M\BPA\B\)O#^"+"&"*`DF&&LF*DO2*>?9$<@1P,`4R1&X$68[[BT*'?#"*Q0+ +MS$;=_](LF-#0=,;>_P```/(D@8(LCB#_H%K_\B_7^5CB)('R+(X@[J!:[N(N +MK^D/9BJSL60#6H+2***"**/!B@.`W1'0B"#`B""":TR&Y?_2)('B+(X@W;!: +MW=(ML=D>LB2!TBR.(+NP6KNR*[*Y+0;<_S9!``P-D8L#%H0`)A0I)B0Z)C1' +MP,,1RL*:S)(,?^8I`M89`28I8B8Y"R9)/V99!>(,@!;>!!WP#!_`PQ'*PIK, +M\DR`D@Q_QO3_``#`PQ'*PIK,TDR`D@Q_1O#_#$[`PQ'*PIK,XDQ_#$D&[/_B +M#(!6+ORAC`/23'^]`ZJBI04`'?```-),?QWP`+*@`Z&-`[),?S"S(*"B@.4# +M`!WP```V00!($E("*C("*QM$21)7$QD,!RPH*F5B!@@;55!0=(>U#5)"*BT& +M'?```"*@_QWPKC +MXMX*TFXQPD(UF/(+^1:/-8+)_A8H-7JC#`D,7,D!DDJ!F.*0T016/0R0Z`06 +MW@N0]`16?PO"H-2B);N2);N");O`JH+`F8+`B(*JHYJ3HMH*H@K+BH.2V0J2 +M""N(.R=+="M(-R.<= +M.?(ENX*D$##_H(K_^!_\+Y(EN\(ENZ"9@J#,@IJ3DMD*D@G)B!'*P\"9H)+9 +M"I(I-(((W())$48"```PHR`E6@&QD`/2);O");NBH-2@W8*@S(+0TX#`PX#2 +MW0K2#L=2@1#`_R0OLH`1WPD(@$%MC+D*0$%GK+K0*]`R4. +M`;&0`X8J_ZT#)=T`L9`#!IC_PB6[HJ#4H,R"RL/"W`O"+"06;!CB);N@[H+J +MX^+>"^(N)/A"Z#YZT_>>'PP(@DV!F/(+^1:/%Z+)_A8:()CB#&S)`<8<_P`H +M`1WPX@V!%BX5#&_Y`9CBQA?_`)(ENZ*@U*"9@@P(FI.2V0N":23&OO\PHR`B +M803E:``B);O"H-3`(H+BH``J(R+2"^)B)/(EN\#_@OKS\M\*XD_*TB6[P-V" +M/\``*(EN\*@ +MU,"J@JJCHMH+HBHDH@H65HK*@U,(D^](D^Z(D^[(D^^#,@N#=@N"J@LK#PMP*P@S)X+N"VM/0 +MS*#"W`K"+#2JHZ+:"EELH@K)NK.PJJ"BV@JB*C2"H/^"2A&2)/NB)/O@F8+@ +MJH*:DY+9"I()R:JCH)F@DMD*DBDTF&F"233R)/N")/O@_X+@B(+Z\_+?"O(/ +MR8J#@/^@\M\*\B\T##NR3Q/2)/OR)/O@W8+@_X+:T]+="M(-R?KS\-V@TMT* +MTBTTLDT4PB3[TB3[X,R"X-V"RL/"W`K"#,G:T]#,H,+<"L(L-+),%J(D^](D +M^[T#X*J"X-V"JJ.BV@JB"LG"H`'0TX#0JJ"BV@JB*C00$2`E4P#B)/OR)/N" +MH-2`[H*`_X+JX^+>"N(.R?KS\.Z@XMX*XBXTV$79/L(D^](D^X#,@H#=@LK# +MPMP*P@S)VM/0S*#"W`K"+#2R!3:R3!*B)/N`JH*JHRJJD@H)&YF22@GR)/N` +M_X+Z\RK_X@\)#`T6_A*M#_!?(`P,=H`R*$H;W9("$Z+*!+(B!B8Y)0=I#;(B +M!X(K#H=H!((+-9SH%VD+F(*XZ8()-8=K`8SXY[U=AO'_B.N':-2""S56Z/P; +MS")E%$M5X@\)1OC_/?!&,O^""S6L2`=I#;(B!X(K#H=H!((+-9PX%VD+F(*X +MZ8()-8=K`8Q(Y[UXQDS_F`$;S")I%.(/"4N9F0$&^O\``*(/",)/"J>\%?"L +MH':`#&)J%+(/"!O,2ZJWO`(&^__RH-3B)/O2)/O")/OP[H+PW8+PS(+JX]K3 +MXMX*X@[+RL/2W0K2#\J00^O/B3_L=\"&0 +M`X(/",)/"H<\`D8Y__"LH':`$6)J%)(/"!O,2ZJ7/`+&,_\]\,;Y_P```((#^Q;(!)(G?Z*@U*"9@IJ22IF2*2+BH-3!.`., +MN;(G?R"[H%J[N!L6NP32)W_@W8+:TDK=PFT>'?":V`@;[_QWP#`I& +M]?\`-D$`@@()#`<6*`A=`JT"DJ``=H`M:$4;=T(&$U+%!+(F!B8T(`=D*[(F +M!S(K#L(+-8=C'YS,&YEB:B1+JH(""8>W)<;R_]CKX@LUAVW65D[^!O3_%V3H +M2(;XY#($-8=OWE83_0;V_P``0@((DD(+1[D9;0D@6:`,!W:`#')E)((""!MF +M2U6'M@(&^_\=\`P)1O7_`#9!`*(#-*)"$9CS#!L6F08+B1:H"B8I#*A#J3*2 +M`S:20A(=\``Y@J)#-)("$]("%@PJH)D@D)!TDD(3N./"`A2@W2"':QW20A:@ +MS"#"0A2R`S7R`A62`A.,BZ#_(/)"%>ACZ1*"R?T66`JX`[DBJ$.I,I(#-I)" +M$AWP##DY8J)#-))"$\CCW0.';!"20A:20A32`S46+0"20A788D"T(""B(,*@ +M`.(C%?(C%/)M%.)M%:4(`*A#J3*2`S:20A(=\#ERHD,TD@(3P@(4T@(6L)D@ +MD)!TDD(3B..PW2"PS""':!K20A;"0A2B`S7R`A62`A.,BK#_(/)"%>ACZ1(F +M.26H`ZDBF$.9,H(#-H)"$AWP(*(@0+0@)1P`PB,$R3*R`S:R0A(=\$"T(""B +M(*4:`.(C!.DRT@,VTD(2'?`V00#B(@92I')04X"R'A+"'A/2'A3B'A46%!3R +M!8!#,(.ABR>BX +M[9CN?.S`NQ"0D`2PF2"9[;CHD)`$P+L0L)D@F>B";A#X@O)N$>)H$O)H$8)O +M$.)O$AWP\@6`7(B`_X*!FP,,&OKSBO^E.P&!G`-K""S4,"HQL@@DU#!^`KY/(8J#0=-),-:R-TJW_J.SB +M"33X$OELLFP0DFP1XDPTT*H0B(+H8JGLXF@2^'+B;Q(=\```\JW_Z.R""32" +M3#22;!&R;!#P[A#8@HABZ>R";1*HA"`A,F-`<,"()"%!WP`/ARZ._8@E#N$.GO +MR.VX8E#,$,GMJ.L,"5"J$*GKDD(4'?```#9!`$("$PP%8J[_!V0.2'(XY%)$ +M-6`S$#GD0@(3%V0/B()(Z%)(-6!$$$)H#D("$R8T"%)"%%)"%1WP`,ARN.Q2 +M3#6H@F"[$+GLF.I22C5X8F"9$)GJB.=21S5@B!")YU)"%%)"%1WP-D$`XM)J +M@BX[P9$#HJ#4H(B"D98#BH+*B(((2?&0`PP+%E@;FD(,"E&2`V*O_S&5`W:` +M0H(D?]*@U-"(@HJ"BHHZB((H?X@H5Z@4DB1_T)F"FI*:FC"9@)(I?Y()$IRI +M@BX[TJ#4T(B"BH+*B(((24NJ&[N'NQJ&[?\``%(D?]!5@EI26EHZ55(E?VT+ +M6"5&\_\;AA9(%)(D?]"9@IJ2D):@.IF2*7^AA0.2"1/"H/_@=A'V.5JR)'_B +M)'^")'_0NX+0[H+0B(*ZLK"VH.KBBH+@YJ`ZN[(K?SKN@(:@.HB"*'_B+G^X +MBX(($^A^"XB`OH/,.ZJRLBN[L@LTQQM*(*(@PJ`#9;G^H84#\9`#!@X`XB1_ +MT.Z"ZN+@YJ`Z[N(N?^ANX@XTQQX@LB1_T+N"NK*PMJ`ZN[(K?R"B(`P\L@L1 +MI;7^H84#\9`#XB1_LJ#4L.Z"ZN+JYSKNXBY_#!W23A+")'^PS(+*PJK,4FQ$ +MDB1_L)F"FI*:ES"9@)(I?\()%+*D?-S,H@D3)CI#!VH(@BD'@B@.A^@+%VHN +MHBD(HBH.AVHEL#*`P@.0G*RR`W#"`W#2)'^M!N*@U.#=@NT"VM+ZW64#`!WP +M'?"Z,@;W_P"(:8CHAVBT1O+_FD(,"@P+TB1_#`SBH-3@W8+M`MK2^MUE```= +M\```-D$`%C4+@L40%M@*4.*@J$ZR"A'1G0,RH/\PF\`6N0G""A.,_-KVDB]_ +MF6J"+W^)>O(O?_F*#`S"2A/"2A7"2A3"2A9"!0GX3@N$A[)'VN;=`G:`'E#= +MH)A=B&F939QHB'FIA-1O;_``#2+G_9BD;U_P``G#10E*#Y.>(%"5".H(@X"^XR2!'B10DW&PFM +M!L*@`N6>_AWP'?"8:HQIR'J,+/B*S/_:AI(H?YEJPBA_R7J"*'^)BOCIB'K" +MJ__`_Q#YZ?CHF(K`_Q#YZ(CI^&K`B!")Z?CO#!GP^P16[_&"U@622`L=\``` +M`#9A`"DATB(3(M-G@B+[#`Z2I!`PB*":B.D8%GT&09$#<8\#FH.BTVJI,8D1 +MQ@T`N"'"(OO2H-2H`=#,@M&0`Z@*RL/:S*6>`*(B^[*@U+"J@K&0`ZJCL*J` +M)7#_V`'((=A=TFP3G'VH3?&>`]D!]GKJ@9\#\/J@^`^*_Z`/````DJ00#`Z" +M(OLPB*":B(@8%A@BJ"%"H_A*0^EZZ4KI"NDTHBH/%DH=@LK_%J@=DLK^%LD; +MK0,E6/^R(OO"H-3`NX+!H`.ZL\J[LBL@H@3THDL1'?"B(0*B*@]2+0(62AN] +M!0PMK,P@Q[Z!$,'_P:5_Z@-N"W((3#3(&6@`*(B^[*@U+"J +M@K&0`Z"C@#WPNJIE4_^B(ONRH-2PJH*QD`.JH[JJ)5O_!H?_PB+[J!W2H-30 +MS(+1D`.X(8CHA^C/%V\(\BD(\B\.A^_#8J#_@J#44B1_TJ00VM/B#=R`58*2#=SR)']: +M4UI;@/^"RE52)7_AD`/ZPU(%$>K,%LP1XLP0%FX1P'N`(B<$L@(1X9T#9QM? +M\@(3C/_J@](H?]EBDBA_F7*"*'^)@@P-TD(3TD(5TD(4TD(6\@P)F$>9`0N/ +MASH"!BP`X'.`H.H@=H".P.Z@F%[X:8AYF4Y6[P;R)W_Y8H89`(AIB.B`B`16 +M^/&&T/\`F&*,:?ARC"^(@LSXZO.2+W^98H(O?XER\B]_^8+X8[*), +M-;"9$))L#E('$R8U#J)'%:)'%)(#"Y>X*<;L_UAW2.6B137XA[!$$$GEZ.^B +M3S789[#N$.GOR.VB336PS!#)[4;R_QWP`#:!`+T#22%I`5D1S0*BUVK6E@#R +MUP3X3V#OD.D!@BH[49$#DJ#4D(B"#`**AUJ(@@A+0M=G#`86N"_1HP,QH@.& +M!@``XBH[\J#4\.Z"ZN=:[N(.2TMF&R+G,@+&M0"")/OBH-3@B(**AXJ&.HB" +M*'^(&+>8SB8<9&8LR)(D^^*@U."9@IJ7FI8ZF9(I?Y()%:E1DLG]%OD9\B3[ +MX/^"^O?Z]CK_\B]_\@\5J5&((?+/_A9_&E:('/(D^^#_@I@!^O?Z]CK_\B]_ +MJ5$;B?@_D(FS@($A@/_`%I_VAHT`DB3[X)F"FI>:ECJ9DBE_D@D5J5$F.4/R +M)/O@_X+Z]_KV.O_R+W_R#Q6I48@A)A].5O@&\B3[X/^"F`'Z]_KV.O_R+W^I +M41N)^#^0B;.`@2&`_\`63_1&-P```*(D^\DQX*J"N4&JIZJF.JJB*G_E3?^H +M4;A!T:,#R#%&Q_\``*(D^\DQX*J"N4&JIZJF.JJB*G^E2_^H4;A!T:,#R#%& +MOO\``/(D^^#_@OKWVO_R+W^I41;O!9(D^X(D^^"9@N"(@IJ7BH?:F9(I?XJ& +M.HB"*'^I49>8&/(D^^#_@OKWVO_R+W^($?@_J5&`_\`6O^JB)/NY0;*@U+"J +M@LDQJJ>JICJJHBI_943_J%&X0=&C`\@QAJ'_HB3[R3'@JH*Y0:JGH*:`.JJB +M*G\E0O^H4;A!T:,#R#'&F/^B)/O),>"J@KE!JJ>JICJJHBI_)4#_J%&X0=&C +M`\@Q1I#_``"B)/O),>"J@KE!JJ>JICJJHBI_Y3W_N$'(,=&C`ZA11GK_``"B +M)/O),>"J@KE!JJ>JICJJHBI_I3O_N$'(,=&C`ZA11G'_``#R)/O@_X+Z]]K_ +M\B]_J5$6[P62)/N")/O@F8+@B(*:EXJ'VIF2*7^*ACJ(@BA_J5&7F!CR)/O@ +M_X+Z]]K_\B]_B!'X/ZE1@/_`%G_7HB3[N4&RH-2PJH+),:JGJJ8ZJJ(J?V4T +M_[A!R#'1HP.H4894_Z(D^\DQX*J"N4&JIZ"F@#JJHBI_)3+_N$'(,=&C`ZA1 +MQDO_HB3[R3'@JH*Y0:JGJJ8ZJJ(J?R4P_[A!R#'1HP.H449#_QWP-D$`#`>" +M`PL+0DD3%I@'+0.BKO\,"7:`16(B)%@3N!8;=TLBMZ4T4@83V'8'90S([9)- +M-:#,$,GM4@83%V40Z(;2+@Z23C6@W1#2;@Y2!A,F-0Z21A621A2"`PN'MRG& +M[/^X=HCKDDLU6(:@B!")ZTCEDD4U^&:@1!!)Y>CODD\UH.X0Z>]&\O\=\``V +M00#RKO\,)=AS@@0*R//P[1$;[L#>DR#=P-+-_W:8*:(D%+(*%*P\!VL,@@H5 +MZ'H'Z`283M<9*1=K#+(*%1?K!KB*Z$O7'CU+1!WP`&8[]X(*%9AJ5OC^F$G7 +MF>KE&O\=\-CN\-T0V>[""A10S!#"2A2B)!2R"A-F.\Z(:NCH\.X0Z>@=\,CK +M\,P0R>N2"A20D`222A2B)!2""A-F.*KH:MCN\-T0V>X=\```-D$`H@0+#`D6 +M"A)]!-*N_PP,XJ`"=H`]@BD=\#9A`.&6`YT" +MN/3(="&0`Q9;&?+5:H(O.]&1`[*@U+"(@O!\$8J%VHB""$H;=PP,%F@)F0$, +M"K&/`^IED.?`XL[_=H"`@B9_(J#4((B"BH6*BKJ(@BA_@@@4!V@7DB9_()F" +MFI6:FKJ9DBE_DBD'DBD$YQDT@B9_(J#4((B"BH6*BKJ(@BA_@@@4&\P7:"&2 +M)G\@F8*:E9J:NIF2*7^8B9A)YYD+#"J&"@`,&D8)````@B\[DJ#4D(B"BH7: +MB(((2DNJA[P,!M[_`)D!ZF60Y\`+[@P*O0/"H`#2H`#]!667_[CT(9`#HB9_ +MPJ#4P*J"JJ4JJI(*"A;+%.@!"\L,&`P/P/B#X.?`"^YVF1NR*A3""Q38>P=L +M!((--8S(%VP&N(N2"S6\R4NJ'?"(3>>8[`P>.6TY&^)--<(J%/"#D(E=L@P5 +MX+L@LDP5LBH4D@L59CG5V&L,',)--9(J%)AI.5DY:1WPB$OGF+S"*A2(C`P9 +M.6NX:+D)+%-(/"]<\`L8C`#WPANO_`-A[F.WB336( +MBR"9$)GMV.CB2#68:R#=$-GHB.GB234@B!")Z<;P_P```.@!X.?`XL[_=ID, +MLBH4\@L4R&LF/P-+JAWP@@PU5EC_F$SGF?#XBYA[#!XY;SEI.6PY&SE?.5DY +M7.)/-=(J%)B-V'V2"362336"*A3X>(AH\@\U\D@UXBH4##W23A4=\+CT(9`# +MQHW_```V00`,`S)"$S)"%#)"%3)"%C)"$CEB.7(Y@AWP-D$`,E<2@J[_HJ#_ +MDJ``%E(`0$'T8&%!0E<34E<48E<5F4>9=YEGF5>21S621S:29Q"29Q&29Q*2 +M9Q,I]T"S@BCGJJNPJ[.`(A"@J"&"K?^`(A!\Z*F'@"(0+`B`(B!\V(`B$"GG +M+0<=\```-D$`8J#^@7T#D7P#L7L##!P,!^&F`Z$U`_*@^$&E`]&D`S%C`U%U +M`]K24FU^4F."?/5"8YKR:H(,Y/%D`^)M?^)CPG)M@.%^`](M@-DOT6\#PF-$ +MPF-%PF]8VM(,#')O4[)O2%)JP+*E#+JRDF.`K0>"8\!I#T)O0.)O..*@`.66 +M_`R+XM(-#"]!D@.2H/_!IP/1J`-BI'Z!9P."8X)J8M)CA!:!J0-V\`Q,`#RFL!"FN1%V@!#R(N?Y,>@Q +MX.`4Z3'8,28]`@;Z_Y@1F0$X`283!8D!*`$=\.&O`P`^IM`0I@P*V0'(`;@! +MJ0$H`<#%%,)'`;"P1+)'`!WP`#9!`%+2#%(E)L&O`V+2!%(%`5)F+``\IM`0 +MIC&P`]#F!-#05#HRXD-\TD-]`#RFL!"F`#RF4!"FX+L14(,D4&($4*84L*H@ +MHE,_DA,_4%$$DF,A@D.`8D.!4D."(@."(F,C#`(=\```-F$`480#HJ$H0M(* +MTB2F#!P,"](-`#*D$#HRTLW[T+R#LD/HDB2FJJ):4I()`9)JXH(E(IP(@@6` +MX@/H\J``@/R#\.X@XD/H#`8`-J;`$*:2HVR:>7[(*;@P9%@L(TB/&PB,8UQP:XB0MX@X] +MXLZ^%CX)@B,8\B/&AS]]HB/&HF,8`#:FP!"FK0SVG$"V7`*BS/LF.F(DI`#_$;(#Y_#,("#N$>"[(,"[(``VIL`0IL)G$Y(G$QN9DF<3@@/? +MX;$#@LC_%@A*PB0NPBP3@B<3DJ`!P,$$]B@"DJ``\(D1\B<4P,@@#!GV+P$, +M"8(7M.#Y$8"($?"((,"((()MC/(G$X%D`^#_$?#[(.#_(/F8D@/?)AD"8F<4 +ML@/?)BM(XB<3\@/DPB4BLJ#4L,R"&__*PL+<"L(,R``/0.#@D>>\`@:)`/(G +M%((#Y.(E(K#N@H+(`>#B@.+>"N(.R``(0/#PD?>^`@:6`/(DI!8?/%@#\%41 +M@@/?\;(#PJ9N@LC^%N@X`#JFL!"FLD2ND@2N%OE+RK(,">*DJ`N%@F$`X.*` +M`#:FH!"FFL+ZS*),8*"@=+9J`D8D`/8J&@`VIL`0IH@!PEN?P,#TQ[@J#!S" +M0_N&'@```"8J""9*$69:%\8"```VIH`0IH)N'@8"```VIL`0IL)NX1N9*[M+ +M[H+*_1:H/+;9FPP:HD/[L@/?HJ$""[L6"SRVV34,',)#^T8+````.J;@$*;B +M0^72`^4673`,'P`ZIK`0IK)#YI(#Y@PHD/B3\F2DQEW_#!S"0_OB)"[B+A,, +M&5=N!/(#WYP?@B0N@B@1%G@`H@/?/?`F&@$,"9)#Y[(D+K(K$U=K!\(#WSWP +M%KPIXB0NXBX1XL[_%GXH\B=1%A\!(*(@Y5$!T6,#%EH`+0H=\```@B0N@B@3 +M%V@?D@/?)BD9`#:FL!"FLF=3HB=3MCH-#&(,',)#^QWP``!B9U,,&@`ZIJ`0 +MII(D+I@)/#ZJF9+)&I>^`L:3`))G$,(G$,)G[;(D+K(K$["W!!:;#``VIO`0 +MIO)CQ>(CQ;8^`H;2`((CQ0N(%C@U#!P`/*:P$*:R8T*B(T)\J9>J`H;(`.(C +M0J9^`D;&``P:`#JF@!"F@F-#\B-#ER\(LB-#YGL"1B$`#&(,',)#^QWP``QB +M#!W20_L=\`Q28F<3#![B0_L=\/(D+?CO\/<$5G_(#!P`/*:0$*:R)2+"HVP@ +MN[#*NY)K(((D+H(H$X"$!!9HR-(#Y58-R`P8`#BFX!"F\B4B@J-L(/^PBO_B +M;R'&&?\,4F)G%`P9DD/['?!B8T.R(T.R8T*B(T*B8\6B)VN2)VR")^Z@H#20 +MD#2C]A:3]AJ#]AYB9VOB%[;R`^4`#T#@X+'B5[?"%[>R%[3`NX*R5[B"%[BB +M`^61>`,`&D``B*&"5[GR)S3B%[3"%[>P_P$+[@O,P.X1\.X@0,P1X,P@X60# +M"YG";DFR+<,6:Q`6:1#"`_P+F68L[@P.'`\BH&!,&()MRN)MRY(D+O+/$`SX +MZIF2"6"2;#_$?#[((#_((%D`^#_(/F8QM#^]MD"A@W_A@O_`#JF +ML!"FLD2O@@2O%OC"#`GBI:BRIFX+QC"))KB`[7PJL"R))K(/((#M;(+(=#,P`P=P,V3X+O`H*V3#!ZPO9/`JB"P +MJB"O*!=0.28Q"A.`.B9LB" +M;X/R+X/R9H+HPXS>PB0MP@P_5EP`DF,,LD/"T@/"9ATAO0+BK__B8P^B)"\E +M^?RB0\/R`\,,&R9O"+)#PPQR'?```((#PR9X1R"B("4C`1;*`:`J(!WPH@/" +M9AH7PB46G!S2H`#20\)E\/N&`0``XJ``XF,,(*(@DB.ZDF7&@B71B5'R)='Y +M0:7<`8QJ#&(=\`QR'?"M`J47`XPJ#&(=\*(#M!8*$[(CNO"[$;GSPB74!VP' +M#!W216D&`0`,#N)%:?(#R19_$8(#S(PH#&(=\)(D+I(I$Q=I"0QK`#NF/?"@ +M$*;"`Z\+S!;,$@S]V3'`(`"1>`,A9`,,)PN9XB)#%IX/%ID/\@/,"YEF+^Z( +M,<(#M`SY\-@1T,P@PF94LB74PB6AHB6B`+L1@,P1P*H@L*H@HF9(EQ@.\B$$ +MXB$%(/\1\.X@XF9'LB2DH@2LD@.TT+L1L*H@H)D1H)D@DF)*@B0NB,@,"LRH +MTB0MT@T_PJ`!T*R#H/H1D7@#PB7CTB.XX@.T"YG`S!&"!*R`W1&R)=70[A'@ +MB"``NQ'0B"#`B""P_R"`_R#R9HWB`[3B9LB")H/X,N(B0](F0X#_(/#N(.#= +M(!8=!!89!*(#S`N99BK=#`(=\```LB.ZN?.&L__")"W"##]6[.WR)=32)=$, +M'O#=P-#>D])#PH:R_U;9\')#S*4YSXTB2DR/O7'!CHZY=N$_(K$((DI)(K$0N(@)^#%FD/D+D@DB2D%MD$ +MF.N7:1FY80?I`@8B`,A1##JI,?#,$O-[(32JA1\+L1)985J0&R$TJH4662%=@!PA-*N&$, +M3M#,@NDQRLK)408/``#R)"_X#[EA\/S`UR_'LA-*J%'PNQ&EDA6I$;(32JA1 +MY8X5N&'H$=(33L(32@Q?^3'@S(+0T?3*RMK,R5&(48E!1IS_``"2)"]660"B +M)*>B9"_"*Q%67`#2)*?2:Q'B*Q#,3O(DI_)K$`SX#!F20\N),0:0_](D+]@- +MT-G`QL[_`#;A`$&U`Z*C4#+2:+(CNZI2@A7$(+N@2KNR*WIBI"1Q8P.WF$;2 +M([O"%<(@W:!*W=(M?-#,P%9L:/(CN^(E.R#_H$K_\B]^@M(*B?'WGB&2([N" +M*"T@F:"""#Q*F9(I@)>8#6J2F>'&V@```++2"KGQK0)E9_T,#I&V`X*@U`PJ +MFI*B25O2([N909&0`X#=@GP/VM*:W?<=(K(-",T-=IL:N$R<.XAK%A@`Z6N( +M>XPHZ7NX3(B+C`CIBTO,XDT-PB.[LJ#4L,R"RL+"W`KB3,V"([NPB()H\8J" +M@M@*XDC(8B8MTB.TPB.[L,R"RL+"W`K"#,UB!CR\+,(CN["\@KJRD+N`]QLB +M\@L(L,L@=I\9F$R<*8AI^'F,".EIC"_I>9A,B(F,".F)2\SB2PV8\9(IFI() +M(PN9%IE3N/&R*YJR"R.RR_X6NU(,#TJBPBJ%%AQ<@B.[DJ#4D(B"BH*"V`J" +M",AGN`ZR([N0NX*PLH"RVPIB2\C"([N"H-2`S(+*PL+<"F),S(CQ@BB:DJ_` +M@@@CLJ"`8;<#@LC^%N@OB/&"*)J""",6."^H\:(JFL*D)*(*(\K"R>&BROT6 +MNEBRTFJR81&2([O2H-30F8*:DI+9"N))R8(CN]"(@HJ"@M@+XF@D0B.[T$2" +M2D)"U`KB1,KR([O0_X+"(1'Z\O+?"N)/R\(L.]#,@M&1`\K"VLS"#$A9,0P$ +M%AP'#`5QCP-ADP.B([L@JJ"BVFNH&JJDH*JP(*J@8*J`)=3^@B.[PJ#4P(B" +MBH**A7J(HFAO\B.[P/^"#`[Z\OKU>O_B;W_2([O`W8*R(1':TMK5>MWB;8^R +M*SO`NX+!D0.ZLLJ[L@M(&T1+5;((F&H)I>8(F&H)I +M>H(F&H)I>X(F&H)I?((F&H)I?8(F&H)I?@Q(XF]_*IM*F4O_IY^R@B.[PJ#4 +MP(B"\3@#BH*"V`KR:##2([ORHU`@W:#ZW>)M,;(CN\"[@@P:NK*RVPJB2\V2 +M([5\"("9$))GQ/(CM=(5Q(#_$,#=`?#=(/%D`])O1L(CN_&U`[(5Q"#,H/K, +MLFQZHB.[DA7"(*J@^JJ2:GR"([O(\=(E.R"(H/J(TFA^TB.[PBPM(-V@^MW" +M##S";8"R([L;N_8K'I&Y`R"+H`PJL*K`D(B`=IH-XFA\XFA^XFB`XFB"2XC" +M)3O"9XNR)3NB%,XBXNT@WEXBX3 +M#`)`W1'@Z`3@W2#29\<=\`""I"2*@HGA@@CJ"X@62$*(X8((ZO*@8("_@[FQ +MR/'"+"W"##VRH'7'NQWR([NX)$B16*'2 +M)'_"(1"M!U"P=-#,@,)D@*54_.(A$>(N+TM$&U7G-=[R(0_R+YKR#R-2(0-Q +M8P,6#Q3!N@.2K__848(CMD(CM;(CNZ(CNX!$@B"[H`N-D(@PRKM*3<*@U,"J +M@LAAJJ*BV@JB"L@+1(!$$,JJH*2"#!PEF`.XP<"[$;JR:KNB:WVB(1&8H:(J +M+PP.I[ETW0EV@!7R*WW"(1'Z]/)K@<(L+QO=LLL0Q[U9#`Y&^/\`R/&RH8#R +M+"V2+"V"+"W"+"WR#SZ8Z8(8%O+/]\(<%Y"9!("(D)"($1O,NHB`S((,&)"H +MD\"Z@BR\Q[\DD;L#H;P#D)^@F`FJF:`)`*+2"JGQ!FK^R/'"+)H,&[),(T:[ +M_AP*@B.[LJ#4L(B"BH*"V`J"",@<#_#Z8Q;X'Y(CN["9@IJ2DMD*D@G(]SD" +M1I'^N/&R*YH,#@PZHDLCAHW^`((CN\(CNY*@U)#,@I"(@LK"PMP*P@S(BH*" +MV`I@S&/"2,P&D_[X\?(OF@P.#$W23R.&GOX`0B.[@J#4@$2"@@SJ2D)"U`I" +M!,@+B!M$0$!T%B@"N(.R("J@H*OP*+*/^#OP("J$."J@N6``\&T`[B!X;T# +MF.'RRC\JU**OP)(97:#_$.K=L)F"(+2@RKN2R3^@F1#R:W]"37_R(1(;I*EQ +M&^_GNE*M"]DA21%`S\#)`0=L%$NK&XV)(8(K?\AQR1&*B8)K@$)-@+@AR!'= +M"8@!G0JM#("!07:8'8(I?QO**[N*C8)I@*)+?H(I@"NJBYF*C8)I?\)+?TQ= +M@60##`G(0<"T$;JR:KOB3)_"*WV9Z-G8TJ_`PLP_T,P0PFM]V%&B([:2([4+ +MC:"9@GSZH(@PFMT+W8#=$/:T!(%D`\GXF'$]\.>Y)@P+0*_`=IH>2LO`C!&* +M@FJ(XBA]&[L;S.KMXFB!]KP$D60#Z?D]\,(CN]*@U-#,@KCQRL+"W`KR3,BR +M*YH,#@P:HDLC1CO^`.*@P.FQQO?^J.'(L:(:7;EAP*J"V5&BRC^0JA"&'/\` +MPB.[L,R"#`[*PL+<"O),R(81_@#XX0P+#`[I7X(?7;G!#!NPB!&"R#^0B!"" +M8[[X7_)J@^)CP0;T_ME1PJ#`R8'&C__94:&^`V7X%-A1#`[&9/\`V5&AOP-E +M]Q3840P.QF#_`-E1H<`#9?84V%$,#L9<_P#94:'!`V7U%-A1#`[&6/\`V5&A +MP@-E]!3840P.QE3_`-E1H<,#9?,4V%$,#L90_P#94:'$`V7R%-A1#`[&3/\` +MV5&AQ0-E\13840P.QDC_`-E1H<8#9?`4V%$,#L9$_P#94:''`V7O%-A1#`[& +M0/\`V5&AR`-E[A3840P.QCS_`#9!``P$`#2F8!"F4J0D6E)B92$R)2$,%K:# +M`D9K`(AE%H@``#2FD!"FDF4BHB4BMHH"AF<`@J^`LB+NPJ$"#`\6FPMQR0.1 +MR@-Z<,8AWP``#=(]);'P`VIM`0ICWPART"INT'8D7G#&(= +M\```/2,R6]\&!``R)2(,#=);WP`30`#6H=);'QON*[MKF>(B[FMW&__GOP+& +MT__R!G*0DH``/*:@$*:@H'06^@T`-J:@ +M$*:'J@+&.0"FZ@)&.```NB.R5Q\`-J:@$*:'J@+&-0"FZ@)&-```VB/25]^] +M"0`\IJ`0IN*@`#*@`J"@=':C4;R:`#:FT!"F/?"'+0*F[0=B1><,8AWP``#= +M(]);'P`VIM`0ICWPART"INT'8D7G#&(=\```/2,R6]\&!``R)2(,#=);WP`3 +M0`#6H=);'QON*[MKF>(B[VMW&__GOP*&T__&"`!B1><,8AWP`&)%YPQB'?`` +MHB4A#`NR5]\`&D``-J$R5Q\&IO\,`AWP8D7G#&(=\`!B1><,8AWP`.(E(0P# +M,E??`!Y``-:ATE<,8AWP`#9A`)+2"H(II:'-`YQ( +MH#*`=H`,PB-_R%S"8W^R*:6,&P;[_T*D@DI"T@1VDJ$"G&T`.::@$*:B1'<` +M.::`$*8,`H)$>!WP````.:;`$*;"1'FR!'D6NP@,!1P\8O_";W_B)'S0 +M[H*X`>KBZN5Z[L)NC[(K.]"[@M&1`[JRVKNR"T@;,TM5MR.9H=$##`TRHE3A +ME`.2H".@\H"0G8(,2""9H.J9=J@R@B^4DLD@@FEW@B^4@FEX@B^4@FEY@B^4 +M@FEZ@B^4@FE[@B^4@FE\@B^4@FE]@B^4@FE^((V@+#D;W3J(PFA_T-!T9BVM +MDM(%PDD#'?```#9A`,*D$,I2@@7HDJ``%B@`DD7S0=(#2D*R)(%BT@D66R:" +M)FV(Z(".!!:H)9(%WV8I!2"B(&7I_S+2:J(E*'+2`1;J`,(C.[(G\R#,H,+< +M!+)L'=(F;=B=)AU#K0)E5P"B(SN2)[4@JJ"2:O&"(SOR)[8@B*#R://B!>46 +MSD>R!>86:T;"(SL@S*#"+//"9\'B(SO2)\$@[J#2;O>&$@"R(SNB)[4@NZ"B +M:_&2(SN")[8@F:"":?/R!>46GT;"!>86/$72(SL@W:#2+?/29\&2(SN")\$@ +MF:"":??R(SOB)_,@_Z#RWP3B;R>B!?,6*CK"H'4,#Z(%W`P8B1&@JI"B1>*2 +M)N3B!>+2)FV2R?Z0^(/2#3WZ[ND!USP,LB9MLBM^]BL##`S)$5R(^`&B)N2R +M%6C"%6F`_X+2%6J!TP/B%6OZ\HK_Y0#^L@7<+`FW.0B2!=P&`0`````,"9)% +MW.(%W.)*--(FYM(-`<%C`[%D`Q8=+>(%W('4`_(D?L#N$>KBBN[B+A_Z[N)K +M1-(C-9(59'P(@-T0P)D!T)D@DFM&\B,U@/\0\FS$DB,[DFH4@@/J@FH5HF9O +M^+7B)F^2)F]`_P'2)FWB'A*"!?&2&1/8[2"(`?#N(`"9$>"9(-#9!##=`="( +M()"(((F+\B9N\B\3DJ`!5V\$H@7?C.K2)F[2+1'P(``+W18=*PP)@B>O\B>N +MX@7G@(@1X/\1\.X@\B;DT@7E@.X@(/\1`-T1\-T@X-T@X;$#\/D1\-T@X-T@ +MV9NB(SO2)F\@JJ"B*O&I'8(C.Z(F;R"(H((H\XDJ\B,[@B9O(/^@\B_W^3CB +M)N06;B62)N0+F1;Y):(FY"8J:`QB#!NR1?L=\#+2:M(C.^(E+R#=H,K=TBT9 +MX-W`%LW9HB,[(*J@RJJB*AFX!1NJY7D4LB4OH+O`%AO8PB9MPBP.P,@$5MPG +MT@7H%@TMXB2!5I[6\B9M^._P^016[]4,4B)%\PQB'?```((C.Y(F;R"(H((H +M\XD)#`W29ZS29ZV2)F^B)2B")F_RKO\,'HCHH*Z3@*H1\(@0H(@@HB9OB>GR +M!>B2)F]\V)CI\/`$\/\1@)D0\)D@\B9OF>J"!>FB)F]\N:CJ@(`$X(@1D*H0 +M@*H@@B9OJ>^2!>KR)F]\>OCOD)`$T)D1H/\0D/\@DB9O^>BB!>N")F]L_XCH +MH*`$P*H1\(@0H(@@\B9OHB;EB>FB;Q/29N6")F^2)F_R!>28Z7SJ\/`$H)D0 +MHB9OD/\@^>B2)2^")F^92E(E+Y(F;UEX\B;D#`J")F_PKH-PJA'BK?^(Z/(F +M;U(F;>"($*"((.(F;TQ:B>GH[ECE@J^_@.X04%D$H%414.X@Z>_9ZZG;DB,O +M#`6L6:'5`ZJB=H`9+`U7/0GR*G_B)'[Z[NG[@B,OHLH0&U6'M03&]_\``.(D +M?](D?NK=TFM'HB1_DB1^#`*JF9)LQ1WP^!&,3X(C/58XTO$S`Y(O\)#2%!:] +M#X(%W-'4`Y(D?L"($8J"VHB"*!^:B()K1/(C->(59'P-T/\0P.X!\.X@XFM& +MDB,UT)D0DFS$!D7_DB,X5FG%H8P#/?"JHF6`^Z)%W,(%W"P+QSL"1C\`#`W2 +M1=R&#?\``.(%WPON5E[4!E'_`/(C.X(F;R#_H/(O]_D(!H?_@B,[DB9O((B@ +M@BCQB0G&@O\``)(C.R"9H)(I\9)GP4;E_@"B(SNR(SL@JJ"B*O$@NZ"R*_.P +MJD.B9\%&WOX`LB,[(+N@LBOQLF?!!NK^`,(C.](C.R#,H,(L\2#=H-(M\]#, +M0\)GP0;C_@`@HB#2H`#21?(EG@(6BJXBH`8=\)#H!%;>[Y$U`Y(I3Y)K1((F +MYN(59((8`L#N`8"$],"($8#N(.)K1I(FYK"-$9(9`N*D@N"(()"4],"9$9)L +MQ()O\,8"_Z(%WZ+*_E9:TB"B("62_P:C_@#B!=P,"]'4`\#N$>KBVNZR3H#" +M!=S`S!'*PMK,LDR!AL?^```V@0`,#V*C_.*CW#'6`\*CS$*CQ#HRHB-_RT@$6V"'R:^F")?L@B*#*B/D(@B7[((B@2HCY"((E^R"( +MH.J(^0CR:\&"+1@6.!V239\,8AWP`&JBD@K\4M)G%LDV@B7[((B@\FC_TB7[ +M(-V@TMT$\FTCDB7[TB7[()F@(-V@:IF2*2)JW=(M)->Y5](E^X(E^R#=H""( +MH&K=TBTD:HB"*"*P\4&`W<#W/3CR)?L@_Z!J__@/NK_&'@``:K*""_Q2TF>B +MT@$66#/R:NF")?MZTB"(L/)H^X(M&!88'))-GPQB'?#2)?N2)?L@W:`@F:!J +MW=(M(FJ9DBDDU[DN@B7[DB7[((B@()F@:HB"*")JF9(I)+#Q09"(P(>_#Y(E +M^R"9H&J9F`FPN(E^]+2!-(M,R#NH.+>!-)N)^(J+:P>@B7[DB7[((B@@M@$()F@DMD$@B@A +M@FDC\B7[/?`@_Z"R;_^2)?NAD@,@F:!JF9C9IQD##`(=\+(E^Z+2!*@:(+N@ +M#`*RVP2IRQWP\B7[(/^@\M\$^"_R:^GR*_.2*^F"*^SZF?"9$1;8-9)KP8(- +MB19X-Y(-BA9I-?(E^\(KP2#_H.K_R0_2)?L@W:#";?/")?NR*C0@S*!JS+)L +M*)(E^X(J*B"9H&J9B3E&W?\``((E^R"(H(+8!(A8G%B")?L@B*""V`3R:">2 +M)?L@F:"2V03Y*?(E^Y(K\R#_H/+?!/(O)_I*2"8H6F17B)?O2)?OR(W\@[J`@W;#X+](M +M^\KNNO_ZW=D.TFK!PB7[N"0@S*"R;/>B)?N2)#0@JJ!JJI)J*((E^_(D*B"( +MH&J(^3A&>O\``-(E^R#=H-+=!-A=%IW)@B7[*HAZB(((D!:(&](E^R#=H/)M +M_Y(E^R"9H)+9!/)I(P8=_P"")?L@B*""V`2(6)Q8TB7[(-V@TMT$^2V2)?L@ +MF:"2V03R:2>")?OR*O,@B*""V`2"*">'/P*&E?_2)?N2*L0@W:#2W038+=J9 +MDFKI!I3_`/(E^^(E^R#NH&KNXBXB(/^@2O_JZ^D/Z2K&._^2)?O")?L@F:"2 +MV022*2$@S*":FY)L\8(E^\(E^Y(E^R"(H((H\2#,H,(L^2"9H,J(@FGSDB7[ +M\B7[@M($PB7[(/^@\B_Q(,R@PBSS()F@ZIG`_T/Y"?D8!B7_``P/!GG_%G_> +M"_^&>/\,!,:&_P``TB7[PB7[XJ/$(,RPPBS[(-V@ZMVZS,D-PFK!AJG_``"" +M)?N2)?L@B+""*/L@F:"ZB()I\?(E^\(E^X(E^R#_L)(C?R#,H,(L\9@I\B_\ +M((B@RIF:__)H\_(E^](E^X(E^R#=H-(M\2"(H((H\R#_H.K_@-U#V0_2:L'& +MD?\+^?)KP08G_\(E^X(KP2#,H.K,B0R2)?L@F:"":?%&*?\``)(E^](KP2"9 +MH.J9V0F")?L@B*#*B-D(\B7[(/^@TF_Q!B#_`((E^R"(H/)H_](E^X(E^R#= +MH-(M\2"(H(+8!-)H(X:L_JA!#`1&2_\V802AU@-=`JJBDBI_<9$#8M)JF(D, +M'H(J?DN9`!E``$ZA%NACLBI^9AL"ACT"G0X,`\(F.]*@U-#,@LK%>LS"#$H, +M#1;<$<*@`++5`2*@U/(F.R#_@OKU^OSRWPOX3_(/%!O=%A\.\B8[(/^"^O7Z +M_/+?"_A/@BOS^#_WN"GR)CN")CL@_X(@B(+Z]8J%BHR"V`N(2/K\\M\+B#CX +M3T"(P(D/Q@@```#R)CN")CL@_X(@B(+Z]8J%^OSRWPN*C(+8"XA(^$^(.(D/ +M@B8[(J#4((B"BH6*C(+8"XA(@@@4!V@F\B8[@B8[(/^"((B"^O7Z_(J%BHSR +MWPOX3X+8"XA(^`^(>##_D/E(@B8[(J#4((B"BH6*C(+8"XA(@@@4%V@G\B8[ +M@B8[(/^"((B"^O7Z_(J%BHSRWPOX3X+8"XA(^`^(B)#_D/)H!((F._*@U/"( +M@HJ%>HB""$K"S`0BH-2'O0*&NO\BU02"`N\,#V8H`H9``H("[['7`Q9(4((J +M?A9H9O)B%.)B%;(F.\*@U,"[@KJU>KNR"TK=#\P;!FX"#`O-`0P$=H!8\B8[ +MXJ#4X/^"^O7Z^_+?"_A/\@\3&]VLG_(F.^#_@OKU^OORWPOX3X@2^"_W*!2" +M)CO@B((;1(J%BHN"V`N(2(D,2\SB)CORH-3P[H+JY7KNX@Y*2[OGO0(&Z/^B +M86R288!"87:M`;T$#'SE"@*2)CNBH-2@F8*:E7J9D@E*[0$,"Q9I!L(A=@P) +MX,R@=H!8\B8[TJ#4T/^"^O7Z^?+?"_A/\@\3&[NLGZ(F.]"J@JJEJJFBV@NH +M2H@2J"JGJ!3R)CO0_X(;1/KU^OGRWPOX3_D,2\R")CNBH-2@B(**A7J(@@A* +M2YF'NP(&Z/^B(79"87@,;*!$P+T$X*J@HF%SI0$"XB%V%GX&W0X0D2#@P#2B +MT0&BRB"@I*!VK`>X";D*2YE+JM"$(7:H18@)N!FY&K@IN2JX.;DZN$FY2KA9 +MN5JX:;EJN'FY>KB)N8JXF;F:N*G8RX"KD)2ZI+FKB)N8JXF;F:N*G8 +MR-'8`Z(A +M;.*D4`P/\F(4\F(5ZN7B87"B*GX,#]K5TF%WY88!PB%X#`\B88'1V0.B(6SB +MI%2RT0&RRR#@Y8#B876B*G[0U8#2871EA`'B)CORH-3P[H+JY7KNX@Y+DB&` +M#`(6/@RRH`#"P7_"S!%V@+3B)CO2)CLRH-0P[H(PW8+JY=K5ZNOBW@O:V]+= +M"^(N%.D,TBT4T@T5!VTKXB8[\B8[,.Z",/^"ZN7Z]>KKXMX+XBX4^OORWPOH +M?O(O%.AN^']`[I#B;P7R)CLRH-0P_X+Z]?K[\M\+\B\4TJ#4\@\52\P;(A=O +M*X(F.Z(F.S"(@C"J@HJ%JJ6*BX+8"X(H%*JKHMH+B(BB*A2(:*B*D(B0@FH% +MHB8[T*J"JJ5ZJJ(*2TN[I[("!M'_V*606.6.1V@/"U03"+!0,"Y"5@,#P%':?#?(ID=(I;DN9\-W` +MT+Z330[`(D$]\':2,H(ID:(I;L(IDM(I;^(ID_(I<"(IE#(I<9+)$("*P,"M +MP.#/P"#3P("TDZ"TD\"TD]"TDQ8;78(F.Q8X``P"'?"B)>ZRU0'"*]32*]7` +MJF.B:]22)>\L#-"98Y)KU1:*3O;*6]&4`U":H-J9H-S`H=L#T.`DJJ5VG@?B +M*FWB:7]+F="#03WP=I@R@BIMDLD@@FEW@BIM@FEX@BIM@FEY@BIM@FEZ@BIM +M@FE[@BIM@FE\@BIM@FE]@BIM@FE^DBO5O0D624ZVR0)&W/^AV@-0F:"JF:'; +M`["\P+#P)*JE=I\'PBJ0PFF12YFP@T$]\':8,H(JD)+)(()IB8(JD()IBH(J +MD()IBX(JD()IC((JD()IC8(JD()ICH(JD()ICX(JD()ID`P"'?``TB8[\J#4 +M\-V"VM)ZW=(-2@P,%FT6DM(!#`O&(@""*GX6R$VR)CO"H-3`NX*ZM7J[L@M* +MW0_,&T:O`@P+$,$@#`1V@$F")CORH-3PB(**A8J+@M@+B$B""!0;W9Q8@B8[ +M\(B"&T2*A8J+@M@+B$B";`#"S`3R)CN"H-2`_X+Z]7K_\@]*2[OW/0+&C@`] +M\,;K_](F._*@U/#=@MK5>MW2#4I+N]<\`H8T`((F.]*@U-"(@HJ%BHN"V`N( +M2((($QO,9CC-\B8[T/^"^O7Z^_+?"_A/^&_X[X=OMX(F.]"(@HJ%BHN"V`N( +M2(AH@@@U5@CZ@B8[T(B"BH6*BX+8"XA(\BGSB#B'ORB")COR)CO0B(+0_X** +MA?KU^OORWPOX3XJ+@M@+^#^(2$#_P/D(A@@``((F._(F.]"(@M#_@HJ%^O6* +MBX+8"_K[\M\+^$^(2/@_^0CR)CO2)CN"H-2`_X*`W8+Z]?K[VM7:V_+?"_A/ +MTMT+V$WX;]@-V4\&Q?\,"0P#1E_^``""`O@6V$%]"DT/HB8[G01"87H6*M#2 +M!NGBU0K,'<81`O(N+?(O<@P(@F%[%E\'0F%^\=H##`-0U*#ZW9(G?SJ9DBEV +MHJ#4H)F"FI6PB8"""("2V0AVF`JB*;3""A,F/!I+F8(N+?(A>TLS@BAR&__R +M87N'/\62(7X&"@#(:O(L%1;/_?(F.X@J4/^@\B_W]YC.PFUN@BFT&T1+W8(( +M$8),-$;O_Z(N+:(J9(G?]J9DBEXH)F" +MFI6ZB8((@)+9"':8"J(IM,(*$R8\%$N9\BXM2]WR+W.BH-0;,_'G]3R(7F"(7K";Y$;B()A>J(IM$O_\F%YH@H1 +MHDPTQNW_``P>DB%ZHM4!0FK4DFK5QO;^/0X,"4;!_:)A;))A@*T!O00,+#)A +M?V68`O_R#TNR(7\,!!8_#`P,,L%_,L,1=H"TTB8[@B8[HJ#4H-V" +MH(B"VM6*A=KHB""$M+S(>T`P;1_P!R(6Q`M"#" +MH`.BP7^BRA'EA@'-!-(A=^(A<*(G?@P?LL%_LLL1Y1L!#!X,#\+5`?)LU8:B +M_BT/PM4!\FS4\FS5'?```+;*`L;;_M':`U":H*"LP-J9H-`D=IT'XB>!XFEN +M2YF@@T$]\':8,H(G@9+)(()I9H(G@8)I9X(G@8)I:((G@8)I:8(G@8)I:H(G +M@8)I:X(G@8)I;((G@8)I;9(KU4;%_K;)`@:C_J':`U"9H*J9L*S`H/`D=I\' +MLB>!LFF12YF@@T$]\':8,H(G@9+)(()IB8(G@8)IBH(G@8)IBX(G@8)IC((G +M@8)IC8(G@8)ICH(G@8)ICX(G@8)ID`P"'?``T=L#VM7"+9#B+9'B;9#";9%& +MAOX,!*)A;))A@(:I_0""`OC"U0$6J%]]"DT/DB8[%HGOH@;IXM4*%HIZTBXM +MTBUR#`B"87$6K00,`X':`\)A;5#4H(#=@)(G?SJ9DBEVHJ#4H)F"FI6PJ8"B +M"H"2V0AVF@JB*;3""A,F/")+F8(N+?(A<4LS@BAR&__R87&'/\7"(6T,'@P/ +M0FS4!J/_`,AJ\BP5%D_]\B8[B"I0_Z#R+_?WF,;";6Z"*;0;1$O=@@@1@DPT +M1NW_DB8[PJ#4P)F"FI5ZF9()2LT/%JEXT=H##`E"H`#0U8!V@##R)CLRH-0P +M_X+Z]?KY\M\+\B\$\@\3PLP!)C\7@B8[\J#4\(B"BH5ZB(((2DN9A[Q^!O+_ +M@B8[,(B"BH6*B8+8"XA(B&B(Z(=HT?(F.S#_@OKU^OGRWPOX3_AO\@\U5J_[ +M@B8[\B8[,/^"^O7Z^?+?"_A/^&]0B*""*/?X#_+>"^A.Z&[H[H=NT?(F.\#_@OKU^OGRWPOX3_AO\@\U +M5J_[@B8[HB8[P*J"JJ6JJ:+:"ZA*J&I0B*""*/>H"J>HF_(F.\#_@OKU^OGR +MWPOX3_AO\FUNXB8[P.Z"ZN7JZ>+>"^A.&T1+W>(.$>)/-,;:_P!"87W"H`31 +MV`,PM,!0HZ"B86ZR87S0JH!E1`'"(7W2(7P6@P@PLR"1V@,P\#10K:":JIJ5 +M=J\)XBENXFJ12YE+JK"$(7:H98(I;K(I;[)JDK(I<+)JD[(I<;)JE+(I+)JF[(I>;)JG+(I +M>K)JG;(I>[)JGK(I?+)JG[(I?;)JH()JD:+*0)+)0,R*8:R:IBR*8>R:IFR*8BR:IJR*8FR +M:INR*8JR:IRR*8NR:IVR*8RR:IZR*8VR:I^R*8ZR:J"":I&BRD"2R4"2U0'" +M:=7":=3R)CN"H-2`_X(,#OKU>O_R#TN286V=#!;O#O':`PP)4-R@\-V`=H`U +M@B8[LJ#4L(B"BH6*B8+8"X(H%((($^+.`28X'*(F.[*@U+"J@JJE>JJB"DM+ +MF:<^`L8H`#WPQO#_PB8[L,R"RL7*R<+<"\(L%,ALP@PU%JS\@B8[\B8[L(B" +ML/^"BH7Z]8J)@M@+^OGRWPOR+Q2"*!3X;XAH^&_Y6,(F.[#,@LK%RLG"W`O" +M+!3(;,)M;J(F.["J@JJEJJFBV@NB*A2B"A&B3#2")CNPB(**A8J)@M@+@B@4 +MB&B";9'R)CNP_X+Z]?KY\M\+\B\4&T1+W?(/$?)(-$;1_P``DB%M\"``DBG4 +M?U/(A>8(A>L)OD1N(@F%ZHBFT2__R +M87FB"A&B3#3&[?\`#`2B86R288"&\OT`DB8[TJ#4T)F"FI5ZF9()2CT/%GDC +M#`G1V@,,!,)A;=K5!@4`\B8[@J#4@/^"^O5Z__(/2DN9][-VPB8[\J#4\,R" +MRL7*R<+<"\A,P@P3&S-F/-"")COPB(**A8J)@M@+B$B(:(CHAVBZPB8[\,R" +MRL7*R<+<"\A,R&S"##56//K")COPS(+*QJ*@U*"9@IJ5L(F`@@B`DMD(=I@*HBFTP@H3)CP:2YF" +M+BWR(6]+,X(H=!O_\F%OAS_%PB%M!A7^R&KR+!46S_WR)CN(*E#_H/(O]_>8 +MSL)M;H(IM!M$2]V""!&"3#1&[_\,!*)A;$9+_@P$PF%MHF%LAI;_-F$`,J00 +M.F)I$6(&WU&)`QR$)B936H*""'Z,N*T"#`LE10",*@QB'?"8$9()V:+2`:)A +M`!8)/[(B[J(JU+>Z(+&4`R":H+"9@':`#](I?T)--,(B[ANJ2YG'N@1&^O\` +M`/@!XB^NXF_4"X86:"O2T@'!E@/*PI(L?^':`RP$%ND,\BW5HBVNLBVO@BW4 +M\+MC@*ICHFW4LFW5%LHL]LI6H/3`()J@DME:\+`DZJ)VFP>R*FZR::1+F?"# +M03WP=I@R@BINDLD@@FF<@BIN@FF=@BIN@FF>@BIN@FF?@BIN@FF@@BIN@FFA +M@BIN@FFB@BIN@FFCLBW5%OLL]LM3ZJ*P],`@FZ"2V5KP@"1VF`>R*I&R:<=+ +MF?"#03WP=I@R@BJ1DLD@@FF_@BJ1@FG`@BJ1@FG!@BJ1@FG"@BJ1@FG#@BJ1 +M@FG$@BJ1@FG%@BJ1@FG&DBW4%ND'\60#HM):V0%V@%7B*J1B*J6+JM(.-;C^ +MX@XTD-T1L+L1)AD_DLG^<@8T#`2"H/^`5\!0=(.`CL!(]H!W$6(&-3!$$4!W +M(!!F$7!F(`P'@.>#L%X@4%T@8%4@4F\52_^<6<;H_PP)HJ#_H*[`H.F#L(X@ +M@(T@@F\5V`'AV@,L!)(MU1:I!_%D`Z+26G:`5>(JQV(JR(NJT@XUN/[B#C20 +MW1&PNQ$F&3^2R?YR!C0,!(*@_X!7P%!T@X".P$CV@'<18@8U,$010'<@$&81 +M<&8@#`>`YX.P7B!072!@52!2;R5+_YQ9QNC_#`FBH/^@KL"@Z8.PCB"`C2"" +M;R7AV@,L!)%D`Z+2`DP]V=D,#=)I#K(JE+QKX/*`=H`N@B]N4BQ_N!@@5:`Z +M55B%4+O`N?FR+'^(*""[H#J[N(NPB,")^5(JE!O=2_]7O0*&\O])Z8(JE0P- +MO'CJXG:`+O(ND;(L?X@?(+N@.KNXB["(P(GY@BQ_^"\@B*`ZB(B(@/_`^?FR +M*I4;W4ONM[T$AO+_``#2+'\JW3K=T@W:XJ#_YQUHJ!&B*A"\^@NZH+L1LFDX +MXBQ_TJ#_*NX,`CKNTD[:'?#B+'_2H/\J[@P".N[23MH=\%KR\@]_%C\0K0(, +M&R44`!::#PQB'?``J!&B*A$6^OP+NJ"[$;)I..(L?]*@_RKN#`(Z[M).VAWP +M#`+!?@/":3@=\```MLH"AF'_H/3`()J@DME:\(`D6J)VF`>R*B.R::1+F?"# +M03WP=I@R@BHCDLD@@FF<@BHC@FF=@BHC@FF>@BHC@FF?@BHC@FF@@BHC@FFA +M@BHC@FFB@BHC@FFCLBW55OO2MLL"!F#_6J*P],`@FZ"2V5KP@"1VF`>R*B.R +M:<=+F?"#03WP=I@R@BHCDLD@@FF_@BHC@FG`@BHC@FG!@BHC@FG"@BHC@FG# +M@BHC@FG$@BHC@FG%@BHC@FG&1DK_``#"(N[":M3&#?_H$>(.V=+2`:S.\B+O +MHBW5][H;()J@DME:=H`/PBG'0DPTLB+O&ZI+F;>Z`D;Z_^(MK^)MU<8!__(B +M[_)MU8;__@``-N$`_0)AIP/BHECJTFIB%E,ZH=D#D=P#@BU_LB9",J8@4J0A+B#WP2&&HT;CQ*,%+JBN[&R(IP4HB(@(`N?&IT8+"_1;H(;9B`@:' +M`/8B,'CQB%%8<7(7`!;"#RAQ>B(;PH>L`L8V`(#"P!O,QC0`2$?'E*RB*2!2 +M)Q2G%:<&Z/]"POX61`Z(L5(A$$@!#`>'M1,H@3A!4"+`(L(!=I(&*`,RP_PI +M(T($22(A`7:4"8(FN1MW%O@%2R*")KRB)KRXL4B1AYH"1M?_PB$06*&HX8)D +M@$M$29%+JDM5&\S"81!9H:GAQ[L"!L__J#&X@2CAH(R@P+O`*[NJ(B+2_G:; +M$7(B@$LBC'=")Q2L%'D(2X@]\$;$_P``@B)_B&BB*!462OFR+6NH"+>:C(;C +M_P``0BD@R`?P1*#J1$(D84<"@9`#N-%Z?XIW0@<+PB:\ +MN`MVE"FB)R2""A1+=ZR.!V@+*'I"`C6,-%A2MQ4R%V@+*(J"`C6,.*A2MQHL +M/?#BHEA]#,8)````9CCP*&I"`C46A/Y84K>5XWT"XJ)81@,`?0+BHEA&`0`` +M?0+BHEA(X5(A$*BQ@B$0&U5281"GN!(H@3A!@"+`&R)VD@8H`S+#_"DCJ*%+ +M1(B12>%(L7)H@$NJJ:%+B(F15[0"1H#_2#&H@2CA0(6@4*K`*ZI*(B+2_G:: +M(7(B@$LBQQ<70@`Z(M?H(F0C*E(%*GK%I2.C)")D(+JKJR +MRL+),;EAJ8&&%?^B+6ZI49(MG9DA1AC_````-F$`63&!WP-1X`.=`G!8@R82 +M668B5*8440P".2%)`3`TH`P$F`&7)`)&0P!X(7!TH(8X`!LB2WX!L@QJ'H;F\"[H*)K`))F`-@!UR*]Z`'G),`= +M\*84^@P"F1$Y(4D!,#2@#`3X`?>B-7@A<'*@A@$`&R)+=S<7)K(G`((+$SWP +M!VCMJ'O@!0`66OX;(J@'N`;(,:AZ&YO`NZ"I"Y)F`-@!UZ0R>"%P=*"&`0`; +M1$MW-Q""Q,7:/"HB^`%`!:*_AM$J`>X!L@QJ(H;F\"[H*D+DF8`V`'7 +M(HS7)(3X$?+/_E:O]M>B`D;'_]>D`L;'_\;6_P`;1$MW-QB"Q,7:O"H +MB^`%`!:*_AM$R`?8!N@QR(P;O>#=H,D-N0;X`?Y41;**"K'R3'2!LOX40P.TLW_%NTCXF$"HB]#D@;0@@;/HBH1 +M<(@1D*H1H)D@D(@@D60#R%&)J?(O0^'*`XD!\B\1#`F"(0067P"R!LLF&Q3" +M+$/"+!/`Q006#!/2!LO2S?X6?1)!Y`-1Y0/X4:(&R](HI8(HIO(O0PNJB1'R +M+Q&"H`&@F(/RS_X6#RWJE_%D`TP:(>(#J=\Y[S'C`W:=38*9'J*9'[*9(,*9 +MWM*9W^*9X&N9@("$<*H1X+L!P,"$<-T1X.X!,(@04*H00+L0,,P04-T00.X0 +M@(H@P*T@((@0(*H0@(L@H*X@B?^I_R'B`S'C`T'D`U'E`Y',`_%D`TP*B!&I +M[Y"7@':838*9'J*9'[*9(,*9WM*9W^*9X&N9@("$<*H1X+L!P,"$<-T1X.X! +M,(@04*H00+L0,,P04-T00.X0@(H@P*T@((@0(*H0@(L@H*X@B?^I_\A!Z%'R +M+.+"+.'B+D/`_Q'2!M"R!L_PS!'B+A'PS"!PNQ&0[A'@W2#0NR#`NR#!9`.Y +MK(@QZ%&R*):B+D22H21PNZ"H&IJ[LBO#\60#L*K`HF\0@BB6XBY$<(B@Z"Z: +MB((HPX#NP.)O$=(&RV8=5,@AJ`&X[/(,-=C\L.D$T/\1\*H@L+`$X.X1X-T@ +MP+L1T+L@T60#Z#&PJB"B;122+I;RI"2(''"9H/J9F#F0B,"";1+B+I;(+'#N +MH/KNZ#[@S,#";1/H07S]TF[`P@;E#`CX08Q,@D]R'?``L@;0F$$,&K"*@X)) +M(DA%F[;J%&8^*(JN:"9P!:9 +MVKCHL+D$%AO:V%'"*!#2+;F2*!$+W="<@Q:I&Y")((DAAF'_B$$R2'-"!NKR +M!M"@1!$6GQ>B%EBR!NP]\/"J$27G$:)&[\A1T:8#XBR[D>8#PBR[X@X&FI?" +M#`=`[A'@Y"`PS!'@S"#A9`/0S"#":8#":83":8/";D+2!L7X48%C`W#=$=#< +M(-DNPFA"L@;J*L?),0N[%EL2X@;JTJ!@HJ"`X*V#\B]"\@\]\L^^%E\1#!ZR +M!LCX40P-<+N@\B^Y*KO"%EWRS_[PWH/0S(*R*VG`RH)"*7K`P4'*N[I$0FA. +MD@;ODFA&P"``1BO_````%KG2J$$,6?@1+`+PW1$@W6/PCQ&2:N&2:N(@^&/Y +M$19M!.J'!VT3(E@@(E@?(E@>,EC@,EC?,EC>:XC0L4$]\':;)2)8(")8'R)8 +M'C)8X#)8WS)8WB)8(R)8(B)8(3)8XS)8XC)8X,EC@,EC?,EC>:XB0L4$]\':;)2)8(")8'R)8'C)8X#)8WS)8 +MWB)8(R)8(B)8(3)8XS)8XC)8X:QAWP`.@7(/F@^`_H#O@/]Z[)G0@&\?\`:!<@6:!8 +M!6@&6`5GI;6="`;L_P#H%R!IH&@&Z%YH5N>FH9T(!N?_`.@7(/F@^`_H3OA/ +M]ZZ-G0@&XO\`-D$`IB-"#`H+TWT"#!@,":##P`N\=JL/)B1L)C15)F0^)G0G +M&XA+=QNJEQL2(&R@((F@6`ABUOYR)G]Y"%)F?WT"#!@,"=>:QAWP`.@7(/F@ +M^`_H+O@O]Z[)G0@&\?\`:!<@6:!8!6@F6"5GI;6="`;L_P#H%R!IH&@&Z!YH +M%N>FH9T(!N?_`.@7(/F@^`_H#O@/]ZZ-G0@&XO\`-H$`#`QAE@/RH_!2HDQJ +M8D(F?S(F?^(F?R!$L"`SL%I$0B1H(.ZP6C,R(VGZ[LD.TB9_(-VP6MW";6BB +M)G\@JJ!:JJ(JBEI2LB5Q&ZKEK!&RI&I]"I(EH$DA.1&0BL`6:!:Z0J'6`S&L +M`YD!JJ*I,0P)XB9_'`S2!((J[KKNTDZ`=JP37(_P^8+Z\CK_\B]_IV\'.YF0 +MD'22H/^21(BB!(C"H/_`JL`6VA2B!(B2!(BRI`!<##`KZ\HK_Y1/[J4%Y2GEZ +MPJ$`\J(`Z.H,'8*@_X)*--)*-O#N(,"^(+GJ;/S`NQ"YZJ@QD# +ML60#D6,#P60##`JB:8"B:<"I#*)K0()I@AWP```V00!]`B@#G"1\]@M%6B)@ +M1#`+(D`B$'I"20,=\'J"B0,=\``V00`,!4*@_S&O`V'J`X8&``RHG04;59>X +M`H8H```VIJ`0IJ"@=*+*@!;Z"``SIK`0I@P,L-!TL+!T1YL6=H`0`#.FX!"F +M&\S@T'3@X'1'G@(&^O\`,Z:P$*8,"K"P=$>;%7:`#0`SIK`0IANJL+!T1YL$ +MQOK_``"`ZA&@[L#JNX"L$1P^P*K`JJWGN@_QZP.![`/P^J#X#XK_H`\`YAL" +M1MO_/?!V@`\`,Z:`$*8+N^8;`H;6_SWPQOG_``P"'?`,$AWPYAL"AM'_=H`/ +M`#.FD!"F"[OF&P)&S?\]\$;Z_^8;`H;*_W:`#P`SIJ`0I@N[YAL"1L;_/?!& +M^O_F&P*&P_]V@`\`,Z;`$*8+N^8;`D:__SWP1OK_YAL"AKS_=H`/`#.FT!"F +M"[OF&P)&N/\]\$;Z_^8;`H:U_W:`#P`SIN`0I@N[YAL"1K'_/?!&^O_F&P*& +MKO]V@`\`,Z;P$*8+N^8;`D:J_SWP1OK_YAL"AJ?_=H`/`#.F@!"F"[OF&P)& +MH_\]\$;Z_^8;`H:@_W:`#P`SII`0I@N[YAL"1IS_/?!&^O_F&P*&F?]V@`\` +M,Z:@$*8+N^8;`D:5_SWP1OK_YAL"AI+_=H`/`#.FP!"F"[OF&P)&CO\]\$;Z +M_^8;`H:+_W:`#P`SIM`0I@N[YAL"1H?_/?!&^O_F&P*&A/]V@`\`,Z;@$*8+ +MN^8;`D:`_SWP1OK_YAL"AGW_=H`/`#.F\!"F"[OF&P)&>?\]\$;Z_ZT"90D` +M!G;_````YAL"QG/_=H`/`#.F@!"F"[OF&P*&;_\]\$;Z_^8;`L9L_W:`#P`S +MII`0I@N[YAL"AFC_/?!&^O_F&P+&9?]V@`\`,Z:@$*8+N^8;`H9A_SWP1OK_ +MYAL"QE[_=H`/`#.FP!"F"[OF&P*&6O\]\$;Z_^8;`L97_W:`#P`SIM`0I@N[ +MYAL"AE/_/?!&^O\`-D$`70,QKP,`,Z9`$*8,!V*D<&IB@(X4B7&"8Q^"!.98D6BA%G@%@@3I^3$6B&`,']DAR1$F/@;8 +M40P,T/R3B#$,'B8X!MA!#`S0[).((0P=)C@&B&$,#(#\90``#,N0PMTD3TI9+_/#JQ_0,,O@`^IM(CQ\(CJ]K, +MEHQ"QZI'+'W&$0#R(E*VSP)&]`""(Q*"R.$66&.B(Q*BROI6R@H,S=)C$K($ +MYA9;#(*A`@`XIO`0IO)#C.(#C!8^"\)C%`SIDF,2!BH`NMS2#0#B(\C"(ZOJ +MS)8\/<S^0BC^1*294R"(ZWR(^`@B*#R:&<=\-(C$N+;`=+-^=#20>#= +MH-@-V4/"(Q(,VL+,^<#`%,)#F:)C$JT"Y3\!@B.MHB.LD@.7H_@(D_@2@F5, +M\B.MXB/@(/^@XF]G'?````#!_0/*N[(+`-(CR,(CJ]K,E@Q$QZH%+'P&`@`` +MT?T#VLS"#`"180/B(R""!-WR`XR:[H/^%//^&>)F5M(D0)CSHB.KVIFC^02A +M``2S^0K#^1"29E62(ZV"(ZSR`Y?H,X/Y"//Y$7K9JIGC_12M`M)FR0Q.F<6= +M`HASB<7XL_)E#':N(L@IN!G`P-2PL.3#^P^YQ;(J7$NJ%HL`)AMK)BM6)CLC +MDLD@@B.MHB.LD@.7H_@(D_@2@F5,\B.MXB/@(/^@XF]G'?``R$FX.<#`U+"P +MY,/[#[G%B&GX68"`U/#PY(/_#_G%Z(G8>>#@U-#0Y./]#]G%QNK_Z$G8.>#@ +MU-#0Y./]#]G%1N;_B&GX68"`U/#PY(/_#_G%QN'_`#VFHF.MDF.LP!"FPF/) +M1O#^````/:9\^)GSTD.2@F/)\!"F\F,3XB,3&^[B8Q(&[_ZZG(&Q`\(C(/($ +MW>(#C(K,\_P4X_P9PF96LB1`B/.B(ZN2"0"ZB*/X!*'_`]/X"I/X$()F58(C +MK?(CK.(#E\@S\_@(X_@1>KBJB,/[%+)FR8G%PB.M\B.LX@.7\_P(X_P2PF5, +MLB.MHB/@(+N@HFMG'?"R)"S"(E/@HH"B80##^P@`.Z:0$*:2:A6M`F6#!@P: +MO0+EJ`:H`;@4PBJ@RKN6RRD\/;>M!BQ\1@(```#!_0/*R\(,`-(JH+@DVKN6 +M.R@\/K>N!"QYQ@$`D?T#FIN2"0""*A7H>M($W;(*8./X%=/X%+/X&8)F5O(J +M^]A*XBJ@^MWC_03A``3#_0J3_1#29E7R*J*R*J&2"FN"(D.S_PB3_Q'J[WK_ +M@_\4\F;)Z<72(D?9Q;(B2[G%J!*8(K(B4J"@Y)"0U`N[%ELH\B)2\L_^%D\@ +MD_H/J<6(HOB2@(#4\/#D@_\/^<7"(ZWB(ZS2`Y?C_`C3_!+"94RR(ZV"(^`@ +MNZ"":V<=\`#"1//"8E+28E.R)"S"(E/@HH"B80##^P@`.Z;22F>0$*:2:A6M +M`B5R!@P:O0*EEP:H`;@4PBJ@RKN6FQP\/;>M>BQ\1A\`#`U&"/\`@;$#PB,@ +M\@3=X@.,BLSS_!3C_!G"9E:R)$"(\Z(CJPP)NHBC^`2A_P/3^`J3^!""9E6" +M(ZWR(ZSB`Y?(,_/X"./X$7JXJHC#^Q2R9LF)Q<(CK?(CK.(#E_/\"./\$L)E +M3+(CK:(CX""[H*)K9QWP`,']`\K+P@P`TBJ@N"3:NY;;$SP^MZX$+'G&`0"1 +M_0.:FY()`((J%>AZT@3=L@I@X_@5T_@4L_@9@F96\BK[V$KB*J#ZW>/]!.$` +M!,/]"I/]$-)F5?(JHK(JH9(*:X(B0[/_")/_$>KO>O^#_Q3R9LGIQ=(B1]G% +MLB)+N<6H$I@BLB)2H*#DD)#4"[L6&Q7R(E+RS_X6WPN3^@^IQ8BB^)*`@-3P +M\.2#_P_YQ<(CK>(CK-(#E^/\"-/\$L)E3+(CK8(CX""[H()K9QWP``P+QNS^ +M#`R&\O[H80P,B'$,'PP-@-^#X,^#T,P0V%$,"8A!T)^#T@.*#`Z`[X/@W1#0 +MF1#`F1"20XK&A/X,#$9<_PP)!F+_`)/Z#ZG%LB(2@B(1L+#4@(#DL_@/B<72 +M(ZWR(ZSB`Y?S_0CC_1+294S"(ZVR(^`@S*"R;&<=\`P,!J[_``P)AK/_D_H/ +MJ<7"(A*R(A'`P-2PL.3#^P^YQ>(CK8(CK/(#EX/^"//^$N)E3-(CK<(CX"#= +MH,)M9QWP`)/Z#ZG%\B.MLB.L@@.7L_\(@_\2\F5,XB.MTB/@(.Z@TFYG'?`@ +MHB#"H`_"8Q+E;0+R(ZV2(ZR"`Y>3_PB#_Q+R94SB(ZW2(^`@[J#2;F>0```` +M`)/Z#ZG%TB.M\B.LX@.7\_T(X_T2TF5,PB.MLB/@(,R@LFQG'?`````V00!2 +MH1A:0J($?S*D'#HR&ZJB1'^2`_2"!'^7F`6"H`""1'^R)-:RRP&R9-:B)-:2 +M$V"@F<`6.0CB(QCBS@'B8QC2(QC"$V#7''BA>`.Q8P-V@!*"!'_R*TT+JH=? +M"HR:D@/P)BD,AOG_S&H,*J)#\*4?_PQ]TF3-DB3-PB39#!L,"L"K@Z/Y#Y)D +MS?(DS8($?X/_$?)DS>(DI](DS2#NH%KNXBXCX_T4TF3-P!"FL@/OS#OB`_"< +M'@PR'?#P$*8,(AWP(!"F##(=\``,60`YIH`0IIP8H@/3)BH(N".F&P,,`AWP +M##(=\`P"'?`````V@0`RT@&"(],`.*8,#D*DA$I"D@1QXF,4DD.+XD.,Z4.P +M$*:"(\FPH72PF70;B!:8'Z)B[9)B[*(CR;"1Y0P?%LH?F?.R(\D+N[)CR?)# +MDN)C$^)C$@S+T@1ZTD.*PB,2860#'&7'M5Z2(Q(L^)9`D:*`H(C$@PK%G@PDB)2/`ZV20)&0@#R8E*R +M)>?(AS^0BC^1*29DR"(ZWR(^`@B*#R:&<=\((B4H>^#/)$ +MA_)B4O)B4X:Y_P"2(E*0D`16Z5>R8E*&M?\``#ZFHF.MDF.LP!"FPF/)1G[_ +M````/J9\^IGSXD.2HF/)@!"F@F,2TB,2TF,31G[_#(NR8Q(`/J:0$*:28Q0` +M/J:P$*:"H`P]\+>X!/)$APP+LF,5`#ZF@J`,M[@"\D2'L!"FLF,6`#ZF#,FW +MN0+R1(>`$*:"8Q>2(_*R(Q/B(Q52(Q2S^0BR(Q93^1#C^12S^1B#^1P`.:8, +MQ8>U`O)$ARE1(!"F(F,@XB,@LB,@DB,@4B,@X.`4XF,8@B,@L+(4LF,9(B,@ +MD)04DF,:\B,@4%844F,;@(@4@F,BDQ*%$6&`6"!'WY$18H>PP?Z0$F.P;H,0P+X/N3B`$,'B8X!H@A#`N` +MZY,,&R8Y!HA!#`F`N9,,&28U"H@1*5$,`H"2DRA14@.*D(L04%X04%\0@%40 +M4D.*K0*E3@4,&KT"Y28&LB/'HB.KNJJ6&FT\/*C^`B3^!*"9DSR(ZWB(^`@_Z#B;V<=\`#R(_*2 +M(Q."`Y*3_PB#_P\`/Z:0$*:28R#B8Q*"!'V"0XKR(\F6[W^1>`,+F>(G@Q8N +M7!8I7/($B`N99B_N#+@`.*;B(\>R(ZOJNY9K8KK"PU("`Y+/X#XG&XBHHTBHGX.#4T-#DX_T/V<8&U/\`LBHB@BHAL+#4 +M@(#DL_@/B<;B*B32*B/@X-30T.3C_0_9QL(J)K(J)<#`U+"PY,/[#[G&@BHH +MXBHG@(#4X.#D@_X/Z<8&PO\`Z"K8&N#@U-#0Y./]#]G&R$JX.L#`U+"PY,/[ +M#[G&B&KH6H"`U.#@Y(/^#^G&V(K(>M#0U,#`Y-/\#\G&!K+_`+(I6!8K!R8; +M2H++_E:(Z]@JR!K0T-3`P.33_`_)QK(J(H(J(;"PU("`Y+/X#XG&Z$K8.N#@ +MU-#0Y./]#]G&PBHDLBHCP,#4L+#DP_L/N<9&G?\``,(J(K(J(<#`U+"PY,/[ +M#[G&@BHDXBHC@(#4X.#D@_X/Z<:&D_^X*H@:L+#4@(#DL_@/B<;H2M@ZX.#4 +MT-#DX_T/V<9&B_\``+(I6!8K!R8;2L++_E;,X8@JZ!J`@-3@X.2#_@_IQM(J +M(L(J(=#0U,#`Y-/\#\G&N&J(6K"PU("`Y+/X#XG&XBHFTBHEX.#4T-#DX_T/ +MV<9&=O\``.(J(M(J(>#@U-#0Y./]#]G&PBHFLBHEP,#4L+#DP_L/N<:&;/_8 +M*L@:T-#4P,#DT_P/R<:X:HA:L+#4@(#DL_@/B<9&9/\``+(I6+SK)ALHXLO^ +M5A[8V"K(&M#0U,#`Y-/\#\G&LBHB@BHAL+#4@(#DL_@/B<:&5_^"*B+B*B&` +M@-3@X.2#_@_IQH92_\@JN!K`P-2PL.3#^P^YQ@9._P`,/N)B4D95_A99"POY +M%C\Y@LG^5I@+R"*X$L#`U+"PY,/[#[G&HB(BDB(AH*#4D)#DH_D/F<:&)0#: +MZ^(.`/(CR+(CJ_J[EGLHMRP"1F(`DB,@T@.2P@1QL@.,T_D:P_D4L_D9DF=6 +M@B0E^/.2(ZN*_Y/_!"QXX_\*@_\0@0($\F=5\B.MTB.LP@.7N#/3_PC#_Q&J +MGXK_L_D4DF?)^<:R(ZW2(ZS"`Y?3^PC#^Q*R9DR2(ZV"(^`@F:"":6<=\``` +M^"+H$O#PU.#@Y//^#^G&DB):%BDT"XD6"#>BR?Y6.I:R(A*B(A&PL-2@H.2S +M^@^IQI(B,H(B,9"0U("`Y)/X#XG&TB.M\B.LX@.7\_T(X_T2TF9,PB.MLB/@ +M(,R@LFQG'?``V"+($M#0U,#`Y-/\#\G&AC[^Z*+8DN#@U-#0Y./]#]G&PB(J +MLB(IP,#4L+#DP_L/N<:"(ZVB(ZR2`Y>C^`B3^!*"9DSR(ZWB(^`@_Z#B;V<= +M\```@B(B\B(A@(#4\/#D@_\/^<8&*?ZR8Q*2!'K,&0;9_<*A`@`\IK`0IK)# +MC*(#C,P:!M3]\F,4#.W28Q)&T?V8(H@2D)#4@(#DD_@/B<;R(B+B(B'P\-3@ +MX.3S_@_IQL85_H(C(/(#DL($<9(#C//X&L/X%)/X&8)G5O(D)#`GPGH.PCH.X,9"($)@AL%Z##`N0OH.2`XJP +MF1"051"`51!20XI&&?X@HB#"H`_"8E+B8D3EIP'R(ZV2(ZR"`Y>3_PB#_Q+R +M9DSB(ZW2(^`@[J#2;F>0`````+(B(J(B(;"PU*"@Y+/Z#ZG&QD7_V"+($M#0 +MU,#`Y-/\#\G&DB.MLB.LH@.7L_D(H_D2DF9,@B.M\B/@((B@\FAG'?``PB(B +MLB(AP,#4L+#DP_L/N<:"(ZVB(ZR2`Y>C^`B3^!*"9DSR(ZWB(^`@_Z#B;V<= +M\+(B$J(B$;"PU*"@Y+/Z#ZG&\B.MDB.L@@.7D_\(@_\2\F9,XB.MTB/@(.Z@ +MTFYG'?```*(B,I(B,:"@U)"0Y*/Y#YG&XB.M@B.L\@.7@_X(\_X2XF9,TB.M +MPB/@(-V@PFUG'?``HJ`!(+(@I9P%H3@#PJ`ST?T#A@'^`#9!`$*D+$I".(0` +M,Z8,#C+2`?($R?)#B^)C%.)#C.E#T!"F`#ZFT+'ET,ETXD.2T-%TTF.MPF.L +MN?.@$*8,^PS]2Z)$W\)C$H(C$H)C$Y($THRI +MHD.*PB,29JP"AB$`TB,2MQU8K0*E"@""(ZVR(ZRB`Y>19`.S^`BC^!*":4SR +M(ZWB)!4@_Z#B;V<=\`#B(Q(67@?R(Q+7'VB2(Q+1`00+F9"20="9H)@)F4." +M(Q(+B("`%()#F<)C$@;D_P"M`F6)`<(CK?(CK.(#E]%D`_/\"./\$L)M3+(C +MK:(D%2"[H*)K9QWPPJ$"`#RFD!"FDD.,@@.,#.T62/:B8Q328Q+&UO^R8Q(& +MT?\`#,[B8Q+&SO\V80`RT@'"(_+B(E/2(E3C_`C3_!``/*:P$*:B`YD,JX"J +M$;"J(``ZII`0IH(CSPP*%O@+`#JF\!"F^3.(,T*D@$!"@+9(!8*@`8)$BY(C +M$I+)\Q8I"B"R(**@`*6#!=(CQ^(CJZ(CJ\']`[*@,]JJTB/(EMH(IZL$+'X& +M`0#*ZN(.`*(CJPP)VJJ6N@>GJP0L>08!`,J:D@D`LB,@\@1UTB,2P@.,\_L4 +M\6,#T_L5P_L9LF]6HB0FV/."(ZNJW8/]!./]"I/]$-)O5=$X`Z(CK<(CK+(# +MEX@SP_H(L_H1P0,$L60#VMJ#_132;\G*JJG+'?``J3.&T/^M`F7?!4;7_P`` +M``P.1M[_1N/_-H$`#`R"(D(RT@$,?H+(_A8(19(#E1;Y0[(#C;)#BZ(B1IT, +M#`06:D\,&PP*D_X*\@.+TB/?D@.5\_X+@@.7\B.MT*N#H_X/(/^@\B]ID_X0 +M@_X1\_X4`#ZFPF,4PD.,R4.0$*;2(\F0L720J70;W1;-.[)CK:)CK`P>@B/) +M\J$"D*'E%@@UTB/)"]W28\GB0Y+"8Q/"8Q*I\[(CR18[.I"`!()#B[']`V%C +M`T%D`U*D&%!2@*(%YJ)#BI(C$G$X`Z*@,Q:9.H(B4M*@"+9("((B4O;(`H9? +M`/(B4K;/".)%\^)C$L)C$X(B4_(#BX/]"//]#@`]IN(B[.)B4,(B[<)B48(# +MBQ8(`N(CKO#N$>)CKM(CK_#=$=)CK\(#E1:,`/(CK/+/__)C$(`0IJT"@F)@ +MI3\%#!J]`B5E!<(BZ[@5/#K*NY:+1;>J!"Q\Q@$`P?T#RLO"#`#2(NNX)=J[ +MECM$MZH&+'E&`@```)']`YJ;D@D`TB)@@@.+\B)2X@.,@_T4\_T5X_T9TF96 +MLB)/@B5`HB+KNHBC^`3#^`J3^!""9E6!``3B(NWR`Y72`Y>R(E"B(D/S_A#3 +M_A%ZGK/Y"*/Y%))FR?(B[(KN\_X(Z<32(D?9Q+(B2[G$J!*8(K(B4J"@Y)"0 +MU`N[%HL]LB)2LLO^%FL[D_H/J<38HLB2T-#4P,#DT_P/R<3R(Q&B(Q"2`Y6" +M`Y>C_PB3_Q"#_Q+R9$SB`XL6KAZ2(NZ0D4&28NZ"(N^`@4&"8N_X0_E3XB,2 +MZ6/2`XO20XW"(Q&R(^`@S*"R;&<=\```@B,2MF@"QI\`DB,2@J`!\J``DLG[ +MD/B#\D.4TF,2`#RFD!"FDF,4`#RFMDD"XD7S\!"F\F,5`#RFMD\"XD7S@!"F +M@F,6`#RFMD@"XD7SD!"FDF,7\B,3P@.+@B,4\_T(P_T.\B,5PB,6@_T0\_T4 +MP_T8D_T<`#VF@B.L@F,0\B.M\F,1P@.+G-S2(Z[PW1'28Z["(Z_PS!'"8Z^" +M`Y6,:/(CK`O_\F,0MDD"XD7S*5'P$*;R8R#2(R#"(R"2(R#R(R#0T!328QB" +M(R#`PA3"8QDB(R"0E!228QKB(R#P]A3R8QN`B!2"8QR)(>#L%.E!XF,>XB,@ +M("H4(F,=X.X4XF,?@@7F*3$H41;X!((%Z>D1%E@\#![9`28\!M@Q#`S0[).( +M`0P=)C@&B"$,#(#(CK`ONXF,0\!"FD7@#\F,@ +M"YF")H,6:"(6:2+"!?0+F68L[@R^`#ZFTB/'PB.KVLR6["''JDLL?<82`((C +M$H+(X1:X)Z(C$J+*^A;J(.(C$O+;`>+.^>#B0?#NH.@.Z4/2(Q+"H`W2S?G0 +MT!320YG"8Q*M`J4+`08Z_PP9#!1&P/X`NMS2#0#B(\C"(ZOJS)9,',>J!"QY +M!@$`NIR2"0#QL0.R(R#B`XO"`XSZN^/[%,/[&;)F5J(E0/CS@B.KP?\#JO^# +M_P33_PJ3_Q#R9E6B(ZWB`Y6R`Y>"(Q#X,^/Z$+/Z$7KJ@_X(\_X4XF;)LB.L +MRJJS^@BIQ,89_PP,1NS^#`D&\OX`D_H/J<2R(A*"(A&PL-2`@.2S^`^)Q,80 +M_Y/Z#ZG$Q@[_L?T#NKJR"P#"(\BB(ZO*JI;*%#P]IZT'+'J&`@````#!_0/* +MJJ(*`.%A`Y(C(-(#B\(#C.J9T_D4P_D9DF96@B5`Z//R(ZN*[O/^!+/^"J/^ +M$.)F59(CK=(#E<(#EX(C$-/Y$/@ST0`$P_D1>NF#_@CS_A3B9LG"(ZP,3MJ9 +MP_D(F<2(86JN``/Z;0$*;20XS"`XP6O-_B8Q0,[_)C$@9\_P`,"\:I +M_PP*AK#_#`GX00P,#!@,#>#8@_#(@_@QT,P0V"'PF(,,#]#X@](#BO#=$-"9 +M$,"9$))#B@84_P```*T"#/B"8Q)E;@)&I?X`-D$`,J$8.C*B`W^RI$BZ(J+* +M`:)#?Y("R((#?Y>8!`P(@D-_LB/6&[NR8]:B(]:2$DJG&4OHTAONZ=+2(@W" +M$DK7'$.A>`.Q8P-"H`%V@!*"`W_R*TT+JH=?"HR:D@+$)BD,AOG_S&H,*J)" +MQ"6S_<`0IK("P\P[T@+$G!T,,AWPX!"F#"(=\/`0I@PR'?``#%D`.::`$*:< +MR*("IR8J$[(CPZ8;#<(#?0P"P,3`PD-]'?``##(=\-(#?0P"T-3`TD-]'?`` +M```VH0`,#0Q_@B)"C*"R/X6J#J2`_46F3FR`^VR0^NB`_(,&0P>%AHZ +M#!L,"I/_"D(#Z\(C]Y(#]4/_"X(#]T(CQ<"K@Z/_#R!$H'I$0B1!D_\0@_\1 +M0_\4`#^FTF,LTD/LTF,(CX0ONXF/A\D/RTF,KTF,JHF,GLB/AD(`$%FLO@D/K#,Y"I!A* +M0J($YJ)#ZI(C*E%D`QQJESH"!B4`DB,J+/B7N`)&(@"B(RH<>[>:`L9Y`N(C +M*O$!!.+.Z.#B0?#NH.@.XF,C0T!320_G"8RH@HB`ER0""(RFR +M(RBB`_62`_>S^`BC^!"3^!*"94SR`^L6+R.B(NZ@H4&B8NZ2(N^0D4&28N^" +M(QR"8QWR(RKR8Q[B`^OB0^W2(RG"(_@@W:!PW8#";3^0``!A8P/BH`B"(RJA +M.`/"H#."R.H6*":"(E(\"9>8`L9;`H(C*A88=X(B4CP-AST"AF$`\D3S\F,J +M\F,KDB)3@@/KD_X(@_X.`#ZF\B+L\F)0TB+MTF)1D@/KG.GR(\;P_Q'R8\;B +M(\?P[A'B8\?2`_46?0""(\0+B()C*)`0IJT"DF)@)5D$#!J]`J76!,(BZ[@4 +M/#K*NY8;-K>J!"Q\Q@$`P?T#RLO"#`#2(NNX)-J[EMLTMZH&+'E&`@```)'] +M`YJ;D@D`TB)@H@/K@B)2\@/RX@/LH_T4@_T5\_T:X_T9TF96LB)/@B1`HB+K +MNHBC^`3#^`J3^!""9E61.`.!``3B(NWR`_72`_>R(E"B(D/S_A#3_A&:GK/Y +M"*/Y%))FR?(B[(KN\_X(Z<72(D?9Q;(B2[G%HB)2DB)8"ZH6:BRR(E*RR_X6 +M2VZLJ689`D;\`68I,?@BZ!+P\-3@X.3S_@_IQ=(B(L(B(=#0U,#`Y-/\#\G% +MA@,`F"*($I"0U("`Y)/X#XG%DB)9%KEY9AD"!O$!HLG^5EKAZ*+8DN#@U-#0 +MY./]#]G%R".X$\#`U+"PY,/[#[G%!GW_`((C*O9(8?)C*D:=_[(#]8R;@@/U +M/?`6:'86/G8`/*:0$*:20^L`/::B8R>`$*:"8RKB(RKB8RNR(^$+N[)CX=)# +M\H94_](C'-)C'<(C*L)C'K(#Z[)#[:(C*9(C^""JH'JJDFH_'?``\B,J\/`$ +M5H]?#"B"8RH&@O\`/::R8\6B8\3`$*;"8^&&-_\`X@/U5B[0DJ$#`#FF@!"F +M@D/KACW_TD/K[0T,&<8:_P"=#0P.H@/IHD/K1A?_G0T,#H85_^)C*@`]ICWP +MD!"FDF,L`#VF#,B7N`+R1/.0$*:28RT`/:8,R)>X`O)$\Y`0II)C+@`]IH*@ +M#)>X`O)$\Y`0IM(C*X(#ZSWPT_X(TB,L@_X.@B,MT_X0TB,NDF,O@_X4T_X8 +MD_X<`#ZF#,B7N`+R1/."(\2"8RCR(\7R8RGB`^N)CQM(CQ_#= +M$=)CQY(#]8QI\B/$"__R8R@I<5F!:9&0$*:28SCR(SCB(SC2(SB2(SCP\!3R +M8S`B(SC@XA3B8S%2(SC0U!328S)B(SB0EA228S."(S@@*!0B8S0I,5!:%%E! +M4F,U8&P4*'%I46)C-H".%(EA@F,W@@3F6(%HD1:(!8($Z?DA%CAE#!_9$9D! +M)CX&V$$,"=#YDX@A#!XF.`;8,0P)T.F3B!$,'28X!XA1DJ``@-F3B`$,&28X +M"HAA*7$,`H"2DRAQ@@/J@.X0D(T0X.\0@.X0XD/JK0+ER`,,&KT"):$$LB/? +MHB/#NJJ6.EP\/*>L0BQZ1A$`#`P&*O\`#`F&+_\6"5P+V18M8.+)_E:.N:@B +MF!*@H-20D.2C^0^9Q8(B(O(B(8"`U/#PY(/_#_G%1MW^``"Q_0.ZJJ(*`,(C +MX+(CP\J[EMM6/#VWK00L>\8!`,']`\J[L@L`G0+!80/B(SB"`^OR`^S*[H/^ +M%//^&>)F5M(D0((C)\(CP^T"VHC#^`2C^`JS^!""9E6"(\7R`_72`_?"(RCS +M^!"R(QOQ.`/3^!'1``3Z^,/_"+/_%/)FR<(CQ-J(#$O#^`B)Q?(C'_G%TB,C +MV<5&`@```.+.($N9%CNMHBE<"[L6^B4+VA;M&_+*_A;/$68ZX:(I6!8Z#0N* +M%F@(9BK3J"Z('J"@U("`Y*/X#XG%\BXBTBXA\/#4T-#D\_T/V<7(3J@^P,#4 +MH*#DP_H/J<6"+B3R+B.`@-3P\.2#_P_YQ=ANR%[0T-3`P.33_`_)Q:(N)H(N +M):"@U("`Y*/X#XG%^([8?O#PU-#0Y//]#]G%PBXHHBXGP,#4H*#DP_H/J<4& +MU/\`\BXBTBXA\/#4T-#D\_T/V<7"+B2B+B/`P-2@H.3#^@^IQ8(N)O(N)8"` +MU/#PY(/_#_G%TBXHPBXGT-#4P,#DT_P/R<4&PO\`R"ZH'L#`U*"@Y,/Z#ZG% +MB$[X/H"`U/#PY(/_#_G%V&[(7M#0U,#`Y-/\#\G%J(Z(?J"@U("`Y*/X#XG% +M!K+_`*(I6!8J!R8:2M+*_E:-ZZ@NB!Z@H-2`@.2C^`^)Q?(N(M(N(?#PU-#0 +MY//]#]G%R$ZH/L#`U*"@Y,/Z#ZG%@BXD\BXC@(#4\/#D@_\/^<5&G?\``((N +M(O(N(8"`U/#PY(/_#_G%TBXDPBXCT-#4P,#DT_P/R<6&D__X+M@>\/#4T-#D +M\_T/V<7(3J@^P,#4H*#DP_H/J<5&B_\``*(I6!8J!R8:2H+*_E;(X=@NR![0 +MT-3`P.33_`_)Q:(N(H(N(:"@U("`Y*/X#XG%^&[87O#PU-#0Y//]#]G%PBXF +MHBXEP,#4H*#DP_H/J<5&=O\``,(N(J(N(<#`U*"@Y,/Z#ZG%@BXF\BXE@(#4 +M\/#D@_\/^<6&;/^H+H@>H*#4@(#DH_@/B<7X;MA>\/#4T-#D\_T/V<5&9/\` +M`*(I6+SJ)AHHPLK^5AS8J"Z('J"@U("`Y*/X#XG%\BXBTBXA\/#4T-#D\_T/ +MV<6&5__2+B+"+B'0T-3`P.33_`_)Q892_X@N^!Z`@-3P\.2#_P_YQ09._P#2 +M8RKR!.GR0^JR(RN2`^N"`_*S_@B3_@Z#_@\`/J;R(\3R8RBR(\6R8RF2`^N< +M^;(CQO"[$;)CQI(CQ_"9$9)CQX(#]1:(`-(CQ-+-_])C*/`0IO)C..(CX9;> +M)I%X`PN9@B:#%A@:%AD:L@3T"YEF*^X,O0`]IM(CW[(CP]J[ECL:MZP_+'N& +M$``,/_)C*L8#_@``%AD+"XD6.""BR?Y66@OH(M@2X.#4T-#DX_T/V<7"(B*R +M(B'`P-2PL.3#^P^YQ88D`-']`]J[L@L`XB/@TB/#ZMV6/177K`0L><8!`)'] +M`YJ=D@D`TB,X@@/K\@/RX@/L@_T4\_T:X_T9TF96PB1`\B,G@B/#RO^#_P2S +M_PJ3_Q#R9E6"(\7B`_72`_?"(RCC^!#R(QO3^!'1`@2JZ,/^"//^%.)FR<(C +MQ-J(P_@(B<4&L_T``*@BF!*@H-20D.2C^0^9Q9(B6A;9$@NY%@L5)BD"AJK] +M\B(2XB(1\/#4X.#D\_X/Z<72(C+"(C'0T-3`P.33_`_)Q4:A_9BBB)*0D-2` +M@.23^`^)Q<:<_9"P!+)#Z\8F_M(B(L(B(=#0U,#`Y-/\#\G%A@O^\B(JXB(I +M\/#4X.#D\_X/Z<6&D/WB8RJ"!.;,&$:,_0`\IJ`0IJ)#[)(#[,P9!HC]\F,L +M#.NR8RI&A?VM`@S\PF)2TF)$);(!QH+]`%99Y@PMTD3T)?W\H3@#/#Q&E?\, +M"H:A_@P+AJ?^#`M&J/\`#`F&K?_X(N@2\/#4X.#D\_X/Z<4&=/T`V%$,"?AA +M#!X,"_"^@]">@["9$+A!#`CX,;".@[(#Z@P-\-Z#T+L0L(@0D(@0@D/J1G+^ +M`)(B(H(B(9"0U("`Y)/X#XG%QF']LB(2HB(1L+#4H*#DL_H/J<7&7/W2(B+" +M(B'0T-3`P.33_`_)Q<:H__(B,N(B,?#PU.#@Y//^#^G%QE+]``"BH`$@LB"E +M.`2A.`/"H#.&9O\V00`,"S+2`0P?#'6"(D)"I$1*0H+(_A98%Y(#E0P:%ED6 +MT@.-TD.+PB)&G0O`FH,,#9/U"H(#B^CDP@.5H@.7@_4+@B.MX-^#T_4/((B@ +M@BAIP_40H_41@_44`#6FLF,4LD.,N4.@$*:R0Y+B`Y52H0*@D`06O@^20XL` +M.Z:@D>6@N72@P73"8ZVR8ZR9\X`0I@SZ@F,2XB,2XF,3TB,2#-L\?/)$ +MQ[)C$M(C$M)C$^($NHRN\D.*@B,2@LCT%G@-DB,2H)G`%BD+(*(@90\`P60# +MLB,1\B,0X@.5T@.7\_L(X_L0T_L2LFQ,H@.+%AH&XB.NX.%!XF.NTB.OT-%! +MTF.OPB,$PF,%LB,2N6.B`XNB0XV2(Q&(]""9H()I9QWP@B,2%C@)DB,2X0$$ +MQYD"1B``TB,2"]W0TD'@W:#8#=E#PB,2"\S`P!3"0YFR8Q(&U_^H0ZE3DB,2 +MF6."`XN"0XWR(Q'H]"#_H.)O9QWP````-:;`$*;"0XN&OO^M`F6,`8;2_[)# +MBPP9QJ?_G0O2`XG20XL&I?\``#6F@!"F@D.,X@.,#.D6;O'R8Q228Q)&P_\` +M`*)C$@:]_PS+LF,2!KO_```V00#"(E0,B_(B4S+2`>(#B](#DO/["./[#M/[ +M#\/[$``[IJ(CK*)C$)(CK9)C$8(#BYSHHB.N\*H1HF.NDB.O\)D1DF.O@@.5 +MC'BR(ZRRR_^R8Q"@$*:2`YD,JH"9$:"9(``YIH`0ID*D%$I"R*0,"1;\#``Y +MIK`0IKDSPB,#TJ`!MDP"TD3WXB,2XL[S%GX+#`J]`B42!,(CJZ@DT?T#/#O* +MJL+2"I::"J>K!"QZ!@$`VJJB"@#"+"W"##WBH&3GG!CB(\C"(ZL,">K,E@P) +MQRL"AB``+'F&````G0K!8P/2(R""`XOR(Q+B`XR#_13S_17C_1G2;%:R)$'X +M\X(CJ[K_L3@#@_\$H_\*D_\0\FQ5\B.MX@.5@0,$T@.7X_\0XB,0T_\1NK_8 +M,XK_X_L(T_L4LFS)LB.L@60#L_\(^<@=\`"9,X;,_ZT"96P$AM'_````#`I& +MU__:G)()``;?_T;>_S9!`$*@[$I"HB3WLB)3L_H(`#JFD!"F@B3.,6,#DJ2$ +MUL@"D"*`D7@#=H`.@B.#"YF,F(R9H@*()BH,AOK_S&D,*[)"B&6Y_`R\`#RF +M1@``FB*1!03B)"6"`G'R!*":[H/^%($X`_/^&>)C5M(B)<(D%/$&!.%D`]K, +MPF-5TB2RLB2QH@2KF(2S_0BC_1&*C?K=D_@4@F/)V)C5M(B)<(D%/$&!.%D`]K,PF-5TB2RLB2QH@2KF(2S_0BC_1&*C?K= +MD_@4@F/)V70R730T7328ZW"8ZRY\Z`0I@S[#-RB8Q*2(Q*28Q."(Q(< +MG:*@`8>]3*)$W\)C$H(C$H)C$Y($THRIHD.*PB,29JP"QB$`TB,2/?"W'5>M +M`J4*`((CK;(CK*(#EY%D`[/X"*/X$H)I3/(CK>(D%2#_H.)O9QWPXB,2%CX' +M\B,2UQ]GDB,2T0$$"YF0DD'0F:"8"9E#@B,2"XB`@!2"0YG"8Q+&X_\`K0+E +MZ/_"(ZWR(ZSB`Y?19`/S_`CC_!+";4RR(ZVB)!4@NZ"B:V<=\!Q\`#RFD!"F +MDD.,@@.,#.T62/:B8Q328Q+&UO^R8Q(&T?\,SN)C$@;/_P``-D$`,M(!PB/R +MXB)3TB)4X_P(T_P0`#RFL!"FH@.9#*N`JA&PJB``.J:0$*:"(\\6N`L<:``X +MIO`0IODSF#-"I(!*0K9)!8*@`8)$BY(C$I+)\Q;Y"2"B(*4I!-']`[(CQZ(C +MJ\*@,^(CR+"J@);Z"*>L!"Q[!@$`VKJR"P"B(ZL,">JJEMH'IZP%+'E&`0`` +MVIJ2"0#"(R#R!'7B(Q+2`XSS_!3Q8P/C_!73_!G";U:B)";H\X(CJZKN@_X$ +ML_X*D_X0XF]5X3@#HB.MTB.LP@.7B#/3^@C#^A'1`P3!9`/JZH/^%.)OR=JJ +MJ6B +M8D^0$*:21F:"!F8RT@$6"#_28Q+28Q/28\GQ_0-18P-Q9`,,',)&7H(B4J$X +M`SP[[,CA_@/2(_+JW0`]IL`0II%X`\)C(':`$X(E@PN9%B@8%AD8P@3TPLS^ +M%HP81OG_XB,2]DX"A@D!@B)2MF@"1F,`'!WB(Q(,B0P(XL[[X(R#@D.4DF,2 +M`#VFX!"FXF,4`#VFMDX"PD3S@!"F@F,5`#VFMD@"PD3SX!"FXF,6`#VFMDX" +MPD3S@!"FTB,3X@.+T_D(X_D.T@.2XB,4T_D/X_D0XB,5TB,6@F,7X_D4T_D8 +M@_D<`#FFMD@"PD3S(F$'4F$(:9&0$*:28R#B(R#2(R#"(R"2(R#@X!3B8Q@B +M(R#0TA328QE2(R#`Q!3"8QIB(R"0EA228QN"(R`@*!0B8QPI,5!:%%E!4F,= +M8&P4*'%I46)C'H".%(EA@F,?@@3F6(%HD1:H!8($Z>DA%JA8#![)$9D!)CT' +MR$&2H`#`Z9.((0P=)C@&R#$,"<#9DX@1#!PF.`:(40P)@,F3B`$,&28X"HAA +M*7$,`H"2DRAQ@@.*/?"`W1"0C!#0WA"`W1#20XJM`J6U`JT"9?\#PB/'HB.K +M/#O*JI9J4:K2"Q]!A(```""(Q*"R.$6R%GB(E*VS@*&V0""(Q*"R/I6R`H, +MRJ)C$I($YA99#!Q^`#ZFT!"FTD.,L@.,%DL+PF,4#._R8Q)&*@#ZW-(-`.(C +MR,(CJ^K,EEPVQRL"!G$`P;$#@B,@L@3=D@.,RHBS^!23^!F"95;R)$#H\X(C +MJ_KN@_X$+'_3_@KS_A#Q_P/B957B(ZW"(ZRR`Y>8,\/^"+/^$:J.^NZ3^!2" +M9+.^>#@%.)#F=)C$JT"Y;S_LB+MTB+LP@9KT_L( +MP_L2LF=,HB+MDB;5(*J@DFIG'?#1_0/:S,(,`-%A`X(C(+($W9(#C-J(L_@4 +MD_@9@F56\B1`V//B(ZOZW>/]!/$X`^$`!*/]"L/]$-)E5=(CK;(CK)(#EX@S +ML_T(D_T1^OV#_Q3JW0Q(\F7)V<>X<[G'F+.]`I)G#""2(':H$Z(I7$N9%GH% +M)AI()BHY)CHBLLL@LB+MTB+LP@9KT_L(P_L2LF=,HB+MDB;5(*J@DFIG'?"H +M&ZG'B#N)Q_A;^^G'1O+_`-@;V5W`ZT"9=`#LB:@J!2ZJI9:)CP\IZP$+'O& +M`0"Q_0.ZNK(+`,(FH*@DRJJ6ZB0\/:>M!"QYQ@$`D?T#FIJ2"0#R)A7(=J($ +MW8(&8,/_%:/_%(/_&?)E5N(F^\A&TB:@ZLS3_`2S_`J3_!#"957R)J*B)J&2 +M!FOA``2C_PB3_Q&1.`."(D/J[YK_@_\4\F7)Z(FU2#_ +MH.)O9QWPPD3SPF8'TF8(XB0L^(;S_@@`/J;0$*:M`M)F%>5H`ZT"9<$#LB:@ +MJ!2ZJI:*&CP\IZQ[+'N&'P`,#08D_P``\;$#LB,@X@3=P@.,^KOC^Q3#^QFR +M95:")$#H\_(CJPP)BN[S_@33_@J3_A#B956R(ZW"(ZR"`Y?X,\/[",'_`X/[ +M$:KK\_X4XF7)RKNYQ^(B[8(B[/(&:X/^"//^$N)G3,(B[;(FU2#,H+)L9QWP +M`+']`[JZL@L`PB:@J"3*JI:J$3P]IZT$+'G&`0"1_0.:FI()`/(F%B(E*8$@NJ +M%NH1TB)2TLW^%OT)F@X#.@]A!#`C`F1#(,=".@PP- +MP-Z#P@.*T,P0P(@0D(@0@D.*!J7^#`N&:?\,"49O_P"9Q_(B$?G'PB+MXB+L +MT@9KX_P(T_P2PF=,LB+MHB;5(+N@HFMG'?``#`N&MO\,"4:\_YG'XB(1Z<>R +M(NW2(NS"!FO3^PC#^Q*R9TRB(NV")M4@JJ"":F<=\)G'HB+MPB+LL@9KP_H( +ML_H2HF=,@B+M\B;5((B@\FAG'?````"M`@S]TF)2I53_@B+MHB+LD@9KH_@( +MD_@2@F=,\B+MXB;5(/^@XF]G'?"9Q[(B[=(B[,(&:]/[",/[$K)G3*(B[9(F +MU2"JH))J9QWP```V00!BH1AJ0J($?S*D2#HR&ZJB1'^2`\B"!']=`@P"EY@" +M(D1_HB36&ZJB9-:2)-:"$TJ0B,`6^`?8TQO=V=/(T[(32L<;>*%X`[%C`W:` +M$O($?^(K30NJ]UX*C)J"`\0F*`R&^?_,:@PIDD/$9?W[#'S"9,V"),VR)-D, +M&@P)L)J#D_@/@F3-XB3-\@1_\_X1XF3-TB2GPB3-4-V@:MW2+2/3_!3"9,VP +M$*:B`\/,.M(#Q)P=##(=\.`0I@PB'?#P$*8,,AWP`!P*`#JFD!"F##B0*),= +M\``VP0`RH2PZ,H(CR``XID*D&$I"X@3=XD-?#`[B0V#B8D3B8E2@$*8:+*ZJ!"Q\ +MQ@$`P?T#RLO"#`#2(Z"X)-J[EALPMZH&+'E&`@```)']`YJ;D@D`\B,5N'.B +M!-V"`V"S_Q6C_Q2#_QGR9E;B(_NX0](CH.J[X0`$T_L$P_L*D_L0LF95\B.B +MHB.AD@-K@B)#H_\(D_\1ZN]Z_X/_%/)FR>G%TB)'V<6R(DNYQ:(B4I(B6`NJ +M%AHIPB)2PLS^%OQ%%BEN"]D6#2[BR?X6;BV2(ED6^7?RR?\6[R."R?X6^""R +M(NW2(NS"`VO3^PC#^Q*R94RB(NV2(]4@JJ"2:F<=\/(B4O+/T!;O=L*@`<)$ +M\\)C!\F#HB0LN(.S^@@`.J:0$*8@HB"28Q6ET@*M`J5J`[(CH*@4NJJ6ZFD\ +M/*>L'"Q[Q@<``#^FD!"F?/V2;!*"+!*";!/2;,D&?/\`L?T#NKJR"P#"(Z"H +M),JJEEIF/#VGK00L><8!`)']`YJ:D@D`XB,5J'."!-WR`V"C_A6#_A3S_AGB +M9E;2(_NH0\(CH-JJT0`$P_H$L_H*D_H0HF95XB.BDB.A@@-K\B)#D_X(@_X1 +MVMYZ[O/^%.)FR=G%PB)'R<6B(DNIQ9(B6!8I;0NY%AMOPLG^5FSON!*YQ:(B +M(:G%\B+MDB+L@@-KD_\(@_\2\F5,XB+MTB/5(.Z@TFYG'?```/(L\I(L$X(, +MDI/_"(/_#P`_II`0II)L(.)L$H($Z8),BO(LR9;O=)%X`PN9XB:#%JY4%JE4 +M\@3T"YEF+^X,N``XIN(LQ[(LJ^J[ELM7MZH$+'X&`0#:Z^(.`/(LR+(LJ_J[ +MEJM6MRH"1L,`DBP@T@3=L@R,H@R2T_D4L_D9H_D:DF96@B1`^/R2+*N*_Y/_ +M!"QXX_\*@_\0@0($\F95\BRMTBRLL@R7J#S3_PBS_Q%ZGXK_H_D4DF;)^<6B +M(NW2(NRR`VO3^@BS^A*B94R2(NV"(]4@F:"":6<=\`#HDNG%PB(IR<62(NVR +M(NRB`VNS^0BC^1*294R"(NWR(]4@B*#R:&<=\,(B*(B(>G%!D?_ +M'!X,B9)L$@`^IH`0IH)L%``^IH>_!?*@`?)$\Y`0II)L%0`^I@S(E[@%\J`! +M\D3SD!"FDFP6`#ZF#,B7N`7BH`'B1/.0$*;B+/*"+!/R+!2#_@CS_A""+!7R +M+!:2;!>#_A3S_AB3_AP`/J8,R)>X!`P9DD3S(F$*,F$+6<%IT9`0II)L("(L +M()(L(/(L(.(L("`@%")L&"F!,BP@D)(4DFP94BP@\/04**'R;!IB+"#@YA3B +M;!N"+"`P.!0R;!PY05!:%%E14FP=8&P4.+%I86)L'H".%(EQ@FP?@@3F6,%H +MT188!H($Z9DQ%MA&#!F(,?DAZ1$F.`;X40P.\)Z3B($,'YD!)C@&Z$$,">#Y +MDX@A#!XF.`B(80P)/?"`Z9.($0P9)C@*B'$IH0P"@)*3**&"#(J`CQ#X`R*JO*NY:+/CP]MRT"ACD` +M+'M&.@```!89/@OI%@XX\LG^%F\WDB):%@E#)ADP@LG^5BBZDB(1F<7R(C'Y +MQ<(B[>(B[-(#:^/\"-/\$L)E3+(B[:(CU2"[H*)K9QWP`/(B,?G%PB+MXB+L +MT@-KX_P(T_P2PF5,LB+MHB/5(+N@HFMG'?#:FZ(L(/($W=(,C+(,DO/Z%-/Z +M&;/Z&J)F5H(D0-C\\BRKD@D`BMWS_03C_0J3_1#29E6B+*VR+*R"#)?X/+/Z +M"+$"!(/Z$7K:\_T4TF;)NJJIQ=(B[8(B[/(#:X/]"//]$M)E3+(B[:(CU2"[ +MH*)K9QWPP?T#RKNR"P#2*LC"*JO:S);,+CP^QZX$+'W&`0#1_0/:W-(-`)%A +M`^(J((($W?(*C)KN@_X4\_X9XF96PB1`B/J2*JO*B)/X!+/X"M/X$()F5>(J +MK?(JK,(*EY@Z\_X(\0`$P_X1>HZ3^!2"9LGZ[@Q/Z<7(>LG%F+K-`IG%G0(& +M#````&8J(]@AIQ<+, +M($N9%K^BHBE<"_\6^@HF&G`F*C5F.N:B*5B(L)^G%QO'_J!RIQ8@\B<7H7.G%V'S9Q0;M_P"B*5BL:B8:%V8JJ(@_Z(I6*RJ +M)AH;@LK^5MCVZ!SIQ=(L(=G%N%RYQ:(L):G%!M;_`*(L(:G%@BPEB<6&TO_8 +M'-G%N%RYQ<;/_Z(I6)Q:)AH+XLK^5A[S@BP!@F4,HBPAJ<7&R/^X'+G%!L?_ +M``!6R:O)D;)$]&5L^SPZR)'1_0.&JO[($LG%!DC^\FP2T@3F%NV``#FF\!"F +M\DR,X@R,S!Y&__T,Z`P9DFP4@FP2!OS]#`F&:?X,"T9A_@P.AJ+^`*(L(/($ +MW=(,C+(,DO/Z%-/Z&;/Z&J)F5H(D0-C\\BRK#`F*W?/]!./]"I/]$-)F5:(L +MK;(LK((,E_@\L_H(L0($@_H1>MKS_1329LFZJJG%TB+M@B+L\@-K@_T(\_T2 +MTF5,LB+MHB/5(+N@HFMG'?#XDOG%PB+MXB+LT@-KX_P(T_P2PF5,LB+MHB/5 +M(+N@HFMG'?"M`@SX@F)2XF)$Y:G^LB+MTB+LP@-KT_L(P_L2LF5,HB+MDB/5 +M(*J@DFIG'?#H$NG%\B(A^<4&'_^($HG%LB+MTB+LP@-KT_L(P_L2LF5,HB+M +MDB/5(*J@DFIG'?#B(B'IQ;(B[=(B[,(#:]/[",/[$K)E3*(B[9(CU2"JH))J +M9QWP#`L&0O\`#`W&1__X$OG%1@C_N'$,#XAA#!D,#H#I@[#Y@XA1#`OP[A#X +M08"Y@PP(\(F#\@R*R9&`_Q#PNQ#@NQ"R3(J&[?Z8$IG%XB+M@B+L\@-K@_X( +M\_X2XF5,TB+MPB/5(-V@PFUG'?#R(A'YQ<(B[>(B[-(#:^/\"-/\$L)E3+(B +M[:(CU2"[H*)K9QWPPF$)(*(@9>0"HJ`ST?T#R)'&+?X``#9!``R+XB)30M(! +MT@2+P@22X_L(T_L.P_L/`#NFHB2LHF00DB2MDF01@@2+G-B2)*[PF1&29*Z" +M)*_PB!&"9*_R!)6,;Z(DK`NJHF00P!"FLB3),6,#DJ2,UKL"FB*1>`-V@`[2 +M(X,+F8R=C)GB`H`F+@R&^O_,:0PO\D*`)43[#+@`.*9&``":(H(D(+($BZ(D +M$I($C+/X%*/X%9/X&8)C5O(B(^CTL3@#^N[B8U62)*W2!)6A!@3"!)?3^1#2 +M)!##^1&ZN<@TJIG3^PC#^Q2R8\FR)*RA9`.S^0B9RAWP-D$`#`DRT@&"(D)" +MI$1*0H+(_A8H&*(#E0P;%BH7T@.-TD.+PB)&K0G`JX,,'PQ[@@.+H_L*J.2# +M^POB`Y4,"-(#E\(CK:"/@X/[#R#,H,(L:>/[$-/[$(#B](#DO/["./[#M/[#\/[$``[IJ(CK*)C$)(C +MK9)C$8(#BYSHHB.N\*H1HF.NDB.O\)D1DF.O@@.5%G@`LB.L"[NR8Q#P$*;B +M`YD,KX#N$?#N(``^IM`0IL(CSQQI#`T6;`P`.::`$*:),Z@S0J2,2D*V2@0, +M&()$?Y(C$CWPDLGS%ID*(*(@):\"T?T#LB/'HB.KPJ`SXB/(L*J`EIH)IZP% +M+'M&`0``VKJR"P"B(ZL,">JJX6,#EEH(IZP$+'D&`0#:FI()`/(C(,(#BZ(C +M$H(#C,/_%*/_%8/_&?)N5M(D(ZCSPB.KVJK1.`/#^@2S^@J3^A"B;E6B(ZV" +M`Y7!`P3R`Y>#^A""(Q#S^A':VO@SRJJ#_0CS_132;LG2(ZS!9`/3^@BIS!WP +MV3/&SO^M`J7"`L;4_P````P+AMO_``#&X/\`-D$`#(OB(E-"T@'2!(O"!)+C +M^PC3^P[#^P\`.Z:B)*RB9!"2)*V29!&"!(N("@"8N#(;Z_\QI#"_R0H#E`_L,N``XID8``)HB@B0@L@2+HB02D@2,L_@4 +MH_@5D_@9@F-6\B(CZ/2Q.`/Z[N)C59(DK=($E:$&!,($E]/Y$-(D$,/Y$;JY +MR#2JF=/[",/[%+)CR;(DK*%D`[/Y")G*'?`VH0`,#C+2`0Q_@B)"0J1(2D*" +MR/X6V$J2`Y4,&A9)2<(#C<)#B[(B1IT.L)J##!P,"Y/_"H(#B]C4H@.5@_\+ +MD@.7@B.MT+R#L_\/((B@@BAIH_\0D_\1@_\4`#^FXF,4XD.,Z4.@$*:R`Y+8 +M(Z"1=!:]/L(#B,)#DI)CK?(#E1Q,#!T63S\,"8Q+@@.2@)V#%EE!#`FX([++ +M_A;K08(#E0"($<"((``XIO`0IO)#B^DCO#F!!P0`.*;P$*;R0XBX(QN[N2.2 +M`XC)C$N)C$^)CR9)CK+GSPJ`(L?T#86,#<3@#4@2V4D.*\B,2HJ`S460#%O\Z +M@B)2MD@(\B)2]L\"QEP`@B)2ML@(TD3#TF,2XF,3@B)4\B)3X@.+T@.2\_P( +MX_P.T_P/@_P0`#RF\B+L\F)0XB+MXF)1T@.+%BT"TB.N\-T1TF.NPB.O\,P1 +MPF.O@@.5%J@`XB.L/?#BSO_B8Q#P$*8@HB#R8F#E(@*M`F5[`L(BZ[(CQSPZ +MRKN6ZT6WJ@0L?,8!`,']`\K+P@P`TB+KLB/(VKN6BT2WJ@4L>08"``"1_0.: +MFY()`-(B8((#B_(B4N(#C(/]%//]%>/]&=)F5K(B3X(D-*(BZ[J(H_@$P_@* +MD_@0@F95@0`$XB+M\@.5T@.7LB)0HB)#\_X0T_X1>IZS^0BC^1229LGR(NR* +M[O/^".G%TB)'V<6R(DNYQ:(B4I@2"ZH6:CVB(E*BROX6.CR9Q;B2N<72(Q&" +M(Q#R`Y7B`Y>#_0CS_1#C_1+294S"`XL6O!SR(N[P\4'R8N[B(N_@X4'B8N_8 +M0]E3PB,2R6.R`XNR0XVB(Q&8Y""JH))J9QWP@B,2MF@"QJ@`'!^2(Q(,&.*@ +M`)+)^Y#H@^)#E,)C$@`_II`0II)C%``_IK9)`M)$P^`0IN)C%0`_IK9.`M)$ +MPX`0IH)C%@`_IK9(`M)$P^T,D!"F\B,3@@.+\_X(\B,4@_X.@B,5\_X0\B,6 +MDF,7@_X4\_X8D_X<`#ZFMDD"TD3#TB.LTF,0DB.MDF,1@@.+%@@"@B.N\(@1 +M@F.N\B.O\/\1\F.OX@.5%HX`DB.LDLG_DF,0*8%9D6FAD!"FDF,@\B,@XB,@ +MTB,@DB,@\/`4\F,8(B,@X.(4XF,94B,@T-04TF,:8B,@D)84DF,;@B,@("@4 +M(F,<*3%06A1905)C'6!L%"B!:5%B8QZ`CA2)88)C'X($MEB1:*$6N`6"!+GY +M(19(-PP?V1&9`28^!MA!#`G0^9.((0P>)C@&V#$,"=#IDX@1#!TF.`:(40P) +M@-F3B`$,&28X"HAA*8$,`H"2DRB!@@.*R7$]\(#N$)"-$.#O$(#N$.)#BLEQ +MK0(E"0&M`N52`L(CQ[(CJZAQRKN6RR\\/;"(Q#X,^/Z$+/Z$7KJ@_X(\_X4XF;)LB.LRJJS^@BIQ083_P`, +M#,;J_@P)AO#^F<6"(A&)Q<8-_YG%A@S_P?T#RKNR"P#2(\C"(ZO:S);\#SP^ +MQZX&+'Q&`@```-']`]K,P@P`TB,@\@.+X@.,\_T4H_T5X_T9TF96DB0T^/." +M(ZN:_X/_!+/_"L/_$/)F5:(CK>(#E=(#EY(C$./Z$(@SX0`$T_H1>OJ3_PB# +M_Q3R9LG2(ZP,3^JJT_H(J<68P`[IJ`0IJ)#C)(#C!:IW])C%`SLPF,2QGO_````-D$`,J$8 +M.C*B`W^RI$"Z(ANJHD-_D@+0@@-_0J``EY@"0D-_J,(;JJG"F,*"$DZ7&$[2 +M(]G2S0'28]G"(]FR$D['&U>A>`.Q8P-2H`%V@!+R`W_B*TT+JO=>"HR:@@+, +M)B@,AOG_S&H,*9)"S"5]^K`0IJ("R\PZP@+,C)P,,AWPT!"F#"(=\.(#?9S> +M'`@`.*;P$*:,OPPR'?``D!"F##(=\`!"0WT,`AWP`%)#?0P"'?``-L$`#`X, +M&PQ]@B)"C*"R/X6&$J2`VD6J4BB`V&B0U^2`V8,"O(#7Y/]"L(CU//] +M"Y(#:8(#:_(CHL"K@Z/]#R#_H'K_\B\>D_T0@_T1\_T4`#VFZ9/B0V#B8D2@ +M$*:R`V;"(D*@D706'#2"`UR"0V:28Z*2`VD<3`P?%JDT#`D66P"R`V:PGX,6 +M638,"=(B0M+-_A9=0;(#:0"[$<"[(``[IH`0IH)#7^)B0D*@H$I"O(G1!P0` +M/::P$*:R1.B2)!H;F9)D&H($Z-SXT@3U`-T1P-T@`#VFL!"FLD3KD@3KDD3I +M@B0:@L@!@F0:H+'E@@-F'%F@J706V"WI<^F#XF.^HF.AN4-A8P-19`.A.`/" +MI(C*PM(,=M)#7HAS/#L,C1;(.9(D*AQ8ES@*F'/V25/R9"I&&`"(DB3&\)D1DF3& +M@B3'\(@1@F3'\@3UC&_"),0+S,)D*-`0IJT"TF,5I5D!K0*E\0'2([S"(Z"A +M``0\.]K,EEP]QZL&+'U&`@```-']`]K08" +M``"1_0.:G)()`,(C%8(#7_ASX@-@@_P4\_P5X_P9PF96LB/[^$."(NNZ_X/_ +M!($X`]/_"I/_$/)F5?(B[>($]<($][(B4)(B0^/_$,/_$8J/L_@(D_@4@F;) +M@B+LJO^#_PCYQ>(B1^G%PB)+R<6R(E*2(E@+NQ9+-*(B4J+*_A::3Q8);PNY +M%KMOPLG^%EQPDB)9%GENTLG_%AUOXLG^%OYOB&.X4Z(#:9(#:[/X"*/X$)/X +M$H)E3/(#7[P/HB3&H*%!HF3&DB3'D)%!DF3'@B)$@F)%^'/R8D;B`U_B0V'8 +M8\(CU2#=H'K=PFT<'?#R(D3R8D7H<^)B1M(#7])#8LRR;!P= +M\(AS@LC0%FAN\DR#\F)2\F)3DB)3@@-?XB)4D_T(@_T.X_T0`#VFDB+LDF)0 +M@B+M@F)1X@-?G,[B(Z/P[A'B8Z/2(Z3PW1'28Z3"`VF,7/(CH0O_^5.`$*:M +M`H)B8"4_`:T")=M5BQ\1A8```""`VDN!"QYQ@$`D?T#FIN2"0"R(F#R`U_B(E+2`V#S^Q3C^Q73^QFR9E:" +M(_OB(D_R(NN*[O/^!/$X`\/^"I/^$.)F5>(B[=(#:;(#:Y(B4((B0]/^$+/^ +M$?K^D_\(@_\4\F;)\B+LJN[S_@CIQ=(B1]G%LB)+N<62(E@6*5<+B1886*+) +M_E9ZXL@2R<6R(B&YQ<:&_^)#7PP91MW^T@-=TD-?AOS^G0[R`UWR0U]&V/[B +M9"J")"OR!.N2!/*#_0B")"SS_0Z3_0^#_1``/:;R),3R9"B2),629"F"!.N< +M^.(DQO#N$>)DQM(DQ_#=$=)DQY($]1:)`/(DQ/+/__)D*)`0II)D.((DX9;8 +M5Y%X`PN9TB:#%EU%%EE%X@R$"YEF+NX,OP`_IN(DW](DP^K=EEU,UZL&+'U& +M`@```.']`^K=T@T`\B3@XB3#^NZ6WDKGJP4L>08"``"1_0.:GI()`((D./($ +MZ^($\K($[//X%./X&K/X&8)F5O(D)[(L).(DP_J[X_L$T_L*D_L0LF95\B3% +M@@3UX@3WLB0H@_\0X_\1@B0;JN^S_@BQ`@2#_A3B9LF"),2Z_X/_"/G%!CS_ +M``P-A@W_#`E&$_\``!9I10N)%HA%HLG^5EK-R!+)Q;(B(;G%1C+_'![29"H` +M/J8]\)`0II)D+``^I@S(E[@"\DR#D!"FDF0M`#ZF#,B7N`+R3(.0$*:29"X` +M/J:"H`R7N`+R3(.=#8`0IN(D*^/Y".($Z^/Y#N($\N/Y#^(D+./Y$.(D+>/Y +M%.(D+H)D+SWPX_D8@_D<`#FF#,Z'O@+R3(.2),229"B"),6"9"GR!.L6_P&" +M),;PB!&"9,;R),?P_Q'R9,?B!/46?@"2),0+F9)D*"FQ.<%9T6GAD!"FDF0X +M(B0XDB0X\B0XXB0X("`4(F0P*8$R)#B0DA229#%2)#CP]!0HL?)D,F(D..#F +M%.)D,X(D.#`X%#)D-#E!4%H465%29#5@;!0XP6EA8F0V@(X4B7&"9#>"#'98 +MT6CA%A@&@@QYF3$62#0,&8@Q^2'I$28X!OA1#`[PGI.(@0P?F0$F.`;H00P) +MX/F3B"$,'B8X!HAA#`F`Z9.($0P9)C@*B'$IL0P"@)*3*+&"!.J`CQ#X`=FA +MR9&`_Q"0CA"`_Q#R1.K9HN/BQ]1A``G"D+^1:_*F8I#Y@2F<6"(B&)Q<8``*@2J<62(EH6J2@+N19; +M*<+)_E:LK^(B$>G%TB(QV<5&N_X``-']`]KO +M!"Q\Q@$`X?T#ZLS"#`"2)#CR!.N(D>($[//Y%*/Y%>/Y&9)F5J(D)X(H))(D +MPZJ(D_@$T_@*P_@0@F95HB3%\@3UX@3WP3@#\_H0X_H1\B0HXB0;RLKS_`CC +M_!3"9LG"),2ZJL/Z"`Q,J<62)!^M`IG%G0*")".)Q08,````9BLCV!K9Q;(J +M(;G%B#J)Q?(J(_G%Z%KIQ=(J)=G%N'JYQ8(J)XG%HLH@2YD6?**R*5P+S!;[ +M"B8;<"8K-68[YK(I6)R+9ANWLBHAN<6"*B.)Q?(J)?G%XBHGZ<7&\?^(&HG% +M^#KYQ>A:Z<78>MG%!NW_`+(I6*QK)AL79BNH^!KYQ>(J(>G%V#K9Q;(J([G% +MQN3_LBHAN<6"*B.)Q8;A_^@:Z<78.MG%QM[_LBE8K*LF&QORR_Y6W_;H&NG% +MTBHAV<6X6KG%@BHEB<4&UO\`@BHAB<7R*B7YQ8;2_]@:V<6X6KG%QL__LBE8 +MG-LF&Q/BR_Y6'O.(&HG%\BHA^<5&R?\``+(J(;G%QL;_V!K9Q0;%_P``5AF[ +MR9$,+N),A"7@^:$X`SP[R)%&Y_Z($HG%AD3^`)B2F<4&1_X`HB(AJ<5&0/ZR +M(BFYQ<9"_M@2V<7"(B')Q48[_OB2^<7H%.G%!CW^``S)DF0J@@QVS!B&Z/T` +M.J;`$*;"1.RR!.S,&T;D_?)D+`SMTF0JAN']#`Q&@OX,"4:(_@#H$NG%!B[^ +M``P-AM'^#`E&U_X``/(B(?G%QBC^K0(,^()B4N)B1&7*_L8D_@P-AFK_#`R& +M@_Q'P[B#B8@2(AN2R?T6Z>X`-*:P$*:H'*`@'2`AL!`B!&`=R!YV(P6"!+P6>!>2)"(< +MO"8Y(@`\IK`0IF$(!%(B7'$)!+D2HL7_%OH*TL7^%MT,XL7]%KX.40H$\B0C +M)C\B`#6F,!"F80L$4B)=<0P$.9)F%0+&(P""Q?X6V`J2Q?T6^0VB)"3!#00F +M.B(`/*8]\+`0IF$.!%(B7G$/!+)B$285;V8E`D8C`-+%_18]#>(D)4$0!"8^ +M'P`TIC`0IE$1!$(B7V$2!#)B&0OT%@\4@L3^%E@4)C0"'?```#:FP!"FPF(; +M`#6FL!"FH1,$LF(=`#JFD!"FDF(?'?``-J;0$*;94@;4_P``-J;@$*;IT@;< +M_P``-J;P$*;R8A7&X_\`-Z8P$*8Y,@;+_P``-Z:`$*:)L@;3_P``-Z:0$*:2 +M8A/&VO\`-Z;0$*;9,@`VIL`0IK$4!,E2`#NFH!"FJ7)&O?\````WIE`0IEFR +M`#:F,!"F\14$.=(`/Z;@$*;I\D;`_P```#>FL!"FLF(3`#:FH!"FD18$HF(5 +M`#FF@!"F@F(7AL+_PB)8)CP,')X`/J8]\-`0IM)D$?(D(R8_%($7!``XIE`0 +MIC(D$:!5$5`S(#)D$9(D)"8Y%L$8!``\IK`0IJ(D$3WP0+L1L*H@HF01TB0E +MTLW]%CWC,1D$`#.F\!"FXB01X/\!\.X@XF01QH;_`#6F@!"F@F(='?``-J:0 +M$*:28AL=\``V00!RH`%BH0(R(NY2H`!28D>V(VV"(NY"(EB"R/X6Z"FD!"FF14`-Z:`$*:) +M)0`WIC`0ICDU`#>F\!"F^44`-Z;@$*;I50`WIM`0IMEE`#>FP!"FR74`-Z:P +M$*:YA086````-Z;0$*;9%0`WIL`0ILDE`#>FL!"FN34`-Z:@$*:I108-```` +M-Z:`$*:)%0`WIC`0ICDE`#>F\!"F^54`-Z;@$*;I908$````-Z:@$*:I%0`W +MII`0IIDE4L4@2T1-`@Q+=JO04B)8%E4,PL7]%OP+4B)<%E4*)A5Z)B50TL7] +M5MT*`#>FP!"FPF0A`#>FL!"FLF0B`#>FH!"FHF0C`#>FD!"FDF0D`#>F@!"F +M@F0E`#>F,!"F,F0F`#>F\!"F\F0G`#>FX!"FXF0HAA@``#>F,!"F,F0A`#>F +M\!"F\F0B`#>FX!"FXF0C`#>FT!"FTF0DQ@X``#>FL!"FLF0A`#>FH!"FHF0B +M`#>FD!"FDF0E`#>F@!"F@F0F!@4````WIM`0IM)D(0`WICWPP!"FPF0B0L0@ +M2R(=\``F%!$F-`X`-J;@$*;@X'3@Y\#B8D="(EDF%!PF-!D`-J8P$*;R(D<] +M\#`P=#`WP*`S$3#_(/)B1T(B6B84&B8T%P`VIH`0ID(B1X"`=("'P$"($8!$ +M($)B1T(B6PN4%AG8HL3]%KK7`#:FP!"FLB)'P,!TP,?`X,P!P+L@LF)'!EC_ +MG"0F-!``-J;0$*8]\-#0=-#7P-)B2T(B69R4)C07`#:F\!"FXB)+\/!T\/?` +MH/\1\.X@XF)+0B):G)0F-!<`-J9`$*8R(DM`0'1`1\!`1!%`,R`R8DM"(EL6 +MM->"Q/T66-<`-J:@$*:2(DN@H'2@I\#@J@&@F2"28DN&5O\`-D$`,B+N4J`` +M4F)'MB-T0B)8)A0.)C0+DJ`9`#FF@!"F@F)'0B)9)A09)C06P1<$`#RFL!"F +MHB)'/?"@NQ&PJB"B8D="(EHF%!DF-!;Q&`0`/Z;@$*;2(D<]\$#N$>#=(-)B +M1T(B6R84&28T%H$9!``XID`0IC(B1SWPX$0!0#,@,F)'DB+O4F)+MBEK0B)8 +MC,0F-`H!*$?!`Q,=JPK8B)8G.8F-AQ`=0&`]R``/Z;@$*;B9"%B(EP+UA;-""8F +M>28V3AM50L0@2R(=\```L#@@`#.F\!"FH.@@^34`/J;0$*;`>"#950`WIC`0 +MICEU!N3_L.@@`#ZFT!"FV36&X/\``*`X(``SIO`0IOE5AMS_``"@-R``,Z;P +M$*:0YR#R9",`/J;0$*:PQR#29"4`/*9@$*9B9"=&XO\`H-<@`#VFP!"FPF0C +M1M[_`)#W(``_IN`0IN)D)4;:_P`V00`,%8*A`@P',B)2(B +M[^+._A:N&8R4`#>F/?#P$*;R8DLR(EJ<(P`WIH`0ID(B2SWP0(@1@$0@0F)+ +M0B)8)A00`#6FH!"FJ1(`-::0$*:28@*R(EHF&Q$`-:;0$*;28A$`-:;`$*;" +M8A+B(EB<#@`UIC`0IC)B(0`UIO`0IO)B(H(B6IPH`#6FH!"FHF(Q`#6FD!"F +MDF(R'?`=\```0B)@LB+N0$`40F)8MBL7DB+NDLG^%KD2)A0+`#>FH!"FHF)' +M0B)8LB+OMBL6PB+OPLS^%IP2C*0`-Z;0$*;28DM"(E@F%!0`-:;P$*;R8@$` +M-:;@$*;B8@)"(E@6Q/D`-::`$*:"8B$`-:8P$*8R8B(=\``F%!$`.*:0$*9B +M(EF0D'20E<"28D<+IA9JWP`XIL`0IK(B1\#`=,#%P*#,$<"[(+)B1\9V_XST +M`#BFT!"F/?#0T'30U<#28DOB(ED6KM\`.*8P$*;R(DLP,'0P-<"@,Q$P_R#R +M8DO&=_\F%!$`.*:0$*9B(EJ0D'20E<"28D<+IA;:Y@`XIL`0IK(B1\#`=,#% +MP$#,$<"[(+)B1X:4_XS4`#BFT!"FT-!TT-7`TF)+XB):%C[G`#BF,!"F\B)+ +M,#!T,#7`0#,1,/\@\F)+!I;_"Y06V>T`.*:@$*9"(EB@H'2@I<"B8D<&LO\` +M`!8$[@`XIK`0ID(B6+"P=+"UP+)B2\:R_S9!`!S&'*@FP!"F +MPF)'TB+O]BT2`#6F\!"F^1(`-J;@$*;B8B$=\``XIJ`0IJ)B2P`UII`0IID2 +M`#:F,!"F,F(A'?"2(F"R(NZ0E!228EJV*RLF%`L`-Z:@$*:B8D>2(EHF&1;1 +M&`0`/:;`$*:R(D<]\$#,$<"[(+)B1T(B6.(B[[8N*8QT`#BF\!"F\F)+,B): +MG%.1&P0`.::`$*9"(DL]\$"($8!$($)B2T(B6"84"``UIJ`0IJ)B`;(B6M$- +M!"8;"@`]ICWPP!"FPF(1XB)8C)X`-J8]\/`0IO)B(3(B6A9C#I$@!``YIH`0 +MIH)B,1WPHB+N]BH"ACD``#>FP!"FPF)'`#6FL!"FN1(=\)(B8-(B[I"2%))B +M6;8M*R84#0`WICWPH!"FHF)'DB)9)AD4T1<$`#VFP!"FLB)'H,P1P+L@LF)' +M0B)8XB+OMBXJC'0`.*;P$*;R8DLR(EF<8Y$:!``YIH`0ID(B2_`@`*"($8!$ +M($)B2T(B6"84"``UIJ`0IJ)B`;(B628;"M$*!``]IL`0ILF2XB)8%HX``#:F +M\!"F\F(A,B)9G..1(00`.::`$*:"8BD=\`"B(N_V*@T`-J:P$*:R8B$=\!WP +M```XIM`0IM)B2P`VIL`0IL)B(1WP`#6FX!"FZ1(=\```-D$`#$8,%9*A`@P( +M0J#<,B)22D*"8D@[A'@W2#28D<`-:9B1+S`$*;)$@`UIE)$M[`0IKDB`#6F +MHB)@H*`4HF)8D!"FF9(`-::"(F"`@A2"8EDP$*8YHAWP`-(B[O8M`H8Q`.(B +M[N+._A;N#0`XIJ`0IJ)B1P`UIF)$O)`0IID2`#6F,B0I4D2W,#`4,F0A\!"F +M^2(=\+(B[K8K)<(B[L+,_A9<#0`XIO`0IO)B1P`XIN`0IM(B1SWP0.X1X-T@ +MTF)'`#6F8D2\P!"FR1(`-:921+>P$*:Y(@`UIJ(B8*"@%*)B6)`0II)B$0`U +MIH(B8("$%()B6C`0IC)B$AWP`#FF\!"F\/!T\/7`\F)'`#FFX!"FTB)'X.!T +MX.7`H.X1X-T@TF)'AKW_````-:9B1+R0$*:9$@`UIH(D*5)$MX"`%()D(3`0 +MICDB'?``.:;0$*;0T'30U<#28D<`-:9B1+S`$*;)$@`UIK(D*5)$M["P%+)D +M(:`0IJDB'?``.:8P$*8P,'0P-<`R8D<`.:;P$*;B(D?P\'3P]V(Q8@ +M_Q'P[B#B8D<&YO\V00`,#;(CZT*@S$I#`#VFH!"F#!TL^,*D),HSH*!TI[@" +MTD/GZ&,@FI#!(@3@[I"P[A'JS,J9D@D`DF01@@/:O,CR)!^,3X(D'[9("I(D +M'Q:)":($OJQJPB0?#.[G'!_R)!\FKQF2)!$,^)<($:(#VA:Z`.*A`@`^IL`0 +MIL)$P/(D$:S/`#VFH!"FJ>28Y!R8ER@>R.1L;=N"(++S()D +MN$8!`)9[!;)DN)%X`Z%C`W:`#K(J@PN9C)N\:<(#Z"8L!(;Z_ZRYT@/HC!T= +M\`"")!'R!,`,OH/^"?/^"``^IAWP`)(#RPN95NGUH@/=5MKU1M7_#"NR0^AE +MJ/C&\?_"RS3"9+A&Z/\````V@0)18P,,"9D!8B6"+`B`9B!B98(R)85\Y!P& +M0#,0,F6%=H`)LB6&N0&H`6>*!,;[_P``0J/H/?!V@`W2)8/9`<@!"T2,3"8$ +M`D;Z_PP8XB6&3`_-#^#F5>)A1CT.,#B3,F%',,Z3O"QBP1`+C)T&8&R@A@$` +M"XA+F6<9'W*CZ*(EE:D)=H`1TB6&T-95V0&X`0MWAQO>)@?;QOG_#!>"P1"2 +MP1QBH^CH".)EE7:`$4(EAD!&54D!.`$+9G<3!28&`L;Y_QMW2XB7F-@,+H&` +M`PPWLJ&`NF+VQ@)&MP"M`@P)Q@(`DLD@HLK@8L;@ML8G`#BF,!"F0J/H.0$X +M`3)EE7:`$3(EAC`V53D!.`$+1"8ST28$SL;Y_S*N@#`ZP!8C+#*NH"#9P("F +M$>"J(#K=`#JF0!"F#!I)`3(A```=0$*CZ``SH0`=0`"JH:+*_S"J(*)EE7:` +M$9(EAI"659D!.`$+1"8S!28$`L;Y_T*CZ#*A@-JR.KNPM4&RRP-V@`VB)8.I +M`9@!"T2,228$`L;Z_S(E@F*OWV`S$#)E@J(E@J$C!)(EFQPFH)D0F0$`-J8P +M$*8R8428`6(EFRP#H&80HB6"D&;`8F%%DJ&`8&+`FI8PJB"B98*B)8*0H$06 +M>AZ`2A'@1"``-*8P$*8;NZ`FP#D!*BTRH8`Z(B`@1#P#)S,-'`,G,P4BPD"& +M```BPB!BH^@X`0`:0'STVGD@=\``1*%RQR!P=4%`,R`R995RQ_=V@!%")89` +M1E5)`3@!"V9W$P4F!@+&^?^@*<"\$IT"1@$``)+)X*QI`#BF,!"F8J/H.0$X +M`3)EE7:`$3(EAC`V53D!2`$+9G<4V"8&U<;Y_X"=$2!E0;JVX)D@`#FF@!"F +MB0&<&BP#H#/`@#,1X#,@`#.FT!"FV0$WB8&V\;Y +M_Z(A1X!LP)(A1KIVBG>@^9-P?\!P<'1WE@K&$0`+=W!P=&<7/T*CZ)@!DF65 +M=H`1LB6&L+95N0&H`0M$)AH%)@0"QOG_0J/HTB65V0%V@!'R)8;P]E7Y`>@! +M"T06WOLF!+K&^?_'N#]BP1`,!V"8H&!LH(8!`'T(2YEG&2J"QP&B*0!RH^BB +M995V@!;")8;`QE7)`;@!AQOV`@::_WT.QIC_#`V&8/\``#9!`!R)0M(!8B+K`#FF +M@!"F4J1^B41:4H(%@+RHHB02%EH`LB02MDL*PB02%HP/T@2*K#WB)!(,[_<> +M'((D$B:H%JA$#/FG"0^R!8",FQQ]`#VFP!"FPD2,Z$0Q8P,6S@6Q)`2B(XZZ +MLO(K@,*@$J"@9!8O"-(CCM#89*<]$>*@-:<^"X(K?_(DW(<_`@8M```\II`0 +MIID4N!0`-V +M@`^B(X,+F8S*%JD&L@6.)BL'1OK_```6R07"!8Z,'!WP`/A$X@2,#+WS_0GC +M_0@`/:8=\```@BM_9@B9X2,$TB.;X-T0`#RF\!"F^122(YO@F1#0F<"0FL!6 +MF??B)-SB:W\&W/\`\@5Q"_]6[^^"!8-6V.]&O?\,*9)%CJ54^,;E_P#EK/^I +M%(;2_Z+&-*)DJ\;9_P``-D$`#!RB(NL`/*:P$*:R8D&2(D$O")+*S))BZT8!`):*!*)BZY%X`Z%C`S*DC#HR=H`.@BJ# +M"YF,F*P9L@.`)BL$AOK_G&G"`X",'!WP`-(B1`R^<-T1X-T@`#VF'?`,+N)# +M@&5+^`;W_P#RRC3R8NL&[/\````V00`<+$*@O+$D!#%C`U(BZ[JRHB..@BN` +M2D*@H&06:`>"(XZ`B&2G.!&2H#6G.0OB*W_2).WG/0(&*0``/*;P$*;R9!*2 +M)!(L".+%S.)DO$8!`)8%"%)DO)%X`_*D +MC/HB=H`/@B.#"YF,N!89!:("@"8J!D;Z_P`6202R`H"LZQWP`-(K?V8-IH$C +M!/(CFX#_$``\II`0II)D$N(CFX#N$/#NP.>:B((D[8)K?\;?_Y(D%0RZ<)D1 +MH)D@`#FF'?`,*J)"@*4\^,;K_P#EE/^B9!*&UO\``++%-+)DO`;>_P```#9! +M`"$E!!WP-D$`LJ#^?/D+A/NCH*1!D(@P&ZJP.A#[DI"403"I@J#)$0N1&ZM`N[L+@0L*J0 +MJG>7LQ+`*1$J)`LB("@0("+P*B<=\```P",1*B0+(B`H$"`B\"HG'?`````V +M00`A)00=\#9!`#CB3!IE`>ZM`[$E!($G!)$F!))B,X)B-*6\"5%]`V%\`W$J +M!)*@_^$I!$$H!"D#PM,#\@P=#!N-"Y#_$4#_(/)C$D$K!!SOXF,3XF,4T@P@ +M#`[C^`BB#!_3^`P,;:/X#9/X%()C%7)C$>)C$`PW8F,98?X#4F,:0F,;?/4, +M)/)C'+)C'_+3".)C(-)C'=$U`[)C'I(B(;*@^")CP*(B(J)CP9)CPI&E`XC" +M@F/#XDP=@:@#XDP?XDP@8EP?4DQ`4DQ!XDQ"XDQ#XDQ$8EPD8EPE8EPF8EPGXDQ0 +M4DQ1XDQ246,#XDQ3XDQ4XDQJ0DQK06<#Z=^R;8*B(Q*RHQZZLT"J(*)E@I)E +MF@P:@F6%8B,4:2?R(Q/R9<+B(Q'B94+BPUC2(Q+298+"#!W2PT`EPN]"98(, +M`AWP-F$`#`JQ+`1(XF(C.E(C.\T$9,DB6X-:",J#_P%41 +MT/V04F@:H-T14J\`D/\1.O]0_Q#Z?_)H)\)*R')H,'K_H(X1\FH;T'%!.HA0 +MB!`ZW5#=$(J/@FHMBOWR:B[ZE_K=TFH2:C!R:B\,)W)*R>>V,,">$3J9 +M4)D01@L```#"(B'1-0/":AG`PT'@S!#";12R(B'!.`.PL"3*N[)J&!WP``#` +MEA$ZF5"9$/%'`Y".$<)K^#J(4(@0BHV)>YJ(@FLIFHB":TN:B()K;9J(@FN/ +MBHF":[&*B8)KTW(B(8$U`W)J&7!S0?!W$')H%&(B(7$X`V!@)'IF8FH8'?`` +M`))*4`9P_YACDEH:@AH:@EHF^'/R6AOB&AOB6B>2)!*RK]^PF1"29!+&@_\` +M-H$`6.(,!I*BD)I%8D39@@22)E@"8D22H@22\"``%GI`,6,#LB42LF."8D2. +M=H`(PB.&P,95]DP"!OS_#&\`/Z;@$*9II6FU:<72!&1RI$S2S?U6O2IZ=<($ +MDK&O`PQ-#+X,WZ*BB*JE`#VFD!"F%FDXMCD"!N```#NFD!"FD(A!C'@,>JE! +M!J````#@B<`6V!F"R?06R`_PB08F>R8F?4HB$!LJ!0I7$)8D6*K07E1P,KNA8K/%;Z-ZT%8D0VL@0X +MY8T#*\H63#Q6>CBM!>6M`99*/&G5:>5I]>($..)$1-($."9-2?($*B8OY`D9]`((EHX"9P((E +MHY)A`HANM!>62`*T%94D! +MK04E2@%6"AJ"!)+F6`J2!)(]\*8Y`L;(_Z($DJ+*^E8:&\;%_Y(EHX@QESB" +M#"J&8/^M!:6$!:E!>G4,&L($C=+%0.+%6+*C'KJUY67O3!K!9P/"8X(EC^WB +M)_;B8C72!)*<;?($DN9?!8($DN8X&)($DB99!:($DB9J#+BE%OL+#"S)`2@! +M'?#2!*%\_`#=(YS-X@2A`.XC9AXC\@38@J#]@/\0\D38PD2A1@0`````D@38 +MHJ#^H)D0DD38PD2AL@2@=^MIL@2@TB0E`+LCU[LKDJ?7L(NP4(B@FHAB2(#B +M!-MB2'^"HI#@\'3Z]8K_LD_L;Z_@QZAOG^#'I&^/X`#!K&]OX,*H;U_@QZ1O3^``QZQO+^#$J&\?X` +M`#9!``P:PJ*B +M54BB54ER191R196"19:"19>"19B2)1\,`AN9DF4?'?``L@6D=^L98@6D\B4B +M`&8C][8-8$:P($2@FD2B!(`6N@UB!92B)2(`9B.GM@]@1K`@1*":1*($@#WP +M%KH)D@65`)DC%FD(H@65`*HC9AJ&L@7,H?X#T+L0LD7,HE5&HE5'HE5(HE5) +M460##`W!L0/"95.295FB(A0,*RP@]/['B(J+"(J,,&PNJ"\S#^@BS^A*S^A6B94RM`J5&`6)E4_(B%/DEL@>PX@** +MT@?,P@>SX_L!H@?/#![3^P.2!],,#LF4X'?""`HJQ_@.A3P.\>,('L,"ZDYT+AL'_```68_&2)R(+ +M@PN9@_D(X_D4T_D8F<5IQ?(G(@O_@_\(\F5,!KW_#.E&G?\``,('L,"KDYT* +M1K/_`#:!`*T"I3P!T4\#060#+!LQ8P-L^@P^43,##`;"HG#*POT&DB7P8_\! +MX_\#H)D0DF7P@B/"B1%R#$.B#%^2#&-S_P6S_P:"##YR#(2C_Q*3_Q2#_Q5S +M_Q[R9#C9E&)D/*(B%;(,A`R7L_H(HF1"DB+%@B+"\3($K0::B()D1_)D2+(B +MHM(BH^/Z`PN["]W`NQ'3^PRR9$FB9$J2(B"29%-B9%F"(A^"9%@`-Z;P$*;A +M,P3B8A'2(A'28T*(;*A\N'R8;+"9@J/X")/X$()C4W(,X7?G&N(,X?*B<-(L +M)@#N(R#NH/#N@.(N.N#=@-)C4J(,P;*B<((L)@"J(R"JH+JJHBHZJHB"8T[X +MXNALO0;8\O#N@ASJX_L0T_L(LF-(HF-4B&P,&X"`)()C1OA\^2%IPF)"#F)" +M#Q;O$\EA#`_Y408$`(A1LD(.F"$;B(E1D(C`%B@28D(/PB*B#`H6//[M!@R] +M8_T*L_X&8_X'L_T18_T58_X,Z3'9008%``"(PAN(@(`DB<*R0@_R(J(;JO>Z +ML9C"P3$$`!E``-NA=H`)XB--"\SG#02,',;[_Y$Q!`R-S0KX4>C"@@(.\_P( +M_0RS_Q#C_Q&#_QFS_Q2S_Q;YQ&)D#.("#X("#O(B#./]"(/]"6/]"O/]$7:` +M"((C@PN9C%B,.0;\_P``>#']#``]IF/_$&/_$9("#H("#^C"D_<3@_<4X_\< +MD!"FB$$`.*:S_Q]C]Q5C]Q9C]Q=R8U7R8\GB(J(,B>M`@O="^[C_0BS_1*S_1729$RE$P'19@-B9$5R +M8\+B(A3I),(B%=#,(,)D0K(D0J(B%:)D0I(D0FG"8D(.8D(/\B7P'`B`_R#R +M9?`=\#9!`)+2`C()N@P-%N,*TF(&@@*-8J`!%A@-H@G/\30$K"JR"<\Q.@2R +MR_\6:Q7""<^A/`3"S/X67!7B"<^!.P3BSOT6/A3Y/U'IS&,@F^P@F^X@F^:LP+S&KNX_4``!Q``/NA +M,/_`\_4$&V:<=#()O_()OTHS,_4,"S,`$T``ZZ'P[L#C]1`,A&>T!!NG8J`` +M4F@D2X@=\``,!<;J_]ER@@G,MBA.H@G/G(JR"<\+NQ:K#<()S\+,_A8<#^() +MS^+._1:.#?$U!/EB!A,`,@G/P38$G(.""<\+B!:(":()SZ+*_A;Z";()S[++ +M_1;K",ER!LW_`.()SYR>\@G/\L__%B\),@G/,L/^%I,*@@G/@LC]%@@)H3<$ +MJ6(,!K()S`P$+#RV*P:!.`3&````@3D$/U +M`!M$%E8`\A=_\_40MF0%&V8K=PP$4F(D2R(=\`P%QO?_.7)&K_^)<@:N_P"I +MI(4%G)4%O($1)"0 +MY)R?H@1$HLK_%AIJ\@1$\L_^%H]P@@1$@LC]%OAQDA07K&F2%!=R5!>B!$60 +MD.2)/\%8+(_X!=@U/\'?/\ +M'L)C.%("CZ($/J+*_A8*&\("C*/Y"))C0HCB@F-% +M\@18T34##!P+_Q;?%/($6/+/_19/%*($M/(BP@"J(Z"JL""JH.JJHBJ!^JJB +M8T28@L"9$8B2@_D4DF-&\B+%XB+"H3($^N[B8T>B8TB"(J*B(J,+B`NJP(@1 +MH_@,@F-)D@18\@0^#"Z,_Z($/@NJ%JI-\@0^\L_^%L].#`H,F%($,/($5J/Y +M`U/Y!_/Y#9)C2N(B(.)C4P`XIE`0IN*@_PPO\_P&X_P4PF(1@B(1@F9"@B*B +M\B*C4B*CXB*B4.Z"\_@(X_@0@F934@*+%K41@@35=^@5H@35DB0C`*HC(*J@ +MNJJB*CFJF9)F4N($M<(D(P#N(R#NH+KNXBXYZLS"9DZR(J*HXICRL*J"C0>C +M^!"3^`B"9DCR!%@+_Q;?"!SO\F94XB*BHM8$X.`DXF9&PB(9PF:`LB(:LF;` +MDB(;F0J"(AR"8T#R(A_R8UCB(AWB9D#"(A[";8`=\`""!#X66`"2`HH6N4WQ +M,P.2+_"0HA06^DJB!+3R(L(`JB.@JK`@JJ#JJJ(J@?JJHF-$F(+`F1'&I__" +M!%A6C.3R`HX6?U2B`HN@K9.C]02&C?\,RJ)F5')F1Y(BHN+6!)"0)))F1H(B +M&8)F@/(B&O)FP,(B&\D.LB(@FV`'?#"!-5W +M[!7R!-7B)",`_R,@_Z"Z__(O-_KNXF92D@2U@B0C`)DC()F@NIF2*3>:B()F +M3@:X_Z($6!;:0\($6`O,%DQ$\@18\L_]%K]#@@18@LC\%CA"#`JC]1'&!_\` +MFJ(6BLY2&@"""@@ID7FQ::%R&@%B&@,B"@P`B".`@$0C^`4B&@(I48)C%5)C +M%G)C%WBQ(F,88F,9@@0^*)%HH5:HRH(*#!9(RHA163&`A<`6J,F"(A62!'B3 +M^`B"8T)2"@B"(L(`52-05;`@5:#J55(E@:D!BE528T12+7V(DGP)D%40@_44 +MF#%28T98D\>9!:(A!<<:%-F!K0*E7O^RHGS!_@/8@>*F-/*C2(@!DJ,H69/" +M6`#"6`+"8Q:"&`*"8Q@&"O\```":HA8*Q%(:`((*"'FQ::$ID6(:`R(*#'(: +M`GEA`(@C@(!$(_@%(AH!@F,:+%B8QQ28QTB8QZ"!#YHH2B15BC`@@H, +M%LB_B&%9(8"%P!8HOX(B%9($>)/X"()C0E(*"((BP@!5(U!5L"!5H.I54B6! +MJ0&*55)C1%(M?8B2?`F051"#]128(5)C1EB3QYD%HB$&QQH4V8&M`B52_[*B +M?,'^`]B!XJ8T\J-(B`&2HRA9D\)8`,)8`L)C'8(8`H)C&P;@_@```)JB%HJY +M4AH`@@H(*9%YL6FA_P#ZHH;.__("B_#L@ZT.1L+^ +M@A16@MB`%F@0DE17!EC^`*(46,"JP!;J#Y)4649?_@""!,2BHSBJHH"'!!:8 +MROJB!BG_`(($Q**C.*JB@(<$%MC5^J(&5O\`@@3$HJ,XJJ*`AP06&.'ZH@:# +M_P""!,2BHSBJHH"'!!98[/JB!K#_`/(49O+?@!:_#))49P8\_@""%&C`B,`6 +M*`R25&E&0_X`HA1>HMJ`%JH+DE1?!C3^`/(48,#_P!8O"Y)4848[_@"0B`16 +MF+3BI(*PFA&"+4^"8T3@F2"2;_"2+5*&?/X``*($M/(BP@"J(Z"JL""JH.JJ +MHBJ!^JJB8T28@L"9$<9S_O($UL($MO><)0P*QO/^`)($UH($QI>8)PP*!O#^ +M``"25%9&%OX``))46(8?_@``H@2V)HH%P@36)HQ3#"I&Y_Z"!-;R!+:''RF2 +M!+8FB40,*D;B_I)49@8)_@"25&B&$OX``))47D8%_@``DE1@A@[^``"B!-8F +MB@7"!,8FC!\,*D;6_O("BPP*\*V#AJS^#!I&TOZ"!-8FB+0,&H;/_@P:1L[^ +M````-D$`#)@`.*8@$*8=\````#9!`)C2B+(,!IZ'""B +M(+*@`,(B"]C")38`J<+HLAONZ;+8TLBRUSSB#!=B0@1B0@5B0@9B0@=B0@AB +M0@EB0@IB0@MB0@QB0@UB0@YB0@]B0A""(J/XLD%D`[*B6(<_`@:0`+I2,6,# +M^+(6+R68U8BR&XB7.!&2!78W:0NB!56B0HAB0HG&`@#"!53"0HBR!5VR0HG2 +M!9QF/1?B!6W<'@Q8`#BFD!"F"_D6_R.BR?X6FB.M`KBRY;8$L@5V!VL,P@55 +MPD(*8D(+!@,``.("B.)""M("B=)""V)"#VFB@B*B^*(]\(<_`L99`)C"L3$$ +M`!E``*>A=H`)PB--"[NG#`2,&\;[_YBBR+*XPJ("#L/Y"+/Y$:/Y&9)B&(A2 +MK0+@"`!6"ANQ,00,BH("#_("#N("$-(B#(/Z"//Z">/Z"M/Z$7:`")(C@PN[ +MC#F,&P;\_PR^`#JF#!L,"=("",(""8(""O(""\+,_<";@Y/]!L("#K("#X/] +M!_/]#)("!,/]$[/]%(("!_("!9/]%8/]%LBBN++S_1>2`@>S_`B"`@;XPI/\ +M$(/\$?/\''/\'[`0II(""((""?(""I/^"H/^$?/^%0`^IM)C5<)CR;C%#(FW +M.16Q,01V@`O2)$,+N]#0%(Q-C"M&^_\`^**8LHC"D_\(@_\2\F1,^,7HHBON +M]SX3H@5V%VH-L@55LD(*8D(+1@,```#2`HC20@K"`HG"0@OP$*:1-0/B*<'@ +MX&16W@2"!<96>`3(PAO,P,`DR<)R0@^XHAN[N:*B(J*8HJ>Y`L:E_VFB^+(; +M__FR(BHD@A,B$!Y[<"AMO_<3$$=H`-8BE#"W=@8!06UO46I_7&^O\M +M!1WP````-D$`8J*4:E(R!=0,.0P',#`4K"."!=2`@!2"R/\66`ZB!=2@H!2B +MROX6^@VR!=2PL!2RR_T6VP[2!=?"!=;0S,`6W`N"!=;B)22`H'2JHFIJ8@;8 +M&\@,&N](#>Q9M!^*B`@`^IJ`0IO9* +M6*)#C``YIJ`0IO8J0(RZ`#FFH!"F/?#V*DT;JJ)#>``YIJ`0IK8J`WSB'?"B +M0WJ"`VX,CX>_)I(#IZP)H@.*)AH;#`(,&[)#C;)#EQWP?.(=\```LD.,1NK_ +M?.(=\`P"LD.-LD.7'?!\XAWP#$S"0XS&X_\V00!"T@(R!.,,^`P"%@,$HJ4" +MD@3C8J,"#!"0L1&X?\< +MUF<5&!SC-Q4-'/F20JP&^?]\XAWP``!B0JP&]O\`(`(S*+0H=\```-::0$*;&\?^2`@W"H#^Q2@06:0*B`@PF6D'"(A@@ +MHB"PO""YPV4;`1:Z!'S2'?"M`N4?`0P"'?````#2`@S2S?L630GB(A@@HB"P +M[B#B8PRE&`$6R@DBK_T=\``@HB!B0@G"0@CR(ACR8PSE%@$6&@0BK_T=\``@ +MHB"R(0#"(0$E(`&"%#(`.*:0$*8]\/;9`6T)8D(0(*(@LJ`*I2,!D@21MIF. +M(*(@90D!%EKX+0H=\```-::0$*:V*0-\XAWPDD(&HA0R`#JFD!"F/?#VV0%M +M"6)"$$;Q_R"B(&)""<)""+(B&+)C#"4/`19*`7S2'?``(*(@LB$`PB$!91@! +M#`(=\,($D;:<#2"B("4#`19*`*`J(!WP`#6FD!"F]BD&DD(&#`(=\'SB'?`V +M80`,"D*B/$I"HD(&HD(0HD((D@29DD('@B2N4J$"LJ0X"X@62`J8HBJ9NIF2 +M"<0Q9`.ZPA8)!@PW`(`!8Z%RT*'?``-:9@$*;&R?^2`@W,R:("$+*@WSWP +ML*H0HD(0P@(,PLS[%JP3(*(@LB$`PB$!I?H`1MG_K0+E]`!M"M(""-#20>9] +M1^("".#B09;N`_($D3S#MI\.@@((-P@"1CP`D@(05KD.H@((IP,:)V87`#6F +MD!"FMBD"QDX`DD(&#`(=\*T")?``#`(=\````+(""+"R029[,](""`RLT-)! +MURP(X@((X.)!YHZC\@((#+CP\D&''Q2"`@B`@D$FJ(^2`@B0DD'FN0*B`@BR +M`@APNR"R0@C&W?_"`@W,S-("$.*@[SWPX-T0TD(0\@(,\L_[%C\*(*(@LB$` +MPB$!Y>T`AJW_@@(-TJ`_P4H$%L@*D@(,DLG[%BD,HB(8P*H@HF,,(*(@Y>`` +M%BH.?-(=\`"R`@W,J\("$-*@]]#,$,)"$.("#"9>8:T"N`'($>7H`(:E_P`@ +MHB`EU``6JO"@*B"0````\@((+`B`_R#R0@AIPT:*_Y("#0`;0I&J?_2`@@<#N#=(-)""&G#1H3_\@((#(B` +M_R#R0@AIPP:,_WSB'?"2`@R2R?L6N0JB(AC`JB"IPR"B("76`!8J"WS2'?`` +M(*(@PJ``PD()TD((LB(8LF,,9=0`%GH%?-(=\-(""*T",-T@TD(()=4`;0K& +MC/\```"M`K@!PB$!9=P`XA0R#`P`/J:0$*;VV0'-"<)"$""B(+*@"N7?`/($ +MD3WP]I\"1I+_K0)EQ0`6&N0M"AWP```UII`0IK8I`WSB'?"20@:"%#(,"P`X +MII`0IO;9`;T)LD(01O#_#`JB0@FM`M)"")(B&)G#)TLG]%@T7?/(=\%)"":)" +M"``TII`0IK8I9'SB'?``XA0TS04`/J:0$*;VV0'-"<)"$*T"LJ`,Y;(`\@25 +M]I\"QAX`K0*EF``6.@6O +M`)($E;:99B"B(*65`!;:!2T*'?``DD(&0J(X2D*B%#3-!0`ZII`0IO;9`"0@P@5J!2)20,)U`@=+SR@)(1 +M<)D@`#FF8!"F``)`?.)@@)&!WPL58$@D(,`#NF(!"F(*/%K$I\XAWP``!@04%0*'5* +M(@=F`B`@8"`@M"D3#`(=\``I$PP"'?```""`A""9E)D#B1,,`AWP```V00!" +MH99*0E(4?P`UIG`0I@P90A2`#`@;9T>W4"Q%9[4)DD(-8L?"0@P@5J!2)20,)U`@=+SR@)(1<)D@`#FF8!"F``)` +M?.)@@)&U"9)"#6+'W,8```""0@TL*61WPP5D$@D(,`#RF(!"F(+]!K$M\XAWP``!02'6`)A!*(@=F`B`@8"`@M"D3 +M#`(=\``I$PP"'?```+*A_B"F0?""$9*@_@P"D(@0L*H0J0.)$QWP```V00!" +MH99*0E(4?P`UIG`0I@P90A2`#`@;9T>W4BQ%9[4)DD(-8L?6L2WSB +M'?```%!(=8`F$$HB!V8"("!@(""T*1,,`AWP`"D3#`(=\```LJ/^(*=!\((1 +MDJ'^#`*0B!"PJA"I`XD3'?```#9!`$*AEDI"4A1_`#6FU"9)"#6+'W,8```""0@TL +M*61WPP5<$@D(,`#RF(!"F(+:5K$M\ +MXAWP``!02'6`)A!*(@=F`B`@8"`@M"D3#`(=\``I$PP"'?```+%!O(#NB8?:H(#NB8H%`P"'?``?.(=\%)#NL;S_WSB'?```)*C +M`@`YII`0IK%A!+:)#'SB'?``4D.ZQNO_``"PN9#""P#"0\BR"P&R0\FB`_@6 +MJ@<`/:;`$*;`R$$6[`9\XAWP`#RFD!"FMED9?/(=\````#RFD!"FMEDN?/(= +M\&)#NH;9_P"20\A20\GB`\@F3F_R`_@6GP8`/::`$*:`B$$6V`5\XAWP``"2 +M0\A20\FB`\@F2F^R`_@6FP8`/:;`$*;`R$$6W`5\XAWP``!B0[!20['2`_H6 +M?1KB`_86GAL`-Z:0$*:V20+&8P"20[3R`]X63P:M`J4H`!;*!2T*'?``8D.P +M4D.Q@@/WC$B2`_H6J1JB`_86BA@`-Z:0$*:V24Q\XAWP8D.P4D.QL@/Z%GL7 +MP@/V%FP:`#>FD!"FMDD"1E0`DD.TT@/>%LT+K0(E(P`62@LM"AWP`.(#R"9. +M30`WII`0IK9)-7SB'?```))#M/(#WA;?`""B(&4@`!9*`"T*'?``@@/(@LC\ +M%O@,`#2FD!"F]BD"AB4`?.(=\)"@!)"Q!+)#LZ)#LE)#K\(#R`O,%GP5T@/( +MTLW]%NT4X@/?%HX8\@/("_\6SQ*"`\B"R/T6.!(`-Z:@$*:V2@)&3P"V.AP, +M*@`TIK`0IK8K`@95`*+*`9*@$*>Y`H95`%9+_J)"CPP"'?``H@/(HLK\%IK? +M`#>FD!"FMDD"AC4`#`*0L`20P03"0[.R0[)20Z\=\))#L](#]Q8M$P`TII`0 +MIK8I`@8_`))#LN(#^1:>$@`TII`0IK8I`D8_`))#K_(#R`O_5E_:D6($`#FF +MH!"F'$BG.`)&.0!\\AWP?.(=\```H@/V%FKF`#>FD!"FMDE4?.(=\`!\XAWP +M4D.TAI/_``!20[1&LO\``+(#]A9KZ0`WII`0IK9);'SB'?``P@/V%MSJ`#>F +MD!"FMDD"QB@`D-`$D.$$XD.PTD.QAJ3_4D.T1IC_`)#P!)"!!()#L/)#L49^ +M_P!\XAWPD@/)"YD6J="B`\FBROU6JNR&/__!8@0`/*:@$*8<2Z>[&7SR'?!\ +MXAWP``"0T`20X03B0[#20[%&A/\`\6,$^OKR#P#R0ZZ&GO]\XAWP?.(=\``` +M4D*/#`(=\`!\\AWP?.(=\"%C!"HJ(@(`(D.N#`(=\`!20[)&M?]\XAWP``!2 +M0Z^&M_\``#9!`(*B5H`B@$("H8*A`A94`)("I!9Y!J("H!:J!2("7ALB`#BF +M0!"F464$0#%!)A0)#`E\XC`I@QWP`$%D!#WP=J(K`#2F(!"F("+5*B,`-*8P +M$*8P,M4Z(@`UIC`0IC`^03HB`#6F,!"F,#Y!.C(,"7SB,"F#'?`,$@;I_P`` +MH@*@#"N,FL("6PPRP"N#!N3_#"+&XO\`-F$`##P,*@P&<6@$O0-=`D+5`H($ +MNC%F!"%G!+R8#!V"!+IQ:00A:@0F&%@6"P@+BQ:X"O9+!;8K`@8T``P"8D3` +M8D3!8D3"8D3#8D3%8E148E15'?`````6.S#)`0N;%@DR]DL%MBL"1H@`#`*B +M1,"B1,%B1,)B1,-B1,5B5%1B5%4=\!:['`N+%B@B]DL%MBL"QI@`#`)B1,!B +M1,%B1,)B1,-B1,5B5%1B5%4=\`!B1,)B1,-B1,5B5%1B5%62!8H6N2*R!+`] +M\!:K(=)$P*)$P:T%I5S^%DH%+0H=\`!B1,5B5%1B5%7B!8H6SB/R!+`+_Q9/ +M(L)$P-)$P:)$PJ)$PZT%I5G^O$HM"AWPK05B1,!B1,%B1,)B1,-B1,5B5%1B +M5%6E5_X62B(M"AWP`(*A`@`XII`0IK8I;WSB'?`,&J)%C9($XA;)+0`SII`0 +MIK9)`@:4`))$S[($YQ8[,P`RII`0IK9)`L:H`-*@`9#`!)#A!.)$OL#-D\)$ +MOX($K`S/AS\"AFP`D6L$`#FFP!"FMDP"AFP`PD3,4*4@LJ`%Y6\"%@I*+0H= +M\`"218T662\,#,)%CJ($XA;J+``SII`0IK9)`H:0`))$S[($YQ:;/@`RII`0 +MIK9)`L:3``P=D,`$D.$$XD2^P,V3PD2_@@2L#,^'/P)&;`"1:`0`.:;`$*:V +M7`)&;`#"1,RB!,RBROP6:D2BHP(`.J:0$*:VB0+&^`"R!,RRR_T6ZTO1;`0, +M;-#9D-(=`-)43,)43>(%C1:^2P`ZII`0IO:)`L:I`'SB'?!B1,)B1,-B1,5B +M5%1B5%5B18UB18[R!8H6WR2"!+`+B!98(LD!HD3`TD3!K07E0?X6BA,M"AWP +M````K05B1,!B1,%B1,)B1,-B1,5B5%1B5%6E/_X6"B@M"AWP`&)$Q6)45&)4 +M56)%C6)%CJ)$S)(%BA8Y+K($L`N[%KLDPD3`TD3!HD3"HD3#K04E//X6^A(M +M"AWPHD3`TD3!1GC_HD3`HD3!!G;_K05B1,!B1,%B1,)B1,-B1,5B5%1B5%7E +M./X66B\M"AWP`-)$P,)$P:)$PJ)$P\9U_P#"1,#"1,&B1,*B1,/&)$PN)$PV)$Q6)4 +M5&)4524P_A;:'"T*'?``?/(=\(%G!``XIL`0IO9<`D:3_WSR'?``D@3B%ADN +M`#.FD!"FMDD"1H0`DD3/H@3G%HHO`#*FD!"FMDD"!J\`#!R0L`20T0321+ZP +MO).R1+_BH0(`/J:0$*;V*0(&30!\XAWP`'SR'?!\\AWP@6($`#BFH!"F'$^G +MOQ%\\AWP``!B1,_&2O]\\AWP``"Q8P2ZNK(+`+)$KI($XA;I,0`SII`0IK9) +M`H::`))$S\($YQ9<.``RII`0IK9)`D:P``P>D-`$D/$$\D2^T-Z3TD2_DJ$" +M`#FF@!"F]B@"AI4`?.(=\```8D3/1D[_``!B1+YB1+\&./_)`=)$P*)$P89U +M_Z*A`@`ZIL`0IK8L`@:"`,)%CH8]_\D!HD3`HD3!AFW_L@3B%JLQ`#.FD!"F +MMDD"1I0`DD3/T@2L#,S7/`+&3```-Z;`$*;V7`+&3`!\\AWP\6X$XJ!^\/F0 +M\A\`\E1*XE1+`#JFD!"F]HD"ABL`?.(=\```TD3`PD3!HD3"HD3#!FS_`%"E +M(*5A`!8J"Z`J()````"H`0PKD*N#HD3,@J$"`#BFD!"FMBD"AG,`%LD?X?X# +MXE14T6\$`#VFD!"FD,Q!%FP'<)$S/($S&8_>%"E(+*@ +M`24F`A;*!BT*'?``D2\$`#FFD!"FD(E!%D@1?.(=\`"R!*P,RK>Z7\%K!``\ +MIL`0IO9,7]%Q!,)$S``]II`0IK8Y`L9<`!9Y(POI%IXAD?X#DE15@6\$`#BF +MD!"FD/Q!%H\=?.(=\`!\\AWP8D3/ADG_``"M!274_1;Z\BT*'?!\\AWP?.(= +M\*%M!``ZIL`0IK9,GWSR'?!B1+YB1+^&1O^M!0PKY1L"%NH:+0H=\`#!<@0, +MB\#)D,(<`,)43+)434;/_M*B`@`]II`0IK9)`H8Z`/%S!$R.\/F0\A\`\E1* +MXE1+AGG_`'SB'?!\\AWP?/(=\'SR'?#"%%20UE30S"#"5%2B%%20L%2`NQ&P +MJB"B5%2"%%2"5%6M!0P+910"%HH.+0H=\`!B1,]&.O\``.($S)"F).+._18. +M%H%L!`QO@(J0@A@`@E1,\E1-PJ!^D-,DD+`DX6X$<+N0LAL`X-V0TAT`TE1* +MPE1+LE10H@3,9CH?\J("`#^FD!"FMDD'?.(=\'SB'?"!<`2`B9""&`""5$]0 +MI2"E*P`6ZN"@*B"0````8D2^8D2_1B/_8D3/1CO_`&)$S\9C_WSR'?!\XAWP +M``"Q_@.R5%2B!*P,R:>Y6<%K!``\IL`0ICWP]DQ7PD3,X6\$`#ZFD!"FD-Q! +M%MT3?.(=\%"E("4Q`!;*VJ`J()```&)$S$95_P"!+P0`.*:0$*:0^4$67PE\ +MXAWP`*T%9;G]%CK8+0H=\)%M!``YIL`0IK9,IWSR'?#"%%60UE30S"#"5%6B +M%%60L%2`NQ&PJB"B5%6&7_ZM!0P+90`"%OH.+0H=\('^`X)45/%O!``_II`0 +MII#L01:N#GSB'?"Q6`3!_@/"5%3"5%4`.Z:0$*:0J'46Z@Y\XAWPX7($#(W@ +MZI#B'@#B5$S25$W&IO_R!,R0IQ3RS_T6KQ:Q=`0,F+"ZD+(;`+)43()434R( +MD-`4D*44L7,$D/(D%T!-*@">#ID.(>`.)43-)43=*@ +M2(%P!+#G%+"2%/%S!+#$)'#,D,(<`*+/,*"9D/#ND%"E()(9`+#P%.(>`.)4 +M2H#_D/(?`-)42\)44))43O)43R4#`!9ZN"T*'?"Q=@0,^+"ZD+(;`+)43()4 +M34:D_]%V!`S\T-F0TAT`TE1,PE1-QN+_-D$`K0+EI?V,2BT*'?```**B2:JB +M@@J;#`R2H0(6N`8`.::P$*9\XK8K`1WPLDIPT@IPXJ("%NT&`#ZFL!"F?.+V +M2TVR2H$`.::P$*9\XO8K-8R[`#FFL!"F?.+V*T4;N[)*;0`YIK`0I@R/?.*V +M*P(=\`"R2F^""F.'/Q8,`L)*@L)*C!WP`!WP``#"2H$&[?\=\)(*G`P"#!N< +M&;)*@K)*C!WP'?``#$W22H&&Y?\,`L)*@L)*C!WP```V00"M`@P[)=4!C"HM +M"AWPPJ))RL*"#)P,"@P=K-CR#&.!=P0,CO<^$@`XII`0IKP9)ADX)BD^?/(= +M\`#23(+23(RM`B7!_8RZ+0H=\*),@J),C,;Z_ZT"Y93]#`F@J8,M"AWPHDR" +MHDR,!O7_TDR"TDR,QO+_#$L,*J),@M),C*T"9031>P0F.B2Y +M4AWPK!,F$SKV0QRV(QG!>@3)4AWPG*,F$S#V0Q6V(Q)I4AWPV5(=\.%\!.E2 +M'?!I4AWP\7T$^5(=\`!!?@1)4AWP`(%_!(E2'?``D8`$F5(=\``V00`\^8&! +M!))""`P)DD()`#BFH!"FTJ$"LJ70NL+VV@*@FB"20A"HW"8:3YBB*IFZF9() +M/))"!J*B4*JBX@I[)BXDD@J%DD('L@I]MIL,K0*ES_Z,2BT*'?```-%D`\(B +M&`P"R%IBB*IFZF9()Q,;R_P```#VFD!"FQNO_`#VFD!"FQNW_ +M```V00`,"3SZHD((DD()DJ<@FH*"*!_2H0(F&&2HHBJJFIJ2"82Q@0220@0` +M.Z:0$*;"I=#*LK;9`WSR'?"20A#HVR8>5YBB*IG*F9()/))"!J*B4*JBX@I[ +M)BXMD@J%DD('L@I]MIL,K0(EQ?Z,2BT*'?```-%D`\(B&`P"R%9BB*IG*F9()Q(;P_P``/::0$*;&Z?\`/::0$*;&Z_\``#9! +M`)*C\)J"@B@?/0*RH0(F&&2HHBJJFIJ2"80,&@P"460#0J(X2D.L69%)!")# +M!")#!2)#!K($G;)#!R)#$")#"*)#"8(C&)"(((G%*<4=\")#!N($G>)#!R)# +M$")#"-(4,``]IJ`0IM&"!,(4,=K:QSH,?/(=\``[II`0IH;F_](-`-"$!-"5 +M!-#`%,)#"9)#!8)#!/(#"1;_""=M$.(4-``^II`0IO;9`2T)(D,0\@,)#"8F +M'Q."`PF"R/X6*`F2`PGA2P0]\"8Y(Z%*!+(#!9(C&-##!+/Z&*"9()G%B',, +M"ZT#X`@`K#HM"AWP`/(#!=(C&//^&.#=(-G%PA0S`#RF4!"FMK4S?/(=\``` +M@@25]I@"QB$`D@,0%AD(K0.EKOX6F@;%-!*(C&`P"L*H@J<4=\```/Z;0$*96;?[J\_(/ +M>@#_(_"RLP`[II`0IGSRG`F"R?\6N!6BR?X6FA>RR?T6^PH=\.I#PD,&PD,' +MPD,0PD,(DA0R`#FFX!"F@A0S<8($ASX.?/(=\````#^FD!"F!M3_>N[B#@#@ +ME`3@=03@@!2"0PER0P620P2"`PD,-Q8($:J#@B@>)AAKF*,ZF:J9D@F`%HD& +M)VX4HA0VP)P@`#JFH!"F]MH"H)H@DD,0T@,)X@,%LB,8P-T!P_T6X_T8T+L@ +MLF4,X@29MIX/\@,0C)^M`R6*_HPJ+0H=\`P"'?```(%1!"(C&(`B("G%#`+) +MQ(4-``^IE`0 +MIO9%`L98`'SR'?"Q202B(Q@,`K"J(*G%R<4=\#S]TD,(`#^FD!"FMBD5?.(= +M\`#Q4@3B(Q@,`O#N(.G%R<4=\))#!``_II`0IO8I9HSY@A0V`#BFD!"F]MD! +MS0G"0Q``/Z:0$*:V*0-\XAWPDD,&H@29]II%#`*R(QBYQ1WP`'SR'?#@PP2B +M`PFR`P62(QC`J@'3^A:S^ACS^AJ@F2"9Q8ASLJ``,*,@X`@`%@KJ+0H=\`!\ +MXAWP?.(=\*T#)73^%AK[+0H=\`P/1K[_L@,%%LL0`#^FT!"FMBT"!C\`)VX1 +M\A0V`#^FD!"F]MD"D,D@PD,0@@,))B@"AB``P@,%8_H6LB,8P_H8T_H:H+L@ +MN<62%#0`.:90$*;V10(&,0!\\AWP)VX0TA0V`#VFD!"F]MD!S0G"0Q#R`PD+ +M_Q;_#((#"68H:K&$!,(#!:(C&,/[&+"J(*G%DA0U`#FF4!"F]K4"QB0`?/(= +M\```8,40B'.M`PP+X`@`%EH++0H=\`#@PP2B`PFR`P62(QC`J@%C^A:S^AC3 +M^AJ@F2"9Q8ASLJ``,*,@X`@`%DK:+0H=\```X,,$H@,)L@,%DB,8P*H!<_H6 +ML_H8H)D@F<6(E5/X6J@=\ +MTAWP`(*A`@`XII`0IK8I`WSB'?"20@8W9!F2$S0`.::0$*;VV0%="5)"$*(B +M&*G'#`(=\*(B&*G'#`(=\*T"B'(,*T#"!.`(`(PZ+0H=\``W9!"2$S0`.::0 +M$*;VV0%="5)"$*(#E;::([("$)S;K0)E0_Z<:BT*'?"M`@PKB'(,C,#&$.`( +M`(QJ+0H=\`P"'?"M`@PKB'(,3,#&$.`(`(PJ+0H=\*T"#"N(<@PLP,80X`@` +MC$HM"AWP``!@P`2(M`J4T_A;*!WS2'?```#:FD!"FMBD'?.(=\'SR'?"20@8W9!G2 +M$S8`/::0$*;VV0%="5)"$.(B&.G'#`(=\.(B&.G'#`(=\'SR'?```(%3!/(B +M&(#_(/G'`#:F8!"FMB81?.(=\*&'!)(B&*"9()G'!N/_K0*(<@P;0,($X`@` +MO'HM"AWPK0(,&XAR#(S`QA#@"`"\:BT*'?``L50$DB(8K0*PF2"9QXAR0,($ +M#!O@"``6&NXM"AWP``#-!HARK0(,&^`(`!;:["T*'?``K0(,&XAR#$S`QA#@ +M"`",*BT*'?"M`@P;B'(,+,#&$.`(`(PJ+0H=\&#`!(ARK0(,&^`(`!8:Z2T* +M'?``-D$`#"D65`1RHC!ZT*A98"R!DH&(F)&!, +M-&`@-!;""("R$9"[(``[IH`0I@`"0'SB@*"1%GH&'?!\\AWP#`)!9`/V(P4I +MQ`P"'?#"H0,`/*9@$*8Q8P/A,02V)@8,!@R-TF.!8_(;*<0BH`!VKA."(YAB +M(YA2(YCR(YAB)#L;(@?F`PP"'?`79A"BH0(`.J:0$*:V*01\XAWP``P"'?!@ +M5'2`(4%:(@=H`B`@8+R$@+01D+L@`#NF@!"F``1`@*"1G&I\XAWPT54$`#VF +M0!"F0,'EK,Q\XAWP``!@4-6`04%:1`=H`D!`8(('G#WP]B@%\"(1\$01()#4 +M0""TD_(,QL[_0"B$0$!T!O?_````-D$`#"D65`1RHC!ZT*A98"R!DH&(F)&!,-&`@-!;""("R$9"[(``[IH`0I@`"0'SB@*"1 +M%GH&'?!\\AWP#`)!9`/V(P4IQ`P"'?#"H0,`/*9@$*8Q8P/A,02V)@8,!@R- +MTF.!8_(;*<0BH`!VKA."(YAB(YA2(YCR(YAB)#L;(@?F`PP"'?`79A"BH0(` +M.J:0$*:V*01\XAWP``P"'?!@5'2`(4%:(@=H`B`@8+R$@+01D+L@`#NF@!"F +M``1`@*"1G&I\XAWPT58$`#VF0!"F0,/%K,Q\XAWP``!@4-6`04%:1`=H`D!` +M8(('G#WP]B@%\"(1\$01()#40""TD_(,QL[_0"F40$"$!O?_````-D$`#"D6 +M5`1RHC!ZT*A98"R!DH&(F)&!,-&`@-!;""("R +M$9"[(``[IH`0I@`"0'SB@*"1%GH&'?!\\AWP#`)!9`/V(P4IQ`P"'?#"H0,` +M/*9@$*8Q8P/A,02V)@8,!@R-TF.!8_(;*<0BH`!VKA."(YAB(YA2(YCR(YAB +M)#L;(@?F`PP"'?`79A"BH0(`.J:0$*:V*01\XAWP``P"'?!@5'2`(4%:(@=H +M`B`@8+R$@+01D+L@`#NF@!"F``1`@*"1G&I\XAWPT5<$`#VF0!"F0,:5K,Q\ +MXAWP``!@4-6`04%:1`=H`D!`8(('G#WP]B@%\"(1\$01()#40""TD_(,QL[_ +M0"JT0$"4!O?_````-D$`#"D65`1RHC!ZT*A98 +M"R!DH&(F)&!,-&`@-!;""("R$9"[(``[IH`0I@`"0'SB@*"1%GH&'?!\\AWP +M#`)!9`/V(P4IQ`P"'?#"H0,`/*9@$*8Q8P/A,02V)@8,!@R-TF.!8_(;*<0B +MH`!VKA."(YAB(YA2(YCR(YAB)#L;(@?F`PP"'?`79A"BH0(`.J:0$*:V*01\ +MXAWP``P"'?!@5'2`(4%:(@=H`B`@8+R$@+01D+L@`#NF@!"F``1`@*"1G&I\ +MXAWPT5@$`#VF0!"F0,AUK,Q\XAWP``!@4-6`04%:1`=H`D!`8(('G#WP]B@% +M\"(1\$01()#40""TD_(,QL[_0"O$0$"D!O?_````-D$`#"D6M`5RHC!ZT0$T0$T0$T0$BH@(`.J:` +M$*9\Z@R,MD@$AO;_``"2`W8660X`.Z:0$*;V*0)&*`!\ZD;P_P!20R<&\_^M +M`J7]^Y8J$EG"4D**6?)9XK(#0+)#3%)"BUG28D.:H@-`HLK\%OH2P@-`G,S2 +M`T`+W1;=#N(#0.9.#_(#0*8O"8&(!(E2Q@,```"2`T22R?T6:0RA>02I4JT" +MX@-;XD-(T@-(#=Q:N!P`[II`0IK8I*GSJ1KO_`%)#-<)#8,)#84;R_ZT"0D,X@A,H +M@E,.\A,I\E,/Y0G\#`K&L?\6^0I"0T#"`T`6+`S2`T`+W1:]#.(#0)*G`B8N +M=?(#0"8_?PP*QJ?_@7L$B5)&S?^1?@294D;+_PQ"'?#"0V#"0V'&VO\``$)# +M0`;N_ZT"9:/ZD@/A#!@,(I`HDQWP`%)#0`;H_ZT"0D,X0D,Y4D-(4D-)4D-* +M4D-+Y>GZK0*E!_L@HB"ET_NR`^$,&@PBL"J3'?``.:;`$*:V[&=\ZH:)_P`` +M`#FFT!"FMNUH?.J&A?\``/%B!')#0``_IL`0IAQ>YQP$'&W'O2E\^D9^_P"M +M`N4J_%8*WY(#6A9I'T81`*T"Y2G\5OK=L@-:%LL>1A$```#7'%&!B02*C((( +M`()#)D;`_ZT"I2?\5KK;T@-:%LTC1@\`K0)E)OQ6JMKR`UH6/R,&$`"A9@0` +M.J:0$*:V24A\^@9D_\%F!``\II`0IK9)4WSZQE__8D-`4D,F!JW_``#A9@0` +M/J:0$*;V20)&00!\^@98_X%F!``XII`0IO9)`@9#`'SZ!E/_DD-'D@-T%FD; +MHJ("`#JFD!"FMDEG?.J&3/\``))#1[(#9)RKP@-D"\P6?!O2`V32S?X6?1WB +M`V0]\.+._19^&X(3*()3#O(3*?)3#ZT"Y>S[8D,X0D,ZDJ$"`#FFD!"FMBD$ +M?.H&.?\6B1Q"0T2M`@PK)3D`5DK-QK$```"20V2<":+)_Q:*(;+)_A:;)\+) +M_18\)>(3*.)3#M(3*=)3#ZT"I>?[0D,X@@,D#,^'ORN1:`0`.::0$*;V62NB +MR?P6&A^20T2R`T2RR_U6ZPVM`@P;)3,`5DK'1C0``,%G!``\II`0IK99TWSZ +MQA?_DD-'T@-T%IT2XJ("`#ZFD!"FMDEF?.I&$?\`DD-'\@-DG*^"`V0+B!:( +M$Y(#9)+)_A9Y%:(#9#WPHLK]%GH3PA,HPE,.LA,ILE,/K0(EWONM`E)#15)# +M1N4;_%8:P-(#)`R,U[P"1CD`QF@`4D-'QJC_`%)#1P:N_P```))#9)P)TLG_ +M%OT=XLG^%BX@\LG]%G\>DA,HDE,.@A,I@E,/K0+EV/NM`E)#15)#1J46_%;: +MNN(#)`R-Y[T"1C@`AF(`K0*EVOM6>KG2`HP631T&7````%)#9+(3*+)3#J(3 +M*:)3#T:S_P``4D-'1L7_``!20T<&RO\``-(3*-#10=)3#L(3*<)3#T:5_P`` +M\A,H\/%!\E,.XA,IX.%!XE,/AH__DA,HDE,.@A,I@(%!@E,/!HO_`%)#9+(3 +M*+)3#J(3*:)3#T;6_P``4D-$QHS_``#B`UT6K@MR0T-R0TUR0RMR0HR&%?^" +M$RB`@4&"4P[R$RGR4P\&M?\`HA,HH*%!HE,.DA,ID)%!DE,/AJ__PA,HPE,. +MLA,IL+%!LE,/!JO_`/(#719?"G)#0W)#37)#*W)"C(8!_Y(3*)"109)3#H(3 +M*8)3#P9[_P#!_@/"4Q"R`R0,RK>Z6=%K!``]II`0ICWP]DE7\6\$DD-$`#^F +MD!"FD.Q!%FX+?.I&F?X`DA,HD)%!DE,.@A,I@(%!@E,/AFC_4D-#4D--1M#_ +M``"R$RBR4PZB$RF@H4&B4P]&8?\``,%M!``\II`0IK9)IWSZQH?^``!20RM2 +M0HS&V_Y20T-20TV&U?\``*T")<'[5AJ@P@*,PD,KQM3^\A,H\/%!\E,.XA,I +MXE,/1HG_``"2$RB0D4&24PZ"$RF`@4&"4P^&@_^R$RBR4PZB$RF@H4&B4P\& +M?_\`"*(!B)SB*9F)E3L(E0Y$Q!+(E0Z(E0W:I!=(E0Q;]_PP"Q@`` +M``!\XC$S`V%"`PP.XF57Z0%V@!'R(^?P\!0F/PM(`1M460%'-@+&^?\=\`"1 +MB@0`.::`$*:V>`-\\AWPLJ"(L+."NK(,`MJ[HFM_'?#BH(C@XX+JXMKN@FY_ +MHD>=@F57XBZ`PB*@B,*D),K"!@(`ZKOJS.JJUQI&(BI_ +MMB+P)B)!9C+J#`2"*H`R*<'P=4$B*:(ZB(!WH!9"_5@!C0P`!4!V@!=8!QM$ +M4%"14%`$4DA08BFBV +M1V+"P%*D))I+4$2`8%`4=I4*,%`$4D20,#%!&T1@(D%VDB4P(`0P44$P800P +M<@0P,P1+1")$C&)$C5`A07)$CC)$CR`A02`Q02(IHC@X8J!@)S8"AJ/_4J0D +MFDMBPJ!@@!1:1':8"C"`!()$L#`Q01M$8")!/?!VDB4P(`0P44$P800P<@0P +M,P1+1")$K&)$K5`A07)$KC)$KR`A02`Q08:0_P```#:!``Q&'#=!-0,<&0P% +M@J**TJ,>LJ0(./*BHH@Y4>+#6/+#0/DQZ4&JH[JSVM/9(;D!HF$!@#.`4D/? +MDF0\@@.7@F0\H@.8/?`F*CA20Y0`-J:0$*9R9#R29#PF&3DF*38,A!92_IR%$,'EFL6;Q9S%G<6>Q9_.),BK(#)@P=L+V3LDR+H@,_HD-* +M4D,\4D,X4D,Y4D,[4E,/4E,0D@,FS-D,'PPH@D,V\D,WQ@(````,*0P:HD,V +MDD,WJ%&RH`;R`UGR0T;B`UKB0T?2`U;20TC"`U?"0TFR0YBR`S^EZ?VB(05E +M3_JH425M^JA1Y07ZJ%%9JE)J"Z7:^0PH@D.81@4``*A1903ZHB$%4FH*6;HE +MV?D,*9)#F":2$*+"]18J)++"]!8+%0S]9_^(#/N)#2M(#/F9-+ZA1#"B2H`-2 +M2HN20YB"0S:"0S=20T920T=20TA20TDE/?JB(06E6OJH4>4F^P86`*(#,&8J +M%\A1X@,F#!T,"^"]@[),BV)#F`8#`````(A1##]22(OR0YBB(06R`TKETOW" +M`UG"0T:R`UJR0T>B`U:B0TBH49(#5Y)#264W^J(A!>54^JA19>[Z#"(&5O\< +M;_)D/.(#F.)D/-(#F.8]!8(#F-;X`9(#F)+)_18I"Z(#F.9J![(#F#WPYDL0 +MP@.8PLSZ%KP)##(&1_\```#2`YAF302H4:7H^0P:N"'"`Y/8,>A!Y0CI#!J( +M40QKLD.86:A9N%G(6=A9Z%GXHDB*\@,F#!FM"/#YD_)(B^(#/^)#2E)#/+(# +M/R4*_?Q*HB$%\@-9\D-&X@-:XD-'T@-6TD-(P@-7PD-)L@,_)<7]J%$E*_JB +M(06E2/JH427B^@PB!B7_*YH,B`PRD"B#!B+_````J%'EW_FH45FJ4FH+I;3Y +M##(,*J)#F`8;_QQ=TF0\P@.8PF0\L@.8YCL%X@.8UDX-\@.8YE\%@@.8YC@1 +MD@.8DLG[%OD+H@.8HLKZ5FH+P2\$`#RF\!"FS0_PN4&,.PR"A@C_S$\,,L8& +M_P#84=(-BLR]Z%'B+J/G/R0,,H8!_XA1@BBCA[\$##)&_OZ84<(IHY(IH\#/ +MP)<\!`PRAOG^N%')VZ*A`@`ZII`0IK8I!`R"1O3^O(FH4:6R_(RJ*]H,C`PR +MT"R#!N_^J%$,&()#/+(#/^(#/O(*BO"^@Z7W_(S:*[H,B0PRL"F#!N;^```` +MJ%'E&?JB(04ET/JH4>70^@PB!N#^##+&WOX`(,A!C#P,@@;<_@PB',W29#R& +MV?X=\```-F$`2.(,!W)D-H(B&HE44B(<663"(A;R(R#*__F$XB,ARN[IE-(C +M(LK=V:2R(R-1BP3*N[FTDB6$?!J@F1"2982``*:,F':`!)``IHP9!OW_X!"F +MZ>30$*;9],`0IL)D$+`0IK)D$3WP\"``H`"FC)IV@`3P`*:,'P;]_\`0IL)D +M$K`0IK)D$Z`0IJ)D%)`0II)D%3WP/?"``*:,F':`!-``IHP=!OW_H!"FHF06 +MD!"FDF07@!"F@F08\!"F/?`]\.``IHR>=H`$L`"FC!L&_?_`(`"`$*9@$*;P +M$*;@$*8<#"P&T@1+HB,:O08+W="\@^7,`AR,X8P$\J"`DJO_@8T$O0K2(QS2 +M5!FH8]AS>32R5!BBRC_0T/2`JA"R)8JY)*)4&M)4&X(#X*$X`Y"[$("`!()D +M.6"($8"[(/"[(."[(,"[(&"[(+DDDB,UIQD'XJ8`X.L@Z23R!$F"`^&"9#CP +M\!0F/PCPW1'0T/325!N]`0P>),?@Q\/`4^3'H,28^`@;Z_Z%A +M`Z)IVAWP-@$!..*2(SJ"H`""8106*5K"`TP;Z>)C.A:\6L%@`PP?#`ZQ-0/B +M8S#R8R[2*R#9`9@!H3,#XF$3P)D0DFL@@B,XD8L$LA,:@(`4@FF#^"/R:8K8 +M,\&.!!P.X-T@V0RR:OB(8X)IB?@S\/`49A\4@A,9H3,#@)#$@(%!`(@1D(@@ +M@FP5\A,;XA,9`/\1\.X@XFP7N(.R;!B8DY)L&8BC@FP:^+/R;!OB`TFR$QJ2 +M$R'@X!3BSOT6KEX;F="9$9";@MASL@-+XJ_`TLT_X-T0V2'0V9#2S3_@W1#9 +M0=K9TLT_X-T0V6'0V9#2S3_@W1#9@=K9TLT_X-T0V3'0V9#2S3_@W1#94=K9 +MTLT_X-T0V7'0V9#2S3_@W1#9D28;5=$U`Y(JK-(M()"P!`=I!WSNX.D0XFJL +MP"``@34#\J$`\/T@\F@@\B@@XJ[_X/\0\F@@/?!V@!#B*N?IH=BAT-`4V:&( +MH28X!:$S`\;X_\`@`(P;DFJL\B,RB[&P_Z#X#_F(Z$S`^$U`Y(JK.(N()#0!`=I"/*O +M_O#Y$/)JK,`@`/$U`X%@`\#N(.)O(.(O((#N$.)O(':`$^(JY^GAB.&`@!2) +MX?CA\L_]%K\E1OG_``"@$*:B8R60$*:28R:`$*:"8R?P$*;R8RBR$Q@F%@S" +M(RX,;3WPT,P0PF,N9YL,XB,N#"\]\/#N(.)C+I(A$^(%"\(%"O(%#2(%#[(5 +M!*(%#M(%#+"&5"JJ^MWJS-K,RJJB8R\H%9)C*Y)C+2`H=198)K"&!+#+!+": +M!+#9!,J9L,@$VLRPUP3:B,J(FHB'N@P,C>$S`PP?\F,KTFZP#!F-`H")DX)C +M+)R2LA4!HB,ML+`$L*H@S+H,3-$S`PP>XF,KPFVP\B,P@B,I@F,JC#^2(RW, +M6:T#O05E.P`;;$18B`">4"\(C+M*@!-#, +M(,)C+JT#O04E0``;1'>4T.(A$)(#2QP(+`\+F9#X@_I55YX"4B$18B$2LA,8 +M8L8!8F$28L8!9[L"QFO_@B,V5IC:DB$14)G`5OGLH`"FC)IV@`2P`*:,&P;] +M_X`0IH)C&?`0IO)C&N`0IN)C&]`0IM)C'#WP/?#``*:,G':`!)``IHP9!OW_ +MX!"FXF,=T!"FTF,>P!"FPF,?L!"FLF,@/?`]\*``IHR:=H`$\`"FC!\&_?_` +M$*;"8R&P$*:R8R*@$*:B8R.0$*:28R0]\#WP@`"F%JCB=H`%T`"F%AWBQOS_ +M``"1-0/B(1,,&()I+B(C-@P_(.^3+0X=\`"B`TL+JA9*I<$U`PP"#!NR;"X= +M\-(#2=#0%"8]!^(#2@ON%BX2HB,R#!B2$QR`JC"B8S(PJJ"2:C3R(S*`_S#R +M8S.&B/Z"`TP+B%9XNYBQHJ0`H)D@F;$&[?X``,`@`(P=DFJL#`X,#?$X`X8! +M`(T.&^Z'.Q*!BP2"*(B)`9@!EP\"TLT!MEWEYSL"1M;_T34#DBJLTBT@D+`$ +M!VD'?.[@Z1#B:JS`(`"!-0/A8`/`_2#R:"#R*"#@_Q#R:"#2*N?9\81I(C,@N*%B@*L.F@Z`[IW*(C,M"JH*@*J?RA,P/&S?X,0AWP@B,R\A,< +M,(B@@B@T@/_`%M^0#`(=\`P9DF,MQD[_#!(=\```)AIXHB,RL*J@J`JIW)(C +M,M"9H)@)F?R"(S/@B*"("(GLHB,S\*J@J`JB;!"A,P-&M_X``((C,["(H(@( +MB=RB(S/0JJ"H"JG\DB,SX)F@F`F9[((C,Z$S`_"(H(@(@FP0!JO^`."YH+@+ +MN>RB(S+PJJ"H"J)L$*$S`\:D_H(C,["(H(@(B=RB(S/0JJ"H"JG\DB,RX)F@ +MF`F9[((C,J$S`_"(H(@(@FP0!IG^`#9!`"*@[!WP-F$`HJ#LO0$,#(CBB0&E +M%^A-"K*@[.4T`GSYH9$$*02QD`2R8C2B8C.29"F29"J29#229#4,`AWP```` +M-F$`3!JE=>:1BP0,'<`@``SK\B(WTF(VZ!(;__)B-]D.PBF$R0&Y$:@1B`&@ +MB""":83`(``=\``V00!B(BY"(BU=`F!@%)RD@""FC)AV@`20(*:,&0;]_P`V +MI@P"8F4I'?```((3`:("4`R'@)`$X)D1@()!<'@0D&8@<&8@K&J2`E&0D!3` +MF1&09B!R)2^1M0."$P1P<*1`=Q&0B!"`9B!P9B`&Z/\`/`J@J!"@9B`&]O\` +M-J$!#$6A80/A.`/!3@1(,O&2!-&#!$!`%(ST"X06"!"BQ/X,"7SRH"F#'?"R +M(BYB$P!!0`."(BU@[X-`3B"`Y)--#B=K`J!.(%(3`>&3!)&4!%"P)!;+%R=E +M`N!$(!=E`I!$(%"`!()A)@=E`M!$(%=E`L!$(-&5!'("2<&6!')A)'!P%!8[ +M%;&7!%"(%."(`;!$$$!(((&8!"(2(&"F(("$$"+"`2"R(`!'$8!$("4C`KT" +MD9D$HF$EH(!T@(@18*8@D$00@$0@Y24"@J\`LB$F@(00H$!T@$0@%ML0#`X, +M`PP-#`L,!@P*#`(,#PP)D(`T4(@!@$0@P&"FC)QV@`3`8*:,'`;]_P!TIH+) +M_A98$<+)_!9\&B:)-1LI'?```((B+/`@`!88$J(B+K(3`%":$!;;%U>*`@8E +M`$&:!,!@IHQ,T&"F5IW_`'2F#!(=\(!@IHQ(P&"F5IS_`'^F@&"FC$C`8*96 +MG/\`Z8]\,!@IHQ,\&"F5I__`'VF/?"`8*:,2*!@IE::_P!SICWPL&"F +MC$O`8*96G/\`?J8;*1WP#`(=\)!$(`:B_P#`A""RQ_W01""P2)/&JO\`#`QA +MFP3AL0.Q-@/QG`31G00AG@2"Q_T6V!(+AQ:(#Y+'_A8I#PP.#`,,#0P+#`8, +M"@P"#`\,"4:R_P``H&"FC$JP8*96F_\`?Z8]\,!@IHQ,T&"F5IW_`'*F&RD= +M\```@B(M5GCMDB(K5AGM8A,`LB(N8.^#30XG:P*@3B!2$P$]\`=E`M!$(-(" +M268]`L;7`@8E`)&5!)"7P!:I#/"'P!9H$`P&#`H,`@P/#`D, +M#@P##`T,"\9N_Y'"`Y"$$()A(Y>$-`P.#`T,*6&@!,#Z$2(A)0P*\/"TP"(1 +M(#&T("*T0#,1L#,@0"(1#`M@,Q`P_R`,!@P#AE[_@94$\'00@(?`%B@ID98$ +MD)?`%ADL\(?`%C@O#`X,`PP-#`L,!@P*#`(,#PP)AE+_D<(#\90$D)00DF$C +M\)G`%IEE@9,$\B$C@/_`%A]T\<(#DB$C]YD"!HX"#`8,"@P"#`\,"0P.#`,, +M#0P+QD+_@<(#D90$@(00@F$CD(C`S!@&!`+QDP22(2/WF0+&^@*-"9'"`Y>8 +M`D9V`PP.#`,,#0P+#`8,"@P"#`\,"<8R_P``#!^1H02!E`0B(2201!"`1"`, +M*(`B$(*3"9T"D)^3@F$?_0N281B0_9.`D2&`F2.282+PF1&7&`6!0`.`_R"2 +MDPB282&0<2&`=R/PAQ&'&0>!80,]\(#_(`P6#`62DPN281X@5H,AH@1B(252 +M81=0O9.0@2&`B".)(5(A(L!F$2`O$&I54%"T0%414"(@4:`$V"'PB!%0(A#` +M6A%:]_#PM"#_("T+AQD%(4`#("L@@I,*@F$@@+$A@+LC\)L1EQ@%@6$#@"(@ +MHB$?DB$B&XJ`@2&@B;.AH@1JG9"0M$"9$:"B$"&@!)"J()(A&""J$%HK(""T +MH"(@K0R0KI.`D2'PF1&7&`610`.0JB"2(2%B81(;B8"!(9"'LX"1(?"9$9<8 +M")%A`V)A$I"J(%!1(3(A(9(A%V(A'QN#D,Z3@($A,(>S,B$B&Y:0D2%@D[-A +MH@0R(1*0D2%@:A`P,4&:DX"A(9"0M$"9$9!F()&@!*JEH*"TD&808*H@8B$> +M&X:`@2%@C;-M#("1(?"9$9<8!6%``V!L(,(A((+,`8"!(<"+LX"1(?"9$9<8 +M!9%A`Y!F(.(A((&B!!N>@(80D)$AX)NSXB$>D&$A#$D;SL#!(>#-L\#!(8`@;W!`P&#`H,`@P/#`D,#@P##`T,"\:H_H&4!/(A(X>? +M`@9T!/&3!)(A(_>9`@9L!8T)D<(#EY@"1NX%#`X,`PP-#`L,!@P*#`(,#PP) +MQIK^(:,$L/L@<90$@:$$DI,)DF$?@$00<$0@@I,(@F$AD'$$%0 +M@4&"81J`9H!@8+1`9A%@(B#`:A%`(A"AI`1"DPM@]X#P\+1"81X@_R`M#4"1 +M(9)A$4!!!$`JDY*3"I)A($(A)Y"!(8"((X)A'?"($8<9!8%A`X`B()*3#6)A +M'))A%9"!!(#:DX&B!)"A(:G!DB$>HB$:@((0D)(A(B$=F7&JF9"0M*T-0)D1 +MD(@@D:`$:B(@(+20B!"2DPR`(B"281:0@2&`B".)8?"($8<9!:%A`Z"M((&C +M!&&B!)*3#Y)A%&!J$)#1(:AAD)$$TF$0D+B3@B$5TB$:DB$<@((AB:':B("` +MM$"($8!F((&@!)"J@*"@M(!F$&"J((*3#H)A&;!K(("1(8"9(Y)A&_"9$9<8 +M!6%A`V!K()(A%(&B!)"2(9F!@(80VIF0D+1`F1&0B""1H`1B(1N0B!"2(1RX +MT9IF8&"T@&8@F.$;BX"!(;")LY%``X"`!+T,@+F3DB$A&XF`@2&0A[.`D2'P +MF1&7&`7180/0NR#8T8(A(5`R03)A$U(A(!N8D)$A@)>SB.$;?7!Q(=!XL](A +M'7!Q(1N%@($A>C,P,+10C;/2(1%`,Q%8<1M]<'$AT'6S4B$+.2(1UP<`2"(2!PXY-R(1$;.#`Q(8`YLYAQ&X>`@2%P +MB;-QH@22(1-P?1"`T2':F8&@!##1(9"0M#(A%MK50)D1D'<@T-"T@'<0<-T@ +M>&$;@X"!(3"'L^`^(("1(?"9$9<8!3%A`S`^($)A)^%``T(A%B)A*8(A$!N4 +MD)$A0)>S2($;*"`A(8`DLR`@!"#.D^(A&4(A&QN.@($AX(2S2,'HH1LD("$A +M0"ZSXB$30:($("$A*NY`0Q`B(2G@X+20,2$Z-4#N$8"1(>!$(.&@!/"9$3`P +MM.!$$$`S(.T,0B$GEQ@%X6$#X.P@PB$9(F$IDB$;(B$0&XR`@2'`B;/(@1N2 +M@($AD)$A()RS(:($BH7"(1,@+A"0X2'JS)&@!(#@M,#`M$#,$<`B()`B$"#N +M(`R)(B$I1KC]````4&P$DI,)DF$?8+V3_0N0@2&`B"."82+PB!&'&07Q0`/P +M^R""DPB"82&`<2&`=R/PEQ&7&`6!80.`_R!@SI."(2+2(1\AH@2R(24;G2`O +M$,"[$;HXP/H1D)$AT)BS\F$<,#"T^O=`,Q&0T2$P(B`QH`3PW1'P\+0P(A`@ +M_R`M#-<9!2%``R`L(*(A(8+*`8"!(:"'LX"1(?"9$9<8!9%A`Y`B(*(A(<(A +M'V&B!!N:&XR0D2&@E[.B(2)@8A"`@2'`BK.PH4&`@2&JB("`M$"($8!F((&@ +M!)`A(8!F$((A'`PI#`J`@2&*(B`@M&`B(`P&!C7^`%#=!.*3"\&F!.)A'N"Q +M(8"[(]!LDV#V(/"+$8<>!?%``_#V((*3"BDQ@F$@@)$A@)DCDF$=\)D1EQ@' +MP6$#*3'`_R"!IP0H,9(A'L(A)3&B!!OIP,P1,#\0T"B3\B$=P(N`@("T0(@1 +M@#,@@:`$X.$AD.NS@#,0P(H1@F$8&(0&XJ`@2&@B[/`H4&`@2&JB("`M$"($8!F((&@!)`A(8!F$((A +M'`PI#`J`@2&*(B`@M&`B(`P&QO/]4"P$L'L@@I,)@F$?('V3!80,]\(#_(((A +M(B&B!%!N!)*3#9)A%6D!8+V3("\08B$EP/H1\F$SDB$B4F$:@($AX(FSF/'B(16`@2&*55!0M!N.@($A +MX(FSX:($0%41D:`$X.H08*$A4.X@;0R0[A!2(1R`D2'PF1%042&@I8"@H+3@ +MJB"7&`5A0`-@;"#"(1JR81;98>(A%1N+@($AL(VS@)$A\)D1EQ@+D6$#TF$& +MLF$6D&8@V&&!H@0R(18;OK"Q(1N3@(80D)$A,)VS#`.082'8\0Q):F5@8+3@ +MO;.PL2&ZO$N[L+"T0+L1L(@@L:`$#`X,#;"($(!F(`P+!KK\`%#\!(*3"8)A +M'_FQ\+V3_0N`D2&`F2.282+PF1&7&`7Q0`/P^R""DP@I,8)A(8!Q(8!W(_"7 +M$9<8!X%A`RDQ@/\@@:8$(:($LB$E4)T$F4'`NQ$@+Q"0:)/`^A&"(2+R81R2 +MDPN281[Z]_#PM+J(@("T0(@1@"(@@:`$D-$A@-TC@"(0(/\@\(T18"8@AQD% +M@4`#@"8@DI,*DF$@D*$A@*HCHF$=\*H1IQD%@6$#@"(@F+$R(1^B(2*0SI,; +M@X"!(9&@!#"*LS&B!+JMH*"T0*H1,#(0H#,@D#,0(B$=DB$,:($ +M@($ABE504+0P.A!`51%@H2%M#E`S(!N)4:`$@($AD(VS4#,04B$<@)$A\)D1 +M4%$AJJ6@H+0PJB"7&`5A0`-@;B#"(2"R(1T;C("!(<"+LX"1(?"9$9<8!9%A +M`Y!F(((A(+(A'N(A'1N8&\O`P2&0D2&`GK.PS;.!H@2R(1K`P2&`AA#*NY!A +M(;"PM$"[$0Q)L(@@L:`$:F5@8+2PB!"`9B!&^OP`4.T$\:8$TI,+S0;281[0 +ML2&`NR/PBQ'@SY/]#(<=!?%``_#\((*3"BDQ@F$@@)$A@)DCDF$=\)D1EQ@' +MP6$#*3'`_R#8,2&B!,(A)5!_!(*3#X)A%'D14:8$P,P1("\0<&63\B$=REN` +M<2%04+1`51%0(B!1H`2`=R/PEQ%0(A#`6A%:_U)A'/#PM"#_("T&EQ@%(4`# +M("8@@I,.@F$9@)$A@)DCDF$;\)D1EQ@%H6$#H"(@,:($RH>+B("`M$"($3`R +M$(`S((&@!"(A&X`S$((A')&G!(HB(""T,"(@/0W@.9.2(1ZM`X+)`8"!(9"+ +MLX"1(?"9$9<8!:%``Z"C()(A(.(A'1N)@($AD(ZSXB$!@)$A\)D1EQ@%D6$# +MD*H@4B$@@:<$DB$=&V7@V)-@82%0:;/`44&2(1[!H@1281H;B<#*$("!(6"A +M(9"+LVT-@($ADB$4BE504+1`51%0S"!1H`0;B8"!(9"'LU#,$%(A'("1(?"9 +M$5!1(:JEH*"TP*H@EQ@%84`#8&T@PB$9LB$;&XR`@2'`B[.`D2'PF1&7&`61 +M80.09B`,`](A&X&B!.(A&;(A%("&$!N>&\O`P2&0D2'@G;.PQ[,,#@P-LB$: +MD&$AP,$A#$G*NTN[L+"T0+L1L(@@L:`$:F5@8+2PB!"`9B`,"X;!^WT+4/P$ +M@I,)@F$?^;'P?9/]!X"1(8"9(Y)A(O"9$9<8!?%``_#W((*3""DQ@F$A@'$A +M@'D($A +M@(@CB2'PB!&'&0B!0`,B(0F`(B"2DPJ282"0H2&`JB.B81WPJA&G&06!80.` +M(B"B(1*8(8&B!*J9@((0D)"T0)D1D(@@D:`$(B$=D(@0DB$S@)$A +M\)D1EQ@(D6$#TF$&D+L@,B$2@B$ATB$?,#%!&Y@;79"1(8"7LX(A(E!1(3)A +M&M!8L](A'E!1(5HS,#"T6"$;C8"!(="%L]&B!%(A'$`S$=#;$%!1(9"Q(3#= +M()A!,:`$NK6PL+0PW1#0NR`X,=&G!)`]D]T#@)$A\)D1EQ@%T4`#T-,@`&`D2'PF1&7&`6180.0W2`B82DB(1X;DI"1(2"3 +MLR(A%4)A)TCQ&X*`@2$@A+,B(2!PSI-"(1T;,C`Q(2`TLT(A&B&B!)"1(9!$ +M@"`M$("1(3#1(4!`M#T,0$01\)D10"(@0:`$T-6`T-"T0"(0(-T@0B$G(B$I +MEQ@%,4`#,#P@XB$6R&$;CH"!(>",LX"1(?"9$9<8!9%A`Y`S(")A*2(A%)(A +M%NA1&X*`@2$@CK,H81O)P,$AD,*SDB$5*/$;Z>#A(9#BLY&B!"(A&I"3$.`Q +M(3HBX:`$P#$A2R+!IP0Z-2`@M$`B$3`PM""9("(A`>"9$)`S(.@Q@)$A\)D1 +M(.R3X,X@(B$IEQ@%X4`#X.P@DB$9PB$;&XF`@2&0C+.`D2'PF1&7&`6180.0 +M[B#"(1DB82F2(1LB(10;C("!(<")L\A1&Y*`@2&0D2$@G+,AH@2*A<(A&B`N +M$)#A(>K,D:`$@."T2\S`P+1`S!'`(B"0(A`@[B`,B2(A*8:_^J*B`)*C`)"5 +M$*<9`@8?^U?E`H8=^\!$(`8<^X*3"5(A)8)A'X"1(P+$AP-T1TF$2@+LC\.L1 +MVMO0@`2`;Y-@]B#G'`7Q0`/P]B""DPJ"82"`D2&`F2.281WPF1&7&`?!80,] +M\,#_((&B!-"1M$"9$8"/$)"(()&@!/(A'9"($,":$9K_\/"T@/\@@B$2XB$> +MDF$<@(%!@F$:UBX`AJ("K0O!IP2PX2'JV-#0!-`LDZ"!(?"($8<:!9%``Y`B +M(.(A(-(A'1NNH*$AX*VSH,$A\,P1QQH%P6$#P"(@PB$=8:($@B$>TB$@8&(0 +M&Z@;G:"A(8"KLX(A&I"1(:"A(:J(@(&T0(@1@&8@@:`$T)RSD"$A@&80@B$< +M#"D,"H"!(8HB(""T8"(@#`;&A?M]"U#\!(*3"8)A'_FQ\'V3_0>`D2&9T1=H +M!?%``_#W((*3"()A(8!Q(8!W(_"7$9<8!8%A`X#_()(A)8(A'U`N!""]DRD! +M(:($@((AP)D1DF$2B>&0D4&281H@+Q":B,#Z$8"`M$"($?)A'(`B((&@!/KW +M\/"T@"(0(/\@@I,-@F$5L"L@@)$ADF$,%V@%(4`#("L@@I,,@F$6@)$A@)DC +MDF$&\)D1EQ@%H6$#H"(@LB$5,:($@B$:L+(A,#(0BHN`@+1`B!&`,R"!H`28 +MT2AA@#,0@B$<&]F*(B`@M(BQ,"(@/0R`/I.(X=#1(3"C()#8LP=M!:%``Z"C +M()(A(1O9T-$AD->ST($A\(@1AQT%@6$#@*H@V-%2(1*(`9(A(5!208#.DQMI +M8&$A&XV09[.8X5)A$X"!(=")L]&B!("!(8I54%"T0%41T-H04-T@4:`$4-T0 +M4B$<8*$A4%$AJJ6@H+30JB#8P6T,DLT!D)$AT)NS!VD%84`#8&P@TB$6N:'( +M81N-@($AT(RS@)$A\)D1EQ@'D6$#N:&09B`,`[BAXB$6@:($V&$;GH"&$)"1 +M(>"=L]C!D&$A#`X,21O-P,$AT,NSLB$3:F7`P2'*N["PM$"[$;"((+&@!&!@ +MM`P-L(@0@&8@#`M&M_D``(*3"5(A)8)A'X"1(#A(9#GL^"!(?"($8<>!X%A`SWP@*H@TB$: +MP:($4B$ADB$?P,H0&X4;Z8"!(5"'LU(A(N#A(8"A(9#ELY(A'E(A'.#A(>K= +MT-&T0-T14%$AT,P@T:`$JJ6@H+30S!#`JB"6Z6S="Y&G!,(A&F@QL.$AZLS` +MP`3`:9/0@2'PB!&''0610`.09B""(2#B(1T;R,#!(8#.L\#1(?#=$=<XB$=&Y@;W-#1(9"1(8">L\#;LX&B!,(A&M#1(8"&$-K, +MD&$AP,&T0,P1#$G`B"#!H`1J96!@M,"($(!F((:+^@```%"]!.&F!,*3"_T& +MPF$>P-$ATF$1L/Z3^9$7;`>!0`/XD8#_()*3"BDQDF$@D,$A@,PCPF$=\,P1 +MQQD(T6$#(F$#T/\@PB$1(:($4(\$XI,/4:8$XF$4B1&`99-2(24@+Q#R(1W` +M51%281):7%!1M$!5$5`B(%&@!."!(8)A$%`B$,!:$5K_4F$<\/"T(/\@8"8@ +M%VX%(4`#("8@@I,.@F$9@)$A@)DCDF$;\)D1EQ@%H6$#H"(@@B$2XB$0,:($ +MBHXP,A"`@;1`B!&`,R"!H`0B(1N`,Q""(1R2(1&*(B`@M(&G!#`B(#@Q&]SI +M4;`XDX(A'M#1(:T#@((AD-BS!VT%H4`#H*,@@B$@XB$=&[BPL2&`OK.PT2'P +MW1'7&P7180/0JB!2(1VX$9&G!&@Q&]SB(1["(1+0T2'@XB'`PD&P:9.QH@22 +M(2#"81.PNA`;B8"!(9"%LX"A(5(A$8(A%)(A$%#>LX""(5(A'.A1T-$AVLS` +MP+0;[D#,$5!1(:JEP+L@X.$AP:`$D.BSH*"TP+L0L*H@S08';@5A0`-@;"#" +M(1FR(1L;C("!(<"+LX"1(?"9$9<8!9%A`Y!F(`P.#`/"(1NR(132(1F!H@2P +MLB$;G8"&$)"1(="` +MD2&9T1=H!?%``_#W((*3""DQ@F$A@'$A@'("\0@/"T0/\1 +M\"(@@:`$P/H1H:8$@"(0\F$<4(T$^O?P\+2)02#_(&`F((`JDQ=I!8%``X`B +M()*3"I)A()"A(8"J(Z)A'?"J$:<9!8%A`X`B()(A'J(A&H&B!)"2(9EQ@((0 +MJIF0D+1`F1&0B""1H`0B(1V0B!"2(1R:(B`@M%">!)D!D+V3@"(@DI,-K0N2 +M8160@2&)P1=I!:%``Z"K(+*3#+)A%K#1(8#=(])A!O#=$=<;!8%A`X"J(+&B +M!-&F!%!?!%D14&V3TB$5L+H04B$:T-(AV:%:W=#0M$#=$="[(-&@!)*3#ZAA +MT+L0TB$!80,]\("[(#(A$I(A(=C1,#)! +M&XD;78"!(9"'LYCA4%$A,F$3T%FSTB$14%$A6C,P,+18<1N=D)$AT)6ST:($ +M4B$<0#,1T-L04%$A@+$A,-T@B$$QH`2ZM;"PM##=$-"[(#@QT:<$@#V3W0,' +M:0710`/0TR"2(2`B82DB(1V"R0&`@2&0@K,B(2F`D2'PF1&7&`6180.0W2"8 +MP4)A)TBA&XF`@2&0A+-"(2`B82DB(1T;-#`Q(4`RLR(A$4AQ&Y*0D2$@E+-" +M(1,AH@20D2&:1"`M$)@!0$"T,-$AVM5`1!%`(B#0T+1!H`20SI,]#$`B$"#= +M($(A)R(A*0=H!3%``S`\(.(A%LAA&XZ`@2'@C+.`D2'PF1&7&`6180.0,R`B +M82DB(1#"(1;H@1N"@($A((ZS*&$;G)"1(<"2L\C!**$;[.#A(<#BL\&B!"(A +M$\##$.`Q(3HBX:`$D#$A(""TD:<$0"(1.C4P,+0@S"#@S!#`,R#H,<@1(B$I +MP.F3S0X':`7A0`/@[""2(1G"(1L;B8"!(9",LX"1(?"9$9<8!Y%A`SWPD.X@ +MPB$9(F$IDB$;(B$0&XR`@2'`B;/(@1N2@($AD)$A()RS(:($BH7"(1,@+A"0 +MX2'JS)&@!(#@M,#`M$#,$<`B()`B$"#N(`R)(B$I1KCW&ZF2(1J@H2&@L2&Z +MF9"0!)#.DRT,AAW]``#!IP0;KJ"A(:#A(>K8T-`$T"R3AEO]&]B"(1K0T2'0 +MD2&:B("`!(#.DZT,AB[^``#AIP1H,8(A&AO9T-$AT)$AFHB`@`2`;I.&2OX` +M-D$`#`0@4!2<%0Q'4'?`,'=C<#/`=I<$0D(`&R(P\@T``H-M``$ET#_C`````#.`2%MSD$A;L@H``/(-``*FT`` +M!`0\``6$``)KS```8@WT``"70``+R"P#YLZ!HK?`,``&?O-`*,`P`"!_:X`@ +M?[/`*<^!HL2````!S\&BT0WT``&70``+R"P#Y\Z!HKO`,``&?O-`*,`P`"!_ +M:X`@?[/`*<^!HL6````!S\&BT@WT``*70``+R"P#Z,Z!HK_`,``&?O-`*,`P +M`"!_:X`@?[/`*<^!HL:````!S\&BT\@L`^G.@:+#P#``!G[S0"C`,``@?VN` +M('^SP"G/@:+'@````<_!HM2````!S$``0GQ`P`!\00``*10`'3%4``&90``, +M,1@0`,@<`!&5P```R!P`$4``,Y! +M(6G.@2%JS<$A:X````',`2%L?$#``'Q!``!\04``?$&``'Q!P``HI``(,F0` +M_PYH`#R6@``*?`(``'Q"```>,``#S```:IL```-"(``%!"``0(```0]\`D`` +M?@)``)I````*9``!,.P`$)K```K,``!BP"H`!,@L`"%^DH`,S```0``#)GP`"'_WP`M_^\`,*G@`&,_``^//@`/D)K```G\_``#/``/E@``#'7R` +MP`!\0,``*-``"#$0``^5```/)2@``0:H`;*>@````````(```=/`$@@`@``! +MX<@4``^```'HR!0`$(```>_,P:*D@``!^,@4`!$PT``_#2@`%9J``!(-*``> +MFH``'@TH`"":@``C#20`#PTH`!!^:H`,FH``)@T@``0-)``4#2@`*'YB0`Q^ +MIH`,FH``*L@4`!&````!S,&BI,`2"`!\04``?0S`#,`2``@I6``#*5P`#'Q" +M``!]T<`+)B``%'X>0`Q^3H`,SH&BI(````'-@:'^R!0`#P00(0Z50```R!0` +M#]!1``"````!S,&BI,@4`!`$$"$(E4```,@4`!#040``@````99@`('W9P"Q\U,`,S-X``$7<``3(*``7EH``#\`.``$H +M:``(*JP`%C*H`/\.L`!)?R\`"Y<```8`````R!0`!7Q`P`"```(A?$$``(`` +M`B300`!_A``".7Q`P`"4P``#R!``%ID` +M``3,P`!H@````GQ`@`"$``(YP!2``,P``$'-03!*P!2``)D```#($``6@``` +M`GQ`@`#`$@`!?%%`#(````'050``?$#``'Q!``!\04``?$&``"D<`!_,P`!* +MS0``2Y7```/`'(``S<$@$-V#```%7"``S```8H````'8'T$`?$#``'Q!``!\ +M04``?$&``,S``$S-``!-W8,```5``/`W@`#P-X``\# +M>``/`W@`#P-X``\#>``/`W@`#P-X``\#>``/`W@`#P-X``\#>``/`W@`#P-X +H``\#>``/`W@`#P-X``\#>``/`W@`#P-X``\#>``/`W@`#P-X``\#>``` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV730_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV730_pfp.bin.uu new file mode 100644 index 00000000000..d4b3c6341eb --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV730_pfp.bin.uu @@ -0,0 +1,79 @@ +begin 644 RV730_pfp.bin +M?$"``*````!^@H`+@````-P#``#,@`!`T$``0'Q`@`"@````?H*`"\@8``XQ +MF``!?$)``)6``CI\0H``R!P`',`WP`!\0,``?$$``'RT@`O`-@`#F<```,@< +M`!Q\M(`,)-0``GUE0`#-0`!#SH``0\T``$/,@`!`SD``0,Z``$#,P`!`W#H` +M`)>`_][-``!`?$#``(```!A\00``U``#0-0`#\#4``^BR!@`#H````PQF``" +MU``#P-0`#\#4``^BR!@`#BB,``@PS``/-!```7T-``B````,?9&`"\R``$#0 +M0`!`?$"``*````!^@H`+U``#0-0`#\#4``^BS(``0-!``$!\0(``H````'Z" +M@`O4``/`U``/P-0`#Z+,@`!`T$``0'Q`@`"@````?H*`"\Q``_F```))S$`# +M^,`W__]\04``ST&BGL@@`_C('`/Y9B``(,@8`_M]X<`L?5C`"'S0`$'``!ST``0,W``$#/``/Z?`,``,H,`!!\00``E,``!'Q!0`#4(`+$ +MS>``1)L```M\08``S```2\V@`$G-(`!!S6``00`$'``!ST``0,W``$#/``/Z?`,``(```+5\ +M04``S```2(```.X`````R"``%\@<`",.)``"F<``%7Q!@``*(``!S@``5M0` +M!$#,``!`P#;``,H4`!.60``'-W1Y`,]``$#,``!`R#`#^H```0//```BS``` +M(I5``4;,``!_S*``1H````#,(`!&@``"2``#,@`!`S,``0-!``$#(#``E +ME,#]Y,@0``C-``!`U``/P(````#4``^BU``#0-0`#\#4``^BS(``0-!``$!\ +M0(``H````'Z"@`O4``/`U``/P-0`#Z+,@`!`T$``0'Q`@`"@````?H*`"WQ` +MP``PT````!ID```?(%``5F4``!\@T``H-M``$ET#_C`````#.`2%MSD$A;L@H``/(-``*FT`` +M!`0\``6$``)MS```8@WT``"70``+R"P#YLZ!HK?`,``&?O-`*,`P`"!_:X`@ +M?[/`*<^!HL2````!S\&BT0WT``&70``+R"P#Y\Z!HKO`,``&?O-`*,`P`"!_ +M:X`@?[/`*<^!HL6````!S\&BT@WT``*70``+R"P#Z,Z!HK_`,``&?O-`*,`P +M`"!_:X`@?[/`*<^!HL:````!S\&BT\@L`^G.@:+#P#``!G[S0"C`,``@?VN` +M('^SP"G/@:+'@````<_!HM2````!S$``0GQ`P`!\00``*10`'3%4``&90``- +M,1@0`,@<`!$)W``!E<#__\@<`!',P2$`S0$A`0`0)9`___('``1S,$A<,T! +M(7'((``2E@```,@@`!*```.?S```9'Q`P`!\00``S```1``!ET``*@>X +M`26?@````````(```35_&X`$@``!.7\;@`6```$]?QN``H```4%_&X`#@``! +M17\;@`>```%)?QN`!H```4XHI``(FX``&2BD``B```%>,F0`_YN``!4HI``( +M@``!7C)D`/^;@``1**0`"(```5XR9`#_FX``#2BD``B```%>,F0`_YN```DH +MI``(@``!7C)D`/^;@``%**0`"(```5XR9`#_**0`"#)D`/\.:``\FH#^L2CL +M``A\0T``?$.``'Q#P`"6P``'S```8L]!(6G/@2%JS\$A:X````',`2%L@``` +M`<_U``#,``!KA``#H@YH`#R:@``$R"@`%8````'00`!_EH#_JWX"0`"$``([ +MP`X``LP``$&```(YS,$P2GQ`P`!\00``P!X``2DD`!+`(@`"ED``!<`F``3` +M)__[?24`"\`F``!]TH`+?A+`"WTE``Q\04``?$&``,S!(6F:@``*S0$A:LU! +M(6N6P/Z"S8$A;,@P`!B7````R#``&(````',```8A``#HLP``'_(%``3R!@` +M%,U!(6N6P/YVS8$A;(```8+(,``8R`P`")C```#(#``(?$$``)4```(````` +M?$%``,@@``G,0`!#S@&A],Q``$3`#H``?$)``'Q"@``JK``?EL#^8\`U\`#. +M0`/B,G@``R9\``A_]\`+?_O`#"IX`!C/P`/CSX`#Y":P``)_/P``SP`#Y8`` +M`Q]\@,``?$#``"C0``@Q$``/E0``#R4H``$&J`&SGH````````"```'4P!(( +M`(```>+(%``/@``!Z<@4`!"```'PS,&BI(```?G(%``1,-``/PTH`!6:@``2 +M#2@`'IJ``!X-*``@FH``(PTD``\-*``0?FJ`#)J``"8-(``$#20`%`TH`"A^ +M8D`,?J:`#)J``"K(%``1@`````"PE)``"?F)`((````',Y@`` +M?$$``,P``&S,``!MR!@`'\@<`!YEF``@?=G`+'S4P`S,W@``1=P`!,@H`!>6 +M@``/P`X``2AH``@JK``6,J@`_PZP`$E_+P`+EP``!@````#(%``%?$#``(`` +M`B-\00``@``")M!``'^$``([S```0````"?$"``,@8`^J9@/UW?$#``)3` +M``/($``6F0``!,S``&B````"?$"``(0``CO`%(``S```0!`$=T``34-X$` +M1W0`!-0W@0!'=``$"=P`!-0W@0"9P/_X1W0`!"DD`!_`.``9ED#\H<`^``3/ +M@2'X-^`A^``\#FP`/`YL`#P.;``\# +MFP`/`YL`#P.;``\#FP`/`YL`#P.;``\#FP`/`YL`#P.;``\#FP`/`YL`#P.; +H``\#FP`/`YL`#P.;``\#FP`/`YL`#P.;``\#FP`/`YL`#P.;``\#FP`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/RV770_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/RV770_pfp.bin.uu new file mode 100644 index 00000000000..9d97399f615 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/RV770_pfp.bin.uu @@ -0,0 +1,79 @@ +begin 644 RV770_pfp.bin +M?$"``*````!^@H`+@````-P#``#,@`!`T$``0'Q`@`"@````?H*`"\@8``XQ +MF``!?$)``)6``E)\0H``R!P`',`WP`!\0,``?$$``'RT@`O`-@`#F<```,@< +M`!Q\M(`,)-0``GUE0`#-0`!#SH``0\T``$/,@`!`SD``0,Z``$#,P`!`W#H` +M`)>`_][-``!`?$#``(```!A\00``U``#0-0`#\#4``^BR!@`#H````PQF``" +MU``#P-0`#\#4``^BR!@`#BB,``@PS``/-!```7T-``B````,?9&`"\R``$#0 +M0`!`?$"``*````!^@H`+U``#0-0`#\#4``^BS(``0-!``$!\0(``H````'Z" +M@`O4``/`U``/P-0`#Z+,@`!`T$``0'Q`@`"@````?H*`"\Q``_F```)AS$`# +M^,@@`_C('`/YR!@#^\`W__]\04``ST&BGF8@`"!]X<`L?5C`"'S"F0``=0`$D#.0`!`P#;` +M`):`````0<^@`$'.8`!!)QP``GWUP"!I^``@?;)``<\``$O.8`!)S>`` +M0<^@`$&```"]SF``0<@@`!?(,``BF@``!@XH``'()``>"F0``=0`$D#.0`!` +MR@P`$'Q!``"4P``+P#;``):```0#/0`!`S```0,@P`_J```$$SP`` +M(LP``"*50`%=S```?\R@`$:`````S"``1H```F',``!DR"``%\@0`!^6```% +M"1```=0`!$#-``!`S0``(LR``$#00`!`R`P`)93`_NO($``(S0``0-0`#\"` +M````U``/HGQ`P`!\00``S,`#_0`O,``!"@``"8R!0``YM``!L$.``, +MA``!7L@4``.;0``7!#@`"(0``5[(%``#FT``$P0X``2$``%>R!0``YM``!7( +M#`/]FH``"<@0`_R;``$8S```3004`!#,P`!"S0``0H```3;-0`!"EL`!$0``GR@ +M@`LF9``0?*2`#,R``$#-P`!`S,``0)7```[-``!`"=P``<@H``.6@``(SH`` +M0,@T`!V70```R#0`'2:H``B$``)DS"L``)G`__<)W``!W#H``)>```1\08`` +M@``!HR68``*@````?8"``,@8`!U\0,``9-``")6```#(&``=S!,``,R``$#, +MP`!`@````,Q``$#($``??$#``,R``$!\T4`,S4``0`48``&`````S8``(GQ` +MP`!D4``@A``"9,P``&%\T,`LR"``%\C6``"90``(?$.``-^#``#/H`!/A``" +M9,P``&*`````T$``?X```F',``!BA``"9,P``&'((``7?$#``,`V_P#($``- +MP#`__WSU0`M]48`+?8&`#YF```A\\X`+WX,``,^@`$^$``)DS```8H````#0 +M0`!_@``"8``!\0@``?$)``'Q!@`!]Y<`+?>*`!YJ```Y!K``%FL`` +M``KL``$PW``0F<``!`````"```(,R1T``(```@S)'@``S(``0,S``$#00`!` +MR`P`)93`_>/($``(S0``0-0`#\"`````U``/HM0``T#4``_`U``/HLR``$#0 +M0`!`?$"``*````!^@H`+U``#P-0`#\#4``^BS(``0-!``$!\0(``H````'Z" +M@`M\0,``,-``!@T0``:9```'R!0`%9E```7,``!2U``#0-0`#\#4``^BS(`` +M0,S``$"`````T$``0'Q`P`#,30``W#H``)>`_;P$S``!@``"0\Q-``!\0,`` +M?$$``"DD`!@R9``!ED``#\R``$!\04``?$&``'Q!P`#,P`!#S0``0S'`$D! +MQ@!*`=``50(F`%8"+@!@``H`80`J`&(`,`!C`#``9``P`&4`,`!F`#``9P`P +M`&@`-P!I`#\`:@!'`&L`1P!L`$<`;0!'`&X`1P!O`$<`<`!'`',"7P![`D$` +M```%````!0````4````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +1!0````4````%````!0````4` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/SUMO2_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/SUMO2_me.bin.uu new file mode 100644 index 00000000000..f2e2b21661c --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/SUMO2_me.bin.uu @@ -0,0 +1,126 @@ +begin 644 SUMO2_me.bin +M?$"``*````#,@`!-@````-1``'\SH&BN\^!HL6`````S\&BTBGT``*70``'!#"BOH0``-[.@:*_SX&B +MQH````#/P:+3!#"BPH0``-[.@:+#SX&BQX````#/P:+4P"X`!'\O``?,,0`` +MR"P`!,`P``9^\T`CP#``(']K@""(````?[/`),P``$*`````S$``'WQ`P`!\ +M00``&10`/9E``!,$%``NA``$H008`"F$``)ER!P`$P04`"J$``2A!!@`+4``,Y!(6G.@2%J +MS<$A:X````#,`2%L?$#``'Q!``!\04``?$&``'Q!P``8I!_H*F@`/):```I\ +M`@``?$(``#HP``/,``!8FP```T(@``4$(`!`@``!4'P"0`!^`D``FD````ID +M``$<[``0FL``"LP``$W`*@`$R"P`('Z2@`?,``!!S"D``,[``!Z```%@R#`` +M!,T!(6W-02%NR#```W\?``8<]``'$W@``9=``"H'N`%EGX````````"```%U +M?QN`#H```7E_&X`/@``!?7\;@`R```&!?QN`#8```85_&X`1@``!B7\;@!"` +M``&.%*0`")N``!D4I``(@``!GAYD`/^;@``5%*0`"(```9X>9`#_FX``$12D +M``B```&>'F0`_YN```T4I``(@``!GAYD`/^;@``)%*0`"(```9X>9`#_FX`` +M!12D``B```&>'F0`_Q2D``@>9`#_*F@`/)J`_G`4[``(?$-``'Q#@`!\0\`` +MEL``!\P``$W/02%ISX$A:L_!(6N`````S`$A;(````#/]0``S```680`!*$J +M:``\FH``!,@H`!>`````U$``?Y:`_ZM^`D``A``"E\`.``+,``!!@``!K,S! +M,$J4````R#P`''Q`P`!\00``P!X``14D`!+`(@`"ED``!<`F``3`)__[?24` +M!L`F``!]TH`&?A+`!GTE``=\04``?$&``,S!(6F:@``,S0$A:LU!(6N6P/X_ +MS8$A;(0`!*',``!_R#``&I<```#(,``:@````7Q`@`"$``2AS```?\@4`!7( +M&``6S4$A:Y;`_C'-@2%L@``!P\P``']\0,``?$"``!24`!`15``%'(C__Q"( +M``5\0,``%-``$!S,___`&@`$!9@;I,P9``#(&``$'9@/_WT9`!"9`/X>?8T` +M$)D`_AS,``!8S```680`!*',@2%TR`P`%Y3`___,``!9@````7Q`@`#,``/E +MR"P`(,`.("0$$#``(,PB:P04,`',``!!T!$``,S5``#.P``>R`P`"9C```#( +M#``)?$$``'Q!0`#,``/GS``#Z,P``^G,0`!#S$``1-1``'^`````?(#``'Q` +MP``8T`'H$2@``94``!`&J`(*GH````````"```(BP!((`(```C#(%``1@``" +M-\@4`!*```(^S,&BI(```D<``"FT```\@, +M`"J$``-;R!0`+)N```,$$``0A``#`)T>X!53,``!BS_H``)I```#()``HR"@`(SJH``*:@/__R"@`(\@H`"6: +M@```R"@`)8```M'`,``"!9C``!#<``@4X``8S=D``,@<`"+()``B'=P/_\W9 +M``%^8D`'SED``M@840/8&%$$B````-@840<;^`#PP#8(`)>```/`,`"`B``` +M`,`J``3/02%\SP$A?:0/_VP#X`!-```_Q\00``@````7Q`@`"$``-; +M?$#``'Q`@`"@````S(``3<@\``Z7P``#TP`#YH@````$/``FS\&BI,@\`^8+ +M_``!S\`#YIO`__O,``!-!#P`!<_!HJ3,`:'TA``$H(````S```?X0` +M`W)\0,``?$"``*````#,@`!-!#P`(L_!HJ2$``2AS```2(@```#,``!_A``# +M?7Q`P`!\0(``H````,R``$T$/``CS\&BI,P!H?.$``2AS```28@```#,``!_ +M@````'Q`P`"`````?$#``,`2``%\44`'@````-15``#,0`!ER#@`+<@\`"[` +M->``P#(`!'^W@`9_]\`&([@0`"/\$`#/@2%4S\$A5T`'ST``0,P``$#.``!`SD``0,Z``$"7```# +MSL``0-"``%P)5``!S(``0,P``$#,``!`S```0,W``$"50/^>?-C`((```$%4 +MT``@?$#``'Q!0`"```!N?$&``'Q`P``$%``!P!H``WR8@`=\0<``R!``+,@@ +M`"M1$``@?2$`)WS0P""50/^,5-``(,S``$+-``!"T4``0L@@``/()``#R"@` +M`\@L``.6`/^#R#```Y9`_X'(-`/]?K>`$9>```-_:T`!?`-`!L]#HI[,``!L +MS,``;B7@``' +MT$`#X(0``W+,``!_R#@#X)N```#(.`/@F<```,@<`"!\M(`'$-0``GUE0`#- +M0`!#SH``0\T``$/,@`!`SD``0,Z``$#,P`!`X#H``)>`_SG-``!`?$#``(`` +M`+U\00``'(P``IC```G($``@%5``&(!```7T5``.` +M``"H?9&`!IE`__C('``'S<``0,P``$"```#FS```;L`.@(#,``!G!-"`@,P` +M`&C-``/QS0`#\LT``_/-``/TS0`#]LT``_?-``/X@```!5`/_WR!0`19E```3(&``*S8``0,P``$"```%?V``(0'Q`P`#($`!'F0#_ +M_`````#,@`!`S,``0-1``$!\0(``H`````0H``'($`!&V``'0,T``$"$``%V +MS0``0,@,`$.4P``*R!0`2(```6\$$``#R!``1M@`!\#-``!`A``!=LT``$#( +M%`!(G4```,P``&K(*``6'J@``9J```/`*0`!B````,`L`5;.@`!E,``",@4`!R9```*R!P`"(0``W7,``!4@``! +MD,R``$"90``$R!P`!H0``W7,``!2S(``0(````#40`!`S$``)\Q``"B```-O +MS```:\`R``/`-___@``!FWRP@`=\0T``R"``*,@<`"?(&``FST.BGGQ!0`!2 +M(``@?>'`)WU8P`-\W,`@5-``((```;#,@`!`?$&``,R``$"```&MS8``0,`9 +M___,@`!`S8.BGGQ`P`!\00``?$%``,S#H?K-`Z'YS4.BG```!34`!]] +M84`&S(``0)5```-\00``S,``6148`!_,P`!`E8```\T``$#-``!:@``#;\P` +M`'_((``??$$``-@@`D3.(`!$?$%``'Q!@`#-H`!)S2``09P/]@```` +M`-```_J`````?$#``,R``$"`````U$``0'Q`P`!\00``?$.``'Q#P``$'``" +MSX``0L_``$+-P`!"!!P`!,S``$+-``!"S<``0@0<```$(``!?`)``,@4``/( +M&``#49@`('U90"?(*``#R"P``\@P``/(-``#4NP`('ZN@"=3=``@?S<`)W\K +M0"%^=D`@5J@`/UT`G?65` +M(%58`"#,``!;S78``,VV``#((`!!F@```,@@`$&````!?$"``'Q`P`!\00`` +MS,`#_LT``__,P`!"S0``0A44`!\9&`#P)UP``7UV``:9@``%?5Y`!LP``$*` +M``-OS```3168``$5+``(F8``,1[L``&6```$%3``#(```V_,``!"!!0`!,U` +M`$(?,``!("@``00X``0$/```R!0``\@8``/('``#R"```WU=0`U]H<`-?5U` +M!Q80`!\5G``??1T`!GT70`9^DH`&FT``$@NX``2;P/_R"_P``<@,`_Z:@``) +MR!`#_YL``/C,``!-!!0`!,S``$+-``!"@``"8^.#``"`````W`,!_Y9```3,``!.@``#;\P` +M`$+2``!"R`@``\@,``/($``#R!0``\@8``/('``#R"0``\@H``,5_``?%K`` +M'W_SP`84\``??_/`!A5P`!]_\\`&?8B``9?```U]S,`!?E$``7Z50`%\D(`, +M?-3`#)K```-\CT`&)+0``9M``,C,``!-@``#;\P``$[(#`/^R!`#_\S``$*` +M``*-S0``0GQ`P`!\00``?$+``'Q#``#`.P`??$-``'^W@`;`/A``EX#]2'T] +M``=_/P`'&10`.\P``%N50``3R!0`0#%8``*5@/__R!0`0,P``&,A'(``S,$A +MAA``# +M``!\0@``?$)``'Q! +M@`!]Y<`&?>*`$9J`_+U!K``%FL````KL``$L`-`-@`#4!F@`X`&8`.0(4`#P#,@`_`=D`00*P`$(" +MUP!#`N$`1`+N`$H"_P!5`U0`5@-;`&``I@!A`,P`8@#T`&,`W@!D`-X`90#> +M`&8`W@!G`-X`:`$!`&D!"@!J`5H`:P$H`&P!*`!M`2@`;@$H`&\!*`!P`2T` +MSH&BN\^!HL6`````S\&BTBGT``*70``'!#"BOH0``-[.@:*_SX&B +MQH````#/P:+3!#"BPH0``-[.@:+#SX&BQX````#/P:+4P"X`!'\O``?,,0`` +MR"P`!,`P``9^\T`CP#``(']K@""(````?[/`),P``$*`````S$``'WQ`P`!\ +M00``&10`/9E``!,$%``NA``$H008`"F$``)ER!P`$P04`"J$``2A!!@`+4``,Y!(6G.@2%J +MS<$A:X````#,`2%L?$#``'Q!``!\04``?$&``'Q!P``8I!_H*F@`/):```I\ +M`@``?$(``#HP``/,``!8FP```T(@``4$(`!`@``!4'P"0`!^`D``FD````ID +M``$<[``0FL``"LP``$W`*@`$R"P`('Z2@`?,``!!S"D``,[``!Z```%@R#`` +M!,T!(6W-02%NR#```W\?``8<]``'$W@``9=``"H'N`%EGX````````"```%U +M?QN`#H```7E_&X`/@``!?7\;@`R```&!?QN`#8```85_&X`1@``!B7\;@!"` +M``&.%*0`")N``!D4I``(@``!GAYD`/^;@``5%*0`"(```9X>9`#_FX``$12D +M``B```&>'F0`_YN```T4I``(@``!GAYD`/^;@``)%*0`"(```9X>9`#_FX`` +M!12D``B```&>'F0`_Q2D``@>9`#_*F@`/)J`_G`4[``(?$-``'Q#@`!\0\`` +MEL``!\P``$W/02%ISX$A:L_!(6N`````S`$A;(````#/]0``S```680`!*$J +M:``\FH``!,@H`!>`````U$``?Y:`_ZM^`D``A``"E\`.``+,``!!@``!K,S! +M,$J4````R#P`''Q`P`!\00``P!X``14D`!+`(@`"ED``!<`F``3`)__[?24` +M!L`F``!]TH`&?A+`!GTE``=\04``?$&``,S!(6F:@``,S0$A:LU!(6N6P/X_ +MS8$A;(0`!*',``!_R#``&I<```#(,``:@````7Q`@`"$``2AS```?\@4`!7( +M&``6S4$A:Y;`_C'-@2%L@``!P\P``']\0,``?$"``!24`!`15``%'(C__Q"( +M``5\0,``%-``$!S,___`&@`$!9@;I,P9``#(&``$'9@/_WT9`!"9`/X>?8T` +M$)D`_AS,``!8S```680`!*',@2%TR`P`%Y3`___,``!9@````7Q`@`#,``/E +MR"P`(,`.("0$$#``(,PB:P04,`',``!!T!$``,S5``#.P``>R`P`"9C```#( +M#``)?$$``'Q!0`#,``/GS``#Z,P``^G,0`!#S$``1-1``'^`````?(#``'Q` +MP``8T`'H$2@``94``!`&J`(*GH````````"```(BP!((`(```C#(%``1@``" +M-\@4`!*```(^S,&BI(```D<``"FT```\@, +M`"J$``-;R!0`+)N```,$$``0A``#`)T>X!53,``!BS_H``)I```#()``HR"@`(SJH``*:@/__R"@`(\@H`"6: +M@```R"@`)8```M'`,``"!9C``!#<``@4X``8S=D``,@<`"+()``B'=P/_\W9 +M``%^8D`'SED``M@840/8&%$$B````-@840<;^`#PP#8(`)>```/`,`"`B``` +M`,`J``3/02%\SP$A?:0/_VP#X`!-```_Q\00``@````7Q`@`"$``-; +M?$#``'Q`@`"@````S(``3<@\``Z7P``#TP`#YH@````$/``FS\&BI,@\`^8+ +M_``!S\`#YIO`__O,``!-!#P`!<_!HJ3,`:'TA``$H(````S```?X0` +M`W)\0,``?$"``*````#,@`!-!#P`(L_!HJ2$``2AS```2(@```#,``!_A``# +M?7Q`P`!\0(``H````,R``$T$/``CS\&BI,P!H?.$``2AS```28@```#,``!_ +M@````'Q`P`"`````?$#``,`2``%\44`'@````-15``#,0`!ER#@`+<@\`"[` +M->``P#(`!'^W@`9_]\`&([@0`"/\$`#/@2%4S\$A5T`'ST``0,P``$#.``!`SD``0,Z``$"7```# +MSL``0-"``%P)5``!S(``0,P``$#,``!`S```0,W``$"50/^>?-C`((```$%4 +MT``@?$#``'Q!0`"```!N?$&``'Q`P``$%``!P!H``WR8@`=\0<``R!``+,@@ +M`"M1$``@?2$`)WS0P""50/^,5-``(,S``$+-``!"T4``0L@@``/()``#R"@` +M`\@L``.6`/^#R#```Y9`_X'(-`/]?K>`$9>```-_:T`!?`-`!L]#HI[,``!L +MS,``;B7@``' +MT$`#X(0``W+,``!_R#@#X)N```#(.`/@F<```,@<`"!\M(`'$-0``GUE0`#- +M0`!#SH``0\T``$/,@`!`SD``0,Z``$#,P`!`X#H``)>`_SG-``!`?$#``(`` +M`+U\00``'(P``IC```G($``@%5``&(!```7T5``.` +M``"H?9&`!IE`__C('``'S<``0,P``$"```#FS```;L`.@(#,``!G!-"`@,P` +M`&C-``/QS0`#\LT``_/-``/TS0`#]LT``_?-``/X@```!5`/_WR!0`19E```3(&``*S8``0,P``$"```%?V``(0'Q`P`#($`!'F0#_ +M_`````#,@`!`S,``0-1``$!\0(``H`````0H``'($`!&V``'0,T``$"$``%V +MS0``0,@,`$.4P``*R!0`2(```6\$$``#R!``1M@`!\#-``!`A``!=LT``$#( +M%`!(G4```,P``&K(*``6'J@``9J```/`*0`!B````,`L`5;.@`!E,``",@4`!R9```*R!P`"(0``W7,``!4@``! +MD,R``$"90``$R!P`!H0``W7,``!2S(``0(````#40`!`S$``)\Q``"B```-O +MS```:\`R``/`-___@``!FWRP@`=\0T``R"``*,@<`"?(&``FST.BGGQ!0`!2 +M(``@?>'`)WU8P`-\W,`@5-``((```;#,@`!`?$&``,R``$"```&MS8``0,`9 +M___,@`!`S8.BGGQ`P`!\00``?$%``,S#H?K-`Z'YS4.BG```!34`!]] +M84`&S(``0)5```-\00``S,``6148`!_,P`!`E8```\T``$#-``!:@``#;\P` +M`'_((``??$$``-@@`D3.(`!$?$%``'Q!@`#-H`!)S2``09P/]@```` +M`-```_J`````?$#``,R``$"`````U$``0'Q`P`!\00``?$.``'Q#P``$'``" +MSX``0L_``$+-P`!"!!P`",S``$+-``!"S<``0@0<``$$(``!?`)``,@4``/( +M&``#49@`('U90"?(*``#R"P``\@P``/(-``#4NP`('ZN@"=3=``@?S<`)W\K +M0"%^=D`@5J@`/UT`G?65` +M(%58`"#,``!;S78``,VV``#((`!!F@```,@@`$&````!?$"``'Q`P`!\00`` +MS,`#_LT``__,P`!"S0``0A44`!\9&`#P)UP``7UV``:9@``%?5Y`!LP``$*` +M``-OS```3168``$5+``(F8``,1[L``&6```$%3``#(```V_,``!"!!0`",U` +M`$(?,``!("@``00X``@$/``!R!0``\@8``/('``#R"```WU=0`U]H<`-?5U` +M!Q80`!\5G``??1T`!GT70`9^DH`&FT``$@NX``2;P/_R"_P``<@,`_Z:@``) +MR!`#_YL``/C,``!-!!0`",S``$+-``!"@``"8^.#``"`````W`,!_Y9```3,``!.@``#;\P` +M`$+2``!"R`@``\@,``/($``#R!0``\@8``/('``#R"0``\@H``,5_``?%K`` +M'W_SP`84\``??_/`!A5P`!]_\\`&?8B``9?```U]S,`!?E$``7Z50`%\D(`, +M?-3`#)K```-\CT`&)+0``9M``,C,``!-@``#;\P``$[(#`/^R!`#_\S``$*` +M``*-S0``0GQ`P`!\00``?$+``'Q#``#`.P`??$-``'^W@`;`/A``EX#]2'T] +M``=_/P`'&10`.\P``%N50``3R!0`0#%8``*5@/__R!0`0,P``&,A'(``S,$A +MAA``# +M``!\0@``?$)``'Q! +M@`!]Y<`&?>*`$9J`_+U!K``%FL````KL``$L`-`-@`#4!F@`X`&8`.0(4`#P#,@`_`=D`00*P`$(" +MUP!#`N$`1`+N`$H"_P!5`U0`5@-;`&``I@!A`,P`8@#T`&,`W@!D`-X`90#> +M`&8`W@!G`-X`:`$!`&D!"@!J`5H`:P$H`&P!*`!M`2@`;@$H`&\!*`!P`2T` +M```!N!(@``80``*D1N``?A``!8"`X``+`,"`(P`C__LRQ``#+#0`` +MS#$``,L-``":0`"6`````(0``F(@"`(0@``!(@````"$``'S`````(```)0` +M````S```#LP```[($`("("@!PR`<``#($`("R`@"!7^+@`?("`(!E(``%``` +M``"```'W`````(0``$T`````B`````````#-G`(#A```J2`X``"5`/_O```` +M`,`P`<"(````S[$``"`X``'/@``#R!`"`LP``@'("``:E(`!1@````#-@``. +M`````(0``*D1N``?A``!ER`X``+,,0``R`@"`)B```0`````A```?P````"$ +M``%@(#@``(`````````,@)/3;(#3TWE,#_P@````#($3TXR!4].<@= +M/3K((3T[R"4]-02H`##.@3V"S,$]@\T!/83-03V%S<$]ALX!/8<0B``#!(P` +M&,B6`#R50/^QR-(`*'TE``$)5``!!,P`*)D`__L`````R)(`.`40`$!]"L`` +MR-8`!,`<``3(X@`4R.8`),X*`4S.;@%,",P`!`B(``0*[``$"=P``9G`__@` +M````S0H!8,P*`63-03U'@```M0````#("`!$A```'E"(``C(.`!(EX#_0\@X +M`@:;@``$`````(0``-X`````R#@`1Q^X``&7@``#P#@`$,^``$?(.`!''[@` +M$)N`__X`````A```30````"$``%@(#@``9I`_Q_(.`!(A``!HL@X`@>```!7 +M`````"`(``',@``#P#``1\`((`#+#0``?,C`!IC`__X`````P#`]-X +M``0$B``!RXX``,S(``!'N``$!(@``X``'+D```![@`````/`.``0SX``1R`<``#("`(!E(``5P`` +M``#(*```EH``5"`(``'-@``.S(```!P<```JB`&[E(``20````"```"D```` +M`,@(`$10B``(A``!9`````"9P/]Y(`@``(0``6`@.```EX#_=2`(``#,``(` +MS``"`<`P(8T@#``!S/$``,`P(8X@S#__S/$``,`P(;;`"A0`S+$``,@(`$`< +MB`(`F(#_H,`P`$?+$0``'0P$`)3``$P`````R`P`&I3`__L`````@``!C@`` +M``#)S`(#E,#_6B`(``#`#"&VR-$``,`*%`!]"0`&F0#_5"`(``"$``%@(#@` +M`I>`_U`@"```FD#_T0````"$``!M(`@"$(```A4`````A```30````"(```` +M`````,@X`@:;@``&`````)I```0`````A```W@````#)^`(#FX#_"0````"` +M``"4`````"J(`;R8@/_S`````)4`_C8`````R"@``I:`_X`@"``!S8``#LR` +M``*```"/`````,`0(`O`%```P!;``,U1``#)%0``P##__\B,``!\\0`&E0`` +M#`2(``'(E```S5$``!3,`!!\\0`&E0``!@2(``'(E```S5$``(```F@$B``! +MB``````````=#$``E,#_3\`P/:_+#0``',P``I3`_TO`,#TTRPT``)C`_PX` +M`````````,@(`@@$B``!S(`"",`P/37,,0``P#`],`_9`@ +M#``-P#`@"N6O^"4_QL8PQ[ +M;LBK@O6B6P``````'@,`!P````P```$;,]2P`1P)_4>(.9C@Y^0VMT;DMVA, +MVG4XK8X]*4OU>CK"%1\-```!E_N->SXNR?[*B+=E8`\F?)ALE +M7;\&P@\```'Z:Z&+.R1B0.6*F'F-Y=S:B7J'PHT``];"E-/C]54?]NBR8(D0 +M```!6NEDI$(H2).M])KKTCN"=SXD\^-(:*$0```:YI +M_W^%:W!^?2P:89X08C"%"R8P+E1R:#^#XNX?V[ULT#@]7!(```$^ZW6[1L?^ +M]`#AT24M?H7'8;-^T!!J2-5$J@`_9WE;YBS_2?,````````````````````` +M`````````````````````````````````,5)$-5)(.5),/5)`#0``-S_`&'0 +M_P!A$``!82\`!`"Q@`1@``````````````````````````````````````#% +M"1#5"2#E"3#U"0`U```````````````````````````````````````````` +M````````````````````````R4D`T0D0V4D@Z4DP^4E`@$E0D$E@H$EPL$D` +M-````````````````````````````````````````````````,D)$-D)(.D) +M<-$),/D)0(<)4)<)8*<)<+<)`#4````````````````````````````````` +M``````````````#-20#1"1#=22#M23#]24!`25!026!@27!P28"`29"02:"@ +M2;"P20`T````````````````````````````````S0D0W0D@[0FPT0DP_0E` +M2PE06PE@:PEP>PF`BPF0FPF@JPFPNPD`-0`````````````````````````` +M````#```Y!,``!,``1,``A,``Q,`!!,`!1,0(```21,`2!,0(```:!,`@!,` +M@1,`D!,`D1,`H!,`H1,P(```L1,`LA,`LQ,`PA,`PQ,`T1,`TA,`TQ,`Z!,` +MZA,`\!,`\1,`\A,,\B#F$Q`@`$P"#`-V@@[2

G!^=$@``,P`0,IX3GQ(`(#,`,#(F$0,F$1(.8#,+$#(F$2,F$3 +M;`,P(A`K(B#F$Q+1`1+!@!`@`!`1(!4%`!+!@#(A$2(A$#`#$R`"$SCQ*.$P +M`1,@`!,B(1(R(1,@YA,PL1,0(`#XT>C!V+'(H;B1J(&8<8AA>%%H05@Q2"$X +M$2@!$M$!$L&``#`````V`0$@80!`X@-0Y`,A+@!01!`@1!!61``@;P`=\##T +M0!SR,#+``!-`02\`0$.PG&,,$@`BH2#C$R(D`&(D`19"_-`"`(;O_P`@\`,@ +M\!,H!&@4%@+[T`(`ANK_`#8A`##J`RHS,/`3'?`````V(0#VP@E1+P!0(K`Y +M`DD2'?`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````8P```````` +M````````````````````````````````AE[_```````````````````````` +M```````````````0-````````````````````````````````````````!+! +M@"D!(.@#9D("1E#_*`$2T0$2P8`&2?\`````````AD;_`#8A`$!O`##D`R`S +M(##D$T#F$Q`@`!WP`#8A`$!O`##D`R`S("`S,##D$T#F$Q`@`!WP```````` +M`````(8V_P`@TA,A,``Y$DDB63)I0GE2B6*9%)H0E@R2"(X$B#2`Q`R`````#8A`"#J`QWP-B$` +M(/`3`"``'?``-B$`(/(3`"``'?``-B$`(/`#'?`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````'@-@````````````````OJ8`8+ZF`&`QIP!@OJ8`8+ZF`&"^I@!@OJ8` +M8"JG`&"^I@!@*J<`8+ZF`&"^I@!@OJ8`8+ZF`&"^I@!@OJ8`8("X`&#)N0!@ +M@+@`8("X`&"`N`!@R;D`8"NZ`&"`N`!@@+@`8"NZ`&"`N`!@@+@`8("X`&"6 +MN@!@@+H`8("X`&"`N`!@@+@`8("X`&"`N`!@H[D`8````````````````,#C +M`&"/XP!@-^4`8`/E`&#CY`!@:^0`8!CD`&``````"@X4&`X4&!L4&!L>&!L> +M(@8-%!P-%!P@%!P@)1P@)2H``00(!0(#!@D,#0H'"PX/``$($`D"`PH1&"`9 +M$@L$!0P3&B$H,"DB&Q0-!@<.%1PC*C$X.3(K)!T6#Q<>)2PS.CLT+28?)RXU +M/#TV+S<^/T85`6!&%0%@7A8!8$(6`6!"%@%@G1(!8)T2`6"=$@%@G1(!8)T2 +M`6"=$@%@0A8!8"86`6`*%@%@G1(!8)T2`6"=$@%@G1(!8)T2`6"=$@%@G1(! +M8`H6`6#N%0%@TA4!8)T2`6"=$@%@G1(!8)T2`6"=$@%@G1(!8)T2`6"V%0%@ +MMA4!8)H5`6"=$@%@G1(!8)T2`6"=$@%@G1(!8)T2`6"=$@%@?A4!8&(5`6`` +M``````$"`P0%!@<("0H+#`T.#Q`1$A,4%187&!D:&QP='1X?("`A(B(C(R0D +M)24E)B8F)R`P<%"PH-#`X/)R\K!RT+ +M+@T0#@,&!0D*'PPC$R45*AHL'"$C(B4D*B@L)P$K`BT$+@@1$1(2%!08&!,& +M%0D:%AP9%R`;(1TB'B06*!DF)BDI`@$#`P0'!0\('P("`P8$#@4>!SX````` +M````````````0(`!08$"0H(#0X,$1(0%184&1H8'1X<(2(@)28D*2HH+2XL, +M3(P-38T.3HX/3X\04)`149$24I(34Y,45)0559465I875Y<86)@969D:6IH; +M6YL<7)P=79T>7IX?7Y\@8*`A8:$B8J(C8Z,D9*0E9:4F9J8G9Z@%6J0,`S9IG,*](!87&!H<'B`C%Q@:'!X@(R89&AP>(",F*1L< +M'B`C)BDM$!$2$Q05%A<1$A,4%187&!(3%!46%Q@9$Q05%A<8&AL4%187&1H; +M'!46%Q@:&QP>%A<8&AL<'A\7&!D;'!X?(04````````````````````````` +M`````(````!@````"`````8````!````L````)`````+````"0````(```!@ +M`0``(`$``!8````2`````P```,`"``!``@``6````!(````$````@`4``(`$ +M``!@`0``$@````4`````````````````````````!0`````````````````` +M```````````````````````!`````0````$````!`````0````$````!```` +M`0````$````!`````0````(````"````&#T"8"T]`F"#0`)@>D`"8'%``F!H +M0`)@7T`"8``````#`````P````,````#````!`````0````$````!`````4` +M`````````````````````````0````(````#``````````$````"`````P`` +M````````````````````````````!`````@````,````$````!0````8```` +M'````"`````D````*````"P````P````-````#@````\````______[___\! +M`````@`````````````````````````!`````0````$````!`````@````(` +M```"`````@````,````#`````P````,````$````!`````0````$````!0`` +M```````````````````````!`````@````,``````````0````(````#```` +M``````$````"`````P`````````!`````@````,``````````0````(````# +M`````````````````````````#P````X````-````#`````L````*````"0` +M```@````'````!@````4````$`````P````(````!`````````#_5@)@35<" +M8$!7`F`S5P)@)E<"8!E7`F`,5P)@``````,````#`````P````,````$```` +M!`````0````$````!0`````````````````````````!`````@````,````` +M`````0````(````#`````````````````````````/_____^____`0````(` +M````````!`````@````,````$````!0````8````'````"`````D````*``` +M`"P````P````-````#@````\``````````````````````````$````!```` +M`0````$````"`````@````(````"`````P````,````#`````P````0````$ +M````!`````0````%``````````````````````````$````"`````P`````` +M```!`````@````,``````````0````(````#``````````$````"`````P`` +M```````!`````@````,`````````````````````````/````#@````T```` +M,````"P````H````)````"`````<````&````!0````0````#`````@````$ +M`````````(VD`F##I`)@NJ0"8+&D`F"HI`)@GZ0"8):D`F``````0``&`$4` +M``!&````O@`"`,(`!@#D`08`,`$``#`!```P`@8`Q@(&`"@#!@"(`P8`"`,` +M``@#```(`P``"`,```D#```)`P``0@4&`+@%!@#V`P``]@,``/8#``#V`P`` +M]P,``/<#``"F!@8`200``$H$``!*!```2@0``$H$``!+!```2P0``$L$``!+ +M!```2P0``$L$``!+!```2P0``$L$``!+!```2P0``$L$``!+!```2P0``$L$ +M``!+!```2P0``$L$``!+!```2P0``$L$``!+!```2P0``$L$``!+!```2P0` +M`$L$``!+!```2P0``$L$``!+!```2P0````````````````````````````` +M```````````````````````````````````````````````````````````! +M`````@```$```P`(````2``#`%```@`3````$P```!0````4````%````!0` +M```4````%````!0````4````%0```!4````5````%0```!4````5````%0`` +M`!4````5````%0```!4````5````%0```!4````5````%0```%0``@!8``(` +M'````!P````=````'@```!\````@````(0```"$````A````(0```%P``0`D +M````)0```%X`!0`#`````P````,````#````!`````4````&````!P````D` +M```*````"P````P````-````#0````X````.````#P```!`````1````$@`` +M`!8````6````%P```!@````9````&@```!L````;````(@```",````F```` +M)@```"<````H````*0```"H````K````+````"T````N````+P```#`````Q +M````,@```#,````T````-0```#8````W````.````#D````Z````.P```#P` +M```]````/@```#\```!`````00```$(```!#````1````$<```!'````2``` +M`$D```!```4`8``%`(``!0"@``4`P``$`-``!`#@``0`\``#`/@``@#Y```` +M^@```/H```#[````^P```/L```#[````_````/P```#\````_````/P```#\ +M````_````/P```#]````_0```/T```#]````_0```/T```#]````_0```/X` +M``#^````_``!`/X``@`"`0$`!`$!``@!```&`00`$@$``!(!```2`0``$@$` +M`!(!```2`0``$@$``!(!```3`0``$P$``!,!```3`0``%@$#`!X!`@`>`0`` +M'@$``!\!```?`0``'P$``!\!```?`0``'P$``!\!```?`0``2@```$L```!, +M````30```$X```!/````4````%$```!2````4P```%0```!5````5@```%<` +M``!8````60```%H```!;````7````%T```!>````7P```&````!A````8@`` +M`&,```!D````90```&8```!G````:````&D```!J````:P```&P```!M```` +M;@```&\```!P````<0```'(```!S````=````'4```!V````=P```'@```!Y +M````>@```'L```!\````?0```'X```!_````@````($```""````@P```(0` +M``"%````A@```(<```"(````B0```(H```"+````C````(T```".````CP`` +M`)````"1````D@```),```"4````E0```)8```"7````F````)D```":```` +MFP```)P```"=````G@```)\```"@````H0```*(```"C````I````*4```"F +M````IP```*@```"I````J@```*L```"L````K0```*X```"O````L````+$` +M``"R````LP```+0```"U````M@```+<```"X````N0```+H```"[````O``` +M`+T```"^````OP```,````#!````P@```,,```#$````Q````,4```#%```` +MQ@```,8```#'````R````,D```#*````RP```,P```#-````S@```,\```#0 +M````T0```-(```#3````U````-4```#6````UP```-@```#9````V@```-L` +M``#<````W0```-X```#?````X````.$```#B````XP```.0```#E````Y@`` +M`.<```#H````Z0```.D```#J````Z@```.L```#K````[````.P```#M```` +M[0```.X```#N````[P```.\```#P````\0```/(```#S````]````/0```#U +M````]0```/8```#W````^````/@```#_``````$```$!```"`0```P$```,! +M```$`0``!0$```8!```'`0``"0$```H!```+`0``"P$```P!```,`0``#0$` +M``T!```.`0``#@$```\!```/`0``$`$``!`!```1`0``$0$``!0!```5`0`` +M%@$``!`0``7P$``&`!``!A`0``8@$``&,!``!D`0``90$``&8! +M``!G`0``:`$``&D!``!J`0``:@$``&L!``!K`0``;`$``&P!``!M`0``;0$` +M`&X!``!O`0``<`$``'$!``!R`0``0$``'H!``!Z`0``>P$``'L!``!^`0``?P$``((!``""`0``@P$``(0!``"% +M`0``A0$``(4!``"%`0``A0$``(4!``"%`0``A0$``(8!``"&`0``A@$``(8! +M``"&`0``A@$``(8!``"&`0``AP$``(`(``'D"``!Z`@`` +M>P(``'P"``!]`@``?@(``'\"``"``@``@0(``(("``"#`@``A`(``(4"``"& +M`@``AP(``(@"``")`@``B@(``(L"``",`@``C0(``(X"``"/`@``D`(``)$" +M``"2`@``DP(``)0"``"5`@``E@(``)<"``"8`@``F0(``)H"``";`@``G`(` +M`)T"``">`@``GP(``*`"``"A`@``H@(``*,"``"D`@``I0(``*8"``"G`@`` +MJ`(``*D"``"J`@``JP(``*P"``"M`@``K@(``*\"``"P`@``L0(``+("``"S +M`@``M`(``+4"``"V`@``MP(``+@"``"Y`@``N@(``+L"``"[`@``O`(``+P" +M``"]`@``O0(``+X"``"^`@``OP(``+\"``#``@``P`(``,$"``#!`@``P@(` +M`,("``##`@``Q`(``,4"``#&`@``QP(``,@"``#)`@``R@(``,L"``#,`@`` +MS0(``,X"``#/`@``T`(``-$"``#2`@``TP(``-0"``#5`@``U@(``-<"``#8 +M`@``V0(``-H"``#;`@``W`(``-T"``#>`@``WP(``.`"``#A`@``X@(``.," +M``#D`@``Y0(``.8"``#G`@``Z`(``.D"``#J`@``ZP(``.P"``#M`@``[@(` +M`.\"``#O`@``\`(``/`"``#Q`@``\@(``/,"``#T`@``]0(``/8"``#W`@`` +M^`(``/D"``#Z`@``^P(``/P"``#]`@``_@(``/\"``#_`@````,```$#```" +M`P```P,```0#```%`P``!@,```<#```*`P``"@,```H#```*`P``"P,```L# +M```+`P``"P,```P#```,`P``#`,```P#```,`P``#`,```P#```,`P``0``! +M``\#```0`P``$`,``!$#``!"``(`%@,``!8#```7`P``%P,``!<#```7`P`` +M1@`"`$H``@!.``$`(0,``"(#``!0``$`4@`!`"<#```H`P``*`,``"D#```J +M`P``5``#`%P``P!D``,`;``"`'```@!)`P``2@,``'0``0!-`P``30,``$T# +M``!-`P``30,``$T#``!-`P``30,``$T#``!-`P``30,``$T#``!-`P``30,` +M`$T#``!-`P``#0,```X#```2`P``$P,``!0#```5`P``&`,``!D#```:`P`` +M&P,``!P#```=`P``'@,``!X#```?`P``(`,``",#```D`P``)0,``"8#```K +M`P``+`,``"T#```N`P``+P,``#`#```Q`P``,@,``#,#```T`P``-0,``#8# +M```W`P``.`,``#D#```Z`P``.P,``#P#```]`P``/@,``#\#``!``P``00,` +M`$$#``!"`P``0P,``$0#``!%`P``1@,``$<#``!(`P``2`,``$L#``!,`P`` +M3@,``$```0!1`P``40,``%(#``!"``0`60,``%(``0!<`P``70,``%X#``!> +M`P``7P,``%\#``!?`P``7P,``&`#``!@`P``8`,``&`#``!@`P``8`,``&`# +M``!@`P``8`,``&`#``!@`P``8`,``&`#``!@`P``8`,``&`#``!A`P``80,` +M`%0`!`!D``0`>P,``'L#``![`P``>P,``'0`!`"$``0`E``$`*0`!`"T``0` +MQ``#`,P``P#4``,`W``"`.```@#D``(`Z``"`.P``0#R`P``\P,``/0#``#U +M`P``]0,``/4#``#U`P``]0,``/4#``#U`P``]0,``$\#``!0`P``4P,``%,# +M``!4`P``50,``%8#``!6`P``5@,``%8#``!7`P``5P,``%<#``!7`P``6`,` +M`%@#``!8`P``6`,``%H#``!;`P``8@,``&(#``!B`P``8@,``&(#``!B`P`` +M8@,``&(#``!C`P``9`,``&4#``!F`P``9P,``&@#``!I`P``:@,``&L#``!L +M`P``;0,``&X#``!O`P``<`,``'$#``!R`P``0,``'H#``!\`P``?0,``'X#``!_`P``@`,``($#``""`P``@P,` +M`(0#``"%`P``A@,``(<#``"(`P``B0,``(H#``"+`P``C`,``(T#``".`P`` +MCP,``)`#``"1`P``D@,``),#``"4`P``E0,``)8#``"7`P``F`,``)D#``": +M`P``FP,``)P#``"=`P``G@,``)\#``"@`P``H0,``*(#``"C`P``I`,``*4# +M``"F`P``IP,``*@#``"I`P``J@,``*L#``"L`P``K0,``*X#``"O`P``L`,` +M`+$#``"R`P``LP,``+0#``"U`P``M@,``+<#``"X`P``N0,``+H#``"[`P`` +MO`,``+T#``"^`P``OP,``,`#``#!`P``P@,``,,#``#$`P``Q0,``,8#``#' +M`P``R`,``,@#``#)`P``R0,``,H#``#+`P``S`,``,T#``#.`P``SP,``-`# +M``#1`P``T@,``-,#``#4`P``U0,``-8#``#7`P``V`,``-D#``#:`P``VP,` +M`-P#``#=`P``W@,``-\#``#@`P``X`,``.$#``#B`P``XP,``.0#``#E`P`` +MY@,``.<#``#H`P``Z0,``.H#``#K`P``[`,``.T#``#N`P``[P,``.\#``#P +M`P``\0,``/@#``!```(`_`,``/T#``#^`P``_@,``/X#``#^`P``_P,````$ +M``!$``(`2``"`$P``0`*!```"P0```P$```-!```#00```T$```-!```#@0` +M``X$```.!```#@0```\$```/!```#P0```\$```0!```$`0``!`$```0!``` +M3@`$`%X``0`8!```&00``!H$```:!```&P0``!L$``!@``,`(00``"($```B +M!```:``#`'```P!X``,`@``"`#T$```^!```/P0``#\$``!`!```000``(0` +M`@"(``$`1P0``$<$``!'!```1P0``$@$``!(!```2`0``$@$``#Y`P``^0,` +M`/H#``#[`P```00```($```#!```!`0```4$```&!```!P0```<$```(!``` +M"00``!$$```1!```$00``!$$```2!```$P0``!0$```4!```%00``!4$```5 +M!```%00``!4$```5!```%00``!4$```6!```%P0``!P$```!0#M`@4`[0,%``P#!0`- +M\P4`[1$%`/D0!0#V!P4`!@@%`/KR!0`&"P4`!@X%``?K!0``Y@4`_A`%``?S +M!0#^$04`]@D%``#J!0#Z]P4`_AH%``_Q!0`/]04`#_<%`/,"!0`/_@4`_AP% +M`/_@!0`##`4`Z`(%`/?Z!0`/!04`#PX%`/L+!0`#$04`#QL%`/_D!0`0`@4` +M`QL%`/,%!0`$]@4`$?D%`!'\!0`!#@4`_^8%``<(!0#[&P4`!PH%`!$$!0`1 +M'04`$OP%`!+^!0`2_P4`!PL%`/_J!0`3]@4`$_<%``L%``C[!0`5_04`Z>4%``$?!0#_\@4`%0D% +M`!;_!0`6`@4`%@8%`!?A!0`7Y04``NT%`._\!0`8_P4`^?$%`!@&!0#U!P4` +M]0D%``@$!0`(!04`^?8%``@'!0`:`04`!`L%`.4+!0`)[P4`"?$%`.P1!0`< +M_@4`"?4%``GV!0`%]`4`]NH%`!WQ!0#R^04`_18%`/T9!0#^XP4`'0(%`/[H +M!0`=!`4`'OD%`![_!0#^[@4`_N\%`!_S!0#R_04`[?D%`/[R!0`-_@0`X1\$ +M``+P!`#_"@0`]OP$``/M!`#O`00`#@$$``X#!``#\P0`_PX$`/P+!`#]\00` +M_?,$`/<$!``)!P0`^_@$`.[_!``5``0`%0$$`/OZ!`#X_`0``!X$`!D!!``` +M'P0`\0$$``H'!``%\P0`_1$$``'Q!`#A_P0`^0L$``#M!```[P0`'_T$`/KY +M!``(`P0`]P(#`/OY`P#V`0,`^/T#`/;_`P`'!P,`"P,#`/L$`P`%^`,`Y@`# +M``K^`P#X`0(`"/\"`/P'`@``X0(```D!``D`!@`$_P4`_``$``/_`P#]_P,` +M!@`%`/?_`0#[_@$``!L"``#V`@``]0$`_@H%`.[R!0#X$P4`_A\%``H$!0#X%P4``?(%`/GE!0`*%P4`"^D% +M`.[]!0`+\04`"_4%`.[^!0`+^P4`Y^$%``0;!0`%YP4`!>L%``7L!0`%[P4` +MY^4%`.X*!0#Y^`4`"PD%``L+!0`,YP4`[_L%``7V!0#G^04`Y_\%`./^!0#A +M!04`Z/8%`.\'!0#O%04`Z/T%``P$!0`,!04`#!`%``W@!0`-Y04`#>T%``WQ +M!0#H_P4`Z``%``WZ!0#U#@4`#?P%`/P,!0#\#04`_`X%`/45!0#\$04`_!,% +M`/;C!0`%"04`#N,%``[V!0`%"@4`Z`$%`/WE!0`%#04`_><%`/;V!0`."`4` +M!14%`/;X!0#][@4`#_D%``_[!0`&Z@4`!NP%`/`"!0`&\`4`!O$%``$5!0`& +M]`4`]OH%``\'!0`/#04`_?(%`/D-!0#P`P4`X`$%`!#_!0#A$04``N0%`!`' +M!0`0"@4``NL%`/D3!0#ZY04`^NT%`!'Z!0`1^P4`^O$%`.$4!0`1_@4`Y.`% +M`/KV!0#D[`4`$0(%`.$>!0#I!`4`$08%`!$)!0`1#P4`ZOX%`!$?!0#Q!@4` +M!@D%`/$+!0#Q&P4`$@$%``8-!0`2!04`$@8%`/8(!0`&#P4`$_@%``80!0`& +M$04`$_X%``?A!0`'Z@4`\O8%`/81!0`'[P4`$P<%`/8;!0`4_P4`%``%`!0! +M!0`'\@4`%>T%`!7O!0#J_P4`]_4%`/+[!0#]#`4`Z@H%`!4'!0#]#@4`%O$% +M`.OZ!0`6``4`Z_X%`.O_!0`7X`4`X?X%`/("!0`7Z04`%^P%`!?M!0`7^04` +M%_\%`!<`!0#]%P4``@L%`/(#!0#]'04`&`$%`!@#!0`"#@4`&?D%``(/!0`" +M$`4`_1X%`/T?!0`9!@4`&1T%``/A!0`#X@4``^4%``/G!0`#Z04`!PX%``/J +M!0`;`@4`&P,%`/($!0`;%P4`!Q,%`/[G!0#R"`4`"/<%`!P"!0`4% +M`/[M!0#R"@4`'?(%`!WY!0#S^P4`\_P%``GK!`#Q!00`^@H$`/0'!``-!00` +M#O\$```1!``%]00`]OL$``_]!`#]#P0`_Q4$`/L(!`#]$P0`_O`$`/7Z!``! +MX00``P@$`/+^!`#Y"00``0P$`!("!``3^00`"OL$`.+_!`#O`P0`$P,$`!7_ +M!``![P0`^1$$`/WA!``7`P0`!0@$``;E!``!&@0`!O4$`!O]!``&]@0``1L$ +M``<-!`#M_P0``.D$``CZ!``=Z00`'?T$``#K!`#I``0`#/X$`./C!`#_[00` +M_?0$`/GR!`#X`P,`$``#`/```P#\^`,`$0$#`/;^`P`""`,`_P\#``8'`P`' +M!0,`#``#`.L!`P`#^`,`_O<#``$-`P`!#P,`!/D"`/\;`@`(`@(`^?L"`/O[ +M`@`&^@(`_P@"``0%`@#\^P(``/\$`/__!0`"`P0```4$``("`P#X_P$`!P(! +M``(%!@#[`04`_`,&`/\=`@`$^@(`^0<"``T!`@#Y_P4``P($`./_`@`"]@(` +M!@4"``?Y`@`(_@(`!OD"`.$``0#Y_@$`!P,!`/X&!@`%_08```@!`/S\`0#] +M!@$``.4!``4"!@#_^P4``_L&`/O]!@#W^P,`_/<#``$*`P`.``,`[P`#`.T! +M`P#X!`,`"04#`/@%`P`"\0,``O(#`/[V`P#Z"`,`^`8#`.X``P`<_P,`]0,# +M`/WX`P`'\0,`]_D#``/Q`P`%]P,`_O@"```=`@#S_P(`^`("`/GY`@#Z!@(` +M#0`"``8#`0`$_08`XP`&`/K]`0`$!`$`_O\"`!L`!@#\!`$`'P`!`/H`!0`& +M`@8`'P$#`/_T!`#[ZP0`]``"`/C^`@`!XP(`!0,&`/P&`0`'_@$``.,&`/_Z +M!@`'_P4``_T$`/_^`@``!@4`]P$!`/?C!`#I_00`^0@$`.G_!`#]%00`]/X$ +M`/[Q!`#^]`0`"@4$`/+_!`#\"@0`^0\$`/P/!`#\%@0`]08$`/WI!``+`@0` +M_>T$``L%!`#Z]00`#/D$``S[!`#U"P0`!@H$``/^!`#U#00`^`@$``WY!``- +M^P0``PX$``?V!`#V^00``Q4$``3T!``"X@0``NX$``T'!``"[P0`_?8$`/\, +M!``.`@0`^?4$``X&!`#P`00`\?L$`/\0!`#T`@0``!0$``\#!``/#P0`#Q$$ +M```6!``1X@0`$>T$`!'W!`#_%`0`X?T$`/L-!`#\]@0`!Q$$``<6!`#U]00` +M!`@$`/<*!``3_P0`XOX$``C]!``3`@0``.`$`!7Y!`#X]P0`_A,$`/CX!`#^ +M&P0`]?P$``@&!``9_00`&?\$`/_B!``)[00`&O\$``#H!`#L_P0`Y`$$``#L +M!``"#00`&PD$`/_G!```[@0`[?X$`.GY!``#\@0`^@L$``/T!``%"P0`'0,$ +M``4,!``?X00`^A$$`/T*!``)"@0`#0(#``$3`P`""@,`#_\#``D$`P#V!`,` +M"OT#``/U`P`#]@,`]P4#```,`P`#"P,`"_D#```/`P#G`0,`_PT#``G[`P#T +M_P,`_QH#`/#_`P#M``,`'_\#`/D&`P#^"P,``1T"`/\+`@`)_0(``O<"``?\ +M`@`/``(`"/P"`!H``@`;_P(`"0("``'E`@#C`0(`\0`"`!T!`@`*`0(`]?\! +M`/H#`0`#^@$`_00&`/K_!@`!!@8`_OX#`/\`!``!_P4`!?X&`/_W`0#^"@(` +M^@4"``'Z!@#[`P8`_P0$`/L"!@`#!08`_?<"``0&`@`=_P(``0@"``7Z`@`> +M``(``P8!`!D``0#_"0$``OH&``+Y!@`(``8``P,$`/T"!```^00`_?X$`/SZ +M`@`&\@0`]PD$``#T`P#]_`$`_?D!`/P%`0`*``8``0<&``#Z!0#_^04`_@@! +M``,/`P#^#0,`_A8#`/_A`P``]P8``?D%``KZ`P`/`@,`!P8#``;N`P`(]@,` +M"/@#`!,!`P`7`@,`&``#`/(``P#U!0,`!_4#``?W`P`!$0,`\0,#``GW`P#W +M_`,`^`<#``L'`P#Y]P,`_Q<#`/0!`P#Y!0(`!@8"`/D$`@#[!0$`_04&`.0` +M!@`'`04`Y0`&`/S]!@`&^`(`\?T"``,'`0#B``$`!@0!`/[]!`#]`P0```(& +M```!!`````$````````````````````````````````````````````````` +M`````````````````````````````````````$``!@!-````R``&`"X!!@"> +M````G@```(X!!@#N`08`,@(&`)("!@#L`@8`1`,&`&X!``!N`0``;@$``&X! +M``"F`P8`&@0&`.L!``#K`0``[`$``.P!``#L`0``[`$``'P$!@#L!`8`7@4& +M`,8%!@#C`@``XP(``.,"``#C`@``)`8&`#0#``"D!@8`$`<&`*<#``"G`P`` +M?@<&`,X'!@`'!```!P0``#X(!@!^"`8`2P0``$L$``!+!```2P0``$```P!( +M``,`4``"`%0``@!8``$`6@`#`!X````>````8@`!`"$````B````(@```",` +M```C````(P```",````D````)````"0````D````)````"0````D````)``` +M`"0````D````)````"0````D````)````"0````D````9``"`&@``@!L``$` +M+P```#`````P````,````#`````Q````,@```#,````T````-0```#4````U +M````-0```&X``P!V``$`/````#T````^````/@```'@``P"```,`3````$P` +M``!,````3````$P```!,````3````$P````!`````@````,````$````!0`` +M``8````'````"`````D````*````"P````P````-````#@````\````/```` +M$````!$````2````$P```!0````5````%@```!<````8````&0```!H````: +M````&@```!H````;````&P```!P````=````'P```"`````E````)@```"<` +M```H````*0```"H````K````+````"T````N````-@```#8````W````.``` +M`#D````Y````.0```#D````Z````.P```#\````_````/P```#\```!````` +M00```$(```!#````1````$4```!&````1P```$@```!)````2@```$L```!. +M````3@```$X```!.````3@```$X```!.````3@```$\```!/````3P```$\` +M``!```,`2``#`%```P!8``(`7``"`&```0!P````<````'$```!Q````<@`` +M`&(``0!U````=0```'8```!D``$`>0```'D```!Y````>0```'H```!Z```` +M>@```'H```!Z````>@```'H```!Z````>@```'H```!Z````>@```'H```!Z +M````>@```'H```!Z````>@```'H```!Z````>@```'H```!Z````>@```'H` +M``!Z````>@```'H```!Z````>@```'H```!Z````4````%$```!2````4P`` +M`%0```!5````5@```%<```!8````60```%H```!;````7````%T```!>```` +M7P```&````!A````8@```&,```!D````9````&4```!E````9@```&<```!H +M````:0```&H```!K````;````&T```!N````;P```',```!T````=P```'@` +M``![````>P```'L```![````>P```'L```![````>P```'L```![````>P`` +M`'L```![````>P```'L```![````?````'P```!\````?````$```P""```` +M2``"`$P``@!0``(`5``!`%8``0"2````6``!`%H``0!<``$`7@`!`)L```"; +M````FP```)L```";````FP```)L```";````FP```)L```";````FP```)L` +M``";````FP```)L```"<````G````)P```"<````G````)P```"<````G``` +M`)T```"=````G0```)T```"=````G0```)T```"=````?0```'T```!^```` +M?P```(````"`````@0```($```"#````A````(4```"&````AP```(@```") +M````B@```(L```",````C0```(T```".````CP```)````"1````DP```)0` +M``"5````E@```)<```"8````F0```)H```!```(`H@```*,```!$``(`J``` +M`*@```"H````J````$@``@!,``(`4``"`+0```"U````M@```+<```"W```` +MN````+@```"X````N````+D```"Y````5``!`%8``0"^````OP```,````!8 +M``(`Q````,0```#%````7``"`,H```#*````R@```,H```#*````R@```,H` +M``#*````R@```,H```#*````R@```,H```#*````R@```,H```#*````R@`` +M`,H```#*````R@```,H```#*````R@```,H```#*````R@```,H```#*```` +MR@```,H```#*````GP```)\```"@````H0```*0```"E````I@```*<```"I +M````J@```*L```"L````K0```*X```"O````L````+$```"R````LP```+,` +M``"Z````NP```+P```"]````P0```,$```#"````PP```,8```#'````R``` +M`,D```#+````RP```,L```#+````RP```,L```#+````RP```,L```#+```` +MRP```,L```#+````RP```,L```#+````S````,P```#,````S````,P```#, +M````S````,P```#-````S0```,T```#-````0``"`-$```#2````T@```-,` +M``#3````TP```-,```#3````TP```-,```#3````TP```-,```#3````TP`` +M`-,```#3````TP```-,```#3````TP```-,```#3````TP```-,```#3```` +MTP```-,```#3````TP```-,```#3````TP```-,```#3````S@```,\```#0 +M````T````-0```#4````U````-0```#4````U````-0```#4````U````-0` +M``#4````U````-0```#4````U````-0```#5````U0```-4```#5````0``" +M`$0``0!&``$`2``!`$H``0#A````X@```.(```!,``(`4``"`%0``@!8``(` +M\@```/(```#R````\@```/(```#R````\@```/(```#R````\@```/(```#R +M````\@```/(```#R````\@```%P``0!>``$`]P```/@```#Y````^0```/D` +M``#Y````^@```/H```#Z````^@```/L```#[````^P```/L```#6````U@`` +M`-<```#8````V0```-H```#;````W````-T```#>````WP```.````#C```` +MXP```.0```#E````Y@```.<```#H````Z0```.H```#K````[````.T```#N +M````[P```/````#Q````\P```/0```#U````]@```/P```#\````_````/P` +M``#]````_0```$```@!$``$``P$``$8``@`'`0``!P$```@!```(`0``"`$` +M``@!```)`0``"0$```D!```)`0``"0$```D!```)`0``"0$```H!```*`0`` +M"@$```H!``!*``(`3@`"`%(``@!6``$`&0$``!D!```9`0``&0$``!D!```9 +M`0``&0$``!D!```9`0``&0$``!D!```9`0``&0$``!D!```9`0``&0$``!H! +M```:`0``&P$``%@``0`>`0``'@$``!X!```>`0``'P$``!\!```?`0``'P$` +M`"`!```@`0``(`$``"`!``#^````_P`````!`````0```0$```(!```$`0`` +M!`$```4!```&`0``"P$```P!```-`0``#@$```\!```0`0``$0$``!(!```3 +M`0``%`$``!4!```6`0``%P$``!@!```<`0``'0$``"$!```A`0``(0$``"$! +M```A`0``(0$``"$!```A`0``(0$``"$!```A`0``(0$``"$!```A`0``(0$` +M`"$!```B`0``(@$``"(!```B`0``(@$``"(!```B`0``(@$``"(!```B`0`` +M(@$``"(!```B`0``(@$``"(!```B`0``0``!`"4!```F`0``)P$``"@!```H +M`0``*`$``"@!``!"``(`1@`"`$H``@!.``(`4@`!`%0``0!6``$`/@$``#\! +M```_`0``/P$``#\!```_`0``/P$``#\!```_`0``/P$``#\!```_`0``/P$` +M`#\!```_`0``/P$``#\!```C`0``)`$``"D!```J`0``*P$``"P!```M`0`` +M+@$``"\!```P`0``,0$``#(!```S`0``-`$``#4!```V`0``-P$``#``$`8``!`&T!``!M`0``;0$``&T!``!M`0``;0$` +M`&T!``!M`0``0@$``$,!``!$`0``10$``$8!``!'`0``2`$``$D!``!*`0`` +M2P$``$T!``!.`0``3P$``%`!``!1`0``4@$``%,!``!4`0``50$``%8!``!7 +M`0``5P$``%@!``!9`0``6P$``%P!``!=`0``7@$``&(!``!C`0``:0$``&H! +M``!K`0``;`$``&\!``!P`0``<0$``'(!``!S`0```$``'D!``!Z`0``>P$``'P!``!]`0``?@$``'\!``"` +M`0``@0$``((!``"#`0``A`$``(4!``"&`0``AP$``(@!``")`0``C`$``(T! +M``".`0``CP$``)0!``"5`0``F0$``)D!``":`0``FP$``)\!``"@`0``H0$` +M`*(!``"D`0``I0$``*8!``"G`0``J`$``*D!``"J`0``JP$``*P!``"M`0`` +MK@$``*\!``"P`0``L0$``+(!``"S`0``M@$``+8!``"V`0``M@$``+``$`8``!`.4!``#F`0``YP$``.@!``#I`0``Z@$``.H! +M``#J`0``Z@$``+X!``"_`0``P0$``,(!``##`0``Q`$``,@!``#(`0``R0$` +M`,H!``#-`0``S@$``,\!``#0`0``T0$``-(!``#3`0``U`$``-4!``#6`0`` +MUP$``-@!``#9`0``V@$``-L!``#<`0``W0$``-X!``#?`0``X`$``.$!``#B +M`0``XP$``.0!``#M`0``[@$``$```0!"``$`\P$``/,!``#S`0``\P$``$0` +M`0!&``$`2``!`$H``0!,``$`_@$``/\!`````@```0(```$"```"`@```@(` +M``,"```#`@```P(```,"```$`@``!`(```0"```$`@``!`(```0"```$`@`` +M!`(```4"```%`@``!@(```8"```'`@``3@`"`%(``@!6``(`%`(``!0"```4 +M`@``%`(``!0"```4`@``%`(``!0"``!:``(`7@`"`&(``@!F``$`:``!`&H` +M`0!L``$`*0(``"H"```J`@``*P(``"P"```M`@``+0(``"X"``!N``$`[P$` +M`/`!``#Q`0``\@$``/0!``#U`0``]@$``/`@``'P(``"`"```A`@``(@(``","```D`@``)0(``"8"```G`@``*`(` +M`"\"```P`@``,0(``#$"```Q`@``,0(``$```0!"``$`-@(``#<"```X`@`` +M.`(``#D"```Z`@``1``"`$@``@!,``(`4``"`$L"``!+`@``2P(``$L"``!+ +M`@``2P(``$L"``!+`@``5``"`%@``@!<``(`8``!`&(``0!D``$`9@`!`&`" +M``!A`@``80(``&$"``!A`@``80(``&$"``!A`@``80(``&$"``!A`@``80(` +M`&$"``!A`@``80(``&$"``!A`@``8@(``&("``!B`@``8@(``&,"``!C`@`` +M8P(``&,"``!H``$`9@(``&<"``!H`@``:@`!`&P``0!N``$`<``!`#("```S +M`@``-`(``#4"```[`@``/`(``#T"```^`@``/P(``$`"``!!`@``0@(``$," +M``!$`@``10(``$8"``!'`@``2`(``$D"``!*`@``3`(``$T"``!.`@``3P(` +M`%`"``!1`@``4@(``%,"``!4`@``50(``%8"``!7`@``6`(``%D"``!:`@`` +M6P(``%P"``!=`@``7@(``%\"``!D`@``90(``&D"``!J`@``:P(``&P"``!M +M`@``;@(``&\"``!P`@``<0(``'("``!S`@```(``'@"``!Y`@``>0(``$```@!$``(`2``" +M`$P``@!0``(`5``!`%8``0!8``$`6@`!`)8"``"7`@``EP(``)@"``"8`@`` +MF`(``)@"``"9`@``F0(``)D"``"9`@``7``!`)P"``"=`@``7@`!`*`"``"@ +M`@``H`(``*`"``!@``$`8@`!`*4"``"E`@``I@(``*8"``"F`@``I@(``*8" +M``"F`@``I@(``*8"``"G`@``9``"`*L"``"L`@``K0(``*X"``"O`@``KP(` +M`'H"``![`@``?`(``'T"``!^`@``?P(``(`"``"!`@``@@(``(,"``"$`@`` +MA0(``(8"``"'`@``B`(``(D"``"*`@``BP(``(P"``"-`@``C@(``(\"``"0 +M`@``D0(``)("``"3`@``E`(``)4"``":`@``FP(``)X"``"?`@``H0(``*(" +M``"C`@``I`(``*@"``"H`@``J0(``*H"``"P`@``L`(``+`"``"P`@``L0(` +M`+$"``"Q`@``L0(``+("``!```(`1``"`$@``@!,``(`4``!`,4"``#&`@`` +MQP(``,<"``#'`@``QP(``,@"``#(`@``4@`"`,P"``#-`@``S0(``,X"``#. +M`@``SP(``%8``0#2`@``T@(``-,"``#3`@``TP(``-,"``#3`@``TP(``-," +M``#3`@``6``!`%H``0!<``$`V@(``-L"``#;`@``W`(``-P"``#=`@``W0(` +M`-T"``#=`@``W@(``-X"``#?`@``WP(``.`"``#@`@``X0(``.$"``#B`@`` +MX@(``.("``#B`@``LP(``+0"``"U`@``M@(``+<"``"X`@``N0(``+H"``"[ +M`@``O`(``+T"``"^`@``OP(``,`"``#!`@``P@(``,,"``#$`@``R0(``,D" +M``#*`@``RP(``-`"``#1`@``U`(``-4"``#6`@``UP(``-@"``#9`@``Y`(` +M`.0"``#E`@``Y0(``.8"``!```(`ZP(``.L"``!$``(`2``"`$P``@!0``(` +M5``"`%@``@!<``(`8``!``D#```)`P``"0,```D#```)`P``"0,```D#```) +M`P``"0,```D#```)`P``"0,```D#```)`P``"0,```D#``!B``$`9``!`&8` +M`0!H``$`:@`!`!0#```5`P``%@,``!<#```7`P``&`,``!D#```:`P``&@,` +M`!L#```;`P``;``"`'```0!R``$`=``!`'8``0!X``$`>@`!`'P``@`N`P`` +M+@,``"\#```P`P``,0,``#(#```S`P``,P,``.<"``#H`@``Z0(``.H"``#L +M`@``[0(``.X"``#O`@``\`(``/$"``#R`@``\P(``/0"``#U`@``]@(``/<" +M``#X`@``^0(``/H"``#[`@``_`(``/T"``#^`@``_P(````#```!`P```@,` +M``,#```$`P``!0,```8#```&`P``!P,```@#```*`P``"P,```P#```-`P`` +M#@,```\#```0`P``$0,``!(#```3`P``'`,``!T#```>`P``'@,``!\#```@ +M`P``(0,``"(#```C`P``)`,``"4#```F`P``)P,``"@#```I`P``*@,``"L# +M```K`P``+`,``"T#```U`P``-0,``#4#```U`P``-@,``#8#``!```(`1``" +M`$@``@!,``(`4``"`%0``@!8``(`7``"`&```0!B``$`6@,``%H#``!;`P`` +M6P,``%P#``!<`P``70,``%T#``!>`P``7@,``%X#``!>`P``7P,``%\#``!? +M`P``7P,``&`#``!D``$`9@`!`&@``0!G`P``9P,``&<#``!G`P``:`,``&@# +M``!H`P``:`,``&H``0!K`P``;`,``&P#``!M`P``;0,``&T#``!M`P``;0,` +M`&T#``!M`P``;0,``&T#``!M`P``;0,``&T#``!M`P``;0,``&T#``!M`P`` +M-P,``#@#```Y`P``.@,``#L#```\`P``/0,``#X#```_`P``0`,``$$#``!" +M`P``0P,``$0#``!%`P``1@,``$<#``!(`P``20,``$H#``!+`P``3`,``$T# +M``!.`P``3P,``%`#``!1`P``4@,``%,#``!4`P``50,``%4#``!6`P``5P,` +M`%@#``!9`P``80,``&(#``!C`P``9`,``&4#``!F`P``:0,``&H#``!N`P`` +M;@,``&X#``!N`P``;@,``&X#``!N`P``;@,``&X#``!N`P``;@,``&X#``!N +M`P``;@,``&X#``!N`P``;P,``&\#``!P`P``<`,``'$#``!R`P``0,``'H# +M``![`P``?`,``'T#``!_`P``@`,``($#``""`P``@P,``(0#``"%`P``A@,` +M`(<#``"(`P``B0,``(H#``"+`P``C`,``(T#``".`P``CP,``)`#``"1`P`` +MD@,``),#``"4`P``E0,``)8#``"7`P``F`,``)D#``"9`P``F@,``)L#``"< +M`P``G0,``)X#``"?`P``H`,``*$#``"B`P``HP,``*@#``"H`P``J`,``*@# +M``"I`P``J0,``*H#``!```$`K0,``*T#``"M`P``K0,``*X#``"N`P``K@,` +M`*X#``"O`P``KP,``+`#``"Q`P``L@,``+,#``"T`P``M`,``+4#``"U`P`` +MM0,``+4#``"U`P``M0,``+4#``"U`P``M@,``+8#``"V`P``M@,``+8#``"V +M`P``M@,``+8#``"V`P``M@,``+8#``"V`P``M@,``+8#``"V`P``M@,``+<# +M``!"``$`1``!`$8``0!(``$`2@`!`$P``0!.``$`Q@,``,<#``#(`P``R0,` +M`,H#``#*`P``RP,``,L#``"K`P``K`,``+@#``"Y`P``N@,``+L#``"\`P`` +MO0,``+X#``"_`P``P`,``,$#``#"`P``PP,``,0#``#%`P``S`,``$```@#0 +M`P``T0,``-(#``#2`P``TP,``-,#``#4`P``U`,``-0#``#4`P``1``"`$@` +M`@!,``(`4``"`%0``@!8``(`7``"`&```@!D``$`9@`!`&@``0!J``$`;``! +M`&X``0`!!````@0```,$```$!```!00```4$```&!```!@0```8$```&!``` +M!@0```8$```&!```!@0```8$```&!```!@0```8$```&!```!@0```8$```& +M!```!@0```8$```&!```!@0```8$```&!```!@0```8$```&!```!@0```8$ +M```&!```!@0```8$```&!```!@0``,T#``#-`P``S@,``,\#``#5`P``U@,` +M`-<#``#8`P``V0,``-H#``#;`P``W`,``-T#``#>`P``WP,``.`#``#A`P`` +MX@,``.,#``#D`P``Y0,``.8#``#G`P``Z`,``.D#``#J`P``ZP,``.P#``#M +M`P``[@,``.\#``#P`P``\0,``/(#``#S`P``]`,``/4#``#V`P``]P,``/@# +M``#Y`P``^@,``/L#``#\`P``_0,``/X#``#_`P````0```@$```(!```"`0` +M``@$```(!```"`0```@$```(!```"`0```@$```(!```"`0```@$```(!``` +M"`0```@$```)!```"00```H$```+!```#`0```T$```.!```#@0```\$```/ +M!```#P0```\$```/!```#P0```\$```/!```$`0``!`$```0!```$`0``!`$ +M```0!```$`0``!`$```0!```$`0``!`$```0!```$`0``!`$```0!```$`0` +M`!`$```0!```$`0``!`$```0!```$`0``!`$```0!```$`0``!`$```0!``` +M$`0``!`$```0!```$`0``!`$``!```$`0@`!`$0``0!&``$`2``!`$H``0!, +M``$`'P0``"`$```@!```(`0``"`$```A!```3@`"`"8$```G!```*`0``"@$ +M```H!```*`0``"@$```H!```*`0``"@$```I!```*@0``"L$```L!```+00` +M`"T$```N!```+@0``"\$```O!```+P0``"\$```O!```+P0``"\$```O!``` +M+P0``"\$```O!```+P0``"\$```O!```+P0``"\$```P!```,`0``#`$```P +M!```,00``#$$```Q!```,00``#($```R!```4@`"`%8``@!:``(`7@`"`&(` +M`@!F``(`$00``!($```3!```%`0``!4$```6!```%P0``!@$```9!```&@0` +M`!L$```$#`/[^`P#_`08`_P,#`/H`!``% +M$0,`_.0#`!7U`P#T"@,`#@<#`.[]`P`/XP,`!@P#``;U`P`&%0,`Z1<#``+K +M`P`'Y0,`"^,#`/$'`P`'%0,`&_P#`.7Y`P#[\P,`X`(#`!?_`@`._`(`\P," +M``4)`@`>_@(``@P"`/[R`@#P_0(`\P("`!$#`@#^"0$`^?L!``L`!0#D``4` +M`OD&`/OY`0`!\P$```D%`/G]!@`>_P$`^`,!```&!`#^``$``@$"``+]!``) +M!`(`[/P#`/OU`P`)^0(`!_H"`/[X!@`%]0(`[O\"`.7^`@#M`@(``_,"`!<" +M`@#^#`(`"`0"``@&`@`*^0(`__,!`/L$`0#^"@$`!?L!`/_Q`0#U`08`#?\! +M```,`0`'_`$`]`$!``X!`0`/_P$``_``8``@\"``(0`@`'!@(`^/@"``#^`0#]``(` +M_@(#``,"!`#][P(`^?4"`/H$`0`!'08`__H%```"`0#^`0(`^_\$`/<#`0#] +M$@(`]?D"`/\/`0`$!0$``PD!`!K_`0#]]P$`_0D!`/7]`0#T_@$``?@&``#V +M!0`*`P$`_0X"`.K^`@`=_0(``>H"`!$"`@`#"@(``@T"`./]`@`&"@(`!_8" +M`/WC`@#G`0(`"?L"`.$"`@#^_P(`[0`!`/SY`0#L``$`"/P!`/D#!@#_'08` +M_/\$`/T"!``"`P0`_`$$`/H!!0`#X0(`Y`("`/\:`0`!X@$`!P4!`/7_!@`< +M`0$`]_P"`.\"`@`&_@4`!0$$``("`P#__`0`]P0"`.L#`@`%]P(`_/<"``/M +M`@#^&@(`_N,"`/CZ`@#A'P(`"_D"`!C_`@#H`@(``.X!``P!`0```P(`^O\% +M`/_E!@`!$0$`__0!``0!!```X00`^P$$`/\"`@#__@(`_`\!``7^!0#Y +M_P0`!`@!`.T!`0`!#0$`_Q$!``#P!@`*_P8`^0$$```$`P`'^0$`ZP`!``'E +M!@`=_P4`'P`%`/_D`0#@_@(`_@\"```>!@`%_04`_^(&``H$`@#E_0(`_A<" +M`/WT`@#]`P0``NP"`.K_`@`,`P(`_NX"`!_]`@`#\@(`[`("`.,"`@`!#P$` +M`!,!``<$`0`%!P$``!4!``#J`0#]^`$`\?T!``#T!@#]!P8``?L$`/\$!``` +M^P,`_^,%`/X'!@`,``8`_P4$`.4!!@`,_@$`#O\!```(!0`$^0$``P@!`/H& +M`0`%!@$``08%`/D``P#B``4`&@$!`/KX`@#O_0(`_^$&`/_Y!`#Q^@(`^?8" +M``+B`@`+^P(`!_<"``+H`@`8_@(`_1<"`/<&`@#^'`(`[/\"`/[D`@#J`@(` +M`Q$"`.D"`@#X^P(`&@("`.H!`@#L_@(`%O\"```8`0`"]P$`!OL!`.@``0#V +M_P8``O@&``0$!@#Q``8`!@0&``'Y!````04``/\$`!H`!@`&_`8`!@4!``;Z +M`0#V_0$`_0L!```=!`#Y!`$`\`$!``/X`0``%P$``PL!``'I`0`+_0$`\@(! +M``X"`0`&^`$``_H&``#F!@`<_P8`X0`%`/`"``+E`@`5`@(`$04"`/7\ +M`@#[^`(`Z_T"`!\?`@`2`0$``?(!`/(!`0`5`0$`'/X!`.W_`0``$@$`!/@! +M`/@"!@#[`@4``!H&``8#!@`#_`4`\``&``$<`0`3_@$``.0$``0'`0`+`@$` +M#?X!`/L'`0`-`08`"@$&`/X&!0``\08`_PL&`/3Z`@#Z]@(`]_L"`.?]`@#M +M^0(`Y@$"``_Y`@#]'0(`_N`"`.D#`@`3^0(`]@0"``+O`@#U^P(`^0@"``$5 +M`@``!0,`&`$"`!GC`@#^Z@(`!O`"`!,%`@`3!@(`!O("`!_^`@#\#@(`"/L" +M``/I`@`!Y@(`"OP!`/WV`0#X!@$`_N(!`/GZ`0#_'P$`%``!`/\9`0#]^@8` +M`_\"``#E!``)``0``_4!``8'`0#D_P8`_@@&`/'_!@#I`0$`]OP!``+R`0#D +M_@$`\0(!`/SV`0`7`0$`"OT!``@"!@`.``8`!@(%`!``!@`?_P8`]_\%``@"`/@*`@`:_`(`&OT"``+C`@`1^0(`_?`" +M``OZ`@#D_0(`X0,"`.3\`@`*^P(``Q,"``,=`@#^$`(`\04"`.7I`@`8`@(` +M^0D!`/'^`0#T`@$`#P,!``+U`0`![0$`\`(!``@#`0``\P8`_`,%``$$!``$ +M_@0`^0<"`/D1`@#V`08`_`8&``0&!@`-``8``OL% +M`/S^!``"_`0``1L&``4-`@`$]`(`%_T"`/SU`@`#Y0(`_>4"`!+]`@`0_`(` +M%`("`.+]`@`*^`(``NH"``CX`@`.`P(`#@0"``L&`@`!ZP$`Y`$!``$(!@`` +M\@8`!`($`/L#!0`#]@$``Q<"`/WK`@#]!@8`"0$%`/W\!0#G``8`#/\!`/KY +M`0`'_04``.,#`/#_`0#_%0$`^OL!``(+`0`&^0$`_0@!``D#!@`#^P4`!/T% +M``;_!`#]^P4```L%`/O]!0#^!04`^``$`("`!```'P4`^/\%``H"!@`0!`(` +M]`8"`/T5`@#_%@(`'0$%``GZ`@#G_@(`_A$"``/T`@#S^P(`[OX"`/4'`@#H +M`0(`!PD"``<1`@`(]@(`#@8"`!<&`@`"Y`(`YOX"`/[H`@`"Z0(`!>,"`/GX +M`@`%]@(``1("`/8%`@`,!`(`%/\"`/'[`@`#X@(`_Q(!`/[U`0#X!`$``P$" +M`/8&`0`=_@$``.P!`.G_`0`-`@$``O0!`/_O`0#S_0$`Z0`!`/\>`0#R``8` +M`?$&``'A!@`%`@4``.\&`/;^!@#Z_@4`&_\%`/WI`@`$"@(`#OX!`/_M`0`# +M\0$`%@`!`/WS`0`9_P$`_O0!`!+_`0#C_@$`_^P"``[X`@`4_@(``_`" +M``+M`@#X]@(`_NT"``L$`@#P`P(`!0@"`/4)`@#B`@(`%@$!`/L&`0#I_0$` +M`>X!`/OZ`0#Y!@$`%@(! +M``P"`0`-_0$`$@(!`!K^`0`3_0$`$/X!``$9`0`;_@$`Y@`&``+V!@#[_`8` +M_PT&`/[[!0#X`04`^OT&``'D`0#X"0(`#?H"`/?^!@#B_P8`_/T%``,$!0#^ +M_`0``A4"`/X3`@`7Y0(`%_4"`.'^`@#]X@(`_1\"`/H)`@#\]`(`^>$"`/\8 +M`@`$]0(`]O@"`/'Y`@#^Y0(`%/P"`.(#`@`,^@(`#/P"`!G^`@#Z\@(`'OT" +M``GW`@`'"`(`&0("`/KT`@`."@(`$0<"`.L"`@#P_`(`\QT"`.4&`@`"#@$` +M&0$!`.W]`0#Z!P$``0P!`.W^`0`0_P$`_A(!`.L!`0#G_P$`&``!``+S`0`! +M"P8```X&``()!@`)_@8`!/P%``+_`0`!`04``0,"`/H"!0#\^@8``.T&``D" +M!@#@``8``!D%``/^`P`#``$`%P`!`/H(`0#@_P$`^@4!``,/`0#AX0$`$P,! +M``'P`0`5_P$`_^`!``T#`0#L`0$`_>$!`/WQ`0`$^P8`Y0`$``8&!@`;^P(` +M!AX"``?I`@`:!`(``@H&`/\*!@`$_P,`#P$&```/!@#Q`08`_QP&`/_W!0`! +M"04``OX"``($!```'`0`_00%``;Q`@#YZ0(`$1$"`!+X`@#V^0(`_!8"`!L" +M`@#I!P(`&P4"`.?C`@#\X0(`%_D"`/$&`@#D!@(``PP"`!(#`@#U!`(`_>P" +M``P<`@`/!`(`\@8"`/@(`@#S^0(`^0L"`/__!`!```(`-!@``!`4```0%``` +M"!0```@4``!$``(`+!@```P0```,$```#!````P0```4$```%!```!00```4 +M$```!Q@``$@``@`X&```%Q@```,0```#$````Q````,0```$$```!!````00 +M```$$```3``&``\8```^&```C``"``88``"0``(`&!@``)0`!``"$````A`` +M``(0```"$```*!0``"@4```@%```(!0``!88``"D``,``10```$4```\#``` +M/`P``#P,```\#```/`P``#P,```\#```/`P``#\4```_%```#A@``*P``P`< +M%```'!0``#`4```P%```"P0```L$```B"```/0@``"L(```O"```)`0``"0$ +M```Z"```-P@``",(```%"```.P@``#L(```["```.P@``#L(```["```.P@` +M`#L(```["```.P@``#L(```["```.P@``#L(```["```.P@``#D4```Y%``` +M'1@``"48```9$```&1```!D0```9$```-1```#40```U$```-1```"T0```M +M$```+1```"T0```R!```,@0``#($```R!```,@0``#($```R!```,@0``#($ +M```R!```,@0``#($```R!```,@0``#($```R!```,@0``#($```R!```,@0` +M`#($```R!```,@0``#($```R!```,@0``#($```R!```,@0``#($```R!``` +M,@0```T(```J"```$P0``!,$```?!```'P0``"X(```;"```$@0``!($```2 +M!```$@0``!($```2!```$@0``!($```S"```,P@``#,(```S"```&@P``!H, +M```Q$```*1```!$,```G#```'@@``!X(```V"```-@@``!4(```5"```"0@` +M``D(```F#```(0P```H$```*!```"@0```H$``!```8`'!@``"@4```H%``` +M(!```"`0```@$```(!```"P8```8&```/!0``#P4```0$```$!```!`0```0 +M$`````@````(````"`````@````(````"`````@````(````"`````@````( +M````"`````@````(````"`````@``.(`!@`T&```#!0```P4```D&```,@$& +M``(8```"`@8`,!0``#`4```X%```.!0``!00```4$```%!```!00```(#``` +M"`P```@,```(#```"`P```@,```(#```"`P```0,```$#```!`P```0,```$ +M#```!`P```0,```$#````00```$$```!!````00```$$```!!````00```$$ +M```!!````00```$$```!!````00```$$```!!````00```$$```!!````00` +M``$$```!!````00```$$```!!````00```$$```!!````00```$$```!!``` +M`00```$$```&#```!@P```8,```&#```!@P```8,```&#```!@P```<8```? +M&```0``&``L8```]$```/1```#T0```]$```+A```"X0```N$```+A```#<8 +M```9&```#10```T4```_$```/Q```#\0```_$```@``!`&`8```K&```@@`% +M`'$8``!I&```31@``$48``!U&```71@``%$4``!1%```8A```&(0``!B$``` +M8A```'(0``!R$````0``'@$ +M``!X!```>`0``'@$``!X!```>`0``'@$``!X!```>`0``'@$``!X!```>`0` +M`'@$``!X!```>`0``'@$``!X!```>`0``'@$``!X!```>`0``'@$``!X!``` +M>`0``'@$``!X!```>`0``'@$``!X!```>`0``'@$``!L!```3`0``'`$``!P +M!```<`0``'`$``!P!```<`0``'`$``!P!```<`0``'`$``!P!```<`0``'`$ +M``!P!```<`0``'`$``!##```0PP``$,,``!##```5Q```%<0``!S$```$```'A```!X0```>$```,10` +M`#$4```M%```+10```D0```)$```"1````D0```V$```-A```#80```V$``` +M$@P``!(,```2#```$@P``!(,```2#```$@P``!(,```C&```$Q@``$@8``!` +M``0`!1````40```%$```!1```'0$``!T!```=`0``'0$``!T!```=`0``'0$ +M``!T!```6`@``%@(``!8"```6`@``$<0``!K$```4@P``%(,```*#```"@P` +M``H,```*#```"@P```H,```*#```"@P``#H0```Z$```.A```#H0```R$``` +M,A```#(0```R$```(1```"$0```A$```(1```!T4```=%```-10``#44```# +M#````PP```,,```##````PP```,,```##````PP``!8,```6#```%@P``!8, +M```6#```%@P``!8,```6#```.Q@``$``!@!_&```?A@``'P0``!\$```?!`` +M`'P0```B#```(@P``"(,```B#```(@P``"(,```B#```(@P``%`8``"(``,` +M,Q@``)``!@`O%```+Q0``!<4```7%```7`0``%P$``!$```7A```%X0``!>$```8Q```&,0 +M``!C$```8Q```&H$``!J!```:@0``&H$``!Y#```90P``%D(``!9"```7PP` +M`'<,``!["```>P@``%0$``!4!```5`0``%0$```G!```)P0``"<$```G!``` +M)P0``"<$```G!```)P0``"<$```G!```)P0``"<$```G!```)P0``"<$```G +M!```)P0``"<$```G!```)P0``"<$```G!```)P0``"<$```G!```)P0``"<$ +M```G!```)P0``"<$```G!```)P0``&0(``!D"```9`@``&0(``!D"```9`@` +M`&0(``!D"```9`@``&0(``!D"```9`@``&0(``!D"```9`@``&0(``!Z#``` +M>@P``'H,``!Z#```>@P``'H,``!Z#```>@P``%L8``!6&```9A0``&84``!G +M%```9Q0``&$4``!A%```/@@``#X(```^"```/@@``#X(```^"```/@@``#X( +M```^"```/@@``#X(```^"```/@@``#X(```^"```/@@```X,```.#```#@P` +M``X,```.#```#@P```X,```.#```)A```"80```F$```)A```!$0```1$``` +M$1```!$0```Y$```.1```#D0```Y$```0``!`&@8```E%```)10``"D0```I +M$```*1```"D0```5$```%1```!40```5$```*@P``"H,```J#```*@P``"H, +M```J#```*@P``"H,```:$```&A```!H0```:$```1!@``$(8```/%```#Q0` +M`!L$``!!!```"!`0$Q`3%A86%A86&A@:&QL;&AH:&AL;&QT='2(B(AT='1L; +M'1T@("(B)28E(R,B(R8F*"@H,#`N+C@X.D5%4]SQ_)\4)_V?T?\'`!`>`V`0 +M'P-@)@#X_X#U_)]\]OR?____?P```(```&```/+\GX;W`P``]OR?6!,``/2? +M`&`````(__\?``````$```!``.[\GP```@`PH`!@9)X`8````D*($P````@` +M`("6F`#]"?S_`/K\GP#>_)\`&````.+\G__G__\`4OR?```!`/___O_`#P`` +M```_``````0#`__@`P+_X```,`,&"__P!```@`$``(#_]___`"[\GP```H"' +M$P``____#P```,``_ON?Y`T``/___P'__U\`>_C]_P```&(#``"`A`<"``#^ +M_)\````"____O?____```!"`__/__P`?````0```_W_P_P"`"0````#P_[__ +M_P``"(````.`__#_____#_\```^````&@````8```!&`E0$`0)4``$``#@`` +M``#`````,`````P````#`)T``$"5`P!`E0(`0```"@````6````$@```#8`` +M``R`C0``0!`(`&```/`/`#__`/___X`6```(($X``````.````"@____P/=] +M__\`@```````4""__P`I!`0```!X`":DA`#&A(0`)*20$@``,`8A)`0`0&\` +M`.AN``#@#P``3`\``(`/``!(K@!@6+$`8/___[]$,R(1____`+P2``"H:P`` +MP+8&`-Q'`6```%(`S&L``!!N```,;```K&P```#_`/_X'0``\/\``$`(```@ +M/_\``B```#?-0OUFN/2,B_%/!SQM``#`$@````#`/XP,``!0"`!@P&L``!`- +M```_G``````D``%@``"(#P``M`\``/0+``"`#0``H`T``+`6``!H70``Z%T` +M`"L-``#$$@``M`L``"@-``"T/0``##X``)D]``"L&P``!!P``)`,``"P"`!@ +M"`P``%1M```T#```=`P``*@+``#H#P``2!,``$`0```5/0``E!(```((``"( +M#```0&T``*P,``"0"0``N!0``+@2``"L70``;&L``*@2```4#P``B%X``)P2 +M``!`"0!@\&T``!!K```1#P```%("````.`0`X(8"``#,``!X:0``=B\``-@; +M``#L#0``1@4`3F(``%!B```.8P``$&,``/QK``#0#@``8&T``!`/```8#P`` +M/!0``%0;``#__[__@%X`````0`"8"P``9%\``/!?``"P70``*0T``/1=```, +M"0``3`T``$1M```,"@``#`T``(@_`6"D/P%@9G>(F?__`_@``/P'`/X#`+02 +M``!`6`HA@%@#%0!8"B3`6"$2@%@8)%P``"/#;`6``(`,`@'^`?U0(```\"@)@;.H!8)@(`F"H +MZP%@$`L`8!H+`&!8"@)@D`H"8'0*`F"T"`)@[`@"8-`(`F"$Z@%@P.L!8+3J +M`6#PZP%@G.H!8-CK`6"!`/`/`P@```L``@#_W___,`L`8,`+`&```%$```!0 +M````<0```'`````1`!\R```?,0`````0````T0```)$```#0````D`#_#P`` +M_Q\``/X/``#^'P``'S4``!\S```?-````A(```#````?6```T`L`8!]0```" +M#@``'U<``#@,`&`?5```'UH``!]9``!0#`!@8`P`8"`,`&`?4@``'U$``$`, +M`&`0#`!@'U8```@,`&``#`!@'U,``&3^`6"0X`%@]/X!8/3A`6"H_P%@9`0" +M8.#E`6!T`0)@G`4"8!\K``!P#`!@@`P`8!\P`````+``#`@``%@5`F#@#@`` +MD`P`8/___P0$B(ZHI$?@1#`PA.0!@_R#R +M8ZIR8\3B(A?I(8@AR4UR:S?,>*+!#+$Z`.40*9+1$W)CM')CM;(CL[)I&:(I +M&7SD0*H0HF.S@B('@FD:I2@"PM$3HFP^Y6D3;0KE="2@2B"E+1K2T1/2+3Z@ +MY'/P(`!@W7/@W7-PW7/9425H$Z!*("4L&O$\`*!$0B"""8]UR;U;B +M8\:EE/<,BK%"`,O!)93W#&JQ0P#-`663]Z*AP&6O]PP>@40`B2'X(?)CQ.)B +M+M(CP*$U``PKL-T@V2'((<)CP)(B+X+1$U)H.K"9())B+R6L]U%%`$$V`&%& +M`.+1%-+1$](M'-D>!A(`9CH"1O0"O">"(B_RT10,29"((()B+Y@'#`[I3YQ9 +M"ZD62ANRR?X6:R;"R?T6#"%F20*&<@(,'=D'TF))@M$4#`_BT1-R;C?Y2**A +M@"6G]PP)TM$4R#%RT1-R)S>H0:D]R5VBH8"9,9E!Y:/W@M$4B%@6.`:RT132 +M(B_!0``,3N#=(-)B+\(L0\DAF"$,"JE+EID+J"&@H4&V^ARRH0"G.V/,%\9F +M`L@'PLS_S!S&2@(,'=)B20;D_[8J<+8Z`H;/_\P7AA`#Z`=F'@)&N0(,'_)B +M28;<_P``@M$4B#@6N!.8@;+1%`P*J4L;F9F!S!?&50+(!\+,_A:\\`P=TF(N +MAM'_````XJ(!Y[H"ABL`\J(!I[\"!CD`S!?&1P.(!V88`@8Z`PP9DF))!L?_ +MS!K&$P.V*@*&L__,%P;U`J@'9AH"1JD"#!NR8DD&O_\`L30`J"&PJA"@H4', +M&H9V`F8:`H9P`F9*`H:H`L+*^U9LZ<%``+B1PBQ$R2&H(;"JP*"B0<`@`)+1 +M$^(B/;+1$[(K.NDAV"&PJJ#9"G:`&_(CY_)I(>(I(>#@%.)I(=(I(=+-_>`PPO^0<,&()B2<:/_Y*B`I":P%8)X,P7AAP$J`=F +M&@)&W0,,&[)B28:+_P``TM$4V$WBT13-#1O=V4['-@(&AO_B(B]\O_#N$.)B +M+X:"_P``P"``@M$3@B@Z/?#,&`8'`\`@`*+1$PP)TM$3TBTZ#$O")Q_)#;D' +MDFHCH4<`=H`;XB/GDM$3X.4$5LYT\BDC&X^":2/WN@*&SP$]\(;V_P"R(ZJ2 +MT1.B)Q"B:3BR:22H2F8J`@8*`[%(`*(I)+"J$,+1$Z)L)4P*PBPEPF.J)8#W +MHB.LH,`$!VH"QI("DM$3/?!V@!3R(^?R:2?B*2?@X!3B:2?2*20*2T1,]\':`%.(CY^)I*=(I*=#0%-)I*;(I*28[`H;X__%,`(%+`-(B +M(`Q.D4H`X-T@XJ``TF(@P"``LB(@P"``XFF"@+L@XF\6P"``LF(@L4T`P"`` +MTB(@P"``L-T0TF(@P"``TB(@P"``XFF"@-T@XF\6P"``TF(@P"``DB(@@J_[ +MP"``L)D0DF(@P"``\B(@DM$3P"``@/\0\F(@P"``=H`4LB/GLFDJ@BDJ@(`4 +M@FDJ\BDJ)C\#!OG_`(Q\HF.LPB.LPFDH3`HE:??A3@#R(ZRRT1.R*SBB(B#P +MP`3P@`2,&`9'`I*A`)":())B()+1$\`@`((B(()I*\`@`#WP=H`4@B/G@FDL +M@BDL@(`4@FDL@BDL)C@"AOC_@J[_@(H0@F(@P"``@B(@@FDKP"``C'SR8ZRB +M(ZRB:2NA0`#X.Y(J27SLP)D0F2'((8A+#!T,"8+(_H"=@]*@@,"9((+1$_)H +M/`P,DFI)TF.HG0@,#<)CJ:A+=H`4HB/GHFDM@BDM@(`4@FDM\BDM)C\"!OG_ +M\B.LHB(@\,`$\(`$C!C&'@*2T1,,*("J(*)B(,`@`*(B(,`@`':`%((CYX)I +M+X(I+X"`%()I+X(I+R8X`@;Y_WS8@(H0@F(@P"``@B(@@FDPP"``C'SR8ZRB +M(ZRB:2[29WKRT13"H`#";P*2T1.B+N6B:3&(2_%/`"8H,L(I,?#,(,)I,8(K +M-:+1$_$^`(")!!9X)*(J,:)NY9(K-8+1%))G))":%))G>MPYQ@<``/%0`,(I +M,?#,$,)I,8;Q_P``DM$4B"@,'`P*@*R#J2F2)R0':4+R*S#R9R:B*S&B9R>2 +M*S*29RB"*S."9RGR8F3")R?"8F6B)RBB8F:2)RF28F?29R6"*Q8,'\T-@,^# +MPFE:X +M$QN[_``#R*S;!40#P^046OPN2*S:B*S:"*S;`F1#! +M4@"0ED&@F1'`JA#!4P"@H/6@JA'`B!"`BE56&`CRT1.2;SG,FH(G)8J)@F@B=ZDM$4F"D6F`H6&0F2)R3!5`"BH/"':0V@J1#` +MJB"B8G0&!````/%5`,*@\,#)$/#,(,)B=*$^`+*@>0R-XM$4\M$4DM$3^!_R +M:3_PZ@.2H'"28ZC"(ZGY'OD.T,P@PF.ILF.HHF.IDF.HTB.I?'ZA5@#@W1#2 +M8ZGE"?<,#>%.`)(CW;+1$X(G-K(K.)DA!V@JR"%\[_#,$,)CW08+`((G))*@ +M\)"($)%7`)"((()B=$;@_Z(G)*)B=`;>_\@A?*_PS!`,'_#,(,)CW8A+%F@$ +MF$LF&4&H2_%8`"9*.+._N"=@\"9())K5N`(`/+1$Z)O +M/8R:@B(O#(F0B"""8B^2T1.Q0`#BT1/B+CCRH'#"*U;H3GS=?.KBSO[@K8/` +MJA"B:U:`Z@/R8ZCB(ZG16@"BH`%@[B#B8ZG"(ZFRH'2":3O0S!#"8ZFR8ZAE +M$O?X)_+/^E;O$)+1$W:`&;(CY[)I,J(I,J"@%*)I,H(I,F8X`L8C`#WPQO?_ +MT5L`#`H,',)M3<)B2>55`<:7_9CWD.($C!Y&LOWQ0``,2J"I(*GW@B]$@F<4 +M\B]%\F<3AH']``P;T4``#`SRTP3B+43I#](M1=D2PF/_R0>R8DD&A_T`F"&( +M"I<8#':`!L@AN`K'&P*&_/_A6P`,'=)N3=)B28:!_0P?\F))AG_]#!B"8BZ& +M??T``,(CK+(B(#WPP-`$P*`$5@H_DM$3#"[@NR"R8B#`(`"R(B#`(`!V@!2B +M(^>B:32"*32`@!2":33R*30F/P0&^?\``'S?\/L0\F(@P"``XB(@XFDUP"`` +MC'W"8ZR"(ZR":3.RT1.B(ZJB:S:A.`"2*S9R:S>@F2"28ZK`(`"B)Q*R)Q&E +MHP!]"A9:-L+1$\(L-\(L(-%<`,#`=-#,(-$W``P#PFVFV`=G'0H;,Z*@`25` +M`5>3[^%=`#<^`L9%`#$W`'+1$W(G-PP?##B)!_)B+D9%_8QGB`=F2`)&-?T, +M&9)B209$_:AQ&ZJI<8QGN`>RR_T6^T/"T1/"+#KL[*%``(%>`*(J1*DAF"'X +M(9F1@/\0\/-!\F(6V"'B(A;I(>%?`-#0).#=H.+1$])N.L`@`,+1$\(L.I+1 +M$[(B/;D,\B/G\FDBXBDBX.`4XFDBTBDB9CWJD5L`#!B":4V"8DD&)?V8]S=I +M`D9$_:%```R,P,D@R?>R*D2R9Q:B*D6B9Q4&#/T````6QSS8!PO=%ETV#![B +M8DF&%_V8]Q=I`D94_?%```PJH*D@J?>"+T2"9R'R+T7R9R"&_OP`P4``X6`` +MTBQ$V2'"+$78(0P;ZMW";8"R8DG&!_VRT1.BT1.2T1.2*3>B*CVR*SRY%ZDG +MF"DQ-P`6B38+R1;,,0P-V3?H1Q;N">%``(+1$Z+1$[+1%)+1$Y(I/[@+HBH[ +M@B@WD)O`L*K`J5>99_(H>/EWXBY'Z8?2(AW9E\(B',FGLB/RN;>B(_.IQY(C +M\9G7\B/U^>?B(_;I]](C]-)G$,(CZ\)G$;(C[+)G$J(CI*)G$Y(CHY)G%/(B +M5/)G%?*@`.(B5>)G%M(B5M)G%\(B5\)G&+(CZK)G&:(CHJ)G&I(C]Y)G&_)H +M><`@`'+1$W(G-PP:##NY!Z)B+H;,_`P8@F))QLW\#!F28DG&R_S2T1-\[N#J +M$.)CK,`@`+(CK+)M)L`@`$9F_0""T1-\Z9":$))CK,`@`/(CK/)H*,`@`(9_ +M_0``DM$3?.B`CQ""8ZS`(`""(ZR":2O`(``&LOU\Z("/$()CK,`@`((CK()I +M+L`@``;;_<%``-+1$_`@`.(L1.DAPBQ%PFT=P"``J"&RT1.R*QVBV@'E=@!Q +M80`,`_+1%*EO@M$4B&B("'>8"1LS#!IE%`%7D^NB(0*RT1.R*QTE=``RH`#" +MT12B;`?2T138?=@-=QT+,L,!HJ`!I1$!5Y/IX5T`-SX"QC@`,3<`DM$3DBDW +M#!\,.(D)\F))QH[\F/=G:0*&P_RA0`!,#,#)(,GWLBI$LF<:HBI%HF<9QG7\ +MV$PF+0*&[/RBH/N&Z_P,'N)B20:!_'+1$W(G-PP?##B)!_)B+D9Y_'SJH*P0 +MHF.LP"``@B.L@FDSP"``QOW^LB<>N9&B)QZQ8@"@HT&PJA"B8A:R)Q[!7P`, +M`["P),"[H,+1$[)L.G:`#M(B%MDAR"&G'`D;,T<3!(;Z_P``X6,`_0,Q-P#W +M/@)&Y?PQ-P`,&`Q)HM$3"8DE&7OP`L60`HBDDL*H0QO3\B*$2B +M9QB"*$6"9Q>&+_P`F/>0Q`16',G10``<#_#Y(/GWXBU$XF<2TBU%TF<1!B?\ +M@M$3@B@W@BA+DJ*`FHB"""Z"R/X6R#(,&9DW!C+_`+%``,(K1,)G'K(K1;)G +M':(B/:)G'T89_`P=TF))!BC\#![B8DD&)OSRT1/R+S?R+TN"IH"*__(/80P8 +M\/B3^3<&(?\`R\&BT1.2(ZH,J))J(`P)=J@*N(S2H>R,JQN9VLP,'N)B2<85 +M_/+1%/A_B"^)C/A/\FP5)IGF#`T,/K+1%+A[Z7S2;!;X6_#P!/)L/>A1H64` +MX.F"JN[B;%*(4>%``("(H*"(D*+,'()L4_A1TFPH\FP2TFY)N$O2T1.B;3?V +M.P(&*0"V2Q?Q9@#W.VN!9@"WN`N16`"7&P(&)0`&%P`,#/%(`.+1$^(N(++1 +M%+A[\.X0#&_B8ZK":E8,3NE:\FHW^2J8>Y)J/HB+@FH_^'O[__#T0?)J1.B+ +MTJ"$VMK[[N#D0>)J1\)-I,)-I<)-B+)J$*5:(\84``!F2S0,2`R)P4@`LM$3 +MLBL@\M$4^'_`NQ"R8ZJ9*HDZB'^)FO(O"/)J"J6+&,8(``",2[8K-B8K;/%( +M`.+1$^(N(-*@`/#N$.)CJM)L"64$`3$W`)$X`(+1$X(H(`P?D(@@@F.J\F)) +MAL;[``"RH0`,#I%(`((M(/+1%`Q-^'^0B!""8ZJ8KY)L$PP9B'^";!#XC_)L +M$>)L*>FLV%D`-(M(++1%+A[X-T0TF.JLFP7F9PEKB+& +MX_\`F/=W:0)&(/SA0`""H("`B2")]_(N1/)G'.(N1>)G&\:6^PP+RY&BH`IV +MJA72T138?SJF=#,P!;,"QN[\M$4^'_X3_+/_E;/#0P+RY$,J':H +M"JB)C*H;N\*A[,J91@,```#2T138?=@MV8EFFQ#RT1,,#@P8@F))XF\W!H_[ +M``QI#`P,/X*A[("+@LMQBG?Y=\)G%NA1HM$3\64`X.N"@M$4^N[B9U+84<)G +M*-)G$K(CJK)J'K%D`*(J'GF(B'BPJA"B8ZJ9EX)G%W+''*T'9:`BDM$3HB.J +MHFD?H6<`DBD?LM$4N(N@F2"28ZK&!0`,',)B2<9P^]++]A;M\\*A[,#+@LNQ +MRKN8>ZR9)DDG)CDDTM$3#![B8DER;3?&9OL,#_DWQF;^DM$3#`@,&J)B28)I +M-P9A^W++'`P>PM$4#`W9>\A\XFL6PFL7R)S":RI&2?O2R_86?_8,$Z$W`)%I`,`@ +M`+(JQ;D!B`&7>`22:L8Y`L@!\3\`P,X%%LP1LJ$`X4``(BJJ*1'B+DD,`LT" +MX.`$X,.3"]P671*12`"($9"($()JJF%H`%%)`.$Y`$%+`(8,```I(0RI=JD# +M/?`]\(@A`UV@`72*<5'?03&_/\``,`@`**@@*5=]AWP`#9!`**A`&5> +M]J$W`+%!`,`@`+)JQH(JQ3WP%W@+=H`%DBK%%WD"QOS_#!S)$K)JQL`@`**A +M`.59]AWP`#9!``P&<38`L6L`P6P`(*PU43<`,$!TD6(`,3D`((-!D(@0@F,4 +MDB7E@*H!P$0@L)D0H)D@DF7E0F6F/?!V@`JB(Q2G&`D;9G<6!`;[_P``L6,` +M9SL*034`("`D0"*@'?`,`AWP````-H$`P3<`LJ"8@B)ZH6T`DB(4%B@ULFRH +MXBRILFRHH.X0XFRILFRHTBRIV0&Q;P"A;@""+.I10``,#J"($(D1^!'R;.KB +M94?2+.;9(:@A@7``L*H@J2'X(=%Q`(#_$/DAZ"'@W2#9(;@ALFSFX7(`T3D` +M#!O`(`"A`+"P=/"[(+)LIJ(LY:DQ^#&R(AZ`_Q#Y,?@Q +MX+L0\+L@N3&H,:)LY8(B':%[`("`=*"((()LIO(C'Q9?'H(C(/(B%HK_\FU/ +MLB,AHB(6NJJB;5J2(R*"(A::B()M6_(C([(B%OJ[LFUA1)CX"!OK_?-_P^1#R;2#`(`#B+2#I8<`@ +M`)S[HFRL@BRL'?"2+-R@F1#PF]`ZT"X`@`'?"R;*CB+*GQ +M1@"R;*B@[A#P[B#B;*FR;*C2+*G9`<8H_Z(C()(B%JJ9DFU/@B,B\B(6BO_R +M;5L&B_^!3@"A4`"R*.6Y,9@QH)D0F3&X,;)HY8:*_P"!@P"";4[&CO^1A`"2 +M;4Z&C/\``*&%`*)M3L:)_P```#9A`*T"(3<`X4``@6X`\B+J#`G"*DN`_Q#Y +M`=@!\6\`TF+JDFY'@B+FB1'8$9%P`/#=(-D1B!'1A@"0B!")$?@1\-T@V1&8 +M$9)BYKT#\J"8D4P`P"``@7,`V!&`W1#9$8@1@F+FB`$,'="((-%M`()BZO)B +MJ((BJ?)BJ-"($()BJ?)BJ-(BJ8(C'Q;H$_(C(-(J%OK=TFD8@B,A\BH6BO_R +M:1G2(R*"*A;:B()I&O(C(](J%OK=TFD;D7X`4J02\BL>,BL?TBL=,/\14/\@ +M@#,1X-T1,-T@\-T@TF+P@BLD)"D>)B*N)B+^)B,>)B,N)B,^)B +M-.)B->)B-N)B-T("6+#%$?#3(+CBLD*0TF(FTF(KP,,@T8X`0$010$,@X@)9 +MT,P@PF(G,.X10.X@\.X@XF(LXF(M'?`,%0P3AN/_QN+_-H$`,,"TMBP.]DP% +MMBP"1G<`0LS\%G0=#!5A20!Q:`#'8U#Q.0#H(N)O@M@RTF9"4F9$4F9%N%*R +M9IJH0J)F@IB"DF;"B)*))TBB0F=".+(R;X#HPN)OP-C2TF9`N.*R9H"B(@^B +M9L"2(A"29P""(A&"9T!!D0#R(A(,"PP#\/2#=I\GTB=#B#>2)L.B)H-2)D,; +MN]"((*!5()!5((!5((S%#`OB(A0;,R8N"$8!```,K[>_[H$W`#WP=H`:0BCG +M0$`4)C0*DB(4#`LF*0W&^O\;NPRJMSH#!O?_`)(HK)"@!`=I$GSMT-D0TFBL +MP"``LBBLN0'`(`#1D@`X,M`S(#)F0OBBT/\@\F="Z(+0[B#B9L*XDE%R`$&3 +M`-"[(+)G`O(B!,!%@S&4`$#_(/)F@C)FFN(FFC<>"W:`!4(FFC<4`L;\_\(F +M0K(FPE@G0B=",B:".0$QCP#`(`#X,O)F0NA"XF:"V(+29L+(DLDGLB(*LF=" +M,F::4B::-Q4+=H`%TB::-QT"QOS_P"``/?!V@#KH0M(F@MD1PB9"R2&R)T*Y +M,5(FPEE!2"=)4?@1]Y[@^"'H,O>>V5@Q2*)7E-+(0;B"QYO+Z%'8DN<=`P;O +M_P"<2I)HK,`@`$(HK$D!P"``?/_R9H$=\`!\^()F@1WP``PT`H;[_QWP`#9!`$*A]':D!%@"-Q7_'?`V00`L`W:C +M'8)R!()R1()RA()RQ(+2`2+2`H)X!()X1()XA()XQ!WP-F$`,.H#,F$`=H`. +MD.H#F1&(`4@1@$3`)[0"AOK_'?`V00#!FP#1F@#QCP!!F0!1F``,9N$\``PH +ML4D`D3D`#`-,>J)I@C)I@*%3`#)I@3)I@S)IA#)IP)&<`#DK.0LY&SE+.5N) +M:^)K0H&=`#)K0#)K03)K1#)K13)K2")K3C)K42)K4C)K4S)K5#)K5S)K6#)K +M66)K6V&>`#)K7#)K73)K7U)K@C)K@%&?`#)K@3)KA#)KAC)KBS)KC#)KCC)K +MD3)KDD)KE$%H`#)KEC)KF#)KF?)KFC)KGC)KHO)KIC)KJ.)KPM)KP#)KP3)K +MQ")KQ3)KQC)KQS)KR#)KRC)KR\)KS3)KSC)KTCDD.00Y%#ED.82IE#FD.;0Y +MU#GD,F00,F01,F02,F03,F04,F05,F06,F07,F08,F09,F0:,F0;,F0<,F0= +M,F0>,F0?,F0@,F0A,F0B,F0C,F0D,F0E,F0F,F0G,F0H,F0I,F0J,F0K,F0L +M,F0M,F0N,F0O,F0P,F0Q,F0R,F0S,F0TDF0U,F0V,F0W,F0X,F0Y,F0Z,F0[ +M,F0\,F0],F0^@F0_8F1",F1`,F1!,F1#(F1$,F1%,F1&(F1',F1(,F1),F1* +M,F1-,F1.4F10,F11,F12,F13,F14,F15,F16,F17,F18,F19'?`V00`AH``= +M\#9A`+T!#`P,#8(B2Z&A`()A`"6W"3T*L:$`Y>,F#(L,!9&B`"DCPM,&HB(A +MHFPGV`'2;"BHLD+3#IJ3VJJB;"F29%Y220:B)%[EX":AHP`L2ZJCHF12)>`F +MK0,EZ`3BH/^2TVJQC0#!C@"!I`#RTV`,&HJ#HD@S4D@0H:4`TB(ATF\?PF); +MLF)?4FGUXFGVXFGWD:8`TB1>PB12#"M270*R3".B8G:28G<,`AWP````-F$` +M,B)+0J%<#`B)`4I"0*0@Y<3_K02RH`!EF_^1-P"A.0#!:`#A20!\^_*C\/)N +MF-(NF+)N@;)NP;D(F&,(CK**O_G(B2\#0!`=L$:#\$/)CK,`@`((CK()A +M`<`@`$%)`(%I`/(D@H"/(()D@H(D@O)D@H(D@HD1%NT`PF.LP"``TB.LTF$! +MP"``P:@`X/P%TB=I4J8H4%>`\-T@TF=IPF8\@B=I@F8\\@6Y)F\"DD6Y@:D` +MHJ/P?/X,#-&K`)&J`+(%N;FAFI?R*7_:UYF!&__R:7_Q/P#"1;C"1<'"1<+" +M;83B;8.R))BY`:)DF)(DF(D!Z`'9D<&G`/#N(.)DFM(DFK(A`)&.`,"[$+)D +MFJ(DFI)D@H(D@L`@`&6P_Z*A7*JBHF$+I:7_F(%V@`G"(T[)(;@A=VL$1OO_ +M``#2*8`6[1.M!V6/`+*@&*!Z(,(A"<`@`.+*Z!:N$_(B>:(L?*)B>(CE#'FH +ML9"(8X#_(/)B>66C_WSRJ+$,"^5Y_\%H`")D@2)DP2D<(FQ!(F1!(F:!HB.L +MDB8@H+`$!VH2?.[@ZA#B8ZS`(`#2(ZS90<`@``PNX/D@\F8@P"``DB8@P"`` +M=H`0\B/G^5'84=#0%-E1B%$F.`,&^O\`?-W0V1#29B#`(`"")B")8<`@`(Q+ +MHF.L\B.L#/.2!<(,N`RFDLG^D':#AQ=Q''JG%VRRQ^H62PG2Q_8630DF%UV" +MQ_@,CRT#@"^#)I(XD:P`=H`@"YGR)(/8/+(L0Z(D0_#=(-"[(+"J((S:%GD& +M@@7")B@(!O;_````%HD%D@7"DLG^D":#)H(9)I)%-Q(*'!JG$DJRH!2W$@@, +M`AWP'$)&ZO\,$AWPR)'"+'L]\!9LZZT'I:D!AJO_``P)L-K`#![B;(16?>N9 +MP88%`!P2QM[_``PB'?#B1<+E<@E&Y_\,,AWP7&BH`"QK0`E,_4,!PP:Y4[U +MF*&HAL:'_P```#:!`+ASHB,&('(@/?"PJH*QK@!B(DN@JA&Z +MJN4K];&M`**@`&#&("4L]:*@`>5']=+3#.&J`(&O`*(C%NKFBH:B:'22(A22 +M:'7R(A/R:';2#>")8>E1T,`$T-`$TFZ`5@P((30`O0.-`PR)P;(`^%'B(ZVA +ML0#2HCC:TZJFXF^!X;``RL;RH(#JYG:I59(HC))J?Y(HC9)J@)(K>H+($*+* +M$""9$))L?Y(-@(N[B\SPF1"23GB2#8"23HB2*(J2:GV2*(N2:GZ2*WDKW2ON +M()D0DFQ^D@U_\)D0DDYWD@U_DDZ'N&&(4:(CK*)K@I(G(9)H?8(H@%+6#9*@ +M9!:(6H(C.!:H6PO(%NQ=TLC^%OU<@B4E#![RKX#R2#WB9FF2H^CRH/O(88(E +M);B3LFQQH@/SJ8CB`_;B2#RB)26RH/W2`_2""CC9FL(#](C +M.L(E)0PH@.X0H@PYX.$$X.X1\*H0X*H@HDPYPB4EFI/R*3+R;'[B*3.B&6CB +M;'_V*A/RH(2@_X+Z_/+?`J)?`.(9:>)?`?*C\`P((B4E0AEJPM8*TBSEHAEZ +MXAF*HF)SHAF:0F)R0BURXF)THF)UG,0,"OJ3=H`3&XBJXD(99T)N=N(M>X +M`T;Y_P#"+.62+'4,"*PI^I,,"M(E)7:`$QN(JDWR&9?R9'SB+'5+JBN9Y[@% +M1OG_````#`(\"N(E)@P,D@/\R4'"H-^9SH(#_HG^0@/_0FX0\@/XT@Y,@J#O +M`/\C^0[R(SNPW1!"H0!`_Q#P^`3P_Q'PW2#23DSR)2:2(SM,#>(/3*"9$)"4 +M09)O$4(C.X#N$(*@@(!$$$!'!,!$$4#N(`R$XD],DB4FHB,[\J#$@@E,T*H0 +MH*8$L*H1P(@0H(@@@DE,XB,[TB4F^O-`[A#"#4P,1.#C!)#N$<#`9.#,(,)- +M3)(E)J(C.\*@_H()34"J$*"B!,"($*"((())39(E)J(C.PPL@@E-P*H0H*$$ +M\*H1L(@0LJ"TH(@@@DE-.J*=`@R(NJKRSQ`BPA!VJ!NR"E"")28KJAO)FHBR +M2&"R)2:""D\KF)B +M0MACR'.R(SK0T/3`I+30U$'24MK`P/1`NQ"PLD'`Q$'"4MRPL&"RRP)E92:2 +MH/ZR$MS2)26"$MJB4MNBH0`+Z,#($<#[$?)2X<)2X/#P]+"(@H)2W[(2X(AA +M\/^0\/$A\FAYHFAWLFAXXET6PA+;LB6>HB,<"\S"71>B6P*B`_"B8DJR(SJ" +MIE:*AK"P!+)(B28:"[+*_A;+(,+*_1:\'M(2X>(2X-#10>#A0>)2XM)2X_(E +M)O(/3`P>#`WP\03PWH/22(C"(SO`P`3"2(:R`_H`NR.R8D6B`_L\/0"J(Z)B +M1O(CBO)B-.(CB^)B-;(C.<(E):A1T+M#LDP^HBJ`+`^\:K*@OZ(C.N(E)4P, +MP*H0T@XYH*8$H*H1L-T0H-T@TDXYLB4EPB,ZH@LY\,P0P,4$D*H0P*H@HDLY +M#`S2)WHQ20"BH5P6O0BJ)Z(E)>(*/>+.OA9^%[(*/ASDM[0,T@B)C&WH8>(N +MCA9^%@P=H;4`L;0`08T`^"9R)9[0X'2@[A'22):"!P=R!P8,'3"($4!W$8!W +M((+3!'#N($#N(`SG06@`XF]AXF]@XF]:\;8`TF18PF13P;,`PF1(LF.`HF/` +M#`NM`ID()<58]]D(G2PP:#`[B +M80#EZO2A5@"ER_0@HB"!MP""8X+R(X+R80!E(?^!-P"B*$ZI$9@1=^GUP"`` +M#`K!N`""H"!VJ!H`/*:`$*:)`8@!F`&@L$0`&T"0B(&)`8@!JJBI(:T')5K_ +MS00,"K&M`"7']`P:)>/TB''AN0#8(9*@_L*@`.<=#D&Z`$<="+&[`+"MP%8Z +M[>AA#!W2;HY&LO\``/(E)9)//0:;_J(8-K(8-;)8-Z)8.(:%_](E)4PLPDT] +MAI3^`.(8-?(8-O)8..#A0>)8-P9^_P``@B4EDD@]!HW^HB4E3-F22CU&BOX, +M#4:F_PPM!J7_```V80!\_U&\``P*,J4X0M(&D@3A.C*B8T9:4O)E(XS)@LG] +M%@@2)FD$'"(=\``,-L&]`)&^`+&_`'%)``P=NK+B*[OI$>(GA@P:#`B0[A#@ +MYI7@BH,6J`D,AH(E'B8(&*(C()(3OANJIQD"!B``@B,?XA/!&XB'GG62(T86 +MZ0[*HJ(J?])$X/)D%Q:Z"J(K1+T"Y68`HD3ADB4C()F@DMD&N#F,^PP*HFD5 +MLB)C&[NR8F,M!AWPLB)C&[NR8F,M!AWPXBM$X@XXX.4$%FX3@B4>&X@6B!RB +M(R"2$[X;JJ>9#8(C'^(3P1N(@.[`%OX:'((=\+D!K0*E,02X`<&]``P=?/\+ +MFA9)%>($ZMRN)BH8J!&B"@#AP``<6(6:BT&'?"")2.#"YFH.((H0V(G0^"J(*"(((!F(!9V +M"Q9Y"Z($ZF8JVN($ZA8.#`PV8D3A#*8,"()$XQR)EQ:4H@3I/?`6"@CB!.I6 +M?O2A1@#BH`#B1.F2)X&"H`B@F1"0FT&0:)."QOX6R.NB!.&2ROL6N>0+ZA9N +MY)&^`(+*_5:(XH:._P``TD3@##8&C/^M`N4D!+@!P;T`#!U\_PP)DF4C!N7_ +MX@3+HJ`@YSHB(*(@)0L`H&H@N`'!O0`,'7S_AMW_'';&??^"!.I6B/?&Y/\, +MX,HAWP +M````5HKZ#"S"2^JEM@@,+\;F_X(+ZE:H]88(``P8@DO@@@O2XDOIXDOJ%J@4 +MXM(!X@Z=%AX4XBV*XL[^XFU_@@O2JJ(6N!0,/C(JCH(*?>)+ZXES@BV>@F,# +M@@O3@D,A,@O3%H,`@BJ.X@O4XD@BXBJ.@BV7B4Z""]:"3B#B"]:,?H(JCN(M +MF.)H!N(J(>B>K)YF'DGB)((Y88*D-#(JCB#NL(KNXBYLZ1/B)((@[K"*[N(N +M;>DC!@D`````.6'B)(*"I#0R*HX@[J"*[N(NC.E3XB2"(.Z@BN[B+FKI`V8G +M%.(M8((M8:'$`(#N$>"((*"((()I3(@B@B@V!^ACH:P`"ZJ"+(,H.>(I0](L +M0X`B("#N(.#=(!9]!A9Z!M(+ZJ+*_V8MW)(EYYDQB#&`@!2),>@Q9C[NTB7= +MV4'(07S:#`OPS"#"9=V&``"W-@OR)=WY0>A!&[LW;O"(0:"($()EW;(EY[E1 +MJ%&@H!2I49A19CGN+0<=\.(MB@ONQJ[_````5@KZ#"_R2^JEG@@,+\;D_^(J +MF.#@=`:K_P```#9!``P+D<4`%H0`)A0I)B0Z)C1'P*,1JJ*:JI(*?^8I`M89 +M`28I828Y"R9)/V99!<(*@!;[`K"K +M(*><`QWP``#2`BLJW3)-"*)"*QWP````-D$`#!."`BM"`BH,`H!$P$`C@QWP +M````-H$`8M-MXB8R#`J2I?PP[J":[JE.V/*R)C(,'-+-_CJ[FKO0K(.B2]Z" +M`CF:DYDQ!V@(,*,@L@G/)>G_R#'"#.1F'`OB(0/2H`#23N1EJ?ZR`CA1R`!! +MR0"P\006#S*"TQ2"*"^RTPT62#B2*R62"3F0E@06B3?2)C*RH-2PW8+"H`#0 +MTX#2W0[";1RB)C*PJH*QR@"JH[JJY8@!HB8RLJ#4L*J"L#=)N*,(".#=L&9(F,@P8H)F"#`^:DY+9#?)I*8)" +M-?EB!@4`TB8R#`N@W8)\_-K3TMT-PFTILD(UF/(+Z18^*O+)_A;?*0Q8B2&R +M)C*B)C4PNZ"RVVVB:S:R`CBPD016J0C"`CD'[`)&(`!':P+&'@#2)C+BH-3@ +MW8+:T]+=#?(-J^(-K-(-JO#NP.>=60P-O`9R(TJ#4T)F"FI-*F9()*1N[ESL"!MC_/?#&[__-"^T/AO?_ +MLB8RPJ#4P+N"L+.`HML-H@JI,,,@L*J@O0*BV@VB*BPE=@'8\A8]#J(F,K*@ +MU+"J@JJC@MH-@@BIDMH.H(B@@M@-@B@L@FD<\B8R#!XZ__+?;>)/X-(F,K*@ +MU+#=@MK3TMT-P@VI&\S"3:FB)C)!R@"PJH*JHTJJ)5X!HB8RLJ#4L*J"JJ-* +MJB5F`<(F,M*@U-#,@LK#PMP-X@RKT@RJP@RLZMW7K&#X,2@A#`[B3^T=\`"" +M`CF`@`06^-:PE`06F=:M`KT#)0<"QE?_````K0,EW0%&JO^B)C(ZNK+;;;(+ +MX)R[LJ#4L*J"JJ.BV@ZB*AP6N@#"R?\6O!72R?X6'18,;NDA!DW_*"$=\((F +M,I*@U)"(@@P/BH."V`[R:!R&S/\`K0.Y`2E1Y4$!\B8RLJ#4L/^"#`[Z\_+? +M#N)O'-(F,K#=@MK3TMT-XDVJPB8RL,R""*I^":7B"*I^":7F"*I^":7J" +M*I^":7N"*I^":7R"*I^":7V"*I^":7ZH$>)G?]*@C-J[VO]+=Z>7L(;8_B"B +M(#"S("4X`J`J(!WP``#B"A/BSOY6KND&!@#R)C*"H-2`_X+Z\_+?#O(O'/(/ +M$PO_5D_HD@(Y!^D"1B$`HB8RLJ#4L*J"JJ.BV@ZB*ARB"A862N:B)C+-`[*@ +MU+"J@KT"JJ.BV@ZB*APE30&B)C*RH-2PJH*QR@"JH[JJ93D!HB8RLJ#4L*J" +ML2`CA1R`!!R0"0\006 +M#S:"TQ2"*"^RTPT6*#F2*R62"3D,#I"6!!9)./(F,J*@U*#_@OKS\M\.XF\< +MTB8RH-V"P34`VM/2W0W";2BR`C@W:QNR)C(,&:"[@@P(NK.RVPV":RF20C6) +M8@8%````TB8RH-V"#`S:T]+=#7)M*<)"-9CR)AD6)BD3XB8R#%_Y03#NH.+> +M;7)N-D8/``"B)C(ZBH+8;8((X)RXLJ#4L*J"JJ.BV@ZB*AP6N@#"R?\6_$O2 +MR?X6G4/B)C7R)C(,:(E!,/^@\M]MXF\VD@(XX@(YD*$$5FH2X+`$%@L2D,0$ +M5JP1TB8R\J#4\-V"VM/2W0V"#:OR#:C2#:IRTVJ`_\#PWH`@:N`)A1D@GM%JD4LB8RPJ#4P+N"NK.RVPVB"ZD+JJ)+ +MJ=(G\N*@U.#=@MK32MWR#2G2#2CB`CGWG6<'[L7R)_*"H-2`_X+Z\TK_\@\I +MLJ``%H\F#`KA-`#"K_]V@#?2)C+RH-3PW8+:T]K:6MW2+6^2)_+X+4NJ@@T2 +MYZ\!G)C2H-30F8*:DTJ9D@DI&[N7.P)&V/\]\$;P_P#-"^T/1O?_`.#P!!9? +M"[(F,L*@U,"[@K"S@*+;#:(*J3##(+"JH""R(*+:#:(J+.40`=CR%DT=HB8R +MLJ#4L*J"JJ."V@V""*F2V@Z@B*""V`V"*"R":1SR)C(,'CK_\M]MXD_@\B8R +MTJ#4T/^"^O/RWPWB#ZD;[N)/J<(F,M#,@LK#PMP-X@RKT@RJP@RLZMW7K#Z( +M40P"(DCM*$$=\```H@(YH*`$%FK0D+0$%@O0K0*]`^6C`88]_P```*T#Y7D! +MAK#_(*(@,+,@Y>L!H"H@'?`H01WP#`S"0C4&F/^M`[EQ(F$(I>$`@B8R\J#4 +M\(B"#`Z*@X+8#N)H''(F,O!W@GISJ(B8R\"*"X<0P/ +MP((KGX)I>8(KGX)I>H(KGX)I>X(KGX)I?((KGX)I?8(KGX)I?H@!V!&2H(R: +M_YK,XFU_2]W9$8>=JP;3_K(F,L*@U,"[@@P*NK.RVPZB:QQ&D/\@HB`PLR#E +MU0&@*B`=\-(F,N*@U.#=@M#3@-+=#M(M'-(-$]+-_U:MNO(".0=O:H(F,I*@ +MU)"(@H"#@(+8#H(H'(((%A;(N*(F,LT#LJ#4L*J"O0*JHZ+:#J(J'.7K`/(F +M,B*@U"#_@@P,^O/RWP[";QSB)C(P[J#BWFUR;C;2)C(,4CK=TMUMPDW@'?`` +M@@H3@LC^5FBSAN/_DB8RHJ#4H)F"FI.2V0Z2*1R2"196*;*&Y/\``#:A`,'. +M`)*@U.'/`#+2:O(C\NKBZ2&0_X+B+G_Z\LK_XD^!TB/RD-V"#`7:TLK=4DU_ +MLB/RD+N"NK+*NU)+@((C\D')`)"(@HJ"2HB"""D,)EDQ%O@-#`?2(_*RH-2P +MW8+:TMK7TMT-4FT\PB/RL,R"RL+*Q\+<#EG,HB/RL*J"JJ*JIZ+:#:(J+&4: +M`:(C\K*@U+"J@JJBJJ>BV@VB*BR2"A,':17H>M(..?*@_O#=$-)..(C\DMW\J#4 +M\.Z"V#'JXDKNX@XI&]W9,>>]`L;6_X8-``"8>H().<*@_L"($()).?AZ4D\U +M^(KB#SG`[A#B3SG8BE)--;AJD@LYP)D0DDLYB&I22#5&Z/\,!\&R`.&Q`!P) +MF5'JXLK"R6$&!0```!MW^%&(88ON"_]+B(EA^5$6SR"AL``JMZJ[D@N(TJ#_ +MUQG<\B/R@J#4@/^"^O)*__(/*0P,%G_\#`JY`7:`I+(C\M*@U-"[@KJRNKJR +MVPVR*RR2"Q/8>P=I);(N?_@-MQ\8C%L,"P8&````@BZ`5BC_N&&8?;(K?[>9 +MZ`P;1@``#`O2(_+RH-3PW8+:TMK:TMT-TBTL\@T3%V\>^(W2+H"(#]<8$=P= +MDBY_S,F(8=(O!X(H?X>=`F"[(-(C\O*@U/#=@MK2VOKRWPWR+RR2#Q,;S$J- +MMQD/@@@I2ZJ'/`)&Q_\]\`;5_P=K:-A_P@TY@J#^@,P0#!B`S"#"33G2(_*2 +MH-20W8+:TMK:TMT-TBTLP@T4F`&`S"#"3122"7B\&8(C\M*@U-"(@HJ"BHJ" +MV`V"*"SR"!4,&9#_(/)(%<(C\M#,@LK"RLK"W`W"+"S(?)),-1=K=8(C\K*@ +MU+"(@HJ"BHJ"V`V"*"R(B/((.9*@_I#_$`P9D/\@\D@YTB/RL-V"VM+:VM+= +M#=(M+,(-%)@!8,P@PDT4D@EXK.GR(_*P_X+Z\OKZ\M\-\B\LT@\58-T@TD\5 +MPB/RL,R"RL+*RL+<#<(L+,B,#!F23#62(_+2H-30F8*:DIJ:DMD-DBDL@@D4 +M@LC]5GCAB&GR"#FRH/ZP_Q`,&[#_(/)(.<(C\M#,@LK"RLK"W`W"+"SXC+A\ +M\@\UL@LUR&SPNQ"R3#7&=__B(_+RH-3P[H+QR@#JXOKNT@X)#`P6_4P,!ZT. +MZ4%V@#"X2AO,D@L32ZKX:R8Y)P=I#/A[@@\Y!V@$@@\UK"@7:0R8B_().8() +M-0=O`9PHU[PA!O+_``""#SD':-&"#S56N/R801MWLFD4T@X)2YF908;V_Z(. +M"')."J>W%>"GH':`#%)J%+(."!MW2ZJWMP(&^__B(_+RH-3P[H+QR@#JXOKN +MT@X)#`P6'40,#ZT.XF$(=H`PN$H;S)(+$TNJ>&LF.2<':31X>X('.0=H+((' +M-3WPK$B8@1O_LFDDT@X)2YF9@=>\*`;R_P``@@RVPVR*RR2"Q.H$0=I%OA[X@\Y@J#^@.X0XD\Y +MTBL'4DTUD@L3%VD5V(O"#3GBH/[@S!#"33F8BU))-9(+$R8Y)U)+%%)+%?(C +M\H*@U(#_@DMW^O)*__(/*1NJJ1'WN@*&UO^AS@#�#8>\(-.>*@_N#,$,)- +M.9A[4DDUF(N""3G@B!""23GXBU)/-=AKP@TYX,P0PDTYF&M2235&Z/\``.(C +M\O*@U/#N@M@AZN*J[O(.@.(.?](M?_KNX-W`V7$671-QT``,"(F1!BP`D34` +MD)W`%LD)P*^@>JJB*G^R"A/@GQ$':RVX>H(+.0P=PJ#^P(@0T(@@@DLYPB/R +MX,R"P,*`P,^@<,R`PBQ_L@P4T+L@LDP4HB/RPJ#4P*J"JJ*JJ7JJHBI_T@H3 +M%VTK^(KB#SF"H/Z`[A`,&(#N(.)/.=(C\L#=@MK2VMEPW8#2+7^R#11@NR"R +M312B(_*RH-2PJH*JHJ"9@'"9@)(I?Z()%"8Z;M`9RXPB/RXJ#4X,R"RL)*G)()*1N[ESL"QKW_/?`&\/_=#OT+ +MQO;_Z&G2#CGRH/[PW1`,'_#=(-)..<;>_P``TB/RXJ#4X-V"X'N" +M!SD':"B"!S4]\*P(&_^R8B1+(M(."=>\*`;S_P``@@#+@\)-WH(D\I*@U)"(@G'*`(J#@M@-P@BKD@BL +M@@BJ4?27*E_'!S@(('[;*@U*SH +MHB3RL*J"JJ.BV@V2"JD+F9)*J<(D\M*@U-#,@LK#6LS2#"G"#"C7',YQR@`& +M`P``K0,0$2#EN0#&]?\`LB3RXJ#4X+N"NK.BVPW""JFPS*#"W`W"+"PI;*(* +MJ;"JH*+:#:(J+'SYDDH1@B3RX(B"BH/RV`WR#ZF`_Z#RWPWR+RR(;_(/$?)( +M--(D\N#=@MK3PMT-P@RIT,R@PMP-PBPL##_R3!.R)/+@NX*ZLZ+;#:(*J;"J +MH*+:#:(J+/)*%)(D\N"9@IJ3@MD-@@BID(B@@M@-@B@L\D@6TB3RX-V"VM.B +MW0VB"JD,'+T#T*J@HMH-HBHL$!$@94\`DB3R@J#4@)F"FI/RV0WR#ZF0_Z#R +MWPWR+RSH0ND_TB3R@-V"VM/"W0W"#*G0S*#"W`W"+"RR`C:R3!*B)/*`JH*J +MHZ+:#9(*J1N9DDJI\B3R@/^"^O-Z_^(/"0P+%@X1#`VM#UT/=H`P*$H;NY(" +M$TNJR&(F.2<':0S([70;R +M_P``@@PY!VC1@@PU5KC\&]TB911+5>(/"8;W_SWPAE3_`((,-:Q(!VD,R'>" +M##D':`2"##6<2!=I#)B'P@DY@@DU!VP!C$CGNUX&:/\;W7)B%$LBX@\)!OO_ +M``"2#PC23PJ7O17PK:!V@`QB:A2R#P@;W4NJM[T"!OO_PB3RTJ#4T,R"RL/" +MW`WB#*O2#*K"#*SJW=\J7\^O/B3^T=\"@!< +M`((#[1;(!)(G?_*@U+*@U+"I@M$U`*JB2JJB*B(@R:!:S!9:`,(L!!;,!.(G +M?_#N@NKB2N[2;AX=\`":'?`V00""`@D,!Q;H!PP*(%(@(+(@=H`P:$4;=T(&$TM5F&8F-"<' +M9`R8=C().<()-0=C`:PL%V0,2(;2!#GB!#4';0&<+H>W'0;R_P``\@DY,@DU +M!V_.5K/\&ZIB:Q1+NX(""8;W_T(""*)""D>Z&6T*(%J@#`=V@`QR912"`@@; +M9DM5A[8"!OO_'?`,"D;U_P`V00""`@D,!Q9H"`P)(%(@(*(@=H`L:$4;=T(& +M$TM5N&8F-",'9#"X=C(+.<(+-3WP!V,CK`P;F6)J)$NJ@@()A[ACZ1*" +MR?T6&`JX`[DBJ$.I,I(#-I)"$AWPDJ`#,F(&HD,TDD(3P@,Y!VP.DD(6DD(4 +MT@,U%BT`DD(5O02M`@P,90D`F(*(/DRX@,VXD(2'?```#ERHD,T +MD@(3T@(6L)D@D)!TDD(3P@,YL-T@!VP@P@(4\@(5TD(6L,P@PD(4H@,UD@(3 +ML/\@C%KR0A7H8^D2)CDFJ`.I(IA#F3*"`S:"0A(=\``@HB!`M"`E'0#"(P3) +M,K(#-K)"$AWP0+0@(*(@I1L`XB,$Z3+2`S;20A(=\#9!`.(B!E*F4%!3@+(> +M$L(>$](>%.(>%18$%8(%@/*@6(#_@H'2``P:^O.*_Z4``JERL@6`0=0`7(^P +MOX*!TP"ZLTJ[H@M4#$=BH/M@JA!PJB"B2U3H8@PJD@6`LAX2PAX3D/^"TAX4 +M^O/B'A6*_Z7\`:F"X@6`7(W@W8+:TTK=P@VL8,P0<,P@PDVLJ(*(8KARZ`CI +M(L@HV#CB"#28&)D+R0K9._@X^3KB2S32"#322C3)*LDKF1J9&Y(*.8((.>*@ +M_N"9$("`!)"((()*.8AR^(*2"#GR#SG@F1#P\`20_R#R2#G88LB"@@TU@DPU +M^'+8;8)/-=ELV6_9$K(,.9*@_0PMD+L0T+L@LDPY^'*(@M(/.8((.9#=$("! +M!/"($8#=(-)/.=B"R&+R#3C"##C@_Q#`P`3PS"#"33C(D!J8*&N/\`-D$`#`I!U@!ARF(*(#K@)J6*PB$,,"XDZB0J)(O@.V`F)/HDY +M^1KY&=DJV2[R"CG"#CF"H/Z`_Q`';`?""3D';`$,&[#@!/#N(.)*.;AR#!S2 +M"S4,"IB"C$W2"370K)/(8O*@_:#@=.),-:Q>X@PY@@DTV!*2;!&R;!""3#3P +M[A#B3#FH@MEL^&+R:A*(B"T@XY8-T0TDXYR()23#7(8K(,.6"[$+),.:AB +M4DHU4D(44D(5'?`V@0"M`H+3:HDA@BCRDJ#4(G-J8WDQ<=``AA,``.A!G(_`GZ"($8DYD@P)P-F@ +MV#U\^Y+)_[)-$9),":E1LJ#_MQX+O0ZM`\*@`J7V_:A1R"'"+/+2H-30S(+* +MPRK,P@PI2U4;1,=R-@J +MR"O7G,&2"Q,':1>8>X().<*@_L"($()).?A[#`[B3S62"Q,7:1B(B_((.9*@ +M_I#_$/)(.>B+TJ``TDXUD@L39CDTF'OR"3F"H/Z`_Q#R23GH>PP,PDXUZ(O2 +M#CF`W1#23CF8B\))-?AKX@\Y@.X0XD\YV&O"334,#,)+%<)+%+@QLBM_PJ#4 +MP+N"NK.ZM7J[LBM_L@L1J5&"H/^'&PBM`PP\I>C]J%'(,8(L?]*@U-"(@HJ# +MBH5ZB((H?PP?\D@2XBQ_\=<`T.Z"ZN/Z[D)N1,(L?]#,@M'*`,K#VLP6;.Z2 +MS!`6">[*U;A-X@L1\J#_]QY_@@L3C/B")KN):_(FN_)K!Y(FNY)K".E!#`_R +M2Q/R2Q7R2Q3R2Q;83?(,"=D1#`T+GY9S_B(D;W4KMK#CR#`D+GY<^`L:0_SWP1O7_`/(FN_EKAO;_F$Z")KN)>P;U +M_P``DB:[F8N&]/^8:XQY^'N,/XB+5N@`DB:[F6N")KN)>_(FN_F+@@DY\J#[ +M\(@0@DDYB'LI82((.?`B$")(.8B+(@@Y\"(0(D@Y^&OR#SDH8?#S!%8O\[@! +M#!F22X`&?_\`'?```#9!`'+2:H(G\M')`**@U*"(@I&O`(J"VHB"""G!R@`, +M"Q;X$YI2#`I!-`!BK_\QT`!V@#+B)7_RH-3P[H+JXNKJ.N[B+G^2)_+X+DNJ +M@@X21Z\!G#CBH-3@F8*:DMJ9D@DI&[N7NPF&\?]-#VT+QOC_&Z86^@ZR)7_@ +MNX*ZLK"VH#J[LBM_TJ#_D@L3H=<`X'81]CDGZ'NXBPOY\+Z#S#NJLK(KN[(+ +M--<;*B"B(,*@`Z7*_:'7`,'*``8&`.AKX@XTUQX0L@L1(*(@##SER/VAUP#! +MR@#R)7^RH-2P_X+Z\OKW.O_R+W\,'N)/$M(E?[#=@MK2JMU";422)7^PF8*: +MDIJ7,)F`DBE_\@D4LJ9;W+^B"1,F.D`':@B"*0>""#D'Z`H7:BRHB:(*.0=J +M)+JBT@J/G*W2)7^R"G#BH-2M!N#=@NT"VM+*W;#+(&4#`!WP'?"ZH@;W__AI +M\@\Y!V^VAO+_FE*BH`#2)7_BH-2RH`#@W8(@XB#:TLK=#`QE```=\``V00`6 +M-0N"Q1`6V`I0XJ"H3K(*$=')`#*@_S";P!:Y"<(*$XS\VO:2+W^9:H(O?XEZ +M\B]_^8H,#,)*$\)*%<)*%,)*%D(%"?A."X2'LD7:YMT"=H`>4-V@F%V(:9E- +MG&B(>9RHV(D;S*P-0@4)*MP+A(>]'X;V_P""+G^):L;W_YA-@BY_B7I&]O\` +M`)(N?YF*1O7_G%10Y*#Y/J(%"5#:H-@]?/P+JL)-$:)%"3<;":T&PJ`");+] +M'?`=\)AJC&GX>HPOB(K,^-K&DBQ_F6KR+'_Y>L(L?\F*P@DY\J#[\,P0PDDY +MF'J""3GPB!""23G(BI(,.?"9$)),.8AJ@@@Y#!F`@P16>/'2U@:23>D=\#9A +M`"DA(:\`#`K8(2HC@B)_DJ7\TBT3,(B@FHBI2!9-!D')`(+3:IIS>1&),7'( +M`,8.`+(A`L(B?]*@U*(A`-#,@M'*`*(J`,K#VLS=`V69`*(B?[*@U+"J@K'* +M`*JCNJHE3/_8`<@AV%W2;!.<#:A-\=@`V0'V>NKP^J#X#Z`/`)*E_`P*@B)_ +M,(B@FHB(2*QHF"'2H^3:TZEYJ4FI":)MAI(I#Q:Y%^+)_Q;>&?+)_A:_%3"C +M(*4U_QWPJ"&H^K@M%DH5#!S8(0P._0/83>59`*@AF`$,&[)*-9@IF6KR(G^" +MH-38$8#_@H'.``P<^O.*_^(/@8(/@/(/?PP9X.F#BO_W+@*&UO_"3>T&U?_H +M,>(N\O*@U/#N@NKC2N[B#BH,!E*@`*S^HB)_LJ#4L*J"JJ.JI7JJHBI_Y8W_ +MR#'"+/+2H-30S(+*PT#,@,(,*E+%!&+&`<U& +M%0`]\$:F_P"<&.B)&]V<;O(*"M`L*@`B5I_5<4 +M!`P"'?``DB-_HJ7\()F@JIF821:I_@P2'?`V00`,"'("*@P)=I06>E)2!0@; +M1RPF-Q4.?0D;B&>T`7T$/?`,$AWP#`(=\#9!`$("*C("*T`CP$>S!"+"(AWP +M'?```#9!`)CRPJ#_4=D`%GD*0=H`8J97#!I*(R89&&8I)9(B'3J9:IF""74, +M*["((())=08$``#2(ATZW6K=L@UUH+L@LDUUDB(=.IEJZ>(.=5IS9CY9LB=E +ML@LTQQL4K0/"H`+E7/VR)V6M`PP\L@LT)5S]LB(=#`\ZNVJ[\DMUHB(=.JI* +MJO)*C((B'9*@U)"(@FK#BH-:B/)HFN(B'7S]#%(P[J!*[M)N(2),BAWP#&)* +MR:),C!WP6G.R)V6R"S3'&Q.M`PPLI5;]LB=EK0,,/+(+-.55_0Q2'?`````V +M80"]`B+3:H(B\G')`)*@U)"(@@P%BH-ZB(((*PP$\J#^%N@,#`UAVP#AO0#! +MKP""H-3JX\K#1B$```"2"A.(>@=I$)((.?"9$))(.8AZTD@UD@H3%VD3B(J2 +M"#GPF1"22#F"*@C22#62"A-F.3"(>I((.?"9$))(.8AZTD@UB(J2"#GPF1"2 +M2#F(BM)(-8(J!I((.?"9$))(.8AJTD@UTDH4TDH5HB+R@J#4@*J"2T2JHWJJ +MH@HK&U6"H-2GM3.B+'^`JH*JHZJD:JJB*G^8&K>9T9(N?[DA5OGUZ0')$;T# +MY4G_N"'($0P-Z`'RH/Z&[/\`'?```#:!`&D!22&]`ED1.5%2UVKR)?(,`R*@ +MU"#_@B')`$A1^O?SB8;1V8KR,(E\M*@U-#,@LK'RJ:BV@ZHRI(*%>+)_18^$>+)_A:>$O@A +MD=P`%H\9FIR2*7\661>@R@\]QZ4Q@T`B#&"*'^Y0JIJ+: +M#JC*)3/_N$&&QO\`R#'"+'^Y0Z"*'^Y0JIJ+:#JC*Y2#_N$&&C_^B +M)?*RH-2PJH*]!ZJGJJ:BV@ZHRN4F_[A!AHC_`,@QPBQ_N4',C+T'I27_N$&& +M@_]E'?^X08:!__@!B#'8.AOO\.^SX.$AX-W`%BW?@BA_N4',N+T'Y2+_N$%& +M>/\```!E&O^X089U_QWP`#9A`,&O``P$LM-JRL/2+']QW0"2H-20W8(+HMK3 +M>MVB;7^"*_+RH/YAR0"0B()1VP"*@VJ(@@@KX;T`#`(6.`SJXPP-1B```)(* +M$XAZ!VD0D@@Y\)D0DD@YB'K22#62"A,7:1.(BI((.?"9$))(.8(J"-)(-9(* +M$V8Y,(AZD@@Y\)D0DD@YB'K22#6(BI((.?"9$))(.8B*TD@U@BH&D@@Y\)D0 +MDD@YB&K22#722A322A6B*_*"H-2`JH*JHVJJH@HK2R(;1*>T.I(L?Z*@U*"9 +M@IJ3FJ):JJ(J?WJ9DBE_B!J'JD!R1&]`V42_\@1#`WH`?*@ +M_K@A1NO_'?```#9!`+T$<;T`\J#^8=``@@0*G0.H>0PCV/GPRA$;S-"LDR"J +MP`LJ=I@LHBL4P@H4K&T';`R""A7H>@?H!)A.)QEK%VP/P@H5F(H7[`?H22#N +MP!8^'$N['?``9CSW@@H5F&I6^/Z2*00GF>FE_/YZI:(J?U8*_JT$L@0)#`,, +M!Q9+,':;%[`!`[``$[++ZK+;`[`!$P`@`+`"`[++`\M4,DB_? +MF6R"+]^)?/(OW_)L"`P)DDP3DDP5DDP4DDP6T@0)#`_H2@N-A[,V,",@HM4, +M0-*@F%V(:9E-S$B"*M^";`:(>S-C`C +M(*+5#$#2H)A=B&F93B,W![RU0R2+]^9;((OWXE\\B_? +M\FP(X@DY@J#[@.X0XDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TYT-,$ +M5JWK#!^"IFF*A?)(@!WP(:\`*B6B(G^RH-2PJH*JI:JG:JJB*G^8:I()-+*@ +M_[<9";(*$0P\K07EQ_RR(G^2H-20NX*ZM;JW:KNR*W\,&J)+$H(B?Y"(@HJ% +M@M@-,F@H%D2\PL00%NR[2J?"*@2R#!'2H/_0V\`670GB#!.<'O+5#)(OWYEL +M@B_?B7SR+]_R;`@,"9),$Y),%9),%)),%M($"0P/Z$H+C8>S-C`C(*+5#$#2 +MH)A=B&F93(L"#WPW![RU0R2+]^9;((OWXE\\B_?\FP(X@DY@J#[@.X0 +MXDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TYT-,$5JWQ#!^"IFF*A?)( +M@!WP````-F$`D@0+K031O0"\^0PO8=``R//BH/X,`W:9,;(J))(+%*RL!VD0 +M@@L5>'L':`B")P4@B,`6.`T7:1"2"Q47:0J8BX(I!2"(P!8X)$NJ'?!F.?B2 +M"Q6(:V8Y\(A8)YCKD@L3!VD2R'NB##G@JA"B3#F8>S))-9(+$Q=I$XB+\@@Y +MX/\0\D@YPBL(,DPUD@L39CDPF'N""3G@B!""23GX>S)/-?B+P@\YX,P0PD\Y +MJ(LR2C6H:Y(*.>"9$))*.8(K!C)(-3)+%#)+%=J5DBE_5KGWK03"!`D,!PP+ +M%GPS=IP7P`$#P``3PLP=PMP#P`$3`"``P`(#PLP!V$K8;=A=2ZH@W"($()'.<(J),A\,DPUPBHDL@P4\+L0LDP4LBHDD@L5\)D0DDL5 +MDBHD@@D39C@2B&G""#G@S!#"2#FR*B2X:S)+-=KEXBY_5D[OLBHDD@L3\)D0 +MDDL3@BHD@@@35OCMK03"!`D,!PP+=IP.V$K8?=A=2ZHG'08;=TN[X+<1(:\` +M*B6B(G_"H-3`JH*JI:JK:JJB*G_H>N(.-+DA\J#_]QX+L@H1##RM!269_+@A +MPB)_DJ#4D,R"RL7*RVK,PBQ_#!JB3!*"(G^0B(**A8+8#7)H*!:4YM+$$!8] +MYD"K@,(J!+(,$>*@_^#KP!;^(?(,$YP?@M4,TBC?V6R2*-^9?((HWX)L"#), +M$S),%3),%#),%M($"0P/Z$H+C8>W-"T'HM4,0-*@F%V(:9E-S#B"*M^);(AY +MS%B838(JWXE\V(D;__HGS#V"*M^)C-($"0N=ES+/G'U`C:#I.*($"4#ZH/@_ +MPJ__HLK_PD\1HD0)DJ#_D)O`%HG"[(*$0P\K07E@/RX$<(B?Y*@U)#,@LK%RLMJS,(L +M?PP:HDP2@B)_D(B"BH6"V`UR:"@65,[2Q!`6_B,W"[RU0R2+]^9;((O +MWX)L!_(OW_)L".().8*@^X#N$.)).>A\T@XY@-T0TDXY^(SB#SF`[A#B3SG8 +M;-(-.=#3!%8MV0P?@J9IBH7R2(`=\)ALC&G8?(PMZ(S<+O+5#)(OWYEL@B_? +M@FP'\B_?\FP(X@DY@J#[@.X0XDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=AL +MT@TYT-,$5MWK#!^"IFF*A?)(@!WP(:\`*B6B(G_"H-3`JH*JI:JK:JJB*G^8 +M:I()-+D!PJ#_QQD-L@H1PJ`#4*4@Y63\N`'"(G^2H-20S(+*QBU0Q`TJ"878AIF4W,.((JWXELB'G,6)A-@BK?B7S8B1O_^B?,/8(J +MWXF,T@0)"YV7,L^(L"#WPW![RU0R2+]^9;((OWXE\\B_?\FP( +MX@DY@J#[@.X0XDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TYT-,$5NWQ +M#!^"IFF*A?)(@!WP````-F$`X:\`B/3X=#D!%N@<,M5JDB/RHJ#4H)F"H_%8;H_PP:Q@,```PJ1@(` +M`.IE(.?`"^X,"@P,.`$,#?T%O0,E`/_")G_2H-30S(+1R@"H],K%VLR2#`H6 +MR@H,'@OZ("?`"R(,"O"N@W:9'-(L%.(-%/A]!VX$@@\UC-@7;@?2+0B2#36\ +MR4O,'?"X3R>;ZPP;.6\Y';)/-9(L%*#3D-E?@@D5L(@@@DD5TBP4X@T59C[5 +MB&T,'_)(->(L%.AN.5XY;AWPF$TGF;SB+!0,&YB..6TY'K))->(L%*"#D(E9 +MT@X5#"_PW2#23A72+!2R#15F.Y28;0P8@DDU\BP4^&\Y7SEO'?```"`GP`LB +M=ID,TBP4@@T4Z&TF.`-+S!WPD@XU5EG_J$XGFO"(C9A]#!\Y:#EI.6XY'3E8 +M.5DY7O)(-;(L%*B+N'NB"C6B2S62+!2(>9AI@@@U@DDU\BP4##NR3Q4=\'T/ +M8:\`K0.]!>7=_FIE!K/_`#9!``P#,D(3,D(4,D(5,D(6,D(2.6(Y9\E)2%(Q)0$%!8&%!8E(5,E(20E(3<@(XN4*Y$`TB2\D>``BH+"#3B:DKJRX,P0#`["33BR +M9$.29$*B)+RB9$3B0^.2"(#"H/<,C<"9$-"9())(@(+(6#P9=JD=D@B`L@C8 +MHLA8P)D0P+L0T)D@T+L@DDB`LDC8@LI8:6.BIDF1X@"JHE)*@)J24FF!XFE] +MXFE_4DJ!XFE^XFF`4FF"'?`````V80`,2`P50M(/0B0>60%9$0`XIC`0IB$W +M`#)A`7:`$*(BYZDAF"&0D!29(8@A)C@"!OK_R!')`;@!K"LQXP``,Z8@$*8, +M#2D!^`'H`=D!*`'P]13R1`'@X$3B1``=\`!9`2@!'?```#9!`''D`'IR,B>\ +MP>,`0M(&,@,!,F0D`#RFX!"F#!OQY0#@T%3@Y@3Z(M)"?>)"?``\IJ`0I@`\ +MII`0I@P&4J``PJ"$,J`"X*H1D(84H(@@@E(_0A(_0F(A=J,^@B=#HB(A6HB" +MV`+2&`'*5:>=*<(8`,)B(K8F1PP-D/$$D#($D(,D@D*`,D*!\D*"H+V#\F(C +MLF(B#`(=\!MFPB(A#`J0T020X@20\R3R0H#B0H'20H+28B/`NH.R8B(,`AWP +M`)"C))`Q!)""!()"@3)"@C)B(Z)"@`P"'?`````V@0`,'`P*8;P`0M(-DB2> +M,J7<.C*R"0!J8H(F([++^["L@Z)#^I()`9)C+9PHL@:`DM(&@@G6#`JPK(.@ +MB"""2=8,!P`WIM`0IL(F'H*D,-)CRR8,)(JBXBIA/?`6OA.R$VR2*F&"*F*P +MF8+R(\N0B(""R`&''P)&(`#"T@'"#)X,&%+2!A:\$>(EPM(E%.<=&;(D)?(+ +M/3WP\L^^%C\2LB44HB7"MSI,HF44`#>FH!"F/?"VF@(&-@"V6@*BROO"ROT6 +MS`S2ROP6;0RB1(R@X'3B0_(`-Z:@$*:V^@H,4H)%Z7)$C1WP`*)$C:T"Y=H` +M#!@6&A`,8AWP````'((=\`P,N6&2`_*BH0*R(0:2R?\625VVW`6"1>FBH0*R +M)":R"TQ7:P7"`_(6?#C2)";2+1'2S?\6/3?B(RVLWK+2#O(K78S?PB2=PBP% +MPF2=DBM=5@G_T@76%MU,`#JF\!"F\D77`#JFX!"FXD78DB0FD@E,D)$$%HDD +MH@/RHLK^%OHC`#>FP!"FPF,OLB,O]CL"!HP`@D7I#&(=\```TBIB5MWK1K7_ +MX@72%@[PHB7"\B44\*H1H/_`%A_OHF44@D7@!KK_`,(%[59<[=(%R%;][()+ +M/]+2!>(=V@P*&^X6ONS-`GS^XFQJ\AW:&ZI+S!O_]SKP1JW_``"R)"6XBPPN +M2[N`NQ'@NR``.Z:@$*:2`_JB8S2<&?*D,-(F(_K"PBR?(-V@^MW";8G2)"72 +M#3FBH0+0T006#2%R9)QR1=/R)"62))R29"3R#SFRH``G;PC2`_?"H`'0O(/R +M`_JR0_:<+P`WIK`0IK)E)9(E)3WPMAD"AL?_LB0ER)L6S#:R)"72*PG2S?\6 +MO2/R)"7XGV8?&,(F([*D,"#,L+K,<`TJ:(VM+JX@`WIJ`0ILJR^KNB +M2V"@H'2V:@(&:?^<^B8:'28J+29*-B9:,QO,2^Y+W9+*_18Y-;;FX!"FXF7!TB7!MCT"QF/_\B7!"_\6WS<`.*:@$*:B93Z2)3Y\JJ>I +M`L9<_[(E/J9[`H9:_P`XIM`0IM)E/\(E/Z>L`@96_^(E/^9^`H8T``93_P`` +M`#JFD!"FDD73\@73%L\?O0@`.J;0$*;21=3"!=3`OI.R9)R&<_\````ZIO`0 +MIA9OZ0`WIL`0II(%SL)F8[(F8PN9&[NR9F-6V><`-Z;P$*;R9F32)F0;W=)F +M9$::_PP;QH__`)(#\@N95CG(K0*E00$,&%9ZPZ*A`L8<_\(+.,#'05:LVP`X +MIO`0II(F([*EW""9L+J9^2G2)";2#4S0U`06S=NR`_=6:]L`.*;`$*;2)B/R +MI=P@W;#ZW"`_>P +M(@&@H#0`"$"0D+&C]Q8`&$"24V_2$V^2(TB"(\K0;X*0D#0+_Y/W&F)3<`O= +M0-T18&#T@_<>P/\1@:P`5N(;A!#!@`-Z;0$*:V?0+&0P#2:X$F'0)F/0H`-Z8] +M\*`0IJ)K?68M"``WIL`0IL)K?B8]`F9M"``WIN`0IN)K?V9-"``WIO`0IO)K +M@,(DG1;,#KA'G`-*FB-K2ZN(`-Z:P$*;*DOJ9LDF@L+!T +MMFL"!G[^N5&L2[E1)AL@)BLN)DLZN5$F6S4;S)A12^Y+W9+)_18YG;;FD!"FN#&2;:&7N]M&;_X`-Z:0$*:Y49)M7H;R_P``-Z:0$*:Y49)N +MG\;N_P``5BCA#"JB1>KE+`3&@?\```!R93]R93[&8/\``()%Z0QB'?```#BF +ML!"FPB8CTJ7<(,R@VLRY#$:R_N@1XF2=1L;_```VH0!=`@P?0J5@-LB>22D+B)%/(>]@[H@LAP)G`X-W`T-^3D)^3@,K`P,^3T)D@P)D@ +MC/B,VJ(#U((+(J"(P("/DX"9(+(GDL(#UH(D3/A+H@L@#!Z`_\#`VL#0WI/P +M_I/PF2#0F2",[(S*PB1-J&O`JL"@KI.@F2!\_"%)`.(D/`P;#`;=!N#;@]#9 +M()'I`!8=!(&.`&)C&-@EX34`XF+(@FU;@F*"\B,4C,_R)R7R#S_,3V)C%+)# +MX((#X`N(%K@;H@/A)GI`K06E.P&(E8XR^8D/@93[Z +MQ@```&)C%%"E(((DZO(D//)A!O)A!8)D-"75`1:*``QB'?`,R9#8+R1;\,Y(D-F*@_Q;I!UFAT6@` +MPM5<L`PNQ&`JA$0B!%PHH.PJB"@B"!@M<`,"K!:@^!U('!_((!W(')M%4O= +MG%F&Z?\```!@A<`,#(!<@^"U(+"_(+)M%5BA>)$A20"2)#<6R0=9H=%H`,+5 +M7'F1=H!24BS\#`+R!37H]5(%-)#_$;#N$28908(L_9+)_HO,H@@TN/B""#5@ +M>L`PNQ&`JA$0B!%PHH.PJB"@B"!@M<`,"K!:@^!U('!_((!W(')M)4O=G$F& +MZ?\``&"%P`P,@%R#X+4@L+\@LFTE6*%XD2%)`+%H``P*3#S)VZGKF./QZ@#" +MH``6*07PU8!V@!^"+6ZB)#"8&*"9P)G[DB0PB"B0B,")^^CC&\Q+W>>\+$;V +M_P``FM72+8'"8Q<6?1VB)R>]!65U^PP;HD/AX@/AXL[Z%B[BLD/A#'(=\$P( +MB>OH\PP,K'[ZU7:`'Y(MD>(D,*@9X*K`J?NB)#"8*:"9P)G[Z/,;S$O=Y[P# +M1O;_`-'K`-J5\BF76O_RWP;R#\E@_\`6WQ[(XQ:,&8+,_Z"($8)K.,(IEWSZ +M6LS"W`:B3,G2`]*280,6G1CB).JR%*K@KB#P[A'B9#\E,R&B9!:R%*JB).JE +M-2&Q:`#P^A'R9!6")#^2H1B:E0=H"`P:HDF%1@$```P,PDF%T@/G%DT6X@/J +M5E[:\B(./PP=X*V#@@>,H&H1\B1`X@/2D:P`PB1. +MTB3H"YG`S!&`W1'0[A$`_Q'P9B#@B"#0B"#`B""`9B!B8HWR`]+R8LB"(H/X +M.^(K0](B0X#_(/#N(.#=(!:-"A:)"J(#Z@N99BK=#`(=\```HB%?(, +M.1=O#X(L$)(L$0NMH)B#%HD/S0G2)YP6W03B##D7;AKR##@'[P+&(0"(80PY +MF4'PB!&)81N(B5'&`@"H_&8J`L8G``P-V4'2##3!Z0#*Q6<=3?'K`%#MH/KN +M\BQ^XBYH^N[B8E+&??^")R6""#D7:`62`]\6^0ZB`]*2##D6.@G88=#101=I +M;`P8#`^880R.Z4&0D`20^(/P_9#Y48;I_Z@QTBQ^HBIHVJJB8E+&:_\`R7&H +M4;(36B4+(;(36K#*@LD!J%$E!R&Q:`#(<>(36O@!#"W90:#_D/EA^N[I40;9 +M_P"(89(37@P:J4&*B8EAB5%&U/_98>(37@Q_^4'@X4'J[>E1AL__````5ESP +MPB>?QK__%^E/TBP1%MT(XBP0%GX(HB#, +M@M#10P`\J5` +M,M)JHB/R^E*2%;P@JJ!*JL(J>-*F#'%)`,>9/)(J>N(5NI>>,\(J?+(E.N+2 +M#>)A$,"[P%;K9O(N)8(J?O(//-J2F?&'GQN(\9(J@(((X)"(P!98,H8"``"2 +MT@W:HJGQDF$0K0(EJ_P,"^'*`/'M`-(C\H*@U/KR@-V"8D];VM+JW<(-"/)A +M#IT-=IP9B$F<**AHR'B,"KEHC"RY>(A)^(B,#[F(2YFR30W"(_*2H-20S(+* +MPL+<#;),K:(C\I"J@O(A$*JBHMH-LDJH@B/R\B\ED(B"HB/JBH*2V`V2":VI +ML?(//*Q9ZNC2#@B=#G:=&8A)G"BH:,AXC`JY:(PLN7B(2=B(C`VYB$N9LDX- +M@B$0@BB2@@@CTJ_`"^@6OC*2R/X663)*D@P*PBF%#`L6_$_B(_*"H-2`[H+J +MXN+>#?).K((A$((HDH(((V'N`.*@@,+(_A;\,Q;(,Y+(_1:)54(C\L*@U,!$ +M@DI"0M0-LD2I\B/RP/^"^O+RWPZR;QSB(_+`[H+JXN+>#;).JM(C\L#=@MK2 +MTMT-LDVKHB/RP*J"P4KF(C\M*@U-!F@O$U`&IB8M8-\F8HXB/R\J5`(.Z@^NZR +M;C/"(_+0S((,&LK"PMP-HDRMDB/K?`C2%;R`F1"29\1B(^O`_0&`9A!@_R!A +M:`#R9D;B(_)A[``@[J!J[M)N>,(C\J(5NB#,H&K,HFQZDB/R\B$0@B4Z()F@ +M:IF":7SR+R6"(_+H\?(//""(H&J(\FA^\B/RX@[@(/^@:O_B;X#2(_(,)AO= +M]BT@D>\`((V@#";0IL":B'::$+)H>[)H?;)H?[)H@;)H@TN(?`XB%<"2)3JB +M%;S2%;W"%<&"%;J`W1$`_!'0V""@B(*29XM")3H`B!&`W2!`1`%`(B`@_R#R +M9\;29U/2(^O`Q$'`S`'@W1#0S"#1:`#);:(E'PP++0;V*@$M"^(E(`Q(]BXV +M@B$0^/&"*":B'U22"$R`JA&@JR"0D020DB"@F2"29XPB"$WR#]L@(`1`_Q$@ +M_R#R9\<,`AWP`*(A$)CQHBHFPAE4L@I,@,P1P,@@L+$$L+(@P+L@LF>,H@I- +MD@G;#`*@H`1`F1&@F2"29\<=\$J2LBF%%JL_PB$0PBPEH@PY@AP7XAP6H*$$ +M&X@;[L(,/H#N@@P8PLSWR5&@:)/@MH(LOK"[D)"[$><\`L9O`('P`(#LH.@. +MN6&@#@"(\8((X`NH%OHXLJ!@@.N#Z:&"(_(66#L@R*#"W&W"+#X,"!O,R<&R +M(_(@NZ"RVVVB*SNB:SSR(_*2H-20_X+Z\O+?#?(/J.C!LJ`1BO_P[H#B8^7G +MNP*R8^7"(1#"+"7"##W"S+X6C#.)@_L+!TJIEP58)RK\!2Q3]PB!!P51!QQ@"9<8)I?WIRK0=ET_J( +MP5)A$9(CY1N(B9&7N"-(<5(A"<(D?Y(A$:T'4+!TRIF29(#ET/K2(^5"Q`12 +MQ0'7->""(1""*)+B""-2(0)Q20`67@_!\0#2(0N"(^Q"(^NR(_*BH-2`1(*@ +MJX+0@&`@NZ!`38#*NZJBR(&BV@VB"J@+1(!$$,JJH*2"#!QE7P.(P;B1P(@1 +MBH)JB*)H?<(CY<>[&7:`$J(H?:JDHFB!DB/E&[N"R!"7NP.&^?\`PB$0PBR2 +M#!NR3",,"X;+_O(C\@P+@J#4@/^"XBF&^O+RWPWB3ZS&O?X<"L(A$,(L)<(L +M?AP.X*ICMBP'XB/R/?`6/B6R(_+BH-3@NX*PLH"RVPV""Z@6*"&GN`OB(1#B +M+I+"H`/"3B."(_*RH-2PB(**@H+8#;((J/<[`@:B_O)(J(:@_MK"R?%&;?X, +M"PQ-TD@C!JK^``!"(_*"H-2`1(*(\4I"0M0-@@C@0@2H"_@;1$!`=!;_(+*@ +M8(#K@^DQ#!Q,#:)A$N@QLJ:J9VH+(/Y*O +MP)"($()K?:(C[)(CZ]BQH)F"T.!@FMT+W>#=$/:T!>%H`()N#YA!B!&7N">" +MH`!`K\!VFAY*N,#+$O^"(_)6.-[@R(+*PL+<#;(,J!N[LDRH!G3_`(CQ@AA9&^KI`8#(D*#,$;"( +M$8+(/\K+P.Z"PB/DT(@0@.Z0Y[P"AF#_J`%&7_\``)*@P)DQQGO_``"281/R +M812A]`"X8:5J(/(A%)(A$]*OP+AA!D__DF$3\F$4H?4`N&'E:"#R(122(1/2 +MK\"X809(_Y)A$_)A%*'V`+AA)6<@\B$4DB$3TJ_`N&$&0?^281/R812A]P"X +M865E(/(A%)(A$]*OP+AA!CK_DF$3\F$4H7\`N&&E8R#R(122(1/2K\"X808S +M_Y)A$_)A%*&:`+AAY6$@\B$4DB$3TJ_`N&$&+/^281/R812A^`"X825@(/(A +M%)(A$]*OP+AA!B7_DF$3\F$4H?D`N&%E7B#R(122(1/2K\"X808>_Y)A$_)A +M%*'Z`+AAI5P@\B$4DB$3TJ_`N&$&%_^281/R812A^P"X8>5:(/(A%)(A$]*O +MP+AA!A#_DF$3\F$4H?P`N&$E62#R(122(1/2K\"X808)_P``-F$`#`0`-*9@ +M$*92T@9B92(R)2(,%K:#`L9L`(BEC'@`-*:0$*:292.B)2.VB@)&9P!RKX"R +MT@*Y(;(K[\*A`@P$%CL,@?T`X?X`21&*@H"@8*JX`#RFD!"FD)!T%GD7`#:F +MD!"F=ZD"QE@`IND"1E<``-DCTE@?`#:FD!"F=ZD"QE(`IND"1E$``/DC\EC? +M.*46\P4`/*:0$*8,#PPM*KOJNY"0=':M2[PY`#:FT!"F=ZT"!D8`INT"AD0` +M`-TCTEL?`#:FT!"F=ZT"!D``INT"ACX``#TC,EO?A@0````R)2,,#=);WP`3 +M0`#6H=);'QO_*[LX(?@1:X@R(^\;__)A`3>_`@;2_X(%S@N(5J@+F"&2*?`, +M!!8)"X'_`.$``4D!BH*`L&"ZJ``\II`0II"0=!99"P`VII`0IG>I`D8C`*;I +M`L8A``#9(])8'P`VII`0IG.;I=0#Y(_)8WSBE%C,%`#RFD!"F#`\,+2JJ +MZJJ0D'1VK3^L>0`VIM`0IG;M-@`](S): +MWX8$````,B4C#`W26M\`$T``UJ'26A\;_RNJ."'X`6N(,B/P&__Y`3>_`L;6 +M_PP"'?!B1>D,8AWP`-(E(@P/\EC?`!U``):ADE@?QJC_DB4B#`W26-\`&4`` +M-J$R6!_&U_\V@0`,"Z'1`)$"`8'(`'$!`6')`%T"#!\,`OE!*1$ARP!J97IU +MBH6:E:JEJ3&9`8)A`L@QF$&"!BBB#("R;%*R3(&R3(*R3(.JF9E!IA@J#`-" +M(0*B)W^JHZ"JL%"JH""J@.4A_J)D;PP,PF2/PF1_L@8H&S-+1+RB+F:))>;))>L))>]))?.))??))?B))?XN(8J",(KE2D6`F5."1)H,2))$FUJ=*IEJ[FK=HJ``=J@R@B09 +MDLD@@FEW@B09@FEX@B09@FEY@B09@FEZ@B09@FE[@B09@FE\@B09@FE]@B09 +M@FE^#$BB;W]:G2J92_\WG[3"U08,"[),X1WP`#9A`$+2!H($U@P,C!C"1.$Q +M!@$Z,J(C(&+2#!9J+((F98((.8"&!!:H*Y($SF8I!ZT")>7_PJ``4M)MHB0D +M(F9>(N"28>+B"B(.52`,*@`)(G-:(G +M-/($TZ)G,I)G,Q9_3H($U!:839)G/Y(G/Y)G-D8,````DBR"S2"H/^'&Q>M`L*@`N4P +M^K(F9ZT"PJ`#L@LT)3#Z#`SR)3(J__+?!L)/S.(E,GS](.Z@XMYMTFXVDB4R +MHJ#4H)F"FI*2V0[":1R")3+"0XD@B(""V&W"2.#"1.&AQ@"JHF4U^@P,+`NB +M1,N@H'2GNP;"1,M&"@``P(H1BH*"V&#"2(#R!,O`_Q'P\H#RWV#"3X'B)3+2 +M!,L@[J#BWFW2;CF2)3(@J8"BVFVB"N!F&@L@N:"RVVVR*SFR1,O2H'4,#[(F +M9:($RY(FW`P8B1&2R?Z@JI"B1-"B!-#B"SV0^(/ZJN<]"M(K?O8M!.*@`.D1 +MLA1@PA1ATA1BXA1C@0P3<`T@T!LBSP%ETI\0@!/?#PNQ"")F62&A*R;/#2 +M!,OR%%S"(QW`W1':TM+=8-(M'[%H`.(:$]K,PFM$PB4KP/\!?`W0S!#`_R#R +M:T;")2OQ20``[A'0S!#";\32!-_(I*)F9R#=`4#,`8((.<"9()#N(("!!#"( +M`8#=(.#=(-F+PB($UE:>T?($SO+/_E8/T8(E,E:HT*T");7_#`P&0/\` +M`)(G,YD*XJ#^HB0DTB9G#`S"9R["9RUR#3D,&*"HD^!W$'"J(*)-.=(F9Y($ +MUG*@_:(-.)"0!/"9$7"J$)"J(*)-.-(F9Z(-.)*@^Y"J$)($UY"0!."9$9"J +M(*)-.-(F9Z(-.)*@]Y"J$)($V)"0!-"9$9"J(*)-.-(F9Z(-.)*@[Y"J$)($ +MV9"0!,"9$9"J(*)-.*(F9Y(FW9)J$]($TL)FW9(*.-#0!."9$-"9())*.-(F +M9^(D*^E-HB0KJ7VB#3F2)MP,#G"J$)#H@_#N$>"J(*)-.8(F9Y(F97((.)() +M.:*@OZ!W$)"1!*"9$9!W(')(..(F9TQ:0B4Q0FX4T@7"TFX5XM)JR>NIVY(N +MY0P$K$FA"0&JHG:`&2P,1SP)@BI_TB,=BMW9^Y(NY:+*$!M$E[0#QO?_`.(C +M'M(C'>K=TFM'PB,>HB,=#`+*JJ)OQ1WP``"R)37RRX$6O\+2)3(@W:#2W6W2 +M+3:"S8$6F,$,"M>;`@8*__(E+@P>\*Z#1@?_```62L,JB8+8!H((S!:8P@P9 +MDD.)1@C_``!6"LF&-/_8$8Q-XB4S5O[5^"*!"@'R+S:`NR#P\`16;]62%^"" +MH("7.`*&4O_R+-WY`=@!#$[@W2#2;-T&3O\`DB=KB#N7F"V2"Q,]\"89'[+) +M_E:;O-(FW&8=&0;P_@#B)S;I"@:`_X(G,HD*!G[_LB;<)BO9#!W20XE&Z/X` +M`*)G/X;(_@``D.I#XF<_QL7^HF<_QLW^`)#Z0_)G/T;+_B"B((*@`()$X"5I +M`L*@`!;ZJ@QB'?``-F$`<0L!#`UZ>],["10=".P)]$=">P+"!09>X +M"-@?L+W`A@(``+(J\B"[H,J[N!O2!.,6/2;B!.067B3R*O(@_Z#RWP;R+QGZ +M^_)FL_)FOY(D+](J\N@TXF:V(-V@RHV"*".7&`B"W0;R)NOR:!^2)"@62?'B +M*O(@[J#BW@;2+AG2;AO"*O(@S*#"W`6R;#V&O?\,`O(FO_)FR!WP`%+2:I(E +M\B"9H)+9!H@Y%N@`TFD?HB7R(*J@HMH&TFH`HB7RLB;K(*J@HMH&TBH?U[L- +MV`JR)L+:N[)FX48!``#H"N)FX:(FZY(FX?(FY*J9\)D1%B\=DF:_L@3C%DL> +MT@3D%KT]":#LP.D+Q@`` +M``#)"[(G,L*@U,"[@KJVNKBRVPVR*SP,$_(+%,(A?>A[!V\1PBSD#`_8"PO, +MP/.#\-V0TFX$LB\`T;O_P"287B0.2`0H2"0N2`, +M?&4"`M(B\@P,XJ#4X-V"@B%XVM9*W=(-*H)A=^T!%CT%,F%O#`D0TZ!V@#VR +M)S+RH-3PNX*ZMKJYLML-LBL\&\SR"Q-+F:@KC+\XE:>C!QN(LFT`TLT$LB+R +M\J#4\+N"NK9*N[(+*K>\!,;N_P``@F%X,B%O#&RR(7C@HZ"R87:B87`PN\"R +M87_E^0$R86_B(7\6DP8R86_=`XT!,/`THM$!HLH@H*Z@=I\'N`BY"DN(2ZK0 +ME$%VF468"+@8N1JX*+DJN#BY.KA(N4JX6+E:N&BY:KAXN7JXB+F*N)BYFKBH +MV,C(N+FJR;JXV-G*V.BYVKCXV>J9"KGZHLI`@LA`TB%VPB%OU[QJHB%PO0[@ +M\#2"T0&"R"!VGP>8"ID(2ZI+B,T(L)1!C0JM#':919@(N!BY&K@HN2JX.+DZ +MN$BY2KA8N5JX:+EJN'BY>KB(N8JXF+F:N*C8R,BXN:K)NKC8V*F.`P/\F49\F48ZN;B87$,#Z(JY-K6 +MTF%R)74!PB%V#`_1#0&B(7WBICRRT0&RRR#JYN)A=*(JY-#6@-)A<^5R`>(B +M\O*@U/#N@NKF2N[B#BL,"()A=18N"0P)HL%_HLH1=H!^,BX!8;>_P```()A=4(A<2(AH`8,N@#`+:S`PM!A8``((=`)*@U)"(@HJ&2NCB#H!+(H+8"W:> +M*9(HK-()$^AYF(D';0OR+A6,7_B5.`[W$TX7;0O2*16,7?B5Z`GW'DM+B((A +M?8(HY3(A?`PM@BAR&S,R87R'LS^2(7V2*>4,""J9DBEV=JT2TB%]TBWEBMW2 +MW0+B'0&JB)<>A`P(AN#_XFQN&[M+S,;M_P``DFQN&[M+S,;J_P``XB%]XB[E +MXBYS#`_R87L6;@H,#H'J``PL8">@BB+&%0""'`"2H-20B(**ADJ8D@F`2^Z" +MV`MVF2F2**S""1/8>9B)!VP+\BT5C%_XE3@-]Q-.%VP+PBD5C%SXE=@)]QU+ +M2XB"(7V"*.4R(7L,+((H':L$L(A?<(L +MY8K,PMP"TAP!JHB7'80,"(;@_])BD1MW2R+&[?\``))BD1MW2R+&ZO\``')E +M&;)E&"P,%AL@]LM8H>H`8)N@JIFA#@&PW,#0X"2JIG:>![(J;;)I;DN9T(-! +M/?!VF#*"*FV2R2"":6:"*FV":6>"*FV":6B"*FV":6F"*FV":6J"*FV":6N" +M*FV":6R"*FV":6V")1D6."#VR%K1Z@!@F*"A#@&`O,"P\"2@IH#0F8!VGP?" +M*I#":9%+F;"#03WP=I@R@BJ0DLD@@FF)@BJ0@FF*@BJ0@FF+@BJ0@FF,@BJ0 +M@FF-@BJ0@FF.@BJ0@FF/@BJ0@FF0#`(=\`#B(O+RH-3P[H+JYDKNX@XJ#`G, +M'H8&`[I62R2"":6:"*N>":6>"*N>" +M:6B"*N>":6F"*N>":6J"*N>":6N"*N>":6R"*N>":6T&?O\```"VR`+&E/^A +MZ@!@F*"`O,"P\"2JF7:?"L(A?<(LY\)ID4N9HB%]L(-!=I@R@BKGDLD@@FF) +M@BKG@FF*@BKG@FF+@BKG@FF,@BKG@FF-@BKG@FF.@BKG@FF/@BKG@FF0#`(= +M\`#R!?X6KT(,!W)A>'+6;8(A>()A=T:L_@"2)S(6:7>R!\%Q$`',&X80`L(A +M?<(LY<(L<@P"%DQV#`X,",(A>-'J``PO8,R@VLS&=0```()A>!"A(+(A>,*@ +M`B5^`<(A>`P/T0P!HB%]XJ8X#`NR91CJYN)A<;T!HBKDVM;287(E"`'R(O*" +MH-2`_X+Z]DK_\@\K#`B"88`6[ZL,":+!?Z+*$7:`@S(G,K*@U+`S@CHV.CDR +MTPZXP[D*.,,,'[(#%0P.R',':Q6R(7VR*^3=#,ALLLO_L.^#X,R0PFT%,BA;X'='J`&#+H`P"VLP,+<9<`((=`)*@U)"(@DMWBH9`Z(#B#H`BP@&"V`MV +MGBF2**S2"1/H>9B)!VT+\BX5C%_XE3@.]Q-*%VT+TBD5C%WXE>@)]QY'2X@R +M(7TR(^4R(W(,"`PM-S("QE8`DB%]DBGE<)F`DBEV=JT2TB%]TBWEBMW2W0+B +M'0&JB)<>A`P(AN#_XFQN&[M+S,;N_P``DFQN&[M+S,;K_P``@AT`DJ#4D(B" +M\"``BH9*^/(/@(+8"W:?#I(HK+()$TN(V&DF.SX]\-(A?=(MY4ON#`C2+7(, +M+QLBUS("!EX!DB%]DBGEZIF2*79VKQ+2(7W2+>6*W=+=`K(=`:J(EQN?#`A& +MY__R+146K_NX*3@%MY.S\B%XTFQN2\P;__)A>$;I_P``@AT`DJ#4D(B"BH9* +MF)()@$LB@M@+=IDIDBBLT@D3Z'F8B0=M"_(N%8Q?^)4X#O<33A=M"](I%8Q= +M^)7H"?<>2TN(@B%]@BCE,B%Z#"V"*'0;,S)A>H>S7)(A?9(IY0P(*IF2*7IV +MK1+2(7W2+>6*W=+=`N(=`:J(EQZ$#`B&X/_B;&X;NTO,QNW_``"2;&X;NTO, +MQNK_````LF48#`[B91E&B?X,`@P/\F48\F49'?"Z5H89_8(A?8(HY8(H=0P) +MDF%Y%MB?#`Z!Z@`,+&`GH(HB1A<`@AP`DJ#4D(B"BH9*F)()@$ON@M@+=IDL +MDBBLP@D3V'F8B0=L#?(M%8Q_\B4),BT`]Q-8%VP,PBD5C&SXE=(I`/<=4TN( +M@B%]@BCE,B%Y#"R"*'4;,S)A>8=`H;>_SWP#`B&W?_28I$;=TLBANO_`))BD1MW2R+& +MZ/\``'+6;0P)Q@?]T@7^%BUEH`#"]@S*#:S$8G`=(B\O*@ +MU/#=@MK62MW2#2H,"*$, +M`0QY)T;Q_P"B#3FR#34':N)6^_WX#>@%]Z[8HB%XTFQN2\P; +MJJ)A>`;R_P#"H`2B(6XR(7BQ#`$R87Z@,\!@JJ"B86VPJH`PLR!E(P'2(6[" +M(7XR86P6C0@R86R!Z@!@HZ#0D#2*JHJ&=ID)LBANLFJ12XA+JM"407:999(H +M;K(H;[)JDK(H<+)JD[(H<;)JE+(H+)JF[(H>;)JG+(H>K)JG;(H>[)JGK(H?+)JG[(H?;)J +MH))JD8+(0*+*0,<]`H8B`*'J`-(A;((A;;T-JHC0T#2JIG:="9(H;I)JD4N( +M2ZJPE$%VF662*&ZR*&^R:I*R*'"R:I.R*'&R:I2R*'*R:I6R*'.R:I:R*'2R +M:I>R*'6R:IBR*':R:IFR*'>R:IJR*'BR:INR*'FR:IRR*'JR:IVR*'NR:IZR +M*'RR:I^R*'VR:J"2:I&"R$"BRD#"91G"91BB(O*RH-2PJH*JIDJJH@HK#`F] +M#!;Z"M'J``P(8,R@VLQV@##2)S(RH-0PW8+:UMK8TMT.V,WB#1,;F=AM)CX7 +MXB+R\J#4\.Z"ZN9*[N(.*TN(Y[EN!O+_H@TU%AK^N&VY7:(G,C"J@JJFJJBB +MV@ZHRJAJHFQN\B#NC. +MZ&[B;)&R)S+R(7@PNX(;_[JVNKBRVPZXR_)A>$O,L@L1LDXTAM__````LB48 +MP0P!8*N@RJK"(7BPO,`,'.4"`:(E&+(A>`PGX,#D8/ +M``""'0"2H-20B(+P(`"*ADKX\@^`@M@+=I\.DBBLL@D32XC8:28[/3WPPB%] +MPBSE2^X,",(L3M,(A=])G?TMW&\S"87>&Z?^R(7C2 +M(7?291FR91A&.?WB(7WB+N7B+G0,`A9NJ@P'T>H`8,N@#`C:S`PM1D```.(A +M?>(NY>(N=`P"%NXP#`X,",(A>-'J``PO8,R@VLP&5P```((=`)*@U)"(@O`@ +M`(J&2MC2#8""V`MVG0Z2**RR"1-+B-AI)CL^/?#2(7W2+>5+[@P(TBUR#"\; +M=]J9DBEV=J\2TB%]TBWEBMW2W0*R'0&JB)<;GPP(1N?_ +M\BT5%J_[N"DX!;>3L_(A>-)L;DO,&__R87A&Z?\``((=`)*@U)"(@DMWBH9` +MF("2"8`BP@&"V`MVF2F2**S2"1/H>9B)!VT+\BX5C%_XE3@.]Q-*%VT+TBD5 +MC%WXE>@)]QY'2X@R(7TR(^4R(W0,"`PM-S("QF3^DB%]DBGE<)F`DBEZ=JT2 +MTB%]TBWEBMW2W0+B'0&JB)<>A`P(AN#_XFQN&[M+S,;N_P``DFQN&[M+S,;K +M_P``@AT`DJ#4D(B"\"``BH9*^/(/@(+8"W:?#I(HK+()$TN(V&DF.SX]\-(A +M?=(MY4ON#`C2+70,+QLBUS("1F<`DB%]DBGEZIF2*7IVKQ+2(7W2+>6*W=+= +M`K(=`:J(EQN?#`A&Y__R+146K_NX*3@%MY.S\B%XTFQN2\P;__)A>$;I_[I6 +M!E3[`'+6;0P(@F%X!H3]``"B(O*RH-2PJH*JIDJJH@HJ#`D6FBARUFT,"/*@ +MU,'J``P-TF%XRL;2)S+PW8+0UH#0V(#2W0W2+3R2R0'R#1-+B-AM9C\7H@TY +ML@TU!VH.S+OR(7C2;&Y+S!O_\F%X,B+RHJ#4H#.".C9*,S(#*O*@U#*$,`0P,/0NJIN7-`+(A>+)E&,(B\M*@U-#,@LK&2LS"#"L,"1;,!PP(T>H` +M8,.@,J#4VLS2)S(PW8+:UMK8TMT.V,WB#1,;F=AM9CX[X@TUO%ZX;;E=HB$O,\@\1 +M\DHTTB+RXJ#4X-V"VM9*W=(-*TN(,J#4USF2LB48P0P!\B%X8*N@RJJPO\#" +MH`$EPP#2(7C291C&`?RR)1@&X?T`LB%XLF48AM[]XB%]XB[EXBYU#`(67LH, +M#O(A=PP(#"U@_Z!Z?X8/`((=`)*@U)"(@O`@`(J&2IB2"8""V`MVF0Z2**RR +M"1-+B-AI)CL^/?#"(7W"+.5+[@P(PBQU#"T;(LJ9DBE\ +M=JT2TB%]TBWEBMW2W0*R'0&JB)<;GPP(1N?_\BT5%J_[N"DX!;>3L\(A=])G +M?TMW&\S"87=&Z?\``-(A?=(MY=(M=`P'%EWT#`X,",(A>-'J``PO8,R@VLP& +M$````((=`)*@U)"(@O`@`(J&2MC2#8""V`MVG0Z2**RR"1-+B-AI)CL^/?#2 +M(7W2+>5+[@P(TBUT#"\;=]J9DBEZ=J\2TB%]TBWEBMW2 +MW0*R'0&JB)<;GPP(1N?_\BT5%J_[N"DX!;>3L_(A>-)L;DO,&__R87A&Z?\` +M`'+6;0P(@F%X!O;]`'+6;0P)DF%X1G+_`#;!`"EA@;\`8J/`:F**0DF1%O,\ +M01$!H0T!^&&2)H"!$@%2WP@+F9F!BH^JKZDAB5%*_[B1:&&R*[F"I?2*9A9; +M/,(F+MA6\,P1\-T1V4$;S,D1P1,!N&$,#3A12!%)<3(#`-G1RKOBP_T6CC99 +MX8AAF"$,#:B!V?$,#1OJPMG^D*J@Z<&2R?R9L9')`,FAJ3&:B(D!!C0`Z)%* +M,X(#"I(NN>(NO':8'X(C%'((%$LSG)D'9P:H>$(*-:PD%V<&J(A""C6L!#WP +MK0[&!P!F-_6H:$(*-5;4_EA*QY7H!@,`2$K'E-8&`0!82L>5V$C!F/%8H8C! +M2YF9\8>]$CB!*#'0,\`;,W:3!C@"(L+\.2(;W:)E@(BQ2U59H4N(B;'7-"Q( +M(:B!./%`G:#0JL`KJD`S@'+3_G::%>@#,L,$C+Z")X!""#46=`2)"4N92W=+ +M_SC1F.%(41LS.=%*,S(#`$N9F>&"P_T6R":V8P*&F@#V(RYX#^@1%H,6.'%8 +M03HW&\-7O`)&,P!0P\`;S$8Q``!(2,>4LJ(K(%(H%*<5K8;I_^+#_A8.%4C! +M.($H,4>]#M`SP!LS=I,&.`(BPOPY(@P##"1VI'I8D5(E0CI54M4"@A4!5E@& +M0A4`.&%2H-101()1R0!*,UI34@4I%F4(@=``#`F*,W:50((C?W(($ZAH9C<, +MPBH5C&Q()N(J`$<>:0=G#:AXPBH5C%Q()N@*1QY8%V<0J(C"*A6,C$@FZ`I` +M[L`63@1+,QN9!@X`@J"$BC.AR0"88:J9D@DI6`$X85:9",8'`$(K(3AA@J#4 +M@$2"R7%*,T'*`,C!2*'"++R(\5BQH,S` +M%@SL&]VB9(!+B$M56;&)\4M$2:'7O@)&JO]((:B!./%`G:#0JL`KJDHS`XB@4C'Z)"4N92W<&G_]8)D@(5Q3S!OO_`%(%*<;"_XAQ +MR$$;EW`XP)EQ4G%V<+Z(A"#C6, +M-%A>EQ48/?#M"D8$``!F-_3H:$(.-1;$_E(N!9>5YDC!B,'(\5BAA[T2.($H +M,=`SP!LS=I,&.`(BPOPY(AO=B+'B98!+S,GQ2U59H4N(B;'7M`)&;O]X(4B! +M./%P[:#01,`K1'HSB)P"""A,':.^B*@?@!0`6:OX;(J@'N`;(,:AZDLL!P+N@HFL`DF8` +MV`'7(KOH`>"%PX!L@QJ'H;F\"[H*D+F0;8 +M`=>D,G@A<'2@Q@$``!M$2W="K*@8\(F0M$Y`.$8`8%2`.)M/.A!@FT\ +MP@P]\@73<@7<(@7?TBYP<_@`XBYO(_@!\_@"T-!$X.!$X_@#T_@(QSL"0)0@ +MN$'R(X*3^`V`F""'_P6C^`Z`F""-!))CJ<(KJ,)CJ](K6<(K6K(K5M/X`,/X +M!K/X#*/X$H)CJ@Q(J$'2!>P,*:(J60O=%MT@@D7P#(_R1>[R1>^X0;(K6O8J +M`D"4(/(56M(F0_8K`D"$(`P<<6@`X@U,@/\1\/@@X.$$X.D@\.X@^$'B8XS2 +M#4RB)KFR+UGR+UH@JA'@NQ&`_Q%7;02"!B!=7X09(%SA9J +M$"$9`3$:`=(O6<(H$0N9#`CR+UKY$<+,_@P?D(^#%BPEB#%,&9G72>?JB$$; +M`7:=1Y*8'J*8'[*8(,*8WM*8W^*8X&N(D)"$<*H1X+L!P,"$<-T1X.X!0*H0 +M,+L00-T0,.X0H)D@T*P@()D0(*H0D)L@H*X@F?>I]R$9`9$``8@Q,1H!01L! +MFHB8$>*@0.)G#G:91Y*8'J*8'[*8(,*8WM*8W^*8X&N(D)"$<*H1X+L!P,"$ +M<-T1X.X!0*H0,+L00-T0,.X0H)D@T*P@()D0(*H0D)L@H*X@F?>I]\(%TK(E +M(J(%T>(E(](F0W"J$<#N$=(M$?"[$>"[()#=$=#,(,"J(+"J(*FGPB9$Z(78 +M'.#=P-)G$-B%R"S0S,#"9Q&R![B1>_21?`&>_^(,?(%TX+87X(H/(D!%@_G +MDB:YJ/B0JL`66N:R"#FPL006R^7"*!"B*!$+V="L@Q8:((T*B0'&D?_X`?(O +M%1:_&9'K`(@QFHB"*)<6Z!B8`:().8().)CYH*$$@(`$P(@1X*H1H)D@D(@@ +M#(F0B""X0:@!@F<4TBMRR!K0S,#"9Q*R*W*H*K"JP*)G$T;/_P#B! +MVP9L_P``B"'R!=)"2'\6SQ6B%5JR!>[PJA'ECQVB1?&"!>P+N!9+%<*@8)*@ +M@("<@](F0J$<`8@QT@T]JHC2S;X6#12R%5\,'.@QTB:Y\@7+#`K2S?[@_Z#0 +MK(.PJH+AZP"@J8+J__(O:.(H?Z"A0:K_^N[B8T[B!?'B8T;`(`"&5O\``!:8 +MVH@1+`_PW1$,6J)E(J)E(_#=8_"8$?")8XD1%IT$B#'@B(`';1/R6"#R6!_R +M6!Y"6.!"6-]"6-YKB-"Q03WP=ILE\E@@\E@?\E@>0EC@0EC?0EC>\E@C\E@B +M\E@A0ECC0ECB0ECARXBX$1;;TZ$``8@QG0N@B(`':Q/R6"#R6!_R6!Y"6.!" +M6-]"6-YKB)"Q03WP=ILE\E@@\E@?\E@>0EC@0EC?0EC>\E@C\E@B\E@A0ECC +M0ECB0ECARXC&.O^H`8CZD@HUL@HXH@HYT)D1L+`$P+L1L)D@H*$$X*H1H(@@ +MD(@@1IK_HA5:L@7N97H=HD7QAJC_DJ#`1JO_``#1ZP"X,<(H?]J[LBMHRKNR +M8TX&M_\```!6R-^")KR&??\````V00"F(T(,"@O3?0(,&`P)H,/`"[QVJP\6 +MQ`8F%%4F1#XF5"<;B$MW&ZJ7&Q(@;*`@B:!8"&+6_G(F?WD(4F9_?0(,&`P) +MUYK&'?``Z!<@^:#X#^@.^`_WKLF="`;Q_P!H%R!9H%@%:`98!6>EM9T(!NS_ +M`.@7(&F@:`;H7FA6YZ:AG0@&Y_\`Z!<@^:#X#^A.^$_WKHV="`;B_P`V00"F +M(T(,"@O3?0(,&`P)H,/`"[QVJP\F)&PF-%4F9#XF="<;B$MW&ZJ7&Q(@;*`@ +MB:!8"&+6_G(F?WD(4F9_?0(,&`P)UYK&'?``Z!<@^:#X#^@N^"_WKLF="`;Q +M_P!H%R!9H%@%:"98)6>EM9T(!NS_`.@7(&F@:`;H'F@6YZ:AG0@&Y_\`Z!<@ +M^:#X#^@.^`_WKHV="`;B_P`V@0!AKP!J8D(F?PP(4J0\($2P6D0R)&N"9&O2 +M)G]")&H@W;!:W<(M:\)M:J(F?R"JH%JJHBJ&6E*R)7,;JN57';*F2'T*DB6< +M22$Y$9"*P!:8%+I"H0L!,>$`F0&JHJDQ#`J2)G\<#X($@RJ9NIF"28%VKQ-< +MC,#*@LK".LS"#(`G;`<[JJ"@=**@_\*@_Z)$B*"@=,>:`@8A`%R/H+^"NK(Z +MNY(+@,*@^PP*P)D0#$S`F2"22X"R%#R"!(C"%#W2%#Z`_X*!'0'B%#_P\H"* +M_Z5#^WEZR#&2H._RH/W2"CD,'GSX@DHTXDHV@@HX\-T0#"_PW2"0B!""2CCR +MH/[0T'3PW1#@W2#22CG"+']Y2G)EG,B(E +M8^D:TB5DV2K")6?).K(E9[D*DDHTO0)EQ?CR)G\;IX*D/"#_H(K_`;"R@*(K?Y+2 +M!H*@`J+*`:)K?X))ZF4``!WP-F$`HJ`!I>'K92/VL7,`X6@`D4D`\6@`#`W2 +M:8#2:<#9#])N0,(IJ`.%AH,H@7.T2(!\2>F*<7H@"K0+@"`"( +M$JT"X`@`%NK^+0H=\```HB8A%BK^HJ!`9=;K#!@,#4K"#"Y!-P"1IP`RI#3R +M),0Z,OD!D/\0\F3$XF2TL@72DB47\B-APBQ_R=4@_Z!Z__(O).(&?Y#8@_/\ +M$,G5X_P,T_P/R=46NP"2!GV"(X"3^!B"8X!8`9(C@*T"`#FFB!+P(`#@"``6 +MROXM"@P*HF2THJ!`)D2#'_2(XH,'`P+@B-A>J*B"G\@B*#0O(.S_P_R8X"C_Q'R +M8X""*&R#_Q3R8X`&M?\``.$F`>D"!K+_^0+&L/^"(FD6&`9*LJ*C#*)K?\;= +M_P``P2@!R1*&JO^B!D"!MG_\2L!^0(&RO^!+`&)`@;5_Z$M +M`:D"!L;_L2X!N1)&TO_"(FFLG$KBTJ(,TFY_!NK_\2\!^0(&OO^"(FFD"!M[_````-J$`,M(&J-,` +M.J8,#D+2`9(#TY)$D^EDXF06XD24L!"F4M(#B'.PH72PF70;B!9H0:)EKI)E +MK29!$+__)EQ])$FN)D%-)$DG%)`/$S`6%H`,(D%*$U +M`#P[[.S!E@"2)>K`F8``.::`$*:1K`""9")V@!/2)X,+F19=%Q9)%^(#ZN+. +M_A:^%T;Y_P#R(E3V3P*&$P&V;`(&8`""S/L,'PP,@,^#PD2<#(B"9!0`/J;P +M$*;R9!8`/J;(@;9/`M)#Z<`0IL)D%P`^IK9,`M)#Z<`0IK9,!=)#Z<*@`,)D +M&``^IK9,`M)#Z>`0IL(D%>)D&?(EZH(D%L/_"(/_$,(D%X(D&,/_%(/_&./_ +M'``_IK9.`M)#Z8`0IH)D(N(D(M(D(L(D(O(D(N#B%.)D&X(D(M#4%-)D'/#X +M%/E!\F0>@(H4B5&"9!_R)"*")"+`QA3"9!V`C!2"9"")88(D(O#P%/)D&H". +M%(EQ@F0A@@/<%K@%@@/?^3$6>%\,'^DAB#'9$K/BQ] +MA@\`ML\"AO``\LSA%D]B@LSZ5M@*D@/<#,JB9!06"0SBH0(`/J;`$*;"1)2R +M!)06ZPK29!8,[_)D%,8H`/K(EK/K=X_T$\34`X34!L_T*P_T0TF=5HB6MTB6ND@2? +MB%2C_0B3_1'Z_8/_%.K=#$CR9\G9QJB4J<:8U*T"F<:=`G:H(?A)Z#GP\-3@ +MX.3S_@_IQK(J7DNJC'LF&VHF*U4F.R*2R2"R):V2):ZB!)^S^0BC^1*29DR" +M):[R(Q@@B*#R:&H=\/AIZ%GP\-3@X.3S_@_IQMB)R'G0T-3`P.33_`_)QKBI +MB)FPL-2`@.2S^`^)Q@;K_[AIB%FPL-2`@.2S^`^)QH;F_]B)R'G0T-3`P.33 +M_`_)Q@;B_P`^IJ)EKI)EK?`0IO)EQP;W_@```#ZF?/N29!'B1)JR9<>@$*:B +M9!6")!4;B()D%(;U_@#ZG+(D(O%3`.(#T\($E/J[X_L4P_L9LF=6@B7^XB01 +M\B6LD@D`BN[S_@33_@J3_A#B9U7"):VR):[X5(($G\/[",$T`8/[$:KK\_X4 +MXF?)RKNYQH(EK>(EKO($GX/^"//^$N)F3,(EKK(C&"#,H+)L:AWP`*(D%9(C +M*J/Y"``YIH`0IB"B(()D(J6T!J*@`;T"9=D&LB6LJ%.ZJI9:*3P\IZP$+'O& +M`0"Q,P&ZNK(+`,(EK*ACRJJ6ZB<\/:>M!"QYQ@$`D3,!FIJ2"0"B)!3B)"*" +M`]/R!)2C_A6#_A3S_AGB9U;2)?ZB)!'"):S:JL/Z!+/Z"I/Z$*)G59(EK>(E +MKH($G]$U`9/^"(/^$8$U`/(B1=K>BN[S_A3B9\G9QL(B2L>2Q[!A\` +M#`U&#/_Q4P"R)"+B`]/"!)3ZN^/[%,/[&;)G5H(E_N(D$?(EK`P)BN[S_@33 +M_@J3_A#B9U7"):VR):[X5(($G\/[",$T`8/[$:KK\_X4XF?)RKNYQH(EK>(E +MKO($GX/^"//^$N)F3,(EKK(C&"#,H+)L:AWPL3,!NKJR"P#"):RH8\JJE@H4 +M/#VGK00L><8!`)$S`9J:D@D`HB04XB0B@@/3\@24H_X5@_X4\_X9XF=6TB7^ +MHB01PB6LVJK#^@2S^@J3^A"B9U62):WB):Z"!)_1-0&3_@B#_A&!-0#R(D7: +MWHKN\_X4XF?)V<;"(DG)QK(B3;G&J#*80K(B5*"@Y)"0U`O+%OP4PLO^%NP+ +MD_H/J<;8PLBRT-#4P,#DT_P/R<:R):WR):Z"!)^S_PB#_Q+R9DSB):[2(Q@@ +M[J#2;FH=\`P+!N_^``P,AO3^F&$,#]AQ#!P,"-",@Y#\@X#_$(A1#`[808#L +M@X($D@P)T)R#D(@0@.X0\.X0XD22!HK^#`N&7?\,"49C_P``D_H/J<;B(A32 +M(A/@X-30T.3C_0_9QL(EK8(EKK($G\/X"+/X$H)F3/(EKN(C&"#_H.)O:AWP +M#`M&K?\`#`G&LO^3^@^IQO(B%.(B$_#PU.#@Y//^#^G&TB6MLB6NP@2?T_L( +MP_L2LF9,@B6N\B,8((B@\FAJ'?``D_H/J<;B):W"):[2!)_C_`C3_!+"9DRR +M):Z"(Q@@NZ"":VH=\""B(/*@#_)D%"5@`L(EK:(EKK($G\/Z"+/Z$J)F3)(E +MKH(C&""9H()I:I``````D_H/J<:R):WR):Z"!)^S_PB#_Q+R9DSB):[2(Q@@ +M[J#2;FH=\````#9!`#*F"&*A(&I"@@1_.C*2`^:"R`&"1'^`@'27F`0,"()$ +M?U*E/%I2HB5%DA7`HLH!HF5%IQETDB,5@A-:DLD!DF,5EQALH:P`L4D`=H`2 +MT@1_PBM-"ZK77`J,FN(#XB8N#(;Y_\QJ#"_R0^*E1?_"!'\,>O(E2+(E'PP> +M#`T@NZ!JN_#>@]/Z#Z)E/L/Z$:)E/K(K)+/Z%*)E/I`0IH(#X9><`L8D`K$V`<(D%`S=TF04PLSH +MP*)!L*J@P,`4PD2AJ`JI9*T"I<@`HB.M@B.ND@2?H_@(D_@2@F9,\B.NXB47 +M(/^@XF]J'?``PB)4<4D`H34`@LSJ%A@7XB04#"N"H#"'G@+&A0(6_"ZV3@)& +M0P#R8E2R)!6B(^JS^@@`.J:0$*8@HB"29"+E!@8,&KT"I8$&PB/%LB.L/#K2 +M(\;*NY:[);>J!"Q\Q@$`P3,!RLO"#`"R(ZR")"+:N](D%)8K)+>J!BQY1@(` +M``"1,P&:FY()`+(%SZ($E-/X%;/X%*/X&8)G5O(C_M(D$>(CK/K=X_T$P_T* +MD_T0TF=5LB.M@B.NH@2?\34!L_@(H_@1H34`DB)%^OBJB)/X%()GR?G&XB)) +MZ<;2(DW9QJ(B5)(B6K+*_Q9+'>+*_A9N718Y;_+)_Q8?=&8I`L;=`9(B6\P9 +MQ@8"9AD"1A$"@LG^%EANTB.MLB.NP@2?T_L(P_L2LF9,HB.NDB47(*J@DFIJ +M'?`\#L>^"_)%Y?)B5/)B5<:X_\#P!%9/5[)B5,:U_P`]IJ)CKI)CK8`0IH)C +MQX:&_P``/:9\_))D$=)$FL)CQ[`0IK)D%*(D%*)D%8:&_PR+LF04`#VFD!"F +MDF06`#VFL!"F@J`,M[@%\D7ELJ``LF07`#VFPJ`,M[P"\D7E@!"F@F08`#VF +M#,Z'O@+R1>6P$*;2)!B2)!6R9!G"(^J")!;B)!>3_`B#_!#C_!33_!BS_!P` +M/*8,R;>Y`O)%Y=`0IM)D(L(D(K(D(I(D(N(D(L#`%,)D&H(D(K"R%+)D&_(D +M(I"4%))D'-(D(N#F%.)D'8"(%()D'HD1\/H4\F0?^2'R)"+0W!329"#P_A3R +M9"&"!=@6>`2"!=O9`198>PP=)CP&B!$,#(#3H0M@RX.#4T-#DX_T/V<;"(B2R(B/`P-2PL.3#^P^YQJ(CK8(C +MKI($GZ/X")/X$H)F3/(CKN(E%R#_H.)O:AWP`/(D%<(CZN($FO/\"./\#P`\ +MII`0II)D(M)D%/(CQX(%VX)$DM8O`,8``I&L`)+)_X(G@Q;87!;97,(%Y@N9 +M9BSN#+T`/:;"(\6R(ZS*NY;K8CP]MRT"QN,`+'R&Y````+$S`;JJH@H`PB/& +MLB.LRKN6:V`\/;>M!"Q]Q@$`T3,!VMO2#0"1/@#B)"*"!<_R!)2:[H/^%//^ +M&>)G5L(C_I(D$;(CK,J9L_D$P34`L34!H_D*T_D0DF=5@B.MDB.N\@2?Z%2# +M^0CS^1'*R;J9X_P4O0+"9\F9Q@Q,G0*(E(G&^-3YQ@8"``"RRR!+F18\T:(I +M7@O,%OHE"]H6[1OBROX6SA%F.N&B*5H6.@T+^A9O"&8JTXA+^#N`@-3P\.2# +M_P_YQN(K)-(K(^#@U-#0Y./]#]G&J&N(6Z"@U("`Y*/X#XG&\BLFXBLE\/#4 +MX.#D\_X/Z<;8BZA[T-#4H*#DT_H/J<:"*RCR*R>`@-3P\.2#_P_YQNBKV)O@ +MX-30T.3C_0_9QJ(K*H(K*:"@U("`Y*/X#XG&!M3_`.(K)-(K(^#@U-#0Y./] +M#]G&HBLF@BLEH*#4@(#DH_@/B<;R*RCB*R?P\-3@X.3S_@_IQM(K*J(K*=#0 +MU*"@Y-/Z#ZG&!L+_`*A+B#N@H-2`@.2C^`^)QOAKZ%OP\-3@X.3S_@_IQMB+ +MJ'O0T-2@H.33^@^IQHBK^)N`@-3P\.2#_P_YQ@:R_P"B*5H6*@N(2_@[@(#4\/#D@_\/^<;B*R32*R/@X-30T.3C_0_9QJAKB%N@H-2`@.2C +M^`^)QO(K)N(K)?#PU.#@Y//^#^G&1IW_``#R*R3B*R/P\-3@X.3S_@_IQM(K +M)J(K)=#0U*"@Y-/Z#ZG&AI/_Z$O8.^#@U-#0Y./]#]G&J&N(6Z"@U("`Y*/X +M#XG&1HO_``"B*5H6*@^#@U-#0Y./]#]G&1F3_``"B*5J\ZB8:*-+*_E8=V*A+ +MB#N@H-2`@.2C^`^)QO(K).(K(_#PU.#@Y//^#^G&AE?_XBLDTBLCX.#4T-#D +MX_T/V<:&4O^(2_@[@(#4\/#D@_\/^<8&3O\`##F28E0&6/X6F0L+J19*.;+) +M_E;;"_A"Z#+P\-3@X.3S_@_IQM(B),(B(]#0U,#`Y-/\#\G&AB8`P3,!RLO" +M#`#2(\:R(ZS:NY:+*#P^MRX"QF$`T@2:@B0BL@7/D@24T_@:L_@4D_@9@F=6 +M\B/^XB01@B.L^NZ#_@0L?\/^"O/^$/$W`>)G5=(CK>(CKK($GYA4T_X(L_X1 +MJH[Z[I/X%()GR>G&TB.MDB.NL@2?T_D(L_D2DF9,@B.N\B47((B@\FAJ'?#X +M0N@R\/#4X.#D\_X/Z<:2(EP6Z3,+B1;(-J+)_E;JEK(B%*(B$["PU*"@Y+/Z +M#ZG&DB(T@B(SD)#4@(#DD_@/B<;R(ZW2(Z[B!)_S_0CC_1+29DS"(ZZR)1<@ +MS*"R;&H=\`#80L@RT-#4P,#DT_P/R<9&0?[HPMBRX.#4T-#DX_T/V<;"(BRR +M(BO`P-2PL.3#^P^YQJ(CK8(CKI($GZ/X")/X$H)F3/(CKN(E%R#_H.)O:AWP +M``""(B3R(B.`@-3P\.2#_P_YQL8K_G)D%,P>1N#]LJ$"`#NFH!"FHD24D@24 +MS!E&V_WR9!8,[,)D%(;8_0"(0O@R@(#4\/#D@_\/^<;B(B32(B/@X-30T.3C +M_0_9Q@89_@"2!)3B!)KQ,P&")"+2!<_Z^^/X&M/X%)/X&8)G5I(C_N(D$8(C +MK/(/`)KN@_X$P_X*\_X0XF=5TB.MDB.N^%2"!)_3^0C1-P&#^1&JZ?/^%.)G +MR=J9F<:"(ZWB(Z[R!)^#_@CS_A+B9DS2(ZZ2)1<@W:"2;6H=\`!6F:.R1>:E +MH?ZA-0!&B_X`Z,+8LN#@U-#0Y./]#]G&PB.MHB.NL@2?P_H(L_H2HF9,DB.N +M@B47()F@@FEJ'?``TB(LPB(KT-#4P,#DT_P/R<:R(ZV2(ZZB!)^S^0BC^1*2 +M9DR"(Z[R)1<@B*#R:&H=\`P*1GO^#`U&@?X`#`S&6O^R!)KR)"*2!<^"!)2S +M_QJ3_Q2#_QGR9U;B(_[2)!'R(ZSJW?/]!`P.P_T*X_T0X3K=@_\4\F?)V<:R(ZV"(ZZ2!)^S^`B3^!*"9DSR(Z[B +M)1<@_Z#B;VH=\(@A#`L,#`P9#`[PZ8/0R8/@S!#H$8"Y@PP(X(F#X@22@.X0 +MX+L0P+L0LD22AA;^TF)&(*(@\J`/\F)4Y9T!PB.MHB.NL@2?P_H(L_H2HF9, +MDB.N@B47()F@@FEJD```XB(DTB(CX.#4T-#DX_T/V<:&1O^(0O@R@(#4\/#D +M@_\/^<;2(ZVR(Z["!)_3^PC#^Q*R9DRB(ZZ2)1<@JJ"2:FH=\/(B).(B(_#P +MU.#@Y//^#^G&TB.MLB.NP@2?T_L(P_L2LF9,HB.NDB47(*J@DFIJ'?#B(A32 +M(A/@X-30T.3C_0_9QL(CK:(CKK($G\/Z"+/Z$J)F3)(CKH(E%R"9H()I:AWP +M``""(C3R(C.`@-3P\.2#_P_YQM(CK;(CKL($G]/[",/[$K)F3*(CKI(E%R"J +MH))J:AWP``P:O0+ET06A-0"&`OX`-D$`0J0,2D*R)(H`.Z8RT@$,#Z*F7JJB +M@@IU\D.4\F,6^6."0Y/@$*8`/Z;@P>7@V73R0YK29&K@X73B9&O"8Q&P$*8, +M_0S>#!RR8Q22(Q2"(Q0_2,)*B^)C%.)C%8(*?A:X`)(C%,)#DF:I +M`D8>`*(C%-<:2ZT"Y0D`@B1JTB1K\@.?X6@`@_T(\_T2TFY,PB1KLB25(,R@ +MLFQJ'?"R(Q06FP;W&U\+FY#P%/)#H?$V`>)C%)"20?"9H)@)F6/&YO^M`J6` +M`=(D:J(D:\(#G[%H`-/Z",/Z$J)K3)(D:X(DE2"9H()I:AWP@J$"`#BF\!"F +M\D.4X@.4#.D6'O?"8Q:28Q0&VO_28Q0&U/\`#,NR8Q3&T?\V80#B(E4RH-Q" +MI%A*0L(DE-(B5CHRX_P(T_P0`#RFL!"FH@/%#*N`JA&PJB``.J:0$*:")'0, +M"A:H"P`ZIH`0IHGCF.-2IEY04H"V206"H`&"18N2(QV2R?,6Z0F]`@P*9;D% +MTB1OHB16P3,!/#O:JM(D<);*"*>K!2Q^1@$``,KJX@X`HB16\@5U#`G:JI9J +M!Z>K!"QY!@$`RIJ2"0"R(RO"`[C2(QWS^Q3Q20#3^Q7#^QFR;U:B)*C2(QJ" +M)%:JW8/]!./]"I/]$-)O58CCPB17HB18L@/#T34`P_H(L_H1P3@!L6@`VMJ# +M_132;\G*JJG+'?"IX\;1_P"M`N7/!<;7_PP.QM[_AN3_-H$`#`PRT@%"T@." +M(D12I@1:4H+(_A:H0Y(#G;(#E19I0J(B2)T,LD.3%FI-#`[2)18,&PP*#'AB +M`Y.3^`J2)*YC^`O0JX.R`YVC^`\@F:"B`Y^2*6RS^!"C^!&3^!0`.*;"0Y3" +M8Q;)8Z`0IGAEH+%TH)ET&W<65SJR9*Z29*T,&8(E!O*A`J"QY188--(DQZ#@ +M!`O=TF3'LF,1DD.:PF,5PF,4%KTXXD.3<4D`T3,!H34`/#OB(Q1B!=AI06)# +MDF%H`!:>.?(B5`R-MD\%]L\"QE\`@B)4\"``ML@*#![B1>7B8Q3"8Q7R(E7B +M`Y/S_0CC_0X`/:;")*V")*[R`Y."8E/"8E(6_P'")+#2)*^"`YWPS!'PW1'2 +M9*_"9+`6>`#2)*T+W=)C$N`0IJT"XF)B978%#!J]`B6;!<(DQ;(DK#PZTB3& +MRKN6FT.WJ@0L?,8!`,$S`48"```` +MD3,!FIN2"0"R(E2B`Y33^!2S^!6C^!F"9U;R)/[2(E&!-0#B)*SZW?$U`>/] +M!,/]"I/]$-)G59(B1<(#G=(DKK(#GZ(B4L/]$+/]$8J-H_@(D_@4@F?)XB2M +M^MWC_0C9QL(B2XD7E\!"F\F,8`#RFMD\$#!B"1>60$*:28QG"(Q>"(Q7B +M(Q;R`Y.#_0B"(QCS_0[C_1##_12#_1B3_1P`/:;B)*[R)*W"`Y/R8Q+B8Q.< +MW-(DL.(DK\(#G?#=$?#N$>)DK])DL(QLXB2M"^[B8Q*V200,'_)%Y?`0IO)C +M(M(C(L(C(I(C(O(C(M#0%-)C&N(C(L#"%,)C&Y"4%))C'/#V%.#H%.D1XF,> +MXB,B@B,B\F,=X.H4@(P4XF,?Z2'B(R*"8R"),>#N%.)C(8(%V!;8!((%V^D! +M%M@[#!XF/0>($=*@`(#MDPP=)CP&B"$,#(#@`L>L9Z`-(#G8P=%CXP`#^FX!"FXD.3`#RFLF,1H!"F +M@B3'HF,5DB,5"X@;F9)C%()DQ\)#FL8I_P"20Y6R)1?"(Q/B(Q388]ESZ8,@ +MS*"R;&H=\````#RFLF2NDF2M@!"F@F3'1A/_``"2`YU6V<:RH0,`.Z:@$*:B +M0Y-&&/_"0Y/M#`P9QO;^`)T,#`[2`Y'20Y-&\_["`Y.1.0'#^0X`.:;R)*Z" +M)*WB`Y."8Q+R8Q.(G@Q9>(199(?(%Y@N99B_N#+\`/Z;B),7")*SJS):\(<>K +M/RQ\Q@\`@L[A%M@GDL[Z%BDAL3,!#-W"SOG`HD'28Q3`P!3"0Z&RRT"PJJ"H +M"J)C!JT"I04!AD'_#!D,'L;(_@#:S,(,`/(DQN(DK/KNEMX\8!`,$S`$U`?KXP_\(H_\4\F?)PB2M +MZHBM`L/X"(G&^)/YQNC3XF8,=JTBZ$G8.>#@U-#0Y./]#]G&LBI>2ZH6BP`F +M&TTF*S@F.P62R2`&Y_[H:=A9X.#4T-#DX_T/V<;(B;AYP,#4L+#DP_L/N<:( +MJ?B9@(#4\/#D@_\/^<9&\O^(:?A9@(#4\/#D@_\/^<;&[?_(B;AYP,#4L+#D +MP_L/N<9&Z?\``%89WPPMTD7F)>_]H34`/#O1,P&&=_\``*#@!.)#D\8^_PP, +MAHG_#`E&CO\`^$$,R()C%!8?X+*A`@`[IJ`0IJ)#E)(#E!;YW@SL#!W28Q;" +M8Q2&>/\,"D:G_PP+1JW_``P(V#$,"0P?#`S@SX/0GX/8(<"9$,@1T(^##`W` +MWX/"`Y+0S!#`B!"0B!""0Y*&%?^M`@S^XF,4988"!JK^```V00"2I@@RH1XZ +M,H(#@9HBD@+F@L@!@D.!@(!TEY@$#`B"0X&2(A*B$EJ2R0&28A*7&D6R(A6R +MRP&R8A6W&D"AK`"Q20!V@!+2`X'"*TT+JM=<"HR:X@+B)BX,AOG_S&H,+_)" +MXF7?_9`0IH("X(#ZX(DKM(E%Y/W"@P; +M#`G0FX,@B*"R`_7C]PNJB)/W#Y(#]X(H0K/W$)/W$8/W%``WIL)#[,)C+,)C +M')`0IOAUD-%TD+ET&_\6;R[29*ZR9*T,'X(E!]*A`I"QY18H)^(DQPONXF3' +MLF,G\D/RPF,KPF,J%OXLD(`$@D/K86@`'&OB(RIR!=QR0^KG.P)&(0`L^.>X +M`D8?`!QYEYX"1FH"P38!#-_2SNC0LD'R8RK0T!320_G`NZ"X"[)C'*T"$!$@ +M9<4`HJ"HPB,H@B,IL@/UD@/WP_@(L_@0D_@2@F9,D@/KXB,I@B,J%GDA\B,< +MTB2PPB2O(.Z@JN[`P4'0T4'29+#"9*_2)1CR8QV"8QZ20^W2;D`=\`R.TB,J +M<4D`L34`@LWJ%B@E\B)4/`B'GP+&3P(6370\#/<\`@9B``P=TD7ITF,JTF,K +MTB)5P@/KT_X(P_X.`#ZF@B2NDB2M\@/KDF)2@F)3G-_R)+"")*_B`_7P_Q'P +MB!&"9*_R9+",;H(DK0N(@F,HD!"FK0*28F)EE@0,&B"R("41!<(DK+A5HJ"H +M/#W*NY9+,[>M!2Q\!@(``,$S`)G5M(B48(E/K(D +MK-J(L_@$P_@*D_@0@F=5D34`@34!LB)%\@/UXB2NT@/WPB)2\_X0T_X1FI[# +M^0BS^1229\GR)*V*[O/^".G&TB))V<;"(DW)QL(B5)(B6@N\%ILIXLS^%KYK +MK*EF&0+&\`%F*3&X0I@RL+#4D)#DL_D/F<:"(B3R(B.`@-3P\.2#_P_YQH8# +M`-A"R#+0T-3`P.33_`_)QI(B6Q9I=V89`H;E`>+)_E8>XKC"F+*PL-20D.2S +M^0^9QH@C^!.`@-3P\.2#_P_YQ@:`__9-6`P%O9[`#VF +M@!"F@D/K`#RFLF,G@!"FDB3'@F,JXB,JXF,K"YF29,?"0_(&7O^20^VR)1C" +M(RGB(RK2(QS28QWB8QX@S*"JS+)L0!WPT(`$5AA>#"F28RK&A?\````\IM)D +MKK)DK>`0IN)DQP9#_P``@@/U5IC2LJ$#`#NFD!"FDD/K!DC_PD/K;0P,&48F +M_P"=#`P&T@/ITD/KQB+_G0P,!@8A_^)C*@`\ICWPD!"FDF,L`#RF#,B7N`+R +M1>F`$*:"8RT`/*8,S8>]`O)%Z=`0IM)C+@`\II*@#->Y`O)%Z9`0II)C+](C +M*\(#ZX(C+-/^",/^#M(C+<(C+H/^$-/^%,/^&)/^'``^I@S(E[@"\D7I\B2N +MDB2MX@/KDF,H\F,IG+[")+#2)*^"`_7PS!'PW1'29*_"9+`62``+V=)C*/`0 +MIO)C.-(C.,(C.)(C./(C.-#0%-)C,.(C.,#"%,)C,9"4%))C,O#V%.#H%.D1 +MXF,TXB,X@B,X\F,SX.H4@(P4XF,UZ2'B(SB"8S:),>#N%.)C-X(%W!:8!((% +MW^D!%AAE#!XF/0:($0P-@.V3#!TF/`:((0P,@-R3#!PF.0:(,0P)@,F3#!DF +M/P:(`0P/@)^3\@/JD(P0\/X0\/T0@/\0\D/JK0(E"00,&KT"9=X$PB3%LB2L +MHJ"HRKN6ZUP\/;>M02Q\!A$`#`R&-?\,"88]_P``%JE<"^D6CF#RR?Y6[[S( +M0K@RP,#4L+#DP_L/N<:2(B2"(B.0D-2`@.23^`^)QL;J_L$S`N!BQ]1@(```#1,P':V](-`)$^`.(C.((#Z_(#[)KN@_X4 +M\_X9XF=6LB3^@B,GDB2LNHBQ-0&3^`3#^`K3^!""9U7R`_6")*[!-0#B`_?S +M^!#R(RCC^!'*R.(C&[J(\_P(X_P4PF?)DB2M#$O-`I/X")T"B<;R(Q_YQN(C +M(^G&Q@$`PLP@2YD6N[#2*5X+NQ;M)0OM%MX;\LW^%K\19CWATBE:%BT-"XT6 +M6`AF+=.(3/@\@(#4\/#D@_\/^<;B+"32+"/@X-30T.3C_0_9QHAL^%R`@-3P +M\.2#_P_YQN(L)M(L)>#@U-#0Y./]#]G&B(SX?("`U/#PY(/_#_G&XBPHTBPG +MX.#4T-#DX_T/V<:(K/B<@(#4\/#D@_\/^<;B+"K2+"G@X-30T.3C_0_9Q@;4 +M_X(L)/(L(X"`U/#PY(/_#_G&XBPFTBPEX.#4T-#DX_T/V<:"+"CR+">`@-3P +M\.2#_P_YQN(L*M(L*>#@U-#0Y./]#]G&1L+_`(A,^#R`@-3P\.2#_P_YQNAL +MV%S@X-30T.3C_0_9QHB,^'R`@-3P\.2#_P_YQNBLV)S@X-30T.3C_0_9QD:R +M_P#2*5H6+08,+N)%ZN4N_:*@J+$U``:5 +M_Y"`!()#Z\8/_@P,AI[^#`T&I?X`#`S&I?\,"4:L_[A"F#*PL-20D.2S^0^9 +MQ@9__0P-F#$,#PP<#`C@C(.0_(.8(8#_$(@1D-R##`F`G(."`^J0B!"`W1#P +MW1#20^J&;_["(B2R(B/`P-2PL.3#^P^YQL9M_>(B%-(B$^#@U-#0Y./]#]G& +MQFC]@B(D\B(C@(#4\/#D@_\/^<:&J/^R(C22(C.PL-20D.2S^0^9QL9>_0`, +M&KT"I74$HJ"HL34`QF7_```V00`,"S+2`8(B1$*F)%*CO%I22D+HY(+(_A8H +M%I(#G0P:T@.5%OD4PB)(G0O20Y/`FH.B`Y,,'0P,#'B3^`K@S8.C^`OB`YVB +M)7_#^`_"`Y\@JJ"B*FSC^!##^!&C^!0`.*:Y8[)C%K)#E*`0IN*A`O(#G;)# +MFJ#`!!9O#L)#DP`[IJ"!Y:"9=*"Q=+)E?Y)E?H)C$?`0I@S[#-SR8Q22(Q2" +M(Q0_=])$Q<)C%,)C%<($N!:\`/(C%-)#DO+/]!8_#((C%+"(P!;H +M"2"B("4.`*%H`-(C$I(C$\(#G;(#G]/Y",/Y$+/Y$I)J3)(#D_(C$Z(C%!:I +M!"#_H.(D#](E@<(E@((C!M#10<#!0<)E@-)E@8ESJ8.20Y7B;VH=\*(C%!8J +M"/<:>0OZ\(`4@D.A@38!PF,4\/)!@/^@^`_Y8P;;_Y)#E;(C$\ACJ/32(Q39 +M@\ES(+N@HFMJ'?`````^IO`0IO)#D\;#_ZT"):L!AM?_LD.3#!F&K/^="X(# +MD8)#D\:I_P``/J:@$*:B0Y22`Y0,[!:I\M)C%L)C%$;(_P``LF,4QL'_#,_R +M8Q3&O_\``#9!`)(B5L(B50R(,M(!L@.3H@.:P_@(L_@.H_@/D_@0`#BF0J18 +M@@.32D*2)%BB)%>B8Q*28Q.)D6HQM\B17 +M"__R8Q*P$*:B`Z$,JX"J$;"J(``ZII`0IH(D=`P)%C@,`#FFP!"FR5."(Q38 +M4_+2!H+(\[9-!>*@`>)/Z1:8"B"R(**@`*5/!-$S`;(D;Z(D5L*@,^(D<+JJ +MEGH)IZP$+'L&`0#:NK(+`*(D5O(C(H(#E.JJX4D`ENH'IZP$+'D&`0#:FI() +M`,(#DZ(C%,/_%*/_%8/_&?)N5M(DJ*(C$<(D5MJJT34`P_H$L_H*D_H0HFY5 +M@@.=HB18P3@!\@.?@_H0@B,2\_H1VMKX4\JJ@_T(\_T4TF[)TB17P6@`T_H( +MJ)C5M(DJ,(E&O$[`>%H`-K,<_P*8_P0PF-5LB17TB18H@7#F.6S +M_0BC_1&*C?K=D_@4@F/)VG('`*(D<)8:"Z>K!2QV1@$``,IJ8@8`LB)5HB24 +M4J#<6E*S^@@`.J:0$*:")'$Q20"2IE_6R`*:(I&L`':`#H(C@PN9C*B,J:(" +MBR8J#8;Z_P#,:0PKLD*+Y=O\#+P`/*9&``":(I$Z`>(E*X("=/(%N)KN@_X4 +M@34`\_X9XF-6TB2HPB4:\3L!X6@`VLQS_`IC_!#"8U6R)%?2)%BB!<.8Y;/] +M"*/]$8J-^MV3^!2"8\G9SAWP#`?&T?\,!H;5_P``-D$`0J0,2D*R)(H`.Z8R +MT@$,"**F7JJBD@IU@D.4@F,6B6.20Y/@$*8<7X)#F@`_IN#!Y>#9=-)D:N#A +M=.)D:\)C$;`0I@S]#-X,'+)C%)(C%((C%!R?DF,5A[]&PDJ+XF,4XF,5@@I^ +MC'B2(Q3"0Y(FJ7NB(Q0]\-<:2ZT"Y0D`@B1JTB1K\@.?X6@`@_T(\_T2TFY, +MPB1KLB25(,R@LFQJ'?"R(Q06>P;W&UX+FY#P%/)#H?$V`>)C%)"20?"9H)@) +MF6-&Y_^M`F7E_](D:J(D:\(#G[%H`-/Z",/Z$J)K3)(D:X(DE2"9H()I:AWP +M''@`.*;P$*;R0Y3B`Y0,Z18.]\)C%I)C%,;9_])C%,;4_PS+LF,4QM+_```V +M00#B(E4RH-Q"I%A*0L(DE-(B5CHRX_P(T_P0`#RFL!"FH@/%#*N`JA&PJB`` +M.J:0$*:")'0<:19H"P`YIH`0IHGCDB,=4J9>J.-:4I+)\[9*!`P8@D6+%MD) +MK0*E(031,P&R)&^B)%8\/.(D<+JJE@H)IZP%+'M&`0``VKJR"P"B)%;R!74, +M">JJEJH'IZP$+'D&`0#:FI()`,(C*](#N.(C'?/\%/%)`./\%=/\&<)O5J(D +MJ.(C&H(D5JKN@_X$L_X*D_X0XF]5B./2)%>B)%C"`\/A-0#3^@C#^A'1.`'! +M:`#JZH/^%.)OR=JJJ-&TO^M`N4O!(;7_P````P+QMW_AN/_-J$` +M0M(#\B3-`#^F4M(&,M(!X@73XD.3#`[B0Y3B8E;B8D:@$*8)DQV%)`-$S`7%H`*$U +M`#P[PB)4#!_R0Y+LS,&6`)(DZLJ9`#FF@!"FD:P`@F,B=H`3XB:#"YD6;A<6 +M61?R!>KRS_X6SQ=&^?_2(Q3V30*&+P&V;`(&80#2S?L,#-#/@]*@$<)#G,*@ +M",)C%``]IH`0IH)C%@`]IK9(`O)%Z>`0IN)C%P`]IK9.`O)%Z8`0IH)C&``] +MIK9(`O)%Z=`0IH(C%8/\"((#D^(#FH/\#H(C%N/\#X/\$((C%^(C&-)C&8/\ +M%./\&-/\'``\IK9-`O)%Z8`0IH)C(N(C(M(C(L(C(O(C(N#B%.)C&X(C(M#4 +M%-)C'/#X%/E!\F,>@(H4B5&"8Q_R(R*"(R+`QA3"8QV`C!2"8R")88(C(O#P +M%/)C&H".%(EQ@F,A@@7<%M@%@@7?^3$6Z%\,'^DAB#'9$(DK8(DKM(#GY$U`./X"-/X$=A3FIBJB-/Y%`Q-DF;) +MB<>=`OB3^(?XG'Z)_IQT;R_P#8 +M/]G'R%_)QT;O_P"(/XG'Z'_IQT;L_P"H/ZG'1NK_`,$S`0S?XLWYX+)!\F,4 +MX.`4XD.APLQ`P+N@N`NY8ZT"):W_DB2M\B2N@@.?D_\(@_\2\F=,XB2NTB38 +M(.Z@TFYJ'?``9FVXH@7<#,NR8Q06NOP")*W2)*[R`Y^# +M_0CS_1+29TS")*ZR)-@@S*"R;&H=\`"B(Q62)2JC^0@`.::`$*8@HB""8R*E +MI0,@HB`EOP.R)*RH5;JJEIHC/#RG+`+&+@`L>X8O`+$S`;JZL@L`PB2LJ&7* +MJI9:(3P]IZT$+'G&`0"1,P&:FI()`-(C%((C(L(%TZ(#E-/X%(DK/K=X_T$L_T*D_T0TF95PB2M@B2NH@.?\34!P_@(H_@1H34` +MDB)%^OBJB)/X%()FR?G'XB))Z(DK/K=X_T$L_T*D_T0TF95PB2M@B2NH@.?\34!P_@(H_@1 +MH34`DB)%^OBJB)/X%()FR?G'XB))ZB)*WR)*Z"`Y^C_PB#_Q+R9TSB)*[2)-@@[J#2;FH=\)G'\B2MTB2N +MX@.?\_T(X_T2TF=,PB2NLB38(,R@LFQJ'?```*T"#/B"8E3E2/_2)*VR)*[" +M`Y_3^PC#^Q*R9TRB)*Z2)-@@JJ"2:FH=\#9!`#*F*%T"KOPWH/3^@^B9C[#^A&B9CZR*R2S^A2B9CZ0 +M$*:"`\',2((#PA8X`0PR'?"0$*8,(AWP`*`0I@PR'?``'`T`/:;`$*8,.\`K +MDQWP`#9!`#*F%**A(*JR@@M_.C*2`]H;B()+?X"`=)>8!8*@`()+?QP'/+;( +M\T+2!9(35!O,R?/`F<`6Z0GB)%?2%-X;[N)D5^#=P!8=#<(+?]+2;=(M--F# +MF(."(Q(,%"HR:@@/6 +M)B@,AOG_S&H,*9)#UF41_*(#UA::!`PR4+EE4,ATPF0M8+L0LF0L'?#`$*8` +M-Z;P$*;2)%CP@'3PN'3PD`629$>R9"V"9"[B)"[P^65@_Q`@[J#R9"P,(JKN +MTFXB'?```#>FT!"F5LWZ#`(=\-`0I@`WIH`0IN(D6("0=(#(=("P!;)D1\)D +M+9)D+O(D+H")96"($"#_H()D+`PRJO_B;R(=\``VH0!2T@,R)*=(C%!Q8US@*]DUF#!W28E0&'`""SNH6Z$$L^=>Y`@99`!QYHLWIS!K& +M_0'!,P'RH`WBS>C@LD'R8Q3@X!3B0Z'"S$#`NZ"R*P"Y8ZT"Y3C_DB6M\B6N +M@@.?D_\(@_\2\F9,XB6NTB78(.Z@TFYJ'?````?N"`PMTF)4A@$``.*@`^)B +M5)(C%8(D*I/X"``XIO`0IB"B(/)C(F4#`R"B("5;`[A4PB6L/#K2):S*NY8K +M,;>J!2Q\!@(``,$S`J!"QYQ@$`D3,!FIN2 +M"0"R!-.B`Y33^!6S^!2C^!F"9U;R)?[2(Q'B):SZW>/]!,/]"I/]$-)G5;(E +MK8(EKJ(#G_$U`;/X"*/X$:$U`)(B1?KXJHB3^!2"9\GYQN(B2>G&TB)-V<:B +M(E22(EH+NA8+*>+*_A9N1!89;0OY%@\N@LG^%F@MDB);%OEV"ZD6ZB.RR?X6 +M^R""):WB):[R`Y^#_@CS_A+B9DS2):[")=@@W:#";6H=\)+.T!8I=K(D*L*@ +M`<)$ZM!"QYQ@$`D3,!FIJ2"0"B(Q3B(R*"!-/R`Y2C_A6#_A3S_AGB +M9U;2)?ZB(Q'"):S:JL/Z!+/Z"I/Z$*)G59(EK>(EKH(#G]$U`9/^"(/^$8$U +M`/(B1=K>BN[S_A3B9\G9QL(B2=)&L``N9@B>#%IA3 +M%IE3P@3J"YEF+.X,O@`^IN(EQ<(EK.K,ELQ6QZL$+'X&`0#:[.(.`/(EQL(E +MK/K,EJQ5QRL"1KT`T@33DB,BP@.4L@.:T_D4P_D9L_D:DF=6@B7^\B,1DB6L +MBO^3_P0L>./_"H/_$($W`?)G5=(EK?(EKL(#G[A3T_\(P_\1JI^*_[/Y%))G +MR?G&TB6MLB6NP@.?T_L(P_L2LF9,DB6N@B78()F@@FEJ'?#HLNG&PB(KR<:R +M):V2):ZB`Y^S^0BC^1*29DR"):[R)=@@B*#R:&H=\,(B*\G&LB6MDB6NH@.? +ML_D(H_D2DF9,@B6N\B78((B@\FAJ'?`,#`8^_P`,"<9#_P```!9)7B89+M+) +M_E9]V.@RZ<;"(B/)QK(EK9(EKJ(#G[/Y"*/Y$I)F3((EKO(EV""(H/)H:AWP +MPB(CR<:R):V2):ZB`Y^S^0BC^1*29DR"):[R)=@@B*#R:&H=\-@RV<;B(B/I +MQ@9'_QP=#(F28Q0`/::`$*:"8Q8`/:8,SX>_!>*@`>)$Z8`0IH)C%P`]I@S/ +MA[\%DJ`!DD3I\!"F\F,8`#VF#,[WO@6"H`&"1.G@$*:"(Q7B8QGR)>J2(Q?2 +M(Q:#_PB"(QC3_Q"3_Q2#_QCC_QP`/Z8,S>>]!`P9DD3I@!"F@F,BXB,BTB,B +MDB,B\B,BX.(4XF,;@B,BT-04TF,<\/@4^4'R8QZ`BA2)48)C'_(C(H(C(I"6 +M%))C'8",%()C((EA@B,B\/`4\F,:@(X4B7&"8R&"!-P6Z`6"!-_Y,18H1PP? +MZ2&(,=D1F0$F.`;800P)T/F3B"$,'B8X!]A1DJ``T.F3B!$,'28X"((A!I*@ +M`(#9DX@!#!DF.`J(<2F!#`*`DI,H@8(#DH"/$(#N$)"-$(#N$.)#DJT"Y6`" +MK0(E#@.R)<6B):RZJI8Z/SP\IRP"QCD`+'J&.@```!;)/@O9%KTXXLG^%AXX +MDB)<%KE#)ADP\LG^5J^[@B(3B<;B(C/IQM(EK;(EKL(#G]/[",/[$K)F3*(E +MKI(EV""JH))J:AWP`.(B,^G&TB6MLB6NP@.?T_L(P_L2LF9,HB6NDB78(*J@ +MDFIJ'?#R!-/:G+(C(M(#E,(#FO/[%-/[&M!BQ\1@(```#!,P'*R\(,`($^`-(C(O($T^(#E(K=\_T4X_T9 +MTF=6LB7^@B,1DB6LNHB3^`2Q-0"1-0&C^`K#^!""9U7R):V"):[B`Y_84_/X +M"./X$;JXFHC3^Q2=`K)GR8G&#$OXD_G&Z-/IQNT"1@P`````9BHCV#[9QL(N +M(\G&J%ZIQH(N)8G&^'[YQM(N)]G&R)[)QJ(N*:G&XLX@2YD6NZ.B*5X+NQ;Z +M"B8:<"8J-68ZYJ(I6IR*9AJWPBXCR<:B+B6IQH(N)XG&\BXI^<;&\?^H/JG& +MB%Z)QOA^^<;8GMG&!NW_`*(I6JQJ)AH79BJHB#Z)QO(N(_G&V%[9QL(N))QH;2_]@^V<;(?LG&QL__HBE: +MG%HF&@ORROY6'_."+@."9@RB+B.IQL;(_\@^R<8&Q_\`5MFL#"W21.HE@/NA +M-0`\.]$S`8:N_N@RZ<9&3/X,R()C%!;_@0`YIK`0IK)#E*(#E,P:A@/^#.P, +M'=)C%L)C%$8`_@`,"89L_@P+1F3^#`Z&IOX`\@33LB,BT@.4P@.:\_L4T_L9 +MP_L:LF=6@B7^TB,1\B6L#`F*W?/]!./]"I/]$-)G5<(EK;(EKOA3@@.?P_L( +MP3K!2QW +M1@$``,IZ<@<`HB1PENH.IZL%+'9&`0``RFIB!@#B(E4,BU*@W%I2T@6WP@6^ +MX_L(T_L.P_L/`#NFDB18HB17@@6WHF4;DF4&PO\,!D;&_P`,*9)*@*5-^\;A +M_P`V00`,"3+2`4*F)%*CO((B1%I22D*"R/X6R!:B`YT,&](#E1::%<(B2*T) +MTD.3P*N#R.0,'0QXL@.3H_@*HB5_L_@+#`L@JJ#`O8.S^`_"`YVR`Y^B*FS# +M^!"S^!&C^!0`.*:98Y)C%I)#E*`0IN(#G:#P!/)#D]PNX@.='$\`[A'P[B`` +M/J;`$*;"0Y,<6``XIJ#!Y:#A=*#Y=/)E?N)E?Y)#FL)C$;`0I@SL!"QY!@$`VIJ2"0#"`Y.B(Q3#_Q2C +M_Q6#_QGR;E;2)*BB(Q'")%;:JM$U`,/Z!+/Z"I/Z$*)N58(#G:(D6,$X`?(# +MGX/Z$((C$O/Z$=K:^%/*JH/]"//]%-)NR=(D5\%H`-/Z"*G,'?`,#=E3!M#_ +M`*T"99D"QM3_#`O&V_\,"0;B_P``-D$`LB)5#(A2H-Q:4J(%MY(%OK/X"*/X +M#I/X#P`XID*D6$I"HB1OP3,!/#N6&@ZGJP4L=T8!``#*>G('`*(D<)8J#:>K +M!RQVQ@$`````RFIB!@"B)%B2)%>"!;>291NB91R&R?\,!L;-_P`,*9)*@"4*^\;A +M_P`VH0`,#3+2`4+2`PQ_@B)$4J8D6E*"R/X6&$J2`YT,&L(#E1992+(B2)T- +MPD.3L)J#@@.3N.63_PH,&@P)L)J#@_\+H@.=@B2ND_\/D@.?((B@@BALH_\0 +MD_\1@_\4`#^FV6/28Q;20Y2P$*;H0\(#FK"1=!;>/:(#D*)#FI)DKO(#G1Q. +M#!D67SX,"HQ,@@.:@*F#%HI`#`K(0\+,_A8L08(#G0"($>"((``XIO`0IO)# +MD]E#O#J!0`$`.*;P$*;(0_)#D*(#D!O,R4/"((``XIO`0IO)# +MDZA#P@.3PD.1&ZJI0^(#FK#!Y;"I=!9>.-)B5=)B5*)DK=)DQ\)B40R,<4D` +M86@`H34`/#OB(Q3R!;CY@?)#DO$S`18^.O(B5+9/!?;/`H9=`((B5/`@`+;( +M"@P>XD7%XF,4TF,5XB)6TB)5@@.3\@.:T_P(@_P.\_P/X_P0`#RF@B2NTB2M +M\@.3TF)2@F)3%O\!\B2P@B2OX@.=\/\1\(@1@F2O\F2P%GX`@B2M"XB"8Q*0 +M$*:M`I)B8F4Z`JT"Y5,"PB3%LB2L/#K2),;*NY9;1+>J!BQ\1@(```#!,P'* +MR\(,`+(DK((B8MJ[T@.3EJM"MZH&+'E&`@```)$S`9J;D@D`LB)4H@.4T_@4 +ML_@5H_@9@F=6\B3^TB)1@34`XB2L^MWQ-0'C_03#_0J3_1#29U62(D7"`YW2 +M)*ZR`Y^B(E+#_1"S_1&*C:/X")/X%()GR>(DK?K=X_T(V<;"(DG)QK(B3;G& +MPB)4F#(+K!:J.^+,_A:N.IG&^++YQK(C$H(C$Z(#G9(#G[/X"*/X$)/X$H)F +M3)(#D](C$_(C%!:I&R#=H,CULB2PHB2OZ&.PL4&@H4&B9*^R9+#I<_F#DD.5 +MPFUJ'?```+9N`H:F`,)C%-+.^PP9#`C0B8,<'8)#G``]IO`0IO)C%@`]IK9/ +M!`P>XD7%\!"F\F,7`#VFMD\$#!B"1<60$*:28Q@`/::V200,'=)%Q?T,X!"F +MXF,9DB,5@@.3TB,6D_\(@_\.DB,7@B,8T_\0D_\4@_\8X_\<`#^FMDX$#!W2 +M1<7R)*Z2)*WB`Y.28Q+R8Q.)DK])DL!9(``OI +MXF,2@!"F@F,BXB,BTB,BDB,B\B,BX.(4XF,;@B,BT-04TF,<\/@4^4'R8QZ` +MBA2)48)C'_(C(H(C(I"6%))C'8",%()C((EA@B,B\/`4\F,:@(X4B7&"8R&" +M!;@6^`6"!;OY,1;X-@P?Z2&(,=D1F0$F.`;800P)T/F3B"$,'B8X!MA1#`G0 +MZ9.($0P=)C@&B&$,"8#9DX@!#!DF.`J(<2FA#`*`DI,HH8(#DLF1/?"`CQ"` +M[A"0C1"`[A#B0Y+)D:T"I2,!K0+E*P+"),6R)*RHD,(DK<+,_\)C$M`0 +MII&L`-)C(@N9XB>#%IX=%ID=@@7&"YEF*.X,O@`^IM(DQ<(DK-K,EDP=QZLX +M+'P&#@`<[^>_`H9F`(+.^A:8(*$S`0SK!"QY!@$`^IV2"0""`Y/2 +M(R+R`YKB`Y2#_13S_1KC_1G29U:R)/[R(Q&")*RZ_X/_!,/_"I/_$/)G5?A3 +MX@.=@B2NT@.?LB,2X_@0T_@1T30!JNBS_@CS_A3B9\FR)*W:B+/X"(G&!AG_ +M#`R&\?X,"4;X_IG&HB(3J<8&%/^9QL82_\$S`N!BQY1@(```"1,P&:FY()`((#D^(C(@Q+\@.4@_X4H_X5\_X9XF=6TB3^ +M\B,1@B2LK0+:_X/_!,/_"I/_$/)G58A3X@.=\B2NDB,2T@.?X_\0X34`T_\1 +MT34!ZN^3_@B#_A3B9\F")*W:_YT"@_\(^<;HD^G&V-/9QG:K$K(J7DNJO'LF +M&RDF*QLF.P62R2"&Z/[H.>G&V%G9QLAYR<:XF;G&AOG_B#F)QOA9^<;&]O_( +M."?@]"9$-A!#`[0[X/2`Y+)D>#=$-"($)"($()#DH8L +M_^B!#,_R8Q06GN`<>@`ZII`0II)#E((#E!:(WPSK#!S"8Q:R8Q3&>O\````V +M00`,!)*F(#*A'CHR@@.!FB*2`LZ"R`&"0X&`@'27F`)"0X&(PJ(23AN(B<*' +M&D28\AN9F?*7&E:AK`"Q20`,%7:`$M(#@<(K30NJUUP*C)KB`LHF+@R&^?_, +M:@PO\D+*Y8KZD!"F@@+)S#BB`LJ,F@PR'?"P$*8,(AWPP@-_G-P<#@`^IM`0 +MIHR]##(=\`#P$*8,,AWP`$)#?PP"'?``4D-_#`(=\``V00`,#3*F%**@^*I" +M@@2G.C*2`]J"R`&"1*>`@'27F`+21*<<#L*@^SRWF/-2T@6"$U0;F9GSD(C` +M%B@,\B57LA7>&__R95?PN\`6JQ*2!*>RTFVR*S2Y@XB#8B,2#!^3^`R)@YB# +M#`M@OX.S^0^9@V`0IF"`=()E+O(E+K(C$R#_H*K_LF\LDB4NB(,@F:"JF9(I +M+K%)`*&L`)/X$()C"':`$H($I_(K30NJAU\,C+J2`]8F*16&^?\``,S:#"JB +M0]9E>OK"H/L,#1P.L@/5S$OR`]86OP:"!*4H@V"Y96"1Y6"H=*)E+<"9$'"[ +M$+)E+))D%8/R&"F###(=\```T!"F`#ZFT!"FT)'ET+ATLF4MP)D0T+EE<+L0 +MT-!TTF4N@B4NLF4LDF05((B@JH@B)5@B:"SR!*78@PPB\_T8V8,=\`#R!*46 +M+P@`/J:`$*86B`8,,J($I9B#8.EE8+'E8-ATTF4MP+L0<.X0XF4LLF05H_D8 +MF8,=\/`0I@`^IO`0IH(E6/"QY?#8=-)E+<"[$/#997#=$/#P=/)E+I(E+M)E +M++)D%2"9H*J9@FDL(@2E^(,C_QCY@PPR'?#21*4H@X($I8/R&"F##`(=\)B# +M#!NR1*6B!*4,`J/Y&)F#'?`VH0`,#`P=0M(#@B)$4J8DHJ"HJC):4NCE@LC^ +M%IA)D@/UL@/M%OE'D@/RLD/K#'BR`^N3^`J2)*ZS^`L,"^"]@R"9H-(#];/X +M#ZJ9L@/WDBE"T_@0L_@1D_@4`#BFPD/LPF,LPF,)C +M&MS[X@/U`.X1\.X@`#ZFL!"FLD/KXB,:@@/K@D/IXLX!XF,:T.'E\@/R'%O0 +MV7067RW"8E7"8E329*W"9,?B8E$,C7%)`&%H`+$U`#P_@@6XXB,JB8&"0^H6 +M?CGR(E0<6?Y`H9V`!Q[MYX" +M1A8"P3,!#-_2SNC0LD'R8RK0T!320_G"S$#`NZ"X"[)C'*T"I1__HJ"HQDX` +M!^X)#"[B8RK&`0```/*@`_)C*O(#Z^(B5H/]"//]#N/]$``]II(DKL(DK8(# +MZ\)B4I)B4Q;H`<(DL-(DKY(#]?#,$?#=$=)DK\)DL(QITB2M"]W28RC@$*:M +M`N)B8B56`:T"):X!HJ"HTB3%PB2LL34!/#[:S)9L/<>N!"Q]Q@$`T3,!VMS2 +M#0#R),;")*SZS)8,/,>N!"QYQ@$`D3,!FIR2"0#R`^N"(F+B(E3"`^SS^!3C +M^!7#^!F"9U;R)/["(E'B)*SZS./\!-/\"I/\$,)G59(#]8(DKL(B1?(#]Y/X +M$)$U`.(B4O/X$9J8X_D(P_D4DF?)DB2MNHB3^`B)QO(B2?G&XB)-Z<:R(E22 +M(EH+RQ9L-(++_A;(3A:Y;;+)_Q8[;L+)_A;<;I(B6Q8);=+)_Q:=;>+)_A9^ +M;K(C*/(C*9(#]8(#][/_")/_$(/_$O)F3)(#Z](C*?(C*JR)XB,)C'?)C'I)#[<)M0!WPDD/MV/7B(RF"(RKR +M(QSR8QV"8QX@[J"J[M)N0!WP``#RSM`6#VWR`^N"H`&#_0B"1<6"8E7B(E:" +M8E3S_0[C_1``/::2)*[")*V"`^O"8E*28E,6Z`'")+#2)*^2`_7PS!'PW1'2 +M9*_"9+",:=(DK0O=TF,HX!"FK0+B8F*E.P&M`J63`=(DQ<(DK**@J+$U`=K, +MEJQC/#['KE)B4?)DQX`0IH)B5/(B5/)B5<9&_PP+T(`$ +M@D/KQBS_T3,!VMS2#0#B),;")*SJS)8,73P_QZ\$+'G&`0"1,P&:G)()`/(# +MZX(B8N(B5,(#[//X%./X%(DK/K,X_P$T_P*D_P0PF=5 +M@@/U\B2NDB)%X@/W@_\0@34`PB)2X_\1BH_#^`B3^!2"9\F")*VZ_X/_"/G& +MXB))Z<;"(DW)QI(B6A9Y50N)%EA6LLG^5COBV#+9QL(B(\G&QH7_PD/K#!E& +MW_[B`^GB0^N&_OZ=#/(#Z?)#ZT;:_L)C*H(C*Y(#\N(#ZX/]"((C+./]#I/] +M#X/]$``]II(DKN(DK8(#Z^)C*))C*:P(PB2PTB2OD@/U\,P1\-T1TF2OPF2P +M%ID`TB2M/?`+W=)C*(`0IN(DQX)C.);.59&L`#WP"YG")X,6G$,6F4/2!<8+ +MF68M[@R^`#ZFTB3%PB2LVLR6;$K'KP0L?,8!`-$S`=K,P@P`XB3&TB2LZMV6 +M#4G7KP0L><8!`)$S`9J=D@D`\@/K@B,XX@/RT@/L\_@4X_@:T_@9@F=6\B3^ +MTB,GXB2L^MWC_03#_0J3_1#29U6"`_7R)*[B`_?2(RB#_Q#C_Q&"(QNZ[]/^ +M"-$W`8/^%.)GR8(DK=K_@_\(^<8&._\`#`W&#/\,"482_P``%NE#"XD6"$2R +MR?Y6&\W8,MG&PB(CR<9&,?\<'-)C*@`\IO`0IO)C+``\I@S.][X$#!B"1<7@ +M$*;B8RT`/*8,R>>Y!?*@`?)%Q9`0II)C+@`\I@S(E[@$#!S"1<6-#?`0IO)C +M+^(C*Y(#\L(#Z^/X".(C+,/X#I/X#\(C+9(C+N/X$,/X%)/X&//X'``XI@S. +M][X$#!_R1<7")*Z2)*V"`^N28RC"8RD6R`'R)+"")*_B`_7P_Q'PB!&"9*_R +M9+`63@`+B8)C*(`0IH)C..(C.,(C.)(C./(C..#B%.)C,8(C.,#$%,)C,O#X +M%/E!\F,T@(H4B5&"8S7R(SB"(SB0EA228S.`C!2"8S:)88(C./#P%/)C,(". +M%(EQ@F,W@@6X%N@%@@6[^3$6V#,,'^DAB#')$9D!)C@'R$&2H`#`^9.((0P> +M)C@&R%$,"<#IDX@1#!PF.`:(80P)@,F3B`$,&28X"HAQ*:$,`H"2DRBA@@/J +MV9&`CQ"`[A"0C!"`[A#B0^K9D:T"I:@`K0+E50&BH*CB),72)*RQ-0'(D>K= +MEFTI/#_7KSTL?@80``"<*0N)%E@J9BD/N#*YQI(B(YG&Q@``R#+)QI(B7!9) +M*`O9%OTHXLG^5HZP@B(3B<;R(C/YQL:^_N$S`>KMX@X`\B3&TB2L^MV6720\ +M.->H!"Q]Q@$`\3,!^MW2#0"2`^OR(SB"`^R3_Q3#_Q6#_QGR9U;")/Z2(R?* +MF<(DK,/Y!./Y"M/Y$))G58(#]<(DKO(#]]$U`(/\$//\$8(C*/(C&]K<@_T( +M\_T4TF?)TB2MNLS3_`C=`LG&DB,?S0*9Q@Q)@B,CB<:&"P!F*R.(/8G&\BTC +M^<;H7>G&LBTEN<:(?8G&\BTG^<;HG>G&LBTIN<;2S2!+S!:YH[(L7@N9%OL* +M)AMP)BLU9COFLBQ:G(MF&[>"+2.)QO(M)?G&XBTGZ<:R+2FYQL;Q_X@]B<;X +M7?G&Z'WIQKB=N<8&[?\`LBQ:K&LF&Q=F*ZB(/8G&\BTC^<;H7>G&LBTEN<;& +MY/_B+2/IQK(M);G&AN'_B#V)QOA=^<;&WO^R+%JLJR8;&^++_E;>]N@]Z<:R +M+2.YQHA]B<;R+2?YQ@;6_P""+2.)QO(M)_G&AM+_Z#WIQKA]N<;&S_^R+%J< +MVR8;$_++_E8?\[@]N<:"+2.)QD;)_P``XBTCZ<;&QO_X/?G&!L7_`%;9O`PH +M@D7&9='YHJ"HL34`/#^&[OZ8,IG&!DK^N+*YQL9,_L(B(\G&1D;^TB(KV<;& +M2/[X,OG&XB(CZ<9&0?Z8LIG&B!.)Q@9#_@#(@0S-TF,JS!P&[OT`.Z;P$*;R +M0^SB`^S,'L;I_0SH#!F28RR"8RJ&YOT,#0:)_@`,"<:._K@RN<;&,_X,#,;8 +M_@P)1M[^``#"(B/)QL8N_L)B1JT"#/W28E1EJ_ZBH*@&*OX`#`Z&:_\,#89Q +M_^@RZ<:&)?[R(B/YQH8C_H(B$XG&AB'^DB(CF<8&6?^R(C.YQH8=_NAAR%$, +M'PP(F''`CX,,#)#/@PP)X)^#P)D0R$$,#L#O@\(#ZMF1X,P0P(@0D(@0@D/J +MQCC_K0)E)`&BH*BQ-0`\/\:K_@``-D$`4J/`#`=R8DE:4E(E?PP60M(!MB4% +M@@2<%E@,70(,27:I&Z(B6B8Z$$(B7CWP%L0))A1U)B1.)C0'4L4@2R(=\``` +M-J:0$*:9-0`VIH`0IHE%`#:F,!"F.54`-J;P$*;Y90`VIN`0INEU`#:FT!"F +MV84`-J;`$*;)E0`VIK`0IKFE!NW_```VIM`0IMDU`#:FP!"FR44`-J:P$*:Y +M50`VIJ`0IJEE!N3_```VIH`0IHDU`#:F,!"F.44`-J;P$*;Y=0`VIN`0INF% +M!MO_```VIJ`0IJDU`#:FD!"FF44&UO\`@B):)B55)C@'`#>FL!"FN93")!LF +M/!``-Z;@$*;8E*#N$>#=(-)D"?(D'"8_$0`WIE`0IC(D"4!5$5`S(#)D"8(D +M'8+(_18([P`WIJ`0IIB4X*H!H)D@F91&M_]2H0(F.`T`-::P$*:PL'2PML"Y +ME,(D&R8\%0`UIN`0IMB4X.!TX.;`H.X1X-T@V93R)!PF/Q4`-:9P$*8XE'!P +M='!VP$!W$7`S(#F4@B0=@LC]%HCH`#6FH!"FF)2@H'2@IL#@J@&@F2"9E,:; +M_P``-D$`,M(%#`B"8DDR(R]"H.!*0K8C!8($O!:(%Y(D(AR\)CDC`#RFL!"F +M84$!4B)><4(!LF(#HL7_%OH*TL7^%MT,XL7]%KX.43X!\B0C)C\B`#6F,!"F +M84,!4B)?<40!.;)F%0+&(P""Q?X6V`J2Q?T6^0VB)"3!/P$F.B(`/*8]\+`0 +MIF%%`5(B8'%&`;)B$R85;V8E`D8C`-+%_18]#>(D)4%'`28^'P`TIC`0IE%( +M`4(B86%)`3)B&POT%@\4@L3^%E@4)C0"'?```#:FP!"FPF(=`#6FL!"FH4H! +MLF(?`#JFD!"FDF(A'?``-J;0$*;9<@;4_P``-J;@$*;I\@;<_P``-J;P$*;R +M8A?&X_\`-Z8P$*8Y4@;+_P``-Z:`$*:)T@;3_P``-Z:0$*:28A7&VO\`-Z;0 +M$*;94@`VIL`0IK%+`FL!"FLF(5`#:FH!"FD4T!HF(7`#FF@!"F@F(9 +MAL+_PB):)CP,')X`/J8]\-`0IM)D$?(D(R8_%($\`0`XIE`0IC(D$:!5$5`S +M(#)D$9(D)"8Y%L$]`0`\IK`0IJ(D$3WP0+L1L*H@HF01TB0ETLW]%BWC,4X! +M`#.F\!"FXB01X/\!\.X@XF01AH;_`#6F@!"F@F(?'?``-J:0$*:28AT=\``V +M00!BH\`,!5)B26IB0B9_#!>"H0*V)&J2Q/Y"(EH6:2#=(-)B24(B7284%"8T$0`UIC`0IO(B2>`S`3#_(/)B25)B34(F +M@+8D9)+$_D(B6A9)*(RD)C0(`#6FH!"FHF)-0B);G#0F-!$`-:;`$*:R(DV@ +MS!'`NR"R8DU"(ER<-"8T$0`UIN`0IM(B34#N$>#=(-)B34(B79PT)C01`#6F +M,!"F\B)-X#,!,/\@\F)-30(@4B""H`1VJ,!B)%H+EA8Y"Z+&_1;:"F(D7A9V +M"286<"8F2;+&_5:["0`WIJ`0IJDU`#>FD!"FF44`-Z:`$*:)50`WIC`0ICEE +M`#>F\!"F^74`-Z;@$*;IA0`WIM`0IMF5`#>FP!"FR:4&%@```#>FX!"FZ34` +M-Z;0$*;910`WIL`0ILE5`#>FL!"FN64�```#>FD!"FF34`-Z:`$*:)10`W +MIC`0ICEU`#>F\!"F^84&!````#>FL!"FN34`-Z:@$*:I15+%($M$30(,3':L +MT%(B6A95#-+%_1;]"U(B7A95"B85>B8E4.+%_5;>"@`WIM`0IM)D(P`WIL`0 +MIL)D)``WIK`0IK)D)0`WIJ`0IJ)D)@`WII`0II)D)P`WIH`0IH)D*``WIC`0 +MIC)D*0`WIO`0IO)D*H88```WIH`0IH)D(P`WIC`0IC)D)``WIO`0IO)D)0`W +MIN`0IN)D)L8.```WIL`0IL)D(P`WIK`0IK)D)``WIJ`0IJ)D)P`WII`0II)D +M*`8%````-Z;@$*;B9",`-Z8]\-`0IM)D)$+$($LB'?``)A01)C0.`#BF\!"F +M\/!T\/?`\F))0B);)A0<)C09`#BF0!"F,B))/?!`0'1`1\"@1!%`,R`R8DE" +M(EPF%!HF-!<`.*:@$*:2(DF@H'2@I\!`JA&@F2"28DE"(ET+M!:;V,+$_18\ +MV``XIN`0IM(B2>#@=.#GP.#N`>#=(-)B209:_YPD)C00`#BF\!"F/?#P\'3P +M]\#R8DU"(EN"^<63@@F)W$F-TH;9E+%($M$#`4F,!"F.94&Y/^PZ"``/J;0 +M$*;958;@_P``H#@@`#.F\!"F^76&W/\``*`W(``SIO`0II#G(/)D)0`^IM`0 +MIK#'(-)D)P`\IF`0IF)D*4;B_P"@UR``/:;`$*;"9"5&WO\`D/<@`#^FX!"F +MXF0G1MK_`#9!``P6HJ$"0B)44J/`#`F28DF28DU:4@LT%B,;@L3^%E@-#= +M(-)B24(B6E(E@+8E+O+%_A9O&8R4`#FF/?`P$*8R8DV"(ER<*``YIK`0IJ(B +M33WP0+L1L*H@HF)-0B):)A00`#:FT!"FV3(`-J;`$*;"8@3B(EPF'A$`-J8P +M$*8R8A,`-J;P$*;R8A2"(EJ<"``VIJ`0IJ)B(P`VII`0II)B)+(B7)PK`#:F +MT!"FTF(S`#:FP!"FPF(T'?`=\```0B)B0$`40F):@H!2B92&`$*:)0AWP +M`#FF\!"F\/!T\/;`\F))`#FFX!"FTB))X.!TX.;`0.X1X-T@TF))!L?_`#9! +M`#+2!0P(@F)),B,O')JV(Q$`.J:0$*9"(E228DDF)"8F-$H*A`@`^IK`0IK)"P/(B$:S/`#VF +ML!"FN>*8XAR8ER@>N.)L;=/]"``]IAWP`(($<@N(5BCVD@2#5AGV1M;_#"JB1(XEG?C&\?^RS#2R:G!& +MZ/\````V00`O"(+* +MS()L?T8!`)9Z!:)L?Y&L`*%)`':`#K(J@PN9C)N\:<(#CB8L!(;Z_ZRYT@.. +MC!T=\`""(A'R`L`,OH/^"?/^"``^IAWP`)(#<@N95BGVL@.#5AOV1M;_#"S" +M0XXECOC&\?_2RC32;']&Z/\````V00`,';*CM+JRHBM_`#VFP!"FPF)#DB)# +M')B7*!_"(D-L;=HEL9HEL8 +MHEL74,:"HEL6P-R0H,P1D-T1VM,+W0Q*HDN$@DF!XFD>HDF`#"XPH�VA#2 +M:2&"2X?:C8)I).)+B(J-BMV0Y1&":2?JXPON\DN)TF2IX.H0ZMW`X4'2:QLZ +MS`O,P,H0VOSR:QSZS/J.@FL>VN[B:QW"9*A7MA(,#)*@_\"%$8J#"XB`JA#& +M`P``#`R2H/_`UA':TPO=T*H046@`,7(`HFM0JNK":R[B:W*J[N)KE,$W`*KN +MXFNVJN[B:]BJ[N)K^J(LK-%)`.@$H+`$!VH2?.B`BA"";*S`(`#R+*SY`<`@ +M`))G@O(N)X%C`2&/`##_(/)M@L`@`#(M@B)MFL`@`/(MFH)MA3(N+#DE(BXK +M(FW"\BXF\FU"XBXGXFV"P"``TBV"V0'`(`"<"PP"HFRLP"``@BRLB0'`(``= +M\`P"'?```#9!``P[#!I2(DN2(SIR(SN"(SA"U0)BU0>0PP2"R/X66!NB1)ZB +M$WR0M`2B5+20I02"$WV"5+7R$WZ0A@3R5+:0]P3B$W_B5+?2(T!PY`729=S" +M1C["1CEPU06"1C;R1C&R1CBB1C?B1CK21C)PY@1PUP1PI01PM`1PPP1P\P4, +M"()&4?)$G\)&-<)&VK)&-+)&V:)&,*)&V()&U8)&U/)&.])&UN)&UW#8)7#L +M)7#X!'"+!'"@!'"Q%'#`)<)&/+)&VW#/!;)$DZ)&W'"[!:)$D:($GH)&W8)$ +MDO)&Y.)&YM)&Z,)&Y;)&YZ+*_18*#]ACR'.XT\#=$=)41M)43,#,$<)41\)4 +M319+$.C3^^[@Y$'IA;AS?.P;N\"[$+F5HB,6B`70JA&B99CR*"#@ +M%.D1V!$F/0(&^O^"TPB"*"&"8G@F)`6,)`P2'?`,`AWP````)5(%30J&X?\` +M```V00#E.^Z(`I%)`((H)X)I@IBR#`.V*04RR?[&__\,2Z@"V.+"H(S*JC`] +MLJ>3R`+14P#295-B95G"+"RZL@PMT_P$R26B +M!X_""X62`EK2"WV""X?R"X"3_0&#_0.2!WV"!X+S_07C_08,#^('HL/]$@N( +M#!RC_123_16`_(/S_1WC_1[293BB"WFY$:+*_A;J$PP)#%Z9E3)E1?('@@P& +MTJ#X\L_^%C\420%'LUH,#S!$P+(BE@8!`!O_1Q](#`H66_\ZS\8"``"R94RR +M(I8;JK>ZY+T*P_L(C0OC^!33^!B)Q6)E#)(BEH*@")PF4X,BFL +M,$`$!V,1HJ_^H*,0HFFLP"``@BFLP"``R`+QD@#B+"WP[B#B94+`(`#2)4+` +M(`#"+"W"94+`(`"R)4+`(`",Q#)IK,`@`((IK,`@`!WP'?#1E@"B"WV2`EJQ +M;P"@K).\6:#;DYT-1JK_````%H/K\B<7"\,+_\/_"./_%-/_&/G%:<6R)Q<+ +MN\/["+)E3(:E_PSF1H3_``"@O9.="X:<_S9!`'SVTJ?=#$L,*`P*#!E"HGA* +M4I)%-W(%?*FRJ:(`=R."13:!9P%P=Y`@=Z"*=[)'"(+2"(((#?*@_N*@_3+( +M_Q:C&++(_19+&,(BW)")(!8,!<(%K#(%LI)%@@"\(W?L!3+#_Q:C(8)%LF)% +MK;(5/,(5.S(5.C)54L)54[)55,(%?+(%?C(5/3)55;)%KL)%K+(%@<(%@#(% +M?S)%K\)%L+)%L<(%C((%D@"\(W?L`A:X&$(%G8S49A04L@7$X+L0LD7$!@(` +MP@7$\,P0PD7$DD<)8D6-XA5+@@6?0@6A\A5*D@6><@6@,@5]LA5-PA5,PE5$ +MLE5%,D6=DE5-\D6,0D6?XE5*@D60('>@VG>"!X!62`F- +M"BP)`@=Z#0=X#"!X`6 +M#!`B!7T6@A(+@A:X"V)%?&)%?6)%@:)%?J)%?Z)%@*)%@@P"F,6QE@"R53JR +M53NR53RR53T;F9G%'?```#(%S#<[`H::_["+D$*B>""(H-J(HDB`L@7.HDA_ +MC0JZ,AN[2C/"0\]"H"&PL'1'NP*PBR"R![`8T+,@7-AQ,"@D7.<@7, +M1I3_`#9!`$*GDTI",@1Y#`T60PG98H("74($A0P6%O@*C/0+E!:)$J+$_A8J +M$[+$_19+$L%H`/U'IQ6,@E_:K.S]0"RR_\`&T``_*$P_\#S]00;9IQ$\@F`2C\S]0P+ +M,P`30`#LH?#NP./U$`R$9[0#&Z<,!E)H&$N('?`,!<;M_X($AU($A=ERMB@X +MG`62Q?\620RBQ?X6Z@VRQ?T6BPS!:0')8@8-``",]`OD%@X)\L3^%J\),L3] +M%L,(@6H!B7(&T_\`C/4+E19)":+%_A;J"K+%_1:+"<%K`L9(`TD#+3_S(3?UT-,_4`&T2,1I(7?Y/U +M$+9D!1MF*W<,!%)B&$LB'?`,!0;X_Z%N`:ERQK?_L6\!N7+&M?_!<`')ERQK'_\7(!^7+&K_\Q0'I8L;4_P```#9A`#(BM""B(&7D_\%) +M`%$Y`)@"LJ)(NK+B*2[B98#2*2?2;()""T#B(A+R"T%#_@%"IXCS_@/B;(O2 +M(A%*XM)LC/(+,F(+-M(.G*(.GH(.H'(.D:/V`X/V!J(.G8(.GW/V"//V&'(. +MFM/V&:/V&X/V'8(;#W/V'F)LC?(I,?)L@`P/TBDKTFS"\FS$HB*H;J9VOGJ@@N\D@O,<98``&@C`-DC=^@_ +M=^E\8(:0((B@2HB"*#,ZB(GZT@OA@AN2`-TC@-W`5OTST@O<`)TCT-<$5CTS +MD(F0((B@2HB"*#,ZB(GZAAH``'?I/-"-D""(H$J(@B@S.HB)^I(+X8(;D@"9 +M(X"9P%9Y,=(+W`"=(]#7!%:],)")D""(H$J(@B@S.HB)^H8*``#2"ZP`W2/0 +MW9`@W:!*W=(M,SK=V?J2"ZP`F2.0F9`@F:!*F9(I,SJ9F?J""ZP`B".`B)`@ +MB*!*B((H,](;%F(;%SJ(B?KR:A#R:A'R:A+R:A/R:A22"SB<[=#0Y/);%IQI +M@LG_%AA#@LG^%BA'@LG]%DA+@LG\%NA,K`;2"SE@8.3R6Q><70N-%LA!@LW^ +M%NA%@LW]%@A*@LW\%JA+"R?T6J#S2R?P6S4"2`EJ" +M#HAR"S8,%@P-"W=PUH.3^`%R#I*2#I!B#HMS^`-R"T-C^`63^!)B"S&2"U9S +M^!1C^!73^!V3^!Z":CAR#H32`E]RQ_X6]QN2`EV"W`23_068`M)J.?)J//(I +M,_D(\@M6DBDM\_D(DFI"@@NL`(@C@(B0((B@2DA")#,Z1$)J1/CB\FI%F(+X +MDL"9$?/Y%))J1H(BJ4%F`3J(@FI'0FI(\B*7DB*6"_\+F<"9$?/Y#))J24(. +MA`P/T@LVC)0+A!98*)+$_A:Y*@P)@@Z10@M"D_T#@_T'0_T-TFI*2`*2(A62 +M:E,,F?)J68(B%()J6$(D-$)J0``YIH`0II@"07H!0FDFDBDFDFQ"@B*6DB*7 +M30B`B8*3]`B#]!!";%.2"\U"`EL`F2,6M`^6^0#2HD@@J:#:JJ(J.SJJHFQ2 +M@@NMDJ)(`(@C((B@FHB"*#LZB()L3I(BEHCBV/*0B(*M#X/Z$-/Z"*)L2)(+ +M-M$W``N9%JD(HJ`>HFQ4DB*6D)`DDFQ&HBWP\BW=@J_[D@LV@(\0@FW=)BD= +MG*DF21BR#H2RR_X6BQJ"#EW,F)(.7\Q)L@ZA%OLK@0@!Z`*`BA"";?#R+C#R +M;$#B+B_B9<`=\)(+S`"9(Y"9D""9H$J9DBDS.IF9^@9,_](+S`#=(]#=D"#= +MH$K=TBTS.MW9^@9&_PS(@FQ4\FQ'QMO_D@LV5IGC@@)>8@);%D@Q#!A@:).= +M!I/]!,:(_P"6^0#2HD@@J:#:JJ(J.3JJHFQ2@@NMDJ)(`(@C((B@FHB"*#DZ +MB()L3@;`_Y(+-A;)'PN)%G@@@LG]%A@@@LG\%K@>G0^3_1'&]O[:D@PF%AG3 +M@AD`23$I$3DA(@D,,AD"0AD!(_8%(AD#8FH5@FH60FH72#$R:A@B:ADX(2@1 +M1D#_`-J2#"866=&"&0)),2D1.2$B"0PR&0!"&0,C]@4B&0%B:AJ":AM":AQ( +M,3)J'2)J'C@A*!%&.?\`VI(,)A:9SX(9`$DQ*1$Y(2()##(9`D(9`2/V!2(9 +M`V)J)8)J)D)J)T@Q,FHH(FHI."$H$48R_P#:D@PF%MG-TAD`@@D,*1%R&0(B +M&0.#]@6"&0%B:BIR:BLB:BPH$=)J+8)J+D8M_P`,.09?_Y("6E8)Y4:7_WJ2 +M#!:&Q?]ZD@P6QM'_>I(,%@;>_P!ZD@P6!NK_`(("6SDA#"D,$X"3@S@A!E'_ +M@AM2@MB`%M@1TEM3!O3^TAM4<-W`%FT18EM51OG^``P&DJ+\FI)&L?\,!I*B +M_)J2QKS_#`:2HOR:DD;(_PP&DJ+\FI+&T_^"&V*"V(`6*!#26V-&XOX`TAMD +M<-W`%JT/8EME1N?^``P6DJ,#`G&@?\``&(+ +MSH(+OHD!9YA8#`E&??^13P"2;::"+::17`#A"@&`@'20B""";::R(I;@JB`, +MB;\%((BKQ9H +M*7SR'?!IHJT"I0;_N-*YLF)"!&)"!6)"!F)"!V)""&)""6)""F)""V)"#&)" +M#6)"#F)"#V)"$*(BEPP<06@`ISL"AHP`4M(",4D`>>G(62Q$;BZ])"6*)"6>(%GF8^'/(%A=QODJ`%`#FFD!"F/?`+B19X +M*J+)_A8:*KBRK0+E+`2R!7T,'`=K"](%>-)""F)""\8"`.("6?("6/)""N)" +M"V)"#X(BEFFB#`T6F""XPJ%E`0`;0`#LH7:`"I(C39<."0NJ%HH&AOO_```6 +M"@:M`L(B"XA2D@(.P_T(L_T1D_T9TF(3X`@`XB.!TB(0#!SG#0*&>P"I`59: +M(:%E`?(B#(("$+("#Y("#N*@"+/^")/^"8/^"O/^$7:`"M(C@PNJ%ET$%BH$ +MAOO_(*(@Y>[^,J__(*(@Y4``D@6NXLG]%EX<\LG\%G\8@LGZ%I@;+0,=\``` +MD@5]D)($%AGNH@5XHD)88D)9QKO_``RY`#ZF#!\,#:("";(""H(""*+*_:#? +M@_("#J(""]/X!K/X!]("#[("!*/X#//X$ZBR^*+3^!2S^!72`@>R`@:C_PBH +MPM/_$-/X%K/_$;("!:/_',/_'[/X%Z`0IM(""+("":(""M/Y"K/Y$:/Y%0`Y +MIH)C5?)CR=(E%@R+USL5H64!=H`+LB1#"ZJPL!2,2XPJ1OO_`(BRZ*+XPH/^ +M"//^$N)D3-BBXB46*]WG/1*2!7T7:0RB!7BB0@IB0@L&`P``L@)9T@)8TD(* +MLD(+\!"FX3D`XB[!X.!D5B[NDB.!@B(0EP@"AK7_J`*B*C<6&@2M`N7;_@:S +M_P!2T@+2)1>R)18,`PO="[O3^PC#^Q+#^Q6R9$P&K/\``,)BLN*C+@QO#%B" +M8J_R8K#B8K%\\AWP``#"0@^XPMBBDB*6&[L;W=FBL+`DN<*7O0+&??]IHKBR +MPD(.HB*7&[NYLJ>[`L9;_\;E_P`,7`P=TD6O::)ILL)%KBT#'?````#B)2_< +M3@QJ#$F"HZ""93&292^B93#R(X'R93*M`J71_L:)_ZT")??^+0,=\#T*K0)E +MT/[&A?\`L7L!`#NFD!"FC$G2R8!6S=0,`AWP````-D$`HB*7#`,,#9QJK0(, +M"\T#I0,`H-H@)@HMHB*7,L,!IS/G@B*6LLK_D6@`HJ`!@LC_L_@(H_@2H_@5 +MK0*":4SE'`"M`B7P_AWP`#9A`&(BE@P,9S,"1C<`,/!@L6@`@4D`#!WM!$#M +MDPP)864!`!5``*VA=J8'120"@B""":8(=\``V00`H`F%)`%(B,3(F +M@4%]`9$^`%`S$$!3$%)F@4>#`QWP``""(B>0B"""9H(=\``V00!!?@%BH69J +M8E(6@&(6?_M5^V905"$]!5)BEV!D(6)BEDI54@4`2D9"!`!C\PA3\Q!#\Q@R +M8A$=\``V00"M`@P+I:$#C"HM"AWP4J("`#6FH!"FD7\!0J'^,J><.C)*0J)# +M?Y"JD*(:`*)4-0`UIH`0IJT"BYF"0X.0B)""&`""5#FE"`",*BT*'?""!),, +M#**A`A:(!@`ZII`0II)#BQ8Y!@`UIK`0IK)#A@`ZIK`0IHQK`#JFL!"F&[NR +M0X@`.J;P$*8,C>(#??)#BK(B$.>]'X($E)R8D@-Q)AD4#!JB0XZB1('!20#" +M+(''"PQ\\AWPPD..PD2!1OK_#`(=\,)#AD;I_P`,3=)#A@;G_S9!`%+2`D(% +MDPP+#/D6M`?"I0)RHP)BIZ$,&"84&28D=B8T$T%)`#(B$$(D@7SR1P,!'?`, +M`AWPXJ$"`#ZFH!"F:F*B1H<6N@?2H@(`/:9`$*8,N@PO%N0`)A1_,L3^%B,+ +MTL3]%DT)@D5\DD5]X@5\IQZO`#>F0!"F)G12\@9X2O\;__)%>$;F_P``LD5X +MLD5\LD5]QN+_DD5]@D5\:F*"1H<`-Z9`$*;V=`PR!GA*,QLS,D5XAMK_`#RF +M@!"F@D5XAM?_LD5\LD5]1M7_````/*:0$*:217C&T?\`/:9`$*:"H`5`0!06 +MA``F%$DF)&LF-%#R17R"17T&W/\`/J:`$*:`0`0':`(F%'2R17VB17P&UO\` +M/:9`$*9`0!2,I"84+)*@""8D3B8T/X)%?0QIDD5\ALW_``QK##W217RR17T& +MRO^"17P,GN)%?4;'_PQ_#$,R17WR17P&Q/\,J`Q)DD5\@D5]QL#_``"217T, +MF[)%?(:]_P"217SR17T&N_^R17T,K=)%?$:X_S9!`'*E`@`WIG`0IK*A`@R# +M#!IBIS$,"5*B#%I2C0EJ8G)&_W"*@X!ZDW*", +MDX)%>T;C_QS8AQ<4'._W%PD<\S)&Z$;I_P``@D;H1N?_'+B"1NA&Y?\``#9! +M`&*A`@`VIE`0IA:%```VIE`0IE+%`7*GI7IR4D=_`#:F4!"FC&4`-J90$*8; +M55)'@``VIJ`0II%)`((B$*)'@9(I@7SREP@!'?`,`AWP-D$`0J'Z2D(R!((, +M!G*GF2:3)(*C`@`XID`0IGJR#!DF="RR"X`<^DJ[L*ICH)ESDD(*8D(+'?#2 +MH0(`/:;`$*:L?.($?N)""F)""QWP``""I0(`.*9`$*8,'QSS0#-C,/]S\D(* +M8D(+'?``>I*2"8"20@H=\```-F$`0J$"DJ*`#`4,&[)""5)""%)"$%)"!IJ" +MHMC_@B+=H@K_HD(')A@UJ*(JJIJ:D@G\,6@`G&G!@`&R(A.M`L"[(+G#);,` +M%FH$+0H=\`"(8JT"O0'@"`",RBT*'?```#2FD!"F1O+_8J'XPJ`_L8$!T@(- +MD@(,HB(3%AT")EDVL.H@XF,,K0+EK@"\ZBT*'?"M`A`1(&6Q``P"'?```"99 +M=+#Z(/)C#""B(*6L`!:Z!Z`J(!WP`%)""<)""*)C#""B("6K`!8:`RT*'?"M +M`K@!PB$!Y;,`:C*2$SP`.::`$*:M`@RK@D(09;D`H@.$MIJFK0(EZ?\,`AWP +M`#2FT!"F:C+"$SS20@8`/*:P$*:R0A"&]?\``%)""<)""*)C#""B("6E`!8: +M`2T*'?"M`K@!R!'EK0`,`AWP`&KBX@Z$]IX,`#2F\!"F\D(&#`(=\*T"9>/_ +M`#2F\!"F\D(&#`(=\``V80"BHT!2H0*"(O]"H?@,!F)"!F)"$&)""$I"D@2' +MDD(')AARF*(JF:J9D@G$#!PQ:`"JLJSY##=R0@G(VPO,%DP(F*(JF:J9D@D\ +M%AD%L8(!HB(3L*H@J<,@HB!EFP`6V@8M"AWP`,)""=C;"]T6'0R8HBJ9JIF2 +M"3P660BQ@`&B(A.PJB"B8PP@HB!EF``6RA,M"AWP```UII`0I@;C__(4/``_ +MIN`0IM&#`<(B$R"B(.)"$-#,(,)C#&65`!9J`BT*'?`````UII`0IH;>_ZT" +M99<`K0+EE@"M`J66`*T"998`#`(=\(("$&%3`%=H(HABK0(0L2#@"``6B@HM +M"AWP`(ABK0*]`>`(`!:Z!"T*'?``(*(@Y9(`D@(01VD;@B(&(*(@O0'@"``6 +M&A$M"AWP```UII`0ID;/_R"B(&60`)("$#=I/X(B!B"B(+T!X`@`%@H1+0H= +M\`#"H#^Q@0'2`@VB(A.2`@P6;1;BR?L6OA>P^B#R8PP@HB!EB0`6"ATM"AWP +M```@HB"EBP""`A`G:$."(@8@HB"]`>`(`!;*#RT*'?``D@(-S*FB`A"RH-^P +MJA"B0A#"`@S"S/L6W`RM`K@!PB$!98X`QM+_`*T"98<`#`(=\*T"Y88`/0K" +M`@C`LD'F>SN6BP/2!(0\Q$"\$+:=&$>,!^("$/`@`(S.K0+EP?^R`@CP(`!` +MNQ`6&_PG8[X`-:;`$*;"0@8,`AWP```F>P\,K;X"-)"#:++VX8``,)"#0PK+"VG/2K"0@P@ +M*J`B(A@@0'2\%("4$;"9(``YIE`0IB"(=%!!08I$!V480$!@A@0`+#W7&D4, +M7N)"#,D#R1,,`AWP`$!`U$D#($!U%A0%@(01L(@@`#BF\!"F("AU\%%!6B(' +M;PP@(&`@D+29$PP"'?``()"TF1,,`AWPPD(,6N2`[A&P[B``/J;0$*8,`@`% +M0-"@D:"F$-#7$-D3J0,=\$D3#`(=\#9!`*T"O0,,G`R-XJ'_\J#_Y?'_+0H= +M\#9!`*T"O0,,K`R=XJ/_\J'_9?#_+0H=\#9!`*T"O0,,S`RMX8P!\J/_Y>[_ +M+0H=\#9!`*T"O0,,W`R]X8T!\J?_9>W_+0H=\#9!`,+2`L(<-``\IK`0I@P= +M#`PL2!N[K0NWN`C20@VBR]N&``#"0@T,*RPMISTLPD(,("J@(B(8?.8@0'2\ +M-("4$;"9(``YIE`0IB"(=&!%$(I$!V4:0$!@!@4`+#W7&D<,7N)"#,D#R1,, +M`AWP````0$#420,@0'46=`6`A!&PB"``.*;P$*8@6'5@+Q!:(@=O#"`@8""0 +MM)D3#`(=\``@D+29$PP"'?#"0@Q:Y(#N$;#N(``^IJ`0I@O5#`(`#4"@T)'P +MJA'0UA#9`Z"G$*D3'?``21,,`AWP```V00"M`KT##(P,?>*A_O*@_B7Q_RT* +M'?`V00"M`KT##)P,C>*C_O*A_J7O_RT*'?`V00"M`KT##+P,G>&.`?*C_B7N +M_RT*'?`V00"M`KT##,P,K>&/`?*G_J7L_RT*'?`V00`Q90$,!%%H`':C$CWP +M/?`]\#WP/?`]\((E.AM$S*B2(K,;F9)BLWSR'?`,`AWP````-D$`84D`,B(0 +M?0)")H$,"`P"1X,.@J$#`#BF(!"F#!@&````#`11:`"190%0H@&IQ7:I$^(F +MF-(FF,(FF+(FF"(E.QM$!^(+\B>S#`(;__)GLQWPC,@78@J"H0(`.*8P$*8= +M\!WP```V00!Q20!2(A"-`F(G@0P)#`)GA0^2H0,`.:8@$*8,&48`````H64! +M,_0,86@`#`,C]!M)QG:J$^(GF-(GF,(GF+(GF"(F.QLS!^(+\BBS#`(;__)H +MLQWPC,D78@J"H0(`.*90$*8=\!WP```V00`R`A""T@+L,X((D:*GH*HBG)B2 +M`HG^##KA +MXP#!DP'Q20""`^71E`&QE0&<>)+(_Q9I"K+(_A;[$@P"'?!"0^5"1"0^:`@'0F2`V2`Q&,>0`^IK`0IK)#Z$)#ZN(#$`P8@D/IC$Z2 +M`Q0622NR`P\6NRCBH@(`/J8]\(`0IH)#ZX(#KQ98%I(#$(Q)L@,4%CLXX@,/ +M%MXQ@@/K&XB"14L`-J:0$*:20_`+F1;Y*,(B$+(O@7SZP+L0L$J3%M02+00= +M\```0D/E0D7(QLW_`#NF@!"F0D/G@D/F@(!T)D@-D@,1C'D`/J:P$*:R0^A" +M0^H,&.(#%()#Z8(##Q9>(!:H(9*B`@`YIH`0IH)#Z[(#KQ:+$N(#$(QN@@,4 +M/?`62#:2`P\6^2^"`^L;B()%2P`VII`0II)#\`N9%@DHLB^!PB(0?/HM!,"[ +M$+`JDQ;"#AWP@D/E@D7(AJK_``"RHP(`.Z:P$*:1E@&"`Q&2R2"0NY"2"P&2 +M0^>R"P"R0^:,>``^IH`0IH)#Z$)#ZH(##Y(#%`P;LD/I%ND?%C@AXJ("`#ZF +M@!"F@D/K@@.O%A@+D@,0C$FR`Q06.R_B`P\6CBZ"`^L;B()%2P`VII`0II)# +M\`N9%GDEPB(0LB^!?/J-!,"[$+"*DQ9X!RT('?""`^8F2"D`-J;@$*;2`Q#B +M0^P632P`-J:`$*;R`Q*"0^T6ORL`-J:`$*:"0^Z"`^8+F%:IX,&7`0`\IJ`0 +MIK&6`0P"HD/ONJJB"@"B14D=\-(#YM+-_!9MW@`VIO`0IO)#[``VIN`0I@P" +MXD/M0D/N'?```((#YB9(&0`VII`0II)#[``VICWP@!"F0D/N@D/M@@/F)A@" +M9C@6P9O^2`P\6B=4`-J;@$*;B0^D`-J:P$*:R +M0^K&4/\`L9@!DJ=`FI)VJ$D`/*:`$*:"67F`@D'0B!""68$`/*:`$*:"67V` +M@D'0B!""684`.Z:`$*:B&8&`@-2`BB""68$`.Z:`$*:B&84KF8"`U("*(()9 +MA,9%_P```!;(X``VIN`0IN)#Z0`VIK`0IK)#ZL9]_PP(QGO_#!A&./\```"Q +MF`&2IT":DG:H20`\IH`0IH)9>8""0="($()9@0`\IH`0IH)9?8""0="($()9 +MA0`[IH`0IJ(9@8"`U("*(()9@0`[IH`0IJ(9A2N9@(#4@(H@@EF$ADG_L@,/ +M%LL+X@/JX*>#C0I&'?\,&,8__P``L9@!DJ=`FI)VJ$D`/*:`$*:"67F`@D'0 +MB!""68$`/*:`$*:"67V`@D'0B!""684`.Z:`$*:B&8&`@-2`BB""68$`.Z:` +M$*:B&84KF8"`U("*(()9A,93_[(##Q8;!>(#ZN"G@XT*!B7_``""`^%6)>%AWP`!:#)0N#%H@I]D,%MB,"AM,`#`+* +ME&))-F))-V)).&)).6)).V)9%6)9%AWPH@1:RC1B0SAB0SEB0SMB4Q5B4Q86 +MRBO"!8L6K"V"`]^2$Y'20S8`B".7F$.2`]IWZ3T,2J)#-P8.````@@1:RC1B +M0SMB4Q5B4Q86J#&2!8N2R?\6&3"B0S:R0SBR0SG20S=`I""EL_X66A8M"AWP +M`+)#-ZT$I;+^K%HM"AWPRJ1B2C9B2C=B2CAB2CEB2CMB6A5B6A:M!*6P_A;* +M,BT*'?#"H0(`/*:P$*:R1%VR1:D66U8,"M(%5:)$7J)%JA:M2@`RIN`0IN)% +MD_(%7Q8_2J&;`0`ZIH`0IH"1!))#*("`!()#*<(%E`S+Q[L+T9P!`#VFH!"F +M!@(`X9T!`#ZFH!"FHD65H/!T\L_\%N]&HJ,"`#JFD!"F@@65DD69\)D1@LC] +M%JA&L9X!NKFR&P"R4Q#"!%T6C$;RHP(`/Z;0$*;AGP'219;@W9#2'0#24P^R +MHP(`.Z:0$*:AH`&219J"!96@F9"2&0"24Q-F.!32H@(`/:;`$*;"19QPS)#" +M'`#"4Q)`I"!E?@`6BB6@*B"0``#*-.(#W_(3D0#N(_>>$/(#VG?O"M)#-M)# +M-\8!````LD,VLD,W8D,X8D,Y8D,[8E,58E,6K02EG?X6.ALM"AWP@@55#!F2 +M1%T6N$(`,J:@$*:B19.R!5\62T+AFP$`/J;`$*;`T0320RC`P`3"0RF"!90, +MSX>_"Y&A`0`YIJ`0I@8"`*&B`0`ZIJ`0IJ)%E0Q;0*0@I1,"%LH;+0H=\`"" +M!%K*-&)#.&)#.6)#.V)3%6)3%F)$76)$7A9X/9(%BPN9%JE!P@/?@A.1`,PC +M@,S`5HP+@@/:@(<$5O@*#$F20S:&*@""!%K*-&)#.V)3%6)3%F)$76)$7K)% +ME19(/)(%BPN9%LDZHD,VTD,WLD,XLD,YK02EC_X6BB8M"AWP`,JD8DHV8DHW +M8DHX8DHY8DH[8EH58EH6K01EC?X66CPM"AWP`,(#W](3D0#,(]<<`@8E`-(# +MVG=M`L8B``Q(@D,V@D,WQE[_`)(#WZ(3D0"9(Z>9#Z(#VG?J"0Q+LD,V!@$` +M``"R0S;20S=&5?^R0S;20S>B80!`I"!EA_X62A,M"AWP`*T$RL1B3#9B3#=B +M3#AB3#EB3#MB7!5B7!8EA?X6FD$M"AWP`*)#-[)#.+)#.=)#-H8^_P"B0S:B +M0S>R0SBR0SF&.O\`LD,VLD,W1CS_T@55%DT_`#*FX!"FXD63@@64#,^'OPN1 +MG`$`.::@$*8&`@"AG0$`.J:@$*:RROR@D'221946BSQF.1NM!+*@`>7Y`9P* +M+0H=\$"D(*5C`!8*`:`J(!WPK01E5OZ,.BT*'?``#`(=\**C`@`ZII`0IL(% +ME9)%F?"9$<+,_1:\/;&>`;"Y@+(;`+)3$/*C`@`_IH`0II&?`8)%EI"(D((8 +M`()3#P`_IM`0IN+)P-)%FL(%E>#=D-(=`-)3$V8\%+*B`@`[IJ`0IJ)%G'"J +MD*(:`*)3$D"D(&51`!9J^*`J()````#"!546'#@`,J;0$*;219/B!5\6KC>1 +MFP$`.:;P$*;P@02"0RCP\`3R0RFRH0(`.Z;@$*;(`=*@`N#-@\)%E0`[IJ`0 +MIKP:P98`PE,5DJ8"`#FFL!"FHA,5LD67L*H@HE,5`#FF@!"F\A,5@D68@(@1 +M@/\@\E,5\E,6K00,"^7G`1:*'BT*'?`````,+LK48DT[8ET58ET6HDTVHDTW +MXDTXXDTYK01E:?X62ADM"AWP`+&7`0`[II`0IJ&6`8(%5:J9D@D`DD,O%N@L +M`#*FP!"FPD63T@5?%FTL@9L!`#BFX!"FX/$$\D,HX.`$XD,IHJ$"`#JFD!"F +M0*0@LJ`"Y=\!%EHR+0H=\`!B19/&U?X``&)#*&)#*<;9_L(%E`S+Q[LVT:$! +M`#VFH!"FQ@P`X:,!ZNGB'@#B4Q!&Y/X`DJ("`#FF\!"F@:0!\D66@/^0\A\` +M\E,/QN3^`*&B`0`ZIJ`0IK&E`:)%E0`[II`0IA9Y)@O)%CPCH98`HE,6\J8" +M`#^FD!"F@A,6D(@@@E,6`#^FX!"FTA,6@.X1X-T@TE,6QL'^``!B19.&]?X` +M`&)#*&)#*8;Y_K*A`@`[IJ`0IL:C_L(#W](3D0#,(]><,M(#VG?M+*D!#$[B +M0S;B0S=&./_20S:B0S>R0SBR0SG&$_\`HD,VHD,WLD,XLD,YQ@__`+)#-K)# +M-ZD!ABW_`/(#WX(3D=)#-@#_(X#_P%8?#H(#VH"'!%:(#:D!#$F20S<&)/]` +MI"#E-@`66M2@*B"0``"B!546&A\`,J:P$*:R19,`-Z;`$*86?!X,+=)%E:T$ +M#"NER0$6ZAXM"AWP`**B`@`ZII`0IN(%E9)%F?"9$>+._18^'+&F`;"Y@+(; +M`+)3$/*B`@`_IK`0IL&D`;)%EL"[D+(;`+)3#Z*C`@`ZIH`0II+,$()%FI"( +MD((8`()3$P`_IM`0IN+,(-)%F\(%E>#=D-(=`-)3$68\%.*B`@`^IM`0IM)% +MG'#=D-(=`-)3$D"D(&4A`!9JR*`J()````"R0S>I`4;N_@"M!`QKY;X!%NH4 +M+0H=\`!B19-&`_\,SX(%E)&6`))3%8>_"Z&A`0`ZIJ`0I@8"`+&B`0`[IJ`0 +MIJ)%E>*F`@`^IH`0IO(3%8)%EX#_(/)3%0`^IM`0II(%E<(3%=)%F(#=$=#, +M(,)3%<)3%D;W_@"AHP&JJ:(:`*)3$$8(_P``8D63!B#_``!B0RAB0RD&)/]B +M19/&3/\`8D,H8D,I!E'_@98`@E,5TJ8"`#VF\!"FXA,5\.X@XE,5`#VFP!"F +MLA,5@,P1P+L@LE,5QC3^``"AE@"B4Q6B4Q:RI@(`.Z:0$*:"$Q60B"""4Q4` +M.Z;P$*;B$Q6`_Q'P[B#B4Q4`.Z;0$*;"$Q;0S"#"4Q8`.Z:@$*:2$Q:`JA&@ +MF2"24Q8&(/ZM!`P+Y:P!O-HM"AWP``!B19,&A/\``&)%E8:%_P``L:BJJ(6R`8`/*:P +M$*;RH@*R2H6PL'06"P8`/Z:P$*:R2H``/*:P$*86BP``/*:P$*:RRP&R2H(` +M/*:0$*:""G<,CY)*A(<_".)*B.)-=D8#`+(-B0P<%NO^PDJ(PDUVX4D`TB(0 +MXBZ!?/+G#0(=\``,`AWPXDJ`QNG_#$O&Y_\`-D$`K0(,.R65`8PJ+0H=\`P, +MLJ()NK*""XFBIZ*JHKQ8\@IW#!T,CO<^&8&H`0`XII`0IHQ))ADR)BE,PDJ( +MPDMV1@$`TDJ(TDMVK0*E(_Z,VBT*'?```,)*B,)+=D;Z_ZT"I?K]C+HM"AWP +MTDJ(TDMV1O7_H4D`DB(0HBJ!IPD#?/(=\`P"'?`,+,)*B-)+=JT"#$LEC`$6 +M^OHM"AWP`#9!`&*GDVIB4@9Y<:D!@@:'C$4F%1E2'?``\;`!^5(=\`!!L0%) +M4AWP`#9!`*&R`0P+//S"0@BR0@D`.J:0$*;"I-B20A#*LHC;TJ$")AA5F*(J +MF*BB*JJ: +MFI()A(&R`9)"!``XIO`0IL*DV/)"$,JRZ-LF'E^8HBJ9RIF2"3R20@;BT@CB +M#BJBH?ZJHB8N*9(*@?(*?H%H`))"!_:?"2(B$RG(#`(=\`"M`B4+_H%H`"(B +M$RG(#`(=\)(K+R89()BB*IG*F9()Q(;Q_P``/::0$*:&X?\`/::0$*;&Y_\` +M```]II`0I@;J_P```#9!`((BW9*B^,*A`@N(%B@,J*(JJIJ:D@F$#!L,"D%H +M`#*A]CHRK'F1@`&"(A/"`XFR0@G"0@>B0@:B0@6B0@2B0@BB0A"0B"`M"HG$ +MJ<0=\*)"!M(3.N(#B>)"!Z)""*)"$``]IJ`0IK&S`;JJH@H`H)`4H-0$H.4$ +MXD(%TD($DD()%KD&)VH.@A,]`#BF\!"FD@()\D(0P+D!T0H!P@(%DB(3T+L@ +MP_L8L)D@F<22`@D,)289".+)_A8N"28Y;*##!(AR#`NM`N`(`(S:+0H=\``` +M`#RFD!"F!L__D@.&MIEFH@(0%@H&K0)E^/T,`AWP//[B0@@`/*;0$*;20@0` +M/*:P$*:,JX(3/0`XIO`0IO)"$``\IJ`0II(#AJ)"!O:92+(B$[G$#`(=\`#2 +M$SP`/:9`$*:M`@P+B'(,C,#$$.`(`+PJ+0H=\`P"'?```)(3.P`YID`0IJT" +MB'(,"U#$$.`(`*QZ+0H=\`"M`B7P_;(B$[G$#`(=\*T"#`N(<@Q,P,00X`@` +MG(HM"AWP``!`P`2((C$X(#!<#_`9/_%H/_&+/_&O#N(.G"P@,))BQHT,,$B'.M`PP+X`@` +M%HKP+0H=\`"M`R7,_9(C$YG"#`(=\(RJHA0^`#JFD!"FDD,0P@,)LB,3X@,% +MP,P!8_P6X_P8P+L@N<*2`PDF&6HF*330PP2([_+0H=\#9A`*T"O0/-!`RM +M#)[RH_^"H?^)`67L_RT*'?`V80"M`KT#S00,S0RN\8P!@J/_B0&EZO\M"AWP +M-F$`K0*]`\T$#-T,OO&-`8*G_XD!Y>C_+0H=\#9!``PM#`P,"K*A;!94"+J2 +MDAE^`#FF0!"F6J:"H'Q'."X@9*!B)AA@S@5@3#1@4#06-0>`E1'0F2``.:9P +M$*9@A'1P44&*50=G7%!08(85`!NJ@*H1T*H@`#JF@!"FDL8!0L$@0B0```E` +M@,`$@%"14%<0@(%!@$000$R`TM((T@T:]BT%\%41\$014.#40*"TX_H,06@` +MC&,+\Q:O""8C):G$#`(=\!84_8"4$="9(``YIG`0IF"`U7!!08I$!V>Z0$!@ +M!NW_X4D`#`72(A#B+H$,!O*A`^>-"@`_IE`0I@P6QO__#`-3^AN!90'#^ARI +MQ':H#SWP/?`]\#WP4B0[&S,'Y0VZHI(J6`P"&YF2:E@=\(P6%^4##`(=\+*A +M`@`[IJ`0I@P"'?`,`L/Z'*G$'?``-F$`K0*]`\T$#)T,?O*A_X*@?XD!9>O_ +M+0H=\#9A`*T"O0/-!`RM#([RH_^"H/^)`:7I_RT*'?`V80"M`KT#S00,S0R> +M\8P!@J'_B0'EY_\M"AWP-F$`K0*]`\T$#-T,KO&-`8*C_XD!)>;_+0H=\#9! +M`#Q+#`8R(A="HDRBHEBJHTI#8D1C8F(W8F/=8F/_8F2.(B.8I0,1H;9:`N8Z$\+*^Q:<#69J"@O9%JT2XLG]%DX2 +MK0-E^_R2!$@,.))$JI(%Z*($2:)$J_+)_&GC:?-B0UIIPY)$,FG38D-;@D1B +M%B\-K`D+N18+"^9)&:8I%L&X`_Y&O`9E31MS_`*T#N+/"(Y8AQ@DEXB&&" +M27>(,8))@()#DV8X!`P8@D.3B"&"28&"0Y&($8))@H@!@DF#@D.2XDF%\DF$ +MXD.?PDF'TDF&PD.0LDF(N%&R28FRROSV2P)&1P"1N`"PPD$G:P@`.::P$*:B +MROS="<"!07:8#@`]IH`0I@`]IH`0IJ+*^"9*$@PI;`B`BK"`B!&0B"``.*;P +M$*:M`B5S`+(D@9(B$+>)`D8U`,(C+U:\XWSR8F,O4F,PXJ)MXF,QTB2!TF,R +M'?"H`2@1@B,O2"%H,HB!@DEYB'&"27B(88))=V)#DR8V*T)) +M@4)#D2))@J))@WSRHD.2XDF%\DF$XD.?PDF'TDF&PD.0LDF(4DF)'?``#!B" +M0Y-"28%"0Y$B28*B28-\\J)#DN))A?))A.)#G\))A]))AL)#D+))B%))B1WP +M5JOPAL;_``"B4TVB4T<@HB`E9`#")(&R(A#'"Q[2(R]6#=4BK_]B8R]28S#R +MHG?R8S'B)('B8S*0````HE-,HE-&+`BG.!J2(R]6:=)28S"B8S)\\K*B?PQ\ +MPF,OLF,Q'?`@HB#E7@#B)('2(A#G#1[R(R]6S\]B8R^"HH=28S""8S$B)($B +M8S(BK_^0````)JH8DB,O5JG-"O+,_1;_"Y%)`((B$)(I@7SREP@!'?`, +M`AWP\>,`@J`$@D/=`#^FX!"F8D1$L@3:H@3;PA0ITA0HTE04PE05HD19LD18 +M(*(@9;/\!N[_`,;)_P!20_G21%C21%E&T?\,#%)#W0;B_])$6-)$60;-_\&7 +M`7)#W0`\IL`0IAQIPD/FEQQ:T;H!VMS2#0#21#W"`]V&UO^M`B78_!:J!"T* +M'?"M`F77_!;:#"T*'?`````ZICWPX!"FK0+B0_WEU?P62A$M"AWP```ZICWP +M\!"FK0+R0_UEU/P6BAHM"AWP`+)#W5)$/8;I_X(#!18((Z&9`0`ZII`0II)# +MZ+(#`A9K(L*B`@`\II`0II)#$))$6YP)TLG_%@TKXLG^%FXN\LG]%K\L@A0I +MDA0HDE04@E05K0+EI/RR`^D,RF)$1+>Z"\&<`0`\IK`0IH8"`-&=`0`]ICWP +ML!"FXLO\%LX=L/!T\D/J\L_]5M\0K0(,&^5&`!8Z$"T*'?``@@,%%I@=H9D! +M`#JFD!"FDD/HD@1;C/D+N1:[(,+)_A8<)-+)_18](>(4*?(4*/)4%.)4%:T" +M)9W\8D1&##JB1$22H0(`.::`$*86J!EB0^JM`K*@`N5``!9J&RT*'?``L@,% +M%BL9T9D!`#VFP!"FPD/HX@,"%GX8\J("`#^F\"``D!"FDD,0DD1;C/D+B19X +M(Z+)_A;:)K+)_18K)<(4*=(4*-)4%,)4%:T"Y97\4D1`4D1!K0+ES?P6N@HM +M"AWPX:(!`#ZFL!"FHJ8"LD/J`#JFT!"FPA0$(&9`0`X +MIO`0IO)#Z)($6XSY"ZD6>A>RR?X6VQK"R?T6_!?2%"GB%"CB5!325!6M`F6, +M_%)$0%)$0:T"9<3\O,HM"AWP``#R`ERL?U)#XU)"7$9*_P``D@/I#(B7N`2B +M!%;,FE)#^E)$0\8!````/^B +M%"BR%"FR5!6@H4&B5!0&5?\`PA0ITA0HTE04P,%!PE051F__``#B%"GR%"C@ +MX4'P\4'R5!3B5!6&2O^"%"F2%"B25!2`@4&"5!4&1O\`HA0HLA0ILE05H*%! +MHE041J/_``#"%"G2%"C`P4'0T4'25!3"5!6&G?_B%"CR%"GR5!7@X4'B5!1& +M<_\`@A0IDA0HDE04@(%!@E051I3_``"B%"FR%"B@H4&PL4&R5!2B5!7&:/_" +M%"G2%"C25!3`P4'"5!5&9/\`X@),``#BF(!"F`#BF4!"F`#BF,!"F`#BF0!"F`#,1@%414"(@@$0!0#,@ +M,"(@'?```#9A`&%)`(&[`7(FF]!#$8!W$$>W5W"#\`P#]L@"QB<`1G2(J]6'0'R8K"28K+B +MHH""H`6"8J_B8K%\]9*@B)"3@IJ2LFG=1AD`N`*R*R>R9(*R*:RPT`0':PUP +M^Q#R::S`(`#B*:SI0>(D0L`@`,#^(/)D0L`@`((D0L`@`&)D5\`@`/(D5\`@ +M`.)D0L`@`((D0H)A!,`@`(Q]LFFLP"``@BFLLBHWL*L@LBL`)3/ITB2!PB(0 +MUPP#?/(=\/$Y`/(OP7S^\/!D\%Z3+04=\``,"8%E`0P&#"QVJ`;2)$,;F9Q] +MXBHO\"``S-[":B_R:C!B:C*"HI.":C%\]7(B$7)DC.(BEG(BEY$W`.#>(.#G +M@G/]"./]$-)D4](IK'*O_M#@!`=M#G"-$()IK,`@`((IK()A`,%?`((D0L`@ +M`,#X(/)D0L`@`/(D0L`@`+)D5\`@`/(D5\`@`()D0L`@`/(D0OD!P"``C)[2 +M::S`(`""*:R)`>%E`0P-=JX'\B17&]TF'QF"*B_<&&)J,M*BK@Q.#"_R:B_B +M:C#2:C%\]0SH`#BFT!"F##^V?0*&*0"V/1'BS?T6C@OV;0+V307RS?H6CQ/B +MH(C@XX*"H`+@XH"";MVR2H72*:S0\`0';0YPC1""::S`(`""*:R"80&")$+` +M(`#`."`R9$+`(``R)$+`(`"R9%?`(``R)%?`(`""9$+`(``R)$(Y$<`@`(R? +MTFFLP"``@BFLB1'2+MZR*C;:N[)D3N%E`0P+=JX&\B1#&[N,?X(J+Q:H"5*O +M_^(D0](D0[(D0W:`$[(IY[DQB#&`@!2),?@Q\L_]%M_=1OG_`.*@B.#C@NKB +M\F[=LDJ%LBFLL-`$!VL-<(L0@FFLP"``\BFL^2&")$+`(`#`^"#R9$+`(`#R +M)$+`(``,/_)D5\`@`/(D5\`@`()D0L`@`/(D0ODAP"``C*VR::S`(`""*:R" +M80+2+MZR*C;:N[)D3D;4_P``8FHRXJ+D#$\,*()J+_)J,.)J,8;3_P``TJ"( +MT-."VM*R;=U&RO\``#9A`)T"_0.M`@P+,,!$P.,1TJ.XVM+I$@ +M%D+]6`&-#``%0':`%U@'&T104)%04`122%!B*99RQQ`;B&>TLD;X_QWP`(@1 +M4BK>,BF6(BFW+`1`0V-:(BJ(*`@6Q`1M!"DA0%`4(J,LFDLJ1"@A=I4*(%`$ +M4D10("%!&T1@,D%VDR4@,`0@44$@800@<@0@(P1+1#)$3&)$35`Q07)$3B)$ +M3S`Q03`A03(IEB@8+`9,!$!#8T>V2V+$X%*C+)!+@%!$@&!0%':5"B!0!%)$ +M<"`A01M$8#)!=I,E(#`$(%%!(&$$('($(",$2T0R1&QB1&U0,4%R1&XB1&\P +M,4$P(4$R*98H*$P&0J!@0$-C1[9*8L3`4J,LFDM01(!@4!1VE0H@4`121)`@ +M(4$;1&`R07:3)2`P!"!102!A!"!R!"`C!$M$,D2,8D2-4#%!EQF5&)87)$8X(E$')D'')D'7)D'G)D'Y(C@9<( +M9I(FK)#@!`=I$WSH@(D0@F:LP"``@B:L@F$`P"``2:%(!2F1(;T!@B0G:;$@ +MB"""8X+`(`!B(X+`(`!HL4(D)T)C@DBAP"``(B."P"``*)&,SI)FK,`@`((F +MK(D!P"``#"X`/J:0$*:190$]\':`#P`\IN`0IND1B!$+F),18)%9A!#!^'.0$,#PP8#`GPF(.<"9@QZ$$,&(F!D.[`E[X# +M#`F9@18*$I($8H;:_Y($8@;9_P"R80)0I2!E-P"R(0+R(X'B)1`,3-'C`/>. +M`A;*$G)$8@P)AL__N2&M!274^Y8*$*A1B"$\2PPY=5YY7GUK07E^/RX(?(E$.(C +M@0Q,T>,`]PX"!B$`%OH2D@1BQK;_LF$"4*4@I5,`LB$"DB.!@B40#$S1XP"7 +MB`(6Z@H,&0P:HD1B!JW_``"M!0P>#!RX<8@A#&_2"YRR"YKR2`)YI7FU><5Y +MU7GE>?7"15K0WI/215NR1#)R1#HE1/VX(>(E$)(C@0Q,T>,`YXD(%BH'D@1B +MAIG_D@1B!IC_`)($8D:6_P``D@1B1I3_```6;P22!&*&D?^="(A!#!J7.`*& +ML?\,"D:P_P``H@1M5EH`L@1D%KL)#`(,W`P=TD1HPD1I'?`,&0P>XD1BQH/_ +M#"D,+_)$8D:!_XB!%L@1D@1BAG[_`*T%N''B!$7R!$?R1#SB1#W""V72"V32 +M1#["1#^R"YHE[_VM!67S^JT%)73[N"$,3-'C`%:Z#9($8H+)^Q9HW:+)_E9* +MVT9S_[AQ.&)S*D@1BQF+_1"BR?P6&A`+Z19>$?+)_1;_ +M$.($88+.^Q:8$69N"@NI%NH.XLG]%HX.K05EMOOX.0?SJN'&2!5JBH`&""YFR +M"YJB1#I0I2"0N(/E)?VX(?(C@>(E$`Q,T>,`]XX55BH!N2&M!>5=^ZT%Y5[[ +MN"$,3-'C`)($8D8;_P``D@1B1AG_``""!,B`AP06^.\,*0P:HD1EDD1BD@1B +MAA+_X@2X=^[I\@3(\/<$%@_N1O?_`&8IV4:[_[AQ#$BR"YP,&@P)L)J#DD5; +M@D1B!K__`*T%#"S2H`-R15MR1#QR1#UR1#YR1#_21&+"1#3"1#6EU?JM!26, +M^[@A#$S1XP`&W?\`-D$`#`LRHARBIRR@HH`P,H"R4SZR4S^R4T"RH*CEH`^R +MH@(`.Z;P$*:2HP(,/L+2!_),+.)#@@`YIM`0IM),+0`[IJ`0IJ),+@`YIH`0 +MIO*E`H),+P`_IE`0IK*A`E),,``[ID`0IN&_`4),,0`^IJ`0I@QT#&4L"`PM +MT*J0HE,^HEP9I[@"1EL`@B,HS-BB8RM"8RA"8RF2HFN28RI\_0`^IJ`0IH@" +M#"F0JI""*`NB4S^B7!JGN!;2(RA6[0!28RA"8RFB8ROBHG_B8RI\_0`[IJ`0 +MIJ),-@`[II`0II),-P`[IH`0IH),.``[IN`0IN),.0`[IJ`0IJ),.@`[II`0 +MII),.P`[IH`0IN*D`J'``8),/!9X"8&8`0`XII`0IAN9DEP?`#BFD!"F&YF2 +M7"``.Z:`$*:"3$*,`@DQ&%A@+`#NF@!"F@DQ'%@@+`#JF@!"F@EPEBXB`@T&"4T`` +M.Z:`$*:"3$R]&((BKU:(Z:)BLE)BKT)BL)*B +M<9)BL8:A_P`,#8:@_X*@>()30$;8_P```#FF0!"F@<$!BH2""`!"3$C@B!&" +M4T``/J9`$*9"3$D&S_\`-D$`30*"H0(`.*;@$*9BT@?B1M0`.*;0$*;21M4` +M.*;`$*;"1M8`.*:P$*:R1M<`.*:@$*:B1M@`.*:0$*:21MD`.*9P$*:2H@)R +M1MH`.:8P$*9RT@(R1MLR1Y-F,P0,'_)'DP`XIK`0IK)&W+)'D0`XIJ`0IJ)& +MW:)'D@`YICWP4!"F,J=L4D;>.C0B!E%!XP!21Y!VD@H`-*8@$*8;,R)#?P`X +MIL`0IE&_`<)&WQ8<"P`UIB`0I@QY#&HL#0PC,"*0(E=&(E9P)SUSLB\",(G+R*O_Q;\"=(&VHR=`#BF/?#@ +M$*;B1N0`.*;P$*8,B4*C`O)&Y1;_!0`TIC`0IIM34D>4,D;F`#BFH!"FHD;G +M%LH$`#2FL!"FF\O"1Y6R1N@=\`#2%TPGO1?B)R]67O@B9S*B9R^29S#RH\SR +M9S'&W/\,`@;<_P`R%TPB%TTB5T#PPU#`RBH-!RH(BR +MH:RZLGIRJJ*I`Y(B3))C/L)C/5)C.8(B."*A@(E#*B/"0LZR8Y2RH`B2!Z"2 +M0M2"!Z&"0M6E$NBM`R)A`:5Z``PY#`P,+2T#4L,80&:"LJ"`NK/"2Y322Y8, +M'N)+E9)+DI)+D('%`6!FD$*@]$I#D&81@F=4K09`M"#"H`'2H0"EL@*B8DZ+ +M(E>2Z:'&`;T$PJ`!TJ$`9;$"O018$0P)G51WP```V00"X +M(B +M(4ND^B3B8B+88\*@V+*@X/O=T-1!TF0WB'.ZL^@$^XB`A$&"9#CX8_)N"MAS +MTFX+)4K`T;\_P"2H22:DS*B*CHTHD/K2B"8"B0]J""7J"4VSR"7SR0]?B*2'B:Q[2*2+2:Q_"*2/":QRB*22B +M:QUB0]Z8!289!*("@(SZ'?``#`J&W_\,"[)#WD;Y_P"M!*7E`+(#'J@$L+`T +MLD7YN*JHNON[L,3T^ZJPM$&@I$&B4R/`JH*R4R*@H/2B4R'"!"%Z5`=L(0P, +M#`VRH/B@JJ#@JA&PM("ECP*R$R&B94&PNZ#@NQ$E,0^RH)"AS0'"$R/2$R*J +MI,#,$<#=$=)4#,)4#64O#Z(3(;8Z!`N:1@``#!F0H/2<"@P)&YF@H4%6>O^2 +M18UB0H`=\`P+LD6-8D*`'?``-J$`,3<`'1`4!5$>)J,I!5(`SIL%4@4FHM4FHLDFHT##NR:B:1T@&2:C%2 +M*BM29,)1:`"R*BVR94*R*BRY);(J)K)D0K+4!/)D1/)D1?)E6))D@.)DP`SI +MX5X`B0N294"R*B?@NQ"R9(*2)(*,K<)CK,`@`)(CK,`@`**A7*JBHF$(I07H +MHB<[D=,!TJ"HVM>"'>3"'>.:E[(I?PO,"XBZJJ)DQ9(I?_(G/$"($<#,$9K_ +M\F5'\B29,KB9,O-"`R)=JDQD@A@BXB29,R2"%F29,R2"%J29,R2"%N2 +M9,R2"%R29,R2"%V29,R2"%Z29,R2"%^29,R2H`AVJ3&2#*"+S))DS)(,F9)D +MS)(,FI)DS)(,FY)DS)(,G))DS)(,G9)DS)(,GI)DS)(,GY)DS,*AU,K'R9'" +M#'@,NOE!%LP3'%:!U`'2)Y1V@"4+B,(D@[(DPY@U\B5#XB1#P+L@L)D@D/\@ +M\.X@C*X6:`_H#28N!L;T_P`6J`Z(#8+(_H!J@Z#VP!;O'`PE#!IEM]VB(]VI +M(9(A`B*@"%"9())CW7:`"<(CW/?#@W1#28]UV@!"2 +M(^>9,8@Q@(`4B3'X,28_`@;Z_ZB!9>WGJ)&X!\%R`,)D@K(K)[)D@J(*>B8: +M!-B1(DUZ]J8$#)[GMA52`@RZTB>41L'_ +M*)$,#_)"A`P"'?`)(D@_(DP^@UTB5#PB1#D/\@\.X@X-T@ +MT,P@%IP*%I@*J)&B*A^H"@N(9BK3TB/GV1'($<#`%,D1N!%F.^[H46:N`L8G +M``RXAYX"1B<`#.JGG@+&)@`FC@]F'@(&*`!H0>+.]PR=X&V#9=WG#+KRQO56 +MS]XAT0$4J`<,#=D.RJKEJN>(D;'7`0SLXM0$#`WQT@'R9(`B +M9,#9#L)E0)(D@J@'#"^PF1"2:B>29(+R2'H&>O^(D0P"(DB%##(=\`!6&/:H +M<:(JD`PIDFH`Y3T"1M3_`*T'92T`J5%&P_\,QD;?_P`,ML;=_P"X<:AAL@OZ +MY3L`1MK_`-B1K0<,',)->.4+#QQ6QM7_````-D$`(=@!'?`V00`AV0$=\#9A +M``P=2`)Q-P#RH/\,#&(GK+%)`%'/`6"@!`=F$GSH@(80@F>LP"``,B>L.0'` +M(``Q.0"!S@&"9"=2:X+R9"7"9"KR8X*(0I+"$%'0`0OH%EX/XLCQ%FX.4F0K +M?/."H=2*@O((@>((@,)D,\)D,,)D+C)D+S#_$4#N$3'1`3)D,O#N(%#N(`SO +M\F0TXF0M##7B9"Q29"91T@'B)"M29#'B:\+A:`#R)"WR;D+R)"SY+O(D)O)K +M0O+;!-)K1-)K1=)N6%)K@#)KP`SE,5X`R0]2;D#R)"YFK<:9,*@L\<:D=*@MM>:B^($@I'4 +M`59N!\(BE/%)`(%H``N9TB^#LB_#HB@#@BA#\B]#T+L@L*H@H(@@@/\@%A\& +M%AD&J`R!:`#Q20!F*M&X#"8K(ZT"92@!/0H&S_\`+0,=\`RR'?``P@9^]LP< +MK0*E)@$]"H;(_PRR#"W21(,=\`P2##[B1(,=\``,@AWPJ`(,2\*@C,JJY7GG +MPB*41NO_``!6B?H,+=D,I1`"PB*4QN;_-D$`,J'0.C*2`WX,)4*@`R8I,JT" +MY3<`C$H,$AWP``""(R"("`PI#+IF*`520WY&`@"M`N66"$)#?@PY)CD"9AG- +M+0H=\`RR'?```#9!``P(S +M!*(*@(PJ'?```%($@'T(+!M:PIK,&R4@('0R3()B!'^WL@%]`G<6W7)$@!WP +M#!D@H[!ZJI)*@(;M_R"SL'J[@DN`QNK_#$P@T[!ZW<)-?X;G_P```#9!`%(" +M`3("`@P'+!17$QL;96!@="I54@4$1[83@@(#8D(!"XB"0@,M!1WP(J#_'?"2 +M`@-R0@$+F9)"`RT%'?`V00`,%I("`8("`@P*+`0;>'!P='AF")G&(""8H!0;T_Q::&/I7D;8`DF0X)8_GP5,`#.WBTP0,"_'1 +M`:@'@=(!@F.`\F/`#"^Y#M)D0,)D4_)D6:(J+$Q9+`S`JB"I)+GDF=2"!1S8 +M`0"((["(4W"(L((H3MJ(B?3B!20`[B.P[E-P[K#B+D[:[NGTP@9^<,RPPBQ. +MVLS)]*(%WZ+*_A9J$`P9F;3")YBAW`')(2>\5>@A>3&J9^#BP.D1#`)X(;(5 +M)WIRK02NW@QQ@``JF<,`L(5)S(F@`O,QY,3LF:`TB9_ +M/0EE@XM"F"V('"G +M("69#I&L``P(L<0`@*H1H*(@L*H@HF1,@D4M=H`0N#0+F8S+%LD$PB.4R`PF +M+`0&^O^\Z9&L`#WP=H`0TB1#"YF,O;R9XB.4Z`XF+@2&^?^LR?@##`B"9%/R +M+RSY)!WPN;3&O?_Z5ZC%#"F9"J7=`4::_P#(Q0PKN0SEW`'&[/_HQ0PMV0XE +MW`'X`PP(@F13\B\L^20=\``V80!!90$,188```",U``UIH`0IHD!.`$+1!;C +M_I@!T>,`G#D`/:;`$*8,"LD!N`&R0@"I`2@!'?`,'ND!*`$=\````#9!`)%E +M`0Q%Q@```!:9%@`UIH`0I@N9%AC_H>,``#JFD!"F@<`!`#BFL!"F`#BFH!"F +M8=X!:F*2!G\,%-Q)R`*R4@RB4@VIO+)L"B"B(.49`$)&?[*B`@`[IO`0IJ*E +M`C*B0CHB\D*]`#JFX!"F#`QRH@,RH0+2`KW@X'3B4F`6G0F"`L\6.`B2`K^0 +ME,"20K\`,Z:@$*:@H'0F&G;"0LX`-Z:0$*;V*2X`,Z:P$*8,"0`SIJ`0ID") +M(*"8DP`SIO`0I@R>@-D1\D+0X-T@`#VFP!"F#`(=\,+)_A;<"]+)_18]#`P) +M`#.FH!"FH)23`#.F\!"F#)Z`V1'R0M#@W2``/:;`$*8,`AWP``#"0K^&W_\` +M`$)"SD;A_P``0D*_`#JFT!"FXJ`7HA(7TD+1T-!TUSY_HF8B`#>FD!"F]BD\ +M`#.FX!"FDJ```#>FH!"F]BHU`#.F\!"F`#.FT!"F#)I`N2#"0L[0FY.`B1&@ +MB"``.*8@$*8,`AWP#!(=\"8I1"8Y7`P)!O#_)BI$9CK)`#NFX!"F4)D@1N__ +M````.Z;P$*8,J4;"_P``.Z:`$*8<24:__P"RS>IE>0ZRH@(,#*)F(D;<_P`[ +MII`0I@R)!M[_`#NFT!"F#"J@F2!&WO\````[IN`0IAP)1M?_`#9!`$'+`0P6 +M4J$]2D*2!(`RHB@Z,A8Y"((#%'?H$EIRL@?_`)LC()FP6IF2"0$F*6^R`QP` +MFR-WZPH@J;!:JJ(*`28J_P``K0(, +M#.6@_R"B(+(#',*@`B6@_T;=_P`V00!2H=1:4C(%@$(2#,'?`19#!'(53F(5 +M38(B-Z(B.++$?\"[$,"J`<"($0MF"W>R54.2$@U`=Q'`9A&@B"!P9B"AX`%Q +M:`"2R3^@F1"2542"9T9B9TD=\.%H`#(53M(536(B./(B-T)50\!F`<#_$0O= +M"S-R$@UR541`,Q'`W1%@_R`PW2#R;D;2;DD=\``VH0"2H^@QRP'!O@!Q20`P +M,H!B(R)V@!6R)X8,&`P*P+L0L+:5L*B#C%D+F8P:QOC_PJ(LRL+)D19I2=(, +M(0PE06@`_"V1U`&B(I1V@"8+F<(G@[(GPX@T\B1#XB=#P+L@L(@@@/\@\.X@ +M%FX3%FD3V`HF+1*&]/\`J`(,2\*@C,JJ)0+GHB*4V`K2S?X6O43R`B!7;PF! +MX0&"8Q^&`0``D>(!DF,?TJ("H>,`X3<`B`*1XP%2H0*(6,*E`K'D`8+(^Q8H +M%X'E`0`XIH`0IB;(`PSB'?``.J:`$*;XD8)/SP`UIO`0I@`UIH`0I@`UIO`0 +MI@`UIH`0I@`UIO`0IH*C`@`XIE`0IH'F`5!5H(!5H/@564&:@HE1@@B#4J$" +M\/#T%M@]@A(,]YBFDJ"HFI*98?AA\@]B(/^P\B].:O_R9$0`-::0$*:XD;(+ +MW!;;.8(A"8((TQ;X.9'G`8B1N%$,#_)(V))K,O*D`@`_IK`0II(A"9()W!8I +M10`\IH`0I@`UIK`0I@`UII`0IJQI=H`-`#JF@!"F`#6F\!"FG%_&^O\```!6 +M">Y9"F6'`:(BE$:U_P```(AA#`NY@9(8XO(8X[B1`)D1D/\@\F=3DB,BL@O3 +M#`_R2&"RR_X6^S^"(CH<[YJ(@F=.\F=4B&&8D8(8X_A1LAEK@(`D@F=&LF]# +MLB[P\B[=@J_[@(\0@F[=D@G3DLG^%IE$D0@!D)L0DF[P4M(FLB43#`[I<1;[ +M(&'-`3+2(VIBQB\`#$@`.*;P$*8`.J:`$*8`.J;P$*;QZ`$`/Z:`$*8`/Z:` +M$*;QN```/Z:`$*8`.J;P$*8`.Z:P$*8`.J;P$*:(D?)(S[*C`@`[IK`0IK9[ +M`H:1_X'I`8"+H(@(H`@`DB42/?"LJ8(CWB"B(&"V(.`(`*(C\9(C]R"JH*+: +M))DJ@B/D#!NM`N`(`+(E$AM$MS33Z($;[NF!T>H!`#VFP!"F)AP.@>L!`#BF +M\!"F\L__%N\2F'&B)1,;F9EQISD"!E$`N)&M`@P$0DLBI9P!\F,]\F,\\F,U\F,TXF,QXF,PXF,MXF,L +M\F,[\F,Z\F,W\F,V\F,S\F,RXF,OXF,NXF,KXF,JT>0!`#VFP!"F@J4"`#BF +ML!"FL+!TN8&BH@(`.J:0$*8`.*9`$*9"8_?R)1(,!!;O\X(CWJT"8+8@X`@` +MLB/QF)&B(_<@NZ"RVR2I*Y(9(<(CY)>T"ZT"#`O@#``&`@```*T"#!O@#`#" +M)1(;1,P$`/Z;0$*;2S8%6G>NQXP``.Z:@$*9&J_\``,B1P@PCHB*4/?`6 +M7"/8"M+-_A;M6PP.L6@`F&$,"K(K3-(9X_(I:K#(=-#,@K"P=,J["XNPBH." +M:6[I#^B1#!\,#=).(_).(<(G@9A1LBD\DBD]H<0`@+L1L)D@H)D@H6@`#`B2 +M:DRM`H)B0*4;#K';`>B1V%$,#*).(L)M/<)M/``[IJ`0IJ+*X!8:4PP2'?`M +M"AWP#!(,/_),(AWP`(B1J)@,L@P)F0I22"(=\```^)&0L'2R3]-6^\68D0P( +M@DG8!AG_B`*)$8BHL@.`]Q@-F!'YJ68;!@PKLD.`#"N80?@1F"F(OY"0])DA +MEQ@+F;]F&P8,*PPIDD.`\J"H^O+Y828;.\@"J+S(K/NJH*1!^\S`M/2B7^3` +MQ$&PJH+"7^.2'^.B7^*AS0'`F1&24@R"'^2RH)"JHL"($8)2#27P#9AADAGB +MMCD%"YF&````#!D,"Y"0](RY=H`&&[N0D?2,&8;\_ZA1LDJ!K0)EG/^AXP#" +MI0+A-P#X48A!#!NR3X.8.))O'HA(@F\?1MG^```\IK`0IOB1L+!TLE]K1NC^ +M.&&"(Q`,SYJ(@F=2\F=4#`B"9TB"9T>"9U^2`V`,J[/X!9/X"8)G8)(G8;+2 +M(V#Y(_)KPI">M$"9(Y)KPY(G8AN(8/DC\FO$D)ZT0)DCDFO%@F=@DB=A8/DC +M\FO&D)ZT0)DCDFO'\B=B8(\C\)ZT@FO(@5,`0)DCDFO)@/\0\F.!K0(, +M#=)B0.7@#2B1^%$,#J)"(N)O/>)O/`PB'?"XD9"`=()+TU8XY_B1#`W23]A& +MGO\````\IH`0IIB1@(!T@EEKAI[_HF=2#,BX88)G5`P(@F=(@F='@F=?T@M@ +M#*_S^`73^`F"9V#")V'2TB/`GK1@S"/";<)`F2.2;M&#,(\)M +MQ$"9(Y)MQ8)G8/(G89%3`/#.M&#_(_)MQD#,(\)MQ_(G8I"?$/#.M&#_(_)M +MR$#,(\)MR9)KG,:0_Y@"B`&9$9BIL@.`AQD-F!&)J68;!@PKLD.`#"N($8BX +M]Q@-F!'YN68;!@PKLD.`#"ORH*CZ\OEA)AL\R`*HO,BL^ZJ@I$'[S,"T]*)? +MY,#$0;"J@L)?XY(?XZ)?XJ'-`<"9$9)2#((?Y+*@D*"B@,"($8)2#26O#9AA +MDAGBMCD$"YE&```,&0P+D)#TC.EV@`8;NY"1](Q)AOS_````J%&R2H&M`F5; +M_Z'C`,*E`OA1TJ("#!NR3X-&/?^RH*#RH'A&-O^RH4#RH/`&-/^RH(#RH&#& +M,?^RH+#RH)"&+_^RH6#RH2!&+?^"`B"2H/Z0B!`,&9"((()"(`PB'?"XD0PJ +MHDLB1I?^`.$*`?$W`-AAX.H@XF_PV-T,C-<\`L98_X$W``Q/\/L@\FC=1E7_ +MB`I6&-Q&@?^HD0PIDDHBAG?_R)$,"[),*H9Y_P``-D$`?!9:A#IR,>T!BB=G +M(B:6P@.FLA0@8#0P9J!H!B`D(6`BD/`B$1WP```P(J`H`O`B$1WP```@(&`@ +M8#0P9J!H!B`D(6`BD"`@8/`B$1WPX"(1("/`*`(@(&#P(A$=\````#9!`'P6 +M&W(;DQNE&X1`A+-0I;,PD[,@<;X_PP2'?```!9L +M_UA1@J(DBE7"!2G\')'4`>(E"W:`)@N9\B.#TB/#R#2R)$.B(T/PW2#0S"#` +MNR"PJB`62DX624Z(#B8H$H;T_ZA1J`H,2\*@C,JJY4KFZ+6X#@P"LLO^%AM- +MZ%'RWB8B;QLB;QG"#B#Y`2)NF%=L"YA!@>$!@FE^!@(``+A!H>(!HFM^R%'1 +M[P%A4P!RW`':S,D1HB$%I5,`@@71,6[G4D@48`)DC()E3 +M@)FPDBE.ZIF9])(%(`"9(R"94X"9L)(I3NJ9F?2B"F*`JK"B*D[JJJGTD@7; +M9BEKZ$'"9"6X,2)D%>(N@;(K$)&L`.J[LF-2@B1#"YD6>#X6>3ZH,:(J:J@* +M9BKJN#'H`0S(@F-4DBXPXBXQ@BL6@)D1D.X@`(@1@.X@XF-(LBL6(.L1X+L@ +MLF-'A@4`HB$%97,`%MH+H"H@D```PF05'.F28U2X,0P.LAOCHA>V(D4JL+`D +MLF-&%MH$=H!&G0VM#((5)6)C5=/Z"O/Y"!O=O0GS^@+#^AK#^QVR8\DC^A;# +M^A3#^A4C^A(C^A.IQ"G$DF1,UY@%\L\!TJ``@A>V&^Z'O@.&[/\`F#&2*9F2 +MR?X6F3&B(0"R*C"B*C&`NQ&PJB"QQ`"PJB"B9$RB(04B:D"EAPW(`0P)HD4J +M(FPQ(FPPH@4J)CH()AH%TLK^5DWC+0D=\.A1X@XA!^X-J%$ESP"="KA1R`&& +M`@"H467#!9T*N%'(`28Y,+9)#`P?##B"12KR12F&XO]F*;4&X?^84:(9#9(9 +M#`"J$:"9()F$1HC_(D4I#"EF.P$`.J;P$*:2 +M#%#RSX$67PL,+X")$?"((``XIO`0IJ(,40PM@*H1T*H@`#JF@!"FB2&2%22" +M:T"7.!,,:8;4_P"H4:6_`)T*N%'(`<;0_Z@ALA4EI6$-N!&B:^.R%26B(0+E +M8PWH$;A1HF[BT@LAR`$'[0Z"I0(`.*;P$*;R;#>&!0"H(=(L,J"JH-"JH-*E +M`@`]II`0II):`:*A`@`ZIM`0IA:]$``ZIN`0IJS>=H`/`#JF\!"F@BN]&XB" +M:[V(,*(#_ +M$8#_(``_IN`0IN)5:@`ZIM`0II*B`@`YIH`0IH)%V_*C`@`_IN`0II(%V^)% +MXQ89!-*C`@`]II`0II)%X`NIHD7@"YF0D'06614`&4`,&*'P`:)L)@"(H8)L +M*+#X$?#@8.)L*_+/_Z"($8)L*?)L*I(%V]+)_A9=#N(+M(R.#.D,/_)%*@89 +M`((+(2=H.9(%X@P:D)J##/H[F:"98PPJ@)D1H)D@`#FFX!"FTJ$"`#VFH!"F +MH*!TC$H`.:;0$*;RH0(`/Z;@$*:8$8'L`8)I'()I'8)I(()I(8)I)()I)8)I +M*()I*8)I+()I+0P)5HG;#!W23%*B"R&@H`16J@JH426E`)T*N%'(`09G_P`` +M`%8IL_*@`O)N`"65`.(E"\;(_BD.#"(B12H,LAWP#!(=\`PH@D7;1C?_```` +M5AG"HB$#\F$&HBIJTF$'#"F9"N61``P$+F9"0=!8I!``90`P?X?`!XFPG`/^A\FPLH(\1@FPML/\1"X^" +M;"[P\&#R;"\&MO^!YP&";":&L?^H4:6/!9T*N%'(`48\_RT*'?"1YP&2;"<& +MK?\````V80""H@(`.*:0$*8RHD0Z,H(#Q,P8DD.[0J$"`#2FX!"FLL(4#`^A +M20#1TP&"$Q3"$Q7:T@"($8#,(,)J4Y(#N\(#Q/)+])+)_A;I"!9\%9(M?X(K +M-1SOFHB":D[R:E3"$Q7`P"3":D:LSJ@!=H`1`#2FD!"FT@/$X@.[C&V<63WP +MQOG_`!NJ)BX(\B,L\L\!\F,L5HG^J0$`-*:@$*:2`\(,*H(#Q("9$:"9(!9X +M"P`YIL`0I@`TIN`0IM(#Q#WP%OT*`#2FD!"F\@.[DD.\)B\$DD/1'?`=\``` +MDM(C5EP`@BG*@F$`PBU_@BLU#,7*B()J4E)J5/)J2/)J1_)J7X(+]`RLP_\% +M@_\)\FI@4BIA4,ZT8%4C4FG"0,PCPFG#@BIB&\^`7K1@B".":<1`52-2:<7" +M:F""*F'!4P"`7K1@B".":<9`52-2:<>"*F+`R!"`7K1@B".":(#NZ(36M#,@E+2(\JJ)BXQX@/1K$Z2 +M)\B)=%F`@0M"9)ET2!Q(:"G@.8:`H8G`.82`@8K +M`+T")2`-S0II$6@1:F>F%DSF$@(&*0"M!KT"R2&E'@V8(:"YP*(ES/"[$;)E +MT'JJIAI#YA("!B4`O0*E'`U]"J861.82`@8D`&"F(""R(&4;#:#'P/#,$<)E +MSL:>_^82`L8@`&"@8+T"R2&E&0V@H&"8(<;J_P"F$GR@H&"]`F48#:!P8.86 +MNJ82=[T"8*!@91<-H*!@!N[_`&D1IA)NH*!@O0(E%@V@P&`&U_\`(+!@:1$E +M%0V@P&!&T_^M!B"P8,DA)10-H*!@F"'&U/\@L&!E$PV@<&!&V?^M!B"P8&42 +M#:"@8$;:_ZT&O0+"80)E$0V8(8;*_[T"Y1`-?0J&S_\``*T&O0+E#PT&T?\` +MO0)E#PW-"D:\_P``-D$`#!=BH0(R`B%"HBQ*0B=C-%($V@PH#/E05X,[59!5 +M8X!5$8!5(``UII`0I@`VIH`0IH"`=!98```UIH`0I@`VICWPD!"FH@(6TJ`` +M)BH.4@33LL7_%FL.PL7]%GP-TD35X@(A-VX*4@33"_46[Q06M10R!-R"HP(6 +M(PX`.*:0$*:R!-,,.CWPLLO]%OL+P@(@)VP9T@3<%CT4`#:FX!"F\@3<%C\4 +M`#:F/?`P$*:2!-Q2I0(6*0L`-::P$*9B%&L6)@E2!-.Q\`'!YP$6)032!-P6 +M'0\`.*;@$*9B!-@61@=2TB8+9F!@=&)$V!9F#K)E)@`60`#GH>)E*+#>$="0 +M8))E*PO=H.X1XF4ITF4J4@33)B5D4M(F_.B1"(, +MXAWP```XIL`0IL)$VX;%_P`UIF`0IF!@=&)4:X;1_P"2!-P6&0@`.*;0$*9B +M!-D6EOQ2TB8+9F!@=&)$V19V![)E)P`60`"'H8)E+*"8$9)E+;"($0N8DF4N +M@(!@@F4OAM;_```VIJ`0IH:J_P`XIF`0IF!@=&)$V,;!_\)E)H;,_P```#:F +MD!"FDD3.1JW_`#:FL!"FLD30QJW_`#:FP!"FPD35AI?_`#BF8!"F8&!T8D39 +MQMW_`,)E)\:__P``-D$`#!5BI0)"TB.B(D`RHBPZ,K(3(67H#*)D\;(3(:(B +M0.7J#*)D\(("(0?H#0`VII`0II)D]X8%````LB)`PB3RL+N@P+N@`#:FH!"F +MHEL!HJ$"`#JFP!"F%JP3`#JFT!"FG%UV@`\`.J;@$*;R(S(;__)C,HPN1OK_ +M```ZIH`0IO(#V@PN@/\1X/\@`#^FT!"FTE-F`#JFP!"FLJ("`#NFD!"FPJ," +MDD/3`#RF@!"F\>P!PF0JPF0KPF0NPF0OPF0RPF0S +MPF0VPF0WPF0ZPF0['?`````ZIM`0I@P"P>P!PF0JPF0KPF0NPF0OPF0RPF0S +MPF0VPF0WPF0ZPF0['?``#`+A[`'B9"KB9"OB9"[B9"_B9#+B9#/B9#;B9#?B +M9#KB9#L=\``\II`0II)#V0NYLD/9"YF0D'2LB=)DYP`90`#%H<)D[*#\$?)D +M[;#,$0O\\F3NP,!@PF3O!L+_\F3F1K[_`/)DY\:^_P``-D$`0?$!`#2F,!"F +M@J$"4L$D6`46PP4`.*:0$*8PI\`ZUQ:)!:D%`#2F8!"F0L$H,L$@.`-(!+SF +M`#BFD!"F8*/`:N.\R:D$:`5L!W>F!&+&0&D%IL8$LL;`N058!#WP=Z4$4L5` +M603FQ0$=\,+%P,D$'?!Y!4;K_SD$1O+_V07&Z/\`Z02&[_\````V00#!\0$` +M/*:P$*8,+M*A`J+!)*@*%FL(`#VF@!"F@)(1X)D@%C@(`#FF@!"F#!^P_\#P +M\X+Z]X#_P`O_^0H`/*;`$*9RP2BRP2"X"W@'%BP%`#VF\!"F@)(1X)D@%B\& +M`#FFX!"F#!W`W<#0TX+:V^#=P`O=V0B`VHB*0HGI`1@XL#I"B@'5Z(% +M8"*`(F<`)R0!'?!@\L#Y!QWP>0I&YO^Y!T;S_P```#FF@!"F"_OP\X+Z]_J( +M&XB)"@;?_P```#FF(!"F"XR`@X**BXHB&R(I!T;G_P``-D$`HB)!DB*4#"@; +MJJ)B08D)90``'?``-F$`HJ`!95;;)9CEH3X`T6@`D4D`X6@`#`S":8#":<#) +M#L)M0+(I@KD!B`&@B""":8(=\#9!`'@#G`108&!:1PM$8$00*B0I`RT$'?`J +M9RT':0,=\````#9!``P2'?``-D$`#!(=\``V00`,%0S#)[,##`(=\"T%'?`` +M`#9!``P5#.,GLP,,`AWP+04=\```-D$`#!4<`R>S`PP"'?`M!1WP```V00`, +M%1PC)[,##`(=\"T%'?```#9!``P5'$,GLP,,`AWP+04=\```-D$`#!4<8R>S +M`PP"'?`M!1WP```V00`,`AWP`#9A`*T"Y18`C$HM"AWP``!120!QS0&Q-P"1 +M\@%\N*(K\,(KW3*B*#HR@(P0@FO=@@/70J"H2D*"R/X6J`V!"`&`BA"":_!Z +M`9J2F0%J8H@!@BC-K0*]!^`(`*(F/+'R`9(F0B"JH+JJDFHQ@B8JO0>M +M`N`(`,&T``P+LD9^TB6!UPP"!C<`W,KB`R?.Y";)#)^(#+@P?\D,E%LX$ +MLB1OH48`&[NR9&^2)8$,F*"9$)";09`HDQWP``#Q"@$,C?#Z(/)K\.(B-PQ( +M@(P@YST"!L7_@FO=AL/_`,@)5GSX+0H=\")#)D;I_P"R0RZR)&^A1@`;N[)D +M;Y(E@0R8H)D0D)M!D"B3'?`,LGS]#![B0R?298$=\#9A`)&L`#%H`(+2*XBH +M@F$!=H`1HB-#"YF,^A:9(;(BE+@+)BL(QOG_````%HD@0L(0P4D`\@(AHJ(B +MJJ+B"MWP\030_Q'P[B#B;(V80@P6TLG]%AT2TLGQ%KT1X@(@^`+@X`2(O_BO +M0.X!`(@1@/\@\.X@Z8."%`5R%`211@``B!&`=R!R;,92"M]R!!`,"[!5$7!U +M!-!W$7!5(%)C./(D-.(D,UT+P/\!P.X1\.X@Z6/8!/($%'(*W>($$((*VH!W +M$>#@!)"($3#_$=+-\=!9@X#_($Q=0(X14.X@@'<@/9T\(* +M&H@1`,PCL,Q3(,RPPBQ.BLS)\Y(*(@"9(["94R"9L)(I3HJ9F?-R!/I1]`$@ +M=[!R)T[A\P'1]@&*=WGS\@00PM(C+)_A8N)_+)_18?)B'Z`=)LWB)LY`P" +M'?"R$@V2`B""$@P`NQ&0D`1`F0&PB""0B"")@P:X__'[`?)LY?'\`9(*W>'L +M`5+2)B89,8+)_A;8#68Y`D8D``P"'![!ZP&1_0&R8SC291Z291_"91KB15"R +M2BP=\+)*+`P"'?``8F,5@@00J0$G:!"1_P&A_@&B;-Z2;-]&`P```+$``M'S +M`=)LWK)LWZ@!@@KB#`(,"X+($8"`=()%4("($?"((()E&N)L.^)L.N)L-^)L +M-N)L,^)L,K)*+!WP``"B(I1"PA`,*9D*);;_1GK_D0$"8F,5@@KBDF4? +M@L@1@(!T@D50@(@1\(@@@F4:XFP[XFPZXFPWXFPVXFPSXFPRT@2D%BWUJ0&X +M`0SB##JB2RP=\*D!8F,ELF,5T@KC,@KB'"B"15`WO0G,TRN3DD50A@$`S#TK +MK:)%4+($$"=K"BDQT0("TF4>Q@$`*3&!]`&"91Y!!`(Q`P(H,0P&<@50XFPR +MXFPSXFPZXFP[XFPTXFPUXFP\XFP]8FPO8FPN8FPK8FPJ@'<1.B+P=R`,`W)L +MV@P&95H,HF)#N-6F$T+F&\FPL&"M`R59#*"P8+)B +MNP;P_["P8"58#*#`8,)B0\;U_Z8;$:"@8"57#*#08-)B0T;Q_P```"56#*)B +M0T;N_P``IAL-K08E50R@X&#B8KL&X/^M`V54#*)BNT;=_Z@!#`(,"[)*+!WP +M``P"8F,5XFS>LFSD'?!R;-ZR;.0,`AWP`(@!8F,E@@@:#`+Q!0(`B"."8Q52 +M;-[R;.0=\*@!#`N1!@*2;.6&9O^A!P(,"Z)LY:@!1F/_L0@"J`&R;.4,"P9@ +M_Z@!#`OA"0+B;.7&7/^H`0P+\0H"\FSEAEG_J`$,"X$+`H)LY496_Z@!#`N1 +M#`*2;.4&4_\``#;!`%%H`.'<`0P'@B,3DB,1R-.X\ZT"?.T,$M"[$-#,$-"9 +M$-"($()C$Y)C$9)C'LG3PF,=`PPK=JL88BD< +MLBD=BYF6=@'6BP#`RT/0UE/RH`$]\.IJ5N\91@0```"6"__`QD/0VU,,'T;Y +M_^IJTB9_XB:`S0<+])T$\)>#X_P*T_P"<_P!<_P:D_P6(_P4<_P5<_P2<_P3 +M(_P;R<4F%!:H<[C3B,.@H`2PL+2`@-2S^`ZC^!R)Q9QTR)/8\[(C#L#`!-#0 +MM+"PU-/[#L/['+)E#/(F@.(F?]T'\_T*X_T"(_T!<_T:D_T6(_T4<_T5<_T2 +M<_T3(_T;V<4F%!FH@[(C$8(C$*"@!+"PM("`U+/X#J/X'()E#)QTR*/2(Q.R +M(Q+`P`30T+2PL-33^P[#^QRYQ?(F@.(F?]T'\_T*X_T"<_T!<_T:(_T8D_T6 +M(_T4<_T5<_T2<_T3(_T;V<4F%!>H<[(C'(C#H*`$L+"T@(#4L_@.H_@MX08I`.J-LLT_T+VS@L@@L+8AN8&@NQ&2RT"9H8<_,<";P)+) +M0)72)4.H<=#0!-D1R!'A#0(;JA:<"JEQIZ[A1B@` +M#`J=`WS]#"]VKR6R*1S"*1TF&@XF*AR6NP+6'`%R:1W&`@"(H8KKXFD2*3C`_Q&: +MB!N(P(@!@/\@^3'Y908!`*DAIRL8#!HE]^38,:@AZ&7I$<(A`;$-`J+*`=>< +MX2)#C`PJQL7_-D$`46@`H=P!@L3^#`O="VT+@&23JJ+R*H#B*G\P9K#S_0KC +M_0*S_0&S_1I#_1:S_12S_16S_1*S_1/9Q(F$-+$ +M_O#PM.#@U//^#NG%%NT.XBJ`TBI_G0OC^0K3^0*S^0&S^1I#^1:S^12S^16S +M^1+#^1.9Q8(F%?(F%.+$_H"`M/#PU(/_#OG%%FX,\BJ`XBI_W0OS_0KC_0*S +M_0&S_1I#_1:S_12S_17#_1+#_1/9Q9(F&8(F&/+$_I"0M("`U)/X#HG%%N\) +MXBJ`TBI_D0X"K0OC^@J:(H(B?]/Z`K/Z`X!@P*VL*R3'_!#P+@FA'*F<+, +M,)@)F1.28R+`RJ#(#,DS\@(@XJ$"4L(4!^\*`#ZFH!"FJ2.2(R+"R?D6'!;R +MI3\`/Z:@$*:VN@BBH`#0@H"R2'_Q$`*(,Y@3\,J@R`R2R?R*S,DS%BD2#`?R +M!0PG;Q68$R9)""8Y!8(C`Q9X```^II`0IIE3D:P`04D`=H`1HB2#"YF,ZA:) +M$,(EC\@,)BP'QOG_```6B0]AW@'2)3NH0VIB%@T+@B8PX`@`N#.PR@%PNQ'` +MNR#"H0O`NR``.Z:H0ZJGJ4/B!GZ(4Y(F/+$1`@P?()F@NM+"+=:ZF=(MUY(I +M*+@CP_T(\_T0#`RS_1&C_1*3_1>#_1P,.,/]'>/]'M)DR;(F/)(F.^T,L_X* +MD_X"D6@`P_X!\_X:@_X6\_X4\_X5P_X2P_X3Z/]"=)D8,)D8<)D8L)D5L)D51WP@B8PJJ>B8P3@"`"8,["J`7"9 +M$:"9(**A"Z"9(``YIJA#AM+_DJ("`#FF@>`>&LO\=\`#:LK(K +M(`PJJ0ME'__&O?\`-L$`4J$"`#6FD!"F#!8,!=*B+)D#5KD%VJ+RI#_A$@)R +MH`>RH!1"SF!V@"4`/Z;`$*8]\,>[!&)*(PP,X)R@F`F9$R99#I)C(D",H(@( +MB3.HF3)6<-28QA28Q128Q!9TU)C +M&5)C%5)C$:(I/)(I.U/^!:/X"I/X`E/X`6/X&E/X%F/X%&/X%5/X$E/X$XG' +M6<=B9%_R#PC14P#"TB/S_@GB9&!29&%29&)29%;29%72+/#"+/'3_`C"9TP= +M\```%MHWDL(8\BDZF:&B(P06CR*"(0V"*.7@"`#(,YBQL-H!<,P1T,P@#+W0 +MS"``/*:HP;A#NJJI0]@3X@E^PBD\LBD[B",@_*"S_`CRWR3X+X/\$:/\$O/\ +M%U/\'>/\'K8]`F/\$,)DR:(C(A;J%`O*%IP4TLK^%IU$Z-'R+O#B+O'S_@CB +M9TP=\(("(*+"&*)A"@?H"X*A`@`XIL`0IL)C`@`YIL`0IMJ2MKP$8DDC#`S1 +M$`*(,Z(C(M#2:"+.7@"`#(,[#:`7#,$=#,(-*A"]#,(``\ +MIJC!N$.ZJJE#D=X!V!.((YJ2F;'"*3SB"7Z2*3L@_*#RWR3X+Y/\"(/\$:/\ +M$O/\%U/\'>/\'O8]`D91`+T%V*&8L6/\$,)DR5G#4F,84F,44F,06=-28QE2 +M8Q528Q&"*3N2*3P,/^T%D_X*@_X"4_X!8_X:\_X68_X48_X54_X24_X3Z<=B +M9%_2#?"HT5/[!=/[";)D8%)D85)D8E)D5E)D5;(J\*(J\;/Z"*)G3!WPF-&H +MP[C3LF,9LF,5LF,1HF,0HF,4HF,8HBGQDBGPC06C^`J3^`)3^`%C^!I3^!9C +M^!1C^!53^!)3^!.)Q_C3Z,/8H?#PM.#@U//^#NG'8F1?T@WPS053_`73_`G" +M9&"XTZC#L+"TH*#4L_H.HF1AHF1BHF16HF15HB,BQHW_B-&8P8(HY:JIJ4/@ +M"`#(,["Z`9BQ<*P1L*H@#+NPJB``.J:H0P9U_P``5JKGZ*'B+HX,+=)N`"7? +M_H::_P""H@(`.*;P$*:B(R+@_Z#X#_G!QBG_K06XH8BQPF3)6<-28QA28Q12 +M8Q!9TU)C&5)C%5)C$?(H.X(H/`P^W06#_0KS_0)3_0%C_1KC_19C_11C_153 +M_1)3_1/9QV)D7[(+\)C14_H%L_H)HF1@4F1A4F1B4F164F15HBGPDBGQH_D( +MDF=,'?```,+2(\)A#:(L*K(L,L(L.J65`:)A":C1LBHSPBH[HBHKI90!\L,T +M@=X!G0JH@8J"B;&R*#/"*#72*#;B*#2B"MCY(9D!DL,PF1&"*#'XD>`(`)B! +MHB,B!OS^F,&"+.6JJ:E#X`@`R#.PN@%PK!&PJB"RH0NPJB``.J:H0P9E_P`` +MXB*4#"WRPACYH=D.9`(`*(C%+(C#,(C$&61`;C3J7'"(Q&B +M(Q6ED`'RPV2(T9T*J(&R*.C"*.K2*.OB*.FB"MCY(9D!DL-@F1&"*.;X<>`( +M`)B!!J3^K0*]`\*@`&5?_\BA8F1?P@SP4_4%P_4)4F1@N-.HP["PM*"@U+/Z +M#J)D89(C$8(C$)"0M("`U)/X#H)D8O(C%>(C%/#PM.#@U//^#N)D5M(C&<(C +M&+C1T-"TP,#4T_P.PF15PBOPLBOQP_L(LF=,'?``-N$`4J$"`#6FH!"F#!L, +M!?*B0*D#5GH%^F+A$@)"I#\<37+.8':`)0`TIL`0ICWPQ[T$LD8/#`S@G*"8 +M"9D3)ED.DF,B<*R@J`JI,YSEQO3_#'JB8R*2H0(`.::@$*8,&`P,J0.@R(,F +M'+Q&``"H`T%)`)%H`-'>`>*@B%8:$I(C(J*E/V$3`H+)_1:8,(+)_!8X,``Z +MIL`0IOIBMKP$LD8/#`RA%`+:DG+#,.J"B?%YP9GA>#.2(R*"PS2@K*"H"HG1 +M@LG^>JJI,W+2(Q:X0`O)%FQJ#`F,FN*A`@`^IM`0IME3HJ$"`#JF@!"FDF$) +MB6,6Z%Z"!M0;B()&U.*A`@`^IO`0IOES`#ZFT!"FV8/")_$,&]*B0"K,VLRR +M3.BB)RJR)S+")SKE8`&R)S.IH<(G.Z(G*R5@`;BAV,'R!L3HT:#*(!NOH*!T +M\J`!Y74`HB+#1-(&Q`P?S0H; +MK:"@=-+#0.5R`)&L`#WP=H`4XB2#"YD6+@L6V6?X1O@/\L_^%H\*AOC_VG(, +MB()C(F(G.\(G/*A#B%-C_`BS_!UB!WZC_!*#_!QC_!YM"\)DR5G#4F,84F,4 +M4F,06=-28QE28Q528Q&B)SSJPH(G.Z/V"JT%@_8"4_8!L_8:4_86L_84L_85 +M4_824_834_8;:J$,6Z4Z")^4,%N`( +M`,@SL-H!<,P1T,P@#+W0S"``/*:HD;A#NJJI0]@3N.'X4Y@CPBL\X@M^LBL[ +M((R@@M@DB"BS_`B3_!&C_!*#_!?S_!Q3_!WC_!ZV/0)C_!#"9,G88U9]"*(G +M\,(G\;T%\6@`P_4*H_4"L_4!8_4:L_468_448_45L_42L_43L_4;6<^8TXC# +MR/&0D+2`@-23^`Z)S^C3V,/28QC28Q328Q#B8QGB8Q7B8Q%B9%_"#("S^P7# +M^PFR9&"HTYC#H*"TD)#4H_D.DF1ADF1BDF16DF15@B?PXB?Q@_X(XF],'?"M +M`KT##`SEZ?[H\6)D7^(.@%/U!>/U"5)D8-C3R,/0T+3`P-33_`["9&&R(Q&" +M(Q"PL+2`@-2S^`Z"9&*"9%:HVH*)X18\0H(H,.`(`,@SL-H!<,P1T,P@TJ$+T,P@`#RF +MJ)&X0[JJJ4/8$_A3F"/HX7+2(\(G\;(G\.(.?B",H+/\"(+8)(@HD_P1H_P2 +M@_P74_P=\_P]CT"!LX`_04,'N/\$,)DR5G#4F,84F,44F,06=-28QE2 +M8Q528Q&B)_&2)_`,.*/_"I/_`E/_`>/_&H/_%H%H`./_%./_%5/_$E/_$U/_ +M&_G(XF1?T@:`O053^P73^PFR9&!29&%29&)29%929%6B)_&RHD`JJKJJ4DKH +MDB?P\B?QD_\(\FA,'?",FM*A`@`]IL`0ILE3HB`(`*C# +MLB`( +M`)&L`#WP"YFB)(,6&B86&2:X\;(KMCL$#!JC_!"M`L)DR;T# +M#`QE\OZ(\0P9DF1?@@B`_053_P6#_PGR9&#HT]C#X."TT-#4X_T.TF1APB,1 +MLB,0P,"TL+#4P_L.LF1BHB,5DB,4H*"TD)#4H_D.DF16@B,9\B,8Z.&`@+3P +M\-2#_P[R9%7B+CSRHD`J[OKN4D[HTB?PLB?QP6@`T_L(LFQ,'?``HB?QLJ)` +M*JJZJE)*Z*(G*K(G,L(G.N4#`;(G,ZE!PB<[HB`(`$:0_@"8D8(G +MY:JIJ4/@"`#(,["Z`0P6<*P1L*H@#+NPJB``.J:H0T;#_@``5HG(XB9R#"W9 +M#N4[_M'>`08>_P#2H@(`/::0$*;!$P*H,\"9H)@)!E'^##_M!<)DR5G#4F,8 +M4F,44F,06=-28QE28Q528Q&2)_&")_`,'9/^"H/^`E/^`=/^&O/^%O%H`-/^ +M%-/^%5/^$E/^$U/^&^G/TF1?L@:`K053^@6S^@FB9&!29&%29&)29%929%62 +M)_&BHD`JF:J94DGH@B?PXB?Q@_X(XF],'?"X\;(KPL620O-"X"[ +M$>"[(``[IK`0IL"`=``80`"JH9"!8`N(@(J"BKL;N["`8)"XHP`_II`0IHRI +M`#VF@!"FD/!@@)^3"](6+0@6^0>`_!'@_R``/Z;`$*:0T6`+W=#:@MK,&\S` +M\&"0SZ.Z,SD%,",@L+H1L+!@MZ,'H"H1(".`*06P.A$W(@>@BA&`@L")!;SG +M&R1`)+,@(2$J+/`B$2D&MZ(&H(H1BB(I!C>B`QWP``"@FA&0DL"9!AWPO0D+ +MPL"`=``80`"JH<;8_\T)!N;_`,HD*0;&\?\`-L$`\J$"`#^FP!"F#!<,!,D# +M5FP)LL(84J0_'$WA$@*BHBR@HH!BSF!V@$4`-:;`$*;'O1Z8#G)*(YD3)EDU +MDF,BB`:),\(+D&8L(?8I'@80````X)R@F`F9$R99%I)C(F",H(@(B3.""Y`F +M*"&\A#WPQNS_#'F28R(`/Z;`$*8,&`P)R0/`F(,F&9\&!P``]BG:`#^FP!"F +MPF,A%NS\@B,B6XB"8R)65/S(`U%)`)%H`!8\"*("J&+"&*+*_A9J(:%3`.T' +M\M(FTB\P@B\QR$.R#U+3^`C#^!)S^!VS^!Z"9G)2$86FD@+FA9)2++2(\+2)LG!N='2ROX6/56AK`"8 +MH:+*_^(E@Q8>+18:+?B9\B\`HLK_9B_K@B8ZJ$,6^#Z(T8(HY>`(`,@S\6@` +ML-H!<,P1T,P@#+W0S"``/*:HL;A#NJJI0\C!V!.8([(L,>(,4L(L,""+H(+8 +M)(@HP_L(D_L1H_L2@_L70_L=X_L>MCT"<_L0LF7)HB,B%EHN"]H6#2YF*F:M +M`KT#PJ``)9C^@F7) +M@B\Q\B\PS02#_@KS_@)#_@%S_AI#_A9S_A1S_A5#_A)#_A-S_AGIR4G)(N``NJ/?!F+NJH0_(F.H+2(X)A#19?,((HY>`(`,@S +ML-H!<,P1T,P@TJ$+T,P@`#RFJ+&X0[JJJ4/8$X@CDM(FF<&R*3'B"5*2*3`@ +M^Z#RWR3X+Y/["(/[$:/[$O/[%T/['>/['K8]`G/[$-T$P6@`J,&R9`(`*(C(H:W_@`= +M\)BQ@BCEJJFI0^`(`,@SL+H!<*P1L*H@LJ$+L*H@`#JFJ$.&/?\``#ZFT!"F +MP-V@V`W9L88@_\C1HBPJLBPRPBPZ)68`J5&B(0VR*C/"*CNB*BOE9`#RPS2( +MT9T*J*&R*.C"*.K2*.OB*.FB"MCY(9D!DL,PF1&"*.;X4>`(`,C1J,.R+#;" +M+#HE:P#(T:EAHB,-LBPWPBP[)6H`B-&="O+#1*BALBCHPBCJTBCKXBCIH@K8 +M^2&9`9+#0)D1@BCF^&'@"`"HT;C#PB,0HBHN96T`J7&HT;C3PB,1HBHOI6P` +M\L-4B-&="JBALBCHPBCJTBCKXBCIH@K8^2&9`9+#4)D1@BCF^''@"`"B(Q2R +M(PS"(Q#E:P"XTZF!PB,1HB,5)6L`\L-DB-&="JBALBCHPBCJTBCKXBCIH@K8 +M^2&9`9+#8)D1@BCF^('@"`#&9/XVH0`Y8:*B>HASV&.1%0(,&]#;DYJ2\BF! +MXBF`PBE_DBE^T.^3Z4'0G).941:H&JJ2D@F`\)D1D)O`N&&9`;B+"\0,"1:+ +M&9D1%@P:#`T,#NF1TF$(2&$]`:A1F$'Q%P)1%@(,2(EQ6E+Z\ODQH)G`F2&X +M82A1:$&X:\@QHB5_C)M7/`<3&YO\```"F$@^@H&"]`J4X"J!P8'G$1N'_O0+E-PI]"JG$1M[_(+!@ +M)3<*H&!@:=1&XO\```"F$@^@H&"]`J4U"J!@8&G4QMS_O0+E-`IM"JG4QMG_ +MD*J"IAH>IA(*O0*E,PJIY$;:_P`@L&#E,@J@L&"YY(;6_P```*82#Z"@8+T" +M93$*H,!@R>0&T?^]`J4P"JGDAL[_``"0JH*F&AZF$@J]`F4O"JGT!LW_`""P +M8*4N"J"P8+GT1LG_````IA(/O0*@H&`E+0J@P&#)],;#_[T"92P*J?1&P?\, +M"8:6_P"JDI()@'S[L)F01I;_D?$!`#FFH!"FJ8&RH0*,Z@`[IN`0ILB!P-!@ +MX,V3R8$`.:;P$*;YD1;/XP`[IJ`0IHB1@)!@H(F3B9%&BO\`-F$`4J!W018" +M8M(CDB;-@B;/#$=*0I"(P()A`*(D?[*OB9;J`:*8;924C"JG#!B4```"WJD'")L^R)LV@K(*F&ARF&PEE(0JIPP8>````L+!@ +MI2`*H-!@V<,&&@```*8;#:"@8&4?"J#@8.G#1A4`I1X*J<-&$P"!&`+@^A'P +M\L"*__(O?_#P8/G#Q@T``+"P8*4<"J"`8(G#!@H```"F&PV@H&!E&PJ@D&"9 +MPT8%`*4:"JG#1@,`P1@"(+J@RKNR*W^R8PRB)(#BKXF6R@&G)0*&)@#2)L^R +M)LW0JH*F&G6F&V)E%PJITP8D`.>J0/(FS[(FS?"J@J8:&Z8;".45"JG3AAT` +M`+"P8"45"J"`8(G3QAD```"F&PV@H&#E$PJ@D&"9TP85`"43"JG3!A,`P0," +MX+H1L++`RKNR*T.PL&"YTX8-``"PL&`E$0J@P&#)T\8)````IAL-H*!@Y0\* +MH-!@V=,&!0`E#PJITP8#`/$#`B#JH/KNXBY#Z=.B)'^2KXF6R@&G)0+&)0"( +M`;(FS8"J@J8:J/;@!L*J"LB;-IAH9IAL'90H*J>,& +M'0"PL&"E"0J@P&#)XX89``"F&PV@H&"E"`J@T XP85`.4'"JGC!A,`\0," +MX.H1X.+`^N[B+KO@X&#IXX8-``"PL&#E!0J@\&#YX\8)````IAL-H*!@I00* +MH(!@B>,&!0#E`PJIXP8#`+$#`B":H+J9DBF[F>.B)(#2KXF6R@&G)0+&)0#( +M`;(FS<"J@J8:J/>@!LB;-X*J"IAH9IAL')?\)J?,& +M'0"PL&!E_@F@\&#Y\X89``"F&PV@H&!E_0F@@&")\P85`*7\":GS!A,`L0," +MX)H1D)+`NIF2*;N0D&"9\X8-``"PL&"E^@F@H&"I\\8)````IAL-H*!@9?D) +MH+!@N?,&!0"E^`FI\P8#`-$#`B#*H-K,PBR[R?,RPQ"+1`MW5K?1'?```#9! +M`">C"3D$2T$'?`G)`PWI`,M!!WP+0,=\!WP'?```#9!`''L`7<2%G<3 +M*W<4.">C!C>D&RT#'?`GI`\=\```=Q-H=Q0YEB,$EE0%,"1#'?`GI`\M!!WP +M=Q1:IA(YED0$)R3O'?```">C#.83QJ82\@P$+00=\`#F$L`&`0```);C``P$ +M,"1#'?```#P!=Q,N=Q0[)Z,)-Z0>+0,=\````">D#QWP```G)/@,`S`D +M0QWP```P)$,=\">D#RT$'?!W%"RF$N&6!`(G).\=\```)Z,,YA/#IA+R#`0M +M!!WP`.82P`P$,"1#'?`,`RT#'?`=\```-D$`8>P!#`5@8L!@)8,GHPHW)!,G +MI`XM!!WP`">D`1WP0"-#'?`=\"T#'?`V00`GHPDW)!(GI`TM!!WP)Z0!'?!` +M(T,=\!WP+0,=\#:!``P;DJ``84D`46@`HB+&(D\?(/4B"9H-/^ +M",/^$)+9)`PLF"FS_A&C_A*]`ZT"D_X7@_X=\_X>XF;));O]#`D,&[D#QMK_ +MK0*]`\*@`65__Y&L``N9@B:#%L@\%LD\J)>H"I+)_V8J[,(B0++2)MA#%DP_ +M@BLEN5&M#>`(`(@SZ%&PF@%PB!&0B"`,N9"((``XIMA!^$/ZW=E#H@Y2DB3Q +MXB3P#`L@R:#C^0C"W"3H(\@LL_D0X_D1T_D2P_D7L_D=#"R]`Z/Y'I)FR:T" +MY;']#`D,&P:V_P``@L,TH@?8LB3HPB3JTB3KXB3I\B0JDB0KF0&)(9+#,)D1 +M@B3FX`@`@L,\PB3NTB3OXB3M\B0LN,.2)"VR9"JR).RHTZ)D*Z('V9D!B2&2 +MPSB9$8(DY^`(`)&L`-CCTF0LR//"9"T+F>(F@Q8>+Q89+_(BE/@/DLG_9B_K +M@B)`LM(FV$,6"#."*R6Y4:T-X`@`R%$,&_@S#`FPB@%P_Q&`_R`,N(#_(``_ +MIMA!Z$/JW=E#@B3PHBPQ\B3QZ",@JJ"#_PBBVB2"#%*H*I/_$./_$=/_$J/_ +M%Y/_'8/_'O)FR8C3Z/.HX_C#\F,8\F,4\F,0HF,:HF,6HF,2XF,3XF,7@F,1 +M@F,5@F,9XF,;#"CB+#&B+##]">/_"J/_`I/_`;/_&H/_%K/_%+/_%9/_$I/_ +M$_G%Z-.HP^#@M*"@U./Z#JG%B//XXX"`M/#PU(/_#OG%QF#_`(+#/*('V;(D +M[,(D[M(D[^(D[?(D+)(D+9D!B2&2PSB280&").?@"`"1K`"XX[)D+*CSHF0M +M"YG")H,6W!T6V1W2)PG8#9+)_V8MZ^(B0++2)MA#%HXC@BLEN5&M#>`(`,A1 +M#!OX,PP)L(H!A#ZMW90_(D\>(D\(@CK0_C^@@@ +M_Z#B#%*3^A#RWR3X+X/Z$=/Z$O/Z%Y/Z'>/Z'J)FR8CS^./R8QKR8Q;R8Q*" +M8QN"8Q>"8Q/B)/&B)/"-">/X"J/X`I/X`;/X&K/X%K/X%+/X%9/X$I/X$XG% +M^//HX_#PM.#@U//^#NG%QB'_`(+#-*('V+(DZ,(DZM(DZ^(DZ?(D*I(D*YD! +MB2&2PS"280&").;@"`"1K`"XP[)D*JC3HF0K"YG")H,6'`\6&0_2)PG8#9+) +M_V8MZ^(B0++2)MA#%HX6@BLEN5&M#>`(`,A1#!OX,PP)L(H!A#ZMW90Z(D\8(D\.@C_0J#_P@@JJ""#%*3_Q"BVB2H*N/_$=/_ +M$J/_%Y/_'8/_'O)FR>C#XF,8XF,4XF,0HB3Q@B3P_0FC_PJ#_P*3_P&S_QJ3 +M_Q:S_Q2S_Q63_Q*3_Q/YQ>C3J,/@X+2@H-3C^@ZIQ8;E_@P*J4'&WOX,#=E! +M1O+^`%;)P_(BE`PNZ0_EU?S&"_]6B=&2(I0,*(D)Y=3\QD+_5LGBLB*4#"JI +M"^73_,:'_U:)\=(BE`PLR0WETOS&PO^H0;E1@BLEVJJI0^`(`+@SZ%&PR@%P +MNQ'`NR`,O,"[(``[IMA#1@+_J$&Y48(K)=JJJ4/@"`#(40P;V#,,";#J`7#= +M$>#=(`R^X-T@`#VFV$-&,_^H0;E1@BLEVJJI0^`(`,A1#!O8,PP)L.H!<-T1 +MX-T@#+[@W2``/:;80T9Q_ZA!N5&"*R7:JJE#X`@`R%$,&]@S#`FPZ@%PW1'@ +MW2`,ON#=(``]IMA#1J7_-L$`#!QA20!1:`"B(L9RT@$,"Q8:"T+2(Q9Z&)+2 +M)H(I,*(I,:E!^$&#_PCY0>A!V$/#_AWI0:A!@@E2T_H2J4'X08/_'OE!Z$'B +M9LFR8Q&R8Q6R8QFYT[)C$+)C%+)C&+G#R4&H0=(I,9(I,-/Z"JE!B$&3^`*) +M0?A!L_\!^4'H0G%N<7)`Z(D\-(D\=E!F$&C^0B908A!@F5,'?`\_@`^IJ`0IJ)C +M(-@'0M(CN;%6K0BR9E^Y09A!#*J"!PBC^0690?A!@_\)^4'H0>)F8-(F8="N +MM&#=(])DPD"J(Z)DPY(F8I".M&"9(Y)DQ$"((_A!@F3%\L\!\F9@XB9AX-ZT +M8.XCXF3&0-TCTF3'XB9BH5,`X/T%X(P%X)L%H*X0X-ZT8.XCXF3(0-TCTF3) +M\F>)@F>(DF>'HF>&HB,@%LIX@J$_`#BFT!"F#"[R(R"BH0+9LR8O.K)C`[)C +M`/*B0,P=!@4")AUFDLW^%HDR@LW]%B@VDB>&5GGGPB3PTB3QV4&X0?ZR)"ZH<<(D+]+#0*(*Q.+#1/*@`1NJH*!T97?^V)&H<>(A"K(D+*(*Q<(D +M+?*@`:+*`:"@=*5U_K(D,*AQPB0QTL-(H@K%XL-,#!\;JJ"@=.5S_N(C$.)D +M+M(C$=)D+\(C$L)D,+(C$[)D,08A``"B)/&9<2JJ^JJR2NB""=39@>G!9A@" +M!B0"B,&R).C").K2).OB).FHA!DMDDF"FC_A+I08A!^%.3^!>)0>A!\_XE!F$'3^1Z908A!@F;)^&-67TNB)/&Y09A!@B3PH_D*F4'X08/_`OE!Z$&S +M_@'I0=A!P_T:V4&800PJH_D6F4&(0A!L_X2Z4'80;/] +M$]E!J$&S^ANI09A!F<6(P_C3@(#4B4'H0?#PM//^#NE!V$'9Q?CSF..HPXC3 +M@F,1@F,5@F,9HF,0HF,4D)#4F4'H0:)C&/#PM//^#NE!V$'9Q9CSJ..B8QJB +M8Q:B8Q*28QN28Q>28Q,&-_\`.J;0$*;ZDH+#.(F1V6."PSR)H1;-7LE1F7$, +M"(EA#!JE%.*B)4.@H`2I4:AAF%&Q#0(;JA;)'ZEAIZOA!GT``#JF@!"FTL,P +MXL,T^I*9<8EC%J@&@J$"`#BFD!"FF7,`.*;P$*8,&X*B0*AQ^8/")/$,'Y(* +MU"K,BLP;F9)*U+),Z*(*Q+(D*L(D*QNJH*!T94K^LB0NJ''")"_2PT"B"L3B +MPT0,'QNJH*!TI4C^PB,0PF0NLB,1LF0OAA(```"2)/&(<2J9^IFR2>B""-3I +MP=F!"X@6R&6(P;(DZ,(DZM(DZ^(DZ:AQ\B0JDB0KH@K$F0&)(8B!B1&").;@ +M"`#(P\)D+KC3LF0OD:P`Z,/B9"K8T])D*PN9\B:#%H]*%HE*@B=4B`@+F68H +M[)@'J$,6&52").7@"``,'.@S#`NP^@%P[A'P[B`,O_#N(``^IJBQV$/:JJE# +MTM(F@BTPDBTQF4'X08/_"/E!Z$'X([/^$.E!Z$$@F:#S_A'I0>A!DMDDF"FC +M_A+I08A!^%.3^!>)0>A!\_XE!F$'3^1Z908A!@F;)^&-6 +M/R>2)/&Y08A!\B3PD_@*B4'H0?/^`NE!V$&S_0'90:A!P_H:J4&80;/Y%IE! +MB$'#^!2)0?A!P_\5^4'H0;/^$NE!V$&S_1/90:A!L_H;J4&809G%B,/XTX"` +MU(E!Z$'P\+3S_@[I0=A!V<68TZC#HF,8HF,4HF,0DF,9DF,5DF,1QJG^#!H, +M"PP,R6&R926B914,&F7RX?(E)>(E%:AAP/\1\.X@Z5'848$-`J+*`28=!:)A +M!J>HV0P;LD.,@J$"`#BFD!"FF9,`.*;P$*;8D>BA@J)`J''YH\(D\0P?D@K4 +M*LR*S!N9DDK4LDSHH@K%LB0LPB0MHLH!H*!TI2C^LB0PJ''")#'2PTBB"L7B +MPTP,'Z+*`:"@=.4F_L(C$L)D,+(C$[)D,9&L`.CCXF0LV//29"T+F?(F@Q9? +M+!99+((G5(@(DLG_9BCKF`>H0Q:9-((DY>`(``PE!Z$&2V228*:/^$NE!B$'X4Y/X%XE!Z$'S_ASI0>A!T@U2L_X=Z4&8 +M0=/Y'IE!B$&"9LGX8U8_"9(D\;E!B$'R)/"3^`J)0>A!\_X"Z4'80;/]`=E! +MJ$'#^AJI09A!P_D6F4&(0A!L_X2Z4'80;/]$]E!J$&S +M^ANI09A!F<6(X_CS@(#4B4'H0?#PM//^#NE!V$'9Q9CSJ..B8QJB8Q:B8Q*2 +M8QN28Q>28Q/&-?ZM`KT#PJ`"I:7\#`L,'(8Q_@"M`KT##!REI/P,"PP<1BW^ +MK0*]`PP,I:/\#`L,'$8I_@P+#!KB)X?I8](GB-ESPB>)R8.IH[F3K0*]`PP, +MI:'^LB3PPB3QR4&H09@C#`BS^@BI0?A!HM(FXBHQ@_\0^4'X08A#(.Z@D_\1 +M^4'X0>+>).@N@_\2^4'80Y8Z(GB+T#J7.M`I(GB9F#^:.)D^66_I&L``N9 +MPB:#%@P9%@D9TB=4V`T+F68M[.@'J$,6SAV").7@"`#(,[#:`7#,$=#,(`R] +MT,P@`#RFJ+&X0[JJJ4.2TB;"*3#R*3'Y0;A!P_L(N4&(00P.N"/C^!")08A! +M(/^@L_@1B4&(0?+?)/@OH_@2B4'80B4'X0?)FR=ACZ4$6_1>M`KT##"SEB_P,"PP<1LK]5DG4Z''H3M*@ +M`M)N`*4?_`9-_P!6";:(<8A(\J`"\F@`91[\!M3^`)BQ@B3EJJFI0^`(``P< +MZ#.PV@$,"W"N$="J(`R]T*H@`#JFJ$/&._X`HB3Q*JKZJK)*Z(()U)EQ"X@6 +MR!.(H;(D[,(D[M(D[^(D[:AQ\B0LDB0MH@K%F0&)(8B1B1&").?@"`#(X\)D +M,+CSLF0QQB+_F+&").6JJ:E#X`@`#!SH,[#:`0P+<*X1T*H@#+W0JB``.J:H +M0X8L_YBQ@B3EJJFI0^`(``P>"(I0,+_D()1'\QIK_K0*]`PPL);;\#`L,'$:"_P``R'$,#PP[H@S$ +MLDS4LB0JPB0K&ZJ@H'3EY?T&WOT``-B1Z*$,#\AQ##L;JJ"@=+),U+(D+,(D +M+>7C_0;B_0"8L8(DY:JIJ4/@"`#(,["Z`7"L$;"J(`R[L*H@`#JFJ$/&A_^M +M`KT##"SEKOP,"PP<1FK]``"H<0P[#`^R2M2B"L2R)"K")"L;JJ"@=*7>_09K +M_@```-B1Z*&H<0P[#`^R2M2B"L6R)"S")"T;JJ"@=&7<_0:R_P`V00`,"`PY +M<1D"8J'04L(8,@7PHB4Z:F)"%DYZ:!X)GBQO,PF>*X!"FT@9_#"+,7?(ECO@/G-\R!0@P +M-T$P*8,=\*`0I@PBDD9^@F4Z@F>+@F>*'?``L@4(+0BPMT&,"QWPTB=T`#VF +MP!"F"\S`B8,M"!WP```V00!2H+A:4C(%4`P&H4D`&S,P,'0R15`F@T&"%=IB +M:E62)1+1W`&R%=L;F9)E$I<8(MHBPB*`,B)_&\S"8H#'&P7@$*8=\`!B8H`; +M,S)B?_`0IAWP@!"F8F42'?!B15#&[?\`-D$`#`D,/:'L`7+2(X+2`F+"&+(F +M.D(&\%(8-AN[&T1`0'1"1O!FA`*21O"R9CJWE3+22$Z29CJ29_&29_"B9RJB +M9RNB9RZB9R^B9S*B9S.B9S:B9S>B9SJB9SO(`PPB%HP.'?#B)_'R)CW"(Q2P +M[A'JXL)NZE(G\4(C%;!5$5I20F7KXB?QPB,8L.X1ZN+";NY2)_%"(QFP51%: +M4D)E[^(8-\(G\?"[P`ON&\S"9_'GO%SR(Q#R9RKB(Q'B9RM2(QA29RY"(QE" +M9R_R&#>P7!%:(O&Y__P$*8, +M(AWP`*)G+Z)G+E(G\*)G*Z)G*AM50A@W4F?PDF?Q1ZM#HFWKDGB(NKB9S+"(NO"9S.R(NZR +M9S:B(N^B9S=&S?]2(O)29SI"(O-"9SOR&#>WKUCB(NKB9S+"(NO"9S.R(NZR +M9S:B(N^B9S<&PO\``*)G,J)G,Z)G-J)G-\:]_P#R!@CP]T&\+RT)'?"P3!%* +M0K(DZK)G,J(DZZ)G,U(D[E)G-D(D[T)G-X:R_Z)G,J)G,Z)G-J)G-\:N_P"B +M)]H`.J:`$*8+B("=@RT)'?```#9A``P^D>P!#`KRHD!RPAA"!_"")SKZ8E(6 +M%H+(`:)&U$+$`4!`=$)'\&:$`J)'\()G.H>5-<+2(^)&#J)G.J)L\:)L\))L +M*I)L*Y)L+I)L+Y)L,I)L,Y)L-I)L-Y)L.I)L.[@##"(66R@=\+(G/=ACL+C` +M%DT,@B,B%F@>"\@6'!Z"TB/"*/%2(Q2PS!'*POK,4FQ:0BCQTB,5L$012D+Z +M1-)D6\(H\5(C&+#,$2VB!PB@IT&@+H,=\`""TB/"*/%2(Q2PS!'*POK,4FQ:0BCQTB,5 +ML$012D+Z1-)D6\(H\5(C&+#,$K%))H,I)H,Y)H-I)H-Y)H.I)H.P9Z_](&Z5(F8A9M%-+2$$(M\DI%0,`$ +M0$$AP$0@0F@ZTBWSPB9C#!3:S,#0!,#!(=#,(,)H.T)&U%(6%[\F@VTB5?TF@W!A+_(F@RPB5;PF@S +MLB5>LF@VDB5?DF@W!@S_-D$`#`FA[`&Q20!RH+AZB9AJB9AO")M>B9AZB9A]6;`G@$*8=\```G)2 +M9^I")M7R)NRP1!%*0O)DZ^(FU=(F[[#N$>KBTF[NPB;5LB;PL,P1RL*R;.^" +M&#=R)M6R)N@+B!MWTBWSTF8?XB;7%CX('?`` +M`(>70*)F'J)F'_(F\$(F[X(FZ)(FYYGFB?9"9A+R9A,6DP>PIQ&JHM(JZM)F +M%L(JZ\)F%[(J[K)F&J(J[Z)F&\;L_P``HF83HF82J?:")M2IYI)FU1N(@F;4 +M0B+J0F86\B+K\F87XB+NXF8:TB+OTF8;PB+RPF8>LB+SLF8?1MW_D!"F'?"B +M9A:B9A>B9AJB9ANB9AZB9A_&UO\``*)F%J)F%Z)F&J)F&X;2_P`V00`,"0P] +MH>P!5,L@# +M#"(6[!'22$Z29CJ29_&29_"B9RJB9RNB9RZB9R^B9S*B9S.B9S:B9S>B9SJB +M9SL=\.(G\?(F/<(C%+#N$>KBPF[J4B?Q0B,5L%416E)"9>OB)_'"(QBP[A'J +MXL)N[E(G\4(C&;!5$5I20F7OXA@WPB?Q\+O`"^X;S,)G\>>\7/(C$/)G*N(C +M$>)G*U(C&%)G+D(C&4)G+_(8-[!<$5`B@/\(FCL(L`!8\$^(&".#G0>`M@QWP`.><=?(G +M\+(C$+)G*J(C$:)G*U(C&%)G+D(C&4)G+Q:O^[#L$>KB4B[J4FK0J)G,J)G,Z)G-J)G-Z)G.J)G.P;,_P!"(O)"9SKR(O/R9SOB +M&#>WKDGB(NKB9S+"(NO"9S.R(NZR9S:B(N^B9S>&P/]2(O)29SI"(O-"9SOR +M&#>WKRSB(NKB9S+"(NO"9S.R(NZR9S:B(N^B9S=&M?\``*)G,J)G,Z)G-J)G +M-P:Q_P"B9S*B9S.B9S:B9S<&K?\`(B?:`#*F\!"F"__PG8,M"1WP```V80`Y +M(2D1.!&120`RPQB"`_`,%PP"&XB`@'2"0_!FB`(B0_"((0P$(FE5@@B,46@` +M80T"%C@&>0$;1`P:)=G@LB5#L+`$N0&H`18J`$>FZ`P$P!P(@!P'<1@'<@>67&````9Q0B&T0,&J75X*AEJ0&8`7>9[-(E%<(E)<#= +M$=#,(,D!N`%F&]GH(2).C+$<`F$;`H(C.E@10J'0&XA*16I5\A1.##:"8SJ` +M_\`6/PR!20`,J2)H7_(#\,T"D_P%\_P)PFA@XBAAX-ZT8.XCXF5H0-TCTF5I +MXBAB&\S@WK1@[B/B96I`W2/296O":&"B*&&@GK1@JB.B96RA4P!`F2.296V" +M*&*@J!"`S06`W`6`ZP6`_K1@B"."96Y`_R.2)9?R96^"%$_B9%/29%3"9%6B +M9%(;F9)EEY>8$Z@1PB66(F67NJH;S"P+PF66)=('N"&R*P`F&P+`$*;2!'_, +M7>(CCN@.K.[R`P@,(O#W0?`F@QWPJ!%B1'XB8SHB99X +M(;@+)AL.P!"F'?#2`PC0UT&,+1WP'?#R)8``/Z;@$*8+[N`F@QWP-D$`0>P! +MX1P"HM(!DB)`PJ'.RL*"'$\;F9)B0)"(P)$=`C"P=`P-FC(6R!S!20`,J-)L +M7_(*")T-@_D%\_D)DFQ@@BQA@/ZT8(@C@F.E0/\C\F.F@BQB&YF`_K1@B"." +M8Z=`_R/R8ZB2;&""+&&`_K1@B"."8ZF!4P!`_R/R8ZK"+&*`C!#`GK1@S"/" +M8ZM`F2.28ZSR(]2"8L;"(^:P_Q'Z\L)OZI(CU((CY["9$9J2@FGK\B/4PB/N +ML/\1^O+";^Z2(]2"(^^PF1&:DH)I[_(CU,(CZ+#_$?KRPF_LDB/4@B/IL)D1 +MFI*":>WR(]3"(_"P_Q'Z\L)O\)(CU((C\;"9$9J2@FGQ\B/4DB/GPAJW&Z^B +M8]3'NF^9X\(CYM(CZ>(CZ/(C[X(C[H)C$?)C$NGSTF,0R=.2(_&28Q3"(_#" +M8Q,6FQ.PVA'0TH#B+>KB8Q7"+>O"8Q:R+?*R8QV2+?.28QZ"+>R"8Q?R+>WR +M8QCB+?3B8Q_2+?728R#B(]8+[A9^"O`0IAWP"XR`BL!6Z`G"(^:2(^?2(^GB +M(^B"(^[R(^_R8Q*"8Q'I\])C$)GCR=.2(_'"(_#"8Q.28Q06J_NPVA':TN(M +MZN)C%<(MZ\)C%K(M\K)C'9(M\Y)C'H(M[()C%_(M[?)C&.(M].)C'](M]=)C +M((;@_^JB+`L,/_),@-)B0&6K!T)C%4)C%D)C'4)C'D)C%T)C&((CUD)C'T)C +M("88!9`0IAWP`!WP``#28]3"(]/JHK*@(,+,`<)CTZ6G!](CU+#=$=K2PBWJ +MPF,5LBWKLF,6HBWRHF,=DBWSDF,>@BWL@F,7\BWM\F,8XBWTXF,?TBWUTF,@ +M!K__`$)C%4)C%D)C'4)C'D)C%T)C&$)C'T)C(`:X_P`V@0"AK`"RH*B1:``, +M(X+2*XBHB0%V@!'"*4,+JHS\%OH\TB*4V`TF+0C&^?\````6ZCNZ4M@"PA(, +M\4D`@@(A0A(-8J(D:F+B!ML`1!&`@030B!&`[B#B;XWHO=BM0,P@`.X1X-T@ +MV8G";\:R!MW"`B"PNQ'`Q030S!'`NR"R:3BB(CB"(C?`J@'`B!&@B""):4(" +M)((&V^(&V#!$$8"($9#N$8#N($#N(.)OQ\(&XPP;0M(C]GP+@1X"@(R@B`B@ +M"```H?L!HF3E3%@,!WGIB=GR!AC8`0#_(W#_4R#_L/(O3MK_^?GB!B``[B-P +M[E,@[K#B+D[:[NGYP@5B(,RPPBQ.H=X!VLS)^<(&VZJB"\P6S!4<'-$A`N$@ +M`O$?`G)I.('K`8)J)?)J*^)J+-)J+<)*?,$B`L)J+M$W`')&*L(M\.(MW7RX +M@(X0@FW=\@;;\L_^%D\6D0@!D)P0DFWPJ2&M`K(E%L(D\H(DX+"[H,"[H.`( +M`*T"LB46PB3R@B3AL+N@P+N@X`@`L4D`P;0`TBN!UPP"AI$`W'KB!BO<+O(E +M:O(O`,ROD@8J)CD%)AD"9BFMMDH"ABP`J1%R)-NR)1:"(D`R805P>\"'MQIP +M-R"").*M`C"S(.`(`)(B0!LSES/LLB46.%&R9-G,EPP*HF3QHF3P1@4`K0>R +M%B7EC0>B9/&R%B6M!V60!Z)D\+(E%K>W`D8P`)(E:L(&*_(5XGS^"]NP_\#P +MWH/291D6C!.("8+(_A:H$ZBV#`F9"I)&*[(&,@P`]DRT#'?`M"AWPP?P!\2,"X20"T24"LFD5@@;@ +MTFHLXFHM\FHN@L@1@(!T@DI\@(@1P(@@@FHEP28"PFHK@>P!@F0R@F0S@F0V +M@F0W@F0Z@F0[1I__@0H!@(P@@FWP^-4,B?9"AO,TJ``TF3QPF3P@B3CK0+@ +M"`#R)/*X,>(D\+>)/#=H'J\TAT+V2Z2(D"Y,1N[ESNP +MLB461JO_B`E6&.PH$1WP`#)&*@P)AK#_X4D`\B5O#`F21C(;__)E;_%&`.(N +M@0R=\.X0X.M!X#V3+0,=\*$&`J)DY<9'_\$'`L)DY89%_]$(`M)DY49#_^$) +M`N)DY09!__$*`O)DY<8^_X$+`H)DY88\_Z$,`J)DY48Z_PRRP4D`?/L,'=)& +M*[)L@1WP`+I2XB5J.0ZEO/J1:`"&#/\``#:!`(MSRU.BH<]+D^M#:X.K8VE! +MB2%)89D1JJ)947DQ4J#P%#_$(#_(/)#`>$H`@`^IL`0 +MIM$I`@P9T,S`%IP4AD\`8)J@DBD`X*H1D)!T)EG+RLJR`P'(#,)#`)#`-%"[ +M$,"[(+)#`69)$_*B`@`_IM`0IN$G`N#=H-@-TF1VHB)`PB1_%MH$@B1SH(C` +M5M@(LA,!HB1VNJJ@H/2B4P'@#`"B9'<6>@T,&K@1I3(`#!JX(24R``P:N#&E +M,0`,&KA!93$`#`JX4>4P``P*N&%E,`"&*@``LA,!HB1VNJJ@H/2B4P'@#`"B +M9'<6*@D,&K@192X`#!JX(>4M``P:N#%E+0`,&KA!Y2P`HJ``N%%E+`"BH`"R +M(0;E*P"&&````+(DC*"JH#WPL*J@HMK_HAIWX`P`HF1W%LH"#!JX$:4I``P: +MN"$E*0`,&K@QI2@`#!JX024H`**@`+A1I2<`HJ``LB$&)2<`TB)`XB2,PB1V +MT-V@X-V@TMW_TAUWVLS"4P$,"0OI%G[G'?``HB)`G.KR)'.")':@FJ"G'^2R +M)(RPF:"2V?^2&7>:B()3`0;T_](3`<(D=MK,PE,!AO#_`#9!`)+2)I(I,G*A +M`C"#H)`XH``WIF`0ID*E/PP8#=(``]IL`0 +MIJHRD:P`=H`1@B2#"YF,Z!;)$*(C<:@*)BH'QOG_```6R0^R!0#!+0)PNQ'` +MNR``.Z8,&H(FU>(%`;'>`<(FUN"5!+JRT@M^X.8$@_P(\BL\@A4!H_P0#`4@ +M_Z!Z__(O)Y/\$8/\$O/\%^/\'%/\'0P^T_P>W07"9,F2*SSR*SO!:`"3_0KS +M_0)3_0&C_1KC_1:C_12C_153_1)3_1/9S-(K.[(K/-/["+)L3*)D7Y(#?(T% +M4_@%D_@)@F1@4F1A4F1B4F164F15\@-\&__P\'3R0WPFCS#`$*8=\`"1K`"J +M,@N9TB2#K%VL:>(C<>@."YEF+N[R!0""H0MP_Q&`_R``/Z:&RO\`4D-\@!"F +M'?!6&?Z2(W&R:0`E?/I&]?\`HB-QN0IE>_K&O?\`-D$`O%(A+@(`,J8@$*:\ +M8@PF@%(18%4@`#6F8!"F#!<+0D?6#P`20`"'H8"&P!N(@E,`'?!B4P`=\``` +MD2\"`#FF(!"F5G+\#`JB4P`=\``V@0!BI#_2H._"H/"RH0+Q,`(<3E+2(PP) +M0J(J2D*29=P`.Z:@$*:2`P&@H`3`JA'0F1"@F2"20P&0A`16B`L`-J:@$*8, +M%Z>^+I@/<"($)"((()#`:'J`0`ZIJ`0II$R`@P8 +MD*K`H*B39AH"!MW_!@D``.(#`?$Q`L#N$/#ZH/(O`/)#`)#P-/#N(.)#`=(" +MJ-+-_A8]#9(#`3WP1^DID)`T@LG]%D@*HLG\%NH)O&DF&32RR?X6ZPX=\`PZ +MP)D0H)D@DD,!1VG5#`NR4P*R4P2R4P:R4PBR4P.R4P6R4P>R4PD=\````+(E +M,L(E.J(E*J4C_;(E,\(E.Z`J(*(E*Z4B_9+!$.(EZ=(EZ\(EZK(EZ/+!%(T* +MH@3:^2&9$8D!@B7F_0+@"`"2`P&H4;A!LE,"LE,$LE,&LE,(HE,#HE,%HE,' +MHE,)D)`T1MG_#`S"4P+"4P3"4P;"4PC"4P/"4P7"4P?"4PD=\```MB<"1LG_ +M`#NFH!"FD@,!H*`$D*H1D)!DH)D@D)!TDD,!D-=!%DWPP+D0D-`T6]W0T#30 +MNR"R0P$&O/\``+(E,L(E.J(E*J47_;(E,\(E.Z`J(*(E*Z46_9+!&.(EZ=(E +MZ\(EZK(EZ/+!'(T*H@3:^2&9$8D!@B7F_0+@"`"R)3;")3J8<:AAHE,"DE,# +MI1S]LB4W+0K")3NH<>4;_?+!'+(EZ,(EZM(EZ^(EZ9+!&(T*H@3:F1'Y(8)A +M`((EYB#R(.`(`*(E+K*3`I(A!\AAPE,$DE,%Y1[]LI,#+0K(<:(E+R4>_?+! +M'+(EZ,(EZM(EZ^(EZ9+!&(T*H@3:F1'Y(8)A`((EYB#R(.`(`+*3`L*3!)(A +M!ZAAHE,&DE,')1W]LI,#+0K"DP6H<64<_?+!'+(EZ,(EZM(EZ^(EZ9+!&(T* +MH@3:F1'Y(8D!@B7F_0+@"`"8<:AAHE,(DE,)'?```#9!``P&0M(C4B3R8F3< +M,&.@4%:@D@4!#![@9A%'Z7C!)P*BI3_RH<_2H@*0D#2"R?T6^`FRR?P6FPD` +M.J:0$*;P@H"VN062H`#B2(#A,P*R!0"B!0'@Z:#H#J"@-.J[LD4`9AH.`#VF +M\!"FP/^@\B\`\F3B9-W*N[)5`1WPFD!"FLJ#?@@4!D)`$L)D1L(@0D(@@ +M@D4!`#JFD!"FMKD(DJ``\**`XDJ`\2L"X@4`L@4!\/F@^`^PL#3Z[N)%`&9+ +M#@`]IH`0IL"(H((H`()DW)("("=I**(%`:"@-"9*!+(%`)R;`#>FT!"FXJ"_ +MP@4!T-`$H-T1X,P0T,P@PD4!LB3E%O,+XB39-YY(PA4!HB3`+`*)DW1WPPA4!HB3<\"`` +MRJJ@H/2B50'@"P"B9-T66N8,&DNUI:;_#!JRQ08EIO\,&K+%"*6E_PP:LL4* +M):7_#`K+M:6D_^NU#`HEI/\=\```-H$`H2P"#!P,"ZIR8B?704D`,%.@8%6@ +MD@4!XJ",86@`1^DS#"V0D#2"R?T6F#;RR?P6/S;J,I&L`':`%8(D@PN9%K@) +M%KD)XB-QZ`[BSOX6#@K&^/\``(+2)M(H,*(H,>J2\A4!T_H(T@A2P_H=\_H2 +MT_H>HF3)HB@Q_0R"*#"C_PJM"X/_`K/_`(GUO/^".)F3!WP````5OD`@B-QTF@`)1#Z#`NA+`(,')(GPH(% +M`+"9`7"($9"((`RYD(@@`#BFXM(FT@4!@B?5\BXQZ0&2)];B#E(@_Z"#^0BJ +M_]"%!(/Y$8(5`?(O)]#0-(/Y$O/Y%[/Y'>/Y'J8]`L/Y$))DR9(%`9"0-(P9 +M9AE:F`'RE0.-"Z(I,?#PM)(I,*/X"J*5`I/X`K/X`3%)(:*5`CD1#`Z-#OT..`&I44*5`Z"@ +MU'(C,$!`M)(C,4/Z#D*5!9/_"I*5!W/_`D!`M'*5">/_`>/_&I"0M./_%N/_ +M%./_%>/_$N/_$_G&J<;R(S&PH-1#^@Y2(S!-#O/T"@P?4_0"X_0!X_0:X_06 +MX_04X_05\_02X_032<:IQE(C,4(C,*T.4_H*0_H"P%#4D_4.X_H!G0[C^AKC +M^A;C^A3C^A7C^A+S^A.IQEG&0B,Q<%"THB,P>#%#^`JC^`+00-2A#@)3]`[C +M^`%80>/X&N/X%JHBX_@4J%'C^!7S^!+S^!.)QDG&0B,Q,B,P@B)_0_D*,_D" +M2"$X$>/Y`?/Y&O/Y&./Y%O/Y%//Y%>/Y$N/Y$YG&X`@`LI4%PI4'TI4)@B)_ +M+0JBE0/@"``,'-*5`R"`U*"0M`P+HI4"L.L@D_@.L_X%DI4%@F8,T-"T@I4$ +MPF1?H*#4T_H.\@-\TI4)D)"T@(#4D_@.\_X)T-"T\I4'XF1@HF1AXI4&HI4( +M\/"T@F1BX.#4\_X.H*#4T_H.XF16HF15D@4!D)`THLG[%NH5P@-\&\S`P'3" +M0WPFC!#P$*;B)]72)];C_0C29DP=\+)#?*`0II(GU8(GUI/X"()F3!WP\B?" +M%I\:\I4"#'.`_Q$P_R``/Z:0$*:"E0,,B8"($9"((``XIC`0IO*5!`RC@/\1 +M,/\@`#^FD!"F@I4%#,F`B!&0B"``.*8P$*;RE08,TX#_$3#_(``_II`0IH*5 +M!PSI@(@1D(@@`#BF,!"FD:P`ZC(+F8(D@Q;8$1;9$>(C<>@.DLG_9B[K\@4` +M@2T"IC@"P_D0##V29,F")];B)]6M"X/Z"N/Z`K/Z +M`)D8-)D8=)D8M)D5M)D58:-_P!6 +MR>ZR(W'2:P`ER_D,"Z$L`@P<1K;_````D:P`ZC(+F>(D@YS>G.GR(W'X#PN9 +M9B_N@@4`DJ$+<(@1D(@@`#BFQJ[_`%:9_I(C<=)I`.7&^0P+H2P"#!R&]?\` +M`#9!``PY#`J!-`*Q&0)B(D!RH+A2H=!:4GIR,A?:&V9B9Q*P(H!GDS=!-0*2 +M17["(G.B8HNB8HK`QL#"8G4`-*:P$*9F&U4AO@%V@`X`,J;@$*8`-*;0$*9F +M'4"&^O\``#(BB_(53QLS,F*+-Y\*LB**HF*+&[NR8HK"!7]A*`)1*0+,;-(G +M9M(M`)RM`#:FX!"F#")0[L#@*8,=\``XIO`0I@PB'?`````VIC`0IE<3`PP" +M'?"R(G.B)Q*PJL"B8G4`.*:0$*8,,AWP`#9!`/'D`7+2`4(#`6+2(](B0$!` +M-$+$^19$'Z'J`;$R`I'L`0P.##S2S0&"H=!2%[:`@H#28D#7E6'"2'[B9O'B +M9O"29BJ29BN29BZ29B^29C*29C.29C:29C>29CJ29CL`.J;0$*8Q-@*PW<`6 +M_1``,Z;@$*9F'A$A-P(`,J:`$*8`,Z9`$*8F%/``.J:0$*8,XK"9P!9I#AWP +M`,(B0_(F\>*3!E*AT+#_$?KR6O_B;W9")O'RDP>P1!%*0EI$\F1WXB;Q\I,( +ML.X1ZN):[O)N>D(F\>*3";!$$4I"6D3B9'M"&$]2)O'`S<`+1!O5TF;Q1[U/ +M4I,%0I,$XF8O\F8N4F8K0F8J0A>WL/T1^B)'+`+&+`"29C*29C.29C:29C>2 +M9CJ29CN2"'_1*`(6>0P`/::P$*;!*0(,.@PBP+O`L"J#'?!"%[<+1$>=1T*3 +M!%*3!>)F+_)F+E)F*Y)F.Y)F.D)F*C(7MSC`H8[`))F,I)F,Y)F-I)F +M-X;I_Z(FV9@'H)G`DF;;`#^F@!"F#"(=\.(F\))F+Y)F+I)F*Y)F*@P/\F;Q +MTA>W&^[B9O#7K&^29C*29C.29C:29C>29CJ29CM&U__B(O+B9CI2(O-29CM" +M%[?'I'72(NK29C+"(NO"9C.2(NZ29C9"(N]"9C<&S/\``.(G5.@.5O[R`#JF +M\!"FMY\"QB``#`(=\$(FV4!-P$)FVP`_IB`0I@PR'?``XB+RXF8ZTB+STF8[ +M4A>WQZ5)PB+JPF8RDB+KDF8S0B+N0F8V\B+O\F8W1K7_DF8RDF8SDF8VDF8W +MAK'_L.T1ZN)"+NI"9C(R+NLR9C/R+N[R9C;B+N_B9C>&J?^29C*29C.29C:2 +M9C?&I?\`@B;92`>`1,!"9MLAY`$`,J;P$*8,,AWP-D$`#&@,&G$X`M$Y`@PL +M##MV@"F`F!&PZ2``/J:`$*9PB*"(",#I((!@]9PF`#ZF8!"F@/#T<'^@@(#U +MK$K&\__0^*!R'P&`=Q'`=R``-Z9@$*9B#P#R#P$`9B-I!`#_(_)E`(@$DJ^` +MEY@=LJ8"`#NFP!"FPLS@PF0``#NFH!"FHLK@HF4`@B0`*FAI!"@%.B(I!8@$ +M,J_`AR,'@LA`@F0`*`4G(P@BPD`B90"")`"FV`B2R,"29``B)0#FT@$=\*+" +MP*D%'?`V00`,:`P:<3H"T3L"#"P,.W:`*8"8$;#I(``^IH`0IG"(H(@(P.D@ +M@&#UG"8`/J9@$*:`\/1P?Z"`@/6L2L;S_]#XH'(?`8!W$"R$""9``H!2B"]0PS!&`[A&0JA'@JB#`JB"B9<=R8T!R0WR2 +M0WIY[8G=\@L4`/\C(+'`#N(W#N4R#NL.(N3DKNZ?W" +M!O8@S+#"+$Y*S,G]L@O7"[L6NQ;Q/@*!/0*"8RCR8RZ8`9()ZA;Y$J$_`J)C +M(-@!\AUML3<`D(\!X/\!BO_R8T&B*_#"*]U\ON#L$.)KW=(-U]+-_A:-$($( +M`8"*$()K\*@!8M(!DA:V#`1R2B:LB7'-`7IR@B,HK0)PMR#@"`"M`K(#?((C +M+@P)DD-ZX`@`HA:V&T2G--P,![@!L@O7W%N!P`$`.*;P$*;BH0(`/J;`$*;8 +M`<)-Z0QL`#RFL!"FHB$`H@HGDB*4%AH-V`G2S?X6'0VA:`"(`0P)HBI,PA@C +MZ*B@N'3`NX*@H'2ZJ@OZH/F#^>AY#L@!#!VR#"[23"5R3"<6BPKR(ID;__)B +MF>(E@:(C.H(C.Y'$`("J$:"(()"(()%H`*T"@FE,/Y"+('?@P>X_D0P_D1S0W3^1VS^1Z2:LF")M?R)M:1:`"#_`KS_`+C +M_!I#_!;C_!3C_!73_!+3_!/)R;(FUH(FU[/X"()I3!WP#&N11`)&PO\`LJ`` +MPJ``I0$`DJ$"HF,#1M/_TB*460WE+/FA20`&V_\``#9!`!Q)'`T,C#S+/`\< +M?@S*H(,0)^0HIP,])DAOPLCX%EP+9J@KD#(0C-/2P_P6[2'BP_`67B>7DQ>P +M)3`=\`"G`S`F2&YBR/@6A@O2R/06K0T,`AWP``"0,A"7`BIBP_P6=@Z"P_`6 +M6!"7PB*P)3`=\```D#(0EP(.8L/\%L8-@L/P%M@/E\(N+04=\)`R$!83$*+# +M_!;Z$<+#\!8,%I>3.5#5!!9-+E#C!!8>*BR"("4P'?"0,A`6PPYBP_P6)A&" +MP_`6R!27DSU7Y;M0HP062BC0)3`=\`"0,A"<`\+#_!8,%-+#\!:=&)#CP%:. +M\U#U!%;?(5!C!!9V'2S"("4P'?```)`R$!83#F+#_!9F$H+#\!98%Y>3%5"5 +M!%9)*E"C!!:Z)BS"("4P'?"0,A`64_5BP_P6=A*"P_`6"!B0H\!6RO"P)3`= +M\```4+4$5FOS4-0$%OT4P"4P'?!0Y0167O)0]`06_PW`)3`=\```4&4$5B8: +M4(0$%O@5/$(@)3`=\`!09006YN]0A`06"!6@)3`=\%"E!%;:[E"S!!8K%=`E +M,!WP``!0Q016K.U0XP063A30)3`=\%#U!%:?[/:%`@9(`%>^`H9&`!R"("4P +M'?```%!E!%;FZO:%`@9#`%>^`H9!`!R"("4P'?!090065NE0@P06.!20)3`= +M\```4)4$%ID/4*,$%LH5+((@)3`=\`!09006%@]0A`062!6@)3`=\%"5!!9) +M#U"D!!9Z%O`E,!WP``!0M006ZPY0PP06/!:0)3`=\*`E,!WP``!0U006'0Y0 +MY`06#A#P)3`=\%#U!%8?XE!D!!9F#\`E,!WP``!0A016F!/VA0)&,`!7O@+& +M+@`L0B`E,!WP4&4$5E82]H4"QBL`5[X"1BH`+$(@)3`=\```H"4P'?!790(& +M(0!09`06=@P\0B`E,!WP4&4$5I8/4(0$%K@+/$(@)3`=\``L@B`E,!WP`/`E +M,!WPP"4P'?`#`UA20!QW@'!:`")`WIRS+@, +M:Y%%`@PE##2&&0``V=/9PXA#DB<\HB<[FHB2!WZC^`C3^!#C^!V3^!Z"9LGR +M)SRR)SNM#O/Z"K/Z`N/Z&M/Z%N/Z%./Z%=/Z$M/Z$ZG,V"(I12:``ES/@&V_\` +M-F$`#&N110(,)0PTQ@,````\IK`0IJ"P]:"`])"8H("[$4#+(``\IJ`0II"J +MH*@*4,L@H-#U5FW]H+I!@+L14+L@`#NFD!"F#!QA20"!W@%Q[P$,"Z"0E)DS +MN0.A:`!ZPF;)PBL\LBL[T6@`P_D*L_D"H_D:0_D6H_D4 +MH_D50_D20_D3F"(I12:``EKO@&V_\`-D$`P!"F#`ZBH="RH+BZ +MLI(K$JJB@AO:&YF2:Q*7QW@'1$0(Z,MK"LBS7DB,\@B-!(+N@()F@VIG: +MN[(K*+)LOH)I*/(C/-(:3QO_\F,\]QT,'?`,.()*?N)K$AWP`.)C/.)C0:(C +M.^)C([(C(ANJHF,[Y5<%#!P,"Z"\@[)#?AWP-D$`048"2D*")-W,&(`0I@P, +M4>P!TB)`DJ"X8J'0:J*:DK(9VAO=TF)`T+O`%GL)<3P">G+R)SOB)TFP_Q'Z +M\FK_XF]VTB<[LB=*L-T1VM)JW;)M=Z(:3[(G.PNJ&[NR9SNGNS*").J2).F2 +M9!2"9!46\PNB)-NPJA&JHFJJTBIVTF0AWP-D$`,B)+LJ14/?"M`^4S!8*B +M()%(`J%'`J)B=Y)B=HJ#?/(B:'\B:(`,`AWP````-H$`N'.B(P:PJH*QK@!" +M(DN@JA&PJH"EPM,,"K%)`LT$Y<+3#!KEWM-2U`,,"()E4'(B&G)DWO(B'/)D +MW^(C(-(B%NK=TF3APB,ALB(6RKNR9.*B(R*2(A:JF9)DXX(C(_(B%G%*`(K_ +M\F3DTB>$XJ_QX-T0TF>$P`"FC)QV@`20`*:,&0;]_^`0IN)E+-`0IM)E+<`0 +MIL)E+K`0IK)E+SWP/?"@`*:,FG:`!/``IHP?!OW_P!"FPF4PL!"FLF4QH!"F +MHF4RD!"FDF4S/?`]\(``IHR8=H`$T`"FC!T&_?^@$*:B9320$*:2936`$*:" +M93;P$*8]\#WPX`"FC)YV@`2P`*:,&P;]_\`@`(`0IF`0ID`0IO`0ID$W`&%/ +M`!P-X@7#LJ`@HB,:XL[_X+V#Y2T%?*VB54J"(QR"54OX<_)53.AC\>`!8F4< +MHB3PXLX_\.X0LB3=XE5-#![0VQ#@W2#29-W"!<,L"1;\#[$(`;"Z$+)D\-(# +MX!R.\J"`T-`$TF538-T18-T@\-T@X-T@D)T@DF4;PB,UEVP(XJ8`X.D@XF4; +MH@/AHF52@B>$DJ!`D(@@@F>$\@7!\/`4)C\(LA5,\+L1LE5,PB(APF4@=H`0 +M\B3G^0'H`>#@%.D!V`$F/0(&^O^R)*RA.0"PP`22*B`':Q-\[=#;$-)DK,`@ +M`((DK()A`<`@``PNX.D@XFH@P"``DBH@P"``=H`0TB3GV2&((8"`%(DA^"$F +M/P0&^O\``'S?\/D0\FH@P"``XBH@Z3'`(`",3+)DK((DK':`$+(DY[E!J$&@ +MH!2I09A!)CD"!OK_P3X`PF3:'?#2!<0+W59][_$*`>(57/#Z(/)D\/:.`H:[ +M_PQ8@(L@@F3=QKC_````-N$`B)2&B:QB2)2*2:QF")2.":QKR)23R:QOB!<&B%4V2%5W@X!3BSOT6KE$; +MF="9$9":@C+!((OQXL$80B4@@B4HHJ_`0L0_H$0026%`29#@B*!"Q#^@1!!) +M(4I)0L0_H$0028%`29!"Q#^@1!!)04I)0L0_H$0027%`29"("(F;0L0_H$00 +MTB4H23%*24+$/_#=H-@-H$0029'9NX(E*$!)D$+$/Z!$$$E1,(B@B`B)J](E +M*$+!$(+FQTB2FV;&2).69L8(D]XFQ8B3X:;%")/!)L3(LBCFQ^`_YL>B+Z;'2 +M*QS9L9C;F;&(^XFQ:.MIL4(K$$FQ,BL1.;'R*Q/YL>(K$NFQTBL4V;&8FYFQ +MB+N)L6BK:;%(RV%H`$FQ0B4>,BL7.;'R*QCYL>(K&0Q/Z;$,7M(K&MFQDBL; +MF;&")D:)L6(F1($Y`&FQ88L`0FA*,@7##`1"81$+,S#O@S*CW``>0`#:H3HW +M,F$0V0&8`9)H3&)H3HPZ@B50C)A\^Z(E&M%*`D8&``P6PJ0YP9C!D)`4F<&(P28X`\;X +M_P`,"X(JW8G1Z-'!PP`,+_#N(.)JW7:`#N(JW>G1F-$;NS?I"+<\!:$W`,;Y +M__C1?-@]\(#_$/)JW7:`$,(JY\GAN.&PL!2YX9CA)CD&H3<`1OG_`.(A$N>] +M!0PR'?```-(E&K%+`@P,R0V2*L0A.0`,'["9$)D!B`&":L3R8BX,`AWP``"0 +M$*:294.`$*:"943P$*;R947@$*;B94:B%4HF%@RR)4P,;#WPP+L0LF5,IY8* +MTB5,#"[@W2#294P,"?(##](#"^(##<(##+(#"J(##NK,VKOZJLJ[NJJR$P2B +M94V($Y)E29)E2[#V5("(=8)A$Q9?'+"&!+#+!+":!+#9!,J9L,@$VLRPUP3: +MB,J(D(B`A[H-#(WA-P#RH`'R94G2;K""(1,,&8")DX)E2IRHLA,!HB5+L+`$ +ML*H@S,H,3-$W`.*@`>)E2<)ML/(E3H(E1X)E2(Q/DB5+5FD`K0>]`Z4Z`B(A +M$QLBO$(,!(QT@A,`@L@!@E,`DA5*HB$3/?!GF1",&J>4"\(E3-*@!-#,(,)E +M3*T',+,@)3\"&T0GE,OH\9(%PQP(+`\+F9#X@_HS-YX",B$08B$1HA5*8L8! +M8F$18L8!9[H"QGK_@B505EC>DB$0,)G`5CGLH`"FC)IV@`2P`*:,&P;]_X`0 +MIH)E-_`0IO)E..`0IN)E.=`0IM)E.CWP/?#``*:,G':`!)``IHP9!OW_X!"F +MXF4[T!"FTF4\P!"FPF4]L!"FLF4^/?`]\*``IHR:=H`$\`"FC!\&_?_`$*;" +M93^P$*:R94"@$*:B94&0$*:294(]\#WP@`"F%NCA=H`%T`"F%EWAQOS_``#B +M!<,+[A;.IR$Y``P?\F(N#!(=\((%P8"`%"8X"I(%PCWP9AD"!B``TB4H#!O" +M%5BPW3#292APW:#";>JB)2BPJC"B92G&D?X62@?Q-P`,+@P8@F5)XF^P!I7_ +M`'SM*YG0F1#@F1&0FH(&M_Z"!<16V+>B!<&@T!32S?T6';>"!<(6.`?2%5J2 +M%5C7F3J2)2@+BA;H".#9H-@-V=NB)2CPJJ"H"JG[AN?^\B4HXA58"(H(@(B=O2)2GPW:#8#=G[HB4I +M,*J@J`JIZY(E*4"9H)@)DFL0QLC^,-F@V`W9ZZ(E*$"JH*@*HFL0AL/^TB4I +MX-V@V`W9VZ(E*?"JH*@*J?N2)2@PF:"8"9GK@B4H0(B@B`B":Q"&N/X````V +M00`BI(`=\#9A``P:)4G3D4H`#!W`(``,Z_*AV/KR@B^;TF^:XB]D&XB";YO9 +M#L(IA,D!N1&H$8@!H(@@@FF$P"``'?`````V80"RI%12(DMR(A""PCB)`6B' +MK05X=_MF8&1!"PF53L+N0D+L1LF56NMO295F!30+X`>%.`I*A3+*A9**A6*JENK6: +ME9D5N36I)0QKHB79XF]I@F]HY3S=#`(=\````#9!`+ASHB,&L*J"L:X`0B)+ +MH*H1L*J`9133#`JQ3P+-!*44TPP:I3#3HB(APJ"PTJ*XLB39VM3*PZ)K()(C +M.))$+((C.8)$+?(C.O)$+N(,P.)$+X(,P@PJ#!XF&!;RR/X6_Q^2R/T6>2!F +M2`H,2[)D+88``.)D+?(,Q/)$N+(,Q;)$N9(,QI)$NH(,QX)$N_(,R/)$P((, +MR0P/)A@.DLC^%GD<9C@(HF0OA@``\F0O@@S*@D3!L@S+LD3"H@S,HD3#D@S- +MDD3$@@S.@D3%L@S/LD3&H@/L#$F-`Q:Z!D"D(':I99((\(+($))*-*+*$)(( +MX9)*)9((XI)*)I((XY)*)Y((Y))**)((Y9)**9((YI)**I((YY)**Y((Z))* +M+)((Z9)*+9((ZI)*+I((ZY)*+Y(([))*,)(([9)*,9(([I)*,I(([Y)*,Y(# +M[:T$%KD&DJ`$=JEED@R`PLP0DDITHLH0D@QQDDIED@QRDDIFD@QSDDIGD@QT +MDDIHD@QUDDIID@QVDDIJD@QWDDIKD@QXDDILD@QYDDIMD@QZDDIND@Q[DDIO +MD@Q\DDIPD@Q]DDIQD@Q^DDIRD@Q_DDISHB0OLLK^%DL)@@0LP@0`#!^`S,#` +MSY/"1`&88_N9D)1!DF0VN'.")"W[N["T0;"9@K)D-PN9DF0X)B@%)C@"'?`` +M@@2X%E@`L@V0A[L(HB0OXDUHXD2X@@2Y)BI>%E@`P@V4A[P%XDUHXD2Y\B0M +M9C_,@@2Z%E@`D@V1A[D%XDUHXD2ZHB0O@@2[)BI!%E@`L@V5A[NHXDUHXD2[ +M'?#R1`%&W?\``*)D+4:#_P``XF0O1H__##_R9"U&?_^,:)(-DCWPA[FEXDUH +MXD2Y!N?_C'BB#9.'.@(&V?_B36CB1+L=\#:!`*T"D3D`,B)+@J#_@FF"I3($ +M8J%<:F*M!N5`W:T##`(B8S\E*`!="MQJ,`#$+2HJ#:TP95```` +M``R5D:P`(6@`04D`#"<]\':`&X(D@_@RXB)#"YF`_R#P[B",[HSYPB/'J`PF +M*A/&]O\```!6>0"R(\=Y"R4=!,(CQPR]UQ4$Z`QF+AFM!@P+\J!D@B/9#`F2 +M;`#R:#7E$=VM`R4@`+(C/Z(C.+JJE^]S80;'C`.*@K_(M'PP,PDV`R0\F)`+&W/\&B/\`O0/E&P3&H?^"HJ"* +M@X((@8S8HB,XO0,;JF4:!`PJ1@``#%JR(RV2H(2:DR8[#<@3N"/8,]DCPF,# +MLF,!XBGS&^[B:?.B8\\&O?\,M0P/^0P&<_\`@B/'>0@E_0/&FO\`#`(=\)@, +M5BGUHB-$HF,_QN#_#`G&T_\`PBT?#+4,"[D,QF;_-D$`#"P,&E%1`@P)?/-" +MHJ1M`G(FV2(B+4I&(YTO@/Z#9Z__GRZ`[8 +M%GKNZ?+8#0PE>MW9\K(F+_(&`4(F+;++_A8[">+$_19.#1;?#:)B%:)B%C(F +M-D(F-\@6"S,+1$!$$<`S$4`S(#)B24(F+WR[/(,6%`<+E`P$D$6#T/01,/\0 +M\F)*Z';89L#N`<#=$>#=(-)B1L@,03<`>LS"8D1R8D=R:,4B)/!R)-V!"`&P +MMQ"R9-VB)BV`@A`F.BZ"9/`,`AWPL5("LF8^1J#_``#2IQ_29CZ&G?\F-$.B +M8A6B8A:28B7&VO\,%,;C_S$*`5%/`%)DIE(DIH%<`#`R(%!0=(!5(%)DIC)D +M\/(F-@R.#`+WOA\,2("'(()DW1WP`))B%:)B)9)B%L;)_Z)B%<)B%H;'_PP" +M'?`````V80!@P'10L'1`T'3A4P(P\'0`/J:`$*;PG1$@W9!R#;@`6",,*`LW +M)A<0C-6`HQ&`JB``.J9P$*9R80!"I1\6W!(`-*9@$*9B8D\`=B-R8D^03Z`< +M!BP/?`D@1*`6,Q`6!1!0<6``$T"H`0MW`'>A>JH;JJ!P8%"GHU(D1P`30`!F +MH0"9H19+#U!1(:I54F1'EZ4(`'^A<%6`4F1'9R4+`!-``(^A@%7`4F1'\)41 +MDF1'`#ZF4!"FH@VY`%4C"SHF&A06%0&2H`*`@Q&0B"``.*9P$*9R80$6S`FB +MI1\`.J9@$*9B8E``QB/"8E`7I0<`?Z%Z55)D1V>E +M`D;'_P`30`"/H8"%P()D1X;#_P`6!092)$BJ55)D2)>E"@`30`"?H9I54F1( +M9R4+`!-``*^AH%7`4F1(L@+25MOXPB(O9BR'#`+PU1'29$@=\```@B1(XB(O +M70CBSOY6+O.`42%29$A&RO\`#`+P]1'R9$@=\```@B1(77_PP"'?`V00"15`)1:`!RPFBQ20`,-L(B0M(B +M0PP(30BM"-/Z`,/Z"&/Z'J)KR3(B+:(B0PP;,L/]H_0*8_04@_0:L_0L(-,$%BT)(B\-81T-"TT_P.#`TPWH/3_!S)Q=(B3\(B4&(G2*(G1T(B +M+WSK&^J@ZK.P[A`F)"WP-A$P,2$;\S#SL["_$`P?IAH"!BX`#`_&+````)"@ +M!&"PM+/\#J/\',G%1NW_8$$A&S0,%D`TL["S$`P3.0'F&@,,#_D!,@+!YA0! +M#`:\,]Q9^`%*1D!!(4I,"T2JKZ"A(:JM!A,```"@^I!`1)"H`4I&0$$A2DP; +M1/JJH*$AJJW&"P``W)F@^I!`1)"H`4I&0$$A2DP+1/JJH*$AJJU&!`#X`4I& +M0$$A2DP;1*JOH*$AJJV@,-0,'0P&\$010,"TD&V#P_,.8_,<.<7&#`"JKZ"A +M(:JM#!WF%@$,#6IM#!-@82%J;!OV"V9`;Y,,#T#S@_!&$4`PM*!@U#/V#O/V +M'&G%X,#4B<5`\2$;VJ#:LQMOL*"T0B(OT($A\&^S8&$A\(@1@(#4\&818&"T +M)B0QH_P."_0,&PP.\.N#X_PO\&!P!C^`Z0T`2C_`X,&PP$D$N#T_PT()@&(J2C(J24!`!&!@M#`PU&/S#D/S'#G+6"I0(`.*9P$*9P<'1R0YT6-TBB`ZR& +M"`"B`ZQF+-X'Z@(7:MBBH0(`.J:0$*:B`ZR20ZT]\$?JQW(#G;D!-^H)!VHL +MP@-;N0&L3*T"LJ``P@-HT@-LY3__T@-KLB$`9AT+XB,N\B,M\F,QXF,RH@.L +MN0&@@@16N!,7:@T<^@`ZII`0II)#K@8!`#S\PD.NH@.L!VH0T@-;C*WRH0(` +M/Z;@$*:B`ZR"(Q.@D!2"R/X6Z!.<2<(#K@=J&M(#79T$4_D`G!U3^0T&`P#B +M`ZQ"0ZX,#`?NY`P)#+[#^0&`V1'@W2!`E"``/::B(RF"(RCR`ZRC^0"#^0@' +M;P)3^1"A4P#R`UQS^1'!20",'U/Y%O(#KN(#K=(#G//Y%^/Y'4/Y'M/Y'Y)L +MR8(C%7%H`.%4`H+(_A8(#H++_1:829++_A:Y%`O+%FQ*TB,IP@.L\B,HG03` +ML`3S^0+3^0I3^113^14';#D,.(/Y%E/Y'$/Y&A;[,J"Y(+G'TB,IPB,H#`+3 +M]`##]`A"9TP=\-(C*<(C*`P"T_0`P_0(0F=,'?``#,_P_!#RS_067T+`@@06 +M>`U3^1;&[/\`K0(,&\(#:0P-92G_D@-KN`%F&0NB(S#"(R_"8S.B8S2B`ZQ& +MI_\``+*A`@`[IJ`0IJ"@=*)#K,9>_P``-^H*PB,5O07"S/[`MH,,G=<*`H:J +M_T)C,D)C,4)C+D)C+<:F__++_1;/48++_E:H,O(C*<(#K((C*)T$P+`$P-`$ +M@_D"\_D*4_D44_D5%BT\##S#^193^1Q#^1H6JT2@^2#YQ^(C*=(C*`P"X_0` +MT_0(0F=,'?``"XL6^#R2`UH,&J)#:X++_@P>#`V`WH/20VJ&6/]#^1;&MO\` +MD@+3YAD"AKS_W0(,"\*@F,K"A@D`##BB`VN#^18,"`NJH*O`H(^#@_D:F<"`ZSR+4JB#(`GZ#B9QZ(M2/(M1_"J +M$1N/\(^SH*$A&_J@^K-\ZJ"($*#_$/#PM*(,?X"`U//X#J"@!*/X'(G'1L?_ +M``"@H`2"+4GP_Q'P\+2`@-3S^`ZC^!R)QYG'\BU'HBU(?.@;G_"J$:"A(?"? +MLX"9$!OZD)#4H/JSH@Q_@/\0\/"T\_D.H*`$H_D9QX(C%8"`!(/_'/G'1HC_^I)228`,,AWP`)G'H@.LX)D@ +MH+,$%IL,XB,NTB,MX."TT-#4X_T.0_T_](C*<(C*`P"T_0` +MP_0(0F=,'?``)BP'#`M&FOYF+/>2`UH,"\8]_Z#B!!;>">(C,-(C+^#@M-#0 +MU./]#D/]'-G'F"(RDB(RB#]``C]`A"9TP,`AWP +MT@.LT-8$5FW"#"J2`UK&"/^9Q[(C+J(C+1N+&RJ@*K.PB[-\ZJ`B$*"($("` +MM"`@U(/R#D/R'"G'\B,IXB,H#`+S]`#C]`A"9TP=\``ZIK`0I@9)_@``0_D6 +MQNK^F<>B`ZS@F2"@PP06?`KR(R[B(RWP\+3@X-3S_@Y#_ASIQ](#K-#2!!9M +M$,(C,+(C+\#`M+"PU,/[#D/['+G'F<>"(RVB(RY\ZQOH&_J@^K.`Z+.P[A"P +M_Q#P\+3@X-3S_@Y#_ASIQ\(C+](C,!N,&ZW0K;/`C+.PB!"PJA"@H+2`@-2C +M^`Y#^!R)Q](C*<(C*`P"T_0`P_0(0F=,'?"M`F48_^(C*=(C*`P"X_0`T_0( +M0F=,'?`G:E;B(S#2(R_@X+30T-3C_0Y#_1S9QYG'LB,OPB,P?.H;^QN,P(RS +ML/NSH/\0H(@0@("T\/#4@_\.0_\<^)QR(C*?(C*"/T``P"\_0(0F=,'?``FXD.@&\QVJ`RZJ2N9(*J@TFI' +MTFI(2[L,"0PH9BSDPJ4"`#RFL!"F0J*@LD.AL+!T%NL*HJ$"`#JFT!"FK#V1 +MXP``.::`$*8`.J;P$*:<+W:`#0`YIL`0I@`ZIK`0IHP;QOK_\54"`#^FT!"F +M%JT(#`K!5P+15@(,_P`\IK`0IB:+"_>;%0`]IH`0IH;Z_P`]II`0IJ+*(8;W +M_P#2IA\`/:;`$*:R(QV@K("BRO^G.S'R(R.P_X+B(R;PJH"B8RNG/BB2`UR" +M`V*A20`PF1&L&+*@@+"Y(+)JQZT")0(`+0H=\$K"XDR`##(=\+T"Y8,"AO/_ +MDFK'QO?_``PR'?`V00!"(D1B(C8RPEQ`I""]!N6K`J)C*[T&K00EJ`(,!Z)C +M+%*BH%I2K0*E8/]R0ZBR(R&2(RQ"(RV"(Q\;F1M$0F,MDF,LEY@*HB,K>"X(C*W)C+(+(`8)C*U:I\*(E +M'Z@*5HKZ8+3`5AO\QN?_##+120#R([!\_`P>Z0_";8$=\``V00!2HTQ04H"" +M)3E")3B`(!218`*B82^@@'2`B!%0 +MI2"0(A"`(B"EA`*"KP"R(3"`@A"@('2`(B`6FQ`,"PP&#`0,`PP-#`X,"@P% +M#`S`\#10_P'P(B"08*:,F7:`!(!@IHP8!OW_`'*FDLS^%AD1\LS\%C\:)HPU +M&RP=\`""*DKP(``6Z!&B*DRR$P!0FA`6JQ=7"A0A80+`8*:,3-!@IE:=_P!R +MI@P2'?`,`AWP\&"FC$^`8*96F/\`=::08*:,2?!@IE:?_P!ZICWP@&"FC$B0 +M8*96F?\`?J8]\*!@IHQ*X&"F5I[_`'VF/?#P8*:,3X!@IE:8_P!SICWPD&"F +MC$F@8*96FO\`=*8]\-!@IHQ-X&"F5I[_`':F/?#P8*:,3X!@IE:8_P![IALL +M'?"0(B`&H_\`T,(@@L;]X"(@@"R3QJO_``P+46("P5,`T3P`X6,"<60"\64" +M@L;]%J@P"X86B`^2QOX6*0\,"PP&#`0,`PP-#`X,"@P%#`Q&L_\``+!@IHQ+ +MT&"F5IW_`'6F/?#@8*:,3O!@IE:?_P!ZIALL'?```((J2U:H[9(J259)[5(3 +M`,(J3%#R@RT/)VP"L"\@0A,!/?`'9`+@(B#B"L%F/@+&:09R&ERM!1MWO0>E +M9`(]"G"W(%"E(&5H`H%@`C"0=("9$8""$)"((*`@=)*O`)"($(`B(`:C_P`` +M@68"H"D!@"(@AI__D&"FC$FP8*96F_\`=:8]\/!@IHQ/@&"F5IC_`'JF/?"0 +M8*:,2:!@IE::_P!^ICWPL&"FC$O@8*96GO\`?:8;+!WP``!A@0"!70)@8A"` +MAL`6V%^!7`*`AL`6R'^1@0"70@*&=0!!:0`,"2)A,7*3"[)A,J)A-+(A+@PO +M#!KPNQ!P(2']#8T+L)J#\&(18&?`DF$@L(J3@-Z3D/Z30%\@DI,)0$T@8/63 +MD.$A\%X14%G`4-230I,*43X`,F$S0*$A4&\@\+H1L+3`L/:38B$S(F$LXF$H +M8I8(HF$F4%T@8+$A\#L1,#;`,-6346<",B$TLF$G4/\0P#,1,F$M.KLZJC(A +M+U!=$*"@M,`S$3)A*CHB.N[@X+0@(+1`(A%`[A$Q:`+@52`@_R#A90(B(3&P +ML+3@_Q`P(A#@51`Q"@&P52#PJB"R(3+B(3+Q90(P(B"`[)/6*0`&V`*2824R +M(2B0TB'PW1'7$P6!:0"`[B#6)@"&U0(R(2=@TB'PW1'7$P6!/@"`[B`R(24; +MAH""(1N3,-(AD)(A,)VS8#(ATB$J8(.S,B$@T-%!TF$IVIDPO).0D+0Q9P)` +MF1'="S#N$#(A+9#N(/#N$#`Q(3J(@("T@.X@UB<`AL,"8B$L<+(A\+L1MQ8% +MP6D`P-T@UB0`!KH"PB$F0+(A\+L1MQP%P3X`P-T@0,(A<+(A&X0;EY"2(8"" +M(7";L[%G`D",LPQ,L-T0LB$I.HB`@+2ZF9"0M$"9$9#=(/#=$(#=((8"```, +M#0P.#`H,!0P,#`L,!@P$#`.&^/Z!?P"`DA"282N'@C,,!`P##`X,++(A+\!: +M$5!0M,"[$;!AM+"BM$"J$4!F$0P+T&8@\&80#`U@52`,!@;I_@``88$`@5P" +M8&(0@(;`S!A&E`*!70*'E@(&%P.1@0"70@)&>`+283MR83;"83=BDPK"DPMB +M82-@\2'P?Q%P9L!Q:0*-#L"1!)#GDY$^`$)A-<)A))!>(&#EDU*3#?)A)N)A +M.%!!!$"'DT*3#)"8($)A(D#A(?!N$6!$P$")DV*3#D*3#X)A.F)A(8%J`F"1 +M(?!Y$7!FP$!Q!'#8DW$^`%)A'^)A&G!](D])A/'*3"=(A.T)A'G!A! +MDV$^`))A&=)A.V#=(&*3"&)A.3(A.6!A(?"&$8`SP((A.W)A)6)A)S"-DX)A +M.\`Q(<#:$=)A+3)A+-JOVN[:9F!@M.#@M*"@M,`R(7#Q(<(A.#)A%/)A*!N/ +M@($$VMG0T+1PD@3PB;-P3@B$Y8"(00"(@;0C6 +M*`!&K01R(2>`0B'P1!%'%P6!/@"`,R""(24;1F"2(4!"(6!)LY(A*("#(1MY +M<'(AD'BS@B$JD6<"@()!D#,0BG=P<+1`=Q%P,R!R(2V2(13P,Q!P<2%Z1$!` +MM$`S($(A+()A%9"0!!N$@($$0(FSD6L"30R`29."(2/6*`"&#@5B(2."(2:" +M80]@8B'P9A&2(0]G&06!/@"`1"!B(2."(20B83T;EF`B(9"2(6"2LR(A+("# +M(7J9&V)@8B$@:+,A9P*"(160D+0@1!"*9F!@M((A'4!F$6!$(&(A%R+(`?!$ +M$)!$("`A!)%K`F!@!(`FLR#)DX(A(L!L("(A/=8H`,;Q!,(A%8(A(I(A&I)A +M$(""(?"($8)A$9(A$8(A$)<8!8$^`(!F(#)A/B)A/3(A'R(A(C`S(1N"()(A +M@((A((FS(B$=>HB`@+0;DI"2(2"3LR%G`LJ9D)"T0)D1(&80(6D`D&8@\&80 +MDB$<@&8@@B$6&SDP,02`@`20.+,PLI.2(2$B(3TR(3[6*0`&U022(2&"(1F" +M81*0DB'PF1&281."(1.2(1*'&061/@"0NR"2(2&0@B$;^?#R(9#XLWK_\F$\ +MDB$>\B$&PLB'PNQ&W$P>!:0#HH8#N(-8F``:&!#(A)V"R(?"[ +M$;<3!<$^`,#N(+CAD6T"&X:`@B&P>9-@LB%@B[.R(27!9P(;F[#2(9"2(;"= +ML[(A*L#N$+"Q0;)A*;J9D)"TLB$M0)D1D.X@\.X0L+$ANHB`@+2`[B""(20] +M!]T'UB@`1G($8B$L@$(A\$011Q8%T6D`T-,@@B$CUB@`!F@$PB$F@#(A\#,1 +M-QP%@3X`@-T@PB$D&XS`DB&`@B'`B;.2(2,B83T;*9#"(2`B(9`LLPQ,DB$I +MNB(@(+2:B)%G`H"`M$"($9#=$(#=(/#=$"#=("(A/09[_I%_`($*`9"2$))A +M*X>9`D8Q`Y%;`H(A*U)A&)>8`H:J`X%_`%)A&(="`L::`?(A&*)A-')A-B)A +M/4",!$">!$!O!&FQF<&"83HA;`)]#4"M!*GAD'Z3@-Z370]@4I/BDPWB81^@ +M\I-2842A:0!2DPE2826@AR"@32#@(2%0D2&282@B81WP:1'P(A%@5)-2DPM2821R84/BDP_B81YR(41082%B82S@@2&"81R@IR#P9A'P +M*!$@[L!@5<`B(4-0])/@>I-R843B(4.A/@!2DPQ282*@(B!002%"81KP9!%@ +M5)A*E!$$.J9ZJKJB.IWBXB+JI"0M$"9$:"@M("`M%`S$'!P +MM$!W$5!=$$"($4"J$:!$((`S()!5('#_()T+XB%"Y.]!\T'UBD`AL$# +M@B$<@F$)<'(A\'<1DB$)=QD%L6D`L+P@PB$AUBP`AJL#8`L8O`Y%;`E)A&)>8`L:'`X%_`(="`L:!`4%I`,)A-W)A-K)A12)A +M/;(A&"(A+W*3"W)A),`B$7#!(?",$<)A+(!WP(%L`BK,P)`$D+B3P,&T0,P1 +M@I,)0&L@<+:3@F$E)A)O"($"HN(""T@*(@@I,- +M(B$]@F$?@.$AXF$=T.T@%V@%X6D`X.T@TI,,(F$]T($ATF$B\"@1(-W`(3X` +M("X@T.*3TB$?(B$IT-(ATF$7*MTA9P+0T+1`W1$@+A#0(B#2(2V"81KP(A#: +MV$"/!-#0M"#M($(A&"%L`HFQ@$*3@I,/(B$]@F$>@-$ATF$+%PO)-Q:0#"(1]P>R"0MY-R(1W`PR$;EY"2(7"GB2(2%P<+1P9B#6*0"&G@-R(1F0 +MPB'PS!''%P6!/@"`NR""(2&2(1XB83T;R(`B(<#"(8#"LR(A')"3(1N"@((A +M((FS(6<"DB$5(+L0FH@B(1N`@+1`B!&`NR#PNQ`JS,#`M"(A/<"[(`R,AL7Z +M#`T,#@P*#`4,#`P+#`8,!`P#1L#Z``!R839`7`0B83V"DPF"824B(2]0WI/` +M>A%0O).YH7)A+5%I`(!A(<`B$6)A*")A*BHF4%T@\&81(""T8&C`8-638I,( +M0"(143X`8*$AHF$G>GI072#PJA&@IL"@U9-19P)P<+2M"U!=$"!5("(A/?!5 +M$'!5(-8H`$83`[(A)3(A*+"R(?"[$;<3![%I`*BAL*H@UB8`1A`#,B$G8+(A +M\+L1MQ,%P3X`P*H@8((AXB$E&[:PLB$;SN#2(<#"(>#-L](A+>%G`F"XL]#1 +M(>"J$-J[TB$J#`ZPL+30T4':S,#`M`P-0,P1P*H@#"SPJA"PJB"&A_L`P6P" +M46T"(F$]LB$OP(H1TI,*DI,+DF$DTF$C@F$MP+L1T.$AXF$FLF$JD"$ABHZ` +M@+0B82RZLO#N$?`B$>#=P+"PM$#M!.!UDU(A&$"[$2`IP.!!FP&#"DR*3"O)A&2)A(R!A(6)A)O#F$>`BP*IFX3X`JJ]@ +M8+3Q90+@Y2`@7I/B(2^@H+0B(3W`[A'B82KJF>K=B]V0D+1`F1'A9P+0T+1` +MW1'@51#@S!#0S""052#190*1;0+M!]#,$-!5$&!5(,"J(+#ID^G1UB@`ABD" +MLB$D8B$LL+(A\+L1MQ8'@6D`Z-&`[B"2(2/6*0#&)0+"(2:0LB'PNQ&W'`7! +M/@#`[B"XL=(A(Y%M`AN-L'F3@((AT+(AT(NSTB$D&YW0LB&0DB'0F[.R(2K1 +M9P+-!["Q0=#N$+J9D)"T0)D1D.X@DB$MW0?P[A"0D2&:B("`M(#N(((A'K)A +M*9)A&]8H`,88`C(A'("R(?"[$;<3!=%I`-#<(((A(=8H`(8&`G(A&8"R(?"[ +M$;<7!<$^`,#=(+(A(8(A'@Q,L)(A@&(A&T@;.S`R(4!"(8!&L[`YLV(A&PP+ +M@6<":C-B(2F`W1`P,+1J1`P&2T1`0+1`1!%`W2#PW1`,!##=(`P#QD?Y&VA@ +M@2&)\6!B(?!F$<;P^L(A%1N(@)$ADF$0@((A\(@1@F$11@W[`!N9D($A@F$2 +MD)(A\)D1DF$3!BK[#`L,!@P$#`,,#0P.#`H,!0P,AC/YPJ(`LJ,`L+00QQL" +M!I+Y5^0"AI#YT"(@!H_YLB$EF>$;N[`Q(;"R(?"[$89U^P`;MK`Q(;"R(?"[ +M$49X^QLX,,$A,#(A\#,11I;[&TA`82%`0B'P1!$&C/L``)(A+\"*$7*3"7)A +M)8)A+7!1(<"9$9!!05)A*$)A*4%I`)J5D&`$\%41D)&T4%?`8-Z30$T@8I,( +M4-2303X`8%$A4F$GBH7P51%`32!05L!0U)-19P)`F1&`@+1071"052#P51"` +M52"6UW$R(2BM"^(A*7#2(?"]$>K=T-`$T*R3MQ,%X6D`X*H@EG9Q,B$G8+(A +M\+L1MQ,'P3X`/?#`JB!@@B'B(24;MK"R(1O.X-(AP,(AX,VSTB$MX6<"8+BS +MT-$AX*H0VKO2(2D,#K"PM-K,P,&T#`U`S!'`JB`,+/"J$+"J(,8?_@"9H1M( +M0($AB4%`0B'P1!&&[?L;1D"!(8E10$(A\$01AO'[&VE@@2&)<6!B(?!F$484 +M_!NXL,$AL+(A\+L1AC/\&\S`<2'`PB'PS!'&4OP``&(A)!MF8($AB6%@8B'P +M9A&&_OL`&\C`@2&)@<#"(?#,$48?_!MY<($AB9%P9.M![<6 +M!=%I`-"J(.(A(Y:.7,(A)N"R(?"[$;<#2(1NY +M&\[`PB&PLB'@S;/2(2WA9P*0N+/0T2'@JA#:N](A*0P.L+"TVLS`P;0,#4#, +M$<"J(`PL\*H0L*H@QL#]``!`G`1M#8*3"8)A)9!NDX!1(5)A*&!6(!=H!5%I +M`%!6(')A-H(A+R)A/9)A2T!N!)$^`&#>DVG!P"H1(F$M8I,(P(@1@F$JD)4@ +M@(%!8*$AHF$G*BJ"82GPJA&@IL"@69.A9P*2(24@(+2@I1"0DB&9,8IY<'"T +M@I,-@F$?0'<1<*H@\*H0(%H@@)$AK0V281TB(3V2(4L7:`6A:0"@K2#2(2CH +M,1N-X.`$@($$T(ZST6D`[0N0[)/0WB"`[9."DPR`T2&"82+PG1&0B,"1/@"0 +MFB"`J9."(1^2(2F`@B&"81>:B)%G`H"`M$"($9":$("9(((A+=)A&O"9$(J- +M@("TD*@@EB9',B$G8-(A\-T1UQ,%@3X`@.X@DB$M&X9@TB&`@B%@C;/2(260 +MD2&281N:B)(A*")A/=#3(1LI("(AD"VSTB$7DB$J@("TT-`$D))!DF$5FB*1 +M9P(@(+1`(A&0[A`@[B`B(1WP[A"8P8#N(!N"@($$((VS(6D`D+R3DB$B("L@ +M@+*3W0LB(3V6>3_"(1J0LB'PNQ&W'`7!/@#`W2`,3+(A(F(A'X(A';"2(6!C +M(1M(&SLP,B%`0B&`1K.P.;-B(1L,"X%G`FHS8B$5@-T0,#"T:D0,!D!`M$!$ +M$4#=(/#=$`P$,-T@#`/&!_C!;`*2(1A`W02"DPN"8239X8"Q(;)A+-"K= +MT-&TDF$<0-T1T*H@\*H0L%H@0*0@%V@%H6D`H*0@P6D`N.&!;0+M!Y*3#I)A +M(;#HDX(A)+(A+,#.((""!!O;T-$$L-BST.R3@3X`T6<"D,$A\+P1L)G`@(H@ +MD*B3DB$J@B$ +M\.X0D)$ADF$;FHB`@+2`[B"1:0""(1S`P@20ER`;N+"Q!("\LX(A(;!YD]T' +MEL@B)/=!P9C^QNX +ML#$AL+(A\+L1AN7]&T9`@2&)`4!"(?!$$<8!_!MH8($AB1%@8B'P9A'&(_P; +MN;#!(;"R(?"[$49#_!O)P'$AP,(A\,P1QE_\@B$IK0L;-S"R(8J+,#$A\+L1 +M@(`$@*R3!C?^`!NVL#$AL+(A\+L1ACC^&VF!;0*2(2E@LB%@82&:F_"[$9"0 +M!)!XDZT'QHG^&[ZPP2&PLB'PNQ%&C/X;UM`Q(=#2(?#=$<;A_ANYL,$AL+(A +M\+L1A@#_&[NPP2&PLB'PNQ&&5/\;N+!Q(;"R(?"[$49S_P``-F$`HJ`!)>7. +MY2;9@6@`H4D`#`^1:`#R:H#R:L#Y"9$W`/)H0+(IK+#`!`=K$GSNX.L0XFFL +MP"``TBFLV0'`(`!V@!#B*>?I$=@1T-`4V1&($28X`@;Z_X$Y`!P.(B@@#$W` +M(`#0(B`B:"#`(`#2*"#`(`#R:I[`(`#@W2#2:"#`(`#B*"!L\B#N$.)H("(H +M('R]T"(0(F@@G+SQ/@"R::S`(`""*:R)`<`@`.(J@O#N(.)J@AWP`+$^`)(J +M@K"9())J@AWP```V00"BH`&EV,ZRH;2ZLJ(KI`PHDB+'&ZJB:Z2)":7Q_QWP +M```V00`,&Z&T`'S\D;4`T6\"83D`4J#_#`A!20!Q;@)R8EOB(DMR9()Q:`"" +M8EY28EE29H+28E_29,(R#B7R#B0,YC`S$4#_$3#_(-#_(/)B8/DG\@XEX@XD +M,9``,/\10.X1\.X@T.X@XF)AXF="TF):TF1"HF)EDF)F8F)H@F)BPF)C@F)D +M@F)GLF1$LF1%LF=8HF2`DF3`B0=B9T!2(EQ29)HR9(4=\``V@0"1K`!!:`!Q +M20`,)6T"(J*@*B-V@!NR)X.H-((D0PN9L*H@H(@@C.B,^<(B'\@,)BP01O?_ +M````5GD`TB/'60VEXO_E"=D,[X+7!`P%D;4`H;0`HF>`DF?`60CR9$#B(S]I +M`>DA9SX"QC\`^"'H`6T%*5'P[L#I$:@ALB,VN4&JIJDQI1X`+0JB8T.X0:@Q +M)2$`#!NB8T(,.?T%(_\`H_\(D_\>\F?)XB-#TB,MS07C_`IF/123_!13_!K= +M#+/]'+/]`+/]%D8$``"3_!13_!K=#+/]'+/]`%/]%L(C+PP>HB-")BQP"_SP +MBA&#_0*S_1L,"/".@X/]`=G$PB,O#!\,#B8L6JT%"XR`[X-3^@[C^ARIQ*%4 +M`AMF#!^@S2#)Q,(C+PP.J!$F+#O=!0N,@.^#4_T.X_T/\`-/\",)D3%9Z\BA1:`'&!`"C_0)3_1L&YO]9Q(;K_P!9Q$;S_U)"@9&L +M`#WP=H`;HB>#B#3R)$,+F:"(((#_((SOG#FR(\>X"R8K!\;V_P```(PY8F,_ +M'?#2(\<,+,)M`"7,_V)C/QWP````-D$`#`0@4!2<%0Q'4'?`,'=C<#/`=I<$ +M0D(`&R(PL@0>HF-BDD0F=VL0##(;ZN)C$1WPK0*E*?'&\O^M`@P,)2GQ +MXB,1##(;[N)C$1WP=VL8(*(@L@-2PJ``92?Q\B,1##(;__)C$1WP`*T"#`PE +M)O$&]_\`#!Q\^+(#4K)$)H)$'J)C8JT"I23QDB,1##(;F9)C$1WP````-D$` +MLM("L@M$=VL!'?"M`@P,92+Q'?`````````````````````````````````` +M`````````````````!X#8``>`V``'@-@`!X#8`````#_____`````/____\` +M````_____P````#_____`````/____\`````_____P````#_____`````/__ +M__\`````_____P````#_____`````/____\`````_____P````#_____```` +M`/____\`````_____P````#_____`````/____\`````_____P````#_____ +M`````/____\`````_____P````#_____`````/____\`````_____P````#_ +M____`````/____\`````_____P````#_____`````/____\`````_____P`` +M``#_____`````/____\````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +/```````````>`P`'A0`" +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_ce.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_ce.bin.uu new file mode 100644 index 00000000000..b2ebe23ba3d --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_ce.bin.uu @@ -0,0 +1,194 @@ +begin 644 TAHITI_ce.bin +M?$"``8@```#40`!_?$"``8@```#$(``+Q@P`!93``"0D4``/,10``I5```3, +M0``DS$``)8`````Q%``#E4`!.\Q``";,0``G@````,0@``O,(``%?$$``5!4 +M`"!\08`!!B0``@8U``P&-@`-`4H`$1\0@`!?$)``94` +M``>&@```@``!4(```5"```%0@``!4(```%(15``0?A8`"LU``!'480``E8#_ +MLL0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``!'48@``E8#_J<0@``Z:`/__ +M?$"``8@```!\0,`!%-``'C$4``*50`#K&-0`,!C0`>@8_``T),P`#P3H`&A\ +M08`!?$'``93``!*&@```@``` +M`!J```!_4=P`('V=@!J90``#Q:(``(```'_)H@``@```?\6A``"50``%!9@` +M`<6E``!29``@?B8`&@4H`(-\08`!?$'``94```>&@```@``!4(```5"```%0 +M@``!4(```)/8```1SAD``)5```0%F``!5B``(,X9``"7P/]QQ#DA0'Q`@`&( +M````4=P`('V=@!K8```1SAH``)5```0%F``$5B``(,X:``";P/^]?$"``8@` +M``#8``/VV``#]=@``_38``/SV``#\M@``_'8``/PV``#[]@``^[,0`!_S$`` +M?\Q``']\0,`!S,```=1``'^`````?$#``5!0`"",``#+?-#`&L0@``O$U@`` +M?$.``<0D`!.:```)V&0#],9K`_&:@/__QFL#[@:H``'.I`/NS60#Z]@D`_29 +M0``)WX,``,^@``Z,``#/U$``?YH`_SS&

?16`#IF```_80``IR!``'7U1@!)]C<`/F<#__=@``"E0X``! +M?A9`#II```1]8H`2TH``(X````#0```C@````-B``"G$/`!_S```(-A``"C$ +M#``V$``'8````#,```@V$``*,0, +M`!R8P/__V```*-```![0```?V$``'7Q!``&`````?$#``7Q!``$5&``?S0`` +M$5$4`""9@``#U$T``(````!]34`:&1P`,=16``#$(``.E<#^R,0@``Z:`/__ +M@````'Q`P`%\08`!%-``'C$0``(DU`#_E0#^O\V4`P"`````Q"``$WQ`P`'$ +MTP,`S```$`(0`]@"'`/D`B`$"`(D!%P!]`3P`?@%$`'\!+``B`*X`BP$B +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````"`````@````(````"`````@````(````"`````@````(````"```` +M`@````(````"`````@````(````"`````@````(````"`````@````(````" +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +:``(````"`````@````(````"`````@````(` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_mc.bin.uu new file mode 100644 index 00000000000..42dcc68be65 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_mc.bin.uu @@ -0,0 +1,694 @@ +begin 644 TAHITI_mc.bin +M``/HX``"O@$```('``/_```#_P```J`.``'`&0`#Z````^@0``/H(``#Z#`` +M`V`@``-A2``",;@``TEL``-("@`#KPH``K0$``)O]```^BT``K0/``)/%``` +M^@H``ZB,``#"`0`#0"0``K1```*U#P`#2J8``D1!``/P`@`"294``VJF``-* +M40`#0"0``K@"``*Y_@`"1)0``DB!``.H@``"9$@``VI1``-`)@`"OX```KP$ +M``))^0`#\$(``_0```'`00`"OX```TA4``*X#P`"N?```D$8``)"*0`#:%0` +M`TMI``/`C``"9$P``VMI``)$2``#:VD``F$?``)B+``#:%0``BP%``-+3``# +M_P```V%$``-+'``#0"H``K3\``-A0``"0S0``F$>``-K'``"2JX``_!&``-) +MU0`"O!```DS'``/P0@`"O"T``C)S``-`)``"M$```K7P``-*I@`"1$$``_`" +M``)IE0`#:J8``T````/_```#^`$``\1```/$40`"QD4``@````-`$``#_P`` +M`_\```/H(``#Z#```V`0``"1Y0``D@T``_@#``(POP`",;(``T@(``*TGP`" +M0`0``V@(``-(P``#2,8``K3\``*U#P`"010``DF4``)")0`"2J4``D,U``)+ +MM0`#:,```VC&``-(```#2`4``KL_``*\OP`"O^\``)(E``"*)@``@BH``+HH +M``"J+``"01L``KO[``)`#``#:````KS^``)%7P`"1WP``V@%``-($``#2=T` +M`KOQ``*\`@``BBD``*HK``)!&P`"81P``V@0``)%6P`"95P``VG=``-`#0`# +M_P```_\```.A3```B?\``K,"``)#-``#HS```)G^``*S!``"0S0``Z,R``"9 +M_0`#0"D``T````*\(```N<<``D(L``/P!P`"L````((Q``(Z,P`#Z````('E +M``/T```!PEP``T````*\(```\C$``D,\``/P!0`".C,``^@```"!Y0`#]``` +M`<)<``-((0`"L\$``D=S``-H(0`#:HD``T@E``*SP0`"1W,``V@E``-JC0`# +M2"D``TEP``-`$@`"OP<``D`/``.````#``X``Z^(``-)U@`"O!```DS+``/P +M00`"P`\``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H+0`#P00``\$5 +M``-IZ``#:>P``TK"``*_P``"2(\``VK"``-JQ@`#Z````^C0``(NE@`#:.0` +M`\'>``(NE@`#:00``^A```*]```",@(``KT!``(R`@`#0"P``_\```*T`@`" +M1`0``*()``-)U@`"M1```D1;``.D1@``H@L``J!.``/P`P`",[<``_0```'! +M!0`#]````=)]``*\```",CT``T`.``#R,@`#Z/```Z"V``-)U0``^@0``K$/ +M``)"%P`"I2```_`!``#Z,@`"0QL``J4C``/P`0``\@0``T````-`+@`"MA`` +M`K0,```J,@`"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`!``/HP``` +MX@,``T`(``*T````>@0``J`D``/P00`"L@@``J#^``/P00`"L@0``K0_``)" +M)```DAH``TJ4``/_```#88```T````/_```"M$```D0$``/P`P`#Z````((Q +M``(BX``#0````_\```*T0``"1!0``_`"``#R,0`"(N```T````/_```"M$`` +M`F$0``)$%``#\`$``BSW``-*E``#_P```V&$``-````#_P```K0"``)$)``# +M\`,``^@```"",0`"(PP``T````/_```"M`(``D0T``/P`@``\C$``B,,``-* +ME``#_P```V&(``(QL@`#0````_\```/_```"1`X``_`#``/H````@C$``B0; +M``(QL@`#0````_\```/_```"1!X``_`"``#R,0`")!L``BTN``-*E``#_P`` +M`V&,``-````#_P```K0"``)$0``#\`L``^@```"",0`")@<``T`L``/_```" +MM"```D1```/P`P`#Z````((Q``(Q*0`#2I0``_\```-AD``#0````_\```*T +M!``"1$```_`#``/H````@C$``B?3``-*E``#_P```V&4``-````#_P```K00 +M``)$0``#\`P``^@```"",0`"*'H```'_``/_```#_P```J0.``/P!```\@`` +M`BAZ``/H````@@```TJ4``/_```#89@``T````/_```"M"```D1```/P`P`# +MZ````((Q``(J"@`#2I0``_\```-AG````@,``_\```*T`0`"1`0``_`$``/H +M````@C$``\'^``(JO````@,``_\```*T`@`"1`0``_`$``/H````@C$``^CP +M``(JO``#0````_\```/_```"1"X``_`#``/H````@C$``C?1``-````#_P`` +M`K00``)$)``#\`,``^@```"",0`"./4``_@#``-*E``#_P```V%@``-````# +M_P```K0"``)$00`#\`H``/(Q``(F!P`#0"P``_\```*T(``"1$```_`"``#R +M,0`",2D``TJ4``/_```#860``T````/_```"M`0``D1!``/P`@``\C$``B?3 +M``-*E``#_P```V%H``-````#_P```K00``)$00`#\`L``/(Q``(H>@```?\` +M`_\```/_```"I`X``_`$``#R```"*'H``^@```""```#2I0``_\```-A;``# +M0````_\```*T(``"1$$``_`"``#R,0`"*@H``TJ4``/_```#87````(#``/_ +M```"M`0``D0$``/P`P``\C$``\'^``(JO````@,``_\```*T"``"1`0``_`# +M``#R,0`#Z/```BJ\``-````#_P```_\```)$/@`#\`(``/(Q``(WT0`#0``` +M`_\```*T$``"1#0``_`"``#R,0`"./4``TJ4``/_```#870``_@#``-````# +M_P```K0(``)@`0`"1`0``_`,``-("``#_P```K1```)@!``#:`@``TF8``*T +M_0`"010``VF8``/H,``#P2X``V@P``(Q1``#Z````^@0``/H,``"L@,``V@P +M``-````#_P```K6```)A$``"114``_`!``(W,``#2I0``_\```-A>``"O`$` +M`C(]```",@`#_P```_\```*A#@`#\`(``^@```""!P`"+2X``T@```-(!0`` +M"B8```(J```2)0``*BP``#HH``/_```#:````V@%``-($``#2=T```HI```J +M*P`#_P```V@0``-IW0`#27$``K(!``/H,``#P08``\$7``-H,``",40``^@` +M``/H$``"L@,``K,```-H,````@L``_\```/_```"H`X``@*!``/T```!P``` +M``'E``-`$@`#0!4```H-``*@#@`#\`(``_0```'"G``"P1X``(H-``)KN@`" +M95L``L9N``/P00`#!FX``V`5``*R#P`"1$(``J44``/P!P`#Z*```^BP``-@ +M$@`#Z````('E``/T```!P&L``T`L``/_```"M"```D!```/P`@`#]````<*H +M``/H````@C$``C$I``#R,0`",2D``^@```"",0`",%X``/(Q``(P7@`#23T` +M`TC```*V"``"1F0``_`"``*U,``"8B4``VC```-HQ``#2QT``T`H``*\$``" +MOP0``DS```/P!0`"9W\``VL=``(Q1``"9WX``VL=``-`(``#_P```_\```+" +M+@`#\$0``L,^``/P0@`"LO\``K/_``-@(``",;(``TE(``-`*@`"M#\``K6` +M``*V0``"1F@``_!%``)#-``"8S4``VE(``)#-``#:4@``^@```/H$``#Z"`` +M`^@P``-DI``#9.0``_0```'````#0`0``&HQ``/H@``#Z)```^B@``/HL``" +MH-X``_`#``-DJ@`#]````_!!``-DZ@``8>D``J#>``/P`P`#Z$```_0```/P +M00`#A.H``]A```/>@``_@#``/4G@`#^P```P_^``("]P``(<,``J#> +M``/P`P``8<(``_0```/P00``8<$``K\(``/<0``#V,```_@#``/4G@`#^P`` +M`P_^``(#!@`#^`,``^P````",@``:C$``_\```*@#@`#\`$``^P```-).``" +MH-X``_!!``-).``"N/X``D(H``-I.``#2=```K0$``)A%``"L@$``K,2``*@ +MW@`#\$$``K,1``-H,``#27$``KCO``*Y!``#P08``F%Y``)#.``#:#```T@) +M``*X_0`"1$@``V@)``(M"``#2:```K01``/!)``"L0\``VF@``-*1``"M/X` +M`F$>``-J1``"010``VI$``*@W@`#\`,``T)A``/T```#\$$``T)=``/_```# +M_P```^A@``-II0`#:&L``KH,``*XP``#W($``]BA``*P^``"L0<``^@@``/H +M,``#_@```]0?``-H:P`#Z/```B/)``(CL@`"(]X``J'^``/P00`#8GH``T)X +M``/_```#_P```J"```'#9P`"H)$``<-G``*@H@`!PV<``J"S``'#9P`"S_X` +M`KP,``*A_``#\$(``_0```'#40``^``-">``# +M_P```_\```*@@``!PWT``J"1``'#?0`"H*(``<-]``*@LP`!PWT``L_^``*\ +M#``"H?P``_!"``/T```!PVH``&'.``#YQ0`#_P```J7/``'#C0`"I?P``<.( +M``/H\``#Z,```_0```'#D``##,\``ZS```/H\``#]````<.0``,/_``#K_`` +M`^C```(CR0`#P?P``B.R``-).``"H-X``_!!``-).``#_P```F(N``-I.``# +M2=```K3[``)!%``"L@$``K,2``*@W@`#\$$``K,1``-H,``#27$``KCO``*Y +M^P`#P08``D%Y``)#.``#:#```T@)``*X_0`"1$@``V@)``*P&``"(_T``BTN +M``/L```#P0\``\$?``/!+P`#P3\``J#>``/P!0`#9+```V2T``-DN``#]``` +M`_!#``-D\``#9/0``V3X``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``# +M:,@``^P```/!#P`#P1\``\$O``/!/P`"H-X``_`$``-DK``#9+P``_0```/P +M0@`#9.P``V3\``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P` +M``*P$``"(_T``TH<``(D#0`#P8P``TH@``(D#0`#C,8``FB,``-*)``")`T` +M`\&<``-**``")`T``XS&``)IG``#2BP``B0-``/!K``#2C```B0-``.,Q@`" +M:JP``THT``(D#0`#P;P``THX``(D#0`#C,8``FN\``/L```#:&L``KD(``*X +MP``#W(```]B0``/H$``#Z"```^@P``/^```#U!X``VAK``/!CP`"OQ```BT$ +M``/!^``#[````^C```.'/``#IW8``X8L``.F:``#A1P``Z5:``.$#``#I$P` +M`FS'``)LQ@`";,4``FS$``/L```#0"0``&HQ``/_```#H`8``J$.``/P`0`` +M@?D``TFA``-)I``"NT```KJ_``)%I0`"H-X``_`#``)#HP`#]````_!!``)C +MLP`#::0``VFA``(R8``#Z````^@@``/H,``"H-X``_`#```)^P`#]````_!! +M```)^@`"N,```VAK``/8```#W(```]0>``*_"``"+00``X#@``"!]@``@?4` +M`^@```"!]```@?,``/'R``-(5``"H-X``_`#``.$Z``#]````_!!``.$Z@`" +M8B0``VA4``-)=0`#B.8``F!H``/!%P`#P2X``\$^``*@W@`#\`$``X,P``-H +M,``#2%0``J#>``/P`P`#A.@``_0```/P00`#A.H``\!$``)")``#:%0``&(+ +M``*_`@`"+00``J#.``/P`@`#]````@2#``(NJ``#Z'```X3F``)&2P`"H&0` +M`_!*``-)T@`#Z&```XJR``.JJ@`"H:X``_`"``,!K@`")?<``_0```'%(@`" +MOP@``D_Y``.O]``#B[(``ZN\``(E.P`#]````<4B``-`#``#_P```K\(``)/ +M\``#\$(``_0```'$E``"OP```KL!``(E.P```@0``_\```/_```"H`X``_!" +M``/T```!Q2(``/'T``#Q\P`"H-X``_`#``!Y^``#]````_!!``!Y]P`#C>(` +M`]S0``/8\``#B>8``FF>``#QXP``0?D``^C0``./X``#P:@``XSM``#AYP`` +MXC```BX1``*W`0``0?D``^B@``#1XP`"H'X``_`!``.H@``##]\``\'9``/! +MJ``#C.T``.'G``#B,``"+A$``BY2``/!!``#P28``V)P``*_`0`#0!$``XC@ +M``*@_@`#\`0``D1(``/P`@`#]````@4(``*W`0``0?D``_\```*@?@`#\`$` +M`ZB```/HT``#C^```\&H``.,[0``X><``.(P``(N$0`"+E(``T)P``.,ZP`# +MC.H``^CP``+(0``#J(```"H)``+*8@`#JJ```J9>``($Y0``:C$``/()``/! +M6``#P7H``V)Q``/T```"!)\``J%>``/P#@``:C$``\&1``/!LP`"H-X``_`# +M``-A+@`#]````_!!``-A,@`"P($``Z@```+"HP`#JB```X50``"J"0`#@>`` +M`P"$``/P)``"H80``_`!``+$00`#!$X``\%4``,"I@`#\"0``J&F``/P`0`" +MQF$``P9N``/!=@`#U%X``F`"``($]P``:C$``K\"``(M!``#27$``X'D``/! +M!@`#HFP``J`N``(%(@`"87$``\$N``/!/@`"H-X``_`!``.#,``#AF```_!' +M``-H,``#C^T``BT$``./[0`"+00``X_M``(M!``#C^T``BT$``-)=0`#P2X` +M`\$&``/!%P`#P3X``J#>``/P`0`#@S```V@P```!Y0`#_P```_\```*E#@`# +M\$@``T`1``*@W@`#\`,``F9N``/T```#\$$``F=^``-@$0`#Z````('E``/L +M```"H/X``<5'``*P#P`"L0\``K(/``*S#P`"H-X``_`#``-C*``#]````_!! +M``-C:``",40``TI```!!\@``2?8``%'U``*\,P`"1`P``D4<``)D10`"1BP` +M`D<\``)F9P`"9$8``J%.``/P`0`"M`$``J".``/P!0`"I$D``_!#``*D2P`# +M\$$``/'T``"A]@`"O,P``D0,``)%'``"1BP``D<\``)D10`"9$8``F1'``*A +M3@`#\`$``K0!``*@C@`#\`4``J1*``/P0P`"I$L``_!!``#Q\P``H?4``^A` +M``"A\@```?0``!'S``*Q#P`"LP4``J7^``(%G0`"H/X``_!!``/H\``"H`X` +M`_`!``+/_@`"L1```J`N``/P`0`"S_$``K.0``*F\P`#\$(``/'E``/L```" +M0P(``_!#``(EW0`#]````<5'``*T$0`##_0``J#>``/P`P``^?$``_0$``/P +M`0``^?```T,I``*@W@`#\$$``T-I``*_=P`");P``^P```-(Y0`"H-X``_!! +M``-)!0`"N!$``J`.``/P`0`"Q$@``DE!``*DDP`#\`$``/'T``*@+@`#\`$` +M`L58``))40`"I),``_`!``#Q\P`"H-X``_`#``-HY0`#]````_!!``-I!0`" +M0`(``J`.``(%1P`"L0(``B7W``/L```"H?X``_!!``/L```#H?8``X_V``.@ +M]@`"H0X``_`'``*\"0`"H$P``_!!``*\#P`#P4P``\%<``,`#@`"H1X``_`' +M``*\"0`"H&P``_!!``*\#P`#P6P``\%\``,!'@`"H-X``_`#``-C*0`#]``` +M`_!!``-C:0`"8@$``@7"``/L```#0RD``J#>``/P00`#0VD``J`.``/P!0`" +MM`\``DS^``/P`0`"M`D``\%4``*@+@`#\`8``K8/``.L]@`"3,X``_`!``*V +M"0`#P78``J#>``/P`P`#8RD``_0```/P00`#8VD``^P```-(Y0`"H-X``_!! +M``-)!0`"L!$``L1```+%4``"H-X``_`#``-HY0`#]````_!!``-I!0`#`1X` +M`@7[``/L````:C$``^@```(N@@``\>\``^@```"![@`#0`P``T`M``*X$``" +MN0@``DH8``.JI@`"2TD``ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`!``*S +M!@`#0"T```H$``*P0``"0$```_!!``/H,``"01X``_`!``/H,```F>T``BT( +M``*X$``"N?X``J#>``/P"0`#2"$``KH/``)&:@`"1WD``F9H``-H(0`#:HD` +M`_0```/P1P`#2"4``KH/``)&:@`"1WD``F9H``-H)0`#:HT``C`H``*_`P`" +M+_0``K]D``(M!```:C$``_\```/_```"H-X``_`#``*[```#]````_!!``*[ +M0```V>```\$.``*Q$0`"LA```VI$``*Q$``#Z"```VI$``*P_P`"L?\``K+] +M``*S_P`#:&```TI@``*_]P`"L1,``D`/``)@#@`#:F```#'^```Y_0`"O`@` +M`K_^``.&:@`"8B8``J1^``/P`0`"LP0``D`/``)@#``#:F```X_A``(M!``# +M:&L``_\```/^````8B\``%HN``/_```#V,$``]RQ``./XP`"+00``]`?``., +M[P`#C^0``F_^``)``0`"0B,``D`"``),P``#^P$``]`?``,/_@`"!G@``J#> +M``/P`P`#2"$``_0```/P00`#2"4``\#,``(&I``#C.8``L9L``/P00`"QWX` +M`J#>``/P!``#:"$``VJ)``/T```#\$(``V@E``-JC0`"I7X``_`"``/T```! +MQDH``T`1``*P"```\>4``J#>``/P`P`"9F```_0```/P00`"9W```V`1``/T +M```"!]$``X#A``.!!@`"81X``X+G``-J1``#@08``^@@``-J1``","@``T`L +M``!:'0`"M`0``^CP``)$0``#\`$``K\!``*DO@`#\`$``K\$``(O]```\AD` +M`/(7``(R6@`","@```HM```1_@``&?T``K`"``*@W@`#\$$``K`$``."*@`" +MI#X``_`!``*S!``#@18``F`!``*Q,P`#:F```T`*``*P`0`"L0(``K(```*S +M`0`"H"L``_`"``/H(``#P3L``VIH``/!#@`"L@D``D`)``/P`0`#Z"```K`3 +M``*Q`@`#@B8``^@P``-J<``#0"T``&($```2&@`"OT```D]/``/P`P`"H,X` +M`_`!``*R"``"L"$``K$"``*S`0`#:G0```H=``*P`0`#_P```J0>``/P!0`" +ML00``K(```*S`@`#]`0``_`#``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`0`"L0(``K,$``-J?````>X``_\```/_```"P`X``('N``(O[P```AD``T`* +M``-`#0`"H`X``_`%``*P`0`"0`4``X`&``/T!``#\`,``K`$``)`"0`#@`(` +M`K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`"LP$``VID``(NO0`" +M+LH```'O``/_```#_P```J`.``/P3@`#0"P``KP$``/``/P +M`0`#Z/```]CP``*\"0`"OS\``DL?``(MBP`#Z/```/GO```![@`#_P```_\` +M``+`#@``@>X```GM``-`+@`#_P```J`!``('2@`"L`$``D$(``/P!0```C(` +M`_\```/_```"H`X``@=*``-*=```>AH``_\```/_```#P2\``VIT``(O[P`` +M`AD``T`*``-`#0`"H`X``_`%``*P!``"0`4``X`"``/T!``#\`(``K`0``)` +M"0`"L4,``F@!``-*9``"M(```!'@``)`!``"8`@``Z(B``/!/@`#:F0``BZ] +M``(NR@``0@,``K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```''>@`#0`X` +M`K`0``/_```"00D``J`0``('>@```AD``_\```/_```"P`X``((9``*Q`@`" +MI`$``@<```!!X````<,``_\```/_```#V(```]P```*_"0`"L````]P!``*P +MP``#V`$``BZT```![@`#_P```_\```+`#@``@>X``B_O``-`"@`"L$```_\` +M``)`"0`#H`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`"LP$` +M`VID``(NO0`"+LH``T`E``!"`P`"L"```D`%``/P2``"L`(``J#>``/P00`# +M@`(``D`(``/P`@`#]````<>_``-`+@`#_P```K`(``)!"``"H!```@>_``*P +M@``"00@``_`%```",@`#_P```_\```*@#@`"![\```(7``/_```#_P```^@0 +M``"*%P`"I`X``@``/P`P`"NV(``_0```/P00`"NV@``_\```/_ +M````V>P``C"E``/H```"+H(``KL"``#:,``#Z````K%@``/H(``#Z#```VF@ +M``/H```"L1```^@@``/H,``#:D0``C`H``*_`@`"+_0``K#_``*Q_P`"LOT` +M`K/_``-H8```"BT``!'^```9_0`"L`H``J#>``/P00`"L`P``X$6``)@`0`# +M@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+00``VAK``/_ +M```#_@```C`>``-*8```,?X``#G]``*T]@`"M0,``X9J``)B)@`"I'X``_`! +M``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``#:F@` +M`K"```*R"0`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`" +ML0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`@`"L0(``K,$``-J?``",EH``^AP``-*9``"M(```D`$``/H(``#Z#```VID +M``-*9``"M(```!'L``)`!``"M`,``F`$``*S$``#:F0``BZ]``-*9``"M`@` +M`D1```)G=``"I7X``@AX``/H```"+H(``J#>``/P`P`#2"(``_0```/P00`# +M2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H(@`#:HH``_0```/P +M0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R#T``T`2``#QY0`"OP0``J#> +M``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R'@``C`>``/L````:C$` +M`/'O``/H````@@8``T`(``-`+0`"N$```KD(``)*"``#JJH``DM)``.KM``" +MLP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!```/P +M00`#Z#```D$>``/P`0`#Z#```)H%```AY0`#Z%```_\```"B#```J>4``&HQ +M``/_```#_P```J#>``/P`P``6<(``_0```/P0P``6<$``_\```/_````V>`` +M`T`L``!:'0`"M`0``^CP``)$0``#\`$``K\!``)+O@`"H+X``_`#``(O)0`# +M]```````D`$``)@"``#HB(``K,!``-J9``" +M+KT``B[*```![P`#_P```_\```*@#@`#\$X``T`L``*\!``#W,```K_```*@ +MW@`#\`$``K^```/8\``#C.0``K\_``)+'P`"+8L``^CP``#Y[P```@8``_\` +M``/_```"P`X``((&``!:'0``>A<``K@(``)*O@`"H*X``AH``_\```/_```#P2\``VIT``(O[P```A@``T`*``-`#0`"H`X` +M`_`%``*P"``"0`4``X````/T!``#\`,``K`@``)`"0`#H````K%#``)H`0`# +M2F0``K2````1X``"0`0``F`(``.B(@`"LP$``VID``(NO0`"+LH``$(#``*P +M`0`"H-X``_!!``.``@`"0`@``_`"``/T```!R;4``T`*``/_```"L$```D$( +M``*@$``"";4```(8``/_```#_P```L`.``""&``"L0(``J0!``()#````>`` +M`$'#``/_```#_P```]@```/<@``"OP@``K#```/8`0`"L````]P!``(NM``` +M`@8``_\```/_```"P`X``((&``(O[P`#0`H``K"```/_```"0`D``Z`$``*Q +M`P`":`$``TID``*T@```$>```D`$``)@"``#HB(``K,!``*Q```#:F0``BZ] +M``(NR@``0@,``K`!``*@W@`#\$$``X`"``)`"``#\`(``_0```')]P`#0"X` +M`_\```*P"``"00@``J`0``()]P`"L(```D$(``/P!0```C(``_\```/_```" +MH`X``@GW```"%P`#_P```_\```/H$```BA<``J0.``()3P``8<,``%G@``/_ +M```#W,```]BP``*_"``"L,```]@!``*P```#W`$``C)@``-H:P``$=8``K/` +M``/HT``#8G0``BVS``(P'@`#[````&HQ``/_```#_P```J#>``/P`P`"NU,` +M`_0```/P00`"NUL``_\```/_````V>P``T`0``*['P`#2"D``J#>``/P00`# +M2"T``D`+``.O`@`#C/8``FS/``./]@`#2>@``J-,``/P!``#!$P``P5?``/T +M```#\$(``P3$``,%]0`#P00``\$5``*@W@`#\`0``V@I``-IZ``#]````_!" +M``-H+0`#:>P``^@```(NE@`#Z````K%```/H(``#Z#```VI$``(P*``"OP(` +M`B\E```*+0``$?X``!G]``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`" +ML80``F(A``*D/@`#\`$``K,$``*Q&``#:F```T`*``*P`0`"L0(``K(*``/H +M,``#:F@``K"```*R"``"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP +M``*P(0`"L0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP` +M`_\```*P`@`"L0(``K,$``-J?``",EH``^AP``(O[P`#2F0``K2````1[``" +M0`0``K0#``)@!``"LQ```VID``(NO0`#2F0``K0(``)$0``"9W0``J5^``(* +MN0`#Z````BZ6``*@W@`#\`0``T@J``-)Z``#]````_!"``-(+@`#2>P``KP1 +M``*_$``"R9\``LB,``/P00`#Z(```\$(``/!&0`"H-X``_`$``-H*@`#:>@` +M`_0```/P0@`#:"X``VGL``-*P``"OP<``DW>``/P`0`"OS@``J&.``/P0P`" +M8`\``VK```-JQ``"NP$``-HP``/H<``"3_```_`#``*[_P`"H(L``_`"``/T +M```!RG$``T`2``#QY0`"OR```J#>``/P`P`":J\``_0```/P00`":[\``V`2 +M``(P*``"+^\``^P```!J,0`#Z````(',``*@W@`#\`,``%G"``/T```#\$$` +M`%G!``*P?P`"H?X``_!!``)+L```V>```C):``(P*```"BT``!'^```9_0`" +ML`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&```)B(0`"I#X``_`!``*S +M!``#0!4``K$(``*V\``"1$8``F$4``-J8``"L`$``K$"``*R```"LP(``VIH +M``*R"``"L!,``K$"``.")@`#Z#```VIP```2&@`"L"$``K$"``*S`0`#:G0` +M`K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P`0`"L0(``K,$``-J?``" +MO`0``]S```!YX``"O`@``KL8``/8\``"+8L```',``-`)0`"OQ```L`.``"! +MS``"3U\``_`#``(KQ``#]````````G#``-`)@`" +MLA```]@```/<$``"OP@``K#```/8`0`"L````]P!``)"*0`#\$4``Z_P``*@ +MS@`#\`(``_L```/[`0`#T)X``_L```*E+@`#\`$``_L```/4GP`#^P$``J4N +M``/P`0`#^P$``P_^``(+.```````_\```/``/L```"O!$` +M`J#>``/P!``#2,P``TC1``/T```#\$(``TCL``-(\0`"*Z\``J#>``/P!``# +M:,P``VC1``/T```#\$(``VCL``-H\0`"H-X``_`$``-(U``#2-D``_0```/P +M0@`#2/0``TCY``(KKP`"H-X``_`$``-HU``#:-D``_0```/P0@`#:/0``VCY +M``*@W@`#\`,``TC<``/T```#\$$``TC\``*@_@`#\`0``L`,``+!'``#]``` +M`_!"``,`#``#`1P``J#>``/P`P`#:-P``_0```/P00`#:/P``^P```*@_@`# +M\`H``L`,``+!'``"PBP``L,\``+$3``"Q5P``L9L``+'?``#]````_!(``,` +M#``#`1P``P(L``,#/``#!$P``P5<``,&;``#!WP``^P```*P?P`"L?\``K+_ +M``*S_P`#:&```VAK```)U@`#Z````Z`#``/<```#V!```T`Q``*_`P`"O`(` +M`J;\``/P00`#P0<``J#\``/P00`#P08``J#^``/P00`#P04``J'^``/P00`# +MP00``\$0``/!(``#P3```_X```/4'@`#:&L``_L```,/_@`""](``T`U``*_ +M`P`#_P```J;\``/P00`#P0<``J#\``/P00`#P08``J#^``/P00`#P04``J'^ +M``/P00`#P00``\$0``/!(``#P3```_X```/4'@`#:&L``_L```,/_@`""^H` +M`T`X``-`/0`#_P```VJ$``-J@0`#[````TA5``/_```"M\```VA5``-H:P`# +M2`H``K]_``)H^``"LN\``Z"!``*_PP`"0`\``T`E``*S_P`"L?\``D]>``/P +M`@`"N?,``D(I``*\`@`"3%P``_`!``*S^P`#:&```TA```./\@`"O/L``D$< +M``)A'P`#:$```VAK``-)?``"M`0``F$4``-I?``#2I0``_\```-A?``#:&L` +M`C%$``/_```#_@```_\```-!20`#_P```_\```-(9``#B$0``ZB```/H\``# +MW/```KQ```+,R``#V,```]0>``(R9@`#84D``TAD``*T$``"1B0``_`"``/T +M```!S)D``TAD``-(-@`"M$```K4$``)$0``"15@``F1%``',60`"M#P``D1` +M``/P0P`".KT``_0```',*P`#0!0``_\```/_```"PSX``_!!``,#/@`#8!0` +M`K#_``*Q_P`"LO\``K/_``-JD``#^`,``TAD``.,Z@``\@@``DP,``',=0`# +M2#0``KP$``),P``"#&0``.((``-)/0`"OQ```D1/``/P!``"O_\``BT$``*_ +M4``"+00``K\(``(M!``#]``````#:"T``VGM``-(R``"N/L``D(H``-HR``#2)@``K@@``)@"``# +M2+$``VB8``)D2``#:+$``\$.``/!'@`#P2X``\$^``-C,``#8W```V,T``-C +M=``#8S@``V-X``/T```!S/```T@(``*X]P`"0`@``V@(``-(*``"N-\``D,X +M``-(+0`#:"@``VGH``)'>``#:"T``VGM``-(R``"N`0``F(H``-HR``#2)@` +M`KC?``)`"``#2+$``VB8``)$2``#:+$``K`#``/!$``#P2```\$P``-C,``# +M8W```V,T``-C=``#8S@``V-X``-)?``"M/L``D$4``-I?``#:&L``_0```', +M*P`#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(``VC*``)H(0`#:,H``\&" +M``-HR@`#[````_@#``,/_@`"#04``^P```(R8``#:&L``\$.``/H$``#Z"`` +M`^@P``.D$P`#V!```]Q```/^```#U!X``VAK``-II``#Z````_X```/4'@`# +M:&L``VFD``*@W@`#\`,``T)@``/T```#\$$``T)<``-"60`"H-X``VFD``/P +M`P`#0F@``_0```/P00`#0F0``VFA``/^```#U!X``VAK``-H:P`#[````C)@ +M``-H:P`#0E8``\$.``/H$``#Z"```^@P``.D$P`#V!```]Q```/4'@`"OP(` +M`BT$``-H:P`#::0``VFB``/H```#_P```]0>``*_`@`"+00``VAK``-II``" +M,F```VAK``/L```#:&L``C)@``*Q#``#Z````Z`#``/<```#V!```^@```/H +M$``#Z"```^@P``/^```#U!X``VAK``/[```#^P```XCC``/X`P`#_@```]0> +M``-H:P`#^P```PB.``(-6@`#[````"'K``/H4``#Z&```^AP``*Y"``"N,`` +M`]R!``/8D0`#0E```_@#``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`# +M:&L``\&/``*_$``"+00``K09``/^```#U%\``VAK``*_$``"+00``\'X``-) +MI0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``#"9X``@V' +M``-II0`#[````J&^``/P#@`#T!X``P^^``*Z/P`#``X``D`*``,!'@`"01H` +M`P(N``)"*@`#`SX``D,Z``/4'@`##_X``@V0``/[```##,X``@V+``/L```" +MH;X``_`.``/0'@`##[X``KH_``+`#@`"0`H``L$>``)!&@`"PBX``D(J``+# +M/@`"0SH``]0>``,/_@`"#:0``_L```,,S@`"#9\``^P```/0G@`#T!\``KP_ +M``)(C``"29P``DJL``)+O``"1`P``D4<``)&+``"1SP``KP@``+`A``#H``` +M`J-(``/P00`"P`P``L&5``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`# +M\$$``L(L``+#MP`#HS```J-[``/P00`"PSP``KP'``*CW``#\$X``W)T``-2 +M=@`#_P```_\```/^```#U!X``VAK``/[```#<``&(P``/_```"H;X``_!"``#QY0`#[````J'.``/P00`#"[X` +M`PS.``#9YP``XC```TI```!:"0`#_P```_\```*@O@`#\$(``Z````.B(``# +MT%X``&'\``!9XP`#H@(``D`)``)"*0`"I8X``@X\``,(C@`"H`T``_`+``!! +M^0`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$3P`#P50``J6N +M``(.3``#"JX``J`M``/P"P``4?D``L9O``/!=@`"H+X``_!&``/47@`"QF\` +M`\%V``/47@`"QF\``\%V``/47@`##,X``@Y-``)KB@`"#A$``^P```-"<``` +M4@D``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``"H6@``_!!``+& +M:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,&:``#`B@``P,X +M``,*K@`"#F```\%4``/!=@`#U%X``V)P``/L```#P6(``P9N``/<$``#V``` +M`]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X``_L```,&;@`" +M#G4``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``#:1```VD4``-I +M&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I-``#[````\$0 +M``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC<``/T```#\$4` +M`VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4``D$#``-)T@`# +M_P```D`*``-)P@`"I1```_`!``-)Q@`#[````]">``/[```#_P```_\```/4 +MGP`#^P$``P_^``(.M``#[````_@!``*_!``#2F0``_\```/_```"00\``@Z_ +M``/X`P`#:&L``_\```/_```#_@```^P```-*9``#_P```K\(``)!#P`"H!\` +M`@[K``-`$@`"M1```J4E``/P!``"OP(``FJO``/T```!SN@``L15``*E)``# +M\`0``K\"``)KOP`#]````<[H``+$10`"I20``_`$``*_$``":J\``_0```'. +MZ``"OQ```FN_``#QY0`#8!(``B[L``/L```#2G```_\```/!P@`#0"X``K`! +M``-JJ``#_P```_\```/_```#2JP``K0"``-JJ0`#P````\`1``/`(@`#P#,` +M`TJM``*_D``"H,\``_`%``/`1``"OP\``D]/``/T```#\$$``\#T``*@W@`# +M\`L``T`9``/_```#_P```F1```)E40`"9F(``F=S``-@&0`":J\``_0```/P +M20`#0!T``_\```/_```"9$```F51``)F8@`"9W,``V`=``)KOP`#8"X``^P` +M``+$1@`#:JD``_\```/_```#_P```TJL``/L```",F```VAK```)U@`"L,`` +M`]P```/8$``"H/X``_`$``/H```#Z!```^@@``/H,``"H/X``_!$``*P50`# +MP1```\$@``/!,``"H/X``_`$``*T_P`#P50``\%D``/!=``"H/X``_!$``*T +MJ@`#P50``\%D``/!=``"O`<``J/^``(/G@``0?\``_\```/_```"H(X``@]D +M``*@W@`#\`,``T!"``/T!``#\`$``T!&``#J,0``:@```J3>``/P!``#P(@` +M`\"9``/`J@`#P+L``F`(``)A&0`"8BH``F,[``)D2``"95D``F9J``)G>P`` +M:C$``_\```/_```#_@```]0>``-H:P`#^P```PS.``/^```#U%X``VAK``/[ +M```##,X``@]D``!!_P``8@```_\```*@C@`"#XD``T!*``*DS@`#\`0``\"( +M``/`F0`#P*H``\"[``*DW@`#\`(``\&*``/!FP`"N@\``DJH``.+I@`":JL` +M`KOP``)+N``#I[8``FNW``/T!``#\`,``^A@``/HH``#Z+```K3P``)@2@`# +MP1```\$@``/!,``#:H0``J#^``/P`P`"M/```_0$``/P`0`"M`\``F!+``/! +M$``#P2```\$P``-J@``#[````_X```/4'@`#:&L``_L```,,S@`"N0,``J#Y +M``/P1``#Z$```^A0``/H8``#Z'```_X```/47@`#:&L``_L```,,S@`"#ZH` +M`K#P``*Q_P`"H/D``_!"``/H```#Z!```\$A``/!,0`#:H0``VJ```/L```" +M,F```VAK```)U@`"L,```]P```/8$``"M/\``\%D``/!=``"O`<``_X```*U +M_P`#U%X``VAK``/[```##,X``_X```*U[P`#U%X``VAK``/[```##,X``@_% +M``*U_P`#:H4``K#P``/!$``#P2```\$P``-J@``#2F(``B_O``/H\``"+_L` +M`VIB```)U@`"L,```]P```/8$``"M/\``\%4``/!9``#P70``KP'``/^```# +MU%X``VAK``/[```##,X``@_G``(R6@`#[````TID``*T@``"0`0``VID``/L +M```"L`0``J#P``/P`P`"+R4``_0$``/P`0`"*\0``^@```/````#P1```K+] +M``*S_P`#:&````HM```Q_@``&?T``K`*``*@W@`#\$$``K`,``.!%@`"8`$` +M`K$6``*D/@`#\`$``K,$``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`" +ML@0``F(F``-J8``#C^$``BT$``-H:P`#_P```_X```/L```#2F```_\```/H +M,``"8`X``VI@``-*9``"M/(``D`$``-J9``#[````K`!``/H$``#Z"```^@P +M``-J8``#[````&HQ``-`!``#_P```K@$``)%X``"H%X``_!$``*@W@`#\$(` +M`T`D``/_````8>D``_\```/_```#W,```X_J``*@W@`#\`$``^CP``/8\``# +MC.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<``D`(``/P +M0P`"+8L``_0```/P00`"+9\``D1N``/P"0`#Z,```ZMB``.E8``"15X``_!# +M``(MBP`#]````_!!``(MGP`#[````&HQ``-`*``#0"$``KA```)(@``#\`,` +M`D9N``/P`0`#[````%'#``*@W@`#\`,``%G"``/T```#\$$``%G!``/_```# +MW*```]BP``-`!@`#_P```_\```)`Z``#\`,``J#>``/P00`#0"8``_\```/_ +M```#24$``J`.``/P0P`"H-X``_!!``/!10`"14X``_!#``.,Y``#]````_!! +M``.,XP`#B9@``ZJ<``*@K@`#\`,``BV+``/T```#\$$``BV?``-`!@`#_P`` +M`_\```-)00`"0(X``J`.``/P0P`"H-X``_!!``/!10`#Z,```ZM"``)%3@`# +M\`<``Z5```)%7@`#\$,``BV+``/T```#\$$``BV?``/L```"H-X``_`#``-( +M(0`#]````_!!``-()0`#_P```KL!``.B9@`#@68``Z$6``.'=@`"8"<``P`+ +M``.G!@`#@@8``F8A``*@W@`#\`0``V@A``-JB0`#]````_!"``-H)0`#:HT` +M`^P```./[0`"+00``^@P``."X``#Z!```^@```-H,``#C^T``BT$``-)G``# +M2=4``T`J``*T$``"1$<``K4"``)%6@`#A50``D1%``.D0``"MO<``D(F``)B +M)``#:9P``^CP``-)<``#Z'```K8!``/!40`#P4```V@Q``*X_``#P5,``\%" +M``)%6``#270``C%$``-H,0`#P5$``\%```(Q1``#:#$``\%3``/!0@`#29@` +M`C%$``-H,0`#P5$``\%```(Q1``#:#$``\%3``/!0@`#29P``C%$``-H,0`# +MP5$``\%```(Q1``#:#$``\%3``/!0@`#2.@``C%$``-H,0`#P5$``\%```*W +M$``",40``V@Q``/!4P`#P4(``C%$``-H,0`#[````KP#``-)/0`#2,```J#> +M``/P00`#2,0``K8$``)&9``#\`0``X;*``/!?``"8B8``F$7``*@W@`#\`,` +M`VC```/T```#\$$``VC$``-`*@`"M@@``X?&``)&:``#\`$``F,W``*@W@`# +M\`,``VC```/T```#\$$``VC$``/L```","X``TD]``-`*``"OP@``KP$``)/ +M#P`"3$P``F#\``/P00`#[````K0!``(R`@`",0D``J'^``/P"0`",<,``C`H +M``-`*``"O`@``_\```)"+``#\$(``_0```/P0@`#Z$```C("``/L```#_P`` +M`_\```/_```#[````V%(``-A00`#848``V)_``/!#@`#Z!```^@@``/H,``# +M:.@``^@```/_```#:.@``T%(``/_```#[````C)@``-H:P``"=8``^@```.@ +M`P`#W````]@0``*\`P`"L/<``J#^``/P00`"L'\``\$0``/!(``#P3```K3_ +M``/!5``#P60``\%T``/^```#U!X``VAK``.@`0`#H1$``Z(A``.C,0`#^P`` +M`_X```/47@`#:&L``_L```,,S@`"$6H``K#_``*\"``#P1```\$@``/!,``# +M:H```J3^``'1A``"H/P``_`"``-JA``#[````K#W``.A`0`#HA$``Z,A``-J +MA``#[````TD]``/_```"N(```F1(``-I/0`"L`$``K$"``*R/P`"0B\``K,` +M``-J:``"L````K$```*R```"LP(``VIT``*Q`0`"L@@``K,```-J>``"L`$` +M`K(```-J?```$>```K#```)`#P`#H`(``F`.``*Q```#HB(``K,!``-J9``" +M,EH``_\```/_```"+KT``KA_``)$2``#:3T``^P```/H```#Z!```K(#``*S +M```#:#```^P```-`+``#_P```_\```/H(``#Z#```V`L``/H```#Z!```V`8 +M``-@'``#[````&HQ``*P`0`#Z!```^@@``/H,``#:F```K\!``(O]``"OQ`` +M`BT$``*\%``#2F```K_W``*Q$P`"0`\``F`.``-J8```,?X``#G]``*\B``" +MM?X``X9J``)B)@`"I'X``_`!``*S!``"0`4``F`,``-J8``#2I8``T`I``*\ +M!P`#_P```D1,``.%1``"Q5X``\'%``/H0``#Z&```^AP``-JD0`"M/\``K5_ +M``*V_P`"M_\``VAA``-H:P`#_P```_X```,)G``#\$4``\"9``,*K@`#\$(` +M`\"J``,+O@`#:I(``X````.@```#:F```K\0``(M!``#[````T`J``-'+``" +MH-X``_!!``-';``"MG\``X5,``)`!@`"29X``_`!``)@!0`#P1```\$@``/! +M,``"H-X``_!$``-G+``#9S```_0```/P0@`#9VP``V=P``-'-``"H-X``_!! +M``-'=``"MM\``X5(``)`!@`"8`4``\$0``/!(``#P3```J#>``/P1``#9S0` +M`V``#2,```J#>``/P00`#2,0``K8_``)")@`" +MML```J!.``/P`0`#Z&```F(F``*@W@`#\`,``VC```/T```#\$$``VC$``/L +M```#29@``K@/``*Y]0`#Z#```\$N``*@S@`#\`(``F`(``)!&0`#:#```T@( +M``*X0``"H,X``_`"``)@"``#:`@``^P```-A4``#854``V%:``-A7P`"+`4` +M`T%0``-!50`#05H``T%?``/_```#_P```^P```*P_P`"L;\``K+_``*S_P`# +M:&```^P```*P?P`"L?\``K+_``*S_P`#:&```^P```+$3@`#\$H``L5>``/P +M2``"QFX``_!&``+'?@`#\$0``K3_``*U_P`"MO\``K?_``/L```"H```^A```*@`0`#\`$``\%.``(T7@`#2`@``KC^``)! +M&``#:`@``KP```(T"0`"-#H``T`!``/H````@C$``D1.``/P`0`")!L``T`! +M``/_````\C$``D5>``/P`0`")!L```(*``.!X``#_P```J00``/P`@`#P4X` +M`C1>``*\`0`"-`D``C0Z``*_`P`"-N0``C-%``(NJ``"OQ```D_[``'2X``` +M>``(N@@`"+J@``X3B``/!R0`#Z````K$#``*R"@`"LRT``D1)``/P +M`0`"LR\``^A0``(N<0`#@.H``BYQ``*X+P`"M`(``D1,``/P`0`"N"T``\&8 +M``/!J``#P;@``V,J``-C:@`"+J@``X'B``.@X0`#HY8``X+D``+"+@`#Z%`` +M`BYQ``.@XP`"+G$``BZH``.`Y0`"0*```\$0``/!(``#P3```V2H``-DZ``# +M@.```H((``)"`@`#@B0``)'4``/L```"+J@``TEP``)$C@`#\$,``K7S``)" +M)0`#:7```^AP``/!;@`#P5,``\%"``-H,0`"1)X``_`&``-)G``#I.$``F(D +M``/!4P`#P4(``V@Q``)$C@`#\$T``TF<``.$Y0`#I><``D`$``)!%0`#I(@` +M`X1```.%1@`"8`4``F$4``/H,``#P2X``V@P``-#I```(=0``K7/``)`!0`" +M8`0``\$0``/!(``#P3```V.D``-CY``"1$0``_`!``(VWP`#@80``Z`8``." +M!@`"8`(``^C0``(NE@`#P=X``BZ6``-)T0`"+J@``^A@``*E$``#\`$``K9` +M``)&=@`#IFH``TB0``.DN@`"H$X``_!!``*T!``"M0,``J!%``/P00`"M`$` +M`K7P``)!%0`"810``K?^``)`!P`"8`8``VB0``-HJ``#:)0``VBL``.@I@`# +MP1```\$@``/!,``#9"0``V1D``.*M@`#2"$``K@#``)F:``"N0\``KO^``)& +M:0`"9FH``D=[``-H(0`#:HD``V@E``-JC0`#2`@``T@A``)A'@`#:`@``TC( +M``*X0``"N3\``F`(``-HR``"0`D``VC(``/L```#0"P``KA```*Y@``#Z+`` +M`TJE``)(&``#\`$``KLP``))&0`#\`(``KK```)KN@`"95L``VJE``-(G``" +MO'L``D`,``-HG``#:*```VBT``-HN``#2)```X3B``.EYP`"014``F$4``*U +M_@`"0`4``VB0``-HJ``#:)0``VBL``-).``"M0,``F(E``*U\P`"0B4``VDX +M``/HP``"-`D``C0Z``/H```"L0,``K()``/H,``#Z%```BYQ``.`Z@`"+G$` +M`K`$``/!$``#P2```\$P``-C)``#8V0``K`@``/!$``#P2```\$P``-C*``# +M8V@``C;?``-("``#2"$``ZCM``)!&``#:`@``ZCK``)&:``#P#X``D53``-H +M(0`#:HD``V@E``-JC0`#Z$```C1>``/H\``"/B(``K\!``(^(@`#[````T`I +M``/_```"N"H``D)>``/P`0`"N&0``J#.``/P00`"N!```\&8``/!J``#P;@` +M`V@`# +M0[(``K`'``*Q*``"0EX``_`!``*Q.``"H,X``_!!``*Q```"2(```FB!``/! +MF``#P:@``\&X``-CL@`#8_(``^P```-)=``#P6X``^AP``.(2``#P%X``X59 +M``)")0`"8B@``VET``/!0@`#P5,``V@Q``/L```"OP,``C;D``-("``"N/X` +M`D$8``-H"``#0"@``KP$``*_`P`"3,(``_`#``(]RP`#]````=2+``-(5``" +MO&```F(L``-H5``#278``KP0``)DK``#P5L``\%N``/H<``#:#$``C%$``-( +M5``"O)\``D(L``-H5``#P4H``V@Q``(SJP`#0D4``C)F``-B10`#[````&HQ +M``(M"```\>4``C`H``(KQ``#0`0``T`*``*\`P`"OP0``D$<``,&\0`"0`\` +M`_`!``/!:@`"Q&X``K4(``(XK@`#0`0``^CP``#Z!@`"LD```D(@``'4\0`# +MCP0``Z_X``#Z`P`#2<$``KP/``)(SP`#J(```XF"``*ZXP`"1$H``F1)``)) +M_@`#B9(``KK[``)%6@`"95D``VG!``.!A@`"8($``BZ6``/H```"H-X``_!! +M``*P0``"L0,``K()``*S"0`"1.\``_`!``*S#P`#Z%```BYQ``*C_``!U/$` +M`^C```#AS@``X>X``C97``-`&``"H-X``_!!``-`'```0>X``&'.``)@`0`" +M8`(``F`#``*A#@`#\$(``LB.``#![@`"N@(``KL?``+,R@``X4``_0` +M``'4J@`"S_X``/H#``#"!@`#]````=2J``/HP```X@,``^@P``(V:P`#W.`` +M`K\(``/8\``"L"```\$0``/!(``#P3```K\1``/4'@`#_P```_L```,/_@`" +M%/T``C97``!B`P`"L````]P```/<`0`#C\(``K!```+`#P`#V````K`_``)! +M#P`"L,```L`!``/8`0`#U%X``]`?``*_$``"H<\``=4>``*@W@`#\`,``\$* +M``/T!``#\`$``\$+``/4'P`#]````=4E``*@W@`#\`,``\$J``/T!``#\`$` +M`\$K``/4'P`"-@\``T`&``*P'P`"L2```\$N``)!&``#\`$``L(N``+,P@`` +MX@,``J7```(5`@`#2I0``_\```-@O``#0`0``]S@``*_"``#V/```]SA``*_ +M+``#V/$``K\(``.L%@`"I<\``_!#``/`S``";,\``LS.``*_"``#T!X``]!? +M``/!B0`#P9H``\&K``+$0``#H$```L`,``/!L``"Q5$``Z%0``+!'``"IAL` +M`_`!``/!L0`"QF(``Z)@``+"+``"IBL``_`!``/!L@`"QW,``Z-P``+#/``" +MICL``_`!``/!LP`#U!X``]2?``/[```#^P$``P_^``(50P`#03@``T%)``-! +M*@`"O`X``J,!``/P`0`#P0$``J,"``/P`0`#P0(``J,#``/P`0`#P0,``J,( +M``/P`0`#P0@``J,)``/P`0`#P0D``^@0``*F#``#\`,``\````.`!@`#H08` +M`\$!``*C10`#\`$``\%%``*C1@`#\`$``\%&``*C1P`#\`$``\%'``*C2@`# +M\`$``\%*``*C2P`#\`$``\%+``/H(``"IDP``_`#``/`1``#A$8``Z)&``/! +M,@`"H-X``_`#``-DJ``#]`0``_`!``-DZ``#W.```K\(``/8\``#T%X``K\$ +M``/<\0`"OX```J#>``/P00`"O\```]CQ``*\$``"N`$``KD#``*Z#P`"H4P` +M`_!%``/`1``"1$H``P0$``/T!``#\`(``P1*``+$0``"H5P``_!%``/`50`" +M15H``P4%``/T!``#\`(``P5:``+%4``"H6P``_!%``/`9@`"1FH``P8&``/T +M!``#\`(``P9J``+&8``"H7P``_!%``/`=P`"1WH``P<'``/T!``#\`(``P=Z +M``+'<``#U%\``_L```/[`0`#T%X``PB.``(5J0`"N`$``\$!``/!$@`#P2,` +M`PF>``(5J0`#1*@``J#>``/P00`#1.@``J%,``/P10`#P$0``D1*``,$!``# +M]`0``_`"``,$2@`"Q$```J%<``/P10`#P%4``D5:``,%%0`#]`0``_`"``,% +M6@`"Q5$``J%L``/P10`#P&8``D9J``,&)@`#]`0``_`"``,&:@`"QF(``J%\ +M``/P10`#P'<``D=Z``,'-P`#]`0``_`"``,'>@`"QW,``]1?``(L]P`"-&L` +M`C`H``(O[P`#[````BZH``.CE@`"-FL``X#E``)#H``"-G0``_0```'6`@`# +MP9```J'/``/P`0`#P9(``V)U``#)S@`#W.```K\(``/8\``#W.$``K\L``/8 +M\0`"OP$``\$$``(V,0`#0G4``K\!``/_```#P04``C8Q``-"=0`"OP$``_\` +M``/!!@`"-C$``T)U``*_`0`#_P```\$'``(V,0`````/4GP`#^P```_L! +M``.@```##_X``A8R``/L```"LQ```J7#``/P!@`#P#P``X,V``.C-@`"-G0` +M`_0```'69``"LP\``LS.``)#/``"-FL``C&X``(L]P`"-&L``K\8``(X7``" +M+NP``^P```*Q!``"L(```J#>``/P00`"L,```K()``/H4``"+G$``^P```/! +M`P`#P1,``\$C``*@W@`#\`,``V2H``/T!``#\`$``V3H``/L```#0`0``KR` +M``/_```"3,```=:>``-!`0`"H-X``_!!``-!!0`"L00``K"```*@W@`#\$$` +M`K#```/<$``#V````\&$``(VNP`#P84``C:[``/!A@`"-KL``\&'``(VNP`" +MH-X``_`#``-DH0`#]`0``_`!``-DX0`#]````=:X``*Q!``"L(```J#>``/P +M00`"L,```]P1``/8`0`"L0$``K`(``*@W@`#\$$``K`L``/<$``#V````K\( +M``(NM``#00$``J#>``/P00`#004``J#>``/P`P`#9*D``_0$``/P`0`#9.D` +M`BSW``(T:P`#[````\&8``/!J``#P;@``K(!``/4G@`#^P```P(N``(6OP`# +M[````K$$``*P@``"H-X``_!!``*PP``#W!```]@```*Q`0`"L`@``J#>``/P +M00`"L"P``]P1``/8`0`"OP@``BZT``-$J``"H-X``_!!``-$Z``"H-X``_`# +M``-A```#]`0``_`!``-A!``#[````TL,``*U_``"014``VL,``/L```#2PX` +M`\#/``)JKP`#:PX``C%$``)*K``#:PX``^P```*_`P`"-N0``TG```-)U0`" +M3`X``_!"``/T```!URD``TG```.'=@`"IG```_!"``/!$@`#Z````Z(6``.! +M%@`#H18``TB1``*\\``"15P``F52``*\!``"0PP``Z,R``*\_@`"1$P``F1# +M``-HD0`#:)4``VBI``-HK0`#P4$``\%1``/!80`#P7$``V0A``-D)0`#9&$` +M`V1E``*\`@`"0@P``X(J``-(G0`"LW\``D1#``)D0@`#:)T``VBA``-HM0`# +M:+D``J$.``/P`@`"-M\``K`0``/!$``#P2```\$P``-CH``#8Z0``V/@``-C +MY``#27P``K3[``)!%``#:7P``VAK``/T```!S`4``C`H``(O[P`#0````_\` +M``/_```#H`P``Z$<``.!$``"81```P\>``/HT``"H/X``_!!``*]`0`#P4``_\```)&8@`"9FH``VGE``/T!``"%W8``J/^``(7R@``T=`` +M`J#>``(7GP``T=$``LW>``/T!``"%U4``$'1``/_```#_P```J"H``(7R@`" +MH:@``_!(``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@``VGE``-()0`#`Z@``X,P +M``)G4``KB```)G>``#8!$` +M`TF8``*U!``"814``VF8``-("``#_P```X3(``)@!``#:`@``_@#``/L```` +M:C$``^@```""#```@<\``CC*``-`)``#_P```_\```)`#@`#\$L``T`0``*\ +M!``#W,```X_J``*@W@`#\`$``^CP``/8\``"O`D``\&Q``(MBP`#0"0``_\` +M``*\`@`"0`P``_!+``-`$``"O`0``]S```*_P``"H-X``_`!``*_@``#V/`` +M`XSD``/!L0`"+8L``BO$``*T!@`"M0@``K8$``(XK@`"OQ@``CA<``(X@P`" +MOP```B_T``-*<``#_P```_\```*RD``#:G```K\3``(X7``".(,``T`D``/_ +M```#_P```D`.``/P2P`#0!```KP$``/``/P`0`#Z/```]CP +M``*\"0`#BQ```BV?``-`)``#_P```KP"``)`#``#\$L``T`0``*\!``#W,`` +M`K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(MGP`#2G```_\```/_```" +MLH```VIP``*_&``".%P``CB#``*_```"+_0``TIP``/_```#_P```K*0``-J +M<``"OQ,``CA<``(X@P`#0"0``_\```/_```"0`X``_!+``-`$``"O`0``]S` +M``./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+8L``T`D``/_```"O`(` +M`D`,``/P2P`#0!(``KP$``/``/P`0`"OX```]CP``.,Y``# +MP;D``BV+``(X[``#[````^@```/````"L;\``\$@``*S_P`#:&```C`H``(O +M[P``"BT``!'^```9_0`"L`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&$ +M``)B(0`"I#X``_`!``*S!``#P1\``VI@``-*9``"M(```!'L``)`!``"M`,` +M`F`$``*S$``#:F0``BZ]``*_"``"3_```_`!``#R#``#[`````(,``/_```# +M_P```J4.``/P`0`#[````^@```""#``#0!(``_\```/_```"1(X``J!.``/P +M`0``\>4``K]```*@W@`#\`,``FJO``/T```#\$$``FN_``-@$@`"+NP``'G/ +M``/_```#0"```J#^``/P00`#[````J#>``/P!0`"P`X``_!!``*P_P`#]``` +M`_!#``+!'@`#\$$``K'_``-@(```\<\``^P```*P`0`"L0(``\$D``/H,``# +M:F@``\$E``*P$P`"L0(``X(F``/H,``#:G```K`A``*Q`@`#P28``K,!``-J +M=``"L`$``K$"``*R#P`"LP$``VIX``-*?``#_P```K````*Q```"LP0``VI\ +M``/L```"L`$``K$1``*R$``#:D0``K$0``/H(``#:D0``J#>``/P`P`"NU,` +M`_0```/P00`"NUL``-GL``-("``"M$```('F``)@!``#:`@``T@!``*POP`" +M1$```V@!``/H```"L4```^@@``/H,``#:D0``K`!``/H$``#Z"```^@P``-J +M8``#[````C`H``(O[P``(>8``_\```-("``#_P```\$$``-H"``#[`````HR +M``!J,0`#_P```D`>``/P00`#[````CC*``*_```"+_0``#(:``/_```"M0D` +M`Z9B``+&;@`"Q&X``CBN``-`*``#Z/```J#>``/P00`"OT```/G@``.@#``` +M@<4``T`8``-`'0`#0"X``&'E``/_```#_P```V%0``-A50`#85H``.''``-` +M$```>>```KP$``/``/P00`#0!P``T`M``/_```#U!X``]1? +M``*_`0`#W/```K\```.(P@`"S_@``]CP``/$```#Q!$``\0B``/$,P`"H-X` +M`_!!``/!9P`"M1$``D1E``/$1``"P`0``K4B``)$90`#Q$0``L$4``*U1``" +M1&4``\1$``+")``"M8@``D1E``/$1``"PS0``]0>``!YQ0`#0G4``T)R``)/ +M_@`#\$(``L`!``+"(P`"H00``_!&``*E"0`#\`0``\&,``/!D``#P:P``\&P +M``*C"0`#\$(``\&L``/!L``#8G(``T)&``*A)@`#\$8``J4I``/P!``#P8P` +M`\&2``/!K``#P;(``J,I``/P0@`#P:P``\&R``-B1@`"H/X``=FN``-"3@`" +MH14``_!&``*E&0`#\`0``\&,``/!D0`#P:P``\&Q``*C&0`#\$(``\&L``/! +ML0`#8DX``T)*``*A-P`#\$8``J4Y``/P!``#P8P``\&3``/!K``#P;,``J,Y +M``/P0@`#P:P``\&S``-B2@`#8G0``_L!``*Q$``"S,X``.'.``*@P0`!V3<` +M`T)P``-"10`#_P```L@"``.H@``"RD8``ZJ@``-"3``#0DD``_\```+)`@`# +MJ9```LM&``.KL``".=L``T`0``!YX``"O`0``]S```/8\``"O`D``\&Q``(M +MGP`","@``B_O``-!4``#054``T%:``!AQP`#_P```_\```-@&``#8!T``V`N +M``#AY0`#[````KLA``*[$````<4``_\```/_```"0`X``=H3``.IA``#JZ0` +M`KP/``.(@``"2(P``XJ@``)*K``#2)P``TBA``*@W@`#\$(``TBT``-(N0`# +MP1@``\%:``.,%@`#CU8``F$<``)E7P`"H-X``_`$``-HG``#:*$``_0```/P +M0@`#:+0``VBY``-*Z``#2NT``J#>``/P0@`#2O```TKU``*\[@`"0`P``D1, +M``.(E@`";)@``F`,``.*M@`";+H``F1,``*@W@`#\`0``VKH``-J[0`#]``` +M`_!"``-J\``#:O4``^P```*_!0`"O````J#>``/P00`"O$```]SP``/8P``" +MO(```FB,``)IG``":JP``FN\``/!"``".BL``\$)``(Z*P`#P0H``CHK``/! +M"P`".BL``]2>``/[```#U)X``^P```/!$``#P2```\$P``/4'@`#^P```]0> +M``/[```#[````&HQ``(M"``#Z````K%@``/H(``#Z#```VF@``-)F``"N`\` +M`K7U``*S```#P2X``F`(``)!%0`#:#```K\!``(M!``".,H``C`H``-`+``" +MOP0``_\```)/\``#K_(``^CP``(O]```,AH``_\```*U"0`"Q&X``CBN``/H +M\``"H-X``_!!``*_0```^>```%G'``!YX``"O`0``]S```/8\``"O`D``BV+ +M``/HP```X``/P00`#P:L``&'.``!YQ@`# +MU%\``_L!``/07@`"NP(``J'^``/P00`#P4H``J#^``/P00`#P5H``J#[``/P +M00`#P6H``J;[``/P00`#P7H``]1>``/[```"L!```LS.``*EP``#\`8``.'. +M``/!C``#P:P``CG;``/T```!VFL``K$$``+/_@``^<8``J'Q``':I@`#Z+`` +M`-G.``/!BP`#P:L``CG;``!YX``"O`0``]S```/8\``"O`D``\&^``(MBP`# +MW.```KM```/8L``#]````=IK``(X[``"N`@``KH(``(YVP``6<<``'G@``*\ +M!``#W,```]CP``*\`P`"R[P``KP)``(MGP`#2`@``K1@``)@!``#:`@``TF8 +M``/_```"L@$``^@P``-H,``#[````K0$``)&-``"H&0``=K*``/H\``"/?0` +M`K\!``(]]``#:&L``T))``(R9@`#8DD``^P```-"30`",F8``V)-``-(9``# +M^`$``KT,``))T@`"H-D``_!&``*_`P`".RD``K\#``*]```".PH``^P```*] +M!``"2=(``_`&``*_`0`".RD``K\!``*]```".PH``^P```*]"``"2=(``_`& +M``*_`@`".RD``K\"``*]```".PH``^P```*]8``"2=(``J#9``/P1P`"OP,` +M`CNP``*_`P`"O0$``KP!``(["@`#[````KT@``))T@`#\`<``K\!``([L``" +MOP$``KT!``*\`0`".PH``^P```*]0``"2=(``_`'``*_`@`".[```K\"``*] +M`0`"O`$``CL*``/L```#2&(``DS.``(;'``#@/(``\````.!^``#P!$``DW> +M``/P10`#P````FJ@``)*H0`#]`0``_`#``/`$0`"2J```FJA``-H8@`"L/(` +M`FJ@``*@"@`#\$<``TA```*T"``"M?<``F$4``-H0``"014``VA```-H:P`# +M[````TA4``/H@``"N0,``DO^``/P`0`":(D``KH"``*Y#``"2_H``_`!``)H +MB0`"8S@``VA4``/HD``"M`0``DO^``/P`0`":9H``DOZ``/P`0`":90``TE@ +M``-H:P`#_P```_\```-(90`#_P```DO6``*@O0`!VZ<``DN3``';/@`#0"@` +M`X3P``"B`@`#HB8``C%$``,"+@`!VTT``T@$``*T[P``BBP``D$4``-H!``" +MM8```DO^``/P!0`#2)@``K2_``)#-``"8S4``VB8``)+^@`#\`4``TBP``*T +MOP`"0S0``F,U``-HL``"/>@``K8$``-H,0`#0"@``C%$``)!&@`"&Y```$H! +M``/_```"N(```\"9``.)G``"2_X``_`&``-)/``#2)D``F,X``)D20`#:3P` +M`VB9``)+^@`#\`8``TE```-(L0`"8S@``F1)``-I0``#:+$``DO^``/P!@`# +M2)```TB5``)@"``"9$@``VB0``-HE0`"2_H``_`&``-(J``#2*T``F`(``)D +M2``#:*@``VBM``-`*``#_P```K@$``)!&``#\`$``CQH``-`*``#_P```K@( +M``)!&``#\`$``CTJ``-(0``"N(```DO^``/P`0`"81@``DOZ``/P`0`"8B@` +M`VA```*\`0`#[````TA4``/`B``"0S@``VA4``-"20`",F8``V))``*\```# +M[````T`H``#YNP`"N`@``D$8``/P`0`"/4$``T`H``/_```"N`0``D$8``/P +M`0`"/+<``T`H``/_```"N`(``D$8``(;YP`"2_X``AO*``-)/``#2)D``KA_ +M``)#.``"1$@``VD\``-HF0`"O`(``DO\``(;U``#24```TBQ``*X?P`"0S@` +M`D1(``-I0``#:+$``DO^``(;W0`#2)```TB5``*X?P`"0`@``D1(``-HD``# +M:)4``KP"``)+_``"&^<``TBH``-(K0`"N'\``D`(``)$2``#:*@``VBM``-` +M*``#_P```K@.``)!&``"'`<``CT4``)!%P`#:,@``T@(``*X$``"01@``=P' +M``)+_@`"&_P``T@@``*T`0`"M?P``F$4``-H(``"014``V@@``*\`@`"2_P` +M`AP&``-()``"M`$``K7\``)A%``#:"0``D$5``-H)``"-N0``DO^``(<#@`# +M2)@``K3```)C-``"0S0``VB8``*\`@`"2_P``AP6``-(L``"M,```F,T``)# +M-``#:+```KP#``(]R``#2$```KA_``)+_@`#\`$``D(H``*\`@`"2_P``_`! +M``)!&``#:$```T@(``*X$``"01@``=PQ``-`*``"O`0``_\```),P@`#\`,` +M`CU8``/T```#\$$``CW+``).[@`!W#,``KP(``(]R```>;L``_\```/_```" +M2_X``_`$``-(F``"M#\``D,T``-HF``"O`(``DO\``/P!``#2+```K0_``)# +M-``#:+```TA```*X(``"2($``AQ*``(]Z``"M@(``V@Q``-)?``"N`(``DB` +M``(<40`#27$``CWH``-H,0`#2`0``"(L``/_```#_P```\$4``-H!```>;L` +M`K@```*\`@`#2%0``DO^``/P`0`"N`,``DO\``/P`@`"O`P``FB,``/`B``" +M0S@``VA4``.`^```@@(``^P```-("``"N!```D$8``'<>0`"2_X``_`$``-* +M5``"M`\``F`$``-J5``"NP(``DO[``/P!``#2E@``K0/``)@!``#:E@``DO^ +M``/P!``#2E0``K3P``)@!``#:E0``KL"``)+^P`#\`0``TI8``*T\``"8`0` +M`VI8``-("``"N!```D$8``'``/P`@`"OP`` +M`CWT``*\`@`"2]P``_`"``*_`0`"/?0``\']``/L```"M_P``K8S``*U1``" +MM````TC(``*@_@`#\$$``K0!``*\`@`"H/P``_!!``*T`@`"810``VC(``)@ +M!0`#:,@``_\```)`!@`#:,@``KP"``(]R``#[````T@(``*X$``"01@``=T[ +M``)+_@`#\`0``TB8``*T?P`"0B0``VB8``*[`@`"2[\``_`$``-(L``"M'\` +M`D(D``-HL``#23@``X3R``/`1``"0B0``VDX``/L```#23@``X3R``)B)``# +M:3@``T@(``*X$``"01@``_`!``/L```"2_X``_`$``-(F``"M(```F(D``-H +MF``"NP(``DN_``/P!``#2+```K2```)B)``#:+```^P```-"20`",F8``V)) +M``)!_@`"'64``T.N``*P[P`#_P```DNP``)*L``"2;```DBP``-CK@`"L0(` +M`D'Q``(=<``#0^X``K#O``/_```"2[```DJP``))L``"2+```V/N``-(5``# +MC/@``F(L``-H5``#270``KS?``)$+``#P5,``CWH``-H,0`",40``KP0``)D +M3``#:#$``C%$``-(5``"O)\``D(L``-H5``#270``_\```/!0@`#P5,``CWH +M``-H,0`"0?X``AV3``-#K@`"L!```_\```)KL``":K```FFP``)HL``#8ZX` +M`K$"``)!\0`"'9X``T/N``*P$``#_P```FNP``)JL``":;```FBP``-C[@`" +MO`(``D?^``),_``";,<``K<#``*@?P`#\$$``^C```-(R``"N$```KD_``)@ +M"``"81P``VC(``)`"0`#:,@``\#,``)!'``#:,@``KO\``)*_@`#\`@``T@A +M``/_```"95X``V@A``-JB0`"15L``V@A``-JB0`"N@(``DJO``/P"``#2"4` +M`_\```)E7@`#:"4``VJ-``)%6P`#:"4``VJ-``/L```##,X``=W(``/L```" +M/>@``K8"``-H,0`"M@$``TF>``*\$``"9*P``\%;``-H,0`#29H``KP"``)D +MK``#P5L``V@Q``/_```#270``KP0``)D+``#P5,``V@Q``(Q1``#P,P``D1, +M``-H,0`",40``\%*``/!6P`#:#$``^P```/!;@`"MP,``DW^``/P`@`"O0(` +M`D=]``*]`@`"3?T``_`"``*]`0`"1WT``^P```*X!``"L0(``K"```)/_@`# +M\`$``K#```(^0@`"L0,``K````)/_@`#\`$``K!```(^0@`"L0,``K"```)/ +M_@`#\`$``K#```(^0@`"L00``K````)/_@`#\`$``K!```(^0@`"L00``K"` +M``)/_@`#\`$``K#```(^0@`"3_X``_!'``-'-``#1SD``_\```-G-``#9SD` +M`_0$``/P!0`#1W0``T=Y``/_```#9W0``V=Y``/L```"N`0``^@```/H$``# +MZ"```^@P``)/_@`"'C```V4L``-E,``#930``V4X``-E/``#]````=XU``-E +M;``#97```V5T``-E>``#97P``K$&``*P```"3_X``_`!``*P0``"/D(``K$& +M``*P@``"3_X``_`!``*PP``"/D(``^P```+""``#W!```]@```/<$0`#V"$` +M`]`>``/07P`"O`<``]0>``/47P`#^P```_L```/[`0`#^P$``]`>``/07P`# +:#,X``=Y*``/L```#_P```_\```/_```#_P`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_me.bin.uu new file mode 100644 index 00000000000..74b24a00065 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_me.bin.uu @@ -0,0 +1,194 @@ +begin 644 TAHITI_me.bin +M?$"``8@```#40`!_?$"``8@```!\0,`!S$``*,Q``"E\0(`!B````-A``![$ +M$``A)1```I4`__Y\00`!Q!P`)L0@`"38```50``"V4&BI,0;``+8```;S8``&L`^``3,`:'TS#T@!,0]``',```%V$`` +M&]A``!]\0(`!B````,Q!+@',02X"S$$N`\Q!+@!\0(`!B````'Q`P`&,``4B +MS$$N`'`&GQ"``$E)``! +MS,``(]%``"31@``ET<``)MA``">60``,Q"@`+)J`___()``M?EZ`#)J`_YP2 +M+``&!NP``0KL``&:P/__V$``)X```&#$*``LFH#__WQ`@`&(````?$#``<00 +M`##,027,?04```````ET```\Z!HKN````` +MEX```\Z!HK^`````SH&BPX`````$&```@``!0P08``'$)``F?$#``<9K`^08 +MT``P)-0`_P:H``'.I`/DFD``$L0X``?80``>Q#P`(2?\``*7P/_^S(``"Y>` +M``+90:*DQ#\``L_``!K`/@`$S`&A],P](`3$.0`!S```!=A``!_-0:#:S(`` +M"\U!+A29@``"S````LU```A\0(`!B````'Q`P`$8T`'H&-0`,!C8`#0%*`%K +M?$(``7Q"0`&5```'AH```(```86```&I@``!OX``!1Z```%[$50`$'X6``K, +M@``+U&$``)6`_HO`.@`$S#DA0,0Y``%\0(`!B````!%4`!!29``@?B8`&LU` +M`!W48@``E8#^@,0@`!V:`/__?$"``8@```#<.@``F4``&R><``&5P``-"[@` +M```%\0@`!",P``08D``$&*``"SAVA_``"```(.P"(`!'X6``K,(0``Q!T``7Q"0`%\0H`!F,`` +M`\WE``"`````SD$A:'@```@``"1X```DR```)1@``"5H```EN```)@@``"97\;@`\4I``( +MEX``'29D`/^```)V?QN`#A2D``B7@``8)F0`_X```G9_&X`,%*0`")N``!,F +M9`#_@``"=G\;@`T4I``(FX``#B9D`/^```)V?QN`#Q2D``B;@``))F0`_X`` +M`G9_&X`.%*0`")N```0F9`#_@``"=A2D``@F9`#_,F@`/!3L``B:@/V7?$-` +M`7Q#@`%\0\`!S```"Y;```;/02%ISX$A:L_!(6O,`2%L@````,_U``"````` +M,F@`/)J`_[/40`!_@````'Q`P`%\00`!P!X``144`!+`(@`"P"8`!)5```3` +M)__[?24`"<`F``!]TH`)?A+`"7TE``I\04`!?$&``@%*`*I',S^",R```N5```)AH```(```K2```+#@``"RH```M&` +M``+7@``"XX```P',P:*D?$"``8@```#`$@@`?$%``7Q"``%]#,`*P!(`!!58 +M``,57``-?='`"1(@`!-^'D`*?DZ`"LZ!HJ3-@:'^?$"``8@````$$"$8Q!0` +M"Y5`___440``S,&BI'Q`@`&(````!!`A!L04``R50/__U%$``,S!HJ1\0(`! +MB````-A```_,P:*DQ!``#YD`__]\0(`!B````!C0`#01%``4Q"0`#99`___, +M02$`?45`"LU!(0',02$"S$$A`\S!HJ1\0(`!B````"38``%\00`!?$%``1&< +M`!!\0@`!?5U`"A5D`!TF9``"E8``"<0\`!^7P/__FD``#<0H`#`6J``"?BH` +M`@``#L8```[2```.V@``#N(```[J```.\ +M4=P`('V>`!J```/]R"``+8```_W((``6@``#_<@@`!>```/]R"``&(```_W( +M(``R@``#_9E```,AW``P@``#PB'<`%#-@2%MS<$A;L@B``"```/]4=P`('V= +M@!K8```CT8``)-A``"?$*``LFH#__\@@`"Z```/]Q!P`,,`R``1]G8`!%9@` +M`LV!)<+,,27#E4```\R```O,,27#Q"$``95``"3$)0`!4F0`('XF`!J```/] +M,:P(`,0T`!"6P``#S````8```_`YK`I\/;`*=YK```27```#S````8```_`Y +MK`K&@```@``$,H``!#R```1*@``$%8``!"?$-``0S(``"\X9``"50``$ +M!9@``58@`"#.&0``E\#[\L`Z``3,.2%`Q#D``<]``!!\0(`!B````#&L"`#$ +M-``0EL```\P```&```0(.:P*?#VP"G?$-``0FL``!)<```/,```!@``$"#FL +M"MP]L`K9FL```Y<```+,```!@``$"%'<`"!]G8`:V```'LP!(7[`*@`$!!0`!$%<``@H+`!`SL``(]A``"<)W``!F<#__\R` +M``O,*2%_Q"4``19L`!]!7``"FL#_^<0T`"R;0/__V```'WQ`@`&(````Q`P` +M$S#0``&5```#S(``"]L!HJ3,0``.Q`P`$L00`!,PU```/1@``7U9P`K80``Q +MF<#_^MA``!/0```R?$"``8@```#`#@$`S````@`_`4`` +M0`.=`$$$60!"!'0`0P1\`$0"F`!%`AD`1@*C`$<"HP!(`J,`2@,3`%(#&@!3 +M`RT`5P,T`%\#60!@`SH`80-,`&@#9@!I`VH`<@-R`',#CP!V`VX`=P-N`'H$ +MM0!]!,X`?@32`(4$UP"&!-P`B@4-`(L%#0`/!1X`#P4>``\%'@`/!1X`#P4> +M``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X` +M#P4>``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/ +:!1X`#P4>``\%'@`/!1X`#P4>``\%'@`/!1X` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_pfp.bin.uu new file mode 100644 index 00000000000..4d84cdf5bcb --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TAHITI_pfp.bin.uu @@ -0,0 +1,194 @@ +begin 644 TAHITI_pfp.bin +M?$"``8@```#,@```U$```'Q`@`&(````S(```,S```#40```?$"``8@````D +M3``/,.@``B20``*:@``,?$%``5!8`"!]E<`:F,```]'``!F`````F0```]'` +M`!J`````T<``&X````#$(``5QB0`"I9``6-\00`!?$%``S,.A^LT#H?G-0Z*=S4`` +M`,Q```!\0(`!B````'Q#0`$ +MS,.A^LT#H?G-0Z*=S4```,Q```!\0(`!B````'Q`P`$DT``!S,.BG]A``!>5 +M```"V(``%\R```#,P```?$"``8@```!\0,`!S(```,S#HJ+,P```?$"``8@` +M``!\0,`!%-0`'\R```!\00`!E4```LS``!\5&``?S,```,T```"5@``"S0`` +M(,P``'^```.*(`@`?B"(!^C$(``5'*@`$,Z@``1\00`!4%0`('Q!@`$&)``! +MSD``%16<`!A]%0`:S>``"T`:?65`$558`"#,```AS78``,VV``#$(``3F@#__WQ`@`&(````Q"`` +M)'Q`P`%\00`!S.`#_F\``?Y````#80``>Q#P`'I?` +M`'N0````C``##<0@`!5\0,`!P#;_`,00`!;`,#__?/5`"7U1@`E]@8`=?/.` +M"9F```;?@P``SZ``#XP``Q'40`!_@````(P``Q%\0(`!B````'Q`P`$4W``( +ME<``&23<`!!\00`!4%0`()G```/%'0``@``#,WT5`!K%'@``?$(``7Q"0`%\ +M08`!?>7`"7WB@`]!K``"FH#\QP;L``,*[``!FL#__R3<`!"9P``#Q1T``(`` +M`S;%'@``@``#-LR```#,P```U$```'Q`@`&(````Q!P`!,W```#,````S(`` +M`-1```!\0(`!B````'Q`P`$DT``&,1``!L04``^9```(S```$L0D`'Z60``X +MF4``!,0<``3-P```S````,R```#,P```U$```'Q`@`&(````?$#``7Q!``$5 +M&``?S0``(5$4`""9@``#U$T``(````!]34`:&1P`,=16``"5P/R5Q"``$YH` +M__]\0(`!B````'Q`P`%\00`!%-0`'C%8``(DW`#_E4``!)F`_(K-'`,`@``` +M`,R```#,P```S0```'Q`@`&(````Q"``)'Q`P`'$TP,`S(```,S```#,```A +MS2$A07Q`@`&(````U$``?WQ`@`&(````Q"0`?I9```-\0(`!B````(```XX` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````P-(``4!7P`&`.P`!P#S``@!`0`)`0@`$`.'`!$`"P`2`"<`$P`K`!8` +M+@`D`#<`)0!Q`"8!&0`7`8$`(@+H`",#%0`G`3,`'P&S`"`!XP`H`5(`*@%" +M`"P`4``O`4P`,0.'`#(!>0`S`X<`-`-/`#4!(``X`)(`-P&/`#P#*``_`6$` +M0`)5`$$"F`!"`KP`0P+$`$0"U`!*`MX`50-+`%\`WP!@`+L`80#6`&D`[P!S +M`/8`=@$$`'?4U`"1%4`!A^EH`*P`J)0'W)``K%%0``%50`$'U!0!Y]34`)$50`&'Z6 +M@`I^@H`>Q!<``GZ6@`F0````Q!<`8`E4``=^T0`0?14`!'R10`^0````P!@` +M`!,P``B0",``)#?!2`"A%4`!!^EH`*C``#`W[.P`'`'HE`C``"0WP4 +M@`H15``8?I:`"HP``P-^SL`!SH,`6I````"6P`"I*NP``<[``#"60`"BQ"`` +M')8``*#,```PD````"@,``&,``(,*#@``8P``EDH.```C``"+9>``?_`.#$! +MQ[D``!>X`!`GK`?_EL```\`D``",``#^S8```L00``.5`/__S```$,`X``&0 +M````P!PPT,V=``#`'##.Q=T``'W5P`)]T<`/E<``-WT"P`J0````Q"L``HP` +M`N7`#H``?X^`"L`.@`!_3T`**#P`H!/\`!`K_`#_C``"7,`<,07%[0``$NP` +M&";L`/_`)```C```_LP``!*0````D````"?0`/\Q$`#_F0#__<`4,1?/U0`` +MD````"@X``",``)9*#@``8P``BTH#```C``"#,P``"V```0RP`J,`,`,)%!\ +MR,`*Q-$``,`*C0#`#"10?,C`"L35``!]%0`*)1`#@'T!0`V0````EL#_TG[! +M``K`'##0S9T``,`<,,[%U0``%2P`!);`_\.,``#^E@#_P9````#,```MS8`` +M#LP#``#`,#!)QPD``,`R`!!\L<`)E<`"T,`P,0''"0``))P``97``NT4K``( +M)NP`_\`D``'`(```C``!4)8``8G-@P``@``$,HP``'O,```.Q`@`-\0(`#.4 +M@``#S8``#HP``DC$"``JE(```\V```Z,``,8Q`@`*Y2```+-@``.Q`@`*)2` +M__+-@``.C``!N(P``ZV```%PQ`@`')2``J[-@P``@``$2":H`/\4Y``$$F0` +M""3<``]^7,`*S,``(\Z```R```0RQ`@`$)2`__/$"``1E(#_\<0H``"6@`$2 +MS8``#B@(``'$#``@S(```#*(`;N4@`!NS`,``(```5O$'P!@"=P`!R@@`!": +M``'W*!0`0(```ZS$'``SE<#_7B$",``+7 +M%J@`"":,`/]\U,`+P!0``<`*B$",``*3$9@`"'Y:0`K`'HD`C``"UQ:H``@F +MC`#_?-3`"\`4``'`"HD`C``"DQ&8`!!^6D`*P!Z)0(P``M<6J``()HP`_WS4 +MP`O`%``!P`J)0(P``I,1F``8?EI`"I````#`&"35?8F`"L69```H'```*!`` +M`,`@``B50``,),@``92```5\D(`$?8F`"@E4``$%W``!"B```13,``$%$``! +MF@#_]B68`/^0````Q"<``)9``$K,`P``@``!6\`8)-5]B8`*Q9D``'T!`!Y] +MD,`)*!P``"@D``#`(``(E4``#"3(``&4@``%?*2`!'V)@`L)5``!!=P``0H@ +M``$4S``!!F0``9H`__8EF`#_D````,`()-?`#H@`?(S`"L35```E5`#_P`Z( +M0'R,P`K$T0``)1``_Q$0``A]44`*P`Z)`'R,P`K$T0``)1``_Q$0`!!]44`* +MP`Z)0'R,P`K$T0``)1``_Q$0`!A]44`*D````"G((F_$B0``*C``#M\07`"690``'C``!1)5` +M``7`#"35?@$`"LT#`!Z,``.WS`,`#I````"7@``$P!`Q&<4=``"9P/_^ET`` +M!,`0,1K%'0``F<#__I````"```-]Q`@`#Y2`___$*P`"C``"Y<`.@`!_CX`* +MP`Z``']/0`HH/`"0$_P`$"O\`/^,``)Q`\`87R-``R9```& +MQ!$Q"WS0P`K,PP`>P!@``(` +M"LU)``"0````!!@``/1=KM,\,<:T\B```````5P,`!0```!0```%BG>0>8>H(\]]+MR/TG;T>2D<,J`#U +MNZ7DB+4]VXH.CGAI44T5```!CWQ(XCF?ZF;JP7SFC;DQAT2V+8SD6[\PG>JP +M;=8$C>&U![WV%@```3,TA:R18(0257X/K?B!TQ0[(V.M`:4-3]975?2,9UW3 +MBE'N7!<```':QR\H[&(X_$#*"(X8`K`_L(-/G*GF\L($8M`SHOZX[6;/T$T8 +M```!R.O__)`]W@6`-OY2&K<]?P$K@CIA;.*8(-92CGE(:O&B:3%=```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````,5)$-5)(.5),/5)`#0``-S_`&'0 +M_P!A$``!82\`!`"Q@`1@``````````````````````````````````````#% +M"1#5"2#E"3#U"0`U```````````````````````````````````````````` +M````````````````````````R4D`T0D0V4D@Z4DP^4E`@$E0D$E@H$EPL$D` +M-````````````````````````````````````````````````,D)$-D)(.D) +M<-$),/D)0(<)4)<)8*<)<+<)`#4````````````````````````````````` +M``````````````#-20#1"1#=22#M23#]24!`25!026!@27!P28"`29"02:"@ +M2;"P20`T````````````````````````````````S0D0W0D@[0FPT0DP_0E` +M2PE06PE@:PEP>PF`BPF0FPF@JPFPNPD`-0`````````````````````````` +M````#```Y!,``!,``1,``A,``Q,`!!,`!1,0(```21,`2!,0(```:!,`@!,` +M@1,`D!,`D1,`H!,`H1,P(```L1,`LA,`LQ,`PA,`PQ,`T1,`TA,`TQ,`Z!,` +MZA,`\!,`\1,`\A,,\B#F$Q`@`$P"#`-V@@[2

G!^=$@``,P`0,IX3GQ(`(#,`,#(F$0,F$1(.8#,+$#(F$2,F$3 +M;`,P(A`K(B#F$Q+1`1+!@!`@`!`1(!4%`!+!@#(A$2(A$#`#$R`"$SCQ*.$P +M`1,@`!,B(1(R(1,@YA,PL1,0(`#XT>C!V+'(H;B1J(&8<8AA>%%H05@Q2"$X +M$2@!$M$!$L&``#`````V`0$@80!`X@-0Y`,A+@!01!`@1!!61``@;P`=\##T +M0!SR,#+``!-`02\`0$.PG&,,$@`BH2#C$R(D`&(D`19"_-`"`(;O_P`@\`,@ +M\!,H!&@4%@+[T`(`ANK_`#8A`##J`RHS,/`3'?`````V(0#VP@E1+P!0(K`Y +M`DD2'?`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````8P```````` +M````````````````````````````````AE[_```````````````````````` +M```````````````0-````````````````````````````````````````!+! +M@"D!(.@#9D("1E#_*`$2T0$2P8`&2?\`````````AD;_`#8A`$!O`##D`R`S +M(##D$T#F$Q`@`!WP`#8A`$!O`##D`R`S("`S,##D$T#F$Q`@`!WP```````` +M`````(8V_P`@TA,A,``Y$DDB63)I0GE2B6*9%)H0E@R2"(X$B#2`Q`R`````#8A`"#J`QWP-B$` +M(/`3`"``'?``-B$`(/(3`"``'?``-B$`(/`#'?`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````5P-@````````````````7K(`8%ZR`L@!@7K(`8%ZR`&!>L@!@7K(` +M8,JR`&!>L@!@RK(`8%ZR`&!>L@!@7K(`8%ZR`&!>L@!@7K(`8*S%`&#UQ@!@ +MK,4`8*S%`&"LQ0!@]<8`8%?'`&"LQ0!@K,4`8%?'`&"LQ0!@K,4`8*S%`&#" +MQP!@K,<`8*S%`&"LQ0!@K,4`8*S%`&"LQ0!@S\8`8````````````````.SP +M`&"[\`!@8_(`8"_R`&`/\@!@E_$`8$3Q`&``````"@X4&`X4&!L4&!L>&!L> +M(@8-%!P-%!P@%!P@)1P@)2H``00(!0(#!@D,#0H'"PX/``$($`D"`PH1&"`9 +M$@L$!0P3&B$H,"DB&Q0-!@<.%1PC*C$X.3(K)!T6#Q<>)2PS.CLT+28?)RXU +M/#TV+S<^/Y(B`6"2(@%@JB,!8(XC`6".(P%@Z1\!8.D?`6#I'P%@Z1\!8.D? +M`6#I'P%@CB,!8'(C`6!6(P%@Z1\!8.D?`6#I'P%@Z1\!8.D?`6#I'P%@Z1\! +M8%8C`6`Z(P%@'B,!8.D?`6#I'P%@Z1\!8.D?`6#I'P%@Z1\!8.D?`6`"(P%@ +M`B,!8.8B`6#I'P%@Z1\!8.D?`6#I'P%@Z1\!8.D?`6#I'P%@RB(!8*XB`6`` +M``````$"`P0%!@<("0H+#`T.#Q`1$A,4%187&!D:&QP='1X?("`A(B(C(R0D +M)24E)B8F)R`P<%"PH-#`X/)R\K!RT+ +M+@T0#@,&!0D*'PPC$R45*AHL'"$C(B4D*B@L)P$K`BT$+@@1$1(2%!08&!,& +M%0D:%AP9%R`;(1TB'B06*!DF)BDI`@$#`P0'!0\('P("`P8$#@4>!SX````` +M````````````0(`!08$"0H(#0X,$1(0%184&1H8'1X<(2(@)28D*2HH+2XL, +M3(P-38T.3HX/3X\04)`149$24I(34Y,45)0559465I875Y<86)@969D:6IH; +M6YL<7)P=79T>7IX?7Y\@8*`A8:$B8J(C8Z,D9*0E9:4F9J8G9Z@%6J0,`S9IG,*](!87&!H<'B`C%Q@:'!X@(R89&AP>(",F*1L< +M'B`C)BDM$!$2$Q05%A<1$A,4%187&!(3%!46%Q@9$Q05%A<8&AL4%187&1H; +M'!46%Q@:&QP>%A<8&AL<'A\7&!D;'!X?(04````````````````````````` +M`````(````!@````"`````8````!````L````)`````+````"0````(```!@ +M`0``(`$``!8````2`````P```,`"``!``@``6````!(````$````@`4``(`$ +M``!@`0``$@````4`````````````````````````!0`````````````````` +M```````````````````````!`````0````$````!`````0````$````!```` +M`0````$````!`````0````(````"````C',"8*%S`F#W=@)@[G8"8.5V`F#< +M=@)@TW8"8``````#`````P````,````#````!`````0````$````!`````4` +M`````````````````````````0````(````#``````````$````"`````P`` +M````````````````````````````!`````@````,````$````!0````8```` +M'````"`````D````*````"P````P````-````#@````\````______[___\! +M`````@`````````````````````````!`````0````$````!`````@````(` +M```"`````@````,````#`````P````,````$````!`````0````$````!0`` +M```````````````````````!`````@````,``````````0````(````#```` +M``````$````"`````P`````````!`````@````,``````````0````(````# +M`````````````````````````#P````X````-````#`````L````*````"0` +M```@````'````!@````4````$`````P````(````!`````````!SC0)@P8T" +M8+2-`F"GC0)@FHT"8(V-`F"`C0)@``````,````#`````P````,````$```` +M!`````0````$````!0`````````````````````````!`````@````,````` +M`````0````(````#`````````````````````````/_____^____`0````(` +M````````!`````@````,````$````!0````8````'````"`````D````*``` +M`"P````P````-````#@````\``````````````````````````$````!```` +M`0````$````"`````@````(````"`````P````,````#`````P````0````$ +M````!`````0````%``````````````````````````$````"`````P`````` +M```!`````@````,``````````0````(````#``````````$````"`````P`` +M```````!`````@````,`````````````````````````/````#@````T```` +M,````"P````H````)````"`````<````&````!0````0````#`````@````$ +M``````````';`F`WVP)@+ML"8"7;`F``0`` +M'@$``!\!```?`0``'P$``!\!```?`0``'P$``!\!```?`0``2@```$L```!, +M````30```$X```!/````4````%$```!2````4P```%0```!5````5@```%<` +M``!8````60```%H```!;````7````%T```!>````7P```&````!A````8@`` +M`&,```!D````90```&8```!G````:````&D```!J````:P```&P```!M```` +M;@```&\```!P````<0```'(```!S````=````'4```!V````=P```'@```!Y +M````>@```'L```!\````?0```'X```!_````@````($```""````@P```(0` +M``"%````A@```(<```"(````B0```(H```"+````C````(T```".````CP`` +M`)````"1````D@```),```"4````E0```)8```"7````F````)D```":```` +MFP```)P```"=````G@```)\```"@````H0```*(```"C````I````*4```"F +M````IP```*@```"I````J@```*L```"L````K0```*X```"O````L````+$` +M``"R````LP```+0```"U````M@```+<```"X````N0```+H```"[````O``` +M`+T```"^````OP```,````#!````P@```,,```#$````Q````,4```#%```` +MQ@```,8```#'````R````,D```#*````RP```,P```#-````S@```,\```#0 +M````T0```-(```#3````U````-4```#6````UP```-@```#9````V@```-L` +M``#<````W0```-X```#?````X````.$```#B````XP```.0```#E````Y@`` +M`.<```#H````Z0```.D```#J````Z@```.L```#K````[````.P```#M```` +M[0```.X```#N````[P```.\```#P````\0```/(```#S````]````/0```#U +M````]0```/8```#W````^````/@```#_``````$```$!```"`0```P$```,! +M```$`0``!0$```8!```'`0``"0$```H!```+`0``"P$```P!```,`0``#0$` +M``T!```.`0``#@$```\!```/`0``$`$``!`!```1`0``$0$``!0!```5`0`` +M%@$``!`0``7P$``&`!``!A`0``8@$``&,!``!D`0``90$``&8! +M``!G`0``:`$``&D!``!J`0``:@$``&L!``!K`0``;`$``&P!``!M`0``;0$` +M`&X!``!O`0``<`$``'$!``!R`0``0$``'H!``!Z`0``>P$``'L!``!^`0``?P$``((!``""`0``@P$``(0!``"% +M`0``A0$``(4!``"%`0``A0$``(4!``"%`0``A0$``(8!``"&`0``A@$``(8! +M``"&`0``A@$``(8!``"&`0``AP$``(`(``'D"``!Z`@`` +M>P(``'P"``!]`@``?@(``'\"``"``@``@0(``(("``"#`@``A`(``(4"``"& +M`@``AP(``(@"``")`@``B@(``(L"``",`@``C0(``(X"``"/`@``D`(``)$" +M``"2`@``DP(``)0"``"5`@``E@(``)<"``"8`@``F0(``)H"``";`@``G`(` +M`)T"``">`@``GP(``*`"``"A`@``H@(``*,"``"D`@``I0(``*8"``"G`@`` +MJ`(``*D"``"J`@``JP(``*P"``"M`@``K@(``*\"``"P`@``L0(``+("``"S +M`@``M`(``+4"``"V`@``MP(``+@"``"Y`@``N@(``+L"``"[`@``O`(``+P" +M``"]`@``O0(``+X"``"^`@``OP(``+\"``#``@``P`(``,$"``#!`@``P@(` +M`,("``##`@``Q`(``,4"``#&`@``QP(``,@"``#)`@``R@(``,L"``#,`@`` +MS0(``,X"``#/`@``T`(``-$"``#2`@``TP(``-0"``#5`@``U@(``-<"``#8 +M`@``V0(``-H"``#;`@``W`(``-T"``#>`@``WP(``.`"``#A`@``X@(``.," +M``#D`@``Y0(``.8"``#G`@``Z`(``.D"``#J`@``ZP(``.P"``#M`@``[@(` +M`.\"``#O`@``\`(``/`"``#Q`@``\@(``/,"``#T`@``]0(``/8"``#W`@`` +M^`(``/D"``#Z`@``^P(``/P"``#]`@``_@(``/\"``#_`@````,```$#```" +M`P```P,```0#```%`P``!@,```<#```*`P``"@,```H#```*`P``"P,```L# +M```+`P``"P,```P#```,`P``#`,```P#```,`P``#`,```P#```,`P``0``! +M``\#```0`P``$`,``!$#``!"``(`%@,``!8#```7`P``%P,``!<#```7`P`` +M1@`"`$H``@!.``$`(0,``"(#``!0``$`4@`!`"<#```H`P``*`,``"D#```J +M`P``5``#`%P``P!D``,`;``"`'```@!)`P``2@,``'0``0!-`P``30,``$T# +M``!-`P``30,``$T#``!-`P``30,``$T#``!-`P``30,``$T#``!-`P``30,` +M`$T#``!-`P``#0,```X#```2`P``$P,``!0#```5`P``&`,``!D#```:`P`` +M&P,``!P#```=`P``'@,``!X#```?`P``(`,``",#```D`P``)0,``"8#```K +M`P``+`,``"T#```N`P``+P,``#`#```Q`P``,@,``#,#```T`P``-0,``#8# +M```W`P``.`,``#D#```Z`P``.P,``#P#```]`P``/@,``#\#``!``P``00,` +M`$$#``!"`P``0P,``$0#``!%`P``1@,``$<#``!(`P``2`,``$L#``!,`P`` +M3@,``$```0!1`P``40,``%(#``!"``0`60,``%(``0!<`P``70,``%X#``!> +M`P``7P,``%\#``!?`P``7P,``&`#``!@`P``8`,``&`#``!@`P``8`,``&`# +M``!@`P``8`,``&`#``!@`P``8`,``&`#``!@`P``8`,``&`#``!A`P``80,` +M`%0`!`!D``0`>P,``'L#``![`P``>P,``'0`!`"$``0`E``$`*0`!`"T``0` +MQ``#`,P``P#4``,`W``"`.```@#D``(`Z``"`.P``0#R`P``\P,``/0#``#U +M`P``]0,``/4#``#U`P``]0,``/4#``#U`P``]0,``$\#``!0`P``4P,``%,# +M``!4`P``50,``%8#``!6`P``5@,``%8#``!7`P``5P,``%<#``!7`P``6`,` +M`%@#``!8`P``6`,``%H#``!;`P``8@,``&(#``!B`P``8@,``&(#``!B`P`` +M8@,``&(#``!C`P``9`,``&4#``!F`P``9P,``&@#``!I`P``:@,``&L#``!L +M`P``;0,``&X#``!O`P``<`,``'$#``!R`P``0,``'H#``!\`P``?0,``'X#``!_`P``@`,``($#``""`P``@P,` +M`(0#``"%`P``A@,``(<#``"(`P``B0,``(H#``"+`P``C`,``(T#``".`P`` +MCP,``)`#``"1`P``D@,``),#``"4`P``E0,``)8#``"7`P``F`,``)D#``": +M`P``FP,``)P#``"=`P``G@,``)\#``"@`P``H0,``*(#``"C`P``I`,``*4# +M``"F`P``IP,``*@#``"I`P``J@,``*L#``"L`P``K0,``*X#``"O`P``L`,` +M`+$#``"R`P``LP,``+0#``"U`P``M@,``+<#``"X`P``N0,``+H#``"[`P`` +MO`,``+T#``"^`P``OP,``,`#``#!`P``P@,``,,#``#$`P``Q0,``,8#``#' +M`P``R`,``,@#``#)`P``R0,``,H#``#+`P``S`,``,T#``#.`P``SP,``-`# +M``#1`P``T@,``-,#``#4`P``U0,``-8#``#7`P``V`,``-D#``#:`P``VP,` +M`-P#``#=`P``W@,``-\#``#@`P``X`,``.$#``#B`P``XP,``.0#``#E`P`` +MY@,``.<#``#H`P``Z0,``.H#``#K`P``[`,``.T#``#N`P``[P,``.\#``#P +M`P``\0,``/@#``!```(`_`,``/T#``#^`P``_@,``/X#``#^`P``_P,````$ +M``!$``(`2``"`$P``0`*!```"P0```P$```-!```#00```T$```-!```#@0` +M``X$```.!```#@0```\$```/!```#P0```\$```0!```$`0``!`$```0!``` +M3@`$`%X``0`8!```&00``!H$```:!```&P0``!L$``!@``,`(00``"($```B +M!```:``#`'```P!X``,`@``"`#T$```^!```/P0``#\$``!`!```000``(0` +M`@"(``$`1P0``$<$``!'!```1P0``$@$``!(!```2`0``$@$``#Y`P``^0,` +M`/H#``#[`P```00```($```#!```!`0```4$```&!```!P0```<$```(!``` +M"00``!$$```1!```$00``!$$```2!```$P0``!0$```4!```%00``!4$```5 +M!```%00``!4$```5!```%00``!4$```6!```%P0``!P$```!0#M`@4`[0,%``P#!0`- +M\P4`[1$%`/D0!0#V!P4`!@@%`/KR!0`&"P4`!@X%``?K!0``Y@4`_A`%``?S +M!0#^$04`]@D%``#J!0#Z]P4`_AH%``_Q!0`/]04`#_<%`/,"!0`/_@4`_AP% +M`/_@!0`##`4`Z`(%`/?Z!0`/!04`#PX%`/L+!0`#$04`#QL%`/_D!0`0`@4` +M`QL%`/,%!0`$]@4`$?D%`!'\!0`!#@4`_^8%``<(!0#[&P4`!PH%`!$$!0`1 +M'04`$OP%`!+^!0`2_P4`!PL%`/_J!0`3]@4`$_<%``L%``C[!0`5_04`Z>4%``$?!0#_\@4`%0D% +M`!;_!0`6`@4`%@8%`!?A!0`7Y04``NT%`._\!0`8_P4`^?$%`!@&!0#U!P4` +M]0D%``@$!0`(!04`^?8%``@'!0`:`04`!`L%`.4+!0`)[P4`"?$%`.P1!0`< +M_@4`"?4%``GV!0`%]`4`]NH%`!WQ!0#R^04`_18%`/T9!0#^XP4`'0(%`/[H +M!0`=!`4`'OD%`![_!0#^[@4`_N\%`!_S!0#R_04`[?D%`/[R!0`-_@0`X1\$ +M``+P!`#_"@0`]OP$``/M!`#O`00`#@$$``X#!``#\P0`_PX$`/P+!`#]\00` +M_?,$`/<$!``)!P0`^_@$`.[_!``5``0`%0$$`/OZ!`#X_`0``!X$`!D!!``` +M'P0`\0$$``H'!``%\P0`_1$$``'Q!`#A_P0`^0L$``#M!```[P0`'_T$`/KY +M!``(`P0`]P(#`/OY`P#V`0,`^/T#`/;_`P`'!P,`"P,#`/L$`P`%^`,`Y@`# +M``K^`P#X`0(`"/\"`/P'`@``X0(```D!``D`!@`$_P4`_``$``/_`P#]_P,` +M!@`%`/?_`0#[_@$``!L"``#V`@``]0$`_@H%`.[R!0#X$P4`_A\%``H$!0#X%P4``?(%`/GE!0`*%P4`"^D% +M`.[]!0`+\04`"_4%`.[^!0`+^P4`Y^$%``0;!0`%YP4`!>L%``7L!0`%[P4` +MY^4%`.X*!0#Y^`4`"PD%``L+!0`,YP4`[_L%``7V!0#G^04`Y_\%`./^!0#A +M!04`Z/8%`.\'!0#O%04`Z/T%``P$!0`,!04`#!`%``W@!0`-Y04`#>T%``WQ +M!0#H_P4`Z``%``WZ!0#U#@4`#?P%`/P,!0#\#04`_`X%`/45!0#\$04`_!,% +M`/;C!0`%"04`#N,%``[V!0`%"@4`Z`$%`/WE!0`%#04`_><%`/;V!0`."`4` +M!14%`/;X!0#][@4`#_D%``_[!0`&Z@4`!NP%`/`"!0`&\`4`!O$%``$5!0`& +M]`4`]OH%``\'!0`/#04`_?(%`/D-!0#P`P4`X`$%`!#_!0#A$04``N0%`!`' +M!0`0"@4``NL%`/D3!0#ZY04`^NT%`!'Z!0`1^P4`^O$%`.$4!0`1_@4`Y.`% +M`/KV!0#D[`4`$0(%`.$>!0#I!`4`$08%`!$)!0`1#P4`ZOX%`!$?!0#Q!@4` +M!@D%`/$+!0#Q&P4`$@$%``8-!0`2!04`$@8%`/8(!0`&#P4`$_@%``80!0`& +M$04`$_X%``?A!0`'Z@4`\O8%`/81!0`'[P4`$P<%`/8;!0`4_P4`%``%`!0! +M!0`'\@4`%>T%`!7O!0#J_P4`]_4%`/+[!0#]#`4`Z@H%`!4'!0#]#@4`%O$% +M`.OZ!0`6``4`Z_X%`.O_!0`7X`4`X?X%`/("!0`7Z04`%^P%`!?M!0`7^04` +M%_\%`!<`!0#]%P4``@L%`/(#!0#]'04`&`$%`!@#!0`"#@4`&?D%``(/!0`" +M$`4`_1X%`/T?!0`9!@4`&1T%``/A!0`#X@4``^4%``/G!0`#Z04`!PX%``/J +M!0`;`@4`&P,%`/($!0`;%P4`!Q,%`/[G!0#R"`4`"/<%`!P"!0`4% +M`/[M!0#R"@4`'?(%`!WY!0#S^P4`\_P%``GK!`#Q!00`^@H$`/0'!``-!00` +M#O\$```1!``%]00`]OL$``_]!`#]#P0`_Q4$`/L(!`#]$P0`_O`$`/7Z!``! +MX00``P@$`/+^!`#Y"00``0P$`!("!``3^00`"OL$`.+_!`#O`P0`$P,$`!7_ +M!``![P0`^1$$`/WA!``7`P0`!0@$``;E!``!&@0`!O4$`!O]!``&]@0``1L$ +M``<-!`#M_P0``.D$``CZ!``=Z00`'?T$``#K!`#I``0`#/X$`./C!`#_[00` +M_?0$`/GR!`#X`P,`$``#`/```P#\^`,`$0$#`/;^`P`""`,`_P\#``8'`P`' +M!0,`#``#`.L!`P`#^`,`_O<#``$-`P`!#P,`!/D"`/\;`@`(`@(`^?L"`/O[ +M`@`&^@(`_P@"``0%`@#\^P(``/\$`/__!0`"`P0```4$``("`P#X_P$`!P(! +M``(%!@#[`04`_`,&`/\=`@`$^@(`^0<"``T!`@#Y_P4``P($`./_`@`"]@(` +M!@4"``?Y`@`(_@(`!OD"`.$``0#Y_@$`!P,!`/X&!@`%_08```@!`/S\`0#] +M!@$``.4!``4"!@#_^P4``_L&`/O]!@#W^P,`_/<#``$*`P`.``,`[P`#`.T! +M`P#X!`,`"04#`/@%`P`"\0,``O(#`/[V`P#Z"`,`^`8#`.X``P`<_P,`]0,# +M`/WX`P`'\0,`]_D#``/Q`P`%]P,`_O@"```=`@#S_P(`^`("`/GY`@#Z!@(` +M#0`"``8#`0`$_08`XP`&`/K]`0`$!`$`_O\"`!L`!@#\!`$`'P`!`/H`!0`& +M`@8`'P$#`/_T!`#[ZP0`]``"`/C^`@`!XP(`!0,&`/P&`0`'_@$``.,&`/_Z +M!@`'_P4``_T$`/_^`@``!@4`]P$!`/?C!`#I_00`^0@$`.G_!`#]%00`]/X$ +M`/[Q!`#^]`0`"@4$`/+_!`#\"@0`^0\$`/P/!`#\%@0`]08$`/WI!``+`@0` +M_>T$``L%!`#Z]00`#/D$``S[!`#U"P0`!@H$``/^!`#U#00`^`@$``WY!``- +M^P0``PX$``?V!`#V^00``Q4$``3T!``"X@0``NX$``T'!``"[P0`_?8$`/\, +M!``.`@0`^?4$``X&!`#P`00`\?L$`/\0!`#T`@0``!0$``\#!``/#P0`#Q$$ +M```6!``1X@0`$>T$`!'W!`#_%`0`X?T$`/L-!`#\]@0`!Q$$``<6!`#U]00` +M!`@$`/<*!``3_P0`XOX$``C]!``3`@0``.`$`!7Y!`#X]P0`_A,$`/CX!`#^ +M&P0`]?P$``@&!``9_00`&?\$`/_B!``)[00`&O\$``#H!`#L_P0`Y`$$``#L +M!``"#00`&PD$`/_G!```[@0`[?X$`.GY!``#\@0`^@L$``/T!``%"P0`'0,$ +M``4,!``?X00`^A$$`/T*!``)"@0`#0(#``$3`P`""@,`#_\#``D$`P#V!`,` +M"OT#``/U`P`#]@,`]P4#```,`P`#"P,`"_D#```/`P#G`0,`_PT#``G[`P#T +M_P,`_QH#`/#_`P#M``,`'_\#`/D&`P#^"P,``1T"`/\+`@`)_0(``O<"``?\ +M`@`/``(`"/P"`!H``@`;_P(`"0("``'E`@#C`0(`\0`"`!T!`@`*`0(`]?\! +M`/H#`0`#^@$`_00&`/K_!@`!!@8`_OX#`/\`!``!_P4`!?X&`/_W`0#^"@(` +M^@4"``'Z!@#[`P8`_P0$`/L"!@`#!08`_?<"``0&`@`=_P(``0@"``7Z`@`> +M``(``P8!`!D``0#_"0$``OH&``+Y!@`(``8``P,$`/T"!```^00`_?X$`/SZ +M`@`&\@0`]PD$``#T`P#]_`$`_?D!`/P%`0`*``8``0<&``#Z!0#_^04`_@@! +M``,/`P#^#0,`_A8#`/_A`P``]P8``?D%``KZ`P`/`@,`!P8#``;N`P`(]@,` +M"/@#`!,!`P`7`@,`&``#`/(``P#U!0,`!_4#``?W`P`!$0,`\0,#``GW`P#W +M_`,`^`<#``L'`P#Y]P,`_Q<#`/0!`P#Y!0(`!@8"`/D$`@#[!0$`_04&`.0` +M!@`'`04`Y0`&`/S]!@`&^`(`\?T"``,'`0#B``$`!@0!`/[]!`#]`P0```(& +M```!!`````$````````````````````````````````````````````````` +M`````````````````````````````````````$``!@!-````R``&`"X!!@"> +M````G@```(X!!@#N`08`,@(&`)("!@#L`@8`1`,&`&X!``!N`0``;@$``&X! +M``"F`P8`&@0&`.L!``#K`0``[`$``.P!``#L`0``[`$``'P$!@#L!`8`7@4& +M`,8%!@#C`@``XP(``.,"``#C`@``)`8&`#0#``"D!@8`$`<&`*<#``"G`P`` +M?@<&`,X'!@`'!```!P0``#X(!@!^"`8`2P0``$L$``!+!```2P0``$```P!( +M``,`4``"`%0``@!8``$`6@`#`!X````>````8@`!`"$````B````(@```",` +M```C````(P```",````D````)````"0````D````)````"0````D````)``` +M`"0````D````)````"0````D````)````"0````D````9``"`&@``@!L``$` +M+P```#`````P````,````#`````Q````,@```#,````T````-0```#4````U +M````-0```&X``P!V``$`/````#T````^````/@```'@``P"```,`3````$P` +M``!,````3````$P```!,````3````$P````!`````@````,````$````!0`` +M``8````'````"`````D````*````"P````P````-````#@````\````/```` +M$````!$````2````$P```!0````5````%@```!<````8````&0```!H````: +M````&@```!H````;````&P```!P````=````'P```"`````E````)@```"<` +M```H````*0```"H````K````+````"T````N````-@```#8````W````.``` +M`#D````Y````.0```#D````Z````.P```#\````_````/P```#\```!````` +M00```$(```!#````1````$4```!&````1P```$@```!)````2@```$L```!. +M````3@```$X```!.````3@```$X```!.````3@```$\```!/````3P```$\` +M``!```,`2``#`%```P!8``(`7``"`&```0!P````<````'$```!Q````<@`` +M`&(``0!U````=0```'8```!D``$`>0```'D```!Y````>0```'H```!Z```` +M>@```'H```!Z````>@```'H```!Z````>@```'H```!Z````>@```'H```!Z +M````>@```'H```!Z````>@```'H```!Z````>@```'H```!Z````>@```'H` +M``!Z````>@```'H```!Z````>@```'H```!Z````4````%$```!2````4P`` +M`%0```!5````5@```%<```!8````60```%H```!;````7````%T```!>```` +M7P```&````!A````8@```&,```!D````9````&4```!E````9@```&<```!H +M````:0```&H```!K````;````&T```!N````;P```',```!T````=P```'@` +M``![````>P```'L```![````>P```'L```![````>P```'L```![````>P`` +M`'L```![````>P```'L```![````?````'P```!\````?````$```P""```` +M2``"`$P``@!0``(`5``!`%8``0"2````6``!`%H``0!<``$`7@`!`)L```"; +M````FP```)L```";````FP```)L```";````FP```)L```";````FP```)L` +M``";````FP```)L```"<````G````)P```"<````G````)P```"<````G``` +M`)T```"=````G0```)T```"=````G0```)T```"=````?0```'T```!^```` +M?P```(````"`````@0```($```"#````A````(4```"&````AP```(@```") +M````B@```(L```",````C0```(T```".````CP```)````"1````DP```)0` +M``"5````E@```)<```"8````F0```)H```!```(`H@```*,```!$``(`J``` +M`*@```"H````J````$@``@!,``(`4``"`+0```"U````M@```+<```"W```` +MN````+@```"X````N````+D```"Y````5``!`%8``0"^````OP```,````!8 +M``(`Q````,0```#%````7``"`,H```#*````R@```,H```#*````R@```,H` +M``#*````R@```,H```#*````R@```,H```#*````R@```,H```#*````R@`` +M`,H```#*````R@```,H```#*````R@```,H```#*````R@```,H```#*```` +MR@```,H```#*````GP```)\```"@````H0```*0```"E````I@```*<```"I +M````J@```*L```"L````K0```*X```"O````L````+$```"R````LP```+,` +M``"Z````NP```+P```"]````P0```,$```#"````PP```,8```#'````R``` +M`,D```#+````RP```,L```#+````RP```,L```#+````RP```,L```#+```` +MRP```,L```#+````RP```,L```#+````S````,P```#,````S````,P```#, +M````S````,P```#-````S0```,T```#-````0``"`-$```#2````T@```-,` +M``#3````TP```-,```#3````TP```-,```#3````TP```-,```#3````TP`` +M`-,```#3````TP```-,```#3````TP```-,```#3````TP```-,```#3```` +MTP```-,```#3````TP```-,```#3````TP```-,```#3````S@```,\```#0 +M````T````-0```#4````U````-0```#4````U````-0```#4````U````-0` +M``#4````U````-0```#4````U````-0```#5````U0```-4```#5````0``" +M`$0``0!&``$`2``!`$H``0#A````X@```.(```!,``(`4``"`%0``@!8``(` +M\@```/(```#R````\@```/(```#R````\@```/(```#R````\@```/(```#R +M````\@```/(```#R````\@```%P``0!>``$`]P```/@```#Y````^0```/D` +M``#Y````^@```/H```#Z````^@```/L```#[````^P```/L```#6````U@`` +M`-<```#8````V0```-H```#;````W````-T```#>````WP```.````#C```` +MXP```.0```#E````Y@```.<```#H````Z0```.H```#K````[````.T```#N +M````[P```/````#Q````\P```/0```#U````]@```/P```#\````_````/P` +M``#]````_0```$```@!$``$``P$``$8``@`'`0``!P$```@!```(`0``"`$` +M``@!```)`0``"0$```D!```)`0``"0$```D!```)`0``"0$```H!```*`0`` +M"@$```H!``!*``(`3@`"`%(``@!6``$`&0$``!D!```9`0``&0$``!D!```9 +M`0``&0$``!D!```9`0``&0$``!D!```9`0``&0$``!D!```9`0``&0$``!H! +M```:`0``&P$``%@``0`>`0``'@$``!X!```>`0``'P$``!\!```?`0``'P$` +M`"`!```@`0``(`$``"`!``#^````_P`````!`````0```0$```(!```$`0`` +M!`$```4!```&`0``"P$```P!```-`0``#@$```\!```0`0``$0$``!(!```3 +M`0``%`$``!4!```6`0``%P$``!@!```<`0``'0$``"$!```A`0``(0$``"$! +M```A`0``(0$``"$!```A`0``(0$``"$!```A`0``(0$``"$!```A`0``(0$` +M`"$!```B`0``(@$``"(!```B`0``(@$``"(!```B`0``(@$``"(!```B`0`` +M(@$``"(!```B`0``(@$``"(!```B`0``0``!`"4!```F`0``)P$``"@!```H +M`0``*`$``"@!``!"``(`1@`"`$H``@!.``(`4@`!`%0``0!6``$`/@$``#\! +M```_`0``/P$``#\!```_`0``/P$``#\!```_`0``/P$``#\!```_`0``/P$` +M`#\!```_`0``/P$``#\!```C`0``)`$``"D!```J`0``*P$``"P!```M`0`` +M+@$``"\!```P`0``,0$``#(!```S`0``-`$``#4!```V`0``-P$``#``$`8``!`&T!``!M`0``;0$``&T!``!M`0``;0$` +M`&T!``!M`0``0@$``$,!``!$`0``10$``$8!``!'`0``2`$``$D!``!*`0`` +M2P$``$T!``!.`0``3P$``%`!``!1`0``4@$``%,!``!4`0``50$``%8!``!7 +M`0``5P$``%@!``!9`0``6P$``%P!``!=`0``7@$``&(!``!C`0``:0$``&H! +M``!K`0``;`$``&\!``!P`0``<0$``'(!``!S`0```$``'D!``!Z`0``>P$``'P!``!]`0``?@$``'\!``"` +M`0``@0$``((!``"#`0``A`$``(4!``"&`0``AP$``(@!``")`0``C`$``(T! +M``".`0``CP$``)0!``"5`0``F0$``)D!``":`0``FP$``)\!``"@`0``H0$` +M`*(!``"D`0``I0$``*8!``"G`0``J`$``*D!``"J`0``JP$``*P!``"M`0`` +MK@$``*\!``"P`0``L0$``+(!``"S`0``M@$``+8!``"V`0``M@$``+``$`8``!`.4!``#F`0``YP$``.@!``#I`0``Z@$``.H! +M``#J`0``Z@$``+X!``"_`0``P0$``,(!``##`0``Q`$``,@!``#(`0``R0$` +M`,H!``#-`0``S@$``,\!``#0`0``T0$``-(!``#3`0``U`$``-4!``#6`0`` +MUP$``-@!``#9`0``V@$``-L!``#<`0``W0$``-X!``#?`0``X`$``.$!``#B +M`0``XP$``.0!``#M`0``[@$``$```0!"``$`\P$``/,!``#S`0``\P$``$0` +M`0!&``$`2``!`$H``0!,``$`_@$``/\!`````@```0(```$"```"`@```@(` +M``,"```#`@```P(```,"```$`@``!`(```0"```$`@``!`(```0"```$`@`` +M!`(```4"```%`@``!@(```8"```'`@``3@`"`%(``@!6``(`%`(``!0"```4 +M`@``%`(``!0"```4`@``%`(``!0"``!:``(`7@`"`&(``@!F``$`:``!`&H` +M`0!L``$`*0(``"H"```J`@``*P(``"P"```M`@``+0(``"X"``!N``$`[P$` +M`/`!``#Q`0``\@$``/0!``#U`0``]@$``/`@``'P(``"`"```A`@``(@(``","```D`@``)0(``"8"```G`@``*`(` +M`"\"```P`@``,0(``#$"```Q`@``,0(``$```0!"``$`-@(``#<"```X`@`` +M.`(``#D"```Z`@``1``"`$@``@!,``(`4``"`$L"``!+`@``2P(``$L"``!+ +M`@``2P(``$L"``!+`@``5``"`%@``@!<``(`8``!`&(``0!D``$`9@`!`&`" +M``!A`@``80(``&$"``!A`@``80(``&$"``!A`@``80(``&$"``!A`@``80(` +M`&$"``!A`@``80(``&$"``!A`@``8@(``&("``!B`@``8@(``&,"``!C`@`` +M8P(``&,"``!H``$`9@(``&<"``!H`@``:@`!`&P``0!N``$`<``!`#("```S +M`@``-`(``#4"```[`@``/`(``#T"```^`@``/P(``$`"``!!`@``0@(``$," +M``!$`@``10(``$8"``!'`@``2`(``$D"``!*`@``3`(``$T"``!.`@``3P(` +M`%`"``!1`@``4@(``%,"``!4`@``50(``%8"``!7`@``6`(``%D"``!:`@`` +M6P(``%P"``!=`@``7@(``%\"``!D`@``90(``&D"``!J`@``:P(``&P"``!M +M`@``;@(``&\"``!P`@``<0(``'("``!S`@```(``'@"``!Y`@``>0(``$```@!$``(`2``" +M`$P``@!0``(`5``!`%8``0!8``$`6@`!`)8"``"7`@``EP(``)@"``"8`@`` +MF`(``)@"``"9`@``F0(``)D"``"9`@``7``!`)P"``"=`@``7@`!`*`"``"@ +M`@``H`(``*`"``!@``$`8@`!`*4"``"E`@``I@(``*8"``"F`@``I@(``*8" +M``"F`@``I@(``*8"``"G`@``9``"`*L"``"L`@``K0(``*X"``"O`@``KP(` +M`'H"``![`@``?`(``'T"``!^`@``?P(``(`"``"!`@``@@(``(,"``"$`@`` +MA0(``(8"``"'`@``B`(``(D"``"*`@``BP(``(P"``"-`@``C@(``(\"``"0 +M`@``D0(``)("``"3`@``E`(``)4"``":`@``FP(``)X"``"?`@``H0(``*(" +M``"C`@``I`(``*@"``"H`@``J0(``*H"``"P`@``L`(``+`"``"P`@``L0(` +M`+$"``"Q`@``L0(``+("``!```(`1``"`$@``@!,``(`4``!`,4"``#&`@`` +MQP(``,<"``#'`@``QP(``,@"``#(`@``4@`"`,P"``#-`@``S0(``,X"``#. +M`@``SP(``%8``0#2`@``T@(``-,"``#3`@``TP(``-,"``#3`@``TP(``-," +M``#3`@``6``!`%H``0!<``$`V@(``-L"``#;`@``W`(``-P"``#=`@``W0(` +M`-T"``#=`@``W@(``-X"``#?`@``WP(``.`"``#@`@``X0(``.$"``#B`@`` +MX@(``.("``#B`@``LP(``+0"``"U`@``M@(``+<"``"X`@``N0(``+H"``"[ +M`@``O`(``+T"``"^`@``OP(``,`"``#!`@``P@(``,,"``#$`@``R0(``,D" +M``#*`@``RP(``-`"``#1`@``U`(``-4"``#6`@``UP(``-@"``#9`@``Y`(` +M`.0"``#E`@``Y0(``.8"``!```(`ZP(``.L"``!$``(`2``"`$P``@!0``(` +M5``"`%@``@!<``(`8``!``D#```)`P``"0,```D#```)`P``"0,```D#```) +M`P``"0,```D#```)`P``"0,```D#```)`P``"0,```D#``!B``$`9``!`&8` +M`0!H``$`:@`!`!0#```5`P``%@,``!<#```7`P``&`,``!D#```:`P``&@,` +M`!L#```;`P``;``"`'```0!R``$`=``!`'8``0!X``$`>@`!`'P``@`N`P`` +M+@,``"\#```P`P``,0,``#(#```S`P``,P,``.<"``#H`@``Z0(``.H"``#L +M`@``[0(``.X"``#O`@``\`(``/$"``#R`@``\P(``/0"``#U`@``]@(``/<" +M``#X`@``^0(``/H"``#[`@``_`(``/T"``#^`@``_P(````#```!`P```@,` +M``,#```$`P``!0,```8#```&`P``!P,```@#```*`P``"P,```P#```-`P`` +M#@,```\#```0`P``$0,``!(#```3`P``'`,``!T#```>`P``'@,``!\#```@ +M`P``(0,``"(#```C`P``)`,``"4#```F`P``)P,``"@#```I`P``*@,``"L# +M```K`P``+`,``"T#```U`P``-0,``#4#```U`P``-@,``#8#``!```(`1``" +M`$@``@!,``(`4``"`%0``@!8``(`7``"`&```0!B``$`6@,``%H#``!;`P`` +M6P,``%P#``!<`P``70,``%T#``!>`P``7@,``%X#``!>`P``7P,``%\#``!? +M`P``7P,``&`#``!D``$`9@`!`&@``0!G`P``9P,``&<#``!G`P``:`,``&@# +M``!H`P``:`,``&H``0!K`P``;`,``&P#``!M`P``;0,``&T#``!M`P``;0,` +M`&T#``!M`P``;0,``&T#``!M`P``;0,``&T#``!M`P``;0,``&T#``!M`P`` +M-P,``#@#```Y`P``.@,``#L#```\`P``/0,``#X#```_`P``0`,``$$#``!" +M`P``0P,``$0#``!%`P``1@,``$<#``!(`P``20,``$H#``!+`P``3`,``$T# +M``!.`P``3P,``%`#``!1`P``4@,``%,#``!4`P``50,``%4#``!6`P``5P,` +M`%@#``!9`P``80,``&(#``!C`P``9`,``&4#``!F`P``:0,``&H#``!N`P`` +M;@,``&X#``!N`P``;@,``&X#``!N`P``;@,``&X#``!N`P``;@,``&X#``!N +M`P``;@,``&X#``!N`P``;P,``&\#``!P`P``<`,``'$#``!R`P``0,``'H# +M``![`P``?`,``'T#``!_`P``@`,``($#``""`P``@P,``(0#``"%`P``A@,` +M`(<#``"(`P``B0,``(H#``"+`P``C`,``(T#``".`P``CP,``)`#``"1`P`` +MD@,``),#``"4`P``E0,``)8#``"7`P``F`,``)D#``"9`P``F@,``)L#``"< +M`P``G0,``)X#``"?`P``H`,``*$#``"B`P``HP,``*@#``"H`P``J`,``*@# +M``"I`P``J0,``*H#``!```$`K0,``*T#``"M`P``K0,``*X#``"N`P``K@,` +M`*X#``"O`P``KP,``+`#``"Q`P``L@,``+,#``"T`P``M`,``+4#``"U`P`` +MM0,``+4#``"U`P``M0,``+4#``"U`P``M@,``+8#``"V`P``M@,``+8#``"V +M`P``M@,``+8#``"V`P``M@,``+8#``"V`P``M@,``+8#``"V`P``M@,``+<# +M``!"``$`1``!`$8``0!(``$`2@`!`$P``0!.``$`Q@,``,<#``#(`P``R0,` +M`,H#``#*`P``RP,``,L#``"K`P``K`,``+@#``"Y`P``N@,``+L#``"\`P`` +MO0,``+X#``"_`P``P`,``,$#``#"`P``PP,``,0#``#%`P``S`,``$```@#0 +M`P``T0,``-(#``#2`P``TP,``-,#``#4`P``U`,``-0#``#4`P``1``"`$@` +M`@!,``(`4``"`%0``@!8``(`7``"`&```@!D``$`9@`!`&@``0!J``$`;``! +M`&X``0`!!````@0```,$```$!```!00```4$```&!```!@0```8$```&!``` +M!@0```8$```&!```!@0```8$```&!```!@0```8$```&!```!@0```8$```& +M!```!@0```8$```&!```!@0```8$```&!```!@0```8$```&!```!@0```8$ +M```&!```!@0```8$```&!```!@0``,T#``#-`P``S@,``,\#``#5`P``U@,` +M`-<#``#8`P``V0,``-H#``#;`P``W`,``-T#``#>`P``WP,``.`#``#A`P`` +MX@,``.,#``#D`P``Y0,``.8#``#G`P``Z`,``.D#``#J`P``ZP,``.P#``#M +M`P``[@,``.\#``#P`P``\0,``/(#``#S`P``]`,``/4#``#V`P``]P,``/@# +M``#Y`P``^@,``/L#``#\`P``_0,``/X#``#_`P````0```@$```(!```"`0` +M``@$```(!```"`0```@$```(!```"`0```@$```(!```"`0```@$```(!``` +M"`0```@$```)!```"00```H$```+!```#`0```T$```.!```#@0```\$```/ +M!```#P0```\$```/!```#P0```\$```/!```$`0``!`$```0!```$`0``!`$ +M```0!```$`0``!`$```0!```$`0``!`$```0!```$`0``!`$```0!```$`0` +M`!`$```0!```$`0``!`$```0!```$`0``!`$```0!```$`0``!`$```0!``` +M$`0``!`$```0!```$`0``!`$``!```$`0@`!`$0``0!&``$`2``!`$H``0!, +M``$`'P0``"`$```@!```(`0``"`$```A!```3@`"`"8$```G!```*`0``"@$ +M```H!```*`0``"@$```H!```*`0``"@$```I!```*@0``"L$```L!```+00` +M`"T$```N!```+@0``"\$```O!```+P0``"\$```O!```+P0``"\$```O!``` +M+P0``"\$```O!```+P0``"\$```O!```+P0``"\$```P!```,`0``#`$```P +M!```,00``#$$```Q!```,00``#($```R!```4@`"`%8``@!:``(`7@`"`&(` +M`@!F``(`$00``!($```3!```%`0``!4$```6!```%P0``!@$```9!```&@0` +M`!L$```$#`/[^`P#_`08`_P,#`/H`!``% +M$0,`_.0#`!7U`P#T"@,`#@<#`.[]`P`/XP,`!@P#``;U`P`&%0,`Z1<#``+K +M`P`'Y0,`"^,#`/$'`P`'%0,`&_P#`.7Y`P#[\P,`X`(#`!?_`@`._`(`\P," +M``4)`@`>_@(``@P"`/[R`@#P_0(`\P("`!$#`@#^"0$`^?L!``L`!0#D``4` +M`OD&`/OY`0`!\P$```D%`/G]!@`>_P$`^`,!```&!`#^``$``@$"``+]!``) +M!`(`[/P#`/OU`P`)^0(`!_H"`/[X!@`%]0(`[O\"`.7^`@#M`@(``_,"`!<" +M`@#^#`(`"`0"``@&`@`*^0(`__,!`/L$`0#^"@$`!?L!`/_Q`0#U`08`#?\! +M```,`0`'_`$`]`$!``X!`0`/_P$``_``8``@\"``(0`@`'!@(`^/@"``#^`0#]``(` +M_@(#``,"!`#][P(`^?4"`/H$`0`!'08`__H%```"`0#^`0(`^_\$`/<#`0#] +M$@(`]?D"`/\/`0`$!0$``PD!`!K_`0#]]P$`_0D!`/7]`0#T_@$``?@&``#V +M!0`*`P$`_0X"`.K^`@`=_0(``>H"`!$"`@`#"@(``@T"`./]`@`&"@(`!_8" +M`/WC`@#G`0(`"?L"`.$"`@#^_P(`[0`!`/SY`0#L``$`"/P!`/D#!@#_'08` +M_/\$`/T"!``"`P0`_`$$`/H!!0`#X0(`Y`("`/\:`0`!X@$`!P4!`/7_!@`< +M`0$`]_P"`.\"`@`&_@4`!0$$``("`P#__`0`]P0"`.L#`@`%]P(`_/<"``/M +M`@#^&@(`_N,"`/CZ`@#A'P(`"_D"`!C_`@#H`@(``.X!``P!`0```P(`^O\% +M`/_E!@`!$0$`__0!``0!!```X00`^P$$`/\"`@#__@(`_`\!``7^!0#Y +M_P0`!`@!`.T!`0`!#0$`_Q$!``#P!@`*_P8`^0$$```$`P`'^0$`ZP`!``'E +M!@`=_P4`'P`%`/_D`0#@_@(`_@\"```>!@`%_04`_^(&``H$`@#E_0(`_A<" +M`/WT`@#]`P0``NP"`.K_`@`,`P(`_NX"`!_]`@`#\@(`[`("`.,"`@`!#P$` +M`!,!``<$`0`%!P$``!4!``#J`0#]^`$`\?T!``#T!@#]!P8``?L$`/\$!``` +M^P,`_^,%`/X'!@`,``8`_P4$`.4!!@`,_@$`#O\!```(!0`$^0$``P@!`/H& +M`0`%!@$``08%`/D``P#B``4`&@$!`/KX`@#O_0(`_^$&`/_Y!`#Q^@(`^?8" +M``+B`@`+^P(`!_<"``+H`@`8_@(`_1<"`/<&`@#^'`(`[/\"`/[D`@#J`@(` +M`Q$"`.D"`@#X^P(`&@("`.H!`@#L_@(`%O\"```8`0`"]P$`!OL!`.@``0#V +M_P8``O@&``0$!@#Q``8`!@0&``'Y!````04``/\$`!H`!@`&_`8`!@4!``;Z +M`0#V_0$`_0L!```=!`#Y!`$`\`$!``/X`0``%P$``PL!``'I`0`+_0$`\@(! +M``X"`0`&^`$``_H&``#F!@`<_P8`X0`%`/`"``+E`@`5`@(`$04"`/7\ +M`@#[^`(`Z_T"`!\?`@`2`0$``?(!`/(!`0`5`0$`'/X!`.W_`0``$@$`!/@! +M`/@"!@#[`@4``!H&``8#!@`#_`4`\``&``$<`0`3_@$``.0$``0'`0`+`@$` +M#?X!`/L'`0`-`08`"@$&`/X&!0``\08`_PL&`/3Z`@#Z]@(`]_L"`.?]`@#M +M^0(`Y@$"``_Y`@#]'0(`_N`"`.D#`@`3^0(`]@0"``+O`@#U^P(`^0@"``$5 +M`@``!0,`&`$"`!GC`@#^Z@(`!O`"`!,%`@`3!@(`!O("`!_^`@#\#@(`"/L" +M``/I`@`!Y@(`"OP!`/WV`0#X!@$`_N(!`/GZ`0#_'P$`%``!`/\9`0#]^@8` +M`_\"``#E!``)``0``_4!``8'`0#D_P8`_@@&`/'_!@#I`0$`]OP!``+R`0#D +M_@$`\0(!`/SV`0`7`0$`"OT!``@"!@`.``8`!@(%`!``!@`?_P8`]_\%``@"`/@*`@`:_`(`&OT"``+C`@`1^0(`_?`" +M``OZ`@#D_0(`X0,"`.3\`@`*^P(``Q,"``,=`@#^$`(`\04"`.7I`@`8`@(` +M^0D!`/'^`0#T`@$`#P,!``+U`0`![0$`\`(!``@#`0``\P8`_`,%``$$!``$ +M_@0`^0<"`/D1`@#V`08`_`8&``0&!@`-``8``OL% +M`/S^!``"_`0``1L&``4-`@`$]`(`%_T"`/SU`@`#Y0(`_>4"`!+]`@`0_`(` +M%`("`.+]`@`*^`(``NH"``CX`@`.`P(`#@0"``L&`@`!ZP$`Y`$!``$(!@`` +M\@8`!`($`/L#!0`#]@$``Q<"`/WK`@#]!@8`"0$%`/W\!0#G``8`#/\!`/KY +M`0`'_04``.,#`/#_`0#_%0$`^OL!``(+`0`&^0$`_0@!``D#!@`#^P4`!/T% +M``;_!`#]^P4```L%`/O]!0#^!04`^``$`("`!```'P4`^/\%``H"!@`0!`(` +M]`8"`/T5`@#_%@(`'0$%``GZ`@#G_@(`_A$"``/T`@#S^P(`[OX"`/4'`@#H +M`0(`!PD"``<1`@`(]@(`#@8"`!<&`@`"Y`(`YOX"`/[H`@`"Z0(`!>,"`/GX +M`@`%]@(``1("`/8%`@`,!`(`%/\"`/'[`@`#X@(`_Q(!`/[U`0#X!`$``P$" +M`/8&`0`=_@$``.P!`.G_`0`-`@$``O0!`/_O`0#S_0$`Z0`!`/\>`0#R``8` +M`?$&``'A!@`%`@4``.\&`/;^!@#Z_@4`&_\%`/WI`@`$"@(`#OX!`/_M`0`# +M\0$`%@`!`/WS`0`9_P$`_O0!`!+_`0#C_@$`_^P"``[X`@`4_@(``_`" +M``+M`@#X]@(`_NT"``L$`@#P`P(`!0@"`/4)`@#B`@(`%@$!`/L&`0#I_0$` +M`>X!`/OZ`0#Y!@$`%@(! +M``P"`0`-_0$`$@(!`!K^`0`3_0$`$/X!``$9`0`;_@$`Y@`&``+V!@#[_`8` +M_PT&`/[[!0#X`04`^OT&``'D`0#X"0(`#?H"`/?^!@#B_P8`_/T%``,$!0#^ +M_`0``A4"`/X3`@`7Y0(`%_4"`.'^`@#]X@(`_1\"`/H)`@#\]`(`^>$"`/\8 +M`@`$]0(`]O@"`/'Y`@#^Y0(`%/P"`.(#`@`,^@(`#/P"`!G^`@#Z\@(`'OT" +M``GW`@`'"`(`&0("`/KT`@`."@(`$0<"`.L"`@#P_`(`\QT"`.4&`@`"#@$` +M&0$!`.W]`0#Z!P$``0P!`.W^`0`0_P$`_A(!`.L!`0#G_P$`&``!``+S`0`! +M"P8```X&``()!@`)_@8`!/P%``+_`0`!`04``0,"`/H"!0#\^@8``.T&``D" +M!@#@``8``!D%``/^`P`#``$`%P`!`/H(`0#@_P$`^@4!``,/`0#AX0$`$P,! +M``'P`0`5_P$`_^`!``T#`0#L`0$`_>$!`/WQ`0`$^P8`Y0`$``8&!@`;^P(` +M!AX"``?I`@`:!`(``@H&`/\*!@`$_P,`#P$&```/!@#Q`08`_QP&`/_W!0`! +M"04``OX"``($!```'`0`_00%``;Q`@#YZ0(`$1$"`!+X`@#V^0(`_!8"`!L" +M`@#I!P(`&P4"`.?C`@#\X0(`%_D"`/$&`@#D!@(``PP"`!(#`@#U!`(`_>P" +M``P<`@`/!`(`\@8"`/@(`@#S^0(`^0L"`/__!`!```(`-!@``!`4```0%``` +M"!0```@4``!$``(`+!@```P0```,$```#!````P0```4$```%!```!00```4 +M$```!Q@``$@``@`X&```%Q@```,0```#$````Q````,0```$$```!!````00 +M```$$```3``&``\8```^&```C``"``88``"0``(`&!@``)0`!``"$````A`` +M``(0```"$```*!0``"@4```@%```(!0``!88``"D``,``10```$4```\#``` +M/`P``#P,```\#```/`P``#P,```\#```/`P``#\4```_%```#A@``*P``P`< +M%```'!0``#`4```P%```"P0```L$```B"```/0@``"L(```O"```)`0``"0$ +M```Z"```-P@``",(```%"```.P@``#L(```["```.P@``#L(```["```.P@` +M`#L(```["```.P@``#L(```["```.P@``#L(```["```.P@``#D4```Y%``` +M'1@``"48```9$```&1```!D0```9$```-1```#40```U$```-1```"T0```M +M$```+1```"T0```R!```,@0``#($```R!```,@0``#($```R!```,@0``#($ +M```R!```,@0``#($```R!```,@0``#($```R!```,@0``#($```R!```,@0` +M`#($```R!```,@0``#($```R!```,@0``#($```R!```,@0``#($```R!``` +M,@0```T(```J"```$P0``!,$```?!```'P0``"X(```;"```$@0``!($```2 +M!```$@0``!($```2!```$@0``!($```S"```,P@``#,(```S"```&@P``!H, +M```Q$```*1```!$,```G#```'@@``!X(```V"```-@@``!4(```5"```"0@` +M``D(```F#```(0P```H$```*!```"@0```H$``!```8`'!@``"@4```H%``` +M(!```"`0```@$```(!```"P8```8&```/!0``#P4```0$```$!```!`0```0 +M$`````@````(````"`````@````(````"`````@````(````"`````@````( +M````"`````@````(````"`````@``.(`!@`T&```#!0```P4```D&```,@$& +M``(8```"`@8`,!0``#`4```X%```.!0``!00```4$```%!```!00```(#``` +M"`P```@,```(#```"`P```@,```(#```"`P```0,```$#```!`P```0,```$ +M#```!`P```0,```$#````00```$$```!!````00```$$```!!````00```$$ +M```!!````00```$$```!!````00```$$```!!````00```$$```!!````00` +M``$$```!!````00```$$```!!````00```$$```!!````00```$$```!!``` +M`00```$$```&#```!@P```8,```&#```!@P```8,```&#```!@P```<8```? +M&```0``&``L8```]$```/1```#T0```]$```+A```"X0```N$```+A```#<8 +M```9&```#10```T4```_$```/Q```#\0```_$```@``!`&`8```K&```@@`% +M`'$8``!I&```31@``$48``!U&```71@``%$4``!1%```8A```&(0``!B$``` +M8A```'(0``!R$````0``'@$ +M``!X!```>`0``'@$``!X!```>`0``'@$``!X!```>`0``'@$``!X!```>`0` +M`'@$``!X!```>`0``'@$``!X!```>`0``'@$``!X!```>`0``'@$``!X!``` +M>`0``'@$``!X!```>`0``'@$``!X!```>`0``'@$``!L!```3`0``'`$``!P +M!```<`0``'`$``!P!```<`0``'`$``!P!```<`0``'`$``!P!```<`0``'`$ +M``!P!```<`0``'`$``!##```0PP``$,,``!##```5Q```%<0``!S$```$```'A```!X0```>$```,10` +M`#$4```M%```+10```D0```)$```"1````D0```V$```-A```#80```V$``` +M$@P``!(,```2#```$@P``!(,```2#```$@P``!(,```C&```$Q@``$@8``!` +M``0`!1````40```%$```!1```'0$``!T!```=`0``'0$``!T!```=`0``'0$ +M``!T!```6`@``%@(``!8"```6`@``$<0``!K$```4@P``%(,```*#```"@P` +M``H,```*#```"@P```H,```*#```"@P``#H0```Z$```.A```#H0```R$``` +M,A```#(0```R$```(1```"$0```A$```(1```!T4```=%```-10``#44```# +M#````PP```,,```##````PP```,,```##````PP``!8,```6#```%@P``!8, +M```6#```%@P``!8,```6#```.Q@``$``!@!_&```?A@``'P0``!\$```?!`` +M`'P0```B#```(@P``"(,```B#```(@P``"(,```B#```(@P``%`8``"(``,` +M,Q@``)``!@`O%```+Q0``!<4```7%```7`0``%P$``!$```7A```%X0``!>$```8Q```&,0 +M``!C$```8Q```&H$``!J!```:@0``&H$``!Y#```90P``%D(``!9"```7PP` +M`'<,``!["```>P@``%0$``!4!```5`0``%0$```G!```)P0``"<$```G!``` +M)P0``"<$```G!```)P0``"<$```G!```)P0``"<$```G!```)P0``"<$```G +M!```)P0``"<$```G!```)P0``"<$```G!```)P0``"<$```G!```)P0``"<$ +M```G!```)P0``"<$```G!```)P0``&0(``!D"```9`@``&0(``!D"```9`@` +M`&0(``!D"```9`@``&0(``!D"```9`@``&0(``!D"```9`@``&0(``!Z#``` +M>@P``'H,``!Z#```>@P``'H,``!Z#```>@P``%L8``!6&```9A0``&84``!G +M%```9Q0``&$4``!A%```/@@``#X(```^"```/@@``#X(```^"```/@@``#X( +M```^"```/@@``#X(```^"```/@@``#X(```^"```/@@```X,```.#```#@P` +M``X,```.#```#@P```X,```.#```)A```"80```F$```)A```!$0```1$``` +M$1```!$0```Y$```.1```#D0```Y$```0``!`&@8```E%```)10``"D0```I +M$```*1```"D0```5$```%1```!40```5$```*@P``"H,```J#```*@P``"H, +M```J#```*@P``"H,```:$```&A```!H0```:$```1!@``$(8```/%```#Q0` +M`!L$``!!!```"!`0$Q`3%A86%A86&A@:&QL;&AH:&AL;&QT='2(B(AT='1L; +M'1T@("(B)28E(R,B(R8F*"@H,#`N+C@X.D5%4]SQ_)\4)_V?T?\'`!!7`V`0 +M6`-@)@#X_X#U_)]\]OR?____?P```(```&```/+\GX;W`P``]OR?2!0``&RJ +M`&`````(__\?``````$```!``.[\GP```@"HJ@!@W*@`8````D*($P````@` +M``$`@````(```%+\GP"9`````OR?@):8`/T)_/\`^OR?`/[\GP8``.`&``"@ +M`"[\GP#>_)\`&````.+\G__G______^_```!`/___O_`#P`````_``````0# +M`__@`P+_X```,`,&"__P!```@`$``(#_]___```"@(<3``#___\/````P/_O +M`````!```/[[G^0-``#___\!__]?`'OX_?\```"@````X`$``.`!``"@`P`` +MX`,``*`*``#@"@``H````&(#``"`A`<"``````+___^]____\```$(#_\___ +M`!\```!```#_?_#_`(`)`````/#_O___```(@````X#_\/____\/_P``#X`` +M``:````!@```$8"5`0!`E0``0``.`````,`````P````#`````,`__\_^/__ +M_\<```X`````.`#P`0```,`'G0``0)4#`$"5`@!``(`,````"@````6````$ +M@```#8````R`C0``0!`(`&```/`/`#__`/___X`6```(($X``/___\#W??__ +M`(```````%`@O_\`*00$````>``FI(0`QH2$`"2DD!(``#`&(20$``,@```" +M(```0&\``.AN``#@#P``3`\``(`/``!@NP!@?+X`8$0S(A&\$@``J&L``/__ +M_P#`M@8`*%4!8```4@#,:P``$&X```QL``"L;````/\`__@=``#P_P``0`@` +M`"`__P`WS4+]9KCTC(OQ3P<\;0``P!(`````P#^,#```4`@`8,!K```0#0`` +M/YP`````)``!8```B`\``+0/``#T"P``@`T``*`-``"P%@``:%T``.A=```K +M#0``Q!(``+0+```H#0``M#T```P^``"9/0``K!L```0<``"0#```L`@`8`@, +M``!4;0``-`P``'0,``"H"P``Z`\``$@3``!`$```%3T``)02````(`,``@@` +M`(@,``!`;0``K`P``)`)``"X%```N!(``*Q=``!L:P``J!(``!0/``"(7@`` +MG!(``$`)`&#P;0``$&L``!$/````4@(````X!`#@A@(``,P``'AI``!V+P`` +MV!L``.P-``!&!0!.8@``4&(```YC```08P``_&L``-`.``!@;0``$`\``!@/ +M```\%```5!L``/__O_^`7@````!``)@+``!D7P``\%\``+!=```I#0``]%T` +M``P)``!,#0``1&T```P*```,#0``U$P!8/!,`6!F=XB9__\#^```_`<`_@,` +MM!(``%P]``"<:P```#__`=1K```H@P%@['8!8."L`6!@;0%@@&`!8)AW`6"( +M;P%@.*P!8'23`6!880%@=*`!8-!7`6"LI`%@J)(!8,"N`6#TAP%@'(H!8,B4 +M`6#P"0!@```0^```0/@P"@!@````^```,/@(@`````#@`0``(/@9```0&0`` +M(!L``!`;```@$P`!`!L``(`;``!`&P``D!L``%`;``"@&P``8!L``#`;``"P +M&P``#0``0/"^K=[__```8!$``````&"`$0``H!$``,`1``"D +M$```!!$``````#RH$```"!$``````!#,$```+!$``-`0```P$0``K!````P1 +M`````-S_``#@_P#P_P``7V`!*)0`````_P``_P```0```8N%`@"+A08````` +M_@``$`$,A@(`#(8&`/G_``#P#P``/X`-`$#[`@`L*P``=%X"8```"0``@`0` +M\`P`8)Q<`F`,AP)@H"H``,0E``#,)@``(S__`",___`#`/`/<``'`/@-```L +M*0``,'4```,`_P\#`/$/_____D`K````T`(`^"(```,6``#$)`````!0^-0E +M``"`_P``P/\``,AW`F!D=P)@T"4```(1```"%@``,`T`8*2%`F`"&```$`X` +M8`,1```%$0``N`L``-`-`&`D*0``.",``#"&`F`_"0``1",``#25`F!\M`)@ +MG*4"8&R3`F#@#P!@?(<"8`S/`F!\QP)@!(@"8`4``$#@Q@)@])L"8"3*`F#@ +MQP)@N-`"8*BZ`F!0)@``!-,"8,34`F"$AP)@\(<"8-R'`F#(AP)@M(<"8*"' +M`F",AP)@MPL``"`I```P#@!@D`X`8&@C``#@#@!@T`X`8*`/`&`\)```#"0` +M`!0D``!@)0``F"0``'`C``!H)```J",``'0C``"P$0!@9-L"8,3J`F!+1%/#P-/)N +M+:(N+=(N+9(N+8$]`,#=$8"9$="9(*"9())CY8)B%8)B%V(C]V)N+4(N+5*O +MQQP&4$008$0@0F/W03X`\B/>L3L`PL%D0/\@\FXMTBXMTF/>DB.BHJ<`43\` +MH)D@DFXM@BXM@F.B\B/=\FXM\4$`XBXMT4``#'KP[B#B8]UR;5928\9E@?<, +MBK%"`,+!9*6`]Z*@!K%#`!#!(.5_]Z*AP.6;]PP>@40`@F$8\B$8\F/$XF(N +MTB/`LJ`"L-T@TF$8PB$8PF/`DB(OH34`L)D@DF(OI9CW038`4M$48M$54B4N +M4F8:444`848`QA,`9CP"1MH#O,>")P#,&,:1`\(B+[+1%0Q-T,P@PF(OF`<, +M"J)K$)Q9"^D6WB/RR?X6GS."R?T6."ZBR?P6FEL,&[)G`+)B20P-XM$5>>[2 +M;A"BH8!ED_<,#[+1%:(A&7+1%7CG@B$:HFL=@FL +M`D;&!/+1%0P8@F))HF\01HO_``"2H@.0G,!6B=W8]Z%``.*A`.#=(-GWPBI$ +MPFGF0,,*JD'#!NR8DG&:_^] +M"L%'`-+1%:)M(L>:(Z+!$+*@#.5.+*+!($P+94XL#`Z2T14,"++1%;(K(H)I +M%N)I%\%(`+>\,:(B+]%)`,*OS\"J$!P,P*H@HF(OTBV&X4H`T-1!Y\T1X4L` +M\BX(`-H1\/#T\-T@TFX(DM$5&XN":1"W-@)&4/^B(B]\N["J$*)B+\9,_\`@ +M`,+1%<(L%3WPS!S&S0/`(`#BT10,#9+1%9(I%0Q/@B6+ +M`>T*LB<1HB<2D@X`@@X!\@X"X@X#@)D1D(@@@(@1@/\@@/\1\.X@XF=_)8D! +MLM$5LBLBQH[^````TB$8R`O7'`YV@`?R(1CH"_<>`T;\_P"Q4@`,&8+1%:)H +M$))K39)B2<:5_@PD2TF/_V0?"8DF&B_X`DM$5 +M#!NR8DFB:1!&BOX``&9)`D;;`V9I`@8J!*(CK#WPH,`$!VH"1K<"DM$5=H`0 +M\B/G^0GH">#@%.D)V`DF/0(&^O^150"Q5`#R(B`,2-%3`(#_(`P(\F(@P"`` +MXB(@P"``@FV"L.X@@FD6P"``XF(@X58`P"``\B(@P"``X/\0\F(@P"``\B(@ +MP"``@FV"L/\@@FD6P"``\F(@P"``TB(@DM$5P"``X-T0TF(@P"``@B(@?+O` +M(`"PB!""8B#`(`!V@!#B(^?I&=@9T-`4V1FX&28[`P;Z_P",K(+1%*)CK/(C +MK/)H/TP*Y2;WTB.LLM$5N/NB(B#0P`0';0*&B`*2T17RH0#P^B#R8B#`(`#B +M(B#B:0+`(`!V@!#R(^?Y.>@YX.`4Z3F(.28X`@;Z_^*N_^#J$.)B(,`@`((B +M((DIP"``%HP`TF.L\B.L\FD"@M$5^#OR:!.!0`#2*$D,&GSNX-T0TF$8DB$8 +MR$L,#^%7`,+,_L#Z@PP*D/\@\FA)TB(8DM$5@3\`X-T0TF$8R$N@^B#B(1C" +MS/K`^(/"H(#P[B#B81C2(1C28AC"8ZBB8ZF"*P1V@!#2(^?92QE<"DM$5#"_P^B#R8B#`(`"B(B#`(`!V +M@!#R(^?Y:>AIX.`4Z6F(:28X`@;Z_WS>X.H0XF(@P"``@B(@B7G`(`",;-)C +MK/(CK/E9T4D`DM$5#`@,"J)G?H)I&Y+1%=(MY=F)R$OQ6``F+"[HB?#N(.F) +M@BLUP4D`HM$5@(D$%D@DJ(JB;.62*S7RT1629RB0FA229W[,Z08'`-%9`,B) +MT,P0R8F&\O_BT17B+AL,&0P(X(F#@F\;\B(G-.)B:M(G-=)B:X8%````DF)HTBA+XL[^_(Z&/@#2)S<,B&8="N(K%@SZPJ``5KX`\BLU@/\@\F)G*08D`)JZJ/VR;2'P(`"B*A;EY"O2T17"T17(_-(M(<(L%J#M@N#,P*P\ +MHM$5J/J]#:(J%J7B*]+1%=(M$<(G*1OJX-V"VLS"9RG&$0```*+1%:CZO0VB +M*A9EX"O2T172+1'")RF@W8+:S,)G*08)`/(K%N(G*?KNXF_P``DB$8?*J@F1`,&J"9())CW+._N"=@\"9())K5N`(`/+1%:)O%(RJ@B(ODJ`(D(@@@F(ODM$5L4`` +MXM$5Z/[RH'#"*U;H3GS=?.KBSO[@K8/`JA"B:U:`Z@/R8ZCB(ZG18P"BH`%@ +M[B#B8ZG"(ZFRH'2":1+0S!#"8ZFR8ZAES?;X)R9O`H8@`)+1%7:`$+(CY[F9 +MJ)F@H!2IF8B9)C@2!OK_PM$5#!W28BZB;!!&VOP``,(CK+(B(#WPP-`$P.`$ +M5CY5DM$5#"_P^R#R8B#`(`"R(B#`(`!V@!#B(^?IN:BYH*`4J;F(N28X`@;Z +M_WS8@(L0@F(@P"``\B(@^3\(%E`#)B249^_```TL$0DM$5 +M#`C"T16BT16B*A?"+!:":2/0VJ"Y#1NJTL$@H*!TT,R@N0P,.R6=*PP\DM$5 +MH(!TTM$5LM$5LBLCTBT6#`J":1<;_?#0--)I%M(B+Y+!$':L"<@)2YF\S+J\ +M&ZK!:`"W/#GA20`L"Z*OSZ"M$+"J(*)B+^(NAO%*`.#D0?=.`L9+_,%+`-B, +M`+H1T-#TT+L@N8P&1_P`9CH"1C0##`L,"I+!(!P.=JX*R`E+F18L'+J\&ZKQ +M:0"W/P+&;@"!20`<"Z*OSZ"M$+"J(*)B+X(HAI%*`("$09=(`D8U_,%+`-B, +M`+H1T-#TT+L@N8R&,/R8]S=I`L9D_.%```R(@(D@B??R+D3R9QCB+D7B9Q?& +M)?P``,P7QBX"F`<+F1;Y<[+1%0P?S10``,+_#Y +M(/GWXBU$XF8*3$W`,P9QA,""\G, +M'`8!`@P-V3?H1Q;^">%``(+1%:+1%;+1%9+1%9(I&+(K&:(J$HCHD)O`L*K` +MJ5>99_(H?/EWXBY'Z8?2(AW9E\(B',FGLB/RN;>B(_.IQY(C\9G7\B/U^>?B +M(_;B9P_2(_329Q#"(^O"9Q&R(^RR9Q*B(Z2B9Q.2(Z.29Q3R(E3R9Q7RH`#B +M(E7B9Q;2(E;29Q?"(E?"9QBR(^JR9QFB(Z*B9QJ2(_>29QOR:'W`(`!RT15X +MYPP:##NY!Z)B+D;D^X+1%0P9DF))HF@01N/[``"B;A`,',)B20;@^P#BRO`6 +M7GCQ20"BK\^@K1"B8B_R+X:!2@#P]$&'3P*&Q_O!2P#8C`"Z$=#0]-"[(+F, +MQL+[\M$4?.B`BA""8ZS`(`#B(ZSB;SC`(`#&HOP``++1%'SMT-H0TF.LP"`` +MDB.LDFL_P"``QD']``#RT15\Z("-$()CK,`@`.(CK.DOP"``QG#]?._P_1#R +M8ZS`(`#B(ZSI6<`@`$:B_0``P4``TM$4XBQ$XF$8PBQ%PFTOP"``HB$8LM$4 +MLBLOHMH!)8"ALSHJ`!Y7L!5Y/IHB$8 +MLM$4LBLO9HBI%HF<=AGK[`.A-)BX"QA3\HJ#[AA;\``#RT14,&()B2:)O$$:%^P`` +M.<,&0PZJ0>28BX&?OM\ZJ"L$*)CK,`@`((CK(FIP"``1J7^`+(G(+)A +M'Z(G(+%L`*"C0;"J$*)B%K(G(,%G``P#L+`DP+N@PM$5LFP5=H`0TB(6TF$8 +MPB$8IQP'&S-'$P(&^O_A;0#]`S$W`/<^`D8>_#$W``P8#$FBT15YZID'@F)) +M1F+[``"Q;@"B*3:PJA"&+?R2(ZR0H`0':1;2T11\[N#I$.)CK,`@`,(CK,)M +M/L`@`,%O`'P+TM$5,FTE0FTF,4X`(FTD04\`@B."(B/"^"3B)$*PB!#`R""P +M(A#2(T*P_Q"P[A""8X(B8\+Y)+#=$.)D0M)C0L`@`,)C@L%P`,"R(+)CPL"_ +M(+DDP+X@LF1"P,T@PF-"P"``LB."PB/"N"3")$*R(T+`(`""8X(B8\+Y)"+1 +M%2(B).)D0M)C0L`@`,(C@L+1%+(CPH@D0B1",B-"0M$50B0F,FP^P"``,M$5 +M,B,ES!K&H?R28ZS`(`#B(ZSB;#[`(`!&G?P``)(CK)"@!`=I%H+1%'SKL+D0 +MLF.LP"``\B.L\F@]P"``TM$5(FTDDFTJ4FTG0FTF`)8T`LM$5LBLBQI[Z``#"T14,'=)B +M2:)L$$:M^@``DB.LD*`$!VD6\M$4?.B`B1""8ZS`(`#B(ZSB;SS`(`#2T14B +M;222;2I2;2=";29R;2EB;2@R;25A=``Q3@!Q0]`16?XN!0``<#,#)(,GW +MHBA$HF<4@BA%@F<3!DKZDB.LD*`$!VD6XM$4?._P^1#R8ZS`(`#2(ZS2;CO` +M(`#2T14B;222;2I2;2=";29R;2EB;2@R;25A=@`Q3@!Q=0!!3P!2(X+"(\*X +M))(D0GP-T%40@B-"T,P0<"P@T+L0 +MXF))HFT0!@3Z`/+1%?CO\B]/@J:`BO_R#V$,&/#XD_DW!NC]``"!:0"W.`(& +M'/Y&K/T`#`G"T12R(ZH,JK)L,L+!9':J"MB,XJ($C+T;F>K,#!_R8DD&\/D` +M@M$5@B@?J"BIC(A(@FP5)IGD#`T,/K+1%;(K'^E\TFP6^%OP\`3R;$'B(1NA +M=P#@Z8*J[N)L5H(A&^%``("(H*"(D*+,'()L5_(A&])L+/)L$M)N2;A+XM$5 +MHFX.MDMKMEL4\7@`]SLZ@7@`MS@"1BX`D6$`EYM?#$P,C?%-`.+1%.(N,K+1 +M%;(K'_#N$.)CJMDJR3K(>\F:N(NYJN56&\83``!F:S"2+A\,"`ROV*G2;!.X +M>;)L$+*A`)B)DFP1^9R";"VES1C&"0``]BL"1BP`MCLV)CM3X4T`TM$4TBTR +MLJ``X-T0TF.JLFP)I3L!,3<`@3@`\M$4\B\R#!Z`_R#R8ZKB8DE&K?D``-%N +M`++1%+(K,@QHDBX?T+L0LF.JDFP7B9RE?B7&\?\`#$\,#0QND4T`@M$4@B@R +MPM$5PBP?D(@0@F.JZ2K2:EKB:COY6KA\LFI"F(R2:D.(?/N(@(1!@FI(^(SB +MRFS[__#T0?)J2]).S-).S=).L,)J$"5#)H;;_Q8+];8K`H;2_[*A`)%-`/(N +M'X+1%((H,@Q-#`Z0B!""8ZJ8KY)L$PP9B'^";!#XC_)L$>)L+>FLV4\`.(*`+(G$9(*`?(*`H(*`Z(G$H"9$9#N(`#_$8"(`8#_(/#N(.)G?V4Z +M`++1%;(K(L93^0P+DL%D#*QVK!;BT17B+A_8B>@N\J($^IG@W<`6[0P;NX+1 +M%8(H'XA(@LC^5B@/#`N2P62BH`IVJ@K(B8RL&[O2H@3:F88#````XM$5XBX? +MZ"[IB6:;#H+1%0P/#!F28DGYZ,9,^0QI#`P,/X*B!("+@G+!9(IW^7?"9Q;B +M(1NBT13Q=P#@ZX*"T17Z[N)G5M(A&\)G+-)G$K(CJK)J,+%N`*(J,')H(((H +M'["J$*)CJIF7@F<70"2*3'"T17"+""@F2"2 +M8ZJ&"````-+1%0P>XF))HFT01BOY``#RR_86S_+2H@30VX+"P63:S)A\O%DF +M23,F.3#BT14,'_)B27GNQB#Y@6@`M[@"!LG\QKG\HM$5#`D,&[)B29GJ!AKY +M``P,R3?&`OT`TM$4\M$5#`<,&++1%;(K(H)L%GE\\B\?\FP7@#`(`"R*L6Y`8@!EW@$DFK&.0+(`?$_ +M`,#.!1;,$;*A`.%``"(JJBD1XBY)#`+-`N#@!.##DPO<%ET2D4T`B!&0B!"" +M:JIA3P!13@#A.0!!5`"&#```*2$,J7:I`SWP/?"((7(JYPRM#!EP9.`=R!Y(7:M`SWP/?"((0N[G,@F"QJ\'&8$O]@=T-`$V2'& +M[?\```#H(>P.,FJT=H`+DBJUF2&((0N(%O@)1OO_`-(N($=M-2DA!N;_`.(J +MMCWPEOX)#"B":K1V@`FR*K6Y(9@A)AD"QOO_(FJT\FK&R!'":JI,"F7"]1WP +M`((E@XDAF"&")P#P[B#I`<@!R0VY`9@! +MDFK&!N;_`")JM$;B_P``D6X`B!&0B!"":JJ&M?\``+$U`,*@\,)JJ+)JJ0;: +M_P`V00"BH("ENO61-P"Q0`#`(``,',D"HBM#HFM#@BG%1W@-=H`%TBG%1WT$ +MQOS_``#`(`"BH(`EMO4=\``V00"BH0#EMO6A-P"Q00#`(`"R:L:"*L4]\!=X +M"W:`!9(JQ1=Y`L;\_PP@AX-T@V2&X(;)LYN&#`-$Y``P;P"``H80`B"&@B!")(?@A\FSF +MJ!&!/`"PJB"B;.J";-J2;4KR(A6!A0#P\'2`_R#R;*:R+.6Y,8@QHJ\/\B(E +MH(@0B3&(,?#\-<#_$8#_(/DQN#&R;.6B(B2QA@#QAP"@H'2PJB"B;*:"+.6) +M,;@QHB(E\+L0N3&X,:"L-8"J$;"J(*DQB#&";.7R(B2!-0"AB`#P\'2`_R#R +M;*:R+.6Y,8@Q\B(EH(@0B3&(,?#\-<#_`8#_(/DQN#&R;.6B(B2QB0"@H'2P +MJB"B;*:"(B2A9`"`@'2@B""";*;R(B2!B@#P\'2`_R#R;*:R(A?QBP"!9@"P +ML'3PNR"R;*:B+.6I,?@QLB(@@/\0^3'X,>"[$/"[(+DQJ#&B;.6"(A^AC`"` +M@'2@B""";*;R(Q\6'R."(R#R(AB*__)M3[(C(:(B&+JJHFU:DB,B@B(8FHB" +M;5OR(R.R(ACZN[)M7*(C%J)M3/*B`,`@`)(B?A9Y(A:4(/)M3+(C-I=["Q84 +M(H&-`()M3@8"`!8$(I&.`))M3E&/`**D$H(C'I(C'W(C'3"($:"((("9$>!W +M$9!W((!W(')L\+(C)**AP)(C)%"[$%&0`*"9$+"Y0:&1`*"[`9"60<"9`5"[ +M$%&4`*"9$+"9(*(C)#R+@B,DL*H0L9(`H*-!X*H!L*H0L9,`@(`D`(@1L(@0 +MH(@@D(@@@F973&X,:&5`%"[$+DQF#&!E@"@F1"9,7(C)*&7`)&8`(!W +M$'!QY8@Q4B,D4'6,/H;[_P``HBRLDBT@H+`$!VH2?.B`BA"";*S`(`#R+*SY0<`@``PN +MX)D@DFT@P"``DBT@P"``=H`0XBSGZ5&(48"`%(E1^%$F/P(&^O]\V(")$()M +M(,`@`/(M(/EAP"``G/NB;*R2+*P=\+(LW*"[$/"[P%:K]0;0_X(B>[T#K0+@ +M"``=\+)LJ.(LJ?%&`+)LJ*#N$/#N(.)LJ;)LJ-(LJ=D!QA7_HB,@DB(8JIF2 +M;4^"(R+R(AB*__)M6P9X_X%)`*%9`+(HY;DQF#&@F1"9,;@QLFCEAG?_`(&: +M`()M3L9[_Y&;`))M3H9Y_P``H9P`HFU.QG;_````-F$`D3<`K0(A?P#R*>K1 +M0``,#"#_$/D!(8``Z`'B:>K";4>"*>:)$?@1X8$`(/\@^1'8$8&=`.#=$-D1 +MR!'`B"")$2@1(FGFO0/"H)@A.0#`(`#QA`#H$?#N$.D1V!'2:>;H`0P8\J02 +M@.X@XFGJTB,>XB,?@B,=,-T1\-T@@.X1X(@1X(@@T(@@@FGP\B,@XBH8^N[B +M8D_2(R&"*AC:B()B6O(C(N(J&/KNXF);TB,C\BH8@BI[X7X`T/^`\F),BL?TBL= +M,/\14/\@@#,1X-T1,-T@\-T@TF+P@BLD_#P=##_ +M(/)BIN(J%_&+`)&C`.#@=/#N(.)BII)M3D)LVN`(`!WP``""(R#R*AB*__)I +M&-(C(H(J&-J(@FD:QK3_````-D$`\:4`#`YBH_X,%X&H`)&G`**@__:S#$&D +M`$!#H$@$#!6@!``,!3)B(V)B,')B+H)B*9)B**)B)>)"D>)B*N)B+^)B,>)B +M,N)B,^)B-.)B->)B-N)B-T("6+#%$?#3(+CBLD*0TF(FTF(KP,,@T:8`0$01 +M0$,@X@)9T,P@PF(G,.X10.X@\.X@XF(LXF(M'?`,%0P3AN/_QN+_-H$`,,"T +MMBP.]DP%MBP"1G<`0LS\%G0=#!5A3@!Q3P#'8U#Q.0#H(N)O@M@RTF9"4F9$ +M4F9%N%*R9IJH0J)F@IB"DF;"B)*))TBB0F=".+(R;X#HPN)OP-C2TF9`N.*R +M9H"B(@^B9L"2(A"29P""(A&"9T!!J0#R(A(,"PP#\/2#=I\GTB=#B#>2)L.B +M)H-2)D,;N]"((*!5()!5((!5((S%#`OB(A0;,R8N"$8!```,K[>_[H$W`#WP +M=H`:0BCG0$`4)C0*DB(4#`LF*0W&^O\;NPRJMSH#!O?_`)(HK)"@!`=I$GSM +MT-D0TFBLP"``LBBLN0'`(`#1<``X,M`S(#)F0OBBT/\@\F="Z(+0[B#B9L*X +MDE&#`$%O`-"[(+)G`O(B!,!%@S&J`$#_(/)F@C)FFN(FFC<>"W:`!4(FFC<4 +M`L;\_\(F0K(FPE@G0B=",B:".0$QIP#`(`#X,O)F0NA"XF:"V(+29L+(DLDG +MLB(*LF=",F::4B::-Q4+=H`%TB::-QT"QOS_P"``/?!V@#KH0M(F@MD1PB9" +MR2&R)T*Y,5(FPEE!2"=)4?@1]Y[@^"'H,O>>V5@Q2*)7E-+(0;B"QYO+Z%'8 +MDN<=`P;O_P"<2I)HK,`@`$(HK$D!P"``?/_R9H$=\`!\^()F@1WP``PT`H;[_QWP`#9!`$*A]':D!%@"-Q7_'?`V +M00`L`W:C'8)R!()R1()RA()RQ(+2`2+2`H)X!()X1()XA()XQ!WP-F$`,.H# +M,F$`=H`.D.H#F1&(`4@1@$3`)[0"AOK_'?`V00#!L0#1L`#QIP!!KP!1K@`, +M9N$\``PHL4X`D3D`#`-,>J)I@C)I@*%<`#)I@3)I@S)IA#)IP)&R`#DK.0LY +M&SE+.5N):^)K0H&S`#)K0#)K03)K1#)K13)K2")K3C)K42)K4C)K4S)K5#)K +M5S)K6#)K66)K6V&T`#)K7#)K73)K7U)K@C)K@%&U`#)K@3)KA#)KAC)KBS)K +MC#)KCC)KD3)KDD)KE$%/`#)KEC)KF#)KF?)KFC)KGC)KHO)KIC)KJ.)KPM)K +MP#)KP3)KQ")KQ3)KQC)KQS)KR#)KRC)KR\)KS3)KSC)KTCDD.00Y%#ED.82I +ME#FD.;0YU#GD,F00,F01,F02,F03,F04,F05,F06,F07,F08,F09,F0:,F0; +M,F0<,F0=,F0>,F0?,F0@,F0A,F0B,F0C,F0D,F0E,F0F,F0G,F0H,F0I,F0J +M,F0K,F0L,F0M,F0N,F0O,F0P,F0Q,F0R,F0S,F0TDF0U,F0V,F0W,F0X,F0Y +M,F0Z,F0[,F0\,F0],F0^@F0_8F1",F1`,F1!,F1#(F1$,F1%,F1&(F1',F1( +M,F1),F1*,F1-,F1.4F10,F11,F12,F13,F14,F15,F16,F17,F18,F19'?`V +M00`Q.0`B8UTB(UX=\```-F$!H4X`,3<`03D`8BJ" +MAW@NX;8`:4$`/J:0$*8,!2<9'M)A(,)A'_$_`(&#`+)A'O#W(("&(()A(?)A +M(D8%```=\````#JFD!"F&U4G&?"RH!-7.^K1MP``/:;P(`#`$*:M`67)_\*@ +M`G:`%((CYX)A&?(A&?#P%/)A&>(A&28^`D;X_Z(CK)(D(*"P!`=J$WSNX.H0 +MXF.LP"``TB.LTF$:P"``P/D@\F0@P"``DB0@P"``?-UV@!3R(^?R81OB(1O@ +MX!3B81N"(1LF.`*&^/_0Z1#B9"#`(`"")"""81S`(`",>Z)CK/(CK/)A&I(A +M'Z(A(+%.`-(A(H(A(8)K@O(K@H(A'F)K@N(K@M)KFL(KFG)KFK(KFJ)D2JT! +MDF1,@F1.Y;K_H;8`/?!V@`62(TYW:06&^_\```!V@!?2(^?281W"(1W`P!3" +M81VR(1VRR_T6^^Y&^/\`-D$`(;@`'?`V80"]`0P,#`V"(D^AN0""80!EN@D] +M"K&Y`&6D*0R+#`61N@`I(\+3!J(B):)L)]@!TFPHJ+)"TPZ:D]JJHFPIDF1> +M4DD&HB1>9:$IH;L`+$NJHZ)D4J6@*:T#9>D$XJ#_DM-JL:4`P:8`@;P`\M-@ +M#!J*@Z)(,U)($*&]`-(B)=)O'\)B7[)B8U)I]>)I]N)I]Y&^`-(D7L(D4@PK +M4ET"LDPCHF)ZDF)[#`(=\````#9A`#(B3T*A;`P(B0%*0D"D(&6M_ZT$LJ`` +MY8/_D3<`H3D`P4\`X4X`?/ORH0+R;IC2+IBR;H&R;L&Y'+)L0;)N0;)J@<(I +MK+(J(,#0!`=L$GSO\/P0\FFLP"``@BFLB1'`(``,*("+(()J(,`@`+(J(,`@ +M`':`$/(IY_DAB"&`@!2)(?@A)C\#!OK_`'S?\/L0\FH@P"``@BH@B3'`(`", +M3<)IK((IK/$_`)&:`++3;<(B%L)J2K(K)[)J3))J3H(NFHD!V`&Q5P#PW2#2 +M;IK"+IJH`;"J$*)NFI(NFB6H_QWP`#;!`#$W`&$Y``P)F0'B)AC"(ZRBK_YR +M(D_`T`0';!"@_!#R8ZS`(`""(ZR)$<`@`$%.`(%Z`/(D@H"/(()D@H(D@O)D +M@H(D@H)A`1;=`,)CK,`@`-(CK-D1P"``P;\`X/P%TB=I4J8H6E?PW2#29VG" +M9CR")VF"9CSR!;D]\"9O`I)%N;*A`GS_#`V1P`#AP0"B!;FIH>KGFI>"*7_I +MD9F!&XB":7_21;C21<'21<+2;H3R;H/"))C)`:@!@<(`\3\`L*H@HF28DB28 +MB0'H`<%7`/#N(.)DFM(DFK@!D:8`P+L0LF2:HB2:DF2"@B2"P"``I9C_HJ%L +MJJ*B80OEC?^8@7:`"<(C3LDAN"%W:P5&^_\```#2*8`6'12B(G_EO?^M!R60 +M`!R+?0K(D<`@`.+*Z!:N$_(B?:(L?*)B?(CE#'FHL9"(8X#_(/)B?66+_WSR +MJ+$,"^5A_\%/`")D@2)DP2D<(FQ!(F1!(F:!HB.LDB8@H+`$!VH2?.[@ZA#B +M8ZS`(`#2(ZS90<`@``PNX/D@\F8@P"``DB8@P"``=H`0\B/G^5'84=#0%-E1 +MB%$F.`,&^O\`?-W0V1#29B#`(`"")B")8<`@`(Q+HF.L\B.L#/.2!<(,N`RF +MDLG^D':#AQ=Q''JG%VRRQ^H62PG2Q_8630DF%UV"Q_@,CRT#@"^#)I(XD<,` +M=H`@"YGR)(/8/+(L0Z(D0_#=(-"[(+"J((S:%GD&@@7")B@(!O;_````%HD% +MD@7"DLG^D":#)H(9)I)%-Q(*'!JG$DJRH!2W$@@,`AWP'$)&ZO\,$AWPR)'" +M+'L]\!8\ZZT'9:H!QJK_``P)L-K`#![B;(16?>N9P88%`!P2QM[_``PB'?#B +M1<*E=0E&Y_\,,AWP7$,"K'$`.5@]`P'#!JE?/28H:AQ\J8@@J.X +MBHKZ^I)/P7)H?W)H@')/RG)/R7)/P'G/97(`R)'HP7T*'(T;[M<:`H:(_^G! +M9IZ!AH;_```V@0"X''`,K&\J"`ZN9VJ562*(R2:G^2*(V2:H"2*WJ"R!"BRA`@F1"2;'^2#8"+ +MNXO,\)D0DDYXD@V`DDZ(DBB*DFI]DBB+DFI^DBMY*]TK[B"9$))L?I(-?_"9 +M$)).=Y(-?Y).A[AAB%&B(ZRB:X*2)R62:'V"*(!2U@V2H&06"%N"(S@6*%P+ +MR!9L7M+(_A9]78(E)0P>\J^`\D@]XF9IDJ/H\J#[R&&")26XD[)L<:(#\ZF( +MX@/VXD@\HB4ELJ#]T@/T@@HXV9K"`_7)JL(C.@R-@(!DT,P0P,,$D,P1P(@@ +M@DHXPB4EXB,Z#$VB##G0[A#@X@3P[A&PJA#@JB"B3#GB(SK")24,*(#N$*(, +M.>#A!.#N$?"J$."J(*),.<(E)9J3\BDR\FQ^XBDSHAEHXFQ_]BH3\J"$H/^" +M^OSRWP*B7P#B&6GB7P'RH_`,""(E)4(9:L+6"M(LY:(9>N(9BJ)B>X`D;Y_](LY9(M +M=`P(K`D,"OJ3(B4E=H`3&XBJXD(9AT)N>N(M=$NJ*YGGN`-&^?\`PBSEDBQU +M#`BL*?J3#`K2)25V@!,;B*I-\AF7\F1\XBQU2ZHKF>>X!4;Y_P````P"/`KB +M)28,#)(#_,E!PJ#?F2_\`'T``[J'B8D+88\ASLB,ZT-#T +MP*2TT-1!TE+:P,#T0+L0L+)!P,1!PE+:)H +M=[)H>.)=%L(2V[(EGJ(C'`O,PET7HEL"H@/PHF)*LB,Z@J96BH:PL`2R2(DF +M&@NRROX62R'"ROT6/!_2$N'B$N#0T4'@X4'B4N+24N/R)2;R#TP,'@P-\/$$ +M\-Z#TDB(PB,[P,`$PDB&L@/Z`+LCLF)%H@/[/#T`JB.B8D;R(XKR8C3B(XOB +M8C6R(SG")26H4="[0[),/J(J@"P/O&JRH+^B(SKB)25,#,"J$-(..:"F!*"J +M$;#=$*#=(-)..;(E)<(C.J(+.?#,$,#%!)"J$,"J(*)+.0P,TB=^,4X`HJ%L +M%KT(JB>B)27B"CWBSKX6_A>R"CXT#-((B8QMZ&'B+HX6_A8,':',`+'+ +M`$&E`/@FT.!TH.X1TDB6@@<'<@<&#!TPB!%`=Q&`=R""TP1P[B!`[B`, +MYT%/`.)O9>)O9.)O7O'-`-)D6,)D4\'*`,)D2+)C@*)CP`P+K0*9"')D0/)D +M.&7F_AWP``"X4;(K@%:[]M(%K:HGB7%6/?9")T^B)W\,#N)A`*4\_Z*@`248 +M]*%?`"7Y\R"B(('.`()C@O(C@O)A`*4(_X$W`*(H3JD1F!%WZ?7`(`"BH`#! +MMP""H"!VJ!H`/*:`$*:)`8@!F`&@L$0`&T"0B(&)`8@!JJBI(:T'Y5C_S00, +M"K'$`&7T\PP:91#TB''ASP#8(9*@_L*@`.<=#D'0`$<="+'1`+"MP%:Z[.AA +M#!W2;HY&L/\``/(E)9)//0:9_J(8-K(8-;)8-Z)8.(:#_](E)4PLPDT]AI+^ +M`.(8-?(8-O)8..#A0>)8-P9\_P``@B4EDD@]!HO^HB4E3-F22CU&B/X,#4:D +M_PPM!J/_```V80!\_U'2``P*,J4X0M(&D@3A.C*B8T9:4O)E(XS)@LG]%@@2 +M)FD$'"(=\``,-L'3`)'4`+'5`'%.``P=NK+B*[OI$>(GA@P:#`B0[A#@YI7@ +MBH,6J`D,AH(E'B8(&*(C()(3OANJIQD"!B``@B,?XA/!&XB'GG62(T86Z0[* +MHJ(J?])$X/)D%Q:Z"J(K1+T"Y68`HD3ADB4C()F@DMD&N#F,^PP*HFD5LB)C +M&[NR8F,M!AWPLB)C&[NR8F,M!AWPXBM$X@XXX.4$%FX3@B4>&X@6B!RB(R"2 +M$[X;JJ>9#8(C'^(3P1N(@.[`%OX:'((=\+D!K0*E,02X`<'3``P=?/\+FA9) +M%>($ZMRN)BH8J!&B"@#AU@`<6(6:BT&'?"")2.#"YFH.((H0V(G0^"J(*"(((!F(!9V"Q9Y +M"Z($ZF8JVN($ZA8.#`PV8D3A#*8,"()$XQR)EQ:4H@3I/?`6"@CB!.I6?O2A +M1@#BH`#B1.F2)X&"H`B@F1"0FT&0:)."QOX6R.NB!.&2ROL6N>0+ZA9NY)'4 +M`(+*_5:(XH:._P``TD3@##8&C/^M`N4F!+@!P=,`#!U\_PP)DF4C!N7_X@3+ +MHJ`@YSHB(*(@)0L`H&H@N`'!TP`,'7S_AMW_'';&??^"!.I6B/?&Y/\,X,HAWP```` +M5HKZ#"S"2^JEN`@,+\;F_X(+ZE:H]88(``P8@DO@@@O2XDOIXDOJ%J@4XM(! +MX@Z=%AX4XBV*XL[^XFU_@@O2JJ(6N!0,/C(JCH(*?>)+ZXES@BV>@F,#@@O3 +M@D,A,@O3%H,`@BJ.X@O4XD@BXBJ.@BV7B4Z""]:"3B#B"]:,?H(JCN(MF.)H +M!N(J(>B>K)YF'DGB)((Y88*D-#(JCB#NL(KNXBYLZ1/B)((@[K"*[N(N;>DC +M!@D`````.6'B)(*"I#0R*HX@[J"*[N(NC.E3XB2"(.Z@BN[B+FKI`V8G%.(M +M8((M8:':`(#N$>"((*"((()I3(@B@B@Z!^ACH<,`"ZJ"+(,H.>(I0](L0X`B +M("#N(.#=(!9]!A9Z!M(+ZJ+*_V8MW)(EYYDQB#&`@!2),>@Q9C[NTB7=V4'( +M07S:#`OPS"#"9=V&``"W-@OR)=WY0>A!&[LW;O"(0:"($()EW;(EY[E1J%&@ +MH!2I49A19CGN+0<=\.(MB@ONQJ[_````5@KZ#"_R2^JEH`@,+\;D_^(JF.#@ +M=`:K_P```#9!``P+D=L`%H0`)A0I)B0Z)C1'P*,1JJ*:JI(*?^8I`M89`28I +M828Y"R9)/V99!<(*@!;[`K"K(*>< +M`QWP``#2`BLJW3)-"*)"*QWP````-D$`#!."`BM"`BH,`H!$P$`C@QWP```` +M-H$`8M-MXB8R#`J2I?PP[J":[JE.V/*R)C(,'-+-_CJ[FKO0K(.B2]Z"`CF: +MDYDQ!V@(,*,@L@G/)>G_R#'"#.1F'`OB(0/2H`#23N2ED/ZR`CA1W@!!WP"P +M\006#S*"TQ2"*"^RTPT62#B2*R62"3F0E@06B3?2)C*RH-2PW8+"H`#0TX#2 +MW0[";1RB)C*PJH*QX`"JH[JJY8@!HB8RLJ#4L*J"L>``JJ.PJH"ED`'B)C*B +MH-2@[H+1-0#JX^+>#=)N*,(".#=L&9(F,@P8H)F"#`^:DY+9#?)I*8)"-?EB +M!@4`TB8R#`N@W8)\_-K3TMT-PFTILD(UF/(+Z18^*O+)_A;?*0Q8B2&R)C*B +M)C4PNZ"RVVVB:S:R`CBPD016J0C"`CD'[`)&(`!':P+&'@#2)C+BH-3@W8+: +MT]+=#?(-J^(-K-(-JO#NP.>=60P-O`9R(TJ#4T)F"FI-*F9()*1N[ESL"!MC_/?#&[__-"^T/AO?_LB8R +MPJ#4P+N"L+.`HML-H@JI,,,@L*J@O0*BV@VB*BPE=@'8\A8]#J(F,K*@U+"J +M@JJC@MH-@@BIDMH.H(B@@M@-@B@L@FD<\B8R#!XZ__+?;>)/X-(F,K*@U+#= +M@MK3TMT-P@VI&\S"3:FB)C)!X`"PJH*JHTJJ)5X!HB8RLJ#4L*J"JJ-*JB5F +M`<(F,M*@U-#,@LK#PMP-X@RKT@RJP@RLZMW7K&#X,2@A#`[B3^T=\`""`CF` +M@`06^-:PE`06F=:M`KT#)0<"QE?_````K0,EW0%&JO^B)C(ZNK+;;;(+X)R[ +MLJ#4L*J"JJ.BV@ZB*AP6N@#"R?\6O!72R?X6'18,;NDA!DW_*"$=\((F,I*@ +MU)"(@@P/BH."V`[R:!R&S/\`K0.Y`2E1Y4$!\B8RLJ#4L/^"#`[Z\_+?#N)O +M'-(F,K#=@MK3TMT-XDVJPB8RL,R"$`H**`H*JP,*J@L*J`970#DB8RPB$$ +MTJ#4T)F"FI.:G%J9HFEO@B8RT(B"#`Z*@XJ,6HCB:'_R)C+0_X+Z\_K\6O_B +M;X^R)_+0NX(;(KJS2KNR"RA+S,E!MS*6*%$,"\'B`/'C`(*D1'*D/'ISBH.) +M$?KSJ`$,2#J;RIEVJ#*"*I^2R2"":7>"*I^":7B"*I^":7F"*I^":7J"*I^" +M:7N"*I^":7R"*I^":7V"*I^":7ZH$>)G?]*@C-J[VO]+=Z>7L(;8_B"B(#"S +M("4X`J`J(!WP``#B"A/BSOY6KND&!@#R)C*"H-2`_X+Z\_+?#O(O'/(/$PO_ +M5D_HD@(Y!^D"1B$`HB8RLJ#4L*J"JJ.BV@ZB*ARB"A862N:B)C+-`[*@U+"J +M@KT"JJ.BV@ZB*APE30&B)C*RH-2PJH*QX`"JH[JJ93D!HB8RLJ#4L*J"L>`` +MJJ.PJH`E00$B)C*"H-2`(H(,#"HC(M(.PF(<\B8R?/XP_Z#RWVWB;S;2)C(, +M4CK=TMUMPDW@'?"2)C*BH-2@F8*:DY+9#I(I')()%E;IW8;=_P``-J$`8M-M +MXB8R#`J2I?PP[J":[JE.V/*R)C(,'-+-_CJ[FKO0K(.B2]Z"`CF:DYE1!V@( +M,*,@L@G/Y8G_R%'"#.1F'`GH40P-TD[DI3'^?/>2`CA1W@!!WP"0\006#S:" +MTQ2"*"^RTPT6*#F2*R62"3D,#I"6!!9)./(F,J*@U*#_@OKS\M\.XF\;7)N +M-D8/``"B)C(ZBH+8;8((X)RXLJ#4L*J"JJ.BV@ZB*AP6N@#"R?\6_$O2R?X6 +MG4/B)C7R)C(,:(E!,/^@\M]MXF\VD@(XX@(YD*$$5FH2X+`$%@L2D,0$5JP1 +MTB8R\J#4\-V"VM/2W0V"#:OR#:C2#:IRTVJ`_\#PWH`@:N`)A1D@GM%JD4LB8RPJ#4P+N"NK.RVPVB"ZD+JJ)+J=(G +M\N*@U.#=@MK32MWR#2G2#2CB`CGWG6<'[L7R)_*"H-2`_X+Z\TK_\@\ILJ`` +M%H\F#`KA-`#"K_]V@#?2)C+RH-3PW8+:T]K:6MW2+6^2)_+X+4NJ@@T2YZ\! +MG)C2H-30F8*:DTJ9D@DI&[N7.P)&V/\]\$;P_P#-"^T/1O?_`.#P!!9?"[(F +M,L*@U,"[@K"S@*+;#:(*J3##(+"JH""R(*+:#:(J+.40`=CR%DT=HB8RLJ#4 +ML*J"JJ."V@V""*F2V@Z@B*""V`V"*"R":1SR)C(,'CK_\M]MXD_@\B8RTJ#4 +MT/^"^O/RWPWB#ZD;[N)/J<(F,M#,@LK#PMP-X@RKT@RJP@RLZMW7K#Z(40P" +M(DCM*$$=\```H@(YH*`$%FK0D+0$%@O0K0*]`^6C`88]_P```*T#Y7D!AK#_ +M(*(@,+,@Y>L!H"H@'?`H01WP#`S"0C4&F/^M`[EQ(F$(I>$`@B8R\J#4\(B" +M#`Z*@X+8#N)H''(F,O!W@GISJ(B8R\"*"X<0P/P>,` +M@J0\TJ1$VM.*@XD1V0'*PZ'B``Q(.I^JF7:H,H(KGY+)(()I=X(KGX)I>((K +MGX)I>8(KGX)I>H(KGX)I>X(KGX)I?((KGX)I?8(KGX)I?H@!V!&2H(R:_YK, +MXFU_2]W9$8>=JP;3_K(F,L*@U,"[@@P*NK.RVPZB:QQ&D/\@HB`PLR#EU0&@ +M*B`=\-(F,N*@U.#=@M#3@-+=#M(M'-(-$]+-_U:MNO(".0=O:H(F,I*@U)"( +M@H"#@(+8#H(H'(((%A;(N*(F,LT#LJ#4L*J"O0*JHZ+:#J(J'.7K`/(F,B*@ +MU"#_@@P,^O/RWP[";QSB)C(P[J#BWFUR;C;2)C(,4CK=TMUMPDW@'?``@@H3 +M@LC^5FBSAN/_DB8RHJ#4H)F"FI.2V0Z2*1R2"196*;*&Y/\``#:A`,'D`)*@ +MU.'E`#+2:O(C\NKBZ2&0_X+B+G_Z\LK_XD^!TB/RD-V"#`7:TLK=4DU_LB/R +MD+N"NK+*NU)+@((C\D'?`)"(@HJ"2HB"""D,)EDQ%O@-#`?2(_*RH-2PW8+: +MTMK7TMT-4FT\PB/RL,R"RL+*Q\+<#EG,HB/RL*J"JJ*JIZ+:#:(J+&4:`:(C +M\K*@U+"J@JJBJJ>BV@VB*BR2"A,':17H>M(..?*@_O#=$-)..(C\DMW\J#4\.Z" +MV#'JXDKNX@XI&]W9,>>]`L;6_X8-``"8>H().<*@_L"($()).?AZ4D\U^(KB +M#SG`[A#B3SG8BE)--;AJD@LYP)D0DDLYB&I22#5&Z/\,!\')`.'(`!P)F5'J +MXLK"R6$&!0```!MW^%&(88ON"_]+B(EA^5$6SR"AQP`JMZJ[D@N(TJ#_UQG< +M\B/R@J#4@/^"^O)*__(/*0P,%G_\#`JY`7:`I+(C\M*@U-"[@KJRNKJRVPVR +M*RR2"Q/8>P=I);(N?_@-MQ\8C%L,"P8&````@BZ`5BC_N&&8?;(K?[>9Z`P; +M1@``#`O2(_+RH-3PW8+:TMK:TMT-TBTL\@T3%V\>^(W2+H"(#]<8$=P=DBY_ +MS,F(8=(O!X(H?X>=`F"[(-(C\O*@U/#=@MK2VOKRWPWR+RR2#Q,;S$J-MQD/ +M@@@I2ZJ'/`)&Q_\]\`;5_P=K:-A_P@TY@J#^@,P0#!B`S"#"33G2(_*2H-20 +MW8+:TMK:TMT-TBTLP@T4F`&`S"#"3122"7B\&8(C\M*@U-"(@HJ"BHJ"V`V" +M*"SR"!4,&9#_(/)(%<(C\M#,@LK"RLK"W`W"+"S(?)),-1=K=8(C\K*@U+"( +M@HJ"BHJ"V`V"*"R(B/((.9*@_I#_$`P9D/\@\D@YTB/RL-V"VM+:VM+=#=(M +M+,(-%)@!8,P@PDT4D@EXK.GR(_*P_X+Z\OKZ\M\-\B\LT@\58-T@TD\5PB/R +ML,R"RL+*RL+<#<(L+,B,#!F23#62(_+2H-30F8*:DIJ:DMD-DBDL@@D4@LC] +M5GCAB&GR"#FRH/ZP_Q`,&[#_(/)(.<(C\M#,@LK"RLK"W`W"+"SXC+A\\@\U +ML@LUR&SPNQ"R3#7&=__B(_+RH-3P[H+QX`#JXOKNT@X)#`P6_4P,!ZT.Z4%V +M@#"X2AO,D@L32ZKX:R8Y)P=I#/A[@@\Y!V@$@@\UK"@7:0R8B_().8()-0=O +M`9PHU[PA!O+_``""#SD':-&"#S56N/R801MWLFD4T@X)2YF908;V_Z(."'). +M"J>W%>"GH':`#%)J%+(."!MW2ZJWMP(&^__B(_+RH-3P[H+QX`#JXOKNT@X) +M#`P6'40,#ZT.XF$(=H`PN$H;S)(+$TNJ>&LF.2<':31X>X('.0=H+(('-3WP +MK$B8@1O_LFDDT@X)2YF9@=>\*`;R_P``@@0`\DX+E[\;X+^@/?!V@`Q2:R3"#@@;_TN[ +MQ[\&H>0`QOG_`+(C\O@ATJ#4T+N"\B]_NK*JNX(+@.(+?_#P=(KN]RX"1N(` +M4DM_XB/RT.Z"ZN*J[E).@,(C\M#,@LK"2LS"#"D,#ND1%DP.#`?2(_*RH-2P +MW8+:TMK7TMT-4FT\PB/RL,R"RL+*Q\+<#EG,HB/RL*J"JJ*JIZ+:#:(J+"71 +M`+(C\L*@U,"[@KJRNK>RVPVR*RR2"Q.H$0=I%OA[X@\Y@J#^@.X0XD\YTBL' +M4DTUD@L3%VD5V(O"#3GBH/[@S!#"33F8BU))-9(+$R8Y)U)+%%)+%?(C\H*@ +MU(#_@DMW^O)*__(/*1NJJ1'WN@*&UO^AY`#�#8>\(-.>*@_N#,$,)-.9A[ +M4DDUF(N""3G@B!""23GXBU)/-=AKP@TYX,P0PDTYF&M2235&Z/\``.(C\O*@ +MU/#N@M@AZN*J[O(.@.(.?](M?_KNX-W`V7$671-QY@`,"(F1!BP`D34`D)W` +M%LD)P*^@>JJB*G^R"A/@GQ$':RVX>H(+.0P=PJ#^P(@0T(@@@DLYPB/RX,R" +MP,*`P,^@<,R`PBQ_L@P4T+L@LDP4HB/RPJ#4P*J"JJ*JJ7JJHBI_T@H3%VTK +M^(KB#SF"H/Z`[A`,&(#N(.)/.=(C\L#=@MK2VMEPW8#2+7^R#11@NR"R312B +M(_*RH-2PJH*JHJ"9@'"9@)(I?Z()%"8Z;M`9RXPB/RXJ#4X,R"RL)*G)()*1N[ESL"QKW_/?`&\/_=#OT+QO;_ +MZ&G2#CGRH/[PW1`,'_#=(-)..<;>_P``TB/RXJ#4X-V"X>``VM+JW<(-"0P+ +M#`X6;`6M#=!M(':`,$A*&[N2!!-+JOAD)CDG!VD,^'2"#SD':`2"#S6L*!=I +M#)B$\@DY@@DU!V\!G"C'NQT&\O\``((/.0=HT8(/-5:X_!ON0F842V;"#0F& +M]_^2#0CB30J7OA70KJ!V@`Q2:A2R#0@;[DNJM[X"!OO_XB/R\J#4\.Z"\>`` +MZN+Z[M(."0P,#`\6W06M#N`N(':`++A*&\R2"Q-+JGAK)CDC!VDP>'N"!SD' +M:"B"!S4]\*P(&_^R8B1+(M(."=>\*`;S_P``@@#+@\)-WH(D\I*@U)"(@G'@`(J#@M@-P@BKD@BL@@BJ +M4=\`P)G`EQ@"ABX`#`W"H`#AY@!V@!<``0,``!,"P(\"T`,``1,`(````@," +MP`&B)/*RH-2PJH*JHZJLZJJB*G^2H-0;W8(*%$O,\@H5%A@`G&^")/*0B(** +M@UJ(@@@IUS@"1I4`1A<````0$2#ED0#R)/*"H-2`_X+Z\WK_X@\)#`LI`18N +M+PP-+0^M#W:`%P`!`P``$P+`00+0`@`!$P`@```"`P+``7A*D@<3&[M+JL+) +M_5;L(,AG@@PY!^@"QH``QGX``-(D\N*@U.#=@MK3TMT-X@VIT@VHYYT(,*,@ +M$!$@90X!\B3R@J#4@/^"^O-:_X(/*?(/*(>?27*E_'!S@(('[;*@U*SHHB3R +ML*J"JJ.BV@V2"JD+F9)*J<(D\M*@U-#,@LK#6LS2#"G"#"C7',YQX``&`P`` +MK0,0$2#EN0#&]?\`LB3RXJ#4X+N"NK.BVPW""JFPS*#"W`W"+"PI;*(*J;"J +MH*+:#:(J+'SYDDH1@B3RX(B"BH/RV`WR#ZF`_Z#RWPWR+RR(;_(/$?)(--(D +M\N#=@MK3PMT-P@RIT,R@PMP-PBPL##_R3!.R)/+@NX*ZLZ+;#:(*J;"JH*+: +M#:(J+/)*%)(D\N"9@IJ3@MD-@@BID(B@@M@-@B@L\D@6TB3RX-V"VM.BW0VB +M"JD,'+T#T*J@HMH-HBHL$!$@94\`DB3R@J#4@)F"FI/RV0WR#ZF0_Z#RWPWR +M+RSH0ND_TB3R@-V"VM/"W0W"#*G0S*#"W`W"+"RR`C:R3!*B)/*`JH*JHZ+: +M#9(*J1N9DDJI\B3R@/^"^O-Z_^(/"0P+%@X1#`VM#UT/=H`P*$H;NY("$TNJ +MR&(F.2<':0S([70;R_P`` +M@@PY!VC1@@PU5KC\&]TB911+5>(/"8;W_SWPAE3_`((,-:Q(!VD,R'>"##D' +M:`2"##6<2!=I#)B'P@DY@@DU!VP!C$CGNUX&:/\;W7)B%$LBX@\)!OO_``"2 +M#PC23PJ7O17PK:!V@`QB:A2R#P@;W4NJM[T"!OO_PB3RTJ#4T,R"RL/"W`WB +M#*O2#*K"#*SJW=\J7\^O/B3^T=\"@!<>``@@\(TD\*AST" +M!EO_\*V@=H`18FH4D@\(&]U+JI<]`H95_SWPQOG_#`U&X/\`#`U&\_\````V +M80""TFJ)`8(H\F'?`)*@U)"(@I'&`(J":HB"""D,!)!R@!:8"5'F`#*@`*(G +M?[*@U+"J@JJBJJ-0JH"B*G^E7`#(`<(L\M*@U-#,@LK":LS"#"E+,QM$QS30 +MK0*EW@!2I?R,:EHRT@/M%GT%XB=_0><`\J#4\.Z"ZN)*[N(.@5`R@!9>`((# +M[1;(!)(G?_*@U+*@U+"I@M$U`*JB2JJB*B(@R:!:S!9:`,(L!!;,!.(G?_#N +M@NKB2N[2;AX=\`":'?`V00""`@D,!Q;H!PP*(%(@(+(@=H`P:$4;=T(&$TM5F&8F-"<'9`R8 +M=C().<()-0=C`:PL%V0,2(;2!#GB!#4';0&<+H>W'0;R_P``\@DY,@DU!V_. +M5K/\&ZIB:Q1+NX(""8;W_T(""*)""D>Z&6T*(%J@#`=V@`QR912"`@@;9DM5 +MA[8"!OO_'?`,"D;U_P`V00""`@D,!Q9H"`P)(%(@(*(@=H`L:$4;=T(&$TM5 +MN&8F-",'9#"X=C(+.<(+-3WP!V,CK`P;F6)J)$NJ@@()A[ACZ1*"R?T6 +M&`JX`[DBJ$.I,I(#-I)"$AWPDJ`#,F(&HD,TDD(3P@,Y!VP.DD(6DD(4T@,U +M%BT`DD(5O02M`@P,90D`F(*(/DRX@,VXD(2'?```#ERHD,TD@(3 +MT@(6L)D@D)!TDD(3P@,YL-T@!VP@P@(4\@(5TD(6L,P@PD(4H@,UD@(3L/\@ +MC%KR0A7H8^D2)CDFJ`.I(IA#F3*"`S:"0A(=\``@HB!`M"`E'0#"(P3),K(# +M-K)"$AWP0+0@(*(@I1L`XB,$Z3+2`S;20A(=\#9!`.(B!E*F4%!3@+(>$L(> +M$](>%.(>%18$%8(%@/*@6(#_@H'H``P:^O.*_Z4``JERL@6`0>H`7(^POX*! +MZ0"ZLTJ[H@M4#$=BH/M@JA!PJB"B2U3H8@PJD@6`LAX2PAX3D/^"TAX4^O/B +M'A6*_Z7\`:F"X@6`7(W@W8+:TTK=P@VL8,P0<,P@PDVLJ(*(8KARZ`CI(L@H +MV#CB"#28&)D+R0K9._@X^3KB2S32"#322C3)*LDKF1J9&Y(*.8((.>*@_N"9 +M$("`!)"((()*.8AR^(*2"#GR#SG@F1#P\`20_R#R2#G88LB"@@TU@DPU^'+8 +M;8)/-=ELV6_9$K(,.9*@_0PMD+L0T+L@LDPY^'*(@M(/.8((.9#=$("!!/"( +M$8#=(-)/.=B"R&+R#3C"##C@_Q#`P`3PS"#"33C(D! +MJ8*&N/\`-D$`#`I![`!ARF(*(#K@)J6*PB$,,"XDZB0J)(O@.V`F)/HDY^1KY +M&=DJV2[R"CG"#CF"H/Z`_Q`';`?""3D';`$,&[#@!/#N(.)*.;AR#!S2"S4, +M"IB"C$W2"370K)/(8O*@_:#@=.),-:Q>X@PY@@DTV!*2;!&R;!""3#3P[A#B +M3#FH@MEL^&+R:A*(B"T@XY8-T0TDXYR()23#7(8K(,.6"[$+),.:AB4DHU +M4D(44D(5'?`V@0"M`H+3:HDA@BCRDJ#4(=\`D(B"BH,JB(((*0P$%A@E#`5A +M[0!QQ@""IFF*@XD!>G-J8WDQ<>8`AA,``.A!G(_`GZ"($8DYD@P)P-F@V#U\ +M^Y+)_[)-$9),":E1LJ#_MQX+O0ZM`\*@`J7V_:A1R"'"+/+2H-30S(+*PRK, +MP@PI2U4;1,=R-@JR"O7 +MG,&2"Q,':1>8>X().<*@_L"($()).?A[#`[B3S62"Q,7:1B(B_((.9*@_I#_ +M$/)(.>B+TJ``TDXUD@L39CDTF'OR"3F"H/Z`_Q#R23GH>PP,PDXUZ(O2#CF` +MW1#23CF8B\))-?AKX@\Y@.X0XD\YV&O"334,#,)+%<)+%+@QLBM_PJ#4P+N" +MNK.ZM7J[LBM_L@L1J5&"H/^'&PBM`PP\I>C]J%'(,8(L?]*@U-"(@HJ#BH5Z +MB((H?PP?\D@2XBQ_\>T`T.Z"ZN/Z[D)N1,(L?]#,@M'@`,K#VLP6;.Z2S!`6 +M">[*U;A-X@L1\J#_]QY_@@L3C/B")KN):_(FN_)K!Y(FNY)K".E!#`_R2Q/R +M2Q7R2Q3R2Q;83?(,"=D1#`T+GY9S_ +MB(D;W4KMK#CR#`D+GY<^`L:0_SWP1O7_`/(FN_EKAO;_F$Z")KN)>P;U_P`` +MDB:[F8N&]/^8:XQY^'N,/XB+5N@`DB:[F6N")KN)>_(FN_F+@@DY\J#[\(@0 +M@DDYB'LI82((.?`B$")(.8B+(@@Y\"(0(D@Y^&OR#SDH8?#S!%8O\[@!#!F2 +M2X`&?_\`'?```#9!`'+2:H(G\M'?`**@U*"(@I'&`(J"VHB"""G!X``,"Q;X +M$YI2#`I!-`!BK_\QY@!V@#+B)7_RH-3P[H+JXNKJ.N[B+G^2)_+X+DNJ@@X2 +M1Z\!G#CBH-3@F8*:DMJ9D@DI&[N7NPF&\?]-#VT+QOC_&Z86^@ZR)7_@NX*Z +MLK"VH#J[LBM_TJ#_D@L3H>T`X'81]CDGZ'NXBPOY\+Z#S#NJLK(KN[(+--<; +M*B"B(,*@`Z7*_:'M`,'@``8&`.AKX@XTUQX0L@L1(*(@##SER/VA[0#!X`#R +M)7^RH-2P_X+Z\OKW.O_R+W\,'N)/$M(E?[#=@MK2JMU";422)7^PF8*:DIJ7 +M,)F`DBE_\@D4LJ9;W+^B"1,F.D`':@B"*0>""#D'Z`H7:BRHB:(*.0=J)+JB +MT@J/G*W2)7^R"G#BH-2M!N#=@NT"VM+*W;#+(&4#`!WP'?"ZH@;W__AI\@\Y +M!V^VAO+_FE*BH`#2)7_BH-2RH`#@W8(@XB#:TLK=#`QE```=\``V00`6-0N" +MQ1`6V`I0XJ"H3K(*$='?`#*@_S";P!:Y"<(*$XS\VO:2+W^9:H(O?XEZ\B]_ +M^8H,#,)*$\)*%<)*%,)*%D(%"?A."X2'LD7:YMT"=H`>4-V@F%V(:9E-G&B( +M>9RHV(D;S*P-0@4)*MP+A(>]'X;V_P""+G^):L;W_YA-@BY_B7I&]O\``)(N +M?YF*1O7_G%10Y*#Y/J(%"5#:H-@]?/P+JL)-$:)%"3<;":T&PJ`");+]'?`= +M\)AJC&GX>HPOB(K,^-K&DBQ_F6KR+'_Y>L(L?\F*P@DY\J#[\,P0PDDYF'J" +M"3GPB!""23G(BI(,.?"9$)),.8AJ@@@Y#!F`@P16>/'2U@:23>D=\#9A`"DA +M(<8`#`K8(2HC@B)_DJ7\TBT3,(B@FHBI2!9-!D'?`(+3:IIS>1&),7'>`,8. +M`+(A`L(B?]*@U*(A`-#,@M'@`*(J`,K#VLS=`V69`*(B?[*@U+"J@K'@`*JC +MNJHE3/_8`<@AV%W2;!.<#:A-\>X`V0'V>NKP^J#X#Z`/`)*E_`P*@B)_,(B@ +MFHB(2*QHF"'2H^3:TZEYJ4FI":)MAI(I#Q:Y%^+)_Q;>&?+)_A:_%3"C(*4U +M_QWPJ"&H^K@M%DH5#!S8(0P._0/83>59`*@AF`$,&[)*-9@IF6KR(G^"H-38 +M$8#_@H'D``P<^O.*_^(/@8(/@/(/?PP9X.F#BO_W+@*&UO_"3>T&U?_H,>(N +M\O*@U/#N@NKC2N[B#BH,!E*@`*S^HB)_LJ#4L*J"JJ.JI7JJHBI_Y8W_R#'" +M+/+2H-30S(+*PT#,@,(,*E+%!&+&`<``JJ.ZJB4V_Z(B +M?[*@U+"J@K'@`*JCNJKE/?\&HO^R(0+"(G_2H-2B(0#0S(+1X`"B*@'*P]K, +MW0.EV`"B(G^RH-2PJH*QX`"JH[JJI3K_!I7_`,@AHFUZJ2Q&IO^M"[T#934` +M1JO_LBUZDBUYHFU]^"&PR4/`N\#`F<"2;7FR;7KH#YD?@BUZB2_I/\:9_[@A +MHFUYJ1M&E_\``#9A`-+2:H(M\N'?`)*@U)"(@HJ"ZHB"""D,#!:X!3'&``P+ +MH>8`,#*`=H`7``$#```3`L!(`M`!``$3`"````(#`L`!DB-_\J#4\)F"FI*: +MFZJ9DBE_\@D2@@D4C`^U&%0`] +M\$:F_P"<&.B)&]V<;O(*"M`L*@`B5I_5<4!`P" +M'?``DB-_HJ7\()F@JIF821:I_@P2'?`V00`,"'("*@P)=I06>E)2!0@;1RPF +M-Q4.?0D;B&>T`7T$/?`,$AWP#`(=\#9!`$("*C("*T`CP$>S!"+"(AWP'?`` +M`#9!`)CRPJ#_4>\`%GD*0?``8J97#!I*(R89&&8I)9(B'3J9:IF""74,*["( +M(())=08$``#2(ATZW6K=L@UUH+L@LDUUDB(=.IEJZ>(.=5IS9CY9LB=EL@LT +MQQL4K0/"H`+E7/VR)V6M`PP\L@LT)5S]LB(=#`\ZNVJ[\DMUHB(=.JI*JO)* +MC((B'9*@U)"(@FK#BH-:B/)HFN(B'7S]#%(P[J!*[M)N(2),BAWP#&)*R:), +MC!WP6G.R)V6R"S3'&Q.M`PPLI5;]LB=EK0,,/+(+-.55_0Q2'?`````V80"] +M`B+3:H(B\G'?`)*@U)"(@@P%BH-ZB(((*PP$\J#^%N@,#`UA\0#ATP#!Q@"" +MH-3JX\K#1B$```"2"A.(>@=I$)((.?"9$))(.8AZTD@UD@H3%VD3B(J2"#GP +MF1"22#F"*@C22#62"A-F.3"(>I((.?"9$))(.8AZTD@UB(J2"#GPF1"22#F( +MBM)(-8(J!I((.?"9$))(.8AJTD@UTDH4TDH5HB+R@J#4@*J"2T2JHWJJH@HK +M&U6"H-2GM3.B+'^`JH*JHZJD:JJB*G^8&K>9T9(N?[DA5OGUZ0')$;T#Y4G_ +MN"'($0P-Z`'RH/Z&[/\`'?```#:!`&D!22&]`ED1.5%2UVKR)?(,`R*@U"#_ +M@B'?`$A1^O? +MSB8;1V8KR,(E\M*@U-#,@LK'RJ:BV@ZHRI(*%>+)_18^$>+)_A:>$O@AD?(` +M%H\9FIR2*7\661>@R@\]QZ4Q@T`B#&"*'^Y0JIJ+:#JC* +M)3/_N$&&QO\`R#'"+'^Y0Z"*'^Y0JIJ+:#JC*Y2#_N$&&C_^B)?*R +MH-2PJH*]!ZJGJJ:BV@ZHRN4F_[A!AHC_`,@QPBQ_N4',C+T'I27_N$&&@_]E +M'?^X08:!__@!B#'8.AOO\.^SX.$AX-W`%BW?@BA_N4',N+T'Y2+_N$%&>/\` +M``!E&O^X089U_QWP`#9A`,'&``P$LM-JRL/2+']Q\P"2H-20W8(+HMK3>MVB +M;7^"*_+RH/YAWP"0B()1\0"*@VJ(@@@KX=,`#`(6.`SJXPP-1B```)(*$XAZ +M!VD0D@@Y\)D0DD@YB'K22#62"A,7:1.(BI((.?"9$))(.8(J"-)(-9(*$V8Y +M,(AZD@@Y\)D0DD@YB'K22#6(BI((.?"9$))(.8B*TD@U@BH&D@@Y\)D0DD@Y +MB&K22#722A322A6B*_*"H-2`JH*JHVJJH@HK2R(;1*>T.I(L?Z*@U*"9@IJ3 +MFJ):JJ(J?WJ9DBE_B!J'JD!R1&]`V42_\@1#`WH`?*@_K@A +M1NO_'?```#9!`+T$<=,`\J#^8>8`@@0*G0.H>0PCV/GPRA$;S-"LDR"JP`LJ +M=I@LHBL4P@H4K&T';`R""A7H>@?H!)A.)QEK%VP/P@H5F(H7[`?H22#NP!8^ +M'$N['?``9CSW@@H5F&I6^/Z2*00GF>FE_/YZI:(J?U8*_JT$L@0)#`,,!Q9+ +M,':;%[`!`[``$[++ZK+;`[`!$P`@`+`"`[++`\M4,DB_?F6R" +M+]^)?/(OW_)L"`P)DDP3DDP5DDP4DDP6T@0)#`_H2@N-A[,V,",@HM4,0-*@ +MF%V(:9E-S$B"*M^";`:(>S-C`C(*+5 +M#$#2H)A=B&F93B,W![RU0R2+]^9;((OWXE\\B_?\FP( +MX@DY@J#[@.X0XDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TYT-,$5JWK +M#!^"IFF*A?)(@!WP(<8`*B6B(G^RH-2PJH*JI:JG:JJB*G^8:I()-+*@_[<9 +M";(*$0P\K07EQ_RR(G^2H-20NX*ZM;JW:KNR*W\,&J)+$H(B?Y"(@HJ%@M@- +M,F@H%D2\PL00%NR[2J?"*@2R#!'2H/_0V\`670GB#!.<'O+5#)(OWYEL@B_? +MB7SR+]_R;`@,"9),$Y),%9),%)),%M($"0P/Z$H+C8>S-C`C(*+5#$#2H)A= +MB&F93(L"#WPW![RU0R2+]^9;((OWXE\\B_?\FP(X@DY@J#[@.X0XDDY +MZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TYT-,$5JWQ#!^"IFF*A?)(@!WP +M````-F$`D@0+K031TP"\^0PO8>8`R//BH/X,`W:9,;(J))(+%*RL!VD0@@L5 +M>'L':`B")P4@B,`6.`T7:1"2"Q47:0J8BX(I!2"(P!8X)$NJ'?!F.?B2"Q6( +M:V8Y\(A8)YCKD@L3!VD2R'NB##G@JA"B3#F8>S))-9(+$Q=I$XB+\@@YX/\0 +M\D@YPBL(,DPUD@L39CDPF'N""3G@B!""23GX>S)/-?B+P@\YX,P0PD\YJ(LR +M2C6H:Y(*.>"9$))*.8(K!C)(-3)+%#)+%=J5DBE_5KGWK03"!`D,!PP+%GPS +M=IP7P`$#P``3PLP=PMP#P`$3`"``P`(#PLP!V$K8;=A=2ZH@W"($()'.<(J),A\,DPUPBHDL@P4\+L0LDP4LBHDD@L5\)D0DDL5DBHD +M@@D39C@2B&G""#G@S!#"2#FR*B2X:S)+-=KEXBY_5D[OLBHDD@L3\)D0DDL3 +M@BHD@@@35OCMK03"!`D,!PP+=IP.V$K8?=A=2ZHG'08;=TN[X+<1(<8`*B6B +M(G_"H-3`JH*JI:JK:JJB*G_H>N(.-+DA\J#_]QX+L@H1##RM!269_+@APB)_ +MDJ#4D,R"RL7*RVK,PBQ_#!JB3!*"(G^0B(**A8+8#7)H*!:4YM+$$!8]YD"K +M@,(J!+(,$>*@_^#KP!;^(?(,$YP?@M4,TBC?V6R2*-^9?((HWX)L"#),$S), +M%3),%#),%M($"0P/Z$H+C8>W-"T'HM4,0-*@F%V(:9E-S#B"*M^);(AYS%B8 +M38(JWXE\V(D;__HGS#V"*M^)C-($"0N=ES+/G'U`C:#I.*($"4#ZH/@_PJ__ +MHLK_PD\1HD0)DJ#_D)O`%HG"[(*$0P\K07E@/RX$<(B?Y*@U)#,@LK%RLMJS,(L?PP: +MHDP2@B)_D(B"BH6"V`UR:"@65,[2Q!`6_B,W"[RU0R2+]^9;((OWX)L +M!_(OW_)L".().8*@^X#N$.)).>A\T@XY@-T0TDXY^(SB#SF`[A#B3SG8;-(- +M.=#3!%8MV0P?@J9IBH7R2(`=\)ALC&G8?(PMZ(S<+O+5#)(OWYEL@B_?@FP' +M\B_?\FP(X@DY@J#[@.X0XDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TY +MT-,$5MWK#!^"IFF*A?)(@!WP(<8`*B6B(G_"H-3`JH*JI:JK:JJB*G^8:I() +M-+D!PJ#_QQD-L@H1PJ`#4*4@Y63\N`'"(G^2H-20S(+*QBU0Q`TJ"878AIF4W,.((JWXELB'G,6)A-@BK?B7S8B1O_^B?,/8(JWXF, +MT@0)"YV7,L^(L"#WPW![RU0R2+]^9;((OWXE\\B_?\FP(X@DY +M@J#[@.X0XDDYZ'S2#CF`W1#23CGXC.(/.8#N$.)/.=ALT@TYT-,$5NWQ#!^" +MIFF*A?)(@!WP````-F$`X<8`B/3X=#D!%N@<,M5JDB/RHJ#4H)F"H=\`\'\1 +MFI6JF9()*AMW#`\6:0<,#-'>`.!E@"#GP.+._W:`5K(F?X*@U("[@KJUNKS: +MN[(K?X(+%)A[!V@%DBD$YQDYLB9_@J#4@+N"NK6ZO-J[LBM_&_^""Q1+S)B+ +M%V@%DBD$YQD;LB/R@J#4@+N"NK6JN[(+*K>_%8;H_PP:Q@,```PJ1@(``.IE +M(.?`"^X,"@P,.`$,#?T%O0,E`/_")G_2H-30S(+1X`"H],K%VLR2#`H6R@H, +M'@OZ("?`"R(,"O"N@W:9'-(L%.(-%/A]!VX$@@\UC-@7;@?2+0B2#36\R4O, +M'?"X3R>;ZPP;.6\Y';)/-9(L%*#3D-E?@@D5L(@@@DD5TBP4X@T59C[5B&T, +M'_)(->(L%.AN.5XY;AWPF$TGF;SB+!0,&YB..6TY'K))->(L%*"#D(E9T@X5 +M#"_PW2#23A72+!2R#15F.Y28;0P8@DDU\BP4^&\Y7SEO'?```"`GP`LB=ID, +MTBP4@@T4Z&TF.`-+S!WPD@XU5EG_J$XGFO"(C9A]#!\Y:#EI.6XY'3E8.5DY +M7O)(-;(L%*B+N'NB"C6B2S62+!2(>9AI@@@U@DDU\BP4##NR3Q4=\'T/8<8` +MK0.]!>7=_FIE!K/_`#9!``P#,D(3,D(4,D(5,D(6,D(2.6(Y9\E)2%(Q)0$%!8&%!8E(5,E(20E(3<@(XN4*YD!V`',O0`XIC`0ICD! +M^`'P5I.8`0M55BD`5O7[J`&L*O'Z```_IN`0I@P+Z0'8`<@!N0'0U13`P$32 +M0@'"0@`H`1WP`&D!*`$=\```-D$`G(R)[S!^@!"T@8R`P$R9"0`/*;@ +M$*8,&_'\`.#05.#F!/HBTD)]XD)\`#RFH!"F`#RFD!"F#`92H`#"H(0RH`+@ +MJA&0AA2@B"""4C]"$C]"8B%VHSZ")T.B(B%:B(+8`M(8`FT!"FPB8> +M@J0PTF/+)@PDBJ+B*F$]\!:^$[(3;)(J88(J8K"9@O(CRY"(@(+(`8LM(.\BM=C-_"))W"+`7"9)V2*UU6"?_2!=86W4P` +M.J;P$*;R1=<`.J;@$*;B1=B2)":2"4R0D006B22B`_*BROX6^B,`-Z;`$*;" +M8R^R(R_V.P(&C`""1>D,8AWP``#2*F)6W>M&M?_B!=(6#O"B)<+R)13PJA&@ +M_\`6'^^B912"1>`&NO\`P@7M5ESMT@7(5OWL@DL_TM(%XAW:#`H;[A:^[,T" +M?/[B;&KR'=H;JDO,&__W.O!&K?\``+(D);B+#"Y+NX"[$>"[(``[IJ`0II(# +M^J)C-)P9\J0PTB8C^L+"+)\@W:#ZW<)MB=(D)=(-.:*A`M#1!!8-(7)DG')% +MT_(D)9(DG))D)/(/.;*@`"=O"-(#]\*@`="\@_(#^K)#]IPO`#>FL!"FLF4E +MDB4E/?"V&0*&Q_^R)"7(FQ;,-K(D)=(K"=+-_Q:](_(D)?B?9A\8PB8CLJ0P +M(,RPNLQR;&V2)B,@F;"ZF7)I;M(D)M(-31=M!0`WIO`0II(#\F89"``ZIK`0 +MIK)%T<(D)L(,3%=L!](#\CWP%MT<\B0F\B\1C'^2`_*2R?\6R1L,"\(D)K)# +M^=C\8J0P:F(;W=)F8\(L$+(#\AO,PF9D%DL6"YL6^16R`_(F&P)R9F3"`_(] +M\&8L`G)F8](DG!;=';@E\+L1D@/R\?T`DLG^%EG<`#JFD!"FDD2.D@2.%FG; +MN6$,#`OKZ3'A_@#2IHC:TNKB`#>FH!"FRK+ZNZ)+8*"@=+9J`@9I_YSZ)AH= +M)BHM)DHV)EHS&\Q+[DO=DLK]%CDUMMS,@D7IQEO_`#>FD!"FN#&2;>&7N]P& +M7/\````WIK`0IK)M'L;R_P`WII`0II)N7\;O_P!R8R\`.*:P$*:B)":H"KJJ +MHLH:EKK;/#NGJP+&;/_")":B9F"B8\G"#$S`QT$6O!$`-Z;@$*;B9<'2)<&V +M/0+&8__R)<$+_Q;?-P`XIJ`0IJ)E/I(E/GRJIZD"QES_LB4^IGL"AEK_`#BF +MT!"FTF4_PB4_IZP"!E;_XB4_YGX"AC0`!E/_````.J:0$*:21=/R!=,6SQ^] +M"``ZIM`0IM)%U,(%U,"^D[)DG(9S_P```#JF\!"F%F_I`#>FP!"FD@7.PF9C +MLB9C"YD;N[)F8U;9YP`WIO`0IO)F9-(F9!O=TF9D1IK_#!O&C_\`D@/R"YE6 +M.%/`/(3;)(3;B(C$Z(C1X(#][`B`:"@-``(0)"0L:/W%@`8 +M0))3;](3;Y(C2((CRM!O@I"0-`O_D_<:8E-P"]U`W1%@8/2#]Q[`_Q&!PP!R +M8T<@_R``9J$A3@!B4W'PW2#2;DF"R/^B(L,62A\62!^R!>H+B&8K[@P-'`[R +MH&`<"4P#_(``_IL`0IM(F(_*EW"#=H/#=@,)M(I(D)I()3$=I!9(#]Q8Y&+(F +M(\*EW""[H,J[>0O&%/]R1=@`.J;0$*;21=G"!=D6'+,,"O'_`!P\X>4`^O+Y +M(>HBJ0&GO`T,LAWP`')DG')%U,;W_AR+B"$BPA@;FID!*4&BR!BI$:DA)2PD +MN$$,&``WIM`0IK9]`L9#`-)K@28=`F8]"@`WICWPH!"FHFM]9BT(`#>FP!"F +MPFM^)CT"9FT(`#>FX!"FXFM_9DT(`#>F\!"F\FN`PB2=%LP.N%R,6\T+N%M6 +MB_^8$9E[ +MVT9O_@`WII`0IKE1DFU>AO+_```WII`0IKE1DFZ?QN[_``!6*.$,*J)%ZN4L +M!,:!_P```')E/W)E/L9@_P``@D7I#&(=\```.*:P$*;")B/2I=P@S*#:S+D, +M1K+^Z!'B9)U&QO\``#:A`%T"#!]"I6!RT@TRT@:"`].2!XVR)Y)*0N(D4\A[ +MV#NB"R'`F<#@W<#0WY.0GY.`RL#`SY/0F2#`F2",^(S:H@/4@@LBH(C`@(^3 +M@)D@LB>2P@/6@B1,^$NB"R`,'H#_P,#:P-#>D_#^D_"9(-"9((SLC,K")$VH +M:\"JP*"NDZ"9('S\(4X`XB0\#!L,!MT&X-N#T-D@D0`!%AT$@:8`8F,8V"7A +M-0#B8LB";5^"8H+R(Q2,S_(G)?(//\Q/8F,4LD/@@@/@"X@6N!NB`^$F>D"M +M!:4[`9R:+0H=\```T@/@9AT1XB5CC+YB0^"E(_K&````8F,44*4@@B3J\B0\ +M\F$&\F$%@F0T)=4!%HH`#&(=\`QR'?``D@/.)BD8H@>.F8&,BJT%#`OE.`-6 +M^OV8@;(D%[)D-@O)%OPSDB0V8J#_%ND'6:'13P#"U5QR80EV@%)2+-D,`O(% +M->CU4@4TD/\1L.X1)AE"@BS:DLG^B\RB"#2X^(((-6!ZP#"[$8"J$1"($7"B +M@["J(*"((&"UP`P*L%J#X'4@<'\@@'<@9%V@%)2+/P,`O(%->CU +M4@4TD/\1L.X1)AE!@BS]DLG^B\RB"#2X^(((-6!ZP#"[$8"J$1"($7"B@["J +M(*"((&"UP`P*L%J#X'4@<'\@@'<@N8X_$!`<*@`!8I!?#5@':`'X(M;J(D +M,)@8H)G`F?N2)#"(*)"(P(G[Z.,;S$O=Y[PL1O;_``":U=(M@<)C%Q9]':(G +M)[T%97/[#!NB0^'B`^'BSOH6+N*R0^$,)D/V7P(Z)D%K(4JJ(DZN7R([%/`/#Z$?)D%8(D/Y*A +M&)J5!V@(#!JB285&`0``#`S"2872`^<631;B`^I67MKR)R;R#TP7;PB2H`8` +M.::`$*:B`\X+JA;Z&`S\PF$$P"``D<,`#"62R?_2*T,6G146F17B`^H+F68N +M[OA!P@/2#/CPWQ'0S"#"8E2B)#_")!62)!8`JA&`S!'`F2"@F2"28DB''PSX +M4>AA(/\1\.X@XF)'@B,H)D1T,P1P*H@H)D@DFM*B,@,"LR8 +MXB]!26U^PP;HD/A!HG_`+('CQ:[`%"E +M(+*@`>4"`U8*R,(D&,)D-P8I_Q;.Y@O>H-T1TFLX1IC_``"R%*JB).JB9#\E +MV".B9!:R%*JB).JEVB.Q3P"B9!7&GO_B)R7B#C]6'NF2)#_R)#P,&)#_P/#X +MD_)#X$:?_P``H#!JI08J)B6&) +M44;4_]EAXA->#'_Y0>#A0>KMZ5&&S_\```!67/#")Y_&O_\7Z4_2+!$6W0CB +M+!`6?@BB)R>8#J@*R7'X#9":P)"18/"JP*"A8*>I,K(36J(A!O"[$:6_(ZD1 +MLA-:J&&ENR/2$UK($0Q.T,R"Z4'*RLEA!@X```QO^4$&MO\``+(36JAA/?#P +MNQ%EO".I(;(36JAA9;@CTA->XA-:R"$,7_E!X,R"T-%!RLK:S,EAL4\`R'&( +M88E1QJ;_#&(,&9)#Z1WP````-@$!#"9!`P'RI4`RTFJB(_+Z4I(5O""JH$JJ +MPBIXTJ8,<4X`QYD\DBIZXA6ZEYXSPBI\LB4ZXM(-XF$0P+O`5NMF\BXE@BI^ +M\@\\VI*9\8>?&XCQDBJ`@@C@D(C`%E@RA@(``)+2#=JBJ?&281"M`B6I_`P+ +MX>``\00!TB/R@J#4^O*`W8)B3UO:TNK=P@T(\F$.G0UVG!F(29PHJ&C(>(P* +MN6B,++EXB$GXB(P/N8A+F;)-#<(C\I*@U)#,@LK"PMP-LDRMHB/RD*J"\B$0 +MJJ*BV@VR2JB"(_+R+R60B(*B(^J*@I+8#9()K:FQ\@\\K%GJZ-(.")T.=IT9 +MB$F<**AHR'B,"KEHC"RY>(A)V(B,#;F(2YFR3@V"(1""*)*"""/2K\`+Z!:^ +M,I+(_A99,DJ2#`K"*84,"Q;\3^(C\H*@U(#N@NKBXMX-\DZL@B$0@BB2@@@C +M804!XJ"`PLC^%OPS%L@SDLC]%HE50B/RPJ#4P$2"2D)"U`VR1*GR(_+`_X+Z +M\O+?#K)O'.(C\L#N@NKBXMX-LDZJTB/RP-V"VM+2W0VR3:NB(_+`JH+!WP"J +MHLJJH@HH62$,!!8J!PP%<>$`8=X`HB/R(*J@HMIMHBH^H*2`H*JP(*J@<*J` +M9"*AJ":7B"*AJ":7F"*AJ" +M:7J"*AJ":7N"*AJ":7R"*AJ":7V"*AJ":7X,2+)D?RJ=J-%JF4M$IY2N8B/R +MTJ#4T&:"\34`:F)BU@WR9BCB(_+RI4`@[J#Z[K)N,\(C\M#,@@P:RL+"W`VB +M3*V2(^M\"-(5O("9$))GQ&(CZ\#]`8!F$&#_(&%/`/)F1N(C\F$#`2#NH&KN +MTFYXPB/RHA6Z(,R@:LRB;'J2(_+R(1"")3H@F:!JF8)I?/(O)8(C\NCQ\@\\ +M((B@:HCR:'[R(_+B#N`@_Z!J_^)O@-(C\@PF&]WV+2"1!@$@C:`,)M"FP)J( +M=IH0LFA[LFA]LFA_LFB!LFB#2XA\#B(5P)(E.J(5O-(5O<(5P8(5NH#=$0#\ +M$=#8(*"(@I)GBT(E.@"($8#=($!$`4`B("#_(/)GQM)G4](CZ\#$0<#,`>#= +M$-#,(-%/`,EMHB4?#`LM!O8J`2T+XB4@#$CV+C:"(1#X\8(H)J(?5)((3("J +M$:"K()"1!)"2(*"9())GC"((3?(/VR`@!$#_$2#_(/)GQPP"'?``HB$0F/&B +M*B;"&52R"DR`S!'`R""PL02PLB#`NR"R9XRB"DV2"=L,`J"@!$"9$:"9())G +MQQWP2I*R*846JS_"(1#"+"6B##F"'!?B'!:@H00;B!ONP@P^@.Z"#!C"S/?) +M4:!HD^"V@BR^L+N0D+L1YSP"QF\`@0>[`K)CY<(A$,(L)<(,/<+, +MOA:,,XF!R/&B(_*RH-3"'%FPJH*XH:JBHMH-P+N"H@JHLLL_T+L0BJJPJH), +M#;(C\L$(`5DA(+N@RKO"H`&E:@-8H;C!@LH_>"&A"0$@FZ!R%[^PL'2JF7!5 +M@G*OP%+%/W"($'!5$''<`)EQ@FE_>G*M!V71^HC!4F$1DB/E&XB)D9>X(TAQ +M4B$)PB1_DB$1K0=0L'3*F9)D@.7.^M(CY4+$!%+%`=#\$(`=(A"X(C[$(CZ[(C\J*@U(!$@J"K@M"`8""[H$!-@,J[JJ+( +M@:+:#:(*J`M$@$00RJJ@I((,'&5?`XC!N)'`B!&*@FJ(HFA]PB/EQ[L9=H`2 +MHBA]JJ2B:(&2(^4;NX+($)>[`X;Y_P#"(1#"+)(,&[),(PP+ALO^\B/R#`N" +MH-2`_X+B*8;Z\O+?#>)/K,:]_AP*PB$0PBPEPBQ^'`[@JF.V+`?B(_(]\!8^ +M);(C\N*@U."[@K"R@++;#8(+J!8H(:>X"^(A$.(NDL*@`\).(X(C\K*@U+"( +M@HJ"@M@-L@BH]SL"!J+^\DBHAJ#^VL+)\49M_@P+#$W22",&JOX``$(C\H*@ +MU(!$@HCQ2D)"U`V"".!"!*@+^!M$0$!T%O\@LJ!@@.N#Z3$,'$P-HF$2Z#&R +MIIR(\?(C\I*@U((869#_@KJR\/*`@.Z"\M\-\@^H@J_`XLX_@.X0\*K`H*Z" +MY4P#V#&Q"0$@E*"(\?+*/^*OP!NDJ1'@_Q""&%FZF2JT\FE_@-V"\B$2TLT_ +MX-T0&\_)0>+;#T).D,>Z18T)P0H!K01`[\#*NP=N$$N)PBE_J!$;N\K-PFF` +M0DM_X)%!/?!VF1V2*'\;RHN(FIV2:'ZB2X"2*'XKJBN[FIV2:'_"2W],6:%/ +M`-CAR$'`M!&ZLFJ[PDV?@BM]#`S)ZIG:@L@_DJ_`D(@0@FM]HB/LDB/KV+&@ +MF8+0X&":W0O=X-T0]K0%X4\`@FX/F$&($9>X)X*@`$"OP'::'DJXP,L1RL)J +MS.(L?1N(&[OJ[>)L@?:[!)%/`.GY/?#"(_+2H-30S(*R(1#*PL+<#?),J+(K +MD@P:HDLC#`N&2_[BH,#IH<8;_[CQJ*&R&UFPJH*)@:+*/]"J$$8V_\(C\N*@ +MU.#,@@P*RL+"W`WR3*@&,?X`#!BH\0P/#`RR&EG)P?EJL+L1LLL_T+L0LF/[ +MJ&JB:8/R8_Z&#/\``((A$/)+J((H)8(H?O8H`D9Z_X(C\E8XWN#(@LK"PMP- +ML@RH&[NR3*@&=/\`B/&"&%D;ZND!@,B0H,P1L(@1@L@_RLO`[H+"(^30B!"` +M[I#GO`*&8/^H`49?_P``DJ#`F3'&>_\``))A$_)A%*$+`;AAY24@(_(A%)(A$]*OP+AA!C/_DF$3\F$4H;``N&$E'R/R +M(122(1/2K\"X808L_Y)A$_)A%*$/`;AA91TC\B$4DB$3TJ_`N&$&)?^281/R +M812A$`&X8:4;(_(A%)(A$]*OP+AA!A[_DF$3\F$4H1$!N&'E&2/R(122(1/2 +MK\"X8087_Y)A$_)A%*$2`;AA)1@C\B$4DB$3TJ_`N&$&$/^281/R812A$P&X +M8646(_(A%)(A$]*OP+AA!@G_```V80`,!``TIF`0IE+2!F)E(C(E(@P6MH," +MQFP`B*6,>``TII`0II)E(Z(E([:*`D9G`'*O@++2`KDALBOOPJ$"#`06.PR! +M%`'A%0%)$8J"@*!@JK@`/*:0$*:0D'06>1<`-J:0$*9WJ0+&6`"FZ0)&5P`` +MV2/26!\`-J:0$*9WJ0+&4@"FZ0)&40``^2/R6-\XI1;S!0`\II`0I@P/#"TJ +MN^J[D)!T=JU+O#D`-J;0$*9WK0(&1@"F[0*&1```W2/26Q\`-J;0$*9WK0(& +M0`"F[0*&/@``/2,R6]^&!````#(E(PP-TEO?`!-``-:ATEL?&_\KNS@A^!%K +MB#(C[QO_\F$!-[\"!M+_@@7."XA6J`N8(9(I\`P$%@D+@18!X1<` +MD1D!@=X`<1@!8=\`70(,'PP"^4$I$2'A`&IE>G6*A9J5JJ6I,9D!@F$"R#&8 +M08(&**(,@+)L4K),@;),@K),@ZJ9F4&F&"H,`T(A`J(G?ZJCH*JP4*J@(*J` +MY1_^HF1O#`S"9(_"9'^R!B@;,TM$MR/92W?H`0P)P34`L1H!B!'8(?*@U/IF +M^MU:J+JJV2$;B-@QB1$,"\)M'I)*@/K=V3'GG87H0:8>1:T.D1L!#`C@\"2: +ME7:O!H))@!N9&XB@(R%VHBF"28`;J"NX.\A+V%OH:_A[*(N9HDEYLDEZPDE[ +MTDE\XDE]\DE^(DE_BXABH(PAX@`,#0P(F$%!'`'AXP`RI$3RI#SZ]3HUZN5* +M18"94X)$F@Q(DD2;6ITJF6KN:MVBH`!VJ#*")!F2R2"":7>")!F":7B")!F" +M:7F")!F":7J")!F":7N")!F":7R")!F":7V")!F":7X,2*)O?UJ=*IE+_S>? +MM,+5!@P+LDSA'?``-F$`0M(&@@36#`R,&,)$X3$=`3HRHB,@8M(,%FHL@B9E +M@@@Y@(8$%J@KD@3.9BD'K0(EY?_"H`!2TFVB)"1RT@6,^M(E,K(G:SWP(-V@ +MTMT&LFT5XB9EXBX))AXN(*(@Y5(`PJ``DB"M@Y(E,K*@U+"Y@KJRLML.LBL<%OL\%DI"#!W20XGB`XD6GCWR)3(@ +M_X#RWP;R#\R\O[(F9[(+-(*@_X<;%ZT"PJ`"Y2[ZLB9GK0+"H`.R"S0E+OH, +M#/(E,BK_\M\&PD_,XB4R?/T@[J#BWFW2;C:2)3*BH-2@F8*:DI+9#L)I'((E +M,L)#B2"(@(+8;<)(X,)$X:'<`*JB93/Z#`PL"Z)$RZ"@=*>[!L)$RT8*``#` +MBA&*@H+88,)(@/($R\#_$?#R@/+?8,)/@>(E,M($RR#NH.+>;=)N.9(E,B"I +M@*+:;:(*X&8:"R"YH++;;;(K.;)$R]*@=0P/LB9EH@3+DB;<#!B)$9+)_J"J +MD*)$T*($T.(+/9#X@_JJYST*TBM^]BT$XJ``Z1&R%&#"%&'2%&+B%&.!'@%< +MC_#Z@J(FW/#R@(#_@"7N_;($RRP(MS@%G0N&````#`F21,N0X'3B2C32)M[! +M-P#2#0&R+/`672GQ'P$]\/"[$((F99(:$K)L\-($R_(47,(C'<#=$=K2TMU@ +MTBT?L4\`XAH3VLS":T3")2O`_P%\#=#,$,#_(/)K1L(E*_%.``#N$=#,$,)O +MQ-($W\BDHF9G(-T!0,P!@@@YP)D@D.X@@($$,(@!@-T@X-T@V8O")S+)&I(G +M,YDJ@BTB,=ZMW2:T?"(QZB(QT, +M`LJJHF_%'?```+(E-?++@1:_PM(E,B#=H-+=;=(M-H+-@1:8P0P*UYL"!@K_ +M\B4N#![PKH-&!_\``!9*PRJ)@M@&@@C,%IC"#!F20XE&"/\``%8*R88T_]@1 +MC$WB)3-6_M7X(H$A`?(O.H"[(/#P!%9OU9(7X(*@@)8+9(+$SWP)AD?LLG^5IN\TB;<9AT9!O#^`.(G +M-ND*!H#_@B`/(J\B#_H,K_XB\=TB\?Y[T1T)[`L(%!E[@(V!^PO<"&`@``LBKR(+N@ +MRKNX&]($XQ8])N($Y!9>)/(J\B#_H/+?!O(O&?K[\F:S\F:_DB0OTBKRZ#3B +M9K8@W:#*C8(H(Y<8"(+=!O(FZ_)H'Y(D*!9)\>(J\B#NH.+>!M(N&=)N&\(J +M\B#,H,+X.F3DB=_J#D6^A'2T@K2+>78/0P*%BT1^`D,"PP#=H`,NH^("!NJ2[LZ +M.->Z!`;[_P``%JX%LB=_"ZZI`;(K`Z58(K(G?ZD1PB7RJ`')(;@[950BPJ7P +MN!&((0P-,+N"((B@@M@&HF@=\B=_XB7R#`KX#R#NH.+>!N(N'7:`#*J/B`@; +MW4NJNKC7/@8&^_\```P+DB0HS%FB)W^H&KJZT@3C%MT,X@3D%OX*@B=_\B7R +MB"@@_[#RWP7R+SFZB(K_\F:S\F:_TB7RLB0OZ#3B9K8@W:#*W;)M(Z(E\I(D +M)2"JH,JJF4I&0O\``/(J\B#_H/+?!O(O&?K[\F:R\F:_AFW_`)(J\B"9H(+9 +M!H(H&9+9!8J+@F:RDBDWFIB29K.0B$."9K:"9K]&8_\,`X;`_PNIHF:_QHG_ +MLB:_LF:VLF:RQB3_#`Z&J_\``-(FO])FMM)FL])FLD8?_P#B)?(@[K#BW@7B +M+CFZ[N)FLN)FO\;4_P"")?(@B+""V`7R*#F2)W^Z__)FLI@I@B@Z^IF:B()F +MLX#_0_)FMO)FOX;)_V+2`T8@_P``@MD%TF@]\BKRXB:R(/^@\M\&XF\;QAG_ +M-F$$LJ780=\`#!B2T@JB*>5M`I)A?:B*(M)JDBGD2ZH`&D``J*$6*73"(O+2 +MH-30S(+*QDK,P@PJ#`G,',81`[!6@'+6;8*@`':`I+(G,L*@U,"[@KJVNKBR +MVPVR*SSB"Q0;F<@[%BX'TB4UQ[T)H.S`Z0O&`````,D+LBY`@;5_Y(%]F8I`H;?`A8Y)`Y(!"A()"Y(`Q\90("TB+R#`SBH-3@W8*" +M(7C:UDK=T@TJ@F%W[0$6/04R86\,"1#3H':`/;(G,O*@U/"[@KJVNKFRVPVR +M*SP;S/(+$TN9J"N,OSB5IZ,'&XBR;0#2S02R(O+RH-3PNX*ZMDJ[L@LJM[P$ +MQN[_``""87@R(6\,;+(A>."CH+)A=J)A<#"[P+)A?^7Y`3)A;^(A?Q:3!C)A +M;]T#C0$P\#2BT0&BRB"@KJ!VGP>X"+D*2XA+JM"407:919@(N!BY&K@HN2JX +M.+DZN$BY2KA8N5JX:+EJN'BY>KB(N8JXF+F:N*C8R,BXN:K)NKC8V+EZ +MN(BYBKB8N9JXJ-C(R+BYJLFZN-C9RMCHN=JX^-GJF0JY^J+*0(+(0+T!PB%V +MT2,!HB%]XJ8X#`_R91GR91CJYN)A<0P/HBKDVM;287(E=0'"(78,#]$D`:(A +M?>*F/++1`;++(.KFXF%THBKDT-:`TF%SY7(!XB+R\J#4\.Z"ZN9*[N(.*PP( +M@F%U%BX)#`FBP7^BRA%V@'XR)S*RH-2P,X(Z-CHY,M,.N,.Y"CC##!^R`Q4, +M#LAS!VL5LB%]LBODW0S(;+++_[#O@^#,D,)M!3(G,DNJLJ#4L#."&X@Z-CHY +M,M,..,/B(7T,'\(#%4N9V(,7;`[B+N3(;0ONX.^3X,R0R5WR(O(RH-0P_X+Z +M]DK_\@\K][@%AM[_````@F%U0B%Q(B%RLB%UPJ`#HL%_HLH1I=H!(-(@[03" +M(77RH`&B(7VRP7^RRQ&B*N0E90'"(772(7/B(70,'Z(A?;+!?[++$:(JY*5C +M`=(A>,(A=]#,P%;L"^(A>/8N`D8M`!;.!2TN(@B%]@BCE,B%\#"V"*'(;,S)A +M?(>S/Y(A?9(IY0P(*IF2*79VK1+2(7W2+>6*W=+=`N(=`:J(EQZ$#`B&X/_B +M;&X;NTO,QNW_``"2;&X;NTO,QNK_``#B(7WB+N7B+G,,#_)A>Q9N"@P.@0$! +M#"Q@)Z"*(L85`((<`)*@U)"(@HJ&2IB2"8!+[H+8"W:9*9(HK,()$]AYF(D' +M;`OR+16,7_B5.`WW$TX7;`O"*16,7/B5V`GW'4M+B((A?8(HY3(A>PPL@BAS +M&S,R87N'LS^2(7V2*>4,".J9DBEX=JP2PB%]PBSEBLS"W`+2'`&JB)<=A`P( +MAN#_TF*1&W=+(L;M_P``DF*1&W=+(L;J_P``A@8#NE9RUFT,"':`-+(G +M,L*@U,"[@KJVNKBRVPVR*SS""Q,;F28\'-(B\N*@U.#=@MK62MW2#2I+B-^!?D+A@```,D+LBR:6Y+ +MF:(A?="#07:8,H(JYY+)(()I9H(JYX)I9X(JYX)I:((JYX)I:8(JYX)I:H(J +MYX)I:X(JYX)I;((JYX)I;09^_P```+;(`L:4_Z$!`6"8H("\P+#P)*J9=I\* +MPB%]PBSGPFF12YFB(7VP@T%VF#*"*N>2R2"":8F"*N>":8J"*N>":8N"*N>" +M:8R"*N>":8V"*N>":8Z"*N>":8^"*N>":9`,`AWP`/(%_A:O0@P'*AD#H@.(.@"+"`8+8"W:>*9(HK-()$^AYF(D';0OR +M+A6,7_B5.`[W$TH7;0O2*16,7?B5Z`GW'D=+B#(A?3(CY3(C<@P(#"TW,@+& +M5@"2(7V2*>5PF8"2*79VK1+2(7W2+>6*W=+=`N(=`:J(EQZ$#`B&X/_B;&X; +MNTO,QN[_``"2;&X;NTO,QNO_``""'0"2H-20B(+P(`"*ADKX\@^`@M@+=I\. +MDBBLL@D32XC8:28[/CWPTB%]TBWE2^X,"-(M<@PO&R+7,@(&7@&2(7V2*>7J +MF9(I=G:O$M(A?=(MY8K=TMT"LAT!JHB7&Y\,"$;G__(M%1:O^[@I.`6WD[/R +M(7C2;&Y+S!O_\F%X1NG_``""'0"2H-20B(**ADJ8D@F`2R*"V`MVF2F2**S2 +M"1/H>9B)!VT+\BX5C%_XE3@.]Q-.%VT+TBD5C%WXE>@)]QY+2XB"(7V"*.4R +M(7H,+8(H=!LS,F%ZA[-G:M$M(A?=(MY8K=TMT"XAT! +MJHB7'H0,"(;@_^)L;AN[2\S&[?\``))L;AN[2\S&ZO\```"R91@,#N)E&4:) +M_@P"#`_R91CR91D=\+I6AAG]@B%]@BCE@BAU#`F287D6V)\,#H$!`0PL8">@ +MBB)&%P""'`"2H-20B(**ADJ8D@F`2^Z"V`MVF2R2**S""1/8>9B)!VP-\BT5 +MC'_R)0DR+0#W$U@7;`S"*16,;/B5TBD`]QU32XB"(7V"*.4R(7D,+((H=1LS +M,F%YAS,"!F3^DB%]DBGE#`C@F8"2*7QVK!?"(7W"+.6*S,+<`M(<`:J(EYT" +MAM[_/?`,"(;=_])BD1MW2R*&Z_\`DF*1&W=+(L;H_P``,;A_0P/\F%WQK3]@B,#&@':`,M(G,O*@U/#=@MK6VMC2W0W2+3P;F?(- +M$TN(TBT&)C\7,B+RLJ#4L#.".C9*,S(#*C>Y*(;Q_P``\@TYL@TU!V_>5KO] +M.`WX!3-)L;DO,&[NR87@&\?\`LB%XH2,!#%P]"Z"F@*4M`;(B\L*@ +MU,"[@KJV2KNR"RH,"3)A;A:[!C)A;M$!`0P(8,.@VLQV@#/2)S+BH-3@W8+: +MUMK8TMT-TBT\,J#4&YGB#1."R`32+08F/A/R(O(P_X+Z]DK_\@\J][DG1O'_ +M`*(-.;(--0=JXE;[_?@-Z`7WKMBB(7C2;&Y+S!NJHF%X!O+_`,*@!*(A;C(A +M>+$C`3)A?J`SP&"JH*)A;;"J@#"S(&4C`=(A;L(A?C)A;!:-"#)A;($!`6"C +MH-"0-(JJBH9VF0FR*&ZR:I%+B$NJT)1!=IEEDBANLBAOLFJ2LBAPLFJ3LBAQ +MLFJ4LBARLFJ5LBASLFJ6LBATLFJ7LBAULFJ8LBAVLFJ9LBAWLFJ:LBAXLFJ; +MLBAYLFJLBA\LFJ?LBA]LFJ@DFJ1@LA`HLI`QST"AB(` +MH0$!TB%L@B%MO0VJB-#0-*JF=IT)DBANDFJ12XA+JK"407:999(H;K(H;[)J +MDK(H<+)JD[(H<;)JE+(H+)JF[(H>;)JG+(H>K)JG;(H>[)JGK(H?+)JG[(H?;)JH))JD8+( +M0*+*0,)E&<)E&*(B\K*@U+"J@JJF2JJB"BL,";T,%OH*T0$!#`A@S*#:S':` +M,-(G,C*@U##=@MK6VMC2W0[8S>(-$QN9V&TF/A?B(O+RH-3P[H+JYDKNX@XK +M2XCGN6X&\O^B#346&OZX;;E=HB#"[@AO_ +MNK:ZN++;#KC+\F%X2\RR"Q&R3C2&W_\```"R)1C!(P%@JZ#*JL(A>+"\P`P< +MY0(!HB48LB%X#!S1)`&@N\!@JJ#:JJ4!`<(A>,)E&<)E&`8>_K(E&(9E_0#2 +M(7W2+>72+7,,`A8M">(A=PP(#"U@[J!Z?@P.1@\``((=`)*@U)"(@O`@`(J& +M2OCR#X""V`MVGPZ2**RR"1-+B-AI)CL]/?#"(7W"+.5+[@P(PBQS#"TBP@'' +MLD.2(7V2*>7@F8"2*7AVK1+2(7W2+>6*W=+=`K(=`:J(EQN@#`B&Y__R+146 +MO_NX*3@%MY.TPB%WTF=_2W<;S,)A=X;I_[(A>-(A=])E&;)E&$8Y_>(A?>(N +MY>(N=`P"%FZJ#`?1`0%@RZ`,"-K,#"U&0```XB%]XB[EXBYT#`(6[C`,#@P( +MPB%XT0$!#"]@S*#:S`97````@AT`DJ#4D(B"\"``BH9*V-(-@(+8"W:=#I(H +MK+()$TN(V&DF.SX]\-(A?=(MY4ON#`C2+7(,+QMWUS<"!JP`DB%]DBGEZIF2 +M*79VKQ+2(7W2+>6*W=+=`K(=`:J(EQN?#`A&Y__R+146K_NX*3@%MY.S\B%X +MTFQN2\P;__)A>$;I_P``@AT`DJ#4D(B"2W>*AD"8@)()@"+"`8+8"W:9*9(H +MK-()$^AYF(D';0OR+A6,7_B5.`[W$TH7;0O2*16,7?B5Z`GW'D=+B#(A?3(C +MY3(C=`P(#"TW,@+&9/Z2(7V2*>5PF8"2*7IVK1+2(7W2+>6*W=+=`N(=`:J( +MEQZ$#`B&X/_B;&X;NTO,QN[_``"2;&X;NTO,QNO_``""'0"2H-20B(+P(`"* +MADKX\@^`@M@+=I\.DBBLL@D32XC8:28[/CWPTB%]TBWE2^X,"-(M=`PO&R+7 +M,@)&9P"2(7V2*>7JF9(I>G:O$M(A?=(MY8K=TMT"LAT!JHB7&Y\,"$;G__(M +M%1:O^[@I.`6WD[/R(7C2;&Y+S!O_\F%X1NG_NE8&5/L`B#3FR#34':@[,N_(A>-)L;DO, +M&__R87@R(O*BH-2@,X(Z-DHS,@,J\J#4-SFRLB%XH2,!#`P]"ZJFY(-$QN9V&UF/COB#36\7KAMN5VB)S(PJH*JIJJHHMH.J,JH:J)L +M;O(G,K(A>##_@AN[^O;Z^/+?#OC/LF%X2\SR#Q'R2C32(O+BH-3@W8+:UDK= +MT@TK2X@RH-37.9*R)1C!(P'R(7A@JZ#*JK"_P,*@`27#`-(A>-)E&,8!_+(E +M&`;A_0"R(7BR91B&WOWB(7WB+N7B+G4,`A9>R@P.\B%W#`@,+6#_H'I_A@\` +M@AT`DJ#4D(B"\"``BH9*F)()@(+8"W:9#I(HK+()$TN(V&DF.SX]\,(A?<(L +MY4ON#`C"+'4,+1LBQS("1A7_DB%]DBGEZIF2*7QVK1+2(7W2+>6*W=+=`K(= +M`:J(EQN?#`A&Y__R+146K_NX*3@%MY.SPB%WTF=_2W<;S,)A=T;I_P``TB%] +MTBWETBUT#`<67?0,#@P(PB%XT0$!#"]@S*#:S`80````@AT`DJ#4D(B"\"`` +MBH9*V-(-@(+8"W:=#I(HK+()$TN(V&DF.SX]\-(A?=(MY4ON#`C2+70,+QMW +MUS<"!KS_DB%]DBGEZIF2*7IVKQ+2(7W2+>6*W=+=`K(=`:J(EQN?#`A&Y__R +M+146K_NX*3@%MY.S\B%XTFQN2\P;__)A>$;I_P``@&`P!(2L>4U@8!`%A*QY782,&8\5BAB,%+F9GQA[T2.($H,=`SP!LS +M=I,&.`(BPOPY(AO=HF6`B+%+55FA2XB)L=\`D8S`%##P!O, +M1C$``$A(QY2RHBL@4B@4IQ6MANG_XL/^%@X52,$X@2@Q1[T.T#/`&S-VDP8X +M`B+"_#DB#`,,)':D>EB14B5".E52U0*"%0%66`9"%0`X85*@U%!$@E'?`$HS +M6E-2!2D690B!Y@`,"8HS=I5`@B-_<@@3J&AF-PS"*A6,;$@FXBH`1QYI!V<- +MJ'C"*A6,7$@FZ`I''E@79Q"HB,(J%8R,2";H"D#NP!9.!$LS&YD&#@""H(2* +M,Z'?`)AAJIF2"2E8`3AA5ID(Q@<`0BLA.&&"H-2`1(+)<4HS0>``QRX"AHK_ +MZ$'@S,"&B/^HD:(JO,B1Z,%(H<(LO(CQ6+&@S,`6#.P;W:)D@$N(2U59L8GQ +M2T1)H=>^`D:J_T@AJ($X\4"=H-"JP"NJ2C-RT_YVFA/(`TLSC*R")X#B*!2, +M?HD)2YE+=P:?_U@F2`A7%/,&^_\`4@4IQL+_B''(01N7<#C`ER@"QC<`RL,+ +MS`;7_T(K(3AA@J#4@$2"F.%*,T'@`*B1F`E*,^(#"\(JN:(JO':>*8(C)'(( +M%$LSK$P'9POH>$(.-8PT6%Z7%2<79POHB$(.-8PT6%Z7%1@]\.T*1@0``&8W +M].AH0@XU%L3^4BX%EY7F2,&(P)E@$O,R?%+55FA2XB)L=>T`D9N_W@A2($X\7#MH-!$P"M$>C-RT_YV +ME"-8`TLSIQ4:@B>`P@@UC-Q"*`67E`C"*R!2*!3'%0.)#DON2W<&7_\+PX:? +M_PP"'?`,8@P=TD;U'?``02L!D2,!^&'B)G^!+`%2WP<+[NF!BH^:GYDAB5%* +M_P8+_P``HB8NN%:Y0:D1A@__-F$`G0*!+0$M!5$N`7!8@R897F8I6"DQIA13 +M#`(Y(4D!,#2@#`28`9X!L@QJ'J2RP'`NZ"B:P"29@#8`=AN;P+N@J0N9!M@!UZ0R>"%P=*#&`0``&T1+ +M=S<7(J@'@@H3%VCPJ(K@!0`6BOX;1*@'N`;(,:B*&YO`NZ"I"YD&V`'7(HW7 +M)(7X$?+/_E:/]M>B`D;&_]>D`L;&_T;6_QM$"%P)CC-(-3*(FN;(O6?(O6B"J$>"[ +M$8#_$5=M!((%SHS8DB9#DBD1/?`+F199)`P,X5P`D@75\-P1@@73L-T@H)D@ +M`(@1D(@@@-T@\-T@X-T@V9>B)106>B*"!HI@?LI@@PIC> +MTIC?XIC@:XB0D(1PJA'@NP'`P(1PW1'@[@%`JA`PNQ!`W1`P[A"@F2#0K"`@ +MF1`@JA"0FR"@KB"9]ZGW(3`!D1 +MHI@?LI@@PIC>TIC?XIC@:XB0D(1PJA'@NP'`P(1PW1'@[@%`JA`PNQ!`W1`P +M[A"@F2#0K"`@F1`@JA"0FR"@KB"9]ZGWP@72LB4BH@71XB4CTB9#<*H1P.X1 +MTBT1\+L1X+L@D-T1T,P@P*H@L*H@J:?")D3HA=@2)KFH^)"JP!9:YK((.;"Q +M!!;+Y<(H$*(H$0O9T*R#%AH@C0J)`<:1__@!\B\5%K\9D0(!B#&:B((HEQ;H +M&)@!H@DY@@DXF/F@H02`@`3`B!'@JA&@F2"0B"`,B9"((+A!J`&"9Q32*W+( +M&M#,P,)G$K(K)C1L`@`(96_P``%IC:B!$L#_#=$0Q:HF4BHF4C +M\-UC\)@1\(ECB1$6G02(,>"(@`=M$_)8(/)8'_)8'D)8X$)8WT)8WFN(T+%! +M/?!VFR7R6"#R6!_R6!Y"6.!"6-]"6-[R6"/R6"+R6"%"6.-"6.)"6.'+B+@1 +M%MO3H1ZE-R"B +M1?&&J/^2H,!&J_\``-$"`;@QPBA_VKNR*VC*N[)C3@:W_P```%;(WX(FO(9] +M_P```#9!`*8C0@P*"]-]`@P8#`F@P\`+O':K#Q;$!B84529$/B94)QN(2W<; +MJI<;$B!LH"")H%@(8M;^0A29G]]`@P8#`G7FL8=\`#H%R#YH/@/Z`[X +M#_>NR9T(!O'_`&@7(%F@6`5H!E@%9Z6UG0@&[/\`Z!<@::!H!NA>:%;GIJ&= +M"`;G_P#H%R#YH/@/Z$[X3_>NC9T(!N+_`#9!`*8C0@P*"]-]`@P8#`F@P\`+ +MO':K#R8D;"8T529D/B9T)QN(2W<;JI<;$B!LH"")H%@(8M;^0A29G]] +M`@P8#`G7FL8=\`#H%R#YH/@/Z"[X+_>NR9T(!O'_`&@7(%F@6`5H)E@E9Z6U +MG0@&[/\`Z!<@::!H!N@>:!;GIJ&="`;G_P#H%R#YH/@/Z`[X#_>NC9T(!N+_ +M`#:!`&'&`&IB0B9_#`A2I#P@1+!:1#(D:X)D:](F?T(D:B#=L%K=PBUKPFUJ +MHB9_(*J@6JJB*H9:4K(E(4/_#R@(K_I4'[>7K(,9*@[_*@_=(* +M.0P>?/B"2C3B2C:""CCPW1`,+_#=()"($()*./*@_M#0=/#=$.#=(-)*.<(L +M?WE*B`*M`N`(`(@2K0+@"``6ZOXM"AWP``"B +M)B$6*OZBH$"E`>L,&`P-2L(,+D$W`)%7`#*D-/(DQ#HR^0&0_Q#R9,3B9+2R +M!=*2)1?R(V'"+'_)U2#_H'K_\B\DX@9_D-B#\_P0R=7C_`S3_`_)U1:[`)(& +M?8(C@)/X&()C@%@!DB.`K0(`.::($O`@`.`(`!;*_BT*#`JB9+2BH$!E^.I2 +M9,0=\*(%SA::"`NZ%CL,PB)I%FP-2N+2H0S2;G_R(FF!.@$6#PB)$H;+_Z(% +MWK(%TYHR#(P@NQ'`NR"R8YT6V@:B!4,'1:L0?(EQY)D +M$0O_\F7'TD2:XF04TD22<4X`\4H!84\`PB04H34`/#OL[,&L`)(EZL"9@``Y +MIH`0II'#`()D(G:`$](G@PN9%ET7%DD7X@/JXL[^%KX71OG_`/(B5/9/`H83 +M`;9L`@9@`(+,^PP?#`R`SX/"1)P,B()D%``^IO`0IO)D%@`^ILB!MD\"TD/I +MP!"FPF07`#ZFMDP"TD/IP!"FMDP%TD/IPJ``PF08`#ZFMDP"TD/IX!"FPB05 +MXF09\B7J@B06P_\(@_\0PB07@B08P_\4@_\8X_\<`#^FMDX"TD/I@!"F@F0B +MXB0BTB0BPB0B\B0BX.(4XF0;@B0BT-04TF0<\/@4^4'R9!Z`BA2)48)D'_(D +M(H(D(L#&%,)D'8",%()D((EA@B0B\/`4\F0:@(X4B7&"9"&"`]P6N`6"`]_Y +M,19X7PP?Z2&(,=D1R0$F.`;800P,T/R3B"$,'B8X!MA1#`S0[).($0P=)C@& +MB&$,#(#W*@+&3``L>X9-``#,Z0PMTD/J);?_ +MH34`/#OQ2@$,O@`^IM(EQ<(EK-K,EOQ`QZL^+'V&#P"VSP*&\`#RS.$63V*" +MS/I6V`J2`]P,RJ)D%!8)#.*A`@`^IL`0IL)$E+($E!;K"M)D%@SO\F04QB@` +M^MS2#0#B)<;"):SJS)8L/,)G5<(EK>(EKK($GYA4P_X(L_X1 +MJH[Z[I/X%()GR>G&PB6MDB6NL@2?P_D(L_D2DF9,@B6N\B,8((B@\FAJ'?#A +M2@$,V/+,^?#208)D%/#P%/)$H>+.0.#=H-@-V62M`B4Z`;(EK9(EKJ($G[/Y +M"*/Y$I)F3((EKO(C&""(H/)H:AWP`,%*`2ZJ,>R8; +M:B8K528[(I+)(+(EK9(EKJ($G[/Y"*/Y$I)F3((EKO(C&""(H/)H:AWP^&GH +M6?#PU.#@Y//^#^G&V(G(>=#0U,#`Y-/\#\G&N*F(F;"PU("`Y+/X#XG&!NO_ +MN&F(6;"PU("`Y+/X#XG&AN;_V(G(>=#0U,#`Y-/\#\G&!N+_`#ZFHF6NDF6M +M\!"F\F7'!O?^````/J9\^Y)D$>)$FK)EQZ`0IJ)D%8(D%1N(@F04AO7^`/J< +MLB0B\5P`X@/3P@24^KOC^Q3#^QFR9U:")?[B)!'R):R2"0"*[O/^!-/^"I/^ +M$.)G5<(EK;(EKOA4@@2?P_L(P4L!@_L1JNOS_A3B9\G*N[G&@B6MXB6N\@2? +M@_X(\_X2XF9,PB6NLB,8(,R@LFQJ'?``HB05DB,JH_D(`#FF@!"F(*(@@F0B +MI;0&HJ`!O0)EV0:R):RH4[JJEEHI/#RGK`0L>\8!`+%*`;JZL@L`PB6LJ&/* +MJI;J)SP]IZT$+'G&`0"12@&:FI()`*(D%.(D(H(#T_($E*/^%8/^%//^&>)G +M5M(E_J(D$<(EK-JJP_H$L_H*D_H0HF=5DB6MXB6N@@2?T4P!D_X(@_X1@34` +M\B)%VMZ*[O/^%.)GR=G&PB))R<:R(DVYQJ@RF$*R(E2@H.20D-0+RQ;,)\++ +M_A;L'Y/Z#ZG&V,+(LM#0U,#`Y-/\#\G&LB6M\B6N@@2?L_\(@_\2\F9,XB6N +MTB,8(.Z@TFYJ'?#R(RK20^GB9!729!3C_P@`/Z;B1)L]\.`0IB"B(.)D(N6C +M!J*@`;T"I<@&LB6LJ%.ZJI:Z'#P\IZQY+'L&'P`,#48,__%<`+(D(N(#T\($ +ME/J[X_L4P_L9LF=6@B7^XB01\B6L#`F*[O/^!-/^"I/^$.)G5<(EK;(EKOA4 +M@@2?P_L(P4L!@_L1JNOS_A3B9\G*N[G&@B6MXB6N\@2?@_X(\_X2XF9,PB6N +MLB,8(,R@LFQJ'?"Q2@&ZNK(+`,(EK*ACRJJ6"A0\/:>M!"QYQ@$`D4H!FIJ2 +M"0"B)!3B)"*"`]/R!)2C_A6#_A3S_AGB9U;2)?ZB)!'"):S:JL/Z!+/Z"I/Z +M$*)G59(EK>(EKH($G]%,`9/^"(/^$8$U`/(B1=K>BN[S_A3B9\G9QL(B28!`P(@D1_4J4\6E*B)462%<"BR@&B +M946G&722(Q6"$UJ2R0&28Q67&&RAPP"Q3@!V@!+2!'_"*TT+JM=<"HR:X@/B +M)BX,AOG_S&H,+_)#XJ5%_\($?PQZ\B5(LB4?#!X,#2"[H&J[\-Z#T_H/HF4^ +MP_H1HF4^LBLDL_H4HF4^D!"F@@/AS#B"`^*<&`PR'?"0$*8,(AWPH!"F##(= +M\``,7``\IK`0IHR;T@/&)BW29!$+JJ)CQ_)$FM)D%=)D%`S'84\`'&K"(E3B!=CB1)+' +MNE`L^,>`L:%`A;\+K9.`D9#`/)B5+(D%:(CZK/Z"``Z +MII`0IB"B())D(N4&!@P:O0*E@0;"(\6R(ZP\.M(CQLJ[EKLEMZH$+'S&`0#! +M2@'*R\(,`+(CK((D(MJ[TB04EBLDMZH&+'E&`@```)%*`9J;D@D`L@7/H@24 +MT_@5L_@4H_@9@F=6\B/^TB01XB.L^MWC_03#_0J3_1#29U6R(ZV"(ZZB!)_Q +M3`&S^`BC^!&A-0"2(D7Z^*J(D_@4@F?)^<;B(DGIQM(B3=G&HB)4DB):LLK_ +M%DL=XLK^%FY=%CEO\LG_%A]T9BD"QMT!DB);S!G&!@)F&0)&$0*"R?X66&[2 +M(ZVR(Z["!)_3^PC#^Q*R9DRB(ZZ2)1<@JJ"2:FH=\#P.Q[X+\D7E\F)4\F)5 +MQKC_P/`$5D]7LF)4QK7_`#VFHF.NDF.M@!"F@F/'AH;_```]IGS\DF01TD2: +MPF/'L!"FLF04HB04HF05AH;_#(NR9!0`/::0$*:29!8`/::P$*:"H`RWN`7R +M1>6RH`"R9!<`/:;"H`RWO`+R1>6`$*:"9!@`/:8,SH>^`O)%Y;`0IM(D&)(D +M%;)D&<(CZH(D%N(D%Y/\"(/\$./\%-/\&+/\'``\I@S)M[D"\D7ET!"FTF0B +MPB0BLB0BDB0BXB0BP,`4PF0:@B0BL+(4LF0;\B0BD)04DF0B1'P^A3R9!_Y(?(D(M#<%-)D(/#^%/)D(8(%V!9X!((%V]D!%EA[ +M#!TF/`:($0P,@-R3#!PF.P:((0P+@,N3#!LF.0:(`0P)@+F3#!DF/@0,#O"> +MD_($DI"+$/#]$/#\$(#_$/)$DJT")8<%#!J]`F5L8P``P,AFO_#`E&V89`H;W`=+)_E9-Y.A"V#+@X-30 +MT.3C_0_9QL(B)+(B(\#`U+"PY,/[#[G&HB.M@B.ND@2?H_@(D_@2@F9,\B.N +MXB47(/^@XF]J'?``\B05PB/JX@2:\_P(X_P/`#RFD!"FDF0BTF04\B/'@@7; +M@D22UB\`Q@`"D<,`DLG_@B>#%MA<%ME"\P6^B4+VA;M&^+*_A;. +M$68ZX:(I6A8Z#0OZ%F\(9BK3B$OX.X"`U/#PY(/_#_G&XBLDTBLCX.#4T-#D +MX_T/V<:H:XA;H*#4@(#DH_@/B<;R*R;B*R7P\-3@X.3S_@_IQMB+J'O0T-2@ +MH.33^@^IQH(K*/(K)X"`U/#PY(/_#_G&Z*O8F^#@U-#0Y./]#]G&HBLJ@BLI +MH*#4@(#DH_@/B<8&U/\`XBLDTBLCX.#4T-#DX_T/V<:B*R:"*R6@H-2`@.2C +M^`^)QO(K*.(K)_#PU.#@Y//^#^G&TBLJHBLIT-#4H*#DT_H/J<8&PO\`J$N( +M.Z"@U("`Y*/X#XG&^&OH6_#PU.#@Y//^#^G&V(NH>]#0U*"@Y-/Z#ZG&B*OX +MFX"`U/#PY(/_#_G&!K+_`*(I6A8J!R8:2M+*_E:-ZXA+^#N`@-3P\.2#_P_Y +MQN(K)-(K(^#@U-#0Y./]#]G&J&N(6Z"@U("`Y*/X#XG&\BLFXBLE\/#4X.#D +M\_X/Z<9&G?\``/(K).(K(_#PU.#@Y//^#^G&TBLFHBLET-#4H*#DT_H/J<:& +MD__H2]@[X.#4T-#DX_T/V<:H:XA;H*#4@(#DH_@/B<9&B_\``*(I6A8J!R8: +M2O+*_E;/X=A+J#O0T-2@H.33^@^IQH(K)/(K(X"`U/#PY(/_#_G&Z(O8>^#@ +MU-#0Y./]#]G&HBLH@BLGH*#4@(#DH_@/B<9&=O\``*(K)((K(Z"@U("`Y*/X +M#XG&\BLHXBLG\/#4X.#D\_X/Z<:&;/^(2_@[@(#4\/#D@_\/^<;HB]A[X.#4 +MT-#DX_T/V<9&9/\``*(I6KSJ)AHHTLK^5AW8J$N(.Z"@U("`Y*/X#XG&\BLD +MXBLC\/#4X.#D\_X/Z<:&5__B*R32*R/@X-30T.3C_0_9QH92_XA+^#N`@-3P +M\.2#_P_YQ@9._P`,.9)B5`98_A:9"PNI%DHYLLG^5ML+^$+H,O#PU.#@Y//^ +M#^G&TB(DPB(CT-#4P,#DT_P/R<:&)@#!2@'*R\(,`-(CQK(CK-J[EHLH/#ZW +M+@+&80#2!)J")"*R!<^2!)33^!JS^!23^!F"9U;R(_[B)!&"(ZSZ[H/^!"Q_ +MP_X*\_X0\4X!XF=5TB.MXB.NL@2?F%33_@BS_A&JCOKND_@4@F?)Z<;2(ZV2 +M(ZZR!)_3^0BS^1*29DR"(Z[R)1<@B*#R:&H=\/A"Z#+P\-3@X.3S_@_IQI(B +M7!;I,PN)%L@VHLG^5NJ6LB(4HB(3L+#4H*#DL_H/J<:2(C2"(C.0D-2`@.23 +M^`^)QO(CK=(CKN($G_/]"./]$M)F3,(CKK(E%R#,H+)L:AWP`-A"R#+0T-3` +MP.33_`_)QD9!_NC"V++@X-30T.3C_0_9QL(B++(B*\#`U+"PY,/[#[G&HB.M +M@B.ND@2?H_@(D_@2@F9,\B.NXB47(/^@XF]J'?```((B)/(B(X"`U/#PY(/_ +M#_G&QBO^(CKO($GX/^ +M"//^$N)F3-(CKI(E%R#=H))M:AWP`%:9H[)%YJ6A_J$U`$:+_@#HPMBRX.#4 +MT-#DX_T/V<;"(ZVB(ZZR!)_#^@BS^A*B9DR2(ZZ")1<@F:"":6H=\`#2(BS" +M(BO0T-3`P.33_`_)QK(CK9(CKJ($G[/Y"*/Y$I)F3((CKO(E%R"(H/)H:AWP +M#`I&>_X,#4:!_@`,#,9:_[($FO(D(I(%SX($E+/_&I/_%(/_&?)G5N(C_M(D +M$?(CK.K=\_T$#`[#_0KC_1#A3@'29U6R(ZW2(ZZ2!)^(5+/]")/]$:K]ZMV# +M_Q3R9\G9QK(CK8(CKI($G[/X")/X$H)F3/(CKN(E%R#_H.)O:AWPB"$,"PP, +M#!D,#O#I@]#)@^#,$.@1@+F##`C@B8/B!)*`[A#@NQ#`NQ"R1)*&%O[28D8@ +MHB#RH`_R8E3EG0'"(ZVB(ZZR!)_#^@BS^A*B9DR2(ZZ")1<@F:"":6J0``#B +M(B32(B/@X-30T.3C_0_9QH9&_XA"^#*`@-3P\.2#_P_YQM(CK;(CKL($G]/[ +M",/[$K)F3*(CKI(E%R"JH))J:AWP\B(DXB(C\/#4X.#D\_X/Z<;2(ZVR(Z[" +M!)_3^PC#^Q*R9DRB(ZZ2)1<@JJ"2:FH=\.(B%-(B$^#@U-#0Y./]#]G&PB.M +MHB.NL@2?P_H(L_H2HF9,DB.N@B47()F@@FEJ'?```((B-/(B,X"`U/#PY(/_ +M#_G&TB.MLB.NP@2?T_L(P_L2LF9,HB.NDB47(*J@DFIJ'?``#!J]`N71!:$U +M`(8"_@`V00!"I`Q*0K(DB@`[IC+2`0P/HJ9>JJ*""G7R0Y3R8Q;Y8X)#D^`0 +MI@`_IN#!Y>#9=/)#FM)D:N#A=.)D:\)C$;`0I@S]#-X,'+)C%)(C%((C%!R? +MDF,5A[](PDJ+XF,4XF,5@@I^%K@`DB,4PD.29JD"1AX`HB,4UQI+K0+E"0"" +M)&K2)&OR`Y_A3P"#_0CS_1+2;DS")&NR))4@S*"R;&H=\+(C%!:;!O<;7PN; +MD/`4\D.A\4T!XF,4D))!\)F@F`F98\;F_ZT"I8`!TB1JHB1KP@.?L4\`T_H( +MP_H2HFM,DB1K@B25()F@@FEJ'?""H0(`.*;P$*;R0Y3B`Y0,Z18>]\)C%I)C +M%`;:_])C%`;4_P`,R[)C%,;1_S9A`.(B53*@W$*D6$I"PB24TB)6.C+C_`C3 +M_!``/*:P$*:B`\4,JX"J$;"J(``ZII`0IH(D=`P*%J@+`#JF@!"FB>.8XU*F +M7E!2@+9)!8*@`8)%BY(C'9+)\Q;I";T"#`IEN072)&^B)%;!2@$\.]JJTB1P +MELH(IZL%+'Y&`0``RNKB#@"B)%;R!74,"=JJEFH'IZL$+'D&`0#*FI()`+(C +M*\(#N-(C'?/[%/%.`-/[%B)%BR`\/1-0##^@BS^A'!3P&Q3P#:VH/]%-)OR&(#DY/X"I(DKF/X"]"K@[(# +MG:/X#R"9H*(#GY(I;+/X$*/X$9/X%``XIL)#E,)C%LECH!"F>&6@L72@F70; +M=Q97.K)DKI)DK0P9@B4&\J$"H+'E%A@TTB3'H.`$"]W29,>R8Q&20YK"8Q7" +M8Q06O3CB0Y-Q3@#12@&A-0`\.^(C%&(%V&E!8D.284\`%IXY\B)4#(VV3P7V +MSP+&7P""(E3P(`"VR`H,'N)%Y>)C%,)C%?(B5>(#D_/]"./]#@`]IL(DK8(D +MKO(#DX)B4\)B4A;_`<(DL-(DKX(#G?#,$?#=$=)DK\)DL!9X`-(DK0O=TF,2 +MX!"FK0+B8F)E=@4,&KT")9L%PB3%LB2L/#K2),;*NY:;0[>J!"Q\Q@$`P4H! +MRLO"#`"R)*R"(F+:N](#DY8;0K>J!BQY1@(```"12@&:FY()`+(B5*(#E-/X +M%+/X%:/X&8)G5O(D_M(B48$U`.(DK/K=\4P!X_T$P_T*D_T0TF=5DB)%P@.= +MTB2NL@.?HB)2P_T0L_T1BHVC^`B3^!2"9\GB)*WZW>/]"-G&PB))R<:R(DVY +MQJ@RF$+"(E2@H.20D-0+O!:K.^+,_A:>.9/Z#ZG&B,+XLH"`U/#PY(/_#_G& +MPB,2DB,3L@.=H@.?P_D(L_D0H_D2DF9,D@.3XB,3@B,4%DD=(.Z@TB47PB2P +MLB2O^&/`P4&PL4&R9*_"9+#Y7P +M$*;R8Q@`/*:V3P0,&()%Y9`0II)C&<(C%X(C%>(C%O(#DX/]"((C&//]#N/] +M$,/]%(/]&)/]'``]IN(DKO(DK<(#D_)C$N)C$YS(C(H)C((DQX.X4XF,A@@78%M@$@@7;Z0$6V#L,'B8]!X@1TJ``@.V3 +M#!TF/`:((0P,@-R3#!PF.0:(,0P)@,F3#!DF/P:(`0P/@)^3\@.2D(P0\"`` +M\/X0\/T0@/\0\D.2K0*E800,&KT"97,%LB3%HB2LNJJ66C4\/*B8Q62(Q4+B!N9DF,4 +M@F3'PD.:QBG_`))#E;(E%\(C$^(C%-ACV7/I@R#,H+)L:AWP````/*:R9*Z2 +M9*V`$*:"9,=&$_\``)(#G5;9QK*A`P`[IJ`0IJ)#DT88_\)#D^T,#!G&]OX` +MG0P,#M(#D=)#DT;S_L(#DY%0`(#DX)C$O)C$YS>\B2P +M@B2OX@.=\/\1\(@1@F2O\F2PC&Z")*T+B()C$L`0II'#`,)C(@N9XB>#%EXA +M%EDA\@7F"YEF+^X,OP`_IN(DQ<(DK.K,EKPAQZL_+'S&#P""SN$6V">2SOH6 +M*2&Q2@$,W<+.^<"B0=)C%,#`%,)#H;++0+"JH*@*HF,&K0*E!0&&0?\,&0P> +MQLC^`-K,P@P`\B3&XB2L^NZ6WASGJP0L>08!`-J>D@D`@5P`TB,B\@.3X@.4 +MBMWS_13C_1G29U:R)/[R(Q&")*RZ_X/_!,/_"I/_$/)G5?A3X@.=@B2NT@.? +MLB,2X_@0T_@1T4L!JNBS_@CS_A3B9\FR)*W:B+/X"(G&!B'_#`P&]/X`#`F& +M^OZ3^@^IQL(B%+(B$\#`U+"PY,/[#[G&!AC_``"3^@^IQH85_[%*`;JJH@H` +MPB3&LB2LRKN6:Q4\/;>M!"Q[Q@$`P4H!RKNR"P`,3<$^`/(C(I(#DX(#E,K_ +MD_\4@_\9\F=6XB3^@B,1PB2LG0+JB,/X!*/X"K/X$()G5:A3\@.=@B2NPB,2 +MX@.?\_@0\34`X_@1X4P!^OC#_PBC_Q3R9\G")*WJB*T"P_@(B<;XD_G&Z-/B +M9@QVK2+H2=@YX.#4T-#DX_T/V<:R*EY+JA:+`"8;328K."8[!9+)(`;G_NAI +MV%G@X-30T.3C_0_9QLB)N'G`P-2PL.3#^P^YQHBI^)F`@-3P\.2#_P_YQD;R +M_XAI^%F`@-3P\.2#_P_YQL;M_\B)N'G`P-2PL.3#^P^YQD;I_P``5AG?#"W2 +M1>8E[_VA-0`\.]%*`89W_P``H.`$XD.3QC[_#`R&B?\,"4:._P#X00S(@F,4 +M%A_@LJ$"`#NFH!"FHD.4D@.4%OG>#.P,'=)C%L)C%(9X_PP*1J?_#`M&K?\` +M#`C8,0P)#!\,#.#/@]"?@]@AP)D0R!'0CX,,#<#?@\(#DM#,$,"($)"($()# +MDH85_ZT"#/[B8Q1EA@(&JOX``#9!`)*F"#*A'CHR@@.!FB*2`N:"R`&"0X&` +M@'27F`0,"()#@9(B$J(26I+)`9)B$I<:1;(B%;++`;)B%;<:0*'#`+%.`':` +M$M(#@<(K30NJUUP*C)KB`N(F+@R&^?_,:@PO\D+B9=_]D!"F@@+AS#BB`N*< +M&@PR'?"P$*8,(AWPP!"F##(=\``,7@`^IM`0IHR=\@+&)B_B`W\, +M`@P9H)G`DD-_'?`V80`,#%+2!D+2`PQW@B)$HJ"HJC*"R/X6R#>2`_72`^VR +M`_(663;20^L6>S<,%@P9X@/K@B2NTB47D_<*#!L,"=";@R"(H+(#]>/W"ZJ( +MD_FPD/LPF,LPF,R8R?R0_+"8RO"8RH6_BR0 +M@`2"0^MA3P`<:^(C*G(%W')#ZN<[`D8A`"SXY[@"1A\`''F7G@)&:@+!30$, +MW]+.Z-"R0?)C*M#0%-)#^<"[H+@+LF,2'R(QS2)+#")*\@[J"J[L#!0=#1 +M0=)DL,)DK](E&/)C'8)C'I)#[=)N0!WP#([2(RIQ3@"Q-0""S>H6*"7R(E0\ +M"(>?`L9/`A9-=#P,]SP"!F(`#!W21>G28RK28RO2(E7"`^O3_@C#_@X`/J:" +M)*Z2)*WR`^N28E*"8E.<8!`)%*`9J;D@D` +MXB)BLB)4T_X4L_X5@_X:\_X9XF=6TB)1@B4^LB2LVHBS^`3#^`J3^!""9U61 +M-0"!3`&R(D7R`_7B)*[2`_?"(E+S_A#3_A&:GL/Y"+/Y%))GR?(DK8KN\_X( +MZ<;2(DG9QL(B3`$*:2 +M),>"8RKB(RKB8RL+F9)DQ\)#\@9>_Y)#[;(E&,(C*>(C*M(C'-)C'>)C'B#, +MH*K,LFQ`'?#0@`16&%X,*9)C*L:%_P```#RFTF2NLF2MX!"FXF3'!D/_``"" +M`_56F-*RH0,`.Z:0$*:20^L&2/_"0^MM#`P91B;_`)T,#`;2`^G20^O&(O^= +M#`P&!B'_XF,J`#RF/?"0$*:28RP`/*8,R)>X`O)%Z8`0IH)C+0`\I@S-A[T" +M\D7IT!"FTF,N`#RFDJ`,U[D"\D7ID!"FDF,OTB,KP@/K@B,LT_X(P_X.TB,M +MPB,N@_X0T_X4P_X8D_X<`#ZF#,B7N`+R1>GR)*Z2)*WB`^N28RCR8RF(C.()C-HDQX.X4XF,W@@7<%I@$@@7?Z0$6&&4,'B8]!H@1#`V` +M[9,,'28\!H@A#`R`W),,'"8Y!H@Q#`F`R9,,&28_!H@!#`^`GY/R`^J0C!#P +M_A#P_1"`_Q#R0^JM`B4)!`P:O0)EW@3"),6R)*RBH*C*NY;K7#P]MZU!+'P& +M$0`,#(8U_PP)ACW_```6J5P+Z1:.8/+)_E;OO,A"N#+`P-2PL.3#^P^YQI(B +M)((B(Y"0U("`Y)/X#XG&QNK^P4H!RLO"#`#2),:R)*S:NY:;5SP^MZX&+'U& +M`@```-%*`=K;T@T`D3X`XB,X@@/K\@/LFNZ#_A3S_AGB9U:R)/Z"(R>2)*RZ +MB+%,`9/X!,/X"M/X$()G5?(#]8(DKL$U`.(#]_/X$/(C*./X$'2*5H6+0T+C198"&8MTXA,^#R`@-3P\.2# +M_P_YQN(L)-(L(^#@U-#0Y./]#]G&B&SX7("`U/#PY(/_#_G&XBPFTBPEX.#4 +MT-#DX_T/V<:(C/A\@(#4\/#D@_\/^<;B+"C2+"?@X-30T.3C_0_9QHBL^)R` +M@-3P\.2#_P_YQN(L*M(L*>#@U-#0Y./]#]G&!M3_@BPD\BPC@(#4\/#D@_\/ +M^<;B+";2+"7@X-30T.3C_0_9QH(L*/(L)X"`U/#PY(/_#_G&XBPJTBPIX.#4 +MT-#DX_T/V<9&PO\`B$SX/("`U/#PY(/_#_G&Z&S87.#@U-#0Y./]#]G&B(SX +M?("`U/#PY(/_#_G&Z*S8G.#@U-#0Y./]#]G&1K+_`-(I6A8M!R8=2N+-_E:> +MZ^A,V#S@X-30T.3C_0_9QH(L)/(L(X"`U/#PY(/_#_G&Z&S87.#@U-#0Y./] +M#]G&@BPF\BPE@(#4\/#D@_\/^<:&G?\``.(L)-(L(^#@U-#0Y./]#]G&@BPF +M\BPE@(#4\/#D@_\/^<;&D__H3-@\X.#4T-#DX_T/V<:(;/A<@(#4\/#D@_\/ +M^<:&B_\``-(I6A8M!R8=2O+-_E;?X?A,Z#SP\-3@X.3S_@_IQM(L)((L(]#0 +MU("`Y-/X#XG&^(SH?/#PU.#@Y//^#^G&TBPH@BPGT-#4@(#DT_@/B<:&=O\` +M`/(L).(L(_#PU.#@Y//^#^G&TBPH@BPGT-#4@(#DT_@/B<;&;/_X3.@\\/#4 +MX.#D\_X/Z<;8C(A\T-#4@(#DT_@/B<:&9/\``-(I6KSM)ATH@LW^5BC8B$SX +M/("`U/#PY(/_#_G&XBPDTBPCX.#4T-#DX_T/V<;&5__B+"32+"/@X-30T.3C +M_0_9QL92_XA,^#R`@-3P\.2#_P_YQD9._P#"8RJ"`_*2`^O2(ROR!=_R0^K3 +M_@B3_@Z#_@\`/J;2)*[R)*V2`^OR8RC28RFL"9(DL,(DKX(#]?"9$?#,$<)D +MKY)DL!:8`,(DK3WP"\S"8RC@$*;2),?B8SB632>1PP`]\`N9\B>#%A\:%AD: +M@@7J"YEF*.X,N0`YIM(DQ<(DK-K,ENP:/#['KCXL?$80```,/_)C*D8-_A99 +M"PN)%H@@LLG^5IL+^$+H,O#PU.#@Y//^#^G&TB(DPB(CT-#4P,#DT_P/R<:& +M)0#12@':S,(,`.(DQM(DK.K=ELT5/#_7KP8L>48"````D4H!FIV2"0#R`^N" +M(SCB`_+2`^SS^!3C^!K3^!F"9U;R)/[2(R?B)*SZW>/]!,/]"I/]$-)G58(# +M]?(DKN(#]](C*(/_$./_$8(C&[KOT_X(T4X!@_X4XF?)@B2MVO^#_PCYQD:_ +M_0``F$*(,I"0U("`Y)/X#XG&DB)<%ND2"[D6&Q4F*0+&MOWR(A3B(A/P\-3@ +MX.3S_@_IQM(B-,(B,]#0U,#`Y-/\#\G&AJW]F,*(LI"0U("`Y)/X#XG&!JG] +MPB(DLB(CP,#4L+#DP_L/N<8&%_[B(BS2(BO@X-30T.3C_0_9Q@:?_0S(@F,J +MS!?&F?T`/::P$*:R0^R2`^S,&8:5_?)C+`SLPF,JQI+]``#"8D:M`@S]TF)4 +M9=`!HJ"H1I#]`%99Y@PNXD7JY2[]HJ"HL34`!I7_D(`$@D/KQ@_^#`R&GOX, +M#0:E_@`,#,:E_PP)1JS_N$*8,K"PU)"0Y+/Y#YG&!G_]#`V8,0P/#!P,".", +M@Y#\@Y@A@/\0B!&0W(,,"8"<@X(#ZI"($(#=$/#=$-)#ZH9O_L(B)+(B(\#` +MU+"PY,/[#[G&QFW]XB(4TB(3X.#4T-#DX_T/V<;&:/V"(B3R(B.`@-3P\.2# +M_P_YQH:H_[(B-)(B,["PU)"0Y+/Y#YG&QE[]``P:O0*E=02BH*BQ-0#&9?\` +M`#9!``P+,M(!@B)$0J8D4J.\6E)*0NCD@LC^%B@6D@.=#!K2`Y46^13"(DB= +M"])#D\":@Z(#DPP=#`P,>)/X"N#-@Z/X"^(#G:(E?\/X#\(#GR"JH*(J;./X +M$,/X$:/X%``XIKECLF,6LD.4H!"FXJ$"\@.=LD.:H,`$%F\.PD.3`#NFH('E +MH)ETH+%TLF5_DF5^@F,1\!"F#/L,W/)C%)(C%((C%!R?DF,5A[]WTD3%PF,4 +MPF,5P@2X%KP`\B,4TD.2\L_T%C\,@B,4L(C`%N@)(*(@)0X`H4\`TB,2DB,3 +MP@.=L@.?T_D(P_D0L_D2DFI,D@.3\B,3HB,4%JD$(/^@XB0/TB6!PB6`@B,& +MT-%!P,%!PF6`TF6!B7.I@Y)#E>)O:AWPHB,4%BH(]QIY"_KP@!2"0Z&!30'" +M8Q3P\D&`_Z#X#_EC!MO_DD.5LB,3R&.H]-(C%-F#R7,@NZ"B:VH=\````#ZF +M\!"F\D.3QL/_K0(EJP&&U_^R0Y,,&8:L_YT+@@.1@D.3QJG_```^IJ`0IJ)# +ME)(#E`SL%JGRTF,6PF,41LC_``"R8Q3&P?\,S_)C%,:__P``-D$`DB)6PB)5 +M#(@RT@&R`Y.B`YK#^`BS^`ZC^`^3^!``.*9"I%B"`Y-*0I(D6*(D5Z)C$I)C +M$YS8XB1:\B19T@.=\.X1\/\1\F19XF1:C&WR)%<+__)C$K`0IJ(#H0RK@*H1 +ML*H@`#JFD!"F@B1T#`D6.`P`.:;`$*;)4X(C%-A3\M(&@LCSMDT%XJ`!XD_I +M%I@*(+(@HJ``I4\$T4H!LB1OHB16PJ`SXB1PNJJ6>@FGK`0L>P8!`-JZL@L` +MHB16\B,B@@.4ZJKA3@"6Z@>GK`0L>08!`-J:D@D`P@.3HB,4P_\4H_\5@_\9 +M\FY6TB2HHB,1PB16VJK1-0##^@2S^@J3^A"B;E6"`YVB)%C!3P'R`Y^#^A"" +M(Q+S^A':VOA3RJJ#_0CS_132;LG2)%?!3P#3^@BIS!WPF5.&S_^M`J5E!(;5 +M_P````P+QMO_#`D&XO\``#9!`$*D6$I"HB1OP4H!/#N6"@RGJP4L=T8!``#* +M>G('`*(D<)8:"Z>K!2QV1@$``,IJ8@8`LB)5HB244J#<6E*S^@@`.J:0$*:" +M)'$Q3@"2IE_6R`*:(I'#`':`#H(C@PN9C*B,J:("BR8J#8;Z_P#,:0PKLD*+ +MY>G\#+P`/*9&``":(I%1`>(E*X("=/(%N)KN@_X4@34`\_X9XF-6TB2HPB4: +M\5(!X4\`VLQS_`IC_!#"8U6R)%?2)%BB!<.8Y;/]"*/]$8J-^MV3^!2"8\G9 +MSAWP#`?&T?\,!H;5_P``-D$`0J182D*B)&_!2@$\.Y8*#*>K!2QW1@$``,IZ +M<@<`HB1PEAH+IZL%+'9&`0``RFIB!@"R(E6B))12H-Q:4K/Z"``ZII`0IH(D +M<3%.`)*F7];(`IHBD<,`=H`.@B.#"YF,J(RIH@*+)BH-AOK_`,QI#"NR0HOE +MV_P,O``\ID8``)HBD5$!XB4K@@)T\@6XFNZ#_A2!-0#S_AGB8U;2)*C")1KQ +M4@'A3P#:S'/\"F/\$,)C5;(D5](D6*(%PYCEL_T(H_T1BHWZW9/X%()CR=G. +M'?`,!\;1_PP&AM7_```V00!"I`Q*0K(DB@`[IC+2`0P(HJ9>JJ*2"G6"0Y2" +M8Q:)8Y)#D^`0IAQ?@D.:`#^FX,'EX-ETTF1JX.%TXF1KPF,1L!"F#/T,W@P< +MLF,4DB,4@B,4')^28Q6'OT;"2HOB8Q3B8Q6""GZ,>)(C%,)#DB:I>Z(C%#WP +MUQI+K0+E"0"")&K2)&OR`Y_A3P"#_0CS_1+2;DS")&NR))4@S*"R;&H=\+(C +M%!9[!O<;7@N;D/`4\D.A\4T!XF,4D))!\)F@F`F98T;G_ZT"9>7_TB1JHB1K +MP@.?L4\`T_H(P_H2HFM,DB1K@B25()F@@FEJ'?`<>``XIO`0IO)#E.(#E`SI +M%@[WPF,6DF,4QMG_TF,4QM3_#,NR8Q3&TO\``#9!`.(B53*@W$*D6$I"PB24 +MTB)6.C+C_`C3_!``/*:P$*:B`\4,JX"J$;"J(``ZII`0IH(D=!QI%F@+`#FF +M@!"FB>.2(QU2IEZHXUI2DLGSMDH$#!B"18L6V0FM`J4A!-%*`;(D;Z(D5CP\ +MXB1PNJJ6"@FGK`4L>T8!``#:NK(+`*(D5O(%=0P)ZJJ6J@>GK`0L>08!`-J: +MD@D`PB,KT@.XXB,=\_P4\4X`X_P5T_P9PF]6HB2HXB,:@B16JNZ#_@2S_@J3 +M_A#B;U6(X](D5Z(D6,(#P^$U`-/Z",/Z$=%/`<%/`.KJ@_X4XF_)VJJIS!WP +M#`B)XT;2_ZT"Y2\$AM?_````#`O&W?^&X_\VH0!"T@/R),T`/Z92T@8RT@'B +M!=/B0Y,,#N)#E.)B5N)B1J`0IAP]`#VFH,ETH+%TLF2NPF2MH*'EHF)1D!"F +MDD.:@@.:%DA"XF)4XF)5XF3'84X`T4H!<4\`H34`/#O"(E0,'_)#DNS,P:P` +MDB3JRID`.::`$*:1PP""8R)V@!/B)H,+F19N%Q99%_(%ZO+/_A;/%T;Y_](C +M%/9-`H8O`;9L`@9A`-+-^PP,T,^#TJ`1PD.IEDORA-0`\.]%*`0R_`#^FXB3%PB2LZLR6'$['JVT8"````L4H!NKVR"P#1/@"2 +M(R+B!=/:F=(#E./Y%-/Y&9)F5H(D_O(C$8K_@B2L@_\$P_\*L_\0\F95XB2M +M@B2NT@.?D34`X_@(T_@1V%.:F*J(T_D4#$V29LF)QYT"^)/YQ_T"Z-/IQW:M +M$Z(I7DN9%GH%)AI()BHY)CHB\L\@DB2M\B2N@@.?D_\(@_\2\F=,XB2NTB38 +M(.Z@TFYJ'?"X/[G'J%^IQXA_BT8L``#Q7`#:G+(C(M(%T\(#E/J[T_L4 +MP_L9LF96@B3^TB,1\B2LD@D`BMWS_03C_0J3_1#29E7")*VR)*[X4X(#G\/[ +M",%+`8/[$:K;\_T4TF;)RKNYQX(DK=(DKO(#GX/]"//]$M)G3,(DKK(DV"#, +MH+)L:AWP`*(C%9(E*J/Y"``YIH`0IB"B(()C(J6E`R"B("6_`[(DK*A5NJJ6 +MFB,\/*<8!`)%* +M`9J:D@D`TB,4@B,BP@73H@.4T_@5P_@4H_@9@F96\B3^TB,1XB2L^MWC_02S +M_0J3_1#29E7")*V")*ZB`Y_Q3`'#^`BC^!&A-0"2(D7Z^*J(D_@4@F;)^<8! +M`)%*`9J:D@D`TB,4@B,BP@73H@.4T_@5P_@4H_@9@F96\B3^TB,1XB2L^MWC +M_02S_0J3_1#29E7")*V")*ZB`Y_Q3`'#^`BC^!&A-0"2(D7Z^*J(D_@4@F;) +M^")*W2)*[R`Y^#_0CS_1+29TS")*ZR)-@@S*"R +M;&H=\`P,1N?^#`M&[?X`^&'H40P8#`S8<>#(@PP.T.B##`WPV(/@W1#H00P/ +MX/B#X@.2\.X0X,P0T,P0PD.2QHC^``P+QG?_#`F&??\,"P:C_P`,"8:H_YG' +MTB(3VR +M)*V")*ZB`Y^S^`BC^!*"9TSR)*[B)-@@_Z#B;VH=\`"9QZ(DK?(DKH(#GZ/_ +M"(/_$O)G3.(DKM(DV"#NH-)N:AWPF8`B)$ +M?V*E/&IEDB9%@A;`&YF29D67&'.8TX(32AN9F=.7&&^APP"Q3@!V@!+2!'_" +M*TT+JM=<"XRJX@/")BX-AOG_`,QJ#"_R0\)E(_S"!'\,>O(F2+(F'PP>#`U0 +MNZ!ZN_#>@]/Z#Z)F/L/Z$:)F/K(K)+/Z%*)F/I`0IH(#P(D5](4WAONXF17X-W`%AT-P@M_TM)MTBTTV8.8@X(C$@P5P_D,F8/H@PP/ +M@/6#\_X/Z8-0$*90T'329"[")"Z2(Q,@S*"JS))L(H(D+OB#((B@JHB"*"3! +M3@"APP"#_Q#Y@W:`$O(+?^(L30NJ]UX*C)J"`]8F*`R&^?_,:@PIDD/691'\ +MH@/6%IH$##)0N650R'3"9"U@NQ"R9"P=\,`0I@`WIO`0IM(D6/"`=/"X=/"0 +M!9)D1[)D+8)D+N(D+O#Y96#_$"#NH/)D+`PBJN[2;B(=\```-Z;0$*96S?H, +M`AWPT!"F`#>F@!"FXB18@)!T@,AT@+`%LF1'PF0MDF0N\B0N@(EE8(@0(/^@ +M@F0L##*J_^)O(AWP`#:A`%+2`S(ES0`SI@P,,M(!0M(&\@33\D.3PD.4PF)& +MPF)6H!"F'#X`/J:@L72@V7329:VR9:Z@H>6B8E&0$*:20YJ"`YH<61:('L)B +M5<)B5,)EQW%.`-%*`6%/`*$U`#P[XB)4\@3<\D.2%IXITB,4'%C7.`KV368, +M'=)B5`8<`(+.ZA;H02SYU[D"!ED`''FBS>G,&L;]`<%*`?*@#>+-Z."R0?)C +M%.#@%.)#H<+,0,"[H+(K`+ECK0+E./^2):WR):Z"`Y^3_PB#_Q+R9DSB):[2 +M)=@@[J#2;FH=\```!^X(#"W28E2&`0``XJ`#XF)4DB,5@B0JD_@(`#BF\!"F +M(*(@\F,B90,#(*(@)5L#N%3"):P\.M(EK,J[EBLQMZH%+'P&`@``P4H!RLO" +M#`"X9((C(MJ[TB,4EJLOMZH$+'G&`0"12@&:FY()`+($TZ(#E-/X%;/X%*/X +M&8)G5O(E_M(C$>(EK/K=X_T$P_T*D_T0TF=5LB6M@B6NH@.?\4P!L_@(H_@1 +MH34`DB)%^OBJB)/X%()GR?G&XB))Z<;2(DW9QJ(B5)(B6@NZ%@LIXLK^%FY$ +M%AEM"_D6#RZ"R?X6:"V2(EL6^78+J1;J([+)_A;[(((EK>(EKO(#GX/^"//^ +M$N)F3-(EKL(EV"#=H,)M:AWPDL[0%BEVLB0JPJ`!PD3IP_L(PF,4PF,5`#NF +MH!"FHF,B(*(@)?("K0(E2@.R):RH5+JJEBII/#RGK!PL>\8'```YIO`0IGS] +M\F)4XB)4XF)5TF7'!H+_`+%*`;JZL@L`PB6LJ&3*JI::93P]IZT$+'G&`0"1 +M2@&:FI()`*(C%.(C(H($T_(#E*/^%8/^%//^&>)G5M(E_J(C$<(EK-JJP_H$ +ML_H*D_H0HF=5DB6MXB6N@@.?T4P!D_X(@_X1@34`\B)%VMZ*[O/^%.)GR=G& +MPB))R<:B(DVIQI(B6A9);`NY%CMNPLG^5ESON#*YQJ(B(ZG&DB6M\B6N@@.? +MD_\(@_\2\F9,XB6NTB78(.Z@TFYJ'?``\B,5DB7JX@.:\_D(X_D/`#FF@!"F +M@F,BPF,4XB7'\@3?\D.2EAYTD<,`"YF")X,6F%,6F5/"!.H+F68L[@R^`#ZF +MXB7%PB6LZLR6S%;'JP0L?@8!`-KLX@X`\B7&PB6L^LR6K%7'*P)&O0#2!-.2 +M(R+"`Y2R`YK3^13#^1FS^1J29U:")?[R(Q&2):R*_Y/_!"QXX_\*@_\0@4X! +M\F=5TB6M\B6NP@.?N%/3_PC#_Q&JGXK_L_D4DF?)^<;2):VR):["`Y_3^PC# +M^Q*R9DR2):Z")=@@F:"":6H=\.BRZ<;"(BO)QK(EK9(EKJ(#G[/Y"*/Y$I)F +M3((EKO(EV""(H/)H:AWPPB(KR<:R):V2):ZB`Y^S^0BC^1*29DR"):[R)=@@ +MB*#R:&H=\`P,!C[_``P)QD/_````%DE>)ADNTLG^5GW8Z#+IQL(B(\G&LB6M +MDB6NH@.?L_D(H_D2DF9,@B6N\B78((B@\FAJ'?#"(B/)QK(EK9(EKJ(#G[/Y +M"*/Y$I)F3((EKO(EV""(H/)H:AWPV#+9QN(B(^G&!D?_'!T,B9)C%``]IH`0 +MIH)C%@`]I@S/A[\%XJ`!XD3I@!"F@F,7`#VF#,^'OP62H`&21.GP$*;R8Q@` +M/:8,SO>^!8*@`8)$Z>`0IH(C%>)C&?(EZI(C%](C%H/_"((C&-/_$)/_%(/_ +M&./_'``_I@S-Y[T$#!F21.F`$*:"8R+B(R+2(R*2(R+R(R+@XA3B8QN"(R+0 +MU!328QSP^!3Y0?)C'H"*%(E1@F,?\B,B@B,BD)84DF,=@(P4@F,@B6&"(R+P +M\!3R8QJ`CA2)<8)C(8($W!;H!8($W_DQ%BA'#!_I(8@QV1&9`28X!MA!#`G0 +M^9.((0P>)C@'V%&2H`#0Z9.($0P=)C@(@B$&DJ``@-F3B`$,&28X"HAQ*8$, +M`H"2DRB!@@.2@(\0@.X0D(T0@.X0XD.2K0+E8`*M`B4.`[(EQ:(EK+JJECH_ +M/#RG+`+&.0`L>H8Z````%LD^"]D6O3CBR?X6'CB2(EP6N4,F&3#RR?Y6K[N" +M(A.)QN(B,^G&TB6MLB6NP@.?T_L(P_L2LF9,HB6NDB78(*J@DFIJ'?``XB(S +MZ<;2):VR):["`Y_3^PC#^Q*R9DRB):Z2)=@@JJ"2:FH=\/($T]JV<8&[?\` +MHBE:K&HF&A=F*JB(/HG&\BXC^<;87MG&PBXER<;&Y/_"+B/)QJ(N):G&AN'_ +M^#[YQMA>V<;&WO^B*5JLJB8:&X+*_E;8]O@^^<;2+B/9QLA^R<:B+B>IQ@;6 +M_P"B+B.IQH(N)XG&AM+_V#[9QLA^R<;&S_^B*5J<6B8:"_+*_E8?\X(N`X)F +M#*(N(ZG&QLC_R#[)Q@;'_P!6V:P,+=)$ZB6`^Z$U`#P[T4H!AJ[^Z#+IQD9, +M_@S(@F,4%O^!`#FFL!"FLD.4H@.4S!J&`_X,[`P=TF,6PF,41@#^``P)AFS^ +M#`M&9/X,#H:F_@#R!-.R(R+2`Y3"`YKS^Q33^QG#^QJR9U:")?[2(Q'R):P, +M"8K=\_T$X_T*D_T0TF=5PB6MLB6N^%."`Y_#^PC!3@&#^Q&JV_/]%-)GR(EKO(#GX/^"//^$N)F3-(EKL(EV"#=H,)M:AWPLB(CN<:B):V"):Z2`Y^C +M^`B3^!*"9DSR):[B)=@@_Z#B;VH=\`P*AC__#`P&1O\`R#+)QH8%_P"(80P. +MR'$,&0P/P/F#@.F#\.X0^%$,#"!;>B91N291R(D6/%2`9(%PZ/^$*(E&Y/^$8J.F.7Z[J/X")/X%()CR8(D5_%/ +M`(/^".G/'?`,!X;"_PP&1L;_``PIDDJ`I4W[QN'_`#9!``P),M(!0J8D4J.\ +M@B)$6E)*0H+(_A;(%J(#G0P;T@.5%IH5PB)(K0G20Y/`JX/(Y`P=#'BR`Y.C +M^`JB)7^S^`L,"R"JH,"]@[/X#\(#G;(#GZ(J;,/X$+/X$:/X%``XIIECDF,6 +MDD.4H!"FX@.=H/`$\D.3W"[B`YT<3P#N$?#N(``^IL`0IL)#DQQ8`#BFH,'E +MH.%TH/ET\F5^XF5_DD.:PF,1L!"F#-RR8Q2"(Q3R(Q0,^X)C%19O#:(C%!R) +MISD:"^K@\!3R0Z'Q30'"8Q3@XD'P[J#H#NECA@,`@LKG%A@-TD3%PF,4PF,5 +MD@2XC*FB(Q320Y*BRO06N@G"(Q0]\+<<;""B(&4+`.%/`)(C$M(C$X(#G?(# +MGY/]"(/]$//]$M)N3)(#D[(C$](C%!9I`B"[H*(D#X(E@?(E@,AC@(%!\/%! +M\F6`@F6!R7/9@Y)#E:)K:AWP`))#E;(C$\ACJ/32(Q39@\ES(+N@HFMJ'?"M +M`J49``;D_P```))#DPP:!JK_K0GR`Y'R0Y-&I_\`#,B"8Q2&U/\T8!``#:NK(+`*(D5O(C(H(#E.JJ +MX4X`ENH'IZP$+'D&`0#:FI()`,(#DZ(C%,/_%*/_%8/_&?)N5M(DJ*(C$<(D +M5MJJT34`P_H$L_H*D_H0HFY5@@.=HB18P4\!\@.?@_H0@B,2\_H1VMKX4\JJ +M@_T(\_T4TF[)TB17P4\`T_H(JK!2QW1@$``,IZ<@<`HB1PEBH-IZL'+';&`0````#*:F(&`*(D +M6)(D5X(%MY)E&Z)E')RXPB1:TB19L@7!\,P1\-T1TF19PF1:C$O2R?_291OP +M$*;B)'$Q3@#6;@*1PP"BIFJJHG:`#[(C@PN9C+L6F0?""H`F+`9&^O\`%LD& +M#+T`/::"!;?2)2OR)1WB!;B#_13S_17C_1G28U;")*BR)1J!-0#*NW/["F/[ +M$+)C5:(%P>(D6/%2`9(%PZ/^$*(E&Y/^$8J.F.7Z[J/X")/X%()CR8(D5_%/ +M`(/^".G/'?`,!X;)_PP&QLW_``PIDDJ`)0K[QN'_`#:A``P-,M(!0M(##'^" +M(D12IB1:4H+(_A882I(#G0P:P@.5%EE(LB)(G0W"0Y.PFH."`Y.XY9/_"@P: +M#`FPFH.#_PNB`YV")*Z3_P^2`Y\@B*""*&RC_Q"3_Q&#_Q0`/Z;98])C%M)# +ME+`0INA#P@.:L)%T%MX]H@.0HD.:DF2N\@.='$X,&19?/@P*C$R"`YJ`J8,6 +MBD`,"LA#PLS^%BQ!@@.=`(@1X(@@`#BF\!"F\D.3V4.\.H%7`0`XIO`0ILA# +M\D.0H@.0&\S)0]S*@@.=`(@1X(@@`#BF\!"F\D.3J$/"`Y/"0Y$;JJE#X@.: +ML,'EL*ET%EXXTF)5TF)4HF2MTF3'PF)1#(QQ3@!A3P"A-0`\.^(C%/(%N/F! +M\D.2\4H!%CXZ\B)4MD\%]L\"AET`@B)4\"``ML@*#![B1<7B8Q328Q7B(E;2 +M(E6"`Y/R`YK3_`B#_`[S_`_C_!``/*:")*[2)*WR`Y/28E*"8E,6_P'R)+"" +M)*_B`YWP_Q'PB!&"9*_R9+`6?@"")*T+B()C$I`0IJT"DF)B93H"K0+E4P+" +M),6R)*P\.M(DQLJ[EEM$MZH&+'Q&`@```,%*`48"````D4H!FIN2"0"R(E2B`Y33^!2S^!6C^!F"9U;R)/[2(E&! +M-0#B)*SZW?%,`>/]!,/]"I/]$-)G59(B1<(#G=(DKK(#GZ(B4L/]$+/]$8J- +MH_@(D_@4@F?)XB2M^MWC_0C9QL(B2"(QC3_Q"3_Q2#_QCC_QP`/Z:V3@0,'=)%Q?(DKI(DK>(#DY)C$O)C +M$YR^TB2PXB2O@@.=\-T1\.X1XF2OTF2P%D@`"^GB8Q*`$*:"8R+B(R+2(R*2 +M(R+R(R+@XA3B8QN"(R+0U!328QSP^!3Y0?)C'H"*%(E1@F,?\B,B@B,BD)84 +MDF,=@(P4@F,@B6&"(R+P\!3R8QJ`CA2)<8)C(8(%N!;X!8(%N_DQ%O@V#!_I +M(8@QV1&9`28X!MA!#`G0^9.((0P>)C@&V%$,"=#IDX@1#!TF.`:(80P)@-F3 +MB`$,&28X"HAQ*:$,`H"2DRBA@@.2R9$]\("/$(#N$)"-$(#N$.)#DLF1K0*E +M(P&M`N4K`L(DQ;(DK*B1RKN6.R\\/;2ZJ\>R8;*28K&R8[!9+)((;H_N@Y +MZ<;86=G&R'G)QKB9N<:&^?^(.8G&^%GYQL;V_\@YR<:X>;G&!O3_`-@YV<8& +M\O\`\L[A5J^VK0(,^()C%.5]_T;7_@!6V>(,*9)%QB69^J$U`#P[\4H!AH;_ +M#`R&F?\`#`D&GO\,#(:\_PP)!L/_`.AAV%$,'PP(F''0CX,,#9#?@PP)X)^# +MT)D0V$$,#M#O@](#DLF1X-T0T(@0D(@0@D.2ABS_Z($,S_)C%!:>X!QZ`#JF +MD!"FDD.4@@.4%HC?#.L,',)C%K)C%,9Z_P```#9!``P$DJ8@,J$>.C*"`X&: +M(I("SH+(`8)#@8"`=)>8`D)#@8C"HA).&XB)PH<:1)CR&YF9\I<:5J'#`+%. +M``P5=H`2T@.!PBM-"ZK77`J,FN("RB8N#(;Y_\QJ#"_R0LKEBOJ0$*:"`LG, +M.*("RHR:##(=\+`0I@PB'?#"`W^8`M)$IQP.PJ#[/+>8\U+2!8(35!N9F?.0B,`6*`SR)5>R%=X;__)E5_"[ +MP!:K$I($I[+2;;(K-+F#B(-B(Q(,'Y/X#(F#F(,,"V"_@[/Y#YF#8!"F8(!T +M@F4N\B4NLB,3(/^@JO^R;RR2)2Z(@R"9H*J9DBDNL4X`H<,`D_@0@F,(=H`2 +M@@2G\BM-"ZJ'7PR,NI(#UB8I%8;Y_P``S-H,*J)#UF5Z^L*@^PP-'`ZR`]7, +M2_(#UA:_!H($I2B#8+EE8)'E8*ATHF4MP)D0<+L0LF4LDF05@_(8*8,,,AWP +M``#0$*8`/J;0$*;0D>70N'2R92W`F1#0N65PNQ#0T'3292Z")2ZR92R29!4@ +MB*"JB"(E6")H+/($I=B##"+S_1C9@QWP`/($I18O"``^IH`0IA:(!@PRH@2E +MF(-@Z65@L>5@V'3292W`NQ!P[A#B92RR9!6C^1B9@QWP\!"F`#ZF\!"F@B58 +M\+'E\-ATTF4MP+L0\-EE<-T0\/!T\F4NDB4NTF4LLF05()F@JIF":2PB!*7X +M@R/_&/F###(=\-)$I2B#@@2E@_(8*8,,`AWPF(,,&[)$I:($I0P"H_D8F8,= +M\#:A``P,#!U"T@."(D12IB2BH*BJ,EI2Z.6"R/X6F$F2`_6R`^T6^4>2`_*R +M0^L,>+(#ZY/X"I(DKK/X"PP+X+V#()F@T@/UL_@/JIFR`_>2*4+3^!"S^!&3 +M^!0`.*;"0^S"8RS"8QS0$*;R(QKB`_+0D706;S/R`^CR0_*29*Z"`_4<3PP9 +M%N@S#`L67@#B`_+@N8,6VS4,"X(C&H+(_A;80((#]0"($?"((``XIN`0IN)# +MZ\)C&KR;L57R`_(<6]#9=!9?+<)B5<)B5-)DK<)D +MQ^)B40R-<4X`84\`L34`/#^"!;CB(RJ)@8)#ZA9^.?(B5!Q9]SD/@B)5]D]) +M#!S"8RH&%0```(+.ZA;X2BSY][D"AG8`''NWG@)&%@+!2@$,W]+.Z-"R0?)C +M*M#0%-)#^<+,0,"[H+@+LF,(D +MK/K,X_P$T_P*D_P0PF=5D@/U@B2NPB)%\@/WD_@0D34`XB)2\_@1FICC^0C# +M^1229\F2)*VZB)/X"(G&\B))^<;B(DWIQK(B5)(B6@O+%FPT@LO^%LA.%KEM +MLLG_%CMNPLG^%MQNDB);%@EMTLG_%IUMXLG^%GYNLB,H\B,ID@/U@@/WL_\( +MD_\0@_\2\F9,D@/KTB,I\B,JK(GB(QS")+"R)*\@W:"JW;"Q0<#!0<)DL+)D +MK\CUXF,=\F,>DD/MPFU`'?"20^W8]>(C*8(C*O(C'/)C'8)C'B#NH*KNTFY` +M'?```/+.T!8/;?(#ZX*@`8/]"()%Q8)B5>(B5H)B5//]#N/]$``]II(DKL(D +MK8(#Z\)B4I)B4Q;H`<(DL-(DKY(#]?#,$?#=$=)DK\)DL(QITB2M"]W28RC@ +M$*:M`N)B8J4[`:T"I9,!TB3%PB2LHJ"HL4P!VLR6K&,\/L>N5RQ]AA8`@@/U +M'#L`B!&PB"``.*:29*[P$*;R0_+&+?\`L@/R#`ZPZ8-67LP&"``````[IGS_ +MTF2MXF)1\F3'@!"F@F)4\B)4\F)5QD;_#`O0@`2"0^O&+/_12@':W-(-`.(D +MQL(DK.K,E@Q=/#_'KP0L><8!`)%*`9J#_Q"! +M-0#"(E+C_Q&*C\/X")/X%()GR8(DK;K_@_\(^<;B(DGIQL(B3)#ZX;^_IT,\@/I +M\D/K1MK^PF,J@B,KD@/RX@/K@_T(@B,LX_T.D_T/@_T0`#VFDB2NXB2M@@/K +MXF,HDF,IK`C")+#2)*^2`_7PS!'PW1'29*_"9+`6F0#2)*T]\`O=TF,H@!"F +MXB3'@F,XELY5D<,`/?`+F<(G@Q:<0Q:90](%Q@N99BWN#+X`/J;2),7")*S: +MS)9L2L>O!"Q\Q@$`T4H!VLS"#`#B),;2)*SJW98-2=>O!"QYQ@$`D4H!FIV2 +M"0#R`^N"(SCB`_+2`^SS^!3C^!K3^!F"9U;R)/[2(R?B)*SZW>/]!,/]"I/] +M$-)G58(#]?(DKN(#]](C*(/_$./_$8(C&[KOT_X(T4X!@_X4XF?)@B2MVO^# +M_PCYQ@8[_P`,#<8,_PP)1A+_```6Z4,+B18(1++)_E8;S=@RV<;"(B/)QD8Q +M_QP`0IN)C+0`\I@S)Y[D%\J`! +M\D7%D!"FDF,N`#RF#,B7N`0,',)%Q8T-\!"F\F,OXB,KD@/RP@/KX_@(XB,L +MP_@.D_@/PB,MDB,NX_@0P_@4D_@8\_@<`#BF#,[WO@0,'_)%Q<(DKI(DK8(# +MZY)C*,)C*1;(`?(DL((DK^(#]?#_$?"($8)DK_)DL!9.``N)@F,H@!"F@F,X +MXB,XPB,XDB,X\B,XX.(4XF,Q@B,XP,04PF,R\/@4^4'R8S2`BA2)48)C-?(C +M.((C.)"6%))C,X",%()C-HEA@B,X\/`4\F,P@(X4B7&"8S>"!;@6Z`6"!;OY +M,1;8,PP?Z2&(,O/2Q^!A```)PI +M"XD66"IF*0^X,KG&DB(CF<;&``#(,LG&DB)<%DDH"]D6_2CBR?Y6CK""(A.) +MQO(B,_G&QK[^X4H!ZNWB#@#R),;2)*SZW99=)#PXUZ@$+'W&`0#Q2@'ZW=(- +M`)(#Z_(C.((#[)/_%,/_%8/_&?)G5L(D_I(C)\J9PB2LP_D$X_D*T_D0DF=5 +M@@/UPB2N\@/WT34`@_P0\_P1@B,H\B,;VMR#_0CS_1329\G2)*VZS-/\"-T" +MR<:2(Q_-`IG&#$F"(R.)QH8+`&8K(X@]B<;R+2/YQNA=Z<:R+26YQHA]B<;R +M+2?YQNB=Z<:R+2FYQM+-($O,%KFCLBQ>"YD6^PHF&W`F*S5F.^:R+%JG&N)VYQ@;M_P"R +M+%JL:R8;%V8KJ(@]B<;R+2/YQNA=Z<:R+26YQL;D_^(M(^G&LBTEN<:&X?^( +M/8G&^%WYQL;>_[(L6JRK)AL;XLO^5M[VZ#WIQK(M([G&B'V)QO(M)_G&!M;_ +M`((M(XG&\BTG^<:&TO_H/>G&N'VYQL;/_[(L6IS;)AL3\LO^5A_SN#VYQH(M +M(XG&1LG_``#B+2/IQL;&__@]^<8&Q?\`5MF\#"B"1<9ET?FBH*BQ-0`\/X;N +M_I@RF<8&2OZXLKG&QDS^PB(CR<9&1O[2(BO9QL9(_O@R^<;B(B/IQD9!_IBR +MF<:($XG&!D/^`,B!#,W28RK,'`;N_0`[IO`0IO)#[.(#[,P>QNG]#.@,&9)C +M+()C*H;F_0P-!HG^``P)QH[^N#*YQL8S_@P,QMC^#`E&WOX``,(B(\G&QB[^ +MPF)&K0(,_=)B5&6K_J*@J`8J_@`,#H9K_PP-AG'_Z#+IQH8E_O(B(_G&AB/^ +M@B(3B<:&(?Z2(B.9Q@99_[(B,[G&AAW^Z&'(40P?#`B8<<"/@PP,D,^##`G@ +MGX/`F1#(00P.P.^#P@/JV9'@S!#`B!"0B!""0^K&./^M`F4D`:*@J+$U`#P_ +MQJO^```V00!2H\`,!W)B25I24B5_#!9"T@&V)06"!)P66`Q=`@Q)=JD;HB): +M)CH00B)>/?`6Q`DF%'4F)$XF-`=2Q2!+(AWP```VII`0IIDU`#:F@!"FB44` +M-J8P$*8Y50`VIO`0IOEE`#:FX!"FZ74`-J;0$*;9A0`VIL`0ILF5`#:FL!"F +MN:4&[?\``#:FT!"FV34`-J;`$*;)10`VIK`0IKE5`#:FH!"FJ64&Y/\``#:F +M@!"FB34`-J8P$*8Y10`VIO`0IOEU`#:FX!"FZ84&V_\``#:FH!"FJ34`-J:0 +M$*:910;6_P""(EHF)54F.`<`-Z:P$*:YE,(D&R8\$``WIN`0IMB4H.X1X-T@ +MTF0)\B0<)C\1`#>F4!"F,B0)0%414#,@,F0)@B0=@LC]%@CO`#>FH!"FF)3@ +MJ@&@F2"9E$:W_U*A`B8X#0`UIK`0IK"P=+"VP+F4PB0;)CP5`#6FX!"FV)3@ +MX'3@YL"@[A'@W2#9E/(D'"8_%0`UIG`0ICB4<'!T<';`0'<1<#,@.92")!V" +MR/T6B.@`-::@$*:8E*"@=*"FP."J`:"9()F4QIO_```V00`RT@4,"()B23(C +M+T*@X$I"MB,%@@2\%H@7DB0B'+PF.2,`/*:P$*9A6`%2(EYQ60&R8@.BQ?\6 +M^@K2Q?X6W0SBQ?T6O@Y150'R)",F/R(`-:8P$*9A6@%2(E]Q6P$YLF85`L8C +M`(+%_A;8"I+%_1;Y#:(D),%6`28Z(@`\ICWPL!"F85P!4B)@<5T!LF(3)A5O +M9B4"1B,`TL7]%CT-XB0E05X!)CX?`#2F,!"F45\!0B)A86`!,F(;"_06#Q2" +MQ/X66!0F-`(=\```-J;`$*;"8AT`-::P$*:A80&R8A\`.J:0$*:28B$=\``V +MIM`0IMER!M3_```VIN`0INGR!MS_```VIO`0IO)B%\;C_P`WIC`0ICE2!LO_ +M```WIH`0IHG2!M/_```WII`0II)B%<;:_P`WIM`0IME2`#:FP!"FL6(!R7(` +M.Z:@$*:IDD:]_P```#>F4!"F6=(`-J8P$*;Q8P$Y\@`_IN`0IN)B$0;`_P`` +M-Z:P$*:R8A4`-J:@$*:19`&B8A<`.::`$*:"8AF&PO_"(EHF/`P,Q90$`,Z;P$*;B)!'@_P'P[B#B +M9!&&AO\`-::`$*:"8A\=\``VII`0II)B'1WP`#9!`&*CP`P%4F)):F)")G\, +M%X*A`K8D:I+$_D(B6A9I)R84"R8T"``UIJ`0IJ)B24(B6R84%"8T$0`UIL`0 +MIK(B2:#,$<"[(+)B24(B7"84%B8T$P`UIN`0IM(B23WP0.X1X-T@TF))0B)= +M)A04)C01`#6F,!"F\B))X#,!,/\@\F))4F)-0B:`MB1DDL3^0B):%DDHC*0F +M-`@`-::@$*:B8DU"(EN<-"8T$0`UIL`0IK(B3:#,$<"[(+)B34(B7)PT)C01 +M`#6FX!"FTB)-0.X1X-T@TF)-0B)=G#0F-!$`-:8P$*;R(DW@,P$P_R#R8DU- +M`B!2((*@!':HP&(D6@N6%CD+HL;]%MH*8B1>%G8))A9P)B9)LL;]5KL)`#>F +MH!"FJ34`-Z:0$*:910`WIH`0IHE5`#>F,!"F.64`-Z;P$*;Y=0`WIN`0INF% +M`#>FT!"FV94`-Z;`$*;)I086````-Z;@$*;I-0`WIM`0IME%`#>FP!"FR54` +M-Z:P$*:Y908-````-Z:0$*:9-0`WIH`0IHE%`#>F,!"F.74`-Z;P$*;YA08$ +M````-Z:P$*:Y-0`WIJ`0IJE%4L4@2T1-`@Q,=JS04B):%E4,TL7]%OT+4B)> +M%E4*)A5Z)B50XL7]5MX*`#>FT!"FTF0C`#>FP!"FPF0D`#>FL!"FLF0E`#>F +MH!"FHF0F`#>FD!"FDF0G`#>F@!"F@F0H`#>F,!"F,F0I`#>F\!"F\F0JAA@` +M`#>F@!"F@F0C`#>F,!"F,F0D`#>F\!"F\F0E`#>FX!"FXF0FQ@X``#>FP!"F +MPF0C`#>FL!"FLF0D`#>FH!"FHF0G`#>FD!"FDF0H!@4````WIN`0IN)D(P`W +MICWPT!"FTF0D0L0@2R(=\``F%!$F-`X`.*;P$*;P\'3P]\#R8DE"(ELF%!PF +M-!D`.*9`$*8R(DD]\$!`=$!'P*!$$4`S(#)B24(B7"84&B8T%P`XIJ`0II(B +M2:"@=*"GP$"J$:"9())B24(B70NT%IO8PL3]%CS8`#BFX!"FTB))X.!TX.?` +MX.X!X-T@TF))!EK_G"0F-!``.*;P$*8]\/#P=/#WP/)B34(B6YR4)C07`#BF +M0!"F,B)-0$!T0$?`H$010#,@,F)-0B)RQ/T62]<`.*;0$*;"(DW0T'30U\#@W0'0S"#"8DU& +M5O\`-D$`0J/`#`9B8DE*0C(D?[8C=%(B6B85#B8U"Y*@&0`YIH`0IH)B25(B +M6R85&28U%L%3`0`\IK`0IJ(B23WPH+L1L*H@HF))4B)<)A49)C46\50!`#^F +MX!"FTB))/?!`[A'@W2#28DE2(ETF%1DF-1:!90$`.*90$*8R(DD]\.!5`5`S +M(#)B26)B39(D@+8I:U(B6HS%)C4*'*L`.Z:@$*:B8DU2(EN<928U%.%F`0`^ +MIM`0IL(B3:#=$=#,(,)B35(B7)R%)C4606"9`9"((()B30P&'+G!8@&A6`&Q60%- +M`ET"TJ`$=JTK)C<;0(8!D#@@`#.F\!"F^35R)%X+YQ9.""8G<28W +M2AMF4L4@2T0,!1S(L6D!D6H!H6L!30(,3':L*V(B6ISF)C8<0'4!@/<@`#^F +MX!"FXF0C8B)>"]86S0@F)GDF-DX;54+$($LB'?```+`X(``SIO`0IJ#H(/E5 +M`#ZFT!"FP'@@V74`-Z8P$*8YE0;D_[#H(``^IM`0IME5AN#_``"@."``,Z;P +M$*;Y=8;<_P``H#<@`#.F\!"FD.<@\F0E`#ZFT!"FL,<@TF0G`#RF8!"F8F0I +M1N+_`*#7(``]IL`0IL)D)4;>_P"0]R``/Z;@$*;B9"=&VO\`-D$`#!:BH0)" +M(E12H\`,"9)B29)B35I2"S06(QN"Q/X66`UR(F)P0!1"8EIP$0`VIC`0IC)B$P`VIO`0IO)B%((B +M6IP(`#:FH!"FHF(C`#:FD!"FDF(DLB)_^,]``ZIO`0ICWP +M\/!T\/;`\F)-,B);%J/@`#JF@!"F0B)-@(!T@(;`H(@1@$0@0F)-QGO_)A01 +M`#JFL!"F@$*:I0@`VII(B8I"0%))B6H`0IHFR`#:F +M,B)B,#(4,F);\!"F^<(=\```0B1_]B0"AB\`PL3^%IP-`#BF,!"F,F))`#:F +M0$*:9 +M0@`VIH(B8H"`%()B6C`0IC)B$P`VIO(B8O#T%/)B7.`0IN)B%!WP`#FFT!"F +MT-!TT-;`TF))`#FFP!"FLB))P,!TP,;`H,P1P+L@LF))1K__````-J9R1;PP +M$*8Y,@`VIO(E*6)%M_#P%/)E(>`0INE"'?``.:;`$*;`P'3`QL#"8DD`-J9R +M1;RP$*:Y,@`VIJ(E*6)%MZ"@%*)E(8`0IHE"'?``.:;P$*;P\'3P]L#R8DD` +M.:;@$*;2(DG@X'3@YL!`[A'@W2#28DD&Q_\`-D$`,M(%#`B"8DDR(R\N"O+,S/)J<,8!````EGP%PFIPD<,`H4X`=H`.@BJ#"YF,F+QI +ML@2.)BL$AOK_K+G"!(Z,'!WP`/(B$>("P`R]\_T)X_T(`#VF'?``@@1R"XA6 +M*/:2!(-6&?9&UO\,*J)$CB6=^,;Q_[+,-+)J<$;H_P```#9!`!R(PJ.TRL*B +M+'\`.*:0$*:RH-0RIEPZ,H(#@+HBDF(1O%B2(A^,&;9)"M(B'Q9-">("OJPN +MLB(?#._W&QLFJQB2(A$,^)<($+(#@(RKXJ`7`#ZFT!"FTD+`\B(1K,\<+0`] +MIK`0IKGBF.(N"O+*S/)K?\8!````EHH$HFM_D<,`H4X`,J9J.C)V@`Z"*H,+F8R8K!FR +M`X`F*P2&^O^<:<(#@(P<'?``TB)&#+YPW1'@W2``/:8=\`PNXD.`)87X!O?_ +M`/+*-/)K?P;L_P```#9!`!PMLJ.TNK*B*W\`/:;`$*;"8D.2(D,N"O+*S/)K?\8!````EHH$HFM_D<,`H4X`,J9J.C)V@`Z" +M*H,+F8R8K!FR`X`F*P2&^O^<:<(#@(P<'?``TB)&#+YPW1'@W2``/:8=\`PN +MXD.`)7SX!O?_`/+*-/)K?P;L_P```#9!`"%O`1WP-D$`DJ#^^W+[@T`@8'!T +M08"$01N(H*<1D%<16E2JI)`X$#"'@@NJ"U504A"@HA!WLPW`9Q%J9`MF8&(0 +MA@(``,!C$6ID"V9@8A!@EO":58"8D)"9$:"($8J$FI0+F0N(@((0H(B0D"(0 +M("*0BB):(AWP```V00`A<`$=\#9!`"%Q`1WP-F$`0B)/HJ`!Y7[CK02Q;P%8 +MDFBB@7,!D7(!DF)Z@F)[^V;[55!406!D0>5=&%F$#!N!=`$;9J*@X*JBHF0` +M@&808F0)Y3SNP78!L`'R#5B0=Q&`=R!R;2<,&)T(GMDJ?B6R:B6R&B6R"B6Q^B6QZB6QFB6QBB6Q=0QH*B6Q;`W)"@S!&0 +MW1':TPO=#$JB2X2"28'B:1ZB28`,+C"@8-#:$-)I(8)+A]J-@FDDXDN(BHV* +MW9#E$8)I)^KC"^[R2XG29*G@ZA#JW<#A0=)K&SK,"\S`RA#:_/)K'/K,^HZ" +M:Q[:[N)K'<)DJ%>V$@P,DJ#_P(41BH,+B("J$,8#```,#)*@_\#6$=K3"]W0 +MJA!13P`Q@P"B:U"JZL)K+N)K"\BXG@7H!(:<`,/\@ +M\FV"P"``,BV"(FV:P"``\BV:@FV%,BXL.24B+BLB;<+R+B;R;4+B+B?B;8+` +M(`#2+8+9`<`@`)P+#`*B;*S`(`""+*R)`<`@`!WP#`(=\```-D$`##L,&E(B +M3Y(C.G(C.X(C.$+5`F+5!Y##!(+(_A98&Z)$GJ(3?)"T!*)4M)"E!((3?8)4 +MM?(3?I"&!/)4MI#W!.(3?^)4M](C0'#D!=)EW,)&/L)&.7#5!8)&-O)&,;)& +M.*)&-^)&.M)&,G#F!'#7!'"E!'"T!'##!'#S!0P(@D91\D2?PD8UPD;:LD8T +MLD;9HD8PHD;8@D;5@D;4\D8[TD;6XD;7<-@E<.PE@D;=@D22\D;DXD;FTD;HPD;ELD;G +MHLK]%@H/V&/(<[C3P-T1TE1&TE1,P,P1PE1'PE1-%DL0Z-/[[N#D0>F%N'-\ +M[!N[P+L0N96B(Q:(!="J$:)EF/(H)RP)D/\@\F@GLA1'HA1&L*J"L<4`H*H1 +ML*J`I2'C#`JQ>P'-!>4AXPP:Y3WCD3<`LJ"`\6P`<.D4PB6VXD20X3D`P,-! +MTB(ETF6T\,P0T8\`PFX4LFFHH@;G@@;EL@;FP@;HP(@1L+L1<,P1T,P0@*H1 +MTJ$`T*H0P*H@PJ#@P+L0'`S`B!"PB""@B"""::G2);;0TT'PW1#2;A3"(B71 +M-0#`P"3:S,)EM1WP`+)$GK)&+,:0_\@%F&.(<_C3DE1&DE89@E1'@E8:C'^H +MT_NJH*1!J86R+"?2K]_0NQ"R;"=&R?\`Z&/IA0:__P`V80`R(D]BHB9@8X"" +M!H@]\"98!`P(@D:(04X`J`/1.0#"H/]2H(S";8*R*B=0JH"R9(*2)(+E(>YV +M@`CB)(;@YE7V3@(&_/^B(G^E4NX,:@`ZII`0IJ(C`((B3X)J%_(&>"8_#@%.D1V!$F/0(&^O^" +MTPB"*"&"8GPF)`6,)`P2'?`,`AWP````95@%30H&XO\````V00#E(.Z(`I%. +M`((H)X)I@IBR#`.V*04RR?[&__\,2Z@"V.+"H(S*JC`]WMK0(,!$GR +M2<(E=P!)HCFR'?```#9A`""B(&5.`5%/`('*`'*A_'IR@F5(C'.2!X*2R?X6 +MJ1X,)BP>LJ>3R`+17`#295-B95G"+"RZL@PMT_P$R26B!X_""X62`EK2"WV" +M"X?R"X"3_0&#_0.2!WV"!X+S_07C_08,#^('HL/]$@N(#!RC_123_16`_(/S +M_1WC_1[293BB"WFY$:+*_A;J$PP)#%Z9E3)E1?('@@P&TJ#X\L_^%C\420%' +MLUH,#S!$P+(BE@8!`!O_1Q](#`H66_\ZS\8"``"R94RR(I8;JK>ZY+T*P_L( +MC0OC^!33^!B)Q6)E#)(BEH*@")PF4X,BFL,$`$!V,1HJ_^H*,0 +MHFFLP"``@BFLP"``R`+Q<`#B+"WP[B#B94+`(`#2)4+`(`#"+"W"94+`(`"R +M)4+`(`",Q#)IK,`@`((IK,`@`!WP'?#1K`"B"WV2`EJQ@`"@K).\6:#;DYT- +M1JK_````%H/K\B<7"\,+_\/_"./_%-/_&/G%:<6R)Q<+N\/["+)E3(:E_PSF +M1H3_``"@O9.="X:<_S9!`'SVTJ?=#$L,*`P*#!E"HGA*4I)%-W(%?*FRJ:(` +M=R."13:!?0%P=Y`@=Z"*=[)'"(+2"(((#?*@_N*@_3+(_Q:C&++(_19+&,(B +MW)")(!8,!<(%K#(%LI)%@@"\(W?L!3+#_Q:C(8)%LF)%K;(5/,(5.S(5.C)5 +M4L)54[)55,(%?+(%?C(5/3)55;)%KL)%K+(%@<(%@#(%?S)%K\)%L+)%L<(% +MC((%D@"\(W?L`A:X&$(%G8S49A04L@7$X+L0LD7$!@(`P@7$\,P0PD7$DD<) +M8D6-XA5+@@6?0@6A\A5*D@6><@6@,@5]LA5-PA5,PE5$LE5%,D6=DE5-\D6,0D6?XE5*@D60('>@VG>"!X!62`F-"BP)`@=Z#0=X#"!X`6#!`B!7T6@A(+@A:X +M"V)%?&)%?6)%@:)%?J)%?Z)%@*)%@@P"F,6QK`"R53JR53NR53RR53T;F9G% +M'?```#(%S#<[`H::_["+D$*B>""(H-J(HDB`L@7.HDA_C0JZ,AN[2C/"0\]" +MH"&PL'1'NP*PBR"R![`8T+,@7-AQ,"@D7.<@7,1I3_`#9!`$*GDTI" +M,@1Y#`T60PG98H("74($A0P6%O@*C/0+E!:)$J+$_A8J$[+$_19+$L%^`/U'IQ6,@E_ +M:K.S]0"RR_\`&T``_*$P_\#S]00;9IQ$\@F`2C\S]0P+,P`30`#LH?#NP./U +M$`R$9[0#&Z<,!E)H&$N('?`,!<;M_X($AU($A=ERMB@XG`62Q?\620RBQ?X6 +MZ@VRQ?T6BPS!?P')8@8-``",]`OD%@X)\L3^%J\),L3]%L,(@8`!B7(&T_\` +MC/4+E19)":+%_A;J"K+%_1:+"<&!`L9(`TD#+3_S(3?UT-,_4`&T2,1I(7?Y/U$+9D!1MF*W<,!%)B +M&$LB'?`,!0;X_Z&$`:ERQK?_L84!N7+&M?_!A@')ERQK'_\8@! +M^7+&K_\QB0$Y;J9VOGJ@@N\D@O,<:P``&@C`-DC=^@_=^E\8(:0((B@2HB" +M*#,ZB(GZT@OA@AN2`-TC@-W`5GTTT@O<`)TCT-<$5KTSD(F0((B@2HB"*#,Z +MB(GZAAH``'?I/-"-D""(H$J(@B@S.HB)^I(+X8(;D@"9(X"9P%;Y,=(+W`"= +M(]#7!%8],9")D""(H$J(@B@S.HB)^H8*``#2"ZP`W2/0W9`@W:!*W=(M,SK= +MV?J2"ZP`F2.0F9`@F:!*F9(I,SJ9F?J""ZP`B".`B)`@B*!*B((H,](;%F(; +M%SJ(B?KR:A#R:A'R:A+R:A/R:A22"SB<[=#0Y/);%IQI@LG_%IA#@LG^%JA' +M@LG]%LA+@LG\%FA-K`;2"SE@8.3R6Q><70N-%DA"@LW^%FA&@LW]%HA*@LW\ +M%BA,."`EYB`EL62#$,&&!HDYT&D_T$ +MQH;_`);Y`-*B2""IH-JJHBHY.JJB;%*""ZV2HD@`B",@B*":B((H.3J(@FQ. +M!L#_D@LV%LD?"XD6>"""R?T6&"""R?P6N!Z=#Y/]$<;T_MJ2#"86F=*"&0!) +M,2D1.2$B"0PR&0)"&0$C]@4B&0-B:A6":A9":A=(,3)J&")J&3@A*!%&/O\` +MVI(,)A;9T((9`DDQ*1$Y(2()##(9`$(9`R/V!2(9`6)J&H)J&T)J'$@Q,FH= +M(FH>."$H$48W_P#:D@PF%AG/@AD`23$I$3DA(@D,,AD"0AD!(_8%(AD#8FHE +M@FHF0FHG2#$R:B@B:BDX(2@11C#_`-J2#"866I(,%H;% +M_WJ2#!;&T?]ZD@P6!M[_`'J2#!8&ZO\`@@);.2$,*0P3@).#."$&3_^"&U*" +MV(`6V!'26U,&\O[2&U1PW<`6;1%B6U5&]_X`#`:2HOR:DD:Q_PP&DJ+\FI+& +MO/\,!I*B_)J21LC_#`:2HOR:DL;3_X(;8H+8@!8H$-);8T;@_@#2&V1PW<`6 +MK0]B6V5&Y?X`#!:2HQR:DD:?_PP6DJ, +MN`*B;?#B*S#B;$"R*R^R9<`=\```TEM2AJK^``!B6U2&L?X``":'`B:&%T@=[TD)8HD)9X@6>9CX<\@6%W&^2H`4`.::0$*8]\`N)%G@JHLG^ +M%AHJN+*M`F4L!+(%?0PZB!7BB0EAB0EG&N_\`#+D`/J8,'PP-H@()L@(*@@((HLK]H-^#\@(. +MH@(+T_@&L_@'T@(/L@($H_@,\_@3J++XHM/X%+/X%=("![("!J/_"*C"T_\0 +MT_@6L_\1L@(%H_\<]$I(%?1=I#*(%>*)""F)""P8#``"R`EG2`EC20@JR0@OP +M$*;A.0#B+L'@X&16+NZ2(X&"(A"7"`*&M?^H`J(J-Q8:!*T"9=O^!K/_`%+2 +M`M(E%[(E%@P#"]T+N]/[",/[$L/[%;)D3`:L_P``PF*RXJ,N#&\,6()BK_)B +ML.)BL7SR'?```,)"#[C"V**2(I8;NQO=V:*PL"2YPI>]`L9]_VFBN++"0@ZB +M(I<;N[FRI[L"QEO_QN7_``Q<#!W21:]IHFFRPD6N+0,=\````.(E+]Q.#&H, +M28*CH()E,9)E+Z)E,/(C@?)E,JT")='^QHG_K0*E]OXM`QWP/0JM`N7/_L:% +M_P"QD0$`.Z:0$*:,2=+)@%;-U`P"'?`````V00"B(I<,`PP-G&JM`@P+S0.E +M`P"@VB`F"BVB(I"(I:RRO^13P"BH`&"R/^S^`BC^!*C^!6M`H)I +M3.4<`*T"I>_^'?``-F$`8B*6#`QG,P)&-P`P\&"Q3P"!3@`,'>T$0.V3#`EA +M^0``%4``K:%VI@=R*$T;F7<*#((BLQN(@F*S?/(=\``,!SILH?D`0_8(G0;3 +M]A!3]A%IRW:J!J(H@QMWC+JR(K,;N[)BLWSR'?``#(<,&CD!\&S`#`-@:I.M +M"6/W"./W"5/W$0`WIG`0IG&2`0`WIF/S%-/Z$E/Z'./S$S)H5=/Z'Z)HR7(B +MEF*@"#(A`'J**BH((URP>#`RWJ&,,&QNG?0R@H'3GN@%]"G)&U185!B85 +M4B8E3S&L`$CF@*B0TJ?<(*J@(M((VJI":A^R2H#"2H$R5CXR5C\R5D`R5D&" +M1H221H72%GSB!B7R!B0B`@PB1HCR1H;B1H?21HDM"!WP?/(=\```TD;,1NK_ +M#!G&W/\`LD;,1N?_```V80`A^0!13@!A3P`]\':B')(E0T(F0W@V@B7#,B6# +MD$0@@#,@<#,@0#,@%O/_,3<`=H`0PB/GR0&X`;"P%+D!J`$F.@(&^O\=\``` +M-D$`#!KES.&(`J$^`((H)Y%.`*"((()I@AWP`#9!`"@"84X`4B(Q,B:!09,! +MD3X`4#,00%,04F:!1X,#'?```((B)Y"((()F@AWP`#9!`$&4`6*A9FIB4A:` +M8A9_^U7[9E!4(3T%4F*78&0A8F*62E52!0!*1D($`&/S"%/S$$/S&#)B$1WP +M`#9!`*T"#`NEH0.,*BT*'?!2H@(`-::@$*:1E0%"H?XRIYPZ,DI"HD-_D*J0 +MHAH`HE0U`#6F@!"FK0*+F8)#@Y"(D((8`()4.:4(`(PJ+0H=\(($DPP,HJ$" +M%H@&`#JFD!"FDD.+%CD&`#6FL!"FLD.&`#JFL!"FC&L`.J:P$*8;N[)#B``Z +MIO`0I@R-X@-]\D.*LB(0Y[T?@@24G)B2`W$F&10,&J)#CJ)$@<%.`,(L@<<+ +M#'SR'?#"0X["1(%&^O\,`AWPPD.&1NG_``Q-TD.&!N?_-D$`4M("0@63#`L, +M^1:T!\*E`G*C`F*GH0P8)A09)B1V)C0304X`,B(00B2!?/)'`P$=\`P"'?#B +MH0(`/J:@$*9J8J)&AQ:Z!]*B`@`]ID`0I@RZ#"\6Y``F%'\RQ/X6(PO2Q/T6 +M30F"17R217WB!7RG'J\`-Z9`$*8F=%+R!GA*_QO_\D5X1N;_``"R17BR17RR +M17W&XO^217V"17QJ8H)&AP`WID`0IO9T##(&>$HS&S,R17B&VO\`/*:`$*:" +M17B&U_^R17RR17U&U?\````\II`0II)%>,;1_P`]ID`0IH*@!4!`%!:$`"84 +M228D:R8T4/)%?()%?0;<_P`^IH`0IH!`!`=H`B84=+)%?:)%?`;6_P`]ID`0 +MID!`%(RD)A0LDJ`()B1.)C0_@D5]#&F217R&S?\`#&L,/=)%?+)%?0;*_X)% +M?`R>XD5]1L?_#'\,0S)%??)%?`;$_PRH#$F217R"17W&P/\``))%?0R;LD5\ +MAKW_`))%?/)%?0:[_[)%?0RMTD5\1KC_-D$`F]UQS.=SY-\L?]\D;HPD5[HD5X!O/_,@8`DJ("%I/\`#FF@!"F +M@D;Z1N__``!R1NC"17NB17A&ZO\`.Z;@$*8,'0P*E>G)21W\`-J90$*:,90`VIE`0IAM54D>` +M`#:FH!"FD4X`@B(0HD>!DBF!?/*7"`$=\`P"'?`V00!"H?I*0C($@@P&9 +M)I,D@J,"`#BF0!"F>K(,&29T++(+@!SZ2KNPJF.@F7.20@IB0@L=\-*A`@`] +MIL`0IJQ\X@1^XD(*8D(+'?```(*E`@`XID`0I@P?'/-`,V,P_W/R0@IB0@L= +M\`!ZDI()@))""AWP```V80!"H0*2HH`,!0P;LD()4D((4D(04D(&FH*BV/^" +M(MVB"O^B0@`(`(S*+0H=\```-*:0$*9&\O]BH?C"H#^QEP'2`@V2`@RB +M(A,6'0(F63:PZB#B8PRM`N6N`+SJ+0H=\*T"$!$@9;$`#`(=\```)EETL/H@ +M\F,,(*(@I:P`%KH'H"H@'?``4D()PD((HF,,(*(@):L`%AH#+0H=\*T"N`'" +M(0'ELP!J,I(3/``YIH`0IJT"#*N"0A!EN0"B`X2VFJ:M`B7I_PP"'?``-*;0 +M$*9J,L(3/-)"!@`\IK`0IK)"$(;U_P``4D()PD((HF,,(*(@):4`%AH!+0H= +M\*T"N`'($>6M``P"'?``:N+B#H3VG@P`-*;P$*;R0@8,`AWPK0)EX_\`-*;P +M$*;R0@8,`AWP`#9A`**C0%*A`H(B_T*A^`P&8D(&8D(08D((2D*2!(>20@`(`!8:$2T* +M'?```#6FD!"F1L__(*(@99``D@(0-VD_@B(&(*(@O0'@"``6"A$M"AWP`,*@ +M/[&7`=("#:(B$Y("#!9M%N+)^Q:^%[#Z(/)C#""B(&6)`!8*'2T*'?```""B +M(*6+`(("$"=H0X(B!B"B(+T!X`@`%LH/+0H=\`"2`@W,J:("$+*@W["J$*)" +M$,("#,+,^Q;<#*T"N`'"(0%EC@#&TO\`K0)EAP`,`AWPK0+EA@`]"L("","R +M0>9[.Y:+`]($A#S$0+P0MIT81XP'X@(0\"``C,ZM`N7!_[(""/`@`$"[$!8; +M_"=CO@`UIL`0IL)"!@P"'?```"9[#PRMMRT"YHN[#+[G&P(FJ[-PS"#"0@B& +MZO_R`@W,SX("$)*@[SWPD(@0@D(0H@(,)EIJK0*X`<(A`>6$`,:V_P"R`@W, +MJ\("$-*@]]#,$,)"$.("#.+.^Q8>#*T"N`'"(0%E@@#&O_\`\@((+`B`_R#R +M0@AIPX:>_Y("#@#B!(3VG@+&EO^M +M`J6J_PP"'?`````UII`0IH(4/))"!@`XIO`0IO)"$,;T_V)""<)""*)C#""B +M(*5F`!9:`2T*'?`@HB"R(0#"(0%E;P`,`AWP``"B!(3VF@T`-::P$*:R0@8, +M`AWP`*T"I:3_`#6FL!"FLD(&#`(=\```-F$`DJ0(#!H,!5)"!E)"!U)"$%)" +M"*)""9J"@B@?8J$""X@6V`BHHBJJFIJ2"82R(MVBHOAF&P)&(`"XHBJ[JJNB +M"H3"H?@Q3P"`9(B$Z"9())C +M#""B("5-`!8Z"*`J(!WP`#S\<9\!L@(,T@(-0J'X2D(6W0>"R_L6*`V2!(%W +MZ0RAG`$`.J:0$*9&`@``L9L!`#NFD!"F)AD+PLG^%NP2TLG]%GT)\A0\`#^F +MX!"FK0*RH`SB0A"E5P""!(0]\+:8!*T"98?_H9(B$R"B(/#N(.)C#"4I`!8Z +M`2T*'?"M`F5I_X;`_ZT"Y6C_!MO_B`$H$8/R#"G##`(=\``V00#"T@+"'#0` +M/*:P$*8,'0P,+$@;NZT+M[@(TD(-HLO;A@``PD(-#"LL+:<]*L)"#"`JH"(B +M&"!`=+P4@)01L)D@`#FF4!"F((AT4$%!BD0'91A`0&"&!``L/=<:10Q>XD(, +MR0/)$PP"'?``0$#420,@0'46%`6`A!&PB"``.*;P$*8@*'7P44%:(@=O#"`@ +M8""0M)D3#`(=\``@D+29$PP"'?#"0@Q:Y(#N$;#N(``^IM`0I@P"``5`T*"1 +MH*80T-<0V1.I`QWP21,,`AWP-D$`K0*]`PR<#(WBH?_RH/_E\?\M"AWP-D$` +MK0*]`PRL#)WBH__RH?]E\/\M"AWP-D$`K0*]`PS,#*WAH0'RH__E[O\M"AWP +M-D$`K0*]`PS<#+WAH@'RI_]E[?\M"AWP-D$`PM("PAPT`#RFL!"F#!T,#"Q( +M&[NM"[>X"-)"#:++VX8``,)"#0PK+"VG/2S"0@P@*J`B(AA\YB!`=+PT@)01 +ML)D@`#FF4!"F((AT8$40BD0'91I`0&`&!0`L/=<:1PQ>XD(,R0/)$PP"'?`` +M``!`0-1)`R!`=19T!8"$$;"((``XIO`0IB!8=6`O$%HB!V\,("!@()"TF1,, +M`AWP`""0M)D3#`(=\,)"#%KD@.X1L.X@`#ZFH!"F"]4,`@`-0*#0D?"J$=#6 +M$-D#H*<0J1,=\`!)$PP"'?```#9!`*T"O0,,C`Q]XJ'^\J#^)?'_+0H=\#9! +M`*T"O0,,G`R-XJ/^\J'^I>__+0H=\#9!`*T"O0,,O`R=X:,!\J/^)>[_+0H= +M\#9!`*T"O0,,S`RMX:0!\J?^I>S_+0H=\#9!`#'Y``P$44\`=J,2/?`]\#WP +M/?`]\#WP@B4Z&T3,J)(BLQN9DF*S?/(=\`P"'?`````V00!A3@`R(A!]`D(F +M@0P(#`)'@PZ"H0,`.*8@$*8,&`8````,!%%/`)'Y`%"B`:G%=JD3XB:8TB:8 +MPB:8LB:8(B4[&T0'X@OR)[,,`AO_\F>S'?",R!=B"H*A`@`XIC`0IAWP'?`` +M`#9!`'%.`%(B$(T"8B>!#`D,`F>%#Y*A`P`YIB`0I@P91@````"A^0`S]`QA +M3P`,`R/T&TG&=JH3XB>8TB>8PB>8LB>8(B8[&S,'X@OR*+,,`AO_\FBS'?", +MR1=B"H*A`@`XIE`0IAWP'?```#9!`#("$(+2`NPS@@B1HJ>@JB*=P9ME(?#,LG.P[1I0$`/:;`$*8=\!WP``#QI@$`/Z;@$*8=\`"!IP$`.*8P +M$*8=\``V00`,)PP84J(P,J"0^:`@'0F2`V2`Q&,>0`^IK`0IK)#Z$)#Z@P8 +MX@,4@D/I@@,/%EX@%J@ADJ("`#FF@!"F@D/KL@.O%HL2X@,0C&Z"`Q0]\!9( +M-I(##Q;Y+X(#ZQN(@D5+`#:FD!"FDD/P"YD6"2BR+X'"(A!\^BT$P+L0L"J3 +M%L(.'?""0^6"127"(A"R+X%\^HT$P+L0L(J3%G@'+0@=\((#YB9(*0`VIN`0IM(#$.)#[!9- +M+``VIH`0IO(#$H)#[1:_*P`VIH`0IH)#[H(#Y@N85JG@P:P!`#RFH!"FL:L! +M#`*B0^^ZJJ(*`*)%21WPT@/FTLW\%FW>`#:F\!"F\D/L`#:FX!"F#`+B0^U" +M0^X=\```@@/F)D@9`#:FD!"FDD/L`#:F/?"`$*9"0^Z"0^V"`^8F&`)F.!;! +MK`$`/*:@$*:QJP&B0^^ZJJ(*`*)%2=(#L!;=(H(#Y@OH%LX>\LC]%F\>@J(" +M`#BF@!"F]C@"!G\`#"A&``"LR@`VIJ`0IAN('`F'N?"B(J_<&H)BLK*B2`R, +M#%W28J_"8K"R8K&"0E]\^BT*'?""0E\,"BT*'?`,"$9>_P`66.``-J:`$*:" +M0^D`-J;@$*;B0^H&?/\,"`9Z_Y(##Q:)U0`VIN`0IN)#Z0`VIK`0IK)#ZL90 +M_P"QK0&2IT":DG:H20`\IH`0IH)9>8""0="($()9@0`\IH`0IH)9?8""0="( +M$()9A0`[IH`0IJ(9@8"`U("*(()9@0`[IH`0IJ(9A2N9@(#4@(H@@EF$QD7_ +M````%LC@`#:FX!"FXD/I`#:FL!"FLD/JQGW_#`C&>_\,&$8X_P```+&M`9*G +M0)J2=JA)`#RF@!"F@EEY@()!T(@0@EF!`#RF@!"F@EE]@()!T(@0@EF%`#NF +M@!"FHAF!@(#4@(H@@EF!`#NF@!"FHAF%*YF`@-2`BB""682&2?^R`P\6RPOB +M`^K@IX.-"D8=_PP8QC__``"QK0&2IT":DG:H20`\IH`0IH)9>8""0="($()9 +M@0`\IH`0IH)9?8""0="($()9A0`[IH`0IJ(9@8"`U("*(()9@0`[IH`0IJ(9 +MA2N9@(#4@(H@@EF$QE/_L@,/%AL%X@/JX*>#C0H&)?\``((#YR88!?+(_5;/ +MX`P"'?`,&(9%_X(##ZSHD@/JD*>#C0J&0?^"0E\,"BT*'?`,",9._P`,"`91 +M_T)"7PP"'?`,*(;O_@PH!A+_#"@&-_\`-F$`#$T,.@PK#`9RH0)-`E*GA5I2 +MD@6'PJ)*(:X!O"D,'7&O`2896Q9#"`N#%K@+]D,%MB,"!CT`#`+*E&))-F)) +M-V)).&)).6)).V)9%6)9%AWP%I,>J0'2P_\6[5/V0P6V(P+&O0`,`LKDLDXV +MLDXW8DXX8DXY8DX[8EX58EX6'?``%H,E"X,6B"GV0P6V(P*&TP`,`LJ48DDV +M8DDW8DDX8DDY8DD[8ED58ED6'?"B!%K*-&)#.&)#.6)#.V)3%6)3%A;**\(% +MBQ:L+8(#WY(3D=)#-@"((Y>80Y(#VG?I/0Q*HD,W!@X```""!%K*-&)#.V)3 +M%6)3%A:H,9(%BY+)_Q89,*)#-K)#.+)#.=)#-T"D(*6S_A9:%BT*'?``LD,W +MK02ELOZL6BT*'?#*I&)*-F)*-V)*.&)*.6)*.V):%6):%JT$I;#^%LHR+0H= +M\,*A`@`\IK`0IK)$7;)%J19;5@P*T@55HD1>HD6J%JU*`#*FX!"FXD63\@5? +M%C]*H;`!`#JF@!"F@)$$DD,H@(`$@D,IP@64#,O'NPO1L0$`/::@$*8&`@#A +ML@$`/J:@$*:B196@\'3RS_P6[T:BHP(`.J:0$*:"!96219GPF1&"R/T6J$:Q +MLP&ZN;(;`+)3$,($71:,1O*C`@`_IM`0IN&T`=)%EN#=D-(=`-)3#[*C`@`[ +MII`0IJ&U`9)%FH(%E:"9D)(9`))3$V8X%-*B`@`]IL`0IL)%G'#,D,(<`,)3 +M$D"D(&5^`!:*):`J()```,HTX@/?\A.1`.XC]YX0\@/:=^\*TD,VTD,WQ@$` +M``"R0S:R0S=B0SAB0SEB0SMB4Q5B4Q:M!*6=_A8Z&RT*'?""!54,&9)$71:X +M0@`RIJ`0IJ)%D[(%7Q9+0N&P`0`^IL`0IL#1!-)#*,#`!,)#*8(%E`S/A[\+ +MD;8!`#FFH!"F!@(`H;%G@]D@6+"YD6J4'"`]^"$Y$`S".`S,!6 +MC`N"`]J`AP16^`H,29)#-H8J`(($6LHT8D,[8E,58E,68D1=8D1>LD65%D@\ +MD@6+"YD6R3JB0S;20S>R0SBR0SFM!*6/_A:*)BT*'?``RJ1B2C9B2C=B2CAB +M2CEB2CMB6A5B6A:M!&6-_A9:/"T*'?``P@/?TA.1`,PCUQP"!B4`T@/:=VT" +MQB(`#$B"0S:"0S?&7O\`D@/?HA.1`)DCIYD/H@/:=^H)#$NR0S8&`0```+)# +M-M)#-T95_[)#-M)#-Z)A`$"D(&6'_A9*$RT*'?``K03*Q&),-F),-V),.&), +M.6),.V)<%6)<%B6%_A::02T*'?``HD,WLD,XLD,YTD,VAC[_`*)#-J)#-[)# +M.+)#.88Z_P"R0S:R0S=&//_2!54633\`,J;@$*;B19."!90,SX>_"Y&Q`0`Y +MIJ`0I@8"`*&R`0`ZIJ`0IK+*_*"0=))%E1:+/&8Y&ZT$LJ`!Y?D!G`HM"AWP +M0*0@I6,`%@H!H"H@'?"M!&56_HPZ+0H=\``,`AWPHJ,"`#JFD!"FP@65DD69 +M\)D1PLS]%KP]L;,!L+F`LAL`LE,0\J,"`#^F@!"FD;0!@D66D(B0@A@`@E,/ +M`#^FT!"FXLG`TD6:P@65X-V0TAT`TE,39CP4LJ("`#NFH!"FHD6<<*J0HAH` +MHE,20*0@95$`%FKXH"H@D````,(%518<.``RIM`0IM)%D^(%7Q:N-Y&P`0`Y +MIO`0IO"!!()#*/#P!/)#*;*A`@`[IN`0IL@!TJ`"X,V#PD65`#NFH!"FO!K! +MK`#"4Q62I@(`.::P$*:B$Q6R19>PJB"B4Q4`.::`$*;R$Q6"19B`B!&`_R#R +M4Q7R4Q:M!`P+Y>+0H=\`````PNRM1B33MB715B71:B33:B33?B33CB +M33FM!&5I_A9*&2T*'?``L:P!`#NFD!"FH:L!@@55JIF2"0"20R\6Z"P`,J;` +M$*;"19/2!5\6;2R!L`$`.*;@$*;@\03R0RC@X`3B0RFBH0(`.J:0$*9`I""R +MH`+EWP$66C(M"AWP`&)%D\;5_@``8D,H8D,IQMG^P@64#,O'NS;1M@$`/::@ +M$*;&#`#AN`'JZ>(>`.)3$$;D_@"2H@(`.:;P$*:!N0'R19:`_Y#R'P#R4P_& +MY/X`H;R0SBR0SG&#_\`LD,VLD,WJ0&& +M+?\`\@/?@A.1TD,V`/\C@/_`5A\.@@/:@(<$5H@-J0$,29)#-P8D_T"D(.4V +M`!9:U*`J()```*(%518:'P`RIK`0IK)%DP`WIL`0IA9\'@PMTD65K00,*Z7) +M`1;J'BT*'?``HJ("`#JFD!"FX@65DD69\)D1XL[]%CX`.)3 +M$0`]IL`0IL)%G'#,D,(<`,)3$J4!`!;:J*`J(!WP`-&\`=K9TAT`TE,0QN+_ +M```V00"M`B4*_HPJ+0H=\`P.PJ$"TJ()VM*"#8BBIZ*JHA;(!@`\IK`0IO*B +M`K)*A;"P=!8+!@`_IK`0IK)*@``\IK`0IA:+```\IK`0IK++`;)*@@`\II`0 +MIH(*=PR/DDJ$AS\(XDJ(XDUV1@,`L@V)#!P6Z_["2HC"37;A3@#2(A#B+H%\ +M\N<-`AWP``P"'?#B2H#&Z?\,2\;G_P`V00"M`@P[)94!C"HM"AWP#`RRH@FZ +MLH(+B:*GHJJBO%CR"G<,'0R.]SX9@;T!`#BFD!"FC$DF&3(F*4S"2HC"2W9& +M`0#22HC22W:M`J4C_HS:+0H=\```PDJ(PDMV1OK_K0*E^OV,NBT*'?#22HC2 +M2W9&]?^A3@"2(A"B*H&G"0-\\AWP#`(=\`PLPDJ(TDMVK0(,2R6,`1;Z^BT* +M'?``-D$`8J>3:F)2!GEQO@&"!H>,1285%R8E)HQS)A--]D,"]B,[)C@HD;\! +MF5(=\*QC)A-`]D,AMB,>H<`!J5(=\*P#)A,V]D,;MB,8>5(=\`"QP0&Y4AWP +M`,'"`5(=\-'#`=E2'?``X<0!Z5(=\`#QQ0'Y4AWP`$'&`4E2'?`` +M-D$`H<7YBB*IG*F9()/))"!N+2".(.*J*A +M_JJB)BXID@J!\@I^@4\`DD(']I\)(B(3*<@,`AWP`*T")0O^@4\`(B(3*<@, +M`AWPDBLO)AD@F*(JF9&6`8(B$\(#B;)""<)"!Z)"!J)"!:)"!*)""*)"$)"(("T*B<2IQ!WP +MHD(&TA,ZX@.)XD('HD((HD(0`#VFH!"FL<@!NJJB"@"@D!2@U`2@Y03B0@72 +M0@220@D6N08G:@Z"$ST`.*;P$*:2`@GR0A#`N0'1(0'"`@62(A/0NR##^QBP +MF2"9Q)(""0PE)AD(XLG^%BX))CELH,,$B'(,"ZT"X`@`C-HM"AWP````/*:0 +M$*8&S_^2`X:VF6:B`A`6"@:M`F7X_0P"'?`\_N)""``\IM`0IM)"!``\IK`0 +MIHRK@A,]`#BF\!"F\D(0`#RFH!"FD@.&HD(&]IE(LB(3N<0,`AWP`-(3/``] +MID`0IJT"#`N(<@R,P,00X`@`O"HM"AWP#`(=\```DA,[`#FF0!"FK0*(<@P+ +M4,00X`@`K'HM"AWP`*T")?#]LB(3N<0,`AWPK0(,"XAR#$S`Q!#@"`""X@6>`R2(PHPF8"@F8"2"8#0H@06Z0LG;0NR%#X`.Z:@$*:B0Q#B +M`PG2(Q/R`P7`[@'#_A;S_AC@W2#9PO($B+:?,8(#$*RXK0,EV_T,`AWP2H." +M"(4`B".`O[,`.Z:0$*;2(Q.@Z0'@W2"@W2#9PLG")CD5#`(=\``^II`0IH:\ +M_P`^II`0IH;)_\G"#`(=\#S[LD,(`#ZFH!"FHD,$`#ZFD!"FC,G2%#X`/:8] +M\,`0IL)#$``^IH`0IO($B()#!O:?=)(C$YG"#`(=\``^II`0IH;._\($A0#, +M(\"_LP`[II`0IE*@`B8Y6_(#!19_"0`^IK`0IHRJHA0^`#JF@!"F@D,0\@,) +MXB,3@@,%P/\!D_\6@_\8L_\:\.X@Z<+"`PDF+&C0PP2(1EP&"(A.M`I"(((G&Y77^%EH&+0H=\`#"$SP` +M/*90$*:QF0&B(A/P(`"PJB"IQJT"I7/^%HH'+0H=\`#2`X8\_N)""+:=!*T" +M);/]@J$"`#BF\!"F\D(&-^0(LB(3N<8,`AWPHA,]`#JFD!"FDD(0LB(3N<8, +M`AWPK0*(<@PK0,($X`@`C#HM"AWP`#=D"Z(3/0`ZII`0II)"$+(#AK:;"L(" +M$(Q,(*(@):W]#`(=\*T"#"N(<@R,P,40X`@`C"HM"AWPK0(,*XAR#$S`Q1#@ +M"`",*BT*'?"M`@PKB'(,+,#%$.`(`(PJ+0H=\%#`!(ARK0(,*^`(`!8*^2T* +M'?``-D$`,J'T#`B"0@>"0A""0@B"0@DZ,F(3.X)"!@`VID`0IE')`6%/`**E +MH%I$0@0`JH)2H0)`D!220@D6V0>"*!\+B!88"[BB*KN@JX"B"H3"R?T6W`I6 +MJ@21R@$`.::0$*;Q:0#B(A/2R?Z@B0&`[B#P[B#B9@P6W0RBR?T6>@XW9!S" +M$SX`/*:0$*:R`XB20A"0T'2VFP>,32"B(.6=_0P"'?#QEP'B(A.M`O#N(.G& +MI5O^%NH&+0H=\`""`X@\^9)""+:8!*T")9O]`#6FH!"FHD(&-^0(TB(3V<8, +M`AWPPA,^`#RFL!"FLD(0TB(3V<8,`AWP````-::@$*:2`@G&TO_B$ST`/J90 +M$*;QF0&2(A.L6O#Y(/G&(*(@Y53^O`HM"AWPK0*"(@>RH`%`P@3@"``6BO0M +M"AWP`*'+`:"I(*G&AO3_`*T")5+^K)HM"AWP`*T"#!N(<@R,P,40X`@`K*HM +M"AWP`#6F4!"F(*(@I4_^K,HM"AWPK0*"(@>RH`%`P@3@"``62N\M"AWP`*T" +M#!N(<@Q,P,40X`@`G$HM"AWPK0*(<@P;0,($X`@`G&HM"AWPK0(,&XAR#"S` +MQ1#@"`"`(`!9*ZBT*'?``4,`$B'*M`@P;X`@` +M%@KI+0H=\``V00`,*0P*%N0&HM("HAHT`#JF0!"F@L2Y%G@,(&2@8B888$PT +M8%`TG(6`I1&0JB``.J9P$*9@A'1P44&*50=G`E!08)R4@(01D(@@`#BFL!"F +M8'#5L$%!<$2`!VL"0$!@DM((D@D:]BD%\%41\$014+#40*"TL_H,04\`MB-> +MT4X`#`7"(A#2+8$,!N*A`]>,"@`^IE`0I@P6QO__#`/Q^0!3^ANIQ':O#SWP +M/?`]\#WP4B0[&S,'Y0V"(K,;B()BLPP"'?```(P6%^4##`(=\**A`@`ZII`0 +MI@P"'?"IQ`P"'?!:5H!5$9!5(``UIH`0I@`&0$+!($@$@%"14%<0@$00AM;_ +M```V80"M`KT#S00,G0R.\J'_@J#_B0$E[O\M"AWP-F$`K0*]`\T$#*T,GO*C +M_X*A_XD!9>S_+0H=\#9A`*T"O0/-!`S-#*[QH0&"H_^)`:7J_RT*'?`V80"M +M`KT#S00,W0R^\:(!@J?_B0'EZ/\M"AWP-D$`#"T,#`P*LJ%L%E0(NI*2&7X` +M.:9`$*9:IH*@?$G_+0H=\#9A`*T"O0/-!`S-#)[QH0&" +MH?^)`>7G_RT*'?`V80"M`KT#S00,W0RN\:(!@J/_B0$EYO\M"AWP-D$`/$L, +M!C(B%T*B3**B6*JC2D-B1&-B8C=B8]UB8_]B9(XB(Y@EP!.AS`%,:ZJC9;\3 +M(F.8,*,@95(`L4X`PB,0LBN!QPL"AB``5OH'4J-I\V)#6FG#DD0R:=-B0UN"1&(6+PVL +M"0NY%@L+YDD9IBD6P`"*@`!WPT@2X=^T(X@3( +MX.<$%D[R,*,@(+(@Y9P`(J``'?#RR?X6W_(PHR`@LB"EFP`BH``=\('!`8E3 +M1M[_D<0!F5-&W/\`K0.XL\(CEZ6H^ZT#)DQV2&`YP2`U"2`PA2`L02`CA6)08))=H)#GK8H`@8X`(CA +M@DE_B-&"27Z(P8))?8BQ@DE\B*&"27N(D8))>HB!@DEYB'&"27B(88))=X@Q +M@DF`@D.39C@$#!B"0Y.((8))@8)#D8@1@DF"B`&"28."0Y+B287R283B0Y_" +M28?228;"0Y"R28BX4;))B;+*_/9+`D9'`)&W`+#"02=K"``YIK`0IJ+*_-T) +MP(%!=I@.`#VF@!"F`#VF@!"FHLKX)DH2#"EL"("*L("($9"((``XIO`0IJT" +M)7,`LB2!DB(0MXD"1C4`PB,O5KSC?/)B8R]28S#BHFWB8S'2)('28S(=\*@! +M*!&"(R]((6@QS/AR8R]28S"(08)C,H*A\H)C,5A1B.%B28""27^(T8))?HC! +M@DE]B+&"27R(H8))>XB1@DEZB(&"27F(<8))>(AA@DEW8D.3)C8K0DF!0D.1 +M(DF"HDF#?/*B0Y+B287R283B0Y_"28?228;"0Y"R28A228D=\``,&()#DT)) +M@4)#D2))@J))@WSRHD.2XDF%\DF$XD.?PDF'TDF&PD.0LDF(4DF)'?!6J_"& +MQO\``*)33:)31R"B("5D`,(D@;(B$,<+'M(C+U8-U2*O_V)C+U)C,/*B=_)C +M,>(D@>)C,I````"B4TRB4T8L"*`.(D@=(B$.<-'O(C+U;/SV)C+X*BAU)C,()C,2(D@2)C,B*O +M_Y`````FJAB2(R]6J)#_!;\"P`Z +MIO`0IO)#^19_#+)$6+)$6<$W`/*@@/)LJ.(#^='.`?*A`,">$;"9$(#N$?#N +M$."9(-"9())LJ0`ZIH`0I@P[75_!9*$2T*'?```#JF/?#P$*:M +M`O)#_674_!:*&BT*'?``LD/=4D0]ANG_@@,%%@@CH:X!`#JFD!"FDD/HL@," +M%FLBPJ("`#RFD!"FDD,0DD1;G`G2R?\6#2OBR?X6;B[RR?T6ORR"%"F2%"B2 +M5!2"5!6M`N6D_+(#Z0S*8D1$M[H+P;$!`#RFL!"FA@(`T;(!`#VF/?"P$*;B +MR_P6SAVP\'3R0^KRS_U6WQ"M`@P;Y48`%CH0+0H=\`""`P46F!VAK@$`.J:0 +M$*:20^B2!%N,^0NY%KL@PLG^%APDTLG]%CTAXA0I\A0H\E04XE05K0(EG?QB +M1$8,.J)$1)*A`@`YIH`0IA:H&6)#ZJT"LJ`"Y4``%FH;+0H=\`"R`P46*QG1 +MK@$`/:;`$*;"0^CB`P(6?ACRH@(`/Z;P(`"0$*:20Q"21%N,^0N)%G@CHLG^ +M%MHFLLG]%BLEPA0ITA0HTE04PE05K0+EE?Q21$!21$&M`N7-_!:Z"BT*'?#A +MMP$`/J:P$*:BI@*R0^H`.J;0$*;"%!S20^S0S"#"5!P`.J:0$*;R`^J20^V" +M%!R`F1'RS_V0B"""5!P6'^^M`B64_!8*!2T*'?``X@,%%MX0@:X!`#BF\!"F +M\D/HD@1;C/D+J19Z%[+)_A;;&L+)_1;\%](4*>(4*.)4%-)4%:T"98S\4D1` +M4D1!K0)EQ/R\RBT*'?```/("7*Q_4D/C4D)<1DK_``"2`^D,B)>X!*($5LR: +M4D/Z4D1#Q@$```!R0_IR1$-R0^-R0EP&0/\`P@/I#(O'NU?2!%86'05R0_IR +M1$.&]_\`4D/H!G7_``!21%OB%"GR%"CR5!3B5!5&??\,R)(#Z:&L`*)4')#A0>)4%$9S_P"" +M%"F2%"B25!2`@4&"5!5&E/\``*(4*;(4**"A0;"Q0;)4%*)4%<9H_\(4*=(4 +M*-)4%,#!0<)4%49D_P#B`ESB0^.&V_X````V00#!QP$,"#S]TD((@D()`#RF +ML!"FHJ$"LD(0`#JFD!"F,4\`0M("0@1_DD(&0D('(B(3*<,M"!WP```V00"! +M^@``.*8@$*8`.*90$*8`.*8P$*8`.*9`$*8`,Q&`51%0(B"`1`%`,R`P(B`= +M\```-F$`84X`@=`!*$``YIO`@`,`0IALS-#O#XP(#_$2#_(``_IN`0IC$W`*&G`"(CK,&J`(*O_B!0!`=B$8"" +M$()CK,`@`$(CK$)A`,`@`,)FFL`@`+(FFL`@`*)FFL`@`)(FFID!P"``G$4B +M8ZS`(`#2(ZS9`<`@`!WP5LCXANG_'?!6>/B&Y_\``#:!``Q/#!NBT@*""H9! +M3@`,!18H#,*A`@`\IJ`0II'1`0`YII`0IK9Y&=(BKU8=`?)BL))BLN*B@(*@ +M!8)BK^)BL7SUDJ"(D)."FI*R:=U&&0"X`K(K)[)D@K(IK+#0!`=K#7#[$/)I +MK,`@`.(IK.E!XB1"P"``P/X@\F1"P"``@B1"P"``8F17P"``\B17P"``XF1" +MP"``@B1"@F$$P"``C'VR::S`(`""*:RR*C>PJR"R*P"E%^G2)('"(A#7#`-\ +M\AWP\3D`\B_!?/[P\&3P7I,M!1WP``P)@?D`#`8,+':H!M(D0QN9G'WB*B_P +M(`#,WL)J+_)J,&)J,H*BDX)J,7SU"<_T( +MX_T0TF13TBFL+-_18."_9M`O9-!?+-^A8/$^*@B.#C +M@H*@`N#B@()NW;)*A=(IK-#P!`=M#G"-$()IK,`@`((IK()A`8(D0L`@`,`X +M(#)D0L`@`#(D0L`@`+)D5\`@`#(D5\`@`()D0L`@`#(D0CD1P"``C)_2::S` +M(`""*:R)$=(NWK(J-MJ[LF1.X?D`#`MVK@;R)$,;NXR/@BHO/?`6"`E\]7:` +M$^(IY^DQV#'0T!39,;@QLLO]%EO>1OG_`.*@B.#C@NKB\F[=LDJ%LBFLL-`$ +M!VL-<(L0@FFLP"``\BFL^2&")$+`(`#`^"#R9$+`(`#R)$+`(``,/_)D5\`@ +M`/(D5\`@`()D0L`@`/(D0ODAP"``C*VR::S`(`""*:R"80+2+MZR*C;:N[)D +M3D;6_P``8FHRXJ+D#$\,*()J+_)J,.)J,0;6_P``TJ"(T-."VM*R;=U&S/\` +M`#:!`/T#L9,`P6D`@3<`G0+1?`#`(Q'B*.4I$>DAT-X0X.0T@.X!X-T@,.!$ +MTFCEPFBFZ0'2H[C:V>*@B*(HIL*C+,K)J3&R:*92**:A?0`,"U!0=*!5(%)H +MIJT)1@(``.J[ZLSJJM<:1B(JW;8B\"8B9V8RZ@P$,BK>@BFW\'5!(BF6.HB` +M=Z`60OU8`8T,``5`=H`76`<;1%!0D5!0!%)(4&(IEG+'$!N(9[2R1OC_P=(! +MB#&Q?0"1-P"`@'2PB""X(:(IY<"[$,%\`,"J$+"J(*)IY8)IIAWPB!%2*MXR +M*98B*;V2F+$P%*C+)I+4$2`8%`4=I4*(%`$4D20("%! +M&T1@,D%VDR4@,`0@44$@800@<@0@(P1+1#)$C&)$C5`Q07)$CB)$CS`Q03`A +M03(IEB@X8J!@-S8"AIC_4J,LFDMBPZ!@@!1:1':8"B"`!()$L"`A01M$8#)! +M/?!VDR4@,`0@44$@800@<@0@(P1+1#)$K&)$K5`Q07)$KB)$KS`Q03`A08:% +M_P```#:A`#%.`'$W`%*B3-',`?*G=.*B6,*BK&(B%PP$#`NY@4EQLF(W2`'* +MQNKF^O;:UEI6LD5CV5'Y8>E!\J``X?H`TJ`$@B80LF4LF4?DB.! +MEPAFDB>LD*`$!VD3?.B`B1""9ZS`(`"")ZR"80'`(`!)H4@&*9$ATP&")"=9 +ML2"((()C@L`@`%(C@L`@`%BQ0B0G0F."2*'`(``B(X+`(``HD8S*DF>LP"`` +M@B>LB1'`(``,*@`ZII`0II'Y``P8"Z1"H`"@2(-V@"``/::@$*:I(8@AS+@, +M^``XIJ`0I@P80)B3J"$+F(;1:D!O8T9[)%9P`^ +MIJ`0IH(F$)(C@8"9$(*A`)"HD_;Z."::'9*@"Y<:9O+*]!9O%H+*\Q8(#9+* +M\A9)$_+*\1;/";),`@P8@DP#D@5B#`H,#_F!J7$,#X8``)(%8B8I"((,`H+( +M^U:X[0PB'?``D@(\C,D,*Z*@C*JB)8'H#`(=\,(%9XPL#`(=\+)%9PP"'?"A +MU`$`.J9`$*:2)A""(X&7B#46)!6"!EJB)I<6J!4,'ZT`PP*J7&(@1;H$I(%8@;=_P"2!6)&V__"80-@IB"E.0"RH`#( +M,?(C@9(F$`Q-X?H`]XD"%HH3LD5B#`F&T?\`R3&M!F7-^Y:Z$#Q+F#$,.@P( +M@DD$@FDR@FE4@FEV@FF8@FFZ@FG:Y]N7Q_`P+R#&")A#R(X$,3>'Z`((%1?(%1_)%/.)%/<(+9=(+9-)%/L)%/[(+FJ7G_:T&9>OZK0:E +M;/L,"\@Q#$WA^@!6:@Z2!6*"R?L6"-VBR?Y6ZMK&'Z`)>(158J!+AAP@9:H@N9L@N:#!W2 +M13K`NH.M!F4=_0P+R#&"(X'R)A`,3>'Z`(>/&-Q:R3&M!F55^ZT&95;[#`O" +M(0/2H`3A^@"2!6)&%?\``)(%8D83_P``H@7(H*<$%CKO#"\,&()%9?)%8I(% +M8H8,_Z(%N'?JZ?(%R/#W!!9/[4;W_P!F*=E&N/^X80Q(L@N<#!H,";":@Y)& +M6X)%8H:\_ZT&#"T,/@P,PD9;XD5BTD4TTD4UPD4\PD4]PD4^PD4_9X%M(C*%;M`%)C*$)C*:)C*^*B?^)C*GS] +M`#NFH!"FHDPV`#NFD!"FDDPW`#NF@!"F@DPX`#NFX!"FXDPY`#NFH!"FHDPZ +M`#NFD!"FDDP[`#NF@!"FXJ0"H=8!@DP\%G@)@:T!`#BFD!"F&YF27!\`.*:0 +M$*8;F9)<(``[IH`0IH),0ISH`#ZF0!"F#.A"3$.'%!&2H`^7E`L`.J:`$*:" +M3$2"3$4`.Z:`$*:1^@""3$86&`L`.Z:`$*:"3$<6"`L`.J:`$*:"7"6+B("# +M08)30``[IH`0IH),3)RX`#FF@!"F@DQ-`#FF@!"F@DQ.`#FF/?"`$*:"3$\` +M.Z:0$*:23%"\>0`_IH`0IH),40`^II`0II),4@`^ICWPL!"FDJ9VLDQ3FI)V +MF!,`.J:`$*:"66\`.J:`$*8KF8)9CBT-'?#8`MBMI[T8@B*O5HCIHF*R4F*O +M0F*PDJ)QDF*QAJ'_``P-AJ#_@J!X@E-`1MC_````.:9`$*:!UP&*A(((`$), +M2."($8)30``^ID`0ID),20;/_P`V00!-`H*A`@`XIN`0IF+2!^)&U``XIM`0 +MIM)&U0`XIL`0IL)&U@`XIK`0IK)&UP`XIJ`0IJ)&V``XII`0II)&V0`XIG`0 +MII*B`G)&V@`YIC`0IG+2`C)&VS)'DV8S!`P?\D>3`#BFL!"FLD;1`#BF +MH!"FHD;=HD>2`#FF/?!0$*8RIVQ21MXZ-"(&44'Z`%)'D':2"@`TIB`0IALS +M(D-_`#BFP!"F4=4!PD;?%AP+`#6F(!"F#'D,:BP-#",P(I`B5T8B5G`G/7.R +M)R\6ZPI\\@`UIE`0I@PKPA=-L%604E='4E9Q5[P(PB]%^(G+U9>^")G,J)G+Y)G +M,/*CS/)G,<;<_PP"!MS_`#(73"(732)71S)71@P"AM__DD>4QNG_`))'E1WP +M(F`?)+6/)+6?GK\D3U\D3,\D3+\D3*\D3(\D2Z\D2Y\D2X\D2H +M\D2G\D2F?/NR1,FR1+>R1+:R1*625&B25%^25%:R1*21K`"25&.25&*25&&2 +M5&"25%J25%F25%B25%>25%&25%"25$^RH,"25$ZZM+)D-@P[LD3T#"NR1/:2 +MH*Z:E))D-9*D=)J4HDF!\FD>PFDA#$_R28#*_*)$]_K,H3<`VMSR:23"9$>R +M1/C29#?:^/J(\F0X@F1&^HZ"9#K:[N)D.9(JK-@$X4X`D+`$!VD2?.S`R1#" +M:JS`(`""*JR)`<`@`($Y``P"P4\`,FB"\BTG\FZ"@BTLB2SR+2OR;L+2+2;2 +M;D*,ZY)JK,`@`+(JK+D!P"``'?`,`AWP-J$`L=\!0B)/<4``PJ",J`1B)U)2 +M)U'*JN7AYY%.`(&/`+@$TB,VHJ"`LBLKA_T%H,L@PFG"\B,DXB,DTB,DPB,D +M@/\0\/ET@J'`@.X0P,`D/(B`W1""(Q[@YG30TW06:"^R(QX,2TD!V2&"(QW) +M$=(B'!9X+J(C'0PJJ5&BH5"JI-)JX,(B'L)JX9(B&I)JXX(B(X)JXG(C&G)J +MY7@!0B,60FKVTB,@PB(8@J3$BG?:S,)G-9(C(8(B&)J(@F6'*F9)G.((C'()G.6"$!4(C'T)'\."(`4'@`=(B)6!U +M!=!W`=)JY,C3T>$!0(@0^\S0=Q"`=R#`Q$&!X@')BI(C$F#+!&`Z!-#,`=#, +M$.`S`=%I`$`S$/N9D)1!2$&9FF"F!6"4!4+$E$+L1T(@0T+L0L+,@T>8!4#Q$ +M8#,1T#,0T.X0X(@@TJ,`4.H4@.X1T.X0,.X@X+L@,3D`XJ$(L)D@D&8@L3<` +M4)05@)D1T)D0H)D@D(@@HJ",HF-=@'<@J&%P1"!RH("86I)C7H(B(I*@D.)K +MJ("(`8)KJ8*@>')C7=)C7G*@8))C79*A#H)C7G)C74R'V$K28UYP9B!,S8(B +M'7'G`9)KJ)%``("(`8)KJ4Q(@F-=7(A8F-=0F->TF-=V-QAZ`'(W`#=$6#=$,#`M-#,(,)C7L*A#))C78(J +M-9*A&X)C7G)C77*A*$(J-T)C7N)C7=(J-M)C7L)C7:(J.*)C7H(B%Y)KJ)@Q +M@(@!@FNIPB(DTJ$'TFNH@,P!PFNI +MHB(DP8H`H*!TP*H@HFNFH4X`DBD6DFK='?`,"P9"_PP*QD7_`#:A`.$^`)'I +M`0P,LJ1$T4X`8J340B)/4BV"@BV::F2ZM,)&Z*(B@*)K7Z$Y`'*AB'ITDFH\ +MDB?5DFH\D3\`,BH8\34`68&0,R`R:A@Q-P")D?)J3N)CVE(B&8&%`$P.4%!T +M@%4@4F.F\B?5\FI*XFI,X>H!XFI.\!"F@B)_#`7PB,`6J`^(D?&#`)"(((EA +MB('PB"")488%`/`0II(B?QO,\)G`%FD-@J`3Q[@"1C,`@B/GB0'X`?#P%/D! +MF`%F.>Z2(ZSR*B"04`0':1)\Z(")$()CK,`@`((CK(D1P"``#"B`_R#R:B#` +M(`#R*B#`(`!V@!""(^>)(8@A@(`4B2&((28X`P;Z_P!\V("/$()J(,`@`((J +M(,`@`(Q%DF.L\B.L^(&849)M@H(M@HAA\FV"DBV"F)&";9KR+9J2;9I,"8(M +MFO(GU?)J2I)J3.)J3H``IHRH=H`$\`"FC"\&_?\`=H`3\B/G^3&8,9"0%)DQ +MB#&"R/T6"/)&^?\````,!?)4%/#`]<)4%9`0II)4%I"0]9)4%X`0IH)4&("` +M]8)4&8`0IH)$-(#(=8"0]9)$-L)$-X"(08)$-8`0IH)$.(#(=8"0]9)$.L)$ +M.X"(08)$.8`0IH)$/(#(=8"0]9)$/L)$/X"(08)$/8`0IH)$0(#(=8"0]9)$ +M0L)$0X"(08)$08`0IH)$1(#(=8"0]9)$1L)$1X"(08)$18`0IH)$2(#(=8"0 +M]9)$2L)$2X"(08)$29`0II)$3)#`]<)4)Y"809)$3<`0IL)4*,"(=8)$4\#` +M]<)$4I`0ICWP/?"``*:,F':`!/``IHP?!OW_LF$'P"``D!"F@!"F\!"FP!"F +M\3X`@34`D>L!DFH\@FI.\F/:PB(;\84`P,!T\,P@PF.FDB?2DFI*@B?7@FI, +MXFI.0*0@4FW;4FW<4F?E4DO<94H`4J``HB?4#`NR9^FR9_.B9_72)A7")A;7 +MO`JM!+*@P!`1(*5A`!M59D7FX@0[#$L67AL,#_E6#!F21R62!#FB!#JB1R(+ +MB1:H%Z+)_A:*%MAQ#`H,#,)-2`P9XLK_%LX9%@H>#`FB!$:21R.2!#D+^A9? +M&8+)_1:H&ZAQ#"F22D3(<<(L*!9\'-($/!9=%`P>XD2"D@0^\LG[%M\-@LGS +M%G@-#`JB1(_1K`#B%"?R!#G"%"C@L'3RS_W`H'2`JA$6;Q6PJB#`^'2`_Q'@ +MN'2@H/2B5#WPNR"R5#RPL/2"R^`6&`K,&])4/(+*X!88"LSJTE0]1@(`#`L, +M"J)4/+)4/=($2I"#!,AQD@0]T.`DT/0DT+<$@DQ2LD28\DP>XDP@LDP?T-,$ +MTDP=-VD$##F&``"0D@221L"0H'22%!DF.E>R%!@;R<#,$<)4-1N[P+L1LE0T +M0*0@I=$`=H`0\B/G^4'H0>#@%.E!V$$F/0(&^O^")CF"8GP,`AWP#!JB1(\& +MR?\```"RRN`,#,)4/%;;]0P-TE0]QMG_X@0Y)CX)&YF0D2$+F9)4&:(4&!NY +MLE0U&ZJB5#2&YO_"!#H+S%;LZ,8```!6&NCH<0P:#!W23D@&H?\`\@0[%C\( +M@@1()^AU#"F21(*&JO^B!$NY5A9:Y,($21;\XPQ=V58&CO_B!#GBSOY6GN7& +MEO_RR?U6G^:8<0P(@DE$AIG_L+H@L+#TLE0\PLO@%MSL5AOMO0W25#Q&LO\` +MPLK^5NSCZ'$,'=).1,:.__($.0O_5F_A1H7_`+)$@@:/_PPX@D2"!HW_#`F2 +M1((&B_\``#:!`-%.`)(M@H(MFK`0IG*DR'IR,@?T0J`!%J,/LE("L%#U4E(# +M\!"F,<(`\$AU0D((,/\0\F(#T!"FTE((T.AUXD(3T-#UTD(2D!"F@@(YDD(4 +MD*#UD,A!PD(5HD(6D)AUDD(7)C@+0A(#0(@4@LC^%C@;DM("HBFZ#`462@E] +M`F*@`(&``.':`:*@`':`(K`0ID(2`[#0](#=P-"Z@T#(%"8<$AMFN6?R*;H; +M54MW][5@AO7_``#2`CFPP/7+-28]'``#0$!`L28=/P?D`L+,_K#0]`"\$="[ +M((;Q_P``\@)&9B_KRS7@W!#PW1&PP!4``T!`\+'0S"#P\`1@T2'PW3#@W1'0 +MS"!&\?\'9,(KS$;O_QWP``#B)SX,"K#NP!;.#V$Y`%$W`.$_`/&#`,'J`>#H +M(/#Y(/E1A@4`L!"F,B<^&ZJP,\`6(PU"H!.GM`)&,@`R)>R9DS"9DXP`*:,HW:`!/``IHPO!OW_`':`$_(EY_E!N$&PL!2Y03A!,L/] +M%D/R1OG_````#!1"1_2&??\``#'L`5*A`#`T$%`S(#)2`T:._P``-D$`#!8, +M>H("/3(".4+2!0P%,L/^4F0B4F0;4F0A%F,54F0?4F0@4F0=4F0>L?$!T?`! +M\>X!F9B9!(R95WR95[H9'$U``QF\.X@\>\!\F5=XF5>R)3Q\P'295W`S!%@ +MS"#"95ZHE-'U`;)E7<"J$6"J(*)E7CC$P?0!@F5=<#,@,F5>Z-2A]@'R95W` +M[A%@[B#B95ZXY''X`=)E7<"[(+)E7HCTT?,B00\?D! +MXB01#%OR95W`[A&P[B#B95[")!+0S"#1^@'295W"95ZB)!/` +MJA&PJB"Q^P&R95VB95Z")!9R)!2`B`&`=R"!_`&"95UR95XR)!;`,Q%@,R!A +M_0%B95TR95X=\)($M&)D'V)D((QY4F0=4F0>!JC_8F0=8F0>QJ7_````-D$` +MHJ$PI73G%VH(HJ$P)73G%^KVHJ$P97/G!WH(HJ$PY7+G!_KVH=H`4J1\6E*2 +M)2Q!.0"7ND#2)1:1_@&@W8#291:BH&"B9%W")1;"9%Z")2NR)2R0B(":N[)E +M+()E*^5NYR+2`N(BM:<>"Z*@8.5MY_(BM:>?\W'N`>$]`-'_`;%.`/(%I,(E +M**(KQ&#_$?#,(+#,`=#,$."J$,"J(*)KQ"(E)X(E*)'O`9)D78HB<"(@(F1> +M(B4LLJ,`#`>M`J4R$6T*LJ,`K0)E-1$,2')D7;$``F"0M$"J$;"J$*"9(+*@ +M8*T#DF1>@F1=)3,1P0("\0$"#(V@X'3P[B#B9%[29%W"9%ZR)2B"!:2B)2HZ +MN[)E**<[%Z";P))E*)RHHB4L@BBH3!E7^<'^O:!1@!"HQQ`0H"2 +M)(Y1.0"7N#6B)&^BV@BB9&^BH(RB95V2)&^295Z")(Z"V/B"9([E6^W#+#'P/#,$0O,R7'&```, +M?=EQ:3$Y$5DAL3D`V'&H43#`=/AQ2)&"(E@;GYE!D)$AFHB"8EB1``+F3P,, +M'FDQB#%H@0P_H*!T0$01R:%`=1'!"0*0=Q"01!"IX?#]0Z(A$OGQTLW\2<%R +M81%!!P)Q!@)`9A'9T4"($=$(`I"($)!F$&FQ@F$0800"#`EVKN.(X?C1,B$2 +MZ/%2(1`P.L`P[Y.`[A&@\+0,`S)K7?!5(%)K7E(B8F#N$."((%II#$5P9@'0 +M9A!@:"!2:UW`9B!B:UX,AF)K77)K7C)K73(A$:+*(/`S(#)K7C(B8E)K75@1 +M.CEP,P'0,Q`PB"#`B""":UYB:UU":UYA!`(6-098H3BQ#`B":UWP,R`R:UXR +M(F+@52`,3CHY<#,!XFM=T#,0,#4@P#,@,FM>#(,R:UTQ"@(R:UXXP8)K7?`S +M(#)K7@R#@B)BXFM=X0L"@(F`<(@!T(@0@%4@P%4@4FM>,FM=XFM>2YF"(1*H +M0;AAF`&`BK""81*7.$NB*R'"`HB8,;(+M-+,_A;]#`O<%ET/``M`#(S`P+$6 +MRA&2R1"(D?B!V"$<#N#@L>K=B_^*C()A"?)A"-)A`IDQ&[K(80P-TF$2LFPA +M\B)BZ'&(D:@AN('(,=(A$M)B6\)B7[)B8*)B78)B7OKN&^[B8F+VOD,=\``6 +MV0P)3)I)#5M)3)Y(#0-(3'.(#9/(#0<(3';(3 +M'H(#0J(3'Z)3,8)#9K)3,,)3+_)#9>)#4M)3+I)#9-(3).(#1/(#0_)#9\(# +M4N)#:-)3-@"\(\#'!!;<"%)#0%)#06)#0F)#0V)#1"(C+X&L`()3'()3'8)3 +M'H)3'QLB(F,O#`(=\````)(#4@"Y(W?I!JT"#`PE#@"R`T"M`L*@``"[(R4- +M`)(#018I"689JU)#0%)#06)#0F)#0V)#1"*@`.*@_=(#B,(C+_&L`/)3'/)3 +M'?)3'O)3'QO,X-T0TD.(PF,O'?`````@HB#"H`!E"`!20T!20T%B0T)B0T-B +M0T0B(R^!K`""4QR"4QV"4QZ"4Q\BP@$B8R\,`AWP``"2`XBBH/Z@F1"20X@& +MJO\`L@.(PJ#]P+L0LD.(!J;_`%)#0%)#06)#0F)#0V)#1"(C+^*@_M(#B(&L +M`()3'()3'8)3'H)3'^#=$!LB(F,OTD.(#`(=\```-D$`4@+T#`ABI'57LQ>, +M="84."8D1R8T5#!SD"!WH&IW0@>`C`0=\$T(L@+V+!F"1W\;J[JR,DOWP@+U +MH#!TE[,!30-''-Y"0O8=\`P4#!TP@:G>" +M1X!&[?\,23!SD"!WH&IWDD=_0@>`ANC_````-N$`K0*E_P"AW@&"$A:RH*YR +MPBJG&!S"`CDF/`72`CL6S7*2$A;B$E^0[L!6CFFZ\O)B-8(7`J<8$9(2%Z(2 +M7Y"JP%9::;#"@,)B-M('#R8]!>('$"8>!*T"Y?L`@@=8\@'RS_P6?V7H$=CA#`S)5M(M +MQ><]`H9N`7GQ.!%(L0P-#`X,#PP9F7'Y4>EAV:%`I)`+,PN$B3$Y0?"J$3%. +M`'NJ0$`422&I`0QT1A``````N.&R*]CF>QZM`J6+_Z*A,&7@YE=J"**A,.7? +MYE?J]LCAPBS8IGS@R%;H$=CA&\S)5M(MQ0P/\F8BYST"1E`!T@(]-^T+X@([ +M)AXG\@(\)A\AN`&((;"S019X60O8%JU3XLC^%EY4P/`4%N]4"[NM`B5Z_YBQ +MP0,"B.&R)54,#0P*J<'29AO29AS91H(HQ,"[$+"P];G1ES@"!@L!#`?&$``, +M&1N*X*B3&_K`KY/V.@*2H`"B`DV3^Q:3^Q>C^QBR94R2)AB,.0NYLF88V$;H +MPS#"`A86G##2 +M`A<6O3#H<:"U!+)&C(S^\A((DJ`!\/:4%O\KD(#TB:%V@`>B(]JG!`4]\$;\ +M_P"@DT2V*?/2$@.@S#46K/Z@J#4'[0L,&?9:#0P)!@(````,'J"NDYT*%NG\ +MF#&(1@P?EY@+R$&H5L>:!`P=TF$&X@(5H@(4T@(2#`G"`A.-"=/Y``P=P_D& +MH_D,X_D2J&'HH;/Y&*"MD\T.X,V3P_D9H_D:DF/)F%;2`A;"`A>H1M/X`,/X +M!J/X#)/X%//X'X)CR8Q^#`X,"(EQXF$*HA(#D@(YH-$4H+Q!H/,$N8&@N!0F +M.0?BR_X,'."\@^(2"*#`!`=J"H'C`3WP@.X@XE((X(T$#$DR81$B81`,"N`N +M!#T*(#F3#"DM"H`ID^",!(`B(`R)X(\$@*F3B$8PJB`@JB`X5BB!J9$S^`@C +M^!$X42C!T_@5L_@7\_@9P_@:.B(;(C$W`*/X'(G%(F.YJ#4B(1`R(1&0JA"@ +MHT%F&A5V@`J(-9"($("#0688!PR)!OO_````%LP+F$;<":*A,*6MY@=J"**A +M,"6MY@?J]OP'L0,"HB55L*H0N-'8L:"@];>:`>S+U[HJXB8;X.1!X.K`MDX& +MK0+E5/\,%PP/^=$&!`"BH3`EJ>97Z@<,!X(F&X)F')CAHBG/[$-/[$9#($(#3!/#H$*T.T_L2 +M#!_`SY/#^Q/@KY.`P`2C^Q2M#,"ODZ/[%:T-EX@"QBS_&ZV&*_\`N&*YQ:@U +M#(F0JA"@HT%F&A)V@`K(-9#,$,##068(IOBVA[^@K0*RH,#E%_^&\O\``*$#`I(E5:"9$*@QD)#UISD" +MQJ;^=H`5P0,"LB55P+L0R#&PL/7'.P(&H?X]\,;X_P!X\9('_-+)_1:]%.+) +M_!9N"O+)^A;_$QWP`,"`%(+(_19("ZT"Y2;_AK'^!VP["[L@HB#E)?\&KOX` +MK0)E)?_&J_["$FB0S,!6+);2H,#:TM)B-<95_N(2:)#NP%9NEO*@P/KR\F(V +MQE;^K0)E(O_&G_ZM`N4A_\:=_K+*$(+)$("$(;"T(;FQB1'&9?X`Z!'8X0P, +MR5;2+<7G/0*&V/_HL7GQ"^[I,88=``QO\D?\QE3^DD?\1E/^#%@,"0P:HD?] +MF4:95H)'_!WPP@(\5LR,NM+28C4&,?X+NZT"91O_QH/^Z.'B+MCF?B`@HB!E +M)?^BH3`E>N97:@BBH3"E>>97ZO;R(0[R+]BF?][")@68$8CA&\S)5H(HQ0P* +MHF8BE[@PK0(,"]BQY9$`X0,"TB55X-T0Z#'0T/7GO:9V@!"!`P+R)56`_Q"( +M,?#P]8>_D@;Z_WCQAJK_K0(E6O\=\#9A``R+44\`,A(UTA(TP4X`@J4D("1T("@N"U!+)"IA8T0@OT%J])XJ``X_81,B(U#`1IE4Q6 +M2:79M6G58B(V2>4R`PBR!@CHY0#S(P#K(W?C*W?K5/#OD"#NH.+>!.(N.ZKN +MZ?6R!@@`NR.PNY`@NZ"RVP2R*SNJN[GUQA4`=^LHX#Z0(#.@,M,$,B,[JC,Y +M]?(&"`#_(_#_D"#_H/+?!/(O.ZK_^?7&"@#B`J0`[B/@[I`@[J#BW@3B+CNJ +M[NGUL@*D`+LCL+N0(+N@LML$LBL[JKNY]3("I``S(S`SD"`SH#+3!#(C.ZHS +M.?5"91!"91'B!X@<#[$Y`!;^(@L^%F,U,L[^%D,_XA(\\:P`8@*$G([@X.1" +M4CP6!@$+-A:S.S+&_A931#+&_19S1N(2/6("A9Q^X.#D0E(]C/8+-A:C.C+& +M_A:#0S+&_1:C16("A/*@G!86`>+&_Q9^(#+&_A83,^+&_18^/F("A186`3+& +M_Q9S(N+&_A8>,C+&_18S/6("AA86`>+&_Q9^)#+&_A83,>+&_18^/&("AXSV +M"S86DR;BQOX6/C#RQOT67SL,`]('EN("@@P?#`;BSO_0;X/@/X/2`CKB!XSR +M`D/3_@'2!Y1C_@/S_@5B`H_R"'#3_A)C_A0S_AWS_A[B93C2!X@RW`1B"3_2 +MS?X6O0_2"3WH`M/V!6)E.4)E//(N,_D#,@APXBXM\J!\,_X(XF5"T@*DZ`DX +M&0#=(]#=D"#=H-+=!-(M.\`S$<#N$:JMHF=9TBG],.Z"HJ!XZMW2:?ZB:UTR +M)UDR:U[R:UWB)UKB:U[8:=)E1:@)V!DQ?`'`JA'3^A2B948R94CR"'!B$AFB +M$ACRS_T6WPC`JA%C^@RB94ER!X@,+&("@HR7"^<6'AKRQ_X6_R`,#O("1^/V +M`_#Q!//V#6)E2MC9TF530F59J,EX`L"J(*)E6'(G-')E0#((<#+#_1;3+S(" +M1U=C#4$-`E*A!%)K74)K7AWP#`K"H03":UVB:UX=\`#2`H)6W>_B"3[2"3L6 +MKD0,']#?D^T-X_8$QKG_8L80HLH0H*0A8&0A"V8+JL"J$8;7_P``,J$`,FM= +MX@B0P.X1\.X0XFM>8@*"%K8R"^86?C:F1@(&FP#F)@*&F0!"0H1"0H5"0H9" +M0H>&:/_Z8@PN%L;?,A8`*1%)(7DQ0@8,3%"!@QR%@`B%@-#_@5" +M%@'B91HR91LB91PH$7)E'4)E'G@Q2"$&:_\`^F(,+A;&VS(6`"D122%Y,4(& +M#'(6`B(6`4/^!4(6`^)E)3)E)B)E)R@1#%((09C_P#Z8@PN%J;9 +M\A8`22$I$4(&##(6`B(6`T/^!4(6`>)E*C)E*R)E+/)E+2@10F4N2"&&6_\` +M##X&F/_R(C;R#PKP.\!6HQP,#H;T_@``8J$`8FM=,@B0P#,1\#,0T#,@,FM> +M8@*"%@8E"^86?B&F1@)&:@#F)@+&:`!"0H1"0H5"0H9"0H?&'/\`#!YB(C;& +MLO\,'F(B-L:^_PP>8B(VQLK_#!YB(C;&UO\R"3L,'PPN,.^#!GG_\B(V,B(U +M\@\*,@,*.0'P,\!6LQ8,#H;3_@``,A).,M.`%K,9XE)/!A#_`#(24/`SP!8C +M&>)24484_P`R`CD,%@LS,#:38J$`8FM=X@B0@#,18#,0P.X1\.X0,.X@#",P +M[B#B:UYB`H(6MAX+YA8N'*9&`D9&`.8F`L9$`$)"A$)"A4)"AD)"AX;N_@P. +M8B(UQH3_#`YB(C7&D/\,#F(B-<:<_PP.8B(UQJC_8B(V,A8`,M.`%K,6XE8! +M1NO^``!B(C8R%@+P,\`6\Q7B5@.&[OX``&(B-3(6`#+3@!9#&>)6`4;A_@`` +M8B(U,A8"\#/`%G,8XE8#AN3^``!"0H9"0H="4CQ"4CT,+N)"A.)"A<;,_@#R +M`DH&D/[R"3I"0H9"0H<6/PPR!XP+,Q;S"M)"A0PNXD*$QHC^ +M`.)6`$:0_@``XE8"AI;^``#R"3H6GPLR!XQF$P(&)P#20H4,+@P_\D*$XD*& +MXD*'!GS^```R"3I"0H9"0H<6\PKB!XP6W@G20H0,+_)"A49T_N)6``9\_@#B +M5@*&@O[M#48X_@`X`5;3\>T-AC7^#!\,#M#O@T;L_M)"A`PC##[B0H4R0H8R +M0H?&9?X`[0W&+/X,+PPS,D*$,D*%\D*&\D*'AE_^TD*$#"[B0H7&7/X`#"_R +M0H3R0H7&6?X`TD*$#",,/N)"A3)"AC)"A\94_@`,+PPS,D*$,D*%\D*&\D*' +MQD_^`-)"A0PNXD*$QDS^``PO\D*$\D*%QDG^`#9!`(("]D("]0P)?/*`1,!` +M*9,=\````#9!`%("[,*@`V("]5!0%!:E``N%%N@()B4")C5^#`B2`O:B`O1J +M0()F@RIFR28&B28!":1\R4DXR4D\R4E`R4E%R0J2"0J7" +M$A3B`IGR`IC2#8C20JCR0J;B0J?"4E8M!QWP`'SR'?#"0NQ&ZO\,&,;<_P"B +M0NQ&Y_\``#:!`$DA#`HY,8*C;"D!*`%989AABB*(,:)B@*)B@9%$,#=)JR8IWB"&2 +M:LGM!X/^".E!\_X0Z<;9QMG&V<;9QNQELB95R&%`NQ"PL/4;V]<<*,(B@,#$ +M0<#+P+9,'*@!983^#!6&!````**A,.78Y5?J!PP%TB*`TF*!XB/_`D;9_Y'Y`':`#:(F0PN9H*`4%HKT%EGTQOK_*&$=\```-D$` +MF+*(HC$/`CG"^XC[F9"408"$09"(@I$.`H"(L)"($9J(DJ_`D(@0B=(,`AWP +M-F$`H1`"O0$,#&(B3VD!2*)HD@P-^T3[9F!D04!$0:7``CT*L1`"98T/##4, +M#**@X'*@F+*AO+JR>G*JHJD#DB)0DF,^PF,]4F,Y@B(\(J&`B4,J(\)"SK)C +ME+*@")('H))"U(('H8)"U>5IY:T#(F$!Y7L`##D,#`PM+0-2PQA`9H*RH("Z +ML\)+E-)+E@P>XDN5DDN2DDN0@1$"8&:00J#T2D.09A&"9U2M!D"T(,*@`=*A +M`"6W`J)B3HLB5Y+IH1("O03"H`'2H0#EM0*]!%@1#!RB8SK2H0"A$P*EM`*B +M8SNB8SPBH`BQ%`+2HH#0TX""R\!VHF>2"`#""P#"33+""`'"1?/""`/B"`+B +M1?3B"`7R"`3R1?;R"`)%]\)%]<(+`<)-,\(+`^(+`N)- +M-.(+!?(+!/)--O(+!R(+!N)--R)-.(N[PDTU\DTYDD7RB]V+50P"X14"XF=5 +M'?```#9!`+ASHB,&L*J"L<4`0B)/H*H1L*J`Y7?:#`JQ%@+-!"5XV@P:)93: +M4L00\1<"XB(E2Z3Z).)B(MACPJ#8LJ#@^]W0U$'29#>(<[JSZ`3[B("$08)D +M./AC\FX*V'/2;@ME=@^2!1`,%C=I#[+$*$P,HJ)RJJ0E=0^2!1!':0RRQ&A, +M#**BLJJDY7,/PA0.YBP"AB,`#`H,&W:`!QNJ\+L1QZL#1OS_`)*A))J3,J(J +M.C2B0]S"`]7"9;^R"7AQ&`(62P:""7^"0]+R"7WR0]WB"7[B0]#2"7O20];" +M"7G"0]6R"8&R0]MZM*()@*)#VH()>H)3;/()?/)#U^(I(>)K'M(I(M)K'\(I +M(\)K'*(I)*)K'6)#WI@%)AD$H@*`C/H=\``,"H;?_PP+LD/>1OG_`*T$)>H` +ML@,>J`2PL#2R1?FXJJBZ^[NPQ/3[JK"T0:"D0:)3(\"J@K)3(J"@]*)3(<($ +M(7I4!VPA#`P,#;*@^*"JH."J$;"T@"64`K(3(:)E0;"[H."[$65@#[*@D*$9 +M`L(3(](3(JJDP,P1P-T1TE0,PE0-I5X/HA,AMCH$"YI&```,&9"@])P*#`D; +MF:"A059Z_Y)%C6)"@!WP#`NR18UB0H`=\``VH0`Q-P!R(D_"(ZQM!Z@'P-`$ +M!VP2?.F0G!"28ZS`(`""(ZR)`<`@`.$Y`$$:`K*@_T)J)T%.``P(\1L"\F2" +M@FHJLFHELFZ"^$92QA"Q'`(+GQ9I+)+/\19Y*@P?LFHK6:%2H=5\_EI6D@6` +M4@5_@FHN@FHP@FHSXFHO,)D1X1T"0%41XFHRD%4@#.FP52!2:BU2:BR2:C0, +M.[)J)I$>`I)J,5(J*U)DPE%/`+(J+;)E0K(J++DELBHFLF1"\F1$LJ$`\F1% +M\F58LF28LM0$DF2`XF3`DJ`.X68`@FL`DF5`LBHGX+L0LF2"DB2"C*W"8ZS` +M(`"2(ZS`(`"BH6RJHJF!95SE#`^R)CNA'P+BH*CJYI(>Y-(>XZJFPBI_"]T+ +MF")CCB)C>0W2#`B`'`[A&`[B"(H>)E +M1M)E2>(($!P,R7'@L`16BQF8"`N9%CDDF3,D@R?DF3,HB)_97WEPJ'4RL?)D<(,>`RZ%@P4'%:!(`+2)Y1V@"4+ +MB,(D@[(DPY@U\B5#XB1#P+L@L)D@D/\@\.X@C*X6F`_H#28N!L;T_P`6V`Z( +M#8+(_H!J@Z#VP!8O'0PE#!JE4]JB(]VI(9(A`B*@"%"9())CW7:`"<(CW/?#@W1#28]UV@!"2(^>9,8@Q@(`4B3'X,28_`@;Z_ZB! +MI4/EJ)&X!\&#`,)D@K(K)[)D@J(*>B8:!-B1(DUZ]J8$#)[GMA$A`N)J*T94 +M__B1\@^%%J\6##(=\`P?6:&1(@*2:BL&3O^H,J+*_%8ZX\)DBT:0_RP<#!W0 +MVR#22!#"9(M&C/\`#"[I#256`@RZTB>4AL#_*)$,#_)"A`P"'?``'`:BH1"J +MIZE1I4T`LL<0N6&B2_JVRB'"URO"#"0,NAPF5LSIV)'2#8-63>GXD1P&#`[B +M3X,&HO\`F)%,"@P(@DF#@FDD93[:J&&H"@NJ%NH.K0>`D8G``SJIYX"QB8` +M)HX/9AX"!B@`:''BSO<,G>!M@V4SY0RZ\L;U5H_>(1T"'`8,2\*@C.(GE*@' +M#`W9#LJJY0#EB)&Q(P(,[.+4!`P-\1X"\F2`(F3`V0["94"2)(*H!PPOL)D0 +MDFHGDF2"\DAZ!GG_B)$,`B)(A0PR'?``5ACVJ&&B*I`,*9)J`"5!`D;4_P"M +M!^4M`*E!1L/_#,9&W_\`#+;&W?\`N&&H4;(+^F4\`$;:_P#8D:T'#!S"37CE +M.0\<5L;5_P```#9!`"$D`AWP-D$`(24"'?`V80`,'4@"<3<`\J#_#`QB)ZRQ +M3@!1&P)@H`0'9A)\Z("&$()GK,`@`#(GK#D!P"``,3D`@1H"@F0G4FN"\F0E +MPF0J\F."B$*2PA!1'`(+Z!;>#^+(\1;N#E)D*WSS@J'4BH+R"('B"(#"9#/" +M9##"9"XR9"\P_Q%`[A$Q'0(R9#+P[B!0[B`,[_)D-.)D+0PUXF0L4F0F41X" +MXB0K4F0QXFO"X4\`\B0M\FY"\B0L^2[R)";R:T+2:T3RH0#2:T72;ECR:YCR +MVP12:X`R:\`,Y3%F`,D/4FY`\B0G,/\0\FN"XBN"\28"#%M\_OKR%NH`8F>L +MP"``HB>LHF$`P"``XF_3XF_.XF_-PF\[PF\ZPF\WPF\VPF\YPF\XPF\UPF\T +MPF\SPF\RPF\OPF\NPF\QPF\PPF\MPF\LXDGYTF@EPDB"LDAZ'?``,2$",F0K +MAL+_@2("@F0K1L#_```V00`,,U$G`D*ARV*@C'*B2'IR:F)*0I($@X8&`*T" +MI8(`/0J2!(."R?T6J`L+J19:"[9#`L8K`++)_A;;"L("(,"0!`=L(-(B`-(M +M!29=%P`UIN`0IO*@_I("(";.!?"9$))"()"0!%89^ZT'Y4$`9AH"QB0`@B9Q +MB`B2H*\F*'^B!'T,VZ>YFK<:9,*@L\<:D=*@MM>:B^($@I$@`E9N!\(BE/%. +M`(%/``N9TB^#LB_#HB@#@BA#\B]#T+L@L*H@H(@@@/\@%A\&%AD&J`R!3P#Q +M3@!F*M&X#"8K(ZT")2L!/0H&S_\`+0,=\`RR'?``P@9^]LPS!*(*@(PJ'?`` +M`%($@'T(+!M:PIK,&R4@('0R3()B!'^WL@%]`G<6W7)$@!WP#!D@H[!ZJI)* +M@(;M_R"SL'J[@DN`QNK_#$P@T[!ZW<)-?X;G_P```#9!`%("`3("`@P'+!17 +M$QL;96!@="I54@4$1[83@@(#8D(!"XB"0@,M!1WP(J#_'?"2`@-R0@$+F9)" +M`RT%'?`V00`,%I("`8("`@P*+`0;>'!P='AF" +M)G&(""8H!0;T_Q::&/I7D3DP5P`#.WBTP0,"_$=`J@'@1X"@F.` +M\F/`#"^Y#M)D0,)D4_)D6:(J+$Q9+`S`JB"I)+GDF=2"!1S8`0"((["(4W"( +ML((H3MJ(B?3B!20`[B.P[E-P[K#B+D[:[NGTP@9^<,RPPBQ.VLS)]*(%WZ+* +M_A9J$`P9F;3")YBA*`+)(2>\5>@A>3&J9^#BP.D1#`)X(;(5)WIRK0>ERPX] +M"J)F@+(5)ZT')2NW@QQ@``JF<,`L(5)S(F@`O,QY,3LF:`TB9_/0&````G!0`-::`$*:)`3@!K`.8`0M$%JG^ +MJ`'1^@"L:@`]IL`0ILD!N`&R0@!I`2@!'?```#>F\!"F^0'H`18._6D!#!1& +M\O\,$BD!*`$=\#9A`)'Y``P&#$4,^@`UIH`0IMQX`#JFP!"FR0&X`8PK:0$, +M&0N95BG^#!(=\*'Z```ZII`0IH'6`0`XIK`0I@`XIJ`0IG$J`G!R@-('?T*@ +M`58]`<@"LE(,HE(-J;RYK*T"Y1D`0D=_LJ("`#NF\!"FHJ4",J)".B+R0KT` +M.J;@$*;"H@,RH0+2`KW@X'3B4F`6O0F"`L\66`B2`K^0E,"20K\`,Z:@$*:@ +MH'0F&GAB0LX`/*:0$*;V*3``,Z:P$*8,"0`SIJ`0ID")(*"8DP`SIO`0I@R> +M@-D1\D+0X-T@`#VFP!"F#`(=\```PLG^%IP+TLG]%OT+#`D`,Z:@$*:@E),` +M,Z;P$*8,GH#9$?)"T.#=(``]IL`0I@P"'?```&)"OP;?_P``0D+.QN#_``!" +M0K\`.J;0$*;BH!>B$A?20M'0T'37/GNB9R(`/*:0$*;V*3@`,Z;@$*:2H``` +M/*:@$*;V*C$`,Z;P$*8`,Z;`$*8,FD"Y(&)"SL";DX")$:"((``XIB`0I@P" +M'?`F*4_P`` +M.Z;`$*8,*J"9($;>_P```#NFT!"F'`E&U_\`-D$`01<"#!92H3U*0I($@#*B +M*#HR%CD(@@,4=^@26G*R!_\`FR,@F;!:F9()`28I;[(#'`";(W?K"B"IL%JJ +MH@H!)BISD@2`8D,F#(4F&4/H`MB^Z*[[W=#40?ONX/1!TE,DX.3T\E,CPA,C +MX-V"TE,BP,P1PE(,LA,DK0+`NQ&R4@WE!`"A&0)B1("RH)"JHF5_#BT%8D/I +M'?``#`7&ZO^M`@P,I9__L@?_(*(@PJ`"Y9[_1M[_``"M`@P,)9[_(*(@L@,< +MPJ`"99W_1MW_`#9!`%*AU%I2,@6`0A(,P2L"%D,$#LB?#B#3R)$/B)T/`NR"PB""`_R#P[B`6;A,6:1/8"B8M +M$H;T_P"H`@Q+PJ",RJKE5.2B(I38"M+-_A:]1/("(%=O"8$M`H)C'X8!``"1 +M+@*28Q_2H@*A^@#A-P"(`I$O`E*A`HA8PJ4"L3`"@LC[%B@7@3$"`#BF@!"F +M)L@##.(=\``ZIH`0IOB1@D_/`#6F\!"F`#6F@!"F`#6F\!"F`#6F@!"F`#6F +M\!"F@J,"`#BF4!"F@3("4%6@@%6@^!5909J"B5&""(-2H0+P\/06V#V"$@SW +MF*:2H*B:DIEA^&'R#V(@_[#R+TYJ__)D1``UII`0IKB1L@O<%MLY@B$)@@C3 +M%O@YD3,"B)&X40P/\DC8DFLR\J0"`#^FL!"FDB$)D@G<%BE%`#RF@!"F`#6F +ML!"F`#6FD!"FK&EV@`T`.J:`$*8`-:;P$*:<7\;Z_P```%8)[ED*98(*(@8+8@X`@`HB/QDB/W(*J@HMHDF2J"(^0,&ZT" +MX`@`LB42&T2W--/H@1ONZ8'1-@(`/:;`$*8F'`Z!-P(`.*;P$*;RS_\6[Q*8 +M<:(E$QN9F7&G.0(&40"XD:T"#`1"2R*EEP%6:AS(@1;\"^$V`@`^IM`0I@P$ +M)AT"QMW_#`[Q.`+R8SWR8SSR8S7R8S3B8S'B8S#B8RWB8RSR8SOR8SKR8S?R +M8S;R8S/R8S+B8R_B8R[B8ROB8RK1,`(`/:;`$*:"I0(`.*:P$*:PL'2Y@:*B +M`@`ZII`0I@`XID`0ID)C]_(E$@P$%N_S@B/>K0)@MB#@"`"R(_&8D:(C]R"[ +MH++;)*DKDADAPB/DE[0+K0(,"^`,``8"````K0(,&^`,`,(E$AM$QS3`!K__ +M`-(E$@P$%CWO@B/>(*(@8+8@X`@`LB/QF)&B(_<@NZ"RVR2I*Y(9(<(CY)>T +M"ZT"#`O@#``&`@```*T"#!O@#`#")1(;1,!F%&R*3R2*3VAV@"`NQ&PF2"@F2"A3P`,"))J3*T"@F)`948. +ML2<"Z)'840P,HDXBPFT]PFT\`#NFH!"FHLK@%AI3#!(=\"T*'?`,$@P_\DPB +M'?``B)&HF`RR#`F9"E)((AWP``#XD9"P=+)/TU;[Q9B1#`B"2=@&&?^(`HD1 +MB*BR`X#W&`V8$?FI9AL&#"NR0X`,*YA!^!&8*8B_D)#TF2&7&`N9OV8;!@PK +M#"F20X#RH*CZ\OEA)AL[R`*HO,BL^ZJ@I$'[S,"T]*)?Y,#$0;"J@L)?XY(? +MXZ)?XJ$9`L"9$9)2#((?Y+*@D*JBP(@1@E(-Y1H.F&&2&>*V.04+F88````, +M&0P+D)#TC+EV@`8;NY"1](P9AOS_J%&R2H&M`F6<_Z'Z`,*E`N$W`/A1B$$, +M&[)/@Y@XDF\>B$B";Q]&V?X``#RFL!"F^)&PL'2R7VM&Z/XX88(C$`S/FHB" +M9U+R9U0,"()G2()G1X)G7Y(#8`RKL_@%D_@)@F=@DB=ALM(C8/DC\FO"D)ZT +M0)DCDFO#DB=B&XA@^2/R:\20GK1`F2.2:\6"9V"2)V%@^2/R:\:0GK1`F2.2 +M:\?R)V)@CR/PGK2":\B!7`!`F2.2:\F`_Q#R8YP&XOZ1(0&0FR"2;O""(C<, +MB8_P```#RF@!"F +MF)&`@'2"66N&GO^B9U(,R+AA@F=4#`B"9TB"9T>"9U_2"V`,K_/X!=/X"8)G +M8,(G8=+2(\">M&#,(\)MPD"9(Y)MP\(G8AN(P)ZT8,PCPFW$0)DCDFW%@F=@ +M\B=AD5P`\,ZT8/\C\FW&0,PCPFW'\B=BD)\0\,ZT8/\C\FW(0,PCPFW)DFN< +MQI#_F`*(`9D1F*FR`X"'&0V8$8FI9AL&#"NR0X`,*X@1B+CW&`V8$?FY9AL& +M#"NR0X`,*_*@J/KR^6$F&SS(`JB\R*S[JJ"D0?O,P+3THE_DP,1!L*J"PE_C +MDA_CHE_BH1D"P)D1DE(,@A_DLJ"0H**`P(@1@E(-Y=D-F&&2&>*V.00+F48` +M``P9#`N0D/2,Z7:`!AN[D)'TC$F&_/\```"H4;)*@:T"95O_H?H`PJ4"^%'2 +MH@(,&[)/@T8]_[*@H/*@>$8V_[*A0/*@\`8T_[*@@/*@8,8Q_[*@L/*@D(8O +M_[*A8/*A($8M_X("()*@_I"($`P9D(@@@D(@#"(=\+B1#"JB2R)&E_X`X2$! +M\3<`V&'@ZB#B;_#8W0R,USP"QEC_@3<`#$_P^R#R:-U&5?^("E88W$:!_ZB1 +M#"F22B*&=__(D0P+LDPJAGG_```V00!\%EJ$.G(Q.0**)V*)VK_@BB!\B\D04\`,4X`BO_R9$1V +M@!6R(X8,&@P)T+L0L+:5L)J#C%P+S(QYQOC_#!(=\```%FS_6%&"HB2*5<(% +M*?P/HM;@.#`*RR_X6&TWH4?+>)B)O&R)O +M&<(.(/D!(FZ85VP+F$&!+0*":7X&`@``N$&A+@*B:W[(4=$[`F%<`'+<`=K, +MR1&B(06E4P""!=S"H`%6B`^2(04,#>A!F$D,#^(N@0NI%FH>HLG]%@H>LLGQ +M%JL=B%&(")BXB*@`F1&0B"")A(A1HA@-DA@,`*H1H)D@J#&28\8B9#BXZIC: +MP+L!P)D1L)D@F62R!=N`NQ&R8\@!#,B" +M8U22+C#B+C&"*Q:`F1&0[B``B!&`[B#B8TBR*Q8@ZQ'@NR"R8T>&!0"B(05E +M^`X;L_P"8,9(IF9+)_A:9,:(A`+(J +M,*(J,8"[$;"J(+':`+"J(*)D3*(A!2)J0&6R#<@!#`FB12HB;#$B;#"B!2HF +M.@@F&@72ROY63>,M"1WPZ%'B#B$'[@VH427/`)T*N%'(`88"`*A19<,%G0JX +M4<@!)CDPMDD,#!\,.()%*O)%*8;B_V8IM0;A_YA1HAD-DAD,`*H1H)D@F81& +MB/\B12D,*68YSJ(%*1:J!0Q-`#VFX!"F%NXF@@Q1#"F`B!&0B"``.*:@$*;R +M*YBB:T"GO\R2%227NL:X466Y_JA1)8``5LHLR`&H40P;LDQ2H@HA!VI=T@7; +M)BU7J%%EN@6="KA1R`'&YO\,;0`]IH`0IJ&1`0`ZIO`0II(,4/+/@19?"PPO +M@(D1\(@@`#BF\!"FH@Q1#"V`JA'0JB``.J:`$*:)(9(5)()K0)@1N%&B;N+2 +M"R'(`0?M#H*E`@`XIO`0IO)L-X8%`*@ATBPRH*J@T*J@TJ4"`#VFD!"FDEH! +MHJ$"`#JFT!"F%KT0`#JFX!"FK-YV@`\`.J;P$*:"*[T;B()KO9Q_HJ$"AOG_ +M#"Z+V8#=$>#=(``]IJ`0I@;1_Z*A`@`ZIH`0IO(%X@PH@/\1@/\@`#^FX!"F +MXE5J`#JFT!"FDJ("`#FF@!"F@D7;\J,"`#^FX!"FD@7;XD7C%AD$TJ,"`#VF +MD!"FDD7@"ZFB1>`+F9"0=!99%0`90`P8H3P"HFPF`(BA@FPHL/@1\.!@XFPK +M\L__H(@1@FPI\FPJD@7;TLG^%ET.X@NTC(X,Z0P_\D4J!AD`@@LA)V@YD@7B +M#!J0FH,,^CN9H)EC#"J`F1&@F2``.:;@$*;2H0(`/::@$*:@H'2,2@`YIM`0 +MIO*A`@`_IN`0II@1@3@"@FD<@FD=@FD@@FDA@FDD@FDE@FDH@FDI@FDL@FDM +M#`E6B=L,'=),4J(+(:"@!%:J"JA1):4`G0JX4<@!!F?_````5BFS\J`"\FX` +M)94`XB4+QLC^*0X,(B)%*@RR'?`,$AWP#"B"1=M&-_\```!6&<*B(0/R80:B +M*FK280<,*9D*Y9$`#!S8$+J:)%X0N9 +MD)!T%BD$`!E`#!_A/`+B;"<`_Z'R;"R@CQ&";"VP_Q$+CX)L+O#P8/)L+P:V +M_X$S`H)L)H:Q_ZA1I8\%G0JX4<@!1CS_+0H=\)$S`I)L)P:M_P```#9A`(*B +M`@`XII`0IC*B1#HR@@/$S!B20[M"H0(`-*;@$*:RPA0,#Z%.`-$?`H(3%,(3 +M%=K2`(@1@,P@PFI3D@.[P@/$\DOTDLG^%ND(%GP5DBU_@BLU'.^:B()J3O)J +M5,(3%<#`),)J1JS.J`%V@!$`-*:0$*;2`\3B`[N,;9Q9/?#&^?\`&ZHF+@CR +M(RSRSP'R8RQ6B?ZI`0`TIJ`0II(#P@PJ@@/$@)D1H)D@%G@+`#FFP!"F`#2F +MX!"FT@/$/?`6_0H`-*:0$*;R`[N20[PF+P220]$=\!WP``"2TB-67`""*M&"((X)IQ$!5(U)IQ<)J8((J8<%<`(!> +MM&"((X)IQD!5(U)IQX(J8L#($(!>M&"((X)IR$!5(U)IR<)KP<:]_P`YIM`0 +MIM)36D;0_](;!,@!X@.[HA-:T,R"4M(CRJHF+C'B`]&L3I(ES))ERZ)ES*#Y +MP!9?\I"*P()ES0;'_P#"TB:2*[B9`9FLAJ;_DB7+1O;_`&(ERV":P))ES](+ +M#-#2!!9=[R(ET68"!"T)DF71('$AH*>`YAH"AB<`YA("!BL`O0+E2@W-"FD1 +M:!%J9Z863.82`@8I`*T&O0+)(65)#9@AH+G`HB7,\+L1LF70>JJF&D/F$@(& +M)0"]`F5'#7T*IA9$YA("!B0`8*8@(+(@)48-H,?`\,P1PF7.QI[_YA("QB`` +M8*!@O0+)(65$#:"@8)@AQNK_`*82?*"@8+T")4,-H'!@YA:ZIA)WO0)@H&`E +M0@V@H&`&[O\`:1&F$FZ@H&"]`N5`#:#`8`;7_P`@L&!I$>4_#:#`8$;3_ZT& +M(+!@R2'E/@V@H&"8(<;4_R"P8"4^#:!P8$;9_ZT&(+!@)3T-H*!@1MK_K0:] +M`L)A`B4\#9@AALK_O0*E.PU]"H;/_P``K0:]`J4Z#0;1_P"]`B4Z#AXF4HL-X1T)!@DF4K"]V@[A'B +M92G292I2!-,F)612TB9R15+R`B%B%&L';PDB)3)B4@$,`AWP8F4W#`(=\``R +M`J@RP_Y6X_&"!-P6"`L`-J:0$*:&Q/^R`K0]\!9[\Z)$(@SB'?```#BFP!"F +MPD3;AL7_`#6F8!"F8&!T8E1KAM'_`)($W!89"``XIM`0IF($V1:6_%+2)@MF +M8&!T8D39%G8'LF4G`!9``(>A@F4LH)@1DF4ML(@1"YB292Z`@&""92^&UO\` +M`#:FH!"FAJK_`#BF8!"F8&!T8D38QL'_PF4FALS_````-J:0$*:21,Y&K?\` +M-J:P$*:R1-#&K?\`-J;`$*;"1-6&E_\`.*9@$*9@8'1B1-G&W?\`PF4GQK__ +M```V00`,%6*E`D+2(Z(B0#*B+#HRLA,A)1,-HF3QLA,AHB)`I14-HF3P@@(A +M!^@-`#:FD!"FDF3WA@4```"R(D#")/*PNZ#`NZ``-J:@$*:B6P&BH0(`.J;` +M$*86K!,`.J;0$*:<77:`#P`ZIN`0IO(C,AO_\F,RC"Y&^O\``#JF@!"F\@/: +M#"Z`_Q'@_R``/Z;0$*;24V8`.J;`$*:RH@(`.Z:0$*;"HP*20],`/*:`$*;Q +M,P*2`]/1/`*"0]N\>0`\II`0II)#V`NYLD/8"YF0D'06^1'29.8`&4``A:&" +M9.BPN!&@B!&"9.FP@&""9.L+N[)DZI(#T[+)_A;K"\("M(Q\#.(,/=)#(AWP +M\@(A)^\"AB``D@/:#/N0E8,[F;"98X"9$>"9(``YIK`0I@`ZIH`0IH"`=+P8 +M`#FFL!"F`#JFT!"F#`+!.`+"9"K"9"O"9"["9"_"9#+"9#/"9#;"9#?"9#K" +M9#L=\````#JFT!"F#`+!.`+"9"K"9"O"9"["9"_"9#+"9#/"9#;"9#?"9#K" +M9#L=\``,`N$X`N)D*N)D*^)D+N)D+^)D,N)D,^)D-N)D-^)D.N)D.QWP`#RF +MD!"FDD/9"[FR0]D+F9"0=*R)TF3G`!E``,6APF3LH/P1\F3ML,P1"_SR9.[` +MP&#"9.\&PO_R9.9&OO\`\F3GQK[_```V00!!/0(`-*8P$*:"H0)2P218!1;# +M!0`XII`0IC"GP#K7%HD%J04`-*9@$*9"P2@RP2`X`T@$O.8`.*:0$*9@H\!J +MX[S)J01H!6P'=Z8$8L9`:06FQ@2RQL"Y!5@$/?!WI012Q4!9!.;%`1WPPL7` +MR00=\'D%1NO_.01&\O_9!<;H_P#I!(;O_P```#9!`,$]`@`\IK`0I@PNTJ$" +MHL$DJ`H6:P@`/::`$*:`DA'@F2`6.`@`.::`$*8,'[#_P/#S@OKW@/_`"__Y +M"@`\IL`0IG+!*++!(+@+>`<6+`4`/:;P$*:`DA'@F2`6+P8`.:;@$*8,'<#= +MP-#3@MK;X-W`"]W9!R@*5Z(#:B(I"B>D!&#BP.D**`=7H@5@(H`B9P`G)`$= +M\&#RP/D''?!Y"D;F_[D'1O/_````.::`$*8+^_#S@OKW^H@;B(D*!M__```` +M.:8@$*8+C("#@HJ+BB(;(BD'1N?_```V00"B(D&2(I0,*!NJHF)!B0EE```= +M\``V80"BH`$E[]?EZN*A/@#13P"13@#A3P`,#,)I@,)IP,D.PFU`LBF"N0&( +M`:"((()I@AWP-D$`>`.S +M`PP"'?`M!1WP```V00`,%1P#)[,##`(=\"T%'?```#9!``P5'",GLP,,`AWP +M+04=\```-D$`#!4<0R>S`PP"'?`M!1WP```V00`,%1QC)[,##`(=\"T%'?`` +M`#9!``P"'?``-F$`K0+E%@",2BT*'?```%%.`'$9`K$W`)$^`GRXHBOPPBO= +M,J(H.C*`C!"":]V"`]="H*A*0H+(_A:H#8$?`8"*$()K\'IR82H"FI*9`6IB +MB`&"*,VM`KT'X`@`HB8\L3X"DB9"(*J@NJJ2:C&")BJ]!ZT"X`@`P("0PBT4\`)BAQF*/2+4SR$R,, +M#-#H=/#N@M#0=.K="ZW0K(.IX[D)LD,GX@,N#!_R0R46S@2R)&^A1@`;N[)D +M;Y(E@0R8H)D0D)M!D"B3'?```/$A`0R-\/H@\FOPXB(W#$B`C"#G/0(&Q?^" +M:]V&P_\`R`E6?/@M"AWP(D,F1NG_`+)#+K(D;Z%&`!N[LF1ODB6!#)B@F1"0 +MFT&0*),=\`RR?/T,'N)#)])E@1WP-F$`D<,`,4\`@M(KB*B"80%V@!&B(T,+ +MF8SZ%IDALB*4N`LF*PC&^?\````6B2!"PA#!3@#R`B&BHB*JHN(*W?#Q!-#_ +M$?#N(.)LC9A"#!;2R?T6'1+2R?$6O1'B`B#X`N#@!(B_^*]`[@$`B!&`_R#P +M[B#I@X(4!7(4!)%&``"($8!W(')LQE(*WW($$`P+L%41<'4$T'<1<%4@4F,X +M\B0TXB0S70O`_P'`[A'P[B#I8]@$\@04<@K=X@00@@K:@'<1X.`$D(@1,/\1 +MTLWQT%F#@/\@3%U`CA%0[B"`=R!P_R#P[B#B;,>YX]G3P@H:B!$`S".PS%,@ +MS+#"+$Z*S,GSD@HB`)DCL)E3()FPDBE.BIF9\W($^E%``B!WL'(G3N$_`M%" +M`HIW>?/R!!#"TB-Q00('[Q22"N7V>5?Q0P+P^:#X#ZD!H`\```"Q1`*2"MVR +M;.6Q10(+B18H)JD!XLG^%BXG\LG]%A\F(48"TFS>(FSD#`(=\+(2#9("(((2 +M#`"[$9"0!$"9`;"(()"(((F#!KC_\4<"\FSE\4@"D@K=X3@"4M(F)ADQ@LG^ +M%M@-9CD"1B0`#`(<'L$W`I%)`K)C.-)E'I)E'\)E&N)%4+)*+!WPLDHL#`(= +M\`!B8Q6"!!"I`2=H$)%+`J%*`J)LWI)LWT8#````L4P"T3\"TFS>LFS?J`&" +M"N(,`@P+@L@1@(!T@D50@(@1\(@@@F4:XFP[XFPZXFPWXFPVXFPSXFPRLDHL +M'?```*(BE$+"$`PIF0HEMO]&>O^130)B8Q6""N)R91Z291^"R!&`@'2"15"` +MB!'PB"""91KB;#OB;#KB;#?B;#;B;#/B;#+2!*06+?6I`;@!#.(,.J)++!WP +MJ0%B8R6R8Q72"N,R"N(<*()%4#>]"`,X"`9L`6AP>B)0^R)0U` +MJH*F&C"F&QXEA0RB8D.XU:830N8;R;"P8*T#Y8,,H+!@LF*[!O#_L+!@Y8(, +MH,!@PF)#QO7_IAL1H*!@Y8$,H-!@TF)#1O'_````Y8`,HF)#1N[_``"F&PVM +M!N5_#*#@8.)BNP;@_ZT#)7\,HF*[1MW_J`$,`@P+LDHL'?``#`)B8Q7B;-ZR +M;.0=\')LWK)LY`P"'?``B`%B8R6""!H,`O%1`@"((X)C%5)LWO)LY!WPJ`$, +M"Y%2`I)LY89F_Z%3`@P+HFSEJ`%&8_^Q5`*H`;)LY0P+!F#_J`$,"^%5`N)L +MY<9<_Z@!#`OQ5@+R;.6&6?^H`0P+@5<"@FSE1E;_J`$,"Y%8`I)LY093_P`` +M-L$`44\`X2@"#`>"(Q.2(Q'(T[CSK0)\[0P2T+L0T,P0T)D0T(@0@F,3DF,1 +MDF,>R=/"8QRY\[)C'8)C'V8D/0P,#`W]!YT##"MVJQAB*1RR*1V+F99V`=:+ +M`,#+0]#64_*@`3WPZFI6[QE&!````)8+_\#&0]#;4PP?1OG_ZFK2)G_B)H#- +M!POTG03PEX/C_`K3_`)S_`%S_!J3_!8C_!1S_!5S_!)S_!,C_!O)Q284%JAS +MN-.(PZ"@!+"PM("`U+/X#J/X'(G%G'3(D]CSLB,.P,`$T-"TL+#4T_L.P_L< +MLF4,\B:`XB9_W0?S_0KC_0(C_0%S_1J3_18C_11S_15S_1)S_1,C_1O9Q284 +M&:B#LB,1@B,0H*`$L+"T@(#4L_@.H_@<@F4,G'3(H](C$[(C$L#`!-#0M+"P +MU-/[#L/['+G%\B:`XB9_W0?S_0KC_0)S_0%S_1HC_1B3_18C_11S_15S_1)S +M_1,C_1O9Q284%ZASLB,+")4.HD<#`!,D!N`'160(;JA;+"JF1IZWA +M!BD`ZHVRS3_0O;."R""PMB&Y@:"[$9++0)FAAS\QP)O`DLE`ERXH*1&I80P+ +MN7$,&J58XM(E0ZAQT-`$V1'($>%9`ANJ%IP*J7&GKN%&*``,"IT#?/T,+W:O +M);(I',(I'28:#B8J'):[`M8<`7)I'<8"`(BABNOB:1R*C()I'8N91F'_^*'P +MB\"":1SP_,#R:1U&^O\`EES^TFD=QO?_'?``XAH-1L7_#`NH8;E!N+&2*C>B +M*CC`F1&PJL`+JL"J`:"9()E1F65&`0``J4&G*Q@,&F5.XMA1J$'H9>D!PB$` +ML5D"HLH!UYSA(D.,#!K&U_\,")AAB2&(@?(I-Y(I.,#_$9J(&XC`B`&`_R#Y +M,?EE!@$`J2&G*Q@,&N5)XM@QJ"'H9>D1PB$!L5D"HLH!UYSA(D.,#"K&Q?\V +M00!13P"A*`*"Q/X,"]T+;0N`9).JHO(J@.(J?S!FL//]"N/]`K/]`;/]&D/] +M%K/]%+/]%;/]$K/]$]G%R-:8QL#`M)"0U,/Y#IG%%H@1#!S2*H"2*G^-"]/X +M"I/X`K/X`;/X&D/X%K/X%+/X%I0^(&?HA3DB8\L5T"#!\@F:"ZTL(MUKJ9TBW7DBDHN"/#_0CS_1`, +M#+/]$:/]$I/]%X/]'`PXP_T=X_T>TF3)LB8\DB8[[0RS_@J3_@*13P##_@'S +M_AJ#_A;S_A3S_A7#_A+#_A/IR;(F.X(F/+/X"()I3/)D7^(%]-T,P_T%X_T) +MTF1@PF1APF1BPF16PF15'?"")C"JIZ)C!.`(`)@SL*H!<)D1H)D@HJ$+H)D@ +M`#FFJ$.&TO^2H@(`.:9P$*:"ST"`=Z!X!X:R_QWP`-JRLBL@#"JI"V4?_\:] +M_P`VP0!2H0(`-::0$*8,%@P%TJ(LF0-6N07:HO*D/^%>`G*@![*@%$+.8':` +M)0`_IL`0ICWPQ[L$8DHC#`S@G*"8"9D3)ED.DF,B0(R@B`B),YSEQO3_)D8%)D85)D8E)D5M)D5=(L\,(L\=/\",)G3!WP```6VC>2PACR +M*3J9H:(C!!:/(H(A#8(HY>`(`,@SF+&PV@%PS!'0S"`,O=#,(``\IJC!N$.Z +MJJE#V!/B"7["*3RR*3N((R#\H+/\"/+?)/@O@_P1H_P2\_P74_P=X_P>MCT" +M8_P0PF3)HB,B%NH4"\H6G!32ROX6G43HT?(N\.(N\?/^".)G3!WP@@(@HL(8 +MHF$*!^@+@J$"`#BFP!"FPF,"`#FFP!"FVI*VO`1B22,,#-%<`H@SHB,BT-R@ +MV`VBROR*W=DS%MHL#`[IP:'#``NJ\B2#%M\8%MH8B)F("`NJ9BCMF*&H0Y(I +M.L+2(\)A#19Y)H(LY>`(`,@SL-H!<,P1T,P@TJ$+T,P@`#RFJ,&X0[JJJ4.1 +M*@+8$X@CFI*9L<(I/.()?I(I.R#\H/+?)/@OD_P(@_P1H_P2\_P74_P=X_P> +M]CT"1E$`O078H9BQ8_P0PF3)6<-28QA28Q128Q!9TU)C&5)C%5)C$8(I.Y(I +M/`P_[063_@J#_@)3_@%C_AKS_A9C_A1C_A53_A)3_A/IQV)D7](-\*C14_L% +MT_L)LF1@4F1A4F1B4F164F15LBKPHBKQL_H(HF=,'?"8T:C#N-.R8QFR8Q6R +M8Q&B8Q"B8Q2B8QBB*?&2*?"-!:/X"I/X`E/X`6/X&E/X%F/X%&/X%5/X$E/X +M$XG'^-/HP]BA\/"TX.#4\_X.Z<=B9%_2#?#-!5/\!=/\"<)D8+C3J,.PL+2@ +MH-2S^@ZB9&&B9&*B9%:B9%6B(R+&C?^(T9C!@BCEJJFI0^`(`,@SL+H!F+%P +MK!&PJB`,N["J(``ZIJA#!G7_``!6JN?HH>(NC@PMTFX`)=_^AIK_`(*B`@`X +MIO`0IJ(C(N#_H/@/^<'&*?^M!;BAB+'"9,E9PU)C&%)C%%)C$%G34F,94F,5 +M4F,1\B@[@B@\##[=!8/]"O/]`E/]`6/]&N/]%F/]%&/]%5/]$E/]$]G'8F1? +ML@OPF-%3^@6S^@FB9&!29&%29&)29%929%6B*?"2*?&C^0B29TP=\```PM(C +MPF$-HBPJLBPRPBPZI94!HF$)J-&R*C/"*CNB*BNEE`'RPS2!*@*="JB!BH*) +ML;(H,\(H-=(H-N(H-*(*V/DAF0&2PS"9$8(H,?B1X`@`F(&B(R(&_/Z8P8(L +MY:JIJ4/@"`#(,["Z`7"L$;"J(+*A"["J(``ZIJA#!F7_``#B(I0,+?+"&/FA +MV0YES?Z8H08<_P`_IH`0IN"(H(@(B<%&2?\`R-&B+"JR+#+"+#JEBP&I0:C1 +MLBHSPBH[HBHKI8H!\L,TB-&="JB!LBCHPBCJTBCKXBCIH@K8^2&9`9+#,)D1 +M@BCF^$'@"`#(T:C#LBPVPBPZY9`!R-&I4:C3LBPWPBP[Y8\!B-&="O+#1*B! +MLBCHPBCJTBCKXBCIH@K8^2&9`9+#0))A`8(HYO(A!3WPX`@`J-&XP\(C$*(J +M+N62`:EAJ-&XT\(C$:(J+R62`?+#5(C1G0JH@;(HZ,(HZM(HZ^(HZ:(*V/DA +MF0&2PU"9$8(HYOAAX`@`HB,4LB,,PB,099$!N-.I<<(C$:(C%:60`?+#9(C1 +MG0JH@;(HZ,(HZM(HZ^(HZ:(*V/DAF0&2PV"9$8(HYOAQX`@`F($&I/ZM`KT# +MPJ``95__R*%B9%_"#/!3]07#]0E29&"XTZC#L+"TH*#4L_H.HF1ADB,1@B,0 +MD)"T@(#4D_@.@F1B\B,5XB,4\/"TX.#4\_X.XF16TB,9PB,8N-'0T+3`P-33 +M_`["9%7"*_"R*_'#^PBR9TP=\``VX0!2H0(`-::@$*8,&PP%\J)`J0-6>@7Z +M8N%>`D*D/QQ-J)C(I*A`@`YIJ`0I@P8#`RI`Z#(@R8%X,Y(C(H+#-*"LH*@*B=&"R?YZJJDS/\'K8]`F/\$,)DR=AC5GT(HB?PPB?QO07Q3P## +M]0JC]0*S]0%C]1JS]19C]11C]16S]1*S]1.S]1M9SYC3B,/(\9"0M("`U)/X +M#HG/Z-/8P])C&-)C%-)C$.)C&>)C%>)C$6)D7\(,@+/[!X_P0PF3)6<-28QA28Q128Q!9TU)C&5)C%5)C$:(G\9(G +M\`PXH_\*D_\"4_\!X_\:@_\6@4\`X_\4X_\54_\24_\34_\;^I8<(G.ZC392D!\L-$LB?HPB?JTB?KXB?IDL-`C0JB!L29$?DAB0&")^;X +M8>`(`*(G+KC#PB,0)2T!N-.I<<(C$:(G+R4L`?+#5+(GZ,(GZM(GZ^(GZ9+# +M4(T*H@;$F1'Y(8D!@B?F^''@"`"B(Q2XP\(C$.4K`;C3J8'"(Q&B(Q4E*P'R +MPV2R)^C")^K2)^OB)^F2PV"-"J(&Q)D1^2&)`8(GYOB!X`@`D<,`/?`+F:(D +M@Q8:)A89)KCQLBMRN`L+F68KZLCQPBP>J$,6S":"(0Z"*##@"`"8,["J`7"9 +M$:"9(`RZH)D@`#FFJ$.I0[@3Z%.((]CADB?PPB?Q\BT\T@U^D_P((/^@\M\D +M^"^#_!&C_!+S_!?C_!Q3_!W3_!ZV.P0,&J/\$*T"PF3)O0,,#&7R_HCQ#!F2 +M9%^""(#]!5/_!8/_"?)D8.C3V,/@X+30T-3C_0[29&'"(Q&R(Q#`P+2PL-3# +M^PZR9&*B(Q62(Q2@H+20D-2C^0Z29%:"(QGR(QCHX8"`M/#PU(/_#O)D5>(N +M//*B0"KN^NY23NC2)_"R)_'!3P#3^PBR;$P=\`"B)_&RHD`JJKJJ4DKHHBB")_#B)_&#_@CB;TP=\+CQLBMRHJ`"HFL`)3'^QHC^`)B1@B@PJJFI0^`( +M`,@SL+H!<*P1L*H@LJ$+L*H@`#JFJ$,&]OX```!6F=KH1@PMV0ZE+?Y&9_\` +MDJ("`#FF@!"F8(B@B`B)D<;7_@"(X8(H,*E#X`@`F#.PJ@%PF1&@F2`,NJ"9 +M(``YIJA#!F3_V,'HT0P/&ZH,.[)&U*"@=+(A!&4``$8U_@`V00#Q/0(`/Z:0 +M$*;2H0*,J0`]IJ`0II"`8*"8DPPN#!H+LA9["Q9)"\T+@+L1X+L@`#NFL!"F +MP(!T`!A``*JAD(%@"XB`BH**NQN[L(!@D+BC`#^FD!"FC*D`/::`$*:0\&"` +MGY,+TA8M"!;Y!X#\$>#_(``_IL`0II#18`O=T-J"VLP;S,#P8)#/H[HS.04P +M(R"PNA&PL&"WHP>@*A$@(X`I!;`Z$3%>`J*B+*"B@&+.8':`10`UIL`0IL>]'I@.!A````#@G*"8"9D3)ED6DF,B8(R@B`B),X(+D"8H(;R$/?#&[/\, +M>9)C(@`_IL`0I@P8#`G)`\"8@R89GP8'``#V*=H`/Z;`$*;"8R$6[/R"(R); +MB()C(E94_,@#44X`D4\`%CP(H@*H8L(8HLK^%FHAH5P`[0?RTB;2+S""+S'( +M0[(/4M/X",/X$G/X';/X'H)ER8(O,?(O,,T$@_X*\_X"0_X!<_X:0_X6<_X4 +M<_X50_X20_X3<_X9Z)DH')AH$V#,6O0``/Z;@$*;B8P6B(R(6 +MRD8+BA9X1A::2`N:%DE(LM(CPM(FR<&YT=+*_A8]5:'#`)BAHLK_XB6#%AXM +M%AHM^)GR+P"BRO]F+^N")CJH0Q;X/HC1@BCEX`@`R#/Q3P"PV@%PS!'0S"`, +MO=#,(``\IJBQN$.ZJJE#R,'8$Y@CLBPQX@Q2PBPP((N@@M@DB"C#^PB3^Q&C +M^Q*#^Q=#^QWC^QZV/0)S^Q"R9G)2()4I(I,"#[H/+?)/@OD_L( +M@_L1H_L2\_L70_L=X_L>MCT"<_L0W03!3P"HP;)ER4G#0F,80F,40F,02=-" +M8QE"8Q5"8Q&2*C"B*C$,./T$H_\*D_\"0_\!<_\:@_\6<_\4<_\50_\20_\3 +M^/]"=)E8$)E84)E8D)E5D)E5=(J\*(J\=/Z"*)L3!WP +M``!6BM/")HX,*[D,Y)E8N)E5N)E5>(M\-(M\>/]"-)O +M3!WPJ-&XP\C3PF,9PF,5PF,1LF,0LF,4LF,8LBKQHBKPG02S^0JC^0)#^0%S +M^1I#^19S^11S^15#^1)#^1.9SXC3Z,.`@+3@X-2#_@[IS](&""=M%=ACG`V" +M(Q'B(Q"`@+3@X-2#_@[B;PQR95_"!O"]!$/[!`(`+(&""=K3,AC%GP$ +MPB$-HBPJLBPRPBPZ96X`J4&HT;(J,\(J.Z(J*V5M`/+#1(C!G0JHH;(H*,(H +M*M(H*^(H*:(*V/DAF0&2PT"9$8(H)OA!X`@`HB,BAK?^`!WPF+&"*.6JJ:E# +MX`@`R#.PN@%PK!&PJB"RH0NPJB``.J:H0X8]_P``/J;0$*;`W:#8#=FQAB#_ +MR-&B+"JR+#+"+#HE9@"I4:(A#;(J,\(J.Z(J*^5D`/+#-(C1G0JHH;(HZ,(H +MZM(HZ^(HZ:(*V/DAF0&2PS"9$8(HYOA1X`@`R-&HP[(L-L(L.B5K`,C1J6&B +M(PVR+#?"+#LE:@"(T9T*\L-$J*&R*.C"*.K2*.OB*.FB"MCY(9D!DL-`F1&" +M*.;X8>`(`*C1N,/"(Q"B*BYE;0"I<:C1N-/"(Q&B*B^E;`#RPU2(T9T*J*&R +M*.C"*.K2*.OB*.FB"MCY(9D!DL-0F1&"*.;X<>`(`*(C%+(C#,(C$.5K`+C3 +MJ8'"(Q&B(Q4E:P#RPV2(T9T*J*&R*.C"*.K2*.OB*.FB"MCY(9D!DL-@F1&" +M*.;X@>`(`,9D_C:A`#EAHJ)ZB'/88Y%A`@P;T-N3FI+R*8'B*8#"*7^2*7[0 +M[Y/I0="O0+E:@I]"JG$N(&Z=WG$HB6`8*J" +MYAH"!B$`IA)PO0+E:`IM"JG4V)&H(<1&X?^]`J5B"GT*J<1&WO\@L&#E80J@8&!IU$;B +M_P```*82#Z"@8+T"96`*H&!@:=3&W/^]`J5?"FT*J=3&V?^0JH*F&AZF$@J] +M`F5>"JGD1MK_`""P8*5="J"P8+GDAM;_````IA(/H*!@O0(E7`J@P&#)Y`;1 +M_[T"95L*J>2&SO\``)"J@J8:'J82"KT")5H*J?0&S?\`(+!@95D*H+!@N?1& +MR?\```"F$@^]`J"@8.57"J#`8,GTQL/_O0(E5PJI]$;!_PP)AI;_`*J2D@F` +M?/NPF9!&EO^1/0(`.::@$*:I@;*A`HSJ`#NFX!"FR('`T&#@S9/)@0`YIO`0 +MIOF1%L_C`#NFH!"FB)&`D&"@B9.)D4:*_P`V80!2H'=!8@)BTB.2)LV")L\, +M1TI"D(C`@F$`HB1_LJ^)ENH!IR4"1B<`DB;/LB;-H*F"IAIXIAMEY4T*J<,& +M)0```+>J0<(FS[(FS:"L@J8:'*8;"25,"JG#!AX```"PL&!E2PJ@T PP8: +M````IAL-H*!@)4H*H.!@Z<-&%0!E20JIPT83`(%D`N#Z$?#RP(K_\B]_\/!@ +M^.&(P``EZH]N`&PJH*R)LVF&AFF&P,&$P#Q3P+@ZA'@XL#Z[N(N +MN^#@8.GCA@T``+"P8*4P"J#P8/GCQ@D```"F&PV@H&!E+PJ@@&")XP8%`*4N +M"JGC!@,`L4\"()J@NIF2*;N9XZ(D@-*OB9;*`:D`RT$'?`M`QWP'?`=\```-D$`<3@"=Q(6=Q,K=Q0X)Z,&-Z0; +M+0,=\">D#QWP``!W$VAW%#F6(P265`4P)$,=\">D#RT$'?!W%%JF$CF61`0G +M).\=\```)Z,,YA/&IA+R#`0M!!WP`.82P`8!````EN,`#`0P)$,=\```-R2E +MEA3\#`(=\```)R2@#`,P)$,=\`P"'?`,`RT#'?!P5,`,`E`DDQWP'?`V00!Q +M.`)W$RYW%#LGHPDWI!XM`QWP````)Z0/'?```"C"CD#BT$'?``)Z0! +M'?!`(T,=\!WP+0,=\#9!`">C"3D#2T$'?`GI`$=\$`C0QWP'?`M`QWP +M-H$`#!N2H`!A3@!13P"B(L9RHBQP9`Z(G.U;Z],(D\+(D\#_AWS_A[B9LDEN_T,"0P;N0/&VO^M`KT#PJ`!97__ +MD<,`"YF")H,6R#P6R3RHEZ@*DLG_9BKLPB)`LM(FV$,63#^"*R6Y4:T-X`@` +MB#/H4;":`7"($9"((`RYD(@@`#BFV$'X0_K=V4.B#E*2)/'B)/`,"R#)H./Y +M",+<).@CR"RS^1#C^1'3^1+#^1>S^1T,++T#H_D>DF;)K0+EL?T,"0P;!K;_ +M``""PS2B!]BR).C").K2).OB).GR)"J2)"N9`8DADL,PF1&").;@"`""PSS" +M).[2)._B).WR)"RXPY(D+;)D*K(D[*C3HF0KH@?9F0&)(9+#.)D1@B3GX`@` +MD<,`V./29"S(\\)D+0N9XB:#%AXO%ADO\B*4^`^2R?]F+^N"(D"RTB;80Q8( +M,X(K);E1K0W@"`#(40P;^#,,";"*`7#_$8#_(`RX@/\@`#^FV$'H0^K=V4." +M)/"B+#'R)/'H(R"JH(/_"*+:)((,4J@JD_\0X_\1T_\2H_\7D_\=@_\>\F;) +MB-/H\ZCC^,/R8QCR8Q3R8Q"B8QJB8Q:B8Q+B8Q/B8Q>"8Q&"8Q6"8QGB8QL, +M*.(L,:(L,/T)X_\*H_\"D_\!L_\:@_\6L_\4L_\5D_\2D_\3^<7HTZC#X."T +MH*#4X_H.J<6(\_CC@("T\/#4@_\.^<7&8/\`@L,\H@?9LB3LPB3NTB3OXB3M +M\B0LDB0MF0&)(9+#.))A`8(DY^`(`)'#`+CCLF0LJ/.B9"T+F<(F@Q;<'1;9 +M'=(G"=@-DLG_9BWKXB)`LM(FV$,6CB."*R6Y4:T-X`@`R%$,&_@S#`FPB@%P +M_Q&`_R`,N(#_(``_IMA!Z$/JW=E#\B3QXB3PB".M#^/Z""#_H.(,4I/Z$/+? +M)/@O@_H1T_H2\_H7D_H=X_H>HF;)B//XX_)C&O)C%O)C$H)C&X)C%X)C$^(D +M\:(D\(T)X_@*H_@"D_@!L_@:L_@6L_@4L_@5D_@2D_@3B<7X\^CC\/"TX.#4 +M\_X.Z<7&(?\`@L,TH@?8LB3HPB3JTB3KXB3I\B0JDB0KF0&)(9+#,))A`8(D +MYN`(`)'#`+C#LF0JJ-.B9"L+F<(F@Q8<#Q89#](G"=@-DLG_9BWKXB)`LM(F +MV$,6CA:"*R6Y4:T-X`@`R%$,&_@S#`FPB@%P_Q&`_R`,N(#_(``_IMA!Z$/J +MW=E#HB3Q@B3PZ"/]"H/_"""JH((,4I/_$*+:)*@JX_\1T_\2H_\7D_\=@_\> +M\F;)Z,/B8QCB8Q3B8Q"B)/&")/#]":/_"H/_`I/_`;/_&I/_%K/_%+/_%9/_ +M$I/_$_G%Z-.HP^#@M*"@U./Z#JG%AN7^#`JI0<;>_@P-V4%&\OX`5LG#\B*4 +M#"[I#^75_,8+_U:)T9(BE`PHB0GEU/S&0O]6R>*R(I0,*JD+Y=/\QH?_5HGQ +MTB*4#"S)#>72_,;"_ZA!N5&"*R7:JJE#X`@`N#/H4;#*`7"[$<"[(`R\P+L@ +M`#NFV$-&`O^H0;E1@BLEVJJI0^`(`,A1#!O8,PP)L.H!<-T1X-T@#+[@W2`` +M/:;80T8S_ZA!N5&"*R7:JJE#X`@`R%$,&]@S#`FPZ@%PW1'@W2`,ON#=(``] +MIMA#1G'_J$&Y48(K)=JJJ4/@"`#(40P;V#,,";#J`7#=$>#=(`R^X-T@`#VF +MV$-&I?\VP0`,'&%.`%%/`*(BQG+2`0P+%AH+0M(C%GH8DM(F@BDPHBDQJ4'X +M08/_"/E!Z$'80\/^'>E!J$&""5+3^A*I0?A!@_\>^4'H0>)FR;)C$;)C%;)C +M&;G3LF,0LF,4LF,8NA! +MP_X:Z4'80;/]%ME!J$'#^A2I09A!P_D5F4&(0;/X$HE!^$&S_Q/Y0>A!Z<6Y +MQA!XF9@TB9AT*ZT8-TCTF3"0*HC +MHF3#DB9BD(ZT8)DCDF3$0(@C^$&"9,7RSP'R9F#B)F'@WK1@[B/B9,9`W2/2 +M9,?B)F*A7`#@_07@C`7@FP6@KA#@WK1@[B/B9,A`W2/29,GR9XF"9XB29X>B +M9X:B(R`6RGB"H3\`.*;0$*8,+O(C(**A`MFS)B\ZLF,#LF,`\J)`S!T&!0(F +M'6:2S?X6B3*"S?T6*#:2)X96>>?")/#2)/'90;A!P_L(N4&H0:)E3!WP``"" +MI@(`.*;P$*;Y,ZR?F+. +M`HBALB3LPB3NTB3OXB3M\B0LDB0MF0&)(8B1B1&").?@"`#(P\)D+KC3LF0O +MJ..B9#"8\Y)D,9'#`(C#@F0J^-,+F?)D*^CCXF0LV//29"VB)H,62F$626&R +M)U2X"PN99BOLR`>H0Q;,<((DY>`(``PE! +MZ$&2V228*:/^$NE!B$'X4Y/X%XE!Z$'S_ASI0>A!T@U2L_X=Z4&80=/Y'IE! +MB$&"9LGX8U9?2Z(D\;E!F$&")/"C^0J90?A!@_\"^4'H0;/^`>E!V$'#_1K9 +M09A!#"JC^1:908A!P_@4B4'X0A!\/"T\_X.Z4'80=G%^/.8XZC#B-."8Q&"8Q6"8QFB +M8Q"B8Q20D-290>A!HF,8\/"T\_X.Z4'80=G%F/.HXZ)C&J)C%J)C$I)C&Y)C +M%Y)C$P8W_P`ZIM`0IOJ2@L,XB9'98X+#/(FA%LU>R5&9<0P(B6$,&F5GWZ(E +M0Z"@!*E1J&&84;%9`ANJ%LD?J6&GJ^$&?0``.J:`$*;2PS#BPS3ZDIEQB6,6 +MJ`:"H0(`.*:0$*:9H0Q895((D +MY>`(``PE!Z$&2V228*:/^$NE!B$'X4Y/X +M%XE!Z$'S_ASI0>A!T@U2L_X=Z4&80=/Y'IE!B$&"9LGX8U8_)Y(D\;E!B$'R +M)/"3^`J)0>A!\_X"Z4'80;/]`=E!J$'#^AJI09A!L_D6F4&(0A!L_X2Z4'80;/]$]E!J$&S^ANI09A!F<6(P_C3@(#4B4'H0?#PM//^ +M#NE!V$'9Q9C3J,.B8QBB8Q2B8Q"28QF28Q628Q'&J?X,&@P+#`S)8;)E):)E +M%0P:)47?\B4EXB45J&'`_Q'P[B#I4=A1@5D"HLH!)AT%HF$&IZC9#!NR0XR" +MH0(`.*:0$*:9DP`XIO`0IMB1Z*&"HD"H+#3`P?HLH!H*!T +MY2;^PB,2PF0PLB,3LF0QD<,`Z./B9"S8\])D+0N9\B:#%E\L%EDL@B=4B`B2 +MR?]F*.N8!ZA#%IDT@B3EX`@`#!SH,PP+L/H!<.X1\.X@#+_P[B``/J:HL=A# +MVJJI0]+2)H(M,)(M,9E!^$&#_PCY0>A!^".S_A#I0>A!()F@\_X1Z4'H09+9 +M))@IH_X2Z4&(0?A3D_@7B4'H0?/^'.E!Z$'2#5*S_AWI09A!T_D>F4&(08)F +MR?AC5C\)DB3QN4&(0?(D\)/X"HE!Z$'S_@+I0=A!L_T!V4&H0A!\/"T\_X.Z4'80=G%F/.HXZ)C&J)C%J)C$I)C&Y)C%Y)C$\8U +M_JT"O0/"H`*EI?P,"PP(V7/")XG)@ZFCN9.M`KT##`REH?ZR)/#")/') +M0:A!F",,"+/Z"*E!^$&BTB;B*C&#_Q#Y0?A!B$,@[J"3_Q'Y0?A!XMXDZ"Z# +M_Q+Y0=A!R%/C_1?90;A!P_LA.TJ`"TFX`Y2W\!GG^``P< +M#`@,'[(GA[ECHB>(O0.I)F8/YHXF3Y9;^D<,`"YG")H,6#!D6"1G2 +M)U38#0N99BWLZ`>H0Q;.'8(DY>`(`,@SL-H!<,P1T,P@#+W0S"``/*:HL;A# +MNJJI0Y+2)L(I,/(I,?E!N$'#^PBY08A!#`ZX(^/X$(E!B$$@_Z"S^!&)08A! +M\M\D^"^C^!*)0=A!R%/S_1?90;A!P_LA.TJ`"TFX`I1_\!DW_ +M`%8)MHAQB$CRH`+R:`!E'OP&U/X`F+&").6JJ:E#X`@`#!SH,[#:`0P+<*X1 +MT*H@#+W0JB``.J:H0\8[_@"B)/$JJOJJLDKH@@G4F7$+B!;($XBALB3LPB3N +MTB3OXB3MJ''R)"R2)"VB"L69`8DAB)&)$8(DY^`(`,CCPF0PN/.R9#'&(O^8 +ML8(DY:JIJ4/@"``,'.@SL-H!#`MPKA'0JB`,O="J(``ZIJA#ABS_F+&").6J +MJ:E#X`@`#!SH,[#:`0P+<*X1T*H@#+W0JB``.J:H0X:N_@```%:)YX(BE`PO +M^0@E$?S&FO^M`KT##"PEMOP,"PP<1H+_``#(<0P/##NB#,2R3-2R)"K")"L; +MJJ"@=.7E_0;>_0``V)'HH0P/R'$,.QNJH*!TLDS4LB0LPB0MY>/]!N+]`)BQ +M@B3EJJFI0^`(`,@SL+H!<*P1L*H@#+NPJB``.J:H0\:'_ZT"O0,,+.6N_`P+ +M#!Q&:OT``*AQ##L,#[)*U*(*Q+(D*L(D*QNJH*!TI=[]!FO^````V)'HH:AQ +M##L,#[)*U*(*Q;(D+,(D+1NJH*!T9=S]!K+_`#9!``P(##EQ90)BH=!2PA@R +M!?"B)3IJ8D(63GIR&ZH;,S`P=#)%\&:#`H)%\*)E.J<4-+(GB\(GBJ(63QN[ +MLF>+MYH'@F>+&\S"9XK@$*;2!G\,(LQ=\B6.^`^`0IAWP`&)B@!LS,F)_\!"F'?"` +M$*9B91(=\&)%4,;M_P`V00`,"0P]H3@"5,M)(3I)F.I)G\9)G\*)G*J)G*Z)G+J)G+Z)G +M,J)G,Z)G-J)G-Z)G.J)G.\@##"(6C`X=\.(G\?(F/<(C%+#N$>KBPF[J4B?Q +M0B,5L%416E)"9>OB)_'"(QBP[A'JXL)N[E(G\4(C&;!5$5I20F7OXA@WPB?Q +M\+O`"^X;S,)G\>>\7/(C$/)G*N(C$>)G*U(C&%)G+D(C&4)G+_(8-[!<$5HB +M]RL"ABL`HF\(FCL(L +M`!;\#N(&".#G0>`M@QWP`.><0.(C$.)G*E(C$5)G*T(C&$)G+O(C&?)G+Z)G +M.Z)G.N(8-^N`H8P`*)G,J)G,Z)G-J)G-X;G__`0I@PB'?``HFB9SJB9SL&V?\` +M`$(B\D)G.O(B\_)G.^(8-[>N2>(BZN)G,L(BZ\)G,[(B[K)G-J(B[Z)G-T;- +M_U(B\E)G.D(B\T)G._(8-[>O6.(BZN)G,L(BZ\)G,[(B[K)G-J(B[Z)G-P;" +M_P``HF0F@V\B5?\F@W!AW_PBC:`#RFL!"F"[NPKH,M"AWP +M```B:#)")5M":#/R)5[R:#;2)5_2:#<&$O\B:#+")5O":#.R)5ZR:#:2)5^2 +M:#<&#/\V00`,":$X`K%.`'*@N'IR0@=0868"@M("0L0!0$!T0D=09H0"DD=0 +MDFM5PB<2:F*R%]H;S,)G$L>;,`P]TDA.DF<2J>:I]J)F$J)F$Z)F%J)F%Z)F +M&J)F&\(FUZ)F'J)F'U9L">`0IAWP``!R)M52)NNP=Q%ZJ"9A9"+>M" +M9AXR9AKR+>_R9AOB+?+B9A[2+?/29A_B)M<6/@@=\```AY=`HF8>HF8? +M\B;P0B;O@B;HDB;GF>:)]D)F$O)F$Q:3!["G$:JBTBKJTF86PBKKPF87LBKN +MLF8:HBKOHF8;QNS_``"B9A.B9A*I]H(FU*GFDF;5&XB"9M1"(NI"9A;R(NOR +M9A?B(N[B9AK2(N_29AO"(O+"9AZR(O.R9A]&W?^0$*8=\*)F%J)F%Z)F&J)F +M&Z)F'J)F'\;6_P``HF86HF87HF8:HF8;AM+_`#9!``P)##VA.`)RTB."T@)B +MPABR)CI"!O!2NQM$0$!T0D;P9H0"DD;PLF8ZMY4RR`,,(A;L$=)(3I)F +M.I)G\9)G\*)G*J)G*Z)G+J)G+Z)G,J)G,Z)G-J)G-Z)G.J)G.QWPXB?Q\B8] +MPB,4L.X1ZN+";NI2)_%"(Q6P51%:4D)EZ^(G\<(C&+#N$>KBPF[N4B?Q0B,9 +ML%416E)"9>_B&#?")_'PN\`+[AO,PF?QY[Q<\B,0\F29SJ29SL&Y?\`\!"F#"+22$Z29CJ29_&29_"B9RJB9RNB9RZB9R^B9S*B +M9S.B9S:B9S>B9SJB9SL=\*)G+Z)G+E(G\*)G*Z)G*AM50A@W4F?PDF?Q1ZM" +MHFN2>(BZN)G +M,L(BZ\)G,[(B[K)G-J(B[Z)G-X;`_U(B\E)G.D(B\T)G._(8-[>O+.(BZN)G +M,L(BZ\)G,[(B[K)G-J(B[Z)G-T:U_P``HFJ&6I`9@!=YGLTB45PB4EP-T1T,P@R0&X`68; +MV>@A(DZ,L6@"86<"@B,Z6!%"H=`;B$I%:E7R%$X,-H)C.H#_P!8_#(%.``RI +M(FA?\@/PS0*3_`7S_`G":&#B*&'@WK1@[B/B96A`W2/296GB*&(;S.#>M&#N +M(^)E:D#=(])E:\)H8*(H8:">M&"J(Z)E;*%<`$"9(Y)E;8(H8J"H$(#-!8#< +M!8#K!8#^M&"((X)E;D#_(Y(EE_)E;X(43^)D4])D5,)D5:)D4AN9DF67EY@3 +MJ!'")98B99>ZJAO,+`O"99;E_`>X(;(K`"8;`L`0IM($?\Q=XB..Z`ZL[O(# +M"`PB\/=!\":#'?"H$6)$?B)C.B)EER)EEKJJ#"(L"R7Y![@AN`LF&P[`$*8= +M\-(#"-#708PM'?`=\/(E@``_IN`0I@ONX":#'?`V00!!.`+A:`*BT@&2(D#" +MH<[*PH(<3QN9DF)`D(C`D6D",+!T#`V:,A;(',%.``RHTFQ?\@H(G0V#^07S +M^0F2;&""+&&`_K1@B"."8Z5`_R/R8Z:"+&(;F8#^M&"((X)CIT#_(_)CJ))L +M8((L88#^M&"((X)CJ8%<`$#_(_)CJL(L8H",$,">M&#,(\)CJT"9(Y)CK/(C +MU()BQL(CYK#_$?KRPF_JDB/4@B/GL)D1FI*":>OR(]3"(^ZP_Q'Z\L)O[I(C +MU((C[["9$9J2@FGO\B/4PB/HL/\1^O+";^R2(]2"(^FPF1&:DH)I[?(CU,(C +M\+#_$?KRPF_PDB/4@B/QL)D1FI*":?'R(]22(^?"&K<;KZ)CU,>Z;YGCPB/F +MTB/IXB/H\B/O@B/N@F,1\F,2Z?/28Q#)TY(C\9)C%,(C\,)C$Q:;$[#:$=#2 +M@.(MZN)C%<(MZ\)C%K(M\K)C'9(M\Y)C'H(M[()C%_(M[?)C&.(M].)C'](M +M]=)C(.(CU@ON%GX*\!"F'?`+C("*P%;H"<(CYI(CY](CZ>(CZ((C[O(C[_)C +M$H)C$>GSTF,0F>/)TY(C\<(C\,)C$Y)C%!:K^[#:$=K2XBWJXF,5PBWKPF,6 +MLBWRLF,=DBWSDF,>@BWL@F,7\BWM\F,8XBWTXF,?TBWUTF,@AN#_ZJ(L"PP_ +M\DR`TF)`)=8'0F,50F,60F,=0F,>0F,70F,8@B/60F,?0F,@)A@%D!"F'?`` +M'?```-)CU,(CT^JBLJ`@PLP!PF/39=('TB/4L-T1VM+"+>K"8Q6R+>NR8Q:B +M+?*B8QV2+?.28QZ"+>R"8Q?R+>WR8QCB+?3B8Q_2+?728R`&O_\`0F,50F,6 +M0F,=0F,>0F,70F,80F,?0F,@!KC_`#:!`*'#`+*@J)%/``PC@M(KB*B)`7:` +M$<(I0PNJC/P6^CS2(I38#28M",;Y_P```!;J.[I2V`+"$@SQ3@""`B%"$@UB +MHB1J8N(&VP!$$8"!!-"($8#N(.)OC>B]V*U`S"``[A'@W2#9B<)OQK(&W<(" +M(+"[$<#%!-#,$<"[(+)I.*(B.((B-\"J`<"($:"(((EI0@(D@@;;X@;8,$01 +M@(@1D.X1@.X@0.X@XF_'P@;C#!M"TB/V?`N!:@*`C*"("*`(``"A1P*B9.5, +M6`P'>>F)V?(&&-@!`/\C(&(`#N(W#N4R#NL.(N3MKN +MZ?G"!6(@S+#"+$ZA*@+:S,GYP@;;JJ(+S!;,%1PN(&*]PN\B5J\B\`S*^2!BHF +M.04F&0)F*:VV2@*&+`"I$7(DV[(E%H(B0#)A!7![P(>W&G`W(((DXJT",+,@ +MX`@`DB)`&S.7,^RR)18X4;)DV@])E&1:,$X@) +M@LC^%J@3J+8,"9D*DD8KL@8R#!S"1BD6ZQ+R)6_A3@`;__)E;_%&`.(N@0R= +M\.X0X.M!X#V3+0,=\"T*'?#!2`+Q;P+A<`+1<0*R:16"!N#2:BSB:BWR:BZ" +MR!&`@'2"2GR`B!'`B""":B7!<@+":BN!.`*"9#*"9#."9#:"9#>"9#J"9#M& +MG_^!(0&`C""";?#XU0R)]SD"!J3_#$F0GB"2;=U&H?^((8(H+JT"O0?@"``, +M"M(D\G"WH/@APB3Q#`[B3WX@S*#"W"30NZ"R&P&Y+)(B0*)A!++'`9>[47)A +M`Z(D\<(D\)(6)1NJHF3QIYD*&\S2H`#29/'"9/"")..M`N`(`/(D\K@QXB3Q +MR$&PVZ`@[J`;S,E!XMXD\-V@>KS2'0O9+I(B0+DQ&[N7.["R)19&J_^("588 +M["@1'?``,D8J#`F&L/_A3@#R)6\,"9)&,AO_\F5O\48`XBZ!#)WP[A#@ZT'@ +M/9,M`QWPH5("HF3EQD?_P5,"PF3EAD7_T50"TF3E1D/_X54"XF3E!D'_\58" +M\F3EQC[_@5<"@F3EACS_H5@"HF3E1CK_#++!3@!\^PP=TD8KLFR!'?``NE+B +M)6HY#J6\^I%/`(8,_P``-H$`BW/+4Z*ASTN3ZT-K@ZMC:4&)(4EAF1&JHEE1 +M>3%2H/!RHS^I`9%S`D%E`@P(8LF@0$*`@F1V`#>FH!"FP78"#(NGNS6X`9@& +M#!JB2X"0D'0,"F99,_(#`0QX4/\0@/\@\D,!X70"`#ZFP!"FT74"#!G0S,`6 +MG!2&3P!@FJ"2*0#@JA&0D'0F6`,`*)D=Q9Z#0P:N!&E,@`,&K@A)3(`#!JX,:4Q``P:N$%E,0`, +M"KA1Y3``#`JX864P`(8J``"R$P&B)':ZJJ"@]*)3`>`,`*)D=Q8J"0P:N!%E +M+@`,&K@AY2T`#!JX,64M``P:N$'E+`"BH`"X464L`**@`+(A!N4K`(88```` +MLB2,H*J@/?"PJJ"BVO^B&G?@#`"B9'<6R@(,&K@1I2D`#!JX(24I``P:N#&E +M*``,&KA!)2@`HJ``N%&E)P"BH`"R(08E)P#2(D#B)(S")';0W:#@W:#2W?_2 +M'7?:S,)3`0P)"^D6?N<=\`"B(D"F +M8!"F0J4_#!ARH-]2`P%@8`2P9A%P51!@52!20P$`-*90$*:Q=P+A=P+VM0ZB +M`P"PM:"X"[JJHD,`'?`,#?+2`H)/3^#=H-@-P@,`VLS"0P`=\``V00`,*W%X +M`D%.`**@C'IBDB;7@B;",%.@D%6@%A@4,I4"#'B`,Q&`,R``,Z;P$*;BE0,, +MCX#N$?#N(``^IM`0IL*5!`RM@,P1T,P@`#RFD!"F@I4%#,F`B!&0B"``.*8P +M$*;RE08,TX#_$3#_(``_IN`0IM*5!PSN@-T1X-T@`#VFP!"FJC*1PP!V@!&" +M)(,+F8SH%LD0HB-QJ`HF*@?&^?\``!;)#[(%`,%Y`G"[$<"[(``[I@P:@B;5 +MX@4!L2H"PB;6X)4$NK+2"W[@Y@2#_`CR*SR"%0&C_!`,!2#_H'K_\B\GD_P1 +M@_P2\_P7X_P<4_P=##[3_![=!<)DR9(K//(K.\%/`)/]"O/]`E/]`:/]&N/] +M%J/]%*/]%5/]$E/]$]G,TBL[LBL\T_L(LFQ,HF1?D@-\C053^`63^`F"9&!2 +M9&%29&)29%929%7R`WP;__#P=/)#?":/,,`0IAWP`)'#`*HR"YG2)(.L7:QI +MXB-QZ`X+F68N[O(%`(*A"W#_$8#_(``_IH;*_P!20WR`$*8=\%89_I(C<;)I +M`"5\^D;U_P"B(W&Y"F5[^L:]_P`V00"\4B%Z`@`RIB`0IKQB#":`4A%@52`` +M-:9@$*8,%PM"1]8/`!)``(>A@(;`&XB"4P`=\&)3`!WP``"1>P(`.:8@$*96 +M;]`N`(`)(#`:A1N$&R4P*R4P2R4P:R4PBB4P.B4P6B4P>B4PF0D#1&V?\, +M#,)3`L)3!,)3!L)3",)3`\)3!<)3!\)3"1WP``"V)P)&R?\`.Z:@$*:2`P&@ +MH`20JA&0D&2@F2"0D'220P&0UT$63?#`N1"0T#1;W=#0--"[(+)#`0:\_P`` +MLB4RPB4ZHB4JI1?]LB4SPB4[H"H@HB4KI1;]DL$8XB7ITB7KPB7JLB7H\L$< +MC0JB!-KY(9D1B0&")>;]`N`(`+(E-L(E.IAQJ&&B4P*24P.E'/VR)3;]`N`(`)AQJ&&B4PB24PD=\```-D$`#`9"TB-2)/)B9-PP8Z!05J"2!0$, +M'N!F$4?I>,%S`J*E/_*AS]*B`I"0-(+)_1;X";+)_!:;"0`ZII`0IO""@+:Y +M!9*@`.)(@.%_`K(%`*(%`>#IH.@.H*`TZKNR10!F&@X`/:;P$*;`_Z#R+P#R +M9-RR).46XQB")-DWF"O"%0&B)-S*JJ"@]*)5`>`+`*)DW1WP``#2)-GBU?\W +MG0(=\`#B'G?B50$=\*(D\CWP:JJBVO^B&G?@"P#")/*R)-QJS,+<_\(<=Z)D +MW6K_PP*Z[5EJ__")/*R)-QJS,+<_\(<=\J[LE4! +M'?#"%0&B)-P]\,JJH*#THE4!X`L`HF3='?#"%0&B)-SP(`#*JJ"@]*)5`>`+ +M`*)DW19:Y@P:2[6EIO\,&K+%!B6F_PP:LL4(I:7_#!JRQ0HEI?\,"LNUI:3_ +MZ[4,"B6D_QWP```V@0"A>`(,'`P+JG)B)]=!3@`P4Z!@5:"2!0'BH(QA3P!' +MZ3,,+9"0-(+)_1:8-O+)_!8_-NHRD<,`=H`5@B2#"YD6N`D6N0GB(W'H#N+. +M_A8."L;X_P``@M(FTB@PHB@QZI+R%0'3^@C2"%+#^AWS^A+3^AZB9,FB*#'] +M#((H,*/_"JT+@_\"L_\!P_\:L_\6P_\4P_\5L_\2L_\3^<:YQL)D7]()?(%< +M`+/Z!=/Z":)D8+)D8;)D8K)D5H)D5?()?!O_\/!T\DE\\L_X%C\^\B?5XB?6 +M\_X(XF9,'?````!6^0""(W'2:``E$/H,"Z%X`@PICT"P_D0DF3)D@4!D)`TC!EF&5J8`?*5`XT+ +MHBDQ\/"TDBDPH_@*HI4"D_@"L_@!P_@:L_@6H*#4\_H.P_@4P_@5L_@2L_@3 +MB<:IQL)D7^(#?-T+L_T%X_T)TF1@HF1AHF1BHF16HF15D@4!D)`THLG^5HH: +M64'2E0C"E0:RE01Y,4DAHI4".1$,#HT._0XX`:E10I4#H*#4/Z +M$O/Z$ZG&6<9"(S%P4+2B(S!X,4/X"J/X`M!`U*%:`E/T#N/X`5A!X_@:X_@6 +MJB+C^!2H4>/X%?/X$O/X$XG&2<9"(S$R(S""(G]#^0HS^0)((3@1X_D!\_D: +M\_D8X_D6\_D4\_D5X_D2X_D3F<;@"`"RE07"E0?2E0F"(G\M"J*5`^`(``P< +MTI4#((#4H)"T#`NBE0*PZR"3^`ZS_@62E06"9@S0T+2"E03"9%^@H-33^@[R +M`WS2E0F0D+2`@-23^`[S_@G0T+3RE0?B9&"B9&'BE0:BE0CP\+2"9&+@X-3S +M_@Z@H-33^@[B9%:B9%62!0&0D#2BR?L6ZA7"`WP;S,#`=,)#?":,$/`0IN(G +MU=(GUN/]"-)F3!WPLD-\H!"FDB?5@B?6D_@(@F9,'?#R)\(6GQKRE0(,0)P_Q&`_R`` +M/Z;R%0&2)];2)]6"!0$@Z:#3^0B@[H"`U03B+B>`@#33^1'S^1+2TB;2#5+C +M^1>S^1W3^1ZF.`+#^1`,/9)DR8(GUN(GU:T+@_H*X_H"L_H!P_H:T_H6P_H4 +MP_H5L_H2L_H3J<;"9%^"`WS]"[/_!8/_"?)D8+)D8;)D8K)D5K)D5<:L_P`` +MHB?6PB?5LDE\P_H(HF9,'?"R50*R502R50:R50BR50.R506R50>H`;)5"8T+ +MDBHPHBHQL-#4L_T.H_@*D_@"L_@!P_@:L_@6P_@4P_@5L_@2L_@3P_@9B<;9 +MQL)D7_(#?.T+L_X%\_X)XF1@TF1ATF1BTF16TF15AHW_`%;)[K(C<=)K`"7+ +M^0P+H7@"#!Q&MO\```"1PP#J,@N9XB2#G-Z`(,'(;U_P``-D$`##D,"H&` +M`K%E`F(B0'*@N%*AT%I2>G(R%]H;9F)G$K`B@&>3-T&!`I)%?L(B58<)(?N)F\>)F\))F*I)F*Y)F +M+I)F+Y)F,I)F,Y)F-I)F-Y)F.I)F.P`ZIM`0IC&"`K#=P!;]$``SIN`0IF8> +M$2&#`@`RIH`0I@`SID`0IB84\``ZII`0I@SBL)G`%FD.'?``PB)#\B;QXI,& +M4J'0L/\1^O):_^)O=D(F\?*3![!$$4I"6D3R9'?B)O'RDPBP[A'JXEKN\FYZ +M0B;QXI,)L$012D):1.)D>T(83U(F\<#-P`M$&]729O%'O4]2DP5"DP3B9B_R +M9BY29BM"9BI"%[>P_1'Z(DW-RP%QZ,"ACL`DF8RDF8SDF8VDF8WANG_HB;9F`>@ +MF<"29ML`/Z:`$*8,(AWPXB;PDF8ODF8NDF8KDF8J#`_R9O'2%[<;[N)F\->L +M;Y)F,I)F,Y)F-I)F-Y)F.I)F.T;7_^(B\N)F.E(B\U)F.T(7M\>D==(BZM)F +M,L(BZ\)F,Y(B[I)F-D(B[T)F-P;,_P``XB=4Z`Y6_O(`.J;P$*:WGP+&(``, +M`AWP0B;90$W`0F;;`#^F(!"F##(=\`#B(O+B9CK2(O/29CM2%[?'I4G"(NK" +M9C*2(NN29C-"(NY"9C;R(N_R9C=&M?^29C*29C.29C:29C>&L?^P[1'JXD(N +MZD)F,C(NZS)F,_(N[O)F-N(N[^)F-X:I_Y)F,I)F,Y)F-I)F-\:E_P"")ME( +M!X!$P$)FVR$P`@`RIO`0I@PR'?`V00`,:`P:<80"T84"#"P,.W:`*8"8$;#I +M(``^IH`0IG"(H(@(P.D@@&#UG"8`/J9@$*:`\/1P?Z"`@/6L2L;S_]#XH'(? +M`8!W$"R$"" +M9``H!2F8!"F8@\`\@\!`&8C:00` +M_R/R90"(!)*O@)>8';*F`@`[IL`0IL+,X,)D```[IJ`0IJ+*X*)E`((D`"IH +M:00H!3HB*06(!#*OP(B7B(I3H#B8N$\;S_Z@" +MLJ`$PJ",P*J`I2C(&#?(6`](+U^#A!-#N$>#=(-)EC=%/``#_$?#,(,F- +MPF7&H@O9P@8,,8@"L*H1P,4$T,P1P*H@HFTX\B8SXB8R.C+`_P'`[A'P[B#I +M;<(&$.(+UZ(+U##,$8#N$9"J$>"J(,"J(*)EQW)C0')#?))#>GGMB=WR"Q0` +M_R-P_U,@_[#R+TY*__G]X@L<`.XC<.Y3(.ZPXBY.2N[I_<(&]B#,L,(L3DK, +MR?VR"]<+NQ:[%O&*`H&)`H)C*/)C+I@!D@GJ%OD2H8L"HF,@V`'R'6VQ-P"0 +MCP'@_P&*__)C0:(K\,(KW7R^X.P0XFO=T@W7TLW^%HT0@1\!@(H0@FOPJ`%B +MT@&2%K8,!')*)JR)<1D">G*"(RBM`G"W(.`(`*T"L@-\@B,N#`F20WK@"`"B +M%K8;1*2(I06&@W8"=+-_A8=#:%/`(@!#`FB*DS"&"/HJ*"X=,"[@J"@ +M=+JJ"_J@^8/YZ'D.R`$,';(,+M),)7),)Q:+"O(BF1O_\F*9XB6!HB,Z@B,[ +MD=H`@*H1H(@@D(@@D4\`K0*":4QR8D`E.@:X`0P"HDLF4L^:%.``;;_P``-D$`'$D<#0R,/,L\#QQ^#,J@@Q`GY"BG +M`STF2&_"R/@67`MFJ"N0,A",T]+#_!;M(>+#\!9>)Y>3%[`E,!WP`*<#,"9( +M;F+(^!:&"]+(]!:M#0P"'?```)`R$)<"*F+#_!9V#H+#\!98$)?"(K`E,!WP +M``"0,A"7`@YBP_P6Q@V"P_`6V`^7PBXM!1WPD#(0%A,0HL/\%OH1PL/P%@P6 +MEY,Y4-4$%DTN4.,$%AXJ+((@)3`=\)`R$!;##F+#_!8F$8+#\!;(%)>3/5?E +MNU"C!!9**-`E,!WP`)`R$)P#PL/\%@P4TL/P%IT8D./`5H[S4/4$5M\A4&,$ +M%G8=+,(@)3`=\```D#(0%A,.8L/\%F82@L/P%E@7EY,54)4$5DDJ4*,$%KHF +M+,(@)3`=\)`R$!93]6+#_!9V$H+#\!8(&)"CP%;*\+`E,!WP``!0M016:_-0 +MU`06_13`)3`=\%#E!%9>\E#T!!;_#<`E,!WP``!09016)AI0A`06^!4\0B`E +M,!WP`%!E!!;F[U"$!!8(%:`E,!WP4*4$5MKN4+,$%BL5T"4P'?```%#%!%:L +M[5#C!!9.%-`E,!WP4/4$5I_L]H4"!D@`5[X"AD8`'((@)3`=\```4&4$5N;J +M]H4"!D,`5[X"AD$`'((@)3`=\%!E!!96Z5"#!!8X%)`E,!WP``!0E006F0]0 +MHP06RA4L@B`E,!WP`%!E!!86#U"$!!9(%:`E,!WP4)4$%DD/4*0$%GH6\"4P +M'?```%"U!!;K#E##!!8\%I`E,!WPH"4P'?```%#5!!8=#E#D!!8.$/`E,!WP +M4/4$5A_B4&0$%F8/P"4P'?```%"%!%:8$_:%`D8P`%>^`L8N`"Q"("4P'?!0 +M90165A+VA0+&*P!7O@)&*@`L0B`E,!WP``"@)3`=\%=E`@8A`%!D!!9V##Q" +M("4P'?!09016E@]0A`06N`L\0B`E,!WP`"R"("4P'?``\"4P'?#`)3`=\!S" +M("4P'?`G+,N`QKD9$"#"4,-(89 +M``#9T]G#B$.2)SRB)SN:B)('?J/X"-/X$./X'9/X'H)FR?(G/+(G.ZT.\_H* +ML_H"X_H:T_H6X_H4X_H5T_H2T_H3J*2*>.C^0B2;$P=\`#($0P$21.B +M+!RR+"3"+"@EF?NI`:@1LBHEPBHIHBH=)9C[PL,PTL,T@B`(`)'# +M``N9HB:#%@H)%@D)LB*4N`L+F68K[.@SC00,OW#N$?#N(``^I@P9TB<\R$/H +M(_(G.]K,T@=^\_P(0_P0X_P1T_P>PF;)LB<\HB<[T4\`L_@*H_@"D_@:0_@6 +MD_@4D_@50_@20_@3B(LXL(LX^/\",)M3!WP +M\B*460^ES?C!3P`,#0P>QK/_`%:)]X(BE%)H`"7,^`;;_P`V80`,:Y&1`@PE +M##3&`P```#RFL!"FH+#UH(#TD)B@@+L10,L@`#RFH!"FD*J@J`I0RR"@T/56 +M;?V@ND&`NQ%0NR``.Z:0$*8,'&%.`($J`G$[`@P+H)"4F3.Y`Z%/`'IRBH*) +M$?;9`D8E`.*A`DD3\LG`^3,`/J;0$*:1PP#28P)V@!&")H,+F8SX%ND2TB*4 +MV`TF+0C&^?\````6V1&8,XT+TJ$+<)D1T)D@`#FFF!'80[G#N=/R*3SB*3OZ +MW>/]"/@CX@E^P_T0\_T1X_T>TF;)TBD\DBD[T_@*D_@"P_@:0_@6P_@4P_@5 +ML_@2L_@3B_NR)R6B80#" +M)RFB)QUE>ON"(0'"PS#2PS2"*"&]"J(A`.`(`)'#``N9HB:#%@H)%@D)LB*4 +MN`L+F68K[.@SG00,OW#N$?#N(``^IK@1#!K(0](K/.@C\BL[VLS2"W[S_`A# +M_!#C_!'3_!["9LG"*SRR*SO13P##^0JS^0*C^1I#^1:C^12C^15#^1)#^1.9 +MS8C3^,.`@+3P\-2#_P[YS>(GXL(GX^/\",)M3!WP\B*460^EK_BA3P`,"PP< +MQK/_`%:)]X(BE%)H`"6N^`;;_P`V00#`$*8,#J*AT+*@N+JRDBL2JJ*"&]H; +MF9)K$I<8-3$J`M%=`CHRVL*R+->2(SR"(T$@NZ`@F:#:F=J[LBLHLFR^@FDH +M\B,\TAI/&__R8SSW'0P=\`PX@DI^XFL2'?``XF,\XF-!HB,[XF,CLB,B&ZJB +M8SNE@@4,'`P+H+R#LD-^'?`V00!!D@)*0H(DWPEQB`)Z[,H(DZI(DZ9)D%()D%1;S"Z(D +MV["J$:JB:JK2*G;29!S"*G?"9!VR*GZR9""B*G^B9"$=\+(DV[>:1E)D(%)D +M(<(DZM(DZ=)D%,)D%18#";#K$>KB:N[R+G;R9!SB+G?B9!T=\`P_\DI^PF)` +M4F044F054F0<4F0=4F0@4F0A'?``LB(D +MVU)D%%)D%;#N$>KB:NZ"+G:"9!SR+G?R9!WB+G[B9"#2)SL,'+#=$=K2:MW2 +M+7_29"'"1WP=\%)D'%)D'5)D(%)D(1WP``!29!Q29!T=\`P?,D=\,F04,F05 +M4F0<4F0=4F0@4F0A\D=Z'?`V00`R(D^RI%0]\*T#I5X%@J(@D90"H9,"HF)[ +MDF)ZBH-\\B)H?R)H@`P"'?`````VP0!Q3@!1.0"")X)R)YIB)4ZXK,PF3C +MDB,C@B(8L4X`X5,`FHB"9.3"+H2HH7P?\,P0PFZ$D`"FC)EV@`20`*:,&0;] +M_^`0IO(B?T$W``P,X/_`%E\/D3\`X8,`D)<@X.H@Z;&9P88%`.`0IO(B?QO, +MX/_`%D\-@J`3Q[@"QC(`\B3G^0'H`>#@%.D!F`%F.>[B)*R2)2#@\`0';A)\ +MZ(".$()DK,`@`((DK(D1P"``#"B`F2"292#`(`"2)2#`(`!V@!"").>)(8@A +M@(`4B2&((28X`P;Z_P!\V(")$()E(,`@`((E((DQP"``C&_B9*R2)*R9$>BQ +M^,'B:X*2*X*B:X*"*X+R:YI,#^(KFG)KFI(KFH(B&H)E2O)E3-)E3N``IHRN +M=H`$\`"FC"\&_?\`=H`3XB3GZ4&809"0%)E!B$&"R/T6"/)&^?\`XF8LH!"F +MHF8MD!"FDF8N@!"F@F8O/?`]\/``IHR?=H`$L`"FC!L&_?^`$*:"9C#P$*;R +M9C'@$*;B9C+0$*;29C,]\#WPP`"FC)QV@`20`*:,&0;]_^`0IN)F--`0IM)F +M-<`0IL)F-K`0IO`@`/`@`*``IHR:=H`$\`"FC!\&_?_`(`#`$*:P$*:@$*:0 +M$*8J")"F2P2"0B*"("()J$)(D*/"9H)@)DFH1@B0HP(B@B`B":A.")"B2 +MP1"0B*"("()J$H(D*)+!()"(H(@(@FH4@A1-PA1=DB(;\84`&\R0D'3PF2#` +MS`'`B"#R%$K"%%R29::10`")BAO,P,P1PFH) +ML<(J&,FQDBH9F;&13P""*AJ)L<(J&X(D'LFQHBE&J;&A.0"2*429L8)J2L($ +MPPQ)#%@+S,")@P`80`#_H?)A`/&C`,(A`,)J3/)J3I``IHR9=H`$H`"FC!H& +M_?^`$*:"81O"(H`,"X#,P!9\$($_`)&#`*$Y`("-()">())A&()A&88&`(`0 +MIH)A&\(B@+++`8#,P!;<#9*@$[>Y`@8U`)(EYYG!B,&`@!2)P&(X8"`%(GAB.$F.`:A.0!&^?\`?-B`C!"":B#`(`""*B#`(`", +M0Y)EK,(EK,(A&,)F@L(A&9(F@N)F@H(F@L)FFI(FFM)FFH(FFL(D'L)J2I@! +MDFI,\FI.@`"FC-AV@`2``*:,6*$Y`$;\_P!V@!.")>>)\6#.(D3`PO/?#P[B#B9$S2`@OB`@WR`@^B`@["`@RR`@KZ +MJNK,VKO*N[JJ#`RR$@2B9$V8$L)D2<)D2["&5)"8=9)A'!8X';"&!+#+!+": +M!+#9!,J9L,@$VLRPUP3:B,J(FHB'N@D,C0P>XF1)TF6P\B$<#!CP^)/R9$J< +MGZ(2`9(D2Z"@!*"9(%:Y`+*@!,*@`<)D2;)EL-(D3N(D1^)D2(Q-\B1+5F\` +MK0>]`B4_`H(A'!N(@F$=O(@RH`",B%$IBQ@%B81=BQ@%GN@*&>O^")%!62-Z2(18@FN@ +M`*:,FG:`!+``IHP;!OW_PB$5%IP3#`WB(1OB9#?2816@$*:B9#B0$*:29#F` +M$*:"9#H]\/`@`/``IHR?=H`$L`"FC!L&_?^`$*:"9#OP$*;R9#S@$*;B9#W0 +M$*;29#X]\#WPP`"FC)QV@`20`*:,&0;]_^`0IN)D/]`0IM)D0,`0IL)D0;`0 +MIK)D0CWP/?"@`*86ZN!V@`7P`*867^#&_/\``(($PPN(%GB3H3D`#!(,&9)J +M+AWPL@3!L+`4)CL*P@3"/?!F'`(&(P"B)"@,&)(46("J,*)D*'"JH))JZO(D +M*(#_,/)D*<9`_A8*"`PK#!S"9$FR9;`&D?\KF3"9$."9$9"<@@9H_@``@@3$ +M5MBC@@3!@F$3@(`4@LC]%NBBD@3"%LD(DA1:@A18EYA'@B$3DB0H"X@6R`KP +MB:"("(G:@B0HP(B@B`B)^@:9_@"0$*:29#?&L?^R)"BB%%APNZ"R*^JPJL`6 +M2H@,`AWP``PK")"CRP2#PS*#(#,)J$`9L_@"")"GPB*"("(G:DB0IP)F@F`F9^I(D*(+! +M$("9H)@)F>J2)"B"P2"`F:"8"9)J$$9?_@``-D$`(J2`'?`V80`,&B6XSY%3 +M``P=P"``#.ORH=CZ\H(OF])OFN(O9!N(@F^;V0["*83)`;D1J!&(`:"((()I +MA,`@`!WP````-F$`LJ144B)/'?[9F!D07+'#W!T0663 +M!)&8`@S[V`%\_T*@X(*AO,*BN,K%BH)*0D)EV8)EQQP$#`*-!2)L9@R"\D4` +M\F5$\F4X:75Y9>(-^.)%)-(-^=)%);),D+),D;),DK),D[),E+),E7:B2T)( +M=*()`$)(=;()`4)(=L()`D)(=]()`T)(>.()!$)(>?()!4)(>B()!D)(>S() +M!XN(HD@LLD@MPD@NTD@OXD@P\D@Q(D@R,D@SBYD,#&"W@L)E4["[D)"[$;)E +M5KK;TF59@9D"^`'AF@*2H4RRH62BH5BJI;JUFI69%;DUJ24,:Z(EV>)O:X)O +M:N5EV@P"'?`````V00"X)A@6\LC^%O\?DLC]%GD@9D@*#$NR9"V&``#B9"WR#,3R +M1+BR#,6R1+F2#,:21+J"#,>"1+OR#,CR1,""#,D,#R88#I+(_A9Y'&8X"*)D +M+X8``/)D+X(,RH)$P;(,R[)$PJ(,S*)$PY(,S9)$Q((,SH)$Q;(,S[)$QJ(# +M[`Q)C0,6N@9`I"!VJ662"/""R!"22C2BRA"2".&22B62".*22B:2"..22B>2 +M".222BB2".622BF2".:22BJ2".>22BN2".B22BR2".F22BV2".J22BZ2".N2 +M2B^2".R22C"2".V22C&2".Z22C*2".^22C.2`^VM!!:Y!I*@!':I99(,@,+, +M$))*=*+*$)(,<9)*99(,))*;)(,>9)*;9(,>I)*;I(,>Y)*;Y(,?))*<)(,?9)*<9(,?I)* +M["*(D+^)- +M:.)$N(($N28J7A98`,(-E(>\!>)-:.)$N?(D+68_S(($NA98`)(-D8>Y!>)- +M:.)$NJ(D+X($NR8J0198`+(-E8>[J.)-:.)$NQWP\D0!1MW_``"B9"U&@_\` +M`.)D+T:/_PP_\F0M1G__C&B2#9(]\(>YI>)-:.)$N0;G_XQXH@V3ASH"!MG_ +MXDUHXD2['?`V@0"M`I$Y`#(B3X*@_X)I@B4S!&*A;&IB8*8@I6G:HB)_99O: +MK0,BH``B8S\E*`!="MQJJHE)-K80;'Z +M`.*@K_(M'PP,PDV`R0\F)`+&W/\&B/\`O0-E'`3&H?^"HJ"*@X((@8S8HB,X +MO0,;JN4:!`PJ1@``#%JR(RV2H(2:DR8[#<@3N"/8,]DCPF,#LF,!XBGS&^[B +M:?.B8\\&O?\,M0P/^0P&<_\`@B/'>0@E_0/&FO\`#`(=\)@,5BGUHB-$HF,_ +MQN#_#`G&T_\`PBT?#+4,"[D,QF;_-D$`#"P,&E&=`@P)?/-"HJ1M`G(FV2(B +M+4I&(YTO@/Z#9Z__GRZ`[8%GKNZ?+8#0PE +M>MW9\K(F+_(&`4(F+;++_A8[">+$_19.#1;?#:)B%:)B%C(F-D(F-\@6"S,+ +M1$!$$<`S$4`S(#)B24(F+WR[/(,6%`<+E`P$D$6#T/01,/\0\F)*Z';89L#N +M`<#=$>#=(-)B1L@,03<`>LS"8D1R8D=R:,4B)/!R)-V!'P&PMQ"R9-VB)BV` +M@A`F.BZ"9/`,`AWPL9X"LF8^1J#_``#2IQ_29CZ&G?\F-$.B8A6B8A:28B7& +MVO\,%,;C_S$A`5%8`%)DIE(DIH%D`#`R(%!0=(!5(%)DIC)D\/(F-@R.#`+W +MOA\,2("'(()DW1WP`))B%:)B)9)B%L;)_Z)B%<)B%H;'_PP"'?`````V80!@ +MP'10L'1`T'3AGP(P\'0`/J:`$*;PG1$@W9!R#;@`6",,*`LW)A<0C-6`HQ&` +MJB``.J9P$*9R80!"I1\6W!(`-*9@$*9B8D\`=B-R8D^03Z`A>JH;JJ!P8%"GHU(D1P`30`!FH0"9H19+#U!1 +M(:I54F1'EZ4(`'^A<%6`4F1'9R4+`!-``(^A@%7`4F1'\)41DF1'`#ZF4!"F +MH@VY`%4C"SHF&A06%0&2H`*`@Q&0B"``.*9P$*9R80$6S`FBI1\`.J9@$*9B +M8E``QB/"8E`7I0<`?Z%Z55)D1V>E`D;'_P`30`"/ +MH8"%P()D1X;#_P`6!092)$BJ55)D2)>E"@`30`"?H9I54F1(9R4+`!-``*^A +MH%7`4F1(L@+25MOXPB(O9BR'#`+PU1'29$@=\```@B1(XB(O70CBSOY6+O.` +M42%29$A&RO\`#`+P]1'R9$@=\```@B1(77_PP"'?`V00"1H`)13P!RPFBQ3@`,-L(B0M(B0PP(30BM"-/Z +M`,/Z"&/Z'J)KR3(B+:(B0PP;,L/]H_0*8_04@_0:L_0L(-,$%BT)(B\-81T-"TT_P.#`TPWH/3_!S)Q=(B3\(B4&(G2*(G1T(B+WSK&^J@ZK.P +M[A`F)"WP-A$P,2$;\S#SL["_$`P?IAH"!BX`#`_&+````)"@!&"PM+/\#J/\ +M',G%1NW_8$$A&S0,%D`TL["S$`P3.0'F&@,,#_D!,@+!YA0!#`:\,]Q9^`%* +M1D!!(4I,"T2JKZ"A(:JM!A,```"@^I!`1)"H`4I&0$$A2DP;1/JJH*$AJJW& +M"P``W)F@^I!`1)"H`4I&0$$A2DP+1/JJH*$AJJU&!`#X`4I&0$$A2DP;1*JO +MH*$AJJV@,-0,'0P&\$010,"TD&V#P_,.8_,<.<7&#`"JKZ"A(:JM#!WF%@$, +M#6IM#!-@82%J;!OV"V9`;Y,,#T#S@_!&$4`PM*!@U#/V#O/V'&G%X,#4B<5` +M\2$;VJ#:LQMOL*"T0B(OT($A\&^S8&$A\(@1@(#4\&818&"T)B0QH_P."_0, +M&PP.\.N#X_PO\&!P!C +M^`Z0T`2C_`X,&PP$D$N#T_PT()@&(J2C(J24!`!&!@M#`PU&/S#D/S'#G+6"I0(`.*9P$*9P<'1R0YT6-TBB`ZR&"`"B`ZQF+-X' +MZ@(7:MBBH0(`.J:0$*:B`ZR20ZT]\$?JQW(#G;D!-^H)!VHLP@-;N0&L3*T" +MLJ``P@-HT@-LY3__T@-KLB$`9AT+XB,N\B,M\F,QXF,RH@.LN0&@@@16N!,7 +M:@T<^@`ZII`0II)#K@8!`#S\PD.NH@.L!VH0T@-;C*WRH0(`/Z;@$*:B`ZR" +M(Q.@D!2"R/X6Z!.<2<(#K@=J&M(#79T$4_D`G!U3^0T&`P#B`ZQ"0ZX,#`?N +MY`P)#+[#^0&`V1'@W2!`E"``/::B(RF"(RCR`ZRC^0"#^0@';P)3^1"A7`#R +M`UQS^1'!3@",'U/Y%O(#KN(#K=(#G//Y%^/Y'4/Y'M/Y'Y)LR8(C%7%/`.&@ +M`H+(_A8(#H++_1:829++_A:Y%`O+%FQ*TB,IP@.L\B,HG03`L`3S^0+3^0I3 +M^113^14';#D,.(/Y%E/Y'$/Y&A;[,J"Y(+G'TB,IPB,H#`+3]`##]`A"9TP= +M\-(C*<(C*`P"T_0`P_0(0F=,'?``#,_P_!#RS_067T+`@@06>`U3^1;&[/\` +MK0(,&\(#:0P-92G_D@-KN`%F&0NB(S#"(R_"8S.B8S2B`ZQ&I_\``+*A`@`[ +MIJ`0IJ"@=*)#K,9>_P``-^H*PB,5O07"S/[`MH,,G=<*`H:J_T)C,D)C,4)C +M+D)C+<:F__++_1;/48++_E:H,O(C*<(#K((C*)T$P+`$P-`$@_D"\_D*4_D4 +M4_D5%BT\##S#^193^1Q#^1H6JT2@^2#YQ^(C*=(C*`P"X_0`T_0(0F=,'?`` +M"XL6^#R2`UH,&J)#:X++_@P>#`V`WH/20VJ&6/]#^1;&MO\`D@+3YAD"AKS_ +MW0(,"\*@F,K"A@D`##BB`VN#^18,"`NJH*O`H(^#@_D:F<"`ZSR+4JB#(`GZ#B9QZ(M2/(M1_"J$1N/\(^SH*$A +M&_J@^K-\ZJ"($*#_$/#PM*(,?X"`U//X#J"@!*/X'(G'1L?_``"@H`2"+4GP +M_Q'P\+2`@-3S^`ZC^!R)QYG'\BU'HBU(?.@;G_"J$:"A(?"?LX"9$!OZD)#4 +MH/JSH@Q_@/\0\/"T\_D.H*`$H_D9QX(C%8"`!(/_'/G'1HC_^I)228`,,AWP`)G'H@.LX)D@H+,$%IL,XB,N +MTB,MX."TT-#4X_T.0_T_](C*<(C*`P"T_0`P_0(0F=,'?`` +M)BP'#`M&FOYF+/>2`UH,"\8]_Z#B!!;>">(C,-(C+^#@M-#0U./]#D/]'-G' +MF"(RDB(RB#]``C]`A"9TP,`AWPT@.LT-8$5FW" +M#"J2`UK&"/^9Q[(C+J(C+1N+&RJ@*K.PB[-\ZJ`B$*"($("`M"`@U(/R#D/R +M'"G'\B,IXB,H#`+S]`#C]`A"9TP=\``ZIK`0I@9)_@``0_D6QNK^F<>B`ZS@ +MF2"@PP06?`KR(R[B(RWP\+3@X-3S_@Y#_ASIQ](#K-#2!!9M$,(C,+(C+\#` +MM+"PU,/[#D/['+G'F<>"(RVB(RY\ZQOH&_J@^K.`Z+.P[A"P_Q#P\+3@X-3S +M_@Y#_ASIQ\(C+](C,!N,&ZW0K;/`C+.PB!"PJA"@H+2`@-2C^`Y#^!R)Q](C +M*<(C*`P"T_0`P_0(0F=,'?"M`F48_^(C*=(C*`P"X_0`T_0(0F=,'?`G:E;B +M(S#2(R_@X+30T-3C_0Y#_1S9QYG'LB,OPB,P?.H;^QN,P(RSL/NSH/\0H(@0 +M@("T\/#4@_\.0_\<^)QR(C*?(C*"/T``P"\_0(0F=,'?``FXD.@&\QVJ`RZJ2N9(*J@TFI'TFI(2[L,"0PH +M9BSDPJ4"`#RFL!"F0J*@LD.AL+!T%NL*HJ$"`#JFT!"FK#V1^@``.::`$*8` +M.J;P$*:<+W:`#0`YIL`0I@`ZIK`0IHP;QOK_\:$"`#^FT!"F%JT(#`K!HP+1 +MH@(,_P`\IK`0IB:+"_>;%0`]IH`0IH;Z_P`]II`0IJ+*(8;W_P#2IA\`/:;` +M$*:R(QV@K("BRO^G.S'R(R.P_X+B(R;PJH"B8RNG/BB2`UR"`V*A3@`PF1&L +M&+*@@+"Y(+)JQZT")0(`+0H=\$K"XDR`##(=\+T"980"AO/_DFK'QO?_``PR +M'?`V00!"(D1B(C8RPEQ`I""]!F6L`J)C*[T&K02EJ`(,!Z)C+%*BH%I2K0*E +M8/]R0ZBR(R&2(RQ"(RV"(Q\;F1M$0F,MDF,LEY@*HB,K>"X(C*W)C+(+(`8)C*U:I\*(E'Z@*5HKZ8+3` +M5AO\QN?_##+13@#R([!\_`P>Z0_";8$=\``V00!2HTQ04H"")3E")3B`(!2< +MI(`@IHR8=H`$D""FC!D&_?\`,J8B930,`AWP``""$P&B!7P,A(!@!.!F$8"" +M(4!($&`B($`B(*QJD@5]D)`4P)D1D"(@0B4Z<5H`8A,$0$"D0$01<&808"(@ +M0"(@!NC_`#P)D)@0D"(@!O;_`#;!`@Q%L3X`\34`T6D`HM(#0B+(!(:4" +M0$`4C/0+A!;X#Y+$_A9I$GSR'?```,(J3%(3`)%Z`((J2U#R@Y`O((#RDRT/ +M)VP"L"\@0A,!\4@`D2$!0,`D%HP7)V0"\"(@%V0"D"(@0(`$@F$P!V0"X"(@ +M5V0"T"(@X>$!8@K!T>`!8F$N8&`4%OP4P:8"0(@4X(@!P"(0("@@@:<"1J`*B82^@@'2`B!%0I2"0(A"`(B`E +MA0*"KP"R(3"`@A"@('2`(B`6FQ`,"PP&#`0,`PP-#`X,"@P%#`S`\#10_P'P +M(B"08*:,F7:`!(!@IHP8!OW_`'*FDLS^%AD1\LS\%C\:)HPU&RP=\`""*DKP +M(``6Z!&B*DRR$P!0FA`6JQ=7"A0AJ0+`8*:,3-!@IE:=_P!RI@P2'?`,`AWP +M\&"FC$^`8*96F/\`=::08*:,2?!@IE:?_P!ZICWP@&"FC$B08*96F?\`?J8] +M\*!@IHQ*X&"F5I[_`'VF/?#P8*:,3X!@IE:8_P!SICWPD&"FC$F@8*96FO\` +M=*8]\-!@IHQ-X&"F5I[_`':F/?#P8*:,3X!@IE:8_P![IALL'?"0(B`&H_\` +MT,(@@L;]X"(@@"R3QJO_``P+4:H"P5P`T3P`X:L"@`,"2)A,7*3"[)A,J)A-+(A+@PO#!KPNQ!P(2'] +M#8T+L)J#\&(18&?`DF$@L(J3@-Z3D/Z30%\@DI,)0$T@8/63D.$A\%X14%G` +M4-230I,*43X`,F$S0*$A4&\@\+H1L+3`L/:38B$S(F$LXF$H8I8(HF$F4%T@ +M8+$A\#L1,#;`,-634:X",B$TLF$G4/\0P#,1,F$M.KLZJC(A+U!=$*"@M,`S +M$3)A*CHB.N[@X+0@(+1`(A%`[A$QKP+@52`@_R#AK`(B(3&PL+3@_Q`P(A#@ +M51`Q(0&P52#PJB"R(3+B(3+QK`(P(B"`[)/6*0`&V`*2824R(2B0TB'PW1'7 +M$P6!>@"`[B#6)@"&U0(R(2=@TB'PW1'7$P6!/@"`[B`R(24;AH""(1N3,-(A +MD)(A,)VS8#(ATB$J8(.S,B$@T-%!TF$IVIDPO).0D+0QK@)`F1'="S#N$#(A +M+9#N(/#N$#`Q(3J(@("T@.X@UB<`AL,"8B$L<+(A\+L1MQ8%P7H`P-T@UB0` +M!KH"PB$F0+(A\+L1MQP%P3X`P-T@0,(A<+(A&X0;EY"2(8""(7";L[&N`D", +MLPQ,L-T0LB$I.HB`@+2ZF9"0M$"9$9#=(/#=$(#=((8"```,#0P.#`H,!0P, +M#`L,!@P$#`.&^/Z!D`"`DA"282N'@C,,!`P##`X,++(A+\!:$5!0M,"[$;!A +MM+"BM$"J$4!F$0P+T&8@\&80#`U@52`,!@;I_@``89(`@>$!8&(0@(;`S!A& +ME`*!X`&'E@(&%P.1D@"70@)&>`+283MR83;"83=BDPK"DPMB82-@\2'P?Q%P +M9L!QL`*-#L"1!)#GDY$^`$)A-<)A))!>(&#EDU*3#?)A)N)A.%!!!$"'DT*3 +M#)"8($)A(D#A(?!N$6!$P$")DV*3#D*3#X)A.F)A(8&Q`F"1(?!Y$7!FP$!Q +M!'#8DW$^`%)A'^)A&G!](D])A/'*3"=(A.T)A'G!A!DV$^`))A&=)A +M.V#=(&*3"&)A.3(A.6!A(?"&$8`SP((A.W)A)6)A)S"-DX)A.\`Q(<#:$=)A +M+3)A+-JOVN[:9F!@M.#@M*"@M,`R(7#Q(<(A.#)A%/)A*!N/@($$VMG0T+1P +MD@3PB;-P3@B$Y8"(00"(@;0C6*`!&K01R(2>` +M0B'P1!%'%P6!/@"`,R""(24;1F"2(4!"(6!)LY(A*("#(1MY<'(AD'BS@B$J +MD:X"@()!D#,0BG=P<+1`=Q%P,R!R(2V2(13P,Q!P<2%Z1$!`M$`S($(A+()A +M%9"0!!N$@($$0(FSD;("30R`29."(2/6*`"&#@5B(2."(2:"80]@8B'P9A&2 +M(0]G&06!/@"`1"!B(2."(20B83T;EF`B(9"2(6"2LR(A+("#(7J9&V)@8B$@ +M:+,AK@*"(160D+0@1!"*9F!@M((A'4!F$6!$(&(A%R+(`?!$$)!$("`A!)&R +M`F!@!(`FLR#)DX(A(L!L("(A/=8H`,;Q!,(A%8(A(I(A&I)A$(""(?"($8)A +M$9(A$8(A$)<8!8$^`(!F(#)A/B)A/3(A'R(A(C`S(1N"()(A@((A((FS(B$= +M>HB`@+0;DI"2(2"3LR&N`LJ9D)"T0)D1(&80(7H`D&8@\&80DB$<@&8@@B$6 +M&SDP,02`@`20.+,PLI.2(2$B(3TR(3[6*0`&U022(2&"(1F"81*0DB'PF1&2 +M81."(1.2(1*'&061/@"0NR"2(2&0@B$;^?#R(9#XLWK_\F$\DB$>\B$&PLB'PNQ&W$P>!>@#HH8#N(-8F``:&!#(A)V"R(?"[$;<3!<$^`,#N +M(+CAD;0"&X:`@B&P>9-@LB%@B[.R(27!K@(;F[#2(9"2(;"=L[(A*L#N$+"Q +M0;)A*;J9D)"TLB$M0)D1D.X@\.X0L+$ANHB`@+2`[B""(20]!]T'UB@`1G($ +M8B$L@$(A\$011Q8%T7H`T-,@@B$CUB@`!F@$PB$F@#(A\#,1-QP%@3X`@-T@ +MPB$D&XS`DB&`@B'`B;.2(2,B83T;*9#"(2`B(9`LLPQ,DB$INB(@(+2:B)&N +M`H"`M$"($9#=$(#=(/#=$"#=("(A/09[_I&0`($A`9"2$))A*X>9`D8Q`Y%( +M`((A*U)A&)>8`H:J`X&0`%)A&(="`L::`?(A&*)A-')A-B)A/4",!$">!$!O +M!&FQF<&"83HALP)]#4"M!*GAD'Z3@-Z370]@4I/BDPWB81^@\I-2842A>@!2 +MDPE2826@AR"@32#@(2%0D2&282@B81WP:1'P(A%@5)-2 +MDPM2821R84/BDP_B81YR(41082%B82S@@2&"81R@IR#P9A'P*!$@[L!@5<`B +M(4-0])/@>I-R843B(4.A/@!2DPQ282*@(B!002%"81KP9!%@5)A*E!$$.J9ZJKJB.IWBXB+JI"0M$"9$:"@M("`M%`S$'!PM$!W$5!=$$"( +M$4"J$:!$((`S()!5('#_()T+XB%"@!@:R""(2+6*`#&R@/"(1J`LB'PNQ&W'`7!/@#`9B"R(2*2 +M(1\;B[#"(8""(;",LQNYD,(AL+(AD+RSD:X"PB$ID&80RKN2(1M+N["PM$"[ +M$;!F()J(@("T\&80L;0"@&8@B+&2(1Z`>Y.]!\T'UBD`AL$#@B$<@F$) +M<'(A\'<1DB$)=QD%L7H`L+P@PB$AUBP`AJL#8`L8O +M`Y%(`%)A&)>8`L:'`X&0`(="`L:!`4%Z`,)A-W)A-K)A12)A/;(A&"(A+W*3 +M"W)A),`B$7#!(?",$<)A+(!WP(&S`BK,P)`$D+B3P,&T0,P1@I,)0&L@<+:3 +M@F$E)A)O"($"HN(""T@*(@@I,-(B$]@F$?@.$A +MXF$=T.T@%V@%X7H`X.T@TI,,(F$]T($ATF$B\"@1(-W`(3X`("X@T.*3TB$? +M(B$IT-(ATF$7*MTAK@+0T+1`W1$@+A#0(B#2(2V"81KP(A#:V$"/!-#0M"#M +M($(A&"&S`HFQ@$*3@I,/(B$]@F$>@-$ATF$@#0U""(,4(A*")A +M/8"`!!LD("$$0"BS@I,.07H`/0N0/)-`0R`@-)."82&`02'P)!$@B,`A/@`@ +M+2"`TI."(1XB(2F`@B&"818JB"&N`H"`M$"($2`M$(`B(((A+4)A&?`B$(J$ +M@("T(-@@(B$]UB8`AOP#8$(A@B$GB0'P1!&2(0!'&06!/@"`,R!"(2U@@B$B +M83T;EI"2(2(A)6"8LX(A*$!!(4)A&TJ9(",A&TA`0B&`0K."(2J0D+2`@D&" +M816*1(&N`D!`M$!$$8`S$$`S(((A+$(A%/`S$)`S(!LH0$`$("$$F.&`)+.! +MM`)P1R"02).1>@""(2.0E"`@29,B(3W6*`!&VP-B(2."(2:)$6!B(?!F$9(A +M`6<9!8$^`(!$()(A(S)A/B)A/3(A%QN)D&(A@((AD(:S8B$=*,$P,`0;EI"1 +M!&"3LS%Z`""\DR(A)#`[()"SDS(A+"`C(1N3D)(A,)*S,:X"(B$5;0LP1!`J +MF3(A/I"0M"(A&T"9$9!$()(A(BJ(\$00(B$]@("T@$0@UBD`!KL#PB$:D+(A +M\+L1MQP%P3X`P&8@DB$BLB$6&XF0PB&`@B&0C+/"(1RPL`0;G)"1!,";L[T' +MP;0">+%PO)-Q>@#"(1]P>R"0MY-R(1W`PR$;EY"2(7"GB2(2%P<+1P9B#6*0"&G@-R(1F0PB'PS!''%P6! +M/@"`NR""(2&2(1XB83T;R(`B(<#"(8#"LR(A')"3(1N"@((A((FS(:X"DB$5 +M(+L0FH@B(1N`@+1`B!&`NR#PNQ`JS,#`M"(A/<"[(`R,AL7Z#`T,#@P*#`4, +M#`P+#`8,!`P#1L#Z``!R839`7`0B83V"DPF"824B(2]0WI/`>A%0O).YH7)A +M+5%Z`(!A(<`B$6)A*")A*BHF4%T@\&81(""T8&C`8-638I,(0"(143X`8*$A +MHF$G>GI072#PJA&@IL"@U9-1K@)P<+2M"U!=$"!5("(A/?!5$'!5(-8H`$83 +M`[(A)3(A*+"R(?"[$;<3![%Z`*BAL*H@UB8`1A`#,B$G8+(A\+L1MQ,%P3X` +MP*H@8((AXB$E&[:PLB$;SN#2(<#"(>#-L](A+>&N`F"XL]#1(>"J$-J[TB$J +M#`ZPL+30T4':S,#`M`P-0,P1P*H@#"SPJA"PJB"&A_L`P;,"4;0"(F$]LB$O +MP(H1TI,*DI,+DF$DTF$C@F$MP+L1T.$AXF$FLF$JD"$ABHZ`@+0B82RZLO#N +M$?`B$>#=P+"PM$#M!.!UDU(A&$"[$2`IP.!@!BDPV0@2&"82AB81_P^!'P^@#0 +MVR""(2+6*`"&:0+"(1J`LB'PNQ&W'`7!/@#`W2"R(2*"(1\,3+"2(8!B(1M( +M&SLP,B%`0B&`1K.P.;-B(1L,"X&N`FHS8B$I@-T0,#"T:D0,!DM$0$"T0$01 +M0-T@\-T0#`0PW2`,`\;'^1M(0'$A0$(A\$01!E'[````8F%)0+T$\;,"4B$8 +M(F$]P*H1@I,+@F$DHF$M0"\$*;'-!8"1(9)A+"#/D_#I$;!?D^#HP/%Z`"*3 +M#R)A'O#5(.!=D_#\("#1(=)A'/!M$6`BP"#/DV*3#B$^`&)A(6#Q(2`L(/#O +M$>!FP&#"DR*3"O)A&2)A(R!A(6)A)O#F$>`BP*IFX3X`JJ]@8+3QK`+@Y2`@ +M7I/B(2^@H+0B(3W`[A'B82KJF>K=B]V0D+1`F1'AK@+0T+1`W1'@51#@S!#0 +MS""052#1K`*1M`+M!]#,$-!5$&!5(,"J(+#ID^G1UB@`ABD"LB$D8B$LL+(A +M\+L1MQ8'@7H`Z-&`[B"2(2/6*0#&)0+"(2:0LB'PNQ&W'`7!/@#`[B"XL=(A +M(Y&T`AN-L'F3@((AT+(AT(NSTB$D&YW0LB&0DB'0F[.R(2K1K@+-!["Q0=#N +M$+J9D)"T0)D1D.X@DB$MW0?P[A"0D2&:B("`M(#N(((A'K)A*9)A&]8H`,88 +M`C(A'("R(?"[$;<3!=%Z`-#<(((A(=8H`(8&`G(A&8"R(?"[$;<7!<$^`,#= +M(+(A(8(A'@Q,L)(A@&(A&T@;.S`R(4!"(8!&L[`YLV(A&PP+@:X":C-B(2F` +MW1`P,+1J1`P&2T1`0+1`1!%`W2#PW1`,!##=(`P#QD?Y&VA@@2&)\6!B(?!F +M$<;P^L(A%1N(@)$ADF$0@((A\(@1@F$11@W[`!N9D($A@F$2D)(A\)D1DF$3 +M!BK[#`L,!@P$#`,,#0P.#`H,!0P,AC/YPJ(`LJ,`L+00QQL"!I+Y5^0"AI#Y +MT"(@!H_YLB$EF>$;N[`Q(;"R(?"[$89U^P`;MK`Q(;"R(?"[$49X^QLX,,$A +M,#(A\#,11I;[&TA`82%`0B'P1!$&C/L``)(A+\"*$7*3"7)A)8)A+7!1(<"9 +M$9!!05)A*$)A*4%Z`)J5D&`$\%41D)&T4%?`8-Z30$T@8I,(4-2303X`8%$A +M4F$GBH7P51%`32!05L!0U)-1K@)`F1&`@+1071"052#P51"`52"6UW$R(2BM +M"^(A*7#2(?"]$>K=T-`$T*R3MQ,%X7H`X*H@EG9Q,B$G8+(A\+L1MQ,'P3X` +M/?#`JB!@@B'B(24;MK"R(1O.X-(AP,(AX,VSTB$MX:X"8+BST-$AX*H0VKO2 +M(2D,#K"PM-K,P,&T#`U`S!'`JB`,+/"J$+"J(,8?_@"9H1M(0($AB4%`0B'P +M1!&&[?L;1D"!(8E10$(A\$01AO'[&VE@@2&)<6!B(?!F$484_!NXL,$AL+(A +M\+L1AC/\&\S`<2'`PB'PS!'&4OP``&(A)!MF8($AB6%@8B'P9A&&_OL`&\C` +M@2&)@<#"(?#,$48?_!MY<($AB9%P9.M![<6!=%Z`-"J(.(A +M(Y:.7,(A)N"R(?"[$;<#2(1NY&\[`PB&PLB'@ +MS;/2(2WAK@*0N+/0T2'@JA#:N](A*0P.L+"TVLS`P;0,#4#,$<"J(`PL\*H0 +ML*H@QL#]``!`G`1M#8*3"8)A)9!NDX!1(5)A*&!6(!=H!5%Z`%!6(')A-H(A +M+R)A/9)A2T!N!)$^`&#>DVG!P"H1(F$M8I,(P(@1@F$JD)4@@(%!8*$AHF$G +M*BJ"82GPJA&@IL"@69.AK@*2(24@(+2@I1"0DB&9,8IY<'"T@I,-@F$?0'<1 +M<*H@\*H0(%H@@)$AK0V281TB(3V2(4L7:`6A>@"@K2#2(2CH,1N-X.`$@($$ +MT(ZST7H`[0N0[)/0WB"`[9."DPR`T2&"82+PG1&0B,"1/@"0FB"`J9."(1^2 +M(2F`@B&"81>:B)&N`H"`M$"($9":$("9(((A+=)A&O"9$(J-@("TD*@@EB9' +M,B$G8-(A\-T1UQ,%@3X`@.X@DB$M&X9@TB&`@B%@C;/2(260D2&281N:B)(A +M*")A/=#3(1LI("(AD"VSTB$7DB$J@("TT-`$D))!DF$5FB*1K@(@(+1`(A&0 +M[A`@[B`B(1WP[A"8P8#N(!N"@($$((VS(7H`D+R3DB$B("L@@+*3W0LB(3V6 +M>3_"(1J0LB'PNQ&W'`7!/@#`W2`,3+(A(F(A'X(A';"2(6!C(1M(&SLP,B%` +M0B&`1K.P.;-B(1L,"X&N`FHS8B$5@-T0,#"T:D0,!D!`M$!$$4#=(/#=$`P$ +M,-T@#`/&!_C!LP*2(1A`W02"DPN"8239X8"Q(;)A+-"K=T-&TDF$<0-T1 +MT*H@\*H0L%H@0*0@%V@%H7H`H*0@P7H`N.&!M`+M!Y*3#I)A(;#HDX(A)+(A +M+,#.((""!!O;T-$$L-BST.R3@3X`T:X"D,$A\+P1L)G`@(H@D*B3DB$J@B$< +MPF$9T-H0FHB`@;1`B!&`W2""(2VR(2/PW1"*S,#`M-"L()9[*L(A)K"R(?"[ +M$;<\.X0D)$ADF$; +MFHB`@+2`[B"1>@""(1S`P@20ER`;N+"Q!("\LX(A(;!YD]T'EL@B)/=!P9C^QNXL#$AL+(A\+L1 +MAN7]&T9`@2&)`4!"(?!$$<8!_!MH8($AB1%@8B'P9A'&(_P;N;#!(;"R(?"[ +M$49#_!O)P'$AP,(A\,P1QE_\@B$IK0L;-S"R(8J+,#$A\+L1@(`$@*R3!C?^ +M`!NVL#$AL+(A\+L1ACC^&VF!M`*2(2E@LB%@82&:F_"[$9"0!)!XDZT'QHG^ +M&[ZPP2&PLB'PNQ%&C/X;UM`Q(=#2(?#=$<;A_ANYL,$AL+(A\+L1A@#_&[NP +MP2&PLB'PNQ&&5/\;N+!Q(;"R(?"[$49S_P``-F$`HJ`!I5/+94_6@4\`H4X` +M#`^13P#R:H#R:L#Y"9$W`/)H0+(IK+#`!`=K$GSNX.L0XFFLP"``TBFLV0'` +M(`!V@!#B*>?I$=@1T-`4V1&($28X`@;Z_X$Y`!P.(B@@#$W`(`#0(B`B:"#` +M(`#2*"#`(`#R:I[`(`#@W2#2:"#`(`#B*"!L\B#N$.)H("(H('R]T"(0(F@@ +MG+SQ/@"R::S`(`""*:R)`<`@`.(J@O#N(.)J@AWP`+$^`)(J@K"9())J@AWP +M```V00"BH`$E1\NRH;2ZLJ(KI`PHDB+'&ZJB:Z2)":7Q_QWP```V00"RH0`, +M''S]H0#2(\=9#27B_^4QU@SO@M<$#`61S`"ARP"B9X"29\!9"/)D0.(C/VD! +MZ2%G/@+&/P#X(>@!;04I4?#NP.D1J"&R(S:Y0:JFJ3&E'@`M"J)C0[A!J#$E +M(0`,&Z)C0@PY_04C_P"C_PB3_Q[R9\GB(T/2(RW-!>/\"F8]%)/\%%/\&MT, +ML_TU%E!$ +MP``40``SH3WP=I0(-S(","+`,#%!-S(","+`'?`,`AWP```V00"V(SEM`E#R +M0$#S0$>U)%!$P``40``SH2*@`':4#3)BA)=VLK#!W210>2`U*B(Q&R!";" +M(V+"8V"R1!ZR!!ZB8V*21"9W:Q`,,AOJXF,1'?"M`B7\\,;R_ZT"#`RE^_#B +M(Q$,,AONXF,1'?!W:Q@@HB"R`U+"H`#E^?#R(Q$,,AO_\F,1'?``K0(,#*7X +M\`;W_P`,''SXL@-2LD0F@D0>HF-BK0(E]_"2(Q$,,AN9DF,1'?`````V00"R +MT@*R"T1W:P$=\*T"#`SE]/`=\````````%<#8`!7`V``5P-@`%<#8`````#_ +M____`````/____\`````_____P````#_____`````/____\`````_____P`` +M``#_____`````/____\`````_____P````#_____`````/____\`````____ +M_P````#_____`````/____\`````_____P````#_____`````/____\````` +M_____P````#_____`````/____\`````_____P````#_____`````/____\` +M````_____P````#_____`````/____\`````_____P````#_____`````/__ +M__\`````_____P````#_____`````/____\````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +;``````````````````````````!7`P`(-P`! +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TURKS_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TURKS_mc.bin.uu new file mode 100644 index 00000000000..8ea23315a8a --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TURKS_mc.bin.uu @@ -0,0 +1,539 @@ +begin 644 TURKS_mc.bin +M``/HX``"O@$```(4``/_```#_P```J`.``'`'0`#Z````^@0``/H(``#Z#`` +M`V`8``-@'``#8"```V`H``*P_P`"L?\``K+_``*S_P`#83@``TEL``/_```# +MKPH``K0$``)O]```^CL``K0/``)/%```^A<``T`D``*T0``"M0\``TJF``)$ +M00`#\`(``DF5``-JI@`"+:@``TG4```R0P``(A@``#H5``*U$```FD,``D53 +M``/P"``"H'X``_!&``*@8P`#\$0``/(/``(TOP`#]````<`E``/H````@@\` +M`T`D``*T0``"M?```TJF``)$00`#\`(``FF5``-JI@`#0````_\```/X`0`# +MQ$```\11``+&10`"`````T`0``/_```#_P```^@@``/H,``#8!```_@#``(S +M;``",J@``T@(``*TGP`"0`0``V@(``-((0`"L\$``D=S``-H(0`#:HD``T@E +M``*SP0`"1W,``V@E``-JC0`#2,```TC&``"",0``BC```,(O``#*+@`#Z!`` +M`^B0``-HP``#:,8``TJD``/H0``#_P```D(D``-JI``#2````T@%``*[/P`" +MO+\``K_O``"2,P``BC0``((X``"Z-@``JCH``D$;``*[^P`"0BL``D`,``-H +M```"15\``V@%``-($``#2=T``KOQ``*\`@``BC<``*HY``)!&P`"81P``V@0 +M``)%6P`"95P``VG=``-`#0`#_P```_\```.A3```B@T``K,"``)#-``#HS`` +M`)H,``*S!``"0S0``Z,R``":"P`"L`@``()!``*P"0``@D(``T@I``-)<``" +MOP<``D`/``.````#``X``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H +M+0`#P00``\$5``-IZ``#:>P``^@```/HT``",$\``VCD``/!W@`",$\``VD$ +M``-`+``#_P```K0"``)$!```HA8``TG6``*U$``"1%L``Z1&``"B&``"H$X` +M`_`#``(T:@`#]````<#%``/T```!TW(``T`.``#R0``#Z/```Z"V``-)U0`` +M^A$``K$/``)"%P`"I2```_`!``#Z0``"0QL``J4C``/P`0``\A$``T````-` +M+@`"MA```K0,```J0``"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`! +M``/HP```XA```T`(``*T````>A$``J`D``/P00`"L@@``J#^``/P00`"L@0` +M`K0_``)")```DB@``TJ4``/_```#8&P``T````/_```"M$```D0$``/P`P`# +MZ````((_``(B^@`#0````_\```*T0``"1!0``_`"``#R/P`"(OH``T````/_ +M```"M$```D04``/P`0`"+FX``TJ4``/_```#8'```T````/_```"M`(``D0D +M``/P`P`#Z````((_``(C,0`#0````_\```*T`@`"1#0``_`"``#R/P`"(S$` +M`TJ4``/_```#830``C-L``-````#_P```_\```)$#@`#\`,``^@```""/P`" +M)%H``C-L``-````#_P```_\```)$'@`#\`(``/(_``(D6@`"+JD``TJ4``/_ +M```#8'0``K````""*P`#0````_\```*T`@`"1$```_`#``/H````@C\``B89 +M``-*E``#_P```V!X``-````#_P```K0$``)$0``#\`,``^@```""/P`"*)P` +M`TJ4``/_```#8'P``T````/_```"M!```D1```/P#``#Z````((_``(I;``` +M`@T``_\```/_```"I`X``_`$``#R#@`"*6P``^@```""#@`#2I0``_\```-@ +MK``#0````_\```*T(``"1$```_`#``/H````@C\``BN$``-*E``#_P```V"P +M``/H````@C\``K#_``*Q_P`#P2```VA@``-H:``#0````_\```*T$``"1$`` +M`_!"``/T```"`8\``T`-``-`)@`"L4```K(0``*S"``"010``Z$:``)")``# +MHB0``F(A``)#.``#HS```F(C``"2*P`"I!X``_`)``-)/0`"LH```\`B``)$ +M0@`"*6P``TD]``/_```"LH```F1"```"$``#_P```K0!``)$!``#\`0``^@` +M``""/P`#P?X``BQ&```"$``#_P```K0"``)$!``#\`0``^@```""/P`#Z/`` +M`BQ&``-````#_P```_\```)$+@`#\`,``^@```""/P`"-7<``T````/_```" +MM!```D0D``/P`P`#Z````((_``(VJ0`#^`,``TJ4``/_```#8+0``K````"" +M*P`#0````_\```*T`@`"1$$``_`"``#R/P`")AD``TJ4``/_```#8+@``T`` +M``/_```"M`0``D1!``/P`@``\C\``BB<``-*E``#_P```V"\``-````#_P`` +M`K00``)$00`#\`L``/(_``(I;````@T``_\```/_```"I`X``_`$``#R#@`" +M*6P``^@```""#@`#2I0``_\```-@[``#0````_\```*T(``"1$$``_`"``#R +M/P`"*X0``TJ4``/_```#8/```/(_``*P_P`"L?\``\$@``-H8``#:&@``T`` +M``/_```"M!```D1!``/P0@`#]````@(.``-`#0`#0"8``K%```*R$``"LP@` +M`D$4``.A&@`"0B0``Z(D``)B(0`"0S@``Z,P``)B(P``DBL``J0>``/P"0`# +M23T``K*```/`(@`"1$(``BEL``-)/0`#_P```K*```)D0@```A```_\```*T +M!``"1`0``_`#``#R/P`#P?X``BQ&```"$``#_P```K0(``)$!``#\`,``/(_ +M``/H\``"+$8``T````/_```#_P```D0^``/P`@``\C\``C5W``-````#_P`` +M`K00``)$-``#\`(``/(_``(VJ0`#2I0``_\```-@]``#^`,```(8``/_```# +M_P```J`.``/P0@`#]````@)L``-`+``#_P```K0@``)`0``"H`0``_!(``/H +M````@C\``C((``(R30``\C\``C((``(R30`",N0``T````/_```"M`@``D0$ +M``/P#``#2`@``_\```*T0``"8`0``V@(``-)F``"M/T``D$4``-IF``#Z#`` +M`\$N``-H,``",O@``^@```/H$``#Z#```K(#``-H,``#0````_\```*U"``" +M114``_`!``(TUP`#2I0``_\```-@^````D```_\```/_```"H0X``_`"``/H +M````@A0``BZI``-(```#2`4```HT```".```$C,``"HZ```Z-@`#_P```V@` +M``-H!0`#2!```TG=```*-P``*CD``_\```-H$``#:=T``TEQ``*R`0`#Z#`` +M`\$&``/!%P`#:#```TEL``*U%@`"H%$``<*?``*PSP`"L04``K(!``*S```# +M:#```C+X``*PM``#:#```C+X``*PO``#:#```C+X``*PN``#:#```C+X``*P +MRP`#:#```C+X``*PC``#:#```C+X``*PT0`#:#```C+X``/H```#Z!```K(# +M``*S```#:#````(8``/_```#_P```J`.``/P0@`#]````<`````!]``#0!(` +M`T`5```*&P`"H`X``_`"``/T```!PL\``L$>``"*&P`":[H``F5;``+&;@`# +M\$$``L=^``-@%0`"L@\``D1"``*E%``#\`<``^B@``/HL``#8!(``^@```"! +M]``#]````P`#P?```BY[``/!\``"+GL``T`@``/_```# +M_P```L`.``/P10`"P1X``_!#``+"+@`#\$$``L,^``-@(``",VP``TE(``*T +M/P`"M8```D,T``)C-0`#:4@``D,T``-I2``#]````<````-`!```:C\``^B` +M``/HD``#Z*```^BP``*U$``"1!4``_`&``*@W@`#\`,``V2J``/T```#\$$` +M`V3J``/X`0`"M0@``D0%``(#'```8?@``J#>``/P`P`#Z$```_0```/P00`# +MA.H``]A```/?<``_@#``/4G@`#^P```P_^``(#&``#^`$``X7D``)$ +M%0`"`R\``"'Y``*@W@`#\`,``&'Q``/T```#\$$``&'P``*_"``#W$```]C` +M``/X`P`#U)X``_L```,/_@`"`RL``_@#``/L`````A0```I```!J/P`#_P`` +M`D`!``*@#@`#\`$``^P```-).``"H-X``_!!``-*7``"N/X``D(H``*@W@`# +M\`,``VDX``/T```#\$$``VI<``-)T``"M`0``F$4``*R`0`"LQ(``J#>``/P +M00`"LQ$``V@P``-)<0`"N.\``KD$``/!!@`"87D``D,X``-H,``#2`D``KC] +M``)$2``#:`D``BY_``-)H``"M!$``\$D``*Q#P`#::```TI$``*T_@`"81X` +M`VI$``)!%``#:D0``J#>``/P`P`#0F$``_0```/P00`#0ET``_\```/_```# +MZ&```VFE``-H:P`"N@P``KC```/<@0`#V*$``K#X``*Q!P`#Z"```^@P``/^ +M```#U!\``VAK``/H\``"(_\``B/B``(D'``"H?X``_!!``-B>@`#0G@``_\` +M``/_```"H(```<.3``*@D0`!PY,``J"B``'#DP`"H+,``<.3``+/_@`"O`P` +M`J'\``/P0@`#]````<-]``#Z!``#Z/```B/B``(C_P`")!P``T)X``/_```# +M_P```J"```'#J0`"H)$``<.I``*@H@`!PZD``J"S``'#J0`"S_X``KP,``*A +M_``#\$(``_0```'#E@``8@0``/H#``/_```"I<\``<.Y``*E_``!P[0``^CP +M``/HP``#]````<.\``,,SP`#K,```^CP``/T```!P[P``P_\``.O\``#Z,`` +M`B/_``/!_``"(^(``TDX``*@W@`#\$$``TI<``/_```"8BX``J#>``/P`P`# +M:3@``_0```/P00`#:EP``TG0``*T^P`"010``K(!``*S$@`"H-X``_!!``*S +M$0`#:#```TEQ``*X[P`"N?L``\$&``)!>0`"0S@``V@P``-("0`"N/T``D1( +M``-H"0`"L!@``B1```/L```#1+D``J#>``/P00`#1/D``\$/``/!'P`#P2\` +M`\$_``/!3P`#P5\``J#>``/P!0`#9+```V2T``-DN0`#]````_!#``-D\``# +M9/0``V3Y``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P```-$ +MN0`"H-X``_!!``-$^0`#P0\``\$?``/!+P`#P3\``\%O``/!?P`"H-X``_`% +M``-DK``#9+P``V2Y``/T```#\$,``V3L``-D_``#9/D``TC(``*T\P`"M00` +M`D`$``)@!0`#:,@``D`$``-HR``#[````K`0``(D0``",O@``C+X``(R^``" +M,O@``C+X``-*'``")$P``\&,``-*(``")$P``XS&``)HC``#2B0``B1,``/! +MG``#2B@``B1,``.,Q@`":9P``THL``(D3``#P:P``THP``(D3``#C,8``FJL +M``-*-``")$P``\&\``-*.``")$P``XS&``)KO``#[````VAK``*Y"``"N,`` +M`]R```/8D``#Z!```^@@``/H,``#_@```]0>``-H:P`#[````^C```.'/``# +MIW8``X8L``.F:``#A1P``Z5:``.$#``#I$P``FS'``)LQ@`";,4``FS$``/L +M````(@\``T`D``/_```"1$X``Z`&``*A#@`#\`$``(('``-)I``#2:$``&H_ +M``.+Z@`#P*L``D6E``*@W@`#\`,``D.C``/T```#\$$``F.S``-II``#::$` +M`K+_``*Q_P`"L'\``VA@``/H```#Z"```^@P``*@W@`#\`,```H)``/T```# +M\$$```H(``*XP``#:&L``]@```/<@``#U!X``K\"``(N>P`#@.```(($``"" +M`P`#Z````(("``""`0``\@```TA4``*@W@`#\`,``X3H``/T```#\$$``X3J +M``)B)``#:%0``TF8``.(Y0`#P3X``J#>``/P`0`#@S```\$N``)@"``#:#`` +M`TEU``.(Y@`"8&@``\$7``/!+@`#P3X``J#>``/P`0`#@S```V@P``-(5``" +MH-X``_`#``.$Z``#]````_!!``.$Z@`#P$0``D(D``-H5``"OP(``BY[```" +M&``#_P```_\```*@#@`#\`(``_0```($UP`",&$``^AP``.$Y@`"1DL``J!D +M``/P3P`#2=(``^A@``.*L@`#JJH``X2F``)D2@`#P50``J#>``/P`P`#:.4` +M`_0```/P00`#:04``_0```'%@@`"OP@``D_Y``.O]``#B[(``ZN\``(EI@`# +M]````@6"``-`#``#_P```K\(``)/\``#\$(``_0```'$]``"OP```KL!``(E +MI@```A$``_\```/_```"H`X``_!"``/T```!Q8(``K$"``*P$0`"Q$```L50 +M``*@W@`#\`,``VCE``/T```#\$$``VD%``,!'@`"!.D``/("``#R`0`"H-X` +M`_`#``!Z!@`#]````_!!``!Z!0`#C>(``]S0``/8\``#B>8``FF>``#Q\@`` +M0@<``^C0``./X``#P:@``XSM``#A]@``XCX``B_*``*W`0``0@<``^B@``#1 +M\@`"H'X``_`!``.H@``##]\``\'9``/!J``#C.T``.'V``#B/@`"+\H``C`+ +M``/!!``#P28``V)P``*_`0`#0!$``XC@``*@_@`#\`0``D1(``/P`@`#]``` +M`@5H``*W`0``0@<``_\```*@?@`#\`$``ZB```/HT``#C^```\&H``.,[0`` +MX?8``.(^``(OR@`",`L``T)P``.,ZP`#C.H``^CP``+(0``#J(```"H6``+* +M8@`#JJ```J9>``(%10``:C\``/(6``/!6``#P7H``V)Q``/T```"!/\``J%> +M``/P#@``:C\``\&1``/!LP`"H-X``_`#``-A+@`#]````_!!``-A,@`"P($` +M`Z@```+"HP`#JB```X50``"J%@`#@>```P"$``/P)``"H80``_`!``+$00`# +M!$X``\%4``,"I@`#\"0``J&F``/P`0`"QF$``P9N``/!=@`#U%X``F`"``(% +M5P``:C\``K\"``(N>P`#27$``X'D``/!!@`#HFP``J`N``(%@@`"87$``\$N +M``/!/@`"H-X``_`!``.#,``#AF```_!'``-H,``#C^T``BY[``./[0`"+GL` +M`X_M``(N>P`#C^T``BY[``-)=0`#P2X``\$&``/!%P`#P3X``J#>``/P`0`# +M@S```V@P``-)F``#_P```\$^``*@W@`#\`$``X,P``/!+@`#:#````H/```! +M]``#_P```D$>``/P`0`#[````J4.``/P2``#0!$``J#>``/P`P`"9FX``_0` +M``/P00`"9WX``V`1``/H````@?0``^P```(R^``#2D```$(```!*!```4@,` +M`KPS``)$#``"11P``F1%``)&+``"1SP``F9G``)D1@`"H4X``_`!``*T`0`" +MH(X``_`%``*D20`#\$,``J1+``/P00``\@(``*($``*\S``"1`P``D4<``)& +M+``"1SP``F1%``)D1@`"9$<``J%.``/P`0`"M`$``J".``/P!0`"I$H``_!# +M``*D2P`#\$$``/(!``"B`P`#Z$```*(```-#*0`"H-X``_!!``-#:0```@(` +M`!(!``*Q#P`"LP<``J7^``(%_``"H`X``_`&``*\#P`"I$$``_`!``*\"0`# +MP4P``\%<``*@+@`#\`8``KP/``*D80`#\`$``KP)``/!;``#P7P``J#>``/P +M`P`#8RD``_0```/P00`#8VD``DP"``*@S@`#\`8``L_^``*\"0`"I?P``_`" +M``/T```!Q:8``TCE``*@W@`#\$$``TD%``*X$0`"H`X``_`!``+$2``"24$` +M`J23``/P`0``\@(``J`N``/P`0`"Q5@``DE1``*DDP`#\`$``/(!``*@W@`# +M\`,``VCE``/T```#\$$``VD%``)``@`"H`X``@6F``/L````:C\``^@```(P +M.P`#29@``K@/``*U]0`"LP$``J#>``/P`0`#@S```\$N``)@"``"014``V@P +M``*_```"+GL``/'_``/H````@?X``T`,``-`+0`"N!```KD(``)*&``#JJ8` +M`DM)``.KM``"LP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*$0`" +ML$```D!```/P00`#Z#```D$>``/P`0`#Z#```)G]``(N?P`"O`$``J#>``/P +M"0`#2"$``XS&``.&9@`#IF8``F9L``-H(0`#:HD``_0```/P1P`#2"4``XS& +M``.&9@`#IF8``F9L``-H)0`#:HT``K`!``/H$``#Z"```^@P``-J8``"OP,` +M`C'5``-("``#A.H``('U``)@!``#:`@``K]D``(N>P``:C\``_\```/_```" +MH-X``_`#``*[```#]````_!!``*[0```V>\``\$.``/!'@`#@18``F$>``." +MY@`#:D0``\$>``.!%@`#Z"```VI$``/H```#P````\$0``*R_0`#:&```TI@ +M``*_]P`"L1,``D`/``)@#@`#:F```#(,```Z"P`"O`@``K_^``.&:@`"8B8` +M`J1^``/P`0`"LP0``D`/``)@#``#:F```X_A``(N>P`#:&L``_\```/^```` +M8CT``%H\``/_```#V,$``]RQ``./XP`"+GL``]`?``.,[P`#C^0``F_^``)` +M`0`"0B,``D`"``),P``#^P$``]`?``,/_@`"!J(``J#>``/P`P`#2"$``_0` +M``/P00`#2"4``\#,``(&S@`#C.8``L9L``/P00`"QWX``J#>``/P!``#:"$` +M`VJ)``/T```#\$(``V@E``-JC0`"I7X``_`"``/T```!QG$``T`1``*P"``` +M\?0``J#>``/P`P`"9F```_0```/P00`"9W```V`1``/T```""(,``X#A``.! +M!@`"81X``X+G``-J1``#@08``^@@``-J1``"L`$``^@0``/H(``#Z#```VI@ +M``-`+```6BL``K0$``/H\``"1$```_`!``*_`0`"I+X``_`!``*_!``",=4` +M`/(G``#R)0`"L/\``K&_``/!(``#:&```K`!``/H$``#Z"```^@P``-J8``` +M"CL``!(,```:"P`"L`(``J#>``/P00`"L`0``X(J``*D/@`#\`$``K,$``.! +M%@`"8`$``K$S``-J8``#0`H``K`!``*Q`@`"L@```K,!``*@*P`#\`(``^@@ +M``/!.P`#:F@``\$.```20@`"0`D``_`!``/H(``"L!,``K$"``.")@`#Z#`` +M`VIP``-`+0``8A$``!(H``*_0``"3T\``_`#``*@S@`#\`$``K((``*P(0`" +ML0(``K,!``-J=```"BL``K`!``/_```"I!X``_`%``*Q!``"L@```K,"``/T +M!``#\`,``K$"``*R#P`"LP$``VIX``-*?``#_P```K`!``*Q`@`"LP0``VI\ +M```!_@`#_P```_\```+`#@``@?X``C'0```")P`#0`H``T`-``*@#@`#\`4` +M`K`!``)`!0`#@`8``_0$``/P`P`"L`0``D`)``.``@`"L0,``F@!```"*P`# +M_P```_\```*D#@`#\`L``!(H``*P(P`"L0,``K,!``-J=``#2GP``_\```*P +M`0`"L00``K,$``-J?``#2F0``K2````1[P`"0`0``F`(``.B(@`"LP$``VID +M``(PE0`",*(```'_``/_```#_P```J`.``/P3@`#0"P``KP$``/``/P`0`#Z/```]CP``*\"0`"OS\``DL?``(O"P`#Z/```/G_```!_@`# +M_P```_\```+`#@``@?X``T`E```:$``"L@0``D(@``*@W@`#\$$``Z,R``*Y +M`@`"29,``F(I``*Y@``"294``F(I``*YA@`#Z(```J`I``/P00`#P8X``,': +M```)_0`#0"X``_\```*@`0`"!Z(``K`!``)!"``#\`4```)```/_```#_P`` +M`J`.``('H@`#2G0``'HH``/_```#_P```\$O``-J=``",=````(G``-`"@`# +M0`T``J`.``/P!0`"L`0``D`%``.``@`#]`0``_`"``*P$``"0`D``'G:``*Q +M0P`#_P```J#^``/P00`"L2,``F@!```"*P`#_P```_\```*@#@`"!]0``!(H +M``*P0P`"L00``K,!``-J=``#2GP``_\```*P`0`"L04``K,$``-J?``#2F0` +M`K2````1[P`"0`0``F`(``*X(``"8`@``KB_``)`"``#HB(``\$^``-J9``# +M]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``/!/@`#:F0``C"5``(P +MH@``0A```K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```'']0`#0`X``K`0 +M``/_```"00D``J`0``(']0```B<``_\```/_```"P`X``((G``*Q`@`"I`$` +M`@``/P1@`#Z/```K$D``+(@0`#V(```L`!``/8 +M@0`",(P```'^``/_```#_P```L`.``"!_@``>=H``C'0``*@_@`#\$4``K`/ +M``/!$``#P2```\$P``-J@``#0`H``K!```/_```"0`D``Z`"``*Q`P`":`$` +M``(K``/_```#_P```J0.``/P"P``$B@``K!#``*Q!0`"LP$``VIT``-*?``# +M_P```K`!``*Q!@`"LP0``VI\``-*9``"M(```!'O``)`!``"8`@``Z(B``*S +M`0`#:F0``C"5``(PH@`#0"4``$(0``*P(``"0`4``_!(``*P`@`"H-X``_!! +M``.``@`"0`@``_`"``/T```!R&4``!'^``*P@``"LP,``J`C``/P0P`"0`4` +M`_`!``(QE@`#0"X``_\```*P"``"00@``J`0``((90`"L(```D$(``/P!0`` +M`D```_\```/_```"H`X``@AE```")0`#_P```_\```/H$```BB4``J0.``(' +M=P```>\``$'Y``/_```#_P```]@```/<@```>D(``K````/8`0`"L`$``]P! +M``-`#0`"O2```_\```)-U0`"IMX``_`#``(O*P`#]`0``_`*``*P?P`"L?\` +M`K+_``-H8``#:&L``!'E``*SP``#Z-```V!,``(O9@`"L`$``^@0``/H(``# +MZ#```VI@``-*9``"M(```D`$``-J9```(?4``_\```-("``#_P```\$$``-H +M"``#[````^@```/H$``"H-X``_`#``-I'``#]`0``_`!``-I-``#[````&H_ +M``/_```#_P```J#>``/P`P`"NV(``_0```/P00`"NV@``_\```/_````V?P` +M`C*.``/H```",#L``KL"``#:/@`#2`$``K"_``)$0``#:`$``TF8``*T#P`" +MM?T``F`$``)!%0`#P2X``\$^``*@W@`#\`$``X,P``-H,``#2`@``K1```"! +M]0`"8`0``V@(``/H```"L6```^@@``/H,``#::```^@```*Q$``#Z"```^@P +M``-J1``"L`$``^@0``/H(``#Z#```VI@``*_`@`",=4``^@```/````#P1`` +M`K+]``-H8```"CL``!(,```:"P`"L`H``J#>``/P00`"L`P``X$6``)@`0`# +M@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+GL``VAK``/_ +M```#_@```C'^``-*8```,@P``#H+``*T]@`"M0,``X9J``)B)@`"I'X``_`! +M``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``#:F@` +M`K"````20@`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`" +ML0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`@`"L0(``K,$``-J?``"L/\``K&_``/!(``#:&```^AP``-*9``"M(```D`$ +M``/H(``#Z#```VID``-*9``"M(```!'\``)`!``"M`,``F`$``*S$``#:F0` +M`C"5``-*9``"M`@``D1```)G=``"I7X``@E<``/H```",#L``J#>``/P`P`# +M2"(``_0```/P00`#2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H +M(@`#:HH``_0```/P0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R2$``T`2 +M``#Q]``"OP0``J#>``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R5P` +M`K`!``/H$``#Z"```^@P``-J8``#2F0``K2```)`!``#:F0``"'U``/_```# +M2`@``_\```/!!``#:`@``^P```!J/P``\?\``^@```""$P`#0`@``T`M``*X +M0``"N0@``DH(``.JJ@`"2TD``ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`! +M``*S!@`#0"T```H1``*P0``"0$```_!!``/H,``"01X``_`!``/H,```FA(` +M`"'T``/H4``#_P```*(9``"I]```:C\``_\```/_```"H-X``_`#``!9\0`# +M]````_!#``!9\``#_P```_\```#9[P`#2````X3J``/`1``#_P```D`$``-H +M```#2`0``\!^``/_```#_P```D,W``-H!``#0"P``%HK``*T!``#Z/```D1` +M``/P`0`"OP$``DN^``*@O@`#\`,``C#]``/T```!R;4``K_+``(S00``\B8` +M`/(E``*P_P`"L;\``\$@``-H8``"L`$``^@0``/H(``#Z#```VI@```*.P`` +M$@P``!H+``*P`@`"H-X``_!!``*P!``#@18``F`!``-`%0`#@BH``K&```)B +M(0`"I#X``_`!``*S!``"MO```D1&``*Q"``"810``VI@``-`"@`"L`$``K$" +M``*R```"LP$``J`K``/P`@`#Z"```\$[``-J:``"L`$``!)!``)`"0`#\`$` +M`^@@``*P$P`"L0(``X(F``/H,``#:G```T`M``!B$0``$B@``K]```)/3P`# +M\`,``J#.``/P`0`"L@@``K`A``*Q`@`"LP$``VIT```**P`"L`$``_\```)! +M$``"I!X``_`%``*Q!``"L@```K,"``/T!``#\`,``K$"``*R#P`"LP$``VIX +M``-*?``#_P```K`!``*Q`@`"LP0``VI\```**P`#_P```_\```)!'@`"I!X` +M`@I4```"$P`#_P```_\```+`#@``@A,``C'0```")@`#0`H``T`-``*@#@`# +M\`4``K`"``)`!0`#@`0``_0$``/P`P`"L`@``D`)``.````"L0,``F@!```" +M*P`#_P```_\```)`#@`"I`X``_`+```2*``"L",``K$#``*S`0`#:G0``TI\ +M``/_```"L`$``K$$``*S!``#:GP``TID``*T@```$>\``D`$``)@"``#HB(` +M`K,!``-J9``",)4``C"B```!_P`#_P```_\```*@#@`#\$X``T`L``*\!``# +MW,```K_```*@W@`#\`$``K^```/8\``#C.0``K\_``)+'P`"+PL``^CP``#Y +M_P```A,``_\```/_```"P`X``((3``!:*P``>B4``K@(``)*O@`"H*X``B@``_\```/_```#P2\``VIT +M``(QT````B8``T`*``-`#0`"H`X``_`%``*P"``"0`4``X````/T!``#\`,` +M`K`@``)`"0`#H````K%#``)H`0```BL``_\```/_```"0`X``J`.``(*O``` +M$B@``K!#``*Q!``"LP$``VIT``-*?``#_P```K`!``*Q!0`"LP0``VI\``-* +M9``"M(```!'O``)`!``"8`@``K@@``)@"``"N+\``D`(``.B(@`"L00``\$^ +M``-J9``#]`0``_`(``-*9``"M(```!'O``)`!``"8`@``Z(B``*S`0`#:F0` +M`C"5``(PH@``6BL``KH!``/_```"2[H``J"Z``/P0@`#]``````/P00`#@`(``D`(``/P`@`#]````\``D`$ +M``)@"``#HB(``K,!``*Q```#:F0``C"5``(PH@``6BL``KH#``*Y`0`#_P`` +M`DBZ``*DB0`!RU<``KD$``/_```"2+H``J"*``'+.0```B4``K((``*S```# +M_P```J0"``'+5P`"H`X``_!#``":)0`#]````D$``K````/8`0`"L`$``]P!``-`#0`"O4```_\` +M``)-U0`"IMX``_`#``(O*P`#]`0``_`*``*P?P`"L?\``K+_``-H8``#:&L` +M`!'E``*SP``#Z-```V!,``(O9@`"L`$``^@0``/H(``#Z#```VI@``(QT``# +M[````&H_``/_```#_P```J#>``/P`P`"NU,``_0```/P00`"NUL``_\```/_ +M````V?P``T`0``*[#P`#2"D``J#>``/P00`#2"T``K\$``)`"P`#JP(``P_[ +M``.,]@`";,\``X_V``-)Z``"HTP``_`$``,$3``#!5\``_0```/P10`#A.8` +M`X56``.E5@`"950``F1.``/!!``#P14``J#>``/P!``#:"D``VGH``/T```# +M\$(``V@M``-I[``#Z````C!/``-(`0`"L+\``D1```-H`0`#Z````K%```/H +M(``#Z#```VI$``*P`0`#Z!```^@@``/H,``#:F```K\"``(QU0``"CL``!(, +M```:"P`"L`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&$``)B(0`"I#X` +M`_`!``*S!``"L1@``VI@``-`"@`"L`$``K$"``*R$@`#Z#```VIH``*P@``` +M$D$``D`(``/P`0`#Z"```K`3``*Q`@`#@B8``^@P``-J<``"L"$``K$"``*R +M`0`"LP$``VIT``*P`0`"L0(``K(/``*S`0`#:G@``TI\``/_```"L`(``K$" +M``*S!``#:GP``^@```/````"L;\``\$@``-H8``#Z'```TID``*T@``"0`0` +M`VID``-*9``"M(```!'\``)`!``"M`,``F`$``*S$``#:F0``C"5``-*9``" +MM`@``D1```)G=``"I7X``@P\``/H```",$\``J#>``/P!``#2"H``TGH``/T +M```#\$(``T@N``-)[``"O!$``K\0``+)GP`"R(P``\$(``/!&0`"H-X``_`$ +M``-H*@`#:>@``_0```/P0@`#:"X``VGL``*[`0``VCX``^AP``.+Y0`#B[8` +M`J6+``/P`@`#]````\``K#_``*QOP`#P2`` +M`VA@``*P`0`#Z!```^@@``/H,``#:F````H[```2#```&@L``K`"``*@W@`# +M\$$``K`$``.!%@`"8`$``X(J``*Q@``"8B$``J0^``/P`0`"LP0``T`5``*Q +M"``"MO```D1&``)A%``#:F```K`!``*Q`@`"L@```K,"``-J:```$?L``K`3 +M``*Q`@`#@B8``^@P``-J<```$B@``K`A``*Q`@`"LP$``VIT``*P`0`"L0(` +M`K(/``*S`0`#:G@``TI\``/_```"L`$``K$"``*S!``#:GP``KP$``/>\``&'[``*[&``#V/```B\+```!V0`#0"4``K\0``+`#@``@=D``D]?``/P +M`P`"+6@``_0```',J0`"OP@``J`.``/P`0`#P?X``C,+``-*@``"H/X``_!! +M``-JA```8>\``K"```/H\``"H<```_!!``/!_@`"+1L``C'0```1[P`#Z!`` +M`K`C``.B(@`"LP$``VID``(PE0``8=D```'O```)^0`#0"8``K(0``/8```# +MW!```'G[``*P```#V`$``K`!``/<`0`"0BD``_!%``.O\``"H,X``_`"``/[ +M```#^P$``]">``/[```"I2X``_`!``/[```#U)\``_L!``*E+@`#\`$``_L! +M``,/_@`"#,L```'9``/_```#_P```L`.``"!V0``8>\``K"```/!_@`"H<`` +M`_!!``/H\``"+1L``C'0```1[P`"L`,``^@0``.B(@`"LP$``VID``(PE0`" +M,*(``T`E```!V0`"L0,``K((``*S$``"0S4``_`"``)")0`#\`(``J4!``', +ME@``8?D``%GO``/_```#W,```]BP``*P```#V`$``K`!``/<`0``>?L``T`- +M``*]0``#_P```DW5``*FW@`#\`,``B\K``/T!``#\`H``K!_``*Q_P`"LO\` +M`VA@``-H:P``$>4``K/```/HT``#8$P``B]F``*P`0`#Z!```^@@``/H,``# +M:F```C'0``/L```"O!$``J#>``/P!``#2,P``TC1``/T```#\$(``TCL``-( +M\0`"+5,``J#>``/P!``#:,P``VC1``/T```#\$(``VCL``-H\0`"H-X``_`$ +M``-(U``#2-D``_0```/P0@`#2/0``TCY``(M4P`"H-X``_`$``-HU``#:-D` +M`_0```/P0@`#:/0``VCY``*@W@`#\`,``TC<``/T```#\$$``TC\``*@_@`# +M\`0``L`,``+!'``#]````_!"``,`#``#`1P``J#>``/P`P`#:-P``_0```/P +M00`#:/P``^P```*@_@`#\`H``L`,``+!'``"PBP``L,\``+$3``"Q5P``L9L +M``+'?``#]````_!(``,`#``#`1P``P(L``,#/``#!$P``P5<``,&;``#!WP` +M`^P```*P?P`"L?\``K+_``-H8``#:&L```GE``/H```#H`,``]P```/8$``# +M0#$``K\#``*\`@`"IOP``_!!``/!!P`"H/P``_!!``/!!@`"H/X``_!!``/! +M!0`"H?X``_!!``/!!``#P1```\$@``/!,``#_@```]0>``-H:P`#^P```P_^ +M``(-=0`#0#4``K\#``/_```"IOP``_!!``/!!P`"H/P``_!!``/!!@`"H/X` +M`_!!``/!!0`"H?X``_!!``/!!``#P1```\$@``/!,``#_@```]0>``-H:P`# +M^P```P_^``(-C0`#0#@``T`]``/_```#:H0``VJ!``/L```#85```V%5``-A +M6@`#85\``TA4``/_```#Z#```Z,S``-H5``#:&L``TA5``/H```#Z'```K+O +M``*Q_P`"L+\``VA@``-H:P`#27P``K0$``)A%``#:7P``TD\``/_```"81X` +M`VD\``-*E``#03D``_\```/_```"IC<``_`'``*F)@`#\`4``J85``/P`P`" +MI00``_`!``-A.``#8/P``_\```/^```#_P```TAD``*T$``"0B0``J`D``/P +M0P`"+A4``_0```'-T``"L/\``K'_``*R_P`"L_\``VJ0``-)/``#P$X``D$4 +M``-I/``#2%0``K4_``)#4P`#:%0``^@```"!]```@AH``((;``-(9``#C.H` +M`/(5``),#``#\$@``T@T``/_```#@`@``Z`,``*@#@`#^`$``@WQ``""%0`# +M^`,``TA5``/H```#AP<``VA5``-)/0`"OQ```D1/``/P!``"O_\``BY[``*_ +M4``"+GL``Z=P``,'?@`"#@<``\`@``/`$``#P````VA@``-H:P`#H!```VA@ +M``-!4``#054``T%:``-!7P`#[````_@#``-)T``"N`@``DDX``*@F``"#F@` +M`TG4``*T$``"0S0``J`T``(.1``#2`@``K@(``)@"``#:`@``T@H``*X(``" +M8S@``T@M``-H*``#:>@``F=X``-H+0`#:>T``TC(``*X^P`"0B@``VC(``-( +MF``"N"```F`(``-(L0`#:)@``F1(``-HL0`#P0X``\$>``/!+@`#P3X``V,P +M``-C<``#8S0``V-T``-C.``#8W@``_0```'.:``#2`@``KCW``)`"``#:`@` +M`T@H``*XWP`"0S@``T@M``-H*``#:>@``D=X``-H+0`#:>T``TC(``*X!``" +M8B@``VC(``-(F``"N-\``D`(``-(L0`#:)@``D1(``-HL0`"L`,``\$0``/! +M(``#P3```V,P``-C<``#8S0``V-T``/!+@`#P3X``V,X``-C>``#27P``K3[ +M``)!%``#:7P``VAK``/L```#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(` +M`VC*``)H(0`#:,H``\&"``-HR@`#[````_@#``,/_@`"#GP``^P```/H```# +MP!```\`@``.@$``#:&```VAK``/!#@`#Z!```^@@``/H,``#I!,``]@0``/< +M0``#_@```]0>``-H:P`#::0``^@```/^```#U!X``VAK``-II``"H-X``_`# +M``-"8``#]````_!!``-"7``#0ED``J#>``-II``#\`,``T)H``/T```#\$$` +M`T)D``-IH0`#_@```]0>``-H:P`#:&L``^P```/H```#P"```\`0``.@$``# +M:&```VAK``-"5@`#P0X``^@0``/H(``#Z#```Z03``/8$``#W$```]0>``*_ +M`@`"+GL``VAK``-II``#::(``^@```/_```#U!X``K\"``(N>P`#:&L``VFD +M``/H```#P"```\`0``/````#:&```VAK``/L```#:&L``K!_``*Q_P`"LO\` +M`VA@``*Q#``#Z````Z`#``/<```#V!```^@```/H$``#Z"```^@P``/^```# +MU!X``VAK``/[```#^P```XCC``/X`P`#_@```]0>``-H:P`#^P```PB.``(. +MX``#[````"'Z``/H4``#Z&```^AP``*Y"``"N,```]R!``/8D0`#0E```_@# +M``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`#:&L``K09``/^```#U%\` +M`VAK``-)I0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``# +M"9X``@\'``-II0`#[````J&^``/P"@`#T!X``P^^``/X`P`#``X``P$>``," +M+@`#`SX``]0>``,/_@`"#Q```_L```,,S@`"#PL``^P```*AO@`#\`H``]`> +M``,/O@`#^`,``L`.``+!'@`"PBX``L,^``/4'@`##_X``@\@``/[```##,X` +M`@\;``/L```#T)X``]`?``*\/P`"2(P``DF<``)*K``"2[P``D0,``)%'``" +M1BP``D<\``*\(``"P(0``Z````*C2``#\$$``L`,``+!E0`#H1```J-9``/P +M00`"P1P``L*F``.B(``"HVH``_!!``+"+``"P[<``Z,P``*C>P`#\$$``L,\ +M``/HT``#C.D``P2```+HC0`#!9$``NF=``,&H@`"ZJT``P>S``+KO0`#8FX` +M`DB,``))G``"2JP``DN\``/4G@`#0FX``F1%``)D1@`"9$<``@]-``!J/P`# +M^P```_L!``,/_@`"#RL``^P```/0G@`#T!\``KP_``)(C``"29P``DJL``)+ +MO``"1`P``D4<``)&+``"1SP``KP@``+`A``#H````J-(``/P00`"P`P``L&5 +M``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`#\$$``L(L``+#MP`#HS`` +M`J-[``/P00`"PSP``KP'``*CW``#\$X``W!,``-03@`#_P```_\```/^```# +MU!X``VAK``/[```#<$X``U!,``/_```#_P```_0$``/P"``"O`@``J3<``/P +M`0`#:H0``KP)``*DW``#\`$``VJ```*P_P`"L;\``K+_``-H8``#^P```_L! +M``+-W@`"IM\``@]F``-*9``"M(```D`$``-J9``"L````K$```*R```"LP$` +M`VIT``*P,0`"L08``K($``*S```#:G@``TI\``/_```"L`$``K$!``*S```# +M:GP``TID``*T@``"0`0``K0#``)@!``#:F0``C"5``-*9``"M(```D`$``-J +M9```:C\``C-L``/L````6?8``&(^``/_```"H;X``_!"``#Q]``#[````J'. +M``/P00`#"[X``PS.``#9]@``XCX``TI```!:%@`#_P```_\```*@O@`#\$(` +M`Z````.B(``#T%X``&(*``!9\@`#H@(``D`)``)"*0`"I8X``@_U``,(C@`" +MH`T``_`+``!"!P`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$ +M3P`#P50``J6N``(0!0`#"JX``J`M``/P"P``4@<``L9O``/!=@`"H+X``_!& +M``/47@`"QF\``\%V``/47@`"QF\``\%V``/47@`##,X``A`&``)KB@`"#\H` +M`^P```-"<```4A8``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``" +MH6@``_!!``+&:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,& +M:``#`B@``P,X``,*K@`"$!D``\%4``/!=@`#U%X``V)P``/L```#P6(``P9N +M``/<$``#V````]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X` +M`_L```,&;@`"$"X``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``# +M:1```VD4``-I&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I +M-``#[````\$0``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC< +M``/T```#\$4``VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4` +M`D$#``-)T@`#_P```D`*``-)P@`"I1```_`!``-)Q@`#[````K!_``*Q_P`" +MLO\``VA@``-H:P`#Z````^@0``/!+@`"LS```VFD``/H```"L3```^@@``/H +M,``#Z$```Z5#``/80``#W%```_X```/4'@`#:&L``_L```/[```"L!(``^@0 +M``/^```#U!X``VAK``,(C@`"$(8``^P```/0G@`#^P```_\```/_```#U)\` +M`_L!``,/_@`"$(P``^P```/X`0`"OP0``TID``/_```#_P```D$/``(0EP`# +M^`,``VAK``/_```#_P```_X```/L```#2F0``_\```*_"``"00\``J`?``(0 +MPP`#0!(``K40``*E)0`#\`0``K\"``)JKP`#]````=#```+$50`"I20``_`$ +M``*_`@`":[\``_0```'0P``"Q$4``J4D``/P!``"OQ```FJO``/T```!T,`` +M`K\0``)KOP``\?0``V`2``(PQ``#[````TIP``/_```#P<(``T`N``*P`0`# +M:J@``_\```/_```#_P```TJL``*T`@`#:JD``\````/`$0`#P"(``\`S``-* +MK0`"OY```J#/``/P!0`#P$0``K\/``)/3P`#]````_!!``/`]``"H-X``_`+ +M``-`&0`#_P```_\```)D0``"95$``F9B``)G4``K#```/<```#V!```J#^``/P!``#Z````^@0``/H(``#Z#```J#^ +M``/P1``"L%4``\$0``/!(``#P3```J#^``/P!``"M/\``\%4``/!9``#P70` +M`J#^``/P1``"M*H``\%4``/!9``#P70``KP'``*C_@`"$7D``$(-``/_```# +M_P```J".``(1/P`"H-X``_`#``-`0@`#]`0``_`!``-`1@``ZC\``&H.``*D +MW@`#\`0``\"(``/`F0`#P*H``\"[``)@"``"81D``F(J``)C.P`"9$@``F59 +M``)F:@`"9WL``&H_``/_```#_P```_X```/4'@`#:&L``_L```,,S@`#_@`` +M`]1>``-H:P`#^P```PS.``(1/P``0@T``&(.``/_```"H(X``A%D``-`2@`" +MI,X``_`$``/`B``#P)D``\"J``/`NP`"I-X``_`"``/!B@`#P9L``KH/``)* +MJ``#BZ8``FJK``*[\``"2[@``Z>V``)KMP`#]`0``_`#``/H8``#Z*```^BP +M``*T\``"8$H``\$0``/!(``#P3```VJ$``*@_@`#\`,``K3P``/T!``#\`$` +M`K0/``)@2P`#P1```\$@``/!,``#:H```^P```/^```#U!X``VAK``/[```# +M#,X``KD#``*@^0`#\$0``^A```/H4``#Z&```^AP``/^```#U%X``VAK``/[ +M```##,X``A&%``*P\``"L?\``J#Y``/P0@`#Z````^@0``/!(0`#P3$``VJ$ +M``-J@``#[````K!_``*Q_P`"LO\``VA@``-H:P``">4``K#```/<```#V!`` +M`K3_``/!9``#P70``KP'``/^```"M?\``]1>``-H:P`#^P```PS.``/^```" +MM>\``]1>``-H:P`#^P```PS.``(1HP`"M?\``VJ%``*P\``#P1```\$@``/! +M,``#:H```TIB``(QT``#Z/```C'<``-J8@``">4``K#```/<```#V!```K3_ +M``/!5``#P60``\%T``*\!P`#_@```]1>``-H:P`#^P```PS.``(1Q0`"L/\` +M`K&_``/!(``#:&```^P```-*9``"M(```D`$``-J9``#[````K`$``*@\``# +M\`,``C#]``/T!``#\`$``BUH``/H```#P````\$0``*R_0`#:&````H[```R +M#```&@L``K`*``*@W@`#\$$``K`,``.!%@`"8`$``K$6``*D/@`#\`$``K,$ +M``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`"L@0``F(F``-J8``#C^$` +M`BY[``-H:P`#_P```_X```/L```#2F```_\```/H,``"8`X``VI@``-*9``" +MM/(``D`$``-J9``#[````&H_``-`!``#_P```K@$``)%X``"H%X``_!$``*@ +MW@`#\$(``T`D``/_````8?@``_\```/_```#W,```X_J``*@W@`#\`$``^CP +M``/8\``#C.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<` +M`D`(``/P0P`"+PL``_0```/P00`"+QL``D1N``/P"0`#Z,```ZMB``.E8``" +M15X``_!#``(O"P`#]````_!!``(O&P`#[````TC```-(Q0`#Z!```^A0``*@ +MW@`#\`@``VC````",0``"C```_\```/_```#:,```_0```/P1@`#:,4``"(O +M```J+@`#_P```_\```-HQ0`#[````&H_``/_```#_P```%'Y``*@W@`#\`,` +M`%GQ``/T```#\$$``%GP``/_```#W*```]BP``-`!@`#_P```_\```)`Z``# +M\`,``J#>``/P00`#0"8``_\```/_```#24$``J`.``/P0P`"H-X``_!!``/! +M10`"14X``_!#``.,Y``#]````_!!``.,XP`#B9@``ZJ<``*@K@`#\`,``B\+ +M``/T```#\$$``B\;``-`!@`#_P```_\```-)00`"0(X``J`.``/P0P`"H-X` +M`_!!``/!10`#Z,```ZM"``)%3@`#\`<``Z5```)%7@`#\$,``B\+``/T```# +M\$$``B\;``/L```"H-X``_`#``-((0`#]````_!!``-()0`#_P```KL!``.B +M9@`#@68``Z$6``.'=@`"8"<``P`+``.G!@`#@@8``F8A``*@W@`#\`0``V@A +M``-JB0`#]````_!"``-H)0`#:HT``^P```./[0`"+GL``^@P``."X``#Z!`` +M`^@```-H,``#C^T``BY[``/H\``#27```^AP``*V`0`#P5$``\%```-H,0`" +MN/P``\%3``/!0@`"15@``TET``(R^``#:#$``\%1``/!0``",O@``V@Q``/! +M4P`#P4(``TF8``(R^``#:#$``\%1``/!0``",O@``V@Q``/!4P`#P4(``TF< +M``(R^``#:#$``\%1``/!0``",O@``V@Q``/!4P`#P4(``TCH``(R^``#:#$` +M`\%1``/!0``"MQ```C+X``-H,0`#P5,``\%"``(R^``#:#$``^P```-)/0`" +ML`@``D`$``/P!0`#2J0``_\```/_```"L@,``VJD``*P!``"000``J`0``/P +M1@`#2,```TC%``*Q`P`"M0,``VC```-HQ0`#[````_\```/_```#_P```^P` +M``-A2``#84$``V%&``-B?P`#P0X``^@0``/H(``#Z#```VCH``/H```#_P`` +M`VCH``-!2``#_P```^P```*P?P`"L?\``K+_``-H8``#:&L```GE``/H```# +MH`,``]P```/8$``"O`,``K#W``*@_@`#\$$``K!_``/!$``#P2```\$P``*T +M_P`#P50``\%D``/!=``#_@```]0>``-H:P`#H`$``Z$1``.B(0`#HS$``_L` +M``/^```#U%X``VAK``/[```##,X``A,A``*P_P`"O`@``\$0``/!(``#P3`` +M`VJ```*D_@`!TSL``J#\``/P`@`#:H0``^P```*P]P`#H0$``Z(1``.C(0`# +M:H0``^P```-)/0`#_P```KB```)D2``#:3T``K`!``*Q`@`"LC\``D(O``*S +M```#:F@``K````*Q```"L@```K,"``-J=``"L0$``K((``*S```#:G@``K`! +M``*R```#:GP``!'O``*PP``"0`\``Z`"``)@#@`"L0```Z(B``*S`0`#:F0` +M`K#_``*QOP`#P2```VA@``/_```#_P```C"5``*X?P`"1$@``VD]``/L```# +MZ````^@0``*R`P`"LP```V@P``/L```#Z````((_``(B^@``\C\``B+Z``(S +MJ``"+FX``TF8``*T]P`"010``VF8``/!+@`#Z#```V@P```"%P`#@>```^A` +M``*@`0`#\`$``\%.``(TL@`#2`@``KC^``)!&``#:`@``^@```""/P`")%H` +M`/(_``(D6@```A<``X'@``/_```"I!```_`"``/!3@`"-+(``C0"``-`+``" +MN$```KF```*[_P`#2J4``D@8``/P`0`"N\\``DD9``/P`@`"NC\``DNZ``)% +M6P`#:J4``_0```'";``#2=$``KA```)$>``#A$```TB<``.%X@`"8`0``F`% +M``-HG``#:*```VBT``-HN``#23@``X7A``/`50`"0B4``VDX``-J7``#H.$` +M`X'A``/H,``#@N@``X7E``(P*@`#0Z8``X#H``/_```"2(4``FB```/!F``# +MP:@``\&X``-CI@`#8^8``^@```/HT``",#L``\'>``(P.P`",&$``X3B``/! +MR0`#Z````X'A``.#Y``"PC$``P(N``+#/@`"1$D``_`!``.#Y0`#Z%```C`J +M``.`Z@`","H``XCE``.$X``"1$P``_`"``.(Y``"R(X``\&8``/!J``#P;@` +M`V,J``-C:@`",&$``X'B``.@X0`#HY8``X+D``+"+@`#Z%```C`J``.@XP`" +M,"H``C!A``.`Y0`"0*```\$0``/!(``#P3```V2H``-DZ``#@.```H((``)" +M`@`#@B0``)'C``/L```",&$``TEP``)$C@`#\$,``K7S``)")0`#:7```^AP +M``/!;@`#P5,``\%"``-H,0`"1)X``_`&``-)G``#I.$``F(D``/!4P`#P4(` +M`V@Q``)$C@`#\$T``TF<``.$Y0`#I><``D`$``)!%0`#I(@``X1```.%1@`" +M8`4``F$4``/H,``#P2X``V@P``-#I```(>,``K4/``/_```"0`4``F`$``/! +M$``#P2```\$P``-CI``#8^0``X&$``.@&``#@@8``F`"``/HT``",$\``\'> +M``(P3P`#2)```Z2Z``.EYP`"014``F$4``-HD``#:*@``VB4``-HK``#H*8` +M`\$0``/!(``#P3```V0D``-D9``#BK8``T@A``*X`P`"9F@``KD/``*[_@`" +M1FD``F9J``)'>P`#:"$``VJ)``-H)0`#:HT``T@(``-((0`"81X``V@(``-( +MR``"N$```KD_``)@"``#:,@``D`)``-HR``"95X``V@A``-JB0`#:"4``VJ- +M``)%6P`#:"$``VJ)``-H)0`#:HT``^P```-`+``"N$```KF```/HL``#2J4` +M`D@8``/P`0`"NS```DD9``/P`@`"NL```FNZ``)E6P`#:J4``TB<``-(H0`" +MO'L``D`,``)$3``#:)P``VBA``-(M``#2+D``D`,``)$3``#:+0``VBY``-( +MD``#A.(``Z7G``)!%0`"810``VB0``-HJ``#:)0``VBL``-).``#A>$``F(E +M``-I.``#:EP``Z#A``.!X0`#@^@``X+H``.%Y0`","H``^@```.!X0`#@^0` +M`L(Q``/H,``#Z%```C`J``.`Z@`","H``T@(``-((0`#J.T``D$8``-H"``# +MJ.L``D9H``/`/@`"15,``V@A``-JB0`#:"4``VJ-``/H0``"-+(``^P```-) +M=``#P6X``^AP``.(2``#P%X``X59``)")0`"8B@``VET``/!0@`#P5,``V@Q +M``/L```#2`@``KC^``)!&``#:`@``TA4``*\8``"8BP``VA4``-)=@`"O!`` +M`F2L``/!6P`#P6X``^AP``-H,0`",O@``TA4``*\GP`"0BP``VA4``/!2@`# +M:#$``C14``/L````\=X``/'=``/!_0`#P4``_0$``(5&```T=\``J#>``(5 +M/@``T>```LW>``/T!``"%.\``$'@``/_```#_P```J"H``(590`"H:@``_!( +M``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@``VGE``-()0`#`Z@``X,P``)G``#8!$``\'?``-) +MF``#A>(``\!5``)!%0`#:9@``^@P``/!+@`#:#```T@(``/_```#A,@``F`$ +M``-H"``#^`,``^P```/_```#_P```&H_``/H````@AD``('<``*P`0`"L1$` +M`K(0``-J1``"L1```^@@``-J1``#0"0``J#>``/P`P`"NU,``_0```/P00`" +MNUL``-G\``)`#@`#\$L``T`0``*\!``#W,```X_J``*@W@`#\`$``^CP``/8 +M\``"O`D``\&Q``(O"P`#0"0``_\```*\`@`"0`P``_!+``-`$``"O`0``]S` +M``*_P``"H-X``_`!``*_@``#V/```XSD``/!L0`"+PL``TF8``.(Y0`"M?T` +M`\$^``*@W@`#\`$``X,P``/!+@`"8`@``D$5``-H,``#2`@``K1```"!]0`" +M8`0``V@(``-(`0`"L+\``D1```-H`0`#Z````K%```/H(``#Z#```VI$``-` +M+@`"L`$``^@0``/H(``#Z#```VI@``(M:``"L`$``K$"``*R!@`#Z#```VIH +M```200`"L!,``K$"``.")@`#Z#```VIP``*P(0`"L0(``K($``*S`0`#:G0` +M`K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P```"L0```K,$``-J?``" +MOQ@``C91``(V?@`"OP```C'5``-*<``#_P```_\```*RD``#:G```K\3``(V +M40`"-GX``T`D``/_```#_P```D`.``/P2P`#0!```KP$``/ +M``/P`0`#Z/```]CP``*\"0`#BQ```B\;``-`)``#_P```KP"``)`#``#\$L` +M`T`0``*\!``#W,```K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(O&P`# +M2G```_\```/_```"LH```VIP``*_&``"-E$``C9^``*_```",=4``TIP``/_ +M```#_P```K*0``-J<``"OQ,``C91``(V?@`#0"0``_\```/_```"0`X``_!+ +M``-`$``"O`0``]S```./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+PL` +M`T`D``/_```"O`(``D`,``/P2P`#0!(``KP$``/``/P`0`" +MOX```]CP``.,Y``#P;D``B\+``*P`0`#Z!```^@@``/H,``#:F```TID``*T +M@``"0`0``VID```A]0`#_P```T@(``/_```#P00``V@(``/L```#Z````\`` +M``*QOP`#P2```VA@``*P`0`#Z!```^@@``/H,``#:F```TID``*T@``"0`0` +M`VID```*.P``$@P``!H+``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`" +ML80``F(A``*D/@`#\`$``K,$``/!'P`#:F```TID``*T@```$?P``D`$``*T +M`P`"8`0``K,0``-J9``",)4``K\(``)/\``#\`$``/(9``/L`````AD``_\` +M``/_```"I0X``_`!``/L```#Z````((9``-`$@`#_P```_\```)$C@`"H$X` +M`_`!``#Q]``"OT```J#>``/P`P`":J\``_0```/P00`":[\``V`2``(PQ``` +M>=P``_\```-`*``"H/X``_!!``/L```"H-X``_`%``+`#@`#\$$``L$>``/T +M```#\$,``L(N``/P00`"PSX``V`H``#QW``#[`````(4```*0```:C\``_\` +M``)``0`"H`X``_`!``/L```#2)P``TBA``-*2@`"H-X``_!#``-(M``#2+D` +M`TI.``*\$``"8BX``F9N``)HC``":9P``J#>``/P!0`#:)P``VBA``-J2@`# +M]````_!#``-HM``#:+D``VI.``/HP```X=L``K`0``*Q```"LA```K,```-B +M=``"L(```]@!``*P```#W`$``K`2``*Q`@`"LA(``K,"``-B=``"L!```K$2 +M``*R$``"LQ(``V)P``-B1``"L0(``K,"``-B3``#8D@``T`L``/_```#_P`` +M`^@@``/H,``#8"P``^@```/H$```8=L``V`8``-@'``#P8P``\&<``/!K``# +MP;P``C=S``(U=P``8=L``_\```*P```#W````K!```./P@`"P`\``]@```-` +M&``"H-X``_!!``-`'``#0"T``_\```/4'@`#U%\``K\```/<\``"O\```XC" +M``+/^``#V/```\0```/$$0`#Q"(``\0S``*U#P`"1&4``Z5F``*@W@`#\$,` +M`K4/``)$=0`#I78``Z9"``.$2@`#IU(``X5:``/$1``#Q&8``L`!``+`!``" +MPB,``L(F``/$%0`#Q#<``]0>``-"=0`#0G(``K\0``*A!``#\$8``J4)``/P +M!``#P8P``\&0``/!K``#P;```J,)``/P0@`#P:P``\&P``-B<@`#0D8``J$F +M``/P1@`"I2D``_`$``/!C``#P9(``\&L``/!L@`"HRD``_!"``/!K``#P;(` +M`V)&``-"3@`"H14``_!&``*E&0`#\`0``\&,``/!D0`#P:P``\&Q``*C&0`# +M\$(``\&L``/!L0`#8DX``T)*``*A-P`#\$8``J4Y``/P!``#P8P``\&3``/! +MK``#P;,``J,Y``/P0@`#P:P``\&S``-B2@`#8G0``_L!``*Q$``"S,X``.'; +M``*@P0`!UN(``T)P``-"10`#_P```L@"``.H@``"RD8``ZJ@``-"3``#0DD` +M`_\```+)`@`#J9```LM&``.KL``"-W,``^P```-(G``#2*$``J#>``/P0@`# +M2+0``TBY``/!&``#P5H``XF6``.+M@`"81D``F5;``*@W@`#\`0``VB<``-H +5H0`#]````_!"``-HM``#:+D``^P` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TURKS_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TURKS_me.bin.uu new file mode 100644 index 00000000000..2eebbc63ef4 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TURKS_me.bin.uu @@ -0,0 +1,126 @@ +begin 644 TURKS_me.bin +M?$"``*````#,@`!-@````-1``'\``!ET``*@>X`62?@````````(```71_&X`. +M@``!>'\;@`^```%\?QN`#(```8!_&X`-@``!A'\;@!&```&(?QN`$(```8T4 +MI``(FX``&12D``B```&='F0`_YN``!44I``(@``!G1YD`/^;@``1%*0`"(`` +M`9T>9`#_FX``#12D``B```&='F0`_YN```D4I``(@``!G1YD`/^;@``%%*0` +M"(```9T>9`#_%*0`"!YD`/\J:``\FH#^<13L``A\0T``?$.``'Q#P`"6P``' +MS```3<]!(6G/@2%JS\$A:X````#,`2%L@````,_U``#,``!9A``$G2IH`#R: +M@``$R"@`%X````#40`!_EH#_JWX"0`"$``*6P`X``LP``$&```&KS,$P2I0` +M``#(/``@1*``!E0``$`:H`@F>@````````(```B'`$@@`@``"+\@4`!&```(VR!0` +M$H```CW,P:*D@``"1ASH`#^```)N?,&`"QS0`#\I*``&*2P`%GZN@`?('``3 +MFH``/004`"Z`````S,&BI,`2"`!\04``?0S`!\`2``@56``#%5P`#'Q"``!] +MT<`&$B``%'X>0`=^3H`'SH&BI(````#-@:'^R!0`$000(1B50```R!0`$=11 +M``"`````S,&BI,@4`!($$"$&E4```,@4`!+440``@````,S!HJ3,P:*D!!`` +M`5P``)R#0`,<@X`##(/``M4W0`('^W@"='N`50S``` +M8L_Z``":0```R"0`)\@H`",ZJ``"FH#__\@H`"/`,``!R"@`))J```#(*``D +MSP``6U#8``@4W``8P#X0`"'<@`!]_<`'S8$A@,W!(8'`'@`@42``"!4D`!A^ +M?D`'$S``'GYR0`=]74`'S@$A@LY!(8/-02&$?$"``*````#,@`!-A``$G1QT +M``$<>``"FT```\@,`"J$``-"R!0`+)N```,$$``0A``#4LS!HF#-`:!@A``# +M#P08"8"$``2=S```9,@\`"Z$``,=R!``*L@<`"\=W``!R"0`*)7```G(-``Q +MR#@`,,@\`"Y3=``@?[>`)T>X!53,``!BS_H``)I```#()``HR"@`(SJH``*: +M@/__R"@`(\@H`"6:@```R"@`)8```M#`,``"!9C``!#<``@4X``8S=D``,@< +M`"+()``B'=P/_\W9``%^8D`'SED``M@840/8&%$$B````-@840<;^`#PP#8( +M`)>```/`,`"`B````,`J``3/02%\SP$A?7`!YG`__[('``E@````7Q`@`!\0,``?$$``!DH`#"6@``( +MR"@`)\@D`"B:0```R"0`)YI```#()``HS``#X'Q!0`!\08``%1P`'\S``,?- +M``#(E<```\`<@`#-P2`0X8,```5<(`#,``!-@````-P?00!\0,``?$$``'Q! +M0`!\08``S,``R`!#(#``I +M4-``"!!4``*```05?16`(,`>`"#(#``J4-``"`A4!``15``"?5&`(,W``&+4 +M6@``?$"``*````#,@`!-?$#``!S0``,1*``!E0``"@:H!!^>@```?$&``(`` +M!"U\0<``@``$,WQ!P`"```0Y?$'``'Q!@`!\0<``%-0`$`54H`"`````S94` +M`,`B``0%F*``?:&`!\P9``"```0IR!@`!,`B``3-@276(B`EU\PA``"```0I +MR!@`!,V!(6W-P2%N@``$*<@8``-\0,``@````,Q,`^`@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8` +M#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/!)8`#P26``\$E@`/ +.!)8`#P26``\$E@`/!)8` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/TURKS_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/TURKS_pfp.bin.uu new file mode 100644 index 00000000000..6d902c16c41 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/TURKS_pfp.bin.uu @@ -0,0 +1,103 @@ +begin 644 TURKS_pfp.bin +M?$"``*`````$*``!@````.`#``#,@`!`U$``0'Q`@`"@````!"@``1!,``&8 +MP``%')```LQ``"F```-?S$``*ID```4`````S$``*X```U_,0``LS$``+8`` +M`U_,0``N'(P``LR``$"8P``$S$``0(```U_,``!2@``#7\P``%2`````S$`# +M_<@0`"[(#``M41``('S0P"=\Q0`@510`(,T``$/-0`!#T,``0\R``$#,``!` +MS$``0'Q`@`"@````!"@``<@0`"S(#``K41``('S0P"=\Q0`@510`(,T``$+- +M0`!"T0``0GQ`P`#(&``#R!P``\@@``.5@/_"R"0``Y7`_\#(*``=FH``!,P` +M`%78``/`S```0,@H`!;`+@`$R#``#1JH`"=^\L`'SL``0,P``$#-@`!`S<`` +M0,X``$"6@``#SD``0-"``%S,@`!`S```0,S``$!\0(``H`````0H``'($``L +MR`P`*U$0`"!\T,`G?,4`(%44`"#-``!"S4``0M%``$)\0,``R!@``\@<``/( +M(``#R"0``Y6`_YG(*``#E<#_E\@L`_U^+P`1EP```W[BP`%\`L`&SL.BGLP` +M`&S-``!MS4``;<@P`!V;```$S```5=@``\#,``!`R"P`%L`R``7(-``-&NP` +M)W\W``?/``!`T$``0,V``$#-P`!`S@``0,Y``$"6P``#SH``0-"``%S,@`!` +MS```0,S``$!\0(``H`````0H``'(&``5'9@``7Q"0`"5@`+.?$*``,@<`"#` +M-\``?$#``'Q!``!\M(`&P#8``QJX`>B7@``'T$`#X(0``V+,``!_R#@#X)N` +M``#(.`/@F<```,@<`"!\M(`'$-0``GUE0`#-0`!#SH``0\T``$/,@`!`SD`` +M0,Z``$#,P`!`X#H``)>`_U3-``!`?$#``(```*)\00``'(P``IC```G($``< +MF0``!,@<``:$``-ES```4L@8`!6```".'9@``L@0`!Z9`/_\R!P`"(0``V7, +M``!4R!@`%8```(X=F``"'(P``L@0`!V8P``.R!0`29D```3('``'A``#9@%5``&(!```7T5``.```".?9&`!IE`__C('``'S<`` +M0,P``$"```#+S```;L`.@(#,``!G!-"`@,P``&C-``/QS0`#\LT``_/-``/T +MS0`#]LT``_?-``/X@```!5`/_WR!0`19E```3(&``* +MS8``0,P``$"```%$V``(0'Q`P`#($`!'F0#__`````#,@`!`S,``0-1``$!\ +M0(``H`````0H``'($`!&V``'0,T``$"$``%;S0``0,@,`$.4P``*R!0`2(`` +M`50$$``#R!``1M@`!\#-``!`A``!6\T``$#(%`!(G4```,P``&K(*``6'J@` +M`9J```/`*0`!B````,`L`5;.@`! +ME,``",@4`!R9```*R!P`"(0``V7,``!4@``!='`)WU8P`-\W,`@5-`` +M((```97,@`!`?$&``,R``$"```&2S8``0,`9___,@`!`S8.BGGQ`P`!\00`` +M?$%``,S#H?K-`Z'YS4.BG9P/]C`````-```_J`````?$#``,R``$"`````U$``0'Q`P`!\ +M00``?$.``'Q#P``$'``"SX``0L_``$+-P`!"!!P`",S``$+-``!"S<``0@0< +M``$$(``!?`)``,@4``/(&``#49@`('U90"?(*``#R"P``\@P``/(-``#4NP` +M('ZN@"=3=``@?S<`)W\K0"%^=D`@5J@`/UT`G?65`(%58`"#,``!;S78``,VV``#((`!!F@```,@@`$&` +M```!?$"``'Q`P`!\00``S,`#_LT``__,P`!"S0``0A44`!\9&`#P)UP``7UV +M``:9@``%?5Y`!LP``$*```-?S```3168``$5+``(F8``,1[L``&6```$%3`` +M#(```U_,``!"!!0`",U``$(?,``!("@``00X``@$/``!R!0``\@8``/('``# +MR"```WU=0`U]H<`-?5U`!Q80`!\5G``??1T`!GT70`9^DH`&FT``$@NX``2; +MP/_R"_P``<@,`_Z:@``)R!`#_YL``0;,``!-!!0`",S``$+-``!"@``"0\U` +M`$*6P`#_S```38```U_,``!.FL```\P``$W,``!.EX#]F>.#``"`````W`,! +M_Y9```3,``!.@``#7\P``$+2``!"R`@``\@,``/($``#R!0``\@8``/('``# +MR"0``\@H``,5_``?%K``'W_SP`84\``??_/`!A5P`!]_\\`&?8B``9?```U] +MS,`!?E$``7Z50`%\D(`,?-3`#)K```-\CT`&)+0``9M``-;,``!-@``#7\P` +M`$[(#`/^R!`#_\S``$*```)OS0``0GQ`P`!\00``?$+``'Q#``#`.P`??$-` +M`'^W@`;`/A``EX#]9GT]``=_/P`'&10`.\P``%N50``3R!0`0#%8``*5@/__ +MR!0`0,P``&,A'(``S,$AA +MA``#8LP``%W((``??$#``,`V_P#($``AP#`__WSU0`9]48`&?8&`"IF```A\ +M\X`&XX,``,^@`$^$``-BS```7H````#40`!_@``#7\P``%Z$``-B?$#``!3< +M``B5P``9'-P`$'Q!``"9P``$4%0`((```QW)'0``?14`)\D>``!\0@``?$)` +M`'Q!@`!]Y<`&?>*`$9J`_-Y!K``%FL````KL``$<`(@+L`","_0`G`8P`'P'Y`"`"*0`H`:X`*0%[`"H!H``K +M`9``+P&I`#(!S0`T`S\`-0%_`#D!]@`\`Q$`/P&[`$$"D@!"`KD`0P+#`$0" +MT`!*`MX`50,S`%8#.@!@`(P`80"Q`&(`V0!C`,,`9`##`&4`PP!F`,,`9P## +M`&@`Y@!I`.\`:@$_`&L!#0!L`0T`;0$-`&X!#0!O`0T`<`$2`',`^P!T`/L` +M=0%F`'L#3`````4````%````!0````4````%````!0````4````%````!0`` +M``4````%````!0````4````%````!0````4````%````!0````4````%```` +9!0````4````%````!0````4````%````!0`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/VERDE_ce.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_ce.bin.uu new file mode 100644 index 00000000000..89b637f20e9 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_ce.bin.uu @@ -0,0 +1,194 @@ +begin 644 VERDE_ce.bin +M?$"``8@```#40`!_?$"``8@```#$(``+Q@P`!93``"0D4``/,10``I5```3, +M0``DS$``)8`````Q%``#E4`!.\Q``";,0``G@````,0@``O,(``%?$$``5!4 +M`"!\08`!!B0``@8U``P&-@`-`4H`$1\0@`!?$)``94` +M``>&@```@``!4(```5"```%0@``!4(```%(15``0?A8`"LU``!'480``E8#_ +MLL0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``!'48@``E8#_J<0@``Z:`/__ +M?$"``8@```!\0,`!%-``'C$4``*50`#K&-0`,!C0`>@8_``T),P`#P3H`&A\ +M08`!?$'``93``!*&@```@``` +M`!J```!_4=P`('V=@!J90``#Q:(``(```'_)H@``@```?\6A``"50``%!9@` +M`<6E``!29``@?B8`&@4H`(-\08`!?$'``94```>&@```@``!4(```5"```%0 +M@``!4(```)/8```1SAD``)5```0%F``!5B``(,X9``"7P/]QQ#DA0'Q`@`&( +M````4=P`('V=@!K8```1SAH``)5```0%F``$5B``(,X:``";P/^]?$"``8@` +M``#8``/VV``#]=@``_38``/SV``#\M@``_'8``/PV``#[]@``^[,0`!_S$`` +M?\Q``']\0,`!S,```=1``'^`````?$#``5!0`"",``#+?-#`&L0@``O$U@`` +M?$.``<0D`!.:```)V&0#],9K`_&:@/__QFL#[@:H``'.I`/NS60#Z]@D`_29 +M0``)WX,``,^@``Z,``#/U$``?YH`_SS&

?16`#IF```_80``IR!``'7U1@!)]C<`/F<#__=@``"E0X``! +M?A9`#II```1]8H`2TH``(X````#0```C@````-B``"G$/`!_S```(-A``"C$ +M#``V$``'8````#,```@V$``*,0, +M`!R8P/__V```*-```![0```?V$``'7Q!``&`````?$#``7Q!``$5&``?S0`` +M$5$4`""9@``#U$T``(````!]34`:&1P`,=16``#$(``.E<#^R,0@``Z:`/__ +M@````'Q`P`%\08`!%-``'C$0``(DU`#_E0#^O\V4`P"`````Q"``$WQ`P`'$ +MTP,`S```$`(0`]@"'`/D`B`$"`(D!%P!]`3P`?@%$`'\!+``B`*X`BP$B +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +M``(````"`````@````(````"`````@````(````"`````@````(````"```` +M`@````(````"`````@````(````"`````@````(````"`````@````(````" +M`````@````(````"`````@````(````"`````@````(````"`````@````(` +M```"`````@````(````"`````@````(````"`````@````(````"`````@`` +:``(````"`````@````(````"`````@````(` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/VERDE_mc.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_mc.bin.uu new file mode 100644 index 00000000000..2797c58ea17 --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_mc.bin.uu @@ -0,0 +1,694 @@ +begin 644 VERDE_mc.bin +M``/HX``"O@$```('``/_```#_P```J`.``'`&0`#Z````^@0``/H(``#Z#`` +M`V`@``-A2``",;@``TEL``-("@`#KPH``K0$``)O]```^BT``K0/``)/%``` +M^@H``ZB,``#"`0`#0"0``K1```*U#P`#2J8``D1!``/P`@`"294``VJF``-* +M40`#0"0``K@"``*Y_@`"1)0``DB!``.H@``"9$@``VI1``-`)@`"OX```KP$ +M``))^0`#\$(``_0```'`00`"OX```TA4``*X#P`"N?```D$8``)"*0`#:%0` +M`TMI``/`C``"9$P``VMI``)$2``#:VD``F$?``)B+``#:%0``BP%``-+3``# +M_P```V%$``-+'``#0"H``K3\``-A0``"0S0``F$>``-K'``"2JX``_!&``-) +MU0`"O!```DS'``/P0@`"O"T``C)S``-`)``"M$```K7P``-*I@`"1$$``_`" +M``)IE0`#:J8``T````/_```#^`$``\1```/$40`"QD4``@````-`$``#_P`` +M`_\```/H(``#Z#```V`0``"1Y0``D@T``_@#``(POP`",;(``T@(``*TGP`" +M0`0``V@(``-(P``#2,8``K3\``*U#P`"010``DF4``)")0`"2J4``D,U``)+ +MM0`#:,```VC&``-(```#2`4``KL_``*\OP`"O^\``)(E``"*)@``@BH``+HH +M``"J+``"01L``KO[``)`#``#:````KS^``)%7P`"1WP``V@%``-($``#2=T` +M`KOQ``*\`@``BBD``*HK``)!&P`"81P``V@0``)%6P`"95P``VG=``-`#0`# +M_P```_\```.A3```B?\``K,"``)#-``#HS```)G^``*S!``"0S0``Z,R``"9 +M_0`#0"D``T````*\(```N<<``D(L``/P!P`"L````((Q``(Z,P`#Z````('E +M``/T```!PEP``T````*\(```\C$``D,\``/P!0`".C,``^@```"!Y0`#]``` +M`<)<``-((0`"L\$``D=S``-H(0`#:HD``T@E``*SP0`"1W,``V@E``-JC0`# +M2"D``TEP``-`$@`"OP<``D`/``.````#``X``Z^(``-)U@`"O!```DS+``/P +M00`"P`\``X0&``.%5@`#I58``F54``)D0``#2>@``V@I``-H+0`#P00``\$5 +M``-IZ``#:>P``TK"``*_P``"2(\``VK"``-JQ@`#Z````^C0``(NE@`#:.0` +M`\'>``(NE@`#:00``^A```*]```",@(``KT!``(R`@`#0"P``_\```*T`@`" +M1`0``*()``-)U@`"M1```D1;``.D1@``H@L``J!.``/P`P`",[<``_0```'! +M!0`#]````=)]``*\```",CT``T`.``#R,@`#Z/```Z"V``-)U0``^@0``K$/ +M``)"%P`"I2```_`!``#Z,@`"0QL``J4C``/P`0``\@0``T````-`+@`"MA`` +M`K0,```J,@`"0B0``Z(B``)#-``";",``D9H``/P`P`"H%X``_`!``/HP``` +MX@,``T`(``*T````>@0``J`D``/P00`"L@@``J#^``/P00`"L@0``K0_``)" +M)```DAH``TJ4``/_```#88```T````/_```"M$```D0$``/P`P`#Z````((Q +M``(BX``#0````_\```*T0``"1!0``_`"``#R,0`"(N```T````/_```"M$`` +M`F$0``)$%``#\`$``BSW``-*E``#_P```V&$``-````#_P```K0"``)$)``# +M\`,``^@```"",0`"(PP``T````/_```"M`(``D0T``/P`@``\C$``B,,``-* +ME``#_P```V&(``(QL@`#0````_\```/_```"1`X``_`#``/H````@C$``B0; +M``(QL@`#0````_\```/_```"1!X``_`"``#R,0`")!L``BTN``-*E``#_P`` +M`V&,``-````#_P```K0"``)$0``#\`L``^@```"",0`")@<``T`L``/_```" +MM"```D1```/P`P`#Z````((Q``(Q*0`#2I0``_\```-AD``#0````_\```*T +M!``"1$```_`#``/H````@C$``B?3``-*E``#_P```V&4``-````#_P```K00 +M``)$0``#\`P``^@```"",0`"*'H```'_``/_```#_P```J0.``/P!```\@`` +M`BAZ``/H````@@```TJ4``/_```#89@``T````/_```"M"```D1```/P`P`# +MZ````((Q``(J"@`#2I0``_\```-AG````@,``_\```*T`0`"1`0``_`$``/H +M````@C$``\'^``(JO````@,``_\```*T`@`"1`0``_`$``/H````@C$``^CP +M``(JO``#0````_\```/_```"1"X``_`#``/H````@C$``C?1``-````#_P`` +M`K00``)$)``#\`,``^@```"",0`"./4``_@#``-*E``#_P```V%@``-````# +M_P```K0"``)$00`#\`H``/(Q``(F!P`#0"P``_\```*T(``"1$```_`"``#R +M,0`",2D``TJ4``/_```#860``T````/_```"M`0``D1!``/P`@``\C$``B?3 +M``-*E``#_P```V%H``-````#_P```K00``)$00`#\`L``/(Q``(H>@```?\` +M`_\```/_```"I`X``_`$``#R```"*'H``^@```""```#2I0``_\```-A;``# +M0````_\```*T(``"1$$``_`"``#R,0`"*@H``TJ4``/_```#87````(#``/_ +M```"M`0``D0$``/P`P``\C$``\'^``(JO````@,``_\```*T"``"1`0``_`# +M``#R,0`#Z/```BJ\``-````#_P```_\```)$/@`#\`(``/(Q``(WT0`#0``` +M`_\```*T$``"1#0``_`"``#R,0`"./4``TJ4``/_```#870``_@#``-````# +M_P```K0(``)@`0`"1`0``_`,``-("``#_P```K1```)@!``#:`@``TF8``*T +M_0`"010``VF8``/H,``#P2X``V@P``(Q1``#Z````^@0``/H,``"L@,``V@P +M``-````#_P```K6```)A$``"114``_`!``(W,``#2I0``_\```-A>``"O`$` +M`C(]```",@`#_P```_\```*A#@`#\`(``^@```""!P`"+2X``T@```-(!0`` +M"B8```(J```2)0``*BP``#HH``/_```#:````V@%``-($``#2=T```HI```J +M*P`#_P```V@0``-IW0`#27$``K(!``/H,``#P08``\$7``-H,``",40``^@` +M``/H$``"L@,``K,```-H,````@L``_\```/_```"H`X``@*!``/T```!P``` +M``'E``-`$@`#0!4```H-``*@#@`#\`(``_0```'"G``"P1X``(H-``)KN@`" +M95L``L9N``/P00`#!FX``V`5``*R#P`"1$(``J44``/P!P`#Z*```^BP``-@ +M$@`#Z````('E``/T```!P&L``T`L``/_```"M"```D!```/P`@`#]````<*H +M``/H````@C$``C$I``#R,0`",2D``^@```"",0`",%X``/(Q``(P7@`#23T` +M`TC```*V"``"1F0``_`"``*U,``"8B4``VC```-HQ``#2QT``T`H``*\$``" +MOP0``DS```/P!0`"9W\``VL=``(Q1``"9WX``VL=``-`(``#_P```_\```+" +M+@`#\$0``L,^``/P0@`"LO\``K/_``-@(``",;(``TE(``-`*@`"M#\``K6` +M``*V0``"1F@``_!%``)#-``"8S4``VE(``)#-``#:4@``^@```/H$``#Z"`` +M`^@P``-DI``#9.0``_0```'````#0`0``&HQ``/H@``#Z)```^B@``/HL``" +MH-X``_`#``-DJ@`#]````_!!``-DZ@``8>D``J#>``/P`P`#Z$```_0```/P +M00`#A.H``]A```/>@``_@#``/4G@`#^P```P_^``("]P``(<,``J#> +M``/P`P``8<(``_0```/P00``8<$``K\(``/<0``#V,```_@#``/4G@`#^P`` +M`P_^``(#!@`#^`,``^P````",@``:C$``_\```*@#@`#\`$``^P```-).``" +MH-X``_!!``-).``"N/X``D(H``-I.``#2=```K0$``)A%``"L@$``K,2``*@ +MW@`#\$$``K,1``-H,``#27$``KCO``*Y!``#P08``F%Y``)#.``#:#```T@) +M``*X_0`"1$@``V@)``(M"``#2:```K01``/!)``"L0\``VF@``-*1``"M/X` +M`F$>``-J1``"010``VI$``*@W@`#\`,``T)A``/T```#\$$``T)=``/_```# +M_P```^A@``-II0`#:&L``KH,``*XP``#W($``]BA``*P^``"L0<``^@@``/H +M,``#_@```]0?``-H:P`#Z/```B/)``(CL@`"(]X``J'^``/P00`#8GH``T)X +M``/_```#_P```J"```'#9P`"H)$``<-G``*@H@`!PV<``J"S``'#9P`"S_X` +M`KP,``*A_``#\$(``_0```'#40``^``-">``# +M_P```_\```*@@``!PWT``J"1``'#?0`"H*(``<-]``*@LP`!PWT``L_^``*\ +M#``"H?P``_!"``/T```!PVH``&'.``#YQ0`#_P```J7/``'#C0`"I?P``<.( +M``/H\``#Z,```_0```'#D``##,\``ZS```/H\``#]````<.0``,/_``#K_`` +M`^C```(CR0`#P?P``B.R``-).``"H-X``_!!``-).``#_P```F(N``-I.``# +M2=```K3[``)!%``"L@$``K,2``*@W@`#\$$``K,1``-H,``#27$``KCO``*Y +M^P`#P08``D%Y``)#.``#:#```T@)``*X_0`"1$@``V@)``*P&``"(_T``BTN +M``/L```#P0\``\$?``/!+P`#P3\``J#>``/P!0`#9+```V2T``-DN``#]``` +M`_!#``-D\``#9/0``V3X``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``# +M:,@``^P```/!#P`#P1\``\$O``/!/P`"H-X``_`$``-DK``#9+P``_0```/P +M0@`#9.P``V3\``-(R``"M/,``K4$``)`!``"8`4``VC(``)`!``#:,@``^P` +M``*P$``"(_T``TH<``(D#0`#P8P``TH@``(D#0`#C,8``FB,``-*)``")`T` +M`\&<``-**``")`T``XS&``)IG``#2BP``B0-``/!K``#2C```B0-``.,Q@`" +M:JP``THT``(D#0`#P;P``THX``(D#0`#C,8``FN\``/L```#:&L``KD(``*X +MP``#W(```]B0``/H$``#Z"```^@P``/^```#U!X``VAK``/!CP`"OQ```BT$ +M``/!^``#[````^C```.'/``#IW8``X8L``.F:``#A1P``Z5:``.$#``#I$P` +M`FS'``)LQ@`";,4``FS$``/L```#0"0``&HQ``/_```#H`8``J$.``/P`0`` +M@?D``TFA``-)I``"NT```KJ_``)%I0`"H-X``_`#``)#HP`#]````_!!``)C +MLP`#::0``VFA``(R8``#Z````^@@``/H,``"H-X``_`#```)^P`#]````_!! +M```)^@`"N,```VAK``/8```#W(```]0>``*_"``"+00``X#@``"!]@``@?4` +M`^@```"!]```@?,``/'R``-(5``"H-X``_`#``.$Z``#]````_!!``.$Z@`" +M8B0``VA4``-)=0`#B.8``F!H``/!%P`#P2X``\$^``*@W@`#\`$``X,P``-H +M,``#2%0``J#>``/P`P`#A.@``_0```/P00`#A.H``\!$``)")``#:%0``&(+ +M``*_`@`"+00``J#.``/P`@`#]````@2#``(NJ``#Z'```X3F``)&2P`"H&0` +M`_!*``-)T@`#Z&```XJR``.JJ@`"H:X``_`"``,!K@`")?<``_0```'%(@`" +MOP@``D_Y``.O]``#B[(``ZN\``(E.P`#]````<4B``-`#``#_P```K\(``)/ +M\``#\$(``_0```'$E``"OP```KL!``(E.P```@0``_\```/_```"H`X``_!" +M``/T```!Q2(``/'T``#Q\P`"H-X``_`#``!Y^``#]````_!!``!Y]P`#C>(` +M`]S0``/8\``#B>8``FF>``#QXP``0?D``^C0``./X``#P:@``XSM``#AYP`` +MXC```BX1``*W`0``0?D``^B@``#1XP`"H'X``_`!``.H@``##]\``\'9``/! +MJ``#C.T``.'G``#B,``"+A$``BY2``/!!``#P28``V)P``*_`0`#0!$``XC@ +M``*@_@`#\`0``D1(``/P`@`#]````@4(``*W`0``0?D``_\```*@?@`#\`$` +M`ZB```/HT``#C^```\&H``.,[0``X><``.(P``(N$0`"+E(``T)P``.,ZP`# +MC.H``^CP``+(0``#J(```"H)``+*8@`#JJ```J9>``($Y0``:C$``/()``/! +M6``#P7H``V)Q``/T```"!)\``J%>``/P#@``:C$``\&1``/!LP`"H-X``_`# +M``-A+@`#]````_!!``-A,@`"P($``Z@```+"HP`#JB```X50``"J"0`#@>`` +M`P"$``/P)``"H80``_`!``+$00`#!$X``\%4``,"I@`#\"0``J&F``/P`0`" +MQF$``P9N``/!=@`#U%X``F`"``($]P``:C$``K\"``(M!``#27$``X'D``/! +M!@`#HFP``J`N``(%(@`"87$``\$N``/!/@`"H-X``_`!``.#,``#AF```_!' +M``-H,``#C^T``BT$``./[0`"+00``X_M``(M!``#C^T``BT$``-)=0`#P2X` +M`\$&``/!%P`#P3X``J#>``/P`0`#@S```V@P```!Y0`#_P```_\```*E#@`# +M\$@``T`1``*@W@`#\`,``F9N``/T```#\$$``F=^``-@$0`#Z````('E``/L +M```"H/X``<5'``*P#P`"L0\``K(/``*S#P`"H-X``_`#``-C*``#]````_!! +M``-C:``",40``TI```!!\@``2?8``%'U``*\,P`"1`P``D4<``)D10`"1BP` +M`D<\``)F9P`"9$8``J%.``/P`0`"M`$``J".``/P!0`"I$D``_!#``*D2P`# +M\$$``/'T``"A]@`"O,P``D0,``)%'``"1BP``D<\``)D10`"9$8``F1'``*A +M3@`#\`$``K0!``*@C@`#\`4``J1*``/P0P`"I$L``_!!``#Q\P``H?4``^A` +M``"A\@```?0``!'S``*Q#P`"LP4``J7^``(%G0`"H/X``_!!``/H\``"H`X` +M`_`!``+/_@`"L1```J`N``/P`0`"S_$``K.0``*F\P`#\$(``/'E``/L```" +M0P(``_!#``(EW0`#]````<5'``*T$0`##_0``J#>``/P`P``^?$``_0$``/P +M`0``^?```T,I``*@W@`#\$$``T-I``*_=P`");P``^P```-(Y0`"H-X``_!! +M``-)!0`"N!$``J`.``/P`0`"Q$@``DE!``*DDP`#\`$``/'T``*@+@`#\`$` +M`L58``))40`"I),``_`!``#Q\P`"H-X``_`#``-HY0`#]````_!!``-I!0`" +M0`(``J`.``(%1P`"L0(``B7W``/L```"H?X``_!!``/L```#H?8``X_V``.@ +M]@`"H0X``_`'``*\"0`"H$P``_!!``*\#P`#P4P``\%<``,`#@`"H1X``_`' +M``*\"0`"H&P``_!!``*\#P`#P6P``\%\``,!'@`"H-X``_`#``-C*0`#]``` +M`_!!``-C:0`"8@$``@7"``/L```#0RD``J#>``/P00`#0VD``J`.``/P!0`" +MM`\``DS^``/P`0`"M`D``\%4``*@+@`#\`8``K8/``.L]@`"3,X``_`!``*V +M"0`#P78``J#>``/P`P`#8RD``_0```/P00`#8VD``^P```-(Y0`"H-X``_!! +M``-)!0`"L!$``L1```+%4``"H-X``_`#``-HY0`#]````_!!``-I!0`#`1X` +M`@7[``/L````:C$``^@```(N@@``\>\``^@```"![@`#0`P``T`M``*X$``" +MN0@``DH8``.JI@`"2TD``ZNT``*S!``";ZL``_!!``*S`@`"3ZL``_`!``*S +M!@`#0"T```H$``*P0``"0$```_!!``/H,``"01X``_`!``/H,```F>T``BT( +M``*X$``"N?X``J#>``/P"0`#2"$``KH/``)&:@`"1WD``F9H``-H(0`#:HD` +M`_0```/P1P`#2"4``KH/``)&:@`"1WD``F9H``-H)0`#:HT``C`H``*_`P`" +M+_0``K]D``(M!```:C$``_\```/_```"H-X``_`#``*[```#]````_!!``*[ +M0```V>```\$.``*Q$0`"LA```VI$``*Q$``#Z"```VI$``*P_P`"L?\``K+] +M``*S_P`#:&```TI@``*_]P`"L1,``D`/``)@#@`#:F```#'^```Y_0`"O`@` +M`K_^``.&:@`"8B8``J1^``/P`0`"LP0``D`/``)@#``#:F```X_A``(M!``# +M:&L``_\```/^````8B\``%HN``/_```#V,$``]RQ``./XP`"+00``]`?``., +M[P`#C^0``F_^``)``0`"0B,``D`"``),P``#^P$``]`?``,/_@`"!G@``J#> +M``/P`P`#2"$``_0```/P00`#2"4``\#,``(&I``#C.8``L9L``/P00`"QWX` +M`J#>``/P!``#:"$``VJ)``/T```#\$(``V@E``-JC0`"I7X``_`"``/T```! +MQDH``T`1``*P"```\>4``J#>``/P`P`"9F```_0```/P00`"9W```V`1``/T +M```"!]$``X#A``.!!@`"81X``X+G``-J1``#@08``^@@``-J1``","@``T`L +M``!:'0`"M`0``^CP``)$0``#\`$``K\!``*DO@`#\`$``K\$``(O]```\AD` +M`/(7``(R6@`","@```HM```1_@``&?T``K`"``*@W@`#\$$``K`$``."*@`" +MI#X``_`!``*S!``#@18``F`!``*Q,P`#:F```T`*``*P`0`"L0(``K(```*S +M`0`"H"L``_`"``/H(``#P3L``VIH``/!#@`"L@D``D`)``/P`0`#Z"```K`3 +M``*Q`@`#@B8``^@P``-J<``#0"T``&($```2&@`"OT```D]/``/P`P`"H,X` +M`_`!``*R"``"L"$``K$"``*S`0`#:G0```H=``*P`0`#_P```J0>``/P!0`" +ML00``K(```*S`@`#]`0``_`#``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`0`"L0(``K,$``-J?````>X``_\```/_```"P`X``('N``(O[P```AD``T`* +M``-`#0`"H`X``_`%``*P`0`"0`4``X`&``/T!``#\`,``K`$``)`"0`#@`(` +M`K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`"LP$``VID``(NO0`" +M+LH```'O``/_```#_P```J`.``/P3@`#0"P``KP$``/``/P +M`0`#Z/```]CP``*\"0`"OS\``DL?``(MBP`#Z/```/GO```![@`#_P```_\` +M``+`#@``@>X```GM``-`+@`#_P```J`!``('2@`"L`$``D$(``/P!0```C(` +M`_\```/_```"H`X``@=*``-*=```>AH``_\```/_```#P2\``VIT``(O[P`` +M`AD``T`*``-`#0`"H`X``_`%``*P!``"0`4``X`"``/T!``#\`(``K`0``)` +M"0`"L4,``F@!``-*9``"M(```!'@``)`!``"8`@``Z(B``/!/@`#:F0``BZ] +M``(NR@``0@,``K`"``*@W@`#\$$``X`"``)`"``#\`(``_0```''>@`#0`X` +M`K`0``/_```"00D``J`0``('>@```AD``_\```/_```"P`X``((9``*Q`@`" +MI`$``@<```!!X````<,``_\```/_```#V(```]P```*_"0`"L````]P!``*P +MP``#V`$``BZT```![@`#_P```_\```+`#@``@>X``B_O``-`"@`"L$```_\` +M``)`"0`#H`(``K$#``)H`0`#2F0``K2````1X``"0`0``F`(``.B(@`"LP$` +M`VID``(NO0`"+LH``T`E``!"`P`"L"```D`%``/P2``"L`(``J#>``/P00`# +M@`(``D`(``/P`@`#]````<>_``-`+@`#_P```K`(``)!"``"H!```@>_``*P +M@``"00@``_`%```",@`#_P```_\```*@#@`"![\```(7``/_```#_P```^@0 +M``"*%P`"I`X``@``/P`P`"NV(``_0```/P00`"NV@``_\```/_ +M````V>P``C"E``/H```"+H(``KL"``#:,``#Z````K%@``/H(``#Z#```VF@ +M``/H```"L1```^@@``/H,``#:D0``C`H``*_`@`"+_0``K#_``*Q_P`"LOT` +M`K/_``-H8```"BT``!'^```9_0`"L`H``J#>``/P00`"L`P``X$6``)@`0`# +M@BH``K$,``)B(0`"I#X``_`!``*S!``"L18``VI@``./X0`"+00``VAK``/_ +M```#_@```C`>``-*8```,?X``#G]``*T]@`"M0,``X9J``)B)@`"I'X``_`! +M``*W!``"8S<``P$5``)`!``#:F```T`*``*P`0`"L0(``K(2``/H,``#:F@` +M`K"```*R"0`"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP``*P(0`" +ML0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P +M`@`"L0(``K,$``-J?``",EH``^AP``-*9``"M(```D`$``/H(``#Z#```VID +M``-*9``"M(```!'L``)`!``"M`,``F`$``*S$``#:F0``BZ]``-*9``"M`@` +M`D1```)G=``"I7X``@AX``/H```"+H(``J#>``/P`P`#2"(``_0```/P00`# +M2"8``_\```.,Y@`"RJP``_!!``++O@`"H-X``_`$``-H(@`#:HH``_0```/P +M0@`#:"8``VJ.``/H<``"IKX``_`"``/T```!R#T``T`2``#QY0`"OP0``J#> +M``/P`P`":J\``_0```/P00`":[\``V`2``/T```!R'@``C`>``/L````:C$` +M`/'O``/H````@@8``T`(``-`+0`"N$```KD(``)*"``#JJH``DM)``.KM``" +MLP0``F^K``/P00`"LP(``D^K``/P`0`"LP8``T`M```*!``"L$```D!```/P +M00`#Z#```D$>``/P`0`#Z#```)H%```AY0`#Z%```_\```"B#```J>4``&HQ +M``/_```#_P```J#>``/P`P``6<(``_0```/P0P``6<$``_\```/_````V>`` +M`T`L``!:'0`"M`0``^CP``)$0``#\`$``K\!``)+O@`"H+X``_`#``(O)0`# +M]```````D`$``)@"``#HB(``K,!``-J9``" +M+KT``B[*```![P`#_P```_\```*@#@`#\$X``T`L``*\!``#W,```K_```*@ +MW@`#\`$``K^```/8\``#C.0``K\_``)+'P`"+8L``^CP``#Y[P```@8``_\` +M``/_```"P`X``((&``!:'0``>A<``K@(``)*O@`"H*X``AH``_\```/_```#P2\``VIT``(O[P```A@``T`*``-`#0`"H`X` +M`_`%``*P"``"0`4``X````/T!``#\`,``K`@``)`"0`#H````K%#``)H`0`# +M2F0``K2````1X``"0`0``F`(``.B(@`"LP$``VID``(NO0`"+LH``$(#``*P +M`0`"H-X``_!!``.``@`"0`@``_`"``/T```!R;4``T`*``/_```"L$```D$( +M``*@$``"";4```(8``/_```#_P```L`.``""&``"L0(``J0!``()#````>`` +M`$'#``/_```#_P```]@```/<@``"OP@``K#```/8`0`"L````]P!``(NM``` +M`@8``_\```/_```"P`X``((&``(O[P`#0`H``K"```/_```"0`D``Z`$``*Q +M`P`":`$``TID``*T@```$>```D`$``)@"``#HB(``K,!``*Q```#:F0``BZ] +M``(NR@``0@,``K`!``*@W@`#\$$``X`"``)`"``#\`(``_0```')]P`#0"X` +M`_\```*P"``"00@``J`0``()]P`"L(```D$(``/P!0```C(``_\```/_```" +MH`X``@GW```"%P`#_P```_\```/H$```BA<``J0.``()3P``8<,``%G@``/_ +M```#W,```]BP``*_"``"L,```]@!``*P```#W`$``C)@``-H:P``$=8``K/` +M``/HT``#8G0``BVS``(P'@`#[````&HQ``/_```#_P```J#>``/P`P`"NU,` +M`_0```/P00`"NUL``_\```/_````V>P``T`0``*['P`#2"D``J#>``/P00`# +M2"T``D`+``.O`@`#C/8``FS/``./]@`#2>@``J-,``/P!``#!$P``P5?``/T +M```#\$(``P3$``,%]0`#P00``\$5``*@W@`#\`0``V@I``-IZ``#]````_!" +M``-H+0`#:>P``^@```(NE@`#Z````K%```/H(``#Z#```VI$``(P*``"OP(` +M`B\E```*+0``$?X``!G]``*P`@`"H-X``_!!``*P!``#@18``F`!``."*@`" +ML80``F(A``*D/@`#\`$``K,$``*Q&``#:F```T`*``*P`0`"L0(``K(*``/H +M,``#:F@``K"```*R"``"0`@``_`!``/H(``"L!,``K$"``.")@`#Z#```VIP +M``*P(0`"L0(``K(!``*S`0`#:G0``K`!``*Q`@`"L@\``K,!``-J>``#2GP` +M`_\```*P`@`"L0(``K,$``-J?``",EH``^AP``(O[P`#2F0``K2````1[``" +M0`0``K0#``)@!``"LQ```VID``(NO0`#2F0``K0(``)$0``"9W0``J5^``(* +MN0`#Z````BZ6``*@W@`#\`0``T@J``-)Z``#]````_!"``-(+@`#2>P``KP1 +M``*_$``"R9\``LB,``/P00`#Z(```\$(``/!&0`"H-X``_`$``-H*@`#:>@` +M`_0```/P0@`#:"X``VGL``-*P``"OP<``DW>``/P`0`"OS@``J&.``/P0P`" +M8`\``VK```-JQ``"NP$``-HP``/H<``"3_```_`#``*[_P`"H(L``_`"``/T +M```!RG$``T`2``#QY0`"OR```J#>``/P`P`":J\``_0```/P00`":[\``V`2 +M``(P*``"+^\``^P```!J,0`#Z````(',``*@W@`#\`,``%G"``/T```#\$$` +M`%G!``*P?P`"H?X``_!!``)+L```V>```C):``(P*```"BT``!'^```9_0`" +ML`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&```)B(0`"I#X``_`!``*S +M!``#0!4``K$(``*V\``"1$8``F$4``-J8``"L`$``K$"``*R```"LP(``VIH +M``*R"``"L!,``K$"``.")@`#Z#```VIP```2&@`"L"$``K$"``*S`0`#:G0` +M`K`!``*Q`@`"L@\``K,!``-J>``#2GP``_\```*P`0`"L0(``K,$``-J?``" +MO`0``]S```!YX``"O`@``KL8``/8\``"+8L```',``-`)0`"OQ```L`.``"! +MS``"3U\``_`#``(KQ``#]````````G#``-`)@`" +MLA```]@```/<$``"OP@``K#```/8`0`"L````]P!``)"*0`#\$4``Z_P``*@ +MS@`#\`(``_L```/[`0`#T)X``_L```*E+@`#\`$``_L```/4GP`#^P$``J4N +M``/P`0`#^P$``P_^``(+.```````_\```/``/L```"O!$` +M`J#>``/P!``#2,P``TC1``/T```#\$(``TCL``-(\0`"*Z\``J#>``/P!``# +M:,P``VC1``/T```#\$(``VCL``-H\0`"H-X``_`$``-(U``#2-D``_0```/P +M0@`#2/0``TCY``(KKP`"H-X``_`$``-HU``#:-D``_0```/P0@`#:/0``VCY +M``*@W@`#\`,``TC<``/T```#\$$``TC\``*@_@`#\`0``L`,``+!'``#]``` +M`_!"``,`#``#`1P``J#>``/P`P`#:-P``_0```/P00`#:/P``^P```*@_@`# +M\`H``L`,``+!'``"PBP``L,\``+$3``"Q5P``L9L``+'?``#]````_!(``,` +M#``#`1P``P(L``,#/``#!$P``P5<``,&;``#!WP``^P```*P?P`"L?\``K+_ +M``*S_P`#:&```VAK```)U@`#Z````Z`#``/<```#V!```T`Q``*_`P`"O`(` +M`J;\``/P00`#P0<``J#\``/P00`#P08``J#^``/P00`#P04``J'^``/P00`# +MP00``\$0``/!(``#P3```_X```/4'@`#:&L``_L```,/_@`""](``T`U``*_ +M`P`#_P```J;\``/P00`#P0<``J#\``/P00`#P08``J#^``/P00`#P04``J'^ +M``/P00`#P00``\$0``/!(``#P3```_X```/4'@`#:&L``_L```,/_@`""^H` +M`T`X``-`/0`#_P```VJ$``-J@0`#[````TA5``/_```"M\```VA5``-H:P`# +M2`H``K]_``)H^``"LN\``Z"!``*_PP`"0`\``T`E``*S_P`"L?\``D]>``/P +M`@`"N?,``D(I``*\`@`"3%P``_`!``*S^P`#:&```TA```./\@`"O/L``D$< +M``)A'P`#:$```VAK``-)?``"M`0``F$4``-I?``#2I0``_\```-A?``#:&L` +M`C%$``/_```#_@```_\```-!20`#_P```_\```-(9``#B$0``ZB```/H\``# +MW/```KQ```+,R``#V,```]0>``(R9@`#84D``TAD``*T$``"1B0``_`"``/T +M```!S)D``TAD``-(-@`"M$```K4$``)$0``"15@``F1%``',60`"M#P``D1` +M``/P0P`".KT``_0```',*P`#0!0``_\```/_```"PSX``_!!``,#/@`#8!0` +M`K#_``*Q_P`"LO\``K/_``-JD``#^`,``TAD``.,Z@``\@@``DP,``',=0`# +M2#0``KP$``),P``"#&0``.((``-)/0`"OQ```D1/``/P!``"O_\``BT$``*_ +M4``"+00``K\(``(M!``#]``````#:"T``VGM``-(R``"N/L``D(H``-HR``#2)@``K@@``)@"``# +M2+$``VB8``)D2``#:+$``\$.``/!'@`#P2X``\$^``-C,``#8W```V,T``-C +M=``#8S@``V-X``/T```!S/```T@(``*X]P`"0`@``V@(``-(*``"N-\``D,X +M``-(+0`#:"@``VGH``)'>``#:"T``VGM``-(R``"N`0``F(H``-HR``#2)@` +M`KC?``)`"``#2+$``VB8``)$2``#:+$``K`#``/!$``#P2```\$P``-C,``# +M8W```V,T``-C=``#8S@``V-X``-)?``"M/L``D$4``-I?``#:&L``_0```', +M*P`#2,H``K`$``*Q0``#P2@``F@@``-HR@`#P8(``VC*``)H(0`#:,H``\&" +M``-HR@`#[````_@#``,/_@`"#04``^P```(R8``#:&L``\$.``/H$``#Z"`` +M`^@P``.D$P`#V!```]Q```/^```#U!X``VAK``-II``#Z````_X```/4'@`# +M:&L``VFD``*@W@`#\`,``T)@``/T```#\$$``T)<``-"60`"H-X``VFD``/P +M`P`#0F@``_0```/P00`#0F0``VFA``/^```#U!X``VAK``-H:P`#[````C)@ +M``-H:P`#0E8``\$.``/H$``#Z"```^@P``.D$P`#V!```]Q```/4'@`"OP(` +M`BT$``-H:P`#::0``VFB``/H```#_P```]0>``*_`@`"+00``VAK``-II``" +M,F```VAK``/L```#:&L``C)@``*Q#``#Z````Z`#``/<```#V!```^@```/H +M$``#Z"```^@P``/^```#U!X``VAK``/[```#^P```XCC``/X`P`#_@```]0> +M``-H:P`#^P```PB.``(-6@`#[````"'K``/H4``#Z&```^AP``*Y"``"N,`` +M`]R!``/8D0`#0E```_@#``/_```#:D0``^@@``,!'@`#:D0``_X```/47P`# +M:&L``\&/``*_$``"+00``K09``/^```#U%\``VAK``*_$``"+00``\'X``-) +MI0`#_P```_\```/!!``#P14``X+@``)B)@`#P3<``VFD``*Y"``#"9X``@V' +M``-II0`#[````J&^``/P#@`#T!X``P^^``*Z/P`#``X``D`*``,!'@`"01H` +M`P(N``)"*@`#`SX``D,Z``/4'@`##_X``@V0``/[```##,X``@V+``/L```" +MH;X``_`.``/0'@`##[X``KH_``+`#@`"0`H``L$>``)!&@`"PBX``D(J``+# +M/@`"0SH``]0>``,/_@`"#:0``_L```,,S@`"#9\``^P```/0G@`#T!\``KP_ +M``)(C``"29P``DJL``)+O``"1`P``D4<``)&+``"1SP``KP@``+`A``#H``` +M`J-(``/P00`"P`P``L&5``.A$``"HUD``_!!``+!'``"PJ8``Z(@``*C:@`# +M\$$``L(L``+#MP`#HS```J-[``/P00`"PSP``KP'``*CW``#\$X``W)T``-2 +M=@`#_P```_\```/^```#U!X``VAK``/[```#<``&(P``/_```"H;X``_!"``#QY0`#[````J'.``/P00`#"[X` +M`PS.``#9YP``XC```TI```!:"0`#_P```_\```*@O@`#\$(``Z````.B(``# +MT%X``&'\``!9XP`#H@(``D`)``)"*0`"I8X``@X\``,(C@`"H`T``_`+``!! +M^0`"Q$\``\%4``*@O@`#\$8``]1>``+$3P`#P50``]1>``+$3P`#P50``J6N +M``(.3``#"JX``J`M``/P"P``4?D``L9O``/!=@`"H+X``_!&``/47@`"QF\` +M`\%V``/47@`"QF\``\%V``/47@`##,X``@Y-``)KB@`"#A$``^P```-"<``` +M4@D``X_L``.(Z@`#JJ```J2N``/P!@`"H4@``_!!``+$2``"H6@``_!!``+& +M:``#BN```J9/``/P0P`#!$@``P`(``,!&``"IF\``_!#``,&:``#`B@``P,X +M``,*K@`"#F```\%4``/!=@`#U%X``V)P``/L```#P6(``P9N``/<$``#V``` +M`]">``/_```#_P```DB%``)H@P`#P9@``\&H``/!N``#U)X``_L```,&;@`" +M#G4``^P```/!$``#P2```\$P``*@W@`#\`@``VD(``-I#``#:1```VD4``-I +M&``#:1P``_0```/P1@`#:2```VDD``-I*``#:2P``VDP``-I-``#[````\$0 +M``/!(``#P3```J#>``/P!P`#:,P``VC0``-HU``#:-@``VC<``/T```#\$4` +M`VCL``-H\``#:/0``VCX``-H_``#[````TG4``/_```#@.4``D$#``-)T@`# +M_P```D`*``-)P@`"I1```_`!``-)Q@`#[````]">``/[```#_P```_\```/4 +MGP`#^P$``P_^``(.M``#[````_@!``*_!``#2F0``_\```/_```"00\``@Z_ +M``/X`P`#:&L``_\```/_```#_@```^P```-*9``#_P```K\(``)!#P`"H!\` +M`@[K``-`$@`"M1```J4E``/P!``"OP(``FJO``/T```!SN@``L15``*E)``# +M\`0``K\"``)KOP`#]````<[H``+$10`"I20``_`$``*_$``":J\``_0```'. +MZ``"OQ```FN_``#QY0`#8!(``B[L``/L```#2G```_\```/!P@`#0"X``K`! +M``-JJ``#_P```_\```/_```#2JP``K0"``-JJ0`#P````\`1``/`(@`#P#,` +M`TJM``*_D``"H,\``_`%``/`1``"OP\``D]/``/T```#\$$``\#T``*@W@`# +M\`L``T`9``/_```#_P```F1```)E40`"9F(``F=S``-@&0`":J\``_0```/P +M20`#0!T``_\```/_```"9$```F51``)F8@`"9W,``V`=``)KOP`#8"X``^P` +M``+$1@`#:JD``_\```/_```#_P```TJL``/L```",F```VAK```)U@`"L,`` +M`]P```/8$``"H/X``_`$``/H```#Z!```^@@``/H,``"H/X``_!$``*P50`# +MP1```\$@``/!,``"H/X``_`$``*T_P`#P50``\%D``/!=``"H/X``_!$``*T +MJ@`#P50``\%D``/!=``"O`<``J/^``(/G@``0?\``_\```/_```"H(X``@]D +M``*@W@`#\`,``T!"``/T!``#\`$``T!&``#J,0``:@```J3>``/P!``#P(@` +M`\"9``/`J@`#P+L``F`(``)A&0`"8BH``F,[``)D2``"95D``F9J``)G>P`` +M:C$``_\```/_```#_@```]0>``-H:P`#^P```PS.``/^```#U%X``VAK``/[ +M```##,X``@]D``!!_P``8@```_\```*@C@`"#XD``T!*``*DS@`#\`0``\"( +M``/`F0`#P*H``\"[``*DW@`#\`(``\&*``/!FP`"N@\``DJH``.+I@`":JL` +M`KOP``)+N``#I[8``FNW``/T!``#\`,``^A@``/HH``#Z+```K3P``)@2@`# +MP1```\$@``/!,``#:H0``J#^``/P`P`"M/```_0$``/P`0`"M`\``F!+``/! +M$``#P2```\$P``-J@``#[````_X```/4'@`#:&L``_L```,,S@`"N0,``J#Y +M``/P1``#Z$```^A0``/H8``#Z'```_X```/47@`#:&L``_L```,,S@`"#ZH` +M`K#P``*Q_P`"H/D``_!"``/H```#Z!```\$A``/!,0`#:H0``VJ```/L```" +M,F```VAK```)U@`"L,```]P```/8$``"M/\``\%D``/!=``"O`<``_X```*U +M_P`#U%X``VAK``/[```##,X``_X```*U[P`#U%X``VAK``/[```##,X``@_% +M``*U_P`#:H4``K#P``/!$``#P2```\$P``-J@``#2F(``B_O``/H\``"+_L` +M`VIB```)U@`"L,```]P```/8$``"M/\``\%4``/!9``#P70``KP'``/^```# +MU%X``VAK``/[```##,X``@_G``(R6@`#[````TID``*T@``"0`0``VID``/L +M```"L`0``J#P``/P`P`"+R4``_0$``/P`0`"*\0``^@```/````#P1```K+] +M``*S_P`#:&````HM```Q_@``&?T``K`*``*@W@`#\$$``K`,``.!%@`"8`$` +M`K$6``*D/@`#\`$``K,$``.&:@`"L@(``K0$``*C_@`#\`,``J#T``/P`0`" +ML@0``F(F``-J8``#C^$``BT$``-H:P`#_P```_X```/L```#2F```_\```/H +M,``"8`X``VI@``-*9``"M/(``D`$``-J9``#[````K`!``/H$``#Z"```^@P +M``-J8``#[````&HQ``-`!``#_P```K@$``)%X``"H%X``_!$``*@W@`#\$(` +M`T`D``/_````8>D``_\```/_```#W,```X_J``*@W@`#\`$``^CP``/8\``# +MC.0``\&R``-)/0`"H-X``_!!``-)00`#_P```D1N``/P`0`"O`<``D`(``/P +M0P`"+8L``_0```/P00`"+9\``D1N``/P"0`#Z,```ZMB``.E8``"15X``_!# +M``(MBP`#]````_!!``(MGP`#[````&HQ``-`*``#0"$``KA```)(@``#\`,` +M`D9N``/P`0`#[````%'#``*@W@`#\`,``%G"``/T```#\$$``%G!``/_```# +MW*```]BP``-`!@`#_P```_\```)`Z``#\`,``J#>``/P00`#0"8``_\```/_ +M```#24$``J`.``/P0P`"H-X``_!!``/!10`"14X``_!#``.,Y``#]````_!! +M``.,XP`#B9@``ZJ<``*@K@`#\`,``BV+``/T```#\$$``BV?``-`!@`#_P`` +M`_\```-)00`"0(X``J`.``/P0P`"H-X``_!!``/!10`#Z,```ZM"``)%3@`# +M\`<``Z5```)%7@`#\$,``BV+``/T```#\$$``BV?``/L```"H-X``_`#``-( +M(0`#]````_!!``-()0`#_P```KL!``.B9@`#@68``Z$6``.'=@`"8"<``P`+ +M``.G!@`#@@8``F8A``*@W@`#\`0``V@A``-JB0`#]````_!"``-H)0`#:HT` +M`^P```./[0`"+00``^@P``."X``#Z!```^@```-H,``#C^T``BT$``-)G``# +M2=4``T`J``*T$``"1$<``K4"``)%6@`#A50``D1%``.D0``"MO<``D(F``)B +M)``#:9P``^CP``-)<``#Z'```K8!``/!40`#P4```V@Q``*X_``#P5,``\%" +M``)%6``#270``C%$``-H,0`#P5$``\%```(Q1``#:#$``\%3``/!0@`#29@` +M`C%$``-H,0`#P5$``\%```(Q1``#:#$``\%3``/!0@`#29P``C%$``-H,0`# +MP5$``\%```(Q1``#:#$``\%3``/!0@`#2.@``C%$``-H,0`#P5$``\%```*W +M$``",40``V@Q``/!4P`#P4(``C%$``-H,0`#[````KP#``-)/0`#2,```J#> +M``/P00`#2,0``K8$``)&9``#\`0``X;*``/!?``"8B8``F$7``*@W@`#\`,` +M`VC```/T```#\$$``VC$``-`*@`"M@@``X?&``)&:``#\`$``F,W``*@W@`# +M\`,``VC```/T```#\$$``VC$``/L```","X``TD]``-`*``"OP@``KP$``)/ +M#P`"3$P``F#\``/P00`#[````K0!``(R`@`",0D``J'^``/P"0`",<,``C`H +M``-`*``"O`@``_\```)"+``#\$(``_0```/P0@`#Z$```C("``/L```#_P`` +M`_\```/_```#[````V%(``-A00`#848``V)_``/!#@`#Z!```^@@``/H,``# +M:.@``^@```/_```#:.@``T%(``/_```#[````C)@``-H:P``"=8``^@```.@ +M`P`#W````]@0``*\`P`"L/<``J#^``/P00`"L'\``\$0``/!(``#P3```K3_ +M``/!5``#P60``\%T``/^```#U!X``VAK``.@`0`#H1$``Z(A``.C,0`#^P`` +M`_X```/47@`#:&L``_L```,,S@`"$6H``K#_``*\"``#P1```\$@``/!,``# +M:H```J3^``'1A``"H/P``_`"``-JA``#[````K#W``.A`0`#HA$``Z,A``-J +MA``#[````TD]``/_```"N(```F1(``-I/0`"L`$``K$"``*R/P`"0B\``K,` +M``-J:``"L````K$```*R```"LP(``VIT``*Q`0`"L@@``K,```-J>``"L`$` +M`K(```-J?```$>```K#```)`#P`#H`(``F`.``*Q```#HB(``K,!``-J9``" +M,EH``_\```/_```"+KT``KA_``)$2``#:3T``^P```/H```#Z!```K(#``*S +M```#:#```^P```-`+``#_P```_\```/H(``#Z#```V`L``/H```#Z!```V`8 +M``-@'``#[````&HQ``*P`0`#Z!```^@@``/H,``#:F```K\!``(O]``"OQ`` +M`BT$``*\%``#2F```K_W``*Q$P`"0`\``F`.``-J8```,?X``#G]``*\B``" +MM?X``X9J``)B)@`"I'X``_`!``*S!``"0`4``F`,``-J8``#2I8``T`I``*\ +M!P`#_P```D1,``.%1``"Q5X``\'%``/H0``#Z&```^AP``-JD0`"M/\``K5_ +M``*V_P`"M_\``VAA``-H:P`#_P```_X```,)G``#\$4``\"9``,*K@`#\$(` +M`\"J``,+O@`#:I(``X````.@```#:F```K\0``(M!``#[````T`J``-'+``" +MH-X``_!!``-';``"MG\``X5,``)`!@`"29X``_`!``)@!0`#P1```\$@``/! +M,``"H-X``_!$``-G+``#9S```_0```/P0@`#9VP``V=P``-'-``"H-X``_!! +M``-'=``"MM\``X5(``)`!@`"8`4``\$0``/!(``#P3```J#>``/P1``#9S0` +M`V``#2,```J#>``/P00`#2,0``K8_``)")@`" +MML```J!.``/P`0`#Z&```F(F``*@W@`#\`,``VC```/T```#\$$``VC$``/L +M```#29@``K@/``*Y]0`#Z#```\$N``*@S@`#\`(``F`(``)!&0`#:#```T@( +M``*X0``"H,X``_`"``)@"``#:`@``^P```-A4``#854``V%:``-A7P`"+`4` +M`T%0``-!50`#05H``T%?``/_```#_P```^P```*P_P`"L;\``K+_``*S_P`# +M:&```^P```*P?P`"L?\``K+_``*S_P`#:&```^P```+$3@`#\$H``L5>``/P +M2``"QFX``_!&``+'?@`#\$0``K3_``*U_P`"MO\``K?_``/L```"H```^A```*@`0`#\`$``\%.``(T7@`#2`@``KC^``)! +M&``#:`@``KP```(T"0`"-#H``T`!``/H````@C$``D1.``/P`0`")!L``T`! +M``/_````\C$``D5>``/P`0`")!L```(*``.!X``#_P```J00``/P`@`#P4X` +M`C1>``*\`0`"-`D``C0Z``*_`P`"-N0``C-%``(NJ``"OQ```D_[``'2X``` +M>``(N@@`"+J@``X3B``/!R0`#Z````K$#``*R"@`"LRT``D1)``/P +M`0`"LR\``^A0``(N<0`#@.H``BYQ``*X+P`"M`(``D1,``/P`0`"N"T``\&8 +M``/!J``#P;@``V,J``-C:@`"+J@``X'B``.@X0`#HY8``X+D``+"+@`#Z%`` +M`BYQ``.@XP`"+G$``BZH``.`Y0`"0*```\$0``/!(``#P3```V2H``-DZ``# +M@.```H((``)"`@`#@B0``)'4``/L```"+J@``TEP``)$C@`#\$,``K7S``)" +M)0`#:7```^AP``/!;@`#P5,``\%"``-H,0`"1)X``_`&``-)G``#I.$``F(D +M``/!4P`#P4(``V@Q``)$C@`#\$T``TF<``.$Y0`#I><``D`$``)!%0`#I(@` +M`X1```.%1@`"8`4``F$4``/H,``#P2X``V@P``-#I```(=0``K7/``)`!0`" +M8`0``\$0``/!(``#P3```V.D``-CY``"1$0``_`!``(VWP`#@80``Z`8``." +M!@`"8`(``^C0``(NE@`#P=X``BZ6``-)T0`"+J@``^A@``*E$``#\`$``K9` +M``)&=@`#IFH``TB0``.DN@`"H$X``_!!``*T!``"M0,``J!%``/P00`"M`$` +M`K7P``)!%0`"810``K?^``)`!P`"8`8``VB0``-HJ``#:)0``VBL``.@I@`# +MP1```\$@``/!,``#9"0``V1D``.*M@`#2"$``K@#``)F:``"N0\``KO^``)& +M:0`"9FH``D=[``-H(0`#:HD``V@E``-JC0`#2`@``T@A``)A'@`#:`@``TC( +M``*X0``"N3\``F`(``-HR``"0`D``VC(``/L```#0"P``KA```*Y@``#Z+`` +M`TJE``)(&``#\`$``KLP``))&0`#\`(``KK```)KN@`"95L``VJE``-(G``" +MO'L``D`,``-HG``#:*```VBT``-HN``#2)```X3B``.EYP`"014``F$4``*U +M_@`"0`4``VB0``-HJ``#:)0``VBL``-).``"M0,``F(E``*U\P`"0B4``VDX +M``/HP``"-`D``C0Z``/H```"L0,``K()``/H,``#Z%```BYQ``.`Z@`"+G$` +M`K`$``/!$``#P2```\$P``-C)``#8V0``K`@``/!$``#P2```\$P``-C*``# +M8V@``C;?``-("``#2"$``ZCM``)!&``#:`@``ZCK``)&:``#P#X``D53``-H +M(0`#:HD``V@E``-JC0`#Z$```C1>``/H\``"/B(``K\!``(^(@`#[````T`I +M``/_```"N"H``D)>``/P`0`"N&0``J#.``/P00`"N!```\&8``/!J``#P;@` +M`V@`# +M0[(``K`'``*Q*``"0EX``_`!``*Q.``"H,X``_!!``*Q```"2(```FB!``/! +MF``#P:@``\&X``-CL@`#8_(``^P```-)=``#P6X``^AP``.(2``#P%X``X59 +M``)")0`"8B@``VET``/!0@`#P5,``V@Q``/L```"OP,``C;D``-("``"N/X` +M`D$8``-H"``#0"@``KP$``*_`P`"3,(``_`#``(]RP`#]````=2+``-(5``" +MO&```F(L``-H5``#278``KP0``)DK``#P5L``\%N``/H<``#:#$``C%$``-( +M5``"O)\``D(L``-H5``#P4H``V@Q``(SJP`#0D4``C)F``-B10`#[````&HQ +M``(M"```\>4``C`H``(KQ``#0`0``T`*``*\`P`"OP0``D$<``,&\0`"0`\` +M`_`!``/!:@`"Q&X``K4(``(XK@`#0`0``^CP``#Z!@`"LD```D(@``'4\0`# +MCP0``Z_X``#Z`P`#2<$``KP/``)(SP`#J(```XF"``*ZXP`"1$H``F1)``)) +M_@`#B9(``KK[``)%6@`"95D``VG!``.!A@`"8($``BZ6``/H```"H-X``_!! +M``*P0``"L0,``K()``*S"0`"1.\``_`!``*S#P`#Z%```BYQ``*C_``!U/$` +M`^C```#AS@``X>X``C97``-`&``"H-X``_!!``-`'```0>X``&'.``)@`0`" +M8`(``F`#``*A#@`#\$(``LB.``#![@`"N@(``KL?``+,R@``X4``_0` +M``'4J@`"S_X``/H#``#"!@`#]````=2J``/HP```X@,``^@P``(V:P`#W.`` +M`K\(``/8\``"L"```\$0``/!(``#P3```K\1``/4'@`#_P```_L```,/_@`" +M%/T``C97``!B`P`"L````]P```/<`0`#C\(``K!```+`#P`#V````K`_``)! +M#P`"L,```L`!``/8`0`#U%X``]`?``*_$``"H<\``=4>``*@W@`#\`,``\$* +M``/T!``#\`$``\$+``/4'P`#]````=4E``*@W@`#\`,``\$J``/T!``#\`$` +M`\$K``/4'P`"-@\``T`&``*P'P`"L2```\$N``)!&``#\`$``L(N``+,P@`` +MX@,``J7```(5`@`#2I0``_\```-@O``#0`0``]S@``*_"``#V/```]SA``*_ +M+``#V/$``K\(``.L%@`"I<\``_!#``/`S``";,\``LS.``*_"``#T!X``]!? +M``/!B0`#P9H``\&K``+$0``#H$```L`,``/!L``"Q5$``Z%0``+!'``"IAL` +M`_`!``/!L0`"QF(``Z)@``+"+``"IBL``_`!``/!L@`"QW,``Z-P``+#/``" +MICL``_`!``/!LP`#U!X``]2?``/[```#^P$``P_^``(50P`#03@``T%)``-! +M*@`"O`X``J,!``/P`0`#P0$``J,"``/P`0`#P0(``J,#``/P`0`#P0,``J,( +M``/P`0`#P0@``J,)``/P`0`#P0D``^@0``*F#``#\`,``\````.`!@`#H08` +M`\$!``*C10`#\`$``\%%``*C1@`#\`$``\%&``*C1P`#\`$``\%'``*C2@`# +M\`$``\%*``*C2P`#\`$``\%+``/H(``"IDP``_`#``/`1``#A$8``Z)&``/! +M,@`"H-X``_`#``-DJ``#]`0``_`!``-DZ``#W.```K\(``/8\``#T%X``K\$ +M``/<\0`"OX```J#>``/P00`"O\```]CQ``*\$``"N`$``KD#``*Z#P`"H4P` +M`_!%``/`1``"1$H``P0$``/T!``#\`(``P1*``+$0``"H5P``_!%``/`50`" +M15H``P4%``/T!``#\`(``P5:``+%4``"H6P``_!%``/`9@`"1FH``P8&``/T +M!``#\`(``P9J``+&8``"H7P``_!%``/`=P`"1WH``P<'``/T!``#\`(``P=Z +M``+'<``#U%\``_L```/[`0`#T%X``PB.``(5J0`"N`$``\$!``/!$@`#P2,` +M`PF>``(5J0`#1*@``J#>``/P00`#1.@``J%,``/P10`#P$0``D1*``,$!``# +M]`0``_`"``,$2@`"Q$```J%<``/P10`#P%4``D5:``,%%0`#]`0``_`"``,% +M6@`"Q5$``J%L``/P10`#P&8``D9J``,&)@`#]`0``_`"``,&:@`"QF(``J%\ +M``/P10`#P'<``D=Z``,'-P`#]`0``_`"``,'>@`"QW,``]1?``(L]P`"-&L` +M`C`H``(O[P`#[````BZH``.CE@`"-FL``X#E``)#H``"-G0``_0```'6`@`# +MP9```J'/``/P`0`#P9(``V)U``#)S@`#W.```K\(``/8\``#W.$``K\L``/8 +M\0`"OP$``\$$``(V,0`#0G4``K\!``/_```#P04``C8Q``-"=0`"OP$``_\` +M``/!!@`"-C$``T)U``*_`0`#_P```\$'``(V,0`````/4GP`#^P```_L! +M``.@```##_X``A8R``/L```"LQ```J7#``/P!@`#P#P``X,V``.C-@`"-G0` +M`_0```'69``"LP\``LS.``)#/``"-FL``C&X``(L]P`"-&L``K\8``(X7``" +M+NP``^P```*Q!``"L(```J#>``/P00`"L,```K()``/H4``"+G$``^P```/! +M`P`#P1,``\$C``*@W@`#\`,``V2H``/T!``#\`$``V3H``/L```#0`0``KR` +M``/_```"3,```=:>``-!`0`"H-X``_!!``-!!0`"L00``K"```*@W@`#\$$` +M`K#```/<$``#V````\&$``(VNP`#P84``C:[``/!A@`"-KL``\&'``(VNP`" +MH-X``_`#``-DH0`#]`0``_`!``-DX0`#]````=:X``*Q!``"L(```J#>``/P +M00`"L,```]P1``/8`0`"L0$``K`(``*@W@`#\$$``K`L``/<$``#V````K\( +M``(NM``#00$``J#>``/P00`#004``J#>``/P`P`#9*D``_0$``/P`0`#9.D` +M`BSW``(T:P`#[````\&8``/!J``#P;@``K(!``/4G@`#^P```P(N``(6OP`# +M[````K$$``*P@``"H-X``_!!``*PP``#W!```]@```*Q`0`"L`@``J#>``/P +M00`"L"P``]P1``/8`0`"OP@``BZT``-$J``"H-X``_!!``-$Z``"H-X``_`# +M``-A```#]`0``_`!``-A!``#[````TL,``*U_``"014``VL,``/L```#2PX` +M`\#/``)JKP`#:PX``C%$``)*K``#:PX``^P```*_`P`"-N0``TG```-)U0`" +M3`X``_!"``/T```!URD``TG```.'=@`"IG```_!"``/!$@`#Z````Z(6``.! +M%@`#H18``TB1``*\\``"15P``F52``*\!``"0PP``Z,R``*\_@`"1$P``F1# +M``-HD0`#:)4``VBI``-HK0`#P4$``\%1``/!80`#P7$``V0A``-D)0`#9&$` +M`V1E``*\`@`"0@P``X(J``-(G0`"LW\``D1#``)D0@`#:)T``VBA``-HM0`# +M:+D``J$.``/P`@`"-M\``K`0``/!$``#P2```\$P``-CH``#8Z0``V/@``-C +MY``#27P``K3[``)!%``#:7P``VAK``/T```!S`4``C`H``(O[P`#0````_\` +M``/_```#H`P``Z$<``.!$``"81```P\>``/HT``"H/X``_!!``*]`0`#P4``_\```)&8@`"9FH``VGE``/T!``"%W8``J/^``(7R@``T=`` +M`J#>``(7GP``T=$``LW>``/T!``"%U4``$'1``/_```#_P```J"H``(7R@`" +MH:@``_!(``-((0`#`XH``X,P``)G4``_\```)&8@`"9F@``VGE``-()0`#`Z@``X,P +M``)G4``KB```)G>``#8!$` +M`TF8``*U!``"814``VF8``-("``#_P```X3(``)@!``#:`@``_@#``/L```` +M:C$``^@```""#```@<\``CC*``-`)``#_P```_\```)`#@`#\$L``T`0``*\ +M!``#W,```X_J``*@W@`#\`$``^CP``/8\``"O`D``\&Q``(MBP`#0"0``_\` +M``*\`@`"0`P``_!+``-`$``"O`0``]S```*_P``"H-X``_`!``*_@``#V/`` +M`XSD``/!L0`"+8L``BO$``*T!@`"M0@``K8$``(XK@`"OQ@``CA<``(X@P`" +MOP```B_T``-*<``#_P```_\```*RD``#:G```K\3``(X7``".(,``T`D``/_ +M```#_P```D`.``/P2P`#0!```KP$``/``/P`0`#Z/```]CP +M``*\"0`#BQ```BV?``-`)``#_P```KP"``)`#``#\$L``T`0``*\!``#W,`` +M`K_```*@W@`#\`$``K^```/8\``#C.0``XL0``(MGP`#2G```_\```/_```" +MLH```VIP``*_&``".%P``CB#``*_```"+_0``TIP``/_```#_P```K*0``-J +M<``"OQ,``CA<``(X@P`#0"0``_\```/_```"0`X``_!+``-`$``"O`0``]S` +M``./Z@`"H-X``_`!``/H\``#V/```KP)``/!L0`"+8L``T`D``/_```"O`(` +M`D`,``/P2P`#0!(``KP$``/``/P`0`"OX```]CP``.,Y``# +MP;D``BV+``(X[``#[````^@```/````"L;\``\$@``*S_P`#:&```C`H``(O +M[P``"BT``!'^```9_0`"L`(``J#>``/P00`"L`0``X$6``)@`0`#@BH``K&$ +M``)B(0`"I#X``_`!``*S!``#P1\``VI@``-*9``"M(```!'L``)`!``"M`,` +M`F`$``*S$``#:F0``BZ]``*_"``"3_```_`!``#R#``#[`````(,``/_```# +M_P```J4.``/P`0`#[````^@```""#``#0!(``_\```/_```"1(X``J!.``/P +M`0``\>4``K]```*@W@`#\`,``FJO``/T```#\$$``FN_``-@$@`"+NP``'G/ +M``/_```#0"```J#^``/P00`#[````J#>``/P!0`"P`X``_!!``*P_P`#]``` +M`_!#``+!'@`#\$$``K'_``-@(```\<\``^P```*P`0`"L0(``\$D``/H,``# +M:F@``\$E``*P$P`"L0(``X(F``/H,``#:G```K`A``*Q`@`#P28``K,!``-J +M=``"L`$``K$"``*R#P`"LP$``VIX``-*?``#_P```K````*Q```"LP0``VI\ +M``/L```"L`$``K$1``*R$``#:D0``K$0``/H(``#:D0``J#>``/P`P`"NU,` +M`_0```/P00`"NUL``-GL``-("``"M$```('F``)@!``#:`@``T@!``*POP`" +M1$```V@!``/H```"L4```^@@``/H,``#:D0``K`!``/H$``#Z"```^@P``-J +M8``#[````C`H``(O[P``(>8``_\```-("``#_P```\$$``-H"``#[`````HR +M``!J,0`#_P```D`>``/P00`#[````CC*``*_```"+_0``#(:``/_```"M0D` +M`Z9B``+&;@`"Q&X``CBN``-`*``#Z/```J#>``/P00`"OT```/G@``.@#``` +M@<4``T`8``-`'0`#0"X``&'E``/_```#_P```V%0``-A50`#85H``.''``-` +M$```>>```KP$``/``/P00`#0!P``T`M``/_```#U!X``]1? +M``*_`0`#W/```K\```.(P@`"S_@``]CP``/$```#Q!$``\0B``/$,P`"H-X` +M`_!!``/!9P`"M1$``D1E``/$1``"P`0``K4B``)$90`#Q$0``L$4``*U1``" +M1&4``\1$``+")``"M8@``D1E``/$1``"PS0``]0>``!YQ0`#0G4``T)R``)/ +M_@`#\$(``L`!``+"(P`"H00``_!&``*E"0`#\`0``\&,``/!D``#P:P``\&P +M``*C"0`#\$(``\&L``/!L``#8G(``T)&``*A)@`#\$8``J4I``/P!``#P8P` +M`\&2``/!K``#P;(``J,I``/P0@`#P:P``\&R``-B1@`"H/X``=FN``-"3@`" +MH14``_!&``*E&0`#\`0``\&,``/!D0`#P:P``\&Q``*C&0`#\$(``\&L``/! +ML0`#8DX``T)*``*A-P`#\$8``J4Y``/P!``#P8P``\&3``/!K``#P;,``J,Y +M``/P0@`#P:P``\&S``-B2@`#8G0``_L!``*Q$``"S,X``.'.``*@P0`!V3<` +M`T)P``-"10`#_P```L@"``.H@``"RD8``ZJ@``-"3``#0DD``_\```+)`@`# +MJ9```LM&``.KL``".=L``T`0``!YX``"O`0``]S```/8\``"O`D``\&Q``(M +MGP`","@``B_O``-!4``#054``T%:``!AQP`#_P```_\```-@&``#8!T``V`N +M``#AY0`#[````KLA``*[$````<4``_\```/_```"0`X``=H3``.IA``#JZ0` +M`KP/``.(@``"2(P``XJ@``)*K``#2)P``TBA``*@W@`#\$(``TBT``-(N0`# +MP1@``\%:``.,%@`#CU8``F$<``)E7P`"H-X``_`$``-HG``#:*$``_0```/P +M0@`#:+0``VBY``-*Z``#2NT``J#>``/P0@`#2O```TKU``*\[@`"0`P``D1, +M``.(E@`";)@``F`,``.*M@`";+H``F1,``*@W@`#\`0``VKH``-J[0`#]``` +M`_!"``-J\``#:O4``^P```*_!0`"O````J#>``/P00`"O$```]SP``/8P``" +MO(```FB,``)IG``":JP``FN\``/!"``".BL``\$)``(Z*P`#P0H``CHK``/! +M"P`".BL``]2>``/[```#U)X``^P```/!$``#P2```\$P``/4'@`#^P```]0> +M``/[```#[````&HQ``(M"``#Z````K%@``/H(``#Z#```VF@``-)F``"N`\` +M`K7U``*S```#P2X``F`(``)!%0`#:#```K\!``(M!``".,H``C`H``-`+``" +MOP0``_\```)/\``#K_(``^CP``(O]```,AH``_\```*U"0`"Q&X``CBN``/H +M\``"H-X``_!!``*_0```^>```%G'``!YX``"O`0``]S```/8\``"O`D``BV+ +M``/HP```X``/P00`#P:L``&'.``!YQ@`# +MU%\``_L!``/07@`"NP(``J'^``/P00`#P4H``J#^``/P00`#P5H``J#[``/P +M00`#P6H``J;[``/P00`#P7H``]1>``/[```"L!```LS.``*EP``#\`8``.'. +M``/!C``#P:P``CG;``/T```!VFL``K$$``+/_@``^<8``J'Q``':I@`#Z+`` +M`-G.``/!BP`#P:L``CG;``!YX``"O`0``]S```/8\``"O`D``\&^``(MBP`# +MW.```KM```/8L``#]````=IK``(X[``"N`@``KH(``(YVP``6<<``'G@``*\ +M!``#W,```]CP``*\`P`"R[P``KP)``(MGP`#2`@``K1@``)@!``#:`@``TF8 +M``/_```"L@$``^@P``-H,``#[````K0$``)&-``"H&0``=K*``/H\``"/?0` +M`K\!``(]]``#:&L``T))``(R9@`#8DD``^P```-"30`",F8``V)-``-(9``# +M^`$``KT,``))T@`"H-D``_!&``*_`P`".RD``K\#``*]```".PH``^P```*] +M!``"2=(``_`&``*_`0`".RD``K\!``*]```".PH``^P```*]"``"2=(``_`& +M``*_`@`".RD``K\"``*]```".PH``^P```*]8``"2=(``J#9``/P1P`"OP,` +M`CNP``*_`P`"O0$``KP!``(["@`#[````KT@``))T@`#\`<``K\!``([L``" +MOP$``KT!``*\`0`".PH``^P```*]0``"2=(``_`'``*_`@`".[```K\"``*] +M`0`"O`$``CL*``/L```#2&(``DS.``(;'``#@/(``\````.!^``#P!$``DW> +M``/P10`#P````FJ@``)*H0`#]`0``_`#``/`$0`"2J```FJA``-H8@`"L/(` +M`FJ@``*@"@`#\$<``TA```*T"``"M?<``F$4``-H0``"014``VA```-H:P`# +M[````TA4``/H@``"N0,``DO^``/P`0`":(D``KH"``*Y#``"2_H``_`!``)H +MB0`"8S@``VA4``/HD``"M`0``DO^``/P`0`":9H``DOZ``/P`0`":90``TE@ +M``-H:P`#_P```_\```-(90`#_P```DO6``*@O0`!VZ<``DN3``';/@`#0"@` +M`X3P``"B`@`#HB8``C%$``,"+@`!VTT``T@$``*T[P``BBP``D$4``-H!``" +MM8```DO^``/P!0`#2)@``K2_``)#-``"8S4``VB8``)+^@`#\`4``TBP``*T +MOP`"0S0``F,U``-HL``"/>@``K8$``-H,0`#0"@``C%$``)!&@`"&Y```$H! +M``/_```"N(```\"9``.)G``"2_X``_`&``-)/``#2)D``F,X``)D20`#:3P` +M`VB9``)+^@`#\`8``TE```-(L0`"8S@``F1)``-I0``#:+$``DO^``/P!@`# +M2)```TB5``)@"``"9$@``VB0``-HE0`"2_H``_`&``-(J``#2*T``F`(``)D +M2``#:*@``VBM``-`*``#_P```K@$``)!&``#\`$``CQH``-`*``#_P```K@( +M``)!&``#\`$``CTJ``-(0``"N(```DO^``/P`0`"81@``DOZ``/P`0`"8B@` +M`VA```*\`0`#[````TA4``/`B``"0S@``VA4``-"20`",F8``V))``*\```# +M[````T`H``#YNP`"N`@``D$8``/P`0`"/4$``T`H``/_```"N`0``D$8``/P +M`0`"/+<``T`H``/_```"N`(``D$8``(;YP`"2_X``AO*``-)/``#2)D``KA_ +M``)#.``"1$@``VD\``-HF0`"O`(``DO\``(;U``#24```TBQ``*X?P`"0S@` +M`D1(``-I0``#:+$``DO^``(;W0`#2)```TB5``*X?P`"0`@``D1(``-HD``# +M:)4``KP"``)+_``"&^<``TBH``-(K0`"N'\``D`(``)$2``#:*@``VBM``-` +M*``#_P```K@.``)!&``"'`<``CT4``)!%P`#:,@``T@(``*X$``"01@``=P' +M``)+_@`"&_P``T@@``*T`0`"M?P``F$4``-H(``"014``V@@``*\`@`"2_P` +M`AP&``-()``"M`$``K7\``)A%``#:"0``D$5``-H)``"-N0``DO^``(<#@`# +M2)@``K3```)C-``"0S0``VB8``*\`@`"2_P``AP6``-(L``"M,```F,T``)# +M-``#:+```KP#``(]R``#2$```KA_``)+_@`#\`$``D(H``*\`@`"2_P``_`! +M``)!&``#:$```T@(``*X$``"01@``=PQ``-`*``"O`0``_\```),P@`#\`,` +M`CU8``/T```#\$$``CW+``).[@`!W#,``KP(``(]R```>;L``_\```/_```" +M2_X``_`$``-(F``"M#\``D,T``-HF``"O`(``DO\``/P!``#2+```K0_``)# +M-``#:+```TA```*X(``"2($``AQ*``(]Z``"M@(``V@Q``-)?``"N`(``DB` +M``(<40`#27$``CWH``-H,0`#2`0``"(L``/_```#_P```\$4``-H!```>;L` +M`K@```*\`@`#2%0``DO^``/P`0`"N`,``DO\``/P`@`"O`P``FB,``/`B``" +M0S@``VA4``.`^```@@(``^P```-("``"N!```D$8``'<>0`"2_X``_`$``-* +M5``"M`\``F`$``-J5``"NP(``DO[``/P!``#2E@``K0/``)@!``#:E@``DO^ +M``/P!``#2E0``K3P``)@!``#:E0``KL"``)+^P`#\`0``TI8``*T\``"8`0` +M`VI8``-("``"N!```D$8``'``/P`@`"OP`` +M`CWT``*\`@`"2]P``_`"``*_`0`"/?0``\']``/L```"M_P``K8S``*U1``" +MM````TC(``*@_@`#\$$``K0!``*\`@`"H/P``_!!``*T`@`"810``VC(``)@ +M!0`#:,@``_\```)`!@`#:,@``KP"``(]R``#[````T@(``*X$``"01@``=T[ +M``)+_@`#\`0``TB8``*T?P`"0B0``VB8``*[`@`"2[\``_`$``-(L``"M'\` +M`D(D``-HL``#23@``X3R``/`1``"0B0``VDX``/L```#23@``X3R``)B)``# +M:3@``T@(``*X$``"01@``_`!``/L```"2_X``_`$``-(F``"M(```F(D``-H +MF``"NP(``DN_``/P!``#2+```K2```)B)``#:+```^P```-"20`",F8``V)) +M``)!_@`"'64``T.N``*P[P`#_P```DNP``)*L``"2;```DBP``-CK@`"L0(` +M`D'Q``(=<``#0^X``K#O``/_```"2[```DJP``))L``"2+```V/N``-(5``# +MC/@``F(L``-H5``#270``KS?``)$+``#P5,``CWH``-H,0`",40``KP0``)D +M3``#:#$``C%$``-(5``"O)\``D(L``-H5``#270``_\```/!0@`#P5,``CWH +M``-H,0`"0?X``AV3``-#K@`"L!```_\```)KL``":K```FFP``)HL``#8ZX` +M`K$"``)!\0`"'9X``T/N``*P$``#_P```FNP``)JL``":;```FBP``-C[@`" +MO`(``D?^``),_``";,<``K<#``*@?P`#\$$``^C```-(R``"N$```KD_``)@ +M"``"81P``VC(``)`"0`#:,@``\#,``)!'``#:,@``KO\``)*_@`#\`@``T@A +M``/_```"95X``V@A``-JB0`"15L``V@A``-JB0`"N@(``DJO``/P"``#2"4` +M`_\```)E7@`#:"4``VJ-``)%6P`#:"4``VJ-``/L```##,X``=W(``/L```" +M/>@``K8"``-H,0`"M@$``TF>``*\$``"9*P``\%;``-H,0`#29H``KP"``)D +MK``#P5L``V@Q``/_```#270``KP0``)D+``#P5,``V@Q``(Q1``#P,P``D1, +M``-H,0`",40``\%*``/!6P`#:#$``^P```/!;@`"MP,``DW^``/P`@`"O0(` +M`D=]``*]`@`"3?T``_`"``*]`0`"1WT``^P```*X!``"L0(``K"```)/_@`# +M\`$``K#```(^0@`"L0,``K````)/_@`#\`$``K!```(^0@`"L0,``K"```)/ +M_@`#\`$``K#```(^0@`"L00``K````)/_@`#\`$``K!```(^0@`"L00``K"` +M``)/_@`#\`$``K#```(^0@`"3_X``_!'``-'-``#1SD``_\```-G-``#9SD` +M`_0$``/P!0`#1W0``T=Y``/_```#9W0``V=Y``/L```"N`0``^@```/H$``# +MZ"```^@P``)/_@`"'C```V4L``-E,``#930``V4X``-E/``#]````=XU``-E +M;``#97```V5T``-E>``#97P``K$&``*P```"3_X``_`!``*P0``"/D(``K$& +M``*P@``"3_X``_`!``*PP``"/D(``^P```+""``#W!```]@```/<$0`#V"$` +M`]`>``/07P`"O`<``]0>``/47P`#^P```_L```/[`0`#^P$``]`>``/07P`# +:#,X``=Y*``/L```#_P```_\```/_```#_P`` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/VERDE_me.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_me.bin.uu new file mode 100644 index 00000000000..ad4aba2695d --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_me.bin.uu @@ -0,0 +1,194 @@ +begin 644 VERDE_me.bin +M?$"``8@```#40`!_?$"``8@```!\0,`!S$``*,Q``"E\0(`!B````-A``![$ +M$``A)1```I4`__Y\00`!Q!P`)L0@`"38```50``"V4&BI,0;``+8```;S8``&L`^``3,`:'TS#T@!,0]``',```%V$`` +M&]A``!]\0(`!B````,Q!+@',02X"S$$N`\Q!+@!\0(`!B````'Q`P`&,``4G +MS$$N`'`&GQ"``$E)``! +MS,``(]%``"31@``ET<``)MA``">60``,Q"@`+)J`___()``M?EZ`#)J`_YP2 +M+``&!NP``0KL``&:P/__V$``)X```&#$*``LFH#__WQ`@`&(````?$#``<00 +M`##,027,?04```````ET```\Z!HKN````` +MEX```\Z!HK^`````SH&BPX`````$&```@``!0P08``'$)``F?$#``<9K`^08 +MT``P)-0`_P:H``'.I`/DFD``$L0X``?80``>Q#P`(2?\``*7P/_^S(``"Y>` +M``+90:*DQ#\``L_``!K`/@`$S`&A],P](`3$.0`!S```!=A``!_-0:#:S(`` +M"\U!+A29@``"S````LU```A\0(`!B````'Q`P`$8T`'H&-0`,!C8`#0%*`%K +M?$(``7Q"0`&5```'AH```(```86```&I@``!OX``!2.```%[$50`$'X6``K, +M@``+U&$``)6`_HO`.@`$S#DA0,0Y``%\0(`!B````!%4`!!29``@?B8`&LU` +M`!W48@``E8#^@,0@`!V:`/__?$"``8@```#<.@``F4``&R><``&5P``-"[@` +M```%\0@`!",P``08D``$&*``"SAVA_``"```(.P"(`!'X6``K,(0``Q!T``7Q"0`%\0H`!F,`` +M`\WE``"`````SD$A:'@```@``"1X```DR```)1@``"5H```EN```)@@``"97\;@`\4I``( +MEX``'29D`/^```)V?QN`#A2D``B7@``8)F0`_X```G9_&X`,%*0`")N``!,F +M9`#_@``"=G\;@`T4I``(FX``#B9D`/^```)V?QN`#Q2D``B;@``))F0`_X`` +M`G9_&X`.%*0`")N```0F9`#_@``"=A2D``@F9`#_,F@`/!3L``B:@/V7?$-` +M`7Q#@`%\0\`!S```"Y;```;/02%ISX$A:L_!(6O,`2%L@````,_U``"````` +M,F@`/)J`_[/40`!_@````'Q`P`%\00`!P!X``144`!+`(@`"P"8`!)5```3` +M)__[?24`"<`F``!]TH`)?A+`"7TE``I\04`!?$&``@%*`*I',S^",R```N5```)AH```(```K2```+#@``"RH```M&` +M``+7@``"XX```P',P:*D?$"``8@```#`$@@`?$%``7Q"``%]#,`*P!(`!!58 +M``,57``-?='`"1(@`!-^'D`*?DZ`"LZ!HJ3-@:'^?$"``8@````$$"$8Q!0` +M"Y5`___440``S,&BI'Q`@`&(````!!`A!L04``R50/__U%$``,S!HJ1\0(`! +MB````-A```_,P:*DQ!``#YD`__]\0(`!B````!C0`#01%``4Q"0`#99`___, +M02$`?45`"LU!(0',02$"S$$A`\S!HJ1\0(`!B````"38``%\00`!?$%``1&< +M`!!\0@`!?5U`"A5D`!TF9``"E8``"<0\`!^7P/__FD``#<0H`#`6J``"?BH` +M`Q#P`(2?\``*7P/_^S(``"]E!HJ3$/P`" +MS\``&L`^``3,`:'TS#T@!,0]``',```%V$``'Y````!\0,`!!#P`(LR```O/ +MP:*DS```!GQ`@`&(````P!(``7Q10`K,@``+U%4``'Q`@`&(````?$#``5!0 +M`"!\T,`:51P`/WQ!0`%\08`!S(``"]#``(.5P``#P!R``,W!(!"5@/RVC``% +M)]V#```%7"``S```"]1=``"```4O?$#``5!0`"!\T,`:?$%``7Q!@`',@``+ +MT,``A)6`_*B,``4GW8,```5Q`P`(23,``&4P/_^QB<# +MY'Q`P`',@``+S,$A?,Q!(7W$&``D?$$``7Q!0`&60``"S8$A>LT!(7[`-@#` +MP"H`!']/0`D17``!!=P``9=``!3,*2%_Q"4``1IL`#Z6P``'$5P``07<``$) +MW``!F<#__\R```N```27%W0`%R@L`&";0``"*"P`0,[``"/80``GQ#0`+)M` +M__^```2O"=P``9G`___,@``+S"DA?\0E``$6;``?$5P``07<``&:P/_X%/P` +M']@``!^;P/M+Q!``)LP0`_=\0(`!B````'Q`P`%\00`!%1@`'U$4`"`9'``Q +MF8``",T``!U]34`:U%8``)7`^SW$(``=F@#__X````#<.@``P"8`!,S!(6E] +M)0`*S0$A:@NX``+,02%KS$$A;)N`__V9P/V_?$"``8@````D3`#_S$P#`'Q` +M@`&(````Q"``)L1/`P#,@``+S.$A18````#,@``+VL&BI'Q`P`%\0(`!B``` +M`,0,`!J8P``#V$``+X``!.'80``P?$$``7T!0`$55``!)50``9E```DE$``! +ME0#[%,@4`#250``%R!@`&Y6```-]E<`.E<#[#L@@`#/2```RV```'L0@`"$F +M(``!E@#__L`F"$#.02%\S`$A?<0H`"3.@2%ZS`$A?L`J``0$%``$05P`""@L +M`$#.P``CV$``)PG<``&9P/__S(``"\PI(7_$)0`!%FP`'T%<``*:P/_YQ#0` +M+)M`___8```??$"``8@```#$#``3,-```94```/,@``+VP&BI,Q```[$#``2 +MQ!``$S#4```]&``!?5G`"MA``#&9P/_ZV$``$]```#)\0(`!B````,`.`0#, +M```!S,$P2H``!2;80``1Q#P`$9?`__V0````V```$<0\`!&;P/_YD````-@` +M`!'$/``1F\#_]7Q`@`&(````V(``'L0\`"$G_``$E\#__L`X`"_`/@`$SX$A +M^,P](?G$.``F!#P`!7_[@`+$/0`!?_O`!2?\``&;P/_VV(``'Y`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````0.<`!```@`1``4`$@`*`!4`)0`6`"L`%P"Q`!L`-``<`$$`'0!O`!X` +M3``A`+L`)`#9`"4`V0`G`.,`*`#6`"H`WP`L`-D`+0#C`"X`YP`O`.T`,`#Q +M`#(!0@`T`0,`-0#C`#@`_`4`` +M0`.B`$$$7@!"!'D`0P2!`$0"F`!%`AD`1@*C`$<"HP!(`J,`2@,3`%(#'P!3 +M`S(`5P,Y`%\#7@!@`S\`80-1`&@#:P!I`V\`<@-W`',#E`!V`W,`=P-S`'H$ +MN@!]!-,`?@37`(4$W`"&!.$`B@42`(L%$@`/!2,`#P4C``\%(P`/!2,`#P4C +M``\%(P`/!2,`#P4C``\%(P`/!2,`#P4C``\%(P`/!2,`#P4C``\%(P`/!2,` +M#P4C``\%(P`/!2,`#P4C``\%(P`/!2,`#P4C``\%(P`/!2,`#P4C``\%(P`/ +:!2,`#P4C``\%(P`/!2,`#P4C``\%(P`/!2,` +` +end diff --git a/sys/contrib/dev/drm2/radeonkmsfw/VERDE_pfp.bin.uu b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_pfp.bin.uu new file mode 100644 index 00000000000..0e91860c87a --- /dev/null +++ b/sys/contrib/dev/drm2/radeonkmsfw/VERDE_pfp.bin.uu @@ -0,0 +1,194 @@ +begin 644 VERDE_pfp.bin +M?$"``8@```#,@```U$```'Q`@`&(````S(```,S```#40```?$"``8@````D +M3``/,.@``B20``*:@``,?$%``5!8`"!]E<`:F,```]'``!F`````F0```]'` +M`!J`````T<``&X````#$(``5QB0`"I9``6M\00`!?$%```_RU\0,`!?$$` +M`8```,G$$``/Q!P`!)D```3,```2S<```,P```#$&``()9@``H```+TDC``" +MQ!``$,08``B8P``(F0``!<0<``7,```3S<```,P````9F``P@```O1F8`#B` +M``"]Q!P`!,W```#,````S(```-1```!\0(`!B````,0<``3-P```S````,@, +M`!G,@```S$```!!0``)]#0`1510`(-$```/80``#S````'Q`@`&(````Q!P` +M!@8U``P&-@`-`4H`:-\ +M0@`!?$)``94```>&@```@``#F(```YB```.8@``#F(```;$15``0?A8`"LU` +M`"'480``E8#^4\0Y(4!\0(`!B````!%4`!!29``@?B8`&LU``"'48@``E8#^ +M2L0@`!.:`/__?$"``8@```!\0,`!?$$``7Q#@`%\0\`!41``(%/\`"!_OX`: +M?-#`&@0<`!#3@``"V(```M#```+-P``"!!P`!`0@``%\`D`!Q!<``\0;``-1 +MF``@?5E`&L0K``/$+P`#Q#,``\0W``,)W``!4NP`('ZN@!I3=``@?S<`&G\K +M0!)^=D`15J@`/U0`F9 +M@``$S````LP```V```.4%9@``14L``@F[``!F8``,Q4P``R6```#S````H`` +M`Y0$%``0S4```B`_=$+N``!Q#\``YN` +M__V`````S```#I9```/,```"@``#E-H```+$"P`#Q`\``\03``/$%P`#Q!L` +M`\0?``/$)P`#Q"L``Q7\`!\6L``??_/`"13P`!]_\\`)%7``'W_SP`E]B(`" +M?8P/__?$"``8@```#$*``DQ#``#\0T``2:@``% +MFP``!,P``!+/0```S````'Q`P`'8:`/WS(```,S```#40```%-``'YD``+J` +M``+(S(```,Q```#,0```S$```'Q`P`',P``6S,```-1```!\0(`!B````'Q` +MP`'$%``=%-P`'1C8`#Q\U,`*S(```,S```"9P``#F8#]$H```Y3-@``D@``# +ME'Q`P`%04``@C``#%WS0P!K$)``5Q!0`)'Q#@`&60``(Q-8``)E``!G?@P`` +MSZ0`#XP``QO40`!_@````,5?`^Z5P/__V%0#\<5;`_25@``#V!0#\9F`__S% +M7P/N/>```IH```?%8P/KF@``!=^#``#/I``/C``#&]1``'\)W``!S=0#[M@4 +M`_&,``,;?$"``8@```#8```>Q#P`'IO``'^0````V$``'L0\`!Z7P`![D``` +M`(P``Q?$(``5?$#``<`V_P#$$``6P#`__WSU0`E]48`)?8&`'7SS@`F9@``& +MWX,``,^@``^,``,;U$``?X````",``,;?$"``8@```!\0,`!%-P`")7``!DD +MW``0?$$``5!4`""9P``#Q1T``(```SU]%0`:Q1X``'Q"``%\0D`!?$&``7WE +MP`E]XH`/0:P``IJ`_+T&[``#"NP``9K`__\DW``0F<```\4=``"```-`Q1X` +M`(```T#,@```S,```-1```!\0(`!B````,0<``3-P```S````,R```#40``` +M?$"``8@```!\0,`!)-``!C$0``;$%``/F0``",P``!+$)`!^ED``.)E```3$ +M'``$S<```,P```#,@```S,```-1```!\0(`!B````'Q`P`%\00`!%1@`'\T` +M`"%1%``@F8```]1-``"`````?4U`&AD<`#'45@``E<#\B\0@`!.:`/__?$"` +M`8@```!\0,`!?$$``134`!XQ6``")-P`_Y5```29@/R`S1P#`(````#,@``` +MS,```,T```!\0(`!B````,0@`"1\0,`!Q-,#`,R```#,P```S```(,0+``V4@``$C``# +MA(P`!4&```!XQ`@`UR2(``24@/_+Q`@`+I2`_\F,``-2@```>":H`/\4Y``$ +M$F0`""3<``]^7,`*S,``(\Z```R```!XS```+,V```[-@``MQ`@`$I2` +M``*,``$#Q`@`$)B```.,``%&C``%@\0(`!&8@``"C``!UL0G``":0`!=@``` +M>,0K``*,``7`P`Z``'^/@`K`#@``?T]`"B@\`*`3_``0*_P`_XP``8'`'#$% +MQ>T``!+L`!@F[`#_P"0``(P`!9_,```2D````"@,``&,``%H*#@``8P``74H +M.```C``!<9>```[`.#$!Q[D``!>X`!`GK`?_EL```\`D``",``6?S8```L00 +M``.5`/__S```$,`X``&0````Q`P`$93```4H.```C``!=2@,``",``%HP#@` +M`)````#$"``/E(#__\0K``*,``7`P`Z``'^/@`K`#@``?T]`"B@\`)`3_``0 +M*_P`_XP``8'`'#$%Q>T``!+L`!@F[`#_P"0``<`@``",``6?S8``$I````#$ +M"``3E(#__\P```+$"``/Q!```YD`___`+#$>QNT``,`D``",``6?Q#@`$9>` +M`````3`$#$9Q1T``)G`__Z70``$P!`Q&L4= +M``"9P/_^D````(P``7C`%#$5SY4``,`4,1;/50``P!0Q&,\5``#`$#$=Q1$` +M`"40``&9```$P!0Q%\_5``"0````)]``_S$0`/^9```$P!0Q%\_5``"0```` +MP!0`",`>@`!]^<`)E<```L`4`!8)5``!?\$`"L`=_P!]'0`)?14`"L`<,1?- +M'0``E4``!\`<,1?%W0``?='`#)7`__V,``%X@``!FI````",``+-F0``*LV` +M`"W$#``2E,```HP``0/$#``0F,```HP``48H.```C``!=2@X``&,``%QP!PB +M<(P`!8S.@P`CQ`\``L03`")^D0`*?-#`"HP``167@``$S```+.```PU``# +MF4``"##4``290``*E,``'LS+``!'N``$!(@``<>.``#,RP``1[@`!`2(``&` +M``'ME,``%<`0``/,RP``1[@`!`2(``''C@``S,L```D0``&9`/_[1[@`!`2( +M``''D@``S0L```C,``&8P/_[1[@`!`2(``''C@``P!```Y3```*```(!S`L` +M``2(``',@P`&D````'W!P`G$$P`(Q`\`"IC```:9```#*`@`D(```AS$"P`M +M@``"*\03``B9```(P`PPQ,3)``"8@``#P!P``9````!0B``(@``"4L0+`"Y0 +MB``(Q`\`+7R,@`J```)2Q(\``)3``"0PT``#E0``!LV#``@$B``!S(,`+<2/ +M``"```(V,-``!)D```8$B``!Q-4``,U+```$B``!@``"*P2(``'`/```Q(\` +M``2(``&4P``1Q),```2(``'$EP``!(@``<_-```'_``!Q1T``,W+``#/S0`` +M!_P``<4A``#."P``!(@``GU_``R7`/_V@``"/7W!P`F0````Q(X``)3`__TP +MT``#E0``".``3,RP`!QXX`",S+``+-@P`'D````,>B``#`##!QS@T``,>B``3`##!P +MS@T``,>B``C`##!RS@T``)````#$.P`&![@``<`,,'''HP``S@T``,`,,'#' +MHP`!S@T``,`,,'+'HP`"S@T``)````",``+!D````,`((8'."0``P`@A@\P) +M``#`""&`S,D``,`((8+-"0``P`@AA,U)``"0````P`@AH,2-```4S``6),P` +M`9C`__V0````P`@AH,2-```4S``"),P``9C`__V0````P`PAML31``#`"A0` +M?0D`"9````#`,"&VS+$``,<)``"0````*#"``!,P`!",``+@*#"@`!,P`!", +M``+@*##``!,P`!",``+@D````"LT(8W-M0``*S0ACL`-___,]0``D````,`P +M(`C`"/_ZS+$``,<-``#,,0``QPT``)````#$)P`*FD```R@(`)"```)HQ`@` +MQ%"(``B```*#Q#@`R)>```[$.P`'FX```HP``H\H.``!C``!<<0G``K$.`#( +MFD``!,0[``:,``*H@``#`U.X``B,``*>D````,V```[`'")PC``%C,Z#`"/$ +M(P`B?J*`"LZ#``&,``/0Q`@`UR2(``24@``&C``$0Y2``$'$(P`!?>'`"8`` +M`Q;/0P`%Q!\``8P``]O`%```S!<`%`54``$Q2``$E(#__8P``^2,``/SC``$ +M&L0G``]^I(`+F(```H```U%\IL`)Q`\`))3```3`,```S`,`)(```RI\JP`) +MP`@Q`\2A``!^,@`*S@D``'YR0`K.0P`/Q`L`"Y2```7`#"37C``$-GT)``J, +M``0LSL,`"\\#``PVR```S(,`#<`D``"7```/?P*`"L`\"O_`+#$%QNT``";L +M`/^,``.EC``$SL`H`!",``2OP`PDUXP`!#;$,P`,?3$`"HP`!"S`#"37C``$ +M-L0O``M^P4`>?14`"8P`!"R,``.$D````,V```[`$#$$Q0D``,03``)\D(`) +MP"`Q`\8-``!\T,`)?(U`"WU.P`E]2P`)P`PDUXP`!#9_$P`)SL,`"\\#``Q^ +MPD`>Q@T``'SDP`E\T,`)S.$``,`D``"7```,?P*`"L`\"O_`+#$%QNT``";L +M`/^,``.EP!`Q`\4-``#$,P`,?/#`"LS1``#`)```Q"L`"Y:```G`/`G_P"PQ +M!<;M```6[``()NP`_XP``Z7`*``8@``#@,`H`!",``3.C``$K\P#``.0```` +MS8``#L03``O`"#$&Q(T``'S`P!Y]#H`)EH``>I0`O-0P`+?2B`#)2```+, +M`P`-P`@Q`\2-``!^@0`>?-#`";```%Q"L`%)J```,',``!@``#J<0W`!K$.P`;D````,0?``+`##$+Q/D` +M`'^?@`G`'``*P`PQ#,3U``!_7,`.E,```GW#0`J0````?X#``<`4```DT``? +MS1<`$!3,``@%5``!,4@``I2`__N0````?X#``<`@`"#`)``!P"@``'SD@`E^ +MBH`!%,P``0H@``&:`/_\?K2`#Y2```/`)```@``#\G]J0`*0````)=``_\T# +M`!@5W``()=``_\T#`!D5W``()=``_\T#`!H5W``()=``_\T#`!O`#```P!0` +M`,`@``'`'```Q=,`&'TA``F9```.Q=,`$'T@@`F8@``$?D"`#I2```D*9``! +MQ>L`%'ZB@`K.GP`4!,P``7ST@`^4@``"D`````7<``$]R``"E(#_[@54``$2 +M(``!/4@`!92`_^F0````P!P``@G<``'`(``(P"@``,7G`!1^IH`*E<``!7ZB +M@`0&(``("=P``8``!!Z0````S8``#L03`![`#"35C``$+,P#``Z0````)10` +M_\`*B`!\C(`*S4D``!44``@E5`#_P`J(0'R,@`K-20``D````,`0``#`"HA` +M?(R`"L25```E5``??14`"A$0``C`"H@`?(R`"L25```E5``??14`"I````#$ +M$P`%ST,`!7]10`^90``@?38``L`(,0/$E0``?4"`'L0/``)\C(`)E(``&<03 +M``]]%,`+E,``%L`4``#`$``!P`P``'R1P`E\W,`!%(@``054``$Q7``0E<#_ +M^WSA``^5```%?@"`"HP`!&A\@(`)D````'S`@`I^#H`"C``$:,`T``I_:T`" +MS8,`),`(``&0````Q!,`#\`<,0/%W0``P!0``7W6``F:```'?19`"99```5] +MU<`*?4)`'GTE``D(B``!$50``95```*8@/_VS0,`#\`,)->,``0LD````,0K +M``+$)P`!?D)`'GZF@`G`"##7Q(T``,`(``@HB``$?,C`"13,``($S`2'A,`` +M`(``!(N```2.@``$DX``!*C.@P`@SH,`(8``!*W.@P`@P`@Q`\2I``#.@P`A +M@``$K<0(`"^8@``#Q"L`#X``!*2,``/0ST,`!8P``]O`'```S!\`%`7<``$Q +MR``"E(#__8P``^3$'P`!C``#\XP`!!K.@P`/Q!,``LT#`"'.@P`@@``$K<03 +M``_-`P`@P`@Q`\2I``#.@P`AC``%P)````#`##$1SPT``,`,`__,P``QP`@` +M!,`0`!`)$``!F0#__X``!+V60``%Q"``')8```/,```QD````,04`#250``) +ME(``!0B(``'`#`/_S,``,8``!,?,```QP"```)````#`##$2Q-$``'TI``R5 +M`/_JP"```,P``#&0````P!P``,`*@`!_B,`)F,``.'](P`F8P``VP`@``<`, +M``#`$```?X%`"GU*``F:```,!1```03,``$0B``!,.``"I8`__I_04`*P`P` +M`#$@``J6`/_VP!P``9`````%(`3GA@```(``!/&```3S@``$]8``!/>```3Y +M@``$^X``!/V```3_@``%`8``!0/`,``(@``%!<`P``>```4%P#``!X``!07` +M,``'@``%!<`P``B```4%P#``"(``!07`,``'@``%!<`P``>```4%P#``!X`` +M!07`,``(@``%!0LP``$3,``&?Q,`"H``!0W`,``6"S```1,P``8K,``*D``` +M`,Z#`!7`+#$%QNT``";L`/_`)```P#P._XP``Z7`/`;_Q"L`%7Z"@![$.P`" +M?KJ`"8P``Z7`/`[_P#8``)=```3`.```C``!@8P`!:S`-```P#J``(P``8&, +M``6LP"P`@8P`!,[`*``0P"0``(P`!*^0````P"PQ!<;I```6J``()JP`_\`D +M``#`/`W_Q"L``HP``Z7`.```P#8``)=```.,``&!C``%K,`T``#`.H``C``! +M@<`L`(&,``3.P"@`&L`D``&,``2OD````,0+``V4@``VP`@P[\2-``"4P``S +MP`@PT,V)``#`"##.Q)4``,03`!R9```#S4,`')````!]4(`"?(R`#YB```*0 +M````P`PDUXP`!#9\$D`*Q!<``L`,,0O$R0``?("`'GR4@`E]",`)Q`L`"\`0 +M``#`%```P!P``7W*``F6```"!50``1'<``$%$``!/2``$)8`__K`"```P!`` +M`<`<``!]#(`)E(```WW1P`H)5``!$1```9E`__O$(P`+?F)`"GW!0![$$P`" +M?5%`"7Y5``G`#"37C``$+,W#``O,`P`,``?*@``%S<`8``',`P`. +MP`W__\S#`![,PP!AP`@Q!,S)``#,`P`#S`,`8XP`!X?`"`4`*`P``,R/`$'` +M"B`@*(@/!03,``',CP!!P`HP,"B('@\$S``!S(\`0<`*0$`HB"@>!,P`` +MB`",``B$",``%50`$"G,)-?$S0``?4U`"9`````PC`!`F,``,SB,`$"4P``4 +M"(@`0'RMP!`5W``&C``''GZ"@!Y^LH`)C``'9B:,`/]_`4`*C``&8GP:0`H6 +MJ``()HP`_W]!0`J,``9B$9@`"'Y:0`K.0P!A@``'9<`,,0G$S0``)-```9D` +M``?$#P!=Q!,`7L07`%5]40`.?-$`"ID``!3`'`!`?Q`\`8<`0,0/%$0``?-#`"7R-``R9```$S,,`'L`8 +M``'-@P`.D````,@)/3;(#3TWE,#X,<@1/3C(%3TYR!T].L@A/3O()3TU!*@` +M,,Z!/8+,P3V#S0$]A,U!/87-P3V&S@$]AQ"(``,$C``8R)8`/)5`^"'(T@`H +M?24``@E4``$$S``HF0#_^\B2`#@%$`!`?0K`` + */ + +/* + * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com + * + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ + +static int drm_ati_alloc_pcigart_table(struct drm_device *dev, + struct drm_ati_pcigart_info *gart_info) +{ + gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size, + PAGE_SIZE, 0xFFFFFFFFUL); + if (gart_info->table_handle == NULL) + return -ENOMEM; + + return 0; +} + +static void drm_ati_free_pcigart_table(struct drm_device *dev, + struct drm_ati_pcigart_info *gart_info) +{ + drm_pci_free(dev, gart_info->table_handle); + gart_info->table_handle = NULL; +} + +int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) +{ + struct drm_sg_mem *entry = dev->sg; +#ifdef __linux__ + unsigned long pages; + int i; + int max_pages; +#endif + + /* we need to support large memory configurations */ + if (!entry) { + DRM_ERROR("no scatter/gather memory!\n"); + return 0; + } + + if (gart_info->bus_addr) { +#ifdef __linux__ + + max_pages = (gart_info->table_size / sizeof(u32)); + pages = (entry->pages <= max_pages) + ? entry->pages : max_pages; + + for (i = 0; i < pages; i++) { + if (!entry->busaddr[i]) + break; + pci_unmap_page(dev->pdev, entry->busaddr[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } +#endif + + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) + gart_info->bus_addr = 0; + } + + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && + gart_info->table_handle) { + drm_ati_free_pcigart_table(dev, gart_info); + } + + return 1; +} + +int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) +{ + struct drm_local_map *map = &gart_info->mapping; + struct drm_sg_mem *entry = dev->sg; + void *address = NULL; + unsigned long pages; + u32 *pci_gart = NULL, page_base, gart_idx; + dma_addr_t bus_address = 0; + int i, j, ret = 0; + int max_ati_pages, max_real_pages; + + if (!entry) { + DRM_ERROR("no scatter/gather memory!\n"); + goto done; + } + + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { + DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); + +#ifdef __linux__ + if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) { + DRM_ERROR("fail to set dma mask to 0x%Lx\n", + (unsigned long long)gart_info->table_mask); + ret = 1; + goto done; + } +#endif + + ret = drm_ati_alloc_pcigart_table(dev, gart_info); + if (ret) { + DRM_ERROR("cannot allocate PCI GART page!\n"); + goto done; + } + + pci_gart = gart_info->table_handle->vaddr; + address = gart_info->table_handle->vaddr; + bus_address = gart_info->table_handle->busaddr; + } else { + address = gart_info->addr; + bus_address = gart_info->bus_addr; + DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n", + (unsigned long long)bus_address, + (unsigned long)address); + } + + + max_ati_pages = (gart_info->table_size / sizeof(u32)); + max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); + pages = (entry->pages <= max_real_pages) + ? entry->pages : max_real_pages; + + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { + memset(pci_gart, 0, max_ati_pages * sizeof(u32)); + } else { + memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u32)); + } + + gart_idx = 0; + for (i = 0; i < pages; i++) { +#ifdef __linux__ + /* we need to support large memory configurations */ + entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], + 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { + DRM_ERROR("unable to map PCIGART pages!\n"); + drm_ati_pcigart_cleanup(dev, gart_info); + address = NULL; + bus_address = 0; + goto done; + } +#endif + page_base = (u32) entry->busaddr[i]; + + for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { + u32 val; + + switch(gart_info->gart_reg_if) { + case DRM_ATI_GART_IGP: + val = page_base | 0xc; + break; + case DRM_ATI_GART_PCIE: + val = (page_base >> 8) | 0xc; + break; + default: + case DRM_ATI_GART_PCI: + val = page_base; + break; + } + if (gart_info->gart_table_location == + DRM_ATI_GART_MAIN) + pci_gart[gart_idx] = cpu_to_le32(val); + else + DRM_WRITE32(map, gart_idx * sizeof(u32), val); + gart_idx++; + page_base += ATI_PCIGART_PAGE_SIZE; + } + } + ret = 1; + +#if defined(__i386) || defined(__amd64) + wbinvd(); +#else + mb(); +#endif + + done: + gart_info->addr = address; + gart_info->bus_addr = bus_address; + return ret; +} diff --git a/sys/dev/drm2/radeon/ObjectID.h b/sys/dev/drm2/radeon/ObjectID.h new file mode 100644 index 00000000000..db559da6a2d --- /dev/null +++ b/sys/dev/drm2/radeon/ObjectID.h @@ -0,0 +1,699 @@ +/* +* Copyright 2006-2007 Advanced Micro Devices, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ +/* based on stg/asic_reg/drivers/inc/asic_reg/ObjectID.h ver 23 */ + +#ifndef _OBJECTID_H +#define _OBJECTID_H + +#include +__FBSDID("$FreeBSD$"); + +#if defined(_X86_) +#pragma pack(1) +#endif + +/****************************************************/ +/* Graphics Object Type Definition */ +/****************************************************/ +#define GRAPH_OBJECT_TYPE_NONE 0x0 +#define GRAPH_OBJECT_TYPE_GPU 0x1 +#define GRAPH_OBJECT_TYPE_ENCODER 0x2 +#define GRAPH_OBJECT_TYPE_CONNECTOR 0x3 +#define GRAPH_OBJECT_TYPE_ROUTER 0x4 +/* deleted */ +#define GRAPH_OBJECT_TYPE_DISPLAY_PATH 0x6 +#define GRAPH_OBJECT_TYPE_GENERIC 0x7 + +/****************************************************/ +/* Encoder Object ID Definition */ +/****************************************************/ +#define ENCODER_OBJECT_ID_NONE 0x00 + +/* Radeon Class Display Hardware */ +#define ENCODER_OBJECT_ID_INTERNAL_LVDS 0x01 +#define ENCODER_OBJECT_ID_INTERNAL_TMDS1 0x02 +#define ENCODER_OBJECT_ID_INTERNAL_TMDS2 0x03 +#define ENCODER_OBJECT_ID_INTERNAL_DAC1 0x04 +#define ENCODER_OBJECT_ID_INTERNAL_DAC2 0x05 /* TV/CV DAC */ +#define ENCODER_OBJECT_ID_INTERNAL_SDVOA 0x06 +#define ENCODER_OBJECT_ID_INTERNAL_SDVOB 0x07 + +/* External Third Party Encoders */ +#define ENCODER_OBJECT_ID_SI170B 0x08 +#define ENCODER_OBJECT_ID_CH7303 0x09 +#define ENCODER_OBJECT_ID_CH7301 0x0A +#define ENCODER_OBJECT_ID_INTERNAL_DVO1 0x0B /* This belongs to Radeon Class Display Hardware */ +#define ENCODER_OBJECT_ID_EXTERNAL_SDVOA 0x0C +#define ENCODER_OBJECT_ID_EXTERNAL_SDVOB 0x0D +#define ENCODER_OBJECT_ID_TITFP513 0x0E +#define ENCODER_OBJECT_ID_INTERNAL_LVTM1 0x0F /* not used for Radeon */ +#define ENCODER_OBJECT_ID_VT1623 0x10 +#define ENCODER_OBJECT_ID_HDMI_SI1930 0x11 +#define ENCODER_OBJECT_ID_HDMI_INTERNAL 0x12 +#define ENCODER_OBJECT_ID_ALMOND 0x22 +#define ENCODER_OBJECT_ID_TRAVIS 0x23 +#define ENCODER_OBJECT_ID_NUTMEG 0x22 +/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */ +#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13 +#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14 +#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 0x15 +#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 0x16 /* Shared with CV/TV and CRT */ +#define ENCODER_OBJECT_ID_SI178 0X17 /* External TMDS (dual link, no HDCP.) */ +#define ENCODER_OBJECT_ID_MVPU_FPGA 0x18 /* MVPU FPGA chip */ +#define ENCODER_OBJECT_ID_INTERNAL_DDI 0x19 +#define ENCODER_OBJECT_ID_VT1625 0x1A +#define ENCODER_OBJECT_ID_HDMI_SI1932 0x1B +#define ENCODER_OBJECT_ID_DP_AN9801 0x1C +#define ENCODER_OBJECT_ID_DP_DP501 0x1D +#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY 0x1E +#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA 0x1F +#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20 +#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21 +#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24 + +#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF + +/****************************************************/ +/* Connector Object ID Definition */ +/****************************************************/ +#define CONNECTOR_OBJECT_ID_NONE 0x00 +#define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I 0x01 +#define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I 0x02 +#define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D 0x03 +#define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D 0x04 +#define CONNECTOR_OBJECT_ID_VGA 0x05 +#define CONNECTOR_OBJECT_ID_COMPOSITE 0x06 +#define CONNECTOR_OBJECT_ID_SVIDEO 0x07 +#define CONNECTOR_OBJECT_ID_YPbPr 0x08 +#define CONNECTOR_OBJECT_ID_D_CONNECTOR 0x09 +#define CONNECTOR_OBJECT_ID_9PIN_DIN 0x0A /* Supports both CV & TV */ +#define CONNECTOR_OBJECT_ID_SCART 0x0B +#define CONNECTOR_OBJECT_ID_HDMI_TYPE_A 0x0C +#define CONNECTOR_OBJECT_ID_HDMI_TYPE_B 0x0D +#define CONNECTOR_OBJECT_ID_LVDS 0x0E +#define CONNECTOR_OBJECT_ID_7PIN_DIN 0x0F +#define CONNECTOR_OBJECT_ID_PCIE_CONNECTOR 0x10 +#define CONNECTOR_OBJECT_ID_CROSSFIRE 0x11 +#define CONNECTOR_OBJECT_ID_HARDCODE_DVI 0x12 +#define CONNECTOR_OBJECT_ID_DISPLAYPORT 0x13 +#define CONNECTOR_OBJECT_ID_eDP 0x14 +#define CONNECTOR_OBJECT_ID_MXM 0x15 +#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16 + +/* deleted */ + +/****************************************************/ +/* Router Object ID Definition */ +/****************************************************/ +#define ROUTER_OBJECT_ID_NONE 0x00 +#define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL 0x01 + +/****************************************************/ +/* Generic Object ID Definition */ +/****************************************************/ +#define GENERIC_OBJECT_ID_NONE 0x00 +#define GENERIC_OBJECT_ID_GLSYNC 0x01 +#define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE 0x02 +#define GENERIC_OBJECT_ID_MXM_OPM 0x03 +#define GENERIC_OBJECT_ID_STEREO_PIN 0x04 //This object could show up from Misc Object table, it follows ATOM_OBJECT format, and contains one ATOM_OBJECT_GPIO_CNTL_RECORD for the stereo pin + +/****************************************************/ +/* Graphics Object ENUM ID Definition */ +/****************************************************/ +#define GRAPH_OBJECT_ENUM_ID1 0x01 +#define GRAPH_OBJECT_ENUM_ID2 0x02 +#define GRAPH_OBJECT_ENUM_ID3 0x03 +#define GRAPH_OBJECT_ENUM_ID4 0x04 +#define GRAPH_OBJECT_ENUM_ID5 0x05 +#define GRAPH_OBJECT_ENUM_ID6 0x06 +#define GRAPH_OBJECT_ENUM_ID7 0x07 + +/****************************************************/ +/* Graphics Object ID Bit definition */ +/****************************************************/ +#define OBJECT_ID_MASK 0x00FF +#define ENUM_ID_MASK 0x0700 +#define RESERVED1_ID_MASK 0x0800 +#define OBJECT_TYPE_MASK 0x7000 +#define RESERVED2_ID_MASK 0x8000 + +#define OBJECT_ID_SHIFT 0x00 +#define ENUM_ID_SHIFT 0x08 +#define OBJECT_TYPE_SHIFT 0x0C + + +/****************************************************/ +/* Graphics Object family definition */ +/****************************************************/ +#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \ + GRAPHICS_OBJECT_ID << OBJECT_ID_SHIFT) +/****************************************************/ +/* GPU Object ID definition - Shared with BIOS */ +/****************************************************/ +#define GPU_ENUM_ID1 ( GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT) + +/****************************************************/ +/* Encoder Object ID definition - Shared with BIOS */ +/****************************************************/ +/* +#define ENCODER_INTERNAL_LVDS_ENUM_ID1 0x2101 +#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 0x2102 +#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 0x2103 +#define ENCODER_INTERNAL_DAC1_ENUM_ID1 0x2104 +#define ENCODER_INTERNAL_DAC2_ENUM_ID1 0x2105 +#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 0x2106 +#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 0x2107 +#define ENCODER_SIL170B_ENUM_ID1 0x2108 +#define ENCODER_CH7303_ENUM_ID1 0x2109 +#define ENCODER_CH7301_ENUM_ID1 0x210A +#define ENCODER_INTERNAL_DVO1_ENUM_ID1 0x210B +#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 0x210C +#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 0x210D +#define ENCODER_TITFP513_ENUM_ID1 0x210E +#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 0x210F +#define ENCODER_VT1623_ENUM_ID1 0x2110 +#define ENCODER_HDMI_SI1930_ENUM_ID1 0x2111 +#define ENCODER_HDMI_INTERNAL_ENUM_ID1 0x2112 +#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 0x2113 +#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 0x2114 +#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 0x2115 +#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 0x2116 +#define ENCODER_SI178_ENUM_ID1 0x2117 +#define ENCODER_MVPU_FPGA_ENUM_ID1 0x2118 +#define ENCODER_INTERNAL_DDI_ENUM_ID1 0x2119 +#define ENCODER_VT1625_ENUM_ID1 0x211A +#define ENCODER_HDMI_SI1932_ENUM_ID1 0x211B +#define ENCODER_ENCODER_DP_AN9801_ENUM_ID1 0x211C +#define ENCODER_DP_DP501_ENUM_ID1 0x211D +#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 0x211E +*/ +#define ENCODER_INTERNAL_LVDS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DAC1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DAC2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT) + +#define ENCODER_SIL170B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT) + +#define ENCODER_CH7303_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT) + +#define ENCODER_CH7301_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DVO1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT) + +#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) + +#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) + + +#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT) + + +#define ENCODER_TITFP513_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT) + +#define ENCODER_VT1623_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT) + +#define ENCODER_HDMI_SI1930_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT) + +#define ENCODER_HDMI_INTERNAL_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) + + +#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) + + +#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) // Shared with CV/TV and CRT + +#define ENCODER_SI178_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT) + +#define ENCODER_MVPU_FPGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DDI_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT) + +#define ENCODER_VT1625_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT) + +#define ENCODER_HDMI_SI1932_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT) + +#define ENCODER_DP_DP501_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT) + +#define ENCODER_DP_AN9801_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) + +#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT) + +#define ENCODER_ALMOND_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT) + +#define ENCODER_ALMOND_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT) + +#define ENCODER_TRAVIS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT) + +#define ENCODER_TRAVIS_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT) + +#define ENCODER_NUTMEG_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT) + +#define ENCODER_VCE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_VCE << OBJECT_ID_SHIFT) + +/****************************************************/ +/* Connector Object ID definition - Shared with BIOS */ +/****************************************************/ +/* +#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 0x3101 +#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 0x3102 +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 0x3103 +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 0x3104 +#define CONNECTOR_VGA_ENUM_ID1 0x3105 +#define CONNECTOR_COMPOSITE_ENUM_ID1 0x3106 +#define CONNECTOR_SVIDEO_ENUM_ID1 0x3107 +#define CONNECTOR_YPbPr_ENUM_ID1 0x3108 +#define CONNECTOR_D_CONNECTORE_ENUM_ID1 0x3109 +#define CONNECTOR_9PIN_DIN_ENUM_ID1 0x310A +#define CONNECTOR_SCART_ENUM_ID1 0x310B +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 0x310C +#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 0x310D +#define CONNECTOR_LVDS_ENUM_ID1 0x310E +#define CONNECTOR_7PIN_DIN_ENUM_ID1 0x310F +#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 0x3110 +*/ +#define CONNECTOR_LVDS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) + +#define CONNECTOR_LVDS_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) + +#define CONNECTOR_eDP_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT) + +#define CONNECTOR_eDP_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) + +#define CONNECTOR_VGA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) + +#define CONNECTOR_COMPOSITE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) + +#define CONNECTOR_COMPOSITE_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) + +#define CONNECTOR_SVIDEO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) + +#define CONNECTOR_SVIDEO_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) + +#define CONNECTOR_YPbPr_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) + +#define CONNECTOR_YPbPr_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) + +#define CONNECTOR_D_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_D_CONNECTOR_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_9PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) + +#define CONNECTOR_9PIN_DIN_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) + +#define CONNECTOR_SCART_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) + +#define CONNECTOR_SCART_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_B_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) + +#define CONNECTOR_7PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) + +#define CONNECTOR_7PIN_DIN_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) + +#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_CROSSFIRE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) + +#define CONNECTOR_CROSSFIRE_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) + + +#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) + +#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_MXM_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_A + +#define CONNECTOR_MXM_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_B + +#define CONNECTOR_MXM_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_C + +#define CONNECTOR_MXM_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_D + +#define CONNECTOR_MXM_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_LVDS_TXxx + +#define CONNECTOR_MXM_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_LVDS_UXxx + +#define CONNECTOR_MXM_ENUM_ID7 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DAC + +#define CONNECTOR_LVDS_eDP_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT) + +#define CONNECTOR_LVDS_eDP_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT) + +/****************************************************/ +/* Router Object ID definition - Shared with BIOS */ +/****************************************************/ +#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT) + +/* deleted */ + +/****************************************************/ +/* Generic Object ID definition - Shared with BIOS */ +/****************************************************/ +#define GENERICOBJECT_GLSYNC_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_GLSYNC << OBJECT_ID_SHIFT) + +#define GENERICOBJECT_PX2_NON_DRIVABLE_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT) + +#define GENERICOBJECT_PX2_NON_DRIVABLE_ID2 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT) + +#define GENERICOBJECT_MXM_OPM_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT) + +#define GENERICOBJECT_STEREO_PIN_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_STEREO_PIN << OBJECT_ID_SHIFT) + +/****************************************************/ +/* Object Cap definition - Shared with BIOS */ +/****************************************************/ +#define GRAPHICS_OBJECT_CAP_I2C 0x00000001L +#define GRAPHICS_OBJECT_CAP_TABLE_ID 0x00000002L + + +#define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID 0x01 +#define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID 0x02 +#define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID 0x03 + +#if defined(_X86_) +#pragma pack() +#endif + +#endif /*GRAPHICTYPE */ + + + + diff --git a/sys/dev/drm2/radeon/README b/sys/dev/drm2/radeon/README new file mode 100644 index 00000000000..fad030f068c --- /dev/null +++ b/sys/dev/drm2/radeon/README @@ -0,0 +1,6 @@ +# $FreeBSD$ + +== Updates to reg_srcs/ files == + +When a file in the "reg_srcs" subdirectory in updated, be sure to regen +headers by running "make" in tools/tools/drm/radeon/mkregtable. diff --git a/sys/dev/drm2/radeon/atom-bits.h b/sys/dev/drm2/radeon/atom-bits.h new file mode 100644 index 00000000000..ab099f9964a --- /dev/null +++ b/sys/dev/drm2/radeon/atom-bits.h @@ -0,0 +1,51 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Stanislaw Skowronek + */ + +#ifndef ATOM_BITS_H +#define ATOM_BITS_H + +#include +__FBSDID("$FreeBSD$"); + +static inline uint8_t get_u8(void *bios, int ptr) +{ + return ((unsigned char *)bios)[ptr]; +} +#define U8(ptr) get_u8(ctx->ctx->bios, (ptr)) +#define CU8(ptr) get_u8(ctx->bios, (ptr)) +static inline uint16_t get_u16(void *bios, int ptr) +{ + return get_u8(bios ,ptr)|(((uint16_t)get_u8(bios, ptr+1))<<8); +} +#define U16(ptr) get_u16(ctx->ctx->bios, (ptr)) +#define CU16(ptr) get_u16(ctx->bios, (ptr)) +static inline uint32_t get_u32(void *bios, int ptr) +{ + return get_u16(bios, ptr)|(((uint32_t)get_u16(bios, ptr+2))<<16); +} +#define U32(ptr) get_u32(ctx->ctx->bios, (ptr)) +#define CU32(ptr) get_u32(ctx->bios, (ptr)) +#define CSTR(ptr) (((char *)(ctx->bios))+(ptr)) + +#endif diff --git a/sys/dev/drm2/radeon/atom-names.h b/sys/dev/drm2/radeon/atom-names.h new file mode 100644 index 00000000000..737ea7d84f9 --- /dev/null +++ b/sys/dev/drm2/radeon/atom-names.h @@ -0,0 +1,103 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Stanislaw Skowronek + */ + +#ifndef ATOM_NAMES_H +#define ATOM_NAMES_H + +#include +__FBSDID("$FreeBSD$"); + +#include "atom.h" + +#ifdef ATOM_DEBUG + +#define ATOM_OP_NAMES_CNT 123 +static char *atom_op_names[ATOM_OP_NAMES_CNT] = { +"RESERVED", "MOVE_REG", "MOVE_PS", "MOVE_WS", "MOVE_FB", "MOVE_PLL", +"MOVE_MC", "AND_REG", "AND_PS", "AND_WS", "AND_FB", "AND_PLL", "AND_MC", +"OR_REG", "OR_PS", "OR_WS", "OR_FB", "OR_PLL", "OR_MC", "SHIFT_LEFT_REG", +"SHIFT_LEFT_PS", "SHIFT_LEFT_WS", "SHIFT_LEFT_FB", "SHIFT_LEFT_PLL", +"SHIFT_LEFT_MC", "SHIFT_RIGHT_REG", "SHIFT_RIGHT_PS", "SHIFT_RIGHT_WS", +"SHIFT_RIGHT_FB", "SHIFT_RIGHT_PLL", "SHIFT_RIGHT_MC", "MUL_REG", +"MUL_PS", "MUL_WS", "MUL_FB", "MUL_PLL", "MUL_MC", "DIV_REG", "DIV_PS", +"DIV_WS", "DIV_FB", "DIV_PLL", "DIV_MC", "ADD_REG", "ADD_PS", "ADD_WS", +"ADD_FB", "ADD_PLL", "ADD_MC", "SUB_REG", "SUB_PS", "SUB_WS", "SUB_FB", +"SUB_PLL", "SUB_MC", "SET_ATI_PORT", "SET_PCI_PORT", "SET_SYS_IO_PORT", +"SET_REG_BLOCK", "SET_FB_BASE", "COMPARE_REG", "COMPARE_PS", +"COMPARE_WS", "COMPARE_FB", "COMPARE_PLL", "COMPARE_MC", "SWITCH", +"JUMP", "JUMP_EQUAL", "JUMP_BELOW", "JUMP_ABOVE", "JUMP_BELOW_OR_EQUAL", +"JUMP_ABOVE_OR_EQUAL", "JUMP_NOT_EQUAL", "TEST_REG", "TEST_PS", "TEST_WS", +"TEST_FB", "TEST_PLL", "TEST_MC", "DELAY_MILLISEC", "DELAY_MICROSEC", +"CALL_TABLE", "REPEAT", "CLEAR_REG", "CLEAR_PS", "CLEAR_WS", "CLEAR_FB", +"CLEAR_PLL", "CLEAR_MC", "NOP", "EOT", "MASK_REG", "MASK_PS", "MASK_WS", +"MASK_FB", "MASK_PLL", "MASK_MC", "POST_CARD", "BEEP", "SAVE_REG", +"RESTORE_REG", "SET_DATA_BLOCK", "XOR_REG", "XOR_PS", "XOR_WS", "XOR_FB", +"XOR_PLL", "XOR_MC", "SHL_REG", "SHL_PS", "SHL_WS", "SHL_FB", "SHL_PLL", +"SHL_MC", "SHR_REG", "SHR_PS", "SHR_WS", "SHR_FB", "SHR_PLL", "SHR_MC", +"DEBUG", "CTB_DS", +}; + +#define ATOM_TABLE_NAMES_CNT 74 +static char *atom_table_names[ATOM_TABLE_NAMES_CNT] = { +"ASIC_Init", "GetDisplaySurfaceSize", "ASIC_RegistersInit", +"VRAM_BlockVenderDetection", "SetClocksRatio", "MemoryControllerInit", +"GPIO_PinInit", "MemoryParamAdjust", "DVOEncoderControl", +"GPIOPinControl", "SetEngineClock", "SetMemoryClock", "SetPixelClock", +"DynamicClockGating", "ResetMemoryDLL", "ResetMemoryDevice", +"MemoryPLLInit", "EnableMemorySelfRefresh", "AdjustMemoryController", +"EnableASIC_StaticPwrMgt", "ASIC_StaticPwrMgtStatusChange", +"DAC_LoadDetection", "TMDS2EncoderControl", "LCD1OutputControl", +"DAC1EncoderControl", "DAC2EncoderControl", "DVOOutputControl", +"CV1OutputControl", "SetCRTC_DPM_State", "TVEncoderControl", +"TMDS1EncoderControl", "LVDSEncoderControl", "TV1OutputControl", +"EnableScaler", "BlankCRTC", "EnableCRTC", "GetPixelClock", +"EnableVGA_Render", "EnableVGA_Access", "SetCRTC_Timing", +"SetCRTC_OverScan", "SetCRTC_Replication", "SelectCRTC_Source", +"EnableGraphSurfaces", "UpdateCRTC_DoubleBufferRegisters", +"LUT_AutoFill", "EnableHW_IconCursor", "GetMemoryClock", +"GetEngineClock", "SetCRTC_UsingDTDTiming", "TVBootUpStdPinDetection", +"DFP2OutputControl", "VRAM_BlockDetectionByStrap", "MemoryCleanUp", +"ReadEDIDFromHWAssistedI2C", "WriteOneByteToHWAssistedI2C", +"ReadHWAssistedI2CStatus", "SpeedFanControl", "PowerConnectorDetection", +"MC_Synchronization", "ComputeMemoryEnginePLL", "MemoryRefreshConversion", +"VRAM_GetCurrentInfoBlock", "DynamicMemorySettings", "MemoryTraining", +"EnableLVDS_SS", "DFP1OutputControl", "SetVoltage", "CRT1OutputControl", +"CRT2OutputControl", "SetupHWAssistedI2CStatus", "ClockSource", +"MemoryDeviceInit", "EnableYUV", +}; + +#define ATOM_IO_NAMES_CNT 5 +static char *atom_io_names[ATOM_IO_NAMES_CNT] = { +"MM", "PLL", "MC", "PCIE", "PCIE PORT", +}; + +#else + +#define ATOM_OP_NAMES_CNT 0 +#define ATOM_TABLE_NAMES_CNT 0 +#define ATOM_IO_NAMES_CNT 0 + +#endif + +#endif diff --git a/sys/dev/drm2/radeon/atom-types.h b/sys/dev/drm2/radeon/atom-types.h new file mode 100644 index 00000000000..7009de7bacf --- /dev/null +++ b/sys/dev/drm2/radeon/atom-types.h @@ -0,0 +1,45 @@ +/* + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Dave Airlie + */ + +#ifndef ATOM_TYPES_H +#define ATOM_TYPES_H + +#include +__FBSDID("$FreeBSD$"); + +/* sync atom types to kernel types */ + +typedef uint16_t USHORT; +typedef uint32_t ULONG; +typedef uint8_t UCHAR; + + +#ifndef ATOM_BIG_ENDIAN +#if defined(__BIG_ENDIAN) +#define ATOM_BIG_ENDIAN 1 +#else +#define ATOM_BIG_ENDIAN 0 +#endif +#endif +#endif diff --git a/sys/dev/drm2/radeon/atom.c b/sys/dev/drm2/radeon/atom.c new file mode 100644 index 00000000000..f5c557c059d --- /dev/null +++ b/sys/dev/drm2/radeon/atom.c @@ -0,0 +1,1403 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Stanislaw Skowronek + */ + +#include +__FBSDID("$FreeBSD$"); + +#define ATOM_DEBUG + +#include "atom.h" +#include "atom-names.h" +#include "atom-bits.h" +#include "radeon.h" + +#define ATOM_COND_ABOVE 0 +#define ATOM_COND_ABOVEOREQUAL 1 +#define ATOM_COND_ALWAYS 2 +#define ATOM_COND_BELOW 3 +#define ATOM_COND_BELOWOREQUAL 4 +#define ATOM_COND_EQUAL 5 +#define ATOM_COND_NOTEQUAL 6 + +#define ATOM_PORT_ATI 0 +#define ATOM_PORT_PCI 1 +#define ATOM_PORT_SYSIO 2 + +#define ATOM_UNIT_MICROSEC 0 +#define ATOM_UNIT_MILLISEC 1 + +#define PLL_INDEX 2 +#define PLL_DATA 3 + +typedef struct { + struct atom_context *ctx; + uint32_t *ps, *ws; + int ps_shift; + uint16_t start; + unsigned last_jump; + unsigned long last_jump_jiffies; + bool abort; +} atom_exec_context; + +int atom_debug = 0; +static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params); + +static uint32_t atom_arg_mask[8] = + { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000, +0xFF000000 }; +static int atom_arg_shift[8] = { 0, 0, 8, 16, 0, 8, 16, 24 }; + +static int atom_dst_to_src[8][4] = { + /* translate destination alignment field to the source alignment encoding */ + {0, 0, 0, 0}, + {1, 2, 3, 0}, + {1, 2, 3, 0}, + {1, 2, 3, 0}, + {4, 5, 6, 7}, + {4, 5, 6, 7}, + {4, 5, 6, 7}, + {4, 5, 6, 7}, +}; +static int atom_def_dst[8] = { 0, 0, 1, 2, 0, 1, 2, 3 }; + +static int debug_depth = 0; +#ifdef ATOM_DEBUG +static void debug_print_spaces(int n) +{ + while (n--) + printf(" "); +} + +#define DEBUG(...) do if (atom_debug) { printf(__FILE__ __VA_ARGS__); } while (0) +#define SDEBUG(...) do if (atom_debug) { printf(__FILE__); debug_print_spaces(debug_depth); printf(__VA_ARGS__); } while (0) +#else +#define DEBUG(...) do { } while (0) +#define SDEBUG(...) do { } while (0) +#endif + +static uint32_t atom_iio_execute(struct atom_context *ctx, int base, + uint32_t index, uint32_t data) +{ + struct radeon_device *rdev = ctx->card->dev->dev_private; + uint32_t temp = 0xCDCDCDCD; + + while (1) + switch (CU8(base)) { + case ATOM_IIO_NOP: + base++; + break; + case ATOM_IIO_READ: + temp = ctx->card->ioreg_read(ctx->card, CU16(base + 1)); + base += 3; + break; + case ATOM_IIO_WRITE: + if (rdev->family == CHIP_RV515) + (void)ctx->card->ioreg_read(ctx->card, CU16(base + 1)); + ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp); + base += 3; + break; + case ATOM_IIO_CLEAR: + temp &= + ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << + CU8(base + 2)); + base += 3; + break; + case ATOM_IIO_SET: + temp |= + (0xFFFFFFFF >> (32 - CU8(base + 1))) << CU8(base + + 2); + base += 3; + break; + case ATOM_IIO_MOVE_INDEX: + temp &= + ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << + CU8(base + 3)); + temp |= + ((index >> CU8(base + 2)) & + (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + + 3); + base += 4; + break; + case ATOM_IIO_MOVE_DATA: + temp &= + ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << + CU8(base + 3)); + temp |= + ((data >> CU8(base + 2)) & + (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + + 3); + base += 4; + break; + case ATOM_IIO_MOVE_ATTR: + temp &= + ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << + CU8(base + 3)); + temp |= + ((ctx-> + io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - + CU8 + (base + + + 1)))) + << CU8(base + 3); + base += 4; + break; + case ATOM_IIO_END: + return temp; + default: + DRM_INFO("Unknown IIO opcode.\n"); + return 0; + } +} + +static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, + int *ptr, uint32_t *saved, int print) +{ + uint32_t idx, val = 0xCDCDCDCD, align, arg; + struct atom_context *gctx = ctx->ctx; + arg = attr & 7; + align = (attr >> 3) & 7; + switch (arg) { + case ATOM_ARG_REG: + idx = U16(*ptr); + (*ptr) += 2; + if (print) + DEBUG("REG[0x%04X]", idx); + idx += gctx->reg_block; + switch (gctx->io_mode) { + case ATOM_IO_MM: + val = gctx->card->reg_read(gctx->card, idx); + break; + case ATOM_IO_PCI: + DRM_INFO( + "PCI registers are not implemented.\n"); + return 0; + case ATOM_IO_SYSIO: + DRM_INFO( + "SYSIO registers are not implemented.\n"); + return 0; + default: + if (!(gctx->io_mode & 0x80)) { + DRM_INFO("Bad IO mode.\n"); + return 0; + } + if (!gctx->iio[gctx->io_mode & 0x7F]) { + DRM_INFO( + "Undefined indirect IO read method %d.\n", + gctx->io_mode & 0x7F); + return 0; + } + val = + atom_iio_execute(gctx, + gctx->iio[gctx->io_mode & 0x7F], + idx, 0); + } + break; + case ATOM_ARG_PS: + idx = U8(*ptr); + (*ptr)++; + /* get_unaligned_le32 avoids unaligned accesses from atombios + * tables, noticed on a DEC Alpha. */ + val = get_unaligned_le32((u32 *)&ctx->ps[idx]); + if (print) + DEBUG("PS[0x%02X,0x%04X]", idx, val); + break; + case ATOM_ARG_WS: + idx = U8(*ptr); + (*ptr)++; + if (print) + DEBUG("WS[0x%02X]", idx); + switch (idx) { + case ATOM_WS_QUOTIENT: + val = gctx->divmul[0]; + break; + case ATOM_WS_REMAINDER: + val = gctx->divmul[1]; + break; + case ATOM_WS_DATAPTR: + val = gctx->data_block; + break; + case ATOM_WS_SHIFT: + val = gctx->shift; + break; + case ATOM_WS_OR_MASK: + val = 1 << gctx->shift; + break; + case ATOM_WS_AND_MASK: + val = ~(1 << gctx->shift); + break; + case ATOM_WS_FB_WINDOW: + val = gctx->fb_base; + break; + case ATOM_WS_ATTRIBUTES: + val = gctx->io_attr; + break; + case ATOM_WS_REGPTR: + val = gctx->reg_block; + break; + default: + val = ctx->ws[idx]; + } + break; + case ATOM_ARG_ID: + idx = U16(*ptr); + (*ptr) += 2; + if (print) { + if (gctx->data_block) + DEBUG("ID[0x%04X+%04X]", idx, gctx->data_block); + else + DEBUG("ID[0x%04X]", idx); + } + val = U32(idx + gctx->data_block); + break; + case ATOM_ARG_FB: + idx = U8(*ptr); + (*ptr)++; + if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) { + DRM_ERROR("ATOM: fb read beyond scratch region: %d vs. %d\n", + gctx->fb_base + (idx * 4), gctx->scratch_size_bytes); + val = 0; + } else + val = gctx->scratch[(gctx->fb_base / 4) + idx]; + if (print) + DEBUG("FB[0x%02X]", idx); + break; + case ATOM_ARG_IMM: + switch (align) { + case ATOM_SRC_DWORD: + val = U32(*ptr); + (*ptr) += 4; + if (print) + DEBUG("IMM 0x%08X\n", val); + return val; + case ATOM_SRC_WORD0: + case ATOM_SRC_WORD8: + case ATOM_SRC_WORD16: + val = U16(*ptr); + (*ptr) += 2; + if (print) + DEBUG("IMM 0x%04X\n", val); + return val; + case ATOM_SRC_BYTE0: + case ATOM_SRC_BYTE8: + case ATOM_SRC_BYTE16: + case ATOM_SRC_BYTE24: + val = U8(*ptr); + (*ptr)++; + if (print) + DEBUG("IMM 0x%02X\n", val); + return val; + } + return 0; + case ATOM_ARG_PLL: + idx = U8(*ptr); + (*ptr)++; + if (print) + DEBUG("PLL[0x%02X]", idx); + val = gctx->card->pll_read(gctx->card, idx); + break; + case ATOM_ARG_MC: + idx = U8(*ptr); + (*ptr)++; + if (print) + DEBUG("MC[0x%02X]", idx); + val = gctx->card->mc_read(gctx->card, idx); + break; + } + if (saved) + *saved = val; + val &= atom_arg_mask[align]; + val >>= atom_arg_shift[align]; + if (print) + switch (align) { + case ATOM_SRC_DWORD: + DEBUG(".[31:0] -> 0x%08X\n", val); + break; + case ATOM_SRC_WORD0: + DEBUG(".[15:0] -> 0x%04X\n", val); + break; + case ATOM_SRC_WORD8: + DEBUG(".[23:8] -> 0x%04X\n", val); + break; + case ATOM_SRC_WORD16: + DEBUG(".[31:16] -> 0x%04X\n", val); + break; + case ATOM_SRC_BYTE0: + DEBUG(".[7:0] -> 0x%02X\n", val); + break; + case ATOM_SRC_BYTE8: + DEBUG(".[15:8] -> 0x%02X\n", val); + break; + case ATOM_SRC_BYTE16: + DEBUG(".[23:16] -> 0x%02X\n", val); + break; + case ATOM_SRC_BYTE24: + DEBUG(".[31:24] -> 0x%02X\n", val); + break; + } + return val; +} + +static void atom_skip_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr) +{ + uint32_t align = (attr >> 3) & 7, arg = attr & 7; + switch (arg) { + case ATOM_ARG_REG: + case ATOM_ARG_ID: + (*ptr) += 2; + break; + case ATOM_ARG_PLL: + case ATOM_ARG_MC: + case ATOM_ARG_PS: + case ATOM_ARG_WS: + case ATOM_ARG_FB: + (*ptr)++; + break; + case ATOM_ARG_IMM: + switch (align) { + case ATOM_SRC_DWORD: + (*ptr) += 4; + return; + case ATOM_SRC_WORD0: + case ATOM_SRC_WORD8: + case ATOM_SRC_WORD16: + (*ptr) += 2; + return; + case ATOM_SRC_BYTE0: + case ATOM_SRC_BYTE8: + case ATOM_SRC_BYTE16: + case ATOM_SRC_BYTE24: + (*ptr)++; + return; + } + return; + } +} + +static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr) +{ + return atom_get_src_int(ctx, attr, ptr, NULL, 1); +} + +static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr) +{ + uint32_t val = 0xCDCDCDCD; + + switch (align) { + case ATOM_SRC_DWORD: + val = U32(*ptr); + (*ptr) += 4; + break; + case ATOM_SRC_WORD0: + case ATOM_SRC_WORD8: + case ATOM_SRC_WORD16: + val = U16(*ptr); + (*ptr) += 2; + break; + case ATOM_SRC_BYTE0: + case ATOM_SRC_BYTE8: + case ATOM_SRC_BYTE16: + case ATOM_SRC_BYTE24: + val = U8(*ptr); + (*ptr)++; + break; + } + return val; +} + +static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr, + int *ptr, uint32_t *saved, int print) +{ + return atom_get_src_int(ctx, + arg | atom_dst_to_src[(attr >> 3) & + 7][(attr >> 6) & 3] << 3, + ptr, saved, print); +} + +static void atom_skip_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr) +{ + atom_skip_src_int(ctx, + arg | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & + 3] << 3, ptr); +} + +static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr, + int *ptr, uint32_t val, uint32_t saved) +{ + uint32_t align = + atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3], old_val = + val, idx; + struct atom_context *gctx = ctx->ctx; + old_val &= atom_arg_mask[align] >> atom_arg_shift[align]; + val <<= atom_arg_shift[align]; + val &= atom_arg_mask[align]; + saved &= ~atom_arg_mask[align]; + val |= saved; + switch (arg) { + case ATOM_ARG_REG: + idx = U16(*ptr); + (*ptr) += 2; + DEBUG("REG[0x%04X]", idx); + idx += gctx->reg_block; + switch (gctx->io_mode) { + case ATOM_IO_MM: + if (idx == 0) + gctx->card->reg_write(gctx->card, idx, + val << 2); + else + gctx->card->reg_write(gctx->card, idx, val); + break; + case ATOM_IO_PCI: + DRM_INFO( + "PCI registers are not implemented.\n"); + return; + case ATOM_IO_SYSIO: + DRM_INFO( + "SYSIO registers are not implemented.\n"); + return; + default: + if (!(gctx->io_mode & 0x80)) { + DRM_INFO("Bad IO mode.\n"); + return; + } + if (!gctx->iio[gctx->io_mode & 0xFF]) { + DRM_INFO( + "Undefined indirect IO write method %d.\n", + gctx->io_mode & 0x7F); + return; + } + atom_iio_execute(gctx, gctx->iio[gctx->io_mode & 0xFF], + idx, val); + } + break; + case ATOM_ARG_PS: + idx = U8(*ptr); + (*ptr)++; + DEBUG("PS[0x%02X]", idx); + ctx->ps[idx] = cpu_to_le32(val); + break; + case ATOM_ARG_WS: + idx = U8(*ptr); + (*ptr)++; + DEBUG("WS[0x%02X]", idx); + switch (idx) { + case ATOM_WS_QUOTIENT: + gctx->divmul[0] = val; + break; + case ATOM_WS_REMAINDER: + gctx->divmul[1] = val; + break; + case ATOM_WS_DATAPTR: + gctx->data_block = val; + break; + case ATOM_WS_SHIFT: + gctx->shift = val; + break; + case ATOM_WS_OR_MASK: + case ATOM_WS_AND_MASK: + break; + case ATOM_WS_FB_WINDOW: + gctx->fb_base = val; + break; + case ATOM_WS_ATTRIBUTES: + gctx->io_attr = val; + break; + case ATOM_WS_REGPTR: + gctx->reg_block = val; + break; + default: + ctx->ws[idx] = val; + } + break; + case ATOM_ARG_FB: + idx = U8(*ptr); + (*ptr)++; + if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) { + DRM_ERROR("ATOM: fb write beyond scratch region: %d vs. %d\n", + gctx->fb_base + (idx * 4), gctx->scratch_size_bytes); + } else + gctx->scratch[(gctx->fb_base / 4) + idx] = val; + DEBUG("FB[0x%02X]", idx); + break; + case ATOM_ARG_PLL: + idx = U8(*ptr); + (*ptr)++; + DEBUG("PLL[0x%02X]", idx); + gctx->card->pll_write(gctx->card, idx, val); + break; + case ATOM_ARG_MC: + idx = U8(*ptr); + (*ptr)++; + DEBUG("MC[0x%02X]", idx); + gctx->card->mc_write(gctx->card, idx, val); + return; + } + switch (align) { + case ATOM_SRC_DWORD: + DEBUG(".[31:0] <- 0x%08X\n", old_val); + break; + case ATOM_SRC_WORD0: + DEBUG(".[15:0] <- 0x%04X\n", old_val); + break; + case ATOM_SRC_WORD8: + DEBUG(".[23:8] <- 0x%04X\n", old_val); + break; + case ATOM_SRC_WORD16: + DEBUG(".[31:16] <- 0x%04X\n", old_val); + break; + case ATOM_SRC_BYTE0: + DEBUG(".[7:0] <- 0x%02X\n", old_val); + break; + case ATOM_SRC_BYTE8: + DEBUG(".[15:8] <- 0x%02X\n", old_val); + break; + case ATOM_SRC_BYTE16: + DEBUG(".[23:16] <- 0x%02X\n", old_val); + break; + case ATOM_SRC_BYTE24: + DEBUG(".[31:24] <- 0x%02X\n", old_val); + break; + } +} + +static void atom_op_add(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src, saved; + int dptr = *ptr; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + dst += src; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_and(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src, saved; + int dptr = *ptr; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + dst &= src; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg) +{ + DRM_INFO("ATOM BIOS beeped!\n"); +} + +static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg) +{ + int idx = U8((*ptr)++); + int r = 0; + + if (idx < ATOM_TABLE_NAMES_CNT) + SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx]); + else + SDEBUG(" table: %d\n", idx); + if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) + r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift); + if (r) { + ctx->abort = true; + } +} + +static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t saved; + int dptr = *ptr; + attr &= 0x38; + attr |= atom_def_dst[attr >> 3] << 6; + atom_get_dst(ctx, arg, attr, ptr, &saved, 0); + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, 0, saved); +} + +static void atom_op_compare(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src; + SDEBUG(" src1: "); + dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); + SDEBUG(" src2: "); + src = atom_get_src(ctx, attr, ptr); + ctx->ctx->cs_equal = (dst == src); + ctx->ctx->cs_above = (dst > src); + SDEBUG(" result: %s %s\n", ctx->ctx->cs_equal ? "EQ" : "NE", + ctx->ctx->cs_above ? "GT" : "LE"); +} + +static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg) +{ + unsigned count = U8((*ptr)++); + SDEBUG(" count: %d\n", count); + if (arg == ATOM_UNIT_MICROSEC) + DRM_UDELAY(count); + else if (!drm_can_sleep()) + DRM_MDELAY(count); + else + DRM_MSLEEP(count); +} + +static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src; + SDEBUG(" src1: "); + dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); + SDEBUG(" src2: "); + src = atom_get_src(ctx, attr, ptr); + if (src != 0) { + ctx->ctx->divmul[0] = dst / src; + ctx->ctx->divmul[1] = dst % src; + } else { + ctx->ctx->divmul[0] = 0; + ctx->ctx->divmul[1] = 0; + } +} + +static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg) +{ + /* functionally, a nop */ +} + +static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) +{ + int execute = 0, target = U16(*ptr); + unsigned long cjiffies; + + (*ptr) += 2; + switch (arg) { + case ATOM_COND_ABOVE: + execute = ctx->ctx->cs_above; + break; + case ATOM_COND_ABOVEOREQUAL: + execute = ctx->ctx->cs_above || ctx->ctx->cs_equal; + break; + case ATOM_COND_ALWAYS: + execute = 1; + break; + case ATOM_COND_BELOW: + execute = !(ctx->ctx->cs_above || ctx->ctx->cs_equal); + break; + case ATOM_COND_BELOWOREQUAL: + execute = !ctx->ctx->cs_above; + break; + case ATOM_COND_EQUAL: + execute = ctx->ctx->cs_equal; + break; + case ATOM_COND_NOTEQUAL: + execute = !ctx->ctx->cs_equal; + break; + } + if (arg != ATOM_COND_ALWAYS) + SDEBUG(" taken: %s\n", execute ? "yes" : "no"); + SDEBUG(" target: 0x%04X\n", target); + if (execute) { + if (ctx->last_jump == (ctx->start + target)) { + cjiffies = jiffies; + if (time_after(cjiffies, ctx->last_jump_jiffies)) { + cjiffies -= ctx->last_jump_jiffies; + if ((jiffies_to_msecs(cjiffies) > 5000)) { + DRM_ERROR("atombios stuck in loop for more than 5secs aborting\n"); + ctx->abort = true; + } + } else { + /* jiffies wrap around we will just wait a little longer */ + ctx->last_jump_jiffies = jiffies; + } + } else { + ctx->last_jump = ctx->start + target; + ctx->last_jump_jiffies = jiffies; + } + *ptr = ctx->start + target; + } +} + +static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, mask, src, saved; + int dptr = *ptr; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + mask = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr); + SDEBUG(" mask: 0x%08x", mask); + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + dst &= mask; + dst |= src; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_move(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t src, saved; + int dptr = *ptr; + if (((attr >> 3) & 7) != ATOM_SRC_DWORD) + atom_get_dst(ctx, arg, attr, ptr, &saved, 0); + else { + atom_skip_dst(ctx, arg, attr, ptr); + saved = 0xCDCDCDCD; + } + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, src, saved); +} + +static void atom_op_mul(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src; + SDEBUG(" src1: "); + dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); + SDEBUG(" src2: "); + src = atom_get_src(ctx, attr, ptr); + ctx->ctx->divmul[0] = dst * src; +} + +static void atom_op_nop(atom_exec_context *ctx, int *ptr, int arg) +{ + /* nothing */ +} + +static void atom_op_or(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src, saved; + int dptr = *ptr; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + dst |= src; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_postcard(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t val = U8((*ptr)++); + SDEBUG("POST card output: 0x%02X\n", val); +} + +static void atom_op_repeat(atom_exec_context *ctx, int *ptr, int arg) +{ + DRM_INFO("unimplemented!\n"); +} + +static void atom_op_restorereg(atom_exec_context *ctx, int *ptr, int arg) +{ + DRM_INFO("unimplemented!\n"); +} + +static void atom_op_savereg(atom_exec_context *ctx, int *ptr, int arg) +{ + DRM_INFO("unimplemented!\n"); +} + +static void atom_op_setdatablock(atom_exec_context *ctx, int *ptr, int arg) +{ + int idx = U8(*ptr); + (*ptr)++; + SDEBUG(" block: %d\n", idx); + if (!idx) + ctx->ctx->data_block = 0; + else if (idx == 255) + ctx->ctx->data_block = ctx->start; + else + ctx->ctx->data_block = U16(ctx->ctx->data_table + 4 + 2 * idx); + SDEBUG(" base: 0x%04X\n", ctx->ctx->data_block); +} + +static void atom_op_setfbbase(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + SDEBUG(" fb_base: "); + ctx->ctx->fb_base = atom_get_src(ctx, attr, ptr); +} + +static void atom_op_setport(atom_exec_context *ctx, int *ptr, int arg) +{ + int port; + switch (arg) { + case ATOM_PORT_ATI: + port = U16(*ptr); + if (port < ATOM_IO_NAMES_CNT) + SDEBUG(" port: %d (%s)\n", port, atom_io_names[port]); + else + SDEBUG(" port: %d\n", port); + if (!port) + ctx->ctx->io_mode = ATOM_IO_MM; + else + ctx->ctx->io_mode = ATOM_IO_IIO | port; + (*ptr) += 2; + break; + case ATOM_PORT_PCI: + ctx->ctx->io_mode = ATOM_IO_PCI; + (*ptr)++; + break; + case ATOM_PORT_SYSIO: + ctx->ctx->io_mode = ATOM_IO_SYSIO; + (*ptr)++; + break; + } +} + +static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg) +{ + ctx->ctx->reg_block = U16(*ptr); + (*ptr) += 2; + SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block); +} + +static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++), shift; + uint32_t saved, dst; + int dptr = *ptr; + attr &= 0x38; + attr |= atom_def_dst[attr >> 3] << 6; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr); + SDEBUG(" shift: %d\n", shift); + dst <<= shift; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++), shift; + uint32_t saved, dst; + int dptr = *ptr; + attr &= 0x38; + attr |= atom_def_dst[attr >> 3] << 6; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr); + SDEBUG(" shift: %d\n", shift); + dst >>= shift; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++), shift; + uint32_t saved, dst; + int dptr = *ptr; + uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3]; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + /* op needs to full dst value */ + dst = saved; + shift = atom_get_src(ctx, attr, ptr); + SDEBUG(" shift: %d\n", shift); + dst <<= shift; + dst &= atom_arg_mask[dst_align]; + dst >>= atom_arg_shift[dst_align]; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++), shift; + uint32_t saved, dst; + int dptr = *ptr; + uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3]; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + /* op needs to full dst value */ + dst = saved; + shift = atom_get_src(ctx, attr, ptr); + SDEBUG(" shift: %d\n", shift); + dst >>= shift; + dst &= atom_arg_mask[dst_align]; + dst >>= atom_arg_shift[dst_align]; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_sub(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src, saved; + int dptr = *ptr; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + dst -= src; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_switch(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t src, val, target; + SDEBUG(" switch: "); + src = atom_get_src(ctx, attr, ptr); + while (U16(*ptr) != ATOM_CASE_END) + if (U8(*ptr) == ATOM_CASE_MAGIC) { + (*ptr)++; + SDEBUG(" case: "); + val = + atom_get_src(ctx, (attr & 0x38) | ATOM_ARG_IMM, + ptr); + target = U16(*ptr); + if (val == src) { + SDEBUG(" target: %04X\n", target); + *ptr = ctx->start + target; + return; + } + (*ptr) += 2; + } else { + DRM_INFO("Bad case.\n"); + return; + } + (*ptr) += 2; +} + +static void atom_op_test(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src; + SDEBUG(" src1: "); + dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); + SDEBUG(" src2: "); + src = atom_get_src(ctx, attr, ptr); + ctx->ctx->cs_equal = ((dst & src) == 0); + SDEBUG(" result: %s\n", ctx->ctx->cs_equal ? "EQ" : "NE"); +} + +static void atom_op_xor(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++); + uint32_t dst, src, saved; + int dptr = *ptr; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + SDEBUG(" src: "); + src = atom_get_src(ctx, attr, ptr); + dst ^= src; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_debug(atom_exec_context *ctx, int *ptr, int arg) +{ + DRM_INFO("unimplemented!\n"); +} + +static struct { + void (*func) (atom_exec_context *, int *, int); + int arg; +} opcode_table[ATOM_OP_CNT] = { + { + NULL, 0}, { + atom_op_move, ATOM_ARG_REG}, { + atom_op_move, ATOM_ARG_PS}, { + atom_op_move, ATOM_ARG_WS}, { + atom_op_move, ATOM_ARG_FB}, { + atom_op_move, ATOM_ARG_PLL}, { + atom_op_move, ATOM_ARG_MC}, { + atom_op_and, ATOM_ARG_REG}, { + atom_op_and, ATOM_ARG_PS}, { + atom_op_and, ATOM_ARG_WS}, { + atom_op_and, ATOM_ARG_FB}, { + atom_op_and, ATOM_ARG_PLL}, { + atom_op_and, ATOM_ARG_MC}, { + atom_op_or, ATOM_ARG_REG}, { + atom_op_or, ATOM_ARG_PS}, { + atom_op_or, ATOM_ARG_WS}, { + atom_op_or, ATOM_ARG_FB}, { + atom_op_or, ATOM_ARG_PLL}, { + atom_op_or, ATOM_ARG_MC}, { + atom_op_shift_left, ATOM_ARG_REG}, { + atom_op_shift_left, ATOM_ARG_PS}, { + atom_op_shift_left, ATOM_ARG_WS}, { + atom_op_shift_left, ATOM_ARG_FB}, { + atom_op_shift_left, ATOM_ARG_PLL}, { + atom_op_shift_left, ATOM_ARG_MC}, { + atom_op_shift_right, ATOM_ARG_REG}, { + atom_op_shift_right, ATOM_ARG_PS}, { + atom_op_shift_right, ATOM_ARG_WS}, { + atom_op_shift_right, ATOM_ARG_FB}, { + atom_op_shift_right, ATOM_ARG_PLL}, { + atom_op_shift_right, ATOM_ARG_MC}, { + atom_op_mul, ATOM_ARG_REG}, { + atom_op_mul, ATOM_ARG_PS}, { + atom_op_mul, ATOM_ARG_WS}, { + atom_op_mul, ATOM_ARG_FB}, { + atom_op_mul, ATOM_ARG_PLL}, { + atom_op_mul, ATOM_ARG_MC}, { + atom_op_div, ATOM_ARG_REG}, { + atom_op_div, ATOM_ARG_PS}, { + atom_op_div, ATOM_ARG_WS}, { + atom_op_div, ATOM_ARG_FB}, { + atom_op_div, ATOM_ARG_PLL}, { + atom_op_div, ATOM_ARG_MC}, { + atom_op_add, ATOM_ARG_REG}, { + atom_op_add, ATOM_ARG_PS}, { + atom_op_add, ATOM_ARG_WS}, { + atom_op_add, ATOM_ARG_FB}, { + atom_op_add, ATOM_ARG_PLL}, { + atom_op_add, ATOM_ARG_MC}, { + atom_op_sub, ATOM_ARG_REG}, { + atom_op_sub, ATOM_ARG_PS}, { + atom_op_sub, ATOM_ARG_WS}, { + atom_op_sub, ATOM_ARG_FB}, { + atom_op_sub, ATOM_ARG_PLL}, { + atom_op_sub, ATOM_ARG_MC}, { + atom_op_setport, ATOM_PORT_ATI}, { + atom_op_setport, ATOM_PORT_PCI}, { + atom_op_setport, ATOM_PORT_SYSIO}, { + atom_op_setregblock, 0}, { + atom_op_setfbbase, 0}, { + atom_op_compare, ATOM_ARG_REG}, { + atom_op_compare, ATOM_ARG_PS}, { + atom_op_compare, ATOM_ARG_WS}, { + atom_op_compare, ATOM_ARG_FB}, { + atom_op_compare, ATOM_ARG_PLL}, { + atom_op_compare, ATOM_ARG_MC}, { + atom_op_switch, 0}, { + atom_op_jump, ATOM_COND_ALWAYS}, { + atom_op_jump, ATOM_COND_EQUAL}, { + atom_op_jump, ATOM_COND_BELOW}, { + atom_op_jump, ATOM_COND_ABOVE}, { + atom_op_jump, ATOM_COND_BELOWOREQUAL}, { + atom_op_jump, ATOM_COND_ABOVEOREQUAL}, { + atom_op_jump, ATOM_COND_NOTEQUAL}, { + atom_op_test, ATOM_ARG_REG}, { + atom_op_test, ATOM_ARG_PS}, { + atom_op_test, ATOM_ARG_WS}, { + atom_op_test, ATOM_ARG_FB}, { + atom_op_test, ATOM_ARG_PLL}, { + atom_op_test, ATOM_ARG_MC}, { + atom_op_delay, ATOM_UNIT_MILLISEC}, { + atom_op_delay, ATOM_UNIT_MICROSEC}, { + atom_op_calltable, 0}, { + atom_op_repeat, 0}, { + atom_op_clear, ATOM_ARG_REG}, { + atom_op_clear, ATOM_ARG_PS}, { + atom_op_clear, ATOM_ARG_WS}, { + atom_op_clear, ATOM_ARG_FB}, { + atom_op_clear, ATOM_ARG_PLL}, { + atom_op_clear, ATOM_ARG_MC}, { + atom_op_nop, 0}, { + atom_op_eot, 0}, { + atom_op_mask, ATOM_ARG_REG}, { + atom_op_mask, ATOM_ARG_PS}, { + atom_op_mask, ATOM_ARG_WS}, { + atom_op_mask, ATOM_ARG_FB}, { + atom_op_mask, ATOM_ARG_PLL}, { + atom_op_mask, ATOM_ARG_MC}, { + atom_op_postcard, 0}, { + atom_op_beep, 0}, { + atom_op_savereg, 0}, { + atom_op_restorereg, 0}, { + atom_op_setdatablock, 0}, { + atom_op_xor, ATOM_ARG_REG}, { + atom_op_xor, ATOM_ARG_PS}, { + atom_op_xor, ATOM_ARG_WS}, { + atom_op_xor, ATOM_ARG_FB}, { + atom_op_xor, ATOM_ARG_PLL}, { + atom_op_xor, ATOM_ARG_MC}, { + atom_op_shl, ATOM_ARG_REG}, { + atom_op_shl, ATOM_ARG_PS}, { + atom_op_shl, ATOM_ARG_WS}, { + atom_op_shl, ATOM_ARG_FB}, { + atom_op_shl, ATOM_ARG_PLL}, { + atom_op_shl, ATOM_ARG_MC}, { + atom_op_shr, ATOM_ARG_REG}, { + atom_op_shr, ATOM_ARG_PS}, { + atom_op_shr, ATOM_ARG_WS}, { + atom_op_shr, ATOM_ARG_FB}, { + atom_op_shr, ATOM_ARG_PLL}, { + atom_op_shr, ATOM_ARG_MC}, { +atom_op_debug, 0},}; + +static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params) +{ + int base = CU16(ctx->cmd_table + 4 + 2 * index); + int len, ws, ps, ptr; + unsigned char op; + atom_exec_context ectx; + int ret = 0; + + if (!base) + return -EINVAL; + + len = CU16(base + ATOM_CT_SIZE_PTR); + ws = CU8(base + ATOM_CT_WS_PTR); + ps = CU8(base + ATOM_CT_PS_PTR) & ATOM_CT_PS_MASK; + ptr = base + ATOM_CT_CODE_PTR; + + SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps); + + ectx.ctx = ctx; + ectx.ps_shift = ps / 4; + ectx.start = base; + ectx.ps = params; + ectx.abort = false; + ectx.last_jump = 0; + if (ws) + ectx.ws = malloc(4 * ws, DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + else + ectx.ws = NULL; + + debug_depth++; + while (1) { + op = CU8(ptr++); + if (op < ATOM_OP_NAMES_CNT) + SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1); + else + SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1); + if (ectx.abort) { + DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n", + base, len, ws, ps, ptr - 1); + ret = -EINVAL; + goto free; + } + + if (op < ATOM_OP_CNT && op > 0) + opcode_table[op].func(&ectx, &ptr, + opcode_table[op].arg); + else + break; + + if (op == ATOM_OP_EOT) + break; + } + debug_depth--; + SDEBUG("<<\n"); + +free: + if (ws) + free(ectx.ws, DRM_MEM_DRIVER); + return ret; +} + +int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) +{ + int r; + + sx_xlock(&ctx->mutex); + /* reset reg block */ + ctx->reg_block = 0; + /* reset fb window */ + ctx->fb_base = 0; + /* reset io mode */ + ctx->io_mode = ATOM_IO_MM; + r = atom_execute_table_locked(ctx, index, params); + sx_xunlock(&ctx->mutex); + return r; +} + +static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; + +static void atom_index_iio(struct atom_context *ctx, int base) +{ + ctx->iio = malloc(2 * 256, DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + while (CU8(base) == ATOM_IIO_START) { + ctx->iio[CU8(base + 1)] = base + 2; + base += 2; + while (CU8(base) != ATOM_IIO_END) + base += atom_iio_len[CU8(base)]; + base += 3; + } +} + +struct atom_context *atom_parse(struct card_info *card, void *bios) +{ + int base; + struct atom_context *ctx = + malloc(sizeof(struct atom_context), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + char *str; + char name[512]; + int i; + + if (!ctx) + return NULL; + + ctx->card = card; + ctx->bios = bios; + + if (CU16(0) != ATOM_BIOS_MAGIC) { + DRM_INFO("Invalid BIOS magic.\n"); + free(ctx, DRM_MEM_DRIVER); + return NULL; + } + if (strncmp + (CSTR(ATOM_ATI_MAGIC_PTR), ATOM_ATI_MAGIC, + strlen(ATOM_ATI_MAGIC))) { + DRM_INFO("Invalid ATI magic.\n"); + free(ctx, DRM_MEM_DRIVER); + return NULL; + } + + base = CU16(ATOM_ROM_TABLE_PTR); + if (strncmp + (CSTR(base + ATOM_ROM_MAGIC_PTR), ATOM_ROM_MAGIC, + strlen(ATOM_ROM_MAGIC))) { + DRM_INFO("Invalid ATOM magic.\n"); + free(ctx, DRM_MEM_DRIVER); + return NULL; + } + + ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR); + ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR); + atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR) + 4); + + str = CSTR(CU16(base + ATOM_ROM_MSG_PTR)); + while (*str && ((*str == '\n') || (*str == '\r'))) + str++; + /* name string isn't always 0 terminated */ + for (i = 0; i < 511; i++) { + name[i] = str[i]; + if (name[i] < '.' || name[i] > 'z') { + name[i] = 0; + break; + } + } + DRM_INFO("ATOM BIOS: %s\n", name); + + return ctx; +} + +int atom_asic_init(struct atom_context *ctx) +{ + struct radeon_device *rdev = ctx->card->dev->dev_private; + int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR); + uint32_t ps[16]; + int ret; + + memset(ps, 0, 64); + + ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR)); + ps[1] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFMCLK_PTR)); + if (!ps[0] || !ps[1]) + return 1; + + if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT)) + return 1; + ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps); + if (ret) + return ret; + + memset(ps, 0, 64); + + if (rdev->family < CHIP_R600) { + if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL)) + atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps); + } + return ret; +} + +void atom_destroy(struct atom_context *ctx) +{ + if (ctx->iio) + free(ctx->iio, DRM_MEM_DRIVER); + free(ctx, DRM_MEM_DRIVER); +} + +bool atom_parse_data_header(struct atom_context *ctx, int index, + uint16_t * size, uint8_t * frev, uint8_t * crev, + uint16_t * data_start) +{ + int offset = index * 2 + 4; + int idx = CU16(ctx->data_table + offset); + u16 *mdt = (u16 *)((char *)ctx->bios + ctx->data_table + 4); + + if (!mdt[index]) + return false; + + if (size) + *size = CU16(idx); + if (frev) + *frev = CU8(idx + 2); + if (crev) + *crev = CU8(idx + 3); + *data_start = idx; + return true; +} + +bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, + uint8_t * crev) +{ + int offset = index * 2 + 4; + int idx = CU16(ctx->cmd_table + offset); + u16 *mct = (u16 *)((char *)ctx->bios + ctx->cmd_table + 4); + + if (!mct[index]) + return false; + + if (frev) + *frev = CU8(idx + 2); + if (crev) + *crev = CU8(idx + 3); + return true; +} + +int atom_allocate_fb_scratch(struct atom_context *ctx) +{ + int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware); + uint16_t data_offset; + int usage_bytes = 0; + struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage; + + if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { + firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)((char *)ctx->bios + data_offset); + + DRM_DEBUG("atom firmware requested %08x %dkb\n", + firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware, + firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); + + usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024; + } + ctx->scratch_size_bytes = 0; + if (usage_bytes == 0) + usage_bytes = 20 * 1024; + /* allocate some scratch memory */ + ctx->scratch = malloc(usage_bytes, DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!ctx->scratch) + return -ENOMEM; + ctx->scratch_size_bytes = usage_bytes; + return 0; +} diff --git a/sys/dev/drm2/radeon/atom.h b/sys/dev/drm2/radeon/atom.h new file mode 100644 index 00000000000..dbca87ba888 --- /dev/null +++ b/sys/dev/drm2/radeon/atom.h @@ -0,0 +1,161 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Stanislaw Skowronek + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef ATOM_H +#define ATOM_H + +#include + +#define ATOM_BIOS_MAGIC 0xAA55 +#define ATOM_ATI_MAGIC_PTR 0x30 +#define ATOM_ATI_MAGIC " 761295520" +#define ATOM_ROM_TABLE_PTR 0x48 + +#define ATOM_ROM_MAGIC "ATOM" +#define ATOM_ROM_MAGIC_PTR 4 + +#define ATOM_ROM_MSG_PTR 0x10 +#define ATOM_ROM_CMD_PTR 0x1E +#define ATOM_ROM_DATA_PTR 0x20 + +#define ATOM_CMD_INIT 0 +#define ATOM_CMD_SETSCLK 0x0A +#define ATOM_CMD_SETMCLK 0x0B +#define ATOM_CMD_SETPCLK 0x0C +#define ATOM_CMD_SPDFANCNTL 0x39 + +#define ATOM_DATA_FWI_PTR 0xC +#define ATOM_DATA_IIO_PTR 0x32 + +#define ATOM_FWI_DEFSCLK_PTR 8 +#define ATOM_FWI_DEFMCLK_PTR 0xC +#define ATOM_FWI_MAXSCLK_PTR 0x24 +#define ATOM_FWI_MAXMCLK_PTR 0x28 + +#define ATOM_CT_SIZE_PTR 0 +#define ATOM_CT_WS_PTR 4 +#define ATOM_CT_PS_PTR 5 +#define ATOM_CT_PS_MASK 0x7F +#define ATOM_CT_CODE_PTR 6 + +#define ATOM_OP_CNT 123 +#define ATOM_OP_EOT 91 + +#define ATOM_CASE_MAGIC 0x63 +#define ATOM_CASE_END 0x5A5A + +#define ATOM_ARG_REG 0 +#define ATOM_ARG_PS 1 +#define ATOM_ARG_WS 2 +#define ATOM_ARG_FB 3 +#define ATOM_ARG_ID 4 +#define ATOM_ARG_IMM 5 +#define ATOM_ARG_PLL 6 +#define ATOM_ARG_MC 7 + +#define ATOM_SRC_DWORD 0 +#define ATOM_SRC_WORD0 1 +#define ATOM_SRC_WORD8 2 +#define ATOM_SRC_WORD16 3 +#define ATOM_SRC_BYTE0 4 +#define ATOM_SRC_BYTE8 5 +#define ATOM_SRC_BYTE16 6 +#define ATOM_SRC_BYTE24 7 + +#define ATOM_WS_QUOTIENT 0x40 +#define ATOM_WS_REMAINDER 0x41 +#define ATOM_WS_DATAPTR 0x42 +#define ATOM_WS_SHIFT 0x43 +#define ATOM_WS_OR_MASK 0x44 +#define ATOM_WS_AND_MASK 0x45 +#define ATOM_WS_FB_WINDOW 0x46 +#define ATOM_WS_ATTRIBUTES 0x47 +#define ATOM_WS_REGPTR 0x48 + +#define ATOM_IIO_NOP 0 +#define ATOM_IIO_START 1 +#define ATOM_IIO_READ 2 +#define ATOM_IIO_WRITE 3 +#define ATOM_IIO_CLEAR 4 +#define ATOM_IIO_SET 5 +#define ATOM_IIO_MOVE_INDEX 6 +#define ATOM_IIO_MOVE_ATTR 7 +#define ATOM_IIO_MOVE_DATA 8 +#define ATOM_IIO_END 9 + +#define ATOM_IO_MM 0 +#define ATOM_IO_PCI 1 +#define ATOM_IO_SYSIO 2 +#define ATOM_IO_IIO 0x80 + +struct card_info { + struct drm_device *dev; + void (* reg_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ + uint32_t (* reg_read)(struct card_info *, uint32_t); /* filled by driver */ + void (* ioreg_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ + uint32_t (* ioreg_read)(struct card_info *, uint32_t); /* filled by driver */ + void (* mc_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ + uint32_t (* mc_read)(struct card_info *, uint32_t); /* filled by driver */ + void (* pll_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ + uint32_t (* pll_read)(struct card_info *, uint32_t); /* filled by driver */ +}; + +struct atom_context { + struct card_info *card; + struct sx mutex; + void *bios; + uint32_t cmd_table, data_table; + uint16_t *iio; + + uint16_t data_block; + uint32_t fb_base; + uint32_t divmul[2]; + uint16_t io_attr; + uint16_t reg_block; + uint8_t shift; + int cs_equal, cs_above; + int io_mode; + uint32_t *scratch; + int scratch_size_bytes; +}; + +extern int atom_debug; + +struct atom_context *atom_parse(struct card_info *, void *); +int atom_execute_table(struct atom_context *, int, uint32_t *); +int atom_asic_init(struct atom_context *); +void atom_destroy(struct atom_context *); +bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, + uint8_t *frev, uint8_t *crev, uint16_t *data_start); +bool atom_parse_cmd_header(struct atom_context *ctx, int index, + uint8_t *frev, uint8_t *crev); +int atom_allocate_fb_scratch(struct atom_context *ctx); +#include "atom-types.h" +#include "atombios.h" +#include "ObjectID.h" + +#endif diff --git a/sys/dev/drm2/radeon/atombios.h b/sys/dev/drm2/radeon/atombios.h new file mode 100644 index 00000000000..8ef8196fb30 --- /dev/null +++ b/sys/dev/drm2/radeon/atombios.h @@ -0,0 +1,8013 @@ +/* + * Copyright 2006-2007 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + + +/****************************************************************************/ +/*Portion I: Definitions shared between VBIOS and Driver */ +/****************************************************************************/ + + +#ifndef _ATOMBIOS_H +#define _ATOMBIOS_H + +#define ATOM_VERSION_MAJOR 0x00020000 +#define ATOM_VERSION_MINOR 0x00000002 + +#define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR) + +/* Endianness should be specified before inclusion, + * default to little endian + */ +#ifndef ATOM_BIG_ENDIAN +#error Endian not specified +#endif + +#ifdef _H2INC + #ifndef ULONG + typedef unsigned long ULONG; + #endif + + #ifndef UCHAR + typedef unsigned char UCHAR; + #endif + + #ifndef USHORT + typedef unsigned short USHORT; + #endif +#endif + +#define ATOM_DAC_A 0 +#define ATOM_DAC_B 1 +#define ATOM_EXT_DAC 2 + +#define ATOM_CRTC1 0 +#define ATOM_CRTC2 1 +#define ATOM_CRTC3 2 +#define ATOM_CRTC4 3 +#define ATOM_CRTC5 4 +#define ATOM_CRTC6 5 +#define ATOM_CRTC_INVALID 0xFF + +#define ATOM_DIGA 0 +#define ATOM_DIGB 1 + +#define ATOM_PPLL1 0 +#define ATOM_PPLL2 1 +#define ATOM_DCPLL 2 +#define ATOM_PPLL0 2 +#define ATOM_EXT_PLL1 8 +#define ATOM_EXT_PLL2 9 +#define ATOM_EXT_CLOCK 10 +#define ATOM_PPLL_INVALID 0xFF + +#define ENCODER_REFCLK_SRC_P1PLL 0 +#define ENCODER_REFCLK_SRC_P2PLL 1 +#define ENCODER_REFCLK_SRC_DCPLL 2 +#define ENCODER_REFCLK_SRC_EXTCLK 3 +#define ENCODER_REFCLK_SRC_INVALID 0xFF + +#define ATOM_SCALER1 0 +#define ATOM_SCALER2 1 + +#define ATOM_SCALER_DISABLE 0 +#define ATOM_SCALER_CENTER 1 +#define ATOM_SCALER_EXPANSION 2 +#define ATOM_SCALER_MULTI_EX 3 + +#define ATOM_DISABLE 0 +#define ATOM_ENABLE 1 +#define ATOM_LCD_BLOFF (ATOM_DISABLE+2) +#define ATOM_LCD_BLON (ATOM_ENABLE+2) +#define ATOM_LCD_BL_BRIGHTNESS_CONTROL (ATOM_ENABLE+3) +#define ATOM_LCD_SELFTEST_START (ATOM_DISABLE+5) +#define ATOM_LCD_SELFTEST_STOP (ATOM_ENABLE+5) +#define ATOM_ENCODER_INIT (ATOM_DISABLE+7) +#define ATOM_INIT (ATOM_DISABLE+7) +#define ATOM_GET_STATUS (ATOM_DISABLE+8) + +#define ATOM_BLANKING 1 +#define ATOM_BLANKING_OFF 0 + +#define ATOM_CURSOR1 0 +#define ATOM_CURSOR2 1 + +#define ATOM_ICON1 0 +#define ATOM_ICON2 1 + +#define ATOM_CRT1 0 +#define ATOM_CRT2 1 + +#define ATOM_TV_NTSC 1 +#define ATOM_TV_NTSCJ 2 +#define ATOM_TV_PAL 3 +#define ATOM_TV_PALM 4 +#define ATOM_TV_PALCN 5 +#define ATOM_TV_PALN 6 +#define ATOM_TV_PAL60 7 +#define ATOM_TV_SECAM 8 +#define ATOM_TV_CV 16 + +#define ATOM_DAC1_PS2 1 +#define ATOM_DAC1_CV 2 +#define ATOM_DAC1_NTSC 3 +#define ATOM_DAC1_PAL 4 + +#define ATOM_DAC2_PS2 ATOM_DAC1_PS2 +#define ATOM_DAC2_CV ATOM_DAC1_CV +#define ATOM_DAC2_NTSC ATOM_DAC1_NTSC +#define ATOM_DAC2_PAL ATOM_DAC1_PAL + +#define ATOM_PM_ON 0 +#define ATOM_PM_STANDBY 1 +#define ATOM_PM_SUSPEND 2 +#define ATOM_PM_OFF 3 + +/* Bit0:{=0:single, =1:dual}, + Bit1 {=0:666RGB, =1:888RGB}, + Bit2:3:{Grey level} + Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888}*/ + +#define ATOM_PANEL_MISC_DUAL 0x00000001 +#define ATOM_PANEL_MISC_888RGB 0x00000002 +#define ATOM_PANEL_MISC_GREY_LEVEL 0x0000000C +#define ATOM_PANEL_MISC_FPDI 0x00000010 +#define ATOM_PANEL_MISC_GREY_LEVEL_SHIFT 2 +#define ATOM_PANEL_MISC_SPATIAL 0x00000020 +#define ATOM_PANEL_MISC_TEMPORAL 0x00000040 +#define ATOM_PANEL_MISC_API_ENABLED 0x00000080 + + +#define MEMTYPE_DDR1 "DDR1" +#define MEMTYPE_DDR2 "DDR2" +#define MEMTYPE_DDR3 "DDR3" +#define MEMTYPE_DDR4 "DDR4" + +#define ASIC_BUS_TYPE_PCI "PCI" +#define ASIC_BUS_TYPE_AGP "AGP" +#define ASIC_BUS_TYPE_PCIE "PCI_EXPRESS" + +/* Maximum size of that FireGL flag string */ + +#define ATOM_FIREGL_FLAG_STRING "FGL" //Flag used to enable FireGL Support +#define ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING 3 //sizeof( ATOM_FIREGL_FLAG_STRING ) + +#define ATOM_FAKE_DESKTOP_STRING "DSK" //Flag used to enable mobile ASIC on Desktop +#define ATOM_MAX_SIZE_OF_FAKE_DESKTOP_STRING ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING + +#define ATOM_M54T_FLAG_STRING "M54T" //Flag used to enable M54T Support +#define ATOM_MAX_SIZE_OF_M54T_FLAG_STRING 4 //sizeof( ATOM_M54T_FLAG_STRING ) + +#define HW_ASSISTED_I2C_STATUS_FAILURE 2 +#define HW_ASSISTED_I2C_STATUS_SUCCESS 1 + +#pragma pack(1) /* BIOS data must use byte aligment */ + +/* Define offset to location of ROM header. */ + +#define OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER 0x00000048L +#define OFFSET_TO_ATOM_ROM_IMAGE_SIZE 0x00000002L + +#define OFFSET_TO_ATOMBIOS_ASIC_BUS_MEM_TYPE 0x94 +#define MAXSIZE_OF_ATOMBIOS_ASIC_BUS_MEM_TYPE 20 /* including the terminator 0x0! */ +#define OFFSET_TO_GET_ATOMBIOS_STRINGS_NUMBER 0x002f +#define OFFSET_TO_GET_ATOMBIOS_STRINGS_START 0x006e + +/* Common header for all ROM Data tables. + Every table pointed _ATOM_MASTER_DATA_TABLE has this common header. + And the pointer actually points to this header. */ + +typedef struct _ATOM_COMMON_TABLE_HEADER +{ + USHORT usStructureSize; + UCHAR ucTableFormatRevision; /*Change it when the Parser is not backward compatible */ + UCHAR ucTableContentRevision; /*Change it only when the table needs to change but the firmware */ + /*Image can't be updated, while Driver needs to carry the new table! */ +}ATOM_COMMON_TABLE_HEADER; + +/****************************************************************************/ +// Structure stores the ROM header. +/****************************************************************************/ +typedef struct _ATOM_ROM_HEADER +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR uaFirmWareSignature[4]; /*Signature to distinguish between Atombios and non-atombios, + atombios should init it as "ATOM", don't change the position */ + USHORT usBiosRuntimeSegmentAddress; + USHORT usProtectedModeInfoOffset; + USHORT usConfigFilenameOffset; + USHORT usCRC_BlockOffset; + USHORT usBIOS_BootupMessageOffset; + USHORT usInt10Offset; + USHORT usPciBusDevInitCode; + USHORT usIoBaseAddress; + USHORT usSubsystemVendorID; + USHORT usSubsystemID; + USHORT usPCI_InfoOffset; + USHORT usMasterCommandTableOffset; /*Offset for SW to get all command table offsets, Don't change the position */ + USHORT usMasterDataTableOffset; /*Offset for SW to get all data table offsets, Don't change the position */ + UCHAR ucExtendedFunctionCode; + UCHAR ucReserved; +}ATOM_ROM_HEADER; + +/*==============================Command Table Portion==================================== */ + +#ifdef UEFI_BUILD + #define UTEMP USHORT + #define USHORT void* +#endif + +/****************************************************************************/ +// Structures used in Command.mtb +/****************************************************************************/ +typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{ + USHORT ASIC_Init; //Function Table, used by various SW components,latest version 1.1 + USHORT GetDisplaySurfaceSize; //Atomic Table, Used by Bios when enabling HW ICON + USHORT ASIC_RegistersInit; //Atomic Table, indirectly used by various SW components,called from ASIC_Init + USHORT VRAM_BlockVenderDetection; //Atomic Table, used only by Bios + USHORT DIGxEncoderControl; //Only used by Bios + USHORT MemoryControllerInit; //Atomic Table, indirectly used by various SW components,called from ASIC_Init + USHORT EnableCRTCMemReq; //Function Table,directly used by various SW components,latest version 2.1 + USHORT MemoryParamAdjust; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock if needed + USHORT DVOEncoderControl; //Function Table,directly used by various SW components,latest version 1.2 + USHORT GPIOPinControl; //Atomic Table, only used by Bios + USHORT SetEngineClock; //Function Table,directly used by various SW components,latest version 1.1 + USHORT SetMemoryClock; //Function Table,directly used by various SW components,latest version 1.1 + USHORT SetPixelClock; //Function Table,directly used by various SW components,latest version 1.2 + USHORT EnableDispPowerGating; //Atomic Table, indirectly used by various SW components,called from ASIC_Init + USHORT ResetMemoryDLL; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock + USHORT ResetMemoryDevice; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock + USHORT MemoryPLLInit; //Atomic Table, used only by Bios + USHORT AdjustDisplayPll; //Atomic Table, used by various SW componentes. + USHORT AdjustMemoryController; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock + USHORT EnableASIC_StaticPwrMgt; //Atomic Table, only used by Bios + USHORT ASIC_StaticPwrMgtStatusChange; //Obsolete , only used by Bios + USHORT DAC_LoadDetection; //Atomic Table, directly used by various SW components,latest version 1.2 + USHORT LVTMAEncoderControl; //Atomic Table,directly used by various SW components,latest version 1.3 + USHORT HW_Misc_Operation; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT DAC1EncoderControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT DAC2EncoderControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT DVOOutputControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT CV1OutputControl; //Atomic Table, Atomic Table, Obsolete from Ry6xx, use DAC2 Output instead + USHORT GetConditionalGoldenSetting; //Only used by Bios + USHORT TVEncoderControl; //Function Table,directly used by various SW components,latest version 1.1 + USHORT PatchMCSetting; //only used by BIOS + USHORT MC_SEQ_Control; //only used by BIOS + USHORT TV1OutputControl; //Atomic Table, Obsolete from Ry6xx, use DAC2 Output instead + USHORT EnableScaler; //Atomic Table, used only by Bios + USHORT BlankCRTC; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT EnableCRTC; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT GetPixelClock; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT EnableVGA_Render; //Function Table,directly used by various SW components,latest version 1.1 + USHORT GetSCLKOverMCLKRatio; //Atomic Table, only used by Bios + USHORT SetCRTC_Timing; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT SetCRTC_OverScan; //Atomic Table, used by various SW components,latest version 1.1 + USHORT SetCRTC_Replication; //Atomic Table, used only by Bios + USHORT SelectCRTC_Source; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT EnableGraphSurfaces; //Atomic Table, used only by Bios + USHORT UpdateCRTC_DoubleBufferRegisters; //Atomic Table, used only by Bios + USHORT LUT_AutoFill; //Atomic Table, only used by Bios + USHORT EnableHW_IconCursor; //Atomic Table, only used by Bios + USHORT GetMemoryClock; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT GetEngineClock; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT SetCRTC_UsingDTDTiming; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT ExternalEncoderControl; //Atomic Table, directly used by various SW components,latest version 2.1 + USHORT LVTMAOutputControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT VRAM_BlockDetectionByStrap; //Atomic Table, used only by Bios + USHORT MemoryCleanUp; //Atomic Table, only used by Bios + USHORT ProcessI2cChannelTransaction; //Function Table,only used by Bios + USHORT WriteOneByteToHWAssistedI2C; //Function Table,indirectly used by various SW components + USHORT ReadHWAssistedI2CStatus; //Atomic Table, indirectly used by various SW components + USHORT SpeedFanControl; //Function Table,indirectly used by various SW components,called from ASIC_Init + USHORT PowerConnectorDetection; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT MC_Synchronization; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock + USHORT ComputeMemoryEnginePLL; //Atomic Table, indirectly used by various SW components,called from SetMemory/EngineClock + USHORT MemoryRefreshConversion; //Atomic Table, indirectly used by various SW components,called from SetMemory or SetEngineClock + USHORT VRAM_GetCurrentInfoBlock; //Atomic Table, used only by Bios + USHORT DynamicMemorySettings; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock + USHORT MemoryTraining; //Atomic Table, used only by Bios + USHORT EnableSpreadSpectrumOnPPLL; //Atomic Table, directly used by various SW components,latest version 1.2 + USHORT TMDSAOutputControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT SetVoltage; //Function Table,directly and/or indirectly used by various SW components,latest version 1.1 + USHORT DAC1OutputControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT DAC2OutputControl; //Atomic Table, directly used by various SW components,latest version 1.1 + USHORT ComputeMemoryClockParam; //Function Table,only used by Bios, obsolete soon.Switch to use "ReadEDIDFromHWAssistedI2C" + USHORT ClockSource; //Atomic Table, indirectly used by various SW components,called from ASIC_Init + USHORT MemoryDeviceInit; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock + USHORT GetDispObjectInfo; //Atomic Table, indirectly used by various SW components,called from EnableVGARender + USHORT DIG1EncoderControl; //Atomic Table,directly used by various SW components,latest version 1.1 + USHORT DIG2EncoderControl; //Atomic Table,directly used by various SW components,latest version 1.1 + USHORT DIG1TransmitterControl; //Atomic Table,directly used by various SW components,latest version 1.1 + USHORT DIG2TransmitterControl; //Atomic Table,directly used by various SW components,latest version 1.1 + USHORT ProcessAuxChannelTransaction; //Function Table,only used by Bios + USHORT DPEncoderService; //Function Table,only used by Bios + USHORT GetVoltageInfo; //Function Table,only used by Bios since SI +}ATOM_MASTER_LIST_OF_COMMAND_TABLES; + +// For backward compatible +#define ReadEDIDFromHWAssistedI2C ProcessI2cChannelTransaction +#define DPTranslatorControl DIG2EncoderControl +#define UNIPHYTransmitterControl DIG1TransmitterControl +#define LVTMATransmitterControl DIG2TransmitterControl +#define SetCRTC_DPM_State GetConditionalGoldenSetting +#define SetUniphyInstance ASIC_StaticPwrMgtStatusChange +#define HPDInterruptService ReadHWAssistedI2CStatus +#define EnableVGA_Access GetSCLKOverMCLKRatio +#define EnableYUV GetDispObjectInfo +#define DynamicClockGating EnableDispPowerGating +#define SetupHWAssistedI2CStatus ComputeMemoryClockParam + +#define TMDSAEncoderControl PatchMCSetting +#define LVDSEncoderControl MC_SEQ_Control +#define LCD1OutputControl HW_Misc_Operation + + +typedef struct _ATOM_MASTER_COMMAND_TABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_MASTER_LIST_OF_COMMAND_TABLES ListOfCommandTables; +}ATOM_MASTER_COMMAND_TABLE; + +/****************************************************************************/ +// Structures used in every command table +/****************************************************************************/ +typedef struct _ATOM_TABLE_ATTRIBUTE +{ +#if ATOM_BIG_ENDIAN + USHORT UpdatedByUtility:1; //[15]=Table updated by utility flag + USHORT PS_SizeInBytes:7; //[14:8]=Size of parameter space in Bytes (multiple of a dword), + USHORT WS_SizeInBytes:8; //[7:0]=Size of workspace in Bytes (in multiple of a dword), +#else + USHORT WS_SizeInBytes:8; //[7:0]=Size of workspace in Bytes (in multiple of a dword), + USHORT PS_SizeInBytes:7; //[14:8]=Size of parameter space in Bytes (multiple of a dword), + USHORT UpdatedByUtility:1; //[15]=Table updated by utility flag +#endif +}ATOM_TABLE_ATTRIBUTE; + +typedef union _ATOM_TABLE_ATTRIBUTE_ACCESS +{ + ATOM_TABLE_ATTRIBUTE sbfAccess; + USHORT susAccess; +}ATOM_TABLE_ATTRIBUTE_ACCESS; + +/****************************************************************************/ +// Common header for all command tables. +// Every table pointed by _ATOM_MASTER_COMMAND_TABLE has this common header. +// And the pointer actually points to this header. +/****************************************************************************/ +typedef struct _ATOM_COMMON_ROM_COMMAND_TABLE_HEADER +{ + ATOM_COMMON_TABLE_HEADER CommonHeader; + ATOM_TABLE_ATTRIBUTE TableAttribute; +}ATOM_COMMON_ROM_COMMAND_TABLE_HEADER; + +/****************************************************************************/ +// Structures used by ComputeMemoryEnginePLLTable +/****************************************************************************/ +#define COMPUTE_MEMORY_PLL_PARAM 1 +#define COMPUTE_ENGINE_PLL_PARAM 2 +#define ADJUST_MC_SETTING_PARAM 3 + +/****************************************************************************/ +// Structures used by AdjustMemoryControllerTable +/****************************************************************************/ +typedef struct _ATOM_ADJUST_MEMORY_CLOCK_FREQ +{ +#if ATOM_BIG_ENDIAN + ULONG ulPointerReturnFlag:1; // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block + ULONG ulMemoryModuleNumber:7; // BYTE_3[6:0] + ULONG ulClockFreq:24; +#else + ULONG ulClockFreq:24; + ULONG ulMemoryModuleNumber:7; // BYTE_3[6:0] + ULONG ulPointerReturnFlag:1; // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block +#endif +}ATOM_ADJUST_MEMORY_CLOCK_FREQ; +#define POINTER_RETURN_FLAG 0x80 + +typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS +{ + ULONG ulClock; //When returen, it's the re-calculated clock based on given Fb_div Post_Div and ref_div + UCHAR ucAction; //0:reserved //1:Memory //2:Engine + UCHAR ucReserved; //may expand to return larger Fbdiv later + UCHAR ucFbDiv; //return value + UCHAR ucPostDiv; //return value +}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS; + +typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 +{ + ULONG ulClock; //When return, [23:0] return real clock + UCHAR ucAction; //0:reserved;COMPUTE_MEMORY_PLL_PARAM:Memory;COMPUTE_ENGINE_PLL_PARAM:Engine. it return ref_div to be written to register + USHORT usFbDiv; //return Feedback value to be written to register + UCHAR ucPostDiv; //return post div to be written to register +}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2; +#define COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS + + +#define SET_CLOCK_FREQ_MASK 0x00FFFFFF //Clock change tables only take bit [23:0] as the requested clock value +#define USE_NON_BUS_CLOCK_MASK 0x01000000 //Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) +#define USE_MEMORY_SELF_REFRESH_MASK 0x02000000 //Only applicable to memory clock change, when set, using memory self refresh during clock transition +#define SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE 0x04000000 //Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change +#define FIRST_TIME_CHANGE_CLOCK 0x08000000 //Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup +#define SKIP_SW_PROGRAM_PLL 0x10000000 //Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL +#define USE_SS_ENABLED_PIXEL_CLOCK USE_NON_BUS_CLOCK_MASK + +#define b3USE_NON_BUS_CLOCK_MASK 0x01 //Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) +#define b3USE_MEMORY_SELF_REFRESH 0x02 //Only applicable to memory clock change, when set, using memory self refresh during clock transition +#define b3SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE 0x04 //Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change +#define b3FIRST_TIME_CHANGE_CLOCK 0x08 //Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup +#define b3SKIP_SW_PROGRAM_PLL 0x10 //Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL + +typedef struct _ATOM_COMPUTE_CLOCK_FREQ +{ +#if ATOM_BIG_ENDIAN + ULONG ulComputeClockFlag:8; // =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM + ULONG ulClockFreq:24; // in unit of 10kHz +#else + ULONG ulClockFreq:24; // in unit of 10kHz + ULONG ulComputeClockFlag:8; // =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM +#endif +}ATOM_COMPUTE_CLOCK_FREQ; + +typedef struct _ATOM_S_MPLL_FB_DIVIDER +{ + USHORT usFbDivFrac; + USHORT usFbDiv; +}ATOM_S_MPLL_FB_DIVIDER; + +typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 +{ + union + { + ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter + ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter + }; + UCHAR ucRefDiv; //Output Parameter + UCHAR ucPostDiv; //Output Parameter + UCHAR ucCntlFlag; //Output Parameter + UCHAR ucReserved; +}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3; + +// ucCntlFlag +#define ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN 1 +#define ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE 2 +#define ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE 4 +#define ATOM_PLL_CNTL_FLAG_SPLL_ISPARE_9 8 + + +// V4 are only used for APU which PLL outside GPU +typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 +{ +#if ATOM_BIG_ENDIAN + ULONG ucPostDiv; //return parameter: post divider which is used to program to register directly + ULONG ulClock:24; //Input= target clock, output = actual clock +#else + ULONG ulClock:24; //Input= target clock, output = actual clock + ULONG ucPostDiv; //return parameter: post divider which is used to program to register directly +#endif +}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4; + +typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 +{ + union + { + ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter + ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter + }; + UCHAR ucRefDiv; //Output Parameter + UCHAR ucPostDiv; //Output Parameter + union + { + UCHAR ucCntlFlag; //Output Flags + UCHAR ucInputFlag; //Input Flags. ucInputFlag[0] - Strobe(1)/Performance(0) mode + }; + UCHAR ucReserved; +}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5; + +// ucInputFlag +#define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN 1 // 1-StrobeMode, 0-PerformanceMode + +// use for ComputeMemoryClockParamTable +typedef struct _COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 +{ + union + { + ULONG ulClock; + ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output:UPPER_WORD=FB_DIV_INTEGER, LOWER_WORD=FB_DIV_FRAC shl (16-FB_FRACTION_BITS) + }; + UCHAR ucDllSpeed; //Output + UCHAR ucPostDiv; //Output + union{ + UCHAR ucInputFlag; //Input : ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN: 1-StrobeMode, 0-PerformanceMode + UCHAR ucPllCntlFlag; //Output: + }; + UCHAR ucBWCntl; +}COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1; + +// definition of ucInputFlag +#define MPLL_INPUT_FLAG_STROBE_MODE_EN 0x01 +// definition of ucPllCntlFlag +#define MPLL_CNTL_FLAG_VCO_MODE_MASK 0x03 +#define MPLL_CNTL_FLAG_BYPASS_DQ_PLL 0x04 +#define MPLL_CNTL_FLAG_QDR_ENABLE 0x08 +#define MPLL_CNTL_FLAG_AD_HALF_RATE 0x10 + +//MPLL_CNTL_FLAG_BYPASS_AD_PLL has a wrong name, should be BYPASS_DQ_PLL +#define MPLL_CNTL_FLAG_BYPASS_AD_PLL 0x04 + +typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER +{ + ATOM_COMPUTE_CLOCK_FREQ ulClock; + ULONG ulReserved[2]; +}DYNAMICE_MEMORY_SETTINGS_PARAMETER; + +typedef struct _DYNAMICE_ENGINE_SETTINGS_PARAMETER +{ + ATOM_COMPUTE_CLOCK_FREQ ulClock; + ULONG ulMemoryClock; + ULONG ulReserved; +}DYNAMICE_ENGINE_SETTINGS_PARAMETER; + +/****************************************************************************/ +// Structures used by SetEngineClockTable +/****************************************************************************/ +typedef struct _SET_ENGINE_CLOCK_PARAMETERS +{ + ULONG ulTargetEngineClock; //In 10Khz unit +}SET_ENGINE_CLOCK_PARAMETERS; + +typedef struct _SET_ENGINE_CLOCK_PS_ALLOCATION +{ + ULONG ulTargetEngineClock; //In 10Khz unit + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved; +}SET_ENGINE_CLOCK_PS_ALLOCATION; + +/****************************************************************************/ +// Structures used by SetMemoryClockTable +/****************************************************************************/ +typedef struct _SET_MEMORY_CLOCK_PARAMETERS +{ + ULONG ulTargetMemoryClock; //In 10Khz unit +}SET_MEMORY_CLOCK_PARAMETERS; + +typedef struct _SET_MEMORY_CLOCK_PS_ALLOCATION +{ + ULONG ulTargetMemoryClock; //In 10Khz unit + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved; +}SET_MEMORY_CLOCK_PS_ALLOCATION; + +/****************************************************************************/ +// Structures used by ASIC_Init.ctb +/****************************************************************************/ +typedef struct _ASIC_INIT_PARAMETERS +{ + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit +}ASIC_INIT_PARAMETERS; + +typedef struct _ASIC_INIT_PS_ALLOCATION +{ + ASIC_INIT_PARAMETERS sASICInitClocks; + SET_ENGINE_CLOCK_PS_ALLOCATION sReserved; //Caller doesn't need to init this structure +}ASIC_INIT_PS_ALLOCATION; + +/****************************************************************************/ +// Structure used by DynamicClockGatingTable.ctb +/****************************************************************************/ +typedef struct _DYNAMIC_CLOCK_GATING_PARAMETERS +{ + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucPadding[3]; +}DYNAMIC_CLOCK_GATING_PARAMETERS; +#define DYNAMIC_CLOCK_GATING_PS_ALLOCATION DYNAMIC_CLOCK_GATING_PARAMETERS + +/****************************************************************************/ +// Structure used by EnableDispPowerGatingTable.ctb +/****************************************************************************/ +typedef struct _ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 +{ + UCHAR ucDispPipeId; // ATOM_CRTC1, ATOM_CRTC2, ... + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucPadding[2]; +}ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1; + +/****************************************************************************/ +// Structure used by EnableASIC_StaticPwrMgtTable.ctb +/****************************************************************************/ +typedef struct _ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS +{ + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucPadding[3]; +}ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS; +#define ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS + +/****************************************************************************/ +// Structures used by DAC_LoadDetectionTable.ctb +/****************************************************************************/ +typedef struct _DAC_LOAD_DETECTION_PARAMETERS +{ + USHORT usDeviceID; //{ATOM_DEVICE_CRTx_SUPPORT,ATOM_DEVICE_TVx_SUPPORT,ATOM_DEVICE_CVx_SUPPORT} + UCHAR ucDacType; //{ATOM_DAC_A,ATOM_DAC_B, ATOM_EXT_DAC} + UCHAR ucMisc; //Valid only when table revision =1.3 and above +}DAC_LOAD_DETECTION_PARAMETERS; + +// DAC_LOAD_DETECTION_PARAMETERS.ucMisc +#define DAC_LOAD_MISC_YPrPb 0x01 + +typedef struct _DAC_LOAD_DETECTION_PS_ALLOCATION +{ + DAC_LOAD_DETECTION_PARAMETERS sDacload; + ULONG Reserved[2];// Don't set this one, allocation for EXT DAC +}DAC_LOAD_DETECTION_PS_ALLOCATION; + +/****************************************************************************/ +// Structures used by DAC1EncoderControlTable.ctb and DAC2EncoderControlTable.ctb +/****************************************************************************/ +typedef struct _DAC_ENCODER_CONTROL_PARAMETERS +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + UCHAR ucDacStandard; // See definition of ATOM_DACx_xxx, For DEC3.0, bit 7 used as internal flag to indicate DAC2 (==1) or DAC1 (==0) + UCHAR ucAction; // 0: turn off encoder + // 1: setup and turn on encoder + // 7: ATOM_ENCODER_INIT Initialize DAC +}DAC_ENCODER_CONTROL_PARAMETERS; + +#define DAC_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PARAMETERS + +/****************************************************************************/ +// Structures used by DIG1EncoderControlTable +// DIG2EncoderControlTable +// ExternalEncoderControlTable +/****************************************************************************/ +typedef struct _DIG_ENCODER_CONTROL_PARAMETERS +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + UCHAR ucConfig; + // [2] Link Select: + // =0: PHY linkA if bfLane<3 + // =1: PHY linkB if bfLanes<3 + // =0: PHY linkA+B if bfLanes=3 + // [3] Transmitter Sel + // =0: UNIPHY or PCIEPHY + // =1: LVTMA + UCHAR ucAction; // =0: turn off encoder + // =1: turn on encoder + UCHAR ucEncoderMode; + // =0: DP encoder + // =1: LVDS encoder + // =2: DVI encoder + // =3: HDMI encoder + // =4: SDVO encoder + UCHAR ucLaneNum; // how many lanes to enable + UCHAR ucReserved[2]; +}DIG_ENCODER_CONTROL_PARAMETERS; +#define DIG_ENCODER_CONTROL_PS_ALLOCATION DIG_ENCODER_CONTROL_PARAMETERS +#define EXTERNAL_ENCODER_CONTROL_PARAMETER DIG_ENCODER_CONTROL_PARAMETERS + +//ucConfig +#define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK 0x01 +#define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ 0x00 +#define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ 0x01 +#define ATOM_ENCODER_CONFIG_DPLINKRATE_5_40GHZ 0x02 +#define ATOM_ENCODER_CONFIG_LINK_SEL_MASK 0x04 +#define ATOM_ENCODER_CONFIG_LINKA 0x00 +#define ATOM_ENCODER_CONFIG_LINKB 0x04 +#define ATOM_ENCODER_CONFIG_LINKA_B ATOM_TRANSMITTER_CONFIG_LINKA +#define ATOM_ENCODER_CONFIG_LINKB_A ATOM_ENCODER_CONFIG_LINKB +#define ATOM_ENCODER_CONFIG_TRANSMITTER_SEL_MASK 0x08 +#define ATOM_ENCODER_CONFIG_UNIPHY 0x00 +#define ATOM_ENCODER_CONFIG_LVTMA 0x08 +#define ATOM_ENCODER_CONFIG_TRANSMITTER1 0x00 +#define ATOM_ENCODER_CONFIG_TRANSMITTER2 0x08 +#define ATOM_ENCODER_CONFIG_DIGB 0x80 // VBIOS Internal use, outside SW should set this bit=0 +// ucAction +// ATOM_ENABLE: Enable Encoder +// ATOM_DISABLE: Disable Encoder + +//ucEncoderMode +#define ATOM_ENCODER_MODE_DP 0 +#define ATOM_ENCODER_MODE_LVDS 1 +#define ATOM_ENCODER_MODE_DVI 2 +#define ATOM_ENCODER_MODE_HDMI 3 +#define ATOM_ENCODER_MODE_SDVO 4 +#define ATOM_ENCODER_MODE_DP_AUDIO 5 +#define ATOM_ENCODER_MODE_TV 13 +#define ATOM_ENCODER_MODE_CV 14 +#define ATOM_ENCODER_MODE_CRT 15 +#define ATOM_ENCODER_MODE_DVO 16 +#define ATOM_ENCODER_MODE_DP_SST ATOM_ENCODER_MODE_DP // For DP1.2 +#define ATOM_ENCODER_MODE_DP_MST 5 // For DP1.2 + +typedef struct _ATOM_DIG_ENCODER_CONFIG_V2 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucReserved1:2; + UCHAR ucTransmitterSel:2; // =0: UniphyAB, =1: UniphyCD =2: UniphyEF + UCHAR ucLinkSel:1; // =0: linkA/C/E =1: linkB/D/F + UCHAR ucReserved:1; + UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz +#else + UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz + UCHAR ucReserved:1; + UCHAR ucLinkSel:1; // =0: linkA/C/E =1: linkB/D/F + UCHAR ucTransmitterSel:2; // =0: UniphyAB, =1: UniphyCD =2: UniphyEF + UCHAR ucReserved1:2; +#endif +}ATOM_DIG_ENCODER_CONFIG_V2; + + +typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V2 +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + ATOM_DIG_ENCODER_CONFIG_V2 acConfig; + UCHAR ucAction; + UCHAR ucEncoderMode; + // =0: DP encoder + // =1: LVDS encoder + // =2: DVI encoder + // =3: HDMI encoder + // =4: SDVO encoder + UCHAR ucLaneNum; // how many lanes to enable + UCHAR ucStatus; // = DP_LINK_TRAINING_COMPLETE or DP_LINK_TRAINING_INCOMPLETE, only used by VBIOS with command ATOM_ENCODER_CMD_QUERY_DP_LINK_TRAINING_STATUS + UCHAR ucReserved; +}DIG_ENCODER_CONTROL_PARAMETERS_V2; + +//ucConfig +#define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_MASK 0x01 +#define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_1_62GHZ 0x00 +#define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_2_70GHZ 0x01 +#define ATOM_ENCODER_CONFIG_V2_LINK_SEL_MASK 0x04 +#define ATOM_ENCODER_CONFIG_V2_LINKA 0x00 +#define ATOM_ENCODER_CONFIG_V2_LINKB 0x04 +#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER_SEL_MASK 0x18 +#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER1 0x00 +#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER2 0x08 +#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER3 0x10 + +// ucAction: +// ATOM_DISABLE +// ATOM_ENABLE +#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_START 0x08 +#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1 0x09 +#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2 0x0a +#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3 0x13 +#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE 0x0b +#define ATOM_ENCODER_CMD_DP_VIDEO_OFF 0x0c +#define ATOM_ENCODER_CMD_DP_VIDEO_ON 0x0d +#define ATOM_ENCODER_CMD_QUERY_DP_LINK_TRAINING_STATUS 0x0e +#define ATOM_ENCODER_CMD_SETUP 0x0f +#define ATOM_ENCODER_CMD_SETUP_PANEL_MODE 0x10 + +// ucStatus +#define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE 0x10 +#define ATOM_ENCODER_STATUS_LINK_TRAINING_INCOMPLETE 0x00 + +//ucTableFormatRevision=1 +//ucTableContentRevision=3 +// Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver +typedef struct _ATOM_DIG_ENCODER_CONFIG_V3 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucReserved1:1; + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) + UCHAR ucReserved:3; + UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz +#else + UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz + UCHAR ucReserved:3; + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) + UCHAR ucReserved1:1; +#endif +}ATOM_DIG_ENCODER_CONFIG_V3; + +#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 +#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ 0x00 +#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ 0x01 +#define ATOM_ENCODER_CONFIG_V3_ENCODER_SEL 0x70 +#define ATOM_ENCODER_CONFIG_V3_DIG0_ENCODER 0x00 +#define ATOM_ENCODER_CONFIG_V3_DIG1_ENCODER 0x10 +#define ATOM_ENCODER_CONFIG_V3_DIG2_ENCODER 0x20 +#define ATOM_ENCODER_CONFIG_V3_DIG3_ENCODER 0x30 +#define ATOM_ENCODER_CONFIG_V3_DIG4_ENCODER 0x40 +#define ATOM_ENCODER_CONFIG_V3_DIG5_ENCODER 0x50 + +typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V3 +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + ATOM_DIG_ENCODER_CONFIG_V3 acConfig; + UCHAR ucAction; + union { + UCHAR ucEncoderMode; + // =0: DP encoder + // =1: LVDS encoder + // =2: DVI encoder + // =3: HDMI encoder + // =4: SDVO encoder + // =5: DP audio + UCHAR ucPanelMode; // only valid when ucAction == ATOM_ENCODER_CMD_SETUP_PANEL_MODE + // =0: external DP + // =1: internal DP2 + // =0x11: internal DP1 for NutMeg/Travis DP translator + }; + UCHAR ucLaneNum; // how many lanes to enable + UCHAR ucBitPerColor; // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP + UCHAR ucReserved; +}DIG_ENCODER_CONTROL_PARAMETERS_V3; + +//ucTableFormatRevision=1 +//ucTableContentRevision=4 +// start from NI +// Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver +typedef struct _ATOM_DIG_ENCODER_CONFIG_V4 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucReserved1:1; + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) + UCHAR ucReserved:2; + UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version +#else + UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version + UCHAR ucReserved:2; + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) + UCHAR ucReserved1:1; +#endif +}ATOM_DIG_ENCODER_CONFIG_V4; + +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_MASK 0x03 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ 0x00 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ 0x01 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ 0x02 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ 0x03 +#define ATOM_ENCODER_CONFIG_V4_ENCODER_SEL 0x70 +#define ATOM_ENCODER_CONFIG_V4_DIG0_ENCODER 0x00 +#define ATOM_ENCODER_CONFIG_V4_DIG1_ENCODER 0x10 +#define ATOM_ENCODER_CONFIG_V4_DIG2_ENCODER 0x20 +#define ATOM_ENCODER_CONFIG_V4_DIG3_ENCODER 0x30 +#define ATOM_ENCODER_CONFIG_V4_DIG4_ENCODER 0x40 +#define ATOM_ENCODER_CONFIG_V4_DIG5_ENCODER 0x50 +#define ATOM_ENCODER_CONFIG_V4_DIG6_ENCODER 0x60 + +typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V4 +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + union{ + ATOM_DIG_ENCODER_CONFIG_V4 acConfig; + UCHAR ucConfig; + }; + UCHAR ucAction; + union { + UCHAR ucEncoderMode; + // =0: DP encoder + // =1: LVDS encoder + // =2: DVI encoder + // =3: HDMI encoder + // =4: SDVO encoder + // =5: DP audio + UCHAR ucPanelMode; // only valid when ucAction == ATOM_ENCODER_CMD_SETUP_PANEL_MODE + // =0: external DP + // =1: internal DP2 + // =0x11: internal DP1 for NutMeg/Travis DP translator + }; + UCHAR ucLaneNum; // how many lanes to enable + UCHAR ucBitPerColor; // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP + UCHAR ucHPD_ID; // HPD ID (1-6). =0 means to skip HDP programming. New comparing to previous version +}DIG_ENCODER_CONTROL_PARAMETERS_V4; + +// define ucBitPerColor: +#define PANEL_BPC_UNDEFINE 0x00 +#define PANEL_6BIT_PER_COLOR 0x01 +#define PANEL_8BIT_PER_COLOR 0x02 +#define PANEL_10BIT_PER_COLOR 0x03 +#define PANEL_12BIT_PER_COLOR 0x04 +#define PANEL_16BIT_PER_COLOR 0x05 + +//define ucPanelMode +#define DP_PANEL_MODE_EXTERNAL_DP_MODE 0x00 +#define DP_PANEL_MODE_INTERNAL_DP2_MODE 0x01 +#define DP_PANEL_MODE_INTERNAL_DP1_MODE 0x11 + +/****************************************************************************/ +// Structures used by UNIPHYTransmitterControlTable +// LVTMATransmitterControlTable +// DVOOutputControlTable +/****************************************************************************/ +typedef struct _ATOM_DP_VS_MODE +{ + UCHAR ucLaneSel; + UCHAR ucLaneSet; +}ATOM_DP_VS_MODE; + +typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS +{ + union + { + USHORT usPixelClock; // in 10KHz; for bios convenient + USHORT usInitInfo; // when init uniphy,lower 8bit is used for connector type defined in objectid.h + ATOM_DP_VS_MODE asMode; // DP Voltage swing mode + }; + UCHAR ucConfig; + // [0]=0: 4 lane Link, + // =1: 8 lane Link ( Dual Links TMDS ) + // [1]=0: InCoherent mode + // =1: Coherent Mode + // [2] Link Select: + // =0: PHY linkA if bfLane<3 + // =1: PHY linkB if bfLanes<3 + // =0: PHY linkA+B if bfLanes=3 + // [5:4]PCIE lane Sel + // =0: lane 0~3 or 0~7 + // =1: lane 4~7 + // =2: lane 8~11 or 8~15 + // =3: lane 12~15 + UCHAR ucAction; // =0: turn off encoder + // =1: turn on encoder + UCHAR ucReserved[4]; +}DIG_TRANSMITTER_CONTROL_PARAMETERS; + +#define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION DIG_TRANSMITTER_CONTROL_PARAMETERS + +//ucInitInfo +#define ATOM_TRAMITTER_INITINFO_CONNECTOR_MASK 0x00ff + +//ucConfig +#define ATOM_TRANSMITTER_CONFIG_8LANE_LINK 0x01 +#define ATOM_TRANSMITTER_CONFIG_COHERENT 0x02 +#define ATOM_TRANSMITTER_CONFIG_LINK_SEL_MASK 0x04 +#define ATOM_TRANSMITTER_CONFIG_LINKA 0x00 +#define ATOM_TRANSMITTER_CONFIG_LINKB 0x04 +#define ATOM_TRANSMITTER_CONFIG_LINKA_B 0x00 +#define ATOM_TRANSMITTER_CONFIG_LINKB_A 0x04 + +#define ATOM_TRANSMITTER_CONFIG_ENCODER_SEL_MASK 0x08 // only used when ATOM_TRANSMITTER_ACTION_ENABLE +#define ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER 0x00 // only used when ATOM_TRANSMITTER_ACTION_ENABLE +#define ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER 0x08 // only used when ATOM_TRANSMITTER_ACTION_ENABLE + +#define ATOM_TRANSMITTER_CONFIG_CLKSRC_MASK 0x30 +#define ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL 0x00 +#define ATOM_TRANSMITTER_CONFIG_CLKSRC_PCIE 0x20 +#define ATOM_TRANSMITTER_CONFIG_CLKSRC_XTALIN 0x30 +#define ATOM_TRANSMITTER_CONFIG_LANE_SEL_MASK 0xc0 +#define ATOM_TRANSMITTER_CONFIG_LANE_0_3 0x00 +#define ATOM_TRANSMITTER_CONFIG_LANE_0_7 0x00 +#define ATOM_TRANSMITTER_CONFIG_LANE_4_7 0x40 +#define ATOM_TRANSMITTER_CONFIG_LANE_8_11 0x80 +#define ATOM_TRANSMITTER_CONFIG_LANE_8_15 0x80 +#define ATOM_TRANSMITTER_CONFIG_LANE_12_15 0xc0 + +//ucAction +#define ATOM_TRANSMITTER_ACTION_DISABLE 0 +#define ATOM_TRANSMITTER_ACTION_ENABLE 1 +#define ATOM_TRANSMITTER_ACTION_LCD_BLOFF 2 +#define ATOM_TRANSMITTER_ACTION_LCD_BLON 3 +#define ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL 4 +#define ATOM_TRANSMITTER_ACTION_LCD_SELFTEST_START 5 +#define ATOM_TRANSMITTER_ACTION_LCD_SELFTEST_STOP 6 +#define ATOM_TRANSMITTER_ACTION_INIT 7 +#define ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT 8 +#define ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT 9 +#define ATOM_TRANSMITTER_ACTION_SETUP 10 +#define ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH 11 +#define ATOM_TRANSMITTER_ACTION_POWER_ON 12 +#define ATOM_TRANSMITTER_ACTION_POWER_OFF 13 + +// Following are used for DigTransmitterControlTable ver1.2 +typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V2 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) + UCHAR ucReserved:1; + UCHAR fDPConnector:1; //bit4=0: DP connector =1: None DP connector + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector +#else + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) + UCHAR fDPConnector:1; //bit4=0: DP connector =1: None DP connector + UCHAR ucReserved:1; + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) +#endif +}ATOM_DIG_TRANSMITTER_CONFIG_V2; + +//ucConfig +//Bit0 +#define ATOM_TRANSMITTER_CONFIG_V2_DUAL_LINK_CONNECTOR 0x01 + +//Bit1 +#define ATOM_TRANSMITTER_CONFIG_V2_COHERENT 0x02 + +//Bit2 +#define ATOM_TRANSMITTER_CONFIG_V2_LINK_SEL_MASK 0x04 +#define ATOM_TRANSMITTER_CONFIG_V2_LINKA 0x00 +#define ATOM_TRANSMITTER_CONFIG_V2_LINKB 0x04 + +// Bit3 +#define ATOM_TRANSMITTER_CONFIG_V2_ENCODER_SEL_MASK 0x08 +#define ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER 0x00 // only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP +#define ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER 0x08 // only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP + +// Bit4 +#define ATOM_TRASMITTER_CONFIG_V2_DP_CONNECTOR 0x10 + +// Bit7:6 +#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER_SEL_MASK 0xC0 +#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1 0x00 //AB +#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2 0x40 //CD +#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3 0x80 //EF + +typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 +{ + union + { + USHORT usPixelClock; // in 10KHz; for bios convenient + USHORT usInitInfo; // when init uniphy,lower 8bit is used for connector type defined in objectid.h + ATOM_DP_VS_MODE asMode; // DP Voltage swing mode + }; + ATOM_DIG_TRANSMITTER_CONFIG_V2 acConfig; + UCHAR ucAction; // define as ATOM_TRANSMITER_ACTION_XXX + UCHAR ucReserved[4]; +}DIG_TRANSMITTER_CONTROL_PARAMETERS_V2; + +typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V3 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) + UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, EXT_CLK=2 + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector +#else + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F + UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, EXT_CLK=2 + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) +#endif +}ATOM_DIG_TRANSMITTER_CONFIG_V3; + + +typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 +{ + union + { + USHORT usPixelClock; // in 10KHz; for bios convenient + USHORT usInitInfo; // when init uniphy,lower 8bit is used for connector type defined in objectid.h + ATOM_DP_VS_MODE asMode; // DP Voltage swing mode + }; + ATOM_DIG_TRANSMITTER_CONFIG_V3 acConfig; + UCHAR ucAction; // define as ATOM_TRANSMITER_ACTION_XXX + UCHAR ucLaneNum; + UCHAR ucReserved[3]; +}DIG_TRANSMITTER_CONTROL_PARAMETERS_V3; + +//ucConfig +//Bit0 +#define ATOM_TRANSMITTER_CONFIG_V3_DUAL_LINK_CONNECTOR 0x01 + +//Bit1 +#define ATOM_TRANSMITTER_CONFIG_V3_COHERENT 0x02 + +//Bit2 +#define ATOM_TRANSMITTER_CONFIG_V3_LINK_SEL_MASK 0x04 +#define ATOM_TRANSMITTER_CONFIG_V3_LINKA 0x00 +#define ATOM_TRANSMITTER_CONFIG_V3_LINKB 0x04 + +// Bit3 +#define ATOM_TRANSMITTER_CONFIG_V3_ENCODER_SEL_MASK 0x08 +#define ATOM_TRANSMITTER_CONFIG_V3_DIG1_ENCODER 0x00 +#define ATOM_TRANSMITTER_CONFIG_V3_DIG2_ENCODER 0x08 + +// Bit5:4 +#define ATOM_TRASMITTER_CONFIG_V3_REFCLK_SEL_MASK 0x30 +#define ATOM_TRASMITTER_CONFIG_V3_P1PLL 0x00 +#define ATOM_TRASMITTER_CONFIG_V3_P2PLL 0x10 +#define ATOM_TRASMITTER_CONFIG_V3_REFCLK_SRC_EXT 0x20 + +// Bit7:6 +#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER_SEL_MASK 0xC0 +#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER1 0x00 //AB +#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER2 0x40 //CD +#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER3 0x80 //EF + + +/****************************************************************************/ +// Structures used by UNIPHYTransmitterControlTable V1.4 +// ASIC Families: NI +// ucTableFormatRevision=1 +// ucTableContentRevision=4 +/****************************************************************************/ +typedef struct _ATOM_DP_VS_MODE_V4 +{ + UCHAR ucLaneSel; + union + { + UCHAR ucLaneSet; + struct { +#if ATOM_BIG_ENDIAN + UCHAR ucPOST_CURSOR2:2; //Bit[7:6] Post Cursor2 Level <= New in V4 + UCHAR ucPRE_EMPHASIS:3; //Bit[5:3] Pre-emphasis Level + UCHAR ucVOLTAGE_SWING:3; //Bit[2:0] Voltage Swing Level +#else + UCHAR ucVOLTAGE_SWING:3; //Bit[2:0] Voltage Swing Level + UCHAR ucPRE_EMPHASIS:3; //Bit[5:3] Pre-emphasis Level + UCHAR ucPOST_CURSOR2:2; //Bit[7:6] Post Cursor2 Level <= New in V4 +#endif + }; + }; +}ATOM_DP_VS_MODE_V4; + +typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V4 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) + UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3 <= New + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector +#else + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F + UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3 <= New + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) +#endif +}ATOM_DIG_TRANSMITTER_CONFIG_V4; + +typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 +{ + union + { + USHORT usPixelClock; // in 10KHz; for bios convenient + USHORT usInitInfo; // when init uniphy,lower 8bit is used for connector type defined in objectid.h + ATOM_DP_VS_MODE_V4 asMode; // DP Voltage swing mode Redefined comparing to previous version + }; + union + { + ATOM_DIG_TRANSMITTER_CONFIG_V4 acConfig; + UCHAR ucConfig; + }; + UCHAR ucAction; // define as ATOM_TRANSMITER_ACTION_XXX + UCHAR ucLaneNum; + UCHAR ucReserved[3]; +}DIG_TRANSMITTER_CONTROL_PARAMETERS_V4; + +//ucConfig +//Bit0 +#define ATOM_TRANSMITTER_CONFIG_V4_DUAL_LINK_CONNECTOR 0x01 +//Bit1 +#define ATOM_TRANSMITTER_CONFIG_V4_COHERENT 0x02 +//Bit2 +#define ATOM_TRANSMITTER_CONFIG_V4_LINK_SEL_MASK 0x04 +#define ATOM_TRANSMITTER_CONFIG_V4_LINKA 0x00 +#define ATOM_TRANSMITTER_CONFIG_V4_LINKB 0x04 +// Bit3 +#define ATOM_TRANSMITTER_CONFIG_V4_ENCODER_SEL_MASK 0x08 +#define ATOM_TRANSMITTER_CONFIG_V4_DIG1_ENCODER 0x00 +#define ATOM_TRANSMITTER_CONFIG_V4_DIG2_ENCODER 0x08 +// Bit5:4 +#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SEL_MASK 0x30 +#define ATOM_TRANSMITTER_CONFIG_V4_P1PLL 0x00 +#define ATOM_TRANSMITTER_CONFIG_V4_P2PLL 0x10 +#define ATOM_TRANSMITTER_CONFIG_V4_DCPLL 0x20 // New in _V4 +#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SRC_EXT 0x30 // Changed comparing to V3 +// Bit7:6 +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER_SEL_MASK 0xC0 +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER1 0x00 //AB +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER2 0x40 //CD +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER3 0x80 //EF + + +typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V5 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucReservd1:1; + UCHAR ucHPDSel:3; + UCHAR ucPhyClkSrcId:2; + UCHAR ucCoherentMode:1; + UCHAR ucReserved:1; +#else + UCHAR ucReserved:1; + UCHAR ucCoherentMode:1; + UCHAR ucPhyClkSrcId:2; + UCHAR ucHPDSel:3; + UCHAR ucReservd1:1; +#endif +}ATOM_DIG_TRANSMITTER_CONFIG_V5; + +typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 +{ + USHORT usSymClock; // Encoder Clock in 10kHz,(DP mode)= linkclock/10, (TMDS/LVDS/HDMI)= pixel clock, (HDMI deep color), =pixel clock * deep_color_ratio + UCHAR ucPhyId; // 0=UNIPHYA, 1=UNIPHYB, 2=UNIPHYC, 3=UNIPHYD, 4= UNIPHYE 5=UNIPHYF + UCHAR ucAction; // define as ATOM_TRANSMITER_ACTION_xxx + UCHAR ucLaneNum; // indicate lane number 1-8 + UCHAR ucConnObjId; // Connector Object Id defined in ObjectId.h + UCHAR ucDigMode; // indicate DIG mode + union{ + ATOM_DIG_TRANSMITTER_CONFIG_V5 asConfig; + UCHAR ucConfig; + }; + UCHAR ucDigEncoderSel; // indicate DIG front end encoder + UCHAR ucDPLaneSet; + UCHAR ucReserved; + UCHAR ucReserved1; +}DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5; + +//ucPhyId +#define ATOM_PHY_ID_UNIPHYA 0 +#define ATOM_PHY_ID_UNIPHYB 1 +#define ATOM_PHY_ID_UNIPHYC 2 +#define ATOM_PHY_ID_UNIPHYD 3 +#define ATOM_PHY_ID_UNIPHYE 4 +#define ATOM_PHY_ID_UNIPHYF 5 +#define ATOM_PHY_ID_UNIPHYG 6 + +// ucDigEncoderSel +#define ATOM_TRANMSITTER_V5__DIGA_SEL 0x01 +#define ATOM_TRANMSITTER_V5__DIGB_SEL 0x02 +#define ATOM_TRANMSITTER_V5__DIGC_SEL 0x04 +#define ATOM_TRANMSITTER_V5__DIGD_SEL 0x08 +#define ATOM_TRANMSITTER_V5__DIGE_SEL 0x10 +#define ATOM_TRANMSITTER_V5__DIGF_SEL 0x20 +#define ATOM_TRANMSITTER_V5__DIGG_SEL 0x40 + +// ucDigMode +#define ATOM_TRANSMITTER_DIGMODE_V5_DP 0 +#define ATOM_TRANSMITTER_DIGMODE_V5_LVDS 1 +#define ATOM_TRANSMITTER_DIGMODE_V5_DVI 2 +#define ATOM_TRANSMITTER_DIGMODE_V5_HDMI 3 +#define ATOM_TRANSMITTER_DIGMODE_V5_SDVO 4 +#define ATOM_TRANSMITTER_DIGMODE_V5_DP_MST 5 + +// ucDPLaneSet +#define DP_LANE_SET__0DB_0_4V 0x00 +#define DP_LANE_SET__0DB_0_6V 0x01 +#define DP_LANE_SET__0DB_0_8V 0x02 +#define DP_LANE_SET__0DB_1_2V 0x03 +#define DP_LANE_SET__3_5DB_0_4V 0x08 +#define DP_LANE_SET__3_5DB_0_6V 0x09 +#define DP_LANE_SET__3_5DB_0_8V 0x0a +#define DP_LANE_SET__6DB_0_4V 0x10 +#define DP_LANE_SET__6DB_0_6V 0x11 +#define DP_LANE_SET__9_5DB_0_4V 0x18 + +// ATOM_DIG_TRANSMITTER_CONFIG_V5 asConfig; +// Bit1 +#define ATOM_TRANSMITTER_CONFIG_V5_COHERENT 0x02 + +// Bit3:2 +#define ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SEL_MASK 0x0c +#define ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SEL_SHIFT 0x02 + +#define ATOM_TRANSMITTER_CONFIG_V5_P1PLL 0x00 +#define ATOM_TRANSMITTER_CONFIG_V5_P2PLL 0x04 +#define ATOM_TRANSMITTER_CONFIG_V5_P0PLL 0x08 +#define ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT 0x0c +// Bit6:4 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD_SEL_MASK 0x70 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD_SEL_SHIFT 0x04 + +#define ATOM_TRANSMITTER_CONFIG_V5_NO_HPD_SEL 0x00 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL 0x10 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL 0x20 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL 0x30 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL 0x40 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL 0x50 +#define ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL 0x60 + +#define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION_V1_5 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 + + +/****************************************************************************/ +// Structures used by ExternalEncoderControlTable V1.3 +// ASIC Families: Evergreen, Llano, NI +// ucTableFormatRevision=1 +// ucTableContentRevision=3 +/****************************************************************************/ + +typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 +{ + union{ + USHORT usPixelClock; // pixel clock in 10Khz, valid when ucAction=SETUP/ENABLE_OUTPUT + USHORT usConnectorId; // connector id, valid when ucAction = INIT + }; + UCHAR ucConfig; // indicate which encoder, and DP link rate when ucAction = SETUP/ENABLE_OUTPUT + UCHAR ucAction; // + UCHAR ucEncoderMode; // encoder mode, only used when ucAction = SETUP/ENABLE_OUTPUT + UCHAR ucLaneNum; // lane number, only used when ucAction = SETUP/ENABLE_OUTPUT + UCHAR ucBitPerColor; // output bit per color, only valid when ucAction = SETUP/ENABLE_OUTPUT and ucEncodeMode= DP + UCHAR ucReserved; +}EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3; + +// ucAction +#define EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT 0x00 +#define EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT 0x01 +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT 0x07 +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP 0x0f +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF 0x10 +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11 +#define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12 +#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP 0x14 + +// ucConfig +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ 0x00 +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ 0x01 +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ 0x02 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER_SEL_MASK 0x70 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER1 0x00 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER2 0x10 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER3 0x20 + +typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 +{ + EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 sExtEncoder; + ULONG ulReserved[2]; +}EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3; + + +/****************************************************************************/ +// Structures used by DAC1OuputControlTable +// DAC2OuputControlTable +// LVTMAOutputControlTable (Before DEC30) +// TMDSAOutputControlTable (Before DEC30) +/****************************************************************************/ +typedef struct _DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +{ + UCHAR ucAction; // Possible input:ATOM_ENABLE||ATOMDISABLE + // When the display is LCD, in addition to above: + // ATOM_LCD_BLOFF|| ATOM_LCD_BLON ||ATOM_LCD_BL_BRIGHTNESS_CONTROL||ATOM_LCD_SELFTEST_START|| + // ATOM_LCD_SELFTEST_STOP + + UCHAR aucPadding[3]; // padding to DWORD aligned +}DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS; + +#define DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS + + +#define CRT1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define CRT1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define CRT2_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define CRT2_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define CV1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define CV1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define TV1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define TV1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define DFP1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define DFP1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define DFP2_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define DFP2_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define LCD1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define LCD1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION + +#define DVO_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS +#define DVO_OUTPUT_CONTROL_PS_ALLOCATION DIG_TRANSMITTER_CONTROL_PS_ALLOCATION +#define DVO_OUTPUT_CONTROL_PARAMETERS_V3 DIG_TRANSMITTER_CONTROL_PARAMETERS + +/****************************************************************************/ +// Structures used by BlankCRTCTable +/****************************************************************************/ +typedef struct _BLANK_CRTC_PARAMETERS +{ + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucBlanking; // ATOM_BLANKING or ATOM_BLANKINGOFF + USHORT usBlackColorRCr; + USHORT usBlackColorGY; + USHORT usBlackColorBCb; +}BLANK_CRTC_PARAMETERS; +#define BLANK_CRTC_PS_ALLOCATION BLANK_CRTC_PARAMETERS + +/****************************************************************************/ +// Structures used by EnableCRTCTable +// EnableCRTCMemReqTable +// UpdateCRTC_DoubleBufferRegistersTable +/****************************************************************************/ +typedef struct _ENABLE_CRTC_PARAMETERS +{ + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucPadding[2]; +}ENABLE_CRTC_PARAMETERS; +#define ENABLE_CRTC_PS_ALLOCATION ENABLE_CRTC_PARAMETERS + +/****************************************************************************/ +// Structures used by SetCRTC_OverScanTable +/****************************************************************************/ +typedef struct _SET_CRTC_OVERSCAN_PARAMETERS +{ + USHORT usOverscanRight; // right + USHORT usOverscanLeft; // left + USHORT usOverscanBottom; // bottom + USHORT usOverscanTop; // top + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucPadding[3]; +}SET_CRTC_OVERSCAN_PARAMETERS; +#define SET_CRTC_OVERSCAN_PS_ALLOCATION SET_CRTC_OVERSCAN_PARAMETERS + +/****************************************************************************/ +// Structures used by SetCRTC_ReplicationTable +/****************************************************************************/ +typedef struct _SET_CRTC_REPLICATION_PARAMETERS +{ + UCHAR ucH_Replication; // horizontal replication + UCHAR ucV_Replication; // vertical replication + UCHAR usCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucPadding; +}SET_CRTC_REPLICATION_PARAMETERS; +#define SET_CRTC_REPLICATION_PS_ALLOCATION SET_CRTC_REPLICATION_PARAMETERS + +/****************************************************************************/ +// Structures used by SelectCRTC_SourceTable +/****************************************************************************/ +typedef struct _SELECT_CRTC_SOURCE_PARAMETERS +{ + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucDevice; // ATOM_DEVICE_CRT1|ATOM_DEVICE_CRT2|.... + UCHAR ucPadding[2]; +}SELECT_CRTC_SOURCE_PARAMETERS; +#define SELECT_CRTC_SOURCE_PS_ALLOCATION SELECT_CRTC_SOURCE_PARAMETERS + +typedef struct _SELECT_CRTC_SOURCE_PARAMETERS_V2 +{ + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucEncoderID; // DAC1/DAC2/TVOUT/DIG1/DIG2/DVO + UCHAR ucEncodeMode; // Encoding mode, only valid when using DIG1/DIG2/DVO + UCHAR ucPadding; +}SELECT_CRTC_SOURCE_PARAMETERS_V2; + +//ucEncoderID +//#define ASIC_INT_DAC1_ENCODER_ID 0x00 +//#define ASIC_INT_TV_ENCODER_ID 0x02 +//#define ASIC_INT_DIG1_ENCODER_ID 0x03 +//#define ASIC_INT_DAC2_ENCODER_ID 0x04 +//#define ASIC_EXT_TV_ENCODER_ID 0x06 +//#define ASIC_INT_DVO_ENCODER_ID 0x07 +//#define ASIC_INT_DIG2_ENCODER_ID 0x09 +//#define ASIC_EXT_DIG_ENCODER_ID 0x05 + +//ucEncodeMode +//#define ATOM_ENCODER_MODE_DP 0 +//#define ATOM_ENCODER_MODE_LVDS 1 +//#define ATOM_ENCODER_MODE_DVI 2 +//#define ATOM_ENCODER_MODE_HDMI 3 +//#define ATOM_ENCODER_MODE_SDVO 4 +//#define ATOM_ENCODER_MODE_TV 13 +//#define ATOM_ENCODER_MODE_CV 14 +//#define ATOM_ENCODER_MODE_CRT 15 + +/****************************************************************************/ +// Structures used by SetPixelClockTable +// GetPixelClockTable +/****************************************************************************/ +//Major revision=1., Minor revision=1 +typedef struct _PIXEL_CLOCK_PARAMETERS +{ + USHORT usPixelClock; // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) + // 0 means disable PPLL + USHORT usRefDiv; // Reference divider + USHORT usFbDiv; // feedback divider + UCHAR ucPostDiv; // post divider + UCHAR ucFracFbDiv; // fractional feedback divider + UCHAR ucPpll; // ATOM_PPLL1 or ATOM_PPL2 + UCHAR ucRefDivSrc; // ATOM_PJITTER or ATO_NONPJITTER + UCHAR ucCRTC; // Which CRTC uses this Ppll + UCHAR ucPadding; +}PIXEL_CLOCK_PARAMETERS; + +//Major revision=1., Minor revision=2, add ucMiscIfno +//ucMiscInfo: +#define MISC_FORCE_REPROG_PIXEL_CLOCK 0x1 +#define MISC_DEVICE_INDEX_MASK 0xF0 +#define MISC_DEVICE_INDEX_SHIFT 4 + +typedef struct _PIXEL_CLOCK_PARAMETERS_V2 +{ + USHORT usPixelClock; // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) + // 0 means disable PPLL + USHORT usRefDiv; // Reference divider + USHORT usFbDiv; // feedback divider + UCHAR ucPostDiv; // post divider + UCHAR ucFracFbDiv; // fractional feedback divider + UCHAR ucPpll; // ATOM_PPLL1 or ATOM_PPL2 + UCHAR ucRefDivSrc; // ATOM_PJITTER or ATO_NONPJITTER + UCHAR ucCRTC; // Which CRTC uses this Ppll + UCHAR ucMiscInfo; // Different bits for different purpose, bit [7:4] as device index, bit[0]=Force prog +}PIXEL_CLOCK_PARAMETERS_V2; + +//Major revision=1., Minor revision=3, structure/definition change +//ucEncoderMode: +//ATOM_ENCODER_MODE_DP +//ATOM_ENOCDER_MODE_LVDS +//ATOM_ENOCDER_MODE_DVI +//ATOM_ENOCDER_MODE_HDMI +//ATOM_ENOCDER_MODE_SDVO +//ATOM_ENCODER_MODE_TV 13 +//ATOM_ENCODER_MODE_CV 14 +//ATOM_ENCODER_MODE_CRT 15 + +//ucDVOConfig +//#define DVO_ENCODER_CONFIG_RATE_SEL 0x01 +//#define DVO_ENCODER_CONFIG_DDR_SPEED 0x00 +//#define DVO_ENCODER_CONFIG_SDR_SPEED 0x01 +//#define DVO_ENCODER_CONFIG_OUTPUT_SEL 0x0c +//#define DVO_ENCODER_CONFIG_LOW12BIT 0x00 +//#define DVO_ENCODER_CONFIG_UPPER12BIT 0x04 +//#define DVO_ENCODER_CONFIG_24BIT 0x08 + +//ucMiscInfo: also changed, see below +#define PIXEL_CLOCK_MISC_FORCE_PROG_PPLL 0x01 +#define PIXEL_CLOCK_MISC_VGA_MODE 0x02 +#define PIXEL_CLOCK_MISC_CRTC_SEL_MASK 0x04 +#define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1 0x00 +#define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2 0x04 +#define PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK 0x08 +#define PIXEL_CLOCK_MISC_REF_DIV_SRC 0x10 +// V1.4 for RoadRunner +#define PIXEL_CLOCK_V4_MISC_SS_ENABLE 0x10 +#define PIXEL_CLOCK_V4_MISC_COHERENT_MODE 0x20 + + +typedef struct _PIXEL_CLOCK_PARAMETERS_V3 +{ + USHORT usPixelClock; // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) + // 0 means disable PPLL. For VGA PPLL,make sure this value is not 0. + USHORT usRefDiv; // Reference divider + USHORT usFbDiv; // feedback divider + UCHAR ucPostDiv; // post divider + UCHAR ucFracFbDiv; // fractional feedback divider + UCHAR ucPpll; // ATOM_PPLL1 or ATOM_PPL2 + UCHAR ucTransmitterId; // graphic encoder id defined in objectId.h + union + { + UCHAR ucEncoderMode; // encoder type defined as ATOM_ENCODER_MODE_DP/DVI/HDMI/ + UCHAR ucDVOConfig; // when use DVO, need to know SDR/DDR, 12bit or 24bit + }; + UCHAR ucMiscInfo; // bit[0]=Force program, bit[1]= set pclk for VGA, b[2]= CRTC sel + // bit[3]=0:use PPLL for dispclk source, =1: use engine clock for dispclock source + // bit[4]=0:use XTALIN as the source of reference divider,=1 use the pre-defined clock as the source of reference divider +}PIXEL_CLOCK_PARAMETERS_V3; + +#define PIXEL_CLOCK_PARAMETERS_LAST PIXEL_CLOCK_PARAMETERS_V2 +#define GET_PIXEL_CLOCK_PS_ALLOCATION PIXEL_CLOCK_PARAMETERS_LAST + +typedef struct _PIXEL_CLOCK_PARAMETERS_V5 +{ + UCHAR ucCRTC; // ATOM_CRTC1~6, indicate the CRTC controller to + // drive the pixel clock. not used for DCPLL case. + union{ + UCHAR ucReserved; + UCHAR ucFracFbDiv; // [gphan] temporary to prevent build problem. remove it after driver code is changed. + }; + USHORT usPixelClock; // target the pixel clock to drive the CRTC timing + // 0 means disable PPLL/DCPLL. + USHORT usFbDiv; // feedback divider integer part. + UCHAR ucPostDiv; // post divider. + UCHAR ucRefDiv; // Reference divider + UCHAR ucPpll; // ATOM_PPLL1/ATOM_PPLL2/ATOM_DCPLL + UCHAR ucTransmitterID; // ASIC encoder id defined in objectId.h, + // indicate which graphic encoder will be used. + UCHAR ucEncoderMode; // Encoder mode: + UCHAR ucMiscInfo; // bit[0]= Force program PPLL + // bit[1]= when VGA timing is used. + // bit[3:2]= HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:32bpp + // bit[4]= RefClock source for PPLL. + // =0: XTLAIN( default mode ) + // =1: other external clock source, which is pre-defined + // by VBIOS depend on the feature required. + // bit[7:5]: reserved. + ULONG ulFbDivDecFrac; // 20 bit feedback divider decimal fraction part, range from 1~999999 ( 0.000001 to 0.999999 ) + +}PIXEL_CLOCK_PARAMETERS_V5; + +#define PIXEL_CLOCK_V5_MISC_FORCE_PROG_PPLL 0x01 +#define PIXEL_CLOCK_V5_MISC_VGA_MODE 0x02 +#define PIXEL_CLOCK_V5_MISC_HDMI_BPP_MASK 0x0c +#define PIXEL_CLOCK_V5_MISC_HDMI_24BPP 0x00 +#define PIXEL_CLOCK_V5_MISC_HDMI_30BPP 0x04 +#define PIXEL_CLOCK_V5_MISC_HDMI_32BPP 0x08 +#define PIXEL_CLOCK_V5_MISC_REF_DIV_SRC 0x10 + +typedef struct _CRTC_PIXEL_CLOCK_FREQ +{ +#if ATOM_BIG_ENDIAN + ULONG ucCRTC:8; // ATOM_CRTC1~6, indicate the CRTC controller to + // drive the pixel clock. not used for DCPLL case. + ULONG ulPixelClock:24; // target the pixel clock to drive the CRTC timing. + // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version. +#else + ULONG ulPixelClock:24; // target the pixel clock to drive the CRTC timing. + // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version. + ULONG ucCRTC:8; // ATOM_CRTC1~6, indicate the CRTC controller to + // drive the pixel clock. not used for DCPLL case. +#endif +}CRTC_PIXEL_CLOCK_FREQ; + +typedef struct _PIXEL_CLOCK_PARAMETERS_V6 +{ + union{ + CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; // pixel clock and CRTC id frequency + ULONG ulDispEngClkFreq; // dispclk frequency + }; + USHORT usFbDiv; // feedback divider integer part. + UCHAR ucPostDiv; // post divider. + UCHAR ucRefDiv; // Reference divider + UCHAR ucPpll; // ATOM_PPLL1/ATOM_PPLL2/ATOM_DCPLL + UCHAR ucTransmitterID; // ASIC encoder id defined in objectId.h, + // indicate which graphic encoder will be used. + UCHAR ucEncoderMode; // Encoder mode: + UCHAR ucMiscInfo; // bit[0]= Force program PPLL + // bit[1]= when VGA timing is used. + // bit[3:2]= HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:32bpp + // bit[4]= RefClock source for PPLL. + // =0: XTLAIN( default mode ) + // =1: other external clock source, which is pre-defined + // by VBIOS depend on the feature required. + // bit[7:5]: reserved. + ULONG ulFbDivDecFrac; // 20 bit feedback divider decimal fraction part, range from 1~999999 ( 0.000001 to 0.999999 ) + +}PIXEL_CLOCK_PARAMETERS_V6; + +#define PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL 0x01 +#define PIXEL_CLOCK_V6_MISC_VGA_MODE 0x02 +#define PIXEL_CLOCK_V6_MISC_HDMI_BPP_MASK 0x0c +#define PIXEL_CLOCK_V6_MISC_HDMI_24BPP 0x00 +#define PIXEL_CLOCK_V6_MISC_HDMI_36BPP 0x04 +#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP 0x08 +#define PIXEL_CLOCK_V6_MISC_HDMI_48BPP 0x0c +#define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC 0x10 + +typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2 +{ + PIXEL_CLOCK_PARAMETERS_V3 sDispClkInput; +}GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2; + +typedef struct _GET_DISP_PLL_STATUS_OUTPUT_PARAMETERS_V2 +{ + UCHAR ucStatus; + UCHAR ucRefDivSrc; // =1: reference clock source from XTALIN, =0: source from PCIE ref clock + UCHAR ucReserved[2]; +}GET_DISP_PLL_STATUS_OUTPUT_PARAMETERS_V2; + +typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V3 +{ + PIXEL_CLOCK_PARAMETERS_V5 sDispClkInput; +}GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V3; + +/****************************************************************************/ +// Structures used by AdjustDisplayPllTable +/****************************************************************************/ +typedef struct _ADJUST_DISPLAY_PLL_PARAMETERS +{ + USHORT usPixelClock; + UCHAR ucTransmitterID; + UCHAR ucEncodeMode; + union + { + UCHAR ucDVOConfig; //if DVO, need passing link rate and output 12bitlow or 24bit + UCHAR ucConfig; //if none DVO, not defined yet + }; + UCHAR ucReserved[3]; +}ADJUST_DISPLAY_PLL_PARAMETERS; + +#define ADJUST_DISPLAY_CONFIG_SS_ENABLE 0x10 +#define ADJUST_DISPLAY_PLL_PS_ALLOCATION ADJUST_DISPLAY_PLL_PARAMETERS + +typedef struct _ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3 +{ + USHORT usPixelClock; // target pixel clock + UCHAR ucTransmitterID; // GPU transmitter id defined in objectid.h + UCHAR ucEncodeMode; // encoder mode: CRT, LVDS, DP, TMDS or HDMI + UCHAR ucDispPllConfig; // display pll configure parameter defined as following DISPPLL_CONFIG_XXXX + UCHAR ucExtTransmitterID; // external encoder id. + UCHAR ucReserved[2]; +}ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3; + +// usDispPllConfig v1.2 for RoadRunner +#define DISPPLL_CONFIG_DVO_RATE_SEL 0x0001 // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_DVO_DDR_SPEED 0x0000 // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_DVO_SDR_SPEED 0x0001 // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_DVO_OUTPUT_SEL 0x000c // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_DVO_LOW12BIT 0x0000 // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_DVO_UPPER12BIT 0x0004 // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_DVO_24BIT 0x0008 // need only when ucTransmitterID = DVO +#define DISPPLL_CONFIG_SS_ENABLE 0x0010 // Only used when ucEncoderMode = DP or LVDS +#define DISPPLL_CONFIG_COHERENT_MODE 0x0020 // Only used when ucEncoderMode = TMDS or HDMI +#define DISPPLL_CONFIG_DUAL_LINK 0x0040 // Only used when ucEncoderMode = TMDS or LVDS + + +typedef struct _ADJUST_DISPLAY_PLL_OUTPUT_PARAMETERS_V3 +{ + ULONG ulDispPllFreq; // return display PPLL freq which is used to generate the pixclock, and related idclk, symclk etc + UCHAR ucRefDiv; // if it is none-zero, it is used to be calculated the other ppll parameter fb_divider and post_div ( if it is not given ) + UCHAR ucPostDiv; // if it is none-zero, it is used to be calculated the other ppll parameter fb_divider + UCHAR ucReserved[2]; +}ADJUST_DISPLAY_PLL_OUTPUT_PARAMETERS_V3; + +typedef struct _ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 +{ + union + { + ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3 sInput; + ADJUST_DISPLAY_PLL_OUTPUT_PARAMETERS_V3 sOutput; + }; +} ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3; + +/****************************************************************************/ +// Structures used by EnableYUVTable +/****************************************************************************/ +typedef struct _ENABLE_YUV_PARAMETERS +{ + UCHAR ucEnable; // ATOM_ENABLE:Enable YUV or ATOM_DISABLE:Disable YUV (RGB) + UCHAR ucCRTC; // Which CRTC needs this YUV or RGB format + UCHAR ucPadding[2]; +}ENABLE_YUV_PARAMETERS; +#define ENABLE_YUV_PS_ALLOCATION ENABLE_YUV_PARAMETERS + +/****************************************************************************/ +// Structures used by GetMemoryClockTable +/****************************************************************************/ +typedef struct _GET_MEMORY_CLOCK_PARAMETERS +{ + ULONG ulReturnMemoryClock; // current memory speed in 10KHz unit +} GET_MEMORY_CLOCK_PARAMETERS; +#define GET_MEMORY_CLOCK_PS_ALLOCATION GET_MEMORY_CLOCK_PARAMETERS + +/****************************************************************************/ +// Structures used by GetEngineClockTable +/****************************************************************************/ +typedef struct _GET_ENGINE_CLOCK_PARAMETERS +{ + ULONG ulReturnEngineClock; // current engine speed in 10KHz unit +} GET_ENGINE_CLOCK_PARAMETERS; +#define GET_ENGINE_CLOCK_PS_ALLOCATION GET_ENGINE_CLOCK_PARAMETERS + +/****************************************************************************/ +// Following Structures and constant may be obsolete +/****************************************************************************/ +//Maxium 8 bytes,the data read in will be placed in the parameter space. +//Read operaion successeful when the paramter space is non-zero, otherwise read operation failed +typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS +{ + USHORT usPrescale; //Ratio between Engine clock and I2C clock + USHORT usVRAMAddress; //Address in Frame Buffer where to pace raw EDID + USHORT usStatus; //When use output: lower byte EDID checksum, high byte hardware status + //WHen use input: lower byte as 'byte to read':currently limited to 128byte or 1byte + UCHAR ucSlaveAddr; //Read from which slave + UCHAR ucLineNumber; //Read from which HW assisted line +}READ_EDID_FROM_HW_I2C_DATA_PARAMETERS; +#define READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION READ_EDID_FROM_HW_I2C_DATA_PARAMETERS + + +#define ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSDATABYTE 0 +#define ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSTWODATABYTES 1 +#define ATOM_WRITE_I2C_FORMAT_PSCOUNTER_PSOFFSET_IDDATABLOCK 2 +#define ATOM_WRITE_I2C_FORMAT_PSCOUNTER_IDOFFSET_PLUS_IDDATABLOCK 3 +#define ATOM_WRITE_I2C_FORMAT_IDCOUNTER_IDOFFSET_IDDATABLOCK 4 + +typedef struct _WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS +{ + USHORT usPrescale; //Ratio between Engine clock and I2C clock + USHORT usByteOffset; //Write to which byte + //Upper portion of usByteOffset is Format of data + //1bytePS+offsetPS + //2bytesPS+offsetPS + //blockID+offsetPS + //blockID+offsetID + //blockID+counterID+offsetID + UCHAR ucData; //PS data1 + UCHAR ucStatus; //Status byte 1=success, 2=failure, Also is used as PS data2 + UCHAR ucSlaveAddr; //Write to which slave + UCHAR ucLineNumber; //Write from which HW assisted line +}WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS; + +#define WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS + +typedef struct _SET_UP_HW_I2C_DATA_PARAMETERS +{ + USHORT usPrescale; //Ratio between Engine clock and I2C clock + UCHAR ucSlaveAddr; //Write to which slave + UCHAR ucLineNumber; //Write from which HW assisted line +}SET_UP_HW_I2C_DATA_PARAMETERS; + + +/**************************************************************************/ +#define SPEED_FAN_CONTROL_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS + + +/****************************************************************************/ +// Structures used by PowerConnectorDetectionTable +/****************************************************************************/ +typedef struct _POWER_CONNECTOR_DETECTION_PARAMETERS +{ + UCHAR ucPowerConnectorStatus; //Used for return value 0: detected, 1:not detected + UCHAR ucPwrBehaviorId; + USHORT usPwrBudget; //how much power currently boot to in unit of watt +}POWER_CONNECTOR_DETECTION_PARAMETERS; + +typedef struct POWER_CONNECTOR_DETECTION_PS_ALLOCATION +{ + UCHAR ucPowerConnectorStatus; //Used for return value 0: detected, 1:not detected + UCHAR ucReserved; + USHORT usPwrBudget; //how much power currently boot to in unit of watt + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; +}POWER_CONNECTOR_DETECTION_PS_ALLOCATION; + +/****************************LVDS SS Command Table Definitions**********************/ + +/****************************************************************************/ +// Structures used by EnableSpreadSpectrumOnPPLLTable +/****************************************************************************/ +typedef struct _ENABLE_LVDS_SS_PARAMETERS +{ + USHORT usSpreadSpectrumPercentage; + UCHAR ucSpreadSpectrumType; //Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD + UCHAR ucSpreadSpectrumStepSize_Delay; //bits3:2 SS_STEP_SIZE; bit 6:4 SS_DELAY + UCHAR ucEnable; //ATOM_ENABLE or ATOM_DISABLE + UCHAR ucPadding[3]; +}ENABLE_LVDS_SS_PARAMETERS; + +//ucTableFormatRevision=1,ucTableContentRevision=2 +typedef struct _ENABLE_LVDS_SS_PARAMETERS_V2 +{ + USHORT usSpreadSpectrumPercentage; + UCHAR ucSpreadSpectrumType; //Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD + UCHAR ucSpreadSpectrumStep; // + UCHAR ucEnable; //ATOM_ENABLE or ATOM_DISABLE + UCHAR ucSpreadSpectrumDelay; + UCHAR ucSpreadSpectrumRange; + UCHAR ucPadding; +}ENABLE_LVDS_SS_PARAMETERS_V2; + +//This new structure is based on ENABLE_LVDS_SS_PARAMETERS but expands to SS on PPLL, so other devices can use SS. +typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL +{ + USHORT usSpreadSpectrumPercentage; + UCHAR ucSpreadSpectrumType; // Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD + UCHAR ucSpreadSpectrumStep; // + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucSpreadSpectrumDelay; + UCHAR ucSpreadSpectrumRange; + UCHAR ucPpll; // ATOM_PPLL1/ATOM_PPLL2 +}ENABLE_SPREAD_SPECTRUM_ON_PPLL; + +typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 +{ + USHORT usSpreadSpectrumPercentage; + UCHAR ucSpreadSpectrumType; // Bit[0]: 0-Down Spread,1-Center Spread. + // Bit[1]: 1-Ext. 0-Int. + // Bit[3:2]: =0 P1PLL =1 P2PLL =2 DCPLL + // Bits[7:4] reserved + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + USHORT usSpreadSpectrumAmount; // Includes SS_AMOUNT_FBDIV[7:0] and SS_AMOUNT_NFRAC_SLIP[11:8] + USHORT usSpreadSpectrumStep; // SS_STEP_SIZE_DSFRAC +}ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2; + +#define ATOM_PPLL_SS_TYPE_V2_DOWN_SPREAD 0x00 +#define ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD 0x01 +#define ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD 0x02 +#define ATOM_PPLL_SS_TYPE_V2_PPLL_SEL_MASK 0x0c +#define ATOM_PPLL_SS_TYPE_V2_P1PLL 0x00 +#define ATOM_PPLL_SS_TYPE_V2_P2PLL 0x04 +#define ATOM_PPLL_SS_TYPE_V2_DCPLL 0x08 +#define ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK 0x00FF +#define ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT 0 +#define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK 0x0F00 +#define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT 8 + +// Used by DCE5.0 + typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 +{ + USHORT usSpreadSpectrumAmountFrac; // SS_AMOUNT_DSFRAC New in DCE5.0 + UCHAR ucSpreadSpectrumType; // Bit[0]: 0-Down Spread,1-Center Spread. + // Bit[1]: 1-Ext. 0-Int. + // Bit[3:2]: =0 P1PLL =1 P2PLL =2 DCPLL + // Bits[7:4] reserved + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + USHORT usSpreadSpectrumAmount; // Includes SS_AMOUNT_FBDIV[7:0] and SS_AMOUNT_NFRAC_SLIP[11:8] + USHORT usSpreadSpectrumStep; // SS_STEP_SIZE_DSFRAC +}ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3; + +#define ATOM_PPLL_SS_TYPE_V3_DOWN_SPREAD 0x00 +#define ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD 0x01 +#define ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD 0x02 +#define ATOM_PPLL_SS_TYPE_V3_PPLL_SEL_MASK 0x0c +#define ATOM_PPLL_SS_TYPE_V3_P1PLL 0x00 +#define ATOM_PPLL_SS_TYPE_V3_P2PLL 0x04 +#define ATOM_PPLL_SS_TYPE_V3_DCPLL 0x08 +#define ATOM_PPLL_SS_TYPE_V3_P0PLL ATOM_PPLL_SS_TYPE_V3_DCPLL +#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK 0x00FF +#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT 0 +#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK 0x0F00 +#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT 8 + +#define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION ENABLE_SPREAD_SPECTRUM_ON_PPLL + +/**************************************************************************/ + +typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION +{ + PIXEL_CLOCK_PARAMETERS sPCLKInput; + ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;//Caller doesn't need to init this portion +}SET_PIXEL_CLOCK_PS_ALLOCATION; + +#define ENABLE_VGA_RENDER_PS_ALLOCATION SET_PIXEL_CLOCK_PS_ALLOCATION + +/****************************************************************************/ +// Structures used by ### +/****************************************************************************/ +typedef struct _MEMORY_TRAINING_PARAMETERS +{ + ULONG ulTargetMemoryClock; //In 10Khz unit +}MEMORY_TRAINING_PARAMETERS; +#define MEMORY_TRAINING_PS_ALLOCATION MEMORY_TRAINING_PARAMETERS + + +/****************************LVDS and other encoder command table definitions **********************/ + + +/****************************************************************************/ +// Structures used by LVDSEncoderControlTable (Before DCE30) +// LVTMAEncoderControlTable (Before DCE30) +// TMDSAEncoderControlTable (Before DCE30) +/****************************************************************************/ +typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + UCHAR ucMisc; // bit0=0: Enable single link + // =1: Enable dual link + // Bit1=0: 666RGB + // =1: 888RGB + UCHAR ucAction; // 0: turn off encoder + // 1: setup and turn on encoder +}LVDS_ENCODER_CONTROL_PARAMETERS; + +#define LVDS_ENCODER_CONTROL_PS_ALLOCATION LVDS_ENCODER_CONTROL_PARAMETERS + +#define TMDS1_ENCODER_CONTROL_PARAMETERS LVDS_ENCODER_CONTROL_PARAMETERS +#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION TMDS1_ENCODER_CONTROL_PARAMETERS + +#define TMDS2_ENCODER_CONTROL_PARAMETERS TMDS1_ENCODER_CONTROL_PARAMETERS +#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION TMDS2_ENCODER_CONTROL_PARAMETERS + + +//ucTableFormatRevision=1,ucTableContentRevision=2 +typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS_V2 +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + UCHAR ucMisc; // see PANEL_ENCODER_MISC_xx defintions below + UCHAR ucAction; // 0: turn off encoder + // 1: setup and turn on encoder + UCHAR ucTruncate; // bit0=0: Disable truncate + // =1: Enable truncate + // bit4=0: 666RGB + // =1: 888RGB + UCHAR ucSpatial; // bit0=0: Disable spatial dithering + // =1: Enable spatial dithering + // bit4=0: 666RGB + // =1: 888RGB + UCHAR ucTemporal; // bit0=0: Disable temporal dithering + // =1: Enable temporal dithering + // bit4=0: 666RGB + // =1: 888RGB + // bit5=0: Gray level 2 + // =1: Gray level 4 + UCHAR ucFRC; // bit4=0: 25FRC_SEL pattern E + // =1: 25FRC_SEL pattern F + // bit6:5=0: 50FRC_SEL pattern A + // =1: 50FRC_SEL pattern B + // =2: 50FRC_SEL pattern C + // =3: 50FRC_SEL pattern D + // bit7=0: 75FRC_SEL pattern E + // =1: 75FRC_SEL pattern F +}LVDS_ENCODER_CONTROL_PARAMETERS_V2; + +#define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 LVDS_ENCODER_CONTROL_PARAMETERS_V2 + +#define TMDS1_ENCODER_CONTROL_PARAMETERS_V2 LVDS_ENCODER_CONTROL_PARAMETERS_V2 +#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS1_ENCODER_CONTROL_PARAMETERS_V2 + +#define TMDS2_ENCODER_CONTROL_PARAMETERS_V2 TMDS1_ENCODER_CONTROL_PARAMETERS_V2 +#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS2_ENCODER_CONTROL_PARAMETERS_V2 + +#define LVDS_ENCODER_CONTROL_PARAMETERS_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V2 +#define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V3 + +#define TMDS1_ENCODER_CONTROL_PARAMETERS_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V3 +#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS1_ENCODER_CONTROL_PARAMETERS_V3 + +#define TMDS2_ENCODER_CONTROL_PARAMETERS_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V3 +#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS2_ENCODER_CONTROL_PARAMETERS_V3 + +/****************************************************************************/ +// Structures used by ### +/****************************************************************************/ +typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS +{ + UCHAR ucEnable; // Enable or Disable External TMDS encoder + UCHAR ucMisc; // Bit0=0:Enable Single link;=1:Enable Dual link;Bit1 {=0:666RGB, =1:888RGB} + UCHAR ucPadding[2]; +}ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS; + +typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION +{ + ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS sXTmdsEncoder; + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; //Caller doesn't need to init this portion +}ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION; + +#define ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2 LVDS_ENCODER_CONTROL_PARAMETERS_V2 + +typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2 +{ + ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2 sXTmdsEncoder; + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; //Caller doesn't need to init this portion +}ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2; + +typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION +{ + DIG_ENCODER_CONTROL_PARAMETERS sDigEncoder; + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; +}EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION; + +/****************************************************************************/ +// Structures used by DVOEncoderControlTable +/****************************************************************************/ +//ucTableFormatRevision=1,ucTableContentRevision=3 + +//ucDVOConfig: +#define DVO_ENCODER_CONFIG_RATE_SEL 0x01 +#define DVO_ENCODER_CONFIG_DDR_SPEED 0x00 +#define DVO_ENCODER_CONFIG_SDR_SPEED 0x01 +#define DVO_ENCODER_CONFIG_OUTPUT_SEL 0x0c +#define DVO_ENCODER_CONFIG_LOW12BIT 0x00 +#define DVO_ENCODER_CONFIG_UPPER12BIT 0x04 +#define DVO_ENCODER_CONFIG_24BIT 0x08 + +typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3 +{ + USHORT usPixelClock; + UCHAR ucDVOConfig; + UCHAR ucAction; //ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT + UCHAR ucReseved[4]; +}DVO_ENCODER_CONTROL_PARAMETERS_V3; +#define DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 DVO_ENCODER_CONTROL_PARAMETERS_V3 + +//ucTableFormatRevision=1 +//ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for +// bit1=0: non-coherent mode +// =1: coherent mode + +//========================================================================================== +//Only change is here next time when changing encoder parameter definitions again! +#define LVDS_ENCODER_CONTROL_PARAMETERS_LAST LVDS_ENCODER_CONTROL_PARAMETERS_V3 +#define LVDS_ENCODER_CONTROL_PS_ALLOCATION_LAST LVDS_ENCODER_CONTROL_PARAMETERS_LAST + +#define TMDS1_ENCODER_CONTROL_PARAMETERS_LAST LVDS_ENCODER_CONTROL_PARAMETERS_V3 +#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_LAST TMDS1_ENCODER_CONTROL_PARAMETERS_LAST + +#define TMDS2_ENCODER_CONTROL_PARAMETERS_LAST LVDS_ENCODER_CONTROL_PARAMETERS_V3 +#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_LAST TMDS2_ENCODER_CONTROL_PARAMETERS_LAST + +#define DVO_ENCODER_CONTROL_PARAMETERS_LAST DVO_ENCODER_CONTROL_PARAMETERS +#define DVO_ENCODER_CONTROL_PS_ALLOCATION_LAST DVO_ENCODER_CONTROL_PS_ALLOCATION + +//========================================================================================== +#define PANEL_ENCODER_MISC_DUAL 0x01 +#define PANEL_ENCODER_MISC_COHERENT 0x02 +#define PANEL_ENCODER_MISC_TMDS_LINKB 0x04 +#define PANEL_ENCODER_MISC_HDMI_TYPE 0x08 + +#define PANEL_ENCODER_ACTION_DISABLE ATOM_DISABLE +#define PANEL_ENCODER_ACTION_ENABLE ATOM_ENABLE +#define PANEL_ENCODER_ACTION_COHERENTSEQ (ATOM_ENABLE+1) + +#define PANEL_ENCODER_TRUNCATE_EN 0x01 +#define PANEL_ENCODER_TRUNCATE_DEPTH 0x10 +#define PANEL_ENCODER_SPATIAL_DITHER_EN 0x01 +#define PANEL_ENCODER_SPATIAL_DITHER_DEPTH 0x10 +#define PANEL_ENCODER_TEMPORAL_DITHER_EN 0x01 +#define PANEL_ENCODER_TEMPORAL_DITHER_DEPTH 0x10 +#define PANEL_ENCODER_TEMPORAL_LEVEL_4 0x20 +#define PANEL_ENCODER_25FRC_MASK 0x10 +#define PANEL_ENCODER_25FRC_E 0x00 +#define PANEL_ENCODER_25FRC_F 0x10 +#define PANEL_ENCODER_50FRC_MASK 0x60 +#define PANEL_ENCODER_50FRC_A 0x00 +#define PANEL_ENCODER_50FRC_B 0x20 +#define PANEL_ENCODER_50FRC_C 0x40 +#define PANEL_ENCODER_50FRC_D 0x60 +#define PANEL_ENCODER_75FRC_MASK 0x80 +#define PANEL_ENCODER_75FRC_E 0x00 +#define PANEL_ENCODER_75FRC_F 0x80 + +/****************************************************************************/ +// Structures used by SetVoltageTable +/****************************************************************************/ +#define SET_VOLTAGE_TYPE_ASIC_VDDC 1 +#define SET_VOLTAGE_TYPE_ASIC_MVDDC 2 +#define SET_VOLTAGE_TYPE_ASIC_MVDDQ 3 +#define SET_VOLTAGE_TYPE_ASIC_VDDCI 4 +#define SET_VOLTAGE_INIT_MODE 5 +#define SET_VOLTAGE_GET_MAX_VOLTAGE 6 //Gets the Max. voltage for the soldered Asic + +#define SET_ASIC_VOLTAGE_MODE_ALL_SOURCE 0x1 +#define SET_ASIC_VOLTAGE_MODE_SOURCE_A 0x2 +#define SET_ASIC_VOLTAGE_MODE_SOURCE_B 0x4 + +#define SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE 0x0 +#define SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL 0x1 +#define SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK 0x2 + +typedef struct _SET_VOLTAGE_PARAMETERS +{ + UCHAR ucVoltageType; // To tell which voltage to set up, VDDC/MVDDC/MVDDQ + UCHAR ucVoltageMode; // To set all, to set source A or source B or ... + UCHAR ucVoltageIndex; // An index to tell which voltage level + UCHAR ucReserved; +}SET_VOLTAGE_PARAMETERS; + +typedef struct _SET_VOLTAGE_PARAMETERS_V2 +{ + UCHAR ucVoltageType; // To tell which voltage to set up, VDDC/MVDDC/MVDDQ + UCHAR ucVoltageMode; // Not used, maybe use for state machine for differen power mode + USHORT usVoltageLevel; // real voltage level +}SET_VOLTAGE_PARAMETERS_V2; + + +typedef struct _SET_VOLTAGE_PARAMETERS_V1_3 +{ + UCHAR ucVoltageType; // To tell which voltage to set up, VDDC/MVDDC/MVDDQ/VDDCI + UCHAR ucVoltageMode; // Indicate action: Set voltage level + USHORT usVoltageLevel; // real voltage level in unit of mv or Voltage Phase (0, 1, 2, .. ) +}SET_VOLTAGE_PARAMETERS_V1_3; + +//ucVoltageType +#define VOLTAGE_TYPE_VDDC 1 +#define VOLTAGE_TYPE_MVDDC 2 +#define VOLTAGE_TYPE_MVDDQ 3 +#define VOLTAGE_TYPE_VDDCI 4 + +//SET_VOLTAGE_PARAMETERS_V3.ucVoltageMode +#define ATOM_SET_VOLTAGE 0 //Set voltage Level +#define ATOM_INIT_VOLTAGE_REGULATOR 3 //Init Regulator +#define ATOM_SET_VOLTAGE_PHASE 4 //Set Vregulator Phase +#define ATOM_GET_MAX_VOLTAGE 6 //Get Max Voltage, not used in SetVoltageTable v1.3 +#define ATOM_GET_VOLTAGE_LEVEL 6 //Get Voltage level from vitual voltage ID + +// define vitual voltage id in usVoltageLevel +#define ATOM_VIRTUAL_VOLTAGE_ID0 0xff01 +#define ATOM_VIRTUAL_VOLTAGE_ID1 0xff02 +#define ATOM_VIRTUAL_VOLTAGE_ID2 0xff03 +#define ATOM_VIRTUAL_VOLTAGE_ID3 0xff04 + +typedef struct _SET_VOLTAGE_PS_ALLOCATION +{ + SET_VOLTAGE_PARAMETERS sASICSetVoltage; + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; +}SET_VOLTAGE_PS_ALLOCATION; + +// New Added from SI for GetVoltageInfoTable, input parameter structure +typedef struct _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_1 +{ + UCHAR ucVoltageType; // Input: To tell which voltage to set up, VDDC/MVDDC/MVDDQ/VDDCI + UCHAR ucVoltageMode; // Input: Indicate action: Get voltage info + USHORT usVoltageLevel; // Input: real voltage level in unit of mv or Voltage Phase (0, 1, 2, .. ) or Leakage Id + ULONG ulReserved; +}GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_1; + +// New Added from SI for GetVoltageInfoTable, output parameter structure when ucVotlageMode == ATOM_GET_VOLTAGE_VID +typedef struct _GET_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_1 +{ + ULONG ulVotlageGpioState; + ULONG ulVoltageGPioMask; +}GET_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_1; + +// New Added from SI for GetVoltageInfoTable, output parameter structure when ucVotlageMode == ATOM_GET_VOLTAGE_STATEx_LEAKAGE_VID +typedef struct _GET_LEAKAGE_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_1 +{ + USHORT usVoltageLevel; + USHORT usVoltageId; // Voltage Id programmed in Voltage Regulator + ULONG ulReseved; +}GET_LEAKAGE_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_1; + + +// GetVoltageInfo v1.1 ucVoltageMode +#define ATOM_GET_VOLTAGE_VID 0x00 +#define ATOM_GET_VOTLAGE_INIT_SEQ 0x03 +#define ATOM_GET_VOLTTAGE_PHASE_PHASE_VID 0x04 +// for SI, this state map to 0xff02 voltage state in Power Play table, which is power boost state +#define ATOM_GET_VOLTAGE_STATE0_LEAKAGE_VID 0x10 + +// for SI, this state map to 0xff01 voltage state in Power Play table, which is performance state +#define ATOM_GET_VOLTAGE_STATE1_LEAKAGE_VID 0x11 +// undefined power state +#define ATOM_GET_VOLTAGE_STATE2_LEAKAGE_VID 0x12 +#define ATOM_GET_VOLTAGE_STATE3_LEAKAGE_VID 0x13 + +/****************************************************************************/ +// Structures used by TVEncoderControlTable +/****************************************************************************/ +typedef struct _TV_ENCODER_CONTROL_PARAMETERS +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + UCHAR ucTvStandard; // See definition "ATOM_TV_NTSC ..." + UCHAR ucAction; // 0: turn off encoder + // 1: setup and turn on encoder +}TV_ENCODER_CONTROL_PARAMETERS; + +typedef struct _TV_ENCODER_CONTROL_PS_ALLOCATION +{ + TV_ENCODER_CONTROL_PARAMETERS sTVEncoder; + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; // Don't set this one +}TV_ENCODER_CONTROL_PS_ALLOCATION; + +//==============================Data Table Portion==================================== + +/****************************************************************************/ +// Structure used in Data.mtb +/****************************************************************************/ +typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES +{ + USHORT UtilityPipeLine; // Offest for the utility to get parser info,Don't change this position! + USHORT MultimediaCapabilityInfo; // Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios + USHORT MultimediaConfigInfo; // Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios + USHORT StandardVESA_Timing; // Only used by Bios + USHORT FirmwareInfo; // Shared by various SW components,latest version 1.4 + USHORT PaletteData; // Only used by BIOS + USHORT LCD_Info; // Shared by various SW components,latest version 1.3, was called LVDS_Info + USHORT DIGTransmitterInfo; // Internal used by VBIOS only version 3.1 + USHORT AnalogTV_Info; // Shared by various SW components,latest version 1.1 + USHORT SupportedDevicesInfo; // Will be obsolete from R600 + USHORT GPIO_I2C_Info; // Shared by various SW components,latest version 1.2 will be used from R600 + USHORT VRAM_UsageByFirmware; // Shared by various SW components,latest version 1.3 will be used from R600 + USHORT GPIO_Pin_LUT; // Shared by various SW components,latest version 1.1 + USHORT VESA_ToInternalModeLUT; // Only used by Bios + USHORT ComponentVideoInfo; // Shared by various SW components,latest version 2.1 will be used from R600 + USHORT PowerPlayInfo; // Shared by various SW components,latest version 2.1,new design from R600 + USHORT CompassionateData; // Will be obsolete from R600 + USHORT SaveRestoreInfo; // Only used by Bios + USHORT PPLL_SS_Info; // Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info + USHORT OemInfo; // Defined and used by external SW, should be obsolete soon + USHORT XTMDS_Info; // Will be obsolete from R600 + USHORT MclkSS_Info; // Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used + USHORT Object_Header; // Shared by various SW components,latest version 1.1 + USHORT IndirectIOAccess; // Only used by Bios,this table position can't change at all!! + USHORT MC_InitParameter; // Only used by command table + USHORT ASIC_VDDC_Info; // Will be obsolete from R600 + USHORT ASIC_InternalSS_Info; // New tabel name from R600, used to be called "ASIC_MVDDC_Info" + USHORT TV_VideoMode; // Only used by command table + USHORT VRAM_Info; // Only used by command table, latest version 1.3 + USHORT MemoryTrainingInfo; // Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 + USHORT IntegratedSystemInfo; // Shared by various SW components + USHORT ASIC_ProfilingInfo; // New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 + USHORT VoltageObjectInfo; // Shared by various SW components, latest version 1.1 + USHORT PowerSourceInfo; // Shared by various SW components, latest versoin 1.1 +}ATOM_MASTER_LIST_OF_DATA_TABLES; + +typedef struct _ATOM_MASTER_DATA_TABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables; +}ATOM_MASTER_DATA_TABLE; + +// For backward compatible +#define LVDS_Info LCD_Info +#define DAC_Info PaletteData +#define TMDS_Info DIGTransmitterInfo + +/****************************************************************************/ +// Structure used in MultimediaCapabilityInfoTable +/****************************************************************************/ +typedef struct _ATOM_MULTIMEDIA_CAPABILITY_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulSignature; // HW info table signature string "$ATI" + UCHAR ucI2C_Type; // I2C type (normal GP_IO, ImpactTV GP_IO, Dedicated I2C pin, etc) + UCHAR ucTV_OutInfo; // Type of TV out supported (3:0) and video out crystal frequency (6:4) and TV data port (7) + UCHAR ucVideoPortInfo; // Provides the video port capabilities + UCHAR ucHostPortInfo; // Provides host port configuration information +}ATOM_MULTIMEDIA_CAPABILITY_INFO; + +/****************************************************************************/ +// Structure used in MultimediaConfigInfoTable +/****************************************************************************/ +typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulSignature; // MM info table signature sting "$MMT" + UCHAR ucTunerInfo; // Type of tuner installed on the adapter (4:0) and video input for tuner (7:5) + UCHAR ucAudioChipInfo; // List the audio chip type (3:0) product type (4) and OEM revision (7:5) + UCHAR ucProductID; // Defines as OEM ID or ATI board ID dependent on product type setting + UCHAR ucMiscInfo1; // Tuner voltage (1:0) HW teletext support (3:2) FM audio decoder (5:4) reserved (6) audio scrambling (7) + UCHAR ucMiscInfo2; // I2S input config (0) I2S output config (1) I2S Audio Chip (4:2) SPDIF Output Config (5) reserved (7:6) + UCHAR ucMiscInfo3; // Video Decoder Type (3:0) Video In Standard/Crystal (7:4) + UCHAR ucMiscInfo4; // Video Decoder Host Config (2:0) reserved (7:3) + UCHAR ucVideoInput0Info;// Video Input 0 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) + UCHAR ucVideoInput1Info;// Video Input 1 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) + UCHAR ucVideoInput2Info;// Video Input 2 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) + UCHAR ucVideoInput3Info;// Video Input 3 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) + UCHAR ucVideoInput4Info;// Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) +}ATOM_MULTIMEDIA_CONFIG_INFO; + + +/****************************************************************************/ +// Structures used in FirmwareInfoTable +/****************************************************************************/ + +// usBIOSCapability Definition: +// Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; +// Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; +// Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; +// Others: Reserved +#define ATOM_BIOS_INFO_ATOM_FIRMWARE_POSTED 0x0001 +#define ATOM_BIOS_INFO_DUAL_CRTC_SUPPORT 0x0002 +#define ATOM_BIOS_INFO_EXTENDED_DESKTOP_SUPPORT 0x0004 +#define ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT 0x0008 // (valid from v1.1 ~v1.4):=1: memclk SS enable, =0 memclk SS disable. +#define ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT 0x0010 // (valid from v1.1 ~v1.4):=1: engclk SS enable, =0 engclk SS disable. +#define ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU 0x0020 +#define ATOM_BIOS_INFO_WMI_SUPPORT 0x0040 +#define ATOM_BIOS_INFO_PPMODE_ASSIGNGED_BY_SYSTEM 0x0080 +#define ATOM_BIOS_INFO_HYPERMEMORY_SUPPORT 0x0100 +#define ATOM_BIOS_INFO_HYPERMEMORY_SIZE_MASK 0x1E00 +#define ATOM_BIOS_INFO_VPOST_WITHOUT_FIRST_MODE_SET 0x2000 +#define ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE 0x4000 +#define ATOM_BIOS_INFO_MEMORY_CLOCK_EXT_SS_SUPPORT 0x0008 // (valid from v2.1 ): =1: memclk ss enable with external ss chip +#define ATOM_BIOS_INFO_ENGINE_CLOCK_EXT_SS_SUPPORT 0x0010 // (valid from v2.1 ): =1: engclk ss enable with external ss chip + +#ifndef _H2INC + +//Please don't add or expand this bitfield structure below, this one will retire soon.! +typedef struct _ATOM_FIRMWARE_CAPABILITY +{ +#if ATOM_BIG_ENDIAN + USHORT Reserved:1; + USHORT SCL2Redefined:1; + USHORT PostWithoutModeSet:1; + USHORT HyperMemory_Size:4; + USHORT HyperMemory_Support:1; + USHORT PPMode_Assigned:1; + USHORT WMI_SUPPORT:1; + USHORT GPUControlsBL:1; + USHORT EngineClockSS_Support:1; + USHORT MemoryClockSS_Support:1; + USHORT ExtendedDesktopSupport:1; + USHORT DualCRTC_Support:1; + USHORT FirmwarePosted:1; +#else + USHORT FirmwarePosted:1; + USHORT DualCRTC_Support:1; + USHORT ExtendedDesktopSupport:1; + USHORT MemoryClockSS_Support:1; + USHORT EngineClockSS_Support:1; + USHORT GPUControlsBL:1; + USHORT WMI_SUPPORT:1; + USHORT PPMode_Assigned:1; + USHORT HyperMemory_Support:1; + USHORT HyperMemory_Size:4; + USHORT PostWithoutModeSet:1; + USHORT SCL2Redefined:1; + USHORT Reserved:1; +#endif +}ATOM_FIRMWARE_CAPABILITY; + +typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS +{ + ATOM_FIRMWARE_CAPABILITY sbfAccess; + USHORT susAccess; +}ATOM_FIRMWARE_CAPABILITY_ACCESS; + +#else + +typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS +{ + USHORT susAccess; +}ATOM_FIRMWARE_CAPABILITY_ACCESS; + +#endif + +typedef struct _ATOM_FIRMWARE_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulDriverTargetEngineClock; //In 10Khz unit + ULONG ulDriverTargetMemoryClock; //In 10Khz unit + ULONG ulMaxEngineClockPLL_Output; //In 10Khz unit + ULONG ulMaxMemoryClockPLL_Output; //In 10Khz unit + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulASICMaxEngineClock; //In 10Khz unit + ULONG ulASICMaxMemoryClock; //In 10Khz unit + UCHAR ucASICMaxTemperature; + UCHAR ucPadding[3]; //Don't use them + ULONG aulReservedForBIOS[3]; //Don't use them + USHORT usMinEngineClockPLL_Input; //In 10Khz unit + USHORT usMaxEngineClockPLL_Input; //In 10Khz unit + USHORT usMinEngineClockPLL_Output; //In 10Khz unit + USHORT usMinMemoryClockPLL_Input; //In 10Khz unit + USHORT usMaxMemoryClockPLL_Input; //In 10Khz unit + USHORT usMinMemoryClockPLL_Output; //In 10Khz unit + USHORT usMaxPixelClock; //In 10Khz unit, Max. Pclk + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usMinPixelClockPLL_Output; //In 10Khz unit, the definitions above can't change!!! + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usReferenceClock; //In 10Khz unit + USHORT usPM_RTS_Location; //RTS PM4 starting location in ROM in 1Kb unit + UCHAR ucPM_RTS_StreamSize; //RTS PM4 packets in Kb unit + UCHAR ucDesign_ID; //Indicate what is the board design + UCHAR ucMemoryModule_ID; //Indicate what is the board design +}ATOM_FIRMWARE_INFO; + +typedef struct _ATOM_FIRMWARE_INFO_V1_2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulDriverTargetEngineClock; //In 10Khz unit + ULONG ulDriverTargetMemoryClock; //In 10Khz unit + ULONG ulMaxEngineClockPLL_Output; //In 10Khz unit + ULONG ulMaxMemoryClockPLL_Output; //In 10Khz unit + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulASICMaxEngineClock; //In 10Khz unit + ULONG ulASICMaxMemoryClock; //In 10Khz unit + UCHAR ucASICMaxTemperature; + UCHAR ucMinAllowedBL_Level; + UCHAR ucPadding[2]; //Don't use them + ULONG aulReservedForBIOS[2]; //Don't use them + ULONG ulMinPixelClockPLL_Output; //In 10Khz unit + USHORT usMinEngineClockPLL_Input; //In 10Khz unit + USHORT usMaxEngineClockPLL_Input; //In 10Khz unit + USHORT usMinEngineClockPLL_Output; //In 10Khz unit + USHORT usMinMemoryClockPLL_Input; //In 10Khz unit + USHORT usMaxMemoryClockPLL_Input; //In 10Khz unit + USHORT usMinMemoryClockPLL_Output; //In 10Khz unit + USHORT usMaxPixelClock; //In 10Khz unit, Max. Pclk + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usMinPixelClockPLL_Output; //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usReferenceClock; //In 10Khz unit + USHORT usPM_RTS_Location; //RTS PM4 starting location in ROM in 1Kb unit + UCHAR ucPM_RTS_StreamSize; //RTS PM4 packets in Kb unit + UCHAR ucDesign_ID; //Indicate what is the board design + UCHAR ucMemoryModule_ID; //Indicate what is the board design +}ATOM_FIRMWARE_INFO_V1_2; + +typedef struct _ATOM_FIRMWARE_INFO_V1_3 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulDriverTargetEngineClock; //In 10Khz unit + ULONG ulDriverTargetMemoryClock; //In 10Khz unit + ULONG ulMaxEngineClockPLL_Output; //In 10Khz unit + ULONG ulMaxMemoryClockPLL_Output; //In 10Khz unit + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulASICMaxEngineClock; //In 10Khz unit + ULONG ulASICMaxMemoryClock; //In 10Khz unit + UCHAR ucASICMaxTemperature; + UCHAR ucMinAllowedBL_Level; + UCHAR ucPadding[2]; //Don't use them + ULONG aulReservedForBIOS; //Don't use them + ULONG ul3DAccelerationEngineClock;//In 10Khz unit + ULONG ulMinPixelClockPLL_Output; //In 10Khz unit + USHORT usMinEngineClockPLL_Input; //In 10Khz unit + USHORT usMaxEngineClockPLL_Input; //In 10Khz unit + USHORT usMinEngineClockPLL_Output; //In 10Khz unit + USHORT usMinMemoryClockPLL_Input; //In 10Khz unit + USHORT usMaxMemoryClockPLL_Input; //In 10Khz unit + USHORT usMinMemoryClockPLL_Output; //In 10Khz unit + USHORT usMaxPixelClock; //In 10Khz unit, Max. Pclk + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usMinPixelClockPLL_Output; //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usReferenceClock; //In 10Khz unit + USHORT usPM_RTS_Location; //RTS PM4 starting location in ROM in 1Kb unit + UCHAR ucPM_RTS_StreamSize; //RTS PM4 packets in Kb unit + UCHAR ucDesign_ID; //Indicate what is the board design + UCHAR ucMemoryModule_ID; //Indicate what is the board design +}ATOM_FIRMWARE_INFO_V1_3; + +typedef struct _ATOM_FIRMWARE_INFO_V1_4 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulDriverTargetEngineClock; //In 10Khz unit + ULONG ulDriverTargetMemoryClock; //In 10Khz unit + ULONG ulMaxEngineClockPLL_Output; //In 10Khz unit + ULONG ulMaxMemoryClockPLL_Output; //In 10Khz unit + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulASICMaxEngineClock; //In 10Khz unit + ULONG ulASICMaxMemoryClock; //In 10Khz unit + UCHAR ucASICMaxTemperature; + UCHAR ucMinAllowedBL_Level; + USHORT usBootUpVDDCVoltage; //In MV unit + USHORT usLcdMinPixelClockPLL_Output; // In MHz unit + USHORT usLcdMaxPixelClockPLL_Output; // In MHz unit + ULONG ul3DAccelerationEngineClock;//In 10Khz unit + ULONG ulMinPixelClockPLL_Output; //In 10Khz unit + USHORT usMinEngineClockPLL_Input; //In 10Khz unit + USHORT usMaxEngineClockPLL_Input; //In 10Khz unit + USHORT usMinEngineClockPLL_Output; //In 10Khz unit + USHORT usMinMemoryClockPLL_Input; //In 10Khz unit + USHORT usMaxMemoryClockPLL_Input; //In 10Khz unit + USHORT usMinMemoryClockPLL_Output; //In 10Khz unit + USHORT usMaxPixelClock; //In 10Khz unit, Max. Pclk + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usMinPixelClockPLL_Output; //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usReferenceClock; //In 10Khz unit + USHORT usPM_RTS_Location; //RTS PM4 starting location in ROM in 1Kb unit + UCHAR ucPM_RTS_StreamSize; //RTS PM4 packets in Kb unit + UCHAR ucDesign_ID; //Indicate what is the board design + UCHAR ucMemoryModule_ID; //Indicate what is the board design +}ATOM_FIRMWARE_INFO_V1_4; + +//the structure below to be used from Cypress +typedef struct _ATOM_FIRMWARE_INFO_V2_1 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulReserved1; + ULONG ulReserved2; + ULONG ulMaxEngineClockPLL_Output; //In 10Khz unit + ULONG ulMaxMemoryClockPLL_Output; //In 10Khz unit + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulBinaryAlteredInfo; //Was ulASICMaxEngineClock + ULONG ulDefaultDispEngineClkFreq; //In 10Khz unit + UCHAR ucReserved1; //Was ucASICMaxTemperature; + UCHAR ucMinAllowedBL_Level; + USHORT usBootUpVDDCVoltage; //In MV unit + USHORT usLcdMinPixelClockPLL_Output; // In MHz unit + USHORT usLcdMaxPixelClockPLL_Output; // In MHz unit + ULONG ulReserved4; //Was ulAsicMaximumVoltage + ULONG ulMinPixelClockPLL_Output; //In 10Khz unit + USHORT usMinEngineClockPLL_Input; //In 10Khz unit + USHORT usMaxEngineClockPLL_Input; //In 10Khz unit + USHORT usMinEngineClockPLL_Output; //In 10Khz unit + USHORT usMinMemoryClockPLL_Input; //In 10Khz unit + USHORT usMaxMemoryClockPLL_Input; //In 10Khz unit + USHORT usMinMemoryClockPLL_Output; //In 10Khz unit + USHORT usMaxPixelClock; //In 10Khz unit, Max. Pclk + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usMinPixelClockPLL_Output; //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usCoreReferenceClock; //In 10Khz unit + USHORT usMemoryReferenceClock; //In 10Khz unit + USHORT usUniphyDPModeExtClkFreq; //In 10Khz unit, if it is 0, In DP Mode Uniphy Input clock from internal PPLL, otherwise Input clock from external Spread clock + UCHAR ucMemoryModule_ID; //Indicate what is the board design + UCHAR ucReserved4[3]; +}ATOM_FIRMWARE_INFO_V2_1; + +//the structure below to be used from NI +//ucTableFormatRevision=2 +//ucTableContentRevision=2 +typedef struct _ATOM_FIRMWARE_INFO_V2_2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulReserved[2]; + ULONG ulReserved1; //Was ulMaxEngineClockPLL_Output; //In 10Khz unit* + ULONG ulReserved2; //Was ulMaxMemoryClockPLL_Output; //In 10Khz unit* + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulBinaryAlteredInfo; //Was ulASICMaxEngineClock ? + ULONG ulDefaultDispEngineClkFreq; //In 10Khz unit. This is the frequency before DCDTO, corresponding to usBootUpVDDCVoltage. + UCHAR ucReserved3; //Was ucASICMaxTemperature; + UCHAR ucMinAllowedBL_Level; + USHORT usBootUpVDDCVoltage; //In MV unit + USHORT usLcdMinPixelClockPLL_Output; // In MHz unit + USHORT usLcdMaxPixelClockPLL_Output; // In MHz unit + ULONG ulReserved4; //Was ulAsicMaximumVoltage + ULONG ulMinPixelClockPLL_Output; //In 10Khz unit + UCHAR ucRemoteDisplayConfig; + UCHAR ucReserved5[3]; //Was usMinEngineClockPLL_Input and usMaxEngineClockPLL_Input + ULONG ulReserved6; //Was usMinEngineClockPLL_Output and usMinMemoryClockPLL_Input + ULONG ulReserved7; //Was usMaxMemoryClockPLL_Input and usMinMemoryClockPLL_Output + USHORT usReserved11; //Was usMaxPixelClock; //In 10Khz unit, Max. Pclk used only for DAC + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usBootUpVDDCIVoltage; //In unit of mv; Was usMinPixelClockPLL_Output; + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usCoreReferenceClock; //In 10Khz unit + USHORT usMemoryReferenceClock; //In 10Khz unit + USHORT usUniphyDPModeExtClkFreq; //In 10Khz unit, if it is 0, In DP Mode Uniphy Input clock from internal PPLL, otherwise Input clock from external Spread clock + UCHAR ucMemoryModule_ID; //Indicate what is the board design + UCHAR ucReserved9[3]; + USHORT usBootUpMVDDCVoltage; //In unit of mv; Was usMinPixelClockPLL_Output; + USHORT usReserved12; + ULONG ulReserved10[3]; // New added comparing to previous version +}ATOM_FIRMWARE_INFO_V2_2; + +#define ATOM_FIRMWARE_INFO_LAST ATOM_FIRMWARE_INFO_V2_2 + + +// definition of ucRemoteDisplayConfig +#define REMOTE_DISPLAY_DISABLE 0x00 +#define REMOTE_DISPLAY_ENABLE 0x01 + +/****************************************************************************/ +// Structures used in IntegratedSystemInfoTable +/****************************************************************************/ +#define IGP_CAP_FLAG_DYNAMIC_CLOCK_EN 0x2 +#define IGP_CAP_FLAG_AC_CARD 0x4 +#define IGP_CAP_FLAG_SDVO_CARD 0x8 +#define IGP_CAP_FLAG_POSTDIV_BY_2_MODE 0x10 + +typedef struct _ATOM_INTEGRATED_SYSTEM_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulBootUpEngineClock; //in 10kHz unit + ULONG ulBootUpMemoryClock; //in 10kHz unit + ULONG ulMaxSystemMemoryClock; //in 10kHz unit + ULONG ulMinSystemMemoryClock; //in 10kHz unit + UCHAR ucNumberOfCyclesInPeriodHi; + UCHAR ucLCDTimingSel; //=0:not valid.!=0 sel this timing descriptor from LCD EDID. + USHORT usReserved1; + USHORT usInterNBVoltageLow; //An intermidiate PMW value to set the voltage + USHORT usInterNBVoltageHigh; //Another intermidiate PMW value to set the voltage + ULONG ulReserved[2]; + + USHORT usFSBClock; //In MHz unit + USHORT usCapabilityFlag; //Bit0=1 indicates the fake HDMI support,Bit1=0/1 for Dynamic clocking dis/enable + //Bit[3:2]== 0:No PCIE card, 1:AC card, 2:SDVO card + //Bit[4]==1: P/2 mode, ==0: P/1 mode + USHORT usPCIENBCfgReg7; //bit[7:0]=MUX_Sel, bit[9:8]=MUX_SEL_LEVEL2, bit[10]=Lane_Reversal + USHORT usK8MemoryClock; //in MHz unit + USHORT usK8SyncStartDelay; //in 0.01 us unit + USHORT usK8DataReturnTime; //in 0.01 us unit + UCHAR ucMaxNBVoltage; + UCHAR ucMinNBVoltage; + UCHAR ucMemoryType; //[7:4]=1:DDR1;=2:DDR2;=3:DDR3.[3:0] is reserved + UCHAR ucNumberOfCyclesInPeriod; //CG.FVTHROT_PWM_CTRL_REG0.NumberOfCyclesInPeriod + UCHAR ucStartingPWM_HighTime; //CG.FVTHROT_PWM_CTRL_REG0.StartingPWM_HighTime + UCHAR ucHTLinkWidth; //16 bit vs. 8 bit + UCHAR ucMaxNBVoltageHigh; + UCHAR ucMinNBVoltageHigh; +}ATOM_INTEGRATED_SYSTEM_INFO; + +/* Explanation on entries in ATOM_INTEGRATED_SYSTEM_INFO +ulBootUpMemoryClock: For Intel IGP,it's the UMA system memory clock + For AMD IGP,it's 0 if no SidePort memory installed or it's the boot-up SidePort memory clock +ulMaxSystemMemoryClock: For Intel IGP,it's the Max freq from memory SPD if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0 + For AMD IGP,for now this can be 0 +ulMinSystemMemoryClock: For Intel IGP,it's 133MHz if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0 + For AMD IGP,for now this can be 0 + +usFSBClock: For Intel IGP,it's FSB Freq + For AMD IGP,it's HT Link Speed + +usK8MemoryClock: For AMD IGP only. For RevF CPU, set it to 200 +usK8SyncStartDelay: For AMD IGP only. Memory access latency in K8, required for watermark calculation +usK8DataReturnTime: For AMD IGP only. Memory access latency in K8, required for watermark calculation + +VC:Voltage Control +ucMaxNBVoltage: Voltage regulator dependent PWM value. Low 8 bits of the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all. +ucMinNBVoltage: Voltage regulator dependent PWM value. Low 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all. + +ucNumberOfCyclesInPeriod: Indicate how many cycles when PWM duty is 100%. low 8 bits of the value. +ucNumberOfCyclesInPeriodHi: Indicate how many cycles when PWM duty is 100%. high 8 bits of the value.If the PWM has an inverter,set bit [7]==1,otherwise set it 0 + +ucMaxNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all. +ucMinNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all. + + +usInterNBVoltageLow: Voltage regulator dependent PWM value. The value makes the the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all. +usInterNBVoltageHigh: Voltage regulator dependent PWM value. The value makes the the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all. +*/ + + +/* +The following IGP table is introduced from RS780, which is supposed to be put by SBIOS in FB before IGP VBIOS starts VPOST; +Then VBIOS will copy the whole structure to its image so all GPU SW components can access this data structure to get whatever they need. +The enough reservation should allow us to never change table revisions. Whenever needed, a GPU SW component can use reserved portion for new data entries. + +SW components can access the IGP system infor structure in the same way as before +*/ + + +typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulBootUpEngineClock; //in 10kHz unit + ULONG ulReserved1[2]; //must be 0x0 for the reserved + ULONG ulBootUpUMAClock; //in 10kHz unit + ULONG ulBootUpSidePortClock; //in 10kHz unit + ULONG ulMinSidePortClock; //in 10kHz unit + ULONG ulReserved2[6]; //must be 0x0 for the reserved + ULONG ulSystemConfig; //see explanation below + ULONG ulBootUpReqDisplayVector; + ULONG ulOtherDisplayMisc; + ULONG ulDDISlot1Config; + ULONG ulDDISlot2Config; + UCHAR ucMemoryType; //[3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved + UCHAR ucUMAChannelNumber; + UCHAR ucDockingPinBit; + UCHAR ucDockingPinPolarity; + ULONG ulDockingPinCFGInfo; + ULONG ulCPUCapInfo; + USHORT usNumberOfCyclesInPeriod; + USHORT usMaxNBVoltage; + USHORT usMinNBVoltage; + USHORT usBootUpNBVoltage; + ULONG ulHTLinkFreq; //in 10Khz + USHORT usMinHTLinkWidth; + USHORT usMaxHTLinkWidth; + USHORT usUMASyncStartDelay; + USHORT usUMADataReturnTime; + USHORT usLinkStatusZeroTime; + USHORT usDACEfuse; //for storing badgap value (for RS880 only) + ULONG ulHighVoltageHTLinkFreq; // in 10Khz + ULONG ulLowVoltageHTLinkFreq; // in 10Khz + USHORT usMaxUpStreamHTLinkWidth; + USHORT usMaxDownStreamHTLinkWidth; + USHORT usMinUpStreamHTLinkWidth; + USHORT usMinDownStreamHTLinkWidth; + USHORT usFirmwareVersion; //0 means FW is not supported. Otherwise it's the FW version loaded by SBIOS and driver should enable FW. + USHORT usFullT0Time; // Input to calculate minimum HT link change time required by NB P-State. Unit is 0.01us. + ULONG ulReserved3[96]; //must be 0x0 +}ATOM_INTEGRATED_SYSTEM_INFO_V2; + +/* +ulBootUpEngineClock: Boot-up Engine Clock in 10Khz; +ulBootUpUMAClock: Boot-up UMA Clock in 10Khz; it must be 0x0 when UMA is not present +ulBootUpSidePortClock: Boot-up SidePort Clock in 10Khz; it must be 0x0 when SidePort Memory is not present,this could be equal to or less than maximum supported Sideport memory clock + +ulSystemConfig: +Bit[0]=1: PowerExpress mode =0 Non-PowerExpress mode; +Bit[1]=1: system boots up at AMD overdrived state or user customized mode. In this case, driver will just stick to this boot-up mode. No other PowerPlay state + =0: system boots up at driver control state. Power state depends on PowerPlay table. +Bit[2]=1: PWM method is used on NB voltage control. =0: GPIO method is used. +Bit[3]=1: Only one power state(Performance) will be supported. + =0: Multiple power states supported from PowerPlay table. +Bit[4]=1: CLMC is supported and enabled on current system. + =0: CLMC is not supported or enabled on current system. SBIOS need to support HT link/freq change through ATIF interface. +Bit[5]=1: Enable CDLW for all driver control power states. Max HT width is from SBIOS, while Min HT width is determined by display requirement. + =0: CDLW is disabled. If CLMC is enabled case, Min HT width will be set equal to Max HT width. If CLMC disabled case, Max HT width will be applied. +Bit[6]=1: High Voltage requested for all power states. In this case, voltage will be forced at 1.1v and powerplay table voltage drop/throttling request will be ignored. + =0: Voltage settings is determined by powerplay table. +Bit[7]=1: Enable CLMC as hybrid Mode. CDLD and CILR will be disabled in this case and we're using legacy C1E. This is workaround for CPU(Griffin) performance issue. + =0: Enable CLMC as regular mode, CDLD and CILR will be enabled. +Bit[8]=1: CDLF is supported and enabled on current system. + =0: CDLF is not supported or enabled on current system. +Bit[9]=1: DLL Shut Down feature is enabled on current system. + =0: DLL Shut Down feature is not enabled or supported on current system. + +ulBootUpReqDisplayVector: This dword is a bit vector indicates what display devices are requested during boot-up. Refer to ATOM_DEVICE_xxx_SUPPORT for the bit vector definitions. + +ulOtherDisplayMisc: [15:8]- Bootup LCD Expansion selection; 0-center, 1-full panel size expansion; + [7:0] - BootupTV standard selection; This is a bit vector to indicate what TV standards are supported by the system. Refer to ucTVSupportedStd definition; + +ulDDISlot1Config: Describes the PCIE lane configuration on this DDI PCIE slot (ADD2 card) or connector (Mobile design). + [3:0] - Bit vector to indicate PCIE lane config of the DDI slot/connector on chassis (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12) + [7:4] - Bit vector to indicate PCIE lane config of the same DDI slot/connector on docking station (bit 4=1 lane 3:0; bit 5=1 lane 7:4; bit 6=1 lane 11:8; bit 7=1 lane 15:12) + When a DDI connector is not "paired" (meaming two connections mutualexclusive on chassis or docking, only one of them can be connected at one time. + in both chassis and docking, SBIOS has to duplicate the same PCIE lane info from chassis to docking or vice versa. For example: + one DDI connector is only populated in docking with PCIE lane 8-11, but there is no paired connection on chassis, SBIOS has to copy bit 6 to bit 2. + + [15:8] - Lane configuration attribute; + [23:16]- Connector type, possible value: + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D + CONNECTOR_OBJECT_ID_HDMI_TYPE_A + CONNECTOR_OBJECT_ID_DISPLAYPORT + CONNECTOR_OBJECT_ID_eDP + [31:24]- Reserved + +ulDDISlot2Config: Same as Slot1. +ucMemoryType: SidePort memory type, set it to 0x0 when Sideport memory is not installed. Driver needs this info to change sideport memory clock. Not for display in CCC. +For IGP, Hypermemory is the only memory type showed in CCC. + +ucUMAChannelNumber: how many channels for the UMA; + +ulDockingPinCFGInfo: [15:0]-Bus/Device/Function # to CFG to read this Docking Pin; [31:16]-reg offset in CFG to read this pin +ucDockingPinBit: which bit in this register to read the pin status; +ucDockingPinPolarity:Polarity of the pin when docked; + +ulCPUCapInfo: [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, [7:0]=4:Pharaoh, other bits reserved for now and must be 0x0 + +usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%. + +usMaxNBVoltage:Max. voltage control value in either PWM or GPIO mode. +usMinNBVoltage:Min. voltage control value in either PWM or GPIO mode. + GPIO mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=0 + PWM mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=1 + GPU SW don't control mode: usMaxNBVoltage & usMinNBVoltage=0 and no care about ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE + +usBootUpNBVoltage:Boot-up voltage regulator dependent PWM value. + +ulHTLinkFreq: Bootup HT link Frequency in 10Khz. +usMinHTLinkWidth: Bootup minimum HT link width. If CDLW disabled, this is equal to usMaxHTLinkWidth. + If CDLW enabled, both upstream and downstream width should be the same during bootup. +usMaxHTLinkWidth: Bootup maximum HT link width. If CDLW disabled, this is equal to usMinHTLinkWidth. + If CDLW enabled, both upstream and downstream width should be the same during bootup. + +usUMASyncStartDelay: Memory access latency, required for watermark calculation +usUMADataReturnTime: Memory access latency, required for watermark calculation +usLinkStatusZeroTime:Memory access latency required for watermark calculation, set this to 0x0 for K8 CPU, set a proper value in 0.01 the unit of us +for Griffin or Greyhound. SBIOS needs to convert to actual time by: + if T0Ttime [5:4]=00b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.1us (0.0 to 1.5us) + if T0Ttime [5:4]=01b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.5us (0.0 to 7.5us) + if T0Ttime [5:4]=10b, then usLinkStatusZeroTime=T0Ttime [3:0]*2.0us (0.0 to 30us) + if T0Ttime [5:4]=11b, and T0Ttime [3:0]=0x0 to 0xa, then usLinkStatusZeroTime=T0Ttime [3:0]*20us (0.0 to 200us) + +ulHighVoltageHTLinkFreq: HT link frequency for power state with low voltage. If boot up runs in HT1, this must be 0. + This must be less than or equal to ulHTLinkFreq(bootup frequency). +ulLowVoltageHTLinkFreq: HT link frequency for power state with low voltage or voltage scaling 1.0v~1.1v. If boot up runs in HT1, this must be 0. + This must be less than or equal to ulHighVoltageHTLinkFreq. + +usMaxUpStreamHTLinkWidth: Asymmetric link width support in the future, to replace usMaxHTLinkWidth. Not used for now. +usMaxDownStreamHTLinkWidth: same as above. +usMinUpStreamHTLinkWidth: Asymmetric link width support in the future, to replace usMinHTLinkWidth. Not used for now. +usMinDownStreamHTLinkWidth: same as above. +*/ + +// ATOM_INTEGRATED_SYSTEM_INFO::ulCPUCapInfo - CPU type definition +#define INTEGRATED_SYSTEM_INFO__UNKNOWN_CPU 0 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__GRIFFIN 1 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__GREYHOUND 2 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__K8 3 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH 4 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__OROCHI 5 + +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__MAX_CODE INTEGRATED_SYSTEM_INFO__AMD_CPU__OROCHI // this deff reflects max defined CPU code + +#define SYSTEM_CONFIG_POWEREXPRESS_ENABLE 0x00000001 +#define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE 0x00000002 +#define SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE 0x00000004 +#define SYSTEM_CONFIG_PERFORMANCE_POWERSTATE_ONLY 0x00000008 +#define SYSTEM_CONFIG_CLMC_ENABLED 0x00000010 +#define SYSTEM_CONFIG_CDLW_ENABLED 0x00000020 +#define SYSTEM_CONFIG_HIGH_VOLTAGE_REQUESTED 0x00000040 +#define SYSTEM_CONFIG_CLMC_HYBRID_MODE_ENABLED 0x00000080 +#define SYSTEM_CONFIG_CDLF_ENABLED 0x00000100 +#define SYSTEM_CONFIG_DLL_SHUTDOWN_ENABLED 0x00000200 + +#define IGP_DDI_SLOT_LANE_CONFIG_MASK 0x000000FF + +#define b0IGP_DDI_SLOT_LANE_MAP_MASK 0x0F +#define b0IGP_DDI_SLOT_DOCKING_LANE_MAP_MASK 0xF0 +#define b0IGP_DDI_SLOT_CONFIG_LANE_0_3 0x01 +#define b0IGP_DDI_SLOT_CONFIG_LANE_4_7 0x02 +#define b0IGP_DDI_SLOT_CONFIG_LANE_8_11 0x04 +#define b0IGP_DDI_SLOT_CONFIG_LANE_12_15 0x08 + +#define IGP_DDI_SLOT_ATTRIBUTE_MASK 0x0000FF00 +#define IGP_DDI_SLOT_CONFIG_REVERSED 0x00000100 +#define b1IGP_DDI_SLOT_CONFIG_REVERSED 0x01 + +#define IGP_DDI_SLOT_CONNECTOR_TYPE_MASK 0x00FF0000 + +// IntegratedSystemInfoTable new Rev is V5 after V2, because of the real rev of V2 is v1.4. This rev is used for RR +typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulBootUpEngineClock; //in 10kHz unit + ULONG ulDentistVCOFreq; //Dentist VCO clock in 10kHz unit, the source of GPU SCLK, LCLK, UCLK and VCLK. + ULONG ulLClockFreq; //GPU Lclk freq in 10kHz unit, have relationship with NCLK in NorthBridge + ULONG ulBootUpUMAClock; //in 10kHz unit + ULONG ulReserved1[8]; //must be 0x0 for the reserved + ULONG ulBootUpReqDisplayVector; + ULONG ulOtherDisplayMisc; + ULONG ulReserved2[4]; //must be 0x0 for the reserved + ULONG ulSystemConfig; //TBD + ULONG ulCPUCapInfo; //TBD + USHORT usMaxNBVoltage; //high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; + USHORT usMinNBVoltage; //low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; + USHORT usBootUpNBVoltage; //boot up NB voltage + UCHAR ucHtcTmpLmt; //bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD + UCHAR ucTjOffset; //bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD + ULONG ulReserved3[4]; //must be 0x0 for the reserved + ULONG ulDDISlot1Config; //see above ulDDISlot1Config definition + ULONG ulDDISlot2Config; + ULONG ulDDISlot3Config; + ULONG ulDDISlot4Config; + ULONG ulReserved4[4]; //must be 0x0 for the reserved + UCHAR ucMemoryType; //[3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved + UCHAR ucUMAChannelNumber; + USHORT usReserved; + ULONG ulReserved5[4]; //must be 0x0 for the reserved + ULONG ulCSR_M3_ARB_CNTL_DEFAULT[10];//arrays with values for CSR M3 arbiter for default + ULONG ulCSR_M3_ARB_CNTL_UVD[10]; //arrays with values for CSR M3 arbiter for UVD playback + ULONG ulCSR_M3_ARB_CNTL_FS3D[10];//arrays with values for CSR M3 arbiter for Full Screen 3D applications + ULONG ulReserved6[61]; //must be 0x0 +}ATOM_INTEGRATED_SYSTEM_INFO_V5; + +#define ATOM_CRT_INT_ENCODER1_INDEX 0x00000000 +#define ATOM_LCD_INT_ENCODER1_INDEX 0x00000001 +#define ATOM_TV_INT_ENCODER1_INDEX 0x00000002 +#define ATOM_DFP_INT_ENCODER1_INDEX 0x00000003 +#define ATOM_CRT_INT_ENCODER2_INDEX 0x00000004 +#define ATOM_LCD_EXT_ENCODER1_INDEX 0x00000005 +#define ATOM_TV_EXT_ENCODER1_INDEX 0x00000006 +#define ATOM_DFP_EXT_ENCODER1_INDEX 0x00000007 +#define ATOM_CV_INT_ENCODER1_INDEX 0x00000008 +#define ATOM_DFP_INT_ENCODER2_INDEX 0x00000009 +#define ATOM_CRT_EXT_ENCODER1_INDEX 0x0000000A +#define ATOM_CV_EXT_ENCODER1_INDEX 0x0000000B +#define ATOM_DFP_INT_ENCODER3_INDEX 0x0000000C +#define ATOM_DFP_INT_ENCODER4_INDEX 0x0000000D + +// define ASIC internal encoder id ( bit vector ), used for CRTC_SourceSelTable +#define ASIC_INT_DAC1_ENCODER_ID 0x00 +#define ASIC_INT_TV_ENCODER_ID 0x02 +#define ASIC_INT_DIG1_ENCODER_ID 0x03 +#define ASIC_INT_DAC2_ENCODER_ID 0x04 +#define ASIC_EXT_TV_ENCODER_ID 0x06 +#define ASIC_INT_DVO_ENCODER_ID 0x07 +#define ASIC_INT_DIG2_ENCODER_ID 0x09 +#define ASIC_EXT_DIG_ENCODER_ID 0x05 +#define ASIC_EXT_DIG2_ENCODER_ID 0x08 +#define ASIC_INT_DIG3_ENCODER_ID 0x0a +#define ASIC_INT_DIG4_ENCODER_ID 0x0b +#define ASIC_INT_DIG5_ENCODER_ID 0x0c +#define ASIC_INT_DIG6_ENCODER_ID 0x0d +#define ASIC_INT_DIG7_ENCODER_ID 0x0e + +//define Encoder attribute +#define ATOM_ANALOG_ENCODER 0 +#define ATOM_DIGITAL_ENCODER 1 +#define ATOM_DP_ENCODER 2 + +#define ATOM_ENCODER_ENUM_MASK 0x70 +#define ATOM_ENCODER_ENUM_ID1 0x00 +#define ATOM_ENCODER_ENUM_ID2 0x10 +#define ATOM_ENCODER_ENUM_ID3 0x20 +#define ATOM_ENCODER_ENUM_ID4 0x30 +#define ATOM_ENCODER_ENUM_ID5 0x40 +#define ATOM_ENCODER_ENUM_ID6 0x50 + +#define ATOM_DEVICE_CRT1_INDEX 0x00000000 +#define ATOM_DEVICE_LCD1_INDEX 0x00000001 +#define ATOM_DEVICE_TV1_INDEX 0x00000002 +#define ATOM_DEVICE_DFP1_INDEX 0x00000003 +#define ATOM_DEVICE_CRT2_INDEX 0x00000004 +#define ATOM_DEVICE_LCD2_INDEX 0x00000005 +#define ATOM_DEVICE_DFP6_INDEX 0x00000006 +#define ATOM_DEVICE_DFP2_INDEX 0x00000007 +#define ATOM_DEVICE_CV_INDEX 0x00000008 +#define ATOM_DEVICE_DFP3_INDEX 0x00000009 +#define ATOM_DEVICE_DFP4_INDEX 0x0000000A +#define ATOM_DEVICE_DFP5_INDEX 0x0000000B + +#define ATOM_DEVICE_RESERVEDC_INDEX 0x0000000C +#define ATOM_DEVICE_RESERVEDD_INDEX 0x0000000D +#define ATOM_DEVICE_RESERVEDE_INDEX 0x0000000E +#define ATOM_DEVICE_RESERVEDF_INDEX 0x0000000F +#define ATOM_MAX_SUPPORTED_DEVICE_INFO (ATOM_DEVICE_DFP3_INDEX+1) +#define ATOM_MAX_SUPPORTED_DEVICE_INFO_2 ATOM_MAX_SUPPORTED_DEVICE_INFO +#define ATOM_MAX_SUPPORTED_DEVICE_INFO_3 (ATOM_DEVICE_DFP5_INDEX + 1 ) + +#define ATOM_MAX_SUPPORTED_DEVICE (ATOM_DEVICE_RESERVEDF_INDEX+1) + +#define ATOM_DEVICE_CRT1_SUPPORT (0x1L << ATOM_DEVICE_CRT1_INDEX ) +#define ATOM_DEVICE_LCD1_SUPPORT (0x1L << ATOM_DEVICE_LCD1_INDEX ) +#define ATOM_DEVICE_TV1_SUPPORT (0x1L << ATOM_DEVICE_TV1_INDEX ) +#define ATOM_DEVICE_DFP1_SUPPORT (0x1L << ATOM_DEVICE_DFP1_INDEX ) +#define ATOM_DEVICE_CRT2_SUPPORT (0x1L << ATOM_DEVICE_CRT2_INDEX ) +#define ATOM_DEVICE_LCD2_SUPPORT (0x1L << ATOM_DEVICE_LCD2_INDEX ) +#define ATOM_DEVICE_DFP6_SUPPORT (0x1L << ATOM_DEVICE_DFP6_INDEX ) +#define ATOM_DEVICE_DFP2_SUPPORT (0x1L << ATOM_DEVICE_DFP2_INDEX ) +#define ATOM_DEVICE_CV_SUPPORT (0x1L << ATOM_DEVICE_CV_INDEX ) +#define ATOM_DEVICE_DFP3_SUPPORT (0x1L << ATOM_DEVICE_DFP3_INDEX ) +#define ATOM_DEVICE_DFP4_SUPPORT (0x1L << ATOM_DEVICE_DFP4_INDEX ) +#define ATOM_DEVICE_DFP5_SUPPORT (0x1L << ATOM_DEVICE_DFP5_INDEX ) + +#define ATOM_DEVICE_CRT_SUPPORT (ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT) +#define ATOM_DEVICE_DFP_SUPPORT (ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT | ATOM_DEVICE_DFP3_SUPPORT | ATOM_DEVICE_DFP4_SUPPORT | ATOM_DEVICE_DFP5_SUPPORT | ATOM_DEVICE_DFP6_SUPPORT) +#define ATOM_DEVICE_TV_SUPPORT (ATOM_DEVICE_TV1_SUPPORT) +#define ATOM_DEVICE_LCD_SUPPORT (ATOM_DEVICE_LCD1_SUPPORT | ATOM_DEVICE_LCD2_SUPPORT) + +#define ATOM_DEVICE_CONNECTOR_TYPE_MASK 0x000000F0 +#define ATOM_DEVICE_CONNECTOR_TYPE_SHIFT 0x00000004 +#define ATOM_DEVICE_CONNECTOR_VGA 0x00000001 +#define ATOM_DEVICE_CONNECTOR_DVI_I 0x00000002 +#define ATOM_DEVICE_CONNECTOR_DVI_D 0x00000003 +#define ATOM_DEVICE_CONNECTOR_DVI_A 0x00000004 +#define ATOM_DEVICE_CONNECTOR_SVIDEO 0x00000005 +#define ATOM_DEVICE_CONNECTOR_COMPOSITE 0x00000006 +#define ATOM_DEVICE_CONNECTOR_LVDS 0x00000007 +#define ATOM_DEVICE_CONNECTOR_DIGI_LINK 0x00000008 +#define ATOM_DEVICE_CONNECTOR_SCART 0x00000009 +#define ATOM_DEVICE_CONNECTOR_HDMI_TYPE_A 0x0000000A +#define ATOM_DEVICE_CONNECTOR_HDMI_TYPE_B 0x0000000B +#define ATOM_DEVICE_CONNECTOR_CASE_1 0x0000000E +#define ATOM_DEVICE_CONNECTOR_DISPLAYPORT 0x0000000F + + +#define ATOM_DEVICE_DAC_INFO_MASK 0x0000000F +#define ATOM_DEVICE_DAC_INFO_SHIFT 0x00000000 +#define ATOM_DEVICE_DAC_INFO_NODAC 0x00000000 +#define ATOM_DEVICE_DAC_INFO_DACA 0x00000001 +#define ATOM_DEVICE_DAC_INFO_DACB 0x00000002 +#define ATOM_DEVICE_DAC_INFO_EXDAC 0x00000003 + +#define ATOM_DEVICE_I2C_ID_NOI2C 0x00000000 + +#define ATOM_DEVICE_I2C_LINEMUX_MASK 0x0000000F +#define ATOM_DEVICE_I2C_LINEMUX_SHIFT 0x00000000 + +#define ATOM_DEVICE_I2C_ID_MASK 0x00000070 +#define ATOM_DEVICE_I2C_ID_SHIFT 0x00000004 +#define ATOM_DEVICE_I2C_ID_IS_FOR_NON_MM_USE 0x00000001 +#define ATOM_DEVICE_I2C_ID_IS_FOR_MM_USE 0x00000002 +#define ATOM_DEVICE_I2C_ID_IS_FOR_SDVO_USE 0x00000003 //For IGP RS600 +#define ATOM_DEVICE_I2C_ID_IS_FOR_DAC_SCL 0x00000004 //For IGP RS690 + +#define ATOM_DEVICE_I2C_HARDWARE_CAP_MASK 0x00000080 +#define ATOM_DEVICE_I2C_HARDWARE_CAP_SHIFT 0x00000007 +#define ATOM_DEVICE_USES_SOFTWARE_ASSISTED_I2C 0x00000000 +#define ATOM_DEVICE_USES_HARDWARE_ASSISTED_I2C 0x00000001 + +// usDeviceSupport: +// Bits0 = 0 - no CRT1 support= 1- CRT1 is supported +// Bit 1 = 0 - no LCD1 support= 1- LCD1 is supported +// Bit 2 = 0 - no TV1 support= 1- TV1 is supported +// Bit 3 = 0 - no DFP1 support= 1- DFP1 is supported +// Bit 4 = 0 - no CRT2 support= 1- CRT2 is supported +// Bit 5 = 0 - no LCD2 support= 1- LCD2 is supported +// Bit 6 = 0 - no DFP6 support= 1- DFP6 is supported +// Bit 7 = 0 - no DFP2 support= 1- DFP2 is supported +// Bit 8 = 0 - no CV support= 1- CV is supported +// Bit 9 = 0 - no DFP3 support= 1- DFP3 is supported +// Bit 10 = 0 - no DFP4 support= 1- DFP4 is supported +// Bit 11 = 0 - no DFP5 support= 1- DFP5 is supported +// +// + +/****************************************************************************/ +/* Structure used in MclkSS_InfoTable */ +/****************************************************************************/ +// ucI2C_ConfigID +// [7:0] - I2C LINE Associate ID +// = 0 - no I2C +// [7] - HW_Cap = 1, [6:0]=HW assisted I2C ID(HW line selection) +// = 0, [6:0]=SW assisted I2C ID +// [6-4] - HW_ENGINE_ID = 1, HW engine for NON multimedia use +// = 2, HW engine for Multimedia use +// = 3-7 Reserved for future I2C engines +// [3-0] - I2C_LINE_MUX = A Mux number when it's HW assisted I2C or GPIO ID when it's SW I2C + +typedef struct _ATOM_I2C_ID_CONFIG +{ +#if ATOM_BIG_ENDIAN + UCHAR bfHW_Capable:1; + UCHAR bfHW_EngineID:3; + UCHAR bfI2C_LineMux:4; +#else + UCHAR bfI2C_LineMux:4; + UCHAR bfHW_EngineID:3; + UCHAR bfHW_Capable:1; +#endif +}ATOM_I2C_ID_CONFIG; + +typedef union _ATOM_I2C_ID_CONFIG_ACCESS +{ + ATOM_I2C_ID_CONFIG sbfAccess; + UCHAR ucAccess; +}ATOM_I2C_ID_CONFIG_ACCESS; + + +/****************************************************************************/ +// Structure used in GPIO_I2C_InfoTable +/****************************************************************************/ +typedef struct _ATOM_GPIO_I2C_ASSIGMENT +{ + USHORT usClkMaskRegisterIndex; + USHORT usClkEnRegisterIndex; + USHORT usClkY_RegisterIndex; + USHORT usClkA_RegisterIndex; + USHORT usDataMaskRegisterIndex; + USHORT usDataEnRegisterIndex; + USHORT usDataY_RegisterIndex; + USHORT usDataA_RegisterIndex; + ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; + UCHAR ucClkMaskShift; + UCHAR ucClkEnShift; + UCHAR ucClkY_Shift; + UCHAR ucClkA_Shift; + UCHAR ucDataMaskShift; + UCHAR ucDataEnShift; + UCHAR ucDataY_Shift; + UCHAR ucDataA_Shift; + UCHAR ucReserved1; + UCHAR ucReserved2; +}ATOM_GPIO_I2C_ASSIGMENT; + +typedef struct _ATOM_GPIO_I2C_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_GPIO_I2C_ASSIGMENT asGPIO_Info[ATOM_MAX_SUPPORTED_DEVICE]; +}ATOM_GPIO_I2C_INFO; + +/****************************************************************************/ +// Common Structure used in other structures +/****************************************************************************/ + +#ifndef _H2INC + +//Please don't add or expand this bitfield structure below, this one will retire soon.! +typedef struct _ATOM_MODE_MISC_INFO +{ +#if ATOM_BIG_ENDIAN + USHORT Reserved:6; + USHORT RGB888:1; + USHORT DoubleClock:1; + USHORT Interlace:1; + USHORT CompositeSync:1; + USHORT V_ReplicationBy2:1; + USHORT H_ReplicationBy2:1; + USHORT VerticalCutOff:1; + USHORT VSyncPolarity:1; //0=Active High, 1=Active Low + USHORT HSyncPolarity:1; //0=Active High, 1=Active Low + USHORT HorizontalCutOff:1; +#else + USHORT HorizontalCutOff:1; + USHORT HSyncPolarity:1; //0=Active High, 1=Active Low + USHORT VSyncPolarity:1; //0=Active High, 1=Active Low + USHORT VerticalCutOff:1; + USHORT H_ReplicationBy2:1; + USHORT V_ReplicationBy2:1; + USHORT CompositeSync:1; + USHORT Interlace:1; + USHORT DoubleClock:1; + USHORT RGB888:1; + USHORT Reserved:6; +#endif +}ATOM_MODE_MISC_INFO; + +typedef union _ATOM_MODE_MISC_INFO_ACCESS +{ + ATOM_MODE_MISC_INFO sbfAccess; + USHORT usAccess; +}ATOM_MODE_MISC_INFO_ACCESS; + +#else + +typedef union _ATOM_MODE_MISC_INFO_ACCESS +{ + USHORT usAccess; +}ATOM_MODE_MISC_INFO_ACCESS; + +#endif + +// usModeMiscInfo- +#define ATOM_H_CUTOFF 0x01 +#define ATOM_HSYNC_POLARITY 0x02 //0=Active High, 1=Active Low +#define ATOM_VSYNC_POLARITY 0x04 //0=Active High, 1=Active Low +#define ATOM_V_CUTOFF 0x08 +#define ATOM_H_REPLICATIONBY2 0x10 +#define ATOM_V_REPLICATIONBY2 0x20 +#define ATOM_COMPOSITESYNC 0x40 +#define ATOM_INTERLACE 0x80 +#define ATOM_DOUBLE_CLOCK_MODE 0x100 +#define ATOM_RGB888_MODE 0x200 + +//usRefreshRate- +#define ATOM_REFRESH_43 43 +#define ATOM_REFRESH_47 47 +#define ATOM_REFRESH_56 56 +#define ATOM_REFRESH_60 60 +#define ATOM_REFRESH_65 65 +#define ATOM_REFRESH_70 70 +#define ATOM_REFRESH_72 72 +#define ATOM_REFRESH_75 75 +#define ATOM_REFRESH_85 85 + +// ATOM_MODE_TIMING data are exactly the same as VESA timing data. +// Translation from EDID to ATOM_MODE_TIMING, use the following formula. +// +// VESA_HTOTAL = VESA_ACTIVE + 2* VESA_BORDER + VESA_BLANK +// = EDID_HA + EDID_HBL +// VESA_HDISP = VESA_ACTIVE = EDID_HA +// VESA_HSYNC_START = VESA_ACTIVE + VESA_BORDER + VESA_FRONT_PORCH +// = EDID_HA + EDID_HSO +// VESA_HSYNC_WIDTH = VESA_HSYNC_TIME = EDID_HSPW +// VESA_BORDER = EDID_BORDER + +/****************************************************************************/ +// Structure used in SetCRTC_UsingDTDTimingTable +/****************************************************************************/ +typedef struct _SET_CRTC_USING_DTD_TIMING_PARAMETERS +{ + USHORT usH_Size; + USHORT usH_Blanking_Time; + USHORT usV_Size; + USHORT usV_Blanking_Time; + USHORT usH_SyncOffset; + USHORT usH_SyncWidth; + USHORT usV_SyncOffset; + USHORT usV_SyncWidth; + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + UCHAR ucH_Border; // From DFP EDID + UCHAR ucV_Border; + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucPadding[3]; +}SET_CRTC_USING_DTD_TIMING_PARAMETERS; + +/****************************************************************************/ +// Structure used in SetCRTC_TimingTable +/****************************************************************************/ +typedef struct _SET_CRTC_TIMING_PARAMETERS +{ + USHORT usH_Total; // horizontal total + USHORT usH_Disp; // horizontal display + USHORT usH_SyncStart; // horozontal Sync start + USHORT usH_SyncWidth; // horizontal Sync width + USHORT usV_Total; // vertical total + USHORT usV_Disp; // vertical display + USHORT usV_SyncStart; // vertical Sync start + USHORT usV_SyncWidth; // vertical Sync width + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + UCHAR ucCRTC; // ATOM_CRTC1 or ATOM_CRTC2 + UCHAR ucOverscanRight; // right + UCHAR ucOverscanLeft; // left + UCHAR ucOverscanBottom; // bottom + UCHAR ucOverscanTop; // top + UCHAR ucReserved; +}SET_CRTC_TIMING_PARAMETERS; +#define SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION SET_CRTC_TIMING_PARAMETERS + +/****************************************************************************/ +// Structure used in StandardVESA_TimingTable +// AnalogTV_InfoTable +// ComponentVideoInfoTable +/****************************************************************************/ +typedef struct _ATOM_MODE_TIMING +{ + USHORT usCRTC_H_Total; + USHORT usCRTC_H_Disp; + USHORT usCRTC_H_SyncStart; + USHORT usCRTC_H_SyncWidth; + USHORT usCRTC_V_Total; + USHORT usCRTC_V_Disp; + USHORT usCRTC_V_SyncStart; + USHORT usCRTC_V_SyncWidth; + USHORT usPixelClock; //in 10Khz unit + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + USHORT usCRTC_OverscanRight; + USHORT usCRTC_OverscanLeft; + USHORT usCRTC_OverscanBottom; + USHORT usCRTC_OverscanTop; + USHORT usReserve; + UCHAR ucInternalModeNumber; + UCHAR ucRefreshRate; +}ATOM_MODE_TIMING; + +typedef struct _ATOM_DTD_FORMAT +{ + USHORT usPixClk; + USHORT usHActive; + USHORT usHBlanking_Time; + USHORT usVActive; + USHORT usVBlanking_Time; + USHORT usHSyncOffset; + USHORT usHSyncWidth; + USHORT usVSyncOffset; + USHORT usVSyncWidth; + USHORT usImageHSize; + USHORT usImageVSize; + UCHAR ucHBorder; + UCHAR ucVBorder; + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + UCHAR ucInternalModeNumber; + UCHAR ucRefreshRate; +}ATOM_DTD_FORMAT; + +/****************************************************************************/ +// Structure used in LVDS_InfoTable +// * Need a document to describe this table +/****************************************************************************/ +#define SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 +#define SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 +#define SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 +#define SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 + +//ucTableFormatRevision=1 +//ucTableContentRevision=1 +typedef struct _ATOM_LVDS_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT sLCDTiming; + USHORT usModePatchTableOffset; + USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. + USHORT usOffDelayInMs; + UCHAR ucPowerSequenceDigOntoDEin10Ms; + UCHAR ucPowerSequenceDEtoBLOnin10Ms; + UCHAR ucLVDS_Misc; // Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} + // Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} + // Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} + // Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} + UCHAR ucPanelDefaultRefreshRate; + UCHAR ucPanelIdentification; + UCHAR ucSS_Id; +}ATOM_LVDS_INFO; + +//ucTableFormatRevision=1 +//ucTableContentRevision=2 +typedef struct _ATOM_LVDS_INFO_V12 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT sLCDTiming; + USHORT usExtInfoTableOffset; + USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. + USHORT usOffDelayInMs; + UCHAR ucPowerSequenceDigOntoDEin10Ms; + UCHAR ucPowerSequenceDEtoBLOnin10Ms; + UCHAR ucLVDS_Misc; // Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} + // Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} + // Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} + // Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} + UCHAR ucPanelDefaultRefreshRate; + UCHAR ucPanelIdentification; + UCHAR ucSS_Id; + USHORT usLCDVenderID; + USHORT usLCDProductID; + UCHAR ucLCDPanel_SpecialHandlingCap; + UCHAR ucPanelInfoSize; // start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable + UCHAR ucReserved[2]; +}ATOM_LVDS_INFO_V12; + +//Definitions for ucLCDPanel_SpecialHandlingCap: + +//Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. +//Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL +#define LCDPANEL_CAP_READ_EDID 0x1 + +//If a design supports DRR (dynamic refresh rate) on internal panels (LVDS or EDP), this cap is set in ucLCDPanel_SpecialHandlingCap together +//with multiple supported refresh rates@usSupportedRefreshRate. This cap should not be set when only slow refresh rate is supported (static +//refresh rate switch by SW. This is only valid from ATOM_LVDS_INFO_V12 +#define LCDPANEL_CAP_DRR_SUPPORTED 0x2 + +//Use this cap bit for a quick reference whether an embadded panel (LCD1 ) is LVDS or eDP. +#define LCDPANEL_CAP_eDP 0x4 + + +//Color Bit Depth definition in EDID V1.4 @BYTE 14h +//Bit 6 5 4 + // 0 0 0 - Color bit depth is undefined + // 0 0 1 - 6 Bits per Primary Color + // 0 1 0 - 8 Bits per Primary Color + // 0 1 1 - 10 Bits per Primary Color + // 1 0 0 - 12 Bits per Primary Color + // 1 0 1 - 14 Bits per Primary Color + // 1 1 0 - 16 Bits per Primary Color + // 1 1 1 - Reserved + +#define PANEL_COLOR_BIT_DEPTH_MASK 0x70 + +// Bit7:{=0:Random Dithering disabled;1 Random Dithering enabled} +#define PANEL_RANDOM_DITHER 0x80 +#define PANEL_RANDOM_DITHER_MASK 0x80 + +#define ATOM_LVDS_INFO_LAST ATOM_LVDS_INFO_V12 // no need to change this + +/****************************************************************************/ +// Structures used by LCD_InfoTable V1.3 Note: previous version was called ATOM_LVDS_INFO_V12 +// ASIC Families: NI +// ucTableFormatRevision=1 +// ucTableContentRevision=3 +/****************************************************************************/ +typedef struct _ATOM_LCD_INFO_V13 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT sLCDTiming; + USHORT usExtInfoTableOffset; + USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. + ULONG ulReserved0; + UCHAR ucLCD_Misc; // Reorganized in V13 + // Bit0: {=0:single, =1:dual}, + // Bit1: {=0:LDI format for RGB888, =1 FPDI format for RGB888} // was {=0:666RGB, =1:888RGB}, + // Bit3:2: {Grey level} + // Bit6:4 Color Bit Depth definition (see below definition in EDID V1.4 @BYTE 14h) + // Bit7 Reserved. was for ATOM_PANEL_MISC_API_ENABLED, still need it? + UCHAR ucPanelDefaultRefreshRate; + UCHAR ucPanelIdentification; + UCHAR ucSS_Id; + USHORT usLCDVenderID; + USHORT usLCDProductID; + UCHAR ucLCDPanel_SpecialHandlingCap; // Reorganized in V13 + // Bit0: Once DAL sees this CAP is set, it will read EDID from LCD on its own + // Bit1: See LCDPANEL_CAP_DRR_SUPPORTED + // Bit2: a quick reference whether an embadded panel (LCD1 ) is LVDS (0) or eDP (1) + // Bit7-3: Reserved + UCHAR ucPanelInfoSize; // start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable + USHORT usBacklightPWM; // Backlight PWM in Hz. New in _V13 + + UCHAR ucPowerSequenceDIGONtoDE_in4Ms; + UCHAR ucPowerSequenceDEtoVARY_BL_in4Ms; + UCHAR ucPowerSequenceVARY_BLtoDE_in4Ms; + UCHAR ucPowerSequenceDEtoDIGON_in4Ms; + + UCHAR ucOffDelay_in4Ms; + UCHAR ucPowerSequenceVARY_BLtoBLON_in4Ms; + UCHAR ucPowerSequenceBLONtoVARY_BL_in4Ms; + UCHAR ucReserved1; + + UCHAR ucDPCD_eDP_CONFIGURATION_CAP; // dpcd 0dh + UCHAR ucDPCD_MAX_LINK_RATE; // dpcd 01h + UCHAR ucDPCD_MAX_LANE_COUNT; // dpcd 02h + UCHAR ucDPCD_MAX_DOWNSPREAD; // dpcd 03h + + USHORT usMaxPclkFreqInSingleLink; // Max PixelClock frequency in single link mode. + UCHAR uceDPToLVDSRxId; + UCHAR ucLcdReservd; + ULONG ulReserved[2]; +}ATOM_LCD_INFO_V13; + +#define ATOM_LCD_INFO_LAST ATOM_LCD_INFO_V13 + +//Definitions for ucLCD_Misc +#define ATOM_PANEL_MISC_V13_DUAL 0x00000001 +#define ATOM_PANEL_MISC_V13_FPDI 0x00000002 +#define ATOM_PANEL_MISC_V13_GREY_LEVEL 0x0000000C +#define ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT 2 +#define ATOM_PANEL_MISC_V13_COLOR_BIT_DEPTH_MASK 0x70 +#define ATOM_PANEL_MISC_V13_6BIT_PER_COLOR 0x10 +#define ATOM_PANEL_MISC_V13_8BIT_PER_COLOR 0x20 + +//Color Bit Depth definition in EDID V1.4 @BYTE 14h +//Bit 6 5 4 + // 0 0 0 - Color bit depth is undefined + // 0 0 1 - 6 Bits per Primary Color + // 0 1 0 - 8 Bits per Primary Color + // 0 1 1 - 10 Bits per Primary Color + // 1 0 0 - 12 Bits per Primary Color + // 1 0 1 - 14 Bits per Primary Color + // 1 1 0 - 16 Bits per Primary Color + // 1 1 1 - Reserved + +//Definitions for ucLCDPanel_SpecialHandlingCap: + +//Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. +//Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL +#define LCDPANEL_CAP_V13_READ_EDID 0x1 // = LCDPANEL_CAP_READ_EDID no change comparing to previous version + +//If a design supports DRR (dynamic refresh rate) on internal panels (LVDS or EDP), this cap is set in ucLCDPanel_SpecialHandlingCap together +//with multiple supported refresh rates@usSupportedRefreshRate. This cap should not be set when only slow refresh rate is supported (static +//refresh rate switch by SW. This is only valid from ATOM_LVDS_INFO_V12 +#define LCDPANEL_CAP_V13_DRR_SUPPORTED 0x2 // = LCDPANEL_CAP_DRR_SUPPORTED no change comparing to previous version + +//Use this cap bit for a quick reference whether an embadded panel (LCD1 ) is LVDS or eDP. +#define LCDPANEL_CAP_V13_eDP 0x4 // = LCDPANEL_CAP_eDP no change comparing to previous version + +//uceDPToLVDSRxId +#define eDP_TO_LVDS_RX_DISABLE 0x00 // no eDP->LVDS translator chip +#define eDP_TO_LVDS_COMMON_ID 0x01 // common eDP->LVDS translator chip without AMD SW init +#define eDP_TO_LVDS_RT_ID 0x02 // RT tanslator which require AMD SW init + +typedef struct _ATOM_PATCH_RECORD_MODE +{ + UCHAR ucRecordType; + USHORT usHDisp; + USHORT usVDisp; +}ATOM_PATCH_RECORD_MODE; + +typedef struct _ATOM_LCD_RTS_RECORD +{ + UCHAR ucRecordType; + UCHAR ucRTSValue; +}ATOM_LCD_RTS_RECORD; + +//!! If the record below exits, it shoud always be the first record for easy use in command table!!! +// The record below is only used when LVDS_Info is present. From ATOM_LVDS_INFO_V12, use ucLCDPanel_SpecialHandlingCap instead. +typedef struct _ATOM_LCD_MODE_CONTROL_CAP +{ + UCHAR ucRecordType; + USHORT usLCDCap; +}ATOM_LCD_MODE_CONTROL_CAP; + +#define LCD_MODE_CAP_BL_OFF 1 +#define LCD_MODE_CAP_CRTC_OFF 2 +#define LCD_MODE_CAP_PANEL_OFF 4 + +typedef struct _ATOM_FAKE_EDID_PATCH_RECORD +{ + UCHAR ucRecordType; + UCHAR ucFakeEDIDLength; + UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. +} ATOM_FAKE_EDID_PATCH_RECORD; + +typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD +{ + UCHAR ucRecordType; + USHORT usHSize; + USHORT usVSize; +}ATOM_PANEL_RESOLUTION_PATCH_RECORD; + +#define LCD_MODE_PATCH_RECORD_MODE_TYPE 1 +#define LCD_RTS_RECORD_TYPE 2 +#define LCD_CAP_RECORD_TYPE 3 +#define LCD_FAKE_EDID_PATCH_RECORD_TYPE 4 +#define LCD_PANEL_RESOLUTION_RECORD_TYPE 5 +#define LCD_EDID_OFFSET_PATCH_RECORD_TYPE 6 +#define ATOM_RECORD_END_TYPE 0xFF + +/****************************Spread Spectrum Info Table Definitions **********************/ + +//ucTableFormatRevision=1 +//ucTableContentRevision=2 +typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT +{ + USHORT usSpreadSpectrumPercentage; + UCHAR ucSpreadSpectrumType; //Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Bit2=1: PCIE REFCLK SS =0 iternal PPLL SS Others:TBD + UCHAR ucSS_Step; + UCHAR ucSS_Delay; + UCHAR ucSS_Id; + UCHAR ucRecommendedRef_Div; + UCHAR ucSS_Range; //it was reserved for V11 +}ATOM_SPREAD_SPECTRUM_ASSIGNMENT; + +#define ATOM_MAX_SS_ENTRY 16 +#define ATOM_DP_SS_ID1 0x0f1 // SS ID for internal DP stream at 2.7Ghz. if ATOM_DP_SS_ID2 does not exist in SS_InfoTable, it is used for internal DP stream at 1.62Ghz as well. +#define ATOM_DP_SS_ID2 0x0f2 // SS ID for internal DP stream at 1.62Ghz, if it exists in SS_InfoTable. +#define ATOM_LVLINK_2700MHz_SS_ID 0x0f3 // SS ID for LV link translator chip at 2.7Ghz +#define ATOM_LVLINK_1620MHz_SS_ID 0x0f4 // SS ID for LV link translator chip at 1.62Ghz + + +#define ATOM_SS_DOWN_SPREAD_MODE_MASK 0x00000000 +#define ATOM_SS_DOWN_SPREAD_MODE 0x00000000 +#define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 +#define ATOM_SS_CENTRE_SPREAD_MODE 0x00000001 +#define ATOM_INTERNAL_SS_MASK 0x00000000 +#define ATOM_EXTERNAL_SS_MASK 0x00000002 +#define EXEC_SS_STEP_SIZE_SHIFT 2 +#define EXEC_SS_DELAY_SHIFT 4 +#define ACTIVEDATA_TO_BLON_DELAY_SHIFT 4 + +typedef struct _ATOM_SPREAD_SPECTRUM_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_SPREAD_SPECTRUM_ASSIGNMENT asSS_Info[ATOM_MAX_SS_ENTRY]; +}ATOM_SPREAD_SPECTRUM_INFO; + +/****************************************************************************/ +// Structure used in AnalogTV_InfoTable (Top level) +/****************************************************************************/ +//ucTVBootUpDefaultStd definition: + +//ATOM_TV_NTSC 1 +//ATOM_TV_NTSCJ 2 +//ATOM_TV_PAL 3 +//ATOM_TV_PALM 4 +//ATOM_TV_PALCN 5 +//ATOM_TV_PALN 6 +//ATOM_TV_PAL60 7 +//ATOM_TV_SECAM 8 + +//ucTVSupportedStd definition: +#define NTSC_SUPPORT 0x1 +#define NTSCJ_SUPPORT 0x2 + +#define PAL_SUPPORT 0x4 +#define PALM_SUPPORT 0x8 +#define PALCN_SUPPORT 0x10 +#define PALN_SUPPORT 0x20 +#define PAL60_SUPPORT 0x40 +#define SECAM_SUPPORT 0x80 + +#define MAX_SUPPORTED_TV_TIMING 2 + +typedef struct _ATOM_ANALOG_TV_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucTV_SupportedStandard; + UCHAR ucTV_BootUpDefaultStandard; + UCHAR ucExt_TV_ASIC_ID; + UCHAR ucExt_TV_ASIC_SlaveAddr; + /*ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING];*/ + ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING]; +}ATOM_ANALOG_TV_INFO; + +#define MAX_SUPPORTED_TV_TIMING_V1_2 3 + +typedef struct _ATOM_ANALOG_TV_INFO_V1_2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucTV_SupportedStandard; + UCHAR ucTV_BootUpDefaultStandard; + UCHAR ucExt_TV_ASIC_ID; + UCHAR ucExt_TV_ASIC_SlaveAddr; + ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING_V1_2]; +}ATOM_ANALOG_TV_INFO_V1_2; + +typedef struct _ATOM_DPCD_INFO +{ + UCHAR ucRevisionNumber; //10h : Revision 1.0; 11h : Revision 1.1 + UCHAR ucMaxLinkRate; //06h : 1.62Gbps per lane; 0Ah = 2.7Gbps per lane + UCHAR ucMaxLane; //Bits 4:0 = MAX_LANE_COUNT (1/2/4). Bit 7 = ENHANCED_FRAME_CAP + UCHAR ucMaxDownSpread; //Bit0 = 0: No Down spread; Bit0 = 1: 0.5% (Subject to change according to DP spec) +}ATOM_DPCD_INFO; + +#define ATOM_DPCD_MAX_LANE_MASK 0x1F + +/**************************************************************************/ +// VRAM usage and their defintions + +// One chunk of VRAM used by Bios are for HWICON surfaces,EDID data. +// Current Mode timing and Dail Timing and/or STD timing data EACH device. They can be broken down as below. +// All the addresses below are the offsets from the frame buffer start.They all MUST be Dword aligned! +// To driver: The physical address of this memory portion=mmFB_START(4K aligned)+ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR +// To Bios: ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR->MM_INDEX + +#ifndef VESA_MEMORY_IN_64K_BLOCK +#define VESA_MEMORY_IN_64K_BLOCK 0x100 //256*64K=16Mb (Max. VESA memory is 16Mb!) +#endif + +#define ATOM_EDID_RAW_DATASIZE 256 //In Bytes +#define ATOM_HWICON_SURFACE_SIZE 4096 //In Bytes +#define ATOM_HWICON_INFOTABLE_SIZE 32 +#define MAX_DTD_MODE_IN_VRAM 6 +#define ATOM_DTD_MODE_SUPPORT_TBL_SIZE (MAX_DTD_MODE_IN_VRAM*28) //28= (SIZEOF ATOM_DTD_FORMAT) +#define ATOM_STD_MODE_SUPPORT_TBL_SIZE 32*8 //32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT) +//20 bytes for Encoder Type and DPCD in STD EDID area +#define DFP_ENCODER_TYPE_OFFSET (ATOM_EDID_RAW_DATASIZE + ATOM_DTD_MODE_SUPPORT_TBL_SIZE + ATOM_STD_MODE_SUPPORT_TBL_SIZE - 20) +#define ATOM_DP_DPCD_OFFSET (DFP_ENCODER_TYPE_OFFSET + 4 ) + +#define ATOM_HWICON1_SURFACE_ADDR 0 +#define ATOM_HWICON2_SURFACE_ADDR (ATOM_HWICON1_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE) +#define ATOM_HWICON_INFOTABLE_ADDR (ATOM_HWICON2_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE) +#define ATOM_CRT1_EDID_ADDR (ATOM_HWICON_INFOTABLE_ADDR + ATOM_HWICON_INFOTABLE_SIZE) +#define ATOM_CRT1_DTD_MODE_TBL_ADDR (ATOM_CRT1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_CRT1_STD_MODE_TBL_ADDR (ATOM_CRT1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_LCD1_EDID_ADDR (ATOM_CRT1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_LCD1_DTD_MODE_TBL_ADDR (ATOM_LCD1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_LCD1_STD_MODE_TBL_ADDR (ATOM_LCD1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_TV1_DTD_MODE_TBL_ADDR (ATOM_LCD1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DFP1_EDID_ADDR (ATOM_TV1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DFP1_DTD_MODE_TBL_ADDR (ATOM_DFP1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_DFP1_STD_MODE_TBL_ADDR (ATOM_DFP1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_CRT2_EDID_ADDR (ATOM_DFP1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_CRT2_DTD_MODE_TBL_ADDR (ATOM_CRT2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_CRT2_STD_MODE_TBL_ADDR (ATOM_CRT2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_LCD2_EDID_ADDR (ATOM_CRT2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_LCD2_DTD_MODE_TBL_ADDR (ATOM_LCD2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_LCD2_STD_MODE_TBL_ADDR (ATOM_LCD2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DFP6_EDID_ADDR (ATOM_LCD2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DFP6_DTD_MODE_TBL_ADDR (ATOM_DFP6_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_DFP6_STD_MODE_TBL_ADDR (ATOM_DFP6_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DFP2_EDID_ADDR (ATOM_DFP6_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DFP2_DTD_MODE_TBL_ADDR (ATOM_DFP2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_DFP2_STD_MODE_TBL_ADDR (ATOM_DFP2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_CV_EDID_ADDR (ATOM_DFP2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_CV_DTD_MODE_TBL_ADDR (ATOM_CV_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_CV_STD_MODE_TBL_ADDR (ATOM_CV_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DFP3_EDID_ADDR (ATOM_CV_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DFP3_DTD_MODE_TBL_ADDR (ATOM_DFP3_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_DFP3_STD_MODE_TBL_ADDR (ATOM_DFP3_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DFP4_EDID_ADDR (ATOM_DFP3_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DFP4_DTD_MODE_TBL_ADDR (ATOM_DFP4_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_DFP4_STD_MODE_TBL_ADDR (ATOM_DFP4_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DFP5_EDID_ADDR (ATOM_DFP4_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DFP5_DTD_MODE_TBL_ADDR (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) +#define ATOM_DFP5_STD_MODE_TBL_ADDR (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_DP_TRAINING_TBL_ADDR (ATOM_DFP5_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) + +#define ATOM_STACK_STORAGE_START (ATOM_DP_TRAINING_TBL_ADDR + 1024) +#define ATOM_STACK_STORAGE_END ATOM_STACK_STORAGE_START + 512 + +//The size below is in Kb! +#define ATOM_VRAM_RESERVE_SIZE ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC) + +#define ATOM_VRAM_RESERVE_V2_SIZE 32 + +#define ATOM_VRAM_OPERATION_FLAGS_MASK 0xC0000000L +#define ATOM_VRAM_OPERATION_FLAGS_SHIFT 30 +#define ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION 0x1 +#define ATOM_VRAM_BLOCK_NEEDS_RESERVATION 0x0 + +/***********************************************************************************/ +// Structure used in VRAM_UsageByFirmwareTable +// Note1: This table is filled by SetBiosReservationStartInFB in CoreCommSubs.asm +// at running time. +// note2: From RV770, the memory is more than 32bit addressable, so we will change +// ucTableFormatRevision=1,ucTableContentRevision=4, the strcuture remains +// exactly same as 1.1 and 1.2 (1.3 is never in use), but ulStartAddrUsedByFirmware +// (in offset to start of memory address) is KB aligned instead of byte aligend. +/***********************************************************************************/ +// Note3: +/* If we change usReserved to "usFBUsedbyDrvInKB", then to VBIOS this usFBUsedbyDrvInKB is a predefined, unchanged constant across VGA or non VGA adapter, +for CAIL, The size of FB access area is known, only thing missing is the Offset of FB Access area, so we can have: + +If (ulStartAddrUsedByFirmware!=0) +FBAccessAreaOffset= ulStartAddrUsedByFirmware - usFBUsedbyDrvInKB; +Reserved area has been claimed by VBIOS including this FB access area; CAIL doesn't need to reserve any extra area for this purpose +else //Non VGA case + if (FB_Size<=2Gb) + FBAccessAreaOffset= FB_Size - usFBUsedbyDrvInKB; + else + FBAccessAreaOffset= Aper_Size - usFBUsedbyDrvInKB + +CAIL needs to claim an reserved area defined by FBAccessAreaOffset and usFBUsedbyDrvInKB in non VGA case.*/ + +/***********************************************************************************/ +#define ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO 1 + +typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO +{ + ULONG ulStartAddrUsedByFirmware; + USHORT usFirmwareUseInKb; + USHORT usReserved; +}ATOM_FIRMWARE_VRAM_RESERVE_INFO; + +typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_FIRMWARE_VRAM_RESERVE_INFO asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO]; +}ATOM_VRAM_USAGE_BY_FIRMWARE; + +// change verion to 1.5, when allow driver to allocate the vram area for command table access. +typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO_V1_5 +{ + ULONG ulStartAddrUsedByFirmware; + USHORT usFirmwareUseInKb; + USHORT usFBUsedByDrvInKb; +}ATOM_FIRMWARE_VRAM_RESERVE_INFO_V1_5; + +typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE_V1_5 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_FIRMWARE_VRAM_RESERVE_INFO_V1_5 asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO]; +}ATOM_VRAM_USAGE_BY_FIRMWARE_V1_5; + +/****************************************************************************/ +// Structure used in GPIO_Pin_LUTTable +/****************************************************************************/ +typedef struct _ATOM_GPIO_PIN_ASSIGNMENT +{ + USHORT usGpioPin_AIndex; + UCHAR ucGpioPinBitShift; + UCHAR ucGPIO_ID; +}ATOM_GPIO_PIN_ASSIGNMENT; + +typedef struct _ATOM_GPIO_PIN_LUT +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1]; +}ATOM_GPIO_PIN_LUT; + +/****************************************************************************/ +// Structure used in ComponentVideoInfoTable +/****************************************************************************/ +#define GPIO_PIN_ACTIVE_HIGH 0x1 + +#define MAX_SUPPORTED_CV_STANDARDS 5 + +// definitions for ATOM_D_INFO.ucSettings +#define ATOM_GPIO_SETTINGS_BITSHIFT_MASK 0x1F // [4:0] +#define ATOM_GPIO_SETTINGS_RESERVED_MASK 0x60 // [6:5] = must be zeroed out +#define ATOM_GPIO_SETTINGS_ACTIVE_MASK 0x80 // [7] + +typedef struct _ATOM_GPIO_INFO +{ + USHORT usAOffset; + UCHAR ucSettings; + UCHAR ucReserved; +}ATOM_GPIO_INFO; + +// definitions for ATOM_COMPONENT_VIDEO_INFO.ucMiscInfo (bit vector) +#define ATOM_CV_RESTRICT_FORMAT_SELECTION 0x2 + +// definitions for ATOM_COMPONENT_VIDEO_INFO.uc480i/uc480p/uc720p/uc1080i +#define ATOM_GPIO_DEFAULT_MODE_EN 0x80 //[7]; +#define ATOM_GPIO_SETTING_PERMODE_MASK 0x7F //[6:0] + +// definitions for ATOM_COMPONENT_VIDEO_INFO.ucLetterBoxMode +//Line 3 out put 5V. +#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_A 0x01 //represent gpio 3 state for 16:9 +#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_B 0x02 //represent gpio 4 state for 16:9 +#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_SHIFT 0x0 + +//Line 3 out put 2.2V +#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_A 0x04 //represent gpio 3 state for 4:3 Letter box +#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_B 0x08 //represent gpio 4 state for 4:3 Letter box +#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_SHIFT 0x2 + +//Line 3 out put 0V +#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_A 0x10 //represent gpio 3 state for 4:3 +#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_B 0x20 //represent gpio 4 state for 4:3 +#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_SHIFT 0x4 + +#define ATOM_CV_LINE3_ASPECTRATIO_MASK 0x3F // bit [5:0] + +#define ATOM_CV_LINE3_ASPECTRATIO_EXIST 0x80 //bit 7 + +//GPIO bit index in gpio setting per mode value, also represend the block no. in gpio blocks. +#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_A 3 //bit 3 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. +#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_B 4 //bit 4 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. + + +typedef struct _ATOM_COMPONENT_VIDEO_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMask_PinRegisterIndex; + USHORT usEN_PinRegisterIndex; + USHORT usY_PinRegisterIndex; + USHORT usA_PinRegisterIndex; + UCHAR ucBitShift; + UCHAR ucPinActiveState; //ucPinActiveState: Bit0=1 active high, =0 active low + ATOM_DTD_FORMAT sReserved; // must be zeroed out + UCHAR ucMiscInfo; + UCHAR uc480i; + UCHAR uc480p; + UCHAR uc720p; + UCHAR uc1080i; + UCHAR ucLetterBoxMode; + UCHAR ucReserved[3]; + UCHAR ucNumOfWbGpioBlocks; //For Component video D-Connector support. If zere, NTSC type connector + ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS]; + ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS]; +}ATOM_COMPONENT_VIDEO_INFO; + +//ucTableFormatRevision=2 +//ucTableContentRevision=1 +typedef struct _ATOM_COMPONENT_VIDEO_INFO_V21 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucMiscInfo; + UCHAR uc480i; + UCHAR uc480p; + UCHAR uc720p; + UCHAR uc1080i; + UCHAR ucReserved; + UCHAR ucLetterBoxMode; + UCHAR ucNumOfWbGpioBlocks; //For Component video D-Connector support. If zere, NTSC type connector + ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS]; + ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS]; +}ATOM_COMPONENT_VIDEO_INFO_V21; + +#define ATOM_COMPONENT_VIDEO_INFO_LAST ATOM_COMPONENT_VIDEO_INFO_V21 + +/****************************************************************************/ +// Structure used in object_InfoTable +/****************************************************************************/ +typedef struct _ATOM_OBJECT_HEADER +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usDeviceSupport; + USHORT usConnectorObjectTableOffset; + USHORT usRouterObjectTableOffset; + USHORT usEncoderObjectTableOffset; + USHORT usProtectionObjectTableOffset; //only available when Protection block is independent. + USHORT usDisplayPathTableOffset; +}ATOM_OBJECT_HEADER; + +typedef struct _ATOM_OBJECT_HEADER_V3 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usDeviceSupport; + USHORT usConnectorObjectTableOffset; + USHORT usRouterObjectTableOffset; + USHORT usEncoderObjectTableOffset; + USHORT usProtectionObjectTableOffset; //only available when Protection block is independent. + USHORT usDisplayPathTableOffset; + USHORT usMiscObjectTableOffset; +}ATOM_OBJECT_HEADER_V3; + +typedef struct _ATOM_DISPLAY_OBJECT_PATH +{ + USHORT usDeviceTag; //supported device + USHORT usSize; //the size of ATOM_DISPLAY_OBJECT_PATH + USHORT usConnObjectId; //Connector Object ID + USHORT usGPUObjectId; //GPU ID + USHORT usGraphicObjIds[1]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. +}ATOM_DISPLAY_OBJECT_PATH; + +typedef struct _ATOM_DISPLAY_EXTERNAL_OBJECT_PATH +{ + USHORT usDeviceTag; //supported device + USHORT usSize; //the size of ATOM_DISPLAY_OBJECT_PATH + USHORT usConnObjectId; //Connector Object ID + USHORT usGPUObjectId; //GPU ID + USHORT usGraphicObjIds[2]; //usGraphicObjIds[0]= GPU internal encoder, usGraphicObjIds[1]= external encoder +}ATOM_DISPLAY_EXTERNAL_OBJECT_PATH; + +typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE +{ + UCHAR ucNumOfDispPath; + UCHAR ucVersion; + UCHAR ucPadding[2]; + ATOM_DISPLAY_OBJECT_PATH asDispPath[1]; +}ATOM_DISPLAY_OBJECT_PATH_TABLE; + + +typedef struct _ATOM_OBJECT //each object has this structure +{ + USHORT usObjectID; + USHORT usSrcDstTableOffset; + USHORT usRecordOffset; //this pointing to a bunch of records defined below + USHORT usReserved; +}ATOM_OBJECT; + +typedef struct _ATOM_OBJECT_TABLE //Above 4 object table offset pointing to a bunch of objects all have this structure +{ + UCHAR ucNumberOfObjects; + UCHAR ucPadding[3]; + ATOM_OBJECT asObjects[1]; +}ATOM_OBJECT_TABLE; + +typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT //usSrcDstTableOffset pointing to this structure +{ + UCHAR ucNumberOfSrc; + USHORT usSrcObjectID[1]; + UCHAR ucNumberOfDst; + USHORT usDstObjectID[1]; +}ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT; + + +//Two definitions below are for OPM on MXM module designs + +#define EXT_HPDPIN_LUTINDEX_0 0 +#define EXT_HPDPIN_LUTINDEX_1 1 +#define EXT_HPDPIN_LUTINDEX_2 2 +#define EXT_HPDPIN_LUTINDEX_3 3 +#define EXT_HPDPIN_LUTINDEX_4 4 +#define EXT_HPDPIN_LUTINDEX_5 5 +#define EXT_HPDPIN_LUTINDEX_6 6 +#define EXT_HPDPIN_LUTINDEX_7 7 +#define MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES (EXT_HPDPIN_LUTINDEX_7+1) + +#define EXT_AUXDDC_LUTINDEX_0 0 +#define EXT_AUXDDC_LUTINDEX_1 1 +#define EXT_AUXDDC_LUTINDEX_2 2 +#define EXT_AUXDDC_LUTINDEX_3 3 +#define EXT_AUXDDC_LUTINDEX_4 4 +#define EXT_AUXDDC_LUTINDEX_5 5 +#define EXT_AUXDDC_LUTINDEX_6 6 +#define EXT_AUXDDC_LUTINDEX_7 7 +#define MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES (EXT_AUXDDC_LUTINDEX_7+1) + +//ucChannelMapping are defined as following +//for DP connector, eDP, DP to VGA/LVDS +//Bit[1:0]: Define which pin connect to DP connector DP_Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[3:2]: Define which pin connect to DP connector DP_Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[5:4]: Define which pin connect to DP connector DP_Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[7:6]: Define which pin connect to DP connector DP_Lane3, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +typedef struct _ATOM_DP_CONN_CHANNEL_MAPPING +{ +#if ATOM_BIG_ENDIAN + UCHAR ucDP_Lane3_Source:2; + UCHAR ucDP_Lane2_Source:2; + UCHAR ucDP_Lane1_Source:2; + UCHAR ucDP_Lane0_Source:2; +#else + UCHAR ucDP_Lane0_Source:2; + UCHAR ucDP_Lane1_Source:2; + UCHAR ucDP_Lane2_Source:2; + UCHAR ucDP_Lane3_Source:2; +#endif +}ATOM_DP_CONN_CHANNEL_MAPPING; + +//for DVI/HDMI, in dual link case, both links have to have same mapping. +//Bit[1:0]: Define which pin connect to DVI connector data Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[3:2]: Define which pin connect to DVI connector data Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[5:4]: Define which pin connect to DVI connector data Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[7:6]: Define which pin connect to DVI connector clock lane, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +typedef struct _ATOM_DVI_CONN_CHANNEL_MAPPING +{ +#if ATOM_BIG_ENDIAN + UCHAR ucDVI_CLK_Source:2; + UCHAR ucDVI_DATA0_Source:2; + UCHAR ucDVI_DATA1_Source:2; + UCHAR ucDVI_DATA2_Source:2; +#else + UCHAR ucDVI_DATA2_Source:2; + UCHAR ucDVI_DATA1_Source:2; + UCHAR ucDVI_DATA0_Source:2; + UCHAR ucDVI_CLK_Source:2; +#endif +}ATOM_DVI_CONN_CHANNEL_MAPPING; + +typedef struct _EXT_DISPLAY_PATH +{ + USHORT usDeviceTag; //A bit vector to show what devices are supported + USHORT usDeviceACPIEnum; //16bit device ACPI id. + USHORT usDeviceConnector; //A physical connector for displays to plug in, using object connector definitions + UCHAR ucExtAUXDDCLutIndex; //An index into external AUX/DDC channel LUT + UCHAR ucExtHPDPINLutIndex; //An index into external HPD pin LUT + USHORT usExtEncoderObjId; //external encoder object id + union{ + UCHAR ucChannelMapping; // if ucChannelMapping=0, using default one to one mapping + ATOM_DP_CONN_CHANNEL_MAPPING asDPMapping; + ATOM_DVI_CONN_CHANNEL_MAPPING asDVIMapping; + }; + UCHAR ucChPNInvert; // bit vector for up to 8 lanes, =0: P and N is not invert, =1 P and N is inverted + USHORT usCaps; + USHORT usReserved; +}EXT_DISPLAY_PATH; + +#define NUMBER_OF_UCHAR_FOR_GUID 16 +#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7 + +//usCaps +#define EXT_DISPLAY_PATH_CAPS__HBR2_DISABLE 0x01 + +typedef struct _ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucGuid [NUMBER_OF_UCHAR_FOR_GUID]; // a GUID is a 16 byte long string + EXT_DISPLAY_PATH sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; // total of fixed 7 entries. + UCHAR ucChecksum; // a simple Checksum of the sum of whole structure equal to 0x0. + UCHAR uc3DStereoPinId; // use for eDP panel + UCHAR ucRemoteDisplayConfig; + UCHAR uceDPToLVDSRxId; + UCHAR Reserved[4]; // for potential expansion +}ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO; + +//Related definitions, all records are different but they have a commond header +typedef struct _ATOM_COMMON_RECORD_HEADER +{ + UCHAR ucRecordType; //An emun to indicate the record type + UCHAR ucRecordSize; //The size of the whole record in byte +}ATOM_COMMON_RECORD_HEADER; + + +#define ATOM_I2C_RECORD_TYPE 1 +#define ATOM_HPD_INT_RECORD_TYPE 2 +#define ATOM_OUTPUT_PROTECTION_RECORD_TYPE 3 +#define ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE 4 +#define ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD_TYPE 5 //Obsolete, switch to use GPIO_CNTL_RECORD_TYPE +#define ATOM_ENCODER_FPGA_CONTROL_RECORD_TYPE 6 //Obsolete, switch to use GPIO_CNTL_RECORD_TYPE +#define ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE 7 +#define ATOM_JTAG_RECORD_TYPE 8 //Obsolete, switch to use GPIO_CNTL_RECORD_TYPE +#define ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE 9 +#define ATOM_ENCODER_DVO_CF_RECORD_TYPE 10 +#define ATOM_CONNECTOR_CF_RECORD_TYPE 11 +#define ATOM_CONNECTOR_HARDCODE_DTD_RECORD_TYPE 12 +#define ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE 13 +#define ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE 14 +#define ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE 15 +#define ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE 16 //This is for the case when connectors are not known to object table +#define ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE 17 //This is for the case when connectors are not known to object table +#define ATOM_OBJECT_LINK_RECORD_TYPE 18 //Once this record is present under one object, it indicats the oobject is linked to another obj described by the record +#define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE 19 +#define ATOM_ENCODER_CAP_RECORD_TYPE 20 + + +//Must be updated when new record type is added,equal to that record definition! +#define ATOM_MAX_OBJECT_RECORD_NUMBER ATOM_ENCODER_CAP_RECORD_TYPE + +typedef struct _ATOM_I2C_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + ATOM_I2C_ID_CONFIG sucI2cId; + UCHAR ucI2CAddr; //The slave address, it's 0 when the record is attached to connector for DDC +}ATOM_I2C_RECORD; + +typedef struct _ATOM_HPD_INT_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucHPDIntGPIOID; //Corresponding block in GPIO_PIN_INFO table gives the pin info + UCHAR ucPlugged_PinState; +}ATOM_HPD_INT_RECORD; + + +typedef struct _ATOM_OUTPUT_PROTECTION_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucProtectionFlag; + UCHAR ucReserved; +}ATOM_OUTPUT_PROTECTION_RECORD; + +typedef struct _ATOM_CONNECTOR_DEVICE_TAG +{ + ULONG ulACPIDeviceEnum; //Reserved for now + USHORT usDeviceID; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT" + USHORT usPadding; +}ATOM_CONNECTOR_DEVICE_TAG; + +typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucNumberOfDevice; + UCHAR ucReserved; + ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation +}ATOM_CONNECTOR_DEVICE_TAG_RECORD; + + +typedef struct _ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucConfigGPIOID; + UCHAR ucConfigGPIOState; //Set to 1 when it's active high to enable external flow in + UCHAR ucFlowinGPIPID; + UCHAR ucExtInGPIPID; +}ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD; + +typedef struct _ATOM_ENCODER_FPGA_CONTROL_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucCTL1GPIO_ID; + UCHAR ucCTL1GPIOState; //Set to 1 when it's active high + UCHAR ucCTL2GPIO_ID; + UCHAR ucCTL2GPIOState; //Set to 1 when it's active high + UCHAR ucCTL3GPIO_ID; + UCHAR ucCTL3GPIOState; //Set to 1 when it's active high + UCHAR ucCTLFPGA_IN_ID; + UCHAR ucPadding[3]; +}ATOM_ENCODER_FPGA_CONTROL_RECORD; + +typedef struct _ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucGPIOID; //Corresponding block in GPIO_PIN_INFO table gives the pin info + UCHAR ucTVActiveState; //Indicating when the pin==0 or 1 when TV is connected +}ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD; + +typedef struct _ATOM_JTAG_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucTMSGPIO_ID; + UCHAR ucTMSGPIOState; //Set to 1 when it's active high + UCHAR ucTCKGPIO_ID; + UCHAR ucTCKGPIOState; //Set to 1 when it's active high + UCHAR ucTDOGPIO_ID; + UCHAR ucTDOGPIOState; //Set to 1 when it's active high + UCHAR ucTDIGPIO_ID; + UCHAR ucTDIGPIOState; //Set to 1 when it's active high + UCHAR ucPadding[2]; +}ATOM_JTAG_RECORD; + + +//The following generic object gpio pin control record type will replace JTAG_RECORD/FPGA_CONTROL_RECORD/DVI_EXT_INPUT_RECORD above gradually +typedef struct _ATOM_GPIO_PIN_CONTROL_PAIR +{ + UCHAR ucGPIOID; // GPIO_ID, find the corresponding ID in GPIO_LUT table + UCHAR ucGPIO_PinState; // Pin state showing how to set-up the pin +}ATOM_GPIO_PIN_CONTROL_PAIR; + +typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucFlags; // Future expnadibility + UCHAR ucNumberOfPins; // Number of GPIO pins used to control the object + ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1]; // the real gpio pin pair determined by number of pins ucNumberOfPins +}ATOM_OBJECT_GPIO_CNTL_RECORD; + +//Definitions for GPIO pin state +#define GPIO_PIN_TYPE_INPUT 0x00 +#define GPIO_PIN_TYPE_OUTPUT 0x10 +#define GPIO_PIN_TYPE_HW_CONTROL 0x20 + +//For GPIO_PIN_TYPE_OUTPUT the following is defined +#define GPIO_PIN_OUTPUT_STATE_MASK 0x01 +#define GPIO_PIN_OUTPUT_STATE_SHIFT 0 +#define GPIO_PIN_STATE_ACTIVE_LOW 0x0 +#define GPIO_PIN_STATE_ACTIVE_HIGH 0x1 + +// Indexes to GPIO array in GLSync record +// GLSync record is for Frame Lock/Gen Lock feature. +#define ATOM_GPIO_INDEX_GLSYNC_REFCLK 0 +#define ATOM_GPIO_INDEX_GLSYNC_HSYNC 1 +#define ATOM_GPIO_INDEX_GLSYNC_VSYNC 2 +#define ATOM_GPIO_INDEX_GLSYNC_SWAP_REQ 3 +#define ATOM_GPIO_INDEX_GLSYNC_SWAP_GNT 4 +#define ATOM_GPIO_INDEX_GLSYNC_INTERRUPT 5 +#define ATOM_GPIO_INDEX_GLSYNC_V_RESET 6 +#define ATOM_GPIO_INDEX_GLSYNC_SWAP_CNTL 7 +#define ATOM_GPIO_INDEX_GLSYNC_SWAP_SEL 8 +#define ATOM_GPIO_INDEX_GLSYNC_MAX 9 + +typedef struct _ATOM_ENCODER_DVO_CF_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + ULONG ulStrengthControl; // DVOA strength control for CF + UCHAR ucPadding[2]; +}ATOM_ENCODER_DVO_CF_RECORD; + +// Bit maps for ATOM_ENCODER_CAP_RECORD.ucEncoderCap +#define ATOM_ENCODER_CAP_RECORD_HBR2 0x01 // DP1.2 HBR2 is supported by HW encoder +#define ATOM_ENCODER_CAP_RECORD_HBR2_EN 0x02 // DP1.2 HBR2 setting is qualified and HBR2 can be enabled + +typedef struct _ATOM_ENCODER_CAP_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + union { + USHORT usEncoderCap; + struct { +#if ATOM_BIG_ENDIAN + USHORT usReserved:14; // Bit1-15 may be defined for other capability in future + USHORT usHBR2En:1; // Bit1 is for DP1.2 HBR2 enable + USHORT usHBR2Cap:1; // Bit0 is for DP1.2 HBR2 capability. +#else + USHORT usHBR2Cap:1; // Bit0 is for DP1.2 HBR2 capability. + USHORT usHBR2En:1; // Bit1 is for DP1.2 HBR2 enable + USHORT usReserved:14; // Bit1-15 may be defined for other capability in future +#endif + }; + }; +}ATOM_ENCODER_CAP_RECORD; + +// value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle +#define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA 1 +#define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB 2 + +typedef struct _ATOM_CONNECTOR_CF_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + USHORT usMaxPixClk; + UCHAR ucFlowCntlGpioId; + UCHAR ucSwapCntlGpioId; + UCHAR ucConnectedDvoBundle; + UCHAR ucPadding; +}ATOM_CONNECTOR_CF_RECORD; + +typedef struct _ATOM_CONNECTOR_HARDCODE_DTD_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + ATOM_DTD_FORMAT asTiming; +}ATOM_CONNECTOR_HARDCODE_DTD_RECORD; + +typedef struct _ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; //ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE + UCHAR ucSubConnectorType; //CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D|X_ID_DUAL_LINK_DVI_D|HDMI_TYPE_A + UCHAR ucReserved; +}ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD; + + +typedef struct _ATOM_ROUTER_DDC_PATH_SELECT_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucMuxType; //decide the number of ucMuxState, =0, no pin state, =1: single state with complement, >1: multiple state + UCHAR ucMuxControlPin; + UCHAR ucMuxState[2]; //for alligment purpose +}ATOM_ROUTER_DDC_PATH_SELECT_RECORD; + +typedef struct _ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucMuxType; + UCHAR ucMuxControlPin; + UCHAR ucMuxState[2]; //for alligment purpose +}ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD; + +// define ucMuxType +#define ATOM_ROUTER_MUX_PIN_STATE_MASK 0x0f +#define ATOM_ROUTER_MUX_PIN_SINGLE_STATE_COMPLEMENT 0x01 + +typedef struct _ATOM_CONNECTOR_HPDPIN_LUT_RECORD //record for ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE +{ + ATOM_COMMON_RECORD_HEADER sheader; + UCHAR ucHPDPINMap[MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES]; //An fixed size array which maps external pins to internal GPIO_PIN_INFO table +}ATOM_CONNECTOR_HPDPIN_LUT_RECORD; + +typedef struct _ATOM_CONNECTOR_AUXDDC_LUT_RECORD //record for ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE +{ + ATOM_COMMON_RECORD_HEADER sheader; + ATOM_I2C_ID_CONFIG ucAUXDDCMap[MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES]; //An fixed size array which maps external pins to internal DDC ID +}ATOM_CONNECTOR_AUXDDC_LUT_RECORD; + +typedef struct _ATOM_OBJECT_LINK_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + USHORT usObjectID; //could be connector, encorder or other object in object.h +}ATOM_OBJECT_LINK_RECORD; + +typedef struct _ATOM_CONNECTOR_REMOTE_CAP_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + USHORT usReserved; +}ATOM_CONNECTOR_REMOTE_CAP_RECORD; + +/****************************************************************************/ +// ASIC voltage data table +/****************************************************************************/ +typedef struct _ATOM_VOLTAGE_INFO_HEADER +{ + USHORT usVDDCBaseLevel; //In number of 50mv unit + USHORT usReserved; //For possible extension table offset + UCHAR ucNumOfVoltageEntries; + UCHAR ucBytesPerVoltageEntry; + UCHAR ucVoltageStep; //Indicating in how many mv increament is one step, 0.5mv unit + UCHAR ucDefaultVoltageEntry; + UCHAR ucVoltageControlI2cLine; + UCHAR ucVoltageControlAddress; + UCHAR ucVoltageControlOffset; +}ATOM_VOLTAGE_INFO_HEADER; + +typedef struct _ATOM_VOLTAGE_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_VOLTAGE_INFO_HEADER viHeader; + UCHAR ucVoltageEntries[64]; //64 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries*ucBytesPerVoltageEntry +}ATOM_VOLTAGE_INFO; + + +typedef struct _ATOM_VOLTAGE_FORMULA +{ + USHORT usVoltageBaseLevel; // In number of 1mv unit + USHORT usVoltageStep; // Indicating in how many mv increament is one step, 1mv unit + UCHAR ucNumOfVoltageEntries; // Number of Voltage Entry, which indicate max Voltage + UCHAR ucFlag; // bit0=0 :step is 1mv =1 0.5mv + UCHAR ucBaseVID; // if there is no lookup table, VID= BaseVID + ( Vol - BaseLevle ) /VoltageStep + UCHAR ucReserved; + UCHAR ucVIDAdjustEntries[32]; // 32 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries +}ATOM_VOLTAGE_FORMULA; + +typedef struct _VOLTAGE_LUT_ENTRY +{ + USHORT usVoltageCode; // The Voltage ID, either GPIO or I2C code + USHORT usVoltageValue; // The corresponding Voltage Value, in mV +}VOLTAGE_LUT_ENTRY; + +typedef struct _ATOM_VOLTAGE_FORMULA_V2 +{ + UCHAR ucNumOfVoltageEntries; // Number of Voltage Entry, which indicate max Voltage + UCHAR ucReserved[3]; + VOLTAGE_LUT_ENTRY asVIDAdjustEntries[32];// 32 is for allocation, the actual number of entries is in ucNumOfVoltageEntries +}ATOM_VOLTAGE_FORMULA_V2; + +typedef struct _ATOM_VOLTAGE_CONTROL +{ + UCHAR ucVoltageControlId; //Indicate it is controlled by I2C or GPIO or HW state machine + UCHAR ucVoltageControlI2cLine; + UCHAR ucVoltageControlAddress; + UCHAR ucVoltageControlOffset; + USHORT usGpioPin_AIndex; //GPIO_PAD register index + UCHAR ucGpioPinBitShift[9]; //at most 8 pin support 255 VIDs, termintate with 0xff + UCHAR ucReserved; +}ATOM_VOLTAGE_CONTROL; + +// Define ucVoltageControlId +#define VOLTAGE_CONTROLLED_BY_HW 0x00 +#define VOLTAGE_CONTROLLED_BY_I2C_MASK 0x7F +#define VOLTAGE_CONTROLLED_BY_GPIO 0x80 +#define VOLTAGE_CONTROL_ID_LM64 0x01 //I2C control, used for R5xx Core Voltage +#define VOLTAGE_CONTROL_ID_DAC 0x02 //I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI +#define VOLTAGE_CONTROL_ID_VT116xM 0x03 //I2C control, used for R6xx Core Voltage +#define VOLTAGE_CONTROL_ID_DS4402 0x04 +#define VOLTAGE_CONTROL_ID_UP6266 0x05 +#define VOLTAGE_CONTROL_ID_SCORPIO 0x06 +#define VOLTAGE_CONTROL_ID_VT1556M 0x07 +#define VOLTAGE_CONTROL_ID_CHL822x 0x08 +#define VOLTAGE_CONTROL_ID_VT1586M 0x09 +#define VOLTAGE_CONTROL_ID_UP1637 0x0A + +typedef struct _ATOM_VOLTAGE_OBJECT +{ + UCHAR ucVoltageType; //Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI + UCHAR ucSize; //Size of Object + ATOM_VOLTAGE_CONTROL asControl; //describ how to control + ATOM_VOLTAGE_FORMULA asFormula; //Indicate How to convert real Voltage to VID +}ATOM_VOLTAGE_OBJECT; + +typedef struct _ATOM_VOLTAGE_OBJECT_V2 +{ + UCHAR ucVoltageType; //Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI + UCHAR ucSize; //Size of Object + ATOM_VOLTAGE_CONTROL asControl; //describ how to control + ATOM_VOLTAGE_FORMULA_V2 asFormula; //Indicate How to convert real Voltage to VID +}ATOM_VOLTAGE_OBJECT_V2; + +typedef struct _ATOM_VOLTAGE_OBJECT_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_VOLTAGE_OBJECT asVoltageObj[3]; //Info for Voltage control +}ATOM_VOLTAGE_OBJECT_INFO; + +typedef struct _ATOM_VOLTAGE_OBJECT_INFO_V2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_VOLTAGE_OBJECT_V2 asVoltageObj[3]; //Info for Voltage control +}ATOM_VOLTAGE_OBJECT_INFO_V2; + +typedef struct _ATOM_LEAKID_VOLTAGE +{ + UCHAR ucLeakageId; + UCHAR ucReserved; + USHORT usVoltage; +}ATOM_LEAKID_VOLTAGE; + +typedef struct _ATOM_VOLTAGE_OBJECT_HEADER_V3{ + UCHAR ucVoltageType; //Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI + UCHAR ucVoltageMode; //Indicate voltage control mode: Init/Set/Leakage/Set phase + USHORT usSize; //Size of Object +}ATOM_VOLTAGE_OBJECT_HEADER_V3; + +typedef struct _VOLTAGE_LUT_ENTRY_V2 +{ + ULONG ulVoltageId; // The Voltage ID which is used to program GPIO register + USHORT usVoltageValue; // The corresponding Voltage Value, in mV +}VOLTAGE_LUT_ENTRY_V2; + +typedef struct _LEAKAGE_VOLTAGE_LUT_ENTRY_V2 +{ + USHORT usVoltageLevel; // The Voltage ID which is used to program GPIO register + USHORT usVoltageId; + USHORT usLeakageId; // The corresponding Voltage Value, in mV +}LEAKAGE_VOLTAGE_LUT_ENTRY_V2; + +typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3 +{ + ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; + UCHAR ucVoltageRegulatorId; //Indicate Voltage Regulator Id + UCHAR ucVoltageControlI2cLine; + UCHAR ucVoltageControlAddress; + UCHAR ucVoltageControlOffset; + ULONG ulReserved; + VOLTAGE_LUT_ENTRY asVolI2cLut[1]; // end with 0xff +}ATOM_I2C_VOLTAGE_OBJECT_V3; + +typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3 +{ + ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; + UCHAR ucVoltageGpioCntlId; // default is 0 which indicate control through CG VID mode + UCHAR ucGpioEntryNum; // indiate the entry numbers of Votlage/Gpio value Look up table + UCHAR ucPhaseDelay; // phase delay in unit of micro second + UCHAR ucReserved; + ULONG ulGpioMaskVal; // GPIO Mask value + VOLTAGE_LUT_ENTRY_V2 asVolGpioLut[1]; +}ATOM_GPIO_VOLTAGE_OBJECT_V3; + +typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 +{ + ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; + UCHAR ucLeakageCntlId; // default is 0 + UCHAR ucLeakageEntryNum; // indicate the entry number of LeakageId/Voltage Lut table + UCHAR ucReserved[2]; + ULONG ulMaxVoltageLevel; + LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[1]; +}ATOM_LEAKAGE_VOLTAGE_OBJECT_V3; + +typedef union _ATOM_VOLTAGE_OBJECT_V3{ + ATOM_GPIO_VOLTAGE_OBJECT_V3 asGpioVoltageObj; + ATOM_I2C_VOLTAGE_OBJECT_V3 asI2cVoltageObj; + ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 asLeakageObj; +}ATOM_VOLTAGE_OBJECT_V3; + +typedef struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_VOLTAGE_OBJECT_V3 asVoltageObj[3]; //Info for Voltage control +}ATOM_VOLTAGE_OBJECT_INFO_V3_1; + +typedef struct _ATOM_ASIC_PROFILE_VOLTAGE +{ + UCHAR ucProfileId; + UCHAR ucReserved; + USHORT usSize; + USHORT usEfuseSpareStartAddr; + USHORT usFuseIndex[8]; //from LSB to MSB, Max 8bit,end of 0xffff if less than 8 efuse id, + ATOM_LEAKID_VOLTAGE asLeakVol[2]; //Leakid and relatd voltage +}ATOM_ASIC_PROFILE_VOLTAGE; + +//ucProfileId +#define ATOM_ASIC_PROFILE_ID_EFUSE_VOLTAGE 1 +#define ATOM_ASIC_PROFILE_ID_EFUSE_PERFORMANCE_VOLTAGE 1 +#define ATOM_ASIC_PROFILE_ID_EFUSE_THERMAL_VOLTAGE 2 + +typedef struct _ATOM_ASIC_PROFILING_INFO +{ + ATOM_COMMON_TABLE_HEADER asHeader; + ATOM_ASIC_PROFILE_VOLTAGE asVoltage; +}ATOM_ASIC_PROFILING_INFO; + +typedef struct _ATOM_POWER_SOURCE_OBJECT +{ + UCHAR ucPwrSrcId; // Power source + UCHAR ucPwrSensorType; // GPIO, I2C or none + UCHAR ucPwrSensId; // if GPIO detect, it is GPIO id, if I2C detect, it is I2C id + UCHAR ucPwrSensSlaveAddr; // Slave address if I2C detect + UCHAR ucPwrSensRegIndex; // I2C register Index if I2C detect + UCHAR ucPwrSensRegBitMask; // detect which bit is used if I2C detect + UCHAR ucPwrSensActiveState; // high active or low active + UCHAR ucReserve[3]; // reserve + USHORT usSensPwr; // in unit of watt +}ATOM_POWER_SOURCE_OBJECT; + +typedef struct _ATOM_POWER_SOURCE_INFO +{ + ATOM_COMMON_TABLE_HEADER asHeader; + UCHAR asPwrbehave[16]; + ATOM_POWER_SOURCE_OBJECT asPwrObj[1]; +}ATOM_POWER_SOURCE_INFO; + + +//Define ucPwrSrcId +#define POWERSOURCE_PCIE_ID1 0x00 +#define POWERSOURCE_6PIN_CONNECTOR_ID1 0x01 +#define POWERSOURCE_8PIN_CONNECTOR_ID1 0x02 +#define POWERSOURCE_6PIN_CONNECTOR_ID2 0x04 +#define POWERSOURCE_8PIN_CONNECTOR_ID2 0x08 + +//define ucPwrSensorId +#define POWER_SENSOR_ALWAYS 0x00 +#define POWER_SENSOR_GPIO 0x01 +#define POWER_SENSOR_I2C 0x02 + +typedef struct _ATOM_CLK_VOLT_CAPABILITY +{ + ULONG ulVoltageIndex; // The Voltage Index indicated by FUSE, same voltage index shared with SCLK DPM fuse table + ULONG ulMaximumSupportedCLK; // Maximum clock supported with specified voltage index, unit in 10kHz +}ATOM_CLK_VOLT_CAPABILITY; + +typedef struct _ATOM_AVAILABLE_SCLK_LIST +{ + ULONG ulSupportedSCLK; // Maximum clock supported with specified voltage index, unit in 10kHz + USHORT usVoltageIndex; // The Voltage Index indicated by FUSE for specified SCLK + USHORT usVoltageID; // The Voltage ID indicated by FUSE for specified SCLK +}ATOM_AVAILABLE_SCLK_LIST; + +// ATOM_INTEGRATED_SYSTEM_INFO_V6 ulSystemConfig cap definition +#define ATOM_IGP_INFO_V6_SYSTEM_CONFIG__PCIE_POWER_GATING_ENABLE 1 // refer to ulSystemConfig bit[0] + +// this IntegrateSystemInfoTable is used for Liano/Ontario APU +typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulBootUpEngineClock; + ULONG ulDentistVCOFreq; + ULONG ulBootUpUMAClock; + ATOM_CLK_VOLT_CAPABILITY sDISPCLK_Voltage[4]; + ULONG ulBootUpReqDisplayVector; + ULONG ulOtherDisplayMisc; + ULONG ulGPUCapInfo; + ULONG ulSB_MMIO_Base_Addr; + USHORT usRequestedPWMFreqInHz; + UCHAR ucHtcTmpLmt; + UCHAR ucHtcHystLmt; + ULONG ulMinEngineClock; + ULONG ulSystemConfig; + ULONG ulCPUCapInfo; + USHORT usNBP0Voltage; + USHORT usNBP1Voltage; + USHORT usBootUpNBVoltage; + USHORT usExtDispConnInfoOffset; + USHORT usPanelRefreshRateRange; + UCHAR ucMemoryType; + UCHAR ucUMAChannelNumber; + ULONG ulCSR_M3_ARB_CNTL_DEFAULT[10]; + ULONG ulCSR_M3_ARB_CNTL_UVD[10]; + ULONG ulCSR_M3_ARB_CNTL_FS3D[10]; + ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5]; + ULONG ulGMCRestoreResetTime; + ULONG ulMinimumNClk; + ULONG ulIdleNClk; + ULONG ulDDR_DLL_PowerUpTime; + ULONG ulDDR_PLL_PowerUpTime; + USHORT usPCIEClkSSPercentage; + USHORT usPCIEClkSSType; + USHORT usLvdsSSPercentage; + USHORT usLvdsSSpreadRateIn10Hz; + USHORT usHDMISSPercentage; + USHORT usHDMISSpreadRateIn10Hz; + USHORT usDVISSPercentage; + USHORT usDVISSpreadRateIn10Hz; + ULONG SclkDpmBoostMargin; + ULONG SclkDpmThrottleMargin; + USHORT SclkDpmTdpLimitPG; + USHORT SclkDpmTdpLimitBoost; + ULONG ulBoostEngineCLock; + UCHAR ulBoostVid_2bit; + UCHAR EnableBoost; + USHORT GnbTdpLimit; + USHORT usMaxLVDSPclkFreqInSingleLink; + UCHAR ucLvdsMisc; + UCHAR ucLVDSReserved; + ULONG ulReserved3[15]; + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo; +}ATOM_INTEGRATED_SYSTEM_INFO_V6; + +// ulGPUCapInfo +#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__TMDSHDMI_COHERENT_SINGLEPLL_MODE 0x01 +#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__DISABLE_AUX_HW_MODE_DETECTION 0x08 + +//ucLVDSMisc: +#define SYS_INFO_LVDSMISC__888_FPDI_MODE 0x01 +#define SYS_INFO_LVDSMISC__DL_CH_SWAP 0x02 +#define SYS_INFO_LVDSMISC__888_BPC 0x04 +#define SYS_INFO_LVDSMISC__OVERRIDE_EN 0x08 +#define SYS_INFO_LVDSMISC__BLON_ACTIVE_LOW 0x10 + +// not used any more +#define SYS_INFO_LVDSMISC__VSYNC_ACTIVE_LOW 0x04 +#define SYS_INFO_LVDSMISC__HSYNC_ACTIVE_LOW 0x08 + +/********************************************************************************************************************** + ATOM_INTEGRATED_SYSTEM_INFO_V6 Description +ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock +ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. +ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. +sDISPCLK_Voltage: Report Display clock voltage requirement. + +ulBootUpReqDisplayVector: VBIOS boot up display IDs, following are supported devices in Liano/Ontaio projects: + ATOM_DEVICE_CRT1_SUPPORT 0x0001 + ATOM_DEVICE_CRT2_SUPPORT 0x0010 + ATOM_DEVICE_DFP1_SUPPORT 0x0008 + ATOM_DEVICE_DFP6_SUPPORT 0x0040 + ATOM_DEVICE_DFP2_SUPPORT 0x0080 + ATOM_DEVICE_DFP3_SUPPORT 0x0200 + ATOM_DEVICE_DFP4_SUPPORT 0x0400 + ATOM_DEVICE_DFP5_SUPPORT 0x0800 + ATOM_DEVICE_LCD1_SUPPORT 0x0002 +ulOtherDisplayMisc: Other display related flags, not defined yet. +ulGPUCapInfo: bit[0]=0: TMDS/HDMI Coherent Mode use cascade PLL mode. + =1: TMDS/HDMI Coherent Mode use signel PLL mode. + bit[3]=0: Enable HW AUX mode detection logic + =1: Disable HW AUX mode dettion logic +ulSB_MMIO_Base_Addr: Physical Base address to SB MMIO space. Driver needs to initialize it for SMU usage. + +usRequestedPWMFreqInHz: When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW). + Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0; + + When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below: + 1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use; + VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result, + Changing BL using VBIOS function is functional in both driver and non-driver present environment; + and enabling VariBri under the driver environment from PP table is optional. + + 2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating + that BL control from GPU is expected. + VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1 + Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but + it's per platform + and enabling VariBri under the driver environment from PP table is optional. + +ucHtcTmpLmt: Refer to D18F3x64 bit[22:16], HtcTmpLmt. + Threshold on value to enter HTC_active state. +ucHtcHystLmt: Refer to D18F3x64 bit[27:24], HtcHystLmt. + To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt. +ulMinEngineClock: Minimum SCLK allowed in 10kHz unit. This is calculated based on WRCK Fuse settings. +ulSystemConfig: Bit[0]=0: PCIE Power Gating Disabled + =1: PCIE Power Gating Enabled + Bit[1]=0: DDR-DLL shut-down feature disabled. + 1: DDR-DLL shut-down feature enabled. + Bit[2]=0: DDR-PLL Power down feature disabled. + 1: DDR-PLL Power down feature enabled. +ulCPUCapInfo: TBD +usNBP0Voltage: VID for voltage on NB P0 State +usNBP1Voltage: VID for voltage on NB P1 State +usBootUpNBVoltage: Voltage Index of GNB voltage configured by SBIOS, which is suffcient to support VBIOS DISPCLK requirement. +usExtDispConnInfoOffset: Offset to sExtDispConnInfo inside the structure +usPanelRefreshRateRange: Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set + to indicate a range. + SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 + SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 + SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 + SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 +ucMemoryType: [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved. +ucUMAChannelNumber: System memory channel numbers. +ulCSR_M3_ARB_CNTL_DEFAULT[10]: Arrays with values for CSR M3 arbiter for default +ulCSR_M3_ARB_CNTL_UVD[10]: Arrays with values for CSR M3 arbiter for UVD playback. +ulCSR_M3_ARB_CNTL_FS3D[10]: Arrays with values for CSR M3 arbiter for Full Screen 3D applications. +sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high +ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. +ulMinimumNClk: Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. +ulIdleNClk: NCLK speed while memory runs in self-refresh state. Unit in 10kHz. +ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns. +ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns. +usPCIEClkSSPercentage: PCIE Clock Spred Spectrum Percentage in unit 0.01%; 100 mean 1%. +usPCIEClkSSType: PCIE Clock Spred Spectrum Type. 0 for Down spread(default); 1 for Center spread. +usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. +usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usHDMISSpreadRateIn10Hz: HDMI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usDVISSPercentage: DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usDVISSpreadRateIn10Hz: DVI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usMaxLVDSPclkFreqInSingleLink: Max pixel clock LVDS panel single link, if=0 means VBIOS use default threhold, right now it is 85Mhz +ucLVDSMisc: [bit0] LVDS 888bit panel mode =0: LVDS 888 panel in LDI mode, =1: LVDS 888 panel in FPDI mode + [bit1] LVDS panel lower and upper link mapping =0: lower link and upper link not swap, =1: lower link and upper link are swapped + [bit2] LVDS 888bit per color mode =0: 666 bit per color =1:888 bit per color + [bit3] LVDS parameter override enable =0: ucLvdsMisc parameter are not used =1: ucLvdsMisc parameter should be used + [bit4] Polarity of signal sent to digital BLON output pin. =0: not inverted(active high) =1: inverted ( active low ) +**********************************************************************************************************************/ + +// this Table is used for Liano/Ontario APU +typedef struct _ATOM_FUSION_SYSTEM_INFO_V1 +{ + ATOM_INTEGRATED_SYSTEM_INFO_V6 sIntegratedSysInfo; + ULONG ulPowerplayTable[128]; +}ATOM_FUSION_SYSTEM_INFO_V1; +/********************************************************************************************************************** + ATOM_FUSION_SYSTEM_INFO_V1 Description +sIntegratedSysInfo: refer to ATOM_INTEGRATED_SYSTEM_INFO_V6 definition. +ulPowerplayTable[128]: This 512 bytes memory is used to save ATOM_PPLIB_POWERPLAYTABLE3, starting form ulPowerplayTable[0] +**********************************************************************************************************************/ + +// this IntegrateSystemInfoTable is used for Trinity APU +typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulBootUpEngineClock; + ULONG ulDentistVCOFreq; + ULONG ulBootUpUMAClock; + ATOM_CLK_VOLT_CAPABILITY sDISPCLK_Voltage[4]; + ULONG ulBootUpReqDisplayVector; + ULONG ulOtherDisplayMisc; + ULONG ulGPUCapInfo; + ULONG ulSB_MMIO_Base_Addr; + USHORT usRequestedPWMFreqInHz; + UCHAR ucHtcTmpLmt; + UCHAR ucHtcHystLmt; + ULONG ulMinEngineClock; + ULONG ulSystemConfig; + ULONG ulCPUCapInfo; + USHORT usNBP0Voltage; + USHORT usNBP1Voltage; + USHORT usBootUpNBVoltage; + USHORT usExtDispConnInfoOffset; + USHORT usPanelRefreshRateRange; + UCHAR ucMemoryType; + UCHAR ucUMAChannelNumber; + UCHAR strVBIOSMsg[40]; + ULONG ulReserved[20]; + ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5]; + ULONG ulGMCRestoreResetTime; + ULONG ulMinimumNClk; + ULONG ulIdleNClk; + ULONG ulDDR_DLL_PowerUpTime; + ULONG ulDDR_PLL_PowerUpTime; + USHORT usPCIEClkSSPercentage; + USHORT usPCIEClkSSType; + USHORT usLvdsSSPercentage; + USHORT usLvdsSSpreadRateIn10Hz; + USHORT usHDMISSPercentage; + USHORT usHDMISSpreadRateIn10Hz; + USHORT usDVISSPercentage; + USHORT usDVISSpreadRateIn10Hz; + ULONG SclkDpmBoostMargin; + ULONG SclkDpmThrottleMargin; + USHORT SclkDpmTdpLimitPG; + USHORT SclkDpmTdpLimitBoost; + ULONG ulBoostEngineCLock; + UCHAR ulBoostVid_2bit; + UCHAR EnableBoost; + USHORT GnbTdpLimit; + USHORT usMaxLVDSPclkFreqInSingleLink; + UCHAR ucLvdsMisc; + UCHAR ucLVDSReserved; + UCHAR ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + UCHAR ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + UCHAR ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + UCHAR ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + UCHAR ucLVDSOffToOnDelay_in4Ms; + UCHAR ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + UCHAR ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + UCHAR ucLVDSReserved1; + ULONG ulLCDBitDepthControlVal; + ULONG ulNbpStateMemclkFreq[4]; + USHORT usNBP2Voltage; + USHORT usNBP3Voltage; + ULONG ulNbpStateNClkFreq[4]; + UCHAR ucNBDPMEnable; + UCHAR ucReserved[3]; + UCHAR ucDPMState0VclkFid; + UCHAR ucDPMState0DclkFid; + UCHAR ucDPMState1VclkFid; + UCHAR ucDPMState1DclkFid; + UCHAR ucDPMState2VclkFid; + UCHAR ucDPMState2DclkFid; + UCHAR ucDPMState3VclkFid; + UCHAR ucDPMState3DclkFid; + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo; +}ATOM_INTEGRATED_SYSTEM_INFO_V1_7; + +// ulOtherDisplayMisc +#define INTEGRATED_SYSTEM_INFO__GET_EDID_CALLBACK_FUNC_SUPPORT 0x01 +#define INTEGRATED_SYSTEM_INFO__GET_BOOTUP_DISPLAY_CALLBACK_FUNC_SUPPORT 0x02 +#define INTEGRATED_SYSTEM_INFO__GET_EXPANSION_CALLBACK_FUNC_SUPPORT 0x04 +#define INTEGRATED_SYSTEM_INFO__FAST_BOOT_SUPPORT 0x08 + +// ulGPUCapInfo +#define SYS_INFO_GPUCAPS__TMDSHDMI_COHERENT_SINGLEPLL_MODE 0x01 +#define SYS_INFO_GPUCAPS__DP_SINGLEPLL_MODE 0x02 +#define SYS_INFO_GPUCAPS__DISABLE_AUX_MODE_DETECT 0x08 + +/********************************************************************************************************************** + ATOM_INTEGRATED_SYSTEM_INFO_V1_7 Description +ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock +ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. +ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. +sDISPCLK_Voltage: Report Display clock voltage requirement. + +ulBootUpReqDisplayVector: VBIOS boot up display IDs, following are supported devices in Trinity projects: + ATOM_DEVICE_CRT1_SUPPORT 0x0001 + ATOM_DEVICE_DFP1_SUPPORT 0x0008 + ATOM_DEVICE_DFP6_SUPPORT 0x0040 + ATOM_DEVICE_DFP2_SUPPORT 0x0080 + ATOM_DEVICE_DFP3_SUPPORT 0x0200 + ATOM_DEVICE_DFP4_SUPPORT 0x0400 + ATOM_DEVICE_DFP5_SUPPORT 0x0800 + ATOM_DEVICE_LCD1_SUPPORT 0x0002 +ulOtherDisplayMisc: bit[0]=0: INT15 callback function Get LCD EDID ( ax=4e08, bl=1b ) is not supported by SBIOS. + =1: INT15 callback function Get LCD EDID ( ax=4e08, bl=1b ) is supported by SBIOS. + bit[1]=0: INT15 callback function Get boot display( ax=4e08, bl=01h) is not supported by SBIOS + =1: INT15 callback function Get boot display( ax=4e08, bl=01h) is supported by SBIOS + bit[2]=0: INT15 callback function Get panel Expansion ( ax=4e08, bl=02h) is not supported by SBIOS + =1: INT15 callback function Get panel Expansion ( ax=4e08, bl=02h) is supported by SBIOS + bit[3]=0: VBIOS fast boot is disable + =1: VBIOS fast boot is enable. ( VBIOS skip display device detection in every set mode if LCD panel is connect and LID is open) +ulGPUCapInfo: bit[0]=0: TMDS/HDMI Coherent Mode use cascade PLL mode. + =1: TMDS/HDMI Coherent Mode use signel PLL mode. + bit[1]=0: DP mode use cascade PLL mode ( New for Trinity ) + =1: DP mode use single PLL mode + bit[3]=0: Enable AUX HW mode detection logic + =1: Disable AUX HW mode detection logic + +ulSB_MMIO_Base_Addr: Physical Base address to SB MMIO space. Driver needs to initialize it for SMU usage. + +usRequestedPWMFreqInHz: When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW). + Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0; + + When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below: + 1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use; + VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result, + Changing BL using VBIOS function is functional in both driver and non-driver present environment; + and enabling VariBri under the driver environment from PP table is optional. + + 2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating + that BL control from GPU is expected. + VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1 + Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but + it's per platform + and enabling VariBri under the driver environment from PP table is optional. + +ucHtcTmpLmt: Refer to D18F3x64 bit[22:16], HtcTmpLmt. + Threshold on value to enter HTC_active state. +ucHtcHystLmt: Refer to D18F3x64 bit[27:24], HtcHystLmt. + To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt. +ulMinEngineClock: Minimum SCLK allowed in 10kHz unit. This is calculated based on WRCK Fuse settings. +ulSystemConfig: Bit[0]=0: PCIE Power Gating Disabled + =1: PCIE Power Gating Enabled + Bit[1]=0: DDR-DLL shut-down feature disabled. + 1: DDR-DLL shut-down feature enabled. + Bit[2]=0: DDR-PLL Power down feature disabled. + 1: DDR-PLL Power down feature enabled. +ulCPUCapInfo: TBD +usNBP0Voltage: VID for voltage on NB P0 State +usNBP1Voltage: VID for voltage on NB P1 State +usNBP2Voltage: VID for voltage on NB P2 State +usNBP3Voltage: VID for voltage on NB P3 State +usBootUpNBVoltage: Voltage Index of GNB voltage configured by SBIOS, which is suffcient to support VBIOS DISPCLK requirement. +usExtDispConnInfoOffset: Offset to sExtDispConnInfo inside the structure +usPanelRefreshRateRange: Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set + to indicate a range. + SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 + SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 + SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 + SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 +ucMemoryType: [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved. +ucUMAChannelNumber: System memory channel numbers. +ulCSR_M3_ARB_CNTL_DEFAULT[10]: Arrays with values for CSR M3 arbiter for default +ulCSR_M3_ARB_CNTL_UVD[10]: Arrays with values for CSR M3 arbiter for UVD playback. +ulCSR_M3_ARB_CNTL_FS3D[10]: Arrays with values for CSR M3 arbiter for Full Screen 3D applications. +sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high +ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. +ulMinimumNClk: Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. +ulIdleNClk: NCLK speed while memory runs in self-refresh state. Unit in 10kHz. +ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns. +ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns. +usPCIEClkSSPercentage: PCIE Clock Spread Spectrum Percentage in unit 0.01%; 100 mean 1%. +usPCIEClkSSType: PCIE Clock Spread Spectrum Type. 0 for Down spread(default); 1 for Center spread. +usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. +usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usHDMISSpreadRateIn10Hz: HDMI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usDVISSPercentage: DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usDVISSpreadRateIn10Hz: DVI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usMaxLVDSPclkFreqInSingleLink: Max pixel clock LVDS panel single link, if=0 means VBIOS use default threhold, right now it is 85Mhz +ucLVDSMisc: [bit0] LVDS 888bit panel mode =0: LVDS 888 panel in LDI mode, =1: LVDS 888 panel in FPDI mode + [bit1] LVDS panel lower and upper link mapping =0: lower link and upper link not swap, =1: lower link and upper link are swapped + [bit2] LVDS 888bit per color mode =0: 666 bit per color =1:888 bit per color + [bit3] LVDS parameter override enable =0: ucLvdsMisc parameter are not used =1: ucLvdsMisc parameter should be used + [bit4] Polarity of signal sent to digital BLON output pin. =0: not inverted(active high) =1: inverted ( active low ) +ucLVDSPwrOnSeqDIGONtoDE_in4Ms: LVDS power up sequence time in unit of 4ms, time delay from DIGON signal active to data enable signal active( DE ). + =0 mean use VBIOS default which is 8 ( 32ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON. + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucLVDSPwrOnDEtoVARY_BL_in4Ms: LVDS power up sequence time in unit of 4ms., time delay from DE( data enable ) active to Vary Brightness enable signal active( VARY_BL ). + =0 mean use VBIOS default which is 90 ( 360ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON. + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ucLVDSPwrOffVARY_BLtoDE_in4Ms: LVDS power down sequence time in unit of 4ms, time delay from data enable ( DE ) signal off to LCDVCC (DIGON) off. + =0 mean use VBIOS default delay which is 8 ( 32ms ). The LVDS power down sequence is as following: BLON->VARY_BL->DE->DIGON + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ucLVDSPwrOffDEtoDIGON_in4Ms: LVDS power down sequence time in unit of 4ms, time delay from vary brightness enable signal( VARY_BL) off to data enable ( DE ) signal off. + =0 mean use VBIOS default which is 90 ( 360ms ). The LVDS power down sequence is as following: BLON->VARY_BL->DE->DIGON + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ucLVDSOffToOnDelay_in4Ms: LVDS power down sequence time in unit of 4ms. Time delay from DIGON signal off to DIGON signal active. + =0 means to use VBIOS default delay which is 125 ( 500ms ). + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ucLVDSPwrOnVARY_BLtoBLON_in4Ms: LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active. + =0 means to use VBIOS default delay which is 0 ( 0ms ). + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ucLVDSPwrOffBLONtoVARY_BL_in4Ms: LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off. + =0 means to use VBIOS default delay which is 0 ( 0ms ). + This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ulNbpStateMemclkFreq[4]: system memory clock frequncey in unit of 10Khz in different NB pstate. + +**********************************************************************************************************************/ + +/**************************************************************************/ +// This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design +//Memory SS Info Table +//Define Memory Clock SS chip ID +#define ICS91719 1 +#define ICS91720 2 + +//Define one structure to inform SW a "block of data" writing to external SS chip via I2C protocol +typedef struct _ATOM_I2C_DATA_RECORD +{ + UCHAR ucNunberOfBytes; //Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop" + UCHAR ucI2CData[1]; //I2C data in bytes, should be less than 16 bytes usually +}ATOM_I2C_DATA_RECORD; + + +//Define one structure to inform SW how many blocks of data writing to external SS chip via I2C protocol, in addition to other information +typedef struct _ATOM_I2C_DEVICE_SETUP_INFO +{ + ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; //I2C line and HW/SW assisted cap. + UCHAR ucSSChipID; //SS chip being used + UCHAR ucSSChipSlaveAddr; //Slave Address to set up this SS chip + UCHAR ucNumOfI2CDataRecords; //number of data block + ATOM_I2C_DATA_RECORD asI2CData[1]; +}ATOM_I2C_DEVICE_SETUP_INFO; + +//========================================================================================== +typedef struct _ATOM_ASIC_MVDD_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1]; +}ATOM_ASIC_MVDD_INFO; + +//========================================================================================== +#define ATOM_MCLK_SS_INFO ATOM_ASIC_MVDD_INFO + +//========================================================================================== +/**************************************************************************/ + +typedef struct _ATOM_ASIC_SS_ASSIGNMENT +{ + ULONG ulTargetClockRange; //Clock Out frequence (VCO ), in unit of 10Khz + USHORT usSpreadSpectrumPercentage; //in unit of 0.01% + USHORT usSpreadRateInKhz; //in unit of kHz, modulation freq + UCHAR ucClockIndication; //Indicate which clock source needs SS + UCHAR ucSpreadSpectrumMode; //Bit1=0 Down Spread,=1 Center Spread. + UCHAR ucReserved[2]; +}ATOM_ASIC_SS_ASSIGNMENT; + +//Define ucClockIndication, SW uses the IDs below to search if the SS is required/enabled on a clock branch/signal type. +//SS is not required or enabled if a match is not found. +#define ASIC_INTERNAL_MEMORY_SS 1 +#define ASIC_INTERNAL_ENGINE_SS 2 +#define ASIC_INTERNAL_UVD_SS 3 +#define ASIC_INTERNAL_SS_ON_TMDS 4 +#define ASIC_INTERNAL_SS_ON_HDMI 5 +#define ASIC_INTERNAL_SS_ON_LVDS 6 +#define ASIC_INTERNAL_SS_ON_DP 7 +#define ASIC_INTERNAL_SS_ON_DCPLL 8 +#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9 +#define ASIC_INTERNAL_VCE_SS 10 + +typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2 +{ + ULONG ulTargetClockRange; //For mem/engine/uvd, Clock Out frequence (VCO ), in unit of 10Khz + //For TMDS/HDMI/LVDS, it is pixel clock , for DP, it is link clock ( 27000 or 16200 ) + USHORT usSpreadSpectrumPercentage; //in unit of 0.01% + USHORT usSpreadRateIn10Hz; //in unit of 10Hz, modulation freq + UCHAR ucClockIndication; //Indicate which clock source needs SS + UCHAR ucSpreadSpectrumMode; //Bit0=0 Down Spread,=1 Center Spread, bit1=0: internal SS bit1=1: external SS + UCHAR ucReserved[2]; +}ATOM_ASIC_SS_ASSIGNMENT_V2; + +//ucSpreadSpectrumMode +//#define ATOM_SS_DOWN_SPREAD_MODE_MASK 0x00000000 +//#define ATOM_SS_DOWN_SPREAD_MODE 0x00000000 +//#define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 +//#define ATOM_SS_CENTRE_SPREAD_MODE 0x00000001 +//#define ATOM_INTERNAL_SS_MASK 0x00000000 +//#define ATOM_EXTERNAL_SS_MASK 0x00000002 + +typedef struct _ATOM_ASIC_INTERNAL_SS_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_ASIC_SS_ASSIGNMENT asSpreadSpectrum[4]; +}ATOM_ASIC_INTERNAL_SS_INFO; + +typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_ASIC_SS_ASSIGNMENT_V2 asSpreadSpectrum[1]; //this is point only. +}ATOM_ASIC_INTERNAL_SS_INFO_V2; + +typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3 +{ + ULONG ulTargetClockRange; //For mem/engine/uvd, Clock Out frequence (VCO ), in unit of 10Khz + //For TMDS/HDMI/LVDS, it is pixel clock , for DP, it is link clock ( 27000 or 16200 ) + USHORT usSpreadSpectrumPercentage; //in unit of 0.01% + USHORT usSpreadRateIn10Hz; //in unit of 10Hz, modulation freq + UCHAR ucClockIndication; //Indicate which clock source needs SS + UCHAR ucSpreadSpectrumMode; //Bit0=0 Down Spread,=1 Center Spread, bit1=0: internal SS bit1=1: external SS + UCHAR ucReserved[2]; +}ATOM_ASIC_SS_ASSIGNMENT_V3; + +typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_ASIC_SS_ASSIGNMENT_V3 asSpreadSpectrum[1]; //this is pointer only. +}ATOM_ASIC_INTERNAL_SS_INFO_V3; + + +//==============================Scratch Pad Definition Portion=============================== +#define ATOM_DEVICE_CONNECT_INFO_DEF 0 +#define ATOM_ROM_LOCATION_DEF 1 +#define ATOM_TV_STANDARD_DEF 2 +#define ATOM_ACTIVE_INFO_DEF 3 +#define ATOM_LCD_INFO_DEF 4 +#define ATOM_DOS_REQ_INFO_DEF 5 +#define ATOM_ACC_CHANGE_INFO_DEF 6 +#define ATOM_DOS_MODE_INFO_DEF 7 +#define ATOM_I2C_CHANNEL_STATUS_DEF 8 +#define ATOM_I2C_CHANNEL_STATUS1_DEF 9 +#define ATOM_INTERNAL_TIMER_DEF 10 + +// BIOS_0_SCRATCH Definition +#define ATOM_S0_CRT1_MONO 0x00000001L +#define ATOM_S0_CRT1_COLOR 0x00000002L +#define ATOM_S0_CRT1_MASK (ATOM_S0_CRT1_MONO+ATOM_S0_CRT1_COLOR) + +#define ATOM_S0_TV1_COMPOSITE_A 0x00000004L +#define ATOM_S0_TV1_SVIDEO_A 0x00000008L +#define ATOM_S0_TV1_MASK_A (ATOM_S0_TV1_COMPOSITE_A+ATOM_S0_TV1_SVIDEO_A) + +#define ATOM_S0_CV_A 0x00000010L +#define ATOM_S0_CV_DIN_A 0x00000020L +#define ATOM_S0_CV_MASK_A (ATOM_S0_CV_A+ATOM_S0_CV_DIN_A) + + +#define ATOM_S0_CRT2_MONO 0x00000100L +#define ATOM_S0_CRT2_COLOR 0x00000200L +#define ATOM_S0_CRT2_MASK (ATOM_S0_CRT2_MONO+ATOM_S0_CRT2_COLOR) + +#define ATOM_S0_TV1_COMPOSITE 0x00000400L +#define ATOM_S0_TV1_SVIDEO 0x00000800L +#define ATOM_S0_TV1_SCART 0x00004000L +#define ATOM_S0_TV1_MASK (ATOM_S0_TV1_COMPOSITE+ATOM_S0_TV1_SVIDEO+ATOM_S0_TV1_SCART) + +#define ATOM_S0_CV 0x00001000L +#define ATOM_S0_CV_DIN 0x00002000L +#define ATOM_S0_CV_MASK (ATOM_S0_CV+ATOM_S0_CV_DIN) + +#define ATOM_S0_DFP1 0x00010000L +#define ATOM_S0_DFP2 0x00020000L +#define ATOM_S0_LCD1 0x00040000L +#define ATOM_S0_LCD2 0x00080000L +#define ATOM_S0_DFP6 0x00100000L +#define ATOM_S0_DFP3 0x00200000L +#define ATOM_S0_DFP4 0x00400000L +#define ATOM_S0_DFP5 0x00800000L + +#define ATOM_S0_DFP_MASK ATOM_S0_DFP1 | ATOM_S0_DFP2 | ATOM_S0_DFP3 | ATOM_S0_DFP4 | ATOM_S0_DFP5 | ATOM_S0_DFP6 + +#define ATOM_S0_FAD_REGISTER_BUG 0x02000000L // If set, indicates we are running a PCIE asic with + // the FAD/HDP reg access bug. Bit is read by DAL, this is obsolete from RV5xx + +#define ATOM_S0_THERMAL_STATE_MASK 0x1C000000L +#define ATOM_S0_THERMAL_STATE_SHIFT 26 + +#define ATOM_S0_SYSTEM_POWER_STATE_MASK 0xE0000000L +#define ATOM_S0_SYSTEM_POWER_STATE_SHIFT 29 + +#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC 1 +#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC 2 +#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3 +#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LIT2AC 4 + +//Byte aligned definition for BIOS usage +#define ATOM_S0_CRT1_MONOb0 0x01 +#define ATOM_S0_CRT1_COLORb0 0x02 +#define ATOM_S0_CRT1_MASKb0 (ATOM_S0_CRT1_MONOb0+ATOM_S0_CRT1_COLORb0) + +#define ATOM_S0_TV1_COMPOSITEb0 0x04 +#define ATOM_S0_TV1_SVIDEOb0 0x08 +#define ATOM_S0_TV1_MASKb0 (ATOM_S0_TV1_COMPOSITEb0+ATOM_S0_TV1_SVIDEOb0) + +#define ATOM_S0_CVb0 0x10 +#define ATOM_S0_CV_DINb0 0x20 +#define ATOM_S0_CV_MASKb0 (ATOM_S0_CVb0+ATOM_S0_CV_DINb0) + +#define ATOM_S0_CRT2_MONOb1 0x01 +#define ATOM_S0_CRT2_COLORb1 0x02 +#define ATOM_S0_CRT2_MASKb1 (ATOM_S0_CRT2_MONOb1+ATOM_S0_CRT2_COLORb1) + +#define ATOM_S0_TV1_COMPOSITEb1 0x04 +#define ATOM_S0_TV1_SVIDEOb1 0x08 +#define ATOM_S0_TV1_SCARTb1 0x40 +#define ATOM_S0_TV1_MASKb1 (ATOM_S0_TV1_COMPOSITEb1+ATOM_S0_TV1_SVIDEOb1+ATOM_S0_TV1_SCARTb1) + +#define ATOM_S0_CVb1 0x10 +#define ATOM_S0_CV_DINb1 0x20 +#define ATOM_S0_CV_MASKb1 (ATOM_S0_CVb1+ATOM_S0_CV_DINb1) + +#define ATOM_S0_DFP1b2 0x01 +#define ATOM_S0_DFP2b2 0x02 +#define ATOM_S0_LCD1b2 0x04 +#define ATOM_S0_LCD2b2 0x08 +#define ATOM_S0_DFP6b2 0x10 +#define ATOM_S0_DFP3b2 0x20 +#define ATOM_S0_DFP4b2 0x40 +#define ATOM_S0_DFP5b2 0x80 + + +#define ATOM_S0_THERMAL_STATE_MASKb3 0x1C +#define ATOM_S0_THERMAL_STATE_SHIFTb3 2 + +#define ATOM_S0_SYSTEM_POWER_STATE_MASKb3 0xE0 +#define ATOM_S0_LCD1_SHIFT 18 + +// BIOS_1_SCRATCH Definition +#define ATOM_S1_ROM_LOCATION_MASK 0x0000FFFFL +#define ATOM_S1_PCI_BUS_DEV_MASK 0xFFFF0000L + +// BIOS_2_SCRATCH Definition +#define ATOM_S2_TV1_STANDARD_MASK 0x0000000FL +#define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L +#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8 + +#define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK 0x0C000000L +#define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK_SHIFT 26 +#define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGE 0x10000000L + +#define ATOM_S2_DEVICE_DPMS_STATE 0x00010000L +#define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L + +#define ATOM_S2_DISPLAY_ROTATION_0_DEGREE 0x0 +#define ATOM_S2_DISPLAY_ROTATION_90_DEGREE 0x1 +#define ATOM_S2_DISPLAY_ROTATION_180_DEGREE 0x2 +#define ATOM_S2_DISPLAY_ROTATION_270_DEGREE 0x3 +#define ATOM_S2_DISPLAY_ROTATION_DEGREE_SHIFT 30 +#define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK 0xC0000000L + + +//Byte aligned definition for BIOS usage +#define ATOM_S2_TV1_STANDARD_MASKb0 0x0F +#define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF +#define ATOM_S2_DEVICE_DPMS_STATEb2 0x01 + +#define ATOM_S2_DEVICE_DPMS_MASKw1 0x3FF +#define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASKb3 0x0C +#define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGEb3 0x10 +#define ATOM_S2_TMDS_COHERENT_MODEb3 0x10 // used by VBIOS code only, use coherent mode for TMDS/HDMI mode +#define ATOM_S2_VRI_BRIGHT_ENABLEb3 0x20 +#define ATOM_S2_ROTATION_STATE_MASKb3 0xC0 + + +// BIOS_3_SCRATCH Definition +#define ATOM_S3_CRT1_ACTIVE 0x00000001L +#define ATOM_S3_LCD1_ACTIVE 0x00000002L +#define ATOM_S3_TV1_ACTIVE 0x00000004L +#define ATOM_S3_DFP1_ACTIVE 0x00000008L +#define ATOM_S3_CRT2_ACTIVE 0x00000010L +#define ATOM_S3_LCD2_ACTIVE 0x00000020L +#define ATOM_S3_DFP6_ACTIVE 0x00000040L +#define ATOM_S3_DFP2_ACTIVE 0x00000080L +#define ATOM_S3_CV_ACTIVE 0x00000100L +#define ATOM_S3_DFP3_ACTIVE 0x00000200L +#define ATOM_S3_DFP4_ACTIVE 0x00000400L +#define ATOM_S3_DFP5_ACTIVE 0x00000800L + +#define ATOM_S3_DEVICE_ACTIVE_MASK 0x00000FFFL + +#define ATOM_S3_LCD_FULLEXPANSION_ACTIVE 0x00001000L +#define ATOM_S3_LCD_EXPANSION_ASPEC_RATIO_ACTIVE 0x00002000L + +#define ATOM_S3_CRT1_CRTC_ACTIVE 0x00010000L +#define ATOM_S3_LCD1_CRTC_ACTIVE 0x00020000L +#define ATOM_S3_TV1_CRTC_ACTIVE 0x00040000L +#define ATOM_S3_DFP1_CRTC_ACTIVE 0x00080000L +#define ATOM_S3_CRT2_CRTC_ACTIVE 0x00100000L +#define ATOM_S3_LCD2_CRTC_ACTIVE 0x00200000L +#define ATOM_S3_DFP6_CRTC_ACTIVE 0x00400000L +#define ATOM_S3_DFP2_CRTC_ACTIVE 0x00800000L +#define ATOM_S3_CV_CRTC_ACTIVE 0x01000000L +#define ATOM_S3_DFP3_CRTC_ACTIVE 0x02000000L +#define ATOM_S3_DFP4_CRTC_ACTIVE 0x04000000L +#define ATOM_S3_DFP5_CRTC_ACTIVE 0x08000000L + +#define ATOM_S3_DEVICE_CRTC_ACTIVE_MASK 0x0FFF0000L +#define ATOM_S3_ASIC_GUI_ENGINE_HUNG 0x20000000L +//Below two definitions are not supported in pplib, but in the old powerplay in DAL +#define ATOM_S3_ALLOW_FAST_PWR_SWITCH 0x40000000L +#define ATOM_S3_RQST_GPU_USE_MIN_PWR 0x80000000L + +//Byte aligned definition for BIOS usage +#define ATOM_S3_CRT1_ACTIVEb0 0x01 +#define ATOM_S3_LCD1_ACTIVEb0 0x02 +#define ATOM_S3_TV1_ACTIVEb0 0x04 +#define ATOM_S3_DFP1_ACTIVEb0 0x08 +#define ATOM_S3_CRT2_ACTIVEb0 0x10 +#define ATOM_S3_LCD2_ACTIVEb0 0x20 +#define ATOM_S3_DFP6_ACTIVEb0 0x40 +#define ATOM_S3_DFP2_ACTIVEb0 0x80 +#define ATOM_S3_CV_ACTIVEb1 0x01 +#define ATOM_S3_DFP3_ACTIVEb1 0x02 +#define ATOM_S3_DFP4_ACTIVEb1 0x04 +#define ATOM_S3_DFP5_ACTIVEb1 0x08 + +#define ATOM_S3_ACTIVE_CRTC1w0 0xFFF + +#define ATOM_S3_CRT1_CRTC_ACTIVEb2 0x01 +#define ATOM_S3_LCD1_CRTC_ACTIVEb2 0x02 +#define ATOM_S3_TV1_CRTC_ACTIVEb2 0x04 +#define ATOM_S3_DFP1_CRTC_ACTIVEb2 0x08 +#define ATOM_S3_CRT2_CRTC_ACTIVEb2 0x10 +#define ATOM_S3_LCD2_CRTC_ACTIVEb2 0x20 +#define ATOM_S3_DFP6_CRTC_ACTIVEb2 0x40 +#define ATOM_S3_DFP2_CRTC_ACTIVEb2 0x80 +#define ATOM_S3_CV_CRTC_ACTIVEb3 0x01 +#define ATOM_S3_DFP3_CRTC_ACTIVEb3 0x02 +#define ATOM_S3_DFP4_CRTC_ACTIVEb3 0x04 +#define ATOM_S3_DFP5_CRTC_ACTIVEb3 0x08 + +#define ATOM_S3_ACTIVE_CRTC2w1 0xFFF + +// BIOS_4_SCRATCH Definition +#define ATOM_S4_LCD1_PANEL_ID_MASK 0x000000FFL +#define ATOM_S4_LCD1_REFRESH_MASK 0x0000FF00L +#define ATOM_S4_LCD1_REFRESH_SHIFT 8 + +//Byte aligned definition for BIOS usage +#define ATOM_S4_LCD1_PANEL_ID_MASKb0 0x0FF +#define ATOM_S4_LCD1_REFRESH_MASKb1 ATOM_S4_LCD1_PANEL_ID_MASKb0 +#define ATOM_S4_VRAM_INFO_MASKb2 ATOM_S4_LCD1_PANEL_ID_MASKb0 + +// BIOS_5_SCRATCH Definition, BIOS_5_SCRATCH is used by Firmware only !!!! +#define ATOM_S5_DOS_REQ_CRT1b0 0x01 +#define ATOM_S5_DOS_REQ_LCD1b0 0x02 +#define ATOM_S5_DOS_REQ_TV1b0 0x04 +#define ATOM_S5_DOS_REQ_DFP1b0 0x08 +#define ATOM_S5_DOS_REQ_CRT2b0 0x10 +#define ATOM_S5_DOS_REQ_LCD2b0 0x20 +#define ATOM_S5_DOS_REQ_DFP6b0 0x40 +#define ATOM_S5_DOS_REQ_DFP2b0 0x80 +#define ATOM_S5_DOS_REQ_CVb1 0x01 +#define ATOM_S5_DOS_REQ_DFP3b1 0x02 +#define ATOM_S5_DOS_REQ_DFP4b1 0x04 +#define ATOM_S5_DOS_REQ_DFP5b1 0x08 + +#define ATOM_S5_DOS_REQ_DEVICEw0 0x0FFF + +#define ATOM_S5_DOS_REQ_CRT1 0x0001 +#define ATOM_S5_DOS_REQ_LCD1 0x0002 +#define ATOM_S5_DOS_REQ_TV1 0x0004 +#define ATOM_S5_DOS_REQ_DFP1 0x0008 +#define ATOM_S5_DOS_REQ_CRT2 0x0010 +#define ATOM_S5_DOS_REQ_LCD2 0x0020 +#define ATOM_S5_DOS_REQ_DFP6 0x0040 +#define ATOM_S5_DOS_REQ_DFP2 0x0080 +#define ATOM_S5_DOS_REQ_CV 0x0100 +#define ATOM_S5_DOS_REQ_DFP3 0x0200 +#define ATOM_S5_DOS_REQ_DFP4 0x0400 +#define ATOM_S5_DOS_REQ_DFP5 0x0800 + +#define ATOM_S5_DOS_FORCE_CRT1b2 ATOM_S5_DOS_REQ_CRT1b0 +#define ATOM_S5_DOS_FORCE_TV1b2 ATOM_S5_DOS_REQ_TV1b0 +#define ATOM_S5_DOS_FORCE_CRT2b2 ATOM_S5_DOS_REQ_CRT2b0 +#define ATOM_S5_DOS_FORCE_CVb3 ATOM_S5_DOS_REQ_CVb1 +#define ATOM_S5_DOS_FORCE_DEVICEw1 (ATOM_S5_DOS_FORCE_CRT1b2+ATOM_S5_DOS_FORCE_TV1b2+ATOM_S5_DOS_FORCE_CRT2b2+\ + (ATOM_S5_DOS_FORCE_CVb3<<8)) + +// BIOS_6_SCRATCH Definition +#define ATOM_S6_DEVICE_CHANGE 0x00000001L +#define ATOM_S6_SCALER_CHANGE 0x00000002L +#define ATOM_S6_LID_CHANGE 0x00000004L +#define ATOM_S6_DOCKING_CHANGE 0x00000008L +#define ATOM_S6_ACC_MODE 0x00000010L +#define ATOM_S6_EXT_DESKTOP_MODE 0x00000020L +#define ATOM_S6_LID_STATE 0x00000040L +#define ATOM_S6_DOCK_STATE 0x00000080L +#define ATOM_S6_CRITICAL_STATE 0x00000100L +#define ATOM_S6_HW_I2C_BUSY_STATE 0x00000200L +#define ATOM_S6_THERMAL_STATE_CHANGE 0x00000400L +#define ATOM_S6_INTERRUPT_SET_BY_BIOS 0x00000800L +#define ATOM_S6_REQ_LCD_EXPANSION_FULL 0x00001000L //Normal expansion Request bit for LCD +#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO 0x00002000L //Aspect ratio expansion Request bit for LCD + +#define ATOM_S6_DISPLAY_STATE_CHANGE 0x00004000L //This bit is recycled when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_H_expansion +#define ATOM_S6_I2C_STATE_CHANGE 0x00008000L //This bit is recycled,when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_V_expansion + +#define ATOM_S6_ACC_REQ_CRT1 0x00010000L +#define ATOM_S6_ACC_REQ_LCD1 0x00020000L +#define ATOM_S6_ACC_REQ_TV1 0x00040000L +#define ATOM_S6_ACC_REQ_DFP1 0x00080000L +#define ATOM_S6_ACC_REQ_CRT2 0x00100000L +#define ATOM_S6_ACC_REQ_LCD2 0x00200000L +#define ATOM_S6_ACC_REQ_DFP6 0x00400000L +#define ATOM_S6_ACC_REQ_DFP2 0x00800000L +#define ATOM_S6_ACC_REQ_CV 0x01000000L +#define ATOM_S6_ACC_REQ_DFP3 0x02000000L +#define ATOM_S6_ACC_REQ_DFP4 0x04000000L +#define ATOM_S6_ACC_REQ_DFP5 0x08000000L + +#define ATOM_S6_ACC_REQ_MASK 0x0FFF0000L +#define ATOM_S6_SYSTEM_POWER_MODE_CHANGE 0x10000000L +#define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH 0x20000000L +#define ATOM_S6_VRI_BRIGHTNESS_CHANGE 0x40000000L +#define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK 0x80000000L + +//Byte aligned definition for BIOS usage +#define ATOM_S6_DEVICE_CHANGEb0 0x01 +#define ATOM_S6_SCALER_CHANGEb0 0x02 +#define ATOM_S6_LID_CHANGEb0 0x04 +#define ATOM_S6_DOCKING_CHANGEb0 0x08 +#define ATOM_S6_ACC_MODEb0 0x10 +#define ATOM_S6_EXT_DESKTOP_MODEb0 0x20 +#define ATOM_S6_LID_STATEb0 0x40 +#define ATOM_S6_DOCK_STATEb0 0x80 +#define ATOM_S6_CRITICAL_STATEb1 0x01 +#define ATOM_S6_HW_I2C_BUSY_STATEb1 0x02 +#define ATOM_S6_THERMAL_STATE_CHANGEb1 0x04 +#define ATOM_S6_INTERRUPT_SET_BY_BIOSb1 0x08 +#define ATOM_S6_REQ_LCD_EXPANSION_FULLb1 0x10 +#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIOb1 0x20 + +#define ATOM_S6_ACC_REQ_CRT1b2 0x01 +#define ATOM_S6_ACC_REQ_LCD1b2 0x02 +#define ATOM_S6_ACC_REQ_TV1b2 0x04 +#define ATOM_S6_ACC_REQ_DFP1b2 0x08 +#define ATOM_S6_ACC_REQ_CRT2b2 0x10 +#define ATOM_S6_ACC_REQ_LCD2b2 0x20 +#define ATOM_S6_ACC_REQ_DFP6b2 0x40 +#define ATOM_S6_ACC_REQ_DFP2b2 0x80 +#define ATOM_S6_ACC_REQ_CVb3 0x01 +#define ATOM_S6_ACC_REQ_DFP3b3 0x02 +#define ATOM_S6_ACC_REQ_DFP4b3 0x04 +#define ATOM_S6_ACC_REQ_DFP5b3 0x08 + +#define ATOM_S6_ACC_REQ_DEVICEw1 ATOM_S5_DOS_REQ_DEVICEw0 +#define ATOM_S6_SYSTEM_POWER_MODE_CHANGEb3 0x10 +#define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCHb3 0x20 +#define ATOM_S6_VRI_BRIGHTNESS_CHANGEb3 0x40 +#define ATOM_S6_CONFIG_DISPLAY_CHANGEb3 0x80 + +#define ATOM_S6_DEVICE_CHANGE_SHIFT 0 +#define ATOM_S6_SCALER_CHANGE_SHIFT 1 +#define ATOM_S6_LID_CHANGE_SHIFT 2 +#define ATOM_S6_DOCKING_CHANGE_SHIFT 3 +#define ATOM_S6_ACC_MODE_SHIFT 4 +#define ATOM_S6_EXT_DESKTOP_MODE_SHIFT 5 +#define ATOM_S6_LID_STATE_SHIFT 6 +#define ATOM_S6_DOCK_STATE_SHIFT 7 +#define ATOM_S6_CRITICAL_STATE_SHIFT 8 +#define ATOM_S6_HW_I2C_BUSY_STATE_SHIFT 9 +#define ATOM_S6_THERMAL_STATE_CHANGE_SHIFT 10 +#define ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT 11 +#define ATOM_S6_REQ_SCALER_SHIFT 12 +#define ATOM_S6_REQ_SCALER_ARATIO_SHIFT 13 +#define ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT 14 +#define ATOM_S6_I2C_STATE_CHANGE_SHIFT 15 +#define ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT 28 +#define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH_SHIFT 29 +#define ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT 30 +#define ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT 31 + +// BIOS_7_SCRATCH Definition, BIOS_7_SCRATCH is used by Firmware only !!!! +#define ATOM_S7_DOS_MODE_TYPEb0 0x03 +#define ATOM_S7_DOS_MODE_VGAb0 0x00 +#define ATOM_S7_DOS_MODE_VESAb0 0x01 +#define ATOM_S7_DOS_MODE_EXTb0 0x02 +#define ATOM_S7_DOS_MODE_PIXEL_DEPTHb0 0x0C +#define ATOM_S7_DOS_MODE_PIXEL_FORMATb0 0xF0 +#define ATOM_S7_DOS_8BIT_DAC_ENb1 0x01 +#define ATOM_S7_DOS_MODE_NUMBERw1 0x0FFFF + +#define ATOM_S7_DOS_8BIT_DAC_EN_SHIFT 8 + +// BIOS_8_SCRATCH Definition +#define ATOM_S8_I2C_CHANNEL_BUSY_MASK 0x00000FFFF +#define ATOM_S8_I2C_HW_ENGINE_BUSY_MASK 0x0FFFF0000 + +#define ATOM_S8_I2C_CHANNEL_BUSY_SHIFT 0 +#define ATOM_S8_I2C_ENGINE_BUSY_SHIFT 16 + +// BIOS_9_SCRATCH Definition +#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_MASK +#define ATOM_S9_I2C_CHANNEL_COMPLETED_MASK 0x0000FFFF +#endif +#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_MASK +#define ATOM_S9_I2C_CHANNEL_ABORTED_MASK 0xFFFF0000 +#endif +#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT +#define ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT 0 +#endif +#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT +#define ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT 16 +#endif + + +#define ATOM_FLAG_SET 0x20 +#define ATOM_FLAG_CLEAR 0 +#define CLEAR_ATOM_S6_ACC_MODE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_ACC_MODE_SHIFT | ATOM_FLAG_CLEAR) +#define SET_ATOM_S6_DEVICE_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DEVICE_CHANGE_SHIFT | ATOM_FLAG_SET) +#define SET_ATOM_S6_VRI_BRIGHTNESS_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT | ATOM_FLAG_SET) +#define SET_ATOM_S6_SCALER_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_SCALER_CHANGE_SHIFT | ATOM_FLAG_SET) +#define SET_ATOM_S6_LID_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_LID_CHANGE_SHIFT | ATOM_FLAG_SET) + +#define SET_ATOM_S6_LID_STATE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_SET) +#define CLEAR_ATOM_S6_LID_STATE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_CLEAR) + +#define SET_ATOM_S6_DOCK_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DOCKING_CHANGE_SHIFT | ATOM_FLAG_SET) +#define SET_ATOM_S6_DOCK_STATE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_SET) +#define CLEAR_ATOM_S6_DOCK_STATE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_CLEAR) + +#define SET_ATOM_S6_THERMAL_STATE_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_THERMAL_STATE_CHANGE_SHIFT | ATOM_FLAG_SET) +#define SET_ATOM_S6_SYSTEM_POWER_MODE_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT | ATOM_FLAG_SET) +#define SET_ATOM_S6_INTERRUPT_SET_BY_BIOS ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT | ATOM_FLAG_SET) + +#define SET_ATOM_S6_CRITICAL_STATE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_SET) +#define CLEAR_ATOM_S6_CRITICAL_STATE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_CLEAR) + +#define SET_ATOM_S6_REQ_SCALER ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_SET) +#define CLEAR_ATOM_S6_REQ_SCALER ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_CLEAR ) + +#define SET_ATOM_S6_REQ_SCALER_ARATIO ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_SET ) +#define CLEAR_ATOM_S6_REQ_SCALER_ARATIO ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_CLEAR ) + +#define SET_ATOM_S6_I2C_STATE_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_I2C_STATE_CHANGE_SHIFT | ATOM_FLAG_SET ) + +#define SET_ATOM_S6_DISPLAY_STATE_CHANGE ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT | ATOM_FLAG_SET ) + +#define SET_ATOM_S6_DEVICE_RECONFIG ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT | ATOM_FLAG_SET) +#define CLEAR_ATOM_S0_LCD1 ((ATOM_DEVICE_CONNECT_INFO_DEF << 8 )| ATOM_S0_LCD1_SHIFT | ATOM_FLAG_CLEAR ) +#define SET_ATOM_S7_DOS_8BIT_DAC_EN ((ATOM_DOS_MODE_INFO_DEF << 8 )|ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_SET ) +#define CLEAR_ATOM_S7_DOS_8BIT_DAC_EN ((ATOM_DOS_MODE_INFO_DEF << 8 )|ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_CLEAR ) + +/****************************************************************************/ +//Portion II: Definitinos only used in Driver +/****************************************************************************/ + +// Macros used by driver +#ifdef __cplusplus +#define GetIndexIntoMasterTable(MasterOrData, FieldName) ((reinterpret_cast(&(static_cast(0))->FieldName)-static_cast(0))/sizeof(USHORT)) + +#define GET_COMMAND_TABLE_COMMANDSET_REVISION(TABLE_HEADER_OFFSET) (((static_cast(TABLE_HEADER_OFFSET))->ucTableFormatRevision )&0x3F) +#define GET_COMMAND_TABLE_PARAMETER_REVISION(TABLE_HEADER_OFFSET) (((static_cast(TABLE_HEADER_OFFSET))->ucTableContentRevision)&0x3F) +#else // not __cplusplus +#define GetIndexIntoMasterTable(MasterOrData, FieldName) (((char*)(&((ATOM_MASTER_LIST_OF_##MasterOrData##_TABLES*)0)->FieldName)-(char*)0)/sizeof(USHORT)) + +#define GET_COMMAND_TABLE_COMMANDSET_REVISION(TABLE_HEADER_OFFSET) ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableFormatRevision)&0x3F) +#define GET_COMMAND_TABLE_PARAMETER_REVISION(TABLE_HEADER_OFFSET) ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableContentRevision)&0x3F) +#endif // __cplusplus + +#define GET_DATA_TABLE_MAJOR_REVISION GET_COMMAND_TABLE_COMMANDSET_REVISION +#define GET_DATA_TABLE_MINOR_REVISION GET_COMMAND_TABLE_PARAMETER_REVISION + +/****************************************************************************/ +//Portion III: Definitinos only used in VBIOS +/****************************************************************************/ +#define ATOM_DAC_SRC 0x80 +#define ATOM_SRC_DAC1 0 +#define ATOM_SRC_DAC2 0x80 + +typedef struct _MEMORY_PLLINIT_PARAMETERS +{ + ULONG ulTargetMemoryClock; //In 10Khz unit + UCHAR ucAction; //not define yet + UCHAR ucFbDiv_Hi; //Fbdiv Hi byte + UCHAR ucFbDiv; //FB value + UCHAR ucPostDiv; //Post div +}MEMORY_PLLINIT_PARAMETERS; + +#define MEMORY_PLLINIT_PS_ALLOCATION MEMORY_PLLINIT_PARAMETERS + + +#define GPIO_PIN_WRITE 0x01 +#define GPIO_PIN_READ 0x00 + +typedef struct _GPIO_PIN_CONTROL_PARAMETERS +{ + UCHAR ucGPIO_ID; //return value, read from GPIO pins + UCHAR ucGPIOBitShift; //define which bit in uGPIOBitVal need to be update + UCHAR ucGPIOBitVal; //Set/Reset corresponding bit defined in ucGPIOBitMask + UCHAR ucAction; //=GPIO_PIN_WRITE: Read; =GPIO_PIN_READ: Write +}GPIO_PIN_CONTROL_PARAMETERS; + +typedef struct _ENABLE_SCALER_PARAMETERS +{ + UCHAR ucScaler; // ATOM_SCALER1, ATOM_SCALER2 + UCHAR ucEnable; // ATOM_SCALER_DISABLE or ATOM_SCALER_CENTER or ATOM_SCALER_EXPANSION + UCHAR ucTVStandard; // + UCHAR ucPadding[1]; +}ENABLE_SCALER_PARAMETERS; +#define ENABLE_SCALER_PS_ALLOCATION ENABLE_SCALER_PARAMETERS + +//ucEnable: +#define SCALER_BYPASS_AUTO_CENTER_NO_REPLICATION 0 +#define SCALER_BYPASS_AUTO_CENTER_AUTO_REPLICATION 1 +#define SCALER_ENABLE_2TAP_ALPHA_MODE 2 +#define SCALER_ENABLE_MULTITAP_MODE 3 + +typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS +{ + ULONG usHWIconHorzVertPosn; // Hardware Icon Vertical position + UCHAR ucHWIconVertOffset; // Hardware Icon Vertical offset + UCHAR ucHWIconHorzOffset; // Hardware Icon Horizontal offset + UCHAR ucSelection; // ATOM_CURSOR1 or ATOM_ICON1 or ATOM_CURSOR2 or ATOM_ICON2 + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE +}ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS; + +typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION +{ + ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS sEnableIcon; + ENABLE_CRTC_PARAMETERS sReserved; +}ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION; + +typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS +{ + USHORT usHight; // Image Hight + USHORT usWidth; // Image Width + UCHAR ucSurface; // Surface 1 or 2 + UCHAR ucPadding[3]; +}ENABLE_GRAPH_SURFACE_PARAMETERS; + +typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2 +{ + USHORT usHight; // Image Hight + USHORT usWidth; // Image Width + UCHAR ucSurface; // Surface 1 or 2 + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucPadding[2]; +}ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2; + +typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_3 +{ + USHORT usHight; // Image Hight + USHORT usWidth; // Image Width + UCHAR ucSurface; // Surface 1 or 2 + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + USHORT usDeviceId; // Active Device Id for this surface. If no device, set to 0. +}ENABLE_GRAPH_SURFACE_PARAMETERS_V1_3; + +typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_4 +{ + USHORT usHight; // Image Hight + USHORT usWidth; // Image Width + USHORT usGraphPitch; + UCHAR ucColorDepth; + UCHAR ucPixelFormat; + UCHAR ucSurface; // Surface 1 or 2 + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + UCHAR ucModeType; + UCHAR ucReserved; +}ENABLE_GRAPH_SURFACE_PARAMETERS_V1_4; + +// ucEnable +#define ATOM_GRAPH_CONTROL_SET_PITCH 0x0f +#define ATOM_GRAPH_CONTROL_SET_DISP_START 0x10 + +typedef struct _ENABLE_GRAPH_SURFACE_PS_ALLOCATION +{ + ENABLE_GRAPH_SURFACE_PARAMETERS sSetSurface; + ENABLE_YUV_PS_ALLOCATION sReserved; // Don't set this one +}ENABLE_GRAPH_SURFACE_PS_ALLOCATION; + +typedef struct _MEMORY_CLEAN_UP_PARAMETERS +{ + USHORT usMemoryStart; //in 8Kb boundary, offset from memory base address + USHORT usMemorySize; //8Kb blocks aligned +}MEMORY_CLEAN_UP_PARAMETERS; +#define MEMORY_CLEAN_UP_PS_ALLOCATION MEMORY_CLEAN_UP_PARAMETERS + +typedef struct _GET_DISPLAY_SURFACE_SIZE_PARAMETERS +{ + USHORT usX_Size; //When use as input parameter, usX_Size indicates which CRTC + USHORT usY_Size; +}GET_DISPLAY_SURFACE_SIZE_PARAMETERS; + +typedef struct _GET_DISPLAY_SURFACE_SIZE_PARAMETERS_V2 +{ + union{ + USHORT usX_Size; //When use as input parameter, usX_Size indicates which CRTC + USHORT usSurface; + }; + USHORT usY_Size; + USHORT usDispXStart; + USHORT usDispYStart; +}GET_DISPLAY_SURFACE_SIZE_PARAMETERS_V2; + + +typedef struct _PALETTE_DATA_CONTROL_PARAMETERS_V3 +{ + UCHAR ucLutId; + UCHAR ucAction; + USHORT usLutStartIndex; + USHORT usLutLength; + USHORT usLutOffsetInVram; +}PALETTE_DATA_CONTROL_PARAMETERS_V3; + +// ucAction: +#define PALETTE_DATA_AUTO_FILL 1 +#define PALETTE_DATA_READ 2 +#define PALETTE_DATA_WRITE 3 + + +typedef struct _INTERRUPT_SERVICE_PARAMETERS_V2 +{ + UCHAR ucInterruptId; + UCHAR ucServiceId; + UCHAR ucStatus; + UCHAR ucReserved; +}INTERRUPT_SERVICE_PARAMETER_V2; + +// ucInterruptId +#define HDP1_INTERRUPT_ID 1 +#define HDP2_INTERRUPT_ID 2 +#define HDP3_INTERRUPT_ID 3 +#define HDP4_INTERRUPT_ID 4 +#define HDP5_INTERRUPT_ID 5 +#define HDP6_INTERRUPT_ID 6 +#define SW_INTERRUPT_ID 11 + +// ucAction +#define INTERRUPT_SERVICE_GEN_SW_INT 1 +#define INTERRUPT_SERVICE_GET_STATUS 2 + + // ucStatus +#define INTERRUPT_STATUS__INT_TRIGGER 1 +#define INTERRUPT_STATUS__HPD_HIGH 2 + +typedef struct _INDIRECT_IO_ACCESS +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR IOAccessSequence[256]; +} INDIRECT_IO_ACCESS; + +#define INDIRECT_READ 0x00 +#define INDIRECT_WRITE 0x80 + +#define INDIRECT_IO_MM 0 +#define INDIRECT_IO_PLL 1 +#define INDIRECT_IO_MC 2 +#define INDIRECT_IO_PCIE 3 +#define INDIRECT_IO_PCIEP 4 +#define INDIRECT_IO_NBMISC 5 + +#define INDIRECT_IO_PLL_READ INDIRECT_IO_PLL | INDIRECT_READ +#define INDIRECT_IO_PLL_WRITE INDIRECT_IO_PLL | INDIRECT_WRITE +#define INDIRECT_IO_MC_READ INDIRECT_IO_MC | INDIRECT_READ +#define INDIRECT_IO_MC_WRITE INDIRECT_IO_MC | INDIRECT_WRITE +#define INDIRECT_IO_PCIE_READ INDIRECT_IO_PCIE | INDIRECT_READ +#define INDIRECT_IO_PCIE_WRITE INDIRECT_IO_PCIE | INDIRECT_WRITE +#define INDIRECT_IO_PCIEP_READ INDIRECT_IO_PCIEP | INDIRECT_READ +#define INDIRECT_IO_PCIEP_WRITE INDIRECT_IO_PCIEP | INDIRECT_WRITE +#define INDIRECT_IO_NBMISC_READ INDIRECT_IO_NBMISC | INDIRECT_READ +#define INDIRECT_IO_NBMISC_WRITE INDIRECT_IO_NBMISC | INDIRECT_WRITE + +typedef struct _ATOM_OEM_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; +}ATOM_OEM_INFO; + +typedef struct _ATOM_TV_MODE +{ + UCHAR ucVMode_Num; //Video mode number + UCHAR ucTV_Mode_Num; //Internal TV mode number +}ATOM_TV_MODE; + +typedef struct _ATOM_BIOS_INT_TVSTD_MODE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usTV_Mode_LUT_Offset; // Pointer to standard to internal number conversion table + USHORT usTV_FIFO_Offset; // Pointer to FIFO entry table + USHORT usNTSC_Tbl_Offset; // Pointer to SDTV_Mode_NTSC table + USHORT usPAL_Tbl_Offset; // Pointer to SDTV_Mode_PAL table + USHORT usCV_Tbl_Offset; // Pointer to SDTV_Mode_PAL table +}ATOM_BIOS_INT_TVSTD_MODE; + + +typedef struct _ATOM_TV_MODE_SCALER_PTR +{ + USHORT ucFilter0_Offset; //Pointer to filter format 0 coefficients + USHORT usFilter1_Offset; //Pointer to filter format 0 coefficients + UCHAR ucTV_Mode_Num; +}ATOM_TV_MODE_SCALER_PTR; + +typedef struct _ATOM_STANDARD_VESA_TIMING +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT aModeTimings[16]; // 16 is not the real array number, just for initial allocation +}ATOM_STANDARD_VESA_TIMING; + + +typedef struct _ATOM_STD_FORMAT +{ + USHORT usSTD_HDisp; + USHORT usSTD_VDisp; + USHORT usSTD_RefreshRate; + USHORT usReserved; +}ATOM_STD_FORMAT; + +typedef struct _ATOM_VESA_TO_EXTENDED_MODE +{ + USHORT usVESA_ModeNumber; + USHORT usExtendedModeNumber; +}ATOM_VESA_TO_EXTENDED_MODE; + +typedef struct _ATOM_VESA_TO_INTENAL_MODE_LUT +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_VESA_TO_EXTENDED_MODE asVESA_ToExtendedModeInfo[76]; +}ATOM_VESA_TO_INTENAL_MODE_LUT; + +/*************** ATOM Memory Related Data Structure ***********************/ +typedef struct _ATOM_MEMORY_VENDOR_BLOCK{ + UCHAR ucMemoryType; + UCHAR ucMemoryVendor; + UCHAR ucAdjMCId; + UCHAR ucDynClkId; + ULONG ulDllResetClkRange; +}ATOM_MEMORY_VENDOR_BLOCK; + + +typedef struct _ATOM_MEMORY_SETTING_ID_CONFIG{ +#if ATOM_BIG_ENDIAN + ULONG ucMemBlkId:8; + ULONG ulMemClockRange:24; +#else + ULONG ulMemClockRange:24; + ULONG ucMemBlkId:8; +#endif +}ATOM_MEMORY_SETTING_ID_CONFIG; + +typedef union _ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS +{ + ATOM_MEMORY_SETTING_ID_CONFIG slAccess; + ULONG ulAccess; +}ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS; + + +typedef struct _ATOM_MEMORY_SETTING_DATA_BLOCK{ + ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS ulMemoryID; + ULONG aulMemData[1]; +}ATOM_MEMORY_SETTING_DATA_BLOCK; + + +typedef struct _ATOM_INIT_REG_INDEX_FORMAT{ + USHORT usRegIndex; // MC register index + UCHAR ucPreRegDataLength; // offset in ATOM_INIT_REG_DATA_BLOCK.saRegDataBuf +}ATOM_INIT_REG_INDEX_FORMAT; + + +typedef struct _ATOM_INIT_REG_BLOCK{ + USHORT usRegIndexTblSize; //size of asRegIndexBuf + USHORT usRegDataBlkSize; //size of ATOM_MEMORY_SETTING_DATA_BLOCK + ATOM_INIT_REG_INDEX_FORMAT asRegIndexBuf[1]; + ATOM_MEMORY_SETTING_DATA_BLOCK asRegDataBuf[1]; +}ATOM_INIT_REG_BLOCK; + +#define END_OF_REG_INDEX_BLOCK 0x0ffff +#define END_OF_REG_DATA_BLOCK 0x00000000 +#define ATOM_INIT_REG_MASK_FLAG 0x80 //Not used in BIOS +#define CLOCK_RANGE_HIGHEST 0x00ffffff + +#define VALUE_DWORD SIZEOF ULONG +#define VALUE_SAME_AS_ABOVE 0 +#define VALUE_MASK_DWORD 0x84 + +#define INDEX_ACCESS_RANGE_BEGIN (VALUE_DWORD + 1) +#define INDEX_ACCESS_RANGE_END (INDEX_ACCESS_RANGE_BEGIN + 1) +#define VALUE_INDEX_ACCESS_SINGLE (INDEX_ACCESS_RANGE_END + 1) +//#define ACCESS_MCIODEBUGIND 0x40 //defined in BIOS code +#define ACCESS_PLACEHOLDER 0x80 + +typedef struct _ATOM_MC_INIT_PARAM_TABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usAdjustARB_SEQDataOffset; + USHORT usMCInitMemTypeTblOffset; + USHORT usMCInitCommonTblOffset; + USHORT usMCInitPowerDownTblOffset; + ULONG ulARB_SEQDataBuf[32]; + ATOM_INIT_REG_BLOCK asMCInitMemType; + ATOM_INIT_REG_BLOCK asMCInitCommon; +}ATOM_MC_INIT_PARAM_TABLE; + + +#define _4Mx16 0x2 +#define _4Mx32 0x3 +#define _8Mx16 0x12 +#define _8Mx32 0x13 +#define _16Mx16 0x22 +#define _16Mx32 0x23 +#define _32Mx16 0x32 +#define _32Mx32 0x33 +#define _64Mx8 0x41 +#define _64Mx16 0x42 +#define _64Mx32 0x43 +#define _128Mx8 0x51 +#define _128Mx16 0x52 +#define _256Mx8 0x61 +#define _256Mx16 0x62 + +#define SAMSUNG 0x1 +#define INFINEON 0x2 +#define ELPIDA 0x3 +#define ETRON 0x4 +#define NANYA 0x5 +#define HYNIX 0x6 +#define MOSEL 0x7 +#define WINBOND 0x8 +#define ESMT 0x9 +#define MICRON 0xF + +#define QIMONDA INFINEON +#define PROMOS MOSEL +#define KRETON INFINEON +#define ELIXIR NANYA + +/////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM///////////// + +#define UCODE_ROM_START_ADDRESS 0x1b800 +#define UCODE_SIGNATURE 0x4375434d // 'MCuC' - MC uCode + +//uCode block header for reference + +typedef struct _MCuCodeHeader +{ + ULONG ulSignature; + UCHAR ucRevision; + UCHAR ucChecksum; + UCHAR ucReserved1; + UCHAR ucReserved2; + USHORT usParametersLength; + USHORT usUCodeLength; + USHORT usReserved1; + USHORT usReserved2; +} MCuCodeHeader; + +////////////////////////////////////////////////////////////////////////////////// + +#define ATOM_MAX_NUMBER_OF_VRAM_MODULE 16 + +#define ATOM_VRAM_MODULE_MEMORY_VENDOR_ID_MASK 0xF +typedef struct _ATOM_VRAM_MODULE_V1 +{ + ULONG ulReserved; + USHORT usEMRSValue; + USHORT usMRSValue; + USHORT usReserved; + UCHAR ucExtMemoryID; // An external indicator (by hardcode, callback or pin) to tell what is the current memory module + UCHAR ucMemoryType; // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] reserved; + UCHAR ucMemoryVenderID; // Predefined,never change across designs or memory type/vender + UCHAR ucMemoryDeviceCfg; // [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... + UCHAR ucRow; // Number of Row,in power of 2; + UCHAR ucColumn; // Number of Column,in power of 2; + UCHAR ucBank; // Nunber of Bank; + UCHAR ucRank; // Number of Rank, in power of 2 + UCHAR ucChannelNum; // Number of channel; + UCHAR ucChannelConfig; // [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 + UCHAR ucDefaultMVDDQ_ID; // Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; + UCHAR ucDefaultMVDDC_ID; // Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; + UCHAR ucReserved[2]; +}ATOM_VRAM_MODULE_V1; + + +typedef struct _ATOM_VRAM_MODULE_V2 +{ + ULONG ulReserved; + ULONG ulFlags; // To enable/disable functionalities based on memory type + ULONG ulEngineClock; // Override of default engine clock for particular memory type + ULONG ulMemoryClock; // Override of default memory clock for particular memory type + USHORT usEMRS2Value; // EMRS2 Value is used for GDDR2 and GDDR4 memory type + USHORT usEMRS3Value; // EMRS3 Value is used for GDDR2 and GDDR4 memory type + USHORT usEMRSValue; + USHORT usMRSValue; + USHORT usReserved; + UCHAR ucExtMemoryID; // An external indicator (by hardcode, callback or pin) to tell what is the current memory module + UCHAR ucMemoryType; // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; + UCHAR ucMemoryVenderID; // Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed + UCHAR ucMemoryDeviceCfg; // [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... + UCHAR ucRow; // Number of Row,in power of 2; + UCHAR ucColumn; // Number of Column,in power of 2; + UCHAR ucBank; // Nunber of Bank; + UCHAR ucRank; // Number of Rank, in power of 2 + UCHAR ucChannelNum; // Number of channel; + UCHAR ucChannelConfig; // [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 + UCHAR ucDefaultMVDDQ_ID; // Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; + UCHAR ucDefaultMVDDC_ID; // Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; + UCHAR ucRefreshRateFactor; + UCHAR ucReserved[3]; +}ATOM_VRAM_MODULE_V2; + + +typedef struct _ATOM_MEMORY_TIMING_FORMAT +{ + ULONG ulClkRange; // memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing + union{ + USHORT usMRS; // mode register + USHORT usDDR3_MR0; + }; + union{ + USHORT usEMRS; // extended mode register + USHORT usDDR3_MR1; + }; + UCHAR ucCL; // CAS latency + UCHAR ucWL; // WRITE Latency + UCHAR uctRAS; // tRAS + UCHAR uctRC; // tRC + UCHAR uctRFC; // tRFC + UCHAR uctRCDR; // tRCDR + UCHAR uctRCDW; // tRCDW + UCHAR uctRP; // tRP + UCHAR uctRRD; // tRRD + UCHAR uctWR; // tWR + UCHAR uctWTR; // tWTR + UCHAR uctPDIX; // tPDIX + UCHAR uctFAW; // tFAW + UCHAR uctAOND; // tAOND + union + { + struct { + UCHAR ucflag; // flag to control memory timing calculation. bit0= control EMRS2 Infineon + UCHAR ucReserved; + }; + USHORT usDDR3_MR2; + }; +}ATOM_MEMORY_TIMING_FORMAT; + + +typedef struct _ATOM_MEMORY_TIMING_FORMAT_V1 +{ + ULONG ulClkRange; // memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing + USHORT usMRS; // mode register + USHORT usEMRS; // extended mode register + UCHAR ucCL; // CAS latency + UCHAR ucWL; // WRITE Latency + UCHAR uctRAS; // tRAS + UCHAR uctRC; // tRC + UCHAR uctRFC; // tRFC + UCHAR uctRCDR; // tRCDR + UCHAR uctRCDW; // tRCDW + UCHAR uctRP; // tRP + UCHAR uctRRD; // tRRD + UCHAR uctWR; // tWR + UCHAR uctWTR; // tWTR + UCHAR uctPDIX; // tPDIX + UCHAR uctFAW; // tFAW + UCHAR uctAOND; // tAOND + UCHAR ucflag; // flag to control memory timing calculation. bit0= control EMRS2 Infineon +////////////////////////////////////GDDR parameters/////////////////////////////////// + UCHAR uctCCDL; // + UCHAR uctCRCRL; // + UCHAR uctCRCWL; // + UCHAR uctCKE; // + UCHAR uctCKRSE; // + UCHAR uctCKRSX; // + UCHAR uctFAW32; // + UCHAR ucMR5lo; // + UCHAR ucMR5hi; // + UCHAR ucTerminator; +}ATOM_MEMORY_TIMING_FORMAT_V1; + +typedef struct _ATOM_MEMORY_TIMING_FORMAT_V2 +{ + ULONG ulClkRange; // memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing + USHORT usMRS; // mode register + USHORT usEMRS; // extended mode register + UCHAR ucCL; // CAS latency + UCHAR ucWL; // WRITE Latency + UCHAR uctRAS; // tRAS + UCHAR uctRC; // tRC + UCHAR uctRFC; // tRFC + UCHAR uctRCDR; // tRCDR + UCHAR uctRCDW; // tRCDW + UCHAR uctRP; // tRP + UCHAR uctRRD; // tRRD + UCHAR uctWR; // tWR + UCHAR uctWTR; // tWTR + UCHAR uctPDIX; // tPDIX + UCHAR uctFAW; // tFAW + UCHAR uctAOND; // tAOND + UCHAR ucflag; // flag to control memory timing calculation. bit0= control EMRS2 Infineon +////////////////////////////////////GDDR parameters/////////////////////////////////// + UCHAR uctCCDL; // + UCHAR uctCRCRL; // + UCHAR uctCRCWL; // + UCHAR uctCKE; // + UCHAR uctCKRSE; // + UCHAR uctCKRSX; // + UCHAR uctFAW32; // + UCHAR ucMR4lo; // + UCHAR ucMR4hi; // + UCHAR ucMR5lo; // + UCHAR ucMR5hi; // + UCHAR ucTerminator; + UCHAR ucReserved; +}ATOM_MEMORY_TIMING_FORMAT_V2; + +typedef struct _ATOM_MEMORY_FORMAT +{ + ULONG ulDllDisClock; // memory DLL will be disable when target memory clock is below this clock + union{ + USHORT usEMRS2Value; // EMRS2 Value is used for GDDR2 and GDDR4 memory type + USHORT usDDR3_Reserved; // Not used for DDR3 memory + }; + union{ + USHORT usEMRS3Value; // EMRS3 Value is used for GDDR2 and GDDR4 memory type + USHORT usDDR3_MR3; // Used for DDR3 memory + }; + UCHAR ucMemoryType; // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; + UCHAR ucMemoryVenderID; // Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed + UCHAR ucRow; // Number of Row,in power of 2; + UCHAR ucColumn; // Number of Column,in power of 2; + UCHAR ucBank; // Nunber of Bank; + UCHAR ucRank; // Number of Rank, in power of 2 + UCHAR ucBurstSize; // burst size, 0= burst size=4 1= burst size=8 + UCHAR ucDllDisBit; // position of DLL Enable/Disable bit in EMRS ( Extended Mode Register ) + UCHAR ucRefreshRateFactor; // memory refresh rate in unit of ms + UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 + UCHAR ucPreamble; //[7:4] Write Preamble, [3:0] Read Preamble + UCHAR ucMemAttrib; // Memory Device Addribute, like RDBI/WDBI etc + ATOM_MEMORY_TIMING_FORMAT asMemTiming[5]; //Memory Timing block sort from lower clock to higher clock +}ATOM_MEMORY_FORMAT; + + +typedef struct _ATOM_VRAM_MODULE_V3 +{ + ULONG ulChannelMapCfg; // board dependent paramenter:Channel combination + USHORT usSize; // size of ATOM_VRAM_MODULE_V3 + USHORT usDefaultMVDDQ; // board dependent parameter:Default Memory Core Voltage + USHORT usDefaultMVDDC; // board dependent parameter:Default Memory IO Voltage + UCHAR ucExtMemoryID; // An external indicator (by hardcode, callback or pin) to tell what is the current memory module + UCHAR ucChannelNum; // board dependent parameter:Number of channel; + UCHAR ucChannelSize; // board dependent parameter:32bit or 64bit + UCHAR ucVREFI; // board dependnt parameter: EXT or INT +160mv to -140mv + UCHAR ucNPL_RT; // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters + UCHAR ucFlag; // To enable/disable functionalities based on memory type + ATOM_MEMORY_FORMAT asMemory; // describ all of video memory parameters from memory spec +}ATOM_VRAM_MODULE_V3; + + +//ATOM_VRAM_MODULE_V3.ucNPL_RT +#define NPL_RT_MASK 0x0f +#define BATTERY_ODT_MASK 0xc0 + +#define ATOM_VRAM_MODULE ATOM_VRAM_MODULE_V3 + +typedef struct _ATOM_VRAM_MODULE_V4 +{ + ULONG ulChannelMapCfg; // board dependent parameter: Channel combination + USHORT usModuleSize; // size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE + USHORT usPrivateReserved; // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! + // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) + USHORT usReserved; + UCHAR ucExtMemoryID; // An external indicator (by hardcode, callback or pin) to tell what is the current memory module + UCHAR ucMemoryType; // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; + UCHAR ucChannelNum; // Number of channels present in this module config + UCHAR ucChannelWidth; // 0 - 32 bits; 1 - 64 bits + UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 + UCHAR ucFlag; // To enable/disable functionalities based on memory type + UCHAR ucMisc; // bit0: 0 - single rank; 1 - dual rank; bit2: 0 - burstlength 4, 1 - burstlength 8 + UCHAR ucVREFI; // board dependent parameter + UCHAR ucNPL_RT; // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters + UCHAR ucPreamble; // [7:4] Write Preamble, [3:0] Read Preamble + UCHAR ucMemorySize; // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! + // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros + UCHAR ucReserved[3]; + +//compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level + union{ + USHORT usEMRS2Value; // EMRS2 Value is used for GDDR2 and GDDR4 memory type + USHORT usDDR3_Reserved; + }; + union{ + USHORT usEMRS3Value; // EMRS3 Value is used for GDDR2 and GDDR4 memory type + USHORT usDDR3_MR3; // Used for DDR3 memory + }; + UCHAR ucMemoryVenderID; // Predefined, If not predefined, vendor detection table gets executed + UCHAR ucRefreshRateFactor; // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) + UCHAR ucReserved2[2]; + ATOM_MEMORY_TIMING_FORMAT asMemTiming[5];//Memory Timing block sort from lower clock to higher clock +}ATOM_VRAM_MODULE_V4; + +#define VRAM_MODULE_V4_MISC_RANK_MASK 0x3 +#define VRAM_MODULE_V4_MISC_DUAL_RANK 0x1 +#define VRAM_MODULE_V4_MISC_BL_MASK 0x4 +#define VRAM_MODULE_V4_MISC_BL8 0x4 +#define VRAM_MODULE_V4_MISC_DUAL_CS 0x10 + +typedef struct _ATOM_VRAM_MODULE_V5 +{ + ULONG ulChannelMapCfg; // board dependent parameter: Channel combination + USHORT usModuleSize; // size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE + USHORT usPrivateReserved; // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! + // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) + USHORT usReserved; + UCHAR ucExtMemoryID; // An external indicator (by hardcode, callback or pin) to tell what is the current memory module + UCHAR ucMemoryType; // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; + UCHAR ucChannelNum; // Number of channels present in this module config + UCHAR ucChannelWidth; // 0 - 32 bits; 1 - 64 bits + UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 + UCHAR ucFlag; // To enable/disable functionalities based on memory type + UCHAR ucMisc; // bit0: 0 - single rank; 1 - dual rank; bit2: 0 - burstlength 4, 1 - burstlength 8 + UCHAR ucVREFI; // board dependent parameter + UCHAR ucNPL_RT; // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters + UCHAR ucPreamble; // [7:4] Write Preamble, [3:0] Read Preamble + UCHAR ucMemorySize; // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! + // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros + UCHAR ucReserved[3]; + +//compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level + USHORT usEMRS2Value; // EMRS2 Value is used for GDDR2 and GDDR4 memory type + USHORT usEMRS3Value; // EMRS3 Value is used for GDDR2 and GDDR4 memory type + UCHAR ucMemoryVenderID; // Predefined, If not predefined, vendor detection table gets executed + UCHAR ucRefreshRateFactor; // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) + UCHAR ucFIFODepth; // FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth + UCHAR ucCDR_Bandwidth; // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth + ATOM_MEMORY_TIMING_FORMAT_V1 asMemTiming[5];//Memory Timing block sort from lower clock to higher clock +}ATOM_VRAM_MODULE_V5; + +typedef struct _ATOM_VRAM_MODULE_V6 +{ + ULONG ulChannelMapCfg; // board dependent parameter: Channel combination + USHORT usModuleSize; // size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE + USHORT usPrivateReserved; // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! + // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) + USHORT usReserved; + UCHAR ucExtMemoryID; // An external indicator (by hardcode, callback or pin) to tell what is the current memory module + UCHAR ucMemoryType; // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; + UCHAR ucChannelNum; // Number of channels present in this module config + UCHAR ucChannelWidth; // 0 - 32 bits; 1 - 64 bits + UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 + UCHAR ucFlag; // To enable/disable functionalities based on memory type + UCHAR ucMisc; // bit0: 0 - single rank; 1 - dual rank; bit2: 0 - burstlength 4, 1 - burstlength 8 + UCHAR ucVREFI; // board dependent parameter + UCHAR ucNPL_RT; // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters + UCHAR ucPreamble; // [7:4] Write Preamble, [3:0] Read Preamble + UCHAR ucMemorySize; // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! + // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros + UCHAR ucReserved[3]; + +//compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level + USHORT usEMRS2Value; // EMRS2 Value is used for GDDR2 and GDDR4 memory type + USHORT usEMRS3Value; // EMRS3 Value is used for GDDR2 and GDDR4 memory type + UCHAR ucMemoryVenderID; // Predefined, If not predefined, vendor detection table gets executed + UCHAR ucRefreshRateFactor; // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) + UCHAR ucFIFODepth; // FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth + UCHAR ucCDR_Bandwidth; // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth + ATOM_MEMORY_TIMING_FORMAT_V2 asMemTiming[5];//Memory Timing block sort from lower clock to higher clock +}ATOM_VRAM_MODULE_V6; + +typedef struct _ATOM_VRAM_MODULE_V7 +{ +// Design Specific Values + ULONG ulChannelMapCfg; // mmMC_SHARED_CHREMAP + USHORT usModuleSize; // Size of ATOM_VRAM_MODULE_V7 + USHORT usPrivateReserved; // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) + USHORT usEnableChannels; // bit vector which indicate which channels are enabled + UCHAR ucExtMemoryID; // Current memory module ID + UCHAR ucMemoryType; // MEM_TYPE_DDR2/DDR3/GDDR3/GDDR5 + UCHAR ucChannelNum; // Number of mem. channels supported in this module + UCHAR ucChannelWidth; // CHANNEL_16BIT/CHANNEL_32BIT/CHANNEL_64BIT + UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 + UCHAR ucReserve; // Former container for Mx_FLAGS like DBI_AC_MODE_ENABLE_ASIC for GDDR4. Not used now. + UCHAR ucMisc; // RANK_OF_THISMEMORY etc. + UCHAR ucVREFI; // Not used. + UCHAR ucNPL_RT; // Round trip delay (MC_SEQ_CAS_TIMING [28:24]:TCL=CL+NPL_RT-2). Always 2. + UCHAR ucPreamble; // [7:4] Write Preamble, [3:0] Read Preamble + UCHAR ucMemorySize; // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros + USHORT usSEQSettingOffset; + UCHAR ucReserved; +// Memory Module specific values + USHORT usEMRS2Value; // EMRS2/MR2 Value. + USHORT usEMRS3Value; // EMRS3/MR3 Value. + UCHAR ucMemoryVenderID; // [7:4] Revision, [3:0] Vendor code + UCHAR ucRefreshRateFactor; // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) + UCHAR ucFIFODepth; // FIFO depth can be detected during vendor detection, here is hardcoded per memory + UCHAR ucCDR_Bandwidth; // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth + char strMemPNString[20]; // part number end with '0'. +}ATOM_VRAM_MODULE_V7; + +typedef struct _ATOM_VRAM_INFO_V2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucNumOfVRAMModule; + ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; // just for allocation, real number of blocks is in ucNumOfVRAMModule; +}ATOM_VRAM_INFO_V2; + +typedef struct _ATOM_VRAM_INFO_V3 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMemAdjustTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting + USHORT usMemClkPatchTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting + USHORT usRerseved; + UCHAR aVID_PinsShift[9]; // 8 bit strap maximum+terminator + UCHAR ucNumOfVRAMModule; + ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; // just for allocation, real number of blocks is in ucNumOfVRAMModule; + ATOM_INIT_REG_BLOCK asMemPatch; // for allocation + // ATOM_INIT_REG_BLOCK aMemAdjust; +}ATOM_VRAM_INFO_V3; + +#define ATOM_VRAM_INFO_LAST ATOM_VRAM_INFO_V3 + +typedef struct _ATOM_VRAM_INFO_V4 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMemAdjustTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting + USHORT usMemClkPatchTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting + USHORT usRerseved; + UCHAR ucMemDQ7_0ByteRemap; // DQ line byte remap, =0: Memory Data line BYTE0, =1: BYTE1, =2: BYTE2, =3: BYTE3 + ULONG ulMemDQ7_0BitRemap; // each DQ line ( 7~0) use 3bits, like: DQ0=Bit[2:0], DQ1:[5:3], ... DQ7:[23:21] + UCHAR ucReservde[4]; + UCHAR ucNumOfVRAMModule; + ATOM_VRAM_MODULE_V4 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; // just for allocation, real number of blocks is in ucNumOfVRAMModule; + ATOM_INIT_REG_BLOCK asMemPatch; // for allocation + // ATOM_INIT_REG_BLOCK aMemAdjust; +}ATOM_VRAM_INFO_V4; + +typedef struct _ATOM_VRAM_INFO_HEADER_V2_1 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMemAdjustTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting + USHORT usMemClkPatchTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting + USHORT usPerBytePresetOffset; // offset of ATOM_INIT_REG_BLOCK structure for Per Byte Offset Preset Settings + USHORT usReserved[3]; + UCHAR ucNumOfVRAMModule; // indicate number of VRAM module + UCHAR ucMemoryClkPatchTblVer; // version of memory AC timing register list + UCHAR ucVramModuleVer; // indicate ATOM_VRAM_MODUE version + UCHAR ucReserved; + ATOM_VRAM_MODULE_V7 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; // just for allocation, real number of blocks is in ucNumOfVRAMModule; +}ATOM_VRAM_INFO_HEADER_V2_1; + + +typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR aVID_PinsShift[9]; //8 bit strap maximum+terminator +}ATOM_VRAM_GPIO_DETECTION_INFO; + + +typedef struct _ATOM_MEMORY_TRAINING_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucTrainingLoop; + UCHAR ucReserved[3]; + ATOM_INIT_REG_BLOCK asMemTrainingSetting; +}ATOM_MEMORY_TRAINING_INFO; + + +typedef struct SW_I2C_CNTL_DATA_PARAMETERS +{ + UCHAR ucControl; + UCHAR ucData; + UCHAR ucSatus; + UCHAR ucTemp; +} SW_I2C_CNTL_DATA_PARAMETERS; + +#define SW_I2C_CNTL_DATA_PS_ALLOCATION SW_I2C_CNTL_DATA_PARAMETERS + +typedef struct _SW_I2C_IO_DATA_PARAMETERS +{ + USHORT GPIO_Info; + UCHAR ucAct; + UCHAR ucData; + } SW_I2C_IO_DATA_PARAMETERS; + +#define SW_I2C_IO_DATA_PS_ALLOCATION SW_I2C_IO_DATA_PARAMETERS + +/****************************SW I2C CNTL DEFINITIONS**********************/ +#define SW_I2C_IO_RESET 0 +#define SW_I2C_IO_GET 1 +#define SW_I2C_IO_DRIVE 2 +#define SW_I2C_IO_SET 3 +#define SW_I2C_IO_START 4 + +#define SW_I2C_IO_CLOCK 0 +#define SW_I2C_IO_DATA 0x80 + +#define SW_I2C_IO_ZERO 0 +#define SW_I2C_IO_ONE 0x100 + +#define SW_I2C_CNTL_READ 0 +#define SW_I2C_CNTL_WRITE 1 +#define SW_I2C_CNTL_START 2 +#define SW_I2C_CNTL_STOP 3 +#define SW_I2C_CNTL_OPEN 4 +#define SW_I2C_CNTL_CLOSE 5 +#define SW_I2C_CNTL_WRITE1BIT 6 + +//==============================VESA definition Portion=============================== +#define VESA_OEM_PRODUCT_REV "01.00" +#define VESA_MODE_ATTRIBUTE_MODE_SUPPORT 0xBB //refer to VBE spec p.32, no TTY support +#define VESA_MODE_WIN_ATTRIBUTE 7 +#define VESA_WIN_SIZE 64 + +typedef struct _PTR_32_BIT_STRUCTURE +{ + USHORT Offset16; + USHORT Segment16; +} PTR_32_BIT_STRUCTURE; + +typedef union _PTR_32_BIT_UNION +{ + PTR_32_BIT_STRUCTURE SegmentOffset; + ULONG Ptr32_Bit; +} PTR_32_BIT_UNION; + +typedef struct _VBE_1_2_INFO_BLOCK_UPDATABLE +{ + UCHAR VbeSignature[4]; + USHORT VbeVersion; + PTR_32_BIT_UNION OemStringPtr; + UCHAR Capabilities[4]; + PTR_32_BIT_UNION VideoModePtr; + USHORT TotalMemory; +} VBE_1_2_INFO_BLOCK_UPDATABLE; + + +typedef struct _VBE_2_0_INFO_BLOCK_UPDATABLE +{ + VBE_1_2_INFO_BLOCK_UPDATABLE CommonBlock; + USHORT OemSoftRev; + PTR_32_BIT_UNION OemVendorNamePtr; + PTR_32_BIT_UNION OemProductNamePtr; + PTR_32_BIT_UNION OemProductRevPtr; +} VBE_2_0_INFO_BLOCK_UPDATABLE; + +typedef union _VBE_VERSION_UNION +{ + VBE_2_0_INFO_BLOCK_UPDATABLE VBE_2_0_InfoBlock; + VBE_1_2_INFO_BLOCK_UPDATABLE VBE_1_2_InfoBlock; +} VBE_VERSION_UNION; + +typedef struct _VBE_INFO_BLOCK +{ + VBE_VERSION_UNION UpdatableVBE_Info; + UCHAR Reserved[222]; + UCHAR OemData[256]; +} VBE_INFO_BLOCK; + +typedef struct _VBE_FP_INFO +{ + USHORT HSize; + USHORT VSize; + USHORT FPType; + UCHAR RedBPP; + UCHAR GreenBPP; + UCHAR BlueBPP; + UCHAR ReservedBPP; + ULONG RsvdOffScrnMemSize; + ULONG RsvdOffScrnMEmPtr; + UCHAR Reserved[14]; +} VBE_FP_INFO; + +typedef struct _VESA_MODE_INFO_BLOCK +{ +// Mandatory information for all VBE revisions + USHORT ModeAttributes; // dw ? ; mode attributes + UCHAR WinAAttributes; // db ? ; window A attributes + UCHAR WinBAttributes; // db ? ; window B attributes + USHORT WinGranularity; // dw ? ; window granularity + USHORT WinSize; // dw ? ; window size + USHORT WinASegment; // dw ? ; window A start segment + USHORT WinBSegment; // dw ? ; window B start segment + ULONG WinFuncPtr; // dd ? ; real mode pointer to window function + USHORT BytesPerScanLine;// dw ? ; bytes per scan line + +//; Mandatory information for VBE 1.2 and above + USHORT XResolution; // dw ? ; horizontal resolution in pixels or characters + USHORT YResolution; // dw ? ; vertical resolution in pixels or characters + UCHAR XCharSize; // db ? ; character cell width in pixels + UCHAR YCharSize; // db ? ; character cell height in pixels + UCHAR NumberOfPlanes; // db ? ; number of memory planes + UCHAR BitsPerPixel; // db ? ; bits per pixel + UCHAR NumberOfBanks; // db ? ; number of banks + UCHAR MemoryModel; // db ? ; memory model type + UCHAR BankSize; // db ? ; bank size in KB + UCHAR NumberOfImagePages;// db ? ; number of images + UCHAR ReservedForPageFunction;//db 1 ; reserved for page function + +//; Direct Color fields(required for direct/6 and YUV/7 memory models) + UCHAR RedMaskSize; // db ? ; size of direct color red mask in bits + UCHAR RedFieldPosition; // db ? ; bit position of lsb of red mask + UCHAR GreenMaskSize; // db ? ; size of direct color green mask in bits + UCHAR GreenFieldPosition; // db ? ; bit position of lsb of green mask + UCHAR BlueMaskSize; // db ? ; size of direct color blue mask in bits + UCHAR BlueFieldPosition; // db ? ; bit position of lsb of blue mask + UCHAR RsvdMaskSize; // db ? ; size of direct color reserved mask in bits + UCHAR RsvdFieldPosition; // db ? ; bit position of lsb of reserved mask + UCHAR DirectColorModeInfo;// db ? ; direct color mode attributes + +//; Mandatory information for VBE 2.0 and above + ULONG PhysBasePtr; // dd ? ; physical address for flat memory frame buffer + ULONG Reserved_1; // dd 0 ; reserved - always set to 0 + USHORT Reserved_2; // dw 0 ; reserved - always set to 0 + +//; Mandatory information for VBE 3.0 and above + USHORT LinBytesPerScanLine; // dw ? ; bytes per scan line for linear modes + UCHAR BnkNumberOfImagePages;// db ? ; number of images for banked modes + UCHAR LinNumberOfImagPages; // db ? ; number of images for linear modes + UCHAR LinRedMaskSize; // db ? ; size of direct color red mask(linear modes) + UCHAR LinRedFieldPosition; // db ? ; bit position of lsb of red mask(linear modes) + UCHAR LinGreenMaskSize; // db ? ; size of direct color green mask(linear modes) + UCHAR LinGreenFieldPosition;// db ? ; bit position of lsb of green mask(linear modes) + UCHAR LinBlueMaskSize; // db ? ; size of direct color blue mask(linear modes) + UCHAR LinBlueFieldPosition; // db ? ; bit position of lsb of blue mask(linear modes) + UCHAR LinRsvdMaskSize; // db ? ; size of direct color reserved mask(linear modes) + UCHAR LinRsvdFieldPosition; // db ? ; bit position of lsb of reserved mask(linear modes) + ULONG MaxPixelClock; // dd ? ; maximum pixel clock(in Hz) for graphics mode + UCHAR Reserved; // db 190 dup (0) +} VESA_MODE_INFO_BLOCK; + +// BIOS function CALLS +#define ATOM_BIOS_EXTENDED_FUNCTION_CODE 0xA0 // ATI Extended Function code +#define ATOM_BIOS_FUNCTION_COP_MODE 0x00 +#define ATOM_BIOS_FUNCTION_SHORT_QUERY1 0x04 +#define ATOM_BIOS_FUNCTION_SHORT_QUERY2 0x05 +#define ATOM_BIOS_FUNCTION_SHORT_QUERY3 0x06 +#define ATOM_BIOS_FUNCTION_GET_DDC 0x0B +#define ATOM_BIOS_FUNCTION_ASIC_DSTATE 0x0E +#define ATOM_BIOS_FUNCTION_DEBUG_PLAY 0x0F +#define ATOM_BIOS_FUNCTION_STV_STD 0x16 +#define ATOM_BIOS_FUNCTION_DEVICE_DET 0x17 +#define ATOM_BIOS_FUNCTION_DEVICE_SWITCH 0x18 + +#define ATOM_BIOS_FUNCTION_PANEL_CONTROL 0x82 +#define ATOM_BIOS_FUNCTION_OLD_DEVICE_DET 0x83 +#define ATOM_BIOS_FUNCTION_OLD_DEVICE_SWITCH 0x84 +#define ATOM_BIOS_FUNCTION_HW_ICON 0x8A +#define ATOM_BIOS_FUNCTION_SET_CMOS 0x8B +#define SUB_FUNCTION_UPDATE_DISPLAY_INFO 0x8000 // Sub function 80 +#define SUB_FUNCTION_UPDATE_EXPANSION_INFO 0x8100 // Sub function 80 + +#define ATOM_BIOS_FUNCTION_DISPLAY_INFO 0x8D +#define ATOM_BIOS_FUNCTION_DEVICE_ON_OFF 0x8E +#define ATOM_BIOS_FUNCTION_VIDEO_STATE 0x8F +#define ATOM_SUB_FUNCTION_GET_CRITICAL_STATE 0x0300 // Sub function 03 +#define ATOM_SUB_FUNCTION_GET_LIDSTATE 0x0700 // Sub function 7 +#define ATOM_SUB_FUNCTION_THERMAL_STATE_NOTICE 0x1400 // Notify caller the current thermal state +#define ATOM_SUB_FUNCTION_CRITICAL_STATE_NOTICE 0x8300 // Notify caller the current critical state +#define ATOM_SUB_FUNCTION_SET_LIDSTATE 0x8500 // Sub function 85 +#define ATOM_SUB_FUNCTION_GET_REQ_DISPLAY_FROM_SBIOS_MODE 0x8900// Sub function 89 +#define ATOM_SUB_FUNCTION_INFORM_ADC_SUPPORT 0x9400 // Notify caller that ADC is supported + + +#define ATOM_BIOS_FUNCTION_VESA_DPMS 0x4F10 // Set DPMS +#define ATOM_SUB_FUNCTION_SET_DPMS 0x0001 // BL: Sub function 01 +#define ATOM_SUB_FUNCTION_GET_DPMS 0x0002 // BL: Sub function 02 +#define ATOM_PARAMETER_VESA_DPMS_ON 0x0000 // BH Parameter for DPMS ON. +#define ATOM_PARAMETER_VESA_DPMS_STANDBY 0x0100 // BH Parameter for DPMS STANDBY +#define ATOM_PARAMETER_VESA_DPMS_SUSPEND 0x0200 // BH Parameter for DPMS SUSPEND +#define ATOM_PARAMETER_VESA_DPMS_OFF 0x0400 // BH Parameter for DPMS OFF +#define ATOM_PARAMETER_VESA_DPMS_REDUCE_ON 0x0800 // BH Parameter for DPMS REDUCE ON (NOT SUPPORTED) + +#define ATOM_BIOS_RETURN_CODE_MASK 0x0000FF00L +#define ATOM_BIOS_REG_HIGH_MASK 0x0000FF00L +#define ATOM_BIOS_REG_LOW_MASK 0x000000FFL + +// structure used for VBIOS only + +//DispOutInfoTable +typedef struct _ASIC_TRANSMITTER_INFO +{ + USHORT usTransmitterObjId; + USHORT usSupportDevice; + UCHAR ucTransmitterCmdTblId; + UCHAR ucConfig; + UCHAR ucEncoderID; //available 1st encoder ( default ) + UCHAR ucOptionEncoderID; //available 2nd encoder ( optional ) + UCHAR uc2ndEncoderID; + UCHAR ucReserved; +}ASIC_TRANSMITTER_INFO; + +#define ASIC_TRANSMITTER_INFO_CONFIG__DVO_SDR_MODE 0x01 +#define ASIC_TRANSMITTER_INFO_CONFIG__COHERENT_MODE 0x02 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODEROBJ_ID_MASK 0xc4 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_A 0x00 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_B 0x04 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_C 0x40 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_D 0x44 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_E 0x80 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_F 0x84 + +typedef struct _ASIC_ENCODER_INFO +{ + UCHAR ucEncoderID; + UCHAR ucEncoderConfig; + USHORT usEncoderCmdTblId; +}ASIC_ENCODER_INFO; + +typedef struct _ATOM_DISP_OUT_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT ptrTransmitterInfo; + USHORT ptrEncoderInfo; + ASIC_TRANSMITTER_INFO asTransmitterInfo[1]; + ASIC_ENCODER_INFO asEncoderInfo[1]; +}ATOM_DISP_OUT_INFO; + +typedef struct _ATOM_DISP_OUT_INFO_V2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT ptrTransmitterInfo; + USHORT ptrEncoderInfo; + USHORT ptrMainCallParserFar; // direct address of main parser call in VBIOS binary. + ASIC_TRANSMITTER_INFO asTransmitterInfo[1]; + ASIC_ENCODER_INFO asEncoderInfo[1]; +}ATOM_DISP_OUT_INFO_V2; + + +typedef struct _ATOM_DISP_CLOCK_ID { + UCHAR ucPpllId; + UCHAR ucPpllAttribute; +}ATOM_DISP_CLOCK_ID; + +// ucPpllAttribute +#define CLOCK_SOURCE_SHAREABLE 0x01 +#define CLOCK_SOURCE_DP_MODE 0x02 +#define CLOCK_SOURCE_NONE_DP_MODE 0x04 + +//DispOutInfoTable +typedef struct _ASIC_TRANSMITTER_INFO_V2 +{ + USHORT usTransmitterObjId; + USHORT usDispClkIdOffset; // point to clock source id list supported by Encoder Object + UCHAR ucTransmitterCmdTblId; + UCHAR ucConfig; + UCHAR ucEncoderID; // available 1st encoder ( default ) + UCHAR ucOptionEncoderID; // available 2nd encoder ( optional ) + UCHAR uc2ndEncoderID; + UCHAR ucReserved; +}ASIC_TRANSMITTER_INFO_V2; + +typedef struct _ATOM_DISP_OUT_INFO_V3 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT ptrTransmitterInfo; + USHORT ptrEncoderInfo; + USHORT ptrMainCallParserFar; // direct address of main parser call in VBIOS binary. + USHORT usReserved; + UCHAR ucDCERevision; + UCHAR ucMaxDispEngineNum; + UCHAR ucMaxActiveDispEngineNum; + UCHAR ucMaxPPLLNum; + UCHAR ucCoreRefClkSource; // value of CORE_REF_CLK_SOURCE + UCHAR ucReserved[3]; + ASIC_TRANSMITTER_INFO_V2 asTransmitterInfo[1]; // for alligment only +}ATOM_DISP_OUT_INFO_V3; + +typedef enum CORE_REF_CLK_SOURCE{ + CLOCK_SRC_XTALIN=0, + CLOCK_SRC_XO_IN=1, + CLOCK_SRC_XO_IN2=2, +}CORE_REF_CLK_SOURCE; + +// DispDevicePriorityInfo +typedef struct _ATOM_DISPLAY_DEVICE_PRIORITY_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT asDevicePriority[16]; +}ATOM_DISPLAY_DEVICE_PRIORITY_INFO; + +//ProcessAuxChannelTransactionTable +typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS +{ + USHORT lpAuxRequest; + USHORT lpDataOut; + UCHAR ucChannelID; + union + { + UCHAR ucReplyStatus; + UCHAR ucDelay; + }; + UCHAR ucDataOutLen; + UCHAR ucReserved; +}PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS; + +//ProcessAuxChannelTransactionTable +typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 +{ + USHORT lpAuxRequest; + USHORT lpDataOut; + UCHAR ucChannelID; + union + { + UCHAR ucReplyStatus; + UCHAR ucDelay; + }; + UCHAR ucDataOutLen; + UCHAR ucHPD_ID; //=0: HPD1, =1: HPD2, =2: HPD3, =3: HPD4, =4: HPD5, =5: HPD6 +}PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2; + +#define PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS + +//GetSinkType + +typedef struct _DP_ENCODER_SERVICE_PARAMETERS +{ + USHORT ucLinkClock; + union + { + UCHAR ucConfig; // for DP training command + UCHAR ucI2cId; // use for GET_SINK_TYPE command + }; + UCHAR ucAction; + UCHAR ucStatus; + UCHAR ucLaneNum; + UCHAR ucReserved[2]; +}DP_ENCODER_SERVICE_PARAMETERS; + +// ucAction +#define ATOM_DP_ACTION_GET_SINK_TYPE 0x01 +/* obselete */ +#define ATOM_DP_ACTION_TRAINING_START 0x02 +#define ATOM_DP_ACTION_TRAINING_COMPLETE 0x03 +#define ATOM_DP_ACTION_TRAINING_PATTERN_SEL 0x04 +#define ATOM_DP_ACTION_SET_VSWING_PREEMP 0x05 +#define ATOM_DP_ACTION_GET_VSWING_PREEMP 0x06 +#define ATOM_DP_ACTION_BLANKING 0x07 + +// ucConfig +#define ATOM_DP_CONFIG_ENCODER_SEL_MASK 0x03 +#define ATOM_DP_CONFIG_DIG1_ENCODER 0x00 +#define ATOM_DP_CONFIG_DIG2_ENCODER 0x01 +#define ATOM_DP_CONFIG_EXTERNAL_ENCODER 0x02 +#define ATOM_DP_CONFIG_LINK_SEL_MASK 0x04 +#define ATOM_DP_CONFIG_LINK_A 0x00 +#define ATOM_DP_CONFIG_LINK_B 0x04 +/* /obselete */ +#define DP_ENCODER_SERVICE_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS + + +typedef struct _DP_ENCODER_SERVICE_PARAMETERS_V2 +{ + USHORT usExtEncoderObjId; // External Encoder Object Id, output parameter only, use when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION + UCHAR ucAuxId; + UCHAR ucAction; + UCHAR ucSinkType; // Iput and Output parameters. + UCHAR ucHPDId; // Input parameter, used when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION + UCHAR ucReserved[2]; +}DP_ENCODER_SERVICE_PARAMETERS_V2; + +typedef struct _DP_ENCODER_SERVICE_PS_ALLOCATION_V2 +{ + DP_ENCODER_SERVICE_PARAMETERS_V2 asDPServiceParam; + PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 asAuxParam; +}DP_ENCODER_SERVICE_PS_ALLOCATION_V2; + +// ucAction +#define DP_SERVICE_V2_ACTION_GET_SINK_TYPE 0x01 +#define DP_SERVICE_V2_ACTION_DET_LCD_CONNECTION 0x02 + + +// DP_TRAINING_TABLE +#define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR ATOM_DP_TRAINING_TBL_ADDR +#define DPCD_SET_SS_CNTL_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 8 ) +#define DPCD_SET_LANE_VSWING_PREEMP_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 16 ) +#define DPCD_SET_TRAINING_PATTERN0_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 24 ) +#define DPCD_SET_TRAINING_PATTERN2_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 32) +#define DPCD_GET_LINKRATE_LANENUM_SS_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 40) +#define DPCD_GET_LANE_STATUS_ADJUST_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 48) +#define DP_I2C_AUX_DDC_WRITE_START_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 60) +#define DP_I2C_AUX_DDC_WRITE_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 64) +#define DP_I2C_AUX_DDC_READ_START_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 72) +#define DP_I2C_AUX_DDC_READ_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 76) +#define DP_I2C_AUX_DDC_WRITE_END_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 80) +#define DP_I2C_AUX_DDC_READ_END_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 84) + +typedef struct _PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS +{ + UCHAR ucI2CSpeed; + union + { + UCHAR ucRegIndex; + UCHAR ucStatus; + }; + USHORT lpI2CDataOut; + UCHAR ucFlag; + UCHAR ucTransBytes; + UCHAR ucSlaveAddr; + UCHAR ucLineNumber; +}PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS; + +#define PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS + +//ucFlag +#define HW_I2C_WRITE 1 +#define HW_I2C_READ 0 +#define I2C_2BYTE_ADDR 0x02 + +/****************************************************************************/ +// Structures used by HW_Misc_OperationTable +/****************************************************************************/ +typedef struct _ATOM_HW_MISC_OPERATION_INPUT_PARAMETER_V1_1 +{ + UCHAR ucCmd; // Input: To tell which action to take + UCHAR ucReserved[3]; + ULONG ulReserved; +}ATOM_HW_MISC_OPERATION_INPUT_PARAMETER_V1_1; + +typedef struct _ATOM_HW_MISC_OPERATION_OUTPUT_PARAMETER_V1_1 +{ + UCHAR ucReturnCode; // Output: Return value base on action was taken + UCHAR ucReserved[3]; + ULONG ulReserved; +}ATOM_HW_MISC_OPERATION_OUTPUT_PARAMETER_V1_1; + +// Actions code +#define ATOM_GET_SDI_SUPPORT 0xF0 + +// Return code +#define ATOM_UNKNOWN_CMD 0 +#define ATOM_FEATURE_NOT_SUPPORTED 1 +#define ATOM_FEATURE_SUPPORTED 2 + +typedef struct _ATOM_HW_MISC_OPERATION_PS_ALLOCATION +{ + ATOM_HW_MISC_OPERATION_INPUT_PARAMETER_V1_1 sInput_Output; + PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS sReserved; +}ATOM_HW_MISC_OPERATION_PS_ALLOCATION; + +/****************************************************************************/ + +typedef struct _SET_HWBLOCK_INSTANCE_PARAMETER_V2 +{ + UCHAR ucHWBlkInst; // HW block instance, 0, 1, 2, ... + UCHAR ucReserved[3]; +}SET_HWBLOCK_INSTANCE_PARAMETER_V2; + +#define HWBLKINST_INSTANCE_MASK 0x07 +#define HWBLKINST_HWBLK_MASK 0xF0 +#define HWBLKINST_HWBLK_SHIFT 0x04 + +//ucHWBlock +#define SELECT_DISP_ENGINE 0 +#define SELECT_DISP_PLL 1 +#define SELECT_DCIO_UNIPHY_LINK0 2 +#define SELECT_DCIO_UNIPHY_LINK1 3 +#define SELECT_DCIO_IMPCAL 4 +#define SELECT_DCIO_DIG 6 +#define SELECT_CRTC_PIXEL_RATE 7 +#define SELECT_VGA_BLK 8 + +// DIGTransmitterInfoTable structure used to program UNIPHY settings +typedef struct _DIG_TRANSMITTER_INFO_HEADER_V3_1{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usDPVsPreEmphSettingOffset; // offset of PHY_ANALOG_SETTING_INFO * with DP Voltage Swing and Pre-Emphasis for each Link clock + USHORT usPhyAnalogRegListOffset; // offset of CLOCK_CONDITION_REGESTER_INFO* with None-DP mode Analog Setting's register Info + USHORT usPhyAnalogSettingOffset; // offset of CLOCK_CONDITION_SETTING_ENTRY* with None-DP mode Analog Setting for each link clock range + USHORT usPhyPllRegListOffset; // offset of CLOCK_CONDITION_REGESTER_INFO* with Phy Pll register Info + USHORT usPhyPllSettingOffset; // offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy Pll Settings +}DIG_TRANSMITTER_INFO_HEADER_V3_1; + +typedef struct _CLOCK_CONDITION_REGESTER_INFO{ + USHORT usRegisterIndex; + UCHAR ucStartBit; + UCHAR ucEndBit; +}CLOCK_CONDITION_REGESTER_INFO; + +typedef struct _CLOCK_CONDITION_SETTING_ENTRY{ + USHORT usMaxClockFreq; + UCHAR ucEncodeMode; + UCHAR ucPhySel; + ULONG ulAnalogSetting[1]; +}CLOCK_CONDITION_SETTING_ENTRY; + +typedef struct _CLOCK_CONDITION_SETTING_INFO{ + USHORT usEntrySize; + CLOCK_CONDITION_SETTING_ENTRY asClkCondSettingEntry[1]; +}CLOCK_CONDITION_SETTING_INFO; + +typedef struct _PHY_CONDITION_REG_VAL{ + ULONG ulCondition; + ULONG ulRegVal; +}PHY_CONDITION_REG_VAL; + +typedef struct _PHY_CONDITION_REG_INFO{ + USHORT usRegIndex; + USHORT usSize; + PHY_CONDITION_REG_VAL asRegVal[1]; +}PHY_CONDITION_REG_INFO; + +typedef struct _PHY_ANALOG_SETTING_INFO{ + UCHAR ucEncodeMode; + UCHAR ucPhySel; + USHORT usSize; + PHY_CONDITION_REG_INFO asAnalogSetting[1]; +}PHY_ANALOG_SETTING_INFO; + +/****************************************************************************/ +//Portion VI: Definitinos for vbios MC scratch registers that driver used +/****************************************************************************/ + +#define MC_MISC0__MEMORY_TYPE_MASK 0xF0000000 +#define MC_MISC0__MEMORY_TYPE__GDDR1 0x10000000 +#define MC_MISC0__MEMORY_TYPE__DDR2 0x20000000 +#define MC_MISC0__MEMORY_TYPE__GDDR3 0x30000000 +#define MC_MISC0__MEMORY_TYPE__GDDR4 0x40000000 +#define MC_MISC0__MEMORY_TYPE__GDDR5 0x50000000 +#define MC_MISC0__MEMORY_TYPE__DDR3 0xB0000000 + +/****************************************************************************/ +//Portion VI: Definitinos being oboselete +/****************************************************************************/ + +//========================================================================================== +//Remove the definitions below when driver is ready! +typedef struct _ATOM_DAC_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMaxFrequency; // in 10kHz unit + USHORT usReserved; +}ATOM_DAC_INFO; + + +typedef struct _COMPASSIONATE_DATA +{ + ATOM_COMMON_TABLE_HEADER sHeader; + + //============================== DAC1 portion + UCHAR ucDAC1_BG_Adjustment; + UCHAR ucDAC1_DAC_Adjustment; + USHORT usDAC1_FORCE_Data; + //============================== DAC2 portion + UCHAR ucDAC2_CRT2_BG_Adjustment; + UCHAR ucDAC2_CRT2_DAC_Adjustment; + USHORT usDAC2_CRT2_FORCE_Data; + USHORT usDAC2_CRT2_MUX_RegisterIndex; + UCHAR ucDAC2_CRT2_MUX_RegisterInfo; //Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low + UCHAR ucDAC2_NTSC_BG_Adjustment; + UCHAR ucDAC2_NTSC_DAC_Adjustment; + USHORT usDAC2_TV1_FORCE_Data; + USHORT usDAC2_TV1_MUX_RegisterIndex; + UCHAR ucDAC2_TV1_MUX_RegisterInfo; //Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low + UCHAR ucDAC2_CV_BG_Adjustment; + UCHAR ucDAC2_CV_DAC_Adjustment; + USHORT usDAC2_CV_FORCE_Data; + USHORT usDAC2_CV_MUX_RegisterIndex; + UCHAR ucDAC2_CV_MUX_RegisterInfo; //Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low + UCHAR ucDAC2_PAL_BG_Adjustment; + UCHAR ucDAC2_PAL_DAC_Adjustment; + USHORT usDAC2_TV2_FORCE_Data; +}COMPASSIONATE_DATA; + +/****************************Supported Device Info Table Definitions**********************/ +// ucConnectInfo: +// [7:4] - connector type +// = 1 - VGA connector +// = 2 - DVI-I +// = 3 - DVI-D +// = 4 - DVI-A +// = 5 - SVIDEO +// = 6 - COMPOSITE +// = 7 - LVDS +// = 8 - DIGITAL LINK +// = 9 - SCART +// = 0xA - HDMI_type A +// = 0xB - HDMI_type B +// = 0xE - Special case1 (DVI+DIN) +// Others=TBD +// [3:0] - DAC Associated +// = 0 - no DAC +// = 1 - DACA +// = 2 - DACB +// = 3 - External DAC +// Others=TBD +// + +typedef struct _ATOM_CONNECTOR_INFO +{ +#if ATOM_BIG_ENDIAN + UCHAR bfConnectorType:4; + UCHAR bfAssociatedDAC:4; +#else + UCHAR bfAssociatedDAC:4; + UCHAR bfConnectorType:4; +#endif +}ATOM_CONNECTOR_INFO; + +typedef union _ATOM_CONNECTOR_INFO_ACCESS +{ + ATOM_CONNECTOR_INFO sbfAccess; + UCHAR ucAccess; +}ATOM_CONNECTOR_INFO_ACCESS; + +typedef struct _ATOM_CONNECTOR_INFO_I2C +{ + ATOM_CONNECTOR_INFO_ACCESS sucConnectorInfo; + ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; +}ATOM_CONNECTOR_INFO_I2C; + + +typedef struct _ATOM_SUPPORTED_DEVICES_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usDeviceSupport; + ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO]; +}ATOM_SUPPORTED_DEVICES_INFO; + +#define NO_INT_SRC_MAPPED 0xFF + +typedef struct _ATOM_CONNECTOR_INC_SRC_BITMAP +{ + UCHAR ucIntSrcBitmap; +}ATOM_CONNECTOR_INC_SRC_BITMAP; + +typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usDeviceSupport; + ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2]; + ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2]; +}ATOM_SUPPORTED_DEVICES_INFO_2; + +typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usDeviceSupport; + ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE]; + ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE]; +}ATOM_SUPPORTED_DEVICES_INFO_2d1; + +#define ATOM_SUPPORTED_DEVICES_INFO_LAST ATOM_SUPPORTED_DEVICES_INFO_2d1 + + + +typedef struct _ATOM_MISC_CONTROL_INFO +{ + USHORT usFrequency; + UCHAR ucPLL_ChargePump; // PLL charge-pump gain control + UCHAR ucPLL_DutyCycle; // PLL duty cycle control + UCHAR ucPLL_VCO_Gain; // PLL VCO gain control + UCHAR ucPLL_VoltageSwing; // PLL driver voltage swing control +}ATOM_MISC_CONTROL_INFO; + + +#define ATOM_MAX_MISC_INFO 4 + +typedef struct _ATOM_TMDS_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMaxFrequency; // in 10Khz + ATOM_MISC_CONTROL_INFO asMiscInfo[ATOM_MAX_MISC_INFO]; +}ATOM_TMDS_INFO; + + +typedef struct _ATOM_ENCODER_ANALOG_ATTRIBUTE +{ + UCHAR ucTVStandard; //Same as TV standards defined above, + UCHAR ucPadding[1]; +}ATOM_ENCODER_ANALOG_ATTRIBUTE; + +typedef struct _ATOM_ENCODER_DIGITAL_ATTRIBUTE +{ + UCHAR ucAttribute; //Same as other digital encoder attributes defined above + UCHAR ucPadding[1]; +}ATOM_ENCODER_DIGITAL_ATTRIBUTE; + +typedef union _ATOM_ENCODER_ATTRIBUTE +{ + ATOM_ENCODER_ANALOG_ATTRIBUTE sAlgAttrib; + ATOM_ENCODER_DIGITAL_ATTRIBUTE sDigAttrib; +}ATOM_ENCODER_ATTRIBUTE; + + +typedef struct _DVO_ENCODER_CONTROL_PARAMETERS +{ + USHORT usPixelClock; + USHORT usEncoderID; + UCHAR ucDeviceType; //Use ATOM_DEVICE_xxx1_Index to indicate device type only. + UCHAR ucAction; //ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT + ATOM_ENCODER_ATTRIBUTE usDevAttr; +}DVO_ENCODER_CONTROL_PARAMETERS; + +typedef struct _DVO_ENCODER_CONTROL_PS_ALLOCATION +{ + DVO_ENCODER_CONTROL_PARAMETERS sDVOEncoder; + WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; //Caller doesn't need to init this portion +}DVO_ENCODER_CONTROL_PS_ALLOCATION; + + +#define ATOM_XTMDS_ASIC_SI164_ID 1 +#define ATOM_XTMDS_ASIC_SI178_ID 2 +#define ATOM_XTMDS_ASIC_TFP513_ID 3 +#define ATOM_XTMDS_SUPPORTED_SINGLELINK 0x00000001 +#define ATOM_XTMDS_SUPPORTED_DUALLINK 0x00000002 +#define ATOM_XTMDS_MVPU_FPGA 0x00000004 + + +typedef struct _ATOM_XTMDS_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usSingleLinkMaxFrequency; + ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; //Point the ID on which I2C is used to control external chip + UCHAR ucXtransimitterID; + UCHAR ucSupportedLink; // Bit field, bit0=1, single link supported;bit1=1,dual link supported + UCHAR ucSequnceAlterID; // Even with the same external TMDS asic, it's possible that the program seqence alters + // due to design. This ID is used to alert driver that the sequence is not "standard"! + UCHAR ucMasterAddress; // Address to control Master xTMDS Chip + UCHAR ucSlaveAddress; // Address to control Slave xTMDS Chip +}ATOM_XTMDS_INFO; + +typedef struct _DFP_DPMS_STATUS_CHANGE_PARAMETERS +{ + UCHAR ucEnable; // ATOM_ENABLE=On or ATOM_DISABLE=Off + UCHAR ucDevice; // ATOM_DEVICE_DFP1_INDEX.... + UCHAR ucPadding[2]; +}DFP_DPMS_STATUS_CHANGE_PARAMETERS; + +/****************************Legacy Power Play Table Definitions **********************/ + +//Definitions for ulPowerPlayMiscInfo +#define ATOM_PM_MISCINFO_SPLIT_CLOCK 0x00000000L +#define ATOM_PM_MISCINFO_USING_MCLK_SRC 0x00000001L +#define ATOM_PM_MISCINFO_USING_SCLK_SRC 0x00000002L + +#define ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT 0x00000004L +#define ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH 0x00000008L + +#define ATOM_PM_MISCINFO_LOAD_PERFORMANCE_EN 0x00000010L + +#define ATOM_PM_MISCINFO_ENGINE_CLOCK_CONTRL_EN 0x00000020L +#define ATOM_PM_MISCINFO_MEMORY_CLOCK_CONTRL_EN 0x00000040L +#define ATOM_PM_MISCINFO_PROGRAM_VOLTAGE 0x00000080L //When this bit set, ucVoltageDropIndex is not an index for GPIO pin, but a voltage ID that SW needs program + +#define ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN 0x00000100L +#define ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN 0x00000200L +#define ATOM_PM_MISCINFO_ASIC_SLEEP_MODE_EN 0x00000400L +#define ATOM_PM_MISCINFO_LOAD_BALANCE_EN 0x00000800L +#define ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE 0x00001000L +#define ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE 0x00002000L +#define ATOM_PM_MISCINFO_LOW_LCD_REFRESH_RATE 0x00004000L + +#define ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE 0x00008000L +#define ATOM_PM_MISCINFO_OVER_CLOCK_MODE 0x00010000L +#define ATOM_PM_MISCINFO_OVER_DRIVE_MODE 0x00020000L +#define ATOM_PM_MISCINFO_POWER_SAVING_MODE 0x00040000L +#define ATOM_PM_MISCINFO_THERMAL_DIODE_MODE 0x00080000L + +#define ATOM_PM_MISCINFO_FRAME_MODULATION_MASK 0x00300000L //0-FM Disable, 1-2 level FM, 2-4 level FM, 3-Reserved +#define ATOM_PM_MISCINFO_FRAME_MODULATION_SHIFT 20 + +#define ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE 0x00400000L +#define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2 0x00800000L +#define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4 0x01000000L +#define ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN 0x02000000L //When set, Dynamic +#define ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN 0x04000000L //When set, Dynamic +#define ATOM_PM_MISCINFO_3D_ACCELERATION_EN 0x08000000L //When set, This mode is for acceleated 3D mode + +#define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_MASK 0x70000000L //1-Optimal Battery Life Group, 2-High Battery, 3-Balanced, 4-High Performance, 5- Optimal Performance (Default state with Default clocks) +#define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_SHIFT 28 +#define ATOM_PM_MISCINFO_ENABLE_BACK_BIAS 0x80000000L + +#define ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE 0x00000001L +#define ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT 0x00000002L +#define ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN 0x00000004L +#define ATOM_PM_MISCINFO2_FS3D_OVERDRIVE_INFO 0x00000008L +#define ATOM_PM_MISCINFO2_FORCEDLOWPWR_MODE 0x00000010L +#define ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN 0x00000020L +#define ATOM_PM_MISCINFO2_VIDEO_PLAYBACK_CAPABLE 0x00000040L //If this bit is set in multi-pp mode, then driver will pack up one with the minior power consumption. + //If it's not set in any pp mode, driver will use its default logic to pick a pp mode in video playback +#define ATOM_PM_MISCINFO2_NOT_VALID_ON_DC 0x00000080L +#define ATOM_PM_MISCINFO2_STUTTER_MODE_EN 0x00000100L +#define ATOM_PM_MISCINFO2_UVD_SUPPORT_MODE 0x00000200L + +//ucTableFormatRevision=1 +//ucTableContentRevision=1 +typedef struct _ATOM_POWERMODE_INFO +{ + ULONG ulMiscInfo; //The power level should be arranged in ascending order + ULONG ulReserved1; // must set to 0 + ULONG ulReserved2; // must set to 0 + USHORT usEngineClock; + USHORT usMemoryClock; + UCHAR ucVoltageDropIndex; // index to GPIO table + UCHAR ucSelectedPanel_RefreshRate;// panel refresh rate + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + UCHAR ucNumPciELanes; // number of PCIE lanes +}ATOM_POWERMODE_INFO; + +//ucTableFormatRevision=2 +//ucTableContentRevision=1 +typedef struct _ATOM_POWERMODE_INFO_V2 +{ + ULONG ulMiscInfo; //The power level should be arranged in ascending order + ULONG ulMiscInfo2; + ULONG ulEngineClock; + ULONG ulMemoryClock; + UCHAR ucVoltageDropIndex; // index to GPIO table + UCHAR ucSelectedPanel_RefreshRate;// panel refresh rate + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + UCHAR ucNumPciELanes; // number of PCIE lanes +}ATOM_POWERMODE_INFO_V2; + +//ucTableFormatRevision=2 +//ucTableContentRevision=2 +typedef struct _ATOM_POWERMODE_INFO_V3 +{ + ULONG ulMiscInfo; //The power level should be arranged in ascending order + ULONG ulMiscInfo2; + ULONG ulEngineClock; + ULONG ulMemoryClock; + UCHAR ucVoltageDropIndex; // index to Core (VDDC) votage table + UCHAR ucSelectedPanel_RefreshRate;// panel refresh rate + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + UCHAR ucNumPciELanes; // number of PCIE lanes + UCHAR ucVDDCI_VoltageDropIndex; // index to VDDCI votage table +}ATOM_POWERMODE_INFO_V3; + + +#define ATOM_MAX_NUMBEROF_POWER_BLOCK 8 + +#define ATOM_PP_OVERDRIVE_INTBITMAP_AUXWIN 0x01 +#define ATOM_PP_OVERDRIVE_INTBITMAP_OVERDRIVE 0x02 + +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM63 0x01 +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ADM1032 0x02 +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ADM1030 0x03 +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_MUA6649 0x04 +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM64 0x05 +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_F75375 0x06 +#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ASC7512 0x07 // Andigilog + + +typedef struct _ATOM_POWERPLAY_INFO +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucOverdriveThermalController; + UCHAR ucOverdriveI2cLine; + UCHAR ucOverdriveIntBitmap; + UCHAR ucOverdriveControllerAddress; + UCHAR ucSizeOfPowerModeEntry; + UCHAR ucNumOfPowerModeEntries; + ATOM_POWERMODE_INFO asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; +}ATOM_POWERPLAY_INFO; + +typedef struct _ATOM_POWERPLAY_INFO_V2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucOverdriveThermalController; + UCHAR ucOverdriveI2cLine; + UCHAR ucOverdriveIntBitmap; + UCHAR ucOverdriveControllerAddress; + UCHAR ucSizeOfPowerModeEntry; + UCHAR ucNumOfPowerModeEntries; + ATOM_POWERMODE_INFO_V2 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; +}ATOM_POWERPLAY_INFO_V2; + +typedef struct _ATOM_POWERPLAY_INFO_V3 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR ucOverdriveThermalController; + UCHAR ucOverdriveI2cLine; + UCHAR ucOverdriveIntBitmap; + UCHAR ucOverdriveControllerAddress; + UCHAR ucSizeOfPowerModeEntry; + UCHAR ucNumOfPowerModeEntries; + ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; +}ATOM_POWERPLAY_INFO_V3; + +/* New PPlib */ +/**************************************************************************/ +typedef struct _ATOM_PPLIB_THERMALCONTROLLER + +{ + UCHAR ucType; // one of ATOM_PP_THERMALCONTROLLER_* + UCHAR ucI2cLine; // as interpreted by DAL I2C + UCHAR ucI2cAddress; + UCHAR ucFanParameters; // Fan Control Parameters. + UCHAR ucFanMinRPM; // Fan Minimum RPM (hundreds) -- for display purposes only. + UCHAR ucFanMaxRPM; // Fan Maximum RPM (hundreds) -- for display purposes only. + UCHAR ucReserved; // ---- + UCHAR ucFlags; // to be defined +} ATOM_PPLIB_THERMALCONTROLLER; + +#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_PP_FANPARAMETERS_NOFAN 0x80 // No fan is connected to this controller. + +#define ATOM_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_PP_THERMALCONTROLLER_LM63 1 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1032 2 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1030 3 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_MUA6649 4 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_LM64 5 +#define ATOM_PP_THERMALCONTROLLER_F75375 6 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_RV6xx 7 +#define ATOM_PP_THERMALCONTROLLER_RV770 8 +#define ATOM_PP_THERMALCONTROLLER_ADT7473 9 +#define ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO 11 +#define ATOM_PP_THERMALCONTROLLER_EVERGREEN 12 +#define ATOM_PP_THERMALCONTROLLER_EMC2103 13 /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen. +#define ATOM_PP_THERMALCONTROLLER_SUMO 14 /* 0x0E */ // Sumo type, used internally +#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15 +#define ATOM_PP_THERMALCONTROLLER_SISLANDS 16 +#define ATOM_PP_THERMALCONTROLLER_LM96163 17 + +// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. +// We probably should reserve the bit 0x80 for this use. +// To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). +// The driver can pick the correct internal controller based on the ASIC. + +#define ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 // ADT7473 Fan Control + Internal Thermal Controller +#define ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D // EMC2103 Fan Control + Internal Thermal Controller + +typedef struct _ATOM_PPLIB_STATE +{ + UCHAR ucNonClockStateIndex; + UCHAR ucClockStateIndices[1]; // variable-sized +} ATOM_PPLIB_STATE; + + +typedef struct _ATOM_PPLIB_FANTABLE +{ + UCHAR ucFanTableFormat; // Change this if the table format changes or version changes so that the other fields are not the same. + UCHAR ucTHyst; // Temperature hysteresis. Integer. + USHORT usTMin; // The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. + USHORT usTMed; // The middle temperature where we change slopes. + USHORT usTHigh; // The high point above TMed for adjusting the second slope. + USHORT usPWMMin; // The minimum PWM value in percent (0.01% increments). + USHORT usPWMMed; // The PWM value (in percent) at TMed. + USHORT usPWMHigh; // The PWM value at THigh. +} ATOM_PPLIB_FANTABLE; + +typedef struct _ATOM_PPLIB_FANTABLE2 +{ + ATOM_PPLIB_FANTABLE basicTable; + USHORT usTMax; // The max temperature +} ATOM_PPLIB_FANTABLE2; + +typedef struct _ATOM_PPLIB_EXTENDEDHEADER +{ + USHORT usSize; + ULONG ulMaxEngineClock; // For Overdrive. + ULONG ulMaxMemoryClock; // For Overdrive. + // Add extra system parameters here, always adjust size to include all fields. + USHORT usVCETableOffset; //points to ATOM_PPLIB_VCE_Table + USHORT usUVDTableOffset; //points to ATOM_PPLIB_UVD_Table +} ATOM_PPLIB_EXTENDEDHEADER; + +//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps +#define ATOM_PP_PLATFORM_CAP_BACKBIAS 1 +#define ATOM_PP_PLATFORM_CAP_POWERPLAY 2 +#define ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 4 +#define ATOM_PP_PLATFORM_CAP_ASPM_L0s 8 +#define ATOM_PP_PLATFORM_CAP_ASPM_L1 16 +#define ATOM_PP_PLATFORM_CAP_HARDWAREDC 32 +#define ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY 64 +#define ATOM_PP_PLATFORM_CAP_STEPVDDC 128 +#define ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL 256 +#define ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL 512 +#define ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 1024 +#define ATOM_PP_PLATFORM_CAP_HTLINKCONTROL 2048 +#define ATOM_PP_PLATFORM_CAP_MVDDCONTROL 4096 +#define ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT 0x2000 // Go to boot state on alerts, e.g. on an AC->DC transition. +#define ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT 0x4000 // Do NOT wait for VBLANK during an alert (e.g. AC->DC transition). +#define ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 // Does the driver control VDDCI independently from VDDC. +#define ATOM_PP_PLATFORM_CAP_REGULATOR_HOT 0x00010000 // Enable the 'regulator hot' feature. +#define ATOM_PP_PLATFORM_CAP_BACO 0x00020000 // Does the driver supports BACO state. + + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucDataRevision; + + UCHAR ucNumStates; + UCHAR ucStateEntrySize; + UCHAR ucClockInfoSize; + UCHAR ucNonClockSize; + + // offset from start of this table to array of ucNumStates ATOM_PPLIB_STATE structures + USHORT usStateArrayOffset; + + // offset from start of this table to array of ASIC-specific structures, + // currently ATOM_PPLIB_CLOCK_INFO. + USHORT usClockInfoArrayOffset; + + // offset from start of this table to array of ATOM_PPLIB_NONCLOCK_INFO + USHORT usNonClockInfoArrayOffset; + + USHORT usBackbiasTime; // in microseconds + USHORT usVoltageTime; // in microseconds + USHORT usTableSize; //the size of this structure, or the extended structure + + ULONG ulPlatformCaps; // See ATOM_PPLIB_CAPS_* + + ATOM_PPLIB_THERMALCONTROLLER sThermalController; + + USHORT usBootClockInfoOffset; + USHORT usBootNonClockInfoOffset; + +} ATOM_PPLIB_POWERPLAYTABLE; + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE2 +{ + ATOM_PPLIB_POWERPLAYTABLE basicTable; + UCHAR ucNumCustomThermalPolicy; + USHORT usCustomThermalPolicyArrayOffset; +}ATOM_PPLIB_POWERPLAYTABLE2, *LPATOM_PPLIB_POWERPLAYTABLE2; + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE3 +{ + ATOM_PPLIB_POWERPLAYTABLE2 basicTable2; + USHORT usFormatID; // To be used ONLY by PPGen. + USHORT usFanTableOffset; + USHORT usExtendendedHeaderOffset; +} ATOM_PPLIB_POWERPLAYTABLE3, *LPATOM_PPLIB_POWERPLAYTABLE3; + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE4 +{ + ATOM_PPLIB_POWERPLAYTABLE3 basicTable3; + ULONG ulGoldenPPID; // PPGen use only + ULONG ulGoldenRevision; // PPGen use only + USHORT usVddcDependencyOnSCLKOffset; + USHORT usVddciDependencyOnMCLKOffset; + USHORT usVddcDependencyOnMCLKOffset; + USHORT usMaxClockVoltageOnDCOffset; + USHORT usVddcPhaseShedLimitsTableOffset; // Points to ATOM_PPLIB_PhaseSheddingLimits_Table + USHORT usReserved; +} ATOM_PPLIB_POWERPLAYTABLE4, *LPATOM_PPLIB_POWERPLAYTABLE4; + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 +{ + ATOM_PPLIB_POWERPLAYTABLE4 basicTable4; + ULONG ulTDPLimit; + ULONG ulNearTDPLimit; + ULONG ulSQRampingThreshold; + USHORT usCACLeakageTableOffset; // Points to ATOM_PPLIB_CAC_Leakage_Table + ULONG ulCACLeakage; // The iLeakage for driver calculated CAC leakage table + USHORT usTDPODLimit; + USHORT usLoadLineSlope; // in milliOhms * 100 +} ATOM_PPLIB_POWERPLAYTABLE5, *LPATOM_PPLIB_POWERPLAYTABLE5; + +//// ATOM_PPLIB_NONCLOCK_INFO::usClassification +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +// 2, 4, 6, 7 are reserved + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE 0x0100 +#define ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE 0x0200 +#define ATOM_PPLIB_CLASSIFICATION_UVDSTATE 0x0400 +#define ATOM_PPLIB_CLASSIFICATION_3DLOW 0x0800 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 +#define ATOM_PPLIB_CLASSIFICATION_HD2STATE 0x2000 +#define ATOM_PPLIB_CLASSIFICATION_HDSTATE 0x4000 +#define ATOM_PPLIB_CLASSIFICATION_SDSTATE 0x8000 + +//// ATOM_PPLIB_NONCLOCK_INFO::usClassification2 +#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 +#define ATOM_PPLIB_CLASSIFICATION2_ULV 0x0002 +#define ATOM_PPLIB_CLASSIFICATION2_MVC 0x0004 //Multi-View Codec (BD-3D) + +//// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings +#define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 +#define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK 0x00000002 + +// 0 is 2.5Gb/s, 1 is 5Gb/s +#define ATOM_PPLIB_PCIE_LINK_SPEED_MASK 0x00000004 +#define ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT 2 + +// lanes - 1: 1, 2, 4, 8, 12, 16 permitted by PCIE spec +#define ATOM_PPLIB_PCIE_LINK_WIDTH_MASK 0x000000F8 +#define ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT 3 + +// lookup into reduced refresh-rate table +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK 0x00000F00 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT 8 + +#define ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED 0 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_50HZ 1 +// 2-15 TBD as needed. + +#define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING 0x00001000 +#define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS 0x00002000 + +#define ATOM_PPLIB_DISALLOW_ON_DC 0x00004000 + +#define ATOM_PPLIB_ENABLE_VARIBRIGHT 0x00008000 + +//memory related flags +#define ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF 0x000010000 + +//M3 Arb //2bits, current 3 sets of parameters in total +#define ATOM_PPLIB_M3ARB_MASK 0x00060000 +#define ATOM_PPLIB_M3ARB_SHIFT 17 + +#define ATOM_PPLIB_ENABLE_DRR 0x00080000 + +// remaining 16 bits are reserved +typedef struct _ATOM_PPLIB_THERMAL_STATE +{ + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + UCHAR ucThermalAction; +}ATOM_PPLIB_THERMAL_STATE, *LPATOM_PPLIB_THERMAL_STATE; + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex +#define ATOM_PPLIB_NONCLOCKINFO_VER1 12 +#define ATOM_PPLIB_NONCLOCKINFO_VER2 24 +typedef struct _ATOM_PPLIB_NONCLOCK_INFO +{ + USHORT usClassification; + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + ULONG ulCapsAndSettings; + UCHAR ucRequiredPower; + USHORT usClassification2; + ULONG ulVCLK; + ULONG ulDCLK; + UCHAR ucUnused[5]; +} ATOM_PPLIB_NONCLOCK_INFO; + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE::ucClockStateIndices +typedef struct _ATOM_PPLIB_R600_CLOCK_INFO +{ + USHORT usEngineClockLow; + UCHAR ucEngineClockHigh; + + USHORT usMemoryClockLow; + UCHAR ucMemoryClockHigh; + + USHORT usVDDC; + USHORT usUnused1; + USHORT usUnused2; + + ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_* + +} ATOM_PPLIB_R600_CLOCK_INFO; + +// ulFlags in ATOM_PPLIB_R600_CLOCK_INFO +#define ATOM_PPLIB_R600_FLAGS_PCIEGEN2 1 +#define ATOM_PPLIB_R600_FLAGS_UVDSAFE 2 +#define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE 4 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF 8 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF 16 +#define ATOM_PPLIB_R600_FLAGS_LOWPOWER 32 // On the RV770 use 'low power' setting (sequencer S0). + +typedef struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO +{ + USHORT usEngineClockLow; + UCHAR ucEngineClockHigh; + + USHORT usMemoryClockLow; + UCHAR ucMemoryClockHigh; + + USHORT usVDDC; + USHORT usVDDCI; + USHORT usUnused; + + ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_* + +} ATOM_PPLIB_EVERGREEN_CLOCK_INFO; + +typedef struct _ATOM_PPLIB_SI_CLOCK_INFO +{ + USHORT usEngineClockLow; + UCHAR ucEngineClockHigh; + + USHORT usMemoryClockLow; + UCHAR ucMemoryClockHigh; + + USHORT usVDDC; + USHORT usVDDCI; + UCHAR ucPCIEGen; + UCHAR ucUnused1; + + ULONG ulFlags; // ATOM_PPLIB_SI_FLAGS_*, no flag is necessary for now + +} ATOM_PPLIB_SI_CLOCK_INFO; + + +typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO + +{ + USHORT usLowEngineClockLow; // Low Engine clock in MHz (the same way as on the R600). + UCHAR ucLowEngineClockHigh; + USHORT usHighEngineClockLow; // High Engine clock in MHz. + UCHAR ucHighEngineClockHigh; + USHORT usMemoryClockLow; // For now one of the ATOM_PPLIB_RS780_SPMCLK_XXXX constants. + UCHAR ucMemoryClockHigh; // Currentyl unused. + UCHAR ucPadding; // For proper alignment and size. + USHORT usVDDC; // For the 780, use: None, Low, High, Variable + UCHAR ucMaxHTLinkWidth; // From SBIOS - {2, 4, 8, 16} + UCHAR ucMinHTLinkWidth; // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement. + USHORT usHTLinkFreq; // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200). + ULONG ulFlags; +} ATOM_PPLIB_RS780_CLOCK_INFO; + +#define ATOM_PPLIB_RS780_VOLTAGE_NONE 0 +#define ATOM_PPLIB_RS780_VOLTAGE_LOW 1 +#define ATOM_PPLIB_RS780_VOLTAGE_HIGH 2 +#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE 3 + +#define ATOM_PPLIB_RS780_SPMCLK_NONE 0 // We cannot change the side port memory clock, leave it as it is. +#define ATOM_PPLIB_RS780_SPMCLK_LOW 1 +#define ATOM_PPLIB_RS780_SPMCLK_HIGH 2 + +#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE 0 +#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW 1 +#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH 2 + +typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{ + USHORT usEngineClockLow; //clockfrequency & 0xFFFF. The unit is in 10khz + UCHAR ucEngineClockHigh; //clockfrequency >> 16. + UCHAR vddcIndex; //2-bit vddc index; + USHORT tdpLimit; + //please initalize to 0 + USHORT rsv1; + //please initialize to 0s + ULONG rsv2[2]; +}ATOM_PPLIB_SUMO_CLOCK_INFO; + + + +typedef struct _ATOM_PPLIB_STATE_V2 +{ + //number of valid dpm levels in this state; Driver uses it to calculate the whole + //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR) + UCHAR ucNumDPMLevels; + + //a index to the array of nonClockInfos + UCHAR nonClockInfoIndex; + /** + * Driver will read the first ucNumDPMLevels in this array + */ + UCHAR clockInfoIndex[1]; +} ATOM_PPLIB_STATE_V2; + +typedef struct _StateArray{ + //how many states we have + UCHAR ucNumEntries; + + ATOM_PPLIB_STATE_V2 states[1]; +}StateArray; + + +typedef struct _ClockInfoArray{ + //how many clock levels we have + UCHAR ucNumEntries; + + //sizeof(ATOM_PPLIB_CLOCK_INFO) + UCHAR ucEntrySize; + + UCHAR clockInfo[1]; +}ClockInfoArray; + +typedef struct _NonClockInfoArray{ + + //how many non-clock levels we have. normally should be same as number of states + UCHAR ucNumEntries; + //sizeof(ATOM_PPLIB_NONCLOCK_INFO) + UCHAR ucEntrySize; + + ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1]; +}NonClockInfoArray; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record +{ + USHORT usClockLow; + UCHAR ucClockHigh; + USHORT usVoltage; +}ATOM_PPLIB_Clock_Voltage_Dependency_Record; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Table +{ + UCHAR ucNumEntries; // Number of entries. + ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[1]; // Dynamically allocate entries. +}ATOM_PPLIB_Clock_Voltage_Dependency_Table; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record +{ + USHORT usSclkLow; + UCHAR ucSclkHigh; + USHORT usMclkLow; + UCHAR ucMclkHigh; + USHORT usVddc; + USHORT usVddci; +}ATOM_PPLIB_Clock_Voltage_Limit_Record; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table +{ + UCHAR ucNumEntries; // Number of entries. + ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1]; // Dynamically allocate entries. +}ATOM_PPLIB_Clock_Voltage_Limit_Table; + +typedef struct _ATOM_PPLIB_CAC_Leakage_Record +{ + USHORT usVddc; // We use this field for the "fake" standardized VDDC for power calculations + ULONG ulLeakageValue; +}ATOM_PPLIB_CAC_Leakage_Record; + +typedef struct _ATOM_PPLIB_CAC_Leakage_Table +{ + UCHAR ucNumEntries; // Number of entries. + ATOM_PPLIB_CAC_Leakage_Record entries[1]; // Dynamically allocate entries. +}ATOM_PPLIB_CAC_Leakage_Table; + +typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Record +{ + USHORT usVoltage; + USHORT usSclkLow; + UCHAR ucSclkHigh; + USHORT usMclkLow; + UCHAR ucMclkHigh; +}ATOM_PPLIB_PhaseSheddingLimits_Record; + +typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Table +{ + UCHAR ucNumEntries; // Number of entries. + ATOM_PPLIB_PhaseSheddingLimits_Record entries[1]; // Dynamically allocate entries. +}ATOM_PPLIB_PhaseSheddingLimits_Table; + +typedef struct _VCEClockInfo{ + USHORT usEVClkLow; + UCHAR ucEVClkHigh; + USHORT usECClkLow; + UCHAR ucECClkHigh; +}VCEClockInfo; + +typedef struct _VCEClockInfoArray{ + UCHAR ucNumEntries; + VCEClockInfo entries[1]; +}VCEClockInfoArray; + +typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record +{ + USHORT usVoltage; + UCHAR ucVCEClockInfoIndex; +}ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record; + +typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table +{ + UCHAR numEntries; + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record entries[1]; +}ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table; + +typedef struct _ATOM_PPLIB_VCE_State_Record +{ + UCHAR ucVCEClockInfoIndex; + UCHAR ucClockInfoIndex; //highest 2 bits indicates memory p-states, lower 6bits indicates index to ClockInfoArrary +}ATOM_PPLIB_VCE_State_Record; + +typedef struct _ATOM_PPLIB_VCE_State_Table +{ + UCHAR numEntries; + ATOM_PPLIB_VCE_State_Record entries[1]; +}ATOM_PPLIB_VCE_State_Table; + + +typedef struct _ATOM_PPLIB_VCE_Table +{ + UCHAR revid; +// VCEClockInfoArray array; +// ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table limits; +// ATOM_PPLIB_VCE_State_Table states; +}ATOM_PPLIB_VCE_Table; + + +typedef struct _UVDClockInfo{ + USHORT usVClkLow; + UCHAR ucVClkHigh; + USHORT usDClkLow; + UCHAR ucDClkHigh; +}UVDClockInfo; + +typedef struct _UVDClockInfoArray{ + UCHAR ucNumEntries; + UVDClockInfo entries[1]; +}UVDClockInfoArray; + +typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record +{ + USHORT usVoltage; + UCHAR ucUVDClockInfoIndex; +}ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record; + +typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table +{ + UCHAR numEntries; + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record entries[1]; +}ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table; + +typedef struct _ATOM_PPLIB_UVD_State_Record +{ + UCHAR ucUVDClockInfoIndex; + UCHAR ucClockInfoIndex; //highest 2 bits indicates memory p-states, lower 6bits indicates index to ClockInfoArrary +}ATOM_PPLIB_UVD_State_Record; + +typedef struct _ATOM_PPLIB_UVD_State_Table +{ + UCHAR numEntries; + ATOM_PPLIB_UVD_State_Record entries[1]; +}ATOM_PPLIB_UVD_State_Table; + + +typedef struct _ATOM_PPLIB_UVD_Table +{ + UCHAR revid; +// UVDClockInfoArray array; +// ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table limits; +// ATOM_PPLIB_UVD_State_Table states; +}ATOM_PPLIB_UVD_Table; + +/**************************************************************************/ + + +// Following definitions are for compatibility issue in different SW components. +#define ATOM_MASTER_DATA_TABLE_REVISION 0x01 +#define Object_Info Object_Header +#define AdjustARB_SEQ MC_InitParameter +#define VRAM_GPIO_DetectionInfo VoltageObjectInfo +#define ASIC_VDDCI_Info ASIC_ProfilingInfo +#define ASIC_MVDDQ_Info MemoryTrainingInfo +#define SS_Info PPLL_SS_Info +#define ASIC_MVDDC_Info ASIC_InternalSS_Info +#define DispDevicePriorityInfo SaveRestoreInfo +#define DispOutInfo TV_VideoMode + + +#define ATOM_ENCODER_OBJECT_TABLE ATOM_OBJECT_TABLE +#define ATOM_CONNECTOR_OBJECT_TABLE ATOM_OBJECT_TABLE + +//New device naming, remove them when both DAL/VBIOS is ready +#define DFP2I_OUTPUT_CONTROL_PARAMETERS CRT1_OUTPUT_CONTROL_PARAMETERS +#define DFP2I_OUTPUT_CONTROL_PS_ALLOCATION DFP2I_OUTPUT_CONTROL_PARAMETERS + +#define DFP1X_OUTPUT_CONTROL_PARAMETERS CRT1_OUTPUT_CONTROL_PARAMETERS +#define DFP1X_OUTPUT_CONTROL_PS_ALLOCATION DFP1X_OUTPUT_CONTROL_PARAMETERS + +#define DFP1I_OUTPUT_CONTROL_PARAMETERS DFP1_OUTPUT_CONTROL_PARAMETERS +#define DFP1I_OUTPUT_CONTROL_PS_ALLOCATION DFP1_OUTPUT_CONTROL_PS_ALLOCATION + +#define ATOM_DEVICE_DFP1I_SUPPORT ATOM_DEVICE_DFP1_SUPPORT +#define ATOM_DEVICE_DFP1X_SUPPORT ATOM_DEVICE_DFP2_SUPPORT + +#define ATOM_DEVICE_DFP1I_INDEX ATOM_DEVICE_DFP1_INDEX +#define ATOM_DEVICE_DFP1X_INDEX ATOM_DEVICE_DFP2_INDEX + +#define ATOM_DEVICE_DFP2I_INDEX 0x00000009 +#define ATOM_DEVICE_DFP2I_SUPPORT (0x1L << ATOM_DEVICE_DFP2I_INDEX) + +#define ATOM_S0_DFP1I ATOM_S0_DFP1 +#define ATOM_S0_DFP1X ATOM_S0_DFP2 + +#define ATOM_S0_DFP2I 0x00200000L +#define ATOM_S0_DFP2Ib2 0x20 + +#define ATOM_S2_DFP1I_DPMS_STATE ATOM_S2_DFP1_DPMS_STATE +#define ATOM_S2_DFP1X_DPMS_STATE ATOM_S2_DFP2_DPMS_STATE + +#define ATOM_S2_DFP2I_DPMS_STATE 0x02000000L +#define ATOM_S2_DFP2I_DPMS_STATEb3 0x02 + +#define ATOM_S3_DFP2I_ACTIVEb1 0x02 + +#define ATOM_S3_DFP1I_ACTIVE ATOM_S3_DFP1_ACTIVE +#define ATOM_S3_DFP1X_ACTIVE ATOM_S3_DFP2_ACTIVE + +#define ATOM_S3_DFP2I_ACTIVE 0x00000200L + +#define ATOM_S3_DFP1I_CRTC_ACTIVE ATOM_S3_DFP1_CRTC_ACTIVE +#define ATOM_S3_DFP1X_CRTC_ACTIVE ATOM_S3_DFP2_CRTC_ACTIVE +#define ATOM_S3_DFP2I_CRTC_ACTIVE 0x02000000L + +#define ATOM_S3_DFP2I_CRTC_ACTIVEb3 0x02 +#define ATOM_S5_DOS_REQ_DFP2Ib1 0x02 + +#define ATOM_S5_DOS_REQ_DFP2I 0x0200 +#define ATOM_S6_ACC_REQ_DFP1I ATOM_S6_ACC_REQ_DFP1 +#define ATOM_S6_ACC_REQ_DFP1X ATOM_S6_ACC_REQ_DFP2 + +#define ATOM_S6_ACC_REQ_DFP2Ib3 0x02 +#define ATOM_S6_ACC_REQ_DFP2I 0x02000000L + +#define TMDS1XEncoderControl DVOEncoderControl +#define DFP1XOutputControl DVOOutputControl + +#define ExternalDFPOutputControl DFP1XOutputControl +#define EnableExternalTMDS_Encoder TMDS1XEncoderControl + +#define DFP1IOutputControl TMDSAOutputControl +#define DFP2IOutputControl LVTMAOutputControl + +#define DAC1_ENCODER_CONTROL_PARAMETERS DAC_ENCODER_CONTROL_PARAMETERS +#define DAC1_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION + +#define DAC2_ENCODER_CONTROL_PARAMETERS DAC_ENCODER_CONTROL_PARAMETERS +#define DAC2_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION + +#define ucDac1Standard ucDacStandard +#define ucDac2Standard ucDacStandard + +#define TMDS1EncoderControl TMDSAEncoderControl +#define TMDS2EncoderControl LVTMAEncoderControl + +#define DFP1OutputControl TMDSAOutputControl +#define DFP2OutputControl LVTMAOutputControl +#define CRT1OutputControl DAC1OutputControl +#define CRT2OutputControl DAC2OutputControl + +//These two lines will be removed for sure in a few days, will follow up with Michael V. +#define EnableLVDS_SS EnableSpreadSpectrumOnPPLL +#define ENABLE_LVDS_SS_PARAMETERS_V3 ENABLE_SPREAD_SPECTRUM_ON_PPLL + +//#define ATOM_S2_CRT1_DPMS_STATE 0x00010000L +//#define ATOM_S2_LCD1_DPMS_STATE ATOM_S2_CRT1_DPMS_STATE +//#define ATOM_S2_TV1_DPMS_STATE ATOM_S2_CRT1_DPMS_STATE +//#define ATOM_S2_DFP1_DPMS_STATE ATOM_S2_CRT1_DPMS_STATE +//#define ATOM_S2_CRT2_DPMS_STATE ATOM_S2_CRT1_DPMS_STATE + +#define ATOM_S6_ACC_REQ_TV2 0x00400000L +#define ATOM_DEVICE_TV2_INDEX 0x00000006 +#define ATOM_DEVICE_TV2_SUPPORT (0x1L << ATOM_DEVICE_TV2_INDEX) +#define ATOM_S0_TV2 0x00100000L +#define ATOM_S3_TV2_ACTIVE ATOM_S3_DFP6_ACTIVE +#define ATOM_S3_TV2_CRTC_ACTIVE ATOM_S3_DFP6_CRTC_ACTIVE + +// +#define ATOM_S2_CRT1_DPMS_STATE 0x00010000L +#define ATOM_S2_LCD1_DPMS_STATE 0x00020000L +#define ATOM_S2_TV1_DPMS_STATE 0x00040000L +#define ATOM_S2_DFP1_DPMS_STATE 0x00080000L +#define ATOM_S2_CRT2_DPMS_STATE 0x00100000L +#define ATOM_S2_LCD2_DPMS_STATE 0x00200000L +#define ATOM_S2_TV2_DPMS_STATE 0x00400000L +#define ATOM_S2_DFP2_DPMS_STATE 0x00800000L +#define ATOM_S2_CV_DPMS_STATE 0x01000000L +#define ATOM_S2_DFP3_DPMS_STATE 0x02000000L +#define ATOM_S2_DFP4_DPMS_STATE 0x04000000L +#define ATOM_S2_DFP5_DPMS_STATE 0x08000000L + +#define ATOM_S2_CRT1_DPMS_STATEb2 0x01 +#define ATOM_S2_LCD1_DPMS_STATEb2 0x02 +#define ATOM_S2_TV1_DPMS_STATEb2 0x04 +#define ATOM_S2_DFP1_DPMS_STATEb2 0x08 +#define ATOM_S2_CRT2_DPMS_STATEb2 0x10 +#define ATOM_S2_LCD2_DPMS_STATEb2 0x20 +#define ATOM_S2_TV2_DPMS_STATEb2 0x40 +#define ATOM_S2_DFP2_DPMS_STATEb2 0x80 +#define ATOM_S2_CV_DPMS_STATEb3 0x01 +#define ATOM_S2_DFP3_DPMS_STATEb3 0x02 +#define ATOM_S2_DFP4_DPMS_STATEb3 0x04 +#define ATOM_S2_DFP5_DPMS_STATEb3 0x08 + +#define ATOM_S3_ASIC_GUI_ENGINE_HUNGb3 0x20 +#define ATOM_S3_ALLOW_FAST_PWR_SWITCHb3 0x40 +#define ATOM_S3_RQST_GPU_USE_MIN_PWRb3 0x80 + +/*********************************************************************************/ + +#pragma pack() // BIOS data must use byte aligment + +// +// AMD ACPI Table +// +#pragma pack(1) + +typedef struct { + ULONG Signature; + ULONG TableLength; //Length + UCHAR Revision; + UCHAR Checksum; + UCHAR OemId[6]; + UCHAR OemTableId[8]; //UINT64 OemTableId; + ULONG OemRevision; + ULONG CreatorId; + ULONG CreatorRevision; +} AMD_ACPI_DESCRIPTION_HEADER; +/* +//EFI_ACPI_DESCRIPTION_HEADER from AcpiCommon.h +typedef struct { + UINT32 Signature; //0x0 + UINT32 Length; //0x4 + UINT8 Revision; //0x8 + UINT8 Checksum; //0x9 + UINT8 OemId[6]; //0xA + UINT64 OemTableId; //0x10 + UINT32 OemRevision; //0x18 + UINT32 CreatorId; //0x1C + UINT32 CreatorRevision; //0x20 +}EFI_ACPI_DESCRIPTION_HEADER; +*/ +typedef struct { + AMD_ACPI_DESCRIPTION_HEADER SHeader; + UCHAR TableUUID[16]; //0x24 + ULONG VBIOSImageOffset; //0x34. Offset to the first GOP_VBIOS_CONTENT block from the beginning of the stucture. + ULONG Lib1ImageOffset; //0x38. Offset to the first GOP_LIB1_CONTENT block from the beginning of the stucture. + ULONG Reserved[4]; //0x3C +}UEFI_ACPI_VFCT; + +typedef struct { + ULONG PCIBus; //0x4C + ULONG PCIDevice; //0x50 + ULONG PCIFunction; //0x54 + USHORT VendorID; //0x58 + USHORT DeviceID; //0x5A + USHORT SSVID; //0x5C + USHORT SSID; //0x5E + ULONG Revision; //0x60 + ULONG ImageLength; //0x64 +}VFCT_IMAGE_HEADER; + + +typedef struct { + VFCT_IMAGE_HEADER VbiosHeader; + UCHAR VbiosContent[1]; +}GOP_VBIOS_CONTENT; + +typedef struct { + VFCT_IMAGE_HEADER Lib1Header; + UCHAR Lib1Content[1]; +}GOP_LIB1_CONTENT; + +#pragma pack() + + +#endif /* _ATOMBIOS_H */ diff --git a/sys/dev/drm2/radeon/atombios_crtc.c b/sys/dev/drm2/radeon/atombios_crtc.c new file mode 100644 index 00000000000..c4c5c4606fa --- /dev/null +++ b/sys/dev/drm2/radeon/atombios_crtc.c @@ -0,0 +1,1938 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "radeon.h" +#include "atom.h" +#include "atom-bits.h" + +static void atombios_overscan_setup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + SET_CRTC_OVERSCAN_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); + int a1, a2; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = radeon_crtc->crtc_id; + + switch (radeon_crtc->rmx_type) { + case RMX_CENTER: + args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2); + args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2); + args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2); + args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2); + break; + case RMX_ASPECT: + a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; + a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; + + if (a1 > a2) { + args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); + args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); + } else if (a2 > a1) { + args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); + args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); + } + break; + case RMX_FULL: + default: + args.usOverscanRight = cpu_to_le16(radeon_crtc->h_border); + args.usOverscanLeft = cpu_to_le16(radeon_crtc->h_border); + args.usOverscanBottom = cpu_to_le16(radeon_crtc->v_border); + args.usOverscanTop = cpu_to_le16(radeon_crtc->v_border); + break; + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_scaler_setup(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + ENABLE_SCALER_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); + struct radeon_encoder *radeon_encoder = + to_radeon_encoder(radeon_crtc->encoder); + /* fixme - fill in enc_priv for atom dac */ + enum radeon_tv_std tv_std = TV_STD_NTSC; + bool is_tv = false, is_cv = false; + + if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) + return; + + if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { + struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; + tv_std = tv_dac->tv_std; + is_tv = true; + } + + memset(&args, 0, sizeof(args)); + + args.ucScaler = radeon_crtc->crtc_id; + + if (is_tv) { + switch (tv_std) { + case TV_STD_NTSC: + default: + args.ucTVStandard = ATOM_TV_NTSC; + break; + case TV_STD_PAL: + args.ucTVStandard = ATOM_TV_PAL; + break; + case TV_STD_PAL_M: + args.ucTVStandard = ATOM_TV_PALM; + break; + case TV_STD_PAL_60: + args.ucTVStandard = ATOM_TV_PAL60; + break; + case TV_STD_NTSC_J: + args.ucTVStandard = ATOM_TV_NTSCJ; + break; + case TV_STD_SCART_PAL: + args.ucTVStandard = ATOM_TV_PAL; /* ??? */ + break; + case TV_STD_SECAM: + args.ucTVStandard = ATOM_TV_SECAM; + break; + case TV_STD_PAL_CN: + args.ucTVStandard = ATOM_TV_PALCN; + break; + } + args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; + } else if (is_cv) { + args.ucTVStandard = ATOM_TV_CV; + args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; + } else { + switch (radeon_crtc->rmx_type) { + case RMX_FULL: + args.ucEnable = ATOM_SCALER_EXPANSION; + break; + case RMX_CENTER: + args.ucEnable = ATOM_SCALER_CENTER; + break; + case RMX_ASPECT: + args.ucEnable = ATOM_SCALER_EXPANSION; + break; + default: + if (ASIC_IS_AVIVO(rdev)) + args.ucEnable = ATOM_SCALER_DISABLE; + else + args.ucEnable = ATOM_SCALER_CENTER; + break; + } + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + if ((is_tv || is_cv) + && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) { + atom_rv515_force_tv_scaler(rdev, radeon_crtc); + } +} + +static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int index = + GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); + ENABLE_CRTC_PS_ALLOCATION args; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = radeon_crtc->crtc_id; + args.ucEnable = lock; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_enable_crtc(struct drm_crtc *crtc, int state) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); + ENABLE_CRTC_PS_ALLOCATION args; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = radeon_crtc->crtc_id; + args.ucEnable = state; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); + ENABLE_CRTC_PS_ALLOCATION args; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = radeon_crtc->crtc_id; + args.ucEnable = state; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_blank_crtc(struct drm_crtc *crtc, int state) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); + BLANK_CRTC_PS_ALLOCATION args; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = radeon_crtc->crtc_id; + args.ucBlanking = state; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_powergate_crtc(struct drm_crtc *crtc, int state) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); + ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; + + memset(&args, 0, sizeof(args)); + + args.ucDispPipeId = radeon_crtc->crtc_id; + args.ucEnable = state; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + switch (mode) { + case DRM_MODE_DPMS_ON: + radeon_crtc->enabled = true; + /* adjust pm to dpms changes BEFORE enabling crtcs */ + radeon_pm_compute_clocks(rdev); + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_DISABLE); + atombios_enable_crtc(crtc, ATOM_ENABLE); + if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) + atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); + atombios_blank_crtc(crtc, ATOM_DISABLE); + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); + radeon_crtc_load_lut(crtc); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); + if (radeon_crtc->enabled) + atombios_blank_crtc(crtc, ATOM_ENABLE); + if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) + atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); + atombios_enable_crtc(crtc, ATOM_DISABLE); + radeon_crtc->enabled = false; + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_ENABLE); + /* adjust pm to dpms changes AFTER disabling crtcs */ + radeon_pm_compute_clocks(rdev); + break; + } +} + +static void +atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + SET_CRTC_USING_DTD_TIMING_PARAMETERS args; + int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); + u16 misc = 0; + + memset(&args, 0, sizeof(args)); + args.usH_Size = cpu_to_le16(mode->crtc_hdisplay - (radeon_crtc->h_border * 2)); + args.usH_Blanking_Time = + cpu_to_le16(mode->crtc_hblank_end - mode->crtc_hdisplay + (radeon_crtc->h_border * 2)); + args.usV_Size = cpu_to_le16(mode->crtc_vdisplay - (radeon_crtc->v_border * 2)); + args.usV_Blanking_Time = + cpu_to_le16(mode->crtc_vblank_end - mode->crtc_vdisplay + (radeon_crtc->v_border * 2)); + args.usH_SyncOffset = + cpu_to_le16(mode->crtc_hsync_start - mode->crtc_hdisplay + radeon_crtc->h_border); + args.usH_SyncWidth = + cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start); + args.usV_SyncOffset = + cpu_to_le16(mode->crtc_vsync_start - mode->crtc_vdisplay + radeon_crtc->v_border); + args.usV_SyncWidth = + cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start); + args.ucH_Border = radeon_crtc->h_border; + args.ucV_Border = radeon_crtc->v_border; + + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + misc |= ATOM_VSYNC_POLARITY; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + misc |= ATOM_HSYNC_POLARITY; + if (mode->flags & DRM_MODE_FLAG_CSYNC) + misc |= ATOM_COMPOSITESYNC; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + misc |= ATOM_INTERLACE; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + misc |= ATOM_DOUBLE_CLOCK_MODE; + + args.susModeMiscInfo.usAccess = cpu_to_le16(misc); + args.ucCRTC = radeon_crtc->crtc_id; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_crtc_set_timing(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing); + u16 misc = 0; + + memset(&args, 0, sizeof(args)); + args.usH_Total = cpu_to_le16(mode->crtc_htotal); + args.usH_Disp = cpu_to_le16(mode->crtc_hdisplay); + args.usH_SyncStart = cpu_to_le16(mode->crtc_hsync_start); + args.usH_SyncWidth = + cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start); + args.usV_Total = cpu_to_le16(mode->crtc_vtotal); + args.usV_Disp = cpu_to_le16(mode->crtc_vdisplay); + args.usV_SyncStart = cpu_to_le16(mode->crtc_vsync_start); + args.usV_SyncWidth = + cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start); + + args.ucOverscanRight = radeon_crtc->h_border; + args.ucOverscanLeft = radeon_crtc->h_border; + args.ucOverscanBottom = radeon_crtc->v_border; + args.ucOverscanTop = radeon_crtc->v_border; + + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + misc |= ATOM_VSYNC_POLARITY; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + misc |= ATOM_HSYNC_POLARITY; + if (mode->flags & DRM_MODE_FLAG_CSYNC) + misc |= ATOM_COMPOSITESYNC; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + misc |= ATOM_INTERLACE; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + misc |= ATOM_DOUBLE_CLOCK_MODE; + + args.susModeMiscInfo.usAccess = cpu_to_le16(misc); + args.ucCRTC = radeon_crtc->crtc_id; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_disable_ss(struct radeon_device *rdev, int pll_id) +{ + u32 ss_cntl; + + if (ASIC_IS_DCE4(rdev)) { + switch (pll_id) { + case ATOM_PPLL1: + ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL); + ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; + WREG32(EVERGREEN_P1PLL_SS_CNTL, ss_cntl); + break; + case ATOM_PPLL2: + ss_cntl = RREG32(EVERGREEN_P2PLL_SS_CNTL); + ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; + WREG32(EVERGREEN_P2PLL_SS_CNTL, ss_cntl); + break; + case ATOM_DCPLL: + case ATOM_PPLL_INVALID: + return; + } + } else if (ASIC_IS_AVIVO(rdev)) { + switch (pll_id) { + case ATOM_PPLL1: + ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); + ss_cntl &= ~1; + WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl); + break; + case ATOM_PPLL2: + ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL); + ss_cntl &= ~1; + WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl); + break; + case ATOM_DCPLL: + case ATOM_PPLL_INVALID: + return; + } + } +} + + +union atom_enable_ss { + ENABLE_LVDS_SS_PARAMETERS lvds_ss; + ENABLE_LVDS_SS_PARAMETERS_V2 lvds_ss_2; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 v2; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3; +}; + +static void atombios_crtc_program_ss(struct radeon_device *rdev, + int enable, + int pll_id, + int crtc_id, + struct radeon_atom_ss *ss) +{ + unsigned i; + int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); + union atom_enable_ss args; + + if (!enable) { + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != crtc_id && + pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off spread spectrum as it might turn off + * display on active crtc + */ + return; + } + } + } + + memset(&args, 0, sizeof(args)); + + if (ASIC_IS_DCE5(rdev)) { + args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0); + args.v3.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; + switch (pll_id) { + case ATOM_PPLL1: + args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; + break; + case ATOM_PPLL2: + args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; + break; + case ATOM_DCPLL: + args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; + break; + case ATOM_PPLL_INVALID: + return; + } + args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); + args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); + args.v3.ucEnable = enable; + if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) + args.v3.ucEnable = ATOM_DISABLE; + } else if (ASIC_IS_DCE4(rdev)) { + args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); + args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; + switch (pll_id) { + case ATOM_PPLL1: + args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; + break; + case ATOM_PPLL2: + args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; + break; + case ATOM_DCPLL: + args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; + break; + case ATOM_PPLL_INVALID: + return; + } + args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); + args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); + args.v2.ucEnable = enable; + if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) + args.v2.ucEnable = ATOM_DISABLE; + } else if (ASIC_IS_DCE3(rdev)) { + args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); + args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; + args.v1.ucSpreadSpectrumStep = ss->step; + args.v1.ucSpreadSpectrumDelay = ss->delay; + args.v1.ucSpreadSpectrumRange = ss->range; + args.v1.ucPpll = pll_id; + args.v1.ucEnable = enable; + } else if (ASIC_IS_AVIVO(rdev)) { + if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || + (ss->type & ATOM_EXTERNAL_SS_MASK)) { + atombios_disable_ss(rdev, pll_id); + return; + } + args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); + args.lvds_ss_2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; + args.lvds_ss_2.ucSpreadSpectrumStep = ss->step; + args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay; + args.lvds_ss_2.ucSpreadSpectrumRange = ss->range; + args.lvds_ss_2.ucEnable = enable; + } else { + if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || + (ss->type & ATOM_EXTERNAL_SS_MASK)) { + atombios_disable_ss(rdev, pll_id); + return; + } + args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); + args.lvds_ss.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; + args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2; + args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4; + args.lvds_ss.ucEnable = enable; + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +union adjust_pixel_clock { + ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; + ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3; +}; + +static u32 atombios_adjust_pll(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder = radeon_crtc->encoder; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + u32 adjusted_clock = mode->clock; + int encoder_mode = atombios_get_encoder_mode(encoder); + u32 dp_clock = mode->clock; + int bpc = radeon_get_monitor_bpc(connector); + bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); + + /* reset the pll flags */ + radeon_crtc->pll_flags = 0; + + if (ASIC_IS_AVIVO(rdev)) { + if ((rdev->family == CHIP_RS600) || + (rdev->family == CHIP_RS690) || + (rdev->family == CHIP_RS740)) + radeon_crtc->pll_flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/ + RADEON_PLL_PREFER_CLOSEST_LOWER); + + if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ + radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + else + radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + + if (rdev->family < CHIP_RV770) + radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP; + /* use frac fb div on APUs */ + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + if (ASIC_IS_DCE32(rdev) && mode->clock > 165000) + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + } else { + radeon_crtc->pll_flags |= RADEON_PLL_LEGACY; + + if (mode->clock > 200000) /* range limits??? */ + radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + else + radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + } + + if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + dp_clock = dig_connector->dp_clock; + } + } + + /* use recommended ref_div for ss */ + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + if (radeon_crtc->ss_enabled) { + if (radeon_crtc->ss.refdiv) { + radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; + radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv; + if (ASIC_IS_AVIVO(rdev)) + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + } + } + } + + if (ASIC_IS_AVIVO(rdev)) { + /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ + if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) + adjusted_clock = mode->clock * 2; + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + radeon_crtc->pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + radeon_crtc->pll_flags |= RADEON_PLL_IS_LCD; + } else { + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) + radeon_crtc->pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) + radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; + } + + /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock + * accordingly based on the encoder/transmitter to work around + * special hw requirements. + */ + if (ASIC_IS_DCE3(rdev)) { + union adjust_pixel_clock args; + u8 frev, crev; + int index; + + index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, + &crev)) + return adjusted_clock; + + memset(&args, 0, sizeof(args)); + + switch (frev) { + case 1: + switch (crev) { + case 1: + case 2: + args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v1.ucTransmitterID = radeon_encoder->encoder_id; + args.v1.ucEncodeMode = encoder_mode; + if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) + args.v1.ucConfig |= + ADJUST_DISPLAY_CONFIG_SS_ENABLE; + + atom_execute_table(rdev->mode_info.atom_context, + index, (uint32_t *)&args); + adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; + break; + case 3: + args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; + args.v3.sInput.ucEncodeMode = encoder_mode; + args.v3.sInput.ucDispPllConfig = 0; + if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_SS_ENABLE; + if (ENCODER_MODE_IS_DP(encoder_mode)) { + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_COHERENT_MODE; + /* 16200 or 27000 */ + args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); + } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) + /* deep color support */ + args.v3.sInput.usPixelClock = + cpu_to_le16((mode->clock * bpc / 8) / 10); + if (dig->coherent_mode) + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_COHERENT_MODE; + if (is_duallink) + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_DUAL_LINK; + } + if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != + ENCODER_OBJECT_ID_NONE) + args.v3.sInput.ucExtTransmitterID = + radeon_encoder_get_dp_bridge_encoder_id(encoder); + else + args.v3.sInput.ucExtTransmitterID = 0; + + atom_execute_table(rdev->mode_info.atom_context, + index, (uint32_t *)&args); + adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; + if (args.v3.sOutput.ucRefDiv) { + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; + radeon_crtc->pll_reference_div = args.v3.sOutput.ucRefDiv; + } + if (args.v3.sOutput.ucPostDiv) { + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + radeon_crtc->pll_flags |= RADEON_PLL_USE_POST_DIV; + radeon_crtc->pll_post_div = args.v3.sOutput.ucPostDiv; + } + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return adjusted_clock; + } + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return adjusted_clock; + } + } + return adjusted_clock; +} + +union set_pixel_clock { + SET_PIXEL_CLOCK_PS_ALLOCATION base; + PIXEL_CLOCK_PARAMETERS v1; + PIXEL_CLOCK_PARAMETERS_V2 v2; + PIXEL_CLOCK_PARAMETERS_V3 v3; + PIXEL_CLOCK_PARAMETERS_V5 v5; + PIXEL_CLOCK_PARAMETERS_V6 v6; +}; + +/* on DCE5, make sure the voltage is high enough to support the + * required disp clk. + */ +static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev, + u32 dispclk) +{ + u8 frev, crev; + int index; + union set_pixel_clock args; + + memset(&args, 0, sizeof(args)); + + index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, + &crev)) + return; + + switch (frev) { + case 1: + switch (crev) { + case 5: + /* if the default dcpll clock is specified, + * SetPixelClock provides the dividers + */ + args.v5.ucCRTC = ATOM_CRTC_INVALID; + args.v5.usPixelClock = cpu_to_le16(dispclk); + args.v5.ucPpll = ATOM_DCPLL; + break; + case 6: + /* if the default dcpll clock is specified, + * SetPixelClock provides the dividers + */ + args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk); + if (ASIC_IS_DCE61(rdev)) + args.v6.ucPpll = ATOM_EXT_PLL1; + else if (ASIC_IS_DCE6(rdev)) + args.v6.ucPpll = ATOM_PPLL0; + else + args.v6.ucPpll = ATOM_DCPLL; + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return; + } + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return; + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void atombios_crtc_program_pll(struct drm_crtc *crtc, + u32 crtc_id, + int pll_id, + u32 encoder_mode, + u32 encoder_id, + u32 clock, + u32 ref_div, + u32 fb_div, + u32 frac_fb_div, + u32 post_div, + int bpc, + bool ss_enabled, + struct radeon_atom_ss *ss) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + u8 frev, crev; + int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); + union set_pixel_clock args; + + memset(&args, 0, sizeof(args)); + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, + &crev)) + return; + + switch (frev) { + case 1: + switch (crev) { + case 1: + if (clock == ATOM_DISABLE) + return; + args.v1.usPixelClock = cpu_to_le16(clock / 10); + args.v1.usRefDiv = cpu_to_le16(ref_div); + args.v1.usFbDiv = cpu_to_le16(fb_div); + args.v1.ucFracFbDiv = frac_fb_div; + args.v1.ucPostDiv = post_div; + args.v1.ucPpll = pll_id; + args.v1.ucCRTC = crtc_id; + args.v1.ucRefDivSrc = 1; + break; + case 2: + args.v2.usPixelClock = cpu_to_le16(clock / 10); + args.v2.usRefDiv = cpu_to_le16(ref_div); + args.v2.usFbDiv = cpu_to_le16(fb_div); + args.v2.ucFracFbDiv = frac_fb_div; + args.v2.ucPostDiv = post_div; + args.v2.ucPpll = pll_id; + args.v2.ucCRTC = crtc_id; + args.v2.ucRefDivSrc = 1; + break; + case 3: + args.v3.usPixelClock = cpu_to_le16(clock / 10); + args.v3.usRefDiv = cpu_to_le16(ref_div); + args.v3.usFbDiv = cpu_to_le16(fb_div); + args.v3.ucFracFbDiv = frac_fb_div; + args.v3.ucPostDiv = post_div; + args.v3.ucPpll = pll_id; + if (crtc_id == ATOM_CRTC2) + args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2; + else + args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1; + if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) + args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; + args.v3.ucTransmitterId = encoder_id; + args.v3.ucEncoderMode = encoder_mode; + break; + case 5: + args.v5.ucCRTC = crtc_id; + args.v5.usPixelClock = cpu_to_le16(clock / 10); + args.v5.ucRefDiv = ref_div; + args.v5.usFbDiv = cpu_to_le16(fb_div); + args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); + args.v5.ucPostDiv = post_div; + args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ + if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; + switch (bpc) { + case 8: + default: + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; + break; + case 10: + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; + break; + } + args.v5.ucTransmitterID = encoder_id; + args.v5.ucEncoderMode = encoder_mode; + args.v5.ucPpll = pll_id; + break; + case 6: + args.v6.ulDispEngClkFreq = cpu_to_le32(crtc_id << 24 | clock / 10); + args.v6.ucRefDiv = ref_div; + args.v6.usFbDiv = cpu_to_le16(fb_div); + args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); + args.v6.ucPostDiv = post_div; + args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ + if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; + switch (bpc) { + case 8: + default: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; + break; + case 10: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; + break; + case 12: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; + break; + case 16: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; + break; + } + args.v6.ucTransmitterID = encoder_id; + args.v6.ucEncoderMode = encoder_mode; + args.v6.ucPpll = pll_id; + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return; + } + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = + to_radeon_encoder(radeon_crtc->encoder); + int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder); + + radeon_crtc->bpc = 8; + radeon_crtc->ss_enabled = false; + + if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) { + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = + radeon_get_connector_for_encoder(radeon_crtc->encoder); + struct radeon_connector *radeon_connector = + to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + int dp_clock; + radeon_crtc->bpc = radeon_get_monitor_bpc(connector); + + switch (encoder_mode) { + case ATOM_ENCODER_MODE_DP_MST: + case ATOM_ENCODER_MODE_DP: + /* DP/eDP */ + dp_clock = dig_connector->dp_clock / 10; + if (ASIC_IS_DCE4(rdev)) + radeon_crtc->ss_enabled = + radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss, + ASIC_INTERNAL_SS_ON_DP, + dp_clock); + else { + if (dp_clock == 16200) { + radeon_crtc->ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, + &radeon_crtc->ss, + ATOM_DP_SS_ID2); + if (!radeon_crtc->ss_enabled) + radeon_crtc->ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, + &radeon_crtc->ss, + ATOM_DP_SS_ID1); + } else + radeon_crtc->ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, + &radeon_crtc->ss, + ATOM_DP_SS_ID1); + } + break; + case ATOM_ENCODER_MODE_LVDS: + if (ASIC_IS_DCE4(rdev)) + radeon_crtc->ss_enabled = + radeon_atombios_get_asic_ss_info(rdev, + &radeon_crtc->ss, + dig->lcd_ss_id, + mode->clock / 10); + else + radeon_crtc->ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, + &radeon_crtc->ss, + dig->lcd_ss_id); + break; + case ATOM_ENCODER_MODE_DVI: + if (ASIC_IS_DCE4(rdev)) + radeon_crtc->ss_enabled = + radeon_atombios_get_asic_ss_info(rdev, + &radeon_crtc->ss, + ASIC_INTERNAL_SS_ON_TMDS, + mode->clock / 10); + break; + case ATOM_ENCODER_MODE_HDMI: + if (ASIC_IS_DCE4(rdev)) + radeon_crtc->ss_enabled = + radeon_atombios_get_asic_ss_info(rdev, + &radeon_crtc->ss, + ASIC_INTERNAL_SS_ON_HDMI, + mode->clock / 10); + break; + default: + break; + } + } + + /* adjust pixel clock as needed */ + radeon_crtc->adjusted_clock = atombios_adjust_pll(crtc, mode); + + return true; +} + +static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = + to_radeon_encoder(radeon_crtc->encoder); + u32 pll_clock = mode->clock; + u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; + struct radeon_pll *pll; + int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder); + + switch (radeon_crtc->pll_id) { + case ATOM_PPLL1: + pll = &rdev->clock.p1pll; + break; + case ATOM_PPLL2: + pll = &rdev->clock.p2pll; + break; + case ATOM_DCPLL: + case ATOM_PPLL_INVALID: + default: + pll = &rdev->clock.dcpll; + break; + } + + /* update pll params */ + pll->flags = radeon_crtc->pll_flags; + pll->reference_div = radeon_crtc->pll_reference_div; + pll->post_div = radeon_crtc->pll_post_div; + + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + /* TV seems to prefer the legacy algo on some boards */ + radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock, + &fb_div, &frac_fb_div, &ref_div, &post_div); + else if (ASIC_IS_AVIVO(rdev)) + radeon_compute_pll_avivo(pll, radeon_crtc->adjusted_clock, &pll_clock, + &fb_div, &frac_fb_div, &ref_div, &post_div); + else + radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock, + &fb_div, &frac_fb_div, &ref_div, &post_div); + + atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, + radeon_crtc->crtc_id, &radeon_crtc->ss); + + atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, + encoder_mode, radeon_encoder->encoder_id, mode->clock, + ref_div, fb_div, frac_fb_div, post_div, + radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss); + + if (radeon_crtc->ss_enabled) { + /* calculate ss amount and step size */ + if (ASIC_IS_DCE4(rdev)) { + u32 step_size; + u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000; + radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; + radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; + if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) + step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) / + (125 * 25 * pll->reference_freq / 100); + else + step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) / + (125 * 25 * pll->reference_freq / 100); + radeon_crtc->ss.step = step_size; + } + + atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, + radeon_crtc->crtc_id, &radeon_crtc->ss); + } +} + +static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_framebuffer *radeon_fb; + struct drm_framebuffer *target_fb; + struct drm_gem_object *obj; + struct radeon_bo *rbo; + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; + unsigned bankw, bankh, mtaspect, tile_split; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); + u32 tmp, viewport_w, viewport_h; + int r; + + /* no fb bound */ + if (!atomic && !crtc->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + if (atomic) { + radeon_fb = to_radeon_framebuffer(fb); + target_fb = fb; + } + else { + radeon_fb = to_radeon_framebuffer(crtc->fb); + target_fb = crtc->fb; + } + + /* If atomic, assume fb object is pinned & idle & fenced and + * just update base pointers + */ + obj = radeon_fb->obj; + rbo = gem_to_radeon_bo(obj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + if (atomic) + fb_location = radeon_bo_gpu_offset(rbo); + else { + r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + return -EINVAL; + } + } + + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); + + switch (target_fb->bits_per_pixel) { + case 8: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); + break; + case 15: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555)); + break; + case 16: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif + break; + case 24: + case 32: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); +#endif + break; + default: + DRM_ERROR("Unsupported screen depth %d\n", + target_fb->bits_per_pixel); + return -EINVAL; + } + + if (tiling_flags & RADEON_TILING_MACRO) { + if (rdev->family >= CHIP_TAHITI) + tmp = rdev->config.si.tile_config; + else if (rdev->family >= CHIP_CAYMAN) + tmp = rdev->config.cayman.tile_config; + else + tmp = rdev->config.evergreen.tile_config; + + switch ((tmp & 0xf0) >> 4) { + case 0: /* 4 banks */ + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK); + break; + case 1: /* 8 banks */ + default: + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK); + break; + case 2: /* 16 banks */ + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK); + break; + } + + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); + + evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); + fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split); + fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw); + fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh); + fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect); + } else if (tiling_flags & RADEON_TILING_MICRO) + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); + + if ((rdev->family == CHIP_TAHITI) || + (rdev->family == CHIP_PITCAIRN)) + fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16); + else if (rdev->family == CHIP_VERDE) + fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16); + + switch (radeon_crtc->crtc_id) { + case 0: + WREG32(AVIVO_D1VGA_CONTROL, 0); + break; + case 1: + WREG32(AVIVO_D2VGA_CONTROL, 0); + break; + case 2: + WREG32(EVERGREEN_D3VGA_CONTROL, 0); + break; + case 3: + WREG32(EVERGREEN_D4VGA_CONTROL, 0); + break; + case 4: + WREG32(EVERGREEN_D5VGA_CONTROL, 0); + break; + case 5: + WREG32(EVERGREEN_D6VGA_CONTROL, 0); + break; + default: + break; + } + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(fb_location)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(fb_location)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); + WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); + WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); + + WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); + WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); + + fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); + WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); + + WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, + target_fb->height); + x &= ~3; + y &= ~1; + WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, + (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; + WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (viewport_w << 16) | viewport_h); + + /* pageflip setup */ + /* make sure flip is at vb rather than hb */ + tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); + + if (!atomic && fb && fb != crtc->fb) { + radeon_fb = to_radeon_framebuffer(fb); + rbo = gem_to_radeon_bo(radeon_fb->obj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); + } + + /* Bytes per pixel may have changed */ + radeon_bandwidth_update(rdev); + + return 0; +} + +static int avivo_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_framebuffer *radeon_fb; + struct drm_gem_object *obj; + struct radeon_bo *rbo; + struct drm_framebuffer *target_fb; + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; + u32 tmp, viewport_w, viewport_h; + int r; + + /* no fb bound */ + if (!atomic && !crtc->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + if (atomic) { + radeon_fb = to_radeon_framebuffer(fb); + target_fb = fb; + } + else { + radeon_fb = to_radeon_framebuffer(crtc->fb); + target_fb = crtc->fb; + } + + obj = radeon_fb->obj; + rbo = gem_to_radeon_bo(obj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + /* If atomic, assume fb object is pinned & idle & fenced and + * just update base pointers + */ + if (atomic) + fb_location = radeon_bo_gpu_offset(rbo); + else { + r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + return -EINVAL; + } + } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); + + switch (target_fb->bits_per_pixel) { + case 8: + fb_format = + AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | + AVIVO_D1GRPH_CONTROL_8BPP_INDEXED; + break; + case 15: + fb_format = + AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | + AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555; + break; + case 16: + fb_format = + AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | + AVIVO_D1GRPH_CONTROL_16BPP_RGB565; +#ifdef __BIG_ENDIAN + fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT; +#endif + break; + case 24: + case 32: + fb_format = + AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | + AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; +#ifdef __BIG_ENDIAN + fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT; +#endif + break; + default: + DRM_ERROR("Unsupported screen depth %d\n", + target_fb->bits_per_pixel); + return -EINVAL; + } + + if (rdev->family >= CHIP_R600) { + if (tiling_flags & RADEON_TILING_MACRO) + fb_format |= R600_D1GRPH_ARRAY_MODE_2D_TILED_THIN1; + else if (tiling_flags & RADEON_TILING_MICRO) + fb_format |= R600_D1GRPH_ARRAY_MODE_1D_TILED_THIN1; + } else { + if (tiling_flags & RADEON_TILING_MACRO) + fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; + + if (tiling_flags & RADEON_TILING_MICRO) + fb_format |= AVIVO_D1GRPH_TILED; + } + + if (radeon_crtc->crtc_id == 0) + WREG32(AVIVO_D1VGA_CONTROL, 0); + else + WREG32(AVIVO_D2VGA_CONTROL, 0); + + if (rdev->family >= CHIP_RV770) { + if (radeon_crtc->crtc_id) { + WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + } else { + WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + } + } + WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32) fb_location); + WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + + radeon_crtc->crtc_offset, (u32) fb_location); + WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); + if (rdev->family >= CHIP_R600) + WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); + + WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); + WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); + WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); + WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); + WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); + WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); + + fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); + WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); + + WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, + target_fb->height); + x &= ~3; + y &= ~1; + WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, + (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; + WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (viewport_w << 16) | viewport_h); + + /* pageflip setup */ + /* make sure flip is at vb rather than hb */ + tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); + + if (!atomic && fb && fb != crtc->fb) { + radeon_fb = to_radeon_framebuffer(fb); + rbo = gem_to_radeon_bo(radeon_fb->obj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); + } + + /* Bytes per pixel may have changed */ + radeon_bandwidth_update(rdev); + + return 0; +} + +int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) + return dce4_crtc_do_set_base(crtc, old_fb, x, y, 0); + else if (ASIC_IS_AVIVO(rdev)) + return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0); + else + return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); +} + +int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, enum mode_set_atomic state) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) + return dce4_crtc_do_set_base(crtc, fb, x, y, 1); + else if (ASIC_IS_AVIVO(rdev)) + return avivo_crtc_do_set_base(crtc, fb, x, y, 1); + else + return radeon_crtc_do_set_base(crtc, fb, x, y, 1); +} + +/* properly set additional regs when using atombios */ +static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + u32 disp_merge_cntl; + + switch (radeon_crtc->crtc_id) { + case 0: + disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); + disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); + break; + case 1: + disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); + disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; + WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl); + WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID)); + WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID)); + break; + } +} + +/** + * radeon_get_pll_use_mask - look up a mask of which pplls are in use + * + * @crtc: drm crtc + * + * Returns the mask of which PPLLs (Pixel PLLs) are in use. + */ +static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc *test_crtc; + struct radeon_crtc *test_radeon_crtc; + u32 pll_in_use = 0; + + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + + test_radeon_crtc = to_radeon_crtc(test_crtc); + if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) + pll_in_use |= (1 << test_radeon_crtc->pll_id); + } + return pll_in_use; +} + +/** + * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is + * also in DP mode. For DP, a single PPLL can be used for all DP + * crtcs/encoders. + */ +static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc *test_crtc; + struct radeon_crtc *test_radeon_crtc; + + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + test_radeon_crtc = to_radeon_crtc(test_crtc); + if (test_radeon_crtc->encoder && + ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) { + /* for DP use the same PLL for all */ + if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) + return test_radeon_crtc->pll_id; + } + } + return ATOM_PPLL_INVALID; +} + +/** + * radeon_get_shared_nondp_ppll - return the PPLL used by another non-DP crtc + * + * @crtc: drm crtc + * @encoder: drm encoder + * + * Returns the PPLL (Pixel PLL) used by another non-DP crtc/encoder which can + * be shared (i.e., same clock). + */ +static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *test_crtc; + struct radeon_crtc *test_radeon_crtc; + u32 adjusted_clock, test_adjusted_clock; + + adjusted_clock = radeon_crtc->adjusted_clock; + + if (adjusted_clock == 0) + return ATOM_PPLL_INVALID; + + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + test_radeon_crtc = to_radeon_crtc(test_crtc); + if (test_radeon_crtc->encoder && + !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) { + /* check if we are already driving this connector with another crtc */ + if (test_radeon_crtc->connector == radeon_crtc->connector) { + /* if we are, return that pll */ + if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) + return test_radeon_crtc->pll_id; + } + /* for non-DP check the clock */ + test_adjusted_clock = test_radeon_crtc->adjusted_clock; + if ((crtc->mode.clock == test_crtc->mode.clock) && + (adjusted_clock == test_adjusted_clock) && + (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) && + (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)) + return test_radeon_crtc->pll_id; + } + } + return ATOM_PPLL_INVALID; +} + +/** + * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors + * a single PPLL can be used for all DP crtcs/encoders. For non-DP + * monitors a dedicated PPLL must be used. If a particular board has + * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming + * as there is no need to program the PLL itself. If we are not able to + * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to + * avoid messing up an existing monitor. + * + * Asic specific PLL information + * + * DCE 6.1 + * - PPLL2 is only available to UNIPHYA (both DP and non-DP) + * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP) + * + * DCE 6.0 + * - PPLL0 is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 5.0 + * - DCPLL is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 3.0/4.0/4.1 + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + */ +static int radeon_atom_pick_pll(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = + to_radeon_encoder(radeon_crtc->encoder); + u32 pll_in_use; + int pll; + + if (ASIC_IS_DCE61(rdev)) { + struct radeon_encoder_atom_dig *dig = + radeon_encoder->enc_priv; + + if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && + (dig->linkb == false)) + /* UNIPHY A uses PPLL2 */ + return ATOM_PPLL2; + else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { + /* UNIPHY B/C/D/E/F */ + if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + } else { + /* use the same PPLL for all monitors with the same clock */ + pll = radeon_get_shared_nondp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + /* UNIPHY B/C/D/E/F */ + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL0))) + return ATOM_PPLL0; + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; + } else if (ASIC_IS_DCE4(rdev)) { + /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, + * depending on the asic: + * DCE4: PPLL or ext clock + * DCE5: PPLL, DCPLL, or ext clock + * DCE6: PPLL, PPLL0, or ext clock + * + * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip + * PPLL/DCPLL programming and only program the DP DTO for the + * crtc virtual pixel clock. + */ + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { + if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + else if (ASIC_IS_DCE6(rdev)) + /* use PPLL0 for all DP */ + return ATOM_PPLL0; + else if (ASIC_IS_DCE5(rdev)) + /* use DCPLL for all DP */ + return ATOM_DCPLL; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + } else { + /* use the same PPLL for all monitors with the same clock */ + pll = radeon_get_shared_nondp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + /* all other cases */ + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; + } else { + /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ + /* some atombios (observed in some DCE2/DCE3) code have a bug, + * the matching btw pll and crtc is done through + * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the + * pll (1 or 2) to select which register to write. ie if using + * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2 + * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to + * choose which value to write. Which is reverse order from + * register logic. So only case that works is when pllid is + * same as crtcid or when both pll and crtc are enabled and + * both use same clock. + * + * So just return crtc id as if crtc and pll were hard linked + * together even if they aren't + */ + return radeon_crtc->crtc_id; + } +} + +void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) +{ + /* always set DCPLL */ + if (ASIC_IS_DCE6(rdev)) + atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); + else if (ASIC_IS_DCE4(rdev)) { + struct radeon_atom_ss ss; + bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, + ASIC_INTERNAL_SS_ON_DCPLL, + rdev->clock.default_dispclk); + if (ss_enabled) + atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss); + /* XXX: DCE5, make sure voltage, dispclk is high enough */ + atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); + if (ss_enabled) + atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss); + } + +} + +int atombios_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = + to_radeon_encoder(radeon_crtc->encoder); + bool is_tvcv = false; + + if (radeon_encoder->active_device & + (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) + is_tvcv = true; + + atombios_crtc_set_pll(crtc, adjusted_mode); + + if (ASIC_IS_DCE4(rdev)) + atombios_set_crtc_dtd_timing(crtc, adjusted_mode); + else if (ASIC_IS_AVIVO(rdev)) { + if (is_tvcv) + atombios_crtc_set_timing(crtc, adjusted_mode); + else + atombios_set_crtc_dtd_timing(crtc, adjusted_mode); + } else { + atombios_crtc_set_timing(crtc, adjusted_mode); + if (radeon_crtc->crtc_id == 0) + atombios_set_crtc_dtd_timing(crtc, adjusted_mode); + radeon_legacy_atom_fixup(crtc); + } + atombios_crtc_set_base(crtc, x, y, old_fb); + atombios_overscan_setup(crtc, mode, adjusted_mode); + atombios_scaler_setup(crtc); + return 0; +} + +static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_encoder *encoder; + + /* assign the encoder to the radeon crtc to avoid repeated lookups later */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + radeon_crtc->encoder = encoder; + radeon_crtc->connector = radeon_get_connector_for_encoder(encoder); + break; + } + } + if ((radeon_crtc->encoder == NULL) || (radeon_crtc->connector == NULL)) { + radeon_crtc->encoder = NULL; + radeon_crtc->connector = NULL; + return false; + } + if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) + return false; + if (!atombios_crtc_prepare_pll(crtc, adjusted_mode)) + return false; + /* pick pll */ + radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); + /* if we can't get a PPLL for a non-DP encoder, fail */ + if ((radeon_crtc->pll_id == ATOM_PPLL_INVALID) && + !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) + return false; + + return true; +} + +static void atombios_crtc_prepare(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + + radeon_crtc->in_mode_set = true; + + /* disable crtc pair power gating before programming */ + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_DISABLE); + + atombios_lock_crtc(crtc, ATOM_ENABLE); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +} + +static void atombios_crtc_commit(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + atombios_lock_crtc(crtc, ATOM_DISABLE); + radeon_crtc->in_mode_set = false; +} + +static void atombios_crtc_disable(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_atom_ss ss; + int i; + + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != radeon_crtc->crtc_id && + radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off the pll + */ + goto done; + } + } + + switch (radeon_crtc->pll_id) { + case ATOM_PPLL1: + case ATOM_PPLL2: + /* disable the ppll */ + atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, + 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); + break; + case ATOM_PPLL0: + /* disable the ppll */ + if (ASIC_IS_DCE61(rdev)) + atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, + 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); + break; + default: + break; + } +done: + radeon_crtc->pll_id = ATOM_PPLL_INVALID; + radeon_crtc->adjusted_clock = 0; + radeon_crtc->encoder = NULL; + radeon_crtc->connector = NULL; +} + +static const struct drm_crtc_helper_funcs atombios_helper_funcs = { + .dpms = atombios_crtc_dpms, + .mode_fixup = atombios_crtc_mode_fixup, + .mode_set = atombios_crtc_mode_set, + .mode_set_base = atombios_crtc_set_base, + .mode_set_base_atomic = atombios_crtc_set_base_atomic, + .prepare = atombios_crtc_prepare, + .commit = atombios_crtc_commit, + .load_lut = radeon_crtc_load_lut, + .disable = atombios_crtc_disable, +}; + +void radeon_atombios_init_crtc(struct drm_device *dev, + struct radeon_crtc *radeon_crtc) +{ + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) { + switch (radeon_crtc->crtc_id) { + case 0: + default: + radeon_crtc->crtc_offset = EVERGREEN_CRTC0_REGISTER_OFFSET; + break; + case 1: + radeon_crtc->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET; + break; + case 2: + radeon_crtc->crtc_offset = EVERGREEN_CRTC2_REGISTER_OFFSET; + break; + case 3: + radeon_crtc->crtc_offset = EVERGREEN_CRTC3_REGISTER_OFFSET; + break; + case 4: + radeon_crtc->crtc_offset = EVERGREEN_CRTC4_REGISTER_OFFSET; + break; + case 5: + radeon_crtc->crtc_offset = EVERGREEN_CRTC5_REGISTER_OFFSET; + break; + } + } else { + if (radeon_crtc->crtc_id == 1) + radeon_crtc->crtc_offset = + AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; + else + radeon_crtc->crtc_offset = 0; + } + radeon_crtc->pll_id = ATOM_PPLL_INVALID; + radeon_crtc->adjusted_clock = 0; + radeon_crtc->encoder = NULL; + radeon_crtc->connector = NULL; + drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); +} diff --git a/sys/dev/drm2/radeon/atombios_dp.c b/sys/dev/drm2/radeon/atombios_dp.c new file mode 100644 index 00000000000..3c0f7f563da --- /dev/null +++ b/sys/dev/drm2/radeon/atombios_dp.c @@ -0,0 +1,893 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" + +#include "atom.h" +#include "atom-bits.h" +#include + +/* move these to drm_dp_helper.c/h */ +#define DP_LINK_CONFIGURATION_SIZE 9 +#define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE + +static char *voltage_names[] = { + "0.4V", "0.6V", "0.8V", "1.2V" +}; +static char *pre_emph_names[] = { + "0dB", "3.5dB", "6dB", "9.5dB" +}; + +/***** radeon AUX functions *****/ +union aux_channel_transaction { + PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; + PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; +}; + +static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, + u8 *send, int send_bytes, + u8 *recv, int recv_size, + u8 delay, u8 *ack) +{ + struct drm_device *dev = chan->dev; + struct radeon_device *rdev = dev->dev_private; + union aux_channel_transaction args; + int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); + unsigned char *base; + int recv_bytes; + + memset(&args, 0, sizeof(args)); + + base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); + + memcpy(base, send, send_bytes); + + args.v1.lpAuxRequest = 0 + 4; + args.v1.lpDataOut = 16 + 4; + args.v1.ucDataOutLen = 0; + args.v1.ucChannelID = chan->rec.i2c_id; + args.v1.ucDelay = delay / 10; + if (ASIC_IS_DCE4(rdev)) + args.v2.ucHPD_ID = chan->rec.hpd; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + *ack = args.v1.ucReplyStatus; + + /* timeout */ + if (args.v1.ucReplyStatus == 1) { + DRM_DEBUG_KMS("dp_aux_ch timeout\n"); + return -ETIMEDOUT; + } + + /* flags not zero */ + if (args.v1.ucReplyStatus == 2) { + DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); + return -EBUSY; + } + + /* error */ + if (args.v1.ucReplyStatus == 3) { + DRM_DEBUG_KMS("dp_aux_ch error\n"); + return -EIO; + } + + recv_bytes = args.v1.ucDataOutLen; + if (recv_bytes > recv_size) + recv_bytes = recv_size; + + if (recv && recv_size) + memcpy(recv, base + 16, recv_bytes); + + return recv_bytes; +} + +static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, + u16 address, u8 *send, u8 send_bytes, u8 delay) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + int ret; + u8 msg[20]; + int msg_bytes = send_bytes + 4; + u8 ack; + unsigned retry; + + if (send_bytes > 16) + return -1; + + msg[0] = address; + msg[1] = address >> 8; + msg[2] = AUX_NATIVE_WRITE << 4; + msg[3] = (msg_bytes << 4) | (send_bytes - 1); + memcpy(&msg[4], send, send_bytes); + + for (retry = 0; retry < 4; retry++) { + ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, + msg, msg_bytes, NULL, 0, delay, &ack); + if (ret == -EBUSY) + continue; + else if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + return send_bytes; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + DRM_UDELAY(400); + else + return -EIO; + } + + return -EIO; +} + +static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, + u16 address, u8 *recv, int recv_bytes, u8 delay) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 msg[4]; + int msg_bytes = 4; + u8 ack; + int ret; + unsigned retry; + + msg[0] = address; + msg[1] = address >> 8; + msg[2] = AUX_NATIVE_READ << 4; + msg[3] = (msg_bytes << 4) | (recv_bytes - 1); + + for (retry = 0; retry < 4; retry++) { + ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, + msg, msg_bytes, recv, recv_bytes, delay, &ack); + if (ret == -EBUSY) + continue; + else if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + return ret; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + DRM_UDELAY(400); + else if (ret == 0) + return -EPROTO; + else + return -EIO; + } + + return -EIO; +} + +static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, + u16 reg, u8 val) +{ + radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0); +} + +static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, + u16 reg) +{ + u8 val = 0; + + radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0); + + return val; +} + +int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte) +{ + struct iic_dp_aux_data *algo_data = device_get_softc(dev); + struct radeon_i2c_chan *auxch = algo_data->priv; + u16 address = algo_data->address; + u8 msg[5]; + u8 reply[2]; + unsigned retry; + int msg_bytes; + int reply_bytes = 1; + int ret; + u8 ack; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[2] = AUX_I2C_READ << 4; + else + msg[2] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[2] |= AUX_I2C_MOT << 4; + + msg[0] = address; + msg[1] = address >> 8; + + switch (mode) { + case MODE_I2C_WRITE: + msg_bytes = 5; + msg[3] = msg_bytes << 4; + msg[4] = write_byte; + break; + case MODE_I2C_READ: + msg_bytes = 4; + msg[3] = msg_bytes << 4; + break; + default: + msg_bytes = 4; + msg[3] = 3 << 4; + break; + } + + for (retry = 0; retry < 4; retry++) { + ret = radeon_process_aux_ch(auxch, + msg, msg_bytes, reply, reply_bytes, 0, &ack); + if (ret == -EBUSY) + continue; + else if (ret < 0) { + DRM_DEBUG_KMS("aux_ch failed %d\n", ret); + return ret; + } + + switch (ack & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + /* I2C-over-AUX Reply field is only valid + * when paired with AUX ACK. + */ + break; + case AUX_NATIVE_REPLY_NACK: + DRM_DEBUG_KMS("aux_ch native nack\n"); + return -EREMOTEIO; + case AUX_NATIVE_REPLY_DEFER: + DRM_DEBUG_KMS("aux_ch native defer\n"); + DRM_UDELAY(400); + continue; + default: + DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); + return -EREMOTEIO; + } + + switch (ack & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + if (mode == MODE_I2C_READ) + *read_byte = reply[0]; + return ret; + case AUX_I2C_REPLY_NACK: + DRM_DEBUG_KMS("aux_i2c nack\n"); + return -EREMOTEIO; + case AUX_I2C_REPLY_DEFER: + DRM_DEBUG_KMS("aux_i2c defer\n"); + DRM_UDELAY(400); + break; + default: + DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); + return -EREMOTEIO; + } + } + + DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); + return -EREMOTEIO; +} + +/***** general DP utility functions *****/ + +#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 +#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 + +static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count, + u8 train_set[4]) +{ + u8 v = 0; + u8 p = 0; + int lane; + + for (lane = 0; lane < lane_count; lane++) { + u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane); + u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); + + DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", + lane, + voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], + pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + if (v >= DP_VOLTAGE_MAX) + v |= DP_TRAIN_MAX_SWING_REACHED; + + if (p >= DP_PRE_EMPHASIS_MAX) + p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", + voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], + pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); + + for (lane = 0; lane < 4; lane++) + train_set[lane] = v | p; +} + +/* convert bits per color to bits per pixel */ +/* get bpc from the EDID */ +static int convert_bpc_to_bpp(int bpc) +{ + if (bpc == 0) + return 24; + else + return bpc * 3; +} + +/* get the max pix clock supported by the link rate and lane num */ +static int dp_get_max_dp_pix_clock(int link_rate, + int lane_num, + int bpp) +{ + return (link_rate * lane_num * 8) / bpp; +} + +/***** radeon specific DP functions *****/ + +/* First get the min lane# when low rate is used according to pixel clock + * (prefer low rate), second check max lane# supported by DP panel, + * if the max lane# < low rate lane# then use max lane# instead. + */ +static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, + u8 dpcd[DP_DPCD_SIZE], + int pix_clock) +{ + int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); + int max_link_rate = drm_dp_max_link_rate(dpcd); + int max_lane_num = drm_dp_max_lane_count(dpcd); + int lane_num; + int max_dp_pix_clock; + + for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { + max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); + if (pix_clock <= max_dp_pix_clock) + break; + } + + return lane_num; +} + +static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, + u8 dpcd[DP_DPCD_SIZE], + int pix_clock) +{ + int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); + int lane_num, max_pix_clock; + + if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == + ENCODER_OBJECT_ID_NUTMEG) + return 270000; + + lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); + max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); + if (pix_clock <= max_pix_clock) + return 162000; + max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); + if (pix_clock <= max_pix_clock) + return 270000; + if (radeon_connector_is_dp12_capable(connector)) { + max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); + if (pix_clock <= max_pix_clock) + return 540000; + } + + return drm_dp_max_link_rate(dpcd); +} + +static u8 radeon_dp_encoder_service(struct radeon_device *rdev, + int action, int dp_clock, + u8 ucconfig, u8 lane_num) +{ + DP_ENCODER_SERVICE_PARAMETERS args; + int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); + + memset(&args, 0, sizeof(args)); + args.ucLinkClock = dp_clock / 10; + args.ucConfig = ucconfig; + args.ucAction = action; + args.ucLaneNum = lane_num; + args.ucStatus = 0; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + return args.ucStatus; +} + +u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + struct drm_device *dev = radeon_connector->base.dev; + struct radeon_device *rdev = dev->dev_private; + + return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, + dig_connector->dp_i2c_bus->rec.i2c_id, 0); +} + +static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 buf[3]; + + if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) + return; + + if (radeon_dp_aux_native_read(radeon_connector, DP_SINK_OUI, buf, 3, 0)) + DRM_DEBUG_KMS("Sink OUI: %02hhx%02hhx%02hhx\n", + buf[0], buf[1], buf[2]); + + if (radeon_dp_aux_native_read(radeon_connector, DP_BRANCH_OUI, buf, 3, 0)) + DRM_DEBUG_KMS("Branch OUI: %02hhx%02hhx%02hhx\n", + buf[0], buf[1], buf[2]); +} + +bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) +{ + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 msg[DP_DPCD_SIZE]; + int ret, i; + + ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, + DP_DPCD_SIZE, 0); + if (ret > 0) { + memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); + DRM_DEBUG_KMS("DPCD: "); + for (i = 0; i < DP_DPCD_SIZE; i++) + DRM_DEBUG_KMS("%02x ", msg[i]); + DRM_DEBUG_KMS("\n"); + + radeon_dp_probe_oui(radeon_connector); + + return true; + } + dig_connector->dpcd[0] = 0; + return false; +} + +int radeon_dp_get_panel_mode(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); + u8 tmp; + + if (!ASIC_IS_DCE4(rdev)) + return panel_mode; + + if (dp_bridge != ENCODER_OBJECT_ID_NONE) { + /* DP bridge chips */ + tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || + (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else + panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + /* eDP */ + tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } + + return panel_mode; +} + +void radeon_dp_set_link_config(struct drm_connector *connector, + const struct drm_display_mode *mode) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector; + + if (!radeon_connector->con_priv) + return; + dig_connector = radeon_connector->con_priv; + + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { + dig_connector->dp_clock = + radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); + dig_connector->dp_lane_count = + radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); + } +} + +int radeon_dp_mode_valid_helper(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector; + int dp_clock; + + if (!radeon_connector->con_priv) + return MODE_CLOCK_HIGH; + dig_connector = radeon_connector->con_priv; + + dp_clock = + radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); + + if ((dp_clock == 540000) && + (!radeon_connector_is_dp12_capable(connector))) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, + u8 link_status[DP_LINK_STATUS_SIZE]) +{ + int ret; + ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, + link_status, DP_LINK_STATUS_SIZE, 100); + if (ret <= 0) { + return false; + } + + DRM_DEBUG_KMS("link status %*ph\n", 6, link_status); + return true; +} + +bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) +{ + u8 link_status[DP_LINK_STATUS_SIZE]; + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if (!radeon_dp_get_link_status(radeon_connector, link_status)) + return false; + if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) + return false; + return true; +} + +struct radeon_dp_link_train_info { + struct radeon_device *rdev; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + int enc_id; + int dp_clock; + int dp_lane_count; + bool tp3_supported; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 train_set[4]; + u8 link_status[DP_LINK_STATUS_SIZE]; + u8 tries; + bool use_dpencoder; +}; + +static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) +{ + /* set the initial vs/emph on the source */ + atombios_dig_transmitter_setup(dp_info->encoder, + ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, + 0, dp_info->train_set[0]); /* sets all lanes at once */ + + /* set the vs/emph on the sink */ + radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, + dp_info->train_set, dp_info->dp_lane_count, 0); +} + +static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) +{ + int rtp = 0; + + /* set training pattern on the source */ + if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) { + switch (tp) { + case DP_TRAINING_PATTERN_1: + rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; + break; + case DP_TRAINING_PATTERN_2: + rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; + break; + case DP_TRAINING_PATTERN_3: + rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; + break; + } + atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); + } else { + switch (tp) { + case DP_TRAINING_PATTERN_1: + rtp = 0; + break; + case DP_TRAINING_PATTERN_2: + rtp = 1; + break; + } + radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, + dp_info->dp_clock, dp_info->enc_id, rtp); + } + + /* enable training pattern on the sink */ + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); +} + +static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + u8 tmp; + + /* power up the sink */ + if (dp_info->dpcd[0] >= 0x11) + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_SET_POWER, DP_SET_POWER_D0); + + /* possibly enable downspread on the sink */ + if (dp_info->dpcd[3] & 0x1) + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); + else + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_DOWNSPREAD_CTRL, 0); + + if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && + (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1); + } + + /* set the lane count on the sink */ + tmp = dp_info->dp_lane_count; + if (dp_info->dpcd[DP_DPCD_REV] >= 0x11 && + dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP) + tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); + + /* set the link rate on the sink */ + tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); + + /* start training on the source */ + if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) + atombios_dig_encoder_setup(dp_info->encoder, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); + else + radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, + dp_info->dp_clock, dp_info->enc_id, 0); + + /* disable the training pattern on the sink */ + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + + return 0; +} + +static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) +{ + DRM_UDELAY(400); + + /* disable the training pattern on the sink */ + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + + /* disable the training pattern on the source */ + if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) + atombios_dig_encoder_setup(dp_info->encoder, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); + else + radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, + dp_info->dp_clock, dp_info->enc_id, 0); + + return 0; +} + +static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) +{ + bool clock_recovery; + u8 voltage; + int i; + + radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); + memset(dp_info->train_set, 0, 4); + radeon_dp_update_vs_emph(dp_info); + + DRM_UDELAY(400); + + /* clock recovery loop */ + clock_recovery = false; + dp_info->tries = 0; + voltage = 0xff; + while (1) { + drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); + + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { + DRM_ERROR("displayport link status failed\n"); + break; + } + + if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { + clock_recovery = true; + break; + } + + for (i = 0; i < dp_info->dp_lane_count; i++) { + if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + } + if (i == dp_info->dp_lane_count) { + DRM_ERROR("clock recovery reached max voltage\n"); + break; + } + + if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++dp_info->tries; + if (dp_info->tries == 5) { + DRM_ERROR("clock recovery tried 5 times\n"); + break; + } + } else + dp_info->tries = 0; + + voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + + /* Compute new train_set as requested by sink */ + dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); + + radeon_dp_update_vs_emph(dp_info); + } + if (!clock_recovery) { + DRM_ERROR("clock recovery failed\n"); + return -1; + } else { + DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", + dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> + DP_TRAIN_PRE_EMPHASIS_SHIFT); + return 0; + } +} + +static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) +{ + bool channel_eq; + + if (dp_info->tp3_supported) + radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); + else + radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); + + /* channel equalization loop */ + dp_info->tries = 0; + channel_eq = false; + while (1) { + drm_dp_link_train_channel_eq_delay(dp_info->dpcd); + + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { + DRM_ERROR("displayport link status failed\n"); + break; + } + + if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { + channel_eq = true; + break; + } + + /* Try 5 times */ + if (dp_info->tries > 5) { + DRM_ERROR("channel eq failed: 5 tries\n"); + break; + } + + /* Compute new train_set as requested by sink */ + dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); + + radeon_dp_update_vs_emph(dp_info); + dp_info->tries++; + } + + if (!channel_eq) { + DRM_ERROR("channel eq failed\n"); + return -1; + } else { + DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", + dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) + >> DP_TRAIN_PRE_EMPHASIS_SHIFT); + return 0; + } +} + +void radeon_dp_link_train(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + struct radeon_dp_link_train_info dp_info; + int index; + u8 tmp, frev, crev; + + if (!radeon_encoder->enc_priv) + return; + dig = radeon_encoder->enc_priv; + + radeon_connector = to_radeon_connector(connector); + if (!radeon_connector->con_priv) + return; + dig_connector = radeon_connector->con_priv; + + if ((dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) && + (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) + return; + + /* DPEncoderService newer than 1.1 can't program properly the + * training pattern. When facing such version use the + * DIGXEncoderControl (X== 1 | 2) + */ + dp_info.use_dpencoder = true; + index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); + if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) { + if (crev > 1) { + dp_info.use_dpencoder = false; + } + } + + dp_info.enc_id = 0; + if (dig->dig_encoder) + dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; + else + dp_info.enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; + if (dig->linkb) + dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; + else + dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; + + tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); + if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) + dp_info.tp3_supported = true; + else + dp_info.tp3_supported = false; + + memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); + dp_info.rdev = rdev; + dp_info.encoder = encoder; + dp_info.connector = connector; + dp_info.radeon_connector = radeon_connector; + dp_info.dp_lane_count = dig_connector->dp_lane_count; + dp_info.dp_clock = dig_connector->dp_clock; + + if (radeon_dp_link_train_init(&dp_info)) + goto done; + if (radeon_dp_link_train_cr(&dp_info)) + goto done; + if (radeon_dp_link_train_ce(&dp_info)) + goto done; +done: + if (radeon_dp_link_train_finish(&dp_info)) + return; +} diff --git a/sys/dev/drm2/radeon/atombios_encoders.c b/sys/dev/drm2/radeon/atombios_encoders.c new file mode 100644 index 00000000000..db23f137104 --- /dev/null +++ b/sys/dev/drm2/radeon/atombios_encoders.c @@ -0,0 +1,2660 @@ +/* + * Copyright 2007-11 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon.h" +#include "radeon_asic.h" /* Declares several prototypes; clang is pleased. */ +#include "atom.h" + +static u8 +radeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev) +{ + u8 backlight_level; + u32 bios_2_scratch; + + if (rdev->family >= CHIP_R600) + bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); + else + bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); + + backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >> + ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + + return backlight_level; +} + +static void +radeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev, + u8 backlight_level) +{ + u32 bios_2_scratch; + + if (rdev->family >= CHIP_R600) + bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); + else + bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); + + bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; + bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) & + ATOM_S2_CURRENT_BL_LEVEL_MASK); + + if (rdev->family >= CHIP_R600) + WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); + else + WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); +} + +u8 +atombios_get_backlight_level(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + + if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) + return 0; + + return radeon_atom_get_backlight_level_from_reg(rdev); +} + +void +atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) +{ + struct drm_encoder *encoder = &radeon_encoder->base; + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_atom_dig *dig; + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; + int index; + + if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) + return; + + if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) && + radeon_encoder->enc_priv) { + dig = radeon_encoder->enc_priv; + dig->backlight_level = level; + radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); + if (dig->backlight_level == 0) { + args.ucAction = ATOM_LCD_BLOFF; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } else { + args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + args.ucAction = ATOM_LCD_BLON; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->backlight_level == 0) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); + else { + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); + } + break; + default: + break; + } + } +} + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +static u8 radeon_atom_bl_level(struct backlight_device *bd) +{ + u8 level; + + /* Convert brightness to hardware level */ + if (bd->props.brightness < 0) + level = 0; + else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) + level = RADEON_MAX_BL_LEVEL; + else + level = bd->props.brightness; + + return level; +} + +static int radeon_atom_backlight_update_status(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + struct radeon_encoder *radeon_encoder = pdata->encoder; + + atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd)); + + return 0; +} + +static int radeon_atom_backlight_get_brightness(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + struct radeon_encoder *radeon_encoder = pdata->encoder; + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + + return radeon_atom_get_backlight_level_from_reg(rdev); +} + +static const struct backlight_ops radeon_atom_backlight_ops = { + .get_brightness = radeon_atom_backlight_get_brightness, + .update_status = radeon_atom_backlight_update_status, +}; + +void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, + struct drm_connector *drm_connector) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd; + struct backlight_properties props; + struct radeon_backlight_privdata *pdata; + struct radeon_encoder_atom_dig *dig; + u8 backlight_level; + char bl_name[16]; + + if (!radeon_encoder->enc_priv) + return; + + if (!rdev->is_atom_bios) + return; + + if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) + return; + + pdata = malloc(sizeof(struct radeon_backlight_privdata), DRM_MEM_DRIVER, M_WAITOK); + if (!pdata) { + DRM_ERROR("Memory allocation failed\n"); + goto error; + } + + memset(&props, 0, sizeof(props)); + props.max_brightness = RADEON_MAX_BL_LEVEL; + props.type = BACKLIGHT_RAW; + snprintf(bl_name, sizeof(bl_name), + "radeon_bl%d", dev->primary->index); + bd = backlight_device_register(bl_name, &drm_connector->kdev, + pdata, &radeon_atom_backlight_ops, &props); + if (IS_ERR(bd)) { + DRM_ERROR("Backlight registration failed\n"); + goto error; + } + + pdata->encoder = radeon_encoder; + + backlight_level = radeon_atom_get_backlight_level_from_reg(rdev); + + dig = radeon_encoder->enc_priv; + dig->bl_dev = bd; + + bd->props.brightness = radeon_atom_backlight_get_brightness(bd); + bd->props.power = FB_BLANK_UNBLANK; + backlight_update_status(bd); + + DRM_INFO("radeon atom DIG backlight initialized\n"); + + return; + +error: + free(pdata, DRM_MEM_DRIVER); + return; +} + +static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd = NULL; + struct radeon_encoder_atom_dig *dig; + + if (!radeon_encoder->enc_priv) + return; + + if (!rdev->is_atom_bios) + return; + + if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) + return; + + dig = radeon_encoder->enc_priv; + bd = dig->bl_dev; + dig->bl_dev = NULL; + + if (bd) { + struct radeon_legacy_backlight_privdata *pdata; + + pdata = bl_get_data(bd); + backlight_device_unregister(bd); + free(pdata, DRM_MEM_DRIVER); + + DRM_INFO("radeon atom LVDS backlight unloaded\n"); + } +} + +#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */ + +void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, + struct drm_connector *drm_connector) +{ +} + +static void radeon_atom_backlight_exit(struct radeon_encoder *encoder) +{ +} + +#endif + + +static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + return true; + default: + return false; + } +} + +static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + + /* set the active encoder to connector routing */ + radeon_encoder_set_active_device(encoder); + drm_mode_set_crtcinfo(adjusted_mode, 0); + + /* hw bug */ + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) + && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) + adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; + + /* get the native mode for LVDS */ + if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) + radeon_panel_mode_fixup(encoder, adjusted_mode); + + /* get the native mode for TV */ + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { + struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; + if (tv_dac) { + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M) + radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); + else + radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); + } + } + + if (ASIC_IS_DCE3(rdev) && + ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + radeon_dp_set_link_config(connector, adjusted_mode); + } + + return true; +} + +static void +atombios_dac_setup(struct drm_encoder *encoder, int action) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + DAC_ENCODER_CONTROL_PS_ALLOCATION args; + int index = 0; + struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; + + memset(&args, 0, sizeof(args)); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); + break; + } + + args.ucAction = action; + + if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) + args.ucDacStandard = ATOM_DAC1_PS2; + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + args.ucDacStandard = ATOM_DAC1_CV; + else { + switch (dac_info->tv_std) { + case TV_STD_PAL: + case TV_STD_PAL_M: + case TV_STD_SCART_PAL: + case TV_STD_SECAM: + case TV_STD_PAL_CN: + args.ucDacStandard = ATOM_DAC1_PAL; + break; + case TV_STD_NTSC: + case TV_STD_NTSC_J: + case TV_STD_PAL_60: + default: + args.ucDacStandard = ATOM_DAC1_NTSC; + break; + } + } + args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + +} + +static void +atombios_tv_setup(struct drm_encoder *encoder, int action) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + TV_ENCODER_CONTROL_PS_ALLOCATION args; + int index = 0; + struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; + + memset(&args, 0, sizeof(args)); + + index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); + + args.sTVEncoder.ucAction = action; + + if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + args.sTVEncoder.ucTvStandard = ATOM_TV_CV; + else { + switch (dac_info->tv_std) { + case TV_STD_NTSC: + args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; + break; + case TV_STD_PAL: + args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; + break; + case TV_STD_PAL_M: + args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; + break; + case TV_STD_PAL_60: + args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; + break; + case TV_STD_NTSC_J: + args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; + break; + case TV_STD_SCART_PAL: + args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ + break; + case TV_STD_SECAM: + args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; + break; + case TV_STD_PAL_CN: + args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; + break; + default: + args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; + break; + } + } + + args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + +} + +static u8 radeon_atom_get_bpc(struct drm_encoder *encoder) +{ + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + int bpc = 8; + + if (connector) + bpc = radeon_get_monitor_bpc(connector); + + switch (bpc) { + case 0: + return PANEL_BPC_UNDEFINE; + case 6: + return PANEL_6BIT_PER_COLOR; + case 8: + default: + return PANEL_8BIT_PER_COLOR; + case 10: + return PANEL_10BIT_PER_COLOR; + case 12: + return PANEL_12BIT_PER_COLOR; + case 16: + return PANEL_16BIT_PER_COLOR; + } +} + + +union dvo_encoder_control { + ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds; + DVO_ENCODER_CONTROL_PS_ALLOCATION dvo; + DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3; +}; + +void +atombios_dvo_setup(struct drm_encoder *encoder, int action) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + union dvo_encoder_control args; + int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); + uint8_t frev, crev; + + memset(&args, 0, sizeof(args)); + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + /* some R4xx chips have the wrong frev */ + if (rdev->family <= CHIP_RV410) + frev = 1; + + switch (frev) { + case 1: + switch (crev) { + case 1: + /* R4xx, R5xx */ + args.ext_tmds.sXTmdsEncoder.ucEnable = action; + + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; + + args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; + break; + case 2: + /* RS600/690/740 */ + args.dvo.sDVOEncoder.ucAction = action; + args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + /* DFP1, CRT1, TV1 depending on the type of port */ + args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; + + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; + break; + case 3: + /* R6xx */ + args.dvo_v3.ucAction = action; + args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + args.dvo_v3.ucDVOConfig = 0; /* XXX */ + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +union lvds_encoder_control { + LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; + LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; +}; + +void +atombios_digital_setup(struct drm_encoder *encoder, int action) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + union lvds_encoder_control args; + int index = 0; + int hdmi_detected = 0; + uint8_t frev, crev; + + if (!dig) + return; + + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) + hdmi_detected = 1; + + memset(&args, 0, sizeof(args)); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); + break; + } + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + switch (frev) { + case 1: + case 2: + switch (crev) { + case 1: + args.v1.ucMisc = 0; + args.v1.ucAction = action; + if (hdmi_detected) + args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; + args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) + args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; + if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) + args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; + } else { + if (dig->linkb) + args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; + /*if (pScrn->rgbBits == 8) */ + args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; + } + break; + case 2: + case 3: + args.v2.ucMisc = 0; + args.v2.ucAction = action; + if (crev == 3) { + if (dig->coherent_mode) + args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; + } + if (hdmi_detected) + args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; + args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + args.v2.ucTruncate = 0; + args.v2.ucSpatial = 0; + args.v2.ucTemporal = 0; + args.v2.ucFRC = 0; + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) + args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; + if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { + args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; + if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) + args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; + } + if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { + args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; + if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) + args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; + if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) + args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; + } + } else { + if (dig->linkb) + args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; + } + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +int +atombios_get_encoder_mode(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + + /* dp bridges are always DP */ + if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) + return ATOM_ENCODER_MODE_DP; + + /* DVO is always DVO */ + if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) || + (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) + return ATOM_ENCODER_MODE_DVO; + + connector = radeon_get_connector_for_encoder(encoder); + /* if we don't have an active device yet, just use one of + * the connectors tied to the encoder. + */ + if (!connector) + connector = radeon_get_connector_for_encoder_init(encoder); + radeon_connector = to_radeon_connector(connector); + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ + if (drm_detect_hdmi_monitor(radeon_connector->edid) && + radeon_audio) + return ATOM_ENCODER_MODE_HDMI; + else if (radeon_connector->use_digital) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_CRT; + break; + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + default: + if (drm_detect_hdmi_monitor(radeon_connector->edid) && + radeon_audio) + return ATOM_ENCODER_MODE_HDMI; + else + return ATOM_ENCODER_MODE_DVI; + break; + case DRM_MODE_CONNECTOR_LVDS: + return ATOM_ENCODER_MODE_LVDS; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + dig_connector = radeon_connector->con_priv; + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + return ATOM_ENCODER_MODE_DP; + else if (drm_detect_hdmi_monitor(radeon_connector->edid) && + radeon_audio) + return ATOM_ENCODER_MODE_HDMI; + else + return ATOM_ENCODER_MODE_DVI; + break; + case DRM_MODE_CONNECTOR_eDP: + return ATOM_ENCODER_MODE_DP; + case DRM_MODE_CONNECTOR_DVIA: + case DRM_MODE_CONNECTOR_VGA: + return ATOM_ENCODER_MODE_CRT; + break; + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_9PinDIN: + /* fix me */ + return ATOM_ENCODER_MODE_TV; + /*return ATOM_ENCODER_MODE_CV;*/ + break; + } +} + +/* + * DIG Encoder/Transmitter Setup + * + * DCE 3.0/3.1 + * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. + * Supports up to 3 digital outputs + * - 2 DIG encoder blocks. + * DIG1 can drive UNIPHY link A or link B + * DIG2 can drive UNIPHY link B or LVTMA + * + * DCE 3.2 + * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). + * Supports up to 5 digital outputs + * - 2 DIG encoder blocks. + * DIG1/2 can drive UNIPHY0/1/2 link A or link B + * + * DCE 4.0/5.0/6.0 + * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). + * Supports up to 6 digital outputs + * - 6 DIG encoder blocks. + * - DIG to PHY mapping is hardcoded + * DIG1 drives UNIPHY0 link A, A+B + * DIG2 drives UNIPHY0 link B + * DIG3 drives UNIPHY1 link A, A+B + * DIG4 drives UNIPHY1 link B + * DIG5 drives UNIPHY2 link A, A+B + * DIG6 drives UNIPHY2 link B + * + * DCE 4.1 + * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). + * Supports up to 6 digital outputs + * - 2 DIG encoder blocks. + * llano + * DIG1/2 can drive UNIPHY0/1/2 link A or link B + * ontario + * DIG1 drives UNIPHY0/1/2 link A + * DIG2 drives UNIPHY0/1/2 link B + * + * Routing + * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) + * Examples: + * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI + * crtc1 -> dig1 -> UNIPHY0 link B -> DP + * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS + * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI + */ + +union dig_encoder_control { + DIG_ENCODER_CONTROL_PS_ALLOCATION v1; + DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; + DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; + DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; +}; + +void +atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + union dig_encoder_control args; + int index = 0; + uint8_t frev, crev; + int dp_clock = 0; + int dp_lane_count = 0; + int hpd_id = RADEON_HPD_NONE; + + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + hpd_id = radeon_connector->hpd.hpd; + } + + /* no dig encoder assigned */ + if (dig->dig_encoder == -1) + return; + + memset(&args, 0, sizeof(args)); + + if (ASIC_IS_DCE4(rdev)) + index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); + else { + if (dig->dig_encoder) + index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); + } + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + switch (frev) { + case 1: + switch (crev) { + case 1: + args.v1.ucAction = action; + args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) + args.v3.ucPanelMode = panel_mode; + else + args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) + args.v1.ucLaneNum = dp_lane_count; + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.ucLaneNum = 8; + else + args.v1.ucLaneNum = 4; + + if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000)) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; + break; + } + if (dig->linkb) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; + else + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; + break; + case 2: + case 3: + args.v3.ucAction = action; + args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) + args.v3.ucPanelMode = panel_mode; + else + args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode)) + args.v3.ucLaneNum = dp_lane_count; + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.ucLaneNum = 8; + else + args.v3.ucLaneNum = 4; + + if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000)) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; + args.v3.acConfig.ucDigSel = dig->dig_encoder; + args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder); + break; + case 4: + args.v4.ucAction = action; + args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) + args.v4.ucPanelMode = panel_mode; + else + args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) + args.v4.ucLaneNum = dp_lane_count; + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.ucLaneNum = 8; + else + args.v4.ucLaneNum = 4; + + if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) { + if (dp_clock == 270000) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; + else if (dp_clock == 540000) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; + } + args.v4.acConfig.ucDigSel = dig->dig_encoder; + args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder); + if (hpd_id == RADEON_HPD_NONE) + args.v4.ucHPD_ID = 0; + else + args.v4.ucHPD_ID = hpd_id + 1; + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + +} + +union dig_transmitter_control { + DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5; +}; + +void +atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector; + union dig_transmitter_control args; + int index = 0; + uint8_t frev, crev; + bool is_dp = false; + int pll_id = 0; + int dp_clock = 0; + int dp_lane_count = 0; + int connector_object_id = 0; + int igp_lane_info = 0; + int dig_encoder = dig->dig_encoder; + int hpd_id = RADEON_HPD_NONE; + + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + connector = radeon_get_connector_for_encoder_init(encoder); + /* just needed to avoid bailing in the encoder check. the encoder + * isn't used for init + */ + dig_encoder = 0; + } else + connector = radeon_get_connector_for_encoder(encoder); + + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + hpd_id = radeon_connector->hpd.hpd; + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + connector_object_id = + (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + igp_lane_info = dig_connector->igp_lane_info; + } + + if (encoder->crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + pll_id = radeon_crtc->pll_id; + } + + /* no dig encoder assigned */ + if (dig_encoder == -1) + return; + + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))) + is_dp = true; + + memset(&args, 0, sizeof(args)); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); + break; + } + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + switch (frev) { + case 1: + switch (crev) { + case 1: + args.v1.ucAction = action; + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + args.v1.usInitInfo = cpu_to_le16(connector_object_id); + } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { + args.v1.asMode.ucLaneSel = lane_num; + args.v1.asMode.ucLaneSet = lane_set; + } else { + if (is_dp) + args.v1.usPixelClock = cpu_to_le16(dp_clock / 10); + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + } + + args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; + + if (dig_encoder) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; + else + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; + + if ((rdev->flags & RADEON_IS_IGP) && + (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { + if (is_dp || + !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) { + if (igp_lane_info & 0x1) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; + else if (igp_lane_info & 0x2) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; + else if (igp_lane_info & 0x4) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; + else if (igp_lane_info & 0x8) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; + } else { + if (igp_lane_info & 0x3) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; + else if (igp_lane_info & 0xc) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; + } + } + + if (dig->linkb) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; + else + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; + + if (is_dp) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; + } + break; + case 2: + args.v2.ucAction = action; + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + args.v2.usInitInfo = cpu_to_le16(connector_object_id); + } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { + args.v2.asMode.ucLaneSel = lane_num; + args.v2.asMode.ucLaneSet = lane_set; + } else { + if (is_dp) + args.v2.usPixelClock = cpu_to_le16(dp_clock / 10); + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + } + + args.v2.acConfig.ucEncoderSel = dig_encoder; + if (dig->linkb) + args.v2.acConfig.ucLinkSel = 1; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + args.v2.acConfig.ucTransmitterSel = 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + args.v2.acConfig.ucTransmitterSel = 1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + args.v2.acConfig.ucTransmitterSel = 2; + break; + } + + if (is_dp) { + args.v2.acConfig.fCoherentMode = 1; + args.v2.acConfig.fDPConnector = 1; + } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v2.acConfig.fCoherentMode = 1; + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v2.acConfig.fDualLinkConnector = 1; + } + break; + case 3: + args.v3.ucAction = action; + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + args.v3.usInitInfo = cpu_to_le16(connector_object_id); + } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { + args.v3.asMode.ucLaneSel = lane_num; + args.v3.asMode.ucLaneSet = lane_set; + } else { + if (is_dp) + args.v3.usPixelClock = cpu_to_le16(dp_clock / 10); + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + } + + if (is_dp) + args.v3.ucLaneNum = dp_lane_count; + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.ucLaneNum = 8; + else + args.v3.ucLaneNum = 4; + + if (dig->linkb) + args.v3.acConfig.ucLinkSel = 1; + if (dig_encoder & 1) + args.v3.acConfig.ucEncoderSel = 1; + + /* Select the PLL for the PHY + * DP PHY should be clocked from external src if there is + * one. + */ + /* On DCE4, if there is an external clock, it generates the DP ref clock */ + if (is_dp && rdev->clock.dp_extclk) + args.v3.acConfig.ucRefClkSource = 2; /* external src */ + else + args.v3.acConfig.ucRefClkSource = pll_id; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + args.v3.acConfig.ucTransmitterSel = 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + args.v3.acConfig.ucTransmitterSel = 1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + args.v3.acConfig.ucTransmitterSel = 2; + break; + } + + if (is_dp) + args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v3.acConfig.fCoherentMode = 1; + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.acConfig.fDualLinkConnector = 1; + } + break; + case 4: + args.v4.ucAction = action; + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + args.v4.usInitInfo = cpu_to_le16(connector_object_id); + } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { + args.v4.asMode.ucLaneSel = lane_num; + args.v4.asMode.ucLaneSet = lane_set; + } else { + if (is_dp) + args.v4.usPixelClock = cpu_to_le16(dp_clock / 10); + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + } + + if (is_dp) + args.v4.ucLaneNum = dp_lane_count; + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.ucLaneNum = 8; + else + args.v4.ucLaneNum = 4; + + if (dig->linkb) + args.v4.acConfig.ucLinkSel = 1; + if (dig_encoder & 1) + args.v4.acConfig.ucEncoderSel = 1; + + /* Select the PLL for the PHY + * DP PHY should be clocked from external src if there is + * one. + */ + /* On DCE5 DCPLL usually generates the DP ref clock */ + if (is_dp) { + if (rdev->clock.dp_extclk) + args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK; + else + args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL; + } else + args.v4.acConfig.ucRefClkSource = pll_id; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + args.v4.acConfig.ucTransmitterSel = 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + args.v4.acConfig.ucTransmitterSel = 1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + args.v4.acConfig.ucTransmitterSel = 2; + break; + } + + if (is_dp) + args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */ + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v4.acConfig.fCoherentMode = 1; + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.acConfig.fDualLinkConnector = 1; + } + break; + case 5: + args.v5.ucAction = action; + if (is_dp) + args.v5.usSymClock = cpu_to_le16(dp_clock / 10); + else + args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB; + else + args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD; + else + args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF; + else + args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE; + break; + } + if (is_dp) + args.v5.ucLaneNum = dp_lane_count; + else if (radeon_encoder->pixel_clock > 165000) + args.v5.ucLaneNum = 8; + else + args.v5.ucLaneNum = 4; + args.v5.ucConnObjId = connector_object_id; + args.v5.ucDigMode = atombios_get_encoder_mode(encoder); + + if (is_dp && rdev->clock.dp_extclk) + args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK; + else + args.v5.asConfig.ucPhyClkSrcId = pll_id; + + if (is_dp) + args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */ + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v5.asConfig.ucCoherentMode = 1; + } + if (hpd_id == RADEON_HPD_NONE) + args.v5.asConfig.ucHPDSel = 0; + else + args.v5.asConfig.ucHPDSel = hpd_id + 1; + args.v5.ucDigEncoderSel = 1 << dig_encoder; + args.v5.ucDPLaneSet = lane_set; + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +bool +atombios_set_edp_panel_power(struct drm_connector *connector, int action) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_device *dev = radeon_connector->base.dev; + struct radeon_device *rdev = dev->dev_private; + union dig_transmitter_control args; + int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); + uint8_t frev, crev; + + if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) + goto done; + + if (!ASIC_IS_DCE4(rdev)) + goto done; + + if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) && + (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) + goto done; + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + goto done; + + memset(&args, 0, sizeof(args)); + + args.v1.ucAction = action; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + /* wait for the panel to power up */ + if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) { + int i; + + for (i = 0; i < 300; i++) { + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + return true; + DRM_MDELAY(1); + } + return false; + } +done: + return true; +} + +union external_encoder_control { + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; +}; + +static void +atombios_external_encoder_setup(struct drm_encoder *encoder, + struct drm_encoder *ext_encoder, + int action) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); + union external_encoder_control args; + struct drm_connector *connector; + int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); + u8 frev, crev; + int dp_clock = 0; + int dp_lane_count = 0; + int connector_object_id = 0; + u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + + if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) + connector = radeon_get_connector_for_encoder_init(encoder); + else + connector = radeon_get_connector_for_encoder(encoder); + + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + connector_object_id = + (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + } + + memset(&args, 0, sizeof(args)); + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + switch (frev) { + case 1: + /* no params on frev 1 */ + break; + case 2: + switch (crev) { + case 1: + case 2: + args.v1.sDigEncoder.ucAction = action; + args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) { + if (dp_clock == 270000) + args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + args.v1.sDigEncoder.ucLaneNum = dp_lane_count; + } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.sDigEncoder.ucLaneNum = 8; + else + args.v1.sDigEncoder.ucLaneNum = 4; + break; + case 3: + args.v3.sExtEncoder.ucAction = action; + if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) + args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id); + else + args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) { + if (dp_clock == 270000) + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; + else if (dp_clock == 540000) + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; + args.v3.sExtEncoder.ucLaneNum = dp_lane_count; + } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.sExtEncoder.ucLaneNum = 8; + else + args.v3.sExtEncoder.ucLaneNum = 4; + switch (ext_enum) { + case GRAPH_OBJECT_ENUM_ID1: + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; + break; + case GRAPH_OBJECT_ENUM_ID2: + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; + break; + case GRAPH_OBJECT_ENUM_ID3: + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; + break; + } + args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder); + break; + default: + DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); + return; + } + break; + default: + DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); + return; + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static void +atombios_yuv_setup(struct drm_encoder *encoder, bool enable) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + ENABLE_YUV_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); + uint32_t temp, reg; + + memset(&args, 0, sizeof(args)); + + if (rdev->family >= CHIP_R600) + reg = R600_BIOS_3_SCRATCH; + else + reg = RADEON_BIOS_3_SCRATCH; + + /* XXX: fix up scratch reg handling */ + temp = RREG32(reg); + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + WREG32(reg, (ATOM_S3_TV1_ACTIVE | + (radeon_crtc->crtc_id << 18))); + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); + else + WREG32(reg, 0); + + if (enable) + args.ucEnable = ATOM_ENABLE; + args.ucCRTC = radeon_crtc->crtc_id; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + WREG32(reg, temp); +} + +static void +radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; + int index = 0; + + memset(&args, 0, sizeof(args)); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); + break; + default: + return; + } + + switch (mode) { + case DRM_MODE_DPMS_ON: + args.ucAction = ATOM_ENABLE; + /* workaround for DVOOutputControl on some RS690 systems */ + if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) { + u32 reg = RREG32(RADEON_BIOS_3_SCRATCH); + WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE); + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + WREG32(RADEON_BIOS_3_SCRATCH, reg); + } else + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + args.ucAction = ATOM_LCD_BLON; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + args.ucAction = ATOM_DISABLE; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + args.ucAction = ATOM_LCD_BLOFF; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + break; + } +} + +static void +radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_connector *radeon_connector = NULL; + struct radeon_connector_atom_dig *radeon_dig_connector = NULL; + + if (connector) { + radeon_connector = to_radeon_connector(connector); + radeon_dig_connector = radeon_connector->con_priv; + } + + switch (mode) { + case DRM_MODE_DPMS_ON: + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + if (ext_encoder) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + } + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + } else if (ASIC_IS_DCE4(rdev)) { + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + /* enable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } else { + /* setup and enable the encoder and transmitter */ + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_ON); + radeon_dig_connector->edp_on = true; + } + radeon_dp_link_train(encoder, connector); + if (ASIC_IS_DCE4(rdev)) + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); + } + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + /* disable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + } else if (ASIC_IS_DCE4(rdev)) { + /* disable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + } else { + /* disable the encoder and transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + } + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { + if (ASIC_IS_DCE4(rdev)) + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_OFF); + radeon_dig_connector->edp_on = false; + } + } + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); + break; + } +} + +static void +radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder, + struct drm_encoder *ext_encoder, + int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + + switch (mode) { + case DRM_MODE_DPMS_ON: + default: + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); + break; + } +} + +static void +radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + + DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", + radeon_encoder->encoder_id, mode, radeon_encoder->devices, + radeon_encoder->active_device); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + radeon_atom_encoder_dpms_avivo(encoder, mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + radeon_atom_encoder_dpms_dig(encoder, mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + if (ASIC_IS_DCE5(rdev)) { + switch (mode) { + case DRM_MODE_DPMS_ON: + atombios_dvo_setup(encoder, ATOM_ENABLE); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + atombios_dvo_setup(encoder, ATOM_DISABLE); + break; + } + } else if (ASIC_IS_DCE3(rdev)) + radeon_atom_encoder_dpms_dig(encoder, mode); + else + radeon_atom_encoder_dpms_avivo(encoder, mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + if (ASIC_IS_DCE5(rdev)) { + switch (mode) { + case DRM_MODE_DPMS_ON: + atombios_dac_setup(encoder, ATOM_ENABLE); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + atombios_dac_setup(encoder, ATOM_DISABLE); + break; + } + } else + radeon_atom_encoder_dpms_avivo(encoder, mode); + break; + default: + return; + } + + if (ext_encoder) + radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode); + + radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + +} + +union crtc_source_param { + SELECT_CRTC_SOURCE_PS_ALLOCATION v1; + SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; +}; + +static void +atombios_set_encoder_crtc_source(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + union crtc_source_param args; + int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); + uint8_t frev, crev; + struct radeon_encoder_atom_dig *dig; + + memset(&args, 0, sizeof(args)); + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + switch (frev) { + case 1: + switch (crev) { + case 1: + default: + if (ASIC_IS_AVIVO(rdev)) + args.v1.ucCRTC = radeon_crtc->crtc_id; + else { + if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { + args.v1.ucCRTC = radeon_crtc->crtc_id; + } else { + args.v1.ucCRTC = radeon_crtc->crtc_id << 2; + } + } + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) + args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; + else + args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; + else + args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; + else + args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; + break; + } + break; + case 2: + args.v2.ucCRTC = radeon_crtc->crtc_id; + if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) + args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; + else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA) + args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; + else + args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); + } else + args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + dig = radeon_encoder->enc_priv; + switch (dig->dig_encoder) { + case 0: + args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; + break; + case 1: + args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; + break; + case 2: + args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; + break; + case 3: + args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; + break; + case 4: + args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; + break; + case 5: + args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; + break; + } + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; + else + args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) + args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; + else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) + args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; + else + args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; + break; + } + break; + } + break; + default: + DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); + return; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + /* update scratch regs with new routing */ + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); +} + +static void +atombios_apply_encoder_quirks(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + + /* Funky macbooks */ + if ((dev->pci_device == 0x71C5) && + (dev->pci_subvendor == 0x106b) && + (dev->pci_subdevice == 0x0080)) { + if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { + uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); + + lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; + lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; + + WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); + } + } + + /* set scaler clears this on some chips */ + if (ASIC_IS_AVIVO(rdev) && + (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) { + if (ASIC_IS_DCE4(rdev)) { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, + EVERGREEN_INTERLEAVE_EN); + else + WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); + } else { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, + AVIVO_D1MODE_INTERLEAVE_EN); + else + WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); + } + } +} + +static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *test_encoder; + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t dig_enc_in_use = 0; + + if (ASIC_IS_DCE6(rdev)) { + /* DCE6 */ + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + } + } else if (ASIC_IS_DCE4(rdev)) { + /* DCE4/5 */ + if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { + /* ontario follows DCE4 */ + if (rdev->family == CHIP_PALM) { + if (dig->linkb) + return 1; + else + return 0; + } else + /* llano follows DCE3.2 */ + return radeon_crtc->crtc_id; + } else { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + } + } + } + + /* on DCE32 and encoder can driver any block so just crtc id */ + if (ASIC_IS_DCE32(rdev)) { + return radeon_crtc->crtc_id; + } + + /* on DCE3 - LVTMA can only be driven by DIGB */ + list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { + struct radeon_encoder *radeon_test_encoder; + + if (encoder == test_encoder) + continue; + + if (!radeon_encoder_is_digital(test_encoder)) + continue; + + radeon_test_encoder = to_radeon_encoder(test_encoder); + dig = radeon_test_encoder->enc_priv; + + if (dig->dig_encoder >= 0) + dig_enc_in_use |= (1 << dig->dig_encoder); + } + + if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { + if (dig_enc_in_use & 0x2) + DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n"); + return 1; + } + if (!(dig_enc_in_use & 1)) + return 0; + return 1; +} + +/* This only needs to be called once at startup */ +void +radeon_atom_encoder_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); + break; + default: + break; + } + + if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); + } +} + +static void +radeon_atom_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + radeon_encoder->pixel_clock = adjusted_mode->clock; + + /* need to call this here rather than in prepare() since we need some crtc info */ + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { + if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) + atombios_yuv_setup(encoder, true); + else + atombios_yuv_setup(encoder, false); + } + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + /* handled in dpms */ + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + atombios_dvo_setup(encoder, ATOM_ENABLE); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + atombios_dac_setup(encoder, ATOM_ENABLE); + if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { + if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) + atombios_tv_setup(encoder, ATOM_ENABLE); + else + atombios_tv_setup(encoder, ATOM_DISABLE); + } + break; + } + + atombios_apply_encoder_quirks(encoder, adjusted_mode); + + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { + r600_hdmi_enable(encoder); + if (ASIC_IS_DCE6(rdev)) + ; /* TODO (use pointers instead of if-s?) */ + else if (ASIC_IS_DCE4(rdev)) + evergreen_hdmi_setmode(encoder, adjusted_mode); + else + r600_hdmi_setmode(encoder, adjusted_mode); + } +} + +static bool +atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | + ATOM_DEVICE_CV_SUPPORT | + ATOM_DEVICE_CRT_SUPPORT)) { + DAC_LOAD_DETECTION_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); + uint8_t frev, crev; + + memset(&args, 0, sizeof(args)); + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return false; + + args.sDacload.ucMisc = 0; + + if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || + (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) + args.sDacload.ucDacType = ATOM_DAC_A; + else + args.sDacload.ucDacType = ATOM_DAC_B; + + if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) + args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); + else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) + args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); + else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { + args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); + if (crev >= 3) + args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; + } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { + args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); + if (crev >= 3) + args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + return true; + } else + return false; +} + +static enum drm_connector_status +radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + uint32_t bios_0_scratch; + + if (!atombios_dac_load_detect(encoder, connector)) { + DRM_DEBUG_KMS("detect returned false \n"); + return connector_status_unknown; + } + + if (rdev->family >= CHIP_R600) + bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); + else + bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); + + DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); + if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT1_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT2_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) + return connector_status_connected; /* CTV */ + else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) + return connector_status_connected; /* STV */ + } + return connector_status_disconnected; +} + +static enum drm_connector_status +radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + u32 bios_0_scratch; + + if (!ASIC_IS_DCE4(rdev)) + return connector_status_unknown; + + if (!ext_encoder) + return connector_status_unknown; + + if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) + return connector_status_unknown; + + /* load detect on the dp bridge */ + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); + + bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); + + DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); + if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT1_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT2_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) + return connector_status_connected; /* CTV */ + else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) + return connector_status_connected; /* STV */ + } + return connector_status_disconnected; +} + +void +radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) +{ + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + + if (ext_encoder) + /* ddc_setup on the dp bridge */ + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + +} + +static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + + if ((radeon_encoder->active_device & + (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(encoder) != + ENCODER_OBJECT_ID_NONE)) { + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + if (dig) { + dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); + if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) { + if (rdev->family >= CHIP_R600) + dig->afmt = rdev->mode_info.afmt[dig->dig_encoder]; + else + /* RS600/690/740 have only 1 afmt block */ + dig->afmt = rdev->mode_info.afmt[0]; + } + } + } + + radeon_atom_output_lock(encoder, true); + + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + /* select the clock/data port if it uses a router */ + if (radeon_connector->router.cd_valid) + radeon_router_select_cd_port(radeon_connector); + + /* turn eDP panel on for mode set */ + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_ON); + } + + /* this is needed for the pll/ss setup to work correctly in some cases */ + atombios_set_encoder_crtc_source(encoder); +} + +static void radeon_atom_encoder_commit(struct drm_encoder *encoder) +{ + /* need to call this here as we need the crtc set up */ + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); + radeon_atom_output_lock(encoder, false); +} + +static void radeon_atom_encoder_disable(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig; + + /* check for pre-DCE3 cards with shared encoders; + * can't really use the links individually, so don't disable + * the encoder if it's in use by another connector + */ + if (!ASIC_IS_DCE3(rdev)) { + struct drm_encoder *other_encoder; + struct radeon_encoder *other_radeon_encoder; + + list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { + other_radeon_encoder = to_radeon_encoder(other_encoder); + if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && + drm_helper_encoder_in_use(other_encoder)) + goto disable_done; + } + } + + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + /* handled in dpms */ + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + atombios_dvo_setup(encoder, ATOM_DISABLE); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + atombios_dac_setup(encoder, ATOM_DISABLE); + if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) + atombios_tv_setup(encoder, ATOM_DISABLE); + break; + } + +disable_done: + if (radeon_encoder_is_digital(encoder)) { + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) + r600_hdmi_disable(encoder); + dig = radeon_encoder->enc_priv; + dig->dig_encoder = -1; + } + radeon_encoder->active_device = 0; +} + +/* these are handled by the primary encoders */ +static void radeon_atom_ext_prepare(struct drm_encoder *encoder) +{ + +} + +static void radeon_atom_ext_commit(struct drm_encoder *encoder) +{ + +} + +static void +radeon_atom_ext_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + +} + +static void radeon_atom_ext_disable(struct drm_encoder *encoder) +{ + +} + +static void +radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) +{ + +} + +static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { + .dpms = radeon_atom_ext_dpms, + .mode_fixup = radeon_atom_ext_mode_fixup, + .prepare = radeon_atom_ext_prepare, + .mode_set = radeon_atom_ext_mode_set, + .commit = radeon_atom_ext_commit, + .disable = radeon_atom_ext_disable, + /* no detect for TMDS/LVDS yet */ +}; + +static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { + .dpms = radeon_atom_encoder_dpms, + .mode_fixup = radeon_atom_mode_fixup, + .prepare = radeon_atom_encoder_prepare, + .mode_set = radeon_atom_encoder_mode_set, + .commit = radeon_atom_encoder_commit, + .disable = radeon_atom_encoder_disable, + .detect = radeon_atom_dig_detect, +}; + +static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { + .dpms = radeon_atom_encoder_dpms, + .mode_fixup = radeon_atom_mode_fixup, + .prepare = radeon_atom_encoder_prepare, + .mode_set = radeon_atom_encoder_mode_set, + .commit = radeon_atom_encoder_commit, + .detect = radeon_atom_dac_detect, +}; + +void radeon_enc_destroy(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + radeon_atom_backlight_exit(radeon_encoder); + free(radeon_encoder->enc_priv, DRM_MEM_DRIVER); + drm_encoder_cleanup(encoder); + free(radeon_encoder, DRM_MEM_DRIVER); +} + +static const struct drm_encoder_funcs radeon_atom_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +static struct radeon_encoder_atom_dac * +radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_atom_dac *dac = malloc(sizeof(struct radeon_encoder_atom_dac), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + + if (!dac) + return NULL; + + dac->tv_std = radeon_atombios_get_tv_info(rdev); + return dac; +} + +static struct radeon_encoder_atom_dig * +radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) +{ + int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + struct radeon_encoder_atom_dig *dig = malloc(sizeof(struct radeon_encoder_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + + if (!dig) + return NULL; + + /* coherent mode by default */ + dig->coherent_mode = true; + dig->dig_encoder = -1; + + if (encoder_enum == 2) + dig->linkb = true; + else + dig->linkb = false; + + return dig; +} + +void +radeon_add_atom_encoder(struct drm_device *dev, + uint32_t encoder_enum, + uint32_t supported_device, + u16 caps) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + + /* see if we already added it */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->encoder_enum == encoder_enum) { + radeon_encoder->devices |= supported_device; + return; + } + + } + + /* add a new one */ + radeon_encoder = malloc(sizeof(struct radeon_encoder), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_encoder) + return; + + encoder = &radeon_encoder->base; + switch (rdev->num_crtc) { + case 1: + encoder->possible_crtcs = 0x1; + break; + case 2: + default: + encoder->possible_crtcs = 0x3; + break; + case 4: + encoder->possible_crtcs = 0xf; + break; + case 6: + encoder->possible_crtcs = 0x3f; + break; + } + + radeon_encoder->enc_priv = NULL; + + radeon_encoder->encoder_enum = encoder_enum; + radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + radeon_encoder->devices = supported_device; + radeon_encoder->rmx_type = RMX_OFF; + radeon_encoder->underscan_type = UNDERSCAN_OFF; + radeon_encoder->is_ext_encoder = false; + radeon_encoder->caps = caps; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + radeon_encoder->rmx_type = RMX_FULL; + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); + radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); + } else { + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); + radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); + } + drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); + radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); + drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); + radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); + drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + radeon_encoder->rmx_type = RMX_FULL; + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); + radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); + } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); + radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); + } else { + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); + radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); + } + drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); + break; + case ENCODER_OBJECT_ID_SI170B: + case ENCODER_OBJECT_ID_CH7303: + case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: + case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: + case ENCODER_OBJECT_ID_TITFP513: + case ENCODER_OBJECT_ID_VT1623: + case ENCODER_OBJECT_ID_HDMI_SI1930: + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + /* these are handled by the primary encoders */ + radeon_encoder->is_ext_encoder = true; + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); + else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); + else + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs); + break; + } +} diff --git a/sys/dev/drm2/radeon/atombios_i2c.c b/sys/dev/drm2/radeon/atombios_i2c.c new file mode 100644 index 00000000000..40ba15be931 --- /dev/null +++ b/sys/dev/drm2/radeon/atombios_i2c.c @@ -0,0 +1,203 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include "radeon.h" +#include "atom.h" +#include "iicbus_if.h" +#include "iicbb_if.h" + +#define TARGET_HW_I2C_CLOCK 50 + +/* these are a limitation of ProcessI2cChannelTransaction not the hw */ +#define ATOM_MAX_HW_I2C_WRITE 2 +#define ATOM_MAX_HW_I2C_READ 255 + +static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, + u8 slave_addr, u8 flags, + u8 *buf, u8 num) +{ + struct drm_device *dev = chan->dev; + struct radeon_device *rdev = dev->dev_private; + PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); + unsigned char *base; + u16 out; + + memset(&args, 0, sizeof(args)); + + base = (unsigned char *)rdev->mode_info.atom_context->scratch; + + if (flags & HW_I2C_WRITE) { + if (num > ATOM_MAX_HW_I2C_WRITE) { + DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 2)\n", num); + return EINVAL; + } + memcpy(&out, buf, num); + args.lpI2CDataOut = cpu_to_le16(out); + } + + args.ucI2CSpeed = TARGET_HW_I2C_CLOCK; + args.ucRegIndex = 0; + args.ucTransBytes = num; + args.ucSlaveAddr = slave_addr << 1; + args.ucLineNumber = chan->rec.i2c_id; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + /* error */ + if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) { + DRM_DEBUG_KMS("hw_i2c error\n"); + return EIO; + } + + if (!(flags & HW_I2C_WRITE)) + memcpy(buf, base, num); + + return 0; +} + +static int +radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct iic_msg *p; + int i, remaining, current_count, buffer_offset, max_bytes, ret; + u8 buf = 0, flags; + + /* check for bus probe */ + p = &msgs[0]; + if ((num == 1) && (p->len == 0)) { + ret = radeon_process_i2c_ch(i2c, + p->slave, HW_I2C_WRITE, + &buf, 1); + if (ret) + return ret; + else + return (0); + } + + for (i = 0; i < num; i++) { + p = &msgs[i]; + remaining = p->len; + buffer_offset = 0; + /* max_bytes are a limitation of ProcessI2cChannelTransaction not the hw */ + if (p->flags & IIC_M_RD) { + max_bytes = ATOM_MAX_HW_I2C_READ; + flags = HW_I2C_READ; + } else { + max_bytes = ATOM_MAX_HW_I2C_WRITE; + flags = HW_I2C_WRITE; + } + while (remaining) { + if (remaining > max_bytes) + current_count = max_bytes; + else + current_count = remaining; + ret = radeon_process_i2c_ch(i2c, + p->slave, flags, + &p->buf[buffer_offset], current_count); + if (ret) + return ret; + remaining -= current_count; + buffer_offset += current_count; + } + } + + return (0); +} + +static int +radeon_atom_hw_i2c_probe(device_t dev) +{ + + return (BUS_PROBE_SPECIFIC); +} + +static int +radeon_atom_hw_i2c_attach(device_t dev) +{ + struct radeon_i2c_chan *i2c; + device_t iic_dev; + + i2c = device_get_softc(dev); + device_set_desc(dev, i2c->name); + + /* add generic bit-banging code */ + iic_dev = device_add_child(dev, "iicbus", -1); + if (iic_dev == NULL) + return (ENXIO); + device_quiet(iic_dev); + + /* attach and probe added child */ + bus_generic_attach(dev); + + return (0); +} + +static int +radeon_atom_hw_i2c_detach(device_t dev) +{ + /* detach bit-banding code. */ + bus_generic_detach(dev); + + /* delete bit-banding code. */ + device_delete_children(dev); + return (0); +} + +static int +radeon_atom_hw_i2c_reset(device_t dev, u_char speed, + u_char addr, u_char *oldaddr) +{ + + return (0); +} + +static device_method_t radeon_atom_hw_i2c_methods[] = { + DEVMETHOD(device_probe, radeon_atom_hw_i2c_probe), + DEVMETHOD(device_attach, radeon_atom_hw_i2c_attach), + DEVMETHOD(device_detach, radeon_atom_hw_i2c_detach), + DEVMETHOD(iicbus_reset, radeon_atom_hw_i2c_reset), + DEVMETHOD(iicbus_transfer, radeon_atom_hw_i2c_xfer), + DEVMETHOD_END +}; + +static driver_t radeon_atom_hw_i2c_driver = { + "radeon_atom_hw_i2c", + radeon_atom_hw_i2c_methods, + 0 +}; + +static devclass_t radeon_atom_hw_i2c_devclass; +DRIVER_MODULE_ORDERED(radeon_atom_hw_i2c, drmn, radeon_atom_hw_i2c_driver, + radeon_atom_hw_i2c_devclass, 0, 0, SI_ORDER_ANY); diff --git a/sys/dev/drm2/radeon/avivod.h b/sys/dev/drm2/radeon/avivod.h new file mode 100644 index 00000000000..4f792ebc0fb --- /dev/null +++ b/sys/dev/drm2/radeon/avivod.h @@ -0,0 +1,65 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef AVIVOD_H +#define AVIVOD_H + +#include +__FBSDID("$FreeBSD$"); + + +#define D1CRTC_CONTROL 0x6080 +#define CRTC_EN (1 << 0) +#define D1CRTC_STATUS 0x609c +#define D1CRTC_UPDATE_LOCK 0x60E8 +#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 +#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 + +#define D2CRTC_CONTROL 0x6880 +#define D2CRTC_STATUS 0x689c +#define D2CRTC_UPDATE_LOCK 0x68E8 +#define D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910 +#define D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918 + +#define D1VGA_CONTROL 0x0330 +#define DVGA_CONTROL_MODE_ENABLE (1 << 0) +#define DVGA_CONTROL_TIMING_SELECT (1 << 8) +#define DVGA_CONTROL_SYNC_POLARITY_SELECT (1 << 9) +#define DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1 << 10) +#define DVGA_CONTROL_OVERSCAN_COLOR_EN (1 << 16) +#define DVGA_CONTROL_ROTATE (1 << 24) +#define D2VGA_CONTROL 0x0338 + +#define VGA_HDP_CONTROL 0x328 +#define VGA_MEM_PAGE_SELECT_EN (1 << 0) +#define VGA_MEMORY_DISABLE (1 << 4) +#define VGA_RBBM_LOCK_DISABLE (1 << 8) +#define VGA_SOFT_RESET (1 << 16) +#define VGA_MEMORY_BASE_ADDRESS 0x0310 +#define VGA_RENDER_CONTROL 0x0300 +#define VGA_VSTATUS_CNTL_MASK 0x00030000 + +#endif diff --git a/sys/dev/drm2/radeon/cayman_blit_shaders.c b/sys/dev/drm2/radeon/cayman_blit_shaders.c new file mode 100644 index 00000000000..779f305b6a1 --- /dev/null +++ b/sys/dev/drm2/radeon/cayman_blit_shaders.c @@ -0,0 +1,375 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +/* + * evergreen cards need to use the 3D engine to blit data which requires + * quite a bit of hw state setup. Rather than pull the whole 3D driver + * (which normally generates the 3D state) into the DRM, we opt to use + * statically generated state tables. The regsiter state and shaders + * were hand generated to support blitting functionality. See the 3D + * driver or documentation for descriptions of the registers and + * shader instructions. + */ + +const u32 cayman_default_state[] = +{ + 0xc0066900, + 0x00000000, + 0x00000060, /* DB_RENDER_CONTROL */ + 0x00000000, /* DB_COUNT_CONTROL */ + 0x00000000, /* DB_DEPTH_VIEW */ + 0x0000002a, /* DB_RENDER_OVERRIDE */ + 0x00000000, /* DB_RENDER_OVERRIDE2 */ + 0x00000000, /* DB_HTILE_DATA_BASE */ + + 0xc0026900, + 0x0000000a, + 0x00000000, /* DB_STENCIL_CLEAR */ + 0x00000000, /* DB_DEPTH_CLEAR */ + + 0xc0036900, + 0x0000000f, + 0x00000000, /* DB_DEPTH_INFO */ + 0x00000000, /* DB_Z_INFO */ + 0x00000000, /* DB_STENCIL_INFO */ + + 0xc0016900, + 0x00000080, + 0x00000000, /* PA_SC_WINDOW_OFFSET */ + + 0xc00d6900, + 0x00000083, + 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ + 0x00000000, /* PA_SC_CLIPRECT_0_TL */ + 0x20002000, /* PA_SC_CLIPRECT_0_BR */ + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0xaaaaaaaa, /* PA_SC_EDGERULE */ + 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ + 0x0000000f, /* CB_TARGET_MASK */ + 0x0000000f, /* CB_SHADER_MASK */ + + 0xc0226900, + 0x00000094, + 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ + 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ + 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ + + 0xc0016900, + 0x000000d4, + 0x00000000, /* SX_MISC */ + + 0xc0026900, + 0x000000d9, + 0x00000000, /* CP_RINGID */ + 0x00000000, /* CP_VMID */ + + 0xc0096900, + 0x00000100, + 0x00ffffff, /* VGT_MAX_VTX_INDX */ + 0x00000000, /* VGT_MIN_VTX_INDX */ + 0x00000000, /* VGT_INDX_OFFSET */ + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ + 0x00000000, /* SX_ALPHA_TEST_CONTROL */ + 0x00000000, /* CB_BLEND_RED */ + 0x00000000, /* CB_BLEND_GREEN */ + 0x00000000, /* CB_BLEND_BLUE */ + 0x00000000, /* CB_BLEND_ALPHA */ + + 0xc0016900, + 0x00000187, + 0x00000100, /* SPI_VS_OUT_ID_0 */ + + 0xc0026900, + 0x00000191, + 0x00000100, /* SPI_PS_INPUT_CNTL_0 */ + 0x00000101, /* SPI_PS_INPUT_CNTL_1 */ + + 0xc0016900, + 0x000001b1, + 0x00000000, /* SPI_VS_OUT_CONFIG */ + + 0xc0106900, + 0x000001b3, + 0x20000001, /* SPI_PS_IN_CONTROL_0 */ + 0x00000000, /* SPI_PS_IN_CONTROL_1 */ + 0x00000000, /* SPI_INTERP_CONTROL_0 */ + 0x00000000, /* SPI_INPUT_Z */ + 0x00000000, /* SPI_FOG_CNTL */ + 0x00100000, /* SPI_BARYC_CNTL */ + 0x00000000, /* SPI_PS_IN_CONTROL_2 */ + 0x00000000, /* SPI_COMPUTE_INPUT_CNTL */ + 0x00000000, /* SPI_COMPUTE_NUM_THREAD_X */ + 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Y */ + 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Z */ + 0x00000000, /* SPI_GPR_MGMT */ + 0x00000000, /* SPI_LDS_MGMT */ + 0x00000000, /* SPI_STACK_MGMT */ + 0x00000000, /* SPI_WAVE_MGMT_1 */ + 0x00000000, /* SPI_WAVE_MGMT_2 */ + + 0xc0016900, + 0x000001e0, + 0x00000000, /* CB_BLEND0_CONTROL */ + + 0xc00e6900, + 0x00000200, + 0x00000000, /* DB_DEPTH_CONTROL */ + 0x00000000, /* DB_EQAA */ + 0x00cc0010, /* CB_COLOR_CONTROL */ + 0x00000210, /* DB_SHADER_CONTROL */ + 0x00010000, /* PA_CL_CLIP_CNTL */ + 0x00000004, /* PA_SU_SC_MODE_CNTL */ + 0x00000100, /* PA_CL_VTE_CNTL */ + 0x00000000, /* PA_CL_VS_OUT_CNTL */ + 0x00000000, /* PA_CL_NANINF_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ + 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ + 0x00000000, /* */ + 0x00000000, /* */ + + 0xc0026900, + 0x00000229, + 0x00000000, /* SQ_PGM_START_FS */ + 0x00000000, + + 0xc0016900, + 0x0000023b, + 0x00000000, /* SQ_LDS_ALLOC_PS */ + + 0xc0066900, + 0x00000240, + 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0046900, + 0x00000247, + 0x00000000, /* SQ_GS_VERT_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0116900, + 0x00000280, + 0x00000000, /* PA_SU_POINT_SIZE */ + 0x00000000, /* PA_SU_POINT_MINMAX */ + 0x00000008, /* PA_SU_LINE_CNTL */ + 0x00000000, /* PA_SC_LINE_STIPPLE */ + 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ + 0x00000000, /* VGT_HOS_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, /* VGT_GS_MODE */ + + 0xc0026900, + 0x00000292, + 0x00000000, /* PA_SC_MODE_CNTL_0 */ + 0x00000000, /* PA_SC_MODE_CNTL_1 */ + + 0xc0016900, + 0x000002a1, + 0x00000000, /* VGT_PRIMITIVEID_EN */ + + 0xc0016900, + 0x000002a5, + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ + + 0xc0026900, + 0x000002a8, + 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ + 0x00000000, + + 0xc0026900, + 0x000002ad, + 0x00000000, /* VGT_REUSE_OFF */ + 0x00000000, + + 0xc0016900, + 0x000002d5, + 0x00000000, /* VGT_SHADER_STAGES_EN */ + + 0xc0016900, + 0x000002dc, + 0x0000aa00, /* DB_ALPHA_TO_MASK */ + + 0xc0066900, + 0x000002de, + 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0026900, + 0x000002e5, + 0x00000000, /* VGT_STRMOUT_CONFIG */ + 0x00000000, + + 0xc01b6900, + 0x000002f5, + 0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */ + 0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */ + 0x00000000, /* PA_SC_LINE_CNTL */ + 0x00000000, /* PA_SC_AA_CONFIG */ + 0x00000005, /* PA_SU_VTX_CNTL */ + 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ + 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */ + 0xffffffff, + + 0xc0026900, + 0x00000316, + 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + 0x00000010, /* */ +}; + +const u32 cayman_vs[] = +{ + 0x00000004, + 0x80400400, + 0x0000a03c, + 0x95000688, + 0x00004000, + 0x15000688, + 0x00000000, + 0x88000000, + 0x04000000, + 0x67961001, +#ifdef __BIG_ENDIAN + 0x00020000, +#else + 0x00000000, +#endif + 0x00000000, + 0x04000000, + 0x67961000, +#ifdef __BIG_ENDIAN + 0x00020008, +#else + 0x00000008, +#endif + 0x00000000, +}; + +const u32 cayman_ps[] = +{ + 0x00000004, + 0xa00c0000, + 0x00000008, + 0x80400000, + 0x00000000, + 0x95000688, + 0x00000000, + 0x88000000, + 0x00380400, + 0x00146b10, + 0x00380000, + 0x20146b10, + 0x00380400, + 0x40146b00, + 0x80380000, + 0x60146b00, + 0x00000010, + 0x000d1000, + 0xb0800000, + 0x00000000, +}; + +const u32 cayman_ps_size = DRM_ARRAY_SIZE(cayman_ps); +const u32 cayman_vs_size = DRM_ARRAY_SIZE(cayman_vs); +const u32 cayman_default_size = DRM_ARRAY_SIZE(cayman_default_state); diff --git a/sys/dev/drm2/radeon/cayman_blit_shaders.h b/sys/dev/drm2/radeon/cayman_blit_shaders.h new file mode 100644 index 00000000000..621019b5c43 --- /dev/null +++ b/sys/dev/drm2/radeon/cayman_blit_shaders.h @@ -0,0 +1,38 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef CAYMAN_BLIT_SHADERS_H +#define CAYMAN_BLIT_SHADERS_H + +#include +__FBSDID("$FreeBSD$"); + +extern const u32 cayman_ps[]; +extern const u32 cayman_vs[]; +extern const u32 cayman_default_state[]; + +extern const u32 cayman_ps_size, cayman_vs_size; +extern const u32 cayman_default_size; + +#endif diff --git a/sys/dev/drm2/radeon/cayman_reg_safe.h b/sys/dev/drm2/radeon/cayman_reg_safe.h new file mode 100644 index 00000000000..2802df6eb4a --- /dev/null +++ b/sys/dev/drm2/radeon/cayman_reg_safe.h @@ -0,0 +1,517 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned cayman_reg_safe_bm[2047] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFEF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xCFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFDDEFFF, 0xCF3FFFFF, 0xFFFFE00F, + 0xFEFFFFDF, 0xFFFFFFFF, 0xFFFFFFEF, 0xEFFFFFFF, + 0xFFFFFFCC, 0xFFFFFFFF, 0xFFFFFFFF, 0xBFFFFFD7, + 0xFFFBF8FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF7FFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFB, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFDF0FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xC0000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFC3E4, 0xFFFFFFFF, 0x0000FFFF, 0x00000000, + 0x000CC000, 0x00000000, 0xFF500000, 0x00000000, + 0x00000E00, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFFCF8, 0xFE07FF00, + 0x3CF1F003, 0xE39E7BCF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xE7020000, 0xDDD898DD, 0x279FA3FD, 0x011FFFF0, + 0xBFFF0000, 0xEFC3DF87, 0x7BF0F7E1, 0x1EFC3DF8, + 0xDFBF0F7E, 0xFFFFF7EF, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xCFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, +}; diff --git a/sys/dev/drm2/radeon/evergreen.c b/sys/dev/drm2/radeon/evergreen.c new file mode 100644 index 00000000000..3c98d53a9bd --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen.c @@ -0,0 +1,3759 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include +#include "evergreend.h" +#include "atom.h" +#include "avivod.h" +#include "evergreen_reg.h" +#include "evergreen_blit_shaders.h" + +#define EVERGREEN_PFP_UCODE_SIZE 1120 +#define EVERGREEN_PM4_UCODE_SIZE 1376 + +static const u32 crtc_offsets[6] = +{ + EVERGREEN_CRTC0_REGISTER_OFFSET, + EVERGREEN_CRTC1_REGISTER_OFFSET, + EVERGREEN_CRTC2_REGISTER_OFFSET, + EVERGREEN_CRTC3_REGISTER_OFFSET, + EVERGREEN_CRTC4_REGISTER_OFFSET, + EVERGREEN_CRTC5_REGISTER_OFFSET +}; + +static void evergreen_gpu_init(struct radeon_device *rdev); +void evergreen_pcie_gen2_enable(struct radeon_device *rdev); + +void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, + unsigned *bankh, unsigned *mtaspect, + unsigned *tile_split) +{ + *bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; + *bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; + *mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; + *tile_split = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK; + switch (*bankw) { + default: + case 1: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_1; break; + case 2: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_2; break; + case 4: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_4; break; + case 8: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_8; break; + } + switch (*bankh) { + default: + case 1: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_1; break; + case 2: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_2; break; + case 4: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_4; break; + case 8: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_8; break; + } + switch (*mtaspect) { + default: + case 1: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1; break; + case 2: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2; break; + case 4: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4; break; + case 8: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8; break; + } +} + +void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) +{ + u16 ctl, v; + int err, cap; + + err = pci_find_cap(rdev->dev, PCIY_EXPRESS, &cap); + if (err) + return; + + cap += PCIER_DEVICE_CTL; + + ctl = pci_read_config(rdev->dev, cap, 2); + + v = (ctl & PCIEM_CTL_MAX_READ_REQUEST) >> 12; + + /* if bios or OS sets MAX_READ_REQUEST_SIZE to an invalid value, fix it + * to avoid hangs or perfomance issues + */ + if ((v == 0) || (v == 6) || (v == 7)) { + ctl &= ~PCIEM_CTL_MAX_READ_REQUEST; + ctl |= (2 << 12); + pci_write_config(rdev->dev, cap, ctl, 2); + } +} + +/** + * dce4_wait_for_vblank - vblank wait asic callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to wait for vblank on + * + * Wait for vblank on the requested crtc (evergreen+). + */ +void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + int i; + + if (crtc >= rdev->num_crtc) + return; + + if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) + break; + DRM_UDELAY(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) + break; + DRM_UDELAY(1); + } + } +} + +/** + * radeon_irq_kms_pflip_irq_get - pre-pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to prepare for pageflip on + * + * Pre-pageflip callback (evergreen+). + * Enables the pageflip irq (vblank irq). + */ +void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) +{ + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); +} + +/** + * evergreen_post_page_flip - pos-pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to cleanup pageflip on + * + * Post-pageflip callback (evergreen+). + * Disables the pageflip irq (vblank irq). + */ +void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) +{ + /* disable the pflip int */ + radeon_irq_kms_pflip_irq_put(rdev, crtc); +} + +/** + * evergreen_page_flip - pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to cleanup pageflip on + * @crtc_base: new address of the crtc (GPU MC address) + * + * Does the actual pageflip (evergreen+). + * During vblank we take the crtc lock and wait for the update_pending + * bit to go high, when it does, we release the lock, and allow the + * double buffered update to take place. + * Returns the current update pending status. + */ +u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; + + /* Lock the graphics update lock */ + tmp |= EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* update the scanout addresses */ + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(crtc_base)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(crtc_base)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + /* Wait for update_pending to go high. */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) + break; + DRM_UDELAY(1); + } + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING; +} + +/* get temperature in millidegrees */ +int evergreen_get_temp(struct radeon_device *rdev) +{ + u32 temp, toffset; + int actual_temp = 0; + + if (rdev->family == CHIP_JUNIPER) { + toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> + TOFFSET_SHIFT; + temp = (RREG32(CG_TS0_STATUS) & TS0_ADC_DOUT_MASK) >> + TS0_ADC_DOUT_SHIFT; + + if (toffset & 0x100) + actual_temp = temp / 2 - (0x200 - toffset); + else + actual_temp = temp / 2 + toffset; + + actual_temp = actual_temp * 1000; + + } else { + temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> + ASIC_T_SHIFT; + + if (temp & 0x400) + actual_temp = -256; + else if (temp & 0x200) + actual_temp = 255; + else if (temp & 0x100) { + actual_temp = temp & 0x1ff; + actual_temp |= ~0x1ff; + } else + actual_temp = temp & 0xff; + + actual_temp = (actual_temp * 1000) / 2; + } + + return actual_temp; +} + +int sumo_get_temp(struct radeon_device *rdev) +{ + u32 temp = RREG32(CG_THERMAL_STATUS) & 0xff; + int actual_temp = temp - 49; + + return actual_temp * 1000; +} + +/** + * sumo_pm_init_profile - Initialize power profiles callback. + * + * @rdev: radeon_device pointer + * + * Initialize the power states used in profile mode + * (sumo, trinity, SI). + * Used for profile mode only. + */ +void sumo_pm_init_profile(struct radeon_device *rdev) +{ + int idx; + + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + + /* low,mid sh/mh */ + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + + /* high sh/mh */ + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = + rdev->pm.power_state[idx].num_clock_modes - 1; + + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = + rdev->pm.power_state[idx].num_clock_modes - 1; +} + +/** + * btc_pm_init_profile - Initialize power profiles callback. + * + * @rdev: radeon_device pointer + * + * Initialize the power states used in profile mode + * (BTC, cayman). + * Used for profile mode only. + */ +void btc_pm_init_profile(struct radeon_device *rdev) +{ + int idx; + + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; + /* starting with BTC, there is one state that is used for both + * MH and SH. Difference is that we always use the high clock index for + * mclk. + */ + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; +} + +/** + * evergreen_pm_misc - set additional pm hw parameters callback. + * + * @rdev: radeon_device pointer + * + * Set non-clock parameters associated with a power state + * (voltage, etc.) (evergreen+). + */ +void evergreen_pm_misc(struct radeon_device *rdev) +{ + int req_ps_idx = rdev->pm.requested_power_state_index; + int req_cm_idx = rdev->pm.requested_clock_mode_index; + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if (voltage->type == VOLTAGE_SW) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; + if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { + radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); + } + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->vddci == 0xff01) + return; + if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { + radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); + rdev->pm.current_vddci = voltage->vddci; + DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci); + } + } +} + +/** + * evergreen_pm_prepare - pre-power state change callback. + * + * @rdev: radeon_device pointer + * + * Prepare for a power state change (evergreen+). + */ +void evergreen_pm_prepare(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 tmp; + + /* disable any active CRTCs */ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset); + tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp); + } + } +} + +/** + * evergreen_pm_finish - post-power state change callback. + * + * @rdev: radeon_device pointer + * + * Clean up after a power state change (evergreen+). + */ +void evergreen_pm_finish(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 tmp; + + /* enable any active CRTCs */ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp); + } + } +} + +/** + * evergreen_hpd_sense - hpd sense callback. + * + * @rdev: radeon_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Checks if a digital monitor is connected (evergreen+). + * Returns true if connected, false if not connected. + */ +bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + bool connected = false; + + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_3: + if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_4: + if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_5: + if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_6: + if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + default: + break; + } + + return connected; +} + +/** + * evergreen_hpd_set_polarity - hpd set polarity callback. + * + * @rdev: radeon_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Set the polarity of the hpd pin (evergreen+). + */ +void evergreen_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = evergreen_hpd_sense(rdev, hpd); + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(DC_HPD1_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(DC_HPD2_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + break; + case RADEON_HPD_3: + tmp = RREG32(DC_HPD3_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + break; + case RADEON_HPD_4: + tmp = RREG32(DC_HPD4_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + break; + case RADEON_HPD_5: + tmp = RREG32(DC_HPD5_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + break; + case RADEON_HPD_6: + tmp = RREG32(DC_HPD6_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + break; + default: + break; + } +} + +/** + * evergreen_hpd_init - hpd setup callback. + * + * @rdev: radeon_device pointer + * + * Setup the hpd pins used by the card (evergreen+). + * Enable the pin, set the polarity, and enable the hpd interrupts. + */ +void evergreen_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned enabled = 0; + u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | + DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HPD1_CONTROL, tmp); + break; + case RADEON_HPD_2: + WREG32(DC_HPD2_CONTROL, tmp); + break; + case RADEON_HPD_3: + WREG32(DC_HPD3_CONTROL, tmp); + break; + case RADEON_HPD_4: + WREG32(DC_HPD4_CONTROL, tmp); + break; + case RADEON_HPD_5: + WREG32(DC_HPD5_CONTROL, tmp); + break; + case RADEON_HPD_6: + WREG32(DC_HPD6_CONTROL, tmp); + break; + default: + break; + } + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + enabled |= 1 << radeon_connector->hpd.hpd; + } + radeon_irq_kms_enable_hpd(rdev, enabled); +} + +/** + * evergreen_hpd_fini - hpd tear down callback. + * + * @rdev: radeon_device pointer + * + * Tear down the hpd pins used by the card (evergreen+). + * Disable the hpd interrupts. + */ +void evergreen_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned disabled = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HPD1_CONTROL, 0); + break; + case RADEON_HPD_2: + WREG32(DC_HPD2_CONTROL, 0); + break; + case RADEON_HPD_3: + WREG32(DC_HPD3_CONTROL, 0); + break; + case RADEON_HPD_4: + WREG32(DC_HPD4_CONTROL, 0); + break; + case RADEON_HPD_5: + WREG32(DC_HPD5_CONTROL, 0); + break; + case RADEON_HPD_6: + WREG32(DC_HPD6_CONTROL, 0); + break; + default: + break; + } + disabled |= 1 << radeon_connector->hpd.hpd; + } + radeon_irq_kms_disable_hpd(rdev, disabled); +} + +/* watermark setup */ + +static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, + struct radeon_crtc *radeon_crtc, + struct drm_display_mode *mode, + struct drm_display_mode *other_mode) +{ + u32 tmp; + /* + * Line Buffer Setup + * There are 3 line buffers, each one shared by 2 display controllers. + * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between + * the display controllers. The paritioning is done via one of four + * preset allocations specified in bits 2:0: + * first display controller + * 0 - first half of lb (3840 * 2) + * 1 - first 3/4 of lb (5760 * 2) + * 2 - whole lb (7680 * 2), other crtc must be disabled + * 3 - first 1/4 of lb (1920 * 2) + * second display controller + * 4 - second half of lb (3840 * 2) + * 5 - second 3/4 of lb (5760 * 2) + * 6 - whole lb (7680 * 2), other crtc must be disabled + * 7 - last 1/4 of lb (1920 * 2) + */ + /* this can get tricky if we have two large displays on a paired group + * of crtcs. Ideally for multiple large displays we'd assign them to + * non-linked crtcs for maximum line buffer allocation. + */ + if (radeon_crtc->base.enabled && mode) { + if (other_mode) + tmp = 0; /* 1/2 */ + else + tmp = 2; /* whole */ + } else + tmp = 0; + + /* second controller of the pair uses second half of the lb */ + if (radeon_crtc->crtc_id % 2) + tmp += 4; + WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp); + + if (radeon_crtc->base.enabled && mode) { + switch (tmp) { + case 0: + case 4: + default: + if (ASIC_IS_DCE5(rdev)) + return 4096 * 2; + else + return 3840 * 2; + case 1: + case 5: + if (ASIC_IS_DCE5(rdev)) + return 6144 * 2; + else + return 5760 * 2; + case 2: + case 6: + if (ASIC_IS_DCE5(rdev)) + return 8192 * 2; + else + return 7680 * 2; + case 3: + case 7: + if (ASIC_IS_DCE5(rdev)) + return 2048 * 2; + else + return 1920 * 2; + } + } + + /* controller not enabled, so no lb used */ + return 0; +} + +u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) +{ + u32 tmp = RREG32(MC_SHARED_CHMAP); + + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + return 1; + case 1: + return 2; + case 2: + return 4; + case 3: + return 8; + } +} + +struct evergreen_wm_params { + u32 dram_channels; /* number of dram channels */ + u32 yclk; /* bandwidth per dram data pin in kHz */ + u32 sclk; /* engine clock in kHz */ + u32 disp_clk; /* display clock in kHz */ + u32 src_width; /* viewport width */ + u32 active_time; /* active display time in ns */ + u32 blank_time; /* blank time in ns */ + bool interlaced; /* mode is interlaced */ + fixed20_12 vsc; /* vertical scale ratio */ + u32 num_heads; /* number of active crtcs */ + u32 bytes_per_pixel; /* bytes per pixel display + overlay */ + u32 lb_size; /* line buffer allocated to pipe */ + u32 vtaps; /* vertical scaler taps */ +}; + +static u32 evergreen_dram_bandwidth(struct evergreen_wm_params *wm) +{ + /* Calculate DRAM Bandwidth and the part allocated to display. */ + fixed20_12 dram_efficiency; /* 0.7 */ + fixed20_12 yclk, dram_channels, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + yclk.full = dfixed_const(wm->yclk); + yclk.full = dfixed_div(yclk, a); + dram_channels.full = dfixed_const(wm->dram_channels * 4); + a.full = dfixed_const(10); + dram_efficiency.full = dfixed_const(7); + dram_efficiency.full = dfixed_div(dram_efficiency, a); + bandwidth.full = dfixed_mul(dram_channels, yclk); + bandwidth.full = dfixed_mul(bandwidth, dram_efficiency); + + return dfixed_trunc(bandwidth); +} + +static u32 evergreen_dram_bandwidth_for_display(struct evergreen_wm_params *wm) +{ + /* Calculate DRAM Bandwidth and the part allocated to display. */ + fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */ + fixed20_12 yclk, dram_channels, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + yclk.full = dfixed_const(wm->yclk); + yclk.full = dfixed_div(yclk, a); + dram_channels.full = dfixed_const(wm->dram_channels * 4); + a.full = dfixed_const(10); + disp_dram_allocation.full = dfixed_const(3); /* XXX worse case value 0.3 */ + disp_dram_allocation.full = dfixed_div(disp_dram_allocation, a); + bandwidth.full = dfixed_mul(dram_channels, yclk); + bandwidth.full = dfixed_mul(bandwidth, disp_dram_allocation); + + return dfixed_trunc(bandwidth); +} + +static u32 evergreen_data_return_bandwidth(struct evergreen_wm_params *wm) +{ + /* Calculate the display Data return Bandwidth */ + fixed20_12 return_efficiency; /* 0.8 */ + fixed20_12 sclk, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + sclk.full = dfixed_const(wm->sclk); + sclk.full = dfixed_div(sclk, a); + a.full = dfixed_const(10); + return_efficiency.full = dfixed_const(8); + return_efficiency.full = dfixed_div(return_efficiency, a); + a.full = dfixed_const(32); + bandwidth.full = dfixed_mul(a, sclk); + bandwidth.full = dfixed_mul(bandwidth, return_efficiency); + + return dfixed_trunc(bandwidth); +} + +static u32 evergreen_dmif_request_bandwidth(struct evergreen_wm_params *wm) +{ + /* Calculate the DMIF Request Bandwidth */ + fixed20_12 disp_clk_request_efficiency; /* 0.8 */ + fixed20_12 disp_clk, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + disp_clk.full = dfixed_const(wm->disp_clk); + disp_clk.full = dfixed_div(disp_clk, a); + a.full = dfixed_const(10); + disp_clk_request_efficiency.full = dfixed_const(8); + disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a); + a.full = dfixed_const(32); + bandwidth.full = dfixed_mul(a, disp_clk); + bandwidth.full = dfixed_mul(bandwidth, disp_clk_request_efficiency); + + return dfixed_trunc(bandwidth); +} + +static u32 evergreen_available_bandwidth(struct evergreen_wm_params *wm) +{ + /* Calculate the Available bandwidth. Display can use this temporarily but not in average. */ + u32 dram_bandwidth = evergreen_dram_bandwidth(wm); + u32 data_return_bandwidth = evergreen_data_return_bandwidth(wm); + u32 dmif_req_bandwidth = evergreen_dmif_request_bandwidth(wm); + + return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth)); +} + +static u32 evergreen_average_bandwidth(struct evergreen_wm_params *wm) +{ + /* Calculate the display mode Average Bandwidth + * DisplayMode should contain the source and destination dimensions, + * timing, etc. + */ + fixed20_12 bpp; + fixed20_12 line_time; + fixed20_12 src_width; + fixed20_12 bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + line_time.full = dfixed_const(wm->active_time + wm->blank_time); + line_time.full = dfixed_div(line_time, a); + bpp.full = dfixed_const(wm->bytes_per_pixel); + src_width.full = dfixed_const(wm->src_width); + bandwidth.full = dfixed_mul(src_width, bpp); + bandwidth.full = dfixed_mul(bandwidth, wm->vsc); + bandwidth.full = dfixed_div(bandwidth, line_time); + + return dfixed_trunc(bandwidth); +} + +static u32 evergreen_latency_watermark(struct evergreen_wm_params *wm) +{ + /* First calcualte the latency in ns */ + u32 mc_latency = 2000; /* 2000 ns. */ + u32 available_bandwidth = evergreen_available_bandwidth(wm); + u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth; + u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth; + u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */ + u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) + + (wm->num_heads * cursor_line_pair_return_time); + u32 latency = mc_latency + other_heads_data_return_time + dc_latency; + u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time; + fixed20_12 a, b, c; + + if (wm->num_heads == 0) + return 0; + + a.full = dfixed_const(2); + b.full = dfixed_const(1); + if ((wm->vsc.full > a.full) || + ((wm->vsc.full > b.full) && (wm->vtaps >= 3)) || + (wm->vtaps >= 5) || + ((wm->vsc.full >= a.full) && wm->interlaced)) + max_src_lines_per_dst_line = 4; + else + max_src_lines_per_dst_line = 2; + + a.full = dfixed_const(available_bandwidth); + b.full = dfixed_const(wm->num_heads); + a.full = dfixed_div(a, b); + + b.full = dfixed_const(1000); + c.full = dfixed_const(wm->disp_clk); + b.full = dfixed_div(c, b); + c.full = dfixed_const(wm->bytes_per_pixel); + b.full = dfixed_mul(b, c); + + lb_fill_bw = min(dfixed_trunc(a), dfixed_trunc(b)); + + a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); + b.full = dfixed_const(1000); + c.full = dfixed_const(lb_fill_bw); + b.full = dfixed_div(c, b); + a.full = dfixed_div(a, b); + line_fill_time = dfixed_trunc(a); + + if (line_fill_time < wm->active_time) + return latency; + else + return latency + (line_fill_time - wm->active_time); + +} + +static bool evergreen_average_bandwidth_vs_dram_bandwidth_for_display(struct evergreen_wm_params *wm) +{ + if (evergreen_average_bandwidth(wm) <= + (evergreen_dram_bandwidth_for_display(wm) / wm->num_heads)) + return true; + else + return false; +}; + +static bool evergreen_average_bandwidth_vs_available_bandwidth(struct evergreen_wm_params *wm) +{ + if (evergreen_average_bandwidth(wm) <= + (evergreen_available_bandwidth(wm) / wm->num_heads)) + return true; + else + return false; +}; + +static bool evergreen_check_latency_hiding(struct evergreen_wm_params *wm) +{ + u32 lb_partitions = wm->lb_size / wm->src_width; + u32 line_time = wm->active_time + wm->blank_time; + u32 latency_tolerant_lines; + u32 latency_hiding; + fixed20_12 a; + + a.full = dfixed_const(1); + if (wm->vsc.full > a.full) + latency_tolerant_lines = 1; + else { + if (lb_partitions <= (wm->vtaps + 1)) + latency_tolerant_lines = 1; + else + latency_tolerant_lines = 2; + } + + latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time); + + if (evergreen_latency_watermark(wm) <= latency_hiding) + return true; + else + return false; +} + +static void evergreen_program_watermarks(struct radeon_device *rdev, + struct radeon_crtc *radeon_crtc, + u32 lb_size, u32 num_heads) +{ + struct drm_display_mode *mode = &radeon_crtc->base.mode; + struct evergreen_wm_params wm; + u32 pixel_period; + u32 line_time = 0; + u32 latency_watermark_a = 0, latency_watermark_b = 0; + u32 priority_a_mark = 0, priority_b_mark = 0; + u32 priority_a_cnt = PRIORITY_OFF; + u32 priority_b_cnt = PRIORITY_OFF; + u32 pipe_offset = radeon_crtc->crtc_id * 16; + u32 tmp, arb_control3; + fixed20_12 a, b, c; + + if (radeon_crtc->base.enabled && num_heads && mode) { + pixel_period = 1000000 / (u32)mode->clock; + line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + priority_a_cnt = 0; + priority_b_cnt = 0; + + wm.yclk = rdev->pm.current_mclk * 10; + wm.sclk = rdev->pm.current_sclk * 10; + wm.disp_clk = mode->clock; + wm.src_width = mode->crtc_hdisplay; + wm.active_time = mode->crtc_hdisplay * pixel_period; + wm.blank_time = line_time - wm.active_time; + wm.interlaced = false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + wm.interlaced = true; + wm.vsc = radeon_crtc->vsc; + wm.vtaps = 1; + if (radeon_crtc->rmx_type != RMX_OFF) + wm.vtaps = 2; + wm.bytes_per_pixel = 4; /* XXX: get this from fb config */ + wm.lb_size = lb_size; + wm.dram_channels = evergreen_get_number_of_dram_channels(rdev); + wm.num_heads = num_heads; + + /* set for high clocks */ + latency_watermark_a = min(evergreen_latency_watermark(&wm), (u32)65535); + /* set for low clocks */ + /* wm.yclk = low clk; wm.sclk = low clk */ + latency_watermark_b = min(evergreen_latency_watermark(&wm), (u32)65535); + + /* possibly force display priority to high */ + /* should really do this at mode validation time... */ + if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm) || + !evergreen_average_bandwidth_vs_available_bandwidth(&wm) || + !evergreen_check_latency_hiding(&wm) || + (rdev->disp_priority == 2)) { + DRM_DEBUG_KMS("force priority to high\n"); + priority_a_cnt |= PRIORITY_ALWAYS_ON; + priority_b_cnt |= PRIORITY_ALWAYS_ON; + } + + a.full = dfixed_const(1000); + b.full = dfixed_const(mode->clock); + b.full = dfixed_div(b, a); + c.full = dfixed_const(latency_watermark_a); + c.full = dfixed_mul(c, b); + c.full = dfixed_mul(c, radeon_crtc->hsc); + c.full = dfixed_div(c, a); + a.full = dfixed_const(16); + c.full = dfixed_div(c, a); + priority_a_mark = dfixed_trunc(c); + priority_a_cnt |= priority_a_mark & PRIORITY_MARK_MASK; + + a.full = dfixed_const(1000); + b.full = dfixed_const(mode->clock); + b.full = dfixed_div(b, a); + c.full = dfixed_const(latency_watermark_b); + c.full = dfixed_mul(c, b); + c.full = dfixed_mul(c, radeon_crtc->hsc); + c.full = dfixed_div(c, a); + a.full = dfixed_const(16); + c.full = dfixed_div(c, a); + priority_b_mark = dfixed_trunc(c); + priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; + } + + /* select wm A */ + arb_control3 = RREG32(PIPE0_ARBITRATION_CONTROL3 + pipe_offset); + tmp = arb_control3; + tmp &= ~LATENCY_WATERMARK_MASK(3); + tmp |= LATENCY_WATERMARK_MASK(1); + WREG32(PIPE0_ARBITRATION_CONTROL3 + pipe_offset, tmp); + WREG32(PIPE0_LATENCY_CONTROL + pipe_offset, + (LATENCY_LOW_WATERMARK(latency_watermark_a) | + LATENCY_HIGH_WATERMARK(line_time))); + /* select wm B */ + tmp = RREG32(PIPE0_ARBITRATION_CONTROL3 + pipe_offset); + tmp &= ~LATENCY_WATERMARK_MASK(3); + tmp |= LATENCY_WATERMARK_MASK(2); + WREG32(PIPE0_ARBITRATION_CONTROL3 + pipe_offset, tmp); + WREG32(PIPE0_LATENCY_CONTROL + pipe_offset, + (LATENCY_LOW_WATERMARK(latency_watermark_b) | + LATENCY_HIGH_WATERMARK(line_time))); + /* restore original selection */ + WREG32(PIPE0_ARBITRATION_CONTROL3 + pipe_offset, arb_control3); + + /* write the priority marks */ + WREG32(PRIORITY_A_CNT + radeon_crtc->crtc_offset, priority_a_cnt); + WREG32(PRIORITY_B_CNT + radeon_crtc->crtc_offset, priority_b_cnt); + +} + +/** + * evergreen_bandwidth_update - update display watermarks callback. + * + * @rdev: radeon_device pointer + * + * Update the display watermarks based on the requested mode(s) + * (evergreen+). + */ +void evergreen_bandwidth_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + u32 num_heads = 0, lb_size; + int i; + + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i]->base.enabled) + num_heads++; + } + for (i = 0; i < rdev->num_crtc; i += 2) { + mode0 = &rdev->mode_info.crtcs[i]->base.mode; + mode1 = &rdev->mode_info.crtcs[i+1]->base.mode; + lb_size = evergreen_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1); + evergreen_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); + lb_size = evergreen_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0); + evergreen_program_watermarks(rdev, rdev->mode_info.crtcs[i+1], lb_size, num_heads); + } +} + +/** + * evergreen_mc_wait_for_idle - wait for MC idle callback. + * + * @rdev: radeon_device pointer + * + * Wait for the MC (memory controller) to be idle. + * (evergreen+). + * Returns 0 if the MC is idle, -1 if not. + */ +int evergreen_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + u32 tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(SRBM_STATUS) & 0x1F00; + if (!tmp) + return 0; + DRM_UDELAY(1); + } + return -1; +} + +/* + * GART + */ +void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev) +{ + unsigned i; + u32 tmp; + + WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); + + WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1)); + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(VM_CONTEXT0_REQUEST_RESPONSE); + tmp = (tmp & RESPONSE_TYPE_MASK) >> RESPONSE_TYPE_SHIFT; + if (tmp == 2) { + DRM_ERROR("[drm] r600 flush TLB failed\n"); + return; + } + if (tmp) { + return; + } + DRM_UDELAY(1); + } +} + +static int evergreen_pcie_gart_enable(struct radeon_device *rdev) +{ + u32 tmp; + int r; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); + /* Setup TLB control */ + tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); + if (rdev->flags & RADEON_IS_IGP) { + WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp); + } else { + WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + if ((rdev->family == CHIP_JUNIPER) || + (rdev->family == CHIP_CYPRESS) || + (rdev->family == CHIP_HEMLOCK) || + (rdev->family == CHIP_BARTS)) + WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); + } + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); + WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); + WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT1_CNTL, 0); + + evergreen_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +static void evergreen_pcie_gart_disable(struct radeon_device *rdev) +{ + u32 tmp; + + /* Disable all tables */ + WREG32(VM_CONTEXT0_CNTL, 0); + WREG32(VM_CONTEXT1_CNTL, 0); + + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); + /* Setup TLB control */ + tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); + WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + radeon_gart_table_vram_unpin(rdev); +} + +static void evergreen_pcie_gart_fini(struct radeon_device *rdev) +{ + evergreen_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); +} + + +static void evergreen_agp_enable(struct radeon_device *rdev) +{ + u32 tmp; + + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); + /* Setup TLB control */ + tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); + WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + WREG32(VM_CONTEXT0_CNTL, 0); + WREG32(VM_CONTEXT1_CNTL, 0); +} + +void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) +{ + u32 crtc_enabled, tmp, frame_count, blackout; + int i, j; + + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); + + /* disable VGA render */ + WREG32(VGA_RENDER_CONTROL, 0); + /* blank the display controllers */ + for (i = 0; i < rdev->num_crtc; i++) { + crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + save->crtc_enabled[i] = true; + if (ASIC_IS_DCE6(rdev)) { + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { + radeon_wait_for_vblank(rdev, i); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { + radeon_wait_for_vblank(rdev, i); + tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + DRM_UDELAY(1); + } + } else { + save->crtc_enabled[i] = false; + } + } + + radeon_mc_wait_for_idle(rdev); + + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + if ((blackout & BLACKOUT_MODE_MASK) != 1) { + /* Block CPU access */ + WREG32(BIF_FB_EN, 0); + /* blackout the MC */ + blackout &= ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); + } + /* wait for the MC to settle */ + DRM_UDELAY(100); +} + +void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) +{ + u32 tmp, frame_count; + int i, j; + + /* update crtc base addresses */ + for (i = 0; i < rdev->num_crtc; i++) { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); + } + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); + + /* unblackout the MC */ + tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); + tmp &= ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); + /* allow CPU access */ + WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); + + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled[i]) { + if (ASIC_IS_DCE6(rdev)) { + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + DRM_UDELAY(1); + } + } + } + /* Unlock vga access */ + WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); + DRM_MDELAY(1); + WREG32(VGA_RENDER_CONTROL, save->vga_render_control); +} + +void evergreen_mc_program(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 tmp; + int i, j; + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); + + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Lockout access through VGA aperture*/ + WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); + /* Update configuration */ + if (rdev->flags & RADEON_IS_AGP) { + if (rdev->mc.vram_start < rdev->mc.gtt_start) { + /* VRAM before AGP */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.gtt_end >> 12); + } else { + /* VRAM after AGP */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.gtt_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.vram_end >> 12); + } + } else { + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.vram_end >> 12); + } + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); + /* llano/ontario only */ + if ((rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2)) { + tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; + tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24; + tmp |= ((rdev->mc.vram_start >> 20) & 0xF) << 20; + WREG32(MC_FUS_VM_FB_OFFSET, tmp); + } + tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; + tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); + WREG32(MC_VM_FB_LOCATION, tmp); + WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); + WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); + if (rdev->flags & RADEON_IS_AGP) { + WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16); + WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); + WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); + } else { + WREG32(MC_VM_AGP_BASE, 0); + WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); + WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); + } + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + evergreen_mc_resume(rdev, &save); + /* we need to own VRAM, so turn off the VGA renderer here + * to stop it overwriting our objects */ + rv515_vga_render_disable(rdev); +} + +/* + * CP. + */ +void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + u32 next_rptr; + + /* set to DX10/11 mode */ + radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); + radeon_ring_write(ring, 1); + + if (ring->rptr_save_reg) { + next_rptr = ring->wptr + 3 + 4; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, ((ring->rptr_save_reg - + PACKET3_SET_CONFIG_REG_START) >> 2)); + radeon_ring_write(ring, next_rptr); + } else if (rdev->wb.enabled) { + next_rptr = ring->wptr + 5 + 4; + radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); + radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); + radeon_ring_write(ring, next_rptr); + radeon_ring_write(ring, 0); + } + + radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); + radeon_ring_write(ring, ib->length_dw); +} + + +static int evergreen_cp_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + int i; + + if (!rdev->me_fw || !rdev->pfp_fw) + return -EINVAL; + + r700_cp_stop(rdev); + WREG32(CP_RB_CNTL, +#ifdef __BIG_ENDIAN + BUF_SWAP_32BIT | +#endif + RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3)); + + fw_data = (const __be32 *)rdev->pfp_fw->data; + WREG32(CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < EVERGREEN_PFP_UCODE_SIZE; i++) + WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); + WREG32(CP_PFP_UCODE_ADDR, 0); + + fw_data = (const __be32 *)rdev->me_fw->data; + WREG32(CP_ME_RAM_WADDR, 0); + for (i = 0; i < EVERGREEN_PM4_UCODE_SIZE; i++) + WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); + + WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_RADDR, 0); + return 0; +} + +static int evergreen_cp_start(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r, i; + uint32_t cp_me; + + r = radeon_ring_lock(rdev, ring, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(ring, 0x1); + radeon_ring_write(ring, 0x0); + radeon_ring_write(ring, rdev->config.evergreen.max_hw_contexts - 1); + radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_unlock_commit(rdev, ring); + + cp_me = 0xff; + WREG32(CP_ME_CNTL, cp_me); + + r = radeon_ring_lock(rdev, ring, evergreen_default_size + 19); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + + /* setup clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + for (i = 0; i < evergreen_default_size; i++) + radeon_ring_write(ring, evergreen_default_state[i]); + + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); + + /* set clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); + radeon_ring_write(ring, 0); + + /* SQ_VTX_BASE_VTX_LOC */ + radeon_ring_write(ring, 0xc0026f00); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + + /* Clear consts */ + radeon_ring_write(ring, 0xc0036f00); + radeon_ring_write(ring, 0x00000bc4); + radeon_ring_write(ring, 0xffffffff); + radeon_ring_write(ring, 0xffffffff); + radeon_ring_write(ring, 0xffffffff); + + radeon_ring_write(ring, 0xc0026900); + radeon_ring_write(ring, 0x00000316); + radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + radeon_ring_write(ring, 0x00000010); /* */ + + radeon_ring_unlock_commit(rdev, ring); + + return 0; +} + +static int evergreen_cp_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 tmp; + u32 rb_bufsz; + int r; + + /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ + WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | + SOFT_RESET_PA | + SOFT_RESET_SH | + SOFT_RESET_VGT | + SOFT_RESET_SPI | + SOFT_RESET_SX)); + RREG32(GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(GRBM_SOFT_RESET, 0); + RREG32(GRBM_SOFT_RESET); + + /* Set ring buffer size */ + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB_CNTL, tmp); + WREG32(CP_SEM_WAIT_TIMER, 0x0); + WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); + WREG32(CP_RB_RPTR_WR, 0); + ring->wptr = 0; + WREG32(CP_RB_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(CP_RB_RPTR_ADDR, + ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC)); + WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); + WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); + + if (rdev->wb.enabled) + WREG32(SCRATCH_UMSK, 0xff); + else { + tmp |= RB_NO_UPDATE; + WREG32(SCRATCH_UMSK, 0); + } + + DRM_MDELAY(1); + WREG32(CP_RB_CNTL, tmp); + + WREG32(CP_RB_BASE, ring->gpu_addr >> 8); + WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); + + ring->rptr = RREG32(CP_RB_RPTR); + + evergreen_cp_start(rdev); + ring->ready = true; + r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); + if (r) { + ring->ready = false; + return r; + } + return 0; +} + +/* + * Core functions + */ +static void evergreen_gpu_init(struct radeon_device *rdev) +{ + u32 gb_addr_config; + u32 mc_shared_chmap, mc_arb_ramcfg; + u32 sx_debug_1; + u32 smx_dc_ctl0; + u32 sq_config; + u32 sq_lds_resource_mgmt; + u32 sq_gpr_resource_mgmt_1; + u32 sq_gpr_resource_mgmt_2; + u32 sq_gpr_resource_mgmt_3; + u32 sq_thread_resource_mgmt; + u32 sq_thread_resource_mgmt_2; + u32 sq_stack_resource_mgmt_1; + u32 sq_stack_resource_mgmt_2; + u32 sq_stack_resource_mgmt_3; + u32 vgt_cache_invalidation; + u32 hdp_host_path_cntl, tmp; + u32 disabled_rb_mask; + int i, j, num_shader_engines, ps_thread_count; + + switch (rdev->family) { + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + rdev->config.evergreen.num_ses = 2; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 8; + rdev->config.evergreen.max_simds = 10; + rdev->config.evergreen.max_backends = 4 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 512; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x100; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = CYPRESS_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_JUNIPER: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 4; + rdev->config.evergreen.max_simds = 10; + rdev->config.evergreen.max_backends = 4 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 512; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x100; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = JUNIPER_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_REDWOOD: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 4; + rdev->config.evergreen.max_simds = 5; + rdev->config.evergreen.max_backends = 2 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x100; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_CEDAR: + default: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 2; + rdev->config.evergreen.max_tile_pipes = 2; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 192; + rdev->config.evergreen.max_gs_threads = 16; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 128; + rdev->config.evergreen.sx_max_export_pos_size = 32; + rdev->config.evergreen.sx_max_export_smx_size = 96; + rdev->config.evergreen.max_hw_contexts = 4; + rdev->config.evergreen.sq_num_cf_insts = 1; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_PALM: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 2; + rdev->config.evergreen.max_tile_pipes = 2; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 192; + rdev->config.evergreen.max_gs_threads = 16; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 128; + rdev->config.evergreen.sx_max_export_pos_size = 32; + rdev->config.evergreen.sx_max_export_smx_size = 96; + rdev->config.evergreen.max_hw_contexts = 4; + rdev->config.evergreen.sq_num_cf_insts = 1; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_SUMO: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 4; + if (rdev->ddev->pci_device == 0x9648) + rdev->config.evergreen.max_simds = 3; + else if ((rdev->ddev->pci_device == 0x9647) || + (rdev->ddev->pci_device == 0x964a)) + rdev->config.evergreen.max_simds = 4; + else + rdev->config.evergreen.max_simds = 5; + rdev->config.evergreen.max_backends = 2 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = SUMO_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_SUMO2: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 4; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 512; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = SUMO2_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_BARTS: + rdev->config.evergreen.num_ses = 2; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 8; + rdev->config.evergreen.max_simds = 7; + rdev->config.evergreen.max_backends = 4 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 512; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x100; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = BARTS_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_TURKS: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 4; + rdev->config.evergreen.max_simds = 6; + rdev->config.evergreen.max_backends = 2 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x100; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = TURKS_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_CAICOS: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 2; + rdev->config.evergreen.max_tile_pipes = 2; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 192; + rdev->config.evergreen.max_gs_threads = 16; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 128; + rdev->config.evergreen.sx_max_export_pos_size = 32; + rdev->config.evergreen.sx_max_export_smx_size = 96; + rdev->config.evergreen.max_hw_contexts = 4; + rdev->config.evergreen.sq_num_cf_insts = 1; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = CAICOS_GB_ADDR_CONFIG_GOLDEN; + break; + } + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + + WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); + + evergreen_fix_pci_max_read_req_size(rdev); + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); + if ((rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2)) + mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG); + else + mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + + /* setup tiling info dword. gb_addr_config is not adequate since it does + * not have bank info, so create a custom tiling dword. + * bits 3:0 num_pipes + * bits 7:4 num_banks + * bits 11:8 group_size + * bits 15:12 row_size + */ + rdev->config.evergreen.tile_config = 0; + switch (rdev->config.evergreen.max_tile_pipes) { + case 1: + default: + rdev->config.evergreen.tile_config |= (0 << 0); + break; + case 2: + rdev->config.evergreen.tile_config |= (1 << 0); + break; + case 4: + rdev->config.evergreen.tile_config |= (2 << 0); + break; + case 8: + rdev->config.evergreen.tile_config |= (3 << 0); + break; + } + /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ + if (rdev->flags & RADEON_IS_IGP) + rdev->config.evergreen.tile_config |= 1 << 4; + else { + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ + rdev->config.evergreen.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.evergreen.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.evergreen.tile_config |= 2 << 4; + break; + } + } + rdev->config.evergreen.tile_config |= 0 << 8; + rdev->config.evergreen.tile_config |= + ((gb_addr_config & 0x30000000) >> 28) << 12; + + num_shader_engines = (gb_addr_config & NUM_SHADER_ENGINES(3) >> 12) + 1; + + if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) { + u32 efuse_straps_4; + u32 efuse_straps_3; + + WREG32(RCU_IND_INDEX, 0x204); + efuse_straps_4 = RREG32(RCU_IND_DATA); + WREG32(RCU_IND_INDEX, 0x203); + efuse_straps_3 = RREG32(RCU_IND_DATA); + tmp = (((efuse_straps_4 & 0xf) << 4) | + ((efuse_straps_3 & 0xf0000000) >> 28)); + } else { + tmp = 0; + for (i = (rdev->config.evergreen.num_ses - 1); i >= 0; i--) { + u32 rb_disable_bitmap; + + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; + tmp <<= 4; + tmp |= rb_disable_bitmap; + } + } + /* enabled rb are just the one not disabled :) */ + disabled_rb_mask = tmp; + + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); + WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); + + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); + WREG32(DMA_TILING_CONFIG, gb_addr_config); + + if ((rdev->config.evergreen.max_backends == 1) && + (rdev->flags & RADEON_IS_IGP)) { + if ((disabled_rb_mask & 3) == 1) { + /* RB0 disabled, RB1 enabled */ + tmp = 0x11111111; + } else { + /* RB1 disabled, RB0 enabled */ + tmp = 0x00000000; + } + } else { + tmp = gb_addr_config & NUM_PIPES_MASK; + tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, + EVERGREEN_MAX_BACKENDS, disabled_rb_mask); + } + WREG32(GB_BACKEND_MAP, tmp); + + WREG32(CGTS_SYS_TCC_DISABLE, 0); + WREG32(CGTS_TCC_DISABLE, 0); + WREG32(CGTS_USER_SYS_TCC_DISABLE, 0); + WREG32(CGTS_USER_TCC_DISABLE, 0); + + /* set HW defaults for 3D engine */ + WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | + ROQ_IB2_START(0x2b))); + + WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30)); + + WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO | + SYNC_GRADIENT | + SYNC_WALKER | + SYNC_ALIGNER)); + + sx_debug_1 = RREG32(SX_DEBUG_1); + sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; + WREG32(SX_DEBUG_1, sx_debug_1); + + + smx_dc_ctl0 = RREG32(SMX_DC_CTL0); + smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); + smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); + WREG32(SMX_DC_CTL0, smx_dc_ctl0); + + if (rdev->family <= CHIP_SUMO2) + WREG32(SMX_SAR_CTL0, 0x00010000); + + WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | + POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | + SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); + + WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) | + SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) | + SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size))); + + WREG32(VGT_NUM_INSTANCES, 1); + WREG32(SPI_CONFIG_CNTL, 0); + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); + WREG32(CP_PERFMON_CNTL, 0); + + WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) | + FETCH_FIFO_HIWATER(0x4) | + DONE_FIFO_HIWATER(0xe0) | + ALU_UPDATE_FIFO_HIWATER(0x8))); + + sq_config = RREG32(SQ_CONFIG); + sq_config &= ~(PS_PRIO(3) | + VS_PRIO(3) | + GS_PRIO(3) | + ES_PRIO(3)); + sq_config |= (VC_ENABLE | + EXPORT_SRC_C | + PS_PRIO(0) | + VS_PRIO(1) | + GS_PRIO(2) | + ES_PRIO(3)); + + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: + case CHIP_CAICOS: + /* no vertex cache */ + sq_config &= ~VC_ENABLE; + break; + default: + break; + } + + sq_lds_resource_mgmt = RREG32(SQ_LDS_RESOURCE_MGMT); + + sq_gpr_resource_mgmt_1 = NUM_PS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2))* 12 / 32); + sq_gpr_resource_mgmt_1 |= NUM_VS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 6 / 32); + sq_gpr_resource_mgmt_1 |= NUM_CLAUSE_TEMP_GPRS(4); + sq_gpr_resource_mgmt_2 = NUM_GS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 4 / 32); + sq_gpr_resource_mgmt_2 |= NUM_ES_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 4 / 32); + sq_gpr_resource_mgmt_3 = NUM_HS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32); + sq_gpr_resource_mgmt_3 |= NUM_LS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32); + + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: + ps_thread_count = 96; + break; + default: + ps_thread_count = 128; + break; + } + + sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count); + sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + + sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); + sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); + sq_stack_resource_mgmt_2 = NUM_GS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); + sq_stack_resource_mgmt_2 |= NUM_ES_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); + sq_stack_resource_mgmt_3 = NUM_HS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); + sq_stack_resource_mgmt_3 |= NUM_LS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); + + WREG32(SQ_CONFIG, sq_config); + WREG32(SQ_GPR_RESOURCE_MGMT_1, sq_gpr_resource_mgmt_1); + WREG32(SQ_GPR_RESOURCE_MGMT_2, sq_gpr_resource_mgmt_2); + WREG32(SQ_GPR_RESOURCE_MGMT_3, sq_gpr_resource_mgmt_3); + WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); + WREG32(SQ_THREAD_RESOURCE_MGMT_2, sq_thread_resource_mgmt_2); + WREG32(SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1); + WREG32(SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2); + WREG32(SQ_STACK_RESOURCE_MGMT_3, sq_stack_resource_mgmt_3); + WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, 0); + WREG32(SQ_LDS_RESOURCE_MGMT, sq_lds_resource_mgmt); + + WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | + FORCE_EOV_MAX_REZ_CNT(255))); + + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: + case CHIP_CAICOS: + vgt_cache_invalidation = CACHE_INVALIDATION(TC_ONLY); + break; + default: + vgt_cache_invalidation = CACHE_INVALIDATION(VC_AND_TC); + break; + } + vgt_cache_invalidation |= AUTO_INVLD_EN(ES_AND_GS_AUTO); + WREG32(VGT_CACHE_INVALIDATION, vgt_cache_invalidation); + + WREG32(VGT_GS_VERTEX_REUSE, 16); + WREG32(PA_SU_LINE_STIPPLE_VALUE, 0); + WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + + WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14); + WREG32(VGT_OUT_DEALLOC_CNTL, 16); + + WREG32(CB_PERF_CTR0_SEL_0, 0); + WREG32(CB_PERF_CTR0_SEL_1, 0); + WREG32(CB_PERF_CTR1_SEL_0, 0); + WREG32(CB_PERF_CTR1_SEL_1, 0); + WREG32(CB_PERF_CTR2_SEL_0, 0); + WREG32(CB_PERF_CTR2_SEL_1, 0); + WREG32(CB_PERF_CTR3_SEL_0, 0); + WREG32(CB_PERF_CTR3_SEL_1, 0); + + /* clear render buffer base addresses */ + WREG32(CB_COLOR0_BASE, 0); + WREG32(CB_COLOR1_BASE, 0); + WREG32(CB_COLOR2_BASE, 0); + WREG32(CB_COLOR3_BASE, 0); + WREG32(CB_COLOR4_BASE, 0); + WREG32(CB_COLOR5_BASE, 0); + WREG32(CB_COLOR6_BASE, 0); + WREG32(CB_COLOR7_BASE, 0); + WREG32(CB_COLOR8_BASE, 0); + WREG32(CB_COLOR9_BASE, 0); + WREG32(CB_COLOR10_BASE, 0); + WREG32(CB_COLOR11_BASE, 0); + + /* set the shader const cache sizes to 0 */ + for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4) + WREG32(i, 0); + for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) + WREG32(i, 0); + + tmp = RREG32(HDP_MISC_CNTL); + tmp |= HDP_FLUSH_INVALIDATE_CACHE; + WREG32(HDP_MISC_CNTL, tmp); + + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); + + DRM_UDELAY(50); + +} + +int evergreen_mc_init(struct radeon_device *rdev) +{ + u32 tmp; + int chansize, numchan; + + /* Get VRAM informations */ + rdev->mc.vram_is_ddr = true; + if ((rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2)) + tmp = RREG32(FUS_MC_ARB_RAMCFG); + else + tmp = RREG32(MC_ARB_RAMCFG); + if (tmp & CHANSIZE_OVERRIDE) { + chansize = 16; + } else if (tmp & CHANSIZE_MASK) { + chansize = 64; + } else { + chansize = 32; + } + tmp = RREG32(MC_SHARED_CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + numchan = 1; + break; + case 1: + numchan = 2; + break; + case 2: + numchan = 4; + break; + case 3: + numchan = 8; + break; + } + rdev->mc.vram_width = numchan * chansize; + /* Could aper size report 0 ? */ + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + /* Setup GPU memory space */ + if ((rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2)) { + /* size in bytes on fusion */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); + } else { + /* size in MB on evergreen/cayman/tn */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + } + rdev->mc.visible_vram_size = rdev->mc.aper_size; + r700_vram_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); + + return 0; +} + +bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 srbm_status; + u32 grbm_status; + u32 grbm_status_se0, grbm_status_se1; + + srbm_status = RREG32(SRBM_STATUS); + grbm_status = RREG32(GRBM_STATUS); + grbm_status_se0 = RREG32(GRBM_STATUS_SE0); + grbm_status_se1 = RREG32(GRBM_STATUS_SE1); + if (!(grbm_status & GUI_ACTIVE)) { + radeon_ring_lockup_update(ring); + return false; + } + /* force CP activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +static void evergreen_gpu_soft_reset_gfx(struct radeon_device *rdev) +{ + u32 grbm_reset = 0; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + return; + + dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", + RREG32(CP_STALLED_STAT1)); + dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", + RREG32(CP_STALLED_STAT2)); + dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", + RREG32(CP_BUSY_STAT)); + dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", + RREG32(CP_STAT)); + + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); + + /* reset all the gfx blocks */ + grbm_reset = (SOFT_RESET_CP | + SOFT_RESET_CB | + SOFT_RESET_DB | + SOFT_RESET_PA | + SOFT_RESET_SC | + SOFT_RESET_SPI | + SOFT_RESET_SH | + SOFT_RESET_SX | + SOFT_RESET_TC | + SOFT_RESET_TA | + SOFT_RESET_VC | + SOFT_RESET_VGT); + + dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); + WREG32(GRBM_SOFT_RESET, grbm_reset); + (void)RREG32(GRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(GRBM_SOFT_RESET, 0); + (void)RREG32(GRBM_SOFT_RESET); + + dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", + RREG32(CP_STALLED_STAT1)); + dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", + RREG32(CP_STALLED_STAT2)); + dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", + RREG32(CP_BUSY_STAT)); + dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", + RREG32(CP_STAT)); +} + +static void evergreen_gpu_soft_reset_dma(struct radeon_device *rdev) +{ + u32 tmp; + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + return; + + dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); + + /* Disable DMA */ + tmp = RREG32(DMA_RB_CNTL); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL, tmp); + + /* Reset dma */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA); + RREG32(SRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(SRBM_SOFT_RESET, 0); + + dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); +} + +static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) +{ + struct evergreen_mc_save save; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + + if (reset_mask == 0) + return 0; + + dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); + + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + + if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) + evergreen_gpu_soft_reset_gfx(rdev); + + if (reset_mask & RADEON_RESET_DMA) + evergreen_gpu_soft_reset_dma(rdev); + + /* Wait a little for things to settle down */ + DRM_UDELAY(50); + + evergreen_mc_resume(rdev, &save); + return 0; +} + +int evergreen_asic_reset(struct radeon_device *rdev) +{ + return evergreen_gpu_soft_reset(rdev, (RADEON_RESET_GFX | + RADEON_RESET_COMPUTE | + RADEON_RESET_DMA)); +} + +/* Interrupts */ + +u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc) +{ + if (crtc >= rdev->num_crtc) + return 0; + else + return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); +} + +void evergreen_disable_interrupt_state(struct radeon_device *rdev) +{ + u32 tmp; + + if (rdev->family >= CHIP_CAYMAN) { + cayman_cp_int_cntl_setup(rdev, 0, + CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + cayman_cp_int_cntl_setup(rdev, 1, 0); + cayman_cp_int_cntl_setup(rdev, 2, 0); + tmp = RREG32(CAYMAN_DMA1_CNTL) & ~TRAP_ENABLE; + WREG32(CAYMAN_DMA1_CNTL, tmp); + } else + WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + tmp = RREG32(DMA_CNTL) & ~TRAP_ENABLE; + WREG32(DMA_CNTL, tmp); + WREG32(GRBM_INT_CNTL, 0); + WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + if (rdev->num_crtc >= 4) { + WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } + + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } + + /* only one DAC on DCE6 */ + if (!ASIC_IS_DCE6(rdev)) + WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DACB_AUTODETECT_INT_CONTROL, 0); + + tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + +} + +int evergreen_irq_set(struct radeon_device *rdev) +{ + u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; + u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; + u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; + u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; + u32 dma_cntl, dma_cntl1 = 0; + + if (!rdev->irq.installed) { + dev_warn(rdev->dev, "Can't enable IRQ/MSI because no handler is installed\n"); + return -EINVAL; + } + /* don't enable anything if the ih is disabled */ + if (!rdev->ih.enabled) { + r600_disable_interrupts(rdev); + /* force the active interrupt state to all disabled */ + evergreen_disable_interrupt_state(rdev); + return 0; + } + + hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; + + afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + afmt3 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + afmt4 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + afmt5 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + afmt6 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + + dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE; + + if (rdev->family >= CHIP_CAYMAN) { + /* enable CP interrupts on all rings */ + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); + cp_int_cntl |= TIME_STAMP_INT_ENABLE; + } + if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { + DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); + cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; + } + if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { + DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); + cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; + } + } else { + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); + cp_int_cntl |= RB_INT_ENABLE; + cp_int_cntl |= TIME_STAMP_INT_ENABLE; + } + } + + if (atomic_read(&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX])) { + DRM_DEBUG("r600_irq_set: sw int dma\n"); + dma_cntl |= TRAP_ENABLE; + } + + if (rdev->family >= CHIP_CAYMAN) { + dma_cntl1 = RREG32(CAYMAN_DMA1_CNTL) & ~TRAP_ENABLE; + if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_DMA1_INDEX])) { + DRM_DEBUG("r600_irq_set: sw int dma1\n"); + dma_cntl1 |= TRAP_ENABLE; + } + } + + if (rdev->irq.crtc_vblank_int[0] || + atomic_read(&rdev->irq.pflip[0])) { + DRM_DEBUG("evergreen_irq_set: vblank 0\n"); + crtc1 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[1] || + atomic_read(&rdev->irq.pflip[1])) { + DRM_DEBUG("evergreen_irq_set: vblank 1\n"); + crtc2 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[2] || + atomic_read(&rdev->irq.pflip[2])) { + DRM_DEBUG("evergreen_irq_set: vblank 2\n"); + crtc3 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[3] || + atomic_read(&rdev->irq.pflip[3])) { + DRM_DEBUG("evergreen_irq_set: vblank 3\n"); + crtc4 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[4] || + atomic_read(&rdev->irq.pflip[4])) { + DRM_DEBUG("evergreen_irq_set: vblank 4\n"); + crtc5 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[5] || + atomic_read(&rdev->irq.pflip[5])) { + DRM_DEBUG("evergreen_irq_set: vblank 5\n"); + crtc6 |= VBLANK_INT_MASK; + } + if (rdev->irq.hpd[0]) { + DRM_DEBUG("evergreen_irq_set: hpd 1\n"); + hpd1 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[1]) { + DRM_DEBUG("evergreen_irq_set: hpd 2\n"); + hpd2 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[2]) { + DRM_DEBUG("evergreen_irq_set: hpd 3\n"); + hpd3 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[3]) { + DRM_DEBUG("evergreen_irq_set: hpd 4\n"); + hpd4 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[4]) { + DRM_DEBUG("evergreen_irq_set: hpd 5\n"); + hpd5 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[5]) { + DRM_DEBUG("evergreen_irq_set: hpd 6\n"); + hpd6 |= DC_HPDx_INT_EN; + } + if (rdev->irq.afmt[0]) { + DRM_DEBUG("evergreen_irq_set: hdmi 0\n"); + afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK; + } + if (rdev->irq.afmt[1]) { + DRM_DEBUG("evergreen_irq_set: hdmi 1\n"); + afmt2 |= AFMT_AZ_FORMAT_WTRIG_MASK; + } + if (rdev->irq.afmt[2]) { + DRM_DEBUG("evergreen_irq_set: hdmi 2\n"); + afmt3 |= AFMT_AZ_FORMAT_WTRIG_MASK; + } + if (rdev->irq.afmt[3]) { + DRM_DEBUG("evergreen_irq_set: hdmi 3\n"); + afmt4 |= AFMT_AZ_FORMAT_WTRIG_MASK; + } + if (rdev->irq.afmt[4]) { + DRM_DEBUG("evergreen_irq_set: hdmi 4\n"); + afmt5 |= AFMT_AZ_FORMAT_WTRIG_MASK; + } + if (rdev->irq.afmt[5]) { + DRM_DEBUG("evergreen_irq_set: hdmi 5\n"); + afmt6 |= AFMT_AZ_FORMAT_WTRIG_MASK; + } + + if (rdev->family >= CHIP_CAYMAN) { + cayman_cp_int_cntl_setup(rdev, 0, cp_int_cntl); + cayman_cp_int_cntl_setup(rdev, 1, cp_int_cntl1); + cayman_cp_int_cntl_setup(rdev, 2, cp_int_cntl2); + } else + WREG32(CP_INT_CNTL, cp_int_cntl); + + WREG32(DMA_CNTL, dma_cntl); + + if (rdev->family >= CHIP_CAYMAN) + WREG32(CAYMAN_DMA1_CNTL, dma_cntl1); + + WREG32(GRBM_INT_CNTL, grbm_int_cntl); + + WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); + WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); + if (rdev->num_crtc >= 4) { + WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); + WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); + } + if (rdev->num_crtc >= 6) { + WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); + } + + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + } + + WREG32(DC_HPD1_INT_CONTROL, hpd1); + WREG32(DC_HPD2_INT_CONTROL, hpd2); + WREG32(DC_HPD3_INT_CONTROL, hpd3); + WREG32(DC_HPD4_INT_CONTROL, hpd4); + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, afmt3); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, afmt4); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); + + return 0; +} + +static void evergreen_irq_ack(struct radeon_device *rdev) +{ + u32 tmp; + + rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); + rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); + rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); + rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); + rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + } + + rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + + if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); + + if (rdev->num_crtc >= 4) { + if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); + } + + if (rdev->num_crtc >= 6) { + if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); + } + + if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { + tmp = RREG32(DC_HPD1_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD1_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { + tmp = RREG32(DC_HPD2_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD2_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { + tmp = RREG32(DC_HPD3_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD3_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { + tmp = RREG32(DC_HPD4_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD4_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, tmp); + } + if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, tmp); + } + if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, tmp); + } + if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, tmp); + } + if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, tmp); + } + if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, tmp); + } +} + +static void evergreen_irq_disable(struct radeon_device *rdev) +{ + r600_disable_interrupts(rdev); + /* Wait and acknowledge irq */ + DRM_MDELAY(1); + evergreen_irq_ack(rdev); + evergreen_disable_interrupt_state(rdev); +} + +void evergreen_irq_suspend(struct radeon_device *rdev) +{ + evergreen_irq_disable(rdev); + r600_rlc_stop(rdev); +} + +static u32 evergreen_get_ih_wptr(struct radeon_device *rdev) +{ + u32 wptr, tmp; + + if (rdev->wb.enabled) + wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); + else + wptr = RREG32(IH_RB_WPTR); + + if (wptr & RB_OVERFLOW) { + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", + wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); + rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); + } + return (wptr & rdev->ih.ptr_mask); +} + +irqreturn_t evergreen_irq_process(struct radeon_device *rdev) +{ + u32 wptr; + u32 rptr; + u32 src_id, src_data; + u32 ring_index; + bool queue_hotplug = false; + bool queue_hdmi = false; + + if (!rdev->ih.enabled || rdev->shutdown) + return IRQ_NONE; + + wptr = evergreen_get_ih_wptr(rdev); + +restart_ih: + /* is somebody else already processing irqs? */ + if (atomic_xchg(&rdev->ih.lock, 1)) + return IRQ_NONE; + + rptr = rdev->ih.rptr; + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + + /* Order reading of wptr vs. reading of IH ring data */ + rmb(); + + /* display interrupts */ + evergreen_irq_ack(rdev); + + while (rptr != wptr) { + /* wptr/rptr are in bytes! */ + ring_index = rptr / 4; + src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; + src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; + + switch (src_id) { + case 1: /* D1 vblank/vline */ + switch (src_data) { + case 0: /* D1 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_flip(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + } + break; + case 1: /* D1 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 2: /* D2 vblank/vline */ + switch (src_data) { + case 0: /* D2 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_flip(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + } + break; + case 1: /* D2 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 3: /* D3 vblank/vline */ + switch (src_data) { + case 0: /* D3 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_flip(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + } + break; + case 1: /* D3 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 4: /* D4 vblank/vline */ + switch (src_data) { + case 0: /* D4 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_flip(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + } + break; + case 1: /* D4 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 5: /* D5 vblank/vline */ + switch (src_data) { + case 0: /* D5 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_flip(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + } + break; + case 1: /* D5 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 6: /* D6 vblank/vline */ + switch (src_data) { + case 0: /* D6 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_flip(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + } + break; + case 1: /* D6 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 42: /* HPD hotplug */ + switch (src_data) { + case 0: + if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + } + break; + case 1: + if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + } + break; + case 2: + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + } + break; + case 3: + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + } + break; + case 4: + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + } + break; + case 5: + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 44: /* hdmi */ + switch (src_data) { + case 0: + if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI0\n"); + } + break; + case 1: + if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI1\n"); + } + break; + case 2: + if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI2\n"); + } + break; + case 3: + if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI3\n"); + } + break; + case 4: + if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI4\n"); + } + break; + case 5: + if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI5\n"); + } + break; + default: + DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 146: + case 147: + dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); + dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", + RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); + dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", + RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + /* reset addr and status */ + WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); + break; + case 176: /* CP_INT in ring buffer */ + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ + DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 181: /* CP EOP event */ + DRM_DEBUG("IH: CP EOP\n"); + if (rdev->family >= CHIP_CAYMAN) { + switch (src_data) { + case 0: + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 1: + radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); + break; + case 2: + radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); + break; + } + } else + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 224: /* DMA trap event */ + DRM_DEBUG("IH: DMA trap\n"); + radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX); + break; + case 233: /* GUI IDLE */ + DRM_DEBUG("IH: GUI idle\n"); + break; + case 244: /* DMA trap event */ + if (rdev->family >= CHIP_CAYMAN) { + DRM_DEBUG("IH: DMA1 trap\n"); + radeon_fence_process(rdev, CAYMAN_RING_TYPE_DMA1_INDEX); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + + /* wptr/rptr are in bytes! */ + rptr += 16; + rptr &= rdev->ih.ptr_mask; + } + if (queue_hotplug) + taskqueue_enqueue(rdev->tq, &rdev->hotplug_work); + if (queue_hdmi) + taskqueue_enqueue(rdev->tq, &rdev->audio_work); + rdev->ih.rptr = rptr; + WREG32(IH_RB_RPTR, rdev->ih.rptr); + atomic_set(&rdev->ih.lock, 0); + + /* make sure wptr hasn't changed while processing */ + wptr = evergreen_get_ih_wptr(rdev); + if (wptr != rptr) + goto restart_ih; + + return IRQ_HANDLED; +} + +/** + * evergreen_dma_fence_ring_emit - emit a fence on the DMA ring + * + * @rdev: radeon_device pointer + * @fence: radeon fence object + * + * Add a DMA fence packet to the ring to write + * the fence seq number and DMA trap packet to generate + * an interrupt if needed (evergreen-SI). + */ +void evergreen_dma_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + /* write the fence */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0)); + radeon_ring_write(ring, addr & 0xfffffffc); + radeon_ring_write(ring, (upper_32_bits(addr) & 0xff)); + radeon_ring_write(ring, fence->seq); + /* generate an interrupt */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0)); + /* flush HDP */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); + radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2)); + radeon_ring_write(ring, 1); +} + +/** + * evergreen_dma_ring_ib_execute - schedule an IB on the DMA engine + * + * @rdev: radeon_device pointer + * @ib: IB object to schedule + * + * Schedule an IB in the DMA ring (evergreen). + */ +void evergreen_dma_ring_ib_execute(struct radeon_device *rdev, + struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + + if (rdev->wb.enabled) { + u32 next_rptr = ring->wptr + 4; + while ((next_rptr & 7) != 5) + next_rptr++; + next_rptr += 3; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1)); + radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff); + radeon_ring_write(ring, next_rptr); + } + + /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring. + * Pad as necessary with NOPs. + */ + while ((ring->wptr & 7) != 5) + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_INDIRECT_BUFFER, 0, 0, 0)); + radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0)); + radeon_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF)); + +} + +/** + * evergreen_copy_dma - copy pages using the DMA engine + * + * @rdev: radeon_device pointer + * @src_offset: src GPU address + * @dst_offset: dst GPU address + * @num_gpu_pages: number of GPU pages to xfer + * @fence: radeon fence object + * + * Copy GPU paging using the DMA engine (evergreen-cayman). + * Used by the radeon ttm implementation to move pages if + * registered as the asic copy callback. + */ +int evergreen_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_semaphore *sem = NULL; + int ring_index = rdev->asic->copy.dma_ring_index; + struct radeon_ring *ring = &rdev->ring[ring_index]; + u32 size_in_dw, cur_size_in_dw; + int i, num_loops; + int r = 0; + + r = radeon_semaphore_create(rdev, &sem); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + + size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4; + num_loops = DIV_ROUND_UP(size_in_dw, 0xfffff); + r = radeon_ring_lock(rdev, ring, num_loops * 5 + 11); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + radeon_semaphore_free(rdev, &sem, NULL); + return r; + } + + if (radeon_fence_need_sync(*fence, ring->idx)) { + radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, + ring->idx); + radeon_fence_note_sync(*fence, ring->idx); + } else { + radeon_semaphore_free(rdev, &sem, NULL); + } + + for (i = 0; i < num_loops; i++) { + cur_size_in_dw = size_in_dw; + if (cur_size_in_dw > 0xFFFFF) + cur_size_in_dw = 0xFFFFF; + size_in_dw -= cur_size_in_dw; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw)); + radeon_ring_write(ring, dst_offset & 0xfffffffc); + radeon_ring_write(ring, src_offset & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); + radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff); + src_offset += cur_size_in_dw * 4; + dst_offset += cur_size_in_dw * 4; + } + + r = radeon_fence_emit(rdev, fence, ring->idx); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + + radeon_ring_unlock_commit(rdev, ring); + radeon_semaphore_free(rdev, &sem, *fence); + + return r; +} + +static int evergreen_startup(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* enable pcie gen2 link */ + evergreen_pcie_gen2_enable(rdev); + + if (ASIC_IS_DCE5(rdev)) { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + r = ni_mc_load_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); + return r; + } + } else { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } + + r = r600_vram_scratch_init(rdev); + if (r) + return r; + + evergreen_mc_program(rdev); + if (rdev->flags & RADEON_IS_AGP) { + evergreen_agp_enable(rdev); + } else { + r = evergreen_pcie_gart_enable(rdev); + if (r) + return r; + } + evergreen_gpu_init(rdev); + + r = evergreen_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); + rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + evergreen_irq_set(rdev); + + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, + R600_CP_RB_RPTR, R600_CP_RB_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, + DMA_RB_RPTR, DMA_RB_WPTR, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + if (r) + return r; + + r = evergreen_cp_load_microcode(rdev); + if (r) + return r; + r = evergreen_cp_resume(rdev); + if (r) + return r; + r = r600_dma_resume(rdev); + if (r) + return r; + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = r600_audio_init(rdev); + if (r) { + DRM_ERROR("radeon: audio init failed\n"); + return r; + } + + return 0; +} + +int evergreen_resume(struct radeon_device *rdev) +{ + int r; + + /* reset the asic, the gfx blocks are often in a bad state + * after the driver is unloaded or after a resume + */ + if (radeon_asic_reset(rdev)) + dev_warn(rdev->dev, "GPU reset failed !\n"); + /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, + * posting will perform necessary task to bring back GPU into good + * shape. + */ + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + + rdev->accel_working = true; + r = evergreen_startup(rdev); + if (r) { + DRM_ERROR("evergreen startup failed on resume\n"); + rdev->accel_working = false; + return r; + } + + return r; + +} + +int evergreen_suspend(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r700_cp_stop(rdev); + r600_dma_stop(rdev); + evergreen_irq_suspend(rdev); + radeon_wb_disable(rdev); + evergreen_pcie_gart_disable(rdev); + + return 0; +} + +/* Plan is to move initialization in that function and use + * helper function so that radeon_device_init pretty much + * do nothing more than calling asic specific function. This + * should also allow to remove a bunch of callback function + * like vram_info. + */ +int evergreen_init(struct radeon_device *rdev) +{ + int r; + + /* Read BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); + if (r) + return r; + /* reset the asic, the gfx blocks are often in a bad state + * after the driver is unloaded or after a resume + */ + if (radeon_asic_reset(rdev)) + dev_warn(rdev->dev, "GPU reset failed !\n"); + /* Post card if necessary */ + if (!radeon_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize scratch registers */ + r600_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + radeon_agp_disable(rdev); + } + /* initialize memory controller */ + r = evergreen_mc_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); + + rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); + + r = r600_pcie_gart_init(rdev); + if (r) + return r; + + rdev->accel_working = true; + r = evergreen_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + r700_cp_fini(rdev); + r600_dma_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + evergreen_pcie_gart_fini(rdev); + rdev->accel_working = false; + } + + /* Don't start up if the MC ucode is missing on BTC parts. + * The default clocks and voltages before the MC ucode + * is loaded are not suffient for advanced operations. + */ + if (ASIC_IS_DCE5(rdev)) { + if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { + DRM_ERROR("radeon: MC ucode required for NI+.\n"); + return -EINVAL; + } + } + + return 0; +} + +void evergreen_fini(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r600_blit_fini(rdev); + r700_cp_fini(rdev); + r600_dma_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + evergreen_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_agp_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + if (ASIC_IS_DCE5(rdev)) + ni_fini_microcode(rdev); + else + r600_fini_microcode(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +void evergreen_pcie_gen2_enable(struct radeon_device *rdev) +{ + u32 link_width_cntl, speed_cntl, mask; + int ret; + + if (radeon_pcie_gen2 == 0) + return; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + /* x2 cards have a special sequence */ + if (ASIC_IS_X2(rdev)) + return; + + ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); + if (ret != 0) + return; + + if (!(mask & DRM_PCIE_SPEED_50)) + return; + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if (speed_cntl & LC_CURRENT_DATA_RATE) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); + + if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || + (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { + + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + link_width_cntl &= ~LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl |= LC_GEN2_EN_STRAP; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + } else { + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ + if (1) + link_width_cntl |= LC_UPCONFIGURE_DIS; + else + link_width_cntl &= ~LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } +} diff --git a/sys/dev/drm2/radeon/evergreen_blit_kms.c b/sys/dev/drm2/radeon/evergreen_blit_kms.c new file mode 100644 index 00000000000..1012f3f35f3 --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_blit_kms.c @@ -0,0 +1,733 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_asic.h" + +#include "evergreend.h" +#include "evergreen_blit_shaders.h" +#include "cayman_blit_shaders.h" +#include "radeon_blit_common.h" + +/* emits 17 */ +static void +set_render_target(struct radeon_device *rdev, int format, + int w, int h, u64 gpu_addr) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cb_color_info; + int pitch, slice; + + h = roundup2(h, 8); + if (h < 8) + h = 8; + + cb_color_info = CB_FORMAT(format) | + CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) | + CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + pitch = (w / 8) - 1; + slice = ((w * h) / 64) - 1; + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 15)); + radeon_ring_write(ring, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, pitch); + radeon_ring_write(ring, slice); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, cb_color_info); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, (w - 1) | ((h - 1) << 16)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); +} + +/* emits 5dw */ +static void +cp_set_surface_sync(struct radeon_device *rdev, + u32 sync_type, u32 size, + u64 mc_addr) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cp_coher_size; + + if (size == 0xffffffff) + cp_coher_size = 0xffffffff; + else + cp_coher_size = ((size + 255) >> 8); + + if (rdev->family >= CHIP_CAYMAN) { + /* CP_COHER_CNTL2 has to be set manually when submitting a surface_sync + * to the RB directly. For IBs, the CP programs this as part of the + * surface_sync packet. + */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, 0); /* CP_COHER_CNTL2 */ + } + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, sync_type); + radeon_ring_write(ring, cp_coher_size); + radeon_ring_write(ring, mc_addr >> 8); + radeon_ring_write(ring, 10); /* poll interval */ +} + +/* emits 11dw + 1 surface sync = 16dw */ +static void +set_shaders(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u64 gpu_addr; + + /* VS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 3)); + radeon_ring_write(ring, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, 2); + radeon_ring_write(ring, 0); + + /* PS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.ps_offset; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 4)); + radeon_ring_write(ring, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, 1); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 2); + + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; + cp_set_surface_sync(rdev, PACKET3_SH_ACTION_ENA, 512, gpu_addr); +} + +/* emits 10 + 1 sync (5) = 15 */ +static void +set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_vtx_constant_word2, sq_vtx_constant_word3; + + /* high addr, stride */ + sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) | + SQ_VTXC_STRIDE(16); +#ifdef __BIG_ENDIAN + sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32); +#endif + /* xyzw swizzles */ + sq_vtx_constant_word3 = SQ_VTCX_SEL_X(SQ_SEL_X) | + SQ_VTCX_SEL_Y(SQ_SEL_Y) | + SQ_VTCX_SEL_Z(SQ_SEL_Z) | + SQ_VTCX_SEL_W(SQ_SEL_W); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 8)); + radeon_ring_write(ring, 0x580); + radeon_ring_write(ring, gpu_addr & 0xffffffff); + radeon_ring_write(ring, 48 - 1); /* size */ + radeon_ring_write(ring, sq_vtx_constant_word2); + radeon_ring_write(ring, sq_vtx_constant_word3); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_BUFFER)); + + if ((rdev->family == CHIP_CEDAR) || + (rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2) || + (rdev->family == CHIP_CAICOS)) + cp_set_surface_sync(rdev, + PACKET3_TC_ACTION_ENA, 48, gpu_addr); + else + cp_set_surface_sync(rdev, + PACKET3_VC_ACTION_ENA, 48, gpu_addr); + +} + +/* emits 10 */ +static void +set_tex_resource(struct radeon_device *rdev, + int format, int w, int h, int pitch, + u64 gpu_addr, u32 size) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_tex_resource_word0, sq_tex_resource_word1; + u32 sq_tex_resource_word4, sq_tex_resource_word7; + + if (h < 1) + h = 1; + + sq_tex_resource_word0 = TEX_DIM(SQ_TEX_DIM_2D); + sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 6) | + ((w - 1) << 18)); + sq_tex_resource_word1 = ((h - 1) << 0) | + TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + /* xyzw swizzles */ + sq_tex_resource_word4 = TEX_DST_SEL_X(SQ_SEL_X) | + TEX_DST_SEL_Y(SQ_SEL_Y) | + TEX_DST_SEL_Z(SQ_SEL_Z) | + TEX_DST_SEL_W(SQ_SEL_W); + + sq_tex_resource_word7 = format | + S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE); + + cp_set_surface_sync(rdev, + PACKET3_TC_ACTION_ENA, size, gpu_addr); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 8)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, sq_tex_resource_word0); + radeon_ring_write(ring, sq_tex_resource_word1); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, sq_tex_resource_word4); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, sq_tex_resource_word7); +} + +/* emits 12 */ +static void +set_scissors(struct radeon_device *rdev, int x1, int y1, + int x2, int y2) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + /* workaround some hw bugs */ + if (x2 == 0) + x1 = 1; + if (y2 == 0) + y1 = 1; + if (rdev->family >= CHIP_CAYMAN) { + if ((x2 == 1) && (y2 == 1)) + x2 = 2; + } + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(ring, (x1 << 0) | (y1 << 16)); + radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); + radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); + radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); +} + +/* emits 10 */ +static void +draw_auto(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, DI_PT_RECTLIST); + + radeon_ring_write(ring, PACKET3(PACKET3_INDEX_TYPE, 0)); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 2) | +#endif + DI_INDEX_SIZE_16_BIT); + + radeon_ring_write(ring, PACKET3(PACKET3_NUM_INSTANCES, 0)); + radeon_ring_write(ring, 1); + + radeon_ring_write(ring, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); + radeon_ring_write(ring, 3); + radeon_ring_write(ring, DI_SRC_SEL_AUTO_INDEX); + +} + +/* emits 39 */ +static void +set_default_state(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2, sq_gpr_resource_mgmt_3; + u32 sq_thread_resource_mgmt, sq_thread_resource_mgmt_2; + u32 sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2, sq_stack_resource_mgmt_3; + int num_ps_gprs, num_vs_gprs, num_temp_gprs; + int num_gs_gprs, num_es_gprs, num_hs_gprs, num_ls_gprs; + int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads; + int num_hs_threads, num_ls_threads; + int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; + int num_hs_stack_entries, num_ls_stack_entries; + u64 gpu_addr; + int dwords; + + /* set clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); + radeon_ring_write(ring, 0); + + if (rdev->family < CHIP_CAYMAN) { + switch (rdev->family) { + case CHIP_CEDAR: + default: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 16; + num_gs_threads = 16; + num_es_threads = 16; + num_hs_threads = 16; + num_ls_threads = 16; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_REDWOOD: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_JUNIPER: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_PALM: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 16; + num_gs_threads = 16; + num_es_threads = 16; + num_hs_threads = 16; + num_ls_threads = 16; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_SUMO: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 25; + num_gs_threads = 25; + num_es_threads = 25; + num_hs_threads = 25; + num_ls_threads = 25; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_SUMO2: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 25; + num_gs_threads = 25; + num_es_threads = 25; + num_hs_threads = 25; + num_ls_threads = 25; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_BARTS: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_TURKS: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_CAICOS: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 10; + num_gs_threads = 10; + num_es_threads = 10; + num_hs_threads = 10; + num_ls_threads = 10; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + } + + if ((rdev->family == CHIP_CEDAR) || + (rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2) || + (rdev->family == CHIP_CAICOS)) + sq_config = 0; + else + sq_config = VC_ENABLE; + + sq_config |= (EXPORT_SRC_C | + CS_PRIO(0) | + LS_PRIO(0) | + HS_PRIO(0) | + PS_PRIO(0) | + VS_PRIO(1) | + GS_PRIO(2) | + ES_PRIO(3)); + + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | + NUM_VS_GPRS(num_vs_gprs) | + NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | + NUM_ES_GPRS(num_es_gprs)); + sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | + NUM_LS_GPRS(num_ls_gprs)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | + NUM_VS_THREADS(num_vs_threads) | + NUM_GS_THREADS(num_gs_threads) | + NUM_ES_THREADS(num_es_threads)); + sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | + NUM_LS_THREADS(num_ls_threads)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | + NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | + NUM_ES_STACK_ENTRIES(num_es_stack_entries)); + sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | + NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); + + /* disable dyn gprs */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, 0); + + /* setup LDS */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (SQ_LDS_RESOURCE_MGMT - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, 0x10001000); + + /* SQ config */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 11)); + radeon_ring_write(ring, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, sq_config); + radeon_ring_write(ring, sq_gpr_resource_mgmt_1); + radeon_ring_write(ring, sq_gpr_resource_mgmt_2); + radeon_ring_write(ring, sq_gpr_resource_mgmt_3); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, sq_thread_resource_mgmt); + radeon_ring_write(ring, sq_thread_resource_mgmt_2); + radeon_ring_write(ring, sq_stack_resource_mgmt_1); + radeon_ring_write(ring, sq_stack_resource_mgmt_2); + radeon_ring_write(ring, sq_stack_resource_mgmt_3); + } + + /* CONTEXT_CONTROL */ + radeon_ring_write(ring, 0xc0012800); + radeon_ring_write(ring, 0x80000000); + radeon_ring_write(ring, 0x80000000); + + /* SQ_VTX_BASE_VTX_LOC */ + radeon_ring_write(ring, 0xc0026f00); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + + /* SET_SAMPLER */ + radeon_ring_write(ring, 0xc0036e00); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000012); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + + /* set to DX10/11 mode */ + radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); + radeon_ring_write(ring, 1); + + /* emit an IB pointing at default state */ + dwords = roundup2(rdev->r600_blit.state_len, 0x10); + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; + radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(ring, gpu_addr & 0xFFFFFFFC); + radeon_ring_write(ring, upper_32_bits(gpu_addr) & 0xFF); + radeon_ring_write(ring, dwords); + +} + +int evergreen_blit_init(struct radeon_device *rdev) +{ + u32 obj_size; + int i, r, dwords; + void *ptr; + u32 packet2s[16]; + int num_packet2s = 0; + + rdev->r600_blit.primitives.set_render_target = set_render_target; + rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync; + rdev->r600_blit.primitives.set_shaders = set_shaders; + rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource; + rdev->r600_blit.primitives.set_tex_resource = set_tex_resource; + rdev->r600_blit.primitives.set_scissors = set_scissors; + rdev->r600_blit.primitives.draw_auto = draw_auto; + rdev->r600_blit.primitives.set_default_state = set_default_state; + + rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ + rdev->r600_blit.ring_size_common += 55; /* shaders + def state */ + rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */ + rdev->r600_blit.ring_size_common += 5; /* done copy */ + rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ + + rdev->r600_blit.ring_size_per_loop = 74; + if (rdev->family >= CHIP_CAYMAN) + rdev->r600_blit.ring_size_per_loop += 9; /* additional DWs for surface sync */ + + rdev->r600_blit.max_dim = 16384; + + rdev->r600_blit.state_offset = 0; + + if (rdev->family < CHIP_CAYMAN) + rdev->r600_blit.state_len = evergreen_default_size; + else + rdev->r600_blit.state_len = cayman_default_size; + + dwords = rdev->r600_blit.state_len; + while (dwords & 0xf) { + packet2s[num_packet2s++] = cpu_to_le32(PACKET2(0)); + dwords++; + } + + obj_size = dwords * 4; + obj_size = roundup2(obj_size, 256); + + rdev->r600_blit.vs_offset = obj_size; + if (rdev->family < CHIP_CAYMAN) + obj_size += evergreen_vs_size * 4; + else + obj_size += cayman_vs_size * 4; + obj_size = roundup2(obj_size, 256); + + rdev->r600_blit.ps_offset = obj_size; + if (rdev->family < CHIP_CAYMAN) + obj_size += evergreen_ps_size * 4; + else + obj_size += cayman_ps_size * 4; + obj_size = roundup2(obj_size, 256); + + /* pin copy shader into vram if not already initialized */ + if (!rdev->r600_blit.shader_obj) { + r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->r600_blit.shader_obj); + if (r) { + DRM_ERROR("evergreen failed to allocate shader\n"); + return r; + } + + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_gpu_addr); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + if (r) { + dev_err(rdev->dev, "(%d) pin blit object failed\n", r); + return r; + } + } + + DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", + obj_size, + rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset); + + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_kmap(rdev->r600_blit.shader_obj, &ptr); + if (r) { + DRM_ERROR("failed to map blit object %d\n", r); + return r; + } + + if (rdev->family < CHIP_CAYMAN) { + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset, + evergreen_default_state, rdev->r600_blit.state_len * 4); + + if (num_packet2s) + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); + for (i = 0; i < evergreen_vs_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); + for (i = 0; i < evergreen_ps_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); + } else { + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset, + cayman_default_state, rdev->r600_blit.state_len * 4); + + if (num_packet2s) + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); + for (i = 0; i < cayman_vs_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(cayman_vs[i]); + for (i = 0; i < cayman_ps_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(cayman_ps[i]); + } + radeon_bo_kunmap(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; +} diff --git a/sys/dev/drm2/radeon/evergreen_blit_shaders.c b/sys/dev/drm2/radeon/evergreen_blit_shaders.c new file mode 100644 index 00000000000..6db3cef0255 --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_blit_shaders.c @@ -0,0 +1,358 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +/* + * evergreen cards need to use the 3D engine to blit data which requires + * quite a bit of hw state setup. Rather than pull the whole 3D driver + * (which normally generates the 3D state) into the DRM, we opt to use + * statically generated state tables. The regsiter state and shaders + * were hand generated to support blitting functionality. See the 3D + * driver or documentation for descriptions of the registers and + * shader instructions. + */ + +const u32 evergreen_default_state[] = +{ + 0xc0016900, + 0x0000023b, + 0x00000000, /* SQ_LDS_ALLOC_PS */ + + 0xc0066900, + 0x00000240, + 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0046900, + 0x00000247, + 0x00000000, /* SQ_GS_VERT_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0026900, + 0x00000010, + 0x00000000, /* DB_Z_INFO */ + 0x00000000, /* DB_STENCIL_INFO */ + + 0xc0016900, + 0x00000200, + 0x00000000, /* DB_DEPTH_CONTROL */ + + 0xc0066900, + 0x00000000, + 0x00000060, /* DB_RENDER_CONTROL */ + 0x00000000, /* DB_COUNT_CONTROL */ + 0x00000000, /* DB_DEPTH_VIEW */ + 0x0000002a, /* DB_RENDER_OVERRIDE */ + 0x00000000, /* DB_RENDER_OVERRIDE2 */ + 0x00000000, /* DB_HTILE_DATA_BASE */ + + 0xc0026900, + 0x0000000a, + 0x00000000, /* DB_STENCIL_CLEAR */ + 0x00000000, /* DB_DEPTH_CLEAR */ + + 0xc0016900, + 0x000002dc, + 0x0000aa00, /* DB_ALPHA_TO_MASK */ + + 0xc0016900, + 0x00000080, + 0x00000000, /* PA_SC_WINDOW_OFFSET */ + + 0xc00d6900, + 0x00000083, + 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ + 0x00000000, /* PA_SC_CLIPRECT_0_TL */ + 0x20002000, /* PA_SC_CLIPRECT_0_BR */ + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0xaaaaaaaa, /* PA_SC_EDGERULE */ + 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ + 0x0000000f, /* CB_TARGET_MASK */ + 0x0000000f, /* CB_SHADER_MASK */ + + 0xc0226900, + 0x00000094, + 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ + 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ + 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ + + 0xc0016900, + 0x000000d4, + 0x00000000, /* SX_MISC */ + + 0xc0026900, + 0x00000292, + 0x00000000, /* PA_SC_MODE_CNTL_0 */ + 0x00000000, /* PA_SC_MODE_CNTL_1 */ + + 0xc0106900, + 0x00000300, + 0x00000000, /* PA_SC_LINE_CNTL */ + 0x00000000, /* PA_SC_AA_CONFIG */ + 0x00000005, /* PA_SU_VTX_CNTL */ + 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ + 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_0 */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_7 */ + 0xffffffff, /* PA_SC_AA_MASK */ + + 0xc00d6900, + 0x00000202, + 0x00cc0010, /* CB_COLOR_CONTROL */ + 0x00000210, /* DB_SHADER_CONTROL */ + 0x00010000, /* PA_CL_CLIP_CNTL */ + 0x00000004, /* PA_SU_SC_MODE_CNTL */ + 0x00000100, /* PA_CL_VTE_CNTL */ + 0x00000000, /* PA_CL_VS_OUT_CNTL */ + 0x00000000, /* PA_CL_NANINF_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ + 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* SQ_DYN_GPR_RESOURCE_LIMIT_1 */ + + 0xc0066900, + 0x000002de, + 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + + 0xc0016900, + 0x00000229, + 0x00000000, /* SQ_PGM_START_FS */ + + 0xc0016900, + 0x0000022a, + 0x00000000, /* SQ_PGM_RESOURCES_FS */ + + 0xc0096900, + 0x00000100, + 0x00ffffff, /* VGT_MAX_VTX_INDX */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* SX_ALPHA_TEST_CONTROL */ + 0x00000000, /* CB_BLEND_RED */ + 0x00000000, /* CB_BLEND_GREEN */ + 0x00000000, /* CB_BLEND_BLUE */ + 0x00000000, /* CB_BLEND_ALPHA */ + + 0xc0026900, + 0x000002a8, + 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ + 0x00000000, /* */ + + 0xc0026900, + 0x000002ad, + 0x00000000, /* VGT_REUSE_OFF */ + 0x00000000, /* */ + + 0xc0116900, + 0x00000280, + 0x00000000, /* PA_SU_POINT_SIZE */ + 0x00000000, /* PA_SU_POINT_MINMAX */ + 0x00000008, /* PA_SU_LINE_CNTL */ + 0x00000000, /* PA_SC_LINE_STIPPLE */ + 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ + 0x00000000, /* VGT_HOS_CNTL */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* VGT_GS_MODE */ + + 0xc0016900, + 0x000002a1, + 0x00000000, /* VGT_PRIMITIVEID_EN */ + + 0xc0016900, + 0x000002a5, + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ + + 0xc0016900, + 0x000002d5, + 0x00000000, /* VGT_SHADER_STAGES_EN */ + + 0xc0026900, + 0x000002e5, + 0x00000000, /* VGT_STRMOUT_CONFIG */ + 0x00000000, /* */ + + 0xc0016900, + 0x000001e0, + 0x00000000, /* CB_BLEND0_CONTROL */ + + 0xc0016900, + 0x000001b1, + 0x00000000, /* SPI_VS_OUT_CONFIG */ + + 0xc0016900, + 0x00000187, + 0x00000000, /* SPI_VS_OUT_ID_0 */ + + 0xc0016900, + 0x00000191, + 0x00000100, /* SPI_PS_INPUT_CNTL_0 */ + + 0xc00b6900, + 0x000001b3, + 0x20000001, /* SPI_PS_IN_CONTROL_0 */ + 0x00000000, /* SPI_PS_IN_CONTROL_1 */ + 0x00000000, /* SPI_INTERP_CONTROL_0 */ + 0x00000000, /* SPI_INPUT_Z */ + 0x00000000, /* SPI_FOG_CNTL */ + 0x00100000, /* SPI_BARYC_CNTL */ + 0x00000000, /* SPI_PS_IN_CONTROL_2 */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + 0x00000000, /* */ + + 0xc0026900, + 0x00000316, + 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + 0x00000010, /* */ +}; + +const u32 evergreen_vs[] = +{ + 0x00000004, + 0x80800400, + 0x0000a03c, + 0x95000688, + 0x00004000, + 0x15200688, + 0x00000000, + 0x00000000, + 0x3c000000, + 0x67961001, +#ifdef __BIG_ENDIAN + 0x000a0000, +#else + 0x00080000, +#endif + 0x00000000, + 0x1c000000, + 0x67961000, +#ifdef __BIG_ENDIAN + 0x00020008, +#else + 0x00000008, +#endif + 0x00000000, +}; + +const u32 evergreen_ps[] = +{ + 0x00000003, + 0xa00c0000, + 0x00000008, + 0x80400000, + 0x00000000, + 0x95200688, + 0x00380400, + 0x00146b10, + 0x00380000, + 0x20146b10, + 0x00380400, + 0x40146b00, + 0x80380000, + 0x60146b00, + 0x00000000, + 0x00000000, + 0x00000010, + 0x000d1000, + 0xb0800000, + 0x00000000, +}; + +const u32 evergreen_ps_size = DRM_ARRAY_SIZE(evergreen_ps); +const u32 evergreen_vs_size = DRM_ARRAY_SIZE(evergreen_vs); +const u32 evergreen_default_size = DRM_ARRAY_SIZE(evergreen_default_state); diff --git a/sys/dev/drm2/radeon/evergreen_blit_shaders.h b/sys/dev/drm2/radeon/evergreen_blit_shaders.h new file mode 100644 index 00000000000..a5e2dc3490d --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_blit_shaders.h @@ -0,0 +1,38 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef EVERGREEN_BLIT_SHADERS_H +#define EVERGREEN_BLIT_SHADERS_H + +extern const u32 evergreen_ps[]; +extern const u32 evergreen_vs[]; +extern const u32 evergreen_default_state[]; + +extern const u32 evergreen_ps_size, evergreen_vs_size; +extern const u32 evergreen_default_size; + +#endif diff --git a/sys/dev/drm2/radeon/evergreen_cs.c b/sys/dev/drm2/radeon/evergreen_cs.c new file mode 100644 index 00000000000..693c38c2900 --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_cs.c @@ -0,0 +1,3727 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "evergreend.h" +#include "evergreen_reg_safe.h" +#include "cayman_reg_safe.h" +#include "r600_cs.h" + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); + +struct evergreen_cs_track { + u32 group_size; + u32 nbanks; + u32 npipes; + u32 row_size; + /* value we track */ + u32 nsamples; /* unused */ + struct radeon_bo *cb_color_bo[12]; + u32 cb_color_bo_offset[12]; + struct radeon_bo *cb_color_fmask_bo[8]; /* unused */ + struct radeon_bo *cb_color_cmask_bo[8]; /* unused */ + u32 cb_color_info[12]; + u32 cb_color_view[12]; + u32 cb_color_pitch[12]; + u32 cb_color_slice[12]; + u32 cb_color_slice_idx[12]; + u32 cb_color_attrib[12]; + u32 cb_color_cmask_slice[8];/* unused */ + u32 cb_color_fmask_slice[8];/* unused */ + u32 cb_target_mask; + u32 cb_shader_mask; /* unused */ + u32 vgt_strmout_config; + u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; + u32 db_depth_control; + u32 db_depth_view; + u32 db_depth_slice; + u32 db_depth_size; + u32 db_z_info; + u32 db_z_read_offset; + u32 db_z_write_offset; + struct radeon_bo *db_z_read_bo; + struct radeon_bo *db_z_write_bo; + u32 db_s_info; + u32 db_s_read_offset; + u32 db_s_write_offset; + struct radeon_bo *db_s_read_bo; + struct radeon_bo *db_s_write_bo; + bool sx_misc_kill_all_prims; + bool cb_dirty; + bool db_dirty; + bool streamout_dirty; + u32 htile_offset; + u32 htile_surface; + struct radeon_bo *htile_bo; +}; + +static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) +{ + if (tiling_flags & RADEON_TILING_MACRO) + return ARRAY_2D_TILED_THIN1; + else if (tiling_flags & RADEON_TILING_MICRO) + return ARRAY_1D_TILED_THIN1; + else + return ARRAY_LINEAR_GENERAL; +} + +static u32 evergreen_cs_get_num_banks(u32 nbanks) +{ + switch (nbanks) { + case 2: + return ADDR_SURF_2_BANK; + case 4: + return ADDR_SURF_4_BANK; + case 8: + default: + return ADDR_SURF_8_BANK; + case 16: + return ADDR_SURF_16_BANK; + } +} + +static void evergreen_cs_track_init(struct evergreen_cs_track *track) +{ + int i; + + for (i = 0; i < 8; i++) { + track->cb_color_fmask_bo[i] = NULL; + track->cb_color_cmask_bo[i] = NULL; + track->cb_color_cmask_slice[i] = 0; + track->cb_color_fmask_slice[i] = 0; + } + + for (i = 0; i < 12; i++) { + track->cb_color_bo[i] = NULL; + track->cb_color_bo_offset[i] = 0xFFFFFFFF; + track->cb_color_info[i] = 0; + track->cb_color_view[i] = 0xFFFFFFFF; + track->cb_color_pitch[i] = 0; + track->cb_color_slice[i] = 0xfffffff; + track->cb_color_slice_idx[i] = 0; + } + track->cb_target_mask = 0xFFFFFFFF; + track->cb_shader_mask = 0xFFFFFFFF; + track->cb_dirty = true; + + track->db_depth_slice = 0xffffffff; + track->db_depth_view = 0xFFFFC000; + track->db_depth_size = 0xFFFFFFFF; + track->db_depth_control = 0xFFFFFFFF; + track->db_z_info = 0xFFFFFFFF; + track->db_z_read_offset = 0xFFFFFFFF; + track->db_z_write_offset = 0xFFFFFFFF; + track->db_z_read_bo = NULL; + track->db_z_write_bo = NULL; + track->db_s_info = 0xFFFFFFFF; + track->db_s_read_offset = 0xFFFFFFFF; + track->db_s_write_offset = 0xFFFFFFFF; + track->db_s_read_bo = NULL; + track->db_s_write_bo = NULL; + track->db_dirty = true; + track->htile_bo = NULL; + track->htile_offset = 0xFFFFFFFF; + track->htile_surface = 0; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + } + track->streamout_dirty = true; + track->sx_misc_kill_all_prims = false; +} + +struct eg_surface { + /* value gathered from cs */ + unsigned nbx; + unsigned nby; + unsigned format; + unsigned mode; + unsigned nbanks; + unsigned bankw; + unsigned bankh; + unsigned tsplit; + unsigned mtilea; + unsigned nsamples; + /* output value */ + unsigned bpe; + unsigned layer_size; + unsigned palign; + unsigned halign; + unsigned long base_align; +}; + +static int evergreen_surface_check_linear(struct radeon_cs_parser *p, + struct eg_surface *surf, + const char *prefix) +{ + surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; + surf->base_align = surf->bpe; + surf->palign = 1; + surf->halign = 1; + return 0; +} + +static int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p, + struct eg_surface *surf, + const char *prefix) +{ + struct evergreen_cs_track *track = p->track; + unsigned palign; + + palign = MAX(64, track->group_size / surf->bpe); + surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; + surf->base_align = track->group_size; + surf->palign = palign; + surf->halign = 1; + if (surf->nbx & (palign - 1)) { + if (prefix) { + dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", + __func__, __LINE__, prefix, surf->nbx, palign); + } + return -EINVAL; + } + return 0; +} + +static int evergreen_surface_check_1d(struct radeon_cs_parser *p, + struct eg_surface *surf, + const char *prefix) +{ + struct evergreen_cs_track *track = p->track; + unsigned palign; + + palign = track->group_size / (8 * surf->bpe * surf->nsamples); + palign = MAX(8, palign); + surf->layer_size = surf->nbx * surf->nby * surf->bpe; + surf->base_align = track->group_size; + surf->palign = palign; + surf->halign = 8; + if ((surf->nbx & (palign - 1))) { + if (prefix) { + dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n", + __func__, __LINE__, prefix, surf->nbx, palign, + track->group_size, surf->bpe, surf->nsamples); + } + return -EINVAL; + } + if ((surf->nby & (8 - 1))) { + if (prefix) { + dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n", + __func__, __LINE__, prefix, surf->nby); + } + return -EINVAL; + } + return 0; +} + +static int evergreen_surface_check_2d(struct radeon_cs_parser *p, + struct eg_surface *surf, + const char *prefix) +{ + struct evergreen_cs_track *track = p->track; + unsigned palign, halign, tileb, slice_pt; + unsigned mtile_pr, mtile_ps, mtileb; + + tileb = 64 * surf->bpe * surf->nsamples; + slice_pt = 1; + if (tileb > surf->tsplit) { + slice_pt = tileb / surf->tsplit; + } + tileb = tileb / slice_pt; + /* macro tile width & height */ + palign = (8 * surf->bankw * track->npipes) * surf->mtilea; + halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; + mtileb = (palign / 8) * (halign / 8) * tileb; + mtile_pr = surf->nbx / palign; + mtile_ps = (mtile_pr * surf->nby) / halign; + surf->layer_size = mtile_ps * mtileb * slice_pt; + surf->base_align = (palign / 8) * (halign / 8) * tileb; + surf->palign = palign; + surf->halign = halign; + + if ((surf->nbx & (palign - 1))) { + if (prefix) { + dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", + __func__, __LINE__, prefix, surf->nbx, palign); + } + return -EINVAL; + } + if ((surf->nby & (halign - 1))) { + if (prefix) { + dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n", + __func__, __LINE__, prefix, surf->nby, halign); + } + return -EINVAL; + } + + return 0; +} + +static int evergreen_surface_check(struct radeon_cs_parser *p, + struct eg_surface *surf, + const char *prefix) +{ + /* some common value computed here */ + surf->bpe = r600_fmt_get_blocksize(surf->format); + + switch (surf->mode) { + case ARRAY_LINEAR_GENERAL: + return evergreen_surface_check_linear(p, surf, prefix); + case ARRAY_LINEAR_ALIGNED: + return evergreen_surface_check_linear_aligned(p, surf, prefix); + case ARRAY_1D_TILED_THIN1: + return evergreen_surface_check_1d(p, surf, prefix); + case ARRAY_2D_TILED_THIN1: + return evergreen_surface_check_2d(p, surf, prefix); + default: + dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", + __func__, __LINE__, prefix, surf->mode); + return -EINVAL; + } + return -EINVAL; +} + +static int evergreen_surface_value_conv_check(struct radeon_cs_parser *p, + struct eg_surface *surf, + const char *prefix) +{ + switch (surf->mode) { + case ARRAY_2D_TILED_THIN1: + break; + case ARRAY_LINEAR_GENERAL: + case ARRAY_LINEAR_ALIGNED: + case ARRAY_1D_TILED_THIN1: + return 0; + default: + dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", + __func__, __LINE__, prefix, surf->mode); + return -EINVAL; + } + + switch (surf->nbanks) { + case 0: surf->nbanks = 2; break; + case 1: surf->nbanks = 4; break; + case 2: surf->nbanks = 8; break; + case 3: surf->nbanks = 16; break; + default: + dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n", + __func__, __LINE__, prefix, surf->nbanks); + return -EINVAL; + } + switch (surf->bankw) { + case 0: surf->bankw = 1; break; + case 1: surf->bankw = 2; break; + case 2: surf->bankw = 4; break; + case 3: surf->bankw = 8; break; + default: + dev_warn(p->dev, "%s:%d %s invalid bankw %d\n", + __func__, __LINE__, prefix, surf->bankw); + return -EINVAL; + } + switch (surf->bankh) { + case 0: surf->bankh = 1; break; + case 1: surf->bankh = 2; break; + case 2: surf->bankh = 4; break; + case 3: surf->bankh = 8; break; + default: + dev_warn(p->dev, "%s:%d %s invalid bankh %d\n", + __func__, __LINE__, prefix, surf->bankh); + return -EINVAL; + } + switch (surf->mtilea) { + case 0: surf->mtilea = 1; break; + case 1: surf->mtilea = 2; break; + case 2: surf->mtilea = 4; break; + case 3: surf->mtilea = 8; break; + default: + dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n", + __func__, __LINE__, prefix, surf->mtilea); + return -EINVAL; + } + switch (surf->tsplit) { + case 0: surf->tsplit = 64; break; + case 1: surf->tsplit = 128; break; + case 2: surf->tsplit = 256; break; + case 3: surf->tsplit = 512; break; + case 4: surf->tsplit = 1024; break; + case 5: surf->tsplit = 2048; break; + case 6: surf->tsplit = 4096; break; + default: + dev_warn(p->dev, "%s:%d %s invalid tile split %d\n", + __func__, __LINE__, prefix, surf->tsplit); + return -EINVAL; + } + return 0; +} + +static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id) +{ + struct evergreen_cs_track *track = p->track; + struct eg_surface surf; + unsigned pitch, slice, mslice; + unsigned long offset; + int r; + + mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; + pitch = track->cb_color_pitch[id]; + slice = track->cb_color_slice[id]; + surf.nbx = (pitch + 1) * 8; + surf.nby = ((slice + 1) * 64) / surf.nbx; + surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]); + surf.format = G_028C70_FORMAT(track->cb_color_info[id]); + surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]); + surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]); + surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]); + surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]); + surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]); + surf.nsamples = 1; + + if (!r600_fmt_is_valid_color(surf.format)) { + dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n", + __func__, __LINE__, surf.format, + id, track->cb_color_info[id]); + return -EINVAL; + } + + r = evergreen_surface_value_conv_check(p, &surf, "cb"); + if (r) { + return r; + } + + r = evergreen_surface_check(p, &surf, "cb"); + if (r) { + dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", + __func__, __LINE__, id, track->cb_color_pitch[id], + track->cb_color_slice[id], track->cb_color_attrib[id], + track->cb_color_info[id]); + return r; + } + + offset = track->cb_color_bo_offset[id] << 8; + if (offset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", + __func__, __LINE__, id, offset, surf.base_align); + return -EINVAL; + } + + offset += surf.layer_size * mslice; + if (offset > radeon_bo_size(track->cb_color_bo[id])) { + /* old ddx are broken they allocate bo with w*h*bpp but + * program slice with ALIGN(h, 8), catch this and patch + * command stream. + */ + if (!surf.mode) { + volatile u32 *ib = p->ib.ptr; + unsigned long tmp, nby, bsize, size, min = 0; + + /* find the height the ddx wants */ + if (surf.nby > 8) { + min = surf.nby - 8; + } + bsize = radeon_bo_size(track->cb_color_bo[id]); + tmp = track->cb_color_bo_offset[id] << 8; + for (nby = surf.nby; nby > min; nby--) { + size = nby * surf.nbx * surf.bpe * surf.nsamples; + if ((tmp + size * mslice) <= bsize) { + break; + } + } + if (nby > min) { + surf.nby = nby; + slice = ((nby * surf.nbx) / 64) - 1; + if (!evergreen_surface_check(p, &surf, "cb")) { + /* check if this one works */ + tmp += surf.layer_size * mslice; + if (tmp <= bsize) { + ib[track->cb_color_slice_idx[id]] = slice; + goto old_ddx_ok; + } + } + } + } + dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " + "offset %d, max layer %d, bo size %ld, slice %d)\n", + __func__, __LINE__, id, surf.layer_size, + track->cb_color_bo_offset[id] << 8, mslice, + radeon_bo_size(track->cb_color_bo[id]), slice); + dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", + __func__, __LINE__, surf.nbx, surf.nby, + surf.mode, surf.bpe, surf.nsamples, + surf.bankw, surf.bankh, + surf.tsplit, surf.mtilea); + return -EINVAL; + } +old_ddx_ok: + + return 0; +} + +static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, + unsigned nbx, unsigned nby) +{ + struct evergreen_cs_track *track = p->track; + unsigned long size; + + if (track->htile_bo == NULL) { + dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", + __func__, __LINE__, track->db_z_info); + return -EINVAL; + } + + if (G_028ABC_LINEAR(track->htile_surface)) { + /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */ + nbx = roundup(nbx, 16 * 8); + /* height is npipes htiles aligned == npipes * 8 pixel aligned */ + nby = roundup(nby, track->npipes * 8); + } else { + /* always assume 8x8 htile */ + /* align is htile align * 8, htile align vary according to + * number of pipe and tile width and nby + */ + switch (track->npipes) { + case 8: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup(nbx, 64 * 8); + nby = roundup(nby, 64 * 8); + break; + case 4: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup(nbx, 64 * 8); + nby = roundup(nby, 32 * 8); + break; + case 2: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup(nbx, 32 * 8); + nby = roundup(nby, 32 * 8); + break; + case 1: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup(nbx, 32 * 8); + nby = roundup(nby, 16 * 8); + break; + default: + dev_warn(p->dev, "%s:%d invalid num pipes %d\n", + __func__, __LINE__, track->npipes); + return -EINVAL; + } + } + /* compute number of htile */ + nbx = nbx >> 3; + nby = nby >> 3; + /* size must be aligned on npipes * 2K boundary */ + size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); + size += track->htile_offset; + + if (size > radeon_bo_size(track->htile_bo)) { + dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", + __func__, __LINE__, radeon_bo_size(track->htile_bo), + size, nbx, nby); + return -EINVAL; + } + return 0; +} + +static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) +{ + struct evergreen_cs_track *track = p->track; + struct eg_surface surf; + unsigned pitch, slice, mslice; + unsigned long offset; + int r; + + mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; + pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); + slice = track->db_depth_slice; + surf.nbx = (pitch + 1) * 8; + surf.nby = ((slice + 1) * 64) / surf.nbx; + surf.mode = G_028040_ARRAY_MODE(track->db_z_info); + surf.format = G_028044_FORMAT(track->db_s_info); + surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info); + surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); + surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); + surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); + surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); + surf.nsamples = 1; + + if (surf.format != 1) { + dev_warn(p->dev, "%s:%d stencil invalid format %d\n", + __func__, __LINE__, surf.format); + return -EINVAL; + } + /* replace by color format so we can use same code */ + surf.format = V_028C70_COLOR_8; + + r = evergreen_surface_value_conv_check(p, &surf, "stencil"); + if (r) { + return r; + } + + r = evergreen_surface_check(p, &surf, NULL); + if (r) { + /* old userspace doesn't compute proper depth/stencil alignment + * check that alignment against a bigger byte per elements and + * only report if that alignment is wrong too. + */ + surf.format = V_028C70_COLOR_8_8_8_8; + r = evergreen_surface_check(p, &surf, "stencil"); + if (r) { + dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", + __func__, __LINE__, track->db_depth_size, + track->db_depth_slice, track->db_s_info, track->db_z_info); + } + return r; + } + + offset = track->db_s_read_offset << 8; + if (offset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } + offset += surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_s_read_bo)) { + dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " + "offset %ld, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, + (unsigned long)track->db_s_read_offset << 8, mslice, + radeon_bo_size(track->db_s_read_bo)); + dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", + __func__, __LINE__, track->db_depth_size, + track->db_depth_slice, track->db_s_info, track->db_z_info); + return -EINVAL; + } + + offset = track->db_s_write_offset << 8; + if (offset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } + offset += surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_s_write_bo)) { + dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " + "offset %ld, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, + (unsigned long)track->db_s_write_offset << 8, mslice, + radeon_bo_size(track->db_s_write_bo)); + return -EINVAL; + } + + /* hyperz */ + if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { + r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); + if (r) { + return r; + } + } + + return 0; +} + +static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) +{ + struct evergreen_cs_track *track = p->track; + struct eg_surface surf; + unsigned pitch, slice, mslice; + unsigned long offset; + int r; + + mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; + pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); + slice = track->db_depth_slice; + surf.nbx = (pitch + 1) * 8; + surf.nby = ((slice + 1) * 64) / surf.nbx; + surf.mode = G_028040_ARRAY_MODE(track->db_z_info); + surf.format = G_028040_FORMAT(track->db_z_info); + surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info); + surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); + surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); + surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); + surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); + surf.nsamples = 1; + + switch (surf.format) { + case V_028040_Z_16: + surf.format = V_028C70_COLOR_16; + break; + case V_028040_Z_24: + case V_028040_Z_32_FLOAT: + surf.format = V_028C70_COLOR_8_8_8_8; + break; + default: + dev_warn(p->dev, "%s:%d depth invalid format %d\n", + __func__, __LINE__, surf.format); + return -EINVAL; + } + + r = evergreen_surface_value_conv_check(p, &surf, "depth"); + if (r) { + dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", + __func__, __LINE__, track->db_depth_size, + track->db_depth_slice, track->db_z_info); + return r; + } + + r = evergreen_surface_check(p, &surf, "depth"); + if (r) { + dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", + __func__, __LINE__, track->db_depth_size, + track->db_depth_slice, track->db_z_info); + return r; + } + + offset = track->db_z_read_offset << 8; + if (offset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } + offset += surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_z_read_bo)) { + dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " + "offset %ld, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, + (unsigned long)track->db_z_read_offset << 8, mslice, + radeon_bo_size(track->db_z_read_bo)); + return -EINVAL; + } + + offset = track->db_z_write_offset << 8; + if (offset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } + offset += surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_z_write_bo)) { + dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " + "offset %ld, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, + (unsigned long)track->db_z_write_offset << 8, mslice, + radeon_bo_size(track->db_z_write_bo)); + return -EINVAL; + } + + /* hyperz */ + if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { + r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); + if (r) { + return r; + } + } + + return 0; +} + +static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, + struct radeon_bo *texture, + struct radeon_bo *mipmap, + unsigned idx) +{ + struct eg_surface surf; + unsigned long toffset, moffset; + unsigned dim, llevel, mslice, width, height, depth, i; + u32 texdw[8]; + int r; + + texdw[0] = radeon_get_ib_value(p, idx + 0); + texdw[1] = radeon_get_ib_value(p, idx + 1); + texdw[2] = radeon_get_ib_value(p, idx + 2); + texdw[3] = radeon_get_ib_value(p, idx + 3); + texdw[4] = radeon_get_ib_value(p, idx + 4); + texdw[5] = radeon_get_ib_value(p, idx + 5); + texdw[6] = radeon_get_ib_value(p, idx + 6); + texdw[7] = radeon_get_ib_value(p, idx + 7); + dim = G_030000_DIM(texdw[0]); + llevel = G_030014_LAST_LEVEL(texdw[5]); + mslice = G_030014_LAST_ARRAY(texdw[5]) + 1; + width = G_030000_TEX_WIDTH(texdw[0]) + 1; + height = G_030004_TEX_HEIGHT(texdw[1]) + 1; + depth = G_030004_TEX_DEPTH(texdw[1]) + 1; + surf.format = G_03001C_DATA_FORMAT(texdw[7]); + surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8; + surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx); + surf.nby = r600_fmt_get_nblocksy(surf.format, height); + surf.mode = G_030004_ARRAY_MODE(texdw[1]); + surf.tsplit = G_030018_TILE_SPLIT(texdw[6]); + surf.nbanks = G_03001C_NUM_BANKS(texdw[7]); + surf.bankw = G_03001C_BANK_WIDTH(texdw[7]); + surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]); + surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]); + surf.nsamples = 1; + toffset = texdw[2] << 8; + moffset = texdw[3] << 8; + + if (!r600_fmt_is_valid_texture(surf.format, p->family)) { + dev_warn(p->dev, "%s:%d texture invalid format %d\n", + __func__, __LINE__, surf.format); + return -EINVAL; + } + switch (dim) { + case V_030000_SQ_TEX_DIM_1D: + case V_030000_SQ_TEX_DIM_2D: + case V_030000_SQ_TEX_DIM_CUBEMAP: + case V_030000_SQ_TEX_DIM_1D_ARRAY: + case V_030000_SQ_TEX_DIM_2D_ARRAY: + depth = 1; + break; + case V_030000_SQ_TEX_DIM_2D_MSAA: + case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: + surf.nsamples = 1 << llevel; + llevel = 0; + depth = 1; + break; + case V_030000_SQ_TEX_DIM_3D: + break; + default: + dev_warn(p->dev, "%s:%d texture invalid dimension %d\n", + __func__, __LINE__, dim); + return -EINVAL; + } + + r = evergreen_surface_value_conv_check(p, &surf, "texture"); + if (r) { + return r; + } + + /* align height */ + evergreen_surface_check(p, &surf, NULL); + surf.nby = roundup(surf.nby, surf.halign); + + r = evergreen_surface_check(p, &surf, "texture"); + if (r) { + dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + __func__, __LINE__, texdw[0], texdw[1], texdw[4], + texdw[5], texdw[6], texdw[7]); + return r; + } + + /* check texture size */ + if (toffset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n", + __func__, __LINE__, toffset, surf.base_align); + return -EINVAL; + } + if (moffset & (surf.base_align - 1)) { + dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", + __func__, __LINE__, moffset, surf.base_align); + return -EINVAL; + } + if (dim == SQ_TEX_DIM_3D) { + toffset += surf.layer_size * depth; + } else { + toffset += surf.layer_size * mslice; + } + if (toffset > radeon_bo_size(texture)) { + dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, " + "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n", + __func__, __LINE__, surf.layer_size, + (unsigned long)texdw[2] << 8, mslice, + depth, radeon_bo_size(texture), + surf.nbx, surf.nby); + return -EINVAL; + } + + if (!mipmap) { + if (llevel) { + dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n", + __func__, __LINE__); + return -EINVAL; + } else { + return 0; /* everything's ok */ + } + } + + /* check mipmap size */ + for (i = 1; i <= llevel; i++) { + unsigned w, h, d; + + w = r600_mip_minify(width, i); + h = r600_mip_minify(height, i); + d = r600_mip_minify(depth, i); + surf.nbx = r600_fmt_get_nblocksx(surf.format, w); + surf.nby = r600_fmt_get_nblocksy(surf.format, h); + + switch (surf.mode) { + case ARRAY_2D_TILED_THIN1: + if (surf.nbx < surf.palign || surf.nby < surf.halign) { + surf.mode = ARRAY_1D_TILED_THIN1; + } + /* recompute alignment */ + evergreen_surface_check(p, &surf, NULL); + break; + case ARRAY_LINEAR_GENERAL: + case ARRAY_LINEAR_ALIGNED: + case ARRAY_1D_TILED_THIN1: + break; + default: + dev_warn(p->dev, "%s:%d invalid array mode %d\n", + __func__, __LINE__, surf.mode); + return -EINVAL; + } + surf.nbx = roundup(surf.nbx, surf.palign); + surf.nby = roundup(surf.nby, surf.halign); + + r = evergreen_surface_check(p, &surf, "mipmap"); + if (r) { + return r; + } + + if (dim == SQ_TEX_DIM_3D) { + moffset += surf.layer_size * d; + } else { + moffset += surf.layer_size * mslice; + } + if (moffset > radeon_bo_size(mipmap)) { + dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, " + "offset %ld, coffset %ld, max layer %d, depth %d, " + "bo size %ld) level0 (%d %d %d)\n", + __func__, __LINE__, i, surf.layer_size, + (unsigned long)texdw[3] << 8, moffset, mslice, + d, radeon_bo_size(mipmap), + width, height, depth); + dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", + __func__, __LINE__, surf.nbx, surf.nby, + surf.mode, surf.bpe, surf.nsamples, + surf.bankw, surf.bankh, + surf.tsplit, surf.mtilea); + return -EINVAL; + } + } + + return 0; +} + +static int evergreen_cs_track_check(struct radeon_cs_parser *p) +{ + struct evergreen_cs_track *track = p->track; + unsigned tmp, i; + int r; + unsigned buffer_mask = 0; + + /* check streamout */ + if (track->streamout_dirty && track->vgt_strmout_config) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_config & (1 << i)) { + buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf; + } + } + + for (i = 0; i < 4; i++) { + if (buffer_mask & (1 << i)) { + if (track->vgt_strmout_bo[i]) { + u64 offset = (u64)track->vgt_strmout_bo_offset[i] + + (u64)track->vgt_strmout_size[i]; + if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { + DRM_ERROR("streamout %d bo too small: 0x%jx, 0x%lx\n", + i, (uintmax_t)offset, + radeon_bo_size(track->vgt_strmout_bo[i])); + return -EINVAL; + } + } else { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } + track->streamout_dirty = false; + } + + if (track->sx_misc_kill_all_prims) + return 0; + + /* check that we have a cb for each enabled target + */ + if (track->cb_dirty) { + tmp = track->cb_target_mask; + for (i = 0; i < 8; i++) { + if ((tmp >> (i * 4)) & 0xF) { + /* at least one component is enabled */ + if (track->cb_color_bo[i] == NULL) { + dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", + __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); + return -EINVAL; + } + /* check cb */ + r = evergreen_cs_track_validate_cb(p, i); + if (r) { + return r; + } + } + } + track->cb_dirty = false; + } + + if (track->db_dirty) { + /* Check stencil buffer */ + if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && + G_028800_STENCIL_ENABLE(track->db_depth_control)) { + r = evergreen_cs_track_validate_stencil(p); + if (r) + return r; + } + /* Check depth buffer */ + if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && + G_028800_Z_ENABLE(track->db_depth_control)) { + r = evergreen_cs_track_validate_depth(p); + if (r) + return r; + } + track->db_dirty = false; + } + + return 0; +} + +/** + * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet + * @parser: parser structure holding parsing context. + * @pkt: where to store packet informations + * + * Assume that chunk_ib_index is properly set. Will return -EINVAL + * if packet is bigger than remaining ib size. or if packets is unknown. + **/ +static int evergreen_cs_packet_parse(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx) +{ + struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; + uint32_t header; + + if (idx >= ib_chunk->length_dw) { + DRM_ERROR("Can not parse packet at %d after CS end %d !\n", + idx, ib_chunk->length_dw); + return -EINVAL; + } + header = radeon_get_ib_value(p, idx); + pkt->idx = idx; + pkt->type = CP_PACKET_GET_TYPE(header); + pkt->count = CP_PACKET_GET_COUNT(header); + pkt->one_reg_wr = 0; + switch (pkt->type) { + case PACKET_TYPE0: + pkt->reg = CP_PACKET0_GET_REG(header); + break; + case PACKET_TYPE3: + pkt->opcode = CP_PACKET3_GET_OPCODE(header); + break; + case PACKET_TYPE2: + pkt->count = -1; + break; + default: + DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); + return -EINVAL; + } + if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { + DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", + pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); + return -EINVAL; + } + return 0; +} + +/** + * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3 + * @parser: parser structure holding parsing context. + * @data: pointer to relocation data + * @offset_start: starting offset + * @offset_mask: offset mask (to align start offset on) + * @reloc: reloc informations + * + * Check next packet is relocation packet3, do bo validation and compute + * GPU offset using the provided start. + **/ +static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc) +{ + struct radeon_cs_chunk *relocs_chunk; + struct radeon_cs_packet p3reloc; + unsigned idx; + int r; + + if (p->chunk_relocs_idx == -1) { + DRM_ERROR("No relocation chunk !\n"); + return -EINVAL; + } + *cs_reloc = NULL; + relocs_chunk = &p->chunks[p->chunk_relocs_idx]; + r = evergreen_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return r; + } + p->idx += p3reloc.count + 2; + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + DRM_ERROR("No packet3 for relocation for packet at %d.\n", + p3reloc.idx); + return -EINVAL; + } + idx = radeon_get_ib_value(p, p3reloc.idx + 1); + if (idx >= relocs_chunk->length_dw) { + DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", + idx, relocs_chunk->length_dw); + return -EINVAL; + } + /* FIXME: we assume reloc size is 4 dwords */ + *cs_reloc = p->relocs_ptr[(idx / 4)]; + return 0; +} + +/** + * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP + * @p: structure holding the parser context. + * + * Check if the next packet is a relocation packet3. + **/ +static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet p3reloc; + int r; + + r = evergreen_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return false; + } + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + return false; + } + return true; +} + +/** + * evergreen_cs_packet_next_vline() - parse userspace VLINE packet + * @parser: parser structure holding parsing context. + * + * Userspace sends a special sequence for VLINE waits. + * PACKET0 - VLINE_START_END + value + * PACKET3 - WAIT_REG_MEM poll vline status reg + * RELOC (P3) - crtc_id in reloc. + * + * This function parses this and relocates the VLINE START END + * and WAIT_REG_MEM packets to the correct crtc. + * It also detects a switched off crtc and nulls out the + * wait in that case. + */ +static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p) +{ + struct drm_mode_object *obj; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + struct radeon_cs_packet p3reloc, wait_reg_mem; + int crtc_id; + int r; + uint32_t header, h_idx, reg, wait_reg_mem_info; + volatile uint32_t *ib; + + ib = p->ib.ptr; + + /* parse the WAIT_REG_MEM */ + r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx); + if (r) + return r; + + /* check its a WAIT_REG_MEM */ + if (wait_reg_mem.type != PACKET_TYPE3 || + wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) { + DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n"); + return -EINVAL; + } + + wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1); + /* bit 4 is reg (0) or mem (1) */ + if (wait_reg_mem_info & 0x10) { + DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n"); + return -EINVAL; + } + /* waiting for value to be equal */ + if ((wait_reg_mem_info & 0x7) != 0x3) { + DRM_ERROR("vline WAIT_REG_MEM function not equal\n"); + return -EINVAL; + } + if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) { + DRM_ERROR("vline WAIT_REG_MEM bad reg\n"); + return -EINVAL; + } + + if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) { + DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); + return -EINVAL; + } + + /* jump over the NOP */ + r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2); + if (r) + return r; + + h_idx = p->idx - 2; + p->idx += wait_reg_mem.count + 2; + p->idx += p3reloc.count + 2; + + header = radeon_get_ib_value(p, h_idx); + crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1); + reg = CP_PACKET0_GET_REG(header); + obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_ERROR("cannot find crtc %d\n", crtc_id); + return -EINVAL; + } + crtc = obj_to_crtc(obj); + radeon_crtc = to_radeon_crtc(crtc); + crtc_id = radeon_crtc->crtc_id; + + if (!crtc->enabled) { + /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */ + ib[h_idx + 2] = PACKET2(0); + ib[h_idx + 3] = PACKET2(0); + ib[h_idx + 4] = PACKET2(0); + ib[h_idx + 5] = PACKET2(0); + ib[h_idx + 6] = PACKET2(0); + ib[h_idx + 7] = PACKET2(0); + ib[h_idx + 8] = PACKET2(0); + } else { + switch (reg) { + case EVERGREEN_VLINE_START_END: + header &= ~R600_CP_PACKET0_REG_MASK; + header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2; + ib[h_idx] = header; + ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2; + break; + default: + DRM_ERROR("unknown crtc reloc\n"); + return -EINVAL; + } + } + return 0; +} + +static int evergreen_packet0_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg) +{ + int r; + + switch (reg) { + case EVERGREEN_VLINE_START_END: + r = evergreen_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + return r; + } + break; + default: + DRM_ERROR("Forbidden register 0x%04X in cs at %d\n", + reg, idx); + return -EINVAL; + } + return 0; +} + +static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + unsigned reg, i; + unsigned idx; + int r; + + idx = pkt->idx + 1; + reg = pkt->reg; + for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { + r = evergreen_packet0_check(p, pkt, idx, reg); + if (r) { + return r; + } + } + return 0; +} + +/** + * evergreen_cs_check_reg() - check if register is authorized or not + * @parser: parser structure holding parsing context + * @reg: register we are testing + * @idx: index into the cs buffer + * + * This function will test against evergreen_reg_safe_bm and return 0 + * if register is safe. If register is not flag as safe this function + * will test it against a list of register needind special handling. + */ +static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; + struct radeon_cs_reloc *reloc; + u32 last_reg; + u32 m, i, tmp, *ib; + int r; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = DRM_ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = DRM_ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return 0; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return 0; + } + ib = p->ib.ptr; + switch (reg) { + /* force following reg to 0 in an attempt to disable out buffer + * which will need us to better understand how it works to perform + * security check on it (Jerome) + */ + case SQ_ESGS_RING_SIZE: + case SQ_GSVS_RING_SIZE: + case SQ_ESTMP_RING_SIZE: + case SQ_GSTMP_RING_SIZE: + case SQ_HSTMP_RING_SIZE: + case SQ_LSTMP_RING_SIZE: + case SQ_PSTMP_RING_SIZE: + case SQ_VSTMP_RING_SIZE: + case SQ_ESGS_RING_ITEMSIZE: + case SQ_ESTMP_RING_ITEMSIZE: + case SQ_GSTMP_RING_ITEMSIZE: + case SQ_GSVS_RING_ITEMSIZE: + case SQ_GS_VERT_ITEMSIZE: + case SQ_GS_VERT_ITEMSIZE_1: + case SQ_GS_VERT_ITEMSIZE_2: + case SQ_GS_VERT_ITEMSIZE_3: + case SQ_GSVS_RING_OFFSET_1: + case SQ_GSVS_RING_OFFSET_2: + case SQ_GSVS_RING_OFFSET_3: + case SQ_HSTMP_RING_ITEMSIZE: + case SQ_LSTMP_RING_ITEMSIZE: + case SQ_PSTMP_RING_ITEMSIZE: + case SQ_VSTMP_RING_ITEMSIZE: + case VGT_TF_RING_SIZE: + /* get value to populate the IB don't remove */ + /*tmp =radeon_get_ib_value(p, idx); + ib[idx] = 0;*/ + break; + case SQ_ESGS_RING_BASE: + case SQ_GSVS_RING_BASE: + case SQ_ESTMP_RING_BASE: + case SQ_GSTMP_RING_BASE: + case SQ_HSTMP_RING_BASE: + case SQ_LSTMP_RING_BASE: + case SQ_PSTMP_RING_BASE: + case SQ_VSTMP_RING_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case DB_DEPTH_CONTROL: + track->db_depth_control = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case CAYMAN_DB_EQAA: + if (p->rdev->family < CHIP_CAYMAN) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + break; + case CAYMAN_DB_DEPTH_INFO: + if (p->rdev->family < CHIP_CAYMAN) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + break; + case DB_Z_INFO: + track->db_z_info = radeon_get_ib_value(p, idx); + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] &= ~Z_ARRAY_MODE(0xf); + track->db_z_info &= ~Z_ARRAY_MODE(0xf); + ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + unsigned bankw, bankh, mtaspect, tile_split; + + evergreen_tiling_fields(reloc->lobj.tiling_flags, + &bankw, &bankh, &mtaspect, + &tile_split); + ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + ib[idx] |= DB_TILE_SPLIT(tile_split) | + DB_BANK_WIDTH(bankw) | + DB_BANK_HEIGHT(bankh) | + DB_MACRO_TILE_ASPECT(mtaspect); + } + } + track->db_dirty = true; + break; + case DB_STENCIL_INFO: + track->db_s_info = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case DB_DEPTH_VIEW: + track->db_depth_view = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case DB_DEPTH_SIZE: + track->db_depth_size = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case R_02805C_DB_DEPTH_SLICE: + track->db_depth_slice = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case DB_Z_READ_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->db_z_read_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_z_read_bo = reloc->robj; + track->db_dirty = true; + break; + case DB_Z_WRITE_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->db_z_write_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_z_write_bo = reloc->robj; + track->db_dirty = true; + break; + case DB_STENCIL_READ_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->db_s_read_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_s_read_bo = reloc->robj; + track->db_dirty = true; + break; + case DB_STENCIL_WRITE_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->db_s_write_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_s_write_bo = reloc->robj; + track->db_dirty = true; + break; + case VGT_STRMOUT_CONFIG: + track->vgt_strmout_config = radeon_get_ib_value(p, idx); + track->streamout_dirty = true; + break; + case VGT_STRMOUT_BUFFER_CONFIG: + track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); + track->streamout_dirty = true; + break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->streamout_dirty = true; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + track->streamout_dirty = true; + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + case CB_TARGET_MASK: + track->cb_target_mask = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case CB_SHADER_MASK: + track->cb_shader_mask = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case PA_SC_AA_CONFIG: + if (p->rdev->family >= CHIP_CAYMAN) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; + track->nsamples = 1 << tmp; + break; + case CAYMAN_PA_SC_AA_CONFIG: + if (p->rdev->family < CHIP_CAYMAN) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; + track->nsamples = 1 << tmp; + break; + case CB_COLOR0_VIEW: + case CB_COLOR1_VIEW: + case CB_COLOR2_VIEW: + case CB_COLOR3_VIEW: + case CB_COLOR4_VIEW: + case CB_COLOR5_VIEW: + case CB_COLOR6_VIEW: + case CB_COLOR7_VIEW: + tmp = (reg - CB_COLOR0_VIEW) / 0x3c; + track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case CB_COLOR8_VIEW: + case CB_COLOR9_VIEW: + case CB_COLOR10_VIEW: + case CB_COLOR11_VIEW: + tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8; + track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case CB_COLOR0_INFO: + case CB_COLOR1_INFO: + case CB_COLOR2_INFO: + case CB_COLOR3_INFO: + case CB_COLOR4_INFO: + case CB_COLOR5_INFO: + case CB_COLOR6_INFO: + case CB_COLOR7_INFO: + tmp = (reg - CB_COLOR0_INFO) / 0x3c; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + } + track->cb_dirty = true; + break; + case CB_COLOR8_INFO: + case CB_COLOR9_INFO: + case CB_COLOR10_INFO: + case CB_COLOR11_INFO: + tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + } + track->cb_dirty = true; + break; + case CB_COLOR0_PITCH: + case CB_COLOR1_PITCH: + case CB_COLOR2_PITCH: + case CB_COLOR3_PITCH: + case CB_COLOR4_PITCH: + case CB_COLOR5_PITCH: + case CB_COLOR6_PITCH: + case CB_COLOR7_PITCH: + tmp = (reg - CB_COLOR0_PITCH) / 0x3c; + track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case CB_COLOR8_PITCH: + case CB_COLOR9_PITCH: + case CB_COLOR10_PITCH: + case CB_COLOR11_PITCH: + tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8; + track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case CB_COLOR0_SLICE: + case CB_COLOR1_SLICE: + case CB_COLOR2_SLICE: + case CB_COLOR3_SLICE: + case CB_COLOR4_SLICE: + case CB_COLOR5_SLICE: + case CB_COLOR6_SLICE: + case CB_COLOR7_SLICE: + tmp = (reg - CB_COLOR0_SLICE) / 0x3c; + track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; + track->cb_dirty = true; + break; + case CB_COLOR8_SLICE: + case CB_COLOR9_SLICE: + case CB_COLOR10_SLICE: + case CB_COLOR11_SLICE: + tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; + track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; + track->cb_dirty = true; + break; + case CB_COLOR0_ATTRIB: + case CB_COLOR1_ATTRIB: + case CB_COLOR2_ATTRIB: + case CB_COLOR3_ATTRIB: + case CB_COLOR4_ATTRIB: + case CB_COLOR5_ATTRIB: + case CB_COLOR6_ATTRIB: + case CB_COLOR7_ATTRIB: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + unsigned bankw, bankh, mtaspect, tile_split; + + evergreen_tiling_fields(reloc->lobj.tiling_flags, + &bankw, &bankh, &mtaspect, + &tile_split); + ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + ib[idx] |= CB_TILE_SPLIT(tile_split) | + CB_BANK_WIDTH(bankw) | + CB_BANK_HEIGHT(bankh) | + CB_MACRO_TILE_ASPECT(mtaspect); + } + } + tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c); + track->cb_color_attrib[tmp] = ib[idx]; + track->cb_dirty = true; + break; + case CB_COLOR8_ATTRIB: + case CB_COLOR9_ATTRIB: + case CB_COLOR10_ATTRIB: + case CB_COLOR11_ATTRIB: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + unsigned bankw, bankh, mtaspect, tile_split; + + evergreen_tiling_fields(reloc->lobj.tiling_flags, + &bankw, &bankh, &mtaspect, + &tile_split); + ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + ib[idx] |= CB_TILE_SPLIT(tile_split) | + CB_BANK_WIDTH(bankw) | + CB_BANK_HEIGHT(bankh) | + CB_MACRO_TILE_ASPECT(mtaspect); + } + } + tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8; + track->cb_color_attrib[tmp] = ib[idx]; + track->cb_dirty = true; + break; + case CB_COLOR0_FMASK: + case CB_COLOR1_FMASK: + case CB_COLOR2_FMASK: + case CB_COLOR3_FMASK: + case CB_COLOR4_FMASK: + case CB_COLOR5_FMASK: + case CB_COLOR6_FMASK: + case CB_COLOR7_FMASK: + tmp = (reg - CB_COLOR0_FMASK) / 0x3c; + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->cb_color_fmask_bo[tmp] = reloc->robj; + break; + case CB_COLOR0_CMASK: + case CB_COLOR1_CMASK: + case CB_COLOR2_CMASK: + case CB_COLOR3_CMASK: + case CB_COLOR4_CMASK: + case CB_COLOR5_CMASK: + case CB_COLOR6_CMASK: + case CB_COLOR7_CMASK: + tmp = (reg - CB_COLOR0_CMASK) / 0x3c; + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->cb_color_cmask_bo[tmp] = reloc->robj; + break; + case CB_COLOR0_FMASK_SLICE: + case CB_COLOR1_FMASK_SLICE: + case CB_COLOR2_FMASK_SLICE: + case CB_COLOR3_FMASK_SLICE: + case CB_COLOR4_FMASK_SLICE: + case CB_COLOR5_FMASK_SLICE: + case CB_COLOR6_FMASK_SLICE: + case CB_COLOR7_FMASK_SLICE: + tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c; + track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx); + break; + case CB_COLOR0_CMASK_SLICE: + case CB_COLOR1_CMASK_SLICE: + case CB_COLOR2_CMASK_SLICE: + case CB_COLOR3_CMASK_SLICE: + case CB_COLOR4_CMASK_SLICE: + case CB_COLOR5_CMASK_SLICE: + case CB_COLOR6_CMASK_SLICE: + case CB_COLOR7_CMASK_SLICE: + tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c; + track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx); + break; + case CB_COLOR0_BASE: + case CB_COLOR1_BASE: + case CB_COLOR2_BASE: + case CB_COLOR3_BASE: + case CB_COLOR4_BASE: + case CB_COLOR5_BASE: + case CB_COLOR6_BASE: + case CB_COLOR7_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - CB_COLOR0_BASE) / 0x3c; + track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->cb_color_bo[tmp] = reloc->robj; + track->cb_dirty = true; + break; + case CB_COLOR8_BASE: + case CB_COLOR9_BASE: + case CB_COLOR10_BASE: + case CB_COLOR11_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8; + track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->cb_color_bo[tmp] = reloc->robj; + track->cb_dirty = true; + break; + case DB_HTILE_DATA_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->htile_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->htile_bo = reloc->robj; + track->db_dirty = true; + break; + case DB_HTILE_SURFACE: + /* 8x8 only */ + track->htile_surface = radeon_get_ib_value(p, idx); + /* force 8x8 htile width and height */ + ib[idx] |= 3; + track->db_dirty = true; + break; + case CB_IMMED0_BASE: + case CB_IMMED1_BASE: + case CB_IMMED2_BASE: + case CB_IMMED3_BASE: + case CB_IMMED4_BASE: + case CB_IMMED5_BASE: + case CB_IMMED6_BASE: + case CB_IMMED7_BASE: + case CB_IMMED8_BASE: + case CB_IMMED9_BASE: + case CB_IMMED10_BASE: + case CB_IMMED11_BASE: + case SQ_PGM_START_FS: + case SQ_PGM_START_ES: + case SQ_PGM_START_VS: + case SQ_PGM_START_GS: + case SQ_PGM_START_PS: + case SQ_PGM_START_HS: + case SQ_PGM_START_LS: + case SQ_CONST_MEM_BASE: + case SQ_ALU_CONST_CACHE_GS_0: + case SQ_ALU_CONST_CACHE_GS_1: + case SQ_ALU_CONST_CACHE_GS_2: + case SQ_ALU_CONST_CACHE_GS_3: + case SQ_ALU_CONST_CACHE_GS_4: + case SQ_ALU_CONST_CACHE_GS_5: + case SQ_ALU_CONST_CACHE_GS_6: + case SQ_ALU_CONST_CACHE_GS_7: + case SQ_ALU_CONST_CACHE_GS_8: + case SQ_ALU_CONST_CACHE_GS_9: + case SQ_ALU_CONST_CACHE_GS_10: + case SQ_ALU_CONST_CACHE_GS_11: + case SQ_ALU_CONST_CACHE_GS_12: + case SQ_ALU_CONST_CACHE_GS_13: + case SQ_ALU_CONST_CACHE_GS_14: + case SQ_ALU_CONST_CACHE_GS_15: + case SQ_ALU_CONST_CACHE_PS_0: + case SQ_ALU_CONST_CACHE_PS_1: + case SQ_ALU_CONST_CACHE_PS_2: + case SQ_ALU_CONST_CACHE_PS_3: + case SQ_ALU_CONST_CACHE_PS_4: + case SQ_ALU_CONST_CACHE_PS_5: + case SQ_ALU_CONST_CACHE_PS_6: + case SQ_ALU_CONST_CACHE_PS_7: + case SQ_ALU_CONST_CACHE_PS_8: + case SQ_ALU_CONST_CACHE_PS_9: + case SQ_ALU_CONST_CACHE_PS_10: + case SQ_ALU_CONST_CACHE_PS_11: + case SQ_ALU_CONST_CACHE_PS_12: + case SQ_ALU_CONST_CACHE_PS_13: + case SQ_ALU_CONST_CACHE_PS_14: + case SQ_ALU_CONST_CACHE_PS_15: + case SQ_ALU_CONST_CACHE_VS_0: + case SQ_ALU_CONST_CACHE_VS_1: + case SQ_ALU_CONST_CACHE_VS_2: + case SQ_ALU_CONST_CACHE_VS_3: + case SQ_ALU_CONST_CACHE_VS_4: + case SQ_ALU_CONST_CACHE_VS_5: + case SQ_ALU_CONST_CACHE_VS_6: + case SQ_ALU_CONST_CACHE_VS_7: + case SQ_ALU_CONST_CACHE_VS_8: + case SQ_ALU_CONST_CACHE_VS_9: + case SQ_ALU_CONST_CACHE_VS_10: + case SQ_ALU_CONST_CACHE_VS_11: + case SQ_ALU_CONST_CACHE_VS_12: + case SQ_ALU_CONST_CACHE_VS_13: + case SQ_ALU_CONST_CACHE_VS_14: + case SQ_ALU_CONST_CACHE_VS_15: + case SQ_ALU_CONST_CACHE_HS_0: + case SQ_ALU_CONST_CACHE_HS_1: + case SQ_ALU_CONST_CACHE_HS_2: + case SQ_ALU_CONST_CACHE_HS_3: + case SQ_ALU_CONST_CACHE_HS_4: + case SQ_ALU_CONST_CACHE_HS_5: + case SQ_ALU_CONST_CACHE_HS_6: + case SQ_ALU_CONST_CACHE_HS_7: + case SQ_ALU_CONST_CACHE_HS_8: + case SQ_ALU_CONST_CACHE_HS_9: + case SQ_ALU_CONST_CACHE_HS_10: + case SQ_ALU_CONST_CACHE_HS_11: + case SQ_ALU_CONST_CACHE_HS_12: + case SQ_ALU_CONST_CACHE_HS_13: + case SQ_ALU_CONST_CACHE_HS_14: + case SQ_ALU_CONST_CACHE_HS_15: + case SQ_ALU_CONST_CACHE_LS_0: + case SQ_ALU_CONST_CACHE_LS_1: + case SQ_ALU_CONST_CACHE_LS_2: + case SQ_ALU_CONST_CACHE_LS_3: + case SQ_ALU_CONST_CACHE_LS_4: + case SQ_ALU_CONST_CACHE_LS_5: + case SQ_ALU_CONST_CACHE_LS_6: + case SQ_ALU_CONST_CACHE_LS_7: + case SQ_ALU_CONST_CACHE_LS_8: + case SQ_ALU_CONST_CACHE_LS_9: + case SQ_ALU_CONST_CACHE_LS_10: + case SQ_ALU_CONST_CACHE_LS_11: + case SQ_ALU_CONST_CACHE_LS_12: + case SQ_ALU_CONST_CACHE_LS_13: + case SQ_ALU_CONST_CACHE_LS_14: + case SQ_ALU_CONST_CACHE_LS_15: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case SX_MEMORY_EXPORT_BASE: + if (p->rdev->family >= CHIP_CAYMAN) { + dev_warn(p->dev, "bad SET_CONFIG_REG " + "0x%04X\n", reg); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONFIG_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case CAYMAN_SX_SCATTER_EXPORT_BASE: + if (p->rdev->family < CHIP_CAYMAN) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case SX_MISC: + track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; + break; + default: + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; + } + return 0; +} + +static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 last_reg, m, i; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = DRM_ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = DRM_ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return true; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return true; + } + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + +static int evergreen_packet3_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + struct radeon_cs_reloc *reloc; + struct evergreen_cs_track *track; + volatile u32 *ib; + unsigned idx; + unsigned i; + unsigned start_reg, end_reg, reg; + int r; + u32 idx_value; + + track = (struct evergreen_cs_track *)p->track; + ib = p->ib.ptr; + idx = pkt->idx + 1; + idx_value = radeon_get_ib_value(p, idx); + + switch (pkt->opcode) { + case PACKET3_SET_PREDICATION: + { + int pred_op; + int tmp; + uint64_t offset; + + if (pkt->count != 1) { + DRM_ERROR("bad SET PREDICATION\n"); + return -EINVAL; + } + + tmp = radeon_get_ib_value(p, idx + 1); + pred_op = (tmp >> 16) & 0x7; + + /* for the clear predicate operation */ + if (pred_op == 0) + return 0; + + if (pred_op > 2) { + DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); + return -EINVAL; + } + + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET PREDICATION\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (idx_value & 0xfffffff0) + + ((u64)(tmp & 0xff) << 32); + + ib[idx + 0] = offset; + ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); + } + break; + case PACKET3_CONTEXT_CONTROL: + if (pkt->count != 1) { + DRM_ERROR("bad CONTEXT_CONTROL\n"); + return -EINVAL; + } + break; + case PACKET3_INDEX_TYPE: + case PACKET3_NUM_INSTANCES: + case PACKET3_CLEAR_STATE: + if (pkt->count) { + DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); + return -EINVAL; + } + break; + case CAYMAN_PACKET3_DEALLOC_STATE: + if (p->rdev->family < CHIP_CAYMAN) { + DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); + return -EINVAL; + } + if (pkt->count) { + DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); + return -EINVAL; + } + break; + case PACKET3_INDEX_BASE: + { + uint64_t offset; + + if (pkt->count != 1) { + DRM_ERROR("bad INDEX_BASE\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad INDEX_BASE\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + idx_value + + ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); + + ib[idx+0] = offset; + ib[idx+1] = upper_32_bits(offset) & 0xff; + + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + } + case PACKET3_DRAW_INDEX: + { + uint64_t offset; + if (pkt->count != 3) { + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + idx_value + + ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); + + ib[idx+0] = offset; + ib[idx+1] = upper_32_bits(offset) & 0xff; + + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + } + case PACKET3_DRAW_INDEX_2: + { + uint64_t offset; + + if (pkt->count != 4) { + DRM_ERROR("bad DRAW_INDEX_2\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad DRAW_INDEX_2\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + radeon_get_ib_value(p, idx+1) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = offset; + ib[idx+2] = upper_32_bits(offset) & 0xff; + + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + } + case PACKET3_DRAW_INDEX_AUTO: + if (pkt->count != 1) { + DRM_ERROR("bad DRAW_INDEX_AUTO\n"); + return -EINVAL; + } + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); + return r; + } + break; + case PACKET3_DRAW_INDEX_MULTI_AUTO: + if (pkt->count != 2) { + DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n"); + return -EINVAL; + } + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); + return r; + } + break; + case PACKET3_DRAW_INDEX_IMMD: + if (pkt->count < 2) { + DRM_ERROR("bad DRAW_INDEX_IMMD\n"); + return -EINVAL; + } + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + case PACKET3_DRAW_INDEX_OFFSET: + if (pkt->count != 2) { + DRM_ERROR("bad DRAW_INDEX_OFFSET\n"); + return -EINVAL; + } + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + case PACKET3_DRAW_INDEX_OFFSET_2: + if (pkt->count != 3) { + DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n"); + return -EINVAL; + } + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + case PACKET3_DISPATCH_DIRECT: + if (pkt->count != 3) { + DRM_ERROR("bad DISPATCH_DIRECT\n"); + return -EINVAL; + } + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); + return r; + } + break; + case PACKET3_DISPATCH_INDIRECT: + if (pkt->count != 1) { + DRM_ERROR("bad DISPATCH_INDIRECT\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad DISPATCH_INDIRECT\n"); + return -EINVAL; + } + ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + case PACKET3_WAIT_REG_MEM: + if (pkt->count != 5) { + DRM_ERROR("bad WAIT_REG_MEM\n"); + return -EINVAL; + } + /* bit 4 is reg (0) or mem (1) */ + if (idx_value & 0x10) { + uint64_t offset; + + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad WAIT_REG_MEM\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc); + ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_CP_DMA: + { + u32 command, size, info; + u64 offset, tmp; + if (pkt->count != 4) { + DRM_ERROR("bad CP DMA\n"); + return -EINVAL; + } + command = radeon_get_ib_value(p, idx+4); + size = command & 0x1fffff; + info = radeon_get_ib_value(p, idx+1); + if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ + (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ + ((((info & 0x00300000) >> 20) == 0) && + (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ + ((((info & 0x60000000) >> 29) == 0) && + (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ + /* non mem to mem copies requires dw aligned count */ + if (size % 4) { + DRM_ERROR("CP DMA command requires dw count alignment\n"); + return -EINVAL; + } + } + if (command & PACKET3_CP_DMA_CMD_SAS) { + /* src address space is register */ + /* GDS is ok */ + if (((info & 0x60000000) >> 29) != 1) { + DRM_ERROR("CP DMA SAS not supported\n"); + return -EINVAL; + } + } else { + if (command & PACKET3_CP_DMA_CMD_SAIC) { + DRM_ERROR("CP DMA SAIC only supported for registers\n"); + return -EINVAL; + } + /* src address space is memory */ + if (((info & 0x60000000) >> 29) == 0) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad CP DMA SRC\n"); + return -EINVAL; + } + + tmp = radeon_get_ib_value(p, idx) + + ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); + + offset = reloc->lobj.gpu_offset + tmp; + + if ((tmp + size) > radeon_bo_size(reloc->robj)) { + dev_warn(p->dev, "CP DMA src buffer too small (%ju %lu)\n", + (uintmax_t)tmp + size, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + + ib[idx] = offset; + ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + } else if (((info & 0x60000000) >> 29) != 2) { + DRM_ERROR("bad CP DMA SRC_SEL\n"); + return -EINVAL; + } + } + if (command & PACKET3_CP_DMA_CMD_DAS) { + /* dst address space is register */ + /* GDS is ok */ + if (((info & 0x00300000) >> 20) != 1) { + DRM_ERROR("CP DMA DAS not supported\n"); + return -EINVAL; + } + } else { + /* dst address space is memory */ + if (command & PACKET3_CP_DMA_CMD_DAIC) { + DRM_ERROR("CP DMA DAIC only supported for registers\n"); + return -EINVAL; + } + if (((info & 0x00300000) >> 20) == 0) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad CP DMA DST\n"); + return -EINVAL; + } + + tmp = radeon_get_ib_value(p, idx+2) + + ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32); + + offset = reloc->lobj.gpu_offset + tmp; + + if ((tmp + size) > radeon_bo_size(reloc->robj)) { + dev_warn(p->dev, "CP DMA dst buffer too small (%ju %lu)\n", + (uintmax_t)tmp + size, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + + ib[idx+2] = offset; + ib[idx+3] = upper_32_bits(offset) & 0xff; + } else { + DRM_ERROR("bad CP DMA DST_SEL\n"); + return -EINVAL; + } + } + break; + } + case PACKET3_SURFACE_SYNC: + if (pkt->count != 3) { + DRM_ERROR("bad SURFACE_SYNC\n"); + return -EINVAL; + } + /* 0xffffffff/0x0 is flush all cache flag */ + if (radeon_get_ib_value(p, idx + 1) != 0xffffffff || + radeon_get_ib_value(p, idx + 2) != 0) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SURFACE_SYNC\n"); + return -EINVAL; + } + ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + break; + case PACKET3_EVENT_WRITE: + if (pkt->count != 2 && pkt->count != 0) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } + if (pkt->count) { + uint64_t offset; + + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = offset & 0xfffffff8; + ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_EVENT_WRITE_EOP: + { + uint64_t offset; + + if (pkt->count != 4) { + DRM_ERROR("bad EVENT_WRITE_EOP\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE_EOP\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = offset & 0xfffffffc; + ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + break; + } + case PACKET3_EVENT_WRITE_EOS: + { + uint64_t offset; + + if (pkt->count != 3) { + DRM_ERROR("bad EVENT_WRITE_EOS\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE_EOS\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = offset & 0xfffffffc; + ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + break; + } + case PACKET3_SET_CONFIG_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CONFIG_REG_START) || + (start_reg >= PACKET3_SET_CONFIG_REG_END) || + (end_reg >= PACKET3_SET_CONFIG_REG_END)) { + DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); + return -EINVAL; + } + for (i = 0; i < pkt->count; i++) { + reg = start_reg + (4 * i); + r = evergreen_cs_check_reg(p, reg, idx+1+i); + if (r) + return r; + } + break; + case PACKET3_SET_CONTEXT_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CONTEXT_REG_START) || + (start_reg >= PACKET3_SET_CONTEXT_REG_END) || + (end_reg >= PACKET3_SET_CONTEXT_REG_END)) { + DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n"); + return -EINVAL; + } + for (i = 0; i < pkt->count; i++) { + reg = start_reg + (4 * i); + r = evergreen_cs_check_reg(p, reg, idx+1+i); + if (r) + return r; + } + break; + case PACKET3_SET_RESOURCE: + if (pkt->count % 8) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_RESOURCE_START) || + (start_reg >= PACKET3_SET_RESOURCE_END) || + (end_reg >= PACKET3_SET_RESOURCE_END)) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + for (i = 0; i < (pkt->count / 8); i++) { + struct radeon_bo *texture, *mipmap; + u32 toffset, moffset; + u32 size, offset, mip_address, tex_dim; + + switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { + case SQ_TEX_VTX_VALID_TEXTURE: + /* tex base */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE (tex)\n"); + return -EINVAL; + } + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + ib[idx+1+(i*8)+1] |= + TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + unsigned bankw, bankh, mtaspect, tile_split; + + evergreen_tiling_fields(reloc->lobj.tiling_flags, + &bankw, &bankh, &mtaspect, + &tile_split); + ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split); + ib[idx+1+(i*8)+7] |= + TEX_BANK_WIDTH(bankw) | + TEX_BANK_HEIGHT(bankh) | + MACRO_TILE_ASPECT(mtaspect) | + TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + } + } + texture = reloc->robj; + toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + + /* tex mip base */ + tex_dim = ib[idx+1+(i*8)+0] & 0x7; + mip_address = ib[idx+1+(i*8)+3]; + + if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) && + !mip_address && + !evergreen_cs_packet_next_is_pkt3_nop(p)) { + /* MIP_ADDRESS should point to FMASK for an MSAA texture. + * It should be 0 if FMASK is disabled. */ + moffset = 0; + mipmap = NULL; + } else { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE (tex)\n"); + return -EINVAL; + } + moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + mipmap = reloc->robj; + } + + r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); + if (r) + return r; + ib[idx+1+(i*8)+2] += toffset; + ib[idx+1+(i*8)+3] += moffset; + break; + case SQ_TEX_VTX_VALID_BUFFER: + { + uint64_t offset64; + /* vtx base */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE (vtx)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1+(i*8)+0); + size = radeon_get_ib_value(p, idx+1+(i*8)+1); + if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { + /* force size to size of the buffer */ + dev_warn(p->dev, "vbo resource seems too big for the bo\n"); + ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset; + } + + offset64 = reloc->lobj.gpu_offset + offset; + ib[idx+1+(i*8)+0] = offset64; + ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | + (upper_32_bits(offset64) & 0xff); + break; + } + case SQ_TEX_VTX_INVALID_TEXTURE: + case SQ_TEX_VTX_INVALID_BUFFER: + default: + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + } + break; + case PACKET3_SET_ALU_CONST: + /* XXX fix me ALU const buffers only */ + break; + case PACKET3_SET_BOOL_CONST: + start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_BOOL_CONST_START) || + (start_reg >= PACKET3_SET_BOOL_CONST_END) || + (end_reg >= PACKET3_SET_BOOL_CONST_END)) { + DRM_ERROR("bad SET_BOOL_CONST\n"); + return -EINVAL; + } + break; + case PACKET3_SET_LOOP_CONST: + start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_LOOP_CONST_START) || + (start_reg >= PACKET3_SET_LOOP_CONST_END) || + (end_reg >= PACKET3_SET_LOOP_CONST_END)) { + DRM_ERROR("bad SET_LOOP_CONST\n"); + return -EINVAL; + } + break; + case PACKET3_SET_CTL_CONST: + start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CTL_CONST_START) || + (start_reg >= PACKET3_SET_CTL_CONST_END) || + (end_reg >= PACKET3_SET_CTL_CONST_END)) { + DRM_ERROR("bad SET_CTL_CONST\n"); + return -EINVAL; + } + break; + case PACKET3_SET_SAMPLER: + if (pkt->count % 3) { + DRM_ERROR("bad SET_SAMPLER\n"); + return -EINVAL; + } + start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_SAMPLER_START) || + (start_reg >= PACKET3_SET_SAMPLER_END) || + (end_reg >= PACKET3_SET_SAMPLER_END)) { + DRM_ERROR("bad SET_SAMPLER\n"); + return -EINVAL; + } + break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + u64 offset; + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+1] = offset; + ib[idx+2] = upper_32_bits(offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + u64 offset; + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+3] = offset; + ib[idx+4] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_MEM_WRITE: + { + u64 offset; + + if (pkt->count != 3) { + DRM_ERROR("bad MEM_WRITE (invalid count)\n"); + return -EINVAL; + } + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+0); + offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; + if (offset & 0x7) { + DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); + return -EINVAL; + } + if ((offset + 8) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad MEM_WRITE bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 8, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+0] = offset; + ib[idx+1] = upper_32_bits(offset) & 0xff; + break; + } + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+1] = offset; + ib[idx+2] = upper_32_bits(offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+3] = offset; + ib[idx+4] = upper_32_bits(offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; + case PACKET3_NOP: + break; + default: + DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +int evergreen_cs_parse(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet pkt; + struct evergreen_cs_track *track; + u32 tmp; + int r; + + if (p->track == NULL) { + /* initialize tracker, we are in kms */ + track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (track == NULL) + return -ENOMEM; + evergreen_cs_track_init(track); + if (p->rdev->family >= CHIP_CAYMAN) + tmp = p->rdev->config.cayman.tile_config; + else + tmp = p->rdev->config.evergreen.tile_config; + + switch (tmp & 0xf) { + case 0: + track->npipes = 1; + break; + case 1: + default: + track->npipes = 2; + break; + case 2: + track->npipes = 4; + break; + case 3: + track->npipes = 8; + break; + } + + switch ((tmp & 0xf0) >> 4) { + case 0: + track->nbanks = 4; + break; + case 1: + default: + track->nbanks = 8; + break; + case 2: + track->nbanks = 16; + break; + } + + switch ((tmp & 0xf00) >> 8) { + case 0: + track->group_size = 256; + break; + case 1: + default: + track->group_size = 512; + break; + } + + switch ((tmp & 0xf000) >> 12) { + case 0: + track->row_size = 1; + break; + case 1: + default: + track->row_size = 2; + break; + case 2: + track->row_size = 4; + break; + } + + p->track = track; + } + do { + r = evergreen_cs_packet_parse(p, &pkt, p->idx); + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + p->idx += pkt.count + 2; + switch (pkt.type) { + case PACKET_TYPE0: + r = evergreen_cs_parse_packet0(p, &pkt); + break; + case PACKET_TYPE2: + break; + case PACKET_TYPE3: + r = evergreen_packet3_check(p, &pkt); + break; + default: + DRM_ERROR("Unknown packet type %d !\n", pkt.type); + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return -EINVAL; + } + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); +#if 0 + for (r = 0; r < p->ib.length_dw; r++) { + DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]); + mdelay(1); + } +#endif + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return 0; +} + +/* + * DMA + */ + +#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28) +#define GET_DMA_COUNT(h) ((h) & 0x000fffff) +#define GET_DMA_T(h) (((h) & 0x00800000) >> 23) +#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26) +#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20) + +/** + * evergreen_dma_cs_parse() - parse the DMA IB + * @p: parser structure holding parsing context. + * + * Parses the DMA IB from the CS ioctl and updates + * the GPU addresses based on the reloc information and + * checks for errors. (Evergreen-Cayman) + * Returns 0 for success and an error on failure. + **/ +int evergreen_dma_cs_parse(struct radeon_cs_parser *p) +{ + struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; + struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc; + u32 header, cmd, count, tiled, new_cmd, misc; + volatile u32 *ib = p->ib.ptr; + u32 idx, idx_value; + u64 src_offset, dst_offset, dst2_offset; + int r; + + do { + if (p->idx >= ib_chunk->length_dw) { + DRM_ERROR("Can not parse packet at %d after CS end %d !\n", + p->idx, ib_chunk->length_dw); + return -EINVAL; + } + idx = p->idx; + header = radeon_get_ib_value(p, idx); + cmd = GET_DMA_CMD(header); + count = GET_DMA_COUNT(header); + tiled = GET_DMA_T(header); + new_cmd = GET_DMA_NEW(header); + misc = GET_DMA_MISC(header); + + switch (cmd) { + case DMA_PACKET_WRITE: + r = r600_dma_cs_next_reloc(p, &dst_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_WRITE\n"); + return -EINVAL; + } + if (tiled) { + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + p->idx += count + 7; + } else { + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + p->idx += count + 3; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA write buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset, radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + break; + case DMA_PACKET_COPY: + r = r600_dma_cs_next_reloc(p, &src_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_COPY\n"); + return -EINVAL; + } + r = r600_dma_cs_next_reloc(p, &dst_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_COPY\n"); + return -EINVAL; + } + if (tiled) { + idx_value = radeon_get_ib_value(p, idx + 2); + if (new_cmd) { + switch (misc) { + case 0: + /* L2T, frame to fields */ + if (idx_value & (1 << 31)) { + DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); + return -EINVAL; + } + r = r600_dma_cs_next_reloc(p, &dst2_reloc); + if (r) { + DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); + return -EINVAL; + } + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + dst2_offset = radeon_get_ib_value(p, idx+2); + dst2_offset <<= 8; + src_offset = radeon_get_ib_value(p, idx+8); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n", + (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); + ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 10; + break; + case 1: + /* L2T, T2L partial */ + if (p->family < CHIP_CAYMAN) { + DRM_ERROR("L2T, T2L Partial is cayman only !\n"); + return -EINVAL; + } + /* detile bit */ + if (idx_value & (1 << 31)) { + /* tiled src, linear dst */ + ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); + + ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + } else { + /* linear src, tiled dst */ + ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + } + p->idx += 12; + break; + case 3: + /* L2T, broadcast */ + if (idx_value & (1 << 31)) { + DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); + return -EINVAL; + } + r = r600_dma_cs_next_reloc(p, &dst2_reloc); + if (r) { + DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); + return -EINVAL; + } + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + dst2_offset = radeon_get_ib_value(p, idx+2); + dst2_offset <<= 8; + src_offset = radeon_get_ib_value(p, idx+8); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n", + (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); + ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 10; + break; + case 4: + /* L2T, T2L */ + /* detile bit */ + if (idx_value & (1 << 31)) { + /* tiled src, linear dst */ + src_offset = radeon_get_ib_value(p, idx+1); + src_offset <<= 8; + ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); + + dst_offset = radeon_get_ib_value(p, idx+7); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; + ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + } else { + /* linear src, tiled dst */ + src_offset = radeon_get_ib_value(p, idx+7); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; + ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + } + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + p->idx += 9; + break; + case 5: + /* T2T partial */ + if (p->family < CHIP_CAYMAN) { + DRM_ERROR("L2T, T2L Partial is cayman only !\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); + ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + p->idx += 13; + break; + case 7: + /* L2T, broadcast */ + if (idx_value & (1 << 31)) { + DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); + return -EINVAL; + } + r = r600_dma_cs_next_reloc(p, &dst2_reloc); + if (r) { + DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); + return -EINVAL; + } + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + dst2_offset = radeon_get_ib_value(p, idx+2); + dst2_offset <<= 8; + src_offset = radeon_get_ib_value(p, idx+8); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n", + (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); + ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 10; + break; + default: + DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); + return -EINVAL; + } + } else { + switch (misc) { + case 0: + /* detile bit */ + if (idx_value & (1 << 31)) { + /* tiled src, linear dst */ + src_offset = radeon_get_ib_value(p, idx+1); + src_offset <<= 8; + ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); + + dst_offset = radeon_get_ib_value(p, idx+7); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; + ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + } else { + /* linear src, tiled dst */ + src_offset = radeon_get_ib_value(p, idx+7); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; + ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + } + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + p->idx += 9; + break; + default: + DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); + return -EINVAL; + } + } + } else { + if (new_cmd) { + switch (misc) { + case 0: + /* L2L, byte */ + src_offset = radeon_get_ib_value(p, idx+2); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; + if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, byte src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + count, radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + count, radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 5; + break; + case 1: + /* L2L, partial */ + if (p->family < CHIP_CAYMAN) { + DRM_ERROR("L2L Partial is cayman only !\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + + p->idx += 9; + break; + case 4: + /* L2L, dw, broadcast */ + r = r600_dma_cs_next_reloc(p, &dst2_reloc); + if (r) { + DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); + return -EINVAL; + } + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + dst2_offset = radeon_get_ib_value(p, idx+2); + dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32; + src_offset = radeon_get_ib_value(p, idx+3); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%ju %lu)\n", + (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff; + ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 7; + break; + default: + DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); + return -EINVAL; + } + } else { + /* L2L, dw */ + src_offset = radeon_get_ib_value(p, idx+2); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, dw src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 5; + } + } + break; + case DMA_PACKET_CONSTANT_FILL: + r = r600_dma_cs_next_reloc(p, &dst_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); + return -EINVAL; + } + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA constant fill buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset, radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000; + p->idx += 4; + break; + case DMA_PACKET_NOP: + p->idx += 1; + break; + default: + DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); + return -EINVAL; + } + } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); +#if 0 + for (r = 0; r < p->ib->length_dw; r++) { + DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]); + mdelay(1); + } +#endif + return 0; +} + +/* vm parser */ +static bool evergreen_vm_reg_valid(u32 reg) +{ + /* context regs are fine */ + if (reg >= 0x28000) + return true; + + /* check config regs */ + switch (reg) { + case WAIT_UNTIL: + case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: + case CP_COHER_SIZE: + case VGT_VTX_VECT_EJECT_REG: + case VGT_CACHE_INVALIDATION: + case VGT_GS_VERTEX_REUSE: + case VGT_PRIMITIVE_TYPE: + case VGT_INDEX_TYPE: + case VGT_NUM_INDICES: + case VGT_NUM_INSTANCES: + case VGT_COMPUTE_DIM_X: + case VGT_COMPUTE_DIM_Y: + case VGT_COMPUTE_DIM_Z: + case VGT_COMPUTE_START_X: + case VGT_COMPUTE_START_Y: + case VGT_COMPUTE_START_Z: + case VGT_COMPUTE_INDEX: + case VGT_COMPUTE_THREAD_GROUP_SIZE: + case VGT_HS_OFFCHIP_PARAM: + case PA_CL_ENHANCE: + case PA_SU_LINE_STIPPLE_VALUE: + case PA_SC_LINE_STIPPLE_STATE: + case PA_SC_ENHANCE: + case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ: + case SQ_DYN_GPR_SIMD_LOCK_EN: + case SQ_CONFIG: + case SQ_GPR_RESOURCE_MGMT_1: + case SQ_GLOBAL_GPR_RESOURCE_MGMT_1: + case SQ_GLOBAL_GPR_RESOURCE_MGMT_2: + case SQ_CONST_MEM_BASE: + case SQ_STATIC_THREAD_MGMT_1: + case SQ_STATIC_THREAD_MGMT_2: + case SQ_STATIC_THREAD_MGMT_3: + case SPI_CONFIG_CNTL: + case SPI_CONFIG_CNTL_1: + case TA_CNTL_AUX: + case DB_DEBUG: + case DB_DEBUG2: + case DB_DEBUG3: + case DB_DEBUG4: + case DB_WATERMARKS: + case TD_PS_BORDER_COLOR_INDEX: + case TD_PS_BORDER_COLOR_RED: + case TD_PS_BORDER_COLOR_GREEN: + case TD_PS_BORDER_COLOR_BLUE: + case TD_PS_BORDER_COLOR_ALPHA: + case TD_VS_BORDER_COLOR_INDEX: + case TD_VS_BORDER_COLOR_RED: + case TD_VS_BORDER_COLOR_GREEN: + case TD_VS_BORDER_COLOR_BLUE: + case TD_VS_BORDER_COLOR_ALPHA: + case TD_GS_BORDER_COLOR_INDEX: + case TD_GS_BORDER_COLOR_RED: + case TD_GS_BORDER_COLOR_GREEN: + case TD_GS_BORDER_COLOR_BLUE: + case TD_GS_BORDER_COLOR_ALPHA: + case TD_HS_BORDER_COLOR_INDEX: + case TD_HS_BORDER_COLOR_RED: + case TD_HS_BORDER_COLOR_GREEN: + case TD_HS_BORDER_COLOR_BLUE: + case TD_HS_BORDER_COLOR_ALPHA: + case TD_LS_BORDER_COLOR_INDEX: + case TD_LS_BORDER_COLOR_RED: + case TD_LS_BORDER_COLOR_GREEN: + case TD_LS_BORDER_COLOR_BLUE: + case TD_LS_BORDER_COLOR_ALPHA: + case TD_CS_BORDER_COLOR_INDEX: + case TD_CS_BORDER_COLOR_RED: + case TD_CS_BORDER_COLOR_GREEN: + case TD_CS_BORDER_COLOR_BLUE: + case TD_CS_BORDER_COLOR_ALPHA: + case SQ_ESGS_RING_SIZE: + case SQ_GSVS_RING_SIZE: + case SQ_ESTMP_RING_SIZE: + case SQ_GSTMP_RING_SIZE: + case SQ_HSTMP_RING_SIZE: + case SQ_LSTMP_RING_SIZE: + case SQ_PSTMP_RING_SIZE: + case SQ_VSTMP_RING_SIZE: + case SQ_ESGS_RING_ITEMSIZE: + case SQ_ESTMP_RING_ITEMSIZE: + case SQ_GSTMP_RING_ITEMSIZE: + case SQ_GSVS_RING_ITEMSIZE: + case SQ_GS_VERT_ITEMSIZE: + case SQ_GS_VERT_ITEMSIZE_1: + case SQ_GS_VERT_ITEMSIZE_2: + case SQ_GS_VERT_ITEMSIZE_3: + case SQ_GSVS_RING_OFFSET_1: + case SQ_GSVS_RING_OFFSET_2: + case SQ_GSVS_RING_OFFSET_3: + case SQ_HSTMP_RING_ITEMSIZE: + case SQ_LSTMP_RING_ITEMSIZE: + case SQ_PSTMP_RING_ITEMSIZE: + case SQ_VSTMP_RING_ITEMSIZE: + case VGT_TF_RING_SIZE: + case SQ_ESGS_RING_BASE: + case SQ_GSVS_RING_BASE: + case SQ_ESTMP_RING_BASE: + case SQ_GSTMP_RING_BASE: + case SQ_HSTMP_RING_BASE: + case SQ_LSTMP_RING_BASE: + case SQ_PSTMP_RING_BASE: + case SQ_VSTMP_RING_BASE: + case CAYMAN_VGT_OFFCHIP_LDS_BASE: + case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: + return true; + default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); + return false; + } +} + +static int evergreen_vm_packet3_check(struct radeon_device *rdev, + u32 *ib, struct radeon_cs_packet *pkt) +{ + u32 idx = pkt->idx + 1; + u32 idx_value = ib[idx]; + u32 start_reg, end_reg, reg, i; + u32 command, info; + + switch (pkt->opcode) { + case PACKET3_NOP: + case PACKET3_SET_BASE: + case PACKET3_CLEAR_STATE: + case PACKET3_INDEX_BUFFER_SIZE: + case PACKET3_DISPATCH_DIRECT: + case PACKET3_DISPATCH_INDIRECT: + case PACKET3_MODE_CONTROL: + case PACKET3_SET_PREDICATION: + case PACKET3_COND_EXEC: + case PACKET3_PRED_EXEC: + case PACKET3_DRAW_INDIRECT: + case PACKET3_DRAW_INDEX_INDIRECT: + case PACKET3_INDEX_BASE: + case PACKET3_DRAW_INDEX_2: + case PACKET3_CONTEXT_CONTROL: + case PACKET3_DRAW_INDEX_OFFSET: + case PACKET3_INDEX_TYPE: + case PACKET3_DRAW_INDEX: + case PACKET3_DRAW_INDEX_AUTO: + case PACKET3_DRAW_INDEX_IMMD: + case PACKET3_NUM_INSTANCES: + case PACKET3_DRAW_INDEX_MULTI_AUTO: + case PACKET3_STRMOUT_BUFFER_UPDATE: + case PACKET3_DRAW_INDEX_OFFSET_2: + case PACKET3_DRAW_INDEX_MULTI_ELEMENT: + case PACKET3_MPEG_INDEX: + case PACKET3_WAIT_REG_MEM: + case PACKET3_MEM_WRITE: + case PACKET3_SURFACE_SYNC: + case PACKET3_EVENT_WRITE: + case PACKET3_EVENT_WRITE_EOP: + case PACKET3_EVENT_WRITE_EOS: + case PACKET3_SET_CONTEXT_REG: + case PACKET3_SET_BOOL_CONST: + case PACKET3_SET_LOOP_CONST: + case PACKET3_SET_RESOURCE: + case PACKET3_SET_SAMPLER: + case PACKET3_SET_CTL_CONST: + case PACKET3_SET_RESOURCE_OFFSET: + case PACKET3_SET_CONTEXT_REG_INDIRECT: + case PACKET3_SET_RESOURCE_INDIRECT: + case CAYMAN_PACKET3_DEALLOC_STATE: + break; + case PACKET3_COND_WRITE: + if (idx_value & 0x100) { + reg = ib[idx + 5] * 4; + if (!evergreen_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_COPY_DW: + if (idx_value & 0x2) { + reg = ib[idx + 3] * 4; + if (!evergreen_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_SET_CONFIG_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CONFIG_REG_START) || + (start_reg >= PACKET3_SET_CONFIG_REG_END) || + (end_reg >= PACKET3_SET_CONFIG_REG_END)) { + DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); + return -EINVAL; + } + for (i = 0; i < pkt->count; i++) { + reg = start_reg + (4 * i); + if (!evergreen_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_CP_DMA: + command = ib[idx + 4]; + info = ib[idx + 1]; + if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ + (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ + ((((info & 0x00300000) >> 20) == 0) && + (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ + ((((info & 0x60000000) >> 29) == 0) && + (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ + /* non mem to mem copies requires dw aligned count */ + if ((command & 0x1fffff) % 4) { + DRM_ERROR("CP DMA command requires dw count alignment\n"); + return -EINVAL; + } + } + if (command & PACKET3_CP_DMA_CMD_SAS) { + /* src address space is register */ + if (((info & 0x60000000) >> 29) == 0) { + start_reg = idx_value << 2; + if (command & PACKET3_CP_DMA_CMD_SAIC) { + reg = start_reg; + if (!evergreen_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!evergreen_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } + } + } + } + if (command & PACKET3_CP_DMA_CMD_DAS) { + /* dst address space is register */ + if (((info & 0x00300000) >> 20) == 0) { + start_reg = ib[idx + 2]; + if (command & PACKET3_CP_DMA_CMD_DAIC) { + reg = start_reg; + if (!evergreen_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!evergreen_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } + } + } + } + break; + default: + return -EINVAL; + } + return 0; +} + +int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) +{ + int ret = 0; + u32 idx = 0; + struct radeon_cs_packet pkt; + + do { + pkt.idx = idx; + pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]); + pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]); + pkt.one_reg_wr = 0; + switch (pkt.type) { + case PACKET_TYPE0: + dev_err(rdev->dev, "Packet0 not allowed!\n"); + ret = -EINVAL; + break; + case PACKET_TYPE2: + idx += 1; + break; + case PACKET_TYPE3: + pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]); + ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt); + idx += pkt.count + 2; + break; + default: + dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); + ret = -EINVAL; + break; + } + if (ret) + break; + } while (idx < ib->length_dw); + + return ret; +} + +/** + * evergreen_dma_ib_parse() - parse the DMA IB for VM + * @rdev: radeon_device pointer + * @ib: radeon_ib pointer + * + * Parses the DMA IB from the VM CS ioctl + * checks for errors. (Cayman-SI) + * Returns 0 for success and an error on failure. + **/ +int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) +{ + u32 idx = 0; + u32 header, cmd, count, tiled, new_cmd, misc; + + do { + header = ib->ptr[idx]; + cmd = GET_DMA_CMD(header); + count = GET_DMA_COUNT(header); + tiled = GET_DMA_T(header); + new_cmd = GET_DMA_NEW(header); + misc = GET_DMA_MISC(header); + + switch (cmd) { + case DMA_PACKET_WRITE: + if (tiled) + idx += count + 7; + else + idx += count + 3; + break; + case DMA_PACKET_COPY: + if (tiled) { + if (new_cmd) { + switch (misc) { + case 0: + /* L2T, frame to fields */ + idx += 10; + break; + case 1: + /* L2T, T2L partial */ + idx += 12; + break; + case 3: + /* L2T, broadcast */ + idx += 10; + break; + case 4: + /* L2T, T2L */ + idx += 9; + break; + case 5: + /* T2T partial */ + idx += 13; + break; + case 7: + /* L2T, broadcast */ + idx += 10; + break; + default: + DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); + return -EINVAL; + } + } else { + switch (misc) { + case 0: + idx += 9; + break; + default: + DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); + return -EINVAL; + } + } + } else { + if (new_cmd) { + switch (misc) { + case 0: + /* L2L, byte */ + idx += 5; + break; + case 1: + /* L2L, partial */ + idx += 9; + break; + case 4: + /* L2L, dw, broadcast */ + idx += 7; + break; + default: + DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); + return -EINVAL; + } + } else { + /* L2L, dw */ + idx += 5; + } + } + break; + case DMA_PACKET_CONSTANT_FILL: + idx += 4; + break; + case DMA_PACKET_NOP: + idx += 1; + break; + default: + DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); + return -EINVAL; + } + } while (idx < ib->length_dw); + + return 0; +} diff --git a/sys/dev/drm2/radeon/evergreen_hdmi.c b/sys/dev/drm2/radeon/evergreen_hdmi.c new file mode 100644 index 00000000000..e4702dae26c --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_hdmi.c @@ -0,0 +1,217 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Christian König. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + * Rafał Miłecki + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "evergreend.h" +#include "atom.h" + +/* + * update the N and CTS parameters for a given pixel clock rate + */ +static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + + WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz)); + WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz); + + WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz)); + WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz); + + WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz)); + WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz); +} + +/* + * calculate the crc for a given info frame + */ +static void evergreen_hdmi_infoframe_checksum(uint8_t packetType, + uint8_t versionNumber, + uint8_t length, + uint8_t *frame) +{ + int i; + frame[0] = packetType + versionNumber + length; + for (i = 1; i <= length; i++) + frame[0] += frame[i]; + frame[0] = 0x100 - frame[0]; +} + +/* + * build a HDMI Video Info Frame + */ +static void evergreen_hdmi_videoinfoframe( + struct drm_encoder *encoder, + uint8_t color_format, + int active_information_present, + uint8_t active_format_aspect_ratio, + uint8_t scan_information, + uint8_t colorimetry, + uint8_t ex_colorimetry, + uint8_t quantization, + int ITC, + uint8_t picture_aspect_ratio, + uint8_t video_format_identification, + uint8_t pixel_repetition, + uint8_t non_uniform_picture_scaling, + uint8_t bar_info_data_valid, + uint16_t top_bar, + uint16_t bottom_bar, + uint16_t left_bar, + uint16_t right_bar +) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + + uint8_t frame[14]; + + frame[0x0] = 0; + frame[0x1] = + (scan_information & 0x3) | + ((bar_info_data_valid & 0x3) << 2) | + ((active_information_present & 0x1) << 4) | + ((color_format & 0x3) << 5); + frame[0x2] = + (active_format_aspect_ratio & 0xF) | + ((picture_aspect_ratio & 0x3) << 4) | + ((colorimetry & 0x3) << 6); + frame[0x3] = + (non_uniform_picture_scaling & 0x3) | + ((quantization & 0x3) << 2) | + ((ex_colorimetry & 0x7) << 4) | + ((ITC & 0x1) << 7); + frame[0x4] = (video_format_identification & 0x7F); + frame[0x5] = (pixel_repetition & 0xF); + frame[0x6] = (top_bar & 0xFF); + frame[0x7] = (top_bar >> 8); + frame[0x8] = (bottom_bar & 0xFF); + frame[0x9] = (bottom_bar >> 8); + frame[0xA] = (left_bar & 0xFF); + frame[0xB] = (left_bar >> 8); + frame[0xC] = (right_bar & 0xFF); + frame[0xD] = (right_bar >> 8); + + evergreen_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame); + /* Our header values (type, version, length) should be alright, Intel + * is using the same. Checksum function also seems to be OK, it works + * fine for audio infoframe. However calculated value is always lower + * by 2 in comparison to fglrx. It breaks displaying anything in case + * of TVs that strictly check the checksum. Hack it manually here to + * workaround this issue. */ + frame[0x0] += 2; + + WREG32(AFMT_AVI_INFO0 + offset, + frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); + WREG32(AFMT_AVI_INFO1 + offset, + frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); + WREG32(AFMT_AVI_INFO2 + offset, + frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); + WREG32(AFMT_AVI_INFO3 + offset, + frame[0xC] | (frame[0xD] << 8)); +} + +/* + * update the info frames with the data from the current display mode + */ +void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset; + + /* Silent, r600_hdmi_enable will raise WARN for us */ + if (!dig->afmt->enabled) + return; + offset = dig->afmt->offset; + + r600_audio_set_clock(encoder, mode->clock); + + WREG32(HDMI_VBI_PACKET_CONTROL + offset, + HDMI_NULL_SEND); /* send null packets when required */ + + WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000); + + WREG32(HDMI_AUDIO_PACKET_CONTROL + offset, + HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ + HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ + + WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, + AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ + AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ + + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ + HDMI_ACR_SOURCE); /* select SW CTS value */ + + WREG32(HDMI_VBI_PACKET_CONTROL + offset, + HDMI_NULL_SEND | /* send null packets when required */ + HDMI_GC_SEND | /* send general control packets */ + HDMI_GC_CONT); /* send general control packets every frame */ + + WREG32(HDMI_INFOFRAME_CONTROL0 + offset, + HDMI_AVI_INFO_SEND | /* enable AVI info frames */ + HDMI_AVI_INFO_CONT | /* send AVI info frames every frame/field */ + HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ + HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ + + WREG32(AFMT_INFOFRAME_CONTROL0 + offset, + AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ + + WREG32(HDMI_INFOFRAME_CONTROL1 + offset, + HDMI_AVI_INFO_LINE(2) | /* anything other than 0 */ + HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ + + WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */ + + evergreen_hdmi_videoinfoframe(encoder, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0); + + evergreen_hdmi_update_ACR(encoder, mode->clock); + + /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ + WREG32(AFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF); + WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); + WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); + WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); +} diff --git a/sys/dev/drm2/radeon/evergreen_reg.h b/sys/dev/drm2/radeon/evergreen_reg.h new file mode 100644 index 00000000000..7603168d274 --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_reg.h @@ -0,0 +1,241 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __EVERGREEN_REG_H__ +#define __EVERGREEN_REG_H__ + +/* evergreen */ +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310 +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324 +#define EVERGREEN_D3VGA_CONTROL 0x3e0 +#define EVERGREEN_D4VGA_CONTROL 0x3e4 +#define EVERGREEN_D5VGA_CONTROL 0x3e8 +#define EVERGREEN_D6VGA_CONTROL 0x3ec + +#define EVERGREEN_P1PLL_SS_CNTL 0x414 +#define EVERGREEN_P2PLL_SS_CNTL 0x454 +# define EVERGREEN_PxPLL_SS_EN (1 << 12) + +#define EVERGREEN_AUDIO_PLL1_MUL 0x5b0 +#define EVERGREEN_AUDIO_PLL1_DIV 0x5b4 +#define EVERGREEN_AUDIO_PLL1_UNK 0x5bc + +#define EVERGREEN_AUDIO_ENABLE 0x5e78 +#define EVERGREEN_AUDIO_VENDOR_ID 0x5ec0 + +/* GRPH blocks at 0x6800, 0x7400, 0x10000, 0x10c00, 0x11800, 0x12400 */ +#define EVERGREEN_GRPH_ENABLE 0x6800 +#define EVERGREEN_GRPH_CONTROL 0x6804 +# define EVERGREEN_GRPH_DEPTH(x) (((x) & 0x3) << 0) +# define EVERGREEN_GRPH_DEPTH_8BPP 0 +# define EVERGREEN_GRPH_DEPTH_16BPP 1 +# define EVERGREEN_GRPH_DEPTH_32BPP 2 +# define EVERGREEN_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2) +# define EVERGREEN_ADDR_SURF_2_BANK 0 +# define EVERGREEN_ADDR_SURF_4_BANK 1 +# define EVERGREEN_ADDR_SURF_8_BANK 2 +# define EVERGREEN_ADDR_SURF_16_BANK 3 +# define EVERGREEN_GRPH_Z(x) (((x) & 0x3) << 4) +# define EVERGREEN_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6) +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_1 0 +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_2 1 +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_4 2 +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_8 3 +# define EVERGREEN_GRPH_FORMAT(x) (((x) & 0x7) << 8) +/* 8 BPP */ +# define EVERGREEN_GRPH_FORMAT_INDEXED 0 +/* 16 BPP */ +# define EVERGREEN_GRPH_FORMAT_ARGB1555 0 +# define EVERGREEN_GRPH_FORMAT_ARGB565 1 +# define EVERGREEN_GRPH_FORMAT_ARGB4444 2 +# define EVERGREEN_GRPH_FORMAT_AI88 3 +# define EVERGREEN_GRPH_FORMAT_MONO16 4 +# define EVERGREEN_GRPH_FORMAT_BGRA5551 5 +/* 32 BPP */ +# define EVERGREEN_GRPH_FORMAT_ARGB8888 0 +# define EVERGREEN_GRPH_FORMAT_ARGB2101010 1 +# define EVERGREEN_GRPH_FORMAT_32BPP_DIG 2 +# define EVERGREEN_GRPH_FORMAT_8B_ARGB2101010 3 +# define EVERGREEN_GRPH_FORMAT_BGRA1010102 4 +# define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102 5 +# define EVERGREEN_GRPH_FORMAT_RGB111110 6 +# define EVERGREEN_GRPH_FORMAT_BGR101111 7 +# define EVERGREEN_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11) +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1 0 +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2 1 +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4 2 +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8 3 +# define EVERGREEN_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13) +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B 0 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B 1 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B 2 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B 3 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB 4 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB 5 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB 6 +# define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18) +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1 0 +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2 1 +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4 2 +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8 3 +# define EVERGREEN_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20) +# define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL 0 +# define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED 1 +# define EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1 2 +# define EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1 4 +#define EVERGREEN_GRPH_SWAP_CONTROL 0x680c +# define EVERGREEN_GRPH_ENDIAN_SWAP(x) (((x) & 0x3) << 0) +# define EVERGREEN_GRPH_ENDIAN_NONE 0 +# define EVERGREEN_GRPH_ENDIAN_8IN16 1 +# define EVERGREEN_GRPH_ENDIAN_8IN32 2 +# define EVERGREEN_GRPH_ENDIAN_8IN64 3 +# define EVERGREEN_GRPH_RED_CROSSBAR(x) (((x) & 0x3) << 4) +# define EVERGREEN_GRPH_RED_SEL_R 0 +# define EVERGREEN_GRPH_RED_SEL_G 1 +# define EVERGREEN_GRPH_RED_SEL_B 2 +# define EVERGREEN_GRPH_RED_SEL_A 3 +# define EVERGREEN_GRPH_GREEN_CROSSBAR(x) (((x) & 0x3) << 6) +# define EVERGREEN_GRPH_GREEN_SEL_G 0 +# define EVERGREEN_GRPH_GREEN_SEL_B 1 +# define EVERGREEN_GRPH_GREEN_SEL_A 2 +# define EVERGREEN_GRPH_GREEN_SEL_R 3 +# define EVERGREEN_GRPH_BLUE_CROSSBAR(x) (((x) & 0x3) << 8) +# define EVERGREEN_GRPH_BLUE_SEL_B 0 +# define EVERGREEN_GRPH_BLUE_SEL_A 1 +# define EVERGREEN_GRPH_BLUE_SEL_R 2 +# define EVERGREEN_GRPH_BLUE_SEL_G 3 +# define EVERGREEN_GRPH_ALPHA_CROSSBAR(x) (((x) & 0x3) << 10) +# define EVERGREEN_GRPH_ALPHA_SEL_A 0 +# define EVERGREEN_GRPH_ALPHA_SEL_R 1 +# define EVERGREEN_GRPH_ALPHA_SEL_G 2 +# define EVERGREEN_GRPH_ALPHA_SEL_B 3 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS 0x6810 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS 0x6814 +# define EVERGREEN_GRPH_DFQ_ENABLE (1 << 0) +# define EVERGREEN_GRPH_SURFACE_ADDRESS_MASK 0xffffff00 +#define EVERGREEN_GRPH_PITCH 0x6818 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x681c +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x6820 +#define EVERGREEN_GRPH_SURFACE_OFFSET_X 0x6824 +#define EVERGREEN_GRPH_SURFACE_OFFSET_Y 0x6828 +#define EVERGREEN_GRPH_X_START 0x682c +#define EVERGREEN_GRPH_Y_START 0x6830 +#define EVERGREEN_GRPH_X_END 0x6834 +#define EVERGREEN_GRPH_Y_END 0x6838 +#define EVERGREEN_GRPH_UPDATE 0x6844 +# define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING (1 << 2) +# define EVERGREEN_GRPH_UPDATE_LOCK (1 << 16) +#define EVERGREEN_GRPH_FLIP_CONTROL 0x6848 +# define EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) + +/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */ +#define EVERGREEN_CUR_CONTROL 0x6998 +# define EVERGREEN_CURSOR_EN (1 << 0) +# define EVERGREEN_CURSOR_MODE(x) (((x) & 0x3) << 8) +# define EVERGREEN_CURSOR_MONO 0 +# define EVERGREEN_CURSOR_24_1 1 +# define EVERGREEN_CURSOR_24_8_PRE_MULT 2 +# define EVERGREEN_CURSOR_24_8_UNPRE_MULT 3 +# define EVERGREEN_CURSOR_2X_MAGNIFY (1 << 16) +# define EVERGREEN_CURSOR_FORCE_MC_ON (1 << 20) +# define EVERGREEN_CURSOR_URGENT_CONTROL(x) (((x) & 0x7) << 24) +# define EVERGREEN_CURSOR_URGENT_ALWAYS 0 +# define EVERGREEN_CURSOR_URGENT_1_8 1 +# define EVERGREEN_CURSOR_URGENT_1_4 2 +# define EVERGREEN_CURSOR_URGENT_3_8 3 +# define EVERGREEN_CURSOR_URGENT_1_2 4 +#define EVERGREEN_CUR_SURFACE_ADDRESS 0x699c +# define EVERGREEN_CUR_SURFACE_ADDRESS_MASK 0xfffff000 +#define EVERGREEN_CUR_SIZE 0x69a0 +#define EVERGREEN_CUR_SURFACE_ADDRESS_HIGH 0x69a4 +#define EVERGREEN_CUR_POSITION 0x69a8 +#define EVERGREEN_CUR_HOT_SPOT 0x69ac +#define EVERGREEN_CUR_COLOR1 0x69b0 +#define EVERGREEN_CUR_COLOR2 0x69b4 +#define EVERGREEN_CUR_UPDATE 0x69b8 +# define EVERGREEN_CURSOR_UPDATE_PENDING (1 << 0) +# define EVERGREEN_CURSOR_UPDATE_TAKEN (1 << 1) +# define EVERGREEN_CURSOR_UPDATE_LOCK (1 << 16) +# define EVERGREEN_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24) + +/* LUT blocks at 0x69e0, 0x75e0, 0x101e0, 0x10de0, 0x119e0, 0x125e0 */ +#define EVERGREEN_DC_LUT_RW_MODE 0x69e0 +#define EVERGREEN_DC_LUT_RW_INDEX 0x69e4 +#define EVERGREEN_DC_LUT_SEQ_COLOR 0x69e8 +#define EVERGREEN_DC_LUT_PWL_DATA 0x69ec +#define EVERGREEN_DC_LUT_30_COLOR 0x69f0 +#define EVERGREEN_DC_LUT_VGA_ACCESS_ENABLE 0x69f4 +#define EVERGREEN_DC_LUT_WRITE_EN_MASK 0x69f8 +#define EVERGREEN_DC_LUT_AUTOFILL 0x69fc +#define EVERGREEN_DC_LUT_CONTROL 0x6a00 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE 0x6a04 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN 0x6a08 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_RED 0x6a0c +#define EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE 0x6a10 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN 0x6a14 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_RED 0x6a18 + +#define EVERGREEN_DATA_FORMAT 0x6b00 +# define EVERGREEN_INTERLEAVE_EN (1 << 0) +#define EVERGREEN_DESKTOP_HEIGHT 0x6b04 +#define EVERGREEN_VLINE_START_END 0x6b08 +#define EVERGREEN_VLINE_STATUS 0x6bb8 +# define EVERGREEN_VLINE_STAT (1 << 12) + +#define EVERGREEN_VIEWPORT_START 0x6d70 +#define EVERGREEN_VIEWPORT_SIZE 0x6d74 + +/* display controller offsets used for crtc/cur/lut/grph/viewport/etc. */ +#define EVERGREEN_CRTC0_REGISTER_OFFSET (0x6df0 - 0x6df0) +#define EVERGREEN_CRTC1_REGISTER_OFFSET (0x79f0 - 0x6df0) +#define EVERGREEN_CRTC2_REGISTER_OFFSET (0x105f0 - 0x6df0) +#define EVERGREEN_CRTC3_REGISTER_OFFSET (0x111f0 - 0x6df0) +#define EVERGREEN_CRTC4_REGISTER_OFFSET (0x11df0 - 0x6df0) +#define EVERGREEN_CRTC5_REGISTER_OFFSET (0x129f0 - 0x6df0) + +/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ +#define EVERGREEN_CRTC_V_BLANK_START_END 0x6e34 +#define EVERGREEN_CRTC_CONTROL 0x6e70 +# define EVERGREEN_CRTC_MASTER_EN (1 << 0) +# define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 +# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) +#define EVERGREEN_CRTC_STATUS 0x6e8c +# define EVERGREEN_CRTC_V_BLANK (1 << 0) +#define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 +#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 +#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 + +#define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 +#define EVERGREEN_DC_GPIO_HPD_A 0x64b4 +#define EVERGREEN_DC_GPIO_HPD_EN 0x64b8 +#define EVERGREEN_DC_GPIO_HPD_Y 0x64bc + +/* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */ +#define EVERGREEN_HDMI_BASE 0x7030 + +#endif diff --git a/sys/dev/drm2/radeon/evergreen_reg_safe.h b/sys/dev/drm2/radeon/evergreen_reg_safe.h new file mode 100644 index 00000000000..9d56fe7a536 --- /dev/null +++ b/sys/dev/drm2/radeon/evergreen_reg_safe.h @@ -0,0 +1,517 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned evergreen_reg_safe_bm[2047] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFF0F7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xCFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFDDEFFF, 0xCF3FFFFF, 0xFFFFF40F, + 0xFEFFFFDF, 0xFFFFFFFF, 0xFFFFFFEF, 0xEFFFFFFF, + 0xFFFFF800, 0xFFFFFFFF, 0xFFFFFFFF, 0xBFFFFF07, + 0xFFFBF0FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFDF, 0xFFFFFFFF, 0xFFFF7FFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFB, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFDE, 0xFFFFFFFF, + 0xFFDF0FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xC0000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFC3E4, 0xFFFFFFFF, 0x0000FFFF, 0x00000000, + 0x000CC000, 0x00000000, 0xFFD00000, 0x00000000, + 0x00000E00, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xC0000000, 0xFFFFF8FF, 0xFE07FF00, + 0x3CF1B003, 0xE39E7BCF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xF7020000, 0xDDD89CDD, 0x201FA3FD, 0xFFFFFFF0, + 0xBFFF0002, 0xEFC3DF87, 0x7BF0F7E1, 0x1EFC3DF8, + 0xDFBF0F7E, 0xFFFFF7EF, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xCFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, +}; diff --git a/sys/dev/drm2/radeon/evergreend.h b/sys/dev/drm2/radeon/evergreend.h new file mode 100644 index 00000000000..3fd74ce1e49 --- /dev/null +++ b/sys/dev/drm2/radeon/evergreend.h @@ -0,0 +1,2046 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef EVERGREEND_H +#define EVERGREEND_H + +#define EVERGREEN_MAX_SH_GPRS 256 +#define EVERGREEN_MAX_TEMP_GPRS 16 +#define EVERGREEN_MAX_SH_THREADS 256 +#define EVERGREEN_MAX_SH_STACK_ENTRIES 4096 +#define EVERGREEN_MAX_FRC_EOV_CNT 16384 +#define EVERGREEN_MAX_BACKENDS 8 +#define EVERGREEN_MAX_BACKENDS_MASK 0xFF +#define EVERGREEN_MAX_SIMDS 16 +#define EVERGREEN_MAX_SIMDS_MASK 0xFFFF +#define EVERGREEN_MAX_PIPES 8 +#define EVERGREEN_MAX_PIPES_MASK 0xFF +#define EVERGREEN_MAX_LDS_NUM 0xFFFF + +#define CYPRESS_GB_ADDR_CONFIG_GOLDEN 0x02011003 +#define BARTS_GB_ADDR_CONFIG_GOLDEN 0x02011003 +#define CAYMAN_GB_ADDR_CONFIG_GOLDEN 0x02011003 +#define JUNIPER_GB_ADDR_CONFIG_GOLDEN 0x02010002 +#define REDWOOD_GB_ADDR_CONFIG_GOLDEN 0x02010002 +#define TURKS_GB_ADDR_CONFIG_GOLDEN 0x02010002 +#define CEDAR_GB_ADDR_CONFIG_GOLDEN 0x02010001 +#define CAICOS_GB_ADDR_CONFIG_GOLDEN 0x02010001 +#define SUMO_GB_ADDR_CONFIG_GOLDEN 0x02010002 +#define SUMO2_GB_ADDR_CONFIG_GOLDEN 0x02010002 + +/* Registers */ + +#define RCU_IND_INDEX 0x100 +#define RCU_IND_DATA 0x104 + +#define GRBM_GFX_INDEX 0x802C +#define INSTANCE_INDEX(x) ((x) << 0) +#define SE_INDEX(x) ((x) << 16) +#define INSTANCE_BROADCAST_WRITES (1 << 30) +#define SE_BROADCAST_WRITES (1 << 31) +#define RLC_GFX_INDEX 0x3fC4 +#define CC_GC_SHADER_PIPE_CONFIG 0x8950 +#define WRITE_DIS (1 << 0) +#define CC_RB_BACKEND_DISABLE 0x98F4 +#define BACKEND_DISABLE(x) ((x) << 16) +#define GB_ADDR_CONFIG 0x98F8 +#define NUM_PIPES(x) ((x) << 0) +#define NUM_PIPES_MASK 0x0000000f +#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) +#define BANK_INTERLEAVE_SIZE(x) ((x) << 8) +#define NUM_SHADER_ENGINES(x) ((x) << 12) +#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) +#define NUM_GPUS(x) ((x) << 20) +#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) +#define ROW_SIZE(x) ((x) << 28) +#define GB_BACKEND_MAP 0x98FC +#define DMIF_ADDR_CONFIG 0xBD4 +#define HDP_ADDR_CONFIG 0x2F48 +#define HDP_MISC_CNTL 0x2F4C +#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) + +#define CC_SYS_RB_BACKEND_DISABLE 0x3F88 +#define GC_USER_RB_BACKEND_DISABLE 0x9B7C + +#define CGTS_SYS_TCC_DISABLE 0x3F90 +#define CGTS_TCC_DISABLE 0x9148 +#define CGTS_USER_SYS_TCC_DISABLE 0x3F94 +#define CGTS_USER_TCC_DISABLE 0x914C + +#define CONFIG_MEMSIZE 0x5428 + +#define BIF_FB_EN 0x5490 +#define FB_READ_EN (1 << 0) +#define FB_WRITE_EN (1 << 1) + +#define CP_STRMOUT_CNTL 0x84FC + +#define CP_COHER_CNTL 0x85F0 +#define CP_COHER_SIZE 0x85F4 +#define CP_COHER_BASE 0x85F8 +#define CP_STALLED_STAT1 0x8674 +#define CP_STALLED_STAT2 0x8678 +#define CP_BUSY_STAT 0x867C +#define CP_STAT 0x8680 +#define CP_ME_CNTL 0x86D8 +#define CP_ME_HALT (1 << 28) +#define CP_PFP_HALT (1 << 26) +#define CP_ME_RAM_DATA 0xC160 +#define CP_ME_RAM_RADDR 0xC158 +#define CP_ME_RAM_WADDR 0xC15C +#define CP_MEQ_THRESHOLDS 0x8764 +#define STQ_SPLIT(x) ((x) << 0) +#define CP_PERFMON_CNTL 0x87FC +#define CP_PFP_UCODE_ADDR 0xC150 +#define CP_PFP_UCODE_DATA 0xC154 +#define CP_QUEUE_THRESHOLDS 0x8760 +#define ROQ_IB1_START(x) ((x) << 0) +#define ROQ_IB2_START(x) ((x) << 8) +#define CP_RB_BASE 0xC100 +#define CP_RB_CNTL 0xC104 +#define RB_BUFSZ(x) ((x) << 0) +#define RB_BLKSZ(x) ((x) << 8) +#define RB_NO_UPDATE (1 << 27) +#define RB_RPTR_WR_ENA (1 << 31) +#define BUF_SWAP_32BIT (2 << 16) +#define CP_RB_RPTR 0x8700 +#define CP_RB_RPTR_ADDR 0xC10C +#define RB_RPTR_SWAP(x) ((x) << 0) +#define CP_RB_RPTR_ADDR_HI 0xC110 +#define CP_RB_RPTR_WR 0xC108 +#define CP_RB_WPTR 0xC114 +#define CP_RB_WPTR_ADDR 0xC118 +#define CP_RB_WPTR_ADDR_HI 0xC11C +#define CP_RB_WPTR_DELAY 0x8704 +#define CP_SEM_WAIT_TIMER 0x85BC +#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 +#define CP_DEBUG 0xC1FC + +/* Audio clocks */ +#define DCCG_AUDIO_DTO_SOURCE 0x05ac +# define DCCG_AUDIO_DTO0_SOURCE_SEL(x) ((x) << 0) /* crtc0 - crtc5 */ +# define DCCG_AUDIO_DTO_SEL (1 << 4) /* 0=dto0 1=dto1 */ + +#define DCCG_AUDIO_DTO0_PHASE 0x05b0 +#define DCCG_AUDIO_DTO0_MODULE 0x05b4 +#define DCCG_AUDIO_DTO0_LOAD 0x05b8 +#define DCCG_AUDIO_DTO0_CNTL 0x05bc + +#define DCCG_AUDIO_DTO1_PHASE 0x05c0 +#define DCCG_AUDIO_DTO1_MODULE 0x05c4 +#define DCCG_AUDIO_DTO1_LOAD 0x05c8 +#define DCCG_AUDIO_DTO1_CNTL 0x05cc + +/* DCE 4.0 AFMT */ +#define HDMI_CONTROL 0x7030 +# define HDMI_KEEPOUT_MODE (1 << 0) +# define HDMI_PACKET_GEN_VERSION (1 << 4) /* 0 = r6xx compat */ +# define HDMI_ERROR_ACK (1 << 8) +# define HDMI_ERROR_MASK (1 << 9) +# define HDMI_DEEP_COLOR_ENABLE (1 << 24) +# define HDMI_DEEP_COLOR_DEPTH (((x) & 3) << 28) +# define HDMI_24BIT_DEEP_COLOR 0 +# define HDMI_30BIT_DEEP_COLOR 1 +# define HDMI_36BIT_DEEP_COLOR 2 +#define HDMI_STATUS 0x7034 +# define HDMI_ACTIVE_AVMUTE (1 << 0) +# define HDMI_AUDIO_PACKET_ERROR (1 << 16) +# define HDMI_VBI_PACKET_ERROR (1 << 20) +#define HDMI_AUDIO_PACKET_CONTROL 0x7038 +# define HDMI_AUDIO_DELAY_EN(x) (((x) & 3) << 4) +# define HDMI_AUDIO_PACKETS_PER_LINE(x) (((x) & 0x1f) << 16) +#define HDMI_ACR_PACKET_CONTROL 0x703c +# define HDMI_ACR_SEND (1 << 0) +# define HDMI_ACR_CONT (1 << 1) +# define HDMI_ACR_SELECT(x) (((x) & 3) << 4) +# define HDMI_ACR_HW 0 +# define HDMI_ACR_32 1 +# define HDMI_ACR_44 2 +# define HDMI_ACR_48 3 +# define HDMI_ACR_SOURCE (1 << 8) /* 0 - hw; 1 - cts value */ +# define HDMI_ACR_AUTO_SEND (1 << 12) +# define HDMI_ACR_N_MULTIPLE(x) (((x) & 7) << 16) +# define HDMI_ACR_X1 1 +# define HDMI_ACR_X2 2 +# define HDMI_ACR_X4 4 +# define HDMI_ACR_AUDIO_PRIORITY (1 << 31) +#define HDMI_VBI_PACKET_CONTROL 0x7040 +# define HDMI_NULL_SEND (1 << 0) +# define HDMI_GC_SEND (1 << 4) +# define HDMI_GC_CONT (1 << 5) /* 0 - once; 1 - every frame */ +#define HDMI_INFOFRAME_CONTROL0 0x7044 +# define HDMI_AVI_INFO_SEND (1 << 0) +# define HDMI_AVI_INFO_CONT (1 << 1) +# define HDMI_AUDIO_INFO_SEND (1 << 4) +# define HDMI_AUDIO_INFO_CONT (1 << 5) +# define HDMI_MPEG_INFO_SEND (1 << 8) +# define HDMI_MPEG_INFO_CONT (1 << 9) +#define HDMI_INFOFRAME_CONTROL1 0x7048 +# define HDMI_AVI_INFO_LINE(x) (((x) & 0x3f) << 0) +# define HDMI_AUDIO_INFO_LINE(x) (((x) & 0x3f) << 8) +# define HDMI_MPEG_INFO_LINE(x) (((x) & 0x3f) << 16) +#define HDMI_GENERIC_PACKET_CONTROL 0x704c +# define HDMI_GENERIC0_SEND (1 << 0) +# define HDMI_GENERIC0_CONT (1 << 1) +# define HDMI_GENERIC1_SEND (1 << 4) +# define HDMI_GENERIC1_CONT (1 << 5) +# define HDMI_GENERIC0_LINE(x) (((x) & 0x3f) << 16) +# define HDMI_GENERIC1_LINE(x) (((x) & 0x3f) << 24) +#define HDMI_GC 0x7058 +# define HDMI_GC_AVMUTE (1 << 0) +# define HDMI_GC_AVMUTE_CONT (1 << 2) +#define AFMT_AUDIO_PACKET_CONTROL2 0x705c +# define AFMT_AUDIO_LAYOUT_OVRD (1 << 0) +# define AFMT_AUDIO_LAYOUT_SELECT (1 << 1) +# define AFMT_60958_CS_SOURCE (1 << 4) +# define AFMT_AUDIO_CHANNEL_ENABLE(x) (((x) & 0xff) << 8) +# define AFMT_DP_AUDIO_STREAM_ID(x) (((x) & 0xff) << 16) +#define AFMT_AVI_INFO0 0x7084 +# define AFMT_AVI_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define AFMT_AVI_INFO_S(x) (((x) & 3) << 8) +# define AFMT_AVI_INFO_B(x) (((x) & 3) << 10) +# define AFMT_AVI_INFO_A(x) (((x) & 1) << 12) +# define AFMT_AVI_INFO_Y(x) (((x) & 3) << 13) +# define AFMT_AVI_INFO_Y_RGB 0 +# define AFMT_AVI_INFO_Y_YCBCR422 1 +# define AFMT_AVI_INFO_Y_YCBCR444 2 +# define AFMT_AVI_INFO_Y_A_B_S(x) (((x) & 0xff) << 8) +# define AFMT_AVI_INFO_R(x) (((x) & 0xf) << 16) +# define AFMT_AVI_INFO_M(x) (((x) & 0x3) << 20) +# define AFMT_AVI_INFO_C(x) (((x) & 0x3) << 22) +# define AFMT_AVI_INFO_C_M_R(x) (((x) & 0xff) << 16) +# define AFMT_AVI_INFO_SC(x) (((x) & 0x3) << 24) +# define AFMT_AVI_INFO_Q(x) (((x) & 0x3) << 26) +# define AFMT_AVI_INFO_EC(x) (((x) & 0x3) << 28) +# define AFMT_AVI_INFO_ITC(x) (((x) & 0x1) << 31) +# define AFMT_AVI_INFO_ITC_EC_Q_SC(x) (((x) & 0xff) << 24) +#define AFMT_AVI_INFO1 0x7088 +# define AFMT_AVI_INFO_VIC(x) (((x) & 0x7f) << 0) /* don't use avi infoframe v1 */ +# define AFMT_AVI_INFO_PR(x) (((x) & 0xf) << 8) /* don't use avi infoframe v1 */ +# define AFMT_AVI_INFO_CN(x) (((x) & 0x3) << 12) +# define AFMT_AVI_INFO_YQ(x) (((x) & 0x3) << 14) +# define AFMT_AVI_INFO_TOP(x) (((x) & 0xffff) << 16) +#define AFMT_AVI_INFO2 0x708c +# define AFMT_AVI_INFO_BOTTOM(x) (((x) & 0xffff) << 0) +# define AFMT_AVI_INFO_LEFT(x) (((x) & 0xffff) << 16) +#define AFMT_AVI_INFO3 0x7090 +# define AFMT_AVI_INFO_RIGHT(x) (((x) & 0xffff) << 0) +# define AFMT_AVI_INFO_VERSION(x) (((x) & 3) << 24) +#define AFMT_MPEG_INFO0 0x7094 +# define AFMT_MPEG_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define AFMT_MPEG_INFO_MB0(x) (((x) & 0xff) << 8) +# define AFMT_MPEG_INFO_MB1(x) (((x) & 0xff) << 16) +# define AFMT_MPEG_INFO_MB2(x) (((x) & 0xff) << 24) +#define AFMT_MPEG_INFO1 0x7098 +# define AFMT_MPEG_INFO_MB3(x) (((x) & 0xff) << 0) +# define AFMT_MPEG_INFO_MF(x) (((x) & 3) << 8) +# define AFMT_MPEG_INFO_FR(x) (((x) & 1) << 12) +#define AFMT_GENERIC0_HDR 0x709c +#define AFMT_GENERIC0_0 0x70a0 +#define AFMT_GENERIC0_1 0x70a4 +#define AFMT_GENERIC0_2 0x70a8 +#define AFMT_GENERIC0_3 0x70ac +#define AFMT_GENERIC0_4 0x70b0 +#define AFMT_GENERIC0_5 0x70b4 +#define AFMT_GENERIC0_6 0x70b8 +#define AFMT_GENERIC1_HDR 0x70bc +#define AFMT_GENERIC1_0 0x70c0 +#define AFMT_GENERIC1_1 0x70c4 +#define AFMT_GENERIC1_2 0x70c8 +#define AFMT_GENERIC1_3 0x70cc +#define AFMT_GENERIC1_4 0x70d0 +#define AFMT_GENERIC1_5 0x70d4 +#define AFMT_GENERIC1_6 0x70d8 +#define HDMI_ACR_32_0 0x70dc +# define HDMI_ACR_CTS_32(x) (((x) & 0xfffff) << 12) +#define HDMI_ACR_32_1 0x70e0 +# define HDMI_ACR_N_32(x) (((x) & 0xfffff) << 0) +#define HDMI_ACR_44_0 0x70e4 +# define HDMI_ACR_CTS_44(x) (((x) & 0xfffff) << 12) +#define HDMI_ACR_44_1 0x70e8 +# define HDMI_ACR_N_44(x) (((x) & 0xfffff) << 0) +#define HDMI_ACR_48_0 0x70ec +# define HDMI_ACR_CTS_48(x) (((x) & 0xfffff) << 12) +#define HDMI_ACR_48_1 0x70f0 +# define HDMI_ACR_N_48(x) (((x) & 0xfffff) << 0) +#define HDMI_ACR_STATUS_0 0x70f4 +#define HDMI_ACR_STATUS_1 0x70f8 +#define AFMT_AUDIO_INFO0 0x70fc +# define AFMT_AUDIO_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define AFMT_AUDIO_INFO_CC(x) (((x) & 7) << 8) +# define AFMT_AUDIO_INFO_CT(x) (((x) & 0xf) << 11) +# define AFMT_AUDIO_INFO_CHECKSUM_OFFSET(x) (((x) & 0xff) << 16) +# define AFMT_AUDIO_INFO_CXT(x) (((x) & 0x1f) << 24) +#define AFMT_AUDIO_INFO1 0x7100 +# define AFMT_AUDIO_INFO_CA(x) (((x) & 0xff) << 0) +# define AFMT_AUDIO_INFO_LSV(x) (((x) & 0xf) << 11) +# define AFMT_AUDIO_INFO_DM_INH(x) (((x) & 1) << 15) +# define AFMT_AUDIO_INFO_DM_INH_LSV(x) (((x) & 0xff) << 8) +# define AFMT_AUDIO_INFO_LFEBPL(x) (((x) & 3) << 16) +#define AFMT_60958_0 0x7104 +# define AFMT_60958_CS_A(x) (((x) & 1) << 0) +# define AFMT_60958_CS_B(x) (((x) & 1) << 1) +# define AFMT_60958_CS_C(x) (((x) & 1) << 2) +# define AFMT_60958_CS_D(x) (((x) & 3) << 3) +# define AFMT_60958_CS_MODE(x) (((x) & 3) << 6) +# define AFMT_60958_CS_CATEGORY_CODE(x) (((x) & 0xff) << 8) +# define AFMT_60958_CS_SOURCE_NUMBER(x) (((x) & 0xf) << 16) +# define AFMT_60958_CS_CHANNEL_NUMBER_L(x) (((x) & 0xf) << 20) +# define AFMT_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24) +# define AFMT_60958_CS_CLOCK_ACCURACY(x) (((x) & 3) << 28) +#define AFMT_60958_1 0x7108 +# define AFMT_60958_CS_WORD_LENGTH(x) (((x) & 0xf) << 0) +# define AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 4) +# define AFMT_60958_CS_VALID_L(x) (((x) & 1) << 16) +# define AFMT_60958_CS_VALID_R(x) (((x) & 1) << 18) +# define AFMT_60958_CS_CHANNEL_NUMBER_R(x) (((x) & 0xf) << 20) +#define AFMT_AUDIO_CRC_CONTROL 0x710c +# define AFMT_AUDIO_CRC_EN (1 << 0) +#define AFMT_RAMP_CONTROL0 0x7110 +# define AFMT_RAMP_MAX_COUNT(x) (((x) & 0xffffff) << 0) +# define AFMT_RAMP_DATA_SIGN (1 << 31) +#define AFMT_RAMP_CONTROL1 0x7114 +# define AFMT_RAMP_MIN_COUNT(x) (((x) & 0xffffff) << 0) +# define AFMT_AUDIO_TEST_CH_DISABLE(x) (((x) & 0xff) << 24) +#define AFMT_RAMP_CONTROL2 0x7118 +# define AFMT_RAMP_INC_COUNT(x) (((x) & 0xffffff) << 0) +#define AFMT_RAMP_CONTROL3 0x711c +# define AFMT_RAMP_DEC_COUNT(x) (((x) & 0xffffff) << 0) +#define AFMT_60958_2 0x7120 +# define AFMT_60958_CS_CHANNEL_NUMBER_2(x) (((x) & 0xf) << 0) +# define AFMT_60958_CS_CHANNEL_NUMBER_3(x) (((x) & 0xf) << 4) +# define AFMT_60958_CS_CHANNEL_NUMBER_4(x) (((x) & 0xf) << 8) +# define AFMT_60958_CS_CHANNEL_NUMBER_5(x) (((x) & 0xf) << 12) +# define AFMT_60958_CS_CHANNEL_NUMBER_6(x) (((x) & 0xf) << 16) +# define AFMT_60958_CS_CHANNEL_NUMBER_7(x) (((x) & 0xf) << 20) +#define AFMT_STATUS 0x7128 +# define AFMT_AUDIO_ENABLE (1 << 4) +# define AFMT_AUDIO_HBR_ENABLE (1 << 8) +# define AFMT_AZ_FORMAT_WTRIG (1 << 28) +# define AFMT_AZ_FORMAT_WTRIG_INT (1 << 29) +# define AFMT_AZ_AUDIO_ENABLE_CHG (1 << 30) +#define AFMT_AUDIO_PACKET_CONTROL 0x712c +# define AFMT_AUDIO_SAMPLE_SEND (1 << 0) +# define AFMT_RESET_FIFO_WHEN_AUDIO_DIS (1 << 11) /* set to 1 */ +# define AFMT_AUDIO_TEST_EN (1 << 12) +# define AFMT_AUDIO_CHANNEL_SWAP (1 << 24) +# define AFMT_60958_CS_UPDATE (1 << 26) +# define AFMT_AZ_AUDIO_ENABLE_CHG_MASK (1 << 27) +# define AFMT_AZ_FORMAT_WTRIG_MASK (1 << 28) +# define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29) +# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30) +#define AFMT_VBI_PACKET_CONTROL 0x7130 +# define AFMT_GENERIC0_UPDATE (1 << 2) +#define AFMT_INFOFRAME_CONTROL0 0x7134 +# define AFMT_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - afmt regs */ +# define AFMT_AUDIO_INFO_UPDATE (1 << 7) +# define AFMT_MPEG_INFO_UPDATE (1 << 10) +#define AFMT_GENERIC0_7 0x7138 + +/* DCE4/5 ELD audio interface */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0 0x5f84 /* LPCM */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1 0x5f88 /* AC3 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2 0x5f8c /* MPEG1 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3 0x5f90 /* MP3 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4 0x5f94 /* MPEG2 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5 0x5f98 /* AAC */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6 0x5f9c /* DTS */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7 0x5fa0 /* ATRAC */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR8 0x5fa4 /* one bit audio - leave at 0 (default) */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9 0x5fa8 /* Dolby Digital */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10 0x5fac /* DTS-HD */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11 0x5fb0 /* MAT-MLP */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR12 0x5fb4 /* DTS */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13 0x5fb8 /* WMA Pro */ +# define MAX_CHANNELS(x) (((x) & 0x7) << 0) +/* max channels minus one. 7 = 8 channels */ +# define SUPPORTED_FREQUENCIES(x) (((x) & 0xff) << 8) +# define DESCRIPTOR_BYTE_2(x) (((x) & 0xff) << 16) +# define SUPPORTED_FREQUENCIES_STEREO(x) (((x) & 0xff) << 24) /* LPCM only */ +/* SUPPORTED_FREQUENCIES, SUPPORTED_FREQUENCIES_STEREO + * bit0 = 32 kHz + * bit1 = 44.1 kHz + * bit2 = 48 kHz + * bit3 = 88.2 kHz + * bit4 = 96 kHz + * bit5 = 176.4 kHz + * bit6 = 192 kHz + */ + +#define AZ_HOT_PLUG_CONTROL 0x5e78 +# define AZ_FORCE_CODEC_WAKE (1 << 0) +# define PIN0_JACK_DETECTION_ENABLE (1 << 4) +# define PIN1_JACK_DETECTION_ENABLE (1 << 5) +# define PIN2_JACK_DETECTION_ENABLE (1 << 6) +# define PIN3_JACK_DETECTION_ENABLE (1 << 7) +# define PIN0_UNSOLICITED_RESPONSE_ENABLE (1 << 8) +# define PIN1_UNSOLICITED_RESPONSE_ENABLE (1 << 9) +# define PIN2_UNSOLICITED_RESPONSE_ENABLE (1 << 10) +# define PIN3_UNSOLICITED_RESPONSE_ENABLE (1 << 11) +# define CODEC_HOT_PLUG_ENABLE (1 << 12) +# define PIN0_AUDIO_ENABLED (1 << 24) +# define PIN1_AUDIO_ENABLED (1 << 25) +# define PIN2_AUDIO_ENABLED (1 << 26) +# define PIN3_AUDIO_ENABLED (1 << 27) +# define AUDIO_ENABLED (1 << 31) + + +#define GC_USER_SHADER_PIPE_CONFIG 0x8954 +#define INACTIVE_QD_PIPES(x) ((x) << 8) +#define INACTIVE_QD_PIPES_MASK 0x0000FF00 +#define INACTIVE_SIMDS(x) ((x) << 16) +#define INACTIVE_SIMDS_MASK 0x00FF0000 + +#define GRBM_CNTL 0x8000 +#define GRBM_READ_TIMEOUT(x) ((x) << 0) +#define GRBM_SOFT_RESET 0x8020 +#define SOFT_RESET_CP (1 << 0) +#define SOFT_RESET_CB (1 << 1) +#define SOFT_RESET_DB (1 << 3) +#define SOFT_RESET_PA (1 << 5) +#define SOFT_RESET_SC (1 << 6) +#define SOFT_RESET_SPI (1 << 8) +#define SOFT_RESET_SH (1 << 9) +#define SOFT_RESET_SX (1 << 10) +#define SOFT_RESET_TC (1 << 11) +#define SOFT_RESET_TA (1 << 12) +#define SOFT_RESET_VC (1 << 13) +#define SOFT_RESET_VGT (1 << 14) + +#define GRBM_STATUS 0x8010 +#define CMDFIFO_AVAIL_MASK 0x0000000F +#define SRBM_RQ_PENDING (1 << 5) +#define CF_RQ_PENDING (1 << 7) +#define PF_RQ_PENDING (1 << 8) +#define GRBM_EE_BUSY (1 << 10) +#define SX_CLEAN (1 << 11) +#define DB_CLEAN (1 << 12) +#define CB_CLEAN (1 << 13) +#define TA_BUSY (1 << 14) +#define VGT_BUSY_NO_DMA (1 << 16) +#define VGT_BUSY (1 << 17) +#define SX_BUSY (1 << 20) +#define SH_BUSY (1 << 21) +#define SPI_BUSY (1 << 22) +#define SC_BUSY (1 << 24) +#define PA_BUSY (1 << 25) +#define DB_BUSY (1 << 26) +#define CP_COHERENCY_BUSY (1 << 28) +#define CP_BUSY (1 << 29) +#define CB_BUSY (1 << 30) +#define GUI_ACTIVE (1 << 31) +#define GRBM_STATUS_SE0 0x8014 +#define GRBM_STATUS_SE1 0x8018 +#define SE_SX_CLEAN (1 << 0) +#define SE_DB_CLEAN (1 << 1) +#define SE_CB_CLEAN (1 << 2) +#define SE_TA_BUSY (1 << 25) +#define SE_SX_BUSY (1 << 26) +#define SE_SPI_BUSY (1 << 27) +#define SE_SH_BUSY (1 << 28) +#define SE_SC_BUSY (1 << 29) +#define SE_DB_BUSY (1 << 30) +#define SE_CB_BUSY (1 << 31) +/* evergreen */ +#define CG_THERMAL_CTRL 0x72c +#define TOFFSET_MASK 0x00003FE0 +#define TOFFSET_SHIFT 5 +#define CG_MULT_THERMAL_STATUS 0x740 +#define ASIC_T(x) ((x) << 16) +#define ASIC_T_MASK 0x07FF0000 +#define ASIC_T_SHIFT 16 +#define CG_TS0_STATUS 0x760 +#define TS0_ADC_DOUT_MASK 0x000003FF +#define TS0_ADC_DOUT_SHIFT 0 +/* APU */ +#define CG_THERMAL_STATUS 0x678 + +#define HDP_HOST_PATH_CNTL 0x2C00 +#define HDP_NONSURFACE_BASE 0x2C04 +#define HDP_NONSURFACE_INFO 0x2C08 +#define HDP_NONSURFACE_SIZE 0x2C0C +#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 +#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 +#define HDP_TILING_CONFIG 0x2F3C + +#define MC_SHARED_CHMAP 0x2004 +#define NOOFCHAN_SHIFT 12 +#define NOOFCHAN_MASK 0x00003000 +#define MC_SHARED_CHREMAP 0x2008 + +#define MC_SHARED_BLACKOUT_CNTL 0x20ac +#define BLACKOUT_MODE_MASK 0x00000007 + +#define MC_ARB_RAMCFG 0x2760 +#define NOOFBANK_SHIFT 0 +#define NOOFBANK_MASK 0x00000003 +#define NOOFRANK_SHIFT 2 +#define NOOFRANK_MASK 0x00000004 +#define NOOFROWS_SHIFT 3 +#define NOOFROWS_MASK 0x00000038 +#define NOOFCOLS_SHIFT 6 +#define NOOFCOLS_MASK 0x000000C0 +#define CHANSIZE_SHIFT 8 +#define CHANSIZE_MASK 0x00000100 +#define BURSTLENGTH_SHIFT 9 +#define BURSTLENGTH_MASK 0x00000200 +#define CHANSIZE_OVERRIDE (1 << 11) +#define FUS_MC_ARB_RAMCFG 0x2768 +#define MC_VM_AGP_TOP 0x2028 +#define MC_VM_AGP_BOT 0x202C +#define MC_VM_AGP_BASE 0x2030 +#define MC_VM_FB_LOCATION 0x2024 +#define MC_FUS_VM_FB_OFFSET 0x2898 +#define MC_VM_MB_L1_TLB0_CNTL 0x2234 +#define MC_VM_MB_L1_TLB1_CNTL 0x2238 +#define MC_VM_MB_L1_TLB2_CNTL 0x223C +#define MC_VM_MB_L1_TLB3_CNTL 0x2240 +#define ENABLE_L1_TLB (1 << 0) +#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) +#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) +#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) +#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) +#define EFFECTIVE_L1_TLB_SIZE(x) ((x)<<15) +#define EFFECTIVE_L1_QUEUE_SIZE(x) ((x)<<18) +#define MC_VM_MD_L1_TLB0_CNTL 0x2654 +#define MC_VM_MD_L1_TLB1_CNTL 0x2658 +#define MC_VM_MD_L1_TLB2_CNTL 0x265C +#define MC_VM_MD_L1_TLB3_CNTL 0x2698 + +#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C +#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 +#define FUS_MC_VM_MD_L1_TLB2_CNTL 0x2664 + +#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C +#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 +#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 + +#define PA_CL_ENHANCE 0x8A14 +#define CLIP_VTX_REORDER_ENA (1 << 0) +#define NUM_CLIP_SEQ(x) ((x) << 1) +#define PA_SC_ENHANCE 0x8BF0 +#define PA_SC_AA_CONFIG 0x28C04 +#define MSAA_NUM_SAMPLES_SHIFT 0 +#define MSAA_NUM_SAMPLES_MASK 0x3 +#define PA_SC_CLIPRECT_RULE 0x2820C +#define PA_SC_EDGERULE 0x28230 +#define PA_SC_FIFO_SIZE 0x8BCC +#define SC_PRIM_FIFO_SIZE(x) ((x) << 0) +#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) +#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) +#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 +#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) +#define PA_SC_LINE_STIPPLE 0x28A0C +#define PA_SU_LINE_STIPPLE_VALUE 0x8A60 +#define PA_SC_LINE_STIPPLE_STATE 0x8B10 + +#define SCRATCH_REG0 0x8500 +#define SCRATCH_REG1 0x8504 +#define SCRATCH_REG2 0x8508 +#define SCRATCH_REG3 0x850C +#define SCRATCH_REG4 0x8510 +#define SCRATCH_REG5 0x8514 +#define SCRATCH_REG6 0x8518 +#define SCRATCH_REG7 0x851C +#define SCRATCH_UMSK 0x8540 +#define SCRATCH_ADDR 0x8544 + +#define SMX_SAR_CTL0 0xA008 +#define SMX_DC_CTL0 0xA020 +#define USE_HASH_FUNCTION (1 << 0) +#define NUMBER_OF_SETS(x) ((x) << 1) +#define FLUSH_ALL_ON_EVENT (1 << 10) +#define STALL_ON_EVENT (1 << 11) +#define SMX_EVENT_CTL 0xA02C +#define ES_FLUSH_CTL(x) ((x) << 0) +#define GS_FLUSH_CTL(x) ((x) << 3) +#define ACK_FLUSH_CTL(x) ((x) << 6) +#define SYNC_FLUSH_CTL (1 << 8) + +#define SPI_CONFIG_CNTL 0x9100 +#define GPR_WRITE_PRIORITY(x) ((x) << 0) +#define SPI_CONFIG_CNTL_1 0x913C +#define VTX_DONE_DELAY(x) ((x) << 0) +#define INTERP_ONE_PRIM_PER_ROW (1 << 4) +#define SPI_INPUT_Z 0x286D8 +#define SPI_PS_IN_CONTROL_0 0x286CC +#define NUM_INTERP(x) ((x)<<0) +#define POSITION_ENA (1<<8) +#define POSITION_CENTROID (1<<9) +#define POSITION_ADDR(x) ((x)<<10) +#define PARAM_GEN(x) ((x)<<15) +#define PARAM_GEN_ADDR(x) ((x)<<19) +#define BARYC_SAMPLE_CNTL(x) ((x)<<26) +#define PERSP_GRADIENT_ENA (1<<28) +#define LINEAR_GRADIENT_ENA (1<<29) +#define POSITION_SAMPLE (1<<30) +#define BARYC_AT_SAMPLE_ENA (1<<31) + +#define SQ_CONFIG 0x8C00 +#define VC_ENABLE (1 << 0) +#define EXPORT_SRC_C (1 << 1) +#define CS_PRIO(x) ((x) << 18) +#define LS_PRIO(x) ((x) << 20) +#define HS_PRIO(x) ((x) << 22) +#define PS_PRIO(x) ((x) << 24) +#define VS_PRIO(x) ((x) << 26) +#define GS_PRIO(x) ((x) << 28) +#define ES_PRIO(x) ((x) << 30) +#define SQ_GPR_RESOURCE_MGMT_1 0x8C04 +#define NUM_PS_GPRS(x) ((x) << 0) +#define NUM_VS_GPRS(x) ((x) << 16) +#define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) +#define SQ_GPR_RESOURCE_MGMT_2 0x8C08 +#define NUM_GS_GPRS(x) ((x) << 0) +#define NUM_ES_GPRS(x) ((x) << 16) +#define SQ_GPR_RESOURCE_MGMT_3 0x8C0C +#define NUM_HS_GPRS(x) ((x) << 0) +#define NUM_LS_GPRS(x) ((x) << 16) +#define SQ_GLOBAL_GPR_RESOURCE_MGMT_1 0x8C10 +#define SQ_GLOBAL_GPR_RESOURCE_MGMT_2 0x8C14 +#define SQ_THREAD_RESOURCE_MGMT 0x8C18 +#define NUM_PS_THREADS(x) ((x) << 0) +#define NUM_VS_THREADS(x) ((x) << 8) +#define NUM_GS_THREADS(x) ((x) << 16) +#define NUM_ES_THREADS(x) ((x) << 24) +#define SQ_THREAD_RESOURCE_MGMT_2 0x8C1C +#define NUM_HS_THREADS(x) ((x) << 0) +#define NUM_LS_THREADS(x) ((x) << 8) +#define SQ_STACK_RESOURCE_MGMT_1 0x8C20 +#define NUM_PS_STACK_ENTRIES(x) ((x) << 0) +#define NUM_VS_STACK_ENTRIES(x) ((x) << 16) +#define SQ_STACK_RESOURCE_MGMT_2 0x8C24 +#define NUM_GS_STACK_ENTRIES(x) ((x) << 0) +#define NUM_ES_STACK_ENTRIES(x) ((x) << 16) +#define SQ_STACK_RESOURCE_MGMT_3 0x8C28 +#define NUM_HS_STACK_ENTRIES(x) ((x) << 0) +#define NUM_LS_STACK_ENTRIES(x) ((x) << 16) +#define SQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x8D8C +#define SQ_DYN_GPR_SIMD_LOCK_EN 0x8D94 +#define SQ_STATIC_THREAD_MGMT_1 0x8E20 +#define SQ_STATIC_THREAD_MGMT_2 0x8E24 +#define SQ_STATIC_THREAD_MGMT_3 0x8E28 +#define SQ_LDS_RESOURCE_MGMT 0x8E2C + +#define SQ_MS_FIFO_SIZES 0x8CF0 +#define CACHE_FIFO_SIZE(x) ((x) << 0) +#define FETCH_FIFO_HIWATER(x) ((x) << 8) +#define DONE_FIFO_HIWATER(x) ((x) << 16) +#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) + +#define SX_DEBUG_1 0x9058 +#define ENABLE_NEW_SMX_ADDRESS (1 << 16) +#define SX_EXPORT_BUFFER_SIZES 0x900C +#define COLOR_BUFFER_SIZE(x) ((x) << 0) +#define POSITION_BUFFER_SIZE(x) ((x) << 8) +#define SMX_BUFFER_SIZE(x) ((x) << 16) +#define SX_MEMORY_EXPORT_BASE 0x9010 +#define SX_MISC 0x28350 + +#define CB_PERF_CTR0_SEL_0 0x9A20 +#define CB_PERF_CTR0_SEL_1 0x9A24 +#define CB_PERF_CTR1_SEL_0 0x9A28 +#define CB_PERF_CTR1_SEL_1 0x9A2C +#define CB_PERF_CTR2_SEL_0 0x9A30 +#define CB_PERF_CTR2_SEL_1 0x9A34 +#define CB_PERF_CTR3_SEL_0 0x9A38 +#define CB_PERF_CTR3_SEL_1 0x9A3C + +#define TA_CNTL_AUX 0x9508 +#define DISABLE_CUBE_WRAP (1 << 0) +#define DISABLE_CUBE_ANISO (1 << 1) +#define SYNC_GRADIENT (1 << 24) +#define SYNC_WALKER (1 << 25) +#define SYNC_ALIGNER (1 << 26) + +#define TCP_CHAN_STEER_LO 0x960c +#define TCP_CHAN_STEER_HI 0x9610 + +#define VGT_CACHE_INVALIDATION 0x88C4 +#define CACHE_INVALIDATION(x) ((x) << 0) +#define VC_ONLY 0 +#define TC_ONLY 1 +#define VC_AND_TC 2 +#define AUTO_INVLD_EN(x) ((x) << 6) +#define NO_AUTO 0 +#define ES_AUTO 1 +#define GS_AUTO 2 +#define ES_AND_GS_AUTO 3 +#define VGT_GS_VERTEX_REUSE 0x88D4 +#define VGT_NUM_INSTANCES 0x8974 +#define VGT_OUT_DEALLOC_CNTL 0x28C5C +#define DEALLOC_DIST_MASK 0x0000007F +#define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 +#define VTX_REUSE_DEPTH_MASK 0x000000FF + +#define VM_CONTEXT0_CNTL 0x1410 +#define ENABLE_CONTEXT (1 << 0) +#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define VM_CONTEXT1_CNTL 0x1414 +#define VM_CONTEXT1_CNTL2 0x1434 +#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C +#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C +#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 +#define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 +#define REQUEST_TYPE(x) (((x) & 0xf) << 0) +#define RESPONSE_TYPE_MASK 0x000000F0 +#define RESPONSE_TYPE_SHIFT 4 +#define VM_L2_CNTL 0x1400 +#define ENABLE_L2_CACHE (1 << 0) +#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) +#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) +#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 14) +#define VM_L2_CNTL2 0x1404 +#define INVALIDATE_ALL_L1_TLBS (1 << 0) +#define INVALIDATE_L2_CACHE (1 << 1) +#define VM_L2_CNTL3 0x1408 +#define BANK_SELECT(x) ((x) << 0) +#define CACHE_UPDATE_MODE(x) ((x) << 6) +#define VM_L2_STATUS 0x140C +#define L2_BUSY (1 << 0) +#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC +#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC + +#define WAIT_UNTIL 0x8040 + +#define SRBM_STATUS 0x0E50 +#define SRBM_SOFT_RESET 0x0E60 +#define SRBM_SOFT_RESET_ALL_MASK 0x00FEEFA6 +#define SOFT_RESET_BIF (1 << 1) +#define SOFT_RESET_CG (1 << 2) +#define SOFT_RESET_DC (1 << 5) +#define SOFT_RESET_GRBM (1 << 8) +#define SOFT_RESET_HDP (1 << 9) +#define SOFT_RESET_IH (1 << 10) +#define SOFT_RESET_MC (1 << 11) +#define SOFT_RESET_RLC (1 << 13) +#define SOFT_RESET_ROM (1 << 14) +#define SOFT_RESET_SEM (1 << 15) +#define SOFT_RESET_VMC (1 << 17) +#define SOFT_RESET_DMA (1 << 20) +#define SOFT_RESET_TST (1 << 21) +#define SOFT_RESET_REGBB (1 << 22) +#define SOFT_RESET_ORB (1 << 23) + +/* display watermarks */ +#define DC_LB_MEMORY_SPLIT 0x6b0c +#define PRIORITY_A_CNT 0x6b18 +#define PRIORITY_MARK_MASK 0x7fff +#define PRIORITY_OFF (1 << 16) +#define PRIORITY_ALWAYS_ON (1 << 20) +#define PRIORITY_B_CNT 0x6b1c +#define PIPE0_ARBITRATION_CONTROL3 0x0bf0 +# define LATENCY_WATERMARK_MASK(x) ((x) << 16) +#define PIPE0_LATENCY_CONTROL 0x0bf4 +# define LATENCY_LOW_WATERMARK(x) ((x) << 0) +# define LATENCY_HIGH_WATERMARK(x) ((x) << 16) + +#define IH_RB_CNTL 0x3e00 +# define IH_RB_ENABLE (1 << 0) +# define IH_IB_SIZE(x) ((x) << 1) /* log2 */ +# define IH_RB_FULL_DRAIN_ENABLE (1 << 6) +# define IH_WPTR_WRITEBACK_ENABLE (1 << 8) +# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ +# define IH_WPTR_OVERFLOW_ENABLE (1 << 16) +# define IH_WPTR_OVERFLOW_CLEAR (1 << 31) +#define IH_RB_BASE 0x3e04 +#define IH_RB_RPTR 0x3e08 +#define IH_RB_WPTR 0x3e0c +# define RB_OVERFLOW (1 << 0) +# define WPTR_OFFSET_MASK 0x3fffc +#define IH_RB_WPTR_ADDR_HI 0x3e10 +#define IH_RB_WPTR_ADDR_LO 0x3e14 +#define IH_CNTL 0x3e18 +# define ENABLE_INTR (1 << 0) +# define IH_MC_SWAP(x) ((x) << 1) +# define IH_MC_SWAP_NONE 0 +# define IH_MC_SWAP_16BIT 1 +# define IH_MC_SWAP_32BIT 2 +# define IH_MC_SWAP_64BIT 3 +# define RPTR_REARM (1 << 4) +# define MC_WRREQ_CREDIT(x) ((x) << 15) +# define MC_WR_CLEAN_CNT(x) ((x) << 20) + +#define CP_INT_CNTL 0xc124 +# define CNTX_BUSY_INT_ENABLE (1 << 19) +# define CNTX_EMPTY_INT_ENABLE (1 << 20) +# define SCRATCH_INT_ENABLE (1 << 25) +# define TIME_STAMP_INT_ENABLE (1 << 26) +# define IB2_INT_ENABLE (1 << 29) +# define IB1_INT_ENABLE (1 << 30) +# define RB_INT_ENABLE (1 << 31) +#define CP_INT_STATUS 0xc128 +# define SCRATCH_INT_STAT (1 << 25) +# define TIME_STAMP_INT_STAT (1 << 26) +# define IB2_INT_STAT (1 << 29) +# define IB1_INT_STAT (1 << 30) +# define RB_INT_STAT (1 << 31) + +#define GRBM_INT_CNTL 0x8060 +# define RDERR_INT_ENABLE (1 << 0) +# define GUI_IDLE_INT_ENABLE (1 << 19) + +/* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ +#define CRTC_STATUS_FRAME_COUNT 0x6e98 + +/* 0x6bb8, 0x77b8, 0x103b8, 0x10fb8, 0x11bb8, 0x127b8 */ +#define VLINE_STATUS 0x6bb8 +# define VLINE_OCCURRED (1 << 0) +# define VLINE_ACK (1 << 4) +# define VLINE_STAT (1 << 12) +# define VLINE_INTERRUPT (1 << 16) +# define VLINE_INTERRUPT_TYPE (1 << 17) +/* 0x6bbc, 0x77bc, 0x103bc, 0x10fbc, 0x11bbc, 0x127bc */ +#define VBLANK_STATUS 0x6bbc +# define VBLANK_OCCURRED (1 << 0) +# define VBLANK_ACK (1 << 4) +# define VBLANK_STAT (1 << 12) +# define VBLANK_INTERRUPT (1 << 16) +# define VBLANK_INTERRUPT_TYPE (1 << 17) + +/* 0x6b40, 0x7740, 0x10340, 0x10f40, 0x11b40, 0x12740 */ +#define INT_MASK 0x6b40 +# define VBLANK_INT_MASK (1 << 0) +# define VLINE_INT_MASK (1 << 4) + +#define DISP_INTERRUPT_STATUS 0x60f4 +# define LB_D1_VLINE_INTERRUPT (1 << 2) +# define LB_D1_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD1_INTERRUPT (1 << 17) +# define DC_HPD1_RX_INTERRUPT (1 << 18) +# define DACA_AUTODETECT_INTERRUPT (1 << 22) +# define DACB_AUTODETECT_INTERRUPT (1 << 23) +# define DC_I2C_SW_DONE_INTERRUPT (1 << 24) +# define DC_I2C_HW_DONE_INTERRUPT (1 << 25) +#define DISP_INTERRUPT_STATUS_CONTINUE 0x60f8 +# define LB_D2_VLINE_INTERRUPT (1 << 2) +# define LB_D2_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD2_INTERRUPT (1 << 17) +# define DC_HPD2_RX_INTERRUPT (1 << 18) +# define DISP_TIMER_INTERRUPT (1 << 24) +#define DISP_INTERRUPT_STATUS_CONTINUE2 0x60fc +# define LB_D3_VLINE_INTERRUPT (1 << 2) +# define LB_D3_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD3_INTERRUPT (1 << 17) +# define DC_HPD3_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE3 0x6100 +# define LB_D4_VLINE_INTERRUPT (1 << 2) +# define LB_D4_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD4_INTERRUPT (1 << 17) +# define DC_HPD4_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE4 0x614c +# define LB_D5_VLINE_INTERRUPT (1 << 2) +# define LB_D5_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD5_INTERRUPT (1 << 17) +# define DC_HPD5_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6150 +# define LB_D6_VLINE_INTERRUPT (1 << 2) +# define LB_D6_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD6_INTERRUPT (1 << 17) +# define DC_HPD6_RX_INTERRUPT (1 << 18) + +/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ +#define GRPH_INT_STATUS 0x6858 +# define GRPH_PFLIP_INT_OCCURRED (1 << 0) +# define GRPH_PFLIP_INT_CLEAR (1 << 8) +/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ +#define GRPH_INT_CONTROL 0x685c +# define GRPH_PFLIP_INT_MASK (1 << 0) +# define GRPH_PFLIP_INT_TYPE (1 << 8) + +#define DACA_AUTODETECT_INT_CONTROL 0x66c8 +#define DACB_AUTODETECT_INT_CONTROL 0x67c8 + +#define DC_HPD1_INT_STATUS 0x601c +#define DC_HPD2_INT_STATUS 0x6028 +#define DC_HPD3_INT_STATUS 0x6034 +#define DC_HPD4_INT_STATUS 0x6040 +#define DC_HPD5_INT_STATUS 0x604c +#define DC_HPD6_INT_STATUS 0x6058 +# define DC_HPDx_INT_STATUS (1 << 0) +# define DC_HPDx_SENSE (1 << 1) +# define DC_HPDx_RX_INT_STATUS (1 << 8) + +#define DC_HPD1_INT_CONTROL 0x6020 +#define DC_HPD2_INT_CONTROL 0x602c +#define DC_HPD3_INT_CONTROL 0x6038 +#define DC_HPD4_INT_CONTROL 0x6044 +#define DC_HPD5_INT_CONTROL 0x6050 +#define DC_HPD6_INT_CONTROL 0x605c +# define DC_HPDx_INT_ACK (1 << 0) +# define DC_HPDx_INT_POLARITY (1 << 8) +# define DC_HPDx_INT_EN (1 << 16) +# define DC_HPDx_RX_INT_ACK (1 << 20) +# define DC_HPDx_RX_INT_EN (1 << 24) + +#define DC_HPD1_CONTROL 0x6024 +#define DC_HPD2_CONTROL 0x6030 +#define DC_HPD3_CONTROL 0x603c +#define DC_HPD4_CONTROL 0x6048 +#define DC_HPD5_CONTROL 0x6054 +#define DC_HPD6_CONTROL 0x6060 +# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0) +# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) +# define DC_HPDx_EN (1 << 28) + +/* ASYNC DMA */ +#define DMA_RB_RPTR 0xd008 +#define DMA_RB_WPTR 0xd00c + +#define DMA_CNTL 0xd02c +# define TRAP_ENABLE (1 << 0) +# define SEM_INCOMPLETE_INT_ENABLE (1 << 1) +# define SEM_WAIT_INT_ENABLE (1 << 2) +# define DATA_SWAP_ENABLE (1 << 3) +# define FENCE_SWAP_ENABLE (1 << 4) +# define CTXEMPTY_INT_ENABLE (1 << 28) +#define DMA_TILING_CONFIG 0xD0B8 + +#define CAYMAN_DMA1_CNTL 0xd82c + +/* async DMA packets */ +#define DMA_PACKET(cmd, t, s, n) ((((cmd) & 0xF) << 28) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((n) & 0xFFFFF) << 0)) +/* async DMA Packet types */ +#define DMA_PACKET_WRITE 0x2 +#define DMA_PACKET_COPY 0x3 +#define DMA_PACKET_INDIRECT_BUFFER 0x4 +#define DMA_PACKET_SEMAPHORE 0x5 +#define DMA_PACKET_FENCE 0x6 +#define DMA_PACKET_TRAP 0x7 +#define DMA_PACKET_SRBM_WRITE 0x9 +#define DMA_PACKET_CONSTANT_FILL 0xd +#define DMA_PACKET_NOP 0xf + +/* PCIE link stuff */ +#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */ +#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */ +# define LC_LINK_WIDTH_SHIFT 0 +# define LC_LINK_WIDTH_MASK 0x7 +# define LC_LINK_WIDTH_X0 0 +# define LC_LINK_WIDTH_X1 1 +# define LC_LINK_WIDTH_X2 2 +# define LC_LINK_WIDTH_X4 3 +# define LC_LINK_WIDTH_X8 4 +# define LC_LINK_WIDTH_X16 6 +# define LC_LINK_WIDTH_RD_SHIFT 4 +# define LC_LINK_WIDTH_RD_MASK 0x70 +# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7) +# define LC_RECONFIG_NOW (1 << 8) +# define LC_RENEGOTIATION_SUPPORT (1 << 9) +# define LC_RENEGOTIATE_EN (1 << 10) +# define LC_SHORT_RECONFIG_EN (1 << 11) +# define LC_UPCONFIGURE_SUPPORT (1 << 12) +# define LC_UPCONFIGURE_DIS (1 << 13) +#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */ +# define LC_GEN2_EN_STRAP (1 << 0) +# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1) +# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 5) +# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 6) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3 +# define LC_CURRENT_DATA_RATE (1 << 11) +# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14) +# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21) +# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23) +# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 24) +#define MM_CFGREGS_CNTL 0x544c +# define MM_WR_TO_CFG_EN (1 << 3) +#define LINK_CNTL2 0x88 /* F0 */ +# define TARGET_LINK_SPEED_MASK (0xf << 0) +# define SELECTABLE_DEEMPHASIS (1 << 6) + +/* + * PM4 + */ +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) +#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ + (((reg) >> 2) & 0xFFFF) | \ + ((n) & 0x3FFF) << 16) +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) + +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) + +#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +/* Packet 3 types */ +#define PACKET3_NOP 0x10 +#define PACKET3_SET_BASE 0x11 +#define PACKET3_CLEAR_STATE 0x12 +#define PACKET3_INDEX_BUFFER_SIZE 0x13 +#define PACKET3_DISPATCH_DIRECT 0x15 +#define PACKET3_DISPATCH_INDIRECT 0x16 +#define PACKET3_INDIRECT_BUFFER_END 0x17 +#define PACKET3_MODE_CONTROL 0x18 +#define PACKET3_SET_PREDICATION 0x20 +#define PACKET3_REG_RMW 0x21 +#define PACKET3_COND_EXEC 0x22 +#define PACKET3_PRED_EXEC 0x23 +#define PACKET3_DRAW_INDIRECT 0x24 +#define PACKET3_DRAW_INDEX_INDIRECT 0x25 +#define PACKET3_INDEX_BASE 0x26 +#define PACKET3_DRAW_INDEX_2 0x27 +#define PACKET3_CONTEXT_CONTROL 0x28 +#define PACKET3_DRAW_INDEX_OFFSET 0x29 +#define PACKET3_INDEX_TYPE 0x2A +#define PACKET3_DRAW_INDEX 0x2B +#define PACKET3_DRAW_INDEX_AUTO 0x2D +#define PACKET3_DRAW_INDEX_IMMD 0x2E +#define PACKET3_NUM_INSTANCES 0x2F +#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 +#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 +#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 +#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 +#define PACKET3_MEM_SEMAPHORE 0x39 +#define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B +#define PACKET3_WAIT_REG_MEM 0x3C +#define PACKET3_MEM_WRITE 0x3D +#define PACKET3_INDIRECT_BUFFER 0x32 +#define PACKET3_CP_DMA 0x41 +/* 1. header + * 2. SRC_ADDR_LO or DATA [31:0] + * 3. CP_SYNC [31] | SRC_SEL [30:29] | ENGINE [27] | DST_SEL [21:20] | + * SRC_ADDR_HI [7:0] + * 4. DST_ADDR_LO [31:0] + * 5. DST_ADDR_HI [7:0] + * 6. COMMAND [29:22] | BYTE_COUNT [20:0] + */ +# define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) + /* 0 - SRC_ADDR + * 1 - GDS + */ +# define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) + /* 0 - ME + * 1 - PFP + */ +# define PACKET3_CP_DMA_SRC_SEL(x) ((x) << 29) + /* 0 - SRC_ADDR + * 1 - GDS + * 2 - DATA + */ +# define PACKET3_CP_DMA_CP_SYNC (1 << 31) +/* COMMAND */ +# define PACKET3_CP_DMA_DIS_WC (1 << 21) +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_DST_SWAP(x) ((x) << 24) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_SAS (1 << 26) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_DAS (1 << 27) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_SAIC (1 << 28) +# define PACKET3_CP_DMA_CMD_DAIC (1 << 29) +#define PACKET3_SURFACE_SYNC 0x43 +# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) +# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) +# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) +# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) +# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) +# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) +# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) +# define PACKET3_DB_DEST_BASE_ENA (1 << 14) +# define PACKET3_CB8_DEST_BASE_ENA (1 << 15) +# define PACKET3_CB9_DEST_BASE_ENA (1 << 16) +# define PACKET3_CB10_DEST_BASE_ENA (1 << 17) +# define PACKET3_CB11_DEST_BASE_ENA (1 << 18) +# define PACKET3_FULL_CACHE_ENA (1 << 20) +# define PACKET3_TC_ACTION_ENA (1 << 23) +# define PACKET3_VC_ACTION_ENA (1 << 24) +# define PACKET3_CB_ACTION_ENA (1 << 25) +# define PACKET3_DB_ACTION_ENA (1 << 26) +# define PACKET3_SH_ACTION_ENA (1 << 27) +# define PACKET3_SX_ACTION_ENA (1 << 28) +#define PACKET3_ME_INITIALIZE 0x44 +#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) +#define PACKET3_COND_WRITE 0x45 +#define PACKET3_EVENT_WRITE 0x46 +#define PACKET3_EVENT_WRITE_EOP 0x47 +#define PACKET3_EVENT_WRITE_EOS 0x48 +#define PACKET3_PREAMBLE_CNTL 0x4A +# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) +# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) +#define PACKET3_RB_OFFSET 0x4B +#define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C +#define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D +#define PACKET3_ALU_PS_CONST_UPDATE 0x4E +#define PACKET3_ALU_VS_CONST_UPDATE 0x4F +#define PACKET3_ONE_REG_WRITE 0x57 +#define PACKET3_SET_CONFIG_REG 0x68 +#define PACKET3_SET_CONFIG_REG_START 0x00008000 +#define PACKET3_SET_CONFIG_REG_END 0x0000ac00 +#define PACKET3_SET_CONTEXT_REG 0x69 +#define PACKET3_SET_CONTEXT_REG_START 0x00028000 +#define PACKET3_SET_CONTEXT_REG_END 0x00029000 +#define PACKET3_SET_ALU_CONST 0x6A +/* alu const buffers only; no reg file */ +#define PACKET3_SET_BOOL_CONST 0x6B +#define PACKET3_SET_BOOL_CONST_START 0x0003a500 +#define PACKET3_SET_BOOL_CONST_END 0x0003a518 +#define PACKET3_SET_LOOP_CONST 0x6C +#define PACKET3_SET_LOOP_CONST_START 0x0003a200 +#define PACKET3_SET_LOOP_CONST_END 0x0003a500 +#define PACKET3_SET_RESOURCE 0x6D +#define PACKET3_SET_RESOURCE_START 0x00030000 +#define PACKET3_SET_RESOURCE_END 0x00038000 +#define PACKET3_SET_SAMPLER 0x6E +#define PACKET3_SET_SAMPLER_START 0x0003c000 +#define PACKET3_SET_SAMPLER_END 0x0003c600 +#define PACKET3_SET_CTL_CONST 0x6F +#define PACKET3_SET_CTL_CONST_START 0x0003cff0 +#define PACKET3_SET_CTL_CONST_END 0x0003ff0c +#define PACKET3_SET_RESOURCE_OFFSET 0x70 +#define PACKET3_SET_ALU_CONST_VS 0x71 +#define PACKET3_SET_ALU_CONST_DI 0x72 +#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 +#define PACKET3_SET_RESOURCE_INDIRECT 0x74 +#define PACKET3_SET_APPEND_CNT 0x75 + +#define SQ_RESOURCE_CONSTANT_WORD7_0 0x3001c +#define S__SQ_CONSTANT_TYPE(x) (((x) & 3) << 30) +#define G__SQ_CONSTANT_TYPE(x) (((x) >> 30) & 3) +#define SQ_TEX_VTX_INVALID_TEXTURE 0x0 +#define SQ_TEX_VTX_INVALID_BUFFER 0x1 +#define SQ_TEX_VTX_VALID_TEXTURE 0x2 +#define SQ_TEX_VTX_VALID_BUFFER 0x3 + +#define VGT_VTX_VECT_EJECT_REG 0x88b0 + +#define SQ_CONST_MEM_BASE 0x8df8 + +#define SQ_ESGS_RING_BASE 0x8c40 +#define SQ_ESGS_RING_SIZE 0x8c44 +#define SQ_GSVS_RING_BASE 0x8c48 +#define SQ_GSVS_RING_SIZE 0x8c4c +#define SQ_ESTMP_RING_BASE 0x8c50 +#define SQ_ESTMP_RING_SIZE 0x8c54 +#define SQ_GSTMP_RING_BASE 0x8c58 +#define SQ_GSTMP_RING_SIZE 0x8c5c +#define SQ_VSTMP_RING_BASE 0x8c60 +#define SQ_VSTMP_RING_SIZE 0x8c64 +#define SQ_PSTMP_RING_BASE 0x8c68 +#define SQ_PSTMP_RING_SIZE 0x8c6c +#define SQ_LSTMP_RING_BASE 0x8e10 +#define SQ_LSTMP_RING_SIZE 0x8e14 +#define SQ_HSTMP_RING_BASE 0x8e18 +#define SQ_HSTMP_RING_SIZE 0x8e1c +#define VGT_TF_RING_SIZE 0x8988 + +#define SQ_ESGS_RING_ITEMSIZE 0x28900 +#define SQ_GSVS_RING_ITEMSIZE 0x28904 +#define SQ_ESTMP_RING_ITEMSIZE 0x28908 +#define SQ_GSTMP_RING_ITEMSIZE 0x2890c +#define SQ_VSTMP_RING_ITEMSIZE 0x28910 +#define SQ_PSTMP_RING_ITEMSIZE 0x28914 +#define SQ_LSTMP_RING_ITEMSIZE 0x28830 +#define SQ_HSTMP_RING_ITEMSIZE 0x28834 + +#define SQ_GS_VERT_ITEMSIZE 0x2891c +#define SQ_GS_VERT_ITEMSIZE_1 0x28920 +#define SQ_GS_VERT_ITEMSIZE_2 0x28924 +#define SQ_GS_VERT_ITEMSIZE_3 0x28928 +#define SQ_GSVS_RING_OFFSET_1 0x2892c +#define SQ_GSVS_RING_OFFSET_2 0x28930 +#define SQ_GSVS_RING_OFFSET_3 0x28934 + +#define SQ_ALU_CONST_BUFFER_SIZE_PS_0 0x28140 +#define SQ_ALU_CONST_BUFFER_SIZE_HS_0 0x28f80 + +#define SQ_ALU_CONST_CACHE_PS_0 0x28940 +#define SQ_ALU_CONST_CACHE_PS_1 0x28944 +#define SQ_ALU_CONST_CACHE_PS_2 0x28948 +#define SQ_ALU_CONST_CACHE_PS_3 0x2894c +#define SQ_ALU_CONST_CACHE_PS_4 0x28950 +#define SQ_ALU_CONST_CACHE_PS_5 0x28954 +#define SQ_ALU_CONST_CACHE_PS_6 0x28958 +#define SQ_ALU_CONST_CACHE_PS_7 0x2895c +#define SQ_ALU_CONST_CACHE_PS_8 0x28960 +#define SQ_ALU_CONST_CACHE_PS_9 0x28964 +#define SQ_ALU_CONST_CACHE_PS_10 0x28968 +#define SQ_ALU_CONST_CACHE_PS_11 0x2896c +#define SQ_ALU_CONST_CACHE_PS_12 0x28970 +#define SQ_ALU_CONST_CACHE_PS_13 0x28974 +#define SQ_ALU_CONST_CACHE_PS_14 0x28978 +#define SQ_ALU_CONST_CACHE_PS_15 0x2897c +#define SQ_ALU_CONST_CACHE_VS_0 0x28980 +#define SQ_ALU_CONST_CACHE_VS_1 0x28984 +#define SQ_ALU_CONST_CACHE_VS_2 0x28988 +#define SQ_ALU_CONST_CACHE_VS_3 0x2898c +#define SQ_ALU_CONST_CACHE_VS_4 0x28990 +#define SQ_ALU_CONST_CACHE_VS_5 0x28994 +#define SQ_ALU_CONST_CACHE_VS_6 0x28998 +#define SQ_ALU_CONST_CACHE_VS_7 0x2899c +#define SQ_ALU_CONST_CACHE_VS_8 0x289a0 +#define SQ_ALU_CONST_CACHE_VS_9 0x289a4 +#define SQ_ALU_CONST_CACHE_VS_10 0x289a8 +#define SQ_ALU_CONST_CACHE_VS_11 0x289ac +#define SQ_ALU_CONST_CACHE_VS_12 0x289b0 +#define SQ_ALU_CONST_CACHE_VS_13 0x289b4 +#define SQ_ALU_CONST_CACHE_VS_14 0x289b8 +#define SQ_ALU_CONST_CACHE_VS_15 0x289bc +#define SQ_ALU_CONST_CACHE_GS_0 0x289c0 +#define SQ_ALU_CONST_CACHE_GS_1 0x289c4 +#define SQ_ALU_CONST_CACHE_GS_2 0x289c8 +#define SQ_ALU_CONST_CACHE_GS_3 0x289cc +#define SQ_ALU_CONST_CACHE_GS_4 0x289d0 +#define SQ_ALU_CONST_CACHE_GS_5 0x289d4 +#define SQ_ALU_CONST_CACHE_GS_6 0x289d8 +#define SQ_ALU_CONST_CACHE_GS_7 0x289dc +#define SQ_ALU_CONST_CACHE_GS_8 0x289e0 +#define SQ_ALU_CONST_CACHE_GS_9 0x289e4 +#define SQ_ALU_CONST_CACHE_GS_10 0x289e8 +#define SQ_ALU_CONST_CACHE_GS_11 0x289ec +#define SQ_ALU_CONST_CACHE_GS_12 0x289f0 +#define SQ_ALU_CONST_CACHE_GS_13 0x289f4 +#define SQ_ALU_CONST_CACHE_GS_14 0x289f8 +#define SQ_ALU_CONST_CACHE_GS_15 0x289fc +#define SQ_ALU_CONST_CACHE_HS_0 0x28f00 +#define SQ_ALU_CONST_CACHE_HS_1 0x28f04 +#define SQ_ALU_CONST_CACHE_HS_2 0x28f08 +#define SQ_ALU_CONST_CACHE_HS_3 0x28f0c +#define SQ_ALU_CONST_CACHE_HS_4 0x28f10 +#define SQ_ALU_CONST_CACHE_HS_5 0x28f14 +#define SQ_ALU_CONST_CACHE_HS_6 0x28f18 +#define SQ_ALU_CONST_CACHE_HS_7 0x28f1c +#define SQ_ALU_CONST_CACHE_HS_8 0x28f20 +#define SQ_ALU_CONST_CACHE_HS_9 0x28f24 +#define SQ_ALU_CONST_CACHE_HS_10 0x28f28 +#define SQ_ALU_CONST_CACHE_HS_11 0x28f2c +#define SQ_ALU_CONST_CACHE_HS_12 0x28f30 +#define SQ_ALU_CONST_CACHE_HS_13 0x28f34 +#define SQ_ALU_CONST_CACHE_HS_14 0x28f38 +#define SQ_ALU_CONST_CACHE_HS_15 0x28f3c +#define SQ_ALU_CONST_CACHE_LS_0 0x28f40 +#define SQ_ALU_CONST_CACHE_LS_1 0x28f44 +#define SQ_ALU_CONST_CACHE_LS_2 0x28f48 +#define SQ_ALU_CONST_CACHE_LS_3 0x28f4c +#define SQ_ALU_CONST_CACHE_LS_4 0x28f50 +#define SQ_ALU_CONST_CACHE_LS_5 0x28f54 +#define SQ_ALU_CONST_CACHE_LS_6 0x28f58 +#define SQ_ALU_CONST_CACHE_LS_7 0x28f5c +#define SQ_ALU_CONST_CACHE_LS_8 0x28f60 +#define SQ_ALU_CONST_CACHE_LS_9 0x28f64 +#define SQ_ALU_CONST_CACHE_LS_10 0x28f68 +#define SQ_ALU_CONST_CACHE_LS_11 0x28f6c +#define SQ_ALU_CONST_CACHE_LS_12 0x28f70 +#define SQ_ALU_CONST_CACHE_LS_13 0x28f74 +#define SQ_ALU_CONST_CACHE_LS_14 0x28f78 +#define SQ_ALU_CONST_CACHE_LS_15 0x28f7c + +#define PA_SC_SCREEN_SCISSOR_TL 0x28030 +#define PA_SC_GENERIC_SCISSOR_TL 0x28240 +#define PA_SC_WINDOW_SCISSOR_TL 0x28204 + +#define VGT_PRIMITIVE_TYPE 0x8958 +#define VGT_INDEX_TYPE 0x895C + +#define VGT_NUM_INDICES 0x8970 + +#define VGT_COMPUTE_DIM_X 0x8990 +#define VGT_COMPUTE_DIM_Y 0x8994 +#define VGT_COMPUTE_DIM_Z 0x8998 +#define VGT_COMPUTE_START_X 0x899C +#define VGT_COMPUTE_START_Y 0x89A0 +#define VGT_COMPUTE_START_Z 0x89A4 +#define VGT_COMPUTE_INDEX 0x89A8 +#define VGT_COMPUTE_THREAD_GROUP_SIZE 0x89AC +#define VGT_HS_OFFCHIP_PARAM 0x89B0 + +#define DB_DEBUG 0x9830 +#define DB_DEBUG2 0x9834 +#define DB_DEBUG3 0x9838 +#define DB_DEBUG4 0x983C +#define DB_WATERMARKS 0x9854 +#define DB_DEPTH_CONTROL 0x28800 +#define R_028800_DB_DEPTH_CONTROL 0x028800 +#define S_028800_STENCIL_ENABLE(x) (((x) & 0x1) << 0) +#define G_028800_STENCIL_ENABLE(x) (((x) >> 0) & 0x1) +#define C_028800_STENCIL_ENABLE 0xFFFFFFFE +#define S_028800_Z_ENABLE(x) (((x) & 0x1) << 1) +#define G_028800_Z_ENABLE(x) (((x) >> 1) & 0x1) +#define C_028800_Z_ENABLE 0xFFFFFFFD +#define S_028800_Z_WRITE_ENABLE(x) (((x) & 0x1) << 2) +#define G_028800_Z_WRITE_ENABLE(x) (((x) >> 2) & 0x1) +#define C_028800_Z_WRITE_ENABLE 0xFFFFFFFB +#define S_028800_ZFUNC(x) (((x) & 0x7) << 4) +#define G_028800_ZFUNC(x) (((x) >> 4) & 0x7) +#define C_028800_ZFUNC 0xFFFFFF8F +#define S_028800_BACKFACE_ENABLE(x) (((x) & 0x1) << 7) +#define G_028800_BACKFACE_ENABLE(x) (((x) >> 7) & 0x1) +#define C_028800_BACKFACE_ENABLE 0xFFFFFF7F +#define S_028800_STENCILFUNC(x) (((x) & 0x7) << 8) +#define G_028800_STENCILFUNC(x) (((x) >> 8) & 0x7) +#define C_028800_STENCILFUNC 0xFFFFF8FF +#define V_028800_STENCILFUNC_NEVER 0x00000000 +#define V_028800_STENCILFUNC_LESS 0x00000001 +#define V_028800_STENCILFUNC_EQUAL 0x00000002 +#define V_028800_STENCILFUNC_LEQUAL 0x00000003 +#define V_028800_STENCILFUNC_GREATER 0x00000004 +#define V_028800_STENCILFUNC_NOTEQUAL 0x00000005 +#define V_028800_STENCILFUNC_GEQUAL 0x00000006 +#define V_028800_STENCILFUNC_ALWAYS 0x00000007 +#define S_028800_STENCILFAIL(x) (((x) & 0x7) << 11) +#define G_028800_STENCILFAIL(x) (((x) >> 11) & 0x7) +#define C_028800_STENCILFAIL 0xFFFFC7FF +#define V_028800_STENCIL_KEEP 0x00000000 +#define V_028800_STENCIL_ZERO 0x00000001 +#define V_028800_STENCIL_REPLACE 0x00000002 +#define V_028800_STENCIL_INCR 0x00000003 +#define V_028800_STENCIL_DECR 0x00000004 +#define V_028800_STENCIL_INVERT 0x00000005 +#define V_028800_STENCIL_INCR_WRAP 0x00000006 +#define V_028800_STENCIL_DECR_WRAP 0x00000007 +#define S_028800_STENCILZPASS(x) (((x) & 0x7) << 14) +#define G_028800_STENCILZPASS(x) (((x) >> 14) & 0x7) +#define C_028800_STENCILZPASS 0xFFFE3FFF +#define S_028800_STENCILZFAIL(x) (((x) & 0x7) << 17) +#define G_028800_STENCILZFAIL(x) (((x) >> 17) & 0x7) +#define C_028800_STENCILZFAIL 0xFFF1FFFF +#define S_028800_STENCILFUNC_BF(x) (((x) & 0x7) << 20) +#define G_028800_STENCILFUNC_BF(x) (((x) >> 20) & 0x7) +#define C_028800_STENCILFUNC_BF 0xFF8FFFFF +#define S_028800_STENCILFAIL_BF(x) (((x) & 0x7) << 23) +#define G_028800_STENCILFAIL_BF(x) (((x) >> 23) & 0x7) +#define C_028800_STENCILFAIL_BF 0xFC7FFFFF +#define S_028800_STENCILZPASS_BF(x) (((x) & 0x7) << 26) +#define G_028800_STENCILZPASS_BF(x) (((x) >> 26) & 0x7) +#define C_028800_STENCILZPASS_BF 0xE3FFFFFF +#define S_028800_STENCILZFAIL_BF(x) (((x) & 0x7) << 29) +#define G_028800_STENCILZFAIL_BF(x) (((x) >> 29) & 0x7) +#define C_028800_STENCILZFAIL_BF 0x1FFFFFFF +#define DB_DEPTH_VIEW 0x28008 +#define R_028008_DB_DEPTH_VIEW 0x00028008 +#define S_028008_SLICE_START(x) (((x) & 0x7FF) << 0) +#define G_028008_SLICE_START(x) (((x) >> 0) & 0x7FF) +#define C_028008_SLICE_START 0xFFFFF800 +#define S_028008_SLICE_MAX(x) (((x) & 0x7FF) << 13) +#define G_028008_SLICE_MAX(x) (((x) >> 13) & 0x7FF) +#define C_028008_SLICE_MAX 0xFF001FFF +#define DB_HTILE_DATA_BASE 0x28014 +#define DB_HTILE_SURFACE 0x28abc +#define S_028ABC_HTILE_WIDTH(x) (((x) & 0x1) << 0) +#define G_028ABC_HTILE_WIDTH(x) (((x) >> 0) & 0x1) +#define C_028ABC_HTILE_WIDTH 0xFFFFFFFE +#define S_028ABC_HTILE_HEIGHT(x) (((x) & 0x1) << 1) +#define G_028ABC_HTILE_HEIGHT(x) (((x) >> 1) & 0x1) +#define C_028ABC_HTILE_HEIGHT 0xFFFFFFFD +#define G_028ABC_LINEAR(x) (((x) >> 2) & 0x1) +#define DB_Z_INFO 0x28040 +# define Z_ARRAY_MODE(x) ((x) << 4) +# define DB_TILE_SPLIT(x) (((x) & 0x7) << 8) +# define DB_NUM_BANKS(x) (((x) & 0x3) << 12) +# define DB_BANK_WIDTH(x) (((x) & 0x3) << 16) +# define DB_BANK_HEIGHT(x) (((x) & 0x3) << 20) +# define DB_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 24) +#define R_028040_DB_Z_INFO 0x028040 +#define S_028040_FORMAT(x) (((x) & 0x3) << 0) +#define G_028040_FORMAT(x) (((x) >> 0) & 0x3) +#define C_028040_FORMAT 0xFFFFFFFC +#define V_028040_Z_INVALID 0x00000000 +#define V_028040_Z_16 0x00000001 +#define V_028040_Z_24 0x00000002 +#define V_028040_Z_32_FLOAT 0x00000003 +#define S_028040_ARRAY_MODE(x) (((x) & 0xF) << 4) +#define G_028040_ARRAY_MODE(x) (((x) >> 4) & 0xF) +#define C_028040_ARRAY_MODE 0xFFFFFF0F +#define S_028040_READ_SIZE(x) (((x) & 0x1) << 28) +#define G_028040_READ_SIZE(x) (((x) >> 28) & 0x1) +#define C_028040_READ_SIZE 0xEFFFFFFF +#define S_028040_TILE_SURFACE_ENABLE(x) (((x) & 0x1) << 29) +#define G_028040_TILE_SURFACE_ENABLE(x) (((x) >> 29) & 0x1) +#define C_028040_TILE_SURFACE_ENABLE 0xDFFFFFFF +#define S_028040_ZRANGE_PRECISION(x) (((x) & 0x1) << 31) +#define G_028040_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1) +#define C_028040_ZRANGE_PRECISION 0x7FFFFFFF +#define S_028040_TILE_SPLIT(x) (((x) & 0x7) << 8) +#define G_028040_TILE_SPLIT(x) (((x) >> 8) & 0x7) +#define S_028040_NUM_BANKS(x) (((x) & 0x3) << 12) +#define G_028040_NUM_BANKS(x) (((x) >> 12) & 0x3) +#define S_028040_BANK_WIDTH(x) (((x) & 0x3) << 16) +#define G_028040_BANK_WIDTH(x) (((x) >> 16) & 0x3) +#define S_028040_BANK_HEIGHT(x) (((x) & 0x3) << 20) +#define G_028040_BANK_HEIGHT(x) (((x) >> 20) & 0x3) +#define S_028040_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 24) +#define G_028040_MACRO_TILE_ASPECT(x) (((x) >> 24) & 0x3) +#define DB_STENCIL_INFO 0x28044 +#define R_028044_DB_STENCIL_INFO 0x028044 +#define S_028044_FORMAT(x) (((x) & 0x1) << 0) +#define G_028044_FORMAT(x) (((x) >> 0) & 0x1) +#define C_028044_FORMAT 0xFFFFFFFE +#define V_028044_STENCIL_INVALID 0 +#define V_028044_STENCIL_8 1 +#define G_028044_TILE_SPLIT(x) (((x) >> 8) & 0x7) +#define DB_Z_READ_BASE 0x28048 +#define DB_STENCIL_READ_BASE 0x2804c +#define DB_Z_WRITE_BASE 0x28050 +#define DB_STENCIL_WRITE_BASE 0x28054 +#define DB_DEPTH_SIZE 0x28058 +#define R_028058_DB_DEPTH_SIZE 0x028058 +#define S_028058_PITCH_TILE_MAX(x) (((x) & 0x7FF) << 0) +#define G_028058_PITCH_TILE_MAX(x) (((x) >> 0) & 0x7FF) +#define C_028058_PITCH_TILE_MAX 0xFFFFF800 +#define S_028058_HEIGHT_TILE_MAX(x) (((x) & 0x7FF) << 11) +#define G_028058_HEIGHT_TILE_MAX(x) (((x) >> 11) & 0x7FF) +#define C_028058_HEIGHT_TILE_MAX 0xFFC007FF +#define R_02805C_DB_DEPTH_SLICE 0x02805C +#define S_02805C_SLICE_TILE_MAX(x) (((x) & 0x3FFFFF) << 0) +#define G_02805C_SLICE_TILE_MAX(x) (((x) >> 0) & 0x3FFFFF) +#define C_02805C_SLICE_TILE_MAX 0xFFC00000 + +#define SQ_PGM_START_PS 0x28840 +#define SQ_PGM_START_VS 0x2885c +#define SQ_PGM_START_GS 0x28874 +#define SQ_PGM_START_ES 0x2888c +#define SQ_PGM_START_FS 0x288a4 +#define SQ_PGM_START_HS 0x288b8 +#define SQ_PGM_START_LS 0x288d0 + +#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 +#define VGT_STRMOUT_CONFIG 0x28b94 +#define VGT_STRMOUT_BUFFER_CONFIG 0x28b98 + +#define CB_TARGET_MASK 0x28238 +#define CB_SHADER_MASK 0x2823c + +#define GDS_ADDR_BASE 0x28720 + +#define CB_IMMED0_BASE 0x28b9c +#define CB_IMMED1_BASE 0x28ba0 +#define CB_IMMED2_BASE 0x28ba4 +#define CB_IMMED3_BASE 0x28ba8 +#define CB_IMMED4_BASE 0x28bac +#define CB_IMMED5_BASE 0x28bb0 +#define CB_IMMED6_BASE 0x28bb4 +#define CB_IMMED7_BASE 0x28bb8 +#define CB_IMMED8_BASE 0x28bbc +#define CB_IMMED9_BASE 0x28bc0 +#define CB_IMMED10_BASE 0x28bc4 +#define CB_IMMED11_BASE 0x28bc8 + +/* all 12 CB blocks have these regs */ +#define CB_COLOR0_BASE 0x28c60 +#define CB_COLOR0_PITCH 0x28c64 +#define CB_COLOR0_SLICE 0x28c68 +#define CB_COLOR0_VIEW 0x28c6c +#define R_028C6C_CB_COLOR0_VIEW 0x00028C6C +#define S_028C6C_SLICE_START(x) (((x) & 0x7FF) << 0) +#define G_028C6C_SLICE_START(x) (((x) >> 0) & 0x7FF) +#define C_028C6C_SLICE_START 0xFFFFF800 +#define S_028C6C_SLICE_MAX(x) (((x) & 0x7FF) << 13) +#define G_028C6C_SLICE_MAX(x) (((x) >> 13) & 0x7FF) +#define C_028C6C_SLICE_MAX 0xFF001FFF +#define R_028C70_CB_COLOR0_INFO 0x028C70 +#define S_028C70_ENDIAN(x) (((x) & 0x3) << 0) +#define G_028C70_ENDIAN(x) (((x) >> 0) & 0x3) +#define C_028C70_ENDIAN 0xFFFFFFFC +#define S_028C70_FORMAT(x) (((x) & 0x3F) << 2) +#define G_028C70_FORMAT(x) (((x) >> 2) & 0x3F) +#define C_028C70_FORMAT 0xFFFFFF03 +#define V_028C70_COLOR_INVALID 0x00000000 +#define V_028C70_COLOR_8 0x00000001 +#define V_028C70_COLOR_4_4 0x00000002 +#define V_028C70_COLOR_3_3_2 0x00000003 +#define V_028C70_COLOR_16 0x00000005 +#define V_028C70_COLOR_16_FLOAT 0x00000006 +#define V_028C70_COLOR_8_8 0x00000007 +#define V_028C70_COLOR_5_6_5 0x00000008 +#define V_028C70_COLOR_6_5_5 0x00000009 +#define V_028C70_COLOR_1_5_5_5 0x0000000A +#define V_028C70_COLOR_4_4_4_4 0x0000000B +#define V_028C70_COLOR_5_5_5_1 0x0000000C +#define V_028C70_COLOR_32 0x0000000D +#define V_028C70_COLOR_32_FLOAT 0x0000000E +#define V_028C70_COLOR_16_16 0x0000000F +#define V_028C70_COLOR_16_16_FLOAT 0x00000010 +#define V_028C70_COLOR_8_24 0x00000011 +#define V_028C70_COLOR_8_24_FLOAT 0x00000012 +#define V_028C70_COLOR_24_8 0x00000013 +#define V_028C70_COLOR_24_8_FLOAT 0x00000014 +#define V_028C70_COLOR_10_11_11 0x00000015 +#define V_028C70_COLOR_10_11_11_FLOAT 0x00000016 +#define V_028C70_COLOR_11_11_10 0x00000017 +#define V_028C70_COLOR_11_11_10_FLOAT 0x00000018 +#define V_028C70_COLOR_2_10_10_10 0x00000019 +#define V_028C70_COLOR_8_8_8_8 0x0000001A +#define V_028C70_COLOR_10_10_10_2 0x0000001B +#define V_028C70_COLOR_X24_8_32_FLOAT 0x0000001C +#define V_028C70_COLOR_32_32 0x0000001D +#define V_028C70_COLOR_32_32_FLOAT 0x0000001E +#define V_028C70_COLOR_16_16_16_16 0x0000001F +#define V_028C70_COLOR_16_16_16_16_FLOAT 0x00000020 +#define V_028C70_COLOR_32_32_32_32 0x00000022 +#define V_028C70_COLOR_32_32_32_32_FLOAT 0x00000023 +#define V_028C70_COLOR_32_32_32_FLOAT 0x00000030 +#define S_028C70_ARRAY_MODE(x) (((x) & 0xF) << 8) +#define G_028C70_ARRAY_MODE(x) (((x) >> 8) & 0xF) +#define C_028C70_ARRAY_MODE 0xFFFFF0FF +#define V_028C70_ARRAY_LINEAR_GENERAL 0x00000000 +#define V_028C70_ARRAY_LINEAR_ALIGNED 0x00000001 +#define V_028C70_ARRAY_1D_TILED_THIN1 0x00000002 +#define V_028C70_ARRAY_2D_TILED_THIN1 0x00000004 +#define S_028C70_NUMBER_TYPE(x) (((x) & 0x7) << 12) +#define G_028C70_NUMBER_TYPE(x) (((x) >> 12) & 0x7) +#define C_028C70_NUMBER_TYPE 0xFFFF8FFF +#define V_028C70_NUMBER_UNORM 0x00000000 +#define V_028C70_NUMBER_SNORM 0x00000001 +#define V_028C70_NUMBER_USCALED 0x00000002 +#define V_028C70_NUMBER_SSCALED 0x00000003 +#define V_028C70_NUMBER_UINT 0x00000004 +#define V_028C70_NUMBER_SINT 0x00000005 +#define V_028C70_NUMBER_SRGB 0x00000006 +#define V_028C70_NUMBER_FLOAT 0x00000007 +#define S_028C70_COMP_SWAP(x) (((x) & 0x3) << 15) +#define G_028C70_COMP_SWAP(x) (((x) >> 15) & 0x3) +#define C_028C70_COMP_SWAP 0xFFFE7FFF +#define V_028C70_SWAP_STD 0x00000000 +#define V_028C70_SWAP_ALT 0x00000001 +#define V_028C70_SWAP_STD_REV 0x00000002 +#define V_028C70_SWAP_ALT_REV 0x00000003 +#define S_028C70_FAST_CLEAR(x) (((x) & 0x1) << 17) +#define G_028C70_FAST_CLEAR(x) (((x) >> 17) & 0x1) +#define C_028C70_FAST_CLEAR 0xFFFDFFFF +#define S_028C70_COMPRESSION(x) (((x) & 0x3) << 18) +#define G_028C70_COMPRESSION(x) (((x) >> 18) & 0x3) +#define C_028C70_COMPRESSION 0xFFF3FFFF +#define S_028C70_BLEND_CLAMP(x) (((x) & 0x1) << 19) +#define G_028C70_BLEND_CLAMP(x) (((x) >> 19) & 0x1) +#define C_028C70_BLEND_CLAMP 0xFFF7FFFF +#define S_028C70_BLEND_BYPASS(x) (((x) & 0x1) << 20) +#define G_028C70_BLEND_BYPASS(x) (((x) >> 20) & 0x1) +#define C_028C70_BLEND_BYPASS 0xFFEFFFFF +#define S_028C70_SIMPLE_FLOAT(x) (((x) & 0x1) << 21) +#define G_028C70_SIMPLE_FLOAT(x) (((x) >> 21) & 0x1) +#define C_028C70_SIMPLE_FLOAT 0xFFDFFFFF +#define S_028C70_ROUND_MODE(x) (((x) & 0x1) << 22) +#define G_028C70_ROUND_MODE(x) (((x) >> 22) & 0x1) +#define C_028C70_ROUND_MODE 0xFFBFFFFF +#define S_028C70_TILE_COMPACT(x) (((x) & 0x1) << 23) +#define G_028C70_TILE_COMPACT(x) (((x) >> 23) & 0x1) +#define C_028C70_TILE_COMPACT 0xFF7FFFFF +#define S_028C70_SOURCE_FORMAT(x) (((x) & 0x3) << 24) +#define G_028C70_SOURCE_FORMAT(x) (((x) >> 24) & 0x3) +#define C_028C70_SOURCE_FORMAT 0xFCFFFFFF +#define V_028C70_EXPORT_4C_32BPC 0x0 +#define V_028C70_EXPORT_4C_16BPC 0x1 +#define V_028C70_EXPORT_2C_32BPC 0x2 /* Do not use */ +#define S_028C70_RAT(x) (((x) & 0x1) << 26) +#define G_028C70_RAT(x) (((x) >> 26) & 0x1) +#define C_028C70_RAT 0xFBFFFFFF +#define S_028C70_RESOURCE_TYPE(x) (((x) & 0x7) << 27) +#define G_028C70_RESOURCE_TYPE(x) (((x) >> 27) & 0x7) +#define C_028C70_RESOURCE_TYPE 0xC7FFFFFF + +#define CB_COLOR0_INFO 0x28c70 +# define CB_FORMAT(x) ((x) << 2) +# define CB_ARRAY_MODE(x) ((x) << 8) +# define ARRAY_LINEAR_GENERAL 0 +# define ARRAY_LINEAR_ALIGNED 1 +# define ARRAY_1D_TILED_THIN1 2 +# define ARRAY_2D_TILED_THIN1 4 +# define CB_SOURCE_FORMAT(x) ((x) << 24) +# define CB_SF_EXPORT_FULL 0 +# define CB_SF_EXPORT_NORM 1 +#define R_028C74_CB_COLOR0_ATTRIB 0x028C74 +#define S_028C74_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 4) +#define G_028C74_NON_DISP_TILING_ORDER(x) (((x) >> 4) & 0x1) +#define C_028C74_NON_DISP_TILING_ORDER 0xFFFFFFEF +#define S_028C74_TILE_SPLIT(x) (((x) & 0xf) << 5) +#define G_028C74_TILE_SPLIT(x) (((x) >> 5) & 0xf) +#define S_028C74_NUM_BANKS(x) (((x) & 0x3) << 10) +#define G_028C74_NUM_BANKS(x) (((x) >> 10) & 0x3) +#define S_028C74_BANK_WIDTH(x) (((x) & 0x3) << 13) +#define G_028C74_BANK_WIDTH(x) (((x) >> 13) & 0x3) +#define S_028C74_BANK_HEIGHT(x) (((x) & 0x3) << 16) +#define G_028C74_BANK_HEIGHT(x) (((x) >> 16) & 0x3) +#define S_028C74_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 19) +#define G_028C74_MACRO_TILE_ASPECT(x) (((x) >> 19) & 0x3) +#define CB_COLOR0_ATTRIB 0x28c74 +# define CB_TILE_SPLIT(x) (((x) & 0x7) << 5) +# define ADDR_SURF_TILE_SPLIT_64B 0 +# define ADDR_SURF_TILE_SPLIT_128B 1 +# define ADDR_SURF_TILE_SPLIT_256B 2 +# define ADDR_SURF_TILE_SPLIT_512B 3 +# define ADDR_SURF_TILE_SPLIT_1KB 4 +# define ADDR_SURF_TILE_SPLIT_2KB 5 +# define ADDR_SURF_TILE_SPLIT_4KB 6 +# define CB_NUM_BANKS(x) (((x) & 0x3) << 10) +# define ADDR_SURF_2_BANK 0 +# define ADDR_SURF_4_BANK 1 +# define ADDR_SURF_8_BANK 2 +# define ADDR_SURF_16_BANK 3 +# define CB_BANK_WIDTH(x) (((x) & 0x3) << 13) +# define ADDR_SURF_BANK_WIDTH_1 0 +# define ADDR_SURF_BANK_WIDTH_2 1 +# define ADDR_SURF_BANK_WIDTH_4 2 +# define ADDR_SURF_BANK_WIDTH_8 3 +# define CB_BANK_HEIGHT(x) (((x) & 0x3) << 16) +# define ADDR_SURF_BANK_HEIGHT_1 0 +# define ADDR_SURF_BANK_HEIGHT_2 1 +# define ADDR_SURF_BANK_HEIGHT_4 2 +# define ADDR_SURF_BANK_HEIGHT_8 3 +# define CB_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 19) +#define CB_COLOR0_DIM 0x28c78 +/* only CB0-7 blocks have these regs */ +#define CB_COLOR0_CMASK 0x28c7c +#define CB_COLOR0_CMASK_SLICE 0x28c80 +#define CB_COLOR0_FMASK 0x28c84 +#define CB_COLOR0_FMASK_SLICE 0x28c88 +#define CB_COLOR0_CLEAR_WORD0 0x28c8c +#define CB_COLOR0_CLEAR_WORD1 0x28c90 +#define CB_COLOR0_CLEAR_WORD2 0x28c94 +#define CB_COLOR0_CLEAR_WORD3 0x28c98 + +#define CB_COLOR1_BASE 0x28c9c +#define CB_COLOR2_BASE 0x28cd8 +#define CB_COLOR3_BASE 0x28d14 +#define CB_COLOR4_BASE 0x28d50 +#define CB_COLOR5_BASE 0x28d8c +#define CB_COLOR6_BASE 0x28dc8 +#define CB_COLOR7_BASE 0x28e04 +#define CB_COLOR8_BASE 0x28e40 +#define CB_COLOR9_BASE 0x28e5c +#define CB_COLOR10_BASE 0x28e78 +#define CB_COLOR11_BASE 0x28e94 + +#define CB_COLOR1_PITCH 0x28ca0 +#define CB_COLOR2_PITCH 0x28cdc +#define CB_COLOR3_PITCH 0x28d18 +#define CB_COLOR4_PITCH 0x28d54 +#define CB_COLOR5_PITCH 0x28d90 +#define CB_COLOR6_PITCH 0x28dcc +#define CB_COLOR7_PITCH 0x28e08 +#define CB_COLOR8_PITCH 0x28e44 +#define CB_COLOR9_PITCH 0x28e60 +#define CB_COLOR10_PITCH 0x28e7c +#define CB_COLOR11_PITCH 0x28e98 + +#define CB_COLOR1_SLICE 0x28ca4 +#define CB_COLOR2_SLICE 0x28ce0 +#define CB_COLOR3_SLICE 0x28d1c +#define CB_COLOR4_SLICE 0x28d58 +#define CB_COLOR5_SLICE 0x28d94 +#define CB_COLOR6_SLICE 0x28dd0 +#define CB_COLOR7_SLICE 0x28e0c +#define CB_COLOR8_SLICE 0x28e48 +#define CB_COLOR9_SLICE 0x28e64 +#define CB_COLOR10_SLICE 0x28e80 +#define CB_COLOR11_SLICE 0x28e9c + +#define CB_COLOR1_VIEW 0x28ca8 +#define CB_COLOR2_VIEW 0x28ce4 +#define CB_COLOR3_VIEW 0x28d20 +#define CB_COLOR4_VIEW 0x28d5c +#define CB_COLOR5_VIEW 0x28d98 +#define CB_COLOR6_VIEW 0x28dd4 +#define CB_COLOR7_VIEW 0x28e10 +#define CB_COLOR8_VIEW 0x28e4c +#define CB_COLOR9_VIEW 0x28e68 +#define CB_COLOR10_VIEW 0x28e84 +#define CB_COLOR11_VIEW 0x28ea0 + +#define CB_COLOR1_INFO 0x28cac +#define CB_COLOR2_INFO 0x28ce8 +#define CB_COLOR3_INFO 0x28d24 +#define CB_COLOR4_INFO 0x28d60 +#define CB_COLOR5_INFO 0x28d9c +#define CB_COLOR6_INFO 0x28dd8 +#define CB_COLOR7_INFO 0x28e14 +#define CB_COLOR8_INFO 0x28e50 +#define CB_COLOR9_INFO 0x28e6c +#define CB_COLOR10_INFO 0x28e88 +#define CB_COLOR11_INFO 0x28ea4 + +#define CB_COLOR1_ATTRIB 0x28cb0 +#define CB_COLOR2_ATTRIB 0x28cec +#define CB_COLOR3_ATTRIB 0x28d28 +#define CB_COLOR4_ATTRIB 0x28d64 +#define CB_COLOR5_ATTRIB 0x28da0 +#define CB_COLOR6_ATTRIB 0x28ddc +#define CB_COLOR7_ATTRIB 0x28e18 +#define CB_COLOR8_ATTRIB 0x28e54 +#define CB_COLOR9_ATTRIB 0x28e70 +#define CB_COLOR10_ATTRIB 0x28e8c +#define CB_COLOR11_ATTRIB 0x28ea8 + +#define CB_COLOR1_DIM 0x28cb4 +#define CB_COLOR2_DIM 0x28cf0 +#define CB_COLOR3_DIM 0x28d2c +#define CB_COLOR4_DIM 0x28d68 +#define CB_COLOR5_DIM 0x28da4 +#define CB_COLOR6_DIM 0x28de0 +#define CB_COLOR7_DIM 0x28e1c +#define CB_COLOR8_DIM 0x28e58 +#define CB_COLOR9_DIM 0x28e74 +#define CB_COLOR10_DIM 0x28e90 +#define CB_COLOR11_DIM 0x28eac + +#define CB_COLOR1_CMASK 0x28cb8 +#define CB_COLOR2_CMASK 0x28cf4 +#define CB_COLOR3_CMASK 0x28d30 +#define CB_COLOR4_CMASK 0x28d6c +#define CB_COLOR5_CMASK 0x28da8 +#define CB_COLOR6_CMASK 0x28de4 +#define CB_COLOR7_CMASK 0x28e20 + +#define CB_COLOR1_CMASK_SLICE 0x28cbc +#define CB_COLOR2_CMASK_SLICE 0x28cf8 +#define CB_COLOR3_CMASK_SLICE 0x28d34 +#define CB_COLOR4_CMASK_SLICE 0x28d70 +#define CB_COLOR5_CMASK_SLICE 0x28dac +#define CB_COLOR6_CMASK_SLICE 0x28de8 +#define CB_COLOR7_CMASK_SLICE 0x28e24 + +#define CB_COLOR1_FMASK 0x28cc0 +#define CB_COLOR2_FMASK 0x28cfc +#define CB_COLOR3_FMASK 0x28d38 +#define CB_COLOR4_FMASK 0x28d74 +#define CB_COLOR5_FMASK 0x28db0 +#define CB_COLOR6_FMASK 0x28dec +#define CB_COLOR7_FMASK 0x28e28 + +#define CB_COLOR1_FMASK_SLICE 0x28cc4 +#define CB_COLOR2_FMASK_SLICE 0x28d00 +#define CB_COLOR3_FMASK_SLICE 0x28d3c +#define CB_COLOR4_FMASK_SLICE 0x28d78 +#define CB_COLOR5_FMASK_SLICE 0x28db4 +#define CB_COLOR6_FMASK_SLICE 0x28df0 +#define CB_COLOR7_FMASK_SLICE 0x28e2c + +#define CB_COLOR1_CLEAR_WORD0 0x28cc8 +#define CB_COLOR2_CLEAR_WORD0 0x28d04 +#define CB_COLOR3_CLEAR_WORD0 0x28d40 +#define CB_COLOR4_CLEAR_WORD0 0x28d7c +#define CB_COLOR5_CLEAR_WORD0 0x28db8 +#define CB_COLOR6_CLEAR_WORD0 0x28df4 +#define CB_COLOR7_CLEAR_WORD0 0x28e30 + +#define CB_COLOR1_CLEAR_WORD1 0x28ccc +#define CB_COLOR2_CLEAR_WORD1 0x28d08 +#define CB_COLOR3_CLEAR_WORD1 0x28d44 +#define CB_COLOR4_CLEAR_WORD1 0x28d80 +#define CB_COLOR5_CLEAR_WORD1 0x28dbc +#define CB_COLOR6_CLEAR_WORD1 0x28df8 +#define CB_COLOR7_CLEAR_WORD1 0x28e34 + +#define CB_COLOR1_CLEAR_WORD2 0x28cd0 +#define CB_COLOR2_CLEAR_WORD2 0x28d0c +#define CB_COLOR3_CLEAR_WORD2 0x28d48 +#define CB_COLOR4_CLEAR_WORD2 0x28d84 +#define CB_COLOR5_CLEAR_WORD2 0x28dc0 +#define CB_COLOR6_CLEAR_WORD2 0x28dfc +#define CB_COLOR7_CLEAR_WORD2 0x28e38 + +#define CB_COLOR1_CLEAR_WORD3 0x28cd4 +#define CB_COLOR2_CLEAR_WORD3 0x28d10 +#define CB_COLOR3_CLEAR_WORD3 0x28d4c +#define CB_COLOR4_CLEAR_WORD3 0x28d88 +#define CB_COLOR5_CLEAR_WORD3 0x28dc4 +#define CB_COLOR6_CLEAR_WORD3 0x28e00 +#define CB_COLOR7_CLEAR_WORD3 0x28e3c + +#define SQ_TEX_RESOURCE_WORD0_0 0x30000 +# define TEX_DIM(x) ((x) << 0) +# define SQ_TEX_DIM_1D 0 +# define SQ_TEX_DIM_2D 1 +# define SQ_TEX_DIM_3D 2 +# define SQ_TEX_DIM_CUBEMAP 3 +# define SQ_TEX_DIM_1D_ARRAY 4 +# define SQ_TEX_DIM_2D_ARRAY 5 +# define SQ_TEX_DIM_2D_MSAA 6 +# define SQ_TEX_DIM_2D_ARRAY_MSAA 7 +#define SQ_TEX_RESOURCE_WORD1_0 0x30004 +# define TEX_ARRAY_MODE(x) ((x) << 28) +#define SQ_TEX_RESOURCE_WORD2_0 0x30008 +#define SQ_TEX_RESOURCE_WORD3_0 0x3000C +#define SQ_TEX_RESOURCE_WORD4_0 0x30010 +# define TEX_DST_SEL_X(x) ((x) << 16) +# define TEX_DST_SEL_Y(x) ((x) << 19) +# define TEX_DST_SEL_Z(x) ((x) << 22) +# define TEX_DST_SEL_W(x) ((x) << 25) +# define SQ_SEL_X 0 +# define SQ_SEL_Y 1 +# define SQ_SEL_Z 2 +# define SQ_SEL_W 3 +# define SQ_SEL_0 4 +# define SQ_SEL_1 5 +#define SQ_TEX_RESOURCE_WORD5_0 0x30014 +#define SQ_TEX_RESOURCE_WORD6_0 0x30018 +# define TEX_TILE_SPLIT(x) (((x) & 0x7) << 29) +#define SQ_TEX_RESOURCE_WORD7_0 0x3001c +# define MACRO_TILE_ASPECT(x) (((x) & 0x3) << 6) +# define TEX_BANK_WIDTH(x) (((x) & 0x3) << 8) +# define TEX_BANK_HEIGHT(x) (((x) & 0x3) << 10) +# define TEX_NUM_BANKS(x) (((x) & 0x3) << 16) +#define R_030000_SQ_TEX_RESOURCE_WORD0_0 0x030000 +#define S_030000_DIM(x) (((x) & 0x7) << 0) +#define G_030000_DIM(x) (((x) >> 0) & 0x7) +#define C_030000_DIM 0xFFFFFFF8 +#define V_030000_SQ_TEX_DIM_1D 0x00000000 +#define V_030000_SQ_TEX_DIM_2D 0x00000001 +#define V_030000_SQ_TEX_DIM_3D 0x00000002 +#define V_030000_SQ_TEX_DIM_CUBEMAP 0x00000003 +#define V_030000_SQ_TEX_DIM_1D_ARRAY 0x00000004 +#define V_030000_SQ_TEX_DIM_2D_ARRAY 0x00000005 +#define V_030000_SQ_TEX_DIM_2D_MSAA 0x00000006 +#define V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007 +#define S_030000_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 5) +#define G_030000_NON_DISP_TILING_ORDER(x) (((x) >> 5) & 0x1) +#define C_030000_NON_DISP_TILING_ORDER 0xFFFFFFDF +#define S_030000_PITCH(x) (((x) & 0xFFF) << 6) +#define G_030000_PITCH(x) (((x) >> 6) & 0xFFF) +#define C_030000_PITCH 0xFFFC003F +#define S_030000_TEX_WIDTH(x) (((x) & 0x3FFF) << 18) +#define G_030000_TEX_WIDTH(x) (((x) >> 18) & 0x3FFF) +#define C_030000_TEX_WIDTH 0x0003FFFF +#define R_030004_SQ_TEX_RESOURCE_WORD1_0 0x030004 +#define S_030004_TEX_HEIGHT(x) (((x) & 0x3FFF) << 0) +#define G_030004_TEX_HEIGHT(x) (((x) >> 0) & 0x3FFF) +#define C_030004_TEX_HEIGHT 0xFFFFC000 +#define S_030004_TEX_DEPTH(x) (((x) & 0x1FFF) << 14) +#define G_030004_TEX_DEPTH(x) (((x) >> 14) & 0x1FFF) +#define C_030004_TEX_DEPTH 0xF8003FFF +#define S_030004_ARRAY_MODE(x) (((x) & 0xF) << 28) +#define G_030004_ARRAY_MODE(x) (((x) >> 28) & 0xF) +#define C_030004_ARRAY_MODE 0x0FFFFFFF +#define R_030008_SQ_TEX_RESOURCE_WORD2_0 0x030008 +#define S_030008_BASE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_030008_BASE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_030008_BASE_ADDRESS 0x00000000 +#define R_03000C_SQ_TEX_RESOURCE_WORD3_0 0x03000C +#define S_03000C_MIP_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_03000C_MIP_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_03000C_MIP_ADDRESS 0x00000000 +#define R_030010_SQ_TEX_RESOURCE_WORD4_0 0x030010 +#define S_030010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) +#define G_030010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) +#define C_030010_FORMAT_COMP_X 0xFFFFFFFC +#define V_030010_SQ_FORMAT_COMP_UNSIGNED 0x00000000 +#define V_030010_SQ_FORMAT_COMP_SIGNED 0x00000001 +#define V_030010_SQ_FORMAT_COMP_UNSIGNED_BIASED 0x00000002 +#define S_030010_FORMAT_COMP_Y(x) (((x) & 0x3) << 2) +#define G_030010_FORMAT_COMP_Y(x) (((x) >> 2) & 0x3) +#define C_030010_FORMAT_COMP_Y 0xFFFFFFF3 +#define S_030010_FORMAT_COMP_Z(x) (((x) & 0x3) << 4) +#define G_030010_FORMAT_COMP_Z(x) (((x) >> 4) & 0x3) +#define C_030010_FORMAT_COMP_Z 0xFFFFFFCF +#define S_030010_FORMAT_COMP_W(x) (((x) & 0x3) << 6) +#define G_030010_FORMAT_COMP_W(x) (((x) >> 6) & 0x3) +#define C_030010_FORMAT_COMP_W 0xFFFFFF3F +#define S_030010_NUM_FORMAT_ALL(x) (((x) & 0x3) << 8) +#define G_030010_NUM_FORMAT_ALL(x) (((x) >> 8) & 0x3) +#define C_030010_NUM_FORMAT_ALL 0xFFFFFCFF +#define V_030010_SQ_NUM_FORMAT_NORM 0x00000000 +#define V_030010_SQ_NUM_FORMAT_INT 0x00000001 +#define V_030010_SQ_NUM_FORMAT_SCALED 0x00000002 +#define S_030010_SRF_MODE_ALL(x) (((x) & 0x1) << 10) +#define G_030010_SRF_MODE_ALL(x) (((x) >> 10) & 0x1) +#define C_030010_SRF_MODE_ALL 0xFFFFFBFF +#define V_030010_SRF_MODE_ZERO_CLAMP_MINUS_ONE 0x00000000 +#define V_030010_SRF_MODE_NO_ZERO 0x00000001 +#define S_030010_FORCE_DEGAMMA(x) (((x) & 0x1) << 11) +#define G_030010_FORCE_DEGAMMA(x) (((x) >> 11) & 0x1) +#define C_030010_FORCE_DEGAMMA 0xFFFFF7FF +#define S_030010_ENDIAN_SWAP(x) (((x) & 0x3) << 12) +#define G_030010_ENDIAN_SWAP(x) (((x) >> 12) & 0x3) +#define C_030010_ENDIAN_SWAP 0xFFFFCFFF +#define S_030010_DST_SEL_X(x) (((x) & 0x7) << 16) +#define G_030010_DST_SEL_X(x) (((x) >> 16) & 0x7) +#define C_030010_DST_SEL_X 0xFFF8FFFF +#define V_030010_SQ_SEL_X 0x00000000 +#define V_030010_SQ_SEL_Y 0x00000001 +#define V_030010_SQ_SEL_Z 0x00000002 +#define V_030010_SQ_SEL_W 0x00000003 +#define V_030010_SQ_SEL_0 0x00000004 +#define V_030010_SQ_SEL_1 0x00000005 +#define S_030010_DST_SEL_Y(x) (((x) & 0x7) << 19) +#define G_030010_DST_SEL_Y(x) (((x) >> 19) & 0x7) +#define C_030010_DST_SEL_Y 0xFFC7FFFF +#define S_030010_DST_SEL_Z(x) (((x) & 0x7) << 22) +#define G_030010_DST_SEL_Z(x) (((x) >> 22) & 0x7) +#define C_030010_DST_SEL_Z 0xFE3FFFFF +#define S_030010_DST_SEL_W(x) (((x) & 0x7) << 25) +#define G_030010_DST_SEL_W(x) (((x) >> 25) & 0x7) +#define C_030010_DST_SEL_W 0xF1FFFFFF +#define S_030010_BASE_LEVEL(x) (((x) & 0xF) << 28) +#define G_030010_BASE_LEVEL(x) (((x) >> 28) & 0xF) +#define C_030010_BASE_LEVEL 0x0FFFFFFF +#define R_030014_SQ_TEX_RESOURCE_WORD5_0 0x030014 +#define S_030014_LAST_LEVEL(x) (((x) & 0xF) << 0) +#define G_030014_LAST_LEVEL(x) (((x) >> 0) & 0xF) +#define C_030014_LAST_LEVEL 0xFFFFFFF0 +#define S_030014_BASE_ARRAY(x) (((x) & 0x1FFF) << 4) +#define G_030014_BASE_ARRAY(x) (((x) >> 4) & 0x1FFF) +#define C_030014_BASE_ARRAY 0xFFFE000F +#define S_030014_LAST_ARRAY(x) (((x) & 0x1FFF) << 17) +#define G_030014_LAST_ARRAY(x) (((x) >> 17) & 0x1FFF) +#define C_030014_LAST_ARRAY 0xC001FFFF +#define R_030018_SQ_TEX_RESOURCE_WORD6_0 0x030018 +#define S_030018_MAX_ANISO(x) (((x) & 0x7) << 0) +#define G_030018_MAX_ANISO(x) (((x) >> 0) & 0x7) +#define C_030018_MAX_ANISO 0xFFFFFFF8 +#define S_030018_PERF_MODULATION(x) (((x) & 0x7) << 3) +#define G_030018_PERF_MODULATION(x) (((x) >> 3) & 0x7) +#define C_030018_PERF_MODULATION 0xFFFFFFC7 +#define S_030018_INTERLACED(x) (((x) & 0x1) << 6) +#define G_030018_INTERLACED(x) (((x) >> 6) & 0x1) +#define C_030018_INTERLACED 0xFFFFFFBF +#define S_030018_TILE_SPLIT(x) (((x) & 0x7) << 29) +#define G_030018_TILE_SPLIT(x) (((x) >> 29) & 0x7) +#define R_03001C_SQ_TEX_RESOURCE_WORD7_0 0x03001C +#define S_03001C_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 6) +#define G_03001C_MACRO_TILE_ASPECT(x) (((x) >> 6) & 0x3) +#define S_03001C_BANK_WIDTH(x) (((x) & 0x3) << 8) +#define G_03001C_BANK_WIDTH(x) (((x) >> 8) & 0x3) +#define S_03001C_BANK_HEIGHT(x) (((x) & 0x3) << 10) +#define G_03001C_BANK_HEIGHT(x) (((x) >> 10) & 0x3) +#define S_03001C_NUM_BANKS(x) (((x) & 0x3) << 16) +#define G_03001C_NUM_BANKS(x) (((x) >> 16) & 0x3) +#define S_03001C_TYPE(x) (((x) & 0x3) << 30) +#define G_03001C_TYPE(x) (((x) >> 30) & 0x3) +#define C_03001C_TYPE 0x3FFFFFFF +#define V_03001C_SQ_TEX_VTX_INVALID_TEXTURE 0x00000000 +#define V_03001C_SQ_TEX_VTX_INVALID_BUFFER 0x00000001 +#define V_03001C_SQ_TEX_VTX_VALID_TEXTURE 0x00000002 +#define V_03001C_SQ_TEX_VTX_VALID_BUFFER 0x00000003 +#define S_03001C_DATA_FORMAT(x) (((x) & 0x3F) << 0) +#define G_03001C_DATA_FORMAT(x) (((x) >> 0) & 0x3F) +#define C_03001C_DATA_FORMAT 0xFFFFFFC0 + +#define SQ_VTX_CONSTANT_WORD0_0 0x30000 +#define SQ_VTX_CONSTANT_WORD1_0 0x30004 +#define SQ_VTX_CONSTANT_WORD2_0 0x30008 +# define SQ_VTXC_BASE_ADDR_HI(x) ((x) << 0) +# define SQ_VTXC_STRIDE(x) ((x) << 8) +# define SQ_VTXC_ENDIAN_SWAP(x) ((x) << 30) +# define SQ_ENDIAN_NONE 0 +# define SQ_ENDIAN_8IN16 1 +# define SQ_ENDIAN_8IN32 2 +#define SQ_VTX_CONSTANT_WORD3_0 0x3000C +# define SQ_VTCX_SEL_X(x) ((x) << 3) +# define SQ_VTCX_SEL_Y(x) ((x) << 6) +# define SQ_VTCX_SEL_Z(x) ((x) << 9) +# define SQ_VTCX_SEL_W(x) ((x) << 12) +#define SQ_VTX_CONSTANT_WORD4_0 0x30010 +#define SQ_VTX_CONSTANT_WORD5_0 0x30014 +#define SQ_VTX_CONSTANT_WORD6_0 0x30018 +#define SQ_VTX_CONSTANT_WORD7_0 0x3001c + +#define TD_PS_BORDER_COLOR_INDEX 0xA400 +#define TD_PS_BORDER_COLOR_RED 0xA404 +#define TD_PS_BORDER_COLOR_GREEN 0xA408 +#define TD_PS_BORDER_COLOR_BLUE 0xA40C +#define TD_PS_BORDER_COLOR_ALPHA 0xA410 +#define TD_VS_BORDER_COLOR_INDEX 0xA414 +#define TD_VS_BORDER_COLOR_RED 0xA418 +#define TD_VS_BORDER_COLOR_GREEN 0xA41C +#define TD_VS_BORDER_COLOR_BLUE 0xA420 +#define TD_VS_BORDER_COLOR_ALPHA 0xA424 +#define TD_GS_BORDER_COLOR_INDEX 0xA428 +#define TD_GS_BORDER_COLOR_RED 0xA42C +#define TD_GS_BORDER_COLOR_GREEN 0xA430 +#define TD_GS_BORDER_COLOR_BLUE 0xA434 +#define TD_GS_BORDER_COLOR_ALPHA 0xA438 +#define TD_HS_BORDER_COLOR_INDEX 0xA43C +#define TD_HS_BORDER_COLOR_RED 0xA440 +#define TD_HS_BORDER_COLOR_GREEN 0xA444 +#define TD_HS_BORDER_COLOR_BLUE 0xA448 +#define TD_HS_BORDER_COLOR_ALPHA 0xA44C +#define TD_LS_BORDER_COLOR_INDEX 0xA450 +#define TD_LS_BORDER_COLOR_RED 0xA454 +#define TD_LS_BORDER_COLOR_GREEN 0xA458 +#define TD_LS_BORDER_COLOR_BLUE 0xA45C +#define TD_LS_BORDER_COLOR_ALPHA 0xA460 +#define TD_CS_BORDER_COLOR_INDEX 0xA464 +#define TD_CS_BORDER_COLOR_RED 0xA468 +#define TD_CS_BORDER_COLOR_GREEN 0xA46C +#define TD_CS_BORDER_COLOR_BLUE 0xA470 +#define TD_CS_BORDER_COLOR_ALPHA 0xA474 + +/* cayman 3D regs */ +#define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B4 +#define CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS 0x8E48 +#define CAYMAN_DB_EQAA 0x28804 +#define CAYMAN_DB_DEPTH_INFO 0x2803C +#define CAYMAN_PA_SC_AA_CONFIG 0x28BE0 +#define CAYMAN_MSAA_NUM_SAMPLES_SHIFT 0 +#define CAYMAN_MSAA_NUM_SAMPLES_MASK 0x7 +#define CAYMAN_SX_SCATTER_EXPORT_BASE 0x28358 +/* cayman packet3 addition */ +#define CAYMAN_PACKET3_DEALLOC_STATE 0x14 + +/* DMA regs common on r6xx/r7xx/evergreen/ni */ +#define DMA_RB_CNTL 0xd000 +# define DMA_RB_ENABLE (1 << 0) +# define DMA_RB_SIZE(x) ((x) << 1) /* log2 */ +# define DMA_RB_SWAP_ENABLE (1 << 9) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_ENABLE (1 << 12) +# define DMA_RPTR_WRITEBACK_SWAP_ENABLE (1 << 13) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_TIMER(x) ((x) << 16) /* log2 */ +#define DMA_STATUS_REG 0xd034 +# define DMA_IDLE (1 << 0) + +#endif diff --git a/sys/dev/drm2/radeon/ni.c b/sys/dev/drm2/radeon/ni.c new file mode 100644 index 00000000000..7995684409d --- /dev/null +++ b/sys/dev/drm2/radeon/ni.c @@ -0,0 +1,1980 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include +#include "nid.h" +#include "atom.h" +#include "ni_reg.h" +#include "cayman_blit_shaders.h" + +extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); + +#define EVERGREEN_PFP_UCODE_SIZE 1120 +#define EVERGREEN_PM4_UCODE_SIZE 1376 +#define EVERGREEN_RLC_UCODE_SIZE 768 +#define BTC_MC_UCODE_SIZE 6024 + +#define CAYMAN_PFP_UCODE_SIZE 2176 +#define CAYMAN_PM4_UCODE_SIZE 2176 +#define CAYMAN_RLC_UCODE_SIZE 1024 +#define CAYMAN_MC_UCODE_SIZE 6037 + +#define ARUBA_RLC_UCODE_SIZE 1536 + +#define BTC_IO_MC_REGS_SIZE 29 + +static const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { + {0x00000077, 0xff010100}, + {0x00000078, 0x00000000}, + {0x00000079, 0x00001434}, + {0x0000007a, 0xcc08ec08}, + {0x0000007b, 0x00040000}, + {0x0000007c, 0x000080c0}, + {0x0000007d, 0x09000000}, + {0x0000007e, 0x00210404}, + {0x00000081, 0x08a8e800}, + {0x00000082, 0x00030444}, + {0x00000083, 0x00000000}, + {0x00000085, 0x00000001}, + {0x00000086, 0x00000002}, + {0x00000087, 0x48490000}, + {0x00000088, 0x20244647}, + {0x00000089, 0x00000005}, + {0x0000008b, 0x66030000}, + {0x0000008c, 0x00006603}, + {0x0000008d, 0x00000100}, + {0x0000008f, 0x00001c0a}, + {0x00000090, 0xff000001}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00946a00} +}; + +static const u32 turks_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { + {0x00000077, 0xff010100}, + {0x00000078, 0x00000000}, + {0x00000079, 0x00001434}, + {0x0000007a, 0xcc08ec08}, + {0x0000007b, 0x00040000}, + {0x0000007c, 0x000080c0}, + {0x0000007d, 0x09000000}, + {0x0000007e, 0x00210404}, + {0x00000081, 0x08a8e800}, + {0x00000082, 0x00030444}, + {0x00000083, 0x00000000}, + {0x00000085, 0x00000001}, + {0x00000086, 0x00000002}, + {0x00000087, 0x48490000}, + {0x00000088, 0x20244647}, + {0x00000089, 0x00000005}, + {0x0000008b, 0x66030000}, + {0x0000008c, 0x00006603}, + {0x0000008d, 0x00000100}, + {0x0000008f, 0x00001c0a}, + {0x00000090, 0xff000001}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00936a00} +}; + +static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { + {0x00000077, 0xff010100}, + {0x00000078, 0x00000000}, + {0x00000079, 0x00001434}, + {0x0000007a, 0xcc08ec08}, + {0x0000007b, 0x00040000}, + {0x0000007c, 0x000080c0}, + {0x0000007d, 0x09000000}, + {0x0000007e, 0x00210404}, + {0x00000081, 0x08a8e800}, + {0x00000082, 0x00030444}, + {0x00000083, 0x00000000}, + {0x00000085, 0x00000001}, + {0x00000086, 0x00000002}, + {0x00000087, 0x48490000}, + {0x00000088, 0x20244647}, + {0x00000089, 0x00000005}, + {0x0000008b, 0x66030000}, + {0x0000008c, 0x00006603}, + {0x0000008d, 0x00000100}, + {0x0000008f, 0x00001c0a}, + {0x00000090, 0xff000001}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00916a00} +}; + +static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { + {0x00000077, 0xff010100}, + {0x00000078, 0x00000000}, + {0x00000079, 0x00001434}, + {0x0000007a, 0xcc08ec08}, + {0x0000007b, 0x00040000}, + {0x0000007c, 0x000080c0}, + {0x0000007d, 0x09000000}, + {0x0000007e, 0x00210404}, + {0x00000081, 0x08a8e800}, + {0x00000082, 0x00030444}, + {0x00000083, 0x00000000}, + {0x00000085, 0x00000001}, + {0x00000086, 0x00000002}, + {0x00000087, 0x48490000}, + {0x00000088, 0x20244647}, + {0x00000089, 0x00000005}, + {0x0000008b, 0x66030000}, + {0x0000008c, 0x00006603}, + {0x0000008d, 0x00000100}, + {0x0000008f, 0x00001c0a}, + {0x00000090, 0xff000001}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00976b00} +}; + +int ni_mc_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + u32 mem_type, running, blackout = 0; + u32 *io_mc_regs; + int i, ucode_size, regs_size; + + if (!rdev->mc_fw) + return -EINVAL; + + switch (rdev->family) { + case CHIP_BARTS: + io_mc_regs = (u32 *)&barts_io_mc_regs; + ucode_size = BTC_MC_UCODE_SIZE; + regs_size = BTC_IO_MC_REGS_SIZE; + break; + case CHIP_TURKS: + io_mc_regs = (u32 *)&turks_io_mc_regs; + ucode_size = BTC_MC_UCODE_SIZE; + regs_size = BTC_IO_MC_REGS_SIZE; + break; + case CHIP_CAICOS: + default: + io_mc_regs = (u32 *)&caicos_io_mc_regs; + ucode_size = BTC_MC_UCODE_SIZE; + regs_size = BTC_IO_MC_REGS_SIZE; + break; + case CHIP_CAYMAN: + io_mc_regs = (u32 *)&cayman_io_mc_regs; + ucode_size = CAYMAN_MC_UCODE_SIZE; + regs_size = BTC_IO_MC_REGS_SIZE; + break; + } + + mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT; + running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; + + if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) { + if (running) { + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + WREG32(MC_SHARED_BLACKOUT_CNTL, 1); + } + + /* reset the engine and set to writable */ + WREG32(MC_SEQ_SUP_CNTL, 0x00000008); + WREG32(MC_SEQ_SUP_CNTL, 0x00000010); + + /* load mc io regs */ + for (i = 0; i < regs_size; i++) { + WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); + WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); + } + /* load the MC ucode */ + fw_data = (const __be32 *)rdev->mc_fw->data; + for (i = 0; i < ucode_size; i++) + WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); + + /* put the engine back into the active state */ + WREG32(MC_SEQ_SUP_CNTL, 0x00000008); + WREG32(MC_SEQ_SUP_CNTL, 0x00000004); + WREG32(MC_SEQ_SUP_CNTL, 0x00000001); + + /* wait for training to complete */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD) + break; + DRM_UDELAY(1); + } + + if (running) + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); + } + + return 0; +} + +int ni_init_microcode(struct radeon_device *rdev) +{ + const char *chip_name; + const char *rlc_chip_name; + size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size; + char fw_name[30]; + int err; + + DRM_DEBUG("\n"); + + switch (rdev->family) { + case CHIP_BARTS: + chip_name = "BARTS"; + rlc_chip_name = "BTC"; + pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; + me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; + rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; + mc_req_size = BTC_MC_UCODE_SIZE * 4; + break; + case CHIP_TURKS: + chip_name = "TURKS"; + rlc_chip_name = "BTC"; + pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; + me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; + rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; + mc_req_size = BTC_MC_UCODE_SIZE * 4; + break; + case CHIP_CAICOS: + chip_name = "CAICOS"; + rlc_chip_name = "BTC"; + pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; + me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; + rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; + mc_req_size = BTC_MC_UCODE_SIZE * 4; + break; + case CHIP_CAYMAN: + chip_name = "CAYMAN"; + rlc_chip_name = "CAYMAN"; + pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; + me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; + rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; + mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; + break; + case CHIP_ARUBA: + chip_name = "ARUBA"; + rlc_chip_name = "ARUBA"; + /* pfp/me same size as CAYMAN */ + pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; + me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; + rlc_req_size = ARUBA_RLC_UCODE_SIZE * 4; + mc_req_size = 0; + break; + default: panic("%s: Unsupported family %d", __func__, rdev->family); + } + + DRM_INFO("Loading %s Microcode\n", chip_name); + err = 0; + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_pfp", chip_name); + rdev->pfp_fw = firmware_get(fw_name); + if (rdev->pfp_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->pfp_fw->datasize != pfp_req_size) { + DRM_ERROR( + "ni_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->pfp_fw->datasize, fw_name); + err = -EINVAL; + goto out; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_me", chip_name); + rdev->me_fw = firmware_get(fw_name); + if (rdev->me_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->me_fw->datasize != me_req_size) { + DRM_ERROR( + "ni_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->me_fw->datasize, fw_name); + err = -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_rlc", rlc_chip_name); + rdev->rlc_fw = firmware_get(fw_name); + if (rdev->rlc_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->rlc_fw->datasize != rlc_req_size) { + DRM_ERROR( + "ni_rlc: Bogus length %zu in firmware \"%s\"\n", + rdev->rlc_fw->datasize, fw_name); + err = -EINVAL; + } + + /* no MC ucode on TN */ + if (!(rdev->flags & RADEON_IS_IGP)) { + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc", chip_name); + rdev->mc_fw = firmware_get(fw_name); + if (rdev->mc_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->mc_fw->datasize != mc_req_size) { + DRM_ERROR( + "ni_mc: Bogus length %zu in firmware \"%s\"\n", + rdev->mc_fw->datasize, fw_name); + err = -EINVAL; + } + } +out: + if (err) { + if (err != -EINVAL) + DRM_ERROR( + "ni_cp: Failed to load firmware \"%s\"\n", + fw_name); + if (rdev->pfp_fw != NULL) { + firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); + rdev->pfp_fw = NULL; + } + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + if (rdev->rlc_fw != NULL) { + firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); + rdev->rlc_fw = NULL; + } + if (rdev->mc_fw != NULL) { + firmware_put(rdev->mc_fw, FIRMWARE_UNLOAD); + rdev->mc_fw = NULL; + } + } + return err; +} + +/** + * ni_fini_microcode - drop the firmwares image references + * + * @rdev: radeon_device pointer + * + * Drop the pfp, me, mc and rlc firmwares image references. + * Called at driver shutdown. + */ +void ni_fini_microcode(struct radeon_device *rdev) +{ + + if (rdev->pfp_fw != NULL) { + firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); + rdev->pfp_fw = NULL; + } + + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + + if (rdev->rlc_fw != NULL) { + firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); + rdev->rlc_fw = NULL; + } + + if (rdev->mc_fw != NULL) { + firmware_put(rdev->mc_fw, FIRMWARE_UNLOAD); + rdev->mc_fw = NULL; + } +} + + +/* + * Core functions + */ +static void cayman_gpu_init(struct radeon_device *rdev) +{ + u32 gb_addr_config = 0; + u32 mc_shared_chmap, mc_arb_ramcfg; + u32 cgts_tcc_disable; + u32 sx_debug_1; + u32 smx_dc_ctl0; + u32 cgts_sm_ctrl_reg; + u32 hdp_host_path_cntl; + u32 tmp; + u32 disabled_rb_mask; + int i, j; + + switch (rdev->family) { + case CHIP_CAYMAN: + rdev->config.cayman.max_shader_engines = 2; + rdev->config.cayman.max_pipes_per_simd = 4; + rdev->config.cayman.max_tile_pipes = 8; + rdev->config.cayman.max_simds_per_se = 12; + rdev->config.cayman.max_backends_per_se = 4; + rdev->config.cayman.max_texture_channel_caches = 8; + rdev->config.cayman.max_gprs = 256; + rdev->config.cayman.max_threads = 256; + rdev->config.cayman.max_gs_threads = 32; + rdev->config.cayman.max_stack_entries = 512; + rdev->config.cayman.sx_num_of_sets = 8; + rdev->config.cayman.sx_max_export_size = 256; + rdev->config.cayman.sx_max_export_pos_size = 64; + rdev->config.cayman.sx_max_export_smx_size = 192; + rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sq_num_cf_insts = 2; + + rdev->config.cayman.sc_prim_fifo_size = 0x100; + rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; + rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = CAYMAN_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_ARUBA: + default: + rdev->config.cayman.max_shader_engines = 1; + rdev->config.cayman.max_pipes_per_simd = 4; + rdev->config.cayman.max_tile_pipes = 2; + if ((rdev->ddev->pci_device == 0x9900) || + (rdev->ddev->pci_device == 0x9901) || + (rdev->ddev->pci_device == 0x9905) || + (rdev->ddev->pci_device == 0x9906) || + (rdev->ddev->pci_device == 0x9907) || + (rdev->ddev->pci_device == 0x9908) || + (rdev->ddev->pci_device == 0x9909) || + (rdev->ddev->pci_device == 0x9910) || + (rdev->ddev->pci_device == 0x9917)) { + rdev->config.cayman.max_simds_per_se = 6; + rdev->config.cayman.max_backends_per_se = 2; + } else if ((rdev->ddev->pci_device == 0x9903) || + (rdev->ddev->pci_device == 0x9904) || + (rdev->ddev->pci_device == 0x990A) || + (rdev->ddev->pci_device == 0x9913) || + (rdev->ddev->pci_device == 0x9918)) { + rdev->config.cayman.max_simds_per_se = 4; + rdev->config.cayman.max_backends_per_se = 2; + } else if ((rdev->ddev->pci_device == 0x9919) || + (rdev->ddev->pci_device == 0x9990) || + (rdev->ddev->pci_device == 0x9991) || + (rdev->ddev->pci_device == 0x9994) || + (rdev->ddev->pci_device == 0x99A0)) { + rdev->config.cayman.max_simds_per_se = 3; + rdev->config.cayman.max_backends_per_se = 1; + } else { + rdev->config.cayman.max_simds_per_se = 2; + rdev->config.cayman.max_backends_per_se = 1; + } + rdev->config.cayman.max_texture_channel_caches = 2; + rdev->config.cayman.max_gprs = 256; + rdev->config.cayman.max_threads = 256; + rdev->config.cayman.max_gs_threads = 32; + rdev->config.cayman.max_stack_entries = 512; + rdev->config.cayman.sx_num_of_sets = 8; + rdev->config.cayman.sx_max_export_size = 256; + rdev->config.cayman.sx_max_export_pos_size = 64; + rdev->config.cayman.sx_max_export_smx_size = 192; + rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sq_num_cf_insts = 2; + + rdev->config.cayman.sc_prim_fifo_size = 0x40; + rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; + rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = ARUBA_GB_ADDR_CONFIG_GOLDEN; + break; + } + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + + WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); + + evergreen_fix_pci_max_read_req_size(rdev); + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); + mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + + tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; + rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; + if (rdev->config.cayman.mem_row_size_in_kb > 4) + rdev->config.cayman.mem_row_size_in_kb = 4; + /* XXX use MC settings? */ + rdev->config.cayman.shader_engine_tile_size = 32; + rdev->config.cayman.num_gpus = 1; + rdev->config.cayman.multi_gpu_tile_size = 64; + + tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; + rdev->config.cayman.num_tile_pipes = (1 << tmp); + tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; + rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; + tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; + rdev->config.cayman.num_shader_engines = tmp + 1; + tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; + rdev->config.cayman.num_gpus = tmp + 1; + tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; + rdev->config.cayman.multi_gpu_tile_size = 1 << tmp; + tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; + rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; + + + /* setup tiling info dword. gb_addr_config is not adequate since it does + * not have bank info, so create a custom tiling dword. + * bits 3:0 num_pipes + * bits 7:4 num_banks + * bits 11:8 group_size + * bits 15:12 row_size + */ + rdev->config.cayman.tile_config = 0; + switch (rdev->config.cayman.num_tile_pipes) { + case 1: + default: + rdev->config.cayman.tile_config |= (0 << 0); + break; + case 2: + rdev->config.cayman.tile_config |= (1 << 0); + break; + case 4: + rdev->config.cayman.tile_config |= (2 << 0); + break; + case 8: + rdev->config.cayman.tile_config |= (3 << 0); + break; + } + + /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ + if (rdev->flags & RADEON_IS_IGP) + rdev->config.cayman.tile_config |= 1 << 4; + else { + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ + rdev->config.cayman.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.cayman.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.cayman.tile_config |= 2 << 4; + break; + } + } + rdev->config.cayman.tile_config |= + ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; + rdev->config.cayman.tile_config |= + ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; + + tmp = 0; + for (i = (rdev->config.cayman.max_shader_engines - 1); i >= 0; i--) { + u32 rb_disable_bitmap; + + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; + tmp <<= 4; + tmp |= rb_disable_bitmap; + } + /* enabled rb are just the one not disabled :) */ + disabled_rb_mask = tmp; + + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); + WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); + + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); + WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config); + WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config); + + tmp = gb_addr_config & NUM_PIPES_MASK; + tmp = r6xx_remap_render_backend(rdev, tmp, + rdev->config.cayman.max_backends_per_se * + rdev->config.cayman.max_shader_engines, + CAYMAN_MAX_BACKENDS, disabled_rb_mask); + WREG32(GB_BACKEND_MAP, tmp); + + cgts_tcc_disable = 0xffff0000; + for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) + cgts_tcc_disable &= ~(1 << (16 + i)); + WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); + WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); + WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); + WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); + + /* reprogram the shader complex */ + cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG); + for (i = 0; i < 16; i++) + WREG32(CGTS_SM_CTRL_REG, OVERRIDE); + WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg); + + /* set HW defaults for 3D engine */ + WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); + + sx_debug_1 = RREG32(SX_DEBUG_1); + sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; + WREG32(SX_DEBUG_1, sx_debug_1); + + smx_dc_ctl0 = RREG32(SMX_DC_CTL0); + smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); + smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets); + WREG32(SMX_DC_CTL0, smx_dc_ctl0); + + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); + + /* need to be explicitly zero-ed */ + WREG32(VGT_OFFCHIP_LDS_BASE, 0); + WREG32(SQ_LSTMP_RING_BASE, 0); + WREG32(SQ_HSTMP_RING_BASE, 0); + WREG32(SQ_ESTMP_RING_BASE, 0); + WREG32(SQ_GSTMP_RING_BASE, 0); + WREG32(SQ_VSTMP_RING_BASE, 0); + WREG32(SQ_PSTMP_RING_BASE, 0); + + WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); + + WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) | + POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) | + SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1))); + + WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) | + SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) | + SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size))); + + + WREG32(VGT_NUM_INSTANCES, 1); + + WREG32(CP_PERFMON_CNTL, 0); + + WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) | + FETCH_FIFO_HIWATER(0x4) | + DONE_FIFO_HIWATER(0xe0) | + ALU_UPDATE_FIFO_HIWATER(0x8))); + + WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4)); + WREG32(SQ_CONFIG, (VC_ENABLE | + EXPORT_SRC_C | + GFX_PRIO(0) | + CS1_PRIO(0) | + CS2_PRIO(1))); + WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE); + + WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | + FORCE_EOV_MAX_REZ_CNT(255))); + + WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | + AUTO_INVLD_EN(ES_AND_GS_AUTO)); + + WREG32(VGT_GS_VERTEX_REUSE, 16); + WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + + WREG32(CB_PERF_CTR0_SEL_0, 0); + WREG32(CB_PERF_CTR0_SEL_1, 0); + WREG32(CB_PERF_CTR1_SEL_0, 0); + WREG32(CB_PERF_CTR1_SEL_1, 0); + WREG32(CB_PERF_CTR2_SEL_0, 0); + WREG32(CB_PERF_CTR2_SEL_1, 0); + WREG32(CB_PERF_CTR3_SEL_0, 0); + WREG32(CB_PERF_CTR3_SEL_1, 0); + + tmp = RREG32(HDP_MISC_CNTL); + tmp |= HDP_FLUSH_INVALIDATE_CACHE; + WREG32(HDP_MISC_CNTL, tmp); + + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); + + DRM_UDELAY(50); +} + +/* + * GART + */ +void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) +{ + /* flush hdp cache */ + WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); + + /* bits 0-7 are the VM contexts0-7 */ + WREG32(VM_INVALIDATE_REQUEST, 1); +} + +static int cayman_pcie_gart_enable(struct radeon_device *rdev) +{ + int i, r; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + /* Setup TLB control */ + WREG32(MC_VM_MX_L1_TLB_CNTL, + (0xA << 7) | + ENABLE_L1_TLB | + ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + ENABLE_ADVANCED_DRIVER_MODEL | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7) | + CONTEXT1_IDENTITY_ACCESS_MODE(1)); + WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); + WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + L2_CACHE_BIGK_FRAGMENT_SIZE(6)); + /* setup context0 */ + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); + WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT0_CNTL2, 0); + WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); + + WREG32(0x15D4, 0); + WREG32(0x15D8, 0); + WREG32(0x15DC, 0); + + /* empty context1-7 */ + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ + for (i = 1; i < 8; i++) { + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), + rdev->gart.table_addr >> 12); + } + + /* enable context1-7 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | + RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | + DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | + DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | + PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | + PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | + VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | + VALID_PROTECTION_FAULT_ENABLE_DEFAULT | + READ_PROTECTION_FAULT_ENABLE_INTERRUPT | + READ_PROTECTION_FAULT_ENABLE_DEFAULT | + WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | + WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + cayman_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +static void cayman_pcie_gart_disable(struct radeon_device *rdev) +{ + /* Disable all tables */ + WREG32(VM_CONTEXT0_CNTL, 0); + WREG32(VM_CONTEXT1_CNTL, 0); + /* Setup TLB control */ + WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7) | + CONTEXT1_IDENTITY_ACCESS_MODE(1)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + L2_CACHE_BIGK_FRAGMENT_SIZE(6)); + radeon_gart_table_vram_unpin(rdev); +} + +static void cayman_pcie_gart_fini(struct radeon_device *rdev) +{ + cayman_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); +} + +void cayman_cp_int_cntl_setup(struct radeon_device *rdev, + int ring, u32 cp_int_cntl) +{ + u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3; + + WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3)); + WREG32(CP_INT_CNTL, cp_int_cntl); +} + +/* + * CP. + */ +void cayman_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + + /* flush read cache over gart for this vmid */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ + /* EVENT_WRITE_EOP - flush caches, send int */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); + radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); + radeon_ring_write(ring, fence->seq); + radeon_ring_write(ring, 0); +} + +void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + + /* set to DX10/11 mode */ + radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); + radeon_ring_write(ring, 1); + + if (ring->rptr_save_reg) { + uint32_t next_rptr = ring->wptr + 3 + 4 + 8; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, ((ring->rptr_save_reg - + PACKET3_SET_CONFIG_REG_START) >> 2)); + radeon_ring_write(ring, next_rptr); + } + + radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); + radeon_ring_write(ring, ib->length_dw | + (ib->vm ? (ib->vm->id << 24) : 0)); + + /* flush read cache over gart for this vmid */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, ib->vm ? ib->vm->id : 0); + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ +} + +static void cayman_cp_enable(struct radeon_device *rdev, bool enable) +{ + if (enable) + WREG32(CP_ME_CNTL, 0); + else { + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); + WREG32(SCRATCH_UMSK, 0); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + } +} + +static int cayman_cp_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + int i; + + if (!rdev->me_fw || !rdev->pfp_fw) + return -EINVAL; + + cayman_cp_enable(rdev, false); + + fw_data = (const __be32 *)rdev->pfp_fw->data; + WREG32(CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++) + WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); + WREG32(CP_PFP_UCODE_ADDR, 0); + + fw_data = (const __be32 *)rdev->me_fw->data; + WREG32(CP_ME_RAM_WADDR, 0); + for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++) + WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); + + WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_RADDR, 0); + return 0; +} + +static int cayman_cp_start(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r, i; + + r = radeon_ring_lock(rdev, ring, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(ring, 0x1); + radeon_ring_write(ring, 0x0); + radeon_ring_write(ring, rdev->config.cayman.max_hw_contexts - 1); + radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_unlock_commit(rdev, ring); + + cayman_cp_enable(rdev, true); + + r = radeon_ring_lock(rdev, ring, cayman_default_size + 19); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + + /* setup clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + for (i = 0; i < cayman_default_size; i++) + radeon_ring_write(ring, cayman_default_state[i]); + + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); + + /* set clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); + radeon_ring_write(ring, 0); + + /* SQ_VTX_BASE_VTX_LOC */ + radeon_ring_write(ring, 0xc0026f00); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + radeon_ring_write(ring, 0x00000000); + + /* Clear consts */ + radeon_ring_write(ring, 0xc0036f00); + radeon_ring_write(ring, 0x00000bc4); + radeon_ring_write(ring, 0xffffffff); + radeon_ring_write(ring, 0xffffffff); + radeon_ring_write(ring, 0xffffffff); + + radeon_ring_write(ring, 0xc0026900); + radeon_ring_write(ring, 0x00000316); + radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + radeon_ring_write(ring, 0x00000010); /* */ + + radeon_ring_unlock_commit(rdev, ring); + + /* XXX init other rings */ + + return 0; +} + +static void cayman_cp_fini(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + cayman_cp_enable(rdev, false); + radeon_ring_fini(rdev, ring); + radeon_scratch_free(rdev, ring->rptr_save_reg); +} + +static int cayman_cp_resume(struct radeon_device *rdev) +{ + static const int ridx[] = { + RADEON_RING_TYPE_GFX_INDEX, + CAYMAN_RING_TYPE_CP1_INDEX, + CAYMAN_RING_TYPE_CP2_INDEX + }; + static const unsigned cp_rb_cntl[] = { + CP_RB0_CNTL, + CP_RB1_CNTL, + CP_RB2_CNTL, + }; + static const unsigned cp_rb_rptr_addr[] = { + CP_RB0_RPTR_ADDR, + CP_RB1_RPTR_ADDR, + CP_RB2_RPTR_ADDR + }; + static const unsigned cp_rb_rptr_addr_hi[] = { + CP_RB0_RPTR_ADDR_HI, + CP_RB1_RPTR_ADDR_HI, + CP_RB2_RPTR_ADDR_HI + }; + static const unsigned cp_rb_base[] = { + CP_RB0_BASE, + CP_RB1_BASE, + CP_RB2_BASE + }; + struct radeon_ring *ring; + int i, r; + + /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ + WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | + SOFT_RESET_PA | + SOFT_RESET_SH | + SOFT_RESET_VGT | + SOFT_RESET_SPI | + SOFT_RESET_SX)); + RREG32(GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(GRBM_SOFT_RESET, 0); + RREG32(GRBM_SOFT_RESET); + + WREG32(CP_SEM_WAIT_TIMER, 0x0); + WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); + + WREG32(CP_DEBUG, (1 << 27)); + + /* set the wb address whether it's enabled or not */ + WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); + WREG32(SCRATCH_UMSK, 0xff); + + for (i = 0; i < 3; ++i) { + uint32_t rb_cntl; + uint64_t addr; + + /* Set ring buffer size */ + ring = &rdev->ring[ridx[i]]; + rb_cntl = drm_order(ring->ring_size / 8); + rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8; +#ifdef __BIG_ENDIAN + rb_cntl |= BUF_SWAP_32BIT; +#endif + WREG32(cp_rb_cntl[i], rb_cntl); + + /* set the wb address whether it's enabled or not */ + addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET; + WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC); + WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF); + } + + /* set the rb base addr, this causes an internal reset of ALL rings */ + for (i = 0; i < 3; ++i) { + ring = &rdev->ring[ridx[i]]; + WREG32(cp_rb_base[i], ring->gpu_addr >> 8); + } + + for (i = 0; i < 3; ++i) { + /* Initialize the ring buffer's read and write pointers */ + ring = &rdev->ring[ridx[i]]; + WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); + + ring->rptr = ring->wptr = 0; + WREG32(ring->rptr_reg, ring->rptr); + WREG32(ring->wptr_reg, ring->wptr); + + DRM_MDELAY(1); + WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA); + } + + /* start the rings */ + cayman_cp_start(rdev); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + /* this only test cp0 */ + r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + return r; + } + + return 0; +} + +/* + * DMA + * Starting with R600, the GPU has an asynchronous + * DMA engine. The programming model is very similar + * to the 3D engine (ring buffer, IBs, etc.), but the + * DMA controller has it's own packet format that is + * different form the PM4 format used by the 3D engine. + * It supports copying data, writing embedded data, + * solid fills, and a number of other things. It also + * has support for tiling/detiling of buffers. + * Cayman and newer support two asynchronous DMA engines. + */ +/** + * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine + * + * @rdev: radeon_device pointer + * @ib: IB object to schedule + * + * Schedule an IB in the DMA ring (cayman-SI). + */ +void cayman_dma_ring_ib_execute(struct radeon_device *rdev, + struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + + if (rdev->wb.enabled) { + u32 next_rptr = ring->wptr + 4; + while ((next_rptr & 7) != 5) + next_rptr++; + next_rptr += 3; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1)); + radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff); + radeon_ring_write(ring, next_rptr); + } + + /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring. + * Pad as necessary with NOPs. + */ + while ((ring->wptr & 7) != 5) + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + radeon_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, ib->vm ? ib->vm->id : 0, 0)); + radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0)); + radeon_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF)); + +} + +/** + * cayman_dma_stop - stop the async dma engines + * + * @rdev: radeon_device pointer + * + * Stop the async dma engines (cayman-SI). + */ +void cayman_dma_stop(struct radeon_device *rdev) +{ + u32 rb_cntl; + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + + /* dma0 */ + rb_cntl = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); + rb_cntl &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, rb_cntl); + + /* dma1 */ + rb_cntl = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); + rb_cntl &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, rb_cntl); + + rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false; +} + +/** + * cayman_dma_resume - setup and start the async dma engines + * + * @rdev: radeon_device pointer + * + * Set up the DMA ring buffers and enable them. (cayman-SI). + * Returns 0 for success, error for failure. + */ +int cayman_dma_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + u32 rb_cntl, dma_cntl, ib_cntl; + u32 rb_bufsz; + u32 reg_offset, wb_offset; + int i, r; + + /* Reset dma */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); + RREG32(SRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(SRBM_SOFT_RESET, 0); + + for (i = 0; i < 2; i++) { + if (i == 0) { + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + reg_offset = DMA0_REGISTER_OFFSET; + wb_offset = R600_WB_DMA_RPTR_OFFSET; + } else { + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; + reg_offset = DMA1_REGISTER_OFFSET; + wb_offset = CAYMAN_WB_DMA1_RPTR_OFFSET; + } + + WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL + reg_offset, 0); + WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0); + + /* Set ring buffer size in dwords */ + rb_bufsz = drm_order(ring->ring_size / 4); + rb_cntl = rb_bufsz << 1; +#ifdef __BIG_ENDIAN + rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE; +#endif + WREG32(DMA_RB_CNTL + reg_offset, rb_cntl); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(DMA_RB_RPTR + reg_offset, 0); + WREG32(DMA_RB_WPTR + reg_offset, 0); + + /* set the wb address whether it's enabled or not */ + WREG32(DMA_RB_RPTR_ADDR_HI + reg_offset, + upper_32_bits(rdev->wb.gpu_addr + wb_offset) & 0xFF); + WREG32(DMA_RB_RPTR_ADDR_LO + reg_offset, + ((rdev->wb.gpu_addr + wb_offset) & 0xFFFFFFFC)); + + if (rdev->wb.enabled) + rb_cntl |= DMA_RPTR_WRITEBACK_ENABLE; + + WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8); + + /* enable DMA IBs */ + ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL + reg_offset, ib_cntl); + + dma_cntl = RREG32(DMA_CNTL + reg_offset); + dma_cntl &= ~CTXEMPTY_INT_ENABLE; + WREG32(DMA_CNTL + reg_offset, dma_cntl); + + ring->wptr = 0; + WREG32(DMA_RB_WPTR + reg_offset, ring->wptr << 2); + + ring->rptr = RREG32(DMA_RB_RPTR + reg_offset) >> 2; + + WREG32(DMA_RB_CNTL + reg_offset, rb_cntl | DMA_RB_ENABLE); + + ring->ready = true; + + r = radeon_ring_test(rdev, ring->idx, ring); + if (r) { + ring->ready = false; + return r; + } + } + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + + return 0; +} + +/** + * cayman_dma_fini - tear down the async dma engines + * + * @rdev: radeon_device pointer + * + * Stop the async dma engines and free the rings (cayman-SI). + */ +void cayman_dma_fini(struct radeon_device *rdev) +{ + cayman_dma_stop(rdev); + radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]); + radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]); +} + +static void cayman_gpu_soft_reset_gfx(struct radeon_device *rdev) +{ + u32 grbm_reset = 0; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + return; + + dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", + RREG32(CP_STALLED_STAT1)); + dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", + RREG32(CP_STALLED_STAT2)); + dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", + RREG32(CP_BUSY_STAT)); + dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", + RREG32(CP_STAT)); + + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); + + /* reset all the gfx blocks */ + grbm_reset = (SOFT_RESET_CP | + SOFT_RESET_CB | + SOFT_RESET_DB | + SOFT_RESET_GDS | + SOFT_RESET_PA | + SOFT_RESET_SC | + SOFT_RESET_SPI | + SOFT_RESET_SH | + SOFT_RESET_SX | + SOFT_RESET_TC | + SOFT_RESET_TA | + SOFT_RESET_VGT | + SOFT_RESET_IA); + + dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); + WREG32(GRBM_SOFT_RESET, grbm_reset); + (void)RREG32(GRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(GRBM_SOFT_RESET, 0); + (void)RREG32(GRBM_SOFT_RESET); + + dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", + RREG32(CP_STALLED_STAT1)); + dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", + RREG32(CP_STALLED_STAT2)); + dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", + RREG32(CP_BUSY_STAT)); + dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", + RREG32(CP_STAT)); + +} + +static void cayman_gpu_soft_reset_dma(struct radeon_device *rdev) +{ + u32 tmp; + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + return; + + dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); + + /* dma0 */ + tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); + + /* dma1 */ + tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); + + /* Reset dma */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); + RREG32(SRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(SRBM_SOFT_RESET, 0); + + dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); + +} + +static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) +{ + struct evergreen_mc_save save; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + + if (reset_mask == 0) + return 0; + + dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); + + dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", + RREG32(0x14F8)); + dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", + RREG32(0x14D8)); + dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", + RREG32(0x14FC)); + dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", + RREG32(0x14DC)); + + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + + if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) + cayman_gpu_soft_reset_gfx(rdev); + + if (reset_mask & RADEON_RESET_DMA) + cayman_gpu_soft_reset_dma(rdev); + + /* Wait a little for things to settle down */ + DRM_UDELAY(50); + + evergreen_mc_resume(rdev, &save); + return 0; +} + +int cayman_asic_reset(struct radeon_device *rdev) +{ + return cayman_gpu_soft_reset(rdev, (RADEON_RESET_GFX | + RADEON_RESET_COMPUTE | + RADEON_RESET_DMA)); +} + +/** + * cayman_dma_is_lockup - Check if the DMA engine is locked up + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Check if the async DMA engine is locked up (cayman-SI). + * Returns true if the engine appears to be locked up, false if not. + */ +bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 dma_status_reg; + + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + dma_status_reg = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET); + else + dma_status_reg = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET); + if (dma_status_reg & DMA_IDLE) { + radeon_ring_lockup_update(ring); + return false; + } + /* force ring activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +static int cayman_startup(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* enable pcie gen2 link */ + evergreen_pcie_gen2_enable(rdev); + + if (rdev->flags & RADEON_IS_IGP) { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } else { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + r = ni_mc_load_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); + return r; + } + } + + r = r600_vram_scratch_init(rdev); + if (r) + return r; + + evergreen_mc_program(rdev); + r = cayman_pcie_gart_enable(rdev); + if (r) + return r; + cayman_gpu_init(rdev); + + r = evergreen_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); + rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + + /* allocate rlc buffers */ + if (rdev->flags & RADEON_IS_IGP) { + r = si_rlc_init(rdev); + if (r) { + DRM_ERROR("Failed to init rlc BOs!\n"); + return r; + } + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_DMA1_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + evergreen_irq_set(rdev); + + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, + CP_RB0_RPTR, CP_RB0_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, + DMA_RB_RPTR + DMA0_REGISTER_OFFSET, + DMA_RB_WPTR + DMA0_REGISTER_OFFSET, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + if (r) + return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, + DMA_RB_RPTR + DMA1_REGISTER_OFFSET, + DMA_RB_WPTR + DMA1_REGISTER_OFFSET, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + if (r) + return r; + + r = cayman_cp_load_microcode(rdev); + if (r) + return r; + r = cayman_cp_resume(rdev); + if (r) + return r; + + r = cayman_dma_resume(rdev); + if (r) + return r; + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = radeon_vm_manager_init(rdev); + if (r) { + dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); + return r; + } + + r = r600_audio_init(rdev); + if (r) + return r; + + return 0; +} + +int cayman_resume(struct radeon_device *rdev) +{ + int r; + + /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, + * posting will perform necessary task to bring back GPU into good + * shape. + */ + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + + rdev->accel_working = true; + r = cayman_startup(rdev); + if (r) { + DRM_ERROR("cayman startup failed on resume\n"); + rdev->accel_working = false; + return r; + } + return r; +} + +int cayman_suspend(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + cayman_cp_enable(rdev, false); + cayman_dma_stop(rdev); + evergreen_irq_suspend(rdev); + radeon_wb_disable(rdev); + cayman_pcie_gart_disable(rdev); + return 0; +} + +/* Plan is to move initialization in that function and use + * helper function so that radeon_device_init pretty much + * do nothing more than calling asic specific function. This + * should also allow to remove a bunch of callback function + * like vram_info. + */ +int cayman_init(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* Read BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); + if (r) + return r; + + /* Post card if necessary */ + if (!radeon_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize scratch registers */ + r600_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + /* initialize memory controller */ + r = evergreen_mc_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 1024 * 1024); + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 64 * 1024); + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 64 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); + + r = r600_pcie_gart_init(rdev); + if (r) + return r; + + rdev->accel_working = true; + r = cayman_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + cayman_cp_fini(rdev); + cayman_dma_fini(rdev); + r600_irq_fini(rdev); + if (rdev->flags & RADEON_IS_IGP) + si_rlc_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_vm_manager_fini(rdev); + radeon_irq_kms_fini(rdev); + cayman_pcie_gart_fini(rdev); + rdev->accel_working = false; + } + + /* Don't start up if the MC ucode is missing. + * The default clocks and voltages before the MC ucode + * is loaded are not suffient for advanced operations. + * + * We can skip this check for TN, because there is no MC + * ucode. + */ + if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { + DRM_ERROR("radeon: MC ucode required for NI+.\n"); + return -EINVAL; + } + + return 0; +} + +void cayman_fini(struct radeon_device *rdev) +{ + r600_blit_fini(rdev); + cayman_cp_fini(rdev); + cayman_dma_fini(rdev); + r600_irq_fini(rdev); + if (rdev->flags & RADEON_IS_IGP) + si_rlc_fini(rdev); + radeon_wb_fini(rdev); + radeon_vm_manager_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + cayman_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + ni_fini_microcode(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +/* + * vm + */ +int cayman_vm_init(struct radeon_device *rdev) +{ + /* number of VMs */ + rdev->vm_manager.nvm = 8; + /* base offset of vram pages */ + if (rdev->flags & RADEON_IS_IGP) { + u64 tmp = RREG32(FUS_MC_VM_FB_OFFSET); + tmp <<= 22; + rdev->vm_manager.vram_base_offset = tmp; + } else + rdev->vm_manager.vram_base_offset = 0; + return 0; +} + +void cayman_vm_fini(struct radeon_device *rdev) +{ +} + +#define R600_ENTRY_VALID (1 << 0) +#define R600_PTE_SYSTEM (1 << 1) +#define R600_PTE_SNOOPED (1 << 2) +#define R600_PTE_READABLE (1 << 5) +#define R600_PTE_WRITEABLE (1 << 6) + +uint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags) +{ + uint32_t r600_flags = 0; + r600_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_ENTRY_VALID : 0; + r600_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0; + r600_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0; + if (flags & RADEON_VM_PAGE_SYSTEM) { + r600_flags |= R600_PTE_SYSTEM; + r600_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0; + } + return r600_flags; +} + +/** + * cayman_vm_set_page - update the page tables using the CP + * + * @rdev: radeon_device pointer + * @pe: addr of the page entry + * @addr: dst addr to write into pe + * @count: number of page entries to update + * @incr: increase next addr by incr bytes + * @flags: access flags + * + * Update the page tables using the CP (cayman-si). + */ +void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags) +{ + struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; + uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); + uint64_t value; + unsigned ndw; + + if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) { + while (count) { + ndw = 1 + count * 2; + if (ndw > 0x3FFF) + ndw = 0x3FFF; + + radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw)); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe) & 0xff); + for (; ndw > 1; ndw -= 2, --count, pe += 8) { + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + } else if (flags & RADEON_VM_PAGE_VALID) { + value = addr; + } else { + value = 0; + } + addr += incr; + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } + } + } else { + while (count) { + ndw = count * 2; + if (ndw > 0xFFFFE) + ndw = 0xFFFFE; + + /* for non-physically contiguous pages (system) */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw)); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe) & 0xff); + for (; ndw > 0; ndw -= 2, --count, pe += 8) { + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + } else if (flags & RADEON_VM_PAGE_VALID) { + value = addr; + } else { + value = 0; + } + addr += incr; + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } + } + } +} + +/** + * cayman_vm_flush - vm flush using the CP + * + * @rdev: radeon_device pointer + * + * Update the page table base and flush the VM TLB + * using the CP (cayman-si). + */ +void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) +{ + struct radeon_ring *ring = &rdev->ring[ridx]; + + if (vm == NULL) + return; + + radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0)); + radeon_ring_write(ring, vm->pd_gpu_addr >> 12); + + /* flush hdp cache */ + radeon_ring_write(ring, PACKET0(HDP_MEM_COHERENCY_FLUSH_CNTL, 0)); + radeon_ring_write(ring, 0x1); + + /* bits 0-7 are the VM contexts0-7 */ + radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); + radeon_ring_write(ring, 1 << vm->id); + + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); +} + +void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) +{ + struct radeon_ring *ring = &rdev->ring[ridx]; + + if (vm == NULL) + return; + + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); + radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2)); + radeon_ring_write(ring, vm->pd_gpu_addr >> 12); + + /* flush hdp cache */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); + radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2)); + radeon_ring_write(ring, 1); + + /* bits 0-7 are the VM contexts0-7 */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); + radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); + radeon_ring_write(ring, 1 << vm->id); +} + diff --git a/sys/dev/drm2/radeon/ni_reg.h b/sys/dev/drm2/radeon/ni_reg.h new file mode 100644 index 00000000000..f72c01c09b1 --- /dev/null +++ b/sys/dev/drm2/radeon/ni_reg.h @@ -0,0 +1,89 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#ifndef __NI_REG_H__ +#define __NI_REG_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* northern islands - DCE5 */ + +#define NI_INPUT_GAMMA_CONTROL 0x6840 +# define NI_GRPH_INPUT_GAMMA_MODE(x) (((x) & 0x3) << 0) +# define NI_INPUT_GAMMA_USE_LUT 0 +# define NI_INPUT_GAMMA_BYPASS 1 +# define NI_INPUT_GAMMA_SRGB_24 2 +# define NI_INPUT_GAMMA_XVYCC_222 3 +# define NI_OVL_INPUT_GAMMA_MODE(x) (((x) & 0x3) << 4) + +#define NI_PRESCALE_GRPH_CONTROL 0x68b4 +# define NI_GRPH_PRESCALE_BYPASS (1 << 4) + +#define NI_PRESCALE_OVL_CONTROL 0x68c4 +# define NI_OVL_PRESCALE_BYPASS (1 << 4) + +#define NI_INPUT_CSC_CONTROL 0x68d4 +# define NI_INPUT_CSC_GRPH_MODE(x) (((x) & 0x3) << 0) +# define NI_INPUT_CSC_BYPASS 0 +# define NI_INPUT_CSC_PROG_COEFF 1 +# define NI_INPUT_CSC_PROG_SHARED_MATRIXA 2 +# define NI_INPUT_CSC_OVL_MODE(x) (((x) & 0x3) << 4) + +#define NI_OUTPUT_CSC_CONTROL 0x68f0 +# define NI_OUTPUT_CSC_GRPH_MODE(x) (((x) & 0x7) << 0) +# define NI_OUTPUT_CSC_BYPASS 0 +# define NI_OUTPUT_CSC_TV_RGB 1 +# define NI_OUTPUT_CSC_YCBCR_601 2 +# define NI_OUTPUT_CSC_YCBCR_709 3 +# define NI_OUTPUT_CSC_PROG_COEFF 4 +# define NI_OUTPUT_CSC_PROG_SHARED_MATRIXB 5 +# define NI_OUTPUT_CSC_OVL_MODE(x) (((x) & 0x7) << 4) + +#define NI_DEGAMMA_CONTROL 0x6960 +# define NI_GRPH_DEGAMMA_MODE(x) (((x) & 0x3) << 0) +# define NI_DEGAMMA_BYPASS 0 +# define NI_DEGAMMA_SRGB_24 1 +# define NI_DEGAMMA_XVYCC_222 2 +# define NI_OVL_DEGAMMA_MODE(x) (((x) & 0x3) << 4) +# define NI_ICON_DEGAMMA_MODE(x) (((x) & 0x3) << 8) +# define NI_CURSOR_DEGAMMA_MODE(x) (((x) & 0x3) << 12) + +#define NI_GAMUT_REMAP_CONTROL 0x6964 +# define NI_GRPH_GAMUT_REMAP_MODE(x) (((x) & 0x3) << 0) +# define NI_GAMUT_REMAP_BYPASS 0 +# define NI_GAMUT_REMAP_PROG_COEFF 1 +# define NI_GAMUT_REMAP_PROG_SHARED_MATRIXA 2 +# define NI_GAMUT_REMAP_PROG_SHARED_MATRIXB 3 +# define NI_OVL_GAMUT_REMAP_MODE(x) (((x) & 0x3) << 4) + +#define NI_REGAMMA_CONTROL 0x6a80 +# define NI_GRPH_REGAMMA_MODE(x) (((x) & 0x7) << 0) +# define NI_REGAMMA_BYPASS 0 +# define NI_REGAMMA_SRGB_24 1 +# define NI_REGAMMA_XVYCC_222 2 +# define NI_REGAMMA_PROG_A 3 +# define NI_REGAMMA_PROG_B 4 +# define NI_OVL_REGAMMA_MODE(x) (((x) & 0x7) << 4) + +#endif diff --git a/sys/dev/drm2/radeon/nid.h b/sys/dev/drm2/radeon/nid.h new file mode 100644 index 00000000000..afe7a328698 --- /dev/null +++ b/sys/dev/drm2/radeon/nid.h @@ -0,0 +1,680 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#ifndef NI_H +#define NI_H + +#include +__FBSDID("$FreeBSD$"); + +#define CAYMAN_MAX_SH_GPRS 256 +#define CAYMAN_MAX_TEMP_GPRS 16 +#define CAYMAN_MAX_SH_THREADS 256 +#define CAYMAN_MAX_SH_STACK_ENTRIES 4096 +#define CAYMAN_MAX_FRC_EOV_CNT 16384 +#define CAYMAN_MAX_BACKENDS 8 +#define CAYMAN_MAX_BACKENDS_MASK 0xFF +#define CAYMAN_MAX_BACKENDS_PER_SE_MASK 0xF +#define CAYMAN_MAX_SIMDS 16 +#define CAYMAN_MAX_SIMDS_MASK 0xFFFF +#define CAYMAN_MAX_SIMDS_PER_SE_MASK 0xFFF +#define CAYMAN_MAX_PIPES 8 +#define CAYMAN_MAX_PIPES_MASK 0xFF +#define CAYMAN_MAX_LDS_NUM 0xFFFF +#define CAYMAN_MAX_TCC 16 +#define CAYMAN_MAX_TCC_MASK 0xFF + +#define CAYMAN_GB_ADDR_CONFIG_GOLDEN 0x02011003 +#define ARUBA_GB_ADDR_CONFIG_GOLDEN 0x12010001 + +#define DMIF_ADDR_CONFIG 0xBD4 +#define SRBM_GFX_CNTL 0x0E44 +#define RINGID(x) (((x) & 0x3) << 0) +#define VMID(x) (((x) & 0x7) << 0) +#define SRBM_STATUS 0x0E50 + +#define SRBM_SOFT_RESET 0x0E60 +#define SOFT_RESET_BIF (1 << 1) +#define SOFT_RESET_CG (1 << 2) +#define SOFT_RESET_DC (1 << 5) +#define SOFT_RESET_DMA1 (1 << 6) +#define SOFT_RESET_GRBM (1 << 8) +#define SOFT_RESET_HDP (1 << 9) +#define SOFT_RESET_IH (1 << 10) +#define SOFT_RESET_MC (1 << 11) +#define SOFT_RESET_RLC (1 << 13) +#define SOFT_RESET_ROM (1 << 14) +#define SOFT_RESET_SEM (1 << 15) +#define SOFT_RESET_VMC (1 << 17) +#define SOFT_RESET_DMA (1 << 20) +#define SOFT_RESET_TST (1 << 21) +#define SOFT_RESET_REGBB (1 << 22) +#define SOFT_RESET_ORB (1 << 23) + +#define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 +#define REQUEST_TYPE(x) (((x) & 0xf) << 0) +#define RESPONSE_TYPE_MASK 0x000000F0 +#define RESPONSE_TYPE_SHIFT 4 +#define VM_L2_CNTL 0x1400 +#define ENABLE_L2_CACHE (1 << 0) +#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) +#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) +#define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) +#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 14) +#define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 18) +/* CONTEXT1_IDENTITY_ACCESS_MODE + * 0 physical = logical + * 1 logical via context1 page table + * 2 inside identity aperture use translation, outside physical = logical + * 3 inside identity aperture physical = logical, outside use translation + */ +#define VM_L2_CNTL2 0x1404 +#define INVALIDATE_ALL_L1_TLBS (1 << 0) +#define INVALIDATE_L2_CACHE (1 << 1) +#define VM_L2_CNTL3 0x1408 +#define BANK_SELECT(x) ((x) << 0) +#define CACHE_UPDATE_MODE(x) ((x) << 6) +#define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) +#define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) +#define VM_L2_STATUS 0x140C +#define L2_BUSY (1 << 0) +#define VM_CONTEXT0_CNTL 0x1410 +#define ENABLE_CONTEXT (1 << 0) +#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) +#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) +#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) +#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) +#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) +#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) +#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) +#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) +#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) +#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) +#define VM_CONTEXT1_CNTL 0x1414 +#define VM_CONTEXT0_CNTL2 0x1430 +#define VM_CONTEXT1_CNTL2 0x1434 +#define VM_INVALIDATE_REQUEST 0x1478 +#define VM_INVALIDATE_RESPONSE 0x147c +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 +#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c +#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C +#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C +#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C + +#define MC_SHARED_CHMAP 0x2004 +#define NOOFCHAN_SHIFT 12 +#define NOOFCHAN_MASK 0x00003000 +#define MC_SHARED_CHREMAP 0x2008 + +#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 +#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 +#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C +#define MC_VM_MX_L1_TLB_CNTL 0x2064 +#define ENABLE_L1_TLB (1 << 0) +#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) +#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) +#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) +#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) +#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) +#define FUS_MC_VM_FB_OFFSET 0x2068 + +#define MC_SHARED_BLACKOUT_CNTL 0x20ac +#define MC_ARB_RAMCFG 0x2760 +#define NOOFBANK_SHIFT 0 +#define NOOFBANK_MASK 0x00000003 +#define NOOFRANK_SHIFT 2 +#define NOOFRANK_MASK 0x00000004 +#define NOOFROWS_SHIFT 3 +#define NOOFROWS_MASK 0x00000038 +#define NOOFCOLS_SHIFT 6 +#define NOOFCOLS_MASK 0x000000C0 +#define CHANSIZE_SHIFT 8 +#define CHANSIZE_MASK 0x00000100 +#define BURSTLENGTH_SHIFT 9 +#define BURSTLENGTH_MASK 0x00000200 +#define CHANSIZE_OVERRIDE (1 << 11) +#define MC_SEQ_SUP_CNTL 0x28c8 +#define RUN_MASK (1 << 0) +#define MC_SEQ_SUP_PGM 0x28cc +#define MC_IO_PAD_CNTL_D0 0x29d0 +#define MEM_FALL_OUT_CMD (1 << 8) +#define MC_SEQ_MISC0 0x2a00 +#define MC_SEQ_MISC0_GDDR5_SHIFT 28 +#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 +#define MC_SEQ_MISC0_GDDR5_VALUE 5 +#define MC_SEQ_IO_DEBUG_INDEX 0x2a44 +#define MC_SEQ_IO_DEBUG_DATA 0x2a48 + +#define HDP_HOST_PATH_CNTL 0x2C00 +#define HDP_NONSURFACE_BASE 0x2C04 +#define HDP_NONSURFACE_INFO 0x2C08 +#define HDP_NONSURFACE_SIZE 0x2C0C +#define HDP_ADDR_CONFIG 0x2F48 +#define HDP_MISC_CNTL 0x2F4C +#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) + +#define CC_SYS_RB_BACKEND_DISABLE 0x3F88 +#define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C +#define CGTS_SYS_TCC_DISABLE 0x3F90 +#define CGTS_USER_SYS_TCC_DISABLE 0x3F94 + +#define RLC_GFX_INDEX 0x3FC4 + +#define CONFIG_MEMSIZE 0x5428 + +#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 +#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 + +#define GRBM_CNTL 0x8000 +#define GRBM_READ_TIMEOUT(x) ((x) << 0) +#define GRBM_STATUS 0x8010 +#define CMDFIFO_AVAIL_MASK 0x0000000F +#define RING2_RQ_PENDING (1 << 4) +#define SRBM_RQ_PENDING (1 << 5) +#define RING1_RQ_PENDING (1 << 6) +#define CF_RQ_PENDING (1 << 7) +#define PF_RQ_PENDING (1 << 8) +#define GDS_DMA_RQ_PENDING (1 << 9) +#define GRBM_EE_BUSY (1 << 10) +#define SX_CLEAN (1 << 11) +#define DB_CLEAN (1 << 12) +#define CB_CLEAN (1 << 13) +#define TA_BUSY (1 << 14) +#define GDS_BUSY (1 << 15) +#define VGT_BUSY_NO_DMA (1 << 16) +#define VGT_BUSY (1 << 17) +#define IA_BUSY_NO_DMA (1 << 18) +#define IA_BUSY (1 << 19) +#define SX_BUSY (1 << 20) +#define SH_BUSY (1 << 21) +#define SPI_BUSY (1 << 22) +#define SC_BUSY (1 << 24) +#define PA_BUSY (1 << 25) +#define DB_BUSY (1 << 26) +#define CP_COHERENCY_BUSY (1 << 28) +#define CP_BUSY (1 << 29) +#define CB_BUSY (1 << 30) +#define GUI_ACTIVE (1 << 31) +#define GRBM_STATUS_SE0 0x8014 +#define GRBM_STATUS_SE1 0x8018 +#define SE_SX_CLEAN (1 << 0) +#define SE_DB_CLEAN (1 << 1) +#define SE_CB_CLEAN (1 << 2) +#define SE_VGT_BUSY (1 << 23) +#define SE_PA_BUSY (1 << 24) +#define SE_TA_BUSY (1 << 25) +#define SE_SX_BUSY (1 << 26) +#define SE_SPI_BUSY (1 << 27) +#define SE_SH_BUSY (1 << 28) +#define SE_SC_BUSY (1 << 29) +#define SE_DB_BUSY (1 << 30) +#define SE_CB_BUSY (1 << 31) +#define GRBM_SOFT_RESET 0x8020 +#define SOFT_RESET_CP (1 << 0) +#define SOFT_RESET_CB (1 << 1) +#define SOFT_RESET_DB (1 << 3) +#define SOFT_RESET_GDS (1 << 4) +#define SOFT_RESET_PA (1 << 5) +#define SOFT_RESET_SC (1 << 6) +#define SOFT_RESET_SPI (1 << 8) +#define SOFT_RESET_SH (1 << 9) +#define SOFT_RESET_SX (1 << 10) +#define SOFT_RESET_TC (1 << 11) +#define SOFT_RESET_TA (1 << 12) +#define SOFT_RESET_VGT (1 << 14) +#define SOFT_RESET_IA (1 << 15) + +#define GRBM_GFX_INDEX 0x802C +#define INSTANCE_INDEX(x) ((x) << 0) +#define SE_INDEX(x) ((x) << 16) +#define INSTANCE_BROADCAST_WRITES (1 << 30) +#define SE_BROADCAST_WRITES (1 << 31) + +#define SCRATCH_REG0 0x8500 +#define SCRATCH_REG1 0x8504 +#define SCRATCH_REG2 0x8508 +#define SCRATCH_REG3 0x850C +#define SCRATCH_REG4 0x8510 +#define SCRATCH_REG5 0x8514 +#define SCRATCH_REG6 0x8518 +#define SCRATCH_REG7 0x851C +#define SCRATCH_UMSK 0x8540 +#define SCRATCH_ADDR 0x8544 +#define CP_SEM_WAIT_TIMER 0x85BC +#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 +#define CP_COHER_CNTL2 0x85E8 +#define CP_STALLED_STAT1 0x8674 +#define CP_STALLED_STAT2 0x8678 +#define CP_BUSY_STAT 0x867C +#define CP_STAT 0x8680 +#define CP_ME_CNTL 0x86D8 +#define CP_ME_HALT (1 << 28) +#define CP_PFP_HALT (1 << 26) +#define CP_RB2_RPTR 0x86f8 +#define CP_RB1_RPTR 0x86fc +#define CP_RB0_RPTR 0x8700 +#define CP_RB_WPTR_DELAY 0x8704 +#define CP_MEQ_THRESHOLDS 0x8764 +#define MEQ1_START(x) ((x) << 0) +#define MEQ2_START(x) ((x) << 8) +#define CP_PERFMON_CNTL 0x87FC + +#define VGT_CACHE_INVALIDATION 0x88C4 +#define CACHE_INVALIDATION(x) ((x) << 0) +#define VC_ONLY 0 +#define TC_ONLY 1 +#define VC_AND_TC 2 +#define AUTO_INVLD_EN(x) ((x) << 6) +#define NO_AUTO 0 +#define ES_AUTO 1 +#define GS_AUTO 2 +#define ES_AND_GS_AUTO 3 +#define VGT_GS_VERTEX_REUSE 0x88D4 + +#define CC_GC_SHADER_PIPE_CONFIG 0x8950 +#define GC_USER_SHADER_PIPE_CONFIG 0x8954 +#define INACTIVE_QD_PIPES(x) ((x) << 8) +#define INACTIVE_QD_PIPES_MASK 0x0000FF00 +#define INACTIVE_QD_PIPES_SHIFT 8 +#define INACTIVE_SIMDS(x) ((x) << 16) +#define INACTIVE_SIMDS_MASK 0xFFFF0000 +#define INACTIVE_SIMDS_SHIFT 16 + +#define VGT_PRIMITIVE_TYPE 0x8958 +#define VGT_NUM_INSTANCES 0x8974 +#define VGT_TF_RING_SIZE 0x8988 +#define VGT_OFFCHIP_LDS_BASE 0x89b4 + +#define PA_SC_LINE_STIPPLE_STATE 0x8B10 +#define PA_CL_ENHANCE 0x8A14 +#define CLIP_VTX_REORDER_ENA (1 << 0) +#define NUM_CLIP_SEQ(x) ((x) << 1) +#define PA_SC_FIFO_SIZE 0x8BCC +#define SC_PRIM_FIFO_SIZE(x) ((x) << 0) +#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) +#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) +#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 +#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) + +#define SQ_CONFIG 0x8C00 +#define VC_ENABLE (1 << 0) +#define EXPORT_SRC_C (1 << 1) +#define GFX_PRIO(x) ((x) << 2) +#define CS1_PRIO(x) ((x) << 4) +#define CS2_PRIO(x) ((x) << 6) +#define SQ_GPR_RESOURCE_MGMT_1 0x8C04 +#define NUM_PS_GPRS(x) ((x) << 0) +#define NUM_VS_GPRS(x) ((x) << 16) +#define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) +#define SQ_ESGS_RING_SIZE 0x8c44 +#define SQ_GSVS_RING_SIZE 0x8c4c +#define SQ_ESTMP_RING_BASE 0x8c50 +#define SQ_ESTMP_RING_SIZE 0x8c54 +#define SQ_GSTMP_RING_BASE 0x8c58 +#define SQ_GSTMP_RING_SIZE 0x8c5c +#define SQ_VSTMP_RING_BASE 0x8c60 +#define SQ_VSTMP_RING_SIZE 0x8c64 +#define SQ_PSTMP_RING_BASE 0x8c68 +#define SQ_PSTMP_RING_SIZE 0x8c6c +#define SQ_MS_FIFO_SIZES 0x8CF0 +#define CACHE_FIFO_SIZE(x) ((x) << 0) +#define FETCH_FIFO_HIWATER(x) ((x) << 8) +#define DONE_FIFO_HIWATER(x) ((x) << 16) +#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) +#define SQ_LSTMP_RING_BASE 0x8e10 +#define SQ_LSTMP_RING_SIZE 0x8e14 +#define SQ_HSTMP_RING_BASE 0x8e18 +#define SQ_HSTMP_RING_SIZE 0x8e1c +#define SQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x8D8C +#define DYN_GPR_ENABLE (1 << 8) +#define SQ_CONST_MEM_BASE 0x8df8 + +#define SX_EXPORT_BUFFER_SIZES 0x900C +#define COLOR_BUFFER_SIZE(x) ((x) << 0) +#define POSITION_BUFFER_SIZE(x) ((x) << 8) +#define SMX_BUFFER_SIZE(x) ((x) << 16) +#define SX_DEBUG_1 0x9058 +#define ENABLE_NEW_SMX_ADDRESS (1 << 16) + +#define SPI_CONFIG_CNTL 0x9100 +#define GPR_WRITE_PRIORITY(x) ((x) << 0) +#define SPI_CONFIG_CNTL_1 0x913C +#define VTX_DONE_DELAY(x) ((x) << 0) +#define INTERP_ONE_PRIM_PER_ROW (1 << 4) +#define CRC_SIMD_ID_WADDR_DISABLE (1 << 8) + +#define CGTS_TCC_DISABLE 0x9148 +#define CGTS_USER_TCC_DISABLE 0x914C +#define TCC_DISABLE_MASK 0xFFFF0000 +#define TCC_DISABLE_SHIFT 16 +#define CGTS_SM_CTRL_REG 0x9150 +#define OVERRIDE (1 << 21) + +#define TA_CNTL_AUX 0x9508 +#define DISABLE_CUBE_WRAP (1 << 0) +#define DISABLE_CUBE_ANISO (1 << 1) + +#define TCP_CHAN_STEER_LO 0x960c +#define TCP_CHAN_STEER_HI 0x9610 + +#define CC_RB_BACKEND_DISABLE 0x98F4 +#define BACKEND_DISABLE(x) ((x) << 16) +#define GB_ADDR_CONFIG 0x98F8 +#define NUM_PIPES(x) ((x) << 0) +#define NUM_PIPES_MASK 0x00000007 +#define NUM_PIPES_SHIFT 0 +#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) +#define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 +#define PIPE_INTERLEAVE_SIZE_SHIFT 4 +#define BANK_INTERLEAVE_SIZE(x) ((x) << 8) +#define NUM_SHADER_ENGINES(x) ((x) << 12) +#define NUM_SHADER_ENGINES_MASK 0x00003000 +#define NUM_SHADER_ENGINES_SHIFT 12 +#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) +#define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 +#define SHADER_ENGINE_TILE_SIZE_SHIFT 16 +#define NUM_GPUS(x) ((x) << 20) +#define NUM_GPUS_MASK 0x00700000 +#define NUM_GPUS_SHIFT 20 +#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) +#define MULTI_GPU_TILE_SIZE_MASK 0x03000000 +#define MULTI_GPU_TILE_SIZE_SHIFT 24 +#define ROW_SIZE(x) ((x) << 28) +#define ROW_SIZE_MASK 0x30000000 +#define ROW_SIZE_SHIFT 28 +#define NUM_LOWER_PIPES(x) ((x) << 30) +#define NUM_LOWER_PIPES_MASK 0x40000000 +#define NUM_LOWER_PIPES_SHIFT 30 +#define GB_BACKEND_MAP 0x98FC + +#define CB_PERF_CTR0_SEL_0 0x9A20 +#define CB_PERF_CTR0_SEL_1 0x9A24 +#define CB_PERF_CTR1_SEL_0 0x9A28 +#define CB_PERF_CTR1_SEL_1 0x9A2C +#define CB_PERF_CTR2_SEL_0 0x9A30 +#define CB_PERF_CTR2_SEL_1 0x9A34 +#define CB_PERF_CTR3_SEL_0 0x9A38 +#define CB_PERF_CTR3_SEL_1 0x9A3C + +#define GC_USER_RB_BACKEND_DISABLE 0x9B7C +#define BACKEND_DISABLE_MASK 0x00FF0000 +#define BACKEND_DISABLE_SHIFT 16 + +#define SMX_DC_CTL0 0xA020 +#define USE_HASH_FUNCTION (1 << 0) +#define NUMBER_OF_SETS(x) ((x) << 1) +#define FLUSH_ALL_ON_EVENT (1 << 10) +#define STALL_ON_EVENT (1 << 11) +#define SMX_EVENT_CTL 0xA02C +#define ES_FLUSH_CTL(x) ((x) << 0) +#define GS_FLUSH_CTL(x) ((x) << 3) +#define ACK_FLUSH_CTL(x) ((x) << 6) +#define SYNC_FLUSH_CTL (1 << 8) + +#define CP_RB0_BASE 0xC100 +#define CP_RB0_CNTL 0xC104 +#define RB_BUFSZ(x) ((x) << 0) +#define RB_BLKSZ(x) ((x) << 8) +#define RB_NO_UPDATE (1 << 27) +#define RB_RPTR_WR_ENA (1 << 31) +#define BUF_SWAP_32BIT (2 << 16) +#define CP_RB0_RPTR_ADDR 0xC10C +#define CP_RB0_RPTR_ADDR_HI 0xC110 +#define CP_RB0_WPTR 0xC114 + +#define CP_INT_CNTL 0xC124 +# define CNTX_BUSY_INT_ENABLE (1 << 19) +# define CNTX_EMPTY_INT_ENABLE (1 << 20) +# define TIME_STAMP_INT_ENABLE (1 << 26) + +#define CP_RB1_BASE 0xC180 +#define CP_RB1_CNTL 0xC184 +#define CP_RB1_RPTR_ADDR 0xC188 +#define CP_RB1_RPTR_ADDR_HI 0xC18C +#define CP_RB1_WPTR 0xC190 +#define CP_RB2_BASE 0xC194 +#define CP_RB2_CNTL 0xC198 +#define CP_RB2_RPTR_ADDR 0xC19C +#define CP_RB2_RPTR_ADDR_HI 0xC1A0 +#define CP_RB2_WPTR 0xC1A4 +#define CP_PFP_UCODE_ADDR 0xC150 +#define CP_PFP_UCODE_DATA 0xC154 +#define CP_ME_RAM_RADDR 0xC158 +#define CP_ME_RAM_WADDR 0xC15C +#define CP_ME_RAM_DATA 0xC160 +#define CP_DEBUG 0xC1FC + +#define VGT_EVENT_INITIATOR 0x28a90 +# define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0) +# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) + +/* + * PM4 + */ +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) +#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ + (((reg) >> 2) & 0xFFFF) | \ + ((n) & 0x3FFF) << 16) +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) + +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) + +#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +/* Packet 3 types */ +#define PACKET3_NOP 0x10 +#define PACKET3_SET_BASE 0x11 +#define PACKET3_CLEAR_STATE 0x12 +#define PACKET3_INDEX_BUFFER_SIZE 0x13 +#define PACKET3_DEALLOC_STATE 0x14 +#define PACKET3_DISPATCH_DIRECT 0x15 +#define PACKET3_DISPATCH_INDIRECT 0x16 +#define PACKET3_INDIRECT_BUFFER_END 0x17 +#define PACKET3_MODE_CONTROL 0x18 +#define PACKET3_SET_PREDICATION 0x20 +#define PACKET3_REG_RMW 0x21 +#define PACKET3_COND_EXEC 0x22 +#define PACKET3_PRED_EXEC 0x23 +#define PACKET3_DRAW_INDIRECT 0x24 +#define PACKET3_DRAW_INDEX_INDIRECT 0x25 +#define PACKET3_INDEX_BASE 0x26 +#define PACKET3_DRAW_INDEX_2 0x27 +#define PACKET3_CONTEXT_CONTROL 0x28 +#define PACKET3_DRAW_INDEX_OFFSET 0x29 +#define PACKET3_INDEX_TYPE 0x2A +#define PACKET3_DRAW_INDEX 0x2B +#define PACKET3_DRAW_INDEX_AUTO 0x2D +#define PACKET3_DRAW_INDEX_IMMD 0x2E +#define PACKET3_NUM_INSTANCES 0x2F +#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 +#define PACKET3_INDIRECT_BUFFER 0x32 +#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 +#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 +#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 +#define PACKET3_WRITE_DATA 0x37 +#define PACKET3_MEM_SEMAPHORE 0x39 +#define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_WAIT_REG_MEM 0x3C +#define PACKET3_MEM_WRITE 0x3D +#define PACKET3_PFP_SYNC_ME 0x42 +#define PACKET3_SURFACE_SYNC 0x43 +# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) +# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) +# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) +# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) +# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) +# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) +# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) +# define PACKET3_DB_DEST_BASE_ENA (1 << 14) +# define PACKET3_CB8_DEST_BASE_ENA (1 << 15) +# define PACKET3_CB9_DEST_BASE_ENA (1 << 16) +# define PACKET3_CB10_DEST_BASE_ENA (1 << 17) +# define PACKET3_CB11_DEST_BASE_ENA (1 << 18) +# define PACKET3_FULL_CACHE_ENA (1 << 20) +# define PACKET3_TC_ACTION_ENA (1 << 23) +# define PACKET3_CB_ACTION_ENA (1 << 25) +# define PACKET3_DB_ACTION_ENA (1 << 26) +# define PACKET3_SH_ACTION_ENA (1 << 27) +# define PACKET3_SX_ACTION_ENA (1 << 28) +#define PACKET3_ME_INITIALIZE 0x44 +#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) +#define PACKET3_COND_WRITE 0x45 +#define PACKET3_EVENT_WRITE 0x46 +#define EVENT_TYPE(x) ((x) << 0) +#define EVENT_INDEX(x) ((x) << 8) + /* 0 - any non-TS event + * 1 - ZPASS_DONE + * 2 - SAMPLE_PIPELINESTAT + * 3 - SAMPLE_STREAMOUTSTAT* + * 4 - *S_PARTIAL_FLUSH + * 5 - TS events + */ +#define PACKET3_EVENT_WRITE_EOP 0x47 +#define DATA_SEL(x) ((x) << 29) + /* 0 - discard + * 1 - send low 32bit data + * 2 - send 64bit data + * 3 - send 64bit counter value + */ +#define INT_SEL(x) ((x) << 24) + /* 0 - none + * 1 - interrupt only (DATA_SEL = 0) + * 2 - interrupt when data write is confirmed + */ +#define PACKET3_EVENT_WRITE_EOS 0x48 +#define PACKET3_PREAMBLE_CNTL 0x4A +# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) +# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) +#define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C +#define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D +#define PACKET3_ALU_PS_CONST_UPDATE 0x4E +#define PACKET3_ALU_VS_CONST_UPDATE 0x4F +#define PACKET3_ONE_REG_WRITE 0x57 +#define PACKET3_SET_CONFIG_REG 0x68 +#define PACKET3_SET_CONFIG_REG_START 0x00008000 +#define PACKET3_SET_CONFIG_REG_END 0x0000ac00 +#define PACKET3_SET_CONTEXT_REG 0x69 +#define PACKET3_SET_CONTEXT_REG_START 0x00028000 +#define PACKET3_SET_CONTEXT_REG_END 0x00029000 +#define PACKET3_SET_ALU_CONST 0x6A +/* alu const buffers only; no reg file */ +#define PACKET3_SET_BOOL_CONST 0x6B +#define PACKET3_SET_BOOL_CONST_START 0x0003a500 +#define PACKET3_SET_BOOL_CONST_END 0x0003a518 +#define PACKET3_SET_LOOP_CONST 0x6C +#define PACKET3_SET_LOOP_CONST_START 0x0003a200 +#define PACKET3_SET_LOOP_CONST_END 0x0003a500 +#define PACKET3_SET_RESOURCE 0x6D +#define PACKET3_SET_RESOURCE_START 0x00030000 +#define PACKET3_SET_RESOURCE_END 0x00038000 +#define PACKET3_SET_SAMPLER 0x6E +#define PACKET3_SET_SAMPLER_START 0x0003c000 +#define PACKET3_SET_SAMPLER_END 0x0003c600 +#define PACKET3_SET_CTL_CONST 0x6F +#define PACKET3_SET_CTL_CONST_START 0x0003cff0 +#define PACKET3_SET_CTL_CONST_END 0x0003ff0c +#define PACKET3_SET_RESOURCE_OFFSET 0x70 +#define PACKET3_SET_ALU_CONST_VS 0x71 +#define PACKET3_SET_ALU_CONST_DI 0x72 +#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 +#define PACKET3_SET_RESOURCE_INDIRECT 0x74 +#define PACKET3_SET_APPEND_CNT 0x75 +#define PACKET3_ME_WRITE 0x7A + +/* ASYNC DMA - first instance at 0xd000, second at 0xd800 */ +#define DMA0_REGISTER_OFFSET 0x0 /* not a register */ +#define DMA1_REGISTER_OFFSET 0x800 /* not a register */ + +#define DMA_RB_CNTL 0xd000 +# define DMA_RB_ENABLE (1 << 0) +# define DMA_RB_SIZE(x) ((x) << 1) /* log2 */ +# define DMA_RB_SWAP_ENABLE (1 << 9) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_ENABLE (1 << 12) +# define DMA_RPTR_WRITEBACK_SWAP_ENABLE (1 << 13) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_TIMER(x) ((x) << 16) /* log2 */ +#define DMA_RB_BASE 0xd004 +#define DMA_RB_RPTR 0xd008 +#define DMA_RB_WPTR 0xd00c + +#define DMA_RB_RPTR_ADDR_HI 0xd01c +#define DMA_RB_RPTR_ADDR_LO 0xd020 + +#define DMA_IB_CNTL 0xd024 +# define DMA_IB_ENABLE (1 << 0) +# define DMA_IB_SWAP_ENABLE (1 << 4) +# define CMD_VMID_FORCE (1 << 31) +#define DMA_IB_RPTR 0xd028 +#define DMA_CNTL 0xd02c +# define TRAP_ENABLE (1 << 0) +# define SEM_INCOMPLETE_INT_ENABLE (1 << 1) +# define SEM_WAIT_INT_ENABLE (1 << 2) +# define DATA_SWAP_ENABLE (1 << 3) +# define FENCE_SWAP_ENABLE (1 << 4) +# define CTXEMPTY_INT_ENABLE (1 << 28) +#define DMA_STATUS_REG 0xd034 +# define DMA_IDLE (1 << 0) +#define DMA_SEM_INCOMPLETE_TIMER_CNTL 0xd044 +#define DMA_SEM_WAIT_FAIL_TIMER_CNTL 0xd048 +#define DMA_TILING_CONFIG 0xd0b8 +#define DMA_MODE 0xd0bc + +#define DMA_PACKET(cmd, t, s, n) ((((cmd) & 0xF) << 28) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((n) & 0xFFFFF) << 0)) + +#define DMA_IB_PACKET(cmd, vmid, n) ((((cmd) & 0xF) << 28) | \ + (((vmid) & 0xF) << 20) | \ + (((n) & 0xFFFFF) << 0)) + +/* async DMA Packet types */ +#define DMA_PACKET_WRITE 0x2 +#define DMA_PACKET_COPY 0x3 +#define DMA_PACKET_INDIRECT_BUFFER 0x4 +#define DMA_PACKET_SEMAPHORE 0x5 +#define DMA_PACKET_FENCE 0x6 +#define DMA_PACKET_TRAP 0x7 +#define DMA_PACKET_SRBM_WRITE 0x9 +#define DMA_PACKET_CONSTANT_FILL 0xd +#define DMA_PACKET_NOP 0xf + +#endif diff --git a/sys/dev/drm2/radeon/r100.c b/sys/dev/drm2/radeon/r100.c new file mode 100644 index 00000000000..595f9221ba0 --- /dev/null +++ b/sys/dev/drm2/radeon/r100.c @@ -0,0 +1,4201 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "radeon_asic.h" +#include "r100d.h" +#include "rs100d.h" +#include "rv200d.h" +#include "rv250d.h" +#include "atom.h" + +#include "r100_reg_safe.h" +#include "rn50_reg_safe.h" + +/* Firmware Names */ +#define FIRMWARE_R100 "radeonkmsfw_R100_cp" +#define FIRMWARE_R200 "radeonkmsfw_R200_cp" +#define FIRMWARE_R300 "radeonkmsfw_R300_cp" +#define FIRMWARE_R420 "radeonkmsfw_R420_cp" +#define FIRMWARE_RS690 "radeonkmsfw_RS690_cp" +#define FIRMWARE_RS600 "radeonkmsfw_RS600_cp" +#define FIRMWARE_R520 "radeonkmsfw_R520_cp" + +#include "r100_track.h" + +/* This files gather functions specifics to: + * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 + * and others in some cases. + */ + +/** + * r100_wait_for_vblank - vblank wait asic callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to wait for vblank on + * + * Wait for vblank on the requested crtc (r1xx-r4xx). + */ +void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + int i; + + if (crtc >= rdev->num_crtc) + return; + + if (crtc == 0) { + if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)) + break; + DRM_UDELAY(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) + break; + DRM_UDELAY(1); + } + } + } else { + if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)) + break; + DRM_UDELAY(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) + break; + DRM_UDELAY(1); + } + } + } +} + +/** + * r100_pre_page_flip - pre-pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to prepare for pageflip on + * + * Pre-pageflip callback (r1xx-r4xx). + * Enables the pageflip irq (vblank irq). + */ +void r100_pre_page_flip(struct radeon_device *rdev, int crtc) +{ + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); +} + +/** + * r100_post_page_flip - pos-pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to cleanup pageflip on + * + * Post-pageflip callback (r1xx-r4xx). + * Disables the pageflip irq (vblank irq). + */ +void r100_post_page_flip(struct radeon_device *rdev, int crtc) +{ + /* disable the pflip int */ + radeon_irq_kms_pflip_irq_put(rdev, crtc); +} + +/** + * r100_page_flip - pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to cleanup pageflip on + * @crtc_base: new address of the crtc (GPU MC address) + * + * Does the actual pageflip (r1xx-r4xx). + * During vblank we take the crtc lock and wait for the update_pending + * bit to go high, when it does, we release the lock, and allow the + * double buffered update to take place. + * Returns the current update pending status. + */ +u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; + int i; + + /* Lock the graphics update lock */ + /* update the scanout addresses */ + WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); + + /* Wait for update_pending to go high. */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) + break; + DRM_UDELAY(1); + } + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; + WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; +} + +/** + * r100_pm_get_dynpm_state - look up dynpm power state callback. + * + * @rdev: radeon_device pointer + * + * Look up the optimal power state based on the + * current state of the GPU (r1xx-r5xx). + * Used for dynpm only. + */ +void r100_pm_get_dynpm_state(struct radeon_device *rdev) +{ + int i; + rdev->pm.dynpm_can_upclock = true; + rdev->pm.dynpm_can_downclock = true; + + switch (rdev->pm.dynpm_planned_action) { + case DYNPM_ACTION_MINIMUM: + rdev->pm.requested_power_state_index = 0; + rdev->pm.dynpm_can_downclock = false; + break; + case DYNPM_ACTION_DOWNCLOCK: + if (rdev->pm.current_power_state_index == 0) { + rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; + rdev->pm.dynpm_can_downclock = false; + } else { + if (rdev->pm.active_crtc_count > 1) { + for (i = 0; i < rdev->pm.num_power_states; i++) { + if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + continue; + else if (i >= rdev->pm.current_power_state_index) { + rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; + break; + } else { + rdev->pm.requested_power_state_index = i; + break; + } + } + } else + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index - 1; + } + /* don't use the power state if crtcs are active and no display flag is set */ + if ((rdev->pm.active_crtc_count > 0) && + (rdev->pm.power_state[rdev->pm.requested_power_state_index].clock_info[0].flags & + RADEON_PM_MODE_NO_DISPLAY)) { + rdev->pm.requested_power_state_index++; + } + break; + case DYNPM_ACTION_UPCLOCK: + if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { + rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; + rdev->pm.dynpm_can_upclock = false; + } else { + if (rdev->pm.active_crtc_count > 1) { + for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { + if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + continue; + else if (i <= rdev->pm.current_power_state_index) { + rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; + break; + } else { + rdev->pm.requested_power_state_index = i; + break; + } + } + } else + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index + 1; + } + break; + case DYNPM_ACTION_DEFAULT: + rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.dynpm_can_upclock = false; + break; + case DYNPM_ACTION_NONE: + default: + DRM_ERROR("Requested mode for not defined action\n"); + return; + } + /* only one clock mode per power state */ + rdev->pm.requested_clock_mode_index = 0; + + DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n", + rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].sclk, + rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].mclk, + rdev->pm.power_state[rdev->pm.requested_power_state_index]. + pcie_lanes); +} + +/** + * r100_pm_init_profile - Initialize power profiles callback. + * + * @rdev: radeon_device pointer + * + * Initialize the power states used in profile mode + * (r1xx-r3xx). + * Used for profile mode only. + */ +void r100_pm_init_profile(struct radeon_device *rdev) +{ + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; +} + +/** + * r100_pm_misc - set additional pm hw parameters callback. + * + * @rdev: radeon_device pointer + * + * Set non-clock parameters associated with a power state + * (voltage, pcie lanes, etc.) (r1xx-r4xx). + */ +void r100_pm_misc(struct radeon_device *rdev) +{ + int requested_index = rdev->pm.requested_power_state_index; + struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; + struct radeon_voltage *voltage = &ps->clock_info[0].voltage; + u32 tmp, sclk_cntl, sclk_cntl2, sclk_more_cntl; + + if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) { + if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { + tmp = RREG32(voltage->gpio.reg); + if (voltage->active_high) + tmp |= voltage->gpio.mask; + else + tmp &= ~(voltage->gpio.mask); + WREG32(voltage->gpio.reg, tmp); + if (voltage->delay) + DRM_UDELAY(voltage->delay); + } else { + tmp = RREG32(voltage->gpio.reg); + if (voltage->active_high) + tmp &= ~voltage->gpio.mask; + else + tmp |= voltage->gpio.mask; + WREG32(voltage->gpio.reg, tmp); + if (voltage->delay) + DRM_UDELAY(voltage->delay); + } + } + + sclk_cntl = RREG32_PLL(SCLK_CNTL); + sclk_cntl2 = RREG32_PLL(SCLK_CNTL2); + sclk_cntl2 &= ~REDUCED_SPEED_SCLK_SEL(3); + sclk_more_cntl = RREG32_PLL(SCLK_MORE_CNTL); + sclk_more_cntl &= ~VOLTAGE_DELAY_SEL(3); + if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) { + sclk_more_cntl |= REDUCED_SPEED_SCLK_EN; + if (ps->misc & ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE) + sclk_cntl2 |= REDUCED_SPEED_SCLK_MODE; + else + sclk_cntl2 &= ~REDUCED_SPEED_SCLK_MODE; + if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) + sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(0); + else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) + sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(2); + } else + sclk_more_cntl &= ~REDUCED_SPEED_SCLK_EN; + + if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) { + sclk_more_cntl |= IO_CG_VOLTAGE_DROP; + if (voltage->delay) { + sclk_more_cntl |= VOLTAGE_DROP_SYNC; + switch (voltage->delay) { + case 33: + sclk_more_cntl |= VOLTAGE_DELAY_SEL(0); + break; + case 66: + sclk_more_cntl |= VOLTAGE_DELAY_SEL(1); + break; + case 99: + sclk_more_cntl |= VOLTAGE_DELAY_SEL(2); + break; + case 132: + sclk_more_cntl |= VOLTAGE_DELAY_SEL(3); + break; + } + } else + sclk_more_cntl &= ~VOLTAGE_DROP_SYNC; + } else + sclk_more_cntl &= ~IO_CG_VOLTAGE_DROP; + + if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN) + sclk_cntl &= ~FORCE_HDP; + else + sclk_cntl |= FORCE_HDP; + + WREG32_PLL(SCLK_CNTL, sclk_cntl); + WREG32_PLL(SCLK_CNTL2, sclk_cntl2); + WREG32_PLL(SCLK_MORE_CNTL, sclk_more_cntl); + + /* set pcie lanes */ + if ((rdev->flags & RADEON_IS_PCIE) && + !(rdev->flags & RADEON_IS_IGP) && + rdev->asic->pm.set_pcie_lanes && + (ps->pcie_lanes != + rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) { + radeon_set_pcie_lanes(rdev, + ps->pcie_lanes); + DRM_DEBUG_DRIVER("Setting: p: %d\n", ps->pcie_lanes); + } +} + +/** + * r100_pm_prepare - pre-power state change callback. + * + * @rdev: radeon_device pointer + * + * Prepare for a power state change (r1xx-r4xx). + */ +void r100_pm_prepare(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 tmp; + + /* disable any active CRTCs */ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + if (radeon_crtc->crtc_id) { + tmp = RREG32(RADEON_CRTC2_GEN_CNTL); + tmp |= RADEON_CRTC2_DISP_REQ_EN_B; + WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + } else { + tmp = RREG32(RADEON_CRTC_GEN_CNTL); + tmp |= RADEON_CRTC_DISP_REQ_EN_B; + WREG32(RADEON_CRTC_GEN_CNTL, tmp); + } + } + } +} + +/** + * r100_pm_finish - post-power state change callback. + * + * @rdev: radeon_device pointer + * + * Clean up after a power state change (r1xx-r4xx). + */ +void r100_pm_finish(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 tmp; + + /* enable any active CRTCs */ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + if (radeon_crtc->crtc_id) { + tmp = RREG32(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_DISP_REQ_EN_B; + WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + } else { + tmp = RREG32(RADEON_CRTC_GEN_CNTL); + tmp &= ~RADEON_CRTC_DISP_REQ_EN_B; + WREG32(RADEON_CRTC_GEN_CNTL, tmp); + } + } + } +} + +/** + * r100_gui_idle - gui idle callback. + * + * @rdev: radeon_device pointer + * + * Check of the GUI (2D/3D engines) are idle (r1xx-r5xx). + * Returns true if idle, false if not. + */ +bool r100_gui_idle(struct radeon_device *rdev) +{ + if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) + return false; + else + return true; +} + +/* hpd for digital panel detect/disconnect */ +/** + * r100_hpd_sense - hpd sense callback. + * + * @rdev: radeon_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Checks if a digital monitor is connected (r1xx-r4xx). + * Returns true if connected, false if not connected. + */ +bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + bool connected = false; + + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) + connected = true; + break; + default: + break; + } + return connected; +} + +/** + * r100_hpd_set_polarity - hpd set polarity callback. + * + * @rdev: radeon_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Set the polarity of the hpd pin (r1xx-r4xx). + */ +void r100_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = r100_hpd_sense(rdev, hpd); + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(RADEON_FP_GEN_CNTL); + if (connected) + tmp &= ~RADEON_FP_DETECT_INT_POL; + else + tmp |= RADEON_FP_DETECT_INT_POL; + WREG32(RADEON_FP_GEN_CNTL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(RADEON_FP2_GEN_CNTL); + if (connected) + tmp &= ~RADEON_FP2_DETECT_INT_POL; + else + tmp |= RADEON_FP2_DETECT_INT_POL; + WREG32(RADEON_FP2_GEN_CNTL, tmp); + break; + default: + break; + } +} + +/** + * r100_hpd_init - hpd setup callback. + * + * @rdev: radeon_device pointer + * + * Setup the hpd pins used by the card (r1xx-r4xx). + * Set the polarity, and enable the hpd interrupts. + */ +void r100_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned enable = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + enable |= 1 << radeon_connector->hpd.hpd; + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + } + radeon_irq_kms_enable_hpd(rdev, enable); +} + +/** + * r100_hpd_fini - hpd tear down callback. + * + * @rdev: radeon_device pointer + * + * Tear down the hpd pins used by the card (r1xx-r4xx). + * Disable the hpd interrupts. + */ +void r100_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned disable = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + disable |= 1 << radeon_connector->hpd.hpd; + } + radeon_irq_kms_disable_hpd(rdev, disable); +} + +/* + * PCI GART + */ +void r100_pci_gart_tlb_flush(struct radeon_device *rdev) +{ + /* TODO: can we do somethings here ? */ + /* It seems hw only cache one entry so we should discard this + * entry otherwise if first GPU GART read hit this entry it + * could end up in wrong address. */ +} + +int r100_pci_gart_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.ptr) { + DRM_ERROR("R100 PCI GART already initialized\n"); + return 0; + } + /* Initialize common gart structure */ + r = radeon_gart_init(rdev); + if (r) + return r; + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; + rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; + rdev->asic->gart.set_page = &r100_pci_gart_set_page; + return radeon_gart_table_ram_alloc(rdev); +} + +int r100_pci_gart_enable(struct radeon_device *rdev) +{ + uint32_t tmp; + + radeon_gart_restore(rdev); + /* discard memory request outside of configured range */ + tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; + WREG32(RADEON_AIC_CNTL, tmp); + /* set address range for PCI address translate */ + WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_start); + WREG32(RADEON_AIC_HI_ADDR, rdev->mc.gtt_end); + /* set PCI GART page-table base address */ + WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); + tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; + WREG32(RADEON_AIC_CNTL, tmp); + r100_pci_gart_tlb_flush(rdev); + DRM_INFO("PCI GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +void r100_pci_gart_disable(struct radeon_device *rdev) +{ + uint32_t tmp; + + /* discard memory request outside of configured range */ + tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; + WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); + WREG32(RADEON_AIC_LO_ADDR, 0); + WREG32(RADEON_AIC_HI_ADDR, 0); +} + +int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +{ + u32 *gtt = rdev->gart.ptr; + + if (i < 0 || i > rdev->gart.num_gpu_pages) { + return -EINVAL; + } + gtt[i] = cpu_to_le32(lower_32_bits(addr)); + return 0; +} + +void r100_pci_gart_fini(struct radeon_device *rdev) +{ + radeon_gart_fini(rdev); + r100_pci_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); +} + +int r100_irq_set(struct radeon_device *rdev) +{ + uint32_t tmp = 0; + + if (!rdev->irq.installed) { + DRM_ERROR("Can't enable IRQ/MSI because no handler is installed\n"); + WREG32(R_000040_GEN_INT_CNTL, 0); + return -EINVAL; + } + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + tmp |= RADEON_SW_INT_ENABLE; + } + if (rdev->irq.crtc_vblank_int[0] || + atomic_read(&rdev->irq.pflip[0])) { + tmp |= RADEON_CRTC_VBLANK_MASK; + } + if (rdev->irq.crtc_vblank_int[1] || + atomic_read(&rdev->irq.pflip[1])) { + tmp |= RADEON_CRTC2_VBLANK_MASK; + } + if (rdev->irq.hpd[0]) { + tmp |= RADEON_FP_DETECT_MASK; + } + if (rdev->irq.hpd[1]) { + tmp |= RADEON_FP2_DETECT_MASK; + } + WREG32(RADEON_GEN_INT_CNTL, tmp); + return 0; +} + +void r100_irq_disable(struct radeon_device *rdev) +{ + u32 tmp; + + WREG32(R_000040_GEN_INT_CNTL, 0); + /* Wait and acknowledge irq */ + DRM_MDELAY(1); + tmp = RREG32(R_000044_GEN_INT_STATUS); + WREG32(R_000044_GEN_INT_STATUS, tmp); +} + +static uint32_t r100_irq_ack(struct radeon_device *rdev) +{ + uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); + uint32_t irq_mask = RADEON_SW_INT_TEST | + RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT | + RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT; + + if (irqs) { + WREG32(RADEON_GEN_INT_STATUS, irqs); + } + return irqs & irq_mask; +} + +irqreturn_t r100_irq_process(struct radeon_device *rdev) +{ + uint32_t status, msi_rearm; + bool queue_hotplug = false; + + status = r100_irq_ack(rdev); + if (!status) { + return IRQ_NONE; + } + if (rdev->shutdown) { + return IRQ_NONE; + } + while (status) { + /* SW interrupt */ + if (status & RADEON_SW_INT_TEST) { + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + } + /* Vertical blank interrupts */ + if (status & RADEON_CRTC_VBLANK_STAT) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_flip(rdev, 0); + } + if (status & RADEON_CRTC2_VBLANK_STAT) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_flip(rdev, 1); + } + if (status & RADEON_FP_DETECT_STAT) { + queue_hotplug = true; + DRM_DEBUG("HPD1\n"); + } + if (status & RADEON_FP2_DETECT_STAT) { + queue_hotplug = true; + DRM_DEBUG("HPD2\n"); + } + status = r100_irq_ack(rdev); + } + if (queue_hotplug) + taskqueue_enqueue(rdev->tq, &rdev->hotplug_work); + if (rdev->msi_enabled) { + switch (rdev->family) { + case CHIP_RS400: + case CHIP_RS480: + msi_rearm = RREG32(RADEON_AIC_CNTL) & ~RS400_MSI_REARM; + WREG32(RADEON_AIC_CNTL, msi_rearm); + WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM); + break; + default: + WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); + break; + } + } + return IRQ_HANDLED; +} + +u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) +{ + if (crtc == 0) + return RREG32(RADEON_CRTC_CRNT_FRAME); + else + return RREG32(RADEON_CRTC2_CRNT_FRAME); +} + +/* Who ever call radeon_fence_emit should call ring_lock and ask + * for enough space (today caller are ib schedule and buffer move) */ +void r100_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + + /* We have to make sure that caches are flushed before + * CPU might read something from VRAM. */ + radeon_ring_write(ring, PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, RADEON_RB3D_DC_FLUSH_ALL); + radeon_ring_write(ring, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, RADEON_RB3D_ZC_FLUSH_ALL); + /* Wait until IDLE & CLEAN */ + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); + radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(ring, rdev->config.r100.hdp_cntl | + RADEON_HDP_READ_BUFFER_INVALIDATE); + radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(ring, rdev->config.r100.hdp_cntl); + /* Emit fence sequence & fire IRQ */ + radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); + radeon_ring_write(ring, fence->seq); + radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); + radeon_ring_write(ring, RADEON_SW_INT_FIRE); +} + +void r100_semaphore_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring, + struct radeon_semaphore *semaphore, + bool emit_wait) +{ + /* Unused on older asics, since we don't have semaphores or multiple rings */ + panic("%s: Unused on older asics", __func__); +} + +int r100_copy_blit(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t cur_pages; + uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE; + uint32_t pitch; + uint32_t stride_pixels; + unsigned ndw; + int num_loops; + int r = 0; + + /* radeon limited to 16k stride */ + stride_bytes &= 0x3fff; + /* radeon pitch is /64 */ + pitch = stride_bytes / 64; + stride_pixels = stride_bytes / 4; + num_loops = DIV_ROUND_UP(num_gpu_pages, 8191); + + /* Ask for enough room for blit + flush + fence */ + ndw = 64 + (10 * num_loops); + r = radeon_ring_lock(rdev, ring, ndw); + if (r) { + DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); + return -EINVAL; + } + while (num_gpu_pages > 0) { + cur_pages = num_gpu_pages; + if (cur_pages > 8191) { + cur_pages = 8191; + } + num_gpu_pages -= cur_pages; + + /* pages are in Y direction - height + page width in X direction - width */ + radeon_ring_write(ring, PACKET3(PACKET3_BITBLT_MULTI, 8)); + radeon_ring_write(ring, + RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_SRC_CLIPPING | + RADEON_GMC_DST_CLIPPING | + RADEON_GMC_BRUSH_NONE | + (RADEON_COLOR_FORMAT_ARGB8888 << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS); + radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10)); + radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10)); + radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); + radeon_ring_write(ring, num_gpu_pages); + radeon_ring_write(ring, num_gpu_pages); + radeon_ring_write(ring, cur_pages | (stride_pixels << 16)); + } + radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, RADEON_RB2D_DC_FLUSH_ALL); + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_HOST_IDLECLEAN | + RADEON_WAIT_DMA_GUI_IDLE); + if (fence) { + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); + } + radeon_ring_unlock_commit(rdev, ring); + return r; +} + +static int r100_cp_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + u32 tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_CP_CMDSTRM_BUSY(tmp)) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) +{ + int r; + + r = radeon_ring_lock(rdev, ring, 2); + if (r) { + return; + } + radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); + radeon_ring_write(ring, + RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI); + radeon_ring_unlock_commit(rdev, ring); +} + + +/* Load the microcode for the CP */ +static int r100_cp_init_microcode(struct radeon_device *rdev) +{ + const char *fw_name = NULL; + int err; + + DRM_DEBUG_KMS("\n"); + + if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || + (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) { + DRM_INFO("Loading R100 Microcode\n"); + fw_name = FIRMWARE_R100; + } else if ((rdev->family == CHIP_R200) || + (rdev->family == CHIP_RV250) || + (rdev->family == CHIP_RV280) || + (rdev->family == CHIP_RS300)) { + DRM_INFO("Loading R200 Microcode\n"); + fw_name = FIRMWARE_R200; + } else if ((rdev->family == CHIP_R300) || + (rdev->family == CHIP_R350) || + (rdev->family == CHIP_RV350) || + (rdev->family == CHIP_RV380) || + (rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + DRM_INFO("Loading R300 Microcode\n"); + fw_name = FIRMWARE_R300; + } else if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + DRM_INFO("Loading R400 Microcode\n"); + fw_name = FIRMWARE_R420; + } else if ((rdev->family == CHIP_RS690) || + (rdev->family == CHIP_RS740)) { + DRM_INFO("Loading RS690/RS740 Microcode\n"); + fw_name = FIRMWARE_RS690; + } else if (rdev->family == CHIP_RS600) { + DRM_INFO("Loading RS600 Microcode\n"); + fw_name = FIRMWARE_RS600; + } else if ((rdev->family == CHIP_RV515) || + (rdev->family == CHIP_R520) || + (rdev->family == CHIP_RV530) || + (rdev->family == CHIP_R580) || + (rdev->family == CHIP_RV560) || + (rdev->family == CHIP_RV570)) { + DRM_INFO("Loading R500 Microcode\n"); + fw_name = FIRMWARE_R520; + } + + err = 0; + rdev->me_fw = firmware_get(fw_name); + if (rdev->me_fw == NULL) { + DRM_ERROR("radeon_cp: Failed to load firmware \"%s\"\n", + fw_name); + err = -ENOENT; + } else if (rdev->me_fw->datasize % 8) { + DRM_ERROR( + "radeon_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->me_fw->datasize, fw_name); + err = -EINVAL; + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + return err; +} + +/** + * r100_cp_fini_microcode - drop the firmware image reference + * + * @rdev: radeon_device pointer + * + * Drop the me firmware image reference. + * Called at driver shutdown. + */ +static void r100_cp_fini_microcode (struct radeon_device *rdev) +{ + + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } +} + +static void r100_cp_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + int i, size; + + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } + + if (rdev->me_fw) { + size = rdev->me_fw->datasize / 4; + fw_data = (const __be32 *)rdev->me_fw->data; + WREG32(RADEON_CP_ME_RAM_ADDR, 0); + for (i = 0; i < size; i += 2) { + WREG32(RADEON_CP_ME_RAM_DATAH, + be32_to_cpup(&fw_data[i])); + WREG32(RADEON_CP_ME_RAM_DATAL, + be32_to_cpup(&fw_data[i + 1])); + } + } +} + +int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + unsigned rb_bufsz; + unsigned rb_blksz; + unsigned max_fetch; + unsigned pre_write_timer; + unsigned pre_write_limit; + unsigned indirect2_start; + unsigned indirect1_start; + uint32_t tmp; + int r; + + if (r100_debugfs_cp_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for CP !\n"); + } + if (!rdev->me_fw) { + r = r100_cp_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + /* Align ring size */ + rb_bufsz = drm_order(ring_size / 8); + ring_size = (1 << (rb_bufsz + 1)) * 4; + r100_cp_load_microcode(rdev); + r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET, + RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR, + 0, 0x7fffff, RADEON_CP_PACKET2); + if (r) { + return r; + } + /* Each time the cp read 1024 bytes (16 dword/quadword) update + * the rptr copy in system ram */ + rb_blksz = 9; + /* cp will read 128bytes at a time (4 dwords) */ + max_fetch = 1; + ring->align_mask = 16 - 1; + /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ + pre_write_timer = 64; + /* Force CP_RB_WPTR write if written more than one time before the + * delay expire + */ + pre_write_limit = 0; + /* Setup the cp cache like this (cache size is 96 dwords) : + * RING 0 to 15 + * INDIRECT1 16 to 79 + * INDIRECT2 80 to 95 + * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) + * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) + * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) + * Idea being that most of the gpu cmd will be through indirect1 buffer + * so it gets the bigger cache. + */ + indirect2_start = 80; + indirect1_start = 16; + /* cp setup */ + WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); + tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | + REG_SET(RADEON_RB_BLKSZ, rb_blksz) | + REG_SET(RADEON_MAX_FETCH, max_fetch)); +#ifdef __BIG_ENDIAN + tmp |= RADEON_BUF_SWAP_32BIT; +#endif + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_NO_UPDATE); + + /* Set ring address */ + DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)ring->gpu_addr); + WREG32(RADEON_CP_RB_BASE, ring->gpu_addr); + /* Force read & write ptr to 0 */ + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE); + WREG32(RADEON_CP_RB_RPTR_WR, 0); + ring->wptr = 0; + WREG32(RADEON_CP_RB_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(R_00070C_CP_RB_RPTR_ADDR, + S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) >> 2)); + WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET); + + if (rdev->wb.enabled) + WREG32(R_000770_SCRATCH_UMSK, 0xff); + else { + tmp |= RADEON_RB_NO_UPDATE; + WREG32(R_000770_SCRATCH_UMSK, 0); + } + + WREG32(RADEON_CP_RB_CNTL, tmp); + DRM_UDELAY(10); + ring->rptr = RREG32(RADEON_CP_RB_RPTR); + /* Set cp mode to bus mastering & enable cp*/ + WREG32(RADEON_CP_CSQ_MODE, + REG_SET(RADEON_INDIRECT2_START, indirect2_start) | + REG_SET(RADEON_INDIRECT1_START, indirect1_start)); + WREG32(RADEON_CP_RB_WPTR_DELAY, 0); + WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D); + WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); + + /* at this point everything should be setup correctly to enable master */ + pci_enable_busmaster(rdev->dev); + + radeon_ring_start(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); + if (r) { + DRM_ERROR("radeon: cp isn't working (%d).\n", r); + return r; + } + ring->ready = true; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + + if (!ring->rptr_save_reg /* not resuming from suspend */ + && radeon_ring_supports_scratch_reg(rdev, ring)) { + r = radeon_scratch_get(rdev, &ring->rptr_save_reg); + if (r) { + DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); + ring->rptr_save_reg = 0; + } + } + return 0; +} + +void r100_cp_fini(struct radeon_device *rdev) +{ + if (r100_cp_wait_for_idle(rdev)) { + DRM_ERROR("Wait for CP idle timeout, shutting down CP.\n"); + } + /* Disable ring */ + r100_cp_disable(rdev); + radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg); + radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + DRM_INFO("radeon: cp finalized\n"); +} + +void r100_cp_disable(struct radeon_device *rdev) +{ + /* Disable ring */ + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + WREG32(RADEON_CP_CSQ_MODE, 0); + WREG32(RADEON_CP_CSQ_CNTL, 0); + WREG32(R_000770_SCRATCH_UMSK, 0); + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } +} + +/* + * CS functions + */ +int r100_reloc_pitch_offset(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, + unsigned reg) +{ + int r; + u32 tile_flags = 0; + u32 tmp; + struct radeon_cs_reloc *reloc; + u32 value; + + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + + value = radeon_get_ib_value(p, idx); + tmp = value & 0x003fffff; + tmp += (((u32)reloc->lobj.gpu_offset) >> 10); + + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_DST_TILE_MACRO; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + if (reg == RADEON_SRC_PITCH_OFFSET) { + DRM_ERROR("Cannot src blit from microtiled surface\n"); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } + tile_flags |= RADEON_DST_TILE_MICRO; + } + + tmp |= tile_flags; + p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; + } else + p->ib.ptr[idx] = (value & 0xffc00000) | tmp; + return 0; +} + +int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + int idx) +{ + unsigned c, i; + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + int r = 0; + volatile uint32_t *ib; + u32 idx_value; + + ib = p->ib.ptr; + track = (struct r100_cs_track *)p->track; + c = radeon_get_ib_value(p, idx++) & 0x1F; + if (c > 16) { + DRM_ERROR("Only 16 vertex buffers are allowed %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } + track->num_arrays = c; + for (i = 0; i < (c - 1); i+=2, idx+=3) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + idx_value = radeon_get_ib_value(p, idx); + ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); + + track->arrays[i + 0].esize = idx_value >> 8; + track->arrays[i + 0].robj = reloc->robj; + track->arrays[i + 0].esize &= 0x7F; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); + track->arrays[i + 1].robj = reloc->robj; + track->arrays[i + 1].esize = idx_value >> 24; + track->arrays[i + 1].esize &= 0x7F; + } + if (c & 1) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + idx_value = radeon_get_ib_value(p, idx); + ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); + track->arrays[i + 0].robj = reloc->robj; + track->arrays[i + 0].esize = idx_value >> 8; + track->arrays[i + 0].esize &= 0x7F; + } + return r; +} + +int r100_cs_parse_packet0(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + const unsigned *auth, unsigned n, + radeon_packet0_check_t check) +{ + unsigned reg; + unsigned i, j, m; + unsigned idx; + int r; + + idx = pkt->idx + 1; + reg = pkt->reg; + /* Check that register fall into register range + * determined by the number of entry (n) in the + * safe register bitmap. + */ + if (pkt->one_reg_wr) { + if ((reg >> 7) > n) { + return -EINVAL; + } + } else { + if (((reg + (pkt->count << 2)) >> 7) > n) { + return -EINVAL; + } + } + for (i = 0; i <= pkt->count; i++, idx++) { + j = (reg >> 7); + m = 1 << ((reg >> 2) & 31); + if (auth[j] & m) { + r = check(p, pkt, idx, reg); + if (r) { + return r; + } + } + if (pkt->one_reg_wr) { + if (!(auth[j] & m)) { + break; + } + } else { + reg += 4; + } + } + return 0; +} + +void r100_cs_dump_packet(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + volatile uint32_t *ib; + unsigned i; + unsigned idx; + + ib = p->ib.ptr; + idx = pkt->idx; + for (i = 0; i <= (pkt->count + 1); i++, idx++) { + DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); + } +} + +/** + * r100_cs_packet_parse() - parse cp packet and point ib index to next packet + * @parser: parser structure holding parsing context. + * @pkt: where to store packet informations + * + * Assume that chunk_ib_index is properly set. Will return -EINVAL + * if packet is bigger than remaining ib size. or if packets is unknown. + **/ +int r100_cs_packet_parse(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx) +{ + struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; + uint32_t header; + + if (idx >= ib_chunk->length_dw) { + DRM_ERROR("Can not parse packet at %d after CS end %d !\n", + idx, ib_chunk->length_dw); + return -EINVAL; + } + header = radeon_get_ib_value(p, idx); + pkt->idx = idx; + pkt->type = CP_PACKET_GET_TYPE(header); + pkt->count = CP_PACKET_GET_COUNT(header); + switch (pkt->type) { + case PACKET_TYPE0: + pkt->reg = CP_PACKET0_GET_REG(header); + pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); + break; + case PACKET_TYPE3: + pkt->opcode = CP_PACKET3_GET_OPCODE(header); + break; + case PACKET_TYPE2: + pkt->count = -1; + break; + default: + DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); + return -EINVAL; + } + if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { + DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", + pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); + return -EINVAL; + } + return 0; +} + +/** + * r100_cs_packet_next_vline() - parse userspace VLINE packet + * @parser: parser structure holding parsing context. + * + * Userspace sends a special sequence for VLINE waits. + * PACKET0 - VLINE_START_END + value + * PACKET0 - WAIT_UNTIL +_value + * RELOC (P3) - crtc_id in reloc. + * + * This function parses this and relocates the VLINE START END + * and WAIT UNTIL packets to the correct crtc. + * It also detects a switched off crtc and nulls out the + * wait in that case. + */ +int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) +{ + struct drm_mode_object *obj; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + struct radeon_cs_packet p3reloc, waitreloc; + int crtc_id; + int r; + uint32_t header, h_idx, reg; + volatile uint32_t *ib; + + ib = p->ib.ptr; + + /* parse the wait until */ + r = r100_cs_packet_parse(p, &waitreloc, p->idx); + if (r) + return r; + + /* check its a wait until and only 1 count */ + if (waitreloc.reg != RADEON_WAIT_UNTIL || + waitreloc.count != 0) { + DRM_ERROR("vline wait had illegal wait until segment\n"); + return -EINVAL; + } + + if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) { + DRM_ERROR("vline wait had illegal wait until\n"); + return -EINVAL; + } + + /* jump over the NOP */ + r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2); + if (r) + return r; + + h_idx = p->idx - 2; + p->idx += waitreloc.count + 2; + p->idx += p3reloc.count + 2; + + header = radeon_get_ib_value(p, h_idx); + crtc_id = radeon_get_ib_value(p, h_idx + 5); + reg = CP_PACKET0_GET_REG(header); + obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_ERROR("cannot find crtc %d\n", crtc_id); + return -EINVAL; + } + crtc = obj_to_crtc(obj); + radeon_crtc = to_radeon_crtc(crtc); + crtc_id = radeon_crtc->crtc_id; + + if (!crtc->enabled) { + /* if the CRTC isn't enabled - we need to nop out the wait until */ + ib[h_idx + 2] = PACKET2(0); + ib[h_idx + 3] = PACKET2(0); + } else if (crtc_id == 1) { + switch (reg) { + case AVIVO_D1MODE_VLINE_START_END: + header &= ~R300_CP_PACKET0_REG_MASK; + header |= AVIVO_D2MODE_VLINE_START_END >> 2; + break; + case RADEON_CRTC_GUI_TRIG_VLINE: + header &= ~R300_CP_PACKET0_REG_MASK; + header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; + break; + default: + DRM_ERROR("unknown crtc reloc\n"); + return -EINVAL; + } + ib[h_idx] = header; + ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; + } + + return 0; +} + +/** + * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 + * @parser: parser structure holding parsing context. + * @data: pointer to relocation data + * @offset_start: starting offset + * @offset_mask: offset mask (to align start offset on) + * @reloc: reloc informations + * + * Check next packet is relocation packet3, do bo validation and compute + * GPU offset using the provided start. + **/ +int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc) +{ + struct radeon_cs_chunk *relocs_chunk; + struct radeon_cs_packet p3reloc; + unsigned idx; + int r; + + if (p->chunk_relocs_idx == -1) { + DRM_ERROR("No relocation chunk !\n"); + return -EINVAL; + } + *cs_reloc = NULL; + relocs_chunk = &p->chunks[p->chunk_relocs_idx]; + r = r100_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return r; + } + p->idx += p3reloc.count + 2; + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + DRM_ERROR("No packet3 for relocation for packet at %d.\n", + p3reloc.idx); + r100_cs_dump_packet(p, &p3reloc); + return -EINVAL; + } + idx = radeon_get_ib_value(p, p3reloc.idx + 1); + if (idx >= relocs_chunk->length_dw) { + DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", + idx, relocs_chunk->length_dw); + r100_cs_dump_packet(p, &p3reloc); + return -EINVAL; + } + /* FIXME: we assume reloc size is 4 dwords */ + *cs_reloc = p->relocs_ptr[(idx / 4)]; + return 0; +} + +static int r100_get_vtx_size(uint32_t vtx_fmt) +{ + int vtx_size; + vtx_size = 2; + /* ordered according to bits in spec */ + if (vtx_fmt & RADEON_SE_VTX_FMT_W0) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_FPCOLOR) + vtx_size += 3; + if (vtx_fmt & RADEON_SE_VTX_FMT_FPALPHA) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_PKCOLOR) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_FPSPEC) + vtx_size += 3; + if (vtx_fmt & RADEON_SE_VTX_FMT_FPFOG) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_PKSPEC) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_ST0) + vtx_size += 2; + if (vtx_fmt & RADEON_SE_VTX_FMT_ST1) + vtx_size += 2; + if (vtx_fmt & RADEON_SE_VTX_FMT_Q1) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_ST2) + vtx_size += 2; + if (vtx_fmt & RADEON_SE_VTX_FMT_Q2) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_ST3) + vtx_size += 2; + if (vtx_fmt & RADEON_SE_VTX_FMT_Q3) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_Q0) + vtx_size++; + /* blend weight */ + if (vtx_fmt & (0x7 << 15)) + vtx_size += (vtx_fmt >> 15) & 0x7; + if (vtx_fmt & RADEON_SE_VTX_FMT_N0) + vtx_size += 3; + if (vtx_fmt & RADEON_SE_VTX_FMT_XY1) + vtx_size += 2; + if (vtx_fmt & RADEON_SE_VTX_FMT_Z1) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_W1) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_N1) + vtx_size++; + if (vtx_fmt & RADEON_SE_VTX_FMT_Z) + vtx_size++; + return vtx_size; +} + +static int r100_packet0_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg) +{ + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + volatile uint32_t *ib; + uint32_t tmp; + int r; + int i, face; + u32 tile_flags = 0; + u32 idx_value; + + ib = p->ib.ptr; + track = (struct r100_cs_track *)p->track; + + idx_value = radeon_get_ib_value(p, idx); + + switch (reg) { + case RADEON_CRTC_GUI_TRIG_VLINE: + r = r100_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + break; + /* FIXME: only allow PACKET3 blit? easier to check for out of + * range access */ + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + r = r100_reloc_pitch_offset(p, pkt, idx, reg); + if (r) + return r; + break; + case RADEON_RB3D_DEPTHOFFSET: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->zb.robj = reloc->robj; + track->zb.offset = idx_value; + track->zb_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case RADEON_RB3D_COLOROFFSET: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->cb[0].robj = reloc->robj; + track->cb[0].offset = idx_value; + track->cb_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case RADEON_PP_TXOFFSET_0: + case RADEON_PP_TXOFFSET_1: + case RADEON_PP_TXOFFSET_2: + i = (reg - RADEON_PP_TXOFFSET_0) / 24; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_TXO_MACRO_TILE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= RADEON_TXO_MICRO_TILE_X2; + + tmp = idx_value & ~(0x7 << 2); + tmp |= tile_flags; + ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset); + } else + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[i].robj = reloc->robj; + track->tex_dirty = true; + break; + case RADEON_PP_CUBIC_OFFSET_T0_0: + case RADEON_PP_CUBIC_OFFSET_T0_1: + case RADEON_PP_CUBIC_OFFSET_T0_2: + case RADEON_PP_CUBIC_OFFSET_T0_3: + case RADEON_PP_CUBIC_OFFSET_T0_4: + i = (reg - RADEON_PP_CUBIC_OFFSET_T0_0) / 4; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->textures[0].cube_info[i].offset = idx_value; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[0].cube_info[i].robj = reloc->robj; + track->tex_dirty = true; + break; + case RADEON_PP_CUBIC_OFFSET_T1_0: + case RADEON_PP_CUBIC_OFFSET_T1_1: + case RADEON_PP_CUBIC_OFFSET_T1_2: + case RADEON_PP_CUBIC_OFFSET_T1_3: + case RADEON_PP_CUBIC_OFFSET_T1_4: + i = (reg - RADEON_PP_CUBIC_OFFSET_T1_0) / 4; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->textures[1].cube_info[i].offset = idx_value; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[1].cube_info[i].robj = reloc->robj; + track->tex_dirty = true; + break; + case RADEON_PP_CUBIC_OFFSET_T2_0: + case RADEON_PP_CUBIC_OFFSET_T2_1: + case RADEON_PP_CUBIC_OFFSET_T2_2: + case RADEON_PP_CUBIC_OFFSET_T2_3: + case RADEON_PP_CUBIC_OFFSET_T2_4: + i = (reg - RADEON_PP_CUBIC_OFFSET_T2_0) / 4; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->textures[2].cube_info[i].offset = idx_value; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[2].cube_info[i].robj = reloc->robj; + track->tex_dirty = true; + break; + case RADEON_RE_WIDTH_HEIGHT: + track->maxy = ((idx_value >> 16) & 0x7FF); + track->cb_dirty = true; + track->zb_dirty = true; + break; + case RADEON_RB3D_COLORPITCH: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_COLOR_TILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; + + tmp = idx_value & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + } else + ib[idx] = idx_value; + + track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK; + track->cb_dirty = true; + break; + case RADEON_RB3D_DEPTHPITCH: + track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK; + track->zb_dirty = true; + break; + case RADEON_RB3D_CNTL: + switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { + case 7: + case 8: + case 9: + case 11: + case 12: + track->cb[0].cpp = 1; + break; + case 3: + case 4: + case 15: + track->cb[0].cpp = 2; + break; + case 6: + track->cb[0].cpp = 4; + break; + default: + DRM_ERROR("Invalid color buffer format (%d) !\n", + ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); + return -EINVAL; + } + track->z_enabled = !!(idx_value & RADEON_Z_ENABLE); + track->cb_dirty = true; + track->zb_dirty = true; + break; + case RADEON_RB3D_ZSTENCILCNTL: + switch (idx_value & 0xf) { + case 0: + track->zb.cpp = 2; + break; + case 2: + case 3: + case 4: + case 5: + case 9: + case 11: + track->zb.cpp = 4; + break; + default: + break; + } + track->zb_dirty = true; + break; + case RADEON_RB3D_ZPASS_ADDR: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case RADEON_PP_CNTL: + { + uint32_t temp = idx_value >> 4; + for (i = 0; i < track->num_texture; i++) + track->textures[i].enabled = !!(temp & (1 << i)); + track->tex_dirty = true; + } + break; + case RADEON_SE_VF_CNTL: + track->vap_vf_cntl = idx_value; + break; + case RADEON_SE_VTX_FMT: + track->vtx_size = r100_get_vtx_size(idx_value); + break; + case RADEON_PP_TEX_SIZE_0: + case RADEON_PP_TEX_SIZE_1: + case RADEON_PP_TEX_SIZE_2: + i = (reg - RADEON_PP_TEX_SIZE_0) / 8; + track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1; + track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; + track->tex_dirty = true; + break; + case RADEON_PP_TEX_PITCH_0: + case RADEON_PP_TEX_PITCH_1: + case RADEON_PP_TEX_PITCH_2: + i = (reg - RADEON_PP_TEX_PITCH_0) / 8; + track->textures[i].pitch = idx_value + 32; + track->tex_dirty = true; + break; + case RADEON_PP_TXFILTER_0: + case RADEON_PP_TXFILTER_1: + case RADEON_PP_TXFILTER_2: + i = (reg - RADEON_PP_TXFILTER_0) / 24; + track->textures[i].num_levels = ((idx_value & RADEON_MAX_MIP_LEVEL_MASK) + >> RADEON_MAX_MIP_LEVEL_SHIFT); + tmp = (idx_value >> 23) & 0x7; + if (tmp == 2 || tmp == 6) + track->textures[i].roundup_w = false; + tmp = (idx_value >> 27) & 0x7; + if (tmp == 2 || tmp == 6) + track->textures[i].roundup_h = false; + track->tex_dirty = true; + break; + case RADEON_PP_TXFORMAT_0: + case RADEON_PP_TXFORMAT_1: + case RADEON_PP_TXFORMAT_2: + i = (reg - RADEON_PP_TXFORMAT_0) / 24; + if (idx_value & RADEON_TXFORMAT_NON_POWER2) { + track->textures[i].use_pitch = 1; + } else { + track->textures[i].use_pitch = 0; + track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); + track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); + } + if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) + track->textures[i].tex_coord_type = 2; + switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) { + case RADEON_TXFORMAT_I8: + case RADEON_TXFORMAT_RGB332: + case RADEON_TXFORMAT_Y8: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case RADEON_TXFORMAT_AI88: + case RADEON_TXFORMAT_ARGB1555: + case RADEON_TXFORMAT_RGB565: + case RADEON_TXFORMAT_ARGB4444: + case RADEON_TXFORMAT_VYUY422: + case RADEON_TXFORMAT_YVYU422: + case RADEON_TXFORMAT_SHADOW16: + case RADEON_TXFORMAT_LDUDV655: + case RADEON_TXFORMAT_DUDV88: + track->textures[i].cpp = 2; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case RADEON_TXFORMAT_ARGB8888: + case RADEON_TXFORMAT_RGBA8888: + case RADEON_TXFORMAT_SHADOW32: + case RADEON_TXFORMAT_LDUDUV8888: + track->textures[i].cpp = 4; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case RADEON_TXFORMAT_DXT1: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; + case RADEON_TXFORMAT_DXT23: + case RADEON_TXFORMAT_DXT45: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT35; + break; + } + track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf); + track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf); + track->tex_dirty = true; + break; + case RADEON_PP_CUBIC_FACES_0: + case RADEON_PP_CUBIC_FACES_1: + case RADEON_PP_CUBIC_FACES_2: + tmp = idx_value; + i = (reg - RADEON_PP_CUBIC_FACES_0) / 4; + for (face = 0; face < 4; face++) { + track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); + track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf); + } + track->tex_dirty = true; + break; + default: + DRM_ERROR("Forbidden register 0x%04X in cs at %d\n", + reg, idx); + return -EINVAL; + } + return 0; +} + +int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + struct radeon_bo *robj) +{ + unsigned idx; + u32 value; + idx = pkt->idx + 1; + value = radeon_get_ib_value(p, idx + 2); + if ((value + 1) > radeon_bo_size(robj)) { + DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " + "(need %u have %lu) !\n", + value + 1, + radeon_bo_size(robj)); + return -EINVAL; + } + return 0; +} + +static int r100_packet3_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + unsigned idx; + volatile uint32_t *ib; + int r; + + ib = p->ib.ptr; + idx = pkt->idx + 1; + track = (struct r100_cs_track *)p->track; + switch (pkt->opcode) { + case PACKET3_3D_LOAD_VBPNTR: + r = r100_packet3_load_vbpntr(p, pkt, idx); + if (r) + return r; + break; + case PACKET3_INDX_BUFFER: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset); + r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); + if (r) { + return r; + } + break; + case 0x23: + /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset); + track->num_arrays = 1; + track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 2)); + + track->arrays[0].robj = reloc->robj; + track->arrays[0].esize = track->vtx_size; + + track->max_indx = radeon_get_ib_value(p, idx+1); + + track->vap_vf_cntl = radeon_get_ib_value(p, idx+3); + track->immd_dwords = pkt->count - 1; + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + case PACKET3_3D_DRAW_IMMD: + if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) { + DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); + return -EINVAL; + } + track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0)); + track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); + track->immd_dwords = pkt->count - 1; + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + /* triggers drawing using in-packet vertex data */ + case PACKET3_3D_DRAW_IMMD_2: + if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) { + DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); + return -EINVAL; + } + track->vap_vf_cntl = radeon_get_ib_value(p, idx); + track->immd_dwords = pkt->count; + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + /* triggers drawing using in-packet vertex data */ + case PACKET3_3D_DRAW_VBUF_2: + track->vap_vf_cntl = radeon_get_ib_value(p, idx); + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + /* triggers drawing of vertex buffers setup elsewhere */ + case PACKET3_3D_DRAW_INDX_2: + track->vap_vf_cntl = radeon_get_ib_value(p, idx); + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + /* triggers drawing using indices to vertex buffer */ + case PACKET3_3D_DRAW_VBUF: + track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + /* triggers drawing of vertex buffers setup elsewhere */ + case PACKET3_3D_DRAW_INDX: + track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); + r = r100_cs_track_check(p->rdev, track); + if (r) + return r; + break; + /* triggers drawing using indices to vertex buffer */ + case PACKET3_3D_CLEAR_HIZ: + case PACKET3_3D_CLEAR_ZMASK: + if (p->rdev->hyperz_filp != p->filp) + return -EINVAL; + break; + case PACKET3_NOP: + break; + default: + DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +int r100_cs_parse(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet pkt; + struct r100_cs_track *track; + int r; + + track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!track) + return -ENOMEM; + r100_cs_track_clear(p->rdev, track); + p->track = track; + do { + r = r100_cs_packet_parse(p, &pkt, p->idx); + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + p->idx += pkt.count + 2; + switch (pkt.type) { + case PACKET_TYPE0: + if (p->rdev->family >= CHIP_R200) + r = r100_cs_parse_packet0(p, &pkt, + p->rdev->config.r100.reg_safe_bm, + p->rdev->config.r100.reg_safe_bm_size, + &r200_packet0_check); + else + r = r100_cs_parse_packet0(p, &pkt, + p->rdev->config.r100.reg_safe_bm, + p->rdev->config.r100.reg_safe_bm_size, + &r100_packet0_check); + break; + case PACKET_TYPE2: + break; + case PACKET_TYPE3: + r = r100_packet3_check(p, &pkt); + break; + default: + DRM_ERROR("Unknown packet type %d !\n", + pkt.type); + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return -EINVAL; + } + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return 0; +} + +static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) +{ + DRM_ERROR("pitch %d\n", t->pitch); + DRM_ERROR("use_pitch %d\n", t->use_pitch); + DRM_ERROR("width %d\n", t->width); + DRM_ERROR("width_11 %d\n", t->width_11); + DRM_ERROR("height %d\n", t->height); + DRM_ERROR("height_11 %d\n", t->height_11); + DRM_ERROR("num levels %d\n", t->num_levels); + DRM_ERROR("depth %d\n", t->txdepth); + DRM_ERROR("bpp %d\n", t->cpp); + DRM_ERROR("coordinate type %d\n", t->tex_coord_type); + DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); + DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); + DRM_ERROR("compress format %d\n", t->compress_format); +} + +static int r100_track_compress_size(int compress_format, int w, int h) +{ + int block_width, block_height, block_bytes; + int wblocks, hblocks; + int min_wblocks; + int sz; + + block_width = 4; + block_height = 4; + + switch (compress_format) { + case R100_TRACK_COMP_DXT1: + block_bytes = 8; + min_wblocks = 4; + break; + default: + case R100_TRACK_COMP_DXT35: + block_bytes = 16; + min_wblocks = 2; + break; + } + + hblocks = (h + block_height - 1) / block_height; + wblocks = (w + block_width - 1) / block_width; + if (wblocks < min_wblocks) + wblocks = min_wblocks; + sz = wblocks * hblocks * block_bytes; + return sz; +} + +static int r100_cs_track_cube(struct radeon_device *rdev, + struct r100_cs_track *track, unsigned idx) +{ + unsigned face, w, h; + struct radeon_bo *cube_robj; + unsigned long size; + unsigned compress_format = track->textures[idx].compress_format; + + for (face = 0; face < 5; face++) { + cube_robj = track->textures[idx].cube_info[face].robj; + w = track->textures[idx].cube_info[face].width; + h = track->textures[idx].cube_info[face].height; + + if (compress_format) { + size = r100_track_compress_size(compress_format, w, h); + } else + size = w * h; + size *= track->textures[idx].cpp; + + size += track->textures[idx].cube_info[face].offset; + + if (size > radeon_bo_size(cube_robj)) { + DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", + size, radeon_bo_size(cube_robj)); + r100_cs_track_texture_print(&track->textures[idx]); + return -1; + } + } + return 0; +} + +static int r100_cs_track_texture_check(struct radeon_device *rdev, + struct r100_cs_track *track) +{ + struct radeon_bo *robj; + unsigned long size; + unsigned u, i, w, h, d; + int ret; + + for (u = 0; u < track->num_texture; u++) { + if (!track->textures[u].enabled) + continue; + if (track->textures[u].lookup_disable) + continue; + robj = track->textures[u].robj; + if (robj == NULL) { + DRM_ERROR("No texture bound to unit %u\n", u); + return -EINVAL; + } + size = 0; + for (i = 0; i <= track->textures[u].num_levels; i++) { + if (track->textures[u].use_pitch) { + if (rdev->family < CHIP_R300) + w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); + else + w = track->textures[u].pitch / (1 << i); + } else { + w = track->textures[u].width; + if (rdev->family >= CHIP_RV515) + w |= track->textures[u].width_11; + w = w / (1 << i); + if (track->textures[u].roundup_w) + w = roundup_pow_of_two(w); + } + h = track->textures[u].height; + if (rdev->family >= CHIP_RV515) + h |= track->textures[u].height_11; + h = h / (1 << i); + if (track->textures[u].roundup_h) + h = roundup_pow_of_two(h); + if (track->textures[u].tex_coord_type == 1) { + d = (1 << track->textures[u].txdepth) / (1 << i); + if (!d) + d = 1; + } else { + d = 1; + } + if (track->textures[u].compress_format) { + + size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; + /* compressed textures are block based */ + } else + size += w * h * d; + } + size *= track->textures[u].cpp; + + switch (track->textures[u].tex_coord_type) { + case 0: + case 1: + break; + case 2: + if (track->separate_cube) { + ret = r100_cs_track_cube(rdev, track, u); + if (ret) + return ret; + } else + size *= 6; + break; + default: + DRM_ERROR("Invalid texture coordinate type %u for unit " + "%u\n", track->textures[u].tex_coord_type, u); + return -EINVAL; + } + if (size > radeon_bo_size(robj)) { + DRM_ERROR("Texture of unit %u needs %lu bytes but is " + "%lu\n", u, size, radeon_bo_size(robj)); + r100_cs_track_texture_print(&track->textures[u]); + return -EINVAL; + } + } + return 0; +} + +int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) +{ + unsigned i; + unsigned long size; + unsigned prim_walk; + unsigned nverts; + unsigned num_cb = track->cb_dirty ? track->num_cb : 0; + + if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && + !track->blend_read_enable) + num_cb = 0; + + for (i = 0; i < num_cb; i++) { + if (track->cb[i].robj == NULL) { + DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); + return -EINVAL; + } + size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; + size += track->cb[i].offset; + if (size > radeon_bo_size(track->cb[i].robj)) { + DRM_ERROR("[drm] Buffer too small for color buffer %d " + "(need %lu have %lu) !\n", i, size, + radeon_bo_size(track->cb[i].robj)); + DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", + i, track->cb[i].pitch, track->cb[i].cpp, + track->cb[i].offset, track->maxy); + return -EINVAL; + } + } + track->cb_dirty = false; + + if (track->zb_dirty && track->z_enabled) { + if (track->zb.robj == NULL) { + DRM_ERROR("[drm] No buffer for z buffer !\n"); + return -EINVAL; + } + size = track->zb.pitch * track->zb.cpp * track->maxy; + size += track->zb.offset; + if (size > radeon_bo_size(track->zb.robj)) { + DRM_ERROR("[drm] Buffer too small for z buffer " + "(need %lu have %lu) !\n", size, + radeon_bo_size(track->zb.robj)); + DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", + track->zb.pitch, track->zb.cpp, + track->zb.offset, track->maxy); + return -EINVAL; + } + } + track->zb_dirty = false; + + if (track->aa_dirty && track->aaresolve) { + if (track->aa.robj == NULL) { + DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); + return -EINVAL; + } + /* I believe the format comes from colorbuffer0. */ + size = track->aa.pitch * track->cb[0].cpp * track->maxy; + size += track->aa.offset; + if (size > radeon_bo_size(track->aa.robj)) { + DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " + "(need %lu have %lu) !\n", i, size, + radeon_bo_size(track->aa.robj)); + DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", + i, track->aa.pitch, track->cb[0].cpp, + track->aa.offset, track->maxy); + return -EINVAL; + } + } + track->aa_dirty = false; + + prim_walk = (track->vap_vf_cntl >> 4) & 0x3; + if (track->vap_vf_cntl & (1 << 14)) { + nverts = track->vap_alt_nverts; + } else { + nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; + } + switch (prim_walk) { + case 1: + for (i = 0; i < track->num_arrays; i++) { + size = track->arrays[i].esize * track->max_indx * 4; + if (track->arrays[i].robj == NULL) { + DRM_ERROR("(PW %u) Vertex array %u no buffer " + "bound\n", prim_walk, i); + return -EINVAL; + } + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); + DRM_ERROR("Max indices %u\n", track->max_indx); + return -EINVAL; + } + } + break; + case 2: + for (i = 0; i < track->num_arrays; i++) { + size = track->arrays[i].esize * (nverts - 1) * 4; + if (track->arrays[i].robj == NULL) { + DRM_ERROR("(PW %u) Vertex array %u no buffer " + "bound\n", prim_walk, i); + return -EINVAL; + } + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); + return -EINVAL; + } + } + break; + case 3: + size = track->vtx_size * nverts; + if (size != track->immd_dwords) { + DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", + track->immd_dwords, size); + DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", + nverts, track->vtx_size); + return -EINVAL; + } + break; + default: + DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", + prim_walk); + return -EINVAL; + } + + if (track->tex_dirty) { + track->tex_dirty = false; + return r100_cs_track_texture_check(rdev, track); + } + return 0; +} + +void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) +{ + unsigned i, face; + + track->cb_dirty = true; + track->zb_dirty = true; + track->tex_dirty = true; + track->aa_dirty = true; + + if (rdev->family < CHIP_R300) { + track->num_cb = 1; + if (rdev->family <= CHIP_RS200) + track->num_texture = 3; + else + track->num_texture = 6; + track->maxy = 2048; + track->separate_cube = 1; + } else { + track->num_cb = 4; + track->num_texture = 16; + track->maxy = 4096; + track->separate_cube = 0; + track->aaresolve = false; + track->aa.robj = NULL; + } + + for (i = 0; i < track->num_cb; i++) { + track->cb[i].robj = NULL; + track->cb[i].pitch = 8192; + track->cb[i].cpp = 16; + track->cb[i].offset = 0; + } + track->z_enabled = true; + track->zb.robj = NULL; + track->zb.pitch = 8192; + track->zb.cpp = 4; + track->zb.offset = 0; + track->vtx_size = 0x7F; + track->immd_dwords = 0xFFFFFFFFUL; + track->num_arrays = 11; + track->max_indx = 0x00FFFFFFUL; + for (i = 0; i < track->num_arrays; i++) { + track->arrays[i].robj = NULL; + track->arrays[i].esize = 0x7F; + } + for (i = 0; i < track->num_texture; i++) { + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + track->textures[i].pitch = 16536; + track->textures[i].width = 16536; + track->textures[i].height = 16536; + track->textures[i].width_11 = 1 << 11; + track->textures[i].height_11 = 1 << 11; + track->textures[i].num_levels = 12; + if (rdev->family <= CHIP_RS200) { + track->textures[i].tex_coord_type = 0; + track->textures[i].txdepth = 0; + } else { + track->textures[i].txdepth = 16; + track->textures[i].tex_coord_type = 1; + } + track->textures[i].cpp = 64; + track->textures[i].robj = NULL; + /* CS IB emission code makes sure texture unit are disabled */ + track->textures[i].enabled = false; + track->textures[i].lookup_disable = false; + track->textures[i].roundup_w = true; + track->textures[i].roundup_h = true; + if (track->separate_cube) + for (face = 0; face < 5; face++) { + track->textures[i].cube_info[face].robj = NULL; + track->textures[i].cube_info[face].width = 16536; + track->textures[i].cube_info[face].height = 16536; + track->textures[i].cube_info[face].offset = 0; + } + } +} + +/* + * Global GPU functions + */ +static void r100_errata(struct radeon_device *rdev) +{ + rdev->pll_errata = 0; + + if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { + rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; + } + + if (rdev->family == CHIP_RV100 || + rdev->family == CHIP_RS100 || + rdev->family == CHIP_RS200) { + rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; + } +} + +static int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; + if (tmp >= n) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +int r100_gui_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { + DRM_ERROR("radeon: wait for empty RBBM fifo failed !" + " Bad things might happen.\n"); + } + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(RADEON_RBBM_STATUS); + if (!(tmp & RADEON_RBBM_ACTIVE)) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +int r100_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & RADEON_MC_IDLE) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 rbbm_status; + + rbbm_status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(rbbm_status)) { + radeon_ring_lockup_update(ring); + return false; + } + /* force CP activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ +void r100_enable_bm(struct radeon_device *rdev) +{ + uint32_t tmp; + /* Enable bus mastering */ + tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); +} + +void r100_bm_disable(struct radeon_device *rdev) +{ + u32 tmp; + + /* disable bus mastering */ + tmp = RREG32(R_000030_BUS_CNTL); + WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000044); + DRM_MDELAY(1); + WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000042); + DRM_MDELAY(1); + WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040); + tmp = RREG32(RADEON_BUS_CNTL); + DRM_MDELAY(1); + pci_disable_busmaster(rdev->dev); + DRM_MDELAY(1); +} + +int r100_asic_reset(struct radeon_device *rdev) +{ + struct r100_mc_save save; + u32 status, tmp; + int ret = 0; + + status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(status)) { + return 0; + } + r100_mc_stop(rdev, &save); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* stop CP */ + WREG32(RADEON_CP_CSQ_CNTL, 0); + tmp = RREG32(RADEON_CP_RB_CNTL); + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); + WREG32(RADEON_CP_RB_RPTR_WR, 0); + WREG32(RADEON_CP_RB_WPTR, 0); + WREG32(RADEON_CP_RB_CNTL, tmp); + /* save PCI state */ + pci_save_state(rdev->dev); + /* disable bus mastering */ + r100_bm_disable(rdev); + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_SE(1) | + S_0000F0_SOFT_RESET_RE(1) | + S_0000F0_SOFT_RESET_PP(1) | + S_0000F0_SOFT_RESET_RB(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* reset CP */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* restore PCI & busmastering */ + pci_restore_state(rdev->dev); + r100_enable_bm(rdev); + /* Check if GPU is idle */ + if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) || + G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) { + dev_err(rdev->dev, "failed to reset GPU\n"); + ret = -1; + } else + dev_info(rdev->dev, "GPU reset succeed\n"); + r100_mc_resume(rdev, &save); + return ret; +} + +void r100_set_common_regs(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + bool force_dac2 = false; + u32 tmp; + + /* set these so they don't interfere with anything */ + WREG32(RADEON_OV0_SCALE_CNTL, 0); + WREG32(RADEON_SUBPIC_CNTL, 0); + WREG32(RADEON_VIPH_CONTROL, 0); + WREG32(RADEON_I2C_CNTL_1, 0); + WREG32(RADEON_DVI_I2C_CNTL_1, 0); + WREG32(RADEON_CAP0_TRIG_CNTL, 0); + WREG32(RADEON_CAP1_TRIG_CNTL, 0); + + /* always set up dac2 on rn50 and some rv100 as lots + * of servers seem to wire it up to a VGA port but + * don't report it in the bios connector + * table. + */ + switch (dev->pci_device) { + /* RN50 */ + case 0x515e: + case 0x5969: + force_dac2 = true; + break; + /* RV100*/ + case 0x5159: + case 0x515a: + /* DELL triple head servers */ + if ((dev->pci_subvendor == 0x1028 /* DELL */) && + ((dev->pci_subdevice == 0x016c) || + (dev->pci_subdevice == 0x016d) || + (dev->pci_subdevice == 0x016e) || + (dev->pci_subdevice == 0x016f) || + (dev->pci_subdevice == 0x0170) || + (dev->pci_subdevice == 0x017d) || + (dev->pci_subdevice == 0x017e) || + (dev->pci_subdevice == 0x0183) || + (dev->pci_subdevice == 0x018a) || + (dev->pci_subdevice == 0x019a))) + force_dac2 = true; + break; + } + + if (force_dac2) { + u32 disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + u32 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); + u32 dac2_cntl = RREG32(RADEON_DAC_CNTL2); + + /* For CRT on DAC2, don't turn it on if BIOS didn't + enable it, even it's detected. + */ + + /* force it to crtc0 */ + dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; + dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + + /* set up the TV DAC */ + tv_dac_cntl &= ~(RADEON_TV_DAC_PEDESTAL | + RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK); + tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2 | + (0x58 << 16)); + + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + WREG32(RADEON_DAC_CNTL2, dac2_cntl); + } + + /* switch PM block to ACPI mode */ + tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); + tmp &= ~RADEON_PM_MODE_SEL; + WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); + +} + +/* + * VRAM info + */ +static void r100_vram_get_type(struct radeon_device *rdev) +{ + uint32_t tmp; + + rdev->mc.vram_is_ddr = false; + if (rdev->flags & RADEON_IS_IGP) + rdev->mc.vram_is_ddr = true; + else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) + rdev->mc.vram_is_ddr = true; + if ((rdev->family == CHIP_RV100) || + (rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) { + tmp = RREG32(RADEON_MEM_CNTL); + if (tmp & RV100_HALF_MODE) { + rdev->mc.vram_width = 32; + } else { + rdev->mc.vram_width = 64; + } + if (rdev->flags & RADEON_SINGLE_CRTC) { + rdev->mc.vram_width /= 4; + rdev->mc.vram_is_ddr = true; + } + } else if (rdev->family <= CHIP_RV280) { + tmp = RREG32(RADEON_MEM_CNTL); + if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { + rdev->mc.vram_width = 128; + } else { + rdev->mc.vram_width = 64; + } + } else { + /* newer IGPs */ + rdev->mc.vram_width = 128; + } +} + +static u32 r100_get_accessible_vram(struct radeon_device *rdev) +{ + u32 aper_size; + u8 byte; + + aper_size = RREG32(RADEON_CONFIG_APER_SIZE); + + /* Set HDP_APER_CNTL only on cards that are known not to be broken, + * that is has the 2nd generation multifunction PCI interface + */ + if (rdev->family == CHIP_RV280 || + rdev->family >= CHIP_RV350) { + WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, + ~RADEON_HDP_APER_CNTL); + DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); + return aper_size * 2; + } + + /* Older cards have all sorts of funny issues to deal with. First + * check if it's a multifunction card by reading the PCI config + * header type... Limit those to one aperture size + */ + byte = pci_read_config(rdev->dev, 0xe, 1); + if (byte & 0x80) { + DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); + DRM_INFO("Limiting VRAM to one aperture\n"); + return aper_size; + } + + /* Single function older card. We read HDP_APER_CNTL to see how the BIOS + * have set it up. We don't write this as it's broken on some ASICs but + * we expect the BIOS to have done the right thing (might be too optimistic...) + */ + if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) + return aper_size * 2; + return aper_size; +} + +void r100_vram_init_sizes(struct radeon_device *rdev) +{ + u64 config_aper_size; + + /* work out accessible VRAM */ + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev); + /* FIXME we don't use the second aperture yet when we could use it */ + if (rdev->mc.visible_vram_size > rdev->mc.aper_size) + rdev->mc.visible_vram_size = rdev->mc.aper_size; + config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); + if (rdev->flags & RADEON_IS_IGP) { + uint32_t tom; + /* read NB_TOM to get the amount of ram stolen for the GPU */ + tom = RREG32(RADEON_NB_TOM); + rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + } else { + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + /* Some production boards of m6 will report 0 + * if it's 8 MB + */ + if (rdev->mc.real_vram_size == 0) { + rdev->mc.real_vram_size = 8192 * 1024; + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + } + /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - + * Novell bug 204882 + along with lots of ubuntu ones + */ + if (rdev->mc.aper_size > config_aper_size) + config_aper_size = rdev->mc.aper_size; + + if (config_aper_size > rdev->mc.real_vram_size) + rdev->mc.mc_vram_size = config_aper_size; + else + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + } +} + +void r100_vga_set_state(struct radeon_device *rdev, bool state) +{ + uint32_t temp; + + temp = RREG32(RADEON_CONFIG_CNTL); + if (state == false) { + temp &= ~RADEON_CFG_VGA_RAM_EN; + temp |= RADEON_CFG_VGA_IO_DIS; + } else { + temp &= ~RADEON_CFG_VGA_IO_DIS; + } + WREG32(RADEON_CONFIG_CNTL, temp); +} + +static void r100_mc_init(struct radeon_device *rdev) +{ + u64 base; + + r100_vram_get_type(rdev); + r100_vram_init_sizes(rdev); + base = rdev->mc.aper_base; + if (rdev->flags & RADEON_IS_IGP) + base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = 0; + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + + +/* + * Indirect registers accessor + */ +void r100_pll_errata_after_index(struct radeon_device *rdev) +{ + if (rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS) { + (void)RREG32(RADEON_CLOCK_CNTL_DATA); + (void)RREG32(RADEON_CRTC_GEN_CNTL); + } +} + +static void r100_pll_errata_after_data(struct radeon_device *rdev) +{ + /* This workarounds is necessary on RV100, RS100 and RS200 chips + * or the chip could hang on a subsequent access + */ + if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { + DRM_MDELAY(5); + } + + /* This function is required to workaround a hardware bug in some (all?) + * revisions of the R300. This workaround should be called after every + * CLOCK_CNTL_INDEX register access. If not, register reads afterward + * may not be correct. + */ + if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { + uint32_t save, tmp; + + save = RREG32(RADEON_CLOCK_CNTL_INDEX); + tmp = save & ~(0x3f | RADEON_PLL_WR_EN); + WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); + tmp = RREG32(RADEON_CLOCK_CNTL_DATA); + WREG32(RADEON_CLOCK_CNTL_INDEX, save); + } +} + +uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) +{ + uint32_t data; + + WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); + r100_pll_errata_after_index(rdev); + data = RREG32(RADEON_CLOCK_CNTL_DATA); + r100_pll_errata_after_data(rdev); + return data; +} + +void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); + r100_pll_errata_after_index(rdev); + WREG32(RADEON_CLOCK_CNTL_DATA, v); + r100_pll_errata_after_data(rdev); +} + +static void r100_set_safe_registers(struct radeon_device *rdev) +{ + if (ASIC_IS_RN50(rdev)) { + rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm; + rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(rn50_reg_safe_bm); + } else if (rdev->family < CHIP_R200) { + rdev->config.r100.reg_safe_bm = r100_reg_safe_bm; + rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r100_reg_safe_bm); + } else { + r200_set_safe_registers(rdev); + } +} + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) +static int r100_debugfs_rbbm_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t reg, value; + unsigned i; + + seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); + seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); + seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); + for (i = 0; i < 64; i++) { + WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); + reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; + WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); + value = RREG32(RADEON_RBBM_CMDFIFO_DATA); + seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); + } + return 0; +} + +static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t rdp, wdp; + unsigned count, i, j; + + radeon_ring_free_size(rdev, ring); + rdp = RREG32(RADEON_CP_RB_RPTR); + wdp = RREG32(RADEON_CP_RB_WPTR); + count = (rdp + ring->ring_size - wdp) & ring->ptr_mask; + seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); + seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); + seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); + seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); + seq_printf(m, "%u dwords in ring\n", count); + for (j = 0; j <= count; j++) { + i = (rdp + j) & ring->ptr_mask; + seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); + } + return 0; +} + + +static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t csq_stat, csq2_stat, tmp; + unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; + unsigned i; + + seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); + seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); + csq_stat = RREG32(RADEON_CP_CSQ_STAT); + csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); + r_rptr = (csq_stat >> 0) & 0x3ff; + r_wptr = (csq_stat >> 10) & 0x3ff; + ib1_rptr = (csq_stat >> 20) & 0x3ff; + ib1_wptr = (csq2_stat >> 0) & 0x3ff; + ib2_rptr = (csq2_stat >> 10) & 0x3ff; + ib2_wptr = (csq2_stat >> 20) & 0x3ff; + seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); + seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); + seq_printf(m, "Ring rptr %u\n", r_rptr); + seq_printf(m, "Ring wptr %u\n", r_wptr); + seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); + seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); + seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); + seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); + /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms + * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ + seq_printf(m, "Ring fifo:\n"); + for (i = 0; i < 256; i++) { + WREG32(RADEON_CP_CSQ_ADDR, i << 2); + tmp = RREG32(RADEON_CP_CSQ_DATA); + seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); + } + seq_printf(m, "Indirect1 fifo:\n"); + for (i = 256; i <= 512; i++) { + WREG32(RADEON_CP_CSQ_ADDR, i << 2); + tmp = RREG32(RADEON_CP_CSQ_DATA); + seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); + } + seq_printf(m, "Indirect2 fifo:\n"); + for (i = 640; i < ib1_wptr; i++) { + WREG32(RADEON_CP_CSQ_ADDR, i << 2); + tmp = RREG32(RADEON_CP_CSQ_DATA); + seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); + } + return 0; +} + +static int r100_debugfs_mc_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + tmp = RREG32(RADEON_CONFIG_MEMSIZE); + seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); + tmp = RREG32(RADEON_MC_FB_LOCATION); + seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); + tmp = RREG32(RADEON_BUS_CNTL); + seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); + tmp = RREG32(RADEON_MC_AGP_LOCATION); + seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); + tmp = RREG32(RADEON_AGP_BASE); + seq_printf(m, "AGP_BASE 0x%08x\n", tmp); + tmp = RREG32(RADEON_HOST_PATH_CNTL); + seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); + tmp = RREG32(0x01D0); + seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); + tmp = RREG32(RADEON_AIC_LO_ADDR); + seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); + tmp = RREG32(RADEON_AIC_HI_ADDR); + seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); + tmp = RREG32(0x01E4); + seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); + return 0; +} + +static struct drm_info_list r100_debugfs_rbbm_list[] = { + {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, +}; + +static struct drm_info_list r100_debugfs_cp_list[] = { + {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, + {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, +}; + +static struct drm_info_list r100_debugfs_mc_info_list[] = { + {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, +}; +#endif + +int r100_debugfs_rbbm_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); +#else + return 0; +#endif +} + +int r100_debugfs_cp_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); +#else + return 0; +#endif +} + +int r100_debugfs_mc_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); +#else + return 0; +#endif +} + +int r100_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size) +{ + int surf_index = reg * 16; + int flags = 0; + + if (rdev->family <= CHIP_RS200) { + if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) + == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) + flags |= RADEON_SURF_TILE_COLOR_BOTH; + if (tiling_flags & RADEON_TILING_MACRO) + flags |= RADEON_SURF_TILE_COLOR_MACRO; + } else if (rdev->family <= CHIP_RV280) { + if (tiling_flags & (RADEON_TILING_MACRO)) + flags |= R200_SURF_TILE_COLOR_MACRO; + if (tiling_flags & RADEON_TILING_MICRO) + flags |= R200_SURF_TILE_COLOR_MICRO; + } else { + if (tiling_flags & RADEON_TILING_MACRO) + flags |= R300_SURF_TILE_MACRO; + if (tiling_flags & RADEON_TILING_MICRO) + flags |= R300_SURF_TILE_MICRO; + } + + if (tiling_flags & RADEON_TILING_SWAP_16BIT) + flags |= RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; + if (tiling_flags & RADEON_TILING_SWAP_32BIT) + flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; + + /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */ + if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) { + if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) + if (ASIC_IS_RN50(rdev)) + pitch /= 16; + } + + /* r100/r200 divide by 16 */ + if (rdev->family < CHIP_R300) + flags |= pitch / 16; + else + flags |= pitch / 8; + + + DRM_DEBUG_KMS("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); + WREG32(RADEON_SURFACE0_INFO + surf_index, flags); + WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); + WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); + return 0; +} + +void r100_clear_surface_reg(struct radeon_device *rdev, int reg) +{ + int surf_index = reg * 16; + WREG32(RADEON_SURFACE0_INFO + surf_index, 0); +} + +void r100_bandwidth_update(struct radeon_device *rdev) +{ + fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; + fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; + fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; + uint32_t temp, data, mem_trcd, mem_trp, mem_tras; + fixed20_12 memtcas_ff[8] = { + dfixed_init(1), + dfixed_init(2), + dfixed_init(3), + dfixed_init(0), + dfixed_init_half(1), + dfixed_init_half(2), + dfixed_init(0), + }; + fixed20_12 memtcas_rs480_ff[8] = { + dfixed_init(0), + dfixed_init(1), + dfixed_init(2), + dfixed_init(3), + dfixed_init(0), + dfixed_init_half(1), + dfixed_init_half(2), + dfixed_init_half(3), + }; + fixed20_12 memtcas2_ff[8] = { + dfixed_init(0), + dfixed_init(1), + dfixed_init(2), + dfixed_init(3), + dfixed_init(4), + dfixed_init(5), + dfixed_init(6), + dfixed_init(7), + }; + fixed20_12 memtrbs[8] = { + dfixed_init(1), + dfixed_init_half(1), + dfixed_init(2), + dfixed_init_half(2), + dfixed_init(3), + dfixed_init_half(3), + dfixed_init(4), + dfixed_init_half(4) + }; + fixed20_12 memtrbs_r4xx[8] = { + dfixed_init(4), + dfixed_init(5), + dfixed_init(6), + dfixed_init(7), + dfixed_init(8), + dfixed_init(9), + dfixed_init(10), + dfixed_init(11) + }; + fixed20_12 min_mem_eff; + fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; + fixed20_12 cur_latency_mclk, cur_latency_sclk; + fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, + disp_drain_rate2, read_return_rate; + fixed20_12 time_disp1_drop_priority; + int c; + int cur_size = 16; /* in octawords */ + int critical_point = 0, critical_point2; +/* uint32_t read_return_rate, time_disp1_drop_priority; */ + int stop_req, max_stop_req; + struct drm_display_mode *mode1 = NULL; + struct drm_display_mode *mode2 = NULL; + uint32_t pixel_bytes1 = 0; + uint32_t pixel_bytes2 = 0; + + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) { + mode1 = &rdev->mode_info.crtcs[0]->base.mode; + pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; + } + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + if (rdev->mode_info.crtcs[1]->base.enabled) { + mode2 = &rdev->mode_info.crtcs[1]->base.mode; + pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; + } + } + + min_mem_eff.full = dfixed_const_8(0); + /* get modes */ + if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { + uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); + mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); + mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); + /* check crtc enables */ + if (mode2) + mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); + if (mode1) + mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); + WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + /* + * determine is there is enough bw for current mode + */ + sclk_ff = rdev->pm.sclk; + mclk_ff = rdev->pm.mclk; + + temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); + temp_ff.full = dfixed_const(temp); + mem_bw.full = dfixed_mul(mclk_ff, temp_ff); + + pix_clk.full = 0; + pix_clk2.full = 0; + peak_disp_bw.full = 0; + if (mode1) { + temp_ff.full = dfixed_const(1000); + pix_clk.full = dfixed_const(mode1->clock); /* convert to fixed point */ + pix_clk.full = dfixed_div(pix_clk, temp_ff); + temp_ff.full = dfixed_const(pixel_bytes1); + peak_disp_bw.full += dfixed_mul(pix_clk, temp_ff); + } + if (mode2) { + temp_ff.full = dfixed_const(1000); + pix_clk2.full = dfixed_const(mode2->clock); /* convert to fixed point */ + pix_clk2.full = dfixed_div(pix_clk2, temp_ff); + temp_ff.full = dfixed_const(pixel_bytes2); + peak_disp_bw.full += dfixed_mul(pix_clk2, temp_ff); + } + + mem_bw.full = dfixed_mul(mem_bw, min_mem_eff); + if (peak_disp_bw.full >= mem_bw.full) { + DRM_ERROR("You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = RREG32(RADEON_MEM_TIMING_CNTL); + if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ + mem_trcd = ((temp >> 2) & 0x3) + 1; + mem_trp = ((temp & 0x3)) + 1; + mem_tras = ((temp & 0x70) >> 4) + 1; + } else if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { /* r300, r350 */ + mem_trcd = (temp & 0x7) + 1; + mem_trp = ((temp >> 8) & 0x7) + 1; + mem_tras = ((temp >> 11) & 0xf) + 4; + } else if (rdev->family == CHIP_RV350 || + rdev->family <= CHIP_RV380) { + /* rv3x0 */ + mem_trcd = (temp & 0x7) + 3; + mem_trp = ((temp >> 8) & 0x7) + 3; + mem_tras = ((temp >> 11) & 0xf) + 6; + } else if (rdev->family == CHIP_R420 || + rdev->family == CHIP_R423 || + rdev->family == CHIP_RV410) { + /* r4xx */ + mem_trcd = (temp & 0xf) + 3; + if (mem_trcd > 15) + mem_trcd = 15; + mem_trp = ((temp >> 8) & 0xf) + 3; + if (mem_trp > 15) + mem_trp = 15; + mem_tras = ((temp >> 12) & 0x1f) + 6; + if (mem_tras > 31) + mem_tras = 31; + } else { /* RV200, R200 */ + mem_trcd = (temp & 0x7) + 1; + mem_trp = ((temp >> 8) & 0x7) + 1; + mem_tras = ((temp >> 12) & 0xf) + 4; + } + /* convert to FF */ + trcd_ff.full = dfixed_const(mem_trcd); + trp_ff.full = dfixed_const(mem_trp); + tras_ff.full = dfixed_const(mem_tras); + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7 << 20)) >> 20; + if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { + if (rdev->family == CHIP_RS480) /* don't think rs400 */ + tcas_ff = memtcas_rs480_ff[data]; + else + tcas_ff = memtcas_ff[data]; + } else + tcas_ff = memtcas2_ff[data]; + + if (rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) { + /* extra cas latency stored in bits 23-25 0-4 clocks */ + data = (temp >> 23) & 0x7; + if (data < 5) + tcas_ff.full += dfixed_const(data); + } + + if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { + /* on the R300, Tcas is included in Trbs. + */ + temp = RREG32(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 1) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = RREG32(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + WREG32(R300_MC_IND_INDEX, temp); + temp = RREG32(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = RREG32(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = RREG32(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + if (rdev->family == CHIP_RV410 || + rdev->family == CHIP_R420 || + rdev->family == CHIP_R423) + trbs_ff = memtrbs_r4xx[data]; + else + trbs_ff = memtrbs[data]; + tcas_ff.full += trbs_ff.full; + } + + sclk_eff_ff.full = sclk_ff.full; + + if (rdev->flags & RADEON_IS_AGP) { + fixed20_12 agpmode_ff; + agpmode_ff.full = dfixed_const(radeon_agpmode); + temp_ff.full = dfixed_const_666(16); + sclk_eff_ff.full -= dfixed_mul(agpmode_ff, temp_ff); + } + /* TODO PCIE lanes may affect this - agpmode == 16?? */ + + if (ASIC_IS_R300(rdev)) { + sclk_delay_ff.full = dfixed_const(250); + } else { + if ((rdev->family == CHIP_RV100) || + rdev->flags & RADEON_IS_IGP) { + if (rdev->mc.vram_is_ddr) + sclk_delay_ff.full = dfixed_const(41); + else + sclk_delay_ff.full = dfixed_const(33); + } else { + if (rdev->mc.vram_width == 128) + sclk_delay_ff.full = dfixed_const(57); + else + sclk_delay_ff.full = dfixed_const(41); + } + } + + mc_latency_sclk.full = dfixed_div(sclk_delay_ff, sclk_eff_ff); + + if (rdev->mc.vram_is_ddr) { + if (rdev->mc.vram_width == 32) { + k1.full = dfixed_const(40); + c = 3; + } else { + k1.full = dfixed_const(20); + c = 1; + } + } else { + k1.full = dfixed_const(40); + c = 3; + } + + temp_ff.full = dfixed_const(2); + mc_latency_mclk.full = dfixed_mul(trcd_ff, temp_ff); + temp_ff.full = dfixed_const(c); + mc_latency_mclk.full += dfixed_mul(tcas_ff, temp_ff); + temp_ff.full = dfixed_const(4); + mc_latency_mclk.full += dfixed_mul(tras_ff, temp_ff); + mc_latency_mclk.full += dfixed_mul(trp_ff, temp_ff); + mc_latency_mclk.full += k1.full; + + mc_latency_mclk.full = dfixed_div(mc_latency_mclk, mclk_ff); + mc_latency_mclk.full += dfixed_div(temp_ff, sclk_eff_ff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + temp_ff.full = dfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); + temp_ff.full += trcd_ff.full; + if (temp_ff.full < tras_ff.full) + temp_ff.full = tras_ff.full; + cur_latency_mclk.full = dfixed_div(temp_ff, mclk_ff); + + temp_ff.full = dfixed_const(cur_size); + cur_latency_sclk.full = dfixed_div(temp_ff, sclk_eff_ff); + /* + Find the total latency for the display data. + */ + disp_latency_overhead.full = dfixed_const(8); + disp_latency_overhead.full = dfixed_div(disp_latency_overhead, sclk_ff); + mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; + mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; + + if (mc_latency_mclk.full > mc_latency_sclk.full) + disp_latency.full = mc_latency_mclk.full; + else + disp_latency.full = mc_latency_sclk.full; + + /* setup Max GRPH_STOP_REQ default value */ + if (ASIC_IS_RV100(rdev)) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + + if (mode1) { + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->hdisplay * pixel_bytes1 / 16; + + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* + Find the drain rate of the display buffer. + */ + temp_ff.full = dfixed_const((16/pixel_bytes1)); + disp_drain_rate.full = dfixed_div(pix_clk, temp_ff); + + /* + Find the critical point of the display buffer. + */ + crit_point_ff.full = dfixed_mul(disp_drain_rate, disp_latency); + crit_point_ff.full += dfixed_const_half(0); + + critical_point = dfixed_trunc(crit_point_ff); + + if (rdev->disp_priority == 2) { + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) + critical_point = 0; + + if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + + temp = RREG32(RADEON_GRPH_BUFFER_CNTL); + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((rdev->family == CHIP_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + +#if 0 + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + /* attempt to program RS400 disp regs correctly ??? */ + temp = RREG32(RS400_DISP1_REG_CNTL); + temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | + RS400_DISP1_STOP_REQ_LEVEL_MASK); + WREG32(RS400_DISP1_REQ_CNTL1, (temp | + (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | + (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); + temp = RREG32(RS400_DMIF_MEM_CNTL1); + temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | + RS400_DISP1_CRITICAL_POINT_STOP_MASK); + WREG32(RS400_DMIF_MEM_CNTL1, (temp | + (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | + (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); + } +#endif + + DRM_DEBUG_KMS("GRPH_BUFFER_CNTL from to %x\n", + /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ + (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); + } + + if (mode2) { + u32 grph2_cntl; + stop_req = mode2->hdisplay * pixel_bytes2 / 16; + + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* + Find the drain rate of the display buffer. + */ + temp_ff.full = dfixed_const((16/pixel_bytes2)); + disp_drain_rate2.full = dfixed_div(pix_clk2, temp_ff); + + grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); + grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); + grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); + if ((rdev->family == CHIP_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; + grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) + critical_point2 = 0; + else { + temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; + temp_ff.full = dfixed_const(temp); + temp_ff.full = dfixed_mul(mclk_ff, temp_ff); + if (sclk_ff.full < temp_ff.full) + temp_ff.full = sclk_ff.full; + + read_return_rate.full = temp_ff.full; + + if (mode1) { + temp_ff.full = read_return_rate.full - disp_drain_rate.full; + time_disp1_drop_priority.full = dfixed_div(crit_point_ff, temp_ff); + } else { + time_disp1_drop_priority.full = 0; + } + crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; + crit_point_ff.full = dfixed_mul(crit_point_ff, disp_drain_rate2); + crit_point_ff.full += dfixed_const_half(0); + + critical_point2 = dfixed_trunc(crit_point_ff); + + if (rdev->disp_priority == 2) { + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) + critical_point2 = 0; + + } + + if (critical_point2 == 0 && rdev->family == CHIP_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + + WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { +#if 0 + /* attempt to program RS400 disp2 regs correctly ??? */ + temp = RREG32(RS400_DISP2_REQ_CNTL1); + temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | + RS400_DISP2_STOP_REQ_LEVEL_MASK); + WREG32(RS400_DISP2_REQ_CNTL1, (temp | + (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | + (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); + temp = RREG32(RS400_DISP2_REQ_CNTL2); + temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | + RS400_DISP2_CRITICAL_POINT_STOP_MASK); + WREG32(RS400_DISP2_REQ_CNTL2, (temp | + (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | + (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); +#endif + WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); + WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); + WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); + WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); + } + + DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n", + (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); + } +} + +int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) +{ + uint32_t scratch; + uint32_t tmp = 0; + unsigned i; + int r; + + r = radeon_scratch_get(rdev, &scratch); + if (r) { + DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + r = radeon_ring_lock(rdev, ring, 2); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + radeon_scratch_free(rdev, scratch); + return r; + } + radeon_ring_write(ring, PACKET0(scratch, 0)); + radeon_ring_write(ring, 0xDEADBEEF); + radeon_ring_unlock_commit(rdev, ring); + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) { + break; + } + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { + DRM_INFO("ring test succeeded in %d usecs\n", i); + } else { + DRM_ERROR("radeon: ring test failed (scratch(0x%04X)=0x%08X)\n", + scratch, tmp); + r = -EINVAL; + } + radeon_scratch_free(rdev, scratch); + return r; +} + +void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + + if (ring->rptr_save_reg) { + u32 next_rptr = ring->wptr + 2 + 3; + radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0)); + radeon_ring_write(ring, next_rptr); + } + + radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); + radeon_ring_write(ring, ib->gpu_addr); + radeon_ring_write(ring, ib->length_dw); +} + +int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) +{ + struct radeon_ib ib; + uint32_t scratch; + uint32_t tmp = 0; + unsigned i; + int r; + + r = radeon_scratch_get(rdev, &scratch); + if (r) { + DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &ib, NULL, 256); + if (r) { + DRM_ERROR("radeon: failed to get ib (%d).\n", r); + goto free_scratch; + } + ib.ptr[0] = PACKET0(scratch, 0); + ib.ptr[1] = 0xDEADBEEF; + ib.ptr[2] = PACKET2(0); + ib.ptr[3] = PACKET2(0); + ib.ptr[4] = PACKET2(0); + ib.ptr[5] = PACKET2(0); + ib.ptr[6] = PACKET2(0); + ib.ptr[7] = PACKET2(0); + ib.length_dw = 8; + r = radeon_ib_schedule(rdev, &ib, NULL); + if (r) { + DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); + goto free_ib; + } + r = radeon_fence_wait(ib.fence, false); + if (r) { + DRM_ERROR("radeon: fence wait failed (%d).\n", r); + goto free_ib; + } + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) { + break; + } + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { + DRM_INFO("ib test succeeded in %u usecs\n", i); + } else { + DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", + scratch, tmp); + r = -EINVAL; + } +free_ib: + radeon_ib_free(rdev, &ib); +free_scratch: + radeon_scratch_free(rdev, scratch); + return r; +} + +void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) +{ + /* Shutdown CP we shouldn't need to do that but better be safe than + * sorry + */ + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + WREG32(R_000740_CP_CSQ_CNTL, 0); + + /* Save few CRTC registers */ + save->GENMO_WT = RREG8(R_0003C2_GENMO_WT); + save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL); + save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL); + save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + save->CRTC2_GEN_CNTL = RREG32(R_0003F8_CRTC2_GEN_CNTL); + save->CUR2_OFFSET = RREG32(R_000360_CUR2_OFFSET); + } + + /* Disable VGA aperture access */ + WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & save->GENMO_WT); + /* Disable cursor, overlay, crtc */ + WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1)); + WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL | + S_000054_CRTC_DISPLAY_DIS(1)); + WREG32(R_000050_CRTC_GEN_CNTL, + (C_000050_CRTC_CUR_EN & save->CRTC_GEN_CNTL) | + S_000050_CRTC_DISP_REQ_EN_B(1)); + WREG32(R_000420_OV0_SCALE_CNTL, + C_000420_OV0_OVERLAY_EN & RREG32(R_000420_OV0_SCALE_CNTL)); + WREG32(R_000260_CUR_OFFSET, C_000260_CUR_LOCK & save->CUR_OFFSET); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(R_000360_CUR2_OFFSET, save->CUR2_OFFSET | + S_000360_CUR2_LOCK(1)); + WREG32(R_0003F8_CRTC2_GEN_CNTL, + (C_0003F8_CRTC2_CUR_EN & save->CRTC2_GEN_CNTL) | + S_0003F8_CRTC2_DISPLAY_DIS(1) | + S_0003F8_CRTC2_DISP_REQ_EN_B(1)); + WREG32(R_000360_CUR2_OFFSET, + C_000360_CUR2_LOCK & save->CUR2_OFFSET); + } +} + +void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save) +{ + /* Update base address for crtc */ + WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_start); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, rdev->mc.vram_start); + } + /* Restore CRTC registers */ + WREG8(R_0003C2_GENMO_WT, save->GENMO_WT); + WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL); + WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(R_0003F8_CRTC2_GEN_CNTL, save->CRTC2_GEN_CNTL); + } +} + +void r100_vga_render_disable(struct radeon_device *rdev) +{ + u32 tmp; + + tmp = RREG8(R_0003C2_GENMO_WT); + WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & tmp); +} + +static void r100_debugfs(struct radeon_device *rdev) +{ + int r; + + r = r100_debugfs_mc_info_init(rdev); + if (r) + dev_warn(rdev->dev, "Failed to create r100_mc debugfs file.\n"); +} + +static void r100_mc_program(struct radeon_device *rdev) +{ + struct r100_mc_save save; + + /* Stops all mc clients */ + r100_mc_stop(rdev, &save); + if (rdev->flags & RADEON_IS_AGP) { + WREG32(R_00014C_MC_AGP_LOCATION, + S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | + S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); + WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); + if (rdev->family > CHIP_RV200) + WREG32(R_00015C_AGP_BASE_2, + upper_32_bits(rdev->mc.agp_base) & 0xff); + } else { + WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); + WREG32(R_000170_AGP_BASE, 0); + if (rdev->family > CHIP_RV200) + WREG32(R_00015C_AGP_BASE_2, 0); + } + /* Wait for mc idle */ + if (r100_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "Wait for MC idle timeout.\n"); + /* Program MC, should be a 32bits limited address space */ + WREG32(R_000148_MC_FB_LOCATION, + S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); + r100_mc_resume(rdev, &save); +} + +static void r100_clock_startup(struct radeon_device *rdev) +{ + u32 tmp; + + if (radeon_dynclks != -1 && radeon_dynclks) + radeon_legacy_set_clock_gating(rdev, 1); + /* We need to force on some of the block */ + tmp = RREG32_PLL(R_00000D_SCLK_CNTL); + tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); + if ((rdev->family == CHIP_RV250) || (rdev->family == CHIP_RV280)) + tmp |= S_00000D_FORCE_DISP1(1) | S_00000D_FORCE_DISP2(1); + WREG32_PLL(R_00000D_SCLK_CNTL, tmp); +} + +static int r100_startup(struct radeon_device *rdev) +{ + int r; + + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ + r100_mc_program(rdev); + /* Resume clock */ + r100_clock_startup(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + r100_enable_bm(rdev); + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_enable(rdev); + if (r) + return r; + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r100_irq_set(rdev); + rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int r100_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); + /* Resume clock before doing reset */ + r100_clock_startup(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + radeon_combios_asic_init(rdev->ddev); + /* Resume clock after posting */ + r100_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = r100_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int r100_suspend(struct radeon_device *rdev) +{ + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); + return 0; +} + +void r100_fini(struct radeon_device *rdev) +{ + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + r100_cp_fini_microcode(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +/* + * Due to how kexec works, it can leave the hw fully initialised when it + * boots the new kernel. However doing our init sequence with the CP and + * WB stuff setup causes GPU hangs on the RN50 at least. So at startup + * do some quick sanity checks and restore sane values to avoid this + * problem. + */ +void r100_restore_sanity(struct radeon_device *rdev) +{ + u32 tmp; + + tmp = RREG32(RADEON_CP_CSQ_CNTL); + if (tmp) { + WREG32(RADEON_CP_CSQ_CNTL, 0); + } + tmp = RREG32(RADEON_CP_RB_CNTL); + if (tmp) { + WREG32(RADEON_CP_RB_CNTL, 0); + } + tmp = RREG32(RADEON_SCRATCH_UMSK); + if (tmp) { + WREG32(RADEON_SCRATCH_UMSK, 0); + } +} + +int r100_init(struct radeon_device *rdev) +{ + int r; + + /* Register debugfs file specific to this group of asics */ + r100_debugfs(rdev); + /* Disable VGA */ + r100_vga_render_disable(rdev); + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* sanity check some register to avoid hangs like after kexec */ + r100_restore_sanity(rdev); + /* TODO: disable VGA need to use VGA request */ + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); + return -EINVAL; + } else { + r = radeon_combios_init(rdev); + if (r) + return r; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Set asic errata */ + r100_errata(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) { + radeon_agp_disable(rdev); + } + } + /* initialize VRAM */ + r100_mc_init(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_init(rdev); + if (r) + return r; + } + r100_set_safe_registers(rdev); + + rdev->accel_working = true; + r = r100_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); + rdev->accel_working = false; + } + return 0; +} + +uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg, + bool always_indirect) +{ + if (reg < rdev->rmmio_size && !always_indirect) + return bus_read_4(rdev->rmmio, reg); + else { + unsigned long flags; + uint32_t ret; + + DRM_SPINLOCK_IRQSAVE(&rdev->mmio_idx_lock, flags); + bus_write_4(rdev->rmmio, RADEON_MM_INDEX, reg); + ret = bus_read_4(rdev->rmmio, RADEON_MM_DATA); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->mmio_idx_lock, flags); + + return ret; + } +} + +void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v, + bool always_indirect) +{ + if (reg < rdev->rmmio_size && !always_indirect) + bus_write_4(rdev->rmmio, reg, v); + else { + unsigned long flags; + + DRM_SPINLOCK_IRQSAVE(&rdev->mmio_idx_lock, flags); + bus_write_4(rdev->rmmio, RADEON_MM_INDEX, reg); + bus_write_4(rdev->rmmio, RADEON_MM_DATA, v); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->mmio_idx_lock, flags); + } +} + +u32 r100_io_rreg(struct radeon_device *rdev, u32 reg) +{ + if (reg < rdev->rio_mem_size) + return bus_read_4(rdev->rio_mem, reg); + else { + /* XXX No locking? -- dumbbell@ */ + bus_write_4(rdev->rio_mem, RADEON_MM_INDEX, reg); + return bus_read_4(rdev->rio_mem, RADEON_MM_DATA); + } +} + +void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + if (reg < rdev->rio_mem_size) + bus_write_4(rdev->rio_mem, reg, v); + else { + /* XXX No locking? -- dumbbell@ */ + bus_write_4(rdev->rio_mem, RADEON_MM_INDEX, reg); + bus_write_4(rdev->rio_mem, RADEON_MM_DATA, v); + } +} diff --git a/sys/dev/drm2/radeon/r100_reg_safe.h b/sys/dev/drm2/radeon/r100_reg_safe.h new file mode 100644 index 00000000000..23049ad1166 --- /dev/null +++ b/sys/dev/drm2/radeon/r100_reg_safe.h @@ -0,0 +1,31 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned r100_reg_safe_bm[102] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFCF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFF9F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x38E7FE1F, 0xFFC3FF8E, 0x7FF8FFFF, 0xFFFF803C, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFEFFFF, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFCFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFEF, +}; diff --git a/sys/dev/drm2/radeon/r100_track.h b/sys/dev/drm2/radeon/r100_track.h new file mode 100644 index 00000000000..c4c5d8e4a34 --- /dev/null +++ b/sys/dev/drm2/radeon/r100_track.h @@ -0,0 +1,103 @@ +#include +__FBSDID("$FreeBSD$"); + +#define R100_TRACK_MAX_TEXTURE 3 +#define R200_TRACK_MAX_TEXTURE 6 +#define R300_TRACK_MAX_TEXTURE 16 + +#define R100_MAX_CB 1 +#define R300_MAX_CB 4 + +/* + * CS functions + */ +struct r100_cs_track_cb { + struct radeon_bo *robj; + unsigned pitch; + unsigned cpp; + unsigned offset; +}; + +struct r100_cs_track_array { + struct radeon_bo *robj; + unsigned esize; +}; + +struct r100_cs_cube_info { + struct radeon_bo *robj; + unsigned offset; + unsigned width; + unsigned height; +}; + +#define R100_TRACK_COMP_NONE 0 +#define R100_TRACK_COMP_DXT1 1 +#define R100_TRACK_COMP_DXT35 2 + +struct r100_cs_track_texture { + struct radeon_bo *robj; + struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */ + unsigned pitch; + unsigned width; + unsigned height; + unsigned num_levels; + unsigned cpp; + unsigned tex_coord_type; + unsigned txdepth; + unsigned width_11; + unsigned height_11; + bool use_pitch; + bool enabled; + bool lookup_disable; + bool roundup_w; + bool roundup_h; + unsigned compress_format; +}; + +struct r100_cs_track { + unsigned num_cb; + unsigned num_texture; + unsigned maxy; + unsigned vtx_size; + unsigned vap_vf_cntl; + unsigned vap_alt_nverts; + unsigned immd_dwords; + unsigned num_arrays; + unsigned max_indx; + unsigned color_channel_mask; + struct r100_cs_track_array arrays[16]; + struct r100_cs_track_cb cb[R300_MAX_CB]; + struct r100_cs_track_cb zb; + struct r100_cs_track_cb aa; + struct r100_cs_track_texture textures[R300_TRACK_MAX_TEXTURE]; + bool z_enabled; + bool separate_cube; + bool zb_cb_clear; + bool blend_read_enable; + bool cb_dirty; + bool zb_dirty; + bool tex_dirty; + bool aa_dirty; + bool aaresolve; +}; + +int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track); +void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track); +int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); +void r100_cs_dump_packet(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt); + +int r100_cs_packet_parse_vline(struct radeon_cs_parser *p); + +int r200_packet0_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg); + +int r100_reloc_pitch_offset(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, + unsigned reg); +int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + int idx); diff --git a/sys/dev/drm2/radeon/r100d.h b/sys/dev/drm2/radeon/r100d.h new file mode 100644 index 00000000000..96418ca47a2 --- /dev/null +++ b/sys/dev/drm2/radeon/r100d.h @@ -0,0 +1,883 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __R100D_H__ +#define __R100D_H__ + +#include +__FBSDID("$FreeBSD$"); + +#define CP_PACKET0 0x00000000 +#define PACKET0_BASE_INDEX_SHIFT 0 +#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) +#define PACKET0_COUNT_SHIFT 16 +#define PACKET0_COUNT_MASK (0x3fff << 16) +#define CP_PACKET1 0x40000000 +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) +#define CP_PACKET3 0xC0000000 +#define PACKET3_IT_OPCODE_SHIFT 8 +#define PACKET3_IT_OPCODE_MASK (0xff << 8) +#define PACKET3_COUNT_SHIFT 16 +#define PACKET3_COUNT_MASK (0x3fff << 16) +/* PACKET3 op code */ +#define PACKET3_NOP 0x10 +#define PACKET3_3D_DRAW_VBUF 0x28 +#define PACKET3_3D_DRAW_IMMD 0x29 +#define PACKET3_3D_DRAW_INDX 0x2A +#define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_3D_CLEAR_ZMASK 0x32 +#define PACKET3_INDX_BUFFER 0x33 +#define PACKET3_3D_DRAW_VBUF_2 0x34 +#define PACKET3_3D_DRAW_IMMD_2 0x35 +#define PACKET3_3D_DRAW_INDX_2 0x36 +#define PACKET3_3D_CLEAR_HIZ 0x37 +#define PACKET3_BITBLT_MULTI 0x9B + +#define PACKET0(reg, n) (CP_PACKET0 | \ + REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ + REG_SET(PACKET0_COUNT, (n))) +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) +#define PACKET3(op, n) (CP_PACKET3 | \ + REG_SET(PACKET3_IT_OPCODE, (op)) | \ + REG_SET(PACKET3_COUNT, (n))) + +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) +#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) + +/* Registers */ +#define R_0000F0_RBBM_SOFT_RESET 0x0000F0 +#define S_0000F0_SOFT_RESET_CP(x) (((x) & 0x1) << 0) +#define G_0000F0_SOFT_RESET_CP(x) (((x) >> 0) & 0x1) +#define C_0000F0_SOFT_RESET_CP 0xFFFFFFFE +#define S_0000F0_SOFT_RESET_HI(x) (((x) & 0x1) << 1) +#define G_0000F0_SOFT_RESET_HI(x) (((x) >> 1) & 0x1) +#define C_0000F0_SOFT_RESET_HI 0xFFFFFFFD +#define S_0000F0_SOFT_RESET_SE(x) (((x) & 0x1) << 2) +#define G_0000F0_SOFT_RESET_SE(x) (((x) >> 2) & 0x1) +#define C_0000F0_SOFT_RESET_SE 0xFFFFFFFB +#define S_0000F0_SOFT_RESET_RE(x) (((x) & 0x1) << 3) +#define G_0000F0_SOFT_RESET_RE(x) (((x) >> 3) & 0x1) +#define C_0000F0_SOFT_RESET_RE 0xFFFFFFF7 +#define S_0000F0_SOFT_RESET_PP(x) (((x) & 0x1) << 4) +#define G_0000F0_SOFT_RESET_PP(x) (((x) >> 4) & 0x1) +#define C_0000F0_SOFT_RESET_PP 0xFFFFFFEF +#define S_0000F0_SOFT_RESET_E2(x) (((x) & 0x1) << 5) +#define G_0000F0_SOFT_RESET_E2(x) (((x) >> 5) & 0x1) +#define C_0000F0_SOFT_RESET_E2 0xFFFFFFDF +#define S_0000F0_SOFT_RESET_RB(x) (((x) & 0x1) << 6) +#define G_0000F0_SOFT_RESET_RB(x) (((x) >> 6) & 0x1) +#define C_0000F0_SOFT_RESET_RB 0xFFFFFFBF +#define S_0000F0_SOFT_RESET_HDP(x) (((x) & 0x1) << 7) +#define G_0000F0_SOFT_RESET_HDP(x) (((x) >> 7) & 0x1) +#define C_0000F0_SOFT_RESET_HDP 0xFFFFFF7F +#define S_0000F0_SOFT_RESET_MC(x) (((x) & 0x1) << 8) +#define G_0000F0_SOFT_RESET_MC(x) (((x) >> 8) & 0x1) +#define C_0000F0_SOFT_RESET_MC 0xFFFFFEFF +#define S_0000F0_SOFT_RESET_AIC(x) (((x) & 0x1) << 9) +#define G_0000F0_SOFT_RESET_AIC(x) (((x) >> 9) & 0x1) +#define C_0000F0_SOFT_RESET_AIC 0xFFFFFDFF +#define S_0000F0_SOFT_RESET_VIP(x) (((x) & 0x1) << 10) +#define G_0000F0_SOFT_RESET_VIP(x) (((x) >> 10) & 0x1) +#define C_0000F0_SOFT_RESET_VIP 0xFFFFFBFF +#define S_0000F0_SOFT_RESET_DISP(x) (((x) & 0x1) << 11) +#define G_0000F0_SOFT_RESET_DISP(x) (((x) >> 11) & 0x1) +#define C_0000F0_SOFT_RESET_DISP 0xFFFFF7FF +#define S_0000F0_SOFT_RESET_CG(x) (((x) & 0x1) << 12) +#define G_0000F0_SOFT_RESET_CG(x) (((x) >> 12) & 0x1) +#define C_0000F0_SOFT_RESET_CG 0xFFFFEFFF +#define R_000030_BUS_CNTL 0x000030 +#define S_000030_BUS_DBL_RESYNC(x) (((x) & 0x1) << 0) +#define G_000030_BUS_DBL_RESYNC(x) (((x) >> 0) & 0x1) +#define C_000030_BUS_DBL_RESYNC 0xFFFFFFFE +#define S_000030_BUS_MSTR_RESET(x) (((x) & 0x1) << 1) +#define G_000030_BUS_MSTR_RESET(x) (((x) >> 1) & 0x1) +#define C_000030_BUS_MSTR_RESET 0xFFFFFFFD +#define S_000030_BUS_FLUSH_BUF(x) (((x) & 0x1) << 2) +#define G_000030_BUS_FLUSH_BUF(x) (((x) >> 2) & 0x1) +#define C_000030_BUS_FLUSH_BUF 0xFFFFFFFB +#define S_000030_BUS_STOP_REQ_DIS(x) (((x) & 0x1) << 3) +#define G_000030_BUS_STOP_REQ_DIS(x) (((x) >> 3) & 0x1) +#define C_000030_BUS_STOP_REQ_DIS 0xFFFFFFF7 +#define S_000030_BUS_PM4_READ_COMBINE_EN(x) (((x) & 0x1) << 4) +#define G_000030_BUS_PM4_READ_COMBINE_EN(x) (((x) >> 4) & 0x1) +#define C_000030_BUS_PM4_READ_COMBINE_EN 0xFFFFFFEF +#define S_000030_BUS_WRT_COMBINE_EN(x) (((x) & 0x1) << 5) +#define G_000030_BUS_WRT_COMBINE_EN(x) (((x) >> 5) & 0x1) +#define C_000030_BUS_WRT_COMBINE_EN 0xFFFFFFDF +#define S_000030_BUS_MASTER_DIS(x) (((x) & 0x1) << 6) +#define G_000030_BUS_MASTER_DIS(x) (((x) >> 6) & 0x1) +#define C_000030_BUS_MASTER_DIS 0xFFFFFFBF +#define S_000030_BIOS_ROM_WRT_EN(x) (((x) & 0x1) << 7) +#define G_000030_BIOS_ROM_WRT_EN(x) (((x) >> 7) & 0x1) +#define C_000030_BIOS_ROM_WRT_EN 0xFFFFFF7F +#define S_000030_BM_DAC_CRIPPLE(x) (((x) & 0x1) << 8) +#define G_000030_BM_DAC_CRIPPLE(x) (((x) >> 8) & 0x1) +#define C_000030_BM_DAC_CRIPPLE 0xFFFFFEFF +#define S_000030_BUS_NON_PM4_READ_COMBINE_EN(x) (((x) & 0x1) << 9) +#define G_000030_BUS_NON_PM4_READ_COMBINE_EN(x) (((x) >> 9) & 0x1) +#define C_000030_BUS_NON_PM4_READ_COMBINE_EN 0xFFFFFDFF +#define S_000030_BUS_XFERD_DISCARD_EN(x) (((x) & 0x1) << 10) +#define G_000030_BUS_XFERD_DISCARD_EN(x) (((x) >> 10) & 0x1) +#define C_000030_BUS_XFERD_DISCARD_EN 0xFFFFFBFF +#define S_000030_BUS_SGL_READ_DISABLE(x) (((x) & 0x1) << 11) +#define G_000030_BUS_SGL_READ_DISABLE(x) (((x) >> 11) & 0x1) +#define C_000030_BUS_SGL_READ_DISABLE 0xFFFFF7FF +#define S_000030_BIOS_DIS_ROM(x) (((x) & 0x1) << 12) +#define G_000030_BIOS_DIS_ROM(x) (((x) >> 12) & 0x1) +#define C_000030_BIOS_DIS_ROM 0xFFFFEFFF +#define S_000030_BUS_PCI_READ_RETRY_EN(x) (((x) & 0x1) << 13) +#define G_000030_BUS_PCI_READ_RETRY_EN(x) (((x) >> 13) & 0x1) +#define C_000030_BUS_PCI_READ_RETRY_EN 0xFFFFDFFF +#define S_000030_BUS_AGP_AD_STEPPING_EN(x) (((x) & 0x1) << 14) +#define G_000030_BUS_AGP_AD_STEPPING_EN(x) (((x) >> 14) & 0x1) +#define C_000030_BUS_AGP_AD_STEPPING_EN 0xFFFFBFFF +#define S_000030_BUS_PCI_WRT_RETRY_EN(x) (((x) & 0x1) << 15) +#define G_000030_BUS_PCI_WRT_RETRY_EN(x) (((x) >> 15) & 0x1) +#define C_000030_BUS_PCI_WRT_RETRY_EN 0xFFFF7FFF +#define S_000030_BUS_RETRY_WS(x) (((x) & 0xF) << 16) +#define G_000030_BUS_RETRY_WS(x) (((x) >> 16) & 0xF) +#define C_000030_BUS_RETRY_WS 0xFFF0FFFF +#define S_000030_BUS_MSTR_RD_MULT(x) (((x) & 0x1) << 20) +#define G_000030_BUS_MSTR_RD_MULT(x) (((x) >> 20) & 0x1) +#define C_000030_BUS_MSTR_RD_MULT 0xFFEFFFFF +#define S_000030_BUS_MSTR_RD_LINE(x) (((x) & 0x1) << 21) +#define G_000030_BUS_MSTR_RD_LINE(x) (((x) >> 21) & 0x1) +#define C_000030_BUS_MSTR_RD_LINE 0xFFDFFFFF +#define S_000030_BUS_SUSPEND(x) (((x) & 0x1) << 22) +#define G_000030_BUS_SUSPEND(x) (((x) >> 22) & 0x1) +#define C_000030_BUS_SUSPEND 0xFFBFFFFF +#define S_000030_LAT_16X(x) (((x) & 0x1) << 23) +#define G_000030_LAT_16X(x) (((x) >> 23) & 0x1) +#define C_000030_LAT_16X 0xFF7FFFFF +#define S_000030_BUS_RD_DISCARD_EN(x) (((x) & 0x1) << 24) +#define G_000030_BUS_RD_DISCARD_EN(x) (((x) >> 24) & 0x1) +#define C_000030_BUS_RD_DISCARD_EN 0xFEFFFFFF +#define S_000030_ENFRCWRDY(x) (((x) & 0x1) << 25) +#define G_000030_ENFRCWRDY(x) (((x) >> 25) & 0x1) +#define C_000030_ENFRCWRDY 0xFDFFFFFF +#define S_000030_BUS_MSTR_WS(x) (((x) & 0x1) << 26) +#define G_000030_BUS_MSTR_WS(x) (((x) >> 26) & 0x1) +#define C_000030_BUS_MSTR_WS 0xFBFFFFFF +#define S_000030_BUS_PARKING_DIS(x) (((x) & 0x1) << 27) +#define G_000030_BUS_PARKING_DIS(x) (((x) >> 27) & 0x1) +#define C_000030_BUS_PARKING_DIS 0xF7FFFFFF +#define S_000030_BUS_MSTR_DISCONNECT_EN(x) (((x) & 0x1) << 28) +#define G_000030_BUS_MSTR_DISCONNECT_EN(x) (((x) >> 28) & 0x1) +#define C_000030_BUS_MSTR_DISCONNECT_EN 0xEFFFFFFF +#define S_000030_SERR_EN(x) (((x) & 0x1) << 29) +#define G_000030_SERR_EN(x) (((x) >> 29) & 0x1) +#define C_000030_SERR_EN 0xDFFFFFFF +#define S_000030_BUS_READ_BURST(x) (((x) & 0x1) << 30) +#define G_000030_BUS_READ_BURST(x) (((x) >> 30) & 0x1) +#define C_000030_BUS_READ_BURST 0xBFFFFFFF +#define S_000030_BUS_RDY_READ_DLY(x) (((x) & 0x1) << 31) +#define G_000030_BUS_RDY_READ_DLY(x) (((x) >> 31) & 0x1) +#define C_000030_BUS_RDY_READ_DLY 0x7FFFFFFF +#define R_000040_GEN_INT_CNTL 0x000040 +#define S_000040_CRTC_VBLANK(x) (((x) & 0x1) << 0) +#define G_000040_CRTC_VBLANK(x) (((x) >> 0) & 0x1) +#define C_000040_CRTC_VBLANK 0xFFFFFFFE +#define S_000040_CRTC_VLINE(x) (((x) & 0x1) << 1) +#define G_000040_CRTC_VLINE(x) (((x) >> 1) & 0x1) +#define C_000040_CRTC_VLINE 0xFFFFFFFD +#define S_000040_CRTC_VSYNC(x) (((x) & 0x1) << 2) +#define G_000040_CRTC_VSYNC(x) (((x) >> 2) & 0x1) +#define C_000040_CRTC_VSYNC 0xFFFFFFFB +#define S_000040_SNAPSHOT(x) (((x) & 0x1) << 3) +#define G_000040_SNAPSHOT(x) (((x) >> 3) & 0x1) +#define C_000040_SNAPSHOT 0xFFFFFFF7 +#define S_000040_FP_DETECT(x) (((x) & 0x1) << 4) +#define G_000040_FP_DETECT(x) (((x) >> 4) & 0x1) +#define C_000040_FP_DETECT 0xFFFFFFEF +#define S_000040_CRTC2_VLINE(x) (((x) & 0x1) << 5) +#define G_000040_CRTC2_VLINE(x) (((x) >> 5) & 0x1) +#define C_000040_CRTC2_VLINE 0xFFFFFFDF +#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12) +#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1) +#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF +#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6) +#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1) +#define C_000040_CRTC2_VSYNC 0xFFFFFFBF +#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7) +#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1) +#define C_000040_SNAPSHOT2 0xFFFFFF7F +#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9) +#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1) +#define C_000040_CRTC2_VBLANK 0xFFFFFDFF +#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10) +#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1) +#define C_000040_FP2_DETECT 0xFFFFFBFF +#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11) +#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1) +#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF +#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13) +#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1) +#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF +#define S_000040_DMA_VIPH2_INT_EN(x) (((x) & 0x1) << 14) +#define G_000040_DMA_VIPH2_INT_EN(x) (((x) >> 14) & 0x1) +#define C_000040_DMA_VIPH2_INT_EN 0xFFFFBFFF +#define S_000040_DMA_VIPH3_INT_EN(x) (((x) & 0x1) << 15) +#define G_000040_DMA_VIPH3_INT_EN(x) (((x) >> 15) & 0x1) +#define C_000040_DMA_VIPH3_INT_EN 0xFFFF7FFF +#define S_000040_I2C_INT_EN(x) (((x) & 0x1) << 17) +#define G_000040_I2C_INT_EN(x) (((x) >> 17) & 0x1) +#define C_000040_I2C_INT_EN 0xFFFDFFFF +#define S_000040_GUI_IDLE(x) (((x) & 0x1) << 19) +#define G_000040_GUI_IDLE(x) (((x) >> 19) & 0x1) +#define C_000040_GUI_IDLE 0xFFF7FFFF +#define S_000040_VIPH_INT_EN(x) (((x) & 0x1) << 24) +#define G_000040_VIPH_INT_EN(x) (((x) >> 24) & 0x1) +#define C_000040_VIPH_INT_EN 0xFEFFFFFF +#define S_000040_SW_INT_EN(x) (((x) & 0x1) << 25) +#define G_000040_SW_INT_EN(x) (((x) >> 25) & 0x1) +#define C_000040_SW_INT_EN 0xFDFFFFFF +#define S_000040_GEYSERVILLE(x) (((x) & 0x1) << 27) +#define G_000040_GEYSERVILLE(x) (((x) >> 27) & 0x1) +#define C_000040_GEYSERVILLE 0xF7FFFFFF +#define S_000040_HDCP_AUTHORIZED_INT(x) (((x) & 0x1) << 28) +#define G_000040_HDCP_AUTHORIZED_INT(x) (((x) >> 28) & 0x1) +#define C_000040_HDCP_AUTHORIZED_INT 0xEFFFFFFF +#define S_000040_DVI_I2C_INT(x) (((x) & 0x1) << 29) +#define G_000040_DVI_I2C_INT(x) (((x) >> 29) & 0x1) +#define C_000040_DVI_I2C_INT 0xDFFFFFFF +#define S_000040_GUIDMA(x) (((x) & 0x1) << 30) +#define G_000040_GUIDMA(x) (((x) >> 30) & 0x1) +#define C_000040_GUIDMA 0xBFFFFFFF +#define S_000040_VIDDMA(x) (((x) & 0x1) << 31) +#define G_000040_VIDDMA(x) (((x) >> 31) & 0x1) +#define C_000040_VIDDMA 0x7FFFFFFF +#define R_000044_GEN_INT_STATUS 0x000044 +#define S_000044_CRTC_VBLANK_STAT(x) (((x) & 0x1) << 0) +#define G_000044_CRTC_VBLANK_STAT(x) (((x) >> 0) & 0x1) +#define C_000044_CRTC_VBLANK_STAT 0xFFFFFFFE +#define S_000044_CRTC_VBLANK_STAT_AK(x) (((x) & 0x1) << 0) +#define G_000044_CRTC_VBLANK_STAT_AK(x) (((x) >> 0) & 0x1) +#define C_000044_CRTC_VBLANK_STAT_AK 0xFFFFFFFE +#define S_000044_CRTC_VLINE_STAT(x) (((x) & 0x1) << 1) +#define G_000044_CRTC_VLINE_STAT(x) (((x) >> 1) & 0x1) +#define C_000044_CRTC_VLINE_STAT 0xFFFFFFFD +#define S_000044_CRTC_VLINE_STAT_AK(x) (((x) & 0x1) << 1) +#define G_000044_CRTC_VLINE_STAT_AK(x) (((x) >> 1) & 0x1) +#define C_000044_CRTC_VLINE_STAT_AK 0xFFFFFFFD +#define S_000044_CRTC_VSYNC_STAT(x) (((x) & 0x1) << 2) +#define G_000044_CRTC_VSYNC_STAT(x) (((x) >> 2) & 0x1) +#define C_000044_CRTC_VSYNC_STAT 0xFFFFFFFB +#define S_000044_CRTC_VSYNC_STAT_AK(x) (((x) & 0x1) << 2) +#define G_000044_CRTC_VSYNC_STAT_AK(x) (((x) >> 2) & 0x1) +#define C_000044_CRTC_VSYNC_STAT_AK 0xFFFFFFFB +#define S_000044_SNAPSHOT_STAT(x) (((x) & 0x1) << 3) +#define G_000044_SNAPSHOT_STAT(x) (((x) >> 3) & 0x1) +#define C_000044_SNAPSHOT_STAT 0xFFFFFFF7 +#define S_000044_SNAPSHOT_STAT_AK(x) (((x) & 0x1) << 3) +#define G_000044_SNAPSHOT_STAT_AK(x) (((x) >> 3) & 0x1) +#define C_000044_SNAPSHOT_STAT_AK 0xFFFFFFF7 +#define S_000044_FP_DETECT_STAT(x) (((x) & 0x1) << 4) +#define G_000044_FP_DETECT_STAT(x) (((x) >> 4) & 0x1) +#define C_000044_FP_DETECT_STAT 0xFFFFFFEF +#define S_000044_FP_DETECT_STAT_AK(x) (((x) & 0x1) << 4) +#define G_000044_FP_DETECT_STAT_AK(x) (((x) >> 4) & 0x1) +#define C_000044_FP_DETECT_STAT_AK 0xFFFFFFEF +#define S_000044_CRTC2_VLINE_STAT(x) (((x) & 0x1) << 5) +#define G_000044_CRTC2_VLINE_STAT(x) (((x) >> 5) & 0x1) +#define C_000044_CRTC2_VLINE_STAT 0xFFFFFFDF +#define S_000044_CRTC2_VLINE_STAT_AK(x) (((x) & 0x1) << 5) +#define G_000044_CRTC2_VLINE_STAT_AK(x) (((x) >> 5) & 0x1) +#define C_000044_CRTC2_VLINE_STAT_AK 0xFFFFFFDF +#define S_000044_CRTC2_VSYNC_STAT(x) (((x) & 0x1) << 6) +#define G_000044_CRTC2_VSYNC_STAT(x) (((x) >> 6) & 0x1) +#define C_000044_CRTC2_VSYNC_STAT 0xFFFFFFBF +#define S_000044_CRTC2_VSYNC_STAT_AK(x) (((x) & 0x1) << 6) +#define G_000044_CRTC2_VSYNC_STAT_AK(x) (((x) >> 6) & 0x1) +#define C_000044_CRTC2_VSYNC_STAT_AK 0xFFFFFFBF +#define S_000044_SNAPSHOT2_STAT(x) (((x) & 0x1) << 7) +#define G_000044_SNAPSHOT2_STAT(x) (((x) >> 7) & 0x1) +#define C_000044_SNAPSHOT2_STAT 0xFFFFFF7F +#define S_000044_SNAPSHOT2_STAT_AK(x) (((x) & 0x1) << 7) +#define G_000044_SNAPSHOT2_STAT_AK(x) (((x) >> 7) & 0x1) +#define C_000044_SNAPSHOT2_STAT_AK 0xFFFFFF7F +#define S_000044_CAP0_INT_ACTIVE(x) (((x) & 0x1) << 8) +#define G_000044_CAP0_INT_ACTIVE(x) (((x) >> 8) & 0x1) +#define C_000044_CAP0_INT_ACTIVE 0xFFFFFEFF +#define S_000044_CRTC2_VBLANK_STAT(x) (((x) & 0x1) << 9) +#define G_000044_CRTC2_VBLANK_STAT(x) (((x) >> 9) & 0x1) +#define C_000044_CRTC2_VBLANK_STAT 0xFFFFFDFF +#define S_000044_CRTC2_VBLANK_STAT_AK(x) (((x) & 0x1) << 9) +#define G_000044_CRTC2_VBLANK_STAT_AK(x) (((x) >> 9) & 0x1) +#define C_000044_CRTC2_VBLANK_STAT_AK 0xFFFFFDFF +#define S_000044_FP2_DETECT_STAT(x) (((x) & 0x1) << 10) +#define G_000044_FP2_DETECT_STAT(x) (((x) >> 10) & 0x1) +#define C_000044_FP2_DETECT_STAT 0xFFFFFBFF +#define S_000044_FP2_DETECT_STAT_AK(x) (((x) & 0x1) << 10) +#define G_000044_FP2_DETECT_STAT_AK(x) (((x) >> 10) & 0x1) +#define C_000044_FP2_DETECT_STAT_AK 0xFFFFFBFF +#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) & 0x1) << 11) +#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) >> 11) & 0x1) +#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT 0xFFFFF7FF +#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) & 0x1) << 11) +#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) >> 11) & 0x1) +#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK 0xFFFFF7FF +#define S_000044_DMA_VIPH0_INT(x) (((x) & 0x1) << 12) +#define G_000044_DMA_VIPH0_INT(x) (((x) >> 12) & 0x1) +#define C_000044_DMA_VIPH0_INT 0xFFFFEFFF +#define S_000044_DMA_VIPH0_INT_AK(x) (((x) & 0x1) << 12) +#define G_000044_DMA_VIPH0_INT_AK(x) (((x) >> 12) & 0x1) +#define C_000044_DMA_VIPH0_INT_AK 0xFFFFEFFF +#define S_000044_DMA_VIPH1_INT(x) (((x) & 0x1) << 13) +#define G_000044_DMA_VIPH1_INT(x) (((x) >> 13) & 0x1) +#define C_000044_DMA_VIPH1_INT 0xFFFFDFFF +#define S_000044_DMA_VIPH1_INT_AK(x) (((x) & 0x1) << 13) +#define G_000044_DMA_VIPH1_INT_AK(x) (((x) >> 13) & 0x1) +#define C_000044_DMA_VIPH1_INT_AK 0xFFFFDFFF +#define S_000044_DMA_VIPH2_INT(x) (((x) & 0x1) << 14) +#define G_000044_DMA_VIPH2_INT(x) (((x) >> 14) & 0x1) +#define C_000044_DMA_VIPH2_INT 0xFFFFBFFF +#define S_000044_DMA_VIPH2_INT_AK(x) (((x) & 0x1) << 14) +#define G_000044_DMA_VIPH2_INT_AK(x) (((x) >> 14) & 0x1) +#define C_000044_DMA_VIPH2_INT_AK 0xFFFFBFFF +#define S_000044_DMA_VIPH3_INT(x) (((x) & 0x1) << 15) +#define G_000044_DMA_VIPH3_INT(x) (((x) >> 15) & 0x1) +#define C_000044_DMA_VIPH3_INT 0xFFFF7FFF +#define S_000044_DMA_VIPH3_INT_AK(x) (((x) & 0x1) << 15) +#define G_000044_DMA_VIPH3_INT_AK(x) (((x) >> 15) & 0x1) +#define C_000044_DMA_VIPH3_INT_AK 0xFFFF7FFF +#define S_000044_I2C_INT(x) (((x) & 0x1) << 17) +#define G_000044_I2C_INT(x) (((x) >> 17) & 0x1) +#define C_000044_I2C_INT 0xFFFDFFFF +#define S_000044_I2C_INT_AK(x) (((x) & 0x1) << 17) +#define G_000044_I2C_INT_AK(x) (((x) >> 17) & 0x1) +#define C_000044_I2C_INT_AK 0xFFFDFFFF +#define S_000044_GUI_IDLE_STAT(x) (((x) & 0x1) << 19) +#define G_000044_GUI_IDLE_STAT(x) (((x) >> 19) & 0x1) +#define C_000044_GUI_IDLE_STAT 0xFFF7FFFF +#define S_000044_GUI_IDLE_STAT_AK(x) (((x) & 0x1) << 19) +#define G_000044_GUI_IDLE_STAT_AK(x) (((x) >> 19) & 0x1) +#define C_000044_GUI_IDLE_STAT_AK 0xFFF7FFFF +#define S_000044_VIPH_INT(x) (((x) & 0x1) << 24) +#define G_000044_VIPH_INT(x) (((x) >> 24) & 0x1) +#define C_000044_VIPH_INT 0xFEFFFFFF +#define S_000044_SW_INT(x) (((x) & 0x1) << 25) +#define G_000044_SW_INT(x) (((x) >> 25) & 0x1) +#define C_000044_SW_INT 0xFDFFFFFF +#define S_000044_SW_INT_AK(x) (((x) & 0x1) << 25) +#define G_000044_SW_INT_AK(x) (((x) >> 25) & 0x1) +#define C_000044_SW_INT_AK 0xFDFFFFFF +#define S_000044_SW_INT_SET(x) (((x) & 0x1) << 26) +#define G_000044_SW_INT_SET(x) (((x) >> 26) & 0x1) +#define C_000044_SW_INT_SET 0xFBFFFFFF +#define S_000044_GEYSERVILLE_STAT(x) (((x) & 0x1) << 27) +#define G_000044_GEYSERVILLE_STAT(x) (((x) >> 27) & 0x1) +#define C_000044_GEYSERVILLE_STAT 0xF7FFFFFF +#define S_000044_GEYSERVILLE_STAT_AK(x) (((x) & 0x1) << 27) +#define G_000044_GEYSERVILLE_STAT_AK(x) (((x) >> 27) & 0x1) +#define C_000044_GEYSERVILLE_STAT_AK 0xF7FFFFFF +#define S_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) & 0x1) << 28) +#define G_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) >> 28) & 0x1) +#define C_000044_HDCP_AUTHORIZED_INT_STAT 0xEFFFFFFF +#define S_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) & 0x1) << 28) +#define G_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) >> 28) & 0x1) +#define C_000044_HDCP_AUTHORIZED_INT_AK 0xEFFFFFFF +#define S_000044_DVI_I2C_INT_STAT(x) (((x) & 0x1) << 29) +#define G_000044_DVI_I2C_INT_STAT(x) (((x) >> 29) & 0x1) +#define C_000044_DVI_I2C_INT_STAT 0xDFFFFFFF +#define S_000044_DVI_I2C_INT_AK(x) (((x) & 0x1) << 29) +#define G_000044_DVI_I2C_INT_AK(x) (((x) >> 29) & 0x1) +#define C_000044_DVI_I2C_INT_AK 0xDFFFFFFF +#define S_000044_GUIDMA_STAT(x) (((x) & 0x1) << 30) +#define G_000044_GUIDMA_STAT(x) (((x) >> 30) & 0x1) +#define C_000044_GUIDMA_STAT 0xBFFFFFFF +#define S_000044_GUIDMA_AK(x) (((x) & 0x1) << 30) +#define G_000044_GUIDMA_AK(x) (((x) >> 30) & 0x1) +#define C_000044_GUIDMA_AK 0xBFFFFFFF +#define S_000044_VIDDMA_STAT(x) (((x) & 0x1) << 31) +#define G_000044_VIDDMA_STAT(x) (((x) >> 31) & 0x1) +#define C_000044_VIDDMA_STAT 0x7FFFFFFF +#define S_000044_VIDDMA_AK(x) (((x) & 0x1) << 31) +#define G_000044_VIDDMA_AK(x) (((x) >> 31) & 0x1) +#define C_000044_VIDDMA_AK 0x7FFFFFFF +#define R_000050_CRTC_GEN_CNTL 0x000050 +#define S_000050_CRTC_DBL_SCAN_EN(x) (((x) & 0x1) << 0) +#define G_000050_CRTC_DBL_SCAN_EN(x) (((x) >> 0) & 0x1) +#define C_000050_CRTC_DBL_SCAN_EN 0xFFFFFFFE +#define S_000050_CRTC_INTERLACE_EN(x) (((x) & 0x1) << 1) +#define G_000050_CRTC_INTERLACE_EN(x) (((x) >> 1) & 0x1) +#define C_000050_CRTC_INTERLACE_EN 0xFFFFFFFD +#define S_000050_CRTC_C_SYNC_EN(x) (((x) & 0x1) << 4) +#define G_000050_CRTC_C_SYNC_EN(x) (((x) >> 4) & 0x1) +#define C_000050_CRTC_C_SYNC_EN 0xFFFFFFEF +#define S_000050_CRTC_PIX_WIDTH(x) (((x) & 0xF) << 8) +#define G_000050_CRTC_PIX_WIDTH(x) (((x) >> 8) & 0xF) +#define C_000050_CRTC_PIX_WIDTH 0xFFFFF0FF +#define S_000050_CRTC_ICON_EN(x) (((x) & 0x1) << 15) +#define G_000050_CRTC_ICON_EN(x) (((x) >> 15) & 0x1) +#define C_000050_CRTC_ICON_EN 0xFFFF7FFF +#define S_000050_CRTC_CUR_EN(x) (((x) & 0x1) << 16) +#define G_000050_CRTC_CUR_EN(x) (((x) >> 16) & 0x1) +#define C_000050_CRTC_CUR_EN 0xFFFEFFFF +#define S_000050_CRTC_VSTAT_MODE(x) (((x) & 0x3) << 17) +#define G_000050_CRTC_VSTAT_MODE(x) (((x) >> 17) & 0x3) +#define C_000050_CRTC_VSTAT_MODE 0xFFF9FFFF +#define S_000050_CRTC_CUR_MODE(x) (((x) & 0x7) << 20) +#define G_000050_CRTC_CUR_MODE(x) (((x) >> 20) & 0x7) +#define C_000050_CRTC_CUR_MODE 0xFF8FFFFF +#define S_000050_CRTC_EXT_DISP_EN(x) (((x) & 0x1) << 24) +#define G_000050_CRTC_EXT_DISP_EN(x) (((x) >> 24) & 0x1) +#define C_000050_CRTC_EXT_DISP_EN 0xFEFFFFFF +#define S_000050_CRTC_EN(x) (((x) & 0x1) << 25) +#define G_000050_CRTC_EN(x) (((x) >> 25) & 0x1) +#define C_000050_CRTC_EN 0xFDFFFFFF +#define S_000050_CRTC_DISP_REQ_EN_B(x) (((x) & 0x1) << 26) +#define G_000050_CRTC_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1) +#define C_000050_CRTC_DISP_REQ_EN_B 0xFBFFFFFF +#define R_000054_CRTC_EXT_CNTL 0x000054 +#define S_000054_CRTC_VGA_XOVERSCAN(x) (((x) & 0x1) << 0) +#define G_000054_CRTC_VGA_XOVERSCAN(x) (((x) >> 0) & 0x1) +#define C_000054_CRTC_VGA_XOVERSCAN 0xFFFFFFFE +#define S_000054_VGA_BLINK_RATE(x) (((x) & 0x3) << 1) +#define G_000054_VGA_BLINK_RATE(x) (((x) >> 1) & 0x3) +#define C_000054_VGA_BLINK_RATE 0xFFFFFFF9 +#define S_000054_VGA_ATI_LINEAR(x) (((x) & 0x1) << 3) +#define G_000054_VGA_ATI_LINEAR(x) (((x) >> 3) & 0x1) +#define C_000054_VGA_ATI_LINEAR 0xFFFFFFF7 +#define S_000054_VGA_128KAP_PAGING(x) (((x) & 0x1) << 4) +#define G_000054_VGA_128KAP_PAGING(x) (((x) >> 4) & 0x1) +#define C_000054_VGA_128KAP_PAGING 0xFFFFFFEF +#define S_000054_VGA_TEXT_132(x) (((x) & 0x1) << 5) +#define G_000054_VGA_TEXT_132(x) (((x) >> 5) & 0x1) +#define C_000054_VGA_TEXT_132 0xFFFFFFDF +#define S_000054_VGA_XCRT_CNT_EN(x) (((x) & 0x1) << 6) +#define G_000054_VGA_XCRT_CNT_EN(x) (((x) >> 6) & 0x1) +#define C_000054_VGA_XCRT_CNT_EN 0xFFFFFFBF +#define S_000054_CRTC_HSYNC_DIS(x) (((x) & 0x1) << 8) +#define G_000054_CRTC_HSYNC_DIS(x) (((x) >> 8) & 0x1) +#define C_000054_CRTC_HSYNC_DIS 0xFFFFFEFF +#define S_000054_CRTC_VSYNC_DIS(x) (((x) & 0x1) << 9) +#define G_000054_CRTC_VSYNC_DIS(x) (((x) >> 9) & 0x1) +#define C_000054_CRTC_VSYNC_DIS 0xFFFFFDFF +#define S_000054_CRTC_DISPLAY_DIS(x) (((x) & 0x1) << 10) +#define G_000054_CRTC_DISPLAY_DIS(x) (((x) >> 10) & 0x1) +#define C_000054_CRTC_DISPLAY_DIS 0xFFFFFBFF +#define S_000054_CRTC_SYNC_TRISTATE(x) (((x) & 0x1) << 11) +#define G_000054_CRTC_SYNC_TRISTATE(x) (((x) >> 11) & 0x1) +#define C_000054_CRTC_SYNC_TRISTATE 0xFFFFF7FF +#define S_000054_CRTC_HSYNC_TRISTATE(x) (((x) & 0x1) << 12) +#define G_000054_CRTC_HSYNC_TRISTATE(x) (((x) >> 12) & 0x1) +#define C_000054_CRTC_HSYNC_TRISTATE 0xFFFFEFFF +#define S_000054_CRTC_VSYNC_TRISTATE(x) (((x) & 0x1) << 13) +#define G_000054_CRTC_VSYNC_TRISTATE(x) (((x) >> 13) & 0x1) +#define C_000054_CRTC_VSYNC_TRISTATE 0xFFFFDFFF +#define S_000054_CRT_ON(x) (((x) & 0x1) << 15) +#define G_000054_CRT_ON(x) (((x) >> 15) & 0x1) +#define C_000054_CRT_ON 0xFFFF7FFF +#define S_000054_VGA_CUR_B_TEST(x) (((x) & 0x1) << 17) +#define G_000054_VGA_CUR_B_TEST(x) (((x) >> 17) & 0x1) +#define C_000054_VGA_CUR_B_TEST 0xFFFDFFFF +#define S_000054_VGA_PACK_DIS(x) (((x) & 0x1) << 18) +#define G_000054_VGA_PACK_DIS(x) (((x) >> 18) & 0x1) +#define C_000054_VGA_PACK_DIS 0xFFFBFFFF +#define S_000054_VGA_MEM_PS_EN(x) (((x) & 0x1) << 19) +#define G_000054_VGA_MEM_PS_EN(x) (((x) >> 19) & 0x1) +#define C_000054_VGA_MEM_PS_EN 0xFFF7FFFF +#define S_000054_VCRTC_IDX_MASTER(x) (((x) & 0x7F) << 24) +#define G_000054_VCRTC_IDX_MASTER(x) (((x) >> 24) & 0x7F) +#define C_000054_VCRTC_IDX_MASTER 0x80FFFFFF +#define R_000148_MC_FB_LOCATION 0x000148 +#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000148_MC_FB_START 0xFFFF0000 +#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000148_MC_FB_TOP 0x0000FFFF +#define R_00014C_MC_AGP_LOCATION 0x00014C +#define S_00014C_MC_AGP_START(x) (((x) & 0xFFFF) << 0) +#define G_00014C_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) +#define C_00014C_MC_AGP_START 0xFFFF0000 +#define S_00014C_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) +#define G_00014C_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_00014C_MC_AGP_TOP 0x0000FFFF +#define R_000170_AGP_BASE 0x000170 +#define S_000170_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000170_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000170_AGP_BASE_ADDR 0x00000000 +#define R_00023C_DISPLAY_BASE_ADDR 0x00023C +#define S_00023C_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_00023C_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_00023C_DISPLAY_BASE_ADDR 0x00000000 +#define R_000260_CUR_OFFSET 0x000260 +#define S_000260_CUR_OFFSET(x) (((x) & 0x7FFFFFF) << 0) +#define G_000260_CUR_OFFSET(x) (((x) >> 0) & 0x7FFFFFF) +#define C_000260_CUR_OFFSET 0xF8000000 +#define S_000260_CUR_LOCK(x) (((x) & 0x1) << 31) +#define G_000260_CUR_LOCK(x) (((x) >> 31) & 0x1) +#define C_000260_CUR_LOCK 0x7FFFFFFF +#define R_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00033C +#define S_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00000000 +#define R_000360_CUR2_OFFSET 0x000360 +#define S_000360_CUR2_OFFSET(x) (((x) & 0x7FFFFFF) << 0) +#define G_000360_CUR2_OFFSET(x) (((x) >> 0) & 0x7FFFFFF) +#define C_000360_CUR2_OFFSET 0xF8000000 +#define S_000360_CUR2_LOCK(x) (((x) & 0x1) << 31) +#define G_000360_CUR2_LOCK(x) (((x) >> 31) & 0x1) +#define C_000360_CUR2_LOCK 0x7FFFFFFF +#define R_0003C2_GENMO_WT 0x0003C2 +#define S_0003C2_GENMO_MONO_ADDRESS_B(x) (((x) & 0x1) << 0) +#define G_0003C2_GENMO_MONO_ADDRESS_B(x) (((x) >> 0) & 0x1) +#define C_0003C2_GENMO_MONO_ADDRESS_B 0xFE +#define S_0003C2_VGA_RAM_EN(x) (((x) & 0x1) << 1) +#define G_0003C2_VGA_RAM_EN(x) (((x) >> 1) & 0x1) +#define C_0003C2_VGA_RAM_EN 0xFD +#define S_0003C2_VGA_CKSEL(x) (((x) & 0x3) << 2) +#define G_0003C2_VGA_CKSEL(x) (((x) >> 2) & 0x3) +#define C_0003C2_VGA_CKSEL 0xF3 +#define S_0003C2_ODD_EVEN_MD_PGSEL(x) (((x) & 0x1) << 5) +#define G_0003C2_ODD_EVEN_MD_PGSEL(x) (((x) >> 5) & 0x1) +#define C_0003C2_ODD_EVEN_MD_PGSEL 0xDF +#define S_0003C2_VGA_HSYNC_POL(x) (((x) & 0x1) << 6) +#define G_0003C2_VGA_HSYNC_POL(x) (((x) >> 6) & 0x1) +#define C_0003C2_VGA_HSYNC_POL 0xBF +#define S_0003C2_VGA_VSYNC_POL(x) (((x) & 0x1) << 7) +#define G_0003C2_VGA_VSYNC_POL(x) (((x) >> 7) & 0x1) +#define C_0003C2_VGA_VSYNC_POL 0x7F +#define R_0003F8_CRTC2_GEN_CNTL 0x0003F8 +#define S_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) & 0x1) << 0) +#define G_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) >> 0) & 0x1) +#define C_0003F8_CRTC2_DBL_SCAN_EN 0xFFFFFFFE +#define S_0003F8_CRTC2_INTERLACE_EN(x) (((x) & 0x1) << 1) +#define G_0003F8_CRTC2_INTERLACE_EN(x) (((x) >> 1) & 0x1) +#define C_0003F8_CRTC2_INTERLACE_EN 0xFFFFFFFD +#define S_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) & 0x1) << 4) +#define G_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) >> 4) & 0x1) +#define C_0003F8_CRTC2_SYNC_TRISTATE 0xFFFFFFEF +#define S_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) & 0x1) << 5) +#define G_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) >> 5) & 0x1) +#define C_0003F8_CRTC2_HSYNC_TRISTATE 0xFFFFFFDF +#define S_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) & 0x1) << 6) +#define G_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) >> 6) & 0x1) +#define C_0003F8_CRTC2_VSYNC_TRISTATE 0xFFFFFFBF +#define S_0003F8_CRT2_ON(x) (((x) & 0x1) << 7) +#define G_0003F8_CRT2_ON(x) (((x) >> 7) & 0x1) +#define C_0003F8_CRT2_ON 0xFFFFFF7F +#define S_0003F8_CRTC2_PIX_WIDTH(x) (((x) & 0xF) << 8) +#define G_0003F8_CRTC2_PIX_WIDTH(x) (((x) >> 8) & 0xF) +#define C_0003F8_CRTC2_PIX_WIDTH 0xFFFFF0FF +#define S_0003F8_CRTC2_ICON_EN(x) (((x) & 0x1) << 15) +#define G_0003F8_CRTC2_ICON_EN(x) (((x) >> 15) & 0x1) +#define C_0003F8_CRTC2_ICON_EN 0xFFFF7FFF +#define S_0003F8_CRTC2_CUR_EN(x) (((x) & 0x1) << 16) +#define G_0003F8_CRTC2_CUR_EN(x) (((x) >> 16) & 0x1) +#define C_0003F8_CRTC2_CUR_EN 0xFFFEFFFF +#define S_0003F8_CRTC2_CUR_MODE(x) (((x) & 0x7) << 20) +#define G_0003F8_CRTC2_CUR_MODE(x) (((x) >> 20) & 0x7) +#define C_0003F8_CRTC2_CUR_MODE 0xFF8FFFFF +#define S_0003F8_CRTC2_DISPLAY_DIS(x) (((x) & 0x1) << 23) +#define G_0003F8_CRTC2_DISPLAY_DIS(x) (((x) >> 23) & 0x1) +#define C_0003F8_CRTC2_DISPLAY_DIS 0xFF7FFFFF +#define S_0003F8_CRTC2_EN(x) (((x) & 0x1) << 25) +#define G_0003F8_CRTC2_EN(x) (((x) >> 25) & 0x1) +#define C_0003F8_CRTC2_EN 0xFDFFFFFF +#define S_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) & 0x1) << 26) +#define G_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1) +#define C_0003F8_CRTC2_DISP_REQ_EN_B 0xFBFFFFFF +#define S_0003F8_CRTC2_C_SYNC_EN(x) (((x) & 0x1) << 27) +#define G_0003F8_CRTC2_C_SYNC_EN(x) (((x) >> 27) & 0x1) +#define C_0003F8_CRTC2_C_SYNC_EN 0xF7FFFFFF +#define S_0003F8_CRTC2_HSYNC_DIS(x) (((x) & 0x1) << 28) +#define G_0003F8_CRTC2_HSYNC_DIS(x) (((x) >> 28) & 0x1) +#define C_0003F8_CRTC2_HSYNC_DIS 0xEFFFFFFF +#define S_0003F8_CRTC2_VSYNC_DIS(x) (((x) & 0x1) << 29) +#define G_0003F8_CRTC2_VSYNC_DIS(x) (((x) >> 29) & 0x1) +#define C_0003F8_CRTC2_VSYNC_DIS 0xDFFFFFFF +#define R_000420_OV0_SCALE_CNTL 0x000420 +#define S_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) & 0x1) << 1) +#define G_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) >> 1) & 0x1) +#define C_000420_OV0_NO_READ_BEHIND_SCAN 0xFFFFFFFD +#define S_000420_OV0_HORZ_PICK_NEAREST(x) (((x) & 0x1) << 2) +#define G_000420_OV0_HORZ_PICK_NEAREST(x) (((x) >> 2) & 0x1) +#define C_000420_OV0_HORZ_PICK_NEAREST 0xFFFFFFFB +#define S_000420_OV0_VERT_PICK_NEAREST(x) (((x) & 0x1) << 3) +#define G_000420_OV0_VERT_PICK_NEAREST(x) (((x) >> 3) & 0x1) +#define C_000420_OV0_VERT_PICK_NEAREST 0xFFFFFFF7 +#define S_000420_OV0_SIGNED_UV(x) (((x) & 0x1) << 4) +#define G_000420_OV0_SIGNED_UV(x) (((x) >> 4) & 0x1) +#define C_000420_OV0_SIGNED_UV 0xFFFFFFEF +#define S_000420_OV0_GAMMA_SEL(x) (((x) & 0x7) << 5) +#define G_000420_OV0_GAMMA_SEL(x) (((x) >> 5) & 0x7) +#define C_000420_OV0_GAMMA_SEL 0xFFFFFF1F +#define S_000420_OV0_SURFACE_FORMAT(x) (((x) & 0xF) << 8) +#define G_000420_OV0_SURFACE_FORMAT(x) (((x) >> 8) & 0xF) +#define C_000420_OV0_SURFACE_FORMAT 0xFFFFF0FF +#define S_000420_OV0_ADAPTIVE_DEINT(x) (((x) & 0x1) << 12) +#define G_000420_OV0_ADAPTIVE_DEINT(x) (((x) >> 12) & 0x1) +#define C_000420_OV0_ADAPTIVE_DEINT 0xFFFFEFFF +#define S_000420_OV0_CRTC_SEL(x) (((x) & 0x1) << 14) +#define G_000420_OV0_CRTC_SEL(x) (((x) >> 14) & 0x1) +#define C_000420_OV0_CRTC_SEL 0xFFFFBFFF +#define S_000420_OV0_BURST_PER_PLANE(x) (((x) & 0x7F) << 16) +#define G_000420_OV0_BURST_PER_PLANE(x) (((x) >> 16) & 0x7F) +#define C_000420_OV0_BURST_PER_PLANE 0xFF80FFFF +#define S_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) & 0x1) << 24) +#define G_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) >> 24) & 0x1) +#define C_000420_OV0_DOUBLE_BUFFER_REGS 0xFEFFFFFF +#define S_000420_OV0_BANDWIDTH(x) (((x) & 0x1) << 26) +#define G_000420_OV0_BANDWIDTH(x) (((x) >> 26) & 0x1) +#define C_000420_OV0_BANDWIDTH 0xFBFFFFFF +#define S_000420_OV0_LIN_TRANS_BYPASS(x) (((x) & 0x1) << 28) +#define G_000420_OV0_LIN_TRANS_BYPASS(x) (((x) >> 28) & 0x1) +#define C_000420_OV0_LIN_TRANS_BYPASS 0xEFFFFFFF +#define S_000420_OV0_INT_EMU(x) (((x) & 0x1) << 29) +#define G_000420_OV0_INT_EMU(x) (((x) >> 29) & 0x1) +#define C_000420_OV0_INT_EMU 0xDFFFFFFF +#define S_000420_OV0_OVERLAY_EN(x) (((x) & 0x1) << 30) +#define G_000420_OV0_OVERLAY_EN(x) (((x) >> 30) & 0x1) +#define C_000420_OV0_OVERLAY_EN 0xBFFFFFFF +#define S_000420_OV0_SOFT_RESET(x) (((x) & 0x1) << 31) +#define G_000420_OV0_SOFT_RESET(x) (((x) >> 31) & 0x1) +#define C_000420_OV0_SOFT_RESET 0x7FFFFFFF +#define R_00070C_CP_RB_RPTR_ADDR 0x00070C +#define S_00070C_RB_RPTR_SWAP(x) (((x) & 0x3) << 0) +#define G_00070C_RB_RPTR_SWAP(x) (((x) >> 0) & 0x3) +#define C_00070C_RB_RPTR_SWAP 0xFFFFFFFC +#define S_00070C_RB_RPTR_ADDR(x) (((x) & 0x3FFFFFFF) << 2) +#define G_00070C_RB_RPTR_ADDR(x) (((x) >> 2) & 0x3FFFFFFF) +#define C_00070C_RB_RPTR_ADDR 0x00000003 +#define R_000740_CP_CSQ_CNTL 0x000740 +#define S_000740_CSQ_CNT_PRIMARY(x) (((x) & 0xFF) << 0) +#define G_000740_CSQ_CNT_PRIMARY(x) (((x) >> 0) & 0xFF) +#define C_000740_CSQ_CNT_PRIMARY 0xFFFFFF00 +#define S_000740_CSQ_CNT_INDIRECT(x) (((x) & 0xFF) << 8) +#define G_000740_CSQ_CNT_INDIRECT(x) (((x) >> 8) & 0xFF) +#define C_000740_CSQ_CNT_INDIRECT 0xFFFF00FF +#define S_000740_CSQ_MODE(x) (((x) & 0xF) << 28) +#define G_000740_CSQ_MODE(x) (((x) >> 28) & 0xF) +#define C_000740_CSQ_MODE 0x0FFFFFFF +#define R_000770_SCRATCH_UMSK 0x000770 +#define S_000770_SCRATCH_UMSK(x) (((x) & 0x3F) << 0) +#define G_000770_SCRATCH_UMSK(x) (((x) >> 0) & 0x3F) +#define C_000770_SCRATCH_UMSK 0xFFFFFFC0 +#define S_000770_SCRATCH_SWAP(x) (((x) & 0x3) << 16) +#define G_000770_SCRATCH_SWAP(x) (((x) >> 16) & 0x3) +#define C_000770_SCRATCH_SWAP 0xFFFCFFFF +#define R_000774_SCRATCH_ADDR 0x000774 +#define S_000774_SCRATCH_ADDR(x) (((x) & 0x7FFFFFF) << 5) +#define G_000774_SCRATCH_ADDR(x) (((x) >> 5) & 0x7FFFFFF) +#define C_000774_SCRATCH_ADDR 0x0000001F +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_SE_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_SE_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_SE_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF + + +#define R_00000D_SCLK_CNTL 0x00000D +#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0) +#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7) +#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8 +#define S_00000D_TCLK_SRC_SEL(x) (((x) & 0x7) << 8) +#define G_00000D_TCLK_SRC_SEL(x) (((x) >> 8) & 0x7) +#define C_00000D_TCLK_SRC_SEL 0xFFFFF8FF +#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16) +#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1) +#define C_00000D_FORCE_CP 0xFFFEFFFF +#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17) +#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1) +#define C_00000D_FORCE_HDP 0xFFFDFFFF +#define S_00000D_FORCE_DISP(x) (((x) & 0x1) << 18) +#define G_00000D_FORCE_DISP(x) (((x) >> 18) & 0x1) +#define C_00000D_FORCE_DISP 0xFFFBFFFF +#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19) +#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1) +#define C_00000D_FORCE_TOP 0xFFF7FFFF +#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20) +#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1) +#define C_00000D_FORCE_E2 0xFFEFFFFF +#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21) +#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1) +#define C_00000D_FORCE_SE 0xFFDFFFFF +#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22) +#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1) +#define C_00000D_FORCE_IDCT 0xFFBFFFFF +#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23) +#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1) +#define C_00000D_FORCE_VIP 0xFF7FFFFF +#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24) +#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1) +#define C_00000D_FORCE_RE 0xFEFFFFFF +#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25) +#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1) +#define C_00000D_FORCE_PB 0xFDFFFFFF +#define S_00000D_FORCE_TAM(x) (((x) & 0x1) << 26) +#define G_00000D_FORCE_TAM(x) (((x) >> 26) & 0x1) +#define C_00000D_FORCE_TAM 0xFBFFFFFF +#define S_00000D_FORCE_TDM(x) (((x) & 0x1) << 27) +#define G_00000D_FORCE_TDM(x) (((x) >> 27) & 0x1) +#define C_00000D_FORCE_TDM 0xF7FFFFFF +#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28) +#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1) +#define C_00000D_FORCE_RB 0xEFFFFFFF + +/* PLL regs */ +#define SCLK_CNTL 0xd +#define FORCE_HDP (1 << 17) +#define CLK_PWRMGT_CNTL 0x14 +#define GLOBAL_PMAN_EN (1 << 10) +#define DISP_PM (1 << 20) +#define PLL_PWRMGT_CNTL 0x15 +#define MPLL_TURNOFF (1 << 0) +#define SPLL_TURNOFF (1 << 1) +#define PPLL_TURNOFF (1 << 2) +#define P2PLL_TURNOFF (1 << 3) +#define TVPLL_TURNOFF (1 << 4) +#define MOBILE_SU (1 << 16) +#define SU_SCLK_USE_BCLK (1 << 17) +#define SCLK_CNTL2 0x1e +#define REDUCED_SPEED_SCLK_MODE (1 << 16) +#define REDUCED_SPEED_SCLK_SEL(x) ((x) << 17) +#define MCLK_MISC 0x1f +#define EN_MCLK_TRISTATE_IN_SUSPEND (1 << 18) +#define SCLK_MORE_CNTL 0x35 +#define REDUCED_SPEED_SCLK_EN (1 << 16) +#define IO_CG_VOLTAGE_DROP (1 << 17) +#define VOLTAGE_DELAY_SEL(x) ((x) << 20) +#define VOLTAGE_DROP_SYNC (1 << 19) + +/* mmreg */ +#define DISP_PWR_MAN 0xd08 +#define DISP_D3_GRPH_RST (1 << 18) +#define DISP_D3_SUBPIC_RST (1 << 19) +#define DISP_D3_OV0_RST (1 << 20) +#define DISP_D1D2_GRPH_RST (1 << 21) +#define DISP_D1D2_SUBPIC_RST (1 << 22) +#define DISP_D1D2_OV0_RST (1 << 23) +#define DISP_DVO_ENABLE_RST (1 << 24) +#define TV_ENABLE_RST (1 << 25) +#define AUTO_PWRUP_EN (1 << 26) + +#endif diff --git a/sys/dev/drm2/radeon/r200.c b/sys/dev/drm2/radeon/r200.c new file mode 100644 index 00000000000..fe8b768046c --- /dev/null +++ b/sys/dev/drm2/radeon/r200.c @@ -0,0 +1,552 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "radeon_asic.h" + +#include "r100d.h" +#include "r200_reg_safe.h" + +#include "r100_track.h" + +static int r200_get_vtx_size_0(uint32_t vtx_fmt_0) +{ + int vtx_size, i; + vtx_size = 2; + + if (vtx_fmt_0 & R200_VTX_Z0) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_W0) + vtx_size++; + /* blend weight */ + if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT)) + vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7; + if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_N0) + vtx_size += 3; + if (vtx_fmt_0 & R200_VTX_POINT_SIZE) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_SHININESS_0) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_SHININESS_1) + vtx_size++; + for (i = 0; i < 8; i++) { + int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3; + switch (color_size) { + case 0: break; + case 1: vtx_size++; break; + case 2: vtx_size += 3; break; + case 3: vtx_size += 4; break; + } + } + if (vtx_fmt_0 & R200_VTX_XY1) + vtx_size += 2; + if (vtx_fmt_0 & R200_VTX_Z1) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_W1) + vtx_size++; + if (vtx_fmt_0 & R200_VTX_N1) + vtx_size += 3; + return vtx_size; +} + +int r200_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t size; + uint32_t cur_size; + int i, num_loops; + int r = 0; + + /* radeon pitch is /64 */ + size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT; + num_loops = DIV_ROUND_UP(size, 0x1FFFFF); + r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + /* Must wait for 2D idle & clean before DMA or hangs might happen */ + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, (1 << 16)); + for (i = 0; i < num_loops; i++) { + cur_size = size; + if (cur_size > 0x1FFFFF) { + cur_size = 0x1FFFFF; + } + size -= cur_size; + radeon_ring_write(ring, PACKET0(0x720, 2)); + radeon_ring_write(ring, src_offset); + radeon_ring_write(ring, dst_offset); + radeon_ring_write(ring, cur_size | (1 << 31) | (1 << 30)); + src_offset += cur_size; + dst_offset += cur_size; + } + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); + if (fence) { + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); + } + radeon_ring_unlock_commit(rdev, ring); + return r; +} + + +static int r200_get_vtx_size_1(uint32_t vtx_fmt_1) +{ + int vtx_size, i, tex_size; + vtx_size = 0; + for (i = 0; i < 6; i++) { + tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7; + if (tex_size > 4) + continue; + vtx_size += tex_size; + } + return vtx_size; +} + +int r200_packet0_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg) +{ + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + volatile uint32_t *ib; + uint32_t tmp; + int r; + int i; + int face; + u32 tile_flags = 0; + u32 idx_value; + + ib = p->ib.ptr; + track = (struct r100_cs_track *)p->track; + idx_value = radeon_get_ib_value(p, idx); + switch (reg) { + case RADEON_CRTC_GUI_TRIG_VLINE: + r = r100_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + break; + /* FIXME: only allow PACKET3 blit? easier to check for out of + * range access */ + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + r = r100_reloc_pitch_offset(p, pkt, idx, reg); + if (r) + return r; + break; + case RADEON_RB3D_DEPTHOFFSET: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->zb.robj = reloc->robj; + track->zb.offset = idx_value; + track->zb_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case RADEON_RB3D_COLOROFFSET: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->cb[0].robj = reloc->robj; + track->cb[0].offset = idx_value; + track->cb_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case R200_PP_TXOFFSET_0: + case R200_PP_TXOFFSET_1: + case R200_PP_TXOFFSET_2: + case R200_PP_TXOFFSET_3: + case R200_PP_TXOFFSET_4: + case R200_PP_TXOFFSET_5: + i = (reg - R200_PP_TXOFFSET_0) / 24; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R200_TXO_MACRO_TILE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R200_TXO_MICRO_TILE; + + tmp = idx_value & ~(0x7 << 2); + tmp |= tile_flags; + ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset); + } else + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[i].robj = reloc->robj; + track->tex_dirty = true; + break; + case R200_PP_CUBIC_OFFSET_F1_0: + case R200_PP_CUBIC_OFFSET_F2_0: + case R200_PP_CUBIC_OFFSET_F3_0: + case R200_PP_CUBIC_OFFSET_F4_0: + case R200_PP_CUBIC_OFFSET_F5_0: + case R200_PP_CUBIC_OFFSET_F1_1: + case R200_PP_CUBIC_OFFSET_F2_1: + case R200_PP_CUBIC_OFFSET_F3_1: + case R200_PP_CUBIC_OFFSET_F4_1: + case R200_PP_CUBIC_OFFSET_F5_1: + case R200_PP_CUBIC_OFFSET_F1_2: + case R200_PP_CUBIC_OFFSET_F2_2: + case R200_PP_CUBIC_OFFSET_F3_2: + case R200_PP_CUBIC_OFFSET_F4_2: + case R200_PP_CUBIC_OFFSET_F5_2: + case R200_PP_CUBIC_OFFSET_F1_3: + case R200_PP_CUBIC_OFFSET_F2_3: + case R200_PP_CUBIC_OFFSET_F3_3: + case R200_PP_CUBIC_OFFSET_F4_3: + case R200_PP_CUBIC_OFFSET_F5_3: + case R200_PP_CUBIC_OFFSET_F1_4: + case R200_PP_CUBIC_OFFSET_F2_4: + case R200_PP_CUBIC_OFFSET_F3_4: + case R200_PP_CUBIC_OFFSET_F4_4: + case R200_PP_CUBIC_OFFSET_F5_4: + case R200_PP_CUBIC_OFFSET_F1_5: + case R200_PP_CUBIC_OFFSET_F2_5: + case R200_PP_CUBIC_OFFSET_F3_5: + case R200_PP_CUBIC_OFFSET_F4_5: + case R200_PP_CUBIC_OFFSET_F5_5: + i = (reg - R200_PP_TXOFFSET_0) / 24; + face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->textures[i].cube_info[face - 1].offset = idx_value; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[i].cube_info[face - 1].robj = reloc->robj; + track->tex_dirty = true; + break; + case RADEON_RE_WIDTH_HEIGHT: + track->maxy = ((idx_value >> 16) & 0x7FF); + track->cb_dirty = true; + track->zb_dirty = true; + break; + case RADEON_RB3D_COLORPITCH: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_COLOR_TILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; + + tmp = idx_value & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + } else + ib[idx] = idx_value; + + track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK; + track->cb_dirty = true; + break; + case RADEON_RB3D_DEPTHPITCH: + track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK; + track->zb_dirty = true; + break; + case RADEON_RB3D_CNTL: + switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { + case 7: + case 8: + case 9: + case 11: + case 12: + track->cb[0].cpp = 1; + break; + case 3: + case 4: + case 15: + track->cb[0].cpp = 2; + break; + case 6: + track->cb[0].cpp = 4; + break; + default: + DRM_ERROR("Invalid color buffer format (%d) !\n", + ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); + return -EINVAL; + } + if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) { + DRM_ERROR("No support for depth xy offset in kms\n"); + return -EINVAL; + } + + track->z_enabled = !!(idx_value & RADEON_Z_ENABLE); + track->cb_dirty = true; + track->zb_dirty = true; + break; + case RADEON_RB3D_ZSTENCILCNTL: + switch (idx_value & 0xf) { + case 0: + track->zb.cpp = 2; + break; + case 2: + case 3: + case 4: + case 5: + case 9: + case 11: + track->zb.cpp = 4; + break; + default: + break; + } + track->zb_dirty = true; + break; + case RADEON_RB3D_ZPASS_ADDR: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case RADEON_PP_CNTL: + { + uint32_t temp = idx_value >> 4; + for (i = 0; i < track->num_texture; i++) + track->textures[i].enabled = !!(temp & (1 << i)); + track->tex_dirty = true; + } + break; + case RADEON_SE_VF_CNTL: + track->vap_vf_cntl = idx_value; + break; + case 0x210c: + /* VAP_VF_MAX_VTX_INDX */ + track->max_indx = idx_value & 0x00FFFFFFUL; + break; + case R200_SE_VTX_FMT_0: + track->vtx_size = r200_get_vtx_size_0(idx_value); + break; + case R200_SE_VTX_FMT_1: + track->vtx_size += r200_get_vtx_size_1(idx_value); + break; + case R200_PP_TXSIZE_0: + case R200_PP_TXSIZE_1: + case R200_PP_TXSIZE_2: + case R200_PP_TXSIZE_3: + case R200_PP_TXSIZE_4: + case R200_PP_TXSIZE_5: + i = (reg - R200_PP_TXSIZE_0) / 32; + track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1; + track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; + track->tex_dirty = true; + break; + case R200_PP_TXPITCH_0: + case R200_PP_TXPITCH_1: + case R200_PP_TXPITCH_2: + case R200_PP_TXPITCH_3: + case R200_PP_TXPITCH_4: + case R200_PP_TXPITCH_5: + i = (reg - R200_PP_TXPITCH_0) / 32; + track->textures[i].pitch = idx_value + 32; + track->tex_dirty = true; + break; + case R200_PP_TXFILTER_0: + case R200_PP_TXFILTER_1: + case R200_PP_TXFILTER_2: + case R200_PP_TXFILTER_3: + case R200_PP_TXFILTER_4: + case R200_PP_TXFILTER_5: + i = (reg - R200_PP_TXFILTER_0) / 32; + track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK) + >> R200_MAX_MIP_LEVEL_SHIFT); + tmp = (idx_value >> 23) & 0x7; + if (tmp == 2 || tmp == 6) + track->textures[i].roundup_w = false; + tmp = (idx_value >> 27) & 0x7; + if (tmp == 2 || tmp == 6) + track->textures[i].roundup_h = false; + track->tex_dirty = true; + break; + case R200_PP_TXMULTI_CTL_0: + case R200_PP_TXMULTI_CTL_1: + case R200_PP_TXMULTI_CTL_2: + case R200_PP_TXMULTI_CTL_3: + case R200_PP_TXMULTI_CTL_4: + case R200_PP_TXMULTI_CTL_5: + i = (reg - R200_PP_TXMULTI_CTL_0) / 32; + break; + case R200_PP_TXFORMAT_X_0: + case R200_PP_TXFORMAT_X_1: + case R200_PP_TXFORMAT_X_2: + case R200_PP_TXFORMAT_X_3: + case R200_PP_TXFORMAT_X_4: + case R200_PP_TXFORMAT_X_5: + i = (reg - R200_PP_TXFORMAT_X_0) / 32; + track->textures[i].txdepth = idx_value & 0x7; + tmp = (idx_value >> 16) & 0x3; + /* 2D, 3D, CUBE */ + switch (tmp) { + case 0: + case 3: + case 4: + case 5: + case 6: + case 7: + /* 1D/2D */ + track->textures[i].tex_coord_type = 0; + break; + case 1: + /* CUBE */ + track->textures[i].tex_coord_type = 2; + break; + case 2: + /* 3D */ + track->textures[i].tex_coord_type = 1; + break; + } + track->tex_dirty = true; + break; + case R200_PP_TXFORMAT_0: + case R200_PP_TXFORMAT_1: + case R200_PP_TXFORMAT_2: + case R200_PP_TXFORMAT_3: + case R200_PP_TXFORMAT_4: + case R200_PP_TXFORMAT_5: + i = (reg - R200_PP_TXFORMAT_0) / 32; + if (idx_value & R200_TXFORMAT_NON_POWER2) { + track->textures[i].use_pitch = 1; + } else { + track->textures[i].use_pitch = 0; + track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); + track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); + } + if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE) + track->textures[i].lookup_disable = true; + switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) { + case R200_TXFORMAT_I8: + case R200_TXFORMAT_RGB332: + case R200_TXFORMAT_Y8: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R200_TXFORMAT_AI88: + case R200_TXFORMAT_ARGB1555: + case R200_TXFORMAT_RGB565: + case R200_TXFORMAT_ARGB4444: + case R200_TXFORMAT_VYUY422: + case R200_TXFORMAT_YVYU422: + case R200_TXFORMAT_LDVDU655: + case R200_TXFORMAT_DVDU88: + case R200_TXFORMAT_AVYU4444: + track->textures[i].cpp = 2; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R200_TXFORMAT_ARGB8888: + case R200_TXFORMAT_RGBA8888: + case R200_TXFORMAT_ABGR8888: + case R200_TXFORMAT_BGR111110: + case R200_TXFORMAT_LDVDU8888: + track->textures[i].cpp = 4; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R200_TXFORMAT_DXT1: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; + case R200_TXFORMAT_DXT23: + case R200_TXFORMAT_DXT45: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; + } + track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf); + track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf); + track->tex_dirty = true; + break; + case R200_PP_CUBIC_FACES_0: + case R200_PP_CUBIC_FACES_1: + case R200_PP_CUBIC_FACES_2: + case R200_PP_CUBIC_FACES_3: + case R200_PP_CUBIC_FACES_4: + case R200_PP_CUBIC_FACES_5: + tmp = idx_value; + i = (reg - R200_PP_CUBIC_FACES_0) / 32; + for (face = 0; face < 4; face++) { + track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); + track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf); + } + track->tex_dirty = true; + break; + default: + DRM_ERROR("Forbidden register 0x%04X in cs at %d\n", + reg, idx); + return -EINVAL; + } + return 0; +} + +void r200_set_safe_registers(struct radeon_device *rdev) +{ + rdev->config.r100.reg_safe_bm = r200_reg_safe_bm; + rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r200_reg_safe_bm); +} diff --git a/sys/dev/drm2/radeon/r200_reg_safe.h b/sys/dev/drm2/radeon/r200_reg_safe.h new file mode 100644 index 00000000000..3ef5980f147 --- /dev/null +++ b/sys/dev/drm2/radeon/r200_reg_safe.h @@ -0,0 +1,31 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned r200_reg_safe_bm[102] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFE7FE1F, 0xF003FFFF, 0x7EFFFFFF, 0xFFFF803C, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFEFCE, 0xFFFEFFFF, 0xFFFFFFFE, + 0x020E0FF0, 0xFFCC83FD, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFBFFFF, 0xEFFCFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xDFDFDFDF, 0x3FFDDFDF, 0xFFFFFFFF, 0xFFFFFF7F, + 0xFFFFFFFF, 0x00FFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFE3F, 0xFFFFFFEF, +}; diff --git a/sys/dev/drm2/radeon/r300.c b/sys/dev/drm2/radeon/r300.c new file mode 100644 index 00000000000..b8fdefc3365 --- /dev/null +++ b/sys/dev/drm2/radeon/r300.c @@ -0,0 +1,1566 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "radeon_asic.h" +#include +#include "r100_track.h" +#include "r300d.h" +#include "rv350d.h" +#include "r300_reg_safe.h" + +/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 + * + * GPU Errata: + * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL + * using MMIO to flush host path read cache, this lead to HARDLOCKUP. + * However, scheduling such write to the ring seems harmless, i suspect + * the CP read collide with the flush somehow, or maybe the MC, hard to + * tell. (Jerome Glisse) + */ + +/* + * rv370,rv380 PCIE GART + */ +static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev); + +void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) +{ + uint32_t tmp; + int i; + + /* Workaround HW bug do flush 2 times */ + for (i = 0; i < 2; i++) { + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); + WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB); + (void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); + WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); + } + mb(); +} + +#define R300_PTE_WRITEABLE (1 << 2) +#define R300_PTE_READABLE (1 << 3) + +int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +{ + volatile uint32_t *ptr = rdev->gart.ptr; + + if (i < 0 || i > rdev->gart.num_gpu_pages) { + return -EINVAL; + } + addr = (lower_32_bits(addr) >> 8) | + ((upper_32_bits(addr) & 0xff) << 24) | + R300_PTE_WRITEABLE | R300_PTE_READABLE; + /* on x86 we want this to be CPU endian, on powerpc + * on powerpc without HW swappers, it'll get swapped on way + * into VRAM - so no need for cpu_to_le32 on VRAM tables */ + ptr += i; + *ptr = (uint32_t)addr; + return 0; +} + +int rv370_pcie_gart_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.robj) { + DRM_ERROR("RV370 PCIE GART already initialized\n"); + return 0; + } + /* Initialize common gart structure */ + r = radeon_gart_init(rdev); + if (r) + return r; + r = rv370_debugfs_pcie_gart_info_init(rdev); + if (r) + DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; + rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; + rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; + return radeon_gart_table_vram_alloc(rdev); +} + +int rv370_pcie_gart_enable(struct radeon_device *rdev) +{ + uint32_t table_addr; + uint32_t tmp; + int r; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + /* discard memory request outside of configured range */ + tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; + WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); + WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start); + tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK; + WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp); + WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); + WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); + table_addr = rdev->gart.table_addr; + WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr); + /* FIXME: setup default page */ + WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start); + WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); + /* Clear error */ + WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); + tmp |= RADEON_PCIE_TX_GART_EN; + tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; + WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); + rv370_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)table_addr); + rdev->gart.ready = true; + return 0; +} + +void rv370_pcie_gart_disable(struct radeon_device *rdev) +{ + u32 tmp; + + WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0); + WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0); + WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); + WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); + tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; + WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); + radeon_gart_table_vram_unpin(rdev); +} + +void rv370_pcie_gart_fini(struct radeon_device *rdev) +{ + radeon_gart_fini(rdev); + rv370_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); +} + +void r300_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + + /* Who ever call radeon_fence_emit should call ring_lock and ask + * for enough space (today caller are ib schedule and buffer move) */ + /* Write SC register so SC & US assert idle */ + radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_TL, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_BR, 0)); + radeon_ring_write(ring, 0); + /* Flush 3D cache */ + radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_RB3D_DC_FLUSH); + radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_ZC_FLUSH); + /* Wait until IDLE & CLEAN */ + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, (RADEON_WAIT_3D_IDLECLEAN | + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_DMA_GUI_IDLE)); + radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(ring, rdev->config.r300.hdp_cntl | + RADEON_HDP_READ_BUFFER_INVALIDATE); + radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(ring, rdev->config.r300.hdp_cntl); + /* Emit fence sequence & fire IRQ */ + radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); + radeon_ring_write(ring, fence->seq); + radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); + radeon_ring_write(ring, RADEON_SW_INT_FIRE); +} + +void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) +{ + unsigned gb_tile_config; + int r; + + /* Sub pixel 1/12 so we can have 4K rendering according to doc */ + gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); + switch(rdev->num_gb_pipes) { + case 2: + gb_tile_config |= R300_PIPE_COUNT_R300; + break; + case 3: + gb_tile_config |= R300_PIPE_COUNT_R420_3P; + break; + case 4: + gb_tile_config |= R300_PIPE_COUNT_R420; + break; + case 1: + default: + gb_tile_config |= R300_PIPE_COUNT_RV350; + break; + } + + r = radeon_ring_lock(rdev, ring, 64); + if (r) { + return; + } + radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); + radeon_ring_write(ring, + RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI); + radeon_ring_write(ring, PACKET0(R300_GB_TILE_CONFIG, 0)); + radeon_ring_write(ring, gb_tile_config); + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_3D_IDLECLEAN); + radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0)); + radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG); + radeon_ring_write(ring, PACKET0(R300_GB_SELECT, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(R300_GB_ENABLE, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); + radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); + radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(ring, + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_3D_IDLECLEAN); + radeon_ring_write(ring, PACKET0(R300_GB_AA_CONFIG, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); + radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); + radeon_ring_write(ring, PACKET0(R300_GB_MSPOS0, 0)); + radeon_ring_write(ring, + ((6 << R300_MS_X0_SHIFT) | + (6 << R300_MS_Y0_SHIFT) | + (6 << R300_MS_X1_SHIFT) | + (6 << R300_MS_Y1_SHIFT) | + (6 << R300_MS_X2_SHIFT) | + (6 << R300_MS_Y2_SHIFT) | + (6 << R300_MSBD0_Y_SHIFT) | + (6 << R300_MSBD0_X_SHIFT))); + radeon_ring_write(ring, PACKET0(R300_GB_MSPOS1, 0)); + radeon_ring_write(ring, + ((6 << R300_MS_X3_SHIFT) | + (6 << R300_MS_Y3_SHIFT) | + (6 << R300_MS_X4_SHIFT) | + (6 << R300_MS_Y4_SHIFT) | + (6 << R300_MS_X5_SHIFT) | + (6 << R300_MS_Y5_SHIFT) | + (6 << R300_MSBD1_SHIFT))); + radeon_ring_write(ring, PACKET0(R300_GA_ENHANCE, 0)); + radeon_ring_write(ring, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); + radeon_ring_write(ring, PACKET0(R300_GA_POLY_MODE, 0)); + radeon_ring_write(ring, + R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); + radeon_ring_write(ring, PACKET0(R300_GA_ROUND_MODE, 0)); + radeon_ring_write(ring, + R300_GEOMETRY_ROUND_NEAREST | + R300_COLOR_ROUND_NEAREST); + radeon_ring_unlock_commit(rdev, ring); +} + +static void r300_errata(struct radeon_device *rdev) +{ + rdev->pll_errata = 0; + + if (rdev->family == CHIP_R300 && + (RREG32(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) { + rdev->pll_errata |= CHIP_ERRATA_R300_CG; + } +} + +int r300_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & R300_MC_IDLE) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +static void r300_gpu_init(struct radeon_device *rdev) +{ + uint32_t gb_tile_config, tmp; + + if ((rdev->family == CHIP_R300 && rdev->ddev->pci_device != 0x4144) || + (rdev->family == CHIP_R350 && rdev->ddev->pci_device != 0x4148)) { + /* r300,r350 */ + rdev->num_gb_pipes = 2; + } else { + /* rv350,rv370,rv380,r300 AD, r350 AH */ + rdev->num_gb_pipes = 1; + } + rdev->num_z_pipes = 1; + gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); + switch (rdev->num_gb_pipes) { + case 2: + gb_tile_config |= R300_PIPE_COUNT_R300; + break; + case 3: + gb_tile_config |= R300_PIPE_COUNT_R420_3P; + break; + case 4: + gb_tile_config |= R300_PIPE_COUNT_R420; + break; + default: + case 1: + gb_tile_config |= R300_PIPE_COUNT_RV350; + break; + } + WREG32(R300_GB_TILE_CONFIG, gb_tile_config); + + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } + + tmp = RREG32(R300_DST_PIPE_CONFIG); + WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); + + WREG32(R300_RB2D_DSTCACHE_MODE, + R300_DC_AUTOFLUSH_ENABLE | + R300_DC_DC_DISABLE_IGNORE_PE); + + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } + if (r300_mc_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait MC idle while " + "programming pipes. Bad things might happen.\n"); + } + DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n", + rdev->num_gb_pipes, rdev->num_z_pipes); +} + +int r300_asic_reset(struct radeon_device *rdev) +{ + struct r100_mc_save save; + u32 status, tmp; + int ret = 0; + + status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(status)) { + return 0; + } + r100_mc_stop(rdev, &save); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* stop CP */ + WREG32(RADEON_CP_CSQ_CNTL, 0); + tmp = RREG32(RADEON_CP_RB_CNTL); + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); + WREG32(RADEON_CP_RB_RPTR_WR, 0); + WREG32(RADEON_CP_RB_WPTR, 0); + WREG32(RADEON_CP_RB_CNTL, tmp); + /* save PCI state */ + pci_save_state(rdev->dev); + /* disable bus mastering */ + r100_bm_disable(rdev); + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | + S_0000F0_SOFT_RESET_GA(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* resetting the CP seems to be problematic sometimes it end up + * hard locking the computer, but it's necessary for successful + * reset more test & playing is needed on R3XX/R4XX to find a + * reliable (if any solution) + */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* restore PCI & busmastering */ + pci_restore_state(rdev->dev); + r100_enable_bm(rdev); + /* Check if GPU is idle */ + if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { + dev_err(rdev->dev, "failed to reset GPU\n"); + ret = -1; + } else + dev_info(rdev->dev, "GPU reset succeed\n"); + r100_mc_resume(rdev, &save); + return ret; +} + +/* + * r300,r350,rv350,rv380 VRAM info + */ +void r300_mc_init(struct radeon_device *rdev) +{ + u64 base; + u32 tmp; + + /* DDR for all card after R300 & IGP */ + rdev->mc.vram_is_ddr = true; + tmp = RREG32(RADEON_MEM_CNTL); + tmp &= R300_MEM_NUM_CHANNELS_MASK; + switch (tmp) { + case 0: rdev->mc.vram_width = 64; break; + case 1: rdev->mc.vram_width = 128; break; + case 2: rdev->mc.vram_width = 256; break; + default: rdev->mc.vram_width = 128; break; + } + r100_vram_init_sizes(rdev); + base = rdev->mc.aper_base; + if (rdev->flags & RADEON_IS_IGP) + base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = 0; + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + +void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes) +{ + uint32_t link_width_cntl, mask; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + /* FIXME wait for idle */ + + switch (lanes) { + case 0: + mask = RADEON_PCIE_LC_LINK_WIDTH_X0; + break; + case 1: + mask = RADEON_PCIE_LC_LINK_WIDTH_X1; + break; + case 2: + mask = RADEON_PCIE_LC_LINK_WIDTH_X2; + break; + case 4: + mask = RADEON_PCIE_LC_LINK_WIDTH_X4; + break; + case 8: + mask = RADEON_PCIE_LC_LINK_WIDTH_X8; + break; + case 12: + mask = RADEON_PCIE_LC_LINK_WIDTH_X12; + break; + case 16: + default: + mask = RADEON_PCIE_LC_LINK_WIDTH_X16; + break; + } + + link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + + if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) == + (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT)) + return; + + link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK | + RADEON_PCIE_LC_RECONFIG_NOW | + RADEON_PCIE_LC_RECONFIG_LATER | + RADEON_PCIE_LC_SHORT_RECONFIG_EN); + link_width_cntl |= mask; + WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl | + RADEON_PCIE_LC_RECONFIG_NOW)); + + /* wait for lane set to complete */ + link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + while (link_width_cntl == 0xffffffff) + link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + +} + +int rv370_get_pcie_lanes(struct radeon_device *rdev) +{ + u32 link_width_cntl; + + if (rdev->flags & RADEON_IS_IGP) + return 0; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return 0; + + /* FIXME wait for idle */ + + link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + + switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { + case RADEON_PCIE_LC_LINK_WIDTH_X0: + return 0; + case RADEON_PCIE_LC_LINK_WIDTH_X1: + return 1; + case RADEON_PCIE_LC_LINK_WIDTH_X2: + return 2; + case RADEON_PCIE_LC_LINK_WIDTH_X4: + return 4; + case RADEON_PCIE_LC_LINK_WIDTH_X8: + return 8; + case RADEON_PCIE_LC_LINK_WIDTH_X16: + default: + return 16; + } +} + +#if defined(CONFIG_DEBUG_FS) +static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); + seq_printf(m, "PCIE_TX_GART_CNTL 0x%08x\n", tmp); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_BASE); + seq_printf(m, "PCIE_TX_GART_BASE 0x%08x\n", tmp); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_LO); + seq_printf(m, "PCIE_TX_GART_START_LO 0x%08x\n", tmp); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_HI); + seq_printf(m, "PCIE_TX_GART_START_HI 0x%08x\n", tmp); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_LO); + seq_printf(m, "PCIE_TX_GART_END_LO 0x%08x\n", tmp); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_HI); + seq_printf(m, "PCIE_TX_GART_END_HI 0x%08x\n", tmp); + tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_ERROR); + seq_printf(m, "PCIE_TX_GART_ERROR 0x%08x\n", tmp); + return 0; +} + +static struct drm_info_list rv370_pcie_gart_info_list[] = { + {"rv370_pcie_gart_info", rv370_debugfs_pcie_gart_info, 0, NULL}, +}; +#endif + +static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1); +#else + return 0; +#endif +} + +static int r300_packet0_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg) +{ + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + volatile uint32_t *ib; + uint32_t tmp, tile_flags = 0; + unsigned i; + int r; + u32 idx_value; + + ib = p->ib.ptr; + track = (struct r100_cs_track *)p->track; + idx_value = radeon_get_ib_value(p, idx); + + switch(reg) { + case AVIVO_D1MODE_VLINE_START_END: + case RADEON_CRTC_GUI_TRIG_VLINE: + r = r100_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + break; + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + r = r100_reloc_pitch_offset(p, pkt, idx, reg); + if (r) + return r; + break; + case R300_RB3D_COLOROFFSET0: + case R300_RB3D_COLOROFFSET1: + case R300_RB3D_COLOROFFSET2: + case R300_RB3D_COLOROFFSET3: + i = (reg - R300_RB3D_COLOROFFSET0) >> 2; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->cb[i].robj = reloc->robj; + track->cb[i].offset = idx_value; + track->cb_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case R300_ZB_DEPTHOFFSET: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->zb.robj = reloc->robj; + track->zb.offset = idx_value; + track->zb_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case R300_TX_OFFSET_0: + case R300_TX_OFFSET_0+4: + case R300_TX_OFFSET_0+8: + case R300_TX_OFFSET_0+12: + case R300_TX_OFFSET_0+16: + case R300_TX_OFFSET_0+20: + case R300_TX_OFFSET_0+24: + case R300_TX_OFFSET_0+28: + case R300_TX_OFFSET_0+32: + case R300_TX_OFFSET_0+36: + case R300_TX_OFFSET_0+40: + case R300_TX_OFFSET_0+44: + case R300_TX_OFFSET_0+48: + case R300_TX_OFFSET_0+52: + case R300_TX_OFFSET_0+56: + case R300_TX_OFFSET_0+60: + i = (reg - R300_TX_OFFSET_0) >> 2; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + + if (p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) { + ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */ + ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset); + } else { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_TXO_MACRO_TILE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_TXO_MICRO_TILE; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_TXO_MICRO_TILE_SQUARE; + + tmp = idx_value + ((u32)reloc->lobj.gpu_offset); + tmp |= tile_flags; + ib[idx] = tmp; + } + track->textures[i].robj = reloc->robj; + track->tex_dirty = true; + break; + /* Tracked registers */ + case 0x2084: + /* VAP_VF_CNTL */ + track->vap_vf_cntl = idx_value; + break; + case 0x20B4: + /* VAP_VTX_SIZE */ + track->vtx_size = idx_value & 0x7F; + break; + case 0x2134: + /* VAP_VF_MAX_VTX_INDX */ + track->max_indx = idx_value & 0x00FFFFFFUL; + break; + case 0x2088: + /* VAP_ALT_NUM_VERTICES - only valid on r500 */ + if (p->rdev->family < CHIP_RV515) + goto fail; + track->vap_alt_nverts = idx_value & 0xFFFFFF; + break; + case 0x43E4: + /* SC_SCISSOR1 */ + track->maxy = ((idx_value >> 13) & 0x1FFF) + 1; + if (p->rdev->family < CHIP_RV515) { + track->maxy -= 1440; + } + track->cb_dirty = true; + track->zb_dirty = true; + break; + case 0x4E00: + /* RB3D_CCTL */ + if ((idx_value & (1 << 10)) && /* CMASK_ENABLE */ + p->rdev->cmask_filp != p->filp) { + DRM_ERROR("Invalid RB3D_CCTL: Cannot enable CMASK.\n"); + return -EINVAL; + } + track->num_cb = ((idx_value >> 5) & 0x3) + 1; + track->cb_dirty = true; + break; + case 0x4E38: + case 0x4E3C: + case 0x4E40: + case 0x4E44: + /* RB3D_COLORPITCH0 */ + /* RB3D_COLORPITCH1 */ + /* RB3D_COLORPITCH2 */ + /* RB3D_COLORPITCH3 */ + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_COLOR_TILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_COLOR_MICROTILE_ENABLE; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; + + tmp = idx_value & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + } + i = (reg - 0x4E38) >> 2; + track->cb[i].pitch = idx_value & 0x3FFE; + switch (((idx_value >> 21) & 0xF)) { + case 9: + case 11: + case 12: + track->cb[i].cpp = 1; + break; + case 3: + case 4: + case 13: + case 15: + track->cb[i].cpp = 2; + break; + case 5: + if (p->rdev->family < CHIP_RV515) { + DRM_ERROR("Invalid color buffer format (%d)!\n", + ((idx_value >> 21) & 0xF)); + return -EINVAL; + } + /* Pass through. */ + case 6: + track->cb[i].cpp = 4; + break; + case 10: + track->cb[i].cpp = 8; + break; + case 7: + track->cb[i].cpp = 16; + break; + default: + DRM_ERROR("Invalid color buffer format (%d) !\n", + ((idx_value >> 21) & 0xF)); + return -EINVAL; + } + track->cb_dirty = true; + break; + case 0x4F00: + /* ZB_CNTL */ + if (idx_value & 2) { + track->z_enabled = true; + } else { + track->z_enabled = false; + } + track->zb_dirty = true; + break; + case 0x4F10: + /* ZB_FORMAT */ + switch ((idx_value & 0xF)) { + case 0: + case 1: + track->zb.cpp = 2; + break; + case 2: + track->zb.cpp = 4; + break; + default: + DRM_ERROR("Invalid z buffer format (%d) !\n", + (idx_value & 0xF)); + return -EINVAL; + } + track->zb_dirty = true; + break; + case 0x4F24: + /* ZB_DEPTHPITCH */ + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_DEPTHMACROTILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_DEPTHMICROTILE_TILED; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; + + tmp = idx_value & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + } + track->zb.pitch = idx_value & 0x3FFC; + track->zb_dirty = true; + break; + case 0x4104: + /* TX_ENABLE */ + for (i = 0; i < 16; i++) { + bool enabled; + + enabled = !!(idx_value & (1 << i)); + track->textures[i].enabled = enabled; + } + track->tex_dirty = true; + break; + case 0x44C0: + case 0x44C4: + case 0x44C8: + case 0x44CC: + case 0x44D0: + case 0x44D4: + case 0x44D8: + case 0x44DC: + case 0x44E0: + case 0x44E4: + case 0x44E8: + case 0x44EC: + case 0x44F0: + case 0x44F4: + case 0x44F8: + case 0x44FC: + /* TX_FORMAT1_[0-15] */ + i = (reg - 0x44C0) >> 2; + tmp = (idx_value >> 25) & 0x3; + track->textures[i].tex_coord_type = tmp; + switch ((idx_value & 0x1F)) { + case R300_TX_FORMAT_X8: + case R300_TX_FORMAT_Y4X4: + case R300_TX_FORMAT_Z3Y3X2: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R300_TX_FORMAT_X16: + case R300_TX_FORMAT_FL_I16: + case R300_TX_FORMAT_Y8X8: + case R300_TX_FORMAT_Z5Y6X5: + case R300_TX_FORMAT_Z6Y5X5: + case R300_TX_FORMAT_W4Z4Y4X4: + case R300_TX_FORMAT_W1Z5Y5X5: + case R300_TX_FORMAT_D3DMFT_CxV8U8: + case R300_TX_FORMAT_B8G8_B8G8: + case R300_TX_FORMAT_G8R8_G8B8: + track->textures[i].cpp = 2; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R300_TX_FORMAT_Y16X16: + case R300_TX_FORMAT_FL_I16A16: + case R300_TX_FORMAT_Z11Y11X10: + case R300_TX_FORMAT_Z10Y11X11: + case R300_TX_FORMAT_W8Z8Y8X8: + case R300_TX_FORMAT_W2Z10Y10X10: + case 0x17: + case R300_TX_FORMAT_FL_I32: + case 0x1e: + track->textures[i].cpp = 4; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R300_TX_FORMAT_W16Z16Y16X16: + case R300_TX_FORMAT_FL_R16G16B16A16: + case R300_TX_FORMAT_FL_I32A32: + track->textures[i].cpp = 8; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R300_TX_FORMAT_FL_R32G32B32A32: + track->textures[i].cpp = 16; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + break; + case R300_TX_FORMAT_DXT1: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; + case R300_TX_FORMAT_ATI2N: + if (p->rdev->family < CHIP_R420) { + DRM_ERROR("Invalid texture format %u\n", + (idx_value & 0x1F)); + return -EINVAL; + } + /* The same rules apply as for DXT3/5. */ + /* Pass through. */ + case R300_TX_FORMAT_DXT3: + case R300_TX_FORMAT_DXT5: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT35; + break; + default: + DRM_ERROR("Invalid texture format %u\n", + (idx_value & 0x1F)); + return -EINVAL; + } + track->tex_dirty = true; + break; + case 0x4400: + case 0x4404: + case 0x4408: + case 0x440C: + case 0x4410: + case 0x4414: + case 0x4418: + case 0x441C: + case 0x4420: + case 0x4424: + case 0x4428: + case 0x442C: + case 0x4430: + case 0x4434: + case 0x4438: + case 0x443C: + /* TX_FILTER0_[0-15] */ + i = (reg - 0x4400) >> 2; + tmp = idx_value & 0x7; + if (tmp == 2 || tmp == 4 || tmp == 6) { + track->textures[i].roundup_w = false; + } + tmp = (idx_value >> 3) & 0x7; + if (tmp == 2 || tmp == 4 || tmp == 6) { + track->textures[i].roundup_h = false; + } + track->tex_dirty = true; + break; + case 0x4500: + case 0x4504: + case 0x4508: + case 0x450C: + case 0x4510: + case 0x4514: + case 0x4518: + case 0x451C: + case 0x4520: + case 0x4524: + case 0x4528: + case 0x452C: + case 0x4530: + case 0x4534: + case 0x4538: + case 0x453C: + /* TX_FORMAT2_[0-15] */ + i = (reg - 0x4500) >> 2; + tmp = idx_value & 0x3FFF; + track->textures[i].pitch = tmp + 1; + if (p->rdev->family >= CHIP_RV515) { + tmp = ((idx_value >> 15) & 1) << 11; + track->textures[i].width_11 = tmp; + tmp = ((idx_value >> 16) & 1) << 11; + track->textures[i].height_11 = tmp; + + /* ATI1N */ + if (idx_value & (1 << 14)) { + /* The same rules apply as for DXT1. */ + track->textures[i].compress_format = + R100_TRACK_COMP_DXT1; + } + } else if (idx_value & (1 << 14)) { + DRM_ERROR("Forbidden bit TXFORMAT_MSB\n"); + return -EINVAL; + } + track->tex_dirty = true; + break; + case 0x4480: + case 0x4484: + case 0x4488: + case 0x448C: + case 0x4490: + case 0x4494: + case 0x4498: + case 0x449C: + case 0x44A0: + case 0x44A4: + case 0x44A8: + case 0x44AC: + case 0x44B0: + case 0x44B4: + case 0x44B8: + case 0x44BC: + /* TX_FORMAT0_[0-15] */ + i = (reg - 0x4480) >> 2; + tmp = idx_value & 0x7FF; + track->textures[i].width = tmp + 1; + tmp = (idx_value >> 11) & 0x7FF; + track->textures[i].height = tmp + 1; + tmp = (idx_value >> 26) & 0xF; + track->textures[i].num_levels = tmp; + tmp = idx_value & (1 << 31); + track->textures[i].use_pitch = !!tmp; + tmp = (idx_value >> 22) & 0xF; + track->textures[i].txdepth = tmp; + track->tex_dirty = true; + break; + case R300_ZB_ZPASS_ADDR: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case 0x4e0c: + /* RB3D_COLOR_CHANNEL_MASK */ + track->color_channel_mask = idx_value; + track->cb_dirty = true; + break; + case 0x43a4: + /* SC_HYPERZ_EN */ + /* r300c emits this register - we need to disable hyperz for it + * without complaining */ + if (p->rdev->hyperz_filp != p->filp) { + if (idx_value & 0x1) + ib[idx] = idx_value & ~1; + } + break; + case 0x4f1c: + /* ZB_BW_CNTL */ + track->zb_cb_clear = !!(idx_value & (1 << 5)); + track->cb_dirty = true; + track->zb_dirty = true; + if (p->rdev->hyperz_filp != p->filp) { + if (idx_value & (R300_HIZ_ENABLE | + R300_RD_COMP_ENABLE | + R300_WR_COMP_ENABLE | + R300_FAST_FILL_ENABLE)) + goto fail; + } + break; + case 0x4e04: + /* RB3D_BLENDCNTL */ + track->blend_read_enable = !!(idx_value & (1 << 2)); + track->cb_dirty = true; + break; + case R300_RB3D_AARESOLVE_OFFSET: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + track->aa.robj = reloc->robj; + track->aa.offset = idx_value; + track->aa_dirty = true; + ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + break; + case R300_RB3D_AARESOLVE_PITCH: + track->aa.pitch = idx_value & 0x3FFE; + track->aa_dirty = true; + break; + case R300_RB3D_AARESOLVE_CTL: + track->aaresolve = idx_value & 0x1; + track->aa_dirty = true; + break; + case 0x4f30: /* ZB_MASK_OFFSET */ + case 0x4f34: /* ZB_ZMASK_PITCH */ + case 0x4f44: /* ZB_HIZ_OFFSET */ + case 0x4f54: /* ZB_HIZ_PITCH */ + if (idx_value && (p->rdev->hyperz_filp != p->filp)) + goto fail; + break; + case 0x4028: + if (idx_value && (p->rdev->hyperz_filp != p->filp)) + goto fail; + /* GB_Z_PEQ_CONFIG */ + if (p->rdev->family >= CHIP_RV350) + break; + goto fail; + break; + case 0x4be8: + /* valid register only on RV530 */ + if (p->rdev->family == CHIP_RV530) + break; + /* fallthrough do not move */ + default: + goto fail; + } + return 0; +fail: + DRM_ERROR("Forbidden register 0x%04X in cs at %d (val=%08x)\n", + reg, idx, idx_value); + return -EINVAL; +} + +static int r300_packet3_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + volatile uint32_t *ib; + unsigned idx; + int r; + + ib = p->ib.ptr; + idx = pkt->idx + 1; + track = (struct r100_cs_track *)p->track; + switch(pkt->opcode) { + case PACKET3_3D_LOAD_VBPNTR: + r = r100_packet3_load_vbpntr(p, pkt, idx); + if (r) + return r; + break; + case PACKET3_INDX_BUFFER: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); + r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); + if (r) { + return r; + } + break; + /* Draw packet */ + case PACKET3_3D_DRAW_IMMD: + /* Number of dwords is vtx_size * (num_vertices - 1) + * PRIM_WALK must be equal to 3 vertex data in embedded + * in cmd stream */ + if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) { + DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); + return -EINVAL; + } + track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); + track->immd_dwords = pkt->count - 1; + r = r100_cs_track_check(p->rdev, track); + if (r) { + return r; + } + break; + case PACKET3_3D_DRAW_IMMD_2: + /* Number of dwords is vtx_size * (num_vertices - 1) + * PRIM_WALK must be equal to 3 vertex data in embedded + * in cmd stream */ + if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) { + DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); + return -EINVAL; + } + track->vap_vf_cntl = radeon_get_ib_value(p, idx); + track->immd_dwords = pkt->count; + r = r100_cs_track_check(p->rdev, track); + if (r) { + return r; + } + break; + case PACKET3_3D_DRAW_VBUF: + track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); + r = r100_cs_track_check(p->rdev, track); + if (r) { + return r; + } + break; + case PACKET3_3D_DRAW_VBUF_2: + track->vap_vf_cntl = radeon_get_ib_value(p, idx); + r = r100_cs_track_check(p->rdev, track); + if (r) { + return r; + } + break; + case PACKET3_3D_DRAW_INDX: + track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); + r = r100_cs_track_check(p->rdev, track); + if (r) { + return r; + } + break; + case PACKET3_3D_DRAW_INDX_2: + track->vap_vf_cntl = radeon_get_ib_value(p, idx); + r = r100_cs_track_check(p->rdev, track); + if (r) { + return r; + } + break; + case PACKET3_3D_CLEAR_HIZ: + case PACKET3_3D_CLEAR_ZMASK: + if (p->rdev->hyperz_filp != p->filp) + return -EINVAL; + break; + case PACKET3_3D_CLEAR_CMASK: + if (p->rdev->cmask_filp != p->filp) + return -EINVAL; + break; + case PACKET3_NOP: + break; + default: + DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +int r300_cs_parse(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet pkt; + struct r100_cs_track *track; + int r; + + track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (track == NULL) + return -ENOMEM; + r100_cs_track_clear(p->rdev, track); + p->track = track; + do { + r = r100_cs_packet_parse(p, &pkt, p->idx); + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + p->idx += pkt.count + 2; + switch (pkt.type) { + case PACKET_TYPE0: + r = r100_cs_parse_packet0(p, &pkt, + p->rdev->config.r300.reg_safe_bm, + p->rdev->config.r300.reg_safe_bm_size, + &r300_packet0_check); + break; + case PACKET_TYPE2: + break; + case PACKET_TYPE3: + r = r300_packet3_check(p, &pkt); + break; + default: + DRM_ERROR("Unknown packet type %d !\n", pkt.type); + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return -EINVAL; + } + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return 0; +} + +void r300_set_reg_safe(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = r300_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(r300_reg_safe_bm); +} + +void r300_mc_program(struct radeon_device *rdev) +{ + struct r100_mc_save save; + int r; + + r = r100_debugfs_mc_info_init(rdev); + if (r) { + dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n"); + } + + /* Stops all mc clients */ + r100_mc_stop(rdev, &save); + if (rdev->flags & RADEON_IS_AGP) { + WREG32(R_00014C_MC_AGP_LOCATION, + S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | + S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); + WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); + WREG32(R_00015C_AGP_BASE_2, + upper_32_bits(rdev->mc.agp_base) & 0xff); + } else { + WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); + WREG32(R_000170_AGP_BASE, 0); + WREG32(R_00015C_AGP_BASE_2, 0); + } + /* Wait for mc idle */ + if (r300_mc_wait_for_idle(rdev)) + DRM_INFO("Failed to wait MC idle before programming MC.\n"); + /* Program MC, should be a 32bits limited address space */ + WREG32(R_000148_MC_FB_LOCATION, + S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); + r100_mc_resume(rdev, &save); +} + +void r300_clock_startup(struct radeon_device *rdev) +{ + u32 tmp; + + if (radeon_dynclks != -1 && radeon_dynclks) + radeon_legacy_set_clock_gating(rdev, 1); + /* We need to force on some of the block */ + tmp = RREG32_PLL(R_00000D_SCLK_CNTL); + tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); + if ((rdev->family == CHIP_RV350) || (rdev->family == CHIP_RV380)) + tmp |= S_00000D_FORCE_VAP(1); + WREG32_PLL(R_00000D_SCLK_CNTL, tmp); +} + +static int r300_startup(struct radeon_device *rdev) +{ + int r; + + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ + r300_mc_program(rdev); + /* Resume clock */ + r300_clock_startup(rdev); + /* Initialize GPU configuration (# pipes, ...) */ + r300_gpu_init(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_enable(rdev); + if (r) + return r; + } + + if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350 || + rdev->family == CHIP_RV350) + r100_enable_bm(rdev); + + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_enable(rdev); + if (r) + return r; + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r100_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int r300_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); + /* Resume clock before doing reset */ + r300_clock_startup(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + radeon_combios_asic_init(rdev->ddev); + /* Resume clock after posting */ + r300_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = r300_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int r300_suspend(struct radeon_device *rdev) +{ + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); + return 0; +} + +void r300_fini(struct radeon_device *rdev) +{ + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +int r300_init(struct radeon_device *rdev) +{ + int r; + + /* Disable VGA */ + r100_vga_render_disable(rdev); + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* TODO: disable VGA need to use VGA request */ + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); + return -EINVAL; + } else { + r = radeon_combios_init(rdev); + if (r) + return r; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Set asic errata */ + r300_errata(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) { + radeon_agp_disable(rdev); + } + } + /* initialize memory controller */ + r300_mc_init(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_init(rdev); + if (r) + return r; + } + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_init(rdev); + if (r) + return r; + } + r300_set_reg_safe(rdev); + + rdev->accel_working = true; + r = r300_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); + rdev->accel_working = false; + } + return 0; +} diff --git a/sys/dev/drm2/radeon/r300_cmdbuf.c b/sys/dev/drm2/radeon/r300_cmdbuf.c new file mode 100644 index 00000000000..4f41b13a27b --- /dev/null +++ b/sys/dev/drm2/radeon/r300_cmdbuf.c @@ -0,0 +1,1185 @@ +/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. + * Copyright (C) 2004 Nicolai Haehnle. + * All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Nicolai Haehnle + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon_drv.h" +#include "r300_reg.h" + +#define R300_SIMULTANEOUS_CLIPRECTS 4 + +/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects + */ +static const int r300_cliprect_cntl[4] = { + 0xAAAA, + 0xEEEE, + 0xFEFE, + 0xFFFE +}; + +/** + * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command + * buffer, starting with index n. + */ +static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, int n) +{ + struct drm_clip_rect box; + int nr; + int i; + RING_LOCALS; + + nr = cmdbuf->nbox - n; + if (nr > R300_SIMULTANEOUS_CLIPRECTS) + nr = R300_SIMULTANEOUS_CLIPRECTS; + + DRM_DEBUG("%i cliprects\n", nr); + + if (nr) { + BEGIN_RING(6 + nr * 2); + OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1)); + + for (i = 0; i < nr; ++i) { + if (DRM_COPY_FROM_USER_UNCHECKED + (&box, &cmdbuf->boxes[n + i], sizeof(box))) { + DRM_ERROR("copy cliprect faulted\n"); + return -EFAULT; + } + + box.x2--; /* Hardware expects inclusive bottom-right corner */ + box.y2--; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { + box.x1 = (box.x1) & + R300_CLIPRECT_MASK; + box.y1 = (box.y1) & + R300_CLIPRECT_MASK; + box.x2 = (box.x2) & + R300_CLIPRECT_MASK; + box.y2 = (box.y2) & + R300_CLIPRECT_MASK; + } else { + box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + } + + OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | + (box.y1 << R300_CLIPRECT_Y_SHIFT)); + OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | + (box.y2 << R300_CLIPRECT_Y_SHIFT)); + + } + + OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]); + + /* TODO/SECURITY: Force scissors to a safe value, otherwise the + * client might be able to trample over memory. + * The impact should be very limited, but I'd rather be safe than + * sorry. + */ + OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1)); + OUT_RING(0); + OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK); + ADVANCE_RING(); + } else { + /* Why we allow zero cliprect rendering: + * There are some commands in a command buffer that must be submitted + * even when there are no cliprects, e.g. DMA buffer discard + * or state setting (though state setting could be avoided by + * simulating a loss of context). + * + * Now since the cmdbuf interface is so chaotic right now (and is + * bound to remain that way for a bit until things settle down), + * it is basically impossible to filter out the commands that are + * necessary and those that aren't. + * + * So I choose the safe way and don't do any filtering at all; + * instead, I simply set up the engine so that all rendering + * can't produce any fragments. + */ + BEGIN_RING(2); + OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0); + ADVANCE_RING(); + } + + /* flus cache and wait idle clean after cliprect change */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FLUSH); + ADVANCE_RING(); + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + ADVANCE_RING(); + /* set flush flag */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED; + + return 0; +} + +static u8 r300_reg_flags[0x10000 >> 2]; + +void r300_init_reg_flags(struct drm_device *dev) +{ + int i; + drm_radeon_private_t *dev_priv = dev->dev_private; + + memset(r300_reg_flags, 0, 0x10000 >> 2); +#define ADD_RANGE_MARK(reg, count,mark) \ + for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\ + r300_reg_flags[i]|=(mark); + +#define MARK_SAFE 1 +#define MARK_CHECK_OFFSET 2 + +#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE) + + /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */ + ADD_RANGE(R300_SE_VPORT_XSCALE, 6); + ADD_RANGE(R300_VAP_CNTL, 1); + ADD_RANGE(R300_SE_VTE_CNTL, 2); + ADD_RANGE(0x2134, 2); + ADD_RANGE(R300_VAP_CNTL_STATUS, 1); + ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2); + ADD_RANGE(0x21DC, 1); + ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); + ADD_RANGE(R300_VAP_CLIP_X_0, 4); + ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1); + ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); + ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); + ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); + ADD_RANGE(R300_GB_ENABLE, 1); + ADD_RANGE(R300_GB_MSPOS0, 5); + ADD_RANGE(R300_TX_INVALTAGS, 1); + ADD_RANGE(R300_TX_ENABLE, 1); + ADD_RANGE(0x4200, 4); + ADD_RANGE(0x4214, 1); + ADD_RANGE(R300_RE_POINTSIZE, 1); + ADD_RANGE(0x4230, 3); + ADD_RANGE(R300_RE_LINE_CNT, 1); + ADD_RANGE(R300_RE_UNK4238, 1); + ADD_RANGE(0x4260, 3); + ADD_RANGE(R300_RE_SHADE, 4); + ADD_RANGE(R300_RE_POLYGON_MODE, 5); + ADD_RANGE(R300_RE_ZBIAS_CNTL, 1); + ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4); + ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1); + ADD_RANGE(R300_RE_CULL_CNTL, 1); + ADD_RANGE(0x42C0, 2); + ADD_RANGE(R300_RS_CNTL_0, 2); + + ADD_RANGE(R300_SU_REG_DEST, 1); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) + ADD_RANGE(RV530_FG_ZBREG_DEST, 1); + + ADD_RANGE(R300_SC_HYPERZ, 2); + ADD_RANGE(0x43E8, 1); + + ADD_RANGE(0x46A4, 5); + + ADD_RANGE(R300_RE_FOG_STATE, 1); + ADD_RANGE(R300_FOG_COLOR_R, 3); + ADD_RANGE(R300_PP_ALPHA_TEST, 2); + ADD_RANGE(0x4BD8, 1); + ADD_RANGE(R300_PFS_PARAM_0_X, 64); + ADD_RANGE(0x4E00, 1); + ADD_RANGE(R300_RB3D_CBLEND, 2); + ADD_RANGE(R300_RB3D_COLORMASK, 1); + ADD_RANGE(R300_RB3D_BLEND_COLOR, 3); + ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */ + ADD_RANGE(R300_RB3D_COLORPITCH0, 1); + ADD_RANGE(0x4E50, 9); + ADD_RANGE(0x4E88, 1); + ADD_RANGE(0x4EA0, 2); + ADD_RANGE(R300_ZB_CNTL, 3); + ADD_RANGE(R300_ZB_FORMAT, 4); + ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */ + ADD_RANGE(R300_ZB_DEPTHPITCH, 1); + ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1); + ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13); + ADD_RANGE(R300_ZB_ZPASS_DATA, 2); /* ZB_ZPASS_DATA, ZB_ZPASS_ADDR */ + + ADD_RANGE(R300_TX_FILTER_0, 16); + ADD_RANGE(R300_TX_FILTER1_0, 16); + ADD_RANGE(R300_TX_SIZE_0, 16); + ADD_RANGE(R300_TX_FORMAT_0, 16); + ADD_RANGE(R300_TX_PITCH_0, 16); + /* Texture offset is dangerous and needs more checking */ + ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); + ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); + ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); + + /* Sporadic registers used as primitives are emitted */ + ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1); + ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1); + ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8); + ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { + ADD_RANGE(R500_VAP_INDEX_OFFSET, 1); + ADD_RANGE(R500_US_CONFIG, 2); + ADD_RANGE(R500_US_CODE_ADDR, 3); + ADD_RANGE(R500_US_FC_CTRL, 1); + ADD_RANGE(R500_RS_IP_0, 16); + ADD_RANGE(R500_RS_INST_0, 16); + ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2); + ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2); + ADD_RANGE(R500_ZB_FIFO_SIZE, 2); + } else { + ADD_RANGE(R300_PFS_CNTL_0, 3); + ADD_RANGE(R300_PFS_NODE_0, 4); + ADD_RANGE(R300_PFS_TEXI_0, 64); + ADD_RANGE(R300_PFS_INSTR0_0, 64); + ADD_RANGE(R300_PFS_INSTR1_0, 64); + ADD_RANGE(R300_PFS_INSTR2_0, 64); + ADD_RANGE(R300_PFS_INSTR3_0, 64); + ADD_RANGE(R300_RS_INTERP_0, 8); + ADD_RANGE(R300_RS_ROUTE_0, 8); + + } +} + +static __inline__ int r300_check_range(unsigned reg, int count) +{ + int i; + if (reg & ~0xffff) + return -1; + for (i = (reg >> 2); i < (reg >> 2) + count; i++) + if (r300_reg_flags[i] != MARK_SAFE) + return 1; + return 0; +} + +static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * + dev_priv, + drm_radeon_kcmd_buffer_t + * cmdbuf, + drm_r300_cmd_header_t + header) +{ + int reg; + int sz; + int i; + u32 *value; + RING_LOCALS; + + sz = header.packet0.count; + reg = (header.packet0.reghi << 8) | header.packet0.reglo; + + if ((sz > 64) || (sz < 0)) { + DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", + reg, sz); + return -EINVAL; + } + + for (i = 0; i < sz; i++) { + switch (r300_reg_flags[(reg >> 2) + i]) { + case MARK_SAFE: + break; + case MARK_CHECK_OFFSET: + value = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); + if (!radeon_check_offset(dev_priv, *value)) { + DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n", + reg, sz); + return -EINVAL; + } + break; + default: + DRM_ERROR("Register %04x failed check as flag=%02x\n", + reg + i * 4, r300_reg_flags[(reg >> 2) + i]); + return -EINVAL; + } + } + + BEGIN_RING(1 + sz); + OUT_RING(CP_PACKET0(reg, sz - 1)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + + return 0; +} + +/** + * Emits a packet0 setting arbitrary registers. + * Called by r300_do_cp_cmdbuf. + * + * Note that checks are performed on contents and addresses of the registers + */ +static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + int reg; + int sz; + RING_LOCALS; + + sz = header.packet0.count; + reg = (header.packet0.reghi << 8) | header.packet0.reglo; + + if (!sz) + return 0; + + if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) + return -EINVAL; + + if (reg + sz * 4 >= 0x10000) { + DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, + sz); + return -EINVAL; + } + + if (r300_check_range(reg, sz)) { + /* go and check everything */ + return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, + header); + } + /* the rest of the data is safe to emit, whatever the values the user passed */ + + BEGIN_RING(1 + sz); + OUT_RING(CP_PACKET0(reg, sz - 1)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + + return 0; +} + +/** + * Uploads user-supplied vertex program instructions or parameters onto + * the graphics card. + * Called by r300_do_cp_cmdbuf. + */ +static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + int sz; + int addr; + RING_LOCALS; + + sz = header.vpu.count; + addr = (header.vpu.adrhi << 8) | header.vpu.adrlo; + + if (!sz) + return 0; + if (sz * 16 > drm_buffer_unprocessed(cmdbuf->buffer)) + return -EINVAL; + + /* VAP is very sensitive so we purge cache before we program it + * and we also flush its state before & after */ + BEGIN_RING(6); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FLUSH); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); + OUT_RING(0); + ADVANCE_RING(); + /* set flush flag */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED; + + BEGIN_RING(3 + sz * 4); + OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); + OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * 4); + ADVANCE_RING(); + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); + OUT_RING(0); + ADVANCE_RING(); + + return 0; +} + +/** + * Emit a clear packet from userspace. + * Called by r300_emit_packet3. + */ +static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + RING_LOCALS; + + if (8 * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) + return -EINVAL; + + BEGIN_RING(10); + OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8)); + OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING | + (1 << R300_PRIM_NUM_VERTICES_SHIFT)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, 8); + ADVANCE_RING(); + + BEGIN_RING(4); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FLUSH); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + ADVANCE_RING(); + /* set flush flag */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED; + + return 0; +} + +static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + u32 header) +{ + int count, i, k; +#define MAX_ARRAY_PACKET 64 + u32 *data; + u32 narrays; + RING_LOCALS; + + count = (header & RADEON_CP_PACKET_COUNT_MASK) >> 16; + + if ((count + 1) > MAX_ARRAY_PACKET) { + DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", + count); + return -EINVAL; + } + /* carefully check packet contents */ + + /* We have already read the header so advance the buffer. */ + drm_buffer_advance(cmdbuf->buffer, 4); + + narrays = *(u32 *)drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + k = 0; + i = 1; + while ((k < narrays) && (i < (count + 1))) { + i++; /* skip attribute field */ + data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); + if (!radeon_check_offset(dev_priv, *data)) { + DRM_ERROR + ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", + k, i); + return -EINVAL; + } + k++; + i++; + if (k == narrays) + break; + /* have one more to process, they come in pairs */ + data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); + if (!radeon_check_offset(dev_priv, *data)) { + DRM_ERROR + ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", + k, i); + return -EINVAL; + } + k++; + i++; + } + /* do the counts match what we expect ? */ + if ((k != narrays) || (i != (count + 1))) { + DRM_ERROR + ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", + k, i, narrays, count + 1); + return -EINVAL; + } + + /* all clear, output packet */ + + BEGIN_RING(count + 2); + OUT_RING(header); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 1); + ADVANCE_RING(); + + return 0; +} + +static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + int count, ret; + RING_LOCALS; + + + count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16; + + if (*cmd & 0x8000) { + u32 offset; + u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + if (*cmd1 & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL + | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { + + u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); + offset = *cmd2 << 10; + ret = !radeon_check_offset(dev_priv, offset); + if (ret) { + DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); + return -EINVAL; + } + } + + if ((*cmd1 & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && + (*cmd1 & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { + u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); + offset = *cmd3 << 10; + ret = !radeon_check_offset(dev_priv, offset); + if (ret) { + DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); + return -EINVAL; + } + + } + } + + BEGIN_RING(count+2); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2); + ADVANCE_RING(); + + return 0; +} + +static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + int count; + int expected_count; + RING_LOCALS; + + count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16; + + expected_count = *cmd1 >> 16; + if (!(*cmd1 & R300_VAP_VF_CNTL__INDEX_SIZE_32bit)) + expected_count = (expected_count+1)/2; + + if (count && count != expected_count) { + DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n", + count, expected_count); + return -EINVAL; + } + + BEGIN_RING(count+2); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2); + ADVANCE_RING(); + + if (!count) { + drm_r300_cmd_header_t stack_header, *header; + u32 *cmd1, *cmd2, *cmd3; + + if (drm_buffer_unprocessed(cmdbuf->buffer) + < 4*4 + sizeof(stack_header)) { + DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n"); + return -EINVAL; + } + + header = drm_buffer_read_object(cmdbuf->buffer, + sizeof(stack_header), &stack_header); + + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); + cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); + + if (header->header.cmd_type != R300_CMD_PACKET3 || + header->packet3.packet != R300_CMD_PACKET3_RAW || + *cmd != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) { + DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n"); + return -EINVAL; + } + + if ((*cmd1 & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", + *cmd1); + return -EINVAL; + } + if (!radeon_check_offset(dev_priv, *cmd2)) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", + *cmd2); + return -EINVAL; + } + if (*cmd3 != expected_count) { + DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n", + *cmd3, expected_count); + return -EINVAL; + } + + BEGIN_RING(4); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, 4); + ADVANCE_RING(); + } + + return 0; +} + +static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + u32 *header; + int count; + RING_LOCALS; + + if (4 > drm_buffer_unprocessed(cmdbuf->buffer)) + return -EINVAL; + + /* Fixme !! This simply emits a packet without much checking. + We need to be smarter. */ + + /* obtain first word - actual packet3 header */ + header = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + + /* Is it packet 3 ? */ + if ((*header >> 30) != 0x3) { + DRM_ERROR("Not a packet3 header (0x%08x)\n", *header); + return -EINVAL; + } + + count = (*header >> 16) & 0x3fff; + + /* Check again now that we know how much data to expect */ + if ((count + 2) * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) { + DRM_ERROR + ("Expected packet3 of length %d but have only %d bytes left\n", + (count + 2) * 4, drm_buffer_unprocessed(cmdbuf->buffer)); + return -EINVAL; + } + + /* Is it a packet type we know about ? */ + switch (*header & 0xff00) { + case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ + return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, *header); + + case RADEON_CNTL_BITBLT_MULTI: + return r300_emit_bitblt_multi(dev_priv, cmdbuf); + + case RADEON_CP_INDX_BUFFER: + DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n"); + return -EINVAL; + case RADEON_CP_3D_DRAW_IMMD_2: + /* triggers drawing using in-packet vertex data */ + case RADEON_CP_3D_DRAW_VBUF_2: + /* triggers drawing of vertex buffers setup elsewhere */ + dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | + RADEON_PURGE_EMITED); + break; + case RADEON_CP_3D_DRAW_INDX_2: + /* triggers drawing using indices to vertex buffer */ + /* whenever we send vertex we clear flush & purge */ + dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | + RADEON_PURGE_EMITED); + return r300_emit_draw_indx_2(dev_priv, cmdbuf); + case RADEON_WAIT_FOR_IDLE: + case RADEON_CP_NOP: + /* these packets are safe */ + break; + default: + DRM_ERROR("Unknown packet3 header (0x%08x)\n", *header); + return -EINVAL; + } + + BEGIN_RING(count + 2); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2); + ADVANCE_RING(); + + return 0; +} + +/** + * Emit a rendering packet3 from userspace. + * Called by r300_do_cp_cmdbuf. + */ +static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + int n; + int ret; + int orig_iter = cmdbuf->buffer->iterator; + + /* This is a do-while-loop so that we run the interior at least once, + * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale. + */ + n = 0; + do { + if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) { + ret = r300_emit_cliprects(dev_priv, cmdbuf, n); + if (ret) + return ret; + + cmdbuf->buffer->iterator = orig_iter; + } + + switch (header.packet3.packet) { + case R300_CMD_PACKET3_CLEAR: + DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n"); + ret = r300_emit_clear(dev_priv, cmdbuf); + if (ret) { + DRM_ERROR("r300_emit_clear failed\n"); + return ret; + } + break; + + case R300_CMD_PACKET3_RAW: + DRM_DEBUG("R300_CMD_PACKET3_RAW\n"); + ret = r300_emit_raw_packet3(dev_priv, cmdbuf); + if (ret) { + DRM_ERROR("r300_emit_raw_packet3 failed\n"); + return ret; + } + break; + + default: + DRM_ERROR("bad packet3 type %i at byte %d\n", + header.packet3.packet, + cmdbuf->buffer->iterator - (int)sizeof(header)); + return -EINVAL; + } + + n += R300_SIMULTANEOUS_CLIPRECTS; + } while (n < cmdbuf->nbox); + + return 0; +} + +/* Some of the R300 chips seem to be extremely touchy about the two registers + * that are configured in r300_pacify. + * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace + * sends a command buffer that contains only state setting commands and a + * vertex program/parameter upload sequence, this will eventually lead to a + * lockup, unless the sequence is bracketed by calls to r300_pacify. + * So we should take great care to *always* call r300_pacify before + * *anything* 3D related, and again afterwards. This is what the + * call bracket in r300_do_cp_cmdbuf is for. + */ + +/** + * Emit the sequence to pacify R300. + */ +static void r300_pacify(drm_radeon_private_t *dev_priv) +{ + uint32_t cache_z, cache_3d, cache_2d; + RING_LOCALS; + + cache_z = R300_ZC_FLUSH; + cache_2d = R300_RB2D_DC_FLUSH; + cache_3d = R300_RB3D_DC_FLUSH; + if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) { + /* we can purge, primitive where draw since last purge */ + cache_z |= R300_ZC_FREE; + cache_2d |= R300_RB2D_DC_FREE; + cache_3d |= R300_RB3D_DC_FREE; + } + + /* flush & purge zbuffer */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); + OUT_RING(cache_z); + ADVANCE_RING(); + /* flush & purge 3d */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(cache_3d); + ADVANCE_RING(); + /* flush & purge texture */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0)); + OUT_RING(0); + ADVANCE_RING(); + /* FIXME: is this one really needed ? */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0)); + OUT_RING(0); + ADVANCE_RING(); + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + ADVANCE_RING(); + /* flush & purge 2d through E2 as RB2D will trigger lockup */ + BEGIN_RING(4); + OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0)); + OUT_RING(cache_2d); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_HOST_IDLECLEAN); + ADVANCE_RING(); + /* set flush & purge flags */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; +} + +/** + * Called by r300_do_cp_cmdbuf to update the internal buffer age and state. + * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must + * be careful about how this function is called. + */ +static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf) +{ + drm_radeon_buf_priv_t *buf_priv = buf->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + + buf_priv->age = ++master_priv->sarea_priv->last_dispatch; + buf->pending = 1; + buf->used = 0; +} + +static void r300_cmd_wait(drm_radeon_private_t * dev_priv, + drm_r300_cmd_header_t header) +{ + u32 wait_until; + RING_LOCALS; + + if (!header.wait.flags) + return; + + wait_until = 0; + + switch(header.wait.flags) { + case R300_WAIT_2D: + wait_until = RADEON_WAIT_2D_IDLE; + break; + case R300_WAIT_3D: + wait_until = RADEON_WAIT_3D_IDLE; + break; + case R300_NEW_WAIT_2D_3D: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE; + break; + case R300_NEW_WAIT_2D_2D_CLEAN: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; + break; + case R300_NEW_WAIT_3D_3D_CLEAN: + wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; + break; + case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; + wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; + break; + default: + return; + } + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(wait_until); + ADVANCE_RING(); +} + +static int r300_scratch(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + u32 *ref_age_base; + u32 i, *buf_idx, h_pending; + u64 *ptr_addr; + u64 stack_ptr_addr; + RING_LOCALS; + + if (drm_buffer_unprocessed(cmdbuf->buffer) < + (sizeof(u64) + header.scratch.n_bufs * sizeof(*buf_idx))) { + return -EINVAL; + } + + if (header.scratch.reg >= 5) { + return -EINVAL; + } + + dev_priv->scratch_ages[header.scratch.reg]++; + + ptr_addr = drm_buffer_read_object(cmdbuf->buffer, + sizeof(stack_ptr_addr), &stack_ptr_addr); + ref_age_base = (u32 *)(unsigned long)get_unaligned(ptr_addr); + + for (i=0; i < header.scratch.n_bufs; i++) { + buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + *buf_idx *= 2; /* 8 bytes per buf */ + + if (DRM_COPY_TO_USER(ref_age_base + *buf_idx, + &dev_priv->scratch_ages[header.scratch.reg], + sizeof(u32))) + return -EINVAL; + + if (DRM_COPY_FROM_USER(&h_pending, + ref_age_base + *buf_idx + 1, + sizeof(u32))) + return -EINVAL; + + if (h_pending == 0) + return -EINVAL; + + h_pending--; + + if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1, + &h_pending, + sizeof(u32))) + return -EINVAL; + + drm_buffer_advance(cmdbuf->buffer, sizeof(*buf_idx)); + } + + BEGIN_RING(2); + OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) ); + OUT_RING( dev_priv->scratch_ages[header.scratch.reg] ); + ADVANCE_RING(); + + return 0; +} + +/** + * Uploads user-supplied vertex program instructions or parameters onto + * the graphics card. + * Called by r300_do_cp_cmdbuf. + */ +static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + int sz; + int addr; + int type; + int isclamp; + int stride; + RING_LOCALS; + + sz = header.r500fp.count; + /* address is 9 bits 0 - 8, bit 1 of flags is part of address */ + addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; + + type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); + isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); + + addr |= (type << 16); + addr |= (isclamp << 17); + + stride = type ? 4 : 6; + + DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type); + if (!sz) + return 0; + if (sz * stride * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) + return -EINVAL; + + BEGIN_RING(3 + sz * stride); + OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * stride); + + ADVANCE_RING(); + + return 0; +} + + +/** + * Parses and validates a user-supplied command buffer and emits appropriate + * commands on the DMA ring buffer. + * Called by the ioctl handler function radeon_cp_cmdbuf. + */ +int r300_do_cp_cmdbuf(struct drm_device *dev, + struct drm_file *file_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + struct drm_device_dma *dma = dev->dma; + struct drm_buf *buf = NULL; + int emit_dispatch_age = 0; + int ret = 0; + + DRM_DEBUG("\n"); + + /* pacify */ + r300_pacify(dev_priv); + + if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { + ret = r300_emit_cliprects(dev_priv, cmdbuf, 0); + if (ret) + goto cleanup; + } + + while (drm_buffer_unprocessed(cmdbuf->buffer) + >= sizeof(drm_r300_cmd_header_t)) { + int idx; + drm_r300_cmd_header_t *header, stack_header; + + header = drm_buffer_read_object(cmdbuf->buffer, + sizeof(stack_header), &stack_header); + + switch (header->header.cmd_type) { + case R300_CMD_PACKET0: + DRM_DEBUG("R300_CMD_PACKET0\n"); + ret = r300_emit_packet0(dev_priv, cmdbuf, *header); + if (ret) { + DRM_ERROR("r300_emit_packet0 failed\n"); + goto cleanup; + } + break; + + case R300_CMD_VPU: + DRM_DEBUG("R300_CMD_VPU\n"); + ret = r300_emit_vpu(dev_priv, cmdbuf, *header); + if (ret) { + DRM_ERROR("r300_emit_vpu failed\n"); + goto cleanup; + } + break; + + case R300_CMD_PACKET3: + DRM_DEBUG("R300_CMD_PACKET3\n"); + ret = r300_emit_packet3(dev_priv, cmdbuf, *header); + if (ret) { + DRM_ERROR("r300_emit_packet3 failed\n"); + goto cleanup; + } + break; + + case R300_CMD_END3D: + DRM_DEBUG("R300_CMD_END3D\n"); + /* TODO: + Ideally userspace driver should not need to issue this call, + i.e. the drm driver should issue it automatically and prevent + lockups. + + In practice, we do not understand why this call is needed and what + it does (except for some vague guesses that it has to do with cache + coherence) and so the user space driver does it. + + Once we are sure which uses prevent lockups the code could be moved + into the kernel and the userspace driver will not + need to use this command. + + Note that issuing this command does not hurt anything + except, possibly, performance */ + r300_pacify(dev_priv); + break; + + case R300_CMD_CP_DELAY: + /* simple enough, we can do it here */ + DRM_DEBUG("R300_CMD_CP_DELAY\n"); + { + int i; + RING_LOCALS; + + BEGIN_RING(header->delay.count); + for (i = 0; i < header->delay.count; i++) + OUT_RING(RADEON_CP_PACKET2); + ADVANCE_RING(); + } + break; + + case R300_CMD_DMA_DISCARD: + DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); + idx = header->dma.buf_idx; + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + idx, dma->buf_count - 1); + ret = -EINVAL; + goto cleanup; + } + + buf = dma->buflist[idx]; + if (buf->file_priv != file_priv || buf->pending) { + DRM_ERROR("bad buffer %p %p %d\n", + buf->file_priv, file_priv, + buf->pending); + ret = -EINVAL; + goto cleanup; + } + + emit_dispatch_age = 1; + r300_discard_buffer(dev, file_priv->masterp, buf); + break; + + case R300_CMD_WAIT: + DRM_DEBUG("R300_CMD_WAIT\n"); + r300_cmd_wait(dev_priv, *header); + break; + + case R300_CMD_SCRATCH: + DRM_DEBUG("R300_CMD_SCRATCH\n"); + ret = r300_scratch(dev_priv, cmdbuf, *header); + if (ret) { + DRM_ERROR("r300_scratch failed\n"); + goto cleanup; + } + break; + + case R300_CMD_R500FP: + if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) { + DRM_ERROR("Calling r500 command on r300 card\n"); + ret = -EINVAL; + goto cleanup; + } + DRM_DEBUG("R300_CMD_R500FP\n"); + ret = r300_emit_r500fp(dev_priv, cmdbuf, *header); + if (ret) { + DRM_ERROR("r300_emit_r500fp failed\n"); + goto cleanup; + } + break; + default: + DRM_ERROR("bad cmd_type %i at byte %d\n", + header->header.cmd_type, + cmdbuf->buffer->iterator - (int)sizeof(*header)); + ret = -EINVAL; + goto cleanup; + } + } + + DRM_DEBUG("END\n"); + + cleanup: + r300_pacify(dev_priv); + + /* We emit the vertex buffer age here, outside the pacifier "brackets" + * for two reasons: + * (1) This may coalesce multiple age emissions into a single one and + * (2) more importantly, some chips lock up hard when scratch registers + * are written inside the pacifier bracket. + */ + if (emit_dispatch_age) { + RING_LOCALS; + + /* Emit the vertex buffer age */ + BEGIN_RING(2); + RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch); + ADVANCE_RING(); + } + + COMMIT_RING(); + + return ret; +} diff --git a/sys/dev/drm2/radeon/r300_reg.h b/sys/dev/drm2/radeon/r300_reg.h new file mode 100644 index 00000000000..3478d00920d --- /dev/null +++ b/sys/dev/drm2/radeon/r300_reg.h @@ -0,0 +1,1792 @@ +/* + * Copyright 2005 Nicolai Haehnle et al. + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Nicolai Haehnle + * Jerome Glisse + */ +#ifndef _R300_REG_H_ +#define _R300_REG_H_ + +#include +__FBSDID("$FreeBSD$"); + +#define R300_SURF_TILE_MACRO (1<<16) +#define R300_SURF_TILE_MICRO (2<<16) +#define R300_SURF_TILE_BOTH (3<<16) + + +#define R300_MC_INIT_MISC_LAT_TIMER 0x180 +# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 +# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4 +# define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8 +# define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12 +# define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16 +# define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20 +# define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24 +# define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28 + +#define R300_MC_INIT_GFX_LAT_TIMER 0x154 +# define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0 +# define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4 +# define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8 +# define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12 +# define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16 +# define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20 +# define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24 +# define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28 + +/* + * This file contains registers and constants for the R300. They have been + * found mostly by examining command buffers captured using glxtest, as well + * as by extrapolating some known registers and constants from the R200. + * I am fairly certain that they are correct unless stated otherwise + * in comments. + */ + +#define R300_SE_VPORT_XSCALE 0x1D98 +#define R300_SE_VPORT_XOFFSET 0x1D9C +#define R300_SE_VPORT_YSCALE 0x1DA0 +#define R300_SE_VPORT_YOFFSET 0x1DA4 +#define R300_SE_VPORT_ZSCALE 0x1DA8 +#define R300_SE_VPORT_ZOFFSET 0x1DAC + + +/* + * Vertex Array Processing (VAP) Control + * Stolen from r200 code from Christoph Brill (It's a guess!) + */ +#define R300_VAP_CNTL 0x2080 + +/* This register is written directly and also starts data section + * in many 3d CP_PACKET3's + */ +#define R300_VAP_VF_CNTL 0x2084 +# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0 +# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0) +# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0) +# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0) +# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0) +# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0) +# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0) +# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0) +# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0) +# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0) +# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0) +# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0) + +# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4 + /* State based - direct writes to registers trigger vertex + generation */ +# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4) +# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4) +# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4) +# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4) + + /* I don't think I saw these three used.. */ +# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6 +# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9 +# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10 + + /* index size - when not set the indices are assumed to be 16 bit */ +# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11) + /* number of vertices */ +# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16 + +/* BEGIN: Wild guesses */ +#define R300_VAP_OUTPUT_VTX_FMT_0 0x2090 +# define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0) +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1) +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */ +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */ +# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */ +# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */ + +#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094 + /* each of the following is 3 bits wide, specifies number + of components */ +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 +# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 +/* END: Wild guesses */ + +#define R300_SE_VTE_CNTL 0x20b0 +# define R300_VPORT_X_SCALE_ENA 0x00000001 +# define R300_VPORT_X_OFFSET_ENA 0x00000002 +# define R300_VPORT_Y_SCALE_ENA 0x00000004 +# define R300_VPORT_Y_OFFSET_ENA 0x00000008 +# define R300_VPORT_Z_SCALE_ENA 0x00000010 +# define R300_VPORT_Z_OFFSET_ENA 0x00000020 +# define R300_VTX_XY_FMT 0x00000100 +# define R300_VTX_Z_FMT 0x00000200 +# define R300_VTX_W0_FMT 0x00000400 +# define R300_VTX_W0_NORMALIZE 0x00000800 +# define R300_VTX_ST_DENORMALIZED 0x00001000 + +/* BEGIN: Vertex data assembly - lots of uncertainties */ + +/* gap */ + +#define R300_VAP_CNTL_STATUS 0x2140 +# define R300_VC_NO_SWAP (0 << 0) +# define R300_VC_16BIT_SWAP (1 << 0) +# define R300_VC_32BIT_SWAP (2 << 0) +# define R300_VAP_TCL_BYPASS (1 << 8) + +/* gap */ + +/* Where do we get our vertex data? + * + * Vertex data either comes either from immediate mode registers or from + * vertex arrays. + * There appears to be no mixed mode (though we can force the pitch of + * vertex arrays to 0, effectively reusing the same element over and over + * again). + * + * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure + * if these registers influence vertex array processing. + * + * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3. + * + * In both cases, vertex attributes are then passed through INPUT_ROUTE. + * + * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data + * into the vertex processor's input registers. + * The first word routes the first input, the second word the second, etc. + * The corresponding input is routed into the register with the given index. + * The list is ended by a word with INPUT_ROUTE_END set. + * + * Always set COMPONENTS_4 in immediate mode. + */ + +#define R300_VAP_INPUT_ROUTE_0_0 0x2150 +# define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0) +# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */ +# define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8 +# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */ +# define R300_VAP_INPUT_ROUTE_END (1 << 13) +# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */ +# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */ +# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */ +# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */ +#define R300_VAP_INPUT_ROUTE_0_1 0x2154 +#define R300_VAP_INPUT_ROUTE_0_2 0x2158 +#define R300_VAP_INPUT_ROUTE_0_3 0x215C +#define R300_VAP_INPUT_ROUTE_0_4 0x2160 +#define R300_VAP_INPUT_ROUTE_0_5 0x2164 +#define R300_VAP_INPUT_ROUTE_0_6 0x2168 +#define R300_VAP_INPUT_ROUTE_0_7 0x216C + +/* gap */ + +/* Notes: + * - always set up to produce at least two attributes: + * if vertex program uses only position, fglrx will set normal, too + * - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal. + */ +#define R300_VAP_INPUT_CNTL_0 0x2180 +# define R300_INPUT_CNTL_0_COLOR 0x00000001 +#define R300_VAP_INPUT_CNTL_1 0x2184 +# define R300_INPUT_CNTL_POS 0x00000001 +# define R300_INPUT_CNTL_NORMAL 0x00000002 +# define R300_INPUT_CNTL_COLOR 0x00000004 +# define R300_INPUT_CNTL_TC0 0x00000400 +# define R300_INPUT_CNTL_TC1 0x00000800 +# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */ +# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */ +# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */ +# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */ +# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */ +# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */ + +/* gap */ + +/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0 + * are set to a swizzling bit pattern, other words are 0. + * + * In immediate mode, the pattern is always set to xyzw. In vertex array + * mode, the swizzling pattern is e.g. used to set zw components in texture + * coordinates with only tweo components. + */ +#define R300_VAP_INPUT_ROUTE_1_0 0x21E0 +# define R300_INPUT_ROUTE_SELECT_X 0 +# define R300_INPUT_ROUTE_SELECT_Y 1 +# define R300_INPUT_ROUTE_SELECT_Z 2 +# define R300_INPUT_ROUTE_SELECT_W 3 +# define R300_INPUT_ROUTE_SELECT_ZERO 4 +# define R300_INPUT_ROUTE_SELECT_ONE 5 +# define R300_INPUT_ROUTE_SELECT_MASK 7 +# define R300_INPUT_ROUTE_X_SHIFT 0 +# define R300_INPUT_ROUTE_Y_SHIFT 3 +# define R300_INPUT_ROUTE_Z_SHIFT 6 +# define R300_INPUT_ROUTE_W_SHIFT 9 +# define R300_INPUT_ROUTE_ENABLE (15 << 12) +#define R300_VAP_INPUT_ROUTE_1_1 0x21E4 +#define R300_VAP_INPUT_ROUTE_1_2 0x21E8 +#define R300_VAP_INPUT_ROUTE_1_3 0x21EC +#define R300_VAP_INPUT_ROUTE_1_4 0x21F0 +#define R300_VAP_INPUT_ROUTE_1_5 0x21F4 +#define R300_VAP_INPUT_ROUTE_1_6 0x21F8 +#define R300_VAP_INPUT_ROUTE_1_7 0x21FC + +/* END: Vertex data assembly */ + +/* gap */ + +/* BEGIN: Upload vertex program and data */ + +/* + * The programmable vertex shader unit has a memory bank of unknown size + * that can be written to in 16 byte units by writing the address into + * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs). + * + * Pointers into the memory bank are always in multiples of 16 bytes. + * + * The memory bank is divided into areas with fixed meaning. + * + * Starting at address UPLOAD_PROGRAM: Vertex program instructions. + * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB), + * whereas the difference between known addresses suggests size 512. + * + * Starting at address UPLOAD_PARAMETERS: Vertex program parameters. + * Native reported limits and the VPI layout suggest size 256, whereas + * difference between known addresses suggests size 512. + * + * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the + * floating point pointsize. The exact purpose of this state is uncertain, + * as there is also the R300_RE_POINTSIZE register. + * + * Multiple vertex programs and parameter sets can be loaded at once, + * which could explain the size discrepancy. + */ +#define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200 +# define R300_PVS_UPLOAD_PROGRAM 0x00000000 +# define R300_PVS_UPLOAD_PARAMETERS 0x00000200 +# define R300_PVS_UPLOAD_POINTSIZE 0x00000406 + +/* gap */ + +#define R300_VAP_PVS_UPLOAD_DATA 0x2208 + +/* END: Upload vertex program and data */ + +/* gap */ + +/* I do not know the purpose of this register. However, I do know that + * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL + * for normal rendering. + */ +#define R300_VAP_UNKNOWN_221C 0x221C +# define R300_221C_NORMAL 0x00000000 +# define R300_221C_CLEAR 0x0001C000 + +/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first + * plane is per-pixel and the second plane is per-vertex. + * + * This was determined by experimentation alone but I believe it is correct. + * + * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest. + */ +#define R300_VAP_CLIP_X_0 0x2220 +#define R300_VAP_CLIP_X_1 0x2224 +#define R300_VAP_CLIP_Y_0 0x2228 +#define R300_VAP_CLIP_Y_1 0x2230 + +/* gap */ + +/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between + * rendering commands and overwriting vertex program parameters. + * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and + * avoids bugs caused by still running shaders reading bad data from memory. + */ +#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284 + +/* Absolutely no clue what this register is about. */ +#define R300_VAP_UNKNOWN_2288 0x2288 +# define R300_2288_R300 0x00750000 /* -- nh */ +# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */ + +/* gap */ + +/* Addresses are relative to the vertex program instruction area of the + * memory bank. PROGRAM_END points to the last instruction of the active + * program + * + * The meaning of the two UNKNOWN fields is obviously not known. However, + * experiments so far have shown that both *must* point to an instruction + * inside the vertex program, otherwise the GPU locks up. + * + * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and + * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to + * position takes place. + * + * Most likely this is used to ignore rest of the program in cases + * where group of verts arent visible. For some reason this "section" + * is sometimes accepted other instruction that have no relationship with + * position calculations. + */ +#define R300_VAP_PVS_CNTL_1 0x22D0 +# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 +# define R300_PVS_CNTL_1_POS_END_SHIFT 10 +# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 +/* Addresses are relative the the vertex program parameters area. */ +#define R300_VAP_PVS_CNTL_2 0x22D4 +# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 +# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 +#define R300_VAP_PVS_CNTL_3 0x22D8 +# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10 +# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0 + +/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for + * immediate vertices + */ +#define R300_VAP_VTX_COLOR_R 0x2464 +#define R300_VAP_VTX_COLOR_G 0x2468 +#define R300_VAP_VTX_COLOR_B 0x246C +#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */ +#define R300_VAP_VTX_POS_0_Y_1 0x2494 +#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */ +#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */ +#define R300_VAP_VTX_POS_0_Y_2 0x24A4 +#define R300_VAP_VTX_POS_0_Z_2 0x24A8 +/* write 0 to indicate end of packet? */ +#define R300_VAP_VTX_END_OF_PKT 0x24AC + +/* gap */ + +/* These are values from r300_reg/r300_reg.h - they are known to be correct + * and are here so we can use one register file instead of several + * - Vladimir + */ +#define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000 +# define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4) +# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5) +# define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16) + +#define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004 + /* each of the following is 3 bits wide, specifies number + of components */ +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 +# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 + +/* UNK30 seems to enables point to quad transformation on textures + * (or something closely related to that). + * This bit is rather fatal at the time being due to lackings at pixel + * shader side + */ +#define R300_GB_ENABLE 0x4008 +# define R300_GB_POINT_STUFF_ENABLE (1<<0) +# define R300_GB_LINE_STUFF_ENABLE (1<<1) +# define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2) +# define R300_GB_STENCIL_AUTO_ENABLE (1<<4) +# define R300_GB_UNK31 (1<<31) + /* each of the following is 2 bits wide */ +#define R300_GB_TEX_REPLICATE 0 +#define R300_GB_TEX_ST 1 +#define R300_GB_TEX_STR 2 +# define R300_GB_TEX0_SOURCE_SHIFT 16 +# define R300_GB_TEX1_SOURCE_SHIFT 18 +# define R300_GB_TEX2_SOURCE_SHIFT 20 +# define R300_GB_TEX3_SOURCE_SHIFT 22 +# define R300_GB_TEX4_SOURCE_SHIFT 24 +# define R300_GB_TEX5_SOURCE_SHIFT 26 +# define R300_GB_TEX6_SOURCE_SHIFT 28 +# define R300_GB_TEX7_SOURCE_SHIFT 30 + +/* MSPOS - positions for multisample antialiasing (?) */ +#define R300_GB_MSPOS0 0x4010 + /* shifts - each of the fields is 4 bits */ +# define R300_GB_MSPOS0__MS_X0_SHIFT 0 +# define R300_GB_MSPOS0__MS_Y0_SHIFT 4 +# define R300_GB_MSPOS0__MS_X1_SHIFT 8 +# define R300_GB_MSPOS0__MS_Y1_SHIFT 12 +# define R300_GB_MSPOS0__MS_X2_SHIFT 16 +# define R300_GB_MSPOS0__MS_Y2_SHIFT 20 +# define R300_GB_MSPOS0__MSBD0_Y 24 +# define R300_GB_MSPOS0__MSBD0_X 28 + +#define R300_GB_MSPOS1 0x4014 +# define R300_GB_MSPOS1__MS_X3_SHIFT 0 +# define R300_GB_MSPOS1__MS_Y3_SHIFT 4 +# define R300_GB_MSPOS1__MS_X4_SHIFT 8 +# define R300_GB_MSPOS1__MS_Y4_SHIFT 12 +# define R300_GB_MSPOS1__MS_X5_SHIFT 16 +# define R300_GB_MSPOS1__MS_Y5_SHIFT 20 +# define R300_GB_MSPOS1__MSBD1 24 + + +#define R300_GB_TILE_CONFIG 0x4018 +# define R300_GB_TILE_ENABLE (1<<0) +# define R300_GB_TILE_PIPE_COUNT_RV300 0 +# define R300_GB_TILE_PIPE_COUNT_R300 (3<<1) +# define R300_GB_TILE_PIPE_COUNT_R420 (7<<1) +# define R300_GB_TILE_PIPE_COUNT_RV410 (3<<1) +# define R300_GB_TILE_SIZE_8 0 +# define R300_GB_TILE_SIZE_16 (1<<4) +# define R300_GB_TILE_SIZE_32 (2<<4) +# define R300_GB_SUPER_SIZE_1 (0<<6) +# define R300_GB_SUPER_SIZE_2 (1<<6) +# define R300_GB_SUPER_SIZE_4 (2<<6) +# define R300_GB_SUPER_SIZE_8 (3<<6) +# define R300_GB_SUPER_SIZE_16 (4<<6) +# define R300_GB_SUPER_SIZE_32 (5<<6) +# define R300_GB_SUPER_SIZE_64 (6<<6) +# define R300_GB_SUPER_SIZE_128 (7<<6) +# define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */ +# define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */ +# define R300_GB_SUPER_TILE_A 0 +# define R300_GB_SUPER_TILE_B (1<<15) +# define R300_GB_SUBPIXEL_1_12 0 +# define R300_GB_SUBPIXEL_1_16 (1<<16) + +#define R300_GB_FIFO_SIZE 0x4024 + /* each of the following is 2 bits wide */ +#define R300_GB_FIFO_SIZE_32 0 +#define R300_GB_FIFO_SIZE_64 1 +#define R300_GB_FIFO_SIZE_128 2 +#define R300_GB_FIFO_SIZE_256 3 +# define R300_SC_IFIFO_SIZE_SHIFT 0 +# define R300_SC_TZFIFO_SIZE_SHIFT 2 +# define R300_SC_BFIFO_SIZE_SHIFT 4 + +# define R300_US_OFIFO_SIZE_SHIFT 12 +# define R300_US_WFIFO_SIZE_SHIFT 14 + /* the following use the same constants as above, but meaning is + is times 2 (i.e. instead of 32 words it means 64 */ +# define R300_RS_TFIFO_SIZE_SHIFT 6 +# define R300_RS_CFIFO_SIZE_SHIFT 8 +# define R300_US_RAM_SIZE_SHIFT 10 + /* watermarks, 3 bits wide */ +# define R300_RS_HIGHWATER_COL_SHIFT 16 +# define R300_RS_HIGHWATER_TEX_SHIFT 19 +# define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */ +# define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24 + +#define R300_GB_SELECT 0x401C +# define R300_GB_FOG_SELECT_C0A 0 +# define R300_GB_FOG_SELECT_C1A 1 +# define R300_GB_FOG_SELECT_C2A 2 +# define R300_GB_FOG_SELECT_C3A 3 +# define R300_GB_FOG_SELECT_1_1_W 4 +# define R300_GB_FOG_SELECT_Z 5 +# define R300_GB_DEPTH_SELECT_Z 0 +# define R300_GB_DEPTH_SELECT_1_1_W (1<<3) +# define R300_GB_W_SELECT_1_W 0 +# define R300_GB_W_SELECT_1 (1<<4) + +#define R300_GB_AA_CONFIG 0x4020 +# define R300_AA_DISABLE 0x00 +# define R300_AA_ENABLE 0x01 +# define R300_AA_SUBSAMPLES_2 0 +# define R300_AA_SUBSAMPLES_3 (1<<1) +# define R300_AA_SUBSAMPLES_4 (2<<1) +# define R300_AA_SUBSAMPLES_6 (3<<1) + +/* gap */ + +/* Zero to flush caches. */ +#define R300_TX_INVALTAGS 0x4100 +#define R300_TX_FLUSH 0x0 + +/* The upper enable bits are guessed, based on fglrx reported limits. */ +#define R300_TX_ENABLE 0x4104 +# define R300_TX_ENABLE_0 (1 << 0) +# define R300_TX_ENABLE_1 (1 << 1) +# define R300_TX_ENABLE_2 (1 << 2) +# define R300_TX_ENABLE_3 (1 << 3) +# define R300_TX_ENABLE_4 (1 << 4) +# define R300_TX_ENABLE_5 (1 << 5) +# define R300_TX_ENABLE_6 (1 << 6) +# define R300_TX_ENABLE_7 (1 << 7) +# define R300_TX_ENABLE_8 (1 << 8) +# define R300_TX_ENABLE_9 (1 << 9) +# define R300_TX_ENABLE_10 (1 << 10) +# define R300_TX_ENABLE_11 (1 << 11) +# define R300_TX_ENABLE_12 (1 << 12) +# define R300_TX_ENABLE_13 (1 << 13) +# define R300_TX_ENABLE_14 (1 << 14) +# define R300_TX_ENABLE_15 (1 << 15) + +/* The pointsize is given in multiples of 6. The pointsize can be + * enormous: Clear() renders a single point that fills the entire + * framebuffer. + */ +#define R300_RE_POINTSIZE 0x421C +# define R300_POINTSIZE_Y_SHIFT 0 +# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */ +# define R300_POINTSIZE_X_SHIFT 16 +# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */ +# define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6) + +/* The line width is given in multiples of 6. + * In default mode lines are classified as vertical lines. + * HO: horizontal + * VE: vertical or horizontal + * HO & VE: no classification + */ +#define R300_RE_LINE_CNT 0x4234 +# define R300_LINESIZE_SHIFT 0 +# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */ +# define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6) +# define R300_LINE_CNT_HO (1 << 16) +# define R300_LINE_CNT_VE (1 << 17) + +/* Some sort of scale or clamp value for texcoordless textures. */ +#define R300_RE_UNK4238 0x4238 + +/* Something shade related */ +#define R300_RE_SHADE 0x4274 + +#define R300_RE_SHADE_MODEL 0x4278 +# define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa +# define R300_RE_SHADE_MODEL_FLAT 0x39595 + +/* Dangerous */ +#define R300_RE_POLYGON_MODE 0x4288 +# define R300_PM_ENABLED (1 << 0) +# define R300_PM_FRONT_POINT (0 << 0) +# define R300_PM_BACK_POINT (0 << 0) +# define R300_PM_FRONT_LINE (1 << 4) +# define R300_PM_FRONT_FILL (1 << 5) +# define R300_PM_BACK_LINE (1 << 7) +# define R300_PM_BACK_FILL (1 << 8) + +/* Fog parameters */ +#define R300_RE_FOG_SCALE 0x4294 +#define R300_RE_FOG_START 0x4298 + +/* Not sure why there are duplicate of factor and constant values. + * My best guess so far is that there are separate zbiases for test and write. + * Ordering might be wrong. + * Some of the tests indicate that fgl has a fallback implementation of zbias + * via pixel shaders. + */ +#define R300_RE_ZBIAS_CNTL 0x42A0 /* GUESS */ +#define R300_RE_ZBIAS_T_FACTOR 0x42A4 +#define R300_RE_ZBIAS_T_CONSTANT 0x42A8 +#define R300_RE_ZBIAS_W_FACTOR 0x42AC +#define R300_RE_ZBIAS_W_CONSTANT 0x42B0 + +/* This register needs to be set to (1<<1) for RV350 to correctly + * perform depth test (see --vb-triangles in r300_demo) + * Don't know about other chips. - Vladimir + * This is set to 3 when GL_POLYGON_OFFSET_FILL is on. + * My guess is that there are two bits for each zbias primitive + * (FILL, LINE, POINT). + * One to enable depth test and one for depth write. + * Yet this doesn't explain why depth writes work ... + */ +#define R300_RE_OCCLUSION_CNTL 0x42B4 +# define R300_OCCLUSION_ON (1<<1) + +#define R300_RE_CULL_CNTL 0x42B8 +# define R300_CULL_FRONT (1 << 0) +# define R300_CULL_BACK (1 << 1) +# define R300_FRONT_FACE_CCW (0 << 2) +# define R300_FRONT_FACE_CW (1 << 2) + + +/* BEGIN: Rasterization / Interpolators - many guesses */ + +/* 0_UNKNOWN_18 has always been set except for clear operations. + * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends + * on the vertex program, *not* the fragment program) + */ +#define R300_RS_CNTL_0 0x4300 +# define R300_RS_CNTL_TC_CNT_SHIFT 2 +# define R300_RS_CNTL_TC_CNT_MASK (7 << 2) + /* number of color interpolators used */ +# define R300_RS_CNTL_CI_CNT_SHIFT 7 +# define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18) + /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n + register. */ +#define R300_RS_CNTL_1 0x4304 + +/* gap */ + +/* Only used for texture coordinates. + * Use the source field to route texture coordinate input from the + * vertex program to the desired interpolator. Note that the source + * field is relative to the outputs the vertex program *actually* + * writes. If a vertex program only writes texcoord[1], this will + * be source index 0. + * Set INTERP_USED on all interpolators that produce data used by + * the fragment program. INTERP_USED looks like a swizzling mask, + * but I haven't seen it used that way. + * + * Note: The _UNKNOWN constants are always set in their respective + * register. I don't know if this is necessary. + */ +#define R300_RS_INTERP_0 0x4310 +#define R300_RS_INTERP_1 0x4314 +# define R300_RS_INTERP_1_UNKNOWN 0x40 +#define R300_RS_INTERP_2 0x4318 +# define R300_RS_INTERP_2_UNKNOWN 0x80 +#define R300_RS_INTERP_3 0x431C +# define R300_RS_INTERP_3_UNKNOWN 0xC0 +#define R300_RS_INTERP_4 0x4320 +#define R300_RS_INTERP_5 0x4324 +#define R300_RS_INTERP_6 0x4328 +#define R300_RS_INTERP_7 0x432C +# define R300_RS_INTERP_SRC_SHIFT 2 +# define R300_RS_INTERP_SRC_MASK (7 << 2) +# define R300_RS_INTERP_USED 0x00D10000 + +/* These DWORDs control how vertex data is routed into fragment program + * registers, after interpolators. + */ +#define R300_RS_ROUTE_0 0x4330 +#define R300_RS_ROUTE_1 0x4334 +#define R300_RS_ROUTE_2 0x4338 +#define R300_RS_ROUTE_3 0x433C /* GUESS */ +#define R300_RS_ROUTE_4 0x4340 /* GUESS */ +#define R300_RS_ROUTE_5 0x4344 /* GUESS */ +#define R300_RS_ROUTE_6 0x4348 /* GUESS */ +#define R300_RS_ROUTE_7 0x434C /* GUESS */ +# define R300_RS_ROUTE_SOURCE_INTERP_0 0 +# define R300_RS_ROUTE_SOURCE_INTERP_1 1 +# define R300_RS_ROUTE_SOURCE_INTERP_2 2 +# define R300_RS_ROUTE_SOURCE_INTERP_3 3 +# define R300_RS_ROUTE_SOURCE_INTERP_4 4 +# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */ +# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */ +# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */ +# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */ +# define R300_RS_ROUTE_DEST_SHIFT 6 +# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */ + +/* Special handling for color: When the fragment program uses color, + * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the + * color register index. + * + * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any + * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state. + * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly + * correct or not. - Oliver. + */ +# define R300_RS_ROUTE_0_COLOR (1 << 14) +# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17 +# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */ +/* As above, but for secondary color */ +# define R300_RS_ROUTE_1_COLOR1 (1 << 14) +# define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17 +# define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17) +# define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11) +/* END: Rasterization / Interpolators - many guesses */ + +/* Hierarchical Z Enable */ +#define R300_SC_HYPERZ 0x43a4 +# define R300_SC_HYPERZ_DISABLE (0 << 0) +# define R300_SC_HYPERZ_ENABLE (1 << 0) +# define R300_SC_HYPERZ_MIN (0 << 1) +# define R300_SC_HYPERZ_MAX (1 << 1) +# define R300_SC_HYPERZ_ADJ_256 (0 << 2) +# define R300_SC_HYPERZ_ADJ_128 (1 << 2) +# define R300_SC_HYPERZ_ADJ_64 (2 << 2) +# define R300_SC_HYPERZ_ADJ_32 (3 << 2) +# define R300_SC_HYPERZ_ADJ_16 (4 << 2) +# define R300_SC_HYPERZ_ADJ_8 (5 << 2) +# define R300_SC_HYPERZ_ADJ_4 (6 << 2) +# define R300_SC_HYPERZ_ADJ_2 (7 << 2) +# define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5) +# define R300_SC_HYPERZ_HZ_Z0MIN (1 << 5) +# define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6) +# define R300_SC_HYPERZ_HZ_Z0MAX (1 << 6) + +#define R300_SC_EDGERULE 0x43a8 + +/* BEGIN: Scissors and cliprects */ + +/* There are four clipping rectangles. Their corner coordinates are inclusive. + * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending + * on whether the pixel is inside cliprects 0-3, respectively. For example, + * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned + * the number 3 (binary 0011). + * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set, + * the pixel is rasterized. + * + * In addition to this, there is a scissors rectangle. Only pixels inside the + * scissors rectangle are drawn. (coordinates are inclusive) + * + * For some reason, the top-left corner of the framebuffer is at (1440, 1440) + * for the purpose of clipping and scissors. + */ +#define R300_RE_CLIPRECT_TL_0 0x43B0 +#define R300_RE_CLIPRECT_BR_0 0x43B4 +#define R300_RE_CLIPRECT_TL_1 0x43B8 +#define R300_RE_CLIPRECT_BR_1 0x43BC +#define R300_RE_CLIPRECT_TL_2 0x43C0 +#define R300_RE_CLIPRECT_BR_2 0x43C4 +#define R300_RE_CLIPRECT_TL_3 0x43C8 +#define R300_RE_CLIPRECT_BR_3 0x43CC +# define R300_CLIPRECT_OFFSET 1440 +# define R300_CLIPRECT_MASK 0x1FFF +# define R300_CLIPRECT_X_SHIFT 0 +# define R300_CLIPRECT_X_MASK (0x1FFF << 0) +# define R300_CLIPRECT_Y_SHIFT 13 +# define R300_CLIPRECT_Y_MASK (0x1FFF << 13) +#define R300_RE_CLIPRECT_CNTL 0x43D0 +# define R300_CLIP_OUT (1 << 0) +# define R300_CLIP_0 (1 << 1) +# define R300_CLIP_1 (1 << 2) +# define R300_CLIP_10 (1 << 3) +# define R300_CLIP_2 (1 << 4) +# define R300_CLIP_20 (1 << 5) +# define R300_CLIP_21 (1 << 6) +# define R300_CLIP_210 (1 << 7) +# define R300_CLIP_3 (1 << 8) +# define R300_CLIP_30 (1 << 9) +# define R300_CLIP_31 (1 << 10) +# define R300_CLIP_310 (1 << 11) +# define R300_CLIP_32 (1 << 12) +# define R300_CLIP_320 (1 << 13) +# define R300_CLIP_321 (1 << 14) +# define R300_CLIP_3210 (1 << 15) + +/* gap */ + +#define R300_RE_SCISSORS_TL 0x43E0 +#define R300_RE_SCISSORS_BR 0x43E4 +# define R300_SCISSORS_OFFSET 1440 +# define R300_SCISSORS_X_SHIFT 0 +# define R300_SCISSORS_X_MASK (0x1FFF << 0) +# define R300_SCISSORS_Y_SHIFT 13 +# define R300_SCISSORS_Y_MASK (0x1FFF << 13) +/* END: Scissors and cliprects */ + +/* BEGIN: Texture specification */ + +/* + * The texture specification dwords are grouped by meaning and not by texture + * unit. This means that e.g. the offset for texture image unit N is found in + * register TX_OFFSET_0 + (4*N) + */ +#define R300_TX_FILTER_0 0x4400 +# define R300_TX_REPEAT 0 +# define R300_TX_MIRRORED 1 +# define R300_TX_CLAMP 4 +# define R300_TX_CLAMP_TO_EDGE 2 +# define R300_TX_CLAMP_TO_BORDER 6 +# define R300_TX_WRAP_S_SHIFT 0 +# define R300_TX_WRAP_S_MASK (7 << 0) +# define R300_TX_WRAP_T_SHIFT 3 +# define R300_TX_WRAP_T_MASK (7 << 3) +# define R300_TX_WRAP_Q_SHIFT 6 +# define R300_TX_WRAP_Q_MASK (7 << 6) +# define R300_TX_MAG_FILTER_NEAREST (1 << 9) +# define R300_TX_MAG_FILTER_LINEAR (2 << 9) +# define R300_TX_MAG_FILTER_MASK (3 << 9) +# define R300_TX_MIN_FILTER_NEAREST (1 << 11) +# define R300_TX_MIN_FILTER_LINEAR (2 << 11) +# define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST (5 << 11) +# define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR (9 << 11) +# define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11) +# define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11) + +/* NOTE: NEAREST doesn't seem to exist. + * Im not seting MAG_FILTER_MASK and (3 << 11) on for all + * anisotropy modes because that would void selected mag filter + */ +# define R300_TX_MIN_FILTER_ANISO_NEAREST (0 << 13) +# define R300_TX_MIN_FILTER_ANISO_LINEAR (0 << 13) +# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13) +# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (2 << 13) +# define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) ) +# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21) +# define R300_TX_MAX_ANISO_2_TO_1 (2 << 21) +# define R300_TX_MAX_ANISO_4_TO_1 (4 << 21) +# define R300_TX_MAX_ANISO_8_TO_1 (6 << 21) +# define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) +# define R300_TX_MAX_ANISO_MASK (14 << 21) + +#define R300_TX_FILTER1_0 0x4440 +# define R300_CHROMA_KEY_MODE_DISABLE 0 +# define R300_CHROMA_KEY_FORCE 1 +# define R300_CHROMA_KEY_BLEND 2 +# define R300_MC_ROUND_NORMAL (0<<2) +# define R300_MC_ROUND_MPEG4 (1<<2) +# define R300_LOD_BIAS_MASK 0x1fff +# define R300_EDGE_ANISO_EDGE_DIAG (0<<13) +# define R300_EDGE_ANISO_EDGE_ONLY (1<<13) +# define R300_MC_COORD_TRUNCATE_DISABLE (0<<14) +# define R300_MC_COORD_TRUNCATE_MPEG (1<<14) +# define R300_TX_TRI_PERF_0_8 (0<<15) +# define R300_TX_TRI_PERF_1_8 (1<<15) +# define R300_TX_TRI_PERF_1_4 (2<<15) +# define R300_TX_TRI_PERF_3_8 (3<<15) +# define R300_ANISO_THRESHOLD_MASK (7<<17) + +#define R300_TX_SIZE_0 0x4480 +# define R300_TX_WIDTHMASK_SHIFT 0 +# define R300_TX_WIDTHMASK_MASK (2047 << 0) +# define R300_TX_HEIGHTMASK_SHIFT 11 +# define R300_TX_HEIGHTMASK_MASK (2047 << 11) +# define R300_TX_UNK23 (1 << 23) +# define R300_TX_MAX_MIP_LEVEL_SHIFT 26 +# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 26) +# define R300_TX_SIZE_PROJECTED (1<<30) +# define R300_TX_SIZE_TXPITCH_EN (1<<31) +#define R300_TX_FORMAT_0 0x44C0 + /* The interpretation of the format word by Wladimir van der Laan */ + /* The X, Y, Z and W refer to the layout of the components. + They are given meanings as R, G, B and Alpha by the swizzle + specification */ +# define R300_TX_FORMAT_X8 0x0 +# define R300_TX_FORMAT_X16 0x1 +# define R300_TX_FORMAT_Y4X4 0x2 +# define R300_TX_FORMAT_Y8X8 0x3 +# define R300_TX_FORMAT_Y16X16 0x4 +# define R300_TX_FORMAT_Z3Y3X2 0x5 +# define R300_TX_FORMAT_Z5Y6X5 0x6 +# define R300_TX_FORMAT_Z6Y5X5 0x7 +# define R300_TX_FORMAT_Z11Y11X10 0x8 +# define R300_TX_FORMAT_Z10Y11X11 0x9 +# define R300_TX_FORMAT_W4Z4Y4X4 0xA +# define R300_TX_FORMAT_W1Z5Y5X5 0xB +# define R300_TX_FORMAT_W8Z8Y8X8 0xC +# define R300_TX_FORMAT_W2Z10Y10X10 0xD +# define R300_TX_FORMAT_W16Z16Y16X16 0xE +# define R300_TX_FORMAT_DXT1 0xF +# define R300_TX_FORMAT_DXT3 0x10 +# define R300_TX_FORMAT_DXT5 0x11 +# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ +# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ +# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ +# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ + /* 0x16 - some 16 bit green format.. ?? */ +# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_CUBIC_MAP (1 << 26) + + /* gap */ + /* Floating point formats */ + /* Note - hardware supports both 16 and 32 bit floating point */ +# define R300_TX_FORMAT_FL_I16 0x18 +# define R300_TX_FORMAT_FL_I16A16 0x19 +# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A +# define R300_TX_FORMAT_FL_I32 0x1B +# define R300_TX_FORMAT_FL_I32A32 0x1C +# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D +# define R300_TX_FORMAT_ATI2N 0x1F + /* alpha modes, convenience mostly */ + /* if you have alpha, pick constant appropriate to the + number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ +# define R300_TX_FORMAT_ALPHA_1CH 0x000 +# define R300_TX_FORMAT_ALPHA_2CH 0x200 +# define R300_TX_FORMAT_ALPHA_4CH 0x600 +# define R300_TX_FORMAT_ALPHA_NONE 0xA00 + /* Swizzling */ + /* constants */ +# define R300_TX_FORMAT_X 0 +# define R300_TX_FORMAT_Y 1 +# define R300_TX_FORMAT_Z 2 +# define R300_TX_FORMAT_W 3 +# define R300_TX_FORMAT_ZERO 4 +# define R300_TX_FORMAT_ONE 5 + /* 2.0*Z, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_Z 6 + /* 2.0*W, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_W 7 + +# define R300_TX_FORMAT_B_SHIFT 18 +# define R300_TX_FORMAT_G_SHIFT 15 +# define R300_TX_FORMAT_R_SHIFT 12 +# define R300_TX_FORMAT_A_SHIFT 9 + /* Convenience macro to take care of layout and swizzling */ +# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) ( \ + ((R300_TX_FORMAT_##B)< 0.5, return ARG0, else return ARG1 + * - CMP: If ARG2 < 0, return ARG1, else return ARG0 + * - FLR: use FRC+MAD + * - XPD: use MAD+MAD + * - SGE, SLT: use MAD+CMP + * - RSQ: use ABS modifier for argument + * - Use OUTC_REPL_ALPHA to write results of an alpha-only operation + * (e.g. RCP) into color register + * - apparently, there's no quick DST operation + * - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2" + * - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0" + * - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1" + * + * Operand selection + * First stage selects three sources from the available registers and + * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha). + * fglrx sorts the three source fields: Registers before constants, + * lower indices before higher indices; I do not know whether this is + * necessary. + * + * fglrx fills unused sources with "read constant 0" + * According to specs, you cannot select more than two different constants. + * + * Second stage selects the operands from the sources. This is defined in + * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants + * zero and one. + * Swizzling and negation happens in this stage, as well. + * + * Important: Color and alpha seem to be mostly separate, i.e. their sources + * selection appears to be fully independent (the register storage is probably + * physically split into a color and an alpha section). + * However (because of the apparent physical split), there is some interaction + * WRT swizzling. If, for example, you want to load an R component into an + * Alpha operand, this R component is taken from a *color* source, not from + * an alpha source. The corresponding register doesn't even have to appear in + * the alpha sources list. (I hope this all makes sense to you) + * + * Destination selection + * The destination register index is in FPI1 (color) and FPI3 (alpha) + * together with enable bits. + * There are separate enable bits for writing into temporary registers + * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* + * /DSTA_OUTPUT). You can write to both at once, or not write at all (the + * same index must be used for both). + * + * Note: There is a special form for LRP + * - Argument order is the same as in ARB_fragment_program. + * - Operation is MAD + * - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP + * - Set FPI0/FPI2_SPECIAL_LRP + * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD + */ +#define R300_PFS_INSTR1_0 0x46C0 +# define R300_FPI1_SRC0C_SHIFT 0 +# define R300_FPI1_SRC0C_MASK (31 << 0) +# define R300_FPI1_SRC0C_CONST (1 << 5) +# define R300_FPI1_SRC1C_SHIFT 6 +# define R300_FPI1_SRC1C_MASK (31 << 6) +# define R300_FPI1_SRC1C_CONST (1 << 11) +# define R300_FPI1_SRC2C_SHIFT 12 +# define R300_FPI1_SRC2C_MASK (31 << 12) +# define R300_FPI1_SRC2C_CONST (1 << 17) +# define R300_FPI1_SRC_MASK 0x0003ffff +# define R300_FPI1_DSTC_SHIFT 18 +# define R300_FPI1_DSTC_MASK (31 << 18) +# define R300_FPI1_DSTC_REG_MASK_SHIFT 23 +# define R300_FPI1_DSTC_REG_X (1 << 23) +# define R300_FPI1_DSTC_REG_Y (1 << 24) +# define R300_FPI1_DSTC_REG_Z (1 << 25) +# define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26 +# define R300_FPI1_DSTC_OUTPUT_X (1 << 26) +# define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) +# define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) + +#define R300_PFS_INSTR3_0 0x47C0 +# define R300_FPI3_SRC0A_SHIFT 0 +# define R300_FPI3_SRC0A_MASK (31 << 0) +# define R300_FPI3_SRC0A_CONST (1 << 5) +# define R300_FPI3_SRC1A_SHIFT 6 +# define R300_FPI3_SRC1A_MASK (31 << 6) +# define R300_FPI3_SRC1A_CONST (1 << 11) +# define R300_FPI3_SRC2A_SHIFT 12 +# define R300_FPI3_SRC2A_MASK (31 << 12) +# define R300_FPI3_SRC2A_CONST (1 << 17) +# define R300_FPI3_SRC_MASK 0x0003ffff +# define R300_FPI3_DSTA_SHIFT 18 +# define R300_FPI3_DSTA_MASK (31 << 18) +# define R300_FPI3_DSTA_REG (1 << 23) +# define R300_FPI3_DSTA_OUTPUT (1 << 24) +# define R300_FPI3_DSTA_DEPTH (1 << 27) + +#define R300_PFS_INSTR0_0 0x48C0 +# define R300_FPI0_ARGC_SRC0C_XYZ 0 +# define R300_FPI0_ARGC_SRC0C_XXX 1 +# define R300_FPI0_ARGC_SRC0C_YYY 2 +# define R300_FPI0_ARGC_SRC0C_ZZZ 3 +# define R300_FPI0_ARGC_SRC1C_XYZ 4 +# define R300_FPI0_ARGC_SRC1C_XXX 5 +# define R300_FPI0_ARGC_SRC1C_YYY 6 +# define R300_FPI0_ARGC_SRC1C_ZZZ 7 +# define R300_FPI0_ARGC_SRC2C_XYZ 8 +# define R300_FPI0_ARGC_SRC2C_XXX 9 +# define R300_FPI0_ARGC_SRC2C_YYY 10 +# define R300_FPI0_ARGC_SRC2C_ZZZ 11 +# define R300_FPI0_ARGC_SRC0A 12 +# define R300_FPI0_ARGC_SRC1A 13 +# define R300_FPI0_ARGC_SRC2A 14 +# define R300_FPI0_ARGC_SRC1C_LRP 15 +# define R300_FPI0_ARGC_ZERO 20 +# define R300_FPI0_ARGC_ONE 21 + /* GUESS */ +# define R300_FPI0_ARGC_HALF 22 +# define R300_FPI0_ARGC_SRC0C_YZX 23 +# define R300_FPI0_ARGC_SRC1C_YZX 24 +# define R300_FPI0_ARGC_SRC2C_YZX 25 +# define R300_FPI0_ARGC_SRC0C_ZXY 26 +# define R300_FPI0_ARGC_SRC1C_ZXY 27 +# define R300_FPI0_ARGC_SRC2C_ZXY 28 +# define R300_FPI0_ARGC_SRC0CA_WZY 29 +# define R300_FPI0_ARGC_SRC1CA_WZY 30 +# define R300_FPI0_ARGC_SRC2CA_WZY 31 + +# define R300_FPI0_ARG0C_SHIFT 0 +# define R300_FPI0_ARG0C_MASK (31 << 0) +# define R300_FPI0_ARG0C_NEG (1 << 5) +# define R300_FPI0_ARG0C_ABS (1 << 6) +# define R300_FPI0_ARG1C_SHIFT 7 +# define R300_FPI0_ARG1C_MASK (31 << 7) +# define R300_FPI0_ARG1C_NEG (1 << 12) +# define R300_FPI0_ARG1C_ABS (1 << 13) +# define R300_FPI0_ARG2C_SHIFT 14 +# define R300_FPI0_ARG2C_MASK (31 << 14) +# define R300_FPI0_ARG2C_NEG (1 << 19) +# define R300_FPI0_ARG2C_ABS (1 << 20) +# define R300_FPI0_SPECIAL_LRP (1 << 21) +# define R300_FPI0_OUTC_MAD (0 << 23) +# define R300_FPI0_OUTC_DP3 (1 << 23) +# define R300_FPI0_OUTC_DP4 (2 << 23) +# define R300_FPI0_OUTC_MIN (4 << 23) +# define R300_FPI0_OUTC_MAX (5 << 23) +# define R300_FPI0_OUTC_CMPH (7 << 23) +# define R300_FPI0_OUTC_CMP (8 << 23) +# define R300_FPI0_OUTC_FRC (9 << 23) +# define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) +# define R300_FPI0_OUTC_SAT (1 << 30) +# define R300_FPI0_INSERT_NOP (1 << 31) + +#define R300_PFS_INSTR2_0 0x49C0 +# define R300_FPI2_ARGA_SRC0C_X 0 +# define R300_FPI2_ARGA_SRC0C_Y 1 +# define R300_FPI2_ARGA_SRC0C_Z 2 +# define R300_FPI2_ARGA_SRC1C_X 3 +# define R300_FPI2_ARGA_SRC1C_Y 4 +# define R300_FPI2_ARGA_SRC1C_Z 5 +# define R300_FPI2_ARGA_SRC2C_X 6 +# define R300_FPI2_ARGA_SRC2C_Y 7 +# define R300_FPI2_ARGA_SRC2C_Z 8 +# define R300_FPI2_ARGA_SRC0A 9 +# define R300_FPI2_ARGA_SRC1A 10 +# define R300_FPI2_ARGA_SRC2A 11 +# define R300_FPI2_ARGA_SRC1A_LRP 15 +# define R300_FPI2_ARGA_ZERO 16 +# define R300_FPI2_ARGA_ONE 17 + /* GUESS */ +# define R300_FPI2_ARGA_HALF 18 +# define R300_FPI2_ARG0A_SHIFT 0 +# define R300_FPI2_ARG0A_MASK (31 << 0) +# define R300_FPI2_ARG0A_NEG (1 << 5) + /* GUESS */ +# define R300_FPI2_ARG0A_ABS (1 << 6) +# define R300_FPI2_ARG1A_SHIFT 7 +# define R300_FPI2_ARG1A_MASK (31 << 7) +# define R300_FPI2_ARG1A_NEG (1 << 12) + /* GUESS */ +# define R300_FPI2_ARG1A_ABS (1 << 13) +# define R300_FPI2_ARG2A_SHIFT 14 +# define R300_FPI2_ARG2A_MASK (31 << 14) +# define R300_FPI2_ARG2A_NEG (1 << 19) + /* GUESS */ +# define R300_FPI2_ARG2A_ABS (1 << 20) +# define R300_FPI2_SPECIAL_LRP (1 << 21) +# define R300_FPI2_OUTA_MAD (0 << 23) +# define R300_FPI2_OUTA_DP4 (1 << 23) +# define R300_FPI2_OUTA_MIN (2 << 23) +# define R300_FPI2_OUTA_MAX (3 << 23) +# define R300_FPI2_OUTA_CMP (6 << 23) +# define R300_FPI2_OUTA_FRC (7 << 23) +# define R300_FPI2_OUTA_EX2 (8 << 23) +# define R300_FPI2_OUTA_LG2 (9 << 23) +# define R300_FPI2_OUTA_RCP (10 << 23) +# define R300_FPI2_OUTA_RSQ (11 << 23) +# define R300_FPI2_OUTA_SAT (1 << 30) +# define R300_FPI2_UNKNOWN_31 (1 << 31) +/* END: Fragment program instruction set */ + +/* Fog state and color */ +#define R300_RE_FOG_STATE 0x4BC0 +# define R300_FOG_ENABLE (1 << 0) +# define R300_FOG_MODE_LINEAR (0 << 1) +# define R300_FOG_MODE_EXP (1 << 1) +# define R300_FOG_MODE_EXP2 (2 << 1) +# define R300_FOG_MODE_MASK (3 << 1) +#define R300_FOG_COLOR_R 0x4BC8 +#define R300_FOG_COLOR_G 0x4BCC +#define R300_FOG_COLOR_B 0x4BD0 + +#define R300_PP_ALPHA_TEST 0x4BD4 +# define R300_REF_ALPHA_MASK 0x000000ff +# define R300_ALPHA_TEST_FAIL (0 << 8) +# define R300_ALPHA_TEST_LESS (1 << 8) +# define R300_ALPHA_TEST_LEQUAL (3 << 8) +# define R300_ALPHA_TEST_EQUAL (2 << 8) +# define R300_ALPHA_TEST_GEQUAL (6 << 8) +# define R300_ALPHA_TEST_GREATER (4 << 8) +# define R300_ALPHA_TEST_NEQUAL (5 << 8) +# define R300_ALPHA_TEST_PASS (7 << 8) +# define R300_ALPHA_TEST_OP_MASK (7 << 8) +# define R300_ALPHA_TEST_ENABLE (1 << 11) + +/* gap */ + +/* Fragment program parameters in 7.16 floating point */ +#define R300_PFS_PARAM_0_X 0x4C00 +#define R300_PFS_PARAM_0_Y 0x4C04 +#define R300_PFS_PARAM_0_Z 0x4C08 +#define R300_PFS_PARAM_0_W 0x4C0C +/* GUESS: PARAM_31 is last, based on native limits reported by fglrx */ +#define R300_PFS_PARAM_31_X 0x4DF0 +#define R300_PFS_PARAM_31_Y 0x4DF4 +#define R300_PFS_PARAM_31_Z 0x4DF8 +#define R300_PFS_PARAM_31_W 0x4DFC + +/* Notes: + * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in + * the application + * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND + * are set to the same + * function (both registers are always set up completely in any case) + * - Most blend flags are simply copied from R200 and not tested yet + */ +#define R300_RB3D_CBLEND 0x4E04 +#define R300_RB3D_ABLEND 0x4E08 +/* the following only appear in CBLEND */ +# define R300_BLEND_ENABLE (1 << 0) +# define R300_BLEND_UNKNOWN (3 << 1) +# define R300_BLEND_NO_SEPARATE (1 << 3) +/* the following are shared between CBLEND and ABLEND */ +# define R300_FCN_MASK (3 << 12) +# define R300_COMB_FCN_ADD_CLAMP (0 << 12) +# define R300_COMB_FCN_ADD_NOCLAMP (1 << 12) +# define R300_COMB_FCN_SUB_CLAMP (2 << 12) +# define R300_COMB_FCN_SUB_NOCLAMP (3 << 12) +# define R300_COMB_FCN_MIN (4 << 12) +# define R300_COMB_FCN_MAX (5 << 12) +# define R300_COMB_FCN_RSUB_CLAMP (6 << 12) +# define R300_COMB_FCN_RSUB_NOCLAMP (7 << 12) +# define R300_BLEND_GL_ZERO (32) +# define R300_BLEND_GL_ONE (33) +# define R300_BLEND_GL_SRC_COLOR (34) +# define R300_BLEND_GL_ONE_MINUS_SRC_COLOR (35) +# define R300_BLEND_GL_DST_COLOR (36) +# define R300_BLEND_GL_ONE_MINUS_DST_COLOR (37) +# define R300_BLEND_GL_SRC_ALPHA (38) +# define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA (39) +# define R300_BLEND_GL_DST_ALPHA (40) +# define R300_BLEND_GL_ONE_MINUS_DST_ALPHA (41) +# define R300_BLEND_GL_SRC_ALPHA_SATURATE (42) +# define R300_BLEND_GL_CONST_COLOR (43) +# define R300_BLEND_GL_ONE_MINUS_CONST_COLOR (44) +# define R300_BLEND_GL_CONST_ALPHA (45) +# define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA (46) +# define R300_BLEND_MASK (63) +# define R300_SRC_BLEND_SHIFT (16) +# define R300_DST_BLEND_SHIFT (24) +#define R300_RB3D_BLEND_COLOR 0x4E10 +#define R300_RB3D_COLORMASK 0x4E0C +# define R300_COLORMASK0_B (1<<0) +# define R300_COLORMASK0_G (1<<1) +# define R300_COLORMASK0_R (1<<2) +# define R300_COLORMASK0_A (1<<3) + +/* gap */ + +#define R300_RB3D_COLOROFFSET0 0x4E28 +# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */ +#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */ +#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */ +#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */ + +/* gap */ + +/* Bit 16: Larger tiles + * Bit 17: 4x2 tiles + * Bit 18: Extremely weird tile like, but some pixels duplicated? + */ +#define R300_RB3D_COLORPITCH0 0x4E38 +# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */ +# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */ +# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */ +# define R300_COLOR_MICROTILE_SQUARE_ENABLE (2 << 17) +# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */ +# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */ +# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */ +# define R300_COLOR_FORMAT_RGB565 (2 << 22) +# define R300_COLOR_FORMAT_ARGB8888 (3 << 22) +#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */ +#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */ +#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */ + +#define R300_RB3D_AARESOLVE_OFFSET 0x4E80 +#define R300_RB3D_AARESOLVE_PITCH 0x4E84 +#define R300_RB3D_AARESOLVE_CTL 0x4E88 +/* gap */ + +/* Guess by Vladimir. + * Set to 0A before 3D operations, set to 02 afterwards. + */ +/*#define R300_RB3D_DSTCACHE_CTLSTAT 0x4E4C*/ +# define R300_RB3D_DSTCACHE_UNKNOWN_02 0x00000002 +# define R300_RB3D_DSTCACHE_UNKNOWN_0A 0x0000000A + +/* gap */ +/* There seems to be no "write only" setting, so use Z-test = ALWAYS + * for this. + * Bit (1<<8) is the "test" bit. so plain write is 6 - vd + */ +#define R300_ZB_CNTL 0x4F00 +# define R300_STENCIL_ENABLE (1 << 0) +# define R300_Z_ENABLE (1 << 1) +# define R300_Z_WRITE_ENABLE (1 << 2) +# define R300_Z_SIGNED_COMPARE (1 << 3) +# define R300_STENCIL_FRONT_BACK (1 << 4) + +#define R300_ZB_ZSTENCILCNTL 0x4f04 + /* functions */ +# define R300_ZS_NEVER 0 +# define R300_ZS_LESS 1 +# define R300_ZS_LEQUAL 2 +# define R300_ZS_EQUAL 3 +# define R300_ZS_GEQUAL 4 +# define R300_ZS_GREATER 5 +# define R300_ZS_NOTEQUAL 6 +# define R300_ZS_ALWAYS 7 +# define R300_ZS_MASK 7 + /* operations */ +# define R300_ZS_KEEP 0 +# define R300_ZS_ZERO 1 +# define R300_ZS_REPLACE 2 +# define R300_ZS_INCR 3 +# define R300_ZS_DECR 4 +# define R300_ZS_INVERT 5 +# define R300_ZS_INCR_WRAP 6 +# define R300_ZS_DECR_WRAP 7 +# define R300_Z_FUNC_SHIFT 0 + /* front and back refer to operations done for front + and back faces, i.e. separate stencil function support */ +# define R300_S_FRONT_FUNC_SHIFT 3 +# define R300_S_FRONT_SFAIL_OP_SHIFT 6 +# define R300_S_FRONT_ZPASS_OP_SHIFT 9 +# define R300_S_FRONT_ZFAIL_OP_SHIFT 12 +# define R300_S_BACK_FUNC_SHIFT 15 +# define R300_S_BACK_SFAIL_OP_SHIFT 18 +# define R300_S_BACK_ZPASS_OP_SHIFT 21 +# define R300_S_BACK_ZFAIL_OP_SHIFT 24 + +#define R300_ZB_STENCILREFMASK 0x4f08 +# define R300_STENCILREF_SHIFT 0 +# define R300_STENCILREF_MASK 0x000000ff +# define R300_STENCILMASK_SHIFT 8 +# define R300_STENCILMASK_MASK 0x0000ff00 +# define R300_STENCILWRITEMASK_SHIFT 16 +# define R300_STENCILWRITEMASK_MASK 0x00ff0000 + +/* gap */ + +#define R300_ZB_FORMAT 0x4f10 +# define R300_DEPTHFORMAT_16BIT_INT_Z (0 << 0) +# define R300_DEPTHFORMAT_16BIT_13E3 (1 << 0) +# define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL (2 << 0) +/* reserved up to (15 << 0) */ +# define R300_INVERT_13E3_LEADING_ONES (0 << 4) +# define R300_INVERT_13E3_LEADING_ZEROS (1 << 4) + +#define R300_ZB_ZTOP 0x4F14 +# define R300_ZTOP_DISABLE (0 << 0) +# define R300_ZTOP_ENABLE (1 << 0) + +/* gap */ + +#define R300_ZB_ZCACHE_CTLSTAT 0x4f18 +# define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT (0 << 0) +# define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0) +# define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT (0 << 1) +# define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE (1 << 1) +# define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE (0 << 31) +# define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY (1 << 31) + +#define R300_ZB_BW_CNTL 0x4f1c +# define R300_HIZ_DISABLE (0 << 0) +# define R300_HIZ_ENABLE (1 << 0) +# define R300_HIZ_MIN (0 << 1) +# define R300_HIZ_MAX (1 << 1) +# define R300_FAST_FILL_DISABLE (0 << 2) +# define R300_FAST_FILL_ENABLE (1 << 2) +# define R300_RD_COMP_DISABLE (0 << 3) +# define R300_RD_COMP_ENABLE (1 << 3) +# define R300_WR_COMP_DISABLE (0 << 4) +# define R300_WR_COMP_ENABLE (1 << 4) +# define R300_ZB_CB_CLEAR_RMW (0 << 5) +# define R300_ZB_CB_CLEAR_CACHE_LINEAR (1 << 5) +# define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE (0 << 6) +# define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE (1 << 6) + +# define R500_ZEQUAL_OPTIMIZE_ENABLE (0 << 7) +# define R500_ZEQUAL_OPTIMIZE_DISABLE (1 << 7) +# define R500_SEQUAL_OPTIMIZE_ENABLE (0 << 8) +# define R500_SEQUAL_OPTIMIZE_DISABLE (1 << 8) + +# define R500_BMASK_ENABLE (0 << 10) +# define R500_BMASK_DISABLE (1 << 10) +# define R500_HIZ_EQUAL_REJECT_DISABLE (0 << 11) +# define R500_HIZ_EQUAL_REJECT_ENABLE (1 << 11) +# define R500_HIZ_FP_EXP_BITS_DISABLE (0 << 12) +# define R500_HIZ_FP_EXP_BITS_1 (1 << 12) +# define R500_HIZ_FP_EXP_BITS_2 (2 << 12) +# define R500_HIZ_FP_EXP_BITS_3 (3 << 12) +# define R500_HIZ_FP_EXP_BITS_4 (4 << 12) +# define R500_HIZ_FP_EXP_BITS_5 (5 << 12) +# define R500_HIZ_FP_INVERT_LEADING_ONES (0 << 15) +# define R500_HIZ_FP_INVERT_LEADING_ZEROS (1 << 15) +# define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE (0 << 16) +# define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE (1 << 16) +# define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE (0 << 17) +# define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE (1 << 17) +# define R500_PEQ_PACKING_DISABLE (0 << 18) +# define R500_PEQ_PACKING_ENABLE (1 << 18) +# define R500_COVERED_PTR_MASKING_DISABLE (0 << 18) +# define R500_COVERED_PTR_MASKING_ENABLE (1 << 18) + + +/* gap */ + +/* Z Buffer Address Offset. + * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles. + */ +#define R300_ZB_DEPTHOFFSET 0x4f20 + +/* Z Buffer Pitch and Endian Control */ +#define R300_ZB_DEPTHPITCH 0x4f24 +# define R300_DEPTHPITCH_MASK 0x00003FFC +# define R300_DEPTHMACROTILE_DISABLE (0 << 16) +# define R300_DEPTHMACROTILE_ENABLE (1 << 16) +# define R300_DEPTHMICROTILE_LINEAR (0 << 17) +# define R300_DEPTHMICROTILE_TILED (1 << 17) +# define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17) +# define R300_DEPTHENDIAN_NO_SWAP (0 << 18) +# define R300_DEPTHENDIAN_WORD_SWAP (1 << 18) +# define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18) +# define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18) + +/* Z Buffer Clear Value */ +#define R300_ZB_DEPTHCLEARVALUE 0x4f28 + +#define R300_ZB_ZMASK_OFFSET 0x4f30 +#define R300_ZB_ZMASK_PITCH 0x4f34 +#define R300_ZB_ZMASK_WRINDEX 0x4f38 +#define R300_ZB_ZMASK_DWORD 0x4f3c +#define R300_ZB_ZMASK_RDINDEX 0x4f40 + +/* Hierarchical Z Memory Offset */ +#define R300_ZB_HIZ_OFFSET 0x4f44 + +/* Hierarchical Z Write Index */ +#define R300_ZB_HIZ_WRINDEX 0x4f48 + +/* Hierarchical Z Data */ +#define R300_ZB_HIZ_DWORD 0x4f4c + +/* Hierarchical Z Read Index */ +#define R300_ZB_HIZ_RDINDEX 0x4f50 + +/* Hierarchical Z Pitch */ +#define R300_ZB_HIZ_PITCH 0x4f54 + +/* Z Buffer Z Pass Counter Data */ +#define R300_ZB_ZPASS_DATA 0x4f58 + +/* Z Buffer Z Pass Counter Address */ +#define R300_ZB_ZPASS_ADDR 0x4f5c + +/* Depth buffer X and Y coordinate offset */ +#define R300_ZB_DEPTHXY_OFFSET 0x4f60 +# define R300_DEPTHX_OFFSET_SHIFT 1 +# define R300_DEPTHX_OFFSET_MASK 0x000007FE +# define R300_DEPTHY_OFFSET_SHIFT 17 +# define R300_DEPTHY_OFFSET_MASK 0x07FE0000 + +/* Sets the fifo sizes */ +#define R500_ZB_FIFO_SIZE 0x4fd0 +# define R500_OP_FIFO_SIZE_FULL (0 << 0) +# define R500_OP_FIFO_SIZE_HALF (1 << 0) +# define R500_OP_FIFO_SIZE_QUATER (2 << 0) +# define R500_OP_FIFO_SIZE_EIGTHS (4 << 0) + +/* Stencil Reference Value and Mask for backfacing quads */ +/* R300_ZB_STENCILREFMASK handles front face */ +#define R500_ZB_STENCILREFMASK_BF 0x4fd4 +# define R500_STENCILREF_SHIFT 0 +# define R500_STENCILREF_MASK 0x000000ff +# define R500_STENCILMASK_SHIFT 8 +# define R500_STENCILMASK_MASK 0x0000ff00 +# define R500_STENCILWRITEMASK_SHIFT 16 +# define R500_STENCILWRITEMASK_MASK 0x00ff0000 + +/* BEGIN: Vertex program instruction set */ + +/* Every instruction is four dwords long: + * DWORD 0: output and opcode + * DWORD 1: first argument + * DWORD 2: second argument + * DWORD 3: third argument + * + * Notes: + * - ABS r, a is implemented as MAX r, a, -a + * - MOV is implemented as ADD to zero + * - XPD is implemented as MUL + MAD + * - FLR is implemented as FRC + ADD + * - apparently, fglrx tries to schedule instructions so that there is at + * least one instruction between the write to a temporary and the first + * read from said temporary; however, violations of this scheduling are + * allowed + * - register indices seem to be unrelated with OpenGL aliasing to + * conventional state + * - only one attribute and one parameter can be loaded at a time; however, + * the same attribute/parameter can be used for more than one argument + * - the second software argument for POW is the third hardware argument + * (no idea why) + * - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2 + * + * There is some magic surrounding LIT: + * The single argument is replicated across all three inputs, but swizzled: + * First argument: xyzy + * Second argument: xyzx + * Third argument: xyzw + * Whenever the result is used later in the fragment program, fglrx forces + * x and w to be 1.0 in the input selection; I don't know whether this is + * strictly necessary + */ +#define R300_VPI_OUT_OP_DOT (1 << 0) +#define R300_VPI_OUT_OP_MUL (2 << 0) +#define R300_VPI_OUT_OP_ADD (3 << 0) +#define R300_VPI_OUT_OP_MAD (4 << 0) +#define R300_VPI_OUT_OP_DST (5 << 0) +#define R300_VPI_OUT_OP_FRC (6 << 0) +#define R300_VPI_OUT_OP_MAX (7 << 0) +#define R300_VPI_OUT_OP_MIN (8 << 0) +#define R300_VPI_OUT_OP_SGE (9 << 0) +#define R300_VPI_OUT_OP_SLT (10 << 0) + /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */ +#define R300_VPI_OUT_OP_UNK12 (12 << 0) +#define R300_VPI_OUT_OP_ARL (13 << 0) +#define R300_VPI_OUT_OP_EXP (65 << 0) +#define R300_VPI_OUT_OP_LOG (66 << 0) + /* Used in fog computations, scalar(scalar) */ +#define R300_VPI_OUT_OP_UNK67 (67 << 0) +#define R300_VPI_OUT_OP_LIT (68 << 0) +#define R300_VPI_OUT_OP_POW (69 << 0) +#define R300_VPI_OUT_OP_RCP (70 << 0) +#define R300_VPI_OUT_OP_RSQ (72 << 0) + /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */ +#define R300_VPI_OUT_OP_UNK73 (73 << 0) +#define R300_VPI_OUT_OP_EX2 (75 << 0) +#define R300_VPI_OUT_OP_LG2 (76 << 0) +#define R300_VPI_OUT_OP_MAD_2 (128 << 0) + /* all temps, vector(scalar, vector, vector) */ +#define R300_VPI_OUT_OP_UNK129 (129 << 0) + +#define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8) +#define R300_VPI_OUT_REG_CLASS_ADDR (1 << 8) +#define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8) +#define R300_VPI_OUT_REG_CLASS_MASK (31 << 8) + +#define R300_VPI_OUT_REG_INDEX_SHIFT 13 + /* GUESS based on fglrx native limits */ +#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) + +#define R300_VPI_OUT_WRITE_X (1 << 20) +#define R300_VPI_OUT_WRITE_Y (1 << 21) +#define R300_VPI_OUT_WRITE_Z (1 << 22) +#define R300_VPI_OUT_WRITE_W (1 << 23) + +#define R300_VPI_IN_REG_CLASS_TEMPORARY (0 << 0) +#define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0) +#define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0) +#define R300_VPI_IN_REG_CLASS_NONE (9 << 0) +#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) + +#define R300_VPI_IN_REG_INDEX_SHIFT 5 + /* GUESS based on fglrx native limits */ +#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) + +/* The R300 can select components from the input register arbitrarily. + * Use the following constants, shifted by the component shift you + * want to select + */ +#define R300_VPI_IN_SELECT_X 0 +#define R300_VPI_IN_SELECT_Y 1 +#define R300_VPI_IN_SELECT_Z 2 +#define R300_VPI_IN_SELECT_W 3 +#define R300_VPI_IN_SELECT_ZERO 4 +#define R300_VPI_IN_SELECT_ONE 5 +#define R300_VPI_IN_SELECT_MASK 7 + +#define R300_VPI_IN_X_SHIFT 13 +#define R300_VPI_IN_Y_SHIFT 16 +#define R300_VPI_IN_Z_SHIFT 19 +#define R300_VPI_IN_W_SHIFT 22 + +#define R300_VPI_IN_NEG_X (1 << 25) +#define R300_VPI_IN_NEG_Y (1 << 26) +#define R300_VPI_IN_NEG_Z (1 << 27) +#define R300_VPI_IN_NEG_W (1 << 28) +/* END: Vertex program instruction set */ + +/* BEGIN: Packet 3 commands */ + +/* A primitive emission dword. */ +#define R300_PRIM_TYPE_NONE (0 << 0) +#define R300_PRIM_TYPE_POINT (1 << 0) +#define R300_PRIM_TYPE_LINE (2 << 0) +#define R300_PRIM_TYPE_LINE_STRIP (3 << 0) +#define R300_PRIM_TYPE_TRI_LIST (4 << 0) +#define R300_PRIM_TYPE_TRI_FAN (5 << 0) +#define R300_PRIM_TYPE_TRI_STRIP (6 << 0) +#define R300_PRIM_TYPE_TRI_TYPE2 (7 << 0) +#define R300_PRIM_TYPE_RECT_LIST (8 << 0) +#define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) +#define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) + /* GUESS (based on r200) */ +#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) +#define R300_PRIM_TYPE_LINE_LOOP (12 << 0) +#define R300_PRIM_TYPE_QUADS (13 << 0) +#define R300_PRIM_TYPE_QUAD_STRIP (14 << 0) +#define R300_PRIM_TYPE_POLYGON (15 << 0) +#define R300_PRIM_TYPE_MASK 0xF +#define R300_PRIM_WALK_IND (1 << 4) +#define R300_PRIM_WALK_LIST (2 << 4) +#define R300_PRIM_WALK_RING (3 << 4) +#define R300_PRIM_WALK_MASK (3 << 4) + /* GUESS (based on r200) */ +#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) +#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) +#define R300_PRIM_NUM_VERTICES_SHIFT 16 +#define R300_PRIM_NUM_VERTICES_MASK 0xffff + +/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR. + * Two parameter dwords: + * 0. The first parameter appears to be always 0 + * 1. The second parameter is a standard primitive emission dword. + */ +#define R300_PACKET3_3D_DRAW_VBUF 0x00002800 + +/* Specify the full set of vertex arrays as (address, stride). + * The first parameter is the number of vertex arrays specified. + * The rest of the command is a variable length list of blocks, where + * each block is three dwords long and specifies two arrays. + * The first dword of a block is split into two words, the lower significant + * word refers to the first array, the more significant word to the second + * array in the block. + * The low byte of each word contains the size of an array entry in dwords, + * the high byte contains the stride of the array. + * The second dword of a block contains the pointer to the first array, + * the third dword of a block contains the pointer to the second array. + * Note that if the total number of arrays is odd, the third dword of + * the last block is omitted. + */ +#define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00 + +#define R300_PACKET3_INDX_BUFFER 0x00003300 +# define R300_EB_UNK1_SHIFT 24 +# define R300_EB_UNK1 (0x80<<24) +# define R300_EB_UNK2 0x0810 +#define R300_PACKET3_3D_DRAW_VBUF_2 0x00003400 +#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600 + +/* END: Packet 3 commands */ + + +/* Color formats for 2d packets + */ +#define R300_CP_COLOR_FORMAT_CI8 2 +#define R300_CP_COLOR_FORMAT_ARGB1555 3 +#define R300_CP_COLOR_FORMAT_RGB565 4 +#define R300_CP_COLOR_FORMAT_ARGB8888 6 +#define R300_CP_COLOR_FORMAT_RGB332 7 +#define R300_CP_COLOR_FORMAT_RGB8 9 +#define R300_CP_COLOR_FORMAT_ARGB4444 15 + +/* + * CP type-3 packets + */ +#define R300_CP_CMD_BITBLT_MULTI 0xC0009B00 + +#define R500_VAP_INDEX_OFFSET 0x208c + +#define R500_GA_US_VECTOR_INDEX 0x4250 +#define R500_GA_US_VECTOR_DATA 0x4254 + +#define R500_RS_IP_0 0x4074 +#define R500_RS_INST_0 0x4320 + +#define R500_US_CONFIG 0x4600 + +#define R500_US_FC_CTRL 0x4624 +#define R500_US_CODE_ADDR 0x4630 + +#define R500_RB3D_COLOR_CLEAR_VALUE_AR 0x46c0 +#define R500_RB3D_CONSTANT_COLOR_AR 0x4ef8 + +#define R300_SU_REG_DEST 0x42c8 +#define RV530_FG_ZBREG_DEST 0x4be8 +#define R300_ZB_ZPASS_DATA 0x4f58 +#define R300_ZB_ZPASS_ADDR 0x4f5c + +#endif /* _R300_REG_H */ diff --git a/sys/dev/drm2/radeon/r300_reg_safe.h b/sys/dev/drm2/radeon/r300_reg_safe.h new file mode 100644 index 00000000000..0b5e1eb3b30 --- /dev/null +++ b/sys/dev/drm2/radeon/r300_reg_safe.h @@ -0,0 +1,45 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned r300_reg_safe_bm[159] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, + 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFC48, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, + 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE00BFF, + 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x0000C100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0003FC0B, 0xFFFFFCFF, 0xFFBFFB99, +}; diff --git a/sys/dev/drm2/radeon/r300d.h b/sys/dev/drm2/radeon/r300d.h new file mode 100644 index 00000000000..76511a91df4 --- /dev/null +++ b/sys/dev/drm2/radeon/r300d.h @@ -0,0 +1,357 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __R300D_H__ +#define __R300D_H__ + +#include +__FBSDID("$FreeBSD$"); + +#define CP_PACKET0 0x00000000 +#define PACKET0_BASE_INDEX_SHIFT 0 +#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) +#define PACKET0_COUNT_SHIFT 16 +#define PACKET0_COUNT_MASK (0x3fff << 16) +#define CP_PACKET1 0x40000000 +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) +#define CP_PACKET3 0xC0000000 +#define PACKET3_IT_OPCODE_SHIFT 8 +#define PACKET3_IT_OPCODE_MASK (0xff << 8) +#define PACKET3_COUNT_SHIFT 16 +#define PACKET3_COUNT_MASK (0x3fff << 16) +/* PACKET3 op code */ +#define PACKET3_NOP 0x10 +#define PACKET3_3D_DRAW_VBUF 0x28 +#define PACKET3_3D_DRAW_IMMD 0x29 +#define PACKET3_3D_DRAW_INDX 0x2A +#define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_3D_CLEAR_ZMASK 0x32 +#define PACKET3_INDX_BUFFER 0x33 +#define PACKET3_3D_DRAW_VBUF_2 0x34 +#define PACKET3_3D_DRAW_IMMD_2 0x35 +#define PACKET3_3D_DRAW_INDX_2 0x36 +#define PACKET3_3D_CLEAR_HIZ 0x37 +#define PACKET3_3D_CLEAR_CMASK 0x38 +#define PACKET3_BITBLT_MULTI 0x9B + +#define PACKET0(reg, n) (CP_PACKET0 | \ + REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ + REG_SET(PACKET0_COUNT, (n))) +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) +#define PACKET3(op, n) (CP_PACKET3 | \ + REG_SET(PACKET3_IT_OPCODE, (op)) | \ + REG_SET(PACKET3_COUNT, (n))) + +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) +#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) + +/* Registers */ +#define R_000148_MC_FB_LOCATION 0x000148 +#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000148_MC_FB_START 0xFFFF0000 +#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000148_MC_FB_TOP 0x0000FFFF +#define R_00014C_MC_AGP_LOCATION 0x00014C +#define S_00014C_MC_AGP_START(x) (((x) & 0xFFFF) << 0) +#define G_00014C_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) +#define C_00014C_MC_AGP_START 0xFFFF0000 +#define S_00014C_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) +#define G_00014C_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_00014C_MC_AGP_TOP 0x0000FFFF +#define R_00015C_AGP_BASE_2 0x00015C +#define S_00015C_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) +#define G_00015C_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) +#define C_00015C_AGP_BASE_ADDR_2 0xFFFFFFF0 +#define R_000170_AGP_BASE 0x000170 +#define S_000170_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000170_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000170_AGP_BASE_ADDR 0x00000000 +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF +#define R_0000F0_RBBM_SOFT_RESET 0x0000F0 +#define S_0000F0_SOFT_RESET_CP(x) (((x) & 0x1) << 0) +#define G_0000F0_SOFT_RESET_CP(x) (((x) >> 0) & 0x1) +#define C_0000F0_SOFT_RESET_CP 0xFFFFFFFE +#define S_0000F0_SOFT_RESET_HI(x) (((x) & 0x1) << 1) +#define G_0000F0_SOFT_RESET_HI(x) (((x) >> 1) & 0x1) +#define C_0000F0_SOFT_RESET_HI 0xFFFFFFFD +#define S_0000F0_SOFT_RESET_VAP(x) (((x) & 0x1) << 2) +#define G_0000F0_SOFT_RESET_VAP(x) (((x) >> 2) & 0x1) +#define C_0000F0_SOFT_RESET_VAP 0xFFFFFFFB +#define S_0000F0_SOFT_RESET_RE(x) (((x) & 0x1) << 3) +#define G_0000F0_SOFT_RESET_RE(x) (((x) >> 3) & 0x1) +#define C_0000F0_SOFT_RESET_RE 0xFFFFFFF7 +#define S_0000F0_SOFT_RESET_PP(x) (((x) & 0x1) << 4) +#define G_0000F0_SOFT_RESET_PP(x) (((x) >> 4) & 0x1) +#define C_0000F0_SOFT_RESET_PP 0xFFFFFFEF +#define S_0000F0_SOFT_RESET_E2(x) (((x) & 0x1) << 5) +#define G_0000F0_SOFT_RESET_E2(x) (((x) >> 5) & 0x1) +#define C_0000F0_SOFT_RESET_E2 0xFFFFFFDF +#define S_0000F0_SOFT_RESET_RB(x) (((x) & 0x1) << 6) +#define G_0000F0_SOFT_RESET_RB(x) (((x) >> 6) & 0x1) +#define C_0000F0_SOFT_RESET_RB 0xFFFFFFBF +#define S_0000F0_SOFT_RESET_HDP(x) (((x) & 0x1) << 7) +#define G_0000F0_SOFT_RESET_HDP(x) (((x) >> 7) & 0x1) +#define C_0000F0_SOFT_RESET_HDP 0xFFFFFF7F +#define S_0000F0_SOFT_RESET_MC(x) (((x) & 0x1) << 8) +#define G_0000F0_SOFT_RESET_MC(x) (((x) >> 8) & 0x1) +#define C_0000F0_SOFT_RESET_MC 0xFFFFFEFF +#define S_0000F0_SOFT_RESET_AIC(x) (((x) & 0x1) << 9) +#define G_0000F0_SOFT_RESET_AIC(x) (((x) >> 9) & 0x1) +#define C_0000F0_SOFT_RESET_AIC 0xFFFFFDFF +#define S_0000F0_SOFT_RESET_VIP(x) (((x) & 0x1) << 10) +#define G_0000F0_SOFT_RESET_VIP(x) (((x) >> 10) & 0x1) +#define C_0000F0_SOFT_RESET_VIP 0xFFFFFBFF +#define S_0000F0_SOFT_RESET_DISP(x) (((x) & 0x1) << 11) +#define G_0000F0_SOFT_RESET_DISP(x) (((x) >> 11) & 0x1) +#define C_0000F0_SOFT_RESET_DISP 0xFFFFF7FF +#define S_0000F0_SOFT_RESET_CG(x) (((x) & 0x1) << 12) +#define G_0000F0_SOFT_RESET_CG(x) (((x) >> 12) & 0x1) +#define C_0000F0_SOFT_RESET_CG 0xFFFFEFFF +#define S_0000F0_SOFT_RESET_GA(x) (((x) & 0x1) << 13) +#define G_0000F0_SOFT_RESET_GA(x) (((x) >> 13) & 0x1) +#define C_0000F0_SOFT_RESET_GA 0xFFFFDFFF +#define S_0000F0_SOFT_RESET_IDCT(x) (((x) & 0x1) << 14) +#define G_0000F0_SOFT_RESET_IDCT(x) (((x) >> 14) & 0x1) +#define C_0000F0_SOFT_RESET_IDCT 0xFFFFBFFF + +#define R_00000D_SCLK_CNTL 0x00000D +#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0) +#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7) +#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8 +#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3) +#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1) +#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7 +#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4) +#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1) +#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF +#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5) +#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1) +#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF +#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6) +#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1) +#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF +#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7) +#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1) +#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F +#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8) +#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1) +#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF +#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9) +#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1) +#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF +#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10) +#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1) +#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF +#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11) +#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1) +#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF +#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12) +#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1) +#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF +#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13) +#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1) +#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF +#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14) +#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1) +#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF +#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15) +#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1) +#define C_00000D_FORCE_DISP2 0xFFFF7FFF +#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16) +#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1) +#define C_00000D_FORCE_CP 0xFFFEFFFF +#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17) +#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1) +#define C_00000D_FORCE_HDP 0xFFFDFFFF +#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18) +#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1) +#define C_00000D_FORCE_DISP1 0xFFFBFFFF +#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19) +#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1) +#define C_00000D_FORCE_TOP 0xFFF7FFFF +#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20) +#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1) +#define C_00000D_FORCE_E2 0xFFEFFFFF +#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21) +#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1) +#define C_00000D_FORCE_SE 0xFFDFFFFF +#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22) +#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1) +#define C_00000D_FORCE_IDCT 0xFFBFFFFF +#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23) +#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1) +#define C_00000D_FORCE_VIP 0xFF7FFFFF +#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24) +#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1) +#define C_00000D_FORCE_RE 0xFEFFFFFF +#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25) +#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1) +#define C_00000D_FORCE_PB 0xFDFFFFFF +#define S_00000D_FORCE_TAM(x) (((x) & 0x1) << 26) +#define G_00000D_FORCE_TAM(x) (((x) >> 26) & 0x1) +#define C_00000D_FORCE_TAM 0xFBFFFFFF +#define S_00000D_FORCE_TDM(x) (((x) & 0x1) << 27) +#define G_00000D_FORCE_TDM(x) (((x) >> 27) & 0x1) +#define C_00000D_FORCE_TDM 0xF7FFFFFF +#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28) +#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1) +#define C_00000D_FORCE_RB 0xEFFFFFFF +#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29) +#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1) +#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF +#define S_00000D_FORCE_SUBPIC(x) (((x) & 0x1) << 30) +#define G_00000D_FORCE_SUBPIC(x) (((x) >> 30) & 0x1) +#define C_00000D_FORCE_SUBPIC 0xBFFFFFFF +#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31) +#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1) +#define C_00000D_FORCE_OV0 0x7FFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/r420.c b/sys/dev/drm2/radeon/r420.c new file mode 100644 index 00000000000..e422f9db6bc --- /dev/null +++ b/sys/dev/drm2/radeon/r420.c @@ -0,0 +1,491 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" +#include "r100d.h" +#include "r420d.h" +#include "r420_reg_safe.h" + +void r420_pm_init_profile(struct radeon_device *rdev) +{ + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; +} + +static void r420_set_reg_safe(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = r420_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(r420_reg_safe_bm); +} + +void r420_pipes_init(struct radeon_device *rdev) +{ + unsigned tmp; + unsigned gb_pipe_select; + unsigned num_pipes; + + /* GA_ENHANCE workaround TCL deadlock issue */ + WREG32(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL | + (1 << 2) | (1 << 3)); + /* add idle wait as per freedesktop.org bug 24041 */ + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } + /* get max number of pipes */ + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + num_pipes = ((gb_pipe_select >> 12) & 3) + 1; + + /* SE chips have 1 pipe */ + if ((rdev->ddev->pci_device == 0x5e4c) || + (rdev->ddev->pci_device == 0x5e4f)) + num_pipes = 1; + + rdev->num_gb_pipes = num_pipes; + tmp = 0; + switch (num_pipes) { + default: + /* force to 1 pipe */ + num_pipes = 1; + case 1: + tmp = (0 << 1); + break; + case 2: + tmp = (3 << 1); + break; + case 3: + tmp = (6 << 1); + break; + case 4: + tmp = (7 << 1); + break; + } + WREG32(R500_SU_REG_DEST, (1 << num_pipes) - 1); + /* Sub pixel 1/12 so we can have 4K rendering according to doc */ + tmp |= R300_TILE_SIZE_16 | R300_ENABLE_TILING; + WREG32(R300_GB_TILE_CONFIG, tmp); + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } + + tmp = RREG32(R300_DST_PIPE_CONFIG); + WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); + + WREG32(R300_RB2D_DSTCACHE_MODE, + RREG32(R300_RB2D_DSTCACHE_MODE) | + R300_DC_AUTOFLUSH_ENABLE | + R300_DC_DC_DISABLE_IGNORE_PE); + + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "programming pipes. Bad things might happen.\n"); + } + + if (rdev->family == CHIP_RV530) { + tmp = RREG32(RV530_GB_PIPE_SELECT2); + if ((tmp & 3) == 3) + rdev->num_z_pipes = 2; + else + rdev->num_z_pipes = 1; + } else + rdev->num_z_pipes = 1; + + DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n", + rdev->num_gb_pipes, rdev->num_z_pipes); +} + +u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) +{ + u32 r; + + WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); + r = RREG32(R_0001FC_MC_IND_DATA); + return r; +} + +void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | + S_0001F8_MC_IND_WR_EN(1)); + WREG32(R_0001FC_MC_IND_DATA, v); +} + +static void r420_debugfs(struct radeon_device *rdev) +{ + if (r100_debugfs_rbbm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for RBBM !\n"); + } + if (r420_debugfs_pipes_info_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for pipes !\n"); + } +} + +static void r420_clock_resume(struct radeon_device *rdev) +{ + u32 sclk_cntl; + + if (radeon_dynclks != -1 && radeon_dynclks) + radeon_atom_set_clock_gating(rdev, 1); + sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL); + sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); + if (rdev->family == CHIP_R420) + sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1); + WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); +} + +static void r420_cp_errata_init(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + + /* RV410 and R420 can lock up if CP DMA to host memory happens + * while the 2D engine is busy. + * + * The proper workaround is to queue a RESYNC at the beginning + * of the CP init, apparently. + */ + radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); + radeon_ring_lock(rdev, ring, 8); + radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1)); + radeon_ring_write(ring, rdev->config.r300.resync_scratch); + radeon_ring_write(ring, 0xDEADBEEF); + radeon_ring_unlock_commit(rdev, ring); +} + +static void r420_cp_errata_fini(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + + /* Catch the RESYNC we dispatched all the way back, + * at the very beginning of the CP init. + */ + radeon_ring_lock(rdev, ring, 8); + radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, R300_RB3D_DC_FINISH); + radeon_ring_unlock_commit(rdev, ring); + radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); +} + +static int r420_startup(struct radeon_device *rdev) +{ + int r; + + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ + r300_mc_program(rdev); + /* Resume clock */ + r420_clock_resume(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_enable(rdev); + if (r) + return r; + } + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_enable(rdev); + if (r) + return r; + } + r420_pipes_init(rdev); + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r100_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + r420_cp_errata_init(rdev); + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int r420_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); + /* Resume clock before doing reset */ + r420_clock_resume(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (rdev->is_atom_bios) { + atom_asic_init(rdev->mode_info.atom_context); + } else { + radeon_combios_asic_init(rdev->ddev); + } + /* Resume clock after posting */ + r420_clock_resume(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = r420_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int r420_suspend(struct radeon_device *rdev) +{ + r420_cp_errata_fini(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); + return 0; +} + +void r420_fini(struct radeon_device *rdev) +{ + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + if (rdev->is_atom_bios) { + radeon_atombios_fini(rdev); + } else { + radeon_combios_fini(rdev); + } + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +int r420_init(struct radeon_device *rdev) +{ + int r; + + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* TODO: disable VGA need to use VGA request */ + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) { + return r; + } + } else { + r = radeon_combios_init(rdev); + if (r) { + return r; + } + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) { + radeon_agp_disable(rdev); + } + } + /* initialize memory controller */ + r300_mc_init(rdev); + r420_debugfs(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) { + return r; + } + r = radeon_irq_kms_init(rdev); + if (r) { + return r; + } + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) { + return r; + } + if (rdev->family == CHIP_R420) + r100_enable_bm(rdev); + + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_init(rdev); + if (r) + return r; + } + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_init(rdev); + if (r) + return r; + } + r420_set_reg_safe(rdev); + + rdev->accel_working = true; + r = r420_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); + rdev->accel_working = false; + } + return 0; +} + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) +static int r420_debugfs_pipes_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + tmp = RREG32(R400_GB_PIPE_SELECT); + seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); + tmp = RREG32(R300_GB_TILE_CONFIG); + seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); + tmp = RREG32(R300_DST_PIPE_CONFIG); + seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); + return 0; +} + +static struct drm_info_list r420_pipes_info_list[] = { + {"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL}, +}; +#endif + +int r420_debugfs_pipes_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1); +#else + return 0; +#endif +} diff --git a/sys/dev/drm2/radeon/r420_reg_safe.h b/sys/dev/drm2/radeon/r420_reg_safe.h new file mode 100644 index 00000000000..c929b0b848c --- /dev/null +++ b/sys/dev/drm2/radeon/r420_reg_safe.h @@ -0,0 +1,45 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned r420_reg_safe_bm[159] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, + 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFC48, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, + 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE00BFF, + 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFF800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0003FC0B, 0xFFFFFCFF, 0xFFBFFB99, +}; diff --git a/sys/dev/drm2/radeon/r420d.h b/sys/dev/drm2/radeon/r420d.h new file mode 100644 index 00000000000..78ea0663eb3 --- /dev/null +++ b/sys/dev/drm2/radeon/r420d.h @@ -0,0 +1,252 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef R420D_H +#define R420D_H + +#include +__FBSDID("$FreeBSD$"); + +#define R_0001F8_MC_IND_INDEX 0x0001F8 +#define S_0001F8_MC_IND_ADDR(x) (((x) & 0x7F) << 0) +#define G_0001F8_MC_IND_ADDR(x) (((x) >> 0) & 0x7F) +#define C_0001F8_MC_IND_ADDR 0xFFFFFF80 +#define S_0001F8_MC_IND_WR_EN(x) (((x) & 0x1) << 8) +#define G_0001F8_MC_IND_WR_EN(x) (((x) >> 8) & 0x1) +#define C_0001F8_MC_IND_WR_EN 0xFFFFFEFF +#define R_0001FC_MC_IND_DATA 0x0001FC +#define S_0001FC_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0001FC_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0001FC_MC_IND_DATA 0x00000000 +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF + +/* CLK registers */ +#define R_00000D_SCLK_CNTL 0x00000D +#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0) +#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7) +#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8 +#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3) +#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1) +#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7 +#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4) +#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1) +#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF +#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5) +#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1) +#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF +#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6) +#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1) +#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF +#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7) +#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1) +#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F +#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8) +#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1) +#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF +#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9) +#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1) +#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF +#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10) +#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1) +#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF +#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11) +#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1) +#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF +#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12) +#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1) +#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF +#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13) +#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1) +#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF +#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14) +#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1) +#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF +#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15) +#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1) +#define C_00000D_FORCE_DISP2 0xFFFF7FFF +#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16) +#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1) +#define C_00000D_FORCE_CP 0xFFFEFFFF +#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17) +#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1) +#define C_00000D_FORCE_HDP 0xFFFDFFFF +#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18) +#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1) +#define C_00000D_FORCE_DISP1 0xFFFBFFFF +#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19) +#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1) +#define C_00000D_FORCE_TOP 0xFFF7FFFF +#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20) +#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1) +#define C_00000D_FORCE_E2 0xFFEFFFFF +#define S_00000D_FORCE_VAP(x) (((x) & 0x1) << 21) +#define G_00000D_FORCE_VAP(x) (((x) >> 21) & 0x1) +#define C_00000D_FORCE_VAP 0xFFDFFFFF +#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22) +#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1) +#define C_00000D_FORCE_IDCT 0xFFBFFFFF +#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23) +#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1) +#define C_00000D_FORCE_VIP 0xFF7FFFFF +#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24) +#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1) +#define C_00000D_FORCE_RE 0xFEFFFFFF +#define S_00000D_FORCE_SR(x) (((x) & 0x1) << 25) +#define G_00000D_FORCE_SR(x) (((x) >> 25) & 0x1) +#define C_00000D_FORCE_SR 0xFDFFFFFF +#define S_00000D_FORCE_PX(x) (((x) & 0x1) << 26) +#define G_00000D_FORCE_PX(x) (((x) >> 26) & 0x1) +#define C_00000D_FORCE_PX 0xFBFFFFFF +#define S_00000D_FORCE_TX(x) (((x) & 0x1) << 27) +#define G_00000D_FORCE_TX(x) (((x) >> 27) & 0x1) +#define C_00000D_FORCE_TX 0xF7FFFFFF +#define S_00000D_FORCE_US(x) (((x) & 0x1) << 28) +#define G_00000D_FORCE_US(x) (((x) >> 28) & 0x1) +#define C_00000D_FORCE_US 0xEFFFFFFF +#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29) +#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1) +#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF +#define S_00000D_FORCE_SU(x) (((x) & 0x1) << 30) +#define G_00000D_FORCE_SU(x) (((x) >> 30) & 0x1) +#define C_00000D_FORCE_SU 0xBFFFFFFF +#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31) +#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1) +#define C_00000D_FORCE_OV0 0x7FFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/r500_reg.h b/sys/dev/drm2/radeon/r500_reg.h new file mode 100644 index 00000000000..c56088b8652 --- /dev/null +++ b/sys/dev/drm2/radeon/r500_reg.h @@ -0,0 +1,804 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __R500_REG_H__ +#define __R500_REG_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* pipe config regs */ +#define R300_GA_POLY_MODE 0x4288 +# define R300_FRONT_PTYPE_POINT (0 << 4) +# define R300_FRONT_PTYPE_LINE (1 << 4) +# define R300_FRONT_PTYPE_TRIANGE (2 << 4) +# define R300_BACK_PTYPE_POINT (0 << 7) +# define R300_BACK_PTYPE_LINE (1 << 7) +# define R300_BACK_PTYPE_TRIANGE (2 << 7) +#define R300_GA_ROUND_MODE 0x428c +# define R300_GEOMETRY_ROUND_TRUNC (0 << 0) +# define R300_GEOMETRY_ROUND_NEAREST (1 << 0) +# define R300_COLOR_ROUND_TRUNC (0 << 2) +# define R300_COLOR_ROUND_NEAREST (1 << 2) +#define R300_GB_MSPOS0 0x4010 +# define R300_MS_X0_SHIFT 0 +# define R300_MS_Y0_SHIFT 4 +# define R300_MS_X1_SHIFT 8 +# define R300_MS_Y1_SHIFT 12 +# define R300_MS_X2_SHIFT 16 +# define R300_MS_Y2_SHIFT 20 +# define R300_MSBD0_Y_SHIFT 24 +# define R300_MSBD0_X_SHIFT 28 +#define R300_GB_MSPOS1 0x4014 +# define R300_MS_X3_SHIFT 0 +# define R300_MS_Y3_SHIFT 4 +# define R300_MS_X4_SHIFT 8 +# define R300_MS_Y4_SHIFT 12 +# define R300_MS_X5_SHIFT 16 +# define R300_MS_Y5_SHIFT 20 +# define R300_MSBD1_SHIFT 24 + +#define R300_GA_ENHANCE 0x4274 +# define R300_GA_DEADLOCK_CNTL (1 << 0) +# define R300_GA_FASTSYNC_CNTL (1 << 1) +#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c +# define R300_RB3D_DC_FLUSH (2 << 0) +# define R300_RB3D_DC_FREE (2 << 2) +# define R300_RB3D_DC_FINISH (1 << 4) +#define R300_RB3D_ZCACHE_CTLSTAT 0x4f18 +# define R300_ZC_FLUSH (1 << 0) +# define R300_ZC_FREE (1 << 1) +# define R300_ZC_FLUSH_ALL 0x3 +#define R400_GB_PIPE_SELECT 0x402c +#define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */ +#define R500_SU_REG_DEST 0x42c8 +#define R300_GB_TILE_CONFIG 0x4018 +# define R300_ENABLE_TILING (1 << 0) +# define R300_PIPE_COUNT_RV350 (0 << 1) +# define R300_PIPE_COUNT_R300 (3 << 1) +# define R300_PIPE_COUNT_R420_3P (6 << 1) +# define R300_PIPE_COUNT_R420 (7 << 1) +# define R300_TILE_SIZE_8 (0 << 4) +# define R300_TILE_SIZE_16 (1 << 4) +# define R300_TILE_SIZE_32 (2 << 4) +# define R300_SUBPIXEL_1_12 (0 << 16) +# define R300_SUBPIXEL_1_16 (1 << 16) +#define R300_DST_PIPE_CONFIG 0x170c +# define R300_PIPE_AUTO_CONFIG (1 << 31) +#define R300_RB2D_DSTCACHE_MODE 0x3428 +# define R300_DC_AUTOFLUSH_ENABLE (1 << 8) +# define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17) + +#define RADEON_CP_STAT 0x7C0 +#define RADEON_RBBM_CMDFIFO_ADDR 0xE70 +#define RADEON_RBBM_CMDFIFO_DATA 0xE74 +#define RADEON_ISYNC_CNTL 0x1724 +# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0) +# define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1) +# define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2) +# define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3) +# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) +# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) + +#define RS480_NB_MC_INDEX 0x168 +# define RS480_NB_MC_IND_WR_EN (1 << 8) +#define RS480_NB_MC_DATA 0x16c + +/* + * RS690 + */ +#define RS690_MCCFG_FB_LOCATION 0x100 +#define RS690_MC_FB_START_MASK 0x0000FFFF +#define RS690_MC_FB_START_SHIFT 0 +#define RS690_MC_FB_TOP_MASK 0xFFFF0000 +#define RS690_MC_FB_TOP_SHIFT 16 +#define RS690_MCCFG_AGP_LOCATION 0x101 +#define RS690_MC_AGP_START_MASK 0x0000FFFF +#define RS690_MC_AGP_START_SHIFT 0 +#define RS690_MC_AGP_TOP_MASK 0xFFFF0000 +#define RS690_MC_AGP_TOP_SHIFT 16 +#define RS690_MCCFG_AGP_BASE 0x102 +#define RS690_MCCFG_AGP_BASE_2 0x103 +#define RS690_MC_INIT_MISC_LAT_TIMER 0x104 +#define RS690_HDP_FB_LOCATION 0x0134 +#define RS690_MC_INDEX 0x78 +# define RS690_MC_INDEX_MASK 0x1ff +# define RS690_MC_INDEX_WR_EN (1 << 9) +# define RS690_MC_INDEX_WR_ACK 0x7f +#define RS690_MC_NB_CNTL 0x0 +# define RS690_HIDE_MMCFG_BAR (1 << 3) +# define RS690_AGPMODE30 (1 << 4) +# define RS690_AGP30ENHANCED (1 << 5) +#define RS690_MC_DATA 0x7c +#define RS690_MC_STATUS 0x90 +#define RS690_MC_STATUS_IDLE (1 << 0) +#define RS480_AGP_BASE_2 0x0164 +#define RS480_MC_MISC_CNTL 0x18 +# define RS480_DISABLE_GTW (1 << 1) +# define RS480_GART_INDEX_REG_EN (1 << 12) +# define RS690_BLOCK_GFX_D3_EN (1 << 14) +#define RS480_GART_FEATURE_ID 0x2b +# define RS480_HANG_EN (1 << 11) +# define RS480_TLB_ENABLE (1 << 18) +# define RS480_P2P_ENABLE (1 << 19) +# define RS480_GTW_LAC_EN (1 << 25) +# define RS480_2LEVEL_GART (0 << 30) +# define RS480_1LEVEL_GART (1 << 30) +# define RS480_PDC_EN (1 << 31) +#define RS480_GART_BASE 0x2c +#define RS480_GART_CACHE_CNTRL 0x2e +# define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */ +#define RS480_AGP_ADDRESS_SPACE_SIZE 0x38 +# define RS480_GART_EN (1 << 0) +# define RS480_VA_SIZE_32MB (0 << 1) +# define RS480_VA_SIZE_64MB (1 << 1) +# define RS480_VA_SIZE_128MB (2 << 1) +# define RS480_VA_SIZE_256MB (3 << 1) +# define RS480_VA_SIZE_512MB (4 << 1) +# define RS480_VA_SIZE_1GB (5 << 1) +# define RS480_VA_SIZE_2GB (6 << 1) +#define RS480_AGP_MODE_CNTL 0x39 +# define RS480_POST_GART_Q_SIZE (1 << 18) +# define RS480_NONGART_SNOOP (1 << 19) +# define RS480_AGP_RD_BUF_SIZE (1 << 20) +# define RS480_REQ_TYPE_SNOOP_SHIFT 22 +# define RS480_REQ_TYPE_SNOOP_MASK 0x3 +# define RS480_REQ_TYPE_SNOOP_DIS (1 << 24) + +#define RS690_AIC_CTRL_SCRATCH 0x3A +# define RS690_DIS_OUT_OF_PCI_GART_ACCESS (1 << 1) + +/* + * RS600 + */ +#define RS600_MC_STATUS 0x0 +#define RS600_MC_STATUS_IDLE (1 << 0) +#define RS600_MC_INDEX 0x70 +# define RS600_MC_ADDR_MASK 0xffff +# define RS600_MC_IND_SEQ_RBS_0 (1 << 16) +# define RS600_MC_IND_SEQ_RBS_1 (1 << 17) +# define RS600_MC_IND_SEQ_RBS_2 (1 << 18) +# define RS600_MC_IND_SEQ_RBS_3 (1 << 19) +# define RS600_MC_IND_AIC_RBS (1 << 20) +# define RS600_MC_IND_CITF_ARB0 (1 << 21) +# define RS600_MC_IND_CITF_ARB1 (1 << 22) +# define RS600_MC_IND_WR_EN (1 << 23) +#define RS600_MC_DATA 0x74 +#define RS600_MC_STATUS 0x0 +# define RS600_MC_IDLE (1 << 1) +#define RS600_MC_FB_LOCATION 0x4 +#define RS600_MC_FB_START_MASK 0x0000FFFF +#define RS600_MC_FB_START_SHIFT 0 +#define RS600_MC_FB_TOP_MASK 0xFFFF0000 +#define RS600_MC_FB_TOP_SHIFT 16 +#define RS600_MC_AGP_LOCATION 0x5 +#define RS600_MC_AGP_START_MASK 0x0000FFFF +#define RS600_MC_AGP_START_SHIFT 0 +#define RS600_MC_AGP_TOP_MASK 0xFFFF0000 +#define RS600_MC_AGP_TOP_SHIFT 16 +#define RS600_MC_AGP_BASE 0x6 +#define RS600_MC_AGP_BASE_2 0x7 +#define RS600_MC_CNTL1 0x9 +# define RS600_ENABLE_PAGE_TABLES (1 << 26) +#define RS600_MC_PT0_CNTL 0x100 +# define RS600_ENABLE_PT (1 << 0) +# define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15) +# define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21) +# define RS600_INVALIDATE_ALL_L1_TLBS (1 << 28) +# define RS600_INVALIDATE_L2_CACHE (1 << 29) +#define RS600_MC_PT0_CONTEXT0_CNTL 0x102 +# define RS600_ENABLE_PAGE_TABLE (1 << 0) +# define RS600_PAGE_TABLE_TYPE_FLAT (0 << 1) +#define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR 0x112 +#define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR 0x114 +#define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c +#define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR 0x12c +#define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR 0x13c +#define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR 0x14c +#define RS600_MC_PT0_CLIENT0_CNTL 0x16c +# define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE (1 << 0) +# define RS600_TRANSLATION_MODE_OVERRIDE (1 << 1) +# define RS600_SYSTEM_ACCESS_MODE_MASK (3 << 8) +# define RS600_SYSTEM_ACCESS_MODE_PA_ONLY (0 << 8) +# define RS600_SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 8) +# define RS600_SYSTEM_ACCESS_MODE_IN_SYS (2 << 8) +# define RS600_SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 8) +# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH (0 << 10) +# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 10) +# define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11) +# define RS600_ENABLE_FRAGMENT_PROCESSING (1 << 14) +# define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) +# define RS600_INVALIDATE_L1_TLB (1 << 20) +/* rs600/rs690/rs740 */ +# define RS600_BUS_MASTER_DIS (1 << 14) +# define RS600_MSI_REARM (1 << 20) +/* see RS400_MSI_REARM in AIC_CNTL for rs480 */ + + + +#define RV515_MC_FB_LOCATION 0x01 +#define RV515_MC_FB_START_MASK 0x0000FFFF +#define RV515_MC_FB_START_SHIFT 0 +#define RV515_MC_FB_TOP_MASK 0xFFFF0000 +#define RV515_MC_FB_TOP_SHIFT 16 +#define RV515_MC_AGP_LOCATION 0x02 +#define RV515_MC_AGP_START_MASK 0x0000FFFF +#define RV515_MC_AGP_START_SHIFT 0 +#define RV515_MC_AGP_TOP_MASK 0xFFFF0000 +#define RV515_MC_AGP_TOP_SHIFT 16 +#define RV515_MC_AGP_BASE 0x03 +#define RV515_MC_AGP_BASE_2 0x04 + +#define R520_MC_FB_LOCATION 0x04 +#define R520_MC_FB_START_MASK 0x0000FFFF +#define R520_MC_FB_START_SHIFT 0 +#define R520_MC_FB_TOP_MASK 0xFFFF0000 +#define R520_MC_FB_TOP_SHIFT 16 +#define R520_MC_AGP_LOCATION 0x05 +#define R520_MC_AGP_START_MASK 0x0000FFFF +#define R520_MC_AGP_START_SHIFT 0 +#define R520_MC_AGP_TOP_MASK 0xFFFF0000 +#define R520_MC_AGP_TOP_SHIFT 16 +#define R520_MC_AGP_BASE 0x06 +#define R520_MC_AGP_BASE_2 0x07 + + +#define AVIVO_MC_INDEX 0x0070 +#define R520_MC_STATUS 0x00 +#define R520_MC_STATUS_IDLE (1<<1) +#define RV515_MC_STATUS 0x08 +#define RV515_MC_STATUS_IDLE (1<<4) +#define RV515_MC_INIT_MISC_LAT_TIMER 0x09 +#define AVIVO_MC_DATA 0x0074 + +#define R520_MC_IND_INDEX 0x70 +#define R520_MC_IND_WR_EN (1 << 24) +#define R520_MC_IND_DATA 0x74 + +#define RV515_MC_CNTL 0x5 +# define RV515_MEM_NUM_CHANNELS_MASK 0x3 +#define R520_MC_CNTL0 0x8 +# define R520_MEM_NUM_CHANNELS_MASK (0x3 << 24) +# define R520_MEM_NUM_CHANNELS_SHIFT 24 +# define R520_MC_CHANNEL_SIZE (1 << 23) + +#define AVIVO_CP_DYN_CNTL 0x000f /* PLL */ +# define AVIVO_CP_FORCEON (1 << 0) +#define AVIVO_E2_DYN_CNTL 0x0011 /* PLL */ +# define AVIVO_E2_FORCEON (1 << 0) +#define AVIVO_IDCT_DYN_CNTL 0x0013 /* PLL */ +# define AVIVO_IDCT_FORCEON (1 << 0) + +#define AVIVO_HDP_FB_LOCATION 0x134 + +#define AVIVO_VGA_RENDER_CONTROL 0x0300 +# define AVIVO_VGA_VSTATUS_CNTL_MASK (3 << 16) +#define AVIVO_D1VGA_CONTROL 0x0330 +# define AVIVO_DVGA_CONTROL_MODE_ENABLE (1<<0) +# define AVIVO_DVGA_CONTROL_TIMING_SELECT (1<<8) +# define AVIVO_DVGA_CONTROL_SYNC_POLARITY_SELECT (1<<9) +# define AVIVO_DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1<<10) +# define AVIVO_DVGA_CONTROL_OVERSCAN_COLOR_EN (1<<16) +# define AVIVO_DVGA_CONTROL_ROTATE (1<<24) +#define AVIVO_D2VGA_CONTROL 0x0338 + +#define AVIVO_EXT1_PPLL_REF_DIV_SRC 0x400 +#define AVIVO_EXT1_PPLL_REF_DIV 0x404 +#define AVIVO_EXT1_PPLL_UPDATE_LOCK 0x408 +#define AVIVO_EXT1_PPLL_UPDATE_CNTL 0x40c + +#define AVIVO_EXT2_PPLL_REF_DIV_SRC 0x410 +#define AVIVO_EXT2_PPLL_REF_DIV 0x414 +#define AVIVO_EXT2_PPLL_UPDATE_LOCK 0x418 +#define AVIVO_EXT2_PPLL_UPDATE_CNTL 0x41c + +#define AVIVO_EXT1_PPLL_FB_DIV 0x430 +#define AVIVO_EXT2_PPLL_FB_DIV 0x434 + +#define AVIVO_EXT1_PPLL_POST_DIV_SRC 0x438 +#define AVIVO_EXT1_PPLL_POST_DIV 0x43c + +#define AVIVO_EXT2_PPLL_POST_DIV_SRC 0x440 +#define AVIVO_EXT2_PPLL_POST_DIV 0x444 + +#define AVIVO_EXT1_PPLL_CNTL 0x448 +#define AVIVO_EXT2_PPLL_CNTL 0x44c + +#define AVIVO_P1PLL_CNTL 0x450 +#define AVIVO_P2PLL_CNTL 0x454 +#define AVIVO_P1PLL_INT_SS_CNTL 0x458 +#define AVIVO_P2PLL_INT_SS_CNTL 0x45c +#define AVIVO_P1PLL_TMDSA_CNTL 0x460 +#define AVIVO_P2PLL_LVTMA_CNTL 0x464 + +#define AVIVO_PCLK_CRTC1_CNTL 0x480 +#define AVIVO_PCLK_CRTC2_CNTL 0x484 + +#define AVIVO_D1CRTC_H_TOTAL 0x6000 +#define AVIVO_D1CRTC_H_BLANK_START_END 0x6004 +#define AVIVO_D1CRTC_H_SYNC_A 0x6008 +#define AVIVO_D1CRTC_H_SYNC_A_CNTL 0x600c +#define AVIVO_D1CRTC_H_SYNC_B 0x6010 +#define AVIVO_D1CRTC_H_SYNC_B_CNTL 0x6014 + +#define AVIVO_D1CRTC_V_TOTAL 0x6020 +#define AVIVO_D1CRTC_V_BLANK_START_END 0x6024 +#define AVIVO_D1CRTC_V_SYNC_A 0x6028 +#define AVIVO_D1CRTC_V_SYNC_A_CNTL 0x602c +#define AVIVO_D1CRTC_V_SYNC_B 0x6030 +#define AVIVO_D1CRTC_V_SYNC_B_CNTL 0x6034 + +#define AVIVO_D1CRTC_CONTROL 0x6080 +# define AVIVO_CRTC_EN (1 << 0) +# define AVIVO_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 +#define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 +#define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c +#define AVIVO_D1CRTC_STATUS 0x609c +# define AVIVO_D1CRTC_V_BLANK (1 << 0) +#define AVIVO_D1CRTC_STATUS_POSITION 0x60a0 +#define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 +#define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 + +#define AVIVO_D1MODE_MASTER_UPDATE_MODE 0x60e4 + +/* master controls */ +#define AVIVO_DC_CRTC_MASTER_EN 0x60f8 +#define AVIVO_DC_CRTC_TV_CONTROL 0x60fc + +#define AVIVO_D1GRPH_ENABLE 0x6100 +#define AVIVO_D1GRPH_CONTROL 0x6104 +# define AVIVO_D1GRPH_CONTROL_DEPTH_8BPP (0 << 0) +# define AVIVO_D1GRPH_CONTROL_DEPTH_16BPP (1 << 0) +# define AVIVO_D1GRPH_CONTROL_DEPTH_32BPP (2 << 0) +# define AVIVO_D1GRPH_CONTROL_DEPTH_64BPP (3 << 0) + +# define AVIVO_D1GRPH_CONTROL_8BPP_INDEXED (0 << 8) + +# define AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555 (0 << 8) +# define AVIVO_D1GRPH_CONTROL_16BPP_RGB565 (1 << 8) +# define AVIVO_D1GRPH_CONTROL_16BPP_ARGB4444 (2 << 8) +# define AVIVO_D1GRPH_CONTROL_16BPP_AI88 (3 << 8) +# define AVIVO_D1GRPH_CONTROL_16BPP_MONO16 (4 << 8) + +# define AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888 (0 << 8) +# define AVIVO_D1GRPH_CONTROL_32BPP_ARGB2101010 (1 << 8) +# define AVIVO_D1GRPH_CONTROL_32BPP_DIGITAL (2 << 8) +# define AVIVO_D1GRPH_CONTROL_32BPP_8B_ARGB2101010 (3 << 8) + + +# define AVIVO_D1GRPH_CONTROL_64BPP_ARGB16161616 (0 << 8) + +# define AVIVO_D1GRPH_SWAP_RB (1 << 16) +# define AVIVO_D1GRPH_TILED (1 << 20) +# define AVIVO_D1GRPH_MACRO_ADDRESS_MODE (1 << 21) + +# define R600_D1GRPH_ARRAY_MODE_LINEAR_GENERAL (0 << 20) +# define R600_D1GRPH_ARRAY_MODE_LINEAR_ALIGNED (1 << 20) +# define R600_D1GRPH_ARRAY_MODE_1D_TILED_THIN1 (2 << 20) +# define R600_D1GRPH_ARRAY_MODE_2D_TILED_THIN1 (4 << 20) + +/* The R7xx *_HIGH surface regs are backwards; the D1 regs are in the D2 + * block and vice versa. This applies to GRPH, CUR, etc. + */ +#define AVIVO_D1GRPH_LUT_SEL 0x6108 +#define AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 +#define R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6914 +#define R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6114 +#define AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 +#define R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c +#define R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c +#define AVIVO_D1GRPH_PITCH 0x6120 +#define AVIVO_D1GRPH_SURFACE_OFFSET_X 0x6124 +#define AVIVO_D1GRPH_SURFACE_OFFSET_Y 0x6128 +#define AVIVO_D1GRPH_X_START 0x612c +#define AVIVO_D1GRPH_Y_START 0x6130 +#define AVIVO_D1GRPH_X_END 0x6134 +#define AVIVO_D1GRPH_Y_END 0x6138 +#define AVIVO_D1GRPH_UPDATE 0x6144 +# define AVIVO_D1GRPH_SURFACE_UPDATE_PENDING (1 << 2) +# define AVIVO_D1GRPH_UPDATE_LOCK (1 << 16) +#define AVIVO_D1GRPH_FLIP_CONTROL 0x6148 +# define AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) + +#define AVIVO_D1CUR_CONTROL 0x6400 +# define AVIVO_D1CURSOR_EN (1 << 0) +# define AVIVO_D1CURSOR_MODE_SHIFT 8 +# define AVIVO_D1CURSOR_MODE_MASK (3 << 8) +# define AVIVO_D1CURSOR_MODE_24BPP 2 +#define AVIVO_D1CUR_SURFACE_ADDRESS 0x6408 +#define R700_D1CUR_SURFACE_ADDRESS_HIGH 0x6c0c +#define R700_D2CUR_SURFACE_ADDRESS_HIGH 0x640c +#define AVIVO_D1CUR_SIZE 0x6410 +#define AVIVO_D1CUR_POSITION 0x6414 +#define AVIVO_D1CUR_HOT_SPOT 0x6418 +#define AVIVO_D1CUR_UPDATE 0x6424 +# define AVIVO_D1CURSOR_UPDATE_LOCK (1 << 16) + +#define AVIVO_DC_LUT_RW_SELECT 0x6480 +#define AVIVO_DC_LUT_RW_MODE 0x6484 +#define AVIVO_DC_LUT_RW_INDEX 0x6488 +#define AVIVO_DC_LUT_SEQ_COLOR 0x648c +#define AVIVO_DC_LUT_PWL_DATA 0x6490 +#define AVIVO_DC_LUT_30_COLOR 0x6494 +#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498 +#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c +#define AVIVO_DC_LUT_AUTOFILL 0x64a0 + +#define AVIVO_DC_LUTA_CONTROL 0x64c0 +#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4 +#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8 +#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc +#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0 +#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4 +#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8 + +#define AVIVO_DC_LB_MEMORY_SPLIT 0x6520 +# define AVIVO_DC_LB_MEMORY_SPLIT_MASK 0x3 +# define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT 0 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY 2 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 +# define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) +# define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4 +# define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff + +#define AVIVO_D1MODE_DATA_FORMAT 0x6528 +# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) +#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C +#define AVIVO_D1MODE_VBLANK_STATUS 0x6534 +# define AVIVO_VBLANK_ACK (1 << 4) +#define AVIVO_D1MODE_VLINE_START_END 0x6538 +#define AVIVO_D1MODE_VLINE_STATUS 0x653c +# define AVIVO_D1MODE_VLINE_STAT (1 << 12) +#define AVIVO_DxMODE_INT_MASK 0x6540 +# define AVIVO_D1MODE_INT_MASK (1 << 0) +# define AVIVO_D2MODE_INT_MASK (1 << 8) +#define AVIVO_D1MODE_VIEWPORT_START 0x6580 +#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 +#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 +#define AVIVO_D1MODE_EXT_OVERSCAN_TOP_BOTTOM 0x658c + +#define AVIVO_D1SCL_SCALER_ENABLE 0x6590 +#define AVIVO_D1SCL_SCALER_TAP_CONTROL 0x6594 +#define AVIVO_D1SCL_UPDATE 0x65cc +# define AVIVO_D1SCL_UPDATE_LOCK (1 << 16) + +/* second crtc */ +#define AVIVO_D2CRTC_H_TOTAL 0x6800 +#define AVIVO_D2CRTC_H_BLANK_START_END 0x6804 +#define AVIVO_D2CRTC_H_SYNC_A 0x6808 +#define AVIVO_D2CRTC_H_SYNC_A_CNTL 0x680c +#define AVIVO_D2CRTC_H_SYNC_B 0x6810 +#define AVIVO_D2CRTC_H_SYNC_B_CNTL 0x6814 + +#define AVIVO_D2CRTC_V_TOTAL 0x6820 +#define AVIVO_D2CRTC_V_BLANK_START_END 0x6824 +#define AVIVO_D2CRTC_V_SYNC_A 0x6828 +#define AVIVO_D2CRTC_V_SYNC_A_CNTL 0x682c +#define AVIVO_D2CRTC_V_SYNC_B 0x6830 +#define AVIVO_D2CRTC_V_SYNC_B_CNTL 0x6834 + +#define AVIVO_D2CRTC_CONTROL 0x6880 +#define AVIVO_D2CRTC_BLANK_CONTROL 0x6884 +#define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888 +#define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c +#define AVIVO_D2CRTC_STATUS_POSITION 0x68a0 +#define AVIVO_D2CRTC_FRAME_COUNT 0x68a4 +#define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4 + +#define AVIVO_D2GRPH_ENABLE 0x6900 +#define AVIVO_D2GRPH_CONTROL 0x6904 +#define AVIVO_D2GRPH_LUT_SEL 0x6908 +#define AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910 +#define AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918 +#define AVIVO_D2GRPH_PITCH 0x6920 +#define AVIVO_D2GRPH_SURFACE_OFFSET_X 0x6924 +#define AVIVO_D2GRPH_SURFACE_OFFSET_Y 0x6928 +#define AVIVO_D2GRPH_X_START 0x692c +#define AVIVO_D2GRPH_Y_START 0x6930 +#define AVIVO_D2GRPH_X_END 0x6934 +#define AVIVO_D2GRPH_Y_END 0x6938 +#define AVIVO_D2GRPH_UPDATE 0x6944 +#define AVIVO_D2GRPH_FLIP_CONTROL 0x6948 + +#define AVIVO_D2CUR_CONTROL 0x6c00 +#define AVIVO_D2CUR_SURFACE_ADDRESS 0x6c08 +#define AVIVO_D2CUR_SIZE 0x6c10 +#define AVIVO_D2CUR_POSITION 0x6c14 + +#define AVIVO_D2MODE_VBLANK_STATUS 0x6d34 +#define AVIVO_D2MODE_VLINE_START_END 0x6d38 +#define AVIVO_D2MODE_VLINE_STATUS 0x6d3c +#define AVIVO_D2MODE_VIEWPORT_START 0x6d80 +#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 +#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 +#define AVIVO_D2MODE_EXT_OVERSCAN_TOP_BOTTOM 0x6d8c + +#define AVIVO_D2SCL_SCALER_ENABLE 0x6d90 +#define AVIVO_D2SCL_SCALER_TAP_CONTROL 0x6d94 + +#define AVIVO_DDIA_BIT_DEPTH_CONTROL 0x7214 + +#define AVIVO_DACA_ENABLE 0x7800 +# define AVIVO_DAC_ENABLE (1 << 0) +#define AVIVO_DACA_SOURCE_SELECT 0x7804 +# define AVIVO_DAC_SOURCE_CRTC1 (0 << 0) +# define AVIVO_DAC_SOURCE_CRTC2 (1 << 0) +# define AVIVO_DAC_SOURCE_TV (2 << 0) + +#define AVIVO_DACA_FORCE_OUTPUT_CNTL 0x783c +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_FORCE_DATA_EN (1 << 0) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT (8) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE (1 << 0) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN (1 << 1) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_RED (1 << 2) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY (1 << 24) +#define AVIVO_DACA_POWERDOWN 0x7850 +# define AVIVO_DACA_POWERDOWN_POWERDOWN (1 << 0) +# define AVIVO_DACA_POWERDOWN_BLUE (1 << 8) +# define AVIVO_DACA_POWERDOWN_GREEN (1 << 16) +# define AVIVO_DACA_POWERDOWN_RED (1 << 24) + +#define AVIVO_DACB_ENABLE 0x7a00 +#define AVIVO_DACB_SOURCE_SELECT 0x7a04 +#define AVIVO_DACB_FORCE_OUTPUT_CNTL 0x7a3c +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_FORCE_DATA_EN (1 << 0) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT (8) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE (1 << 0) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN (1 << 1) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_RED (1 << 2) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY (1 << 24) +#define AVIVO_DACB_POWERDOWN 0x7a50 +# define AVIVO_DACB_POWERDOWN_POWERDOWN (1 << 0) +# define AVIVO_DACB_POWERDOWN_BLUE (1 << 8) +# define AVIVO_DACB_POWERDOWN_GREEN (1 << 16) +# define AVIVO_DACB_POWERDOWN_RED + +#define AVIVO_TMDSA_CNTL 0x7880 +# define AVIVO_TMDSA_CNTL_ENABLE (1 << 0) +# define AVIVO_TMDSA_CNTL_HDMI_EN (1 << 2) +# define AVIVO_TMDSA_CNTL_HPD_MASK (1 << 4) +# define AVIVO_TMDSA_CNTL_HPD_SELECT (1 << 8) +# define AVIVO_TMDSA_CNTL_SYNC_PHASE (1 << 12) +# define AVIVO_TMDSA_CNTL_PIXEL_ENCODING (1 << 16) +# define AVIVO_TMDSA_CNTL_DUAL_LINK_ENABLE (1 << 24) +# define AVIVO_TMDSA_CNTL_SWAP (1 << 28) +#define AVIVO_TMDSA_SOURCE_SELECT 0x7884 +/* 78a8 appears to be some kind of (reasonably tolerant) clock? + * 78d0 definitely hits the transmitter, definitely clock. */ +/* MYSTERY1 This appears to control dithering? */ +#define AVIVO_TMDSA_BIT_DEPTH_CONTROL 0x7894 +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN (1 << 0) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH (1 << 4) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN (1 << 8) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH (1 << 12) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN (1 << 16) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL (1 << 24) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26) +#define AVIVO_TMDSA_DCBALANCER_CONTROL 0x78d0 +# define AVIVO_TMDSA_DCBALANCER_CONTROL_EN (1 << 0) +# define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_EN (1 << 8) +# define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_IN_SHIFT (16) +# define AVIVO_TMDSA_DCBALANCER_CONTROL_FORCE (1 << 24) +#define AVIVO_TMDSA_DATA_SYNCHRONIZATION 0x78d8 +# define AVIVO_TMDSA_DATA_SYNCHRONIZATION_DSYNSEL (1 << 0) +# define AVIVO_TMDSA_DATA_SYNCHRONIZATION_PFREQCHG (1 << 8) +#define AVIVO_TMDSA_CLOCK_ENABLE 0x7900 +#define AVIVO_TMDSA_TRANSMITTER_ENABLE 0x7904 +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX0_ENABLE (1 << 0) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKC0EN (1 << 1) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD00EN (1 << 2) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD01EN (1 << 3) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD02EN (1 << 4) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX1_ENABLE (1 << 8) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD10EN (1 << 10) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD11EN (1 << 11) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD12EN (1 << 12) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX_ENABLE_HPD_MASK (1 << 16) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK (1 << 17) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK (1 << 18) + +#define AVIVO_TMDSA_TRANSMITTER_CONTROL 0x7910 +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_ENABLE (1 << 0) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_RESET (1 << 1) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_IDSCKSEL (1 << 4) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_BGSLEEP (1 << 5) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN (1 << 6) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK (1 << 8) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS (1 << 13) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK (1 << 14) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS (1 << 15) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_BYPASS_PLL (1 << 28) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_USE_CLK_DATA (1 << 29) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31) + +#define AVIVO_LVTMA_CNTL 0x7a80 +# define AVIVO_LVTMA_CNTL_ENABLE (1 << 0) +# define AVIVO_LVTMA_CNTL_HDMI_EN (1 << 2) +# define AVIVO_LVTMA_CNTL_HPD_MASK (1 << 4) +# define AVIVO_LVTMA_CNTL_HPD_SELECT (1 << 8) +# define AVIVO_LVTMA_CNTL_SYNC_PHASE (1 << 12) +# define AVIVO_LVTMA_CNTL_PIXEL_ENCODING (1 << 16) +# define AVIVO_LVTMA_CNTL_DUAL_LINK_ENABLE (1 << 24) +# define AVIVO_LVTMA_CNTL_SWAP (1 << 28) +#define AVIVO_LVTMA_SOURCE_SELECT 0x7a84 +#define AVIVO_LVTMA_COLOR_FORMAT 0x7a88 +#define AVIVO_LVTMA_BIT_DEPTH_CONTROL 0x7a94 +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN (1 << 0) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH (1 << 4) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN (1 << 8) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH (1 << 12) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN (1 << 16) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL (1 << 24) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26) + + + +#define AVIVO_LVTMA_DCBALANCER_CONTROL 0x7ad0 +# define AVIVO_LVTMA_DCBALANCER_CONTROL_EN (1 << 0) +# define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_EN (1 << 8) +# define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_IN_SHIFT (16) +# define AVIVO_LVTMA_DCBALANCER_CONTROL_FORCE (1 << 24) + +#define AVIVO_LVTMA_DATA_SYNCHRONIZATION 0x78d8 +# define AVIVO_LVTMA_DATA_SYNCHRONIZATION_DSYNSEL (1 << 0) +# define AVIVO_LVTMA_DATA_SYNCHRONIZATION_PFREQCHG (1 << 8) +#define R500_LVTMA_CLOCK_ENABLE 0x7b00 +#define R600_LVTMA_CLOCK_ENABLE 0x7b04 + +#define R500_LVTMA_TRANSMITTER_ENABLE 0x7b04 +#define R600_LVTMA_TRANSMITTER_ENABLE 0x7b08 +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC0EN (1 << 1) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD00EN (1 << 2) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD01EN (1 << 3) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD02EN (1 << 4) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD03EN (1 << 5) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC1EN (1 << 9) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD10EN (1 << 10) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD11EN (1 << 11) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD12EN (1 << 12) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK (1 << 17) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK (1 << 18) + +#define R500_LVTMA_TRANSMITTER_CONTROL 0x7b10 +#define R600_LVTMA_TRANSMITTER_CONTROL 0x7b14 +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_ENABLE (1 << 0) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_RESET (1 << 1) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_IDSCKSEL (1 << 4) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_BGSLEEP (1 << 5) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN (1 << 6) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK (1 << 8) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS (1 << 13) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK (1 << 14) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS (1 << 15) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_BYPASS_PLL (1 << 28) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_USE_CLK_DATA (1 << 29) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31) + +#define R500_LVTMA_PWRSEQ_CNTL 0x7af0 +#define R600_LVTMA_PWRSEQ_CNTL 0x7af4 +# define AVIVO_LVTMA_PWRSEQ_EN (1 << 0) +# define AVIVO_LVTMA_PWRSEQ_PLL_ENABLE_MASK (1 << 2) +# define AVIVO_LVTMA_PWRSEQ_PLL_RESET_MASK (1 << 3) +# define AVIVO_LVTMA_PWRSEQ_TARGET_STATE (1 << 4) +# define AVIVO_LVTMA_SYNCEN (1 << 8) +# define AVIVO_LVTMA_SYNCEN_OVRD (1 << 9) +# define AVIVO_LVTMA_SYNCEN_POL (1 << 10) +# define AVIVO_LVTMA_DIGON (1 << 16) +# define AVIVO_LVTMA_DIGON_OVRD (1 << 17) +# define AVIVO_LVTMA_DIGON_POL (1 << 18) +# define AVIVO_LVTMA_BLON (1 << 24) +# define AVIVO_LVTMA_BLON_OVRD (1 << 25) +# define AVIVO_LVTMA_BLON_POL (1 << 26) + +#define R500_LVTMA_PWRSEQ_STATE 0x7af4 +#define R600_LVTMA_PWRSEQ_STATE 0x7af8 +# define AVIVO_LVTMA_PWRSEQ_STATE_TARGET_STATE_R (1 << 0) +# define AVIVO_LVTMA_PWRSEQ_STATE_DIGON (1 << 1) +# define AVIVO_LVTMA_PWRSEQ_STATE_SYNCEN (1 << 2) +# define AVIVO_LVTMA_PWRSEQ_STATE_BLON (1 << 3) +# define AVIVO_LVTMA_PWRSEQ_STATE_DONE (1 << 4) +# define AVIVO_LVTMA_PWRSEQ_STATE_STATUS_SHIFT (8) + +#define AVIVO_LVDS_BACKLIGHT_CNTL 0x7af8 +# define AVIVO_LVDS_BACKLIGHT_CNTL_EN (1 << 0) +# define AVIVO_LVDS_BACKLIGHT_LEVEL_MASK 0x0000ff00 +# define AVIVO_LVDS_BACKLIGHT_LEVEL_SHIFT 8 + +#define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988 + +#define AVIVO_DC_GPIO_HPD_A 0x7e94 +#define AVIVO_DC_GPIO_HPD_Y 0x7e9c + +#define AVIVO_DC_I2C_STATUS1 0x7d30 +# define AVIVO_DC_I2C_DONE (1 << 0) +# define AVIVO_DC_I2C_NACK (1 << 1) +# define AVIVO_DC_I2C_HALT (1 << 2) +# define AVIVO_DC_I2C_GO (1 << 3) +#define AVIVO_DC_I2C_RESET 0x7d34 +# define AVIVO_DC_I2C_SOFT_RESET (1 << 0) +# define AVIVO_DC_I2C_ABORT (1 << 8) +#define AVIVO_DC_I2C_CONTROL1 0x7d38 +# define AVIVO_DC_I2C_START (1 << 0) +# define AVIVO_DC_I2C_STOP (1 << 1) +# define AVIVO_DC_I2C_RECEIVE (1 << 2) +# define AVIVO_DC_I2C_EN (1 << 8) +# define AVIVO_DC_I2C_PIN_SELECT(x) ((x) << 16) +# define AVIVO_SEL_DDC1 0 +# define AVIVO_SEL_DDC2 1 +# define AVIVO_SEL_DDC3 2 +#define AVIVO_DC_I2C_CONTROL2 0x7d3c +# define AVIVO_DC_I2C_ADDR_COUNT(x) ((x) << 0) +# define AVIVO_DC_I2C_DATA_COUNT(x) ((x) << 8) +#define AVIVO_DC_I2C_CONTROL3 0x7d40 +# define AVIVO_DC_I2C_DATA_DRIVE_EN (1 << 0) +# define AVIVO_DC_I2C_DATA_DRIVE_SEL (1 << 1) +# define AVIVO_DC_I2C_CLK_DRIVE_EN (1 << 7) +# define AVIVO_DC_I2C_RD_INTRA_BYTE_DELAY(x) ((x) << 8) +# define AVIVO_DC_I2C_WR_INTRA_BYTE_DELAY(x) ((x) << 16) +# define AVIVO_DC_I2C_TIME_LIMIT(x) ((x) << 24) +#define AVIVO_DC_I2C_DATA 0x7d44 +#define AVIVO_DC_I2C_INTERRUPT_CONTROL 0x7d48 +# define AVIVO_DC_I2C_INTERRUPT_STATUS (1 << 0) +# define AVIVO_DC_I2C_INTERRUPT_AK (1 << 8) +# define AVIVO_DC_I2C_INTERRUPT_ENABLE (1 << 16) +#define AVIVO_DC_I2C_ARBITRATION 0x7d50 +# define AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C (1 << 0) +# define AVIVO_DC_I2C_SW_CAN_USE_I2C (1 << 1) +# define AVIVO_DC_I2C_SW_DONE_USING_I2C (1 << 8) +# define AVIVO_DC_I2C_HW_NEEDS_I2C (1 << 9) +# define AVIVO_DC_I2C_ABORT_HDCP_I2C (1 << 16) +# define AVIVO_DC_I2C_HW_USING_I2C (1 << 17) + +#define AVIVO_DC_GPIO_DDC1_MASK 0x7e40 +#define AVIVO_DC_GPIO_DDC1_A 0x7e44 +#define AVIVO_DC_GPIO_DDC1_EN 0x7e48 +#define AVIVO_DC_GPIO_DDC1_Y 0x7e4c + +#define AVIVO_DC_GPIO_DDC2_MASK 0x7e50 +#define AVIVO_DC_GPIO_DDC2_A 0x7e54 +#define AVIVO_DC_GPIO_DDC2_EN 0x7e58 +#define AVIVO_DC_GPIO_DDC2_Y 0x7e5c + +#define AVIVO_DC_GPIO_DDC3_MASK 0x7e60 +#define AVIVO_DC_GPIO_DDC3_A 0x7e64 +#define AVIVO_DC_GPIO_DDC3_EN 0x7e68 +#define AVIVO_DC_GPIO_DDC3_Y 0x7e6c + +#define AVIVO_DISP_INTERRUPT_STATUS 0x7edc +# define AVIVO_D1_VBLANK_INTERRUPT (1 << 4) +# define AVIVO_D2_VBLANK_INTERRUPT (1 << 5) + +#endif diff --git a/sys/dev/drm2/radeon/r520.c b/sys/dev/drm2/radeon/r520.c new file mode 100644 index 00000000000..523c94aaf3b --- /dev/null +++ b/sys/dev/drm2/radeon/r520.c @@ -0,0 +1,330 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" +#include "r520d.h" + +/* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */ + +int r520_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32_MC(R520_MC_STATUS); + if (tmp & R520_MC_STATUS_IDLE) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +static void r520_gpu_init(struct radeon_device *rdev) +{ + unsigned pipe_select_current, gb_pipe_select, tmp; + + rv515_vga_render_disable(rdev); + /* + * DST_PIPE_CONFIG 0x170C + * GB_TILE_CONFIG 0x4018 + * GB_FIFO_SIZE 0x4024 + * GB_PIPE_SELECT 0x402C + * GB_PIPE_SELECT2 0x4124 + * Z_PIPE_SHIFT 0 + * Z_PIPE_MASK 0x000000003 + * GB_FIFO_SIZE2 0x4128 + * SC_SFIFO_SIZE_SHIFT 0 + * SC_SFIFO_SIZE_MASK 0x000000003 + * SC_MFIFO_SIZE_SHIFT 2 + * SC_MFIFO_SIZE_MASK 0x00000000C + * FG_SFIFO_SIZE_SHIFT 4 + * FG_SFIFO_SIZE_MASK 0x000000030 + * ZB_MFIFO_SIZE_SHIFT 6 + * ZB_MFIFO_SIZE_MASK 0x0000000C0 + * GA_ENHANCE 0x4274 + * SU_REG_DEST 0x42C8 + */ + /* workaround for RV530 */ + if (rdev->family == CHIP_RV530) { + WREG32(0x4128, 0xFF); + } + r420_pipes_init(rdev); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(R300_DST_PIPE_CONFIG); + pipe_select_current = (tmp >> 2) & 3; + tmp = (1 << pipe_select_current) | + (((gb_pipe_select >> 8) & 0xF) << 4); + WREG32_PLL(0x000D, tmp); + if (r520_mc_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait MC idle while " + "programming pipes. Bad things might happen.\n"); + } +} + +static void r520_vram_get_type(struct radeon_device *rdev) +{ + uint32_t tmp; + + rdev->mc.vram_width = 128; + rdev->mc.vram_is_ddr = true; + tmp = RREG32_MC(R520_MC_CNTL0); + switch ((tmp & R520_MEM_NUM_CHANNELS_MASK) >> R520_MEM_NUM_CHANNELS_SHIFT) { + case 0: + rdev->mc.vram_width = 32; + break; + case 1: + rdev->mc.vram_width = 64; + break; + case 2: + rdev->mc.vram_width = 128; + break; + case 3: + rdev->mc.vram_width = 256; + break; + default: + rdev->mc.vram_width = 128; + break; + } + if (tmp & R520_MC_CHANNEL_SIZE) + rdev->mc.vram_width *= 2; +} + +static void r520_mc_init(struct radeon_device *rdev) +{ + + r520_vram_get_type(rdev); + r100_vram_init_sizes(rdev); + radeon_vram_location(rdev, &rdev->mc, 0); + rdev->mc.gtt_base_align = 0; + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + +static void r520_mc_program(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + + /* Stops all mc clients */ + rv515_mc_stop(rdev, &save); + + /* Wait for mc idle */ + if (r520_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); + /* Write VRAM size in case we are limiting it */ + WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + /* Program MC, should be a 32bits limited address space */ + WREG32_MC(R_000004_MC_FB_LOCATION, + S_000004_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16)); + WREG32(R_000134_HDP_FB_LOCATION, + S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); + if (rdev->flags & RADEON_IS_AGP) { + WREG32_MC(R_000005_MC_AGP_LOCATION, + S_000005_MC_AGP_START(rdev->mc.gtt_start >> 16) | + S_000005_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); + WREG32_MC(R_000006_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); + WREG32_MC(R_000007_AGP_BASE_2, + S_000007_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base))); + } else { + WREG32_MC(R_000005_MC_AGP_LOCATION, 0xFFFFFFFF); + WREG32_MC(R_000006_AGP_BASE, 0); + WREG32_MC(R_000007_AGP_BASE_2, 0); + } + + rv515_mc_resume(rdev, &save); +} + +static int r520_startup(struct radeon_device *rdev) +{ + int r; + + r520_mc_program(rdev); + /* Resume clock */ + rv515_clock_startup(rdev); + /* Initialize GPU configuration (# pipes, ...) */ + r520_gpu_init(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_enable(rdev); + if (r) + return r; + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int r520_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + /* Resume clock before doing reset */ + rv515_clock_startup(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + atom_asic_init(rdev->mode_info.atom_context); + /* Resume clock after posting */ + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = r520_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int r520_init(struct radeon_device *rdev) +{ + int r; + + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* TODO: disable VGA need to use VGA request */ + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) + return r; + } else { + dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n"); + return -EINVAL; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + + if (!radeon_card_posted(rdev) && rdev->bios) { + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) { + radeon_agp_disable(rdev); + } + } + /* initialize memory controller */ + r520_mc_init(rdev); + rv515_debugfs(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + r = rv370_pcie_gart_init(rdev); + if (r) + return r; + rv515_set_safe_registers(rdev); + + rdev->accel_working = true; + r = r520_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + rv370_pcie_gart_fini(rdev); + radeon_agp_fini(rdev); + rdev->accel_working = false; + } + return 0; +} diff --git a/sys/dev/drm2/radeon/r520d.h b/sys/dev/drm2/radeon/r520d.h new file mode 100644 index 00000000000..6fbd54cbcd6 --- /dev/null +++ b/sys/dev/drm2/radeon/r520d.h @@ -0,0 +1,190 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __R520D_H__ +#define __R520D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* Registers */ +#define R_0000F8_CONFIG_MEMSIZE 0x0000F8 +#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0000F8_CONFIG_MEMSIZE 0x00000000 +#define R_000134_HDP_FB_LOCATION 0x000134 +#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000134_HDP_FB_START 0xFFFF0000 +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_RBBM_HIBUSY(x) (((x) & 0x1) << 28) +#define G_000E40_RBBM_HIBUSY(x) (((x) >> 28) & 0x1) +#define C_000E40_RBBM_HIBUSY 0xEFFFFFFF +#define S_000E40_SKID_CFBUSY(x) (((x) & 0x1) << 29) +#define G_000E40_SKID_CFBUSY(x) (((x) >> 29) & 0x1) +#define C_000E40_SKID_CFBUSY 0xDFFFFFFF +#define S_000E40_VAP_VF_BUSY(x) (((x) & 0x1) << 30) +#define G_000E40_VAP_VF_BUSY(x) (((x) >> 30) & 0x1) +#define C_000E40_VAP_VF_BUSY 0xBFFFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF + + +#define R_000004_MC_FB_LOCATION 0x000004 +#define S_000004_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000004_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000004_MC_FB_START 0xFFFF0000 +#define S_000004_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000004_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000004_MC_FB_TOP 0x0000FFFF +#define R_000005_MC_AGP_LOCATION 0x000005 +#define S_000005_MC_AGP_START(x) (((x) & 0xFFFF) << 0) +#define G_000005_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) +#define C_000005_MC_AGP_START 0xFFFF0000 +#define S_000005_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000005_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000005_MC_AGP_TOP 0x0000FFFF +#define R_000006_AGP_BASE 0x000006 +#define S_000006_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000006_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000006_AGP_BASE_ADDR 0x00000000 +#define R_000007_AGP_BASE_2 0x000007 +#define S_000007_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) +#define G_000007_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) +#define C_000007_AGP_BASE_ADDR_2 0xFFFFFFF0 + +#endif diff --git a/sys/dev/drm2/radeon/r600.c b/sys/dev/drm2/radeon/r600.c new file mode 100644 index 00000000000..b9d41bcaed4 --- /dev/null +++ b/sys/dev/drm2/radeon/r600.c @@ -0,0 +1,4384 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "radeon_mode.h" +#include "r600d.h" +#include "atom.h" +#include "avivod.h" + +#define PFP_UCODE_SIZE 576 +#define PM4_UCODE_SIZE 1792 +#define RLC_UCODE_SIZE 768 +#define R700_PFP_UCODE_SIZE 848 +#define R700_PM4_UCODE_SIZE 1360 +#define R700_RLC_UCODE_SIZE 1024 +#define EVERGREEN_PFP_UCODE_SIZE 1120 +#define EVERGREEN_PM4_UCODE_SIZE 1376 +#define EVERGREEN_RLC_UCODE_SIZE 768 +#define CAYMAN_RLC_UCODE_SIZE 1024 +#define ARUBA_RLC_UCODE_SIZE 1536 + +#ifdef DUMBBELL_WIP +/* Firmware Names */ +MODULE_FIRMWARE("radeon/R600_pfp.bin"); +MODULE_FIRMWARE("radeon/R600_me.bin"); +MODULE_FIRMWARE("radeon/RV610_pfp.bin"); +MODULE_FIRMWARE("radeon/RV610_me.bin"); +MODULE_FIRMWARE("radeon/RV630_pfp.bin"); +MODULE_FIRMWARE("radeon/RV630_me.bin"); +MODULE_FIRMWARE("radeon/RV620_pfp.bin"); +MODULE_FIRMWARE("radeon/RV620_me.bin"); +MODULE_FIRMWARE("radeon/RV635_pfp.bin"); +MODULE_FIRMWARE("radeon/RV635_me.bin"); +MODULE_FIRMWARE("radeon/RV670_pfp.bin"); +MODULE_FIRMWARE("radeon/RV670_me.bin"); +MODULE_FIRMWARE("radeon/RS780_pfp.bin"); +MODULE_FIRMWARE("radeon/RS780_me.bin"); +MODULE_FIRMWARE("radeon/RV770_pfp.bin"); +MODULE_FIRMWARE("radeon/RV770_me.bin"); +MODULE_FIRMWARE("radeon/RV730_pfp.bin"); +MODULE_FIRMWARE("radeon/RV730_me.bin"); +MODULE_FIRMWARE("radeon/RV710_pfp.bin"); +MODULE_FIRMWARE("radeon/RV710_me.bin"); +MODULE_FIRMWARE("radeon/R600_rlc.bin"); +MODULE_FIRMWARE("radeon/R700_rlc.bin"); +MODULE_FIRMWARE("radeon/CEDAR_pfp.bin"); +MODULE_FIRMWARE("radeon/CEDAR_me.bin"); +MODULE_FIRMWARE("radeon/CEDAR_rlc.bin"); +MODULE_FIRMWARE("radeon/REDWOOD_pfp.bin"); +MODULE_FIRMWARE("radeon/REDWOOD_me.bin"); +MODULE_FIRMWARE("radeon/REDWOOD_rlc.bin"); +MODULE_FIRMWARE("radeon/JUNIPER_pfp.bin"); +MODULE_FIRMWARE("radeon/JUNIPER_me.bin"); +MODULE_FIRMWARE("radeon/JUNIPER_rlc.bin"); +MODULE_FIRMWARE("radeon/CYPRESS_pfp.bin"); +MODULE_FIRMWARE("radeon/CYPRESS_me.bin"); +MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin"); +MODULE_FIRMWARE("radeon/PALM_pfp.bin"); +MODULE_FIRMWARE("radeon/PALM_me.bin"); +MODULE_FIRMWARE("radeon/SUMO_rlc.bin"); +MODULE_FIRMWARE("radeon/SUMO_pfp.bin"); +MODULE_FIRMWARE("radeon/SUMO_me.bin"); +MODULE_FIRMWARE("radeon/SUMO2_pfp.bin"); +MODULE_FIRMWARE("radeon/SUMO2_me.bin"); +#endif /* DUMBBELL_WIP */ + +int r600_debugfs_mc_info_init(struct radeon_device *rdev); + +/* r600,rv610,rv630,rv620,rv635,rv670 */ +static void r600_gpu_init(struct radeon_device *rdev); +void r600_irq_disable(struct radeon_device *rdev); +static void r600_pcie_gen2_enable(struct radeon_device *rdev); + +/* get temperature in millidegrees */ +int rv6xx_get_temp(struct radeon_device *rdev) +{ + u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >> + ASIC_T_SHIFT; + int actual_temp = temp & 0xff; + + if (temp & 0x100) + actual_temp -= 256; + + return actual_temp * 1000; +} + +void r600_pm_get_dynpm_state(struct radeon_device *rdev) +{ + int i; + + rdev->pm.dynpm_can_upclock = true; + rdev->pm.dynpm_can_downclock = true; + + /* power state array is low to high, default is first */ + if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) { + int min_power_state_index = 0; + + if (rdev->pm.num_power_states > 2) + min_power_state_index = 1; + + switch (rdev->pm.dynpm_planned_action) { + case DYNPM_ACTION_MINIMUM: + rdev->pm.requested_power_state_index = min_power_state_index; + rdev->pm.requested_clock_mode_index = 0; + rdev->pm.dynpm_can_downclock = false; + break; + case DYNPM_ACTION_DOWNCLOCK: + if (rdev->pm.current_power_state_index == min_power_state_index) { + rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; + rdev->pm.dynpm_can_downclock = false; + } else { + if (rdev->pm.active_crtc_count > 1) { + for (i = 0; i < rdev->pm.num_power_states; i++) { + if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + continue; + else if (i >= rdev->pm.current_power_state_index) { + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index; + break; + } else { + rdev->pm.requested_power_state_index = i; + break; + } + } + } else { + if (rdev->pm.current_power_state_index == 0) + rdev->pm.requested_power_state_index = + rdev->pm.num_power_states - 1; + else + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index - 1; + } + } + rdev->pm.requested_clock_mode_index = 0; + /* don't use the power state if crtcs are active and no display flag is set */ + if ((rdev->pm.active_crtc_count > 0) && + (rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].flags & + RADEON_PM_MODE_NO_DISPLAY)) { + rdev->pm.requested_power_state_index++; + } + break; + case DYNPM_ACTION_UPCLOCK: + if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { + rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; + rdev->pm.dynpm_can_upclock = false; + } else { + if (rdev->pm.active_crtc_count > 1) { + for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { + if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + continue; + else if (i <= rdev->pm.current_power_state_index) { + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index; + break; + } else { + rdev->pm.requested_power_state_index = i; + break; + } + } + } else + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index + 1; + } + rdev->pm.requested_clock_mode_index = 0; + break; + case DYNPM_ACTION_DEFAULT: + rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.requested_clock_mode_index = 0; + rdev->pm.dynpm_can_upclock = false; + break; + case DYNPM_ACTION_NONE: + default: + DRM_ERROR("Requested mode for not defined action\n"); + return; + } + } else { + /* XXX select a power state based on AC/DC, single/dualhead, etc. */ + /* for now just select the first power state and switch between clock modes */ + /* power state array is low to high, default is first (0) */ + if (rdev->pm.active_crtc_count > 1) { + rdev->pm.requested_power_state_index = -1; + /* start at 1 as we don't want the default mode */ + for (i = 1; i < rdev->pm.num_power_states; i++) { + if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + continue; + else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) || + (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) { + rdev->pm.requested_power_state_index = i; + break; + } + } + /* if nothing selected, grab the default state. */ + if (rdev->pm.requested_power_state_index == -1) + rdev->pm.requested_power_state_index = 0; + } else + rdev->pm.requested_power_state_index = 1; + + switch (rdev->pm.dynpm_planned_action) { + case DYNPM_ACTION_MINIMUM: + rdev->pm.requested_clock_mode_index = 0; + rdev->pm.dynpm_can_downclock = false; + break; + case DYNPM_ACTION_DOWNCLOCK: + if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { + if (rdev->pm.current_clock_mode_index == 0) { + rdev->pm.requested_clock_mode_index = 0; + rdev->pm.dynpm_can_downclock = false; + } else + rdev->pm.requested_clock_mode_index = + rdev->pm.current_clock_mode_index - 1; + } else { + rdev->pm.requested_clock_mode_index = 0; + rdev->pm.dynpm_can_downclock = false; + } + /* don't use the power state if crtcs are active and no display flag is set */ + if ((rdev->pm.active_crtc_count > 0) && + (rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].flags & + RADEON_PM_MODE_NO_DISPLAY)) { + rdev->pm.requested_clock_mode_index++; + } + break; + case DYNPM_ACTION_UPCLOCK: + if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { + if (rdev->pm.current_clock_mode_index == + (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) { + rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index; + rdev->pm.dynpm_can_upclock = false; + } else + rdev->pm.requested_clock_mode_index = + rdev->pm.current_clock_mode_index + 1; + } else { + rdev->pm.requested_clock_mode_index = + rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1; + rdev->pm.dynpm_can_upclock = false; + } + break; + case DYNPM_ACTION_DEFAULT: + rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.requested_clock_mode_index = 0; + rdev->pm.dynpm_can_upclock = false; + break; + case DYNPM_ACTION_NONE: + default: + DRM_ERROR("Requested mode for not defined action\n"); + return; + } + } + + DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n", + rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].sclk, + rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].mclk, + rdev->pm.power_state[rdev->pm.requested_power_state_index]. + pcie_lanes); +} + +void rs780_pm_init_profile(struct radeon_device *rdev) +{ + if (rdev->pm.num_power_states == 2) { + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; + } else if (rdev->pm.num_power_states == 3) { + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; + } else { + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; + } +} + +void r600_pm_init_profile(struct radeon_device *rdev) +{ + int idx; + + if (rdev->family == CHIP_R600) { + /* XXX */ + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; + } else { + if (rdev->pm.num_power_states < 4) { + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; + /* low sh */ + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; + /* high sh */ + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; + /* high mh */ + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; + } else { + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; + /* low sh */ + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; + /* high sh */ + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; + /* low mh */ + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; + /* high mh */ + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; + } + } +} + +void r600_pm_misc(struct radeon_device *rdev) +{ + int req_ps_idx = rdev->pm.requested_power_state_index; + int req_cm_idx = rdev->pm.requested_clock_mode_index; + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage); + } + } +} + +bool r600_gui_idle(struct radeon_device *rdev) +{ + if (RREG32(GRBM_STATUS) & GUI_ACTIVE) + return false; + else + return true; +} + +/* hpd for digital panel detect/disconnect */ +bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + bool connected = false; + + if (ASIC_IS_DCE3(rdev)) { + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_3: + if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_4: + if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + /* DCE 3.2 */ + case RADEON_HPD_5: + if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case RADEON_HPD_6: + if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + default: + break; + } + } else { + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) + connected = true; + break; + case RADEON_HPD_3: + if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) + connected = true; + break; + default: + break; + } + } + return connected; +} + +void r600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = r600_hpd_sense(rdev, hpd); + + if (ASIC_IS_DCE3(rdev)) { + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(DC_HPD1_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(DC_HPD2_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + break; + case RADEON_HPD_3: + tmp = RREG32(DC_HPD3_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + break; + case RADEON_HPD_4: + tmp = RREG32(DC_HPD4_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + break; + case RADEON_HPD_5: + tmp = RREG32(DC_HPD5_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + break; + /* DCE 3.2 */ + case RADEON_HPD_6: + tmp = RREG32(DC_HPD6_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + break; + default: + break; + } + } else { + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); + if (connected) + tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; + else + tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); + if (connected) + tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; + else + tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + break; + case RADEON_HPD_3: + tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); + if (connected) + tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; + else + tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); + break; + default: + break; + } + } +} + +void r600_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned enable = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || + connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { + /* don't try to enable hpd on eDP or LVDS avoid breaking the + * aux dp channel on imac and help (but not completely fix) + * https://bugzilla.redhat.com/show_bug.cgi?id=726143 + */ + continue; + } + if (ASIC_IS_DCE3(rdev)) { + u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa); + if (ASIC_IS_DCE32(rdev)) + tmp |= DC_HPDx_EN; + + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HPD1_CONTROL, tmp); + break; + case RADEON_HPD_2: + WREG32(DC_HPD2_CONTROL, tmp); + break; + case RADEON_HPD_3: + WREG32(DC_HPD3_CONTROL, tmp); + break; + case RADEON_HPD_4: + WREG32(DC_HPD4_CONTROL, tmp); + break; + /* DCE 3.2 */ + case RADEON_HPD_5: + WREG32(DC_HPD5_CONTROL, tmp); + break; + case RADEON_HPD_6: + WREG32(DC_HPD6_CONTROL, tmp); + break; + default: + break; + } + } else { + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); + break; + case RADEON_HPD_2: + WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); + break; + case RADEON_HPD_3: + WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); + break; + default: + break; + } + } + enable |= 1 << radeon_connector->hpd.hpd; + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + } + radeon_irq_kms_enable_hpd(rdev, enable); +} + +void r600_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned disable = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + if (ASIC_IS_DCE3(rdev)) { + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HPD1_CONTROL, 0); + break; + case RADEON_HPD_2: + WREG32(DC_HPD2_CONTROL, 0); + break; + case RADEON_HPD_3: + WREG32(DC_HPD3_CONTROL, 0); + break; + case RADEON_HPD_4: + WREG32(DC_HPD4_CONTROL, 0); + break; + /* DCE 3.2 */ + case RADEON_HPD_5: + WREG32(DC_HPD5_CONTROL, 0); + break; + case RADEON_HPD_6: + WREG32(DC_HPD6_CONTROL, 0); + break; + default: + break; + } + } else { + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); + break; + case RADEON_HPD_2: + WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); + break; + case RADEON_HPD_3: + WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); + break; + default: + break; + } + } + disable |= 1 << radeon_connector->hpd.hpd; + } + radeon_irq_kms_disable_hpd(rdev, disable); +} + +/* + * R600 PCIE GART + */ +void r600_pcie_gart_tlb_flush(struct radeon_device *rdev) +{ + unsigned i; + u32 tmp; + + /* flush hdp cache so updates hit vram */ + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && + !(rdev->flags & RADEON_IS_AGP)) { + volatile uint32_t *ptr = rdev->gart.ptr; + u32 tmp; + + /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read + * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL + * This seems to cause problems on some AGP cards. Just use the old + * method for them. + */ + WREG32(HDP_DEBUG1, 0); + tmp = *ptr; + } else + WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); + + WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12); + WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1)); + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(VM_CONTEXT0_REQUEST_RESPONSE); + tmp = (tmp & RESPONSE_TYPE_MASK) >> RESPONSE_TYPE_SHIFT; + if (tmp == 2) { + DRM_ERROR("[drm] r600 flush TLB failed\n"); + return; + } + if (tmp) { + return; + } + DRM_UDELAY(1); + } +} + +int r600_pcie_gart_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.robj) { + DRM_ERROR("R600 PCIE GART already initialized\n"); + return 0; + } + /* Initialize common gart structure */ + r = radeon_gart_init(rdev); + if (r) + return r; + rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; + return radeon_gart_table_vram_alloc(rdev); +} + +static int r600_pcie_gart_enable(struct radeon_device *rdev) +{ + u32 tmp; + int r, i; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); + /* Setup TLB control */ + tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | + ENABLE_WAIT_L2_QUERY; + WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING); + WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); + WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); + WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); + WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + for (i = 1; i < 7; i++) + WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); + + r600_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +static void r600_pcie_gart_disable(struct radeon_device *rdev) +{ + u32 tmp; + int i; + + /* Disable all tables */ + for (i = 0; i < 7; i++) + WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); + + /* Disable L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); + /* Setup L1 TLB control */ + tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | + ENABLE_WAIT_L2_QUERY; + WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); + radeon_gart_table_vram_unpin(rdev); +} + +static void r600_pcie_gart_fini(struct radeon_device *rdev) +{ + radeon_gart_fini(rdev); + r600_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); +} + +static void r600_agp_enable(struct radeon_device *rdev) +{ + u32 tmp; + int i; + + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); + /* Setup TLB control */ + tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | + ENABLE_WAIT_L2_QUERY; + WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING); + WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); + WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); + WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); + for (i = 0; i < 7; i++) + WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); +} + +int r600_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + u32 tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(R_000E50_SRBM_STATUS) & 0x3F00; + if (!tmp) + return 0; + DRM_UDELAY(1); + } + return -1; +} + +static void r600_mc_program(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + u32 tmp; + int i, j; + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); + + rv515_mc_stop(rdev, &save); + if (r600_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Lockout access through VGA aperture (doesn't exist before R600) */ + WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); + /* Update configuration */ + if (rdev->flags & RADEON_IS_AGP) { + if (rdev->mc.vram_start < rdev->mc.gtt_start) { + /* VRAM before AGP */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.gtt_end >> 12); + } else { + /* VRAM after AGP */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.gtt_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.vram_end >> 12); + } + } else { + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12); + } + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); + tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; + tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); + WREG32(MC_VM_FB_LOCATION, tmp); + WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); + WREG32(HDP_NONSURFACE_INFO, (2 << 7)); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); + if (rdev->flags & RADEON_IS_AGP) { + WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22); + WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); + WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); + } else { + WREG32(MC_VM_AGP_BASE, 0); + WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); + WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); + } + if (r600_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + rv515_mc_resume(rdev, &save); + /* we need to own VRAM, so turn off the VGA renderer here + * to stop it overwriting our objects */ + rv515_vga_render_disable(rdev); +} + +/** + * r600_vram_gtt_location - try to find VRAM & GTT location + * @rdev: radeon device structure holding all necessary informations + * @mc: memory controller structure holding memory informations + * + * Function will place try to place VRAM at same place as in CPU (PCI) + * address space as some GPU seems to have issue when we reprogram at + * different address space. + * + * If there is not enough space to fit the unvisible VRAM after the + * aperture then we limit the VRAM size to the aperture. + * + * If we are using AGP then place VRAM adjacent to AGP aperture are we need + * them to be in one from GPU point of view so that we can program GPU to + * catch access outside them (weird GPU policy see ??). + * + * This function will never fails, worst case are limiting VRAM or GTT. + * + * Note: GTT start, end, size should be initialized before calling this + * function on AGP platform. + */ +static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +{ + u64 size_bf, size_af; + + if (mc->mc_vram_size > 0xE0000000) { + /* leave room for at least 512M GTT */ + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = 0xE0000000; + mc->mc_vram_size = 0xE0000000; + } + if (rdev->flags & RADEON_IS_AGP) { + size_bf = mc->gtt_start; + size_af = 0xFFFFFFFF - mc->gtt_end; + if (size_bf > size_af) { + if (mc->mc_vram_size > size_bf) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_bf; + mc->mc_vram_size = size_bf; + } + mc->vram_start = mc->gtt_start - mc->mc_vram_size; + } else { + if (mc->mc_vram_size > size_af) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_af; + mc->mc_vram_size = size_af; + } + mc->vram_start = mc->gtt_end + 1; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %juM 0x%08jX - 0x%08jX (%juM used)\n", + (uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start, + (uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20); + } else { + u64 base = 0; + if (rdev->flags & RADEON_IS_IGP) { + base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; + } + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = 0; + radeon_gtt_location(rdev, mc); + } +} + +static int r600_mc_init(struct radeon_device *rdev) +{ + u32 tmp; + int chansize, numchan; + + /* Get VRAM informations */ + rdev->mc.vram_is_ddr = true; + tmp = RREG32(RAMCFG); + if (tmp & CHANSIZE_OVERRIDE) { + chansize = 16; + } else if (tmp & CHANSIZE_MASK) { + chansize = 64; + } else { + chansize = 32; + } + tmp = RREG32(CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + numchan = 1; + break; + case 1: + numchan = 2; + break; + case 2: + numchan = 4; + break; + case 3: + numchan = 8; + break; + } + rdev->mc.vram_width = numchan * chansize; + /* Could aper size report 0 ? */ + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + /* Setup GPU memory space */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.visible_vram_size = rdev->mc.aper_size; + r600_vram_gtt_location(rdev, &rdev->mc); + + if (rdev->flags & RADEON_IS_IGP) { + rs690_pm_info(rdev); + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + } + radeon_update_bandwidth_info(rdev); + return 0; +} + +int r600_vram_scratch_init(struct radeon_device *rdev) +{ + int r; + void *vram_scratch_ptr_ptr; + + if (rdev->vram_scratch.robj == NULL) { + r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, + PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->vram_scratch.robj); + if (r) { + return r; + } + } + + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (unlikely(r != 0)) { + radeon_bo_unref(&rdev->vram_scratch.robj); + return r; + } + r = radeon_bo_pin(rdev->vram_scratch.robj, + RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->vram_scratch.robj); + radeon_bo_unref(&rdev->vram_scratch.robj); + return r; + } + vram_scratch_ptr_ptr = &rdev->vram_scratch.ptr; + r = radeon_bo_kmap(rdev->vram_scratch.robj, + vram_scratch_ptr_ptr); + if (r) + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + if (r) + radeon_bo_unref(&rdev->vram_scratch.robj); + + return r; +} + +void r600_vram_scratch_fini(struct radeon_device *rdev) +{ + int r; + + if (rdev->vram_scratch.robj == NULL) { + return; + } + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->vram_scratch.robj); + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + } + radeon_bo_unref(&rdev->vram_scratch.robj); +} + +/* We doesn't check that the GPU really needs a reset we simply do the + * reset, it's up to the caller to determine if the GPU needs one. We + * might add an helper function to check that. + */ +static void r600_gpu_soft_reset_gfx(struct radeon_device *rdev) +{ + u32 grbm_busy_mask = S_008010_VC_BUSY(1) | S_008010_VGT_BUSY_NO_DMA(1) | + S_008010_VGT_BUSY(1) | S_008010_TA03_BUSY(1) | + S_008010_TC_BUSY(1) | S_008010_SX_BUSY(1) | + S_008010_SH_BUSY(1) | S_008010_SPI03_BUSY(1) | + S_008010_SMX_BUSY(1) | S_008010_SC_BUSY(1) | + S_008010_PA_BUSY(1) | S_008010_DB03_BUSY(1) | + S_008010_CR_BUSY(1) | S_008010_CB03_BUSY(1) | + S_008010_GUI_ACTIVE(1); + u32 grbm2_busy_mask = S_008014_SPI0_BUSY(1) | S_008014_SPI1_BUSY(1) | + S_008014_SPI2_BUSY(1) | S_008014_SPI3_BUSY(1) | + S_008014_TA0_BUSY(1) | S_008014_TA1_BUSY(1) | + S_008014_TA2_BUSY(1) | S_008014_TA3_BUSY(1) | + S_008014_DB0_BUSY(1) | S_008014_DB1_BUSY(1) | + S_008014_DB2_BUSY(1) | S_008014_DB3_BUSY(1) | + S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) | + S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1); + u32 tmp; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + return; + + dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", + RREG32(R_008010_GRBM_STATUS)); + dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", + RREG32(R_008014_GRBM_STATUS2)); + dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", + RREG32(R_000E50_SRBM_STATUS)); + dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", + RREG32(CP_STALLED_STAT1)); + dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", + RREG32(CP_STALLED_STAT2)); + dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", + RREG32(CP_BUSY_STAT)); + dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", + RREG32(CP_STAT)); + + /* Disable CP parsing/prefetching */ + WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); + + /* Check if any of the rendering block is busy and reset it */ + if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) || + (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) { + tmp = S_008020_SOFT_RESET_CR(1) | + S_008020_SOFT_RESET_DB(1) | + S_008020_SOFT_RESET_CB(1) | + S_008020_SOFT_RESET_PA(1) | + S_008020_SOFT_RESET_SC(1) | + S_008020_SOFT_RESET_SMX(1) | + S_008020_SOFT_RESET_SPI(1) | + S_008020_SOFT_RESET_SX(1) | + S_008020_SOFT_RESET_SH(1) | + S_008020_SOFT_RESET_TC(1) | + S_008020_SOFT_RESET_TA(1) | + S_008020_SOFT_RESET_VC(1) | + S_008020_SOFT_RESET_VGT(1); + dev_info(rdev->dev, " R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(R_008020_GRBM_SOFT_RESET, tmp); + RREG32(R_008020_GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(R_008020_GRBM_SOFT_RESET, 0); + } + /* Reset CP (we always reset CP) */ + tmp = S_008020_SOFT_RESET_CP(1); + dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(R_008020_GRBM_SOFT_RESET, tmp); + RREG32(R_008020_GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(R_008020_GRBM_SOFT_RESET, 0); + + dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", + RREG32(R_008010_GRBM_STATUS)); + dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", + RREG32(R_008014_GRBM_STATUS2)); + dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", + RREG32(R_000E50_SRBM_STATUS)); + dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", + RREG32(CP_STALLED_STAT1)); + dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", + RREG32(CP_STALLED_STAT2)); + dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", + RREG32(CP_BUSY_STAT)); + dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", + RREG32(CP_STAT)); + +} + +static void r600_gpu_soft_reset_dma(struct radeon_device *rdev) +{ + u32 tmp; + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + return; + + dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); + + /* Disable DMA */ + tmp = RREG32(DMA_RB_CNTL); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL, tmp); + + /* Reset dma */ + if (rdev->family >= CHIP_RV770) + WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA); + else + WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA); + RREG32(SRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(SRBM_SOFT_RESET, 0); + + dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); +} + +static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) +{ + struct rv515_mc_save save; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + + if (reset_mask == 0) + return 0; + + dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); + + rv515_mc_stop(rdev, &save); + if (r600_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + + if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) + r600_gpu_soft_reset_gfx(rdev); + + if (reset_mask & RADEON_RESET_DMA) + r600_gpu_soft_reset_dma(rdev); + + /* Wait a little for things to settle down */ + DRM_MDELAY(1); + + rv515_mc_resume(rdev, &save); + return 0; +} + +bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 srbm_status; + u32 grbm_status; + u32 grbm_status2; + + srbm_status = RREG32(R_000E50_SRBM_STATUS); + grbm_status = RREG32(R_008010_GRBM_STATUS); + grbm_status2 = RREG32(R_008014_GRBM_STATUS2); + if (!G_008010_GUI_ACTIVE(grbm_status)) { + radeon_ring_lockup_update(ring); + return false; + } + /* force CP activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +/** + * r600_dma_is_lockup - Check if the DMA engine is locked up + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Check if the async DMA engine is locked up (r6xx-evergreen). + * Returns true if the engine appears to be locked up, false if not. + */ +bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 dma_status_reg; + + dma_status_reg = RREG32(DMA_STATUS_REG); + if (dma_status_reg & DMA_IDLE) { + radeon_ring_lockup_update(ring); + return false; + } + /* force ring activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +int r600_asic_reset(struct radeon_device *rdev) +{ + return r600_gpu_soft_reset(rdev, (RADEON_RESET_GFX | + RADEON_RESET_COMPUTE | + RADEON_RESET_DMA)); +} + +u32 r6xx_remap_render_backend(struct radeon_device *rdev, + u32 tiling_pipe_num, + u32 max_rb_num, + u32 total_max_rb_num, + u32 disabled_rb_mask) +{ + u32 rendering_pipe_num, rb_num_width, req_rb_num; + u32 pipe_rb_ratio, pipe_rb_remain, tmp; + u32 data = 0, mask = 1 << (max_rb_num - 1); + unsigned i, j; + + /* mask out the RBs that don't exist on that asic */ + tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff); + /* make sure at least one RB is available */ + if ((tmp & 0xff) != 0xff) + disabled_rb_mask = tmp; + + rendering_pipe_num = 1 << tiling_pipe_num; + req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); + KASSERT(rendering_pipe_num >= req_rb_num, ("rendering_pipe_num < req_rb_num")); + + pipe_rb_ratio = rendering_pipe_num / req_rb_num; + pipe_rb_remain = rendering_pipe_num - pipe_rb_ratio * req_rb_num; + + if (rdev->family <= CHIP_RV740) { + /* r6xx/r7xx */ + rb_num_width = 2; + } else { + /* eg+ */ + rb_num_width = 4; + } + + for (i = 0; i < max_rb_num; i++) { + if (!(mask & disabled_rb_mask)) { + for (j = 0; j < pipe_rb_ratio; j++) { + data <<= rb_num_width; + data |= max_rb_num - i - 1; + } + if (pipe_rb_remain) { + data <<= rb_num_width; + data |= max_rb_num - i - 1; + pipe_rb_remain--; + } + } + mask >>= 1; + } + + return data; +} + +int r600_count_pipe_bits(uint32_t val) +{ + return hweight32(val); +} + +static void r600_gpu_init(struct radeon_device *rdev) +{ + u32 tiling_config; + u32 ramcfg; + u32 cc_rb_backend_disable; + u32 cc_gc_shader_pipe_config; + u32 tmp; + int i, j; + u32 sq_config; + u32 sq_gpr_resource_mgmt_1 = 0; + u32 sq_gpr_resource_mgmt_2 = 0; + u32 sq_thread_resource_mgmt = 0; + u32 sq_stack_resource_mgmt_1 = 0; + u32 sq_stack_resource_mgmt_2 = 0; + u32 disabled_rb_mask; + + rdev->config.r600.tiling_group_size = 256; + switch (rdev->family) { + case CHIP_R600: + rdev->config.r600.max_pipes = 4; + rdev->config.r600.max_tile_pipes = 8; + rdev->config.r600.max_simds = 4; + rdev->config.r600.max_backends = 4; + rdev->config.r600.max_gprs = 256; + rdev->config.r600.max_threads = 192; + rdev->config.r600.max_stack_entries = 256; + rdev->config.r600.max_hw_contexts = 8; + rdev->config.r600.max_gs_threads = 16; + rdev->config.r600.sx_max_export_size = 128; + rdev->config.r600.sx_max_export_pos_size = 16; + rdev->config.r600.sx_max_export_smx_size = 128; + rdev->config.r600.sq_num_cf_insts = 2; + break; + case CHIP_RV630: + case CHIP_RV635: + rdev->config.r600.max_pipes = 2; + rdev->config.r600.max_tile_pipes = 2; + rdev->config.r600.max_simds = 3; + rdev->config.r600.max_backends = 1; + rdev->config.r600.max_gprs = 128; + rdev->config.r600.max_threads = 192; + rdev->config.r600.max_stack_entries = 128; + rdev->config.r600.max_hw_contexts = 8; + rdev->config.r600.max_gs_threads = 4; + rdev->config.r600.sx_max_export_size = 128; + rdev->config.r600.sx_max_export_pos_size = 16; + rdev->config.r600.sx_max_export_smx_size = 128; + rdev->config.r600.sq_num_cf_insts = 2; + break; + case CHIP_RV610: + case CHIP_RV620: + case CHIP_RS780: + case CHIP_RS880: + rdev->config.r600.max_pipes = 1; + rdev->config.r600.max_tile_pipes = 1; + rdev->config.r600.max_simds = 2; + rdev->config.r600.max_backends = 1; + rdev->config.r600.max_gprs = 128; + rdev->config.r600.max_threads = 192; + rdev->config.r600.max_stack_entries = 128; + rdev->config.r600.max_hw_contexts = 4; + rdev->config.r600.max_gs_threads = 4; + rdev->config.r600.sx_max_export_size = 128; + rdev->config.r600.sx_max_export_pos_size = 16; + rdev->config.r600.sx_max_export_smx_size = 128; + rdev->config.r600.sq_num_cf_insts = 1; + break; + case CHIP_RV670: + rdev->config.r600.max_pipes = 4; + rdev->config.r600.max_tile_pipes = 4; + rdev->config.r600.max_simds = 4; + rdev->config.r600.max_backends = 4; + rdev->config.r600.max_gprs = 192; + rdev->config.r600.max_threads = 192; + rdev->config.r600.max_stack_entries = 256; + rdev->config.r600.max_hw_contexts = 8; + rdev->config.r600.max_gs_threads = 16; + rdev->config.r600.sx_max_export_size = 128; + rdev->config.r600.sx_max_export_pos_size = 16; + rdev->config.r600.sx_max_export_smx_size = 128; + rdev->config.r600.sq_num_cf_insts = 2; + break; + default: + break; + } + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + + WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); + + /* Setup tiling */ + tiling_config = 0; + ramcfg = RREG32(RAMCFG); + switch (rdev->config.r600.max_tile_pipes) { + case 1: + tiling_config |= PIPE_TILING(0); + break; + case 2: + tiling_config |= PIPE_TILING(1); + break; + case 4: + tiling_config |= PIPE_TILING(2); + break; + case 8: + tiling_config |= PIPE_TILING(3); + break; + default: + break; + } + rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes; + rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); + tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); + tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + + tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; + if (tmp > 3) { + tiling_config |= ROW_TILING(3); + tiling_config |= SAMPLE_SPLIT(3); + } else { + tiling_config |= ROW_TILING(tmp); + tiling_config |= SAMPLE_SPLIT(tmp); + } + tiling_config |= BANK_SWAPS(1); + + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; + tmp = R6XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable >> 16) & R6XX_MAX_BACKENDS_MASK); + if (tmp < rdev->config.r600.max_backends) { + rdev->config.r600.max_backends = tmp; + } + + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00; + tmp = R6XX_MAX_PIPES - + r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R6XX_MAX_PIPES_MASK); + if (tmp < rdev->config.r600.max_pipes) { + rdev->config.r600.max_pipes = tmp; + } + tmp = R6XX_MAX_SIMDS - + r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK); + if (tmp < rdev->config.r600.max_simds) { + rdev->config.r600.max_simds = tmp; + } + + disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK; + tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; + tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends, + R6XX_MAX_BACKENDS, disabled_rb_mask); + tiling_config |= tmp << 16; + rdev->config.r600.backend_map = tmp; + + rdev->config.r600.tile_config = tiling_config; + WREG32(GB_TILING_CONFIG, tiling_config); + WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff); + WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff); + WREG32(DMA_TILING_CONFIG, tiling_config & 0xffff); + + tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); + WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK); + WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK); + + /* Setup some CP states */ + WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | ROQ_IB2_START(0x2b))); + WREG32(CP_MEQ_THRESHOLDS, (MEQ_END(0x40) | ROQ_END(0x40))); + + WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO | SYNC_GRADIENT | + SYNC_WALKER | SYNC_ALIGNER)); + /* Setup various GPU states */ + if (rdev->family == CHIP_RV670) + WREG32(ARB_GDEC_RD_CNTL, 0x00000021); + + tmp = RREG32(SX_DEBUG_1); + tmp |= SMX_EVENT_RELEASE; + if ((rdev->family > CHIP_R600)) + tmp |= ENABLE_NEW_SMX_ADDRESS; + WREG32(SX_DEBUG_1, tmp); + + if (((rdev->family) == CHIP_R600) || + ((rdev->family) == CHIP_RV630) || + ((rdev->family) == CHIP_RV610) || + ((rdev->family) == CHIP_RV620) || + ((rdev->family) == CHIP_RS780) || + ((rdev->family) == CHIP_RS880)) { + WREG32(DB_DEBUG, PREZ_MUST_WAIT_FOR_POSTZ_DONE); + } else { + WREG32(DB_DEBUG, 0); + } + WREG32(DB_WATERMARKS, (DEPTH_FREE(4) | DEPTH_CACHELINE_FREE(16) | + DEPTH_FLUSH(16) | DEPTH_PENDING_FREE(4))); + + WREG32(PA_SC_MULTI_CHIP_CNTL, 0); + WREG32(VGT_NUM_INSTANCES, 0); + + WREG32(SPI_CONFIG_CNTL, GPR_WRITE_PRIORITY(0)); + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(0)); + + tmp = RREG32(SQ_MS_FIFO_SIZES); + if (((rdev->family) == CHIP_RV610) || + ((rdev->family) == CHIP_RV620) || + ((rdev->family) == CHIP_RS780) || + ((rdev->family) == CHIP_RS880)) { + tmp = (CACHE_FIFO_SIZE(0xa) | + FETCH_FIFO_HIWATER(0xa) | + DONE_FIFO_HIWATER(0xe0) | + ALU_UPDATE_FIFO_HIWATER(0x8)); + } else if (((rdev->family) == CHIP_R600) || + ((rdev->family) == CHIP_RV630)) { + tmp &= ~DONE_FIFO_HIWATER(0xff); + tmp |= DONE_FIFO_HIWATER(0x4); + } + WREG32(SQ_MS_FIFO_SIZES, tmp); + + /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT + * should be adjusted as needed by the 2D/3D drivers. This just sets default values + */ + sq_config = RREG32(SQ_CONFIG); + sq_config &= ~(PS_PRIO(3) | + VS_PRIO(3) | + GS_PRIO(3) | + ES_PRIO(3)); + sq_config |= (DX9_CONSTS | + VC_ENABLE | + PS_PRIO(0) | + VS_PRIO(1) | + GS_PRIO(2) | + ES_PRIO(3)); + + if ((rdev->family) == CHIP_R600) { + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(124) | + NUM_VS_GPRS(124) | + NUM_CLAUSE_TEMP_GPRS(4)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(0) | + NUM_ES_GPRS(0)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(136) | + NUM_VS_THREADS(48) | + NUM_GS_THREADS(4) | + NUM_ES_THREADS(4)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(128) | + NUM_VS_STACK_ENTRIES(128)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(0) | + NUM_ES_STACK_ENTRIES(0)); + } else if (((rdev->family) == CHIP_RV610) || + ((rdev->family) == CHIP_RV620) || + ((rdev->family) == CHIP_RS780) || + ((rdev->family) == CHIP_RS880)) { + /* no vertex cache */ + sq_config &= ~VC_ENABLE; + + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | + NUM_VS_GPRS(44) | + NUM_CLAUSE_TEMP_GPRS(2)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(17) | + NUM_ES_GPRS(17)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | + NUM_VS_THREADS(78) | + NUM_GS_THREADS(4) | + NUM_ES_THREADS(31)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(40) | + NUM_VS_STACK_ENTRIES(40)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(32) | + NUM_ES_STACK_ENTRIES(16)); + } else if (((rdev->family) == CHIP_RV630) || + ((rdev->family) == CHIP_RV635)) { + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | + NUM_VS_GPRS(44) | + NUM_CLAUSE_TEMP_GPRS(2)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(18) | + NUM_ES_GPRS(18)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | + NUM_VS_THREADS(78) | + NUM_GS_THREADS(4) | + NUM_ES_THREADS(31)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(40) | + NUM_VS_STACK_ENTRIES(40)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(32) | + NUM_ES_STACK_ENTRIES(16)); + } else if ((rdev->family) == CHIP_RV670) { + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | + NUM_VS_GPRS(44) | + NUM_CLAUSE_TEMP_GPRS(2)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(17) | + NUM_ES_GPRS(17)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | + NUM_VS_THREADS(78) | + NUM_GS_THREADS(4) | + NUM_ES_THREADS(31)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(64) | + NUM_VS_STACK_ENTRIES(64)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(64) | + NUM_ES_STACK_ENTRIES(64)); + } + + WREG32(SQ_CONFIG, sq_config); + WREG32(SQ_GPR_RESOURCE_MGMT_1, sq_gpr_resource_mgmt_1); + WREG32(SQ_GPR_RESOURCE_MGMT_2, sq_gpr_resource_mgmt_2); + WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); + WREG32(SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1); + WREG32(SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2); + + if (((rdev->family) == CHIP_RV610) || + ((rdev->family) == CHIP_RV620) || + ((rdev->family) == CHIP_RS780) || + ((rdev->family) == CHIP_RS880)) { + WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(TC_ONLY)); + } else { + WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC)); + } + + /* More default values. 2D/3D driver should adjust as needed */ + WREG32(PA_SC_AA_SAMPLE_LOCS_2S, (S0_X(0xc) | S0_Y(0x4) | + S1_X(0x4) | S1_Y(0xc))); + WREG32(PA_SC_AA_SAMPLE_LOCS_4S, (S0_X(0xe) | S0_Y(0xe) | + S1_X(0x2) | S1_Y(0x2) | + S2_X(0xa) | S2_Y(0x6) | + S3_X(0x6) | S3_Y(0xa))); + WREG32(PA_SC_AA_SAMPLE_LOCS_8S_WD0, (S0_X(0xe) | S0_Y(0xb) | + S1_X(0x4) | S1_Y(0xc) | + S2_X(0x1) | S2_Y(0x6) | + S3_X(0xa) | S3_Y(0xe))); + WREG32(PA_SC_AA_SAMPLE_LOCS_8S_WD1, (S4_X(0x6) | S4_Y(0x1) | + S5_X(0x0) | S5_Y(0x0) | + S6_X(0xb) | S6_Y(0x4) | + S7_X(0x7) | S7_Y(0x8))); + + WREG32(VGT_STRMOUT_EN, 0); + tmp = rdev->config.r600.max_pipes * 16; + switch (rdev->family) { + case CHIP_RV610: + case CHIP_RV620: + case CHIP_RS780: + case CHIP_RS880: + tmp += 32; + break; + case CHIP_RV670: + tmp += 128; + break; + default: + break; + } + if (tmp > 256) { + tmp = 256; + } + WREG32(VGT_ES_PER_GS, 128); + WREG32(VGT_GS_PER_ES, tmp); + WREG32(VGT_GS_PER_VS, 2); + WREG32(VGT_GS_VERTEX_REUSE, 16); + + /* more default values. 2D/3D driver should adjust as needed */ + WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + WREG32(VGT_STRMOUT_EN, 0); + WREG32(SX_MISC, 0); + WREG32(PA_SC_MODE_CNTL, 0); + WREG32(PA_SC_AA_CONFIG, 0); + WREG32(PA_SC_LINE_STIPPLE, 0); + WREG32(SPI_INPUT_Z, 0); + WREG32(SPI_PS_IN_CONTROL_0, NUM_INTERP(2)); + WREG32(CB_COLOR7_FRAG, 0); + + /* Clear render buffer base addresses */ + WREG32(CB_COLOR0_BASE, 0); + WREG32(CB_COLOR1_BASE, 0); + WREG32(CB_COLOR2_BASE, 0); + WREG32(CB_COLOR3_BASE, 0); + WREG32(CB_COLOR4_BASE, 0); + WREG32(CB_COLOR5_BASE, 0); + WREG32(CB_COLOR6_BASE, 0); + WREG32(CB_COLOR7_BASE, 0); + WREG32(CB_COLOR7_FRAG, 0); + + switch (rdev->family) { + case CHIP_RV610: + case CHIP_RV620: + case CHIP_RS780: + case CHIP_RS880: + tmp = TC_L2_SIZE(8); + break; + case CHIP_RV630: + case CHIP_RV635: + tmp = TC_L2_SIZE(4); + break; + case CHIP_R600: + tmp = TC_L2_SIZE(0) | L2_DISABLE_LATE_HIT; + break; + default: + tmp = TC_L2_SIZE(0); + break; + } + WREG32(TC_CNTL, tmp); + + tmp = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, tmp); + + tmp = RREG32(ARB_POP); + tmp |= ENABLE_TC128; + WREG32(ARB_POP, tmp); + + WREG32(PA_SC_MULTI_CHIP_CNTL, 0); + WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | + NUM_CLIP_SEQ(3))); + WREG32(PA_SC_ENHANCE, FORCE_EOV_MAX_CLK_CNT(4095)); + WREG32(VC_ENHANCE, 0); +} + + +/* + * Indirect registers accessor + */ +u32 r600_pciep_rreg(struct radeon_device *rdev, u32 reg) +{ + u32 r; + + WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); + (void)RREG32(PCIE_PORT_INDEX); + r = RREG32(PCIE_PORT_DATA); + return r; +} + +void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); + (void)RREG32(PCIE_PORT_INDEX); + WREG32(PCIE_PORT_DATA, (v)); + (void)RREG32(PCIE_PORT_DATA); +} + +/* + * CP & Ring + */ +void r600_cp_stop(struct radeon_device *rdev) +{ + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); + WREG32(SCRATCH_UMSK, 0); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; +} + +int r600_init_microcode(struct radeon_device *rdev) +{ + const char *chip_name; + const char *rlc_chip_name; + size_t pfp_req_size, me_req_size, rlc_req_size; + char fw_name[30]; + int err; + + DRM_DEBUG("\n"); + + switch (rdev->family) { + case CHIP_R600: + chip_name = "R600"; + rlc_chip_name = "R600"; + break; + case CHIP_RV610: + chip_name = "RV610"; + rlc_chip_name = "R600"; + break; + case CHIP_RV630: + chip_name = "RV630"; + rlc_chip_name = "R600"; + break; + case CHIP_RV620: + chip_name = "RV620"; + rlc_chip_name = "R600"; + break; + case CHIP_RV635: + chip_name = "RV635"; + rlc_chip_name = "R600"; + break; + case CHIP_RV670: + chip_name = "RV670"; + rlc_chip_name = "R600"; + break; + case CHIP_RS780: + case CHIP_RS880: + chip_name = "RS780"; + rlc_chip_name = "R600"; + break; + case CHIP_RV770: + chip_name = "RV770"; + rlc_chip_name = "R700"; + break; + case CHIP_RV730: + case CHIP_RV740: + chip_name = "RV730"; + rlc_chip_name = "R700"; + break; + case CHIP_RV710: + chip_name = "RV710"; + rlc_chip_name = "R700"; + break; + case CHIP_CEDAR: + chip_name = "CEDAR"; + rlc_chip_name = "CEDAR"; + break; + case CHIP_REDWOOD: + chip_name = "REDWOOD"; + rlc_chip_name = "REDWOOD"; + break; + case CHIP_JUNIPER: + chip_name = "JUNIPER"; + rlc_chip_name = "JUNIPER"; + break; + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + chip_name = "CYPRESS"; + rlc_chip_name = "CYPRESS"; + break; + case CHIP_PALM: + chip_name = "PALM"; + rlc_chip_name = "SUMO"; + break; + case CHIP_SUMO: + chip_name = "SUMO"; + rlc_chip_name = "SUMO"; + break; + case CHIP_SUMO2: + chip_name = "SUMO2"; + rlc_chip_name = "SUMO"; + break; + default: panic("%s: Unsupported family %d", __func__, rdev->family); + } + + if (rdev->family >= CHIP_CEDAR) { + pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; + me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; + rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; + } else if (rdev->family >= CHIP_RV770) { + pfp_req_size = R700_PFP_UCODE_SIZE * 4; + me_req_size = R700_PM4_UCODE_SIZE * 4; + rlc_req_size = R700_RLC_UCODE_SIZE * 4; + } else { + pfp_req_size = PFP_UCODE_SIZE * 4; + me_req_size = PM4_UCODE_SIZE * 12; + rlc_req_size = RLC_UCODE_SIZE * 4; + } + + DRM_INFO("Loading %s Microcode\n", chip_name); + err = 0; + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_pfp", chip_name); + rdev->pfp_fw = firmware_get(fw_name); + if (rdev->pfp_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->pfp_fw->datasize != pfp_req_size) { + DRM_ERROR( + "r600_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->pfp_fw->datasize, fw_name); + err = -EINVAL; + goto out; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_me", chip_name); + rdev->me_fw = firmware_get(fw_name); + if (rdev->me_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->me_fw->datasize != me_req_size) { + DRM_ERROR( + "r600_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->me_fw->datasize, fw_name); + err = -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_rlc", rlc_chip_name); + rdev->rlc_fw = firmware_get(fw_name); + if (rdev->rlc_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->rlc_fw->datasize != rlc_req_size) { + DRM_ERROR( + "r600_rlc: Bogus length %zu in firmware \"%s\"\n", + rdev->rlc_fw->datasize, fw_name); + err = -EINVAL; + } + +out: + if (err) { + if (err != -EINVAL) + DRM_ERROR( + "r600_cp: Failed to load firmware \"%s\"\n", + fw_name); + if (rdev->pfp_fw != NULL) { + firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); + rdev->pfp_fw = NULL; + } + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + if (rdev->rlc_fw != NULL) { + firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); + rdev->rlc_fw = NULL; + } + } + return err; +} + +/** + * r600_fini_microcode - drop the firmwares image references + * + * @rdev: radeon_device pointer + * + * Drop the pfp, me and rlc firmwares image references. + * Called at driver shutdown. + */ +void r600_fini_microcode(struct radeon_device *rdev) +{ + + if (rdev->pfp_fw != NULL) { + firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); + rdev->pfp_fw = NULL; + } + + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + + if (rdev->rlc_fw != NULL) { + firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); + rdev->rlc_fw = NULL; + } +} + +static int r600_cp_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + int i; + + if (!rdev->me_fw || !rdev->pfp_fw) + return -EINVAL; + + r600_cp_stop(rdev); + + WREG32(CP_RB_CNTL, +#ifdef __BIG_ENDIAN + BUF_SWAP_32BIT | +#endif + RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3)); + + /* Reset cp */ + WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); + RREG32(GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(GRBM_SOFT_RESET, 0); + + WREG32(CP_ME_RAM_WADDR, 0); + + fw_data = (const __be32 *)rdev->me_fw->data; + WREG32(CP_ME_RAM_WADDR, 0); + for (i = 0; i < PM4_UCODE_SIZE * 3; i++) + WREG32(CP_ME_RAM_DATA, + be32_to_cpup(fw_data++)); + + fw_data = (const __be32 *)rdev->pfp_fw->data; + WREG32(CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < PFP_UCODE_SIZE; i++) + WREG32(CP_PFP_UCODE_DATA, + be32_to_cpup(fw_data++)); + + WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_RADDR, 0); + return 0; +} + +int r600_cp_start(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + uint32_t cp_me; + + r = radeon_ring_lock(rdev, ring, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(ring, 0x1); + if (rdev->family >= CHIP_RV770) { + radeon_ring_write(ring, 0x0); + radeon_ring_write(ring, rdev->config.rv770.max_hw_contexts - 1); + } else { + radeon_ring_write(ring, 0x3); + radeon_ring_write(ring, rdev->config.r600.max_hw_contexts - 1); + } + radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_unlock_commit(rdev, ring); + + cp_me = 0xff; + WREG32(R_0086D8_CP_ME_CNTL, cp_me); + return 0; +} + +int r600_cp_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 tmp; + u32 rb_bufsz; + int r; + + /* Reset cp */ + WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); + RREG32(GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(GRBM_SOFT_RESET, 0); + + /* Set ring buffer size */ + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB_CNTL, tmp); + WREG32(CP_SEM_WAIT_TIMER, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); + WREG32(CP_RB_RPTR_WR, 0); + ring->wptr = 0; + WREG32(CP_RB_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(CP_RB_RPTR_ADDR, + ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC)); + WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); + WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); + + if (rdev->wb.enabled) + WREG32(SCRATCH_UMSK, 0xff); + else { + tmp |= RB_NO_UPDATE; + WREG32(SCRATCH_UMSK, 0); + } + + DRM_MDELAY(1); + WREG32(CP_RB_CNTL, tmp); + + WREG32(CP_RB_BASE, ring->gpu_addr >> 8); + WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); + + ring->rptr = RREG32(CP_RB_RPTR); + + r600_cp_start(rdev); + ring->ready = true; + r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); + if (r) { + ring->ready = false; + return r; + } + return 0; +} + +void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) +{ + u32 rb_bufsz; + int r; + + /* Align ring size */ + rb_bufsz = drm_order(ring_size / 8); + ring_size = (1 << (rb_bufsz + 1)) * 4; + ring->ring_size = ring_size; + ring->align_mask = 16 - 1; + + if (radeon_ring_supports_scratch_reg(rdev, ring)) { + r = radeon_scratch_get(rdev, &ring->rptr_save_reg); + if (r) { + DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); + ring->rptr_save_reg = 0; + } + } +} + +void r600_cp_fini(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r600_cp_stop(rdev); + radeon_ring_fini(rdev, ring); + radeon_scratch_free(rdev, ring->rptr_save_reg); +} + +/* + * DMA + * Starting with R600, the GPU has an asynchronous + * DMA engine. The programming model is very similar + * to the 3D engine (ring buffer, IBs, etc.), but the + * DMA controller has it's own packet format that is + * different form the PM4 format used by the 3D engine. + * It supports copying data, writing embedded data, + * solid fills, and a number of other things. It also + * has support for tiling/detiling of buffers. + */ +/** + * r600_dma_stop - stop the async dma engine + * + * @rdev: radeon_device pointer + * + * Stop the async dma engine (r6xx-evergreen). + */ +void r600_dma_stop(struct radeon_device *rdev) +{ + u32 rb_cntl = RREG32(DMA_RB_CNTL); + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + + rb_cntl &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL, rb_cntl); + + rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false; +} + +/** + * r600_dma_resume - setup and start the async dma engine + * + * @rdev: radeon_device pointer + * + * Set up the DMA ring buffer and enable it. (r6xx-evergreen). + * Returns 0 for success, error for failure. + */ +int r600_dma_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + u32 rb_cntl, dma_cntl, ib_cntl; + u32 rb_bufsz; + int r; + + /* Reset dma */ + if (rdev->family >= CHIP_RV770) + WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA); + else + WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA); + RREG32(SRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(SRBM_SOFT_RESET, 0); + + WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL, 0); + WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL, 0); + + /* Set ring buffer size in dwords */ + rb_bufsz = drm_order(ring->ring_size / 4); + rb_cntl = rb_bufsz << 1; +#ifdef __BIG_ENDIAN + rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE; +#endif + WREG32(DMA_RB_CNTL, rb_cntl); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(DMA_RB_RPTR, 0); + WREG32(DMA_RB_WPTR, 0); + + /* set the wb address whether it's enabled or not */ + WREG32(DMA_RB_RPTR_ADDR_HI, + upper_32_bits(rdev->wb.gpu_addr + R600_WB_DMA_RPTR_OFFSET) & 0xFF); + WREG32(DMA_RB_RPTR_ADDR_LO, + ((rdev->wb.gpu_addr + R600_WB_DMA_RPTR_OFFSET) & 0xFFFFFFFC)); + + if (rdev->wb.enabled) + rb_cntl |= DMA_RPTR_WRITEBACK_ENABLE; + + WREG32(DMA_RB_BASE, ring->gpu_addr >> 8); + + /* enable DMA IBs */ + ib_cntl = DMA_IB_ENABLE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL, ib_cntl); + + dma_cntl = RREG32(DMA_CNTL); + dma_cntl &= ~CTXEMPTY_INT_ENABLE; + WREG32(DMA_CNTL, dma_cntl); + + if (rdev->family >= CHIP_RV770) + WREG32(DMA_MODE, 1); + + ring->wptr = 0; + WREG32(DMA_RB_WPTR, ring->wptr << 2); + + ring->rptr = RREG32(DMA_RB_RPTR) >> 2; + + WREG32(DMA_RB_CNTL, rb_cntl | DMA_RB_ENABLE); + + ring->ready = true; + + r = radeon_ring_test(rdev, R600_RING_TYPE_DMA_INDEX, ring); + if (r) { + ring->ready = false; + return r; + } + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + + return 0; +} + +/** + * r600_dma_fini - tear down the async dma engine + * + * @rdev: radeon_device pointer + * + * Stop the async dma engine and free the ring (r6xx-evergreen). + */ +void r600_dma_fini(struct radeon_device *rdev) +{ + r600_dma_stop(rdev); + radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]); +} + +/* + * GPU scratch registers helpers function. + */ +void r600_scratch_init(struct radeon_device *rdev) +{ + int i; + + rdev->scratch.num_reg = 7; + rdev->scratch.reg_base = SCRATCH_REG0; + for (i = 0; i < rdev->scratch.num_reg; i++) { + rdev->scratch.free[i] = true; + rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); + } +} + +int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) +{ + uint32_t scratch; + uint32_t tmp = 0; + unsigned i; + int r; + + r = radeon_scratch_get(rdev, &scratch); + if (r) { + DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + r = radeon_ring_lock(rdev, ring, 3); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r); + radeon_scratch_free(rdev, scratch); + return r; + } + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); + radeon_ring_write(ring, 0xDEADBEEF); + radeon_ring_unlock_commit(rdev, ring); + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { + DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); + } else { + DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", + ring->idx, scratch, tmp); + r = -EINVAL; + } + radeon_scratch_free(rdev, scratch); + return r; +} + +/** + * r600_dma_ring_test - simple async dma engine test + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Test the DMA engine by writing using it to write an + * value to memory. (r6xx-SI). + * Returns 0 for success, error for failure. + */ +int r600_dma_ring_test(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + unsigned i; + int r; + volatile uint32_t *ptr = rdev->vram_scratch.ptr; + u32 tmp; + + if (!ptr) { + DRM_ERROR("invalid vram scratch pointer\n"); + return -EINVAL; + } + + tmp = 0xCAFEDEAD; + *ptr = tmp; + + r = radeon_ring_lock(rdev, ring, 4); + if (r) { + DRM_ERROR("radeon: dma failed to lock ring %d (%d).\n", ring->idx, r); + return r; + } + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1)); + radeon_ring_write(ring, rdev->vram_scratch.gpu_addr & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xff); + radeon_ring_write(ring, 0xDEADBEEF); + radeon_ring_unlock_commit(rdev, ring); + + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = *ptr; + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + + if (i < rdev->usec_timeout) { + DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); + } else { + DRM_ERROR("radeon: ring %d test failed (0x%08X)\n", + ring->idx, tmp); + r = -EINVAL; + } + return r; +} + +/* + * CP fences/semaphores + */ + +void r600_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + + if (rdev->wb.use_event) { + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + /* flush read cache over gart */ + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | + PACKET3_VC_ACTION_ENA | + PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ + /* EVENT_WRITE_EOP - flush caches, send int */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); + radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); + radeon_ring_write(ring, fence->seq); + radeon_ring_write(ring, 0); + } else { + /* flush read cache over gart */ + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | + PACKET3_VC_ACTION_ENA | + PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0)); + radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); + /* wait for 3D idle clean */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); + radeon_ring_write(ring, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); + /* Emit fence sequence & fire IRQ */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, ((rdev->fence_drv[fence->ring].scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); + radeon_ring_write(ring, fence->seq); + /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ + radeon_ring_write(ring, PACKET0(CP_INT_STATUS, 0)); + radeon_ring_write(ring, RB_INT_STAT); + } +} + +void r600_semaphore_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring, + struct radeon_semaphore *semaphore, + bool emit_wait) +{ + uint64_t addr = semaphore->gpu_addr; + unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL; + + if (rdev->family < CHIP_CAYMAN) + sel |= PACKET3_SEM_WAIT_ON_SIGNAL; + + radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1)); + radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel); +} + +/* + * DMA fences/semaphores + */ + +/** + * r600_dma_fence_ring_emit - emit a fence on the DMA ring + * + * @rdev: radeon_device pointer + * @fence: radeon fence object + * + * Add a DMA fence packet to the ring to write + * the fence seq number and DMA trap packet to generate + * an interrupt if needed (r6xx-r7xx). + */ +void r600_dma_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + + /* write the fence */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0)); + radeon_ring_write(ring, addr & 0xfffffffc); + radeon_ring_write(ring, (upper_32_bits(addr) & 0xff)); + radeon_ring_write(ring, lower_32_bits(fence->seq)); + /* generate an interrupt */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0)); +} + +/** + * r600_dma_semaphore_ring_emit - emit a semaphore on the dma ring + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * @semaphore: radeon semaphore object + * @emit_wait: wait or signal semaphore + * + * Add a DMA semaphore packet to the ring wait on or signal + * other rings (r6xx-SI). + */ +void r600_dma_semaphore_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring, + struct radeon_semaphore *semaphore, + bool emit_wait) +{ + u64 addr = semaphore->gpu_addr; + u32 s = emit_wait ? 0 : 1; + + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SEMAPHORE, 0, s, 0)); + radeon_ring_write(ring, addr & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(addr) & 0xff); +} + +int r600_copy_blit(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_semaphore *sem = NULL; + struct radeon_sa_bo *vb = NULL; + int r; + + r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, &vb, &sem); + if (r) { + return r; + } + r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb); + r600_blit_done_copy(rdev, fence, vb, sem); + return 0; +} + +/** + * r600_copy_dma - copy pages using the DMA engine + * + * @rdev: radeon_device pointer + * @src_offset: src GPU address + * @dst_offset: dst GPU address + * @num_gpu_pages: number of GPU pages to xfer + * @fence: radeon fence object + * + * Copy GPU paging using the DMA engine (r6xx). + * Used by the radeon ttm implementation to move pages if + * registered as the asic copy callback. + */ +int r600_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_semaphore *sem = NULL; + int ring_index = rdev->asic->copy.dma_ring_index; + struct radeon_ring *ring = &rdev->ring[ring_index]; + u32 size_in_dw, cur_size_in_dw; + int i, num_loops; + int r = 0; + + r = radeon_semaphore_create(rdev, &sem); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + + size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4; + num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFE); + r = radeon_ring_lock(rdev, ring, num_loops * 4 + 8); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + radeon_semaphore_free(rdev, &sem, NULL); + return r; + } + + if (radeon_fence_need_sync(*fence, ring->idx)) { + radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, + ring->idx); + radeon_fence_note_sync(*fence, ring->idx); + } else { + radeon_semaphore_free(rdev, &sem, NULL); + } + + for (i = 0; i < num_loops; i++) { + cur_size_in_dw = size_in_dw; + if (cur_size_in_dw > 0xFFFE) + cur_size_in_dw = 0xFFFE; + size_in_dw -= cur_size_in_dw; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw)); + radeon_ring_write(ring, dst_offset & 0xfffffffc); + radeon_ring_write(ring, src_offset & 0xfffffffc); + radeon_ring_write(ring, (((upper_32_bits(dst_offset) & 0xff) << 16) | + (upper_32_bits(src_offset) & 0xff))); + src_offset += cur_size_in_dw * 4; + dst_offset += cur_size_in_dw * 4; + } + + r = radeon_fence_emit(rdev, fence, ring->idx); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + + radeon_ring_unlock_commit(rdev, ring); + radeon_semaphore_free(rdev, &sem, *fence); + + return r; +} + +int r600_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size) +{ + /* FIXME: implement */ + return 0; +} + +void r600_clear_surface_reg(struct radeon_device *rdev, int reg) +{ + /* FIXME: implement */ +} + +static int r600_startup(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + int r; + + /* enable pcie gen2 link */ + r600_pcie_gen2_enable(rdev); + + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + r = r600_vram_scratch_init(rdev); + if (r) + return r; + + r600_mc_program(rdev); + if (rdev->flags & RADEON_IS_AGP) { + r600_agp_enable(rdev); + } else { + r = r600_pcie_gart_enable(rdev); + if (r) + return r; + } + r600_gpu_init(rdev); + r = r600_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); + rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + r600_irq_set(rdev); + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, + R600_CP_RB_RPTR, R600_CP_RB_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, + DMA_RB_RPTR, DMA_RB_WPTR, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + if (r) + return r; + + r = r600_cp_load_microcode(rdev); + if (r) + return r; + r = r600_cp_resume(rdev); + if (r) + return r; + + r = r600_dma_resume(rdev); + if (r) + return r; + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = r600_audio_init(rdev); + if (r) { + DRM_ERROR("radeon: audio init failed\n"); + return r; + } + + return 0; +} + +void r600_vga_set_state(struct radeon_device *rdev, bool state) +{ + uint32_t temp; + + temp = RREG32(CONFIG_CNTL); + if (state == false) { + temp &= ~(1<<0); + temp |= (1<<1); + } else { + temp &= ~(1<<1); + } + WREG32(CONFIG_CNTL, temp); +} + +int r600_resume(struct radeon_device *rdev) +{ + int r; + + /* Do not reset GPU before posting, on r600 hw unlike on r500 hw, + * posting will perform necessary task to bring back GPU into good + * shape. + */ + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + + rdev->accel_working = true; + r = r600_startup(rdev); + if (r) { + DRM_ERROR("r600 startup failed on resume\n"); + rdev->accel_working = false; + return r; + } + + return r; +} + +int r600_suspend(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r600_cp_stop(rdev); + r600_dma_stop(rdev); + r600_irq_suspend(rdev); + radeon_wb_disable(rdev); + r600_pcie_gart_disable(rdev); + + return 0; +} + +/* Plan is to move initialization in that function and use + * helper function so that radeon_device_init pretty much + * do nothing more than calling asic specific function. This + * should also allow to remove a bunch of callback function + * like vram_info. + */ +int r600_init(struct radeon_device *rdev) +{ + int r; + + if (r600_debugfs_mc_info_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for mc !\n"); + } + /* Read BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); + if (r) + return r; + /* Post card if necessary */ + if (!radeon_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize scratch registers */ + r600_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + radeon_agp_disable(rdev); + } + r = r600_mc_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); + + rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); + + r = r600_pcie_gart_init(rdev); + if (r) + return r; + + rdev->accel_working = true; + r = r600_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + r600_cp_fini(rdev); + r600_dma_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + r600_pcie_gart_fini(rdev); + rdev->accel_working = false; + } + + return 0; +} + +void r600_fini(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r600_blit_fini(rdev); + r600_cp_fini(rdev); + r600_dma_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + r600_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_agp_fini(rdev); + radeon_gem_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + r600_fini_microcode(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + + +/* + * CS stuff + */ +void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + u32 next_rptr; + + if (ring->rptr_save_reg) { + next_rptr = ring->wptr + 3 + 4; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, ((ring->rptr_save_reg - + PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); + radeon_ring_write(ring, next_rptr); + } else if (rdev->wb.enabled) { + next_rptr = ring->wptr + 5 + 4; + radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); + radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); + radeon_ring_write(ring, next_rptr); + radeon_ring_write(ring, 0); + } + + radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); + radeon_ring_write(ring, ib->length_dw); +} + +int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) +{ + struct radeon_ib ib; + uint32_t scratch; + uint32_t tmp = 0; + unsigned i; + int r; + + r = radeon_scratch_get(rdev, &scratch); + if (r) { + DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256); + if (r) { + DRM_ERROR("radeon: failed to get ib (%d).\n", r); + goto free_scratch; + } + ib.ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1); + ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); + ib.ptr[2] = 0xDEADBEEF; + ib.length_dw = 3; + r = radeon_ib_schedule(rdev, &ib, NULL); + if (r) { + DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); + goto free_ib; + } + r = radeon_fence_wait(ib.fence, false); + if (r) { + DRM_ERROR("radeon: fence wait failed (%d).\n", r); + goto free_ib; + } + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { + DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib.fence->ring, i); + } else { + DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", + scratch, tmp); + r = -EINVAL; + } +free_ib: + radeon_ib_free(rdev, &ib); +free_scratch: + radeon_scratch_free(rdev, scratch); + return r; +} + +/** + * r600_dma_ib_test - test an IB on the DMA engine + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Test a simple IB in the DMA ring (r6xx-SI). + * Returns 0 on success, error on failure. + */ +int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) +{ + struct radeon_ib ib; + unsigned i; + int r; + volatile uint32_t *ptr = rdev->vram_scratch.ptr; + u32 tmp = 0; + + if (!ptr) { + DRM_ERROR("invalid vram scratch pointer\n"); + return -EINVAL; + } + + tmp = 0xCAFEDEAD; + *ptr = tmp; + + r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256); + if (r) { + DRM_ERROR("radeon: failed to get ib (%d).\n", r); + return r; + } + + ib.ptr[0] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1); + ib.ptr[1] = rdev->vram_scratch.gpu_addr & 0xfffffffc; + ib.ptr[2] = upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xff; + ib.ptr[3] = 0xDEADBEEF; + ib.length_dw = 4; + + r = radeon_ib_schedule(rdev, &ib, NULL); + if (r) { + radeon_ib_free(rdev, &ib); + DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); + return r; + } + r = radeon_fence_wait(ib.fence, false); + if (r) { + radeon_ib_free(rdev, &ib); + DRM_ERROR("radeon: fence wait failed (%d).\n", r); + return r; + } + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = *ptr; + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { + DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib.fence->ring, i); + } else { + DRM_ERROR("radeon: ib test failed (0x%08X)\n", tmp); + r = -EINVAL; + } + radeon_ib_free(rdev, &ib); + return r; +} + +/** + * r600_dma_ring_ib_execute - Schedule an IB on the DMA engine + * + * @rdev: radeon_device pointer + * @ib: IB object to schedule + * + * Schedule an IB in the DMA ring (r6xx-r7xx). + */ +void r600_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + + if (rdev->wb.enabled) { + u32 next_rptr = ring->wptr + 4; + while ((next_rptr & 7) != 5) + next_rptr++; + next_rptr += 3; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1)); + radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff); + radeon_ring_write(ring, next_rptr); + } + + /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring. + * Pad as necessary with NOPs. + */ + while ((ring->wptr & 7) != 5) + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_INDIRECT_BUFFER, 0, 0, 0)); + radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0)); + radeon_ring_write(ring, (ib->length_dw << 16) | (upper_32_bits(ib->gpu_addr) & 0xFF)); + +} + +/* + * Interrupts + * + * Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty + * the same as the CP ring buffer, but in reverse. Rather than the CPU + * writing to the ring and the GPU consuming, the GPU writes to the ring + * and host consumes. As the host irq handler processes interrupts, it + * increments the rptr. When the rptr catches up with the wptr, all the + * current interrupts have been processed. + */ + +void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) +{ + u32 rb_bufsz; + + /* Align ring size */ + rb_bufsz = drm_order(ring_size / 4); + ring_size = (1 << rb_bufsz) * 4; + rdev->ih.ring_size = ring_size; + rdev->ih.ptr_mask = rdev->ih.ring_size - 1; + rdev->ih.rptr = 0; +} + +int r600_ih_ring_alloc(struct radeon_device *rdev) +{ + int r; + void *ring_ptr; + + /* Allocate ring buffer */ + if (rdev->ih.ring_obj == NULL) { + r = radeon_bo_create(rdev, rdev->ih.ring_size, + PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, + NULL, &rdev->ih.ring_obj); + if (r) { + DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); + return r; + } + r = radeon_bo_reserve(rdev->ih.ring_obj, false); + if (unlikely(r != 0)) { + radeon_bo_unref(&rdev->ih.ring_obj); + return r; + } + r = radeon_bo_pin(rdev->ih.ring_obj, + RADEON_GEM_DOMAIN_GTT, + &rdev->ih.gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->ih.ring_obj); + radeon_bo_unref(&rdev->ih.ring_obj); + DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r); + return r; + } + ring_ptr = &rdev->ih.ring; + r = radeon_bo_kmap(rdev->ih.ring_obj, + ring_ptr); + if (r) + radeon_bo_unpin(rdev->ih.ring_obj); + radeon_bo_unreserve(rdev->ih.ring_obj); + if (r) { + DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r); + radeon_bo_unref(&rdev->ih.ring_obj); + return r; + } + } + return 0; +} + +void r600_ih_ring_fini(struct radeon_device *rdev) +{ + int r; + if (rdev->ih.ring_obj) { + r = radeon_bo_reserve(rdev->ih.ring_obj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->ih.ring_obj); + radeon_bo_unpin(rdev->ih.ring_obj); + radeon_bo_unreserve(rdev->ih.ring_obj); + } + radeon_bo_unref(&rdev->ih.ring_obj); + rdev->ih.ring = NULL; + rdev->ih.ring_obj = NULL; + } +} + +void r600_rlc_stop(struct radeon_device *rdev) +{ + + if ((rdev->family >= CHIP_RV770) && + (rdev->family <= CHIP_RV740)) { + /* r7xx asics need to soft reset RLC before halting */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); + RREG32(SRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(SRBM_SOFT_RESET, 0); + RREG32(SRBM_SOFT_RESET); + } + + WREG32(RLC_CNTL, 0); +} + +static void r600_rlc_start(struct radeon_device *rdev) +{ + WREG32(RLC_CNTL, RLC_ENABLE); +} + +static int r600_rlc_init(struct radeon_device *rdev) +{ + u32 i; + const __be32 *fw_data; + + if (!rdev->rlc_fw) + return -EINVAL; + + r600_rlc_stop(rdev); + + WREG32(RLC_HB_CNTL, 0); + + if (rdev->family == CHIP_ARUBA) { + WREG32(TN_RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); + WREG32(TN_RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); + } + if (rdev->family <= CHIP_CAYMAN) { + WREG32(RLC_HB_BASE, 0); + WREG32(RLC_HB_RPTR, 0); + WREG32(RLC_HB_WPTR, 0); + } + if (rdev->family <= CHIP_CAICOS) { + WREG32(RLC_HB_WPTR_LSB_ADDR, 0); + WREG32(RLC_HB_WPTR_MSB_ADDR, 0); + } + WREG32(RLC_MC_CNTL, 0); + WREG32(RLC_UCODE_CNTL, 0); + + fw_data = (const __be32 *)rdev->rlc_fw->data; + if (rdev->family >= CHIP_ARUBA) { + for (i = 0; i < ARUBA_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } else if (rdev->family >= CHIP_CAYMAN) { + for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } else if (rdev->family >= CHIP_CEDAR) { + for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } else if (rdev->family >= CHIP_RV770) { + for (i = 0; i < R700_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } else { + for (i = 0; i < RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + } + WREG32(RLC_UCODE_ADDR, 0); + + r600_rlc_start(rdev); + + return 0; +} + +static void r600_enable_interrupts(struct radeon_device *rdev) +{ + u32 ih_cntl = RREG32(IH_CNTL); + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + + ih_cntl |= ENABLE_INTR; + ih_rb_cntl |= IH_RB_ENABLE; + WREG32(IH_CNTL, ih_cntl); + WREG32(IH_RB_CNTL, ih_rb_cntl); + rdev->ih.enabled = true; +} + +void r600_disable_interrupts(struct radeon_device *rdev) +{ + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + u32 ih_cntl = RREG32(IH_CNTL); + + ih_rb_cntl &= ~IH_RB_ENABLE; + ih_cntl &= ~ENABLE_INTR; + WREG32(IH_RB_CNTL, ih_rb_cntl); + WREG32(IH_CNTL, ih_cntl); + /* set rptr, wptr to 0 */ + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + rdev->ih.enabled = false; + rdev->ih.rptr = 0; +} + +static void r600_disable_interrupt_state(struct radeon_device *rdev) +{ + u32 tmp; + + WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + tmp = RREG32(DMA_CNTL) & ~TRAP_ENABLE; + WREG32(DMA_CNTL, tmp); + WREG32(GRBM_INT_CNTL, 0); + WREG32(DxMODE_INT_MASK, 0); + WREG32(D1GRPH_INTERRUPT_CONTROL, 0); + WREG32(D2GRPH_INTERRUPT_CONTROL, 0); + if (ASIC_IS_DCE3(rdev)) { + WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); + tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + if (ASIC_IS_DCE32(rdev)) { + tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); + } else { + tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); + tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); + } + } else { + WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DACB_AUTODETECT_INT_CONTROL, 0); + tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); + tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); + tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); + } +} + +int r600_irq_init(struct radeon_device *rdev) +{ + int ret = 0; + int rb_bufsz; + u32 interrupt_cntl, ih_cntl, ih_rb_cntl; + + /* allocate ring */ + ret = r600_ih_ring_alloc(rdev); + if (ret) + return ret; + + /* disable irqs */ + r600_disable_interrupts(rdev); + + /* init rlc */ + ret = r600_rlc_init(rdev); + if (ret) { + r600_ih_ring_fini(rdev); + return ret; + } + + /* setup interrupt control */ + /* set dummy read address to ring address */ + WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); + interrupt_cntl = RREG32(INTERRUPT_CNTL); + /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi + * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN + */ + interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; + /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ + interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; + WREG32(INTERRUPT_CNTL, interrupt_cntl); + + WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); + rb_bufsz = drm_order(rdev->ih.ring_size / 4); + + ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | + IH_WPTR_OVERFLOW_CLEAR | + (rb_bufsz << 1)); + + if (rdev->wb.enabled) + ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; + + /* set the writeback address whether it's enabled or not */ + WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); + WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); + + WREG32(IH_RB_CNTL, ih_rb_cntl); + + /* set rptr, wptr to 0 */ + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + + /* Default settings for IH_CNTL (disabled at first) */ + ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10); + /* RPTR_REARM only works if msi's are enabled */ + if (rdev->msi_enabled) + ih_cntl |= RPTR_REARM; + WREG32(IH_CNTL, ih_cntl); + + /* force the active interrupt state to all disabled */ + if (rdev->family >= CHIP_CEDAR) + evergreen_disable_interrupt_state(rdev); + else + r600_disable_interrupt_state(rdev); + + /* at this point everything should be setup correctly to enable master */ + pci_enable_busmaster(rdev->dev); + + /* enable irqs */ + r600_enable_interrupts(rdev); + + return ret; +} + +void r600_irq_suspend(struct radeon_device *rdev) +{ + r600_irq_disable(rdev); + r600_rlc_stop(rdev); +} + +void r600_irq_fini(struct radeon_device *rdev) +{ + r600_irq_suspend(rdev); + r600_ih_ring_fini(rdev); +} + +int r600_irq_set(struct radeon_device *rdev) +{ + u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 mode_int = 0; + u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; + u32 grbm_int_cntl = 0; + u32 hdmi0, hdmi1; + u32 d1grph = 0, d2grph = 0; + u32 dma_cntl; + + if (!rdev->irq.installed) { + DRM_ERROR("Can't enable IRQ/MSI because no handler is installed\n"); + return -EINVAL; + } + /* don't enable anything if the ih is disabled */ + if (!rdev->ih.enabled) { + r600_disable_interrupts(rdev); + /* force the active interrupt state to all disabled */ + r600_disable_interrupt_state(rdev); + return 0; + } + + if (ASIC_IS_DCE3(rdev)) { + hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; + if (ASIC_IS_DCE32(rdev)) { + hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; + hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + } else { + hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + } + } else { + hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; + hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + } + dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE; + + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("r600_irq_set: sw int\n"); + cp_int_cntl |= RB_INT_ENABLE; + cp_int_cntl |= TIME_STAMP_INT_ENABLE; + } + + if (atomic_read(&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX])) { + DRM_DEBUG("r600_irq_set: sw int dma\n"); + dma_cntl |= TRAP_ENABLE; + } + + if (rdev->irq.crtc_vblank_int[0] || + atomic_read(&rdev->irq.pflip[0])) { + DRM_DEBUG("r600_irq_set: vblank 0\n"); + mode_int |= D1MODE_VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[1] || + atomic_read(&rdev->irq.pflip[1])) { + DRM_DEBUG("r600_irq_set: vblank 1\n"); + mode_int |= D2MODE_VBLANK_INT_MASK; + } + if (rdev->irq.hpd[0]) { + DRM_DEBUG("r600_irq_set: hpd 1\n"); + hpd1 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[1]) { + DRM_DEBUG("r600_irq_set: hpd 2\n"); + hpd2 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[2]) { + DRM_DEBUG("r600_irq_set: hpd 3\n"); + hpd3 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[3]) { + DRM_DEBUG("r600_irq_set: hpd 4\n"); + hpd4 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[4]) { + DRM_DEBUG("r600_irq_set: hpd 5\n"); + hpd5 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[5]) { + DRM_DEBUG("r600_irq_set: hpd 6\n"); + hpd6 |= DC_HPDx_INT_EN; + } + if (rdev->irq.afmt[0]) { + DRM_DEBUG("r600_irq_set: hdmi 0\n"); + hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK; + } + if (rdev->irq.afmt[1]) { + DRM_DEBUG("r600_irq_set: hdmi 0\n"); + hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK; + } + + WREG32(CP_INT_CNTL, cp_int_cntl); + WREG32(DMA_CNTL, dma_cntl); + WREG32(DxMODE_INT_MASK, mode_int); + WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); + WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); + WREG32(GRBM_INT_CNTL, grbm_int_cntl); + if (ASIC_IS_DCE3(rdev)) { + WREG32(DC_HPD1_INT_CONTROL, hpd1); + WREG32(DC_HPD2_INT_CONTROL, hpd2); + WREG32(DC_HPD3_INT_CONTROL, hpd3); + WREG32(DC_HPD4_INT_CONTROL, hpd4); + if (ASIC_IS_DCE32(rdev)) { + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, hdmi0); + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, hdmi1); + } else { + WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); + WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1); + } + } else { + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); + WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); + WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1); + } + + return 0; +} + +static void r600_irq_ack(struct radeon_device *rdev) +{ + u32 tmp; + + if (ASIC_IS_DCE3(rdev)) { + rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); + if (ASIC_IS_DCE32(rdev)) { + rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET0); + rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET1); + } else { + rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); + rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS); + } + } else { + rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.r600.disp_int_cont2 = 0; + rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); + rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS); + } + rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); + rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); + + if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED) + WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED) + WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) + WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) + WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) + WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) + WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DC_HPD1_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD1_INT_CONTROL, tmp); + } else { + tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + } + } + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DC_HPD2_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD2_INT_CONTROL, tmp); + } else { + tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + } + } + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DC_HPD3_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD3_INT_CONTROL, tmp); + } else { + tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); + } + } + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { + tmp = RREG32(DC_HPD4_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD4_INT_CONTROL, tmp); + } + if (ASIC_IS_DCE32(rdev)) { + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); + } + if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) { + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1); + tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); + } + } else { + if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { + tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL); + tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; + WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); + } + if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { + if (ASIC_IS_DCE3(rdev)) { + tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL); + tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; + WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); + } else { + tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL); + tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; + WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); + } + } + } +} + +void r600_irq_disable(struct radeon_device *rdev) +{ + r600_disable_interrupts(rdev); + /* Wait and acknowledge irq */ + DRM_MDELAY(1); + r600_irq_ack(rdev); + r600_disable_interrupt_state(rdev); +} + +static u32 r600_get_ih_wptr(struct radeon_device *rdev) +{ + u32 wptr, tmp; + + if (rdev->wb.enabled) + wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); + else + wptr = RREG32(IH_RB_WPTR); + + if (wptr & RB_OVERFLOW) { + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", + wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); + rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); + } + return (wptr & rdev->ih.ptr_mask); +} + +/* r600 IV Ring + * Each IV ring entry is 128 bits: + * [7:0] - interrupt source id + * [31:8] - reserved + * [59:32] - interrupt source data + * [127:60] - reserved + * + * The basic interrupt vector entries + * are decoded as follows: + * src_id src_data description + * 1 0 D1 Vblank + * 1 1 D1 Vline + * 5 0 D2 Vblank + * 5 1 D2 Vline + * 19 0 FP Hot plug detection A + * 19 1 FP Hot plug detection B + * 19 2 DAC A auto-detection + * 19 3 DAC B auto-detection + * 21 4 HDMI block A + * 21 5 HDMI block B + * 176 - CP_INT RB + * 177 - CP_INT IB1 + * 178 - CP_INT IB2 + * 181 - EOP Interrupt + * 233 - GUI Idle + * + * Note, these are based on r600 and may need to be + * adjusted or added to on newer asics + */ + +irqreturn_t r600_irq_process(struct radeon_device *rdev) +{ + u32 wptr; + u32 rptr; + u32 src_id, src_data; + u32 ring_index; + bool queue_hotplug = false; + bool queue_hdmi = false; + + if (!rdev->ih.enabled || rdev->shutdown) + return IRQ_NONE; + + /* No MSIs, need a dummy read to flush PCI DMAs */ + if (!rdev->msi_enabled) + RREG32(IH_RB_WPTR); + + wptr = r600_get_ih_wptr(rdev); + +restart_ih: + /* is somebody else already processing irqs? */ + if (atomic_xchg(&rdev->ih.lock, 1)) + return IRQ_NONE; + + rptr = rdev->ih.rptr; + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + + /* Order reading of wptr vs. reading of IH ring data */ + rmb(); + + /* display interrupts */ + r600_irq_ack(rdev); + + while (rptr != wptr) { + /* wptr/rptr are in bytes! */ + ring_index = rptr / 4; + src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; + src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; + + switch (src_id) { + case 1: /* D1 vblank/vline */ + switch (src_data) { + case 0: /* D1 vblank */ + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_flip(rdev, 0); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + } + break; + case 1: /* D1 vline */ + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 5: /* D2 vblank/vline */ + switch (src_data) { + case 0: /* D2 vblank */ + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_flip(rdev, 1); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + } + break; + case 1: /* D1 vline */ + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 19: /* HPD/DAC hotplug */ + switch (src_data) { + case 0: + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + } + break; + case 1: + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + } + break; + case 4: + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + } + break; + case 5: + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + } + break; + case 10: + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + } + break; + case 12: + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 21: /* hdmi */ + switch (src_data) { + case 4: + if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI0\n"); + } + break; + case 5: + if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { + rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI1\n"); + } + break; + default: + DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 176: /* CP_INT in ring buffer */ + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ + DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 181: /* CP EOP event */ + DRM_DEBUG("IH: CP EOP\n"); + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 224: /* DMA trap event */ + DRM_DEBUG("IH: DMA trap\n"); + radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX); + break; + case 233: /* GUI IDLE */ + DRM_DEBUG("IH: GUI idle\n"); + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + + /* wptr/rptr are in bytes! */ + rptr += 16; + rptr &= rdev->ih.ptr_mask; + } + if (queue_hotplug) + taskqueue_enqueue(rdev->tq, &rdev->hotplug_work); + if (queue_hdmi) + taskqueue_enqueue(rdev->tq, &rdev->audio_work); + rdev->ih.rptr = rptr; + WREG32(IH_RB_RPTR, rdev->ih.rptr); + atomic_set(&rdev->ih.lock, 0); + + /* make sure wptr hasn't changed while processing */ + wptr = r600_get_ih_wptr(rdev); + if (wptr != rptr) + goto restart_ih; + + return IRQ_HANDLED; +} + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) + +static int r600_debugfs_mc_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + + DREG32_SYS(m, rdev, R_000E50_SRBM_STATUS); + DREG32_SYS(m, rdev, VM_L2_STATUS); + return 0; +} + +static struct drm_info_list r600_mc_info_list[] = { + {"r600_mc_info", r600_debugfs_mc_info, 0, NULL}, +}; +#endif + +int r600_debugfs_mc_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, r600_mc_info_list, ARRAY_SIZE(r600_mc_info_list)); +#else + return 0; +#endif +} + +/** + * r600_ioctl_wait_idle - flush host path cache on wait idle ioctl + * rdev: radeon device structure + * bo: buffer object struct which userspace is waiting for idle + * + * Some R6XX/R7XX doesn't seems to take into account HDP flush performed + * through ring buffer, this leads to corruption in rendering, see + * http://bugzilla.kernel.org/show_bug.cgi?id=15186 to avoid this we + * directly perform HDP flush by writing register through MMIO. + */ +void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) +{ + /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read + * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL. + * This seems to cause problems on some AGP cards. Just use the old + * method for them. + */ + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && + rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) { + volatile uint32_t *ptr = rdev->vram_scratch.ptr; + u32 tmp; + + WREG32(HDP_DEBUG1, 0); + tmp = *ptr; + } else + WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); +} + +void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes) +{ + u32 link_width_cntl, mask, target_reg; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + /* x2 cards have a special sequence */ + if (ASIC_IS_X2(rdev)) + return; + + /* FIXME wait for idle */ + + switch (lanes) { + case 0: + mask = RADEON_PCIE_LC_LINK_WIDTH_X0; + break; + case 1: + mask = RADEON_PCIE_LC_LINK_WIDTH_X1; + break; + case 2: + mask = RADEON_PCIE_LC_LINK_WIDTH_X2; + break; + case 4: + mask = RADEON_PCIE_LC_LINK_WIDTH_X4; + break; + case 8: + mask = RADEON_PCIE_LC_LINK_WIDTH_X8; + break; + case 12: + mask = RADEON_PCIE_LC_LINK_WIDTH_X12; + break; + case 16: + default: + mask = RADEON_PCIE_LC_LINK_WIDTH_X16; + break; + } + + link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + + if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) == + (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT)) + return; + + if (link_width_cntl & R600_PCIE_LC_UPCONFIGURE_DIS) + return; + + link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK | + RADEON_PCIE_LC_RECONFIG_NOW | + R600_PCIE_LC_RENEGOTIATE_EN | + R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE); + link_width_cntl |= mask; + + WREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + + /* some northbridges can renegotiate the link rather than requiring + * a complete re-config. + * e.g., AMD 780/790 northbridges (pci ids: 0x5956, 0x5957, 0x5958, etc.) + */ + if (link_width_cntl & R600_PCIE_LC_RENEGOTIATION_SUPPORT) + link_width_cntl |= R600_PCIE_LC_RENEGOTIATE_EN | R600_PCIE_LC_UPCONFIGURE_SUPPORT; + else + link_width_cntl |= R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE; + + WREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl | + RADEON_PCIE_LC_RECONFIG_NOW)); + + if (rdev->family >= CHIP_RV770) + target_reg = R700_TARGET_AND_CURRENT_PROFILE_INDEX; + else + target_reg = R600_TARGET_AND_CURRENT_PROFILE_INDEX; + + /* wait for lane set to complete */ + link_width_cntl = RREG32(target_reg); + while (link_width_cntl == 0xffffffff) + link_width_cntl = RREG32(target_reg); + +} + +int r600_get_pcie_lanes(struct radeon_device *rdev) +{ + u32 link_width_cntl; + + if (rdev->flags & RADEON_IS_IGP) + return 0; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return 0; + + /* x2 cards have a special sequence */ + if (ASIC_IS_X2(rdev)) + return 0; + + /* FIXME wait for idle */ + + link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + + switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { + case RADEON_PCIE_LC_LINK_WIDTH_X0: + return 0; + case RADEON_PCIE_LC_LINK_WIDTH_X1: + return 1; + case RADEON_PCIE_LC_LINK_WIDTH_X2: + return 2; + case RADEON_PCIE_LC_LINK_WIDTH_X4: + return 4; + case RADEON_PCIE_LC_LINK_WIDTH_X8: + return 8; + case RADEON_PCIE_LC_LINK_WIDTH_X16: + default: + return 16; + } +} + +static void r600_pcie_gen2_enable(struct radeon_device *rdev) +{ + u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; + u16 link_cntl2; + u32 mask; + int ret; + + if (radeon_pcie_gen2 == 0) + return; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + /* x2 cards have a special sequence */ + if (ASIC_IS_X2(rdev)) + return; + + /* only RV6xx+ chips are supported */ + if (rdev->family <= CHIP_R600) + return; + + ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); + if (ret != 0) + return; + + if (!(mask & DRM_PCIE_SPEED_50)) + return; + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if (speed_cntl & LC_CURRENT_DATA_RATE) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); + + /* 55 nm r6xx asics */ + if ((rdev->family == CHIP_RV670) || + (rdev->family == CHIP_RV620) || + (rdev->family == CHIP_RV635)) { + /* advertise upconfig capability */ + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + link_width_cntl &= ~LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { + lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; + link_width_cntl &= ~(LC_LINK_WIDTH_MASK | + LC_RECONFIG_ARC_MISSING_ESCAPE); + link_width_cntl |= lanes | LC_RECONFIG_NOW | LC_RENEGOTIATE_EN; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } else { + link_width_cntl |= LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } + } + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && + (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { + + /* 55 nm r6xx asics */ + if ((rdev->family == CHIP_RV670) || + (rdev->family == CHIP_RV620) || + (rdev->family == CHIP_RV635)) { + WREG32(MM_CFGREGS_CNTL, 0x8); + link_cntl2 = RREG32(0x4088); + WREG32(MM_CFGREGS_CNTL, 0); + /* not supported yet */ + if (link_cntl2 & SELECTABLE_DEEMPHASIS) + return; + } + + speed_cntl &= ~LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK; + speed_cntl |= (0x3 << LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT); + speed_cntl &= ~LC_VOLTAGE_TIMER_SEL_MASK; + speed_cntl &= ~LC_FORCE_DIS_HW_SPEED_CHANGE; + speed_cntl |= LC_FORCE_EN_HW_SPEED_CHANGE; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + tmp = RREG32(0x541c); + WREG32(0x541c, tmp | 0x8); + WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); + link_cntl2 = RREG16(0x4088); + link_cntl2 &= ~TARGET_LINK_SPEED_MASK; + link_cntl2 |= 0x2; + WREG16(0x4088, link_cntl2); + WREG32(MM_CFGREGS_CNTL, 0); + + if ((rdev->family == CHIP_RV670) || + (rdev->family == CHIP_RV620) || + (rdev->family == CHIP_RV635)) { + training_cntl = RREG32_PCIE_P(PCIE_LC_TRAINING_CNTL); + training_cntl &= ~LC_POINT_7_PLUS_EN; + WREG32_PCIE_P(PCIE_LC_TRAINING_CNTL, training_cntl); + } else { + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + } + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl |= LC_GEN2_EN_STRAP; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + } else { + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ + if (1) + link_width_cntl |= LC_UPCONFIGURE_DIS; + else + link_width_cntl &= ~LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } +} + +/** + * r600_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (R6xx-cayman). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t r600_get_gpu_clock(struct radeon_device *rdev) +{ + uint64_t clock; + + sx_xlock(&rdev->gpu_clock_mutex); + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); + sx_xunlock(&rdev->gpu_clock_mutex); + return clock; +} diff --git a/sys/dev/drm2/radeon/r600_audio.c b/sys/dev/drm2/radeon/r600_audio.c new file mode 100644 index 00000000000..bf14b6095fa --- /dev/null +++ b/sys/dev/drm2/radeon/r600_audio.c @@ -0,0 +1,258 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Christian König. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_asic.h" +#include "atom.h" + +/* + * check if enc_priv stores radeon_encoder_atom_dig + */ +static bool radeon_dig_encoder(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + return true; + } + return false; +} + +/* + * check if the chipset is supported + */ +static int r600_audio_chipset_supported(struct radeon_device *rdev) +{ + return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE6(rdev)) + || rdev->family == CHIP_RS600 + || rdev->family == CHIP_RS690 + || rdev->family == CHIP_RS740; +} + +struct r600_audio r600_audio_status(struct radeon_device *rdev) +{ + struct r600_audio status; + uint32_t value; + + value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); + + /* number of channels */ + status.channels = (value & 0x7) + 1; + + /* bits per sample */ + switch ((value & 0xF0) >> 4) { + case 0x0: + status.bits_per_sample = 8; + break; + case 0x1: + status.bits_per_sample = 16; + break; + case 0x2: + status.bits_per_sample = 20; + break; + case 0x3: + status.bits_per_sample = 24; + break; + case 0x4: + status.bits_per_sample = 32; + break; + default: + dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", + (int)value); + status.bits_per_sample = 16; + } + + /* current sampling rate in HZ */ + if (value & 0x4000) + status.rate = 44100; + else + status.rate = 48000; + status.rate *= ((value >> 11) & 0x7) + 1; + status.rate /= ((value >> 8) & 0x7) + 1; + + value = RREG32(R600_AUDIO_STATUS_BITS); + + /* iec 60958 status bits */ + status.status_bits = value & 0xff; + + /* iec 60958 category code */ + status.category_code = (value >> 8) & 0xff; + + return status; +} + +/* + * update all hdmi interfaces with current audio parameters + */ +void r600_audio_update_hdmi(void *arg, int pending) +{ + struct radeon_device *rdev = arg; + struct drm_device *dev = rdev->ddev; + struct r600_audio audio_status = r600_audio_status(rdev); + struct drm_encoder *encoder; + bool changed = false; + + if (rdev->audio_status.channels != audio_status.channels || + rdev->audio_status.rate != audio_status.rate || + rdev->audio_status.bits_per_sample != audio_status.bits_per_sample || + rdev->audio_status.status_bits != audio_status.status_bits || + rdev->audio_status.category_code != audio_status.category_code) { + rdev->audio_status = audio_status; + changed = true; + } + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (!radeon_dig_encoder(encoder)) + continue; + if (changed || r600_hdmi_buffer_status_changed(encoder)) + r600_hdmi_update_audio_settings(encoder); + } +} + +/* + * turn on/off audio engine + */ +static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) +{ + u32 value = 0; + DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); + if (ASIC_IS_DCE4(rdev)) { + if (enable) { + value |= 0x81000000; /* Required to enable audio */ + value |= 0x0e1000f0; /* fglrx sets that too */ + } + WREG32(EVERGREEN_AUDIO_ENABLE, value); + } else { + WREG32_P(R600_AUDIO_ENABLE, + enable ? 0x81000000 : 0x0, ~0x81000000); + } + rdev->audio_enabled = enable; +} + +/* + * initialize the audio vars + */ +int r600_audio_init(struct radeon_device *rdev) +{ + if (!radeon_audio || !r600_audio_chipset_supported(rdev)) + return 0; + + r600_audio_engine_enable(rdev, true); + + rdev->audio_status.channels = -1; + rdev->audio_status.rate = -1; + rdev->audio_status.bits_per_sample = -1; + rdev->audio_status.status_bits = 0; + rdev->audio_status.category_code = 0; + + return 0; +} + +/* + * atach the audio codec to the clock source of the encoder + */ +void r600_audio_set_clock(struct drm_encoder *encoder, int clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + int base_rate = 48000; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); + break; + default: + dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", + radeon_encoder->encoder_id); + return; + } + + if (ASIC_IS_DCE4(rdev)) { + /* TODO: other PLLs? */ + WREG32(EVERGREEN_AUDIO_PLL1_MUL, base_rate * 10); + WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); + WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); + + /* Select DTO source */ + WREG32(0x5ac, radeon_crtc->crtc_id); + } else { + switch (dig->dig_encoder) { + case 0: + WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); + WREG32(R600_AUDIO_PLL1_DIV, clock * 100); + WREG32(R600_AUDIO_CLK_SRCSEL, 0); + break; + + case 1: + WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); + WREG32(R600_AUDIO_PLL2_DIV, clock * 100); + WREG32(R600_AUDIO_CLK_SRCSEL, 1); + break; + default: + dev_err(rdev->dev, + "Unsupported DIG on encoder 0x%02X\n", + radeon_encoder->encoder_id); + return; + } + } +} + +/* + * release the audio timer + * TODO: How to do this correctly on SMP systems? + */ +void r600_audio_fini(struct radeon_device *rdev) +{ + if (!rdev->audio_enabled) + return; + + r600_audio_engine_enable(rdev, false); +} diff --git a/sys/dev/drm2/radeon/r600_blit.c b/sys/dev/drm2/radeon/r600_blit.c new file mode 100644 index 00000000000..f9658d49ed2 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_blit.c @@ -0,0 +1,876 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_drv.h" + +#include "r600_blit_shaders.h" + +#define DI_PT_RECTLIST 0x11 +#define DI_INDEX_SIZE_16_BIT 0x0 +#define DI_SRC_SEL_AUTO_INDEX 0x2 + +#define FMT_8 0x1 +#define FMT_5_6_5 0x8 +#define FMT_8_8_8_8 0x1a +#define COLOR_8 0x1 +#define COLOR_5_6_5 0x8 +#define COLOR_8_8_8_8 0x1a + +static void +set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr) +{ + u32 cb_color_info; + int pitch, slice; + RING_LOCALS; + DRM_DEBUG("\n"); + + h = roundup2(h, 8); + if (h < 8) + h = 8; + + cb_color_info = ((format << 2) | (1 << 27)); + pitch = (w / 8) - 1; + slice = ((w * h) / 64) - 1; + + if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600) && + ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) { + BEGIN_RING(21 + 2); + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(gpu_addr >> 8); + OUT_RING(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0)); + OUT_RING(2 << 0); + } else { + BEGIN_RING(21); + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(gpu_addr >> 8); + } + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_SIZE - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING((pitch << 0) | (slice << 10)); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_VIEW - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(0); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_INFO - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(cb_color_info); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_TILE - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(0); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_FRAG - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(0); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_CB_COLOR0_MASK - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(0); + + ADVANCE_RING(); +} + +static void +cp_set_surface_sync(drm_radeon_private_t *dev_priv, + u32 sync_type, u32 size, u64 mc_addr) +{ + u32 cp_coher_size; + RING_LOCALS; + DRM_DEBUG("\n"); + + if (size == 0xffffffff) + cp_coher_size = 0xffffffff; + else + cp_coher_size = ((size + 255) >> 8); + + BEGIN_RING(5); + OUT_RING(CP_PACKET3(R600_IT_SURFACE_SYNC, 3)); + OUT_RING(sync_type); + OUT_RING(cp_coher_size); + OUT_RING((mc_addr >> 8)); + OUT_RING(10); /* poll interval */ + ADVANCE_RING(); +} + +static void +set_shaders(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + u64 gpu_addr; + int i; + u32 *vs, *ps; + uint32_t sq_pgm_resources; + RING_LOCALS; + DRM_DEBUG("\n"); + + /* load shaders */ + vs = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset); + ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256); + + for (i = 0; i < r6xx_vs_size; i++) + vs[i] = cpu_to_le32(r6xx_vs[i]); + for (i = 0; i < r6xx_ps_size; i++) + ps[i] = cpu_to_le32(r6xx_ps[i]); + + dev_priv->blit_vb->used = 512; + + gpu_addr = dev_priv->gart_buffers_offset + dev_priv->blit_vb->offset; + + /* setup shader regs */ + sq_pgm_resources = (1 << 0); + + BEGIN_RING(9 + 12); + /* VS */ + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_START_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(gpu_addr >> 8); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_RESOURCES_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(sq_pgm_resources); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_CF_OFFSET_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(0); + + /* PS */ + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_START_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING((gpu_addr + 256) >> 8); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_RESOURCES_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(sq_pgm_resources | (1 << 28)); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_EXPORTS_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(2); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); + OUT_RING((R600_SQ_PGM_CF_OFFSET_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING(0); + ADVANCE_RING(); + + cp_set_surface_sync(dev_priv, + R600_SH_ACTION_ENA, 512, gpu_addr); +} + +static void +set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr) +{ + uint32_t sq_vtx_constant_word2; + RING_LOCALS; + DRM_DEBUG("\n"); + + sq_vtx_constant_word2 = (((gpu_addr >> 32) & 0xff) | (16 << 8)); +#ifdef __BIG_ENDIAN + sq_vtx_constant_word2 |= (2 << 30); +#endif + + BEGIN_RING(9); + OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7)); + OUT_RING(0x460); + OUT_RING(gpu_addr & 0xffffffff); + OUT_RING(48 - 1); + OUT_RING(sq_vtx_constant_word2); + OUT_RING(1 << 0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(R600_SQ_TEX_VTX_VALID_BUFFER << 30); + ADVANCE_RING(); + + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) + cp_set_surface_sync(dev_priv, + R600_TC_ACTION_ENA, 48, gpu_addr); + else + cp_set_surface_sync(dev_priv, + R600_VC_ACTION_ENA, 48, gpu_addr); +} + +static void +set_tex_resource(drm_radeon_private_t *dev_priv, + int format, int w, int h, int pitch, u64 gpu_addr) +{ + uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4; + RING_LOCALS; + DRM_DEBUG("\n"); + + if (h < 1) + h = 1; + + sq_tex_resource_word0 = (1 << 0); + sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) | + ((w - 1) << 19)); + + sq_tex_resource_word1 = (format << 26); + sq_tex_resource_word1 |= ((h - 1) << 0); + + sq_tex_resource_word4 = ((1 << 14) | + (0 << 16) | + (1 << 19) | + (2 << 22) | + (3 << 25)); + + BEGIN_RING(9); + OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7)); + OUT_RING(0); + OUT_RING(sq_tex_resource_word0); + OUT_RING(sq_tex_resource_word1); + OUT_RING(gpu_addr >> 8); + OUT_RING(gpu_addr >> 8); + OUT_RING(sq_tex_resource_word4); + OUT_RING(0); + OUT_RING(R600_SQ_TEX_VTX_VALID_TEXTURE << 30); + ADVANCE_RING(); + +} + +static void +set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2) +{ + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(12); + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2)); + OUT_RING((R600_PA_SC_SCREEN_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING((x1 << 0) | (y1 << 16)); + OUT_RING((x2 << 0) | (y2 << 16)); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2)); + OUT_RING((R600_PA_SC_GENERIC_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31)); + OUT_RING((x2 << 0) | (y2 << 16)); + + OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2)); + OUT_RING((R600_PA_SC_WINDOW_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2); + OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31)); + OUT_RING((x2 << 0) | (y2 << 16)); + ADVANCE_RING(); +} + +static void +draw_auto(drm_radeon_private_t *dev_priv) +{ + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(10); + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); + OUT_RING((R600_VGT_PRIMITIVE_TYPE - R600_SET_CONFIG_REG_OFFSET) >> 2); + OUT_RING(DI_PT_RECTLIST); + + OUT_RING(CP_PACKET3(R600_IT_INDEX_TYPE, 0)); +#ifdef __BIG_ENDIAN + OUT_RING((2 << 2) | DI_INDEX_SIZE_16_BIT); +#else + OUT_RING(DI_INDEX_SIZE_16_BIT); +#endif + + OUT_RING(CP_PACKET3(R600_IT_NUM_INSTANCES, 0)); + OUT_RING(1); + + OUT_RING(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1)); + OUT_RING(3); + OUT_RING(DI_SRC_SEL_AUTO_INDEX); + + ADVANCE_RING(); + COMMIT_RING(); +} + +static void +set_default_state(drm_radeon_private_t *dev_priv) +{ + int i; + u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2; + u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2; + int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs; + int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads; + int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; + RING_LOCALS; + + switch ((dev_priv->flags & RADEON_FAMILY_MASK)) { + case CHIP_R600: + num_ps_gprs = 192; + num_vs_gprs = 56; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 136; + num_vs_threads = 48; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 128; + num_vs_stack_entries = 128; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + case CHIP_RV630: + case CHIP_RV635: + num_ps_gprs = 84; + num_vs_gprs = 36; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 144; + num_vs_threads = 40; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 40; + num_vs_stack_entries = 40; + num_gs_stack_entries = 32; + num_es_stack_entries = 16; + break; + case CHIP_RV610: + case CHIP_RV620: + case CHIP_RS780: + case CHIP_RS880: + default: + num_ps_gprs = 84; + num_vs_gprs = 36; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 136; + num_vs_threads = 48; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 40; + num_vs_stack_entries = 40; + num_gs_stack_entries = 32; + num_es_stack_entries = 16; + break; + case CHIP_RV670: + num_ps_gprs = 144; + num_vs_gprs = 40; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 136; + num_vs_threads = 48; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 40; + num_vs_stack_entries = 40; + num_gs_stack_entries = 32; + num_es_stack_entries = 16; + break; + case CHIP_RV770: + num_ps_gprs = 192; + num_vs_gprs = 56; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 188; + num_vs_threads = 60; + num_gs_threads = 0; + num_es_threads = 0; + num_ps_stack_entries = 256; + num_vs_stack_entries = 256; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + case CHIP_RV730: + case CHIP_RV740: + num_ps_gprs = 84; + num_vs_gprs = 36; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 188; + num_vs_threads = 60; + num_gs_threads = 0; + num_es_threads = 0; + num_ps_stack_entries = 128; + num_vs_stack_entries = 128; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + case CHIP_RV710: + num_ps_gprs = 192; + num_vs_gprs = 56; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 144; + num_vs_threads = 48; + num_gs_threads = 0; + num_es_threads = 0; + num_ps_stack_entries = 128; + num_vs_stack_entries = 128; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + } + + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) + sq_config = 0; + else + sq_config = R600_VC_ENABLE; + + sq_config |= (R600_DX9_CONSTS | + R600_ALU_INST_PREFER_VECTOR | + R600_PS_PRIO(0) | + R600_VS_PRIO(1) | + R600_GS_PRIO(2) | + R600_ES_PRIO(3)); + + sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(num_ps_gprs) | + R600_NUM_VS_GPRS(num_vs_gprs) | + R600_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); + sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(num_gs_gprs) | + R600_NUM_ES_GPRS(num_es_gprs)); + sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(num_ps_threads) | + R600_NUM_VS_THREADS(num_vs_threads) | + R600_NUM_GS_THREADS(num_gs_threads) | + R600_NUM_ES_THREADS(num_es_threads)); + sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | + R600_NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); + sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | + R600_NUM_ES_STACK_ENTRIES(num_es_stack_entries)); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { + BEGIN_RING(r7xx_default_size + 10); + for (i = 0; i < r7xx_default_size; i++) + OUT_RING(r7xx_default_state[i]); + } else { + BEGIN_RING(r6xx_default_size + 10); + for (i = 0; i < r6xx_default_size; i++) + OUT_RING(r6xx_default_state[i]); + } + OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0)); + OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT); + /* SQ config */ + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 6)); + OUT_RING((R600_SQ_CONFIG - R600_SET_CONFIG_REG_OFFSET) >> 2); + OUT_RING(sq_config); + OUT_RING(sq_gpr_resource_mgmt_1); + OUT_RING(sq_gpr_resource_mgmt_2); + OUT_RING(sq_thread_resource_mgmt); + OUT_RING(sq_stack_resource_mgmt_1); + OUT_RING(sq_stack_resource_mgmt_2); + ADVANCE_RING(); +} + +/* 23 bits of float fractional data */ +#define I2F_FRAC_BITS 23 +#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) + +/* + * Converts unsigned integer into 32-bit IEEE floating point representation. + * Will be exact from 0 to 2^24. Above that, we round towards zero + * as the fractional bits will not fit in a float. (It would be better to + * round towards even as the fpu does, but that is slower.) + */ +__pure uint32_t int2float(uint32_t x) +{ + uint32_t msb, exponent, fraction; + + /* Zero is special */ + if (!x) return 0; + + /* Get location of the most significant bit */ + msb = fls(x); + + /* + * Use a rotate instead of a shift because that works both leftwards + * and rightwards due to the mod(32) behaviour. This means we don't + * need to check to see if we are above 2^24 or not. + */ + fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; + exponent = (127 + msb) << I2F_FRAC_BITS; + + return fraction + exponent; +} + +static int r600_nomm_get_vb(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + dev_priv->blit_vb = radeon_freelist_get(dev); + if (!dev_priv->blit_vb) { + DRM_ERROR("Unable to allocate vertex buffer for blit\n"); + return -EAGAIN; + } + return 0; +} + +static void r600_nomm_put_vb(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + dev_priv->blit_vb->used = 0; + radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->masterp, dev_priv->blit_vb); +} + +static void *r600_nomm_get_vb_ptr(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + return (((char *)dev->agp_buffer_map->handle + + dev_priv->blit_vb->offset + dev_priv->blit_vb->used)); +} + +int +r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + DRM_DEBUG("\n"); + + ret = r600_nomm_get_vb(dev); + if (ret) + return ret; + + dev_priv->blit_vb->file_priv = file_priv; + + set_default_state(dev_priv); + set_shaders(dev); + + return 0; +} + + +void +r600_done_blit_copy(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(5); + OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0)); + OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT); + /* wait for 3D idle clean */ + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); + OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2); + OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN); + + ADVANCE_RING(); + COMMIT_RING(); + + r600_nomm_put_vb(dev); +} + +void +r600_blit_copy(struct drm_device *dev, + uint64_t src_gpu_addr, uint64_t dst_gpu_addr, + int size_bytes) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int max_bytes; + u64 vb_addr; + u32 *vb; + + vb = r600_nomm_get_vb_ptr(dev); + + if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) { + max_bytes = 8192; + + while (size_bytes) { + int cur_size = size_bytes; + int src_x = src_gpu_addr & 255; + int dst_x = dst_gpu_addr & 255; + int h = 1; + src_gpu_addr = src_gpu_addr & ~255; + dst_gpu_addr = dst_gpu_addr & ~255; + + if (!src_x && !dst_x) { + h = (cur_size / max_bytes); + if (h > 8192) + h = 8192; + if (h == 0) + h = 1; + else + cur_size = max_bytes; + } else { + if (cur_size > max_bytes) + cur_size = max_bytes; + if (cur_size > (max_bytes - dst_x)) + cur_size = (max_bytes - dst_x); + if (cur_size > (max_bytes - src_x)) + cur_size = (max_bytes - src_x); + } + + if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { + + r600_nomm_put_vb(dev); + r600_nomm_get_vb(dev); + if (!dev_priv->blit_vb) + return; + set_shaders(dev); + vb = r600_nomm_get_vb_ptr(dev); + } + + vb[0] = int2float(dst_x); + vb[1] = 0; + vb[2] = int2float(src_x); + vb[3] = 0; + + vb[4] = int2float(dst_x); + vb[5] = int2float(h); + vb[6] = int2float(src_x); + vb[7] = int2float(h); + + vb[8] = int2float(dst_x + cur_size); + vb[9] = int2float(h); + vb[10] = int2float(src_x + cur_size); + vb[11] = int2float(h); + + /* src */ + set_tex_resource(dev_priv, FMT_8, + src_x + cur_size, h, src_x + cur_size, + src_gpu_addr); + + cp_set_surface_sync(dev_priv, + R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr); + + /* dst */ + set_render_target(dev_priv, COLOR_8, + dst_x + cur_size, h, + dst_gpu_addr); + + /* scissors */ + set_scissors(dev_priv, dst_x, 0, dst_x + cur_size, h); + + /* Vertex buffer setup */ + vb_addr = dev_priv->gart_buffers_offset + + dev_priv->blit_vb->offset + + dev_priv->blit_vb->used; + set_vtx_resource(dev_priv, vb_addr); + + /* draw */ + draw_auto(dev_priv); + + cp_set_surface_sync(dev_priv, + R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA, + cur_size * h, dst_gpu_addr); + + vb += 12; + dev_priv->blit_vb->used += 12 * 4; + + src_gpu_addr += cur_size * h; + dst_gpu_addr += cur_size * h; + size_bytes -= cur_size * h; + } + } else { + max_bytes = 8192 * 4; + + while (size_bytes) { + int cur_size = size_bytes; + int src_x = (src_gpu_addr & 255); + int dst_x = (dst_gpu_addr & 255); + int h = 1; + src_gpu_addr = src_gpu_addr & ~255; + dst_gpu_addr = dst_gpu_addr & ~255; + + if (!src_x && !dst_x) { + h = (cur_size / max_bytes); + if (h > 8192) + h = 8192; + if (h == 0) + h = 1; + else + cur_size = max_bytes; + } else { + if (cur_size > max_bytes) + cur_size = max_bytes; + if (cur_size > (max_bytes - dst_x)) + cur_size = (max_bytes - dst_x); + if (cur_size > (max_bytes - src_x)) + cur_size = (max_bytes - src_x); + } + + if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { + r600_nomm_put_vb(dev); + r600_nomm_get_vb(dev); + if (!dev_priv->blit_vb) + return; + + set_shaders(dev); + vb = r600_nomm_get_vb_ptr(dev); + } + + vb[0] = int2float(dst_x / 4); + vb[1] = 0; + vb[2] = int2float(src_x / 4); + vb[3] = 0; + + vb[4] = int2float(dst_x / 4); + vb[5] = int2float(h); + vb[6] = int2float(src_x / 4); + vb[7] = int2float(h); + + vb[8] = int2float((dst_x + cur_size) / 4); + vb[9] = int2float(h); + vb[10] = int2float((src_x + cur_size) / 4); + vb[11] = int2float(h); + + /* src */ + set_tex_resource(dev_priv, FMT_8_8_8_8, + (src_x + cur_size) / 4, + h, (src_x + cur_size) / 4, + src_gpu_addr); + + cp_set_surface_sync(dev_priv, + R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr); + + /* dst */ + set_render_target(dev_priv, COLOR_8_8_8_8, + (dst_x + cur_size) / 4, h, + dst_gpu_addr); + + /* scissors */ + set_scissors(dev_priv, (dst_x / 4), 0, (dst_x + cur_size / 4), h); + + /* Vertex buffer setup */ + vb_addr = dev_priv->gart_buffers_offset + + dev_priv->blit_vb->offset + + dev_priv->blit_vb->used; + set_vtx_resource(dev_priv, vb_addr); + + /* draw */ + draw_auto(dev_priv); + + cp_set_surface_sync(dev_priv, + R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA, + cur_size * h, dst_gpu_addr); + + vb += 12; + dev_priv->blit_vb->used += 12 * 4; + + src_gpu_addr += cur_size * h; + dst_gpu_addr += cur_size * h; + size_bytes -= cur_size * h; + } + } +} + +void +r600_blit_swap(struct drm_device *dev, + uint64_t src_gpu_addr, uint64_t dst_gpu_addr, + int sx, int sy, int dx, int dy, + int w, int h, int src_pitch, int dst_pitch, int cpp) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int cb_format, tex_format; + int sx2, sy2, dx2, dy2; + u64 vb_addr; + u32 *vb; + + if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { + + r600_nomm_put_vb(dev); + r600_nomm_get_vb(dev); + if (!dev_priv->blit_vb) + return; + + set_shaders(dev); + } + vb = r600_nomm_get_vb_ptr(dev); + + sx2 = sx + w; + sy2 = sy + h; + dx2 = dx + w; + dy2 = dy + h; + + vb[0] = int2float(dx); + vb[1] = int2float(dy); + vb[2] = int2float(sx); + vb[3] = int2float(sy); + + vb[4] = int2float(dx); + vb[5] = int2float(dy2); + vb[6] = int2float(sx); + vb[7] = int2float(sy2); + + vb[8] = int2float(dx2); + vb[9] = int2float(dy2); + vb[10] = int2float(sx2); + vb[11] = int2float(sy2); + + switch(cpp) { + case 4: + cb_format = COLOR_8_8_8_8; + tex_format = FMT_8_8_8_8; + break; + case 2: + cb_format = COLOR_5_6_5; + tex_format = FMT_5_6_5; + break; + default: + cb_format = COLOR_8; + tex_format = FMT_8; + break; + } + + /* src */ + set_tex_resource(dev_priv, tex_format, + src_pitch / cpp, + sy2, src_pitch / cpp, + src_gpu_addr); + + cp_set_surface_sync(dev_priv, + R600_TC_ACTION_ENA, src_pitch * sy2, src_gpu_addr); + + /* dst */ + set_render_target(dev_priv, cb_format, + dst_pitch / cpp, dy2, + dst_gpu_addr); + + /* scissors */ + set_scissors(dev_priv, dx, dy, dx2, dy2); + + /* Vertex buffer setup */ + vb_addr = dev_priv->gart_buffers_offset + + dev_priv->blit_vb->offset + + dev_priv->blit_vb->used; + set_vtx_resource(dev_priv, vb_addr); + + /* draw */ + draw_auto(dev_priv); + + cp_set_surface_sync(dev_priv, + R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA, + dst_pitch * dy2, dst_gpu_addr); + + dev_priv->blit_vb->used += 12 * 4; +} diff --git a/sys/dev/drm2/radeon/r600_blit_kms.c b/sys/dev/drm2/radeon/r600_blit_kms.c new file mode 100644 index 00000000000..e2ace6936a9 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_blit_kms.c @@ -0,0 +1,758 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_asic.h" + +#include "r600d.h" +#include "r600_blit_shaders.h" +#include "radeon_blit_common.h" + +/* emits 21 on rv770+, 23 on r600 */ +static void +set_render_target(struct radeon_device *rdev, int format, + int w, int h, u64 gpu_addr) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cb_color_info; + int pitch, slice; + + h = roundup2(h, 8); + if (h < 8) + h = 8; + + cb_color_info = CB_FORMAT(format) | + CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) | + CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + pitch = (w / 8) - 1; + slice = ((w * h) / 64) - 1; + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, gpu_addr >> 8); + + if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770) { + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_BASE_UPDATE, 0)); + radeon_ring_write(ring, 2 << 0); + } + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_SIZE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, (pitch << 0) | (slice << 10)); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_VIEW - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 0); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_INFO - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, cb_color_info); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_TILE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 0); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_FRAG - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 0); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (CB_COLOR0_MASK - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 0); +} + +/* emits 5dw */ +static void +cp_set_surface_sync(struct radeon_device *rdev, + u32 sync_type, u32 size, + u64 mc_addr) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cp_coher_size; + + if (size == 0xffffffff) + cp_coher_size = 0xffffffff; + else + cp_coher_size = ((size + 255) >> 8); + + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, sync_type); + radeon_ring_write(ring, cp_coher_size); + radeon_ring_write(ring, mc_addr >> 8); + radeon_ring_write(ring, 10); /* poll interval */ +} + +/* emits 21dw + 1 surface sync = 26dw */ +static void +set_shaders(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u64 gpu_addr; + u32 sq_pgm_resources; + + /* setup shader regs */ + sq_pgm_resources = (1 << 0); + + /* VS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, gpu_addr >> 8); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_RESOURCES_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, sq_pgm_resources); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_CF_OFFSET_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 0); + + /* PS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.ps_offset; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, gpu_addr >> 8); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_RESOURCES_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, sq_pgm_resources | (1 << 28)); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_EXPORTS_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 2); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + radeon_ring_write(ring, (SQ_PGM_CF_OFFSET_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, 0); + + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; + cp_set_surface_sync(rdev, PACKET3_SH_ACTION_ENA, 512, gpu_addr); +} + +/* emits 9 + 1 sync (5) = 14*/ +static void +set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_vtx_constant_word2; + + sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) | + SQ_VTXC_STRIDE(16); +#ifdef __BIG_ENDIAN + sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32); +#endif + + radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 7)); + radeon_ring_write(ring, 0x460); + radeon_ring_write(ring, gpu_addr & 0xffffffff); + radeon_ring_write(ring, 48 - 1); + radeon_ring_write(ring, sq_vtx_constant_word2); + radeon_ring_write(ring, 1 << 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, SQ_TEX_VTX_VALID_BUFFER << 30); + + if ((rdev->family == CHIP_RV610) || + (rdev->family == CHIP_RV620) || + (rdev->family == CHIP_RS780) || + (rdev->family == CHIP_RS880) || + (rdev->family == CHIP_RV710)) + cp_set_surface_sync(rdev, + PACKET3_TC_ACTION_ENA, 48, gpu_addr); + else + cp_set_surface_sync(rdev, + PACKET3_VC_ACTION_ENA, 48, gpu_addr); +} + +/* emits 9 */ +static void +set_tex_resource(struct radeon_device *rdev, + int format, int w, int h, int pitch, + u64 gpu_addr, u32 size) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4; + + if (h < 1) + h = 1; + + sq_tex_resource_word0 = S_038000_DIM(V_038000_SQ_TEX_DIM_2D) | + S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + sq_tex_resource_word0 |= S_038000_PITCH((pitch >> 3) - 1) | + S_038000_TEX_WIDTH(w - 1); + + sq_tex_resource_word1 = S_038004_DATA_FORMAT(format); + sq_tex_resource_word1 |= S_038004_TEX_HEIGHT(h - 1); + + sq_tex_resource_word4 = S_038010_REQUEST_SIZE(1) | + S_038010_DST_SEL_X(SQ_SEL_X) | + S_038010_DST_SEL_Y(SQ_SEL_Y) | + S_038010_DST_SEL_Z(SQ_SEL_Z) | + S_038010_DST_SEL_W(SQ_SEL_W); + + cp_set_surface_sync(rdev, + PACKET3_TC_ACTION_ENA, size, gpu_addr); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 7)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, sq_tex_resource_word0); + radeon_ring_write(ring, sq_tex_resource_word1); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, gpu_addr >> 8); + radeon_ring_write(ring, sq_tex_resource_word4); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, SQ_TEX_VTX_VALID_TEXTURE << 30); +} + +/* emits 12 */ +static void +set_scissors(struct radeon_device *rdev, int x1, int y1, + int x2, int y2) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, (x1 << 0) | (y1 << 16)); + radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); + radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); + radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); + radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); +} + +/* emits 10 */ +static void +draw_auto(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); + radeon_ring_write(ring, DI_PT_RECTLIST); + + radeon_ring_write(ring, PACKET3(PACKET3_INDEX_TYPE, 0)); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 2) | +#endif + DI_INDEX_SIZE_16_BIT); + + radeon_ring_write(ring, PACKET3(PACKET3_NUM_INSTANCES, 0)); + radeon_ring_write(ring, 1); + + radeon_ring_write(ring, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); + radeon_ring_write(ring, 3); + radeon_ring_write(ring, DI_SRC_SEL_AUTO_INDEX); + +} + +/* emits 14 */ +static void +set_default_state(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2; + u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2; + int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs; + int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads; + int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; + u64 gpu_addr; + int dwords; + + switch (rdev->family) { + case CHIP_R600: + num_ps_gprs = 192; + num_vs_gprs = 56; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 136; + num_vs_threads = 48; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 128; + num_vs_stack_entries = 128; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + case CHIP_RV630: + case CHIP_RV635: + num_ps_gprs = 84; + num_vs_gprs = 36; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 144; + num_vs_threads = 40; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 40; + num_vs_stack_entries = 40; + num_gs_stack_entries = 32; + num_es_stack_entries = 16; + break; + case CHIP_RV610: + case CHIP_RV620: + case CHIP_RS780: + case CHIP_RS880: + default: + num_ps_gprs = 84; + num_vs_gprs = 36; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 136; + num_vs_threads = 48; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 40; + num_vs_stack_entries = 40; + num_gs_stack_entries = 32; + num_es_stack_entries = 16; + break; + case CHIP_RV670: + num_ps_gprs = 144; + num_vs_gprs = 40; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 136; + num_vs_threads = 48; + num_gs_threads = 4; + num_es_threads = 4; + num_ps_stack_entries = 40; + num_vs_stack_entries = 40; + num_gs_stack_entries = 32; + num_es_stack_entries = 16; + break; + case CHIP_RV770: + num_ps_gprs = 192; + num_vs_gprs = 56; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 188; + num_vs_threads = 60; + num_gs_threads = 0; + num_es_threads = 0; + num_ps_stack_entries = 256; + num_vs_stack_entries = 256; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + case CHIP_RV730: + case CHIP_RV740: + num_ps_gprs = 84; + num_vs_gprs = 36; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 188; + num_vs_threads = 60; + num_gs_threads = 0; + num_es_threads = 0; + num_ps_stack_entries = 128; + num_vs_stack_entries = 128; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + case CHIP_RV710: + num_ps_gprs = 192; + num_vs_gprs = 56; + num_temp_gprs = 4; + num_gs_gprs = 0; + num_es_gprs = 0; + num_ps_threads = 144; + num_vs_threads = 48; + num_gs_threads = 0; + num_es_threads = 0; + num_ps_stack_entries = 128; + num_vs_stack_entries = 128; + num_gs_stack_entries = 0; + num_es_stack_entries = 0; + break; + } + + if ((rdev->family == CHIP_RV610) || + (rdev->family == CHIP_RV620) || + (rdev->family == CHIP_RS780) || + (rdev->family == CHIP_RS880) || + (rdev->family == CHIP_RV710)) + sq_config = 0; + else + sq_config = VC_ENABLE; + + sq_config |= (DX9_CONSTS | + ALU_INST_PREFER_VECTOR | + PS_PRIO(0) | + VS_PRIO(1) | + GS_PRIO(2) | + ES_PRIO(3)); + + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | + NUM_VS_GPRS(num_vs_gprs) | + NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | + NUM_ES_GPRS(num_es_gprs)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | + NUM_VS_THREADS(num_vs_threads) | + NUM_GS_THREADS(num_gs_threads) | + NUM_ES_THREADS(num_es_threads)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | + NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | + NUM_ES_STACK_ENTRIES(num_es_stack_entries)); + + /* emit an IB pointing at default state */ + dwords = roundup2(rdev->r600_blit.state_len, 0x10); + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; + radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (gpu_addr & 0xFFFFFFFC)); + radeon_ring_write(ring, upper_32_bits(gpu_addr) & 0xFF); + radeon_ring_write(ring, dwords); + + /* SQ config */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 6)); + radeon_ring_write(ring, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); + radeon_ring_write(ring, sq_config); + radeon_ring_write(ring, sq_gpr_resource_mgmt_1); + radeon_ring_write(ring, sq_gpr_resource_mgmt_2); + radeon_ring_write(ring, sq_thread_resource_mgmt); + radeon_ring_write(ring, sq_stack_resource_mgmt_1); + radeon_ring_write(ring, sq_stack_resource_mgmt_2); +} + +int r600_blit_init(struct radeon_device *rdev) +{ + u32 obj_size; + int i, r, dwords; + void *ptr; + u32 packet2s[16]; + int num_packet2s = 0; + + rdev->r600_blit.primitives.set_render_target = set_render_target; + rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync; + rdev->r600_blit.primitives.set_shaders = set_shaders; + rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource; + rdev->r600_blit.primitives.set_tex_resource = set_tex_resource; + rdev->r600_blit.primitives.set_scissors = set_scissors; + rdev->r600_blit.primitives.draw_auto = draw_auto; + rdev->r600_blit.primitives.set_default_state = set_default_state; + + rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ + rdev->r600_blit.ring_size_common += 40; /* shaders + def state */ + rdev->r600_blit.ring_size_common += 5; /* done copy */ + rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ + + rdev->r600_blit.ring_size_per_loop = 76; + /* set_render_target emits 2 extra dwords on rv6xx */ + if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770) + rdev->r600_blit.ring_size_per_loop += 2; + + rdev->r600_blit.max_dim = 8192; + + rdev->r600_blit.state_offset = 0; + + if (rdev->family >= CHIP_RV770) + rdev->r600_blit.state_len = r7xx_default_size; + else + rdev->r600_blit.state_len = r6xx_default_size; + + dwords = rdev->r600_blit.state_len; + while (dwords & 0xf) { + packet2s[num_packet2s++] = cpu_to_le32(PACKET2(0)); + dwords++; + } + + obj_size = dwords * 4; + obj_size = roundup2(obj_size, 256); + + rdev->r600_blit.vs_offset = obj_size; + obj_size += r6xx_vs_size * 4; + obj_size = roundup2(obj_size, 256); + + rdev->r600_blit.ps_offset = obj_size; + obj_size += r6xx_ps_size * 4; + obj_size = roundup2(obj_size, 256); + + /* pin copy shader into vram if not already initialized */ + if (rdev->r600_blit.shader_obj == NULL) { + r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->r600_blit.shader_obj); + if (r) { + DRM_ERROR("r600 failed to allocate shader\n"); + return r; + } + + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_gpu_addr); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + if (r) { + dev_err(rdev->dev, "(%d) pin blit object failed\n", r); + return r; + } + } + + DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n", + obj_size, + rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset); + + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_kmap(rdev->r600_blit.shader_obj, &ptr); + if (r) { + DRM_ERROR("failed to map blit object %d\n", r); + return r; + } + if (rdev->family >= CHIP_RV770) + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset, + r7xx_default_state, rdev->r600_blit.state_len * 4); + else + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset, + r6xx_default_state, rdev->r600_blit.state_len * 4); + if (num_packet2s) + memcpy_toio((char *)ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); + for (i = 0; i < r6xx_vs_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(r6xx_vs[i]); + for (i = 0; i < r6xx_ps_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(r6xx_ps[i]); + radeon_bo_kunmap(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; +} + +void r600_blit_fini(struct radeon_device *rdev) +{ + int r; + + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->r600_blit.shader_obj == NULL) + return; + /* If we can't reserve the bo, unref should be enough to destroy + * it when it becomes idle. + */ + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (!r) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } + radeon_bo_unref(&rdev->r600_blit.shader_obj); +} + +static unsigned r600_blit_create_rect(unsigned num_gpu_pages, + int *width, int *height, int max_dim) +{ + unsigned max_pages; + unsigned pages = num_gpu_pages; + int w, h; + + if (num_gpu_pages == 0) { + /* not supposed to be called with no pages, but just in case */ + h = 0; + w = 0; + pages = 0; + DRM_ERROR("%s: called with no pages", __func__); + } else { + int rect_order = 2; + h = RECT_UNIT_H; + while (num_gpu_pages / rect_order) { + h *= 2; + rect_order *= 4; + if (h >= max_dim) { + h = max_dim; + break; + } + } + max_pages = (max_dim * h) / (RECT_UNIT_W * RECT_UNIT_H); + if (pages > max_pages) + pages = max_pages; + w = (pages * RECT_UNIT_W * RECT_UNIT_H) / h; + w = (w / RECT_UNIT_W) * RECT_UNIT_W; + pages = (w * h) / (RECT_UNIT_W * RECT_UNIT_H); + KASSERT(pages != 0, ("r600_blit_create_rect: pages == 0")); + } + + + DRM_DEBUG("blit_rectangle: h=%d, w=%d, pages=%d\n", h, w, pages); + + /* return width and height only of the caller wants it */ + if (height) + *height = h; + if (width) + *width = w; + + return pages; +} + + +int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, + struct radeon_fence **fence, struct radeon_sa_bo **vb, + struct radeon_semaphore **sem) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + int ring_size; + int num_loops = 0; + int dwords_per_loop = rdev->r600_blit.ring_size_per_loop; + + /* num loops */ + while (num_gpu_pages) { + num_gpu_pages -= + r600_blit_create_rect(num_gpu_pages, NULL, NULL, + rdev->r600_blit.max_dim); + num_loops++; + } + + /* 48 bytes for vertex per loop */ + r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, vb, + (num_loops*48)+256, 256, true); + if (r) { + return r; + } + + r = radeon_semaphore_create(rdev, sem); + if (r) { + radeon_sa_bo_free(rdev, vb, NULL); + return r; + } + + /* calculate number of loops correctly */ + ring_size = num_loops * dwords_per_loop; + ring_size += rdev->r600_blit.ring_size_common; + r = radeon_ring_lock(rdev, ring, ring_size); + if (r) { + radeon_sa_bo_free(rdev, vb, NULL); + radeon_semaphore_free(rdev, sem, NULL); + return r; + } + + if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) { + radeon_semaphore_sync_rings(rdev, *sem, (*fence)->ring, + RADEON_RING_TYPE_GFX_INDEX); + radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX); + } else { + radeon_semaphore_free(rdev, sem, NULL); + } + + rdev->r600_blit.primitives.set_default_state(rdev); + rdev->r600_blit.primitives.set_shaders(rdev); + return 0; +} + +void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, + struct radeon_sa_bo *vb, struct radeon_semaphore *sem) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return; + } + + radeon_ring_unlock_commit(rdev, ring); + radeon_sa_bo_free(rdev, &vb, *fence); + radeon_semaphore_free(rdev, &sem, *fence); +} + +void r600_kms_blit_copy(struct radeon_device *rdev, + u64 src_gpu_addr, u64 dst_gpu_addr, + unsigned num_gpu_pages, + struct radeon_sa_bo *vb) +{ + u64 vb_gpu_addr; + u32 *vb_cpu_addr; + + DRM_DEBUG("emitting copy %16jx %16jx %d\n", + (uintmax_t)src_gpu_addr, (uintmax_t)dst_gpu_addr, num_gpu_pages); + vb_cpu_addr = (u32 *)radeon_sa_bo_cpu_addr(vb); + vb_gpu_addr = radeon_sa_bo_gpu_addr(vb); + + while (num_gpu_pages) { + int w, h; + unsigned size_in_bytes; + unsigned pages_per_loop = + r600_blit_create_rect(num_gpu_pages, &w, &h, + rdev->r600_blit.max_dim); + + size_in_bytes = pages_per_loop * RADEON_GPU_PAGE_SIZE; + DRM_DEBUG("rectangle w=%d h=%d\n", w, h); + + vb_cpu_addr[0] = 0; + vb_cpu_addr[1] = 0; + vb_cpu_addr[2] = 0; + vb_cpu_addr[3] = 0; + + vb_cpu_addr[4] = 0; + vb_cpu_addr[5] = int2float(h); + vb_cpu_addr[6] = 0; + vb_cpu_addr[7] = int2float(h); + + vb_cpu_addr[8] = int2float(w); + vb_cpu_addr[9] = int2float(h); + vb_cpu_addr[10] = int2float(w); + vb_cpu_addr[11] = int2float(h); + + rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8, + w, h, w, src_gpu_addr, size_in_bytes); + rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8, + w, h, dst_gpu_addr); + rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h); + rdev->r600_blit.primitives.set_vtx_resource(rdev, vb_gpu_addr); + rdev->r600_blit.primitives.draw_auto(rdev); + rdev->r600_blit.primitives.cp_set_surface_sync(rdev, + PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA, + size_in_bytes, dst_gpu_addr); + + vb_cpu_addr += 12; + vb_gpu_addr += 4*12; + src_gpu_addr += size_in_bytes; + dst_gpu_addr += size_in_bytes; + num_gpu_pages -= pages_per_loop; + } +} diff --git a/sys/dev/drm2/radeon/r600_blit_shaders.c b/sys/dev/drm2/radeon/r600_blit_shaders.c new file mode 100644 index 00000000000..1095a2c1213 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_blit_shaders.c @@ -0,0 +1,720 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +/* + * R6xx+ cards need to use the 3D engine to blit data which requires + * quite a bit of hw state setup. Rather than pull the whole 3D driver + * (which normally generates the 3D state) into the DRM, we opt to use + * statically generated state tables. The regsiter state and shaders + * were hand generated to support blitting functionality. See the 3D + * driver or documentation for descriptions of the registers and + * shader instructions. + */ + +const u32 r6xx_default_state[] = +{ + 0xc0002400, /* START_3D_CMDBUF */ + 0x00000000, + + 0xc0012800, /* CONTEXT_CONTROL */ + 0x80000000, + 0x80000000, + + 0xc0016800, + 0x00000010, + 0x00008000, /* WAIT_UNTIL */ + + 0xc0016800, + 0x00000542, + 0x07000003, /* TA_CNTL_AUX */ + + 0xc0016800, + 0x000005c5, + 0x00000000, /* VC_ENHANCE */ + + 0xc0016800, + 0x00000363, + 0x00000000, /* SQ_DYN_GPR_CNTL_PS_FLUSH_REQ */ + + 0xc0016800, + 0x0000060c, + 0x82000000, /* DB_DEBUG */ + + 0xc0016800, + 0x0000060e, + 0x01020204, /* DB_WATERMARKS */ + + 0xc0026f00, + 0x00000000, + 0x00000000, /* SQ_VTX_BASE_VTX_LOC */ + 0x00000000, /* SQ_VTX_START_INST_LOC */ + + 0xc0096900, + 0x0000022a, + 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0016900, + 0x00000004, + 0x00000000, /* DB_DEPTH_INFO */ + + 0xc0026900, + 0x0000000a, + 0x00000000, /* DB_STENCIL_CLEAR */ + 0x00000000, /* DB_DEPTH_CLEAR */ + + 0xc0016900, + 0x00000200, + 0x00000000, /* DB_DEPTH_CONTROL */ + + 0xc0026900, + 0x00000343, + 0x00000060, /* DB_RENDER_CONTROL */ + 0x00000040, /* DB_RENDER_OVERRIDE */ + + 0xc0016900, + 0x00000351, + 0x0000aa00, /* DB_ALPHA_TO_MASK */ + + 0xc00f6900, + 0x00000100, + 0x00000800, /* VGT_MAX_VTX_INDX */ + 0x00000000, /* VGT_MIN_VTX_INDX */ + 0x00000000, /* VGT_INDX_OFFSET */ + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ + 0x00000000, /* SX_ALPHA_TEST_CONTROL */ + 0x00000000, /* CB_BLEND_RED */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, /* CB_FOG_RED */ + 0x00000000, + 0x00000000, + 0x00000000, /* DB_STENCILREFMASK */ + 0x00000000, /* DB_STENCILREFMASK_BF */ + 0x00000000, /* SX_ALPHA_REF */ + + 0xc0046900, + 0x0000030c, + 0x01000000, /* CB_CLRCMP_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0046900, + 0x00000048, + 0x3f800000, /* CB_CLEAR_RED */ + 0x00000000, + 0x3f800000, + 0x3f800000, + + 0xc0016900, + 0x00000080, + 0x00000000, /* PA_SC_WINDOW_OFFSET */ + + 0xc00a6900, + 0x00000083, + 0x0000ffff, /* PA_SC_CLIP_RECT_RULE */ + 0x00000000, /* PA_SC_CLIPRECT_0_TL */ + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, /* PA_SC_EDGERULE */ + + 0xc0406900, + 0x00000094, + 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ + 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ + 0x80000000, /* PA_SC_VPORT_SCISSOR_1_TL */ + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + + 0xc0026900, + 0x00000292, + 0x00000000, /* PA_SC_MPASS_PS_CNTL */ + 0x00004010, /* PA_SC_MODE_CNTL */ + + 0xc0096900, + 0x00000300, + 0x00000000, /* PA_SC_LINE_CNTL */ + 0x00000000, /* PA_SC_AA_CONFIG */ + 0x0000002d, /* PA_SU_VTX_CNTL */ + 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ + 0x3f800000, + 0x3f800000, + 0x3f800000, + 0x00000000, /* PA_SC_SAMPLE_LOCS_MCTX */ + 0x00000000, + + 0xc0016900, + 0x00000312, + 0xffffffff, /* PA_SC_AA_MASK */ + + 0xc0066900, + 0x0000037e, + 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + 0x00000000, /* PA_SU_POLY_OFFSET_CLAMP */ + 0x00000000, /* PA_SU_POLY_OFFSET_FRONT_SCALE */ + 0x00000000, /* PA_SU_POLY_OFFSET_FRONT_OFFSET */ + 0x00000000, /* PA_SU_POLY_OFFSET_BACK_SCALE */ + 0x00000000, /* PA_SU_POLY_OFFSET_BACK_OFFSET */ + + 0xc0046900, + 0x000001b6, + 0x00000000, /* SPI_INPUT_Z */ + 0x00000000, /* SPI_FOG_CNTL */ + 0x00000000, /* SPI_FOG_FUNC_SCALE */ + 0x00000000, /* SPI_FOG_FUNC_BIAS */ + + 0xc0016900, + 0x00000225, + 0x00000000, /* SQ_PGM_START_FS */ + + 0xc0016900, + 0x00000229, + 0x00000000, /* SQ_PGM_RESOURCES_FS */ + + 0xc0016900, + 0x00000237, + 0x00000000, /* SQ_PGM_CF_OFFSET_FS */ + + 0xc0026900, + 0x000002a8, + 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ + 0x00000000, /* VGT_INSTANCE_STEP_RATE_1 */ + + 0xc0116900, + 0x00000280, + 0x00000000, /* PA_SU_POINT_SIZE */ + 0x00000000, /* PA_SU_POINT_MINMAX */ + 0x00000008, /* PA_SU_LINE_CNTL */ + 0x00000000, /* PA_SC_LINE_STIPPLE */ + 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ + 0x00000000, /* VGT_HOS_CNTL */ + 0x00000000, /* VGT_HOS_MAX_TESS_LEVEL */ + 0x00000000, /* VGT_HOS_MIN_TESS_LEVEL */ + 0x00000000, /* VGT_HOS_REUSE_DEPTH */ + 0x00000000, /* VGT_GROUP_PRIM_TYPE */ + 0x00000000, /* VGT_GROUP_FIRST_DECR */ + 0x00000000, /* VGT_GROUP_DECR */ + 0x00000000, /* VGT_GROUP_VECT_0_CNTL */ + 0x00000000, /* VGT_GROUP_VECT_1_CNTL */ + 0x00000000, /* VGT_GROUP_VECT_0_FMT_CNTL */ + 0x00000000, /* VGT_GROUP_VECT_1_FMT_CNTL */ + 0x00000000, /* VGT_GS_MODE */ + + 0xc0016900, + 0x000002a1, + 0x00000000, /* VGT_PRIMITIVEID_EN */ + + 0xc0016900, + 0x000002a5, + 0x00000000, /* VGT_MULTI_PRIM_ID_RESET_EN */ + + 0xc0036900, + 0x000002ac, + 0x00000000, /* VGT_STRMOUT_EN */ + 0x00000000, /* VGT_REUSE_OFF */ + 0x00000000, /* VGT_VTX_CNT_EN */ + + 0xc0016900, + 0x000000d4, + 0x00000000, /* SX_MISC */ + + 0xc0016900, + 0x000002c8, + 0x00000000, /* VGT_STRMOUT_BUFFER_EN */ + + 0xc0076900, + 0x00000202, + 0x00cc0000, /* CB_COLOR_CONTROL */ + 0x00000210, /* DB_SHADER_CNTL */ + 0x00010000, /* PA_CL_CLIP_CNTL */ + 0x00000244, /* PA_SU_SC_MODE_CNTL */ + 0x00000100, /* PA_CL_VTE_CNTL */ + 0x00000000, /* PA_CL_VS_OUT_CNTL */ + 0x00000000, /* PA_CL_NANINF_CNTL */ + + 0xc0026900, + 0x0000008e, + 0x0000000f, /* CB_TARGET_MASK */ + 0x0000000f, /* CB_SHADER_MASK */ + + 0xc0016900, + 0x000001e8, + 0x00000001, /* CB_SHADER_CONTROL */ + + 0xc0016900, + 0x00000185, + 0x00000000, /* SPI_VS_OUT_ID_0 */ + + 0xc0016900, + 0x00000191, + 0x00000b00, /* SPI_PS_INPUT_CNTL_0 */ + + 0xc0056900, + 0x000001b1, + 0x00000000, /* SPI_VS_OUT_CONFIG */ + 0x00000000, /* SPI_THREAD_GROUPING */ + 0x00000001, /* SPI_PS_IN_CONTROL_0 */ + 0x00000000, /* SPI_PS_IN_CONTROL_1 */ + 0x00000000, /* SPI_INTERP_CONTROL_0 */ + + 0xc0036e00, /* SET_SAMPLER */ + 0x00000000, + 0x00000012, + 0x00000000, + 0x00000000, +}; + +const u32 r7xx_default_state[] = +{ + 0xc0012800, /* CONTEXT_CONTROL */ + 0x80000000, + 0x80000000, + + 0xc0016800, + 0x00000010, + 0x00008000, /* WAIT_UNTIL */ + + 0xc0016800, + 0x00000542, + 0x07000002, /* TA_CNTL_AUX */ + + 0xc0016800, + 0x000005c5, + 0x00000000, /* VC_ENHANCE */ + + 0xc0016800, + 0x00000363, + 0x00004000, /* SQ_DYN_GPR_CNTL_PS_FLUSH_REQ */ + + 0xc0016800, + 0x0000060c, + 0x00000000, /* DB_DEBUG */ + + 0xc0016800, + 0x0000060e, + 0x00420204, /* DB_WATERMARKS */ + + 0xc0026f00, + 0x00000000, + 0x00000000, /* SQ_VTX_BASE_VTX_LOC */ + 0x00000000, /* SQ_VTX_START_INST_LOC */ + + 0xc0096900, + 0x0000022a, + 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0016900, + 0x00000004, + 0x00000000, /* DB_DEPTH_INFO */ + + 0xc0026900, + 0x0000000a, + 0x00000000, /* DB_STENCIL_CLEAR */ + 0x00000000, /* DB_DEPTH_CLEAR */ + + 0xc0016900, + 0x00000200, + 0x00000000, /* DB_DEPTH_CONTROL */ + + 0xc0026900, + 0x00000343, + 0x00000060, /* DB_RENDER_CONTROL */ + 0x00000000, /* DB_RENDER_OVERRIDE */ + + 0xc0016900, + 0x00000351, + 0x0000aa00, /* DB_ALPHA_TO_MASK */ + + 0xc0096900, + 0x00000100, + 0x00000800, /* VGT_MAX_VTX_INDX */ + 0x00000000, /* VGT_MIN_VTX_INDX */ + 0x00000000, /* VGT_INDX_OFFSET */ + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ + 0x00000000, /* SX_ALPHA_TEST_CONTROL */ + 0x00000000, /* CB_BLEND_RED */ + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0036900, + 0x0000010c, + 0x00000000, /* DB_STENCILREFMASK */ + 0x00000000, /* DB_STENCILREFMASK_BF */ + 0x00000000, /* SX_ALPHA_REF */ + + 0xc0046900, + 0x0000030c, /* CB_CLRCMP_CNTL */ + 0x01000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0016900, + 0x00000080, + 0x00000000, /* PA_SC_WINDOW_OFFSET */ + + 0xc00a6900, + 0x00000083, + 0x0000ffff, /* PA_SC_CLIP_RECT_RULE */ + 0x00000000, /* PA_SC_CLIPRECT_0_TL */ + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0xaaaaaaaa, /* PA_SC_EDGERULE */ + + 0xc0406900, + 0x00000094, + 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ + 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ + 0x80000000, /* PA_SC_VPORT_SCISSOR_1_TL */ + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + 0x00000000, + 0x3f800000, + + 0xc0026900, + 0x00000292, + 0x00000000, /* PA_SC_MPASS_PS_CNTL */ + 0x00514000, /* PA_SC_MODE_CNTL */ + + 0xc0096900, + 0x00000300, + 0x00000000, /* PA_SC_LINE_CNTL */ + 0x00000000, /* PA_SC_AA_CONFIG */ + 0x0000002d, /* PA_SU_VTX_CNTL */ + 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ + 0x3f800000, + 0x3f800000, + 0x3f800000, + 0x00000000, /* PA_SC_SAMPLE_LOCS_MCTX */ + 0x00000000, + + 0xc0016900, + 0x00000312, + 0xffffffff, /* PA_SC_AA_MASK */ + + 0xc0066900, + 0x0000037e, + 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + 0x00000000, /* PA_SU_POLY_OFFSET_CLAMP */ + 0x00000000, /* PA_SU_POLY_OFFSET_FRONT_SCALE */ + 0x00000000, /* PA_SU_POLY_OFFSET_FRONT_OFFSET */ + 0x00000000, /* PA_SU_POLY_OFFSET_BACK_SCALE */ + 0x00000000, /* PA_SU_POLY_OFFSET_BACK_OFFSET */ + + 0xc0046900, + 0x000001b6, + 0x00000000, /* SPI_INPUT_Z */ + 0x00000000, /* SPI_FOG_CNTL */ + 0x00000000, /* SPI_FOG_FUNC_SCALE */ + 0x00000000, /* SPI_FOG_FUNC_BIAS */ + + 0xc0016900, + 0x00000225, + 0x00000000, /* SQ_PGM_START_FS */ + + 0xc0016900, + 0x00000229, + 0x00000000, /* SQ_PGM_RESOURCES_FS */ + + 0xc0016900, + 0x00000237, + 0x00000000, /* SQ_PGM_CF_OFFSET_FS */ + + 0xc0026900, + 0x000002a8, + 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ + 0x00000000, /* VGT_INSTANCE_STEP_RATE_1 */ + + 0xc0116900, + 0x00000280, + 0x00000000, /* PA_SU_POINT_SIZE */ + 0x00000000, /* PA_SU_POINT_MINMAX */ + 0x00000008, /* PA_SU_LINE_CNTL */ + 0x00000000, /* PA_SC_LINE_STIPPLE */ + 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ + 0x00000000, /* VGT_HOS_CNTL */ + 0x00000000, /* VGT_HOS_MAX_TESS_LEVEL */ + 0x00000000, /* VGT_HOS_MIN_TESS_LEVEL */ + 0x00000000, /* VGT_HOS_REUSE_DEPTH */ + 0x00000000, /* VGT_GROUP_PRIM_TYPE */ + 0x00000000, /* VGT_GROUP_FIRST_DECR */ + 0x00000000, /* VGT_GROUP_DECR */ + 0x00000000, /* VGT_GROUP_VECT_0_CNTL */ + 0x00000000, /* VGT_GROUP_VECT_1_CNTL */ + 0x00000000, /* VGT_GROUP_VECT_0_FMT_CNTL */ + 0x00000000, /* VGT_GROUP_VECT_1_FMT_CNTL */ + 0x00000000, /* VGT_GS_MODE */ + + 0xc0016900, + 0x000002a1, + 0x00000000, /* VGT_PRIMITIVEID_EN */ + + 0xc0016900, + 0x000002a5, + 0x00000000, /* VGT_MULTI_PRIM_ID_RESET_EN */ + + 0xc0036900, + 0x000002ac, + 0x00000000, /* VGT_STRMOUT_EN */ + 0x00000000, /* VGT_REUSE_OFF */ + 0x00000000, /* VGT_VTX_CNT_EN */ + + 0xc0016900, + 0x000000d4, + 0x00000000, /* SX_MISC */ + + 0xc0016900, + 0x000002c8, + 0x00000000, /* VGT_STRMOUT_BUFFER_EN */ + + 0xc0076900, + 0x00000202, + 0x00cc0000, /* CB_COLOR_CONTROL */ + 0x00000210, /* DB_SHADER_CNTL */ + 0x00010000, /* PA_CL_CLIP_CNTL */ + 0x00000244, /* PA_SU_SC_MODE_CNTL */ + 0x00000100, /* PA_CL_VTE_CNTL */ + 0x00000000, /* PA_CL_VS_OUT_CNTL */ + 0x00000000, /* PA_CL_NANINF_CNTL */ + + 0xc0026900, + 0x0000008e, + 0x0000000f, /* CB_TARGET_MASK */ + 0x0000000f, /* CB_SHADER_MASK */ + + 0xc0016900, + 0x000001e8, + 0x00000001, /* CB_SHADER_CONTROL */ + + 0xc0016900, + 0x00000185, + 0x00000000, /* SPI_VS_OUT_ID_0 */ + + 0xc0016900, + 0x00000191, + 0x00000b00, /* SPI_PS_INPUT_CNTL_0 */ + + 0xc0056900, + 0x000001b1, + 0x00000000, /* SPI_VS_OUT_CONFIG */ + 0x00000001, /* SPI_THREAD_GROUPING */ + 0x00000001, /* SPI_PS_IN_CONTROL_0 */ + 0x00000000, /* SPI_PS_IN_CONTROL_1 */ + 0x00000000, /* SPI_INTERP_CONTROL_0 */ + + 0xc0036e00, /* SET_SAMPLER */ + 0x00000000, + 0x00000012, + 0x00000000, + 0x00000000, +}; + +/* same for r6xx/r7xx */ +const u32 r6xx_vs[] = +{ + 0x00000004, + 0x81000000, + 0x0000203c, + 0x94000b08, + 0x00004000, + 0x14200b1a, + 0x00000000, + 0x00000000, + 0x3c000000, + 0x68cd1000, +#ifdef __BIG_ENDIAN + 0x000a0000, +#else + 0x00080000, +#endif + 0x00000000, +}; + +const u32 r6xx_ps[] = +{ + 0x00000002, + 0x80800000, + 0x00000000, + 0x94200688, + 0x00000010, + 0x000d1000, + 0xb0800000, + 0x00000000, +}; + +const u32 r6xx_ps_size = DRM_ARRAY_SIZE(r6xx_ps); +const u32 r6xx_vs_size = DRM_ARRAY_SIZE(r6xx_vs); +const u32 r6xx_default_size = DRM_ARRAY_SIZE(r6xx_default_state); +const u32 r7xx_default_size = DRM_ARRAY_SIZE(r7xx_default_state); diff --git a/sys/dev/drm2/radeon/r600_blit_shaders.h b/sys/dev/drm2/radeon/r600_blit_shaders.h new file mode 100644 index 00000000000..591b756d2b3 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_blit_shaders.h @@ -0,0 +1,42 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef R600_BLIT_SHADERS_H +#define R600_BLIT_SHADERS_H + +#include +__FBSDID("$FreeBSD$"); + +extern const u32 r6xx_ps[]; +extern const u32 r6xx_vs[]; +extern const u32 r7xx_default_state[]; +extern const u32 r6xx_default_state[]; + + +extern const u32 r6xx_ps_size, r6xx_vs_size; +extern const u32 r6xx_default_size, r7xx_default_size; + +__pure uint32_t int2float(uint32_t x); +#endif diff --git a/sys/dev/drm2/radeon/r600_cp.c b/sys/dev/drm2/radeon/r600_cp.c new file mode 100644 index 00000000000..2907bdb2fbe --- /dev/null +++ b/sys/dev/drm2/radeon/r600_cp.c @@ -0,0 +1,2645 @@ +/* + * Copyright 2008-2009 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include "radeon_drv.h" +#include "r600_cp.h" + +#define PFP_UCODE_SIZE 576 +#define PM4_UCODE_SIZE 1792 +#define R700_PFP_UCODE_SIZE 848 +#define R700_PM4_UCODE_SIZE 1360 + +# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ +# define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1)) + +#define R600_PTE_VALID (1 << 0) +#define R600_PTE_SYSTEM (1 << 1) +#define R600_PTE_SNOOPED (1 << 2) +#define R600_PTE_READABLE (1 << 5) +#define R600_PTE_WRITEABLE (1 << 6) + +/* MAX values used for gfx init */ +#define R6XX_MAX_SH_GPRS 256 +#define R6XX_MAX_TEMP_GPRS 16 +#define R6XX_MAX_SH_THREADS 256 +#define R6XX_MAX_SH_STACK_ENTRIES 4096 +#define R6XX_MAX_BACKENDS 8 +#define R6XX_MAX_BACKENDS_MASK 0xff +#define R6XX_MAX_SIMDS 8 +#define R6XX_MAX_SIMDS_MASK 0xff +#define R6XX_MAX_PIPES 8 +#define R6XX_MAX_PIPES_MASK 0xff + +#define R7XX_MAX_SH_GPRS 256 +#define R7XX_MAX_TEMP_GPRS 16 +#define R7XX_MAX_SH_THREADS 256 +#define R7XX_MAX_SH_STACK_ENTRIES 4096 +#define R7XX_MAX_BACKENDS 8 +#define R7XX_MAX_BACKENDS_MASK 0xff +#define R7XX_MAX_SIMDS 16 +#define R7XX_MAX_SIMDS_MASK 0xffff +#define R7XX_MAX_PIPES 8 +#define R7XX_MAX_PIPES_MASK 0xff + +static int r600_do_wait_for_fifo(drm_radeon_private_t *dev_priv, int entries) +{ + int i; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) + slots = (RADEON_READ(R600_GRBM_STATUS) + & R700_CMDFIFO_AVAIL_MASK); + else + slots = (RADEON_READ(R600_GRBM_STATUS) + & R600_CMDFIFO_AVAIL_MASK); + if (slots >= entries) + return 0; + DRM_UDELAY(1); + } + DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n", + RADEON_READ(R600_GRBM_STATUS), + RADEON_READ(R600_GRBM_STATUS2)); + + return -EBUSY; +} + +static int r600_do_wait_for_idle(drm_radeon_private_t *dev_priv) +{ + int i, ret; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) + ret = r600_do_wait_for_fifo(dev_priv, 8); + else + ret = r600_do_wait_for_fifo(dev_priv, 16); + if (ret) + return ret; + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(RADEON_READ(R600_GRBM_STATUS) & R600_GUI_ACTIVE)) + return 0; + DRM_UDELAY(1); + } + DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n", + RADEON_READ(R600_GRBM_STATUS), + RADEON_READ(R600_GRBM_STATUS2)); + + return -EBUSY; +} + +void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) +{ + struct drm_sg_mem *entry = dev->sg; +#ifdef __linux__ + int max_pages; + int pages; + int i; +#endif + + if (!entry) + return; + + if (gart_info->bus_addr) { +#ifdef __linux__ + max_pages = (gart_info->table_size / sizeof(u64)); + pages = (entry->pages <= max_pages) + ? entry->pages : max_pages; + + for (i = 0; i < pages; i++) { + if (!entry->busaddr[i]) + break; + pci_unmap_page(dev->pdev, entry->busaddr[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } +#endif + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) + gart_info->bus_addr = 0; + } +} + +/* R600 has page table setup */ +int r600_page_table_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info; + struct drm_local_map *map = &gart_info->mapping; + struct drm_sg_mem *entry = dev->sg; + int ret = 0; + int i, j; + int pages; + u64 page_base; + dma_addr_t entry_addr; + int max_ati_pages, max_real_pages, gart_idx; + + /* okay page table is available - lets rock */ + max_ati_pages = (gart_info->table_size / sizeof(u64)); + max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); + + pages = (entry->pages <= max_real_pages) ? + entry->pages : max_real_pages; + + memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u64)); + + gart_idx = 0; + for (i = 0; i < pages; i++) { +#ifdef __linux__ + entry->busaddr[i] = pci_map_page(dev->pdev, + entry->pagelist[i], 0, + PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { + DRM_ERROR("unable to map PCIGART pages!\n"); + r600_page_table_cleanup(dev, gart_info); + goto done; + } +#endif + entry_addr = entry->busaddr[i]; + for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { + page_base = (u64) entry_addr & ATI_PCIGART_PAGE_MASK; + page_base |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED; + page_base |= R600_PTE_READABLE | R600_PTE_WRITEABLE; + + DRM_WRITE64(map, gart_idx * sizeof(u64), page_base); + + gart_idx++; + + if ((i % 128) == 0) + DRM_DEBUG("page entry %d: 0x%016llx\n", + i, (unsigned long long)page_base); + entry_addr += ATI_PCIGART_PAGE_SIZE; + } + } + ret = 1; +#ifdef __linux__ +done: +#endif + return ret; +} + +static void r600_vm_flush_gart_range(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 resp, countdown = 1000; + RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR, dev_priv->gart_vm_start >> 12); + RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + RADEON_WRITE(R600_VM_CONTEXT0_REQUEST_RESPONSE, 2); + + do { + resp = RADEON_READ(R600_VM_CONTEXT0_REQUEST_RESPONSE); + countdown--; + DRM_UDELAY(1); + } while (((resp & 0xf0) == 0) && countdown); +} + +static void r600_vm_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + /* initialise the VM to use the page table we constructed up there */ + u32 vm_c0, i; + u32 mc_rd_a; + u32 vm_l2_cntl, vm_l2_cntl3; + /* okay set up the PCIE aperture type thingo */ + RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12); + RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); + + /* setup MC RD a */ + mc_rd_a = R600_MCD_L1_TLB | R600_MCD_L1_FRAG_PROC | R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS | + R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | R600_MCD_EFFECTIVE_L1_TLB_SIZE(5) | + R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(5) | R600_MCD_WAIT_L2_QUERY; + + RADEON_WRITE(R600_MCD_RD_A_CNTL, mc_rd_a); + RADEON_WRITE(R600_MCD_RD_B_CNTL, mc_rd_a); + + RADEON_WRITE(R600_MCD_WR_A_CNTL, mc_rd_a); + RADEON_WRITE(R600_MCD_WR_B_CNTL, mc_rd_a); + + RADEON_WRITE(R600_MCD_RD_GFX_CNTL, mc_rd_a); + RADEON_WRITE(R600_MCD_WR_GFX_CNTL, mc_rd_a); + + RADEON_WRITE(R600_MCD_RD_SYS_CNTL, mc_rd_a); + RADEON_WRITE(R600_MCD_WR_SYS_CNTL, mc_rd_a); + + RADEON_WRITE(R600_MCD_RD_HDP_CNTL, mc_rd_a | R600_MCD_L1_STRICT_ORDERING); + RADEON_WRITE(R600_MCD_WR_HDP_CNTL, mc_rd_a /*| R600_MCD_L1_STRICT_ORDERING*/); + + RADEON_WRITE(R600_MCD_RD_PDMA_CNTL, mc_rd_a); + RADEON_WRITE(R600_MCD_WR_PDMA_CNTL, mc_rd_a); + + RADEON_WRITE(R600_MCD_RD_SEM_CNTL, mc_rd_a | R600_MCD_SEMAPHORE_MODE); + RADEON_WRITE(R600_MCD_WR_SEM_CNTL, mc_rd_a); + + vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W; + vm_l2_cntl |= R600_VM_L2_CNTL_QUEUE_SIZE(7); + RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl); + + RADEON_WRITE(R600_VM_L2_CNTL2, 0); + vm_l2_cntl3 = (R600_VM_L2_CNTL3_BANK_SELECT_0(0) | + R600_VM_L2_CNTL3_BANK_SELECT_1(1) | + R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(2)); + RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3); + + vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT; + + RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0); + + vm_c0 &= ~R600_VM_ENABLE_CONTEXT; + + /* disable all other contexts */ + for (i = 1; i < 8; i++) + RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0); + + RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12); + RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12); + RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + + r600_vm_flush_gart_range(dev); +} + +static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv) +{ + const char *chip_name; + size_t pfp_req_size, me_req_size; + char fw_name[30]; + int err; + + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_R600: chip_name = "R600"; break; + case CHIP_RV610: chip_name = "RV610"; break; + case CHIP_RV630: chip_name = "RV630"; break; + case CHIP_RV620: chip_name = "RV620"; break; + case CHIP_RV635: chip_name = "RV635"; break; + case CHIP_RV670: chip_name = "RV670"; break; + case CHIP_RS780: + case CHIP_RS880: chip_name = "RS780"; break; + case CHIP_RV770: chip_name = "RV770"; break; + case CHIP_RV730: + case CHIP_RV740: chip_name = "RV730"; break; + case CHIP_RV710: chip_name = "RV710"; break; + default: panic("%s: Unsupported family %d", __func__, dev_priv->flags & RADEON_FAMILY_MASK); + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { + pfp_req_size = R700_PFP_UCODE_SIZE * 4; + me_req_size = R700_PM4_UCODE_SIZE * 4; + } else { + pfp_req_size = PFP_UCODE_SIZE * 4; + me_req_size = PM4_UCODE_SIZE * 12; + } + + DRM_INFO("Loading %s CP Microcode\n", chip_name); + err = 0; + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_pfp", chip_name); + dev_priv->pfp_fw = firmware_get(fw_name); + if (dev_priv->pfp_fw == NULL) { + err = -ENOENT; + goto out; + } + if (dev_priv->pfp_fw->datasize != pfp_req_size) { + DRM_ERROR( + "r600_cp: Bogus length %zu in firmware \"%s\"\n", + dev_priv->pfp_fw->datasize, fw_name); + err = -EINVAL; + goto out; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_me", chip_name); + dev_priv->me_fw = firmware_get(fw_name); + if (dev_priv->me_fw == NULL) { + err = -ENOENT; + goto out; + } + if (dev_priv->me_fw->datasize != me_req_size) { + DRM_ERROR( + "r600_cp: Bogus length %zu in firmware \"%s\"\n", + dev_priv->me_fw->datasize, fw_name); + err = -EINVAL; + } +out: + if (err) { + if (err != -EINVAL) + DRM_ERROR( + "r600_cp: Failed to load firmware \"%s\"\n", + fw_name); + if (dev_priv->pfp_fw != NULL) { + firmware_put(dev_priv->pfp_fw, FIRMWARE_UNLOAD); + dev_priv->pfp_fw = NULL; + } + if (dev_priv->me_fw != NULL) { + firmware_put(dev_priv->me_fw, FIRMWARE_UNLOAD); + dev_priv->me_fw = NULL; + } + } + return err; +} + +static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) +{ + const __be32 *fw_data; + int i; + + if (!dev_priv->me_fw || !dev_priv->pfp_fw) + return; + + r600_do_cp_stop(dev_priv); + + RADEON_WRITE(R600_CP_RB_CNTL, +#ifdef __BIG_ENDIAN + R600_BUF_SWAP_32BIT | +#endif + R600_RB_NO_UPDATE | + R600_RB_BLKSZ(15) | + R600_RB_BUFSZ(3)); + + RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); + RADEON_READ(R600_GRBM_SOFT_RESET); + DRM_MDELAY(15); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + + fw_data = (const __be32 *)dev_priv->me_fw->data; + RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); + for (i = 0; i < PM4_UCODE_SIZE * 3; i++) + RADEON_WRITE(R600_CP_ME_RAM_DATA, + be32_to_cpup(fw_data++)); + + fw_data = (const __be32 *)dev_priv->pfp_fw->data; + RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < PFP_UCODE_SIZE; i++) + RADEON_WRITE(R600_CP_PFP_UCODE_DATA, + be32_to_cpup(fw_data++)); + + RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); + RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); + RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); + +} + +static void r700_vm_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + /* initialise the VM to use the page table we constructed up there */ + u32 vm_c0, i; + u32 mc_vm_md_l1; + u32 vm_l2_cntl, vm_l2_cntl3; + /* okay set up the PCIE aperture type thingo */ + RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12); + RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); + + mc_vm_md_l1 = R700_ENABLE_L1_TLB | + R700_ENABLE_L1_FRAGMENT_PROCESSING | + R700_SYSTEM_ACCESS_MODE_IN_SYS | + R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + R700_EFFECTIVE_L1_TLB_SIZE(5) | + R700_EFFECTIVE_L1_QUEUE_SIZE(5); + + RADEON_WRITE(R700_MC_VM_MD_L1_TLB0_CNTL, mc_vm_md_l1); + RADEON_WRITE(R700_MC_VM_MD_L1_TLB1_CNTL, mc_vm_md_l1); + RADEON_WRITE(R700_MC_VM_MD_L1_TLB2_CNTL, mc_vm_md_l1); + RADEON_WRITE(R700_MC_VM_MB_L1_TLB0_CNTL, mc_vm_md_l1); + RADEON_WRITE(R700_MC_VM_MB_L1_TLB1_CNTL, mc_vm_md_l1); + RADEON_WRITE(R700_MC_VM_MB_L1_TLB2_CNTL, mc_vm_md_l1); + RADEON_WRITE(R700_MC_VM_MB_L1_TLB3_CNTL, mc_vm_md_l1); + + vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W; + vm_l2_cntl |= R700_VM_L2_CNTL_QUEUE_SIZE(7); + RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl); + + RADEON_WRITE(R600_VM_L2_CNTL2, 0); + vm_l2_cntl3 = R700_VM_L2_CNTL3_BANK_SELECT(0) | R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(2); + RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3); + + vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT; + + RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0); + + vm_c0 &= ~R600_VM_ENABLE_CONTEXT; + + /* disable all other contexts */ + for (i = 1; i < 8; i++) + RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0); + + RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12); + RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12); + RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + + r600_vm_flush_gart_range(dev); +} + +static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) +{ + const __be32 *fw_data; + int i; + + if (!dev_priv->me_fw || !dev_priv->pfp_fw) + return; + + r600_do_cp_stop(dev_priv); + + RADEON_WRITE(R600_CP_RB_CNTL, +#ifdef __BIG_ENDIAN + R600_BUF_SWAP_32BIT | +#endif + R600_RB_NO_UPDATE | + R600_RB_BLKSZ(15) | + R600_RB_BUFSZ(3)); + + RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); + RADEON_READ(R600_GRBM_SOFT_RESET); + DRM_MDELAY(15); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + + fw_data = (const __be32 *)dev_priv->pfp_fw->data; + RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < R700_PFP_UCODE_SIZE; i++) + RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); + RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); + + fw_data = (const __be32 *)dev_priv->me_fw->data; + RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); + for (i = 0; i < R700_PM4_UCODE_SIZE; i++) + RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); + RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); + + RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); + RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); + RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); + +} + +static void r600_test_writeback(drm_radeon_private_t *dev_priv) +{ + u32 tmp; + + /* Start with assuming that writeback doesn't work */ + dev_priv->writeback_works = 0; + + /* Writeback doesn't seem to work everywhere, test it here and possibly + * enable it if it appears to work + */ + radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0); + + RADEON_WRITE(R600_SCRATCH_REG1, 0xdeadbeef); + + for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { + u32 val; + + val = radeon_read_ring_rptr(dev_priv, R600_SCRATCHOFF(1)); + if (val == 0xdeadbeef) + break; + DRM_UDELAY(1); + } + + if (tmp < dev_priv->usec_timeout) { + dev_priv->writeback_works = 1; + DRM_INFO("writeback test succeeded in %d usecs\n", tmp); + } else { + dev_priv->writeback_works = 0; + DRM_INFO("writeback test failed\n"); + } + if (radeon_no_wb == 1) { + dev_priv->writeback_works = 0; + DRM_INFO("writeback forced off\n"); + } + + if (!dev_priv->writeback_works) { + /* Disable writeback to avoid unnecessary bus master transfer */ + RADEON_WRITE(R600_CP_RB_CNTL, +#ifdef __BIG_ENDIAN + R600_BUF_SWAP_32BIT | +#endif + RADEON_READ(R600_CP_RB_CNTL) | + R600_RB_NO_UPDATE); + RADEON_WRITE(R600_SCRATCH_UMSK, 0); + } +} + +int r600_do_engine_reset(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 cp_ptr, cp_me_cntl, cp_rb_cntl; + + DRM_INFO("Resetting GPU\n"); + + cp_ptr = RADEON_READ(R600_CP_RB_WPTR); + cp_me_cntl = RADEON_READ(R600_CP_ME_CNTL); + RADEON_WRITE(R600_CP_ME_CNTL, R600_CP_ME_HALT); + + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0x7fff); + RADEON_READ(R600_GRBM_SOFT_RESET); + DRM_UDELAY(50); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + RADEON_READ(R600_GRBM_SOFT_RESET); + + RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0); + cp_rb_cntl = RADEON_READ(R600_CP_RB_CNTL); + RADEON_WRITE(R600_CP_RB_CNTL, +#ifdef __BIG_ENDIAN + R600_BUF_SWAP_32BIT | +#endif + R600_RB_RPTR_WR_ENA); + + RADEON_WRITE(R600_CP_RB_RPTR_WR, cp_ptr); + RADEON_WRITE(R600_CP_RB_WPTR, cp_ptr); + RADEON_WRITE(R600_CP_RB_CNTL, cp_rb_cntl); + RADEON_WRITE(R600_CP_ME_CNTL, cp_me_cntl); + + /* Reset the CP ring */ + r600_do_cp_reset(dev_priv); + + /* The CP is no longer running after an engine reset */ + dev_priv->cp_running = 0; + + /* Reset any pending vertex, indirect buffers */ + radeon_freelist_reset(dev); + + return 0; + +} + +static u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask; + u32 enabled_backends_count; + u32 cur_pipe; + u32 swizzle_pipe[R6XX_MAX_PIPES]; + u32 cur_backend; + u32 i; + + if (num_tile_pipes > R6XX_MAX_PIPES) + num_tile_pipes = R6XX_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > R6XX_MAX_BACKENDS) + num_backends = R6XX_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + for (i = 0; i < R6XX_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES); + switch (num_tile_pipes) { + case 1: + swizzle_pipe[0] = 0; + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 3: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + break; + case 4: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + break; + case 5: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + break; + case 6: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 5; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + break; + case 7: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + break; + case 8: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + break; + } + + cur_backend = 0; + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; + + backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); + + cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; + } + + return backend_map; +} + +static int r600_count_pipe_bits(uint32_t val) +{ + return hweight32(val); +} + +static void r600_gfx_init(struct drm_device *dev, + drm_radeon_private_t *dev_priv) +{ + int i, j, num_qd_pipes; + u32 sx_debug_1; + u32 tc_cntl; + u32 arb_pop; + u32 num_gs_verts_per_thread; + u32 vgt_gs_per_es; + u32 gs_prim_buffer_depth = 0; + u32 sq_ms_fifo_sizes; + u32 sq_config; + u32 sq_gpr_resource_mgmt_1 = 0; + u32 sq_gpr_resource_mgmt_2 = 0; + u32 sq_thread_resource_mgmt = 0; + u32 sq_stack_resource_mgmt_1 = 0; + u32 sq_stack_resource_mgmt_2 = 0; + u32 hdp_host_path_cntl; + u32 backend_map; + u32 gb_tiling_config = 0; + u32 cc_rb_backend_disable; + u32 cc_gc_shader_pipe_config; + u32 ramcfg; + + /* setup chip specs */ + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_R600: + dev_priv->r600_max_pipes = 4; + dev_priv->r600_max_tile_pipes = 8; + dev_priv->r600_max_simds = 4; + dev_priv->r600_max_backends = 4; + dev_priv->r600_max_gprs = 256; + dev_priv->r600_max_threads = 192; + dev_priv->r600_max_stack_entries = 256; + dev_priv->r600_max_hw_contexts = 8; + dev_priv->r600_max_gs_threads = 16; + dev_priv->r600_sx_max_export_size = 128; + dev_priv->r600_sx_max_export_pos_size = 16; + dev_priv->r600_sx_max_export_smx_size = 128; + dev_priv->r600_sq_num_cf_insts = 2; + break; + case CHIP_RV630: + case CHIP_RV635: + dev_priv->r600_max_pipes = 2; + dev_priv->r600_max_tile_pipes = 2; + dev_priv->r600_max_simds = 3; + dev_priv->r600_max_backends = 1; + dev_priv->r600_max_gprs = 128; + dev_priv->r600_max_threads = 192; + dev_priv->r600_max_stack_entries = 128; + dev_priv->r600_max_hw_contexts = 8; + dev_priv->r600_max_gs_threads = 4; + dev_priv->r600_sx_max_export_size = 128; + dev_priv->r600_sx_max_export_pos_size = 16; + dev_priv->r600_sx_max_export_smx_size = 128; + dev_priv->r600_sq_num_cf_insts = 2; + break; + case CHIP_RV610: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV620: + dev_priv->r600_max_pipes = 1; + dev_priv->r600_max_tile_pipes = 1; + dev_priv->r600_max_simds = 2; + dev_priv->r600_max_backends = 1; + dev_priv->r600_max_gprs = 128; + dev_priv->r600_max_threads = 192; + dev_priv->r600_max_stack_entries = 128; + dev_priv->r600_max_hw_contexts = 4; + dev_priv->r600_max_gs_threads = 4; + dev_priv->r600_sx_max_export_size = 128; + dev_priv->r600_sx_max_export_pos_size = 16; + dev_priv->r600_sx_max_export_smx_size = 128; + dev_priv->r600_sq_num_cf_insts = 1; + break; + case CHIP_RV670: + dev_priv->r600_max_pipes = 4; + dev_priv->r600_max_tile_pipes = 4; + dev_priv->r600_max_simds = 4; + dev_priv->r600_max_backends = 4; + dev_priv->r600_max_gprs = 192; + dev_priv->r600_max_threads = 192; + dev_priv->r600_max_stack_entries = 256; + dev_priv->r600_max_hw_contexts = 8; + dev_priv->r600_max_gs_threads = 16; + dev_priv->r600_sx_max_export_size = 128; + dev_priv->r600_sx_max_export_pos_size = 16; + dev_priv->r600_sx_max_export_smx_size = 128; + dev_priv->r600_sq_num_cf_insts = 2; + break; + default: + break; + } + + /* Initialize HDP */ + j = 0; + for (i = 0; i < 32; i++) { + RADEON_WRITE((0x2c14 + j), 0x00000000); + RADEON_WRITE((0x2c18 + j), 0x00000000); + RADEON_WRITE((0x2c1c + j), 0x00000000); + RADEON_WRITE((0x2c20 + j), 0x00000000); + RADEON_WRITE((0x2c24 + j), 0x00000000); + j += 0x18; + } + + RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff)); + + /* setup tiling, simd, pipe config */ + ramcfg = RADEON_READ(R600_RAMCFG); + + switch (dev_priv->r600_max_tile_pipes) { + case 1: + gb_tiling_config |= R600_PIPE_TILING(0); + break; + case 2: + gb_tiling_config |= R600_PIPE_TILING(1); + break; + case 4: + gb_tiling_config |= R600_PIPE_TILING(2); + break; + case 8: + gb_tiling_config |= R600_PIPE_TILING(3); + break; + default: + break; + } + + gb_tiling_config |= R600_BANK_TILING((ramcfg >> R600_NOOFBANK_SHIFT) & R600_NOOFBANK_MASK); + + gb_tiling_config |= R600_GROUP_SIZE(0); + + if (((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK) > 3) { + gb_tiling_config |= R600_ROW_TILING(3); + gb_tiling_config |= R600_SAMPLE_SPLIT(3); + } else { + gb_tiling_config |= + R600_ROW_TILING(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK)); + gb_tiling_config |= + R600_SAMPLE_SPLIT(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK)); + } + + gb_tiling_config |= R600_BANK_SWAPS(1); + + cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000; + cc_rb_backend_disable |= + R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK); + + cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + cc_gc_shader_pipe_config |= + R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK); + + backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes, + (R6XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable & + R6XX_MAX_BACKENDS_MASK) >> 16)), + (cc_rb_backend_disable >> 16)); + gb_tiling_config |= R600_BACKEND_MAP(backend_map); + + RADEON_WRITE(R600_GB_TILING_CONFIG, gb_tiling_config); + RADEON_WRITE(R600_DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + RADEON_WRITE(R600_HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + if (gb_tiling_config & 0xc0) { + dev_priv->r600_group_size = 512; + } else { + dev_priv->r600_group_size = 256; + } + dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7); + if (gb_tiling_config & 0x30) { + dev_priv->r600_nbanks = 8; + } else { + dev_priv->r600_nbanks = 4; + } + + RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + + num_qd_pipes = + R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8); + RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK); + RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK); + + /* set HW defaults for 3D engine */ + RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) | + R600_ROQ_IB2_START(0x2b))); + + RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, (R600_MEQ_END(0x40) | + R600_ROQ_END(0x40))); + + RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO | + R600_SYNC_GRADIENT | + R600_SYNC_WALKER | + R600_SYNC_ALIGNER)); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) + RADEON_WRITE(R600_ARB_GDEC_RD_CNTL, 0x00000021); + + sx_debug_1 = RADEON_READ(R600_SX_DEBUG_1); + sx_debug_1 |= R600_SMX_EVENT_RELEASE; + if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600)) + sx_debug_1 |= R600_ENABLE_NEW_SMX_ADDRESS; + RADEON_WRITE(R600_SX_DEBUG_1, sx_debug_1); + + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) + RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE); + else + RADEON_WRITE(R600_DB_DEBUG, 0); + + RADEON_WRITE(R600_DB_WATERMARKS, (R600_DEPTH_FREE(4) | + R600_DEPTH_FLUSH(16) | + R600_DEPTH_PENDING_FREE(4) | + R600_DEPTH_CACHELINE_FREE(16))); + RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); + RADEON_WRITE(R600_VGT_NUM_INSTANCES, 0); + + RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0)); + RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(0)); + + sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES); + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) { + sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) | + R600_FETCH_FIFO_HIWATER(0xa) | + R600_DONE_FIFO_HIWATER(0xe0) | + R600_ALU_UPDATE_FIFO_HIWATER(0x8)); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) { + sq_ms_fifo_sizes &= ~R600_DONE_FIFO_HIWATER(0xff); + sq_ms_fifo_sizes |= R600_DONE_FIFO_HIWATER(0x4); + } + RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes); + + /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT + * should be adjusted as needed by the 2D/3D drivers. This just sets default values + */ + sq_config = RADEON_READ(R600_SQ_CONFIG); + sq_config &= ~(R600_PS_PRIO(3) | + R600_VS_PRIO(3) | + R600_GS_PRIO(3) | + R600_ES_PRIO(3)); + sq_config |= (R600_DX9_CONSTS | + R600_VC_ENABLE | + R600_PS_PRIO(0) | + R600_VS_PRIO(1) | + R600_GS_PRIO(2) | + R600_ES_PRIO(3)); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) { + sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(124) | + R600_NUM_VS_GPRS(124) | + R600_NUM_CLAUSE_TEMP_GPRS(4)); + sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(0) | + R600_NUM_ES_GPRS(0)); + sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(136) | + R600_NUM_VS_THREADS(48) | + R600_NUM_GS_THREADS(4) | + R600_NUM_ES_THREADS(4)); + sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(128) | + R600_NUM_VS_STACK_ENTRIES(128)); + sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(0) | + R600_NUM_ES_STACK_ENTRIES(0)); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) { + /* no vertex cache */ + sq_config &= ~R600_VC_ENABLE; + + sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) | + R600_NUM_VS_GPRS(44) | + R600_NUM_CLAUSE_TEMP_GPRS(2)); + sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) | + R600_NUM_ES_GPRS(17)); + sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) | + R600_NUM_VS_THREADS(78) | + R600_NUM_GS_THREADS(4) | + R600_NUM_ES_THREADS(31)); + sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) | + R600_NUM_VS_STACK_ENTRIES(40)); + sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) | + R600_NUM_ES_STACK_ENTRIES(16)); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) { + sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) | + R600_NUM_VS_GPRS(44) | + R600_NUM_CLAUSE_TEMP_GPRS(2)); + sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(18) | + R600_NUM_ES_GPRS(18)); + sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) | + R600_NUM_VS_THREADS(78) | + R600_NUM_GS_THREADS(4) | + R600_NUM_ES_THREADS(31)); + sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) | + R600_NUM_VS_STACK_ENTRIES(40)); + sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) | + R600_NUM_ES_STACK_ENTRIES(16)); + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) { + sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) | + R600_NUM_VS_GPRS(44) | + R600_NUM_CLAUSE_TEMP_GPRS(2)); + sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) | + R600_NUM_ES_GPRS(17)); + sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) | + R600_NUM_VS_THREADS(78) | + R600_NUM_GS_THREADS(4) | + R600_NUM_ES_THREADS(31)); + sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(64) | + R600_NUM_VS_STACK_ENTRIES(64)); + sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(64) | + R600_NUM_ES_STACK_ENTRIES(64)); + } + + RADEON_WRITE(R600_SQ_CONFIG, sq_config); + RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1, sq_gpr_resource_mgmt_1); + RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2, sq_gpr_resource_mgmt_2); + RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); + RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1); + RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2); + + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) + RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY)); + else + RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC)); + + RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_2S, (R600_S0_X(0xc) | + R600_S0_Y(0x4) | + R600_S1_X(0x4) | + R600_S1_Y(0xc))); + RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_4S, (R600_S0_X(0xe) | + R600_S0_Y(0xe) | + R600_S1_X(0x2) | + R600_S1_Y(0x2) | + R600_S2_X(0xa) | + R600_S2_Y(0x6) | + R600_S3_X(0x6) | + R600_S3_Y(0xa))); + RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0, (R600_S0_X(0xe) | + R600_S0_Y(0xb) | + R600_S1_X(0x4) | + R600_S1_Y(0xc) | + R600_S2_X(0x1) | + R600_S2_Y(0x6) | + R600_S3_X(0xa) | + R600_S3_Y(0xe))); + RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1, (R600_S4_X(0x6) | + R600_S4_Y(0x1) | + R600_S5_X(0x0) | + R600_S5_Y(0x0) | + R600_S6_X(0xb) | + R600_S6_Y(0x4) | + R600_S7_X(0x7) | + R600_S7_Y(0x8))); + + + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_R600: + case CHIP_RV630: + case CHIP_RV635: + gs_prim_buffer_depth = 0; + break; + case CHIP_RV610: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV620: + gs_prim_buffer_depth = 32; + break; + case CHIP_RV670: + gs_prim_buffer_depth = 128; + break; + default: + break; + } + + num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16; + vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread; + /* Max value for this is 256 */ + if (vgt_gs_per_es > 256) + vgt_gs_per_es = 256; + + RADEON_WRITE(R600_VGT_ES_PER_GS, 128); + RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es); + RADEON_WRITE(R600_VGT_GS_PER_VS, 2); + RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16); + + /* more default values. 2D/3D driver should adjust as needed */ + RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0); + RADEON_WRITE(R600_VGT_STRMOUT_EN, 0); + RADEON_WRITE(R600_SX_MISC, 0); + RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0); + RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0); + RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0); + RADEON_WRITE(R600_SPI_INPUT_Z, 0); + RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2)); + RADEON_WRITE(R600_CB_COLOR7_FRAG, 0); + + /* clear render buffer base addresses */ + RADEON_WRITE(R600_CB_COLOR0_BASE, 0); + RADEON_WRITE(R600_CB_COLOR1_BASE, 0); + RADEON_WRITE(R600_CB_COLOR2_BASE, 0); + RADEON_WRITE(R600_CB_COLOR3_BASE, 0); + RADEON_WRITE(R600_CB_COLOR4_BASE, 0); + RADEON_WRITE(R600_CB_COLOR5_BASE, 0); + RADEON_WRITE(R600_CB_COLOR6_BASE, 0); + RADEON_WRITE(R600_CB_COLOR7_BASE, 0); + + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_RV610: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV620: + tc_cntl = R600_TC_L2_SIZE(8); + break; + case CHIP_RV630: + case CHIP_RV635: + tc_cntl = R600_TC_L2_SIZE(4); + break; + case CHIP_R600: + tc_cntl = R600_TC_L2_SIZE(0) | R600_L2_DISABLE_LATE_HIT; + break; + default: + tc_cntl = R600_TC_L2_SIZE(0); + break; + } + + RADEON_WRITE(R600_TC_CNTL, tc_cntl); + + hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL); + RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + arb_pop = RADEON_READ(R600_ARB_POP); + arb_pop |= R600_ENABLE_TC128; + RADEON_WRITE(R600_ARB_POP, arb_pop); + + RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); + RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA | + R600_NUM_CLIP_SEQ(3))); + RADEON_WRITE(R600_PA_SC_ENHANCE, R600_FORCE_EOV_MAX_CLK_CNT(4095)); + +} + +static u32 r700_get_tile_pipe_to_backend_map(drm_radeon_private_t *dev_priv, + u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask; + u32 enabled_backends_count; + u32 cur_pipe; + u32 swizzle_pipe[R7XX_MAX_PIPES]; + u32 cur_backend; + u32 i; + bool force_no_swizzle; + + if (num_tile_pipes > R7XX_MAX_PIPES) + num_tile_pipes = R7XX_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > R7XX_MAX_BACKENDS) + num_backends = R7XX_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + for (i = 0; i < R7XX_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_RV770: + case CHIP_RV730: + force_no_swizzle = false; + break; + case CHIP_RV710: + case CHIP_RV740: + default: + force_no_swizzle = true; + break; + } + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES); + switch (num_tile_pipes) { + case 1: + swizzle_pipe[0] = 0; + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 3: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + } + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 3; + swizzle_pipe[3] = 1; + } + break; + case 5: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 5; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + } + break; + case 7: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + swizzle_pipe[6] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + swizzle_pipe[6] = 7; + swizzle_pipe[7] = 5; + } + break; + } + + cur_backend = 0; + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; + + backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); + + cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; + } + + return backend_map; +} + +static void r700_gfx_init(struct drm_device *dev, + drm_radeon_private_t *dev_priv) +{ + int i, j, num_qd_pipes; + u32 ta_aux_cntl; + u32 sx_debug_1; + u32 smx_dc_ctl0; + u32 db_debug3; + u32 num_gs_verts_per_thread; + u32 vgt_gs_per_es; + u32 gs_prim_buffer_depth = 0; + u32 sq_ms_fifo_sizes; + u32 sq_config; + u32 sq_thread_resource_mgmt; + u32 hdp_host_path_cntl; + u32 sq_dyn_gpr_size_simd_ab_0; + u32 backend_map; + u32 gb_tiling_config = 0; + u32 cc_rb_backend_disable; + u32 cc_gc_shader_pipe_config; + u32 mc_arb_ramcfg; + u32 db_debug4; + + /* setup chip specs */ + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_RV770: + dev_priv->r600_max_pipes = 4; + dev_priv->r600_max_tile_pipes = 8; + dev_priv->r600_max_simds = 10; + dev_priv->r600_max_backends = 4; + dev_priv->r600_max_gprs = 256; + dev_priv->r600_max_threads = 248; + dev_priv->r600_max_stack_entries = 512; + dev_priv->r600_max_hw_contexts = 8; + dev_priv->r600_max_gs_threads = 16 * 2; + dev_priv->r600_sx_max_export_size = 128; + dev_priv->r600_sx_max_export_pos_size = 16; + dev_priv->r600_sx_max_export_smx_size = 112; + dev_priv->r600_sq_num_cf_insts = 2; + + dev_priv->r700_sx_num_of_sets = 7; + dev_priv->r700_sc_prim_fifo_size = 0xF9; + dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; + dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; + break; + case CHIP_RV730: + dev_priv->r600_max_pipes = 2; + dev_priv->r600_max_tile_pipes = 4; + dev_priv->r600_max_simds = 8; + dev_priv->r600_max_backends = 2; + dev_priv->r600_max_gprs = 128; + dev_priv->r600_max_threads = 248; + dev_priv->r600_max_stack_entries = 256; + dev_priv->r600_max_hw_contexts = 8; + dev_priv->r600_max_gs_threads = 16 * 2; + dev_priv->r600_sx_max_export_size = 256; + dev_priv->r600_sx_max_export_pos_size = 32; + dev_priv->r600_sx_max_export_smx_size = 224; + dev_priv->r600_sq_num_cf_insts = 2; + + dev_priv->r700_sx_num_of_sets = 7; + dev_priv->r700_sc_prim_fifo_size = 0xf9; + dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; + dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; + if (dev_priv->r600_sx_max_export_pos_size > 16) { + dev_priv->r600_sx_max_export_pos_size -= 16; + dev_priv->r600_sx_max_export_smx_size += 16; + } + break; + case CHIP_RV710: + dev_priv->r600_max_pipes = 2; + dev_priv->r600_max_tile_pipes = 2; + dev_priv->r600_max_simds = 2; + dev_priv->r600_max_backends = 1; + dev_priv->r600_max_gprs = 256; + dev_priv->r600_max_threads = 192; + dev_priv->r600_max_stack_entries = 256; + dev_priv->r600_max_hw_contexts = 4; + dev_priv->r600_max_gs_threads = 8 * 2; + dev_priv->r600_sx_max_export_size = 128; + dev_priv->r600_sx_max_export_pos_size = 16; + dev_priv->r600_sx_max_export_smx_size = 112; + dev_priv->r600_sq_num_cf_insts = 1; + + dev_priv->r700_sx_num_of_sets = 7; + dev_priv->r700_sc_prim_fifo_size = 0x40; + dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; + dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; + break; + case CHIP_RV740: + dev_priv->r600_max_pipes = 4; + dev_priv->r600_max_tile_pipes = 4; + dev_priv->r600_max_simds = 8; + dev_priv->r600_max_backends = 4; + dev_priv->r600_max_gprs = 256; + dev_priv->r600_max_threads = 248; + dev_priv->r600_max_stack_entries = 512; + dev_priv->r600_max_hw_contexts = 8; + dev_priv->r600_max_gs_threads = 16 * 2; + dev_priv->r600_sx_max_export_size = 256; + dev_priv->r600_sx_max_export_pos_size = 32; + dev_priv->r600_sx_max_export_smx_size = 224; + dev_priv->r600_sq_num_cf_insts = 2; + + dev_priv->r700_sx_num_of_sets = 7; + dev_priv->r700_sc_prim_fifo_size = 0x100; + dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; + dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; + + if (dev_priv->r600_sx_max_export_pos_size > 16) { + dev_priv->r600_sx_max_export_pos_size -= 16; + dev_priv->r600_sx_max_export_smx_size += 16; + } + break; + default: + break; + } + + /* Initialize HDP */ + j = 0; + for (i = 0; i < 32; i++) { + RADEON_WRITE((0x2c14 + j), 0x00000000); + RADEON_WRITE((0x2c18 + j), 0x00000000); + RADEON_WRITE((0x2c1c + j), 0x00000000); + RADEON_WRITE((0x2c20 + j), 0x00000000); + RADEON_WRITE((0x2c24 + j), 0x00000000); + j += 0x18; + } + + RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff)); + + /* setup tiling, simd, pipe config */ + mc_arb_ramcfg = RADEON_READ(R700_MC_ARB_RAMCFG); + + switch (dev_priv->r600_max_tile_pipes) { + case 1: + gb_tiling_config |= R600_PIPE_TILING(0); + break; + case 2: + gb_tiling_config |= R600_PIPE_TILING(1); + break; + case 4: + gb_tiling_config |= R600_PIPE_TILING(2); + break; + case 8: + gb_tiling_config |= R600_PIPE_TILING(3); + break; + default: + break; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770) + gb_tiling_config |= R600_BANK_TILING(1); + else + gb_tiling_config |= R600_BANK_TILING((mc_arb_ramcfg >> R700_NOOFBANK_SHIFT) & R700_NOOFBANK_MASK); + + gb_tiling_config |= R600_GROUP_SIZE(0); + + if (((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK) > 3) { + gb_tiling_config |= R600_ROW_TILING(3); + gb_tiling_config |= R600_SAMPLE_SPLIT(3); + } else { + gb_tiling_config |= + R600_ROW_TILING(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK)); + gb_tiling_config |= + R600_SAMPLE_SPLIT(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK)); + } + + gb_tiling_config |= R600_BANK_SWAPS(1); + + cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000; + cc_rb_backend_disable |= + R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK); + + cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + cc_gc_shader_pipe_config |= + R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740) + backend_map = 0x28; + else + backend_map = r700_get_tile_pipe_to_backend_map(dev_priv, + dev_priv->r600_max_tile_pipes, + (R7XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable & + R7XX_MAX_BACKENDS_MASK) >> 16)), + (cc_rb_backend_disable >> 16)); + gb_tiling_config |= R600_BACKEND_MAP(backend_map); + + RADEON_WRITE(R600_GB_TILING_CONFIG, gb_tiling_config); + RADEON_WRITE(R600_DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + RADEON_WRITE(R600_HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + if (gb_tiling_config & 0xc0) { + dev_priv->r600_group_size = 512; + } else { + dev_priv->r600_group_size = 256; + } + dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7); + if (gb_tiling_config & 0x30) { + dev_priv->r600_nbanks = 8; + } else { + dev_priv->r600_nbanks = 4; + } + + RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + + RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0); + RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0); + RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0); + RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0); + + num_qd_pipes = + R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8); + RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK); + RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK); + + /* set HW defaults for 3D engine */ + RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) | + R600_ROQ_IB2_START(0x2b))); + + RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30)); + + ta_aux_cntl = RADEON_READ(R600_TA_CNTL_AUX); + RADEON_WRITE(R600_TA_CNTL_AUX, ta_aux_cntl | R600_DISABLE_CUBE_ANISO); + + sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1); + sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS; + RADEON_WRITE(R700_SX_DEBUG_1, sx_debug_1); + + smx_dc_ctl0 = RADEON_READ(R600_SMX_DC_CTL0); + smx_dc_ctl0 &= ~R700_CACHE_DEPTH(0x1ff); + smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1); + RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV740) + RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) | + R700_GS_FLUSH_CTL(4) | + R700_ACK_FLUSH_CTL(3) | + R700_SYNC_FLUSH_CTL)); + + db_debug3 = RADEON_READ(R700_DB_DEBUG3); + db_debug3 &= ~R700_DB_CLK_OFF_DELAY(0x1f); + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_RV770: + case CHIP_RV740: + db_debug3 |= R700_DB_CLK_OFF_DELAY(0x1f); + break; + case CHIP_RV710: + case CHIP_RV730: + default: + db_debug3 |= R700_DB_CLK_OFF_DELAY(2); + break; + } + RADEON_WRITE(R700_DB_DEBUG3, db_debug3); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV770) { + db_debug4 = RADEON_READ(RV700_DB_DEBUG4); + db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER; + RADEON_WRITE(RV700_DB_DEBUG4, db_debug4); + } + + RADEON_WRITE(R600_SX_EXPORT_BUFFER_SIZES, (R600_COLOR_BUFFER_SIZE((dev_priv->r600_sx_max_export_size / 4) - 1) | + R600_POSITION_BUFFER_SIZE((dev_priv->r600_sx_max_export_pos_size / 4) - 1) | + R600_SMX_BUFFER_SIZE((dev_priv->r600_sx_max_export_smx_size / 4) - 1))); + + RADEON_WRITE(R700_PA_SC_FIFO_SIZE_R7XX, (R700_SC_PRIM_FIFO_SIZE(dev_priv->r700_sc_prim_fifo_size) | + R700_SC_HIZ_TILE_FIFO_SIZE(dev_priv->r700_sc_hiz_tile_fifo_size) | + R700_SC_EARLYZ_TILE_FIFO_SIZE(dev_priv->r700_sc_earlyz_tile_fifo_fize))); + + RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); + + RADEON_WRITE(R600_VGT_NUM_INSTANCES, 1); + + RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0)); + + RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(4)); + + RADEON_WRITE(R600_CP_PERFMON_CNTL, 0); + + sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(16 * dev_priv->r600_sq_num_cf_insts) | + R600_DONE_FIFO_HIWATER(0xe0) | + R600_ALU_UPDATE_FIFO_HIWATER(0x8)); + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1); + break; + case CHIP_RV740: + default: + sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4); + break; + } + RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes); + + /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT + * should be adjusted as needed by the 2D/3D drivers. This just sets default values + */ + sq_config = RADEON_READ(R600_SQ_CONFIG); + sq_config &= ~(R600_PS_PRIO(3) | + R600_VS_PRIO(3) | + R600_GS_PRIO(3) | + R600_ES_PRIO(3)); + sq_config |= (R600_DX9_CONSTS | + R600_VC_ENABLE | + R600_EXPORT_SRC_C | + R600_PS_PRIO(0) | + R600_VS_PRIO(1) | + R600_GS_PRIO(2) | + R600_ES_PRIO(3)); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710) + /* no vertex cache */ + sq_config &= ~R600_VC_ENABLE; + + RADEON_WRITE(R600_SQ_CONFIG, sq_config); + + RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1, (R600_NUM_PS_GPRS((dev_priv->r600_max_gprs * 24)/64) | + R600_NUM_VS_GPRS((dev_priv->r600_max_gprs * 24)/64) | + R600_NUM_CLAUSE_TEMP_GPRS(((dev_priv->r600_max_gprs * 24)/64)/2))); + + RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2, (R600_NUM_GS_GPRS((dev_priv->r600_max_gprs * 7)/64) | + R600_NUM_ES_GPRS((dev_priv->r600_max_gprs * 7)/64))); + + sq_thread_resource_mgmt = (R600_NUM_PS_THREADS((dev_priv->r600_max_threads * 4)/8) | + R600_NUM_VS_THREADS((dev_priv->r600_max_threads * 2)/8) | + R600_NUM_ES_THREADS((dev_priv->r600_max_threads * 1)/8)); + if (((dev_priv->r600_max_threads * 1) / 8) > dev_priv->r600_max_gs_threads) + sq_thread_resource_mgmt |= R600_NUM_GS_THREADS(dev_priv->r600_max_gs_threads); + else + sq_thread_resource_mgmt |= R600_NUM_GS_THREADS((dev_priv->r600_max_gs_threads * 1)/8); + RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); + + RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, (R600_NUM_PS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) | + R600_NUM_VS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4))); + + RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, (R600_NUM_GS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) | + R600_NUM_ES_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4))); + + sq_dyn_gpr_size_simd_ab_0 = (R700_SIMDA_RING0((dev_priv->r600_max_gprs * 38)/64) | + R700_SIMDA_RING1((dev_priv->r600_max_gprs * 38)/64) | + R700_SIMDB_RING0((dev_priv->r600_max_gprs * 38)/64) | + R700_SIMDB_RING1((dev_priv->r600_max_gprs * 38)/64)); + + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0); + RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0); + + RADEON_WRITE(R700_PA_SC_FORCE_EOV_MAX_CNTS, (R700_FORCE_EOV_MAX_CLK_CNT(4095) | + R700_FORCE_EOV_MAX_REZ_CNT(255))); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710) + RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_TC_ONLY) | + R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO))); + else + RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_VC_AND_TC) | + R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO))); + + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV740: + gs_prim_buffer_depth = 384; + break; + case CHIP_RV710: + gs_prim_buffer_depth = 128; + break; + default: + break; + } + + num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16; + vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread; + /* Max value for this is 256 */ + if (vgt_gs_per_es > 256) + vgt_gs_per_es = 256; + + RADEON_WRITE(R600_VGT_ES_PER_GS, 128); + RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es); + RADEON_WRITE(R600_VGT_GS_PER_VS, 2); + + /* more default values. 2D/3D driver should adjust as needed */ + RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16); + RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0); + RADEON_WRITE(R600_VGT_STRMOUT_EN, 0); + RADEON_WRITE(R600_SX_MISC, 0); + RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0); + RADEON_WRITE(R700_PA_SC_EDGERULE, 0xaaaaaaaa); + RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0); + RADEON_WRITE(R600_PA_SC_CLIPRECT_RULE, 0xffff); + RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0); + RADEON_WRITE(R600_SPI_INPUT_Z, 0); + RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2)); + RADEON_WRITE(R600_CB_COLOR7_FRAG, 0); + + /* clear render buffer base addresses */ + RADEON_WRITE(R600_CB_COLOR0_BASE, 0); + RADEON_WRITE(R600_CB_COLOR1_BASE, 0); + RADEON_WRITE(R600_CB_COLOR2_BASE, 0); + RADEON_WRITE(R600_CB_COLOR3_BASE, 0); + RADEON_WRITE(R600_CB_COLOR4_BASE, 0); + RADEON_WRITE(R600_CB_COLOR5_BASE, 0); + RADEON_WRITE(R600_CB_COLOR6_BASE, 0); + RADEON_WRITE(R600_CB_COLOR7_BASE, 0); + + RADEON_WRITE(R700_TCP_CNTL, 0); + + hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL); + RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); + + RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA | + R600_NUM_CLIP_SEQ(3))); + +} + +static void r600_cp_init_ring_buffer(struct drm_device *dev, + drm_radeon_private_t *dev_priv, + struct drm_file *file_priv) +{ + struct drm_radeon_master_private *master_priv; + u32 ring_start; + u64 rptr_addr; + + if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) + r700_gfx_init(dev, dev_priv); + else + r600_gfx_init(dev, dev_priv); + + RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); + RADEON_READ(R600_GRBM_SOFT_RESET); + DRM_MDELAY(15); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + + + /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE(R600_CP_RB_CNTL, + R600_BUF_SWAP_32BIT | + R600_RB_NO_UPDATE | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#else + RADEON_WRITE(R600_CP_RB_CNTL, + RADEON_RB_NO_UPDATE | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#endif + + RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x0); + + /* Set the write pointer delay */ + RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0); + +#ifdef __BIG_ENDIAN + RADEON_WRITE(R600_CP_RB_CNTL, + R600_BUF_SWAP_32BIT | + R600_RB_NO_UPDATE | + R600_RB_RPTR_WR_ENA | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#else + RADEON_WRITE(R600_CP_RB_CNTL, + R600_RB_NO_UPDATE | + R600_RB_RPTR_WR_ENA | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#endif + + /* Initialize the ring buffer's read and write pointers */ + RADEON_WRITE(R600_CP_RB_RPTR_WR, 0); + RADEON_WRITE(R600_CP_RB_WPTR, 0); + SET_RING_HEAD(dev_priv, 0); + dev_priv->ring.tail = 0; + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + rptr_addr = dev_priv->ring_rptr->offset + - dev->agp->base + + dev_priv->gart_vm_start; + } else +#endif + { + rptr_addr = dev_priv->ring_rptr->offset + - ((unsigned long) dev->sg->vaddr) + + dev_priv->gart_vm_start; + } + RADEON_WRITE(R600_CP_RB_RPTR_ADDR, (rptr_addr & 0xfffffffc)); + RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, upper_32_bits(rptr_addr)); + +#ifdef __BIG_ENDIAN + RADEON_WRITE(R600_CP_RB_CNTL, + RADEON_BUF_SWAP_32BIT | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#else + RADEON_WRITE(R600_CP_RB_CNTL, + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#endif + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + /* XXX */ + radeon_write_agp_base(dev_priv, dev->agp->base); + + /* XXX */ + radeon_write_agp_location(dev_priv, + (((dev_priv->gart_vm_start - 1 + + dev_priv->gart_size) & 0xffff0000) | + (dev_priv->gart_vm_start >> 16))); + + ring_start = (dev_priv->cp_ring->offset + - dev->agp->base + + dev_priv->gart_vm_start); + } else +#endif + ring_start = (dev_priv->cp_ring->offset + - (unsigned long)dev->sg->vaddr> + + dev_priv->gart_vm_start); + + RADEON_WRITE(R600_CP_RB_BASE, ring_start >> 8); + + RADEON_WRITE(R600_CP_ME_CNTL, 0xff); + + RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28)); + + /* Initialize the scratch register pointer. This will cause + * the scratch register values to be written out to memory + * whenever they are updated. + * + * We simply put this behind the ring read pointer, this works + * with PCI GART as well as (whatever kind of) AGP GART + */ + { + u64 scratch_addr; + + scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR) & 0xFFFFFFFC; + scratch_addr |= ((u64)RADEON_READ(R600_CP_RB_RPTR_ADDR_HI)) << 32; + scratch_addr += R600_SCRATCH_REG_OFFSET; + scratch_addr >>= 8; + scratch_addr &= 0xffffffff; + + RADEON_WRITE(R600_SCRATCH_ADDR, (uint32_t)scratch_addr); + } + + RADEON_WRITE(R600_SCRATCH_UMSK, 0x7); + + /* Turn on bus mastering */ + radeon_enable_bm(dev_priv); + + radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(0), 0); + RADEON_WRITE(R600_LAST_FRAME_REG, 0); + + radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0); + RADEON_WRITE(R600_LAST_DISPATCH_REG, 0); + + radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(2), 0); + RADEON_WRITE(R600_LAST_CLEAR_REG, 0); + + /* reset sarea copies of these */ + master_priv = file_priv->masterp->driver_priv; + if (master_priv->sarea_priv) { + master_priv->sarea_priv->last_frame = 0; + master_priv->sarea_priv->last_dispatch = 0; + master_priv->sarea_priv->last_clear = 0; + } + + r600_do_wait_for_idle(dev_priv); + +} + +int r600_do_cleanup_cp(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + /* Make sure interrupts are disabled here because the uninstall ioctl + * may not have been called from userspace and after dev_private + * is freed, it's too late. + */ + if (dev->irq_enabled) + drm_irq_uninstall(dev); + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + if (dev_priv->cp_ring != NULL) { + drm_core_ioremapfree(dev_priv->cp_ring, dev); + dev_priv->cp_ring = NULL; + } + if (dev_priv->ring_rptr != NULL) { + drm_core_ioremapfree(dev_priv->ring_rptr, dev); + dev_priv->ring_rptr = NULL; + } + if (dev->agp_buffer_map != NULL) { + drm_core_ioremapfree(dev->agp_buffer_map, dev); + dev->agp_buffer_map = NULL; + } + } else +#endif + { + + if (dev_priv->gart_info.bus_addr) + r600_page_table_cleanup(dev, &dev_priv->gart_info); + + if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) { + drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); + dev_priv->gart_info.addr = NULL; + } + } + /* only clear to the start of flags */ + memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); + + return 0; +} + +int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, + struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + + DRM_DEBUG("\n"); + + sx_init(&dev_priv->cs_mutex, "drm__radeon_private__cs_mutex"); + r600_cs_legacy_init(); + /* if we require new memory map but we don't have it fail */ + if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { + DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { + DRM_DEBUG("Forcing AGP card to PCI mode\n"); + dev_priv->flags &= ~RADEON_IS_AGP; + /* The writeback test succeeds, but when writeback is enabled, + * the ring buffer read ptr update fails after first 128 bytes. + */ + radeon_no_wb = 1; + } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) + && !init->is_pci) { + DRM_DEBUG("Restoring AGP flag\n"); + dev_priv->flags |= RADEON_IS_AGP; + } + + dev_priv->usec_timeout = init->usec_timeout; + if (dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { + DRM_DEBUG("TIMEOUT problem!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + /* Enable vblank on CRTC1 for older X servers + */ + dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; + dev_priv->do_boxes = 0; + dev_priv->cp_mode = init->cp_mode; + + /* We don't support anything other than bus-mastering ring mode, + * but the ring can be in either AGP or PCI space for the ring + * read pointer. + */ + if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && + (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { + DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + switch (init->fb_bpp) { + case 16: + dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; + break; + case 32: + default: + dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; + break; + } + dev_priv->front_offset = init->front_offset; + dev_priv->front_pitch = init->front_pitch; + dev_priv->back_offset = init->back_offset; + dev_priv->back_pitch = init->back_pitch; + + dev_priv->ring_offset = init->ring_offset; + dev_priv->ring_rptr_offset = init->ring_rptr_offset; + dev_priv->buffers_offset = init->buffers_offset; + dev_priv->gart_textures_offset = init->gart_textures_offset; + + master_priv->sarea = drm_getsarea(dev); + if (!master_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); + if (!dev_priv->cp_ring) { + DRM_ERROR("could not find cp ring region!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); + if (!dev_priv->ring_rptr) { + DRM_ERROR("could not find ring read pointer!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + dev->agp_buffer_token = init->buffers_offset; + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if (!dev->agp_buffer_map) { + DRM_ERROR("could not find dma buffer region!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + if (init->gart_textures_offset) { + dev_priv->gart_textures = + drm_core_findmap(dev, init->gart_textures_offset); + if (!dev_priv->gart_textures) { + DRM_ERROR("could not find GART texture region!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + } + +#if __OS_HAS_AGP + /* XXX */ + if (dev_priv->flags & RADEON_IS_AGP) { + drm_core_ioremap_wc(dev_priv->cp_ring, dev); + drm_core_ioremap_wc(dev_priv->ring_rptr, dev); + drm_core_ioremap_wc(dev->agp_buffer_map, dev); + if (!dev_priv->cp_ring->handle || + !dev_priv->ring_rptr->handle || + !dev->agp_buffer_map->handle) { + DRM_ERROR("could not find ioremap agp regions!\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + } else +#endif + { + dev_priv->cp_ring->handle = (void *)(unsigned long)dev_priv->cp_ring->offset; + dev_priv->ring_rptr->handle = + (void *)(unsigned long)dev_priv->ring_rptr->offset; + dev->agp_buffer_map->handle = + (void *)(unsigned long)dev->agp_buffer_map->offset; + + DRM_DEBUG("dev_priv->cp_ring->handle %p\n", + dev_priv->cp_ring->handle); + DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", + dev_priv->ring_rptr->handle); + DRM_DEBUG("dev->agp_buffer_map->handle %p\n", + dev->agp_buffer_map->handle); + } + + dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 24; + dev_priv->fb_size = + (((radeon_read_fb_location(dev_priv) & 0xffff0000u) << 8) + 0x1000000) + - dev_priv->fb_location; + + dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | + ((dev_priv->front_offset + + dev_priv->fb_location) >> 10)); + + dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | + ((dev_priv->back_offset + + dev_priv->fb_location) >> 10)); + + dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | + ((dev_priv->depth_offset + + dev_priv->fb_location) >> 10)); + + dev_priv->gart_size = init->gart_size; + + /* New let's set the memory map ... */ + if (dev_priv->new_memmap) { + u32 base = 0; + + DRM_INFO("Setting GART location based on new memory map\n"); + + /* If using AGP, try to locate the AGP aperture at the same + * location in the card and on the bus, though we have to + * align it down. + */ +#if __OS_HAS_AGP + /* XXX */ + if (dev_priv->flags & RADEON_IS_AGP) { + base = dev->agp->base; + /* Check if valid */ + if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { + DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", + dev->agp->base); + base = 0; + } + } +#endif + /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ + if (base == 0) { + base = dev_priv->fb_location + dev_priv->fb_size; + if (base < dev_priv->fb_location || + ((base + dev_priv->gart_size) & 0xfffffffful) < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + dev_priv->gart_vm_start = base & 0xffc00000u; + if (dev_priv->gart_vm_start != base) + DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", + base, dev_priv->gart_vm_start); + } + +#if __OS_HAS_AGP + /* XXX */ + if (dev_priv->flags & RADEON_IS_AGP) + dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset + - dev->agp->base + + dev_priv->gart_vm_start); + else +#endif + dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset + - (unsigned long)dev->sg->vaddr + + dev_priv->gart_vm_start); + + DRM_DEBUG("fb 0x%08x size %d\n", + (unsigned int) dev_priv->fb_location, + (unsigned int) dev_priv->fb_size); + DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); + DRM_DEBUG("dev_priv->gart_vm_start 0x%08x\n", + (unsigned int) dev_priv->gart_vm_start); + DRM_DEBUG("dev_priv->gart_buffers_offset 0x%08lx\n", + dev_priv->gart_buffers_offset); + + dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; + dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle + + init->ring_size / sizeof(u32)); + dev_priv->ring.size = init->ring_size; + dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); + + dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; + dev_priv->ring.rptr_update_l2qw = drm_order(/* init->rptr_update */ 4096 / 8); + + dev_priv->ring.fetch_size = /* init->fetch_size */ 32; + dev_priv->ring.fetch_size_l2ow = drm_order(/* init->fetch_size */ 32 / 16); + + dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; + + dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + /* XXX turn off pcie gart */ + } else +#endif + { + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); + /* if we have an offset set from userspace */ + if (!dev_priv->pcigart_offset_set) { + DRM_ERROR("Need gart offset from userspace\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + DRM_DEBUG("Using gart offset 0x%08lx\n", dev_priv->pcigart_offset); + + dev_priv->gart_info.bus_addr = + dev_priv->pcigart_offset + dev_priv->fb_location; + dev_priv->gart_info.mapping.offset = + dev_priv->pcigart_offset + dev_priv->fb_aper_offset; + dev_priv->gart_info.mapping.size = + dev_priv->gart_info.table_size; + + drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev); + if (!dev_priv->gart_info.mapping.handle) { + DRM_ERROR("ioremap failed.\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + dev_priv->gart_info.addr = + dev_priv->gart_info.mapping.handle; + + DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", + dev_priv->gart_info.addr, + dev_priv->pcigart_offset); + + if (!r600_page_table_init(dev)) { + DRM_ERROR("Failed to init GART table\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } + + if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) + r700_vm_init(dev); + else + r600_vm_init(dev); + } + + if (!dev_priv->me_fw || !dev_priv->pfp_fw) { + int err = r600_cp_init_microcode(dev_priv); + if (err) { + DRM_ERROR("Failed to load firmware!\n"); + r600_do_cleanup_cp(dev); + return err; + } + } + if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) + r700_cp_load_microcode(dev_priv); + else + r600_cp_load_microcode(dev_priv); + + r600_cp_init_ring_buffer(dev, dev_priv, file_priv); + + dev_priv->last_buf = 0; + + r600_do_engine_reset(dev); + r600_test_writeback(dev_priv); + + return 0; +} + +int r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) { + r700_vm_init(dev); + r700_cp_load_microcode(dev_priv); + } else { + r600_vm_init(dev); + r600_cp_load_microcode(dev_priv); + } + r600_cp_init_ring_buffer(dev, dev_priv, file_priv); + r600_do_engine_reset(dev); + + return 0; +} + +/* Wait for the CP to go idle. + */ +int r600_do_cp_idle(drm_radeon_private_t *dev_priv) +{ + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(5); + OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0)); + OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT); + /* wait for 3D idle clean */ + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); + OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2); + OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN); + + ADVANCE_RING(); + COMMIT_RING(); + + return r600_do_wait_for_idle(dev_priv); +} + +/* Start the Command Processor. + */ +void r600_do_cp_start(drm_radeon_private_t *dev_priv) +{ + u32 cp_me; + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(7); + OUT_RING(CP_PACKET3(R600_IT_ME_INITIALIZE, 5)); + OUT_RING(0x00000001); + if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) + OUT_RING(0x00000003); + else + OUT_RING(0x00000000); + OUT_RING((dev_priv->r600_max_hw_contexts - 1)); + OUT_RING(R600_ME_INITIALIZE_DEVICE_ID(1)); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + ADVANCE_RING(); + COMMIT_RING(); + + /* set the mux and reset the halt bit */ + cp_me = 0xff; + RADEON_WRITE(R600_CP_ME_CNTL, cp_me); + + dev_priv->cp_running = 1; + +} + +void r600_do_cp_reset(drm_radeon_private_t *dev_priv) +{ + u32 cur_read_ptr; + DRM_DEBUG("\n"); + + cur_read_ptr = RADEON_READ(R600_CP_RB_RPTR); + RADEON_WRITE(R600_CP_RB_WPTR, cur_read_ptr); + SET_RING_HEAD(dev_priv, cur_read_ptr); + dev_priv->ring.tail = cur_read_ptr; +} + +void r600_do_cp_stop(drm_radeon_private_t *dev_priv) +{ + uint32_t cp_me; + + DRM_DEBUG("\n"); + + cp_me = 0xff | R600_CP_ME_HALT; + + RADEON_WRITE(R600_CP_ME_CNTL, cp_me); + + dev_priv->cp_running = 0; +} + +int r600_cp_dispatch_indirect(struct drm_device *dev, + struct drm_buf *buf, int start, int end) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + if (start != end) { + unsigned long offset = (dev_priv->gart_buffers_offset + + buf->offset + start); + int dwords = (end - start + 3) / sizeof(u32); + + DRM_DEBUG("dwords:%d\n", dwords); + DRM_DEBUG("offset 0x%lx\n", offset); + + + /* Indirect buffer data must be a multiple of 16 dwords. + * pad the data with a Type-2 CP packet. + */ + while (dwords & 0xf) { + u32 *data = (u32 *) + ((char *)dev->agp_buffer_map->handle + + buf->offset + start); + data[dwords++] = RADEON_CP_PACKET2; + } + + /* Fire off the indirect buffer */ + BEGIN_RING(4); + OUT_RING(CP_PACKET3(R600_IT_INDIRECT_BUFFER, 2)); + OUT_RING((offset & 0xfffffffc)); + OUT_RING((upper_32_bits(offset) & 0xff)); + OUT_RING(dwords); + ADVANCE_RING(); + } + + return 0; +} + +void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_master *master = file_priv->masterp; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + int nbox = sarea_priv->nbox; + struct drm_clip_rect *pbox = sarea_priv->boxes; + int i, cpp, src_pitch, dst_pitch; + uint64_t src, dst; + RING_LOCALS; + DRM_DEBUG("\n"); + + if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888) + cpp = 4; + else + cpp = 2; + + if (sarea_priv->pfCurrentPage == 0) { + src_pitch = dev_priv->back_pitch; + dst_pitch = dev_priv->front_pitch; + src = dev_priv->back_offset + dev_priv->fb_location; + dst = dev_priv->front_offset + dev_priv->fb_location; + } else { + src_pitch = dev_priv->front_pitch; + dst_pitch = dev_priv->back_pitch; + src = dev_priv->front_offset + dev_priv->fb_location; + dst = dev_priv->back_offset + dev_priv->fb_location; + } + + if (r600_prepare_blit_copy(dev, file_priv)) { + DRM_ERROR("unable to allocate vertex buffer for swap buffer\n"); + return; + } + for (i = 0; i < nbox; i++) { + int x = pbox[i].x1; + int y = pbox[i].y1; + int w = pbox[i].x2 - x; + int h = pbox[i].y2 - y; + + DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); + + r600_blit_swap(dev, + src, dst, + x, y, x, y, w, h, + src_pitch, dst_pitch, cpp); + } + r600_done_blit_copy(dev); + + /* Increment the frame counter. The client-side 3D driver must + * throttle the framerate by waiting for this value before + * performing the swapbuffer ioctl. + */ + sarea_priv->last_frame++; + + BEGIN_RING(3); + R600_FRAME_AGE(sarea_priv->last_frame); + ADVANCE_RING(); +} + +int r600_cp_dispatch_texture(struct drm_device *dev, + struct drm_file *file_priv, + drm_radeon_texture_t *tex, + drm_radeon_tex_image_t *image) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_buf *buf; + u32 *buffer; + const u8 __user *data; + int size, pass_size; + u64 src_offset, dst_offset; + + if (!radeon_check_offset(dev_priv, tex->offset)) { + DRM_ERROR("Invalid destination offset\n"); + return -EINVAL; + } + + /* this might fail for zero-sized uploads - are those illegal? */ + if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) { + DRM_ERROR("Invalid final destination offset\n"); + return -EINVAL; + } + + size = tex->height * tex->pitch; + + if (size == 0) + return 0; + + dst_offset = tex->offset; + + if (r600_prepare_blit_copy(dev, file_priv)) { + DRM_ERROR("unable to allocate vertex buffer for swap buffer\n"); + return -EAGAIN; + } + do { + data = (const u8 __user *)image->data; + pass_size = size; + + buf = radeon_freelist_get(dev); + if (!buf) { + DRM_DEBUG("EAGAIN\n"); + if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) + return -EFAULT; + return -EAGAIN; + } + + if (pass_size > buf->total) + pass_size = buf->total; + + /* Dispatch the indirect buffer. + */ + buffer = + (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); + + if (DRM_COPY_FROM_USER(buffer, data, pass_size)) { + DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size); + return -EFAULT; + } + + buf->file_priv = file_priv; + buf->used = pass_size; + src_offset = dev_priv->gart_buffers_offset + buf->offset; + + r600_blit_copy(dev, src_offset, dst_offset, pass_size); + + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + + /* Update the input parameters for next time */ + image->data = (const u8 __user *)image->data + pass_size; + dst_offset += pass_size; + size -= pass_size; + } while (size > 0); + r600_done_blit_copy(dev); + + return 0; +} + +/* + * Legacy cs ioctl + */ +static u32 radeon_cs_id_get(struct drm_radeon_private *radeon) +{ + /* FIXME: check if wrap affect last reported wrap & sequence */ + radeon->cs_id_scnt = (radeon->cs_id_scnt + 1) & 0x00FFFFFF; + if (!radeon->cs_id_scnt) { + /* increment wrap counter */ + radeon->cs_id_wcnt += 0x01000000; + /* valid sequence counter start at 1 */ + radeon->cs_id_scnt = 1; + } + return (radeon->cs_id_scnt | radeon->cs_id_wcnt); +} + +static void r600_cs_id_emit(drm_radeon_private_t *dev_priv, u32 *id) +{ + RING_LOCALS; + + *id = radeon_cs_id_get(dev_priv); + + /* SCRATCH 2 */ + BEGIN_RING(3); + R600_CLEAR_AGE(*id); + ADVANCE_RING(); + COMMIT_RING(); +} + +static int r600_ib_get(struct drm_device *dev, + struct drm_file *fpriv, + struct drm_buf **buffer) +{ + struct drm_buf *buf; + + *buffer = NULL; + buf = radeon_freelist_get(dev); + if (!buf) { + return -EBUSY; + } + buf->file_priv = fpriv; + *buffer = buf; + return 0; +} + +static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf, + struct drm_file *fpriv, int l, int r) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (buf) { + if (!r) + r600_cp_dispatch_indirect(dev, buf, 0, l * 4); + radeon_cp_discard_buffer(dev, fpriv->masterp, buf); + COMMIT_RING(); + } +} + +int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_radeon_cs *cs = data; + struct drm_buf *buf; + unsigned family; + int l, r = 0; + u32 *ib, cs_id = 0; + + if (dev_priv == NULL) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + family = dev_priv->flags & RADEON_FAMILY_MASK; + if (family < CHIP_R600) { + DRM_ERROR("cs ioctl valid only for R6XX & R7XX in legacy mode\n"); + return -EINVAL; + } + sx_xlock(&dev_priv->cs_mutex); + /* get ib */ + l = 0; + r = r600_ib_get(dev, fpriv, &buf); + if (r) { + DRM_ERROR("ib_get failed\n"); + goto out; + } + ib = (u32 *)((uintptr_t)dev->agp_buffer_map->handle + buf->offset); + /* now parse command stream */ + r = r600_cs_legacy(dev, data, fpriv, family, ib, &l); + if (r) { + goto out; + } + +out: + r600_ib_free(dev, buf, fpriv, l, r); + /* emit cs id sequence */ + r600_cs_id_emit(dev_priv, &cs_id); + cs->cs_id = cs_id; + sx_xunlock(&dev_priv->cs_mutex); + return r; +} + +void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + *npipes = dev_priv->r600_npipes; + *nbanks = dev_priv->r600_nbanks; + *group_size = dev_priv->r600_group_size; +} diff --git a/sys/dev/drm2/radeon/r600_cp.h b/sys/dev/drm2/radeon/r600_cp.h new file mode 100644 index 00000000000..b1611ba3e29 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_cp.h @@ -0,0 +1,15 @@ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __R600_CP_H__ +#define __R600_CP_H__ + +void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, + u32 *npipes, u32 *nbanks, u32 *group_size); + +int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, + unsigned family, u32 *ib, int *l); +void r600_cs_legacy_init(void); + +#endif /* !defined(__R600_CP_H__) */ diff --git a/sys/dev/drm2/radeon/r600_cs.c b/sys/dev/drm2/radeon/r600_cs.c new file mode 100644 index 00000000000..6ba46143266 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_cs.c @@ -0,0 +1,2761 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "r600d.h" +#include "r600_reg_safe.h" +#include "r600_cp.h" +#include "r600_cs.h" + +static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); +static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); +typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**); +static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm; + + +struct r600_cs_track { + /* configuration we miror so that we use same code btw kms/ums */ + u32 group_size; + u32 nbanks; + u32 npipes; + /* value we track */ + u32 sq_config; + u32 log_nsamples; + u32 nsamples; + u32 cb_color_base_last[8]; + struct radeon_bo *cb_color_bo[8]; + u64 cb_color_bo_mc[8]; + u64 cb_color_bo_offset[8]; + struct radeon_bo *cb_color_frag_bo[8]; + u64 cb_color_frag_offset[8]; + struct radeon_bo *cb_color_tile_bo[8]; + u64 cb_color_tile_offset[8]; + u32 cb_color_mask[8]; + u32 cb_color_info[8]; + u32 cb_color_view[8]; + u32 cb_color_size_idx[8]; /* unused */ + u32 cb_target_mask; + u32 cb_shader_mask; /* unused */ + bool is_resolve; + u32 cb_color_size[8]; + u32 vgt_strmout_en; + u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; /* unused */ + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; + u32 db_depth_control; + u32 db_depth_info; + u32 db_depth_size_idx; + u32 db_depth_view; + u32 db_depth_size; + u32 db_offset; + struct radeon_bo *db_bo; + u64 db_bo_mc; + bool sx_misc_kill_all_prims; + bool cb_dirty; + bool db_dirty; + bool streamout_dirty; + struct radeon_bo *htile_bo; + u64 htile_offset; + u32 htile_surface; +}; + +#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc, CHIP_R600 } +#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc, CHIP_R600 } +#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 4, 0, CHIP_R600 } +#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc, CHIP_R600 } +#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 8, 0, CHIP_R600 } +#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc, CHIP_R600 } +#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0, CHIP_R600 } +#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 } + +struct gpu_formats { + unsigned blockwidth; + unsigned blockheight; + unsigned blocksize; + unsigned valid_color; + enum radeon_family min_family; +}; + +static const struct gpu_formats color_formats_table[] = { + /* 8 bit */ + FMT_8_BIT(V_038004_COLOR_8, 1), + FMT_8_BIT(V_038004_COLOR_4_4, 1), + FMT_8_BIT(V_038004_COLOR_3_3_2, 1), + FMT_8_BIT(V_038004_FMT_1, 0), + + /* 16-bit */ + FMT_16_BIT(V_038004_COLOR_16, 1), + FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1), + FMT_16_BIT(V_038004_COLOR_8_8, 1), + FMT_16_BIT(V_038004_COLOR_5_6_5, 1), + FMT_16_BIT(V_038004_COLOR_6_5_5, 1), + FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1), + FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1), + FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1), + + /* 24-bit */ + FMT_24_BIT(V_038004_FMT_8_8_8), + + /* 32-bit */ + FMT_32_BIT(V_038004_COLOR_32, 1), + FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1), + FMT_32_BIT(V_038004_COLOR_16_16, 1), + FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1), + FMT_32_BIT(V_038004_COLOR_8_24, 1), + FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1), + FMT_32_BIT(V_038004_COLOR_24_8, 1), + FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1), + FMT_32_BIT(V_038004_COLOR_10_11_11, 1), + FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1), + FMT_32_BIT(V_038004_COLOR_11_11_10, 1), + FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1), + FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1), + FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1), + FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1), + FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0), + FMT_32_BIT(V_038004_FMT_32_AS_8, 0), + FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0), + + /* 48-bit */ + FMT_48_BIT(V_038004_FMT_16_16_16), + FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT), + + /* 64-bit */ + FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1), + FMT_64_BIT(V_038004_COLOR_32_32, 1), + FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1), + FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1), + FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1), + + FMT_96_BIT(V_038004_FMT_32_32_32), + FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT), + + /* 128-bit */ + FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1), + FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1), + + [V_038004_FMT_GB_GR] = { 2, 1, 4, 0 }, + [V_038004_FMT_BG_RG] = { 2, 1, 4, 0 }, + + /* block compressed formats */ + [V_038004_FMT_BC1] = { 4, 4, 8, 0 }, + [V_038004_FMT_BC2] = { 4, 4, 16, 0 }, + [V_038004_FMT_BC3] = { 4, 4, 16, 0 }, + [V_038004_FMT_BC4] = { 4, 4, 8, 0 }, + [V_038004_FMT_BC5] = { 4, 4, 16, 0}, + [V_038004_FMT_BC6] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */ + [V_038004_FMT_BC7] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */ + + /* The other Evergreen formats */ + [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR}, +}; + +bool r600_fmt_is_valid_color(u32 format) +{ + if (format >= DRM_ARRAY_SIZE(color_formats_table)) + return false; + + if (color_formats_table[format].valid_color) + return true; + + return false; +} + +bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family) +{ + if (format >= DRM_ARRAY_SIZE(color_formats_table)) + return false; + + if (family < color_formats_table[format].min_family) + return false; + + if (color_formats_table[format].blockwidth > 0) + return true; + + return false; +} + +int r600_fmt_get_blocksize(u32 format) +{ + if (format >= DRM_ARRAY_SIZE(color_formats_table)) + return 0; + + return color_formats_table[format].blocksize; +} + +int r600_fmt_get_nblocksx(u32 format, u32 w) +{ + unsigned bw; + + if (format >= DRM_ARRAY_SIZE(color_formats_table)) + return 0; + + bw = color_formats_table[format].blockwidth; + if (bw == 0) + return 0; + + return (w + bw - 1) / bw; +} + +int r600_fmt_get_nblocksy(u32 format, u32 h) +{ + unsigned bh; + + if (format >= DRM_ARRAY_SIZE(color_formats_table)) + return 0; + + bh = color_formats_table[format].blockheight; + if (bh == 0) + return 0; + + return (h + bh - 1) / bh; +} + +struct array_mode_checker { + int array_mode; + u32 group_size; + u32 nbanks; + u32 npipes; + u32 nsamples; + u32 blocksize; +}; + +/* returns alignment in pixels for pitch/height/depth and bytes for base */ +static int r600_get_array_mode_alignment(struct array_mode_checker *values, + u32 *pitch_align, + u32 *height_align, + u32 *depth_align, + u64 *base_align) +{ + u32 tile_width = 8; + u32 tile_height = 8; + u32 macro_tile_width = values->nbanks; + u32 macro_tile_height = values->npipes; + u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples; + u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes; + + switch (values->array_mode) { + case ARRAY_LINEAR_GENERAL: + /* technically tile_width/_height for pitch/height */ + *pitch_align = 1; /* tile_width */ + *height_align = 1; /* tile_height */ + *depth_align = 1; + *base_align = 1; + break; + case ARRAY_LINEAR_ALIGNED: + *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize)); + *height_align = 1; + *depth_align = 1; + *base_align = values->group_size; + break; + case ARRAY_1D_TILED_THIN1: + *pitch_align = max((u32)tile_width, + (u32)(values->group_size / + (tile_height * values->blocksize * values->nsamples))); + *height_align = tile_height; + *depth_align = 1; + *base_align = values->group_size; + break; + case ARRAY_2D_TILED_THIN1: + *pitch_align = max((u32)macro_tile_width * tile_width, + (u32)((values->group_size * values->nbanks) / + (values->blocksize * values->nsamples * tile_width))); + *height_align = macro_tile_height * tile_height; + *depth_align = 1; + *base_align = max(macro_tile_bytes, + (*pitch_align) * values->blocksize * (*height_align) * values->nsamples); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void r600_cs_track_init(struct r600_cs_track *track) +{ + int i; + + /* assume DX9 mode */ + track->sq_config = DX9_CONSTS; + for (i = 0; i < 8; i++) { + track->cb_color_base_last[i] = 0; + track->cb_color_size[i] = 0; + track->cb_color_size_idx[i] = 0; + track->cb_color_info[i] = 0; + track->cb_color_view[i] = 0xFFFFFFFF; + track->cb_color_bo[i] = NULL; + track->cb_color_bo_offset[i] = 0xFFFFFFFF; + track->cb_color_bo_mc[i] = 0xFFFFFFFF; + track->cb_color_frag_bo[i] = NULL; + track->cb_color_frag_offset[i] = 0xFFFFFFFF; + track->cb_color_tile_bo[i] = NULL; + track->cb_color_tile_offset[i] = 0xFFFFFFFF; + track->cb_color_mask[i] = 0xFFFFFFFF; + } + track->is_resolve = false; + track->nsamples = 16; + track->log_nsamples = 4; + track->cb_target_mask = 0xFFFFFFFF; + track->cb_shader_mask = 0xFFFFFFFF; + track->cb_dirty = true; + track->db_bo = NULL; + track->db_bo_mc = 0xFFFFFFFF; + /* assume the biggest format and that htile is enabled */ + track->db_depth_info = 7 | (1 << 25); + track->db_depth_view = 0xFFFFC000; + track->db_depth_size = 0xFFFFFFFF; + track->db_depth_size_idx = 0; + track->db_depth_control = 0xFFFFFFFF; + track->db_dirty = true; + track->htile_bo = NULL; + track->htile_offset = 0xFFFFFFFF; + track->htile_surface = 0; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } + track->streamout_dirty = true; + track->sx_misc_kill_all_prims = false; +} + +static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) +{ + struct r600_cs_track *track = p->track; + u32 slice_tile_max, size, tmp; + u32 height, height_align, pitch, pitch_align, depth_align; + u64 base_offset, base_align; + struct array_mode_checker array_check; + volatile u32 *ib = p->ib.ptr; + unsigned array_mode; + u32 format; + /* When resolve is used, the second colorbuffer has always 1 sample. */ + unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples; + + size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; + format = G_0280A0_FORMAT(track->cb_color_info[i]); + if (!r600_fmt_is_valid_color(format)) { + dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", + __func__, __LINE__, format, + i, track->cb_color_info[i]); + return -EINVAL; + } + /* pitch in pixels */ + pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8; + slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1; + slice_tile_max *= 64; + height = slice_tile_max / pitch; + if (height > 8192) + height = 8192; + array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]); + + base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i]; + array_check.array_mode = array_mode; + array_check.group_size = track->group_size; + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = nsamples; + array_check.blocksize = r600_fmt_get_blocksize(format); + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, + G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i, + track->cb_color_info[i]); + return -EINVAL; + } + switch (array_mode) { + case V_0280A0_ARRAY_LINEAR_GENERAL: + break; + case V_0280A0_ARRAY_LINEAR_ALIGNED: + break; + case V_0280A0_ARRAY_1D_TILED_THIN1: + /* avoid breaking userspace */ + if (height > 7) + height &= ~0x7; + break; + case V_0280A0_ARRAY_2D_TILED_THIN1: + break; + default: + dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, + G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i, + track->cb_color_info[i]); + return -EINVAL; + } + + if (!IS_ALIGNED(pitch, pitch_align)) { + dev_warn(p->dev, "%s:%d cb pitch (%d, 0x%x, %d) invalid\n", + __func__, __LINE__, pitch, pitch_align, array_mode); + return -EINVAL; + } + if (!IS_ALIGNED(height, height_align)) { + dev_warn(p->dev, "%s:%d cb height (%d, 0x%x, %d) invalid\n", + __func__, __LINE__, height, height_align, array_mode); + return -EINVAL; + } + if (!IS_ALIGNED(base_offset, base_align)) { + dev_warn(p->dev, "%s offset[%d] 0x%jx 0x%jx, %d not aligned\n", __func__, i, + (uintmax_t)base_offset, (uintmax_t)base_align, array_mode); + return -EINVAL; + } + + /* check offset */ + tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * + r600_fmt_get_blocksize(format) * nsamples; + switch (array_mode) { + default: + case V_0280A0_ARRAY_LINEAR_GENERAL: + case V_0280A0_ARRAY_LINEAR_ALIGNED: + tmp += track->cb_color_view[i] & 0xFF; + break; + case V_0280A0_ARRAY_1D_TILED_THIN1: + case V_0280A0_ARRAY_2D_TILED_THIN1: + tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp; + break; + } + if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { + if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { + /* the initial DDX does bad things with the CB size occasionally */ + /* it rounds up height too far for slice tile max but the BO is smaller */ + /* r600c,g also seem to flush at bad times in some apps resulting in + * bogus values here. So for linear just allow anything to avoid breaking + * broken userspace. + */ + } else { + dev_warn(p->dev, "%s offset[%d] %d %ju %d %lu too big (%d %d) (%d %d %d)\n", + __func__, i, array_mode, + (uintmax_t)track->cb_color_bo_offset[i], tmp, + radeon_bo_size(track->cb_color_bo[i]), + pitch, height, r600_fmt_get_nblocksx(format, pitch), + r600_fmt_get_nblocksy(format, height), + r600_fmt_get_blocksize(format)); + return -EINVAL; + } + } + /* limit max tile */ + tmp = (height * pitch) >> 6; + if (tmp < slice_tile_max) + slice_tile_max = tmp; + tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) | + S_028060_SLICE_TILE_MAX(slice_tile_max - 1); + ib[track->cb_color_size_idx[i]] = tmp; + + /* FMASK/CMASK */ + switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) { + case V_0280A0_TILE_DISABLE: + break; + case V_0280A0_FRAG_ENABLE: + if (track->nsamples > 1) { + uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]); + /* the tile size is 8x8, but the size is in units of bits. + * for bytes, do just * 8. */ + uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1); + + if (bytes + track->cb_color_frag_offset[i] > + radeon_bo_size(track->cb_color_frag_bo[i])) { + dev_warn(p->dev, "%s FMASK_TILE_MAX too large " + "(tile_max=%u, bytes=%u, offset=%ju, bo_size=%lu)\n", + __func__, tile_max, bytes, + (uintmax_t)track->cb_color_frag_offset[i], + radeon_bo_size(track->cb_color_frag_bo[i])); + return -EINVAL; + } + } + /* fall through */ + case V_0280A0_CLEAR_ENABLE: + { + uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); + /* One block = 128x128 pixels, one 8x8 tile has 4 bits.. + * (128*128) / (8*8) / 2 = 128 bytes per block. */ + uint32_t bytes = (block_max + 1) * 128; + + if (bytes + track->cb_color_tile_offset[i] > + radeon_bo_size(track->cb_color_tile_bo[i])) { + dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large " + "(block_max=%u, bytes=%u, offset=%ju, bo_size=%lu)\n", + __func__, block_max, bytes, + (uintmax_t)track->cb_color_tile_offset[i], + radeon_bo_size(track->cb_color_tile_bo[i])); + return -EINVAL; + } + break; + } + default: + dev_warn(p->dev, "%s invalid tile mode\n", __func__); + return -EINVAL; + } + return 0; +} + +static int r600_cs_track_validate_db(struct radeon_cs_parser *p) +{ + struct r600_cs_track *track = p->track; + u32 nviews, bpe, ntiles, size, slice_tile_max, tmp; + u32 height_align, pitch_align, depth_align; + u32 pitch = 8192; + u32 height = 8192; + u64 base_offset, base_align; + struct array_mode_checker array_check; + int array_mode; + volatile u32 *ib = p->ib.ptr; + + + if (track->db_bo == NULL) { + dev_warn(p->dev, "z/stencil with no depth buffer\n"); + return -EINVAL; + } + switch (G_028010_FORMAT(track->db_depth_info)) { + case V_028010_DEPTH_16: + bpe = 2; + break; + case V_028010_DEPTH_X8_24: + case V_028010_DEPTH_8_24: + case V_028010_DEPTH_X8_24_FLOAT: + case V_028010_DEPTH_8_24_FLOAT: + case V_028010_DEPTH_32_FLOAT: + bpe = 4; + break; + case V_028010_DEPTH_X24_8_32_FLOAT: + bpe = 8; + break; + default: + dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info)); + return -EINVAL; + } + if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) { + if (!track->db_depth_size_idx) { + dev_warn(p->dev, "z/stencil buffer size not set\n"); + return -EINVAL; + } + tmp = radeon_bo_size(track->db_bo) - track->db_offset; + tmp = (tmp / bpe) >> 6; + if (!tmp) { + dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n", + track->db_depth_size, bpe, track->db_offset, + radeon_bo_size(track->db_bo)); + return -EINVAL; + } + ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF); + } else { + size = radeon_bo_size(track->db_bo); + /* pitch in pixels */ + pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8; + slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; + slice_tile_max *= 64; + height = slice_tile_max / pitch; + if (height > 8192) + height = 8192; + base_offset = track->db_bo_mc + track->db_offset; + array_mode = G_028010_ARRAY_MODE(track->db_depth_info); + array_check.array_mode = array_mode; + array_check.group_size = track->group_size; + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = track->nsamples; + array_check.blocksize = bpe; + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, + G_028010_ARRAY_MODE(track->db_depth_info), + track->db_depth_info); + return -EINVAL; + } + switch (array_mode) { + case V_028010_ARRAY_1D_TILED_THIN1: + /* don't break userspace */ + height &= ~0x7; + break; + case V_028010_ARRAY_2D_TILED_THIN1: + break; + default: + dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, + G_028010_ARRAY_MODE(track->db_depth_info), + track->db_depth_info); + return -EINVAL; + } + + if (!IS_ALIGNED(pitch, pitch_align)) { + dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n", + __func__, __LINE__, pitch, pitch_align, array_mode); + return -EINVAL; + } + if (!IS_ALIGNED(height, height_align)) { + dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n", + __func__, __LINE__, height, height_align, array_mode); + return -EINVAL; + } + if (!IS_ALIGNED(base_offset, base_align)) { + dev_warn(p->dev, "%s offset 0x%jx, 0x%jx, %d not aligned\n", __func__, + (uintmax_t)base_offset, (uintmax_t)base_align, array_mode); + return -EINVAL; + } + + ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; + nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; + tmp = ntiles * bpe * 64 * nviews * track->nsamples; + if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { + dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", + array_mode, + track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset, + radeon_bo_size(track->db_bo)); + return -EINVAL; + } + } + + /* hyperz */ + if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) { + unsigned long size; + unsigned nbx, nby; + + if (track->htile_bo == NULL) { + dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", + __func__, __LINE__, track->db_depth_info); + return -EINVAL; + } + if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) { + dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n", + __func__, __LINE__, track->db_depth_size); + return -EINVAL; + } + + nbx = pitch; + nby = height; + if (G_028D24_LINEAR(track->htile_surface)) { + /* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */ + nbx = roundup2(nbx, 16 * 8); + /* nby is npipes htiles aligned == npipes * 8 pixel aligned */ + nby = roundup(nby, track->npipes * 8); + } else { + /* always assume 8x8 htile */ + /* align is htile align * 8, htile align vary according to + * number of pipe and tile width and nby + */ + switch (track->npipes) { + case 8: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup2(nbx, 64 * 8); + nby = roundup2(nby, 64 * 8); + break; + case 4: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup2(nbx, 64 * 8); + nby = roundup2(nby, 32 * 8); + break; + case 2: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup2(nbx, 32 * 8); + nby = roundup2(nby, 32 * 8); + break; + case 1: + /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ + nbx = roundup2(nbx, 32 * 8); + nby = roundup2(nby, 16 * 8); + break; + default: + dev_warn(p->dev, "%s:%d invalid num pipes %d\n", + __func__, __LINE__, track->npipes); + return -EINVAL; + } + } + /* compute number of htile */ + nbx = nbx >> 3; + nby = nby >> 3; + /* size must be aligned on npipes * 2K boundary */ + size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); + size += track->htile_offset; + + if (size > radeon_bo_size(track->htile_bo)) { + dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", + __func__, __LINE__, radeon_bo_size(track->htile_bo), + size, nbx, nby); + return -EINVAL; + } + } + + track->db_dirty = false; + return 0; +} + +static int r600_cs_track_check(struct radeon_cs_parser *p) +{ + struct r600_cs_track *track = p->track; + u32 tmp; + int r, i; + + /* on legacy kernel we don't perform advanced check */ + if (p->rdev == NULL) + return 0; + + /* check streamout */ + if (track->streamout_dirty && track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i]) { + u64 offset = (u64)track->vgt_strmout_bo_offset[i] + + (u64)track->vgt_strmout_size[i]; + if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { + DRM_ERROR("streamout %d bo too small: 0x%jx, 0x%lx\n", + i, (uintmax_t)offset, + radeon_bo_size(track->vgt_strmout_bo[i])); + return -EINVAL; + } + } else { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } + track->streamout_dirty = false; + } + + if (track->sx_misc_kill_all_prims) + return 0; + + /* check that we have a cb for each enabled target, we don't check + * shader_mask because it seems mesa isn't always setting it :( + */ + if (track->cb_dirty) { + tmp = track->cb_target_mask; + + /* We must check both colorbuffers for RESOLVE. */ + if (track->is_resolve) { + tmp |= 0xff; + } + + for (i = 0; i < 8; i++) { + if ((tmp >> (i * 4)) & 0xF) { + /* at least one component is enabled */ + if (track->cb_color_bo[i] == NULL) { + dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", + __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); + return -EINVAL; + } + /* perform rewrite of CB_COLOR[0-7]_SIZE */ + r = r600_cs_track_validate_cb(p, i); + if (r) + return r; + } + } + track->cb_dirty = false; + } + + /* Check depth buffer */ + if (track->db_dirty && + G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID && + (G_028800_STENCIL_ENABLE(track->db_depth_control) || + G_028800_Z_ENABLE(track->db_depth_control))) { + r = r600_cs_track_validate_db(p); + if (r) + return r; + } + + return 0; +} + +/** + * r600_cs_packet_parse() - parse cp packet and point ib index to next packet + * @parser: parser structure holding parsing context. + * @pkt: where to store packet informations + * + * Assume that chunk_ib_index is properly set. Will return -EINVAL + * if packet is bigger than remaining ib size. or if packets is unknown. + **/ +static int r600_cs_packet_parse(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx) +{ + struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; + uint32_t header; + + if (idx >= ib_chunk->length_dw) { + DRM_ERROR("Can not parse packet at %d after CS end %d !\n", + idx, ib_chunk->length_dw); + return -EINVAL; + } + header = radeon_get_ib_value(p, idx); + pkt->idx = idx; + pkt->type = CP_PACKET_GET_TYPE(header); + pkt->count = CP_PACKET_GET_COUNT(header); + pkt->one_reg_wr = 0; + switch (pkt->type) { + case PACKET_TYPE0: + pkt->reg = CP_PACKET0_GET_REG(header); + break; + case PACKET_TYPE3: + pkt->opcode = CP_PACKET3_GET_OPCODE(header); + break; + case PACKET_TYPE2: + pkt->count = -1; + break; + default: + DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); + return -EINVAL; + } + if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { + DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", + pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); + return -EINVAL; + } + return 0; +} + +/** + * r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3 + * @parser: parser structure holding parsing context. + * @data: pointer to relocation data + * @offset_start: starting offset + * @offset_mask: offset mask (to align start offset on) + * @reloc: reloc informations + * + * Check next packet is relocation packet3, do bo validation and compute + * GPU offset using the provided start. + **/ +static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc) +{ + struct radeon_cs_chunk *relocs_chunk; + struct radeon_cs_packet p3reloc; + unsigned idx; + int r; + + if (p->chunk_relocs_idx == -1) { + DRM_ERROR("No relocation chunk !\n"); + return -EINVAL; + } + *cs_reloc = NULL; + relocs_chunk = &p->chunks[p->chunk_relocs_idx]; + r = r600_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return r; + } + p->idx += p3reloc.count + 2; + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + DRM_ERROR("No packet3 for relocation for packet at %d.\n", + p3reloc.idx); + return -EINVAL; + } + idx = radeon_get_ib_value(p, p3reloc.idx + 1); + if (idx >= relocs_chunk->length_dw) { + DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", + idx, relocs_chunk->length_dw); + return -EINVAL; + } + /* FIXME: we assume reloc size is 4 dwords */ + *cs_reloc = p->relocs_ptr[(idx / 4)]; + return 0; +} + +/** + * r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3 + * @parser: parser structure holding parsing context. + * @data: pointer to relocation data + * @offset_start: starting offset + * @offset_mask: offset mask (to align start offset on) + * @reloc: reloc informations + * + * Check next packet is relocation packet3, do bo validation and compute + * GPU offset using the provided start. + **/ +static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc) +{ + struct radeon_cs_chunk *relocs_chunk; + struct radeon_cs_packet p3reloc; + unsigned idx; + int r; + + if (p->chunk_relocs_idx == -1) { + DRM_ERROR("No relocation chunk !\n"); + return -EINVAL; + } + *cs_reloc = NULL; + relocs_chunk = &p->chunks[p->chunk_relocs_idx]; + r = r600_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return r; + } + p->idx += p3reloc.count + 2; + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + DRM_ERROR("No packet3 for relocation for packet at %d.\n", + p3reloc.idx); + return -EINVAL; + } + idx = radeon_get_ib_value(p, p3reloc.idx + 1); + if (idx >= relocs_chunk->length_dw) { + DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", + idx, relocs_chunk->length_dw); + return -EINVAL; + } + *cs_reloc = p->relocs; + (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32; + (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0]; + return 0; +} + +/** + * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc + * @parser: parser structure holding parsing context. + * + * Check next packet is relocation packet3, do bo validation and compute + * GPU offset using the provided start. + **/ +static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet p3reloc; + int r; + + r = r600_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return 0; + } + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + return 0; + } + return 1; +} + +/** + * r600_cs_packet_next_vline() - parse userspace VLINE packet + * @parser: parser structure holding parsing context. + * + * Userspace sends a special sequence for VLINE waits. + * PACKET0 - VLINE_START_END + value + * PACKET3 - WAIT_REG_MEM poll vline status reg + * RELOC (P3) - crtc_id in reloc. + * + * This function parses this and relocates the VLINE START END + * and WAIT_REG_MEM packets to the correct crtc. + * It also detects a switched off crtc and nulls out the + * wait in that case. + */ +static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p) +{ + struct drm_mode_object *obj; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + struct radeon_cs_packet p3reloc, wait_reg_mem; + int crtc_id; + int r; + uint32_t header, h_idx, reg, wait_reg_mem_info; + volatile uint32_t *ib; + + ib = p->ib.ptr; + + /* parse the WAIT_REG_MEM */ + r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx); + if (r) + return r; + + /* check its a WAIT_REG_MEM */ + if (wait_reg_mem.type != PACKET_TYPE3 || + wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) { + DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n"); + return -EINVAL; + } + + wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1); + /* bit 4 is reg (0) or mem (1) */ + if (wait_reg_mem_info & 0x10) { + DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n"); + return -EINVAL; + } + /* waiting for value to be equal */ + if ((wait_reg_mem_info & 0x7) != 0x3) { + DRM_ERROR("vline WAIT_REG_MEM function not equal\n"); + return -EINVAL; + } + if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) { + DRM_ERROR("vline WAIT_REG_MEM bad reg\n"); + return -EINVAL; + } + + if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) { + DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); + return -EINVAL; + } + + /* jump over the NOP */ + r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2); + if (r) + return r; + + h_idx = p->idx - 2; + p->idx += wait_reg_mem.count + 2; + p->idx += p3reloc.count + 2; + + header = radeon_get_ib_value(p, h_idx); + crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1); + reg = CP_PACKET0_GET_REG(header); + + obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_ERROR("cannot find crtc %d\n", crtc_id); + return -EINVAL; + } + crtc = obj_to_crtc(obj); + radeon_crtc = to_radeon_crtc(crtc); + crtc_id = radeon_crtc->crtc_id; + + if (!crtc->enabled) { + /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */ + ib[h_idx + 2] = PACKET2(0); + ib[h_idx + 3] = PACKET2(0); + ib[h_idx + 4] = PACKET2(0); + ib[h_idx + 5] = PACKET2(0); + ib[h_idx + 6] = PACKET2(0); + ib[h_idx + 7] = PACKET2(0); + ib[h_idx + 8] = PACKET2(0); + } else if (crtc_id == 1) { + switch (reg) { + case AVIVO_D1MODE_VLINE_START_END: + header &= ~R600_CP_PACKET0_REG_MASK; + header |= AVIVO_D2MODE_VLINE_START_END >> 2; + break; + default: + DRM_ERROR("unknown crtc reloc\n"); + return -EINVAL; + } + ib[h_idx] = header; + ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2; + } + + return 0; +} + +static int r600_packet0_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg) +{ + int r; + + switch (reg) { + case AVIVO_D1MODE_VLINE_START_END: + r = r600_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + return r; + } + break; + default: + DRM_ERROR("Forbidden register 0x%04X in cs at %d\n", + reg, idx); + return -EINVAL; + } + return 0; +} + +static int r600_cs_parse_packet0(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + unsigned reg, i; + unsigned idx; + int r; + + idx = pkt->idx + 1; + reg = pkt->reg; + for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { + r = r600_packet0_check(p, pkt, idx, reg); + if (r) { + return r; + } + } + return 0; +} + +/** + * r600_cs_check_reg() - check if register is authorized or not + * @parser: parser structure holding parsing context + * @reg: register we are testing + * @idx: index into the cs buffer + * + * This function will test against r600_reg_safe_bm and return 0 + * if register is safe. If register is not flag as safe this function + * will test it against a list of register needind special handling. + */ +static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + struct r600_cs_track *track = (struct r600_cs_track *)p->track; + struct radeon_cs_reloc *reloc; + u32 m, i, tmp, *ib; + int r; + + i = (reg >> 7); + if (i >= DRM_ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return 0; + ib = p->ib.ptr; + switch (reg) { + /* force following reg to 0 in an attempt to disable out buffer + * which will need us to better understand how it works to perform + * security check on it (Jerome) + */ + case R_0288A8_SQ_ESGS_RING_ITEMSIZE: + case R_008C44_SQ_ESGS_RING_SIZE: + case R_0288B0_SQ_ESTMP_RING_ITEMSIZE: + case R_008C54_SQ_ESTMP_RING_SIZE: + case R_0288C0_SQ_FBUF_RING_ITEMSIZE: + case R_008C74_SQ_FBUF_RING_SIZE: + case R_0288B4_SQ_GSTMP_RING_ITEMSIZE: + case R_008C5C_SQ_GSTMP_RING_SIZE: + case R_0288AC_SQ_GSVS_RING_ITEMSIZE: + case R_008C4C_SQ_GSVS_RING_SIZE: + case R_0288BC_SQ_PSTMP_RING_ITEMSIZE: + case R_008C6C_SQ_PSTMP_RING_SIZE: + case R_0288C4_SQ_REDUC_RING_ITEMSIZE: + case R_008C7C_SQ_REDUC_RING_SIZE: + case R_0288B8_SQ_VSTMP_RING_ITEMSIZE: + case R_008C64_SQ_VSTMP_RING_SIZE: + case R_0288C8_SQ_GS_VERT_ITEMSIZE: + /* get value to populate the IB don't remove */ + tmp =radeon_get_ib_value(p, idx); + ib[idx] = 0; + break; + case SQ_CONFIG: + track->sq_config = radeon_get_ib_value(p, idx); + break; + case R_028800_DB_DEPTH_CONTROL: + track->db_depth_control = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case R_028010_DB_DEPTH_INFO: + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) && + r600_cs_packet_next_is_pkt3_nop(p)) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->db_depth_info = radeon_get_ib_value(p, idx); + ib[idx] &= C_028010_ARRAY_MODE; + track->db_depth_info &= C_028010_ARRAY_MODE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1); + track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1); + } else { + ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1); + track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1); + } + } else { + track->db_depth_info = radeon_get_ib_value(p, idx); + } + track->db_dirty = true; + break; + case R_028004_DB_DEPTH_VIEW: + track->db_depth_view = radeon_get_ib_value(p, idx); + track->db_dirty = true; + break; + case R_028000_DB_DEPTH_SIZE: + track->db_depth_size = radeon_get_ib_value(p, idx); + track->db_depth_size_idx = idx; + track->db_dirty = true; + break; + case R_028AB0_VGT_STRMOUT_EN: + track->vgt_strmout_en = radeon_get_ib_value(p, idx); + track->streamout_dirty = true; + break; + case R_028B20_VGT_STRMOUT_BUFFER_EN: + track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); + track->streamout_dirty = true; + break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + track->streamout_dirty = true; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + track->streamout_dirty = true; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case R_028238_CB_TARGET_MASK: + track->cb_target_mask = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case R_02823C_CB_SHADER_MASK: + track->cb_shader_mask = radeon_get_ib_value(p, idx); + break; + case R_028C04_PA_SC_AA_CONFIG: + tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); + track->log_nsamples = tmp; + track->nsamples = 1 << tmp; + track->cb_dirty = true; + break; + case R_028808_CB_COLOR_CONTROL: + tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx)); + track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX; + track->cb_dirty = true; + break; + case R_0280A0_CB_COLOR0_INFO: + case R_0280A4_CB_COLOR1_INFO: + case R_0280A8_CB_COLOR2_INFO: + case R_0280AC_CB_COLOR3_INFO: + case R_0280B0_CB_COLOR4_INFO: + case R_0280B4_CB_COLOR5_INFO: + case R_0280B8_CB_COLOR6_INFO: + case R_0280BC_CB_COLOR7_INFO: + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) && + r600_cs_packet_next_is_pkt3_nop(p)) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1); + track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1); + } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1); + track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1); + } + } else { + tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); + } + track->cb_dirty = true; + break; + case R_028080_CB_COLOR0_VIEW: + case R_028084_CB_COLOR1_VIEW: + case R_028088_CB_COLOR2_VIEW: + case R_02808C_CB_COLOR3_VIEW: + case R_028090_CB_COLOR4_VIEW: + case R_028094_CB_COLOR5_VIEW: + case R_028098_CB_COLOR6_VIEW: + case R_02809C_CB_COLOR7_VIEW: + tmp = (reg - R_028080_CB_COLOR0_VIEW) / 4; + track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); + track->cb_dirty = true; + break; + case R_028060_CB_COLOR0_SIZE: + case R_028064_CB_COLOR1_SIZE: + case R_028068_CB_COLOR2_SIZE: + case R_02806C_CB_COLOR3_SIZE: + case R_028070_CB_COLOR4_SIZE: + case R_028074_CB_COLOR5_SIZE: + case R_028078_CB_COLOR6_SIZE: + case R_02807C_CB_COLOR7_SIZE: + tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4; + track->cb_color_size[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_size_idx[tmp] = idx; + track->cb_dirty = true; + break; + /* This register were added late, there is userspace + * which does provide relocation for those but set + * 0 offset. In order to avoid breaking old userspace + * we detect this and set address to point to last + * CB_COLOR0_BASE, note that if userspace doesn't set + * CB_COLOR0_BASE before this register we will report + * error. Old userspace always set CB_COLOR0_BASE + * before any of this. + */ + case R_0280E0_CB_COLOR0_FRAG: + case R_0280E4_CB_COLOR1_FRAG: + case R_0280E8_CB_COLOR2_FRAG: + case R_0280EC_CB_COLOR3_FRAG: + case R_0280F0_CB_COLOR4_FRAG: + case R_0280F4_CB_COLOR5_FRAG: + case R_0280F8_CB_COLOR6_FRAG: + case R_0280FC_CB_COLOR7_FRAG: + tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4; + if (!r600_cs_packet_next_is_pkt3_nop(p)) { + if (!track->cb_color_base_last[tmp]) { + dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); + return -EINVAL; + } + track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; + track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp]; + ib[idx] = track->cb_color_base_last[tmp]; + } else { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); + return -EINVAL; + } + track->cb_color_frag_bo[tmp] = reloc->robj; + track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { + track->cb_dirty = true; + } + break; + case R_0280C0_CB_COLOR0_TILE: + case R_0280C4_CB_COLOR1_TILE: + case R_0280C8_CB_COLOR2_TILE: + case R_0280CC_CB_COLOR3_TILE: + case R_0280D0_CB_COLOR4_TILE: + case R_0280D4_CB_COLOR5_TILE: + case R_0280D8_CB_COLOR6_TILE: + case R_0280DC_CB_COLOR7_TILE: + tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4; + if (!r600_cs_packet_next_is_pkt3_nop(p)) { + if (!track->cb_color_base_last[tmp]) { + dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); + return -EINVAL; + } + track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; + track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp]; + ib[idx] = track->cb_color_base_last[tmp]; + } else { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); + return -EINVAL; + } + track->cb_color_tile_bo[tmp] = reloc->robj; + track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { + track->cb_dirty = true; + } + break; + case R_028100_CB_COLOR0_MASK: + case R_028104_CB_COLOR1_MASK: + case R_028108_CB_COLOR2_MASK: + case R_02810C_CB_COLOR3_MASK: + case R_028110_CB_COLOR4_MASK: + case R_028114_CB_COLOR5_MASK: + case R_028118_CB_COLOR6_MASK: + case R_02811C_CB_COLOR7_MASK: + tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; + track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx); + if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { + track->cb_dirty = true; + } + break; + case CB_COLOR0_BASE: + case CB_COLOR1_BASE: + case CB_COLOR2_BASE: + case CB_COLOR3_BASE: + case CB_COLOR4_BASE: + case CB_COLOR5_BASE: + case CB_COLOR6_BASE: + case CB_COLOR7_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - CB_COLOR0_BASE) / 4; + track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->cb_color_base_last[tmp] = ib[idx]; + track->cb_color_bo[tmp] = reloc->robj; + track->cb_color_bo_mc[tmp] = reloc->lobj.gpu_offset; + track->cb_dirty = true; + break; + case DB_DEPTH_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->db_offset = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_bo = reloc->robj; + track->db_bo_mc = reloc->lobj.gpu_offset; + track->db_dirty = true; + break; + case DB_HTILE_DATA_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + track->htile_offset = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->htile_bo = reloc->robj; + track->db_dirty = true; + break; + case DB_HTILE_SURFACE: + track->htile_surface = radeon_get_ib_value(p, idx); + /* force 8x8 htile width and height */ + ib[idx] |= 3; + track->db_dirty = true; + break; + case SQ_PGM_START_FS: + case SQ_PGM_START_ES: + case SQ_PGM_START_VS: + case SQ_PGM_START_GS: + case SQ_PGM_START_PS: + case SQ_ALU_CONST_CACHE_GS_0: + case SQ_ALU_CONST_CACHE_GS_1: + case SQ_ALU_CONST_CACHE_GS_2: + case SQ_ALU_CONST_CACHE_GS_3: + case SQ_ALU_CONST_CACHE_GS_4: + case SQ_ALU_CONST_CACHE_GS_5: + case SQ_ALU_CONST_CACHE_GS_6: + case SQ_ALU_CONST_CACHE_GS_7: + case SQ_ALU_CONST_CACHE_GS_8: + case SQ_ALU_CONST_CACHE_GS_9: + case SQ_ALU_CONST_CACHE_GS_10: + case SQ_ALU_CONST_CACHE_GS_11: + case SQ_ALU_CONST_CACHE_GS_12: + case SQ_ALU_CONST_CACHE_GS_13: + case SQ_ALU_CONST_CACHE_GS_14: + case SQ_ALU_CONST_CACHE_GS_15: + case SQ_ALU_CONST_CACHE_PS_0: + case SQ_ALU_CONST_CACHE_PS_1: + case SQ_ALU_CONST_CACHE_PS_2: + case SQ_ALU_CONST_CACHE_PS_3: + case SQ_ALU_CONST_CACHE_PS_4: + case SQ_ALU_CONST_CACHE_PS_5: + case SQ_ALU_CONST_CACHE_PS_6: + case SQ_ALU_CONST_CACHE_PS_7: + case SQ_ALU_CONST_CACHE_PS_8: + case SQ_ALU_CONST_CACHE_PS_9: + case SQ_ALU_CONST_CACHE_PS_10: + case SQ_ALU_CONST_CACHE_PS_11: + case SQ_ALU_CONST_CACHE_PS_12: + case SQ_ALU_CONST_CACHE_PS_13: + case SQ_ALU_CONST_CACHE_PS_14: + case SQ_ALU_CONST_CACHE_PS_15: + case SQ_ALU_CONST_CACHE_VS_0: + case SQ_ALU_CONST_CACHE_VS_1: + case SQ_ALU_CONST_CACHE_VS_2: + case SQ_ALU_CONST_CACHE_VS_3: + case SQ_ALU_CONST_CACHE_VS_4: + case SQ_ALU_CONST_CACHE_VS_5: + case SQ_ALU_CONST_CACHE_VS_6: + case SQ_ALU_CONST_CACHE_VS_7: + case SQ_ALU_CONST_CACHE_VS_8: + case SQ_ALU_CONST_CACHE_VS_9: + case SQ_ALU_CONST_CACHE_VS_10: + case SQ_ALU_CONST_CACHE_VS_11: + case SQ_ALU_CONST_CACHE_VS_12: + case SQ_ALU_CONST_CACHE_VS_13: + case SQ_ALU_CONST_CACHE_VS_14: + case SQ_ALU_CONST_CACHE_VS_15: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case SX_MEMORY_EXPORT_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONFIG_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case SX_MISC: + track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; + break; + default: + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; + } + return 0; +} + +unsigned r600_mip_minify(unsigned size, unsigned level) +{ + unsigned val; + + val = max(1U, size >> level); + if (level > 0) + val = roundup_pow_of_two(val); + return val; +} + +static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, + unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format, + unsigned block_align, unsigned height_align, unsigned base_align, + unsigned *l0_size, unsigned *mipmap_size) +{ + unsigned offset, i, level; + unsigned width, height, depth, size; + unsigned blocksize; + unsigned nbx, nby; + unsigned nlevels = llevel - blevel + 1; + + *l0_size = -1; + blocksize = r600_fmt_get_blocksize(format); + + w0 = r600_mip_minify(w0, 0); + h0 = r600_mip_minify(h0, 0); + d0 = r600_mip_minify(d0, 0); + for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) { + width = r600_mip_minify(w0, i); + nbx = r600_fmt_get_nblocksx(format, width); + + nbx = roundup(nbx, block_align); + + height = r600_mip_minify(h0, i); + nby = r600_fmt_get_nblocksy(format, height); + nby = roundup(nby, height_align); + + depth = r600_mip_minify(d0, i); + + size = nbx * nby * blocksize * nsamples; + if (nfaces) + size *= nfaces; + else + size *= depth; + + if (i == 0) + *l0_size = size; + + if (i == 0 || i == 1) + offset = roundup(offset, base_align); + + offset += size; + } + *mipmap_size = offset; + if (llevel == 0) + *mipmap_size = *l0_size; + if (!blevel) + *mipmap_size -= *l0_size; +} + +/** + * r600_check_texture_resource() - check if register is authorized or not + * @p: parser structure holding parsing context + * @idx: index into the cs buffer + * @texture: texture's bo structure + * @mipmap: mipmap's bo structure + * + * This function will check that the resource has valid field and that + * the texture and mipmap bo object are big enough to cover this resource. + */ +static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + struct radeon_bo *texture, + struct radeon_bo *mipmap, + u64 base_offset, + u64 mip_offset, + u32 tiling_flags) +{ + struct r600_cs_track *track = p->track; + u32 dim, nfaces, llevel, blevel, w0, h0, d0; + u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5; + u32 height_align, pitch, pitch_align, depth_align; + u32 barray, larray; + u64 base_align; + struct array_mode_checker array_check; + u32 format; + bool is_array; + + /* on legacy kernel we don't perform advanced check */ + if (p->rdev == NULL) + return 0; + + /* convert to bytes */ + base_offset <<= 8; + mip_offset <<= 8; + + word0 = radeon_get_ib_value(p, idx + 0); + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (tiling_flags & RADEON_TILING_MACRO) + word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); + else if (tiling_flags & RADEON_TILING_MICRO) + word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + } + word1 = radeon_get_ib_value(p, idx + 1); + word2 = radeon_get_ib_value(p, idx + 2) << 8; + word3 = radeon_get_ib_value(p, idx + 3) << 8; + word4 = radeon_get_ib_value(p, idx + 4); + word5 = radeon_get_ib_value(p, idx + 5); + dim = G_038000_DIM(word0); + w0 = G_038000_TEX_WIDTH(word0) + 1; + pitch = (G_038000_PITCH(word0) + 1) * 8; + h0 = G_038004_TEX_HEIGHT(word1) + 1; + d0 = G_038004_TEX_DEPTH(word1); + format = G_038004_DATA_FORMAT(word1); + blevel = G_038010_BASE_LEVEL(word4); + llevel = G_038014_LAST_LEVEL(word5); + /* pitch in texels */ + array_check.array_mode = G_038000_TILE_MODE(word0); + array_check.group_size = track->group_size; + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = 1; + array_check.blocksize = r600_fmt_get_blocksize(format); + nfaces = 1; + is_array = false; + switch (dim) { + case V_038000_SQ_TEX_DIM_1D: + case V_038000_SQ_TEX_DIM_2D: + case V_038000_SQ_TEX_DIM_3D: + break; + case V_038000_SQ_TEX_DIM_CUBEMAP: + if (p->family >= CHIP_RV770) + nfaces = 8; + else + nfaces = 6; + break; + case V_038000_SQ_TEX_DIM_1D_ARRAY: + case V_038000_SQ_TEX_DIM_2D_ARRAY: + is_array = true; + break; + case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: + is_array = true; + /* fall through */ + case V_038000_SQ_TEX_DIM_2D_MSAA: + array_check.nsamples = 1 << llevel; + llevel = 0; + break; + default: + dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); + return -EINVAL; + } + if (!r600_fmt_is_valid_texture(format, p->family)) { + dev_warn(p->dev, "%s:%d texture invalid format %d\n", + __func__, __LINE__, format); + return -EINVAL; + } + + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", + __func__, __LINE__, G_038000_TILE_MODE(word0)); + return -EINVAL; + } + + /* XXX check height as well... */ + + if (!IS_ALIGNED(pitch, pitch_align)) { + dev_warn(p->dev, "%s:%d tex pitch (%d, 0x%x, %d) invalid\n", + __func__, __LINE__, pitch, pitch_align, G_038000_TILE_MODE(word0)); + return -EINVAL; + } + if (!IS_ALIGNED(base_offset, base_align)) { + dev_warn(p->dev, "%s:%d tex base offset (0x%jx, 0x%jx, %d) invalid\n", + __func__, __LINE__, (uintmax_t)base_offset, (uintmax_t)base_align, G_038000_TILE_MODE(word0)); + return -EINVAL; + } + if (!IS_ALIGNED(mip_offset, base_align)) { + dev_warn(p->dev, "%s:%d tex mip offset (0x%jx, 0x%jx, %d) invalid\n", + __func__, __LINE__, (uintmax_t)mip_offset, (uintmax_t)base_align, G_038000_TILE_MODE(word0)); + return -EINVAL; + } + + if (blevel > llevel) { + dev_warn(p->dev, "texture blevel %d > llevel %d\n", + blevel, llevel); + } + if (is_array) { + barray = G_038014_BASE_ARRAY(word5); + larray = G_038014_LAST_ARRAY(word5); + + nfaces = larray - barray + 1; + } + r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format, + pitch_align, height_align, base_align, + &l0_size, &mipmap_size); + /* using get ib will give us the offset into the texture bo */ + if ((l0_size + word2) > radeon_bo_size(texture)) { + dev_warn(p->dev, "texture bo too small ((%d %d) (%d %d) %d %d %d -> %d have %ld)\n", + w0, h0, pitch_align, height_align, + array_check.array_mode, format, word2, + l0_size, radeon_bo_size(texture)); + dev_warn(p->dev, "alignments %d %d %d %jd\n", pitch, pitch_align, height_align, (uintmax_t)base_align); + return -EINVAL; + } + /* using get ib will give us the offset into the mipmap bo */ + if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { + /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", + w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ + } + return 0; +} + +static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 m, i; + + i = (reg >> 7); + if (i >= DRM_ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return true; + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + +static int r600_packet3_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) +{ + struct radeon_cs_reloc *reloc; + struct r600_cs_track *track; + volatile u32 *ib; + unsigned idx; + unsigned i; + unsigned start_reg, end_reg, reg; + int r; + u32 idx_value; + + track = (struct r600_cs_track *)p->track; + ib = p->ib.ptr; + idx = pkt->idx + 1; + idx_value = radeon_get_ib_value(p, idx); + + switch (pkt->opcode) { + case PACKET3_SET_PREDICATION: + { + int pred_op; + int tmp; + uint64_t offset; + + if (pkt->count != 1) { + DRM_ERROR("bad SET PREDICATION\n"); + return -EINVAL; + } + + tmp = radeon_get_ib_value(p, idx + 1); + pred_op = (tmp >> 16) & 0x7; + + /* for the clear predicate operation */ + if (pred_op == 0) + return 0; + + if (pred_op > 2) { + DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); + return -EINVAL; + } + + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET PREDICATION\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (idx_value & 0xfffffff0) + + ((u64)(tmp & 0xff) << 32); + + ib[idx + 0] = offset; + ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); + } + break; + + case PACKET3_START_3D_CMDBUF: + if (p->family >= CHIP_RV770 || pkt->count) { + DRM_ERROR("bad START_3D\n"); + return -EINVAL; + } + break; + case PACKET3_CONTEXT_CONTROL: + if (pkt->count != 1) { + DRM_ERROR("bad CONTEXT_CONTROL\n"); + return -EINVAL; + } + break; + case PACKET3_INDEX_TYPE: + case PACKET3_NUM_INSTANCES: + if (pkt->count) { + DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n"); + return -EINVAL; + } + break; + case PACKET3_DRAW_INDEX: + { + uint64_t offset; + if (pkt->count != 3) { + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; + } + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + idx_value + + ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); + + ib[idx+0] = offset; + ib[idx+1] = upper_32_bits(offset) & 0xff; + + r = r600_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + } + case PACKET3_DRAW_INDEX_AUTO: + if (pkt->count != 1) { + DRM_ERROR("bad DRAW_INDEX_AUTO\n"); + return -EINVAL; + } + r = r600_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); + return r; + } + break; + case PACKET3_DRAW_INDEX_IMMD_BE: + case PACKET3_DRAW_INDEX_IMMD: + if (pkt->count < 2) { + DRM_ERROR("bad DRAW_INDEX_IMMD\n"); + return -EINVAL; + } + r = r600_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; + case PACKET3_WAIT_REG_MEM: + if (pkt->count != 5) { + DRM_ERROR("bad WAIT_REG_MEM\n"); + return -EINVAL; + } + /* bit 4 is reg (0) or mem (1) */ + if (idx_value & 0x10) { + uint64_t offset; + + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad WAIT_REG_MEM\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffff0) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0); + ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_CP_DMA: + { + u32 command, size; + u64 offset, tmp; + if (pkt->count != 4) { + DRM_ERROR("bad CP DMA\n"); + return -EINVAL; + } + command = radeon_get_ib_value(p, idx+4); + size = command & 0x1fffff; + if (command & PACKET3_CP_DMA_CMD_SAS) { + /* src address space is register */ + DRM_ERROR("CP DMA SAS not supported\n"); + return -EINVAL; + } else { + if (command & PACKET3_CP_DMA_CMD_SAIC) { + DRM_ERROR("CP DMA SAIC only supported for registers\n"); + return -EINVAL; + } + /* src address space is memory */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad CP DMA SRC\n"); + return -EINVAL; + } + + tmp = radeon_get_ib_value(p, idx) + + ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); + + offset = reloc->lobj.gpu_offset + tmp; + + if ((tmp + size) > radeon_bo_size(reloc->robj)) { + dev_warn(p->dev, "CP DMA src buffer too small (%ju %lu)\n", + (uintmax_t)tmp + size, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + + ib[idx] = offset; + ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + } + if (command & PACKET3_CP_DMA_CMD_DAS) { + /* dst address space is register */ + DRM_ERROR("CP DMA DAS not supported\n"); + return -EINVAL; + } else { + /* dst address space is memory */ + if (command & PACKET3_CP_DMA_CMD_DAIC) { + DRM_ERROR("CP DMA DAIC only supported for registers\n"); + return -EINVAL; + } + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad CP DMA DST\n"); + return -EINVAL; + } + + tmp = radeon_get_ib_value(p, idx+2) + + ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32); + + offset = reloc->lobj.gpu_offset + tmp; + + if ((tmp + size) > radeon_bo_size(reloc->robj)) { + dev_warn(p->dev, "CP DMA dst buffer too small (%ju %lu)\n", + (uintmax_t)tmp + size, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + + ib[idx+2] = offset; + ib[idx+3] = upper_32_bits(offset) & 0xff; + } + break; + } + case PACKET3_SURFACE_SYNC: + if (pkt->count != 3) { + DRM_ERROR("bad SURFACE_SYNC\n"); + return -EINVAL; + } + /* 0xffffffff/0x0 is flush all cache flag */ + if (radeon_get_ib_value(p, idx + 1) != 0xffffffff || + radeon_get_ib_value(p, idx + 2) != 0) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SURFACE_SYNC\n"); + return -EINVAL; + } + ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + break; + case PACKET3_EVENT_WRITE: + if (pkt->count != 2 && pkt->count != 0) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } + if (pkt->count) { + uint64_t offset; + + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = offset & 0xfffffff8; + ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_EVENT_WRITE_EOP: + { + uint64_t offset; + + if (pkt->count != 4) { + DRM_ERROR("bad EVENT_WRITE_EOP\n"); + return -EINVAL; + } + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } + + offset = reloc->lobj.gpu_offset + + (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + + ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); + + ib[idx+1] = offset & 0xfffffffc; + ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + break; + } + case PACKET3_SET_CONFIG_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) || + (start_reg >= PACKET3_SET_CONFIG_REG_END) || + (end_reg >= PACKET3_SET_CONFIG_REG_END)) { + DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); + return -EINVAL; + } + for (i = 0; i < pkt->count; i++) { + reg = start_reg + (4 * i); + r = r600_cs_check_reg(p, reg, idx+1+i); + if (r) + return r; + } + break; + case PACKET3_SET_CONTEXT_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) || + (start_reg >= PACKET3_SET_CONTEXT_REG_END) || + (end_reg >= PACKET3_SET_CONTEXT_REG_END)) { + DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n"); + return -EINVAL; + } + for (i = 0; i < pkt->count; i++) { + reg = start_reg + (4 * i); + r = r600_cs_check_reg(p, reg, idx+1+i); + if (r) + return r; + } + break; + case PACKET3_SET_RESOURCE: + if (pkt->count % 7) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) || + (start_reg >= PACKET3_SET_RESOURCE_END) || + (end_reg >= PACKET3_SET_RESOURCE_END)) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + for (i = 0; i < (pkt->count / 7); i++) { + struct radeon_bo *texture, *mipmap; + u32 size, offset, base_offset, mip_offset; + + switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) { + case SQ_TEX_VTX_VALID_TEXTURE: + /* tex base */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + } + texture = reloc->robj; + /* tex mip base */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + mipmap = reloc->robj; + r = r600_check_texture_resource(p, idx+(i*7)+1, + texture, mipmap, + base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2), + mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3), + reloc->lobj.tiling_flags); + if (r) + return r; + ib[idx+1+(i*7)+2] += base_offset; + ib[idx+1+(i*7)+3] += mip_offset; + break; + case SQ_TEX_VTX_VALID_BUFFER: + { + uint64_t offset64; + /* vtx base */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1+(i*7)+0); + size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1; + if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { + /* force size to size of the buffer */ + dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n", + size + offset, radeon_bo_size(reloc->robj)); + ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj) - offset; + } + + offset64 = reloc->lobj.gpu_offset + offset; + ib[idx+1+(i*8)+0] = offset64; + ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | + (upper_32_bits(offset64) & 0xff); + break; + } + case SQ_TEX_VTX_INVALID_TEXTURE: + case SQ_TEX_VTX_INVALID_BUFFER: + default: + DRM_ERROR("bad SET_RESOURCE\n"); + return -EINVAL; + } + } + break; + case PACKET3_SET_ALU_CONST: + if (track->sq_config & DX9_CONSTS) { + start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) || + (start_reg >= PACKET3_SET_ALU_CONST_END) || + (end_reg >= PACKET3_SET_ALU_CONST_END)) { + DRM_ERROR("bad SET_ALU_CONST\n"); + return -EINVAL; + } + } + break; + case PACKET3_SET_BOOL_CONST: + start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) || + (start_reg >= PACKET3_SET_BOOL_CONST_END) || + (end_reg >= PACKET3_SET_BOOL_CONST_END)) { + DRM_ERROR("bad SET_BOOL_CONST\n"); + return -EINVAL; + } + break; + case PACKET3_SET_LOOP_CONST: + start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) || + (start_reg >= PACKET3_SET_LOOP_CONST_END) || + (end_reg >= PACKET3_SET_LOOP_CONST_END)) { + DRM_ERROR("bad SET_LOOP_CONST\n"); + return -EINVAL; + } + break; + case PACKET3_SET_CTL_CONST: + start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) || + (start_reg >= PACKET3_SET_CTL_CONST_END) || + (end_reg >= PACKET3_SET_CTL_CONST_END)) { + DRM_ERROR("bad SET_CTL_CONST\n"); + return -EINVAL; + } + break; + case PACKET3_SET_SAMPLER: + if (pkt->count % 3) { + DRM_ERROR("bad SET_SAMPLER\n"); + return -EINVAL; + } + start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) || + (start_reg >= PACKET3_SET_SAMPLER_END) || + (end_reg >= PACKET3_SET_SAMPLER_END)) { + DRM_ERROR("bad SET_SAMPLER\n"); + return -EINVAL; + } + break; + case PACKET3_STRMOUT_BASE_UPDATE: + /* RS780 and RS880 also need this */ + if (p->family < CHIP_RS780) { + DRM_ERROR("STRMOUT_BASE_UPDATE only supported on 7xx\n"); + return -EINVAL; + } + if (pkt->count != 1) { + DRM_ERROR("bad STRMOUT_BASE_UPDATE packet count\n"); + return -EINVAL; + } + if (idx_value > 3) { + DRM_ERROR("bad STRMOUT_BASE_UPDATE index\n"); + return -EINVAL; + } + { + u64 offset; + + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n"); + return -EINVAL; + } + + if (reloc->robj != track->vgt_strmout_bo[idx_value]) { + DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo does not match\n"); + return -EINVAL; + } + + offset = radeon_get_ib_value(p, idx+1) << 8; + if (offset != track->vgt_strmout_bo_offset[idx_value]) { + DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo offset does not match: 0x%jx, 0x%x\n", + (uintmax_t)offset, track->vgt_strmout_bo_offset[idx_value]); + return -EINVAL; + } + + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BASE_UPDATE bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + break; + case PACKET3_SURFACE_BASE_UPDATE: + if (p->family >= CHIP_RV770 || p->family == CHIP_R600) { + DRM_ERROR("bad SURFACE_BASE_UPDATE\n"); + return -EINVAL; + } + if (pkt->count) { + DRM_ERROR("bad SURFACE_BASE_UPDATE\n"); + return -EINVAL; + } + break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+1] = offset; + ib[idx+2] = upper_32_bits(offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+3] = offset; + ib[idx+4] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_MEM_WRITE: + { + u64 offset; + + if (pkt->count != 3) { + DRM_ERROR("bad MEM_WRITE (invalid count)\n"); + return -EINVAL; + } + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+0); + offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; + if (offset & 0x7) { + DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); + return -EINVAL; + } + if ((offset + 8) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad MEM_WRITE bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 8, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+0] = offset; + ib[idx+1] = upper_32_bits(offset) & 0xff; + break; + } + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+1] = offset; + ib[idx+2] = upper_32_bits(offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!r600_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%jx, 0x%lx\n", + (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + offset += reloc->lobj.gpu_offset; + ib[idx+3] = offset; + ib[idx+4] = upper_32_bits(offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!r600_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; + case PACKET3_NOP: + break; + default: + DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +int r600_cs_parse(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet pkt; + struct r600_cs_track *track; + int r; + + if (p->track == NULL) { + /* initialize tracker, we are in kms */ + track = malloc(sizeof(*track), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (track == NULL) + return -ENOMEM; + r600_cs_track_init(track); + if (p->rdev->family < CHIP_RV770) { + track->npipes = p->rdev->config.r600.tiling_npipes; + track->nbanks = p->rdev->config.r600.tiling_nbanks; + track->group_size = p->rdev->config.r600.tiling_group_size; + } else if (p->rdev->family <= CHIP_RV740) { + track->npipes = p->rdev->config.rv770.tiling_npipes; + track->nbanks = p->rdev->config.rv770.tiling_nbanks; + track->group_size = p->rdev->config.rv770.tiling_group_size; + } + p->track = track; + } + do { + r = r600_cs_packet_parse(p, &pkt, p->idx); + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + p->idx += pkt.count + 2; + switch (pkt.type) { + case PACKET_TYPE0: + r = r600_cs_parse_packet0(p, &pkt); + break; + case PACKET_TYPE2: + break; + case PACKET_TYPE3: + r = r600_packet3_check(p, &pkt); + break; + default: + DRM_ERROR("Unknown packet type %d !\n", pkt.type); + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return -EINVAL; + } + if (r) { + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return r; + } + } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); +#if 0 + for (r = 0; r < p->ib.length_dw; r++) { + DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]); + DRM_MDELAY(1); + } +#endif + free(p->track, DRM_MEM_DRIVER); + p->track = NULL; + return 0; +} + +static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p) +{ + if (p->chunk_relocs_idx == -1) { + return 0; + } + p->relocs = malloc(sizeof(struct radeon_cs_reloc), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (p->relocs == NULL) { + return -ENOMEM; + } + return 0; +} + +/** + * cs_parser_fini() - clean parser states + * @parser: parser structure holding parsing context. + * @error: error number + * + * If error is set than unvalidate buffer, otherwise just free memory + * used by parsing context. + **/ +static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error) +{ + unsigned i; + + free(parser->relocs, DRM_MEM_DRIVER); + for (i = 0; i < parser->nchunks; i++) { + free(parser->chunks[i].kdata, DRM_MEM_DRIVER); + if (parser->rdev && (parser->rdev->flags & RADEON_IS_AGP)) { + free(parser->chunks[i].kpage[0], DRM_MEM_DRIVER); + free(parser->chunks[i].kpage[1], DRM_MEM_DRIVER); + } + } + free(parser->chunks, DRM_MEM_DRIVER); + free(parser->chunks_array, DRM_MEM_DRIVER); + free(parser->track, DRM_MEM_DRIVER); +} + +int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, + unsigned family, u32 *ib, int *l) +{ + struct radeon_cs_parser parser; + struct radeon_cs_chunk *ib_chunk; + struct r600_cs_track *track; + int r; + + /* initialize tracker */ + track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (track == NULL) + return -ENOMEM; + r600_cs_track_init(track); + r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size); + /* initialize parser */ + memset(&parser, 0, sizeof(struct radeon_cs_parser)); + parser.filp = filp; + parser.dev = dev->device; + parser.rdev = NULL; + parser.family = family; + parser.track = track; + parser.ib.ptr = ib; + r = radeon_cs_parser_init(&parser, data); + if (r) { + DRM_ERROR("Failed to initialize parser !\n"); + r600_cs_parser_fini(&parser, r); + return r; + } + r = r600_cs_parser_relocs_legacy(&parser); + if (r) { + DRM_ERROR("Failed to parse relocation !\n"); + r600_cs_parser_fini(&parser, r); + return r; + } + /* Copy the packet into the IB, the parser will read from the + * input memory (cached) and write to the IB (which can be + * uncached). */ + ib_chunk = &parser.chunks[parser.chunk_ib_idx]; + parser.ib.length_dw = ib_chunk->length_dw; + *l = parser.ib.length_dw; + r = r600_cs_parse(&parser); + if (r) { + DRM_ERROR("Invalid command stream !\n"); + r600_cs_parser_fini(&parser, r); + return r; + } + r = radeon_cs_finish_pages(&parser); + if (r) { + DRM_ERROR("Invalid command stream !\n"); + r600_cs_parser_fini(&parser, r); + return r; + } + r600_cs_parser_fini(&parser, r); + return r; +} + +void r600_cs_legacy_init(void) +{ + r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm; +} + +/* + * DMA + */ +/** + * r600_dma_cs_next_reloc() - parse next reloc + * @p: parser structure holding parsing context. + * @cs_reloc: reloc informations + * + * Return the next reloc, do bo validation and compute + * GPU offset using the provided start. + **/ +int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc) +{ + struct radeon_cs_chunk *relocs_chunk; + unsigned idx; + + *cs_reloc = NULL; + if (p->chunk_relocs_idx == -1) { + DRM_ERROR("No relocation chunk !\n"); + return -EINVAL; + } + relocs_chunk = &p->chunks[p->chunk_relocs_idx]; + idx = p->dma_reloc_idx; + if (idx >= p->nrelocs) { + DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", + idx, p->nrelocs); + return -EINVAL; + } + *cs_reloc = p->relocs_ptr[idx]; + p->dma_reloc_idx++; + return 0; +} + +#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28) +#define GET_DMA_COUNT(h) ((h) & 0x0000ffff) +#define GET_DMA_T(h) (((h) & 0x00800000) >> 23) + +/** + * r600_dma_cs_parse() - parse the DMA IB + * @p: parser structure holding parsing context. + * + * Parses the DMA IB from the CS ioctl and updates + * the GPU addresses based on the reloc information and + * checks for errors. (R6xx-R7xx) + * Returns 0 for success and an error on failure. + **/ +int r600_dma_cs_parse(struct radeon_cs_parser *p) +{ + struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; + struct radeon_cs_reloc *src_reloc, *dst_reloc; + u32 header, cmd, count, tiled; + volatile u32 *ib = p->ib.ptr; + u32 idx, idx_value; + u64 src_offset, dst_offset; + int r; + + do { + if (p->idx >= ib_chunk->length_dw) { + DRM_ERROR("Can not parse packet at %d after CS end %d !\n", + p->idx, ib_chunk->length_dw); + return -EINVAL; + } + idx = p->idx; + header = radeon_get_ib_value(p, idx); + cmd = GET_DMA_CMD(header); + count = GET_DMA_COUNT(header); + tiled = GET_DMA_T(header); + + switch (cmd) { + case DMA_PACKET_WRITE: + r = r600_dma_cs_next_reloc(p, &dst_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_WRITE\n"); + return -EINVAL; + } + if (tiled) { + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + p->idx += count + 5; + } else { + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + p->idx += count + 3; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA write buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + break; + case DMA_PACKET_COPY: + r = r600_dma_cs_next_reloc(p, &src_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_COPY\n"); + return -EINVAL; + } + r = r600_dma_cs_next_reloc(p, &dst_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_COPY\n"); + return -EINVAL; + } + if (tiled) { + idx_value = radeon_get_ib_value(p, idx + 2); + /* detile bit */ + if (idx_value & (1 << 31)) { + /* tiled src, linear dst */ + src_offset = radeon_get_ib_value(p, idx+1); + src_offset <<= 8; + ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); + + dst_offset = radeon_get_ib_value(p, idx+5); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; + ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + } else { + /* linear src, tiled dst */ + src_offset = radeon_get_ib_value(p, idx+5); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; + ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset <<= 8; + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); + } + p->idx += 7; + } else { + if (p->family >= CHIP_RV770) { + src_offset = radeon_get_ib_value(p, idx+2); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; + ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + p->idx += 5; + } else { + src_offset = radeon_get_ib_value(p, idx+2); + src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16; + + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+3] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; + ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff) << 16; + p->idx += 4; + } + } + if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { + dev_warn(p->dev, "DMA copy src buffer too small (%ju %lu)\n", + (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); + return -EINVAL; + } + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA write dst buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + break; + case DMA_PACKET_CONSTANT_FILL: + if (p->family < CHIP_RV770) { + DRM_ERROR("Constant Fill is 7xx only !\n"); + return -EINVAL; + } + r = r600_dma_cs_next_reloc(p, &dst_reloc); + if (r) { + DRM_ERROR("bad DMA_PACKET_WRITE\n"); + return -EINVAL; + } + dst_offset = radeon_get_ib_value(p, idx+1); + dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; + if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { + dev_warn(p->dev, "DMA constant fill buffer too small (%ju %lu)\n", + (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); + ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000; + p->idx += 4; + break; + case DMA_PACKET_NOP: + p->idx += 1; + break; + default: + DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); + return -EINVAL; + } + } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); +#if 0 + for (r = 0; r < p->ib->length_dw; r++) { + DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]); + DRM_MDELAY(1); + } +#endif + return 0; +} diff --git a/sys/dev/drm2/radeon/r600_cs.h b/sys/dev/drm2/radeon/r600_cs.h new file mode 100644 index 00000000000..9db545e4c70 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_cs.h @@ -0,0 +1,11 @@ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __R600_CS_H__ +#define __R600_CS_H__ + +int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); + +#endif /* !defined(__R600_CS_H__) */ diff --git a/sys/dev/drm2/radeon/r600_hdmi.c b/sys/dev/drm2/radeon/r600_hdmi.c new file mode 100644 index 00000000000..46a72fbad0f --- /dev/null +++ b/sys/dev/drm2/radeon/r600_hdmi.c @@ -0,0 +1,589 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Christian König. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "r600d.h" +#include "atom.h" + +/* + * HDMI color format + */ +enum r600_hdmi_color_format { + RGB = 0, + YCC_422 = 1, + YCC_444 = 2 +}; + +/* + * IEC60958 status bits + */ +enum r600_hdmi_iec_status_bits { + AUDIO_STATUS_DIG_ENABLE = 0x01, + AUDIO_STATUS_V = 0x02, + AUDIO_STATUS_VCFG = 0x04, + AUDIO_STATUS_EMPHASIS = 0x08, + AUDIO_STATUS_COPYRIGHT = 0x10, + AUDIO_STATUS_NONAUDIO = 0x20, + AUDIO_STATUS_PROFESSIONAL = 0x40, + AUDIO_STATUS_LEVEL = 0x80 +}; + +static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + /* 32kHz 44.1kHz 48kHz */ + /* Clock N CTS N CTS N CTS */ + { 25174, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ + { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ + { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ + { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ + { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ + { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ + { 74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ + { 148351, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ + { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ +}; + +/* + * calculate CTS value if it's not found in the table + */ +static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) +{ + if (*CTS == 0) + *CTS = clock * N / (128 * freq) * 1000; + DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", + N, *CTS, freq); +} + +struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) +{ + struct radeon_hdmi_acr res; + u8 i; + + for (i = 0; r600_hdmi_predefined_acr[i].clock != clock && + r600_hdmi_predefined_acr[i].clock != 0; i++) + ; + res = r600_hdmi_predefined_acr[i]; + + /* In case some CTS are missing */ + r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000); + r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100); + r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000); + + return res; +} + +/* + * update the N and CTS parameters for a given pixel clock rate + */ +static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + + WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz)); + WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz); + + WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz)); + WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz); + + WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz)); + WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz); +} + +/* + * calculate the crc for a given info frame + */ +static void r600_hdmi_infoframe_checksum(uint8_t packetType, + uint8_t versionNumber, + uint8_t length, + uint8_t *frame) +{ + int i; + frame[0] = packetType + versionNumber + length; + for (i = 1; i <= length; i++) + frame[0] += frame[i]; + frame[0] = 0x100 - frame[0]; +} + +/* + * build a HDMI Video Info Frame + */ +static void r600_hdmi_videoinfoframe( + struct drm_encoder *encoder, + enum r600_hdmi_color_format color_format, + int active_information_present, + uint8_t active_format_aspect_ratio, + uint8_t scan_information, + uint8_t colorimetry, + uint8_t ex_colorimetry, + uint8_t quantization, + int ITC, + uint8_t picture_aspect_ratio, + uint8_t video_format_identification, + uint8_t pixel_repetition, + uint8_t non_uniform_picture_scaling, + uint8_t bar_info_data_valid, + uint16_t top_bar, + uint16_t bottom_bar, + uint16_t left_bar, + uint16_t right_bar +) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + + uint8_t frame[14]; + + frame[0x0] = 0; + frame[0x1] = + (scan_information & 0x3) | + ((bar_info_data_valid & 0x3) << 2) | + ((active_information_present & 0x1) << 4) | + ((color_format & 0x3) << 5); + frame[0x2] = + (active_format_aspect_ratio & 0xF) | + ((picture_aspect_ratio & 0x3) << 4) | + ((colorimetry & 0x3) << 6); + frame[0x3] = + (non_uniform_picture_scaling & 0x3) | + ((quantization & 0x3) << 2) | + ((ex_colorimetry & 0x7) << 4) | + ((ITC & 0x1) << 7); + frame[0x4] = (video_format_identification & 0x7F); + frame[0x5] = (pixel_repetition & 0xF); + frame[0x6] = (top_bar & 0xFF); + frame[0x7] = (top_bar >> 8); + frame[0x8] = (bottom_bar & 0xFF); + frame[0x9] = (bottom_bar >> 8); + frame[0xA] = (left_bar & 0xFF); + frame[0xB] = (left_bar >> 8); + frame[0xC] = (right_bar & 0xFF); + frame[0xD] = (right_bar >> 8); + + r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame); + /* Our header values (type, version, length) should be alright, Intel + * is using the same. Checksum function also seems to be OK, it works + * fine for audio infoframe. However calculated value is always lower + * by 2 in comparison to fglrx. It breaks displaying anything in case + * of TVs that strictly check the checksum. Hack it manually here to + * workaround this issue. */ + frame[0x0] += 2; + + WREG32(HDMI0_AVI_INFO0 + offset, + frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); + WREG32(HDMI0_AVI_INFO1 + offset, + frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); + WREG32(HDMI0_AVI_INFO2 + offset, + frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); + WREG32(HDMI0_AVI_INFO3 + offset, + frame[0xC] | (frame[0xD] << 8)); +} + +/* + * build a Audio Info Frame + */ +static void r600_hdmi_audioinfoframe( + struct drm_encoder *encoder, + uint8_t channel_count, + uint8_t coding_type, + uint8_t sample_size, + uint8_t sample_frequency, + uint8_t format, + uint8_t channel_allocation, + uint8_t level_shift, + int downmix_inhibit +) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + + uint8_t frame[11]; + + frame[0x0] = 0; + frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4); + frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2); + frame[0x3] = format; + frame[0x4] = channel_allocation; + frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7); + frame[0x6] = 0; + frame[0x7] = 0; + frame[0x8] = 0; + frame[0x9] = 0; + frame[0xA] = 0; + + r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame); + + WREG32(HDMI0_AUDIO_INFO0 + offset, + frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); + WREG32(HDMI0_AUDIO_INFO1 + offset, + frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24)); +} + +/* + * test if audio buffer is filled enough to start playing + */ +static bool r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + + return (RREG32(HDMI0_STATUS + offset) & 0x10) != 0; +} + +/* + * have buffer status changed since last call? + */ +int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + int status, result; + + if (!dig->afmt || !dig->afmt->enabled) + return 0; + + status = r600_hdmi_is_audio_buffer_filled(encoder); + result = dig->afmt->last_buffer_filled_status != status; + dig->afmt->last_buffer_filled_status = status; + + return result; +} + +/* + * write the audio workaround status to the hardware + */ +static void r600_hdmi_audio_workaround(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset = dig->afmt->offset; + bool hdmi_audio_workaround = false; /* FIXME */ + u32 value; + + if (!hdmi_audio_workaround || + r600_hdmi_is_audio_buffer_filled(encoder)) + value = 0; /* disable workaround */ + else + value = HDMI0_AUDIO_TEST_EN; /* enable workaround */ + WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, + value, ~HDMI0_AUDIO_TEST_EN); +} + + +/* + * update the info frames with the data from the current display mode + */ +void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset; + + /* Silent, r600_hdmi_enable will raise WARN for us */ + if (!dig->afmt->enabled) + return; + offset = dig->afmt->offset; + + r600_audio_set_clock(encoder, mode->clock); + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, + HDMI0_NULL_SEND); /* send null packets when required */ + + WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000); + + if (ASIC_IS_DCE32(rdev)) { + WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, + HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ + WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, + AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ + AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ + } else { + WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, + HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ + HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ + HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ + } + + WREG32(HDMI0_ACR_PACKET_CONTROL + offset, + HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ + HDMI0_ACR_SOURCE); /* select SW CTS value */ + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, + HDMI0_NULL_SEND | /* send null packets when required */ + HDMI0_GC_SEND | /* send general control packets */ + HDMI0_GC_CONT); /* send general control packets every frame */ + + /* TODO: HDMI0_AUDIO_INFO_UPDATE */ + WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, + HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ + HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ + HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ + HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */ + + WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, + HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ + HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */ + + WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */ + + r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + r600_hdmi_update_ACR(encoder, mode->clock); + + /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ + WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); + WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); + WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); + WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); + + r600_hdmi_audio_workaround(encoder); +} + +/* + * update settings with current parameters from audio engine + */ +void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct r600_audio audio = r600_audio_status(rdev); + uint32_t offset; + uint32_t iec; + + if (!dig->afmt || !dig->afmt->enabled) + return; + offset = dig->afmt->offset; + + DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n", + r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped", + audio.channels, audio.rate, audio.bits_per_sample); + DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n", + (int)audio.status_bits, (int)audio.category_code); + + iec = 0; + if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL) + iec |= 1 << 0; + if (audio.status_bits & AUDIO_STATUS_NONAUDIO) + iec |= 1 << 1; + if (audio.status_bits & AUDIO_STATUS_COPYRIGHT) + iec |= 1 << 2; + if (audio.status_bits & AUDIO_STATUS_EMPHASIS) + iec |= 1 << 3; + + iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code); + + switch (audio.rate) { + case 32000: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3); + break; + case 44100: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0); + break; + case 48000: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2); + break; + case 88200: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8); + break; + case 96000: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa); + break; + case 176400: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc); + break; + case 192000: + iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe); + break; + } + + WREG32(HDMI0_60958_0 + offset, iec); + + iec = 0; + switch (audio.bits_per_sample) { + case 16: + iec |= HDMI0_60958_CS_WORD_LENGTH(0x2); + break; + case 20: + iec |= HDMI0_60958_CS_WORD_LENGTH(0x3); + break; + case 24: + iec |= HDMI0_60958_CS_WORD_LENGTH(0xb); + break; + } + if (audio.status_bits & AUDIO_STATUS_V) + iec |= 0x5 << 16; + WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f); + + r600_hdmi_audioinfoframe(encoder, audio.channels - 1, 0, 0, 0, 0, 0, 0, + 0); + + r600_hdmi_audio_workaround(encoder); +} + +/* + * enable the HDMI engine + */ +void r600_hdmi_enable(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset; + u32 hdmi; + + if (ASIC_IS_DCE6(rdev)) + return; + + /* Silent, r600_hdmi_enable will raise WARN for us */ + if (dig->afmt->enabled) + return; + offset = dig->afmt->offset; + + /* Older chipsets require setting HDMI and routing manually */ + if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { + hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE; + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN, + ~AVIVO_TMDSA_CNTL_HDMI_EN); + hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN, + ~AVIVO_LVTMA_CNTL_HDMI_EN); + hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA); + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + WREG32_P(DDIA_CNTL, DDIA_HDMI_EN, ~DDIA_HDMI_EN); + hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA); + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA); + break; + default: + dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n", + radeon_encoder->encoder_id); + break; + } + WREG32(HDMI0_CONTROL + offset, hdmi); + } + + if (rdev->irq.installed) { + /* if irq is available use it */ + radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); + } + + dig->afmt->enabled = true; + + DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", + offset, radeon_encoder->encoder_id); +} + +/* + * disable the HDMI engine + */ +void r600_hdmi_disable(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t offset; + + if (ASIC_IS_DCE6(rdev)) + return; + + /* Called for ATOM_ENCODER_MODE_HDMI only */ + if (!dig || !dig->afmt) { + DRM_ERROR("%s: !dig || !dig->afmt", __func__); + return; + } + if (!dig->afmt->enabled) + return; + offset = dig->afmt->offset; + + DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", + offset, radeon_encoder->encoder_id); + + /* disable irq */ + radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); + + /* Older chipsets not handled by AtomBIOS */ + if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + WREG32_P(AVIVO_TMDSA_CNTL, 0, + ~AVIVO_TMDSA_CNTL_HDMI_EN); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + WREG32_P(AVIVO_LVTMA_CNTL, 0, + ~AVIVO_LVTMA_CNTL_HDMI_EN); + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + WREG32_P(DDIA_CNTL, 0, ~DDIA_HDMI_EN); + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + break; + default: + dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n", + radeon_encoder->encoder_id); + break; + } + WREG32(HDMI0_CONTROL + offset, HDMI0_ERROR_ACK); + } + + dig->afmt->enabled = false; +} diff --git a/sys/dev/drm2/radeon/r600_reg.h b/sys/dev/drm2/radeon/r600_reg.h new file mode 100644 index 00000000000..e0578cc3e75 --- /dev/null +++ b/sys/dev/drm2/radeon/r600_reg.h @@ -0,0 +1,177 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __R600_REG_H__ +#define __R600_REG_H__ + +#include +__FBSDID("$FreeBSD$"); + +#define R600_PCIE_PORT_INDEX 0x0038 +#define R600_PCIE_PORT_DATA 0x003c + +#define R600_MC_VM_FB_LOCATION 0x2180 +#define R600_MC_FB_BASE_MASK 0x0000FFFF +#define R600_MC_FB_BASE_SHIFT 0 +#define R600_MC_FB_TOP_MASK 0xFFFF0000 +#define R600_MC_FB_TOP_SHIFT 16 +#define R600_MC_VM_AGP_TOP 0x2184 +#define R600_MC_AGP_TOP_MASK 0x0003FFFF +#define R600_MC_AGP_TOP_SHIFT 0 +#define R600_MC_VM_AGP_BOT 0x2188 +#define R600_MC_AGP_BOT_MASK 0x0003FFFF +#define R600_MC_AGP_BOT_SHIFT 0 +#define R600_MC_VM_AGP_BASE 0x218c +#define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190 +#define R600_LOGICAL_PAGE_NUMBER_MASK 0x000FFFFF +#define R600_LOGICAL_PAGE_NUMBER_SHIFT 0 +#define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194 +#define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198 + +#define R700_MC_VM_FB_LOCATION 0x2024 +#define R700_MC_FB_BASE_MASK 0x0000FFFF +#define R700_MC_FB_BASE_SHIFT 0 +#define R700_MC_FB_TOP_MASK 0xFFFF0000 +#define R700_MC_FB_TOP_SHIFT 16 +#define R700_MC_VM_AGP_TOP 0x2028 +#define R700_MC_AGP_TOP_MASK 0x0003FFFF +#define R700_MC_AGP_TOP_SHIFT 0 +#define R700_MC_VM_AGP_BOT 0x202c +#define R700_MC_AGP_BOT_MASK 0x0003FFFF +#define R700_MC_AGP_BOT_SHIFT 0 +#define R700_MC_VM_AGP_BASE 0x2030 +#define R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 +#define R700_LOGICAL_PAGE_NUMBER_MASK 0x000FFFFF +#define R700_LOGICAL_PAGE_NUMBER_SHIFT 0 +#define R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 +#define R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203c + +#define R600_RAMCFG 0x2408 +# define R600_CHANSIZE (1 << 7) +# define R600_CHANSIZE_OVERRIDE (1 << 10) + + +#define R600_GENERAL_PWRMGT 0x618 +# define R600_OPEN_DRAIN_PADS (1 << 11) + +#define R600_LOWER_GPIO_ENABLE 0x710 +#define R600_CTXSW_VID_LOWER_GPIO_CNTL 0x718 +#define R600_HIGH_VID_LOWER_GPIO_CNTL 0x71c +#define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x720 +#define R600_LOW_VID_LOWER_GPIO_CNTL 0x724 + +#define R600_D1GRPH_SWAP_CONTROL 0x610C +# define R600_D1GRPH_SWAP_ENDIAN_NONE (0 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_16BIT (1 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_32BIT (2 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0) + +#define R600_HDP_NONSURFACE_BASE 0x2c04 + +#define R600_BUS_CNTL 0x5420 +# define R600_BIOS_ROM_DIS (1 << 1) +#define R600_CONFIG_CNTL 0x5424 +#define R600_CONFIG_MEMSIZE 0x5428 +#define R600_CONFIG_F0_BASE 0x542C +#define R600_CONFIG_APER_SIZE 0x5430 + +#define R600_BIF_FB_EN 0x5490 +#define R600_FB_READ_EN (1 << 0) +#define R600_FB_WRITE_EN (1 << 1) + +#define R600_CITF_CNTL 0x200c +#define R600_BLACKOUT_MASK 0x00000003 + +#define R700_MC_CITF_CNTL 0x25c0 + +#define R600_ROM_CNTL 0x1600 +# define R600_SCK_OVERWRITE (1 << 1) +# define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28 +# define R600_SCK_PRESCALE_CRYSTAL_CLK_MASK (0xf << 28) + +#define R600_CG_SPLL_FUNC_CNTL 0x600 +# define R600_SPLL_BYPASS_EN (1 << 3) +#define R600_CG_SPLL_STATUS 0x60c +# define R600_SPLL_CHG_STATUS (1 << 1) + +#define R600_BIOS_0_SCRATCH 0x1724 +#define R600_BIOS_1_SCRATCH 0x1728 +#define R600_BIOS_2_SCRATCH 0x172c +#define R600_BIOS_3_SCRATCH 0x1730 +#define R600_BIOS_4_SCRATCH 0x1734 +#define R600_BIOS_5_SCRATCH 0x1738 +#define R600_BIOS_6_SCRATCH 0x173c +#define R600_BIOS_7_SCRATCH 0x1740 + +/* Audio, these regs were reverse enginered, + * so the chance is high that the naming is wrong + * R6xx+ ??? */ + +/* Audio clocks */ +#define R600_AUDIO_PLL1_MUL 0x0514 +#define R600_AUDIO_PLL1_DIV 0x0518 +#define R600_AUDIO_PLL2_MUL 0x0524 +#define R600_AUDIO_PLL2_DIV 0x0528 +#define R600_AUDIO_CLK_SRCSEL 0x0534 + +/* Audio general */ +#define R600_AUDIO_ENABLE 0x7300 +#define R600_AUDIO_TIMING 0x7344 + +/* Audio params */ +#define R600_AUDIO_VENDOR_ID 0x7380 +#define R600_AUDIO_REVISION_ID 0x7384 +#define R600_AUDIO_ROOT_NODE_COUNT 0x7388 +#define R600_AUDIO_NID1_NODE_COUNT 0x738c +#define R600_AUDIO_NID1_TYPE 0x7390 +#define R600_AUDIO_SUPPORTED_SIZE_RATE 0x7394 +#define R600_AUDIO_SUPPORTED_CODEC 0x7398 +#define R600_AUDIO_SUPPORTED_POWER_STATES 0x739c +#define R600_AUDIO_NID2_CAPS 0x73a0 +#define R600_AUDIO_NID3_CAPS 0x73a4 +#define R600_AUDIO_NID3_PIN_CAPS 0x73a8 + +/* Audio conn list */ +#define R600_AUDIO_CONN_LIST_LEN 0x73ac +#define R600_AUDIO_CONN_LIST 0x73b0 + +/* Audio verbs */ +#define R600_AUDIO_RATE_BPS_CHANNEL 0x73c0 +#define R600_AUDIO_PLAYING 0x73c4 +#define R600_AUDIO_IMPLEMENTATION_ID 0x73c8 +#define R600_AUDIO_CONFIG_DEFAULT 0x73cc +#define R600_AUDIO_PIN_SENSE 0x73d0 +#define R600_AUDIO_PIN_WIDGET_CNTL 0x73d4 +#define R600_AUDIO_STATUS_BITS 0x73d8 + +#define DCE2_HDMI_OFFSET0 (0x7400 - 0x7400) +#define DCE2_HDMI_OFFSET1 (0x7700 - 0x7400) +/* DCE3.2 second instance starts at 0x7800 */ +#define DCE3_HDMI_OFFSET0 (0x7400 - 0x7400) +#define DCE3_HDMI_OFFSET1 (0x7800 - 0x7400) + +#endif diff --git a/sys/dev/drm2/radeon/r600_reg_safe.h b/sys/dev/drm2/radeon/r600_reg_safe.h new file mode 100644 index 00000000000..003a40ded4d --- /dev/null +++ b/sys/dev/drm2/radeon/r600_reg_safe.h @@ -0,0 +1,493 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned r600_reg_safe_bm[1952] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFEFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFEF, 0xFFFFFFFF, 0xCFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFBD1EFFF, 0xCF3FFFFF, 0xFFFFFFFF, + 0xFFFFFFDF, 0xFFFFFFFF, 0xFFF0FEEF, 0xEFFFFFFF, + 0xFFFFFFC1, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF7, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFDF, 0xFFFFFFFF, 0xFFFF7FFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFF0, 0xFFFFFFFB, 0xFFFFFFFF, + 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFDE, 0xFFFFFFFF, + 0xFFFFAFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFF00, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFF00, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFF00, 0xFFFFFFFF, + 0xFFFC0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFC3FF, 0xFFFFFFFF, 0x0000F0FF, 0x00000000, + 0x000CE000, 0x00000000, 0xFFD00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFF8000, + 0x0001801F, 0xFC000000, 0xFFFFFFFF, 0xFFFFFE00, + 0x7BCFFE05, 0xFE07FDEF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xF7E20000, 0xDDDF9CDD, 0xFFFFE3FD, 0xFFFFFFFF, + 0xFFFB0E02, 0xFFFFFFFF, 0xFFFDC3E7, 0x3FFFFFFF, + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xDFFFFFFF, +}; diff --git a/sys/dev/drm2/radeon/r600d.h b/sys/dev/drm2/radeon/r600d.h new file mode 100644 index 00000000000..41cc7c6dd89 --- /dev/null +++ b/sys/dev/drm2/radeon/r600d.h @@ -0,0 +1,1932 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef R600D_H +#define R600D_H + +#include +__FBSDID("$FreeBSD$"); + +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) + +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) + +#define R6XX_MAX_SH_GPRS 256 +#define R6XX_MAX_TEMP_GPRS 16 +#define R6XX_MAX_SH_THREADS 256 +#define R6XX_MAX_SH_STACK_ENTRIES 4096 +#define R6XX_MAX_BACKENDS 8 +#define R6XX_MAX_BACKENDS_MASK 0xff +#define R6XX_MAX_SIMDS 8 +#define R6XX_MAX_SIMDS_MASK 0xff +#define R6XX_MAX_PIPES 8 +#define R6XX_MAX_PIPES_MASK 0xff + +/* PTE flags */ +#define PTE_VALID (1 << 0) +#define PTE_SYSTEM (1 << 1) +#define PTE_SNOOPED (1 << 2) +#define PTE_READABLE (1 << 5) +#define PTE_WRITEABLE (1 << 6) + +/* tiling bits */ +#define ARRAY_LINEAR_GENERAL 0x00000000 +#define ARRAY_LINEAR_ALIGNED 0x00000001 +#define ARRAY_1D_TILED_THIN1 0x00000002 +#define ARRAY_2D_TILED_THIN1 0x00000004 + +/* Registers */ +#define ARB_POP 0x2418 +#define ENABLE_TC128 (1 << 30) +#define ARB_GDEC_RD_CNTL 0x246C + +#define CC_GC_SHADER_PIPE_CONFIG 0x8950 +#define CC_RB_BACKEND_DISABLE 0x98F4 +#define BACKEND_DISABLE(x) ((x) << 16) + +#define R_028808_CB_COLOR_CONTROL 0x28808 +#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4) +#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7) +#define C_028808_SPECIAL_OP 0xFFFFFF8F +#define V_028808_SPECIAL_NORMAL 0x00 +#define V_028808_SPECIAL_DISABLE 0x01 +#define V_028808_SPECIAL_RESOLVE_BOX 0x07 + +#define CB_COLOR0_BASE 0x28040 +#define CB_COLOR1_BASE 0x28044 +#define CB_COLOR2_BASE 0x28048 +#define CB_COLOR3_BASE 0x2804C +#define CB_COLOR4_BASE 0x28050 +#define CB_COLOR5_BASE 0x28054 +#define CB_COLOR6_BASE 0x28058 +#define CB_COLOR7_BASE 0x2805C +#define CB_COLOR7_FRAG 0x280FC + +#define CB_COLOR0_SIZE 0x28060 +#define CB_COLOR0_VIEW 0x28080 +#define R_028080_CB_COLOR0_VIEW 0x028080 +#define S_028080_SLICE_START(x) (((x) & 0x7FF) << 0) +#define G_028080_SLICE_START(x) (((x) >> 0) & 0x7FF) +#define C_028080_SLICE_START 0xFFFFF800 +#define S_028080_SLICE_MAX(x) (((x) & 0x7FF) << 13) +#define G_028080_SLICE_MAX(x) (((x) >> 13) & 0x7FF) +#define C_028080_SLICE_MAX 0xFF001FFF +#define R_028084_CB_COLOR1_VIEW 0x028084 +#define R_028088_CB_COLOR2_VIEW 0x028088 +#define R_02808C_CB_COLOR3_VIEW 0x02808C +#define R_028090_CB_COLOR4_VIEW 0x028090 +#define R_028094_CB_COLOR5_VIEW 0x028094 +#define R_028098_CB_COLOR6_VIEW 0x028098 +#define R_02809C_CB_COLOR7_VIEW 0x02809C +#define R_028100_CB_COLOR0_MASK 0x028100 +#define S_028100_CMASK_BLOCK_MAX(x) (((x) & 0xFFF) << 0) +#define G_028100_CMASK_BLOCK_MAX(x) (((x) >> 0) & 0xFFF) +#define C_028100_CMASK_BLOCK_MAX 0xFFFFF000 +#define S_028100_FMASK_TILE_MAX(x) (((x) & 0xFFFFF) << 12) +#define G_028100_FMASK_TILE_MAX(x) (((x) >> 12) & 0xFFFFF) +#define C_028100_FMASK_TILE_MAX 0x00000FFF +#define R_028104_CB_COLOR1_MASK 0x028104 +#define R_028108_CB_COLOR2_MASK 0x028108 +#define R_02810C_CB_COLOR3_MASK 0x02810C +#define R_028110_CB_COLOR4_MASK 0x028110 +#define R_028114_CB_COLOR5_MASK 0x028114 +#define R_028118_CB_COLOR6_MASK 0x028118 +#define R_02811C_CB_COLOR7_MASK 0x02811C +#define CB_COLOR0_INFO 0x280a0 +# define CB_FORMAT(x) ((x) << 2) +# define CB_ARRAY_MODE(x) ((x) << 8) +# define CB_SOURCE_FORMAT(x) ((x) << 27) +# define CB_SF_EXPORT_FULL 0 +# define CB_SF_EXPORT_NORM 1 +#define CB_COLOR0_TILE 0x280c0 +#define CB_COLOR0_FRAG 0x280e0 +#define CB_COLOR0_MASK 0x28100 + +#define SQ_ALU_CONST_CACHE_PS_0 0x28940 +#define SQ_ALU_CONST_CACHE_PS_1 0x28944 +#define SQ_ALU_CONST_CACHE_PS_2 0x28948 +#define SQ_ALU_CONST_CACHE_PS_3 0x2894c +#define SQ_ALU_CONST_CACHE_PS_4 0x28950 +#define SQ_ALU_CONST_CACHE_PS_5 0x28954 +#define SQ_ALU_CONST_CACHE_PS_6 0x28958 +#define SQ_ALU_CONST_CACHE_PS_7 0x2895c +#define SQ_ALU_CONST_CACHE_PS_8 0x28960 +#define SQ_ALU_CONST_CACHE_PS_9 0x28964 +#define SQ_ALU_CONST_CACHE_PS_10 0x28968 +#define SQ_ALU_CONST_CACHE_PS_11 0x2896c +#define SQ_ALU_CONST_CACHE_PS_12 0x28970 +#define SQ_ALU_CONST_CACHE_PS_13 0x28974 +#define SQ_ALU_CONST_CACHE_PS_14 0x28978 +#define SQ_ALU_CONST_CACHE_PS_15 0x2897c +#define SQ_ALU_CONST_CACHE_VS_0 0x28980 +#define SQ_ALU_CONST_CACHE_VS_1 0x28984 +#define SQ_ALU_CONST_CACHE_VS_2 0x28988 +#define SQ_ALU_CONST_CACHE_VS_3 0x2898c +#define SQ_ALU_CONST_CACHE_VS_4 0x28990 +#define SQ_ALU_CONST_CACHE_VS_5 0x28994 +#define SQ_ALU_CONST_CACHE_VS_6 0x28998 +#define SQ_ALU_CONST_CACHE_VS_7 0x2899c +#define SQ_ALU_CONST_CACHE_VS_8 0x289a0 +#define SQ_ALU_CONST_CACHE_VS_9 0x289a4 +#define SQ_ALU_CONST_CACHE_VS_10 0x289a8 +#define SQ_ALU_CONST_CACHE_VS_11 0x289ac +#define SQ_ALU_CONST_CACHE_VS_12 0x289b0 +#define SQ_ALU_CONST_CACHE_VS_13 0x289b4 +#define SQ_ALU_CONST_CACHE_VS_14 0x289b8 +#define SQ_ALU_CONST_CACHE_VS_15 0x289bc +#define SQ_ALU_CONST_CACHE_GS_0 0x289c0 +#define SQ_ALU_CONST_CACHE_GS_1 0x289c4 +#define SQ_ALU_CONST_CACHE_GS_2 0x289c8 +#define SQ_ALU_CONST_CACHE_GS_3 0x289cc +#define SQ_ALU_CONST_CACHE_GS_4 0x289d0 +#define SQ_ALU_CONST_CACHE_GS_5 0x289d4 +#define SQ_ALU_CONST_CACHE_GS_6 0x289d8 +#define SQ_ALU_CONST_CACHE_GS_7 0x289dc +#define SQ_ALU_CONST_CACHE_GS_8 0x289e0 +#define SQ_ALU_CONST_CACHE_GS_9 0x289e4 +#define SQ_ALU_CONST_CACHE_GS_10 0x289e8 +#define SQ_ALU_CONST_CACHE_GS_11 0x289ec +#define SQ_ALU_CONST_CACHE_GS_12 0x289f0 +#define SQ_ALU_CONST_CACHE_GS_13 0x289f4 +#define SQ_ALU_CONST_CACHE_GS_14 0x289f8 +#define SQ_ALU_CONST_CACHE_GS_15 0x289fc + +#define CONFIG_MEMSIZE 0x5428 +#define CONFIG_CNTL 0x5424 +#define CP_STALLED_STAT1 0x8674 +#define CP_STALLED_STAT2 0x8678 +#define CP_BUSY_STAT 0x867C +#define CP_STAT 0x8680 +#define CP_COHER_BASE 0x85F8 +#define CP_DEBUG 0xC1FC +#define R_0086D8_CP_ME_CNTL 0x86D8 +#define S_0086D8_CP_ME_HALT(x) (((x) & 1)<<28) +#define C_0086D8_CP_ME_HALT(x) ((x) & 0xEFFFFFFF) +#define CP_ME_RAM_DATA 0xC160 +#define CP_ME_RAM_RADDR 0xC158 +#define CP_ME_RAM_WADDR 0xC15C +#define CP_MEQ_THRESHOLDS 0x8764 +#define MEQ_END(x) ((x) << 16) +#define ROQ_END(x) ((x) << 24) +#define CP_PERFMON_CNTL 0x87FC +#define CP_PFP_UCODE_ADDR 0xC150 +#define CP_PFP_UCODE_DATA 0xC154 +#define CP_QUEUE_THRESHOLDS 0x8760 +#define ROQ_IB1_START(x) ((x) << 0) +#define ROQ_IB2_START(x) ((x) << 8) +#define CP_RB_BASE 0xC100 +#define CP_RB_CNTL 0xC104 +#define RB_BUFSZ(x) ((x) << 0) +#define RB_BLKSZ(x) ((x) << 8) +#define RB_NO_UPDATE (1 << 27) +#define RB_RPTR_WR_ENA (1 << 31) +#define BUF_SWAP_32BIT (2 << 16) +#define CP_RB_RPTR 0x8700 +#define CP_RB_RPTR_ADDR 0xC10C +#define RB_RPTR_SWAP(x) ((x) << 0) +#define CP_RB_RPTR_ADDR_HI 0xC110 +#define CP_RB_RPTR_WR 0xC108 +#define CP_RB_WPTR 0xC114 +#define CP_RB_WPTR_ADDR 0xC118 +#define CP_RB_WPTR_ADDR_HI 0xC11C +#define CP_RB_WPTR_DELAY 0x8704 +#define CP_ROQ_IB1_STAT 0x8784 +#define CP_ROQ_IB2_STAT 0x8788 +#define CP_SEM_WAIT_TIMER 0x85BC + +#define DB_DEBUG 0x9830 +#define PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31) +#define DB_DEPTH_BASE 0x2800C +#define DB_HTILE_DATA_BASE 0x28014 +#define DB_HTILE_SURFACE 0x28D24 +#define S_028D24_HTILE_WIDTH(x) (((x) & 0x1) << 0) +#define G_028D24_HTILE_WIDTH(x) (((x) >> 0) & 0x1) +#define C_028D24_HTILE_WIDTH 0xFFFFFFFE +#define S_028D24_HTILE_HEIGHT(x) (((x) & 0x1) << 1) +#define G_028D24_HTILE_HEIGHT(x) (((x) >> 1) & 0x1) +#define C_028D24_HTILE_HEIGHT 0xFFFFFFFD +#define G_028D24_LINEAR(x) (((x) >> 2) & 0x1) +#define DB_WATERMARKS 0x9838 +#define DEPTH_FREE(x) ((x) << 0) +#define DEPTH_FLUSH(x) ((x) << 5) +#define DEPTH_PENDING_FREE(x) ((x) << 15) +#define DEPTH_CACHELINE_FREE(x) ((x) << 20) + +#define DCP_TILING_CONFIG 0x6CA0 +#define PIPE_TILING(x) ((x) << 1) +#define BANK_TILING(x) ((x) << 4) +#define GROUP_SIZE(x) ((x) << 6) +#define ROW_TILING(x) ((x) << 8) +#define BANK_SWAPS(x) ((x) << 11) +#define SAMPLE_SPLIT(x) ((x) << 14) +#define BACKEND_MAP(x) ((x) << 16) + +#define GB_TILING_CONFIG 0x98F0 +#define PIPE_TILING__SHIFT 1 +#define PIPE_TILING__MASK 0x0000000e + +#define GC_USER_SHADER_PIPE_CONFIG 0x8954 +#define INACTIVE_QD_PIPES(x) ((x) << 8) +#define INACTIVE_QD_PIPES_MASK 0x0000FF00 +#define INACTIVE_SIMDS(x) ((x) << 16) +#define INACTIVE_SIMDS_MASK 0x00FF0000 + +#define SQ_CONFIG 0x8c00 +# define VC_ENABLE (1 << 0) +# define EXPORT_SRC_C (1 << 1) +# define DX9_CONSTS (1 << 2) +# define ALU_INST_PREFER_VECTOR (1 << 3) +# define DX10_CLAMP (1 << 4) +# define CLAUSE_SEQ_PRIO(x) ((x) << 8) +# define PS_PRIO(x) ((x) << 24) +# define VS_PRIO(x) ((x) << 26) +# define GS_PRIO(x) ((x) << 28) +# define ES_PRIO(x) ((x) << 30) +#define SQ_GPR_RESOURCE_MGMT_1 0x8c04 +# define NUM_PS_GPRS(x) ((x) << 0) +# define NUM_VS_GPRS(x) ((x) << 16) +# define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) +#define SQ_GPR_RESOURCE_MGMT_2 0x8c08 +# define NUM_GS_GPRS(x) ((x) << 0) +# define NUM_ES_GPRS(x) ((x) << 16) +#define SQ_THREAD_RESOURCE_MGMT 0x8c0c +# define NUM_PS_THREADS(x) ((x) << 0) +# define NUM_VS_THREADS(x) ((x) << 8) +# define NUM_GS_THREADS(x) ((x) << 16) +# define NUM_ES_THREADS(x) ((x) << 24) +#define SQ_STACK_RESOURCE_MGMT_1 0x8c10 +# define NUM_PS_STACK_ENTRIES(x) ((x) << 0) +# define NUM_VS_STACK_ENTRIES(x) ((x) << 16) +#define SQ_STACK_RESOURCE_MGMT_2 0x8c14 +# define NUM_GS_STACK_ENTRIES(x) ((x) << 0) +# define NUM_ES_STACK_ENTRIES(x) ((x) << 16) +#define SQ_ESGS_RING_BASE 0x8c40 +#define SQ_GSVS_RING_BASE 0x8c48 +#define SQ_ESTMP_RING_BASE 0x8c50 +#define SQ_GSTMP_RING_BASE 0x8c58 +#define SQ_VSTMP_RING_BASE 0x8c60 +#define SQ_PSTMP_RING_BASE 0x8c68 +#define SQ_FBUF_RING_BASE 0x8c70 +#define SQ_REDUC_RING_BASE 0x8c78 + +#define GRBM_CNTL 0x8000 +# define GRBM_READ_TIMEOUT(x) ((x) << 0) +#define GRBM_STATUS 0x8010 +#define CMDFIFO_AVAIL_MASK 0x0000001F +#define GUI_ACTIVE (1<<31) +#define GRBM_STATUS2 0x8014 +#define GRBM_SOFT_RESET 0x8020 +#define SOFT_RESET_CP (1<<0) + +#define CG_THERMAL_STATUS 0x7F4 +#define ASIC_T(x) ((x) << 0) +#define ASIC_T_MASK 0x1FF +#define ASIC_T_SHIFT 0 + +#define HDP_HOST_PATH_CNTL 0x2C00 +#define HDP_NONSURFACE_BASE 0x2C04 +#define HDP_NONSURFACE_INFO 0x2C08 +#define HDP_NONSURFACE_SIZE 0x2C0C +#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 +#define HDP_TILING_CONFIG 0x2F3C +#define HDP_DEBUG1 0x2F34 + +#define MC_VM_AGP_TOP 0x2184 +#define MC_VM_AGP_BOT 0x2188 +#define MC_VM_AGP_BASE 0x218C +#define MC_VM_FB_LOCATION 0x2180 +#define MC_VM_L1_TLB_MCD_RD_A_CNTL 0x219C +#define ENABLE_L1_TLB (1 << 0) +#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +#define ENABLE_L1_STRICT_ORDERING (1 << 2) +#define SYSTEM_ACCESS_MODE_MASK 0x000000C0 +#define SYSTEM_ACCESS_MODE_SHIFT 6 +#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 6) +#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 6) +#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 6) +#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 6) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 8) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 8) +#define ENABLE_SEMAPHORE_MODE (1 << 10) +#define ENABLE_WAIT_L2_QUERY (1 << 11) +#define EFFECTIVE_L1_TLB_SIZE(x) (((x) & 7) << 12) +#define EFFECTIVE_L1_TLB_SIZE_MASK 0x00007000 +#define EFFECTIVE_L1_TLB_SIZE_SHIFT 12 +#define EFFECTIVE_L1_QUEUE_SIZE(x) (((x) & 7) << 15) +#define EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00038000 +#define EFFECTIVE_L1_QUEUE_SIZE_SHIFT 15 +#define MC_VM_L1_TLB_MCD_RD_B_CNTL 0x21A0 +#define MC_VM_L1_TLB_MCB_RD_GFX_CNTL 0x21FC +#define MC_VM_L1_TLB_MCB_RD_HDP_CNTL 0x2204 +#define MC_VM_L1_TLB_MCB_RD_PDMA_CNTL 0x2208 +#define MC_VM_L1_TLB_MCB_RD_SEM_CNTL 0x220C +#define MC_VM_L1_TLB_MCB_RD_SYS_CNTL 0x2200 +#define MC_VM_L1_TLB_MCD_WR_A_CNTL 0x21A4 +#define MC_VM_L1_TLB_MCD_WR_B_CNTL 0x21A8 +#define MC_VM_L1_TLB_MCB_WR_GFX_CNTL 0x2210 +#define MC_VM_L1_TLB_MCB_WR_HDP_CNTL 0x2218 +#define MC_VM_L1_TLB_MCB_WR_PDMA_CNTL 0x221C +#define MC_VM_L1_TLB_MCB_WR_SEM_CNTL 0x2220 +#define MC_VM_L1_TLB_MCB_WR_SYS_CNTL 0x2214 +#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190 +#define LOGICAL_PAGE_NUMBER_MASK 0x000FFFFF +#define LOGICAL_PAGE_NUMBER_SHIFT 0 +#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194 +#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198 + +#define PA_CL_ENHANCE 0x8A14 +#define CLIP_VTX_REORDER_ENA (1 << 0) +#define NUM_CLIP_SEQ(x) ((x) << 1) +#define PA_SC_AA_CONFIG 0x28C04 +#define PA_SC_AA_SAMPLE_LOCS_2S 0x8B40 +#define PA_SC_AA_SAMPLE_LOCS_4S 0x8B44 +#define PA_SC_AA_SAMPLE_LOCS_8S_WD0 0x8B48 +#define PA_SC_AA_SAMPLE_LOCS_8S_WD1 0x8B4C +#define S0_X(x) ((x) << 0) +#define S0_Y(x) ((x) << 4) +#define S1_X(x) ((x) << 8) +#define S1_Y(x) ((x) << 12) +#define S2_X(x) ((x) << 16) +#define S2_Y(x) ((x) << 20) +#define S3_X(x) ((x) << 24) +#define S3_Y(x) ((x) << 28) +#define S4_X(x) ((x) << 0) +#define S4_Y(x) ((x) << 4) +#define S5_X(x) ((x) << 8) +#define S5_Y(x) ((x) << 12) +#define S6_X(x) ((x) << 16) +#define S6_Y(x) ((x) << 20) +#define S7_X(x) ((x) << 24) +#define S7_Y(x) ((x) << 28) +#define PA_SC_CLIPRECT_RULE 0x2820c +#define PA_SC_ENHANCE 0x8BF0 +#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +#define FORCE_EOV_MAX_TILE_CNT(x) ((x) << 12) +#define PA_SC_LINE_STIPPLE 0x28A0C +#define PA_SC_LINE_STIPPLE_STATE 0x8B10 +#define PA_SC_MODE_CNTL 0x28A4C +#define PA_SC_MULTI_CHIP_CNTL 0x8B20 + +#define PA_SC_SCREEN_SCISSOR_TL 0x28030 +#define PA_SC_GENERIC_SCISSOR_TL 0x28240 +#define PA_SC_WINDOW_SCISSOR_TL 0x28204 + +#define PCIE_PORT_INDEX 0x0038 +#define PCIE_PORT_DATA 0x003C + +#define CHMAP 0x2004 +#define NOOFCHAN_SHIFT 12 +#define NOOFCHAN_MASK 0x00003000 + +#define RAMCFG 0x2408 +#define NOOFBANK_SHIFT 0 +#define NOOFBANK_MASK 0x00000001 +#define NOOFRANK_SHIFT 1 +#define NOOFRANK_MASK 0x00000002 +#define NOOFROWS_SHIFT 2 +#define NOOFROWS_MASK 0x0000001C +#define NOOFCOLS_SHIFT 5 +#define NOOFCOLS_MASK 0x00000060 +#define CHANSIZE_SHIFT 7 +#define CHANSIZE_MASK 0x00000080 +#define BURSTLENGTH_SHIFT 8 +#define BURSTLENGTH_MASK 0x00000100 +#define CHANSIZE_OVERRIDE (1 << 10) + +#define SCRATCH_REG0 0x8500 +#define SCRATCH_REG1 0x8504 +#define SCRATCH_REG2 0x8508 +#define SCRATCH_REG3 0x850C +#define SCRATCH_REG4 0x8510 +#define SCRATCH_REG5 0x8514 +#define SCRATCH_REG6 0x8518 +#define SCRATCH_REG7 0x851C +#define SCRATCH_UMSK 0x8540 +#define SCRATCH_ADDR 0x8544 + +#define SPI_CONFIG_CNTL 0x9100 +#define GPR_WRITE_PRIORITY(x) ((x) << 0) +#define DISABLE_INTERP_1 (1 << 5) +#define SPI_CONFIG_CNTL_1 0x913C +#define VTX_DONE_DELAY(x) ((x) << 0) +#define INTERP_ONE_PRIM_PER_ROW (1 << 4) +#define SPI_INPUT_Z 0x286D8 +#define SPI_PS_IN_CONTROL_0 0x286CC +#define NUM_INTERP(x) ((x)<<0) +#define POSITION_ENA (1<<8) +#define POSITION_CENTROID (1<<9) +#define POSITION_ADDR(x) ((x)<<10) +#define PARAM_GEN(x) ((x)<<15) +#define PARAM_GEN_ADDR(x) ((x)<<19) +#define BARYC_SAMPLE_CNTL(x) ((x)<<26) +#define PERSP_GRADIENT_ENA (1<<28) +#define LINEAR_GRADIENT_ENA (1<<29) +#define POSITION_SAMPLE (1<<30) +#define BARYC_AT_SAMPLE_ENA (1<<31) +#define SPI_PS_IN_CONTROL_1 0x286D0 +#define GEN_INDEX_PIX (1<<0) +#define GEN_INDEX_PIX_ADDR(x) ((x)<<1) +#define FRONT_FACE_ENA (1<<8) +#define FRONT_FACE_CHAN(x) ((x)<<9) +#define FRONT_FACE_ALL_BITS (1<<11) +#define FRONT_FACE_ADDR(x) ((x)<<12) +#define FOG_ADDR(x) ((x)<<17) +#define FIXED_PT_POSITION_ENA (1<<24) +#define FIXED_PT_POSITION_ADDR(x) ((x)<<25) + +#define SQ_MS_FIFO_SIZES 0x8CF0 +#define CACHE_FIFO_SIZE(x) ((x) << 0) +#define FETCH_FIFO_HIWATER(x) ((x) << 8) +#define DONE_FIFO_HIWATER(x) ((x) << 16) +#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) +#define SQ_PGM_START_ES 0x28880 +#define SQ_PGM_START_FS 0x28894 +#define SQ_PGM_START_GS 0x2886C +#define SQ_PGM_START_PS 0x28840 +#define SQ_PGM_RESOURCES_PS 0x28850 +#define SQ_PGM_EXPORTS_PS 0x28854 +#define SQ_PGM_CF_OFFSET_PS 0x288cc +#define SQ_PGM_START_VS 0x28858 +#define SQ_PGM_RESOURCES_VS 0x28868 +#define SQ_PGM_CF_OFFSET_VS 0x288d0 + +#define SQ_VTX_CONSTANT_WORD0_0 0x30000 +#define SQ_VTX_CONSTANT_WORD1_0 0x30004 +#define SQ_VTX_CONSTANT_WORD2_0 0x30008 +# define SQ_VTXC_BASE_ADDR_HI(x) ((x) << 0) +# define SQ_VTXC_STRIDE(x) ((x) << 8) +# define SQ_VTXC_ENDIAN_SWAP(x) ((x) << 30) +# define SQ_ENDIAN_NONE 0 +# define SQ_ENDIAN_8IN16 1 +# define SQ_ENDIAN_8IN32 2 +#define SQ_VTX_CONSTANT_WORD3_0 0x3000c +#define SQ_VTX_CONSTANT_WORD6_0 0x38018 +#define S__SQ_VTX_CONSTANT_TYPE(x) (((x) & 3) << 30) +#define G__SQ_VTX_CONSTANT_TYPE(x) (((x) >> 30) & 3) +#define SQ_TEX_VTX_INVALID_TEXTURE 0x0 +#define SQ_TEX_VTX_INVALID_BUFFER 0x1 +#define SQ_TEX_VTX_VALID_TEXTURE 0x2 +#define SQ_TEX_VTX_VALID_BUFFER 0x3 + + +#define SX_MISC 0x28350 +#define SX_MEMORY_EXPORT_BASE 0x9010 +#define SX_DEBUG_1 0x9054 +#define SMX_EVENT_RELEASE (1 << 0) +#define ENABLE_NEW_SMX_ADDRESS (1 << 16) + +#define TA_CNTL_AUX 0x9508 +#define DISABLE_CUBE_WRAP (1 << 0) +#define DISABLE_CUBE_ANISO (1 << 1) +#define SYNC_GRADIENT (1 << 24) +#define SYNC_WALKER (1 << 25) +#define SYNC_ALIGNER (1 << 26) +#define BILINEAR_PRECISION_6_BIT (0 << 31) +#define BILINEAR_PRECISION_8_BIT (1 << 31) + +#define TC_CNTL 0x9608 +#define TC_L2_SIZE(x) ((x)<<5) +#define L2_DISABLE_LATE_HIT (1<<9) + +#define VC_ENHANCE 0x9714 + +#define VGT_CACHE_INVALIDATION 0x88C4 +#define CACHE_INVALIDATION(x) ((x)<<0) +#define VC_ONLY 0 +#define TC_ONLY 1 +#define VC_AND_TC 2 +#define VGT_DMA_BASE 0x287E8 +#define VGT_DMA_BASE_HI 0x287E4 +#define VGT_ES_PER_GS 0x88CC +#define VGT_GS_PER_ES 0x88C8 +#define VGT_GS_PER_VS 0x88E8 +#define VGT_GS_VERTEX_REUSE 0x88D4 +#define VGT_PRIMITIVE_TYPE 0x8958 +#define VGT_NUM_INSTANCES 0x8974 +#define VGT_OUT_DEALLOC_CNTL 0x28C5C +#define DEALLOC_DIST_MASK 0x0000007F +#define VGT_STRMOUT_BASE_OFFSET_0 0x28B10 +#define VGT_STRMOUT_BASE_OFFSET_1 0x28B14 +#define VGT_STRMOUT_BASE_OFFSET_2 0x28B18 +#define VGT_STRMOUT_BASE_OFFSET_3 0x28B1c +#define VGT_STRMOUT_BASE_OFFSET_HI_0 0x28B44 +#define VGT_STRMOUT_BASE_OFFSET_HI_1 0x28B48 +#define VGT_STRMOUT_BASE_OFFSET_HI_2 0x28B4c +#define VGT_STRMOUT_BASE_OFFSET_HI_3 0x28B50 +#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_OFFSET_0 0x28ADC +#define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC +#define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC +#define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + +#define VGT_STRMOUT_EN 0x28AB0 +#define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 +#define VTX_REUSE_DEPTH_MASK 0x000000FF +#define VGT_EVENT_INITIATOR 0x28a90 +# define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0) +# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) + +#define VM_CONTEXT0_CNTL 0x1410 +#define ENABLE_CONTEXT (1 << 0) +#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define VM_CONTEXT0_INVALIDATION_LOW_ADDR 0x1490 +#define VM_CONTEXT0_INVALIDATION_HIGH_ADDR 0x14B0 +#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x1574 +#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x1594 +#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x15B4 +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1554 +#define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 +#define REQUEST_TYPE(x) (((x) & 0xf) << 0) +#define RESPONSE_TYPE_MASK 0x000000F0 +#define RESPONSE_TYPE_SHIFT 4 +#define VM_L2_CNTL 0x1400 +#define ENABLE_L2_CACHE (1 << 0) +#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) +#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) +#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 13) +#define VM_L2_CNTL2 0x1404 +#define INVALIDATE_ALL_L1_TLBS (1 << 0) +#define INVALIDATE_L2_CACHE (1 << 1) +#define VM_L2_CNTL3 0x1408 +#define BANK_SELECT_0(x) (((x) & 0x1f) << 0) +#define BANK_SELECT_1(x) (((x) & 0x1f) << 5) +#define L2_CACHE_UPDATE_MODE(x) (((x) & 3) << 10) +#define VM_L2_STATUS 0x140C +#define L2_BUSY (1 << 0) + +#define WAIT_UNTIL 0x8040 +#define WAIT_2D_IDLE_bit (1 << 14) +#define WAIT_3D_IDLE_bit (1 << 15) +#define WAIT_2D_IDLECLEAN_bit (1 << 16) +#define WAIT_3D_IDLECLEAN_bit (1 << 17) + +/* async DMA */ +#define DMA_TILING_CONFIG 0x3ec4 +#define DMA_CONFIG 0x3e4c + +#define DMA_RB_CNTL 0xd000 +# define DMA_RB_ENABLE (1 << 0) +# define DMA_RB_SIZE(x) ((x) << 1) /* log2 */ +# define DMA_RB_SWAP_ENABLE (1 << 9) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_ENABLE (1 << 12) +# define DMA_RPTR_WRITEBACK_SWAP_ENABLE (1 << 13) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_TIMER(x) ((x) << 16) /* log2 */ +#define DMA_RB_BASE 0xd004 +#define DMA_RB_RPTR 0xd008 +#define DMA_RB_WPTR 0xd00c + +#define DMA_RB_RPTR_ADDR_HI 0xd01c +#define DMA_RB_RPTR_ADDR_LO 0xd020 + +#define DMA_IB_CNTL 0xd024 +# define DMA_IB_ENABLE (1 << 0) +# define DMA_IB_SWAP_ENABLE (1 << 4) +#define DMA_IB_RPTR 0xd028 +#define DMA_CNTL 0xd02c +# define TRAP_ENABLE (1 << 0) +# define SEM_INCOMPLETE_INT_ENABLE (1 << 1) +# define SEM_WAIT_INT_ENABLE (1 << 2) +# define DATA_SWAP_ENABLE (1 << 3) +# define FENCE_SWAP_ENABLE (1 << 4) +# define CTXEMPTY_INT_ENABLE (1 << 28) +#define DMA_STATUS_REG 0xd034 +# define DMA_IDLE (1 << 0) +#define DMA_SEM_INCOMPLETE_TIMER_CNTL 0xd044 +#define DMA_SEM_WAIT_FAIL_TIMER_CNTL 0xd048 +#define DMA_MODE 0xd0bc + +/* async DMA packets */ +#define DMA_PACKET(cmd, t, s, n) ((((cmd) & 0xF) << 28) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((n) & 0xFFFF) << 0)) +/* async DMA Packet types */ +#define DMA_PACKET_WRITE 0x2 +#define DMA_PACKET_COPY 0x3 +#define DMA_PACKET_INDIRECT_BUFFER 0x4 +#define DMA_PACKET_SEMAPHORE 0x5 +#define DMA_PACKET_FENCE 0x6 +#define DMA_PACKET_TRAP 0x7 +#define DMA_PACKET_CONSTANT_FILL 0xd /* 7xx only */ +#define DMA_PACKET_NOP 0xf + +#define IH_RB_CNTL 0x3e00 +# define IH_RB_ENABLE (1 << 0) +# define IH_RB_SIZE(x) ((x) << 1) /* log2 */ +# define IH_RB_FULL_DRAIN_ENABLE (1 << 6) +# define IH_WPTR_WRITEBACK_ENABLE (1 << 8) +# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ +# define IH_WPTR_OVERFLOW_ENABLE (1 << 16) +# define IH_WPTR_OVERFLOW_CLEAR (1 << 31) +#define IH_RB_BASE 0x3e04 +#define IH_RB_RPTR 0x3e08 +#define IH_RB_WPTR 0x3e0c +# define RB_OVERFLOW (1 << 0) +# define WPTR_OFFSET_MASK 0x3fffc +#define IH_RB_WPTR_ADDR_HI 0x3e10 +#define IH_RB_WPTR_ADDR_LO 0x3e14 +#define IH_CNTL 0x3e18 +# define ENABLE_INTR (1 << 0) +# define IH_MC_SWAP(x) ((x) << 1) +# define IH_MC_SWAP_NONE 0 +# define IH_MC_SWAP_16BIT 1 +# define IH_MC_SWAP_32BIT 2 +# define IH_MC_SWAP_64BIT 3 +# define RPTR_REARM (1 << 4) +# define MC_WRREQ_CREDIT(x) ((x) << 15) +# define MC_WR_CLEAN_CNT(x) ((x) << 20) + +#define RLC_CNTL 0x3f00 +# define RLC_ENABLE (1 << 0) +#define RLC_HB_BASE 0x3f10 +#define RLC_HB_CNTL 0x3f0c +#define RLC_HB_RPTR 0x3f20 +#define RLC_HB_WPTR 0x3f1c +#define RLC_HB_WPTR_LSB_ADDR 0x3f14 +#define RLC_HB_WPTR_MSB_ADDR 0x3f18 +#define RLC_GPU_CLOCK_COUNT_LSB 0x3f38 +#define RLC_GPU_CLOCK_COUNT_MSB 0x3f3c +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0x3f40 +#define RLC_MC_CNTL 0x3f44 +#define RLC_UCODE_CNTL 0x3f48 +#define RLC_UCODE_ADDR 0x3f2c +#define RLC_UCODE_DATA 0x3f30 + +/* new for TN */ +#define TN_RLC_SAVE_AND_RESTORE_BASE 0x3f10 +#define TN_RLC_CLEAR_STATE_RESTORE_BASE 0x3f20 + +#define SRBM_SOFT_RESET 0xe60 +# define SOFT_RESET_DMA (1 << 12) +# define SOFT_RESET_RLC (1 << 13) +# define RV770_SOFT_RESET_DMA (1 << 20) + +#define CP_INT_CNTL 0xc124 +# define CNTX_BUSY_INT_ENABLE (1 << 19) +# define CNTX_EMPTY_INT_ENABLE (1 << 20) +# define SCRATCH_INT_ENABLE (1 << 25) +# define TIME_STAMP_INT_ENABLE (1 << 26) +# define IB2_INT_ENABLE (1 << 29) +# define IB1_INT_ENABLE (1 << 30) +# define RB_INT_ENABLE (1 << 31) +#define CP_INT_STATUS 0xc128 +# define SCRATCH_INT_STAT (1 << 25) +# define TIME_STAMP_INT_STAT (1 << 26) +# define IB2_INT_STAT (1 << 29) +# define IB1_INT_STAT (1 << 30) +# define RB_INT_STAT (1 << 31) + +#define GRBM_INT_CNTL 0x8060 +# define RDERR_INT_ENABLE (1 << 0) +# define WAIT_COUNT_TIMEOUT_INT_ENABLE (1 << 1) +# define GUI_IDLE_INT_ENABLE (1 << 19) + +#define INTERRUPT_CNTL 0x5468 +# define IH_DUMMY_RD_OVERRIDE (1 << 0) +# define IH_DUMMY_RD_EN (1 << 1) +# define IH_REQ_NONSNOOP_EN (1 << 3) +# define GEN_IH_INT_EN (1 << 8) +#define INTERRUPT_CNTL2 0x546c + +#define D1MODE_VBLANK_STATUS 0x6534 +#define D2MODE_VBLANK_STATUS 0x6d34 +# define DxMODE_VBLANK_OCCURRED (1 << 0) +# define DxMODE_VBLANK_ACK (1 << 4) +# define DxMODE_VBLANK_STAT (1 << 12) +# define DxMODE_VBLANK_INTERRUPT (1 << 16) +# define DxMODE_VBLANK_INTERRUPT_TYPE (1 << 17) +#define D1MODE_VLINE_STATUS 0x653c +#define D2MODE_VLINE_STATUS 0x6d3c +# define DxMODE_VLINE_OCCURRED (1 << 0) +# define DxMODE_VLINE_ACK (1 << 4) +# define DxMODE_VLINE_STAT (1 << 12) +# define DxMODE_VLINE_INTERRUPT (1 << 16) +# define DxMODE_VLINE_INTERRUPT_TYPE (1 << 17) +#define DxMODE_INT_MASK 0x6540 +# define D1MODE_VBLANK_INT_MASK (1 << 0) +# define D1MODE_VLINE_INT_MASK (1 << 4) +# define D2MODE_VBLANK_INT_MASK (1 << 8) +# define D2MODE_VLINE_INT_MASK (1 << 12) +#define DCE3_DISP_INTERRUPT_STATUS 0x7ddc +# define DC_HPD1_INTERRUPT (1 << 18) +# define DC_HPD2_INTERRUPT (1 << 19) +#define DISP_INTERRUPT_STATUS 0x7edc +# define LB_D1_VLINE_INTERRUPT (1 << 2) +# define LB_D2_VLINE_INTERRUPT (1 << 3) +# define LB_D1_VBLANK_INTERRUPT (1 << 4) +# define LB_D2_VBLANK_INTERRUPT (1 << 5) +# define DACA_AUTODETECT_INTERRUPT (1 << 16) +# define DACB_AUTODETECT_INTERRUPT (1 << 17) +# define DC_HOT_PLUG_DETECT1_INTERRUPT (1 << 18) +# define DC_HOT_PLUG_DETECT2_INTERRUPT (1 << 19) +# define DC_I2C_SW_DONE_INTERRUPT (1 << 20) +# define DC_I2C_HW_DONE_INTERRUPT (1 << 21) +#define DISP_INTERRUPT_STATUS_CONTINUE 0x7ee8 +#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE 0x7de8 +# define DC_HPD4_INTERRUPT (1 << 14) +# define DC_HPD4_RX_INTERRUPT (1 << 15) +# define DC_HPD3_INTERRUPT (1 << 28) +# define DC_HPD1_RX_INTERRUPT (1 << 29) +# define DC_HPD2_RX_INTERRUPT (1 << 30) +#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE2 0x7dec +# define DC_HPD3_RX_INTERRUPT (1 << 0) +# define DIGA_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 1) +# define DIGA_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 2) +# define DIGB_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 3) +# define DIGB_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 4) +# define AUX1_SW_DONE_INTERRUPT (1 << 5) +# define AUX1_LS_DONE_INTERRUPT (1 << 6) +# define AUX2_SW_DONE_INTERRUPT (1 << 7) +# define AUX2_LS_DONE_INTERRUPT (1 << 8) +# define AUX3_SW_DONE_INTERRUPT (1 << 9) +# define AUX3_LS_DONE_INTERRUPT (1 << 10) +# define AUX4_SW_DONE_INTERRUPT (1 << 11) +# define AUX4_LS_DONE_INTERRUPT (1 << 12) +# define DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 13) +# define DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 14) +/* DCE 3.2 */ +# define AUX5_SW_DONE_INTERRUPT (1 << 15) +# define AUX5_LS_DONE_INTERRUPT (1 << 16) +# define AUX6_SW_DONE_INTERRUPT (1 << 17) +# define AUX6_LS_DONE_INTERRUPT (1 << 18) +# define DC_HPD5_INTERRUPT (1 << 19) +# define DC_HPD5_RX_INTERRUPT (1 << 20) +# define DC_HPD6_INTERRUPT (1 << 21) +# define DC_HPD6_RX_INTERRUPT (1 << 22) + +#define DACA_AUTO_DETECT_CONTROL 0x7828 +#define DACB_AUTO_DETECT_CONTROL 0x7a28 +#define DCE3_DACA_AUTO_DETECT_CONTROL 0x7028 +#define DCE3_DACB_AUTO_DETECT_CONTROL 0x7128 +# define DACx_AUTODETECT_MODE(x) ((x) << 0) +# define DACx_AUTODETECT_MODE_NONE 0 +# define DACx_AUTODETECT_MODE_CONNECT 1 +# define DACx_AUTODETECT_MODE_DISCONNECT 2 +# define DACx_AUTODETECT_FRAME_TIME_COUNTER(x) ((x) << 8) +/* bit 18 = R/C, 17 = G/Y, 16 = B/Comp */ +# define DACx_AUTODETECT_CHECK_MASK(x) ((x) << 16) + +#define DCE3_DACA_AUTODETECT_INT_CONTROL 0x7038 +#define DCE3_DACB_AUTODETECT_INT_CONTROL 0x7138 +#define DACA_AUTODETECT_INT_CONTROL 0x7838 +#define DACB_AUTODETECT_INT_CONTROL 0x7a38 +# define DACx_AUTODETECT_ACK (1 << 0) +# define DACx_AUTODETECT_INT_ENABLE (1 << 16) + +#define DC_HOT_PLUG_DETECT1_CONTROL 0x7d00 +#define DC_HOT_PLUG_DETECT2_CONTROL 0x7d10 +#define DC_HOT_PLUG_DETECT3_CONTROL 0x7d24 +# define DC_HOT_PLUG_DETECTx_EN (1 << 0) + +#define DC_HOT_PLUG_DETECT1_INT_STATUS 0x7d04 +#define DC_HOT_PLUG_DETECT2_INT_STATUS 0x7d14 +#define DC_HOT_PLUG_DETECT3_INT_STATUS 0x7d28 +# define DC_HOT_PLUG_DETECTx_INT_STATUS (1 << 0) +# define DC_HOT_PLUG_DETECTx_SENSE (1 << 1) + +/* DCE 3.0 */ +#define DC_HPD1_INT_STATUS 0x7d00 +#define DC_HPD2_INT_STATUS 0x7d0c +#define DC_HPD3_INT_STATUS 0x7d18 +#define DC_HPD4_INT_STATUS 0x7d24 +/* DCE 3.2 */ +#define DC_HPD5_INT_STATUS 0x7dc0 +#define DC_HPD6_INT_STATUS 0x7df4 +# define DC_HPDx_INT_STATUS (1 << 0) +# define DC_HPDx_SENSE (1 << 1) +# define DC_HPDx_RX_INT_STATUS (1 << 8) + +#define DC_HOT_PLUG_DETECT1_INT_CONTROL 0x7d08 +#define DC_HOT_PLUG_DETECT2_INT_CONTROL 0x7d18 +#define DC_HOT_PLUG_DETECT3_INT_CONTROL 0x7d2c +# define DC_HOT_PLUG_DETECTx_INT_ACK (1 << 0) +# define DC_HOT_PLUG_DETECTx_INT_POLARITY (1 << 8) +# define DC_HOT_PLUG_DETECTx_INT_EN (1 << 16) +/* DCE 3.0 */ +#define DC_HPD1_INT_CONTROL 0x7d04 +#define DC_HPD2_INT_CONTROL 0x7d10 +#define DC_HPD3_INT_CONTROL 0x7d1c +#define DC_HPD4_INT_CONTROL 0x7d28 +/* DCE 3.2 */ +#define DC_HPD5_INT_CONTROL 0x7dc4 +#define DC_HPD6_INT_CONTROL 0x7df8 +# define DC_HPDx_INT_ACK (1 << 0) +# define DC_HPDx_INT_POLARITY (1 << 8) +# define DC_HPDx_INT_EN (1 << 16) +# define DC_HPDx_RX_INT_ACK (1 << 20) +# define DC_HPDx_RX_INT_EN (1 << 24) + +/* DCE 3.0 */ +#define DC_HPD1_CONTROL 0x7d08 +#define DC_HPD2_CONTROL 0x7d14 +#define DC_HPD3_CONTROL 0x7d20 +#define DC_HPD4_CONTROL 0x7d2c +/* DCE 3.2 */ +#define DC_HPD5_CONTROL 0x7dc8 +#define DC_HPD6_CONTROL 0x7dfc +# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0) +# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) +/* DCE 3.2 */ +# define DC_HPDx_EN (1 << 28) + +#define D1GRPH_INTERRUPT_STATUS 0x6158 +#define D2GRPH_INTERRUPT_STATUS 0x6958 +# define DxGRPH_PFLIP_INT_OCCURRED (1 << 0) +# define DxGRPH_PFLIP_INT_CLEAR (1 << 8) +#define D1GRPH_INTERRUPT_CONTROL 0x615c +#define D2GRPH_INTERRUPT_CONTROL 0x695c +# define DxGRPH_PFLIP_INT_MASK (1 << 0) +# define DxGRPH_PFLIP_INT_TYPE (1 << 8) + +/* PCIE link stuff */ +#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */ +# define LC_POINT_7_PLUS_EN (1 << 6) +#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */ +# define LC_LINK_WIDTH_SHIFT 0 +# define LC_LINK_WIDTH_MASK 0x7 +# define LC_LINK_WIDTH_X0 0 +# define LC_LINK_WIDTH_X1 1 +# define LC_LINK_WIDTH_X2 2 +# define LC_LINK_WIDTH_X4 3 +# define LC_LINK_WIDTH_X8 4 +# define LC_LINK_WIDTH_X16 6 +# define LC_LINK_WIDTH_RD_SHIFT 4 +# define LC_LINK_WIDTH_RD_MASK 0x70 +# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7) +# define LC_RECONFIG_NOW (1 << 8) +# define LC_RENEGOTIATION_SUPPORT (1 << 9) +# define LC_RENEGOTIATE_EN (1 << 10) +# define LC_SHORT_RECONFIG_EN (1 << 11) +# define LC_UPCONFIGURE_SUPPORT (1 << 12) +# define LC_UPCONFIGURE_DIS (1 << 13) +#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */ +# define LC_GEN2_EN_STRAP (1 << 0) +# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1) +# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 5) +# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 6) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3 +# define LC_CURRENT_DATA_RATE (1 << 11) +# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14) +# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21) +# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23) +# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 24) +#define MM_CFGREGS_CNTL 0x544c +# define MM_WR_TO_CFG_EN (1 << 3) +#define LINK_CNTL2 0x88 /* F0 */ +# define TARGET_LINK_SPEED_MASK (0xf << 0) +# define SELECTABLE_DEEMPHASIS (1 << 6) + +/* Audio clocks */ +#define DCCG_AUDIO_DTO0_PHASE 0x0514 +#define DCCG_AUDIO_DTO0_MODULE 0x0518 +#define DCCG_AUDIO_DTO0_LOAD 0x051c +# define DTO_LOAD (1 << 31) +#define DCCG_AUDIO_DTO0_CNTL 0x0520 + +#define DCCG_AUDIO_DTO1_PHASE 0x0524 +#define DCCG_AUDIO_DTO1_MODULE 0x0528 +#define DCCG_AUDIO_DTO1_LOAD 0x052c +#define DCCG_AUDIO_DTO1_CNTL 0x0530 + +#define DCCG_AUDIO_DTO_SELECT 0x0534 + +/* digital blocks */ +#define TMDSA_CNTL 0x7880 +# define TMDSA_HDMI_EN (1 << 2) +#define LVTMA_CNTL 0x7a80 +# define LVTMA_HDMI_EN (1 << 2) +#define DDIA_CNTL 0x7200 +# define DDIA_HDMI_EN (1 << 2) +#define DIG0_CNTL 0x75a0 +# define DIG_MODE(x) (((x) & 7) << 8) +# define DIG_MODE_DP 0 +# define DIG_MODE_LVDS 1 +# define DIG_MODE_TMDS_DVI 2 +# define DIG_MODE_TMDS_HDMI 3 +# define DIG_MODE_SDVO 4 +#define DIG1_CNTL 0x79a0 + +/* rs6xx/rs740 and r6xx share the same HDMI blocks, however, rs6xx has only one + * instance of the blocks while r6xx has 2. DCE 3.0 cards are slightly + * different due to the new DIG blocks, but also have 2 instances. + * DCE 3.0 HDMI blocks are part of each DIG encoder. + */ + +/* rs6xx/rs740/r6xx/dce3 */ +#define HDMI0_CONTROL 0x7400 +/* rs6xx/rs740/r6xx */ +# define HDMI0_ENABLE (1 << 0) +# define HDMI0_STREAM(x) (((x) & 3) << 2) +# define HDMI0_STREAM_TMDSA 0 +# define HDMI0_STREAM_LVTMA 1 +# define HDMI0_STREAM_DVOA 2 +# define HDMI0_STREAM_DDIA 3 +/* rs6xx/r6xx/dce3 */ +# define HDMI0_ERROR_ACK (1 << 8) +# define HDMI0_ERROR_MASK (1 << 9) +#define HDMI0_STATUS 0x7404 +# define HDMI0_ACTIVE_AVMUTE (1 << 0) +# define HDMI0_AUDIO_ENABLE (1 << 4) +# define HDMI0_AZ_FORMAT_WTRIG (1 << 28) +# define HDMI0_AZ_FORMAT_WTRIG_INT (1 << 29) +#define HDMI0_AUDIO_PACKET_CONTROL 0x7408 +# define HDMI0_AUDIO_SAMPLE_SEND (1 << 0) +# define HDMI0_AUDIO_DELAY_EN(x) (((x) & 3) << 4) +# define HDMI0_AUDIO_SEND_MAX_PACKETS (1 << 8) +# define HDMI0_AUDIO_TEST_EN (1 << 12) +# define HDMI0_AUDIO_PACKETS_PER_LINE(x) (((x) & 0x1f) << 16) +# define HDMI0_AUDIO_CHANNEL_SWAP (1 << 24) +# define HDMI0_60958_CS_UPDATE (1 << 26) +# define HDMI0_AZ_FORMAT_WTRIG_MASK (1 << 28) +# define HDMI0_AZ_FORMAT_WTRIG_ACK (1 << 29) +#define HDMI0_AUDIO_CRC_CONTROL 0x740c +# define HDMI0_AUDIO_CRC_EN (1 << 0) +#define HDMI0_VBI_PACKET_CONTROL 0x7410 +# define HDMI0_NULL_SEND (1 << 0) +# define HDMI0_GC_SEND (1 << 4) +# define HDMI0_GC_CONT (1 << 5) /* 0 - once; 1 - every frame */ +#define HDMI0_INFOFRAME_CONTROL0 0x7414 +# define HDMI0_AVI_INFO_SEND (1 << 0) +# define HDMI0_AVI_INFO_CONT (1 << 1) +# define HDMI0_AUDIO_INFO_SEND (1 << 4) +# define HDMI0_AUDIO_INFO_CONT (1 << 5) +# define HDMI0_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hmdi regs */ +# define HDMI0_AUDIO_INFO_UPDATE (1 << 7) +# define HDMI0_MPEG_INFO_SEND (1 << 8) +# define HDMI0_MPEG_INFO_CONT (1 << 9) +# define HDMI0_MPEG_INFO_UPDATE (1 << 10) +#define HDMI0_INFOFRAME_CONTROL1 0x7418 +# define HDMI0_AVI_INFO_LINE(x) (((x) & 0x3f) << 0) +# define HDMI0_AUDIO_INFO_LINE(x) (((x) & 0x3f) << 8) +# define HDMI0_MPEG_INFO_LINE(x) (((x) & 0x3f) << 16) +#define HDMI0_GENERIC_PACKET_CONTROL 0x741c +# define HDMI0_GENERIC0_SEND (1 << 0) +# define HDMI0_GENERIC0_CONT (1 << 1) +# define HDMI0_GENERIC0_UPDATE (1 << 2) +# define HDMI0_GENERIC1_SEND (1 << 4) +# define HDMI0_GENERIC1_CONT (1 << 5) +# define HDMI0_GENERIC0_LINE(x) (((x) & 0x3f) << 16) +# define HDMI0_GENERIC1_LINE(x) (((x) & 0x3f) << 24) +#define HDMI0_GC 0x7428 +# define HDMI0_GC_AVMUTE (1 << 0) +#define HDMI0_AVI_INFO0 0x7454 +# define HDMI0_AVI_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define HDMI0_AVI_INFO_S(x) (((x) & 3) << 8) +# define HDMI0_AVI_INFO_B(x) (((x) & 3) << 10) +# define HDMI0_AVI_INFO_A(x) (((x) & 1) << 12) +# define HDMI0_AVI_INFO_Y(x) (((x) & 3) << 13) +# define HDMI0_AVI_INFO_Y_RGB 0 +# define HDMI0_AVI_INFO_Y_YCBCR422 1 +# define HDMI0_AVI_INFO_Y_YCBCR444 2 +# define HDMI0_AVI_INFO_Y_A_B_S(x) (((x) & 0xff) << 8) +# define HDMI0_AVI_INFO_R(x) (((x) & 0xf) << 16) +# define HDMI0_AVI_INFO_M(x) (((x) & 0x3) << 20) +# define HDMI0_AVI_INFO_C(x) (((x) & 0x3) << 22) +# define HDMI0_AVI_INFO_C_M_R(x) (((x) & 0xff) << 16) +# define HDMI0_AVI_INFO_SC(x) (((x) & 0x3) << 24) +# define HDMI0_AVI_INFO_ITC_EC_Q_SC(x) (((x) & 0xff) << 24) +#define HDMI0_AVI_INFO1 0x7458 +# define HDMI0_AVI_INFO_VIC(x) (((x) & 0x7f) << 0) /* don't use avi infoframe v1 */ +# define HDMI0_AVI_INFO_PR(x) (((x) & 0xf) << 8) /* don't use avi infoframe v1 */ +# define HDMI0_AVI_INFO_TOP(x) (((x) & 0xffff) << 16) +#define HDMI0_AVI_INFO2 0x745c +# define HDMI0_AVI_INFO_BOTTOM(x) (((x) & 0xffff) << 0) +# define HDMI0_AVI_INFO_LEFT(x) (((x) & 0xffff) << 16) +#define HDMI0_AVI_INFO3 0x7460 +# define HDMI0_AVI_INFO_RIGHT(x) (((x) & 0xffff) << 0) +# define HDMI0_AVI_INFO_VERSION(x) (((x) & 3) << 24) +#define HDMI0_MPEG_INFO0 0x7464 +# define HDMI0_MPEG_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define HDMI0_MPEG_INFO_MB0(x) (((x) & 0xff) << 8) +# define HDMI0_MPEG_INFO_MB1(x) (((x) & 0xff) << 16) +# define HDMI0_MPEG_INFO_MB2(x) (((x) & 0xff) << 24) +#define HDMI0_MPEG_INFO1 0x7468 +# define HDMI0_MPEG_INFO_MB3(x) (((x) & 0xff) << 0) +# define HDMI0_MPEG_INFO_MF(x) (((x) & 3) << 8) +# define HDMI0_MPEG_INFO_FR(x) (((x) & 1) << 12) +#define HDMI0_GENERIC0_HDR 0x746c +#define HDMI0_GENERIC0_0 0x7470 +#define HDMI0_GENERIC0_1 0x7474 +#define HDMI0_GENERIC0_2 0x7478 +#define HDMI0_GENERIC0_3 0x747c +#define HDMI0_GENERIC0_4 0x7480 +#define HDMI0_GENERIC0_5 0x7484 +#define HDMI0_GENERIC0_6 0x7488 +#define HDMI0_GENERIC1_HDR 0x748c +#define HDMI0_GENERIC1_0 0x7490 +#define HDMI0_GENERIC1_1 0x7494 +#define HDMI0_GENERIC1_2 0x7498 +#define HDMI0_GENERIC1_3 0x749c +#define HDMI0_GENERIC1_4 0x74a0 +#define HDMI0_GENERIC1_5 0x74a4 +#define HDMI0_GENERIC1_6 0x74a8 +#define HDMI0_ACR_32_0 0x74ac +# define HDMI0_ACR_CTS_32(x) (((x) & 0xfffff) << 12) +#define HDMI0_ACR_32_1 0x74b0 +# define HDMI0_ACR_N_32(x) (((x) & 0xfffff) << 0) +#define HDMI0_ACR_44_0 0x74b4 +# define HDMI0_ACR_CTS_44(x) (((x) & 0xfffff) << 12) +#define HDMI0_ACR_44_1 0x74b8 +# define HDMI0_ACR_N_44(x) (((x) & 0xfffff) << 0) +#define HDMI0_ACR_48_0 0x74bc +# define HDMI0_ACR_CTS_48(x) (((x) & 0xfffff) << 12) +#define HDMI0_ACR_48_1 0x74c0 +# define HDMI0_ACR_N_48(x) (((x) & 0xfffff) << 0) +#define HDMI0_ACR_STATUS_0 0x74c4 +#define HDMI0_ACR_STATUS_1 0x74c8 +#define HDMI0_AUDIO_INFO0 0x74cc +# define HDMI0_AUDIO_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define HDMI0_AUDIO_INFO_CC(x) (((x) & 7) << 8) +#define HDMI0_AUDIO_INFO1 0x74d0 +# define HDMI0_AUDIO_INFO_CA(x) (((x) & 0xff) << 0) +# define HDMI0_AUDIO_INFO_LSV(x) (((x) & 0xf) << 11) +# define HDMI0_AUDIO_INFO_DM_INH(x) (((x) & 1) << 15) +# define HDMI0_AUDIO_INFO_DM_INH_LSV(x) (((x) & 0xff) << 8) +#define HDMI0_60958_0 0x74d4 +# define HDMI0_60958_CS_A(x) (((x) & 1) << 0) +# define HDMI0_60958_CS_B(x) (((x) & 1) << 1) +# define HDMI0_60958_CS_C(x) (((x) & 1) << 2) +# define HDMI0_60958_CS_D(x) (((x) & 3) << 3) +# define HDMI0_60958_CS_MODE(x) (((x) & 3) << 6) +# define HDMI0_60958_CS_CATEGORY_CODE(x) (((x) & 0xff) << 8) +# define HDMI0_60958_CS_SOURCE_NUMBER(x) (((x) & 0xf) << 16) +# define HDMI0_60958_CS_CHANNEL_NUMBER_L(x) (((x) & 0xf) << 20) +# define HDMI0_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24) +# define HDMI0_60958_CS_CLOCK_ACCURACY(x) (((x) & 3) << 28) +#define HDMI0_60958_1 0x74d8 +# define HDMI0_60958_CS_WORD_LENGTH(x) (((x) & 0xf) << 0) +# define HDMI0_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 4) +# define HDMI0_60958_CS_VALID_L(x) (((x) & 1) << 16) +# define HDMI0_60958_CS_VALID_R(x) (((x) & 1) << 18) +# define HDMI0_60958_CS_CHANNEL_NUMBER_R(x) (((x) & 0xf) << 20) +#define HDMI0_ACR_PACKET_CONTROL 0x74dc +# define HDMI0_ACR_SEND (1 << 0) +# define HDMI0_ACR_CONT (1 << 1) +# define HDMI0_ACR_SELECT(x) (((x) & 3) << 4) +# define HDMI0_ACR_HW 0 +# define HDMI0_ACR_32 1 +# define HDMI0_ACR_44 2 +# define HDMI0_ACR_48 3 +# define HDMI0_ACR_SOURCE (1 << 8) /* 0 - hw; 1 - cts value */ +# define HDMI0_ACR_AUTO_SEND (1 << 12) +#define HDMI0_RAMP_CONTROL0 0x74e0 +# define HDMI0_RAMP_MAX_COUNT(x) (((x) & 0xffffff) << 0) +#define HDMI0_RAMP_CONTROL1 0x74e4 +# define HDMI0_RAMP_MIN_COUNT(x) (((x) & 0xffffff) << 0) +#define HDMI0_RAMP_CONTROL2 0x74e8 +# define HDMI0_RAMP_INC_COUNT(x) (((x) & 0xffffff) << 0) +#define HDMI0_RAMP_CONTROL3 0x74ec +# define HDMI0_RAMP_DEC_COUNT(x) (((x) & 0xffffff) << 0) +/* HDMI0_60958_2 is r7xx only */ +#define HDMI0_60958_2 0x74f0 +# define HDMI0_60958_CS_CHANNEL_NUMBER_2(x) (((x) & 0xf) << 0) +# define HDMI0_60958_CS_CHANNEL_NUMBER_3(x) (((x) & 0xf) << 4) +# define HDMI0_60958_CS_CHANNEL_NUMBER_4(x) (((x) & 0xf) << 8) +# define HDMI0_60958_CS_CHANNEL_NUMBER_5(x) (((x) & 0xf) << 12) +# define HDMI0_60958_CS_CHANNEL_NUMBER_6(x) (((x) & 0xf) << 16) +# define HDMI0_60958_CS_CHANNEL_NUMBER_7(x) (((x) & 0xf) << 20) +/* r6xx only; second instance starts at 0x7700 */ +#define HDMI1_CONTROL 0x7700 +#define HDMI1_STATUS 0x7704 +#define HDMI1_AUDIO_PACKET_CONTROL 0x7708 +/* DCE3; second instance starts at 0x7800 NOT 0x7700 */ +#define DCE3_HDMI1_CONTROL 0x7800 +#define DCE3_HDMI1_STATUS 0x7804 +#define DCE3_HDMI1_AUDIO_PACKET_CONTROL 0x7808 +/* DCE3.2 (for interrupts) */ +#define AFMT_STATUS 0x7600 +# define AFMT_AUDIO_ENABLE (1 << 4) +# define AFMT_AZ_FORMAT_WTRIG (1 << 28) +# define AFMT_AZ_FORMAT_WTRIG_INT (1 << 29) +# define AFMT_AZ_AUDIO_ENABLE_CHG (1 << 30) +#define AFMT_AUDIO_PACKET_CONTROL 0x7604 +# define AFMT_AUDIO_SAMPLE_SEND (1 << 0) +# define AFMT_AUDIO_TEST_EN (1 << 12) +# define AFMT_AUDIO_CHANNEL_SWAP (1 << 24) +# define AFMT_60958_CS_UPDATE (1 << 26) +# define AFMT_AZ_AUDIO_ENABLE_CHG_MASK (1 << 27) +# define AFMT_AZ_FORMAT_WTRIG_MASK (1 << 28) +# define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29) +# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30) + +/* + * PM4 + */ +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) +#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ + (((reg) >> 2) & 0xFFFF) | \ + ((n) & 0x3FFF) << 16) +#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +/* Packet 3 types */ +#define PACKET3_NOP 0x10 +#define PACKET3_INDIRECT_BUFFER_END 0x17 +#define PACKET3_SET_PREDICATION 0x20 +#define PACKET3_REG_RMW 0x21 +#define PACKET3_COND_EXEC 0x22 +#define PACKET3_PRED_EXEC 0x23 +#define PACKET3_START_3D_CMDBUF 0x24 +#define PACKET3_DRAW_INDEX_2 0x27 +#define PACKET3_CONTEXT_CONTROL 0x28 +#define PACKET3_DRAW_INDEX_IMMD_BE 0x29 +#define PACKET3_INDEX_TYPE 0x2A +#define PACKET3_DRAW_INDEX 0x2B +#define PACKET3_DRAW_INDEX_AUTO 0x2D +#define PACKET3_DRAW_INDEX_IMMD 0x2E +#define PACKET3_NUM_INSTANCES 0x2F +#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 +#define PACKET3_INDIRECT_BUFFER_MP 0x38 +#define PACKET3_MEM_SEMAPHORE 0x39 +# define PACKET3_SEM_WAIT_ON_SIGNAL (0x1 << 12) +# define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) +# define PACKET3_SEM_SEL_WAIT (0x7 << 29) +#define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B +#define PACKET3_WAIT_REG_MEM 0x3C +#define PACKET3_MEM_WRITE 0x3D +#define PACKET3_INDIRECT_BUFFER 0x32 +#define PACKET3_CP_DMA 0x41 +/* 1. header + * 2. SRC_ADDR_LO [31:0] + * 3. CP_SYNC [31] | SRC_ADDR_HI [7:0] + * 4. DST_ADDR_LO [31:0] + * 5. DST_ADDR_HI [7:0] + * 6. COMMAND [29:22] | BYTE_COUNT [20:0] + */ +# define PACKET3_CP_DMA_CP_SYNC (1 << 31) +/* COMMAND */ +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_DST_SWAP(x) ((x) << 24) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_SAS (1 << 26) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_DAS (1 << 27) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_SAIC (1 << 28) +# define PACKET3_CP_DMA_CMD_DAIC (1 << 29) +#define PACKET3_SURFACE_SYNC 0x43 +# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_TC_ACTION_ENA (1 << 23) +# define PACKET3_VC_ACTION_ENA (1 << 24) +# define PACKET3_CB_ACTION_ENA (1 << 25) +# define PACKET3_DB_ACTION_ENA (1 << 26) +# define PACKET3_SH_ACTION_ENA (1 << 27) +# define PACKET3_SMX_ACTION_ENA (1 << 28) +#define PACKET3_ME_INITIALIZE 0x44 +#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) +#define PACKET3_COND_WRITE 0x45 +#define PACKET3_EVENT_WRITE 0x46 +#define EVENT_TYPE(x) ((x) << 0) +#define EVENT_INDEX(x) ((x) << 8) + /* 0 - any non-TS event + * 1 - ZPASS_DONE + * 2 - SAMPLE_PIPELINESTAT + * 3 - SAMPLE_STREAMOUTSTAT* + * 4 - *S_PARTIAL_FLUSH + * 5 - TS events + */ +#define PACKET3_EVENT_WRITE_EOP 0x47 +#define DATA_SEL(x) ((x) << 29) + /* 0 - discard + * 1 - send low 32bit data + * 2 - send 64bit data + * 3 - send 64bit counter value + */ +#define INT_SEL(x) ((x) << 24) + /* 0 - none + * 1 - interrupt only (DATA_SEL = 0) + * 2 - interrupt when data write is confirmed + */ +#define PACKET3_ONE_REG_WRITE 0x57 +#define PACKET3_SET_CONFIG_REG 0x68 +#define PACKET3_SET_CONFIG_REG_OFFSET 0x00008000 +#define PACKET3_SET_CONFIG_REG_END 0x0000ac00 +#define PACKET3_SET_CONTEXT_REG 0x69 +#define PACKET3_SET_CONTEXT_REG_OFFSET 0x00028000 +#define PACKET3_SET_CONTEXT_REG_END 0x00029000 +#define PACKET3_SET_ALU_CONST 0x6A +#define PACKET3_SET_ALU_CONST_OFFSET 0x00030000 +#define PACKET3_SET_ALU_CONST_END 0x00032000 +#define PACKET3_SET_BOOL_CONST 0x6B +#define PACKET3_SET_BOOL_CONST_OFFSET 0x0003e380 +#define PACKET3_SET_BOOL_CONST_END 0x00040000 +#define PACKET3_SET_LOOP_CONST 0x6C +#define PACKET3_SET_LOOP_CONST_OFFSET 0x0003e200 +#define PACKET3_SET_LOOP_CONST_END 0x0003e380 +#define PACKET3_SET_RESOURCE 0x6D +#define PACKET3_SET_RESOURCE_OFFSET 0x00038000 +#define PACKET3_SET_RESOURCE_END 0x0003c000 +#define PACKET3_SET_SAMPLER 0x6E +#define PACKET3_SET_SAMPLER_OFFSET 0x0003c000 +#define PACKET3_SET_SAMPLER_END 0x0003cff0 +#define PACKET3_SET_CTL_CONST 0x6F +#define PACKET3_SET_CTL_CONST_OFFSET 0x0003cff0 +#define PACKET3_SET_CTL_CONST_END 0x0003e200 +#define PACKET3_STRMOUT_BASE_UPDATE 0x72 /* r7xx */ +#define PACKET3_SURFACE_BASE_UPDATE 0x73 + + +#define R_008020_GRBM_SOFT_RESET 0x8020 +#define S_008020_SOFT_RESET_CP(x) (((x) & 1) << 0) +#define S_008020_SOFT_RESET_CB(x) (((x) & 1) << 1) +#define S_008020_SOFT_RESET_CR(x) (((x) & 1) << 2) +#define S_008020_SOFT_RESET_DB(x) (((x) & 1) << 3) +#define S_008020_SOFT_RESET_PA(x) (((x) & 1) << 5) +#define S_008020_SOFT_RESET_SC(x) (((x) & 1) << 6) +#define S_008020_SOFT_RESET_SMX(x) (((x) & 1) << 7) +#define S_008020_SOFT_RESET_SPI(x) (((x) & 1) << 8) +#define S_008020_SOFT_RESET_SH(x) (((x) & 1) << 9) +#define S_008020_SOFT_RESET_SX(x) (((x) & 1) << 10) +#define S_008020_SOFT_RESET_TC(x) (((x) & 1) << 11) +#define S_008020_SOFT_RESET_TA(x) (((x) & 1) << 12) +#define S_008020_SOFT_RESET_VC(x) (((x) & 1) << 13) +#define S_008020_SOFT_RESET_VGT(x) (((x) & 1) << 14) +#define R_008010_GRBM_STATUS 0x8010 +#define S_008010_CMDFIFO_AVAIL(x) (((x) & 0x1F) << 0) +#define S_008010_CP_RQ_PENDING(x) (((x) & 1) << 6) +#define S_008010_CF_RQ_PENDING(x) (((x) & 1) << 7) +#define S_008010_PF_RQ_PENDING(x) (((x) & 1) << 8) +#define S_008010_GRBM_EE_BUSY(x) (((x) & 1) << 10) +#define S_008010_VC_BUSY(x) (((x) & 1) << 11) +#define S_008010_DB03_CLEAN(x) (((x) & 1) << 12) +#define S_008010_CB03_CLEAN(x) (((x) & 1) << 13) +#define S_008010_VGT_BUSY_NO_DMA(x) (((x) & 1) << 16) +#define S_008010_VGT_BUSY(x) (((x) & 1) << 17) +#define S_008010_TA03_BUSY(x) (((x) & 1) << 18) +#define S_008010_TC_BUSY(x) (((x) & 1) << 19) +#define S_008010_SX_BUSY(x) (((x) & 1) << 20) +#define S_008010_SH_BUSY(x) (((x) & 1) << 21) +#define S_008010_SPI03_BUSY(x) (((x) & 1) << 22) +#define S_008010_SMX_BUSY(x) (((x) & 1) << 23) +#define S_008010_SC_BUSY(x) (((x) & 1) << 24) +#define S_008010_PA_BUSY(x) (((x) & 1) << 25) +#define S_008010_DB03_BUSY(x) (((x) & 1) << 26) +#define S_008010_CR_BUSY(x) (((x) & 1) << 27) +#define S_008010_CP_COHERENCY_BUSY(x) (((x) & 1) << 28) +#define S_008010_CP_BUSY(x) (((x) & 1) << 29) +#define S_008010_CB03_BUSY(x) (((x) & 1) << 30) +#define S_008010_GUI_ACTIVE(x) (((x) & 1) << 31) +#define G_008010_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x1F) +#define G_008010_CP_RQ_PENDING(x) (((x) >> 6) & 1) +#define G_008010_CF_RQ_PENDING(x) (((x) >> 7) & 1) +#define G_008010_PF_RQ_PENDING(x) (((x) >> 8) & 1) +#define G_008010_GRBM_EE_BUSY(x) (((x) >> 10) & 1) +#define G_008010_VC_BUSY(x) (((x) >> 11) & 1) +#define G_008010_DB03_CLEAN(x) (((x) >> 12) & 1) +#define G_008010_CB03_CLEAN(x) (((x) >> 13) & 1) +#define G_008010_VGT_BUSY_NO_DMA(x) (((x) >> 16) & 1) +#define G_008010_VGT_BUSY(x) (((x) >> 17) & 1) +#define G_008010_TA03_BUSY(x) (((x) >> 18) & 1) +#define G_008010_TC_BUSY(x) (((x) >> 19) & 1) +#define G_008010_SX_BUSY(x) (((x) >> 20) & 1) +#define G_008010_SH_BUSY(x) (((x) >> 21) & 1) +#define G_008010_SPI03_BUSY(x) (((x) >> 22) & 1) +#define G_008010_SMX_BUSY(x) (((x) >> 23) & 1) +#define G_008010_SC_BUSY(x) (((x) >> 24) & 1) +#define G_008010_PA_BUSY(x) (((x) >> 25) & 1) +#define G_008010_DB03_BUSY(x) (((x) >> 26) & 1) +#define G_008010_CR_BUSY(x) (((x) >> 27) & 1) +#define G_008010_CP_COHERENCY_BUSY(x) (((x) >> 28) & 1) +#define G_008010_CP_BUSY(x) (((x) >> 29) & 1) +#define G_008010_CB03_BUSY(x) (((x) >> 30) & 1) +#define G_008010_GUI_ACTIVE(x) (((x) >> 31) & 1) +#define R_008014_GRBM_STATUS2 0x8014 +#define S_008014_CR_CLEAN(x) (((x) & 1) << 0) +#define S_008014_SMX_CLEAN(x) (((x) & 1) << 1) +#define S_008014_SPI0_BUSY(x) (((x) & 1) << 8) +#define S_008014_SPI1_BUSY(x) (((x) & 1) << 9) +#define S_008014_SPI2_BUSY(x) (((x) & 1) << 10) +#define S_008014_SPI3_BUSY(x) (((x) & 1) << 11) +#define S_008014_TA0_BUSY(x) (((x) & 1) << 12) +#define S_008014_TA1_BUSY(x) (((x) & 1) << 13) +#define S_008014_TA2_BUSY(x) (((x) & 1) << 14) +#define S_008014_TA3_BUSY(x) (((x) & 1) << 15) +#define S_008014_DB0_BUSY(x) (((x) & 1) << 16) +#define S_008014_DB1_BUSY(x) (((x) & 1) << 17) +#define S_008014_DB2_BUSY(x) (((x) & 1) << 18) +#define S_008014_DB3_BUSY(x) (((x) & 1) << 19) +#define S_008014_CB0_BUSY(x) (((x) & 1) << 20) +#define S_008014_CB1_BUSY(x) (((x) & 1) << 21) +#define S_008014_CB2_BUSY(x) (((x) & 1) << 22) +#define S_008014_CB3_BUSY(x) (((x) & 1) << 23) +#define G_008014_CR_CLEAN(x) (((x) >> 0) & 1) +#define G_008014_SMX_CLEAN(x) (((x) >> 1) & 1) +#define G_008014_SPI0_BUSY(x) (((x) >> 8) & 1) +#define G_008014_SPI1_BUSY(x) (((x) >> 9) & 1) +#define G_008014_SPI2_BUSY(x) (((x) >> 10) & 1) +#define G_008014_SPI3_BUSY(x) (((x) >> 11) & 1) +#define G_008014_TA0_BUSY(x) (((x) >> 12) & 1) +#define G_008014_TA1_BUSY(x) (((x) >> 13) & 1) +#define G_008014_TA2_BUSY(x) (((x) >> 14) & 1) +#define G_008014_TA3_BUSY(x) (((x) >> 15) & 1) +#define G_008014_DB0_BUSY(x) (((x) >> 16) & 1) +#define G_008014_DB1_BUSY(x) (((x) >> 17) & 1) +#define G_008014_DB2_BUSY(x) (((x) >> 18) & 1) +#define G_008014_DB3_BUSY(x) (((x) >> 19) & 1) +#define G_008014_CB0_BUSY(x) (((x) >> 20) & 1) +#define G_008014_CB1_BUSY(x) (((x) >> 21) & 1) +#define G_008014_CB2_BUSY(x) (((x) >> 22) & 1) +#define G_008014_CB3_BUSY(x) (((x) >> 23) & 1) +#define R_000E50_SRBM_STATUS 0x0E50 +#define G_000E50_RLC_RQ_PENDING(x) (((x) >> 3) & 1) +#define G_000E50_RCU_RQ_PENDING(x) (((x) >> 4) & 1) +#define G_000E50_GRBM_RQ_PENDING(x) (((x) >> 5) & 1) +#define G_000E50_HI_RQ_PENDING(x) (((x) >> 6) & 1) +#define G_000E50_IO_EXTERN_SIGNAL(x) (((x) >> 7) & 1) +#define G_000E50_VMC_BUSY(x) (((x) >> 8) & 1) +#define G_000E50_MCB_BUSY(x) (((x) >> 9) & 1) +#define G_000E50_MCDZ_BUSY(x) (((x) >> 10) & 1) +#define G_000E50_MCDY_BUSY(x) (((x) >> 11) & 1) +#define G_000E50_MCDX_BUSY(x) (((x) >> 12) & 1) +#define G_000E50_MCDW_BUSY(x) (((x) >> 13) & 1) +#define G_000E50_SEM_BUSY(x) (((x) >> 14) & 1) +#define G_000E50_RLC_BUSY(x) (((x) >> 15) & 1) +#define G_000E50_BIF_BUSY(x) (((x) >> 29) & 1) +#define R_000E60_SRBM_SOFT_RESET 0x0E60 +#define S_000E60_SOFT_RESET_BIF(x) (((x) & 1) << 1) +#define S_000E60_SOFT_RESET_CG(x) (((x) & 1) << 2) +#define S_000E60_SOFT_RESET_CMC(x) (((x) & 1) << 3) +#define S_000E60_SOFT_RESET_CSC(x) (((x) & 1) << 4) +#define S_000E60_SOFT_RESET_DC(x) (((x) & 1) << 5) +#define S_000E60_SOFT_RESET_GRBM(x) (((x) & 1) << 8) +#define S_000E60_SOFT_RESET_HDP(x) (((x) & 1) << 9) +#define S_000E60_SOFT_RESET_IH(x) (((x) & 1) << 10) +#define S_000E60_SOFT_RESET_MC(x) (((x) & 1) << 11) +#define S_000E60_SOFT_RESET_RLC(x) (((x) & 1) << 13) +#define S_000E60_SOFT_RESET_ROM(x) (((x) & 1) << 14) +#define S_000E60_SOFT_RESET_SEM(x) (((x) & 1) << 15) +#define S_000E60_SOFT_RESET_TSC(x) (((x) & 1) << 16) +#define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17) + +#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 + +#define R_028C04_PA_SC_AA_CONFIG 0x028C04 +#define S_028C04_MSAA_NUM_SAMPLES(x) (((x) & 0x3) << 0) +#define G_028C04_MSAA_NUM_SAMPLES(x) (((x) >> 0) & 0x3) +#define C_028C04_MSAA_NUM_SAMPLES 0xFFFFFFFC +#define S_028C04_AA_MASK_CENTROID_DTMN(x) (((x) & 0x1) << 4) +#define G_028C04_AA_MASK_CENTROID_DTMN(x) (((x) >> 4) & 0x1) +#define C_028C04_AA_MASK_CENTROID_DTMN 0xFFFFFFEF +#define S_028C04_MAX_SAMPLE_DIST(x) (((x) & 0xF) << 13) +#define G_028C04_MAX_SAMPLE_DIST(x) (((x) >> 13) & 0xF) +#define C_028C04_MAX_SAMPLE_DIST 0xFFFE1FFF +#define R_0280E0_CB_COLOR0_FRAG 0x0280E0 +#define S_0280E0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0280E0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0280E0_BASE_256B 0x00000000 +#define R_0280E4_CB_COLOR1_FRAG 0x0280E4 +#define R_0280E8_CB_COLOR2_FRAG 0x0280E8 +#define R_0280EC_CB_COLOR3_FRAG 0x0280EC +#define R_0280F0_CB_COLOR4_FRAG 0x0280F0 +#define R_0280F4_CB_COLOR5_FRAG 0x0280F4 +#define R_0280F8_CB_COLOR6_FRAG 0x0280F8 +#define R_0280FC_CB_COLOR7_FRAG 0x0280FC +#define R_0280C0_CB_COLOR0_TILE 0x0280C0 +#define S_0280C0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0280C0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0280C0_BASE_256B 0x00000000 +#define R_0280C4_CB_COLOR1_TILE 0x0280C4 +#define R_0280C8_CB_COLOR2_TILE 0x0280C8 +#define R_0280CC_CB_COLOR3_TILE 0x0280CC +#define R_0280D0_CB_COLOR4_TILE 0x0280D0 +#define R_0280D4_CB_COLOR5_TILE 0x0280D4 +#define R_0280D8_CB_COLOR6_TILE 0x0280D8 +#define R_0280DC_CB_COLOR7_TILE 0x0280DC +#define R_0280A0_CB_COLOR0_INFO 0x0280A0 +#define S_0280A0_ENDIAN(x) (((x) & 0x3) << 0) +#define G_0280A0_ENDIAN(x) (((x) >> 0) & 0x3) +#define C_0280A0_ENDIAN 0xFFFFFFFC +#define S_0280A0_FORMAT(x) (((x) & 0x3F) << 2) +#define G_0280A0_FORMAT(x) (((x) >> 2) & 0x3F) +#define C_0280A0_FORMAT 0xFFFFFF03 +#define V_0280A0_COLOR_INVALID 0x00000000 +#define V_0280A0_COLOR_8 0x00000001 +#define V_0280A0_COLOR_4_4 0x00000002 +#define V_0280A0_COLOR_3_3_2 0x00000003 +#define V_0280A0_COLOR_16 0x00000005 +#define V_0280A0_COLOR_16_FLOAT 0x00000006 +#define V_0280A0_COLOR_8_8 0x00000007 +#define V_0280A0_COLOR_5_6_5 0x00000008 +#define V_0280A0_COLOR_6_5_5 0x00000009 +#define V_0280A0_COLOR_1_5_5_5 0x0000000A +#define V_0280A0_COLOR_4_4_4_4 0x0000000B +#define V_0280A0_COLOR_5_5_5_1 0x0000000C +#define V_0280A0_COLOR_32 0x0000000D +#define V_0280A0_COLOR_32_FLOAT 0x0000000E +#define V_0280A0_COLOR_16_16 0x0000000F +#define V_0280A0_COLOR_16_16_FLOAT 0x00000010 +#define V_0280A0_COLOR_8_24 0x00000011 +#define V_0280A0_COLOR_8_24_FLOAT 0x00000012 +#define V_0280A0_COLOR_24_8 0x00000013 +#define V_0280A0_COLOR_24_8_FLOAT 0x00000014 +#define V_0280A0_COLOR_10_11_11 0x00000015 +#define V_0280A0_COLOR_10_11_11_FLOAT 0x00000016 +#define V_0280A0_COLOR_11_11_10 0x00000017 +#define V_0280A0_COLOR_11_11_10_FLOAT 0x00000018 +#define V_0280A0_COLOR_2_10_10_10 0x00000019 +#define V_0280A0_COLOR_8_8_8_8 0x0000001A +#define V_0280A0_COLOR_10_10_10_2 0x0000001B +#define V_0280A0_COLOR_X24_8_32_FLOAT 0x0000001C +#define V_0280A0_COLOR_32_32 0x0000001D +#define V_0280A0_COLOR_32_32_FLOAT 0x0000001E +#define V_0280A0_COLOR_16_16_16_16 0x0000001F +#define V_0280A0_COLOR_16_16_16_16_FLOAT 0x00000020 +#define V_0280A0_COLOR_32_32_32_32 0x00000022 +#define V_0280A0_COLOR_32_32_32_32_FLOAT 0x00000023 +#define S_0280A0_ARRAY_MODE(x) (((x) & 0xF) << 8) +#define G_0280A0_ARRAY_MODE(x) (((x) >> 8) & 0xF) +#define C_0280A0_ARRAY_MODE 0xFFFFF0FF +#define V_0280A0_ARRAY_LINEAR_GENERAL 0x00000000 +#define V_0280A0_ARRAY_LINEAR_ALIGNED 0x00000001 +#define V_0280A0_ARRAY_1D_TILED_THIN1 0x00000002 +#define V_0280A0_ARRAY_2D_TILED_THIN1 0x00000004 +#define S_0280A0_NUMBER_TYPE(x) (((x) & 0x7) << 12) +#define G_0280A0_NUMBER_TYPE(x) (((x) >> 12) & 0x7) +#define C_0280A0_NUMBER_TYPE 0xFFFF8FFF +#define S_0280A0_READ_SIZE(x) (((x) & 0x1) << 15) +#define G_0280A0_READ_SIZE(x) (((x) >> 15) & 0x1) +#define C_0280A0_READ_SIZE 0xFFFF7FFF +#define S_0280A0_COMP_SWAP(x) (((x) & 0x3) << 16) +#define G_0280A0_COMP_SWAP(x) (((x) >> 16) & 0x3) +#define C_0280A0_COMP_SWAP 0xFFFCFFFF +#define S_0280A0_TILE_MODE(x) (((x) & 0x3) << 18) +#define G_0280A0_TILE_MODE(x) (((x) >> 18) & 0x3) +#define C_0280A0_TILE_MODE 0xFFF3FFFF +#define V_0280A0_TILE_DISABLE 0 +#define V_0280A0_CLEAR_ENABLE 1 +#define V_0280A0_FRAG_ENABLE 2 +#define S_0280A0_BLEND_CLAMP(x) (((x) & 0x1) << 20) +#define G_0280A0_BLEND_CLAMP(x) (((x) >> 20) & 0x1) +#define C_0280A0_BLEND_CLAMP 0xFFEFFFFF +#define S_0280A0_CLEAR_COLOR(x) (((x) & 0x1) << 21) +#define G_0280A0_CLEAR_COLOR(x) (((x) >> 21) & 0x1) +#define C_0280A0_CLEAR_COLOR 0xFFDFFFFF +#define S_0280A0_BLEND_BYPASS(x) (((x) & 0x1) << 22) +#define G_0280A0_BLEND_BYPASS(x) (((x) >> 22) & 0x1) +#define C_0280A0_BLEND_BYPASS 0xFFBFFFFF +#define S_0280A0_BLEND_FLOAT32(x) (((x) & 0x1) << 23) +#define G_0280A0_BLEND_FLOAT32(x) (((x) >> 23) & 0x1) +#define C_0280A0_BLEND_FLOAT32 0xFF7FFFFF +#define S_0280A0_SIMPLE_FLOAT(x) (((x) & 0x1) << 24) +#define G_0280A0_SIMPLE_FLOAT(x) (((x) >> 24) & 0x1) +#define C_0280A0_SIMPLE_FLOAT 0xFEFFFFFF +#define S_0280A0_ROUND_MODE(x) (((x) & 0x1) << 25) +#define G_0280A0_ROUND_MODE(x) (((x) >> 25) & 0x1) +#define C_0280A0_ROUND_MODE 0xFDFFFFFF +#define S_0280A0_TILE_COMPACT(x) (((x) & 0x1) << 26) +#define G_0280A0_TILE_COMPACT(x) (((x) >> 26) & 0x1) +#define C_0280A0_TILE_COMPACT 0xFBFFFFFF +#define S_0280A0_SOURCE_FORMAT(x) (((x) & 0x1) << 27) +#define G_0280A0_SOURCE_FORMAT(x) (((x) >> 27) & 0x1) +#define C_0280A0_SOURCE_FORMAT 0xF7FFFFFF +#define R_0280A4_CB_COLOR1_INFO 0x0280A4 +#define R_0280A8_CB_COLOR2_INFO 0x0280A8 +#define R_0280AC_CB_COLOR3_INFO 0x0280AC +#define R_0280B0_CB_COLOR4_INFO 0x0280B0 +#define R_0280B4_CB_COLOR5_INFO 0x0280B4 +#define R_0280B8_CB_COLOR6_INFO 0x0280B8 +#define R_0280BC_CB_COLOR7_INFO 0x0280BC +#define R_028060_CB_COLOR0_SIZE 0x028060 +#define S_028060_PITCH_TILE_MAX(x) (((x) & 0x3FF) << 0) +#define G_028060_PITCH_TILE_MAX(x) (((x) >> 0) & 0x3FF) +#define C_028060_PITCH_TILE_MAX 0xFFFFFC00 +#define S_028060_SLICE_TILE_MAX(x) (((x) & 0xFFFFF) << 10) +#define G_028060_SLICE_TILE_MAX(x) (((x) >> 10) & 0xFFFFF) +#define C_028060_SLICE_TILE_MAX 0xC00003FF +#define R_028064_CB_COLOR1_SIZE 0x028064 +#define R_028068_CB_COLOR2_SIZE 0x028068 +#define R_02806C_CB_COLOR3_SIZE 0x02806C +#define R_028070_CB_COLOR4_SIZE 0x028070 +#define R_028074_CB_COLOR5_SIZE 0x028074 +#define R_028078_CB_COLOR6_SIZE 0x028078 +#define R_02807C_CB_COLOR7_SIZE 0x02807C +#define R_028238_CB_TARGET_MASK 0x028238 +#define S_028238_TARGET0_ENABLE(x) (((x) & 0xF) << 0) +#define G_028238_TARGET0_ENABLE(x) (((x) >> 0) & 0xF) +#define C_028238_TARGET0_ENABLE 0xFFFFFFF0 +#define S_028238_TARGET1_ENABLE(x) (((x) & 0xF) << 4) +#define G_028238_TARGET1_ENABLE(x) (((x) >> 4) & 0xF) +#define C_028238_TARGET1_ENABLE 0xFFFFFF0F +#define S_028238_TARGET2_ENABLE(x) (((x) & 0xF) << 8) +#define G_028238_TARGET2_ENABLE(x) (((x) >> 8) & 0xF) +#define C_028238_TARGET2_ENABLE 0xFFFFF0FF +#define S_028238_TARGET3_ENABLE(x) (((x) & 0xF) << 12) +#define G_028238_TARGET3_ENABLE(x) (((x) >> 12) & 0xF) +#define C_028238_TARGET3_ENABLE 0xFFFF0FFF +#define S_028238_TARGET4_ENABLE(x) (((x) & 0xF) << 16) +#define G_028238_TARGET4_ENABLE(x) (((x) >> 16) & 0xF) +#define C_028238_TARGET4_ENABLE 0xFFF0FFFF +#define S_028238_TARGET5_ENABLE(x) (((x) & 0xF) << 20) +#define G_028238_TARGET5_ENABLE(x) (((x) >> 20) & 0xF) +#define C_028238_TARGET5_ENABLE 0xFF0FFFFF +#define S_028238_TARGET6_ENABLE(x) (((x) & 0xF) << 24) +#define G_028238_TARGET6_ENABLE(x) (((x) >> 24) & 0xF) +#define C_028238_TARGET6_ENABLE 0xF0FFFFFF +#define S_028238_TARGET7_ENABLE(x) (((x) & 0xF) << 28) +#define G_028238_TARGET7_ENABLE(x) (((x) >> 28) & 0xF) +#define C_028238_TARGET7_ENABLE 0x0FFFFFFF +#define R_02823C_CB_SHADER_MASK 0x02823C +#define S_02823C_OUTPUT0_ENABLE(x) (((x) & 0xF) << 0) +#define G_02823C_OUTPUT0_ENABLE(x) (((x) >> 0) & 0xF) +#define C_02823C_OUTPUT0_ENABLE 0xFFFFFFF0 +#define S_02823C_OUTPUT1_ENABLE(x) (((x) & 0xF) << 4) +#define G_02823C_OUTPUT1_ENABLE(x) (((x) >> 4) & 0xF) +#define C_02823C_OUTPUT1_ENABLE 0xFFFFFF0F +#define S_02823C_OUTPUT2_ENABLE(x) (((x) & 0xF) << 8) +#define G_02823C_OUTPUT2_ENABLE(x) (((x) >> 8) & 0xF) +#define C_02823C_OUTPUT2_ENABLE 0xFFFFF0FF +#define S_02823C_OUTPUT3_ENABLE(x) (((x) & 0xF) << 12) +#define G_02823C_OUTPUT3_ENABLE(x) (((x) >> 12) & 0xF) +#define C_02823C_OUTPUT3_ENABLE 0xFFFF0FFF +#define S_02823C_OUTPUT4_ENABLE(x) (((x) & 0xF) << 16) +#define G_02823C_OUTPUT4_ENABLE(x) (((x) >> 16) & 0xF) +#define C_02823C_OUTPUT4_ENABLE 0xFFF0FFFF +#define S_02823C_OUTPUT5_ENABLE(x) (((x) & 0xF) << 20) +#define G_02823C_OUTPUT5_ENABLE(x) (((x) >> 20) & 0xF) +#define C_02823C_OUTPUT5_ENABLE 0xFF0FFFFF +#define S_02823C_OUTPUT6_ENABLE(x) (((x) & 0xF) << 24) +#define G_02823C_OUTPUT6_ENABLE(x) (((x) >> 24) & 0xF) +#define C_02823C_OUTPUT6_ENABLE 0xF0FFFFFF +#define S_02823C_OUTPUT7_ENABLE(x) (((x) & 0xF) << 28) +#define G_02823C_OUTPUT7_ENABLE(x) (((x) >> 28) & 0xF) +#define C_02823C_OUTPUT7_ENABLE 0x0FFFFFFF +#define R_028AB0_VGT_STRMOUT_EN 0x028AB0 +#define S_028AB0_STREAMOUT(x) (((x) & 0x1) << 0) +#define G_028AB0_STREAMOUT(x) (((x) >> 0) & 0x1) +#define C_028AB0_STREAMOUT 0xFFFFFFFE +#define R_028B20_VGT_STRMOUT_BUFFER_EN 0x028B20 +#define S_028B20_BUFFER_0_EN(x) (((x) & 0x1) << 0) +#define G_028B20_BUFFER_0_EN(x) (((x) >> 0) & 0x1) +#define C_028B20_BUFFER_0_EN 0xFFFFFFFE +#define S_028B20_BUFFER_1_EN(x) (((x) & 0x1) << 1) +#define G_028B20_BUFFER_1_EN(x) (((x) >> 1) & 0x1) +#define C_028B20_BUFFER_1_EN 0xFFFFFFFD +#define S_028B20_BUFFER_2_EN(x) (((x) & 0x1) << 2) +#define G_028B20_BUFFER_2_EN(x) (((x) >> 2) & 0x1) +#define C_028B20_BUFFER_2_EN 0xFFFFFFFB +#define S_028B20_BUFFER_3_EN(x) (((x) & 0x1) << 3) +#define G_028B20_BUFFER_3_EN(x) (((x) >> 3) & 0x1) +#define C_028B20_BUFFER_3_EN 0xFFFFFFF7 +#define S_028B20_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_028B20_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_028B20_SIZE 0x00000000 +#define R_038000_SQ_TEX_RESOURCE_WORD0_0 0x038000 +#define S_038000_DIM(x) (((x) & 0x7) << 0) +#define G_038000_DIM(x) (((x) >> 0) & 0x7) +#define C_038000_DIM 0xFFFFFFF8 +#define V_038000_SQ_TEX_DIM_1D 0x00000000 +#define V_038000_SQ_TEX_DIM_2D 0x00000001 +#define V_038000_SQ_TEX_DIM_3D 0x00000002 +#define V_038000_SQ_TEX_DIM_CUBEMAP 0x00000003 +#define V_038000_SQ_TEX_DIM_1D_ARRAY 0x00000004 +#define V_038000_SQ_TEX_DIM_2D_ARRAY 0x00000005 +#define V_038000_SQ_TEX_DIM_2D_MSAA 0x00000006 +#define V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007 +#define S_038000_TILE_MODE(x) (((x) & 0xF) << 3) +#define G_038000_TILE_MODE(x) (((x) >> 3) & 0xF) +#define C_038000_TILE_MODE 0xFFFFFF87 +#define V_038000_ARRAY_LINEAR_GENERAL 0x00000000 +#define V_038000_ARRAY_LINEAR_ALIGNED 0x00000001 +#define V_038000_ARRAY_1D_TILED_THIN1 0x00000002 +#define V_038000_ARRAY_2D_TILED_THIN1 0x00000004 +#define S_038000_TILE_TYPE(x) (((x) & 0x1) << 7) +#define G_038000_TILE_TYPE(x) (((x) >> 7) & 0x1) +#define C_038000_TILE_TYPE 0xFFFFFF7F +#define S_038000_PITCH(x) (((x) & 0x7FF) << 8) +#define G_038000_PITCH(x) (((x) >> 8) & 0x7FF) +#define C_038000_PITCH 0xFFF800FF +#define S_038000_TEX_WIDTH(x) (((x) & 0x1FFF) << 19) +#define G_038000_TEX_WIDTH(x) (((x) >> 19) & 0x1FFF) +#define C_038000_TEX_WIDTH 0x0007FFFF +#define R_038004_SQ_TEX_RESOURCE_WORD1_0 0x038004 +#define S_038004_TEX_HEIGHT(x) (((x) & 0x1FFF) << 0) +#define G_038004_TEX_HEIGHT(x) (((x) >> 0) & 0x1FFF) +#define C_038004_TEX_HEIGHT 0xFFFFE000 +#define S_038004_TEX_DEPTH(x) (((x) & 0x1FFF) << 13) +#define G_038004_TEX_DEPTH(x) (((x) >> 13) & 0x1FFF) +#define C_038004_TEX_DEPTH 0xFC001FFF +#define S_038004_DATA_FORMAT(x) (((x) & 0x3F) << 26) +#define G_038004_DATA_FORMAT(x) (((x) >> 26) & 0x3F) +#define C_038004_DATA_FORMAT 0x03FFFFFF +#define V_038004_COLOR_INVALID 0x00000000 +#define V_038004_COLOR_8 0x00000001 +#define V_038004_COLOR_4_4 0x00000002 +#define V_038004_COLOR_3_3_2 0x00000003 +#define V_038004_COLOR_16 0x00000005 +#define V_038004_COLOR_16_FLOAT 0x00000006 +#define V_038004_COLOR_8_8 0x00000007 +#define V_038004_COLOR_5_6_5 0x00000008 +#define V_038004_COLOR_6_5_5 0x00000009 +#define V_038004_COLOR_1_5_5_5 0x0000000A +#define V_038004_COLOR_4_4_4_4 0x0000000B +#define V_038004_COLOR_5_5_5_1 0x0000000C +#define V_038004_COLOR_32 0x0000000D +#define V_038004_COLOR_32_FLOAT 0x0000000E +#define V_038004_COLOR_16_16 0x0000000F +#define V_038004_COLOR_16_16_FLOAT 0x00000010 +#define V_038004_COLOR_8_24 0x00000011 +#define V_038004_COLOR_8_24_FLOAT 0x00000012 +#define V_038004_COLOR_24_8 0x00000013 +#define V_038004_COLOR_24_8_FLOAT 0x00000014 +#define V_038004_COLOR_10_11_11 0x00000015 +#define V_038004_COLOR_10_11_11_FLOAT 0x00000016 +#define V_038004_COLOR_11_11_10 0x00000017 +#define V_038004_COLOR_11_11_10_FLOAT 0x00000018 +#define V_038004_COLOR_2_10_10_10 0x00000019 +#define V_038004_COLOR_8_8_8_8 0x0000001A +#define V_038004_COLOR_10_10_10_2 0x0000001B +#define V_038004_COLOR_X24_8_32_FLOAT 0x0000001C +#define V_038004_COLOR_32_32 0x0000001D +#define V_038004_COLOR_32_32_FLOAT 0x0000001E +#define V_038004_COLOR_16_16_16_16 0x0000001F +#define V_038004_COLOR_16_16_16_16_FLOAT 0x00000020 +#define V_038004_COLOR_32_32_32_32 0x00000022 +#define V_038004_COLOR_32_32_32_32_FLOAT 0x00000023 +#define V_038004_FMT_1 0x00000025 +#define V_038004_FMT_GB_GR 0x00000027 +#define V_038004_FMT_BG_RG 0x00000028 +#define V_038004_FMT_32_AS_8 0x00000029 +#define V_038004_FMT_32_AS_8_8 0x0000002A +#define V_038004_FMT_5_9_9_9_SHAREDEXP 0x0000002B +#define V_038004_FMT_8_8_8 0x0000002C +#define V_038004_FMT_16_16_16 0x0000002D +#define V_038004_FMT_16_16_16_FLOAT 0x0000002E +#define V_038004_FMT_32_32_32 0x0000002F +#define V_038004_FMT_32_32_32_FLOAT 0x00000030 +#define V_038004_FMT_BC1 0x00000031 +#define V_038004_FMT_BC2 0x00000032 +#define V_038004_FMT_BC3 0x00000033 +#define V_038004_FMT_BC4 0x00000034 +#define V_038004_FMT_BC5 0x00000035 +#define V_038004_FMT_BC6 0x00000036 +#define V_038004_FMT_BC7 0x00000037 +#define V_038004_FMT_32_AS_32_32_32_32 0x00000038 +#define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010 +#define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) +#define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) +#define C_038010_FORMAT_COMP_X 0xFFFFFFFC +#define S_038010_FORMAT_COMP_Y(x) (((x) & 0x3) << 2) +#define G_038010_FORMAT_COMP_Y(x) (((x) >> 2) & 0x3) +#define C_038010_FORMAT_COMP_Y 0xFFFFFFF3 +#define S_038010_FORMAT_COMP_Z(x) (((x) & 0x3) << 4) +#define G_038010_FORMAT_COMP_Z(x) (((x) >> 4) & 0x3) +#define C_038010_FORMAT_COMP_Z 0xFFFFFFCF +#define S_038010_FORMAT_COMP_W(x) (((x) & 0x3) << 6) +#define G_038010_FORMAT_COMP_W(x) (((x) >> 6) & 0x3) +#define C_038010_FORMAT_COMP_W 0xFFFFFF3F +#define S_038010_NUM_FORMAT_ALL(x) (((x) & 0x3) << 8) +#define G_038010_NUM_FORMAT_ALL(x) (((x) >> 8) & 0x3) +#define C_038010_NUM_FORMAT_ALL 0xFFFFFCFF +#define S_038010_SRF_MODE_ALL(x) (((x) & 0x1) << 10) +#define G_038010_SRF_MODE_ALL(x) (((x) >> 10) & 0x1) +#define C_038010_SRF_MODE_ALL 0xFFFFFBFF +#define S_038010_FORCE_DEGAMMA(x) (((x) & 0x1) << 11) +#define G_038010_FORCE_DEGAMMA(x) (((x) >> 11) & 0x1) +#define C_038010_FORCE_DEGAMMA 0xFFFFF7FF +#define S_038010_ENDIAN_SWAP(x) (((x) & 0x3) << 12) +#define G_038010_ENDIAN_SWAP(x) (((x) >> 12) & 0x3) +#define C_038010_ENDIAN_SWAP 0xFFFFCFFF +#define S_038010_REQUEST_SIZE(x) (((x) & 0x3) << 14) +#define G_038010_REQUEST_SIZE(x) (((x) >> 14) & 0x3) +#define C_038010_REQUEST_SIZE 0xFFFF3FFF +#define S_038010_DST_SEL_X(x) (((x) & 0x7) << 16) +#define G_038010_DST_SEL_X(x) (((x) >> 16) & 0x7) +#define C_038010_DST_SEL_X 0xFFF8FFFF +#define S_038010_DST_SEL_Y(x) (((x) & 0x7) << 19) +#define G_038010_DST_SEL_Y(x) (((x) >> 19) & 0x7) +#define C_038010_DST_SEL_Y 0xFFC7FFFF +#define S_038010_DST_SEL_Z(x) (((x) & 0x7) << 22) +#define G_038010_DST_SEL_Z(x) (((x) >> 22) & 0x7) +#define C_038010_DST_SEL_Z 0xFE3FFFFF +#define S_038010_DST_SEL_W(x) (((x) & 0x7) << 25) +#define G_038010_DST_SEL_W(x) (((x) >> 25) & 0x7) +#define C_038010_DST_SEL_W 0xF1FFFFFF +# define SQ_SEL_X 0 +# define SQ_SEL_Y 1 +# define SQ_SEL_Z 2 +# define SQ_SEL_W 3 +# define SQ_SEL_0 4 +# define SQ_SEL_1 5 +#define S_038010_BASE_LEVEL(x) (((x) & 0xF) << 28) +#define G_038010_BASE_LEVEL(x) (((x) >> 28) & 0xF) +#define C_038010_BASE_LEVEL 0x0FFFFFFF +#define R_038014_SQ_TEX_RESOURCE_WORD5_0 0x038014 +#define S_038014_LAST_LEVEL(x) (((x) & 0xF) << 0) +#define G_038014_LAST_LEVEL(x) (((x) >> 0) & 0xF) +#define C_038014_LAST_LEVEL 0xFFFFFFF0 +#define S_038014_BASE_ARRAY(x) (((x) & 0x1FFF) << 4) +#define G_038014_BASE_ARRAY(x) (((x) >> 4) & 0x1FFF) +#define C_038014_BASE_ARRAY 0xFFFE000F +#define S_038014_LAST_ARRAY(x) (((x) & 0x1FFF) << 17) +#define G_038014_LAST_ARRAY(x) (((x) >> 17) & 0x1FFF) +#define C_038014_LAST_ARRAY 0xC001FFFF +#define R_0288A8_SQ_ESGS_RING_ITEMSIZE 0x0288A8 +#define S_0288A8_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288A8_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288A8_ITEMSIZE 0xFFFF8000 +#define R_008C44_SQ_ESGS_RING_SIZE 0x008C44 +#define S_008C44_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C44_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C44_MEM_SIZE 0x00000000 +#define R_0288B0_SQ_ESTMP_RING_ITEMSIZE 0x0288B0 +#define S_0288B0_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288B0_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288B0_ITEMSIZE 0xFFFF8000 +#define R_008C54_SQ_ESTMP_RING_SIZE 0x008C54 +#define S_008C54_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C54_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C54_MEM_SIZE 0x00000000 +#define R_0288C0_SQ_FBUF_RING_ITEMSIZE 0x0288C0 +#define S_0288C0_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288C0_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288C0_ITEMSIZE 0xFFFF8000 +#define R_008C74_SQ_FBUF_RING_SIZE 0x008C74 +#define S_008C74_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C74_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C74_MEM_SIZE 0x00000000 +#define R_0288B4_SQ_GSTMP_RING_ITEMSIZE 0x0288B4 +#define S_0288B4_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288B4_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288B4_ITEMSIZE 0xFFFF8000 +#define R_008C5C_SQ_GSTMP_RING_SIZE 0x008C5C +#define S_008C5C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C5C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C5C_MEM_SIZE 0x00000000 +#define R_0288AC_SQ_GSVS_RING_ITEMSIZE 0x0288AC +#define S_0288AC_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288AC_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288AC_ITEMSIZE 0xFFFF8000 +#define R_008C4C_SQ_GSVS_RING_SIZE 0x008C4C +#define S_008C4C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C4C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C4C_MEM_SIZE 0x00000000 +#define R_0288BC_SQ_PSTMP_RING_ITEMSIZE 0x0288BC +#define S_0288BC_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288BC_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288BC_ITEMSIZE 0xFFFF8000 +#define R_008C6C_SQ_PSTMP_RING_SIZE 0x008C6C +#define S_008C6C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C6C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C6C_MEM_SIZE 0x00000000 +#define R_0288C4_SQ_REDUC_RING_ITEMSIZE 0x0288C4 +#define S_0288C4_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288C4_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288C4_ITEMSIZE 0xFFFF8000 +#define R_008C7C_SQ_REDUC_RING_SIZE 0x008C7C +#define S_008C7C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C7C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C7C_MEM_SIZE 0x00000000 +#define R_0288B8_SQ_VSTMP_RING_ITEMSIZE 0x0288B8 +#define S_0288B8_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288B8_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288B8_ITEMSIZE 0xFFFF8000 +#define R_008C64_SQ_VSTMP_RING_SIZE 0x008C64 +#define S_008C64_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_008C64_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_008C64_MEM_SIZE 0x00000000 +#define R_0288C8_SQ_GS_VERT_ITEMSIZE 0x0288C8 +#define S_0288C8_ITEMSIZE(x) (((x) & 0x7FFF) << 0) +#define G_0288C8_ITEMSIZE(x) (((x) >> 0) & 0x7FFF) +#define C_0288C8_ITEMSIZE 0xFFFF8000 +#define R_028010_DB_DEPTH_INFO 0x028010 +#define S_028010_FORMAT(x) (((x) & 0x7) << 0) +#define G_028010_FORMAT(x) (((x) >> 0) & 0x7) +#define C_028010_FORMAT 0xFFFFFFF8 +#define V_028010_DEPTH_INVALID 0x00000000 +#define V_028010_DEPTH_16 0x00000001 +#define V_028010_DEPTH_X8_24 0x00000002 +#define V_028010_DEPTH_8_24 0x00000003 +#define V_028010_DEPTH_X8_24_FLOAT 0x00000004 +#define V_028010_DEPTH_8_24_FLOAT 0x00000005 +#define V_028010_DEPTH_32_FLOAT 0x00000006 +#define V_028010_DEPTH_X24_8_32_FLOAT 0x00000007 +#define S_028010_READ_SIZE(x) (((x) & 0x1) << 3) +#define G_028010_READ_SIZE(x) (((x) >> 3) & 0x1) +#define C_028010_READ_SIZE 0xFFFFFFF7 +#define S_028010_ARRAY_MODE(x) (((x) & 0xF) << 15) +#define G_028010_ARRAY_MODE(x) (((x) >> 15) & 0xF) +#define C_028010_ARRAY_MODE 0xFFF87FFF +#define V_028010_ARRAY_1D_TILED_THIN1 0x00000002 +#define V_028010_ARRAY_2D_TILED_THIN1 0x00000004 +#define S_028010_TILE_SURFACE_ENABLE(x) (((x) & 0x1) << 25) +#define G_028010_TILE_SURFACE_ENABLE(x) (((x) >> 25) & 0x1) +#define C_028010_TILE_SURFACE_ENABLE 0xFDFFFFFF +#define S_028010_TILE_COMPACT(x) (((x) & 0x1) << 26) +#define G_028010_TILE_COMPACT(x) (((x) >> 26) & 0x1) +#define C_028010_TILE_COMPACT 0xFBFFFFFF +#define S_028010_ZRANGE_PRECISION(x) (((x) & 0x1) << 31) +#define G_028010_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1) +#define C_028010_ZRANGE_PRECISION 0x7FFFFFFF +#define R_028000_DB_DEPTH_SIZE 0x028000 +#define S_028000_PITCH_TILE_MAX(x) (((x) & 0x3FF) << 0) +#define G_028000_PITCH_TILE_MAX(x) (((x) >> 0) & 0x3FF) +#define C_028000_PITCH_TILE_MAX 0xFFFFFC00 +#define S_028000_SLICE_TILE_MAX(x) (((x) & 0xFFFFF) << 10) +#define G_028000_SLICE_TILE_MAX(x) (((x) >> 10) & 0xFFFFF) +#define C_028000_SLICE_TILE_MAX 0xC00003FF +#define R_028004_DB_DEPTH_VIEW 0x028004 +#define S_028004_SLICE_START(x) (((x) & 0x7FF) << 0) +#define G_028004_SLICE_START(x) (((x) >> 0) & 0x7FF) +#define C_028004_SLICE_START 0xFFFFF800 +#define S_028004_SLICE_MAX(x) (((x) & 0x7FF) << 13) +#define G_028004_SLICE_MAX(x) (((x) >> 13) & 0x7FF) +#define C_028004_SLICE_MAX 0xFF001FFF +#define R_028800_DB_DEPTH_CONTROL 0x028800 +#define S_028800_STENCIL_ENABLE(x) (((x) & 0x1) << 0) +#define G_028800_STENCIL_ENABLE(x) (((x) >> 0) & 0x1) +#define C_028800_STENCIL_ENABLE 0xFFFFFFFE +#define S_028800_Z_ENABLE(x) (((x) & 0x1) << 1) +#define G_028800_Z_ENABLE(x) (((x) >> 1) & 0x1) +#define C_028800_Z_ENABLE 0xFFFFFFFD +#define S_028800_Z_WRITE_ENABLE(x) (((x) & 0x1) << 2) +#define G_028800_Z_WRITE_ENABLE(x) (((x) >> 2) & 0x1) +#define C_028800_Z_WRITE_ENABLE 0xFFFFFFFB +#define S_028800_ZFUNC(x) (((x) & 0x7) << 4) +#define G_028800_ZFUNC(x) (((x) >> 4) & 0x7) +#define C_028800_ZFUNC 0xFFFFFF8F +#define S_028800_BACKFACE_ENABLE(x) (((x) & 0x1) << 7) +#define G_028800_BACKFACE_ENABLE(x) (((x) >> 7) & 0x1) +#define C_028800_BACKFACE_ENABLE 0xFFFFFF7F +#define S_028800_STENCILFUNC(x) (((x) & 0x7) << 8) +#define G_028800_STENCILFUNC(x) (((x) >> 8) & 0x7) +#define C_028800_STENCILFUNC 0xFFFFF8FF +#define S_028800_STENCILFAIL(x) (((x) & 0x7) << 11) +#define G_028800_STENCILFAIL(x) (((x) >> 11) & 0x7) +#define C_028800_STENCILFAIL 0xFFFFC7FF +#define S_028800_STENCILZPASS(x) (((x) & 0x7) << 14) +#define G_028800_STENCILZPASS(x) (((x) >> 14) & 0x7) +#define C_028800_STENCILZPASS 0xFFFE3FFF +#define S_028800_STENCILZFAIL(x) (((x) & 0x7) << 17) +#define G_028800_STENCILZFAIL(x) (((x) >> 17) & 0x7) +#define C_028800_STENCILZFAIL 0xFFF1FFFF +#define S_028800_STENCILFUNC_BF(x) (((x) & 0x7) << 20) +#define G_028800_STENCILFUNC_BF(x) (((x) >> 20) & 0x7) +#define C_028800_STENCILFUNC_BF 0xFF8FFFFF +#define S_028800_STENCILFAIL_BF(x) (((x) & 0x7) << 23) +#define G_028800_STENCILFAIL_BF(x) (((x) >> 23) & 0x7) +#define C_028800_STENCILFAIL_BF 0xFC7FFFFF +#define S_028800_STENCILZPASS_BF(x) (((x) & 0x7) << 26) +#define G_028800_STENCILZPASS_BF(x) (((x) >> 26) & 0x7) +#define C_028800_STENCILZPASS_BF 0xE3FFFFFF +#define S_028800_STENCILZFAIL_BF(x) (((x) & 0x7) << 29) +#define G_028800_STENCILZFAIL_BF(x) (((x) >> 29) & 0x7) +#define C_028800_STENCILZFAIL_BF 0x1FFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/radeon.h b/sys/dev/drm2/radeon/radeon.h new file mode 100644 index 00000000000..88a5c5a37f6 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon.h @@ -0,0 +1,2050 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_H__ +#define __RADEON_H__ + +/* TODO: Here are things that needs to be done : + * - surface allocator & initializer : (bit like scratch reg) should + * initialize HDP_ stuff on RS600, R600, R700 hw, well anythings + * related to surface + * - WB : write back stuff (do it bit like scratch reg things) + * - Vblank : look at Jesse's rework and what we should do + * - r600/r700: gart & cp + * - cs : clean cs ioctl use bitmap & things like that. + * - power management stuff + * - Barrier in gart code + * - Unmappabled vram ? + * - TESTING, TESTING, TESTING + */ + +/* Initialization path: + * We expect that acceleration initialization might fail for various + * reasons even thought we work hard to make it works on most + * configurations. In order to still have a working userspace in such + * situation the init path must succeed up to the memory controller + * initialization point. Failure before this point are considered as + * fatal error. Here is the init callchain : + * radeon_device_init perform common structure, mutex initialization + * asic_init setup the GPU memory layout and perform all + * one time initialization (failure in this + * function are considered fatal) + * asic_startup setup the GPU acceleration, in order to + * follow guideline the first thing this + * function should do is setting the GPU + * memory controller (only MC setup failure + * are considered as fatal) + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "radeon_family.h" +#include "radeon_mode.h" +#include "radeon_reg.h" + +/* + * Modules parameters. + */ +extern int radeon_no_wb; +extern int radeon_modeset; +extern int radeon_dynclks; +extern int radeon_r4xx_atom; +extern int radeon_agpmode; +extern int radeon_vram_limit; +extern int radeon_gart_size; +extern int radeon_benchmarking; +extern int radeon_testing; +extern int radeon_connector_table; +extern int radeon_tv; +extern int radeon_audio; +extern int radeon_disp_priority; +extern int radeon_hw_i2c; +extern int radeon_pcie_gen2; +extern int radeon_msi; +extern int radeon_lockup_timeout; + +/* + * Copy from radeon_drv.h so we don't have to include both and have conflicting + * symbol; + */ +#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ +#define RADEON_FENCE_JIFFIES_TIMEOUT (DRM_HZ / 2) +/* RADEON_IB_POOL_SIZE must be a power of 2 */ +#define RADEON_IB_POOL_SIZE 16 +#define RADEON_DEBUGFS_MAX_COMPONENTS 32 +#define RADEONFB_CONN_LIMIT 4 +#define RADEON_BIOS_NUM_SCRATCH 8 + +/* max number of rings */ +#define RADEON_NUM_RINGS 5 + +/* fence seq are set to this number when signaled */ +#define RADEON_FENCE_SIGNALED_SEQ 0LL + +/* internal ring indices */ +/* r1xx+ has gfx CP ring */ +#define RADEON_RING_TYPE_GFX_INDEX 0 + +/* cayman has 2 compute CP rings */ +#define CAYMAN_RING_TYPE_CP1_INDEX 1 +#define CAYMAN_RING_TYPE_CP2_INDEX 2 + +/* R600+ has an async dma ring */ +#define R600_RING_TYPE_DMA_INDEX 3 +/* cayman add a second async dma ring */ +#define CAYMAN_RING_TYPE_DMA1_INDEX 4 + +/* hardcode those limit for now */ +#define RADEON_VA_IB_OFFSET (1 << 20) +#define RADEON_VA_RESERVED_SIZE (8 << 20) +#define RADEON_IB_VM_MAX_SIZE (64 << 10) + +/* reset flags */ +#define RADEON_RESET_GFX (1 << 0) +#define RADEON_RESET_COMPUTE (1 << 1) +#define RADEON_RESET_DMA (1 << 2) + +/* + * Errata workarounds. + */ +enum radeon_pll_errata { + CHIP_ERRATA_R300_CG = 0x00000001, + CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002, + CHIP_ERRATA_PLL_DELAY = 0x00000004 +}; + + +struct radeon_device; + + +/* + * BIOS. + */ +bool radeon_get_bios(struct radeon_device *rdev); + +/* + * Dummy page + */ +struct radeon_dummy_page { + drm_dma_handle_t *dmah; + dma_addr_t addr; +}; +int radeon_dummy_page_init(struct radeon_device *rdev); +void radeon_dummy_page_fini(struct radeon_device *rdev); + + +/* + * Clocks + */ +struct radeon_clock { + struct radeon_pll p1pll; + struct radeon_pll p2pll; + struct radeon_pll dcpll; + struct radeon_pll spll; + struct radeon_pll mpll; + /* 10 Khz units */ + uint32_t default_mclk; + uint32_t default_sclk; + uint32_t default_dispclk; + uint32_t dp_extclk; + uint32_t max_pixel_clock; +}; + +/* + * Power management + */ +int radeon_pm_init(struct radeon_device *rdev); +void radeon_pm_fini(struct radeon_device *rdev); +void radeon_pm_compute_clocks(struct radeon_device *rdev); +void radeon_pm_suspend(struct radeon_device *rdev); +void radeon_pm_resume(struct radeon_device *rdev); +void radeon_combios_get_power_modes(struct radeon_device *rdev); +void radeon_atombios_get_power_modes(struct radeon_device *rdev); +void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); +void rs690_pm_info(struct radeon_device *rdev); +extern int rv6xx_get_temp(struct radeon_device *rdev); +extern int rv770_get_temp(struct radeon_device *rdev); +extern int evergreen_get_temp(struct radeon_device *rdev); +extern int sumo_get_temp(struct radeon_device *rdev); +extern int si_get_temp(struct radeon_device *rdev); +extern void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, + unsigned *bankh, unsigned *mtaspect, + unsigned *tile_split); + +/* + * Fences. + */ +struct radeon_fence_driver { + uint32_t scratch_reg; + uint64_t gpu_addr; + volatile uint32_t *cpu_addr; + /* sync_seq is protected by ring emission lock */ + uint64_t sync_seq[RADEON_NUM_RINGS]; + atomic64_t last_seq; + unsigned long last_activity; + bool initialized; +}; + +struct radeon_fence { + struct radeon_device *rdev; + unsigned int kref; + /* protected by radeon_fence.lock */ + uint64_t seq; + /* RB, DMA, etc. */ + unsigned ring; +}; + +int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); +int radeon_fence_driver_init(struct radeon_device *rdev); +void radeon_fence_driver_fini(struct radeon_device *rdev); +void radeon_fence_driver_force_completion(struct radeon_device *rdev); +int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); +void radeon_fence_process(struct radeon_device *rdev, int ring); +bool radeon_fence_signaled(struct radeon_fence *fence); +int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); +int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); +int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); +int radeon_fence_wait_any(struct radeon_device *rdev, + struct radeon_fence **fences, + bool intr); +struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); +void radeon_fence_unref(struct radeon_fence **fence); +unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); +bool radeon_fence_need_sync(struct radeon_fence *fence, int ring); +void radeon_fence_note_sync(struct radeon_fence *fence, int ring); +static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a, + struct radeon_fence *b) +{ + if (!a) { + return b; + } + + if (!b) { + return a; + } + + KASSERT(a->ring == b->ring, ("\"a\" and \"b\" belongs to different rings")); + + if (a->seq > b->seq) { + return a; + } else { + return b; + } +} + +static inline bool radeon_fence_is_earlier(struct radeon_fence *a, + struct radeon_fence *b) +{ + if (!a) { + return false; + } + + if (!b) { + return true; + } + + KASSERT(a->ring == b->ring, ("\"a\" and \"b\" belongs to different rings")); + + return a->seq < b->seq; +} + +/* + * Tiling registers + */ +struct radeon_surface_reg { + struct radeon_bo *bo; +}; + +#define RADEON_GEM_MAX_SURFACES 8 + +/* + * TTM. + */ +struct radeon_mman { + struct ttm_bo_global_ref bo_global_ref; + struct drm_global_reference mem_global_ref; + struct ttm_bo_device bdev; + bool mem_global_referenced; + bool initialized; +}; + +/* bo virtual address in a specific vm */ +struct radeon_bo_va { + /* protected by bo being reserved */ + struct list_head bo_list; + uint64_t soffset; + uint64_t eoffset; + uint32_t flags; + bool valid; + unsigned ref_count; + + /* protected by vm mutex */ + struct list_head vm_list; + + /* constant after initialization */ + struct radeon_vm *vm; + struct radeon_bo *bo; +}; + +struct radeon_bo { + /* Protected by gem.mutex */ + struct list_head list; + /* Protected by tbo.reserved */ + u32 placements[3]; + struct ttm_placement placement; + struct ttm_buffer_object tbo; + struct ttm_bo_kmap_obj kmap; + unsigned pin_count; + void *kptr; + u32 tiling_flags; + u32 pitch; + int surface_reg; + /* list of all virtual address to which this bo + * is associated to + */ + struct list_head va; + /* Constant after initialization */ + struct radeon_device *rdev; + struct drm_gem_object gem_base; + + struct ttm_bo_kmap_obj dma_buf_vmap; + int vmapping_count; +}; +#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base) + +struct radeon_bo_list { + struct ttm_validate_buffer tv; + struct radeon_bo *bo; + uint64_t gpu_offset; + unsigned rdomain; + unsigned wdomain; + u32 tiling_flags; +}; + +/* sub-allocation manager, it has to be protected by another lock. + * By conception this is an helper for other part of the driver + * like the indirect buffer or semaphore, which both have their + * locking. + * + * Principe is simple, we keep a list of sub allocation in offset + * order (first entry has offset == 0, last entry has the highest + * offset). + * + * When allocating new object we first check if there is room at + * the end total_size - (last_object_offset + last_object_size) >= + * alloc_size. If so we allocate new object there. + * + * When there is not enough room at the end, we start waiting for + * each sub object until we reach object_offset+object_size >= + * alloc_size, this object then become the sub object we return. + * + * Alignment can't be bigger than page size. + * + * Hole are not considered for allocation to keep things simple. + * Assumption is that there won't be hole (all object on same + * alignment). + */ +struct radeon_sa_manager { + struct cv wq; + struct sx wq_lock; + struct radeon_bo *bo; + struct list_head *hole; + struct list_head flist[RADEON_NUM_RINGS]; + struct list_head olist; + unsigned size; + uint64_t gpu_addr; + void *cpu_ptr; + uint32_t domain; +}; + +struct radeon_sa_bo; + +/* sub-allocation buffer */ +struct radeon_sa_bo { + struct list_head olist; + struct list_head flist; + struct radeon_sa_manager *manager; + unsigned soffset; + unsigned eoffset; + struct radeon_fence *fence; +}; + +/* + * GEM objects. + */ +struct radeon_gem { + struct sx mutex; + struct list_head objects; +}; + +int radeon_gem_init(struct radeon_device *rdev); +void radeon_gem_fini(struct radeon_device *rdev); +int radeon_gem_object_create(struct radeon_device *rdev, int size, + int alignment, int initial_domain, + bool discardable, bool kernel, + struct drm_gem_object **obj); + +int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); +int radeon_mode_dumb_mmap(struct drm_file *filp, + struct drm_device *dev, + uint32_t handle, uint64_t *offset_p); +int radeon_mode_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); + +/* + * Semaphores. + */ +/* everything here is constant */ +struct radeon_semaphore { + struct radeon_sa_bo *sa_bo; + signed waiters; + uint64_t gpu_addr; +}; + +int radeon_semaphore_create(struct radeon_device *rdev, + struct radeon_semaphore **semaphore); +void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, + struct radeon_semaphore *semaphore); +void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, + struct radeon_semaphore *semaphore); +int radeon_semaphore_sync_rings(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + int signaler, int waiter); +void radeon_semaphore_free(struct radeon_device *rdev, + struct radeon_semaphore **semaphore, + struct radeon_fence *fence); + +/* + * GART structures, functions & helpers + */ +struct radeon_mc; + +#define RADEON_GPU_PAGE_SIZE 4096 +#define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1) +#define RADEON_GPU_PAGE_SHIFT 12 +#define RADEON_GPU_PAGE_ALIGN(a) (((a) + RADEON_GPU_PAGE_MASK) & ~RADEON_GPU_PAGE_MASK) + +struct radeon_gart { + drm_dma_handle_t *dmah; + dma_addr_t table_addr; + struct radeon_bo *robj; + void *ptr; + unsigned num_gpu_pages; + unsigned num_cpu_pages; + unsigned table_size; + vm_page_t *pages; + dma_addr_t *pages_addr; + bool ready; +}; + +int radeon_gart_table_ram_alloc(struct radeon_device *rdev); +void radeon_gart_table_ram_free(struct radeon_device *rdev); +int radeon_gart_table_vram_alloc(struct radeon_device *rdev); +void radeon_gart_table_vram_free(struct radeon_device *rdev); +int radeon_gart_table_vram_pin(struct radeon_device *rdev); +void radeon_gart_table_vram_unpin(struct radeon_device *rdev); +int radeon_gart_init(struct radeon_device *rdev); +void radeon_gart_fini(struct radeon_device *rdev); +void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, + int pages); +int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, + int pages, vm_page_t *pagelist, + dma_addr_t *dma_addr); +void radeon_gart_restore(struct radeon_device *rdev); + + +/* + * GPU MC structures, functions & helpers + */ +struct radeon_mc { + resource_size_t aper_size; + resource_size_t aper_base; + resource_size_t agp_base; + /* for some chips with <= 32MB we need to lie + * about vram size near mc fb location */ + u64 mc_vram_size; + u64 visible_vram_size; + u64 gtt_size; + u64 gtt_start; + u64 gtt_end; + u64 vram_start; + u64 vram_end; + unsigned vram_width; + u64 real_vram_size; + int vram_mtrr; + bool vram_is_ddr; + bool igp_sideport_enabled; + u64 gtt_base_align; +}; + +bool radeon_combios_sideport_present(struct radeon_device *rdev); +bool radeon_atombios_sideport_present(struct radeon_device *rdev); + +/* + * GPU scratch registers structures, functions & helpers + */ +struct radeon_scratch { + unsigned num_reg; + uint32_t reg_base; + bool free[32]; + uint32_t reg[32]; +}; + +int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg); +void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg); + + +/* + * IRQS. + */ + +struct radeon_unpin_work { + struct task work; + struct radeon_device *rdev; + int crtc_id; + struct radeon_fence *fence; + struct drm_pending_vblank_event *event; + struct radeon_bo *old_rbo; + u64 new_crtc_base; +}; + +struct r500_irq_stat_regs { + u32 disp_int; + u32 hdmi0_status; +}; + +struct r600_irq_stat_regs { + u32 disp_int; + u32 disp_int_cont; + u32 disp_int_cont2; + u32 d1grph_int; + u32 d2grph_int; + u32 hdmi0_status; + u32 hdmi1_status; +}; + +struct evergreen_irq_stat_regs { + u32 disp_int; + u32 disp_int_cont; + u32 disp_int_cont2; + u32 disp_int_cont3; + u32 disp_int_cont4; + u32 disp_int_cont5; + u32 d1grph_int; + u32 d2grph_int; + u32 d3grph_int; + u32 d4grph_int; + u32 d5grph_int; + u32 d6grph_int; + u32 afmt_status1; + u32 afmt_status2; + u32 afmt_status3; + u32 afmt_status4; + u32 afmt_status5; + u32 afmt_status6; +}; + +union radeon_irq_stat_regs { + struct r500_irq_stat_regs r500; + struct r600_irq_stat_regs r600; + struct evergreen_irq_stat_regs evergreen; +}; + +#define RADEON_MAX_HPD_PINS 6 +#define RADEON_MAX_CRTCS 6 +#define RADEON_MAX_AFMT_BLOCKS 6 + +struct radeon_irq { + bool installed; + struct mtx lock; + atomic_t ring_int[RADEON_NUM_RINGS]; + bool crtc_vblank_int[RADEON_MAX_CRTCS]; + atomic_t pflip[RADEON_MAX_CRTCS]; + wait_queue_head_t vblank_queue; + bool hpd[RADEON_MAX_HPD_PINS]; + bool afmt[RADEON_MAX_AFMT_BLOCKS]; + union radeon_irq_stat_regs stat_regs; +}; + +int radeon_irq_kms_init(struct radeon_device *rdev); +void radeon_irq_kms_fini(struct radeon_device *rdev); +void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring); +void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); +void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); +void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); +void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block); +void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block); +void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask); +void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); + +/* + * CP & rings. + */ + +struct radeon_ib { + struct radeon_sa_bo *sa_bo; + uint32_t length_dw; + uint64_t gpu_addr; + uint32_t *ptr; + int ring; + struct radeon_fence *fence; + struct radeon_vm *vm; + bool is_const_ib; + struct radeon_fence *sync_to[RADEON_NUM_RINGS]; + struct radeon_semaphore *semaphore; +}; + +struct radeon_ring { + struct radeon_bo *ring_obj; + volatile uint32_t *ring; + unsigned rptr; + unsigned rptr_offs; + unsigned rptr_reg; + unsigned rptr_save_reg; + u64 next_rptr_gpu_addr; + volatile u32 *next_rptr_cpu_addr; + unsigned wptr; + unsigned wptr_old; + unsigned wptr_reg; + unsigned ring_size; + unsigned ring_free_dw; + int count_dw; + unsigned long last_activity; + unsigned last_rptr; + uint64_t gpu_addr; + uint32_t align_mask; + uint32_t ptr_mask; + bool ready; + u32 ptr_reg_shift; + u32 ptr_reg_mask; + u32 nop; + u32 idx; + u64 last_semaphore_signal_addr; + u64 last_semaphore_wait_addr; +}; + +/* + * VM + */ + +/* maximum number of VMIDs */ +#define RADEON_NUM_VM 16 + +/* defines number of bits in page table versus page directory, + * a page is 4KB so we have 12 bits offset, 9 bits in the page + * table and the remaining 19 bits are in the page directory */ +#define RADEON_VM_BLOCK_SIZE 9 + +/* number of entries in page table */ +#define RADEON_VM_PTE_COUNT (1 << RADEON_VM_BLOCK_SIZE) + +struct radeon_vm { + struct list_head list; + struct list_head va; + unsigned id; + + /* contains the page directory */ + struct radeon_sa_bo *page_directory; + uint64_t pd_gpu_addr; + + /* array of page tables, one for each page directory entry */ + struct radeon_sa_bo **page_tables; + + struct sx mutex; + /* last fence for cs using this vm */ + struct radeon_fence *fence; + /* last flush or NULL if we still need to flush */ + struct radeon_fence *last_flush; +}; + +struct radeon_vm_manager { + struct sx lock; + struct list_head lru_vm; + struct radeon_fence *active[RADEON_NUM_VM]; + struct radeon_sa_manager sa_manager; + uint32_t max_pfn; + /* number of VMIDs */ + unsigned nvm; + /* vram base address for page table entry */ + u64 vram_base_offset; + /* is vm enabled? */ + bool enabled; +}; + +/* + * file private structure + */ +struct radeon_fpriv { + struct radeon_vm vm; +}; + +/* + * R6xx+ IH ring + */ +struct r600_ih { + struct radeon_bo *ring_obj; + volatile uint32_t *ring; + unsigned rptr; + unsigned ring_size; + uint64_t gpu_addr; + uint32_t ptr_mask; + atomic_t lock; + bool enabled; +}; + +struct r600_blit_cp_primitives { + void (*set_render_target)(struct radeon_device *rdev, int format, + int w, int h, u64 gpu_addr); + void (*cp_set_surface_sync)(struct radeon_device *rdev, + u32 sync_type, u32 size, + u64 mc_addr); + void (*set_shaders)(struct radeon_device *rdev); + void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr); + void (*set_tex_resource)(struct radeon_device *rdev, + int format, int w, int h, int pitch, + u64 gpu_addr, u32 size); + void (*set_scissors)(struct radeon_device *rdev, int x1, int y1, + int x2, int y2); + void (*draw_auto)(struct radeon_device *rdev); + void (*set_default_state)(struct radeon_device *rdev); +}; + +struct r600_blit { + struct radeon_bo *shader_obj; + struct r600_blit_cp_primitives primitives; + int max_dim; + int ring_size_common; + int ring_size_per_loop; + u64 shader_gpu_addr; + u32 vs_offset, ps_offset; + u32 state_offset; + u32 state_len; +}; + +/* + * SI RLC stuff + */ +struct si_rlc { + /* for power gating */ + struct radeon_bo *save_restore_obj; + uint64_t save_restore_gpu_addr; + /* for clear state */ + struct radeon_bo *clear_state_obj; + uint64_t clear_state_gpu_addr; +}; + +int radeon_ib_get(struct radeon_device *rdev, int ring, + struct radeon_ib *ib, struct radeon_vm *vm, + unsigned size); +void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); +int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, + struct radeon_ib *const_ib); +int radeon_ib_pool_init(struct radeon_device *rdev); +void radeon_ib_pool_fini(struct radeon_device *rdev); +int radeon_ib_ring_tests(struct radeon_device *rdev); +/* Ring access between begin & end cannot sleep */ +bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, + struct radeon_ring *ring); +void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); +int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); +int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); +void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp); +void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp); +void radeon_ring_undo(struct radeon_ring *ring); +void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp); +int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); +void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); +void radeon_ring_lockup_update(struct radeon_ring *ring); +bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); +unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, + uint32_t **data); +int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, + unsigned size, uint32_t *data); +int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, + unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, + u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); +void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp); + + +/* r600 async dma */ +void r600_dma_stop(struct radeon_device *rdev); +int r600_dma_resume(struct radeon_device *rdev); +void r600_dma_fini(struct radeon_device *rdev); + +void cayman_dma_stop(struct radeon_device *rdev); +int cayman_dma_resume(struct radeon_device *rdev); +void cayman_dma_fini(struct radeon_device *rdev); + +/* + * CS. + */ +struct radeon_cs_reloc { + struct drm_gem_object *gobj; + struct radeon_bo *robj; + struct radeon_bo_list lobj; + uint32_t handle; + uint32_t flags; +}; + +struct radeon_cs_chunk { + uint32_t chunk_id; + uint32_t length_dw; + int kpage_idx[2]; + uint32_t *kpage[2]; + uint32_t *kdata; + void __user *user_ptr; + int last_copied_page; + int last_page_index; +}; + +struct radeon_cs_parser { + device_t dev; + struct radeon_device *rdev; + struct drm_file *filp; + /* chunks */ + unsigned nchunks; + struct radeon_cs_chunk *chunks; + uint64_t *chunks_array; + /* IB */ + unsigned idx; + /* relocations */ + unsigned nrelocs; + struct radeon_cs_reloc *relocs; + struct radeon_cs_reloc **relocs_ptr; + struct list_head validated; + unsigned dma_reloc_idx; + /* indices of various chunks */ + int chunk_ib_idx; + int chunk_relocs_idx; + int chunk_flags_idx; + int chunk_const_ib_idx; + struct radeon_ib ib; + struct radeon_ib const_ib; + void *track; + unsigned family; + int parser_error; + u32 cs_flags; + u32 ring; + s32 priority; +}; + +extern int radeon_cs_finish_pages(struct radeon_cs_parser *p); +extern u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx); + +struct radeon_cs_packet { + unsigned idx; + unsigned type; + unsigned reg; + unsigned opcode; + int count; + unsigned one_reg_wr; +}; + +typedef int (*radeon_packet0_check_t)(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, unsigned reg); +typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt); + + +/* + * AGP + */ +int radeon_agp_init(struct radeon_device *rdev); +void radeon_agp_resume(struct radeon_device *rdev); +void radeon_agp_suspend(struct radeon_device *rdev); +void radeon_agp_fini(struct radeon_device *rdev); + + +/* + * Writeback + */ +struct radeon_wb { + struct radeon_bo *wb_obj; + volatile uint32_t *wb; + uint64_t gpu_addr; + bool enabled; + bool use_event; +}; + +#define RADEON_WB_SCRATCH_OFFSET 0 +#define RADEON_WB_RING0_NEXT_RPTR 256 +#define RADEON_WB_CP_RPTR_OFFSET 1024 +#define RADEON_WB_CP1_RPTR_OFFSET 1280 +#define RADEON_WB_CP2_RPTR_OFFSET 1536 +#define R600_WB_DMA_RPTR_OFFSET 1792 +#define R600_WB_IH_WPTR_OFFSET 2048 +#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304 +#define R600_WB_EVENT_OFFSET 3072 + +/** + * struct radeon_pm - power management datas + * @max_bandwidth: maximum bandwidth the gpu has (MByte/s) + * @igp_sideport_mclk: sideport memory clock Mhz (rs690,rs740,rs780,rs880) + * @igp_system_mclk: system clock Mhz (rs690,rs740,rs780,rs880) + * @igp_ht_link_clk: ht link clock Mhz (rs690,rs740,rs780,rs880) + * @igp_ht_link_width: ht link width in bits (rs690,rs740,rs780,rs880) + * @k8_bandwidth: k8 bandwidth the gpu has (MByte/s) (IGP) + * @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP) + * @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP) + * @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP) + * @sclk: GPU clock Mhz (core bandwidth depends of this clock) + * @needed_bandwidth: current bandwidth needs + * + * It keeps track of various data needed to take powermanagement decision. + * Bandwidth need is used to determine minimun clock of the GPU and memory. + * Equation between gpu/memory clock and available bandwidth is hw dependent + * (type of memory, bus size, efficiency, ...) + */ + +enum radeon_pm_method { + PM_METHOD_PROFILE, + PM_METHOD_DYNPM, +}; + +enum radeon_dynpm_state { + DYNPM_STATE_DISABLED, + DYNPM_STATE_MINIMUM, + DYNPM_STATE_PAUSED, + DYNPM_STATE_ACTIVE, + DYNPM_STATE_SUSPENDED, +}; +enum radeon_dynpm_action { + DYNPM_ACTION_NONE, + DYNPM_ACTION_MINIMUM, + DYNPM_ACTION_DOWNCLOCK, + DYNPM_ACTION_UPCLOCK, + DYNPM_ACTION_DEFAULT +}; + +enum radeon_voltage_type { + VOLTAGE_NONE = 0, + VOLTAGE_GPIO, + VOLTAGE_VDDC, + VOLTAGE_SW +}; + +enum radeon_pm_state_type { + POWER_STATE_TYPE_DEFAULT, + POWER_STATE_TYPE_POWERSAVE, + POWER_STATE_TYPE_BATTERY, + POWER_STATE_TYPE_BALANCED, + POWER_STATE_TYPE_PERFORMANCE, +}; + +enum radeon_pm_profile_type { + PM_PROFILE_DEFAULT, + PM_PROFILE_AUTO, + PM_PROFILE_LOW, + PM_PROFILE_MID, + PM_PROFILE_HIGH, +}; + +#define PM_PROFILE_DEFAULT_IDX 0 +#define PM_PROFILE_LOW_SH_IDX 1 +#define PM_PROFILE_MID_SH_IDX 2 +#define PM_PROFILE_HIGH_SH_IDX 3 +#define PM_PROFILE_LOW_MH_IDX 4 +#define PM_PROFILE_MID_MH_IDX 5 +#define PM_PROFILE_HIGH_MH_IDX 6 +#define PM_PROFILE_MAX 7 + +struct radeon_pm_profile { + int dpms_off_ps_idx; + int dpms_on_ps_idx; + int dpms_off_cm_idx; + int dpms_on_cm_idx; +}; + +enum radeon_int_thermal_type { + THERMAL_TYPE_NONE, + THERMAL_TYPE_RV6XX, + THERMAL_TYPE_RV770, + THERMAL_TYPE_EVERGREEN, + THERMAL_TYPE_SUMO, + THERMAL_TYPE_NI, + THERMAL_TYPE_SI, +}; + +struct radeon_voltage { + enum radeon_voltage_type type; + /* gpio voltage */ + struct radeon_gpio_rec gpio; + u32 delay; /* delay in usec from voltage drop to sclk change */ + bool active_high; /* voltage drop is active when bit is high */ + /* VDDC voltage */ + u8 vddc_id; /* index into vddc voltage table */ + u8 vddci_id; /* index into vddci voltage table */ + bool vddci_enabled; + /* r6xx+ sw */ + u16 voltage; + /* evergreen+ vddci */ + u16 vddci; +}; + +/* clock mode flags */ +#define RADEON_PM_MODE_NO_DISPLAY (1 << 0) + +struct radeon_pm_clock_info { + /* memory clock */ + u32 mclk; + /* engine clock */ + u32 sclk; + /* voltage info */ + struct radeon_voltage voltage; + /* standardized clock flags */ + u32 flags; +}; + +/* state flags */ +#define RADEON_PM_STATE_SINGLE_DISPLAY_ONLY (1 << 0) + +struct radeon_power_state { + enum radeon_pm_state_type type; + struct radeon_pm_clock_info *clock_info; + /* number of valid clock modes in this power state */ + int num_clock_modes; + struct radeon_pm_clock_info *default_clock_mode; + /* standardized state flags */ + u32 flags; + u32 misc; /* vbios specific flags */ + u32 misc2; /* vbios specific flags */ + int pcie_lanes; /* pcie lanes */ +}; + +/* + * Some modes are overclocked by very low value, accept them + */ +#define RADEON_MODE_OVERCLOCK_MARGIN 500 /* 5 MHz */ + +struct radeon_pm { + struct sx mutex; + /* write locked while reprogramming mclk */ + struct sx mclk_lock; + u32 active_crtcs; + int active_crtc_count; + int req_vblank; + bool vblank_sync; + fixed20_12 max_bandwidth; + fixed20_12 igp_sideport_mclk; + fixed20_12 igp_system_mclk; + fixed20_12 igp_ht_link_clk; + fixed20_12 igp_ht_link_width; + fixed20_12 k8_bandwidth; + fixed20_12 sideport_bandwidth; + fixed20_12 ht_bandwidth; + fixed20_12 core_bandwidth; + fixed20_12 sclk; + fixed20_12 mclk; + fixed20_12 needed_bandwidth; + struct radeon_power_state *power_state; + /* number of valid power states */ + int num_power_states; + int current_power_state_index; + int current_clock_mode_index; + int requested_power_state_index; + int requested_clock_mode_index; + int default_power_state_index; + u32 current_sclk; + u32 current_mclk; + u16 current_vddc; + u16 current_vddci; + u32 default_sclk; + u32 default_mclk; + u16 default_vddc; + u16 default_vddci; + struct radeon_i2c_chan *i2c_bus; + /* selected pm method */ + enum radeon_pm_method pm_method; + /* dynpm power management */ +#ifdef DUMBBELL_WIP + struct delayed_work dynpm_idle_work; +#endif /* DUMBBELL_WIP */ + enum radeon_dynpm_state dynpm_state; + enum radeon_dynpm_action dynpm_planned_action; + unsigned long dynpm_action_timeout; + bool dynpm_can_upclock; + bool dynpm_can_downclock; + /* profile-based power management */ + enum radeon_pm_profile_type profile; + int profile_index; + struct radeon_pm_profile profiles[PM_PROFILE_MAX]; + /* internal thermal controller on rv6xx+ */ + enum radeon_int_thermal_type int_thermal_type; +#ifdef DUMBBELL_WIP + struct device *int_hwmon_dev; +#endif /* DUMBBELL_WIP */ +}; + +int radeon_pm_get_type_index(struct radeon_device *rdev, + enum radeon_pm_state_type ps_type, + int instance); + +struct r600_audio { + int channels; + int rate; + int bits_per_sample; + u8 status_bits; + u8 category_code; +}; + +/* + * Benchmarking + */ +void radeon_benchmark(struct radeon_device *rdev, int test_number); + + +/* + * Testing + */ +void radeon_test_moves(struct radeon_device *rdev); +void radeon_test_ring_sync(struct radeon_device *rdev, + struct radeon_ring *cpA, + struct radeon_ring *cpB); +void radeon_test_syncing(struct radeon_device *rdev); + + +/* + * Debugfs + */ +struct radeon_debugfs { + struct drm_info_list *files; + unsigned num_files; +}; + +int radeon_debugfs_add_files(struct radeon_device *rdev, + struct drm_info_list *files, + unsigned nfiles); +int radeon_debugfs_fence_init(struct radeon_device *rdev); + + +/* + * ASIC specific functions. + */ +struct radeon_asic { + int (*init)(struct radeon_device *rdev); + void (*fini)(struct radeon_device *rdev); + int (*resume)(struct radeon_device *rdev); + int (*suspend)(struct radeon_device *rdev); + void (*vga_set_state)(struct radeon_device *rdev, bool state); + int (*asic_reset)(struct radeon_device *rdev); + /* ioctl hw specific callback. Some hw might want to perform special + * operation on specific ioctl. For instance on wait idle some hw + * might want to perform and HDP flush through MMIO as it seems that + * some R6XX/R7XX hw doesn't take HDP flush into account if programmed + * through ring. + */ + void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo); + /* check if 3D engine is idle */ + bool (*gui_idle)(struct radeon_device *rdev); + /* wait for mc_idle */ + int (*mc_wait_for_idle)(struct radeon_device *rdev); + /* gart */ + struct { + void (*tlb_flush)(struct radeon_device *rdev); + int (*set_page)(struct radeon_device *rdev, int i, uint64_t addr); + } gart; + struct { + int (*init)(struct radeon_device *rdev); + void (*fini)(struct radeon_device *rdev); + + u32 pt_ring_index; + void (*set_page)(struct radeon_device *rdev, uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags); + } vm; + /* ring specific callbacks */ + struct { + void (*ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib); + int (*ib_parse)(struct radeon_device *rdev, struct radeon_ib *ib); + void (*emit_fence)(struct radeon_device *rdev, struct radeon_fence *fence); + void (*emit_semaphore)(struct radeon_device *rdev, struct radeon_ring *cp, + struct radeon_semaphore *semaphore, bool emit_wait); + int (*cs_parse)(struct radeon_cs_parser *p); + void (*ring_start)(struct radeon_device *rdev, struct radeon_ring *cp); + int (*ring_test)(struct radeon_device *rdev, struct radeon_ring *cp); + int (*ib_test)(struct radeon_device *rdev, struct radeon_ring *cp); + bool (*is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp); + void (*vm_flush)(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); + } ring[RADEON_NUM_RINGS]; + /* irqs */ + struct { + int (*set)(struct radeon_device *rdev); + irqreturn_t (*process)(struct radeon_device *rdev); + } irq; + /* displays */ + struct { + /* display watermarks */ + void (*bandwidth_update)(struct radeon_device *rdev); + /* get frame count */ + u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc); + /* wait for vblank */ + void (*wait_for_vblank)(struct radeon_device *rdev, int crtc); + /* set backlight level */ + void (*set_backlight_level)(struct radeon_encoder *radeon_encoder, u8 level); + /* get backlight level */ + u8 (*get_backlight_level)(struct radeon_encoder *radeon_encoder); + } display; + /* copy functions for bo handling */ + struct { + int (*blit)(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); + u32 blit_ring_index; + int (*dma)(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); + u32 dma_ring_index; + /* method used for bo copy */ + int (*copy)(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); + /* ring used for bo copies */ + u32 copy_ring_index; + } copy; + /* surfaces */ + struct { + int (*set_reg)(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size); + void (*clear_reg)(struct radeon_device *rdev, int reg); + } surface; + /* hotplug detect */ + struct { + void (*init)(struct radeon_device *rdev); + void (*fini)(struct radeon_device *rdev); + bool (*sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd); + void (*set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd); + } hpd; + /* power management */ + struct { + void (*misc)(struct radeon_device *rdev); + void (*prepare)(struct radeon_device *rdev); + void (*finish)(struct radeon_device *rdev); + void (*init_profile)(struct radeon_device *rdev); + void (*get_dynpm_state)(struct radeon_device *rdev); + uint32_t (*get_engine_clock)(struct radeon_device *rdev); + void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock); + uint32_t (*get_memory_clock)(struct radeon_device *rdev); + void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); + int (*get_pcie_lanes)(struct radeon_device *rdev); + void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); + void (*set_clock_gating)(struct radeon_device *rdev, int enable); + } pm; + /* pageflipping */ + struct { + void (*pre_page_flip)(struct radeon_device *rdev, int crtc); + u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); + void (*post_page_flip)(struct radeon_device *rdev, int crtc); + } pflip; +}; + +/* + * Asic structures + */ +struct r100_asic { + const unsigned *reg_safe_bm; + unsigned reg_safe_bm_size; + u32 hdp_cntl; +}; + +struct r300_asic { + const unsigned *reg_safe_bm; + unsigned reg_safe_bm_size; + u32 resync_scratch; + u32 hdp_cntl; +}; + +struct r600_asic { + unsigned max_pipes; + unsigned max_tile_pipes; + unsigned max_simds; + unsigned max_backends; + unsigned max_gprs; + unsigned max_threads; + unsigned max_stack_entries; + unsigned max_hw_contexts; + unsigned max_gs_threads; + unsigned sx_max_export_size; + unsigned sx_max_export_pos_size; + unsigned sx_max_export_smx_size; + unsigned sq_num_cf_insts; + unsigned tiling_nbanks; + unsigned tiling_npipes; + unsigned tiling_group_size; + unsigned tile_config; + unsigned backend_map; +}; + +struct rv770_asic { + unsigned max_pipes; + unsigned max_tile_pipes; + unsigned max_simds; + unsigned max_backends; + unsigned max_gprs; + unsigned max_threads; + unsigned max_stack_entries; + unsigned max_hw_contexts; + unsigned max_gs_threads; + unsigned sx_max_export_size; + unsigned sx_max_export_pos_size; + unsigned sx_max_export_smx_size; + unsigned sq_num_cf_insts; + unsigned sx_num_of_sets; + unsigned sc_prim_fifo_size; + unsigned sc_hiz_tile_fifo_size; + unsigned sc_earlyz_tile_fifo_fize; + unsigned tiling_nbanks; + unsigned tiling_npipes; + unsigned tiling_group_size; + unsigned tile_config; + unsigned backend_map; +}; + +struct evergreen_asic { + unsigned num_ses; + unsigned max_pipes; + unsigned max_tile_pipes; + unsigned max_simds; + unsigned max_backends; + unsigned max_gprs; + unsigned max_threads; + unsigned max_stack_entries; + unsigned max_hw_contexts; + unsigned max_gs_threads; + unsigned sx_max_export_size; + unsigned sx_max_export_pos_size; + unsigned sx_max_export_smx_size; + unsigned sq_num_cf_insts; + unsigned sx_num_of_sets; + unsigned sc_prim_fifo_size; + unsigned sc_hiz_tile_fifo_size; + unsigned sc_earlyz_tile_fifo_size; + unsigned tiling_nbanks; + unsigned tiling_npipes; + unsigned tiling_group_size; + unsigned tile_config; + unsigned backend_map; +}; + +struct cayman_asic { + unsigned max_shader_engines; + unsigned max_pipes_per_simd; + unsigned max_tile_pipes; + unsigned max_simds_per_se; + unsigned max_backends_per_se; + unsigned max_texture_channel_caches; + unsigned max_gprs; + unsigned max_threads; + unsigned max_gs_threads; + unsigned max_stack_entries; + unsigned sx_num_of_sets; + unsigned sx_max_export_size; + unsigned sx_max_export_pos_size; + unsigned sx_max_export_smx_size; + unsigned max_hw_contexts; + unsigned sq_num_cf_insts; + unsigned sc_prim_fifo_size; + unsigned sc_hiz_tile_fifo_size; + unsigned sc_earlyz_tile_fifo_size; + + unsigned num_shader_engines; + unsigned num_shader_pipes_per_simd; + unsigned num_tile_pipes; + unsigned num_simds_per_se; + unsigned num_backends_per_se; + unsigned backend_disable_mask_per_asic; + unsigned backend_map; + unsigned num_texture_channel_caches; + unsigned mem_max_burst_length_bytes; + unsigned mem_row_size_in_kb; + unsigned shader_engine_tile_size; + unsigned num_gpus; + unsigned multi_gpu_tile_size; + + unsigned tile_config; +}; + +struct si_asic { + unsigned max_shader_engines; + unsigned max_tile_pipes; + unsigned max_cu_per_sh; + unsigned max_sh_per_se; + unsigned max_backends_per_se; + unsigned max_texture_channel_caches; + unsigned max_gprs; + unsigned max_gs_threads; + unsigned max_hw_contexts; + unsigned sc_prim_fifo_size_frontend; + unsigned sc_prim_fifo_size_backend; + unsigned sc_hiz_tile_fifo_size; + unsigned sc_earlyz_tile_fifo_size; + + unsigned num_tile_pipes; + unsigned num_backends_per_se; + unsigned backend_disable_mask_per_asic; + unsigned backend_map; + unsigned num_texture_channel_caches; + unsigned mem_max_burst_length_bytes; + unsigned mem_row_size_in_kb; + unsigned shader_engine_tile_size; + unsigned num_gpus; + unsigned multi_gpu_tile_size; + + unsigned tile_config; +}; + +union radeon_asic_config { + struct r300_asic r300; + struct r100_asic r100; + struct r600_asic r600; + struct rv770_asic rv770; + struct evergreen_asic evergreen; + struct cayman_asic cayman; + struct si_asic si; +}; + +/* + * asic initizalization from radeon_asic.c + */ +int radeon_asic_init(struct radeon_device *rdev); + + +/* + * IOCTL. + */ +int radeon_gem_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_va_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); + +/* VRAM scratch page for HDP bug, default vram page */ +struct r600_vram_scratch { + struct radeon_bo *robj; + volatile uint32_t *ptr; + u64 gpu_addr; +}; + +/* + * ACPI + */ +struct radeon_atif_notification_cfg { + bool enabled; + int command_code; +}; + +struct radeon_atif_notifications { + bool display_switch; + bool expansion_mode_change; + bool thermal_state; + bool forced_power_state; + bool system_power_state; + bool display_conf_change; + bool px_gfx_switch; + bool brightness_change; + bool dgpu_display_event; +}; + +struct radeon_atif_functions { + bool system_params; + bool sbios_requests; + bool select_active_disp; + bool lid_state; + bool get_tv_standard; + bool set_tv_standard; + bool get_panel_expansion_mode; + bool set_panel_expansion_mode; + bool temperature_change; + bool graphics_device_types; +}; + +struct radeon_atif { + struct radeon_atif_notifications notifications; + struct radeon_atif_functions functions; + struct radeon_atif_notification_cfg notification_cfg; + struct radeon_encoder *encoder_for_bl; +}; + +struct radeon_atcs_functions { + bool get_ext_state; + bool pcie_perf_req; + bool pcie_dev_rdy; + bool pcie_bus_width; +}; + +struct radeon_atcs { + struct radeon_atcs_functions functions; +}; + +/* + * Core structure, functions and helpers. + */ +typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t); +typedef void (*radeon_wreg_t)(struct radeon_device*, uint32_t, uint32_t); + +struct radeon_device { + device_t dev; + struct drm_device *ddev; + struct sx exclusive_lock; + /* ASIC */ + union radeon_asic_config config; + enum radeon_family family; + unsigned long flags; + int usec_timeout; + enum radeon_pll_errata pll_errata; + int num_gb_pipes; + int num_z_pipes; + int disp_priority; + /* BIOS */ + uint8_t *bios; + bool is_atom_bios; + uint16_t bios_header_start; + struct radeon_bo *stollen_vga_memory; + /* Register mmio */ + resource_size_t rmmio_base; + resource_size_t rmmio_size; + /* protects concurrent MM_INDEX/DATA based register access */ + struct mtx mmio_idx_lock; + int rmmio_rid; + struct resource *rmmio; + radeon_rreg_t mc_rreg; + radeon_wreg_t mc_wreg; + radeon_rreg_t pll_rreg; + radeon_wreg_t pll_wreg; + uint32_t pcie_reg_mask; + radeon_rreg_t pciep_rreg; + radeon_wreg_t pciep_wreg; + /* io port */ + int rio_rid; + struct resource *rio_mem; + resource_size_t rio_mem_size; + struct radeon_clock clock; + struct radeon_mc mc; + struct radeon_gart gart; + struct radeon_mode_info mode_info; + struct radeon_scratch scratch; + struct radeon_mman mman; + struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS]; + struct cv fence_queue; + struct mtx fence_queue_mtx; + struct sx ring_lock; + struct radeon_ring ring[RADEON_NUM_RINGS]; + bool ib_pool_ready; + struct radeon_sa_manager ring_tmp_bo; + struct radeon_irq irq; + struct radeon_asic *asic; + struct radeon_gem gem; + struct radeon_pm pm; + uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; + struct radeon_wb wb; + struct radeon_dummy_page dummy_page; + bool shutdown; + bool suspend; + bool need_dma32; + bool accel_working; + bool fictitious_range_registered; + struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; + const struct firmware *me_fw; /* all family ME firmware */ + const struct firmware *pfp_fw; /* r6/700 PFP firmware */ + const struct firmware *rlc_fw; /* r6/700 RLC firmware */ + const struct firmware *mc_fw; /* NI MC firmware */ + const struct firmware *ce_fw; /* SI CE firmware */ + struct r600_blit r600_blit; + struct r600_vram_scratch vram_scratch; + int msi_enabled; /* msi enabled */ + struct r600_ih ih; /* r6/700 interrupt ring */ + struct si_rlc rlc; + struct taskqueue *tq; + struct task hotplug_work; + struct task audio_work; + int num_crtc; /* number of crtcs */ + struct sx dc_hw_i2c_mutex; /* display controller hw i2c mutex */ + bool audio_enabled; + struct r600_audio audio_status; /* audio stuff */ + struct { + ACPI_HANDLE handle; + ACPI_NOTIFY_HANDLER notifier_call; + } acpi; + /* only one userspace can use Hyperz features or CMASK at a time */ + struct drm_file *hyperz_filp; + struct drm_file *cmask_filp; + /* i2c buses */ + struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; + /* debugfs */ + struct radeon_debugfs debugfs[RADEON_DEBUGFS_MAX_COMPONENTS]; + unsigned debugfs_count; + /* virtual memory */ + struct radeon_vm_manager vm_manager; + struct sx gpu_clock_mutex; + /* ACPI interface */ + struct radeon_atif atif; + struct radeon_atcs atcs; +}; + +int radeon_device_init(struct radeon_device *rdev, + struct drm_device *ddev, + uint32_t flags); +void radeon_device_fini(struct radeon_device *rdev); +int radeon_gpu_wait_for_idle(struct radeon_device *rdev); + +uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg, + bool always_indirect); +void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v, + bool always_indirect); +u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); +void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); + +/* + * Cast helper + */ +#define to_radeon_fence(p) ((struct radeon_fence *)(p)) + +/* + * Registers read & write functions. + */ +#define RREG8(reg) bus_read_1((rdev->rmmio), (reg)) +#define WREG8(reg, v) bus_write_1((rdev->rmmio), (reg), v) +#define RREG16(reg) bus_read_2((rdev->rmmio), (reg)) +#define WREG16(reg, v) bus_write_2((rdev->rmmio), (reg), v) +#define RREG32(reg) r100_mm_rreg(rdev, (reg), false) +#define RREG32_IDX(reg) r100_mm_rreg(rdev, (reg), true) +#define DREG32(reg) DRM_INFO("REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg))) +#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v), false) +#define WREG32_IDX(reg, v) r100_mm_wreg(rdev, (reg), (v), true) +#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) +#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) +#define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg)) +#define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v)) +#define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg)) +#define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v)) +#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg)) +#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v)) +#define RREG32_PCIE_P(reg) rdev->pciep_rreg(rdev, (reg)) +#define WREG32_PCIE_P(reg, v) rdev->pciep_wreg(rdev, (reg), (v)) +#define WREG32_P(reg, val, mask) \ + do { \ + uint32_t tmp_ = RREG32(reg); \ + tmp_ &= (mask); \ + tmp_ |= ((val) & ~(mask)); \ + WREG32(reg, tmp_); \ + } while (0) +#define WREG32_PLL_P(reg, val, mask) \ + do { \ + uint32_t tmp_ = RREG32_PLL(reg); \ + tmp_ &= (mask); \ + tmp_ |= ((val) & ~(mask)); \ + WREG32_PLL(reg, tmp_); \ + } while (0) +#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg), false)) +#define RREG32_IO(reg) r100_io_rreg(rdev, (reg)) +#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v)) + +/* + * Indirect registers accessor + */ +static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) +{ + uint32_t r; + + WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); + r = RREG32(RADEON_PCIE_DATA); + return r; +} + +static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); + WREG32(RADEON_PCIE_DATA, (v)); +} + +void r100_pll_errata_after_index(struct radeon_device *rdev); + + +/* + * ASICs helpers. + */ +#define ASIC_IS_RN50(rdev) ((rdev->ddev->pci_device == 0x515e) || \ + (rdev->ddev->pci_device == 0x5969)) +#define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \ + (rdev->family == CHIP_RV200) || \ + (rdev->family == CHIP_RS100) || \ + (rdev->family == CHIP_RS200) || \ + (rdev->family == CHIP_RV250) || \ + (rdev->family == CHIP_RV280) || \ + (rdev->family == CHIP_RS300)) +#define ASIC_IS_R300(rdev) ((rdev->family == CHIP_R300) || \ + (rdev->family == CHIP_RV350) || \ + (rdev->family == CHIP_R350) || \ + (rdev->family == CHIP_RV380) || \ + (rdev->family == CHIP_R420) || \ + (rdev->family == CHIP_R423) || \ + (rdev->family == CHIP_RV410) || \ + (rdev->family == CHIP_RS400) || \ + (rdev->family == CHIP_RS480)) +#define ASIC_IS_X2(rdev) ((rdev->ddev->pci_device == 0x9441) || \ + (rdev->ddev->pci_device == 0x9443) || \ + (rdev->ddev->pci_device == 0x944B) || \ + (rdev->ddev->pci_device == 0x9506) || \ + (rdev->ddev->pci_device == 0x9509) || \ + (rdev->ddev->pci_device == 0x950F) || \ + (rdev->ddev->pci_device == 0x689C) || \ + (rdev->ddev->pci_device == 0x689D)) +#define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600)) +#define ASIC_IS_DCE2(rdev) ((rdev->family == CHIP_RS600) || \ + (rdev->family == CHIP_RS690) || \ + (rdev->family == CHIP_RS740) || \ + (rdev->family >= CHIP_R600)) +#define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620)) +#define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730)) +#define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR)) +#define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM) && \ + (rdev->flags & RADEON_IS_IGP)) +#define ASIC_IS_DCE5(rdev) ((rdev->family >= CHIP_BARTS)) +#define ASIC_IS_DCE6(rdev) ((rdev->family >= CHIP_ARUBA)) +#define ASIC_IS_DCE61(rdev) ((rdev->family >= CHIP_ARUBA) && \ + (rdev->flags & RADEON_IS_IGP)) + +/* + * BIOS helpers. + */ +#define RBIOS8(i) (rdev->bios[i]) +#define RBIOS16(i) (RBIOS8(i) | (RBIOS8((i)+1) << 8)) +#define RBIOS32(i) ((RBIOS16(i)) | (RBIOS16((i)+2) << 16)) + +int radeon_combios_init(struct radeon_device *rdev); +void radeon_combios_fini(struct radeon_device *rdev); +int radeon_atombios_init(struct radeon_device *rdev); +void radeon_atombios_fini(struct radeon_device *rdev); + + +/* + * RING helpers. + */ +#if !defined(DRM_DEBUG_CODE) || DRM_DEBUG_CODE == 0 +static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v) +{ + ring->ring[ring->wptr++] = v; + ring->wptr &= ring->ptr_mask; + ring->count_dw--; + ring->ring_free_dw--; +} +#else +/* With debugging this is just too big to inline */ +void radeon_ring_write(struct radeon_ring *ring, uint32_t v); +#endif + +/* + * ASICs macro. + */ +#define radeon_init(rdev) (rdev)->asic->init((rdev)) +#define radeon_fini(rdev) (rdev)->asic->fini((rdev)) +#define radeon_resume(rdev) (rdev)->asic->resume((rdev)) +#define radeon_suspend(rdev) (rdev)->asic->suspend((rdev)) +#define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)].cs_parse((p)) +#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) +#define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev)) +#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev)) +#define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), (i), (p)) +#define radeon_asic_vm_init(rdev) (rdev)->asic->vm.init((rdev)) +#define radeon_asic_vm_fini(rdev) (rdev)->asic->vm.fini((rdev)) +#define radeon_asic_vm_set_page(rdev, pe, addr, count, incr, flags) ((rdev)->asic->vm.set_page((rdev), (pe), (addr), (count), (incr), (flags))) +#define radeon_ring_start(rdev, r, cp) (rdev)->asic->ring[(r)].ring_start((rdev), (cp)) +#define radeon_ring_test(rdev, r, cp) (rdev)->asic->ring[(r)].ring_test((rdev), (cp)) +#define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)].ib_test((rdev), (cp)) +#define radeon_ring_ib_execute(rdev, r, ib) (rdev)->asic->ring[(r)].ib_execute((rdev), (ib)) +#define radeon_ring_ib_parse(rdev, r, ib) (rdev)->asic->ring[(r)].ib_parse((rdev), (ib)) +#define radeon_ring_is_lockup(rdev, r, cp) (rdev)->asic->ring[(r)].is_lockup((rdev), (cp)) +#define radeon_ring_vm_flush(rdev, r, vm) (rdev)->asic->ring[(r)].vm_flush((rdev), (r), (vm)) +#define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev)) +#define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev)) +#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->display.get_vblank_counter((rdev), (crtc)) +#define radeon_set_backlight_level(rdev, e, l) (rdev)->asic->display.set_backlight_level((e), (l)) +#define radeon_get_backlight_level(rdev, e) (rdev)->asic->display.get_backlight_level((e)) +#define radeon_fence_ring_emit(rdev, r, fence) (rdev)->asic->ring[(r)].emit_fence((rdev), (fence)) +#define radeon_semaphore_ring_emit(rdev, r, cp, semaphore, emit_wait) (rdev)->asic->ring[(r)].emit_semaphore((rdev), (cp), (semaphore), (emit_wait)) +#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy.blit((rdev), (s), (d), (np), (f)) +#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy.dma((rdev), (s), (d), (np), (f)) +#define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy.copy((rdev), (s), (d), (np), (f)) +#define radeon_copy_blit_ring_index(rdev) (rdev)->asic->copy.blit_ring_index +#define radeon_copy_dma_ring_index(rdev) (rdev)->asic->copy.dma_ring_index +#define radeon_copy_ring_index(rdev) (rdev)->asic->copy.copy_ring_index +#define radeon_get_engine_clock(rdev) (rdev)->asic->pm.get_engine_clock((rdev)) +#define radeon_set_engine_clock(rdev, e) (rdev)->asic->pm.set_engine_clock((rdev), (e)) +#define radeon_get_memory_clock(rdev) (rdev)->asic->pm.get_memory_clock((rdev)) +#define radeon_set_memory_clock(rdev, e) (rdev)->asic->pm.set_memory_clock((rdev), (e)) +#define radeon_get_pcie_lanes(rdev) (rdev)->asic->pm.get_pcie_lanes((rdev)) +#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l)) +#define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e)) +#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s))) +#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r))) +#define radeon_bandwidth_update(rdev) (rdev)->asic->display.bandwidth_update((rdev)) +#define radeon_hpd_init(rdev) (rdev)->asic->hpd.init((rdev)) +#define radeon_hpd_fini(rdev) (rdev)->asic->hpd.fini((rdev)) +#define radeon_hpd_sense(rdev, h) (rdev)->asic->hpd.sense((rdev), (h)) +#define radeon_hpd_set_polarity(rdev, h) (rdev)->asic->hpd.set_polarity((rdev), (h)) +#define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev)) +#define radeon_pm_misc(rdev) (rdev)->asic->pm.misc((rdev)) +#define radeon_pm_prepare(rdev) (rdev)->asic->pm.prepare((rdev)) +#define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) +#define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) +#define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) +#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) +#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) +#define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) +#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) + +/* Common functions */ +/* AGP */ +extern int radeon_gpu_reset(struct radeon_device *rdev); +extern void radeon_agp_disable(struct radeon_device *rdev); +extern int radeon_modeset_init(struct radeon_device *rdev); +extern void radeon_modeset_fini(struct radeon_device *rdev); +extern bool radeon_card_posted(struct radeon_device *rdev); +extern void radeon_update_bandwidth_info(struct radeon_device *rdev); +extern void radeon_update_display_priority(struct radeon_device *rdev); +extern bool radeon_boot_test_post_card(struct radeon_device *rdev); +extern void radeon_scratch_init(struct radeon_device *rdev); +extern void radeon_wb_fini(struct radeon_device *rdev); +extern int radeon_wb_init(struct radeon_device *rdev); +extern void radeon_wb_disable(struct radeon_device *rdev); +extern void radeon_surface_init(struct radeon_device *rdev); +extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); +extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); +extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); +extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); +extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); +extern int radeon_resume_kms(struct drm_device *dev); +extern int radeon_suspend_kms(struct drm_device *dev); +extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); + +/* + * vm + */ +int radeon_vm_manager_init(struct radeon_device *rdev); +void radeon_vm_manager_fini(struct radeon_device *rdev); +void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); +void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); +int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm); +void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm); +struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, + struct radeon_vm *vm, int ring); +void radeon_vm_fence(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_fence *fence); +uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr); +int radeon_vm_bo_update_pte(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_bo *bo, + struct ttm_mem_reg *mem); +void radeon_vm_bo_invalidate(struct radeon_device *rdev, + struct radeon_bo *bo); +struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm, + struct radeon_bo *bo); +struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_bo *bo); +int radeon_vm_bo_set_addr(struct radeon_device *rdev, + struct radeon_bo_va *bo_va, + uint64_t offset, + uint32_t flags); +int radeon_vm_bo_rmv(struct radeon_device *rdev, + struct radeon_bo_va *bo_va); + +/* audio */ +void r600_audio_update_hdmi(void *arg, int pending); + +/* + * R600 vram scratch functions + */ +int r600_vram_scratch_init(struct radeon_device *rdev); +void r600_vram_scratch_fini(struct radeon_device *rdev); + +/* + * r600 cs checking helper + */ +unsigned r600_mip_minify(unsigned size, unsigned level); +bool r600_fmt_is_valid_color(u32 format); +bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family); +int r600_fmt_get_blocksize(u32 format); +int r600_fmt_get_nblocksx(u32 format, u32 w); +int r600_fmt_get_nblocksy(u32 format, u32 h); + +/* + * r600 functions used by radeon_encoder.c + */ +struct radeon_hdmi_acr { + u32 clock; + + int n_32khz; + int cts_32khz; + + int n_44_1khz; + int cts_44_1khz; + + int n_48khz; + int cts_48khz; + +}; + +extern struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock); + +extern void r600_hdmi_enable(struct drm_encoder *encoder); +extern void r600_hdmi_disable(struct drm_encoder *encoder); +extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); +extern u32 r6xx_remap_render_backend(struct radeon_device *rdev, + u32 tiling_pipe_num, + u32 max_rb_num, + u32 total_max_rb_num, + u32 enabled_rb_mask); + +/* + * evergreen functions used by radeon_encoder.c + */ + +extern void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); + +extern int ni_init_microcode(struct radeon_device *rdev); +extern int ni_mc_load_microcode(struct radeon_device *rdev); +extern void ni_fini_microcode(struct radeon_device *rdev); + +/* radeon_acpi.c */ +extern int radeon_acpi_init(struct radeon_device *rdev); +extern void radeon_acpi_fini(struct radeon_device *rdev); + +/* Prototypes added by @dumbbell. */ + +/* atombios_encoders.c */ +void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, + struct drm_connector *drm_connector); +void radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, + uint32_t supported_device, u16 caps); + +/* radeon_atombios.c */ +bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, + struct drm_display_mode *mode); + +/* radeon_combios.c */ +void radeon_combios_connected_scratch_regs(struct drm_connector *connector, + struct drm_encoder *encoder, bool connected); + +/* radeon_connectors.c */ +void radeon_atombios_connected_scratch_regs(struct drm_connector *connector, + struct drm_encoder *encoder, bool connected); +void radeon_add_legacy_connector(struct drm_device *dev, + uint32_t connector_id, + uint32_t supported_device, + int connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint16_t connector_object_id, + struct radeon_hpd *hpd); +void radeon_add_atom_connector(struct drm_device *dev, + uint32_t connector_id, + uint32_t supported_device, + int connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint32_t igp_lane_info, + uint16_t connector_object_id, + struct radeon_hpd *hpd, + struct radeon_router *router); + +/* radeon_encoders.c */ +uint32_t radeon_get_encoder_enum(struct drm_device *dev, + uint32_t supported_device, uint8_t dac); +void radeon_link_encoder_connector(struct drm_device *dev); + +/* radeon_legacy_encoders.c */ +void radeon_add_legacy_encoder(struct drm_device *dev, + uint32_t encoder_enum, uint32_t supported_device); +void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, + struct drm_connector *drm_connector); + +/* radeon_pm.c */ +void radeon_pm_acpi_event_handler(struct radeon_device *rdev); + +/* radeon_ttm.c */ +int radeon_ttm_init(struct radeon_device *rdev); +void radeon_ttm_fini(struct radeon_device *rdev); + +/* r600.c */ +int r600_ih_ring_alloc(struct radeon_device *rdev); +void r600_ih_ring_fini(struct radeon_device *rdev); + +#include "radeon_object.h" + +#endif diff --git a/sys/dev/drm2/radeon/radeon_acpi.c b/sys/dev/drm2/radeon/radeon_acpi.c new file mode 100644 index 00000000000..176e160ffb0 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_acpi.c @@ -0,0 +1,639 @@ +/* + * Copyright 2012 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_acpi.h" +#include "atom.h" + +#define ACPI_AC_CLASS "ac_adapter" + +struct atif_verify_interface { + u16 size; /* structure size in bytes (includes size field) */ + u16 version; /* version */ + u32 notification_mask; /* supported notifications mask */ + u32 function_bits; /* supported functions bit vector */ +} __packed; + +struct atif_system_params { + u16 size; /* structure size in bytes (includes size field) */ + u32 valid_mask; /* valid flags mask */ + u32 flags; /* flags */ + u8 command_code; /* notify command code */ +} __packed; + +struct atif_sbios_requests { + u16 size; /* structure size in bytes (includes size field) */ + u32 pending; /* pending sbios requests */ + u8 panel_exp_mode; /* panel expansion mode */ + u8 thermal_gfx; /* thermal state: target gfx controller */ + u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */ + u8 forced_power_gfx; /* forced power state: target gfx controller */ + u8 forced_power_state; /* forced power state: state id */ + u8 system_power_src; /* system power source */ + u8 backlight_level; /* panel backlight level (0-255) */ +} __packed; + +#define ATIF_NOTIFY_MASK 0x3 +#define ATIF_NOTIFY_NONE 0 +#define ATIF_NOTIFY_81 1 +#define ATIF_NOTIFY_N 2 + +struct atcs_verify_interface { + u16 size; /* structure size in bytes (includes size field) */ + u16 version; /* version */ + u32 function_bits; /* supported functions bit vector */ +} __packed; + +/* Call the ATIF method + */ +/** + * radeon_atif_call - call an ATIF method + * + * @handle: acpi handle + * @function: the ATIF function to execute + * @params: ATIF function params + * + * Executes the requested ATIF function (all asics). + * Returns a pointer to the acpi output buffer. + */ +static ACPI_OBJECT *radeon_atif_call(ACPI_HANDLE handle, int function, + ACPI_BUFFER *params) +{ + ACPI_STATUS status; + ACPI_OBJECT atif_arg_elements[2]; + ACPI_OBJECT_LIST atif_arg; + ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + atif_arg.Count = 2; + atif_arg.Pointer = &atif_arg_elements[0]; + + atif_arg_elements[0].Type = ACPI_TYPE_INTEGER; + atif_arg_elements[0].Integer.Value = function; + + if (params) { + atif_arg_elements[1].Type = ACPI_TYPE_BUFFER; + atif_arg_elements[1].Buffer.Length = params->Length; + atif_arg_elements[1].Buffer.Pointer = params->Pointer; + } else { + /* We need a second fake parameter */ + atif_arg_elements[1].Type = ACPI_TYPE_INTEGER; + atif_arg_elements[1].Integer.Value = 0; + } + + status = AcpiEvaluateObject(handle, "ATIF", &atif_arg, &buffer); + + /* Fail only if calling the method fails and ATIF is supported */ + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", + AcpiFormatException(status)); + AcpiOsFree(buffer.Pointer); + return NULL; + } + + return buffer.Pointer; +} + +/** + * radeon_atif_parse_notification - parse supported notifications + * + * @n: supported notifications struct + * @mask: supported notifications mask from ATIF + * + * Use the supported notifications mask from ATIF function + * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications + * are supported (all asics). + */ +static void radeon_atif_parse_notification(struct radeon_atif_notifications *n, u32 mask) +{ + n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED; + n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED; + n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; + n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; + n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; + n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED; + n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED; + n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; + n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED; +} + +/** + * radeon_atif_parse_functions - parse supported functions + * + * @f: supported functions struct + * @mask: supported functions mask from ATIF + * + * Use the supported functions mask from ATIF function + * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions + * are supported (all asics). + */ +static void radeon_atif_parse_functions(struct radeon_atif_functions *f, u32 mask) +{ + f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; + f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; + f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED; + f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED; + f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED; + f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED; + f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED; + f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED; + f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; + f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED; +} + +/** + * radeon_atif_verify_interface - verify ATIF + * + * @handle: acpi handle + * @atif: radeon atif struct + * + * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function + * to initialize ATIF and determine what features are supported + * (all asics). + * returns 0 on success, error on failure. + */ +static int radeon_atif_verify_interface(ACPI_HANDLE handle, + struct radeon_atif *atif) +{ + ACPI_OBJECT *info; + struct atif_verify_interface output; + size_t size; + int err = 0; + + info = radeon_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); + if (!info) + return -EIO; + + memset(&output, 0, sizeof(output)); + + size = *(u16 *) info->Buffer.Pointer; + if (size < 12) { + DRM_INFO("ATIF buffer is too small: %zu\n", size); + err = -EINVAL; + goto out; + } + size = min(sizeof(output), size); + + memcpy(&output, info->Buffer.Pointer, size); + + /* TODO: check version? */ + DRM_DEBUG_DRIVER("ATIF version %u\n", output.version); + + radeon_atif_parse_notification(&atif->notifications, output.notification_mask); + radeon_atif_parse_functions(&atif->functions, output.function_bits); + +out: + AcpiOsFree(info); + return err; +} + +/** + * radeon_atif_get_notification_params - determine notify configuration + * + * @handle: acpi handle + * @n: atif notification configuration struct + * + * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function + * to determine if a notifier is used and if so which one + * (all asics). This is either Notify(VGA, 0x81) or Notify(VGA, n) + * where n is specified in the result if a notifier is used. + * Returns 0 on success, error on failure. + */ +static int radeon_atif_get_notification_params(ACPI_HANDLE handle, + struct radeon_atif_notification_cfg *n) +{ + ACPI_OBJECT *info; + struct atif_system_params params; + size_t size; + int err = 0; + + info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); + if (!info) { + err = -EIO; + goto out; + } + + size = *(u16 *) info->Buffer.Pointer; + if (size < 10) { + err = -EINVAL; + goto out; + } + + memset(¶ms, 0, sizeof(params)); + size = min(sizeof(params), size); + memcpy(¶ms, info->Buffer.Pointer, size); + + DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n", + params.flags, params.valid_mask); + params.flags = params.flags & params.valid_mask; + + if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) { + n->enabled = false; + n->command_code = 0; + } else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) { + n->enabled = true; + n->command_code = 0x81; + } else { + if (size < 11) { + err = -EINVAL; + goto out; + } + n->enabled = true; + n->command_code = params.command_code; + } + +out: + DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n", + (n->enabled ? "enabled" : "disabled"), + n->command_code); + AcpiOsFree(info); + return err; +} + +/** + * radeon_atif_get_sbios_requests - get requested sbios event + * + * @handle: acpi handle + * @req: atif sbios request struct + * + * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function + * to determine what requests the sbios is making to the driver + * (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atif_get_sbios_requests(ACPI_HANDLE handle, + struct atif_sbios_requests *req) +{ + ACPI_OBJECT *info; + size_t size; + int count = 0; + + info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); + if (!info) + return -EIO; + + size = *(u16 *)info->Buffer.Pointer; + if (size < 0xd) { + count = -EINVAL; + goto out; + } + memset(req, 0, sizeof(*req)); + + size = min(sizeof(*req), size); + memcpy(req, info->Buffer.Pointer, size); + DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending); + + count = hweight32(req->pending); + +out: + AcpiOsFree(info); + return count; +} + +/** + * radeon_atif_handler - handle ATIF notify requests + * + * @rdev: radeon_device pointer + * @event: atif sbios request struct + * + * Checks the acpi event and if it matches an atif event, + * handles it. + * Returns NOTIFY code + */ +void radeon_atif_handler(struct radeon_device *rdev, + UINT32 type) +{ + struct radeon_atif *atif = &rdev->atif; + struct atif_sbios_requests req; + ACPI_HANDLE handle; + int count; + + DRM_DEBUG_DRIVER("event, type = %#x\n", + type); + + if (!atif->notification_cfg.enabled || + type != atif->notification_cfg.command_code) + /* Not our event */ + return; + + /* Check pending SBIOS requests */ + handle = rdev->acpi.handle; + count = radeon_atif_get_sbios_requests(handle, &req); + + if (count <= 0) + return; + + DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count); + + if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) { + struct radeon_encoder *enc = atif->encoder_for_bl; + + if (enc) { + DRM_DEBUG_DRIVER("Changing brightness to %d\n", + req.backlight_level); + + radeon_set_backlight_level(rdev, enc, req.backlight_level); + +#ifdef DUMBBELL_WIP + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *dig = enc->enc_priv; + backlight_force_update(dig->bl_dev, + BACKLIGHT_UPDATE_HOTKEY); + } else { + struct radeon_encoder_lvds *dig = enc->enc_priv; + backlight_force_update(dig->bl_dev, + BACKLIGHT_UPDATE_HOTKEY); + } +#endif /* DUMBBELL_WIP */ + } + } + /* TODO: check other events */ + + /* We've handled the event, stop the notifier chain. The ACPI interface + * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to + * userspace if the event was generated only to signal a SBIOS + * request. + */ +} + +/* Call the ATCS method + */ +/** + * radeon_atcs_call - call an ATCS method + * + * @handle: acpi handle + * @function: the ATCS function to execute + * @params: ATCS function params + * + * Executes the requested ATCS function (all asics). + * Returns a pointer to the acpi output buffer. + */ +static union acpi_object *radeon_atcs_call(ACPI_HANDLE handle, int function, + ACPI_BUFFER *params) +{ + ACPI_STATUS status; + ACPI_OBJECT atcs_arg_elements[2]; + ACPI_OBJECT_LIST atcs_arg; + ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + atcs_arg.Count = 2; + atcs_arg.Pointer = &atcs_arg_elements[0]; + + atcs_arg_elements[0].Type = ACPI_TYPE_INTEGER; + atcs_arg_elements[0].Integer.Value = function; + + if (params) { + atcs_arg_elements[1].Type = ACPI_TYPE_BUFFER; + atcs_arg_elements[1].Buffer.Length = params->Length; + atcs_arg_elements[1].Buffer.Pointer = params->Pointer; + } else { + /* We need a second fake parameter */ + atcs_arg_elements[1].Type = ACPI_TYPE_INTEGER; + atcs_arg_elements[1].Integer.Value = 0; + } + + status = AcpiEvaluateObject(handle, "ATCS", &atcs_arg, &buffer); + + /* Fail only if calling the method fails and ATIF is supported */ + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n", + AcpiFormatException(status)); + AcpiOsFree(buffer.Pointer); + return NULL; + } + + return buffer.Pointer; +} + +/** + * radeon_atcs_parse_functions - parse supported functions + * + * @f: supported functions struct + * @mask: supported functions mask from ATCS + * + * Use the supported functions mask from ATCS function + * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions + * are supported (all asics). + */ +static void radeon_atcs_parse_functions(struct radeon_atcs_functions *f, u32 mask) +{ + f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED; + f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED; + f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED; + f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED; +} + +/** + * radeon_atcs_verify_interface - verify ATCS + * + * @handle: acpi handle + * @atcs: radeon atcs struct + * + * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function + * to initialize ATCS and determine what features are supported + * (all asics). + * returns 0 on success, error on failure. + */ +static int radeon_atcs_verify_interface(ACPI_HANDLE handle, + struct radeon_atcs *atcs) +{ + ACPI_OBJECT *info; + struct atcs_verify_interface output; + size_t size; + int err = 0; + + info = radeon_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL); + if (!info) + return -EIO; + + memset(&output, 0, sizeof(output)); + + size = *(u16 *) info->Buffer.Pointer; + if (size < 8) { + DRM_INFO("ATCS buffer is too small: %zu\n", size); + err = -EINVAL; + goto out; + } + size = min(sizeof(output), size); + + memcpy(&output, info->Buffer.Pointer, size); + + /* TODO: check version? */ + DRM_DEBUG_DRIVER("ATCS version %u\n", output.version); + + radeon_atcs_parse_functions(&atcs->functions, output.function_bits); + +out: + AcpiOsFree(info); + return err; +} + +/** + * radeon_acpi_event - handle notify events + * + * @nb: notifier block + * @val: val + * @data: acpi event + * + * Calls relevant radeon functions in response to various + * acpi events. + * Returns NOTIFY code + */ +static void radeon_acpi_event(ACPI_HANDLE handle, UINT32 type, + void *context) +{ + struct radeon_device *rdev = (struct radeon_device *)context; + +#ifdef DUMBBELL_WIP + if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) { + if (power_supply_is_system_supplied() > 0) + DRM_DEBUG_DRIVER("pm: AC\n"); + else + DRM_DEBUG_DRIVER("pm: DC\n"); + + radeon_pm_acpi_event_handler(rdev); + } +#endif /* DUMBBELL_WIP */ + + /* Check for pending SBIOS requests */ + radeon_atif_handler(rdev, type); +} + +/* Call all ACPI methods here */ +/** + * radeon_acpi_init - init driver acpi support + * + * @rdev: radeon_device pointer + * + * Verifies the AMD ACPI interfaces and registers with the acpi + * notifier chain (all asics). + * Returns 0 on success, error on failure. + */ +int radeon_acpi_init(struct radeon_device *rdev) +{ + ACPI_HANDLE handle; + struct radeon_atif *atif = &rdev->atif; + struct radeon_atcs *atcs = &rdev->atcs; + int ret; + + /* Get the device handle */ + handle = acpi_get_handle(rdev->dev); + + /* No need to proceed if we're sure that ATIF is not supported */ + if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) + return 0; + + /* Call the ATCS method */ + ret = radeon_atcs_verify_interface(handle, atcs); + if (ret) { + DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); + } + + /* Call the ATIF method */ + ret = radeon_atif_verify_interface(handle, atif); + if (ret) { + DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); + goto out; + } + + if (atif->notifications.brightness_change) { + struct drm_encoder *tmp; + struct radeon_encoder *target = NULL; + + /* Find the encoder controlling the brightness */ + list_for_each_entry(tmp, &rdev->ddev->mode_config.encoder_list, + head) { + struct radeon_encoder *enc = to_radeon_encoder(tmp); + + if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) && + enc->enc_priv) { + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *dig = enc->enc_priv; + if (dig->bl_dev) { + target = enc; + break; + } + } else { + struct radeon_encoder_lvds *dig = enc->enc_priv; + if (dig->bl_dev) { + target = enc; + break; + } + } + } + } + + atif->encoder_for_bl = target; + if (!target) { + /* Brightness change notification is enabled, but we + * didn't find a backlight controller, this should + * never happen. + */ + DRM_ERROR("Cannot find a backlight controller\n"); + } + } + + if (atif->functions.sbios_requests && !atif->functions.system_params) { + /* XXX check this workraround, if sbios request function is + * present we have to see how it's configured in the system + * params + */ + atif->functions.system_params = true; + } + + if (atif->functions.system_params) { + ret = radeon_atif_get_notification_params(handle, + &atif->notification_cfg); + if (ret) { + DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", + ret); + /* Disable notification */ + atif->notification_cfg.enabled = false; + } + } + +out: + rdev->acpi.handle = handle; + rdev->acpi.notifier_call = radeon_acpi_event; + AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, + rdev->acpi.notifier_call, rdev); + + return ret; +} + +/** + * radeon_acpi_fini - tear down driver acpi support + * + * @rdev: radeon_device pointer + * + * Unregisters with the acpi notifier chain (all asics). + */ +void radeon_acpi_fini(struct radeon_device *rdev) +{ + AcpiRemoveNotifyHandler(rdev->acpi.handle, ACPI_DEVICE_NOTIFY, + rdev->acpi.notifier_call); +} diff --git a/sys/dev/drm2/radeon/radeon_acpi.h b/sys/dev/drm2/radeon/radeon_acpi.h new file mode 100644 index 00000000000..300be6c882f --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_acpi.h @@ -0,0 +1,446 @@ +/* + * Copyright 2012 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef RADEON_ACPI_H +#define RADEON_ACPI_H + +struct radeon_device; + +void radeon_atif_handler(struct radeon_device *rdev, UINT32 type); + +/* AMD hw uses four ACPI control methods: + * 1. ATIF + * ARG0: (ACPI_INTEGER) function code + * ARG1: (ACPI_BUFFER) parameter buffer, 256 bytes + * OUTPUT: (ACPI_BUFFER) output buffer, 256 bytes + * ATIF provides an entry point for the gfx driver to interact with the sbios. + * The AMD ACPI notification mechanism uses Notify (VGA, 0x81) or a custom + * notification. Which notification is used as indicated by the ATIF Control + * Method GET_SYSTEM_PARAMETERS. When the driver receives Notify (VGA, 0x81) or + * a custom notification it invokes ATIF Control Method GET_SYSTEM_BIOS_REQUESTS + * to identify pending System BIOS requests and associated parameters. For + * example, if one of the pending requests is DISPLAY_SWITCH_REQUEST, the driver + * will perform display device detection and invoke ATIF Control Method + * SELECT_ACTIVE_DISPLAYS. + * + * 2. ATPX + * ARG0: (ACPI_INTEGER) function code + * ARG1: (ACPI_BUFFER) parameter buffer, 256 bytes + * OUTPUT: (ACPI_BUFFER) output buffer, 256 bytes + * ATPX methods are used on PowerXpress systems to handle mux switching and + * discrete GPU power control. + * + * 3. ATRM + * ARG0: (ACPI_INTEGER) offset of vbios rom data + * ARG1: (ACPI_BUFFER) size of the buffer to fill (up to 4K). + * OUTPUT: (ACPI_BUFFER) output buffer + * ATRM provides an interfacess to access the discrete GPU vbios image on + * PowerXpress systems with multiple GPUs. + * + * 4. ATCS + * ARG0: (ACPI_INTEGER) function code + * ARG1: (ACPI_BUFFER) parameter buffer, 256 bytes + * OUTPUT: (ACPI_BUFFER) output buffer, 256 bytes + * ATCS provides an interface to AMD chipset specific functionality. + * + */ +/* ATIF */ +#define ATIF_FUNCTION_VERIFY_INTERFACE 0x0 +/* ARG0: ATIF_FUNCTION_VERIFY_INTERFACE + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * WORD - version + * DWORD - supported notifications mask + * DWORD - supported functions bit vector + */ +/* Notifications mask */ +# define ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED (1 << 0) +# define ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED (1 << 1) +# define ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED (1 << 2) +# define ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED (1 << 3) +# define ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED (1 << 4) +# define ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED (1 << 5) +# define ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED (1 << 6) +# define ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED (1 << 7) +# define ATIF_DGPU_DISPLAY_EVENT_SUPPORTED (1 << 8) +/* supported functions vector */ +# define ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED (1 << 0) +# define ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED (1 << 1) +# define ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED (1 << 2) +# define ATIF_GET_LID_STATE_SUPPORTED (1 << 3) +# define ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED (1 << 4) +# define ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED (1 << 5) +# define ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED (1 << 6) +# define ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED (1 << 7) +# define ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED (1 << 12) +# define ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED (1 << 14) +#define ATIF_FUNCTION_GET_SYSTEM_PARAMETERS 0x1 +/* ARG0: ATIF_FUNCTION_GET_SYSTEM_PARAMETERS + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * DWORD - valid flags mask + * DWORD - flags + * + * OR + * + * WORD - structure size in bytes (includes size field) + * DWORD - valid flags mask + * DWORD - flags + * BYTE - notify command code + * + * flags + * bits 1:0: + * 0 - Notify(VGA, 0x81) is not used for notification + * 1 - Notify(VGA, 0x81) is used for notification + * 2 - Notify(VGA, n) is used for notification where + * n (0xd0-0xd9) is specified in notify command code. + * bit 2: + * 1 - lid changes not reported though int10 + */ +#define ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS 0x2 +/* ARG0: ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * DWORD - pending sbios requests + * BYTE - panel expansion mode + * BYTE - thermal state: target gfx controller + * BYTE - thermal state: state id (0: exit state, non-0: state) + * BYTE - forced power state: target gfx controller + * BYTE - forced power state: state id + * BYTE - system power source + * BYTE - panel backlight level (0-255) + */ +/* pending sbios requests */ +# define ATIF_DISPLAY_SWITCH_REQUEST (1 << 0) +# define ATIF_EXPANSION_MODE_CHANGE_REQUEST (1 << 1) +# define ATIF_THERMAL_STATE_CHANGE_REQUEST (1 << 2) +# define ATIF_FORCED_POWER_STATE_CHANGE_REQUEST (1 << 3) +# define ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST (1 << 4) +# define ATIF_DISPLAY_CONF_CHANGE_REQUEST (1 << 5) +# define ATIF_PX_GFX_SWITCH_REQUEST (1 << 6) +# define ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST (1 << 7) +# define ATIF_DGPU_DISPLAY_EVENT (1 << 8) +/* panel expansion mode */ +# define ATIF_PANEL_EXPANSION_DISABLE 0 +# define ATIF_PANEL_EXPANSION_FULL 1 +# define ATIF_PANEL_EXPANSION_ASPECT 2 +/* target gfx controller */ +# define ATIF_TARGET_GFX_SINGLE 0 +# define ATIF_TARGET_GFX_PX_IGPU 1 +# define ATIF_TARGET_GFX_PX_DGPU 2 +/* system power source */ +# define ATIF_POWER_SOURCE_AC 1 +# define ATIF_POWER_SOURCE_DC 2 +# define ATIF_POWER_SOURCE_RESTRICTED_AC_1 3 +# define ATIF_POWER_SOURCE_RESTRICTED_AC_2 4 +#define ATIF_FUNCTION_SELECT_ACTIVE_DISPLAYS 0x3 +/* ARG0: ATIF_FUNCTION_SELECT_ACTIVE_DISPLAYS + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - selected displays + * WORD - connected displays + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * WORD - selected displays + */ +# define ATIF_LCD1 (1 << 0) +# define ATIF_CRT1 (1 << 1) +# define ATIF_TV (1 << 2) +# define ATIF_DFP1 (1 << 3) +# define ATIF_CRT2 (1 << 4) +# define ATIF_LCD2 (1 << 5) +# define ATIF_DFP2 (1 << 7) +# define ATIF_CV (1 << 8) +# define ATIF_DFP3 (1 << 9) +# define ATIF_DFP4 (1 << 10) +# define ATIF_DFP5 (1 << 11) +# define ATIF_DFP6 (1 << 12) +#define ATIF_FUNCTION_GET_LID_STATE 0x4 +/* ARG0: ATIF_FUNCTION_GET_LID_STATE + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * BYTE - lid state (0: open, 1: closed) + * + * GET_LID_STATE only works at boot and resume, for general lid + * status, use the kernel provided status + */ +#define ATIF_FUNCTION_GET_TV_STANDARD_FROM_CMOS 0x5 +/* ARG0: ATIF_FUNCTION_GET_TV_STANDARD_FROM_CMOS + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * BYTE - 0 + * BYTE - TV standard + */ +# define ATIF_TV_STD_NTSC 0 +# define ATIF_TV_STD_PAL 1 +# define ATIF_TV_STD_PALM 2 +# define ATIF_TV_STD_PAL60 3 +# define ATIF_TV_STD_NTSCJ 4 +# define ATIF_TV_STD_PALCN 5 +# define ATIF_TV_STD_PALN 6 +# define ATIF_TV_STD_SCART_RGB 9 +#define ATIF_FUNCTION_SET_TV_STANDARD_IN_CMOS 0x6 +/* ARG0: ATIF_FUNCTION_SET_TV_STANDARD_IN_CMOS + * ARG1: + * WORD - structure size in bytes (includes size field) + * BYTE - 0 + * BYTE - TV standard + * OUTPUT: none + */ +#define ATIF_FUNCTION_GET_PANEL_EXPANSION_MODE_FROM_CMOS 0x7 +/* ARG0: ATIF_FUNCTION_GET_PANEL_EXPANSION_MODE_FROM_CMOS + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * BYTE - panel expansion mode + */ +#define ATIF_FUNCTION_SET_PANEL_EXPANSION_MODE_IN_CMOS 0x8 +/* ARG0: ATIF_FUNCTION_SET_PANEL_EXPANSION_MODE_IN_CMOS + * ARG1: + * WORD - structure size in bytes (includes size field) + * BYTE - panel expansion mode + * OUTPUT: none + */ +#define ATIF_FUNCTION_TEMPERATURE_CHANGE_NOTIFICATION 0xD +/* ARG0: ATIF_FUNCTION_TEMPERATURE_CHANGE_NOTIFICATION + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - gfx controller id + * BYTE - current temperature (degress Celsius) + * OUTPUT: none + */ +#define ATIF_FUNCTION_GET_GRAPHICS_DEVICE_TYPES 0xF +/* ARG0: ATIF_FUNCTION_GET_GRAPHICS_DEVICE_TYPES + * ARG1: none + * OUTPUT: + * WORD - number of gfx devices + * WORD - device structure size in bytes (excludes device size field) + * DWORD - flags \ + * WORD - bus number } repeated structure + * WORD - device number / + */ +/* flags */ +# define ATIF_PX_REMOVABLE_GRAPHICS_DEVICE (1 << 0) +# define ATIF_XGP_PORT (1 << 1) +# define ATIF_VGA_ENABLED_GRAPHICS_DEVICE (1 << 2) +# define ATIF_XGP_PORT_IN_DOCK (1 << 3) + +/* ATPX */ +#define ATPX_FUNCTION_VERIFY_INTERFACE 0x0 +/* ARG0: ATPX_FUNCTION_VERIFY_INTERFACE + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * WORD - version + * DWORD - supported functions bit vector + */ +/* supported functions vector */ +# define ATPX_GET_PX_PARAMETERS_SUPPORTED (1 << 0) +# define ATPX_POWER_CONTROL_SUPPORTED (1 << 1) +# define ATPX_DISPLAY_MUX_CONTROL_SUPPORTED (1 << 2) +# define ATPX_I2C_MUX_CONTROL_SUPPORTED (1 << 3) +# define ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED (1 << 4) +# define ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED (1 << 5) +# define ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED (1 << 7) +# define ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED (1 << 8) +#define ATPX_FUNCTION_GET_PX_PARAMETERS 0x1 +/* ARG0: ATPX_FUNCTION_GET_PX_PARAMETERS + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * DWORD - valid flags mask + * DWORD - flags + */ +/* flags */ +# define ATPX_LVDS_I2C_AVAILABLE_TO_BOTH_GPUS (1 << 0) +# define ATPX_CRT1_I2C_AVAILABLE_TO_BOTH_GPUS (1 << 1) +# define ATPX_DVI1_I2C_AVAILABLE_TO_BOTH_GPUS (1 << 2) +# define ATPX_CRT1_RGB_SIGNAL_MUXED (1 << 3) +# define ATPX_TV_SIGNAL_MUXED (1 << 4) +# define ATPX_DFP_SIGNAL_MUXED (1 << 5) +# define ATPX_SEPARATE_MUX_FOR_I2C (1 << 6) +# define ATPX_DYNAMIC_PX_SUPPORTED (1 << 7) +# define ATPX_ACF_NOT_SUPPORTED (1 << 8) +# define ATPX_FIXED_NOT_SUPPORTED (1 << 9) +# define ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED (1 << 10) +# define ATPX_DGPU_REQ_POWER_FOR_DISPLAYS (1 << 11) +#define ATPX_FUNCTION_POWER_CONTROL 0x2 +/* ARG0: ATPX_FUNCTION_POWER_CONTROL + * ARG1: + * WORD - structure size in bytes (includes size field) + * BYTE - dGPU power state (0: power off, 1: power on) + * OUTPUT: none + */ +#define ATPX_FUNCTION_DISPLAY_MUX_CONTROL 0x3 +/* ARG0: ATPX_FUNCTION_DISPLAY_MUX_CONTROL + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - display mux control (0: iGPU, 1: dGPU) + * OUTPUT: none + */ +# define ATPX_INTEGRATED_GPU 0 +# define ATPX_DISCRETE_GPU 1 +#define ATPX_FUNCTION_I2C_MUX_CONTROL 0x4 +/* ARG0: ATPX_FUNCTION_I2C_MUX_CONTROL + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - i2c/aux/hpd mux control (0: iGPU, 1: dGPU) + * OUTPUT: none + */ +#define ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION 0x5 +/* ARG0: ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - target gpu (0: iGPU, 1: dGPU) + * OUTPUT: none + */ +#define ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION 0x6 +/* ARG0: ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - target gpu (0: iGPU, 1: dGPU) + * OUTPUT: none + */ +#define ATPX_FUNCTION_GET_DISPLAY_CONNECTORS_MAPPING 0x8 +/* ARG0: ATPX_FUNCTION_GET_DISPLAY_CONNECTORS_MAPPING + * ARG1: none + * OUTPUT: + * WORD - number of display connectors + * WORD - connector structure size in bytes (excludes connector size field) + * BYTE - flags \ + * BYTE - ATIF display vector bit position } repeated + * BYTE - adapter id (0: iGPU, 1-n: dGPU ordered by pcie bus number) } structure + * WORD - connector ACPI id / + */ +/* flags */ +# define ATPX_DISPLAY_OUTPUT_SUPPORTED_BY_ADAPTER_ID_DEVICE (1 << 0) +# define ATPX_DISPLAY_HPD_SUPPORTED_BY_ADAPTER_ID_DEVICE (1 << 1) +# define ATPX_DISPLAY_I2C_SUPPORTED_BY_ADAPTER_ID_DEVICE (1 << 2) +#define ATPX_FUNCTION_GET_DISPLAY_DETECTION_PORTS 0x9 +/* ARG0: ATPX_FUNCTION_GET_DISPLAY_DETECTION_PORTS + * ARG1: none + * OUTPUT: + * WORD - number of HPD/DDC ports + * WORD - port structure size in bytes (excludes port size field) + * BYTE - ATIF display vector bit position \ + * BYTE - hpd id } reapeated structure + * BYTE - ddc id / + * + * available on A+A systems only + */ +/* hpd id */ +# define ATPX_HPD_NONE 0 +# define ATPX_HPD1 1 +# define ATPX_HPD2 2 +# define ATPX_HPD3 3 +# define ATPX_HPD4 4 +# define ATPX_HPD5 5 +# define ATPX_HPD6 6 +/* ddc id */ +# define ATPX_DDC_NONE 0 +# define ATPX_DDC1 1 +# define ATPX_DDC2 2 +# define ATPX_DDC3 3 +# define ATPX_DDC4 4 +# define ATPX_DDC5 5 +# define ATPX_DDC6 6 +# define ATPX_DDC7 7 +# define ATPX_DDC8 8 + +/* ATCS */ +#define ATCS_FUNCTION_VERIFY_INTERFACE 0x0 +/* ARG0: ATCS_FUNCTION_VERIFY_INTERFACE + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * WORD - version + * DWORD - supported functions bit vector + */ +/* supported functions vector */ +# define ATCS_GET_EXTERNAL_STATE_SUPPORTED (1 << 0) +# define ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED (1 << 1) +# define ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED (1 << 2) +# define ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED (1 << 3) +#define ATCS_FUNCTION_GET_EXTERNAL_STATE 0x1 +/* ARG0: ATCS_FUNCTION_GET_EXTERNAL_STATE + * ARG1: none + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * DWORD - valid flags mask + * DWORD - flags (0: undocked, 1: docked) + */ +/* flags */ +# define ATCS_DOCKED (1 << 0) +#define ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST 0x2 +/* ARG0: ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) + * WORD - valid flags mask + * WORD - flags + * BYTE - request type + * BYTE - performance request + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * BYTE - return value + */ +/* flags */ +# define ATCS_ADVERTISE_CAPS (1 << 0) +# define ATCS_WAIT_FOR_COMPLETION (1 << 1) +/* request type */ +# define ATCS_PCIE_LINK_SPEED 1 +/* performance request */ +# define ATCS_REMOVE 0 +# define ATCS_FORCE_LOW_POWER 1 +# define ATCS_PERF_LEVEL_1 2 /* PCIE Gen 1 */ +# define ATCS_PERF_LEVEL_2 3 /* PCIE Gen 2 */ +# define ATCS_PERF_LEVEL_3 4 /* PCIE Gen 3 */ +/* return value */ +# define ATCS_REQUEST_REFUSED 1 +# define ATCS_REQUEST_COMPLETE 2 +# define ATCS_REQUEST_IN_PROGRESS 3 +#define ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION 0x3 +/* ARG0: ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION + * ARG1: none + * OUTPUT: none + */ +#define ATCS_FUNCTION_SET_PCIE_BUS_WIDTH 0x4 +/* ARG0: ATCS_FUNCTION_SET_PCIE_BUS_WIDTH + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) + * BYTE - number of active lanes + * OUTPUT: + * WORD - structure size in bytes (includes size field) + * BYTE - number of active lanes + */ + +#endif diff --git a/sys/dev/drm2/radeon/radeon_agp.c b/sys/dev/drm2/radeon/radeon_agp.c new file mode 100644 index 00000000000..dec4045065c --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_agp.c @@ -0,0 +1,289 @@ +/* + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Dave Airlie + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include + +#if __OS_HAS_AGP + +struct radeon_agpmode_quirk { + u32 hostbridge_vendor; + u32 hostbridge_device; + u32 chip_vendor; + u32 chip_device; + u32 subsys_vendor; + u32 subsys_device; + u32 default_mode; +}; + +static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { + /* Intel E7505 Memory Controller Hub / RV350 AR [Radeon 9600XT] Needs AGPMode 4 (deb #515326) */ + { PCI_VENDOR_ID_INTEL, 0x2550, PCI_VENDOR_ID_ATI, 0x4152, 0x1458, 0x4038, 4}, + /* Intel 82865G/PE/P DRAM Controller/Host-Hub / Mobility 9800 Needs AGPMode 4 (deb #462590) */ + { PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x4a4e, PCI_VENDOR_ID_DELL, 0x5106, 4}, + /* Intel 82865G/PE/P DRAM Controller/Host-Hub / RV280 [Radeon 9200 SE] Needs AGPMode 4 (lp #300304) */ + { PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x5964, + 0x148c, 0x2073, 4}, + /* Intel 82855PM Processor to I/O Controller / Mobility M6 LY Needs AGPMode 1 (deb #467235) */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c59, + PCI_VENDOR_ID_IBM, 0x052f, 1}, + /* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50, + PCI_VENDOR_ID_IBM, 0x0550, 1}, + /* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57, + PCI_VENDOR_ID_IBM, 0x0530, 1}, + /* Intel 82855PM host bridge / FireGL Mobility T2 RV350 Needs AGPMode 2 (fdo #20647) */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e54, + PCI_VENDOR_ID_IBM, 0x054f, 2}, + /* Intel 82855PM host bridge / Mobility M9+ / VaioPCG-V505DX Needs AGPMode 2 (fdo #17928) */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61, + PCI_VENDOR_ID_SONY, 0x816b, 2}, + /* Intel 82855PM Processor to I/O Controller / Mobility M9+ Needs AGPMode 8 (phoronix forum) */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61, + PCI_VENDOR_ID_SONY, 0x8195, 8}, + /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ + { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, + PCI_VENDOR_ID_DELL, 0x00e3, 2}, + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ + { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, + /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ + { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, + 0x1025, 0x0061, 1}, + /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #203007) */ + { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, + 0x1025, 0x0064, 1}, + /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #141551) */ + { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, + PCI_VENDOR_ID_ASUSTEK, 0x1942, 1}, + /* Intel 82852/82855 host bridge / Mobility 9600/9700 Needs AGPMode 1 (deb #510208) */ + { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, + 0x10cf, 0x127f, 1}, + /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */ + { 0x1849, 0x3189, PCI_VENDOR_ID_ATI, 0x5960, + 0x1787, 0x5960, 4}, + /* VIA K8M800 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (fdo #12544) */ + { PCI_VENDOR_ID_VIA, 0x0204, PCI_VENDOR_ID_ATI, 0x5960, + 0x17af, 0x2020, 4}, + /* VIA KT880 Host Bridge / RV350 [Radeon 9550] Needs AGPMode 4 (fdo #19981) */ + { PCI_VENDOR_ID_VIA, 0x0269, PCI_VENDOR_ID_ATI, 0x4153, + PCI_VENDOR_ID_ASUSTEK, 0x003c, 4}, + /* VIA VT8363 Host Bridge / R200 QL [Radeon 8500] Needs AGPMode 2 (lp #141551) */ + { PCI_VENDOR_ID_VIA, 0x0305, PCI_VENDOR_ID_ATI, 0x514c, + PCI_VENDOR_ID_ATI, 0x013a, 2}, + /* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 (deb #515512) */ + { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960, + PCI_VENDOR_ID_ASUSTEK, 0x004c, 2}, + /* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 */ + { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960, + PCI_VENDOR_ID_ASUSTEK, 0x0054, 2}, + /* VIA VT8377 Host Bridge / R200 QM [Radeon 9100] Needs AGPMode 4 (deb #461144) */ + { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x514d, + 0x174b, 0x7149, 4}, + /* VIA VT8377 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (lp #312693) */ + { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5960, + 0x1462, 0x0380, 4}, + /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (ati ML) */ + { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5964, + 0x148c, 0x2073, 4}, + /* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */ + { PCI_VENDOR_ID_ATI, 0xcbb2, PCI_VENDOR_ID_ATI, 0x5c61, + PCI_VENDOR_ID_SONY, 0x8175, 1}, + /* HP Host Bridge / R300 [FireGL X1] Needs AGPMode 2 (fdo #7770) */ + { PCI_VENDOR_ID_HP, 0x122e, PCI_VENDOR_ID_ATI, 0x4e47, + PCI_VENDOR_ID_ATI, 0x0152, 2}, + { 0, 0, 0, 0, 0, 0, 0 }, +}; +#endif + +int radeon_agp_init(struct radeon_device *rdev) +{ +#if __OS_HAS_AGP + struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list; + struct drm_agp_mode mode; + struct drm_agp_info info; + uint32_t agp_status; + int default_mode; + bool is_v3; + int ret; + + /* Acquire AGP. */ + ret = drm_agp_acquire(rdev->ddev); + if (ret) { + DRM_ERROR("Unable to acquire AGP: %d\n", ret); + return ret; + } + + ret = drm_agp_info(rdev->ddev, &info); + if (ret) { + drm_agp_release(rdev->ddev); + DRM_ERROR("Unable to get AGP info: %d\n", ret); + return ret; + } + + if (rdev->ddev->agp->info.ai_aperture_size < 32) { + drm_agp_release(rdev->ddev); + dev_warn(rdev->dev, "AGP aperture too small (%zuM) " + "need at least 32M, disabling AGP\n", + rdev->ddev->agp->info.ai_aperture_size); + return -EINVAL; + } + + mode.mode = info.mode; + /* chips with the agp to pcie bridge don't have the AGP_STATUS register + * Just use the whatever mode the host sets up. + */ + if (rdev->family <= CHIP_RV350) + agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode; + else + agp_status = mode.mode; + is_v3 = !!(agp_status & RADEON_AGPv3_MODE); + + if (is_v3) { + default_mode = (agp_status & RADEON_AGPv3_8X_MODE) ? 8 : 4; + } else { + if (agp_status & RADEON_AGP_4X_MODE) { + default_mode = 4; + } else if (agp_status & RADEON_AGP_2X_MODE) { + default_mode = 2; + } else { + default_mode = 1; + } + } + + /* Apply AGPMode Quirks */ + while (p && p->chip_device != 0) { + if (info.id_vendor == p->hostbridge_vendor && + info.id_device == p->hostbridge_device && + rdev->ddev->pci_vendor == p->chip_vendor && + rdev->ddev->pci_device == p->chip_device && + rdev->ddev->pci_subvendor == p->subsys_vendor && + rdev->ddev->pci_subdevice == p->subsys_device) { + default_mode = p->default_mode; + } + ++p; + } + + if (radeon_agpmode > 0) { + if ((radeon_agpmode < (is_v3 ? 4 : 1)) || + (radeon_agpmode > (is_v3 ? 8 : 4)) || + (radeon_agpmode & (radeon_agpmode - 1))) { + DRM_ERROR("Illegal AGP Mode: %d (valid %s), leaving at %d\n", + radeon_agpmode, is_v3 ? "4, 8" : "1, 2, 4", + default_mode); + radeon_agpmode = default_mode; + } else { + DRM_INFO("AGP mode requested: %d\n", radeon_agpmode); + } + } else { + radeon_agpmode = default_mode; + } + + mode.mode &= ~RADEON_AGP_MODE_MASK; + if (is_v3) { + switch (radeon_agpmode) { + case 8: + mode.mode |= RADEON_AGPv3_8X_MODE; + break; + case 4: + default: + mode.mode |= RADEON_AGPv3_4X_MODE; + break; + } + } else { + switch (radeon_agpmode) { + case 4: + mode.mode |= RADEON_AGP_4X_MODE; + break; + case 2: + mode.mode |= RADEON_AGP_2X_MODE; + break; + case 1: + default: + mode.mode |= RADEON_AGP_1X_MODE; + break; + } + } + + mode.mode &= ~RADEON_AGP_FW_MODE; /* disable fw */ + ret = drm_agp_enable(rdev->ddev, mode); + if (ret) { + DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); + drm_agp_release(rdev->ddev); + return ret; + } + + rdev->mc.agp_base = rdev->ddev->agp->info.ai_aperture_base; + rdev->mc.gtt_size = rdev->ddev->agp->info.ai_aperture_size << 20; + rdev->mc.gtt_start = rdev->mc.agp_base; + rdev->mc.gtt_end = rdev->mc.gtt_start + rdev->mc.gtt_size - 1; + dev_info(rdev->dev, "GTT: %juM 0x%08jX - 0x%08jX\n", + (uintmax_t)rdev->mc.gtt_size >> 20, (uintmax_t)rdev->mc.gtt_start, (uintmax_t)rdev->mc.gtt_end); + + /* workaround some hw issues */ + if (rdev->family < CHIP_R200) { + WREG32(RADEON_AGP_CNTL, RREG32(RADEON_AGP_CNTL) | 0x000e0000); + } + return 0; +#else + return 0; +#endif +} + +void radeon_agp_resume(struct radeon_device *rdev) +{ +#if __OS_HAS_AGP + int r; + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + dev_warn(rdev->dev, "radeon AGP reinit failed\n"); + } +#endif +} + +void radeon_agp_fini(struct radeon_device *rdev) +{ +#if __OS_HAS_AGP + if (rdev->ddev->agp && rdev->ddev->agp->acquired) { + drm_agp_release(rdev->ddev); + } +#endif +} + +void radeon_agp_suspend(struct radeon_device *rdev) +{ + radeon_agp_fini(rdev); +} diff --git a/sys/dev/drm2/radeon/radeon_asic.c b/sys/dev/drm2/radeon/radeon_asic.c new file mode 100644 index 00000000000..374380538ba --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_asic.c @@ -0,0 +1,1961 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" + +/* + * Registers accessors functions. + */ +/** + * radeon_invalid_rreg - dummy reg read function + * + * @rdev: radeon device pointer + * @reg: offset of register + * + * Dummy register read function. Used for register blocks + * that certain asics don't have (all asics). + * Returns the value in the register. + */ +static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) +{ + panic("Invalid callback to read register 0x%04X\n", reg); + return 0; +} + +/** + * radeon_invalid_wreg - dummy reg write function + * + * @rdev: radeon device pointer + * @reg: offset of register + * @v: value to write to the register + * + * Dummy register read function. Used for register blocks + * that certain asics don't have (all asics). + */ +static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + panic("Invalid callback to write register 0x%04X with 0x%08X\n", + reg, v); +} + +/** + * radeon_register_accessor_init - sets up the register accessor callbacks + * + * @rdev: radeon device pointer + * + * Sets up the register accessor callbacks for various register + * apertures. Not all asics have all apertures (all asics). + */ +static void radeon_register_accessor_init(struct radeon_device *rdev) +{ + rdev->mc_rreg = &radeon_invalid_rreg; + rdev->mc_wreg = &radeon_invalid_wreg; + rdev->pll_rreg = &radeon_invalid_rreg; + rdev->pll_wreg = &radeon_invalid_wreg; + rdev->pciep_rreg = &radeon_invalid_rreg; + rdev->pciep_wreg = &radeon_invalid_wreg; + + /* Don't change order as we are overridding accessor. */ + if (rdev->family < CHIP_RV515) { + rdev->pcie_reg_mask = 0xff; + } else { + rdev->pcie_reg_mask = 0x7ff; + } + /* FIXME: not sure here */ + if (rdev->family <= CHIP_R580) { + rdev->pll_rreg = &r100_pll_rreg; + rdev->pll_wreg = &r100_pll_wreg; + } + if (rdev->family >= CHIP_R420) { + rdev->mc_rreg = &r420_mc_rreg; + rdev->mc_wreg = &r420_mc_wreg; + } + if (rdev->family >= CHIP_RV515) { + rdev->mc_rreg = &rv515_mc_rreg; + rdev->mc_wreg = &rv515_mc_wreg; + } + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) { + rdev->mc_rreg = &rs400_mc_rreg; + rdev->mc_wreg = &rs400_mc_wreg; + } + if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { + rdev->mc_rreg = &rs690_mc_rreg; + rdev->mc_wreg = &rs690_mc_wreg; + } + if (rdev->family == CHIP_RS600) { + rdev->mc_rreg = &rs600_mc_rreg; + rdev->mc_wreg = &rs600_mc_wreg; + } + if (rdev->family >= CHIP_R600) { + rdev->pciep_rreg = &r600_pciep_rreg; + rdev->pciep_wreg = &r600_pciep_wreg; + } +} + + +/* helper to disable agp */ +/** + * radeon_agp_disable - AGP disable helper function + * + * @rdev: radeon device pointer + * + * Removes AGP flags and changes the gart callbacks on AGP + * cards when using the internal gart rather than AGP (all asics). + */ +void radeon_agp_disable(struct radeon_device *rdev) +{ + rdev->flags &= ~RADEON_IS_AGP; + if (rdev->family >= CHIP_R600) { + DRM_INFO("Forcing AGP to PCIE mode\n"); + rdev->flags |= RADEON_IS_PCIE; + } else if (rdev->family >= CHIP_RV515 || + rdev->family == CHIP_RV380 || + rdev->family == CHIP_RV410 || + rdev->family == CHIP_R423) { + DRM_INFO("Forcing AGP to PCIE mode\n"); + rdev->flags |= RADEON_IS_PCIE; + rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; + rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; + } else { + DRM_INFO("Forcing AGP to PCI mode\n"); + rdev->flags |= RADEON_IS_PCI; + rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; + rdev->asic->gart.set_page = &r100_pci_gart_set_page; + } + rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; +} + +/* + * ASIC + */ +static struct radeon_asic r100_asic = { + .init = &r100_init, + .fini = &r100_fini, + .suspend = &r100_suspend, + .resume = &r100_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &r100_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &r100_mc_wait_for_idle, + .gart = { + .tlb_flush = &r100_pci_gart_tlb_flush, + .set_page = &r100_pci_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r100_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r100_cs_parse, + .ring_start = &r100_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &r100_irq_set, + .process = &r100_irq_process, + }, + .display = { + .bandwidth_update = &r100_bandwidth_update, + .get_vblank_counter = &r100_get_vblank_counter, + .wait_for_vblank = &r100_wait_for_vblank, + .set_backlight_level = &radeon_legacy_set_backlight_level, + .get_backlight_level = &radeon_legacy_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = NULL, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &r100_hpd_init, + .fini = &r100_hpd_fini, + .sense = &r100_hpd_sense, + .set_polarity = &r100_hpd_set_polarity, + }, + .pm = { + .misc = &r100_pm_misc, + .prepare = &r100_pm_prepare, + .finish = &r100_pm_finish, + .init_profile = &r100_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_legacy_get_engine_clock, + .set_engine_clock = &radeon_legacy_set_engine_clock, + .get_memory_clock = &radeon_legacy_get_memory_clock, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = &radeon_legacy_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, + }, +}; + +static struct radeon_asic r200_asic = { + .init = &r100_init, + .fini = &r100_fini, + .suspend = &r100_suspend, + .resume = &r100_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &r100_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &r100_mc_wait_for_idle, + .gart = { + .tlb_flush = &r100_pci_gart_tlb_flush, + .set_page = &r100_pci_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r100_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r100_cs_parse, + .ring_start = &r100_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &r100_irq_set, + .process = &r100_irq_process, + }, + .display = { + .bandwidth_update = &r100_bandwidth_update, + .get_vblank_counter = &r100_get_vblank_counter, + .wait_for_vblank = &r100_wait_for_vblank, + .set_backlight_level = &radeon_legacy_set_backlight_level, + .get_backlight_level = &radeon_legacy_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &r100_hpd_init, + .fini = &r100_hpd_fini, + .sense = &r100_hpd_sense, + .set_polarity = &r100_hpd_set_polarity, + }, + .pm = { + .misc = &r100_pm_misc, + .prepare = &r100_pm_prepare, + .finish = &r100_pm_finish, + .init_profile = &r100_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_legacy_get_engine_clock, + .set_engine_clock = &radeon_legacy_set_engine_clock, + .get_memory_clock = &radeon_legacy_get_memory_clock, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = &radeon_legacy_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, + }, +}; + +static struct radeon_asic r300_asic = { + .init = &r300_init, + .fini = &r300_fini, + .suspend = &r300_suspend, + .resume = &r300_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &r300_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &r300_mc_wait_for_idle, + .gart = { + .tlb_flush = &r100_pci_gart_tlb_flush, + .set_page = &r100_pci_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &r300_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &r100_irq_set, + .process = &r100_irq_process, + }, + .display = { + .bandwidth_update = &r100_bandwidth_update, + .get_vblank_counter = &r100_get_vblank_counter, + .wait_for_vblank = &r100_wait_for_vblank, + .set_backlight_level = &radeon_legacy_set_backlight_level, + .get_backlight_level = &radeon_legacy_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &r100_hpd_init, + .fini = &r100_hpd_fini, + .sense = &r100_hpd_sense, + .set_polarity = &r100_hpd_set_polarity, + }, + .pm = { + .misc = &r100_pm_misc, + .prepare = &r100_pm_prepare, + .finish = &r100_pm_finish, + .init_profile = &r100_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_legacy_get_engine_clock, + .set_engine_clock = &radeon_legacy_set_engine_clock, + .get_memory_clock = &radeon_legacy_get_memory_clock, + .set_memory_clock = NULL, + .get_pcie_lanes = &rv370_get_pcie_lanes, + .set_pcie_lanes = &rv370_set_pcie_lanes, + .set_clock_gating = &radeon_legacy_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, + }, +}; + +static struct radeon_asic r300_asic_pcie = { + .init = &r300_init, + .fini = &r300_fini, + .suspend = &r300_suspend, + .resume = &r300_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &r300_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &r300_mc_wait_for_idle, + .gart = { + .tlb_flush = &rv370_pcie_gart_tlb_flush, + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &r300_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &r100_irq_set, + .process = &r100_irq_process, + }, + .display = { + .bandwidth_update = &r100_bandwidth_update, + .get_vblank_counter = &r100_get_vblank_counter, + .wait_for_vblank = &r100_wait_for_vblank, + .set_backlight_level = &radeon_legacy_set_backlight_level, + .get_backlight_level = &radeon_legacy_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &r100_hpd_init, + .fini = &r100_hpd_fini, + .sense = &r100_hpd_sense, + .set_polarity = &r100_hpd_set_polarity, + }, + .pm = { + .misc = &r100_pm_misc, + .prepare = &r100_pm_prepare, + .finish = &r100_pm_finish, + .init_profile = &r100_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_legacy_get_engine_clock, + .set_engine_clock = &radeon_legacy_set_engine_clock, + .get_memory_clock = &radeon_legacy_get_memory_clock, + .set_memory_clock = NULL, + .get_pcie_lanes = &rv370_get_pcie_lanes, + .set_pcie_lanes = &rv370_set_pcie_lanes, + .set_clock_gating = &radeon_legacy_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, + }, +}; + +static struct radeon_asic r420_asic = { + .init = &r420_init, + .fini = &r420_fini, + .suspend = &r420_suspend, + .resume = &r420_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &r300_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &r300_mc_wait_for_idle, + .gart = { + .tlb_flush = &rv370_pcie_gart_tlb_flush, + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &r300_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &r100_irq_set, + .process = &r100_irq_process, + }, + .display = { + .bandwidth_update = &r100_bandwidth_update, + .get_vblank_counter = &r100_get_vblank_counter, + .wait_for_vblank = &r100_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &r100_hpd_init, + .fini = &r100_hpd_fini, + .sense = &r100_hpd_sense, + .set_polarity = &r100_hpd_set_polarity, + }, + .pm = { + .misc = &r100_pm_misc, + .prepare = &r100_pm_prepare, + .finish = &r100_pm_finish, + .init_profile = &r420_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &rv370_get_pcie_lanes, + .set_pcie_lanes = &rv370_set_pcie_lanes, + .set_clock_gating = &radeon_atom_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, + }, +}; + +static struct radeon_asic rs400_asic = { + .init = &rs400_init, + .fini = &rs400_fini, + .suspend = &rs400_suspend, + .resume = &rs400_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &r300_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &rs400_mc_wait_for_idle, + .gart = { + .tlb_flush = &rs400_gart_tlb_flush, + .set_page = &rs400_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &r300_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &r100_irq_set, + .process = &r100_irq_process, + }, + .display = { + .bandwidth_update = &r100_bandwidth_update, + .get_vblank_counter = &r100_get_vblank_counter, + .wait_for_vblank = &r100_wait_for_vblank, + .set_backlight_level = &radeon_legacy_set_backlight_level, + .get_backlight_level = &radeon_legacy_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &r100_hpd_init, + .fini = &r100_hpd_fini, + .sense = &r100_hpd_sense, + .set_polarity = &r100_hpd_set_polarity, + }, + .pm = { + .misc = &r100_pm_misc, + .prepare = &r100_pm_prepare, + .finish = &r100_pm_finish, + .init_profile = &r100_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_legacy_get_engine_clock, + .set_engine_clock = &radeon_legacy_set_engine_clock, + .get_memory_clock = &radeon_legacy_get_memory_clock, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = &radeon_legacy_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, + }, +}; + +static struct radeon_asic rs600_asic = { + .init = &rs600_init, + .fini = &rs600_fini, + .suspend = &rs600_suspend, + .resume = &rs600_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &rs600_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &rs600_mc_wait_for_idle, + .gart = { + .tlb_flush = &rs600_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &r300_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &rs600_irq_set, + .process = &rs600_irq_process, + }, + .display = { + .bandwidth_update = &rs600_bandwidth_update, + .get_vblank_counter = &rs600_get_vblank_counter, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &rs600_hpd_init, + .fini = &rs600_hpd_fini, + .sense = &rs600_hpd_sense, + .set_polarity = &rs600_hpd_set_polarity, + }, + .pm = { + .misc = &rs600_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &r420_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = &radeon_atom_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic rs690_asic = { + .init = &rs690_init, + .fini = &rs690_fini, + .suspend = &rs690_suspend, + .resume = &rs690_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &rs600_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &rs690_mc_wait_for_idle, + .gart = { + .tlb_flush = &rs400_gart_tlb_flush, + .set_page = &rs400_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &r300_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &rs600_irq_set, + .process = &rs600_irq_process, + }, + .display = { + .get_vblank_counter = &rs600_get_vblank_counter, + .bandwidth_update = &rs690_bandwidth_update, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r200_copy_dma, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &rs600_hpd_init, + .fini = &rs600_hpd_fini, + .sense = &rs600_hpd_sense, + .set_polarity = &rs600_hpd_set_polarity, + }, + .pm = { + .misc = &rs600_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &r420_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = &radeon_atom_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic rv515_asic = { + .init = &rv515_init, + .fini = &rv515_fini, + .suspend = &rv515_suspend, + .resume = &rv515_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &rs600_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &rv515_mc_wait_for_idle, + .gart = { + .tlb_flush = &rv370_pcie_gart_tlb_flush, + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &rv515_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &rs600_irq_set, + .process = &rs600_irq_process, + }, + .display = { + .get_vblank_counter = &rs600_get_vblank_counter, + .bandwidth_update = &rv515_bandwidth_update, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &rs600_hpd_init, + .fini = &rs600_hpd_fini, + .sense = &rs600_hpd_sense, + .set_polarity = &rs600_hpd_set_polarity, + }, + .pm = { + .misc = &rs600_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &r420_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &rv370_get_pcie_lanes, + .set_pcie_lanes = &rv370_set_pcie_lanes, + .set_clock_gating = &radeon_atom_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic r520_asic = { + .init = &r520_init, + .fini = &rv515_fini, + .suspend = &rv515_suspend, + .resume = &r520_resume, + .vga_set_state = &r100_vga_set_state, + .asic_reset = &rs600_asic_reset, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, + .mc_wait_for_idle = &r520_mc_wait_for_idle, + .gart = { + .tlb_flush = &rv370_pcie_gart_tlb_flush, + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r100_ring_ib_execute, + .emit_fence = &r300_fence_ring_emit, + .emit_semaphore = &r100_semaphore_ring_emit, + .cs_parse = &r300_cs_parse, + .ring_start = &rv515_ring_start, + .ring_test = &r100_ring_test, + .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, + } + }, + .irq = { + .set = &rs600_irq_set, + .process = &rs600_irq_process, + }, + .display = { + .bandwidth_update = &rv515_bandwidth_update, + .get_vblank_counter = &rs600_get_vblank_counter, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r100_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r200_copy_dma, + .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &r100_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + }, + .surface = { + .set_reg = r100_set_surface_reg, + .clear_reg = r100_clear_surface_reg, + }, + .hpd = { + .init = &rs600_hpd_init, + .fini = &rs600_hpd_fini, + .sense = &rs600_hpd_sense, + .set_polarity = &rs600_hpd_set_polarity, + }, + .pm = { + .misc = &rs600_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &r420_pm_init_profile, + .get_dynpm_state = &r100_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &rv370_get_pcie_lanes, + .set_pcie_lanes = &rv370_set_pcie_lanes, + .set_clock_gating = &radeon_atom_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic r600_asic = { + .init = &r600_init, + .fini = &r600_fini, + .suspend = &r600_suspend, + .resume = &r600_resume, + .vga_set_state = &r600_vga_set_state, + .asic_reset = &r600_asic_reset, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &r600_mc_wait_for_idle, + .gart = { + .tlb_flush = &r600_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r600_ring_ib_execute, + .emit_fence = &r600_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &r600_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &r600_gpu_is_lockup, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &r600_dma_ring_ib_execute, + .emit_fence = &r600_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &r600_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &r600_dma_is_lockup, + } + }, + .irq = { + .set = &r600_irq_set, + .process = &r600_irq_process, + }, + .display = { + .bandwidth_update = &rv515_bandwidth_update, + .get_vblank_counter = &rs600_get_vblank_counter, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r600_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &r600_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &r600_hpd_init, + .fini = &r600_hpd_fini, + .sense = &r600_hpd_sense, + .set_polarity = &r600_hpd_set_polarity, + }, + .pm = { + .misc = &r600_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &r600_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &r600_get_pcie_lanes, + .set_pcie_lanes = &r600_set_pcie_lanes, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic rs780_asic = { + .init = &r600_init, + .fini = &r600_fini, + .suspend = &r600_suspend, + .resume = &r600_resume, + .vga_set_state = &r600_vga_set_state, + .asic_reset = &r600_asic_reset, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &r600_mc_wait_for_idle, + .gart = { + .tlb_flush = &r600_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r600_ring_ib_execute, + .emit_fence = &r600_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &r600_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &r600_gpu_is_lockup, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &r600_dma_ring_ib_execute, + .emit_fence = &r600_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &r600_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &r600_dma_is_lockup, + } + }, + .irq = { + .set = &r600_irq_set, + .process = &r600_irq_process, + }, + .display = { + .bandwidth_update = &rs690_bandwidth_update, + .get_vblank_counter = &rs600_get_vblank_counter, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &r600_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &r600_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &r600_hpd_init, + .fini = &r600_hpd_fini, + .sense = &r600_hpd_sense, + .set_polarity = &r600_hpd_set_polarity, + }, + .pm = { + .misc = &r600_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &rs780_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic rv770_asic = { + .init = &rv770_init, + .fini = &rv770_fini, + .suspend = &rv770_suspend, + .resume = &rv770_resume, + .asic_reset = &r600_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &r600_mc_wait_for_idle, + .gart = { + .tlb_flush = &r600_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &r600_ring_ib_execute, + .emit_fence = &r600_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &r600_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &r600_gpu_is_lockup, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &r600_dma_ring_ib_execute, + .emit_fence = &r600_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &r600_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &r600_dma_is_lockup, + } + }, + .irq = { + .set = &r600_irq_set, + .process = &r600_irq_process, + }, + .display = { + .bandwidth_update = &rv515_bandwidth_update, + .get_vblank_counter = &rs600_get_vblank_counter, + .wait_for_vblank = &avivo_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &rv770_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &rv770_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &r600_hpd_init, + .fini = &r600_hpd_fini, + .sense = &r600_hpd_sense, + .set_polarity = &r600_hpd_set_polarity, + }, + .pm = { + .misc = &rv770_pm_misc, + .prepare = &rs600_pm_prepare, + .finish = &rs600_pm_finish, + .init_profile = &r600_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &r600_get_pcie_lanes, + .set_pcie_lanes = &r600_set_pcie_lanes, + .set_clock_gating = &radeon_atom_set_clock_gating, + }, + .pflip = { + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rv770_page_flip, + .post_page_flip = &rs600_post_page_flip, + }, +}; + +static struct radeon_asic evergreen_asic = { + .init = &evergreen_init, + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .gart = { + .tlb_flush = &evergreen_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &evergreen_ring_ib_execute, + .emit_fence = &r600_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &evergreen_dma_ring_ib_execute, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &r600_dma_is_lockup, + } + }, + .irq = { + .set = &evergreen_irq_set, + .process = &evergreen_irq_process, + }, + .display = { + .bandwidth_update = &evergreen_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &evergreen_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &evergreen_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &r600_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &r600_get_pcie_lanes, + .set_pcie_lanes = &r600_set_pcie_lanes, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +static struct radeon_asic sumo_asic = { + .init = &evergreen_init, + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .gart = { + .tlb_flush = &evergreen_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &evergreen_ring_ib_execute, + .emit_fence = &r600_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &evergreen_dma_ring_ib_execute, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &r600_dma_is_lockup, + } + }, + .irq = { + .set = &evergreen_irq_set, + .process = &evergreen_irq_process, + }, + .display = { + .bandwidth_update = &evergreen_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &evergreen_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &evergreen_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &sumo_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +static struct radeon_asic btc_asic = { + .init = &evergreen_init, + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .gart = { + .tlb_flush = &evergreen_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &evergreen_ring_ib_execute, + .emit_fence = &r600_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &evergreen_dma_ring_ib_execute, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &r600_dma_is_lockup, + } + }, + .irq = { + .set = &evergreen_irq_set, + .process = &evergreen_irq_process, + }, + .display = { + .bandwidth_update = &evergreen_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &evergreen_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &evergreen_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &btc_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +static struct radeon_asic cayman_asic = { + .init = &cayman_init, + .fini = &cayman_fini, + .suspend = &cayman_suspend, + .resume = &cayman_resume, + .asic_reset = &cayman_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .gart = { + .tlb_flush = &cayman_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .vm = { + .init = &cayman_vm_init, + .fini = &cayman_vm_fini, + .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .set_page = &cayman_vm_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &cayman_ring_ib_execute, + .ib_parse = &evergreen_ib_parse, + .emit_fence = &cayman_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + .vm_flush = &cayman_vm_flush, + }, + [CAYMAN_RING_TYPE_CP1_INDEX] = { + .ib_execute = &cayman_ring_ib_execute, + .ib_parse = &evergreen_ib_parse, + .emit_fence = &cayman_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + .vm_flush = &cayman_vm_flush, + }, + [CAYMAN_RING_TYPE_CP2_INDEX] = { + .ib_execute = &cayman_ring_ib_execute, + .ib_parse = &evergreen_ib_parse, + .emit_fence = &cayman_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + .vm_flush = &cayman_vm_flush, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &cayman_dma_ring_ib_execute, + .ib_parse = &evergreen_dma_ib_parse, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &cayman_dma_is_lockup, + .vm_flush = &cayman_dma_vm_flush, + }, + [CAYMAN_RING_TYPE_DMA1_INDEX] = { + .ib_execute = &cayman_dma_ring_ib_execute, + .ib_parse = &evergreen_dma_ib_parse, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &cayman_dma_is_lockup, + .vm_flush = &cayman_dma_vm_flush, + } + }, + .irq = { + .set = &evergreen_irq_set, + .process = &evergreen_irq_process, + }, + .display = { + .bandwidth_update = &evergreen_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &evergreen_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &evergreen_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &btc_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +static struct radeon_asic trinity_asic = { + .init = &cayman_init, + .fini = &cayman_fini, + .suspend = &cayman_suspend, + .resume = &cayman_resume, + .asic_reset = &cayman_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .gart = { + .tlb_flush = &cayman_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .vm = { + .init = &cayman_vm_init, + .fini = &cayman_vm_fini, + .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .set_page = &cayman_vm_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &cayman_ring_ib_execute, + .ib_parse = &evergreen_ib_parse, + .emit_fence = &cayman_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + .vm_flush = &cayman_vm_flush, + }, + [CAYMAN_RING_TYPE_CP1_INDEX] = { + .ib_execute = &cayman_ring_ib_execute, + .ib_parse = &evergreen_ib_parse, + .emit_fence = &cayman_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + .vm_flush = &cayman_vm_flush, + }, + [CAYMAN_RING_TYPE_CP2_INDEX] = { + .ib_execute = &cayman_ring_ib_execute, + .ib_parse = &evergreen_ib_parse, + .emit_fence = &cayman_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = &evergreen_cs_parse, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, + .vm_flush = &cayman_vm_flush, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &cayman_dma_ring_ib_execute, + .ib_parse = &evergreen_dma_ib_parse, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &cayman_dma_is_lockup, + .vm_flush = &cayman_dma_vm_flush, + }, + [CAYMAN_RING_TYPE_DMA1_INDEX] = { + .ib_execute = &cayman_dma_ring_ib_execute, + .ib_parse = &evergreen_dma_ib_parse, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = &evergreen_dma_cs_parse, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &cayman_dma_is_lockup, + .vm_flush = &cayman_dma_vm_flush, + } + }, + .irq = { + .set = &evergreen_irq_set, + .process = &evergreen_irq_process, + }, + .display = { + .bandwidth_update = &dce6_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = &r600_copy_blit, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &evergreen_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &evergreen_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &sumo_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +static struct radeon_asic si_asic = { + .init = &si_init, + .fini = &si_fini, + .suspend = &si_suspend, + .resume = &si_resume, + .asic_reset = &si_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .gart = { + .tlb_flush = &si_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .vm = { + .init = &si_vm_init, + .fini = &si_vm_fini, + .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .set_page = &si_vm_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX] = { + .ib_execute = &si_ring_ib_execute, + .ib_parse = &si_ib_parse, + .emit_fence = &si_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = NULL, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &si_gpu_is_lockup, + .vm_flush = &si_vm_flush, + }, + [CAYMAN_RING_TYPE_CP1_INDEX] = { + .ib_execute = &si_ring_ib_execute, + .ib_parse = &si_ib_parse, + .emit_fence = &si_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = NULL, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &si_gpu_is_lockup, + .vm_flush = &si_vm_flush, + }, + [CAYMAN_RING_TYPE_CP2_INDEX] = { + .ib_execute = &si_ring_ib_execute, + .ib_parse = &si_ib_parse, + .emit_fence = &si_fence_ring_emit, + .emit_semaphore = &r600_semaphore_ring_emit, + .cs_parse = NULL, + .ring_test = &r600_ring_test, + .ib_test = &r600_ib_test, + .is_lockup = &si_gpu_is_lockup, + .vm_flush = &si_vm_flush, + }, + [R600_RING_TYPE_DMA_INDEX] = { + .ib_execute = &cayman_dma_ring_ib_execute, + .ib_parse = &evergreen_dma_ib_parse, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = NULL, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &cayman_dma_is_lockup, + .vm_flush = &si_dma_vm_flush, + }, + [CAYMAN_RING_TYPE_DMA1_INDEX] = { + .ib_execute = &cayman_dma_ring_ib_execute, + .ib_parse = &evergreen_dma_ib_parse, + .emit_fence = &evergreen_dma_fence_ring_emit, + .emit_semaphore = &r600_dma_semaphore_ring_emit, + .cs_parse = NULL, + .ring_test = &r600_dma_ring_test, + .ib_test = &r600_dma_ib_test, + .is_lockup = &cayman_dma_is_lockup, + .vm_flush = &si_dma_vm_flush, + } + }, + .irq = { + .set = &si_irq_set, + .process = &si_irq_process, + }, + .display = { + .bandwidth_update = &dce6_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + .set_backlight_level = &atombios_set_backlight_level, + .get_backlight_level = &atombios_get_backlight_level, + }, + .copy = { + .blit = NULL, + .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .dma = &si_copy_dma, + .dma_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &si_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &sumo_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +/** + * radeon_asic_init - register asic specific callbacks + * + * @rdev: radeon device pointer + * + * Registers the appropriate asic specific callbacks for each + * chip family. Also sets other asics specific info like the number + * of crtcs and the register aperture accessors (all asics). + * Returns 0 for success. + */ +int radeon_asic_init(struct radeon_device *rdev) +{ + radeon_register_accessor_init(rdev); + + /* set the number of crtcs */ + if (rdev->flags & RADEON_SINGLE_CRTC) + rdev->num_crtc = 1; + else + rdev->num_crtc = 2; + + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + rdev->asic = &r100_asic; + break; + case CHIP_R200: + case CHIP_RV250: + case CHIP_RS300: + case CHIP_RV280: + rdev->asic = &r200_asic; + break; + case CHIP_R300: + case CHIP_R350: + case CHIP_RV350: + case CHIP_RV380: + if (rdev->flags & RADEON_IS_PCIE) + rdev->asic = &r300_asic_pcie; + else + rdev->asic = &r300_asic; + break; + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + rdev->asic = &r420_asic; + /* handle macs */ + if (rdev->bios == NULL) { + rdev->asic->pm.get_engine_clock = &radeon_legacy_get_engine_clock; + rdev->asic->pm.set_engine_clock = &radeon_legacy_set_engine_clock; + rdev->asic->pm.get_memory_clock = &radeon_legacy_get_memory_clock; + rdev->asic->pm.set_memory_clock = NULL; + rdev->asic->display.set_backlight_level = &radeon_legacy_set_backlight_level; + } + break; + case CHIP_RS400: + case CHIP_RS480: + rdev->asic = &rs400_asic; + break; + case CHIP_RS600: + rdev->asic = &rs600_asic; + break; + case CHIP_RS690: + case CHIP_RS740: + rdev->asic = &rs690_asic; + break; + case CHIP_RV515: + rdev->asic = &rv515_asic; + break; + case CHIP_R520: + case CHIP_RV530: + case CHIP_RV560: + case CHIP_RV570: + case CHIP_R580: + rdev->asic = &r520_asic; + break; + case CHIP_R600: + case CHIP_RV610: + case CHIP_RV630: + case CHIP_RV620: + case CHIP_RV635: + case CHIP_RV670: + rdev->asic = &r600_asic; + break; + case CHIP_RS780: + case CHIP_RS880: + rdev->asic = &rs780_asic; + break; + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + case CHIP_RV740: + rdev->asic = &rv770_asic; + break; + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + /* set num crtcs */ + if (rdev->family == CHIP_CEDAR) + rdev->num_crtc = 4; + else + rdev->num_crtc = 6; + rdev->asic = &evergreen_asic; + break; + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: + rdev->asic = &sumo_asic; + break; + case CHIP_BARTS: + case CHIP_TURKS: + case CHIP_CAICOS: + /* set num crtcs */ + if (rdev->family == CHIP_CAICOS) + rdev->num_crtc = 4; + else + rdev->num_crtc = 6; + rdev->asic = &btc_asic; + break; + case CHIP_CAYMAN: + rdev->asic = &cayman_asic; + /* set num crtcs */ + rdev->num_crtc = 6; + break; + case CHIP_ARUBA: + rdev->asic = &trinity_asic; + /* set num crtcs */ + rdev->num_crtc = 4; + break; + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + rdev->asic = &si_asic; + /* set num crtcs */ + rdev->num_crtc = 6; + break; + default: + /* FIXME: not supported yet */ + return -EINVAL; + } + + if (rdev->flags & RADEON_IS_IGP) { + rdev->asic->pm.get_memory_clock = NULL; + rdev->asic->pm.set_memory_clock = NULL; + } + + return 0; +} + diff --git a/sys/dev/drm2/radeon/radeon_asic.h b/sys/dev/drm2/radeon/radeon_asic.h new file mode 100644 index 00000000000..f3b85f887ff --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_asic.h @@ -0,0 +1,532 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_ASIC_H__ +#define __RADEON_ASIC_H__ + +/* + * common functions + */ +uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev); +void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); +uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev); +void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); + +uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev); +void radeon_atom_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); +uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev); +void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock); +void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); + +void atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level); +u8 atombios_get_backlight_level(struct radeon_encoder *radeon_encoder); +void radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level); +u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder); + + +/* + * r100,rv100,rs100,rv200,rs200 + */ +struct r100_mc_save { + u32 GENMO_WT; + u32 CRTC_EXT_CNTL; + u32 CRTC_GEN_CNTL; + u32 CRTC2_GEN_CNTL; + u32 CUR_OFFSET; + u32 CUR2_OFFSET; +}; +int r100_init(struct radeon_device *rdev); +void r100_fini(struct radeon_device *rdev); +int r100_suspend(struct radeon_device *rdev); +int r100_resume(struct radeon_device *rdev); +void r100_vga_set_state(struct radeon_device *rdev, bool state); +bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); +int r100_asic_reset(struct radeon_device *rdev); +u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); +void r100_pci_gart_tlb_flush(struct radeon_device *rdev); +int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); +int r100_irq_set(struct radeon_device *rdev); +irqreturn_t r100_irq_process(struct radeon_device *rdev); +void r100_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +void r100_semaphore_ring_emit(struct radeon_device *rdev, + struct radeon_ring *cp, + struct radeon_semaphore *semaphore, + bool emit_wait); +int r100_cs_parse(struct radeon_cs_parser *p); +void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg); +int r100_copy_blit(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); +int r100_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size); +void r100_clear_surface_reg(struct radeon_device *rdev, int reg); +void r100_bandwidth_update(struct radeon_device *rdev); +void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); +void r100_hpd_init(struct radeon_device *rdev); +void r100_hpd_fini(struct radeon_device *rdev); +bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void r100_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); +int r100_debugfs_rbbm_init(struct radeon_device *rdev); +int r100_debugfs_cp_init(struct radeon_device *rdev); +void r100_cp_disable(struct radeon_device *rdev); +int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); +void r100_cp_fini(struct radeon_device *rdev); +int r100_pci_gart_init(struct radeon_device *rdev); +void r100_pci_gart_fini(struct radeon_device *rdev); +int r100_pci_gart_enable(struct radeon_device *rdev); +void r100_pci_gart_disable(struct radeon_device *rdev); +int r100_debugfs_mc_info_init(struct radeon_device *rdev); +int r100_gui_wait_for_idle(struct radeon_device *rdev); +int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); +void r100_irq_disable(struct radeon_device *rdev); +void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); +void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save); +void r100_vram_init_sizes(struct radeon_device *rdev); +int r100_cp_reset(struct radeon_device *rdev); +void r100_vga_render_disable(struct radeon_device *rdev); +void r100_restore_sanity(struct radeon_device *rdev); +int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + struct radeon_bo *robj); +int r100_cs_parse_packet0(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + const unsigned *auth, unsigned n, + radeon_packet0_check_t check); +int r100_cs_packet_parse(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx); +void r100_enable_bm(struct radeon_device *rdev); +void r100_set_common_regs(struct radeon_device *rdev); +void r100_bm_disable(struct radeon_device *rdev); +extern bool r100_gui_idle(struct radeon_device *rdev); +extern void r100_pm_misc(struct radeon_device *rdev); +extern void r100_pm_prepare(struct radeon_device *rdev); +extern void r100_pm_finish(struct radeon_device *rdev); +extern void r100_pm_init_profile(struct radeon_device *rdev); +extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); +extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); +extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); +extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); +extern int r100_mc_wait_for_idle(struct radeon_device *rdev); + +/* + * r200,rv250,rs300,rv280 + */ +extern int r200_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); +void r200_set_safe_registers(struct radeon_device *rdev); + +/* + * r300,r350,rv350,rv380 + */ +extern int r300_init(struct radeon_device *rdev); +extern void r300_fini(struct radeon_device *rdev); +extern int r300_suspend(struct radeon_device *rdev); +extern int r300_resume(struct radeon_device *rdev); +extern int r300_asic_reset(struct radeon_device *rdev); +extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); +extern void r300_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +extern int r300_cs_parse(struct radeon_cs_parser *p); +extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); +extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); +extern int rv370_get_pcie_lanes(struct radeon_device *rdev); +extern void r300_set_reg_safe(struct radeon_device *rdev); +extern void r300_mc_program(struct radeon_device *rdev); +extern void r300_mc_init(struct radeon_device *rdev); +extern void r300_clock_startup(struct radeon_device *rdev); +extern int r300_mc_wait_for_idle(struct radeon_device *rdev); +extern int rv370_pcie_gart_init(struct radeon_device *rdev); +extern void rv370_pcie_gart_fini(struct radeon_device *rdev); +extern int rv370_pcie_gart_enable(struct radeon_device *rdev); +extern void rv370_pcie_gart_disable(struct radeon_device *rdev); + +/* + * r420,r423,rv410 + */ +extern int r420_init(struct radeon_device *rdev); +extern void r420_fini(struct radeon_device *rdev); +extern int r420_suspend(struct radeon_device *rdev); +extern int r420_resume(struct radeon_device *rdev); +extern void r420_pm_init_profile(struct radeon_device *rdev); +extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); +extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v); +extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev); +extern void r420_pipes_init(struct radeon_device *rdev); + +/* + * rs400,rs480 + */ +extern int rs400_init(struct radeon_device *rdev); +extern void rs400_fini(struct radeon_device *rdev); +extern int rs400_suspend(struct radeon_device *rdev); +extern int rs400_resume(struct radeon_device *rdev); +void rs400_gart_tlb_flush(struct radeon_device *rdev); +int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg); +void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +int rs400_gart_init(struct radeon_device *rdev); +int rs400_gart_enable(struct radeon_device *rdev); +void rs400_gart_adjust_size(struct radeon_device *rdev); +void rs400_gart_disable(struct radeon_device *rdev); +void rs400_gart_fini(struct radeon_device *rdev); +extern int rs400_mc_wait_for_idle(struct radeon_device *rdev); + +/* + * rs600. + */ +extern int rs600_asic_reset(struct radeon_device *rdev); +extern int rs600_init(struct radeon_device *rdev); +extern void rs600_fini(struct radeon_device *rdev); +extern int rs600_suspend(struct radeon_device *rdev); +extern int rs600_resume(struct radeon_device *rdev); +int rs600_irq_set(struct radeon_device *rdev); +irqreturn_t rs600_irq_process(struct radeon_device *rdev); +void rs600_irq_disable(struct radeon_device *rdev); +u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); +void rs600_gart_tlb_flush(struct radeon_device *rdev); +int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); +void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +void rs600_bandwidth_update(struct radeon_device *rdev); +void rs600_hpd_init(struct radeon_device *rdev); +void rs600_hpd_fini(struct radeon_device *rdev); +bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void rs600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); +extern void rs600_pm_misc(struct radeon_device *rdev); +extern void rs600_pm_prepare(struct radeon_device *rdev); +extern void rs600_pm_finish(struct radeon_device *rdev); +extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); +extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); +void rs600_set_safe_registers(struct radeon_device *rdev); +extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); +extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); + +/* + * rs690,rs740 + */ +int rs690_init(struct radeon_device *rdev); +void rs690_fini(struct radeon_device *rdev); +int rs690_resume(struct radeon_device *rdev); +int rs690_suspend(struct radeon_device *rdev); +uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); +void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +void rs690_bandwidth_update(struct radeon_device *rdev); +void rs690_line_buffer_adjust(struct radeon_device *rdev, + struct drm_display_mode *mode1, + struct drm_display_mode *mode2); +extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); + +/* + * rv515 + */ +struct rv515_mc_save { + u32 vga_render_control; + u32 vga_hdp_control; + bool crtc_enabled[2]; +}; + +int rv515_init(struct radeon_device *rdev); +void rv515_fini(struct radeon_device *rdev); +uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); +void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); +void rv515_bandwidth_update(struct radeon_device *rdev); +int rv515_resume(struct radeon_device *rdev); +int rv515_suspend(struct radeon_device *rdev); +void rv515_bandwidth_avivo_update(struct radeon_device *rdev); +void rv515_vga_render_disable(struct radeon_device *rdev); +void rv515_set_safe_registers(struct radeon_device *rdev); +void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save); +void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save); +void rv515_clock_startup(struct radeon_device *rdev); +void rv515_debugfs(struct radeon_device *rdev); +int rv515_mc_wait_for_idle(struct radeon_device *rdev); + +/* + * r520,rv530,rv560,rv570,r580 + */ +int r520_init(struct radeon_device *rdev); +int r520_resume(struct radeon_device *rdev); +int r520_mc_wait_for_idle(struct radeon_device *rdev); + +/* + * r600,rv610,rv630,rv620,rv635,rv670,rs780,rs880 + */ +int r600_init(struct radeon_device *rdev); +void r600_fini(struct radeon_device *rdev); +int r600_suspend(struct radeon_device *rdev); +int r600_resume(struct radeon_device *rdev); +void r600_vga_set_state(struct radeon_device *rdev, bool state); +int r600_wb_init(struct radeon_device *rdev); +void r600_wb_fini(struct radeon_device *rdev); +void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); +uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg); +void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +int r600_cs_parse(struct radeon_cs_parser *p); +int r600_dma_cs_parse(struct radeon_cs_parser *p); +void r600_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +void r600_semaphore_ring_emit(struct radeon_device *rdev, + struct radeon_ring *cp, + struct radeon_semaphore *semaphore, + bool emit_wait); +void r600_dma_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +void r600_dma_semaphore_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring, + struct radeon_semaphore *semaphore, + bool emit_wait); +void r600_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring); +bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); +int r600_asic_reset(struct radeon_device *rdev); +int r600_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size); +void r600_clear_surface_reg(struct radeon_device *rdev, int reg); +int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); +int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); +void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); +int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); +int r600_copy_blit(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, struct radeon_fence **fence); +int r600_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, struct radeon_fence **fence); +void r600_hpd_init(struct radeon_device *rdev); +void r600_hpd_fini(struct radeon_device *rdev); +bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void r600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); +extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo); +extern bool r600_gui_idle(struct radeon_device *rdev); +extern void r600_pm_misc(struct radeon_device *rdev); +extern void r600_pm_init_profile(struct radeon_device *rdev); +extern void rs780_pm_init_profile(struct radeon_device *rdev); +extern void r600_pm_get_dynpm_state(struct radeon_device *rdev); +extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes); +extern int r600_get_pcie_lanes(struct radeon_device *rdev); +bool r600_card_posted(struct radeon_device *rdev); +void r600_cp_stop(struct radeon_device *rdev); +int r600_cp_start(struct radeon_device *rdev); +void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size); +int r600_cp_resume(struct radeon_device *rdev); +void r600_cp_fini(struct radeon_device *rdev); +int r600_count_pipe_bits(uint32_t val); +int r600_mc_wait_for_idle(struct radeon_device *rdev); +int r600_pcie_gart_init(struct radeon_device *rdev); +void r600_scratch_init(struct radeon_device *rdev); +int r600_blit_init(struct radeon_device *rdev); +void r600_blit_fini(struct radeon_device *rdev); +int r600_init_microcode(struct radeon_device *rdev); +void r600_fini_microcode(struct radeon_device *rdev); +/* r600 irq */ +irqreturn_t r600_irq_process(struct radeon_device *rdev); +int r600_irq_init(struct radeon_device *rdev); +void r600_irq_fini(struct radeon_device *rdev); +void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); +int r600_irq_set(struct radeon_device *rdev); +void r600_irq_suspend(struct radeon_device *rdev); +void r600_disable_interrupts(struct radeon_device *rdev); +void r600_rlc_stop(struct radeon_device *rdev); +/* r600 audio */ +int r600_audio_init(struct radeon_device *rdev); +void r600_audio_set_clock(struct drm_encoder *encoder, int clock); +struct r600_audio r600_audio_status(struct radeon_device *rdev); +void r600_audio_fini(struct radeon_device *rdev); +int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); +void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); +/* r600 blit */ +int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, + struct radeon_fence **fence, struct radeon_sa_bo **vb, + struct radeon_semaphore **sem); +void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, + struct radeon_sa_bo *vb, struct radeon_semaphore *sem); +void r600_kms_blit_copy(struct radeon_device *rdev, + u64 src_gpu_addr, u64 dst_gpu_addr, + unsigned num_gpu_pages, + struct radeon_sa_bo *vb); +uint64_t r600_get_gpu_clock(struct radeon_device *rdev); + +/* + * rv770,rv730,rv710,rv740 + */ +int rv770_init(struct radeon_device *rdev); +void rv770_fini(struct radeon_device *rdev); +int rv770_suspend(struct radeon_device *rdev); +int rv770_resume(struct radeon_device *rdev); +void rv770_pm_misc(struct radeon_device *rdev); +u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); +void r700_cp_stop(struct radeon_device *rdev); +void r700_cp_fini(struct radeon_device *rdev); +int rv770_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); + +/* + * evergreen + */ +struct evergreen_mc_save { + u32 vga_render_control; + u32 vga_hdp_control; + bool crtc_enabled[RADEON_MAX_CRTCS]; +}; + +void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); +int evergreen_init(struct radeon_device *rdev); +void evergreen_fini(struct radeon_device *rdev); +int evergreen_suspend(struct radeon_device *rdev); +int evergreen_resume(struct radeon_device *rdev); +bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); +int evergreen_asic_reset(struct radeon_device *rdev); +void evergreen_bandwidth_update(struct radeon_device *rdev); +void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +void evergreen_hpd_init(struct radeon_device *rdev); +void evergreen_hpd_fini(struct radeon_device *rdev); +bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +void evergreen_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd); +u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc); +int evergreen_irq_set(struct radeon_device *rdev); +irqreturn_t evergreen_irq_process(struct radeon_device *rdev); +extern int evergreen_cs_parse(struct radeon_cs_parser *p); +extern int evergreen_dma_cs_parse(struct radeon_cs_parser *p); +extern void evergreen_pm_misc(struct radeon_device *rdev); +extern void evergreen_pm_prepare(struct radeon_device *rdev); +extern void evergreen_pm_finish(struct radeon_device *rdev); +extern void sumo_pm_init_profile(struct radeon_device *rdev); +extern void btc_pm_init_profile(struct radeon_device *rdev); +extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); +extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); +extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); +void evergreen_disable_interrupt_state(struct radeon_device *rdev); +int evergreen_blit_init(struct radeon_device *rdev); +int evergreen_mc_wait_for_idle(struct radeon_device *rdev); +void evergreen_dma_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +void evergreen_dma_ring_ib_execute(struct radeon_device *rdev, + struct radeon_ib *ib); +int evergreen_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); +void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); +u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev); +void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); +void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); +void evergreen_mc_program(struct radeon_device *rdev); +int evergreen_mc_init(struct radeon_device *rdev); +void evergreen_irq_suspend(struct radeon_device *rdev); + +/* + * cayman + */ +void cayman_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); +int cayman_init(struct radeon_device *rdev); +void cayman_fini(struct radeon_device *rdev); +int cayman_suspend(struct radeon_device *rdev); +int cayman_resume(struct radeon_device *rdev); +int cayman_asic_reset(struct radeon_device *rdev); +void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +int cayman_vm_init(struct radeon_device *rdev); +void cayman_vm_fini(struct radeon_device *rdev); +void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); +uint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags); +void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags); +int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +void cayman_dma_ring_ib_execute(struct radeon_device *rdev, + struct radeon_ib *ib); +bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring); +void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); +extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev, + int ring, u32 cp_int_cntl); + +/* DCE6 - SI */ +void dce6_bandwidth_update(struct radeon_device *rdev); + +/* + * si + */ +void si_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +void si_pcie_gart_tlb_flush(struct radeon_device *rdev); +int si_init(struct radeon_device *rdev); +void si_fini(struct radeon_device *rdev); +int si_suspend(struct radeon_device *rdev); +int si_resume(struct radeon_device *rdev); +bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); +int si_asic_reset(struct radeon_device *rdev); +void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +int si_irq_set(struct radeon_device *rdev); +irqreturn_t si_irq_process(struct radeon_device *rdev); +int si_vm_init(struct radeon_device *rdev); +void si_vm_fini(struct radeon_device *rdev); +void si_vm_set_page(struct radeon_device *rdev, uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags); +void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); +int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +uint64_t si_get_gpu_clock(struct radeon_device *rdev); +int si_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence); +void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); +void si_rlc_fini(struct radeon_device *rdev); +int si_rlc_init(struct radeon_device *rdev); + +#endif diff --git a/sys/dev/drm2/radeon/radeon_atombios.c b/sys/dev/drm2/radeon/radeon_atombios.c new file mode 100644 index 00000000000..309f1477154 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_atombios.c @@ -0,0 +1,3190 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_asic.h" /* Declares several prototypes; clang is pleased. */ + +#include "atom.h" +#include "atom-bits.h" + +/* local */ +static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, + u16 voltage_id, u16 *voltage); + +union atom_supported_devices { + struct _ATOM_SUPPORTED_DEVICES_INFO info; + struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; + struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; +}; + +static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev, + ATOM_GPIO_I2C_ASSIGMENT *gpio, + u8 index) +{ + /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ + if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { + gpio->ucClkMaskShift = 0x19; + gpio->ucDataMaskShift = 0x18; + } + } + + /* some evergreen boards have bad data for this entry */ + if (ASIC_IS_DCE4(rdev)) { + if ((index == 7) && + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && + (gpio->sucI2cId.ucAccess == 0)) { + gpio->sucI2cId.ucAccess = 0x97; + gpio->ucDataMaskShift = 8; + gpio->ucDataEnShift = 8; + gpio->ucDataY_Shift = 8; + gpio->ucDataA_Shift = 8; + } + } + + /* some DCE3 boards have bad data for this entry */ + if (ASIC_IS_DCE3(rdev)) { + if ((index == 4) && + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && + (gpio->sucI2cId.ucAccess == 0x94)) + gpio->sucI2cId.ucAccess = 0x14; + } +} + +static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio) +{ + struct radeon_i2c_bus_rec i2c; + + memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); + + i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; + i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; + i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; + i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; + i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; + i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; + i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; + i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; + i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); + i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); + i2c.en_clk_mask = (1 << gpio->ucClkEnShift); + i2c.en_data_mask = (1 << gpio->ucDataEnShift); + i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); + i2c.y_data_mask = (1 << gpio->ucDataY_Shift); + i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); + i2c.a_data_mask = (1 << gpio->ucDataA_Shift); + + if (gpio->sucI2cId.sbfAccess.bfHW_Capable) + i2c.hw_capable = true; + else + i2c.hw_capable = false; + + if (gpio->sucI2cId.ucAccess == 0xa0) + i2c.mm_i2c = true; + else + i2c.mm_i2c = false; + + i2c.i2c_id = gpio->sucI2cId.ucAccess; + + if (i2c.mask_clk_reg) + i2c.valid = true; + else + i2c.valid = false; + + return i2c; +} + +static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev, + uint8_t id) +{ + struct atom_context *ctx = rdev->mode_info.atom_context; + ATOM_GPIO_I2C_ASSIGMENT *gpio; + struct radeon_i2c_bus_rec i2c; + int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); + struct _ATOM_GPIO_I2C_INFO *i2c_info; + uint16_t data_offset, size; + int i, num_indices; + + memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); + i2c.valid = false; + + if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { + i2c_info = (struct _ATOM_GPIO_I2C_INFO *)((char *)ctx->bios + data_offset); + + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_GPIO_I2C_ASSIGMENT); + + for (i = 0; i < num_indices; i++) { + gpio = &i2c_info->asGPIO_Info[i]; + + radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); + + if (gpio->sucI2cId.ucAccess == id) { + i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); + break; + } + } + } + + return i2c; +} + +void radeon_atombios_i2c_init(struct radeon_device *rdev) +{ + struct atom_context *ctx = rdev->mode_info.atom_context; + ATOM_GPIO_I2C_ASSIGMENT *gpio; + struct radeon_i2c_bus_rec i2c; + int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); + struct _ATOM_GPIO_I2C_INFO *i2c_info; + uint16_t data_offset, size; + int i, num_indices; + char stmp[32]; + + if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { + i2c_info = (struct _ATOM_GPIO_I2C_INFO *)((char *)ctx->bios + data_offset); + + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_GPIO_I2C_ASSIGMENT); + + for (i = 0; i < num_indices; i++) { + gpio = &i2c_info->asGPIO_Info[i]; + + radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); + + i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); + + if (i2c.valid) { + sprintf(stmp, "0x%x", i2c.i2c_id); + rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); + } + } + } +} + +static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, + u8 id) +{ + struct atom_context *ctx = rdev->mode_info.atom_context; + struct radeon_gpio_rec gpio; + int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT); + struct _ATOM_GPIO_PIN_LUT *gpio_info; + ATOM_GPIO_PIN_ASSIGNMENT *pin; + u16 data_offset, size; + int i, num_indices; + + memset(&gpio, 0, sizeof(struct radeon_gpio_rec)); + gpio.valid = false; + + if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { + gpio_info = (struct _ATOM_GPIO_PIN_LUT *)((char *)ctx->bios + data_offset); + + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_GPIO_PIN_ASSIGNMENT); + + for (i = 0; i < num_indices; i++) { + pin = &gpio_info->asGPIO_Pin[i]; + if (id == pin->ucGPIO_ID) { + gpio.id = pin->ucGPIO_ID; + gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4; + gpio.mask = (1 << pin->ucGpioPinBitShift); + gpio.valid = true; + break; + } + } + } + + return gpio; +} + +static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev, + struct radeon_gpio_rec *gpio) +{ + struct radeon_hpd hpd; + u32 reg; + + memset(&hpd, 0, sizeof(struct radeon_hpd)); + + if (ASIC_IS_DCE6(rdev)) + reg = SI_DC_GPIO_HPD_A; + else if (ASIC_IS_DCE4(rdev)) + reg = EVERGREEN_DC_GPIO_HPD_A; + else + reg = AVIVO_DC_GPIO_HPD_A; + + hpd.gpio = *gpio; + if (gpio->reg == reg) { + switch(gpio->mask) { + case (1 << 0): + hpd.hpd = RADEON_HPD_1; + break; + case (1 << 8): + hpd.hpd = RADEON_HPD_2; + break; + case (1 << 16): + hpd.hpd = RADEON_HPD_3; + break; + case (1 << 24): + hpd.hpd = RADEON_HPD_4; + break; + case (1 << 26): + hpd.hpd = RADEON_HPD_5; + break; + case (1 << 28): + hpd.hpd = RADEON_HPD_6; + break; + default: + hpd.hpd = RADEON_HPD_NONE; + break; + } + } else + hpd.hpd = RADEON_HPD_NONE; + return hpd; +} + +static bool radeon_atom_apply_quirks(struct drm_device *dev, + uint32_t supported_device, + int *connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint16_t *line_mux, + struct radeon_hpd *hpd) +{ + + /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ + if ((dev->pci_device == 0x791e) && + (dev->pci_subvendor == 0x1043) && + (dev->pci_subdevice == 0x826d)) { + if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && + (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) + *connector_type = DRM_MODE_CONNECTOR_DVID; + } + + /* Asrock RS600 board lists the DVI port as HDMI */ + if ((dev->pci_device == 0x7941) && + (dev->pci_subvendor == 0x1849) && + (dev->pci_subdevice == 0x7941)) { + if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && + (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) + *connector_type = DRM_MODE_CONNECTOR_DVID; + } + + /* MSI K9A2GM V2/V3 board has no HDMI or DVI */ + if ((dev->pci_device == 0x796e) && + (dev->pci_subvendor == 0x1462) && + (dev->pci_subdevice == 0x7302)) { + if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) || + (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) + return false; + } + + /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ + if ((dev->pci_device == 0x7941) && + (dev->pci_subvendor == 0x147b) && + (dev->pci_subdevice == 0x2412)) { + if (*connector_type == DRM_MODE_CONNECTOR_DVII) + return false; + } + + /* Falcon NW laptop lists vga ddc line for LVDS */ + if ((dev->pci_device == 0x5653) && + (dev->pci_subvendor == 0x1462) && + (dev->pci_subdevice == 0x0291)) { + if (*connector_type == DRM_MODE_CONNECTOR_LVDS) { + i2c_bus->valid = false; + *line_mux = 53; + } + } + + /* HIS X1300 is DVI+VGA, not DVI+DVI */ + if ((dev->pci_device == 0x7146) && + (dev->pci_subvendor == 0x17af) && + (dev->pci_subdevice == 0x2058)) { + if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) + return false; + } + + /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */ + if ((dev->pci_device == 0x7142) && + (dev->pci_subvendor == 0x1458) && + (dev->pci_subdevice == 0x2134)) { + if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) + return false; + } + + + /* Funky macbooks */ + if ((dev->pci_device == 0x71C5) && + (dev->pci_subvendor == 0x106b) && + (dev->pci_subdevice == 0x0080)) { + if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) || + (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) + return false; + if (supported_device == ATOM_DEVICE_CRT2_SUPPORT) + *line_mux = 0x90; + } + + /* mac rv630, rv730, others */ + if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) && + (*connector_type == DRM_MODE_CONNECTOR_DVII)) { + *connector_type = DRM_MODE_CONNECTOR_9PinDIN; + *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1; + } + + /* ASUS HD 3600 XT board lists the DVI port as HDMI */ + if ((dev->pci_device == 0x9598) && + (dev->pci_subvendor == 0x1043) && + (dev->pci_subdevice == 0x01da)) { + if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + } + } + + /* ASUS HD 3600 board lists the DVI port as HDMI */ + if ((dev->pci_device == 0x9598) && + (dev->pci_subvendor == 0x1043) && + (dev->pci_subdevice == 0x01e4)) { + if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + } + } + + /* ASUS HD 3450 board lists the DVI port as HDMI */ + if ((dev->pci_device == 0x95C5) && + (dev->pci_subvendor == 0x1043) && + (dev->pci_subdevice == 0x01e2)) { + if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + } + } + + /* some BIOSes seem to report DAC on HDMI - usually this is a board with + * HDMI + VGA reporting as HDMI + */ + if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { + if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) { + *connector_type = DRM_MODE_CONNECTOR_VGA; + *line_mux = 0; + } + } + + /* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port + * on the laptop and a DVI port on the docking station and + * both share the same encoder, hpd pin, and ddc line. + * So while the bios table is technically correct, + * we drop the DVI port here since xrandr has no concept of + * encoders and will try and drive both connectors + * with different crtcs which isn't possible on the hardware + * side and leaves no crtcs for LVDS or VGA. + */ + if (((dev->pci_device == 0x95c4) || (dev->pci_device == 0x9591)) && + (dev->pci_subvendor == 0x1025) && + (dev->pci_subdevice == 0x013c)) { + if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && + (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { + /* actually it's a DVI-D port not DVI-I */ + *connector_type = DRM_MODE_CONNECTOR_DVID; + return false; + } + } + + /* XFX Pine Group device rv730 reports no VGA DDC lines + * even though they are wired up to record 0x93 + */ + if ((dev->pci_device == 0x9498) && + (dev->pci_subvendor == 0x1682) && + (dev->pci_subdevice == 0x2452) && + (i2c_bus->valid == false) && + !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) { + struct radeon_device *rdev = dev->dev_private; + *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93); + } + + /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ + if (((dev->pci_device == 0x9802) || (dev->pci_device == 0x9806)) && + (dev->pci_subvendor == 0x1734) && + (dev->pci_subdevice == 0x11bd)) { + if (*connector_type == DRM_MODE_CONNECTOR_VGA) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + *line_mux = 0x3103; + } else if (*connector_type == DRM_MODE_CONNECTOR_DVID) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + } + } + + + return true; +} + +const int supported_devices_connector_convert[] = { + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_VGA, + DRM_MODE_CONNECTOR_DVII, + DRM_MODE_CONNECTOR_DVID, + DRM_MODE_CONNECTOR_DVIA, + DRM_MODE_CONNECTOR_SVIDEO, + DRM_MODE_CONNECTOR_Composite, + DRM_MODE_CONNECTOR_LVDS, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_HDMIA, + DRM_MODE_CONNECTOR_HDMIB, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_9PinDIN, + DRM_MODE_CONNECTOR_DisplayPort +}; + +const uint16_t supported_devices_connector_object_id_convert[] = { + CONNECTOR_OBJECT_ID_NONE, + CONNECTOR_OBJECT_ID_VGA, + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */ + CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */ + CONNECTOR_OBJECT_ID_COMPOSITE, + CONNECTOR_OBJECT_ID_SVIDEO, + CONNECTOR_OBJECT_ID_LVDS, + CONNECTOR_OBJECT_ID_9PIN_DIN, + CONNECTOR_OBJECT_ID_9PIN_DIN, + CONNECTOR_OBJECT_ID_DISPLAYPORT, + CONNECTOR_OBJECT_ID_HDMI_TYPE_A, + CONNECTOR_OBJECT_ID_HDMI_TYPE_B, + CONNECTOR_OBJECT_ID_SVIDEO +}; + +const int object_connector_convert[] = { + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_DVII, + DRM_MODE_CONNECTOR_DVII, + DRM_MODE_CONNECTOR_DVID, + DRM_MODE_CONNECTOR_DVID, + DRM_MODE_CONNECTOR_VGA, + DRM_MODE_CONNECTOR_Composite, + DRM_MODE_CONNECTOR_SVIDEO, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_9PinDIN, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_HDMIA, + DRM_MODE_CONNECTOR_HDMIB, + DRM_MODE_CONNECTOR_LVDS, + DRM_MODE_CONNECTOR_9PinDIN, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_DisplayPort, + DRM_MODE_CONNECTOR_eDP, + DRM_MODE_CONNECTOR_Unknown +}; + +bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct atom_context *ctx = mode_info->atom_context; + int index = GetIndexIntoMasterTable(DATA, Object_Header); + u16 size, data_offset; + u8 frev, crev; + ATOM_CONNECTOR_OBJECT_TABLE *con_obj; + ATOM_ENCODER_OBJECT_TABLE *enc_obj; + ATOM_OBJECT_TABLE *router_obj; + ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; + ATOM_OBJECT_HEADER *obj_header; + int i, j, k, path_size, device_support; + int connector_type; + u16 igp_lane_info, conn_id, connector_object_id; + struct radeon_i2c_bus_rec ddc_bus; + struct radeon_router router; + struct radeon_gpio_rec gpio; + struct radeon_hpd hpd; + + if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) + return false; + + if (crev < 2) + return false; + + obj_header = (ATOM_OBJECT_HEADER *) ((char *)ctx->bios + data_offset); + path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(obj_header->usDisplayPathTableOffset)); + con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(obj_header->usConnectorObjectTableOffset)); + enc_obj = (ATOM_ENCODER_OBJECT_TABLE *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(obj_header->usEncoderObjectTableOffset)); + router_obj = (ATOM_OBJECT_TABLE *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(obj_header->usRouterObjectTableOffset)); + device_support = le16_to_cpu(obj_header->usDeviceSupport); + + path_size = 0; + for (i = 0; i < path_obj->ucNumOfDispPath; i++) { + uint8_t *addr = (uint8_t *) path_obj->asDispPath; + ATOM_DISPLAY_OBJECT_PATH *path; + addr += path_size; + path = (ATOM_DISPLAY_OBJECT_PATH *) addr; + path_size += le16_to_cpu(path->usSize); + + if (device_support & le16_to_cpu(path->usDeviceTag)) { + uint8_t con_obj_id, con_obj_num, con_obj_type; + + con_obj_id = + (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) + >> OBJECT_ID_SHIFT; + con_obj_num = + (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) + >> ENUM_ID_SHIFT; + con_obj_type = + (le16_to_cpu(path->usConnObjectId) & + OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; + + /* TODO CV support */ + if (le16_to_cpu(path->usDeviceTag) == + ATOM_DEVICE_CV_SUPPORT) + continue; + + /* IGP chips */ + if ((rdev->flags & RADEON_IS_IGP) && + (con_obj_id == + CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { + uint16_t igp_offset = 0; + ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj; + + index = + GetIndexIntoMasterTable(DATA, + IntegratedSystemInfo); + + if (atom_parse_data_header(ctx, index, &size, &frev, + &crev, &igp_offset)) { + + if (crev >= 2) { + igp_obj = + (ATOM_INTEGRATED_SYSTEM_INFO_V2 + *) ((char *)ctx->bios + igp_offset); + + if (igp_obj) { + uint32_t slot_config, ct; + + if (con_obj_num == 1) + slot_config = + igp_obj-> + ulDDISlot1Config; + else + slot_config = + igp_obj-> + ulDDISlot2Config; + + ct = (slot_config >> 16) & 0xff; + connector_type = + object_connector_convert + [ct]; + connector_object_id = ct; + igp_lane_info = + slot_config & 0xffff; + } else + continue; + } else + continue; + } else { + igp_lane_info = 0; + connector_type = + object_connector_convert[con_obj_id]; + connector_object_id = con_obj_id; + } + } else { + igp_lane_info = 0; + connector_type = + object_connector_convert[con_obj_id]; + connector_object_id = con_obj_id; + } + + if (connector_type == DRM_MODE_CONNECTOR_Unknown) + continue; + + router.ddc_valid = false; + router.cd_valid = false; + for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { + uint8_t grph_obj_id, grph_obj_num, grph_obj_type; + + grph_obj_id = + (le16_to_cpu(path->usGraphicObjIds[j]) & + OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + grph_obj_num = + (le16_to_cpu(path->usGraphicObjIds[j]) & + ENUM_ID_MASK) >> ENUM_ID_SHIFT; + grph_obj_type = + (le16_to_cpu(path->usGraphicObjIds[j]) & + OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; + + if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { + for (k = 0; k < enc_obj->ucNumberOfObjects; k++) { + u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID); + if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) { + ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(enc_obj->asObjects[k].usRecordOffset)); + ATOM_ENCODER_CAP_RECORD *cap_record; + u16 caps = 0; + + while (record->ucRecordSize > 0 && + record->ucRecordType > 0 && + record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { + switch (record->ucRecordType) { + case ATOM_ENCODER_CAP_RECORD_TYPE: + cap_record =(ATOM_ENCODER_CAP_RECORD *) + record; + caps = le16_to_cpu(cap_record->usEncoderCap); + break; + } + record = (ATOM_COMMON_RECORD_HEADER *) + ((char *)record + record->ucRecordSize); + } + radeon_add_atom_encoder(dev, + encoder_obj, + le16_to_cpu + (path-> + usDeviceTag), + caps); + } + } + } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { + for (k = 0; k < router_obj->ucNumberOfObjects; k++) { + u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID); + if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { + ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(router_obj->asObjects[k].usRecordOffset)); + ATOM_I2C_RECORD *i2c_record; + ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; + ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; + ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path; + ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = + (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); + int enum_id; + + router.router_id = router_obj_id; + for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; + enum_id++) { + if (le16_to_cpu(path->usConnObjectId) == + le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) + break; + } + + while (record->ucRecordSize > 0 && + record->ucRecordType > 0 && + record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { + switch (record->ucRecordType) { + case ATOM_I2C_RECORD_TYPE: + i2c_record = + (ATOM_I2C_RECORD *) + record; + i2c_config = + (ATOM_I2C_ID_CONFIG_ACCESS *) + &i2c_record->sucI2cId; + router.i2c_info = + radeon_lookup_i2c_gpio(rdev, + i2c_config-> + ucAccess); + router.i2c_addr = i2c_record->ucI2CAddr >> 1; + break; + case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: + ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) + record; + router.ddc_valid = true; + router.ddc_mux_type = ddc_path->ucMuxType; + router.ddc_mux_control_pin = ddc_path->ucMuxControlPin; + router.ddc_mux_state = ddc_path->ucMuxState[enum_id]; + break; + case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE: + cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *) + record; + router.cd_valid = true; + router.cd_mux_type = cd_path->ucMuxType; + router.cd_mux_control_pin = cd_path->ucMuxControlPin; + router.cd_mux_state = cd_path->ucMuxState[enum_id]; + break; + } + record = (ATOM_COMMON_RECORD_HEADER *) + ((char *)record + record->ucRecordSize); + } + } + } + } + } + + /* look up gpio for ddc, hpd */ + ddc_bus.valid = false; + hpd.hpd = RADEON_HPD_NONE; + if ((le16_to_cpu(path->usDeviceTag) & + (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { + for (j = 0; j < con_obj->ucNumberOfObjects; j++) { + if (le16_to_cpu(path->usConnObjectId) == + le16_to_cpu(con_obj->asObjects[j]. + usObjectID)) { + ATOM_COMMON_RECORD_HEADER + *record = + (ATOM_COMMON_RECORD_HEADER + *) + ((char *)ctx->bios + data_offset + + le16_to_cpu(con_obj-> + asObjects[j]. + usRecordOffset)); + ATOM_I2C_RECORD *i2c_record; + ATOM_HPD_INT_RECORD *hpd_record; + ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; + + while (record->ucRecordSize > 0 && + record->ucRecordType > 0 && + record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { + switch (record->ucRecordType) { + case ATOM_I2C_RECORD_TYPE: + i2c_record = + (ATOM_I2C_RECORD *) + record; + i2c_config = + (ATOM_I2C_ID_CONFIG_ACCESS *) + &i2c_record->sucI2cId; + ddc_bus = radeon_lookup_i2c_gpio(rdev, + i2c_config-> + ucAccess); + break; + case ATOM_HPD_INT_RECORD_TYPE: + hpd_record = + (ATOM_HPD_INT_RECORD *) + record; + gpio = radeon_lookup_gpio(rdev, + hpd_record->ucHPDIntGPIOID); + hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); + hpd.plugged_state = hpd_record->ucPlugged_PinState; + break; + } + record = + (ATOM_COMMON_RECORD_HEADER + *) ((char *)record + + + record-> + ucRecordSize); + } + break; + } + } + } + + /* needed for aux chan transactions */ + ddc_bus.hpd = hpd.hpd; + + conn_id = le16_to_cpu(path->usConnObjectId); + + if (!radeon_atom_apply_quirks + (dev, le16_to_cpu(path->usDeviceTag), &connector_type, + &ddc_bus, &conn_id, &hpd)) + continue; + + radeon_add_atom_connector(dev, + conn_id, + le16_to_cpu(path-> + usDeviceTag), + connector_type, &ddc_bus, + igp_lane_info, + connector_object_id, + &hpd, + &router); + + } + } + + radeon_link_encoder_connector(dev); + + return true; +} + +static uint16_t atombios_get_connector_object_id(struct drm_device *dev, + int connector_type, + uint16_t devices) +{ + struct radeon_device *rdev = dev->dev_private; + + if (rdev->flags & RADEON_IS_IGP) { + return supported_devices_connector_object_id_convert + [connector_type]; + } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) || + (connector_type == DRM_MODE_CONNECTOR_DVID)) && + (devices & ATOM_DEVICE_DFP2_SUPPORT)) { + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct atom_context *ctx = mode_info->atom_context; + int index = GetIndexIntoMasterTable(DATA, XTMDS_Info); + uint16_t size, data_offset; + uint8_t frev, crev; + ATOM_XTMDS_INFO *xtmds; + + if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) { + xtmds = (ATOM_XTMDS_INFO *)((char *)ctx->bios + data_offset); + + if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) { + if (connector_type == DRM_MODE_CONNECTOR_DVII) + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; + else + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; + } else { + if (connector_type == DRM_MODE_CONNECTOR_DVII) + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; + else + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; + } + } else + return supported_devices_connector_object_id_convert + [connector_type]; + } else { + return supported_devices_connector_object_id_convert + [connector_type]; + } +} + +struct bios_connector { + bool valid; + uint16_t line_mux; + uint16_t devices; + int connector_type; + struct radeon_i2c_bus_rec ddc_bus; + struct radeon_hpd hpd; +}; + +bool radeon_get_atom_connector_info_from_supported_devices_table(struct + drm_device + *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct atom_context *ctx = mode_info->atom_context; + int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo); + uint16_t size, data_offset; + uint8_t frev, crev; + uint16_t device_support; + uint8_t dac; + union atom_supported_devices *supported_devices; + int i, j, max_device; + struct bios_connector *bios_connectors; + size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; + struct radeon_router router; + + router.ddc_valid = false; + router.cd_valid = false; + + bios_connectors = malloc(bc_size, DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!bios_connectors) + return false; + + if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, + &data_offset)) { + free(bios_connectors, DRM_MEM_DRIVER); + return false; + } + + supported_devices = + (union atom_supported_devices *)((char *)ctx->bios + data_offset); + + device_support = le16_to_cpu(supported_devices->info.usDeviceSupport); + + if (frev > 1) + max_device = ATOM_MAX_SUPPORTED_DEVICE; + else + max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO; + + for (i = 0; i < max_device; i++) { + ATOM_CONNECTOR_INFO_I2C ci = + supported_devices->info.asConnInfo[i]; + + bios_connectors[i].valid = false; + + if (!(device_support & (1 << i))) { + continue; + } + + if (i == ATOM_DEVICE_CV_INDEX) { + DRM_DEBUG_KMS("Skipping Component Video\n"); + continue; + } + + bios_connectors[i].connector_type = + supported_devices_connector_convert[ci.sucConnectorInfo. + sbfAccess. + bfConnectorType]; + + if (bios_connectors[i].connector_type == + DRM_MODE_CONNECTOR_Unknown) + continue; + + dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; + + bios_connectors[i].line_mux = + ci.sucI2cId.ucAccess; + + /* give tv unique connector ids */ + if (i == ATOM_DEVICE_TV1_INDEX) { + bios_connectors[i].ddc_bus.valid = false; + bios_connectors[i].line_mux = 50; + } else if (i == ATOM_DEVICE_TV2_INDEX) { + bios_connectors[i].ddc_bus.valid = false; + bios_connectors[i].line_mux = 51; + } else if (i == ATOM_DEVICE_CV_INDEX) { + bios_connectors[i].ddc_bus.valid = false; + bios_connectors[i].line_mux = 52; + } else + bios_connectors[i].ddc_bus = + radeon_lookup_i2c_gpio(rdev, + bios_connectors[i].line_mux); + + if ((crev > 1) && (frev > 1)) { + u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap; + switch (isb) { + case 0x4: + bios_connectors[i].hpd.hpd = RADEON_HPD_1; + break; + case 0xa: + bios_connectors[i].hpd.hpd = RADEON_HPD_2; + break; + default: + bios_connectors[i].hpd.hpd = RADEON_HPD_NONE; + break; + } + } else { + if (i == ATOM_DEVICE_DFP1_INDEX) + bios_connectors[i].hpd.hpd = RADEON_HPD_1; + else if (i == ATOM_DEVICE_DFP2_INDEX) + bios_connectors[i].hpd.hpd = RADEON_HPD_2; + else + bios_connectors[i].hpd.hpd = RADEON_HPD_NONE; + } + + /* Always set the connector type to VGA for CRT1/CRT2. if they are + * shared with a DVI port, we'll pick up the DVI connector when we + * merge the outputs. Some bioses incorrectly list VGA ports as DVI. + */ + if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) + bios_connectors[i].connector_type = + DRM_MODE_CONNECTOR_VGA; + + if (!radeon_atom_apply_quirks + (dev, (1 << i), &bios_connectors[i].connector_type, + &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux, + &bios_connectors[i].hpd)) + continue; + + bios_connectors[i].valid = true; + bios_connectors[i].devices = (1 << i); + + if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) + radeon_add_atom_encoder(dev, + radeon_get_encoder_enum(dev, + (1 << i), + dac), + (1 << i), + 0); + else + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + (1 << i), + dac), + (1 << i)); + } + + /* combine shared connectors */ + for (i = 0; i < max_device; i++) { + if (bios_connectors[i].valid) { + for (j = 0; j < max_device; j++) { + if (bios_connectors[j].valid && (i != j)) { + if (bios_connectors[i].line_mux == + bios_connectors[j].line_mux) { + /* make sure not to combine LVDS */ + if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) { + bios_connectors[i].line_mux = 53; + bios_connectors[i].ddc_bus.valid = false; + continue; + } + if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) { + bios_connectors[j].line_mux = 53; + bios_connectors[j].ddc_bus.valid = false; + continue; + } + /* combine analog and digital for DVI-I */ + if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) && + (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) || + ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) && + (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) { + bios_connectors[i].devices |= + bios_connectors[j].devices; + bios_connectors[i].connector_type = + DRM_MODE_CONNECTOR_DVII; + if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) + bios_connectors[i].hpd = + bios_connectors[j].hpd; + bios_connectors[j].valid = false; + } + } + } + } + } + } + + /* add the connectors */ + for (i = 0; i < max_device; i++) { + if (bios_connectors[i].valid) { + uint16_t connector_object_id = + atombios_get_connector_object_id(dev, + bios_connectors[i].connector_type, + bios_connectors[i].devices); + radeon_add_atom_connector(dev, + bios_connectors[i].line_mux, + bios_connectors[i].devices, + bios_connectors[i]. + connector_type, + &bios_connectors[i].ddc_bus, + 0, + connector_object_id, + &bios_connectors[i].hpd, + &router); + } + } + + radeon_link_encoder_connector(dev); + + free(bios_connectors, DRM_MEM_DRIVER); + return true; +} + +union firmware_info { + ATOM_FIRMWARE_INFO info; + ATOM_FIRMWARE_INFO_V1_2 info_12; + ATOM_FIRMWARE_INFO_V1_3 info_13; + ATOM_FIRMWARE_INFO_V1_4 info_14; + ATOM_FIRMWARE_INFO_V2_1 info_21; + ATOM_FIRMWARE_INFO_V2_2 info_22; +}; + +bool radeon_atom_get_clock_info(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + union firmware_info *firmware_info; + uint8_t frev, crev; + struct radeon_pll *p1pll = &rdev->clock.p1pll; + struct radeon_pll *p2pll = &rdev->clock.p2pll; + struct radeon_pll *dcpll = &rdev->clock.dcpll; + struct radeon_pll *spll = &rdev->clock.spll; + struct radeon_pll *mpll = &rdev->clock.mpll; + uint16_t data_offset; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + firmware_info = + (union firmware_info *)((char *)mode_info->atom_context->bios + + data_offset); + /* pixel clocks */ + p1pll->reference_freq = + le16_to_cpu(firmware_info->info.usReferenceClock); + p1pll->reference_div = 0; + + if (crev < 2) + p1pll->pll_out_min = + le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output); + else + p1pll->pll_out_min = + le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output); + p1pll->pll_out_max = + le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); + + if (crev >= 4) { + p1pll->lcd_pll_out_min = + le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100; + if (p1pll->lcd_pll_out_min == 0) + p1pll->lcd_pll_out_min = p1pll->pll_out_min; + p1pll->lcd_pll_out_max = + le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100; + if (p1pll->lcd_pll_out_max == 0) + p1pll->lcd_pll_out_max = p1pll->pll_out_max; + } else { + p1pll->lcd_pll_out_min = p1pll->pll_out_min; + p1pll->lcd_pll_out_max = p1pll->pll_out_max; + } + + if (p1pll->pll_out_min == 0) { + if (ASIC_IS_AVIVO(rdev)) + p1pll->pll_out_min = 64800; + else + p1pll->pll_out_min = 20000; + } + + p1pll->pll_in_min = + le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input); + p1pll->pll_in_max = + le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input); + + *p2pll = *p1pll; + + /* system clock */ + if (ASIC_IS_DCE4(rdev)) + spll->reference_freq = + le16_to_cpu(firmware_info->info_21.usCoreReferenceClock); + else + spll->reference_freq = + le16_to_cpu(firmware_info->info.usReferenceClock); + spll->reference_div = 0; + + spll->pll_out_min = + le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output); + spll->pll_out_max = + le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output); + + /* ??? */ + if (spll->pll_out_min == 0) { + if (ASIC_IS_AVIVO(rdev)) + spll->pll_out_min = 64800; + else + spll->pll_out_min = 20000; + } + + spll->pll_in_min = + le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input); + spll->pll_in_max = + le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input); + + /* memory clock */ + if (ASIC_IS_DCE4(rdev)) + mpll->reference_freq = + le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock); + else + mpll->reference_freq = + le16_to_cpu(firmware_info->info.usReferenceClock); + mpll->reference_div = 0; + + mpll->pll_out_min = + le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output); + mpll->pll_out_max = + le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output); + + /* ??? */ + if (mpll->pll_out_min == 0) { + if (ASIC_IS_AVIVO(rdev)) + mpll->pll_out_min = 64800; + else + mpll->pll_out_min = 20000; + } + + mpll->pll_in_min = + le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input); + mpll->pll_in_max = + le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input); + + rdev->clock.default_sclk = + le32_to_cpu(firmware_info->info.ulDefaultEngineClock); + rdev->clock.default_mclk = + le32_to_cpu(firmware_info->info.ulDefaultMemoryClock); + + if (ASIC_IS_DCE4(rdev)) { + rdev->clock.default_dispclk = + le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq); + if (rdev->clock.default_dispclk == 0) { + if (ASIC_IS_DCE5(rdev)) + rdev->clock.default_dispclk = 54000; /* 540 Mhz */ + else + rdev->clock.default_dispclk = 60000; /* 600 Mhz */ + } + rdev->clock.dp_extclk = + le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); + } + *dcpll = *p1pll; + + rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); + if (rdev->clock.max_pixel_clock == 0) + rdev->clock.max_pixel_clock = 40000; + + /* not technically a clock, but... */ + rdev->mode_info.firmware_flags = + le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess); + + return true; + } + + return false; +} + +union igp_info { + struct _ATOM_INTEGRATED_SYSTEM_INFO info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; +}; + +bool radeon_atombios_sideport_present(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + union igp_info *igp_info; + u8 frev, crev; + u16 data_offset; + + /* sideport is AMD only */ + if (rdev->family == CHIP_RS600) + return false; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + igp_info = (union igp_info *)((char *)mode_info->atom_context->bios + + data_offset); + switch (crev) { + case 1: + if (le32_to_cpu(igp_info->info.ulBootUpMemoryClock)) + return true; + break; + case 2: + if (le32_to_cpu(igp_info->info_2.ulBootUpSidePortClock)) + return true; + break; + default: + DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); + break; + } + } + return false; +} + +bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, TMDS_Info); + uint16_t data_offset; + struct _ATOM_TMDS_INFO *tmds_info; + uint8_t frev, crev; + uint16_t maxfreq; + int i; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + tmds_info = + (struct _ATOM_TMDS_INFO *)((char *)mode_info->atom_context->bios + + data_offset); + + maxfreq = le16_to_cpu(tmds_info->usMaxFrequency); + for (i = 0; i < 4; i++) { + tmds->tmds_pll[i].freq = + le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency); + tmds->tmds_pll[i].value = + tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f; + tmds->tmds_pll[i].value |= + (tmds_info->asMiscInfo[i]. + ucPLL_VCO_Gain & 0x3f) << 6; + tmds->tmds_pll[i].value |= + (tmds_info->asMiscInfo[i]. + ucPLL_DutyCycle & 0xf) << 12; + tmds->tmds_pll[i].value |= + (tmds_info->asMiscInfo[i]. + ucPLL_VoltageSwing & 0xf) << 16; + + DRM_DEBUG_KMS("TMDS PLL From ATOMBIOS %u %x\n", + tmds->tmds_pll[i].freq, + tmds->tmds_pll[i].value); + + if (maxfreq == tmds->tmds_pll[i].freq) { + tmds->tmds_pll[i].freq = 0xffffffff; + break; + } + } + return true; + } + return false; +} + +bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, + struct radeon_atom_ss *ss, + int id) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); + uint16_t data_offset, size; + struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; + uint8_t frev, crev; + int i, num_indices; + + memset(ss, 0, sizeof(struct radeon_atom_ss)); + if (atom_parse_data_header(mode_info->atom_context, index, &size, + &frev, &crev, &data_offset)) { + ss_info = + (struct _ATOM_SPREAD_SPECTRUM_INFO *)((char *)mode_info->atom_context->bios + data_offset); + + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); + + for (i = 0; i < num_indices; i++) { + if (ss_info->asSS_Info[i].ucSS_Id == id) { + ss->percentage = + le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); + ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType; + ss->step = ss_info->asSS_Info[i].ucSS_Step; + ss->delay = ss_info->asSS_Info[i].ucSS_Delay; + ss->range = ss_info->asSS_Info[i].ucSS_Range; + ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; + return true; + } + } + } + return false; +} + +static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, + struct radeon_atom_ss *ss, + int id) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + u16 data_offset, size; + union igp_info *igp_info; + u8 frev, crev; + u16 percentage = 0, rate = 0; + + /* get any igp specific overrides */ + if (atom_parse_data_header(mode_info->atom_context, index, &size, + &frev, &crev, &data_offset)) { + igp_info = (union igp_info *) + ((char *)mode_info->atom_context->bios + data_offset); + switch (crev) { + case 6: + switch (id) { + case ASIC_INTERNAL_SS_ON_TMDS: + percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); + rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_HDMI: + percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); + rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_LVDS: + percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); + rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); + break; + } + break; + case 7: + switch (id) { + case ASIC_INTERNAL_SS_ON_TMDS: + percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); + rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_HDMI: + percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); + rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_LVDS: + percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); + rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); + break; + } + break; + default: + DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); + break; + } + if (percentage) + ss->percentage = percentage; + if (rate) + ss->rate = rate; + } +} + +union asic_ss_info { + struct _ATOM_ASIC_INTERNAL_SS_INFO info; + struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; + struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3; +}; + +bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, + struct radeon_atom_ss *ss, + int id, u32 clock) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); + uint16_t data_offset, size; + union asic_ss_info *ss_info; + uint8_t frev, crev; + int i, num_indices; + + memset(ss, 0, sizeof(struct radeon_atom_ss)); + if (atom_parse_data_header(mode_info->atom_context, index, &size, + &frev, &crev, &data_offset)) { + + ss_info = + (union asic_ss_info *)((char *)mode_info->atom_context->bios + data_offset); + + switch (frev) { + case 1: + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_ASIC_SS_ASSIGNMENT); + + for (i = 0; i < num_indices; i++) { + if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) && + (clock <= le32_to_cpu(ss_info->info.asSpreadSpectrum[i].ulTargetClockRange))) { + ss->percentage = + le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage); + ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode; + ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz); + return true; + } + } + break; + case 2: + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); + for (i = 0; i < num_indices; i++) { + if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) && + (clock <= le32_to_cpu(ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange))) { + ss->percentage = + le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage); + ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode; + ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz); + return true; + } + } + break; + case 3: + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); + for (i = 0; i < num_indices; i++) { + if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) && + (clock <= le32_to_cpu(ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange))) { + ss->percentage = + le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); + ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; + ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); + if (rdev->flags & RADEON_IS_IGP) + radeon_atombios_get_igp_ss_overrides(rdev, ss, id); + return true; + } + } + break; + default: + DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev); + break; + } + + } + return false; +} + +union lvds_info { + struct _ATOM_LVDS_INFO info; + struct _ATOM_LVDS_INFO_V12 info_12; +}; + +struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct + radeon_encoder + *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, LVDS_Info); + uint16_t data_offset, misc; + union lvds_info *lvds_info; + uint8_t frev, crev; + struct radeon_encoder_atom_dig *lvds = NULL; + int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + lvds_info = + (union lvds_info *)((char *)mode_info->atom_context->bios + data_offset); + lvds = + malloc(sizeof(struct radeon_encoder_atom_dig), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + if (!lvds) + return NULL; + + lvds->native_mode.clock = + le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10; + lvds->native_mode.hdisplay = + le16_to_cpu(lvds_info->info.sLCDTiming.usHActive); + lvds->native_mode.vdisplay = + le16_to_cpu(lvds_info->info.sLCDTiming.usVActive); + lvds->native_mode.htotal = lvds->native_mode.hdisplay + + le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time); + lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + + le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset); + lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + + le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth); + lvds->native_mode.vtotal = lvds->native_mode.vdisplay + + le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time); + lvds->native_mode.vsync_start = lvds->native_mode.vdisplay + + le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset); + lvds->native_mode.vsync_end = lvds->native_mode.vsync_start + + le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); + lvds->panel_pwr_delay = + le16_to_cpu(lvds_info->info.usOffDelayInMs); + lvds->lcd_misc = lvds_info->info.ucLVDS_Misc; + + misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); + if (misc & ATOM_VSYNC_POLARITY) + lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC; + if (misc & ATOM_HSYNC_POLARITY) + lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC; + if (misc & ATOM_COMPOSITESYNC) + lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC; + if (misc & ATOM_INTERLACE) + lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE; + if (misc & ATOM_DOUBLE_CLOCK_MODE) + lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN; + + lvds->native_mode.width_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageHSize); + lvds->native_mode.height_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageVSize); + + /* set crtc values */ + drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); + + lvds->lcd_ss_id = lvds_info->info.ucSS_Id; + + encoder->native_mode = lvds->native_mode; + + if (encoder_enum == 2) + lvds->linkb = true; + else + lvds->linkb = false; + + /* parse the lcd record table */ + if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) { + ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; + ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record; + bool bad_record = false; + u8 *record; + + if ((frev == 1) && (crev < 2)) + /* absolute */ + record = (u8 *)((char *)mode_info->atom_context->bios + + le16_to_cpu(lvds_info->info.usModePatchTableOffset)); + else + /* relative */ + record = (u8 *)((char *)mode_info->atom_context->bios + + data_offset + + le16_to_cpu(lvds_info->info.usModePatchTableOffset)); + while (*record != ATOM_RECORD_END_TYPE) { + switch (*record) { + case LCD_MODE_PATCH_RECORD_MODE_TYPE: + record += sizeof(ATOM_PATCH_RECORD_MODE); + break; + case LCD_RTS_RECORD_TYPE: + record += sizeof(ATOM_LCD_RTS_RECORD); + break; + case LCD_CAP_RECORD_TYPE: + record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); + break; + case LCD_FAKE_EDID_PATCH_RECORD_TYPE: + fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; + if (fake_edid_record->ucFakeEDIDLength) { + struct edid *edid; + int edid_size = + max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); + edid = malloc(edid_size, DRM_MEM_KMS, M_WAITOK); + if (edid) { + memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], + fake_edid_record->ucFakeEDIDLength); + + if (drm_edid_is_valid(edid)) { + rdev->mode_info.bios_hardcoded_edid = edid; + rdev->mode_info.bios_hardcoded_edid_size = edid_size; + } else + free(edid, DRM_MEM_KMS); + } + } + record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); + break; + case LCD_PANEL_RESOLUTION_RECORD_TYPE: + panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; + lvds->native_mode.width_mm = panel_res_record->usHSize; + lvds->native_mode.height_mm = panel_res_record->usVSize; + record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); + break; + default: + DRM_ERROR("Bad LCD record %d\n", *record); + bad_record = true; + break; + } + if (bad_record) + break; + } + } + } + return lvds; +} + +struct radeon_encoder_primary_dac * +radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, CompassionateData); + uint16_t data_offset; + struct _COMPASSIONATE_DATA *dac_info; + uint8_t frev, crev; + uint8_t bg, dac; + struct radeon_encoder_primary_dac *p_dac = NULL; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + dac_info = (struct _COMPASSIONATE_DATA *) + ((char *)mode_info->atom_context->bios + data_offset); + + p_dac = malloc(sizeof(struct radeon_encoder_primary_dac), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + if (!p_dac) + return NULL; + + bg = dac_info->ucDAC1_BG_Adjustment; + dac = dac_info->ucDAC1_DAC_Adjustment; + p_dac->ps2_pdac_adj = (bg << 8) | (dac); + + } + return p_dac; +} + +bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, + struct drm_display_mode *mode) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + ATOM_ANALOG_TV_INFO *tv_info; + ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; + ATOM_DTD_FORMAT *dtd_timings; + int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); + u8 frev, crev; + u16 data_offset, misc; + + if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL, + &frev, &crev, &data_offset)) + return false; + + switch (crev) { + case 1: + tv_info = (ATOM_ANALOG_TV_INFO *)((char *)mode_info->atom_context->bios + data_offset); + if (index >= MAX_SUPPORTED_TV_TIMING) + return false; + + mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); + mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); + mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); + mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) + + le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); + + mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); + mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); + mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); + mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) + + le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); + + mode->flags = 0; + misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess); + if (misc & ATOM_VSYNC_POLARITY) + mode->flags |= DRM_MODE_FLAG_NVSYNC; + if (misc & ATOM_HSYNC_POLARITY) + mode->flags |= DRM_MODE_FLAG_NHSYNC; + if (misc & ATOM_COMPOSITESYNC) + mode->flags |= DRM_MODE_FLAG_CSYNC; + if (misc & ATOM_INTERLACE) + mode->flags |= DRM_MODE_FLAG_INTERLACE; + if (misc & ATOM_DOUBLE_CLOCK_MODE) + mode->flags |= DRM_MODE_FLAG_DBLSCAN; + + mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; + + if (index == 1) { + /* PAL timings appear to have wrong values for totals */ + mode->crtc_htotal -= 1; + mode->crtc_vtotal -= 1; + } + break; + case 2: + tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)((char *)mode_info->atom_context->bios + data_offset); + if (index >= MAX_SUPPORTED_TV_TIMING_V1_2) + return false; + + dtd_timings = &tv_info_v1_2->aModeTimings[index]; + mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) + + le16_to_cpu(dtd_timings->usHBlanking_Time); + mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive); + mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) + + le16_to_cpu(dtd_timings->usHSyncOffset); + mode->crtc_hsync_end = mode->crtc_hsync_start + + le16_to_cpu(dtd_timings->usHSyncWidth); + + mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) + + le16_to_cpu(dtd_timings->usVBlanking_Time); + mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive); + mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) + + le16_to_cpu(dtd_timings->usVSyncOffset); + mode->crtc_vsync_end = mode->crtc_vsync_start + + le16_to_cpu(dtd_timings->usVSyncWidth); + + mode->flags = 0; + misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); + if (misc & ATOM_VSYNC_POLARITY) + mode->flags |= DRM_MODE_FLAG_NVSYNC; + if (misc & ATOM_HSYNC_POLARITY) + mode->flags |= DRM_MODE_FLAG_NHSYNC; + if (misc & ATOM_COMPOSITESYNC) + mode->flags |= DRM_MODE_FLAG_CSYNC; + if (misc & ATOM_INTERLACE) + mode->flags |= DRM_MODE_FLAG_INTERLACE; + if (misc & ATOM_DOUBLE_CLOCK_MODE) + mode->flags |= DRM_MODE_FLAG_DBLSCAN; + + mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10; + break; + } + return true; +} + +enum radeon_tv_std +radeon_atombios_get_tv_info(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); + uint16_t data_offset; + uint8_t frev, crev; + struct _ATOM_ANALOG_TV_INFO *tv_info; + enum radeon_tv_std tv_std = TV_STD_NTSC; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + + tv_info = (struct _ATOM_ANALOG_TV_INFO *) + ((char *)mode_info->atom_context->bios + data_offset); + + switch (tv_info->ucTV_BootUpDefaultStandard) { + case ATOM_TV_NTSC: + tv_std = TV_STD_NTSC; + DRM_DEBUG_KMS("Default TV standard: NTSC\n"); + break; + case ATOM_TV_NTSCJ: + tv_std = TV_STD_NTSC_J; + DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); + break; + case ATOM_TV_PAL: + tv_std = TV_STD_PAL; + DRM_DEBUG_KMS("Default TV standard: PAL\n"); + break; + case ATOM_TV_PALM: + tv_std = TV_STD_PAL_M; + DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); + break; + case ATOM_TV_PALN: + tv_std = TV_STD_PAL_N; + DRM_DEBUG_KMS("Default TV standard: PAL-N\n"); + break; + case ATOM_TV_PALCN: + tv_std = TV_STD_PAL_CN; + DRM_DEBUG_KMS("Default TV standard: PAL-CN\n"); + break; + case ATOM_TV_PAL60: + tv_std = TV_STD_PAL_60; + DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); + break; + case ATOM_TV_SECAM: + tv_std = TV_STD_SECAM; + DRM_DEBUG_KMS("Default TV standard: SECAM\n"); + break; + default: + tv_std = TV_STD_NTSC; + DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n"); + break; + } + } + return tv_std; +} + +struct radeon_encoder_tv_dac * +radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, CompassionateData); + uint16_t data_offset; + struct _COMPASSIONATE_DATA *dac_info; + uint8_t frev, crev; + uint8_t bg, dac; + struct radeon_encoder_tv_dac *tv_dac = NULL; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + + dac_info = (struct _COMPASSIONATE_DATA *) + ((char *)mode_info->atom_context->bios + data_offset); + + tv_dac = malloc(sizeof(struct radeon_encoder_tv_dac), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + if (!tv_dac) + return NULL; + + bg = dac_info->ucDAC2_CRT2_BG_Adjustment; + dac = dac_info->ucDAC2_CRT2_DAC_Adjustment; + tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); + + bg = dac_info->ucDAC2_PAL_BG_Adjustment; + dac = dac_info->ucDAC2_PAL_DAC_Adjustment; + tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); + + bg = dac_info->ucDAC2_NTSC_BG_Adjustment; + dac = dac_info->ucDAC2_NTSC_DAC_Adjustment; + tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + + tv_dac->tv_std = radeon_atombios_get_tv_info(rdev); + } + return tv_dac; +} + +static const char *thermal_controller_names[] = { + "NONE", + "lm63", + "adm1032", + "adm1030", + "max6649", + "lm64", + "f75375", + "asc7xxx", +}; + +static const char *pp_lib_thermal_controller_names[] = { + "NONE", + "lm63", + "adm1032", + "adm1030", + "max6649", + "lm64", + "f75375", + "RV6xx", + "RV770", + "adt7473", + "NONE", + "External GPIO", + "Evergreen", + "emc2103", + "Sumo", + "Northern Islands", + "Southern Islands", + "lm96163", +}; + +union power_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; +}; + +union pplib_clock_info { + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; + struct _ATOM_PPLIB_SI_CLOCK_INFO si; +}; + +union pplib_power_state { + struct _ATOM_PPLIB_STATE v1; + struct _ATOM_PPLIB_STATE_V2 v2; +}; + +static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev, + int state_index, + u32 misc, u32 misc2) +{ + rdev->pm.power_state[state_index].misc = misc; + rdev->pm.power_state[state_index].misc2 = misc2; + /* order matters! */ + if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_POWERSAVE; + if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BALANCED; + if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_PERFORMANCE; + rdev->pm.power_state[state_index].flags &= + ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + } + if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BALANCED; + if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[0]; + } else if (state_index == 0) { + rdev->pm.power_state[state_index].clock_info[0].flags |= + RADEON_PM_MODE_NO_DISPLAY; + } +} + +static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + u32 misc, misc2 = 0; + int num_modes = 0, i; + int state_index = 0; + struct radeon_i2c_bus_rec i2c_bus; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return state_index; + power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset); + + /* add the i2c bus for thermal/fan chip */ + if ((power_info->info.ucOverdriveThermalController > 0) && + (power_info->info.ucOverdriveThermalController < DRM_ARRAY_SIZE(thermal_controller_names))) { + DRM_INFO("Possible %s thermal controller at 0x%02x\n", + thermal_controller_names[power_info->info.ucOverdriveThermalController], + power_info->info.ucOverdriveControllerAddress >> 1); + i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); +#ifdef DUMBBELL_WIP + if (rdev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = thermal_controller_names[power_info->info. + ucOverdriveThermalController]; + info.addr = power_info->info.ucOverdriveControllerAddress >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); + } +#endif /* DUMBBELL_WIP */ + } + num_modes = power_info->info.ucNumOfPowerModeEntries; + if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) + num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; + rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * num_modes, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state) + return state_index; + /* last mode is usually default, array is low to high */ + for (i = 0; i < num_modes; i++) { + rdev->pm.power_state[state_index].clock_info = + malloc(sizeof(struct radeon_pm_clock_info) * 1, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state[state_index].clock_info) + return state_index; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + switch (frev) { + case 1: + rdev->pm.power_state[state_index].clock_info[0].mclk = + le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); + rdev->pm.power_state[state_index].clock_info[0].sclk = + le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + continue; + rdev->pm.power_state[state_index].pcie_lanes = + power_info->info.asPowerPlayInfo[i].ucNumPciELanes; + misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); + if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || + (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_GPIO; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = + radeon_lookup_gpio(rdev, + power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_VDDC; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = + power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; + } + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0); + state_index++; + break; + case 2: + rdev->pm.power_state[state_index].clock_info[0].mclk = + le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); + rdev->pm.power_state[state_index].clock_info[0].sclk = + le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + continue; + rdev->pm.power_state[state_index].pcie_lanes = + power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; + misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); + misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); + if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || + (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_GPIO; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = + radeon_lookup_gpio(rdev, + power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_VDDC; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = + power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; + } + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); + state_index++; + break; + case 3: + rdev->pm.power_state[state_index].clock_info[0].mclk = + le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); + rdev->pm.power_state[state_index].clock_info[0].sclk = + le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + continue; + rdev->pm.power_state[state_index].pcie_lanes = + power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; + misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); + misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); + if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || + (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_GPIO; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = + radeon_lookup_gpio(rdev, + power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_VDDC; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = + power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; + if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { + rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = + true; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = + power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; + } + } + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); + state_index++; + break; + } + } + /* last mode is usually default */ + if (rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[state_index - 1].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index - 1; + rdev->pm.power_state[state_index - 1].default_clock_mode = + &rdev->pm.power_state[state_index - 1].clock_info[0]; + rdev->pm.power_state[state_index].flags &= + ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + rdev->pm.power_state[state_index].misc = 0; + rdev->pm.power_state[state_index].misc2 = 0; + } + return state_index; +} + +static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev, + ATOM_PPLIB_THERMALCONTROLLER *controller) +{ + struct radeon_i2c_bus_rec i2c_bus; + + /* add the i2c bus for thermal/fan chip */ + if (controller->ucType > 0) { + if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_NI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_SI; + } else if ((controller->ucType == + ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || + (controller->ucType == + ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || + (controller->ucType == + ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { + DRM_INFO("Special thermal controller config\n"); + } else if (controller->ucType < DRM_ARRAY_SIZE(pp_lib_thermal_controller_names)) { + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", + pp_lib_thermal_controller_names[controller->ucType], + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); +#ifdef DUMBBELL_WIP + if (rdev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = pp_lib_thermal_controller_names[controller->ucType]; + info.addr = controller->ucI2cAddress >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); + } +#endif /* DUMBBELL_WIP */ + } else { + DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", + controller->ucType, + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + } + } +} + +static void radeon_atombios_get_default_voltages(struct radeon_device *rdev, + u16 *vddc, u16 *vddci) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + u8 frev, crev; + u16 data_offset; + union firmware_info *firmware_info; + + *vddc = 0; + *vddci = 0; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + firmware_info = + (union firmware_info *)((char *)mode_info->atom_context->bios + + data_offset); + *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); + if ((frev == 2) && (crev >= 2)) + *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); + } +} + +static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, + int state_index, int mode_index, + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info) +{ + int j; + u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); + u32 misc2 = le16_to_cpu(non_clock_info->usClassification); + u16 vddc, vddci; + + radeon_atombios_get_default_voltages(rdev, &vddc, &vddci); + + rdev->pm.power_state[state_index].misc = misc; + rdev->pm.power_state[state_index].misc2 = misc2; + rdev->pm.power_state[state_index].pcie_lanes = + ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> + ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BALANCED; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_PERFORMANCE; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: + if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_PERFORMANCE; + break; + } + rdev->pm.power_state[state_index].flags = 0; + if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) + rdev->pm.power_state[state_index].flags |= + RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; + if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) { + /* NI chips post without MC ucode, so default clocks are strobe mode only */ + rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; + rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; + rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; + rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; + } else { + /* patch the table values with the default slck/mclk from firmware info */ + for (j = 0; j < mode_index; j++) { + rdev->pm.power_state[state_index].clock_info[j].mclk = + rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[j].sclk = + rdev->clock.default_sclk; + if (vddc) + rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = + vddc; + } + } + } +} + +static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + int state_index, int mode_index, + union pplib_clock_info *clock_info) +{ + u32 sclk, mclk; + u16 vddc; + + if (rdev->flags & RADEON_IS_IGP) { + if (rdev->family >= CHIP_PALM) { + sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); + sclk |= clock_info->sumo.ucEngineClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + } else { + sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); + sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + } + } else if (ASIC_IS_DCE6(rdev)) { + sclk = le16_to_cpu(clock_info->si.usEngineClockLow); + sclk |= clock_info->si.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); + mclk |= clock_info->si.ucMemoryClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = + VOLTAGE_SW; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = + le16_to_cpu(clock_info->si.usVDDC); + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = + le16_to_cpu(clock_info->si.usVDDCI); + } else if (ASIC_IS_DCE4(rdev)) { + sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); + sclk |= clock_info->evergreen.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); + mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = + VOLTAGE_SW; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = + le16_to_cpu(clock_info->evergreen.usVDDC); + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = + le16_to_cpu(clock_info->evergreen.usVDDCI); + } else { + sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); + sclk |= clock_info->r600.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow); + mclk |= clock_info->r600.ucMemoryClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = + VOLTAGE_SW; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = + le16_to_cpu(clock_info->r600.usVDDC); + } + + /* patch up vddc if necessary */ + switch (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage) { + case ATOM_VIRTUAL_VOLTAGE_ID0: + case ATOM_VIRTUAL_VOLTAGE_ID1: + case ATOM_VIRTUAL_VOLTAGE_ID2: + case ATOM_VIRTUAL_VOLTAGE_ID3: + if (radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC, + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage, + &vddc) == 0) + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; + break; + default: + break; + } + + if (rdev->flags & RADEON_IS_IGP) { + /* skip invalid modes */ + if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) + return false; + } else { + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) + return false; + } + return true; +} + +static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j; + int state_index = 0, mode_index = 0; + union pplib_clock_info *clock_info; + bool valid; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return state_index; + power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset); + + radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); + rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * + power_info->pplib.ucNumStates, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state) + return state_index; + /* first mode is usually default, followed by low to high */ + for (i = 0; i < power_info->pplib.ucNumStates; i++) { + mode_index = 0; + power_state = (union pplib_power_state *) + ((char *)mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset) + + i * power_info->pplib.ucStateEntrySize); + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + ((char *)mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + + (power_state->v1.ucNonClockStateIndex * + power_info->pplib.ucNonClockSize)); + rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) * + ((power_info->pplib.ucStateEntrySize - 1) ? + (power_info->pplib.ucStateEntrySize - 1) : 1), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state[i].clock_info) + return state_index; + if (power_info->pplib.ucStateEntrySize - 1) { + for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { + clock_info = (union pplib_clock_info *) + ((char *)mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + + (power_state->v1.ucClockStateIndices[j] * + power_info->pplib.ucClockInfoSize)); + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); + if (valid) + mode_index++; + } + } else { + rdev->pm.power_state[state_index].clock_info[0].mclk = + rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = + rdev->clock.default_sclk; + mode_index++; + } + rdev->pm.power_state[state_index].num_clock_modes = mode_index; + if (mode_index) { + radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, + non_clock_info); + state_index++; + } + } + /* if multiple clock modes, mark the lowest as no display */ + for (i = 0; i < state_index; i++) { + if (rdev->pm.power_state[i].num_clock_modes > 1) + rdev->pm.power_state[i].clock_info[0].flags |= + RADEON_PM_MODE_NO_DISPLAY; + } + /* first mode is usually default */ + if (rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[0].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = 0; + rdev->pm.power_state[0].default_clock_mode = + &rdev->pm.power_state[0].clock_info[0]; + } + return state_index; +} + +static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j, non_clock_array_index, clock_array_index; + int state_index = 0, mode_index = 0; + union pplib_clock_info *clock_info; + struct _StateArray *state_array; + struct _ClockInfoArray *clock_info_array; + struct _NonClockInfoArray *non_clock_info_array; + bool valid; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return state_index; + power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset); + + radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); + state_array = (struct _StateArray *) + ((char *)mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset)); + clock_info_array = (struct _ClockInfoArray *) + ((char *)mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); + non_clock_info_array = (struct _NonClockInfoArray *) + ((char *)mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); + rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * + state_array->ucNumEntries, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state) + return state_index; + for (i = 0; i < state_array->ucNumEntries; i++) { + mode_index = 0; + power_state = (union pplib_power_state *)&state_array->states[i]; + /* XXX this might be an inagua bug... */ + non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + &non_clock_info_array->nonClockInfo[non_clock_array_index]; + rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) * + (power_state->v2.ucNumDPMLevels ? + power_state->v2.ucNumDPMLevels : 1), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state[i].clock_info) + return state_index; + if (power_state->v2.ucNumDPMLevels) { + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = power_state->v2.clockInfoIndex[j]; + /* XXX this might be an inagua bug... */ + if (clock_array_index >= clock_info_array->ucNumEntries) + continue; + clock_info = (union pplib_clock_info *) + &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); + if (valid) + mode_index++; + } + } else { + rdev->pm.power_state[state_index].clock_info[0].mclk = + rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = + rdev->clock.default_sclk; + mode_index++; + } + rdev->pm.power_state[state_index].num_clock_modes = mode_index; + if (mode_index) { + radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, + non_clock_info); + state_index++; + } + } + /* if multiple clock modes, mark the lowest as no display */ + for (i = 0; i < state_index; i++) { + if (rdev->pm.power_state[i].num_clock_modes > 1) + rdev->pm.power_state[i].clock_info[0].flags |= + RADEON_PM_MODE_NO_DISPLAY; + } + /* first mode is usually default */ + if (rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[0].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = 0; + rdev->pm.power_state[0].default_clock_mode = + &rdev->pm.power_state[0].clock_info[0]; + } + return state_index; +} + +void radeon_atombios_get_power_modes(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + int state_index = 0; + + rdev->pm.default_power_state_index = -1; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + switch (frev) { + case 1: + case 2: + case 3: + state_index = radeon_atombios_parse_power_table_1_3(rdev); + break; + case 4: + case 5: + state_index = radeon_atombios_parse_power_table_4_5(rdev); + break; + case 6: + state_index = radeon_atombios_parse_power_table_6(rdev); + break; + default: + break; + } + } else { + rdev->pm.power_state = malloc(sizeof(struct radeon_power_state), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->pm.power_state) { + rdev->pm.power_state[0].clock_info = + malloc(sizeof(struct radeon_pm_clock_info) * 1, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->pm.power_state[0].clock_info) { + /* add the default mode */ + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[0]; + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + rdev->pm.power_state[state_index].pcie_lanes = 16; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].flags = 0; + state_index++; + } + } + } + + rdev->pm.num_power_states = state_index; + + rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.current_clock_mode_index = 0; + if (rdev->pm.default_power_state_index >= 0) + rdev->pm.current_vddc = + rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; + else + rdev->pm.current_vddc = 0; +} + +void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) +{ + DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); + + args.ucEnable = enable; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev) +{ + GET_ENGINE_CLOCK_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock); + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + return le32_to_cpu(args.ulReturnEngineClock); +} + +uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev) +{ + GET_MEMORY_CLOCK_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock); + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + return le32_to_cpu(args.ulReturnMemoryClock); +} + +void radeon_atom_set_engine_clock(struct radeon_device *rdev, + uint32_t eng_clock) +{ + SET_ENGINE_CLOCK_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock); + + args.ulTargetEngineClock = cpu_to_le32(eng_clock); /* 10 khz */ + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +void radeon_atom_set_memory_clock(struct radeon_device *rdev, + uint32_t mem_clock) +{ + SET_MEMORY_CLOCK_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock); + + if (rdev->flags & RADEON_IS_IGP) + return; + + args.ulTargetMemoryClock = cpu_to_le32(mem_clock); /* 10 khz */ + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +union set_voltage { + struct _SET_VOLTAGE_PS_ALLOCATION alloc; + struct _SET_VOLTAGE_PARAMETERS v1; + struct _SET_VOLTAGE_PARAMETERS_V2 v2; + struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; +}; + +void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type) +{ + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); + u8 frev, crev, volt_index = voltage_level; + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage_level == 0xff01) + return; + + switch (crev) { + case 1: + args.v1.ucVoltageType = voltage_type; + args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE; + args.v1.ucVoltageIndex = volt_index; + break; + case 2: + args.v2.ucVoltageType = voltage_type; + args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; + args.v2.usVoltageLevel = cpu_to_le16(voltage_level); + break; + case 3: + args.v3.ucVoltageType = voltage_type; + args.v3.ucVoltageMode = ATOM_SET_VOLTAGE; + args.v3.usVoltageLevel = cpu_to_le16(voltage_level); + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return; + } + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + +static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, + u16 voltage_id, u16 *voltage) +{ + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); + u8 frev, crev; + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return -EINVAL; + + switch (crev) { + case 1: + return -EINVAL; + case 2: + args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; + args.v2.ucVoltageMode = 0; + args.v2.usVoltageLevel = 0; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + *voltage = le16_to_cpu(args.v2.usVoltageLevel); + break; + case 3: + args.v3.ucVoltageType = voltage_type; + args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; + args.v3.usVoltageLevel = cpu_to_le16(voltage_id); + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + *voltage = le16_to_cpu(args.v3.usVoltageLevel); + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return -EINVAL; + } + + return 0; +} + +void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t bios_2_scratch, bios_6_scratch; + + if (rdev->family >= CHIP_R600) { + bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); + bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); + } else { + bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); + bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); + } + + /* let the bios control the backlight */ + bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE; + + /* tell the bios not to handle mode switching */ + bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; + + if (rdev->family >= CHIP_R600) { + WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); + WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); + } else { + WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); + WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); + } + +} + +void radeon_save_bios_scratch_regs(struct radeon_device *rdev) +{ + uint32_t scratch_reg; + int i; + + if (rdev->family >= CHIP_R600) + scratch_reg = R600_BIOS_0_SCRATCH; + else + scratch_reg = RADEON_BIOS_0_SCRATCH; + + for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) + rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4)); +} + +void radeon_restore_bios_scratch_regs(struct radeon_device *rdev) +{ + uint32_t scratch_reg; + int i; + + if (rdev->family >= CHIP_R600) + scratch_reg = R600_BIOS_0_SCRATCH; + else + scratch_reg = RADEON_BIOS_0_SCRATCH; + + for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) + WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]); +} + +void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t bios_6_scratch; + + if (rdev->family >= CHIP_R600) + bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); + else + bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); + + if (lock) { + bios_6_scratch |= ATOM_S6_CRITICAL_STATE; + bios_6_scratch &= ~ATOM_S6_ACC_MODE; + } else { + bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE; + bios_6_scratch |= ATOM_S6_ACC_MODE; + } + + if (rdev->family >= CHIP_R600) + WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); + else + WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); +} + +/* at some point we may want to break this out into individual functions */ +void +radeon_atombios_connected_scratch_regs(struct drm_connector *connector, + struct drm_encoder *encoder, + bool connected) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = + to_radeon_connector(connector); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch; + + if (rdev->family >= CHIP_R600) { + bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); + bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); + bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); + } else { + bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); + bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH); + bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); + } + + if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("TV1 connected\n"); + bios_3_scratch |= ATOM_S3_TV1_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_TV1; + } else { + DRM_DEBUG_KMS("TV1 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_TV1_MASK; + bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("CV connected\n"); + bios_3_scratch |= ATOM_S3_CV_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_CV; + } else { + DRM_DEBUG_KMS("CV disconnected\n"); + bios_0_scratch &= ~ATOM_S0_CV_MASK; + bios_3_scratch &= ~ATOM_S3_CV_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("LCD1 connected\n"); + bios_0_scratch |= ATOM_S0_LCD1; + bios_3_scratch |= ATOM_S3_LCD1_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1; + } else { + DRM_DEBUG_KMS("LCD1 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_LCD1; + bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("CRT1 connected\n"); + bios_0_scratch |= ATOM_S0_CRT1_COLOR; + bios_3_scratch |= ATOM_S3_CRT1_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1; + } else { + DRM_DEBUG_KMS("CRT1 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_CRT1_MASK; + bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("CRT2 connected\n"); + bios_0_scratch |= ATOM_S0_CRT2_COLOR; + bios_3_scratch |= ATOM_S3_CRT2_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2; + } else { + DRM_DEBUG_KMS("CRT2 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_CRT2_MASK; + bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP1 connected\n"); + bios_0_scratch |= ATOM_S0_DFP1; + bios_3_scratch |= ATOM_S3_DFP1_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1; + } else { + DRM_DEBUG_KMS("DFP1 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_DFP1; + bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP2 connected\n"); + bios_0_scratch |= ATOM_S0_DFP2; + bios_3_scratch |= ATOM_S3_DFP2_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2; + } else { + DRM_DEBUG_KMS("DFP2 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_DFP2; + bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP3 connected\n"); + bios_0_scratch |= ATOM_S0_DFP3; + bios_3_scratch |= ATOM_S3_DFP3_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3; + } else { + DRM_DEBUG_KMS("DFP3 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_DFP3; + bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP4 connected\n"); + bios_0_scratch |= ATOM_S0_DFP4; + bios_3_scratch |= ATOM_S3_DFP4_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4; + } else { + DRM_DEBUG_KMS("DFP4 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_DFP4; + bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP5 connected\n"); + bios_0_scratch |= ATOM_S0_DFP5; + bios_3_scratch |= ATOM_S3_DFP5_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5; + } else { + DRM_DEBUG_KMS("DFP5 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_DFP5; + bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP6 connected\n"); + bios_0_scratch |= ATOM_S0_DFP6; + bios_3_scratch |= ATOM_S3_DFP6_ACTIVE; + bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6; + } else { + DRM_DEBUG_KMS("DFP6 disconnected\n"); + bios_0_scratch &= ~ATOM_S0_DFP6; + bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE; + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6; + } + } + + if (rdev->family >= CHIP_R600) { + WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch); + WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch); + WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); + } else { + WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch); + WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch); + WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); + } +} + +void +radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_3_scratch; + + if (ASIC_IS_DCE4(rdev)) + return; + + if (rdev->family >= CHIP_R600) + bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); + else + bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH); + + if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 18); + } + if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 24); + } + if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 16); + } + if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 20); + } + if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 17); + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 19); + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 23); + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) { + bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE; + bios_3_scratch |= (crtc << 25); + } + + if (rdev->family >= CHIP_R600) + WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch); + else + WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch); +} + +void +radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_2_scratch; + + if (ASIC_IS_DCE4(rdev)) + return; + + if (rdev->family >= CHIP_R600) + bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); + else + bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); + + if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_CV_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE; + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) { + if (on) + bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE; + else + bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE; + } + + if (rdev->family >= CHIP_R600) + WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); + else + WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); +} diff --git a/sys/dev/drm2/radeon/radeon_atpx_handler.c b/sys/dev/drm2/radeon/radeon_atpx_handler.c new file mode 100644 index 00000000000..4cfd7434cde --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_atpx_handler.c @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2010 Red Hat Inc. + * Author : Dave Airlie + * + * Licensed under GPLv2 + * + * ATPX support for both Intel/ATI + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "radeon_acpi.h" +#include "radeon_drv.h" + +#ifdef DUMBBELL_WIP +struct radeon_atpx_functions { + bool px_params; + bool power_cntl; + bool disp_mux_cntl; + bool i2c_mux_cntl; + bool switch_start; + bool switch_end; + bool disp_connectors_mapping; + bool disp_detetion_ports; +}; + +struct radeon_atpx { + ACPI_HANDLE handle; + struct radeon_atpx_functions functions; +}; + +static struct radeon_atpx_priv { + bool atpx_detected; + /* handle for device - and atpx */ + ACPI_HANDLE dhandle; + struct radeon_atpx atpx; +} radeon_atpx_priv; + +struct atpx_verify_interface { + u16 size; /* structure size in bytes (includes size field) */ + u16 version; /* version */ + u32 function_bits; /* supported functions bit vector */ +} __packed; + +struct atpx_power_control { + u16 size; + u8 dgpu_state; +} __packed; + +struct atpx_mux { + u16 size; + u16 mux; +} __packed; + +/** + * radeon_atpx_call - call an ATPX method + * + * @handle: acpi handle + * @function: the ATPX function to execute + * @params: ATPX function params + * + * Executes the requested ATPX function (all asics). + * Returns a pointer to the acpi output buffer. + */ +static ACPI_OBJECT *radeon_atpx_call(ACPI_HANDLE handle, int function, + ACPI_BUFFER *params) +{ + ACPI_STATUS status; + ACPI_OBJECT atpx_arg_elements[2]; + ACPI_OBJECT_LIST atpx_arg; + ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + atpx_arg.Count = 2; + atpx_arg.Pointer = &atpx_arg_elements[0]; + + atpx_arg_elements[0].Type = ACPI_TYPE_INTEGER; + atpx_arg_elements[0].Integer.Value = function; + + if (params) { + atpx_arg_elements[1].Type = ACPI_TYPE_BUFFER; + atpx_arg_elements[1].Buffer.Length = params->Length; + atpx_arg_elements[1].Buffer.Pointer = params->Pointer; + } else { + /* We need a second fake parameter */ + atpx_arg_elements[1].Type = ACPI_TYPE_INTEGER; + atpx_arg_elements[1].Integer.Value = 0; + } + + status = AcpiEvaluateObject(handle, NULL, &atpx_arg, &buffer); + + /* Fail only if calling the method fails and ATPX is supported */ + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + DRM_ERROR("failed to evaluate ATPX got %s\n", + AcpiFormatException(status)); + AcpiOsFree(buffer.Pointer); + return NULL; + } + + return buffer.Pointer; +} + +/** + * radeon_atpx_parse_functions - parse supported functions + * + * @f: supported functions struct + * @mask: supported functions mask from ATPX + * + * Use the supported functions mask from ATPX function + * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions + * are supported (all asics). + */ +static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask) +{ + f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED; + f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED; + f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED; + f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED; + f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED; + f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED; + f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED; + f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED; +} + +/** + * radeon_atpx_verify_interface - verify ATPX + * + * @handle: acpi handle + * @atpx: radeon atpx struct + * + * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function + * to initialize ATPX and determine what features are supported + * (all asics). + * returns 0 on success, error on failure. + */ +static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) +{ + ACPI_OBJECT *info; + struct atpx_verify_interface output; + size_t size; + int err = 0; + + info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL); + if (!info) + return -EIO; + + memset(&output, 0, sizeof(output)); + + size = *(u16 *) info->Buffer.Pointer; + if (size < 8) { + DRM_ERROR("ATPX buffer is too small: %zu\n", size); + err = -EINVAL; + goto out; + } + size = min(sizeof(output), size); + + memcpy(&output, info->Buffer.Pointer, size); + + /* TODO: check version? */ + DRM_INFO("ATPX version %u\n", output.version); + + radeon_atpx_parse_functions(&atpx->functions, output.function_bits); + +out: + AcpiOsFree(info); + return err; +} + +/** + * radeon_atpx_set_discrete_state - power up/down discrete GPU + * + * @atpx: atpx info struct + * @state: discrete GPU state (0 = power down, 1 = power up) + * + * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to + * power down/up the discrete GPU (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state) +{ + ACPI_BUFFER params; + ACPI_OBJECT *info; + struct atpx_power_control input; + + if (atpx->functions.power_cntl) { + input.size = 3; + input.dgpu_state = state; + params.Length = input.size; + params.Pointer = &input; + info = radeon_atpx_call(atpx->handle, + ATPX_FUNCTION_POWER_CONTROL, + ¶ms); + if (!info) + return -EIO; + AcpiOsFree(info); + } + return 0; +} + +/** + * radeon_atpx_switch_disp_mux - switch display mux + * + * @atpx: atpx info struct + * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) + * + * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to + * switch the display mux between the discrete GPU and integrated GPU + * (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id) +{ + ACPI_BUFFER params; + ACPI_OBJECT *info; + struct atpx_mux input; + + if (atpx->functions.disp_mux_cntl) { + input.size = 4; + input.mux = mux_id; + params.Length = input.size; + params.Pointer = &input; + info = radeon_atpx_call(atpx->handle, + ATPX_FUNCTION_DISPLAY_MUX_CONTROL, + ¶ms); + if (!info) + return -EIO; + AcpiOsFree(info); + } + return 0; +} + +/** + * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux + * + * @atpx: atpx info struct + * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) + * + * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to + * switch the i2c/hpd mux between the discrete GPU and integrated GPU + * (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id) +{ + ACPI_BUFFER params; + ACPI_OBJECT *info; + struct atpx_mux input; + + if (atpx->functions.i2c_mux_cntl) { + input.size = 4; + input.mux = mux_id; + params.Length = input.size; + params.Pointer = &input; + info = radeon_atpx_call(atpx->handle, + ATPX_FUNCTION_I2C_MUX_CONTROL, + ¶ms); + if (!info) + return -EIO; + AcpiOsFree(info); + } + return 0; +} + +/** + * radeon_atpx_switch_start - notify the sbios of a GPU switch + * + * @atpx: atpx info struct + * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) + * + * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX + * function to notify the sbios that a switch between the discrete GPU and + * integrated GPU has begun (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id) +{ + ACPI_BUFFER params; + ACPI_OBJECT *info; + struct atpx_mux input; + + if (atpx->functions.switch_start) { + input.size = 4; + input.mux = mux_id; + params.Length = input.size; + params.Pointer = &input; + info = radeon_atpx_call(atpx->handle, + ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION, + ¶ms); + if (!info) + return -EIO; + AcpiOsFree(info); + } + return 0; +} + +/** + * radeon_atpx_switch_end - notify the sbios of a GPU switch + * + * @atpx: atpx info struct + * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) + * + * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX + * function to notify the sbios that a switch between the discrete GPU and + * integrated GPU has ended (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id) +{ + ACPI_BUFFER params; + ACPI_OBJECT *info; + struct atpx_mux input; + + if (atpx->functions.switch_end) { + input.size = 4; + input.mux = mux_id; + params.Length = input.size; + params.Pointer = &input; + info = radeon_atpx_call(atpx->handle, + ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION, + ¶ms); + if (!info) + return -EIO; + AcpiOsFree(info); + } + return 0; +} + +/** + * radeon_atpx_switchto - switch to the requested GPU + * + * @id: GPU to switch to + * + * Execute the necessary ATPX functions to switch between the discrete GPU and + * integrated GPU (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) +{ + u16 gpu_id; + + if (id == VGA_SWITCHEROO_IGD) + gpu_id = ATPX_INTEGRATED_GPU; + else + gpu_id = ATPX_DISCRETE_GPU; + + radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id); + radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id); + radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id); + radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id); + + return 0; +} + +/** + * radeon_atpx_power_state - power down/up the requested GPU + * + * @id: GPU to power down/up + * @state: requested power state (0 = off, 1 = on) + * + * Execute the necessary ATPX function to power down/up the discrete GPU + * (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, + enum vga_switcheroo_state state) +{ + /* on w500 ACPI can't change intel gpu state */ + if (id == VGA_SWITCHEROO_IGD) + return 0; + + radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state); + return 0; +} + +/** + * radeon_atpx_pci_probe_handle - look up the ATPX handle + * + * @pdev: pci device + * + * Look up the ATPX handles (all asics). + * Returns true if the handles are found, false if not. + */ +static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) +{ + ACPI_HANDLE dhandle, atpx_handle; + ACPI_STATUS status; + + dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); + if (!dhandle) + return false; + + status = AcpiGetHandle(dhandle, "ATPX", &atpx_handle); + if (ACPI_FAILURE(status)) + return false; + + radeon_atpx_priv.dhandle = dhandle; + radeon_atpx_priv.atpx.handle = atpx_handle; + return true; +} + +/** + * radeon_atpx_init - verify the ATPX interface + * + * Verify the ATPX interface (all asics). + * Returns 0 on success, error on failure. + */ +static int radeon_atpx_init(void) +{ + /* set up the ATPX handle */ + return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); +} + +/** + * radeon_atpx_get_client_id - get the client id + * + * @pdev: pci device + * + * look up whether we are the integrated or discrete GPU (all asics). + * Returns the client id. + */ +static int radeon_atpx_get_client_id(struct pci_dev *pdev) +{ + if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) + return VGA_SWITCHEROO_IGD; + else + return VGA_SWITCHEROO_DIS; +} + +static struct vga_switcheroo_handler radeon_atpx_handler = { + .switchto = radeon_atpx_switchto, + .power_state = radeon_atpx_power_state, + .init = radeon_atpx_init, + .get_client_id = radeon_atpx_get_client_id, +}; + +/** + * radeon_atpx_detect - detect whether we have PX + * + * Check if we have a PX system (all asics). + * Returns true if we have a PX system, false if not. + */ +static bool radeon_atpx_detect(void) +{ + char acpi_method_name[255] = { 0 }; + ACPI_BUFFER buffer = {sizeof(acpi_method_name), acpi_method_name}; + struct pci_dev *pdev = NULL; + bool has_atpx = false; + int vga_count = 0; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + vga_count++; + + has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); + } + + if (has_atpx && vga_count == 2) { + AcpiGetName(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); + DRM_INFO("VGA switcheroo: detected switching method %s handle\n", + acpi_method_name); + radeon_atpx_priv.atpx_detected = true; + return true; + } + return false; +} +#endif /* DUMBBELL_WIP */ + +/** + * radeon_register_atpx_handler - register with vga_switcheroo + * + * Register the PX callbacks with vga_switcheroo (all asics). + */ +void radeon_register_atpx_handler(void) +{ +#ifdef DUMBBELL_WIP + bool r; + + /* detect if we have any ATPX + 2 VGA in the system */ + r = radeon_atpx_detect(); + if (!r) + return; + + vga_switcheroo_register_handler(&radeon_atpx_handler); +#endif /* DUMBBELL_WIP */ +} + +/** + * radeon_unregister_atpx_handler - unregister with vga_switcheroo + * + * Unregister the PX callbacks with vga_switcheroo (all asics). + */ +void radeon_unregister_atpx_handler(void) +{ +#ifdef DUMBBELL_WIP + vga_switcheroo_unregister_handler(); +#endif /* DUMBBELL_WIP */ +} diff --git a/sys/dev/drm2/radeon/radeon_benchmark.c b/sys/dev/drm2/radeon/radeon_benchmark.c new file mode 100644 index 00000000000..ce39748ecff --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_benchmark.c @@ -0,0 +1,255 @@ +/* + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" + +#define RADEON_BENCHMARK_COPY_BLIT 1 +#define RADEON_BENCHMARK_COPY_DMA 0 + +#define RADEON_BENCHMARK_ITERATIONS 1024 +#define RADEON_BENCHMARK_COMMON_MODES_N 17 + +static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, + uint64_t saddr, uint64_t daddr, + int flag, int n) +{ + unsigned long start_jiffies; + unsigned long end_jiffies; + struct radeon_fence *fence = NULL; + int i, r; + + start_jiffies = jiffies; + for (i = 0; i < n; i++) { + switch (flag) { + case RADEON_BENCHMARK_COPY_DMA: + r = radeon_copy_dma(rdev, saddr, daddr, + size / RADEON_GPU_PAGE_SIZE, + &fence); + break; + case RADEON_BENCHMARK_COPY_BLIT: + r = radeon_copy_blit(rdev, saddr, daddr, + size / RADEON_GPU_PAGE_SIZE, + &fence); + break; + default: + DRM_ERROR("Unknown copy method\n"); + r = -EINVAL; + } + if (r) + goto exit_do_move; + r = radeon_fence_wait(fence, false); + if (r) + goto exit_do_move; + radeon_fence_unref(&fence); + } + end_jiffies = jiffies; + r = jiffies_to_msecs(end_jiffies - start_jiffies); + +exit_do_move: + if (fence) + radeon_fence_unref(&fence); + return r; +} + + +static void radeon_benchmark_log_results(int n, unsigned size, + unsigned int time, + unsigned sdomain, unsigned ddomain, + char *kind) +{ + unsigned int throughput = (n * (size >> 10)) / time; + DRM_INFO("radeon: %s %u bo moves of %u kB from" + " %d to %d in %u ms, throughput: %u Mb/s or %u MB/s\n", + kind, n, size >> 10, sdomain, ddomain, time, + throughput * 8, throughput); +} + +static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, + unsigned sdomain, unsigned ddomain) +{ + struct radeon_bo *dobj = NULL; + struct radeon_bo *sobj = NULL; + uint64_t saddr, daddr; + int r, n; + int time; + + n = RADEON_BENCHMARK_ITERATIONS; + r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, NULL, &sobj); + if (r) { + goto out_cleanup; + } + r = radeon_bo_reserve(sobj, false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(sobj, sdomain, &saddr); + radeon_bo_unreserve(sobj); + if (r) { + goto out_cleanup; + } + r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, NULL, &dobj); + if (r) { + goto out_cleanup; + } + r = radeon_bo_reserve(dobj, false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(dobj, ddomain, &daddr); + radeon_bo_unreserve(dobj); + if (r) { + goto out_cleanup; + } + + /* r100 doesn't have dma engine so skip the test */ + /* also, VRAM-to-VRAM test doesn't make much sense for DMA */ + /* skip it as well if domains are the same */ + if ((rdev->asic->copy.dma) && (sdomain != ddomain)) { + time = radeon_benchmark_do_move(rdev, size, saddr, daddr, + RADEON_BENCHMARK_COPY_DMA, n); + if (time < 0) + goto out_cleanup; + if (time > 0) + radeon_benchmark_log_results(n, size, time, + sdomain, ddomain, "dma"); + } + + time = radeon_benchmark_do_move(rdev, size, saddr, daddr, + RADEON_BENCHMARK_COPY_BLIT, n); + if (time < 0) + goto out_cleanup; + if (time > 0) + radeon_benchmark_log_results(n, size, time, + sdomain, ddomain, "blit"); + +out_cleanup: + if (sobj) { + r = radeon_bo_reserve(sobj, false); + if (likely(r == 0)) { + radeon_bo_unpin(sobj); + radeon_bo_unreserve(sobj); + } + radeon_bo_unref(&sobj); + } + if (dobj) { + r = radeon_bo_reserve(dobj, false); + if (likely(r == 0)) { + radeon_bo_unpin(dobj); + radeon_bo_unreserve(dobj); + } + radeon_bo_unref(&dobj); + } + + if (r) { + DRM_ERROR("Error while benchmarking BO move.\n"); + } +} + +void radeon_benchmark(struct radeon_device *rdev, int test_number) +{ + int i; + int common_modes[RADEON_BENCHMARK_COMMON_MODES_N] = { + 640 * 480 * 4, + 720 * 480 * 4, + 800 * 600 * 4, + 848 * 480 * 4, + 1024 * 768 * 4, + 1152 * 768 * 4, + 1280 * 720 * 4, + 1280 * 800 * 4, + 1280 * 854 * 4, + 1280 * 960 * 4, + 1280 * 1024 * 4, + 1440 * 900 * 4, + 1400 * 1050 * 4, + 1680 * 1050 * 4, + 1600 * 1200 * 4, + 1920 * 1080 * 4, + 1920 * 1200 * 4 + }; + + switch (test_number) { + case 1: + /* simple test, VRAM to GTT and GTT to VRAM */ + radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT, + RADEON_GEM_DOMAIN_VRAM); + radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_GTT); + break; + case 2: + /* simple test, VRAM to VRAM */ + radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_VRAM); + break; + case 3: + /* GTT to VRAM, buffer size sweep, powers of 2 */ + for (i = 1; i <= 16384; i <<= 1) + radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE, + RADEON_GEM_DOMAIN_GTT, + RADEON_GEM_DOMAIN_VRAM); + break; + case 4: + /* VRAM to GTT, buffer size sweep, powers of 2 */ + for (i = 1; i <= 16384; i <<= 1) + radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE, + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_GTT); + break; + case 5: + /* VRAM to VRAM, buffer size sweep, powers of 2 */ + for (i = 1; i <= 16384; i <<= 1) + radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE, + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_VRAM); + break; + case 6: + /* GTT to VRAM, buffer size sweep, common modes */ + for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) + radeon_benchmark_move(rdev, common_modes[i], + RADEON_GEM_DOMAIN_GTT, + RADEON_GEM_DOMAIN_VRAM); + break; + case 7: + /* VRAM to GTT, buffer size sweep, common modes */ + for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) + radeon_benchmark_move(rdev, common_modes[i], + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_GTT); + break; + case 8: + /* VRAM to VRAM, buffer size sweep, common modes */ + for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) + radeon_benchmark_move(rdev, common_modes[i], + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_VRAM); + break; + + default: + DRM_ERROR("Unknown benchmark\n"); + } +} diff --git a/sys/dev/drm2/radeon/radeon_bios.c b/sys/dev/drm2/radeon/radeon_bios.c new file mode 100644 index 00000000000..b9ee4d166fa --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_bios.c @@ -0,0 +1,728 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "atom.h" + +/* + * BIOS. + */ + +/* If you boot an IGP board with a discrete card as the primary, + * the IGP rom is not accessible via the rom bar as the IGP rom is + * part of the system bios. On boot, the system bios puts a + * copy of the igp rom at the start of vram if a discrete card is + * present. + */ +static bool igp_read_bios_from_vram(struct radeon_device *rdev) +{ + drm_local_map_t bios_map; + uint8_t __iomem *bios; + resource_size_t vram_base; + resource_size_t size = 256 * 1024; /* ??? */ + + DRM_INFO("%s: ===> Try IGP's VRAM...\n", __func__); + + if (!(rdev->flags & RADEON_IS_IGP)) + if (!radeon_card_posted(rdev)) { + DRM_INFO("%s: not POSTed discrete card detected, skipping this method...\n", + __func__); + return false; + } + + rdev->bios = NULL; + vram_base = drm_get_resource_start(rdev->ddev, 0); + DRM_INFO("%s: VRAM base address: 0x%jx\n", __func__, (uintmax_t)vram_base); + + bios_map.offset = vram_base; + bios_map.size = size; + bios_map.type = 0; + bios_map.flags = 0; + bios_map.mtrr = 0; + drm_core_ioremap(&bios_map, rdev->ddev); + if (bios_map.virtual == NULL) { + DRM_INFO("%s: failed to ioremap\n", __func__); + return false; + } + bios = bios_map.virtual; + size = bios_map.size; + DRM_INFO("%s: Map address: %p (%ju bytes)\n", __func__, bios, (uintmax_t)size); + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + if (size == 0) { + DRM_INFO("%s: Incorrect BIOS size\n", __func__); + } else { + DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", + __func__, bios[0], bios[1]); + } + drm_core_ioremapfree(&bios_map, rdev->ddev); + return false; + } + rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); + if (rdev->bios == NULL) { + drm_core_ioremapfree(&bios_map, rdev->ddev); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + drm_core_ioremapfree(&bios_map, rdev->ddev); + return true; +} + +static bool radeon_read_bios(struct radeon_device *rdev) +{ + uint8_t __iomem *bios; + size_t size; + + DRM_INFO("%s: ===> Try PCI Expansion ROM...\n", __func__); + + rdev->bios = NULL; + /* XXX: some cards may return 0 for rom size? ddx has a workaround */ + bios = vga_pci_map_bios(rdev->dev, &size); + if (!bios) { + return false; + } + DRM_INFO("%s: Map address: %p (%zu bytes)\n", __func__, bios, size); + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + if (size == 0) { + DRM_INFO("%s: Incorrect BIOS size\n", __func__); + } else { + DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", + __func__, bios[0], bios[1]); + } + vga_pci_unmap_bios(rdev->dev, bios); + } + rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); + memcpy(rdev->bios, bios, size); + vga_pci_unmap_bios(rdev->dev, bios); + return true; +} + +/* ATRM is used to get the BIOS on the discrete cards in + * dual-gpu systems. + */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(ACPI_HANDLE atrm_handle, uint8_t *bios, + int offset, int len) +{ + ACPI_STATUS status; + ACPI_OBJECT atrm_arg_elements[2], *obj; + ACPI_OBJECT_LIST atrm_arg; + ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.Count = 2; + atrm_arg.Pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].Type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].Integer.Value = offset; + + atrm_arg_elements[1].Type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].Integer.Value = len; + + status = AcpiEvaluateObject(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + DRM_ERROR("failed to evaluate ATRM got %s\n", AcpiFormatException(status)); + return -ENODEV; + } + + obj = (ACPI_OBJECT *)buffer.Pointer; + memcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length); + len = obj->Buffer.Length; + AcpiOsFree(buffer.Pointer); + return len; +} + +static bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + int ret; + int size = 256 * 1024; + int i; + device_t dev; + ACPI_HANDLE dhandle, atrm_handle; + ACPI_STATUS status; + bool found = false; + + DRM_INFO("%s: ===> Try ATRM...\n", __func__); + + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) { + DRM_INFO("%s: IGP card detected, skipping this method...\n", + __func__); + return false; + } + +#ifdef DUMBBELL_WIP + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { +#endif /* DUMBBELL_WIP */ + if ((dev = pci_find_class(PCIC_DISPLAY, PCIS_DISPLAY_VGA)) != NULL) { + DRM_INFO("%s: pci_find_class() found: %d:%d:%d:%d, vendor=%04x, device=%04x\n", + __func__, + pci_get_domain(dev), + pci_get_bus(dev), + pci_get_slot(dev), + pci_get_function(dev), + pci_get_vendor(dev), + pci_get_device(dev)); + DRM_INFO("%s: Get ACPI device handle\n", __func__); + dhandle = acpi_get_handle(dev); +#ifdef DUMBBELL_WIP + if (!dhandle) + continue; +#endif /* DUMBBELL_WIP */ + if (!dhandle) + return false; + + DRM_INFO("%s: Get ACPI handle for \"ATRM\"\n", __func__); + status = AcpiGetHandle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; +#ifdef DUMBBELL_WIP + break; +#endif /* DUMBBELL_WIP */ + } else { + DRM_INFO("%s: Failed to get \"ATRM\" handle: %s\n", + __func__, AcpiFormatException(status)); + } + } + + if (!found) + return false; + + rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); + if (!rdev->bios) { + DRM_ERROR("Unable to allocate bios\n"); + return false; + } + + for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { + DRM_INFO("%s: Call radeon_atrm_call()\n", __func__); + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); + if (ret < ATRM_BIOS_PAGE) + break; + } + + if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + if (i == 0) { + DRM_INFO("%s: Incorrect BIOS size\n", __func__); + } else { + DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", + __func__, rdev->bios[0], rdev->bios[1]); + } + free(rdev->bios, DRM_MEM_DRIVER); + return false; + } + return true; +} + +static bool ni_read_disabled_bios(struct radeon_device *rdev) +{ + u32 bus_cntl; + u32 d1vga_control; + u32 d2vga_control; + u32 vga_render_control; + u32 rom_cntl; + bool r; + + DRM_INFO("%s: ===> Try disabled BIOS (ni)...\n", __func__); + + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r700_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t cg_spll_func_cntl = 0; + uint32_t cg_spll_status; + bool r; + + DRM_INFO("%s: ===> Try disabled BIOS (r700)...\n", __func__); + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + if (rdev->family == CHIP_RV730) { + cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); + + /* enable bypass mode */ + WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | + R600_SPLL_BYPASS_EN)); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + + WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); + } else + WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + if (rdev->family == CHIP_RV730) { + WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + } + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r600_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t general_pwrmgt; + uint32_t low_vid_lower_gpio_cntl; + uint32_t medium_vid_lower_gpio_cntl; + uint32_t high_vid_lower_gpio_cntl; + uint32_t ctxsw_vid_lower_gpio_cntl; + uint32_t lower_gpio_enable; + bool r; + + DRM_INFO("%s: ===> Try disabled BIOS (r600)...\n", __func__); + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); + low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); + medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); + high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); + ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); + lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + WREG32(R600_ROM_CNTL, + ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | + (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | + R600_SCK_OVERWRITE)); + + WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, + (low_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, + (medium_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, + (high_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, + (ctxsw_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); + WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); + return r; +} + +static bool avivo_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t gpiopad_a; + uint32_t gpiopad_en; + uint32_t gpiopad_mask; + bool r; + + DRM_INFO("%s: ===> Try disabled BIOS (avivo)...\n", __func__); + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(RV370_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + gpiopad_en = RREG32(RADEON_GPIOPAD_EN); + gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + WREG32(RADEON_GPIOPAD_A, 0); + WREG32(RADEON_GPIOPAD_EN, 0); + WREG32(RADEON_GPIOPAD_MASK, 0); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(RV370_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(RADEON_GPIOPAD_A, gpiopad_a); + WREG32(RADEON_GPIOPAD_EN, gpiopad_en); + WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); + return r; +} + +static bool legacy_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t crtc_gen_cntl; + uint32_t crtc2_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t fp2_gen_cntl; + bool r; + + DRM_INFO("%s: ===> Try disabled BIOS (legacy)...\n", __func__); + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + if (rdev->flags & RADEON_IS_PCIE) + bus_cntl = RREG32(RV370_BUS_CNTL); + else + bus_cntl = RREG32(RADEON_BUS_CNTL); + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); + crtc2_gen_cntl = 0; + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + fp2_gen_cntl = 0; + +#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 + + if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + } + + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + else + WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + + /* Turn off mem requests and CRTC for both controllers */ + WREG32(RADEON_CRTC_GEN_CNTL, + ((crtc_gen_cntl & ~RADEON_CRTC_EN) | + (RADEON_CRTC_DISP_REQ_EN_B | + RADEON_CRTC_EXT_DISP_EN))); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, + ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | + RADEON_CRTC2_DISP_REQ_EN_B)); + } + /* Turn off CRTC */ + WREG32(RADEON_CRTC_EXT_CNTL, + ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | + (RADEON_CRTC_SYNC_TRISTAT | + RADEON_CRTC_DISPLAY_DIS))); + + if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); + } + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, bus_cntl); + else + WREG32(RADEON_BUS_CNTL, bus_cntl); + WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + } + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + } + return r; +} + +static bool radeon_read_disabled_bios(struct radeon_device *rdev) +{ + if (rdev->flags & RADEON_IS_IGP) + return igp_read_bios_from_vram(rdev); + else if (rdev->family >= CHIP_BARTS) + return ni_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RV770) + return r700_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_R600) + return r600_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RS600) + return avivo_read_disabled_bios(rdev); + else + return legacy_read_disabled_bios(rdev); +} + +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + ACPI_TABLE_HEADER *hdr; + ACPI_SIZE tbl_size; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + ACPI_STATUS status; + + DRM_INFO("%s: ===> Try VFCT...\n", __func__); + + DRM_INFO("%s: Get \"VFCT\" ACPI table\n", __func__); + status = AcpiGetTable("VFCT", 1, &hdr); + if (!ACPI_SUCCESS(status)) { + DRM_INFO("%s: Failed to get \"VFCT\" table: %s\n", + __func__, AcpiFormatException(status)); + return false; + } + tbl_size = hdr->Length; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->ddev->pci_bus || + vhdr->PCIDevice != rdev->ddev->pci_slot || + vhdr->PCIFunction != rdev->ddev->pci_func || + vhdr->VendorID != rdev->ddev->pci_vendor || + vhdr->DeviceID != rdev->ddev->pci_device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = malloc(vhdr->ImageLength, DRM_MEM_DRIVER, M_WAITOK); + memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength); + ret = !!rdev->bios; + +out_unmap: + return ret; +} + +bool radeon_get_bios(struct radeon_device *rdev) +{ + bool r; + uint16_t tmp; + + r = radeon_atrm_get_bios(rdev); + if (r == false) + r = radeon_acpi_vfct_bios(rdev); + if (r == false) + r = igp_read_bios_from_vram(rdev); + if (r == false) + r = radeon_read_bios(rdev); + if (r == false) { + r = radeon_read_disabled_bios(rdev); + } + if (r == false || rdev->bios == NULL) { + DRM_ERROR("Unable to locate a BIOS ROM\n"); + rdev->bios = NULL; + return false; + } + if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + DRM_ERROR("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); + goto free_bios; + } + + tmp = RBIOS16(0x18); + if (RBIOS8(tmp + 0x14) != 0x0) { + DRM_INFO("Not an x86 BIOS ROM, not using.\n"); + goto free_bios; + } + + rdev->bios_header_start = RBIOS16(0x48); + if (!rdev->bios_header_start) { + goto free_bios; + } + tmp = rdev->bios_header_start + 4; + if (!memcmp(rdev->bios + tmp, "ATOM", 4) || + !memcmp(rdev->bios + tmp, "MOTA", 4)) { + rdev->is_atom_bios = true; + } else { + rdev->is_atom_bios = false; + } + + DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); + return true; +free_bios: + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; + return false; +} diff --git a/sys/dev/drm2/radeon/radeon_blit_common.h b/sys/dev/drm2/radeon/radeon_blit_common.h new file mode 100644 index 00000000000..a8f6827cf79 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_blit_common.h @@ -0,0 +1,47 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * Copyright 2012 Alcatel-Lucent, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __RADEON_BLIT_COMMON_H__ + +#include +__FBSDID("$FreeBSD$"); + +#define DI_PT_RECTLIST 0x11 +#define DI_INDEX_SIZE_16_BIT 0x0 +#define DI_SRC_SEL_AUTO_INDEX 0x2 + +#define FMT_8 0x1 +#define FMT_5_6_5 0x8 +#define FMT_8_8_8_8 0x1a +#define COLOR_8 0x1 +#define COLOR_5_6_5 0x8 +#define COLOR_8_8_8_8 0x1a + +#define RECT_UNIT_H 32 +#define RECT_UNIT_W (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H) + +#define __RADEON_BLIT_COMMON_H__ +#endif diff --git a/sys/dev/drm2/radeon/radeon_clocks.c b/sys/dev/drm2/radeon/radeon_clocks.c new file mode 100644 index 00000000000..9ecd18adb94 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_clocks.c @@ -0,0 +1,917 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" + +/* 10 khz */ +uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) +{ + struct radeon_pll *spll = &rdev->clock.spll; + uint32_t fb_div, ref_div, post_div, sclk; + + fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); + fb_div = (fb_div >> RADEON_SPLL_FB_DIV_SHIFT) & RADEON_SPLL_FB_DIV_MASK; + fb_div <<= 1; + fb_div *= spll->reference_freq; + + ref_div = + RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; + + if (ref_div == 0) + return 0; + + sclk = fb_div / ref_div; + + post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK; + if (post_div == 2) + sclk >>= 1; + else if (post_div == 3) + sclk >>= 2; + else if (post_div == 4) + sclk >>= 3; + + return sclk; +} + +/* 10 khz */ +uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) +{ + struct radeon_pll *mpll = &rdev->clock.mpll; + uint32_t fb_div, ref_div, post_div, mclk; + + fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); + fb_div = (fb_div >> RADEON_MPLL_FB_DIV_SHIFT) & RADEON_MPLL_FB_DIV_MASK; + fb_div <<= 1; + fb_div *= mpll->reference_freq; + + ref_div = + RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; + + if (ref_div == 0) + return 0; + + mclk = fb_div / ref_div; + + post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7; + if (post_div == 2) + mclk >>= 1; + else if (post_div == 3) + mclk >>= 2; + else if (post_div == 4) + mclk >>= 3; + + return mclk; +} + +#ifdef CONFIG_OF +/* + * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device + * tree. Hopefully, ATI OF driver is kind enough to fill these + */ +static bool radeon_read_clocks_OF(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct device_node *dp = rdev->pdev->dev.of_node; + const u32 *val; + struct radeon_pll *p1pll = &rdev->clock.p1pll; + struct radeon_pll *p2pll = &rdev->clock.p2pll; + struct radeon_pll *spll = &rdev->clock.spll; + struct radeon_pll *mpll = &rdev->clock.mpll; + + if (dp == NULL) + return false; + val = of_get_property(dp, "ATY,RefCLK", NULL); + if (!val || !*val) { + printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); + return false; + } + p1pll->reference_freq = p2pll->reference_freq = (*val) / 10; + p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; + if (p1pll->reference_div < 2) + p1pll->reference_div = 12; + p2pll->reference_div = p1pll->reference_div; + + /* These aren't in the device-tree */ + if (rdev->family >= CHIP_R420) { + p1pll->pll_in_min = 100; + p1pll->pll_in_max = 1350; + p1pll->pll_out_min = 20000; + p1pll->pll_out_max = 50000; + p2pll->pll_in_min = 100; + p2pll->pll_in_max = 1350; + p2pll->pll_out_min = 20000; + p2pll->pll_out_max = 50000; + } else { + p1pll->pll_in_min = 40; + p1pll->pll_in_max = 500; + p1pll->pll_out_min = 12500; + p1pll->pll_out_max = 35000; + p2pll->pll_in_min = 40; + p2pll->pll_in_max = 500; + p2pll->pll_out_min = 12500; + p2pll->pll_out_max = 35000; + } + /* not sure what the max should be in all cases */ + rdev->clock.max_pixel_clock = 35000; + + spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; + spll->reference_div = mpll->reference_div = + RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & + RADEON_M_SPLL_REF_DIV_MASK; + + val = of_get_property(dp, "ATY,SCLK", NULL); + if (val && *val) + rdev->clock.default_sclk = (*val) / 10; + else + rdev->clock.default_sclk = + radeon_legacy_get_engine_clock(rdev); + + val = of_get_property(dp, "ATY,MCLK", NULL); + if (val && *val) + rdev->clock.default_mclk = (*val) / 10; + else + rdev->clock.default_mclk = + radeon_legacy_get_memory_clock(rdev); + + DRM_INFO("Using device-tree clock info\n"); + + return true; +} +#else +static bool radeon_read_clocks_OF(struct drm_device *dev) +{ + return false; +} +#endif /* CONFIG_OF */ + +void radeon_get_clock_info(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_pll *p1pll = &rdev->clock.p1pll; + struct radeon_pll *p2pll = &rdev->clock.p2pll; + struct radeon_pll *dcpll = &rdev->clock.dcpll; + struct radeon_pll *spll = &rdev->clock.spll; + struct radeon_pll *mpll = &rdev->clock.mpll; + int ret; + + if (rdev->is_atom_bios) + ret = radeon_atom_get_clock_info(dev); + else + ret = radeon_combios_get_clock_info(dev); + if (!ret) + ret = radeon_read_clocks_OF(dev); + + if (ret) { + if (p1pll->reference_div < 2) { + if (!ASIC_IS_AVIVO(rdev)) { + u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV); + if (ASIC_IS_R300(rdev)) + p1pll->reference_div = + (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; + else + p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; + if (p1pll->reference_div < 2) + p1pll->reference_div = 12; + } else + p1pll->reference_div = 12; + } + if (p2pll->reference_div < 2) + p2pll->reference_div = 12; + if (rdev->family < CHIP_RS600) { + if (spll->reference_div < 2) + spll->reference_div = + RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & + RADEON_M_SPLL_REF_DIV_MASK; + } + if (mpll->reference_div < 2) + mpll->reference_div = spll->reference_div; + } else { + if (ASIC_IS_AVIVO(rdev)) { + /* TODO FALLBACK */ + } else { + DRM_INFO("Using generic clock info\n"); + + /* may need to be per card */ + rdev->clock.max_pixel_clock = 35000; + + if (rdev->flags & RADEON_IS_IGP) { + p1pll->reference_freq = 1432; + p2pll->reference_freq = 1432; + spll->reference_freq = 1432; + mpll->reference_freq = 1432; + } else { + p1pll->reference_freq = 2700; + p2pll->reference_freq = 2700; + spll->reference_freq = 2700; + mpll->reference_freq = 2700; + } + p1pll->reference_div = + RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; + if (p1pll->reference_div < 2) + p1pll->reference_div = 12; + p2pll->reference_div = p1pll->reference_div; + + if (rdev->family >= CHIP_R420) { + p1pll->pll_in_min = 100; + p1pll->pll_in_max = 1350; + p1pll->pll_out_min = 20000; + p1pll->pll_out_max = 50000; + p2pll->pll_in_min = 100; + p2pll->pll_in_max = 1350; + p2pll->pll_out_min = 20000; + p2pll->pll_out_max = 50000; + } else { + p1pll->pll_in_min = 40; + p1pll->pll_in_max = 500; + p1pll->pll_out_min = 12500; + p1pll->pll_out_max = 35000; + p2pll->pll_in_min = 40; + p2pll->pll_in_max = 500; + p2pll->pll_out_min = 12500; + p2pll->pll_out_max = 35000; + } + + spll->reference_div = + RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & + RADEON_M_SPLL_REF_DIV_MASK; + mpll->reference_div = spll->reference_div; + rdev->clock.default_sclk = + radeon_legacy_get_engine_clock(rdev); + rdev->clock.default_mclk = + radeon_legacy_get_memory_clock(rdev); + } + } + + /* pixel clocks */ + if (ASIC_IS_AVIVO(rdev)) { + p1pll->min_post_div = 2; + p1pll->max_post_div = 0x7f; + p1pll->min_frac_feedback_div = 0; + p1pll->max_frac_feedback_div = 9; + p2pll->min_post_div = 2; + p2pll->max_post_div = 0x7f; + p2pll->min_frac_feedback_div = 0; + p2pll->max_frac_feedback_div = 9; + } else { + p1pll->min_post_div = 1; + p1pll->max_post_div = 16; + p1pll->min_frac_feedback_div = 0; + p1pll->max_frac_feedback_div = 0; + p2pll->min_post_div = 1; + p2pll->max_post_div = 12; + p2pll->min_frac_feedback_div = 0; + p2pll->max_frac_feedback_div = 0; + } + + /* dcpll is DCE4 only */ + dcpll->min_post_div = 2; + dcpll->max_post_div = 0x7f; + dcpll->min_frac_feedback_div = 0; + dcpll->max_frac_feedback_div = 9; + dcpll->min_ref_div = 2; + dcpll->max_ref_div = 0x3ff; + dcpll->min_feedback_div = 4; + dcpll->max_feedback_div = 0xfff; + dcpll->best_vco = 0; + + p1pll->min_ref_div = 2; + p1pll->max_ref_div = 0x3ff; + p1pll->min_feedback_div = 4; + p1pll->max_feedback_div = 0x7ff; + p1pll->best_vco = 0; + + p2pll->min_ref_div = 2; + p2pll->max_ref_div = 0x3ff; + p2pll->min_feedback_div = 4; + p2pll->max_feedback_div = 0x7ff; + p2pll->best_vco = 0; + + /* system clock */ + spll->min_post_div = 1; + spll->max_post_div = 1; + spll->min_ref_div = 2; + spll->max_ref_div = 0xff; + spll->min_feedback_div = 4; + spll->max_feedback_div = 0xff; + spll->best_vco = 0; + + /* memory clock */ + mpll->min_post_div = 1; + mpll->max_post_div = 1; + mpll->min_ref_div = 2; + mpll->max_ref_div = 0xff; + mpll->min_feedback_div = 4; + mpll->max_feedback_div = 0xff; + mpll->best_vco = 0; + + if (!rdev->clock.default_sclk) + rdev->clock.default_sclk = radeon_get_engine_clock(rdev); + if ((!rdev->clock.default_mclk) && rdev->asic->pm.get_memory_clock) + rdev->clock.default_mclk = radeon_get_memory_clock(rdev); + + rdev->pm.current_sclk = rdev->clock.default_sclk; + rdev->pm.current_mclk = rdev->clock.default_mclk; + +} + +/* 10 khz */ +static uint32_t calc_eng_mem_clock(struct radeon_device *rdev, + uint32_t req_clock, + int *fb_div, int *post_div) +{ + struct radeon_pll *spll = &rdev->clock.spll; + int ref_div = spll->reference_div; + + if (!ref_div) + ref_div = + RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & + RADEON_M_SPLL_REF_DIV_MASK; + + if (req_clock < 15000) { + *post_div = 8; + req_clock *= 8; + } else if (req_clock < 30000) { + *post_div = 4; + req_clock *= 4; + } else if (req_clock < 60000) { + *post_div = 2; + req_clock *= 2; + } else + *post_div = 1; + + req_clock *= ref_div; + req_clock += spll->reference_freq; + req_clock /= (2 * spll->reference_freq); + + *fb_div = req_clock & 0xff; + + req_clock = (req_clock & 0xffff) << 1; + req_clock *= spll->reference_freq; + req_clock /= ref_div; + req_clock /= *post_div; + + return req_clock; +} + +/* 10 khz */ +void radeon_legacy_set_engine_clock(struct radeon_device *rdev, + uint32_t eng_clock) +{ + uint32_t tmp; + int fb_div, post_div; + + /* XXX: wait for idle */ + + eng_clock = calc_eng_mem_clock(rdev, eng_clock, &fb_div, &post_div); + + tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); + tmp &= ~RADEON_DONT_USE_XTALIN; + WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp &= ~RADEON_SCLK_SRC_SEL_MASK; + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + DRM_UDELAY(10); + + tmp = RREG32_PLL(RADEON_SPLL_CNTL); + tmp |= RADEON_SPLL_SLEEP; + WREG32_PLL(RADEON_SPLL_CNTL, tmp); + + DRM_UDELAY(2); + + tmp = RREG32_PLL(RADEON_SPLL_CNTL); + tmp |= RADEON_SPLL_RESET; + WREG32_PLL(RADEON_SPLL_CNTL, tmp); + + DRM_UDELAY(200); + + tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); + tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT); + tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT; + WREG32_PLL(RADEON_M_SPLL_REF_FB_DIV, tmp); + + /* XXX: verify on different asics */ + tmp = RREG32_PLL(RADEON_SPLL_CNTL); + tmp &= ~RADEON_SPLL_PVG_MASK; + if ((eng_clock * post_div) >= 90000) + tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT); + else + tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT); + WREG32_PLL(RADEON_SPLL_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_SPLL_CNTL); + tmp &= ~RADEON_SPLL_SLEEP; + WREG32_PLL(RADEON_SPLL_CNTL, tmp); + + DRM_UDELAY(2); + + tmp = RREG32_PLL(RADEON_SPLL_CNTL); + tmp &= ~RADEON_SPLL_RESET; + WREG32_PLL(RADEON_SPLL_CNTL, tmp); + + DRM_UDELAY(200); + + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp &= ~RADEON_SCLK_SRC_SEL_MASK; + switch (post_div) { + case 1: + default: + tmp |= 1; + break; + case 2: + tmp |= 2; + break; + case 4: + tmp |= 3; + break; + case 8: + tmp |= 4; + break; + } + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + DRM_UDELAY(20); + + tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); + tmp |= RADEON_DONT_USE_XTALIN; + WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); + + DRM_UDELAY(10); +} + +void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) +{ + uint32_t tmp; + + if (enable) { + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + if ((RREG32(RADEON_CONFIG_CNTL) & + RADEON_CFG_ATI_REV_ID_MASK) > + RADEON_CFG_ATI_REV_A13) { + tmp &= + ~(RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_RB); + } + tmp &= + ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_TDM); + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + } else if (ASIC_IS_R300(rdev)) { + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp &= + ~(RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP + | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR + | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX + | R300_SCLK_FORCE_US | + RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | + RADEON_SCLK_FORCE_OV0); + tmp |= RADEON_DYN_STOP_LAT_MASK; + tmp |= + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_VIP; + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + } else if (rdev->family >= CHIP_RV350) { + tmp = RREG32_PLL(R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | + R300_SCLK_GA_MAX_DYN_STOP_LAT | + R300_SCLK_CBA_MAX_DYN_STOP_LAT); + WREG32_PLL(R300_SCLK_CNTL2, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp &= + ~(RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP + | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR + | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX + | R300_SCLK_FORCE_US | + RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | + RADEON_SCLK_FORCE_OV0); + tmp |= RADEON_DYN_STOP_LAT_MASK; + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_MCLK_MISC); + tmp |= (RADEON_MC_MCLK_DYN_ENABLE | + RADEON_IO_MCLK_DYN_ENABLE); + WREG32_PLL(RADEON_MCLK_MISC, tmp); + + tmp = RREG32_PLL(RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB); + + tmp &= ~(RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + + /* Some releases of vbios have set DISABLE_MC_MCLKA + and DISABLE_MC_MCLKB bits in the vbios table. Setting these + bits will cause H/W hang when reading video memory with dynamic clocking + enabled. */ + if ((tmp & R300_DISABLE_MC_MCLKA) && + (tmp & R300_DISABLE_MC_MCLKB)) { + /* If both bits are set, then check the active channels */ + tmp = RREG32_PLL(RADEON_MCLK_CNTL); + if (rdev->mc.vram_width == 64) { + if (RREG32(RADEON_MEM_CNTL) & + R300_MEM_USE_CD_CH_ONLY) + tmp &= + ~R300_DISABLE_MC_MCLKB; + else + tmp &= + ~R300_DISABLE_MC_MCLKA; + } else { + tmp &= ~(R300_DISABLE_MC_MCLKA | + R300_DISABLE_MC_MCLKB); + } + } + + WREG32_PLL(RADEON_MCLK_CNTL, tmp); + } else { + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp &= ~(R300_SCLK_FORCE_VAP); + tmp |= RADEON_SCLK_FORCE_CP; + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + DRM_MDELAY(15); + + tmp = RREG32_PLL(R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + WREG32_PLL(R300_SCLK_CNTL2, tmp); + } + } else { + tmp = RREG32_PLL(RADEON_CLK_PWRMGT_CNTL); + + tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | + RADEON_DISP_DYN_STOP_LAT_MASK | + RADEON_DYN_STOP_MODE_MASK); + + tmp |= (RADEON_ENGIN_DYNCLK_MODE | + (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); + WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp); + DRM_MDELAY(15); + + tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); + tmp |= RADEON_SCLK_DYN_START_CNTL; + WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); + DRM_MDELAY(15); + + /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 + to lockup randomly, leave them as set by BIOS. + */ + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + /*tmp &= RADEON_SCLK_SRC_SEL_MASK; */ + tmp &= ~RADEON_SCLK_FORCEON_MASK; + + /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300 */ + if (((rdev->family == CHIP_RV250) && + ((RREG32(RADEON_CONFIG_CNTL) & + RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) + || ((rdev->family == CHIP_RV100) + && + ((RREG32(RADEON_CONFIG_CNTL) & + RADEON_CFG_ATI_REV_ID_MASK) <= + RADEON_CFG_ATI_REV_A13))) { + tmp |= RADEON_SCLK_FORCE_CP; + tmp |= RADEON_SCLK_FORCE_VIP; + } + + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + if ((rdev->family == CHIP_RV200) || + (rdev->family == CHIP_RV250) || + (rdev->family == CHIP_RV280)) { + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + + /* RV200::A11 A12 RV250::A11 A12 */ + if (((rdev->family == CHIP_RV200) || + (rdev->family == CHIP_RV250)) && + ((RREG32(RADEON_CONFIG_CNTL) & + RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) { + tmp |= RADEON_SCLK_MORE_FORCEON; + } + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); + DRM_MDELAY(15); + } + + /* RV200::A11 A12, RV250::A11 A12 */ + if (((rdev->family == CHIP_RV200) || + (rdev->family == CHIP_RV250)) && + ((RREG32(RADEON_CONFIG_CNTL) & + RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) { + tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); + tmp |= RADEON_TCL_BYPASS_DISABLE; + WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); + } + DRM_MDELAY(15); + + /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */ + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + DRM_MDELAY(15); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + DRM_MDELAY(15); + } + } else { + /* Turn everything OFF (ForceON to everything) */ + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP + | RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_RB); + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + } else if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 + | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + } else if (rdev->family >= CHIP_RV350) { + /* for RV350/M10, no delays are required. */ + tmp = RREG32_PLL(R300_SCLK_CNTL2); + tmp |= (R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA); + WREG32_PLL(R300_SCLK_CNTL2, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 + | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC); + WREG32_PLL(RADEON_MCLK_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + } else { + tmp = RREG32_PLL(RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); + tmp |= RADEON_SCLK_FORCE_SE; + + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp |= (RADEON_SCLK_FORCE_RB | + RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_HDP); + } else if ((rdev->family == CHIP_R300) || + (rdev->family == CHIP_R350)) { + tmp |= (RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP); + } + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + + DRM_MDELAY(16); + + if ((rdev->family == CHIP_R300) || + (rdev->family == CHIP_R350)) { + tmp = RREG32_PLL(R300_SCLK_CNTL2); + tmp |= (R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + WREG32_PLL(R300_SCLK_CNTL2, tmp); + DRM_MDELAY(16); + } + + if (rdev->flags & RADEON_IS_IGP) { + tmp = RREG32_PLL(RADEON_MCLK_CNTL); + tmp &= ~(RADEON_FORCEON_MCLKA | + RADEON_FORCEON_YCLKA); + WREG32_PLL(RADEON_MCLK_CNTL, tmp); + DRM_MDELAY(16); + } + + if ((rdev->family == CHIP_RV200) || + (rdev->family == CHIP_RV250) || + (rdev->family == CHIP_RV280)) { + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); + DRM_MDELAY(16); + } + + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + DRM_MDELAY(16); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + } + } +} + diff --git a/sys/dev/drm2/radeon/radeon_combios.c b/sys/dev/drm2/radeon/radeon_combios.c new file mode 100644 index 00000000000..caa8a003589 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_combios.c @@ -0,0 +1,3661 @@ +/* + * Copyright 2004 ATI Technologies Inc., Markham, Ontario + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "atom.h" + +#ifdef CONFIG_PPC_PMAC +/* not sure which of these are needed */ +#include +#include +#include +#include +#endif /* CONFIG_PPC_PMAC */ + +/* old legacy ATI BIOS routines */ + +/* COMBIOS table offsets */ +enum radeon_combios_table_offset { + /* absolute offset tables */ + COMBIOS_ASIC_INIT_1_TABLE, + COMBIOS_BIOS_SUPPORT_TABLE, + COMBIOS_DAC_PROGRAMMING_TABLE, + COMBIOS_MAX_COLOR_DEPTH_TABLE, + COMBIOS_CRTC_INFO_TABLE, + COMBIOS_PLL_INFO_TABLE, + COMBIOS_TV_INFO_TABLE, + COMBIOS_DFP_INFO_TABLE, + COMBIOS_HW_CONFIG_INFO_TABLE, + COMBIOS_MULTIMEDIA_INFO_TABLE, + COMBIOS_TV_STD_PATCH_TABLE, + COMBIOS_LCD_INFO_TABLE, + COMBIOS_MOBILE_INFO_TABLE, + COMBIOS_PLL_INIT_TABLE, + COMBIOS_MEM_CONFIG_TABLE, + COMBIOS_SAVE_MASK_TABLE, + COMBIOS_HARDCODED_EDID_TABLE, + COMBIOS_ASIC_INIT_2_TABLE, + COMBIOS_CONNECTOR_INFO_TABLE, + COMBIOS_DYN_CLK_1_TABLE, + COMBIOS_RESERVED_MEM_TABLE, + COMBIOS_EXT_TMDS_INFO_TABLE, + COMBIOS_MEM_CLK_INFO_TABLE, + COMBIOS_EXT_DAC_INFO_TABLE, + COMBIOS_MISC_INFO_TABLE, + COMBIOS_CRT_INFO_TABLE, + COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE, + COMBIOS_COMPONENT_VIDEO_INFO_TABLE, + COMBIOS_FAN_SPEED_INFO_TABLE, + COMBIOS_OVERDRIVE_INFO_TABLE, + COMBIOS_OEM_INFO_TABLE, + COMBIOS_DYN_CLK_2_TABLE, + COMBIOS_POWER_CONNECTOR_INFO_TABLE, + COMBIOS_I2C_INFO_TABLE, + /* relative offset tables */ + COMBIOS_ASIC_INIT_3_TABLE, /* offset from misc info */ + COMBIOS_ASIC_INIT_4_TABLE, /* offset from misc info */ + COMBIOS_DETECTED_MEM_TABLE, /* offset from misc info */ + COMBIOS_ASIC_INIT_5_TABLE, /* offset from misc info */ + COMBIOS_RAM_RESET_TABLE, /* offset from mem config */ + COMBIOS_POWERPLAY_INFO_TABLE, /* offset from mobile info */ + COMBIOS_GPIO_INFO_TABLE, /* offset from mobile info */ + COMBIOS_LCD_DDC_INFO_TABLE, /* offset from mobile info */ + COMBIOS_TMDS_POWER_TABLE, /* offset from mobile info */ + COMBIOS_TMDS_POWER_ON_TABLE, /* offset from tmds power */ + COMBIOS_TMDS_POWER_OFF_TABLE, /* offset from tmds power */ +}; + +enum radeon_combios_ddc { + DDC_NONE_DETECTED, + DDC_MONID, + DDC_DVI, + DDC_VGA, + DDC_CRT2, + DDC_LCD, + DDC_GPIO, +}; + +enum radeon_combios_connector { + CONNECTOR_NONE_LEGACY, + CONNECTOR_PROPRIETARY_LEGACY, + CONNECTOR_CRT_LEGACY, + CONNECTOR_DVI_I_LEGACY, + CONNECTOR_DVI_D_LEGACY, + CONNECTOR_CTV_LEGACY, + CONNECTOR_STV_LEGACY, + CONNECTOR_UNSUPPORTED_LEGACY +}; + +const int legacy_connector_convert[] = { + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_DVID, + DRM_MODE_CONNECTOR_VGA, + DRM_MODE_CONNECTOR_DVII, + DRM_MODE_CONNECTOR_DVID, + DRM_MODE_CONNECTOR_Composite, + DRM_MODE_CONNECTOR_SVIDEO, + DRM_MODE_CONNECTOR_Unknown, +}; + +static uint16_t combios_get_table_offset(struct drm_device *dev, + enum radeon_combios_table_offset table) +{ + struct radeon_device *rdev = dev->dev_private; + int rev; + uint16_t offset = 0, check_offset; + + if (!rdev->bios) + return 0; + + switch (table) { + /* absolute offset tables */ + case COMBIOS_ASIC_INIT_1_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0xc); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_BIOS_SUPPORT_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x14); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DAC_PROGRAMMING_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x2a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MAX_COLOR_DEPTH_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x2c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_CRTC_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x2e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_PLL_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x30); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_TV_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x32); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DFP_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x34); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_HW_CONFIG_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x36); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MULTIMEDIA_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x38); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_TV_STD_PATCH_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x3e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_LCD_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x40); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MOBILE_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x42); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_PLL_INIT_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x46); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MEM_CONFIG_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x48); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_SAVE_MASK_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x4a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_HARDCODED_EDID_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x4c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_ASIC_INIT_2_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x4e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_CONNECTOR_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x50); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DYN_CLK_1_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x52); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_RESERVED_MEM_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x54); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_EXT_TMDS_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x58); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MEM_CLK_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x5a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_EXT_DAC_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x5c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MISC_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x5e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_CRT_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x60); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x62); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_COMPONENT_VIDEO_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x64); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_FAN_SPEED_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x66); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_OVERDRIVE_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x68); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_OEM_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x6a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DYN_CLK_2_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x6c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_POWER_CONNECTOR_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x6e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_I2C_INFO_TABLE: + check_offset = RBIOS16(rdev->bios_header_start + 0x70); + if (check_offset) + offset = check_offset; + break; + /* relative offset tables */ + case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = RBIOS8(check_offset); + if (rev > 0) { + check_offset = RBIOS16(check_offset + 0x3); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_ASIC_INIT_4_TABLE: /* offset from misc info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = RBIOS8(check_offset); + if (rev > 0) { + check_offset = RBIOS16(check_offset + 0x5); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_DETECTED_MEM_TABLE: /* offset from misc info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = RBIOS8(check_offset); + if (rev > 0) { + check_offset = RBIOS16(check_offset + 0x7); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_ASIC_INIT_5_TABLE: /* offset from misc info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = RBIOS8(check_offset); + if (rev == 2) { + check_offset = RBIOS16(check_offset + 0x9); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_RAM_RESET_TABLE: /* offset from mem config */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE); + if (check_offset) { + while (RBIOS8(check_offset++)); + check_offset += 2; + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_POWERPLAY_INFO_TABLE: /* offset from mobile info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = RBIOS16(check_offset + 0x11); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_GPIO_INFO_TABLE: /* offset from mobile info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = RBIOS16(check_offset + 0x13); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_LCD_DDC_INFO_TABLE: /* offset from mobile info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = RBIOS16(check_offset + 0x15); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_TMDS_POWER_TABLE: /* offset from mobile info */ + check_offset = + combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = RBIOS16(check_offset + 0x17); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_TMDS_POWER_ON_TABLE: /* offset from tmds power */ + check_offset = + combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE); + if (check_offset) { + check_offset = RBIOS16(check_offset + 0x2); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_TMDS_POWER_OFF_TABLE: /* offset from tmds power */ + check_offset = + combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE); + if (check_offset) { + check_offset = RBIOS16(check_offset + 0x4); + if (check_offset) + offset = check_offset; + } + break; + default: + break; + } + + return offset; + +} + +bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) +{ + int edid_info, size; + struct edid *edid; + unsigned char *raw; + edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE); + if (!edid_info) + return false; + + raw = rdev->bios + edid_info; + size = EDID_LENGTH * (raw[0x7e] + 1); + edid = malloc(size, DRM_MEM_KMS, M_WAITOK); + if (edid == NULL) + return false; + + memcpy((unsigned char *)edid, raw, size); + + if (!drm_edid_is_valid(edid)) { + free(edid, DRM_MEM_KMS); + return false; + } + + rdev->mode_info.bios_hardcoded_edid = edid; + rdev->mode_info.bios_hardcoded_edid_size = size; + return true; +} + +/* this is used for atom LCDs as well */ +struct edid * +radeon_bios_get_hardcoded_edid(struct radeon_device *rdev) +{ + struct edid *edid; + + if (rdev->mode_info.bios_hardcoded_edid) { + edid = malloc(rdev->mode_info.bios_hardcoded_edid_size, + DRM_MEM_KMS, M_WAITOK); + if (edid) { + memcpy((unsigned char *)edid, + (unsigned char *)rdev->mode_info.bios_hardcoded_edid, + rdev->mode_info.bios_hardcoded_edid_size); + return edid; + } + } + return NULL; +} + +static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, + enum radeon_combios_ddc ddc, + u32 clk_mask, + u32 data_mask) +{ + struct radeon_i2c_bus_rec i2c; + int ddc_line = 0; + + /* ddc id = mask reg + * DDC_NONE_DETECTED = none + * DDC_DVI = RADEON_GPIO_DVI_DDC + * DDC_VGA = RADEON_GPIO_VGA_DDC + * DDC_LCD = RADEON_GPIOPAD_MASK + * DDC_GPIO = RADEON_MDGPIO_MASK + * r1xx + * DDC_MONID = RADEON_GPIO_MONID + * DDC_CRT2 = RADEON_GPIO_CRT2_DDC + * r200 + * DDC_MONID = RADEON_GPIO_MONID + * DDC_CRT2 = RADEON_GPIO_DVI_DDC + * r300/r350 + * DDC_MONID = RADEON_GPIO_DVI_DDC + * DDC_CRT2 = RADEON_GPIO_DVI_DDC + * rv2xx/rv3xx + * DDC_MONID = RADEON_GPIO_MONID + * DDC_CRT2 = RADEON_GPIO_MONID + * rs3xx/rs4xx + * DDC_MONID = RADEON_GPIOPAD_MASK + * DDC_CRT2 = RADEON_GPIO_MONID + */ + switch (ddc) { + case DDC_NONE_DETECTED: + default: + ddc_line = 0; + break; + case DDC_DVI: + ddc_line = RADEON_GPIO_DVI_DDC; + break; + case DDC_VGA: + ddc_line = RADEON_GPIO_VGA_DDC; + break; + case DDC_LCD: + ddc_line = RADEON_GPIOPAD_MASK; + break; + case DDC_GPIO: + ddc_line = RADEON_MDGPIO_MASK; + break; + case DDC_MONID: + if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) + ddc_line = RADEON_GPIOPAD_MASK; + else if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { + ddc_line = RADEON_GPIO_DVI_DDC; + ddc = DDC_DVI; + } else + ddc_line = RADEON_GPIO_MONID; + break; + case DDC_CRT2: + if (rdev->family == CHIP_R200 || + rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { + ddc_line = RADEON_GPIO_DVI_DDC; + ddc = DDC_DVI; + } else if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) + ddc_line = RADEON_GPIO_MONID; + else if (rdev->family >= CHIP_RV350) { + ddc_line = RADEON_GPIO_MONID; + ddc = DDC_MONID; + } else + ddc_line = RADEON_GPIO_CRT2_DDC; + break; + } + + if (ddc_line == RADEON_GPIOPAD_MASK) { + i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; + i2c.mask_data_reg = RADEON_GPIOPAD_MASK; + i2c.a_clk_reg = RADEON_GPIOPAD_A; + i2c.a_data_reg = RADEON_GPIOPAD_A; + i2c.en_clk_reg = RADEON_GPIOPAD_EN; + i2c.en_data_reg = RADEON_GPIOPAD_EN; + i2c.y_clk_reg = RADEON_GPIOPAD_Y; + i2c.y_data_reg = RADEON_GPIOPAD_Y; + } else if (ddc_line == RADEON_MDGPIO_MASK) { + i2c.mask_clk_reg = RADEON_MDGPIO_MASK; + i2c.mask_data_reg = RADEON_MDGPIO_MASK; + i2c.a_clk_reg = RADEON_MDGPIO_A; + i2c.a_data_reg = RADEON_MDGPIO_A; + i2c.en_clk_reg = RADEON_MDGPIO_EN; + i2c.en_data_reg = RADEON_MDGPIO_EN; + i2c.y_clk_reg = RADEON_MDGPIO_Y; + i2c.y_data_reg = RADEON_MDGPIO_Y; + } else { + i2c.mask_clk_reg = ddc_line; + i2c.mask_data_reg = ddc_line; + i2c.a_clk_reg = ddc_line; + i2c.a_data_reg = ddc_line; + i2c.en_clk_reg = ddc_line; + i2c.en_data_reg = ddc_line; + i2c.y_clk_reg = ddc_line; + i2c.y_data_reg = ddc_line; + } + + if (clk_mask && data_mask) { + /* system specific masks */ + i2c.mask_clk_mask = clk_mask; + i2c.mask_data_mask = data_mask; + i2c.a_clk_mask = clk_mask; + i2c.a_data_mask = data_mask; + i2c.en_clk_mask = clk_mask; + i2c.en_data_mask = data_mask; + i2c.y_clk_mask = clk_mask; + i2c.y_data_mask = data_mask; + } else if ((ddc_line == RADEON_GPIOPAD_MASK) || + (ddc_line == RADEON_MDGPIO_MASK)) { + /* default gpiopad masks */ + i2c.mask_clk_mask = (0x20 << 8); + i2c.mask_data_mask = 0x80; + i2c.a_clk_mask = (0x20 << 8); + i2c.a_data_mask = 0x80; + i2c.en_clk_mask = (0x20 << 8); + i2c.en_data_mask = 0x80; + i2c.y_clk_mask = (0x20 << 8); + i2c.y_data_mask = 0x80; + } else { + /* default masks for ddc pads */ + i2c.mask_clk_mask = RADEON_GPIO_MASK_1; + i2c.mask_data_mask = RADEON_GPIO_MASK_0; + i2c.a_clk_mask = RADEON_GPIO_A_1; + i2c.a_data_mask = RADEON_GPIO_A_0; + i2c.en_clk_mask = RADEON_GPIO_EN_1; + i2c.en_data_mask = RADEON_GPIO_EN_0; + i2c.y_clk_mask = RADEON_GPIO_Y_1; + i2c.y_data_mask = RADEON_GPIO_Y_0; + } + + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_RS300: + switch (ddc_line) { + case RADEON_GPIO_DVI_DDC: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_R200: + switch (ddc_line) { + case RADEON_GPIO_DVI_DDC: + case RADEON_GPIO_MONID: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_RV250: + case CHIP_RV280: + switch (ddc_line) { + case RADEON_GPIO_VGA_DDC: + case RADEON_GPIO_DVI_DDC: + case RADEON_GPIO_CRT2_DDC: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_R300: + case CHIP_R350: + switch (ddc_line) { + case RADEON_GPIO_VGA_DDC: + case RADEON_GPIO_DVI_DDC: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_RV350: + case CHIP_RV380: + case CHIP_RS400: + case CHIP_RS480: + switch (ddc_line) { + case RADEON_GPIO_VGA_DDC: + case RADEON_GPIO_DVI_DDC: + i2c.hw_capable = true; + break; + case RADEON_GPIO_MONID: + /* hw i2c on RADEON_GPIO_MONID doesn't seem to work + * reliably on some pre-r4xx hardware; not sure why. + */ + i2c.hw_capable = false; + break; + default: + i2c.hw_capable = false; + break; + } + break; + default: + i2c.hw_capable = false; + break; + } + i2c.mm_i2c = false; + + i2c.i2c_id = ddc; + i2c.hpd = RADEON_HPD_NONE; + + if (ddc_line) + i2c.valid = true; + else + i2c.valid = false; + + return i2c; +} + +static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct radeon_i2c_bus_rec i2c; + u16 offset; + u8 id, blocks, clk, data; + int i; + + i2c.valid = false; + + offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); + if (offset) { + blocks = RBIOS8(offset + 2); + for (i = 0; i < blocks; i++) { + id = RBIOS8(offset + 3 + (i * 5) + 0); + if (id == 136) { + clk = RBIOS8(offset + 3 + (i * 5) + 3); + data = RBIOS8(offset + 3 + (i * 5) + 4); + /* gpiopad */ + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, + (1 << clk), (1 << data)); + break; + } + } + } + return i2c; +} + +void radeon_combios_i2c_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct radeon_i2c_bus_rec i2c; + + /* actual hw pads + * r1xx/rs2xx/rs3xx + * 0x60, 0x64, 0x68, 0x6c, gpiopads, mm + * r200 + * 0x60, 0x64, 0x68, mm + * r300/r350 + * 0x60, 0x64, mm + * rv2xx/rv3xx/rs4xx + * 0x60, 0x64, 0x68, gpiopads, mm + */ + + /* 0x60 */ + i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC"); + /* 0x64 */ + i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC"); + + /* mm i2c */ + i2c.valid = true; + i2c.hw_capable = true; + i2c.mm_i2c = true; + i2c.i2c_id = 0xa0; + rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C"); + + if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { + /* only 2 sw i2c pads */ + } else if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) { + /* 0x68 */ + i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); + + /* gpiopad */ + i2c = radeon_combios_get_i2c_info_from_table(rdev); + if (i2c.valid) + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); + } else if ((rdev->family == CHIP_R200) || + (rdev->family >= CHIP_R300)) { + /* 0x68 */ + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); + } else { + /* 0x68 */ + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); + /* 0x6c */ + i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); + } +} + +bool radeon_combios_get_clock_info(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + uint16_t pll_info; + struct radeon_pll *p1pll = &rdev->clock.p1pll; + struct radeon_pll *p2pll = &rdev->clock.p2pll; + struct radeon_pll *spll = &rdev->clock.spll; + struct radeon_pll *mpll = &rdev->clock.mpll; + int8_t rev; + uint16_t sclk, mclk; + + pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); + if (pll_info) { + rev = RBIOS8(pll_info); + + /* pixel clocks */ + p1pll->reference_freq = RBIOS16(pll_info + 0xe); + p1pll->reference_div = RBIOS16(pll_info + 0x10); + p1pll->pll_out_min = RBIOS32(pll_info + 0x12); + p1pll->pll_out_max = RBIOS32(pll_info + 0x16); + p1pll->lcd_pll_out_min = p1pll->pll_out_min; + p1pll->lcd_pll_out_max = p1pll->pll_out_max; + + if (rev > 9) { + p1pll->pll_in_min = RBIOS32(pll_info + 0x36); + p1pll->pll_in_max = RBIOS32(pll_info + 0x3a); + } else { + p1pll->pll_in_min = 40; + p1pll->pll_in_max = 500; + } + *p2pll = *p1pll; + + /* system clock */ + spll->reference_freq = RBIOS16(pll_info + 0x1a); + spll->reference_div = RBIOS16(pll_info + 0x1c); + spll->pll_out_min = RBIOS32(pll_info + 0x1e); + spll->pll_out_max = RBIOS32(pll_info + 0x22); + + if (rev > 10) { + spll->pll_in_min = RBIOS32(pll_info + 0x48); + spll->pll_in_max = RBIOS32(pll_info + 0x4c); + } else { + /* ??? */ + spll->pll_in_min = 40; + spll->pll_in_max = 500; + } + + /* memory clock */ + mpll->reference_freq = RBIOS16(pll_info + 0x26); + mpll->reference_div = RBIOS16(pll_info + 0x28); + mpll->pll_out_min = RBIOS32(pll_info + 0x2a); + mpll->pll_out_max = RBIOS32(pll_info + 0x2e); + + if (rev > 10) { + mpll->pll_in_min = RBIOS32(pll_info + 0x5a); + mpll->pll_in_max = RBIOS32(pll_info + 0x5e); + } else { + /* ??? */ + mpll->pll_in_min = 40; + mpll->pll_in_max = 500; + } + + /* default sclk/mclk */ + sclk = RBIOS16(pll_info + 0xa); + mclk = RBIOS16(pll_info + 0x8); + if (sclk == 0) + sclk = 200 * 100; + if (mclk == 0) + mclk = 200 * 100; + + rdev->clock.default_sclk = sclk; + rdev->clock.default_mclk = mclk; + + if (RBIOS32(pll_info + 0x16)) + rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16); + else + rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */ + + return true; + } + return false; +} + +bool radeon_combios_sideport_present(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + u16 igp_info; + + /* sideport is AMD only */ + if (rdev->family == CHIP_RS400) + return false; + + igp_info = combios_get_table_offset(dev, COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE); + + if (igp_info) { + if (RBIOS16(igp_info + 0x4)) + return true; + } + return false; +} + +static const uint32_t default_primarydac_adj[CHIP_LAST] = { + 0x00000808, /* r100 */ + 0x00000808, /* rv100 */ + 0x00000808, /* rs100 */ + 0x00000808, /* rv200 */ + 0x00000808, /* rs200 */ + 0x00000808, /* r200 */ + 0x00000808, /* rv250 */ + 0x00000000, /* rs300 */ + 0x00000808, /* rv280 */ + 0x00000808, /* r300 */ + 0x00000808, /* r350 */ + 0x00000808, /* rv350 */ + 0x00000808, /* rv380 */ + 0x00000808, /* r420 */ + 0x00000808, /* r423 */ + 0x00000808, /* rv410 */ + 0x00000000, /* rs400 */ + 0x00000000, /* rs480 */ +}; + +static void radeon_legacy_get_primary_dac_info_from_table(struct radeon_device *rdev, + struct radeon_encoder_primary_dac *p_dac) +{ + p_dac->ps2_pdac_adj = default_primarydac_adj[rdev->family]; + return; +} + +struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct + radeon_encoder + *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint16_t dac_info; + uint8_t rev, bg, dac; + struct radeon_encoder_primary_dac *p_dac = NULL; + int found = 0; + + p_dac = malloc(sizeof(struct radeon_encoder_primary_dac), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + if (!p_dac) + return NULL; + + /* check CRT table */ + dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); + if (dac_info) { + rev = RBIOS8(dac_info) & 0x3; + if (rev < 2) { + bg = RBIOS8(dac_info + 0x2) & 0xf; + dac = (RBIOS8(dac_info + 0x2) >> 4) & 0xf; + p_dac->ps2_pdac_adj = (bg << 8) | (dac); + } else { + bg = RBIOS8(dac_info + 0x2) & 0xf; + dac = RBIOS8(dac_info + 0x3) & 0xf; + p_dac->ps2_pdac_adj = (bg << 8) | (dac); + } + /* if the values are all zeros, use the table */ + if (p_dac->ps2_pdac_adj) + found = 1; + } + + if (!found) /* fallback to defaults */ + radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); + + return p_dac; +} + +enum radeon_tv_std +radeon_combios_get_tv_info(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + uint16_t tv_info; + enum radeon_tv_std tv_std = TV_STD_NTSC; + + tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); + if (tv_info) { + if (RBIOS8(tv_info + 6) == 'T') { + switch (RBIOS8(tv_info + 7) & 0xf) { + case 1: + tv_std = TV_STD_NTSC; + DRM_DEBUG_KMS("Default TV standard: NTSC\n"); + break; + case 2: + tv_std = TV_STD_PAL; + DRM_DEBUG_KMS("Default TV standard: PAL\n"); + break; + case 3: + tv_std = TV_STD_PAL_M; + DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); + break; + case 4: + tv_std = TV_STD_PAL_60; + DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); + break; + case 5: + tv_std = TV_STD_NTSC_J; + DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); + break; + case 6: + tv_std = TV_STD_SCART_PAL; + DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n"); + break; + default: + tv_std = TV_STD_NTSC; + DRM_DEBUG_KMS + ("Unknown TV standard; defaulting to NTSC\n"); + break; + } + + switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) { + case 0: + DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n"); + break; + case 1: + DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n"); + break; + case 2: + DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n"); + break; + case 3: + DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n"); + break; + default: + break; + } + } + } + return tv_std; +} + +static const uint32_t default_tvdac_adj[CHIP_LAST] = { + 0x00000000, /* r100 */ + 0x00280000, /* rv100 */ + 0x00000000, /* rs100 */ + 0x00880000, /* rv200 */ + 0x00000000, /* rs200 */ + 0x00000000, /* r200 */ + 0x00770000, /* rv250 */ + 0x00290000, /* rs300 */ + 0x00560000, /* rv280 */ + 0x00780000, /* r300 */ + 0x00770000, /* r350 */ + 0x00780000, /* rv350 */ + 0x00780000, /* rv380 */ + 0x01080000, /* r420 */ + 0x01080000, /* r423 */ + 0x01080000, /* rv410 */ + 0x00780000, /* rs400 */ + 0x00780000, /* rs480 */ +}; + +static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev, + struct radeon_encoder_tv_dac *tv_dac) +{ + tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family]; + if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250)) + tv_dac->ps2_tvdac_adj = 0x00880000; + tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; + tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; + return; +} + +struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct + radeon_encoder + *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint16_t dac_info; + uint8_t rev, bg, dac; + struct radeon_encoder_tv_dac *tv_dac = NULL; + int found = 0; + + tv_dac = malloc(sizeof(struct radeon_encoder_tv_dac), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!tv_dac) + return NULL; + + /* first check TV table */ + dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); + if (dac_info) { + rev = RBIOS8(dac_info + 0x3); + if (rev > 4) { + bg = RBIOS8(dac_info + 0xc) & 0xf; + dac = RBIOS8(dac_info + 0xd) & 0xf; + tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); + + bg = RBIOS8(dac_info + 0xe) & 0xf; + dac = RBIOS8(dac_info + 0xf) & 0xf; + tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); + + bg = RBIOS8(dac_info + 0x10) & 0xf; + dac = RBIOS8(dac_info + 0x11) & 0xf; + tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + /* if the values are all zeros, use the table */ + if (tv_dac->ps2_tvdac_adj) + found = 1; + } else if (rev > 1) { + bg = RBIOS8(dac_info + 0xc) & 0xf; + dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf; + tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); + + bg = RBIOS8(dac_info + 0xd) & 0xf; + dac = (RBIOS8(dac_info + 0xd) >> 4) & 0xf; + tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); + + bg = RBIOS8(dac_info + 0xe) & 0xf; + dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf; + tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + /* if the values are all zeros, use the table */ + if (tv_dac->ps2_tvdac_adj) + found = 1; + } + tv_dac->tv_std = radeon_combios_get_tv_info(rdev); + } + if (!found) { + /* then check CRT table */ + dac_info = + combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); + if (dac_info) { + rev = RBIOS8(dac_info) & 0x3; + if (rev < 2) { + bg = RBIOS8(dac_info + 0x3) & 0xf; + dac = (RBIOS8(dac_info + 0x3) >> 4) & 0xf; + tv_dac->ps2_tvdac_adj = + (bg << 16) | (dac << 20); + tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; + tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; + /* if the values are all zeros, use the table */ + if (tv_dac->ps2_tvdac_adj) + found = 1; + } else { + bg = RBIOS8(dac_info + 0x4) & 0xf; + dac = RBIOS8(dac_info + 0x5) & 0xf; + tv_dac->ps2_tvdac_adj = + (bg << 16) | (dac << 20); + tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; + tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; + /* if the values are all zeros, use the table */ + if (tv_dac->ps2_tvdac_adj) + found = 1; + } + } else { + DRM_INFO("No TV DAC info found in BIOS\n"); + } + } + + if (!found) /* fallback to defaults */ + radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac); + + return tv_dac; +} + +static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct + radeon_device + *rdev) +{ + struct radeon_encoder_lvds *lvds = NULL; + uint32_t fp_vert_stretch, fp_horz_stretch; + uint32_t ppll_div_sel, ppll_val; + uint32_t lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL); + + lvds = malloc(sizeof(struct radeon_encoder_lvds), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + if (!lvds) + return NULL; + + fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH); + fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH); + + /* These should be fail-safe defaults, fingers crossed */ + lvds->panel_pwr_delay = 200; + lvds->panel_vcc_delay = 2000; + + lvds->lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); + lvds->panel_digon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) & 0xf; + lvds->panel_blon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY2_SHIFT) & 0xf; + + if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) + lvds->native_mode.vdisplay = + ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >> + RADEON_VERT_PANEL_SHIFT) + 1; + else + lvds->native_mode.vdisplay = + (RREG32(RADEON_CRTC_V_TOTAL_DISP) >> 16) + 1; + + if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) + lvds->native_mode.hdisplay = + (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >> + RADEON_HORZ_PANEL_SHIFT) + 1) * 8; + else + lvds->native_mode.hdisplay = + ((RREG32(RADEON_CRTC_H_TOTAL_DISP) >> 16) + 1) * 8; + + if ((lvds->native_mode.hdisplay < 640) || + (lvds->native_mode.vdisplay < 480)) { + lvds->native_mode.hdisplay = 640; + lvds->native_mode.vdisplay = 480; + } + + ppll_div_sel = RREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + ppll_val = RREG32_PLL(RADEON_PPLL_DIV_0 + ppll_div_sel); + if ((ppll_val & 0x000707ff) == 0x1bb) + lvds->use_bios_dividers = false; + else { + lvds->panel_ref_divider = + RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; + lvds->panel_post_divider = (ppll_val >> 16) & 0x7; + lvds->panel_fb_divider = ppll_val & 0x7ff; + + if ((lvds->panel_ref_divider != 0) && + (lvds->panel_fb_divider > 3)) + lvds->use_bios_dividers = true; + } + lvds->panel_vcc_delay = 200; + + DRM_INFO("Panel info derived from registers\n"); + DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.hdisplay, + lvds->native_mode.vdisplay); + + return lvds; +} + +struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder + *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint16_t lcd_info; + uint32_t panel_setup; + char stmp[30]; + int tmp, i; + struct radeon_encoder_lvds *lvds = NULL; + + lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); + + if (lcd_info) { + lvds = malloc(sizeof(struct radeon_encoder_lvds), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + if (!lvds) + return NULL; + + for (i = 0; i < 24; i++) + stmp[i] = RBIOS8(lcd_info + i + 1); + stmp[24] = 0; + + DRM_INFO("Panel ID String: %s\n", stmp); + + lvds->native_mode.hdisplay = RBIOS16(lcd_info + 0x19); + lvds->native_mode.vdisplay = RBIOS16(lcd_info + 0x1b); + + DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.hdisplay, + lvds->native_mode.vdisplay); + + lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c); + lvds->panel_vcc_delay = min_t(u16, lvds->panel_vcc_delay, 2000); + + lvds->panel_pwr_delay = RBIOS8(lcd_info + 0x24); + lvds->panel_digon_delay = RBIOS16(lcd_info + 0x38) & 0xf; + lvds->panel_blon_delay = (RBIOS16(lcd_info + 0x38) >> 4) & 0xf; + + lvds->panel_ref_divider = RBIOS16(lcd_info + 0x2e); + lvds->panel_post_divider = RBIOS8(lcd_info + 0x30); + lvds->panel_fb_divider = RBIOS16(lcd_info + 0x31); + if ((lvds->panel_ref_divider != 0) && + (lvds->panel_fb_divider > 3)) + lvds->use_bios_dividers = true; + + panel_setup = RBIOS32(lcd_info + 0x39); + lvds->lvds_gen_cntl = 0xff00; + if (panel_setup & 0x1) + lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT; + + if ((panel_setup >> 4) & 0x1) + lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE; + + switch ((panel_setup >> 8) & 0x7) { + case 0: + lvds->lvds_gen_cntl |= RADEON_LVDS_NO_FM; + break; + case 1: + lvds->lvds_gen_cntl |= RADEON_LVDS_2_GREY; + break; + case 2: + lvds->lvds_gen_cntl |= RADEON_LVDS_4_GREY; + break; + default: + break; + } + + if ((panel_setup >> 16) & 0x1) + lvds->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW; + + if ((panel_setup >> 17) & 0x1) + lvds->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW; + + if ((panel_setup >> 18) & 0x1) + lvds->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW; + + if ((panel_setup >> 23) & 0x1) + lvds->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL; + + lvds->lvds_gen_cntl |= (panel_setup & 0xf0000000); + + for (i = 0; i < 32; i++) { + tmp = RBIOS16(lcd_info + 64 + i * 2); + if (tmp == 0) + break; + + if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && + (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) { + lvds->native_mode.htotal = lvds->native_mode.hdisplay + + (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; + lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + + (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; + lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + + (RBIOS8(tmp + 23) * 8); + + lvds->native_mode.vtotal = lvds->native_mode.vdisplay + + (RBIOS16(tmp + 24) - RBIOS16(tmp + 26)); + lvds->native_mode.vsync_start = lvds->native_mode.vdisplay + + ((RBIOS16(tmp + 28) & 0x7ff) - RBIOS16(tmp + 26)); + lvds->native_mode.vsync_end = lvds->native_mode.vsync_start + + ((RBIOS16(tmp + 28) & 0xf800) >> 11); + + lvds->native_mode.clock = RBIOS16(tmp + 9) * 10; + lvds->native_mode.flags = 0; + /* set crtc values */ + drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); + + } + } + } else { + DRM_INFO("No panel info found in BIOS\n"); + lvds = radeon_legacy_get_lvds_info_from_regs(rdev); + } + + if (lvds) + encoder->native_mode = lvds->native_mode; + return lvds; +} + +static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = { + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_R100 */ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_RV100 */ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RS100 */ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_RV200 */ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_RS200 */ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_R200 */ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /* CHIP_RV250 */ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RS300 */ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /* CHIP_RV280 */ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R300 */ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R350 */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RV350 */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RV380 */ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R420 */ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R423 */ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RV410 */ + { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, /* CHIP_RS400 */ + { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, /* CHIP_RS480 */ +}; + +bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + int i; + + for (i = 0; i < 4; i++) { + tmds->tmds_pll[i].value = + default_tmds_pll[rdev->family][i].value; + tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq; + } + + return true; +} + +bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint16_t tmds_info; + int i, n; + uint8_t ver; + + tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); + + if (tmds_info) { + ver = RBIOS8(tmds_info); + DRM_DEBUG_KMS("DFP table revision: %d\n", ver); + if (ver == 3) { + n = RBIOS8(tmds_info + 5) + 1; + if (n > 4) + n = 4; + for (i = 0; i < n; i++) { + tmds->tmds_pll[i].value = + RBIOS32(tmds_info + i * 10 + 0x08); + tmds->tmds_pll[i].freq = + RBIOS16(tmds_info + i * 10 + 0x10); + DRM_DEBUG_KMS("TMDS PLL From COMBIOS %u %x\n", + tmds->tmds_pll[i].freq, + tmds->tmds_pll[i].value); + } + } else if (ver == 4) { + int stride = 0; + n = RBIOS8(tmds_info + 5) + 1; + if (n > 4) + n = 4; + for (i = 0; i < n; i++) { + tmds->tmds_pll[i].value = + RBIOS32(tmds_info + stride + 0x08); + tmds->tmds_pll[i].freq = + RBIOS16(tmds_info + stride + 0x10); + if (i == 0) + stride += 10; + else + stride += 6; + DRM_DEBUG_KMS("TMDS PLL From COMBIOS %u %x\n", + tmds->tmds_pll[i].freq, + tmds->tmds_pll[i].value); + } + } + } else { + DRM_INFO("No TMDS info found in BIOS\n"); + return false; + } + return true; +} + +bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_i2c_bus_rec i2c_bus; + + /* default for macs */ + i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + + /* XXX some macs have duallink chips */ + switch (rdev->mode_info.connector_table) { + case CT_POWERBOOK_EXTERNAL: + case CT_MINI_EXTERNAL: + default: + tmds->dvo_chip = DVO_SIL164; + tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ + break; + } + + return true; +} + +bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint16_t offset; + uint8_t ver; + enum radeon_combios_ddc gpio; + struct radeon_i2c_bus_rec i2c_bus; + + tmds->i2c_bus = NULL; + if (rdev->flags & RADEON_IS_IGP) { + i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + tmds->dvo_chip = DVO_SIL164; + tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ + } else { + offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); + if (offset) { + ver = RBIOS8(offset); + DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver); + tmds->slave_addr = RBIOS8(offset + 4 + 2); + tmds->slave_addr >>= 1; /* 7 bit addressing */ + gpio = RBIOS8(offset + 4 + 3); + if (gpio == DDC_LCD) { + /* MM i2c */ + i2c_bus.valid = true; + i2c_bus.hw_capable = true; + i2c_bus.mm_i2c = true; + i2c_bus.i2c_id = 0xa0; + } else + i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + } + } + + if (!tmds->i2c_bus) { + DRM_INFO("No valid Ext TMDS info found in BIOS\n"); + return false; + } + + return true; +} + +bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_i2c_bus_rec ddc_i2c; + struct radeon_hpd hpd; + + rdev->mode_info.connector_table = radeon_connector_table; + if (rdev->mode_info.connector_table == CT_NONE) { +#ifdef CONFIG_PPC_PMAC + if (of_machine_is_compatible("PowerBook3,3")) { + /* powerbook with VGA */ + rdev->mode_info.connector_table = CT_POWERBOOK_VGA; + } else if (of_machine_is_compatible("PowerBook3,4") || + of_machine_is_compatible("PowerBook3,5")) { + /* powerbook with internal tmds */ + rdev->mode_info.connector_table = CT_POWERBOOK_INTERNAL; + } else if (of_machine_is_compatible("PowerBook5,1") || + of_machine_is_compatible("PowerBook5,2") || + of_machine_is_compatible("PowerBook5,3") || + of_machine_is_compatible("PowerBook5,4") || + of_machine_is_compatible("PowerBook5,5")) { + /* powerbook with external single link tmds (sil164) */ + rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; + } else if (of_machine_is_compatible("PowerBook5,6")) { + /* powerbook with external dual or single link tmds */ + rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; + } else if (of_machine_is_compatible("PowerBook5,7") || + of_machine_is_compatible("PowerBook5,8") || + of_machine_is_compatible("PowerBook5,9")) { + /* PowerBook6,2 ? */ + /* powerbook with external dual link tmds (sil1178?) */ + rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; + } else if (of_machine_is_compatible("PowerBook4,1") || + of_machine_is_compatible("PowerBook4,2") || + of_machine_is_compatible("PowerBook4,3") || + of_machine_is_compatible("PowerBook6,3") || + of_machine_is_compatible("PowerBook6,5") || + of_machine_is_compatible("PowerBook6,7")) { + /* ibook */ + rdev->mode_info.connector_table = CT_IBOOK; + } else if (of_machine_is_compatible("PowerMac3,5")) { + /* PowerMac G4 Silver radeon 7500 */ + rdev->mode_info.connector_table = CT_MAC_G4_SILVER; + } else if (of_machine_is_compatible("PowerMac4,4")) { + /* emac */ + rdev->mode_info.connector_table = CT_EMAC; + } else if (of_machine_is_compatible("PowerMac10,1")) { + /* mini with internal tmds */ + rdev->mode_info.connector_table = CT_MINI_INTERNAL; + } else if (of_machine_is_compatible("PowerMac10,2")) { + /* mini with external tmds */ + rdev->mode_info.connector_table = CT_MINI_EXTERNAL; + } else if (of_machine_is_compatible("PowerMac12,1")) { + /* PowerMac8,1 ? */ + /* imac g5 isight */ + rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; + } else if ((dev->pci_device == 0x4a48) && + (dev->pci_subvendor == 0x1002) && + (dev->pci_subdevice == 0x4a48)) { + /* Mac X800 */ + rdev->mode_info.connector_table = CT_MAC_X800; + } else if ((of_machine_is_compatible("PowerMac7,2") || + of_machine_is_compatible("PowerMac7,3")) && + (dev->pci_device == 0x4150) && + (dev->pci_subvendor == 0x1002) && + (dev->pci_subdevice == 0x4150)) { + /* Mac G5 tower 9600 */ + rdev->mode_info.connector_table = CT_MAC_G5_9600; + } else if ((dev->pci_device == 0x4c66) && + (dev->pci_subvendor == 0x1002) && + (dev->pci_subdevice == 0x4c66)) { + /* SAM440ep RV250 embedded board */ + rdev->mode_info.connector_table = CT_SAM440EP; + } else +#endif /* CONFIG_PPC_PMAC */ +#ifdef CONFIG_PPC64 + if (ASIC_IS_RN50(rdev)) + rdev->mode_info.connector_table = CT_RN50_POWER; + else +#endif + rdev->mode_info.connector_table = CT_GENERIC; + } + + switch (rdev->mode_info.connector_table) { + case CT_GENERIC: + DRM_INFO("Connector Table: %d (generic)\n", + rdev->mode_info.connector_table); + /* these are the most common settings */ + if (rdev->flags & RADEON_SINGLE_CRTC) { + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, + &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + } else if (rdev->flags & RADEON_IS_MOBILITY) { + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, + &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, + &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + } else { + /* DVI-I - tv dac, int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, + &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + } + + if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) { + /* TV - tv dac */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, + ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + } + break; + case CT_IBOOK: + DRM_INFO("Connector Table: %d (ibook)\n", + rdev->mode_info.connector_table); + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + /* VGA - TV DAC */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_POWERBOOK_EXTERNAL: + DRM_INFO("Connector Table: %d (powerbook external tmds)\n", + rdev->mode_info.connector_table); + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + /* DVI-I - primary dac, ext tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_2; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + /* XXX some are SL */ + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP2_SUPPORT | + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_POWERBOOK_INTERNAL: + DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", + rdev->mode_info.connector_table); + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + /* DVI-I - primary dac, int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_POWERBOOK_VGA: + DRM_INFO("Connector Table: %d (powerbook vga)\n", + rdev->mode_info.connector_table); + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_MINI_EXTERNAL: + DRM_INFO("Connector Table: %d (mini external tmds)\n", + rdev->mode_info.connector_table); + /* DVI-I - tv dac, ext tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + hpd.hpd = RADEON_HPD_2; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + /* XXX are any DL? */ + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP2_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_MINI_INTERNAL: + DRM_INFO("Connector Table: %d (mini internal tmds)\n", + rdev->mode_info.connector_table); + /* DVI-I - tv dac, int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_IMAC_G5_ISIGHT: + DRM_INFO("Connector Table: %d (imac g5 isight)\n", + rdev->mode_info.connector_table); + /* DVI-D - int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT, + DRM_MODE_CONNECTOR_DVID, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, + &hpd); + /* VGA - tv dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_EMAC: + DRM_INFO("Connector Table: %d (emac)\n", + rdev->mode_info.connector_table); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* VGA - tv dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_RN50_POWER: + DRM_INFO("Connector Table: %d (rn50-power)\n", + rdev->mode_info.connector_table); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + break; + case CT_MAC_X800: + DRM_INFO("Connector Table: %d (mac x800)\n", + rdev->mode_info.connector_table); + /* DVI - primary dac, internal tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* DVI - tv dac, dvo */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + hpd.hpd = RADEON_HPD_2; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP2_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, + &hpd); + break; + case CT_MAC_G5_9600: + DRM_INFO("Connector Table: %d (mac g5 9600)\n", + rdev->mode_info.connector_table); + /* DVI - tv dac, dvo */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP2_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* ADC - primary dac, internal tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_2; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_SAM440EP: + DRM_INFO("Connector Table: %d (SAM440ep embedded board)\n", + rdev->mode_info.connector_table); + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + /* DVI-I - secondary dac, int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 2, + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 3, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + case CT_MAC_G4_SILVER: + DRM_INFO("Connector Table: %d (mac g4 silver)\n", + rdev->mode_info.connector_table); + /* DVI-I - tv dac, int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + default: + DRM_INFO("Connector table: %d (invalid)\n", + rdev->mode_info.connector_table); + return false; + } + + radeon_link_encoder_connector(dev); + + return true; +} + +static bool radeon_apply_legacy_quirks(struct drm_device *dev, + int bios_index, + enum radeon_combios_connector + *legacy_connector, + struct radeon_i2c_bus_rec *ddc_i2c, + struct radeon_hpd *hpd) +{ + + /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, + one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ + if (dev->pci_device == 0x515e && + dev->pci_subvendor == 0x1014) { + if (*legacy_connector == CONNECTOR_CRT_LEGACY && + ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) + return false; + } + + /* X300 card with extra non-existent DVI port */ + if (dev->pci_device == 0x5B60 && + dev->pci_subvendor == 0x17af && + dev->pci_subdevice == 0x201e && bios_index == 2) { + if (*legacy_connector == CONNECTOR_DVI_I_LEGACY) + return false; + } + + return true; +} + +static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev) +{ + /* Acer 5102 has non-existent TV port */ + if (dev->pci_device == 0x5975 && + dev->pci_subvendor == 0x1025 && + dev->pci_subdevice == 0x009f) + return false; + + /* HP dc5750 has non-existent TV port */ + if (dev->pci_device == 0x5974 && + dev->pci_subvendor == 0x103c && + dev->pci_subdevice == 0x280a) + return false; + + /* MSI S270 has non-existent TV port */ + if (dev->pci_device == 0x5955 && + dev->pci_subvendor == 0x1462 && + dev->pci_subdevice == 0x0131) + return false; + + return true; +} + +static uint16_t combios_check_dl_dvi(struct drm_device *dev, int is_dvi_d) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t ext_tmds_info; + + if (rdev->flags & RADEON_IS_IGP) { + if (is_dvi_d) + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; + else + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; + } + ext_tmds_info = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); + if (ext_tmds_info) { + uint8_t rev = RBIOS8(ext_tmds_info); + uint8_t flags = RBIOS8(ext_tmds_info + 4 + 5); + if (rev >= 3) { + if (is_dvi_d) + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; + else + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; + } else { + if (flags & 1) { + if (is_dvi_d) + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; + else + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; + } + } + } + if (is_dvi_d) + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; + else + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; +} + +bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t conn_info, entry, devices; + uint16_t tmp, connector_object_id; + enum radeon_combios_ddc ddc_type; + enum radeon_combios_connector connector; + int i = 0; + struct radeon_i2c_bus_rec ddc_i2c; + struct radeon_hpd hpd; + + conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE); + if (conn_info) { + for (i = 0; i < 4; i++) { + entry = conn_info + 2 + i * 2; + + if (!RBIOS16(entry)) + break; + + tmp = RBIOS16(entry); + + connector = (tmp >> 12) & 0xf; + + ddc_type = (tmp >> 8) & 0xf; + if (ddc_type == 5) + ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev); + else + ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); + + switch (connector) { + case CONNECTOR_PROPRIETARY_LEGACY: + case CONNECTOR_DVI_I_LEGACY: + case CONNECTOR_DVI_D_LEGACY: + if ((tmp >> 4) & 0x1) + hpd.hpd = RADEON_HPD_2; + else + hpd.hpd = RADEON_HPD_1; + break; + default: + hpd.hpd = RADEON_HPD_NONE; + break; + } + + if (!radeon_apply_legacy_quirks(dev, i, &connector, + &ddc_i2c, &hpd)) + continue; + + switch (connector) { + case CONNECTOR_PROPRIETARY_LEGACY: + if ((tmp >> 4) & 0x1) + devices = ATOM_DEVICE_DFP2_SUPPORT; + else + devices = ATOM_DEVICE_DFP1_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, devices, 0), + devices); + radeon_add_legacy_connector(dev, i, devices, + legacy_connector_convert + [connector], + &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, + &hpd); + break; + case CONNECTOR_CRT_LEGACY: + if (tmp & 0x1) { + devices = ATOM_DEVICE_CRT2_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + } else { + devices = ATOM_DEVICE_CRT1_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + } + radeon_add_legacy_connector(dev, + i, + devices, + legacy_connector_convert + [connector], + &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + break; + case CONNECTOR_DVI_I_LEGACY: + devices = 0; + if (tmp & 0x1) { + devices |= ATOM_DEVICE_CRT2_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + } else { + devices |= ATOM_DEVICE_CRT1_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + } + /* RV100 board with external TDMS bit mis-set. + * Actually uses internal TMDS, clear the bit. + */ + if (dev->pci_device == 0x5159 && + dev->pci_subvendor == 0x1014 && + dev->pci_subdevice == 0x029A) { + tmp &= ~(1 << 4); + } + if ((tmp >> 4) & 0x1) { + devices |= ATOM_DEVICE_DFP2_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + connector_object_id = combios_check_dl_dvi(dev, 0); + } else { + devices |= ATOM_DEVICE_DFP1_SUPPORT; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; + } + radeon_add_legacy_connector(dev, + i, + devices, + legacy_connector_convert + [connector], + &ddc_i2c, + connector_object_id, + &hpd); + break; + case CONNECTOR_DVI_D_LEGACY: + if ((tmp >> 4) & 0x1) { + devices = ATOM_DEVICE_DFP2_SUPPORT; + connector_object_id = combios_check_dl_dvi(dev, 1); + } else { + devices = ATOM_DEVICE_DFP1_SUPPORT; + connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; + } + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, devices, 0), + devices); + radeon_add_legacy_connector(dev, i, devices, + legacy_connector_convert + [connector], + &ddc_i2c, + connector_object_id, + &hpd); + break; + case CONNECTOR_CTV_LEGACY: + case CONNECTOR_STV_LEGACY: + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, i, + ATOM_DEVICE_TV1_SUPPORT, + legacy_connector_convert + [connector], + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + default: + DRM_ERROR("Unknown connector type: %d\n", + connector); + continue; + } + + } + } else { + uint16_t tmds_info = + combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); + if (tmds_info) { + DRM_DEBUG_KMS("Found DFP table, assuming DVI connector\n"); + + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; + radeon_add_legacy_connector(dev, + 0, + ATOM_DEVICE_CRT1_SUPPORT | + ATOM_DEVICE_DFP1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + } else { + uint16_t crt_info = + combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); + DRM_DEBUG_KMS("Found CRT table, assuming VGA connector\n"); + if (crt_info) { + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_connector(dev, + 0, + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, + &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + } else { + DRM_DEBUG_KMS("No connector info found\n"); + return false; + } + } + } + + if (rdev->flags & RADEON_IS_MOBILITY || rdev->flags & RADEON_IS_IGP) { + uint16_t lcd_info = + combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); + if (lcd_info) { + uint16_t lcd_ddc_info = + combios_get_table_offset(dev, + COMBIOS_LCD_DDC_INFO_TABLE); + + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + + if (lcd_ddc_info) { + ddc_type = RBIOS8(lcd_ddc_info + 2); + switch (ddc_type) { + case DDC_LCD: + ddc_i2c = + combios_setup_i2c_bus(rdev, + DDC_LCD, + RBIOS32(lcd_ddc_info + 3), + RBIOS32(lcd_ddc_info + 7)); + radeon_i2c_add(rdev, &ddc_i2c, "LCD"); + break; + case DDC_GPIO: + ddc_i2c = + combios_setup_i2c_bus(rdev, + DDC_GPIO, + RBIOS32(lcd_ddc_info + 3), + RBIOS32(lcd_ddc_info + 7)); + radeon_i2c_add(rdev, &ddc_i2c, "LCD"); + break; + default: + ddc_i2c = + combios_setup_i2c_bus(rdev, ddc_type, 0, 0); + break; + } + DRM_DEBUG_KMS("LCD DDC Info Table found!\n"); + } else + ddc_i2c.valid = false; + + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_connector(dev, + 5, + ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, + &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + } + } + + /* check TV table */ + if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) { + uint32_t tv_info = + combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); + if (tv_info) { + if (RBIOS8(tv_info + 6) == 'T') { + if (radeon_apply_legacy_tv_quirks(dev)) { + hpd.hpd = RADEON_HPD_NONE; + ddc_i2c.valid = false; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum + (dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 6, + ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + } + } + } + } + + radeon_link_encoder_connector(dev); + + return true; +} + +static const char *thermal_controller_names[] = { + "NONE", + "lm63", + "adm1032", +}; + +void radeon_combios_get_power_modes(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + u16 offset, misc, misc2 = 0; + u8 rev, blocks, tmp; + int state_index = 0; + struct radeon_i2c_bus_rec i2c_bus; + + rdev->pm.default_power_state_index = -1; + + /* allocate 2 power states */ + rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * 2, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->pm.power_state) { + /* allocate 1 clock mode per state */ + rdev->pm.power_state[0].clock_info = + malloc(sizeof(struct radeon_pm_clock_info) * 1, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + rdev->pm.power_state[1].clock_info = + malloc(sizeof(struct radeon_pm_clock_info) * 1, + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rdev->pm.power_state[0].clock_info || + !rdev->pm.power_state[1].clock_info) + goto pm_failed; + } else + goto pm_failed; + + /* check for a thermal chip */ + offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE); + if (offset) { + u8 thermal_controller = 0, gpio = 0, i2c_addr = 0, clk_bit = 0, data_bit = 0; + + rev = RBIOS8(offset); + + if (rev == 0) { + thermal_controller = RBIOS8(offset + 3); + gpio = RBIOS8(offset + 4) & 0x3f; + i2c_addr = RBIOS8(offset + 5); + } else if (rev == 1) { + thermal_controller = RBIOS8(offset + 4); + gpio = RBIOS8(offset + 5) & 0x3f; + i2c_addr = RBIOS8(offset + 6); + } else if (rev == 2) { + thermal_controller = RBIOS8(offset + 4); + gpio = RBIOS8(offset + 5) & 0x3f; + i2c_addr = RBIOS8(offset + 6); + clk_bit = RBIOS8(offset + 0xa); + data_bit = RBIOS8(offset + 0xb); + } + if ((thermal_controller > 0) && (thermal_controller < 3)) { + DRM_INFO("Possible %s thermal controller at 0x%02x\n", + thermal_controller_names[thermal_controller], + i2c_addr >> 1); + if (gpio == DDC_LCD) { + /* MM i2c */ + i2c_bus.valid = true; + i2c_bus.hw_capable = true; + i2c_bus.mm_i2c = true; + i2c_bus.i2c_id = 0xa0; + } else if (gpio == DDC_GPIO) + i2c_bus = combios_setup_i2c_bus(rdev, gpio, 1 << clk_bit, 1 << data_bit); + else + i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { +#ifdef DUMBBELL_WIP + struct i2c_board_info info = { }; + const char *name = thermal_controller_names[thermal_controller]; + info.addr = i2c_addr >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); +#endif /* DUMBBELL_WIP */ + } + } + } else { + /* boards with a thermal chip, but no overdrive table */ + + /* Asus 9600xt has an f75375 on the monid bus */ + if ((dev->pci_device == 0x4152) && + (dev->pci_subvendor == 0x1043) && + (dev->pci_subdevice == 0xc002)) { + i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { +#ifdef DUMBBELL_WIP + struct i2c_board_info info = { }; + const char *name = "f75375"; + info.addr = 0x28; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); + DRM_INFO("Possible %s thermal controller at 0x%02x\n", + name, info.addr); +#endif /* DUMBBELL_WIP */ + } + } + } + + if (rdev->flags & RADEON_IS_MOBILITY) { + offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); + if (offset) { + rev = RBIOS8(offset); + blocks = RBIOS8(offset + 0x2); + /* power mode 0 tends to be the only valid one */ + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2); + rdev->pm.power_state[state_index].clock_info[0].sclk = RBIOS32(offset + 0x5 + 0x6); + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + goto default_mode; + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + misc = RBIOS16(offset + 0x5 + 0x0); + if (rev > 4) + misc2 = RBIOS16(offset + 0x5 + 0xe); + rdev->pm.power_state[state_index].misc = misc; + rdev->pm.power_state[state_index].misc2 = misc2; + if (misc & 0x4) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO; + if (misc & 0x8) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = true; + if (rev < 6) { + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg = + RBIOS16(offset + 0x5 + 0xb) * 4; + tmp = RBIOS8(offset + 0x5 + 0xd); + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp); + } else { + u8 entries = RBIOS8(offset + 0x5 + 0xb); + u16 voltage_table_offset = RBIOS16(offset + 0x5 + 0xc); + if (entries && voltage_table_offset) { + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg = + RBIOS16(voltage_table_offset) * 4; + tmp = RBIOS8(voltage_table_offset + 0x2); + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp); + } else + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = false; + } + switch ((misc2 & 0x700) >> 8) { + case 0: + default: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 0; + break; + case 1: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 33; + break; + case 2: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 66; + break; + case 3: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 99; + break; + case 4: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 132; + break; + } + } else + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + if (rev > 6) + rdev->pm.power_state[state_index].pcie_lanes = + RBIOS8(offset + 0x5 + 0x10); + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + state_index++; + } else { + /* XXX figure out some good default low power mode for mobility cards w/out power tables */ + } + } else { + /* XXX figure out some good default low power mode for desktop cards */ + } + +default_mode: + /* add the default mode */ + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; + rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0]; + if ((state_index > 0) && + (rdev->pm.power_state[0].clock_info[0].voltage.type == VOLTAGE_GPIO)) + rdev->pm.power_state[state_index].clock_info[0].voltage = + rdev->pm.power_state[0].clock_info[0].voltage; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + rdev->pm.power_state[state_index].pcie_lanes = 16; + rdev->pm.power_state[state_index].flags = 0; + rdev->pm.default_power_state_index = state_index; + rdev->pm.num_power_states = state_index + 1; + + rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.current_clock_mode_index = 0; + return; + +pm_failed: + rdev->pm.default_power_state_index = state_index; + rdev->pm.num_power_states = 0; + + rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.current_clock_mode_index = 0; +} + +void radeon_external_tmds_setup(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; + + if (!tmds) + return; + + switch (tmds->dvo_chip) { + case DVO_SIL164: + /* sil 164 */ + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x08, 0x30); + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x09, 0x00); + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x0a, 0x90); + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x0c, 0x89); + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x08, 0x3b); + break; + case DVO_SIL1178: + /* sil 1178 - untested */ + /* + * 0x0f, 0x44 + * 0x0f, 0x4c + * 0x0e, 0x01 + * 0x0a, 0x80 + * 0x09, 0x30 + * 0x0c, 0xc9 + * 0x0d, 0x70 + * 0x08, 0x32 + * 0x08, 0x33 + */ + break; + default: + break; + } + +} + +bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint16_t offset; + uint8_t blocks, slave_addr, rev; + uint32_t index, id; + uint32_t reg, val, and_mask, or_mask; + struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; + + if (!tmds) + return false; + + if (rdev->flags & RADEON_IS_IGP) { + offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_ON_TABLE); + rev = RBIOS8(offset); + if (offset) { + rev = RBIOS8(offset); + if (rev > 1) { + blocks = RBIOS8(offset + 3); + index = offset + 4; + while (blocks > 0) { + id = RBIOS16(index); + index += 2; + switch (id >> 13) { + case 0: + reg = (id & 0x1fff) * 4; + val = RBIOS32(index); + index += 4; + WREG32(reg, val); + break; + case 2: + reg = (id & 0x1fff) * 4; + and_mask = RBIOS32(index); + index += 4; + or_mask = RBIOS32(index); + index += 4; + val = RREG32(reg); + val = (val & and_mask) | or_mask; + WREG32(reg, val); + break; + case 3: + val = RBIOS16(index); + index += 2; + DRM_UDELAY(val); + break; + case 4: + val = RBIOS16(index); + index += 2; + DRM_MDELAY(val); + break; + case 6: + slave_addr = id & 0xff; + slave_addr >>= 1; /* 7 bit addressing */ + index++; + reg = RBIOS8(index); + index++; + val = RBIOS8(index); + index++; + radeon_i2c_put_byte(tmds->i2c_bus, + slave_addr, + reg, val); + break; + default: + DRM_ERROR("Unknown id %d\n", id >> 13); + break; + } + blocks--; + } + return true; + } + } + } else { + offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); + if (offset) { + index = offset + 10; + id = RBIOS16(index); + while (id != 0xffff) { + index += 2; + switch (id >> 13) { + case 0: + reg = (id & 0x1fff) * 4; + val = RBIOS32(index); + WREG32(reg, val); + break; + case 2: + reg = (id & 0x1fff) * 4; + and_mask = RBIOS32(index); + index += 4; + or_mask = RBIOS32(index); + index += 4; + val = RREG32(reg); + val = (val & and_mask) | or_mask; + WREG32(reg, val); + break; + case 4: + val = RBIOS16(index); + index += 2; + DRM_UDELAY(val); + break; + case 5: + reg = id & 0x1fff; + and_mask = RBIOS32(index); + index += 4; + or_mask = RBIOS32(index); + index += 4; + val = RREG32_PLL(reg); + val = (val & and_mask) | or_mask; + WREG32_PLL(reg, val); + break; + case 6: + reg = id & 0x1fff; + val = RBIOS8(index); + index += 1; + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + reg, val); + break; + default: + DRM_ERROR("Unknown id %d\n", id >> 13); + break; + } + id = RBIOS16(index); + } + return true; + } + } + return false; +} + +static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset) +{ + struct radeon_device *rdev = dev->dev_private; + + if (offset) { + while (RBIOS16(offset)) { + uint16_t cmd = ((RBIOS16(offset) & 0xe000) >> 13); + uint32_t addr = (RBIOS16(offset) & 0x1fff); + uint32_t val, and_mask, or_mask; + uint32_t tmp; + + offset += 2; + switch (cmd) { + case 0: + val = RBIOS32(offset); + offset += 4; + WREG32(addr, val); + break; + case 1: + val = RBIOS32(offset); + offset += 4; + WREG32(addr, val); + break; + case 2: + and_mask = RBIOS32(offset); + offset += 4; + or_mask = RBIOS32(offset); + offset += 4; + tmp = RREG32(addr); + tmp &= and_mask; + tmp |= or_mask; + WREG32(addr, tmp); + break; + case 3: + and_mask = RBIOS32(offset); + offset += 4; + or_mask = RBIOS32(offset); + offset += 4; + tmp = RREG32(addr); + tmp &= and_mask; + tmp |= or_mask; + WREG32(addr, tmp); + break; + case 4: + val = RBIOS16(offset); + offset += 2; + DRM_UDELAY(val); + break; + case 5: + val = RBIOS16(offset); + offset += 2; + switch (addr) { + case 8: + while (val--) { + if (! + (RREG32_PLL + (RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + case 9: + while (val--) { + if ((RREG32(RADEON_MC_STATUS) & + RADEON_MC_IDLE)) + break; + } + break; + default: + break; + } + break; + default: + break; + } + } + } +} + +static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) +{ + struct radeon_device *rdev = dev->dev_private; + + if (offset) { + while (RBIOS8(offset)) { + uint8_t cmd = ((RBIOS8(offset) & 0xc0) >> 6); + uint8_t addr = (RBIOS8(offset) & 0x3f); + uint32_t val, shift, tmp; + uint32_t and_mask, or_mask; + + offset++; + switch (cmd) { + case 0: + val = RBIOS32(offset); + offset += 4; + WREG32_PLL(addr, val); + break; + case 1: + shift = RBIOS8(offset) * 8; + offset++; + and_mask = RBIOS8(offset) << shift; + and_mask |= ~(0xff << shift); + offset++; + or_mask = RBIOS8(offset) << shift; + offset++; + tmp = RREG32_PLL(addr); + tmp &= and_mask; + tmp |= or_mask; + WREG32_PLL(addr, tmp); + break; + case 2: + case 3: + tmp = 1000; + switch (addr) { + case 1: + DRM_UDELAY(150); + break; + case 2: + DRM_MDELAY(1); + break; + case 3: + while (tmp--) { + if (! + (RREG32_PLL + (RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + case 4: + while (tmp--) { + if (RREG32_PLL + (RADEON_CLK_PWRMGT_CNTL) & + RADEON_DLL_READY) + break; + } + break; + case 5: + tmp = + RREG32_PLL(RADEON_CLK_PWRMGT_CNTL); + if (tmp & RADEON_CG_NO1_DEBUG_0) { +#if 0 + uint32_t mclk_cntl = + RREG32_PLL + (RADEON_MCLK_CNTL); + mclk_cntl &= 0xffff0000; + /*mclk_cntl |= 0x00001111;*//* ??? */ + WREG32_PLL(RADEON_MCLK_CNTL, + mclk_cntl); + DRM_MDELAY(10); +#endif + WREG32_PLL + (RADEON_CLK_PWRMGT_CNTL, + tmp & + ~RADEON_CG_NO1_DEBUG_0); + DRM_MDELAY(10); + } + break; + default: + break; + } + break; + default: + break; + } + } + } +} + +static void combios_parse_ram_reset_table(struct drm_device *dev, + uint16_t offset) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + if (offset) { + uint8_t val = RBIOS8(offset); + while (val != 0xff) { + offset++; + + if (val == 0x0f) { + uint32_t channel_complete_mask; + + if (ASIC_IS_R300(rdev)) + channel_complete_mask = + R300_MEM_PWRUP_COMPLETE; + else + channel_complete_mask = + RADEON_MEM_PWRUP_COMPLETE; + tmp = 20000; + while (tmp--) { + if ((RREG32(RADEON_MEM_STR_CNTL) & + channel_complete_mask) == + channel_complete_mask) + break; + } + } else { + uint32_t or_mask = RBIOS16(offset); + offset += 2; + + tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG); + tmp &= RADEON_SDRAM_MODE_MASK; + tmp |= or_mask; + WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp); + + or_mask = val << 24; + tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG); + tmp &= RADEON_B3MEM_RESET_MASK; + tmp |= or_mask; + WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp); + } + val = RBIOS8(offset); + } + } +} + +static uint32_t combios_detect_ram(struct drm_device *dev, int ram, + int mem_addr_mapping) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t mem_cntl; + uint32_t mem_size; + uint32_t addr = 0; + + mem_cntl = RREG32(RADEON_MEM_CNTL); + if (mem_cntl & RV100_HALF_MODE) + ram /= 2; + mem_size = ram; + mem_cntl &= ~(0xff << 8); + mem_cntl |= (mem_addr_mapping & 0xff) << 8; + WREG32(RADEON_MEM_CNTL, mem_cntl); + RREG32(RADEON_MEM_CNTL); + + /* sdram reset ? */ + + /* something like this???? */ + while (ram--) { + addr = ram * 1024 * 1024; + /* write to each page */ + WREG32_IDX((addr) | RADEON_MM_APER, 0xdeadbeef); + /* read back and verify */ + if (RREG32_IDX((addr) | RADEON_MM_APER) != 0xdeadbeef) + return 0; + } + + return mem_size; +} + +static void combios_write_ram_size(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + uint8_t rev; + uint16_t offset; + uint32_t mem_size = 0; + uint32_t mem_cntl = 0; + + /* should do something smarter here I guess... */ + if (rdev->flags & RADEON_IS_IGP) + return; + + /* first check detected mem table */ + offset = combios_get_table_offset(dev, COMBIOS_DETECTED_MEM_TABLE); + if (offset) { + rev = RBIOS8(offset); + if (rev < 3) { + mem_cntl = RBIOS32(offset + 1); + mem_size = RBIOS16(offset + 5); + if ((rdev->family < CHIP_R200) && + !ASIC_IS_RN50(rdev)) + WREG32(RADEON_MEM_CNTL, mem_cntl); + } + } + + if (!mem_size) { + offset = + combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE); + if (offset) { + rev = RBIOS8(offset - 1); + if (rev < 1) { + if ((rdev->family < CHIP_R200) + && !ASIC_IS_RN50(rdev)) { + int ram = 0; + int mem_addr_mapping = 0; + + while (RBIOS8(offset)) { + ram = RBIOS8(offset); + mem_addr_mapping = + RBIOS8(offset + 1); + if (mem_addr_mapping != 0x25) + ram *= 2; + mem_size = + combios_detect_ram(dev, ram, + mem_addr_mapping); + if (mem_size) + break; + offset += 2; + } + } else + mem_size = RBIOS8(offset); + } else { + mem_size = RBIOS8(offset); + mem_size *= 2; /* convert to MB */ + } + } + } + + mem_size *= (1024 * 1024); /* convert to bytes */ + WREG32(RADEON_CONFIG_MEMSIZE, mem_size); +} + +void radeon_combios_asic_init(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + uint16_t table; + + /* port hardcoded mac stuff from radeonfb */ + if (rdev->bios == NULL) + return; + + /* ASIC INIT 1 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_1_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* PLL INIT */ + table = combios_get_table_offset(dev, COMBIOS_PLL_INIT_TABLE); + if (table) + combios_parse_pll_table(dev, table); + + /* ASIC INIT 2 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_2_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + if (!(rdev->flags & RADEON_IS_IGP)) { + /* ASIC INIT 4 */ + table = + combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* RAM RESET */ + table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE); + if (table) + combios_parse_ram_reset_table(dev, table); + + /* ASIC INIT 3 */ + table = + combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* write CONFIG_MEMSIZE */ + combios_write_ram_size(dev); + } + + /* quirk for rs4xx HP nx6125 laptop to make it resume + * - it hangs on resume inside the dynclk 1 table. + */ + if (rdev->family == CHIP_RS480 && + dev->pci_subvendor == 0x103c && + dev->pci_subdevice == 0x308b) + return; + + /* quirk for rs4xx HP dv5000 laptop to make it resume + * - it hangs on resume inside the dynclk 1 table. + */ + if (rdev->family == CHIP_RS480 && + dev->pci_subvendor == 0x103c && + dev->pci_subdevice == 0x30a4) + return; + + /* quirk for rs4xx Compaq Presario V5245EU laptop to make it resume + * - it hangs on resume inside the dynclk 1 table. + */ + if (rdev->family == CHIP_RS480 && + dev->pci_subvendor == 0x103c && + dev->pci_subdevice == 0x30ae) + return; + + /* DYN CLK 1 */ + table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); + if (table) + combios_parse_pll_table(dev, table); + +} + +void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t bios_0_scratch, bios_6_scratch, bios_7_scratch; + + bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); + bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); + bios_7_scratch = RREG32(RADEON_BIOS_7_SCRATCH); + + /* let the bios control the backlight */ + bios_0_scratch &= ~RADEON_DRIVER_BRIGHTNESS_EN; + + /* tell the bios not to handle mode switching */ + bios_6_scratch |= (RADEON_DISPLAY_SWITCHING_DIS | + RADEON_ACC_MODE_CHANGE); + + /* tell the bios a driver is loaded */ + bios_7_scratch |= RADEON_DRV_LOADED; + + WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch); + WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); + WREG32(RADEON_BIOS_7_SCRATCH, bios_7_scratch); +} + +void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t bios_6_scratch; + + bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); + + if (lock) + bios_6_scratch |= RADEON_DRIVER_CRITICAL; + else + bios_6_scratch &= ~RADEON_DRIVER_CRITICAL; + + WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); +} + +void +radeon_combios_connected_scratch_regs(struct drm_connector *connector, + struct drm_encoder *encoder, + bool connected) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = + to_radeon_connector(connector); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_4_scratch = RREG32(RADEON_BIOS_4_SCRATCH); + uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH); + + if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("TV1 connected\n"); + /* fix me */ + bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO; + /*save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP; */ + bios_5_scratch |= RADEON_TV1_ON; + bios_5_scratch |= RADEON_ACC_REQ_TV1; + } else { + DRM_DEBUG_KMS("TV1 disconnected\n"); + bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK; + bios_5_scratch &= ~RADEON_TV1_ON; + bios_5_scratch &= ~RADEON_ACC_REQ_TV1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("LCD1 connected\n"); + bios_4_scratch |= RADEON_LCD1_ATTACHED; + bios_5_scratch |= RADEON_LCD1_ON; + bios_5_scratch |= RADEON_ACC_REQ_LCD1; + } else { + DRM_DEBUG_KMS("LCD1 disconnected\n"); + bios_4_scratch &= ~RADEON_LCD1_ATTACHED; + bios_5_scratch &= ~RADEON_LCD1_ON; + bios_5_scratch &= ~RADEON_ACC_REQ_LCD1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("CRT1 connected\n"); + bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR; + bios_5_scratch |= RADEON_CRT1_ON; + bios_5_scratch |= RADEON_ACC_REQ_CRT1; + } else { + DRM_DEBUG_KMS("CRT1 disconnected\n"); + bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK; + bios_5_scratch &= ~RADEON_CRT1_ON; + bios_5_scratch &= ~RADEON_ACC_REQ_CRT1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("CRT2 connected\n"); + bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR; + bios_5_scratch |= RADEON_CRT2_ON; + bios_5_scratch |= RADEON_ACC_REQ_CRT2; + } else { + DRM_DEBUG_KMS("CRT2 disconnected\n"); + bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK; + bios_5_scratch &= ~RADEON_CRT2_ON; + bios_5_scratch &= ~RADEON_ACC_REQ_CRT2; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP1 connected\n"); + bios_4_scratch |= RADEON_DFP1_ATTACHED; + bios_5_scratch |= RADEON_DFP1_ON; + bios_5_scratch |= RADEON_ACC_REQ_DFP1; + } else { + DRM_DEBUG_KMS("DFP1 disconnected\n"); + bios_4_scratch &= ~RADEON_DFP1_ATTACHED; + bios_5_scratch &= ~RADEON_DFP1_ON; + bios_5_scratch &= ~RADEON_ACC_REQ_DFP1; + } + } + if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) && + (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) { + if (connected) { + DRM_DEBUG_KMS("DFP2 connected\n"); + bios_4_scratch |= RADEON_DFP2_ATTACHED; + bios_5_scratch |= RADEON_DFP2_ON; + bios_5_scratch |= RADEON_ACC_REQ_DFP2; + } else { + DRM_DEBUG_KMS("DFP2 disconnected\n"); + bios_4_scratch &= ~RADEON_DFP2_ATTACHED; + bios_5_scratch &= ~RADEON_DFP2_ON; + bios_5_scratch &= ~RADEON_ACC_REQ_DFP2; + } + } + WREG32(RADEON_BIOS_4_SCRATCH, bios_4_scratch); + WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch); +} + +void +radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH); + + if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { + bios_5_scratch &= ~RADEON_TV1_CRTC_MASK; + bios_5_scratch |= (crtc << RADEON_TV1_CRTC_SHIFT); + } + if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { + bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK; + bios_5_scratch |= (crtc << RADEON_CRT1_CRTC_SHIFT); + } + if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { + bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK; + bios_5_scratch |= (crtc << RADEON_CRT2_CRTC_SHIFT); + } + if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { + bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK; + bios_5_scratch |= (crtc << RADEON_LCD1_CRTC_SHIFT); + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { + bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK; + bios_5_scratch |= (crtc << RADEON_DFP1_CRTC_SHIFT); + } + if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { + bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK; + bios_5_scratch |= (crtc << RADEON_DFP2_CRTC_SHIFT); + } + WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch); +} + +void +radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); + + if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { + if (on) + bios_6_scratch |= RADEON_TV_DPMS_ON; + else + bios_6_scratch &= ~RADEON_TV_DPMS_ON; + } + if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { + if (on) + bios_6_scratch |= RADEON_CRT_DPMS_ON; + else + bios_6_scratch &= ~RADEON_CRT_DPMS_ON; + } + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + if (on) + bios_6_scratch |= RADEON_LCD_DPMS_ON; + else + bios_6_scratch &= ~RADEON_LCD_DPMS_ON; + } + if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (on) + bios_6_scratch |= RADEON_DFP_DPMS_ON; + else + bios_6_scratch &= ~RADEON_DFP_DPMS_ON; + } + WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); +} diff --git a/sys/dev/drm2/radeon/radeon_connectors.c b/sys/dev/drm2/radeon/radeon_connectors.c new file mode 100644 index 00000000000..57d7c269028 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_connectors.c @@ -0,0 +1,2040 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include "radeon.h" +#include "atom.h" + +void radeon_connector_hotplug(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + /* bail if the connector does not have hpd pin, e.g., + * VGA, TV, etc. + */ + if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) + return; + + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + + /* if the connector is already off, don't turn it back on */ + if (connector->dpms != DRM_MODE_DPMS_ON) + return; + + /* just deal with DP (not eDP) here. */ + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + /* if existing sink type was not DP no need to retrain */ + if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) + return; + + /* first get sink type as it may be reset after (un)plug */ + dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); + /* don't do anything if sink is not display port, i.e., + * passive dp->(dvi|hdmi) adaptor + */ + if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + int saved_dpms = connector->dpms; + /* Only turn off the display if it's physically disconnected */ + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } else if (radeon_dp_needs_link_train(radeon_connector)) { + /* set it to OFF so that drm_helper_connector_dpms() + * won't return immediately since the current state + * is ON at this point. + */ + connector->dpms = DRM_MODE_DPMS_OFF; + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + connector->dpms = saved_dpms; + } + } +} + +static void radeon_property_change_mode(struct drm_encoder *encoder) +{ + struct drm_crtc *crtc = encoder->crtc; + + if (crtc && crtc->enabled) { + drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, crtc->fb); + } +} + +int radeon_get_monitor_bpc(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector; + int bpc = 8; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_HDMIB: + if (radeon_connector->use_digital) { + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (connector->display_info.bpc) + bpc = connector->display_info.bpc; + } + } + break; + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (connector->display_info.bpc) + bpc = connector->display_info.bpc; + } + break; + case DRM_MODE_CONNECTOR_DisplayPort: + dig_connector = radeon_connector->con_priv; + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) || + drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (connector->display_info.bpc) + bpc = connector->display_info.bpc; + } + break; + case DRM_MODE_CONNECTOR_eDP: + case DRM_MODE_CONNECTOR_LVDS: + if (connector->display_info.bpc) + bpc = connector->display_info.bpc; + else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + struct drm_encoder *encoder = connector_funcs->best_encoder(connector); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + + if (dig->lcd_misc & ATOM_PANEL_MISC_V13_6BIT_PER_COLOR) + bpc = 6; + else if (dig->lcd_misc & ATOM_PANEL_MISC_V13_8BIT_PER_COLOR) + bpc = 8; + } + break; + } + return bpc; +} + +static void +radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *best_encoder = NULL; + struct drm_encoder *encoder = NULL; + struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; + struct drm_mode_object *obj; + bool connected; + int i; + + best_encoder = connector_funcs->best_encoder(connector); + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, + connector->encoder_ids[i], + DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + + if ((encoder == best_encoder) && (status == connector_status_connected)) + connected = true; + else + connected = false; + + if (rdev->is_atom_bios) + radeon_atombios_connected_scratch_regs(connector, encoder, connected); + else + radeon_combios_connected_scratch_regs(connector, encoder, connected); + + } +} + +static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type) +{ + struct drm_mode_object *obj; + struct drm_encoder *encoder; + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + if (encoder->encoder_type == encoder_type) + return encoder; + } + return NULL; +} + +static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + struct drm_mode_object *obj; + struct drm_encoder *encoder; + + /* pick the encoder ids */ + if (enc_id) { + obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) + return NULL; + encoder = obj_to_encoder(obj); + return encoder; + } + return NULL; +} + +/* + * radeon_connector_analog_encoder_conflict_solve + * - search for other connectors sharing this encoder + * if priority is true, then set them disconnected if this is connected + * if priority is false, set us disconnected if they are connected + */ +static enum drm_connector_status +radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector, + struct drm_encoder *encoder, + enum drm_connector_status current_status, + bool priority) +{ + struct drm_device *dev = connector->dev; + struct drm_connector *conflict; + struct radeon_connector *radeon_conflict; + int i; + + list_for_each_entry(conflict, &dev->mode_config.connector_list, head) { + if (conflict == connector) + continue; + + radeon_conflict = to_radeon_connector(conflict); + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (conflict->encoder_ids[i] == 0) + break; + + /* if the IDs match */ + if (conflict->encoder_ids[i] == encoder->base.id) { + if (conflict->status != connector_status_connected) + continue; + + if (radeon_conflict->use_digital) + continue; + + if (priority == true) { + DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); + DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(connector)); + conflict->status = connector_status_disconnected; + radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); + } else { + DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); + DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(conflict)); + current_status = connector_status_disconnected; + } + break; + } + } + } + return current_status; + +} + +static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + if (native_mode->hdisplay != 0 && + native_mode->vdisplay != 0 && + native_mode->clock != 0) { + mode = drm_mode_duplicate(dev, native_mode); + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + drm_mode_set_name(mode); + + DRM_DEBUG_KMS("Adding native panel mode %s\n", mode->name); + } else if (native_mode->hdisplay != 0 && + native_mode->vdisplay != 0) { + /* mac laptops without an edid */ + /* Note that this is not necessarily the exact panel mode, + * but an approximation based on the cvt formula. For these + * systems we should ideally read the mode info out of the + * registers or add a mode table, but this works and is much + * simpler. + */ + mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false); + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name); + } + return mode; +} + +static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + int i; + struct mode_size { + int w; + int h; + } common_modes[17] = { + { 640, 480}, + { 720, 480}, + { 800, 600}, + { 848, 480}, + {1024, 768}, + {1152, 768}, + {1280, 720}, + {1280, 800}, + {1280, 854}, + {1280, 960}, + {1280, 1024}, + {1440, 900}, + {1400, 1050}, + {1680, 1050}, + {1600, 1200}, + {1920, 1080}, + {1920, 1200} + }; + + for (i = 0; i < 17; i++) { + if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { + if (common_modes[i].w > 1024 || + common_modes[i].h > 768) + continue; + } + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + if (common_modes[i].w > native_mode->hdisplay || + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; + } + if (common_modes[i].w < 320 || common_modes[i].h < 200) + continue; + + mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); + drm_mode_probed_add(connector, mode); + } +} + +static int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + + if (property == rdev->mode_info.coherent_mode_property) { + struct radeon_encoder_atom_dig *dig; + bool new_coherent_mode; + + /* need to find digital encoder on connector */ + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + + if (!radeon_encoder->enc_priv) + return 0; + + dig = radeon_encoder->enc_priv; + new_coherent_mode = val ? true : false; + if (dig->coherent_mode != new_coherent_mode) { + dig->coherent_mode = new_coherent_mode; + radeon_property_change_mode(&radeon_encoder->base); + } + } + + if (property == rdev->mode_info.underscan_property) { + /* need to find digital encoder on connector */ + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->underscan_type != val) { + radeon_encoder->underscan_type = val; + radeon_property_change_mode(&radeon_encoder->base); + } + } + + if (property == rdev->mode_info.underscan_hborder_property) { + /* need to find digital encoder on connector */ + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->underscan_hborder != val) { + radeon_encoder->underscan_hborder = val; + radeon_property_change_mode(&radeon_encoder->base); + } + } + + if (property == rdev->mode_info.underscan_vborder_property) { + /* need to find digital encoder on connector */ + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->underscan_vborder != val) { + radeon_encoder->underscan_vborder = val; + radeon_property_change_mode(&radeon_encoder->base); + } + } + + if (property == rdev->mode_info.tv_std_property) { + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); + if (!encoder) { + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC); + } + + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + if (!radeon_encoder->enc_priv) + return 0; + if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) { + struct radeon_encoder_atom_dac *dac_int; + dac_int = radeon_encoder->enc_priv; + dac_int->tv_std = val; + } else { + struct radeon_encoder_tv_dac *dac_int; + dac_int = radeon_encoder->enc_priv; + dac_int->tv_std = val; + } + radeon_property_change_mode(&radeon_encoder->base); + } + + if (property == rdev->mode_info.load_detect_property) { + struct radeon_connector *radeon_connector = + to_radeon_connector(connector); + + if (val == 0) + radeon_connector->dac_load_detect = false; + else + radeon_connector->dac_load_detect = true; + } + + if (property == rdev->mode_info.tmds_pll_property) { + struct radeon_encoder_int_tmds *tmds = NULL; + bool ret = false; + /* need to find digital encoder on connector */ + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + + tmds = radeon_encoder->enc_priv; + if (!tmds) + return 0; + + if (val == 0) { + if (rdev->is_atom_bios) + ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds); + else + ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds); + } + if (val == 1 || ret == false) { + radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds); + } + radeon_property_change_mode(&radeon_encoder->base); + } + + return 0; +} + +static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + struct drm_display_mode *t, *mode; + + /* If the EDID preferred mode doesn't match the native mode, use it */ + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + if (mode->hdisplay != native_mode->hdisplay || + mode->vdisplay != native_mode->vdisplay) + memcpy(native_mode, mode, sizeof(*mode)); + } + } + + /* Try to get native mode details from EDID if necessary */ + if (!native_mode->clock) { + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + if (mode->hdisplay == native_mode->hdisplay && + mode->vdisplay == native_mode->vdisplay) { + *native_mode = *mode; + drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V); + DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n"); + break; + } + } + } + + if (!native_mode->clock) { + DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n"); + radeon_encoder->rmx_type = RMX_OFF; + } +} + +static int radeon_lvds_get_modes(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *encoder; + int ret = 0; + struct drm_display_mode *mode; + + if (radeon_connector->ddc_bus) { + ret = radeon_ddc_get_modes(radeon_connector); + if (ret > 0) { + encoder = radeon_best_single_encoder(connector); + if (encoder) { + radeon_fixup_lvds_native_mode(encoder, connector); + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + } + return ret; + } + } + + encoder = radeon_best_single_encoder(connector); + if (!encoder) + return 0; + + /* we have no EDID modes */ + mode = radeon_fp_native_mode(encoder); + if (mode) { + ret = 1; + drm_mode_probed_add(connector, mode); + /* add the width/height from vbios tables if available */ + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + } + + return ret; +} + +static int radeon_lvds_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + + if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) + return MODE_PANEL; + + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + /* AVIVO hardware supports downscaling modes larger than the panel + * to the panel size, but I'm not sure this is desirable. + */ + if ((mode->hdisplay > native_mode->hdisplay) || + (mode->vdisplay > native_mode->vdisplay)) + return MODE_PANEL; + + /* if scaling is disabled, block non-native modes */ + if (radeon_encoder->rmx_type == RMX_OFF) { + if ((mode->hdisplay != native_mode->hdisplay) || + (mode->vdisplay != native_mode->vdisplay)) + return MODE_PANEL; + } + } + + return MODE_OK; +} + +static enum drm_connector_status +radeon_lvds_detect(struct drm_connector *connector, bool force) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + enum drm_connector_status ret = connector_status_disconnected; + + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + /* check if panel is valid */ + if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) + ret = connector_status_connected; + + } + + /* check for edid as well */ + if (radeon_connector->edid) + ret = connector_status_connected; + else { + if (radeon_connector->ddc_bus) { + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + radeon_connector->ddc_bus->adapter); + if (radeon_connector->edid) + ret = connector_status_connected; + } + } + /* check acpi lid status ??? */ + + radeon_connector_update_scratch_regs(connector, ret); + return ret; +} + +static void radeon_connector_destroy(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (radeon_connector->edid) + free(radeon_connector->edid, DRM_MEM_KMS); + free(radeon_connector->con_priv, DRM_MEM_DRIVER); +#ifdef DUMBBELL_WIP + drm_sysfs_connector_remove(connector); +#endif /* DUMBBELL_WIP */ + drm_connector_cleanup(connector); + free(connector, DRM_MEM_DRIVER); +} + +static int radeon_lvds_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t value) +{ + struct drm_device *dev = connector->dev; + struct radeon_encoder *radeon_encoder; + enum radeon_rmx_type rmx_type; + + DRM_DEBUG_KMS("\n"); + if (property != dev->mode_config.scaling_mode_property) + return 0; + + if (connector->encoder) + radeon_encoder = to_radeon_encoder(connector->encoder); + else { + struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; + radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector)); + } + + switch (value) { + case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break; + case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break; + case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break; + default: + case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break; + } + if (radeon_encoder->rmx_type == rmx_type) + return 0; + + radeon_encoder->rmx_type = rmx_type; + + radeon_property_change_mode(&radeon_encoder->base); + return 0; +} + + +static const struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = { + .get_modes = radeon_lvds_get_modes, + .mode_valid = radeon_lvds_mode_valid, + .best_encoder = radeon_best_single_encoder, +}; + +static const struct drm_connector_funcs radeon_lvds_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_lvds_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = radeon_connector_destroy, + .set_property = radeon_lvds_set_property, +}; + +static int radeon_vga_get_modes(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + int ret; + + ret = radeon_ddc_get_modes(radeon_connector); + + return ret; +} + +static int radeon_vga_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + + /* XXX check mode bandwidth */ + + if ((mode->clock / 10) > rdev->clock.max_pixel_clock) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static enum drm_connector_status +radeon_vga_detect(struct drm_connector *connector, bool force) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *encoder; + struct drm_encoder_helper_funcs *encoder_funcs; + bool dret = false; + enum drm_connector_status ret = connector_status_disconnected; + + encoder = radeon_best_single_encoder(connector); + if (!encoder) + ret = connector_status_disconnected; + + if (radeon_connector->ddc_bus) + dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { + radeon_connector->detected_by_load = false; + if (radeon_connector->edid) { + free(radeon_connector->edid, DRM_MEM_KMS); + radeon_connector->edid = NULL; + } + radeon_connector->edid = drm_get_edid(&radeon_connector->base, radeon_connector->ddc_bus->adapter); + + if (!radeon_connector->edid) { + DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", + drm_get_connector_name(connector)); + ret = connector_status_connected; + } else { + radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); + + /* some oems have boards with separate digital and analog connectors + * with a shared ddc line (often vga + hdmi) + */ + if (radeon_connector->use_digital && radeon_connector->shared_ddc) { + free(radeon_connector->edid, DRM_MEM_KMS); + radeon_connector->edid = NULL; + ret = connector_status_disconnected; + } else + ret = connector_status_connected; + } + } else { + + /* if we aren't forcing don't do destructive polling */ + if (!force) { + /* only return the previous status if we last + * detected a monitor via load. + */ + if (radeon_connector->detected_by_load) + return connector->status; + else + return ret; + } + + if (radeon_connector->dac_load_detect && encoder) { + encoder_funcs = encoder->helper_private; + ret = encoder_funcs->detect(encoder, connector); + if (ret != connector_status_disconnected) + radeon_connector->detected_by_load = true; + } + } + + if (ret == connector_status_connected) + ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); + + /* RN50 and some RV100 asics in servers often have a hardcoded EDID in the + * vbios to deal with KVMs. If we have one and are not able to detect a monitor + * by other means, assume the CRT is connected and use that EDID. + */ + if ((!rdev->is_atom_bios) && + (ret == connector_status_disconnected) && + rdev->mode_info.bios_hardcoded_edid_size) { + ret = connector_status_connected; + } + + radeon_connector_update_scratch_regs(connector, ret); + return ret; +} + +static const struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = { + .get_modes = radeon_vga_get_modes, + .mode_valid = radeon_vga_mode_valid, + .best_encoder = radeon_best_single_encoder, +}; + +static const struct drm_connector_funcs radeon_vga_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_vga_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = radeon_connector_destroy, + .set_property = radeon_connector_set_property, +}; + +static int radeon_tv_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_display_mode *tv_mode; + struct drm_encoder *encoder; + + encoder = radeon_best_single_encoder(connector); + if (!encoder) + return 0; + + /* avivo chips can scale any mode */ + if (rdev->family >= CHIP_RS600) + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + else { + /* only 800x600 is supported right now on pre-avivo chips */ + tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false); + tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, tv_mode); + } + return 1; +} + +static int radeon_tv_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + if ((mode->hdisplay > 1024) || (mode->vdisplay > 768)) + return MODE_CLOCK_RANGE; + return MODE_OK; +} + +static enum drm_connector_status +radeon_tv_detect(struct drm_connector *connector, bool force) +{ + struct drm_encoder *encoder; + struct drm_encoder_helper_funcs *encoder_funcs; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + enum drm_connector_status ret = connector_status_disconnected; + + if (!radeon_connector->dac_load_detect) + return ret; + + encoder = radeon_best_single_encoder(connector); + if (!encoder) + ret = connector_status_disconnected; + else { + encoder_funcs = encoder->helper_private; + ret = encoder_funcs->detect(encoder, connector); + } + if (ret == connector_status_connected) + ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); + radeon_connector_update_scratch_regs(connector, ret); + return ret; +} + +static const struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = { + .get_modes = radeon_tv_get_modes, + .mode_valid = radeon_tv_mode_valid, + .best_encoder = radeon_best_single_encoder, +}; + +static const struct drm_connector_funcs radeon_tv_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_tv_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = radeon_connector_destroy, + .set_property = radeon_connector_set_property, +}; + +static int radeon_dvi_get_modes(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + int ret; + + ret = radeon_ddc_get_modes(radeon_connector); + return ret; +} + +static bool radeon_check_hpd_status_unchanged(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + enum drm_connector_status status; + + /* We only trust HPD on R600 and newer ASICS. */ + if (rdev->family >= CHIP_R600 + && radeon_connector->hpd.hpd != RADEON_HPD_NONE) { + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + status = connector_status_connected; + else + status = connector_status_disconnected; + if (connector->status == status) + return true; + } + + return false; +} + +/* + * DVI is complicated + * Do a DDC probe, if DDC probe passes, get the full EDID so + * we can do analog/digital monitor detection at this point. + * If the monitor is an analog monitor or we got no DDC, + * we need to find the DAC encoder object for this connector. + * If we got no DDC, we do load detection on the DAC encoder object. + * If we got analog DDC or load detection passes on the DAC encoder + * we have to check if this analog encoder is shared with anyone else (TV) + * if its shared we have to set the other connector to disconnected. + */ +static enum drm_connector_status +radeon_dvi_detect(struct drm_connector *connector, bool force) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *encoder = NULL; + struct drm_encoder_helper_funcs *encoder_funcs; + struct drm_mode_object *obj; + int i; + enum drm_connector_status ret = connector_status_disconnected; + bool dret = false, broken_edid = false; + + if (!force && radeon_check_hpd_status_unchanged(connector)) + return connector->status; + + if (radeon_connector->ddc_bus) + dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { + radeon_connector->detected_by_load = false; + if (radeon_connector->edid) { + free(radeon_connector->edid, DRM_MEM_KMS); + radeon_connector->edid = NULL; + } + radeon_connector->edid = drm_get_edid(&radeon_connector->base, radeon_connector->ddc_bus->adapter); + + if (!radeon_connector->edid) { + DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", + drm_get_connector_name(connector)); + /* rs690 seems to have a problem with connectors not existing and always + * return a block of 0's. If we see this just stop polling on this output */ + if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) { + ret = connector_status_disconnected; + DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); + radeon_connector->ddc_bus = NULL; + } else { + ret = connector_status_connected; + broken_edid = true; /* defer use_digital to later */ + } + } else { + radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); + + /* some oems have boards with separate digital and analog connectors + * with a shared ddc line (often vga + hdmi) + */ + if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) { + free(radeon_connector->edid, DRM_MEM_KMS); + radeon_connector->edid = NULL; + ret = connector_status_disconnected; + } else + ret = connector_status_connected; + + /* This gets complicated. We have boards with VGA + HDMI with a + * shared DDC line and we have boards with DVI-D + HDMI with a shared + * DDC line. The latter is more complex because with DVI<->HDMI adapters + * you don't really know what's connected to which port as both are digital. + */ + if (radeon_connector->shared_ddc && (ret == connector_status_connected)) { + struct drm_connector *list_connector; + struct radeon_connector *list_radeon_connector; + list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) { + if (connector == list_connector) + continue; + list_radeon_connector = to_radeon_connector(list_connector); + if (list_radeon_connector->shared_ddc && + (list_radeon_connector->ddc_bus->rec.i2c_id == + radeon_connector->ddc_bus->rec.i2c_id)) { + /* cases where both connectors are digital */ + if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { + /* hpd is our only option in this case */ + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + free(radeon_connector->edid, DRM_MEM_KMS); + radeon_connector->edid = NULL; + ret = connector_status_disconnected; + } + } + } + } + } + } + } + + if ((ret == connector_status_connected) && (radeon_connector->use_digital == true)) + goto out; + + /* DVI-D and HDMI-A are digital only */ + if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) || + (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)) + goto out; + + /* if we aren't forcing don't do destructive polling */ + if (!force) { + /* only return the previous status if we last + * detected a monitor via load. + */ + if (radeon_connector->detected_by_load) + ret = connector->status; + goto out; + } + + /* find analog encoder */ + if (radeon_connector->dac_load_detect) { + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, + connector->encoder_ids[i], + DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && + encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) + continue; + + encoder_funcs = encoder->helper_private; + if (encoder_funcs->detect) { + if (!broken_edid) { + if (ret != connector_status_connected) { + /* deal with analog monitors without DDC */ + ret = encoder_funcs->detect(encoder, connector); + if (ret == connector_status_connected) { + radeon_connector->use_digital = false; + } + if (ret != connector_status_disconnected) + radeon_connector->detected_by_load = true; + } + } else { + enum drm_connector_status lret; + /* assume digital unless load detected otherwise */ + radeon_connector->use_digital = true; + lret = encoder_funcs->detect(encoder, connector); + DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); + if (lret == connector_status_connected) + radeon_connector->use_digital = false; + } + break; + } + } + } + + if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) && + encoder) { + ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); + } + + /* RN50 and some RV100 asics in servers often have a hardcoded EDID in the + * vbios to deal with KVMs. If we have one and are not able to detect a monitor + * by other means, assume the DFP is connected and use that EDID. In most + * cases the DVI port is actually a virtual KVM port connected to the service + * processor. + */ +out: + if ((!rdev->is_atom_bios) && + (ret == connector_status_disconnected) && + rdev->mode_info.bios_hardcoded_edid_size) { + radeon_connector->use_digital = true; + ret = connector_status_connected; + } + + /* updated in get modes as well since we need to know if it's analog or digital */ + radeon_connector_update_scratch_regs(connector, ret); + return ret; +} + +/* okay need to be smart in here about which encoder to pick */ +static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_mode_object *obj; + struct drm_encoder *encoder; + int i; + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + + if (radeon_connector->use_digital == true) { + if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) + return encoder; + } else { + if (encoder->encoder_type == DRM_MODE_ENCODER_DAC || + encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) + return encoder; + } + } + + /* see if we have a default encoder TODO */ + + /* then check use digitial */ + /* pick the first one */ + if (enc_id) { + obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) + return NULL; + encoder = obj_to_encoder(obj); + return encoder; + } + return NULL; +} + +static void radeon_dvi_force(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + if (connector->force == DRM_FORCE_ON) + radeon_connector->use_digital = false; + if (connector->force == DRM_FORCE_ON_DIGITAL) + radeon_connector->use_digital = true; +} + +static int radeon_dvi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + /* XXX check mode bandwidth */ + + /* clocks over 135 MHz have heat issues with DVI on RV100 */ + if (radeon_connector->use_digital && + (rdev->family == CHIP_RV100) && + (mode->clock > 135000)) + return MODE_CLOCK_HIGH; + + if (radeon_connector->use_digital && (mode->clock > 165000)) { + if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) || + (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || + (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) + return MODE_OK; + else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) { + if (ASIC_IS_DCE6(rdev)) { + /* HDMI 1.3+ supports max clock of 340 Mhz */ + if (mode->clock > 340000) + return MODE_CLOCK_HIGH; + else + return MODE_OK; + } else + return MODE_CLOCK_HIGH; + } else + return MODE_CLOCK_HIGH; + } + + /* check against the max pixel clock */ + if ((mode->clock / 10) > rdev->clock.max_pixel_clock) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { + .get_modes = radeon_dvi_get_modes, + .mode_valid = radeon_dvi_mode_valid, + .best_encoder = radeon_dvi_encoder, +}; + +static const struct drm_connector_funcs radeon_dvi_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dvi_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_connector_set_property, + .destroy = radeon_connector_destroy, + .force = radeon_dvi_force, +}; + +static void radeon_dp_connector_destroy(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + + if (radeon_connector->edid) + free(radeon_connector->edid, DRM_MEM_KMS); + if (radeon_dig_connector->dp_i2c_bus) + radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); + free(radeon_connector->con_priv, DRM_MEM_DRIVER); +#ifdef DUMBBELL_WIP + drm_sysfs_connector_remove(connector); +#endif /* DUMBBELL_WIP */ + drm_connector_cleanup(connector); + free(connector, DRM_MEM_DRIVER); +} + +static int radeon_dp_get_modes(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + int ret; + + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { + struct drm_display_mode *mode; + + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if (!radeon_dig_connector->edp_on) + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_ON); + ret = radeon_ddc_get_modes(radeon_connector); + if (!radeon_dig_connector->edp_on) + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_OFF); + } else { + /* need to setup ddc on the bridge */ + if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != + ENCODER_OBJECT_ID_NONE) { + if (encoder) + radeon_atom_ext_encoder_setup_ddc(encoder); + } + ret = radeon_ddc_get_modes(radeon_connector); + } + + if (ret > 0) { + if (encoder) { + radeon_fixup_lvds_native_mode(encoder, connector); + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + } + return ret; + } + + if (!encoder) + return 0; + + /* we have no EDID modes */ + mode = radeon_fp_native_mode(encoder); + if (mode) { + ret = 1; + drm_mode_probed_add(connector, mode); + /* add the width/height from vbios tables if available */ + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + } + } else { + /* need to setup ddc on the bridge */ + if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != + ENCODER_OBJECT_ID_NONE) { + if (encoder) + radeon_atom_ext_encoder_setup_ddc(encoder); + } + ret = radeon_ddc_get_modes(radeon_connector); + } + + return ret; +} + +u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector) +{ + struct drm_mode_object *obj; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + radeon_encoder = to_radeon_encoder(encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + return radeon_encoder->encoder_id; + default: + break; + } + } + + return ENCODER_OBJECT_ID_NONE; +} + +bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector) +{ + struct drm_mode_object *obj; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + int i; + bool found = false; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2) + found = true; + } + + return found; +} + +bool radeon_connector_is_dp12_capable(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_DCE5(rdev) && + (rdev->clock.dp_extclk >= 53900) && + radeon_connector_encoder_is_hbr2(connector)) { + return true; + } + + return false; +} + +static enum drm_connector_status +radeon_dp_detect(struct drm_connector *connector, bool force) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + enum drm_connector_status ret = connector_status_disconnected; + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + + if (!force && radeon_check_hpd_status_unchanged(connector)) + return connector->status; + + if (radeon_connector->edid) { + free(radeon_connector->edid, DRM_MEM_KMS); + radeon_connector->edid = NULL; + } + + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + /* check if panel is valid */ + if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) + ret = connector_status_connected; + } + /* eDP is always DP */ + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; + if (!radeon_dig_connector->edp_on) + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_ON); + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; + if (!radeon_dig_connector->edp_on) + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_OFF); + } else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != + ENCODER_OBJECT_ID_NONE) { + /* DP bridges are always DP */ + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; + /* get the DPCD from the bridge */ + radeon_dp_getdpcd(radeon_connector); + + if (encoder) { + /* setup ddc on the bridge */ + radeon_atom_ext_encoder_setup_ddc(encoder); + /* bridge chips are always aux */ + if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */ + ret = connector_status_connected; + else if (radeon_connector->dac_load_detect) { /* try load detection */ + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + ret = encoder_funcs->detect(encoder, connector); + } + } + } else { + radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + ret = connector_status_connected; + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) + radeon_dp_getdpcd(radeon_connector); + } else { + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; + } else { + /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ + if (radeon_ddc_probe(radeon_connector, false)) + ret = connector_status_connected; + } + } + } + + radeon_connector_update_scratch_regs(connector, ret); + return ret; +} + +static int radeon_dp_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + + /* XXX check mode bandwidth */ + + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + + if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) + return MODE_PANEL; + + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + /* AVIVO hardware supports downscaling modes larger than the panel + * to the panel size, but I'm not sure this is desirable. + */ + if ((mode->hdisplay > native_mode->hdisplay) || + (mode->vdisplay > native_mode->vdisplay)) + return MODE_PANEL; + + /* if scaling is disabled, block non-native modes */ + if (radeon_encoder->rmx_type == RMX_OFF) { + if ((mode->hdisplay != native_mode->hdisplay) || + (mode->vdisplay != native_mode->vdisplay)) + return MODE_PANEL; + } + } + return MODE_OK; + } else { + if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + return radeon_dp_mode_valid_helper(connector, mode); + else + return MODE_OK; + } +} + +static const struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = { + .get_modes = radeon_dp_get_modes, + .mode_valid = radeon_dp_mode_valid, + .best_encoder = radeon_dvi_encoder, +}; + +static const struct drm_connector_funcs radeon_dp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_connector_set_property, + .destroy = radeon_dp_connector_destroy, + .force = radeon_dvi_force, +}; + +void +radeon_add_atom_connector(struct drm_device *dev, + uint32_t connector_id, + uint32_t supported_device, + int connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint32_t igp_lane_info, + uint16_t connector_object_id, + struct radeon_hpd *hpd, + struct radeon_router *router) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *radeon_dig_connector; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + uint32_t subpixel_order = SubPixelNone; + bool shared_ddc = false; + bool is_dp_bridge = false; + + if (connector_type == DRM_MODE_CONNECTOR_Unknown) + return; + + /* if the user selected tv=0 don't try and add the connector */ + if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || + (connector_type == DRM_MODE_CONNECTOR_Composite) || + (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && + (radeon_tv == 0)) + return; + + /* see if we already added it */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + if (radeon_connector->connector_id == connector_id) { + radeon_connector->devices |= supported_device; + return; + } + if (radeon_connector->ddc_bus && i2c_bus->valid) { + if (radeon_connector->ddc_bus->rec.i2c_id == i2c_bus->i2c_id) { + radeon_connector->shared_ddc = true; + shared_ddc = true; + } + if (radeon_connector->router_bus && router->ddc_valid && + (radeon_connector->router.router_id == router->router_id)) { + radeon_connector->shared_ddc = false; + shared_ddc = false; + } + } + } + + /* check if it's a dp bridge */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->devices & supported_device) { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + is_dp_bridge = true; + break; + default: + break; + } + } + } + + radeon_connector = malloc(sizeof(struct radeon_connector), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_connector) + return; + + connector = &radeon_connector->base; + + radeon_connector->connector_id = connector_id; + radeon_connector->devices = supported_device; + radeon_connector->shared_ddc = shared_ddc; + radeon_connector->connector_object_id = connector_object_id; + radeon_connector->hpd = *hpd; + + radeon_connector->router = *router; + if (router->ddc_valid || router->cd_valid) { + radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); + if (!radeon_connector->router_bus) + DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n"); + } + + if (is_dp_bridge) { + radeon_dig_connector = malloc( + sizeof(struct radeon_connector_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); + if (i2c_bus->valid) { + /* add DP i2c bus */ + if (connector_type == DRM_MODE_CONNECTOR_eDP) + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); + else + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); + if (!radeon_dig_connector->dp_i2c_bus) + DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + switch (connector_type) { + case DRM_MODE_CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_DVIA: + default: + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + case DRM_MODE_CONNECTOR_DisplayPort: + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_HDMIB) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } + break; + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + drm_connector_attach_property(&radeon_connector->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + } + } else { + switch (connector_type) { + case DRM_MODE_CONNECTOR_VGA: + drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + break; + case DRM_MODE_CONNECTOR_DVIA: + drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + radeon_dig_connector = malloc( + sizeof(struct radeon_connector_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + subpixel_order = SubPixelHorizontalRGB; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.coherent_mode_property, + 1); + if (ASIC_IS_AVIVO(rdev)) { + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + } + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_DVII) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + radeon_dig_connector = malloc( + sizeof(struct radeon_connector_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.coherent_mode_property, + 1); + if (ASIC_IS_AVIVO(rdev)) { + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + } + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_HDMIB) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + radeon_dig_connector = malloc( + sizeof(struct radeon_connector_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); + if (i2c_bus->valid) { + /* add DP i2c bus */ + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); + if (!radeon_dig_connector->dp_i2c_bus) + DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + subpixel_order = SubPixelHorizontalRGB; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.coherent_mode_property, + 1); + if (ASIC_IS_AVIVO(rdev)) { + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + } + connector->interlace_allowed = true; + /* in theory with a DP to VGA converter... */ + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_eDP: + radeon_dig_connector = malloc( + sizeof(struct radeon_connector_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); + if (i2c_bus->valid) { + /* add DP i2c bus */ + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); + if (!radeon_dig_connector->dp_i2c_bus) + DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + drm_connector_attach_property(&radeon_connector->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_9PinDIN: + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_atombios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_LVDS: + radeon_dig_connector = malloc( + sizeof(struct radeon_connector_atom_dig), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + drm_connector_attach_property(&radeon_connector->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + } + } + + if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) { + if (i2c_bus->valid) + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + } else + connector->polled = DRM_CONNECTOR_POLL_HPD; + + connector->display_info.subpixel_order = subpixel_order; +#ifdef DUMBBELL_WIP + drm_sysfs_connector_add(connector); +#endif /* DUMBBELL_WIP */ + return; + +failed: + drm_connector_cleanup(connector); + free(connector, DRM_MEM_DRIVER); +} + +void +radeon_add_legacy_connector(struct drm_device *dev, + uint32_t connector_id, + uint32_t supported_device, + int connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint16_t connector_object_id, + struct radeon_hpd *hpd) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + uint32_t subpixel_order = SubPixelNone; + + if (connector_type == DRM_MODE_CONNECTOR_Unknown) + return; + + /* if the user selected tv=0 don't try and add the connector */ + if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || + (connector_type == DRM_MODE_CONNECTOR_Composite) || + (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && + (radeon_tv == 0)) + return; + + /* see if we already added it */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + if (radeon_connector->connector_id == connector_id) { + radeon_connector->devices |= supported_device; + return; + } + } + + radeon_connector = malloc(sizeof(struct radeon_connector), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_connector) + return; + + connector = &radeon_connector->base; + + radeon_connector->connector_id = connector_id; + radeon_connector->devices = supported_device; + radeon_connector->connector_object_id = connector_object_id; + radeon_connector->hpd = *hpd; + + switch (connector_type) { + case DRM_MODE_CONNECTOR_VGA: + drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + break; + case DRM_MODE_CONNECTOR_DVIA: + drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_DVII) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_9PinDIN: + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; + /* RS400,RC410,RS480 chipset seems to report a lot + * of false positive on load detect, we haven't yet + * found a way to make load detect reliable on those + * chipset, thus just disable it for TV. + */ + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) + radeon_connector->dac_load_detect = false; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + radeon_connector->dac_load_detect); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_combios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_LVDS: + drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + drm_connector_attach_property(&radeon_connector->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + } + + if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) { + if (i2c_bus->valid) + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + } else + connector->polled = DRM_CONNECTOR_POLL_HPD; + connector->display_info.subpixel_order = subpixel_order; +#ifdef DUMBBELL_WIP + drm_sysfs_connector_add(connector); +#endif /* DUMBBELL_WIP */ +} diff --git a/sys/dev/drm2/radeon/radeon_cp.c b/sys/dev/drm2/radeon/radeon_cp.c new file mode 100644 index 00000000000..4a036336cdb --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_cp.c @@ -0,0 +1,2245 @@ +/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */ +/* + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2007 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include "radeon_drv.h" +#include "r300_reg.h" + +#define RADEON_FIFO_DEBUG 0 + +/* Firmware Names */ +#define FIRMWARE_R100 "radeonkmsfw_R100_cp" +#define FIRMWARE_R200 "radeonkmsfw_R200_cp" +#define FIRMWARE_R300 "radeonkmsfw_R300_cp" +#define FIRMWARE_R420 "radeonkmsfw_R420_cp" +#define FIRMWARE_RS690 "radeonkmsfw_RS690_cp" +#define FIRMWARE_RS600 "radeonkmsfw_RS600_cp" +#define FIRMWARE_R520 "radeonkmsfw_R520_cp" + +static int radeon_do_cleanup_cp(struct drm_device * dev); +static void radeon_do_cp_start(drm_radeon_private_t * dev_priv); + +u32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off) +{ + u32 val; + + if (dev_priv->flags & RADEON_IS_AGP) { + val = DRM_READ32(dev_priv->ring_rptr, off); + } else { + val = *(((volatile u32 *) + dev_priv->ring_rptr->handle) + + (off / sizeof(u32))); + val = le32_to_cpu(val); + } + return val; +} + +u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv) +{ + if (dev_priv->writeback_works) + return radeon_read_ring_rptr(dev_priv, 0); + else { + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return RADEON_READ(R600_CP_RB_RPTR); + else + return RADEON_READ(RADEON_CP_RB_RPTR); + } +} + +void radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val) +{ + if (dev_priv->flags & RADEON_IS_AGP) + DRM_WRITE32(dev_priv->ring_rptr, off, val); + else + *(((volatile u32 *) dev_priv->ring_rptr->handle) + + (off / sizeof(u32))) = cpu_to_le32(val); +} + +void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val) +{ + radeon_write_ring_rptr(dev_priv, 0, val); +} + +u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index) +{ + if (dev_priv->writeback_works) { + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return radeon_read_ring_rptr(dev_priv, + R600_SCRATCHOFF(index)); + else + return radeon_read_ring_rptr(dev_priv, + RADEON_SCRATCHOFF(index)); + } else { + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return RADEON_READ(R600_SCRATCH_REG0 + 4*index); + else + return RADEON_READ(RADEON_SCRATCH_REG0 + 4*index); + } +} + +static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff)); + ret = RADEON_READ(R520_MC_IND_DATA); + RADEON_WRITE(R520_MC_IND_INDEX, 0); + return ret; +} + +static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff); + ret = RADEON_READ(RS480_NB_MC_DATA); + RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); + return ret; +} + +static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK)); + ret = RADEON_READ(RS690_MC_DATA); + RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK); + return ret; +} + +static u32 RS600_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(RS600_MC_INDEX, ((addr & RS600_MC_ADDR_MASK) | + RS600_MC_IND_CITF_ARB0)); + ret = RADEON_READ(RS600_MC_DATA); + return ret; +} + +static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) + return RS690_READ_MCIND(dev_priv, addr); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + return RS600_READ_MCIND(dev_priv, addr); + else + return RS480_READ_MCIND(dev_priv, addr); +} + +u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) +{ + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) + return RADEON_READ(R700_MC_VM_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return RADEON_READ(R600_MC_VM_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) + return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); + else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) + return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + return RS600_READ_MCIND(dev_priv, RS600_MC_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) + return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); + else + return RADEON_READ(RADEON_MC_FB_LOCATION); +} + +static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) +{ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) + RADEON_WRITE(R700_MC_VM_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + RADEON_WRITE(R600_MC_VM_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) + R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc); + else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) + RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + RS600_WRITE_MCIND(RS600_MC_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) + R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); + else + RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc); +} + +void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc) +{ + /*R6xx/R7xx: AGP_TOP and BOT are actually 18 bits each */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { + RADEON_WRITE(R700_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */ + RADEON_WRITE(R700_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff); + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { + RADEON_WRITE(R600_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */ + RADEON_WRITE(R600_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff); + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) + R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc); + else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) + RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + RS600_WRITE_MCIND(RS600_MC_AGP_LOCATION, agp_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) + R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); + else + RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc); +} + +void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) +{ + u32 agp_base_hi = upper_32_bits(agp_base); + u32 agp_base_lo = agp_base & 0xffffffff; + u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff; + + /* R6xx/R7xx must be aligned to a 4MB boundary */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) + RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + RADEON_WRITE(R600_MC_VM_AGP_BASE, r6xx_agp_base); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) { + R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo); + R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { + RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo); + RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi); + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + RS600_WRITE_MCIND(RS600_AGP_BASE, agp_base_lo); + RS600_WRITE_MCIND(RS600_AGP_BASE_2, agp_base_hi); + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) { + R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo); + R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { + RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); + RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi); + } else { + RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200) + RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi); + } +} + +void radeon_enable_bm(struct drm_radeon_private *dev_priv) +{ + u32 tmp; + /* Turn on bus mastering */ + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { + /* rs600/rs690/rs740 */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { + /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); + } /* PCIE cards appears to not need this */ +} + +static int RADEON_READ_PLL(struct drm_device * dev, int addr) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); + return RADEON_READ(RADEON_CLOCK_CNTL_DATA); +} + +static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) +{ + RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); + return RADEON_READ(RADEON_PCIE_DATA); +} + +#if RADEON_FIFO_DEBUG +static void radeon_status(drm_radeon_private_t * dev_priv) +{ + printk("%s:\n", __func__); + printk("RBBM_STATUS = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_RBBM_STATUS)); + printk("CP_RB_RTPR = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR)); + printk("CP_RB_WTPR = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR)); + printk("AIC_CNTL = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_AIC_CNTL)); + printk("AIC_STAT = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_AIC_STAT)); + printk("AIC_PT_BASE = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE)); + printk("TLB_ADDR = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR)); + printk("TLB_DATA = 0x%08x\n", + (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA)); +} +#endif + +/* ================================================================ + * Engine, FIFO control + */ + +static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) +{ + u32 tmp; + int i; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { + tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); + tmp |= RADEON_RB3D_DC_FLUSH_ALL; + RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) + & RADEON_RB3D_DC_BUSY)) { + return 0; + } + DRM_UDELAY(1); + } + } else { + /* don't flush or purge cache here or lockup */ + return 0; + } + +#if RADEON_FIFO_DEBUG + DRM_ERROR("failed!\n"); + radeon_status(dev_priv); +#endif + return -EBUSY; +} + +static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) +{ + int i; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = (RADEON_READ(RADEON_RBBM_STATUS) + & RADEON_RBBM_FIFOCNT_MASK); + if (slots >= entries) + return 0; + DRM_UDELAY(1); + } + DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n", + RADEON_READ(RADEON_RBBM_STATUS), + RADEON_READ(R300_VAP_CNTL_STATUS)); + +#if RADEON_FIFO_DEBUG + DRM_ERROR("failed!\n"); + radeon_status(dev_priv); +#endif + return -EBUSY; +} + +static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) +{ + int i, ret; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + ret = radeon_do_wait_for_fifo(dev_priv, 64); + if (ret) + return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(RADEON_READ(RADEON_RBBM_STATUS) + & RADEON_RBBM_ACTIVE)) { + radeon_do_pixcache_flush(dev_priv); + return 0; + } + DRM_UDELAY(1); + } + DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n", + RADEON_READ(RADEON_RBBM_STATUS), + RADEON_READ(R300_VAP_CNTL_STATUS)); + +#if RADEON_FIFO_DEBUG + DRM_ERROR("failed!\n"); + radeon_status(dev_priv); +#endif + return -EBUSY; +} + +static void radeon_init_pipes(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t gb_tile_config, gb_pipe_sel = 0; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) { + uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2); + if ((z_pipe_sel & 3) == 3) + dev_priv->num_z_pipes = 2; + else + dev_priv->num_z_pipes = 1; + } else + dev_priv->num_z_pipes = 1; + + /* RS4xx/RS6xx/R4xx/R5xx */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) { + gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT); + dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; + /* SE cards have 1 pipe */ + if ((dev->pci_device == 0x5e4c) || + (dev->pci_device == 0x5e4f)) + dev_priv->num_gb_pipes = 1; + } else { + /* R3xx */ + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 && + dev->pci_device != 0x4144) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350 && + dev->pci_device != 0x4148)) { + dev_priv->num_gb_pipes = 2; + } else { + /* RV3xx/R300 AD/R350 AH */ + dev_priv->num_gb_pipes = 1; + } + } + DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes); + + gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/); + + switch (dev_priv->num_gb_pipes) { + case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; + case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; + case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; + default: + case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { + RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); + RADEON_WRITE(R300_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1)); + } + RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config); + radeon_do_wait_for_idle(dev_priv); + RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); + RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) | + R300_DC_AUTOFLUSH_ENABLE | + R300_DC_DC_DISABLE_IGNORE_PE)); + + +} + +/* ================================================================ + * CP control, initialization + */ + +/* Load the microcode for the CP */ +static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv) +{ + const char *fw_name = NULL; + int err; + + DRM_DEBUG("\n"); + + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) { + DRM_INFO("Loading R100 Microcode\n"); + fw_name = FIRMWARE_R100; + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) { + DRM_INFO("Loading R200 Microcode\n"); + fw_name = FIRMWARE_R200; + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { + DRM_INFO("Loading R300 Microcode\n"); + fw_name = FIRMWARE_R300; + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) { + DRM_INFO("Loading R400 Microcode\n"); + fw_name = FIRMWARE_R420; + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { + DRM_INFO("Loading RS690/RS740 Microcode\n"); + fw_name = FIRMWARE_RS690; + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + DRM_INFO("Loading RS600 Microcode\n"); + fw_name = FIRMWARE_RS600; + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) { + DRM_INFO("Loading R500 Microcode\n"); + fw_name = FIRMWARE_R520; + } + + err = 0; + + dev_priv->me_fw = firmware_get(fw_name); + if (dev_priv->me_fw == NULL) { + err = -ENOENT; + DRM_ERROR("radeon_cp: Failed to load firmware \"%s\"\n", + fw_name); + } else if (dev_priv->me_fw->datasize % 8) { + DRM_ERROR( + "radeon_cp: Bogus length %zu in firmware \"%s\"\n", + dev_priv->me_fw->datasize, fw_name); + err = -EINVAL; + firmware_put(dev_priv->me_fw, FIRMWARE_UNLOAD); + dev_priv->me_fw = NULL; + } + return err; +} + +static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv) +{ + const __be32 *fw_data; + int i, size; + + radeon_do_wait_for_idle(dev_priv); + + if (dev_priv->me_fw) { + size = dev_priv->me_fw->datasize / 4; + fw_data = (const __be32 *)dev_priv->me_fw->data; + RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0); + for (i = 0; i < size; i += 2) { + RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, + be32_to_cpup(&fw_data[i])); + RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, + be32_to_cpup(&fw_data[i + 1])); + } + } +} + +/* Flush any pending commands to the CP. This should only be used just + * prior to a wait for idle, as it informs the engine that the command + * stream is ending. + */ +static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv) +{ + DRM_DEBUG("\n"); +#if 0 + u32 tmp; + + tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31); + RADEON_WRITE(RADEON_CP_RB_WPTR, tmp); +#endif +} + +/* Wait for the CP to go idle. + */ +int radeon_do_cp_idle(drm_radeon_private_t * dev_priv) +{ + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(6); + + RADEON_PURGE_CACHE(); + RADEON_PURGE_ZCACHE(); + RADEON_WAIT_UNTIL_IDLE(); + + ADVANCE_RING(); + COMMIT_RING(); + + return radeon_do_wait_for_idle(dev_priv); +} + +/* Start the Command Processor. + */ +static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) +{ + RING_LOCALS; + DRM_DEBUG("\n"); + + radeon_do_wait_for_idle(dev_priv); + + RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode); + + dev_priv->cp_running = 1; + + /* on r420, any DMA from CP to system memory while 2D is active + * can cause a hang. workaround is to queue a CP RESYNC token + */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) { + BEGIN_RING(3); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); + OUT_RING(5); /* scratch reg 5 */ + OUT_RING(0xdeadbeef); + ADVANCE_RING(); + COMMIT_RING(); + } + + BEGIN_RING(8); + /* isync can only be written through cp on r5xx write it here */ + OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); + OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI); + RADEON_PURGE_CACHE(); + RADEON_PURGE_ZCACHE(); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); + COMMIT_RING(); + + dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; +} + +/* Reset the Command Processor. This will not flush any pending + * commands, so you must wait for the CP command stream to complete + * before calling this routine. + */ +static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) +{ + u32 cur_read_ptr; + DRM_DEBUG("\n"); + + cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); + RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); + SET_RING_HEAD(dev_priv, cur_read_ptr); + dev_priv->ring.tail = cur_read_ptr; +} + +/* Stop the Command Processor. This will not flush any pending + * commands, so you must flush the command stream and wait for the CP + * to go idle before calling this routine. + */ +static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) +{ + RING_LOCALS; + DRM_DEBUG("\n"); + + /* finish the pending CP_RESYNC token */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) { + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FINISH); + ADVANCE_RING(); + COMMIT_RING(); + radeon_do_wait_for_idle(dev_priv); + } + + RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); + + dev_priv->cp_running = 0; +} + +/* Reset the engine. This will stop the CP if it is running. + */ +static int radeon_do_engine_reset(struct drm_device * dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset; + DRM_DEBUG("\n"); + + radeon_do_pixcache_flush(dev_priv); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { + /* may need something similar for newer chips */ + clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); + mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); + + RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | + RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC | + RADEON_FORCEON_AIC)); + } + + rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); + + RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | + RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB)); + RADEON_READ(RADEON_RBBM_SOFT_RESET); + RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & + ~(RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB))); + RADEON_READ(RADEON_RBBM_SOFT_RESET); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { + RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); + RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); + RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); + } + + /* setup the raster pipes */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300) + radeon_init_pipes(dev); + + /* Reset the CP ring */ + radeon_do_cp_reset(dev_priv); + + /* The CP is no longer running after an engine reset */ + dev_priv->cp_running = 0; + + /* Reset any pending vertex, indirect buffers */ + radeon_freelist_reset(dev); + + return 0; +} + +static void radeon_cp_init_ring_buffer(struct drm_device * dev, + drm_radeon_private_t *dev_priv, + struct drm_file *file_priv) +{ + struct drm_radeon_master_private *master_priv; + u32 ring_start, cur_read_ptr; + + /* Initialize the memory controller. With new memory map, the fb location + * is not changed, it should have been properly initialized already. Part + * of the problem is that the code below is bogus, assuming the GART is + * always appended to the fb which is not necessarily the case + */ + if (!dev_priv->new_memmap) + radeon_write_fb_location(dev_priv, + ((dev_priv->gart_vm_start - 1) & 0xffff0000) + | (dev_priv->fb_location >> 16)); + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + radeon_write_agp_base(dev_priv, dev->agp->base); + + radeon_write_agp_location(dev_priv, + (((dev_priv->gart_vm_start - 1 + + dev_priv->gart_size) & 0xffff0000) | + (dev_priv->gart_vm_start >> 16))); + + ring_start = (dev_priv->cp_ring->offset + - dev->agp->base + + dev_priv->gart_vm_start); + } else +#endif + ring_start = (dev_priv->cp_ring->offset + - (unsigned long)dev->sg->vaddr + + dev_priv->gart_vm_start); + + RADEON_WRITE(RADEON_CP_RB_BASE, ring_start); + + /* Set the write pointer delay */ + RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0); + + /* Initialize the ring buffer's read and write pointers */ + cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); + RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); + SET_RING_HEAD(dev_priv, cur_read_ptr); + dev_priv->ring.tail = cur_read_ptr; + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, + dev_priv->ring_rptr->offset + - dev->agp->base + dev_priv->gart_vm_start); + } else +#endif + { + RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, + dev_priv->ring_rptr->offset + - ((unsigned long) dev->sg->vaddr) + + dev_priv->gart_vm_start); + } + + /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE(RADEON_CP_RB_CNTL, + RADEON_BUF_SWAP_32BIT | + (dev_priv->ring.fetch_size_l2ow << 18) | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#else + RADEON_WRITE(RADEON_CP_RB_CNTL, + (dev_priv->ring.fetch_size_l2ow << 18) | + (dev_priv->ring.rptr_update_l2qw << 8) | + dev_priv->ring.size_l2qw); +#endif + + + /* Initialize the scratch register pointer. This will cause + * the scratch register values to be written out to memory + * whenever they are updated. + * + * We simply put this behind the ring read pointer, this works + * with PCI GART as well as (whatever kind of) AGP GART + */ + RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR) + + RADEON_SCRATCH_REG_OFFSET); + + RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); + + radeon_enable_bm(dev_priv); + + radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(0), 0); + RADEON_WRITE(RADEON_LAST_FRAME_REG, 0); + + radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0); + RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0); + + radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(2), 0); + RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); + + /* reset sarea copies of these */ + master_priv = file_priv->masterp->driver_priv; + if (master_priv->sarea_priv) { + master_priv->sarea_priv->last_frame = 0; + master_priv->sarea_priv->last_dispatch = 0; + master_priv->sarea_priv->last_clear = 0; + } + + radeon_do_wait_for_idle(dev_priv); + + /* Sync everything up */ + RADEON_WRITE(RADEON_ISYNC_CNTL, + (RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI)); + +} + +static void radeon_test_writeback(drm_radeon_private_t * dev_priv) +{ + u32 tmp; + + /* Start with assuming that writeback doesn't work */ + dev_priv->writeback_works = 0; + + /* Writeback doesn't seem to work everywhere, test it here and possibly + * enable it if it appears to work + */ + radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0); + + RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); + + for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { + u32 val; + + val = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1)); + if (val == 0xdeadbeef) + break; + DRM_UDELAY(1); + } + + if (tmp < dev_priv->usec_timeout) { + dev_priv->writeback_works = 1; + DRM_INFO("writeback test succeeded in %d usecs\n", tmp); + } else { + dev_priv->writeback_works = 0; + DRM_INFO("writeback test failed\n"); + } + if (radeon_no_wb == 1) { + dev_priv->writeback_works = 0; + DRM_INFO("writeback forced off\n"); + } + + if (!dev_priv->writeback_works) { + /* Disable writeback to avoid unnecessary bus master transfer */ + RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | + RADEON_RB_NO_UPDATE); + RADEON_WRITE(RADEON_SCRATCH_UMSK, 0); + } +} + +/* Enable or disable IGP GART on the chip */ +static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) +{ + u32 temp; + + if (on) { + DRM_DEBUG("programming igp gart %08X %08lX %08X\n", + dev_priv->gart_vm_start, + (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); + + temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL); + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) + IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN | + RS690_BLOCK_GFX_D3_EN)); + else + IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); + + IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | + RS480_VA_SIZE_32MB)); + + temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID); + IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN | + RS480_TLB_ENABLE | + RS480_GTW_LAC_EN | + RS480_1LEVEL_GART)); + + temp = dev_priv->gart_info.bus_addr & 0xfffff000; + temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4; + IGP_WRITE_MCIND(RS480_GART_BASE, temp); + + temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL); + IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) | + RS480_REQ_TYPE_SNOOP_DIS)); + + radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start); + + dev_priv->gart_size = 32*1024*1024; + temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & + 0xffff0000) | (dev_priv->gart_vm_start >> 16)); + + radeon_write_agp_location(dev_priv, temp); + + temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE); + IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | + RS480_VA_SIZE_32MB)); + + do { + temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); + if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) + break; + DRM_UDELAY(1); + } while (1); + + IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, + RS480_GART_CACHE_INVALIDATE); + + do { + temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); + if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) + break; + DRM_UDELAY(1); + } while (1); + + IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0); + } else { + IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0); + } +} + +/* Enable or disable IGP GART on the chip */ +static void rs600_set_igpgart(drm_radeon_private_t *dev_priv, int on) +{ + u32 temp; + int i; + + if (on) { + DRM_DEBUG("programming igp gart %08X %08lX %08X\n", + dev_priv->gart_vm_start, + (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); + + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (RS600_EFFECTIVE_L2_CACHE_SIZE(6) | + RS600_EFFECTIVE_L2_QUEUE_SIZE(6))); + + for (i = 0; i < 19; i++) + IGP_WRITE_MCIND(RS600_MC_PT0_CLIENT0_CNTL + i, + (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE | + RS600_SYSTEM_ACCESS_MODE_IN_SYS | + RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH | + RS600_EFFECTIVE_L1_CACHE_SIZE(3) | + RS600_ENABLE_FRAGMENT_PROCESSING | + RS600_EFFECTIVE_L1_QUEUE_SIZE(3))); + + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL, (RS600_ENABLE_PAGE_TABLE | + RS600_PAGE_TABLE_TYPE_FLAT)); + + /* disable all other contexts */ + for (i = 1; i < 8; i++) + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL + i, 0); + + /* setup the page table aperture */ + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, + dev_priv->gart_info.bus_addr); + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, + dev_priv->gart_vm_start); + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, + (dev_priv->gart_vm_start + dev_priv->gart_size - 1)); + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); + + /* setup the system aperture */ + IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, + dev_priv->gart_vm_start); + IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, + (dev_priv->gart_vm_start + dev_priv->gart_size - 1)); + + /* enable page tables */ + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (temp | RS600_ENABLE_PT)); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1); + IGP_WRITE_MCIND(RS600_MC_CNTL1, (temp | RS600_ENABLE_PAGE_TABLES)); + + /* invalidate the cache */ + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + + temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE); + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp); + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + + temp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE; + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp); + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + + temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE); + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp); + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + + } else { + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, 0); + temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1); + temp &= ~RS600_ENABLE_PAGE_TABLES; + IGP_WRITE_MCIND(RS600_MC_CNTL1, temp); + } +} + +static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) +{ + u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); + if (on) { + + DRM_DEBUG("programming pcie %08X %08lX %08X\n", + dev_priv->gart_vm_start, + (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, + dev_priv->gart_vm_start); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, + dev_priv->gart_info.bus_addr); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, + dev_priv->gart_vm_start); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, + dev_priv->gart_vm_start + + dev_priv->gart_size - 1); + + radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */ + + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, + RADEON_PCIE_TX_GART_EN); + } else { + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, + tmp & ~RADEON_PCIE_TX_GART_EN); + } +} + +/* Enable or disable PCI GART on the chip */ +static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) +{ + u32 tmp; + + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) || + (dev_priv->flags & RADEON_IS_IGPGART)) { + radeon_set_igpgart(dev_priv, on); + return; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + rs600_set_igpgart(dev_priv, on); + return; + } + + if (dev_priv->flags & RADEON_IS_PCIE) { + radeon_set_pciegart(dev_priv, on); + return; + } + + tmp = RADEON_READ(RADEON_AIC_CNTL); + + if (on) { + RADEON_WRITE(RADEON_AIC_CNTL, + tmp | RADEON_PCIGART_TRANSLATE_EN); + + /* set PCI GART page-table base address + */ + RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr); + + /* set address range for PCI address translate + */ + RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start); + RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start + + dev_priv->gart_size - 1); + + /* Turn off AGP aperture -- is this required for PCI GART? + */ + radeon_write_agp_location(dev_priv, 0xffffffc0); + RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */ + } else { + RADEON_WRITE(RADEON_AIC_CNTL, + tmp & ~RADEON_PCIGART_TRANSLATE_EN); + } +} + +static int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv) +{ + struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info; + struct radeon_virt_surface *vp; + int i; + + for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) { + if (!dev_priv->virt_surfaces[i].file_priv || + dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV) + break; + } + if (i >= 2 * RADEON_MAX_SURFACES) + return -ENOMEM; + vp = &dev_priv->virt_surfaces[i]; + + for (i = 0; i < RADEON_MAX_SURFACES; i++) { + struct radeon_surface *sp = &dev_priv->surfaces[i]; + if (sp->refcount) + continue; + + vp->surface_index = i; + vp->lower = gart_info->bus_addr; + vp->upper = vp->lower + gart_info->table_size; + vp->flags = 0; + vp->file_priv = PCIGART_FILE_PRIV; + + sp->refcount = 1; + sp->lower = vp->lower; + sp->upper = vp->upper; + sp->flags = 0; + + RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags); + RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower); + RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper); + return 0; + } + + return -ENOMEM; +} + +static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, + struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + + DRM_DEBUG("\n"); + + /* if we require new memory map but we don't have it fail */ + if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { + DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + + if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { + DRM_DEBUG("Forcing AGP card to PCI mode\n"); + dev_priv->flags &= ~RADEON_IS_AGP; + } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) + && !init->is_pci) { + DRM_DEBUG("Restoring AGP flag\n"); + dev_priv->flags |= RADEON_IS_AGP; + } + + if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { + DRM_ERROR("PCI GART memory not allocated!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + + dev_priv->usec_timeout = init->usec_timeout; + if (dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { + DRM_DEBUG("TIMEOUT problem!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + + /* Enable vblank on CRTC1 for older X servers + */ + dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; + + switch(init->func) { + case RADEON_INIT_R200_CP: + dev_priv->microcode_version = UCODE_R200; + break; + case RADEON_INIT_R300_CP: + dev_priv->microcode_version = UCODE_R300; + break; + default: + dev_priv->microcode_version = UCODE_R100; + } + + dev_priv->do_boxes = 0; + dev_priv->cp_mode = init->cp_mode; + + /* We don't support anything other than bus-mastering ring mode, + * but the ring can be in either AGP or PCI space for the ring + * read pointer. + */ + if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && + (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { + DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + + switch (init->fb_bpp) { + case 16: + dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; + break; + case 32: + default: + dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; + break; + } + dev_priv->front_offset = init->front_offset; + dev_priv->front_pitch = init->front_pitch; + dev_priv->back_offset = init->back_offset; + dev_priv->back_pitch = init->back_pitch; + + switch (init->depth_bpp) { + case 16: + dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; + break; + case 32: + default: + dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; + break; + } + dev_priv->depth_offset = init->depth_offset; + dev_priv->depth_pitch = init->depth_pitch; + + /* Hardware state for depth clears. Remove this if/when we no + * longer clear the depth buffer with a 3D rectangle. Hard-code + * all values to prevent unwanted 3D state from slipping through + * and screwing with the clear operation. + */ + dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | + (dev_priv->color_fmt << 10) | + (dev_priv->microcode_version == + UCODE_R100 ? RADEON_ZBLOCK16 : 0)); + + dev_priv->depth_clear.rb3d_zstencilcntl = + (dev_priv->depth_fmt | + RADEON_Z_TEST_ALWAYS | + RADEON_STENCIL_TEST_ALWAYS | + RADEON_STENCIL_S_FAIL_REPLACE | + RADEON_STENCIL_ZPASS_REPLACE | + RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE); + + dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | + RADEON_BFACE_SOLID | + RADEON_FFACE_SOLID | + RADEON_FLAT_SHADE_VTX_LAST | + RADEON_DIFFUSE_SHADE_FLAT | + RADEON_ALPHA_SHADE_FLAT | + RADEON_SPECULAR_SHADE_FLAT | + RADEON_FOG_SHADE_FLAT | + RADEON_VTX_PIX_CENTER_OGL | + RADEON_ROUND_MODE_TRUNC | + RADEON_ROUND_PREC_8TH_PIX); + + + dev_priv->ring_offset = init->ring_offset; + dev_priv->ring_rptr_offset = init->ring_rptr_offset; + dev_priv->buffers_offset = init->buffers_offset; + dev_priv->gart_textures_offset = init->gart_textures_offset; + + master_priv->sarea = drm_getsarea(dev); + if (!master_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + + dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); + if (!dev_priv->cp_ring) { + DRM_ERROR("could not find cp ring region!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); + if (!dev_priv->ring_rptr) { + DRM_ERROR("could not find ring read pointer!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + dev->agp_buffer_token = init->buffers_offset; + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if (!dev->agp_buffer_map) { + DRM_ERROR("could not find dma buffer region!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + + if (init->gart_textures_offset) { + dev_priv->gart_textures = + drm_core_findmap(dev, init->gart_textures_offset); + if (!dev_priv->gart_textures) { + DRM_ERROR("could not find GART texture region!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + } + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + drm_core_ioremap_wc(dev_priv->cp_ring, dev); + drm_core_ioremap_wc(dev_priv->ring_rptr, dev); + drm_core_ioremap_wc(dev->agp_buffer_map, dev); + if (!dev_priv->cp_ring->handle || + !dev_priv->ring_rptr->handle || + !dev->agp_buffer_map->handle) { + DRM_ERROR("could not find ioremap agp regions!\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + } else +#endif + { + dev_priv->cp_ring->handle = + (void *)(unsigned long)dev_priv->cp_ring->offset; + dev_priv->ring_rptr->handle = + (void *)(unsigned long)dev_priv->ring_rptr->offset; + dev->agp_buffer_map->handle = + (void *)(unsigned long)dev->agp_buffer_map->offset; + + DRM_DEBUG("dev_priv->cp_ring->handle %p\n", + dev_priv->cp_ring->handle); + DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", + dev_priv->ring_rptr->handle); + DRM_DEBUG("dev->agp_buffer_map->handle %p\n", + dev->agp_buffer_map->handle); + } + + dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; + dev_priv->fb_size = + ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) + - dev_priv->fb_location; + + dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | + ((dev_priv->front_offset + + dev_priv->fb_location) >> 10)); + + dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | + ((dev_priv->back_offset + + dev_priv->fb_location) >> 10)); + + dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | + ((dev_priv->depth_offset + + dev_priv->fb_location) >> 10)); + + dev_priv->gart_size = init->gart_size; + + /* New let's set the memory map ... */ + if (dev_priv->new_memmap) { + u32 base = 0; + + DRM_INFO("Setting GART location based on new memory map\n"); + + /* If using AGP, try to locate the AGP aperture at the same + * location in the card and on the bus, though we have to + * align it down. + */ +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + base = dev->agp->base; + /* Check if valid */ + if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { + DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", + dev->agp->base); + base = 0; + } + } +#endif + /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ + if (base == 0) { + base = dev_priv->fb_location + dev_priv->fb_size; + if (base < dev_priv->fb_location || + ((base + dev_priv->gart_size) & 0xfffffffful) < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + dev_priv->gart_vm_start = base & 0xffc00000u; + if (dev_priv->gart_vm_start != base) + DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", + base, dev_priv->gart_vm_start); + } else { + DRM_INFO("Setting GART location based on old memory map\n"); + dev_priv->gart_vm_start = dev_priv->fb_location + + RADEON_READ(RADEON_CONFIG_APER_SIZE); + } + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) + dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset + - dev->agp->base + + dev_priv->gart_vm_start); + else +#endif + dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset + - (unsigned long)dev->sg->vaddr + + dev_priv->gart_vm_start); + + DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); + DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start); + DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n", + dev_priv->gart_buffers_offset); + + dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; + dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle + + init->ring_size / sizeof(u32)); + dev_priv->ring.size = init->ring_size; + dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); + + dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; + dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8); + + dev_priv->ring.fetch_size = /* init->fetch_size */ 32; + dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16); + dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; + + dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + /* Turn off PCI GART */ + radeon_set_pcigart(dev_priv, 0); + } else +#endif + { + u32 sctrl; + int ret; + + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); + /* if we have an offset set from userspace */ + if (dev_priv->pcigart_offset_set) { + dev_priv->gart_info.bus_addr = + (resource_size_t)dev_priv->pcigart_offset + dev_priv->fb_location; + dev_priv->gart_info.mapping.offset = + dev_priv->pcigart_offset + dev_priv->fb_aper_offset; + dev_priv->gart_info.mapping.size = + dev_priv->gart_info.table_size; + + drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev); + dev_priv->gart_info.addr = + dev_priv->gart_info.mapping.handle; + + if (dev_priv->flags & RADEON_IS_PCIE) + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; + else + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; + dev_priv->gart_info.gart_table_location = + DRM_ATI_GART_FB; + + DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", + dev_priv->gart_info.addr, + dev_priv->pcigart_offset); + } else { + if (dev_priv->flags & RADEON_IS_IGPGART) + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; + else + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; + dev_priv->gart_info.gart_table_location = + DRM_ATI_GART_MAIN; + dev_priv->gart_info.addr = NULL; + dev_priv->gart_info.bus_addr = 0; + if (dev_priv->flags & RADEON_IS_PCIE) { + DRM_ERROR + ("Cannot use PCI Express without GART in FB memory\n"); + radeon_do_cleanup_cp(dev); + return -EINVAL; + } + } + + sctrl = RADEON_READ(RADEON_SURFACE_CNTL); + RADEON_WRITE(RADEON_SURFACE_CNTL, 0); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + ret = r600_page_table_init(dev); + else + ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info); + RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl); + + if (!ret) { + DRM_ERROR("failed to init PCI GART!\n"); + radeon_do_cleanup_cp(dev); + return -ENOMEM; + } + + ret = radeon_setup_pcigart_surface(dev_priv); + if (ret) { + DRM_ERROR("failed to setup GART surface!\n"); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + r600_page_table_cleanup(dev, &dev_priv->gart_info); + else + drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info); + radeon_do_cleanup_cp(dev); + return ret; + } + + /* Turn on PCI GART */ + radeon_set_pcigart(dev_priv, 1); + } + + if (!dev_priv->me_fw) { + int err = radeon_cp_init_microcode(dev_priv); + if (err) { + DRM_ERROR("Failed to load firmware!\n"); + radeon_do_cleanup_cp(dev); + return err; + } + } + radeon_cp_load_microcode(dev_priv); + radeon_cp_init_ring_buffer(dev, dev_priv, file_priv); + + dev_priv->last_buf = 0; + + radeon_do_engine_reset(dev); + radeon_test_writeback(dev_priv); + + return 0; +} + +static int radeon_do_cleanup_cp(struct drm_device * dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + /* Make sure interrupts are disabled here because the uninstall ioctl + * may not have been called from userspace and after dev_private + * is freed, it's too late. + */ + if (dev->irq_enabled) + drm_irq_uninstall(dev); + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + if (dev_priv->cp_ring != NULL) { + drm_core_ioremapfree(dev_priv->cp_ring, dev); + dev_priv->cp_ring = NULL; + } + if (dev_priv->ring_rptr != NULL) { + drm_core_ioremapfree(dev_priv->ring_rptr, dev); + dev_priv->ring_rptr = NULL; + } + if (dev->agp_buffer_map != NULL) { + drm_core_ioremapfree(dev->agp_buffer_map, dev); + dev->agp_buffer_map = NULL; + } + } else +#endif + { + + if (dev_priv->gart_info.bus_addr) { + /* Turn off PCI GART */ + radeon_set_pcigart(dev_priv, 0); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + r600_page_table_cleanup(dev, &dev_priv->gart_info); + else { + if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) + DRM_ERROR("failed to cleanup PCI GART!\n"); + } + } + + if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) + { + drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); + dev_priv->gart_info.addr = NULL; + } + } + /* only clear to the start of flags */ + memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); + + return 0; +} + +/* This code will reinit the Radeon CP hardware after a resume from disc. + * AFAIK, it would be very difficult to pickle the state at suspend time, so + * here we make sure that all Radeon hardware initialisation is re-done without + * affecting running applications. + * + * Charl P. Botha + */ +static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (!dev_priv) { + DRM_ERROR("Called with no initialization\n"); + return -EINVAL; + } + + DRM_DEBUG("Starting radeon_do_resume_cp()\n"); + +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) { + /* Turn off PCI GART */ + radeon_set_pcigart(dev_priv, 0); + } else +#endif + { + /* Turn on PCI GART */ + radeon_set_pcigart(dev_priv, 1); + } + + radeon_cp_load_microcode(dev_priv); + radeon_cp_init_ring_buffer(dev, dev_priv, file_priv); + + dev_priv->have_z_offset = 0; + radeon_do_engine_reset(dev); + radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); + + DRM_DEBUG("radeon_do_resume_cp() complete\n"); + + return 0; +} + +int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_init_t *init = data; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if (init->func == RADEON_INIT_R300_CP) + r300_init_reg_flags(dev); + + switch (init->func) { + case RADEON_INIT_CP: + case RADEON_INIT_R200_CP: + case RADEON_INIT_R300_CP: + return radeon_do_init_cp(dev, init, file_priv); + case RADEON_INIT_R600_CP: + return r600_do_init_cp(dev, init, file_priv); + break; + case RADEON_CLEANUP_CP: + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return r600_do_cleanup_cp(dev); + else + return radeon_do_cleanup_cp(dev); + } + + return -EINVAL; +} + +int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if (dev_priv->cp_running) { + DRM_DEBUG("while CP running\n"); + return 0; + } + if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) { + DRM_DEBUG("called with bogus CP mode (%d)\n", + dev_priv->cp_mode); + return 0; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_do_cp_start(dev_priv); + else + radeon_do_cp_start(dev_priv); + + return 0; +} + +/* Stop the CP. The engine must have been idled before calling this + * routine. + */ +int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_cp_stop_t *stop = data; + int ret; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if (!dev_priv->cp_running) + return 0; + + /* Flush any pending CP commands. This ensures any outstanding + * commands are exectuted by the engine before we turn it off. + */ + if (stop->flush) { + radeon_do_cp_flush(dev_priv); + } + + /* If we fail to make the engine go idle, we return an error + * code so that the DRM ioctl wrapper can try again. + */ + if (stop->idle) { + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + ret = r600_do_cp_idle(dev_priv); + else + ret = radeon_do_cp_idle(dev_priv); + if (ret) + return ret; + } + + /* Finally, we can turn off the CP. If the engine isn't idle, + * we will get some dropped triangles as they won't be fully + * rendered before the CP is shut down. + */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_do_cp_stop(dev_priv); + else + radeon_do_cp_stop(dev_priv); + + /* Reset the engine */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_do_engine_reset(dev); + else + radeon_do_engine_reset(dev); + + return 0; +} + +void radeon_do_release(struct drm_device * dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int i, ret; + + if (dev_priv) { + if (dev_priv->cp_running) { + /* Stop the cp */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { + while ((ret = r600_do_cp_idle(dev_priv)) != 0) { + DRM_DEBUG("radeon_do_cp_idle %d\n", ret); +#ifdef __linux__ + schedule(); +#else + tsleep(&ret, PZERO, "rdnrel", 1); +#endif + } + } else { + while ((ret = radeon_do_cp_idle(dev_priv)) != 0) { + DRM_DEBUG("radeon_do_cp_idle %d\n", ret); +#ifdef __linux__ + schedule(); +#else + tsleep(&ret, PZERO, "rdnrel", 1); +#endif + } + } + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { + r600_do_cp_stop(dev_priv); + r600_do_engine_reset(dev); + } else { + radeon_do_cp_stop(dev_priv); + radeon_do_engine_reset(dev); + } + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R600) { + /* Disable *all* interrupts */ + if (dev_priv->mmio) /* remove this after permanent addmaps */ + RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); + + if (dev_priv->mmio) { /* remove all surfaces */ + for (i = 0; i < RADEON_MAX_SURFACES; i++) { + RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0); + RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + + 16 * i, 0); + RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + + 16 * i, 0); + } + } + } + + /* Free memory heap structures */ + radeon_mem_takedown(&(dev_priv->gart_heap)); + radeon_mem_takedown(&(dev_priv->fb_heap)); + + /* deallocate kernel resources */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_do_cleanup_cp(dev); + else + radeon_do_cleanup_cp(dev); + if (dev_priv->me_fw != NULL) { + firmware_put(dev_priv->me_fw, FIRMWARE_UNLOAD); + dev_priv->me_fw = NULL; + } + if (dev_priv->pfp_fw != NULL) { + firmware_put(dev_priv->pfp_fw, FIRMWARE_UNLOAD); + dev_priv->pfp_fw = NULL; + } + } +} + +/* Just reset the CP ring. Called as part of an X Server engine reset. + */ +int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if (!dev_priv) { + DRM_DEBUG("called before init done\n"); + return -EINVAL; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_do_cp_reset(dev_priv); + else + radeon_do_cp_reset(dev_priv); + + /* The CP is no longer running after an engine reset */ + dev_priv->cp_running = 0; + + return 0; +} + +int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return r600_do_cp_idle(dev_priv); + else + return radeon_do_cp_idle(dev_priv); +} + +/* Added by Charl P. Botha to call radeon_do_resume_cp(). + */ +int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return r600_do_resume_cp(dev, file_priv); + else + return radeon_do_resume_cp(dev, file_priv); +} + +int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return r600_do_engine_reset(dev); + else + return radeon_do_engine_reset(dev); +} + +/* ================================================================ + * Fullscreen mode + */ + +/* KW: Deprecated to say the least: + */ +int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + return 0; +} + +/* ================================================================ + * Freelist management + */ + +/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through + * bufs until freelist code is used. Note this hides a problem with + * the scratch register * (used to keep track of last buffer + * completed) being written to before * the last buffer has actually + * completed rendering. + * + * KW: It's also a good way to find free buffers quickly. + * + * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't + * sleep. However, bugs in older versions of radeon_accel.c mean that + * we essentially have to do this, else old clients will break. + * + * However, it does leave open a potential deadlock where all the + * buffers are held by other clients, which can't release them because + * they can't get the lock. + */ + +struct drm_buf *radeon_freelist_get(struct drm_device * dev) +{ + struct drm_device_dma *dma = dev->dma; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_buf_priv_t *buf_priv; + struct drm_buf *buf; + int i, t; + int start; + + if (++dev_priv->last_buf >= dma->buf_count) + dev_priv->last_buf = 0; + + start = dev_priv->last_buf; + + for (t = 0; t < dev_priv->usec_timeout; t++) { + u32 done_age = GET_SCRATCH(dev_priv, 1); + DRM_DEBUG("done_age = %d\n", done_age); + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[start]; + buf_priv = buf->dev_private; + if (buf->file_priv == NULL || (buf->pending && + buf_priv->age <= + done_age)) { + dev_priv->stats.requested_bufs++; + buf->pending = 0; + return buf; + } + if (++start >= dma->buf_count) + start = 0; + } + + if (t) { + DRM_UDELAY(1); + dev_priv->stats.freelist_loops++; + } + } + + return NULL; +} + +void radeon_freelist_reset(struct drm_device * dev) +{ + struct drm_device_dma *dma = dev->dma; + drm_radeon_private_t *dev_priv = dev->dev_private; + int i; + + dev_priv->last_buf = 0; + for (i = 0; i < dma->buf_count; i++) { + struct drm_buf *buf = dma->buflist[i]; + drm_radeon_buf_priv_t *buf_priv = buf->dev_private; + buf_priv->age = 0; + } +} + +/* ================================================================ + * CP command submission + */ + +int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) +{ + drm_radeon_ring_buffer_t *ring = &dev_priv->ring; + int i; + u32 last_head = GET_RING_HEAD(dev_priv); + + for (i = 0; i < dev_priv->usec_timeout; i++) { + u32 head = GET_RING_HEAD(dev_priv); + + ring->space = (head - ring->tail) * sizeof(u32); + if (ring->space <= 0) + ring->space += ring->size; + if (ring->space > n) + return 0; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + if (head != last_head) + i = 0; + last_head = head; + + DRM_UDELAY(1); + } + + /* FIXME: This return value is ignored in the BEGIN_RING macro! */ +#if RADEON_FIFO_DEBUG + radeon_status(dev_priv); + DRM_ERROR("failed!\n"); +#endif + return -EBUSY; +} + +static int radeon_cp_get_buffers(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_dma * d) +{ + int i; + struct drm_buf *buf; + + for (i = d->granted_count; i < d->request_count; i++) { + buf = radeon_freelist_get(dev); + if (!buf) + return -EBUSY; /* NOTE: broken client */ + + buf->file_priv = file_priv; + + if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, + sizeof(buf->idx))) + return -EFAULT; + if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, + sizeof(buf->total))) + return -EFAULT; + + d->granted_count++; + } + return 0; +} + +int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + struct drm_device_dma *dma = dev->dma; + int ret = 0; + struct drm_dma *d = data; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + /* Please don't send us buffers. + */ + if (d->send_count != 0) { + DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", + DRM_CURRENTPID, d->send_count); + return -EINVAL; + } + + /* We'll send you buffers. + */ + if (d->request_count < 0 || d->request_count > dma->buf_count) { + DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", + DRM_CURRENTPID, d->request_count, dma->buf_count); + return -EINVAL; + } + + d->granted_count = 0; + + if (d->request_count) { + ret = radeon_cp_get_buffers(dev, file_priv, d); + } + + return ret; +} + +int radeon_driver_load(struct drm_device *dev, unsigned long flags) +{ + drm_radeon_private_t *dev_priv; + int ret = 0; + + dev_priv = malloc(sizeof(drm_radeon_private_t), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (dev_priv == NULL) + return -ENOMEM; + + dev->dev_private = (void *)dev_priv; + dev_priv->flags = flags; + + switch (flags & RADEON_FAMILY_MASK) { + case CHIP_R100: + case CHIP_RV200: + case CHIP_R200: + case CHIP_R300: + case CHIP_R350: + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV570: + case CHIP_R580: + dev_priv->flags |= RADEON_HAS_HIERZ; + break; + default: + /* all other chips have no hierarchical z buffer */ + break; + } + + pci_enable_busmaster(dev->device); + + if (drm_device_is_agp(dev)) + dev_priv->flags |= RADEON_IS_AGP; + else if (drm_device_is_pcie(dev)) + dev_priv->flags |= RADEON_IS_PCIE; + else + dev_priv->flags |= RADEON_IS_PCI; + + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), + drm_get_resource_len(dev, 2), _DRM_REGISTERS, + _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); + if (ret != 0) + return ret; + + ret = drm_vblank_init(dev, 2); + if (ret) { + radeon_driver_unload(dev); + return ret; + } + + DRM_DEBUG("%s card detected\n", + ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); + return ret; +} + +int radeon_master_create(struct drm_device *dev, struct drm_master *master) +{ + struct drm_radeon_master_private *master_priv; + unsigned long sareapage; + int ret; + + master_priv = malloc(sizeof(*master_priv), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!master_priv) + return -ENOMEM; + + /* prebuild the SAREA */ + sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE); + ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, + &master_priv->sarea); + if (ret) { + DRM_ERROR("SAREA setup failed\n"); + free(master_priv, DRM_MEM_DRIVER); + return ret; + } + master_priv->sarea_priv = (drm_radeon_sarea_t *)((char *)master_priv->sarea->handle) + + sizeof(struct drm_sarea); + master_priv->sarea_priv->pfCurrentPage = 0; + + master->driver_priv = master_priv; + return 0; +} + +void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) +{ + struct drm_radeon_master_private *master_priv = master->driver_priv; + + if (!master_priv) + return; + + if (master_priv->sarea_priv && + master_priv->sarea_priv->pfCurrentPage != 0) + radeon_cp_dispatch_flip(dev, master); + + master_priv->sarea_priv = NULL; + if (master_priv->sarea) +#ifdef __linux__ + drm_rmmap_locked(dev, master_priv->sarea); +#else + drm_rmmap(dev, master_priv->sarea); +#endif + + free(master_priv, DRM_MEM_DRIVER); + + master->driver_priv = NULL; +} + +/* Create mappings for registers and framebuffer so userland doesn't necessarily + * have to find them. + */ +int radeon_driver_firstopen(struct drm_device *dev) +{ + int ret; + drm_local_map_t *map; + drm_radeon_private_t *dev_priv = dev->dev_private; + + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + + dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); + ret = drm_addmap(dev, dev_priv->fb_aper_offset, + drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, + _DRM_WRITE_COMBINING, &map); + if (ret != 0) + return ret; + + return 0; +} + +int radeon_driver_unload(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + drm_rmmap(dev, dev_priv->mmio); + + free(dev_priv, DRM_MEM_DRIVER); + + dev->dev_private = NULL; + return 0; +} + +void radeon_commit_ring(drm_radeon_private_t *dev_priv) +{ + int i; + u32 *ring; + int tail_aligned; + + /* check if the ring is padded out to 16-dword alignment */ + + tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1); + if (tail_aligned) { + int num_p2 = RADEON_RING_ALIGN - tail_aligned; + + ring = dev_priv->ring.start; + /* pad with some CP_PACKET2 */ + for (i = 0; i < num_p2; i++) + ring[dev_priv->ring.tail + i] = CP_PACKET2(); + + dev_priv->ring.tail += i; + + dev_priv->ring.space -= num_p2 * sizeof(u32); + } + + dev_priv->ring.tail &= dev_priv->ring.tail_mask; + + DRM_MEMORYBARRIER(); + GET_RING_HEAD( dev_priv ); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { + RADEON_WRITE(R600_CP_RB_WPTR, dev_priv->ring.tail); + /* read from PCI bus to ensure correct posting */ + RADEON_READ(R600_CP_RB_RPTR); + } else { + RADEON_WRITE(RADEON_CP_RB_WPTR, dev_priv->ring.tail); + /* read from PCI bus to ensure correct posting */ + RADEON_READ(RADEON_CP_RB_RPTR); + } +} diff --git a/sys/dev/drm2/radeon/radeon_cs.c b/sys/dev/drm2/radeon/radeon_cs.c new file mode 100644 index 00000000000..ee299fa7206 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_cs.c @@ -0,0 +1,658 @@ +/* + * Copyright 2008 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" + +void r100_cs_dump_packet(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt); + +static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) +{ + struct drm_device *ddev = p->rdev->ddev; + struct radeon_cs_chunk *chunk; + unsigned i, j; + bool duplicate; + + if (p->chunk_relocs_idx == -1) { + return 0; + } + chunk = &p->chunks[p->chunk_relocs_idx]; + p->dma_reloc_idx = 0; + /* FIXME: we assume that each relocs use 4 dwords */ + p->nrelocs = chunk->length_dw / 4; + p->relocs_ptr = malloc(p->nrelocs * sizeof(void *), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (p->relocs_ptr == NULL) { + return -ENOMEM; + } + p->relocs = malloc(p->nrelocs * sizeof(struct radeon_cs_reloc), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (p->relocs == NULL) { + return -ENOMEM; + } + for (i = 0; i < p->nrelocs; i++) { + struct drm_radeon_cs_reloc *r; + + duplicate = false; + r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4]; + for (j = 0; j < i; j++) { + if (r->handle == p->relocs[j].handle) { + p->relocs_ptr[i] = &p->relocs[j]; + duplicate = true; + break; + } + } + if (!duplicate) { + p->relocs[i].gobj = drm_gem_object_lookup(ddev, + p->filp, + r->handle); + if (p->relocs[i].gobj == NULL) { + DRM_ERROR("gem object lookup failed 0x%x\n", + r->handle); + return -ENOENT; + } + p->relocs_ptr[i] = &p->relocs[i]; + p->relocs[i].robj = gem_to_radeon_bo(p->relocs[i].gobj); + p->relocs[i].lobj.bo = p->relocs[i].robj; + p->relocs[i].lobj.wdomain = r->write_domain; + p->relocs[i].lobj.rdomain = r->read_domains; + p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; + p->relocs[i].handle = r->handle; + p->relocs[i].flags = r->flags; + radeon_bo_list_add_object(&p->relocs[i].lobj, + &p->validated); + + } else + p->relocs[i].handle = 0; + } + return radeon_bo_list_validate(&p->validated); +} + +static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) +{ + p->priority = priority; + + switch (ring) { + default: + DRM_ERROR("unknown ring id: %d\n", ring); + return -EINVAL; + case RADEON_CS_RING_GFX: + p->ring = RADEON_RING_TYPE_GFX_INDEX; + break; + case RADEON_CS_RING_COMPUTE: + if (p->rdev->family >= CHIP_TAHITI) { + if (p->priority > 0) + p->ring = CAYMAN_RING_TYPE_CP1_INDEX; + else + p->ring = CAYMAN_RING_TYPE_CP2_INDEX; + } else + p->ring = RADEON_RING_TYPE_GFX_INDEX; + break; + case RADEON_CS_RING_DMA: + if (p->rdev->family >= CHIP_CAYMAN) { + if (p->priority > 0) + p->ring = R600_RING_TYPE_DMA_INDEX; + else + p->ring = CAYMAN_RING_TYPE_DMA1_INDEX; + } else if (p->rdev->family >= CHIP_R600) { + p->ring = R600_RING_TYPE_DMA_INDEX; + } else { + return -EINVAL; + } + break; + } + return 0; +} + +static void radeon_cs_sync_to(struct radeon_cs_parser *p, + struct radeon_fence *fence) +{ + struct radeon_fence *other; + + if (!fence) + return; + + other = p->ib.sync_to[fence->ring]; + p->ib.sync_to[fence->ring] = radeon_fence_later(fence, other); +} + +static void radeon_cs_sync_rings(struct radeon_cs_parser *p) +{ + int i; + + for (i = 0; i < p->nrelocs; i++) { + if (!p->relocs[i].robj) + continue; + + radeon_cs_sync_to(p, p->relocs[i].robj->tbo.sync_obj); + } +} + +/* XXX: note that this is called from the legacy UMS CS ioctl as well */ +int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) +{ + struct drm_radeon_cs *cs = data; + uint64_t *chunk_array_ptr; + unsigned size, i; + u32 ring = RADEON_CS_RING_GFX; + s32 priority = 0; + + if (!cs->num_chunks) { + return 0; + } + /* get chunks */ + INIT_LIST_HEAD(&p->validated); + p->idx = 0; + p->ib.sa_bo = NULL; + p->ib.semaphore = NULL; + p->const_ib.sa_bo = NULL; + p->const_ib.semaphore = NULL; + p->chunk_ib_idx = -1; + p->chunk_relocs_idx = -1; + p->chunk_flags_idx = -1; + p->chunk_const_ib_idx = -1; + p->chunks_array = malloc(cs->num_chunks * sizeof(uint64_t), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (p->chunks_array == NULL) { + return -ENOMEM; + } + chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks); + if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr, + sizeof(uint64_t)*cs->num_chunks)) { + return -EFAULT; + } + p->cs_flags = 0; + p->nchunks = cs->num_chunks; + p->chunks = malloc(p->nchunks * sizeof(struct radeon_cs_chunk), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (p->chunks == NULL) { + return -ENOMEM; + } + for (i = 0; i < p->nchunks; i++) { + struct drm_radeon_cs_chunk __user **chunk_ptr = NULL; + struct drm_radeon_cs_chunk user_chunk; + uint32_t __user *cdata; + + chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i]; + if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, + sizeof(struct drm_radeon_cs_chunk))) { + return -EFAULT; + } + p->chunks[i].length_dw = user_chunk.length_dw; + p->chunks[i].kdata = NULL; + p->chunks[i].chunk_id = user_chunk.chunk_id; + + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) { + p->chunk_relocs_idx = i; + } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) { + p->chunk_ib_idx = i; + /* zero length IB isn't useful */ + if (p->chunks[i].length_dw == 0) + return -EINVAL; + } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_CONST_IB) { + p->chunk_const_ib_idx = i; + /* zero length CONST IB isn't useful */ + if (p->chunks[i].length_dw == 0) + return -EINVAL; + } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { + p->chunk_flags_idx = i; + /* zero length flags aren't useful */ + if (p->chunks[i].length_dw == 0) + return -EINVAL; + } + + p->chunks[i].length_dw = user_chunk.length_dw; + p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data; + + cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; + if ((p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) || + (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS)) { + size = p->chunks[i].length_dw * sizeof(uint32_t); + p->chunks[i].kdata = malloc(size, DRM_MEM_DRIVER, M_WAITOK); + if (p->chunks[i].kdata == NULL) { + return -ENOMEM; + } + if (DRM_COPY_FROM_USER(p->chunks[i].kdata, + p->chunks[i].user_ptr, size)) { + return -EFAULT; + } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { + p->cs_flags = p->chunks[i].kdata[0]; + if (p->chunks[i].length_dw > 1) + ring = p->chunks[i].kdata[1]; + if (p->chunks[i].length_dw > 2) + priority = (s32)p->chunks[i].kdata[2]; + } + } + } + + /* these are KMS only */ + if (p->rdev) { + if ((p->cs_flags & RADEON_CS_USE_VM) && + !p->rdev->vm_manager.enabled) { + DRM_ERROR("VM not active on asic!\n"); + return -EINVAL; + } + + /* we only support VM on SI+ */ + if ((p->rdev->family >= CHIP_TAHITI) && + ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { + DRM_ERROR("VM required on SI+!\n"); + return -EINVAL; + } + + if (radeon_cs_get_ring(p, ring, priority)) + return -EINVAL; + } + + /* deal with non-vm */ + if ((p->chunk_ib_idx != -1) && + ((p->cs_flags & RADEON_CS_USE_VM) == 0) && + (p->chunks[p->chunk_ib_idx].chunk_id == RADEON_CHUNK_ID_IB)) { + if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) { + DRM_ERROR("cs IB too big: %d\n", + p->chunks[p->chunk_ib_idx].length_dw); + return -EINVAL; + } + if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) { + p->chunks[p->chunk_ib_idx].kpage[0] = malloc(PAGE_SIZE, DRM_MEM_DRIVER, M_WAITOK); + p->chunks[p->chunk_ib_idx].kpage[1] = malloc(PAGE_SIZE, DRM_MEM_DRIVER, M_WAITOK); + if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || + p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { + free(p->chunks[p->chunk_ib_idx].kpage[0], DRM_MEM_DRIVER); + free(p->chunks[p->chunk_ib_idx].kpage[1], DRM_MEM_DRIVER); + p->chunks[p->chunk_ib_idx].kpage[0] = NULL; + p->chunks[p->chunk_ib_idx].kpage[1] = NULL; + return -ENOMEM; + } + } + p->chunks[p->chunk_ib_idx].kpage_idx[0] = -1; + p->chunks[p->chunk_ib_idx].kpage_idx[1] = -1; + p->chunks[p->chunk_ib_idx].last_copied_page = -1; + p->chunks[p->chunk_ib_idx].last_page_index = + ((p->chunks[p->chunk_ib_idx].length_dw * 4) - 1) / PAGE_SIZE; + } + + return 0; +} + +/** + * cs_parser_fini() - clean parser states + * @parser: parser structure holding parsing context. + * @error: error number + * + * If error is set than unvalidate buffer, otherwise just free memory + * used by parsing context. + **/ +static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) +{ + unsigned i; + + if (!error) { + ttm_eu_fence_buffer_objects(&parser->validated, + parser->ib.fence); + } else { + ttm_eu_backoff_reservation(&parser->validated); + } + + if (parser->relocs != NULL) { + for (i = 0; i < parser->nrelocs; i++) { + if (parser->relocs[i].gobj) + drm_gem_object_unreference_unlocked(parser->relocs[i].gobj); + } + } + free(parser->track, DRM_MEM_DRIVER); + free(parser->relocs, DRM_MEM_DRIVER); + free(parser->relocs_ptr, DRM_MEM_DRIVER); + for (i = 0; i < parser->nchunks; i++) { + free(parser->chunks[i].kdata, DRM_MEM_DRIVER); + if ((parser->rdev->flags & RADEON_IS_AGP)) { + free(parser->chunks[i].kpage[0], DRM_MEM_DRIVER); + free(parser->chunks[i].kpage[1], DRM_MEM_DRIVER); + } + } + free(parser->chunks, DRM_MEM_DRIVER); + free(parser->chunks_array, DRM_MEM_DRIVER); + radeon_ib_free(parser->rdev, &parser->ib); + radeon_ib_free(parser->rdev, &parser->const_ib); +} + +static int radeon_cs_ib_chunk(struct radeon_device *rdev, + struct radeon_cs_parser *parser) +{ + struct radeon_cs_chunk *ib_chunk; + int r; + + if (parser->chunk_ib_idx == -1) + return 0; + + if (parser->cs_flags & RADEON_CS_USE_VM) + return 0; + + ib_chunk = &parser->chunks[parser->chunk_ib_idx]; + /* Copy the packet into the IB, the parser will read from the + * input memory (cached) and write to the IB (which can be + * uncached). + */ + r = radeon_ib_get(rdev, parser->ring, &parser->ib, + NULL, ib_chunk->length_dw * 4); + if (r) { + DRM_ERROR("Failed to get ib !\n"); + return r; + } + parser->ib.length_dw = ib_chunk->length_dw; + r = radeon_cs_parse(rdev, parser->ring, parser); + if (r || parser->parser_error) { + DRM_ERROR("Invalid command stream !\n"); + return r; + } + r = radeon_cs_finish_pages(parser); + if (r) { + DRM_ERROR("Invalid command stream !\n"); + return r; + } + radeon_cs_sync_rings(parser); + r = radeon_ib_schedule(rdev, &parser->ib, NULL); + if (r) { + DRM_ERROR("Failed to schedule IB !\n"); + } + return r; +} + +static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, + struct radeon_vm *vm) +{ + struct radeon_device *rdev = parser->rdev; + struct radeon_bo_list *lobj; + struct radeon_bo *bo; + int r; + + r = radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem); + if (r) { + return r; + } + list_for_each_entry(lobj, &parser->validated, tv.head) { + bo = lobj->bo; + r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem); + if (r) { + return r; + } + } + return 0; +} + +static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, + struct radeon_cs_parser *parser) +{ + struct radeon_cs_chunk *ib_chunk; + struct radeon_fpriv *fpriv = parser->filp->driver_priv; + struct radeon_vm *vm = &fpriv->vm; + int r; + + if (parser->chunk_ib_idx == -1) + return 0; + if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) + return 0; + + if ((rdev->family >= CHIP_TAHITI) && + (parser->chunk_const_ib_idx != -1)) { + ib_chunk = &parser->chunks[parser->chunk_const_ib_idx]; + if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) { + DRM_ERROR("cs IB CONST too big: %d\n", ib_chunk->length_dw); + return -EINVAL; + } + r = radeon_ib_get(rdev, parser->ring, &parser->const_ib, + vm, ib_chunk->length_dw * 4); + if (r) { + DRM_ERROR("Failed to get const ib !\n"); + return r; + } + parser->const_ib.is_const_ib = true; + parser->const_ib.length_dw = ib_chunk->length_dw; + /* Copy the packet into the IB */ + if (DRM_COPY_FROM_USER(parser->const_ib.ptr, ib_chunk->user_ptr, + ib_chunk->length_dw * 4)) { + return -EFAULT; + } + r = radeon_ring_ib_parse(rdev, parser->ring, &parser->const_ib); + if (r) { + return r; + } + } + + ib_chunk = &parser->chunks[parser->chunk_ib_idx]; + if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) { + DRM_ERROR("cs IB too big: %d\n", ib_chunk->length_dw); + return -EINVAL; + } + r = radeon_ib_get(rdev, parser->ring, &parser->ib, + vm, ib_chunk->length_dw * 4); + if (r) { + DRM_ERROR("Failed to get ib !\n"); + return r; + } + parser->ib.length_dw = ib_chunk->length_dw; + /* Copy the packet into the IB */ + if (DRM_COPY_FROM_USER(parser->ib.ptr, ib_chunk->user_ptr, + ib_chunk->length_dw * 4)) { + return -EFAULT; + } + r = radeon_ring_ib_parse(rdev, parser->ring, &parser->ib); + if (r) { + return r; + } + + sx_xlock(&rdev->vm_manager.lock); + sx_xlock(&vm->mutex); + r = radeon_vm_alloc_pt(rdev, vm); + if (r) { + goto out; + } + r = radeon_bo_vm_update_pte(parser, vm); + if (r) { + goto out; + } + radeon_cs_sync_rings(parser); + radeon_cs_sync_to(parser, vm->fence); + radeon_cs_sync_to(parser, radeon_vm_grab_id(rdev, vm, parser->ring)); + + if ((rdev->family >= CHIP_TAHITI) && + (parser->chunk_const_ib_idx != -1)) { + r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib); + } else { + r = radeon_ib_schedule(rdev, &parser->ib, NULL); + } + + if (!r) { + radeon_vm_fence(rdev, vm, parser->ib.fence); + } + +out: + radeon_vm_add_to_lru(rdev, vm); + sx_xunlock(&vm->mutex); + sx_xunlock(&rdev->vm_manager.lock); + return r; +} + +static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r) +{ + if (r == -EDEADLK) { + r = radeon_gpu_reset(rdev); + if (!r) + r = -EAGAIN; + } + return r; +} + +int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_cs_parser parser; + int r; + + sx_slock(&rdev->exclusive_lock); + if (!rdev->accel_working) { + sx_sunlock(&rdev->exclusive_lock); + return -EBUSY; + } + /* initialize parser */ + memset(&parser, 0, sizeof(struct radeon_cs_parser)); + parser.filp = filp; + parser.rdev = rdev; + parser.dev = rdev->dev; + parser.family = rdev->family; + r = radeon_cs_parser_init(&parser, data); + if (r) { + DRM_ERROR("Failed to initialize parser !\n"); + radeon_cs_parser_fini(&parser, r); + sx_sunlock(&rdev->exclusive_lock); + r = radeon_cs_handle_lockup(rdev, r); + return r; + } + r = radeon_cs_parser_relocs(&parser); + if (r) { + if (r != -ERESTARTSYS) + DRM_ERROR("Failed to parse relocation %d!\n", r); + radeon_cs_parser_fini(&parser, r); + sx_sunlock(&rdev->exclusive_lock); + r = radeon_cs_handle_lockup(rdev, r); + return r; + } + r = radeon_cs_ib_chunk(rdev, &parser); + if (r) { + goto out; + } + r = radeon_cs_ib_vm_chunk(rdev, &parser); + if (r) { + goto out; + } +out: + radeon_cs_parser_fini(&parser, r); + sx_sunlock(&rdev->exclusive_lock); + r = radeon_cs_handle_lockup(rdev, r); + return r; +} + +int radeon_cs_finish_pages(struct radeon_cs_parser *p) +{ + struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; + int i; + int size = PAGE_SIZE; + + for (i = ibc->last_copied_page + 1; i <= ibc->last_page_index; i++) { + if (i == ibc->last_page_index) { + size = (ibc->length_dw * 4) % PAGE_SIZE; + if (size == 0) + size = PAGE_SIZE; + } + + if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), + (char *)ibc->user_ptr + (i * PAGE_SIZE), + size)) + return -EFAULT; + } + return 0; +} + +static int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx) +{ + int new_page; + struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; + int i; + int size = PAGE_SIZE; + bool copy1 = (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) ? + false : true; + + for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { + if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), + (char *)ibc->user_ptr + (i * PAGE_SIZE), + PAGE_SIZE)) { + p->parser_error = -EFAULT; + return 0; + } + } + + if (pg_idx == ibc->last_page_index) { + size = (ibc->length_dw * 4) % PAGE_SIZE; + if (size == 0) + size = PAGE_SIZE; + } + + new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1; + if (copy1) + ibc->kpage[new_page] = p->ib.ptr + (pg_idx * (PAGE_SIZE / 4)); + + if (DRM_COPY_FROM_USER(ibc->kpage[new_page], + (char *)ibc->user_ptr + (pg_idx * PAGE_SIZE), + size)) { + p->parser_error = -EFAULT; + return 0; + } + + /* copy to IB for non single case */ + if (!copy1) + memcpy((void *)(p->ib.ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size); + + ibc->last_copied_page = pg_idx; + ibc->kpage_idx[new_page] = pg_idx; + + return new_page; +} + +u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx) +{ + struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; + u32 pg_idx, pg_offset; + u32 idx_value = 0; + int new_page; + + pg_idx = (idx * 4) / PAGE_SIZE; + pg_offset = (idx * 4) % PAGE_SIZE; + + if (ibc->kpage_idx[0] == pg_idx) + return ibc->kpage[0][pg_offset/4]; + if (ibc->kpage_idx[1] == pg_idx) + return ibc->kpage[1][pg_offset/4]; + + new_page = radeon_cs_update_pages(p, pg_idx); + if (new_page < 0) { + p->parser_error = new_page; + return 0; + } + + idx_value = ibc->kpage[new_page][pg_offset/4]; + return idx_value; +} diff --git a/sys/dev/drm2/radeon/radeon_cursor.c b/sys/dev/drm2/radeon/radeon_cursor.c new file mode 100644 index 00000000000..0b4e73e1dac --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_cursor.c @@ -0,0 +1,316 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" + +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 + +static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock) +{ + struct radeon_device *rdev = crtc->dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + uint32_t cur_lock; + + if (ASIC_IS_DCE4(rdev)) { + cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset); + if (lock) + cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK; + else + cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK; + WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); + } else if (ASIC_IS_AVIVO(rdev)) { + cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); + if (lock) + cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; + else + cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; + WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); + } else { + cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset); + if (lock) + cur_lock |= RADEON_CUR_LOCK; + else + cur_lock &= ~RADEON_CUR_LOCK; + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock); + } +} + +static void radeon_hide_cursor(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) { + WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset, + EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | + EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); + } else if (ASIC_IS_AVIVO(rdev)) { + WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, + (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); + } else { + u32 reg; + switch (radeon_crtc->crtc_id) { + case 0: + reg = RADEON_CRTC_GEN_CNTL; + break; + case 1: + reg = RADEON_CRTC2_GEN_CNTL; + break; + default: + return; + } + WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN); + } +} + +static void radeon_show_cursor(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) { + WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); + WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | + EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | + EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); + } else if (ASIC_IS_AVIVO(rdev)) { + WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); + WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | + (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); + } else { + switch (radeon_crtc->crtc_id) { + case 0: + WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); + break; + case 1: + WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); + break; + default: + return; + } + + WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | + (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), + ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); + } +} + +static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, + uint64_t gpu_addr) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) { + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(gpu_addr)); + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + gpu_addr & 0xffffffff); + } else if (ASIC_IS_AVIVO(rdev)) { + if (rdev->family >= CHIP_RV770) { + if (radeon_crtc->crtc_id) + WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); + else + WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); + } + WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + gpu_addr & 0xffffffff); + } else { + radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; + /* offset is from DISP(2)_BASE_ADDRESS */ + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); + } +} + +int radeon_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; + struct drm_gem_object *obj; + struct radeon_bo *robj; + uint64_t gpu_addr; + int ret; + + if (!handle) { + /* turn off cursor */ + radeon_hide_cursor(crtc); + obj = NULL; + goto unpin; + } + + if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { + DRM_ERROR("bad cursor width or height %d x %d\n", width, height); + return -EINVAL; + } + + obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); + if (!obj) { + DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); + return -ENOENT; + } + + robj = gem_to_radeon_bo(obj); + ret = radeon_bo_reserve(robj, false); + if (unlikely(ret != 0)) + goto fail; + /* Only 27 bit offset for legacy cursor */ + ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, + &gpu_addr); + radeon_bo_unreserve(robj); + if (ret) + goto fail; + + radeon_crtc->cursor_width = width; + radeon_crtc->cursor_height = height; + + radeon_lock_cursor(crtc, true); + radeon_set_cursor(crtc, obj, gpu_addr); + radeon_show_cursor(crtc); + radeon_lock_cursor(crtc, false); + +unpin: + if (radeon_crtc->cursor_bo) { + robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); + ret = radeon_bo_reserve(robj, false); + if (likely(ret == 0)) { + radeon_bo_unpin(robj); + radeon_bo_unreserve(robj); + } + drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); + } + + radeon_crtc->cursor_bo = obj; + return 0; +fail: + drm_gem_object_unreference_unlocked(obj); + + return ret; +} + +int radeon_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; + int xorigin = 0, yorigin = 0; + int w = radeon_crtc->cursor_width; + + if (ASIC_IS_AVIVO(rdev)) { + /* avivo cursor are offset into the total surface */ + x += crtc->x; + y += crtc->y; + } + DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); + + if (x < 0) { + xorigin = min(-x, CURSOR_WIDTH - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, CURSOR_HEIGHT - 1); + y = 0; + } + + /* fixed on DCE6 and newer */ + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { + int i = 0; + struct drm_crtc *crtc_p; + + /* avivo cursor image can't end on 128 pixel boundary or + * go past the end of the frame if both crtcs are enabled + */ + list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) { + if (crtc_p->enabled) + i++; + } + if (i > 1) { + int cursor_end, frame_end; + + cursor_end = x - xorigin + w; + frame_end = crtc->x + crtc->mode.crtc_hdisplay; + if (cursor_end >= frame_end) { + w = w - (cursor_end - frame_end); + if (!(frame_end & 0x7f)) + w--; + } else { + if (!(cursor_end & 0x7f)) + w--; + } + if (w <= 0) { + w = 1; + cursor_end = x - xorigin + w; + if (!(cursor_end & 0x7f)) { + x--; + if (x < 0) { + DRM_ERROR("%s: x(%d) < 0", __func__, x); + } + } + } + } + } + + radeon_lock_cursor(crtc, true); + if (ASIC_IS_DCE4(rdev)) { + WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y); + WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); + WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, + ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); + } else if (ASIC_IS_AVIVO(rdev)) { + WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y); + WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); + WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, + ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); + } else { + if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) + y *= 2; + + WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset, + (RADEON_CUR_LOCK + | (xorigin << 16) + | yorigin)); + WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset, + (RADEON_CUR_LOCK + | (x << 16) + | y)); + /* offset is from DISP(2)_BASE_ADDRESS */ + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + + (yorigin * 256))); + } + radeon_lock_cursor(crtc, false); + + return 0; +} diff --git a/sys/dev/drm2/radeon/radeon_device.c b/sys/dev/drm2/radeon/radeon_device.c new file mode 100644 index 00000000000..5ed74fdbe23 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_device.c @@ -0,0 +1,1551 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "atom.h" + +static const char radeon_family_name[][16] = { + "R100", + "RV100", + "RS100", + "RV200", + "RS200", + "R200", + "RV250", + "RS300", + "RV280", + "R300", + "R350", + "RV350", + "RV380", + "R420", + "R423", + "RV410", + "RS400", + "RS480", + "RS600", + "RS690", + "RS740", + "RV515", + "R520", + "RV530", + "RV560", + "RV570", + "R580", + "R600", + "RV610", + "RV630", + "RV670", + "RV620", + "RV635", + "RS780", + "RS880", + "RV770", + "RV730", + "RV710", + "RV740", + "CEDAR", + "REDWOOD", + "JUNIPER", + "CYPRESS", + "HEMLOCK", + "PALM", + "SUMO", + "SUMO2", + "BARTS", + "TURKS", + "CAICOS", + "CAYMAN", + "ARUBA", + "TAHITI", + "PITCAIRN", + "VERDE", + "LAST", +}; + +/** + * radeon_surface_init - Clear GPU surface registers. + * + * @rdev: radeon_device pointer + * + * Clear GPU surface registers (r1xx-r5xx). + */ +void radeon_surface_init(struct radeon_device *rdev) +{ + /* FIXME: check this out */ + if (rdev->family < CHIP_R600) { + int i; + + for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { + if (rdev->surface_regs[i].bo) + radeon_bo_get_surface_reg(rdev->surface_regs[i].bo); + else + radeon_clear_surface_reg(rdev, i); + } + /* enable surfaces */ + WREG32(RADEON_SURFACE_CNTL, 0); + } +} + +/* + * GPU scratch registers helpers function. + */ +/** + * radeon_scratch_init - Init scratch register driver information. + * + * @rdev: radeon_device pointer + * + * Init CP scratch register driver information (r1xx-r5xx) + */ +void radeon_scratch_init(struct radeon_device *rdev) +{ + int i; + + /* FIXME: check this out */ + if (rdev->family < CHIP_R300) { + rdev->scratch.num_reg = 5; + } else { + rdev->scratch.num_reg = 7; + } + rdev->scratch.reg_base = RADEON_SCRATCH_REG0; + for (i = 0; i < rdev->scratch.num_reg; i++) { + rdev->scratch.free[i] = true; + rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); + } +} + +/** + * radeon_scratch_get - Allocate a scratch register + * + * @rdev: radeon_device pointer + * @reg: scratch register mmio offset + * + * Allocate a CP scratch register for use by the driver (all asics). + * Returns 0 on success or -EINVAL on failure. + */ +int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) +{ + int i; + + for (i = 0; i < rdev->scratch.num_reg; i++) { + if (rdev->scratch.free[i]) { + rdev->scratch.free[i] = false; + *reg = rdev->scratch.reg[i]; + return 0; + } + } + return -EINVAL; +} + +/** + * radeon_scratch_free - Free a scratch register + * + * @rdev: radeon_device pointer + * @reg: scratch register mmio offset + * + * Free a CP scratch register allocated for use by the driver (all asics) + */ +void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) +{ + int i; + + for (i = 0; i < rdev->scratch.num_reg; i++) { + if (rdev->scratch.reg[i] == reg) { + rdev->scratch.free[i] = true; + return; + } + } +} + +/* + * radeon_wb_*() + * Writeback is the the method by which the the GPU updates special pages + * in memory with the status of certain GPU events (fences, ring pointers, + * etc.). + */ + +/** + * radeon_wb_disable - Disable Writeback + * + * @rdev: radeon_device pointer + * + * Disables Writeback (all asics). Used for suspend. + */ +void radeon_wb_disable(struct radeon_device *rdev) +{ + int r; + + if (rdev->wb.wb_obj) { + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) + return; + radeon_bo_kunmap(rdev->wb.wb_obj); + radeon_bo_unpin(rdev->wb.wb_obj); + radeon_bo_unreserve(rdev->wb.wb_obj); + } + rdev->wb.enabled = false; +} + +/** + * radeon_wb_fini - Disable Writeback and free memory + * + * @rdev: radeon_device pointer + * + * Disables Writeback and frees the Writeback memory (all asics). + * Used at driver shutdown. + */ +void radeon_wb_fini(struct radeon_device *rdev) +{ + radeon_wb_disable(rdev); + if (rdev->wb.wb_obj) { + radeon_bo_unref(&rdev->wb.wb_obj); + rdev->wb.wb = NULL; + rdev->wb.wb_obj = NULL; + } +} + +/** + * radeon_wb_init- Init Writeback driver info and allocate memory + * + * @rdev: radeon_device pointer + * + * Disables Writeback and frees the Writeback memory (all asics). + * Used at driver startup. + * Returns 0 on success or an -error on failure. + */ +int radeon_wb_init(struct radeon_device *rdev) +{ + int r; + void *wb_ptr; + + if (rdev->wb.wb_obj == NULL) { + r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, NULL, &rdev->wb.wb_obj); + if (r) { + dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); + return r; + } + } + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) { + radeon_wb_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, + &rdev->wb.gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->wb.wb_obj); + dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); + radeon_wb_fini(rdev); + return r; + } + wb_ptr = &rdev->wb.wb; + r = radeon_bo_kmap(rdev->wb.wb_obj, wb_ptr); + radeon_bo_unreserve(rdev->wb.wb_obj); + if (r) { + dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); + radeon_wb_fini(rdev); + return r; + } + + /* clear wb memory */ + memset(*(void **)wb_ptr, 0, RADEON_GPU_PAGE_SIZE); + /* disable event_write fences */ + rdev->wb.use_event = false; + /* disabled via module param */ + if (radeon_no_wb == 1) { + rdev->wb.enabled = false; + } else { + if (rdev->flags & RADEON_IS_AGP) { + /* often unreliable on AGP */ + rdev->wb.enabled = false; + } else if (rdev->family < CHIP_R300) { + /* often unreliable on pre-r300 */ + rdev->wb.enabled = false; + } else { + rdev->wb.enabled = true; + /* event_write fences are only available on r600+ */ + if (rdev->family >= CHIP_R600) { + rdev->wb.use_event = true; + } + } + } + /* always use writeback/events on NI, APUs */ + if (rdev->family >= CHIP_PALM) { + rdev->wb.enabled = true; + rdev->wb.use_event = true; + } + + dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); + + return 0; +} + +/** + * radeon_vram_location - try to find VRAM location + * @rdev: radeon device structure holding all necessary informations + * @mc: memory controller structure holding memory informations + * @base: base address at which to put VRAM + * + * Function will place try to place VRAM at base address provided + * as parameter (which is so far either PCI aperture address or + * for IGP TOM base address). + * + * If there is not enough space to fit the unvisible VRAM in the 32bits + * address space then we limit the VRAM size to the aperture. + * + * If we are using AGP and if the AGP aperture doesn't allow us to have + * room for all the VRAM than we restrict the VRAM to the PCI aperture + * size and print a warning. + * + * This function will never fails, worst case are limiting VRAM. + * + * Note: GTT start, end, size should be initialized before calling this + * function on AGP platform. + * + * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size, + * this shouldn't be a problem as we are using the PCI aperture as a reference. + * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but + * not IGP. + * + * Note: we use mc_vram_size as on some board we need to program the mc to + * cover the whole aperture even if VRAM size is inferior to aperture size + * Novell bug 204882 + along with lots of ubuntu ones + * + * Note: when limiting vram it's safe to overwritte real_vram_size because + * we are not in case where real_vram_size is inferior to mc_vram_size (ie + * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu + * ones) + * + * Note: IGP TOM addr should be the same as the aperture addr, we don't + * explicitly check for that thought. + * + * FIXME: when reducing VRAM size align new size on power of 2. + */ +void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base) +{ + uint64_t limit = (uint64_t)radeon_vram_limit << 20; + + mc->vram_start = base; + if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { + dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); + mc->real_vram_size = mc->aper_size; + mc->mc_vram_size = mc->aper_size; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) { + dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); + mc->real_vram_size = mc->aper_size; + mc->mc_vram_size = mc->aper_size; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + if (limit && limit < mc->real_vram_size) + mc->real_vram_size = limit; + dev_info(rdev->dev, "VRAM: %juM 0x%016jX - 0x%016jX (%juM used)\n", + (uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start, + (uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20); +} + +/** + * radeon_gtt_location - try to find GTT location + * @rdev: radeon device structure holding all necessary informations + * @mc: memory controller structure holding memory informations + * + * Function will place try to place GTT before or after VRAM. + * + * If GTT size is bigger than space left then we ajust GTT size. + * Thus function will never fails. + * + * FIXME: when reducing GTT size align new size on power of 2. + */ +void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +{ + u64 size_af, size_bf; + + size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; + size_bf = mc->vram_start & ~mc->gtt_base_align; + if (size_bf > size_af) { + if (mc->gtt_size > size_bf) { + dev_warn(rdev->dev, "limiting GTT\n"); + mc->gtt_size = size_bf; + } + mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; + } else { + if (mc->gtt_size > size_af) { + dev_warn(rdev->dev, "limiting GTT\n"); + mc->gtt_size = size_af; + } + mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; + } + mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; + dev_info(rdev->dev, "GTT: %juM 0x%016jX - 0x%016jX\n", + (uintmax_t)mc->gtt_size >> 20, (uintmax_t)mc->gtt_start, (uintmax_t)mc->gtt_end); +} + +/* + * GPU helpers function. + */ +/** + * radeon_card_posted - check if the hw has already been initialized + * + * @rdev: radeon_device pointer + * + * Check if the asic has been initialized (all asics). + * Used at driver startup. + * Returns true if initialized or false if not. + */ +bool radeon_card_posted(struct radeon_device *rdev) +{ + uint32_t reg; + +#ifdef DUMBBELL_WIP + if (efi_enabled(EFI_BOOT) && + rdev->dev->pci_subvendor == PCI_VENDOR_ID_APPLE) + return false; +#endif /* DUMBBELL_WIP */ + + /* first check CRTCs */ + if (ASIC_IS_DCE41(rdev)) { + reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (reg & EVERGREEN_CRTC_MASTER_EN) + return true; + } else if (ASIC_IS_DCE4(rdev)) { + reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (reg & EVERGREEN_CRTC_MASTER_EN) + return true; + } else if (ASIC_IS_AVIVO(rdev)) { + reg = RREG32(AVIVO_D1CRTC_CONTROL) | + RREG32(AVIVO_D2CRTC_CONTROL); + if (reg & AVIVO_CRTC_EN) { + return true; + } + } else { + reg = RREG32(RADEON_CRTC_GEN_CNTL) | + RREG32(RADEON_CRTC2_GEN_CNTL); + if (reg & RADEON_CRTC_EN) { + return true; + } + } + + /* then check MEM_SIZE, in case the crtcs are off */ + if (rdev->family >= CHIP_R600) + reg = RREG32(R600_CONFIG_MEMSIZE); + else + reg = RREG32(RADEON_CONFIG_MEMSIZE); + + if (reg) + return true; + + return false; + +} + +/** + * radeon_update_bandwidth_info - update display bandwidth params + * + * @rdev: radeon_device pointer + * + * Used when sclk/mclk are switched or display modes are set. + * params are used to calculate display watermarks (all asics) + */ +void radeon_update_bandwidth_info(struct radeon_device *rdev) +{ + fixed20_12 a; + u32 sclk = rdev->pm.current_sclk; + u32 mclk = rdev->pm.current_mclk; + + /* sclk/mclk in Mhz */ + a.full = dfixed_const(100); + rdev->pm.sclk.full = dfixed_const(sclk); + rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); + rdev->pm.mclk.full = dfixed_const(mclk); + rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + + if (rdev->flags & RADEON_IS_IGP) { + a.full = dfixed_const(16); + /* core_bandwidth = sclk(Mhz) * 16 */ + rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a); + } +} + +/** + * radeon_boot_test_post_card - check and possibly initialize the hw + * + * @rdev: radeon_device pointer + * + * Check if the asic is initialized and if not, attempt to initialize + * it (all asics). + * Returns true if initialized or false if not. + */ +bool radeon_boot_test_post_card(struct radeon_device *rdev) +{ + if (radeon_card_posted(rdev)) + return true; + + if (rdev->bios) { + DRM_INFO("GPU not posted. posting now...\n"); + if (rdev->is_atom_bios) + atom_asic_init(rdev->mode_info.atom_context); + else + radeon_combios_asic_init(rdev->ddev); + return true; + } else { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return false; + } +} + +/** + * radeon_dummy_page_init - init dummy page used by the driver + * + * @rdev: radeon_device pointer + * + * Allocate the dummy page used by the driver (all asics). + * This dummy page is used by the driver as a filler for gart entries + * when pages are taken out of the GART + * Returns 0 on sucess, -ENOMEM on failure. + */ +int radeon_dummy_page_init(struct radeon_device *rdev) +{ + if (rdev->dummy_page.dmah) + return 0; + rdev->dummy_page.dmah = drm_pci_alloc(rdev->ddev, + PAGE_SIZE, PAGE_SIZE, ~0); + if (rdev->dummy_page.dmah == NULL) + return -ENOMEM; + rdev->dummy_page.addr = (dma_addr_t)rdev->dummy_page.dmah->vaddr; + return 0; +} + +/** + * radeon_dummy_page_fini - free dummy page used by the driver + * + * @rdev: radeon_device pointer + * + * Frees the dummy page used by the driver (all asics). + */ +void radeon_dummy_page_fini(struct radeon_device *rdev) +{ + if (rdev->dummy_page.dmah == NULL) + return; + drm_pci_free(rdev->ddev, rdev->dummy_page.dmah); + rdev->dummy_page.dmah = NULL; + rdev->dummy_page.addr = 0; +} + + +/* ATOM accessor methods */ +/* + * ATOM is an interpreted byte code stored in tables in the vbios. The + * driver registers callbacks to access registers and the interpreter + * in the driver parses the tables and executes then to program specific + * actions (set display modes, asic init, etc.). See radeon_atombios.c, + * atombios.h, and atom.c + */ + +/** + * cail_pll_read - read PLL register + * + * @info: atom card_info pointer + * @reg: PLL register offset + * + * Provides a PLL register accessor for the atom interpreter (r4xx+). + * Returns the value of the PLL register. + */ +static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) +{ + struct radeon_device *rdev = info->dev->dev_private; + uint32_t r; + + r = rdev->pll_rreg(rdev, reg); + return r; +} + +/** + * cail_pll_write - write PLL register + * + * @info: atom card_info pointer + * @reg: PLL register offset + * @val: value to write to the pll register + * + * Provides a PLL register accessor for the atom interpreter (r4xx+). + */ +static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) +{ + struct radeon_device *rdev = info->dev->dev_private; + + rdev->pll_wreg(rdev, reg, val); +} + +/** + * cail_mc_read - read MC (Memory Controller) register + * + * @info: atom card_info pointer + * @reg: MC register offset + * + * Provides an MC register accessor for the atom interpreter (r4xx+). + * Returns the value of the MC register. + */ +static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) +{ + struct radeon_device *rdev = info->dev->dev_private; + uint32_t r; + + r = rdev->mc_rreg(rdev, reg); + return r; +} + +/** + * cail_mc_write - write MC (Memory Controller) register + * + * @info: atom card_info pointer + * @reg: MC register offset + * @val: value to write to the pll register + * + * Provides a MC register accessor for the atom interpreter (r4xx+). + */ +static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) +{ + struct radeon_device *rdev = info->dev->dev_private; + + rdev->mc_wreg(rdev, reg, val); +} + +/** + * cail_reg_write - write MMIO register + * + * @info: atom card_info pointer + * @reg: MMIO register offset + * @val: value to write to the pll register + * + * Provides a MMIO register accessor for the atom interpreter (r4xx+). + */ +static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) +{ + struct radeon_device *rdev = info->dev->dev_private; + + WREG32(reg*4, val); +} + +/** + * cail_reg_read - read MMIO register + * + * @info: atom card_info pointer + * @reg: MMIO register offset + * + * Provides an MMIO register accessor for the atom interpreter (r4xx+). + * Returns the value of the MMIO register. + */ +static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) +{ + struct radeon_device *rdev = info->dev->dev_private; + uint32_t r; + + r = RREG32(reg*4); + return r; +} + +/** + * cail_ioreg_write - write IO register + * + * @info: atom card_info pointer + * @reg: IO register offset + * @val: value to write to the pll register + * + * Provides a IO register accessor for the atom interpreter (r4xx+). + */ +static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) +{ + struct radeon_device *rdev = info->dev->dev_private; + + WREG32_IO(reg*4, val); +} + +/** + * cail_ioreg_read - read IO register + * + * @info: atom card_info pointer + * @reg: IO register offset + * + * Provides an IO register accessor for the atom interpreter (r4xx+). + * Returns the value of the IO register. + */ +static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) +{ + struct radeon_device *rdev = info->dev->dev_private; + uint32_t r; + + r = RREG32_IO(reg*4); + return r; +} + +/** + * radeon_atombios_init - init the driver info and callbacks for atombios + * + * @rdev: radeon_device pointer + * + * Initializes the driver info and register access callbacks for the + * ATOM interpreter (r4xx+). + * Returns 0 on sucess, -ENOMEM on failure. + * Called at driver startup. + */ +int radeon_atombios_init(struct radeon_device *rdev) +{ + struct card_info *atom_card_info = + malloc(sizeof(struct card_info), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + + if (!atom_card_info) + return -ENOMEM; + + rdev->mode_info.atom_card_info = atom_card_info; + atom_card_info->dev = rdev->ddev; + atom_card_info->reg_read = cail_reg_read; + atom_card_info->reg_write = cail_reg_write; + /* needed for iio ops */ + if (rdev->rio_mem) { + atom_card_info->ioreg_read = cail_ioreg_read; + atom_card_info->ioreg_write = cail_ioreg_write; + } else { + DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n"); + atom_card_info->ioreg_read = cail_reg_read; + atom_card_info->ioreg_write = cail_reg_write; + } + atom_card_info->mc_read = cail_mc_read; + atom_card_info->mc_write = cail_mc_write; + atom_card_info->pll_read = cail_pll_read; + atom_card_info->pll_write = cail_pll_write; + + rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); + sx_init(&rdev->mode_info.atom_context->mutex, + "drm__radeon_device__mode_info__atom_context__mutex"); + radeon_atom_initialize_bios_scratch_regs(rdev->ddev); + atom_allocate_fb_scratch(rdev->mode_info.atom_context); + return 0; +} + +/** + * radeon_atombios_fini - free the driver info and callbacks for atombios + * + * @rdev: radeon_device pointer + * + * Frees the driver info and register access callbacks for the ATOM + * interpreter (r4xx+). + * Called at driver shutdown. + */ +void radeon_atombios_fini(struct radeon_device *rdev) +{ + if (rdev->mode_info.atom_context) { + free(rdev->mode_info.atom_context->scratch, DRM_MEM_DRIVER); + atom_destroy(rdev->mode_info.atom_context); + } + free(rdev->mode_info.atom_card_info, DRM_MEM_DRIVER); +} + +/* COMBIOS */ +/* + * COMBIOS is the bios format prior to ATOM. It provides + * command tables similar to ATOM, but doesn't have a unified + * parser. See radeon_combios.c + */ + +/** + * radeon_combios_init - init the driver info for combios + * + * @rdev: radeon_device pointer + * + * Initializes the driver info for combios (r1xx-r3xx). + * Returns 0 on sucess. + * Called at driver startup. + */ +int radeon_combios_init(struct radeon_device *rdev) +{ + radeon_combios_initialize_bios_scratch_regs(rdev->ddev); + return 0; +} + +/** + * radeon_combios_fini - free the driver info for combios + * + * @rdev: radeon_device pointer + * + * Frees the driver info for combios (r1xx-r3xx). + * Called at driver shutdown. + */ +void radeon_combios_fini(struct radeon_device *rdev) +{ +} + +#ifdef DUMBBELL_WIP +/* if we get transitioned to only one device, take VGA back */ +/** + * radeon_vga_set_decode - enable/disable vga decode + * + * @cookie: radeon_device pointer + * @state: enable/disable vga decode + * + * Enable/disable vga decode (all asics). + * Returns VGA resource flags. + */ +static unsigned int radeon_vga_set_decode(void *cookie, bool state) +{ + struct radeon_device *rdev = cookie; + radeon_vga_set_state(rdev, state); + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} +#endif /* DUMBBELL_WIP */ + +/** + * radeon_check_pot_argument - check that argument is a power of two + * + * @arg: value to check + * + * Validates that a certain argument is a power of two (all asics). + * Returns true if argument is valid. + */ +static bool radeon_check_pot_argument(int arg) +{ + return (arg & (arg - 1)) == 0; +} + +/** + * radeon_check_arguments - validate module params + * + * @rdev: radeon_device pointer + * + * Validates certain module parameters and updates + * the associated values used by the driver (all asics). + */ +static void radeon_check_arguments(struct radeon_device *rdev) +{ + /* vramlimit must be a power of two */ + if (!radeon_check_pot_argument(radeon_vram_limit)) { + dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", + radeon_vram_limit); + radeon_vram_limit = 0; + } + + /* gtt size must be power of two and greater or equal to 32M */ + if (radeon_gart_size < 32) { + dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", + radeon_gart_size); + radeon_gart_size = 512; + + } else if (!radeon_check_pot_argument(radeon_gart_size)) { + dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", + radeon_gart_size); + radeon_gart_size = 512; + } + rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; + + /* AGP mode can only be -1, 1, 2, 4, 8 */ + switch (radeon_agpmode) { + case -1: + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: " + "-1, 0, 1, 2, 4, 8)\n", radeon_agpmode); + radeon_agpmode = 0; + break; + } +} + +/** + * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is + * needed for waking up. + * + * @pdev: pci dev pointer + */ +#ifdef DUMBBELL_WIP +static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) +{ + + /* 6600m in a macbook pro */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && + pdev->subsystem_device == 0x00e2) { + printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n"); + return true; + } + + return false; +} +#endif /* DUMBBELL_WIP */ + +/** + * radeon_switcheroo_set_state - set switcheroo state + * + * @pdev: pci dev pointer + * @state: vga switcheroo state + * + * Callback for the switcheroo driver. Suspends or resumes the + * the asics before or after it is powered up using ACPI methods. + */ +#ifdef DUMBBELL_WIP +static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; + if (state == VGA_SWITCHEROO_ON) { + unsigned d3_delay = dev->pdev->d3_delay; + + printk(KERN_INFO "radeon: switched on\n"); + /* don't suspend or resume card normally */ + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + + if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev)) + dev->pdev->d3_delay = 20; + + radeon_resume_kms(dev); + + dev->pdev->d3_delay = d3_delay; + + dev->switch_power_state = DRM_SWITCH_POWER_ON; + drm_kms_helper_poll_enable(dev); + } else { + printk(KERN_INFO "radeon: switched off\n"); + drm_kms_helper_poll_disable(dev); + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + radeon_suspend_kms(dev, pmm); + dev->switch_power_state = DRM_SWITCH_POWER_OFF; + } +} +#endif /* DUMBBELL_WIP */ + +/** + * radeon_switcheroo_can_switch - see if switcheroo state can change + * + * @pdev: pci dev pointer + * + * Callback for the switcheroo driver. Check of the switcheroo + * state can be changed. + * Returns true if the state can be changed, false if not. + */ +#ifdef DUMBBELL_WIP +static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + bool can_switch; + + spin_lock(&dev->count_lock); + can_switch = (dev->open_count == 0); + spin_unlock(&dev->count_lock); + return can_switch; +} + +static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { + .set_gpu_state = radeon_switcheroo_set_state, + .reprobe = NULL, + .can_switch = radeon_switcheroo_can_switch, +}; +#endif /* DUMBBELL_WIP */ + +/** + * radeon_device_init - initialize the driver + * + * @rdev: radeon_device pointer + * @pdev: drm dev pointer + * @flags: driver flags + * + * Initializes the driver info and hw (all asics). + * Returns 0 for success or an error on failure. + * Called at driver startup. + */ +int radeon_device_init(struct radeon_device *rdev, + struct drm_device *ddev, + uint32_t flags) +{ + int r, i; + int dma_bits; + + rdev->shutdown = false; + rdev->dev = ddev->device; + rdev->ddev = ddev; + rdev->flags = flags; + rdev->family = flags & RADEON_FAMILY_MASK; + rdev->is_atom_bios = false; + rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; + rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + rdev->accel_working = false; + rdev->fictitious_range_registered = false; + /* set up ring ids */ + for (i = 0; i < RADEON_NUM_RINGS; i++) { + rdev->ring[i].idx = i; + } + + DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", + radeon_family_name[rdev->family], ddev->pci_vendor, ddev->pci_device, + ddev->pci_subvendor, ddev->pci_subdevice); + + /* mutex initialization are all done here so we + * can recall function without having locking issues */ + sx_init(&rdev->ring_lock, "drm__radeon_device__ring_lock"); + sx_init(&rdev->dc_hw_i2c_mutex, "drm__radeon_device__dc_hw_i2c_mutex"); + atomic_set(&rdev->ih.lock, 0); + sx_init(&rdev->gem.mutex, "drm__radeon_device__gem__mutex"); + sx_init(&rdev->pm.mutex, "drm__radeon_device__pm__mutex"); + sx_init(&rdev->gpu_clock_mutex, "drm__radeon_device__gpu_clock_mutex"); + sx_init(&rdev->pm.mclk_lock, "drm__radeon_device__pm__mclk_lock"); + sx_init(&rdev->exclusive_lock, "drm__radeon_device__exclusive_lock"); + DRM_INIT_WAITQUEUE(&rdev->irq.vblank_queue); + r = radeon_gem_init(rdev); + if (r) + return r; + /* initialize vm here */ + sx_init(&rdev->vm_manager.lock, "drm__radeon_device__vm_manager__lock"); + /* Adjust VM size here. + * Currently set to 4GB ((1 << 20) 4k pages). + * Max GPUVM size for cayman and SI is 40 bits. + */ + rdev->vm_manager.max_pfn = 1 << 20; + INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); + + /* Set asic functions */ + r = radeon_asic_init(rdev); + if (r) + return r; + radeon_check_arguments(rdev); + + /* all of the newer IGP chips have an internal gart + * However some rs4xx report as AGP, so remove that here. + */ + if ((rdev->family >= CHIP_RS400) && + (rdev->flags & RADEON_IS_IGP)) { + rdev->flags &= ~RADEON_IS_AGP; + } + + if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) { + radeon_agp_disable(rdev); + } + + /* set DMA mask + need_dma32 flags. + * PCIE - can handle 40-bits. + * IGP - can handle 40-bits + * AGP - generally dma32 is safest + * PCI - dma32 for legacy pci gart, 40 bits on newer asics + */ + rdev->need_dma32 = false; + if (rdev->flags & RADEON_IS_AGP) + rdev->need_dma32 = true; + if ((rdev->flags & RADEON_IS_PCI) && + (rdev->family <= CHIP_RS740)) + rdev->need_dma32 = true; + + dma_bits = rdev->need_dma32 ? 32 : 40; +#ifdef DUMBBELL_WIP + r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + rdev->need_dma32 = true; + dma_bits = 32; + printk(KERN_WARNING "radeon: No suitable DMA available.\n"); + } + r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); + printk(KERN_WARNING "radeon: No coherent DMA available.\n"); + } +#endif /* DUMBBELL_WIP */ + + /* Registers mapping */ + /* TODO: block userspace mapping of io register */ + DRM_SPININIT(&rdev->mmio_idx_lock, "drm__radeon_device__mmio_idx_lock"); + rdev->rmmio_rid = PCIR_BAR(2); + rdev->rmmio = bus_alloc_resource_any(rdev->dev, SYS_RES_MEMORY, + &rdev->rmmio_rid, RF_ACTIVE | RF_SHAREABLE); + if (rdev->rmmio == NULL) { + return -ENOMEM; + } + rdev->rmmio_base = rman_get_start(rdev->rmmio); + rdev->rmmio_size = rman_get_size(rdev->rmmio); + DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base); + DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); + + /* io port mapping */ + for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) { + uint32_t data; + + data = pci_read_config(rdev->dev, PCIR_BAR(i), 4); + if (PCI_BAR_IO(data)) { + rdev->rio_rid = PCIR_BAR(i); + rdev->rio_mem = bus_alloc_resource_any(rdev->dev, + SYS_RES_IOPORT, &rdev->rio_rid, + RF_ACTIVE | RF_SHAREABLE); + break; + } + } + if (rdev->rio_mem == NULL) + DRM_ERROR("Unable to find PCI I/O BAR\n"); + + rdev->tq = taskqueue_create("radeonkms", M_WAITOK, + taskqueue_thread_enqueue, &rdev->tq); + taskqueue_start_threads(&rdev->tq, 1, PWAIT, "radeon taskq"); + +#ifdef DUMBBELL_WIP + /* if we have > 1 VGA cards, then disable the radeon VGA resources */ + /* this will fail for cards that aren't VGA class devices, just + * ignore it */ + vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); + vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops); +#endif /* DUMBBELL_WIP */ + + r = radeon_init(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) + DRM_ERROR("ib ring test failed (%d).\n", r); + + if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { + /* Acceleration not working on AGP card try again + * with fallback to PCI or PCIE GART + */ + radeon_asic_reset(rdev); + radeon_fini(rdev); + radeon_agp_disable(rdev); + r = radeon_init(rdev); + if (r) + return r; + } + + DRM_INFO("%s: Taking over the fictitious range 0x%jx-0x%jx\n", + __func__, (uintmax_t)rdev->mc.aper_base, + (uintmax_t)rdev->mc.aper_base + rdev->mc.visible_vram_size); + r = vm_phys_fictitious_reg_range( + rdev->mc.aper_base, + rdev->mc.aper_base + rdev->mc.visible_vram_size, + VM_MEMATTR_WRITE_COMBINING); + if (r != 0) { + DRM_ERROR("Failed to register fictitious range " + "0x%jx-0x%jx (%d).\n", (uintmax_t)rdev->mc.aper_base, + (uintmax_t)rdev->mc.aper_base + rdev->mc.visible_vram_size, r); + return (-r); + } + rdev->fictitious_range_registered = true; + + if ((radeon_testing & 1)) { + radeon_test_moves(rdev); + } + if ((radeon_testing & 2)) { + radeon_test_syncing(rdev); + } + if (radeon_benchmarking) { + radeon_benchmark(rdev, radeon_benchmarking); + } + return 0; +} + +#ifdef DUMBBELL_WIP +static void radeon_debugfs_remove_files(struct radeon_device *rdev); +#endif /* DUMBBELL_WIP */ + +/** + * radeon_device_fini - tear down the driver + * + * @rdev: radeon_device pointer + * + * Tear down the driver info (all asics). + * Called at driver shutdown. + */ +void radeon_device_fini(struct radeon_device *rdev) +{ + DRM_INFO("radeon: finishing device.\n"); + rdev->shutdown = true; + /* evict vram memory */ + radeon_bo_evict_vram(rdev); + + if (rdev->fictitious_range_registered) { + vm_phys_fictitious_unreg_range( + rdev->mc.aper_base, + rdev->mc.aper_base + rdev->mc.visible_vram_size); + } + + radeon_fini(rdev); +#ifdef DUMBBELL_WIP + vga_switcheroo_unregister_client(rdev->pdev); + vga_client_register(rdev->pdev, NULL, NULL, NULL); +#endif /* DUMBBELL_WIP */ + + if (rdev->tq != NULL) { + taskqueue_free(rdev->tq); + rdev->tq = NULL; + } + + if (rdev->rio_mem) + bus_release_resource(rdev->dev, SYS_RES_IOPORT, rdev->rio_rid, + rdev->rio_mem); + rdev->rio_mem = NULL; + bus_release_resource(rdev->dev, SYS_RES_MEMORY, rdev->rmmio_rid, + rdev->rmmio); + rdev->rmmio = NULL; +#ifdef DUMBBELL_WIP + radeon_debugfs_remove_files(rdev); +#endif /* DUMBBELL_WIP */ +} + + +/* + * Suspend & resume. + */ +/** + * radeon_suspend_kms - initiate device suspend + * + * @pdev: drm dev pointer + * @state: suspend state + * + * Puts the hw in the suspend state (all asics). + * Returns 0 for success or an error on failure. + * Called at driver suspend. + */ +int radeon_suspend_kms(struct drm_device *dev) +{ + struct radeon_device *rdev; + struct drm_crtc *crtc; + struct drm_connector *connector; + int i, r; + bool force_completion = false; + + if (dev == NULL || dev->dev_private == NULL) { + return -ENODEV; + } +#ifdef DUMBBELL_WIP + if (state.event == PM_EVENT_PRETHAW) { + return 0; + } +#endif /* DUMBBELL_WIP */ + rdev = dev->dev_private; + + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + + drm_kms_helper_poll_disable(dev); + + /* turn off display hw */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } + + /* unpin the front buffers */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); + struct radeon_bo *robj; + + if (rfb == NULL || rfb->obj == NULL) { + continue; + } + robj = gem_to_radeon_bo(rfb->obj); + /* don't unpin kernel fb objects */ + if (!radeon_fbdev_robj_is_fb(rdev, robj)) { + r = radeon_bo_reserve(robj, false); + if (r == 0) { + radeon_bo_unpin(robj); + radeon_bo_unreserve(robj); + } + } + } + /* evict vram memory */ + radeon_bo_evict_vram(rdev); + + sx_xlock(&rdev->ring_lock); + /* wait for gpu to finish processing current batch */ + for (i = 0; i < RADEON_NUM_RINGS; i++) { + r = radeon_fence_wait_empty_locked(rdev, i); + if (r) { + /* delay GPU reset to resume */ + force_completion = true; + } + } + if (force_completion) { + radeon_fence_driver_force_completion(rdev); + } + sx_xunlock(&rdev->ring_lock); + + radeon_save_bios_scratch_regs(rdev); + + radeon_pm_suspend(rdev); + radeon_suspend(rdev); + radeon_hpd_fini(rdev); + /* evict remaining vram memory */ + radeon_bo_evict_vram(rdev); + + radeon_agp_suspend(rdev); + + pci_save_state(dev->device); +#ifdef DUMBBELL_WIP + if (state.event == PM_EVENT_SUSPEND) { + /* Shut down the device */ + pci_disable_device(dev->pdev); +#endif /* DUMBBELL_WIP */ + pci_set_powerstate(dev->device, PCI_POWERSTATE_D3); +#ifdef DUMBBELL_WIP + } + console_lock(); +#endif /* DUMBBELL_WIP */ + radeon_fbdev_set_suspend(rdev, 1); +#ifdef DUMBBELL_WIP + console_unlock(); +#endif /* DUMBBELL_WIP */ + return 0; +} + +/** + * radeon_resume_kms - initiate device resume + * + * @pdev: drm dev pointer + * + * Bring the hw back to operating state (all asics). + * Returns 0 for success or an error on failure. + * Called at driver resume. + */ +int radeon_resume_kms(struct drm_device *dev) +{ + struct drm_connector *connector; + struct radeon_device *rdev = dev->dev_private; + int r; + + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + +#ifdef DUMBBELL_WIP + console_lock(); +#endif /* DUMBBELL_WIP */ + pci_set_powerstate(dev->device, PCI_POWERSTATE_D0); + pci_restore_state(dev->device); +#ifdef DUMBBELL_WIP + if (pci_enable_device(dev->pdev)) { + console_unlock(); + return -1; + } +#endif /* DUMBBELL_WIP */ + /* resume AGP if in use */ + radeon_agp_resume(rdev); + radeon_resume(rdev); + + r = radeon_ib_ring_tests(rdev); + if (r) + DRM_ERROR("ib ring test failed (%d).\n", r); + + radeon_pm_resume(rdev); + radeon_restore_bios_scratch_regs(rdev); + + radeon_fbdev_set_suspend(rdev, 0); +#ifdef DUMBBELL_WIP + console_unlock(); +#endif /* DUMBBELL_WIP */ + + /* init dig PHYs, disp eng pll */ + if (rdev->is_atom_bios) { + radeon_atom_encoder_init(rdev); + radeon_atom_disp_eng_pll_init(rdev); + /* turn on the BL */ + if (rdev->mode_info.bl_encoder) { + u8 bl_level = radeon_get_backlight_level(rdev, + rdev->mode_info.bl_encoder); + radeon_set_backlight_level(rdev, rdev->mode_info.bl_encoder, + bl_level); + } + } + /* reset hpd state */ + radeon_hpd_init(rdev); + /* blat the mode back in */ + drm_helper_resume_force_mode(dev); + /* turn on display hw */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + + drm_kms_helper_poll_enable(dev); + return 0; +} + +/** + * radeon_gpu_reset - reset the asic + * + * @rdev: radeon device pointer + * + * Attempt the reset the GPU if it has hung (all asics). + * Returns 0 for success or an error on failure. + */ +int radeon_gpu_reset(struct radeon_device *rdev) +{ + unsigned ring_sizes[RADEON_NUM_RINGS]; + uint32_t *ring_data[RADEON_NUM_RINGS]; + + bool saved = false; + + int i, r; + int resched; + + sx_xlock(&rdev->exclusive_lock); + radeon_save_bios_scratch_regs(rdev); + /* block TTM */ + resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); + radeon_suspend(rdev); + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], + &ring_data[i]); + if (ring_sizes[i]) { + saved = true; + dev_info(rdev->dev, "Saved %d dwords of commands " + "on ring %d.\n", ring_sizes[i], i); + } + } + +retry: + r = radeon_asic_reset(rdev); + if (!r) { + dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n"); + radeon_resume(rdev); + } + + radeon_restore_bios_scratch_regs(rdev); + + if (!r) { + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + radeon_ring_restore(rdev, &rdev->ring[i], + ring_sizes[i], ring_data[i]); + ring_sizes[i] = 0; + ring_data[i] = NULL; + } + + r = radeon_ib_ring_tests(rdev); + if (r) { + dev_err(rdev->dev, "ib ring test failed (%d).\n", r); + if (saved) { + saved = false; + radeon_suspend(rdev); + goto retry; + } + } + } else { + radeon_fence_driver_force_completion(rdev); + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + free(ring_data[i], DRM_MEM_DRIVER); + } + } + + drm_helper_resume_force_mode(rdev->ddev); + + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + if (r) { + /* bad news, how to tell it to userspace ? */ + dev_info(rdev->dev, "GPU reset failed\n"); + } + + sx_xunlock(&rdev->exclusive_lock); + return r; +} + + +/* + * Debugfs + */ +#ifdef DUMBBELL_WIP +int radeon_debugfs_add_files(struct radeon_device *rdev, + struct drm_info_list *files, + unsigned nfiles) +{ + unsigned i; + + for (i = 0; i < rdev->debugfs_count; i++) { + if (rdev->debugfs[i].files == files) { + /* Already registered */ + return 0; + } + } + + i = rdev->debugfs_count + 1; + if (i > RADEON_DEBUGFS_MAX_COMPONENTS) { + DRM_ERROR("Reached maximum number of debugfs components.\n"); + DRM_ERROR("Report so we increase " + "RADEON_DEBUGFS_MAX_COMPONENTS.\n"); + return -EINVAL; + } + rdev->debugfs[rdev->debugfs_count].files = files; + rdev->debugfs[rdev->debugfs_count].num_files = nfiles; + rdev->debugfs_count = i; +#if defined(CONFIG_DEBUG_FS) + drm_debugfs_create_files(files, nfiles, + rdev->ddev->control->debugfs_root, + rdev->ddev->control); + drm_debugfs_create_files(files, nfiles, + rdev->ddev->primary->debugfs_root, + rdev->ddev->primary); +#endif + return 0; +} + +static void radeon_debugfs_remove_files(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + unsigned i; + + for (i = 0; i < rdev->debugfs_count; i++) { + drm_debugfs_remove_files(rdev->debugfs[i].files, + rdev->debugfs[i].num_files, + rdev->ddev->control); + drm_debugfs_remove_files(rdev->debugfs[i].files, + rdev->debugfs[i].num_files, + rdev->ddev->primary); + } +#endif +} + +#if defined(CONFIG_DEBUG_FS) +int radeon_debugfs_init(struct drm_minor *minor) +{ + return 0; +} + +void radeon_debugfs_cleanup(struct drm_minor *minor) +{ +} +#endif /* DUMBBELL_WIP */ +#endif diff --git a/sys/dev/drm2/radeon/radeon_display.c b/sys/dev/drm2/radeon/radeon_display.c new file mode 100644 index 00000000000..45c3b0cef68 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_display.c @@ -0,0 +1,1691 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" + +#include "atom.h" + +#include +#include + +static void avivo_crtc_load_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int i; + + DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); + WREG32(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0); + + WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); + WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0); + WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0); + + WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff); + WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff); + WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff); + + WREG32(AVIVO_DC_LUT_RW_SELECT, radeon_crtc->crtc_id); + WREG32(AVIVO_DC_LUT_RW_MODE, 0); + WREG32(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f); + + WREG8(AVIVO_DC_LUT_RW_INDEX, 0); + for (i = 0; i < 256; i++) { + WREG32(AVIVO_DC_LUT_30_COLOR, + (radeon_crtc->lut_r[i] << 20) | + (radeon_crtc->lut_g[i] << 10) | + (radeon_crtc->lut_b[i] << 0)); + } + + WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id); +} + +static void dce4_crtc_load_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int i; + + DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); + WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff); + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff); + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff); + + WREG32(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007); + + WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0); + for (i = 0; i < 256; i++) { + WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset, + (radeon_crtc->lut_r[i] << 20) | + (radeon_crtc->lut_g[i] << 10) | + (radeon_crtc->lut_b[i] << 0)); + } +} + +static void dce5_crtc_load_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int i; + + DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); + + WREG32(NI_INPUT_CSC_CONTROL + radeon_crtc->crtc_offset, + (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) | + NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS))); + WREG32(NI_PRESCALE_GRPH_CONTROL + radeon_crtc->crtc_offset, + NI_GRPH_PRESCALE_BYPASS); + WREG32(NI_PRESCALE_OVL_CONTROL + radeon_crtc->crtc_offset, + NI_OVL_PRESCALE_BYPASS); + WREG32(NI_INPUT_GAMMA_CONTROL + radeon_crtc->crtc_offset, + (NI_GRPH_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT) | + NI_OVL_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT))); + + WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff); + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff); + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff); + + WREG32(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007); + + WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0); + for (i = 0; i < 256; i++) { + WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset, + (radeon_crtc->lut_r[i] << 20) | + (radeon_crtc->lut_g[i] << 10) | + (radeon_crtc->lut_b[i] << 0)); + } + + WREG32(NI_DEGAMMA_CONTROL + radeon_crtc->crtc_offset, + (NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) | + NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) | + NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) | + NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS))); + WREG32(NI_GAMUT_REMAP_CONTROL + radeon_crtc->crtc_offset, + (NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) | + NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS))); + WREG32(NI_REGAMMA_CONTROL + radeon_crtc->crtc_offset, + (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) | + NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS))); + WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset, + (NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) | + NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS))); + /* XXX match this to the depth of the crtc fmt block, move to modeset? */ + WREG32(0x6940 + radeon_crtc->crtc_offset, 0); + +} + +static void legacy_crtc_load_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int i; + uint32_t dac2_cntl; + + dac2_cntl = RREG32(RADEON_DAC_CNTL2); + if (radeon_crtc->crtc_id == 0) + dac2_cntl &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL; + else + dac2_cntl |= RADEON_DAC2_PALETTE_ACC_CTL; + WREG32(RADEON_DAC_CNTL2, dac2_cntl); + + WREG8(RADEON_PALETTE_INDEX, 0); + for (i = 0; i < 256; i++) { + WREG32(RADEON_PALETTE_30_DATA, + (radeon_crtc->lut_r[i] << 20) | + (radeon_crtc->lut_g[i] << 10) | + (radeon_crtc->lut_b[i] << 0)); + } +} + +void radeon_crtc_load_lut(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + + if (!crtc->enabled) + return; + + if (ASIC_IS_DCE5(rdev)) + dce5_crtc_load_lut(crtc); + else if (ASIC_IS_DCE4(rdev)) + dce4_crtc_load_lut(crtc); + else if (ASIC_IS_AVIVO(rdev)) + avivo_crtc_load_lut(crtc); + else + legacy_crtc_load_lut(crtc); +} + +/** Sets the color ramps on behalf of fbcon */ +void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + radeon_crtc->lut_r[regno] = red >> 6; + radeon_crtc->lut_g[regno] = green >> 6; + radeon_crtc->lut_b[regno] = blue >> 6; +} + +/** Gets the color ramps on behalf of fbcon */ +void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + *red = radeon_crtc->lut_r[regno] << 6; + *green = radeon_crtc->lut_g[regno] << 6; + *blue = radeon_crtc->lut_b[regno] << 6; +} + +static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, uint32_t start, uint32_t size) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + int end = (start + size > 256) ? 256 : start + size, i; + + /* userspace palettes are always correct as is */ + for (i = start; i < end; i++) { + radeon_crtc->lut_r[i] = red[i] >> 6; + radeon_crtc->lut_g[i] = green[i] >> 6; + radeon_crtc->lut_b[i] = blue[i] >> 6; + } + radeon_crtc_load_lut(crtc); +} + +static void radeon_crtc_destroy(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + drm_crtc_cleanup(crtc); + free(radeon_crtc, DRM_MEM_DRIVER); +} + +/* + * Handle unpin events outside the interrupt handler proper. + */ +static void radeon_unpin_work_func(void *arg, int pending) +{ + struct radeon_unpin_work *work = arg; + int r; + + /* unpin of the old buffer */ + r = radeon_bo_reserve(work->old_rbo, false); + if (likely(r == 0)) { + r = radeon_bo_unpin(work->old_rbo); + if (unlikely(r != 0)) { + DRM_ERROR("failed to unpin buffer after flip\n"); + } + radeon_bo_unreserve(work->old_rbo); + } else + DRM_ERROR("failed to reserve buffer after flip\n"); + + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); + free(work, DRM_MEM_DRIVER); +} + +void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + struct radeon_unpin_work *work; + struct drm_pending_vblank_event *e; + struct timeval now; + unsigned long flags; + u32 update_pending; + int vpos, hpos; + + DRM_SPINLOCK_IRQSAVE(&rdev->ddev->event_lock, flags); + work = radeon_crtc->unpin_work; + if (work == NULL || + (work->fence && !radeon_fence_signaled(work->fence))) { + DRM_SPINUNLOCK_IRQRESTORE(&rdev->ddev->event_lock, flags); + return; + } + /* New pageflip, or just completion of a previous one? */ + if (!radeon_crtc->deferred_flip_completion) { + /* do the flip (mmio) */ + update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base); + } else { + /* This is just a completion of a flip queued in crtc + * at last invocation. Make sure we go directly to + * completion routine. + */ + update_pending = 0; + radeon_crtc->deferred_flip_completion = 0; + } + + /* Has the pageflip already completed in crtc, or is it certain + * to complete in this vblank? + */ + if (update_pending && + (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, + &vpos, &hpos)) && + ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || + (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { + /* crtc didn't flip in this target vblank interval, + * but flip is pending in crtc. Based on the current + * scanout position we know that the current frame is + * (nearly) complete and the flip will (likely) + * complete before the start of the next frame. + */ + update_pending = 0; + } + if (update_pending) { + /* crtc didn't flip in this target vblank interval, + * but flip is pending in crtc. It will complete it + * in next vblank interval, so complete the flip at + * next vblank irq. + */ + radeon_crtc->deferred_flip_completion = 1; + DRM_SPINUNLOCK_IRQRESTORE(&rdev->ddev->event_lock, flags); + return; + } + + /* Pageflip (will be) certainly completed in this vblank. Clean up. */ + radeon_crtc->unpin_work = NULL; + + /* wakeup userspace */ + if (work->event) { + e = work->event; + e->event.sequence = drm_vblank_count_and_time(rdev->ddev, crtc_id, &now); + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + list_add_tail(&e->base.link, &e->base.file_priv->event_list); +#ifdef DUMBBELL_WIP + wake_up_interruptible(&e->base.file_priv->event_wait); +#endif /* DUMBBELL_WIP */ + } + DRM_SPINUNLOCK_IRQRESTORE(&rdev->ddev->event_lock, flags); + + drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); + radeon_fence_unref(&work->fence); + radeon_post_page_flip(work->rdev, work->crtc_id); + taskqueue_enqueue(rdev->tq, &work->work); +} + +static int radeon_crtc_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_framebuffer *old_radeon_fb; + struct radeon_framebuffer *new_radeon_fb; + struct drm_gem_object *obj; + struct radeon_bo *rbo; + struct radeon_unpin_work *work; + unsigned long flags; + u32 tiling_flags, pitch_pixels; + u64 base; + int r; + + work = malloc(sizeof *work, DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (work == NULL) + return -ENOMEM; + + work->event = event; + work->rdev = rdev; + work->crtc_id = radeon_crtc->crtc_id; + old_radeon_fb = to_radeon_framebuffer(crtc->fb); + new_radeon_fb = to_radeon_framebuffer(fb); + /* schedule unpin of the old buffer */ + obj = old_radeon_fb->obj; + /* take a reference to the old object */ + drm_gem_object_reference(obj); + rbo = gem_to_radeon_bo(obj); + work->old_rbo = rbo; + obj = new_radeon_fb->obj; + rbo = gem_to_radeon_bo(obj); + + mtx_lock(&rbo->tbo.bdev->fence_lock); + if (rbo->tbo.sync_obj) + work->fence = radeon_fence_ref(rbo->tbo.sync_obj); + mtx_unlock(&rbo->tbo.bdev->fence_lock); + + TASK_INIT(&work->work, 0, radeon_unpin_work_func, work); + + /* We borrow the event spin lock for protecting unpin_work */ + DRM_SPINLOCK_IRQSAVE(&dev->event_lock, flags); + if (radeon_crtc->unpin_work) { + DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); + r = -EBUSY; + goto unlock_free; + } + radeon_crtc->unpin_work = work; + radeon_crtc->deferred_flip_completion = 0; + DRM_SPINUNLOCK_IRQRESTORE(&dev->event_lock, flags); + + /* pin the new buffer */ + DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", + work->old_rbo, rbo); + + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve new rbo buffer before flip\n"); + goto pflip_cleanup; + } + /* Only 27 bit offset for legacy CRTC */ + r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + r = -EINVAL; + DRM_ERROR("failed to pin new rbo buffer before flip\n"); + goto pflip_cleanup; + } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); + + if (!ASIC_IS_AVIVO(rdev)) { + /* crtc offset is from display base addr not FB location */ + base -= radeon_crtc->legacy_display_base_addr; + pitch_pixels = fb->pitches[0] / (fb->bits_per_pixel / 8); + + if (tiling_flags & RADEON_TILING_MACRO) { + if (ASIC_IS_R300(rdev)) { + base &= ~0x7ff; + } else { + int byteshift = fb->bits_per_pixel >> 4; + int tile_addr = (((crtc->y >> 3) * pitch_pixels + crtc->x) >> (8 - byteshift)) << 11; + base += tile_addr + ((crtc->x << byteshift) % 256) + ((crtc->y % 8) << 8); + } + } else { + int offset = crtc->y * pitch_pixels + crtc->x; + switch (fb->bits_per_pixel) { + case 8: + default: + offset *= 1; + break; + case 15: + case 16: + offset *= 2; + break; + case 24: + offset *= 3; + break; + case 32: + offset *= 4; + break; + } + base += offset; + } + base &= ~7; + } + + DRM_SPINLOCK_IRQSAVE(&dev->event_lock, flags); + work->new_crtc_base = base; + DRM_SPINUNLOCK_IRQRESTORE(&dev->event_lock, flags); + + /* update crtc fb */ + crtc->fb = fb; + + r = drm_vblank_get(dev, radeon_crtc->crtc_id); + if (r) { + DRM_ERROR("failed to get vblank before flip\n"); + goto pflip_cleanup1; + } + + /* set the proper interrupt */ + radeon_pre_page_flip(rdev, radeon_crtc->crtc_id); + + return 0; + +pflip_cleanup1: + if (unlikely(radeon_bo_reserve(rbo, false) != 0)) { + DRM_ERROR("failed to reserve new rbo in error path\n"); + goto pflip_cleanup; + } + if (unlikely(radeon_bo_unpin(rbo) != 0)) { + DRM_ERROR("failed to unpin new rbo in error path\n"); + } + radeon_bo_unreserve(rbo); + +pflip_cleanup: + DRM_SPINLOCK_IRQSAVE(&dev->event_lock, flags); + radeon_crtc->unpin_work = NULL; +unlock_free: + DRM_SPINUNLOCK_IRQRESTORE(&dev->event_lock, flags); + drm_gem_object_unreference_unlocked(old_radeon_fb->obj); + radeon_fence_unref(&work->fence); + free(work, DRM_MEM_DRIVER); + + return r; +} + +static const struct drm_crtc_funcs radeon_crtc_funcs = { + .cursor_set = radeon_crtc_cursor_set, + .cursor_move = radeon_crtc_cursor_move, + .gamma_set = radeon_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, + .destroy = radeon_crtc_destroy, + .page_flip = radeon_crtc_page_flip, +}; + +static void radeon_crtc_init(struct drm_device *dev, int index) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc; + int i; + + radeon_crtc = malloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (radeon_crtc == NULL) + return; + + drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs); + + drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); + radeon_crtc->crtc_id = index; + rdev->mode_info.crtcs[index] = radeon_crtc; + +#if 0 + radeon_crtc->mode_set.crtc = &radeon_crtc->base; + radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1); + radeon_crtc->mode_set.num_connectors = 0; +#endif + + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r[i] = i << 2; + radeon_crtc->lut_g[i] = i << 2; + radeon_crtc->lut_b[i] = i << 2; + } + + if (rdev->is_atom_bios && (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)) + radeon_atombios_init_crtc(dev, radeon_crtc); + else + radeon_legacy_init_crtc(dev, radeon_crtc); +} + +static const char *encoder_names[37] = { + "NONE", + "INTERNAL_LVDS", + "INTERNAL_TMDS1", + "INTERNAL_TMDS2", + "INTERNAL_DAC1", + "INTERNAL_DAC2", + "INTERNAL_SDVOA", + "INTERNAL_SDVOB", + "SI170B", + "CH7303", + "CH7301", + "INTERNAL_DVO1", + "EXTERNAL_SDVOA", + "EXTERNAL_SDVOB", + "TITFP513", + "INTERNAL_LVTM1", + "VT1623", + "HDMI_SI1930", + "HDMI_INTERNAL", + "INTERNAL_KLDSCP_TMDS1", + "INTERNAL_KLDSCP_DVO1", + "INTERNAL_KLDSCP_DAC1", + "INTERNAL_KLDSCP_DAC2", + "SI178", + "MVPU_FPGA", + "INTERNAL_DDI", + "VT1625", + "HDMI_SI1932", + "DP_AN9801", + "DP_DP501", + "INTERNAL_UNIPHY", + "INTERNAL_KLDSCP_LVTMA", + "INTERNAL_UNIPHY1", + "INTERNAL_UNIPHY2", + "NUTMEG", + "TRAVIS", + "INTERNAL_VCE" +}; + +static const char *hpd_names[6] = { + "HPD1", + "HPD2", + "HPD3", + "HPD4", + "HPD5", + "HPD6", +}; + +static void radeon_print_display_setup(struct drm_device *dev) +{ + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + uint32_t devices; + int i = 0; + + DRM_INFO("Radeon Display Connectors\n"); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + DRM_INFO("Connector %d:\n", i); + DRM_INFO(" %s\n", drm_get_connector_name(connector)); + if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) + DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]); + if (radeon_connector->ddc_bus) { + DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + radeon_connector->ddc_bus->rec.mask_clk_reg, + radeon_connector->ddc_bus->rec.mask_data_reg, + radeon_connector->ddc_bus->rec.a_clk_reg, + radeon_connector->ddc_bus->rec.a_data_reg, + radeon_connector->ddc_bus->rec.en_clk_reg, + radeon_connector->ddc_bus->rec.en_data_reg, + radeon_connector->ddc_bus->rec.y_clk_reg, + radeon_connector->ddc_bus->rec.y_data_reg); + if (radeon_connector->router.ddc_valid) + DRM_INFO(" DDC Router 0x%x/0x%x\n", + radeon_connector->router.ddc_mux_control_pin, + radeon_connector->router.ddc_mux_state); + if (radeon_connector->router.cd_valid) + DRM_INFO(" Clock/Data Router 0x%x/0x%x\n", + radeon_connector->router.cd_mux_control_pin, + radeon_connector->router.cd_mux_state); + } else { + if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || + connector->connector_type == DRM_MODE_CONNECTOR_DVII || + connector->connector_type == DRM_MODE_CONNECTOR_DVID || + connector->connector_type == DRM_MODE_CONNECTOR_DVIA || + connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) + DRM_INFO(" DDC: no ddc bus - possible BIOS bug - please report to xorg-driver-ati@lists.x.org\n"); + } + DRM_INFO(" Encoders:\n"); + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + devices = radeon_encoder->devices & radeon_connector->devices; + if (devices) { + if (devices & ATOM_DEVICE_CRT1_SUPPORT) + DRM_INFO(" CRT1: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_CRT2_SUPPORT) + DRM_INFO(" CRT2: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_LCD1_SUPPORT) + DRM_INFO(" LCD1: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP1_SUPPORT) + DRM_INFO(" DFP1: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP2_SUPPORT) + DRM_INFO(" DFP2: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP3_SUPPORT) + DRM_INFO(" DFP3: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP4_SUPPORT) + DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP5_SUPPORT) + DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP6_SUPPORT) + DRM_INFO(" DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_TV1_SUPPORT) + DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_CV_SUPPORT) + DRM_INFO(" CV: %s\n", encoder_names[radeon_encoder->encoder_id]); + } + } + i++; + } +} + +static bool radeon_setup_enc_conn(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + bool ret = false; + + if (rdev->bios) { + if (rdev->is_atom_bios) { + ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); + if (ret == false) + ret = radeon_get_atom_connector_info_from_object_table(dev); + } else { + ret = radeon_get_legacy_connector_info_from_bios(dev); + if (ret == false) + ret = radeon_get_legacy_connector_info_from_table(dev); + } + } else { + if (!ASIC_IS_AVIVO(rdev)) + ret = radeon_get_legacy_connector_info_from_table(dev); + } + if (ret) { + radeon_setup_encoder_clones(dev); + radeon_print_display_setup(dev); + } + + return ret; +} + +int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) +{ + struct drm_device *dev = radeon_connector->base.dev; + struct radeon_device *rdev = dev->dev_private; + int ret = 0; + + /* on hw with routers, select right port */ + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + + if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != + ENCODER_OBJECT_ID_NONE) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if (dig->dp_i2c_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + dig->dp_i2c_bus->adapter); + } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || + dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + dig->dp_i2c_bus->adapter); + else if (radeon_connector->ddc_bus && !radeon_connector->edid) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + radeon_connector->ddc_bus->adapter); + } else { + if (radeon_connector->ddc_bus && !radeon_connector->edid) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + radeon_connector->ddc_bus->adapter); + } + + if (!radeon_connector->edid) { + if (rdev->is_atom_bios) { + /* some laptops provide a hardcoded edid in rom for LCDs */ + if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) || + (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP))) + radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); + } else + /* some servers provide a hardcoded edid in rom for KVMs */ + radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); + } + if (radeon_connector->edid) { + drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); + ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); + return ret; + } + drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); + return 0; +} + +/* avivo */ +static void avivo_get_fb_div(struct radeon_pll *pll, + u32 target_clock, + u32 post_div, + u32 ref_div, + u32 *fb_div, + u32 *frac_fb_div) +{ + u32 tmp = post_div * ref_div; + + tmp *= target_clock; + *fb_div = tmp / pll->reference_freq; + *frac_fb_div = tmp % pll->reference_freq; + + if (*fb_div > pll->max_feedback_div) + *fb_div = pll->max_feedback_div; + else if (*fb_div < pll->min_feedback_div) + *fb_div = pll->min_feedback_div; +} + +static u32 avivo_get_post_div(struct radeon_pll *pll, + u32 target_clock) +{ + u32 vco, post_div, tmp; + + if (pll->flags & RADEON_PLL_USE_POST_DIV) + return pll->post_div; + + if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { + if (pll->flags & RADEON_PLL_IS_LCD) + vco = pll->lcd_pll_out_min; + else + vco = pll->pll_out_min; + } else { + if (pll->flags & RADEON_PLL_IS_LCD) + vco = pll->lcd_pll_out_max; + else + vco = pll->pll_out_max; + } + + post_div = vco / target_clock; + tmp = vco % target_clock; + + if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { + if (tmp) + post_div++; + } else { + if (!tmp) + post_div--; + } + + if (post_div > pll->max_post_div) + post_div = pll->max_post_div; + else if (post_div < pll->min_post_div) + post_div = pll->min_post_div; + + return post_div; +} + +#define MAX_TOLERANCE 10 + +void radeon_compute_pll_avivo(struct radeon_pll *pll, + u32 freq, + u32 *dot_clock_p, + u32 *fb_div_p, + u32 *frac_fb_div_p, + u32 *ref_div_p, + u32 *post_div_p) +{ + u32 target_clock = freq / 10; + u32 post_div = avivo_get_post_div(pll, target_clock); + u32 ref_div = pll->min_ref_div; + u32 fb_div = 0, frac_fb_div = 0, tmp; + + if (pll->flags & RADEON_PLL_USE_REF_DIV) + ref_div = pll->reference_div; + + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { + avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div); + frac_fb_div = (100 * frac_fb_div) / pll->reference_freq; + if (frac_fb_div >= 5) { + frac_fb_div -= 5; + frac_fb_div = frac_fb_div / 10; + frac_fb_div++; + } + if (frac_fb_div >= 10) { + fb_div++; + frac_fb_div = 0; + } + } else { + while (ref_div <= pll->max_ref_div) { + avivo_get_fb_div(pll, target_clock, post_div, ref_div, + &fb_div, &frac_fb_div); + if (frac_fb_div >= (pll->reference_freq / 2)) + fb_div++; + frac_fb_div = 0; + tmp = (pll->reference_freq * fb_div) / (post_div * ref_div); + tmp = (tmp * 10000) / target_clock; + + if (tmp > (10000 + MAX_TOLERANCE)) + ref_div++; + else if (tmp >= (10000 - MAX_TOLERANCE)) + break; + else + ref_div++; + } + } + + *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) / + (ref_div * post_div * 10); + *fb_div_p = fb_div; + *frac_fb_div_p = frac_fb_div; + *ref_div_p = ref_div; + *post_div_p = post_div; + DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n", + *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div); +} + +/* pre-avivo */ +static inline uint32_t radeon_div(uint64_t n, uint32_t d) +{ + uint64_t mod; + + n += d / 2; + + mod = do_div(n, d); + return n; +} + +void radeon_compute_pll_legacy(struct radeon_pll *pll, + uint64_t freq, + uint32_t *dot_clock_p, + uint32_t *fb_div_p, + uint32_t *frac_fb_div_p, + uint32_t *ref_div_p, + uint32_t *post_div_p) +{ + uint32_t min_ref_div = pll->min_ref_div; + uint32_t max_ref_div = pll->max_ref_div; + uint32_t min_post_div = pll->min_post_div; + uint32_t max_post_div = pll->max_post_div; + uint32_t min_fractional_feed_div = 0; + uint32_t max_fractional_feed_div = 0; + uint32_t best_vco = pll->best_vco; + uint32_t best_post_div = 1; + uint32_t best_ref_div = 1; + uint32_t best_feedback_div = 1; + uint32_t best_frac_feedback_div = 0; + uint32_t best_freq = -1; + uint32_t best_error = 0xffffffff; + uint32_t best_vco_diff = 1; + uint32_t post_div; + u32 pll_out_min, pll_out_max; + + DRM_DEBUG_KMS("PLL freq %ju %u %u\n", (uintmax_t)freq, pll->min_ref_div, pll->max_ref_div); + freq = freq * 1000; + + if (pll->flags & RADEON_PLL_IS_LCD) { + pll_out_min = pll->lcd_pll_out_min; + pll_out_max = pll->lcd_pll_out_max; + } else { + pll_out_min = pll->pll_out_min; + pll_out_max = pll->pll_out_max; + } + + if (pll_out_min > 64800) + pll_out_min = 64800; + + if (pll->flags & RADEON_PLL_USE_REF_DIV) + min_ref_div = max_ref_div = pll->reference_div; + else { + while (min_ref_div < max_ref_div-1) { + uint32_t mid = (min_ref_div + max_ref_div) / 2; + uint32_t pll_in = pll->reference_freq / mid; + if (pll_in < pll->pll_in_min) + max_ref_div = mid; + else if (pll_in > pll->pll_in_max) + min_ref_div = mid; + else + break; + } + } + + if (pll->flags & RADEON_PLL_USE_POST_DIV) + min_post_div = max_post_div = pll->post_div; + + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { + min_fractional_feed_div = pll->min_frac_feedback_div; + max_fractional_feed_div = pll->max_frac_feedback_div; + } + + for (post_div = max_post_div; post_div >= min_post_div; --post_div) { + uint32_t ref_div; + + if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) + continue; + + /* legacy radeons only have a few post_divs */ + if (pll->flags & RADEON_PLL_LEGACY) { + if ((post_div == 5) || + (post_div == 7) || + (post_div == 9) || + (post_div == 10) || + (post_div == 11) || + (post_div == 13) || + (post_div == 14) || + (post_div == 15)) + continue; + } + + for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) { + uint32_t feedback_div, current_freq = 0, error, vco_diff; + uint32_t pll_in = pll->reference_freq / ref_div; + uint32_t min_feed_div = pll->min_feedback_div; + uint32_t max_feed_div = pll->max_feedback_div + 1; + + if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max) + continue; + + while (min_feed_div < max_feed_div) { + uint32_t vco; + uint32_t min_frac_feed_div = min_fractional_feed_div; + uint32_t max_frac_feed_div = max_fractional_feed_div + 1; + uint32_t frac_feedback_div; + uint64_t tmp; + + feedback_div = (min_feed_div + max_feed_div) / 2; + + tmp = (uint64_t)pll->reference_freq * feedback_div; + vco = radeon_div(tmp, ref_div); + + if (vco < pll_out_min) { + min_feed_div = feedback_div + 1; + continue; + } else if (vco > pll_out_max) { + max_feed_div = feedback_div; + continue; + } + + while (min_frac_feed_div < max_frac_feed_div) { + frac_feedback_div = (min_frac_feed_div + max_frac_feed_div) / 2; + tmp = (uint64_t)pll->reference_freq * 10000 * feedback_div; + tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; + current_freq = radeon_div(tmp, ref_div * post_div); + + if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { + if (freq < current_freq) + error = 0xffffffff; + else + error = freq - current_freq; + } else + error = abs(current_freq - freq); + vco_diff = abs(vco - best_vco); + + if ((best_vco == 0 && error < best_error) || + (best_vco != 0 && + ((best_error > 100 && error < best_error - 100) || + (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) { + best_post_div = post_div; + best_ref_div = ref_div; + best_feedback_div = feedback_div; + best_frac_feedback_div = frac_feedback_div; + best_freq = current_freq; + best_error = error; + best_vco_diff = vco_diff; + } else if (current_freq == freq) { + if (best_freq == -1) { + best_post_div = post_div; + best_ref_div = ref_div; + best_feedback_div = feedback_div; + best_frac_feedback_div = frac_feedback_div; + best_freq = current_freq; + best_error = error; + best_vco_diff = vco_diff; + } else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || + ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || + ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || + ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || + ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || + ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { + best_post_div = post_div; + best_ref_div = ref_div; + best_feedback_div = feedback_div; + best_frac_feedback_div = frac_feedback_div; + best_freq = current_freq; + best_error = error; + best_vco_diff = vco_diff; + } + } + if (current_freq < freq) + min_frac_feed_div = frac_feedback_div + 1; + else + max_frac_feed_div = frac_feedback_div; + } + if (current_freq < freq) + min_feed_div = feedback_div + 1; + else + max_feed_div = feedback_div; + } + } + } + + *dot_clock_p = best_freq / 10000; + *fb_div_p = best_feedback_div; + *frac_fb_div_p = best_frac_feedback_div; + *ref_div_p = best_ref_div; + *post_div_p = best_post_div; + DRM_DEBUG_KMS("%lld %d, pll dividers - fb: %d.%d ref: %d, post %d\n", + (long long)freq, + best_freq / 1000, best_feedback_div, best_frac_feedback_div, + best_ref_div, best_post_div); + +} + +static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) +{ + struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); + + if (radeon_fb->obj) { + drm_gem_object_unreference_unlocked(radeon_fb->obj); + } + drm_framebuffer_cleanup(fb); + free(radeon_fb, DRM_MEM_DRIVER); +} + +static int radeon_user_framebuffer_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); + + return drm_gem_handle_create(file_priv, radeon_fb->obj, handle); +} + +static const struct drm_framebuffer_funcs radeon_fb_funcs = { + .destroy = radeon_user_framebuffer_destroy, + .create_handle = radeon_user_framebuffer_create_handle, +}; + +int +radeon_framebuffer_init(struct drm_device *dev, + struct radeon_framebuffer *rfb, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) +{ + int ret; + rfb->obj = obj; + ret = drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs); + if (ret) { + rfb->obj = NULL; + return ret; + } + drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd); + return 0; +} + +static int +radeon_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_framebuffer **res) +{ + struct drm_gem_object *obj; + struct radeon_framebuffer *radeon_fb; + int ret; + + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (obj == NULL) { + dev_err(dev->device, "No GEM object associated to handle 0x%08X, " + "can't create framebuffer\n", mode_cmd->handles[0]); + return -ENOENT; + } + + radeon_fb = malloc(sizeof(*radeon_fb), DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (radeon_fb == NULL) { + drm_gem_object_unreference_unlocked(obj); + return (-ENOMEM); + } + + ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); + if (ret) { + free(radeon_fb, DRM_MEM_DRIVER); + drm_gem_object_unreference_unlocked(obj); + return ret; + } + + *res = &radeon_fb->base; + return 0; +} + +static void radeon_output_poll_changed(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + radeon_fb_output_poll_changed(rdev); +} + +static const struct drm_mode_config_funcs radeon_mode_funcs = { + .fb_create = radeon_user_framebuffer_create, + .output_poll_changed = radeon_output_poll_changed +}; + +static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] = +{ { 0, "driver" }, + { 1, "bios" }, +}; + +static struct drm_prop_enum_list radeon_tv_std_enum_list[] = +{ { TV_STD_NTSC, "ntsc" }, + { TV_STD_PAL, "pal" }, + { TV_STD_PAL_M, "pal-m" }, + { TV_STD_PAL_60, "pal-60" }, + { TV_STD_NTSC_J, "ntsc-j" }, + { TV_STD_SCART_PAL, "scart-pal" }, + { TV_STD_PAL_CN, "pal-cn" }, + { TV_STD_SECAM, "secam" }, +}; + +static struct drm_prop_enum_list radeon_underscan_enum_list[] = +{ { UNDERSCAN_OFF, "off" }, + { UNDERSCAN_ON, "on" }, + { UNDERSCAN_AUTO, "auto" }, +}; + +static int radeon_modeset_create_props(struct radeon_device *rdev) +{ + int sz; + + if (rdev->is_atom_bios) { + rdev->mode_info.coherent_mode_property = + drm_property_create_range(rdev->ddev, 0 , "coherent", 0, 1); + if (!rdev->mode_info.coherent_mode_property) + return -ENOMEM; + } + + if (!ASIC_IS_AVIVO(rdev)) { + sz = DRM_ARRAY_SIZE(radeon_tmds_pll_enum_list); + rdev->mode_info.tmds_pll_property = + drm_property_create_enum(rdev->ddev, 0, + "tmds_pll", + radeon_tmds_pll_enum_list, sz); + } + + rdev->mode_info.load_detect_property = + drm_property_create_range(rdev->ddev, 0, "load detection", 0, 1); + if (!rdev->mode_info.load_detect_property) + return -ENOMEM; + + drm_mode_create_scaling_mode_property(rdev->ddev); + + sz = DRM_ARRAY_SIZE(radeon_tv_std_enum_list); + rdev->mode_info.tv_std_property = + drm_property_create_enum(rdev->ddev, 0, + "tv standard", + radeon_tv_std_enum_list, sz); + + sz = DRM_ARRAY_SIZE(radeon_underscan_enum_list); + rdev->mode_info.underscan_property = + drm_property_create_enum(rdev->ddev, 0, + "underscan", + radeon_underscan_enum_list, sz); + + rdev->mode_info.underscan_hborder_property = + drm_property_create_range(rdev->ddev, 0, + "underscan hborder", 0, 128); + if (!rdev->mode_info.underscan_hborder_property) + return -ENOMEM; + + rdev->mode_info.underscan_vborder_property = + drm_property_create_range(rdev->ddev, 0, + "underscan vborder", 0, 128); + if (!rdev->mode_info.underscan_vborder_property) + return -ENOMEM; + + return 0; +} + +void radeon_update_display_priority(struct radeon_device *rdev) +{ + /* adjustment options for the display watermarks */ + if ((radeon_disp_priority == 0) || (radeon_disp_priority > 2)) { + /* set display priority to high for r3xx, rv515 chips + * this avoids flickering due to underflow to the + * display controllers during heavy acceleration. + * Don't force high on rs4xx igp chips as it seems to + * affect the sound card. See kernel bug 15982. + */ + if ((ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV515)) && + !(rdev->flags & RADEON_IS_IGP)) + rdev->disp_priority = 2; + else + rdev->disp_priority = 0; + } else + rdev->disp_priority = radeon_disp_priority; + +} + +/* + * Allocate hdmi structs and determine register offsets + */ +static void radeon_afmt_init(struct radeon_device *rdev) +{ + int i; + + for (i = 0; i < RADEON_MAX_AFMT_BLOCKS; i++) + rdev->mode_info.afmt[i] = NULL; + + if (ASIC_IS_DCE6(rdev)) { + /* todo */ + } else if (ASIC_IS_DCE4(rdev)) { + /* DCE4/5 has 6 audio blocks tied to DIG encoders */ + /* DCE4.1 has 2 audio blocks tied to DIG encoders */ + rdev->mode_info.afmt[0] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[0]) { + rdev->mode_info.afmt[0]->offset = EVERGREEN_CRTC0_REGISTER_OFFSET; + rdev->mode_info.afmt[0]->id = 0; + } + rdev->mode_info.afmt[1] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[1]) { + rdev->mode_info.afmt[1]->offset = EVERGREEN_CRTC1_REGISTER_OFFSET; + rdev->mode_info.afmt[1]->id = 1; + } + if (!ASIC_IS_DCE41(rdev)) { + rdev->mode_info.afmt[2] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[2]) { + rdev->mode_info.afmt[2]->offset = EVERGREEN_CRTC2_REGISTER_OFFSET; + rdev->mode_info.afmt[2]->id = 2; + } + rdev->mode_info.afmt[3] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[3]) { + rdev->mode_info.afmt[3]->offset = EVERGREEN_CRTC3_REGISTER_OFFSET; + rdev->mode_info.afmt[3]->id = 3; + } + rdev->mode_info.afmt[4] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[4]) { + rdev->mode_info.afmt[4]->offset = EVERGREEN_CRTC4_REGISTER_OFFSET; + rdev->mode_info.afmt[4]->id = 4; + } + rdev->mode_info.afmt[5] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[5]) { + rdev->mode_info.afmt[5]->offset = EVERGREEN_CRTC5_REGISTER_OFFSET; + rdev->mode_info.afmt[5]->id = 5; + } + } + } else if (ASIC_IS_DCE3(rdev)) { + /* DCE3.x has 2 audio blocks tied to DIG encoders */ + rdev->mode_info.afmt[0] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[0]) { + rdev->mode_info.afmt[0]->offset = DCE3_HDMI_OFFSET0; + rdev->mode_info.afmt[0]->id = 0; + } + rdev->mode_info.afmt[1] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[1]) { + rdev->mode_info.afmt[1]->offset = DCE3_HDMI_OFFSET1; + rdev->mode_info.afmt[1]->id = 1; + } + } else if (ASIC_IS_DCE2(rdev)) { + /* DCE2 has at least 1 routable audio block */ + rdev->mode_info.afmt[0] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[0]) { + rdev->mode_info.afmt[0]->offset = DCE2_HDMI_OFFSET0; + rdev->mode_info.afmt[0]->id = 0; + } + /* r6xx has 2 routable audio blocks */ + if (rdev->family >= CHIP_R600) { + rdev->mode_info.afmt[1] = malloc(sizeof(struct radeon_afmt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (rdev->mode_info.afmt[1]) { + rdev->mode_info.afmt[1]->offset = DCE2_HDMI_OFFSET1; + rdev->mode_info.afmt[1]->id = 1; + } + } + } +} + +static void radeon_afmt_fini(struct radeon_device *rdev) +{ + int i; + + for (i = 0; i < RADEON_MAX_AFMT_BLOCKS; i++) { + free(rdev->mode_info.afmt[i], DRM_MEM_DRIVER); + rdev->mode_info.afmt[i] = NULL; + } +} + +int radeon_modeset_init(struct radeon_device *rdev) +{ + int i; + int ret; + + drm_mode_config_init(rdev->ddev); + rdev->mode_info.mode_config_initialized = true; + + rdev->ddev->mode_config.funcs = &radeon_mode_funcs; + + if (ASIC_IS_DCE5(rdev)) { + rdev->ddev->mode_config.max_width = 16384; + rdev->ddev->mode_config.max_height = 16384; + } else if (ASIC_IS_AVIVO(rdev)) { + rdev->ddev->mode_config.max_width = 8192; + rdev->ddev->mode_config.max_height = 8192; + } else { + rdev->ddev->mode_config.max_width = 4096; + rdev->ddev->mode_config.max_height = 4096; + } + + rdev->ddev->mode_config.preferred_depth = 24; + rdev->ddev->mode_config.prefer_shadow = 1; + + rdev->ddev->mode_config.fb_base = rdev->mc.aper_base; + + ret = radeon_modeset_create_props(rdev); + if (ret) { + return ret; + } + + /* init i2c buses */ + radeon_i2c_init(rdev); + + /* check combios for a valid hardcoded EDID - Sun servers */ + if (!rdev->is_atom_bios) { + /* check for hardcoded EDID in BIOS */ + radeon_combios_check_hardcoded_edid(rdev); + } + + /* allocate crtcs */ + for (i = 0; i < rdev->num_crtc; i++) { + radeon_crtc_init(rdev->ddev, i); + } + + /* okay we should have all the bios connectors */ + ret = radeon_setup_enc_conn(rdev->ddev); + if (!ret) { + return ret; + } + + /* init dig PHYs, disp eng pll */ + if (rdev->is_atom_bios) { + radeon_atom_encoder_init(rdev); + radeon_atom_disp_eng_pll_init(rdev); + } + + /* initialize hpd */ + radeon_hpd_init(rdev); + + /* setup afmt */ + radeon_afmt_init(rdev); + + /* Initialize power management */ + radeon_pm_init(rdev); + + radeon_fbdev_init(rdev); + drm_kms_helper_poll_init(rdev->ddev); + + return 0; +} + +void radeon_modeset_fini(struct radeon_device *rdev) +{ + radeon_fbdev_fini(rdev); + free(rdev->mode_info.bios_hardcoded_edid, DRM_MEM_KMS); + radeon_pm_fini(rdev); + + if (rdev->mode_info.mode_config_initialized) { + radeon_afmt_fini(rdev); + drm_kms_helper_poll_fini(rdev->ddev); + radeon_hpd_fini(rdev); + DRM_UNLOCK(rdev->ddev); /* Work around lock recursion. dumbbell@ */ + drm_mode_config_cleanup(rdev->ddev); + DRM_LOCK(rdev->ddev); + rdev->mode_info.mode_config_initialized = false; + } + /* free i2c buses */ + radeon_i2c_fini(rdev); +} + +static bool is_hdtv_mode(const struct drm_display_mode *mode) +{ + /* try and guess if this is a tv or a monitor */ + if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ + (mode->vdisplay == 576) || /* 576p */ + (mode->vdisplay == 720) || /* 720p */ + (mode->vdisplay == 1080)) /* 1080p */ + return true; + else + return false; +} + +bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_encoder *radeon_encoder; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + bool first = true; + u32 src_v = 1, dst_v = 1; + u32 src_h = 1, dst_h = 1; + + radeon_crtc->h_border = 0; + radeon_crtc->v_border = 0; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc != crtc) + continue; + radeon_encoder = to_radeon_encoder(encoder); + connector = radeon_get_connector_for_encoder(encoder); + radeon_connector = to_radeon_connector(connector); + + if (first) { + /* set scaling */ + if (radeon_encoder->rmx_type == RMX_OFF) + radeon_crtc->rmx_type = RMX_OFF; + else if (mode->hdisplay < radeon_encoder->native_mode.hdisplay || + mode->vdisplay < radeon_encoder->native_mode.vdisplay) + radeon_crtc->rmx_type = radeon_encoder->rmx_type; + else + radeon_crtc->rmx_type = RMX_OFF; + /* copy native mode */ + memcpy(&radeon_crtc->native_mode, + &radeon_encoder->native_mode, + sizeof(struct drm_display_mode)); + src_v = crtc->mode.vdisplay; + dst_v = radeon_crtc->native_mode.vdisplay; + src_h = crtc->mode.hdisplay; + dst_h = radeon_crtc->native_mode.hdisplay; + + /* fix up for overscan on hdmi */ + if (ASIC_IS_AVIVO(rdev) && + (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && + ((radeon_encoder->underscan_type == UNDERSCAN_ON) || + ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && + drm_detect_hdmi_monitor(radeon_connector->edid) && + is_hdtv_mode(mode)))) { + if (radeon_encoder->underscan_hborder != 0) + radeon_crtc->h_border = radeon_encoder->underscan_hborder; + else + radeon_crtc->h_border = (mode->hdisplay >> 5) + 16; + if (radeon_encoder->underscan_vborder != 0) + radeon_crtc->v_border = radeon_encoder->underscan_vborder; + else + radeon_crtc->v_border = (mode->vdisplay >> 5) + 16; + radeon_crtc->rmx_type = RMX_FULL; + src_v = crtc->mode.vdisplay; + dst_v = crtc->mode.vdisplay - (radeon_crtc->v_border * 2); + src_h = crtc->mode.hdisplay; + dst_h = crtc->mode.hdisplay - (radeon_crtc->h_border * 2); + } + first = false; + } else { + if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) { + /* WARNING: Right now this can't happen but + * in the future we need to check that scaling + * are consistent across different encoder + * (ie all encoder can work with the same + * scaling). + */ + DRM_ERROR("Scaling not consistent across encoder.\n"); + return false; + } + } + } + if (radeon_crtc->rmx_type != RMX_OFF) { + fixed20_12 a, b; + a.full = dfixed_const(src_v); + b.full = dfixed_const(dst_v); + radeon_crtc->vsc.full = dfixed_div(a, b); + a.full = dfixed_const(src_h); + b.full = dfixed_const(dst_h); + radeon_crtc->hsc.full = dfixed_div(a, b); + } else { + radeon_crtc->vsc.full = dfixed_const(1); + radeon_crtc->hsc.full = dfixed_const(1); + } + return true; +} + +/* + * Retrieve current video scanout position of crtc on a given gpu. + * + * \param dev Device to query. + * \param crtc Crtc to query. + * \param *vpos Location where vertical scanout position should be stored. + * \param *hpos Location where horizontal scanout position should go. + * + * Returns vpos as a positive number while in active scanout area. + * Returns vpos as a negative number inside vblank, counting the number + * of scanlines to go until end of vblank, e.g., -1 means "one scanline + * until start of active scanout / end of vblank." + * + * \return Flags, or'ed together as follows: + * + * DRM_SCANOUTPOS_VALID = Query successful. + * DRM_SCANOUTPOS_INVBL = Inside vblank. + * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of + * this flag means that returned position may be offset by a constant but + * unknown small number of scanlines wrt. real scanout position. + * + */ +int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos) +{ + u32 stat_crtc = 0, vbl = 0, position = 0; + int vbl_start, vbl_end, vtotal, ret = 0; + bool in_vbl = true; + + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_DCE4(rdev)) { + if (crtc == 0) { + vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + + EVERGREEN_CRTC0_REGISTER_OFFSET); + position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + + EVERGREEN_CRTC0_REGISTER_OFFSET); + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 1) { + vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + + EVERGREEN_CRTC1_REGISTER_OFFSET); + position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + + EVERGREEN_CRTC1_REGISTER_OFFSET); + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 2) { + vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + + EVERGREEN_CRTC2_REGISTER_OFFSET); + position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + + EVERGREEN_CRTC2_REGISTER_OFFSET); + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 3) { + vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + + EVERGREEN_CRTC3_REGISTER_OFFSET); + position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + + EVERGREEN_CRTC3_REGISTER_OFFSET); + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 4) { + vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + + EVERGREEN_CRTC4_REGISTER_OFFSET); + position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + + EVERGREEN_CRTC4_REGISTER_OFFSET); + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 5) { + vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + + EVERGREEN_CRTC5_REGISTER_OFFSET); + position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + + EVERGREEN_CRTC5_REGISTER_OFFSET); + ret |= DRM_SCANOUTPOS_VALID; + } + } else if (ASIC_IS_AVIVO(rdev)) { + if (crtc == 0) { + vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); + position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 1) { + vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); + position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); + ret |= DRM_SCANOUTPOS_VALID; + } + } else { + /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ + if (crtc == 0) { + /* Assume vbl_end == 0, get vbl_start from + * upper 16 bits. + */ + vbl = (RREG32(RADEON_CRTC_V_TOTAL_DISP) & + RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT; + /* Only retrieve vpos from upper 16 bits, set hpos == 0. */ + position = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; + stat_crtc = RREG32(RADEON_CRTC_STATUS); + if (!(stat_crtc & 1)) + in_vbl = false; + + ret |= DRM_SCANOUTPOS_VALID; + } + if (crtc == 1) { + vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & + RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT; + position = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; + stat_crtc = RREG32(RADEON_CRTC2_STATUS); + if (!(stat_crtc & 1)) + in_vbl = false; + + ret |= DRM_SCANOUTPOS_VALID; + } + } + + /* Decode into vertical and horizontal scanout position. */ + *vpos = position & 0x1fff; + *hpos = (position >> 16) & 0x1fff; + + /* Valid vblank area boundaries from gpu retrieved? */ + if (vbl > 0) { + /* Yes: Decode. */ + ret |= DRM_SCANOUTPOS_ACCURATE; + vbl_start = vbl & 0x1fff; + vbl_end = (vbl >> 16) & 0x1fff; + } + else { + /* No: Fake something reasonable which gives at least ok results. */ + vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; + vbl_end = 0; + } + + /* Test scanout position against vblank region. */ + if ((*vpos < vbl_start) && (*vpos >= vbl_end)) + in_vbl = false; + + /* Check if inside vblank area and apply corrective offsets: + * vpos will then be >=0 in video scanout area, but negative + * within vblank area, counting down the number of lines until + * start of scanout. + */ + + /* Inside "upper part" of vblank area? Apply corrective offset if so: */ + if (in_vbl && (*vpos >= vbl_start)) { + vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + *vpos = *vpos - vtotal; + } + + /* Correct for shifted end of vbl at vbl_end. */ + *vpos = *vpos - vbl_end; + + /* In vblank? */ + if (in_vbl) + ret |= DRM_SCANOUTPOS_INVBL; + + return ret; +} diff --git a/sys/dev/drm2/radeon/radeon_drm.h b/sys/dev/drm2/radeon/radeon_drm.h new file mode 100644 index 00000000000..e84500c118f --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_drm.h @@ -0,0 +1,985 @@ +/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_DRM_H__ +#define __RADEON_DRM_H__ + +#include + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (radeon_sarea.h) + */ +#ifndef __RADEON_SAREA_DEFINES__ +#define __RADEON_SAREA_DEFINES__ + +/* Old style state flags, required for sarea interface (1.1 and 1.2 + * clears) and 1.2 drm_vertex2 ioctl. + */ +#define RADEON_UPLOAD_CONTEXT 0x00000001 +#define RADEON_UPLOAD_VERTFMT 0x00000002 +#define RADEON_UPLOAD_LINE 0x00000004 +#define RADEON_UPLOAD_BUMPMAP 0x00000008 +#define RADEON_UPLOAD_MASKS 0x00000010 +#define RADEON_UPLOAD_VIEWPORT 0x00000020 +#define RADEON_UPLOAD_SETUP 0x00000040 +#define RADEON_UPLOAD_TCL 0x00000080 +#define RADEON_UPLOAD_MISC 0x00000100 +#define RADEON_UPLOAD_TEX0 0x00000200 +#define RADEON_UPLOAD_TEX1 0x00000400 +#define RADEON_UPLOAD_TEX2 0x00000800 +#define RADEON_UPLOAD_TEX0IMAGES 0x00001000 +#define RADEON_UPLOAD_TEX1IMAGES 0x00002000 +#define RADEON_UPLOAD_TEX2IMAGES 0x00004000 +#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */ +#define RADEON_REQUIRE_QUIESCENCE 0x00010000 +#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ +#define RADEON_UPLOAD_ALL 0x003effff +#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff + +/* New style per-packet identifiers for use in cmd_buffer ioctl with + * the RADEON_EMIT_PACKET command. Comments relate new packets to old + * state bits and the packet size: + */ +#define RADEON_EMIT_PP_MISC 0 /* context/7 */ +#define RADEON_EMIT_PP_CNTL 1 /* context/3 */ +#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ +#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ +#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ +#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ +#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ +#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ +#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ +#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ +#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ +#define RADEON_EMIT_RE_MISC 11 /* misc/1 */ +#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ +#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ +#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ +#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ +#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ +#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ +#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ +#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ +#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ +#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ +#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ +#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ +#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ +#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ +#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ +#define R200_EMIT_TFACTOR_0 30 /* tf/7 */ +#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ +#define R200_EMIT_VAP_CTL 32 /* vap/1 */ +#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ +#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ +#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ +#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ +#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ +#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ +#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ +#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ +#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ +#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ +#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ +#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ +#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ +#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ +#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ +#define R200_EMIT_VTE_CNTL 48 /* vte/1 */ +#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ +#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ +#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ +#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ +#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ +#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ +#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ +#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ +#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ +#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_EMIT_PP_TEX_SIZE_0 73 +#define RADEON_EMIT_PP_TEX_SIZE_1 74 +#define RADEON_EMIT_PP_TEX_SIZE_2 75 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77 +#define RADEON_EMIT_PP_CUBIC_FACES_0 78 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79 +#define RADEON_EMIT_PP_CUBIC_FACES_1 80 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81 +#define RADEON_EMIT_PP_CUBIC_FACES_2 82 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83 +#define R200_EMIT_PP_TRI_PERF_CNTL 84 +#define R200_EMIT_PP_AFS_0 85 +#define R200_EMIT_PP_AFS_1 86 +#define R200_EMIT_ATF_TFACTOR 87 +#define R200_EMIT_PP_TXCTLALL_0 88 +#define R200_EMIT_PP_TXCTLALL_1 89 +#define R200_EMIT_PP_TXCTLALL_2 90 +#define R200_EMIT_PP_TXCTLALL_3 91 +#define R200_EMIT_PP_TXCTLALL_4 92 +#define R200_EMIT_PP_TXCTLALL_5 93 +#define R200_EMIT_VAP_PVS_CNTL 94 +#define RADEON_MAX_STATE_PACKETS 95 + +/* Commands understood by cmd_buffer ioctl. More can be added but + * obviously these can't be removed or changed: + */ +#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ +#define RADEON_CMD_SCALARS 2 /* emit scalar data */ +#define RADEON_CMD_VECTORS 3 /* emit vector data */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ +#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ +#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: + * doesn't make the cpu wait, just + * the graphics hardware */ +#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */ + +typedef union { + int i; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, packet_id, pad0, pad1; + } packet; + struct { + unsigned char cmd_type, offset, stride, count; + } scalars; + struct { + unsigned char cmd_type, offset, stride, count; + } vectors; + struct { + unsigned char cmd_type, addr_lo, addr_hi, count; + } veclinear; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; +} drm_radeon_cmd_header_t; + +#define RADEON_WAIT_2D 0x1 +#define RADEON_WAIT_3D 0x2 + +/* Allowed parameters for R300_CMD_PACKET3 + */ +#define R300_CMD_PACKET3_CLEAR 0 +#define R300_CMD_PACKET3_RAW 1 + +/* Commands understood by cmd_buffer ioctl for R300. + * The interface has not been stabilized, so some of these may be removed + * and eventually reordered before stabilization. + */ +#define R300_CMD_PACKET0 1 +#define R300_CMD_VPU 2 /* emit vertex program upload */ +#define R300_CMD_PACKET3 3 /* emit a packet3 */ +#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */ +#define R300_CMD_CP_DELAY 5 +#define R300_CMD_DMA_DISCARD 6 +#define R300_CMD_WAIT 7 +# define R300_WAIT_2D 0x1 +# define R300_WAIT_3D 0x2 +/* these two defines are DOING IT WRONG - however + * we have userspace which relies on using these. + * The wait interface is backwards compat new + * code should use the NEW_WAIT defines below + * THESE ARE NOT BIT FIELDS + */ +# define R300_WAIT_2D_CLEAN 0x3 +# define R300_WAIT_3D_CLEAN 0x4 + +# define R300_NEW_WAIT_2D_3D 0x3 +# define R300_NEW_WAIT_2D_2D_CLEAN 0x4 +# define R300_NEW_WAIT_3D_3D_CLEAN 0x6 +# define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN 0x8 + +#define R300_CMD_SCRATCH 8 +#define R300_CMD_R500FP 9 + +typedef union { + unsigned int u; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, count, reglo, reghi; + } packet0; + struct { + unsigned char cmd_type, count, adrlo, adrhi; + } vpu; + struct { + unsigned char cmd_type, packet, pad0, pad1; + } packet3; + struct { + unsigned char cmd_type, packet; + unsigned short count; /* amount of packet2 to emit */ + } delay; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; + struct { + unsigned char cmd_type, count, adrlo, adrhi_flags; + } r500fp; +} drm_r300_cmd_header_t; + +#define RADEON_FRONT 0x1 +#define RADEON_BACK 0x2 +#define RADEON_DEPTH 0x4 +#define RADEON_STENCIL 0x8 +#define RADEON_CLEAR_FASTZ 0x80000000 +#define RADEON_USE_HIERZ 0x40000000 +#define RADEON_USE_COMP_ZBUF 0x20000000 + +#define R500FP_CONSTANT_TYPE (1 << 1) +#define R500FP_CONSTANT_CLAMP (1 << 2) + +/* Primitive types + */ +#define RADEON_POINTS 0x1 +#define RADEON_LINES 0x2 +#define RADEON_LINE_STRIP 0x3 +#define RADEON_TRIANGLES 0x4 +#define RADEON_TRIANGLE_FAN 0x5 +#define RADEON_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define RADEON_BUFFER_SIZE 65536 + +/* Byte offsets for indirect buffer data + */ +#define RADEON_INDEX_PRIM_OFFSET 20 + +#define RADEON_SCRATCH_REG_OFFSET 32 + +#define R600_SCRATCH_REG_OFFSET 256 + +#define RADEON_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/GART). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define RADEON_LOCAL_TEX_HEAP 0 +#define RADEON_GART_TEX_HEAP 1 +#define RADEON_NR_TEX_HEAPS 2 +#define RADEON_NR_TEX_REGIONS 64 +#define RADEON_LOG_TEX_GRANULARITY 16 + +#define RADEON_MAX_TEXTURE_LEVELS 12 +#define RADEON_MAX_TEXTURE_UNITS 3 + +#define RADEON_MAX_SURFACES 8 + +/* Blits have strict offset rules. All blit offset must be aligned on + * a 1K-byte boundary. + */ +#define RADEON_OFFSET_SHIFT 10 +#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT) +#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1) + +#endif /* __RADEON_SAREA_DEFINES__ */ + +typedef struct { + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int alpha; +} radeon_color_regs_t; + +typedef struct { + /* Context state */ + unsigned int pp_misc; /* 0x1c14 */ + unsigned int pp_fog_color; + unsigned int re_solid_color; + unsigned int rb3d_blendcntl; + unsigned int rb3d_depthoffset; + unsigned int rb3d_depthpitch; + unsigned int rb3d_zstencilcntl; + + unsigned int pp_cntl; /* 0x1c38 */ + unsigned int rb3d_cntl; + unsigned int rb3d_coloroffset; + unsigned int re_width_height; + unsigned int rb3d_colorpitch; + unsigned int se_cntl; + + /* Vertex format state */ + unsigned int se_coord_fmt; /* 0x1c50 */ + + /* Line state */ + unsigned int re_line_pattern; /* 0x1cd0 */ + unsigned int re_line_state; + + unsigned int se_line_width; /* 0x1db8 */ + + /* Bumpmap state */ + unsigned int pp_lum_matrix; /* 0x1d00 */ + + unsigned int pp_rot_matrix_0; /* 0x1d58 */ + unsigned int pp_rot_matrix_1; + + /* Mask state */ + unsigned int rb3d_stencilrefmask; /* 0x1d7c */ + unsigned int rb3d_ropcntl; + unsigned int rb3d_planemask; + + /* Viewport state */ + unsigned int se_vport_xscale; /* 0x1d98 */ + unsigned int se_vport_xoffset; + unsigned int se_vport_yscale; + unsigned int se_vport_yoffset; + unsigned int se_vport_zscale; + unsigned int se_vport_zoffset; + + /* Setup state */ + unsigned int se_cntl_status; /* 0x2140 */ + + /* Misc state */ + unsigned int re_top_left; /* 0x26c0 */ + unsigned int re_misc; +} drm_radeon_context_regs_t; + +typedef struct { + /* Zbias state */ + unsigned int se_zbias_factor; /* 0x1dac */ + unsigned int se_zbias_constant; +} drm_radeon_context2_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int pp_txfilter; + unsigned int pp_txformat; + unsigned int pp_txoffset; + unsigned int pp_txcblend; + unsigned int pp_txablend; + unsigned int pp_tfactor; + unsigned int pp_border_color; +} drm_radeon_texture_regs_t; + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim:8; + unsigned int stateidx:8; + unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ + unsigned int vc_format; /* vertex format */ +} drm_radeon_prim_t; + +typedef struct { + drm_radeon_context_regs_t context; + drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; + drm_radeon_context2_regs_t context2; + unsigned int dirty; +} drm_radeon_state_t; + +typedef struct { + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. + */ + drm_radeon_context_regs_t context_state; + drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + unsigned int last_clear; + + struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[RADEON_NR_TEX_HEAPS]; + int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ + int tiling_enabled; /* set by drm, read by 2d + 3d clients */ +} drm_radeon_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmRadeon.h) + * + * KW: actually it's illegal to change any of this (backwards compatibility). + */ + +/* Radeon specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_RADEON_CP_INIT 0x00 +#define DRM_RADEON_CP_START 0x01 +#define DRM_RADEON_CP_STOP 0x02 +#define DRM_RADEON_CP_RESET 0x03 +#define DRM_RADEON_CP_IDLE 0x04 +#define DRM_RADEON_RESET 0x05 +#define DRM_RADEON_FULLSCREEN 0x06 +#define DRM_RADEON_SWAP 0x07 +#define DRM_RADEON_CLEAR 0x08 +#define DRM_RADEON_VERTEX 0x09 +#define DRM_RADEON_INDICES 0x0A +#define DRM_RADEON_NOT_USED +#define DRM_RADEON_STIPPLE 0x0C +#define DRM_RADEON_INDIRECT 0x0D +#define DRM_RADEON_TEXTURE 0x0E +#define DRM_RADEON_VERTEX2 0x0F +#define DRM_RADEON_CMDBUF 0x10 +#define DRM_RADEON_GETPARAM 0x11 +#define DRM_RADEON_FLIP 0x12 +#define DRM_RADEON_ALLOC 0x13 +#define DRM_RADEON_FREE 0x14 +#define DRM_RADEON_INIT_HEAP 0x15 +#define DRM_RADEON_IRQ_EMIT 0x16 +#define DRM_RADEON_IRQ_WAIT 0x17 +#define DRM_RADEON_CP_RESUME 0x18 +#define DRM_RADEON_SETPARAM 0x19 +#define DRM_RADEON_SURF_ALLOC 0x1a +#define DRM_RADEON_SURF_FREE 0x1b +/* KMS ioctl */ +#define DRM_RADEON_GEM_INFO 0x1c +#define DRM_RADEON_GEM_CREATE 0x1d +#define DRM_RADEON_GEM_MMAP 0x1e +#define DRM_RADEON_GEM_PREAD 0x21 +#define DRM_RADEON_GEM_PWRITE 0x22 +#define DRM_RADEON_GEM_SET_DOMAIN 0x23 +#define DRM_RADEON_GEM_WAIT_IDLE 0x24 +#define DRM_RADEON_CS 0x26 +#define DRM_RADEON_INFO 0x27 +#define DRM_RADEON_GEM_SET_TILING 0x28 +#define DRM_RADEON_GEM_GET_TILING 0x29 +#define DRM_RADEON_GEM_BUSY 0x2a +#define DRM_RADEON_GEM_VA 0x2b + +#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) +#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) +#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) +#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET) +#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE) +#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t) +#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP) +#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t) +#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t) +#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME) +#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) +#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) +#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) +/* KMS */ +#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info) +#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create) +#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap) +#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) +#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) +#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) +#define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) +#define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) +#define DRM_IOCTL_RADEON_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling) +#define DRM_IOCTL_RADEON_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling) +#define DRM_IOCTL_RADEON_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy) +#define DRM_IOCTL_RADEON_GEM_VA DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_VA, struct drm_radeon_gem_va) + +typedef struct drm_radeon_init { + enum { + RADEON_INIT_CP = 0x01, + RADEON_CLEANUP_CP = 0x02, + RADEON_INIT_R200_CP = 0x03, + RADEON_INIT_R300_CP = 0x04, + RADEON_INIT_R600_CP = 0x05 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cp_mode; + int gart_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long gart_textures_offset; +} drm_radeon_init_t; + +typedef struct drm_radeon_cp_stop { + int flush; + int idle; +} drm_radeon_cp_stop_t; + +typedef struct drm_radeon_fullscreen { + enum { + RADEON_INIT_FULLSCREEN = 0x01, + RADEON_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_radeon_fullscreen_t; + +#define CLEAR_X1 0 +#define CLEAR_Y1 1 +#define CLEAR_X2 2 +#define CLEAR_Y2 3 +#define CLEAR_DEPTH 4 + +typedef union drm_radeon_clear_rect { + float f[5]; + unsigned int ui[5]; +} drm_radeon_clear_rect_t; + +typedef struct drm_radeon_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ + drm_radeon_clear_rect_t __user *depth_boxes; +} drm_radeon_clear_t; + +typedef struct drm_radeon_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_radeon_vertex_t; + +typedef struct drm_radeon_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_radeon_indices_t; + +/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices + * - allows multiple primitives and state changes in a single ioctl + * - supports driver change to emit native primitives + */ +typedef struct drm_radeon_vertex2 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t __user *state; + int nr_prims; + drm_radeon_prim_t __user *prim; +} drm_radeon_vertex2_t; + +/* v1.3 - obsoletes drm_radeon_vertex2 + * - allows arbitrarily large cliprect list + * - allows updating of tcl packet, vector and scalar state + * - allows memory-efficient description of state updates + * - allows state to be emitted without a primitive + * (for clears, ctx switches) + * - allows more than one dma buffer to be referenced per ioctl + * - supports tcl driver + * - may be extended in future versions with new cmd types, packets + */ +typedef struct drm_radeon_cmd_buffer { + int bufsz; + char __user *buf; + int nbox; + struct drm_clip_rect __user *boxes; +} drm_radeon_cmd_buffer_t; + +typedef struct drm_radeon_tex_image { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + const void __user *data; +} drm_radeon_tex_image_t; + +typedef struct drm_radeon_texture { + unsigned int offset; + int pitch; + int format; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t __user *image; +} drm_radeon_texture_t; + +typedef struct drm_radeon_stipple { + unsigned int __user *mask; +} drm_radeon_stipple_t; + +typedef struct drm_radeon_indirect { + int idx; + int start; + int end; + int discard; +} drm_radeon_indirect_t; + +/* enum for card type parameters */ +#define RADEON_CARD_PCI 0 +#define RADEON_CARD_AGP 1 +#define RADEON_CARD_PCIE 2 + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +/* Added with DRM version 1.6. */ +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ +/* Added with DRM version 1.8. */ +#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ +#define RADEON_PARAM_STATUS_HANDLE 8 +#define RADEON_PARAM_SAREA_HANDLE 9 +#define RADEON_PARAM_GART_TEX_HANDLE 10 +#define RADEON_PARAM_SCRATCH_OFFSET 11 +#define RADEON_PARAM_CARD_TYPE 12 +#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ +#define RADEON_PARAM_FB_LOCATION 14 /* FB location */ +#define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ +#define RADEON_PARAM_DEVICE_ID 16 +#define RADEON_PARAM_NUM_Z_PIPES 17 /* num Z pipes */ + +typedef struct drm_radeon_getparam { + int param; + void __user *value; +} drm_radeon_getparam_t; + +/* 1.6: Set up a memory manager for regions of shared memory: + */ +#define RADEON_MEM_REGION_GART 1 +#define RADEON_MEM_REGION_FB 2 + +typedef struct drm_radeon_mem_alloc { + int region; + int alignment; + int size; + int __user *region_offset; /* offset from start of fb or GART */ +} drm_radeon_mem_alloc_t; + +typedef struct drm_radeon_mem_free { + int region; + int region_offset; +} drm_radeon_mem_free_t; + +typedef struct drm_radeon_mem_init_heap { + int region; + int size; + int start; +} drm_radeon_mem_init_heap_t; + +/* 1.6: Userspace can request & wait on irq's: + */ +typedef struct drm_radeon_irq_emit { + int __user *irq_seq; +} drm_radeon_irq_emit_t; + +typedef struct drm_radeon_irq_wait { + int irq_seq; +} drm_radeon_irq_wait_t; + +/* 1.10: Clients tell the DRM where they think the framebuffer is located in + * the card's address space, via a new generic ioctl to set parameters + */ + +typedef struct drm_radeon_setparam { + unsigned int param; + int64_t value; +} drm_radeon_setparam_t; + +#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ +#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ +#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ +#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ +/* 1.14: Clients can allocate/free a surface + */ +typedef struct drm_radeon_surface_alloc { + unsigned int address; + unsigned int size; + unsigned int flags; +} drm_radeon_surface_alloc_t; + +typedef struct drm_radeon_surface_free { + unsigned int address; +} drm_radeon_surface_free_t; + +#define DRM_RADEON_VBLANK_CRTC1 1 +#define DRM_RADEON_VBLANK_CRTC2 2 + +/* + * Kernel modesetting world below. + */ +#define RADEON_GEM_DOMAIN_CPU 0x1 +#define RADEON_GEM_DOMAIN_GTT 0x2 +#define RADEON_GEM_DOMAIN_VRAM 0x4 + +struct drm_radeon_gem_info { + uint64_t gart_size; + uint64_t vram_size; + uint64_t vram_visible; +}; + +#define RADEON_GEM_NO_BACKING_STORE 1 + +struct drm_radeon_gem_create { + uint64_t size; + uint64_t alignment; + uint32_t handle; + uint32_t initial_domain; + uint32_t flags; +}; + +#define RADEON_TILING_MACRO 0x1 +#define RADEON_TILING_MICRO 0x2 +#define RADEON_TILING_SWAP_16BIT 0x4 +#define RADEON_TILING_SWAP_32BIT 0x8 +/* this object requires a surface when mapped - i.e. front buffer */ +#define RADEON_TILING_SURFACE 0x10 +#define RADEON_TILING_MICRO_SQUARE 0x20 +#define RADEON_TILING_EG_BANKW_SHIFT 8 +#define RADEON_TILING_EG_BANKW_MASK 0xf +#define RADEON_TILING_EG_BANKH_SHIFT 12 +#define RADEON_TILING_EG_BANKH_MASK 0xf +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT 16 +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK 0xf +#define RADEON_TILING_EG_TILE_SPLIT_SHIFT 24 +#define RADEON_TILING_EG_TILE_SPLIT_MASK 0xf +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT 28 +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf + +struct drm_radeon_gem_set_tiling { + uint32_t handle; + uint32_t tiling_flags; + uint32_t pitch; +}; + +struct drm_radeon_gem_get_tiling { + uint32_t handle; + uint32_t tiling_flags; + uint32_t pitch; +}; + +struct drm_radeon_gem_mmap { + uint32_t handle; + uint32_t pad; + uint64_t offset; + uint64_t size; + uint64_t addr_ptr; +}; + +struct drm_radeon_gem_set_domain { + uint32_t handle; + uint32_t read_domains; + uint32_t write_domain; +}; + +struct drm_radeon_gem_wait_idle { + uint32_t handle; + uint32_t pad; +}; + +struct drm_radeon_gem_busy { + uint32_t handle; + uint32_t domain; +}; + +struct drm_radeon_gem_pread { + /** Handle for the object being read. */ + uint32_t handle; + uint32_t pad; + /** Offset into the object to read from */ + uint64_t offset; + /** Length of data to read */ + uint64_t size; + /** Pointer to write the data into. */ + /* void *, but pointers are not 32/64 compatible */ + uint64_t data_ptr; +}; + +struct drm_radeon_gem_pwrite { + /** Handle for the object being written to. */ + uint32_t handle; + uint32_t pad; + /** Offset into the object to write to */ + uint64_t offset; + /** Length of data to write */ + uint64_t size; + /** Pointer to read the data from. */ + /* void *, but pointers are not 32/64 compatible */ + uint64_t data_ptr; +}; + +#define RADEON_VA_MAP 1 +#define RADEON_VA_UNMAP 2 + +#define RADEON_VA_RESULT_OK 0 +#define RADEON_VA_RESULT_ERROR 1 +#define RADEON_VA_RESULT_VA_EXIST 2 + +#define RADEON_VM_PAGE_VALID (1 << 0) +#define RADEON_VM_PAGE_READABLE (1 << 1) +#define RADEON_VM_PAGE_WRITEABLE (1 << 2) +#define RADEON_VM_PAGE_SYSTEM (1 << 3) +#define RADEON_VM_PAGE_SNOOPED (1 << 4) + +struct drm_radeon_gem_va { + uint32_t handle; + uint32_t operation; + uint32_t vm_id; + uint32_t flags; + uint64_t offset; +}; + +#define RADEON_CHUNK_ID_RELOCS 0x01 +#define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_FLAGS 0x03 +#define RADEON_CHUNK_ID_CONST_IB 0x04 + +/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ +#define RADEON_CS_KEEP_TILING_FLAGS 0x01 +#define RADEON_CS_USE_VM 0x02 +#define RADEON_CS_END_OF_FRAME 0x04 /* a hint from userspace which CS is the last one */ +/* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */ +#define RADEON_CS_RING_GFX 0 +#define RADEON_CS_RING_COMPUTE 1 +#define RADEON_CS_RING_DMA 2 +/* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ +/* 0 = normal, + = higher priority, - = lower priority */ + +struct drm_radeon_cs_chunk { + uint32_t chunk_id; + uint32_t length_dw; + uint64_t chunk_data; +}; + +/* drm_radeon_cs_reloc.flags */ + +struct drm_radeon_cs_reloc { + uint32_t handle; + uint32_t read_domains; + uint32_t write_domain; + uint32_t flags; +}; + +struct drm_radeon_cs { + uint32_t num_chunks; + uint32_t cs_id; + /* this points to uint64_t * which point to cs chunks */ + uint64_t chunks; + /* updates to the limits after this CS ioctl */ + uint64_t gart_limit; + uint64_t vram_limit; +}; + +#define RADEON_INFO_DEVICE_ID 0x00 +#define RADEON_INFO_NUM_GB_PIPES 0x01 +#define RADEON_INFO_NUM_Z_PIPES 0x02 +#define RADEON_INFO_ACCEL_WORKING 0x03 +#define RADEON_INFO_CRTC_FROM_ID 0x04 +#define RADEON_INFO_ACCEL_WORKING2 0x05 +#define RADEON_INFO_TILING_CONFIG 0x06 +#define RADEON_INFO_WANT_HYPERZ 0x07 +#define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ +#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ +#define RADEON_INFO_NUM_BACKENDS 0x0a /* DB/backends for r600+ - need for OQ */ +#define RADEON_INFO_NUM_TILE_PIPES 0x0b /* tile pipes for r600+ */ +#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ +#define RADEON_INFO_BACKEND_MAP 0x0d /* pipe to backend map, needed by mesa */ +/* virtual address start, va < start are reserved by the kernel */ +#define RADEON_INFO_VA_START 0x0e +/* maximum size of ib using the virtual memory cs */ +#define RADEON_INFO_IB_VM_MAX_SIZE 0x0f +/* max pipes - needed for compute shaders */ +#define RADEON_INFO_MAX_PIPES 0x10 +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ +#define RADEON_INFO_TIMESTAMP 0x11 +/* max shader engines (SE) - needed for geometry shaders, etc. */ +#define RADEON_INFO_MAX_SE 0x12 +/* max SH per SE */ +#define RADEON_INFO_MAX_SH_PER_SE 0x13 + +struct drm_radeon_info { + uint32_t request; + uint32_t pad; + uint64_t value; +}; + +#endif diff --git a/sys/dev/drm2/radeon/radeon_drv.c b/sys/dev/drm2/radeon/radeon_drv.c new file mode 100644 index 00000000000..2ef5426f9cc --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_drv.c @@ -0,0 +1,514 @@ +/** + * \file radeon_drv.c + * ATI Radeon driver + * + * \author Gareth Hughes + */ + +/* + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_drv.h" +#include "radeon_gem.h" +#include "radeon_kms.h" +#include "radeon_irq_kms.h" + +#include + + +/* + * KMS wrapper. + * - 2.0.0 - initial interface + * - 2.1.0 - add square tiling interface + * - 2.2.0 - add r6xx/r7xx const buffer support + * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs + * - 2.4.0 - add crtc id query + * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen + * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) + * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs + * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query + * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query + * 2.10.0 - fusion 2D tiling + * 2.11.0 - backend map, initial compute support for the CS checker + * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS + * 2.13.0 - virtual memory support, streamout + * 2.14.0 - add evergreen tiling informations + * 2.15.0 - add max_pipes query + * 2.16.0 - fix evergreen 2D tiled surface calculation + * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx + * 2.18.0 - r600-eg: allow "invalid" DB formats + * 2.19.0 - r600-eg: MSAA textures + * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query + * 2.21.0 - r600-r700: FMASK and CMASK + * 2.22.0 - r600 only: RESOLVE_BOX allowed + * 2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880 + * 2.24.0 - eg only: allow MIP_ADDRESS=0 for MSAA textures + * 2.25.0 - eg+: new info request for num SE and num SH + * 2.26.0 - r600-eg: fix htile size computation + * 2.27.0 - r600-SI: Add CS ioctl support for async DMA + * 2.28.0 - r600-eg: Add MEM_WRITE packet support + * 2.29.0 - R500 FP16 color clear registers + */ +#define KMS_DRIVER_MAJOR 2 +#define KMS_DRIVER_MINOR 29 +#define KMS_DRIVER_PATCHLEVEL 0 +int radeon_suspend_kms(struct drm_device *dev); +int radeon_resume_kms(struct drm_device *dev); +extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + int *vpos, int *hpos); +extern struct drm_ioctl_desc radeon_ioctls_kms[]; +extern int radeon_max_kms_ioctl; +#ifdef DUMBBELL_WIP +int radeon_mmap(struct file *filp, struct vm_area_struct *vma); +#endif /* DUMBBELL_WIP */ +int radeon_mode_dumb_mmap(struct drm_file *filp, + struct drm_device *dev, + uint32_t handle, uint64_t *offset_p); +int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); +int radeon_mode_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); +struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, + int flags); +struct drm_gem_object *radeon_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf); + +#if defined(CONFIG_DEBUG_FS) +int radeon_debugfs_init(struct drm_minor *minor); +void radeon_debugfs_cleanup(struct drm_minor *minor); +#endif + + +int radeon_no_wb; +int radeon_modeset = 1; +int radeon_dynclks = -1; +int radeon_r4xx_atom = 0; +int radeon_agpmode = 0; +int radeon_vram_limit = 0; +int radeon_gart_size = 512; /* default gart size */ +int radeon_benchmarking = 0; +int radeon_testing = 0; +int radeon_connector_table = 0; +int radeon_tv = 1; +int radeon_audio = 0; +int radeon_disp_priority = 0; +int radeon_hw_i2c = 0; +int radeon_pcie_gen2 = -1; +int radeon_msi = -1; +int radeon_lockup_timeout = 10000; + +#ifdef DUMBBELL_WIP +MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); +module_param_named(no_wb, radeon_no_wb, int, 0444); + +MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); +module_param_named(modeset, radeon_modeset, int, 0400); + +MODULE_PARM_DESC(dynclks, "Disable/Enable dynamic clocks"); +module_param_named(dynclks, radeon_dynclks, int, 0444); + +MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx"); +module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); + +MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing"); +module_param_named(vramlimit, radeon_vram_limit, int, 0600); + +MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); +module_param_named(agpmode, radeon_agpmode, int, 0444); + +MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc)"); +module_param_named(gartsize, radeon_gart_size, int, 0600); + +MODULE_PARM_DESC(benchmark, "Run benchmark"); +module_param_named(benchmark, radeon_benchmarking, int, 0444); + +MODULE_PARM_DESC(test, "Run tests"); +module_param_named(test, radeon_testing, int, 0444); + +MODULE_PARM_DESC(connector_table, "Force connector table"); +module_param_named(connector_table, radeon_connector_table, int, 0444); + +MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); +module_param_named(tv, radeon_tv, int, 0444); + +MODULE_PARM_DESC(audio, "Audio enable (1 = enable)"); +module_param_named(audio, radeon_audio, int, 0444); + +MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)"); +module_param_named(disp_priority, radeon_disp_priority, int, 0444); + +MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)"); +module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); + +MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (-1 = auto, 0 = disable, 1 = enable)"); +module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); + +MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); +module_param_named(msi, radeon_msi, int, 0444); + +MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable)"); +module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444); + +static int radeon_suspend(struct drm_device *dev, pm_message_t state) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return 0; + + /* Disable *all* interrupts */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) + RADEON_WRITE(R500_DxMODE_INT_MASK, 0); + RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); + return 0; +} + +static int radeon_resume(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return 0; + + /* Restore interrupt registers */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) + RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); + RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); + return 0; +} +#endif /* DUMBBELL_WIP */ + +static drm_pci_id_list_t pciidlist[] = { + radeon_PCI_IDS +}; + +#ifdef DUMBBELL_WIP +static const struct file_operations radeon_driver_old_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = drm_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + .read = drm_read, +#ifdef CONFIG_COMPAT + .compat_ioctl = radeon_compat_ioctl, +#endif + .llseek = noop_llseek, +}; + +static struct drm_driver driver_old = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | + DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, + .dev_priv_size = sizeof(drm_radeon_buf_priv_t), + .load = radeon_driver_load, + .firstopen = radeon_driver_firstopen, + .open = radeon_driver_open, + .preclose = radeon_driver_preclose, + .postclose = radeon_driver_postclose, + .lastclose = radeon_driver_lastclose, + .unload = radeon_driver_unload, +#ifdef DUMBBELL_WIP + .suspend = radeon_suspend, + .resume = radeon_resume, +#endif /* DUMBBELL_WIP */ + .get_vblank_counter = radeon_get_vblank_counter, + .enable_vblank = radeon_enable_vblank, + .disable_vblank = radeon_disable_vblank, + .master_create = radeon_master_create, + .master_destroy = radeon_master_destroy, + .irq_preinstall = radeon_driver_irq_preinstall, + .irq_postinstall = radeon_driver_irq_postinstall, + .irq_uninstall = radeon_driver_irq_uninstall, + .irq_handler = radeon_driver_irq_handler, + .ioctls = radeon_ioctls, + .dma_ioctl = radeon_cp_buffers, + .fops = &radeon_driver_old_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; +#endif /* DUMBBELL_WIP */ + +static struct drm_driver_info kms_driver; + +#ifdef DUMBBELL_WIP +static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) +{ + struct apertures_struct *ap; + bool primary = false; + + ap = alloc_apertures(1); + if (!ap) + return -ENOMEM; + + ap->ranges[0].base = pci_resource_start(pdev, 0); + ap->ranges[0].size = pci_resource_len(pdev, 0); + +#ifdef CONFIG_X86 + primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif + remove_conflicting_framebuffers(ap, "radeondrmfb", primary); + kfree(ap); + + return 0; +} + +static int radeon_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int ret; + + /* Get rid of things like offb */ + ret = radeon_kick_out_firmware_fb(pdev); + if (ret) + return ret; + + return drm_get_pci_dev(pdev, ent, &kms_driver); +} + +static void +radeon_pci_remove(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + + drm_put_dev(dev); +} + +static int +radeon_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + return radeon_suspend_kms(dev, state); +} + +static int +radeon_pci_resume(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + return radeon_resume_kms(dev); +} + +static const struct file_operations radeon_driver_kms_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = radeon_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + .read = drm_read, +#ifdef CONFIG_COMPAT + .compat_ioctl = radeon_kms_compat_ioctl, +#endif +}; +#endif /* DUMBBELL_WIP */ + +static struct drm_driver_info kms_driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | + DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_GEM | + DRIVER_PRIME /* | DRIVE_MODESET */, +#ifdef DUMBBELL_WIP + .dev_priv_size = 0, +#endif /* DUMBBELL_WIP */ + .load = radeon_driver_load_kms, + .use_msi = radeon_msi_ok, + .firstopen = radeon_driver_firstopen_kms, + .open = radeon_driver_open_kms, + .preclose = radeon_driver_preclose_kms, + .postclose = radeon_driver_postclose_kms, + .lastclose = radeon_driver_lastclose_kms, + .unload = radeon_driver_unload_kms, +#ifdef DUMBBELL_WIP + .suspend = radeon_suspend_kms, + .resume = radeon_resume_kms, +#endif /* DUMBBELL_WIP */ + .get_vblank_counter = radeon_get_vblank_counter_kms, + .enable_vblank = radeon_enable_vblank_kms, + .disable_vblank = radeon_disable_vblank_kms, + .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, + .get_scanout_position = radeon_get_crtc_scanoutpos, + .irq_preinstall = radeon_driver_irq_preinstall_kms, + .irq_postinstall = radeon_driver_irq_postinstall_kms, + .irq_uninstall = radeon_driver_irq_uninstall_kms, + .irq_handler = radeon_driver_irq_handler_kms, + .ioctls = radeon_ioctls_kms, + .gem_init_object = radeon_gem_object_init, + .gem_free_object = radeon_gem_object_free, + .gem_open_object = radeon_gem_object_open, + .gem_close_object = radeon_gem_object_close, + .dma_ioctl = radeon_dma_ioctl_kms, + .dumb_create = radeon_mode_dumb_create, + .dumb_map_offset = radeon_mode_dumb_mmap, + .dumb_destroy = radeon_mode_dumb_destroy, +#ifdef DUMBBELL_WIP + .fops = &radeon_driver_kms_fops, +#endif /* DUMBBELL_WIP */ + +#ifdef DUMBBELL_WIP + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = radeon_gem_prime_export, + .gem_prime_import = radeon_gem_prime_import, +#endif /* DUMBBELL_WIP */ + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = KMS_DRIVER_MAJOR, + .minor = KMS_DRIVER_MINOR, + .patchlevel = KMS_DRIVER_PATCHLEVEL, +}; + +#ifdef DUMBBELL_WIP +static int __init radeon_init(void) +{ + driver = &driver_old; + pdriver = &radeon_pci_driver; + driver->num_ioctls = radeon_max_ioctl; +#ifdef CONFIG_VGA_CONSOLE + if (vgacon_text_force() && radeon_modeset == -1) { + DRM_INFO("VGACON disable radeon kernel modesetting.\n"); + driver = &driver_old; + pdriver = &radeon_pci_driver; + driver->driver_features &= ~DRIVER_MODESET; + radeon_modeset = 0; + } +#endif + /* if enabled by default */ + if (radeon_modeset == -1) { +#ifdef CONFIG_DRM_RADEON_KMS + DRM_INFO("radeon defaulting to kernel modesetting.\n"); + radeon_modeset = 1; +#else + DRM_INFO("radeon defaulting to userspace modesetting.\n"); + radeon_modeset = 0; +#endif + } + if (radeon_modeset == 1) { + DRM_INFO("radeon kernel modesetting enabled.\n"); + driver = &kms_driver; + pdriver = &radeon_kms_pci_driver; + driver->driver_features |= DRIVER_MODESET; + driver->num_ioctls = radeon_max_kms_ioctl; + radeon_register_atpx_handler(); + } + /* if the vga console setting is enabled still + * let modprobe override it */ + return drm_pci_init(driver, pdriver); +} + +static void __exit radeon_exit(void) +{ + drm_pci_exit(driver, pdriver); + radeon_unregister_atpx_handler(); +} +#endif /* DUMBBELL_WIP */ + +/* =================================================================== */ + +static int +radeon_probe(device_t kdev) +{ + + return drm_probe(kdev, pciidlist); +} + +static int +radeon_attach(device_t kdev) +{ + struct drm_device *dev; + + dev = device_get_softc(kdev); + if (radeon_modeset == 1) { + kms_driver.driver_features |= DRIVER_MODESET; + kms_driver.max_ioctl = radeon_max_kms_ioctl; + radeon_register_atpx_handler(); + } + dev->driver = &kms_driver; + return (drm_attach(kdev, pciidlist)); +} + +static int +radeon_suspend(device_t kdev) +{ + struct drm_device *dev; + int ret; + + dev = device_get_softc(kdev); + ret = radeon_suspend_kms(dev); + + return (-ret); +} + +static int +radeon_resume(device_t kdev) +{ + struct drm_device *dev; + int ret; + + dev = device_get_softc(kdev); + ret = radeon_resume_kms(dev); + + return (-ret); +} + +static device_method_t radeon_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, radeon_probe), + DEVMETHOD(device_attach, radeon_attach), + DEVMETHOD(device_suspend, radeon_suspend), + DEVMETHOD(device_resume, radeon_resume), + DEVMETHOD(device_detach, drm_detach), + DEVMETHOD_END +}; + +static driver_t radeon_driver = { + "drmn", + radeon_methods, + sizeof(struct drm_device) +}; + +extern devclass_t drm_devclass; +DRIVER_MODULE_ORDERED(radeonkms, vgapci, radeon_driver, drm_devclass, + NULL, NULL, SI_ORDER_ANY); +MODULE_DEPEND(radeonkms, drmn, 1, 1, 1); +MODULE_DEPEND(radeonkms, agp, 1, 1, 1); +MODULE_DEPEND(radeonkms, iicbus, 1, 1, 1); +MODULE_DEPEND(radeonkms, iic, 1, 1, 1); +MODULE_DEPEND(radeonkms, iicbb, 1, 1, 1); diff --git a/sys/dev/drm2/radeon/radeon_drv.h b/sys/dev/drm2/radeon/radeon_drv.h new file mode 100644 index 00000000000..f33ea189f6e --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_drv.h @@ -0,0 +1,2165 @@ +/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*- + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_DRV_H__ +#define __RADEON_DRV_H__ + +#include "radeon_family.h" + +/* General customization: + */ + +#define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others." + +#define DRIVER_NAME "radeon" +#define DRIVER_DESC "ATI Radeon" +#define DRIVER_DATE "20080528" + +/* Interface history: + * + * 1.1 - ?? + * 1.2 - Add vertex2 ioctl (keith) + * - Add stencil capability to clear ioctl (gareth, keith) + * - Increase MAX_TEXTURE_LEVELS (brian) + * 1.3 - Add cmdbuf ioctl (keith) + * - Add support for new radeon packets (keith) + * - Add getparam ioctl (keith) + * - Add flip-buffers ioctl, deprecate fullscreen foo (keith). + * 1.4 - Add scratch registers to get_param ioctl. + * 1.5 - Add r200 packets to cmdbuf ioctl + * - Add r200 function to init ioctl + * - Add 'scalar2' instruction to cmdbuf + * 1.6 - Add static GART memory manager + * Add irq handler (won't be turned on unless X server knows to) + * Add irq ioctls and irq_active getparam. + * Add wait command for cmdbuf ioctl + * Add GART offset query for getparam + * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5] + * and R200_PP_CUBIC_OFFSET_F1_[0..5]. + * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and + * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) + * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) + * Add 'GET' queries for starting additional clients on different VT's. + * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl. + * Add texture rectangle support for r100. + * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which + * clients use to tell the DRM where they think the framebuffer is + * located in the card's address space + * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color + * and GL_EXT_blend_[func|equation]_separate on r200 + * 1.12- Add R300 CP microcode support - this just loads the CP on r300 + * (No 3D support yet - just microcode loading). + * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters + * - Add hyperz support, add hyperz flags to clear ioctl. + * 1.14- Add support for color tiling + * - Add R100/R200 surface allocation/free support + * 1.15- Add support for texture micro tiling + * - Add support for r100 cube maps + * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear + * texture filtering on r200 + * 1.17- Add initial support for R300 (3D). + * 1.18- Add support for GL_ATI_fragment_shader, new packets + * R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces + * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR + * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) + * 1.19- Add support for gart table in FB memory and PCIE r300 + * 1.20- Add support for r300 texrect + * 1.21- Add support for card type getparam + * 1.22- Add support for texture cache flushes (R300_TX_CNTL) + * 1.23- Add new radeon memory map work from benh + * 1.24- Add general-purpose packet for manipulating scratch registers (r300) + * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, + * new packet type) + * 1.26- Add support for variable size PCI(E) gart aperture + * 1.27- Add support for IGP GART + * 1.28- Add support for VBL on CRTC2 + * 1.29- R500 3D cmd buffer support + * 1.30- Add support for occlusion queries + * 1.31- Add support for num Z pipes from GET_PARAM + * 1.32- fixes for rv740 setup + * 1.33- Add r6xx/r7xx const buffer support + */ +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 33 +#define DRIVER_PATCHLEVEL 0 + +enum radeon_cp_microcode_version { + UCODE_R100, + UCODE_R200, + UCODE_R300, +}; + +typedef struct drm_radeon_freelist { + unsigned int age; + struct drm_buf *buf; + struct drm_radeon_freelist *next; + struct drm_radeon_freelist *prev; +} drm_radeon_freelist_t; + +typedef struct drm_radeon_ring_buffer { + u32 *start; + u32 *end; + int size; + int size_l2qw; + + int rptr_update; /* Double Words */ + int rptr_update_l2qw; /* log2 Quad Words */ + + int fetch_size; /* Double Words */ + int fetch_size_l2ow; /* log2 Oct Words */ + + u32 tail; + u32 tail_mask; + int space; + + int high_mark; +} drm_radeon_ring_buffer_t; + +typedef struct drm_radeon_depth_clear_t { + u32 rb3d_cntl; + u32 rb3d_zstencilcntl; + u32 se_cntl; +} drm_radeon_depth_clear_t; + +struct drm_radeon_driver_file_fields { + int64_t radeon_fb_delta; +}; + +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + int start; + int size; + struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ +}; + +struct radeon_surface { + int refcount; + u32 lower; + u32 upper; + u32 flags; +}; + +struct radeon_virt_surface { + int surface_index; + u32 lower; + u32 upper; + u32 flags; + struct drm_file *file_priv; +#define PCIGART_FILE_PRIV ((void *) -1L) +}; + +#define RADEON_FLUSH_EMITED (1 << 0) +#define RADEON_PURGE_EMITED (1 << 1) + +struct drm_radeon_master_private { + drm_local_map_t *sarea; + drm_radeon_sarea_t *sarea_priv; +}; + +typedef struct drm_radeon_private { + drm_radeon_ring_buffer_t ring; + + u32 fb_location; + u32 fb_size; + int new_memmap; + + int gart_size; + u32 gart_vm_start; + unsigned long gart_buffers_offset; + + int cp_mode; + int cp_running; + + drm_radeon_freelist_t *head; + drm_radeon_freelist_t *tail; + int last_buf; + int writeback_works; + + int usec_timeout; + + int microcode_version; + + struct { + u32 boxes; + int freelist_timeouts; + int freelist_loops; + int requested_bufs; + int last_frame_reads; + int last_clear_reads; + int clears; + int texture_uploads; + } stats; + + int do_boxes; + int page_flipping; + + u32 color_fmt; + unsigned int front_offset; + unsigned int front_pitch; + unsigned int back_offset; + unsigned int back_pitch; + + u32 depth_fmt; + unsigned int depth_offset; + unsigned int depth_pitch; + + u32 front_pitch_offset; + u32 back_pitch_offset; + u32 depth_pitch_offset; + + drm_radeon_depth_clear_t depth_clear; + + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long gart_textures_offset; + + drm_local_map_t *sarea; + drm_local_map_t *cp_ring; + drm_local_map_t *ring_rptr; + drm_local_map_t *gart_textures; + + struct mem_block *gart_heap; + struct mem_block *fb_heap; + + /* SW interrupt */ + wait_queue_head_t swi_queue; + atomic_t swi_emitted; + int vblank_crtc; + uint32_t irq_enable_reg; + uint32_t r500_disp_irq_reg; + + struct radeon_surface surfaces[RADEON_MAX_SURFACES]; + struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; + + unsigned long pcigart_offset; + unsigned int pcigart_offset_set; + struct drm_ati_pcigart_info gart_info; + + u32 scratch_ages[5]; + + int have_z_offset; + + /* starting from here on, data is preserved across an open */ + uint32_t flags; /* see radeon_chip_flags */ + resource_size_t fb_aper_offset; + + int num_gb_pipes; + int num_z_pipes; + int track_flush; + drm_local_map_t *mmio; + + /* r6xx/r7xx pipe/shader config */ + int r600_max_pipes; + int r600_max_tile_pipes; + int r600_max_simds; + int r600_max_backends; + int r600_max_gprs; + int r600_max_threads; + int r600_max_stack_entries; + int r600_max_hw_contexts; + int r600_max_gs_threads; + int r600_sx_max_export_size; + int r600_sx_max_export_pos_size; + int r600_sx_max_export_smx_size; + int r600_sq_num_cf_insts; + int r700_sx_num_of_sets; + int r700_sc_prim_fifo_size; + int r700_sc_hiz_tile_fifo_size; + int r700_sc_earlyz_tile_fifo_fize; + int r600_group_size; + int r600_npipes; + int r600_nbanks; + + struct sx cs_mutex; + u32 cs_id_scnt; + u32 cs_id_wcnt; + /* r6xx/r7xx drm blit vertex buffer */ + struct drm_buf *blit_vb; + + /* firmware */ + const struct firmware *me_fw, *pfp_fw; +} drm_radeon_private_t; + +typedef struct drm_radeon_buf_priv { + u32 age; +} drm_radeon_buf_priv_t; + +struct drm_buffer; + +typedef struct drm_radeon_kcmd_buffer { + int bufsz; + struct drm_buffer *buffer; + int nbox; + struct drm_clip_rect __user *boxes; +} drm_radeon_kcmd_buffer_t; + +extern int radeon_no_wb; +extern struct drm_ioctl_desc radeon_ioctls[]; +extern int radeon_max_ioctl; + +extern u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv); +extern void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val); + +#define GET_RING_HEAD(dev_priv) radeon_get_ring_head(dev_priv) +#define SET_RING_HEAD(dev_priv, val) radeon_set_ring_head(dev_priv, val) + +/* Check whether the given hardware address is inside the framebuffer or the + * GART area. + */ +static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv, + u64 off) +{ + u32 fb_start = dev_priv->fb_location; + u32 fb_end = fb_start + dev_priv->fb_size - 1; + u32 gart_start = dev_priv->gart_vm_start; + u32 gart_end = gart_start + dev_priv->gart_size - 1; + + return ((off >= fb_start && off <= fb_end) || + (off >= gart_start && off <= gart_end)); +} + +/* radeon_state.c */ +extern void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf); + + /* radeon_cp.c */ +extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv); +extern void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc); +extern void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base); + +extern void radeon_freelist_reset(struct drm_device * dev); +extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); + +extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n); + +extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv); + +extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags); +extern int radeon_presetup(struct drm_device *dev); +extern int radeon_driver_postcleanup(struct drm_device *dev); + +extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void radeon_mem_takedown(struct mem_block **heap); +extern void radeon_mem_release(struct drm_file *file_priv, + struct mem_block *heap); + +extern void radeon_enable_bm(struct drm_radeon_private *dev_priv); +extern u32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off); +extern void radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val); + + /* radeon_irq.c */ +extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state); +extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); + +extern void radeon_do_release(struct drm_device * dev); +extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); +extern int radeon_enable_vblank(struct drm_device *dev, int crtc); +extern void radeon_disable_vblank(struct drm_device *dev, int crtc); +extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); +extern void radeon_driver_irq_preinstall(struct drm_device * dev); +extern int radeon_driver_irq_postinstall(struct drm_device *dev); +extern void radeon_driver_irq_uninstall(struct drm_device * dev); +extern void radeon_enable_interrupt(struct drm_device *dev); +extern int radeon_vblank_crtc_get(struct drm_device *dev); +extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); + +extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); +extern int radeon_driver_unload(struct drm_device *dev); +extern int radeon_driver_firstopen(struct drm_device *dev); +extern void radeon_driver_preclose(struct drm_device *dev, + struct drm_file *file_priv); +extern void radeon_driver_postclose(struct drm_device *dev, + struct drm_file *file_priv); +extern void radeon_driver_lastclose(struct drm_device * dev); +extern int radeon_driver_open(struct drm_device *dev, + struct drm_file *file_priv); +extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); +extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); + +extern int radeon_master_create(struct drm_device *dev, struct drm_master *master); +extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master); +extern void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master); +/* r300_cmdbuf.c */ +extern void r300_init_reg_flags(struct drm_device *dev); + +extern int r300_do_cp_cmdbuf(struct drm_device *dev, + struct drm_file *file_priv, + drm_radeon_kcmd_buffer_t *cmdbuf); + +/* r600_cp.c */ +extern int r600_do_engine_reset(struct drm_device *dev); +extern int r600_do_cleanup_cp(struct drm_device *dev); +extern int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, + struct drm_file *file_priv); +extern int r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv); +extern int r600_do_cp_idle(drm_radeon_private_t *dev_priv); +extern void r600_do_cp_start(drm_radeon_private_t *dev_priv); +extern void r600_do_cp_reset(drm_radeon_private_t *dev_priv); +extern void r600_do_cp_stop(drm_radeon_private_t *dev_priv); +extern int r600_cp_dispatch_indirect(struct drm_device *dev, + struct drm_buf *buf, int start, int end); +extern int r600_page_table_init(struct drm_device *dev); +extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info); +extern int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv); +extern void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv); +extern int r600_cp_dispatch_texture(struct drm_device *dev, + struct drm_file *file_priv, + drm_radeon_texture_t *tex, + drm_radeon_tex_image_t *image); +/* r600_blit.c */ +extern int r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv); +extern void r600_done_blit_copy(struct drm_device *dev); +extern void r600_blit_copy(struct drm_device *dev, + uint64_t src_gpu_addr, uint64_t dst_gpu_addr, + int size_bytes); +extern void r600_blit_swap(struct drm_device *dev, + uint64_t src_gpu_addr, uint64_t dst_gpu_addr, + int sx, int sy, int dx, int dy, + int w, int h, int src_pitch, int dst_pitch, int cpp); + +/* atpx handler */ +void radeon_register_atpx_handler(void); +void radeon_unregister_atpx_handler(void); + +/* Flags for stats.boxes + */ +#define RADEON_BOX_DMA_IDLE 0x1 +#define RADEON_BOX_RING_FULL 0x2 +#define RADEON_BOX_FLIP 0x4 +#define RADEON_BOX_WAIT_IDLE 0x8 +#define RADEON_BOX_TEXTURE_LOAD 0x10 + +/* Register definitions, register access macros and drmAddMap constants + * for Radeon kernel driver. + */ +#define RADEON_MM_INDEX 0x0000 +#define RADEON_MM_DATA 0x0004 + +#define RADEON_AGP_COMMAND 0x0f60 +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */ +# define RADEON_AGP_ENABLE (1<<8) +#define RADEON_AUX_SCISSOR_CNTL 0x26f0 +# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) +# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) +# define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26) +# define RADEON_SCISSOR_0_ENABLE (1 << 28) +# define RADEON_SCISSOR_1_ENABLE (1 << 29) +# define RADEON_SCISSOR_2_ENABLE (1 << 30) + +/* + * PCIE radeons (rv370/rv380, rv410, r423/r430/r480, r5xx) + * don't have an explicit bus mastering disable bit. It's handled + * by the PCI D-states. PMI_BM_DIS disables D-state bus master + * handling, not bus mastering itself. + */ +#define RADEON_BUS_CNTL 0x0030 +/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ +# define RADEON_BUS_MASTER_DIS (1 << 6) +/* rs600/rs690/rs740 */ +# define RS600_BUS_MASTER_DIS (1 << 14) +# define RS600_MSI_REARM (1 << 20) +/* see RS400_MSI_REARM in AIC_CNTL for rs480 */ + +#define RADEON_BUS_CNTL1 0x0034 +# define RADEON_PMI_BM_DIS (1 << 2) +# define RADEON_PMI_INT_DIS (1 << 3) + +#define RV370_BUS_CNTL 0x004c +# define RV370_PMI_BM_DIS (1 << 5) +# define RV370_PMI_INT_DIS (1 << 6) + +#define RADEON_MSI_REARM_EN 0x0160 +/* rv370/rv380, rv410, r423/r430/r480, r5xx */ +# define RV370_MSI_REARM_EN (1 << 0) + +#define RADEON_CLOCK_CNTL_DATA 0x000c +# define RADEON_PLL_WR_EN (1 << 7) +#define RADEON_CLOCK_CNTL_INDEX 0x0008 +#define RADEON_CONFIG_APER_SIZE 0x0108 +#define RADEON_CONFIG_MEMSIZE 0x00f8 +#define RADEON_CRTC_OFFSET 0x0224 +#define RADEON_CRTC_OFFSET_CNTL 0x0228 +# define RADEON_CRTC_TILE_EN (1 << 15) +# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 + +#define RADEON_PCIE_INDEX 0x0030 +#define RADEON_PCIE_DATA 0x0034 +#define RADEON_PCIE_TX_GART_CNTL 0x10 +# define RADEON_PCIE_TX_GART_EN (1 << 0) +# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1) +# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1 << 1) +# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3 << 1) +# define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0 << 3) +# define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1 << 3) +# define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1 << 5) +# define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1 << 8) +#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11 +#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12 +#define RADEON_PCIE_TX_GART_BASE 0x13 +#define RADEON_PCIE_TX_GART_START_LO 0x14 +#define RADEON_PCIE_TX_GART_START_HI 0x15 +#define RADEON_PCIE_TX_GART_END_LO 0x16 +#define RADEON_PCIE_TX_GART_END_HI 0x17 + +#define RS480_NB_MC_INDEX 0x168 +# define RS480_NB_MC_IND_WR_EN (1 << 8) +#define RS480_NB_MC_DATA 0x16c + +#define RS690_MC_INDEX 0x78 +# define RS690_MC_INDEX_MASK 0x1ff +# define RS690_MC_INDEX_WR_EN (1 << 9) +# define RS690_MC_INDEX_WR_ACK 0x7f +#define RS690_MC_DATA 0x7c + +/* MC indirect registers */ +#define RS480_MC_MISC_CNTL 0x18 +# define RS480_DISABLE_GTW (1 << 1) +/* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */ +# define RS480_GART_INDEX_REG_EN (1 << 12) +# define RS690_BLOCK_GFX_D3_EN (1 << 14) +#define RS480_K8_FB_LOCATION 0x1e +#define RS480_GART_FEATURE_ID 0x2b +# define RS480_HANG_EN (1 << 11) +# define RS480_TLB_ENABLE (1 << 18) +# define RS480_P2P_ENABLE (1 << 19) +# define RS480_GTW_LAC_EN (1 << 25) +# define RS480_2LEVEL_GART (0 << 30) +# define RS480_1LEVEL_GART (1 << 30) +# define RS480_PDC_EN (1 << 31) +#define RS480_GART_BASE 0x2c +#define RS480_GART_CACHE_CNTRL 0x2e +# define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */ +#define RS480_AGP_ADDRESS_SPACE_SIZE 0x38 +# define RS480_GART_EN (1 << 0) +# define RS480_VA_SIZE_32MB (0 << 1) +# define RS480_VA_SIZE_64MB (1 << 1) +# define RS480_VA_SIZE_128MB (2 << 1) +# define RS480_VA_SIZE_256MB (3 << 1) +# define RS480_VA_SIZE_512MB (4 << 1) +# define RS480_VA_SIZE_1GB (5 << 1) +# define RS480_VA_SIZE_2GB (6 << 1) +#define RS480_AGP_MODE_CNTL 0x39 +# define RS480_POST_GART_Q_SIZE (1 << 18) +# define RS480_NONGART_SNOOP (1 << 19) +# define RS480_AGP_RD_BUF_SIZE (1 << 20) +# define RS480_REQ_TYPE_SNOOP_SHIFT 22 +# define RS480_REQ_TYPE_SNOOP_MASK 0x3 +# define RS480_REQ_TYPE_SNOOP_DIS (1 << 24) +#define RS480_MC_MISC_UMA_CNTL 0x5f +#define RS480_MC_MCLK_CNTL 0x7a +#define RS480_MC_UMA_DUALCH_CNTL 0x86 + +#define RS690_MC_FB_LOCATION 0x100 +#define RS690_MC_AGP_LOCATION 0x101 +#define RS690_MC_AGP_BASE 0x102 +#define RS690_MC_AGP_BASE_2 0x103 + +#define RS600_MC_INDEX 0x70 +# define RS600_MC_ADDR_MASK 0xffff +# define RS600_MC_IND_SEQ_RBS_0 (1 << 16) +# define RS600_MC_IND_SEQ_RBS_1 (1 << 17) +# define RS600_MC_IND_SEQ_RBS_2 (1 << 18) +# define RS600_MC_IND_SEQ_RBS_3 (1 << 19) +# define RS600_MC_IND_AIC_RBS (1 << 20) +# define RS600_MC_IND_CITF_ARB0 (1 << 21) +# define RS600_MC_IND_CITF_ARB1 (1 << 22) +# define RS600_MC_IND_WR_EN (1 << 23) +#define RS600_MC_DATA 0x74 + +#define RS600_MC_STATUS 0x0 +# define RS600_MC_IDLE (1 << 1) +#define RS600_MC_FB_LOCATION 0x4 +#define RS600_MC_AGP_LOCATION 0x5 +#define RS600_AGP_BASE 0x6 +#define RS600_AGP_BASE_2 0x7 +#define RS600_MC_CNTL1 0x9 +# define RS600_ENABLE_PAGE_TABLES (1 << 26) +#define RS600_MC_PT0_CNTL 0x100 +# define RS600_ENABLE_PT (1 << 0) +# define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15) +# define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21) +# define RS600_INVALIDATE_ALL_L1_TLBS (1 << 28) +# define RS600_INVALIDATE_L2_CACHE (1 << 29) +#define RS600_MC_PT0_CONTEXT0_CNTL 0x102 +# define RS600_ENABLE_PAGE_TABLE (1 << 0) +# define RS600_PAGE_TABLE_TYPE_FLAT (0 << 1) +#define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR 0x112 +#define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR 0x114 +#define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c +#define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR 0x12c +#define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR 0x13c +#define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR 0x14c +#define RS600_MC_PT0_CLIENT0_CNTL 0x16c +# define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE (1 << 0) +# define RS600_TRANSLATION_MODE_OVERRIDE (1 << 1) +# define RS600_SYSTEM_ACCESS_MODE_MASK (3 << 8) +# define RS600_SYSTEM_ACCESS_MODE_PA_ONLY (0 << 8) +# define RS600_SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 8) +# define RS600_SYSTEM_ACCESS_MODE_IN_SYS (2 << 8) +# define RS600_SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 8) +# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH (0 << 10) +# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 10) +# define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11) +# define RS600_ENABLE_FRAGMENT_PROCESSING (1 << 14) +# define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) +# define RS600_INVALIDATE_L1_TLB (1 << 20) + +#define R520_MC_IND_INDEX 0x70 +#define R520_MC_IND_WR_EN (1 << 24) +#define R520_MC_IND_DATA 0x74 + +#define RV515_MC_FB_LOCATION 0x01 +#define RV515_MC_AGP_LOCATION 0x02 +#define RV515_MC_AGP_BASE 0x03 +#define RV515_MC_AGP_BASE_2 0x04 + +#define R520_MC_FB_LOCATION 0x04 +#define R520_MC_AGP_LOCATION 0x05 +#define R520_MC_AGP_BASE 0x06 +#define R520_MC_AGP_BASE_2 0x07 + +#define RADEON_MPP_TB_CONFIG 0x01c0 +#define RADEON_MEM_CNTL 0x0140 +#define RADEON_MEM_SDRAM_MODE_REG 0x0158 +#define RADEON_AGP_BASE_2 0x015c /* r200+ only */ +#define RS480_AGP_BASE_2 0x0164 +#define RADEON_AGP_BASE 0x0170 + +/* pipe config regs */ +#define R400_GB_PIPE_SELECT 0x402c +#define RV530_GB_PIPE_SELECT2 0x4124 +#define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */ +#define R300_GB_TILE_CONFIG 0x4018 +# define R300_ENABLE_TILING (1 << 0) +# define R300_PIPE_COUNT_RV350 (0 << 1) +# define R300_PIPE_COUNT_R300 (3 << 1) +# define R300_PIPE_COUNT_R420_3P (6 << 1) +# define R300_PIPE_COUNT_R420 (7 << 1) +# define R300_TILE_SIZE_8 (0 << 4) +# define R300_TILE_SIZE_16 (1 << 4) +# define R300_TILE_SIZE_32 (2 << 4) +# define R300_SUBPIXEL_1_12 (0 << 16) +# define R300_SUBPIXEL_1_16 (1 << 16) +#define R300_DST_PIPE_CONFIG 0x170c +# define R300_PIPE_AUTO_CONFIG (1 << 31) +#define R300_RB2D_DSTCACHE_MODE 0x3428 +# define R300_DC_AUTOFLUSH_ENABLE (1 << 8) +# define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17) + +#define RADEON_RB3D_COLOROFFSET 0x1c40 +#define RADEON_RB3D_COLORPITCH 0x1c48 + +#define RADEON_SRC_X_Y 0x1590 + +#define RADEON_DP_GUI_MASTER_CNTL 0x146c +# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) +# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) +# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define RADEON_GMC_BRUSH_NONE (15 << 4) +# define RADEON_GMC_DST_16BPP (4 << 8) +# define RADEON_GMC_DST_24BPP (5 << 8) +# define RADEON_GMC_DST_32BPP (6 << 8) +# define RADEON_GMC_DST_DATATYPE_SHIFT 8 +# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) +# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) +# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) +# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) +# define RADEON_GMC_WR_MSK_DIS (1 << 30) +# define RADEON_ROP3_S 0x00cc0000 +# define RADEON_ROP3_P 0x00f00000 +#define RADEON_DP_WRITE_MASK 0x16cc +#define RADEON_SRC_PITCH_OFFSET 0x1428 +#define RADEON_DST_PITCH_OFFSET 0x142c +#define RADEON_DST_PITCH_OFFSET_C 0x1c80 +# define RADEON_DST_TILE_LINEAR (0 << 30) +# define RADEON_DST_TILE_MACRO (1 << 30) +# define RADEON_DST_TILE_MICRO (2 << 30) +# define RADEON_DST_TILE_BOTH (3 << 30) + +#define RADEON_SCRATCH_REG0 0x15e0 +#define RADEON_SCRATCH_REG1 0x15e4 +#define RADEON_SCRATCH_REG2 0x15e8 +#define RADEON_SCRATCH_REG3 0x15ec +#define RADEON_SCRATCH_REG4 0x15f0 +#define RADEON_SCRATCH_REG5 0x15f4 +#define RADEON_SCRATCH_UMSK 0x0770 +#define RADEON_SCRATCH_ADDR 0x0774 + +#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) + +extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index); + +#define GET_SCRATCH(dev_priv, x) radeon_get_scratch(dev_priv, x) + +#define R600_SCRATCH_REG0 0x8500 +#define R600_SCRATCH_REG1 0x8504 +#define R600_SCRATCH_REG2 0x8508 +#define R600_SCRATCH_REG3 0x850c +#define R600_SCRATCH_REG4 0x8510 +#define R600_SCRATCH_REG5 0x8514 +#define R600_SCRATCH_REG6 0x8518 +#define R600_SCRATCH_REG7 0x851c +#define R600_SCRATCH_UMSK 0x8540 +#define R600_SCRATCH_ADDR 0x8544 + +#define R600_SCRATCHOFF(x) (R600_SCRATCH_REG_OFFSET + 4*(x)) + +#define RADEON_GEN_INT_CNTL 0x0040 +# define RADEON_CRTC_VBLANK_MASK (1 << 0) +# define RADEON_CRTC2_VBLANK_MASK (1 << 9) +# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) +# define RADEON_SW_INT_ENABLE (1 << 25) + +#define RADEON_GEN_INT_STATUS 0x0044 +# define RADEON_CRTC_VBLANK_STAT (1 << 0) +# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) +# define RADEON_CRTC2_VBLANK_STAT (1 << 9) +# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) +# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) +# define RADEON_SW_INT_TEST (1 << 25) +# define RADEON_SW_INT_TEST_ACK (1 << 25) +# define RADEON_SW_INT_FIRE (1 << 26) +# define R500_DISPLAY_INT_STATUS (1 << 0) + +#define RADEON_HOST_PATH_CNTL 0x0130 +# define RADEON_HDP_SOFT_RESET (1 << 26) +# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) +# define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28) + +#define RADEON_ISYNC_CNTL 0x1724 +# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0) +# define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1) +# define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2) +# define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3) +# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) +# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) + +#define RADEON_RBBM_GUICNTL 0x172c +# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) +# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) +# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) +# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) + +#define RADEON_MC_AGP_LOCATION 0x014c +#define RADEON_MC_FB_LOCATION 0x0148 +#define RADEON_MCLK_CNTL 0x0012 +# define RADEON_FORCEON_MCLKA (1 << 16) +# define RADEON_FORCEON_MCLKB (1 << 17) +# define RADEON_FORCEON_YCLKA (1 << 18) +# define RADEON_FORCEON_YCLKB (1 << 19) +# define RADEON_FORCEON_MC (1 << 20) +# define RADEON_FORCEON_AIC (1 << 21) + +#define RADEON_PP_BORDER_COLOR_0 0x1d40 +#define RADEON_PP_BORDER_COLOR_1 0x1d44 +#define RADEON_PP_BORDER_COLOR_2 0x1d48 +#define RADEON_PP_CNTL 0x1c38 +# define RADEON_SCISSOR_ENABLE (1 << 1) +#define RADEON_PP_LUM_MATRIX 0x1d00 +#define RADEON_PP_MISC 0x1c14 +#define RADEON_PP_ROT_MATRIX_0 0x1d58 +#define RADEON_PP_TXFILTER_0 0x1c54 +#define RADEON_PP_TXOFFSET_0 0x1c5c +#define RADEON_PP_TXFILTER_1 0x1c6c +#define RADEON_PP_TXFILTER_2 0x1c84 + +#define R300_RB2D_DSTCACHE_CTLSTAT 0x342c /* use R300_DSTCACHE_CTLSTAT */ +#define R300_DSTCACHE_CTLSTAT 0x1714 +# define R300_RB2D_DC_FLUSH (3 << 0) +# define R300_RB2D_DC_FREE (3 << 2) +# define R300_RB2D_DC_FLUSH_ALL 0xf +# define R300_RB2D_DC_BUSY (1 << 31) +#define RADEON_RB3D_CNTL 0x1c3c +# define RADEON_ALPHA_BLEND_ENABLE (1 << 0) +# define RADEON_PLANE_MASK_ENABLE (1 << 1) +# define RADEON_DITHER_ENABLE (1 << 2) +# define RADEON_ROUND_ENABLE (1 << 3) +# define RADEON_SCALE_DITHER_ENABLE (1 << 4) +# define RADEON_DITHER_INIT (1 << 5) +# define RADEON_ROP_ENABLE (1 << 6) +# define RADEON_STENCIL_ENABLE (1 << 7) +# define RADEON_Z_ENABLE (1 << 8) +# define RADEON_ZBLOCK16 (1 << 15) +#define RADEON_RB3D_DEPTHOFFSET 0x1c24 +#define RADEON_RB3D_DEPTHCLEARVALUE 0x3230 +#define RADEON_RB3D_DEPTHPITCH 0x1c28 +#define RADEON_RB3D_PLANEMASK 0x1d84 +#define RADEON_RB3D_STENCILREFMASK 0x1d7c +#define RADEON_RB3D_ZCACHE_MODE 0x3250 +#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 +# define RADEON_RB3D_ZC_FLUSH (1 << 0) +# define RADEON_RB3D_ZC_FREE (1 << 2) +# define RADEON_RB3D_ZC_FLUSH_ALL 0x5 +# define RADEON_RB3D_ZC_BUSY (1 << 31) +#define R300_ZB_ZCACHE_CTLSTAT 0x4f18 +# define R300_ZC_FLUSH (1 << 0) +# define R300_ZC_FREE (1 << 1) +# define R300_ZC_BUSY (1 << 31) +#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c +# define RADEON_RB3D_DC_FLUSH (3 << 0) +# define RADEON_RB3D_DC_FREE (3 << 2) +# define RADEON_RB3D_DC_FLUSH_ALL 0xf +# define RADEON_RB3D_DC_BUSY (1 << 31) +#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c +# define R300_RB3D_DC_FLUSH (2 << 0) +# define R300_RB3D_DC_FREE (2 << 2) +# define R300_RB3D_DC_FINISH (1 << 4) +#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c +# define RADEON_Z_TEST_MASK (7 << 4) +# define RADEON_Z_TEST_ALWAYS (7 << 4) +# define RADEON_Z_HIERARCHY_ENABLE (1 << 8) +# define RADEON_STENCIL_TEST_ALWAYS (7 << 12) +# define RADEON_STENCIL_S_FAIL_REPLACE (2 << 16) +# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) +# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) +# define RADEON_Z_COMPRESSION_ENABLE (1 << 28) +# define RADEON_FORCE_Z_DIRTY (1 << 29) +# define RADEON_Z_WRITE_ENABLE (1 << 30) +# define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31) +#define RADEON_RBBM_SOFT_RESET 0x00f0 +# define RADEON_SOFT_RESET_CP (1 << 0) +# define RADEON_SOFT_RESET_HI (1 << 1) +# define RADEON_SOFT_RESET_SE (1 << 2) +# define RADEON_SOFT_RESET_RE (1 << 3) +# define RADEON_SOFT_RESET_PP (1 << 4) +# define RADEON_SOFT_RESET_E2 (1 << 5) +# define RADEON_SOFT_RESET_RB (1 << 6) +# define RADEON_SOFT_RESET_HDP (1 << 7) +/* + * 6:0 Available slots in the FIFO + * 8 Host Interface active + * 9 CP request active + * 10 FIFO request active + * 11 Host Interface retry active + * 12 CP retry active + * 13 FIFO retry active + * 14 FIFO pipeline busy + * 15 Event engine busy + * 16 CP command stream busy + * 17 2D engine busy + * 18 2D portion of render backend busy + * 20 3D setup engine busy + * 26 GA engine busy + * 27 CBA 2D engine busy + * 31 2D engine busy or 3D engine busy or FIFO not empty or CP busy or + * command stream queue not empty or Ring Buffer not empty + */ +#define RADEON_RBBM_STATUS 0x0e40 +/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register. */ +/* #define RADEON_RBBM_STATUS 0x1740 */ +/* bits 6:0 are dword slots available in the cmd fifo */ +# define RADEON_RBBM_FIFOCNT_MASK 0x007f +# define RADEON_HIRQ_ON_RBB (1 << 8) +# define RADEON_CPRQ_ON_RBB (1 << 9) +# define RADEON_CFRQ_ON_RBB (1 << 10) +# define RADEON_HIRQ_IN_RTBUF (1 << 11) +# define RADEON_CPRQ_IN_RTBUF (1 << 12) +# define RADEON_CFRQ_IN_RTBUF (1 << 13) +# define RADEON_PIPE_BUSY (1 << 14) +# define RADEON_ENG_EV_BUSY (1 << 15) +# define RADEON_CP_CMDSTRM_BUSY (1 << 16) +# define RADEON_E2_BUSY (1 << 17) +# define RADEON_RB2D_BUSY (1 << 18) +# define RADEON_RB3D_BUSY (1 << 19) /* not used on r300 */ +# define RADEON_VAP_BUSY (1 << 20) +# define RADEON_RE_BUSY (1 << 21) /* not used on r300 */ +# define RADEON_TAM_BUSY (1 << 22) /* not used on r300 */ +# define RADEON_TDM_BUSY (1 << 23) /* not used on r300 */ +# define RADEON_PB_BUSY (1 << 24) /* not used on r300 */ +# define RADEON_TIM_BUSY (1 << 25) /* not used on r300 */ +# define RADEON_GA_BUSY (1 << 26) +# define RADEON_CBA2D_BUSY (1 << 27) +# define RADEON_RBBM_ACTIVE (1 << 31) +#define RADEON_RE_LINE_PATTERN 0x1cd0 +#define RADEON_RE_MISC 0x26c4 +#define RADEON_RE_TOP_LEFT 0x26c0 +#define RADEON_RE_WIDTH_HEIGHT 0x1c44 +#define RADEON_RE_STIPPLE_ADDR 0x1cc8 +#define RADEON_RE_STIPPLE_DATA 0x1ccc + +#define RADEON_SCISSOR_TL_0 0x1cd8 +#define RADEON_SCISSOR_BR_0 0x1cdc +#define RADEON_SCISSOR_TL_1 0x1ce0 +#define RADEON_SCISSOR_BR_1 0x1ce4 +#define RADEON_SCISSOR_TL_2 0x1ce8 +#define RADEON_SCISSOR_BR_2 0x1cec +#define RADEON_SE_COORD_FMT 0x1c50 +#define RADEON_SE_CNTL 0x1c4c +# define RADEON_FFACE_CULL_CW (0 << 0) +# define RADEON_BFACE_SOLID (3 << 1) +# define RADEON_FFACE_SOLID (3 << 3) +# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) +# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) +# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) +# define RADEON_ALPHA_SHADE_FLAT (1 << 10) +# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) +# define RADEON_SPECULAR_SHADE_FLAT (1 << 12) +# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) +# define RADEON_FOG_SHADE_FLAT (1 << 14) +# define RADEON_FOG_SHADE_GOURAUD (2 << 14) +# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) +# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) +# define RADEON_VTX_PIX_CENTER_OGL (1 << 27) +# define RADEON_ROUND_MODE_TRUNC (0 << 28) +# define RADEON_ROUND_PREC_8TH_PIX (1 << 30) +#define RADEON_SE_CNTL_STATUS 0x2140 +#define RADEON_SE_LINE_WIDTH 0x1db8 +#define RADEON_SE_VPORT_XSCALE 0x1d98 +#define RADEON_SE_ZBIAS_FACTOR 0x1db0 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 +#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 +#define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200 +# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 +# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 +#define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204 +#define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208 +# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 +#define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C +#define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8 +#define RADEON_SURFACE_ACCESS_CLR 0x0bfc +#define RADEON_SURFACE_CNTL 0x0b00 +# define RADEON_SURF_TRANSLATION_DIS (1 << 8) +# define RADEON_NONSURF_AP0_SWP_MASK (3 << 20) +# define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20) +# define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20) +# define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20) +# define RADEON_NONSURF_AP1_SWP_MASK (3 << 22) +# define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22) +# define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22) +# define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22) +#define RADEON_SURFACE0_INFO 0x0b0c +# define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0) +# define RADEON_SURF_TILE_MODE_MASK (3 << 16) +# define RADEON_SURF_TILE_MODE_MACRO (0 << 16) +# define RADEON_SURF_TILE_MODE_MICRO (1 << 16) +# define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16) +# define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16) +#define RADEON_SURFACE0_LOWER_BOUND 0x0b04 +#define RADEON_SURFACE0_UPPER_BOUND 0x0b08 +# define RADEON_SURF_ADDRESS_FIXED_MASK (0x3ff << 0) +#define RADEON_SURFACE1_INFO 0x0b1c +#define RADEON_SURFACE1_LOWER_BOUND 0x0b14 +#define RADEON_SURFACE1_UPPER_BOUND 0x0b18 +#define RADEON_SURFACE2_INFO 0x0b2c +#define RADEON_SURFACE2_LOWER_BOUND 0x0b24 +#define RADEON_SURFACE2_UPPER_BOUND 0x0b28 +#define RADEON_SURFACE3_INFO 0x0b3c +#define RADEON_SURFACE3_LOWER_BOUND 0x0b34 +#define RADEON_SURFACE3_UPPER_BOUND 0x0b38 +#define RADEON_SURFACE4_INFO 0x0b4c +#define RADEON_SURFACE4_LOWER_BOUND 0x0b44 +#define RADEON_SURFACE4_UPPER_BOUND 0x0b48 +#define RADEON_SURFACE5_INFO 0x0b5c +#define RADEON_SURFACE5_LOWER_BOUND 0x0b54 +#define RADEON_SURFACE5_UPPER_BOUND 0x0b58 +#define RADEON_SURFACE6_INFO 0x0b6c +#define RADEON_SURFACE6_LOWER_BOUND 0x0b64 +#define RADEON_SURFACE6_UPPER_BOUND 0x0b68 +#define RADEON_SURFACE7_INFO 0x0b7c +#define RADEON_SURFACE7_LOWER_BOUND 0x0b74 +#define RADEON_SURFACE7_UPPER_BOUND 0x0b78 +#define RADEON_SW_SEMAPHORE 0x013c + +#define RADEON_WAIT_UNTIL 0x1720 +# define RADEON_WAIT_CRTC_PFLIP (1 << 0) +# define RADEON_WAIT_2D_IDLE (1 << 14) +# define RADEON_WAIT_3D_IDLE (1 << 15) +# define RADEON_WAIT_2D_IDLECLEAN (1 << 16) +# define RADEON_WAIT_3D_IDLECLEAN (1 << 17) +# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) + +#define RADEON_RB3D_ZMASKOFFSET 0x3234 +#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c +# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) + +/* CP registers */ +#define RADEON_CP_ME_RAM_ADDR 0x07d4 +#define RADEON_CP_ME_RAM_RADDR 0x07d8 +#define RADEON_CP_ME_RAM_DATAH 0x07dc +#define RADEON_CP_ME_RAM_DATAL 0x07e0 + +#define RADEON_CP_RB_BASE 0x0700 +#define RADEON_CP_RB_CNTL 0x0704 +# define RADEON_BUF_SWAP_32BIT (2 << 16) +# define RADEON_RB_NO_UPDATE (1 << 27) +# define RADEON_RB_RPTR_WR_ENA (1 << 31) +#define RADEON_CP_RB_RPTR_ADDR 0x070c +#define RADEON_CP_RB_RPTR 0x0710 +#define RADEON_CP_RB_WPTR 0x0714 + +#define RADEON_CP_RB_WPTR_DELAY 0x0718 +# define RADEON_PRE_WRITE_TIMER_SHIFT 0 +# define RADEON_PRE_WRITE_LIMIT_SHIFT 23 + +#define RADEON_CP_IB_BASE 0x0738 + +#define RADEON_CP_CSQ_CNTL 0x0740 +# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) +# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) +# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) +# define RADEON_CSQ_PRIBM_INDDIS (2 << 28) +# define RADEON_CSQ_PRIPIO_INDBM (3 << 28) +# define RADEON_CSQ_PRIBM_INDBM (4 << 28) +# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) + +#define R300_CP_RESYNC_ADDR 0x0778 +#define R300_CP_RESYNC_DATA 0x077c + +#define RADEON_AIC_CNTL 0x01d0 +# define RADEON_PCIGART_TRANSLATE_EN (1 << 0) +# define RS400_MSI_REARM (1 << 3) +#define RADEON_AIC_STAT 0x01d4 +#define RADEON_AIC_PT_BASE 0x01d8 +#define RADEON_AIC_LO_ADDR 0x01dc +#define RADEON_AIC_HI_ADDR 0x01e0 +#define RADEON_AIC_TLB_ADDR 0x01e4 +#define RADEON_AIC_TLB_DATA 0x01e8 + +/* CP command packets */ +#define RADEON_CP_PACKET0 0x00000000 +# define RADEON_ONE_REG_WR (1 << 15) +#define RADEON_CP_PACKET1 0x40000000 +#define RADEON_CP_PACKET2 0x80000000 +#define RADEON_CP_PACKET3 0xC0000000 +# define RADEON_CP_NOP 0x00001000 +# define RADEON_CP_NEXT_CHAR 0x00001900 +# define RADEON_CP_PLY_NEXTSCAN 0x00001D00 +# define RADEON_CP_SET_SCISSORS 0x00001E00 + /* GEN_INDX_PRIM is unsupported starting with R300 */ +# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 +# define RADEON_WAIT_FOR_IDLE 0x00002600 +# define RADEON_3D_DRAW_VBUF 0x00002800 +# define RADEON_3D_DRAW_IMMD 0x00002900 +# define RADEON_3D_DRAW_INDX 0x00002A00 +# define RADEON_CP_LOAD_PALETTE 0x00002C00 +# define RADEON_3D_LOAD_VBPNTR 0x00002F00 +# define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000 +# define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100 +# define RADEON_3D_CLEAR_ZMASK 0x00003200 +# define RADEON_CP_INDX_BUFFER 0x00003300 +# define RADEON_CP_3D_DRAW_VBUF_2 0x00003400 +# define RADEON_CP_3D_DRAW_IMMD_2 0x00003500 +# define RADEON_CP_3D_DRAW_INDX_2 0x00003600 +# define RADEON_3D_CLEAR_HIZ 0x00003700 +# define RADEON_CP_3D_CLEAR_CMASK 0x00003802 +# define RADEON_CNTL_HOSTDATA_BLT 0x00009400 +# define RADEON_CNTL_PAINT_MULTI 0x00009A00 +# define RADEON_CNTL_BITBLT_MULTI 0x00009B00 +# define RADEON_CNTL_SET_SCISSORS 0xC0001E00 + +# define R600_IT_INDIRECT_BUFFER_END 0x00001700 +# define R600_IT_SET_PREDICATION 0x00002000 +# define R600_IT_REG_RMW 0x00002100 +# define R600_IT_COND_EXEC 0x00002200 +# define R600_IT_PRED_EXEC 0x00002300 +# define R600_IT_START_3D_CMDBUF 0x00002400 +# define R600_IT_DRAW_INDEX_2 0x00002700 +# define R600_IT_CONTEXT_CONTROL 0x00002800 +# define R600_IT_DRAW_INDEX_IMMD_BE 0x00002900 +# define R600_IT_INDEX_TYPE 0x00002A00 +# define R600_IT_DRAW_INDEX 0x00002B00 +# define R600_IT_DRAW_INDEX_AUTO 0x00002D00 +# define R600_IT_DRAW_INDEX_IMMD 0x00002E00 +# define R600_IT_NUM_INSTANCES 0x00002F00 +# define R600_IT_STRMOUT_BUFFER_UPDATE 0x00003400 +# define R600_IT_INDIRECT_BUFFER_MP 0x00003800 +# define R600_IT_MEM_SEMAPHORE 0x00003900 +# define R600_IT_MPEG_INDEX 0x00003A00 +# define R600_IT_WAIT_REG_MEM 0x00003C00 +# define R600_IT_MEM_WRITE 0x00003D00 +# define R600_IT_INDIRECT_BUFFER 0x00003200 +# define R600_IT_SURFACE_SYNC 0x00004300 +# define R600_CB0_DEST_BASE_ENA (1 << 6) +# define R600_TC_ACTION_ENA (1 << 23) +# define R600_VC_ACTION_ENA (1 << 24) +# define R600_CB_ACTION_ENA (1 << 25) +# define R600_DB_ACTION_ENA (1 << 26) +# define R600_SH_ACTION_ENA (1 << 27) +# define R600_SMX_ACTION_ENA (1 << 28) +# define R600_IT_ME_INITIALIZE 0x00004400 +# define R600_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) +# define R600_IT_COND_WRITE 0x00004500 +# define R600_IT_EVENT_WRITE 0x00004600 +# define R600_IT_EVENT_WRITE_EOP 0x00004700 +# define R600_IT_ONE_REG_WRITE 0x00005700 +# define R600_IT_SET_CONFIG_REG 0x00006800 +# define R600_SET_CONFIG_REG_OFFSET 0x00008000 +# define R600_SET_CONFIG_REG_END 0x0000ac00 +# define R600_IT_SET_CONTEXT_REG 0x00006900 +# define R600_SET_CONTEXT_REG_OFFSET 0x00028000 +# define R600_SET_CONTEXT_REG_END 0x00029000 +# define R600_IT_SET_ALU_CONST 0x00006A00 +# define R600_SET_ALU_CONST_OFFSET 0x00030000 +# define R600_SET_ALU_CONST_END 0x00032000 +# define R600_IT_SET_BOOL_CONST 0x00006B00 +# define R600_SET_BOOL_CONST_OFFSET 0x0003e380 +# define R600_SET_BOOL_CONST_END 0x00040000 +# define R600_IT_SET_LOOP_CONST 0x00006C00 +# define R600_SET_LOOP_CONST_OFFSET 0x0003e200 +# define R600_SET_LOOP_CONST_END 0x0003e380 +# define R600_IT_SET_RESOURCE 0x00006D00 +# define R600_SET_RESOURCE_OFFSET 0x00038000 +# define R600_SET_RESOURCE_END 0x0003c000 +# define R600_SQ_TEX_VTX_INVALID_TEXTURE 0x0 +# define R600_SQ_TEX_VTX_INVALID_BUFFER 0x1 +# define R600_SQ_TEX_VTX_VALID_TEXTURE 0x2 +# define R600_SQ_TEX_VTX_VALID_BUFFER 0x3 +# define R600_IT_SET_SAMPLER 0x00006E00 +# define R600_SET_SAMPLER_OFFSET 0x0003c000 +# define R600_SET_SAMPLER_END 0x0003cff0 +# define R600_IT_SET_CTL_CONST 0x00006F00 +# define R600_SET_CTL_CONST_OFFSET 0x0003cff0 +# define R600_SET_CTL_CONST_END 0x0003e200 +# define R600_IT_SURFACE_BASE_UPDATE 0x00007300 + +#define RADEON_CP_PACKET_MASK 0xC0000000 +#define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 +#define RADEON_CP_PACKET0_REG_MASK 0x000007ff +#define RADEON_CP_PACKET1_REG0_MASK 0x000007ff +#define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 + +#define RADEON_VTX_Z_PRESENT (1 << 31) +#define RADEON_VTX_PKCOLOR_PRESENT (1 << 3) + +#define RADEON_PRIM_TYPE_NONE (0 << 0) +#define RADEON_PRIM_TYPE_POINT (1 << 0) +#define RADEON_PRIM_TYPE_LINE (2 << 0) +#define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0) +#define RADEON_PRIM_TYPE_TRI_LIST (4 << 0) +#define RADEON_PRIM_TYPE_TRI_FAN (5 << 0) +#define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0) +#define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0) +#define RADEON_PRIM_TYPE_RECT_LIST (8 << 0) +#define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) +#define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) +#define RADEON_PRIM_TYPE_MASK 0xf +#define RADEON_PRIM_WALK_IND (1 << 4) +#define RADEON_PRIM_WALK_LIST (2 << 4) +#define RADEON_PRIM_WALK_RING (3 << 4) +#define RADEON_COLOR_ORDER_BGRA (0 << 6) +#define RADEON_COLOR_ORDER_RGBA (1 << 6) +#define RADEON_MAOS_ENABLE (1 << 7) +#define RADEON_VTX_FMT_R128_MODE (0 << 8) +#define RADEON_VTX_FMT_RADEON_MODE (1 << 8) +#define RADEON_NUM_VERTICES_SHIFT 16 + +#define RADEON_COLOR_FORMAT_CI8 2 +#define RADEON_COLOR_FORMAT_ARGB1555 3 +#define RADEON_COLOR_FORMAT_RGB565 4 +#define RADEON_COLOR_FORMAT_ARGB8888 6 +#define RADEON_COLOR_FORMAT_RGB332 7 +#define RADEON_COLOR_FORMAT_RGB8 9 +#define RADEON_COLOR_FORMAT_ARGB4444 15 + +#define RADEON_TXFORMAT_I8 0 +#define RADEON_TXFORMAT_AI88 1 +#define RADEON_TXFORMAT_RGB332 2 +#define RADEON_TXFORMAT_ARGB1555 3 +#define RADEON_TXFORMAT_RGB565 4 +#define RADEON_TXFORMAT_ARGB4444 5 +#define RADEON_TXFORMAT_ARGB8888 6 +#define RADEON_TXFORMAT_RGBA8888 7 +#define RADEON_TXFORMAT_Y8 8 +#define RADEON_TXFORMAT_VYUY422 10 +#define RADEON_TXFORMAT_YVYU422 11 +#define RADEON_TXFORMAT_DXT1 12 +#define RADEON_TXFORMAT_DXT23 14 +#define RADEON_TXFORMAT_DXT45 15 + +#define R200_PP_TXCBLEND_0 0x2f00 +#define R200_PP_TXCBLEND_1 0x2f10 +#define R200_PP_TXCBLEND_2 0x2f20 +#define R200_PP_TXCBLEND_3 0x2f30 +#define R200_PP_TXCBLEND_4 0x2f40 +#define R200_PP_TXCBLEND_5 0x2f50 +#define R200_PP_TXCBLEND_6 0x2f60 +#define R200_PP_TXCBLEND_7 0x2f70 +#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_SE_VTX_FMT_0 0x2088 +#define R200_SE_VAP_CNTL 0x2080 +#define R200_SE_TCL_MATRIX_SEL_0 0x2230 +#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 +#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 +#define R200_PP_TXFILTER_5 0x2ca0 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXOFFSET_5 0x2d78 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_0 0x2d00 + +#define R200_PP_CUBIC_FACES_0 0x2c18 +#define R200_PP_CUBIC_FACES_1 0x2c38 +#define R200_PP_CUBIC_FACES_2 0x2c58 +#define R200_PP_CUBIC_FACES_3 0x2c78 +#define R200_PP_CUBIC_FACES_4 0x2c98 +#define R200_PP_CUBIC_FACES_5 0x2cb8 +#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 +#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 +#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c +#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 +#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 +#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c +#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 +#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 +#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 +#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c +#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 +#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 +#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c +#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 +#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 +#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c +#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 +#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 +#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 +#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c +#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 +#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 +#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c +#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 +#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 +#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c +#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 +#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 +#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 +#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c + +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_SE_VTE_CNTL 0x20b0 +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +#define R200_PP_TAM_DEBUG3 0x2d9c +#define R200_PP_CNTL_X 0x2cc4 +#define R200_SE_VAP_CNTL_STATUS 0x2140 +#define R200_RE_SCISSOR_TL_0 0x1cd8 +#define R200_RE_SCISSOR_TL_1 0x1ce0 +#define R200_RE_SCISSOR_TL_2 0x1ce8 +#define R200_RB3D_DEPTHXY_OFFSET 0x1d60 +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_SE_VTX_STATE_CNTL 0x2180 +#define R200_RE_POINTSIZE 0x2648 +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 + +#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ +#define RADEON_PP_TEX_SIZE_1 0x1d0c +#define RADEON_PP_TEX_SIZE_2 0x1d14 + +#define RADEON_PP_CUBIC_FACES_0 0x1d24 +#define RADEON_PP_CUBIC_FACES_1 0x1d28 +#define RADEON_PP_CUBIC_FACES_2 0x1d2c +#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ +#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 +#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 + +#define RADEON_SE_TCL_STATE_FLUSH 0x2284 + +#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 +#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 +#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 +#define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100 +#define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200 +#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001 +#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002 +#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b +#define R200_3D_DRAW_IMMD_2 0xC0003500 +#define R200_SE_VTX_FMT_1 0x208c +#define R200_RE_CNTL 0x1c50 + +#define R200_RB3D_BLENDCOLOR 0x3218 + +#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4 + +#define R200_PP_TRI_PERF 0x2cf8 + +#define R200_PP_AFS_0 0x2f80 +#define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */ + +#define R200_VAP_PVS_CNTL_1 0x22D0 + +#define RADEON_CRTC_CRNT_FRAME 0x0214 +#define RADEON_CRTC2_CRNT_FRAME 0x0314 + +#define R500_D1CRTC_STATUS 0x609c +#define R500_D2CRTC_STATUS 0x689c +#define R500_CRTC_V_BLANK (1<<0) + +#define R500_D1CRTC_FRAME_COUNT 0x60a4 +#define R500_D2CRTC_FRAME_COUNT 0x68a4 + +#define R500_D1MODE_V_COUNTER 0x6530 +#define R500_D2MODE_V_COUNTER 0x6d30 + +#define R500_D1MODE_VBLANK_STATUS 0x6534 +#define R500_D2MODE_VBLANK_STATUS 0x6d34 +#define R500_VBLANK_OCCURED (1<<0) +#define R500_VBLANK_ACK (1<<4) +#define R500_VBLANK_STAT (1<<12) +#define R500_VBLANK_INT (1<<16) + +#define R500_DxMODE_INT_MASK 0x6540 +#define R500_D1MODE_INT_MASK (1<<0) +#define R500_D2MODE_INT_MASK (1<<8) + +#define R500_DISP_INTERRUPT_STATUS 0x7edc +#define R500_D1_VBLANK_INTERRUPT (1 << 4) +#define R500_D2_VBLANK_INTERRUPT (1 << 5) + +/* R6xx/R7xx registers */ +#define R600_MC_VM_FB_LOCATION 0x2180 +#define R600_MC_VM_AGP_TOP 0x2184 +#define R600_MC_VM_AGP_BOT 0x2188 +#define R600_MC_VM_AGP_BASE 0x218c +#define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190 +#define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194 +#define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198 + +#define R700_MC_VM_FB_LOCATION 0x2024 +#define R700_MC_VM_AGP_TOP 0x2028 +#define R700_MC_VM_AGP_BOT 0x202c +#define R700_MC_VM_AGP_BASE 0x2030 +#define R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 +#define R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 +#define R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203c + +#define R600_MCD_RD_A_CNTL 0x219c +#define R600_MCD_RD_B_CNTL 0x21a0 + +#define R600_MCD_WR_A_CNTL 0x21a4 +#define R600_MCD_WR_B_CNTL 0x21a8 + +#define R600_MCD_RD_SYS_CNTL 0x2200 +#define R600_MCD_WR_SYS_CNTL 0x2214 + +#define R600_MCD_RD_GFX_CNTL 0x21fc +#define R600_MCD_RD_HDP_CNTL 0x2204 +#define R600_MCD_RD_PDMA_CNTL 0x2208 +#define R600_MCD_RD_SEM_CNTL 0x220c +#define R600_MCD_WR_GFX_CNTL 0x2210 +#define R600_MCD_WR_HDP_CNTL 0x2218 +#define R600_MCD_WR_PDMA_CNTL 0x221c +#define R600_MCD_WR_SEM_CNTL 0x2220 + +# define R600_MCD_L1_TLB (1 << 0) +# define R600_MCD_L1_FRAG_PROC (1 << 1) +# define R600_MCD_L1_STRICT_ORDERING (1 << 2) + +# define R600_MCD_SYSTEM_ACCESS_MODE_MASK (3 << 6) +# define R600_MCD_SYSTEM_ACCESS_MODE_PA_ONLY (0 << 6) +# define R600_MCD_SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 6) +# define R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS (2 << 6) +# define R600_MCD_SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 6) + +# define R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 8) +# define R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 8) + +# define R600_MCD_SEMAPHORE_MODE (1 << 10) +# define R600_MCD_WAIT_L2_QUERY (1 << 11) +# define R600_MCD_EFFECTIVE_L1_TLB_SIZE(x) ((x) << 12) +# define R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) + +#define R700_MC_VM_MD_L1_TLB0_CNTL 0x2654 +#define R700_MC_VM_MD_L1_TLB1_CNTL 0x2658 +#define R700_MC_VM_MD_L1_TLB2_CNTL 0x265c + +#define R700_MC_VM_MB_L1_TLB0_CNTL 0x2234 +#define R700_MC_VM_MB_L1_TLB1_CNTL 0x2238 +#define R700_MC_VM_MB_L1_TLB2_CNTL 0x223c +#define R700_MC_VM_MB_L1_TLB3_CNTL 0x2240 + +# define R700_ENABLE_L1_TLB (1 << 0) +# define R700_ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +# define R700_SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) +# define R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) +# define R700_EFFECTIVE_L1_TLB_SIZE(x) ((x) << 15) +# define R700_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 18) + +#define R700_MC_ARB_RAMCFG 0x2760 +# define R700_NOOFBANK_SHIFT 0 +# define R700_NOOFBANK_MASK 0x3 +# define R700_NOOFRANK_SHIFT 2 +# define R700_NOOFRANK_MASK 0x1 +# define R700_NOOFROWS_SHIFT 3 +# define R700_NOOFROWS_MASK 0x7 +# define R700_NOOFCOLS_SHIFT 6 +# define R700_NOOFCOLS_MASK 0x3 +# define R700_CHANSIZE_SHIFT 8 +# define R700_CHANSIZE_MASK 0x1 +# define R700_BURSTLENGTH_SHIFT 9 +# define R700_BURSTLENGTH_MASK 0x1 +#define R600_RAMCFG 0x2408 +# define R600_NOOFBANK_SHIFT 0 +# define R600_NOOFBANK_MASK 0x1 +# define R600_NOOFRANK_SHIFT 1 +# define R600_NOOFRANK_MASK 0x1 +# define R600_NOOFROWS_SHIFT 2 +# define R600_NOOFROWS_MASK 0x7 +# define R600_NOOFCOLS_SHIFT 5 +# define R600_NOOFCOLS_MASK 0x3 +# define R600_CHANSIZE_SHIFT 7 +# define R600_CHANSIZE_MASK 0x1 +# define R600_BURSTLENGTH_SHIFT 8 +# define R600_BURSTLENGTH_MASK 0x1 + +#define R600_VM_L2_CNTL 0x1400 +# define R600_VM_L2_CACHE_EN (1 << 0) +# define R600_VM_L2_FRAG_PROC (1 << 1) +# define R600_VM_ENABLE_PTE_CACHE_LRU_W (1 << 9) +# define R600_VM_L2_CNTL_QUEUE_SIZE(x) ((x) << 13) +# define R700_VM_L2_CNTL_QUEUE_SIZE(x) ((x) << 14) + +#define R600_VM_L2_CNTL2 0x1404 +# define R600_VM_L2_CNTL2_INVALIDATE_ALL_L1_TLBS (1 << 0) +# define R600_VM_L2_CNTL2_INVALIDATE_L2_CACHE (1 << 1) +#define R600_VM_L2_CNTL3 0x1408 +# define R600_VM_L2_CNTL3_BANK_SELECT_0(x) ((x) << 0) +# define R600_VM_L2_CNTL3_BANK_SELECT_1(x) ((x) << 5) +# define R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(x) ((x) << 10) +# define R700_VM_L2_CNTL3_BANK_SELECT(x) ((x) << 0) +# define R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(x) ((x) << 6) + +#define R600_VM_L2_STATUS 0x140c + +#define R600_VM_CONTEXT0_CNTL 0x1410 +# define R600_VM_ENABLE_CONTEXT (1 << 0) +# define R600_VM_PAGE_TABLE_DEPTH_FLAT (0 << 1) + +#define R600_VM_CONTEXT0_CNTL2 0x1430 +#define R600_VM_CONTEXT0_REQUEST_RESPONSE 0x1470 +#define R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR 0x1490 +#define R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR 0x14b0 +#define R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x1574 +#define R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x1594 +#define R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x15b4 + +#define R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153c +#define R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155c +#define R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157c + +#define R600_HDP_HOST_PATH_CNTL 0x2c00 + +#define R600_GRBM_CNTL 0x8000 +# define R600_GRBM_READ_TIMEOUT(x) ((x) << 0) + +#define R600_GRBM_STATUS 0x8010 +# define R600_CMDFIFO_AVAIL_MASK 0x1f +# define R700_CMDFIFO_AVAIL_MASK 0xf +# define R600_GUI_ACTIVE (1 << 31) +#define R600_GRBM_STATUS2 0x8014 +#define R600_GRBM_SOFT_RESET 0x8020 +# define R600_SOFT_RESET_CP (1 << 0) +#define R600_WAIT_UNTIL 0x8040 + +#define R600_CP_SEM_WAIT_TIMER 0x85bc +#define R600_CP_ME_CNTL 0x86d8 +# define R600_CP_ME_HALT (1 << 28) +#define R600_CP_QUEUE_THRESHOLDS 0x8760 +# define R600_ROQ_IB1_START(x) ((x) << 0) +# define R600_ROQ_IB2_START(x) ((x) << 8) +#define R600_CP_MEQ_THRESHOLDS 0x8764 +# define R700_STQ_SPLIT(x) ((x) << 0) +# define R600_MEQ_END(x) ((x) << 16) +# define R600_ROQ_END(x) ((x) << 24) +#define R600_CP_PERFMON_CNTL 0x87fc +#define R600_CP_RB_BASE 0xc100 +#define R600_CP_RB_CNTL 0xc104 +# define R600_RB_BUFSZ(x) ((x) << 0) +# define R600_RB_BLKSZ(x) ((x) << 8) +# define R600_BUF_SWAP_32BIT (2 << 16) +# define R600_RB_NO_UPDATE (1 << 27) +# define R600_RB_RPTR_WR_ENA (1 << 31) +#define R600_CP_RB_RPTR_WR 0xc108 +#define R600_CP_RB_RPTR_ADDR 0xc10c +#define R600_CP_RB_RPTR_ADDR_HI 0xc110 +#define R600_CP_RB_WPTR 0xc114 +#define R600_CP_RB_WPTR_ADDR 0xc118 +#define R600_CP_RB_WPTR_ADDR_HI 0xc11c +#define R600_CP_RB_RPTR 0x8700 +#define R600_CP_RB_WPTR_DELAY 0x8704 +#define R600_CP_PFP_UCODE_ADDR 0xc150 +#define R600_CP_PFP_UCODE_DATA 0xc154 +#define R600_CP_ME_RAM_RADDR 0xc158 +#define R600_CP_ME_RAM_WADDR 0xc15c +#define R600_CP_ME_RAM_DATA 0xc160 +#define R600_CP_DEBUG 0xc1fc + +#define R600_PA_CL_ENHANCE 0x8a14 +# define R600_CLIP_VTX_REORDER_ENA (1 << 0) +# define R600_NUM_CLIP_SEQ(x) ((x) << 1) +#define R600_PA_SC_LINE_STIPPLE_STATE 0x8b10 +#define R600_PA_SC_MULTI_CHIP_CNTL 0x8b20 +#define R700_PA_SC_FORCE_EOV_MAX_CNTS 0x8b24 +# define R700_FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +# define R700_FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) +#define R600_PA_SC_AA_SAMPLE_LOCS_2S 0x8b40 +#define R600_PA_SC_AA_SAMPLE_LOCS_4S 0x8b44 +#define R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0 0x8b48 +#define R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1 0x8b4c +# define R600_S0_X(x) ((x) << 0) +# define R600_S0_Y(x) ((x) << 4) +# define R600_S1_X(x) ((x) << 8) +# define R600_S1_Y(x) ((x) << 12) +# define R600_S2_X(x) ((x) << 16) +# define R600_S2_Y(x) ((x) << 20) +# define R600_S3_X(x) ((x) << 24) +# define R600_S3_Y(x) ((x) << 28) +# define R600_S4_X(x) ((x) << 0) +# define R600_S4_Y(x) ((x) << 4) +# define R600_S5_X(x) ((x) << 8) +# define R600_S5_Y(x) ((x) << 12) +# define R600_S6_X(x) ((x) << 16) +# define R600_S6_Y(x) ((x) << 20) +# define R600_S7_X(x) ((x) << 24) +# define R600_S7_Y(x) ((x) << 28) +#define R600_PA_SC_FIFO_SIZE 0x8bd0 +# define R600_SC_PRIM_FIFO_SIZE(x) ((x) << 0) +# define R600_SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 8) +# define R600_SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 16) +#define R700_PA_SC_FIFO_SIZE_R7XX 0x8bcc +# define R700_SC_PRIM_FIFO_SIZE(x) ((x) << 0) +# define R700_SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) +# define R700_SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) +#define R600_PA_SC_ENHANCE 0x8bf0 +# define R600_FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +# define R600_FORCE_EOV_MAX_TILE_CNT(x) ((x) << 12) +#define R600_PA_SC_CLIPRECT_RULE 0x2820c +#define R700_PA_SC_EDGERULE 0x28230 +#define R600_PA_SC_LINE_STIPPLE 0x28a0c +#define R600_PA_SC_MODE_CNTL 0x28a4c +#define R600_PA_SC_AA_CONFIG 0x28c04 + +#define R600_SX_EXPORT_BUFFER_SIZES 0x900c +# define R600_COLOR_BUFFER_SIZE(x) ((x) << 0) +# define R600_POSITION_BUFFER_SIZE(x) ((x) << 8) +# define R600_SMX_BUFFER_SIZE(x) ((x) << 16) +#define R600_SX_DEBUG_1 0x9054 +# define R600_SMX_EVENT_RELEASE (1 << 0) +# define R600_ENABLE_NEW_SMX_ADDRESS (1 << 16) +#define R700_SX_DEBUG_1 0x9058 +# define R700_ENABLE_NEW_SMX_ADDRESS (1 << 16) +#define R600_SX_MISC 0x28350 + +#define R600_DB_DEBUG 0x9830 +# define R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31) +#define R600_DB_WATERMARKS 0x9838 +# define R600_DEPTH_FREE(x) ((x) << 0) +# define R600_DEPTH_FLUSH(x) ((x) << 5) +# define R600_DEPTH_PENDING_FREE(x) ((x) << 15) +# define R600_DEPTH_CACHELINE_FREE(x) ((x) << 20) +#define R700_DB_DEBUG3 0x98b0 +# define R700_DB_CLK_OFF_DELAY(x) ((x) << 11) +#define RV700_DB_DEBUG4 0x9b8c +# define RV700_DISABLE_TILE_COVERED_FOR_PS_ITER (1 << 6) + +#define R600_VGT_CACHE_INVALIDATION 0x88c4 +# define R600_CACHE_INVALIDATION(x) ((x) << 0) +# define R600_VC_ONLY 0 +# define R600_TC_ONLY 1 +# define R600_VC_AND_TC 2 +# define R700_AUTO_INVLD_EN(x) ((x) << 6) +# define R700_NO_AUTO 0 +# define R700_ES_AUTO 1 +# define R700_GS_AUTO 2 +# define R700_ES_AND_GS_AUTO 3 +#define R600_VGT_GS_PER_ES 0x88c8 +#define R600_VGT_ES_PER_GS 0x88cc +#define R600_VGT_GS_PER_VS 0x88e8 +#define R600_VGT_GS_VERTEX_REUSE 0x88d4 +#define R600_VGT_NUM_INSTANCES 0x8974 +#define R600_VGT_STRMOUT_EN 0x28ab0 +#define R600_VGT_EVENT_INITIATOR 0x28a90 +# define R600_CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) +#define R600_VGT_VERTEX_REUSE_BLOCK_CNTL 0x28c58 +# define R600_VTX_REUSE_DEPTH_MASK 0xff +#define R600_VGT_OUT_DEALLOC_CNTL 0x28c5c +# define R600_DEALLOC_DIST_MASK 0x7f + +#define R600_CB_COLOR0_BASE 0x28040 +#define R600_CB_COLOR1_BASE 0x28044 +#define R600_CB_COLOR2_BASE 0x28048 +#define R600_CB_COLOR3_BASE 0x2804c +#define R600_CB_COLOR4_BASE 0x28050 +#define R600_CB_COLOR5_BASE 0x28054 +#define R600_CB_COLOR6_BASE 0x28058 +#define R600_CB_COLOR7_BASE 0x2805c +#define R600_CB_COLOR7_FRAG 0x280fc + +#define R600_CB_COLOR0_SIZE 0x28060 +#define R600_CB_COLOR0_VIEW 0x28080 +#define R600_CB_COLOR0_INFO 0x280a0 +#define R600_CB_COLOR0_TILE 0x280c0 +#define R600_CB_COLOR0_FRAG 0x280e0 +#define R600_CB_COLOR0_MASK 0x28100 + +#define AVIVO_D1MODE_VLINE_START_END 0x6538 +#define AVIVO_D2MODE_VLINE_START_END 0x6d38 +#define R600_CP_COHER_BASE 0x85f8 +#define R600_DB_DEPTH_BASE 0x2800c +#define R600_SQ_PGM_START_FS 0x28894 +#define R600_SQ_PGM_START_ES 0x28880 +#define R600_SQ_PGM_START_VS 0x28858 +#define R600_SQ_PGM_RESOURCES_VS 0x28868 +#define R600_SQ_PGM_CF_OFFSET_VS 0x288d0 +#define R600_SQ_PGM_START_GS 0x2886c +#define R600_SQ_PGM_START_PS 0x28840 +#define R600_SQ_PGM_RESOURCES_PS 0x28850 +#define R600_SQ_PGM_EXPORTS_PS 0x28854 +#define R600_SQ_PGM_CF_OFFSET_PS 0x288cc +#define R600_VGT_DMA_BASE 0x287e8 +#define R600_VGT_DMA_BASE_HI 0x287e4 +#define R600_VGT_STRMOUT_BASE_OFFSET_0 0x28b10 +#define R600_VGT_STRMOUT_BASE_OFFSET_1 0x28b14 +#define R600_VGT_STRMOUT_BASE_OFFSET_2 0x28b18 +#define R600_VGT_STRMOUT_BASE_OFFSET_3 0x28b1c +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_0 0x28b44 +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_1 0x28b48 +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_2 0x28b4c +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_3 0x28b50 +#define R600_VGT_STRMOUT_BUFFER_BASE_0 0x28ad8 +#define R600_VGT_STRMOUT_BUFFER_BASE_1 0x28ae8 +#define R600_VGT_STRMOUT_BUFFER_BASE_2 0x28af8 +#define R600_VGT_STRMOUT_BUFFER_BASE_3 0x28b08 +#define R600_VGT_STRMOUT_BUFFER_OFFSET_0 0x28adc +#define R600_VGT_STRMOUT_BUFFER_OFFSET_1 0x28aec +#define R600_VGT_STRMOUT_BUFFER_OFFSET_2 0x28afc +#define R600_VGT_STRMOUT_BUFFER_OFFSET_3 0x28b0c + +#define R600_VGT_PRIMITIVE_TYPE 0x8958 + +#define R600_PA_SC_SCREEN_SCISSOR_TL 0x28030 +#define R600_PA_SC_GENERIC_SCISSOR_TL 0x28240 +#define R600_PA_SC_WINDOW_SCISSOR_TL 0x28204 + +#define R600_TC_CNTL 0x9608 +# define R600_TC_L2_SIZE(x) ((x) << 5) +# define R600_L2_DISABLE_LATE_HIT (1 << 9) + +#define R600_ARB_POP 0x2418 +# define R600_ENABLE_TC128 (1 << 30) +#define R600_ARB_GDEC_RD_CNTL 0x246c + +#define R600_TA_CNTL_AUX 0x9508 +# define R600_DISABLE_CUBE_WRAP (1 << 0) +# define R600_DISABLE_CUBE_ANISO (1 << 1) +# define R700_GETLOD_SELECT(x) ((x) << 2) +# define R600_SYNC_GRADIENT (1 << 24) +# define R600_SYNC_WALKER (1 << 25) +# define R600_SYNC_ALIGNER (1 << 26) +# define R600_BILINEAR_PRECISION_6_BIT (0 << 31) +# define R600_BILINEAR_PRECISION_8_BIT (1 << 31) + +#define R700_TCP_CNTL 0x9610 + +#define R600_SMX_DC_CTL0 0xa020 +# define R700_USE_HASH_FUNCTION (1 << 0) +# define R700_CACHE_DEPTH(x) ((x) << 1) +# define R700_FLUSH_ALL_ON_EVENT (1 << 10) +# define R700_STALL_ON_EVENT (1 << 11) +#define R700_SMX_EVENT_CTL 0xa02c +# define R700_ES_FLUSH_CTL(x) ((x) << 0) +# define R700_GS_FLUSH_CTL(x) ((x) << 3) +# define R700_ACK_FLUSH_CTL(x) ((x) << 6) +# define R700_SYNC_FLUSH_CTL (1 << 8) + +#define R600_SQ_CONFIG 0x8c00 +# define R600_VC_ENABLE (1 << 0) +# define R600_EXPORT_SRC_C (1 << 1) +# define R600_DX9_CONSTS (1 << 2) +# define R600_ALU_INST_PREFER_VECTOR (1 << 3) +# define R600_DX10_CLAMP (1 << 4) +# define R600_CLAUSE_SEQ_PRIO(x) ((x) << 8) +# define R600_PS_PRIO(x) ((x) << 24) +# define R600_VS_PRIO(x) ((x) << 26) +# define R600_GS_PRIO(x) ((x) << 28) +# define R600_ES_PRIO(x) ((x) << 30) +#define R600_SQ_GPR_RESOURCE_MGMT_1 0x8c04 +# define R600_NUM_PS_GPRS(x) ((x) << 0) +# define R600_NUM_VS_GPRS(x) ((x) << 16) +# define R700_DYN_GPR_ENABLE (1 << 27) +# define R600_NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) +#define R600_SQ_GPR_RESOURCE_MGMT_2 0x8c08 +# define R600_NUM_GS_GPRS(x) ((x) << 0) +# define R600_NUM_ES_GPRS(x) ((x) << 16) +#define R600_SQ_THREAD_RESOURCE_MGMT 0x8c0c +# define R600_NUM_PS_THREADS(x) ((x) << 0) +# define R600_NUM_VS_THREADS(x) ((x) << 8) +# define R600_NUM_GS_THREADS(x) ((x) << 16) +# define R600_NUM_ES_THREADS(x) ((x) << 24) +#define R600_SQ_STACK_RESOURCE_MGMT_1 0x8c10 +# define R600_NUM_PS_STACK_ENTRIES(x) ((x) << 0) +# define R600_NUM_VS_STACK_ENTRIES(x) ((x) << 16) +#define R600_SQ_STACK_RESOURCE_MGMT_2 0x8c14 +# define R600_NUM_GS_STACK_ENTRIES(x) ((x) << 0) +# define R600_NUM_ES_STACK_ENTRIES(x) ((x) << 16) +#define R600_SQ_MS_FIFO_SIZES 0x8cf0 +# define R600_CACHE_FIFO_SIZE(x) ((x) << 0) +# define R600_FETCH_FIFO_HIWATER(x) ((x) << 8) +# define R600_DONE_FIFO_HIWATER(x) ((x) << 16) +# define R600_ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_0 0x8db0 +# define R700_SIMDA_RING0(x) ((x) << 0) +# define R700_SIMDA_RING1(x) ((x) << 8) +# define R700_SIMDB_RING0(x) ((x) << 16) +# define R700_SIMDB_RING1(x) ((x) << 24) +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_1 0x8db4 +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_2 0x8db8 +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_3 0x8dbc +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_4 0x8dc0 +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_5 0x8dc4 +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_6 0x8dc8 +#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_7 0x8dcc + +#define R600_SPI_PS_IN_CONTROL_0 0x286cc +# define R600_NUM_INTERP(x) ((x) << 0) +# define R600_POSITION_ENA (1 << 8) +# define R600_POSITION_CENTROID (1 << 9) +# define R600_POSITION_ADDR(x) ((x) << 10) +# define R600_PARAM_GEN(x) ((x) << 15) +# define R600_PARAM_GEN_ADDR(x) ((x) << 19) +# define R600_BARYC_SAMPLE_CNTL(x) ((x) << 26) +# define R600_PERSP_GRADIENT_ENA (1 << 28) +# define R600_LINEAR_GRADIENT_ENA (1 << 29) +# define R600_POSITION_SAMPLE (1 << 30) +# define R600_BARYC_AT_SAMPLE_ENA (1 << 31) +#define R600_SPI_PS_IN_CONTROL_1 0x286d0 +# define R600_GEN_INDEX_PIX (1 << 0) +# define R600_GEN_INDEX_PIX_ADDR(x) ((x) << 1) +# define R600_FRONT_FACE_ENA (1 << 8) +# define R600_FRONT_FACE_CHAN(x) ((x) << 9) +# define R600_FRONT_FACE_ALL_BITS (1 << 11) +# define R600_FRONT_FACE_ADDR(x) ((x) << 12) +# define R600_FOG_ADDR(x) ((x) << 17) +# define R600_FIXED_PT_POSITION_ENA (1 << 24) +# define R600_FIXED_PT_POSITION_ADDR(x) ((x) << 25) +# define R700_POSITION_ULC (1 << 30) +#define R600_SPI_INPUT_Z 0x286d8 + +#define R600_SPI_CONFIG_CNTL 0x9100 +# define R600_GPR_WRITE_PRIORITY(x) ((x) << 0) +# define R600_DISABLE_INTERP_1 (1 << 5) +#define R600_SPI_CONFIG_CNTL_1 0x913c +# define R600_VTX_DONE_DELAY(x) ((x) << 0) +# define R600_INTERP_ONE_PRIM_PER_ROW (1 << 4) + +#define R600_GB_TILING_CONFIG 0x98f0 +# define R600_PIPE_TILING(x) ((x) << 1) +# define R600_BANK_TILING(x) ((x) << 4) +# define R600_GROUP_SIZE(x) ((x) << 6) +# define R600_ROW_TILING(x) ((x) << 8) +# define R600_BANK_SWAPS(x) ((x) << 11) +# define R600_SAMPLE_SPLIT(x) ((x) << 14) +# define R600_BACKEND_MAP(x) ((x) << 16) +#define R600_DCP_TILING_CONFIG 0x6ca0 +#define R600_HDP_TILING_CONFIG 0x2f3c + +#define R600_CC_RB_BACKEND_DISABLE 0x98f4 +#define R700_CC_SYS_RB_BACKEND_DISABLE 0x3f88 +# define R600_BACKEND_DISABLE(x) ((x) << 16) + +#define R600_CC_GC_SHADER_PIPE_CONFIG 0x8950 +#define R600_GC_USER_SHADER_PIPE_CONFIG 0x8954 +# define R600_INACTIVE_QD_PIPES(x) ((x) << 8) +# define R600_INACTIVE_QD_PIPES_MASK (0xff << 8) +# define R600_INACTIVE_SIMDS(x) ((x) << 16) +# define R600_INACTIVE_SIMDS_MASK (0xff << 16) + +#define R700_CGTS_SYS_TCC_DISABLE 0x3f90 +#define R700_CGTS_USER_SYS_TCC_DISABLE 0x3f94 +#define R700_CGTS_TCC_DISABLE 0x9148 +#define R700_CGTS_USER_TCC_DISABLE 0x914c + +/* Constants */ +#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ + +#define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0 +#define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1 +#define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2 +#define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3 +#define RADEON_LAST_DISPATCH 1 + +#define R600_LAST_FRAME_REG R600_SCRATCH_REG0 +#define R600_LAST_DISPATCH_REG R600_SCRATCH_REG1 +#define R600_LAST_CLEAR_REG R600_SCRATCH_REG2 +#define R600_LAST_SWI_REG R600_SCRATCH_REG3 + +#define RADEON_MAX_VB_AGE 0x7fffffff +#define RADEON_MAX_VB_VERTS (0xffff) + +#define RADEON_RING_HIGH_MARK 128 + +#define RADEON_PCIGART_TABLE_SIZE (32*1024) + +#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) +#define RADEON_WRITE(reg, val) \ +do { \ + if (reg < 0x10000) { \ + DRM_WRITE32(dev_priv->mmio, (reg), (val)); \ + } else { \ + DRM_WRITE32(dev_priv->mmio, RADEON_MM_INDEX, (reg)); \ + DRM_WRITE32(dev_priv->mmio, RADEON_MM_DATA, (val)); \ + } \ +} while (0) +#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) +#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) + +#define RADEON_WRITE_PLL(addr, val) \ +do { \ + RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, \ + ((addr) & 0x1f) | RADEON_PLL_WR_EN ); \ + RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val)); \ +} while (0) + +#define RADEON_WRITE_PCIE(addr, val) \ +do { \ + RADEON_WRITE8(RADEON_PCIE_INDEX, \ + ((addr) & 0xff)); \ + RADEON_WRITE(RADEON_PCIE_DATA, (val)); \ +} while (0) + +#define R500_WRITE_MCIND(addr, val) \ +do { \ + RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff)); \ + RADEON_WRITE(R520_MC_IND_DATA, (val)); \ + RADEON_WRITE(R520_MC_IND_INDEX, 0); \ +} while (0) + +#define RS480_WRITE_MCIND(addr, val) \ +do { \ + RADEON_WRITE(RS480_NB_MC_INDEX, \ + ((addr) & 0xff) | RS480_NB_MC_IND_WR_EN); \ + RADEON_WRITE(RS480_NB_MC_DATA, (val)); \ + RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); \ +} while (0) + +#define RS690_WRITE_MCIND(addr, val) \ +do { \ + RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK)); \ + RADEON_WRITE(RS690_MC_DATA, val); \ + RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); \ +} while (0) + +#define RS600_WRITE_MCIND(addr, val) \ +do { \ + RADEON_WRITE(RS600_MC_INDEX, RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 | ((addr) & RS600_MC_ADDR_MASK)); \ + RADEON_WRITE(RS600_MC_DATA, val); \ +} while (0) + +#define IGP_WRITE_MCIND(addr, val) \ +do { \ + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || \ + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) \ + RS690_WRITE_MCIND(addr, val); \ + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) \ + RS600_WRITE_MCIND(addr, val); \ + else \ + RS480_WRITE_MCIND(addr, val); \ +} while (0) + +#define CP_PACKET0( reg, n ) \ + (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) +#define CP_PACKET0_TABLE( reg, n ) \ + (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2)) +#define CP_PACKET1( reg0, reg1 ) \ + (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2)) +#define CP_PACKET2() \ + (RADEON_CP_PACKET2) +#define CP_PACKET3( pkt, n ) \ + (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) + +/* ================================================================ + * Engine control helper macros + */ + +#define RADEON_WAIT_UNTIL_2D_IDLE() do { \ + OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ + OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ + RADEON_WAIT_HOST_IDLECLEAN) ); \ +} while (0) + +#define RADEON_WAIT_UNTIL_3D_IDLE() do { \ + OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ + OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \ + RADEON_WAIT_HOST_IDLECLEAN) ); \ +} while (0) + +#define RADEON_WAIT_UNTIL_IDLE() do { \ + OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ + OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ + RADEON_WAIT_3D_IDLECLEAN | \ + RADEON_WAIT_HOST_IDLECLEAN) ); \ +} while (0) + +#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \ + OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ + OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \ +} while (0) + +#define RADEON_FLUSH_CACHE() do { \ + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH); \ + } else { \ + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_RB3D_DC_FLUSH); \ + } \ +} while (0) + +#define RADEON_PURGE_CACHE() do { \ + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE); \ + } else { \ + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); \ + } \ +} while (0) + +#define RADEON_FLUSH_ZCACHE() do { \ + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ + OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH); \ + } else { \ + OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_ZC_FLUSH); \ + } \ +} while (0) + +#define RADEON_PURGE_ZCACHE() do { \ + if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ + OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE); \ + } else { \ + OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE); \ + } \ +} while (0) + +/* ================================================================ + * Misc helper macros + */ + +/* Perfbox functionality only. + */ +#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ +do { \ + if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \ + u32 head = GET_RING_HEAD( dev_priv ); \ + if (head == dev_priv->ring.tail) \ + dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \ + } \ +} while (0) + +#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ +do { \ + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;\ + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \ + if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ + int __ret; \ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) \ + __ret = r600_do_cp_idle(dev_priv); \ + else \ + __ret = radeon_do_cp_idle(dev_priv); \ + if ( __ret ) return __ret; \ + sarea_priv->last_dispatch = 0; \ + radeon_freelist_reset( dev ); \ + } \ +} while (0) + +#define RADEON_DISPATCH_AGE( age ) do { \ + OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \ + OUT_RING( age ); \ +} while (0) + +#define RADEON_FRAME_AGE( age ) do { \ + OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \ + OUT_RING( age ); \ +} while (0) + +#define RADEON_CLEAR_AGE( age ) do { \ + OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \ + OUT_RING( age ); \ +} while (0) + +#define R600_DISPATCH_AGE(age) do { \ + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); \ + OUT_RING((R600_LAST_DISPATCH_REG - R600_SET_CONFIG_REG_OFFSET) >> 2); \ + OUT_RING(age); \ +} while (0) + +#define R600_FRAME_AGE(age) do { \ + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); \ + OUT_RING((R600_LAST_FRAME_REG - R600_SET_CONFIG_REG_OFFSET) >> 2); \ + OUT_RING(age); \ +} while (0) + +#define R600_CLEAR_AGE(age) do { \ + OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); \ + OUT_RING((R600_LAST_CLEAR_REG - R600_SET_CONFIG_REG_OFFSET) >> 2); \ + OUT_RING(age); \ +} while (0) + +/* ================================================================ + * Ring control + */ + +#define RADEON_VERBOSE 0 + +#define RING_LOCALS int write, _nr, _align_nr; unsigned int mask; u32 *ring; + +#define RADEON_RING_ALIGN 16 + +#define BEGIN_RING( n ) do { \ + if ( RADEON_VERBOSE ) { \ + DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ + } \ + _align_nr = RADEON_RING_ALIGN - ((dev_priv->ring.tail + n) & (RADEON_RING_ALIGN-1)); \ + _align_nr += n; \ + if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) { \ + COMMIT_RING(); \ + radeon_wait_ring( dev_priv, _align_nr * sizeof(u32)); \ + } \ + _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ + ring = dev_priv->ring.start; \ + write = dev_priv->ring.tail; \ + mask = dev_priv->ring.tail_mask; \ +} while (0) + +#define ADVANCE_RING() do { \ + if ( RADEON_VERBOSE ) { \ + DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ + write, dev_priv->ring.tail ); \ + } \ + if (((dev_priv->ring.tail + _nr) & mask) != write) { \ + DRM_ERROR( \ + "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ + ((dev_priv->ring.tail + _nr) & mask), \ + write, __LINE__); \ + } else \ + dev_priv->ring.tail = write; \ +} while (0) + +extern void radeon_commit_ring(drm_radeon_private_t *dev_priv); + +#define COMMIT_RING() do { \ + radeon_commit_ring(dev_priv); \ + } while(0) + +#define OUT_RING( x ) do { \ + if ( RADEON_VERBOSE ) { \ + DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ + (unsigned int)(x), write ); \ + } \ + ring[write++] = (x); \ + write &= mask; \ +} while (0) + +#define OUT_RING_REG( reg, val ) do { \ + OUT_RING( CP_PACKET0( reg, 0 ) ); \ + OUT_RING( val ); \ +} while (0) + +#define OUT_RING_TABLE( tab, sz ) do { \ + int _size = (sz); \ + int *_tab = (int *)(tab); \ + \ + if (write + _size > mask) { \ + int _i = (mask+1) - write; \ + _size -= _i; \ + while (_i > 0 ) { \ + *(int *)(ring + write) = *_tab++; \ + write++; \ + _i--; \ + } \ + write = 0; \ + _tab += _i; \ + } \ + while (_size > 0) { \ + *(ring + write) = *_tab++; \ + write++; \ + _size--; \ + } \ + write &= mask; \ +} while (0) + +/** + * Copy given number of dwords from drm buffer to the ring buffer. + */ +#define OUT_RING_DRM_BUFFER(buf, sz) do { \ + int _size = (sz) * 4; \ + struct drm_buffer *_buf = (buf); \ + int _part_size; \ + while (_size > 0) { \ + _part_size = _size; \ + \ + if (write + _part_size/4 > mask) \ + _part_size = ((mask + 1) - write)*4; \ + \ + if (drm_buffer_index(_buf) + _part_size > PAGE_SIZE) \ + _part_size = PAGE_SIZE - drm_buffer_index(_buf);\ + \ + \ + \ + memcpy(ring + write, &_buf->data[drm_buffer_page(_buf)] \ + [drm_buffer_index(_buf)], _part_size); \ + \ + _size -= _part_size; \ + write = (write + _part_size/4) & mask; \ + drm_buffer_advance(_buf, _part_size); \ + } \ +} while (0) + + +#endif /* __RADEON_DRV_H__ */ diff --git a/sys/dev/drm2/radeon/radeon_encoders.c b/sys/dev/drm2/radeon/radeon_encoders.c new file mode 100644 index 00000000000..be7ad3498cf --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_encoders.c @@ -0,0 +1,381 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon.h" +#include "atom.h" + + +static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *clone_encoder; + uint32_t index_mask = 0; + int count; + + /* DIG routing gets problematic */ + if (rdev->family >= CHIP_R600) + return index_mask; + /* LVDS/TV are too wacky */ + if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) + return index_mask; + /* DVO requires 2x ppll clocks depending on tmds chip */ + if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) + return index_mask; + + count = -1; + list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { + struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); + count++; + + if (clone_encoder == encoder) + continue; + if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) + continue; + if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) + continue; + else + index_mask |= (1 << count); + } + return index_mask; +} + +void radeon_setup_encoder_clones(struct drm_device *dev) +{ + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + encoder->possible_clones = radeon_encoder_clones(encoder); + } +} + +uint32_t +radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac) +{ + struct radeon_device *rdev = dev->dev_private; + uint32_t ret = 0; + + switch (supported_device) { + case ATOM_DEVICE_CRT1_SUPPORT: + case ATOM_DEVICE_TV1_SUPPORT: + case ATOM_DEVICE_TV2_SUPPORT: + case ATOM_DEVICE_CRT2_SUPPORT: + case ATOM_DEVICE_CV_SUPPORT: + switch (dac) { + case 1: /* dac a */ + if ((rdev->family == CHIP_RS300) || + (rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) + ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; + else if (ASIC_IS_AVIVO(rdev)) + ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; + else + ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; + break; + case 2: /* dac b */ + if (ASIC_IS_AVIVO(rdev)) + ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; + else { + /*if (rdev->family == CHIP_R200) + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; + else*/ + ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; + } + break; + case 3: /* external dac */ + if (ASIC_IS_AVIVO(rdev)) + ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; + else + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; + break; + } + break; + case ATOM_DEVICE_LCD1_SUPPORT: + if (ASIC_IS_AVIVO(rdev)) + ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; + else + ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; + break; + case ATOM_DEVICE_DFP1_SUPPORT: + if ((rdev->family == CHIP_RS300) || + (rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; + else if (ASIC_IS_AVIVO(rdev)) + ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; + else + ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; + break; + case ATOM_DEVICE_LCD2_SUPPORT: + case ATOM_DEVICE_DFP2_SUPPORT: + if ((rdev->family == CHIP_RS600) || + (rdev->family == CHIP_RS690) || + (rdev->family == CHIP_RS740)) + ret = ENCODER_INTERNAL_DDI_ENUM_ID1; + else if (ASIC_IS_AVIVO(rdev)) + ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; + else + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; + break; + case ATOM_DEVICE_DFP3_SUPPORT: + ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; + break; + } + + return ret; +} + +void +radeon_link_encoder_connector(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + + /* walk the list and link encoders to connectors */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->devices & radeon_connector->devices) { + drm_mode_connector_attach_encoder(connector, encoder); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + if (rdev->is_atom_bios) + radeon_atom_backlight_init(radeon_encoder, connector); + else + radeon_legacy_backlight_init(radeon_encoder, connector); + rdev->mode_info.bl_encoder = radeon_encoder; + } + } + } + } +} + +void radeon_encoder_set_active_device(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; + DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n", + radeon_encoder->active_device, radeon_encoder->devices, + radeon_connector->devices, encoder->encoder_type); + } + } +} + +struct drm_connector * +radeon_get_connector_for_encoder(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + if (radeon_encoder->active_device & radeon_connector->devices) + return connector; + } + return NULL; +} + +struct drm_connector * +radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + if (radeon_encoder->devices & radeon_connector->devices) + return connector; + } + return NULL; +} + +struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *other_encoder; + struct radeon_encoder *other_radeon_encoder; + + if (radeon_encoder->is_ext_encoder) + return NULL; + + list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { + if (other_encoder == encoder) + continue; + other_radeon_encoder = to_radeon_encoder(other_encoder); + if (other_radeon_encoder->is_ext_encoder && + (radeon_encoder->devices & other_radeon_encoder->devices)) + return other_encoder; + } + return NULL; +} + +u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder) +{ + struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder); + + if (other_encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + return radeon_encoder->encoder_id; + default: + return ENCODER_OBJECT_ID_NONE; + } + } + return ENCODER_OBJECT_ID_NONE; +} + +void radeon_panel_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + unsigned hblank = native_mode->htotal - native_mode->hdisplay; + unsigned vblank = native_mode->vtotal - native_mode->vdisplay; + unsigned hover = native_mode->hsync_start - native_mode->hdisplay; + unsigned vover = native_mode->vsync_start - native_mode->vdisplay; + unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start; + unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start; + + adjusted_mode->clock = native_mode->clock; + adjusted_mode->flags = native_mode->flags; + + if (ASIC_IS_AVIVO(rdev)) { + adjusted_mode->hdisplay = native_mode->hdisplay; + adjusted_mode->vdisplay = native_mode->vdisplay; + } + + adjusted_mode->htotal = native_mode->hdisplay + hblank; + adjusted_mode->hsync_start = native_mode->hdisplay + hover; + adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width; + + adjusted_mode->vtotal = native_mode->vdisplay + vblank; + adjusted_mode->vsync_start = native_mode->vdisplay + vover; + adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width; + + drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); + + if (ASIC_IS_AVIVO(rdev)) { + adjusted_mode->crtc_hdisplay = native_mode->hdisplay; + adjusted_mode->crtc_vdisplay = native_mode->vdisplay; + } + + adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank; + adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover; + adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width; + + adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank; + adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover; + adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width; + +} + +bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, + u32 pixel_clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + + connector = radeon_get_connector_for_encoder(encoder); + /* if we don't have an active device yet, just use one of + * the connectors tied to the encoder. + */ + if (!connector) + connector = radeon_get_connector_for_encoder_init(encoder); + radeon_connector = to_radeon_connector(connector); + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_HDMIB: + if (radeon_connector->use_digital) { + /* HDMI 1.3 supports up to 340 Mhz over single link */ + if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (pixel_clock > 340000) + return true; + else + return false; + } else { + if (pixel_clock > 165000) + return true; + else + return false; + } + } else + return false; + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_DisplayPort: + dig_connector = radeon_connector->con_priv; + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + return false; + else { + /* HDMI 1.3 supports up to 340 Mhz over single link */ + if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (pixel_clock > 340000) + return true; + else + return false; + } else { + if (pixel_clock > 165000) + return true; + else + return false; + } + } + default: + return false; + } +} + diff --git a/sys/dev/drm2/radeon/radeon_family.h b/sys/dev/drm2/radeon/radeon_family.h new file mode 100644 index 00000000000..7ac4937d133 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_family.h @@ -0,0 +1,117 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +/* this file defines the CHIP_ and family flags used in the pciids, + * its is common between kms and non-kms because duplicating it and + * changing one place is fail. + */ +#ifndef RADEON_FAMILY_H +#define RADEON_FAMILY_H +/* + * Radeon chip families + */ +enum radeon_family { + CHIP_R100 = 0, + CHIP_RV100, + CHIP_RS100, + CHIP_RV200, + CHIP_RS200, + CHIP_R200, + CHIP_RV250, + CHIP_RS300, + CHIP_RV280, + CHIP_R300, + CHIP_R350, + CHIP_RV350, + CHIP_RV380, + CHIP_R420, + CHIP_R423, + CHIP_RV410, + CHIP_RS400, + CHIP_RS480, + CHIP_RS600, + CHIP_RS690, + CHIP_RS740, + CHIP_RV515, + CHIP_R520, + CHIP_RV530, + CHIP_RV560, + CHIP_RV570, + CHIP_R580, + CHIP_R600, + CHIP_RV610, + CHIP_RV630, + CHIP_RV670, + CHIP_RV620, + CHIP_RV635, + CHIP_RS780, + CHIP_RS880, + CHIP_RV770, + CHIP_RV730, + CHIP_RV710, + CHIP_RV740, + CHIP_CEDAR, + CHIP_REDWOOD, + CHIP_JUNIPER, + CHIP_CYPRESS, + CHIP_HEMLOCK, + CHIP_PALM, + CHIP_SUMO, + CHIP_SUMO2, + CHIP_BARTS, + CHIP_TURKS, + CHIP_CAICOS, + CHIP_CAYMAN, + CHIP_ARUBA, + CHIP_TAHITI, + CHIP_PITCAIRN, + CHIP_VERDE, + CHIP_LAST, +}; + +/* + * Chip flags + */ +enum radeon_chip_flags { + RADEON_FAMILY_MASK = 0x0000ffffUL, + RADEON_FLAGS_MASK = 0xffff0000UL, + RADEON_IS_MOBILITY = 0x00010000UL, + RADEON_IS_IGP = 0x00020000UL, + RADEON_SINGLE_CRTC = 0x00040000UL, + RADEON_IS_AGP = 0x00080000UL, + RADEON_HAS_HIERZ = 0x00100000UL, + RADEON_IS_PCIE = 0x00200000UL, + RADEON_NEW_MEMMAP = 0x00400000UL, + RADEON_IS_PCI = 0x00800000UL, + RADEON_IS_IGPGART = 0x01000000UL, +}; + +#endif diff --git a/sys/dev/drm2/radeon/radeon_fb.c b/sys/dev/drm2/radeon/radeon_fb.c new file mode 100644 index 00000000000..fc247e2bbc6 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_fb.c @@ -0,0 +1,433 @@ +/* + * Copyright © 2007 David Airlie + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * David Airlie + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "radeon.h" + +#include + +/* object hierarchy - + this contains a helper + a radeon fb + the helper contains a pointer to radeon framebuffer baseclass. +*/ +struct radeon_fbdev { + struct drm_fb_helper helper; + struct radeon_framebuffer rfb; + struct list_head fbdev_list; + struct radeon_device *rdev; +}; + +#ifdef DUMBBELL_WIP +static struct fb_ops radeonfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_blank = drm_fb_helper_blank, + .fb_setcmap = drm_fb_helper_setcmap, + .fb_debug_enter = drm_fb_helper_debug_enter, + .fb_debug_leave = drm_fb_helper_debug_leave, +}; +#endif /* DUMBBELL_WIP */ + + +int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) +{ + int aligned = width; + int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; + int pitch_mask = 0; + + switch (bpp / 8) { + case 1: + pitch_mask = align_large ? 255 : 127; + break; + case 2: + pitch_mask = align_large ? 127 : 31; + break; + case 3: + case 4: + pitch_mask = align_large ? 63 : 15; + break; + } + + aligned += pitch_mask; + aligned &= ~pitch_mask; + return aligned; +} + +static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) +{ + struct radeon_bo *rbo = gem_to_radeon_bo(gobj); + int ret; + + ret = radeon_bo_reserve(rbo, false); + if (likely(ret == 0)) { + radeon_bo_kunmap(rbo); + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); + } + drm_gem_object_unreference_unlocked(gobj); +} + +static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object **gobj_p) +{ + struct radeon_device *rdev = rfbdev->rdev; + struct drm_gem_object *gobj = NULL; + struct radeon_bo *rbo = NULL; + bool fb_tiled = false; /* useful for testing */ + u32 tiling_flags = 0; + int ret; + int aligned_size, size; + int height = mode_cmd->height; + u32 bpp, depth; + + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + /* need to align pitch with crtc limits */ + mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, + fb_tiled) * ((bpp + 1) / 8); + + if (rdev->family >= CHIP_R600) + height = roundup2(mode_cmd->height, 8); + size = mode_cmd->pitches[0] * height; + aligned_size = roundup2(size, PAGE_SIZE); + ret = radeon_gem_object_create(rdev, aligned_size, 0, + RADEON_GEM_DOMAIN_VRAM, + false, true, + &gobj); + if (ret) { + DRM_ERROR("failed to allocate framebuffer (%d)\n", + aligned_size); + return -ENOMEM; + } + rbo = gem_to_radeon_bo(gobj); + + if (fb_tiled) + tiling_flags = RADEON_TILING_MACRO; + +#ifdef __BIG_ENDIAN + switch (bpp) { + case 32: + tiling_flags |= RADEON_TILING_SWAP_32BIT; + break; + case 16: + tiling_flags |= RADEON_TILING_SWAP_16BIT; + default: + break; + } +#endif + + if (tiling_flags) { + ret = radeon_bo_set_tiling_flags(rbo, + tiling_flags | RADEON_TILING_SURFACE, + mode_cmd->pitches[0]); + if (ret) + dev_err(rdev->dev, "FB failed to set tiling flags\n"); + } + + + ret = radeon_bo_reserve(rbo, false); + if (unlikely(ret != 0)) + goto out_unref; + /* Only 27 bit offset for legacy CRTC */ + ret = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, + NULL); + if (ret) { + radeon_bo_unreserve(rbo); + goto out_unref; + } + if (fb_tiled) + radeon_bo_check_tiling(rbo, 0, 0); + ret = radeon_bo_kmap(rbo, NULL); + radeon_bo_unreserve(rbo); + if (ret) { + goto out_unref; + } + + *gobj_p = gobj; + return 0; +out_unref: + radeonfb_destroy_pinned_object(gobj); + *gobj_p = NULL; + return ret; +} + +static int radeonfb_create(struct radeon_fbdev *rfbdev, + struct drm_fb_helper_surface_size *sizes) +{ + struct radeon_device *rdev = rfbdev->rdev; +#ifdef DUMBBELL_WIP + struct fb_info *info; +#endif /* DUMBBELL_WIP */ + struct drm_framebuffer *fb = NULL; + struct drm_mode_fb_cmd2 mode_cmd; + struct drm_gem_object *gobj = NULL; + struct radeon_bo *rbo = NULL; +#ifdef DUMBBELL_WIP + device_t device = rdev->dev; +#endif /* DUMBBELL_WIP */ + int ret; +#ifdef DUMBBELL_WIP + unsigned long tmp; +#endif /* DUMBBELL_WIP */ + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + + /* avivo can't scanout real 24bpp */ + if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) + sizes->surface_bpp = 32; + + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); + if (ret) { + DRM_ERROR("failed to create fbcon object %d\n", ret); + return ret; + } + + rbo = gem_to_radeon_bo(gobj); + +#ifdef DUMBBELL_WIP + /* okay we have an object now allocate the framebuffer */ + info = framebuffer_alloc(0, device); + if (info == NULL) { + ret = -ENOMEM; + goto out_unref; + } + + info->par = rfbdev; +#endif /* DUMBBELL_WIP */ + + ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); + if (ret) { + DRM_ERROR("failed to initalise framebuffer %d\n", ret); + goto out_unref; + } + + fb = &rfbdev->rfb.base; + + /* setup helper */ + rfbdev->helper.fb = fb; +#ifdef DUMBBELL_WIP + rfbdev->helper.fbdev = info; + + memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo)); + + strcpy(info->fix.id, "radeondrmfb"); + + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + + info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; + info->fbops = &radeonfb_ops; + + tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; + info->fix.smem_start = rdev->mc.aper_base + tmp; + info->fix.smem_len = radeon_bo_size(rbo); + info->screen_base = rbo->kptr; + info->screen_size = radeon_bo_size(rbo); + + drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); + + /* setup aperture base/size for vesafb takeover */ + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto out_unref; + } + info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; + info->apertures->ranges[0].size = rdev->mc.aper_size; + + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ + + if (info->screen_base == NULL) { + ret = -ENOSPC; + goto out_unref; + } + + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret) { + ret = -ENOMEM; + goto out_unref; + } + + DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); + DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); + DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); + DRM_INFO("fb depth is %d\n", fb->depth); + DRM_INFO(" pitch is %d\n", fb->pitches[0]); + + vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); +#endif /* DUMBBELL_WIP */ + return 0; + +out_unref: + if (rbo) { + + } + if (fb && ret) { + drm_gem_object_unreference(gobj); + drm_framebuffer_cleanup(fb); + free(fb, DRM_MEM_DRIVER); /* XXX malloc'd in radeon_user_framebuffer_create? */ + } + return ret; +} + +static int radeon_fb_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct radeon_fbdev *rfbdev = (struct radeon_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = radeonfb_create(rfbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + +void radeon_fb_output_poll_changed(struct radeon_device *rdev) +{ + drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper); +} + +static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) +{ +#ifdef DUMBBELL_WIP + struct fb_info *info; +#endif /* DUMBBELL_WIP */ + struct radeon_framebuffer *rfb = &rfbdev->rfb; + +#ifdef DUMBBELL_WIP + if (rfbdev->helper.fbdev) { + info = rfbdev->helper.fbdev; + + unregister_framebuffer(info); + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } +#endif /* DUMBBELL_WIP */ + + if (rfb->obj) { + DRM_UNLOCK(dev); /* Work around lock recursion. dumbbell@ */ + radeonfb_destroy_pinned_object(rfb->obj); + DRM_LOCK(dev); + rfb->obj = NULL; + } + drm_fb_helper_fini(&rfbdev->helper); + drm_framebuffer_cleanup(&rfb->base); + + return 0; +} + +static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { + .gamma_set = radeon_crtc_fb_gamma_set, + .gamma_get = radeon_crtc_fb_gamma_get, + .fb_probe = radeon_fb_find_or_create_single, +}; + +int radeon_fbdev_init(struct radeon_device *rdev) +{ + struct radeon_fbdev *rfbdev; + int bpp_sel = 32; + int ret; + + /* select 8 bpp console on RN50 or 16MB cards */ + if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024)) + bpp_sel = 8; + + rfbdev = malloc(sizeof(struct radeon_fbdev), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (!rfbdev) + return -ENOMEM; + + rfbdev->rdev = rdev; + rdev->mode_info.rfbdev = rfbdev; + rfbdev->helper.funcs = &radeon_fb_helper_funcs; + + ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper, + rdev->num_crtc, + RADEONFB_CONN_LIMIT); + if (ret) { + free(rfbdev, DRM_MEM_DRIVER); + return ret; + } + + drm_fb_helper_single_add_all_connectors(&rfbdev->helper); + drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); + return 0; +} + +void radeon_fbdev_fini(struct radeon_device *rdev) +{ + if (!rdev->mode_info.rfbdev) + return; + + radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev); + free(rdev->mode_info.rfbdev, DRM_MEM_DRIVER); + rdev->mode_info.rfbdev = NULL; +} + +void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state) +{ +#ifdef DUMBBELL_WIP + fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state); +#endif /* DUMBBELL_WIP */ +} + +int radeon_fbdev_total_size(struct radeon_device *rdev) +{ + struct radeon_bo *robj; + int size = 0; + + robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj); + size += radeon_bo_size(robj); + return size; +} + +bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) +{ + if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj)) + return true; + return false; +} diff --git a/sys/dev/drm2/radeon/radeon_fence.c b/sys/dev/drm2/radeon/radeon_fence.c new file mode 100644 index 00000000000..07b1a64b53b --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_fence.c @@ -0,0 +1,983 @@ +/* + * Copyright 2009 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: + * Jerome Glisse + * Dave Airlie + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon_reg.h" +#include "radeon.h" +#ifdef DUMBBELL_WIP +#include "radeon_trace.h" +#endif /* DUMBBELL_WIP */ + +/* + * Fences + * Fences mark an event in the GPUs pipeline and are used + * for GPU/CPU synchronization. When the fence is written, + * it is expected that all buffers associated with that fence + * are no longer in use by the associated ring on the GPU and + * that the the relevant GPU caches have been flushed. Whether + * we use a scratch register or memory location depends on the asic + * and whether writeback is enabled. + */ + +/** + * radeon_fence_write - write a fence value + * + * @rdev: radeon_device pointer + * @seq: sequence number to write + * @ring: ring index the fence is associated with + * + * Writes a fence value to memory or a scratch register (all asics). + */ +static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) +{ + struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; + if (likely(rdev->wb.enabled || !drv->scratch_reg)) { + *drv->cpu_addr = cpu_to_le32(seq); + } else { + WREG32(drv->scratch_reg, seq); + } +} + +/** + * radeon_fence_read - read a fence value + * + * @rdev: radeon_device pointer + * @ring: ring index the fence is associated with + * + * Reads a fence value from memory or a scratch register (all asics). + * Returns the value of the fence read from memory or register. + */ +static u32 radeon_fence_read(struct radeon_device *rdev, int ring) +{ + struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; + u32 seq = 0; + + if (likely(rdev->wb.enabled || !drv->scratch_reg)) { + seq = le32_to_cpu(*drv->cpu_addr); + } else { + seq = RREG32(drv->scratch_reg); + } + return seq; +} + +/** + * radeon_fence_emit - emit a fence on the requested ring + * + * @rdev: radeon_device pointer + * @fence: radeon fence object + * @ring: ring index the fence is associated with + * + * Emits a fence command on the requested ring (all asics). + * Returns 0 on success, -ENOMEM on failure. + */ +int radeon_fence_emit(struct radeon_device *rdev, + struct radeon_fence **fence, + int ring) +{ + /* we are protected by the ring emission mutex */ + *fence = malloc(sizeof(struct radeon_fence), DRM_MEM_DRIVER, M_WAITOK); + if ((*fence) == NULL) { + return -ENOMEM; + } + refcount_init(&((*fence)->kref), 1); + (*fence)->rdev = rdev; + (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; + (*fence)->ring = ring; + radeon_fence_ring_emit(rdev, ring, *fence); + CTR2(KTR_DRM, "radeon fence: emit (ring=%d, seq=%d)", ring, (*fence)->seq); + return 0; +} + +/** + * radeon_fence_process - process a fence + * + * @rdev: radeon_device pointer + * @ring: ring index the fence is associated with + * + * Checks the current fence value and wakes the fence queue + * if the sequence number has increased (all asics). + */ +void radeon_fence_process(struct radeon_device *rdev, int ring) +{ + uint64_t seq, last_seq, last_emitted; + unsigned count_loop = 0; + bool wake = false; + + /* Note there is a scenario here for an infinite loop but it's + * very unlikely to happen. For it to happen, the current polling + * process need to be interrupted by another process and another + * process needs to update the last_seq btw the atomic read and + * xchg of the current process. + * + * More over for this to go in infinite loop there need to be + * continuously new fence signaled ie radeon_fence_read needs + * to return a different value each time for both the currently + * polling process and the other process that xchg the last_seq + * btw atomic read and xchg of the current process. And the + * value the other process set as last seq must be higher than + * the seq value we just read. Which means that current process + * need to be interrupted after radeon_fence_read and before + * atomic xchg. + * + * To be even more safe we count the number of time we loop and + * we bail after 10 loop just accepting the fact that we might + * have temporarly set the last_seq not to the true real last + * seq but to an older one. + */ + last_seq = atomic_load_acq_64(&rdev->fence_drv[ring].last_seq); + do { + last_emitted = rdev->fence_drv[ring].sync_seq[ring]; + seq = radeon_fence_read(rdev, ring); + seq |= last_seq & 0xffffffff00000000LL; + if (seq < last_seq) { + seq &= 0xffffffff; + seq |= last_emitted & 0xffffffff00000000LL; + } + + if (seq <= last_seq || seq > last_emitted) { + break; + } + /* If we loop over we don't want to return without + * checking if a fence is signaled as it means that the + * seq we just read is different from the previous on. + */ + wake = true; + last_seq = seq; + if ((count_loop++) > 10) { + /* We looped over too many time leave with the + * fact that we might have set an older fence + * seq then the current real last seq as signaled + * by the hw. + */ + break; + } + } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq); + + if (wake) { + rdev->fence_drv[ring].last_activity = jiffies; + cv_broadcast(&rdev->fence_queue); + } +} + +/** + * radeon_fence_destroy - destroy a fence + * + * @kref: fence kref + * + * Frees the fence object (all asics). + */ +static void radeon_fence_destroy(struct radeon_fence *fence) +{ + + free(fence, DRM_MEM_DRIVER); +} + +/** + * radeon_fence_seq_signaled - check if a fence sequeuce number has signaled + * + * @rdev: radeon device pointer + * @seq: sequence number + * @ring: ring index the fence is associated with + * + * Check if the last singled fence sequnce number is >= the requested + * sequence number (all asics). + * Returns true if the fence has signaled (current fence value + * is >= requested value) or false if it has not (current fence + * value is < the requested value. Helper function for + * radeon_fence_signaled(). + */ +static bool radeon_fence_seq_signaled(struct radeon_device *rdev, + u64 seq, unsigned ring) +{ + if (atomic_load_acq_64(&rdev->fence_drv[ring].last_seq) >= seq) { + return true; + } + /* poll new last sequence at least once */ + radeon_fence_process(rdev, ring); + if (atomic_load_acq_64(&rdev->fence_drv[ring].last_seq) >= seq) { + return true; + } + return false; +} + +/** + * radeon_fence_signaled - check if a fence has signaled + * + * @fence: radeon fence object + * + * Check if the requested fence has signaled (all asics). + * Returns true if the fence has signaled or false if it has not. + */ +bool radeon_fence_signaled(struct radeon_fence *fence) +{ + if (!fence) { + return true; + } + if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { + return true; + } + if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) { + fence->seq = RADEON_FENCE_SIGNALED_SEQ; + return true; + } + return false; +} + +/** + * radeon_fence_wait_seq - wait for a specific sequence number + * + * @rdev: radeon device pointer + * @target_seq: sequence number we want to wait for + * @ring: ring index the fence is associated with + * @intr: use interruptable sleep + * @lock_ring: whether the ring should be locked or not + * + * Wait for the requested sequence number to be written (all asics). + * @intr selects whether to use interruptable (true) or non-interruptable + * (false) sleep when waiting for the sequence number. Helper function + * for radeon_fence_wait(), et al. + * Returns 0 if the sequence number has passed, error for all other cases. + * -EDEADLK is returned when a GPU lockup has been detected and the ring is + * marked as not ready so no further jobs get scheduled until a successful + * reset. + */ +static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, + unsigned ring, bool intr, bool lock_ring) +{ + unsigned long timeout, last_activity; + uint64_t seq; + unsigned i; + bool signaled, fence_queue_locked; + int r; + + while (target_seq > atomic_load_acq_64(&rdev->fence_drv[ring].last_seq)) { + if (!rdev->ring[ring].ready) { + return -EBUSY; + } + + timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT; + if (time_after(rdev->fence_drv[ring].last_activity, timeout)) { + /* the normal case, timeout is somewhere before last_activity */ + timeout = rdev->fence_drv[ring].last_activity - timeout; + } else { + /* either jiffies wrapped around, or no fence was signaled in the last 500ms + * anyway we will just wait for the minimum amount and then check for a lockup + */ + timeout = 1; + } + seq = atomic_load_acq_64(&rdev->fence_drv[ring].last_seq); + /* Save current last activity valuee, used to check for GPU lockups */ + last_activity = rdev->fence_drv[ring].last_activity; + + CTR2(KTR_DRM, "radeon fence: wait begin (ring=%d, seq=%d)", + ring, seq); + + radeon_irq_kms_sw_irq_get(rdev, ring); + fence_queue_locked = false; + r = 0; + while (!(signaled = radeon_fence_seq_signaled(rdev, + target_seq, ring))) { + if (!fence_queue_locked) { + mtx_lock(&rdev->fence_queue_mtx); + fence_queue_locked = true; + } + if (intr) { + r = cv_timedwait_sig(&rdev->fence_queue, + &rdev->fence_queue_mtx, + timeout); + } else { + r = cv_timedwait(&rdev->fence_queue, + &rdev->fence_queue_mtx, + timeout); + } + if (r != 0) { + if (r == EWOULDBLOCK) { + signaled = + radeon_fence_seq_signaled( + rdev, target_seq, ring); + } + break; + } + } + if (fence_queue_locked) { + mtx_unlock(&rdev->fence_queue_mtx); + } + radeon_irq_kms_sw_irq_put(rdev, ring); + if (unlikely(r == EINTR || r == ERESTART)) { + return -r; + } + CTR2(KTR_DRM, "radeon fence: wait end (ring=%d, seq=%d)", + ring, seq); + + if (unlikely(!signaled)) { +#ifndef __FreeBSD__ + /* we were interrupted for some reason and fence + * isn't signaled yet, resume waiting */ + if (r) { + continue; + } +#endif + + /* check if sequence value has changed since last_activity */ + if (seq != atomic_load_acq_64(&rdev->fence_drv[ring].last_seq)) { + continue; + } + + if (lock_ring) { + sx_xlock(&rdev->ring_lock); + } + + /* test if somebody else has already decided that this is a lockup */ + if (last_activity != rdev->fence_drv[ring].last_activity) { + if (lock_ring) { + sx_xunlock(&rdev->ring_lock); + } + continue; + } + + if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) { + /* good news we believe it's a lockup */ + dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016jx last fence id 0x%016jx)\n", + (uintmax_t)target_seq, (uintmax_t)seq); + + /* change last activity so nobody else think there is a lockup */ + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + rdev->fence_drv[i].last_activity = jiffies; + } + + /* mark the ring as not ready any more */ + rdev->ring[ring].ready = false; + if (lock_ring) { + sx_xunlock(&rdev->ring_lock); + } + return -EDEADLK; + } + + if (lock_ring) { + sx_xunlock(&rdev->ring_lock); + } + } + } + return 0; +} + +/** + * radeon_fence_wait - wait for a fence to signal + * + * @fence: radeon fence object + * @intr: use interruptable sleep + * + * Wait for the requested fence to signal (all asics). + * @intr selects whether to use interruptable (true) or non-interruptable + * (false) sleep when waiting for the fence. + * Returns 0 if the fence has passed, error for all other cases. + */ +int radeon_fence_wait(struct radeon_fence *fence, bool intr) +{ + int r; + + if (fence == NULL) { + DRM_ERROR("Querying an invalid fence : %p !\n", fence); + return -EINVAL; + } + + r = radeon_fence_wait_seq(fence->rdev, fence->seq, + fence->ring, intr, true); + if (r) { + return r; + } + fence->seq = RADEON_FENCE_SIGNALED_SEQ; + return 0; +} + +static bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq) +{ + unsigned i; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + if (seq[i] && radeon_fence_seq_signaled(rdev, seq[i], i)) { + return true; + } + } + return false; +} + +/** + * radeon_fence_wait_any_seq - wait for a sequence number on any ring + * + * @rdev: radeon device pointer + * @target_seq: sequence number(s) we want to wait for + * @intr: use interruptable sleep + * + * Wait for the requested sequence number(s) to be written by any ring + * (all asics). Sequnce number array is indexed by ring id. + * @intr selects whether to use interruptable (true) or non-interruptable + * (false) sleep when waiting for the sequence number. Helper function + * for radeon_fence_wait_any(), et al. + * Returns 0 if the sequence number has passed, error for all other cases. + */ +static int radeon_fence_wait_any_seq(struct radeon_device *rdev, + u64 *target_seq, bool intr) +{ + unsigned long timeout, last_activity, tmp; + unsigned i, ring = RADEON_NUM_RINGS; + bool signaled, fence_queue_locked; + int r; + + for (i = 0, last_activity = 0; i < RADEON_NUM_RINGS; ++i) { + if (!target_seq[i]) { + continue; + } + + /* use the most recent one as indicator */ + if (time_after(rdev->fence_drv[i].last_activity, last_activity)) { + last_activity = rdev->fence_drv[i].last_activity; + } + + /* For lockup detection just pick the lowest ring we are + * actively waiting for + */ + if (i < ring) { + ring = i; + } + } + + /* nothing to wait for ? */ + if (ring == RADEON_NUM_RINGS) { + return -ENOENT; + } + + while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { + timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT; + if (time_after(last_activity, timeout)) { + /* the normal case, timeout is somewhere before last_activity */ + timeout = last_activity - timeout; + } else { + /* either jiffies wrapped around, or no fence was signaled in the last 500ms + * anyway we will just wait for the minimum amount and then check for a lockup + */ + timeout = 1; + } + + CTR2(KTR_DRM, "radeon fence: wait begin (ring=%d, target_seq=%d)", + ring, target_seq[ring]); + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + if (target_seq[i]) { + radeon_irq_kms_sw_irq_get(rdev, i); + } + } + fence_queue_locked = false; + r = 0; + while (!(signaled = radeon_fence_any_seq_signaled(rdev, + target_seq))) { + if (!fence_queue_locked) { + mtx_lock(&rdev->fence_queue_mtx); + fence_queue_locked = true; + } + if (intr) { + r = cv_timedwait_sig(&rdev->fence_queue, + &rdev->fence_queue_mtx, + timeout); + } else { + r = cv_timedwait(&rdev->fence_queue, + &rdev->fence_queue_mtx, + timeout); + } + if (r != 0) { + if (r == EWOULDBLOCK) { + signaled = + radeon_fence_any_seq_signaled( + rdev, target_seq); + } + break; + } + } + if (fence_queue_locked) { + mtx_unlock(&rdev->fence_queue_mtx); + } + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + if (target_seq[i]) { + radeon_irq_kms_sw_irq_put(rdev, i); + } + } + if (unlikely(r == EINTR || r == ERESTART)) { + return -r; + } + CTR2(KTR_DRM, "radeon fence: wait end (ring=%d, target_seq=%d)", + ring, target_seq[ring]); + + if (unlikely(!signaled)) { +#ifndef __FreeBSD__ + /* we were interrupted for some reason and fence + * isn't signaled yet, resume waiting */ + if (r) { + continue; + } +#endif + + sx_xlock(&rdev->ring_lock); + for (i = 0, tmp = 0; i < RADEON_NUM_RINGS; ++i) { + if (time_after(rdev->fence_drv[i].last_activity, tmp)) { + tmp = rdev->fence_drv[i].last_activity; + } + } + /* test if somebody else has already decided that this is a lockup */ + if (last_activity != tmp) { + last_activity = tmp; + sx_xunlock(&rdev->ring_lock); + continue; + } + + if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) { + /* good news we believe it's a lockup */ + dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016jx)\n", + (uintmax_t)target_seq[ring]); + + /* change last activity so nobody else think there is a lockup */ + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + rdev->fence_drv[i].last_activity = jiffies; + } + + /* mark the ring as not ready any more */ + rdev->ring[ring].ready = false; + sx_xunlock(&rdev->ring_lock); + return -EDEADLK; + } + sx_xunlock(&rdev->ring_lock); + } + } + return 0; +} + +/** + * radeon_fence_wait_any - wait for a fence to signal on any ring + * + * @rdev: radeon device pointer + * @fences: radeon fence object(s) + * @intr: use interruptable sleep + * + * Wait for any requested fence to signal (all asics). Fence + * array is indexed by ring id. @intr selects whether to use + * interruptable (true) or non-interruptable (false) sleep when + * waiting for the fences. Used by the suballocator. + * Returns 0 if any fence has passed, error for all other cases. + */ +int radeon_fence_wait_any(struct radeon_device *rdev, + struct radeon_fence **fences, + bool intr) +{ + uint64_t seq[RADEON_NUM_RINGS]; + unsigned i; + int r; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + seq[i] = 0; + + if (!fences[i]) { + continue; + } + + if (fences[i]->seq == RADEON_FENCE_SIGNALED_SEQ) { + /* something was allready signaled */ + return 0; + } + + seq[i] = fences[i]->seq; + } + + r = radeon_fence_wait_any_seq(rdev, seq, intr); + if (r) { + return r; + } + return 0; +} + +/** + * radeon_fence_wait_next_locked - wait for the next fence to signal + * + * @rdev: radeon device pointer + * @ring: ring index the fence is associated with + * + * Wait for the next fence on the requested ring to signal (all asics). + * Returns 0 if the next fence has passed, error for all other cases. + * Caller must hold ring lock. + */ +int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) +{ + uint64_t seq; + + seq = atomic_load_acq_64(&rdev->fence_drv[ring].last_seq) + 1ULL; + if (seq >= rdev->fence_drv[ring].sync_seq[ring]) { + /* nothing to wait for, last_seq is + already the last emited fence */ + return -ENOENT; + } + return radeon_fence_wait_seq(rdev, seq, ring, false, false); +} + +/** + * radeon_fence_wait_empty_locked - wait for all fences to signal + * + * @rdev: radeon device pointer + * @ring: ring index the fence is associated with + * + * Wait for all fences on the requested ring to signal (all asics). + * Returns 0 if the fences have passed, error for all other cases. + * Caller must hold ring lock. + */ +int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) +{ + uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; + int r; + + r = radeon_fence_wait_seq(rdev, seq, ring, false, false); + if (r) { + if (r == -EDEADLK) { + return -EDEADLK; + } + dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", + ring, r); + } + return 0; +} + +/** + * radeon_fence_ref - take a ref on a fence + * + * @fence: radeon fence object + * + * Take a reference on a fence (all asics). + * Returns the fence. + */ +struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) +{ + refcount_acquire(&fence->kref); + return fence; +} + +/** + * radeon_fence_unref - remove a ref on a fence + * + * @fence: radeon fence object + * + * Remove a reference on a fence (all asics). + */ +void radeon_fence_unref(struct radeon_fence **fence) +{ + struct radeon_fence *tmp = *fence; + + *fence = NULL; + if (tmp) { + if (refcount_release(&tmp->kref)) { + radeon_fence_destroy(tmp); + } + } +} + +/** + * radeon_fence_count_emitted - get the count of emitted fences + * + * @rdev: radeon device pointer + * @ring: ring index the fence is associated with + * + * Get the number of fences emitted on the requested ring (all asics). + * Returns the number of emitted fences on the ring. Used by the + * dynpm code to ring track activity. + */ +unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) +{ + uint64_t emitted; + + /* We are not protected by ring lock when reading the last sequence + * but it's ok to report slightly wrong fence count here. + */ + radeon_fence_process(rdev, ring); + emitted = rdev->fence_drv[ring].sync_seq[ring] + - atomic_load_acq_64(&rdev->fence_drv[ring].last_seq); + /* to avoid 32bits warp around */ + if (emitted > 0x10000000) { + emitted = 0x10000000; + } + return (unsigned)emitted; +} + +/** + * radeon_fence_need_sync - do we need a semaphore + * + * @fence: radeon fence object + * @dst_ring: which ring to check against + * + * Check if the fence needs to be synced against another ring + * (all asics). If so, we need to emit a semaphore. + * Returns true if we need to sync with another ring, false if + * not. + */ +bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) +{ + struct radeon_fence_driver *fdrv; + + if (!fence) { + return false; + } + + if (fence->ring == dst_ring) { + return false; + } + + /* we are protected by the ring mutex */ + fdrv = &fence->rdev->fence_drv[dst_ring]; + if (fence->seq <= fdrv->sync_seq[fence->ring]) { + return false; + } + + return true; +} + +/** + * radeon_fence_note_sync - record the sync point + * + * @fence: radeon fence object + * @dst_ring: which ring to check against + * + * Note the sequence number at which point the fence will + * be synced with the requested ring (all asics). + */ +void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) +{ + struct radeon_fence_driver *dst, *src; + unsigned i; + + if (!fence) { + return; + } + + if (fence->ring == dst_ring) { + return; + } + + /* we are protected by the ring mutex */ + src = &fence->rdev->fence_drv[fence->ring]; + dst = &fence->rdev->fence_drv[dst_ring]; + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + if (i == dst_ring) { + continue; + } + dst->sync_seq[i] = max(dst->sync_seq[i], src->sync_seq[i]); + } +} + +/** + * radeon_fence_driver_start_ring - make the fence driver + * ready for use on the requested ring. + * + * @rdev: radeon device pointer + * @ring: ring index to start the fence driver on + * + * Make the fence driver ready for processing (all asics). + * Not all asics have all rings, so each asic will only + * start the fence driver on the rings it has. + * Returns 0 for success, errors for failure. + */ +int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) +{ + uint64_t index; + int r; + + radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); + if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) { + rdev->fence_drv[ring].scratch_reg = 0; + index = R600_WB_EVENT_OFFSET + ring * 4; + } else { + r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg); + if (r) { + dev_err(rdev->dev, "fence failed to get scratch register\n"); + return r; + } + index = RADEON_WB_SCRATCH_OFFSET + + rdev->fence_drv[ring].scratch_reg - + rdev->scratch.reg_base; + } + rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; + rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; + radeon_fence_write(rdev, atomic_load_acq_64(&rdev->fence_drv[ring].last_seq), ring); + rdev->fence_drv[ring].initialized = true; + dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016jx and cpu addr 0x%p\n", + ring, (uintmax_t)rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); + return 0; +} + +/** + * radeon_fence_driver_init_ring - init the fence driver + * for the requested ring. + * + * @rdev: radeon device pointer + * @ring: ring index to start the fence driver on + * + * Init the fence driver for the requested ring (all asics). + * Helper function for radeon_fence_driver_init(). + */ +static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) +{ + int i; + + rdev->fence_drv[ring].scratch_reg = -1; + rdev->fence_drv[ring].cpu_addr = NULL; + rdev->fence_drv[ring].gpu_addr = 0; + for (i = 0; i < RADEON_NUM_RINGS; ++i) + rdev->fence_drv[ring].sync_seq[i] = 0; + atomic_store_rel_64(&rdev->fence_drv[ring].last_seq, 0); + rdev->fence_drv[ring].last_activity = jiffies; + rdev->fence_drv[ring].initialized = false; +} + +/** + * radeon_fence_driver_init - init the fence driver + * for all possible rings. + * + * @rdev: radeon device pointer + * + * Init the fence driver for all possible rings (all asics). + * Not all asics have all rings, so each asic will only + * start the fence driver on the rings it has using + * radeon_fence_driver_start_ring(). + * Returns 0 for success. + */ +int radeon_fence_driver_init(struct radeon_device *rdev) +{ + int ring; + + mtx_init(&rdev->fence_queue_mtx, + "drm__radeon_device__fence_queue_mtx", NULL, MTX_DEF); + cv_init(&rdev->fence_queue, "drm__radeon_device__fence_queue"); + for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { + radeon_fence_driver_init_ring(rdev, ring); + } + if (radeon_debugfs_fence_init(rdev)) { + dev_err(rdev->dev, "fence debugfs file creation failed\n"); + } + return 0; +} + +/** + * radeon_fence_driver_fini - tear down the fence driver + * for all possible rings. + * + * @rdev: radeon device pointer + * + * Tear down the fence driver for all possible rings (all asics). + */ +void radeon_fence_driver_fini(struct radeon_device *rdev) +{ + int ring, r; + + sx_xlock(&rdev->ring_lock); + for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { + if (!rdev->fence_drv[ring].initialized) + continue; + r = radeon_fence_wait_empty_locked(rdev, ring); + if (r) { + /* no need to trigger GPU reset as we are unloading */ + radeon_fence_driver_force_completion(rdev); + } + cv_broadcast(&rdev->fence_queue); + radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); + rdev->fence_drv[ring].initialized = false; + cv_destroy(&rdev->fence_queue); + } + sx_xunlock(&rdev->ring_lock); +} + +/** + * radeon_fence_driver_force_completion - force all fence waiter to complete + * + * @rdev: radeon device pointer + * + * In case of GPU reset failure make sure no process keep waiting on fence + * that will never complete. + */ +void radeon_fence_driver_force_completion(struct radeon_device *rdev) +{ + int ring; + + for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { + if (!rdev->fence_drv[ring].initialized) + continue; + radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); + } +} + + +/* + * Fence debugfs + */ +#if defined(CONFIG_DEBUG_FS) +static int radeon_debugfs_fence_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + int i, j; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + if (!rdev->fence_drv[i].initialized) + continue; + + seq_printf(m, "--- ring %d ---\n", i); + seq_printf(m, "Last signaled fence 0x%016llx\n", + (unsigned long long)atomic_load_acq_64(&rdev->fence_drv[i].last_seq)); + seq_printf(m, "Last emitted 0x%016llx\n", + rdev->fence_drv[i].sync_seq[i]); + + for (j = 0; j < RADEON_NUM_RINGS; ++j) { + if (i != j && rdev->fence_drv[j].initialized) + seq_printf(m, "Last sync to ring %d 0x%016llx\n", + j, rdev->fence_drv[i].sync_seq[j]); + } + } + return 0; +} + +static struct drm_info_list radeon_debugfs_fence_list[] = { + {"radeon_fence_info", &radeon_debugfs_fence_info, 0, NULL}, +}; +#endif + +int radeon_debugfs_fence_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1); +#else + return 0; +#endif +} diff --git a/sys/dev/drm2/radeon/radeon_gart.c b/sys/dev/drm2/radeon/radeon_gart.c new file mode 100644 index 00000000000..36b4452b14b --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_gart.c @@ -0,0 +1,1304 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_reg.h" + +/* + * GART + * The GART (Graphics Aperture Remapping Table) is an aperture + * in the GPU's address space. System pages can be mapped into + * the aperture and look like contiguous pages from the GPU's + * perspective. A page table maps the pages in the aperture + * to the actual backing pages in system memory. + * + * Radeon GPUs support both an internal GART, as described above, + * and AGP. AGP works similarly, but the GART table is configured + * and maintained by the northbridge rather than the driver. + * Radeon hw has a separate AGP aperture that is programmed to + * point to the AGP aperture provided by the northbridge and the + * requests are passed through to the northbridge aperture. + * Both AGP and internal GART can be used at the same time, however + * that is not currently supported by the driver. + * + * This file handles the common internal GART management. + */ + +/* + * Common GART table functions. + */ +/** + * radeon_gart_table_ram_alloc - allocate system ram for gart page table + * + * @rdev: radeon_device pointer + * + * Allocate system memory for GART page table + * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the + * gart table to be in system memory. + * Returns 0 for success, -ENOMEM for failure. + */ +int radeon_gart_table_ram_alloc(struct radeon_device *rdev) +{ + drm_dma_handle_t *dmah; + + dmah = drm_pci_alloc(rdev->ddev, rdev->gart.table_size, + PAGE_SIZE, 0xFFFFFFFFUL); + if (dmah == NULL) { + return -ENOMEM; + } + rdev->gart.dmah = dmah; + rdev->gart.ptr = dmah->vaddr; +#if defined(__i386) || defined(__amd64) + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || + rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { + pmap_change_attr((vm_offset_t)rdev->gart.ptr, + rdev->gart.table_size >> PAGE_SHIFT, PAT_UNCACHED); + } +#endif + rdev->gart.table_addr = dmah->busaddr; + memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size); + return 0; +} + +/** + * radeon_gart_table_ram_free - free system ram for gart page table + * + * @rdev: radeon_device pointer + * + * Free system memory for GART page table + * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the + * gart table to be in system memory. + */ +void radeon_gart_table_ram_free(struct radeon_device *rdev) +{ + if (rdev->gart.ptr == NULL) { + return; + } +#if defined(__i386) || defined(__amd64) + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || + rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { + pmap_change_attr((vm_offset_t)rdev->gart.ptr, + rdev->gart.table_size >> PAGE_SHIFT, PAT_WRITE_COMBINING); + } +#endif + drm_pci_free(rdev->ddev, rdev->gart.dmah); + rdev->gart.dmah = NULL; + rdev->gart.ptr = NULL; + rdev->gart.table_addr = 0; +} + +/** + * radeon_gart_table_vram_alloc - allocate vram for gart page table + * + * @rdev: radeon_device pointer + * + * Allocate video memory for GART page table + * (pcie r4xx, r5xx+). These asics require the + * gart table to be in video memory. + * Returns 0 for success, error for failure. + */ +int radeon_gart_table_vram_alloc(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.robj == NULL) { + r = radeon_bo_create(rdev, rdev->gart.table_size, + PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->gart.robj); + if (r) { + return r; + } + } + return 0; +} + +/** + * radeon_gart_table_vram_pin - pin gart page table in vram + * + * @rdev: radeon_device pointer + * + * Pin the GART page table in vram so it will not be moved + * by the memory manager (pcie r4xx, r5xx+). These asics require the + * gart table to be in video memory. + * Returns 0 for success, error for failure. + */ +int radeon_gart_table_vram_pin(struct radeon_device *rdev) +{ + uint64_t gpu_addr; + int r; + + r = radeon_bo_reserve(rdev->gart.robj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->gart.robj, + RADEON_GEM_DOMAIN_VRAM, &gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->gart.robj); + return r; + } + r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr); + if (r) + radeon_bo_unpin(rdev->gart.robj); + radeon_bo_unreserve(rdev->gart.robj); + rdev->gart.table_addr = gpu_addr; + return r; +} + +/** + * radeon_gart_table_vram_unpin - unpin gart page table in vram + * + * @rdev: radeon_device pointer + * + * Unpin the GART page table in vram (pcie r4xx, r5xx+). + * These asics require the gart table to be in video memory. + */ +void radeon_gart_table_vram_unpin(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.robj == NULL) { + return; + } + r = radeon_bo_reserve(rdev->gart.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->gart.robj); + radeon_bo_unpin(rdev->gart.robj); + radeon_bo_unreserve(rdev->gart.robj); + rdev->gart.ptr = NULL; + } +} + +/** + * radeon_gart_table_vram_free - free gart page table vram + * + * @rdev: radeon_device pointer + * + * Free the video memory used for the GART page table + * (pcie r4xx, r5xx+). These asics require the gart table to + * be in video memory. + */ +void radeon_gart_table_vram_free(struct radeon_device *rdev) +{ + if (rdev->gart.robj == NULL) { + return; + } + radeon_gart_table_vram_unpin(rdev); + radeon_bo_unref(&rdev->gart.robj); +} + +/* + * Common gart functions. + */ +/** + * radeon_gart_unbind - unbind pages from the gart page table + * + * @rdev: radeon_device pointer + * @offset: offset into the GPU's gart aperture + * @pages: number of pages to unbind + * + * Unbinds the requested pages from the gart page table and + * replaces them with the dummy page (all asics). + */ +void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, + int pages) +{ + unsigned t; + unsigned p; + int i, j; + u64 page_base; + + if (!rdev->gart.ready) { + DRM_ERROR("trying to unbind memory from uninitialized GART !\n"); + return; + } + t = offset / RADEON_GPU_PAGE_SIZE; + p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); + for (i = 0; i < pages; i++, p++) { + if (rdev->gart.pages[p]) { + rdev->gart.pages[p] = NULL; + rdev->gart.pages_addr[p] = rdev->dummy_page.addr; + page_base = rdev->gart.pages_addr[p]; + for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { + if (rdev->gart.ptr) { + radeon_gart_set_page(rdev, t, page_base); + } + page_base += RADEON_GPU_PAGE_SIZE; + } + } + } + mb(); + radeon_gart_tlb_flush(rdev); +} + +/** + * radeon_gart_bind - bind pages into the gart page table + * + * @rdev: radeon_device pointer + * @offset: offset into the GPU's gart aperture + * @pages: number of pages to bind + * @pagelist: pages to bind + * @dma_addr: DMA addresses of pages + * + * Binds the requested pages to the gart page table + * (all asics). + * Returns 0 for success, -EINVAL for failure. + */ +int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, + int pages, vm_page_t *pagelist, dma_addr_t *dma_addr) +{ + unsigned t; + unsigned p; + uint64_t page_base; + int i, j; + + if (!rdev->gart.ready) { + DRM_ERROR("trying to bind memory to uninitialized GART !\n"); + return -EINVAL; + } + t = offset / RADEON_GPU_PAGE_SIZE; + p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); + + for (i = 0; i < pages; i++, p++) { + rdev->gart.pages_addr[p] = dma_addr[i]; + rdev->gart.pages[p] = pagelist[i]; + if (rdev->gart.ptr) { + page_base = rdev->gart.pages_addr[p]; + for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { + radeon_gart_set_page(rdev, t, page_base); + page_base += RADEON_GPU_PAGE_SIZE; + } + } + } + mb(); + radeon_gart_tlb_flush(rdev); + return 0; +} + +/** + * radeon_gart_restore - bind all pages in the gart page table + * + * @rdev: radeon_device pointer + * + * Binds all pages in the gart page table (all asics). + * Used to rebuild the gart table on device startup or resume. + */ +void radeon_gart_restore(struct radeon_device *rdev) +{ + int i, j, t; + u64 page_base; + + if (!rdev->gart.ptr) { + return; + } + for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) { + page_base = rdev->gart.pages_addr[i]; + for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { + radeon_gart_set_page(rdev, t, page_base); + page_base += RADEON_GPU_PAGE_SIZE; + } + } + mb(); + radeon_gart_tlb_flush(rdev); +} + +/** + * radeon_gart_init - init the driver info for managing the gart + * + * @rdev: radeon_device pointer + * + * Allocate the dummy page and init the gart driver info (all asics). + * Returns 0 for success, error for failure. + */ +int radeon_gart_init(struct radeon_device *rdev) +{ + int r, i; + + if (rdev->gart.pages) { + return 0; + } + /* We need PAGE_SIZE >= RADEON_GPU_PAGE_SIZE */ + if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) { + DRM_ERROR("Page size is smaller than GPU page size!\n"); + return -EINVAL; + } + r = radeon_dummy_page_init(rdev); + if (r) + return r; + /* Compute table size */ + rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; + rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; + DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", + rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); + /* Allocate pages table */ + rdev->gart.pages = malloc(sizeof(void *) * rdev->gart.num_cpu_pages, + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (rdev->gart.pages == NULL) { + radeon_gart_fini(rdev); + return -ENOMEM; + } + rdev->gart.pages_addr = malloc(sizeof(dma_addr_t) * + rdev->gart.num_cpu_pages, + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (rdev->gart.pages_addr == NULL) { + radeon_gart_fini(rdev); + return -ENOMEM; + } + /* set GART entry to point to the dummy page by default */ + for (i = 0; i < rdev->gart.num_cpu_pages; i++) { + rdev->gart.pages_addr[i] = rdev->dummy_page.addr; + } + return 0; +} + +/** + * radeon_gart_fini - tear down the driver info for managing the gart + * + * @rdev: radeon_device pointer + * + * Tear down the gart driver info and free the dummy page (all asics). + */ +void radeon_gart_fini(struct radeon_device *rdev) +{ + if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { + /* unbind pages */ + radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); + } + rdev->gart.ready = false; + free(rdev->gart.pages, DRM_MEM_DRIVER); + free(rdev->gart.pages_addr, DRM_MEM_DRIVER); + rdev->gart.pages = NULL; + rdev->gart.pages_addr = NULL; + + radeon_dummy_page_fini(rdev); +} + +/* + * GPUVM + * GPUVM is similar to the legacy gart on older asics, however + * rather than there being a single global gart table + * for the entire GPU, there are multiple VM page tables active + * at any given time. The VM page tables can contain a mix + * vram pages and system memory pages and system memory pages + * can be mapped as snooped (cached system pages) or unsnooped + * (uncached system pages). + * Each VM has an ID associated with it and there is a page table + * associated with each VMID. When execting a command buffer, + * the kernel tells the the ring what VMID to use for that command + * buffer. VMIDs are allocated dynamically as commands are submitted. + * The userspace drivers maintain their own address space and the kernel + * sets up their pages tables accordingly when they submit their + * command buffers and a VMID is assigned. + * Cayman/Trinity support up to 8 active VMs at any given time; + * SI supports 16. + */ + +/* + * vm helpers + * + * TODO bind a default page at vm initialization for default address + */ + +/** + * radeon_vm_num_pde - return the number of page directory entries + * + * @rdev: radeon_device pointer + * + * Calculate the number of page directory entries (cayman+). + */ +static unsigned radeon_vm_num_pdes(struct radeon_device *rdev) +{ + return rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE; +} + +/** + * radeon_vm_directory_size - returns the size of the page directory in bytes + * + * @rdev: radeon_device pointer + * + * Calculate the size of the page directory in bytes (cayman+). + */ +static unsigned radeon_vm_directory_size(struct radeon_device *rdev) +{ + return RADEON_GPU_PAGE_ALIGN(radeon_vm_num_pdes(rdev) * 8); +} + +/** + * radeon_vm_manager_init - init the vm manager + * + * @rdev: radeon_device pointer + * + * Init the vm manager (cayman+). + * Returns 0 for success, error for failure. + */ +int radeon_vm_manager_init(struct radeon_device *rdev) +{ + struct radeon_vm *vm; + struct radeon_bo_va *bo_va; + int r; + unsigned size; + + if (!rdev->vm_manager.enabled) { + /* allocate enough for 2 full VM pts */ + size = radeon_vm_directory_size(rdev); + size += rdev->vm_manager.max_pfn * 8; + size *= 2; + r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, + RADEON_GPU_PAGE_ALIGN(size), + RADEON_GEM_DOMAIN_VRAM); + if (r) { + dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", + (rdev->vm_manager.max_pfn * 8) >> 10); + return r; + } + + r = radeon_asic_vm_init(rdev); + if (r) + return r; + + rdev->vm_manager.enabled = true; + + r = radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); + if (r) + return r; + } + + /* restore page table */ + list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { + if (vm->page_directory == NULL) + continue; + + list_for_each_entry(bo_va, &vm->va, vm_list) { + bo_va->valid = false; + } + } + return 0; +} + +/** + * radeon_vm_free_pt - free the page table for a specific vm + * + * @rdev: radeon_device pointer + * @vm: vm to unbind + * + * Free the page table of a specific vm (cayman+). + * + * Global and local mutex must be lock! + */ +static void radeon_vm_free_pt(struct radeon_device *rdev, + struct radeon_vm *vm) +{ + struct radeon_bo_va *bo_va; + int i; + + if (!vm->page_directory) + return; + + list_del_init(&vm->list); + radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence); + + list_for_each_entry(bo_va, &vm->va, vm_list) { + bo_va->valid = false; + } + + if (vm->page_tables == NULL) + return; + + for (i = 0; i < radeon_vm_num_pdes(rdev); i++) + radeon_sa_bo_free(rdev, &vm->page_tables[i], vm->fence); + + free(vm->page_tables, DRM_MEM_DRIVER); +} + +/** + * radeon_vm_manager_fini - tear down the vm manager + * + * @rdev: radeon_device pointer + * + * Tear down the VM manager (cayman+). + */ +void radeon_vm_manager_fini(struct radeon_device *rdev) +{ + struct radeon_vm *vm, *tmp; + int i; + + if (!rdev->vm_manager.enabled) + return; + + sx_xlock(&rdev->vm_manager.lock); + /* free all allocated page tables */ + list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { + sx_xlock(&vm->mutex); + radeon_vm_free_pt(rdev, vm); + sx_xunlock(&vm->mutex); + } + for (i = 0; i < RADEON_NUM_VM; ++i) { + radeon_fence_unref(&rdev->vm_manager.active[i]); + } + radeon_asic_vm_fini(rdev); + sx_xunlock(&rdev->vm_manager.lock); + + radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); + radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); + rdev->vm_manager.enabled = false; +} + +/** + * radeon_vm_evict - evict page table to make room for new one + * + * @rdev: radeon_device pointer + * @vm: VM we want to allocate something for + * + * Evict a VM from the lru, making sure that it isn't @vm. (cayman+). + * Returns 0 for success, -ENOMEM for failure. + * + * Global and local mutex must be locked! + */ +static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) +{ + struct radeon_vm *vm_evict; + + if (list_empty(&rdev->vm_manager.lru_vm)) + return -ENOMEM; + + vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, + struct radeon_vm, list); + if (vm_evict == vm) + return -ENOMEM; + + sx_xlock(&vm_evict->mutex); + radeon_vm_free_pt(rdev, vm_evict); + sx_xunlock(&vm_evict->mutex); + return 0; +} + +/** + * radeon_vm_alloc_pt - allocates a page table for a VM + * + * @rdev: radeon_device pointer + * @vm: vm to bind + * + * Allocate a page table for the requested vm (cayman+). + * Returns 0 for success, error for failure. + * + * Global and local mutex must be locked! + */ +int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) +{ + unsigned pd_size, pts_size; + u64 *pd_addr; + int r; + + if (vm == NULL) { + return -EINVAL; + } + + if (vm->page_directory != NULL) { + return 0; + } + +retry: + pd_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); + r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, + &vm->page_directory, pd_size, + RADEON_GPU_PAGE_SIZE, false); + if (r == -ENOMEM) { + r = radeon_vm_evict(rdev, vm); + if (r) + return r; + goto retry; + + } else if (r) { + return r; + } + + vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->page_directory); + + /* Initially clear the page directory */ + pd_addr = radeon_sa_bo_cpu_addr(vm->page_directory); + memset(pd_addr, 0, pd_size); + + pts_size = radeon_vm_num_pdes(rdev) * sizeof(struct radeon_sa_bo *); + vm->page_tables = malloc(pts_size, DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + + if (vm->page_tables == NULL) { + DRM_ERROR("Cannot allocate memory for page table array\n"); + radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence); + return -ENOMEM; + } + + return 0; +} + +/** + * radeon_vm_add_to_lru - add VMs page table to LRU list + * + * @rdev: radeon_device pointer + * @vm: vm to add to LRU + * + * Add the allocated page table to the LRU list (cayman+). + * + * Global mutex must be locked! + */ +void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm) +{ + list_del_init(&vm->list); + list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); +} + +/** + * radeon_vm_grab_id - allocate the next free VMID + * + * @rdev: radeon_device pointer + * @vm: vm to allocate id for + * @ring: ring we want to submit job to + * + * Allocate an id for the vm (cayman+). + * Returns the fence we need to sync to (if any). + * + * Global and local mutex must be locked! + */ +struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, + struct radeon_vm *vm, int ring) +{ + struct radeon_fence *best[RADEON_NUM_RINGS] = {}; + unsigned choices[2] = {}; + unsigned i; + + /* check if the id is still valid */ + if (vm->fence && vm->fence == rdev->vm_manager.active[vm->id]) + return NULL; + + /* we definately need to flush */ + radeon_fence_unref(&vm->last_flush); + + /* skip over VMID 0, since it is the system VM */ + for (i = 1; i < rdev->vm_manager.nvm; ++i) { + struct radeon_fence *fence = rdev->vm_manager.active[i]; + + if (fence == NULL) { + /* found a free one */ + vm->id = i; + return NULL; + } + + if (radeon_fence_is_earlier(fence, best[fence->ring])) { + best[fence->ring] = fence; + choices[fence->ring == ring ? 0 : 1] = i; + } + } + + for (i = 0; i < 2; ++i) { + if (choices[i]) { + vm->id = choices[i]; + return rdev->vm_manager.active[choices[i]]; + } + } + + /* should never happen */ + panic("%s: failed to allocate next VMID", __func__); + return NULL; +} + +/** + * radeon_vm_fence - remember fence for vm + * + * @rdev: radeon_device pointer + * @vm: vm we want to fence + * @fence: fence to remember + * + * Fence the vm (cayman+). + * Set the fence used to protect page table and id. + * + * Global and local mutex must be locked! + */ +void radeon_vm_fence(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_fence *fence) +{ + radeon_fence_unref(&rdev->vm_manager.active[vm->id]); + rdev->vm_manager.active[vm->id] = radeon_fence_ref(fence); + + radeon_fence_unref(&vm->fence); + vm->fence = radeon_fence_ref(fence); +} + +/** + * radeon_vm_bo_find - find the bo_va for a specific vm & bo + * + * @vm: requested vm + * @bo: requested buffer object + * + * Find @bo inside the requested vm (cayman+). + * Search inside the @bos vm list for the requested vm + * Returns the found bo_va or NULL if none is found + * + * Object has to be reserved! + */ +struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm, + struct radeon_bo *bo) +{ + struct radeon_bo_va *bo_va; + + list_for_each_entry(bo_va, &bo->va, bo_list) { + if (bo_va->vm == vm) { + return bo_va; + } + } + return NULL; +} + +/** + * radeon_vm_bo_add - add a bo to a specific vm + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @bo: radeon buffer object + * + * Add @bo into the requested vm (cayman+). + * Add @bo to the list of bos associated with the vm + * Returns newly added bo_va or NULL for failure + * + * Object has to be reserved! + */ +struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_bo *bo) +{ + struct radeon_bo_va *bo_va; + + bo_va = malloc(sizeof(struct radeon_bo_va), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (bo_va == NULL) { + return NULL; + } + bo_va->vm = vm; + bo_va->bo = bo; + bo_va->soffset = 0; + bo_va->eoffset = 0; + bo_va->flags = 0; + bo_va->valid = false; + bo_va->ref_count = 1; + INIT_LIST_HEAD(&bo_va->bo_list); + INIT_LIST_HEAD(&bo_va->vm_list); + + sx_xlock(&vm->mutex); + list_add(&bo_va->vm_list, &vm->va); + list_add_tail(&bo_va->bo_list, &bo->va); + sx_xunlock(&vm->mutex); + + return bo_va; +} + +/** + * radeon_vm_bo_set_addr - set bos virtual address inside a vm + * + * @rdev: radeon_device pointer + * @bo_va: bo_va to store the address + * @soffset: requested offset of the buffer in the VM address space + * @flags: attributes of pages (read/write/valid/etc.) + * + * Set offset of @bo_va (cayman+). + * Validate and set the offset requested within the vm address space. + * Returns 0 for success, error for failure. + * + * Object has to be reserved! + */ +int radeon_vm_bo_set_addr(struct radeon_device *rdev, + struct radeon_bo_va *bo_va, + uint64_t soffset, + uint32_t flags) +{ + uint64_t size = radeon_bo_size(bo_va->bo); + uint64_t eoffset, last_offset = 0; + struct radeon_vm *vm = bo_va->vm; + struct radeon_bo_va *tmp; + struct list_head *head; + unsigned last_pfn; + + if (soffset) { + /* make sure object fit at this offset */ + eoffset = soffset + size; + if (soffset >= eoffset) { + return -EINVAL; + } + + last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; + if (last_pfn > rdev->vm_manager.max_pfn) { + dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", + last_pfn, rdev->vm_manager.max_pfn); + return -EINVAL; + } + + } else { + eoffset = last_pfn = 0; + } + + sx_xlock(&vm->mutex); + head = &vm->va; + last_offset = 0; + list_for_each_entry(tmp, &vm->va, vm_list) { + if (bo_va == tmp) { + /* skip over currently modified bo */ + continue; + } + + if (soffset >= last_offset && eoffset <= tmp->soffset) { + /* bo can be added before this one */ + break; + } + if (eoffset > tmp->soffset && soffset < tmp->eoffset) { + /* bo and tmp overlap, invalid offset */ + dev_err(rdev->dev, "bo %p va 0x%08X conflict with (bo %p 0x%08X 0x%08X)\n", + bo_va->bo, (unsigned)bo_va->soffset, tmp->bo, + (unsigned)tmp->soffset, (unsigned)tmp->eoffset); + sx_xunlock(&vm->mutex); + return -EINVAL; + } + last_offset = tmp->eoffset; + head = &tmp->vm_list; + } + + bo_va->soffset = soffset; + bo_va->eoffset = eoffset; + bo_va->flags = flags; + bo_va->valid = false; + list_move(&bo_va->vm_list, head); + + sx_xunlock(&vm->mutex); + return 0; +} + +/** + * radeon_vm_map_gart - get the physical address of a gart page + * + * @rdev: radeon_device pointer + * @addr: the unmapped addr + * + * Look up the physical address of the page that the pte resolves + * to (cayman+). + * Returns the physical address of the page. + */ +uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr) +{ + uint64_t result; + + /* page table offset */ + result = rdev->gart.pages_addr[addr >> PAGE_SHIFT]; + + /* in case cpu page size != gpu page size*/ + result |= addr & (~PAGE_MASK); + + return result; +} + +/** + * radeon_vm_update_pdes - make sure that page directory is valid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * + * Allocates new page tables if necessary + * and updates the page directory (cayman+). + * Returns 0 for success, error for failure. + * + * Global and local mutex must be locked! + */ +static int radeon_vm_update_pdes(struct radeon_device *rdev, + struct radeon_vm *vm, + uint64_t start, uint64_t end) +{ + static const uint32_t incr = RADEON_VM_PTE_COUNT * 8; + + uint64_t last_pde = ~0, last_pt = ~0; + unsigned count = 0; + uint64_t pt_idx; + int r; + + start = (start / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + end = (end / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + + /* walk over the address space and update the page directory */ + for (pt_idx = start; pt_idx <= end; ++pt_idx) { + uint64_t pde, pt; + + if (vm->page_tables[pt_idx]) + continue; + +retry: + r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, + &vm->page_tables[pt_idx], + RADEON_VM_PTE_COUNT * 8, + RADEON_GPU_PAGE_SIZE, false); + + if (r == -ENOMEM) { + r = radeon_vm_evict(rdev, vm); + if (r) + return r; + goto retry; + } else if (r) { + return r; + } + + pde = vm->pd_gpu_addr + pt_idx * 8; + + pt = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); + + if (((last_pde + 8 * count) != pde) || + ((last_pt + incr * count) != pt)) { + + if (count) { + radeon_asic_vm_set_page(rdev, last_pde, + last_pt, count, incr, + RADEON_VM_PAGE_VALID); + } + + count = 1; + last_pde = pde; + last_pt = pt; + } else { + ++count; + } + } + + if (count) { + radeon_asic_vm_set_page(rdev, last_pde, last_pt, count, + incr, RADEON_VM_PAGE_VALID); + + } + + return 0; +} + +/** + * radeon_vm_update_ptes - make sure that page tables are valid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * @dst: destination address to map to + * @flags: mapping flags + * + * Update the page tables in the range @start - @end (cayman+). + * + * Global and local mutex must be locked! + */ +static void radeon_vm_update_ptes(struct radeon_device *rdev, + struct radeon_vm *vm, + uint64_t start, uint64_t end, + uint64_t dst, uint32_t flags) +{ + static const uint64_t mask = RADEON_VM_PTE_COUNT - 1; + + uint64_t last_pte = ~0, last_dst = ~0; + unsigned count = 0; + uint64_t addr; + + start = start / RADEON_GPU_PAGE_SIZE; + end = end / RADEON_GPU_PAGE_SIZE; + + /* walk over the address space and update the page tables */ + for (addr = start; addr < end; ) { + uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE; + unsigned nptes; + uint64_t pte; + + if ((addr & ~mask) == (end & ~mask)) + nptes = end - addr; + else + nptes = RADEON_VM_PTE_COUNT - (addr & mask); + + pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); + pte += (addr & mask) * 8; + + if ((last_pte + 8 * count) != pte) { + + if (count) { + radeon_asic_vm_set_page(rdev, last_pte, + last_dst, count, + RADEON_GPU_PAGE_SIZE, + flags); + } + + count = nptes; + last_pte = pte; + last_dst = dst; + } else { + count += nptes; + } + + addr += nptes; + dst += nptes * RADEON_GPU_PAGE_SIZE; + } + + if (count) { + radeon_asic_vm_set_page(rdev, last_pte, last_dst, count, + RADEON_GPU_PAGE_SIZE, flags); + } +} + +/** + * radeon_vm_bo_update_pte - map a bo into the vm page table + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @bo: radeon buffer object + * @mem: ttm mem + * + * Fill in the page table entries for @bo (cayman+). + * Returns 0 for success, -EINVAL for failure. + * + * Object have to be reserved & global and local mutex must be locked! + */ +int radeon_vm_bo_update_pte(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_bo *bo, + struct ttm_mem_reg *mem) +{ + unsigned ridx = rdev->asic->vm.pt_ring_index; + struct radeon_ring *ring = &rdev->ring[ridx]; + struct radeon_semaphore *sem = NULL; + struct radeon_bo_va *bo_va; + unsigned nptes, npdes, ndw; + uint64_t addr; + int r; + + /* nothing to do if vm isn't bound */ + if (vm->page_directory == NULL) + return 0; + + bo_va = radeon_vm_bo_find(vm, bo); + if (bo_va == NULL) { + dev_err(rdev->dev, "bo %p not in vm %p\n", bo, vm); + return -EINVAL; + } + + if (!bo_va->soffset) { + dev_err(rdev->dev, "bo %p don't has a mapping in vm %p\n", + bo, vm); + return -EINVAL; + } + + if ((bo_va->valid && mem) || (!bo_va->valid && mem == NULL)) + return 0; + + bo_va->flags &= ~RADEON_VM_PAGE_VALID; + bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM; + if (mem) { + addr = mem->start << PAGE_SHIFT; + if (mem->mem_type != TTM_PL_SYSTEM) { + bo_va->flags |= RADEON_VM_PAGE_VALID; + bo_va->valid = true; + } + if (mem->mem_type == TTM_PL_TT) { + bo_va->flags |= RADEON_VM_PAGE_SYSTEM; + } else { + addr += rdev->vm_manager.vram_base_offset; + } + } else { + addr = 0; + bo_va->valid = false; + } + + if (vm->fence && radeon_fence_signaled(vm->fence)) { + radeon_fence_unref(&vm->fence); + } + + if (vm->fence && vm->fence->ring != ridx) { + r = radeon_semaphore_create(rdev, &sem); + if (r) { + return r; + } + } + + nptes = radeon_bo_ngpu_pages(bo); + + /* assume two extra pdes in case the mapping overlaps the borders */ + npdes = (nptes >> RADEON_VM_BLOCK_SIZE) + 2; + + /* estimate number of dw needed */ + /* semaphore, fence and padding */ + ndw = 32; + + if (RADEON_VM_BLOCK_SIZE > 11) + /* reserve space for one header for every 2k dwords */ + ndw += (nptes >> 11) * 4; + else + /* reserve space for one header for + every (1 << BLOCK_SIZE) entries */ + ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4; + + /* reserve space for pte addresses */ + ndw += nptes * 2; + + /* reserve space for one header for every 2k dwords */ + ndw += (npdes >> 11) * 4; + + /* reserve space for pde addresses */ + ndw += npdes * 2; + + r = radeon_ring_lock(rdev, ring, ndw); + if (r) { + return r; + } + + if (sem && radeon_fence_need_sync(vm->fence, ridx)) { + radeon_semaphore_sync_rings(rdev, sem, vm->fence->ring, ridx); + radeon_fence_note_sync(vm->fence, ridx); + } + + r = radeon_vm_update_pdes(rdev, vm, bo_va->soffset, bo_va->eoffset); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + + radeon_vm_update_ptes(rdev, vm, bo_va->soffset, bo_va->eoffset, + addr, bo_va->flags); + + radeon_fence_unref(&vm->fence); + r = radeon_fence_emit(rdev, &vm->fence, ridx); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + radeon_ring_unlock_commit(rdev, ring); + radeon_semaphore_free(rdev, &sem, vm->fence); + radeon_fence_unref(&vm->last_flush); + + return 0; +} + +/** + * radeon_vm_bo_rmv - remove a bo to a specific vm + * + * @rdev: radeon_device pointer + * @bo_va: requested bo_va + * + * Remove @bo_va->bo from the requested vm (cayman+). + * Remove @bo_va->bo from the list of bos associated with the bo_va->vm and + * remove the ptes for @bo_va in the page table. + * Returns 0 for success. + * + * Object have to be reserved! + */ +int radeon_vm_bo_rmv(struct radeon_device *rdev, + struct radeon_bo_va *bo_va) +{ + int r; + + sx_xlock(&rdev->vm_manager.lock); + sx_xlock(&bo_va->vm->mutex); + r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL); + sx_xunlock(&rdev->vm_manager.lock); + list_del(&bo_va->vm_list); + sx_xunlock(&bo_va->vm->mutex); + list_del(&bo_va->bo_list); + + free(bo_va, DRM_MEM_DRIVER); + return r; +} + +/** + * radeon_vm_bo_invalidate - mark the bo as invalid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @bo: radeon buffer object + * + * Mark @bo as invalid (cayman+). + */ +void radeon_vm_bo_invalidate(struct radeon_device *rdev, + struct radeon_bo *bo) +{ + struct radeon_bo_va *bo_va; + + list_for_each_entry(bo_va, &bo->va, bo_list) { + bo_va->valid = false; + } +} + +/** + * radeon_vm_init - initialize a vm instance + * + * @rdev: radeon_device pointer + * @vm: requested vm + * + * Init @vm fields (cayman+). + */ +void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) +{ + vm->id = 0; + vm->fence = NULL; + sx_init(&vm->mutex, "drm__radeon_vm__mutex"); + INIT_LIST_HEAD(&vm->list); + INIT_LIST_HEAD(&vm->va); +} + +/** + * radeon_vm_fini - tear down a vm instance + * + * @rdev: radeon_device pointer + * @vm: requested vm + * + * Tear down @vm (cayman+). + * Unbind the VM and remove all bos from the vm bo list + */ +void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) +{ + struct radeon_bo_va *bo_va, *tmp; + int r; + + sx_xlock(&rdev->vm_manager.lock); + sx_xlock(&vm->mutex); + radeon_vm_free_pt(rdev, vm); + sx_xunlock(&rdev->vm_manager.lock); + + if (!list_empty(&vm->va)) { + dev_err(rdev->dev, "still active bo inside vm\n"); + } + list_for_each_entry_safe(bo_va, tmp, &vm->va, vm_list) { + list_del_init(&bo_va->vm_list); + r = radeon_bo_reserve(bo_va->bo, false); + if (!r) { + list_del_init(&bo_va->bo_list); + radeon_bo_unreserve(bo_va->bo); + free(bo_va, DRM_MEM_DRIVER); + } + } + radeon_fence_unref(&vm->fence); + radeon_fence_unref(&vm->last_flush); + sx_xunlock(&vm->mutex); +} diff --git a/sys/dev/drm2/radeon/radeon_gem.c b/sys/dev/drm2/radeon/radeon_gem.c new file mode 100644 index 00000000000..390298edfd4 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_gem.c @@ -0,0 +1,585 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#include "radeon_gem.h" + +int radeon_gem_object_init(struct drm_gem_object *obj) +{ + panic("radeon_gem_object_init() must not be called"); + + return 0; +} + +void radeon_gem_object_free(struct drm_gem_object *gobj) +{ + struct radeon_bo *robj = gem_to_radeon_bo(gobj); + + if (robj) { +#ifdef DUMBBELL_WIP + if (robj->gem_base.import_attach) + drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg); +#endif /* DUMBBELL_WIP */ + radeon_bo_unref(&robj); + } +} + +int radeon_gem_object_create(struct radeon_device *rdev, int size, + int alignment, int initial_domain, + bool discardable, bool kernel, + struct drm_gem_object **obj) +{ + struct radeon_bo *robj; + unsigned long max_size; + int r; + + *obj = NULL; + /* At least align on page size */ + if (alignment < PAGE_SIZE) { + alignment = PAGE_SIZE; + } + + /* maximun bo size is the minimun btw visible vram and gtt size */ + max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); + if (size > max_size) { + DRM_ERROR("%s:%d alloc size %dMb bigger than %ldMb limit\n", + __func__, __LINE__, size >> 20, max_size >> 20); + return -ENOMEM; + } + +retry: + r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); + if (r) { + if (r != -ERESTART) { + if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { + initial_domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } + DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", + size, initial_domain, alignment, r); + } + return r; + } + *obj = &robj->gem_base; + + sx_xlock(&rdev->gem.mutex); + list_add_tail(&robj->list, &rdev->gem.objects); + sx_xunlock(&rdev->gem.mutex); + + return 0; +} + +static int radeon_gem_set_domain(struct drm_gem_object *gobj, + uint32_t rdomain, uint32_t wdomain) +{ + struct radeon_bo *robj; + uint32_t domain; + int r; + + /* FIXME: reeimplement */ + robj = gem_to_radeon_bo(gobj); + /* work out where to validate the buffer to */ + domain = wdomain; + if (!domain) { + domain = rdomain; + } + if (!domain) { + /* Do nothings */ + DRM_ERROR("Set domain without domain !\n"); + return 0; + } + if (domain == RADEON_GEM_DOMAIN_CPU) { + /* Asking for cpu access wait for object idle */ + r = radeon_bo_wait(robj, NULL, false); + if (r) { + DRM_ERROR("Failed to wait for object !\n"); + return r; + } + } + return 0; +} + +int radeon_gem_init(struct radeon_device *rdev) +{ + INIT_LIST_HEAD(&rdev->gem.objects); + return 0; +} + +void radeon_gem_fini(struct radeon_device *rdev) +{ + radeon_bo_force_delete(rdev); +} + +/* + * Call from drm_gem_handle_create which appear in both new and open ioctl + * case. + */ +int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) +{ + struct radeon_bo *rbo = gem_to_radeon_bo(obj); + struct radeon_device *rdev = rbo->rdev; + struct radeon_fpriv *fpriv = file_priv->driver_priv; + struct radeon_vm *vm = &fpriv->vm; + struct radeon_bo_va *bo_va; + int r; + + if (rdev->family < CHIP_CAYMAN) { + return 0; + } + + r = radeon_bo_reserve(rbo, false); + if (r) { + return r; + } + + bo_va = radeon_vm_bo_find(vm, rbo); + if (!bo_va) { + bo_va = radeon_vm_bo_add(rdev, vm, rbo); + } else { + ++bo_va->ref_count; + } + radeon_bo_unreserve(rbo); + + return 0; +} + +void radeon_gem_object_close(struct drm_gem_object *obj, + struct drm_file *file_priv) +{ + struct radeon_bo *rbo = gem_to_radeon_bo(obj); + struct radeon_device *rdev = rbo->rdev; + struct radeon_fpriv *fpriv = file_priv->driver_priv; + struct radeon_vm *vm = &fpriv->vm; + struct radeon_bo_va *bo_va; + int r; + + if (rdev->family < CHIP_CAYMAN) { + return; + } + + r = radeon_bo_reserve(rbo, true); + if (r) { + dev_err(rdev->dev, "leaking bo va because " + "we fail to reserve bo (%d)\n", r); + return; + } + bo_va = radeon_vm_bo_find(vm, rbo); + if (bo_va) { + if (--bo_va->ref_count == 0) { + radeon_vm_bo_rmv(rdev, bo_va); + } + } + radeon_bo_unreserve(rbo); +} + +static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) +{ + if (r == -EDEADLK) { + r = radeon_gpu_reset(rdev); + if (!r) + r = -EAGAIN; + } + return r; +} + +/* + * GEM ioctls. + */ +int radeon_gem_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_gem_info *args = data; + struct ttm_mem_type_manager *man; + unsigned i; + + man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + + args->vram_size = rdev->mc.real_vram_size; + args->vram_visible = (u64)man->size << PAGE_SHIFT; + if (rdev->stollen_vga_memory) + args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); + args->vram_visible -= radeon_fbdev_total_size(rdev); + args->gart_size = rdev->mc.gtt_size - 4096 - RADEON_IB_POOL_SIZE*64*1024; + for(i = 0; i < RADEON_NUM_RINGS; ++i) + args->gart_size -= rdev->ring[i].ring_size; + return 0; +} + +int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + /* TODO: implement */ + DRM_ERROR("unimplemented %s\n", __func__); + return -ENOSYS; +} + +int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + /* TODO: implement */ + DRM_ERROR("unimplemented %s\n", __func__); + return -ENOSYS; +} + +int radeon_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_gem_create *args = data; + struct drm_gem_object *gobj; + uint32_t handle; + int r; + + sx_slock(&rdev->exclusive_lock); + /* create a gem object to contain this object in */ + args->size = roundup(args->size, PAGE_SIZE); + r = radeon_gem_object_create(rdev, args->size, args->alignment, + args->initial_domain, false, + false, &gobj); + if (r) { + sx_sunlock(&rdev->exclusive_lock); + r = radeon_gem_handle_lockup(rdev, r); + return r; + } + handle = 0; + r = drm_gem_handle_create(filp, gobj, &handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(gobj); + if (r) { + sx_sunlock(&rdev->exclusive_lock); + r = radeon_gem_handle_lockup(rdev, r); + return r; + } + args->handle = handle; + sx_sunlock(&rdev->exclusive_lock); + return 0; +} + +int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + /* transition the BO to a domain - + * just validate the BO into a certain domain */ + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_gem_set_domain *args = data; + struct drm_gem_object *gobj; + struct radeon_bo *robj; + int r; + + /* for now if someone requests domain CPU - + * just make sure the buffer is finished with */ + sx_slock(&rdev->exclusive_lock); + + /* just do a BO wait for now */ + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) { + sx_sunlock(&rdev->exclusive_lock); + return -ENOENT; + } + robj = gem_to_radeon_bo(gobj); + + r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); + + drm_gem_object_unreference_unlocked(gobj); + sx_sunlock(&rdev->exclusive_lock); + r = radeon_gem_handle_lockup(robj->rdev, r); + return r; +} + +int radeon_mode_dumb_mmap(struct drm_file *filp, + struct drm_device *dev, + uint32_t handle, uint64_t *offset_p) +{ + struct drm_gem_object *gobj; + struct radeon_bo *robj; + + gobj = drm_gem_object_lookup(dev, filp, handle); + if (gobj == NULL) { + return -ENOENT; + } + robj = gem_to_radeon_bo(gobj); + *offset_p = radeon_bo_mmap_offset(robj); + drm_gem_object_unreference_unlocked(gobj); + return 0; +} + +int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_mmap *args = data; + + return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr); +} + +int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_gem_busy *args = data; + struct drm_gem_object *gobj; + struct radeon_bo *robj; + int r; + uint32_t cur_placement = 0; + + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) { + return -ENOENT; + } + robj = gem_to_radeon_bo(gobj); + r = radeon_bo_wait(robj, &cur_placement, true); + switch (cur_placement) { + case TTM_PL_VRAM: + args->domain = RADEON_GEM_DOMAIN_VRAM; + break; + case TTM_PL_TT: + args->domain = RADEON_GEM_DOMAIN_GTT; + break; + case TTM_PL_SYSTEM: + args->domain = RADEON_GEM_DOMAIN_CPU; + default: + break; + } + drm_gem_object_unreference_unlocked(gobj); + r = radeon_gem_handle_lockup(rdev, r); + return r; +} + +int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_gem_wait_idle *args = data; + struct drm_gem_object *gobj; + struct radeon_bo *robj; + int r; + + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) { + return -ENOENT; + } + robj = gem_to_radeon_bo(gobj); + r = radeon_bo_wait(robj, NULL, false); + /* callback hw specific functions if any */ + if (rdev->asic->ioctl_wait_idle) + robj->rdev->asic->ioctl_wait_idle(rdev, robj); + drm_gem_object_unreference_unlocked(gobj); + r = radeon_gem_handle_lockup(rdev, r); + return r; +} + +int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_set_tiling *args = data; + struct drm_gem_object *gobj; + struct radeon_bo *robj; + int r = 0; + + DRM_DEBUG("%d \n", args->handle); + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) + return -ENOENT; + robj = gem_to_radeon_bo(gobj); + r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); + drm_gem_object_unreference_unlocked(gobj); + return r; +} + +int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_get_tiling *args = data; + struct drm_gem_object *gobj; + struct radeon_bo *rbo; + int r = 0; + + DRM_DEBUG("\n"); + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) + return -ENOENT; + rbo = gem_to_radeon_bo(gobj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + goto out; + radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch); + radeon_bo_unreserve(rbo); +out: + drm_gem_object_unreference_unlocked(gobj); + return r; +} + +int radeon_gem_va_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_va *args = data; + struct drm_gem_object *gobj; + struct radeon_device *rdev = dev->dev_private; + struct radeon_fpriv *fpriv = filp->driver_priv; + struct radeon_bo *rbo; + struct radeon_bo_va *bo_va; + u32 invalid_flags; + int r = 0; + + if (!rdev->vm_manager.enabled) { + args->operation = RADEON_VA_RESULT_ERROR; + return -ENOTTY; + } + + /* !! DONT REMOVE !! + * We don't support vm_id yet, to be sure we don't have have broken + * userspace, reject anyone trying to use non 0 value thus moving + * forward we can use those fields without breaking existant userspace + */ + if (args->vm_id) { + args->operation = RADEON_VA_RESULT_ERROR; + return -EINVAL; + } + + if (args->offset < RADEON_VA_RESERVED_SIZE) { + dev_err(dev->device, + "offset 0x%lX is in reserved area 0x%X\n", + (unsigned long)args->offset, + RADEON_VA_RESERVED_SIZE); + args->operation = RADEON_VA_RESULT_ERROR; + return -EINVAL; + } + + /* don't remove, we need to enforce userspace to set the snooped flag + * otherwise we will endup with broken userspace and we won't be able + * to enable this feature without adding new interface + */ + invalid_flags = RADEON_VM_PAGE_VALID | RADEON_VM_PAGE_SYSTEM; + if ((args->flags & invalid_flags)) { + dev_err(dev->device, "invalid flags 0x%08X vs 0x%08X\n", + args->flags, invalid_flags); + args->operation = RADEON_VA_RESULT_ERROR; + return -EINVAL; + } + if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) { + dev_err(dev->device, "only supported snooped mapping for now\n"); + args->operation = RADEON_VA_RESULT_ERROR; + return -EINVAL; + } + + switch (args->operation) { + case RADEON_VA_MAP: + case RADEON_VA_UNMAP: + break; + default: + dev_err(dev->device, "unsupported operation %d\n", + args->operation); + args->operation = RADEON_VA_RESULT_ERROR; + return -EINVAL; + } + + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) { + args->operation = RADEON_VA_RESULT_ERROR; + return -ENOENT; + } + rbo = gem_to_radeon_bo(gobj); + r = radeon_bo_reserve(rbo, false); + if (r) { + args->operation = RADEON_VA_RESULT_ERROR; + drm_gem_object_unreference_unlocked(gobj); + return r; + } + bo_va = radeon_vm_bo_find(&fpriv->vm, rbo); + if (!bo_va) { + args->operation = RADEON_VA_RESULT_ERROR; + drm_gem_object_unreference_unlocked(gobj); + return -ENOENT; + } + + switch (args->operation) { + case RADEON_VA_MAP: + if (bo_va->soffset) { + args->operation = RADEON_VA_RESULT_VA_EXIST; + args->offset = bo_va->soffset; + goto out; + } + r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, args->flags); + break; + case RADEON_VA_UNMAP: + r = radeon_vm_bo_set_addr(rdev, bo_va, 0, 0); + break; + default: + break; + } + args->operation = RADEON_VA_RESULT_OK; + if (r) { + args->operation = RADEON_VA_RESULT_ERROR; + } +out: + radeon_bo_unreserve(rbo); + drm_gem_object_unreference_unlocked(gobj); + return r; +} + +int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_gem_object *gobj; + uint32_t handle; + int r; + + args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); + args->size = args->pitch * args->height; + args->size = roundup2(args->size, PAGE_SIZE); + + r = radeon_gem_object_create(rdev, args->size, 0, + RADEON_GEM_DOMAIN_VRAM, + false, ttm_bo_type_device, + &gobj); + if (r) + return -ENOMEM; + + r = drm_gem_handle_create(file_priv, gobj, &handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(gobj); + if (r) { + return r; + } + args->handle = handle; + return 0; +} + +int radeon_mode_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle) +{ + return drm_gem_handle_delete(file_priv, handle); +} diff --git a/sys/dev/drm2/radeon/radeon_gem.h b/sys/dev/drm2/radeon/radeon_gem.h new file mode 100644 index 00000000000..c7edd503f21 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_gem.h @@ -0,0 +1,17 @@ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_GEM_H__ +#define __RADEON_GEM_H__ + +#include + +int radeon_gem_object_init(struct drm_gem_object *obj); +void radeon_gem_object_free(struct drm_gem_object *obj); +int radeon_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file_priv); +void radeon_gem_object_close(struct drm_gem_object *obj, + struct drm_file *file_priv); + +#endif /* !defined(__RADEON_GEM_H__) */ diff --git a/sys/dev/drm2/radeon/radeon_i2c.c b/sys/dev/drm2/radeon/radeon_i2c.c new file mode 100644 index 00000000000..917286a14c1 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_i2c.c @@ -0,0 +1,1384 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include "radeon.h" +#include "atom.h" +#include "iicbus_if.h" +#include "iicbb_if.h" + +/** + * radeon_ddc_probe + * + */ +bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) +{ + u8 out = 0x0; + u8 buf[8]; + int ret; + struct iic_msg msgs[] = { + { + .slave = DDC_ADDR << 1, + .flags = 0, + .len = 1, + .buf = &out, + }, + { + .slave = DDC_ADDR << 1, + .flags = IIC_M_RD, + .len = 8, + .buf = buf, + } + }; + + /* on hw with routers, select right port */ + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + + if (use_aux) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + ret = iicbus_transfer(dig->dp_i2c_bus->adapter, msgs, 2); + } else { + ret = iicbus_transfer(radeon_connector->ddc_bus->adapter, msgs, 2); + } + + if (ret != 0) + /* Couldn't find an accessible DDC on this connector */ + return false; + /* Probe also for valid EDID header + * EDID header starts with: + * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00. + * Only the first 6 bytes must be valid as + * drm_edid_block_valid() can fix the last 2 bytes */ + if (drm_edid_header_is_valid(buf) < 6) { + /* Couldn't find an accessible EDID on this + * connector */ + return false; + } + return true; +} + +/* bit banging i2c */ + +static int radeon_iicbb_pre_xfer(device_t dev) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + uint32_t temp; + + /* RV410 appears to have a bug where the hw i2c in reset + * holds the i2c port in a bad state - switch hw i2c away before + * doing DDC - do this for all r200s/r300s/r400s for safety sake + */ + if (rec->hw_capable) { + if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) { + u32 reg; + + if (rdev->family >= CHIP_RV350) + reg = RADEON_GPIO_MONID; + else if ((rdev->family == CHIP_R300) || + (rdev->family == CHIP_R350)) + reg = RADEON_GPIO_DVI_DDC; + else + reg = RADEON_GPIO_CRT2_DDC; + + sx_xlock(&rdev->dc_hw_i2c_mutex); + if (rec->a_clk_reg == reg) { + WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | + R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1))); + } else { + WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | + R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); + } + sx_xunlock(&rdev->dc_hw_i2c_mutex); + } + } + + /* switch the pads to ddc mode */ + if (ASIC_IS_DCE3(rdev) && rec->hw_capable) { + temp = RREG32(rec->mask_clk_reg); + temp &= ~(1 << 16); + WREG32(rec->mask_clk_reg, temp); + } + + /* clear the output pin values */ + temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask; + WREG32(rec->a_clk_reg, temp); + + temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask; + WREG32(rec->a_data_reg, temp); + + /* set the pins to input */ + temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask; + WREG32(rec->en_clk_reg, temp); + + temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask; + WREG32(rec->en_data_reg, temp); + + /* mask the gpio pins for software use */ + temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask; + WREG32(rec->mask_clk_reg, temp); + temp = RREG32(rec->mask_clk_reg); + + temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask; + WREG32(rec->mask_data_reg, temp); + temp = RREG32(rec->mask_data_reg); + + return 0; +} + +static void radeon_iicbb_post_xfer(device_t dev) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + uint32_t temp; + + /* unmask the gpio pins for software use */ + temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask; + WREG32(rec->mask_clk_reg, temp); + temp = RREG32(rec->mask_clk_reg); + + temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask; + WREG32(rec->mask_data_reg, temp); + temp = RREG32(rec->mask_data_reg); +} + +static int radeon_iicbb_get_clock(device_t dev) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + uint32_t val; + + /* read the value off the pin */ + val = RREG32(rec->y_clk_reg); + val &= rec->y_clk_mask; + + return (val != 0); +} + + +static int radeon_iicbb_get_data(device_t dev) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + uint32_t val; + + /* read the value off the pin */ + val = RREG32(rec->y_data_reg); + val &= rec->y_data_mask; + + return (val != 0); +} + +static void radeon_iicbb_set_clock(device_t dev, int clock) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + uint32_t val; + + /* set pin direction */ + val = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask; + val |= clock ? 0 : rec->en_clk_mask; + WREG32(rec->en_clk_reg, val); +} + +static void radeon_iicbb_set_data(device_t dev, int data) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + uint32_t val; + + /* set pin direction */ + val = RREG32(rec->en_data_reg) & ~rec->en_data_mask; + val |= data ? 0 : rec->en_data_mask; + WREG32(rec->en_data_reg, val); +} + +static int +radeon_iicbb_probe(device_t dev) +{ + + return (BUS_PROBE_DEFAULT); +} + +static int +radeon_iicbb_attach(device_t dev) +{ + struct radeon_i2c_chan *i2c; + device_t iic_dev; + + i2c = device_get_softc(dev); + device_set_desc(dev, i2c->name); + + /* add generic bit-banging code */ + iic_dev = device_add_child(dev, "iicbb", -1); + if (iic_dev == NULL) + return (ENXIO); + device_quiet(iic_dev); + + /* attach and probe added child */ + bus_generic_attach(dev); + + return (0); +} + +static int +radeon_iicbb_detach(device_t dev) +{ + + /* detach bit-banding code. */ + bus_generic_detach(dev); + + /* delete bit-banding code. */ + device_delete_children(dev); + return (0); +} + +static int +radeon_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +{ + + /* Not sure what to do here. */ + return 0; +} + +static device_method_t radeon_iicbb_methods[] = { + DEVMETHOD(device_probe, radeon_iicbb_probe), + DEVMETHOD(device_attach, radeon_iicbb_attach), + DEVMETHOD(device_detach, radeon_iicbb_detach), + + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_print_child, bus_generic_print_child), + + DEVMETHOD(iicbb_reset, radeon_iicbb_reset), + DEVMETHOD(iicbb_pre_xfer, radeon_iicbb_pre_xfer), + DEVMETHOD(iicbb_post_xfer, radeon_iicbb_post_xfer), + DEVMETHOD(iicbb_setsda, radeon_iicbb_set_data), + DEVMETHOD(iicbb_setscl, radeon_iicbb_set_clock), + DEVMETHOD(iicbb_getsda, radeon_iicbb_get_data), + DEVMETHOD(iicbb_getscl, radeon_iicbb_get_clock), + DEVMETHOD_END +}; + +static driver_t radeon_iicbb_driver = { + "radeon_iicbb", + radeon_iicbb_methods, + 0 /* softc will be allocated by parent */ +}; +static devclass_t radeon_iicbb_devclass; +DRIVER_MODULE_ORDERED(radeon_iicbb, drmn, radeon_iicbb_driver, + radeon_iicbb_devclass, 0, 0, SI_ORDER_FIRST); +DRIVER_MODULE(iicbb, radeon_iicbb, iicbb_driver, iicbb_devclass, 0, 0); + +/* hw i2c */ + +static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) +{ + u32 sclk = rdev->pm.current_sclk; + u32 prescale = 0; + u32 nm; + u8 n, m, loop; + int i2c_clock; + + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_R200: + case CHIP_RV250: + case CHIP_RS300: + case CHIP_RV280: + case CHIP_R300: + case CHIP_R350: + case CHIP_RV350: + i2c_clock = 60; + nm = (sclk * 10) / (i2c_clock * 4); + for (loop = 1; loop < 255; loop++) { + if ((nm / loop) < loop) + break; + } + n = loop - 1; + m = loop - 2; + prescale = m | (n << 8); + break; + case CHIP_RV380: + case CHIP_RS400: + case CHIP_RS480: + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; + break; + case CHIP_RS600: + case CHIP_RS690: + case CHIP_RS740: + /* todo */ + break; + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV530: + case CHIP_RV560: + case CHIP_RV570: + case CHIP_R580: + i2c_clock = 50; + if (rdev->family == CHIP_R520) + prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock)); + else + prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; + break; + case CHIP_R600: + case CHIP_RV610: + case CHIP_RV630: + case CHIP_RV670: + /* todo */ + break; + case CHIP_RV620: + case CHIP_RV635: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + case CHIP_RV740: + /* todo */ + break; + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + /* todo */ + break; + default: + DRM_ERROR("i2c: unhandled radeon chip\n"); + break; + } + return prescale; +} + + +/* hw i2c engine for r1xx-4xx hardware + * hw can buffer up to 15 bytes + */ +static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, + struct iic_msg *msgs, int num) +{ + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + struct iic_msg *p; + int i, j, k, ret = 0; + u32 prescale; + u32 i2c_cntl_0, i2c_cntl_1, i2c_data; + u32 tmp, reg; + + sx_xlock(&rdev->dc_hw_i2c_mutex); + /* take the pm lock since we need a constant sclk */ + sx_xlock(&rdev->pm.mutex); + + prescale = radeon_get_i2c_prescale(rdev); + + reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) | + RADEON_I2C_DRIVE_EN | + RADEON_I2C_START | + RADEON_I2C_STOP | + RADEON_I2C_GO); + + if (rdev->is_atom_bios) { + tmp = RREG32(RADEON_BIOS_6_SCRATCH); + WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE); + } + + if (rec->mm_i2c) { + i2c_cntl_0 = RADEON_I2C_CNTL_0; + i2c_cntl_1 = RADEON_I2C_CNTL_1; + i2c_data = RADEON_I2C_DATA; + } else { + i2c_cntl_0 = RADEON_DVI_I2C_CNTL_0; + i2c_cntl_1 = RADEON_DVI_I2C_CNTL_1; + i2c_data = RADEON_DVI_I2C_DATA; + + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_RS300: + switch (rec->mask_clk_reg) { + case RADEON_GPIO_DVI_DDC: + /* no gpio select bit */ + break; + default: + DRM_ERROR("gpio not supported with hw i2c\n"); + ret = EINVAL; + goto done; + } + break; + case CHIP_R200: + /* only bit 4 on r200 */ + switch (rec->mask_clk_reg) { + case RADEON_GPIO_DVI_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); + break; + case RADEON_GPIO_MONID: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); + break; + default: + DRM_ERROR("gpio not supported with hw i2c\n"); + ret = EINVAL; + goto done; + } + break; + case CHIP_RV250: + case CHIP_RV280: + /* bits 3 and 4 */ + switch (rec->mask_clk_reg) { + case RADEON_GPIO_DVI_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); + break; + case RADEON_GPIO_VGA_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2); + break; + case RADEON_GPIO_CRT2_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); + break; + default: + DRM_ERROR("gpio not supported with hw i2c\n"); + ret = EINVAL; + goto done; + } + break; + case CHIP_R300: + case CHIP_R350: + /* only bit 4 on r300/r350 */ + switch (rec->mask_clk_reg) { + case RADEON_GPIO_VGA_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); + break; + case RADEON_GPIO_DVI_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); + break; + default: + DRM_ERROR("gpio not supported with hw i2c\n"); + ret = EINVAL; + goto done; + } + break; + case CHIP_RV350: + case CHIP_RV380: + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + case CHIP_RS400: + case CHIP_RS480: + /* bits 3 and 4 */ + switch (rec->mask_clk_reg) { + case RADEON_GPIO_VGA_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); + break; + case RADEON_GPIO_DVI_DDC: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2); + break; + case RADEON_GPIO_MONID: + reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); + break; + default: + DRM_ERROR("gpio not supported with hw i2c\n"); + ret = EINVAL; + goto done; + } + break; + default: + DRM_ERROR("unsupported asic\n"); + ret = EINVAL; + goto done; + break; + } + } + + /* check for bus probe */ + p = &msgs[0]; + if ((num == 1) && (p->len == 0)) { + WREG32(i2c_cntl_0, (RADEON_I2C_DONE | + RADEON_I2C_NACK | + RADEON_I2C_HALT | + RADEON_I2C_SOFT_RST)); + WREG32(i2c_data, (p->slave << 1) & 0xff); + WREG32(i2c_data, 0); + WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | + (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | + RADEON_I2C_EN | + (48 << RADEON_I2C_TIME_LIMIT_SHIFT))); + WREG32(i2c_cntl_0, reg); + for (k = 0; k < 32; k++) { + DRM_UDELAY(10); + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_GO) + continue; + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_DONE) + break; + else { + DRM_DEBUG("i2c write error 0x%08x\n", tmp); + WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); + ret = EIO; + goto done; + } + } + goto done; + } + + for (i = 0; i < num; i++) { + p = &msgs[i]; + for (j = 0; j < p->len; j++) { + if (p->flags & IIC_M_RD) { + WREG32(i2c_cntl_0, (RADEON_I2C_DONE | + RADEON_I2C_NACK | + RADEON_I2C_HALT | + RADEON_I2C_SOFT_RST)); + WREG32(i2c_data, ((p->slave << 1) & 0xff) | 0x1); + WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | + (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | + RADEON_I2C_EN | + (48 << RADEON_I2C_TIME_LIMIT_SHIFT))); + WREG32(i2c_cntl_0, reg | RADEON_I2C_RECEIVE); + for (k = 0; k < 32; k++) { + DRM_UDELAY(10); + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_GO) + continue; + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_DONE) + break; + else { + DRM_DEBUG("i2c read error 0x%08x\n", tmp); + WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); + ret = EIO; + goto done; + } + } + p->buf[j] = RREG32(i2c_data) & 0xff; + } else { + WREG32(i2c_cntl_0, (RADEON_I2C_DONE | + RADEON_I2C_NACK | + RADEON_I2C_HALT | + RADEON_I2C_SOFT_RST)); + WREG32(i2c_data, (p->slave << 1) & 0xff); + WREG32(i2c_data, p->buf[j]); + WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | + (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | + RADEON_I2C_EN | + (48 << RADEON_I2C_TIME_LIMIT_SHIFT))); + WREG32(i2c_cntl_0, reg); + for (k = 0; k < 32; k++) { + DRM_UDELAY(10); + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_GO) + continue; + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_DONE) + break; + else { + DRM_DEBUG("i2c write error 0x%08x\n", tmp); + WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); + ret = EIO; + goto done; + } + } + } + } + } + +done: + WREG32(i2c_cntl_0, 0); + WREG32(i2c_cntl_1, 0); + WREG32(i2c_cntl_0, (RADEON_I2C_DONE | + RADEON_I2C_NACK | + RADEON_I2C_HALT | + RADEON_I2C_SOFT_RST)); + + if (rdev->is_atom_bios) { + tmp = RREG32(RADEON_BIOS_6_SCRATCH); + tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE; + WREG32(RADEON_BIOS_6_SCRATCH, tmp); + } + + sx_xunlock(&rdev->pm.mutex); + sx_xunlock(&rdev->dc_hw_i2c_mutex); + + return ret; +} + +/* hw i2c engine for r5xx hardware + * hw can buffer up to 15 bytes + */ +static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, + struct iic_msg *msgs, int num) +{ + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + struct iic_msg *p; + int i, j, remaining, current_count, buffer_offset, ret = 0; + u32 prescale; + u32 tmp, reg; + u32 saved1, saved2; + + sx_xlock(&rdev->dc_hw_i2c_mutex); + /* take the pm lock since we need a constant sclk */ + sx_xlock(&rdev->pm.mutex); + + prescale = radeon_get_i2c_prescale(rdev); + + /* clear gpio mask bits */ + tmp = RREG32(rec->mask_clk_reg); + tmp &= ~rec->mask_clk_mask; + WREG32(rec->mask_clk_reg, tmp); + tmp = RREG32(rec->mask_clk_reg); + + tmp = RREG32(rec->mask_data_reg); + tmp &= ~rec->mask_data_mask; + WREG32(rec->mask_data_reg, tmp); + tmp = RREG32(rec->mask_data_reg); + + /* clear pin values */ + tmp = RREG32(rec->a_clk_reg); + tmp &= ~rec->a_clk_mask; + WREG32(rec->a_clk_reg, tmp); + tmp = RREG32(rec->a_clk_reg); + + tmp = RREG32(rec->a_data_reg); + tmp &= ~rec->a_data_mask; + WREG32(rec->a_data_reg, tmp); + tmp = RREG32(rec->a_data_reg); + + /* set the pins to input */ + tmp = RREG32(rec->en_clk_reg); + tmp &= ~rec->en_clk_mask; + WREG32(rec->en_clk_reg, tmp); + tmp = RREG32(rec->en_clk_reg); + + tmp = RREG32(rec->en_data_reg); + tmp &= ~rec->en_data_mask; + WREG32(rec->en_data_reg, tmp); + tmp = RREG32(rec->en_data_reg); + + /* */ + tmp = RREG32(RADEON_BIOS_6_SCRATCH); + WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE); + saved1 = RREG32(AVIVO_DC_I2C_CONTROL1); + saved2 = RREG32(0x494); + WREG32(0x494, saved2 | 0x1); + + WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C); + for (i = 0; i < 50; i++) { + DRM_UDELAY(1); + if (RREG32(AVIVO_DC_I2C_ARBITRATION) & AVIVO_DC_I2C_SW_CAN_USE_I2C) + break; + } + if (i == 50) { + DRM_ERROR("failed to get i2c bus\n"); + ret = EBUSY; + goto done; + } + + reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN; + switch (rec->mask_clk_reg) { + case AVIVO_DC_GPIO_DDC1_MASK: + reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC1); + break; + case AVIVO_DC_GPIO_DDC2_MASK: + reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC2); + break; + case AVIVO_DC_GPIO_DDC3_MASK: + reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC3); + break; + default: + DRM_ERROR("gpio not supported with hw i2c\n"); + ret = EINVAL; + goto done; + } + + /* check for bus probe */ + p = &msgs[0]; + if ((num == 1) && (p->len == 0)) { + WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE | + AVIVO_DC_I2C_NACK | + AVIVO_DC_I2C_HALT)); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET); + DRM_UDELAY(1); + WREG32(AVIVO_DC_I2C_RESET, 0); + + WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff); + WREG32(AVIVO_DC_I2C_DATA, 0); + + WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48)); + WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) | + AVIVO_DC_I2C_DATA_COUNT(1) | + (prescale << 16))); + WREG32(AVIVO_DC_I2C_CONTROL1, reg); + WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO); + for (j = 0; j < 200; j++) { + DRM_UDELAY(50); + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_GO) + continue; + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_DONE) + break; + else { + DRM_DEBUG("i2c write error 0x%08x\n", tmp); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); + ret = EIO; + goto done; + } + } + goto done; + } + + for (i = 0; i < num; i++) { + p = &msgs[i]; + remaining = p->len; + buffer_offset = 0; + if (p->flags & IIC_M_RD) { + while (remaining) { + if (remaining > 15) + current_count = 15; + else + current_count = remaining; + WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE | + AVIVO_DC_I2C_NACK | + AVIVO_DC_I2C_HALT)); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET); + DRM_UDELAY(1); + WREG32(AVIVO_DC_I2C_RESET, 0); + + WREG32(AVIVO_DC_I2C_DATA, ((p->slave << 1) & 0xff) | 0x1); + WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48)); + WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) | + AVIVO_DC_I2C_DATA_COUNT(current_count) | + (prescale << 16))); + WREG32(AVIVO_DC_I2C_CONTROL1, reg | AVIVO_DC_I2C_RECEIVE); + WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO); + for (j = 0; j < 200; j++) { + DRM_UDELAY(50); + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_GO) + continue; + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_DONE) + break; + else { + DRM_DEBUG("i2c read error 0x%08x\n", tmp); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); + ret = EIO; + goto done; + } + } + for (j = 0; j < current_count; j++) + p->buf[buffer_offset + j] = RREG32(AVIVO_DC_I2C_DATA) & 0xff; + remaining -= current_count; + buffer_offset += current_count; + } + } else { + while (remaining) { + if (remaining > 15) + current_count = 15; + else + current_count = remaining; + WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE | + AVIVO_DC_I2C_NACK | + AVIVO_DC_I2C_HALT)); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET); + DRM_UDELAY(1); + WREG32(AVIVO_DC_I2C_RESET, 0); + + WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff); + for (j = 0; j < current_count; j++) + WREG32(AVIVO_DC_I2C_DATA, p->buf[buffer_offset + j]); + + WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48)); + WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) | + AVIVO_DC_I2C_DATA_COUNT(current_count) | + (prescale << 16))); + WREG32(AVIVO_DC_I2C_CONTROL1, reg); + WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO); + for (j = 0; j < 200; j++) { + DRM_UDELAY(50); + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_GO) + continue; + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_DONE) + break; + else { + DRM_DEBUG("i2c write error 0x%08x\n", tmp); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); + ret = EIO; + goto done; + } + } + remaining -= current_count; + buffer_offset += current_count; + } + } + } + +done: + WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE | + AVIVO_DC_I2C_NACK | + AVIVO_DC_I2C_HALT)); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET); + DRM_UDELAY(1); + WREG32(AVIVO_DC_I2C_RESET, 0); + + WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_DONE_USING_I2C); + WREG32(AVIVO_DC_I2C_CONTROL1, saved1); + WREG32(0x494, saved2); + tmp = RREG32(RADEON_BIOS_6_SCRATCH); + tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE; + WREG32(RADEON_BIOS_6_SCRATCH, tmp); + + sx_xunlock(&rdev->pm.mutex); + sx_xunlock(&rdev->dc_hw_i2c_mutex); + + return ret; +} + +static int radeon_hw_i2c_xfer(device_t dev, + struct iic_msg *msgs, uint32_t num) +{ + struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_device *rdev = i2c->dev->dev_private; + struct radeon_i2c_bus_rec *rec = &i2c->rec; + int ret = 0; + + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_R200: + case CHIP_RV250: + case CHIP_RS300: + case CHIP_RV280: + case CHIP_R300: + case CHIP_R350: + case CHIP_RV350: + case CHIP_RV380: + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + case CHIP_RS400: + case CHIP_RS480: + ret = r100_hw_i2c_xfer(i2c, msgs, num); + break; + case CHIP_RS600: + case CHIP_RS690: + case CHIP_RS740: + /* XXX fill in hw i2c implementation */ + break; + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV530: + case CHIP_RV560: + case CHIP_RV570: + case CHIP_R580: + if (rec->mm_i2c) + ret = r100_hw_i2c_xfer(i2c, msgs, num); + else + ret = r500_hw_i2c_xfer(i2c, msgs, num); + break; + case CHIP_R600: + case CHIP_RV610: + case CHIP_RV630: + case CHIP_RV670: + /* XXX fill in hw i2c implementation */ + break; + case CHIP_RV620: + case CHIP_RV635: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + case CHIP_RV740: + /* XXX fill in hw i2c implementation */ + break; + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + /* XXX fill in hw i2c implementation */ + break; + default: + DRM_ERROR("i2c: unhandled radeon chip\n"); + ret = EIO; + break; + } + + return ret; +} + +static int +radeon_hw_i2c_probe(device_t dev) +{ + + return (BUS_PROBE_SPECIFIC); +} + +static int +radeon_hw_i2c_attach(device_t dev) +{ + struct radeon_i2c_chan *i2c; + device_t iic_dev; + + i2c = device_get_softc(dev); + device_set_desc(dev, i2c->name); + + /* add generic bit-banging code */ + iic_dev = device_add_child(dev, "iicbus", -1); + if (iic_dev == NULL) + return (ENXIO); + device_quiet(iic_dev); + + /* attach and probe added child */ + bus_generic_attach(dev); + + return (0); +} + +static int +radeon_hw_i2c_detach(device_t dev) +{ + + /* detach bit-banding code. */ + bus_generic_detach(dev); + + /* delete bit-banding code. */ + device_delete_children(dev); + return (0); +} + +static int +radeon_hw_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +{ + + /* Not sure what to do here. */ + return 0; +} + + +static device_method_t radeon_hw_i2c_methods[] = { + DEVMETHOD(device_probe, radeon_hw_i2c_probe), + DEVMETHOD(device_attach, radeon_hw_i2c_attach), + DEVMETHOD(device_detach, radeon_hw_i2c_detach), + DEVMETHOD(iicbus_reset, radeon_hw_i2c_reset), + DEVMETHOD(iicbus_transfer, radeon_hw_i2c_xfer), + DEVMETHOD_END +}; + +static driver_t radeon_hw_i2c_driver = { + "radeon_hw_i2c", + radeon_hw_i2c_methods, + 0 /* softc will be allocated by parent */ +}; + +static devclass_t radeon_hw_i2c_devclass; +DRIVER_MODULE_ORDERED(radeon_hw_i2c, drm, radeon_hw_i2c_driver, + radeon_hw_i2c_devclass, 0, 0, SI_ORDER_FIRST); +DRIVER_MODULE(iicbus, radeon_hw_i2c, iicbus_driver, iicbus_devclass, 0, 0); + +struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_i2c_chan *i2c; + device_t iicbus_dev; + int ret; + + /* don't add the mm_i2c bus unless hw_i2c is enabled */ + if (rec->mm_i2c && (radeon_hw_i2c == 0)) + return NULL; + + i2c = malloc(sizeof(struct radeon_i2c_chan), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (i2c == NULL) + return NULL; + + /* + * Grab Giant before messing with newbus devices, just in case + * we do not hold it already. + */ + mtx_lock(&Giant); + + i2c->rec = *rec; + i2c->dev = dev; + if (rec->mm_i2c || + (rec->hw_capable && + radeon_hw_i2c && + ((rdev->family <= CHIP_RS480) || + ((rdev->family >= CHIP_RV515) && (rdev->family <= CHIP_R580))))) { + /* set the radeon hw i2c adapter */ + snprintf(i2c->name, sizeof(i2c->name), + "Radeon i2c hw bus %s", name); + iicbus_dev = device_add_child(dev->device, "radeon_hw_i2c", -1); + if (iicbus_dev == NULL) { + DRM_ERROR("Failed to create bridge for hw i2c %s\n", + name); + goto out_free; + } + device_quiet(iicbus_dev); + device_set_softc(iicbus_dev, i2c); + + ret = device_probe_and_attach(iicbus_dev); + if (ret != 0) { + DRM_ERROR("Attach failed for bridge for hw i2c %s\n", + name); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + + i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1); + if (i2c->adapter == NULL) { + DRM_ERROR("hw i2c bridge doesn't have iicbus child\n"); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + } else if (rec->hw_capable && + radeon_hw_i2c && + ASIC_IS_DCE3(rdev)) { + /* hw i2c using atom */ + snprintf(i2c->name, sizeof(i2c->name), + "Radeon i2c hw bus %s", name); + iicbus_dev = device_add_child(dev->device, "radeon_atom_hw_i2c", -1); + if (iicbus_dev == NULL) { + DRM_ERROR("Failed to create bridge for hw i2c %s\n", + name); + goto out_free; + } + device_quiet(iicbus_dev); + device_set_softc(iicbus_dev, i2c); + + ret = device_probe_and_attach(iicbus_dev); + if (ret != 0) { + DRM_ERROR("Attach failed for bridge for hw i2c %s\n", + name); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + + i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1); + if (i2c->adapter == NULL) { + DRM_ERROR("hw i2c bridge doesn't have iicbus child\n"); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + } else { + device_t iicbb_dev; + + /* set the radeon bit adapter */ + snprintf(i2c->name, sizeof(i2c->name), + "Radeon i2c bit bus %s", name); + iicbus_dev = device_add_child(dev->device, "radeon_iicbb", -1); + if (iicbus_dev == NULL) { + DRM_ERROR("Failed to create bridge for bb i2c %s\n", + name); + goto out_free; + } + device_quiet(iicbus_dev); + device_set_softc(iicbus_dev, i2c); + + ret = device_probe_and_attach(iicbus_dev); + if (ret != 0) { + DRM_ERROR("Attach failed for bridge for bb i2c %s\n", + name); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + + iicbb_dev = device_find_child(iicbus_dev, "iicbb", -1); + if (iicbb_dev == NULL) { + DRM_ERROR("bb i2c bridge doesn't have iicbb child\n"); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + + i2c->adapter = device_find_child(iicbb_dev, "iicbus", -1); + if (i2c->adapter == NULL) { + DRM_ERROR( + "bbbus bridge doesn't have iicbus grandchild\n"); + device_delete_child(dev->device, iicbus_dev); + goto out_free; + } + } + + i2c->iic_bus = iicbus_dev; + + mtx_unlock(&Giant); + + return i2c; +out_free: + mtx_unlock(&Giant); + free(i2c, DRM_MEM_DRIVER); + return NULL; + +} + +struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name) +{ + struct radeon_i2c_chan *i2c; + int ret; + + i2c = malloc(sizeof(struct radeon_i2c_chan), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (i2c == NULL) + return NULL; + + i2c->rec = *rec; + i2c->dev = dev; + snprintf(i2c->name, sizeof(i2c->name), + "Radeon aux bus %s", name); + ret = iic_dp_aux_add_bus(dev->device, i2c->name, + radeon_dp_i2c_aux_ch, i2c, &i2c->iic_bus, + &i2c->adapter); + if (ret) { + DRM_INFO("Failed to register i2c %s\n", name); + goto out_free; + } + + return i2c; +out_free: + free(i2c, DRM_MEM_DRIVER); + return NULL; + +} + +void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) +{ + if (!i2c) + return; + if (i2c->iic_bus != NULL) { + int ret; + + mtx_lock(&Giant); + ret = device_delete_child(i2c->dev->device, i2c->iic_bus); + mtx_unlock(&Giant); + KASSERT(ret == 0, ("unable to detach iic bus %s: %d", + i2c->name, ret)); + } + free(i2c, DRM_MEM_DRIVER); +} + +/* Add the default buses */ +void radeon_i2c_init(struct radeon_device *rdev) +{ + if (rdev->is_atom_bios) + radeon_atombios_i2c_init(rdev); + else + radeon_combios_i2c_init(rdev); +} + +/* remove all the buses */ +void radeon_i2c_fini(struct radeon_device *rdev) +{ + int i; + + for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { + if (rdev->i2c_bus[i]) { + radeon_i2c_destroy(rdev->i2c_bus[i]); + rdev->i2c_bus[i] = NULL; + } + } +} + +/* Add additional buses */ +void radeon_i2c_add(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *rec, + const char *name) +{ + struct drm_device *dev = rdev->ddev; + int i; + + for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { + if (!rdev->i2c_bus[i]) { + rdev->i2c_bus[i] = radeon_i2c_create(dev, rec, name); + return; + } + } +} + +/* looks up bus based on id */ +struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *i2c_bus) +{ + int i; + + for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { + if (rdev->i2c_bus[i] && + (rdev->i2c_bus[i]->rec.i2c_id == i2c_bus->i2c_id)) { + return rdev->i2c_bus[i]; + } + } + return NULL; +} + +struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) +{ + return NULL; +} + +void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, + u8 slave_addr, + u8 addr, + u8 *val) +{ + u8 out_buf[2]; + u8 in_buf[2]; + struct iic_msg msgs[] = { + { + .slave = slave_addr << 1, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .slave = slave_addr << 1, + .flags = IIC_M_RD, + .len = 1, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if (iicbus_transfer(i2c_bus->adapter, msgs, 2) == 0) { + *val = in_buf[0]; + DRM_DEBUG("val = 0x%02x\n", *val); + } else { + DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n", + addr, *val); + } +} + +void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, + u8 slave_addr, + u8 addr, + u8 val) +{ + uint8_t out_buf[2]; + struct iic_msg msg = { + .slave = slave_addr << 1, + .flags = 0, + .len = 2, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = val; + + if (iicbus_transfer(i2c_bus->adapter, &msg, 1) != 0) + DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n", + addr, val); +} + +/* ddc router switching */ +void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector) +{ + u8 val; + + if (!radeon_connector->router.ddc_valid) + return; + + if (!radeon_connector->router_bus) + return; + + radeon_i2c_get_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x3, &val); + val &= ~radeon_connector->router.ddc_mux_control_pin; + radeon_i2c_put_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x3, val); + radeon_i2c_get_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x1, &val); + val &= ~radeon_connector->router.ddc_mux_control_pin; + val |= radeon_connector->router.ddc_mux_state; + radeon_i2c_put_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x1, val); +} + +/* clock/data router switching */ +void radeon_router_select_cd_port(struct radeon_connector *radeon_connector) +{ + u8 val; + + if (!radeon_connector->router.cd_valid) + return; + + if (!radeon_connector->router_bus) + return; + + radeon_i2c_get_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x3, &val); + val &= ~radeon_connector->router.cd_mux_control_pin; + radeon_i2c_put_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x3, val); + radeon_i2c_get_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x1, &val); + val &= ~radeon_connector->router.cd_mux_control_pin; + val |= radeon_connector->router.cd_mux_state; + radeon_i2c_put_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x1, val); +} + diff --git a/sys/dev/drm2/radeon/radeon_ioc32.c b/sys/dev/drm2/radeon/radeon_ioc32.c new file mode 100644 index 00000000000..361d48cb3f4 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_ioc32.c @@ -0,0 +1,428 @@ +/** + * \file radeon_ioc32.c + * + * 32-bit ioctl compatibility routines for the Radeon DRM. + * + * \author Paul Mackerras + * + * Copyright (C) Paul Mackerras 2005 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include "radeon_drv.h" + +typedef struct drm_radeon_init32 { + int func; + u32 sarea_priv_offset; + int is_pci; + int cp_mode; + int gart_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + u32 fb_offset; + u32 mmio_offset; + u32 ring_offset; + u32 ring_rptr_offset; + u32 buffers_offset; + u32 gart_textures_offset; +} drm_radeon_init32_t; + +static int compat_radeon_cp_init(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_init32_t init32; + drm_radeon_init_t __user *init; + + if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) + return -EFAULT; + + init = compat_alloc_user_space(sizeof(*init)); + if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) + || __put_user(init32.func, &init->func) + || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) + || __put_user(init32.is_pci, &init->is_pci) + || __put_user(init32.cp_mode, &init->cp_mode) + || __put_user(init32.gart_size, &init->gart_size) + || __put_user(init32.ring_size, &init->ring_size) + || __put_user(init32.usec_timeout, &init->usec_timeout) + || __put_user(init32.fb_bpp, &init->fb_bpp) + || __put_user(init32.front_offset, &init->front_offset) + || __put_user(init32.front_pitch, &init->front_pitch) + || __put_user(init32.back_offset, &init->back_offset) + || __put_user(init32.back_pitch, &init->back_pitch) + || __put_user(init32.depth_bpp, &init->depth_bpp) + || __put_user(init32.depth_offset, &init->depth_offset) + || __put_user(init32.depth_pitch, &init->depth_pitch) + || __put_user(init32.fb_offset, &init->fb_offset) + || __put_user(init32.mmio_offset, &init->mmio_offset) + || __put_user(init32.ring_offset, &init->ring_offset) + || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) + || __put_user(init32.buffers_offset, &init->buffers_offset) + || __put_user(init32.gart_textures_offset, + &init->gart_textures_offset)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); +} + +typedef struct drm_radeon_clear32 { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ + u32 depth_boxes; +} drm_radeon_clear32_t; + +static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_clear32_t clr32; + drm_radeon_clear_t __user *clr; + + if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32))) + return -EFAULT; + + clr = compat_alloc_user_space(sizeof(*clr)); + if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr)) + || __put_user(clr32.flags, &clr->flags) + || __put_user(clr32.clear_color, &clr->clear_color) + || __put_user(clr32.clear_depth, &clr->clear_depth) + || __put_user(clr32.color_mask, &clr->color_mask) + || __put_user(clr32.depth_mask, &clr->depth_mask) + || __put_user((void __user *)(unsigned long)clr32.depth_boxes, + &clr->depth_boxes)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); +} + +typedef struct drm_radeon_stipple32 { + u32 mask; +} drm_radeon_stipple32_t; + +static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_stipple32_t __user *argp = (void __user *)arg; + drm_radeon_stipple_t __user *request; + u32 mask; + + if (get_user(mask, &argp->mask)) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user((unsigned int __user *)(unsigned long)mask, + &request->mask)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); +} + +typedef struct drm_radeon_tex_image32 { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + u32 data; +} drm_radeon_tex_image32_t; + +typedef struct drm_radeon_texture32 { + unsigned int offset; + int pitch; + int format; + int width; /* Texture image coordinates */ + int height; + u32 image; +} drm_radeon_texture32_t; + +static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_texture32_t req32; + drm_radeon_texture_t __user *request; + drm_radeon_tex_image32_t img32; + drm_radeon_tex_image_t __user *image; + + if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) + return -EFAULT; + if (req32.image == 0) + return -EINVAL; + if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image, + sizeof(img32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request) + sizeof(*image)); + if (!access_ok(VERIFY_WRITE, request, + sizeof(*request) + sizeof(*image))) + return -EFAULT; + image = (drm_radeon_tex_image_t __user *) (request + 1); + + if (__put_user(req32.offset, &request->offset) + || __put_user(req32.pitch, &request->pitch) + || __put_user(req32.format, &request->format) + || __put_user(req32.width, &request->width) + || __put_user(req32.height, &request->height) + || __put_user(image, &request->image) + || __put_user(img32.x, &image->x) + || __put_user(img32.y, &image->y) + || __put_user(img32.width, &image->width) + || __put_user(img32.height, &image->height) + || __put_user((const void __user *)(unsigned long)img32.data, + &image->data)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); +} + +typedef struct drm_radeon_vertex2_32 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + u32 state; + int nr_prims; + u32 prim; +} drm_radeon_vertex2_32_t; + +static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_vertex2_32_t req32; + drm_radeon_vertex2_t __user *request; + + if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user(req32.idx, &request->idx) + || __put_user(req32.discard, &request->discard) + || __put_user(req32.nr_states, &request->nr_states) + || __put_user((void __user *)(unsigned long)req32.state, + &request->state) + || __put_user(req32.nr_prims, &request->nr_prims) + || __put_user((void __user *)(unsigned long)req32.prim, + &request->prim)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); +} + +typedef struct drm_radeon_cmd_buffer32 { + int bufsz; + u32 buf; + int nbox; + u32 boxes; +} drm_radeon_cmd_buffer32_t; + +static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_cmd_buffer32_t req32; + drm_radeon_cmd_buffer_t __user *request; + + if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user(req32.bufsz, &request->bufsz) + || __put_user((void __user *)(unsigned long)req32.buf, + &request->buf) + || __put_user(req32.nbox, &request->nbox) + || __put_user((void __user *)(unsigned long)req32.boxes, + &request->boxes)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); +} + +typedef struct drm_radeon_getparam32 { + int param; + u32 value; +} drm_radeon_getparam32_t; + +static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_getparam32_t req32; + drm_radeon_getparam_t __user *request; + + if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user(req32.param, &request->param) + || __put_user((void __user *)(unsigned long)req32.value, + &request->value)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); +} + +typedef struct drm_radeon_mem_alloc32 { + int region; + int alignment; + int size; + u32 region_offset; /* offset from start of fb or GART */ +} drm_radeon_mem_alloc32_t; + +static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_mem_alloc32_t req32; + drm_radeon_mem_alloc_t __user *request; + + if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user(req32.region, &request->region) + || __put_user(req32.alignment, &request->alignment) + || __put_user(req32.size, &request->size) + || __put_user((int __user *)(unsigned long)req32.region_offset, + &request->region_offset)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); +} + +typedef struct drm_radeon_irq_emit32 { + u32 irq_seq; +} drm_radeon_irq_emit32_t; + +static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_irq_emit32_t req32; + drm_radeon_irq_emit_t __user *request; + + if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user((int __user *)(unsigned long)req32.irq_seq, + &request->irq_seq)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); +} + +/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ +#if defined (CONFIG_X86_64) || defined(CONFIG_IA64) +typedef struct drm_radeon_setparam32 { + int param; + u64 value; +} __attribute__((packed)) drm_radeon_setparam32_t; + +static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_radeon_setparam32_t req32; + drm_radeon_setparam_t __user *request; + + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) + return -EFAULT; + + request = compat_alloc_user_space(sizeof(*request)); + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) + || __put_user(req32.param, &request->param) + || __put_user((void __user *)(unsigned long)req32.value, + &request->value)) + return -EFAULT; + + return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); +} +#else +#define compat_radeon_cp_setparam NULL +#endif /* X86_64 || IA64 */ + +static drm_ioctl_compat_t *radeon_compat_ioctls[] = { + [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, + [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, + [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, + [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture, + [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2, + [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf, + [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam, + [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam, + [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc, + [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit, +}; + +/** + * Called whenever a 32-bit process running under a 64-bit kernel + * performs an ioctl on /dev/dri/card. + * + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or negative number on failure. + */ +long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + unsigned int nr = DRM_IOCTL_NR(cmd); + drm_ioctl_compat_t *fn = NULL; + int ret; + + if (nr < DRM_COMMAND_BASE) + return drm_compat_ioctl(filp, cmd, arg); + + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) + fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; + + if (fn != NULL) + ret = (*fn) (filp, cmd, arg); + else + ret = drm_ioctl(filp, cmd, arg); + + return ret; +} + +long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + unsigned int nr = DRM_IOCTL_NR(cmd); + int ret; + + if (nr < DRM_COMMAND_BASE) + return drm_compat_ioctl(filp, cmd, arg); + + ret = drm_ioctl(filp, cmd, arg); + + return ret; +} diff --git a/sys/dev/drm2/radeon/radeon_irq.c b/sys/dev/drm2/radeon/radeon_irq.c new file mode 100644 index 00000000000..11e66e197b5 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_irq.c @@ -0,0 +1,403 @@ +/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */ +/* + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + * Michel D�zer + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_drv.h" + +void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (state) + dev_priv->irq_enable_reg |= mask; + else + dev_priv->irq_enable_reg &= ~mask; + + if (dev->irq_enabled) + RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); +} + +static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (state) + dev_priv->r500_disp_irq_reg |= mask; + else + dev_priv->r500_disp_irq_reg &= ~mask; + + if (dev->irq_enabled) + RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); +} + +int radeon_enable_vblank(struct drm_device *dev, int crtc) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { + switch (crtc) { + case 0: + r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1); + break; + case 1: + r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return -EINVAL; + } + } else { + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return -EINVAL; + } + } + + return 0; +} + +void radeon_disable_vblank(struct drm_device *dev, int crtc) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { + switch (crtc) { + case 0: + r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0); + break; + case 1: + r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + break; + } + } else { + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + break; + } + } +} + +static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int) +{ + u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS); + u32 irq_mask = RADEON_SW_INT_TEST; + + *r500_disp_int = 0; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { + /* vbl interrupts in a different place */ + + if (irqs & R500_DISPLAY_INT_STATUS) { + /* if a display interrupt */ + u32 disp_irq; + + disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS); + + *r500_disp_int = disp_irq; + if (disp_irq & R500_D1_VBLANK_INTERRUPT) + RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK); + if (disp_irq & R500_D2_VBLANK_INTERRUPT) + RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK); + } + irq_mask |= R500_DISPLAY_INT_STATUS; + } else + irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT; + + irqs &= irq_mask; + + if (irqs) + RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); + + return irqs; +} + +/* Interrupts - Used for device synchronization and flushing in the + * following circumstances: + * + * - Exclusive FB access with hw idle: + * - Wait for GUI Idle (?) interrupt, then do normal flush. + * + * - Frame throttling, NV_fence: + * - Drop marker irq's into command stream ahead of time. + * - Wait on irq's with lock *not held* + * - Check each for termination condition + * + * - Internally in cp_getbuffer, etc: + * - as above, but wait with lock held??? + * + * NOTE: These functions are misleadingly named -- the irq's aren't + * tied to dma at all, this is just a hangover from dri prehistory. + */ + +irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) +{ + struct drm_device *dev = (struct drm_device *) arg; + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *) dev->dev_private; + u32 stat; + u32 r500_disp_int; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return IRQ_NONE; + + /* Only consider the bits we're interested in - others could be used + * outside the DRM + */ + stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int); + if (!stat) + return IRQ_NONE; + + stat &= dev_priv->irq_enable_reg; + + /* SW interrupt */ + if (stat & RADEON_SW_INT_TEST) + DRM_WAKEUP(&dev_priv->swi_queue); + + /* VBLANK interrupt */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { + if (r500_disp_int & R500_D1_VBLANK_INTERRUPT) + drm_handle_vblank(dev, 0); + if (r500_disp_int & R500_D2_VBLANK_INTERRUPT) + drm_handle_vblank(dev, 1); + } else { + if (stat & RADEON_CRTC_VBLANK_STAT) + drm_handle_vblank(dev, 0); + if (stat & RADEON_CRTC2_VBLANK_STAT) + drm_handle_vblank(dev, 1); + } + return IRQ_HANDLED; +} + +static int radeon_emit_irq(struct drm_device * dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + unsigned int ret; + RING_LOCALS; + + atomic_inc(&dev_priv->swi_emitted); + ret = atomic_read(&dev_priv->swi_emitted); + + BEGIN_RING(4); + OUT_RING_REG(RADEON_LAST_SWI_REG, ret); + OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); + ADVANCE_RING(); + COMMIT_RING(); + + return ret; +} + +static int radeon_wait_irq(struct drm_device * dev, int swi_nr) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *) dev->dev_private; + int ret = 0; + + if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) + return 0; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, + RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); + + return ret; +} + +u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + if (crtc < 0 || crtc > 1) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { + if (crtc == 0) + return RADEON_READ(R500_D1CRTC_FRAME_COUNT); + else + return RADEON_READ(R500_D2CRTC_FRAME_COUNT); + } else { + if (crtc == 0) + return RADEON_READ(RADEON_CRTC_CRNT_FRAME); + else + return RADEON_READ(RADEON_CRTC2_CRNT_FRAME); + } +} + +/* Needs the lock as it touches the ring. + */ +int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_irq_emit_t *emit = data; + int result; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return -EINVAL; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + result = radeon_emit_irq(dev); + + if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { + DRM_ERROR("copy_to_user\n"); + return -EFAULT; + } + + return 0; +} + +/* Doesn't need the hardware lock. + */ +int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_irq_wait_t *irqwait = data; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return -EINVAL; + + return radeon_wait_irq(dev, irqwait->irq_seq); +} + +/* drm_dma.h hooks +*/ +void radeon_driver_irq_preinstall(struct drm_device * dev) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *) dev->dev_private; + u32 dummy; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return; + + /* Disable *all* interrupts */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) + RADEON_WRITE(R500_DxMODE_INT_MASK, 0); + RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); + + /* Clear bits if they're already high */ + radeon_acknowledge_irqs(dev_priv, &dummy); +} + +int radeon_driver_irq_postinstall(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *) dev->dev_private; + + atomic_set(&dev_priv->swi_emitted, 0); + DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); + + dev->max_vblank_count = 0x001fffff; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return 0; + + radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); + + return 0; +} + +void radeon_driver_irq_uninstall(struct drm_device * dev) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *) dev->dev_private; + if (!dev_priv) + return; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) + RADEON_WRITE(R500_DxMODE_INT_MASK, 0); + /* Disable *all* interrupts */ + RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); +} + + +int radeon_vblank_crtc_get(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + + return dev_priv->vblank_crtc; +} + +int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) +{ + drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { + DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); + return -EINVAL; + } + dev_priv->vblank_crtc = (unsigned int)value; + return 0; +} diff --git a/sys/dev/drm2/radeon/radeon_irq_kms.c b/sys/dev/drm2/radeon/radeon_irq_kms.c new file mode 100644 index 00000000000..a679ed192e0 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_irq_kms.c @@ -0,0 +1,468 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon_reg.h" +#include "radeon_irq_kms.h" +#include "radeon.h" +#include "atom.h" + +#define RADEON_WAIT_IDLE_TIMEOUT 200 + +/** + * radeon_driver_irq_handler_kms - irq handler for KMS + * + * @DRM_IRQ_ARGS: args + * + * This is the irq handler for the radeon KMS driver (all asics). + * radeon_irq_process is a macro that points to the per-asic + * irq handler callback. + */ +irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) +{ + struct drm_device *dev = (struct drm_device *) arg; + struct radeon_device *rdev = dev->dev_private; + + return radeon_irq_process(rdev); +} + +/* + * Handle hotplug events outside the interrupt handler proper. + */ +/** + * radeon_hotplug_work_func - display hotplug work handler + * + * @work: work struct + * + * This is the hot plug event work handler (all asics). + * The work gets scheduled from the irq handler if there + * was a hot plug interrupt. It walks the connector table + * and calls the hotplug handler for each one, then sends + * a drm hotplug event to alert userspace. + */ +static void radeon_hotplug_work_func(void *arg, int pending) +{ + struct radeon_device *rdev = arg; + struct drm_device *dev = rdev->ddev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + if (mode_config->num_connector) { + list_for_each_entry(connector, &mode_config->connector_list, head) + radeon_connector_hotplug(connector); + } + /* Just fire off a uevent and let userspace tell us what to do */ + drm_helper_hpd_irq_event(dev); +} + +/** + * radeon_driver_irq_preinstall_kms - drm irq preinstall callback + * + * @dev: drm dev pointer + * + * Gets the hw ready to enable irqs (all asics). + * This function disables all interrupt sources on the GPU. + */ +void radeon_driver_irq_preinstall_kms(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + unsigned long irqflags; + unsigned i; + + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + /* Disable *all* interrupts */ + for (i = 0; i < RADEON_NUM_RINGS; i++) + atomic_set(&rdev->irq.ring_int[i], 0); + for (i = 0; i < RADEON_MAX_HPD_PINS; i++) + rdev->irq.hpd[i] = false; + for (i = 0; i < RADEON_MAX_CRTCS; i++) { + rdev->irq.crtc_vblank_int[i] = false; + atomic_set(&rdev->irq.pflip[i], 0); + rdev->irq.afmt[i] = false; + } + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); + /* Clear bits */ + radeon_irq_process(rdev); +} + +/** + * radeon_driver_irq_postinstall_kms - drm irq preinstall callback + * + * @dev: drm dev pointer + * + * Handles stuff to be done after enabling irqs (all asics). + * Returns 0 on success. + */ +int radeon_driver_irq_postinstall_kms(struct drm_device *dev) +{ + dev->max_vblank_count = 0x001fffff; + return 0; +} + +/** + * radeon_driver_irq_uninstall_kms - drm irq uninstall callback + * + * @dev: drm dev pointer + * + * This function disables all interrupt sources on the GPU (all asics). + */ +void radeon_driver_irq_uninstall_kms(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + unsigned long irqflags; + unsigned i; + + if (rdev == NULL) { + return; + } + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + /* Disable *all* interrupts */ + for (i = 0; i < RADEON_NUM_RINGS; i++) + atomic_set(&rdev->irq.ring_int[i], 0); + for (i = 0; i < RADEON_MAX_HPD_PINS; i++) + rdev->irq.hpd[i] = false; + for (i = 0; i < RADEON_MAX_CRTCS; i++) { + rdev->irq.crtc_vblank_int[i] = false; + atomic_set(&rdev->irq.pflip[i], 0); + rdev->irq.afmt[i] = false; + } + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); +} + +/** + * radeon_msi_ok - asic specific msi checks + * + * @rdev: radeon device pointer + * + * Handles asic specific MSI checks to determine if + * MSIs should be enabled on a particular chip (all asics). + * Returns true if MSIs should be enabled, false if MSIs + * should not be enabled. + */ +int radeon_msi_ok(struct drm_device *dev, unsigned long flags) +{ + int family; + + family = flags & RADEON_FAMILY_MASK; + + /* RV370/RV380 was first asic with MSI support */ + if (family < CHIP_RV380) + return false; + + /* MSIs don't work on AGP */ + if (drm_device_is_agp(dev)) + return false; + + /* force MSI on */ + if (radeon_msi == 1) + return true; + else if (radeon_msi == 0) + return false; + + /* Quirks */ + /* HP RS690 only seems to work with MSIs. */ + if ((dev->pci_device == 0x791f) && + (dev->pci_subvendor == 0x103c) && + (dev->pci_subdevice == 0x30c2)) + return true; + + /* Dell RS690 only seems to work with MSIs. */ + if ((dev->pci_device == 0x791f) && + (dev->pci_subvendor == 0x1028) && + (dev->pci_subdevice == 0x01fc)) + return true; + + /* Dell RS690 only seems to work with MSIs. */ + if ((dev->pci_device == 0x791f) && + (dev->pci_subvendor == 0x1028) && + (dev->pci_subdevice == 0x01fd)) + return true; + + /* Gateway RS690 only seems to work with MSIs. */ + if ((dev->pci_device == 0x791f) && + (dev->pci_subvendor == 0x107b) && + (dev->pci_subdevice == 0x0185)) + return true; + + /* try and enable MSIs by default on all RS690s */ + if (family == CHIP_RS690) + return true; + + /* RV515 seems to have MSI issues where it loses + * MSI rearms occasionally. This leads to lockups and freezes. + * disable it by default. + */ + if (family == CHIP_RV515) + return false; + if (flags & RADEON_IS_IGP) { + /* APUs work fine with MSIs */ + if (family >= CHIP_PALM) + return true; + /* lots of IGPs have problems with MSIs */ + return false; + } + + return true; +} + +/** + * radeon_irq_kms_init - init driver interrupt info + * + * @rdev: radeon device pointer + * + * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). + * Returns 0 for success, error for failure. + */ +int radeon_irq_kms_init(struct radeon_device *rdev) +{ + int r = 0; + + TASK_INIT(&rdev->hotplug_work, 0, radeon_hotplug_work_func, rdev); + TASK_INIT(&rdev->audio_work, 0, r600_audio_update_hdmi, rdev); + + DRM_SPININIT(&rdev->irq.lock, "drm__radeon_device__irq__lock"); + r = drm_vblank_init(rdev->ddev, rdev->num_crtc); + if (r) { + return r; + } + /* enable msi */ + rdev->msi_enabled = rdev->ddev->msi_enabled; + + rdev->irq.installed = true; + DRM_UNLOCK(rdev->ddev); + r = drm_irq_install(rdev->ddev); + DRM_LOCK(rdev->ddev); + if (r) { + rdev->irq.installed = false; + return r; + } + DRM_INFO("radeon: irq initialized.\n"); + return 0; +} + +/** + * radeon_irq_kms_fini - tear down driver interrrupt info + * + * @rdev: radeon device pointer + * + * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). + */ +void radeon_irq_kms_fini(struct radeon_device *rdev) +{ + drm_vblank_cleanup(rdev->ddev); + if (rdev->irq.installed) { + drm_irq_uninstall(rdev->ddev); + rdev->irq.installed = false; + } + taskqueue_drain(rdev->tq, &rdev->hotplug_work); +} + +/** + * radeon_irq_kms_sw_irq_get - enable software interrupt + * + * @rdev: radeon device pointer + * @ring: ring whose interrupt you want to enable + * + * Enables the software interrupt for a specific ring (all asics). + * The software interrupt is generally used to signal a fence on + * a particular ring. + */ +void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) +{ + unsigned long irqflags; + + if (!rdev->ddev->irq_enabled) + return; + + if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); + } +} + +/** + * radeon_irq_kms_sw_irq_put - disable software interrupt + * + * @rdev: radeon device pointer + * @ring: ring whose interrupt you want to disable + * + * Disables the software interrupt for a specific ring (all asics). + * The software interrupt is generally used to signal a fence on + * a particular ring. + */ +void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) +{ + unsigned long irqflags; + + if (!rdev->ddev->irq_enabled) + return; + + if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); + } +} + +/** + * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt + * + * @rdev: radeon device pointer + * @crtc: crtc whose interrupt you want to enable + * + * Enables the pageflip interrupt for a specific crtc (all asics). + * For pageflips we use the vblank interrupt source. + */ +void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) +{ + unsigned long irqflags; + + if (crtc < 0 || crtc >= rdev->num_crtc) + return; + + if (!rdev->ddev->irq_enabled) + return; + + if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); + } +} + +/** + * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt + * + * @rdev: radeon device pointer + * @crtc: crtc whose interrupt you want to disable + * + * Disables the pageflip interrupt for a specific crtc (all asics). + * For pageflips we use the vblank interrupt source. + */ +void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) +{ + unsigned long irqflags; + + if (crtc < 0 || crtc >= rdev->num_crtc) + return; + + if (!rdev->ddev->irq_enabled) + return; + + if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); + } +} + +/** + * radeon_irq_kms_enable_afmt - enable audio format change interrupt + * + * @rdev: radeon device pointer + * @block: afmt block whose interrupt you want to enable + * + * Enables the afmt change interrupt for a specific afmt block (all asics). + */ +void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) +{ + unsigned long irqflags; + + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + rdev->irq.afmt[block] = true; + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); + +} + +/** + * radeon_irq_kms_disable_afmt - disable audio format change interrupt + * + * @rdev: radeon device pointer + * @block: afmt block whose interrupt you want to disable + * + * Disables the afmt change interrupt for a specific afmt block (all asics). + */ +void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) +{ + unsigned long irqflags; + + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + rdev->irq.afmt[block] = false; + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); +} + +/** + * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt + * + * @rdev: radeon device pointer + * @hpd_mask: mask of hpd pins you want to enable. + * + * Enables the hotplug detect interrupt for a specific hpd pin (all asics). + */ +void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) +{ + unsigned long irqflags; + int i; + + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) + rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); +} + +/** + * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt + * + * @rdev: radeon device pointer + * @hpd_mask: mask of hpd pins you want to disable. + * + * Disables the hotplug detect interrupt for a specific hpd pin (all asics). + */ +void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) +{ + unsigned long irqflags; + int i; + + DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); + for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) + rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); + radeon_irq_set(rdev); + DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); +} + diff --git a/sys/dev/drm2/radeon/radeon_irq_kms.h b/sys/dev/drm2/radeon/radeon_irq_kms.h new file mode 100644 index 00000000000..6bfb9889779 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_irq_kms.h @@ -0,0 +1,15 @@ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_IRQ_KMS_H__ +#define __RADEON_IRQ_KMS_H__ + +irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS); +void radeon_driver_irq_preinstall_kms(struct drm_device *dev); +int radeon_driver_irq_postinstall_kms(struct drm_device *dev); +void radeon_driver_irq_uninstall_kms(struct drm_device *dev); + +int radeon_msi_ok(struct drm_device *dev, unsigned long flags); + +#endif /* !defined(__RADEON_IRQ_KMS_H__) */ diff --git a/sys/dev/drm2/radeon/radeon_kms.c b/sys/dev/drm2/radeon/radeon_kms.c new file mode 100644 index 00000000000..8507d016e58 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_kms.c @@ -0,0 +1,727 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include +#include "radeon_asic.h" +#include "radeon_kms.h" + +/** + * radeon_driver_unload_kms - Main unload function for KMS. + * + * @dev: drm dev pointer + * + * This is the main unload function for KMS (all asics). + * It calls radeon_modeset_fini() to tear down the + * displays, and radeon_device_fini() to tear down + * the rest of the device (CP, writeback, etc.). + * Returns 0 on success. + */ +int radeon_driver_unload_kms(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + + if (rdev == NULL) + return 0; + radeon_acpi_fini(rdev); + radeon_modeset_fini(rdev); + radeon_device_fini(rdev); + free(rdev, DRM_MEM_DRIVER); + dev->dev_private = NULL; + return 0; +} + +/** + * radeon_driver_load_kms - Main load function for KMS. + * + * @dev: drm dev pointer + * @flags: device flags + * + * This is the main load function for KMS (all asics). + * It calls radeon_device_init() to set up the non-display + * parts of the chip (asic init, CP, writeback, etc.), and + * radeon_modeset_init() to set up the display parts + * (crtcs, encoders, hotplug detect, etc.). + * Returns 0 on success, error on failure. + */ +int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) +{ + struct radeon_device *rdev; + int r, acpi_status; + + rdev = malloc(sizeof(struct radeon_device), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (rdev == NULL) { + return -ENOMEM; + } + dev->dev_private = (void *)rdev; + + /* update BUS flag */ + if (drm_device_is_agp(dev)) { + DRM_INFO("RADEON_IS_AGP\n"); + flags |= RADEON_IS_AGP; + } else if (drm_device_is_pcie(dev)) { + DRM_INFO("RADEON_IS_PCIE\n"); + flags |= RADEON_IS_PCIE; + } else { + DRM_INFO("RADEON_IS_PCI\n"); + flags |= RADEON_IS_PCI; + } + + /* radeon_device_init should report only fatal error + * like memory allocation failure or iomapping failure, + * or memory manager initialization failure, it must + * properly initialize the GPU MC controller and permit + * VRAM allocation + */ + r = radeon_device_init(rdev, dev, flags); + if (r) { + dev_err(dev->device, "Fatal error during GPU init\n"); + goto out; + } + + /* Again modeset_init should fail only on fatal error + * otherwise it should provide enough functionalities + * for shadowfb to run + */ + r = radeon_modeset_init(rdev); + if (r) + dev_err(dev->device, "Fatal error during modeset init\n"); + + /* Call ACPI methods: require modeset init + * but failure is not fatal + */ + if (!r) { + acpi_status = radeon_acpi_init(rdev); + if (acpi_status) + dev_dbg(dev->device, + "Error during ACPI methods call\n"); + } + +out: + if (r) + radeon_driver_unload_kms(dev); + return r; +} + +/** + * radeon_set_filp_rights - Set filp right. + * + * @dev: drm dev pointer + * @owner: drm file + * @applier: drm file + * @value: value + * + * Sets the filp rights for the device (all asics). + */ +static void radeon_set_filp_rights(struct drm_device *dev, + struct drm_file **owner, + struct drm_file *applier, + uint32_t *value) +{ + DRM_LOCK(dev); + if (*value == 1) { + /* wants rights */ + if (!*owner) + *owner = applier; + } else if (*value == 0) { + /* revokes rights */ + if (*owner == applier) + *owner = NULL; + } + *value = *owner == applier ? 1 : 0; + DRM_UNLOCK(dev); +} + +/* + * Userspace get information ioctl + */ +/** + * radeon_info_ioctl - answer a device specific request. + * + * @rdev: radeon device pointer + * @data: request object + * @filp: drm filp + * + * This function is used to pass device specific parameters to the userspace + * drivers. Examples include: pci device id, pipeline parms, tiling params, + * etc. (all asics). + * Returns 0 on success, -EINVAL on failure. + */ +static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_info *info = data; + struct radeon_mode_info *minfo = &rdev->mode_info; + uint32_t value, *value_ptr; + uint64_t value64, *value_ptr64; + struct drm_crtc *crtc; + int i, found; + + /* TIMESTAMP is a 64-bit value, needs special handling. */ + if (info->request == RADEON_INFO_TIMESTAMP) { + if (rdev->family >= CHIP_R600) { + value_ptr64 = (uint64_t*)((unsigned long)info->value); + if (rdev->family >= CHIP_TAHITI) { + value64 = si_get_gpu_clock(rdev); + } else { + value64 = r600_get_gpu_clock(rdev); + } + + if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { + DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); + return -EFAULT; + } + return 0; + } else { + DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); + return -EINVAL; + } + } + + value_ptr = (uint32_t *)((unsigned long)info->value); + if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { + DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); + return -EFAULT; + } + + switch (info->request) { + case RADEON_INFO_DEVICE_ID: + value = dev->pci_device; + break; + case RADEON_INFO_NUM_GB_PIPES: + value = rdev->num_gb_pipes; + break; + case RADEON_INFO_NUM_Z_PIPES: + value = rdev->num_z_pipes; + break; + case RADEON_INFO_ACCEL_WORKING: + /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ + if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) + value = false; + else + value = rdev->accel_working; + break; + case RADEON_INFO_CRTC_FROM_ID: + for (i = 0, found = 0; i < rdev->num_crtc; i++) { + crtc = (struct drm_crtc *)minfo->crtcs[i]; + if (crtc && crtc->base.id == value) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + value = radeon_crtc->crtc_id; + found = 1; + break; + } + } + if (!found) { + DRM_DEBUG_KMS("unknown crtc id %d\n", value); + return -EINVAL; + } + break; + case RADEON_INFO_ACCEL_WORKING2: + value = rdev->accel_working; + break; + case RADEON_INFO_TILING_CONFIG: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.tile_config; + else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.tile_config; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.tile_config; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.tile_config; + else if (rdev->family >= CHIP_R600) + value = rdev->config.r600.tile_config; + else { + DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); + return -EINVAL; + } + break; + case RADEON_INFO_WANT_HYPERZ: + /* The "value" here is both an input and output parameter. + * If the input value is 1, filp requests hyper-z access. + * If the input value is 0, filp revokes its hyper-z access. + * + * When returning, the value is 1 if filp owns hyper-z access, + * 0 otherwise. */ + if (value >= 2) { + DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); + return -EINVAL; + } + radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value); + break; + case RADEON_INFO_WANT_CMASK: + /* The same logic as Hyper-Z. */ + if (value >= 2) { + DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value); + return -EINVAL; + } + radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value); + break; + case RADEON_INFO_CLOCK_CRYSTAL_FREQ: + /* return clock value in KHz */ + value = rdev->clock.spll.reference_freq * 10; + break; + case RADEON_INFO_NUM_BACKENDS: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.max_backends_per_se * + rdev->config.si.max_shader_engines; + else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.max_backends_per_se * + rdev->config.cayman.max_shader_engines; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.max_backends; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.max_backends; + else if (rdev->family >= CHIP_R600) + value = rdev->config.r600.max_backends; + else { + return -EINVAL; + } + break; + case RADEON_INFO_NUM_TILE_PIPES: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.max_tile_pipes; + else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.max_tile_pipes; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.max_tile_pipes; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.max_tile_pipes; + else if (rdev->family >= CHIP_R600) + value = rdev->config.r600.max_tile_pipes; + else { + return -EINVAL; + } + break; + case RADEON_INFO_FUSION_GART_WORKING: + value = 1; + break; + case RADEON_INFO_BACKEND_MAP: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.backend_map; + else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.backend_map; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.backend_map; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.backend_map; + else if (rdev->family >= CHIP_R600) + value = rdev->config.r600.backend_map; + else { + return -EINVAL; + } + break; + case RADEON_INFO_VA_START: + /* this is where we report if vm is supported or not */ + if (rdev->family < CHIP_CAYMAN) + return -EINVAL; + value = RADEON_VA_RESERVED_SIZE; + break; + case RADEON_INFO_IB_VM_MAX_SIZE: + /* this is where we report if vm is supported or not */ + if (rdev->family < CHIP_CAYMAN) + return -EINVAL; + value = RADEON_IB_VM_MAX_SIZE; + break; + case RADEON_INFO_MAX_PIPES: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.max_cu_per_sh; + else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.max_pipes_per_simd; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.max_pipes; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.max_pipes; + else if (rdev->family >= CHIP_R600) + value = rdev->config.r600.max_pipes; + else { + return -EINVAL; + } + break; + case RADEON_INFO_MAX_SE: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.max_shader_engines; + else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.max_shader_engines; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.num_ses; + else + value = 1; + break; + case RADEON_INFO_MAX_SH_PER_SE: + if (rdev->family >= CHIP_TAHITI) + value = rdev->config.si.max_sh_per_se; + else + return -EINVAL; + break; + default: + DRM_DEBUG_KMS("Invalid request %d\n", info->request); + return -EINVAL; + } + if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { + DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); + return -EFAULT; + } + return 0; +} + + +/* + * Outdated mess for old drm with Xorg being in charge (void function now). + */ +/** + * radeon_driver_firstopen_kms - drm callback for first open + * + * @dev: drm dev pointer + * + * Nothing to be done for KMS (all asics). + * Returns 0 on success. + */ +int radeon_driver_firstopen_kms(struct drm_device *dev) +{ + return 0; +} + +/** + * radeon_driver_firstopen_kms - drm callback for last close + * + * @dev: drm dev pointer + * + * Switch vga switcheroo state after last close (all asics). + */ +void radeon_driver_lastclose_kms(struct drm_device *dev) +{ +#ifdef DUMBBELL_WIP + vga_switcheroo_process_delayed_switch(); +#endif /* DUMBBELL_WIP */ +} + +/** + * radeon_driver_open_kms - drm callback for open + * + * @dev: drm dev pointer + * @file_priv: drm file + * + * On device open, init vm on cayman+ (all asics). + * Returns 0 on success, error on failure. + */ +int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) +{ + struct radeon_device *rdev = dev->dev_private; + + file_priv->driver_priv = NULL; + + /* new gpu have virtual address space support */ + if (rdev->family >= CHIP_CAYMAN) { + struct radeon_fpriv *fpriv; + struct radeon_bo_va *bo_va; + int r; + + fpriv = malloc(sizeof(*fpriv), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (unlikely(!fpriv)) { + return -ENOMEM; + } + + radeon_vm_init(rdev, &fpriv->vm); + + /* map the ib pool buffer read only into + * virtual address space */ + bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, + rdev->ring_tmp_bo.bo); + r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, + RADEON_VM_PAGE_READABLE | + RADEON_VM_PAGE_SNOOPED); + if (r) { + radeon_vm_fini(rdev, &fpriv->vm); + free(fpriv, DRM_MEM_DRIVER); + return r; + } + + file_priv->driver_priv = fpriv; + } + return 0; +} + +/** + * radeon_driver_postclose_kms - drm callback for post close + * + * @dev: drm dev pointer + * @file_priv: drm file + * + * On device post close, tear down vm on cayman+ (all asics). + */ +void radeon_driver_postclose_kms(struct drm_device *dev, + struct drm_file *file_priv) +{ + struct radeon_device *rdev = dev->dev_private; + + /* new gpu have virtual address space support */ + if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { + struct radeon_fpriv *fpriv = file_priv->driver_priv; + struct radeon_bo_va *bo_va; + int r; + + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); + if (!r) { + bo_va = radeon_vm_bo_find(&fpriv->vm, + rdev->ring_tmp_bo.bo); + if (bo_va) + radeon_vm_bo_rmv(rdev, bo_va); + radeon_bo_unreserve(rdev->ring_tmp_bo.bo); + } + + radeon_vm_fini(rdev, &fpriv->vm); + free(fpriv, DRM_MEM_DRIVER); + file_priv->driver_priv = NULL; + } +} + +/** + * radeon_driver_preclose_kms - drm callback for pre close + * + * @dev: drm dev pointer + * @file_priv: drm file + * + * On device pre close, tear down hyperz and cmask filps on r1xx-r5xx + * (all asics). + */ +void radeon_driver_preclose_kms(struct drm_device *dev, + struct drm_file *file_priv) +{ + struct radeon_device *rdev = dev->dev_private; + if (rdev->hyperz_filp == file_priv) + rdev->hyperz_filp = NULL; + if (rdev->cmask_filp == file_priv) + rdev->cmask_filp = NULL; +} + +/* + * VBlank related functions. + */ +/** + * radeon_get_vblank_counter_kms - get frame count + * + * @dev: drm dev pointer + * @crtc: crtc to get the frame count from + * + * Gets the frame count on the requested crtc (all asics). + * Returns frame count on success, -EINVAL on failure. + */ +u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) +{ + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc >= rdev->num_crtc) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + return radeon_get_vblank_counter(rdev, crtc); +} + +/** + * radeon_enable_vblank_kms - enable vblank interrupt + * + * @dev: drm dev pointer + * @crtc: crtc to enable vblank interrupt for + * + * Enable the interrupt on the requested crtc (all asics). + * Returns 0 on success, -EINVAL on failure. + */ +int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) +{ + struct radeon_device *rdev = dev->dev_private; + int r; + + if (crtc < 0 || crtc >= rdev->num_crtc) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + mtx_lock(&rdev->irq.lock); + rdev->irq.crtc_vblank_int[crtc] = true; + r = radeon_irq_set(rdev); + mtx_unlock(&rdev->irq.lock); + return r; +} + +/** + * radeon_disable_vblank_kms - disable vblank interrupt + * + * @dev: drm dev pointer + * @crtc: crtc to disable vblank interrupt for + * + * Disable the interrupt on the requested crtc (all asics). + */ +void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) +{ + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc >= rdev->num_crtc) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return; + } + + mtx_lock(&rdev->irq.lock); + rdev->irq.crtc_vblank_int[crtc] = false; + radeon_irq_set(rdev); + mtx_unlock(&rdev->irq.lock); +} + +/** + * radeon_get_vblank_timestamp_kms - get vblank timestamp + * + * @dev: drm dev pointer + * @crtc: crtc to get the timestamp for + * @max_error: max error + * @vblank_time: time value + * @flags: flags passed to the driver + * + * Gets the timestamp on the requested crtc based on the + * scanout position. (all asics). + * Returns postive status flags on success, negative error on failure. + */ +int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags) +{ + struct drm_crtc *drmcrtc; + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + /* Get associated drm_crtc: */ + drmcrtc = &rdev->mode_info.crtcs[crtc]->base; + + /* Helper routine in DRM core does all the work: */ + return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, + vblank_time, flags, + drmcrtc); +} + +/* + * IOCTL. + */ +int radeon_dma_ioctl_kms(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + /* Not valid in KMS. */ + return -EINVAL; +} + +#define KMS_INVALID_IOCTL(name) \ +static int \ +name(struct drm_device *dev, void *data, struct drm_file *file_priv) \ +{ \ + DRM_ERROR("invalid ioctl with kms %s\n", __func__); \ + return -EINVAL; \ +} + +/* + * All these ioctls are invalid in kms world. + */ +KMS_INVALID_IOCTL(radeon_cp_init_kms) +KMS_INVALID_IOCTL(radeon_cp_start_kms) +KMS_INVALID_IOCTL(radeon_cp_stop_kms) +KMS_INVALID_IOCTL(radeon_cp_reset_kms) +KMS_INVALID_IOCTL(radeon_cp_idle_kms) +KMS_INVALID_IOCTL(radeon_cp_resume_kms) +KMS_INVALID_IOCTL(radeon_engine_reset_kms) +KMS_INVALID_IOCTL(radeon_fullscreen_kms) +KMS_INVALID_IOCTL(radeon_cp_swap_kms) +KMS_INVALID_IOCTL(radeon_cp_clear_kms) +KMS_INVALID_IOCTL(radeon_cp_vertex_kms) +KMS_INVALID_IOCTL(radeon_cp_indices_kms) +KMS_INVALID_IOCTL(radeon_cp_texture_kms) +KMS_INVALID_IOCTL(radeon_cp_stipple_kms) +KMS_INVALID_IOCTL(radeon_cp_indirect_kms) +KMS_INVALID_IOCTL(radeon_cp_vertex2_kms) +KMS_INVALID_IOCTL(radeon_cp_cmdbuf_kms) +KMS_INVALID_IOCTL(radeon_cp_getparam_kms) +KMS_INVALID_IOCTL(radeon_cp_flip_kms) +KMS_INVALID_IOCTL(radeon_mem_alloc_kms) +KMS_INVALID_IOCTL(radeon_mem_free_kms) +KMS_INVALID_IOCTL(radeon_mem_init_heap_kms) +KMS_INVALID_IOCTL(radeon_irq_emit_kms) +KMS_INVALID_IOCTL(radeon_irq_wait_kms) +KMS_INVALID_IOCTL(radeon_cp_setparam_kms) +KMS_INVALID_IOCTL(radeon_surface_alloc_kms) +KMS_INVALID_IOCTL(radeon_surface_free_kms) + + +struct drm_ioctl_desc radeon_ioctls_kms[] = { + DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH), + /* KMS */ + DRM_IOCTL_DEF_DRV(RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_UNLOCKED), +}; +int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); diff --git a/sys/dev/drm2/radeon/radeon_kms.h b/sys/dev/drm2/radeon/radeon_kms.h new file mode 100644 index 00000000000..ff3bbbccdd3 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_kms.h @@ -0,0 +1,30 @@ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_KMS_H__ +#define __RADEON_KMS_H__ + +#include + +int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); +int radeon_driver_unload_kms(struct drm_device *dev); + +int radeon_driver_firstopen_kms(struct drm_device *dev); +void radeon_driver_lastclose_kms(struct drm_device *dev); +int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv); +void radeon_driver_postclose_kms(struct drm_device *dev, + struct drm_file *file_priv); +void radeon_driver_preclose_kms(struct drm_device *dev, + struct drm_file *file_priv); +u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); +int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); +void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); +int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags); +int radeon_dma_ioctl_kms(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +#endif /* !defined(__RADEON_KMS_H__) */ diff --git a/sys/dev/drm2/radeon/radeon_legacy_crtc.c b/sys/dev/drm2/radeon/radeon_legacy_crtc.c new file mode 100644 index 00000000000..54f755a6097 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_legacy_crtc.c @@ -0,0 +1,1085 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "radeon.h" +#include "atom.h" + +static void radeon_overscan_setup(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0); + WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0); + WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0); +} + +static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + int xres = mode->hdisplay; + int yres = mode->vdisplay; + bool hscale = true, vscale = true; + int hsync_wid; + int vsync_wid; + int hsync_start; + int blank_width; + u32 scale, inc, crtc_more_cntl; + u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active; + u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp; + u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp; + struct drm_display_mode *native_mode = &radeon_crtc->native_mode; + + fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & + (RADEON_VERT_STRETCH_RESERVED | + RADEON_VERT_AUTO_RATIO_INC); + fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & + (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + + crtc_more_cntl = 0; + if ((rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. */ + crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + } + + + fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + hsync_start = mode->crtc_hsync_start - 8; + + fp_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + fp_horz_vert_active = 0; + + if (native_mode->hdisplay == 0 || + native_mode->vdisplay == 0) { + hscale = false; + vscale = false; + } else { + if (xres > native_mode->hdisplay) + xres = native_mode->hdisplay; + if (yres > native_mode->vdisplay) + yres = native_mode->vdisplay; + + if (xres == native_mode->hdisplay) + hscale = false; + if (yres == native_mode->vdisplay) + vscale = false; + } + + switch (radeon_crtc->rmx_type) { + case RMX_FULL: + case RMX_ASPECT: + if (!hscale) + fp_horz_stretch |= ((xres/8-1) << 16); + else { + inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; + scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) + / native_mode->hdisplay + 1; + fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((native_mode->hdisplay/8-1) << 16)); + } + + if (!vscale) + fp_vert_stretch |= ((yres-1) << 12); + else { + inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; + scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) + / native_mode->vdisplay + 1; + fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((native_mode->vdisplay-1) << 12)); + } + break; + case RMX_CENTER: + fp_horz_stretch |= ((xres/8-1) << 16); + fp_vert_stretch |= ((yres-1) << 12); + + crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | + RADEON_CRTC_AUTO_VERT_CENTER_EN); + + blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; + if (blank_width > 110) + blank_width = 110; + + fp_crtc_h_total_disp = (((blank_width) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + + fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0))); + + fp_horz_vert_active = (((native_mode->vdisplay) & 0xfff) | + (((native_mode->hdisplay / 8) & 0x1ff) << 16)); + break; + case RMX_OFF: + default: + fp_horz_stretch |= ((xres/8-1) << 16); + fp_vert_stretch |= ((yres-1) << 12); + break; + } + + WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); + WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); + WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); + WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); + WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); + WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); + WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); + WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); +} + +static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + int i = 0; + + /* FIXME: Certain revisions of R300 can't recover here. Not sure of + the cause yet, but this workaround will mask the problem for now. + Other chips usually will pass at the very first test, so the + workaround shouldn't have any effect on them. */ + for (i = 0; + (i < 10000 && + RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); + i++); +} + +static void radeon_pll_write_update(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + + while (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); + + WREG32_PLL_P(RADEON_PPLL_REF_DIV, + RADEON_PPLL_ATOMIC_UPDATE_W, + ~(RADEON_PPLL_ATOMIC_UPDATE_W)); +} + +static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + int i = 0; + + + /* FIXME: Certain revisions of R300 can't recover here. Not sure of + the cause yet, but this workaround will mask the problem for now. + Other chips usually will pass at the very first test, so the + workaround shouldn't have any effect on them. */ + for (i = 0; + (i < 10000 && + RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); + i++); +} + +static void radeon_pll2_write_update(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + + while (RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); + + WREG32_PLL_P(RADEON_P2PLL_REF_DIV, + RADEON_P2PLL_ATOMIC_UPDATE_W, + ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); +} + +static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, + uint16_t fb_div) +{ + unsigned int vcoFreq; + + if (!ref_div) + return 1; + + vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div; + + /* + * This is horribly crude: the VCO frequency range is divided into + * 3 parts, each part having a fixed PLL gain value. + */ + if (vcoFreq >= 30000) + /* + * [300..max] MHz : 7 + */ + return 7; + else if (vcoFreq >= 18000) + /* + * [180..300) MHz : 4 + */ + return 4; + else + /* + * [0..180) MHz : 1 + */ + return 1; +} + +static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t crtc_ext_cntl = 0; + uint32_t mask; + + if (radeon_crtc->crtc_id) + mask = (RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS | + RADEON_CRTC2_DISP_REQ_EN_B); + else + mask = (RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS); + + /* + * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. + * Therefore it is set in the DAC DMPS function. + * This is different for GPU's with a single CRTC but a primary and a + * TV DAC: here it controls the single CRTC no matter where it is + * routed. Therefore we set it here. + */ + if (rdev->flags & RADEON_SINGLE_CRTC) + crtc_ext_cntl = RADEON_CRTC_CRT_ON; + + switch (mode) { + case DRM_MODE_DPMS_ON: + radeon_crtc->enabled = true; + /* adjust pm to dpms changes BEFORE enabling crtcs */ + radeon_pm_compute_clocks(rdev); + if (radeon_crtc->crtc_id) + WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); + else { + WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | + RADEON_CRTC_DISP_REQ_EN_B)); + WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl)); + } + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); + radeon_crtc_load_lut(crtc); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); + if (radeon_crtc->crtc_id) + WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask)); + else { + WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | + RADEON_CRTC_DISP_REQ_EN_B)); + WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl)); + } + radeon_crtc->enabled = false; + /* adjust pm to dpms changes AFTER disabling crtcs */ + radeon_pm_compute_clocks(rdev); + break; + } +} + +int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); +} + +int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, enum mode_set_atomic state) +{ + return radeon_crtc_do_set_base(crtc, fb, x, y, 1); +} + +int radeon_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_framebuffer *radeon_fb; + struct drm_framebuffer *target_fb; + struct drm_gem_object *obj; + struct radeon_bo *rbo; + uint64_t base; + uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; + uint32_t crtc_pitch, pitch_pixels; + uint32_t tiling_flags; + int format; + uint32_t gen_cntl_reg, gen_cntl_val; + int r; + + DRM_DEBUG_KMS("\n"); + /* no fb bound */ + if (!atomic && !crtc->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + if (atomic) { + radeon_fb = to_radeon_framebuffer(fb); + target_fb = fb; + } + else { + radeon_fb = to_radeon_framebuffer(crtc->fb); + target_fb = crtc->fb; + } + + switch (target_fb->bits_per_pixel) { + case 8: + format = 2; + break; + case 15: /* 555 */ + format = 3; + break; + case 16: /* 565 */ + format = 4; + break; + case 24: /* RGB */ + format = 5; + break; + case 32: /* xRGB */ + format = 6; + break; + default: + return false; + } + + /* Pin framebuffer & get tilling informations */ + obj = radeon_fb->obj; + rbo = gem_to_radeon_bo(obj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + /* Only 27 bit offset for legacy CRTC */ + r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, 1 << 27, + &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + return -EINVAL; + } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); + if (tiling_flags & RADEON_TILING_MICRO) + DRM_ERROR("trying to scanout microtiled buffer\n"); + + /* if scanout was in GTT this really wouldn't work */ + /* crtc offset is from display base addr not FB location */ + radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start; + + base -= radeon_crtc->legacy_display_base_addr; + + crtc_offset_cntl = 0; + + pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + crtc_pitch = (((pitch_pixels * target_fb->bits_per_pixel) + + ((target_fb->bits_per_pixel * 8) - 1)) / + (target_fb->bits_per_pixel * 8)); + crtc_pitch |= crtc_pitch << 16; + + crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; + if (tiling_flags & RADEON_TILING_MACRO) { + if (ASIC_IS_R300(rdev)) + crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } else { + if (ASIC_IS_R300(rdev)) + crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + if (tiling_flags & RADEON_TILING_MACRO) { + if (ASIC_IS_R300(rdev)) { + crtc_tile_x0_y0 = x | (y << 16); + base &= ~0x7ff; + } else { + int byteshift = target_fb->bits_per_pixel >> 4; + int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; + base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + crtc_offset_cntl |= (y % 16); + } + } else { + int offset = y * pitch_pixels + x; + switch (target_fb->bits_per_pixel) { + case 8: + offset *= 1; + break; + case 15: + case 16: + offset *= 2; + break; + case 24: + offset *= 3; + break; + case 32: + offset *= 4; + break; + default: + return false; + } + base += offset; + } + + base &= ~7; + + if (radeon_crtc->crtc_id == 1) + gen_cntl_reg = RADEON_CRTC2_GEN_CNTL; + else + gen_cntl_reg = RADEON_CRTC_GEN_CNTL; + + gen_cntl_val = RREG32(gen_cntl_reg); + gen_cntl_val &= ~(0xf << 8); + gen_cntl_val |= (format << 8); + gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK; + WREG32(gen_cntl_reg, gen_cntl_val); + + crtc_offset = (u32)base; + + WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr); + + if (ASIC_IS_R300(rdev)) { + if (radeon_crtc->crtc_id) + WREG32(R300_CRTC2_TILE_X0_Y0, crtc_tile_x0_y0); + else + WREG32(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0); + } + WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, crtc_offset_cntl); + WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); + WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); + + if (!atomic && fb && fb != crtc->fb) { + radeon_fb = to_radeon_framebuffer(fb); + rbo = gem_to_radeon_bo(radeon_fb->obj); + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + radeon_bo_unpin(rbo); + radeon_bo_unreserve(rbo); + } + + /* Bytes per pixel may have changed */ + radeon_bandwidth_update(rdev); + + return 0; +} + +static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_encoder *encoder; + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + uint32_t crtc_h_total_disp; + uint32_t crtc_h_sync_strt_wid; + uint32_t crtc_v_total_disp; + uint32_t crtc_v_sync_strt_wid; + bool is_tv = false; + + DRM_DEBUG_KMS("\n"); + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { + is_tv = true; + DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id); + break; + } + } + } + + switch (crtc->fb->bits_per_pixel) { + case 8: + format = 2; + break; + case 15: /* 555 */ + format = 3; + break; + case 16: /* 565 */ + format = 4; + break; + case 24: /* RGB */ + format = 5; + break; + case 32: /* xRGB */ + format = 6; + break; + default: + return false; + } + + crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + hsync_start = mode->crtc_hsync_start - 8; + + crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + if (radeon_crtc->crtc_id) { + uint32_t crtc2_gen_cntl; + uint32_t disp2_merge_cntl; + + /* if TV DAC is enabled for another crtc and keep it enabled */ + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080; + crtc2_gen_cntl |= ((format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | RADEON_CRTC2_DISP_REQ_EN_B + | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_CSYNC) + ? RADEON_CRTC2_CSYNC_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + + /* rs4xx chips seem to like to have the crtc enabled when the timing is set */ + if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) + crtc2_gen_cntl |= RADEON_CRTC2_EN; + + disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); + disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; + + WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + + WREG32(RADEON_FP_H2_SYNC_STRT_WID, crtc_h_sync_strt_wid); + WREG32(RADEON_FP_V2_SYNC_STRT_WID, crtc_v_sync_strt_wid); + } else { + uint32_t crtc_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t disp_merge_cntl; + + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000; + crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN + | (format << 8) + | RADEON_CRTC_DISP_REQ_EN_B + | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_CSYNC) + ? RADEON_CRTC_CSYNC_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); + + /* rs4xx chips seem to like to have the crtc enabled when the timing is set */ + if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) + crtc_gen_cntl |= RADEON_CRTC_EN; + + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); + + disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); + disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + + WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); + WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + } + + if (is_tv) + radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp, + &crtc_h_sync_strt_wid, &crtc_v_total_disp, + &crtc_v_sync_strt_wid); + + WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp); + WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid); + WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp); + WREG32(RADEON_CRTC_V_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_v_sync_strt_wid); + + return true; +} + +static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_encoder *encoder; + uint32_t feedback_div = 0; + uint32_t frac_fb_div = 0; + uint32_t reference_div = 0; + uint32_t post_divider = 0; + uint32_t freq = 0; + uint8_t pll_gain; + bool use_bios_divs = false; + /* PLL registers */ + uint32_t pll_ref_div = 0; + uint32_t pll_fb_post_div = 0; + uint32_t htotal_cntl = 0; + bool is_tv = false; + struct radeon_pll *pll; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, /* VCLK_SRC/16 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (radeon_crtc->crtc_id) + pll = &rdev->clock.p2pll; + else + pll = &rdev->clock.p1pll; + + pll->flags = RADEON_PLL_LEGACY; + + if (mode->clock > 200000) /* range limits??? */ + pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + else + pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { + is_tv = true; + break; + } + + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) + pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { + if (!rdev->is_atom_bios) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; + if (lvds) { + if (lvds->use_bios_dividers) { + pll_ref_div = lvds->panel_ref_divider; + pll_fb_post_div = (lvds->panel_fb_divider | + (lvds->panel_post_divider << 16)); + htotal_cntl = 0; + use_bios_divs = true; + } + } + } + pll->flags |= RADEON_PLL_USE_REF_DIV; + } + } + } + + DRM_DEBUG_KMS("\n"); + + if (!use_bios_divs) { + radeon_compute_pll_legacy(pll, mode->clock, + &freq, &feedback_div, &frac_fb_div, + &reference_div, &post_divider); + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } + + if (!post_div->divider) + post_div = &post_divs[0]; + + DRM_DEBUG_KMS("dc=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)freq, + feedback_div, + reference_div, + post_divider); + + pll_ref_div = reference_div; +#if defined(__powerpc__) && (0) /* TODO */ + /* apparently programming this otherwise causes a hang??? */ + if (info->MacModel == RADEON_MAC_IBOOK) + pll_fb_post_div = 0x000600ad; + else +#endif + pll_fb_post_div = (feedback_div | (post_div->bitvalue << 16)); + + htotal_cntl = mode->htotal & 0x7; + + } + + pll_gain = radeon_compute_pll_gain(pll->reference_freq, + pll_ref_div & 0x3ff, + pll_fb_post_div & 0x7ff); + + if (radeon_crtc->crtc_id) { + uint32_t pixclks_cntl = ((RREG32_PLL(RADEON_PIXCLKS_CNTL) & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); + + if (is_tv) { + radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl, + &pll_ref_div, &pll_fb_post_div, + &pixclks_cntl); + } + + WREG32_PLL_P(RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + WREG32_PLL_P(RADEON_P2PLL_CNTL, + RADEON_P2PLL_RESET + | RADEON_P2PLL_ATOMIC_UPDATE_EN + | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT), + ~(RADEON_P2PLL_RESET + | RADEON_P2PLL_ATOMIC_UPDATE_EN + | RADEON_P2PLL_PVG_MASK)); + + WREG32_PLL_P(RADEON_P2PLL_REF_DIV, + pll_ref_div, + ~RADEON_P2PLL_REF_DIV_MASK); + + WREG32_PLL_P(RADEON_P2PLL_DIV_0, + pll_fb_post_div, + ~RADEON_P2PLL_FB0_DIV_MASK); + + WREG32_PLL_P(RADEON_P2PLL_DIV_0, + pll_fb_post_div, + ~RADEON_P2PLL_POST0_DIV_MASK); + + radeon_pll2_write_update(dev); + radeon_pll2_wait_for_read_update_complete(dev); + + WREG32_PLL(RADEON_HTOTAL2_CNTL, htotal_cntl); + + WREG32_PLL_P(RADEON_P2PLL_CNTL, + 0, + ~(RADEON_P2PLL_RESET + | RADEON_P2PLL_SLEEP + | RADEON_P2PLL_ATOMIC_UPDATE_EN)); + + DRM_DEBUG_KMS("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + (unsigned)pll_ref_div, + (unsigned)pll_fb_post_div, + (unsigned)htotal_cntl, + RREG32_PLL(RADEON_P2PLL_CNTL)); + DRM_DEBUG_KMS("Wrote2: rd=%u, fd=%u, pd=%u\n", + (unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + (unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK, + (unsigned)((pll_fb_post_div & + RADEON_P2PLL_POST0_DIV_MASK) >> 16)); + + DRM_MDELAY(50); /* Let the clock to lock */ + + WREG32_PLL_P(RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); + } else { + uint32_t pixclks_cntl; + + + if (is_tv) { + pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); + radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div, + &pll_fb_post_div, &pixclks_cntl); + } + + if (rdev->flags & RADEON_IS_MOBILITY) { + /* A temporal workaround for the occasional blanking on certain laptop panels. + This appears to related to the PLL divider registers (fail to lock?). + It occurs even when all dividers are the same with their old settings. + In this case we really don't need to fiddle with PLL registers. + By doing this we can avoid the blanking problem with some panels. + */ + if ((pll_ref_div == (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && + (pll_fb_post_div == (RREG32_PLL(RADEON_PPLL_DIV_3) & + (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { + WREG32_P(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + r100_pll_errata_after_index(rdev); + return; + } + } + + WREG32_PLL_P(RADEON_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_CPUCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + WREG32_PLL_P(RADEON_PPLL_CNTL, + RADEON_PPLL_RESET + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT), + ~(RADEON_PPLL_RESET + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | RADEON_PPLL_PVG_MASK)); + + WREG32_P(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + r100_pll_errata_after_index(rdev); + + if (ASIC_IS_R300(rdev) || + (rdev->family == CHIP_RS300) || + (rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + if (pll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { + /* When restoring console mode, use saved PPLL_REF_DIV + * setting. + */ + WREG32_PLL_P(RADEON_PPLL_REF_DIV, + pll_ref_div, + 0); + } else { + /* R300 uses ref_div_acc field as real ref divider */ + WREG32_PLL_P(RADEON_PPLL_REF_DIV, + (pll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), + ~R300_PPLL_REF_DIV_ACC_MASK); + } + } else + WREG32_PLL_P(RADEON_PPLL_REF_DIV, + pll_ref_div, + ~RADEON_PPLL_REF_DIV_MASK); + + WREG32_PLL_P(RADEON_PPLL_DIV_3, + pll_fb_post_div, + ~RADEON_PPLL_FB3_DIV_MASK); + + WREG32_PLL_P(RADEON_PPLL_DIV_3, + pll_fb_post_div, + ~RADEON_PPLL_POST3_DIV_MASK); + + radeon_pll_write_update(dev); + radeon_pll_wait_for_read_update_complete(dev); + + WREG32_PLL(RADEON_HTOTAL_CNTL, htotal_cntl); + + WREG32_PLL_P(RADEON_PPLL_CNTL, + 0, + ~(RADEON_PPLL_RESET + | RADEON_PPLL_SLEEP + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); + + DRM_DEBUG_KMS("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + pll_ref_div, + pll_fb_post_div, + (unsigned)htotal_cntl, + RREG32_PLL(RADEON_PPLL_CNTL)); + DRM_DEBUG_KMS("Wrote: rd=%d, fd=%d, pd=%d\n", + pll_ref_div & RADEON_PPLL_REF_DIV_MASK, + pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK, + (pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16); + + DRM_MDELAY(50); /* Let the clock to lock */ + + WREG32_PLL_P(RADEON_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_PPLLCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + + if (is_tv) + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); + } +} + +static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) + return false; + return true; +} + +static int radeon_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + /* TODO TV */ + radeon_crtc_set_base(crtc, x, y, old_fb); + radeon_set_crtc_timing(crtc, adjusted_mode); + radeon_set_pll(crtc, adjusted_mode); + radeon_overscan_setup(crtc, adjusted_mode); + if (radeon_crtc->crtc_id == 0) { + radeon_legacy_rmx_mode_set(crtc, adjusted_mode); + } else { + if (radeon_crtc->rmx_type != RMX_OFF) { + /* FIXME: only first crtc has rmx what should we + * do ? + */ + DRM_ERROR("Mode need scaling but only first crtc can do that.\n"); + } + } + return 0; +} + +static void radeon_crtc_prepare(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + + radeon_crtc->in_mode_set = true; + /* + * The hardware wedges sometimes if you reconfigure one CRTC + * whilst another is running (see fdo bug #24611). + */ + list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) + radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF); +} + +static void radeon_crtc_commit(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + + /* + * Reenable the CRTCs that should be running. + */ + list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) { + if (crtci->enabled) + radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); + } + radeon_crtc->in_mode_set = false; +} + +static const struct drm_crtc_helper_funcs legacy_helper_funcs = { + .dpms = radeon_crtc_dpms, + .mode_fixup = radeon_crtc_mode_fixup, + .mode_set = radeon_crtc_mode_set, + .mode_set_base = radeon_crtc_set_base, + .mode_set_base_atomic = radeon_crtc_set_base_atomic, + .prepare = radeon_crtc_prepare, + .commit = radeon_crtc_commit, + .load_lut = radeon_crtc_load_lut, +}; + + +void radeon_legacy_init_crtc(struct drm_device *dev, + struct radeon_crtc *radeon_crtc) +{ + if (radeon_crtc->crtc_id == 1) + radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP; + drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs); +} diff --git a/sys/dev/drm2/radeon/radeon_legacy_encoders.c b/sys/dev/drm2/radeon/radeon_legacy_encoders.c new file mode 100644 index 00000000000..4a1ae163c9d --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_legacy_encoders.c @@ -0,0 +1,1817 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" + +static void radeon_legacy_encoder_disable(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder_helper_funcs *encoder_funcs; + + encoder_funcs = encoder->helper_private; + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); + radeon_encoder->active_device = 0; +} + +static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; + int panel_pwr_delay = 2000; + bool is_mac = false; + uint8_t backlight_level; + DRM_DEBUG_KMS("\n"); + + lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); + backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; + + if (radeon_encoder->enc_priv) { + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + panel_pwr_delay = lvds->panel_pwr_delay; + if (lvds->bl_dev) + backlight_level = lvds->backlight_level; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + panel_pwr_delay = lvds->panel_pwr_delay; + if (lvds->bl_dev) + backlight_level = lvds->backlight_level; + } + } + + /* macs (and possibly some x86 oem systems?) wire up LVDS strangely + * Taken from radeonfb. + */ + if ((rdev->mode_info.connector_table == CT_IBOOK) || + (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) || + (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) || + (rdev->mode_info.connector_table == CT_POWERBOOK_VGA)) + is_mac = true; + + switch (mode) { + case DRM_MODE_DPMS_ON: + disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN); + disp_pwr_man |= RADEON_AUTO_PWRUP_EN; + WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man); + lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl |= RADEON_LVDS_PLL_EN; + WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + DRM_MDELAY(1); + + lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; + WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + + lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS | + RADEON_LVDS_BL_MOD_LEVEL_MASK); + lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | + RADEON_LVDS_DIGON | RADEON_LVDS_BLON | + (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT)); + if (is_mac) + lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; + DRM_MDELAY(panel_pwr_delay); + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); + WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + if (is_mac) { + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); + } else { + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + } + DRM_MDELAY(panel_pwr_delay); + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); + DRM_MDELAY(panel_pwr_delay); + break; + } + + if (rdev->is_atom_bios) + radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + else + radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + +} + +static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + DRM_DEBUG("\n"); + + if (radeon_encoder->enc_priv) { + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + lvds->dpms_mode = mode; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + lvds->dpms_mode = mode; + } + } + + radeon_legacy_lvds_update(encoder, mode); +} + +static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); + radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON); + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, false); + else + radeon_combios_output_lock(encoder, false); +} + +static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl; + + DRM_DEBUG_KMS("\n"); + + lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; + + lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL); + if (rdev->is_atom_bios) { + /* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl + * need to call that on resume to set up the reg properly. + */ + radeon_encoder->pixel_clock = adjusted_mode->clock; + atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); + lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); + } else { + struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; + if (lvds) { + DRM_DEBUG_KMS("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl); + lvds_gen_cntl = lvds->lvds_gen_cntl; + lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) | + (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); + lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) | + (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); + } else + lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); + } + lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + lvds_gen_cntl &= ~(RADEON_LVDS_ON | + RADEON_LVDS_BLON | + RADEON_LVDS_EN | + RADEON_LVDS_RST_FM); + + if (ASIC_IS_R300(rdev)) + lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); + + if (radeon_crtc->crtc_id == 0) { + if (ASIC_IS_R300(rdev)) { + if (radeon_encoder->rmx_type != RMX_OFF) + lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; + } else + lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; + } else { + if (ASIC_IS_R300(rdev)) + lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; + else + lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; + } + + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl); + + if (rdev->family == CHIP_RV410) + WREG32(RADEON_CLOCK_CNTL_INDEX, 0); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); + else + radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); +} + +static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + /* set the active encoder to connector routing */ + radeon_encoder_set_active_device(encoder); + drm_mode_set_crtcinfo(adjusted_mode, 0); + + /* get the native mode for LVDS */ + if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) + radeon_panel_mode_fixup(encoder, adjusted_mode); + + return true; +} + +static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { + .dpms = radeon_legacy_lvds_dpms, + .mode_fixup = radeon_legacy_mode_fixup, + .prepare = radeon_legacy_lvds_prepare, + .mode_set = radeon_legacy_lvds_mode_set, + .commit = radeon_legacy_lvds_commit, + .disable = radeon_legacy_encoder_disable, +}; + +u8 +radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + u8 backlight_level; + + backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> + RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; + + return backlight_level; +} + +void +radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + int dpms_mode = DRM_MODE_DPMS_ON; + + if (radeon_encoder->enc_priv) { + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + if (lvds->backlight_level > 0) + dpms_mode = lvds->dpms_mode; + else + dpms_mode = DRM_MODE_DPMS_OFF; + lvds->backlight_level = level; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + if (lvds->backlight_level > 0) + dpms_mode = lvds->dpms_mode; + else + dpms_mode = DRM_MODE_DPMS_OFF; + lvds->backlight_level = level; + } + } + + radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode); +} + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + uint8_t level; + + /* Convert brightness to hardware level */ + if (bd->props.brightness < 0) + level = 0; + else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) + level = RADEON_MAX_BL_LEVEL; + else + level = bd->props.brightness; + + if (pdata->negative) + level = RADEON_MAX_BL_LEVEL - level; + + return level; +} + +static int radeon_legacy_backlight_update_status(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + struct radeon_encoder *radeon_encoder = pdata->encoder; + + radeon_legacy_set_backlight_level(radeon_encoder, + radeon_legacy_lvds_level(bd)); + + return 0; +} + +static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + struct radeon_encoder *radeon_encoder = pdata->encoder; + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint8_t backlight_level; + + backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> + RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; + + return pdata->negative ? RADEON_MAX_BL_LEVEL - backlight_level : backlight_level; +} + +static const struct backlight_ops radeon_backlight_ops = { + .get_brightness = radeon_legacy_backlight_get_brightness, + .update_status = radeon_legacy_backlight_update_status, +}; + +void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, + struct drm_connector *drm_connector) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd; + struct backlight_properties props; + struct radeon_backlight_privdata *pdata; + uint8_t backlight_level; + char bl_name[16]; + + if (!radeon_encoder->enc_priv) + return; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!pmac_has_backlight_type("ati") && + !pmac_has_backlight_type("mnca")) + return; +#endif + + pdata = malloc(sizeof(struct radeon_backlight_privdata), + DRM_MEM_DRIVER, M_WAITOK); + if (!pdata) { + DRM_ERROR("Memory allocation failed\n"); + goto error; + } + + memset(&props, 0, sizeof(props)); + props.max_brightness = RADEON_MAX_BL_LEVEL; + props.type = BACKLIGHT_RAW; + snprintf(bl_name, sizeof(bl_name), + "radeon_bl%d", dev->primary->index); + bd = backlight_device_register(bl_name, &drm_connector->kdev, + pdata, &radeon_backlight_ops, &props); + if (IS_ERR(bd)) { + DRM_ERROR("Backlight registration failed\n"); + goto error; + } + + pdata->encoder = radeon_encoder; + + backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> + RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; + + /* First, try to detect backlight level sense based on the assumption + * that firmware set it up at full brightness + */ + if (backlight_level == 0) + pdata->negative = true; + else if (backlight_level == 0xff) + pdata->negative = false; + else { + /* XXX hack... maybe some day we can figure out in what direction + * backlight should work on a given panel? + */ + pdata->negative = (rdev->family != CHIP_RV200 && + rdev->family != CHIP_RV250 && + rdev->family != CHIP_RV280 && + rdev->family != CHIP_RV350); + +#ifdef CONFIG_PMAC_BACKLIGHT + pdata->negative = (pdata->negative || + of_machine_is_compatible("PowerBook4,3") || + of_machine_is_compatible("PowerBook6,3") || + of_machine_is_compatible("PowerBook6,5")); +#endif + } + + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + lvds->bl_dev = bd; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + lvds->bl_dev = bd; + } + + bd->props.brightness = radeon_legacy_backlight_get_brightness(bd); + bd->props.power = FB_BLANK_UNBLANK; + backlight_update_status(bd); + + DRM_INFO("radeon legacy LVDS backlight initialized\n"); + + return; + +error: + free(pdata, DRM_MEM_DRIVER); + return; +} + +static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd = NULL; + + if (!radeon_encoder->enc_priv) + return; + + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + bd = lvds->bl_dev; + lvds->bl_dev = NULL; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + bd = lvds->bl_dev; + lvds->bl_dev = NULL; + } + + if (bd) { + struct radeon_backlight_privdata *pdata; + + pdata = bl_get_data(bd); + backlight_device_unregister(bd); + free(pdata, DRM_MEM_DRIVER); + + DRM_INFO("radeon legacy LVDS backlight unloaded\n"); + } +} + +#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */ + +void radeon_legacy_backlight_init(struct radeon_encoder *encoder, + struct drm_connector *drm_connector) +{ +} + +static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder) +{ +} + +#endif + + +static void radeon_lvds_enc_destroy(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->enc_priv) { + radeon_legacy_backlight_exit(radeon_encoder); + free(radeon_encoder->enc_priv, DRM_MEM_DRIVER); + } + drm_encoder_cleanup(encoder); + free(radeon_encoder, DRM_MEM_DRIVER); +} + +static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { + .destroy = radeon_lvds_enc_destroy, +}; + +static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL); + uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); + + DRM_DEBUG_KMS("\n"); + + switch (mode) { + case DRM_MODE_DPMS_ON: + crtc_ext_cntl |= RADEON_CRTC_CRT_ON; + dac_cntl &= ~RADEON_DAC_PDWN; + dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; + dac_cntl |= RADEON_DAC_PDWN; + dac_macro_cntl |= (RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + break; + } + + /* handled in radeon_crtc_dpms() */ + if (!(rdev->flags & RADEON_SINGLE_CRTC)) + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + WREG32(RADEON_DAC_CNTL, dac_cntl); + WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + else + radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + +} + +static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); + radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON); + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, false); + else + radeon_combios_output_lock(encoder, false); +} + +static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl; + + DRM_DEBUG_KMS("\n"); + + if (radeon_crtc->crtc_id == 0) { + if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & + ~(RADEON_DISP_DAC_SOURCE_MASK); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + } else { + dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL); + WREG32(RADEON_DAC_CNTL2, dac2_cntl); + } + } else { + if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & + ~(RADEON_DISP_DAC_SOURCE_MASK); + disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + } else { + dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL; + WREG32(RADEON_DAC_CNTL2, dac2_cntl); + } + } + + dac_cntl = (RADEON_DAC_MASK_ALL | + RADEON_DAC_VGA_ADR_EN | + /* TODO 6-bits */ + RADEON_DAC_8BIT_EN); + + WREG32_P(RADEON_DAC_CNTL, + dac_cntl, + RADEON_DAC_RANGE_CNTL | + RADEON_DAC_BLANKING); + + if (radeon_encoder->enc_priv) { + struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv; + dac_macro_cntl = p_dac->ps2_pdac_adj; + } else + dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); + dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B; + WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); + else + radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); +} + +static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t vclk_ecp_cntl, crtc_ext_cntl; + uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; + enum drm_connector_status found = connector_status_disconnected; + bool color = true; + + /* just don't bother on RN50 those chip are often connected to remoting + * console hw and often we get failure to load detect those. So to make + * everyone happy report the encoder as always connected. + */ + if (ASIC_IS_RN50(rdev)) { + return connector_status_connected; + } + + /* save the regs we need */ + vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); + dac_cntl = RREG32(RADEON_DAC_CNTL); + dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); + + tmp = vclk_ecp_cntl & + ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); + + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + WREG32(RADEON_CRTC_EXT_CNTL, tmp); + + tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | + RADEON_DAC_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (ASIC_IS_R300(rdev)) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else if (ASIC_IS_RV100(rdev)) + tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + WREG32(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); + tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; + WREG32(RADEON_DAC_CNTL, tmp); + + tmp = dac_macro_cntl; + tmp &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + + WREG32(RADEON_DAC_MACRO_CNTL, tmp); + + DRM_MDELAY(2); + + if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) + found = connector_status_connected; + + /* restore the regs we used */ + WREG32(RADEON_DAC_CNTL, dac_cntl); + WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); + + return found; +} + +static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { + .dpms = radeon_legacy_primary_dac_dpms, + .mode_fixup = radeon_legacy_mode_fixup, + .prepare = radeon_legacy_primary_dac_prepare, + .mode_set = radeon_legacy_primary_dac_mode_set, + .commit = radeon_legacy_primary_dac_commit, + .detect = radeon_legacy_primary_dac_detect, + .disable = radeon_legacy_encoder_disable, +}; + + +static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL); + DRM_DEBUG_KMS("\n"); + + switch (mode) { + case DRM_MODE_DPMS_ON: + fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + break; + } + + WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + else + radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + +} + +static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); + radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON); + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); +} + +static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl; + int i; + + DRM_DEBUG_KMS("\n"); + + tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); + tmp &= 0xfffff; + if (rdev->family == CHIP_RV280) { + /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ + tmp ^= (1 << 22); + tmds_pll_cntl ^= (1 << 22); + } + + if (radeon_encoder->enc_priv) { + struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv; + + for (i = 0; i < 4; i++) { + if (tmds->tmds_pll[i].freq == 0) + break; + if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) { + tmp = tmds->tmds_pll[i].value ; + break; + } + } + } + + if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) { + if (tmp & 0xfff00000) + tmds_pll_cntl = tmp; + else { + tmds_pll_cntl &= 0xfff00000; + tmds_pll_cntl |= tmp; + } + } else + tmds_pll_cntl = tmp; + + tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) & + ~(RADEON_TMDS_TRANSMITTER_PLLRST); + + if (rdev->family == CHIP_R200 || + rdev->family == CHIP_R100 || + ASIC_IS_R300(rdev)) + tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); + else /* RV chips got this bit reversed */ + tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN; + + fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) | + (RADEON_FP_CRTC_DONT_SHADOW_VPAR | + RADEON_FP_CRTC_DONT_SHADOW_HEND)); + + fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + + fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN | + RADEON_FP_DFP_SYNC_SEL | + RADEON_FP_CRT_SYNC_SEL | + RADEON_FP_CRTC_LOCK_8DOT | + RADEON_FP_USE_SHADOW_EN | + RADEON_FP_CRTC_USE_SHADOW_VEND | + RADEON_FP_CRT_SYNC_ALT); + + if (1) /* FIXME rgbBits == 8 */ + fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + else + fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + + if (radeon_crtc->crtc_id == 0) { + if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { + fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (radeon_encoder->rmx_type != RMX_OFF) + fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2; + } else { + if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { + fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } + + WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl); + WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl); + WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); + else + radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); +} + +static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = { + .dpms = radeon_legacy_tmds_int_dpms, + .mode_fixup = radeon_legacy_mode_fixup, + .prepare = radeon_legacy_tmds_int_prepare, + .mode_set = radeon_legacy_tmds_int_mode_set, + .commit = radeon_legacy_tmds_int_commit, + .disable = radeon_legacy_encoder_disable, +}; + + +static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + DRM_DEBUG_KMS("\n"); + + switch (mode) { + case DRM_MODE_DPMS_ON: + fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; + fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + fp2_gen_cntl |= RADEON_FP2_BLANK_EN; + fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + break; + } + + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + else + radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + +} + +static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); + radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON); + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, false); + else + radeon_combios_output_lock(encoder, false); +} + +static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t fp2_gen_cntl; + + DRM_DEBUG_KMS("\n"); + + if (rdev->is_atom_bios) { + radeon_encoder->pixel_clock = adjusted_mode->clock; + atombios_dvo_setup(encoder, ATOM_ENABLE); + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + } else { + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + + if (1) /* FIXME rgbBits == 8 */ + fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + + fp2_gen_cntl &= ~(RADEON_FP2_ON | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + + /* XXX: these are oem specific */ + if (ASIC_IS_R300(rdev)) { + if ((dev->pci_device == 0x4850) && + (dev->pci_subvendor == 0x1028) && + (dev->pci_subdevice == 0x2001)) /* Dell Inspiron 8600 */ + fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE; + else + fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE; + + /*if (mode->clock > 165000) + fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/ + } + if (!radeon_combios_external_tmds_setup(encoder)) + radeon_external_tmds_setup(encoder); + } + + if (radeon_crtc->crtc_id == 0) { + if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { + fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; + if (radeon_encoder->rmx_type != RMX_OFF) + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + else + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; + } else + fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; + } else { + if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { + fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else + fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; + } + + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); + else + radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); +} + +static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ + free(radeon_encoder->enc_priv, DRM_MEM_DRIVER); + drm_encoder_cleanup(encoder); + free(radeon_encoder, DRM_MEM_DRIVER); +} + +static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = { + .dpms = radeon_legacy_tmds_ext_dpms, + .mode_fixup = radeon_legacy_mode_fixup, + .prepare = radeon_legacy_tmds_ext_prepare, + .mode_set = radeon_legacy_tmds_ext_mode_set, + .commit = radeon_legacy_tmds_ext_commit, + .disable = radeon_legacy_encoder_disable, +}; + + +static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = { + .destroy = radeon_ext_tmds_enc_destroy, +}; + +static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0; + uint32_t tv_master_cntl = 0; + bool is_tv; + DRM_DEBUG_KMS("\n"); + + is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false; + + if (rdev->family == CHIP_R200) + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + else { + if (is_tv) + tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); + else + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); + } + + switch (mode) { + case DRM_MODE_DPMS_ON: + if (rdev->family == CHIP_R200) { + fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } else { + if (is_tv) + tv_master_cntl |= RADEON_TV_ON; + else + crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + + if (rdev->family == CHIP_R420 || + rdev->family == CHIP_R423 || + rdev->family == CHIP_RV410) + tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + else + tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + if (rdev->family == CHIP_R200) + fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + else { + if (is_tv) + tv_master_cntl &= ~RADEON_TV_ON; + else + crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; + + if (rdev->family == CHIP_R420 || + rdev->family == CHIP_R423 || + rdev->family == CHIP_RV410) + tv_dac_cntl |= (R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + else + tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + break; + } + + if (rdev->family == CHIP_R200) { + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + } else { + if (is_tv) + WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); + /* handled in radeon_crtc_dpms() */ + else if (!(rdev->flags & RADEON_SINGLE_CRTC)) + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + } + + if (rdev->is_atom_bios) + radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + else + radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); + +} + +static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); + radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + + radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON); + + if (rdev->is_atom_bios) + radeon_atom_output_lock(encoder, true); + else + radeon_combios_output_lock(encoder, true); +} + +static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; + uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0; + bool is_tv = false; + + DRM_DEBUG_KMS("\n"); + + is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false; + + if (rdev->family != CHIP_R200) { + tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); + if (rdev->family == CHIP_R420 || + rdev->family == CHIP_R423 || + rdev->family == CHIP_RV410) { + tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + R420_TV_DAC_TVENABLE); + } else { + tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD); + } + + tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD; + + if (is_tv) { + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) + tv_dac_cntl |= tv_dac->ntsc_tvdac_adj; + else + tv_dac_cntl |= tv_dac->pal_tvdac_adj; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J) + tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; + else + tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; + } else + tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 | + tv_dac->ps2_tvdac_adj); + + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + } + + if (ASIC_IS_R300(rdev)) { + gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1; + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + } else if (rdev->family != CHIP_R200) + disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + else if (rdev->family == CHIP_R200) + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + + if (rdev->family >= CHIP_R200) + disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); + + if (is_tv) { + uint32_t dac_cntl; + + dac_cntl = RREG32(RADEON_DAC_CNTL); + dac_cntl &= ~RADEON_DAC_TVO_EN; + WREG32(RADEON_DAC_CNTL, dac_cntl); + + if (ASIC_IS_R300(rdev)) + gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1; + + dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL; + if (radeon_crtc->crtc_id == 0) { + if (ASIC_IS_R300(rdev)) { + disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC | + RADEON_DISP_TV_SOURCE_CRTC); + } + if (rdev->family >= CHIP_R200) { + disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2; + } else { + disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } + } else { + if (ASIC_IS_R300(rdev)) { + disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC; + } + if (rdev->family >= CHIP_R200) { + disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2; + } else { + disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + } + WREG32(RADEON_DAC_CNTL2, dac2_cntl); + } else { + + dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL; + + if (radeon_crtc->crtc_id == 0) { + if (ASIC_IS_R300(rdev)) { + disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (rdev->family == CHIP_R200) { + fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + } else + disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } else { + if (ASIC_IS_R300(rdev)) { + disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (rdev->family == CHIP_R200) { + fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else + disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + WREG32(RADEON_DAC_CNTL2, dac2_cntl); + } + + if (ASIC_IS_R300(rdev)) { + WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + } else if (rdev->family != CHIP_R200) + WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + else if (rdev->family == CHIP_R200) + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + + if (rdev->family >= CHIP_R200) + WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl); + + if (is_tv) + radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode); + + if (rdev->is_atom_bios) + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); + else + radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); + +} + +static bool r300_legacy_tv_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + uint32_t disp_output_cntl, gpiopad_a, tmp; + bool found = false; + + /* save regs needed */ + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + dac_cntl2 = RREG32(RADEON_DAC_CNTL2); + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); + tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + + WREG32_P(RADEON_GPIOPAD_A, 0, ~1); + + WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL); + + WREG32(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT); + + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); + + WREG32(RADEON_DAC_EXT_CNTL, + RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN | + RADEON_DAC_FORCE_DATA_SEL_RGB | + (0xec << RADEON_DAC_FORCE_DATA_SHIFT)); + + WREG32(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT)); + + RREG32(RADEON_TV_DAC_CNTL); + DRM_MDELAY(4); + + WREG32(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT)); + + RREG32(RADEON_TV_DAC_CNTL); + DRM_MDELAY(6); + + tmp = RREG32(RADEON_TV_DAC_CNTL); + if ((tmp & RADEON_TV_DAC_GDACDET) != 0) { + found = true; + DRM_DEBUG_KMS("S-video TV connection detected\n"); + } else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) { + found = true; + DRM_DEBUG_KMS("Composite TV connection detected\n"); + } + + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32(RADEON_DAC_CNTL2, dac_cntl2); + WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + return found; +} + +static bool radeon_legacy_tv_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tv_dac_cntl, dac_cntl2; + uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp; + bool found = false; + + if (ASIC_IS_R300(rdev)) + return r300_legacy_tv_detect(encoder, connector); + + dac_cntl2 = RREG32(RADEON_DAC_CNTL2); + tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); + tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); + config_cntl = RREG32(RADEON_CONFIG_CNTL); + tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL); + + tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; + WREG32(RADEON_DAC_CNTL2, tmp); + + tmp = tv_master_cntl | RADEON_TV_ON; + tmp &= ~(RADEON_TV_ASYNC_RST | + RADEON_RESTART_PHASE_FIX | + RADEON_CRT_FIFO_CE_EN | + RADEON_TV_FIFO_CE_EN | + RADEON_RE_SYNC_NOW_SEL_MASK); + tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; + WREG32(RADEON_TV_MASTER_CNTL, tmp); + + tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT); + + if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) + tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); + else + tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); + WREG32(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | + RADEON_RED_MX_FORCE_DAC_DATA | + RADEON_GRN_MX_FORCE_DAC_DATA | + RADEON_BLU_MX_FORCE_DAC_DATA | + (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); + WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); + + DRM_MDELAY(3); + tmp = RREG32(RADEON_TV_DAC_CNTL); + if (tmp & RADEON_TV_DAC_GDACDET) { + found = true; + DRM_DEBUG_KMS("S-video TV connection detected\n"); + } else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) { + found = true; + DRM_DEBUG_KMS("Composite TV connection detected\n"); + } + + WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); + WREG32(RADEON_DAC_CNTL2, dac_cntl2); + return found; +} + +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; + uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + bool found = false; + int i; + + /* save the regs we need */ + gpio_monid = RREG32(RADEON_GPIO_MONID); + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = RREG32(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + WREG32(RADEON_GPIO_MONID, tmp); + + WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR)); + + WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + + WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B)); + + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = RREG32(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + found = true; + + if (found) + break; + + DRM_MDELAY(1); + if (!drm_can_sleep()) + DRM_MDELAY(1); + else + DRM_MSLEEP(1); + } + + /* restore the regs we used */ + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + WREG32(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + +static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + uint32_t gpiopad_a = 0, pixclks_cntl, tmp; + uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0; + enum drm_connector_status found = connector_status_disconnected; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + bool color = true; + struct drm_crtc *crtc; + + /* find out if crtc2 is in use or if this encoder is using it */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + if ((radeon_crtc->crtc_id == 1) && crtc->enabled) { + if (encoder->crtc != crtc) { + return connector_status_disconnected; + } + } + } + + if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO || + connector->connector_type == DRM_MODE_CONNECTOR_Composite || + connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) { + bool tv_detect; + + if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT)) + return connector_status_disconnected; + + tv_detect = radeon_legacy_tv_detect(encoder, connector); + if (tv_detect && tv_dac) + found = connector_status_connected; + return found; + } + + /* don't probe if the encoder is being used for something else not CRT related */ + if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) { + DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device); + return connector_status_disconnected; + } + + /* R200 uses an external DAC for secondary DAC */ + if (rdev->family == CHIP_R200) { + if (radeon_legacy_ext_dac_detect(encoder, connector)) + found = connector_status_connected; + return found; + } + + /* save the regs we need */ + pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); + + if (rdev->flags & RADEON_SINGLE_CRTC) { + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + } else { + if (ASIC_IS_R300(rdev)) { + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + } else { + disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + } + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } + tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); + dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); + dac_cntl2 = RREG32(RADEON_DAC_CNTL2); + + tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); + + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + WREG32(RADEON_CRTC_EXT_CNTL, tmp); + } else { + tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; + tmp |= RADEON_CRTC2_CRT2_ON | + (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); + WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + + if (ASIC_IS_R300(rdev)) { + WREG32_P(RADEON_GPIOPAD_A, 1, ~1); + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); + } else { + tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; + WREG32(RADEON_DISP_HW_DEBUG, tmp); + } + } + + tmp = RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_PS2; + + WREG32(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (ASIC_IS_R300(rdev)) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + WREG32(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; + WREG32(RADEON_DAC_CNTL2, tmp); + + DRM_MDELAY(10); + + if (ASIC_IS_R300(rdev)) { + if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) + found = connector_status_connected; + } else { + if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) + found = connector_status_connected; + } + + /* restore regs we used */ + WREG32(RADEON_DAC_CNTL2, dac_cntl2); + WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + + if (rdev->flags & RADEON_SINGLE_CRTC) { + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + } else { + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + if (ASIC_IS_R300(rdev)) { + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + } else { + WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + } + } + + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); + + return found; + +} + +static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = { + .dpms = radeon_legacy_tv_dac_dpms, + .mode_fixup = radeon_legacy_mode_fixup, + .prepare = radeon_legacy_tv_dac_prepare, + .mode_set = radeon_legacy_tv_dac_mode_set, + .commit = radeon_legacy_tv_dac_commit, + .detect = radeon_legacy_tv_dac_detect, + .disable = radeon_legacy_encoder_disable, +}; + + +static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + + +static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_int_tmds *tmds = NULL; + bool ret; + + tmds = malloc(sizeof(struct radeon_encoder_int_tmds), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + + if (!tmds) + return NULL; + + if (rdev->is_atom_bios) + ret = radeon_atombios_get_tmds_info(encoder, tmds); + else + ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds); + + if (ret == false) + radeon_legacy_get_tmds_info_from_table(encoder, tmds); + + return tmds; +} + +static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_ext_tmds *tmds = NULL; + bool ret; + + if (rdev->is_atom_bios) + return NULL; + + tmds = malloc(sizeof(struct radeon_encoder_ext_tmds), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + + if (!tmds) + return NULL; + + ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds); + + if (ret == false) + radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds); + + return tmds; +} + +void +radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + + /* see if we already added it */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->encoder_enum == encoder_enum) { + radeon_encoder->devices |= supported_device; + return; + } + + } + + /* add a new one */ + radeon_encoder = malloc(sizeof(struct radeon_encoder), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!radeon_encoder) + return; + + encoder = &radeon_encoder->base; + if (rdev->flags & RADEON_SINGLE_CRTC) + encoder->possible_crtcs = 0x1; + else + encoder->possible_crtcs = 0x3; + + radeon_encoder->enc_priv = NULL; + + radeon_encoder->encoder_enum = encoder_enum; + radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + radeon_encoder->devices = supported_device; + radeon_encoder->rmx_type = RMX_OFF; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + encoder->possible_crtcs = 0x1; + drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS); + drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); + if (rdev->is_atom_bios) + radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); + else + radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder); + radeon_encoder->rmx_type = RMX_FULL; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); + radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC); + drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs); + if (rdev->is_atom_bios) + radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder); + else + radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC); + drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); + if (rdev->is_atom_bios) + radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder); + else + radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder); + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs); + if (!rdev->is_atom_bios) + radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder); + break; + } +} diff --git a/sys/dev/drm2/radeon/radeon_legacy_tv.c b/sys/dev/drm2/radeon/radeon_legacy_tv.c new file mode 100644 index 00000000000..5311a48a56e --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_legacy_tv.c @@ -0,0 +1,926 @@ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" + +/* + * Integrated TV out support based on the GATOS code by + * Federico Ulivi + */ + + +/* + * Limits of h/v positions (hPos & vPos) + */ +#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */ +#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */ + +/* + * Unit for hPos (in TV clock periods) + */ +#define H_POS_UNIT 10 + +/* + * Indexes in h. code timing table for horizontal line position adjustment + */ +#define H_TABLE_POS1 6 +#define H_TABLE_POS2 8 + +/* + * Limits of hor. size (hSize) + */ +#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */ + +/* tv standard constants */ +#define NTSC_TV_CLOCK_T 233 +#define NTSC_TV_VFTOTAL 1 +#define NTSC_TV_LINES_PER_FRAME 525 +#define NTSC_TV_ZERO_H_SIZE 479166 +#define NTSC_TV_H_SIZE_UNIT 9478 + +#define PAL_TV_CLOCK_T 188 +#define PAL_TV_VFTOTAL 3 +#define PAL_TV_LINES_PER_FRAME 625 +#define PAL_TV_ZERO_H_SIZE 473200 +#define PAL_TV_H_SIZE_UNIT 9360 + +/* tv pll setting for 27 mhz ref clk */ +#define NTSC_TV_PLL_M_27 22 +#define NTSC_TV_PLL_N_27 175 +#define NTSC_TV_PLL_P_27 5 + +#define PAL_TV_PLL_M_27 113 +#define PAL_TV_PLL_N_27 668 +#define PAL_TV_PLL_P_27 3 + +/* tv pll setting for 14 mhz ref clk */ +#define NTSC_TV_PLL_M_14 33 +#define NTSC_TV_PLL_N_14 693 +#define NTSC_TV_PLL_P_14 7 + +#define PAL_TV_PLL_M_14 19 +#define PAL_TV_PLL_N_14 353 +#define PAL_TV_PLL_P_14 5 + +#define VERT_LEAD_IN_LINES 2 +#define FRAC_BITS 0xe +#define FRAC_MASK 0x3fff + +struct radeon_tv_mode_constants { + uint16_t hor_resolution; + uint16_t ver_resolution; + enum radeon_tv_std standard; + uint16_t hor_total; + uint16_t ver_total; + uint16_t hor_start; + uint16_t hor_syncstart; + uint16_t ver_syncstart; + unsigned def_restart; + uint16_t crtcPLL_N; + uint8_t crtcPLL_M; + uint8_t crtcPLL_post_div; + unsigned pix_to_tv; +}; + +static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = { + 0x0007, + 0x003f, + 0x0263, + 0x0a24, + 0x2a6b, + 0x0a36, + 0x126d, /* H_TABLE_POS1 */ + 0x1bfe, + 0x1a8f, /* H_TABLE_POS2 */ + 0x1ec7, + 0x3863, + 0x1bfe, + 0x1bfe, + 0x1a2a, + 0x1e95, + 0x0e31, + 0x201b, + 0 +}; + +static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = { + 0x2001, + 0x200d, + 0x1006, + 0x0c06, + 0x1006, + 0x1818, + 0x21e3, + 0x1006, + 0x0c06, + 0x1006, + 0x1817, + 0x21d4, + 0x0002, + 0 +}; + +static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = { + 0x0007, + 0x0058, + 0x027c, + 0x0a31, + 0x2a77, + 0x0a95, + 0x124f, /* H_TABLE_POS1 */ + 0x1bfe, + 0x1b22, /* H_TABLE_POS2 */ + 0x1ef9, + 0x387c, + 0x1bfe, + 0x1bfe, + 0x1b31, + 0x1eb5, + 0x0e43, + 0x201b, + 0 +}; + +static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = { + 0x2001, + 0x200c, + 0x1005, + 0x0c05, + 0x1005, + 0x1401, + 0x1821, + 0x2240, + 0x1005, + 0x0c05, + 0x1005, + 0x1401, + 0x1822, + 0x2230, + 0x0002, + 0 +}; + +/********************************************************************** + * + * availableModes + * + * Table of all allowed modes for tv output + * + **********************************************************************/ +static const struct radeon_tv_mode_constants available_tv_modes[] = { + { /* NTSC timing for 27 Mhz ref clk */ + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_NTSC, /* standard */ + 990, /* horTotal */ + 740, /* verTotal */ + 813, /* horStart */ + 824, /* horSyncStart */ + 632, /* verSyncStart */ + 625592, /* defRestart */ + 592, /* crtcPLL_N */ + 91, /* crtcPLL_M */ + 4, /* crtcPLL_postDiv */ + 1022, /* pixToTV */ + }, + { /* PAL timing for 27 Mhz ref clk */ + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_PAL, /* standard */ + 1144, /* horTotal */ + 706, /* verTotal */ + 812, /* horStart */ + 824, /* horSyncStart */ + 669, /* verSyncStart */ + 696700, /* defRestart */ + 1382, /* crtcPLL_N */ + 231, /* crtcPLL_M */ + 4, /* crtcPLL_postDiv */ + 759, /* pixToTV */ + }, + { /* NTSC timing for 14 Mhz ref clk */ + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_NTSC, /* standard */ + 1018, /* horTotal */ + 727, /* verTotal */ + 813, /* horStart */ + 840, /* horSyncStart */ + 633, /* verSyncStart */ + 630627, /* defRestart */ + 347, /* crtcPLL_N */ + 14, /* crtcPLL_M */ + 8, /* crtcPLL_postDiv */ + 1022, /* pixToTV */ + }, + { /* PAL timing for 14 Mhz ref clk */ + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_PAL, /* standard */ + 1131, /* horTotal */ + 742, /* verTotal */ + 813, /* horStart */ + 840, /* horSyncStart */ + 633, /* verSyncStart */ + 708369, /* defRestart */ + 211, /* crtcPLL_N */ + 9, /* crtcPLL_M */ + 8, /* crtcPLL_postDiv */ + 759, /* pixToTV */ + }, +}; + +#define N_AVAILABLE_MODES DRM_ARRAY_SIZE(available_tv_modes) + +static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder, + uint16_t *pll_ref_freq) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc; + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + const struct radeon_tv_mode_constants *const_ptr; + struct radeon_pll *pll; + + radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc); + if (radeon_crtc->crtc_id == 1) + pll = &rdev->clock.p2pll; + else + pll = &rdev->clock.p1pll; + + if (pll_ref_freq) + *pll_ref_freq = pll->reference_freq; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M) { + if (pll->reference_freq == 2700) + const_ptr = &available_tv_modes[0]; + else + const_ptr = &available_tv_modes[2]; + } else { + if (pll->reference_freq == 2700) + const_ptr = &available_tv_modes[1]; + else + const_ptr = &available_tv_modes[3]; + } + return const_ptr; +} + +static long YCOEF_value[5] = { 2, 2, 0, 4, 0 }; +static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 }; +static long SLOPE_value[5] = { 1, 2, 2, 4, 8 }; +static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 }; + +static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests, + unsigned n_wait_loops, unsigned cnt_threshold) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t save_pll_test; + unsigned int i, j; + + WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100); + save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL); + WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B); + + WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL); + for (i = 0; i < n_tests; i++) { + WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0); + for (j = 0; j < n_wait_loops; j++) + if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold) + break; + } + WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test); + WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff); +} + + +static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder, + uint16_t addr, uint32_t value) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + int i = 0; + + WREG32(RADEON_TV_HOST_WRITE_DATA, value); + + WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr); + WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT); + + do { + tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL); + if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0) + break; + i++; + } while (i < 10000); + WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0); +} + +#if 0 /* included for completeness */ +static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + int i = 0; + + WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr); + WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD); + + do { + tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL); + if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0) + break; + i++; + } while (i < 10000); + WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0); + return RREG32(RADEON_TV_HOST_READ_DATA); +} +#endif + +static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr) +{ + uint16_t h_table; + + switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) { + case 0: + h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL; + break; + case 1: + h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2; + break; + case 2: + h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2; + break; + default: + h_table = 0; + break; + } + return h_table; +} + +static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr) +{ + uint16_t v_table; + + switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) { + case 0: + v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1; + break; + case 1: + v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1; + break; + case 2: + v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1; + break; + default: + v_table = 0; + break; + } + return v_table; +} + +static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + uint16_t h_table, v_table; + uint32_t tmp; + int i; + + WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr); + h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr); + v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr); + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) { + tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]); + radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp); + if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0) + break; + } + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) { + tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]); + radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp); + if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0) + break; + } +} + +static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder) +{ + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart); + WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart); + WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart); +} + +static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + struct radeon_crtc *radeon_crtc; + int restart; + unsigned int h_total, v_total, f_total; + int v_offset, h_offset; + u16 p1, p2, h_inc; + bool h_changed; + const struct radeon_tv_mode_constants *const_ptr; + struct radeon_pll *pll; + + radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc); + if (radeon_crtc->crtc_id == 1) + pll = &rdev->clock.p2pll; + else + pll = &rdev->clock.p1pll; + + const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); + if (!const_ptr) + return false; + + h_total = const_ptr->hor_total; + v_total = const_ptr->ver_total; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) + f_total = NTSC_TV_VFTOTAL + 1; + else + f_total = PAL_TV_VFTOTAL + 1; + + /* adjust positions 1&2 in hor. cod timing table */ + h_offset = tv_dac->h_pos * H_POS_UNIT; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M) { + h_offset -= 50; + p1 = hor_timing_NTSC[H_TABLE_POS1]; + p2 = hor_timing_NTSC[H_TABLE_POS2]; + } else { + p1 = hor_timing_PAL[H_TABLE_POS1]; + p2 = hor_timing_PAL[H_TABLE_POS2]; + } + + p1 = (u16)((int)p1 + h_offset); + p2 = (u16)((int)p2 - h_offset); + + h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] || + p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]); + + tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1; + tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2; + + /* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */ + h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000; + + /* adjust restart */ + restart = const_ptr->def_restart; + + /* + * convert v_pos TV lines to n. of CRTC pixels + */ + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) + v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME); + else + v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME); + + restart -= v_offset + h_offset; + + DRM_DEBUG_KMS("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n", + const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart); + + tv_dac->tv.hrestart = restart % h_total; + restart /= h_total; + tv_dac->tv.vrestart = restart % v_total; + restart /= v_total; + tv_dac->tv.frestart = restart % f_total; + + DRM_DEBUG_KMS("compute_restart: F/H/V=%u,%u,%u\n", + (unsigned)tv_dac->tv.frestart, + (unsigned)tv_dac->tv.vrestart, + (unsigned)tv_dac->tv.hrestart); + + /* compute h_inc from hsize */ + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M) + h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) / + (tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE))); + else + h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) / + (tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE))); + + tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) | + ((u32)h_inc << RADEON_H_INC_SHIFT); + + DRM_DEBUG_KMS("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc); + + return h_changed; +} + +void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; + const struct radeon_tv_mode_constants *const_ptr; + struct radeon_crtc *radeon_crtc; + int i; + uint16_t pll_ref_freq; + uint32_t vert_space, flicker_removal, tmp; + uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl; + uint32_t tv_modulator_cntl1, tv_modulator_cntl2; + uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2; + uint32_t tv_pll_cntl, tv_pll_cntl1, tv_ftotal; + uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl; + uint32_t m, n, p; + const uint16_t *hor_timing; + const uint16_t *vert_timing; + + const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq); + if (!const_ptr) + return; + + radeon_crtc = to_radeon_crtc(encoder->crtc); + + tv_master_cntl = (RADEON_VIN_ASYNC_RST | + RADEON_CRT_FIFO_CE_EN | + RADEON_TV_FIFO_CE_EN | + RADEON_TV_ON); + + if (!ASIC_IS_R300(rdev)) + tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J) + tv_master_cntl |= RADEON_RESTART_PHASE_FIX; + + tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT | + RADEON_SYNC_TIP_LEVEL | + RADEON_YFLT_EN | + RADEON_UVFLT_EN | + (6 << RADEON_CY_FILT_BLEND_SHIFT)); + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J) { + tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) | + (0x3b << RADEON_BLANK_LEVEL_SHIFT); + tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } else if (tv_dac->tv_std == TV_STD_SCART_PAL) { + tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN; + tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } else { + tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN | + (0x3b << RADEON_SET_UP_LEVEL_SHIFT) | + (0x3b << RADEON_BLANK_LEVEL_SHIFT); + tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } + + + tv_rgb_cntl = (RADEON_RGB_DITHER_EN + | RADEON_TVOUT_SCALE_EN + | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT) + | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT) + | RADEON_RGB_ATTEN_SEL(0x3) + | RADEON_RGB_ATTEN_VAL(0xc)); + + if (radeon_crtc->crtc_id == 1) + tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2; + else { + if (radeon_crtc->rmx_type != RMX_OFF) + tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX; + else + tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1; + } + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) + vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME; + else + vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME; + + tmp = RREG32(RADEON_TV_VSCALER_CNTL1); + tmp &= 0xe3ff0000; + tmp |= (vert_space * (1 << FRAC_BITS) / 10000); + tv_vscaler_cntl1 = tmp; + + if (pll_ref_freq == 2700) + tv_vscaler_cntl1 |= RADEON_RESTART_FIELD; + + if (const_ptr->hor_resolution == 1024) + tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT); + else + tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT); + + /* scale up for int divide */ + tmp = const_ptr->ver_total * 2 * 1000; + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) { + tmp /= NTSC_TV_LINES_PER_FRAME; + } else { + tmp /= PAL_TV_LINES_PER_FRAME; + } + flicker_removal = (tmp + 500) / 1000; + + if (flicker_removal < 3) + flicker_removal = 3; + for (i = 0; i < DRM_ARRAY_SIZE(SLOPE_limit); ++i) { + if (flicker_removal == SLOPE_limit[i]) + break; + } + + tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + + 5001) / 10000 / 8 | ((SLOPE_value[i] * + (1 << (FRAC_BITS - 1)) / 8) << 16); + tv_y_fall_cntl = + (YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) | + RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) / + 1024; + tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG| + (flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024; + + tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0; + tv_vscaler_cntl2 |= (0x10 << 24) | + RADEON_DITHER_MODE | + RADEON_Y_OUTPUT_DITHER_EN | + RADEON_UV_OUTPUT_DITHER_EN | + RADEON_UV_TO_BUF_DITHER_EN; + + tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK; + tmp = ((16384 * 256 * 10) / tmp + 5) / 10; + tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000; + tv_dac->tv.timing_cntl = tmp; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) + tv_dac_cntl = tv_dac->ntsc_tvdac_adj; + else + tv_dac_cntl = tv_dac->pal_tvdac_adj; + + tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J) + tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; + else + tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J) { + if (pll_ref_freq == 2700) { + m = NTSC_TV_PLL_M_27; + n = NTSC_TV_PLL_N_27; + p = NTSC_TV_PLL_P_27; + } else { + m = NTSC_TV_PLL_M_14; + n = NTSC_TV_PLL_N_14; + p = NTSC_TV_PLL_P_14; + } + } else { + if (pll_ref_freq == 2700) { + m = PAL_TV_PLL_M_27; + n = PAL_TV_PLL_N_27; + p = PAL_TV_PLL_P_27; + } else { + m = PAL_TV_PLL_M_14; + n = PAL_TV_PLL_N_14; + p = PAL_TV_PLL_P_14; + } + } + + tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) | + (((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | + ((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | + (((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | + ((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); + + tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK) << RADEON_TVPCP_SHIFT) | + ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) | + ((1 & RADEON_TVPDC_MASK) << RADEON_TVPDC_SHIFT) | + RADEON_TVCLK_SRC_SEL_TVPLL | + RADEON_TVPLL_TEST_DIS); + + tv_dac->tv.tv_uv_adr = 0xc8; + + if (tv_dac->tv_std == TV_STD_NTSC || + tv_dac->tv_std == TV_STD_NTSC_J || + tv_dac->tv_std == TV_STD_PAL_M || + tv_dac->tv_std == TV_STD_PAL_60) { + tv_ftotal = NTSC_TV_VFTOTAL; + hor_timing = hor_timing_NTSC; + vert_timing = vert_timing_NTSC; + } else { + hor_timing = hor_timing_PAL; + vert_timing = vert_timing_PAL; + tv_ftotal = PAL_TV_VFTOTAL; + } + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) { + if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) { + if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0) + break; + } + + radeon_legacy_tv_init_restarts(encoder); + + /* play with DAC_CNTL */ + /* play with GPIOPAD_A */ + /* DISP_OUTPUT_CNTL */ + /* use reference freq */ + + /* program the TV registers */ + WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST | + RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST)); + + tmp = RREG32(RADEON_TV_DAC_CNTL); + tmp &= ~RADEON_TV_DAC_NBLANK; + tmp |= RADEON_TV_DAC_BGSLEEP | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD; + WREG32(RADEON_TV_DAC_CNTL, tmp); + + /* TV PLL */ + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL); + WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl); + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET); + + radeon_wait_pll_lock(encoder, 200, 800, 135); + + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET); + + radeon_wait_pll_lock(encoder, 300, 160, 27); + radeon_wait_pll_lock(encoder, 200, 800, 135); + + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf); + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL); + + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK); + WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP); + + /* TV HV */ + WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl); + WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1); + WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1); + WREG32(RADEON_TV_HSTART, const_ptr->hor_start); + + WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1); + WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1); + WREG32(RADEON_TV_FTOTAL, tv_ftotal); + WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1); + WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2); + + WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl); + WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl); + WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl); + + WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST | + RADEON_CRT_ASYNC_RST)); + + /* TV restarts */ + radeon_legacy_write_tv_restarts(radeon_encoder); + + /* tv timings */ + radeon_restore_tv_timing_tables(radeon_encoder); + + WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST)); + + /* tv std */ + WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE)); + WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl); + WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1); + WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2); + WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN | + RADEON_C_GRN_EN | + RADEON_CMP_BLU_EN | + RADEON_DAC_DITHER_EN)); + + WREG32(RADEON_TV_CRC_CNTL, 0); + + WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); + + WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) | + (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT))); + WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) | + (0x100 << RADEON_Y_GAIN_SHIFT))); + + WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); + +} + +void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder, + uint32_t *h_total_disp, uint32_t *h_sync_strt_wid, + uint32_t *v_total_disp, uint32_t *v_sync_strt_wid) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + const struct radeon_tv_mode_constants *const_ptr; + uint32_t tmp; + + const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); + if (!const_ptr) + return; + + *h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | + (((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); + + tmp = *h_sync_strt_wid; + tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR); + tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | + (const_ptr->hor_syncstart & 7); + *h_sync_strt_wid = tmp; + + *v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | + ((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT); + + tmp = *v_sync_strt_wid; + tmp &= ~RADEON_CRTC_V_SYNC_STRT; + tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); + *v_sync_strt_wid = tmp; +} + +static int get_post_div(int value) +{ + int post_div; + switch (value) { + case 1: post_div = 0; break; + case 2: post_div = 1; break; + case 3: post_div = 4; break; + case 4: post_div = 2; break; + case 6: post_div = 6; break; + case 8: post_div = 3; break; + case 12: post_div = 7; break; + case 16: + default: post_div = 5; break; + } + return post_div; +} + +void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder, + uint32_t *htotal_cntl, uint32_t *ppll_ref_div, + uint32_t *ppll_div_3, uint32_t *pixclks_cntl) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + const struct radeon_tv_mode_constants *const_ptr; + + const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); + if (!const_ptr) + return; + + *htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN; + + *ppll_ref_div = const_ptr->crtcPLL_M; + + *ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16); + *pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL); + *pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK; +} + +void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, + uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div, + uint32_t *p2pll_div_0, uint32_t *pixclks_cntl) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + const struct radeon_tv_mode_constants *const_ptr; + + const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); + if (!const_ptr) + return; + + *htotal2_cntl = (const_ptr->hor_total & 0x7); + + *p2pll_ref_div = const_ptr->crtcPLL_M; + + *p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16); + *pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; + *pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL; +} + diff --git a/sys/dev/drm2/radeon/radeon_mem.c b/sys/dev/drm2/radeon/radeon_mem.c new file mode 100644 index 00000000000..9ff87911373 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_mem.c @@ -0,0 +1,304 @@ +/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */ +/* + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_drv.h" + +/* Very simple allocator for GART memory, working on a static range + * already mapped into each client's address space. + */ + +static struct mem_block *split_block(struct mem_block *p, int start, int size, + struct drm_file *file_priv) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = malloc(sizeof(*newblock), + DRM_MEM_DRIVER, M_WAITOK); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->file_priv = NULL; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = malloc(sizeof(*newblock), + DRM_MEM_DRIVER, M_WAITOK); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->file_priv = NULL; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + + out: + /* Our block is in the middle */ + p->file_priv = file_priv; + return p; +} + +static struct mem_block *alloc_block(struct mem_block *heap, int size, + int align2, struct drm_file *file_priv) +{ + struct mem_block *p; + int mask = (1 << align2) - 1; + + list_for_each(p, heap) { + int start = (p->start + mask) & ~mask; + if (p->file_priv == NULL && start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); + } + + return NULL; +} + +static struct mem_block *find_block(struct mem_block *heap, int start) +{ + struct mem_block *p; + + list_for_each(p, heap) + if (p->start == start) + return p; + + return NULL; +} + +static void free_block(struct mem_block *p) +{ + p->file_priv = NULL; + + /* Assumes a single contiguous range. Needs a special file_priv in + * 'heap' to stop it being subsumed. + */ + if (p->next->file_priv == NULL) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + free(q, DRM_MEM_DRIVER); + } + + if (p->prev->file_priv == NULL) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + free(p, DRM_MEM_DRIVER); + } +} + +/* Initialize. How to check for an uninitialized heap? + */ +static int init_heap(struct mem_block **heap, int start, int size) +{ + struct mem_block *blocks = malloc(sizeof(*blocks), + DRM_MEM_DRIVER, M_WAITOK); + + if (!blocks) + return -ENOMEM; + + *heap = malloc(sizeof(**heap), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!*heap) { + free(blocks, DRM_MEM_DRIVER); + return -ENOMEM; + } + + blocks->start = start; + blocks->size = size; + blocks->file_priv = NULL; + blocks->next = blocks->prev = *heap; + + (*heap)->file_priv = (struct drm_file *) - 1; + (*heap)->next = (*heap)->prev = blocks; + return 0; +} + +/* Free all blocks associated with the releasing file. + */ +void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) +{ + struct mem_block *p; + + if (!heap || !heap->next) + return; + + list_for_each(p, heap) { + if (p->file_priv == file_priv) + p->file_priv = NULL; + } + + /* Assumes a single contiguous range. Needs a special file_priv in + * 'heap' to stop it being subsumed. + */ + list_for_each(p, heap) { + while (p->file_priv == NULL && p->next->file_priv == NULL) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + free(q, DRM_MEM_DRIVER); + } + } +} + +/* Shutdown. + */ +void radeon_mem_takedown(struct mem_block **heap) +{ + struct mem_block *p; + + if (!*heap) + return; + + for (p = (*heap)->next; p != *heap;) { + struct mem_block *q = p; + p = p->next; + free(q, DRM_MEM_DRIVER); + } + + free(*heap, DRM_MEM_DRIVER); + *heap = NULL; +} + +/* IOCTL HANDLERS */ + +static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) +{ + switch (region) { + case RADEON_MEM_REGION_GART: + return &dev_priv->gart_heap; + case RADEON_MEM_REGION_FB: + return &dev_priv->fb_heap; + default: + return NULL; + } +} + +int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_alloc_t *alloc = data; + struct mem_block *block, **heap; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + heap = get_heap(dev_priv, alloc->region); + if (!heap || !*heap) + return -EFAULT; + + /* Make things easier on ourselves: all allocations at least + * 4k aligned. + */ + if (alloc->alignment < 12) + alloc->alignment = 12; + + block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); + + if (!block) + return -ENOMEM; + + if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, + sizeof(int))) { + DRM_ERROR("copy_to_user\n"); + return -EFAULT; + } + + return 0; +} + +int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_free_t *memfree = data; + struct mem_block *block, **heap; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + heap = get_heap(dev_priv, memfree->region); + if (!heap || !*heap) + return -EFAULT; + + block = find_block(*heap, memfree->region_offset); + if (!block) + return -EFAULT; + + if (block->file_priv != file_priv) + return -EPERM; + + free_block(block); + return 0; +} + +int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_init_heap_t *initheap = data; + struct mem_block **heap; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + heap = get_heap(dev_priv, initheap->region); + if (!heap) + return -EFAULT; + + if (*heap) { + DRM_ERROR("heap already initialized?"); + return -EFAULT; + } + + return init_heap(heap, initheap->start, initheap->size); +} diff --git a/sys/dev/drm2/radeon/radeon_mode.h b/sys/dev/drm2/radeon/radeon_mode.h new file mode 100644 index 00000000000..ac39bc3ee82 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_mode.h @@ -0,0 +1,738 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Original Authors: + * Kevin E. Martin, Rickard E. Faith, Alan Hourihane + * + * Kernel port Author: Dave Airlie + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef RADEON_MODE_H +#define RADEON_MODE_H + +#include +#include +#include +#include +#include + +struct radeon_bo; +struct radeon_device; + +#define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base) +#define to_radeon_connector(x) container_of(x, struct radeon_connector, base) +#define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base) +#define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base) + +enum radeon_rmx_type { + RMX_OFF, + RMX_FULL, + RMX_CENTER, + RMX_ASPECT +}; + +enum radeon_tv_std { + TV_STD_NTSC, + TV_STD_PAL, + TV_STD_PAL_M, + TV_STD_PAL_60, + TV_STD_NTSC_J, + TV_STD_SCART_PAL, + TV_STD_SECAM, + TV_STD_PAL_CN, + TV_STD_PAL_N, +}; + +enum radeon_underscan_type { + UNDERSCAN_OFF, + UNDERSCAN_ON, + UNDERSCAN_AUTO, +}; + +enum radeon_hpd_id { + RADEON_HPD_1 = 0, + RADEON_HPD_2, + RADEON_HPD_3, + RADEON_HPD_4, + RADEON_HPD_5, + RADEON_HPD_6, + RADEON_HPD_NONE = 0xff, +}; + +#define RADEON_MAX_I2C_BUS 16 + +/* radeon gpio-based i2c + * 1. "mask" reg and bits + * grabs the gpio pins for software use + * 0=not held 1=held + * 2. "a" reg and bits + * output pin value + * 0=low 1=high + * 3. "en" reg and bits + * sets the pin direction + * 0=input 1=output + * 4. "y" reg and bits + * input pin value + * 0=low 1=high + */ +struct radeon_i2c_bus_rec { + bool valid; + /* id used by atom */ + uint8_t i2c_id; + /* id used by atom */ + enum radeon_hpd_id hpd; + /* can be used with hw i2c engine */ + bool hw_capable; + /* uses multi-media i2c engine */ + bool mm_i2c; + /* regs and bits */ + uint32_t mask_clk_reg; + uint32_t mask_data_reg; + uint32_t a_clk_reg; + uint32_t a_data_reg; + uint32_t en_clk_reg; + uint32_t en_data_reg; + uint32_t y_clk_reg; + uint32_t y_data_reg; + uint32_t mask_clk_mask; + uint32_t mask_data_mask; + uint32_t a_clk_mask; + uint32_t a_data_mask; + uint32_t en_clk_mask; + uint32_t en_data_mask; + uint32_t y_clk_mask; + uint32_t y_data_mask; +}; + +struct radeon_tmds_pll { + uint32_t freq; + uint32_t value; +}; + +#define RADEON_MAX_BIOS_CONNECTOR 16 + +/* pll flags */ +#define RADEON_PLL_USE_BIOS_DIVS (1 << 0) +#define RADEON_PLL_NO_ODD_POST_DIV (1 << 1) +#define RADEON_PLL_USE_REF_DIV (1 << 2) +#define RADEON_PLL_LEGACY (1 << 3) +#define RADEON_PLL_PREFER_LOW_REF_DIV (1 << 4) +#define RADEON_PLL_PREFER_HIGH_REF_DIV (1 << 5) +#define RADEON_PLL_PREFER_LOW_FB_DIV (1 << 6) +#define RADEON_PLL_PREFER_HIGH_FB_DIV (1 << 7) +#define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) +#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) +#define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) +#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) +#define RADEON_PLL_USE_POST_DIV (1 << 12) +#define RADEON_PLL_IS_LCD (1 << 13) +#define RADEON_PLL_PREFER_MINM_OVER_MAXP (1 << 14) + +struct radeon_pll { + /* reference frequency */ + uint32_t reference_freq; + + /* fixed dividers */ + uint32_t reference_div; + uint32_t post_div; + + /* pll in/out limits */ + uint32_t pll_in_min; + uint32_t pll_in_max; + uint32_t pll_out_min; + uint32_t pll_out_max; + uint32_t lcd_pll_out_min; + uint32_t lcd_pll_out_max; + uint32_t best_vco; + + /* divider limits */ + uint32_t min_ref_div; + uint32_t max_ref_div; + uint32_t min_post_div; + uint32_t max_post_div; + uint32_t min_feedback_div; + uint32_t max_feedback_div; + uint32_t min_frac_feedback_div; + uint32_t max_frac_feedback_div; + + /* flags for the current clock */ + uint32_t flags; + + /* pll id */ + uint32_t id; +}; + +struct radeon_i2c_chan { + device_t adapter; + device_t iic_bus; + struct drm_device *dev; + struct radeon_i2c_bus_rec rec; + char name[48]; +}; + +/* mostly for macs, but really any system without connector tables */ +enum radeon_connector_table { + CT_NONE = 0, + CT_GENERIC, + CT_IBOOK, + CT_POWERBOOK_EXTERNAL, + CT_POWERBOOK_INTERNAL, + CT_POWERBOOK_VGA, + CT_MINI_EXTERNAL, + CT_MINI_INTERNAL, + CT_IMAC_G5_ISIGHT, + CT_EMAC, + CT_RN50_POWER, + CT_MAC_X800, + CT_MAC_G5_9600, + CT_SAM440EP, + CT_MAC_G4_SILVER +}; + +enum radeon_dvo_chip { + DVO_SIL164, + DVO_SIL1178, +}; + +struct radeon_fbdev; + +struct radeon_afmt { + bool enabled; + int offset; + bool last_buffer_filled_status; + int id; +}; + +struct radeon_mode_info { + struct atom_context *atom_context; + struct card_info *atom_card_info; + enum radeon_connector_table connector_table; + bool mode_config_initialized; + struct radeon_crtc *crtcs[6]; + struct radeon_afmt *afmt[6]; + /* DVI-I properties */ + struct drm_property *coherent_mode_property; + /* DAC enable load detect */ + struct drm_property *load_detect_property; + /* TV standard */ + struct drm_property *tv_std_property; + /* legacy TMDS PLL detect */ + struct drm_property *tmds_pll_property; + /* underscan */ + struct drm_property *underscan_property; + struct drm_property *underscan_hborder_property; + struct drm_property *underscan_vborder_property; + /* hardcoded DFP edid from BIOS */ + struct edid *bios_hardcoded_edid; + int bios_hardcoded_edid_size; + + /* pointer to fbdev info structure */ + struct radeon_fbdev *rfbdev; + /* firmware flags */ + u16 firmware_flags; + /* pointer to backlight encoder */ + struct radeon_encoder *bl_encoder; +}; + +#define RADEON_MAX_BL_LEVEL 0xFF + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +struct radeon_backlight_privdata { + struct radeon_encoder *encoder; + uint8_t negative; +}; + +#endif + +#define MAX_H_CODE_TIMING_LEN 32 +#define MAX_V_CODE_TIMING_LEN 32 + +/* need to store these as reading + back code tables is excessive */ +struct radeon_tv_regs { + uint32_t tv_uv_adr; + uint32_t timing_cntl; + uint32_t hrestart; + uint32_t vrestart; + uint32_t frestart; + uint16_t h_code_timing[MAX_H_CODE_TIMING_LEN]; + uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN]; +}; + +struct radeon_atom_ss { + uint16_t percentage; + uint8_t type; + uint16_t step; + uint8_t delay; + uint8_t range; + uint8_t refdiv; + /* asic_ss */ + uint16_t rate; + uint16_t amount; +}; + +struct radeon_crtc { + struct drm_crtc base; + int crtc_id; + u16 lut_r[256], lut_g[256], lut_b[256]; + bool enabled; + bool can_tile; + bool in_mode_set; + uint32_t crtc_offset; + struct drm_gem_object *cursor_bo; + uint64_t cursor_addr; + int cursor_width; + int cursor_height; + uint32_t legacy_display_base_addr; + uint32_t legacy_cursor_offset; + enum radeon_rmx_type rmx_type; + u8 h_border; + u8 v_border; + fixed20_12 vsc; + fixed20_12 hsc; + struct drm_display_mode native_mode; + int pll_id; + /* page flipping */ + struct radeon_unpin_work *unpin_work; + int deferred_flip_completion; + /* pll sharing */ + struct radeon_atom_ss ss; + bool ss_enabled; + u32 adjusted_clock; + int bpc; + u32 pll_reference_div; + u32 pll_post_div; + u32 pll_flags; + struct drm_encoder *encoder; + struct drm_connector *connector; +}; + +struct radeon_encoder_primary_dac { + /* legacy primary dac */ + uint32_t ps2_pdac_adj; +}; + +struct radeon_encoder_lvds { + /* legacy lvds */ + uint16_t panel_vcc_delay; + uint8_t panel_pwr_delay; + uint8_t panel_digon_delay; + uint8_t panel_blon_delay; + uint16_t panel_ref_divider; + uint8_t panel_post_divider; + uint16_t panel_fb_divider; + bool use_bios_dividers; + uint32_t lvds_gen_cntl; + /* panel mode */ + struct drm_display_mode native_mode; + struct backlight_device *bl_dev; + int dpms_mode; + uint8_t backlight_level; +}; + +struct radeon_encoder_tv_dac { + /* legacy tv dac */ + uint32_t ps2_tvdac_adj; + uint32_t ntsc_tvdac_adj; + uint32_t pal_tvdac_adj; + + int h_pos; + int v_pos; + int h_size; + int supported_tv_stds; + bool tv_on; + enum radeon_tv_std tv_std; + struct radeon_tv_regs tv; +}; + +struct radeon_encoder_int_tmds { + /* legacy int tmds */ + struct radeon_tmds_pll tmds_pll[4]; +}; + +struct radeon_encoder_ext_tmds { + /* tmds over dvo */ + struct radeon_i2c_chan *i2c_bus; + uint8_t slave_addr; + enum radeon_dvo_chip dvo_chip; +}; + +/* spread spectrum */ +struct radeon_encoder_atom_dig { + bool linkb; + /* atom dig */ + bool coherent_mode; + int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB, etc. */ + /* atom lvds/edp */ + uint32_t lcd_misc; + uint16_t panel_pwr_delay; + uint32_t lcd_ss_id; + /* panel mode */ + struct drm_display_mode native_mode; + struct backlight_device *bl_dev; + int dpms_mode; + uint8_t backlight_level; + int panel_mode; + struct radeon_afmt *afmt; +}; + +struct radeon_encoder_atom_dac { + enum radeon_tv_std tv_std; +}; + +struct radeon_encoder { + struct drm_encoder base; + uint32_t encoder_enum; + uint32_t encoder_id; + uint32_t devices; + uint32_t active_device; + uint32_t flags; + uint32_t pixel_clock; + enum radeon_rmx_type rmx_type; + enum radeon_underscan_type underscan_type; + uint32_t underscan_hborder; + uint32_t underscan_vborder; + struct drm_display_mode native_mode; + void *enc_priv; + int audio_polling_active; + bool is_ext_encoder; + u16 caps; +}; + +struct radeon_connector_atom_dig { + uint32_t igp_lane_info; + /* displayport */ + struct radeon_i2c_chan *dp_i2c_bus; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 dp_sink_type; + int dp_clock; + int dp_lane_count; + bool edp_on; +}; + +struct radeon_gpio_rec { + bool valid; + u8 id; + u32 reg; + u32 mask; +}; + +struct radeon_hpd { + enum radeon_hpd_id hpd; + u8 plugged_state; + struct radeon_gpio_rec gpio; +}; + +struct radeon_router { + u32 router_id; + struct radeon_i2c_bus_rec i2c_info; + u8 i2c_addr; + /* i2c mux */ + bool ddc_valid; + u8 ddc_mux_type; + u8 ddc_mux_control_pin; + u8 ddc_mux_state; + /* clock/data mux */ + bool cd_valid; + u8 cd_mux_type; + u8 cd_mux_control_pin; + u8 cd_mux_state; +}; + +struct radeon_connector { + struct drm_connector base; + uint32_t connector_id; + uint32_t devices; + struct radeon_i2c_chan *ddc_bus; + /* some systems have an hdmi and vga port with a shared ddc line */ + bool shared_ddc; + bool use_digital; + /* we need to mind the EDID between detect + and get modes due to analog/digital/tvencoder */ + struct edid *edid; + void *con_priv; + bool dac_load_detect; + bool detected_by_load; /* if the connection status was determined by load */ + uint16_t connector_object_id; + struct radeon_hpd hpd; + struct radeon_router router; + struct radeon_i2c_chan *router_bus; +}; + +struct radeon_framebuffer { + struct drm_framebuffer base; + struct drm_gem_object *obj; +}; + +#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ + ((em) == ATOM_ENCODER_MODE_DP_MST)) + +extern enum radeon_tv_std +radeon_combios_get_tv_info(struct radeon_device *rdev); +extern enum radeon_tv_std +radeon_atombios_get_tv_info(struct radeon_device *rdev); + +extern struct drm_connector * +radeon_get_connector_for_encoder(struct drm_encoder *encoder); +extern struct drm_connector * +radeon_get_connector_for_encoder_init(struct drm_encoder *encoder); +extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, + u32 pixel_clock); + +extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder); +extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector); +extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector); +extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector); +extern int radeon_get_monitor_bpc(struct drm_connector *connector); + +extern void radeon_connector_hotplug(struct drm_connector *connector); +extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, + struct drm_display_mode *mode); +extern void radeon_dp_set_link_config(struct drm_connector *connector, + const struct drm_display_mode *mode); +extern void radeon_dp_link_train(struct drm_encoder *encoder, + struct drm_connector *connector); +extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); +extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); +extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); +extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder, + struct drm_connector *connector); +extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); +extern void radeon_atom_encoder_init(struct radeon_device *rdev); +extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev); +extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, + int action, uint8_t lane_num, + uint8_t lane_set); +extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); +extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); +extern int radeon_dp_i2c_aux_ch(device_t dev, int mode, + u8 write_byte, u8 *read_byte); + +extern void radeon_i2c_init(struct radeon_device *rdev); +extern void radeon_i2c_fini(struct radeon_device *rdev); +extern void radeon_combios_i2c_init(struct radeon_device *rdev); +extern void radeon_atombios_i2c_init(struct radeon_device *rdev); +extern void radeon_i2c_add(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *rec, + const char *name); +extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *i2c_bus); +extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name); +extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name); +extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c); +extern void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, + u8 slave_addr, + u8 addr, + u8 *val); +extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, + u8 slave_addr, + u8 addr, + u8 val); +extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); +extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); +extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); +extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); + +extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); + +extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, + struct radeon_atom_ss *ss, + int id); +extern bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, + struct radeon_atom_ss *ss, + int id, u32 clock); + +extern void radeon_compute_pll_legacy(struct radeon_pll *pll, + uint64_t freq, + uint32_t *dot_clock_p, + uint32_t *fb_div_p, + uint32_t *frac_fb_div_p, + uint32_t *ref_div_p, + uint32_t *post_div_p); + +extern void radeon_compute_pll_avivo(struct radeon_pll *pll, + u32 freq, + u32 *dot_clock_p, + u32 *fb_div_p, + u32 *frac_fb_div_p, + u32 *ref_div_p, + u32 *post_div_p); + +extern void radeon_setup_encoder_clones(struct drm_device *dev); + +struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); +struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv); +struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv); +struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index); +struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index); +extern void atombios_dvo_setup(struct drm_encoder *encoder, int action); +extern void atombios_digital_setup(struct drm_encoder *encoder, int action); +extern int atombios_get_encoder_mode(struct drm_encoder *encoder); +extern bool atombios_set_edp_panel_power(struct drm_connector *connector, int action); +extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); + +extern void radeon_crtc_load_lut(struct drm_crtc *crtc); +extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); +extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, + enum mode_set_atomic state); +extern int atombios_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb); +extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); + +extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); +extern int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, + enum mode_set_atomic state); +extern int radeon_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic); +extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height); +extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y); + +extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + int *vpos, int *hpos); + +extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); +extern struct edid * +radeon_bios_get_hardcoded_edid(struct radeon_device *rdev); +extern bool radeon_atom_get_clock_info(struct drm_device *dev); +extern bool radeon_combios_get_clock_info(struct drm_device *dev); +extern struct radeon_encoder_atom_dig * +radeon_atombios_get_lvds_info(struct radeon_encoder *encoder); +extern bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds); +extern bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds); +extern bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_int_tmds *tmds); +extern bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds); +extern bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, + struct radeon_encoder_ext_tmds *tmds); +extern struct radeon_encoder_primary_dac * +radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder); +extern struct radeon_encoder_tv_dac * +radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder); +extern struct radeon_encoder_lvds * +radeon_combios_get_lvds_info(struct radeon_encoder *encoder); +extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder); +extern struct radeon_encoder_tv_dac * +radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder); +extern struct radeon_encoder_primary_dac * +radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder); +extern bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder); +extern void radeon_external_tmds_setup(struct drm_encoder *encoder); +extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock); +extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev); +extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock); +extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev); +extern void radeon_save_bios_scratch_regs(struct radeon_device *rdev); +extern void radeon_restore_bios_scratch_regs(struct radeon_device *rdev); +extern void +radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc); +extern void +radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on); +extern void +radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc); +extern void +radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on); +extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno); +extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno); +int radeon_framebuffer_init(struct drm_device *dev, + struct radeon_framebuffer *rfb, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj); + +int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); +bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev); +bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev); +void radeon_atombios_init_crtc(struct drm_device *dev, + struct radeon_crtc *radeon_crtc); +void radeon_legacy_init_crtc(struct drm_device *dev, + struct radeon_crtc *radeon_crtc); + +void radeon_get_clock_info(struct drm_device *dev); + +extern bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev); +extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct drm_device *dev); + +void radeon_enc_destroy(struct drm_encoder *encoder); +void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); +void radeon_combios_asic_init(struct drm_device *dev); +bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); +void radeon_panel_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode); +void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc); + +/* legacy tv */ +void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder, + uint32_t *h_total_disp, uint32_t *h_sync_strt_wid, + uint32_t *v_total_disp, uint32_t *v_sync_strt_wid); +void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder, + uint32_t *htotal_cntl, uint32_t *ppll_ref_div, + uint32_t *ppll_div_3, uint32_t *pixclks_cntl); +void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, + uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div, + uint32_t *p2pll_div_0, uint32_t *pixclks_cntl); +void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + +/* fbdev layer */ +int radeon_fbdev_init(struct radeon_device *rdev); +void radeon_fbdev_fini(struct radeon_device *rdev); +void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); +int radeon_fbdev_total_size(struct radeon_device *rdev); +bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); + +void radeon_fb_output_poll_changed(struct radeon_device *rdev); + +void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); + +int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); +#endif diff --git a/sys/dev/drm2/radeon/radeon_object.c b/sys/dev/drm2/radeon/radeon_object.c new file mode 100644 index 00000000000..30d3d81c82a --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_object.c @@ -0,0 +1,651 @@ +/* + * Copyright 2009 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: + * Jerome Glisse + * Thomas Hellstrom + * Dave Airlie + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" +#ifdef DUMBBELL_WIP +#include "radeon_trace.h" +#endif /* DUMBBELL_WIP */ + + +static void radeon_bo_clear_surface_reg(struct radeon_bo *bo); + +/* + * To exclude mutual BO access we rely on bo_reserve exclusion, as all + * function are calling it. + */ + +static void radeon_bo_clear_va(struct radeon_bo *bo) +{ + struct radeon_bo_va *bo_va, *tmp; + + list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) { + /* remove from all vm address space */ + radeon_vm_bo_rmv(bo->rdev, bo_va); + } +} + +static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) +{ + struct radeon_bo *bo; + + bo = container_of(tbo, struct radeon_bo, tbo); + sx_xlock(&bo->rdev->gem.mutex); + list_del_init(&bo->list); + sx_xunlock(&bo->rdev->gem.mutex); + radeon_bo_clear_surface_reg(bo); + radeon_bo_clear_va(bo); + drm_gem_object_release(&bo->gem_base); + free(bo, DRM_MEM_DRIVER); +} + +bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo) +{ + if (bo->destroy == &radeon_ttm_bo_destroy) + return true; + return false; +} + +void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) +{ + u32 c = 0; + + rbo->placement.fpfn = 0; + rbo->placement.lpfn = 0; + rbo->placement.placement = rbo->placements; + rbo->placement.busy_placement = rbo->placements; + if (domain & RADEON_GEM_DOMAIN_VRAM) + rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_VRAM; + if (domain & RADEON_GEM_DOMAIN_GTT) { + if (rbo->rdev->flags & RADEON_IS_AGP) { + rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; + } else { + rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; + } + } + if (domain & RADEON_GEM_DOMAIN_CPU) { + if (rbo->rdev->flags & RADEON_IS_AGP) { + rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM; + } else { + rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; + } + } + if (!c) + rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + rbo->placement.num_placement = c; + rbo->placement.num_busy_placement = c; +} + +int radeon_bo_create(struct radeon_device *rdev, + unsigned long size, int byte_align, bool kernel, u32 domain, + struct sg_table *sg, struct radeon_bo **bo_ptr) +{ + struct radeon_bo *bo; + enum ttm_bo_type type; + unsigned long page_align = roundup2(byte_align, PAGE_SIZE) >> PAGE_SHIFT; + size_t acc_size; + int r; + + size = roundup2(size, PAGE_SIZE); + + if (kernel) { + type = ttm_bo_type_kernel; + } else if (sg) { + type = ttm_bo_type_sg; + } else { + type = ttm_bo_type_device; + } + *bo_ptr = NULL; + + acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, + sizeof(struct radeon_bo)); + + bo = malloc(sizeof(struct radeon_bo), + DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (bo == NULL) + return -ENOMEM; + r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size); + if (unlikely(r)) { + free(bo, DRM_MEM_DRIVER); + return r; + } + bo->rdev = rdev; + bo->gem_base.driver_private = NULL; + bo->surface_reg = -1; + INIT_LIST_HEAD(&bo->list); + INIT_LIST_HEAD(&bo->va); + radeon_ttm_placement_from_domain(bo, domain); + /* Kernel allocation are uninterruptible */ + sx_slock(&rdev->pm.mclk_lock); + r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, + &bo->placement, page_align, !kernel, NULL, + acc_size, sg, &radeon_ttm_bo_destroy); + sx_sunlock(&rdev->pm.mclk_lock); + if (unlikely(r != 0)) { + return r; + } + *bo_ptr = bo; + +#ifdef DUMBBELL_WIP + trace_radeon_bo_create(bo); +#endif /* DUMBBELL_WIP */ + + return 0; +} + +int radeon_bo_kmap(struct radeon_bo *bo, void **ptr) +{ + bool is_iomem; + int r; + + if (bo->kptr) { + if (ptr) { + *ptr = bo->kptr; + } + return 0; + } + r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap); + if (r) { + return r; + } + bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem); + if (ptr) { + *ptr = bo->kptr; + } + radeon_bo_check_tiling(bo, 0, 0); + return 0; +} + +void radeon_bo_kunmap(struct radeon_bo *bo) +{ + if (bo->kptr == NULL) + return; + bo->kptr = NULL; + radeon_bo_check_tiling(bo, 0, 0); + ttm_bo_kunmap(&bo->kmap); +} + +void radeon_bo_unref(struct radeon_bo **bo) +{ + struct ttm_buffer_object *tbo; + struct radeon_device *rdev; + + if ((*bo) == NULL) + return; + rdev = (*bo)->rdev; + tbo = &((*bo)->tbo); + sx_slock(&rdev->pm.mclk_lock); + ttm_bo_unref(&tbo); + sx_sunlock(&rdev->pm.mclk_lock); + if (tbo == NULL) + *bo = NULL; +} + +int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, + u64 *gpu_addr) +{ + int r, i; + + if (bo->pin_count) { + bo->pin_count++; + if (gpu_addr) + *gpu_addr = radeon_bo_gpu_offset(bo); + + if (max_offset != 0) { + u64 domain_start; + + if (domain == RADEON_GEM_DOMAIN_VRAM) + domain_start = bo->rdev->mc.vram_start; + else + domain_start = bo->rdev->mc.gtt_start; + if (max_offset < (radeon_bo_gpu_offset(bo) - domain_start)) { + DRM_ERROR("radeon_bo_pin_restricted: " + "max_offset(%ju) < " + "(radeon_bo_gpu_offset(%ju) - " + "domain_start(%ju)", + (uintmax_t)max_offset, (uintmax_t)radeon_bo_gpu_offset(bo), + (uintmax_t)domain_start); + } + } + + return 0; + } + radeon_ttm_placement_from_domain(bo, domain); + if (domain == RADEON_GEM_DOMAIN_VRAM) { + /* force to pin into visible video ram */ + bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT; + } + if (max_offset) { + u64 lpfn = max_offset >> PAGE_SHIFT; + + if (!bo->placement.lpfn) + bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT; + + if (lpfn < bo->placement.lpfn) + bo->placement.lpfn = lpfn; + } + for (i = 0; i < bo->placement.num_placement; i++) + bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; + r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); + if (likely(r == 0)) { + bo->pin_count = 1; + if (gpu_addr != NULL) + *gpu_addr = radeon_bo_gpu_offset(bo); + } + if (unlikely(r != 0)) + dev_err(bo->rdev->dev, "%p pin failed\n", bo); + return r; +} + +int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) +{ + return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr); +} + +int radeon_bo_unpin(struct radeon_bo *bo) +{ + int r, i; + + if (!bo->pin_count) { + dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo); + return 0; + } + bo->pin_count--; + if (bo->pin_count) + return 0; + for (i = 0; i < bo->placement.num_placement; i++) + bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT; + r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); + if (unlikely(r != 0)) + dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo); + return r; +} + +int radeon_bo_evict_vram(struct radeon_device *rdev) +{ + /* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */ + if (0 && (rdev->flags & RADEON_IS_IGP)) { + if (rdev->mc.igp_sideport_enabled == false) + /* Useless to evict on IGP chips */ + return 0; + } + return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM); +} + +void radeon_bo_force_delete(struct radeon_device *rdev) +{ + struct radeon_bo *bo, *n; + + if (list_empty(&rdev->gem.objects)) { + return; + } + dev_err(rdev->dev, "Userspace still has active objects !\n"); + list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { + dev_err(rdev->dev, "%p %p %lu %lu force free\n", + &bo->gem_base, bo, (unsigned long)bo->gem_base.size, + *((unsigned long *)&bo->gem_base.refcount)); + sx_xlock(&bo->rdev->gem.mutex); + list_del_init(&bo->list); + sx_xunlock(&bo->rdev->gem.mutex); + /* this should unref the ttm bo */ + drm_gem_object_unreference(&bo->gem_base); + } +} + +int radeon_bo_init(struct radeon_device *rdev) +{ + /* Add an MTRR for the VRAM */ + rdev->mc.vram_mtrr = drm_mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, + DRM_MTRR_WC); + DRM_INFO("Detected VRAM RAM=%juM, BAR=%juM\n", + (uintmax_t)rdev->mc.mc_vram_size >> 20, + (uintmax_t)rdev->mc.aper_size >> 20); + DRM_INFO("RAM width %dbits %cDR\n", + rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); + return radeon_ttm_init(rdev); +} + +void radeon_bo_fini(struct radeon_device *rdev) +{ + radeon_ttm_fini(rdev); +} + +void radeon_bo_list_add_object(struct radeon_bo_list *lobj, + struct list_head *head) +{ + if (lobj->wdomain) { + list_add(&lobj->tv.head, head); + } else { + list_add_tail(&lobj->tv.head, head); + } +} + +int radeon_bo_list_validate(struct list_head *head) +{ + struct radeon_bo_list *lobj; + struct radeon_bo *bo; + u32 domain; + int r; + + r = ttm_eu_reserve_buffers(head); + if (unlikely(r != 0)) { + return r; + } + list_for_each_entry(lobj, head, tv.head) { + bo = lobj->bo; + if (!bo->pin_count) { + domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; + + retry: + radeon_ttm_placement_from_domain(bo, domain); + r = ttm_bo_validate(&bo->tbo, &bo->placement, + true, false); + if (unlikely(r)) { + if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { + domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } + return r; + } + } + lobj->gpu_offset = radeon_bo_gpu_offset(bo); + lobj->tiling_flags = bo->tiling_flags; + } + return 0; +} + +#ifdef DUMBBELL_WIP +int radeon_bo_fbdev_mmap(struct radeon_bo *bo, + struct vm_area_struct *vma) +{ + return ttm_fbdev_mmap(vma, &bo->tbo); +} +#endif /* DUMBBELL_WIP */ + +int radeon_bo_get_surface_reg(struct radeon_bo *bo) +{ + struct radeon_device *rdev = bo->rdev; + struct radeon_surface_reg *reg; + struct radeon_bo *old_object; + int steal; + int i; + + KASSERT(radeon_bo_is_reserved(bo), + ("radeon_bo_get_surface_reg: radeon_bo is not reserved")); + + if (!bo->tiling_flags) + return 0; + + if (bo->surface_reg >= 0) { + reg = &rdev->surface_regs[bo->surface_reg]; + i = bo->surface_reg; + goto out; + } + + steal = -1; + for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { + + reg = &rdev->surface_regs[i]; + if (!reg->bo) + break; + + old_object = reg->bo; + if (old_object->pin_count == 0) + steal = i; + } + + /* if we are all out */ + if (i == RADEON_GEM_MAX_SURFACES) { + if (steal == -1) + return -ENOMEM; + /* find someone with a surface reg and nuke their BO */ + reg = &rdev->surface_regs[steal]; + old_object = reg->bo; + /* blow away the mapping */ + DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object); + ttm_bo_unmap_virtual(&old_object->tbo); + old_object->surface_reg = -1; + i = steal; + } + + bo->surface_reg = i; + reg->bo = bo; + +out: + radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch, + bo->tbo.mem.start << PAGE_SHIFT, + bo->tbo.num_pages << PAGE_SHIFT); + return 0; +} + +static void radeon_bo_clear_surface_reg(struct radeon_bo *bo) +{ + struct radeon_device *rdev = bo->rdev; + struct radeon_surface_reg *reg; + + if (bo->surface_reg == -1) + return; + + reg = &rdev->surface_regs[bo->surface_reg]; + radeon_clear_surface_reg(rdev, bo->surface_reg); + + reg->bo = NULL; + bo->surface_reg = -1; +} + +int radeon_bo_set_tiling_flags(struct radeon_bo *bo, + uint32_t tiling_flags, uint32_t pitch) +{ + struct radeon_device *rdev = bo->rdev; + int r; + + if (rdev->family >= CHIP_CEDAR) { + unsigned bankw, bankh, mtaspect, tilesplit, stilesplit; + + bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; + bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; + mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; + tilesplit = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK; + stilesplit = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; + switch (bankw) { + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + return -EINVAL; + } + switch (bankh) { + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + return -EINVAL; + } + switch (mtaspect) { + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + return -EINVAL; + } + if (tilesplit > 6) { + return -EINVAL; + } + if (stilesplit > 6) { + return -EINVAL; + } + } + r = radeon_bo_reserve(bo, false); + if (unlikely(r != 0)) + return r; + bo->tiling_flags = tiling_flags; + bo->pitch = pitch; + radeon_bo_unreserve(bo); + return 0; +} + +void radeon_bo_get_tiling_flags(struct radeon_bo *bo, + uint32_t *tiling_flags, + uint32_t *pitch) +{ + KASSERT(radeon_bo_is_reserved(bo), + ("radeon_bo_get_tiling_flags: radeon_bo is not reserved")); + if (tiling_flags) + *tiling_flags = bo->tiling_flags; + if (pitch) + *pitch = bo->pitch; +} + +int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, + bool force_drop) +{ + KASSERT((radeon_bo_is_reserved(bo) || force_drop), + ("radeon_bo_check_tiling: radeon_bo is not reserved && !force_drop")); + + if (!(bo->tiling_flags & RADEON_TILING_SURFACE)) + return 0; + + if (force_drop) { + radeon_bo_clear_surface_reg(bo); + return 0; + } + + if (bo->tbo.mem.mem_type != TTM_PL_VRAM) { + if (!has_moved) + return 0; + + if (bo->surface_reg >= 0) + radeon_bo_clear_surface_reg(bo); + return 0; + } + + if ((bo->surface_reg >= 0) && !has_moved) + return 0; + + return radeon_bo_get_surface_reg(bo); +} + +void radeon_bo_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem) +{ + struct radeon_bo *rbo; + if (!radeon_ttm_bo_is_radeon_bo(bo)) + return; + rbo = container_of(bo, struct radeon_bo, tbo); + radeon_bo_check_tiling(rbo, 0, 1); + radeon_vm_bo_invalidate(rbo->rdev, rbo); +} + +int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) +{ + struct radeon_device *rdev; + struct radeon_bo *rbo; + unsigned long offset, size; + int r; + + if (!radeon_ttm_bo_is_radeon_bo(bo)) + return 0; + rbo = container_of(bo, struct radeon_bo, tbo); + radeon_bo_check_tiling(rbo, 0, 0); + rdev = rbo->rdev; + if (bo->mem.mem_type == TTM_PL_VRAM) { + size = bo->mem.num_pages << PAGE_SHIFT; + offset = bo->mem.start << PAGE_SHIFT; + if ((offset + size) > rdev->mc.visible_vram_size) { + /* hurrah the memory is not visible ! */ + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); + rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; + r = ttm_bo_validate(bo, &rbo->placement, false, false); + if (unlikely(r != 0)) + return r; + offset = bo->mem.start << PAGE_SHIFT; + /* this should not happen */ + if ((offset + size) > rdev->mc.visible_vram_size) + return -EINVAL; + } + } + return 0; +} + +int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait) +{ + int r; + + r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); + if (unlikely(r != 0)) + return r; + mtx_lock(&bo->tbo.bdev->fence_lock); + if (mem_type) + *mem_type = bo->tbo.mem.mem_type; + if (bo->tbo.sync_obj) + r = ttm_bo_wait(&bo->tbo, true, true, no_wait); + mtx_unlock(&bo->tbo.bdev->fence_lock); + ttm_bo_unreserve(&bo->tbo); + return r; +} + + +/** + * radeon_bo_reserve - reserve bo + * @bo: bo structure + * @no_intr: don't return -ERESTARTSYS on pending signal + * + * Returns: + * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by + * a signal. Release all buffer reservations and return to user-space. + */ +int radeon_bo_reserve(struct radeon_bo *bo, bool no_intr) +{ + int r; + + r = ttm_bo_reserve(&bo->tbo, !no_intr, false, false, 0); + if (unlikely(r != 0)) { + if (r != -ERESTARTSYS) + dev_err(bo->rdev->dev, "%p reserve failed\n", bo); + return r; + } + return 0; +} diff --git a/sys/dev/drm2/radeon/radeon_object.h b/sys/dev/drm2/radeon/radeon_object.h new file mode 100644 index 00000000000..efb7149b867 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_object.h @@ -0,0 +1,193 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef __RADEON_OBJECT_H__ +#define __RADEON_OBJECT_H__ + +#include +#include "radeon.h" + +/* + * Undefine max_offset (defined in vm/vm_map.h), because it conflicts + * with an argument of the function radeon_bo_pin_restricted(). + */ +#undef max_offset + +/** + * radeon_mem_type_to_domain - return domain corresponding to mem_type + * @mem_type: ttm memory type + * + * Returns corresponding domain of the ttm mem_type + */ +static inline unsigned radeon_mem_type_to_domain(u32 mem_type) +{ + switch (mem_type) { + case TTM_PL_VRAM: + return RADEON_GEM_DOMAIN_VRAM; + case TTM_PL_TT: + return RADEON_GEM_DOMAIN_GTT; + case TTM_PL_SYSTEM: + return RADEON_GEM_DOMAIN_CPU; + default: + break; + } + return 0; +} + +int radeon_bo_reserve(struct radeon_bo *bo, bool no_intr); + +static inline void radeon_bo_unreserve(struct radeon_bo *bo) +{ + ttm_bo_unreserve(&bo->tbo); +} + +/** + * radeon_bo_gpu_offset - return GPU offset of bo + * @bo: radeon object for which we query the offset + * + * Returns current GPU offset of the object. + * + * Note: object should either be pinned or reserved when calling this + * function, it might be useful to add check for this for debugging. + */ +static inline u64 radeon_bo_gpu_offset(struct radeon_bo *bo) +{ + return bo->tbo.offset; +} + +static inline unsigned long radeon_bo_size(struct radeon_bo *bo) +{ + return bo->tbo.num_pages << PAGE_SHIFT; +} + +static inline bool radeon_bo_is_reserved(struct radeon_bo *bo) +{ + return ttm_bo_is_reserved(&bo->tbo); +} + +static inline unsigned radeon_bo_ngpu_pages(struct radeon_bo *bo) +{ + return (bo->tbo.num_pages << PAGE_SHIFT) / RADEON_GPU_PAGE_SIZE; +} + +static inline unsigned radeon_bo_gpu_page_alignment(struct radeon_bo *bo) +{ + return (bo->tbo.mem.page_alignment << PAGE_SHIFT) / RADEON_GPU_PAGE_SIZE; +} + +/** + * radeon_bo_mmap_offset - return mmap offset of bo + * @bo: radeon object for which we query the offset + * + * Returns mmap offset of the object. + * + * Note: addr_space_offset is constant after ttm bo init thus isn't protected + * by any lock. + */ +static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo) +{ + return bo->tbo.addr_space_offset; +} + +extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, + bool no_wait); + +extern int radeon_bo_create(struct radeon_device *rdev, + unsigned long size, int byte_align, + bool kernel, u32 domain, + struct sg_table *sg, + struct radeon_bo **bo_ptr); +extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); +extern void radeon_bo_kunmap(struct radeon_bo *bo); +extern void radeon_bo_unref(struct radeon_bo **bo); +extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr); +extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, + u64 max_offset, u64 *gpu_addr); +extern int radeon_bo_unpin(struct radeon_bo *bo); +extern int radeon_bo_evict_vram(struct radeon_device *rdev); +extern void radeon_bo_force_delete(struct radeon_device *rdev); +extern int radeon_bo_init(struct radeon_device *rdev); +extern void radeon_bo_fini(struct radeon_device *rdev); +extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj, + struct list_head *head); +extern int radeon_bo_list_validate(struct list_head *head); +#ifdef DUMBBELL_WIP +extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, + struct vm_area_struct *vma); +#endif /* DUMBBELL_WIP */ +extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, + u32 tiling_flags, u32 pitch); +extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, + u32 *tiling_flags, u32 *pitch); +extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, + bool force_drop); +extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem); +extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); +extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); + +/* + * sub allocation + */ + +static inline uint64_t radeon_sa_bo_gpu_addr(struct radeon_sa_bo *sa_bo) +{ + return sa_bo->manager->gpu_addr + sa_bo->soffset; +} + +static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo) +{ + return (char *)sa_bo->manager->cpu_ptr + sa_bo->soffset; +} + +extern int radeon_sa_bo_manager_init(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager, + unsigned size, u32 domain); +extern void radeon_sa_bo_manager_fini(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager); +extern int radeon_sa_bo_manager_start(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager); +extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager); +extern int radeon_sa_bo_new(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager, + struct radeon_sa_bo **sa_bo, + unsigned size, unsigned align, bool block); +extern void radeon_sa_bo_free(struct radeon_device *rdev, + struct radeon_sa_bo **sa_bo, + struct radeon_fence *fence); +#if defined(CONFIG_DEBUG_FS) +extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, + struct seq_file *m); +#endif + + +#endif diff --git a/sys/dev/drm2/radeon/radeon_pm.c b/sys/dev/drm2/radeon/radeon_pm.c new file mode 100644 index 00000000000..47042dbd8e2 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_pm.c @@ -0,0 +1,918 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Rafał Miłecki + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "avivod.h" +#include "atom.h" + +#define RADEON_IDLE_LOOP_MS 100 +#define RADEON_RECLOCK_DELAY_MS 200 +#define RADEON_WAIT_VBLANK_TIMEOUT 200 + +static const char *radeon_pm_state_type_name[5] = { + "", + "Powersave", + "Battery", + "Balanced", + "Performance", +}; + +#ifdef DUMBBELL_WIP +static void radeon_dynpm_idle_work_handler(struct work_struct *work); +#endif /* DUMBBELL_WIP */ +static int radeon_debugfs_pm_init(struct radeon_device *rdev); +static bool radeon_pm_in_vbl(struct radeon_device *rdev); +static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); +static void radeon_pm_update_profile(struct radeon_device *rdev); +static void radeon_pm_set_clocks(struct radeon_device *rdev); + +int radeon_pm_get_type_index(struct radeon_device *rdev, + enum radeon_pm_state_type ps_type, + int instance) +{ + int i; + int found_instance = -1; + + for (i = 0; i < rdev->pm.num_power_states; i++) { + if (rdev->pm.power_state[i].type == ps_type) { + found_instance++; + if (found_instance == instance) + return i; + } + } + /* return default if no match */ + return rdev->pm.default_power_state_index; +} + +void radeon_pm_acpi_event_handler(struct radeon_device *rdev) +{ + if (rdev->pm.pm_method == PM_METHOD_PROFILE) { + if (rdev->pm.profile == PM_PROFILE_AUTO) { + sx_xlock(&rdev->pm.mutex); + radeon_pm_update_profile(rdev); + radeon_pm_set_clocks(rdev); + sx_xunlock(&rdev->pm.mutex); + } + } +} + +static void radeon_pm_update_profile(struct radeon_device *rdev) +{ + switch (rdev->pm.profile) { + case PM_PROFILE_DEFAULT: + rdev->pm.profile_index = PM_PROFILE_DEFAULT_IDX; + break; + case PM_PROFILE_AUTO: +#ifdef DUMBBELL_WIP + if (power_supply_is_system_supplied() > 0) { + if (rdev->pm.active_crtc_count > 1) + rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX; + else + rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX; + } else { + if (rdev->pm.active_crtc_count > 1) + rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX; + else + rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX; + } +#endif /* DUMBBELL_WIP */ + break; + case PM_PROFILE_LOW: + if (rdev->pm.active_crtc_count > 1) + rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX; + else + rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; + break; + case PM_PROFILE_MID: + if (rdev->pm.active_crtc_count > 1) + rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX; + else + rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX; + break; + case PM_PROFILE_HIGH: + if (rdev->pm.active_crtc_count > 1) + rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX; + else + rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX; + break; + } + + if (rdev->pm.active_crtc_count == 0) { + rdev->pm.requested_power_state_index = + rdev->pm.profiles[rdev->pm.profile_index].dpms_off_ps_idx; + rdev->pm.requested_clock_mode_index = + rdev->pm.profiles[rdev->pm.profile_index].dpms_off_cm_idx; + } else { + rdev->pm.requested_power_state_index = + rdev->pm.profiles[rdev->pm.profile_index].dpms_on_ps_idx; + rdev->pm.requested_clock_mode_index = + rdev->pm.profiles[rdev->pm.profile_index].dpms_on_cm_idx; + } +} + +static void radeon_unmap_vram_bos(struct radeon_device *rdev) +{ + struct radeon_bo *bo, *n; + + if (list_empty(&rdev->gem.objects)) + return; + + list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { + if (bo->tbo.mem.mem_type == TTM_PL_VRAM) + ttm_bo_unmap_virtual(&bo->tbo); + } +} + +static void radeon_sync_with_vblank(struct radeon_device *rdev) +{ + if (rdev->pm.active_crtcs) { + rdev->pm.vblank_sync = false; +#ifdef DUMBBELL_WIP + wait_event_timeout( + rdev->irq.vblank_queue, rdev->pm.vblank_sync, + msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); +#endif /* DUMBBELL_WIP */ + } +} + +static void radeon_set_power_state(struct radeon_device *rdev) +{ + u32 sclk, mclk; + bool misc_after = false; + + if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && + (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) + return; + + if (radeon_gui_idle(rdev)) { + sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].sclk; + if (sclk > rdev->pm.default_sclk) + sclk = rdev->pm.default_sclk; + + /* starting with BTC, there is one state that is used for both + * MH and SH. Difference is that we always use the high clock index for + * mclk. + */ + if ((rdev->pm.pm_method == PM_METHOD_PROFILE) && + (rdev->family >= CHIP_BARTS) && + rdev->pm.active_crtc_count && + ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) || + (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX))) + mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].mclk; + else + mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. + clock_info[rdev->pm.requested_clock_mode_index].mclk; + + if (mclk > rdev->pm.default_mclk) + mclk = rdev->pm.default_mclk; + + /* upvolt before raising clocks, downvolt after lowering clocks */ + if (sclk < rdev->pm.current_sclk) + misc_after = true; + + radeon_sync_with_vblank(rdev); + + if (rdev->pm.pm_method == PM_METHOD_DYNPM) { + if (!radeon_pm_in_vbl(rdev)) + return; + } + + radeon_pm_prepare(rdev); + + if (!misc_after) + /* voltage, pcie lanes, etc.*/ + radeon_pm_misc(rdev); + + /* set engine clock */ + if (sclk != rdev->pm.current_sclk) { + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_engine_clock(rdev, sclk); + radeon_pm_debug_check_in_vbl(rdev, true); + rdev->pm.current_sclk = sclk; + DRM_DEBUG_DRIVER("Setting: e: %d\n", sclk); + } + + /* set memory clock */ + if (rdev->asic->pm.set_memory_clock && (mclk != rdev->pm.current_mclk)) { + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_memory_clock(rdev, mclk); + radeon_pm_debug_check_in_vbl(rdev, true); + rdev->pm.current_mclk = mclk; + DRM_DEBUG_DRIVER("Setting: m: %d\n", mclk); + } + + if (misc_after) + /* voltage, pcie lanes, etc.*/ + radeon_pm_misc(rdev); + + radeon_pm_finish(rdev); + + rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; + rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; + } else + DRM_DEBUG_DRIVER("pm: GUI not idle!!!\n"); +} + +static void radeon_pm_set_clocks(struct radeon_device *rdev) +{ + int i, r; + + /* no need to take locks, etc. if nothing's going to change */ + if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && + (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) + return; + + DRM_LOCK(rdev->ddev); + sx_xlock(&rdev->pm.mclk_lock); + sx_xlock(&rdev->ring_lock); + + /* wait for the rings to drain */ + for (i = 0; i < RADEON_NUM_RINGS; i++) { + struct radeon_ring *ring = &rdev->ring[i]; + if (!ring->ready) { + continue; + } + r = radeon_fence_wait_empty_locked(rdev, i); + if (r) { + /* needs a GPU reset dont reset here */ + sx_xunlock(&rdev->ring_lock); + sx_xunlock(&rdev->pm.mclk_lock); + DRM_UNLOCK(rdev->ddev); + return; + } + } + + radeon_unmap_vram_bos(rdev); + + if (rdev->irq.installed) { + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->pm.active_crtcs & (1 << i)) { + rdev->pm.req_vblank |= (1 << i); + drm_vblank_get(rdev->ddev, i); + } + } + } + + radeon_set_power_state(rdev); + + if (rdev->irq.installed) { + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->pm.req_vblank & (1 << i)) { + rdev->pm.req_vblank &= ~(1 << i); + drm_vblank_put(rdev->ddev, i); + } + } + } + + /* update display watermarks based on new power state */ + radeon_update_bandwidth_info(rdev); + if (rdev->pm.active_crtc_count) + radeon_bandwidth_update(rdev); + + rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; + + sx_xunlock(&rdev->ring_lock); + sx_xunlock(&rdev->pm.mclk_lock); + DRM_UNLOCK(rdev->ddev); +} + +static void radeon_pm_print_states(struct radeon_device *rdev) +{ + int i, j; + struct radeon_power_state *power_state; + struct radeon_pm_clock_info *clock_info; + + DRM_DEBUG_DRIVER("%d Power State(s)\n", rdev->pm.num_power_states); + for (i = 0; i < rdev->pm.num_power_states; i++) { + power_state = &rdev->pm.power_state[i]; + DRM_DEBUG_DRIVER("State %d: %s\n", i, + radeon_pm_state_type_name[power_state->type]); + if (i == rdev->pm.default_power_state_index) + DRM_DEBUG_DRIVER("\tDefault"); + if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP)) + DRM_DEBUG_DRIVER("\t%d PCIE Lanes\n", power_state->pcie_lanes); + if (power_state->flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + DRM_DEBUG_DRIVER("\tSingle display only\n"); + DRM_DEBUG_DRIVER("\t%d Clock Mode(s)\n", power_state->num_clock_modes); + for (j = 0; j < power_state->num_clock_modes; j++) { + clock_info = &(power_state->clock_info[j]); + if (rdev->flags & RADEON_IS_IGP) + DRM_DEBUG_DRIVER("\t\t%d e: %d\n", + j, + clock_info->sclk * 10); + else + DRM_DEBUG_DRIVER("\t\t%d e: %d\tm: %d\tv: %d\n", + j, + clock_info->sclk * 10, + clock_info->mclk * 10, + clock_info->voltage.voltage); + } + } +} + +#ifdef DUMBBELL_WIP +static ssize_t radeon_get_pm_profile(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct radeon_device *rdev = ddev->dev_private; + int cp = rdev->pm.profile; + + return snprintf(buf, PAGE_SIZE, "%s\n", + (cp == PM_PROFILE_AUTO) ? "auto" : + (cp == PM_PROFILE_LOW) ? "low" : + (cp == PM_PROFILE_MID) ? "mid" : + (cp == PM_PROFILE_HIGH) ? "high" : "default"); +} + +static ssize_t radeon_set_pm_profile(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct radeon_device *rdev = ddev->dev_private; + + sx_xlock(&rdev->pm.mutex); + if (rdev->pm.pm_method == PM_METHOD_PROFILE) { + if (strncmp("default", buf, strlen("default")) == 0) + rdev->pm.profile = PM_PROFILE_DEFAULT; + else if (strncmp("auto", buf, strlen("auto")) == 0) + rdev->pm.profile = PM_PROFILE_AUTO; + else if (strncmp("low", buf, strlen("low")) == 0) + rdev->pm.profile = PM_PROFILE_LOW; + else if (strncmp("mid", buf, strlen("mid")) == 0) + rdev->pm.profile = PM_PROFILE_MID; + else if (strncmp("high", buf, strlen("high")) == 0) + rdev->pm.profile = PM_PROFILE_HIGH; + else { + count = -EINVAL; + goto fail; + } + radeon_pm_update_profile(rdev); + radeon_pm_set_clocks(rdev); + } else + count = -EINVAL; + +fail: + sx_xunlock(&rdev->pm.mutex); + + return count; +} + +static ssize_t radeon_get_pm_method(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct radeon_device *rdev = ddev->dev_private; + int pm = rdev->pm.pm_method; + + return snprintf(buf, PAGE_SIZE, "%s\n", + (pm == PM_METHOD_DYNPM) ? "dynpm" : "profile"); +} + +static ssize_t radeon_set_pm_method(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct radeon_device *rdev = ddev->dev_private; + + + if (strncmp("dynpm", buf, strlen("dynpm")) == 0) { + sx_xlock(&rdev->pm.mutex); + rdev->pm.pm_method = PM_METHOD_DYNPM; + rdev->pm.dynpm_state = DYNPM_STATE_PAUSED; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; + sx_xunlock(&rdev->pm.mutex); + } else if (strncmp("profile", buf, strlen("profile")) == 0) { + sx_xlock(&rdev->pm.mutex); + /* disable dynpm */ + rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; + rdev->pm.pm_method = PM_METHOD_PROFILE; + sx_xunlock(&rdev->pm.mutex); +#ifdef DUMBBELL_WIP + cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); +#endif /* DUMBBELL_WIP */ + } else { + count = -EINVAL; + goto fail; + } + radeon_pm_compute_clocks(rdev); +fail: + return count; +} + +static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); +static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); + +static ssize_t radeon_hwmon_show_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct radeon_device *rdev = ddev->dev_private; + int temp; + + switch (rdev->pm.int_thermal_type) { + case THERMAL_TYPE_RV6XX: + temp = rv6xx_get_temp(rdev); + break; + case THERMAL_TYPE_RV770: + temp = rv770_get_temp(rdev); + break; + case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_NI: + temp = evergreen_get_temp(rdev); + break; + case THERMAL_TYPE_SUMO: + temp = sumo_get_temp(rdev); + break; + case THERMAL_TYPE_SI: + temp = si_get_temp(rdev); + break; + default: + temp = 0; + break; + } + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + +static ssize_t radeon_hwmon_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "radeon\n"); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0); + +static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; + +static const struct attribute_group hwmon_attrgroup = { + .attrs = hwmon_attributes, +}; +#endif /* DUMBBELL_WIP */ + +static int radeon_hwmon_init(struct radeon_device *rdev) +{ + int err = 0; + +#ifdef DUMBBELL_WIP + rdev->pm.int_hwmon_dev = NULL; +#endif /* DUMBBELL_WIP */ + + switch (rdev->pm.int_thermal_type) { + case THERMAL_TYPE_RV6XX: + case THERMAL_TYPE_RV770: + case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_NI: + case THERMAL_TYPE_SUMO: + case THERMAL_TYPE_SI: + /* No support for TN yet */ + if (rdev->family == CHIP_ARUBA) + return err; +#ifdef DUMBBELL_WIP + rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); + if (IS_ERR(rdev->pm.int_hwmon_dev)) { + err = PTR_ERR(rdev->pm.int_hwmon_dev); + dev_err(rdev->dev, + "Unable to register hwmon device: %d\n", err); + break; + } + dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); + err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, + &hwmon_attrgroup); + if (err) { + dev_err(rdev->dev, + "Unable to create hwmon sysfs file: %d\n", err); + hwmon_device_unregister(rdev->dev); + } +#endif /* DUMBBELL_WIP */ + break; + default: + break; + } + + return err; +} + +static void radeon_hwmon_fini(struct radeon_device *rdev) +{ +#ifdef DUMBBELL_WIP + if (rdev->pm.int_hwmon_dev) { + sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup); + hwmon_device_unregister(rdev->pm.int_hwmon_dev); + } +#endif /* DUMBBELL_WIP */ +} + +void radeon_pm_suspend(struct radeon_device *rdev) +{ + sx_xlock(&rdev->pm.mutex); + if (rdev->pm.pm_method == PM_METHOD_DYNPM) { + if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) + rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED; + } + sx_xunlock(&rdev->pm.mutex); + +#ifdef DUMBBELL_WIP + cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); +#endif /* DUMBBELL_WIP */ +} + +void radeon_pm_resume(struct radeon_device *rdev) +{ + /* set up the default clocks if the MC ucode is loaded */ + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { + if (rdev->pm.default_vddc) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, + SET_VOLTAGE_TYPE_ASIC_VDDC); + if (rdev->pm.default_vddci) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, + SET_VOLTAGE_TYPE_ASIC_VDDCI); + if (rdev->pm.default_sclk) + radeon_set_engine_clock(rdev, rdev->pm.default_sclk); + if (rdev->pm.default_mclk) + radeon_set_memory_clock(rdev, rdev->pm.default_mclk); + } + /* asic init will reset the default power state */ + sx_xlock(&rdev->pm.mutex); + rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.current_clock_mode_index = 0; + rdev->pm.current_sclk = rdev->pm.default_sclk; + rdev->pm.current_mclk = rdev->pm.default_mclk; + rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; + rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; + if (rdev->pm.pm_method == PM_METHOD_DYNPM + && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { + rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; +#ifdef DUMBBELL_WIP + schedule_delayed_work(&rdev->pm.dynpm_idle_work, + msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); +#endif /* DUMBBELL_WIP */ + } + sx_xunlock(&rdev->pm.mutex); + radeon_pm_compute_clocks(rdev); +} + +int radeon_pm_init(struct radeon_device *rdev) +{ + int ret; + + /* default to profile method */ + rdev->pm.pm_method = PM_METHOD_PROFILE; + rdev->pm.profile = PM_PROFILE_DEFAULT; + rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; + rdev->pm.dynpm_can_upclock = true; + rdev->pm.dynpm_can_downclock = true; + rdev->pm.default_sclk = rdev->clock.default_sclk; + rdev->pm.default_mclk = rdev->clock.default_mclk; + rdev->pm.current_sclk = rdev->clock.default_sclk; + rdev->pm.current_mclk = rdev->clock.default_mclk; + rdev->pm.int_thermal_type = THERMAL_TYPE_NONE; + + if (rdev->bios) { + if (rdev->is_atom_bios) + radeon_atombios_get_power_modes(rdev); + else + radeon_combios_get_power_modes(rdev); + radeon_pm_print_states(rdev); + radeon_pm_init_profile(rdev); + /* set up the default clocks if the MC ucode is loaded */ + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { + if (rdev->pm.default_vddc) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, + SET_VOLTAGE_TYPE_ASIC_VDDC); + if (rdev->pm.default_vddci) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, + SET_VOLTAGE_TYPE_ASIC_VDDCI); + if (rdev->pm.default_sclk) + radeon_set_engine_clock(rdev, rdev->pm.default_sclk); + if (rdev->pm.default_mclk) + radeon_set_memory_clock(rdev, rdev->pm.default_mclk); + } + } + + /* set up the internal thermal sensor if applicable */ + ret = radeon_hwmon_init(rdev); + if (ret) + return ret; + +#ifdef DUMBBELL_WIP + INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler); +#endif /* DUMBBELL_WIP */ + + if (rdev->pm.num_power_states > 1) { + /* where's the best place to put these? */ +#ifdef DUMBBELL_WIP + ret = device_create_file(rdev->dev, &dev_attr_power_profile); +#endif /* DUMBBELL_WIP */ + if (ret) + DRM_ERROR("failed to create device file for power profile\n"); +#ifdef DUMBBELL_WIP + ret = device_create_file(rdev->dev, &dev_attr_power_method); +#endif /* DUMBBELL_WIP */ + if (ret) + DRM_ERROR("failed to create device file for power method\n"); + + if (radeon_debugfs_pm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for PM!\n"); + } + + DRM_INFO("radeon: power management initialized\n"); + } + + return 0; +} + +void radeon_pm_fini(struct radeon_device *rdev) +{ + if (rdev->pm.num_power_states > 1) { + DRM_UNLOCK(rdev->ddev); /* Work around LOR. */ + sx_xlock(&rdev->pm.mutex); + if (rdev->pm.pm_method == PM_METHOD_PROFILE) { + rdev->pm.profile = PM_PROFILE_DEFAULT; + radeon_pm_update_profile(rdev); + radeon_pm_set_clocks(rdev); + } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { + /* reset default clocks */ + rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; + radeon_pm_set_clocks(rdev); + } + sx_xunlock(&rdev->pm.mutex); + DRM_LOCK(rdev->ddev); + +#ifdef DUMBBELL_WIP + cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); + + device_remove_file(rdev->dev, &dev_attr_power_profile); + device_remove_file(rdev->dev, &dev_attr_power_method); +#endif /* DUMBBELL_WIP */ + } + + if (rdev->pm.power_state) { + int i; + for (i = 0; i < rdev->pm.num_power_states; ++i) { + free(rdev->pm.power_state[i].clock_info, DRM_MEM_DRIVER); + } + free(rdev->pm.power_state, DRM_MEM_DRIVER); + rdev->pm.power_state = NULL; + rdev->pm.num_power_states = 0; + } + + radeon_hwmon_fini(rdev); +} + +void radeon_pm_compute_clocks(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + + if (rdev->pm.num_power_states < 2) + return; + + sx_xlock(&rdev->pm.mutex); + + rdev->pm.active_crtcs = 0; + rdev->pm.active_crtc_count = 0; + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id); + rdev->pm.active_crtc_count++; + } + } + + if (rdev->pm.pm_method == PM_METHOD_PROFILE) { + radeon_pm_update_profile(rdev); + radeon_pm_set_clocks(rdev); + } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { + if (rdev->pm.dynpm_state != DYNPM_STATE_DISABLED) { + if (rdev->pm.active_crtc_count > 1) { + if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) { +#ifdef DUMBBELL_WIP + cancel_delayed_work(&rdev->pm.dynpm_idle_work); +#endif /* DUMBBELL_WIP */ + + rdev->pm.dynpm_state = DYNPM_STATE_PAUSED; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; + radeon_pm_get_dynpm_state(rdev); + radeon_pm_set_clocks(rdev); + + DRM_DEBUG_DRIVER("radeon: dynamic power management deactivated\n"); + } + } else if (rdev->pm.active_crtc_count == 1) { + /* TODO: Increase clocks if needed for current mode */ + + if (rdev->pm.dynpm_state == DYNPM_STATE_MINIMUM) { + rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_UPCLOCK; + radeon_pm_get_dynpm_state(rdev); + radeon_pm_set_clocks(rdev); + +#ifdef DUMBBELL_WIP + schedule_delayed_work(&rdev->pm.dynpm_idle_work, + msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); +#endif /* DUMBBELL_WIP */ + } else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) { + rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; +#ifdef DUMBBELL_WIP + schedule_delayed_work(&rdev->pm.dynpm_idle_work, + msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); +#endif /* DUMBBELL_WIP */ + DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n"); + } + } else { /* count == 0 */ + if (rdev->pm.dynpm_state != DYNPM_STATE_MINIMUM) { +#ifdef DUMBBELL_WIP + cancel_delayed_work(&rdev->pm.dynpm_idle_work); +#endif /* DUMBBELL_WIP */ + + rdev->pm.dynpm_state = DYNPM_STATE_MINIMUM; + rdev->pm.dynpm_planned_action = DYNPM_ACTION_MINIMUM; + radeon_pm_get_dynpm_state(rdev); + radeon_pm_set_clocks(rdev); + } + } + } + } + + sx_xunlock(&rdev->pm.mutex); +} + +static bool radeon_pm_in_vbl(struct radeon_device *rdev) +{ + int crtc, vpos, hpos, vbl_status; + bool in_vbl = true; + + /* Iterate over all active crtc's. All crtc's must be in vblank, + * otherwise return in_vbl == false. + */ + for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { + if (rdev->pm.active_crtcs & (1 << crtc)) { + vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos); + if ((vbl_status & DRM_SCANOUTPOS_VALID) && + !(vbl_status & DRM_SCANOUTPOS_INVBL)) + in_vbl = false; + } + } + + return in_vbl; +} + +static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) +{ + u32 stat_crtc = 0; + bool in_vbl = radeon_pm_in_vbl(rdev); + + if (in_vbl == false) + DRM_DEBUG_DRIVER("not in vbl for pm change %08x at %s\n", stat_crtc, + finish ? "exit" : "entry"); + return in_vbl; +} + +#ifdef DUMBBELL_WIP +static void radeon_dynpm_idle_work_handler(struct work_struct *work) +{ + struct radeon_device *rdev; + int resched; + rdev = container_of(work, struct radeon_device, + pm.dynpm_idle_work.work); + + resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); + sx_xlock(&rdev->pm.mutex); + if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) { + int not_processed = 0; + int i; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + struct radeon_ring *ring = &rdev->ring[i]; + + if (ring->ready) { + not_processed += radeon_fence_count_emitted(rdev, i); + if (not_processed >= 3) + break; + } + } + + if (not_processed >= 3) { /* should upclock */ + if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_DOWNCLOCK) { + rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; + } else if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_NONE && + rdev->pm.dynpm_can_upclock) { + rdev->pm.dynpm_planned_action = + DYNPM_ACTION_UPCLOCK; + rdev->pm.dynpm_action_timeout = jiffies + + msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS); + } + } else if (not_processed == 0) { /* should downclock */ + if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_UPCLOCK) { + rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; + } else if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_NONE && + rdev->pm.dynpm_can_downclock) { + rdev->pm.dynpm_planned_action = + DYNPM_ACTION_DOWNCLOCK; + rdev->pm.dynpm_action_timeout = jiffies + + msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS); + } + } + + /* Note, radeon_pm_set_clocks is called with static_switch set + * to false since we want to wait for vbl to avoid flicker. + */ + if (rdev->pm.dynpm_planned_action != DYNPM_ACTION_NONE && + jiffies > rdev->pm.dynpm_action_timeout) { + radeon_pm_get_dynpm_state(rdev); + radeon_pm_set_clocks(rdev); + } + + schedule_delayed_work(&rdev->pm.dynpm_idle_work, + msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); + } + sx_xunlock(&rdev->pm.mutex); + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); +} +#endif /* DUMBBELL_WIP */ + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) + +static int radeon_debugfs_pm_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + + seq_printf(m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk); + seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); + seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk); + if (rdev->asic->pm.get_memory_clock) + seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); + if (rdev->pm.current_vddc) + seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc); + if (rdev->asic->pm.get_pcie_lanes) + seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); + + return 0; +} + +static struct drm_info_list radeon_pm_info_list[] = { + {"radeon_pm_info", radeon_debugfs_pm_info, 0, NULL}, +}; +#endif + +static int radeon_debugfs_pm_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, radeon_pm_info_list, ARRAY_SIZE(radeon_pm_info_list)); +#else + return 0; +#endif +} diff --git a/sys/dev/drm2/radeon/radeon_prime.c b/sys/dev/drm2/radeon/radeon_prime.c new file mode 100644 index 00000000000..c0c7a548b0e --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_prime.c @@ -0,0 +1,230 @@ +/* + * Copyright 2012 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * based on nouveau_prime.c + * + * Authors: Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include "radeon.h" +#include + +#include + +static struct sg_table *radeon_gem_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction dir) +{ + struct radeon_bo *bo = attachment->dmabuf->priv; + struct drm_device *dev = bo->rdev->ddev; + int npages = bo->tbo.num_pages; + struct sg_table *sg; + int nents; + + mutex_lock(&dev->struct_mutex); + sg = drm_prime_pages_to_sg(bo->tbo.ttm->pages, npages); + nents = dma_map_sg(attachment->dev, sg->sgl, sg->nents, dir); + mutex_unlock(&dev->struct_mutex); + return sg; +} + +static void radeon_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *sg, enum dma_data_direction dir) +{ + dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir); + sg_free_table(sg); + kfree(sg); +} + +static void radeon_gem_dmabuf_release(struct dma_buf *dma_buf) +{ + struct radeon_bo *bo = dma_buf->priv; + + if (bo->gem_base.export_dma_buf == dma_buf) { + DRM_ERROR("unreference dmabuf %p\n", &bo->gem_base); + bo->gem_base.export_dma_buf = NULL; + drm_gem_object_unreference_unlocked(&bo->gem_base); + } +} + +static void *radeon_gem_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) +{ + return NULL; +} + +static void radeon_gem_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr) +{ + +} +static void *radeon_gem_kmap(struct dma_buf *dma_buf, unsigned long page_num) +{ + return NULL; +} + +static void radeon_gem_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr) +{ + +} + +static int radeon_gem_prime_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) +{ + return -EINVAL; +} + +static void *radeon_gem_prime_vmap(struct dma_buf *dma_buf) +{ + struct radeon_bo *bo = dma_buf->priv; + struct drm_device *dev = bo->rdev->ddev; + int ret; + + mutex_lock(&dev->struct_mutex); + if (bo->vmapping_count) { + bo->vmapping_count++; + goto out_unlock; + } + + ret = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, + &bo->dma_buf_vmap); + if (ret) { + mutex_unlock(&dev->struct_mutex); + return ERR_PTR(ret); + } + bo->vmapping_count = 1; +out_unlock: + mutex_unlock(&dev->struct_mutex); + return bo->dma_buf_vmap.virtual; +} + +static void radeon_gem_prime_vunmap(struct dma_buf *dma_buf, void *vaddr) +{ + struct radeon_bo *bo = dma_buf->priv; + struct drm_device *dev = bo->rdev->ddev; + + mutex_lock(&dev->struct_mutex); + bo->vmapping_count--; + if (bo->vmapping_count == 0) { + ttm_bo_kunmap(&bo->dma_buf_vmap); + } + mutex_unlock(&dev->struct_mutex); +} +const static struct dma_buf_ops radeon_dmabuf_ops = { + .map_dma_buf = radeon_gem_map_dma_buf, + .unmap_dma_buf = radeon_gem_unmap_dma_buf, + .release = radeon_gem_dmabuf_release, + .kmap = radeon_gem_kmap, + .kmap_atomic = radeon_gem_kmap_atomic, + .kunmap = radeon_gem_kunmap, + .kunmap_atomic = radeon_gem_kunmap_atomic, + .mmap = radeon_gem_prime_mmap, + .vmap = radeon_gem_prime_vmap, + .vunmap = radeon_gem_prime_vunmap, +}; + +static int radeon_prime_create(struct drm_device *dev, + size_t size, + struct sg_table *sg, + struct radeon_bo **pbo) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_bo *bo; + int ret; + + ret = radeon_bo_create(rdev, size, PAGE_SIZE, false, + RADEON_GEM_DOMAIN_GTT, sg, pbo); + if (ret) + return ret; + bo = *pbo; + bo->gem_base.driver_private = bo; + + mutex_lock(&rdev->gem.mutex); + list_add_tail(&bo->list, &rdev->gem.objects); + mutex_unlock(&rdev->gem.mutex); + + return 0; +} + +struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, + int flags) +{ + struct radeon_bo *bo = gem_to_radeon_bo(obj); + int ret = 0; + + ret = radeon_bo_reserve(bo, false); + if (unlikely(ret != 0)) + return ERR_PTR(ret); + + /* pin buffer into GTT */ + ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL); + if (ret) { + radeon_bo_unreserve(bo); + return ERR_PTR(ret); + } + radeon_bo_unreserve(bo); + return dma_buf_export(bo, &radeon_dmabuf_ops, obj->size, flags); +} + +struct drm_gem_object *radeon_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) +{ + struct dma_buf_attachment *attach; + struct sg_table *sg; + struct radeon_bo *bo; + int ret; + + if (dma_buf->ops == &radeon_dmabuf_ops) { + bo = dma_buf->priv; + if (bo->gem_base.dev == dev) { + drm_gem_object_reference(&bo->gem_base); + dma_buf_put(dma_buf); + return &bo->gem_base; + } + } + + /* need to attach */ + attach = dma_buf_attach(dma_buf, dev->dev); + if (IS_ERR(attach)) + return ERR_CAST(attach); + + sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto fail_detach; + } + + ret = radeon_prime_create(dev, dma_buf->size, sg, &bo); + if (ret) + goto fail_unmap; + + bo->gem_base.import_attach = attach; + + return &bo->gem_base; + +fail_unmap: + dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); +fail_detach: + dma_buf_detach(dma_buf, attach); + return ERR_PTR(ret); +} diff --git a/sys/dev/drm2/radeon/radeon_reg.h b/sys/dev/drm2/radeon/radeon_reg.h new file mode 100644 index 00000000000..8697e0f27e7 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_reg.h @@ -0,0 +1,3713 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* + * Authors: + * Kevin E. Martin + * Rickard E. Faith + * Alan Hourihane + * + * References: + * + * !!!! FIXME !!!! + * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical + * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April + * 1999. + * + * !!!! FIXME !!!! + * RAGE 128 Software Development Manual (Technical Reference Manual P/N + * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. + * + */ + +/* !!!! FIXME !!!! NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h + * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT + * ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED! */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef _RADEON_REG_H_ +#define _RADEON_REG_H_ + +#include "r300_reg.h" +#include "r500_reg.h" +#include "r600_reg.h" +#include "evergreen_reg.h" +#include "ni_reg.h" +#include "si_reg.h" + +#define RADEON_MC_AGP_LOCATION 0x014c +#define RADEON_MC_AGP_START_MASK 0x0000FFFF +#define RADEON_MC_AGP_START_SHIFT 0 +#define RADEON_MC_AGP_TOP_MASK 0xFFFF0000 +#define RADEON_MC_AGP_TOP_SHIFT 16 +#define RADEON_MC_FB_LOCATION 0x0148 +#define RADEON_MC_FB_START_MASK 0x0000FFFF +#define RADEON_MC_FB_START_SHIFT 0 +#define RADEON_MC_FB_TOP_MASK 0xFFFF0000 +#define RADEON_MC_FB_TOP_SHIFT 16 +#define RADEON_AGP_BASE_2 0x015c /* r200+ only */ +#define RADEON_AGP_BASE 0x0170 + +#define ATI_DATATYPE_VQ 0 +#define ATI_DATATYPE_CI4 1 +#define ATI_DATATYPE_CI8 2 +#define ATI_DATATYPE_ARGB1555 3 +#define ATI_DATATYPE_RGB565 4 +#define ATI_DATATYPE_RGB888 5 +#define ATI_DATATYPE_ARGB8888 6 +#define ATI_DATATYPE_RGB332 7 +#define ATI_DATATYPE_Y8 8 +#define ATI_DATATYPE_RGB8 9 +#define ATI_DATATYPE_CI16 10 +#define ATI_DATATYPE_VYUY_422 11 +#define ATI_DATATYPE_YVYU_422 12 +#define ATI_DATATYPE_AYUV_444 14 +#define ATI_DATATYPE_ARGB4444 15 + + /* Registers for 2D/Video/Overlay */ +#define RADEON_ADAPTER_ID 0x0f2c /* PCI */ +#define RADEON_AGP_BASE 0x0170 +#define RADEON_AGP_CNTL 0x0174 +# define RADEON_AGP_APER_SIZE_256MB (0x00 << 0) +# define RADEON_AGP_APER_SIZE_128MB (0x20 << 0) +# define RADEON_AGP_APER_SIZE_64MB (0x30 << 0) +# define RADEON_AGP_APER_SIZE_32MB (0x38 << 0) +# define RADEON_AGP_APER_SIZE_16MB (0x3c << 0) +# define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) +# define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) +# define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) +#define RADEON_STATUS_PCI_CONFIG 0x06 +# define RADEON_CAP_LIST 0x100000 +#define RADEON_CAPABILITIES_PTR_PCI_CONFIG 0x34 /* offset in PCI config*/ +# define RADEON_CAP_PTR_MASK 0xfc /* mask off reserved bits of CAP_PTR */ +# define RADEON_CAP_ID_NULL 0x00 /* End of capability list */ +# define RADEON_CAP_ID_AGP 0x02 /* AGP capability ID */ +# define RADEON_CAP_ID_EXP 0x10 /* PCI Express */ +#define RADEON_AGP_COMMAND 0x0f60 /* PCI */ +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ +# define RADEON_AGP_ENABLE (1<<8) +#define RADEON_AGP_PLL_CNTL 0x000b /* PLL */ +#define RADEON_AGP_STATUS 0x0f5c /* PCI */ +# define RADEON_AGP_1X_MODE 0x01 +# define RADEON_AGP_2X_MODE 0x02 +# define RADEON_AGP_4X_MODE 0x04 +# define RADEON_AGP_FW_MODE 0x10 +# define RADEON_AGP_MODE_MASK 0x17 +# define RADEON_AGPv3_MODE 0x08 +# define RADEON_AGPv3_4X_MODE 0x01 +# define RADEON_AGPv3_8X_MODE 0x02 +#define RADEON_ATTRDR 0x03c1 /* VGA */ +#define RADEON_ATTRDW 0x03c0 /* VGA */ +#define RADEON_ATTRX 0x03c0 /* VGA */ +#define RADEON_AUX_SC_CNTL 0x1660 +# define RADEON_AUX1_SC_EN (1 << 0) +# define RADEON_AUX1_SC_MODE_OR (0 << 1) +# define RADEON_AUX1_SC_MODE_NAND (1 << 1) +# define RADEON_AUX2_SC_EN (1 << 2) +# define RADEON_AUX2_SC_MODE_OR (0 << 3) +# define RADEON_AUX2_SC_MODE_NAND (1 << 3) +# define RADEON_AUX3_SC_EN (1 << 4) +# define RADEON_AUX3_SC_MODE_OR (0 << 5) +# define RADEON_AUX3_SC_MODE_NAND (1 << 5) +#define RADEON_AUX1_SC_BOTTOM 0x1670 +#define RADEON_AUX1_SC_LEFT 0x1664 +#define RADEON_AUX1_SC_RIGHT 0x1668 +#define RADEON_AUX1_SC_TOP 0x166c +#define RADEON_AUX2_SC_BOTTOM 0x1680 +#define RADEON_AUX2_SC_LEFT 0x1674 +#define RADEON_AUX2_SC_RIGHT 0x1678 +#define RADEON_AUX2_SC_TOP 0x167c +#define RADEON_AUX3_SC_BOTTOM 0x1690 +#define RADEON_AUX3_SC_LEFT 0x1684 +#define RADEON_AUX3_SC_RIGHT 0x1688 +#define RADEON_AUX3_SC_TOP 0x168c +#define RADEON_AUX_WINDOW_HORZ_CNTL 0x02d8 +#define RADEON_AUX_WINDOW_VERT_CNTL 0x02dc + +#define RADEON_BASE_CODE 0x0f0b +#define RADEON_BIOS_0_SCRATCH 0x0010 +# define RADEON_FP_PANEL_SCALABLE (1 << 16) +# define RADEON_FP_PANEL_SCALE_EN (1 << 17) +# define RADEON_FP_CHIP_SCALE_EN (1 << 18) +# define RADEON_DRIVER_BRIGHTNESS_EN (1 << 26) +# define RADEON_DISPLAY_ROT_MASK (3 << 28) +# define RADEON_DISPLAY_ROT_00 (0 << 28) +# define RADEON_DISPLAY_ROT_90 (1 << 28) +# define RADEON_DISPLAY_ROT_180 (2 << 28) +# define RADEON_DISPLAY_ROT_270 (3 << 28) +#define RADEON_BIOS_1_SCRATCH 0x0014 +#define RADEON_BIOS_2_SCRATCH 0x0018 +#define RADEON_BIOS_3_SCRATCH 0x001c +#define RADEON_BIOS_4_SCRATCH 0x0020 +# define RADEON_CRT1_ATTACHED_MASK (3 << 0) +# define RADEON_CRT1_ATTACHED_MONO (1 << 0) +# define RADEON_CRT1_ATTACHED_COLOR (2 << 0) +# define RADEON_LCD1_ATTACHED (1 << 2) +# define RADEON_DFP1_ATTACHED (1 << 3) +# define RADEON_TV1_ATTACHED_MASK (3 << 4) +# define RADEON_TV1_ATTACHED_COMP (1 << 4) +# define RADEON_TV1_ATTACHED_SVIDEO (2 << 4) +# define RADEON_CRT2_ATTACHED_MASK (3 << 8) +# define RADEON_CRT2_ATTACHED_MONO (1 << 8) +# define RADEON_CRT2_ATTACHED_COLOR (2 << 8) +# define RADEON_DFP2_ATTACHED (1 << 11) +#define RADEON_BIOS_5_SCRATCH 0x0024 +# define RADEON_LCD1_ON (1 << 0) +# define RADEON_CRT1_ON (1 << 1) +# define RADEON_TV1_ON (1 << 2) +# define RADEON_DFP1_ON (1 << 3) +# define RADEON_CRT2_ON (1 << 5) +# define RADEON_CV1_ON (1 << 6) +# define RADEON_DFP2_ON (1 << 7) +# define RADEON_LCD1_CRTC_MASK (1 << 8) +# define RADEON_LCD1_CRTC_SHIFT 8 +# define RADEON_CRT1_CRTC_MASK (1 << 9) +# define RADEON_CRT1_CRTC_SHIFT 9 +# define RADEON_TV1_CRTC_MASK (1 << 10) +# define RADEON_TV1_CRTC_SHIFT 10 +# define RADEON_DFP1_CRTC_MASK (1 << 11) +# define RADEON_DFP1_CRTC_SHIFT 11 +# define RADEON_CRT2_CRTC_MASK (1 << 12) +# define RADEON_CRT2_CRTC_SHIFT 12 +# define RADEON_CV1_CRTC_MASK (1 << 13) +# define RADEON_CV1_CRTC_SHIFT 13 +# define RADEON_DFP2_CRTC_MASK (1 << 14) +# define RADEON_DFP2_CRTC_SHIFT 14 +# define RADEON_ACC_REQ_LCD1 (1 << 16) +# define RADEON_ACC_REQ_CRT1 (1 << 17) +# define RADEON_ACC_REQ_TV1 (1 << 18) +# define RADEON_ACC_REQ_DFP1 (1 << 19) +# define RADEON_ACC_REQ_CRT2 (1 << 21) +# define RADEON_ACC_REQ_TV2 (1 << 22) +# define RADEON_ACC_REQ_DFP2 (1 << 23) +#define RADEON_BIOS_6_SCRATCH 0x0028 +# define RADEON_ACC_MODE_CHANGE (1 << 2) +# define RADEON_EXT_DESKTOP_MODE (1 << 3) +# define RADEON_LCD_DPMS_ON (1 << 20) +# define RADEON_CRT_DPMS_ON (1 << 21) +# define RADEON_TV_DPMS_ON (1 << 22) +# define RADEON_DFP_DPMS_ON (1 << 23) +# define RADEON_DPMS_MASK (3 << 24) +# define RADEON_DPMS_ON (0 << 24) +# define RADEON_DPMS_STANDBY (1 << 24) +# define RADEON_DPMS_SUSPEND (2 << 24) +# define RADEON_DPMS_OFF (3 << 24) +# define RADEON_SCREEN_BLANKING (1 << 26) +# define RADEON_DRIVER_CRITICAL (1 << 27) +# define RADEON_DISPLAY_SWITCHING_DIS (1 << 30) +#define RADEON_BIOS_7_SCRATCH 0x002c +# define RADEON_SYS_HOTKEY (1 << 10) +# define RADEON_DRV_LOADED (1 << 12) +#define RADEON_BIOS_ROM 0x0f30 /* PCI */ +#define RADEON_BIST 0x0f0f /* PCI */ +#define RADEON_BRUSH_DATA0 0x1480 +#define RADEON_BRUSH_DATA1 0x1484 +#define RADEON_BRUSH_DATA10 0x14a8 +#define RADEON_BRUSH_DATA11 0x14ac +#define RADEON_BRUSH_DATA12 0x14b0 +#define RADEON_BRUSH_DATA13 0x14b4 +#define RADEON_BRUSH_DATA14 0x14b8 +#define RADEON_BRUSH_DATA15 0x14bc +#define RADEON_BRUSH_DATA16 0x14c0 +#define RADEON_BRUSH_DATA17 0x14c4 +#define RADEON_BRUSH_DATA18 0x14c8 +#define RADEON_BRUSH_DATA19 0x14cc +#define RADEON_BRUSH_DATA2 0x1488 +#define RADEON_BRUSH_DATA20 0x14d0 +#define RADEON_BRUSH_DATA21 0x14d4 +#define RADEON_BRUSH_DATA22 0x14d8 +#define RADEON_BRUSH_DATA23 0x14dc +#define RADEON_BRUSH_DATA24 0x14e0 +#define RADEON_BRUSH_DATA25 0x14e4 +#define RADEON_BRUSH_DATA26 0x14e8 +#define RADEON_BRUSH_DATA27 0x14ec +#define RADEON_BRUSH_DATA28 0x14f0 +#define RADEON_BRUSH_DATA29 0x14f4 +#define RADEON_BRUSH_DATA3 0x148c +#define RADEON_BRUSH_DATA30 0x14f8 +#define RADEON_BRUSH_DATA31 0x14fc +#define RADEON_BRUSH_DATA32 0x1500 +#define RADEON_BRUSH_DATA33 0x1504 +#define RADEON_BRUSH_DATA34 0x1508 +#define RADEON_BRUSH_DATA35 0x150c +#define RADEON_BRUSH_DATA36 0x1510 +#define RADEON_BRUSH_DATA37 0x1514 +#define RADEON_BRUSH_DATA38 0x1518 +#define RADEON_BRUSH_DATA39 0x151c +#define RADEON_BRUSH_DATA4 0x1490 +#define RADEON_BRUSH_DATA40 0x1520 +#define RADEON_BRUSH_DATA41 0x1524 +#define RADEON_BRUSH_DATA42 0x1528 +#define RADEON_BRUSH_DATA43 0x152c +#define RADEON_BRUSH_DATA44 0x1530 +#define RADEON_BRUSH_DATA45 0x1534 +#define RADEON_BRUSH_DATA46 0x1538 +#define RADEON_BRUSH_DATA47 0x153c +#define RADEON_BRUSH_DATA48 0x1540 +#define RADEON_BRUSH_DATA49 0x1544 +#define RADEON_BRUSH_DATA5 0x1494 +#define RADEON_BRUSH_DATA50 0x1548 +#define RADEON_BRUSH_DATA51 0x154c +#define RADEON_BRUSH_DATA52 0x1550 +#define RADEON_BRUSH_DATA53 0x1554 +#define RADEON_BRUSH_DATA54 0x1558 +#define RADEON_BRUSH_DATA55 0x155c +#define RADEON_BRUSH_DATA56 0x1560 +#define RADEON_BRUSH_DATA57 0x1564 +#define RADEON_BRUSH_DATA58 0x1568 +#define RADEON_BRUSH_DATA59 0x156c +#define RADEON_BRUSH_DATA6 0x1498 +#define RADEON_BRUSH_DATA60 0x1570 +#define RADEON_BRUSH_DATA61 0x1574 +#define RADEON_BRUSH_DATA62 0x1578 +#define RADEON_BRUSH_DATA63 0x157c +#define RADEON_BRUSH_DATA7 0x149c +#define RADEON_BRUSH_DATA8 0x14a0 +#define RADEON_BRUSH_DATA9 0x14a4 +#define RADEON_BRUSH_SCALE 0x1470 +#define RADEON_BRUSH_Y_X 0x1474 +#define RADEON_BUS_CNTL 0x0030 +# define RADEON_BUS_MASTER_DIS (1 << 6) +# define RADEON_BUS_BIOS_DIS_ROM (1 << 12) +# define RS600_BUS_MASTER_DIS (1 << 14) +# define RS600_MSI_REARM (1 << 20) /* rs600/rs690/rs740 */ +# define RADEON_BUS_RD_DISCARD_EN (1 << 24) +# define RADEON_BUS_RD_ABORT_EN (1 << 25) +# define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28) +# define RADEON_BUS_WRT_BURST (1 << 29) +# define RADEON_BUS_READ_BURST (1 << 30) +#define RADEON_BUS_CNTL1 0x0034 +# define RADEON_BUS_WAIT_ON_LOCK_EN (1 << 4) +#define RV370_BUS_CNTL 0x004c +# define RV370_BUS_BIOS_DIS_ROM (1 << 2) +/* rv370/rv380, rv410, r423/r430/r480, r5xx */ +#define RADEON_MSI_REARM_EN 0x0160 +# define RV370_MSI_REARM_EN (1 << 0) + +/* #define RADEON_PCIE_INDEX 0x0030 */ +/* #define RADEON_PCIE_DATA 0x0034 */ +#define RADEON_PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE */ +# define RADEON_PCIE_LC_LINK_WIDTH_SHIFT 0 +# define RADEON_PCIE_LC_LINK_WIDTH_MASK 0x7 +# define RADEON_PCIE_LC_LINK_WIDTH_X0 0 +# define RADEON_PCIE_LC_LINK_WIDTH_X1 1 +# define RADEON_PCIE_LC_LINK_WIDTH_X2 2 +# define RADEON_PCIE_LC_LINK_WIDTH_X4 3 +# define RADEON_PCIE_LC_LINK_WIDTH_X8 4 +# define RADEON_PCIE_LC_LINK_WIDTH_X12 5 +# define RADEON_PCIE_LC_LINK_WIDTH_X16 6 +# define RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT 4 +# define RADEON_PCIE_LC_LINK_WIDTH_RD_MASK 0x70 +# define RADEON_PCIE_LC_RECONFIG_NOW (1 << 8) +# define RADEON_PCIE_LC_RECONFIG_LATER (1 << 9) +# define RADEON_PCIE_LC_SHORT_RECONFIG_EN (1 << 10) +# define R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7) +# define R600_PCIE_LC_RENEGOTIATION_SUPPORT (1 << 9) +# define R600_PCIE_LC_RENEGOTIATE_EN (1 << 10) +# define R600_PCIE_LC_SHORT_RECONFIG_EN (1 << 11) +# define R600_PCIE_LC_UPCONFIGURE_SUPPORT (1 << 12) +# define R600_PCIE_LC_UPCONFIGURE_DIS (1 << 13) + +#define R600_TARGET_AND_CURRENT_PROFILE_INDEX 0x70c +#define R700_TARGET_AND_CURRENT_PROFILE_INDEX 0x66c + +#define RADEON_CACHE_CNTL 0x1724 +#define RADEON_CACHE_LINE 0x0f0c /* PCI */ +#define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */ +#define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */ +#define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */ +# define RADEON_DONT_USE_XTALIN (1 << 4) +# define RADEON_SCLK_DYN_START_CNTL (1 << 15) +#define RADEON_CLOCK_CNTL_DATA 0x000c +#define RADEON_CLOCK_CNTL_INDEX 0x0008 +# define RADEON_PLL_WR_EN (1 << 7) +# define RADEON_PLL_DIV_SEL (3 << 8) +# define RADEON_PLL2_DIV_SEL_MASK (~(3 << 8)) +#define RADEON_CLK_PWRMGT_CNTL 0x0014 +# define RADEON_ENGIN_DYNCLK_MODE (1 << 12) +# define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13) +# define RADEON_ACTIVE_HILO_LAT_SHIFT 13 +# define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12) +# define RADEON_MC_BUSY (1 << 16) +# define RADEON_DLL_READY (1 << 19) +# define RADEON_CG_NO1_DEBUG_0 (1 << 24) +# define RADEON_CG_NO1_DEBUG_MASK (0x1f << 24) +# define RADEON_DYN_STOP_MODE_MASK (7 << 21) +# define RADEON_TVPLL_PWRMGT_OFF (1 << 30) +# define RADEON_TVCLK_TURNOFF (1 << 31) +#define RADEON_PLL_PWRMGT_CNTL 0x0015 /* PLL */ +# define RADEON_PM_MODE_SEL (1 << 13) +# define RADEON_TCL_BYPASS_DISABLE (1 << 20) +#define RADEON_CLR_CMP_CLR_3D 0x1a24 +#define RADEON_CLR_CMP_CLR_DST 0x15c8 +#define RADEON_CLR_CMP_CLR_SRC 0x15c4 +#define RADEON_CLR_CMP_CNTL 0x15c0 +# define RADEON_SRC_CMP_EQ_COLOR (4 << 0) +# define RADEON_SRC_CMP_NEQ_COLOR (5 << 0) +# define RADEON_CLR_CMP_SRC_SOURCE (1 << 24) +#define RADEON_CLR_CMP_MASK 0x15cc +# define RADEON_CLR_CMP_MSK 0xffffffff +#define RADEON_CLR_CMP_MASK_3D 0x1A28 +#define RADEON_COMMAND 0x0f04 /* PCI */ +#define RADEON_COMPOSITE_SHADOW_ID 0x1a0c +#define RADEON_CONFIG_APER_0_BASE 0x0100 +#define RADEON_CONFIG_APER_1_BASE 0x0104 +#define RADEON_CONFIG_APER_SIZE 0x0108 +#define RADEON_CONFIG_BONDS 0x00e8 +#define RADEON_CONFIG_CNTL 0x00e0 +# define RADEON_CFG_VGA_RAM_EN (1 << 8) +# define RADEON_CFG_VGA_IO_DIS (1 << 9) +# define RADEON_CFG_ATI_REV_A11 (0 << 16) +# define RADEON_CFG_ATI_REV_A12 (1 << 16) +# define RADEON_CFG_ATI_REV_A13 (2 << 16) +# define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16) +#define RADEON_CONFIG_MEMSIZE 0x00f8 +#define RADEON_CONFIG_MEMSIZE_EMBEDDED 0x0114 +#define RADEON_CONFIG_REG_1_BASE 0x010c +#define RADEON_CONFIG_REG_APER_SIZE 0x0110 +#define RADEON_CONFIG_XSTRAP 0x00e4 +#define RADEON_CONSTANT_COLOR_C 0x1d34 +# define RADEON_CONSTANT_COLOR_MASK 0x00ffffff +# define RADEON_CONSTANT_COLOR_ONE 0x00ffffff +# define RADEON_CONSTANT_COLOR_ZERO 0x00000000 +#define RADEON_CRC_CMDFIFO_ADDR 0x0740 +#define RADEON_CRC_CMDFIFO_DOUT 0x0744 +#define RADEON_GRPH_BUFFER_CNTL 0x02f0 +# define RADEON_GRPH_START_REQ_MASK (0x7f) +# define RADEON_GRPH_START_REQ_SHIFT 0 +# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH_STOP_REQ_SHIFT 8 +# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH_BUFFER_SIZE (1<<29) +# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH_STOP_CNTL (1<<31) +#define RADEON_GRPH2_BUFFER_CNTL 0x03f0 +# define RADEON_GRPH2_START_REQ_MASK (0x7f) +# define RADEON_GRPH2_START_REQ_SHIFT 0 +# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH2_STOP_REQ_SHIFT 8 +# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH2_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH2_BUFFER_SIZE (1<<29) +# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH2_STOP_CNTL (1<<31) +#define RADEON_CRTC_CRNT_FRAME 0x0214 +#define RADEON_CRTC_EXT_CNTL 0x0054 +# define RADEON_CRTC_VGA_XOVERSCAN (1 << 0) +# define RADEON_VGA_ATI_LINEAR (1 << 3) +# define RADEON_XCRT_CNT_EN (1 << 6) +# define RADEON_CRTC_HSYNC_DIS (1 << 8) +# define RADEON_CRTC_VSYNC_DIS (1 << 9) +# define RADEON_CRTC_DISPLAY_DIS (1 << 10) +# define RADEON_CRTC_SYNC_TRISTAT (1 << 11) +# define RADEON_CRTC_CRT_ON (1 << 15) +#define RADEON_CRTC_EXT_CNTL_DPMS_BYTE 0x0055 +# define RADEON_CRTC_HSYNC_DIS_BYTE (1 << 0) +# define RADEON_CRTC_VSYNC_DIS_BYTE (1 << 1) +# define RADEON_CRTC_DISPLAY_DIS_BYTE (1 << 2) +#define RADEON_CRTC_GEN_CNTL 0x0050 +# define RADEON_CRTC_DBL_SCAN_EN (1 << 0) +# define RADEON_CRTC_INTERLACE_EN (1 << 1) +# define RADEON_CRTC_CSYNC_EN (1 << 4) +# define RADEON_CRTC_ICON_EN (1 << 15) +# define RADEON_CRTC_CUR_EN (1 << 16) +# define RADEON_CRTC_VSTAT_MODE_MASK (3 << 17) +# define RADEON_CRTC_CUR_MODE_MASK (7 << 20) +# define RADEON_CRTC_CUR_MODE_SHIFT 20 +# define RADEON_CRTC_CUR_MODE_MONO 0 +# define RADEON_CRTC_CUR_MODE_24BPP 2 +# define RADEON_CRTC_EXT_DISP_EN (1 << 24) +# define RADEON_CRTC_EN (1 << 25) +# define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) +#define RADEON_CRTC2_GEN_CNTL 0x03f8 +# define RADEON_CRTC2_DBL_SCAN_EN (1 << 0) +# define RADEON_CRTC2_INTERLACE_EN (1 << 1) +# define RADEON_CRTC2_SYNC_TRISTAT (1 << 4) +# define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5) +# define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6) +# define RADEON_CRTC2_CRT2_ON (1 << 7) +# define RADEON_CRTC2_PIX_WIDTH_SHIFT 8 +# define RADEON_CRTC2_PIX_WIDTH_MASK (0xf << 8) +# define RADEON_CRTC2_ICON_EN (1 << 15) +# define RADEON_CRTC2_CUR_EN (1 << 16) +# define RADEON_CRTC2_CUR_MODE_MASK (7 << 20) +# define RADEON_CRTC2_DISP_DIS (1 << 23) +# define RADEON_CRTC2_EN (1 << 25) +# define RADEON_CRTC2_DISP_REQ_EN_B (1 << 26) +# define RADEON_CRTC2_CSYNC_EN (1 << 27) +# define RADEON_CRTC2_HSYNC_DIS (1 << 28) +# define RADEON_CRTC2_VSYNC_DIS (1 << 29) +#define RADEON_CRTC_MORE_CNTL 0x27c +# define RADEON_CRTC_AUTO_HORZ_CENTER_EN (1<<2) +# define RADEON_CRTC_AUTO_VERT_CENTER_EN (1<<3) +# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) +# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) +#define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 +#define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 +# define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) +# define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3) +# define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3 +# define RADEON_CRTC_H_SYNC_WID (0x3f << 16) +# define RADEON_CRTC_H_SYNC_WID_SHIFT 16 +# define RADEON_CRTC_H_SYNC_POL (1 << 23) +#define RADEON_CRTC2_H_SYNC_STRT_WID 0x0304 +# define RADEON_CRTC2_H_SYNC_STRT_PIX (0x07 << 0) +# define RADEON_CRTC2_H_SYNC_STRT_CHAR (0x3ff << 3) +# define RADEON_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3 +# define RADEON_CRTC2_H_SYNC_WID (0x3f << 16) +# define RADEON_CRTC2_H_SYNC_WID_SHIFT 16 +# define RADEON_CRTC2_H_SYNC_POL (1 << 23) +#define RADEON_CRTC_H_TOTAL_DISP 0x0200 +# define RADEON_CRTC_H_TOTAL (0x03ff << 0) +# define RADEON_CRTC_H_TOTAL_SHIFT 0 +# define RADEON_CRTC_H_DISP (0x01ff << 16) +# define RADEON_CRTC_H_DISP_SHIFT 16 +#define RADEON_CRTC2_H_TOTAL_DISP 0x0300 +# define RADEON_CRTC2_H_TOTAL (0x03ff << 0) +# define RADEON_CRTC2_H_TOTAL_SHIFT 0 +# define RADEON_CRTC2_H_DISP (0x01ff << 16) +# define RADEON_CRTC2_H_DISP_SHIFT 16 + +#define RADEON_CRTC_OFFSET_RIGHT 0x0220 +#define RADEON_CRTC_OFFSET 0x0224 +# define RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET (1<<30) +# define RADEON_CRTC_OFFSET__OFFSET_LOCK (1<<31) + +#define RADEON_CRTC2_OFFSET 0x0324 +# define RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET (1<<30) +# define RADEON_CRTC2_OFFSET__OFFSET_LOCK (1<<31) +#define RADEON_CRTC_OFFSET_CNTL 0x0228 +# define RADEON_CRTC_TILE_LINE_SHIFT 0 +# define RADEON_CRTC_TILE_LINE_RIGHT_SHIFT 4 +# define R300_CRTC_X_Y_MODE_EN_RIGHT (1 << 6) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_MASK (3 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_AUTO (0 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_SINGLE (1 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DOUBLE (2 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DIS (3 << 7) +# define R300_CRTC_X_Y_MODE_EN (1 << 9) +# define R300_CRTC_MICRO_TILE_BUFFER_MASK (3 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_AUTO (0 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_SINGLE (1 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_DOUBLE (2 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_DIS (3 << 10) +# define R300_CRTC_MICRO_TILE_EN_RIGHT (1 << 12) +# define R300_CRTC_MICRO_TILE_EN (1 << 13) +# define R300_CRTC_MACRO_TILE_EN_RIGHT (1 << 14) +# define R300_CRTC_MACRO_TILE_EN (1 << 15) +# define RADEON_CRTC_TILE_EN_RIGHT (1 << 14) +# define RADEON_CRTC_TILE_EN (1 << 15) +# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +# define RADEON_CRTC_STEREO_OFFSET_EN (1 << 17) +# define RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN (1 << 28) +# define RADEON_CRTC_GUI_TRIG_OFFSET_RIGHT_EN (1 << 29) + +#define R300_CRTC_TILE_X0_Y0 0x0350 +#define R300_CRTC2_TILE_X0_Y0 0x0358 + +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 +# define RADEON_CRTC2_OFFSET_FLIP_CNTL (1 << 16) +# define RADEON_CRTC2_TILE_EN (1 << 15) +#define RADEON_CRTC_PITCH 0x022c +# define RADEON_CRTC_PITCH__SHIFT 0 +# define RADEON_CRTC_PITCH__RIGHT_SHIFT 16 + +#define RADEON_CRTC2_PITCH 0x032c +#define RADEON_CRTC_STATUS 0x005c +# define RADEON_CRTC_VBLANK_CUR (1 << 0) +# define RADEON_CRTC_VBLANK_SAVE (1 << 1) +# define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1) +#define RADEON_CRTC2_STATUS 0x03fc +# define RADEON_CRTC2_VBLANK_CUR (1 << 0) +# define RADEON_CRTC2_VBLANK_SAVE (1 << 1) +# define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1) +#define RADEON_CRTC_V_SYNC_STRT_WID 0x020c +# define RADEON_CRTC_V_SYNC_STRT (0x7ff << 0) +# define RADEON_CRTC_V_SYNC_STRT_SHIFT 0 +# define RADEON_CRTC_V_SYNC_WID (0x1f << 16) +# define RADEON_CRTC_V_SYNC_WID_SHIFT 16 +# define RADEON_CRTC_V_SYNC_POL (1 << 23) +#define RADEON_CRTC2_V_SYNC_STRT_WID 0x030c +# define RADEON_CRTC2_V_SYNC_STRT (0x7ff << 0) +# define RADEON_CRTC2_V_SYNC_STRT_SHIFT 0 +# define RADEON_CRTC2_V_SYNC_WID (0x1f << 16) +# define RADEON_CRTC2_V_SYNC_WID_SHIFT 16 +# define RADEON_CRTC2_V_SYNC_POL (1 << 23) +#define RADEON_CRTC_V_TOTAL_DISP 0x0208 +# define RADEON_CRTC_V_TOTAL (0x07ff << 0) +# define RADEON_CRTC_V_TOTAL_SHIFT 0 +# define RADEON_CRTC_V_DISP (0x07ff << 16) +# define RADEON_CRTC_V_DISP_SHIFT 16 +#define RADEON_CRTC2_V_TOTAL_DISP 0x0308 +# define RADEON_CRTC2_V_TOTAL (0x07ff << 0) +# define RADEON_CRTC2_V_TOTAL_SHIFT 0 +# define RADEON_CRTC2_V_DISP (0x07ff << 16) +# define RADEON_CRTC2_V_DISP_SHIFT 16 +#define RADEON_CRTC_VLINE_CRNT_VLINE 0x0210 +# define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16) +#define RADEON_CRTC2_CRNT_FRAME 0x0314 +#define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318 +#define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310 +#define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ +#define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ +#define RADEON_CUR_CLR0 0x026c +#define RADEON_CUR_CLR1 0x0270 +#define RADEON_CUR_HORZ_VERT_OFF 0x0268 +#define RADEON_CUR_HORZ_VERT_POSN 0x0264 +#define RADEON_CUR_OFFSET 0x0260 +# define RADEON_CUR_LOCK (1 << 31) +#define RADEON_CUR2_CLR0 0x036c +#define RADEON_CUR2_CLR1 0x0370 +#define RADEON_CUR2_HORZ_VERT_OFF 0x0368 +#define RADEON_CUR2_HORZ_VERT_POSN 0x0364 +#define RADEON_CUR2_OFFSET 0x0360 +# define RADEON_CUR2_LOCK (1 << 31) + +#define RADEON_DAC_CNTL 0x0058 +# define RADEON_DAC_RANGE_CNTL (3 << 0) +# define RADEON_DAC_RANGE_CNTL_PS2 (2 << 0) +# define RADEON_DAC_RANGE_CNTL_MASK 0x03 +# define RADEON_DAC_BLANKING (1 << 2) +# define RADEON_DAC_CMP_EN (1 << 3) +# define RADEON_DAC_CMP_OUTPUT (1 << 7) +# define RADEON_DAC_8BIT_EN (1 << 8) +# define RADEON_DAC_TVO_EN (1 << 10) +# define RADEON_DAC_VGA_ADR_EN (1 << 13) +# define RADEON_DAC_PDWN (1 << 15) +# define RADEON_DAC_MASK_ALL (0xff << 24) +#define RADEON_DAC_CNTL2 0x007c +# define RADEON_DAC2_TV_CLK_SEL (0 << 1) +# define RADEON_DAC2_DAC_CLK_SEL (1 << 0) +# define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) +# define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) +# define RADEON_DAC2_CMP_EN (1 << 7) +# define RADEON_DAC2_CMP_OUT_R (1 << 8) +# define RADEON_DAC2_CMP_OUT_G (1 << 9) +# define RADEON_DAC2_CMP_OUT_B (1 << 10) +# define RADEON_DAC2_CMP_OUTPUT (1 << 11) +#define RADEON_DAC_EXT_CNTL 0x0280 +# define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0) +# define RADEON_DAC2_FORCE_DATA_EN (1 << 1) +# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) +# define RADEON_DAC_FORCE_DATA_EN (1 << 5) +# define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_R (0 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_G (1 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_B (2 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_RGB (3 << 6) +# define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 +# define RADEON_DAC_FORCE_DATA_SHIFT 8 +#define RADEON_DAC_MACRO_CNTL 0x0d04 +# define RADEON_DAC_PDWN_R (1 << 16) +# define RADEON_DAC_PDWN_G (1 << 17) +# define RADEON_DAC_PDWN_B (1 << 18) +#define RADEON_DISP_PWR_MAN 0x0d08 +# define RADEON_DISP_PWR_MAN_D3_CRTC_EN (1 << 0) +# define RADEON_DISP_PWR_MAN_D3_CRTC2_EN (1 << 4) +# define RADEON_DISP_PWR_MAN_DPMS_ON (0 << 8) +# define RADEON_DISP_PWR_MAN_DPMS_STANDBY (1 << 8) +# define RADEON_DISP_PWR_MAN_DPMS_SUSPEND (2 << 8) +# define RADEON_DISP_PWR_MAN_DPMS_OFF (3 << 8) +# define RADEON_DISP_D3_RST (1 << 16) +# define RADEON_DISP_D3_REG_RST (1 << 17) +# define RADEON_DISP_D3_GRPH_RST (1 << 18) +# define RADEON_DISP_D3_SUBPIC_RST (1 << 19) +# define RADEON_DISP_D3_OV0_RST (1 << 20) +# define RADEON_DISP_D1D2_GRPH_RST (1 << 21) +# define RADEON_DISP_D1D2_SUBPIC_RST (1 << 22) +# define RADEON_DISP_D1D2_OV0_RST (1 << 23) +# define RADEON_DIG_TMDS_ENABLE_RST (1 << 24) +# define RADEON_TV_ENABLE_RST (1 << 25) +# define RADEON_AUTO_PWRUP_EN (1 << 26) +#define RADEON_TV_DAC_CNTL 0x088c +# define RADEON_TV_DAC_NBLANK (1 << 0) +# define RADEON_TV_DAC_NHOLD (1 << 1) +# define RADEON_TV_DAC_PEDESTAL (1 << 2) +# define RADEON_TV_MONITOR_DETECT_EN (1 << 4) +# define RADEON_TV_DAC_CMPOUT (1 << 5) +# define RADEON_TV_DAC_STD_MASK (3 << 8) +# define RADEON_TV_DAC_STD_PAL (0 << 8) +# define RADEON_TV_DAC_STD_NTSC (1 << 8) +# define RADEON_TV_DAC_STD_PS2 (2 << 8) +# define RADEON_TV_DAC_STD_RS343 (3 << 8) +# define RADEON_TV_DAC_BGSLEEP (1 << 6) +# define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) +# define RADEON_TV_DAC_BGADJ_SHIFT 16 +# define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) +# define RADEON_TV_DAC_DACADJ_SHIFT 20 +# define RADEON_TV_DAC_RDACPD (1 << 24) +# define RADEON_TV_DAC_GDACPD (1 << 25) +# define RADEON_TV_DAC_BDACPD (1 << 26) +# define RADEON_TV_DAC_RDACDET (1 << 29) +# define RADEON_TV_DAC_GDACDET (1 << 30) +# define RADEON_TV_DAC_BDACDET (1 << 31) +# define R420_TV_DAC_DACADJ_MASK (0x1f << 20) +# define R420_TV_DAC_RDACPD (1 << 25) +# define R420_TV_DAC_GDACPD (1 << 26) +# define R420_TV_DAC_BDACPD (1 << 27) +# define R420_TV_DAC_TVENABLE (1 << 28) +#define RADEON_DISP_HW_DEBUG 0x0d14 +# define RADEON_CRT2_DISP1_SEL (1 << 5) +#define RADEON_DISP_OUTPUT_CNTL 0x0d64 +# define RADEON_DISP_DAC_SOURCE_MASK 0x03 +# define RADEON_DISP_DAC2_SOURCE_MASK 0x0c +# define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 +# define RADEON_DISP_DAC_SOURCE_RMX 0x02 +# define RADEON_DISP_DAC_SOURCE_LTU 0x03 +# define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 +# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03 << 2) +# define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 +# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2) +# define RADEON_DISP_TVDAC_SOURCE_RMX (0x02 << 2) +# define RADEON_DISP_TVDAC_SOURCE_LTU (0x03 << 2) +# define RADEON_DISP_TRANS_MATRIX_MASK (0x03 << 4) +# define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4) +# define RADEON_DISP_TRANS_MATRIX_GRAPHICS (0x01 << 4) +# define RADEON_DISP_TRANS_MATRIX_VIDEO (0x02 << 4) +# define RADEON_DISP_TV_SOURCE_CRTC (1 << 16) /* crtc1 or crtc2 */ +# define RADEON_DISP_TV_SOURCE_LTU (0 << 16) /* linear transform unit */ +#define RADEON_DISP_TV_OUT_CNTL 0x0d6c +# define RADEON_DISP_TV_PATH_SRC_CRTC2 (1 << 16) +# define RADEON_DISP_TV_PATH_SRC_CRTC1 (0 << 16) +#define RADEON_DAC_CRC_SIG 0x02cc +#define RADEON_DAC_DATA 0x03c9 /* VGA */ +#define RADEON_DAC_MASK 0x03c6 /* VGA */ +#define RADEON_DAC_R_INDEX 0x03c7 /* VGA */ +#define RADEON_DAC_W_INDEX 0x03c8 /* VGA */ +#define RADEON_DDA_CONFIG 0x02e0 +#define RADEON_DDA_ON_OFF 0x02e4 +#define RADEON_DEFAULT_OFFSET 0x16e0 +#define RADEON_DEFAULT_PITCH 0x16e4 +#define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 +# define RADEON_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) +# define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) +#define RADEON_DESTINATION_3D_CLR_CMP_VAL 0x1820 +#define RADEON_DESTINATION_3D_CLR_CMP_MSK 0x1824 +#define RADEON_DEVICE_ID 0x0f02 /* PCI */ +#define RADEON_DISP_MISC_CNTL 0x0d00 +# define RADEON_SOFT_RESET_GRPH_PP (1 << 0) +#define RADEON_DISP_MERGE_CNTL 0x0d60 +# define RADEON_DISP_ALPHA_MODE_MASK 0x03 +# define RADEON_DISP_ALPHA_MODE_KEY 0 +# define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1 +# define RADEON_DISP_ALPHA_MODE_GLOBAL 2 +# define RADEON_DISP_RGB_OFFSET_EN (1 << 8) +# define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) +# define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) +# define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) +#define RADEON_DISP2_MERGE_CNTL 0x0d68 +# define RADEON_DISP2_RGB_OFFSET_EN (1 << 8) +#define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 +#define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 +#define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 +#define RADEON_DISP_LIN_TRANS_GRPH_D 0x0d8c +#define RADEON_DISP_LIN_TRANS_GRPH_E 0x0d90 +#define RADEON_DISP_LIN_TRANS_GRPH_F 0x0d98 +#define RADEON_DP_BRUSH_BKGD_CLR 0x1478 +#define RADEON_DP_BRUSH_FRGD_CLR 0x147c +#define RADEON_DP_CNTL 0x16c0 +# define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) +# define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) +# define RADEON_DP_DST_TILE_LINEAR (0 << 3) +# define RADEON_DP_DST_TILE_MACRO (1 << 3) +# define RADEON_DP_DST_TILE_MICRO (2 << 3) +# define RADEON_DP_DST_TILE_BOTH (3 << 3) +#define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 +# define RADEON_DST_Y_MAJOR (1 << 2) +# define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) +# define RADEON_DST_X_DIR_LEFT_TO_RIGHT (1 << 31) +#define RADEON_DP_DATATYPE 0x16c4 +# define RADEON_HOST_BIG_ENDIAN_EN (1 << 29) +#define RADEON_DP_GUI_MASTER_CNTL 0x146c +# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) +# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) +# define RADEON_GMC_SRC_CLIPPING (1 << 2) +# define RADEON_GMC_DST_CLIPPING (1 << 3) +# define RADEON_GMC_BRUSH_DATATYPE_MASK (0x0f << 4) +# define RADEON_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4) +# define RADEON_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4) +# define RADEON_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4) +# define RADEON_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4) +# define RADEON_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4) +# define RADEON_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4) +# define RADEON_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4) +# define RADEON_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4) +# define RADEON_GMC_BRUSH_8x8_COLOR (10 << 4) +# define RADEON_GMC_BRUSH_1X8_COLOR (12 << 4) +# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define RADEON_GMC_BRUSH_NONE (15 << 4) +# define RADEON_GMC_DST_8BPP_CI (2 << 8) +# define RADEON_GMC_DST_15BPP (3 << 8) +# define RADEON_GMC_DST_16BPP (4 << 8) +# define RADEON_GMC_DST_24BPP (5 << 8) +# define RADEON_GMC_DST_32BPP (6 << 8) +# define RADEON_GMC_DST_8BPP_RGB (7 << 8) +# define RADEON_GMC_DST_Y8 (8 << 8) +# define RADEON_GMC_DST_RGB8 (9 << 8) +# define RADEON_GMC_DST_VYUY (11 << 8) +# define RADEON_GMC_DST_YVYU (12 << 8) +# define RADEON_GMC_DST_AYUV444 (14 << 8) +# define RADEON_GMC_DST_ARGB4444 (15 << 8) +# define RADEON_GMC_DST_DATATYPE_MASK (0x0f << 8) +# define RADEON_GMC_DST_DATATYPE_SHIFT 8 +# define RADEON_GMC_SRC_DATATYPE_MASK (3 << 12) +# define RADEON_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12) +# define RADEON_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) +# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) +# define RADEON_GMC_BYTE_PIX_ORDER (1 << 14) +# define RADEON_GMC_BYTE_MSB_TO_LSB (0 << 14) +# define RADEON_GMC_BYTE_LSB_TO_MSB (1 << 14) +# define RADEON_GMC_CONVERSION_TEMP (1 << 15) +# define RADEON_GMC_CONVERSION_TEMP_6500 (0 << 15) +# define RADEON_GMC_CONVERSION_TEMP_9300 (1 << 15) +# define RADEON_GMC_ROP3_MASK (0xff << 16) +# define RADEON_DP_SRC_SOURCE_MASK (7 << 24) +# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) +# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) +# define RADEON_GMC_3D_FCN_EN (1 << 27) +# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) +# define RADEON_GMC_AUX_CLIP_DIS (1 << 29) +# define RADEON_GMC_WR_MSK_DIS (1 << 30) +# define RADEON_GMC_LD_BRUSH_Y_X (1 << 31) +# define RADEON_ROP3_ZERO 0x00000000 +# define RADEON_ROP3_DSa 0x00880000 +# define RADEON_ROP3_SDna 0x00440000 +# define RADEON_ROP3_S 0x00cc0000 +# define RADEON_ROP3_DSna 0x00220000 +# define RADEON_ROP3_D 0x00aa0000 +# define RADEON_ROP3_DSx 0x00660000 +# define RADEON_ROP3_DSo 0x00ee0000 +# define RADEON_ROP3_DSon 0x00110000 +# define RADEON_ROP3_DSxn 0x00990000 +# define RADEON_ROP3_Dn 0x00550000 +# define RADEON_ROP3_SDno 0x00dd0000 +# define RADEON_ROP3_Sn 0x00330000 +# define RADEON_ROP3_DSno 0x00bb0000 +# define RADEON_ROP3_DSan 0x00770000 +# define RADEON_ROP3_ONE 0x00ff0000 +# define RADEON_ROP3_DPa 0x00a00000 +# define RADEON_ROP3_PDna 0x00500000 +# define RADEON_ROP3_P 0x00f00000 +# define RADEON_ROP3_DPna 0x000a0000 +# define RADEON_ROP3_D 0x00aa0000 +# define RADEON_ROP3_DPx 0x005a0000 +# define RADEON_ROP3_DPo 0x00fa0000 +# define RADEON_ROP3_DPon 0x00050000 +# define RADEON_ROP3_PDxn 0x00a50000 +# define RADEON_ROP3_PDno 0x00f50000 +# define RADEON_ROP3_Pn 0x000f0000 +# define RADEON_ROP3_DPno 0x00af0000 +# define RADEON_ROP3_DPan 0x005f0000 +#define RADEON_DP_GUI_MASTER_CNTL_C 0x1c84 +#define RADEON_DP_MIX 0x16c8 +#define RADEON_DP_SRC_BKGD_CLR 0x15dc +#define RADEON_DP_SRC_FRGD_CLR 0x15d8 +#define RADEON_DP_WRITE_MASK 0x16cc +#define RADEON_DST_BRES_DEC 0x1630 +#define RADEON_DST_BRES_ERR 0x1628 +#define RADEON_DST_BRES_INC 0x162c +#define RADEON_DST_BRES_LNTH 0x1634 +#define RADEON_DST_BRES_LNTH_SUB 0x1638 +#define RADEON_DST_HEIGHT 0x1410 +#define RADEON_DST_HEIGHT_WIDTH 0x143c +#define RADEON_DST_HEIGHT_WIDTH_8 0x158c +#define RADEON_DST_HEIGHT_WIDTH_BW 0x15b4 +#define RADEON_DST_HEIGHT_Y 0x15a0 +#define RADEON_DST_LINE_START 0x1600 +#define RADEON_DST_LINE_END 0x1604 +#define RADEON_DST_LINE_PATCOUNT 0x1608 +# define RADEON_BRES_CNTL_SHIFT 8 +#define RADEON_DST_OFFSET 0x1404 +#define RADEON_DST_PITCH 0x1408 +#define RADEON_DST_PITCH_OFFSET 0x142c +#define RADEON_DST_PITCH_OFFSET_C 0x1c80 +# define RADEON_PITCH_SHIFT 21 +# define RADEON_DST_TILE_LINEAR (0 << 30) +# define RADEON_DST_TILE_MACRO (1 << 30) +# define RADEON_DST_TILE_MICRO (2 << 30) +# define RADEON_DST_TILE_BOTH (3 << 30) +#define RADEON_DST_WIDTH 0x140c +#define RADEON_DST_WIDTH_HEIGHT 0x1598 +#define RADEON_DST_WIDTH_X 0x1588 +#define RADEON_DST_WIDTH_X_INCY 0x159c +#define RADEON_DST_X 0x141c +#define RADEON_DST_X_SUB 0x15a4 +#define RADEON_DST_X_Y 0x1594 +#define RADEON_DST_Y 0x1420 +#define RADEON_DST_Y_SUB 0x15a8 +#define RADEON_DST_Y_X 0x1438 + +#define RADEON_FCP_CNTL 0x0910 +# define RADEON_FCP0_SRC_PCICLK 0 +# define RADEON_FCP0_SRC_PCLK 1 +# define RADEON_FCP0_SRC_PCLKb 2 +# define RADEON_FCP0_SRC_HREF 3 +# define RADEON_FCP0_SRC_GND 4 +# define RADEON_FCP0_SRC_HREFb 5 +#define RADEON_FLUSH_1 0x1704 +#define RADEON_FLUSH_2 0x1708 +#define RADEON_FLUSH_3 0x170c +#define RADEON_FLUSH_4 0x1710 +#define RADEON_FLUSH_5 0x1714 +#define RADEON_FLUSH_6 0x1718 +#define RADEON_FLUSH_7 0x171c +#define RADEON_FOG_3D_TABLE_START 0x1810 +#define RADEON_FOG_3D_TABLE_END 0x1814 +#define RADEON_FOG_3D_TABLE_DENSITY 0x181c +#define RADEON_FOG_TABLE_INDEX 0x1a14 +#define RADEON_FOG_TABLE_DATA 0x1a18 +#define RADEON_FP_CRTC_H_TOTAL_DISP 0x0250 +#define RADEON_FP_CRTC_V_TOTAL_DISP 0x0254 +# define RADEON_FP_CRTC_H_TOTAL_MASK 0x000003ff +# define RADEON_FP_CRTC_H_DISP_MASK 0x01ff0000 +# define RADEON_FP_CRTC_V_TOTAL_MASK 0x00000fff +# define RADEON_FP_CRTC_V_DISP_MASK 0x0fff0000 +# define RADEON_FP_H_SYNC_STRT_CHAR_MASK 0x00001ff8 +# define RADEON_FP_H_SYNC_WID_MASK 0x003f0000 +# define RADEON_FP_V_SYNC_STRT_MASK 0x00000fff +# define RADEON_FP_V_SYNC_WID_MASK 0x001f0000 +# define RADEON_FP_CRTC_H_TOTAL_SHIFT 0x00000000 +# define RADEON_FP_CRTC_H_DISP_SHIFT 0x00000010 +# define RADEON_FP_CRTC_V_TOTAL_SHIFT 0x00000000 +# define RADEON_FP_CRTC_V_DISP_SHIFT 0x00000010 +# define RADEON_FP_H_SYNC_STRT_CHAR_SHIFT 0x00000003 +# define RADEON_FP_H_SYNC_WID_SHIFT 0x00000010 +# define RADEON_FP_V_SYNC_STRT_SHIFT 0x00000000 +# define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010 +#define RADEON_FP_GEN_CNTL 0x0284 +# define RADEON_FP_FPON (1 << 0) +# define RADEON_FP_BLANK_EN (1 << 1) +# define RADEON_FP_TMDS_EN (1 << 2) +# define RADEON_FP_PANEL_FORMAT (1 << 3) +# define RADEON_FP_EN_TMDS (1 << 7) +# define RADEON_FP_DETECT_SENSE (1 << 8) +# define RADEON_FP_DETECT_INT_POL (1 << 9) +# define R200_FP_SOURCE_SEL_MASK (3 << 10) +# define R200_FP_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP_SOURCE_SEL_RMX (2 << 10) +# define R200_FP_SOURCE_SEL_TRANS (3 << 10) +# define RADEON_FP_SEL_CRTC1 (0 << 13) +# define RADEON_FP_SEL_CRTC2 (1 << 13) +# define R300_HPD_SEL(x) ((x) << 13) +# define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) +# define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) +# define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17) +# define RADEON_FP_CRTC_USE_SHADOW_VEND (1 << 18) +# define RADEON_FP_RMX_HVSYNC_CONTROL_EN (1 << 20) +# define RADEON_FP_DFP_SYNC_SEL (1 << 21) +# define RADEON_FP_CRTC_LOCK_8DOT (1 << 22) +# define RADEON_FP_CRT_SYNC_SEL (1 << 23) +# define RADEON_FP_USE_SHADOW_EN (1 << 24) +# define RADEON_FP_CRT_SYNC_ALT (1 << 26) +#define RADEON_FP2_GEN_CNTL 0x0288 +# define RADEON_FP2_BLANK_EN (1 << 1) +# define RADEON_FP2_ON (1 << 2) +# define RADEON_FP2_PANEL_FORMAT (1 << 3) +# define RADEON_FP2_DETECT_SENSE (1 << 8) +# define RADEON_FP2_DETECT_INT_POL (1 << 9) +# define R200_FP2_SOURCE_SEL_MASK (3 << 10) +# define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP2_SOURCE_SEL_RMX (2 << 10) +# define R200_FP2_SOURCE_SEL_TRANS_UNIT (3 << 10) +# define RADEON_FP2_SRC_SEL_MASK (3 << 13) +# define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) +# define RADEON_FP2_FP_POL (1 << 16) +# define RADEON_FP2_LP_POL (1 << 17) +# define RADEON_FP2_SCK_POL (1 << 18) +# define RADEON_FP2_LCD_CNTL_MASK (7 << 19) +# define RADEON_FP2_PAD_FLOP_EN (1 << 22) +# define RADEON_FP2_CRC_EN (1 << 23) +# define RADEON_FP2_CRC_READ_EN (1 << 24) +# define RADEON_FP2_DVO_EN (1 << 25) +# define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) +# define R200_FP2_DVO_RATE_SEL_SDR (1 << 27) +# define R300_FP2_DVO_CLOCK_MODE_SINGLE (1 << 28) +# define R300_FP2_DVO_DUAL_CHANNEL_EN (1 << 29) +#define RADEON_FP_H_SYNC_STRT_WID 0x02c4 +#define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 +#define RADEON_FP_HORZ_STRETCH 0x028c +#define RADEON_FP_HORZ2_STRETCH 0x038c +# define RADEON_HORZ_STRETCH_RATIO_MASK 0xffff +# define RADEON_HORZ_STRETCH_RATIO_MAX 4096 +# define RADEON_HORZ_PANEL_SIZE (0x1ff << 16) +# define RADEON_HORZ_PANEL_SHIFT 16 +# define RADEON_HORZ_STRETCH_PIXREP (0 << 25) +# define RADEON_HORZ_STRETCH_BLEND (1 << 26) +# define RADEON_HORZ_STRETCH_ENABLE (1 << 25) +# define RADEON_HORZ_AUTO_RATIO (1 << 27) +# define RADEON_HORZ_FP_LOOP_STRETCH (0x7 << 28) +# define RADEON_HORZ_AUTO_RATIO_INC (1 << 31) +#define RADEON_FP_HORZ_VERT_ACTIVE 0x0278 +#define RADEON_FP_V_SYNC_STRT_WID 0x02c8 +#define RADEON_FP_VERT_STRETCH 0x0290 +#define RADEON_FP_V2_SYNC_STRT_WID 0x03c8 +#define RADEON_FP_VERT2_STRETCH 0x0390 +# define RADEON_VERT_PANEL_SIZE (0xfff << 12) +# define RADEON_VERT_PANEL_SHIFT 12 +# define RADEON_VERT_STRETCH_RATIO_MASK 0xfff +# define RADEON_VERT_STRETCH_RATIO_SHIFT 0 +# define RADEON_VERT_STRETCH_RATIO_MAX 4096 +# define RADEON_VERT_STRETCH_ENABLE (1 << 25) +# define RADEON_VERT_STRETCH_LINEREP (0 << 26) +# define RADEON_VERT_STRETCH_BLEND (1 << 26) +# define RADEON_VERT_AUTO_RATIO_EN (1 << 27) +# define RADEON_VERT_AUTO_RATIO_INC (1 << 31) +# define RADEON_VERT_STRETCH_RESERVED 0x71000000 +#define RS400_FP_2ND_GEN_CNTL 0x0384 +# define RS400_FP_2ND_ON (1 << 0) +# define RS400_FP_2ND_BLANK_EN (1 << 1) +# define RS400_TMDS_2ND_EN (1 << 2) +# define RS400_PANEL_FORMAT_2ND (1 << 3) +# define RS400_FP_2ND_EN_TMDS (1 << 7) +# define RS400_FP_2ND_DETECT_SENSE (1 << 8) +# define RS400_FP_2ND_SOURCE_SEL_MASK (3 << 10) +# define RS400_FP_2ND_SOURCE_SEL_CRTC1 (0 << 10) +# define RS400_FP_2ND_SOURCE_SEL_CRTC2 (1 << 10) +# define RS400_FP_2ND_SOURCE_SEL_RMX (2 << 10) +# define RS400_FP_2ND_DETECT_EN (1 << 12) +# define RS400_HPD_2ND_SEL (1 << 13) +#define RS400_FP2_2_GEN_CNTL 0x0388 +# define RS400_FP2_2_BLANK_EN (1 << 1) +# define RS400_FP2_2_ON (1 << 2) +# define RS400_FP2_2_PANEL_FORMAT (1 << 3) +# define RS400_FP2_2_DETECT_SENSE (1 << 8) +# define RS400_FP2_2_SOURCE_SEL_MASK (3 << 10) +# define RS400_FP2_2_SOURCE_SEL_CRTC1 (0 << 10) +# define RS400_FP2_2_SOURCE_SEL_CRTC2 (1 << 10) +# define RS400_FP2_2_SOURCE_SEL_RMX (2 << 10) +# define RS400_FP2_2_DVO2_EN (1 << 25) +#define RS400_TMDS2_CNTL 0x0394 +#define RS400_TMDS2_TRANSMITTER_CNTL 0x03a4 +# define RS400_TMDS2_PLLEN (1 << 0) +# define RS400_TMDS2_PLLRST (1 << 1) + +#define RADEON_GEN_INT_CNTL 0x0040 +# define RADEON_CRTC_VBLANK_MASK (1 << 0) +# define RADEON_FP_DETECT_MASK (1 << 4) +# define RADEON_CRTC2_VBLANK_MASK (1 << 9) +# define RADEON_FP2_DETECT_MASK (1 << 10) +# define RADEON_GUI_IDLE_MASK (1 << 19) +# define RADEON_SW_INT_ENABLE (1 << 25) +#define RADEON_GEN_INT_STATUS 0x0044 +# define AVIVO_DISPLAY_INT_STATUS (1 << 0) +# define RADEON_CRTC_VBLANK_STAT (1 << 0) +# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) +# define RADEON_FP_DETECT_STAT (1 << 4) +# define RADEON_FP_DETECT_STAT_ACK (1 << 4) +# define RADEON_CRTC2_VBLANK_STAT (1 << 9) +# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) +# define RADEON_FP2_DETECT_STAT (1 << 10) +# define RADEON_FP2_DETECT_STAT_ACK (1 << 10) +# define RADEON_GUI_IDLE_STAT (1 << 19) +# define RADEON_GUI_IDLE_STAT_ACK (1 << 19) +# define RADEON_SW_INT_FIRE (1 << 26) +# define RADEON_SW_INT_TEST (1 << 25) +# define RADEON_SW_INT_TEST_ACK (1 << 25) +#define RADEON_GENENB 0x03c3 /* VGA */ +#define RADEON_GENFC_RD 0x03ca /* VGA */ +#define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */ +#define RADEON_GENMO_RD 0x03cc /* VGA */ +#define RADEON_GENMO_WT 0x03c2 /* VGA */ +#define RADEON_GENS0 0x03c2 /* VGA */ +#define RADEON_GENS1 0x03da /* VGA, 0x03ba */ +#define RADEON_GPIO_MONID 0x0068 /* DDC interface via I2C */ /* DDC3 */ +#define RADEON_GPIO_MONIDB 0x006c +#define RADEON_GPIO_CRT2_DDC 0x006c +#define RADEON_GPIO_DVI_DDC 0x0064 /* DDC2 */ +#define RADEON_GPIO_VGA_DDC 0x0060 /* DDC1 */ +# define RADEON_GPIO_A_0 (1 << 0) +# define RADEON_GPIO_A_1 (1 << 1) +# define RADEON_GPIO_Y_0 (1 << 8) +# define RADEON_GPIO_Y_1 (1 << 9) +# define RADEON_GPIO_Y_SHIFT_0 8 +# define RADEON_GPIO_Y_SHIFT_1 9 +# define RADEON_GPIO_EN_0 (1 << 16) +# define RADEON_GPIO_EN_1 (1 << 17) +# define RADEON_GPIO_MASK_0 (1 << 24) /*??*/ +# define RADEON_GPIO_MASK_1 (1 << 25) /*??*/ +#define RADEON_GRPH8_DATA 0x03cf /* VGA */ +#define RADEON_GRPH8_IDX 0x03ce /* VGA */ +#define RADEON_GUI_SCRATCH_REG0 0x15e0 +#define RADEON_GUI_SCRATCH_REG1 0x15e4 +#define RADEON_GUI_SCRATCH_REG2 0x15e8 +#define RADEON_GUI_SCRATCH_REG3 0x15ec +#define RADEON_GUI_SCRATCH_REG4 0x15f0 +#define RADEON_GUI_SCRATCH_REG5 0x15f4 + +#define RADEON_HEADER 0x0f0e /* PCI */ +#define RADEON_HOST_DATA0 0x17c0 +#define RADEON_HOST_DATA1 0x17c4 +#define RADEON_HOST_DATA2 0x17c8 +#define RADEON_HOST_DATA3 0x17cc +#define RADEON_HOST_DATA4 0x17d0 +#define RADEON_HOST_DATA5 0x17d4 +#define RADEON_HOST_DATA6 0x17d8 +#define RADEON_HOST_DATA7 0x17dc +#define RADEON_HOST_DATA_LAST 0x17e0 +#define RADEON_HOST_PATH_CNTL 0x0130 +# define RADEON_HP_LIN_RD_CACHE_DIS (1 << 24) +# define RADEON_HDP_READ_BUFFER_INVALIDATE (1 << 27) +# define RADEON_HDP_SOFT_RESET (1 << 26) +# define RADEON_HDP_APER_CNTL (1 << 23) +#define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ +# define RADEON_HTOT_CNTL_VGA_EN (1 << 28) +#define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ + + /* Multimedia I2C bus */ +#define RADEON_I2C_CNTL_0 0x0090 +# define RADEON_I2C_DONE (1 << 0) +# define RADEON_I2C_NACK (1 << 1) +# define RADEON_I2C_HALT (1 << 2) +# define RADEON_I2C_SOFT_RST (1 << 5) +# define RADEON_I2C_DRIVE_EN (1 << 6) +# define RADEON_I2C_DRIVE_SEL (1 << 7) +# define RADEON_I2C_START (1 << 8) +# define RADEON_I2C_STOP (1 << 9) +# define RADEON_I2C_RECEIVE (1 << 10) +# define RADEON_I2C_ABORT (1 << 11) +# define RADEON_I2C_GO (1 << 12) +# define RADEON_I2C_PRESCALE_SHIFT 16 +#define RADEON_I2C_CNTL_1 0x0094 +# define RADEON_I2C_DATA_COUNT_SHIFT 0 +# define RADEON_I2C_ADDR_COUNT_SHIFT 4 +# define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT 8 +# define RADEON_I2C_SEL (1 << 16) +# define RADEON_I2C_EN (1 << 17) +# define RADEON_I2C_TIME_LIMIT_SHIFT 24 +#define RADEON_I2C_DATA 0x0098 + +#define RADEON_DVI_I2C_CNTL_0 0x02e0 +# define R200_DVI_I2C_PIN_SEL(x) ((x) << 3) +# define R200_SEL_DDC1 0 /* depends on asic */ +# define R200_SEL_DDC2 1 /* depends on asic */ +# define R200_SEL_DDC3 2 /* depends on asic */ +# define RADEON_SW_WANTS_TO_USE_DVI_I2C (1 << 13) +# define RADEON_SW_CAN_USE_DVI_I2C (1 << 13) +# define RADEON_SW_DONE_USING_DVI_I2C (1 << 14) +# define RADEON_HW_NEEDS_DVI_I2C (1 << 14) +# define RADEON_ABORT_HW_DVI_I2C (1 << 15) +# define RADEON_HW_USING_DVI_I2C (1 << 15) +#define RADEON_DVI_I2C_CNTL_1 0x02e4 +#define RADEON_DVI_I2C_DATA 0x02e8 + +#define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ +#define RADEON_INTERRUPT_PIN 0x0f3d /* PCI */ +#define RADEON_IO_BASE 0x0f14 /* PCI */ + +#define RADEON_LATENCY 0x0f0d /* PCI */ +#define RADEON_LEAD_BRES_DEC 0x1608 +#define RADEON_LEAD_BRES_LNTH 0x161c +#define RADEON_LEAD_BRES_LNTH_SUB 0x1624 +#define RADEON_LVDS_GEN_CNTL 0x02d0 +# define RADEON_LVDS_ON (1 << 0) +# define RADEON_LVDS_DISPLAY_DIS (1 << 1) +# define RADEON_LVDS_PANEL_TYPE (1 << 2) +# define RADEON_LVDS_PANEL_FORMAT (1 << 3) +# define RADEON_LVDS_NO_FM (0 << 4) +# define RADEON_LVDS_2_GREY (1 << 4) +# define RADEON_LVDS_4_GREY (2 << 4) +# define RADEON_LVDS_RST_FM (1 << 6) +# define RADEON_LVDS_EN (1 << 7) +# define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 +# define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) +# define RADEON_LVDS_BL_MOD_EN (1 << 16) +# define RADEON_LVDS_BL_CLK_SEL (1 << 17) +# define RADEON_LVDS_DIGON (1 << 18) +# define RADEON_LVDS_BLON (1 << 19) +# define RADEON_LVDS_FP_POL_LOW (1 << 20) +# define RADEON_LVDS_LP_POL_LOW (1 << 21) +# define RADEON_LVDS_DTM_POL_LOW (1 << 22) +# define RADEON_LVDS_SEL_CRTC2 (1 << 23) +# define RADEON_LVDS_FPDI_EN (1 << 27) +# define RADEON_LVDS_HSYNC_DELAY_SHIFT 28 +#define RADEON_LVDS_PLL_CNTL 0x02d4 +# define RADEON_HSYNC_DELAY_SHIFT 28 +# define RADEON_HSYNC_DELAY_MASK (0xf << 28) +# define RADEON_LVDS_PLL_EN (1 << 16) +# define RADEON_LVDS_PLL_RESET (1 << 17) +# define R300_LVDS_SRC_SEL_MASK (3 << 18) +# define R300_LVDS_SRC_SEL_CRTC1 (0 << 18) +# define R300_LVDS_SRC_SEL_CRTC2 (1 << 18) +# define R300_LVDS_SRC_SEL_RMX (2 << 18) +#define RADEON_LVDS_SS_GEN_CNTL 0x02ec +# define RADEON_LVDS_PWRSEQ_DELAY1_SHIFT 16 +# define RADEON_LVDS_PWRSEQ_DELAY2_SHIFT 20 + +#define RADEON_MAX_LATENCY 0x0f3f /* PCI */ +#define RADEON_DISPLAY_BASE_ADDR 0x23c +#define RADEON_DISPLAY2_BASE_ADDR 0x33c +#define RADEON_OV0_BASE_ADDR 0x43c +#define RADEON_NB_TOM 0x15c +#define R300_MC_INIT_MISC_LAT_TIMER 0x180 +# define R300_MC_DISP0R_INIT_LAT_SHIFT 8 +# define R300_MC_DISP0R_INIT_LAT_MASK 0xf +# define R300_MC_DISP1R_INIT_LAT_SHIFT 12 +# define R300_MC_DISP1R_INIT_LAT_MASK 0xf +#define RADEON_MCLK_CNTL 0x0012 /* PLL */ +# define RADEON_MCLKA_SRC_SEL_MASK 0x7 +# define RADEON_FORCEON_MCLKA (1 << 16) +# define RADEON_FORCEON_MCLKB (1 << 17) +# define RADEON_FORCEON_YCLKA (1 << 18) +# define RADEON_FORCEON_YCLKB (1 << 19) +# define RADEON_FORCEON_MC (1 << 20) +# define RADEON_FORCEON_AIC (1 << 21) +# define R300_DISABLE_MC_MCLKA (1 << 21) +# define R300_DISABLE_MC_MCLKB (1 << 21) +#define RADEON_MCLK_MISC 0x001f /* PLL */ +# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1 << 12) +# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13) +# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) +# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) + +#define RADEON_GPIOPAD_MASK 0x0198 +#define RADEON_GPIOPAD_A 0x019c +#define RADEON_GPIOPAD_EN 0x01a0 +#define RADEON_GPIOPAD_Y 0x01a4 +#define RADEON_MDGPIO_MASK 0x01a8 +#define RADEON_MDGPIO_A 0x01ac +#define RADEON_MDGPIO_EN 0x01b0 +#define RADEON_MDGPIO_Y 0x01b4 + +#define RADEON_MEM_ADDR_CONFIG 0x0148 +#define RADEON_MEM_BASE 0x0f10 /* PCI */ +#define RADEON_MEM_CNTL 0x0140 +# define RADEON_MEM_NUM_CHANNELS_MASK 0x01 +# define RADEON_MEM_USE_B_CH_ONLY (1 << 1) +# define RV100_HALF_MODE (1 << 3) +# define R300_MEM_NUM_CHANNELS_MASK 0x03 +# define R300_MEM_USE_CD_CH_ONLY (1 << 2) +#define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ +#define RADEON_MEM_INIT_LAT_TIMER 0x0154 +#define RADEON_MEM_INTF_CNTL 0x014c +#define RADEON_MEM_SDRAM_MODE_REG 0x0158 +# define RADEON_SDRAM_MODE_MASK 0xffff0000 +# define RADEON_B3MEM_RESET_MASK 0x6fffffff +# define RADEON_MEM_CFG_TYPE_DDR (1 << 30) +#define RADEON_MEM_STR_CNTL 0x0150 +# define RADEON_MEM_PWRUP_COMPL_A (1 << 0) +# define RADEON_MEM_PWRUP_COMPL_B (1 << 1) +# define R300_MEM_PWRUP_COMPL_C (1 << 2) +# define R300_MEM_PWRUP_COMPL_D (1 << 3) +# define RADEON_MEM_PWRUP_COMPLETE 0x03 +# define R300_MEM_PWRUP_COMPLETE 0x0f +#define RADEON_MC_STATUS 0x0150 +# define RADEON_MC_IDLE (1 << 2) +# define R300_MC_IDLE (1 << 4) +#define RADEON_MEM_VGA_RP_SEL 0x003c +#define RADEON_MEM_VGA_WP_SEL 0x0038 +#define RADEON_MIN_GRANT 0x0f3e /* PCI */ +#define RADEON_MM_DATA 0x0004 +#define RADEON_MM_INDEX 0x0000 +# define RADEON_MM_APER (1 << 31) +#define RADEON_MPLL_CNTL 0x000e /* PLL */ +#define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */ +#define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */ +#define RADEON_SEPROM_CNTL1 0x01c0 +# define RADEON_SCK_PRESCALE_SHIFT 24 +# define RADEON_SCK_PRESCALE_MASK (0xff << 24) +#define R300_MC_IND_INDEX 0x01f8 +# define R300_MC_IND_ADDR_MASK 0x3f +# define R300_MC_IND_WR_EN (1 << 8) +#define R300_MC_IND_DATA 0x01fc +#define R300_MC_READ_CNTL_AB 0x017c +# define R300_MEM_RBS_POSITION_A_MASK 0x03 +#define R300_MC_READ_CNTL_CD_mcind 0x24 +# define R300_MEM_RBS_POSITION_C_MASK 0x03 + +#define RADEON_N_VIF_COUNT 0x0248 + +#define RADEON_OV0_AUTO_FLIP_CNTL 0x0470 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_NUM 0x00000007 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_REPEAT_FIELD 0x00000008 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 0x00000010 +# define RADEON_OV0_AUTO_FLIP_CNTL_IGNORE_REPEAT_FIELD 0x00000020 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE 0x00000040 +# define RADEON_OV0_AUTO_FLIP_CNTL_VID_PORT_SELECT 0x00000300 +# define RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN 0x00010000 +# define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN 0x00040000 +# define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN 0x00080000 +# define RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE 0x00800000 + +#define RADEON_OV0_COLOUR_CNTL 0x04E0 +#define RADEON_OV0_DEINTERLACE_PATTERN 0x0474 +#define RADEON_OV0_EXCLUSIVE_HORZ 0x0408 +# define RADEON_EXCL_HORZ_START_MASK 0x000000ff +# define RADEON_EXCL_HORZ_END_MASK 0x0000ff00 +# define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 +# define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 +#define RADEON_OV0_EXCLUSIVE_VERT 0x040C +# define RADEON_EXCL_VERT_START_MASK 0x000003ff +# define RADEON_EXCL_VERT_END_MASK 0x03ff0000 +#define RADEON_OV0_FILTER_CNTL 0x04A0 +# define RADEON_FILTER_PROGRAMMABLE_COEF 0x0 +# define RADEON_FILTER_HC_COEF_HORZ_Y 0x1 +# define RADEON_FILTER_HC_COEF_HORZ_UV 0x2 +# define RADEON_FILTER_HC_COEF_VERT_Y 0x4 +# define RADEON_FILTER_HC_COEF_VERT_UV 0x8 +# define RADEON_FILTER_HARDCODED_COEF 0xf +# define RADEON_FILTER_COEF_MASK 0xf + +#define RADEON_OV0_FOUR_TAP_COEF_0 0x04B0 +#define RADEON_OV0_FOUR_TAP_COEF_1 0x04B4 +#define RADEON_OV0_FOUR_TAP_COEF_2 0x04B8 +#define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC +#define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0 +#define RADEON_OV0_FLAG_CNTL 0x04DC +#define RADEON_OV0_GAMMA_000_00F 0x0d40 +#define RADEON_OV0_GAMMA_010_01F 0x0d44 +#define RADEON_OV0_GAMMA_020_03F 0x0d48 +#define RADEON_OV0_GAMMA_040_07F 0x0d4c +#define RADEON_OV0_GAMMA_080_0BF 0x0e00 +#define RADEON_OV0_GAMMA_0C0_0FF 0x0e04 +#define RADEON_OV0_GAMMA_100_13F 0x0e08 +#define RADEON_OV0_GAMMA_140_17F 0x0e0c +#define RADEON_OV0_GAMMA_180_1BF 0x0e10 +#define RADEON_OV0_GAMMA_1C0_1FF 0x0e14 +#define RADEON_OV0_GAMMA_200_23F 0x0e18 +#define RADEON_OV0_GAMMA_240_27F 0x0e1c +#define RADEON_OV0_GAMMA_280_2BF 0x0e20 +#define RADEON_OV0_GAMMA_2C0_2FF 0x0e24 +#define RADEON_OV0_GAMMA_300_33F 0x0e28 +#define RADEON_OV0_GAMMA_340_37F 0x0e2c +#define RADEON_OV0_GAMMA_380_3BF 0x0d50 +#define RADEON_OV0_GAMMA_3C0_3FF 0x0d54 +#define RADEON_OV0_GRAPHICS_KEY_CLR_LOW 0x04EC +#define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0 +#define RADEON_OV0_H_INC 0x0480 +#define RADEON_OV0_KEY_CNTL 0x04F4 +# define RADEON_VIDEO_KEY_FN_MASK 0x00000003L +# define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L +# define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L +# define RADEON_VIDEO_KEY_FN_EQ 0x00000002L +# define RADEON_VIDEO_KEY_FN_NE 0x00000003L +# define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L +# define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L +# define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L +# define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L +# define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L +# define RADEON_CMP_MIX_MASK 0x00000100L +# define RADEON_CMP_MIX_OR 0x00000000L +# define RADEON_CMP_MIX_AND 0x00000100L +#define RADEON_OV0_LIN_TRANS_A 0x0d20 +#define RADEON_OV0_LIN_TRANS_B 0x0d24 +#define RADEON_OV0_LIN_TRANS_C 0x0d28 +#define RADEON_OV0_LIN_TRANS_D 0x0d2c +#define RADEON_OV0_LIN_TRANS_E 0x0d30 +#define RADEON_OV0_LIN_TRANS_F 0x0d34 +#define RADEON_OV0_P1_BLANK_LINES_AT_TOP 0x0430 +# define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL +# define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L +#define RADEON_OV0_P1_H_ACCUM_INIT 0x0488 +#define RADEON_OV0_P1_V_ACCUM_INIT 0x0428 +# define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L +# define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L +#define RADEON_OV0_P1_X_START_END 0x0494 +#define RADEON_OV0_P2_X_START_END 0x0498 +#define RADEON_OV0_P23_BLANK_LINES_AT_TOP 0x0434 +# define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL +# define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L +#define RADEON_OV0_P23_H_ACCUM_INIT 0x048C +#define RADEON_OV0_P23_V_ACCUM_INIT 0x042C +#define RADEON_OV0_P3_X_START_END 0x049C +#define RADEON_OV0_REG_LOAD_CNTL 0x0410 +# define RADEON_REG_LD_CTL_LOCK 0x00000001L +# define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L +# define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L +# define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L +# define RADEON_REG_LD_CTL_FLIP_READBACK 0x00000010L +#define RADEON_OV0_SCALE_CNTL 0x0420 +# define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L +# define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L +# define RADEON_SCALER_SIGNED_UV 0x00000010L +# define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L +# define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L +# define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L +# define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L +# define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L +# define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L +# define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L +# define RADEON_SCALER_SOURCE_15BPP 0x00000300L +# define RADEON_SCALER_SOURCE_16BPP 0x00000400L +# define RADEON_SCALER_SOURCE_32BPP 0x00000600L +# define RADEON_SCALER_SOURCE_YUV9 0x00000900L +# define RADEON_SCALER_SOURCE_YUV12 0x00000A00L +# define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L +# define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L +# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L +# define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L +# define RADEON_SCALER_CRTC_SEL 0x00004000L +# define RADEON_SCALER_SMART_SWITCH 0x00008000L +# define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L +# define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L +# define RADEON_SCALER_DIS_LIMIT 0x08000000L +# define RADEON_SCALER_LIN_TRANS_BYPASS 0x10000000L +# define RADEON_SCALER_INT_EMU 0x20000000L +# define RADEON_SCALER_ENABLE 0x40000000L +# define RADEON_SCALER_SOFT_RESET 0x80000000L +#define RADEON_OV0_STEP_BY 0x0484 +#define RADEON_OV0_TEST 0x04F8 +#define RADEON_OV0_V_INC 0x0424 +#define RADEON_OV0_VID_BUF_PITCH0_VALUE 0x0460 +#define RADEON_OV0_VID_BUF_PITCH1_VALUE 0x0464 +#define RADEON_OV0_VID_BUF0_BASE_ADRS 0x0440 +# define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L +#define RADEON_OV0_VID_BUF1_BASE_ADRS 0x0444 +# define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L +#define RADEON_OV0_VID_BUF2_BASE_ADRS 0x0448 +# define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L +#define RADEON_OV0_VID_BUF3_BASE_ADRS 0x044C +#define RADEON_OV0_VID_BUF4_BASE_ADRS 0x0450 +#define RADEON_OV0_VID_BUF5_BASE_ADRS 0x0454 +#define RADEON_OV0_VIDEO_KEY_CLR_HIGH 0x04E8 +#define RADEON_OV0_VIDEO_KEY_CLR_LOW 0x04E4 +#define RADEON_OV0_Y_X_START 0x0400 +#define RADEON_OV0_Y_X_END 0x0404 +#define RADEON_OV1_Y_X_START 0x0600 +#define RADEON_OV1_Y_X_END 0x0604 +#define RADEON_OVR_CLR 0x0230 +#define RADEON_OVR_WID_LEFT_RIGHT 0x0234 +#define RADEON_OVR_WID_TOP_BOTTOM 0x0238 +#define RADEON_OVR2_CLR 0x0330 +#define RADEON_OVR2_WID_LEFT_RIGHT 0x0334 +#define RADEON_OVR2_WID_TOP_BOTTOM 0x0338 + +/* first capture unit */ + +#define RADEON_CAP0_BUF0_OFFSET 0x0920 +#define RADEON_CAP0_BUF1_OFFSET 0x0924 +#define RADEON_CAP0_BUF0_EVEN_OFFSET 0x0928 +#define RADEON_CAP0_BUF1_EVEN_OFFSET 0x092C + +#define RADEON_CAP0_BUF_PITCH 0x0930 +#define RADEON_CAP0_V_WINDOW 0x0934 +#define RADEON_CAP0_H_WINDOW 0x0938 +#define RADEON_CAP0_VBI0_OFFSET 0x093C +#define RADEON_CAP0_VBI1_OFFSET 0x0940 +#define RADEON_CAP0_VBI_V_WINDOW 0x0944 +#define RADEON_CAP0_VBI_H_WINDOW 0x0948 +#define RADEON_CAP0_PORT_MODE_CNTL 0x094C +#define RADEON_CAP0_TRIG_CNTL 0x0950 +#define RADEON_CAP0_DEBUG 0x0954 +#define RADEON_CAP0_CONFIG 0x0958 +# define RADEON_CAP0_CONFIG_CONTINUOS 0x00000001 +# define RADEON_CAP0_CONFIG_START_FIELD_EVEN 0x00000002 +# define RADEON_CAP0_CONFIG_START_BUF_GET 0x00000004 +# define RADEON_CAP0_CONFIG_START_BUF_SET 0x00000008 +# define RADEON_CAP0_CONFIG_BUF_TYPE_ALT 0x00000010 +# define RADEON_CAP0_CONFIG_BUF_TYPE_FRAME 0x00000020 +# define RADEON_CAP0_CONFIG_ONESHOT_MODE_FRAME 0x00000040 +# define RADEON_CAP0_CONFIG_BUF_MODE_DOUBLE 0x00000080 +# define RADEON_CAP0_CONFIG_BUF_MODE_TRIPLE 0x00000100 +# define RADEON_CAP0_CONFIG_MIRROR_EN 0x00000200 +# define RADEON_CAP0_CONFIG_ONESHOT_MIRROR_EN 0x00000400 +# define RADEON_CAP0_CONFIG_VIDEO_SIGNED_UV 0x00000800 +# define RADEON_CAP0_CONFIG_ANC_DECODE_EN 0x00001000 +# define RADEON_CAP0_CONFIG_VBI_EN 0x00002000 +# define RADEON_CAP0_CONFIG_SOFT_PULL_DOWN_EN 0x00004000 +# define RADEON_CAP0_CONFIG_VIP_EXTEND_FLAG_EN 0x00008000 +# define RADEON_CAP0_CONFIG_FAKE_FIELD_EN 0x00010000 +# define RADEON_CAP0_CONFIG_ODD_ONE_MORE_LINE 0x00020000 +# define RADEON_CAP0_CONFIG_EVEN_ONE_MORE_LINE 0x00040000 +# define RADEON_CAP0_CONFIG_HORZ_DIVIDE_2 0x00080000 +# define RADEON_CAP0_CONFIG_HORZ_DIVIDE_4 0x00100000 +# define RADEON_CAP0_CONFIG_VERT_DIVIDE_2 0x00200000 +# define RADEON_CAP0_CONFIG_VERT_DIVIDE_4 0x00400000 +# define RADEON_CAP0_CONFIG_FORMAT_BROOKTREE 0x00000000 +# define RADEON_CAP0_CONFIG_FORMAT_CCIR656 0x00800000 +# define RADEON_CAP0_CONFIG_FORMAT_ZV 0x01000000 +# define RADEON_CAP0_CONFIG_FORMAT_VIP 0x01800000 +# define RADEON_CAP0_CONFIG_FORMAT_TRANSPORT 0x02000000 +# define RADEON_CAP0_CONFIG_HORZ_DECIMATOR 0x04000000 +# define RADEON_CAP0_CONFIG_VIDEO_IN_YVYU422 0x00000000 +# define RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422 0x20000000 +# define RADEON_CAP0_CONFIG_VBI_DIVIDE_2 0x40000000 +# define RADEON_CAP0_CONFIG_VBI_DIVIDE_4 0x80000000 +#define RADEON_CAP0_ANC_ODD_OFFSET 0x095C +#define RADEON_CAP0_ANC_EVEN_OFFSET 0x0960 +#define RADEON_CAP0_ANC_H_WINDOW 0x0964 +#define RADEON_CAP0_VIDEO_SYNC_TEST 0x0968 +#define RADEON_CAP0_ONESHOT_BUF_OFFSET 0x096C +#define RADEON_CAP0_BUF_STATUS 0x0970 +/* #define RADEON_CAP0_DWNSC_XRATIO 0x0978 */ +/* #define RADEON_CAP0_XSHARPNESS 0x097C */ +#define RADEON_CAP0_VBI2_OFFSET 0x0980 +#define RADEON_CAP0_VBI3_OFFSET 0x0984 +#define RADEON_CAP0_ANC2_OFFSET 0x0988 +#define RADEON_CAP0_ANC3_OFFSET 0x098C +#define RADEON_VID_BUFFER_CONTROL 0x0900 + +/* second capture unit */ + +#define RADEON_CAP1_BUF0_OFFSET 0x0990 +#define RADEON_CAP1_BUF1_OFFSET 0x0994 +#define RADEON_CAP1_BUF0_EVEN_OFFSET 0x0998 +#define RADEON_CAP1_BUF1_EVEN_OFFSET 0x099C + +#define RADEON_CAP1_BUF_PITCH 0x09A0 +#define RADEON_CAP1_V_WINDOW 0x09A4 +#define RADEON_CAP1_H_WINDOW 0x09A8 +#define RADEON_CAP1_VBI_ODD_OFFSET 0x09AC +#define RADEON_CAP1_VBI_EVEN_OFFSET 0x09B0 +#define RADEON_CAP1_VBI_V_WINDOW 0x09B4 +#define RADEON_CAP1_VBI_H_WINDOW 0x09B8 +#define RADEON_CAP1_PORT_MODE_CNTL 0x09BC +#define RADEON_CAP1_TRIG_CNTL 0x09C0 +#define RADEON_CAP1_DEBUG 0x09C4 +#define RADEON_CAP1_CONFIG 0x09C8 +#define RADEON_CAP1_ANC_ODD_OFFSET 0x09CC +#define RADEON_CAP1_ANC_EVEN_OFFSET 0x09D0 +#define RADEON_CAP1_ANC_H_WINDOW 0x09D4 +#define RADEON_CAP1_VIDEO_SYNC_TEST 0x09D8 +#define RADEON_CAP1_ONESHOT_BUF_OFFSET 0x09DC +#define RADEON_CAP1_BUF_STATUS 0x09E0 +#define RADEON_CAP1_DWNSC_XRATIO 0x09E8 +#define RADEON_CAP1_XSHARPNESS 0x09EC + +/* misc multimedia registers */ + +#define RADEON_IDCT_RUNS 0x1F80 +#define RADEON_IDCT_LEVELS 0x1F84 +#define RADEON_IDCT_CONTROL 0x1FBC +#define RADEON_IDCT_AUTH_CONTROL 0x1F88 +#define RADEON_IDCT_AUTH 0x1F8C + +#define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ +# define RADEON_P2PLL_RESET (1 << 0) +# define RADEON_P2PLL_SLEEP (1 << 1) +# define RADEON_P2PLL_PVG_MASK (7 << 11) +# define RADEON_P2PLL_PVG_SHIFT 11 +# define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16) +# define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) +# define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) +#define RADEON_P2PLL_DIV_0 0x002c +# define RADEON_P2PLL_FB0_DIV_MASK 0x07ff +# define RADEON_P2PLL_POST0_DIV_MASK 0x00070000 +#define RADEON_P2PLL_REF_DIV 0x002B /* PLL */ +# define RADEON_P2PLL_REF_DIV_MASK 0x03ff +# define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ +# define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ +# define R300_PPLL_REF_DIV_ACC_MASK (0x3ff << 18) +# define R300_PPLL_REF_DIV_ACC_SHIFT 18 +#define RADEON_PALETTE_DATA 0x00b4 +#define RADEON_PALETTE_30_DATA 0x00b8 +#define RADEON_PALETTE_INDEX 0x00b0 +#define RADEON_PCI_GART_PAGE 0x017c +#define RADEON_PIXCLKS_CNTL 0x002d +# define RADEON_PIX2CLK_SRC_SEL_MASK 0x03 +# define RADEON_PIX2CLK_SRC_SEL_CPUCLK 0x00 +# define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01 +# define RADEON_PIX2CLK_SRC_SEL_BYTECLK 0x02 +# define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03 +# define RADEON_PIX2CLK_ALWAYS_ONb (1<<6) +# define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7) +# define RADEON_PIXCLK_TV_SRC_SEL (1 << 8) +# define RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb (1 << 9) +# define R300_DVOCLK_ALWAYS_ONb (1 << 10) +# define RADEON_PIXCLK_BLEND_ALWAYS_ONb (1 << 11) +# define RADEON_PIXCLK_GV_ALWAYS_ONb (1 << 12) +# define RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb (1 << 13) +# define R300_PIXCLK_DVO_ALWAYS_ONb (1 << 13) +# define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) +# define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15) +# define R300_PIXCLK_TRANS_ALWAYS_ONb (1 << 16) +# define R300_PIXCLK_TVO_ALWAYS_ONb (1 << 17) +# define R300_P2G2CLK_ALWAYS_ONb (1 << 18) +# define R300_P2G2CLK_DAC_ALWAYS_ONb (1 << 19) +# define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23) +#define RADEON_PLANE_3D_MASK_C 0x1d44 +#define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ +# define RADEON_PLL_MASK_READ_B (1 << 9) +#define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ +#define RADEON_PMI_DATA 0x0f63 /* PCI */ +#define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ +#define RADEON_PMI_PMC_REG 0x0f5e /* PCI */ +#define RADEON_PMI_PMCSR_REG 0x0f60 /* PCI */ +#define RADEON_PMI_REGISTER 0x0f5c /* PCI */ +#define RADEON_PPLL_CNTL 0x0002 /* PLL */ +# define RADEON_PPLL_RESET (1 << 0) +# define RADEON_PPLL_SLEEP (1 << 1) +# define RADEON_PPLL_PVG_MASK (7 << 11) +# define RADEON_PPLL_PVG_SHIFT 11 +# define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16) +# define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) +# define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18) +#define RADEON_PPLL_DIV_0 0x0004 /* PLL */ +#define RADEON_PPLL_DIV_1 0x0005 /* PLL */ +#define RADEON_PPLL_DIV_2 0x0006 /* PLL */ +#define RADEON_PPLL_DIV_3 0x0007 /* PLL */ +# define RADEON_PPLL_FB3_DIV_MASK 0x07ff +# define RADEON_PPLL_POST3_DIV_MASK 0x00070000 +#define RADEON_PPLL_REF_DIV 0x0003 /* PLL */ +# define RADEON_PPLL_REF_DIV_MASK 0x03ff +# define RADEON_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ +# define RADEON_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ +#define RADEON_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */ + +#define RADEON_RBBM_GUICNTL 0x172c +# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) +# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) +# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) +# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) +#define RADEON_RBBM_SOFT_RESET 0x00f0 +# define RADEON_SOFT_RESET_CP (1 << 0) +# define RADEON_SOFT_RESET_HI (1 << 1) +# define RADEON_SOFT_RESET_SE (1 << 2) +# define RADEON_SOFT_RESET_RE (1 << 3) +# define RADEON_SOFT_RESET_PP (1 << 4) +# define RADEON_SOFT_RESET_E2 (1 << 5) +# define RADEON_SOFT_RESET_RB (1 << 6) +# define RADEON_SOFT_RESET_HDP (1 << 7) +#define RADEON_RBBM_STATUS 0x0e40 +# define RADEON_RBBM_FIFOCNT_MASK 0x007f +# define RADEON_RBBM_ACTIVE (1 << 31) +#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c +# define RADEON_RB2D_DC_FLUSH (3 << 0) +# define RADEON_RB2D_DC_FREE (3 << 2) +# define RADEON_RB2D_DC_FLUSH_ALL 0xf +# define RADEON_RB2D_DC_BUSY (1 << 31) +#define RADEON_RB2D_DSTCACHE_MODE 0x3428 +#define RADEON_DSTCACHE_CTLSTAT 0x1714 + +#define RADEON_RB3D_ZCACHE_MODE 0x3250 +#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 +# define RADEON_RB3D_ZC_FLUSH_ALL 0x5 +#define RADEON_RB3D_DSTCACHE_MODE 0x3258 +# define RADEON_RB3D_DC_CACHE_ENABLE (0) +# define RADEON_RB3D_DC_2D_CACHE_DISABLE (1) +# define RADEON_RB3D_DC_3D_CACHE_DISABLE (2) +# define RADEON_RB3D_DC_CACHE_DISABLE (3) +# define RADEON_RB3D_DC_2D_CACHE_LINESIZE_128 (1 << 2) +# define RADEON_RB3D_DC_3D_CACHE_LINESIZE_128 (2 << 2) +# define RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH (1 << 8) +# define RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH (2 << 8) +# define R200_RB3D_DC_2D_CACHE_AUTOFREE (1 << 10) +# define R200_RB3D_DC_3D_CACHE_AUTOFREE (2 << 10) +# define RADEON_RB3D_DC_FORCE_RMW (1 << 16) +# define RADEON_RB3D_DC_DISABLE_RI_FILL (1 << 24) +# define RADEON_RB3D_DC_DISABLE_RI_READ (1 << 25) + +#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325C +# define RADEON_RB3D_DC_FLUSH (3 << 0) +# define RADEON_RB3D_DC_FREE (3 << 2) +# define RADEON_RB3D_DC_FLUSH_ALL 0xf +# define RADEON_RB3D_DC_BUSY (1 << 31) + +#define RADEON_REG_BASE 0x0f18 /* PCI */ +#define RADEON_REGPROG_INF 0x0f09 /* PCI */ +#define RADEON_REVISION_ID 0x0f08 /* PCI */ + +#define RADEON_SC_BOTTOM 0x164c +#define RADEON_SC_BOTTOM_RIGHT 0x16f0 +#define RADEON_SC_BOTTOM_RIGHT_C 0x1c8c +#define RADEON_SC_LEFT 0x1640 +#define RADEON_SC_RIGHT 0x1644 +#define RADEON_SC_TOP 0x1648 +#define RADEON_SC_TOP_LEFT 0x16ec +#define RADEON_SC_TOP_LEFT_C 0x1c88 +# define RADEON_SC_SIGN_MASK_LO 0x8000 +# define RADEON_SC_SIGN_MASK_HI 0x80000000 +#define RADEON_M_SPLL_REF_FB_DIV 0x000a /* PLL */ +# define RADEON_M_SPLL_REF_DIV_SHIFT 0 +# define RADEON_M_SPLL_REF_DIV_MASK 0xff +# define RADEON_MPLL_FB_DIV_SHIFT 8 +# define RADEON_MPLL_FB_DIV_MASK 0xff +# define RADEON_SPLL_FB_DIV_SHIFT 16 +# define RADEON_SPLL_FB_DIV_MASK 0xff +#define RADEON_SPLL_CNTL 0x000c /* PLL */ +# define RADEON_SPLL_SLEEP (1 << 0) +# define RADEON_SPLL_RESET (1 << 1) +# define RADEON_SPLL_PCP_MASK 0x7 +# define RADEON_SPLL_PCP_SHIFT 8 +# define RADEON_SPLL_PVG_MASK 0x7 +# define RADEON_SPLL_PVG_SHIFT 11 +# define RADEON_SPLL_PDC_MASK 0x3 +# define RADEON_SPLL_PDC_SHIFT 14 +#define RADEON_SCLK_CNTL 0x000d /* PLL */ +# define RADEON_SCLK_SRC_SEL_MASK 0x0007 +# define RADEON_DYN_STOP_LAT_MASK 0x00007ff8 +# define RADEON_CP_MAX_DYN_STOP_LAT 0x0008 +# define RADEON_SCLK_FORCEON_MASK 0xffff8000 +# define RADEON_SCLK_FORCE_DISP2 (1<<15) +# define RADEON_SCLK_FORCE_CP (1<<16) +# define RADEON_SCLK_FORCE_HDP (1<<17) +# define RADEON_SCLK_FORCE_DISP1 (1<<18) +# define RADEON_SCLK_FORCE_TOP (1<<19) +# define RADEON_SCLK_FORCE_E2 (1<<20) +# define RADEON_SCLK_FORCE_SE (1<<21) +# define RADEON_SCLK_FORCE_IDCT (1<<22) +# define RADEON_SCLK_FORCE_VIP (1<<23) +# define RADEON_SCLK_FORCE_RE (1<<24) +# define RADEON_SCLK_FORCE_PB (1<<25) +# define RADEON_SCLK_FORCE_TAM (1<<26) +# define RADEON_SCLK_FORCE_TDM (1<<27) +# define RADEON_SCLK_FORCE_RB (1<<28) +# define RADEON_SCLK_FORCE_TV_SCLK (1<<29) +# define RADEON_SCLK_FORCE_SUBPIC (1<<30) +# define RADEON_SCLK_FORCE_OV0 (1<<31) +# define R300_SCLK_FORCE_VAP (1<<21) +# define R300_SCLK_FORCE_SR (1<<25) +# define R300_SCLK_FORCE_PX (1<<26) +# define R300_SCLK_FORCE_TX (1<<27) +# define R300_SCLK_FORCE_US (1<<28) +# define R300_SCLK_FORCE_SU (1<<30) +#define R300_SCLK_CNTL2 0x1e /* PLL */ +# define R300_SCLK_TCL_MAX_DYN_STOP_LAT (1<<10) +# define R300_SCLK_GA_MAX_DYN_STOP_LAT (1<<11) +# define R300_SCLK_CBA_MAX_DYN_STOP_LAT (1<<12) +# define R300_SCLK_FORCE_TCL (1<<13) +# define R300_SCLK_FORCE_CBA (1<<14) +# define R300_SCLK_FORCE_GA (1<<15) +#define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */ +# define RADEON_SCLK_MORE_MAX_DYN_STOP_LAT 0x0007 +# define RADEON_SCLK_MORE_FORCEON 0x0700 +#define RADEON_SDRAM_MODE_REG 0x0158 +#define RADEON_SEQ8_DATA 0x03c5 /* VGA */ +#define RADEON_SEQ8_IDX 0x03c4 /* VGA */ +#define RADEON_SNAPSHOT_F_COUNT 0x0244 +#define RADEON_SNAPSHOT_VH_COUNTS 0x0240 +#define RADEON_SNAPSHOT_VIF_COUNT 0x024c +#define RADEON_SRC_OFFSET 0x15ac +#define RADEON_SRC_PITCH 0x15b0 +#define RADEON_SRC_PITCH_OFFSET 0x1428 +#define RADEON_SRC_SC_BOTTOM 0x165c +#define RADEON_SRC_SC_BOTTOM_RIGHT 0x16f4 +#define RADEON_SRC_SC_RIGHT 0x1654 +#define RADEON_SRC_X 0x1414 +#define RADEON_SRC_X_Y 0x1590 +#define RADEON_SRC_Y 0x1418 +#define RADEON_SRC_Y_X 0x1434 +#define RADEON_STATUS 0x0f06 /* PCI */ +#define RADEON_SUBPIC_CNTL 0x0540 /* ? */ +#define RADEON_SUB_CLASS 0x0f0a /* PCI */ +#define RADEON_SURFACE_CNTL 0x0b00 +# define RADEON_SURF_TRANSLATION_DIS (1 << 8) +# define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20) +# define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21) +# define RADEON_NONSURF_AP1_SWP_16BPP (1 << 22) +# define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23) +#define RADEON_SURFACE0_INFO 0x0b0c +# define RADEON_SURF_TILE_COLOR_MACRO (0 << 16) +# define RADEON_SURF_TILE_COLOR_BOTH (1 << 16) +# define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16) +# define R200_SURF_TILE_NONE (0 << 16) +# define R200_SURF_TILE_COLOR_MACRO (1 << 16) +# define R200_SURF_TILE_COLOR_MICRO (2 << 16) +# define R200_SURF_TILE_COLOR_BOTH (3 << 16) +# define R200_SURF_TILE_DEPTH_32BPP (4 << 16) +# define R200_SURF_TILE_DEPTH_16BPP (5 << 16) +# define R300_SURF_TILE_NONE (0 << 16) +# define R300_SURF_TILE_COLOR_MACRO (1 << 16) +# define R300_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_AP0_SWP_16BPP (1 << 20) +# define RADEON_SURF_AP0_SWP_32BPP (1 << 21) +# define RADEON_SURF_AP1_SWP_16BPP (1 << 22) +# define RADEON_SURF_AP1_SWP_32BPP (1 << 23) +#define RADEON_SURFACE0_LOWER_BOUND 0x0b04 +#define RADEON_SURFACE0_UPPER_BOUND 0x0b08 +#define RADEON_SURFACE1_INFO 0x0b1c +#define RADEON_SURFACE1_LOWER_BOUND 0x0b14 +#define RADEON_SURFACE1_UPPER_BOUND 0x0b18 +#define RADEON_SURFACE2_INFO 0x0b2c +#define RADEON_SURFACE2_LOWER_BOUND 0x0b24 +#define RADEON_SURFACE2_UPPER_BOUND 0x0b28 +#define RADEON_SURFACE3_INFO 0x0b3c +#define RADEON_SURFACE3_LOWER_BOUND 0x0b34 +#define RADEON_SURFACE3_UPPER_BOUND 0x0b38 +#define RADEON_SURFACE4_INFO 0x0b4c +#define RADEON_SURFACE4_LOWER_BOUND 0x0b44 +#define RADEON_SURFACE4_UPPER_BOUND 0x0b48 +#define RADEON_SURFACE5_INFO 0x0b5c +#define RADEON_SURFACE5_LOWER_BOUND 0x0b54 +#define RADEON_SURFACE5_UPPER_BOUND 0x0b58 +#define RADEON_SURFACE6_INFO 0x0b6c +#define RADEON_SURFACE6_LOWER_BOUND 0x0b64 +#define RADEON_SURFACE6_UPPER_BOUND 0x0b68 +#define RADEON_SURFACE7_INFO 0x0b7c +#define RADEON_SURFACE7_LOWER_BOUND 0x0b74 +#define RADEON_SURFACE7_UPPER_BOUND 0x0b78 +#define RADEON_SW_SEMAPHORE 0x013c + +#define RADEON_TEST_DEBUG_CNTL 0x0120 +#define RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001 + +#define RADEON_TEST_DEBUG_MUX 0x0124 +#define RADEON_TEST_DEBUG_OUT 0x012c +#define RADEON_TMDS_PLL_CNTL 0x02a8 +#define RADEON_TMDS_TRANSMITTER_CNTL 0x02a4 +# define RADEON_TMDS_TRANSMITTER_PLLEN 1 +# define RADEON_TMDS_TRANSMITTER_PLLRST 2 +#define RADEON_TRAIL_BRES_DEC 0x1614 +#define RADEON_TRAIL_BRES_ERR 0x160c +#define RADEON_TRAIL_BRES_INC 0x1610 +#define RADEON_TRAIL_X 0x1618 +#define RADEON_TRAIL_X_SUB 0x1620 + +#define RADEON_VCLK_ECP_CNTL 0x0008 /* PLL */ +# define RADEON_VCLK_SRC_SEL_MASK 0x03 +# define RADEON_VCLK_SRC_SEL_CPUCLK 0x00 +# define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01 +# define RADEON_VCLK_SRC_SEL_BYTECLK 0x02 +# define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03 +# define RADEON_PIXCLK_ALWAYS_ONb (1<<6) +# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7) +# define R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF (1<<23) + +#define RADEON_VENDOR_ID 0x0f00 /* PCI */ +#define RADEON_VGA_DDA_CONFIG 0x02e8 +#define RADEON_VGA_DDA_ON_OFF 0x02ec +#define RADEON_VID_BUFFER_CONTROL 0x0900 +#define RADEON_VIDEOMUX_CNTL 0x0190 + +/* VIP bus */ +#define RADEON_VIPH_CH0_DATA 0x0c00 +#define RADEON_VIPH_CH1_DATA 0x0c04 +#define RADEON_VIPH_CH2_DATA 0x0c08 +#define RADEON_VIPH_CH3_DATA 0x0c0c +#define RADEON_VIPH_CH0_ADDR 0x0c10 +#define RADEON_VIPH_CH1_ADDR 0x0c14 +#define RADEON_VIPH_CH2_ADDR 0x0c18 +#define RADEON_VIPH_CH3_ADDR 0x0c1c +#define RADEON_VIPH_CH0_SBCNT 0x0c20 +#define RADEON_VIPH_CH1_SBCNT 0x0c24 +#define RADEON_VIPH_CH2_SBCNT 0x0c28 +#define RADEON_VIPH_CH3_SBCNT 0x0c2c +#define RADEON_VIPH_CH0_ABCNT 0x0c30 +#define RADEON_VIPH_CH1_ABCNT 0x0c34 +#define RADEON_VIPH_CH2_ABCNT 0x0c38 +#define RADEON_VIPH_CH3_ABCNT 0x0c3c +#define RADEON_VIPH_CONTROL 0x0c40 +# define RADEON_VIP_BUSY 0 +# define RADEON_VIP_IDLE 1 +# define RADEON_VIP_RESET 2 +# define RADEON_VIPH_EN (1 << 21) +#define RADEON_VIPH_DV_LAT 0x0c44 +#define RADEON_VIPH_BM_CHUNK 0x0c48 +#define RADEON_VIPH_DV_INT 0x0c4c +#define RADEON_VIPH_TIMEOUT_STAT 0x0c50 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 + +#define RADEON_VIPH_REG_DATA 0x0084 +#define RADEON_VIPH_REG_ADDR 0x0080 + + +#define RADEON_WAIT_UNTIL 0x1720 +# define RADEON_WAIT_CRTC_PFLIP (1 << 0) +# define RADEON_WAIT_RE_CRTC_VLINE (1 << 1) +# define RADEON_WAIT_FE_CRTC_VLINE (1 << 2) +# define RADEON_WAIT_CRTC_VLINE (1 << 3) +# define RADEON_WAIT_DMA_VID_IDLE (1 << 8) +# define RADEON_WAIT_DMA_GUI_IDLE (1 << 9) +# define RADEON_WAIT_CMDFIFO (1 << 10) /* wait for CMDFIFO_ENTRIES */ +# define RADEON_WAIT_OV0_FLIP (1 << 11) +# define RADEON_WAIT_AGP_FLUSH (1 << 13) +# define RADEON_WAIT_2D_IDLE (1 << 14) +# define RADEON_WAIT_3D_IDLE (1 << 15) +# define RADEON_WAIT_2D_IDLECLEAN (1 << 16) +# define RADEON_WAIT_3D_IDLECLEAN (1 << 17) +# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) +# define RADEON_CMDFIFO_ENTRIES_SHIFT 10 +# define RADEON_CMDFIFO_ENTRIES_MASK 0x7f +# define RADEON_WAIT_VAP_IDLE (1 << 28) +# define RADEON_WAIT_BOTH_CRTC_PFLIP (1 << 30) +# define RADEON_ENG_DISPLAY_SELECT_CRTC0 (0 << 31) +# define RADEON_ENG_DISPLAY_SELECT_CRTC1 (1 << 31) + +#define RADEON_X_MPLL_REF_FB_DIV 0x000a /* PLL */ +#define RADEON_XCLK_CNTL 0x000d /* PLL */ +#define RADEON_XDLL_CNTL 0x000c /* PLL */ +#define RADEON_XPLL_CNTL 0x000b /* PLL */ + + + + /* Registers for 3D/TCL */ +#define RADEON_PP_BORDER_COLOR_0 0x1d40 +#define RADEON_PP_BORDER_COLOR_1 0x1d44 +#define RADEON_PP_BORDER_COLOR_2 0x1d48 +#define RADEON_PP_CNTL 0x1c38 +# define RADEON_STIPPLE_ENABLE (1 << 0) +# define RADEON_SCISSOR_ENABLE (1 << 1) +# define RADEON_PATTERN_ENABLE (1 << 2) +# define RADEON_SHADOW_ENABLE (1 << 3) +# define RADEON_TEX_ENABLE_MASK (0xf << 4) +# define RADEON_TEX_0_ENABLE (1 << 4) +# define RADEON_TEX_1_ENABLE (1 << 5) +# define RADEON_TEX_2_ENABLE (1 << 6) +# define RADEON_TEX_3_ENABLE (1 << 7) +# define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12) +# define RADEON_TEX_BLEND_0_ENABLE (1 << 12) +# define RADEON_TEX_BLEND_1_ENABLE (1 << 13) +# define RADEON_TEX_BLEND_2_ENABLE (1 << 14) +# define RADEON_TEX_BLEND_3_ENABLE (1 << 15) +# define RADEON_PLANAR_YUV_ENABLE (1 << 20) +# define RADEON_SPECULAR_ENABLE (1 << 21) +# define RADEON_FOG_ENABLE (1 << 22) +# define RADEON_ALPHA_TEST_ENABLE (1 << 23) +# define RADEON_ANTI_ALIAS_NONE (0 << 24) +# define RADEON_ANTI_ALIAS_LINE (1 << 24) +# define RADEON_ANTI_ALIAS_POLY (2 << 24) +# define RADEON_ANTI_ALIAS_LINE_POLY (3 << 24) +# define RADEON_BUMP_MAP_ENABLE (1 << 26) +# define RADEON_BUMPED_MAP_T0 (0 << 27) +# define RADEON_BUMPED_MAP_T1 (1 << 27) +# define RADEON_BUMPED_MAP_T2 (2 << 27) +# define RADEON_TEX_3D_ENABLE_0 (1 << 29) +# define RADEON_TEX_3D_ENABLE_1 (1 << 30) +# define RADEON_MC_ENABLE (1 << 31) +#define RADEON_PP_FOG_COLOR 0x1c18 +# define RADEON_FOG_COLOR_MASK 0x00ffffff +# define RADEON_FOG_VERTEX (0 << 24) +# define RADEON_FOG_TABLE (1 << 24) +# define RADEON_FOG_USE_DEPTH (0 << 25) +# define RADEON_FOG_USE_DIFFUSE_ALPHA (2 << 25) +# define RADEON_FOG_USE_SPEC_ALPHA (3 << 25) +#define RADEON_PP_LUM_MATRIX 0x1d00 +#define RADEON_PP_MISC 0x1c14 +# define RADEON_REF_ALPHA_MASK 0x000000ff +# define RADEON_ALPHA_TEST_FAIL (0 << 8) +# define RADEON_ALPHA_TEST_LESS (1 << 8) +# define RADEON_ALPHA_TEST_LEQUAL (2 << 8) +# define RADEON_ALPHA_TEST_EQUAL (3 << 8) +# define RADEON_ALPHA_TEST_GEQUAL (4 << 8) +# define RADEON_ALPHA_TEST_GREATER (5 << 8) +# define RADEON_ALPHA_TEST_NEQUAL (6 << 8) +# define RADEON_ALPHA_TEST_PASS (7 << 8) +# define RADEON_ALPHA_TEST_OP_MASK (7 << 8) +# define RADEON_CHROMA_FUNC_FAIL (0 << 16) +# define RADEON_CHROMA_FUNC_PASS (1 << 16) +# define RADEON_CHROMA_FUNC_NEQUAL (2 << 16) +# define RADEON_CHROMA_FUNC_EQUAL (3 << 16) +# define RADEON_CHROMA_KEY_NEAREST (0 << 18) +# define RADEON_CHROMA_KEY_ZERO (1 << 18) +# define RADEON_SHADOW_ID_AUTO_INC (1 << 20) +# define RADEON_SHADOW_FUNC_EQUAL (0 << 21) +# define RADEON_SHADOW_FUNC_NEQUAL (1 << 21) +# define RADEON_SHADOW_PASS_1 (0 << 22) +# define RADEON_SHADOW_PASS_2 (1 << 22) +# define RADEON_RIGHT_HAND_CUBE_D3D (0 << 24) +# define RADEON_RIGHT_HAND_CUBE_OGL (1 << 24) +#define RADEON_PP_ROT_MATRIX_0 0x1d58 +#define RADEON_PP_ROT_MATRIX_1 0x1d5c +#define RADEON_PP_TXFILTER_0 0x1c54 +#define RADEON_PP_TXFILTER_1 0x1c6c +#define RADEON_PP_TXFILTER_2 0x1c84 +# define RADEON_MAG_FILTER_NEAREST (0 << 0) +# define RADEON_MAG_FILTER_LINEAR (1 << 0) +# define RADEON_MAG_FILTER_MASK (1 << 0) +# define RADEON_MIN_FILTER_NEAREST (0 << 1) +# define RADEON_MIN_FILTER_LINEAR (1 << 1) +# define RADEON_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +# define RADEON_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +# define RADEON_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +# define RADEON_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +# define RADEON_MIN_FILTER_ANISO_NEAREST (8 << 1) +# define RADEON_MIN_FILTER_ANISO_LINEAR (9 << 1) +# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +# define RADEON_MIN_FILTER_MASK (15 << 1) +# define RADEON_MAX_ANISO_1_TO_1 (0 << 5) +# define RADEON_MAX_ANISO_2_TO_1 (1 << 5) +# define RADEON_MAX_ANISO_4_TO_1 (2 << 5) +# define RADEON_MAX_ANISO_8_TO_1 (3 << 5) +# define RADEON_MAX_ANISO_16_TO_1 (4 << 5) +# define RADEON_MAX_ANISO_MASK (7 << 5) +# define RADEON_LOD_BIAS_MASK (0xff << 8) +# define RADEON_LOD_BIAS_SHIFT 8 +# define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16) +# define RADEON_MAX_MIP_LEVEL_SHIFT 16 +# define RADEON_YUV_TO_RGB (1 << 20) +# define RADEON_YUV_TEMPERATURE_COOL (0 << 21) +# define RADEON_YUV_TEMPERATURE_HOT (1 << 21) +# define RADEON_YUV_TEMPERATURE_MASK (1 << 21) +# define RADEON_WRAPEN_S (1 << 22) +# define RADEON_CLAMP_S_WRAP (0 << 23) +# define RADEON_CLAMP_S_MIRROR (1 << 23) +# define RADEON_CLAMP_S_CLAMP_LAST (2 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +# define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define RADEON_CLAMP_S_CLAMP_GL (6 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +# define RADEON_CLAMP_S_MASK (7 << 23) +# define RADEON_WRAPEN_T (1 << 26) +# define RADEON_CLAMP_T_WRAP (0 << 27) +# define RADEON_CLAMP_T_MIRROR (1 << 27) +# define RADEON_CLAMP_T_CLAMP_LAST (2 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +# define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define RADEON_CLAMP_T_CLAMP_GL (6 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +# define RADEON_CLAMP_T_MASK (7 << 27) +# define RADEON_BORDER_MODE_OGL (0 << 31) +# define RADEON_BORDER_MODE_D3D (1 << 31) +#define RADEON_PP_TXFORMAT_0 0x1c58 +#define RADEON_PP_TXFORMAT_1 0x1c70 +#define RADEON_PP_TXFORMAT_2 0x1c88 +# define RADEON_TXFORMAT_I8 (0 << 0) +# define RADEON_TXFORMAT_AI88 (1 << 0) +# define RADEON_TXFORMAT_RGB332 (2 << 0) +# define RADEON_TXFORMAT_ARGB1555 (3 << 0) +# define RADEON_TXFORMAT_RGB565 (4 << 0) +# define RADEON_TXFORMAT_ARGB4444 (5 << 0) +# define RADEON_TXFORMAT_ARGB8888 (6 << 0) +# define RADEON_TXFORMAT_RGBA8888 (7 << 0) +# define RADEON_TXFORMAT_Y8 (8 << 0) +# define RADEON_TXFORMAT_VYUY422 (10 << 0) +# define RADEON_TXFORMAT_YVYU422 (11 << 0) +# define RADEON_TXFORMAT_DXT1 (12 << 0) +# define RADEON_TXFORMAT_DXT23 (14 << 0) +# define RADEON_TXFORMAT_DXT45 (15 << 0) +# define RADEON_TXFORMAT_SHADOW16 (16 << 0) +# define RADEON_TXFORMAT_SHADOW32 (17 << 0) +# define RADEON_TXFORMAT_DUDV88 (18 << 0) +# define RADEON_TXFORMAT_LDUDV655 (19 << 0) +# define RADEON_TXFORMAT_LDUDUV8888 (20 << 0) +# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) +# define RADEON_TXFORMAT_FORMAT_SHIFT 0 +# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) +# define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define RADEON_TXFORMAT_NON_POWER2 (1 << 7) +# define RADEON_TXFORMAT_WIDTH_MASK (15 << 8) +# define RADEON_TXFORMAT_WIDTH_SHIFT 8 +# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12) +# define RADEON_TXFORMAT_HEIGHT_SHIFT 12 +# define RADEON_TXFORMAT_F5_WIDTH_MASK (15 << 16) +# define RADEON_TXFORMAT_F5_WIDTH_SHIFT 16 +# define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +# define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20 +# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) +# define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) +# define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) +# define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26) +# define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31) +#define RADEON_PP_CUBIC_FACES_0 0x1d24 +#define RADEON_PP_CUBIC_FACES_1 0x1d28 +#define RADEON_PP_CUBIC_FACES_2 0x1d2c +# define RADEON_FACE_WIDTH_1_SHIFT 0 +# define RADEON_FACE_HEIGHT_1_SHIFT 4 +# define RADEON_FACE_WIDTH_1_MASK (0xf << 0) +# define RADEON_FACE_HEIGHT_1_MASK (0xf << 4) +# define RADEON_FACE_WIDTH_2_SHIFT 8 +# define RADEON_FACE_HEIGHT_2_SHIFT 12 +# define RADEON_FACE_WIDTH_2_MASK (0xf << 8) +# define RADEON_FACE_HEIGHT_2_MASK (0xf << 12) +# define RADEON_FACE_WIDTH_3_SHIFT 16 +# define RADEON_FACE_HEIGHT_3_SHIFT 20 +# define RADEON_FACE_WIDTH_3_MASK (0xf << 16) +# define RADEON_FACE_HEIGHT_3_MASK (0xf << 20) +# define RADEON_FACE_WIDTH_4_SHIFT 24 +# define RADEON_FACE_HEIGHT_4_SHIFT 28 +# define RADEON_FACE_WIDTH_4_MASK (0xf << 24) +# define RADEON_FACE_HEIGHT_4_MASK (0xf << 28) + +#define RADEON_PP_TXOFFSET_0 0x1c5c +#define RADEON_PP_TXOFFSET_1 0x1c74 +#define RADEON_PP_TXOFFSET_2 0x1c8c +# define RADEON_TXO_ENDIAN_NO_SWAP (0 << 0) +# define RADEON_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define RADEON_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define RADEON_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define RADEON_TXO_MACRO_LINEAR (0 << 2) +# define RADEON_TXO_MACRO_TILE (1 << 2) +# define RADEON_TXO_MICRO_LINEAR (0 << 3) +# define RADEON_TXO_MICRO_TILE_X2 (1 << 3) +# define RADEON_TXO_MICRO_TILE_OPT (2 << 3) +# define RADEON_TXO_OFFSET_MASK 0xffffffe0 +# define RADEON_TXO_OFFSET_SHIFT 5 + +#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ +#define RADEON_PP_CUBIC_OFFSET_T0_1 0x1dd4 +#define RADEON_PP_CUBIC_OFFSET_T0_2 0x1dd8 +#define RADEON_PP_CUBIC_OFFSET_T0_3 0x1ddc +#define RADEON_PP_CUBIC_OFFSET_T0_4 0x1de0 +#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 +#define RADEON_PP_CUBIC_OFFSET_T1_1 0x1e04 +#define RADEON_PP_CUBIC_OFFSET_T1_2 0x1e08 +#define RADEON_PP_CUBIC_OFFSET_T1_3 0x1e0c +#define RADEON_PP_CUBIC_OFFSET_T1_4 0x1e10 +#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 +#define RADEON_PP_CUBIC_OFFSET_T2_1 0x1e18 +#define RADEON_PP_CUBIC_OFFSET_T2_2 0x1e1c +#define RADEON_PP_CUBIC_OFFSET_T2_3 0x1e20 +#define RADEON_PP_CUBIC_OFFSET_T2_4 0x1e24 + +#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ +#define RADEON_PP_TEX_SIZE_1 0x1d0c +#define RADEON_PP_TEX_SIZE_2 0x1d14 +# define RADEON_TEX_USIZE_MASK (0x7ff << 0) +# define RADEON_TEX_USIZE_SHIFT 0 +# define RADEON_TEX_VSIZE_MASK (0x7ff << 16) +# define RADEON_TEX_VSIZE_SHIFT 16 +# define RADEON_SIGNED_RGB_MASK (1 << 30) +# define RADEON_SIGNED_RGB_SHIFT 30 +# define RADEON_SIGNED_ALPHA_MASK (1 << 31) +# define RADEON_SIGNED_ALPHA_SHIFT 31 +#define RADEON_PP_TEX_PITCH_0 0x1d08 /* NPOT */ +#define RADEON_PP_TEX_PITCH_1 0x1d10 /* NPOT */ +#define RADEON_PP_TEX_PITCH_2 0x1d18 /* NPOT */ +/* note: bits 13-5: 32 byte aligned stride of texture map */ + +#define RADEON_PP_TXCBLEND_0 0x1c60 +#define RADEON_PP_TXCBLEND_1 0x1c78 +#define RADEON_PP_TXCBLEND_2 0x1c90 +# define RADEON_COLOR_ARG_A_SHIFT 0 +# define RADEON_COLOR_ARG_A_MASK (0x1f << 0) +# define RADEON_COLOR_ARG_A_ZERO (0 << 0) +# define RADEON_COLOR_ARG_A_CURRENT_COLOR (2 << 0) +# define RADEON_COLOR_ARG_A_CURRENT_ALPHA (3 << 0) +# define RADEON_COLOR_ARG_A_DIFFUSE_COLOR (4 << 0) +# define RADEON_COLOR_ARG_A_DIFFUSE_ALPHA (5 << 0) +# define RADEON_COLOR_ARG_A_SPECULAR_COLOR (6 << 0) +# define RADEON_COLOR_ARG_A_SPECULAR_ALPHA (7 << 0) +# define RADEON_COLOR_ARG_A_TFACTOR_COLOR (8 << 0) +# define RADEON_COLOR_ARG_A_TFACTOR_ALPHA (9 << 0) +# define RADEON_COLOR_ARG_A_T0_COLOR (10 << 0) +# define RADEON_COLOR_ARG_A_T0_ALPHA (11 << 0) +# define RADEON_COLOR_ARG_A_T1_COLOR (12 << 0) +# define RADEON_COLOR_ARG_A_T1_ALPHA (13 << 0) +# define RADEON_COLOR_ARG_A_T2_COLOR (14 << 0) +# define RADEON_COLOR_ARG_A_T2_ALPHA (15 << 0) +# define RADEON_COLOR_ARG_A_T3_COLOR (16 << 0) +# define RADEON_COLOR_ARG_A_T3_ALPHA (17 << 0) +# define RADEON_COLOR_ARG_B_SHIFT 5 +# define RADEON_COLOR_ARG_B_MASK (0x1f << 5) +# define RADEON_COLOR_ARG_B_ZERO (0 << 5) +# define RADEON_COLOR_ARG_B_CURRENT_COLOR (2 << 5) +# define RADEON_COLOR_ARG_B_CURRENT_ALPHA (3 << 5) +# define RADEON_COLOR_ARG_B_DIFFUSE_COLOR (4 << 5) +# define RADEON_COLOR_ARG_B_DIFFUSE_ALPHA (5 << 5) +# define RADEON_COLOR_ARG_B_SPECULAR_COLOR (6 << 5) +# define RADEON_COLOR_ARG_B_SPECULAR_ALPHA (7 << 5) +# define RADEON_COLOR_ARG_B_TFACTOR_COLOR (8 << 5) +# define RADEON_COLOR_ARG_B_TFACTOR_ALPHA (9 << 5) +# define RADEON_COLOR_ARG_B_T0_COLOR (10 << 5) +# define RADEON_COLOR_ARG_B_T0_ALPHA (11 << 5) +# define RADEON_COLOR_ARG_B_T1_COLOR (12 << 5) +# define RADEON_COLOR_ARG_B_T1_ALPHA (13 << 5) +# define RADEON_COLOR_ARG_B_T2_COLOR (14 << 5) +# define RADEON_COLOR_ARG_B_T2_ALPHA (15 << 5) +# define RADEON_COLOR_ARG_B_T3_COLOR (16 << 5) +# define RADEON_COLOR_ARG_B_T3_ALPHA (17 << 5) +# define RADEON_COLOR_ARG_C_SHIFT 10 +# define RADEON_COLOR_ARG_C_MASK (0x1f << 10) +# define RADEON_COLOR_ARG_C_ZERO (0 << 10) +# define RADEON_COLOR_ARG_C_CURRENT_COLOR (2 << 10) +# define RADEON_COLOR_ARG_C_CURRENT_ALPHA (3 << 10) +# define RADEON_COLOR_ARG_C_DIFFUSE_COLOR (4 << 10) +# define RADEON_COLOR_ARG_C_DIFFUSE_ALPHA (5 << 10) +# define RADEON_COLOR_ARG_C_SPECULAR_COLOR (6 << 10) +# define RADEON_COLOR_ARG_C_SPECULAR_ALPHA (7 << 10) +# define RADEON_COLOR_ARG_C_TFACTOR_COLOR (8 << 10) +# define RADEON_COLOR_ARG_C_TFACTOR_ALPHA (9 << 10) +# define RADEON_COLOR_ARG_C_T0_COLOR (10 << 10) +# define RADEON_COLOR_ARG_C_T0_ALPHA (11 << 10) +# define RADEON_COLOR_ARG_C_T1_COLOR (12 << 10) +# define RADEON_COLOR_ARG_C_T1_ALPHA (13 << 10) +# define RADEON_COLOR_ARG_C_T2_COLOR (14 << 10) +# define RADEON_COLOR_ARG_C_T2_ALPHA (15 << 10) +# define RADEON_COLOR_ARG_C_T3_COLOR (16 << 10) +# define RADEON_COLOR_ARG_C_T3_ALPHA (17 << 10) +# define RADEON_COMP_ARG_A (1 << 15) +# define RADEON_COMP_ARG_A_SHIFT 15 +# define RADEON_COMP_ARG_B (1 << 16) +# define RADEON_COMP_ARG_B_SHIFT 16 +# define RADEON_COMP_ARG_C (1 << 17) +# define RADEON_COMP_ARG_C_SHIFT 17 +# define RADEON_BLEND_CTL_MASK (7 << 18) +# define RADEON_BLEND_CTL_ADD (0 << 18) +# define RADEON_BLEND_CTL_SUBTRACT (1 << 18) +# define RADEON_BLEND_CTL_ADDSIGNED (2 << 18) +# define RADEON_BLEND_CTL_BLEND (3 << 18) +# define RADEON_BLEND_CTL_DOT3 (4 << 18) +# define RADEON_SCALE_SHIFT 21 +# define RADEON_SCALE_MASK (3 << 21) +# define RADEON_SCALE_1X (0 << 21) +# define RADEON_SCALE_2X (1 << 21) +# define RADEON_SCALE_4X (2 << 21) +# define RADEON_CLAMP_TX (1 << 23) +# define RADEON_T0_EQ_TCUR (1 << 24) +# define RADEON_T1_EQ_TCUR (1 << 25) +# define RADEON_T2_EQ_TCUR (1 << 26) +# define RADEON_T3_EQ_TCUR (1 << 27) +# define RADEON_COLOR_ARG_MASK 0x1f +# define RADEON_COMP_ARG_SHIFT 15 +#define RADEON_PP_TXABLEND_0 0x1c64 +#define RADEON_PP_TXABLEND_1 0x1c7c +#define RADEON_PP_TXABLEND_2 0x1c94 +# define RADEON_ALPHA_ARG_A_SHIFT 0 +# define RADEON_ALPHA_ARG_A_MASK (0xf << 0) +# define RADEON_ALPHA_ARG_A_ZERO (0 << 0) +# define RADEON_ALPHA_ARG_A_CURRENT_ALPHA (1 << 0) +# define RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA (2 << 0) +# define RADEON_ALPHA_ARG_A_SPECULAR_ALPHA (3 << 0) +# define RADEON_ALPHA_ARG_A_TFACTOR_ALPHA (4 << 0) +# define RADEON_ALPHA_ARG_A_T0_ALPHA (5 << 0) +# define RADEON_ALPHA_ARG_A_T1_ALPHA (6 << 0) +# define RADEON_ALPHA_ARG_A_T2_ALPHA (7 << 0) +# define RADEON_ALPHA_ARG_A_T3_ALPHA (8 << 0) +# define RADEON_ALPHA_ARG_B_SHIFT 4 +# define RADEON_ALPHA_ARG_B_MASK (0xf << 4) +# define RADEON_ALPHA_ARG_B_ZERO (0 << 4) +# define RADEON_ALPHA_ARG_B_CURRENT_ALPHA (1 << 4) +# define RADEON_ALPHA_ARG_B_DIFFUSE_ALPHA (2 << 4) +# define RADEON_ALPHA_ARG_B_SPECULAR_ALPHA (3 << 4) +# define RADEON_ALPHA_ARG_B_TFACTOR_ALPHA (4 << 4) +# define RADEON_ALPHA_ARG_B_T0_ALPHA (5 << 4) +# define RADEON_ALPHA_ARG_B_T1_ALPHA (6 << 4) +# define RADEON_ALPHA_ARG_B_T2_ALPHA (7 << 4) +# define RADEON_ALPHA_ARG_B_T3_ALPHA (8 << 4) +# define RADEON_ALPHA_ARG_C_SHIFT 8 +# define RADEON_ALPHA_ARG_C_MASK (0xf << 8) +# define RADEON_ALPHA_ARG_C_ZERO (0 << 8) +# define RADEON_ALPHA_ARG_C_CURRENT_ALPHA (1 << 8) +# define RADEON_ALPHA_ARG_C_DIFFUSE_ALPHA (2 << 8) +# define RADEON_ALPHA_ARG_C_SPECULAR_ALPHA (3 << 8) +# define RADEON_ALPHA_ARG_C_TFACTOR_ALPHA (4 << 8) +# define RADEON_ALPHA_ARG_C_T0_ALPHA (5 << 8) +# define RADEON_ALPHA_ARG_C_T1_ALPHA (6 << 8) +# define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8) +# define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8) +# define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 9) +# define RADEON_ALPHA_ARG_MASK 0xf + +#define RADEON_PP_TFACTOR_0 0x1c68 +#define RADEON_PP_TFACTOR_1 0x1c80 +#define RADEON_PP_TFACTOR_2 0x1c98 + +#define RADEON_RB3D_BLENDCNTL 0x1c20 +# define RADEON_COMB_FCN_MASK (3 << 12) +# define RADEON_COMB_FCN_ADD_CLAMP (0 << 12) +# define RADEON_COMB_FCN_ADD_NOCLAMP (1 << 12) +# define RADEON_COMB_FCN_SUB_CLAMP (2 << 12) +# define RADEON_COMB_FCN_SUB_NOCLAMP (3 << 12) +# define RADEON_SRC_BLEND_GL_ZERO (32 << 16) +# define RADEON_SRC_BLEND_GL_ONE (33 << 16) +# define RADEON_SRC_BLEND_GL_SRC_COLOR (34 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) +# define RADEON_SRC_BLEND_GL_DST_COLOR (36 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) +# define RADEON_SRC_BLEND_GL_SRC_ALPHA (38 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) +# define RADEON_SRC_BLEND_GL_DST_ALPHA (40 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) +# define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) +# define RADEON_SRC_BLEND_MASK (63 << 16) +# define RADEON_DST_BLEND_GL_ZERO (32 << 24) +# define RADEON_DST_BLEND_GL_ONE (33 << 24) +# define RADEON_DST_BLEND_GL_SRC_COLOR (34 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) +# define RADEON_DST_BLEND_GL_DST_COLOR (36 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) +# define RADEON_DST_BLEND_GL_SRC_ALPHA (38 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) +# define RADEON_DST_BLEND_GL_DST_ALPHA (40 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) +# define RADEON_DST_BLEND_MASK (63 << 24) +#define RADEON_RB3D_CNTL 0x1c3c +# define RADEON_ALPHA_BLEND_ENABLE (1 << 0) +# define RADEON_PLANE_MASK_ENABLE (1 << 1) +# define RADEON_DITHER_ENABLE (1 << 2) +# define RADEON_ROUND_ENABLE (1 << 3) +# define RADEON_SCALE_DITHER_ENABLE (1 << 4) +# define RADEON_DITHER_INIT (1 << 5) +# define RADEON_ROP_ENABLE (1 << 6) +# define RADEON_STENCIL_ENABLE (1 << 7) +# define RADEON_Z_ENABLE (1 << 8) +# define RADEON_DEPTHXY_OFFSET_ENABLE (1 << 9) +# define RADEON_RB3D_COLOR_FORMAT_SHIFT 10 + +# define RADEON_COLOR_FORMAT_ARGB1555 3 +# define RADEON_COLOR_FORMAT_RGB565 4 +# define RADEON_COLOR_FORMAT_ARGB8888 6 +# define RADEON_COLOR_FORMAT_RGB332 7 +# define RADEON_COLOR_FORMAT_Y8 8 +# define RADEON_COLOR_FORMAT_RGB8 9 +# define RADEON_COLOR_FORMAT_YUV422_VYUY 11 +# define RADEON_COLOR_FORMAT_YUV422_YVYU 12 +# define RADEON_COLOR_FORMAT_aYUV444 14 +# define RADEON_COLOR_FORMAT_ARGB4444 15 + +# define RADEON_CLRCMP_FLIP_ENABLE (1 << 14) +#define RADEON_RB3D_COLOROFFSET 0x1c40 +# define RADEON_COLOROFFSET_MASK 0xfffffff0 +#define RADEON_RB3D_COLORPITCH 0x1c48 +# define RADEON_COLORPITCH_MASK 0x000001ff8 +# define RADEON_COLOR_TILE_ENABLE (1 << 16) +# define RADEON_COLOR_MICROTILE_ENABLE (1 << 17) +# define RADEON_COLOR_ENDIAN_NO_SWAP (0 << 18) +# define RADEON_COLOR_ENDIAN_WORD_SWAP (1 << 18) +# define RADEON_COLOR_ENDIAN_DWORD_SWAP (2 << 18) +#define RADEON_RB3D_DEPTHOFFSET 0x1c24 +#define RADEON_RB3D_DEPTHPITCH 0x1c28 +# define RADEON_DEPTHPITCH_MASK 0x00001ff8 +# define RADEON_DEPTH_ENDIAN_NO_SWAP (0 << 18) +# define RADEON_DEPTH_ENDIAN_WORD_SWAP (1 << 18) +# define RADEON_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) +#define RADEON_RB3D_PLANEMASK 0x1d84 +#define RADEON_RB3D_ROPCNTL 0x1d80 +# define RADEON_ROP_MASK (15 << 8) +# define RADEON_ROP_CLEAR (0 << 8) +# define RADEON_ROP_NOR (1 << 8) +# define RADEON_ROP_AND_INVERTED (2 << 8) +# define RADEON_ROP_COPY_INVERTED (3 << 8) +# define RADEON_ROP_AND_REVERSE (4 << 8) +# define RADEON_ROP_INVERT (5 << 8) +# define RADEON_ROP_XOR (6 << 8) +# define RADEON_ROP_NAND (7 << 8) +# define RADEON_ROP_AND (8 << 8) +# define RADEON_ROP_EQUIV (9 << 8) +# define RADEON_ROP_NOOP (10 << 8) +# define RADEON_ROP_OR_INVERTED (11 << 8) +# define RADEON_ROP_COPY (12 << 8) +# define RADEON_ROP_OR_REVERSE (13 << 8) +# define RADEON_ROP_OR (14 << 8) +# define RADEON_ROP_SET (15 << 8) +#define RADEON_RB3D_STENCILREFMASK 0x1d7c +# define RADEON_STENCIL_REF_SHIFT 0 +# define RADEON_STENCIL_REF_MASK (0xff << 0) +# define RADEON_STENCIL_MASK_SHIFT 16 +# define RADEON_STENCIL_VALUE_MASK (0xff << 16) +# define RADEON_STENCIL_WRITEMASK_SHIFT 24 +# define RADEON_STENCIL_WRITE_MASK (0xff << 24) +#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c +# define RADEON_DEPTH_FORMAT_MASK (0xf << 0) +# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0) +# define RADEON_DEPTH_FORMAT_32BIT_INT_Z (4 << 0) +# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0) +# define RADEON_DEPTH_FORMAT_16BIT_FLOAT_W (7 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0) +# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0) +# define RADEON_Z_TEST_NEVER (0 << 4) +# define RADEON_Z_TEST_LESS (1 << 4) +# define RADEON_Z_TEST_LEQUAL (2 << 4) +# define RADEON_Z_TEST_EQUAL (3 << 4) +# define RADEON_Z_TEST_GEQUAL (4 << 4) +# define RADEON_Z_TEST_GREATER (5 << 4) +# define RADEON_Z_TEST_NEQUAL (6 << 4) +# define RADEON_Z_TEST_ALWAYS (7 << 4) +# define RADEON_Z_TEST_MASK (7 << 4) +# define RADEON_STENCIL_TEST_NEVER (0 << 12) +# define RADEON_STENCIL_TEST_LESS (1 << 12) +# define RADEON_STENCIL_TEST_LEQUAL (2 << 12) +# define RADEON_STENCIL_TEST_EQUAL (3 << 12) +# define RADEON_STENCIL_TEST_GEQUAL (4 << 12) +# define RADEON_STENCIL_TEST_GREATER (5 << 12) +# define RADEON_STENCIL_TEST_NEQUAL (6 << 12) +# define RADEON_STENCIL_TEST_ALWAYS (7 << 12) +# define RADEON_STENCIL_TEST_MASK (0x7 << 12) +# define RADEON_STENCIL_FAIL_KEEP (0 << 16) +# define RADEON_STENCIL_FAIL_ZERO (1 << 16) +# define RADEON_STENCIL_FAIL_REPLACE (2 << 16) +# define RADEON_STENCIL_FAIL_INC (3 << 16) +# define RADEON_STENCIL_FAIL_DEC (4 << 16) +# define RADEON_STENCIL_FAIL_INVERT (5 << 16) +# define RADEON_STENCIL_FAIL_MASK (0x7 << 16) +# define RADEON_STENCIL_ZPASS_KEEP (0 << 20) +# define RADEON_STENCIL_ZPASS_ZERO (1 << 20) +# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) +# define RADEON_STENCIL_ZPASS_INC (3 << 20) +# define RADEON_STENCIL_ZPASS_DEC (4 << 20) +# define RADEON_STENCIL_ZPASS_INVERT (5 << 20) +# define RADEON_STENCIL_ZPASS_MASK (0x7 << 20) +# define RADEON_STENCIL_ZFAIL_KEEP (0 << 24) +# define RADEON_STENCIL_ZFAIL_ZERO (1 << 24) +# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) +# define RADEON_STENCIL_ZFAIL_INC (3 << 24) +# define RADEON_STENCIL_ZFAIL_DEC (4 << 24) +# define RADEON_STENCIL_ZFAIL_INVERT (5 << 24) +# define RADEON_STENCIL_ZFAIL_MASK (0x7 << 24) +# define RADEON_Z_COMPRESSION_ENABLE (1 << 28) +# define RADEON_FORCE_Z_DIRTY (1 << 29) +# define RADEON_Z_WRITE_ENABLE (1 << 30) +#define RADEON_RE_LINE_PATTERN 0x1cd0 +# define RADEON_LINE_PATTERN_MASK 0x0000ffff +# define RADEON_LINE_REPEAT_COUNT_SHIFT 16 +# define RADEON_LINE_PATTERN_START_SHIFT 24 +# define RADEON_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28) +# define RADEON_LINE_PATTERN_BIG_BIT_ORDER (1 << 28) +# define RADEON_LINE_PATTERN_AUTO_RESET (1 << 29) +#define RADEON_RE_LINE_STATE 0x1cd4 +# define RADEON_LINE_CURRENT_PTR_SHIFT 0 +# define RADEON_LINE_CURRENT_COUNT_SHIFT 8 +#define RADEON_RE_MISC 0x26c4 +# define RADEON_STIPPLE_COORD_MASK 0x1f +# define RADEON_STIPPLE_X_OFFSET_SHIFT 0 +# define RADEON_STIPPLE_X_OFFSET_MASK (0x1f << 0) +# define RADEON_STIPPLE_Y_OFFSET_SHIFT 8 +# define RADEON_STIPPLE_Y_OFFSET_MASK (0x1f << 8) +# define RADEON_STIPPLE_LITTLE_BIT_ORDER (0 << 16) +# define RADEON_STIPPLE_BIG_BIT_ORDER (1 << 16) +#define RADEON_RE_SOLID_COLOR 0x1c1c +#define RADEON_RE_TOP_LEFT 0x26c0 +# define RADEON_RE_LEFT_SHIFT 0 +# define RADEON_RE_TOP_SHIFT 16 +#define RADEON_RE_WIDTH_HEIGHT 0x1c44 +# define RADEON_RE_WIDTH_SHIFT 0 +# define RADEON_RE_HEIGHT_SHIFT 16 + +#define RADEON_RB3D_ZPASS_DATA 0x3290 +#define RADEON_RB3D_ZPASS_ADDR 0x3294 + +#define RADEON_SE_CNTL 0x1c4c +# define RADEON_FFACE_CULL_CW (0 << 0) +# define RADEON_FFACE_CULL_CCW (1 << 0) +# define RADEON_FFACE_CULL_DIR_MASK (1 << 0) +# define RADEON_BFACE_CULL (0 << 1) +# define RADEON_BFACE_SOLID (3 << 1) +# define RADEON_FFACE_CULL (0 << 3) +# define RADEON_FFACE_SOLID (3 << 3) +# define RADEON_FFACE_CULL_MASK (3 << 3) +# define RADEON_BADVTX_CULL_DISABLE (1 << 5) +# define RADEON_FLAT_SHADE_VTX_0 (0 << 6) +# define RADEON_FLAT_SHADE_VTX_1 (1 << 6) +# define RADEON_FLAT_SHADE_VTX_2 (2 << 6) +# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) +# define RADEON_DIFFUSE_SHADE_SOLID (0 << 8) +# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) +# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) +# define RADEON_DIFFUSE_SHADE_MASK (3 << 8) +# define RADEON_ALPHA_SHADE_SOLID (0 << 10) +# define RADEON_ALPHA_SHADE_FLAT (1 << 10) +# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) +# define RADEON_ALPHA_SHADE_MASK (3 << 10) +# define RADEON_SPECULAR_SHADE_SOLID (0 << 12) +# define RADEON_SPECULAR_SHADE_FLAT (1 << 12) +# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) +# define RADEON_SPECULAR_SHADE_MASK (3 << 12) +# define RADEON_FOG_SHADE_SOLID (0 << 14) +# define RADEON_FOG_SHADE_FLAT (1 << 14) +# define RADEON_FOG_SHADE_GOURAUD (2 << 14) +# define RADEON_FOG_SHADE_MASK (3 << 14) +# define RADEON_ZBIAS_ENABLE_POINT (1 << 16) +# define RADEON_ZBIAS_ENABLE_LINE (1 << 17) +# define RADEON_ZBIAS_ENABLE_TRI (1 << 18) +# define RADEON_WIDELINE_ENABLE (1 << 20) +# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) +# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) +# define RADEON_VTX_PIX_CENTER_D3D (0 << 27) +# define RADEON_VTX_PIX_CENTER_OGL (1 << 27) +# define RADEON_ROUND_MODE_TRUNC (0 << 28) +# define RADEON_ROUND_MODE_ROUND (1 << 28) +# define RADEON_ROUND_MODE_ROUND_EVEN (2 << 28) +# define RADEON_ROUND_MODE_ROUND_ODD (3 << 28) +# define RADEON_ROUND_PREC_16TH_PIX (0 << 30) +# define RADEON_ROUND_PREC_8TH_PIX (1 << 30) +# define RADEON_ROUND_PREC_4TH_PIX (2 << 30) +# define RADEON_ROUND_PREC_HALF_PIX (3 << 30) +#define R200_RE_CNTL 0x1c50 +# define R200_STIPPLE_ENABLE 0x1 +# define R200_SCISSOR_ENABLE 0x2 +# define R200_PATTERN_ENABLE 0x4 +# define R200_PERSPECTIVE_ENABLE 0x8 +# define R200_POINT_SMOOTH 0x20 +# define R200_VTX_STQ0_D3D 0x00010000 +# define R200_VTX_STQ1_D3D 0x00040000 +# define R200_VTX_STQ2_D3D 0x00100000 +# define R200_VTX_STQ3_D3D 0x00400000 +# define R200_VTX_STQ4_D3D 0x01000000 +# define R200_VTX_STQ5_D3D 0x04000000 +#define RADEON_SE_CNTL_STATUS 0x2140 +# define RADEON_VC_NO_SWAP (0 << 0) +# define RADEON_VC_16BIT_SWAP (1 << 0) +# define RADEON_VC_32BIT_SWAP (2 << 0) +# define RADEON_VC_HALF_DWORD_SWAP (3 << 0) +# define RADEON_TCL_BYPASS (1 << 8) +#define RADEON_SE_COORD_FMT 0x1c50 +# define RADEON_VTX_XY_PRE_MULT_1_OVER_W0 (1 << 0) +# define RADEON_VTX_Z_PRE_MULT_1_OVER_W0 (1 << 1) +# define RADEON_VTX_ST0_NONPARAMETRIC (1 << 8) +# define RADEON_VTX_ST1_NONPARAMETRIC (1 << 9) +# define RADEON_VTX_ST2_NONPARAMETRIC (1 << 10) +# define RADEON_VTX_ST3_NONPARAMETRIC (1 << 11) +# define RADEON_VTX_W0_NORMALIZE (1 << 12) +# define RADEON_VTX_W0_IS_NOT_1_OVER_W0 (1 << 16) +# define RADEON_VTX_ST0_PRE_MULT_1_OVER_W0 (1 << 17) +# define RADEON_VTX_ST1_PRE_MULT_1_OVER_W0 (1 << 19) +# define RADEON_VTX_ST2_PRE_MULT_1_OVER_W0 (1 << 21) +# define RADEON_VTX_ST3_PRE_MULT_1_OVER_W0 (1 << 23) +# define RADEON_TEX1_W_ROUTING_USE_W0 (0 << 26) +# define RADEON_TEX1_W_ROUTING_USE_Q1 (1 << 26) +#define RADEON_SE_LINE_WIDTH 0x1db8 +#define RADEON_SE_TCL_LIGHT_MODEL_CTL 0x226c +# define RADEON_LIGHTING_ENABLE (1 << 0) +# define RADEON_LIGHT_IN_MODELSPACE (1 << 1) +# define RADEON_LOCAL_VIEWER (1 << 2) +# define RADEON_NORMALIZE_NORMALS (1 << 3) +# define RADEON_RESCALE_NORMALS (1 << 4) +# define RADEON_SPECULAR_LIGHTS (1 << 5) +# define RADEON_DIFFUSE_SPECULAR_COMBINE (1 << 6) +# define RADEON_LIGHT_ALPHA (1 << 7) +# define RADEON_LOCAL_LIGHT_VEC_GL (1 << 8) +# define RADEON_LIGHT_NO_NORMAL_AMBIENT_ONLY (1 << 9) +# define RADEON_LM_SOURCE_STATE_PREMULT 0 +# define RADEON_LM_SOURCE_STATE_MULT 1 +# define RADEON_LM_SOURCE_VERTEX_DIFFUSE 2 +# define RADEON_LM_SOURCE_VERTEX_SPECULAR 3 +# define RADEON_EMISSIVE_SOURCE_SHIFT 16 +# define RADEON_AMBIENT_SOURCE_SHIFT 18 +# define RADEON_DIFFUSE_SOURCE_SHIFT 20 +# define RADEON_SPECULAR_SOURCE_SHIFT 22 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_RED 0x2220 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN 0x2224 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE 0x2228 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA 0x222c +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_RED 0x2230 +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN 0x2234 +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE 0x2238 +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA 0x223c +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN 0x2214 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE 0x2218 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA 0x221c +#define RADEON_SE_TCL_MATERIAL_SPECULAR_RED 0x2240 +#define RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN 0x2244 +#define RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE 0x2248 +#define RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA 0x224c +#define RADEON_SE_TCL_MATRIX_SELECT_0 0x225c +# define RADEON_MODELVIEW_0_SHIFT 0 +# define RADEON_MODELVIEW_1_SHIFT 4 +# define RADEON_MODELVIEW_2_SHIFT 8 +# define RADEON_MODELVIEW_3_SHIFT 12 +# define RADEON_IT_MODELVIEW_0_SHIFT 16 +# define RADEON_IT_MODELVIEW_1_SHIFT 20 +# define RADEON_IT_MODELVIEW_2_SHIFT 24 +# define RADEON_IT_MODELVIEW_3_SHIFT 28 +#define RADEON_SE_TCL_MATRIX_SELECT_1 0x2260 +# define RADEON_MODELPROJECT_0_SHIFT 0 +# define RADEON_MODELPROJECT_1_SHIFT 4 +# define RADEON_MODELPROJECT_2_SHIFT 8 +# define RADEON_MODELPROJECT_3_SHIFT 12 +# define RADEON_TEXMAT_0_SHIFT 16 +# define RADEON_TEXMAT_1_SHIFT 20 +# define RADEON_TEXMAT_2_SHIFT 24 +# define RADEON_TEXMAT_3_SHIFT 28 + + +#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 +# define RADEON_TCL_VTX_W0 (1 << 0) +# define RADEON_TCL_VTX_FP_DIFFUSE (1 << 1) +# define RADEON_TCL_VTX_FP_ALPHA (1 << 2) +# define RADEON_TCL_VTX_PK_DIFFUSE (1 << 3) +# define RADEON_TCL_VTX_FP_SPEC (1 << 4) +# define RADEON_TCL_VTX_FP_FOG (1 << 5) +# define RADEON_TCL_VTX_PK_SPEC (1 << 6) +# define RADEON_TCL_VTX_ST0 (1 << 7) +# define RADEON_TCL_VTX_ST1 (1 << 8) +# define RADEON_TCL_VTX_Q1 (1 << 9) +# define RADEON_TCL_VTX_ST2 (1 << 10) +# define RADEON_TCL_VTX_Q2 (1 << 11) +# define RADEON_TCL_VTX_ST3 (1 << 12) +# define RADEON_TCL_VTX_Q3 (1 << 13) +# define RADEON_TCL_VTX_Q0 (1 << 14) +# define RADEON_TCL_VTX_WEIGHT_COUNT_SHIFT 15 +# define RADEON_TCL_VTX_NORM0 (1 << 18) +# define RADEON_TCL_VTX_XY1 (1 << 27) +# define RADEON_TCL_VTX_Z1 (1 << 28) +# define RADEON_TCL_VTX_W1 (1 << 29) +# define RADEON_TCL_VTX_NORM1 (1 << 30) +# define RADEON_TCL_VTX_Z0 (1 << 31) + +#define RADEON_SE_TCL_OUTPUT_VTX_SEL 0x2258 +# define RADEON_TCL_COMPUTE_XYZW (1 << 0) +# define RADEON_TCL_COMPUTE_DIFFUSE (1 << 1) +# define RADEON_TCL_COMPUTE_SPECULAR (1 << 2) +# define RADEON_TCL_FORCE_NAN_IF_COLOR_NAN (1 << 3) +# define RADEON_TCL_FORCE_INORDER_PROC (1 << 4) +# define RADEON_TCL_TEX_INPUT_TEX_0 0 +# define RADEON_TCL_TEX_INPUT_TEX_1 1 +# define RADEON_TCL_TEX_INPUT_TEX_2 2 +# define RADEON_TCL_TEX_INPUT_TEX_3 3 +# define RADEON_TCL_TEX_COMPUTED_TEX_0 8 +# define RADEON_TCL_TEX_COMPUTED_TEX_1 9 +# define RADEON_TCL_TEX_COMPUTED_TEX_2 10 +# define RADEON_TCL_TEX_COMPUTED_TEX_3 11 +# define RADEON_TCL_TEX_0_OUTPUT_SHIFT 16 +# define RADEON_TCL_TEX_1_OUTPUT_SHIFT 20 +# define RADEON_TCL_TEX_2_OUTPUT_SHIFT 24 +# define RADEON_TCL_TEX_3_OUTPUT_SHIFT 28 + +#define RADEON_SE_TCL_PER_LIGHT_CTL_0 0x2270 +# define RADEON_LIGHT_0_ENABLE (1 << 0) +# define RADEON_LIGHT_0_ENABLE_AMBIENT (1 << 1) +# define RADEON_LIGHT_0_ENABLE_SPECULAR (1 << 2) +# define RADEON_LIGHT_0_IS_LOCAL (1 << 3) +# define RADEON_LIGHT_0_IS_SPOT (1 << 4) +# define RADEON_LIGHT_0_DUAL_CONE (1 << 5) +# define RADEON_LIGHT_0_ENABLE_RANGE_ATTEN (1 << 6) +# define RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN (1 << 7) +# define RADEON_LIGHT_0_SHIFT 0 +# define RADEON_LIGHT_1_ENABLE (1 << 16) +# define RADEON_LIGHT_1_ENABLE_AMBIENT (1 << 17) +# define RADEON_LIGHT_1_ENABLE_SPECULAR (1 << 18) +# define RADEON_LIGHT_1_IS_LOCAL (1 << 19) +# define RADEON_LIGHT_1_IS_SPOT (1 << 20) +# define RADEON_LIGHT_1_DUAL_CONE (1 << 21) +# define RADEON_LIGHT_1_ENABLE_RANGE_ATTEN (1 << 22) +# define RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN (1 << 23) +# define RADEON_LIGHT_1_SHIFT 16 +#define RADEON_SE_TCL_PER_LIGHT_CTL_1 0x2274 +# define RADEON_LIGHT_2_SHIFT 0 +# define RADEON_LIGHT_3_SHIFT 16 +#define RADEON_SE_TCL_PER_LIGHT_CTL_2 0x2278 +# define RADEON_LIGHT_4_SHIFT 0 +# define RADEON_LIGHT_5_SHIFT 16 +#define RADEON_SE_TCL_PER_LIGHT_CTL_3 0x227c +# define RADEON_LIGHT_6_SHIFT 0 +# define RADEON_LIGHT_7_SHIFT 16 + +#define RADEON_SE_TCL_SHININESS 0x2250 + +#define RADEON_SE_TCL_TEXTURE_PROC_CTL 0x2268 +# define RADEON_TEXGEN_TEXMAT_0_ENABLE (1 << 0) +# define RADEON_TEXGEN_TEXMAT_1_ENABLE (1 << 1) +# define RADEON_TEXGEN_TEXMAT_2_ENABLE (1 << 2) +# define RADEON_TEXGEN_TEXMAT_3_ENABLE (1 << 3) +# define RADEON_TEXMAT_0_ENABLE (1 << 4) +# define RADEON_TEXMAT_1_ENABLE (1 << 5) +# define RADEON_TEXMAT_2_ENABLE (1 << 6) +# define RADEON_TEXMAT_3_ENABLE (1 << 7) +# define RADEON_TEXGEN_INPUT_MASK 0xf +# define RADEON_TEXGEN_INPUT_TEXCOORD_0 0 +# define RADEON_TEXGEN_INPUT_TEXCOORD_1 1 +# define RADEON_TEXGEN_INPUT_TEXCOORD_2 2 +# define RADEON_TEXGEN_INPUT_TEXCOORD_3 3 +# define RADEON_TEXGEN_INPUT_OBJ 4 +# define RADEON_TEXGEN_INPUT_EYE 5 +# define RADEON_TEXGEN_INPUT_EYE_NORMAL 6 +# define RADEON_TEXGEN_INPUT_EYE_REFLECT 7 +# define RADEON_TEXGEN_INPUT_EYE_NORMALIZED 8 +# define RADEON_TEXGEN_0_INPUT_SHIFT 16 +# define RADEON_TEXGEN_1_INPUT_SHIFT 20 +# define RADEON_TEXGEN_2_INPUT_SHIFT 24 +# define RADEON_TEXGEN_3_INPUT_SHIFT 28 + +#define RADEON_SE_TCL_UCP_VERT_BLEND_CTL 0x2264 +# define RADEON_UCP_IN_CLIP_SPACE (1 << 0) +# define RADEON_UCP_IN_MODEL_SPACE (1 << 1) +# define RADEON_UCP_ENABLE_0 (1 << 2) +# define RADEON_UCP_ENABLE_1 (1 << 3) +# define RADEON_UCP_ENABLE_2 (1 << 4) +# define RADEON_UCP_ENABLE_3 (1 << 5) +# define RADEON_UCP_ENABLE_4 (1 << 6) +# define RADEON_UCP_ENABLE_5 (1 << 7) +# define RADEON_TCL_FOG_MASK (3 << 8) +# define RADEON_TCL_FOG_DISABLE (0 << 8) +# define RADEON_TCL_FOG_EXP (1 << 8) +# define RADEON_TCL_FOG_EXP2 (2 << 8) +# define RADEON_TCL_FOG_LINEAR (3 << 8) +# define RADEON_RNG_BASED_FOG (1 << 10) +# define RADEON_LIGHT_TWOSIDE (1 << 11) +# define RADEON_BLEND_OP_COUNT_MASK (7 << 12) +# define RADEON_BLEND_OP_COUNT_SHIFT 12 +# define RADEON_POSITION_BLEND_OP_ENABLE (1 << 16) +# define RADEON_NORMAL_BLEND_OP_ENABLE (1 << 17) +# define RADEON_VERTEX_BLEND_SRC_0_PRIMARY (1 << 18) +# define RADEON_VERTEX_BLEND_SRC_0_SECONDARY (1 << 18) +# define RADEON_VERTEX_BLEND_SRC_1_PRIMARY (1 << 19) +# define RADEON_VERTEX_BLEND_SRC_1_SECONDARY (1 << 19) +# define RADEON_VERTEX_BLEND_SRC_2_PRIMARY (1 << 20) +# define RADEON_VERTEX_BLEND_SRC_2_SECONDARY (1 << 20) +# define RADEON_VERTEX_BLEND_SRC_3_PRIMARY (1 << 21) +# define RADEON_VERTEX_BLEND_SRC_3_SECONDARY (1 << 21) +# define RADEON_VERTEX_BLEND_WGT_MINUS_ONE (1 << 22) +# define RADEON_CULL_FRONT_IS_CW (0 << 28) +# define RADEON_CULL_FRONT_IS_CCW (1 << 28) +# define RADEON_CULL_FRONT (1 << 29) +# define RADEON_CULL_BACK (1 << 30) +# define RADEON_FORCE_W_TO_ONE (1 << 31) + +#define RADEON_SE_VPORT_XSCALE 0x1d98 +#define RADEON_SE_VPORT_XOFFSET 0x1d9c +#define RADEON_SE_VPORT_YSCALE 0x1da0 +#define RADEON_SE_VPORT_YOFFSET 0x1da4 +#define RADEON_SE_VPORT_ZSCALE 0x1da8 +#define RADEON_SE_VPORT_ZOFFSET 0x1dac +#define RADEON_SE_ZBIAS_FACTOR 0x1db0 +#define RADEON_SE_ZBIAS_CONSTANT 0x1db4 + +#define RADEON_SE_VTX_FMT 0x2080 +# define RADEON_SE_VTX_FMT_XY 0x00000000 +# define RADEON_SE_VTX_FMT_W0 0x00000001 +# define RADEON_SE_VTX_FMT_FPCOLOR 0x00000002 +# define RADEON_SE_VTX_FMT_FPALPHA 0x00000004 +# define RADEON_SE_VTX_FMT_PKCOLOR 0x00000008 +# define RADEON_SE_VTX_FMT_FPSPEC 0x00000010 +# define RADEON_SE_VTX_FMT_FPFOG 0x00000020 +# define RADEON_SE_VTX_FMT_PKSPEC 0x00000040 +# define RADEON_SE_VTX_FMT_ST0 0x00000080 +# define RADEON_SE_VTX_FMT_ST1 0x00000100 +# define RADEON_SE_VTX_FMT_Q1 0x00000200 +# define RADEON_SE_VTX_FMT_ST2 0x00000400 +# define RADEON_SE_VTX_FMT_Q2 0x00000800 +# define RADEON_SE_VTX_FMT_ST3 0x00001000 +# define RADEON_SE_VTX_FMT_Q3 0x00002000 +# define RADEON_SE_VTX_FMT_Q0 0x00004000 +# define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK 0x00038000 +# define RADEON_SE_VTX_FMT_N0 0x00040000 +# define RADEON_SE_VTX_FMT_XY1 0x08000000 +# define RADEON_SE_VTX_FMT_Z1 0x10000000 +# define RADEON_SE_VTX_FMT_W1 0x20000000 +# define RADEON_SE_VTX_FMT_N1 0x40000000 +# define RADEON_SE_VTX_FMT_Z 0x80000000 + +#define RADEON_SE_VF_CNTL 0x2084 +# define RADEON_VF_PRIM_TYPE_POINT_LIST 1 +# define RADEON_VF_PRIM_TYPE_LINE_LIST 2 +# define RADEON_VF_PRIM_TYPE_LINE_STRIP 3 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_LIST 4 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_FAN 5 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_STRIP 6 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_FLAG 7 +# define RADEON_VF_PRIM_TYPE_RECTANGLE_LIST 8 +# define RADEON_VF_PRIM_TYPE_POINT_LIST_3 9 +# define RADEON_VF_PRIM_TYPE_LINE_LIST_3 10 +# define RADEON_VF_PRIM_TYPE_SPIRIT_LIST 11 +# define RADEON_VF_PRIM_TYPE_LINE_LOOP 12 +# define RADEON_VF_PRIM_TYPE_QUAD_LIST 13 +# define RADEON_VF_PRIM_TYPE_QUAD_STRIP 14 +# define RADEON_VF_PRIM_TYPE_POLYGON 15 +# define RADEON_VF_PRIM_WALK_STATE (0<<4) +# define RADEON_VF_PRIM_WALK_INDEX (1<<4) +# define RADEON_VF_PRIM_WALK_LIST (2<<4) +# define RADEON_VF_PRIM_WALK_DATA (3<<4) +# define RADEON_VF_COLOR_ORDER_RGBA (1<<6) +# define RADEON_VF_RADEON_MODE (1<<8) +# define RADEON_VF_TCL_OUTPUT_CTL_ENA (1<<9) +# define RADEON_VF_PROG_STREAM_ENA (1<<10) +# define RADEON_VF_INDEX_SIZE_SHIFT 11 +# define RADEON_VF_NUM_VERTICES_SHIFT 16 + +#define RADEON_SE_PORT_DATA0 0x2000 + +#define R200_SE_VAP_CNTL 0x2080 +# define R200_VAP_TCL_ENABLE 0x00000001 +# define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 +# define R200_VAP_FORCE_W_TO_ONE 0x00010000 +# define R200_VAP_D3D_TEX_DEFAULT 0x00020000 +# define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 +# define R200_VAP_VF_MAX_VTX_NUM (9 << 18) +# define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 +#define R200_VF_MAX_VTX_INDX 0x210c +#define R200_VF_MIN_VTX_INDX 0x2110 +#define R200_SE_VTE_CNTL 0x20b0 +# define R200_VPORT_X_SCALE_ENA 0x00000001 +# define R200_VPORT_X_OFFSET_ENA 0x00000002 +# define R200_VPORT_Y_SCALE_ENA 0x00000004 +# define R200_VPORT_Y_OFFSET_ENA 0x00000008 +# define R200_VPORT_Z_SCALE_ENA 0x00000010 +# define R200_VPORT_Z_OFFSET_ENA 0x00000020 +# define R200_VTX_XY_FMT 0x00000100 +# define R200_VTX_Z_FMT 0x00000200 +# define R200_VTX_W0_FMT 0x00000400 +# define R200_VTX_W0_NORMALIZE 0x00000800 +# define R200_VTX_ST_DENORMALIZED 0x00001000 +#define R200_SE_VAP_CNTL_STATUS 0x2140 +# define R200_VC_NO_SWAP (0 << 0) +# define R200_VC_16BIT_SWAP (1 << 0) +# define R200_VC_32BIT_SWAP (2 << 0) +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_5 0x2ca0 +# define R200_MAG_FILTER_NEAREST (0 << 0) +# define R200_MAG_FILTER_LINEAR (1 << 0) +# define R200_MAG_FILTER_MASK (1 << 0) +# define R200_MIN_FILTER_NEAREST (0 << 1) +# define R200_MIN_FILTER_LINEAR (1 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) +# define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +# define R200_MIN_FILTER_MASK (15 << 1) +# define R200_MAX_ANISO_1_TO_1 (0 << 5) +# define R200_MAX_ANISO_2_TO_1 (1 << 5) +# define R200_MAX_ANISO_4_TO_1 (2 << 5) +# define R200_MAX_ANISO_8_TO_1 (3 << 5) +# define R200_MAX_ANISO_16_TO_1 (4 << 5) +# define R200_MAX_ANISO_MASK (7 << 5) +# define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) +# define R200_MAX_MIP_LEVEL_SHIFT 16 +# define R200_YUV_TO_RGB (1 << 20) +# define R200_YUV_TEMPERATURE_COOL (0 << 21) +# define R200_YUV_TEMPERATURE_HOT (1 << 21) +# define R200_YUV_TEMPERATURE_MASK (1 << 21) +# define R200_WRAPEN_S (1 << 22) +# define R200_CLAMP_S_WRAP (0 << 23) +# define R200_CLAMP_S_MIRROR (1 << 23) +# define R200_CLAMP_S_CLAMP_LAST (2 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +# define R200_CLAMP_S_CLAMP_BORDER (4 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define R200_CLAMP_S_CLAMP_GL (6 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +# define R200_CLAMP_S_MASK (7 << 23) +# define R200_WRAPEN_T (1 << 26) +# define R200_CLAMP_T_WRAP (0 << 27) +# define R200_CLAMP_T_MIRROR (1 << 27) +# define R200_CLAMP_T_CLAMP_LAST (2 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +# define R200_CLAMP_T_CLAMP_BORDER (4 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define R200_CLAMP_T_CLAMP_GL (6 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +# define R200_CLAMP_T_MASK (7 << 27) +# define R200_KILL_LT_ZERO (1 << 30) +# define R200_BORDER_MODE_OGL (0 << 31) +# define R200_BORDER_MODE_D3D (1 << 31) +#define R200_PP_TXFORMAT_0 0x2c04 +#define R200_PP_TXFORMAT_1 0x2c24 +#define R200_PP_TXFORMAT_2 0x2c44 +#define R200_PP_TXFORMAT_3 0x2c64 +#define R200_PP_TXFORMAT_4 0x2c84 +#define R200_PP_TXFORMAT_5 0x2ca4 +# define R200_TXFORMAT_I8 (0 << 0) +# define R200_TXFORMAT_AI88 (1 << 0) +# define R200_TXFORMAT_RGB332 (2 << 0) +# define R200_TXFORMAT_ARGB1555 (3 << 0) +# define R200_TXFORMAT_RGB565 (4 << 0) +# define R200_TXFORMAT_ARGB4444 (5 << 0) +# define R200_TXFORMAT_ARGB8888 (6 << 0) +# define R200_TXFORMAT_RGBA8888 (7 << 0) +# define R200_TXFORMAT_Y8 (8 << 0) +# define R200_TXFORMAT_AVYU4444 (9 << 0) +# define R200_TXFORMAT_VYUY422 (10 << 0) +# define R200_TXFORMAT_YVYU422 (11 << 0) +# define R200_TXFORMAT_DXT1 (12 << 0) +# define R200_TXFORMAT_DXT23 (14 << 0) +# define R200_TXFORMAT_DXT45 (15 << 0) +# define R200_TXFORMAT_DVDU88 (18 << 0) +# define R200_TXFORMAT_LDVDU655 (19 << 0) +# define R200_TXFORMAT_LDVDU8888 (20 << 0) +# define R200_TXFORMAT_GR1616 (21 << 0) +# define R200_TXFORMAT_ABGR8888 (22 << 0) +# define R200_TXFORMAT_BGR111110 (23 << 0) +# define R200_TXFORMAT_FORMAT_MASK (31 << 0) +# define R200_TXFORMAT_FORMAT_SHIFT 0 +# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define R200_TXFORMAT_NON_POWER2 (1 << 7) +# define R200_TXFORMAT_WIDTH_MASK (15 << 8) +# define R200_TXFORMAT_WIDTH_SHIFT 8 +# define R200_TXFORMAT_HEIGHT_MASK (15 << 12) +# define R200_TXFORMAT_HEIGHT_SHIFT 12 +# define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ +# define R200_TXFORMAT_F5_WIDTH_SHIFT 16 +# define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +# define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 +# define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) +# define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) +# define R200_TXFORMAT_ST_ROUTE_SHIFT 24 +# define R200_TXFORMAT_LOOKUP_DISABLE (1 << 27) +# define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +#define R200_PP_TXFORMAT_X_0 0x2c08 +#define R200_PP_TXFORMAT_X_1 0x2c28 +#define R200_PP_TXFORMAT_X_2 0x2c48 +#define R200_PP_TXFORMAT_X_3 0x2c68 +#define R200_PP_TXFORMAT_X_4 0x2c88 +#define R200_PP_TXFORMAT_X_5 0x2ca8 + +#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ +#define R200_PP_TXSIZE_1 0x2c2c /* NPOT only */ +#define R200_PP_TXSIZE_2 0x2c4c /* NPOT only */ +#define R200_PP_TXSIZE_3 0x2c6c /* NPOT only */ +#define R200_PP_TXSIZE_4 0x2c8c /* NPOT only */ +#define R200_PP_TXSIZE_5 0x2cac /* NPOT only */ + +#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ +#define R200_PP_TXPITCH_1 0x2c30 /* NPOT only */ +#define R200_PP_TXPITCH_2 0x2c50 /* NPOT only */ +#define R200_PP_TXPITCH_3 0x2c70 /* NPOT only */ +#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */ +#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */ + +#define R200_PP_CUBIC_FACES_0 0x2c18 +#define R200_PP_CUBIC_FACES_1 0x2c38 +#define R200_PP_CUBIC_FACES_2 0x2c58 +#define R200_PP_CUBIC_FACES_3 0x2c78 +#define R200_PP_CUBIC_FACES_4 0x2c98 +#define R200_PP_CUBIC_FACES_5 0x2cb8 + +#define R200_PP_TXOFFSET_0 0x2d00 +# define R200_TXO_ENDIAN_NO_SWAP (0 << 0) +# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R200_TXO_MACRO_LINEAR (0 << 2) +# define R200_TXO_MACRO_TILE (1 << 2) +# define R200_TXO_MICRO_LINEAR (0 << 3) +# define R200_TXO_MICRO_TILE (1 << 3) +# define R200_TXO_OFFSET_MASK 0xffffffe0 +# define R200_TXO_OFFSET_SHIFT 5 +#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 +#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 +#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c +#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 +#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 + +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c +#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 +#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 +#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 +#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c + +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 +#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 +#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c +#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 +#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 + +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c +#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 +#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 +#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 +#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 +#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 +#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c +#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 +#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 +#define R200_PP_TXOFFSET_5 0x2d78 +#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c +#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 +#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 +#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 +#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c + +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_PP_TFACTOR_1 0x2ee4 +#define R200_PP_TFACTOR_2 0x2ee8 +#define R200_PP_TFACTOR_3 0x2eec +#define R200_PP_TFACTOR_4 0x2ef0 +#define R200_PP_TFACTOR_5 0x2ef4 + +#define R200_PP_TXCBLEND_0 0x2f00 +# define R200_TXC_ARG_A_ZERO (0) +# define R200_TXC_ARG_A_CURRENT_COLOR (2) +# define R200_TXC_ARG_A_CURRENT_ALPHA (3) +# define R200_TXC_ARG_A_DIFFUSE_COLOR (4) +# define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) +# define R200_TXC_ARG_A_SPECULAR_COLOR (6) +# define R200_TXC_ARG_A_SPECULAR_ALPHA (7) +# define R200_TXC_ARG_A_TFACTOR_COLOR (8) +# define R200_TXC_ARG_A_TFACTOR_ALPHA (9) +# define R200_TXC_ARG_A_R0_COLOR (10) +# define R200_TXC_ARG_A_R0_ALPHA (11) +# define R200_TXC_ARG_A_R1_COLOR (12) +# define R200_TXC_ARG_A_R1_ALPHA (13) +# define R200_TXC_ARG_A_R2_COLOR (14) +# define R200_TXC_ARG_A_R2_ALPHA (15) +# define R200_TXC_ARG_A_R3_COLOR (16) +# define R200_TXC_ARG_A_R3_ALPHA (17) +# define R200_TXC_ARG_A_R4_COLOR (18) +# define R200_TXC_ARG_A_R4_ALPHA (19) +# define R200_TXC_ARG_A_R5_COLOR (20) +# define R200_TXC_ARG_A_R5_ALPHA (21) +# define R200_TXC_ARG_A_TFACTOR1_COLOR (26) +# define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) +# define R200_TXC_ARG_A_MASK (31 << 0) +# define R200_TXC_ARG_A_SHIFT 0 +# define R200_TXC_ARG_B_ZERO (0 << 5) +# define R200_TXC_ARG_B_CURRENT_COLOR (2 << 5) +# define R200_TXC_ARG_B_CURRENT_ALPHA (3 << 5) +# define R200_TXC_ARG_B_DIFFUSE_COLOR (4 << 5) +# define R200_TXC_ARG_B_DIFFUSE_ALPHA (5 << 5) +# define R200_TXC_ARG_B_SPECULAR_COLOR (6 << 5) +# define R200_TXC_ARG_B_SPECULAR_ALPHA (7 << 5) +# define R200_TXC_ARG_B_TFACTOR_COLOR (8 << 5) +# define R200_TXC_ARG_B_TFACTOR_ALPHA (9 << 5) +# define R200_TXC_ARG_B_R0_COLOR (10 << 5) +# define R200_TXC_ARG_B_R0_ALPHA (11 << 5) +# define R200_TXC_ARG_B_R1_COLOR (12 << 5) +# define R200_TXC_ARG_B_R1_ALPHA (13 << 5) +# define R200_TXC_ARG_B_R2_COLOR (14 << 5) +# define R200_TXC_ARG_B_R2_ALPHA (15 << 5) +# define R200_TXC_ARG_B_R3_COLOR (16 << 5) +# define R200_TXC_ARG_B_R3_ALPHA (17 << 5) +# define R200_TXC_ARG_B_R4_COLOR (18 << 5) +# define R200_TXC_ARG_B_R4_ALPHA (19 << 5) +# define R200_TXC_ARG_B_R5_COLOR (20 << 5) +# define R200_TXC_ARG_B_R5_ALPHA (21 << 5) +# define R200_TXC_ARG_B_TFACTOR1_COLOR (26 << 5) +# define R200_TXC_ARG_B_TFACTOR1_ALPHA (27 << 5) +# define R200_TXC_ARG_B_MASK (31 << 5) +# define R200_TXC_ARG_B_SHIFT 5 +# define R200_TXC_ARG_C_ZERO (0 << 10) +# define R200_TXC_ARG_C_CURRENT_COLOR (2 << 10) +# define R200_TXC_ARG_C_CURRENT_ALPHA (3 << 10) +# define R200_TXC_ARG_C_DIFFUSE_COLOR (4 << 10) +# define R200_TXC_ARG_C_DIFFUSE_ALPHA (5 << 10) +# define R200_TXC_ARG_C_SPECULAR_COLOR (6 << 10) +# define R200_TXC_ARG_C_SPECULAR_ALPHA (7 << 10) +# define R200_TXC_ARG_C_TFACTOR_COLOR (8 << 10) +# define R200_TXC_ARG_C_TFACTOR_ALPHA (9 << 10) +# define R200_TXC_ARG_C_R0_COLOR (10 << 10) +# define R200_TXC_ARG_C_R0_ALPHA (11 << 10) +# define R200_TXC_ARG_C_R1_COLOR (12 << 10) +# define R200_TXC_ARG_C_R1_ALPHA (13 << 10) +# define R200_TXC_ARG_C_R2_COLOR (14 << 10) +# define R200_TXC_ARG_C_R2_ALPHA (15 << 10) +# define R200_TXC_ARG_C_R3_COLOR (16 << 10) +# define R200_TXC_ARG_C_R3_ALPHA (17 << 10) +# define R200_TXC_ARG_C_R4_COLOR (18 << 10) +# define R200_TXC_ARG_C_R4_ALPHA (19 << 10) +# define R200_TXC_ARG_C_R5_COLOR (20 << 10) +# define R200_TXC_ARG_C_R5_ALPHA (21 << 10) +# define R200_TXC_ARG_C_TFACTOR1_COLOR (26 << 10) +# define R200_TXC_ARG_C_TFACTOR1_ALPHA (27 << 10) +# define R200_TXC_ARG_C_MASK (31 << 10) +# define R200_TXC_ARG_C_SHIFT 10 +# define R200_TXC_COMP_ARG_A (1 << 16) +# define R200_TXC_COMP_ARG_A_SHIFT (16) +# define R200_TXC_BIAS_ARG_A (1 << 17) +# define R200_TXC_SCALE_ARG_A (1 << 18) +# define R200_TXC_NEG_ARG_A (1 << 19) +# define R200_TXC_COMP_ARG_B (1 << 20) +# define R200_TXC_COMP_ARG_B_SHIFT (20) +# define R200_TXC_BIAS_ARG_B (1 << 21) +# define R200_TXC_SCALE_ARG_B (1 << 22) +# define R200_TXC_NEG_ARG_B (1 << 23) +# define R200_TXC_COMP_ARG_C (1 << 24) +# define R200_TXC_COMP_ARG_C_SHIFT (24) +# define R200_TXC_BIAS_ARG_C (1 << 25) +# define R200_TXC_SCALE_ARG_C (1 << 26) +# define R200_TXC_NEG_ARG_C (1 << 27) +# define R200_TXC_OP_MADD (0 << 28) +# define R200_TXC_OP_CND0 (2 << 28) +# define R200_TXC_OP_LERP (3 << 28) +# define R200_TXC_OP_DOT3 (4 << 28) +# define R200_TXC_OP_DOT4 (5 << 28) +# define R200_TXC_OP_CONDITIONAL (6 << 28) +# define R200_TXC_OP_DOT2_ADD (7 << 28) +# define R200_TXC_OP_MASK (7 << 28) +#define R200_PP_TXCBLEND2_0 0x2f04 +# define R200_TXC_TFACTOR_SEL_SHIFT 0 +# define R200_TXC_TFACTOR_SEL_MASK 0x7 +# define R200_TXC_TFACTOR1_SEL_SHIFT 4 +# define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXC_SCALE_SHIFT 8 +# define R200_TXC_SCALE_MASK (7 << 8) +# define R200_TXC_SCALE_1X (0 << 8) +# define R200_TXC_SCALE_2X (1 << 8) +# define R200_TXC_SCALE_4X (2 << 8) +# define R200_TXC_SCALE_8X (3 << 8) +# define R200_TXC_SCALE_INV2 (5 << 8) +# define R200_TXC_SCALE_INV4 (6 << 8) +# define R200_TXC_SCALE_INV8 (7 << 8) +# define R200_TXC_CLAMP_SHIFT 12 +# define R200_TXC_CLAMP_MASK (3 << 12) +# define R200_TXC_CLAMP_WRAP (0 << 12) +# define R200_TXC_CLAMP_0_1 (1 << 12) +# define R200_TXC_CLAMP_8_8 (2 << 12) +# define R200_TXC_OUTPUT_REG_MASK (7 << 16) +# define R200_TXC_OUTPUT_REG_NONE (0 << 16) +# define R200_TXC_OUTPUT_REG_R0 (1 << 16) +# define R200_TXC_OUTPUT_REG_R1 (2 << 16) +# define R200_TXC_OUTPUT_REG_R2 (3 << 16) +# define R200_TXC_OUTPUT_REG_R3 (4 << 16) +# define R200_TXC_OUTPUT_REG_R4 (5 << 16) +# define R200_TXC_OUTPUT_REG_R5 (6 << 16) +# define R200_TXC_OUTPUT_MASK_MASK (7 << 20) +# define R200_TXC_OUTPUT_MASK_RGB (0 << 20) +# define R200_TXC_OUTPUT_MASK_RG (1 << 20) +# define R200_TXC_OUTPUT_MASK_RB (2 << 20) +# define R200_TXC_OUTPUT_MASK_R (3 << 20) +# define R200_TXC_OUTPUT_MASK_GB (4 << 20) +# define R200_TXC_OUTPUT_MASK_G (5 << 20) +# define R200_TXC_OUTPUT_MASK_B (6 << 20) +# define R200_TXC_OUTPUT_MASK_NONE (7 << 20) +# define R200_TXC_REPL_NORMAL 0 +# define R200_TXC_REPL_RED 1 +# define R200_TXC_REPL_GREEN 2 +# define R200_TXC_REPL_BLUE 3 +# define R200_TXC_REPL_ARG_A_SHIFT 26 +# define R200_TXC_REPL_ARG_A_MASK (3 << 26) +# define R200_TXC_REPL_ARG_B_SHIFT 28 +# define R200_TXC_REPL_ARG_B_MASK (3 << 28) +# define R200_TXC_REPL_ARG_C_SHIFT 30 +# define R200_TXC_REPL_ARG_C_MASK (3 << 30) +#define R200_PP_TXABLEND_0 0x2f08 +# define R200_TXA_ARG_A_ZERO (0) +# define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ +# define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ +# define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) +# define R200_TXA_ARG_A_DIFFUSE_BLUE (5) +# define R200_TXA_ARG_A_SPECULAR_ALPHA (6) +# define R200_TXA_ARG_A_SPECULAR_BLUE (7) +# define R200_TXA_ARG_A_TFACTOR_ALPHA (8) +# define R200_TXA_ARG_A_TFACTOR_BLUE (9) +# define R200_TXA_ARG_A_R0_ALPHA (10) +# define R200_TXA_ARG_A_R0_BLUE (11) +# define R200_TXA_ARG_A_R1_ALPHA (12) +# define R200_TXA_ARG_A_R1_BLUE (13) +# define R200_TXA_ARG_A_R2_ALPHA (14) +# define R200_TXA_ARG_A_R2_BLUE (15) +# define R200_TXA_ARG_A_R3_ALPHA (16) +# define R200_TXA_ARG_A_R3_BLUE (17) +# define R200_TXA_ARG_A_R4_ALPHA (18) +# define R200_TXA_ARG_A_R4_BLUE (19) +# define R200_TXA_ARG_A_R5_ALPHA (20) +# define R200_TXA_ARG_A_R5_BLUE (21) +# define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) +# define R200_TXA_ARG_A_TFACTOR1_BLUE (27) +# define R200_TXA_ARG_A_MASK (31 << 0) +# define R200_TXA_ARG_A_SHIFT 0 +# define R200_TXA_ARG_B_ZERO (0 << 5) +# define R200_TXA_ARG_B_CURRENT_ALPHA (2 << 5) /* guess */ +# define R200_TXA_ARG_B_CURRENT_BLUE (3 << 5) /* guess */ +# define R200_TXA_ARG_B_DIFFUSE_ALPHA (4 << 5) +# define R200_TXA_ARG_B_DIFFUSE_BLUE (5 << 5) +# define R200_TXA_ARG_B_SPECULAR_ALPHA (6 << 5) +# define R200_TXA_ARG_B_SPECULAR_BLUE (7 << 5) +# define R200_TXA_ARG_B_TFACTOR_ALPHA (8 << 5) +# define R200_TXA_ARG_B_TFACTOR_BLUE (9 << 5) +# define R200_TXA_ARG_B_R0_ALPHA (10 << 5) +# define R200_TXA_ARG_B_R0_BLUE (11 << 5) +# define R200_TXA_ARG_B_R1_ALPHA (12 << 5) +# define R200_TXA_ARG_B_R1_BLUE (13 << 5) +# define R200_TXA_ARG_B_R2_ALPHA (14 << 5) +# define R200_TXA_ARG_B_R2_BLUE (15 << 5) +# define R200_TXA_ARG_B_R3_ALPHA (16 << 5) +# define R200_TXA_ARG_B_R3_BLUE (17 << 5) +# define R200_TXA_ARG_B_R4_ALPHA (18 << 5) +# define R200_TXA_ARG_B_R4_BLUE (19 << 5) +# define R200_TXA_ARG_B_R5_ALPHA (20 << 5) +# define R200_TXA_ARG_B_R5_BLUE (21 << 5) +# define R200_TXA_ARG_B_TFACTOR1_ALPHA (26 << 5) +# define R200_TXA_ARG_B_TFACTOR1_BLUE (27 << 5) +# define R200_TXA_ARG_B_MASK (31 << 5) +# define R200_TXA_ARG_B_SHIFT 5 +# define R200_TXA_ARG_C_ZERO (0 << 10) +# define R200_TXA_ARG_C_CURRENT_ALPHA (2 << 10) /* guess */ +# define R200_TXA_ARG_C_CURRENT_BLUE (3 << 10) /* guess */ +# define R200_TXA_ARG_C_DIFFUSE_ALPHA (4 << 10) +# define R200_TXA_ARG_C_DIFFUSE_BLUE (5 << 10) +# define R200_TXA_ARG_C_SPECULAR_ALPHA (6 << 10) +# define R200_TXA_ARG_C_SPECULAR_BLUE (7 << 10) +# define R200_TXA_ARG_C_TFACTOR_ALPHA (8 << 10) +# define R200_TXA_ARG_C_TFACTOR_BLUE (9 << 10) +# define R200_TXA_ARG_C_R0_ALPHA (10 << 10) +# define R200_TXA_ARG_C_R0_BLUE (11 << 10) +# define R200_TXA_ARG_C_R1_ALPHA (12 << 10) +# define R200_TXA_ARG_C_R1_BLUE (13 << 10) +# define R200_TXA_ARG_C_R2_ALPHA (14 << 10) +# define R200_TXA_ARG_C_R2_BLUE (15 << 10) +# define R200_TXA_ARG_C_R3_ALPHA (16 << 10) +# define R200_TXA_ARG_C_R3_BLUE (17 << 10) +# define R200_TXA_ARG_C_R4_ALPHA (18 << 10) +# define R200_TXA_ARG_C_R4_BLUE (19 << 10) +# define R200_TXA_ARG_C_R5_ALPHA (20 << 10) +# define R200_TXA_ARG_C_R5_BLUE (21 << 10) +# define R200_TXA_ARG_C_TFACTOR1_ALPHA (26 << 10) +# define R200_TXA_ARG_C_TFACTOR1_BLUE (27 << 10) +# define R200_TXA_ARG_C_MASK (31 << 10) +# define R200_TXA_ARG_C_SHIFT 10 +# define R200_TXA_COMP_ARG_A (1 << 16) +# define R200_TXA_COMP_ARG_A_SHIFT (16) +# define R200_TXA_BIAS_ARG_A (1 << 17) +# define R200_TXA_SCALE_ARG_A (1 << 18) +# define R200_TXA_NEG_ARG_A (1 << 19) +# define R200_TXA_COMP_ARG_B (1 << 20) +# define R200_TXA_COMP_ARG_B_SHIFT (20) +# define R200_TXA_BIAS_ARG_B (1 << 21) +# define R200_TXA_SCALE_ARG_B (1 << 22) +# define R200_TXA_NEG_ARG_B (1 << 23) +# define R200_TXA_COMP_ARG_C (1 << 24) +# define R200_TXA_COMP_ARG_C_SHIFT (24) +# define R200_TXA_BIAS_ARG_C (1 << 25) +# define R200_TXA_SCALE_ARG_C (1 << 26) +# define R200_TXA_NEG_ARG_C (1 << 27) +# define R200_TXA_OP_MADD (0 << 28) +# define R200_TXA_OP_CND0 (2 << 28) +# define R200_TXA_OP_LERP (3 << 28) +# define R200_TXA_OP_CONDITIONAL (6 << 28) +# define R200_TXA_OP_MASK (7 << 28) +#define R200_PP_TXABLEND2_0 0x2f0c +# define R200_TXA_TFACTOR_SEL_SHIFT 0 +# define R200_TXA_TFACTOR_SEL_MASK 0x7 +# define R200_TXA_TFACTOR1_SEL_SHIFT 4 +# define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXA_SCALE_SHIFT 8 +# define R200_TXA_SCALE_MASK (7 << 8) +# define R200_TXA_SCALE_1X (0 << 8) +# define R200_TXA_SCALE_2X (1 << 8) +# define R200_TXA_SCALE_4X (2 << 8) +# define R200_TXA_SCALE_8X (3 << 8) +# define R200_TXA_SCALE_INV2 (5 << 8) +# define R200_TXA_SCALE_INV4 (6 << 8) +# define R200_TXA_SCALE_INV8 (7 << 8) +# define R200_TXA_CLAMP_SHIFT 12 +# define R200_TXA_CLAMP_MASK (3 << 12) +# define R200_TXA_CLAMP_WRAP (0 << 12) +# define R200_TXA_CLAMP_0_1 (1 << 12) +# define R200_TXA_CLAMP_8_8 (2 << 12) +# define R200_TXA_OUTPUT_REG_MASK (7 << 16) +# define R200_TXA_OUTPUT_REG_NONE (0 << 16) +# define R200_TXA_OUTPUT_REG_R0 (1 << 16) +# define R200_TXA_OUTPUT_REG_R1 (2 << 16) +# define R200_TXA_OUTPUT_REG_R2 (3 << 16) +# define R200_TXA_OUTPUT_REG_R3 (4 << 16) +# define R200_TXA_OUTPUT_REG_R4 (5 << 16) +# define R200_TXA_OUTPUT_REG_R5 (6 << 16) +# define R200_TXA_DOT_ALPHA (1 << 20) +# define R200_TXA_REPL_NORMAL 0 +# define R200_TXA_REPL_RED 1 +# define R200_TXA_REPL_GREEN 2 +# define R200_TXA_REPL_ARG_A_SHIFT 26 +# define R200_TXA_REPL_ARG_A_MASK (3 << 26) +# define R200_TXA_REPL_ARG_B_SHIFT 28 +# define R200_TXA_REPL_ARG_B_MASK (3 << 28) +# define R200_TXA_REPL_ARG_C_SHIFT 30 +# define R200_TXA_REPL_ARG_C_MASK (3 << 30) + +#define R200_SE_VTX_FMT_0 0x2088 +# define R200_VTX_XY 0 /* always have xy */ +# define R200_VTX_Z0 (1<<0) +# define R200_VTX_W0 (1<<1) +# define R200_VTX_WEIGHT_COUNT_SHIFT (2) +# define R200_VTX_PV_MATRIX_SEL (1<<5) +# define R200_VTX_N0 (1<<6) +# define R200_VTX_POINT_SIZE (1<<7) +# define R200_VTX_DISCRETE_FOG (1<<8) +# define R200_VTX_SHININESS_0 (1<<9) +# define R200_VTX_SHININESS_1 (1<<10) +# define R200_VTX_COLOR_NOT_PRESENT 0 +# define R200_VTX_PK_RGBA 1 +# define R200_VTX_FP_RGB 2 +# define R200_VTX_FP_RGBA 3 +# define R200_VTX_COLOR_MASK 3 +# define R200_VTX_COLOR_0_SHIFT 11 +# define R200_VTX_COLOR_1_SHIFT 13 +# define R200_VTX_COLOR_2_SHIFT 15 +# define R200_VTX_COLOR_3_SHIFT 17 +# define R200_VTX_COLOR_4_SHIFT 19 +# define R200_VTX_COLOR_5_SHIFT 21 +# define R200_VTX_COLOR_6_SHIFT 23 +# define R200_VTX_COLOR_7_SHIFT 25 +# define R200_VTX_XY1 (1<<28) +# define R200_VTX_Z1 (1<<29) +# define R200_VTX_W1 (1<<30) +# define R200_VTX_N1 (1<<31) +#define R200_SE_VTX_FMT_1 0x208c +# define R200_VTX_TEX0_COMP_CNT_SHIFT 0 +# define R200_VTX_TEX1_COMP_CNT_SHIFT 3 +# define R200_VTX_TEX2_COMP_CNT_SHIFT 6 +# define R200_VTX_TEX3_COMP_CNT_SHIFT 9 +# define R200_VTX_TEX4_COMP_CNT_SHIFT 12 +# define R200_VTX_TEX5_COMP_CNT_SHIFT 15 + +#define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090 +#define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094 +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +# define R200_OUTPUT_XYZW (1<<0) +# define R200_OUTPUT_COLOR_0 (1<<8) +# define R200_OUTPUT_COLOR_1 (1<<9) +# define R200_OUTPUT_TEX_0 (1<<16) +# define R200_OUTPUT_TEX_1 (1<<17) +# define R200_OUTPUT_TEX_2 (1<<18) +# define R200_OUTPUT_TEX_3 (1<<19) +# define R200_OUTPUT_TEX_4 (1<<20) +# define R200_OUTPUT_TEX_5 (1<<21) +# define R200_OUTPUT_TEX_MASK (0x3f<<16) +# define R200_OUTPUT_DISCRETE_FOG (1<<24) +# define R200_OUTPUT_PT_SIZE (1<<25) +# define R200_FORCE_INORDER_PROC (1<<31) +#define R200_PP_CNTL_X 0x2cc4 +#define R200_PP_TXMULTI_CTL_0 0x2c1c +#define R200_PP_TXMULTI_CTL_1 0x2c3c +#define R200_PP_TXMULTI_CTL_2 0x2c5c +#define R200_PP_TXMULTI_CTL_3 0x2c7c +#define R200_PP_TXMULTI_CTL_4 0x2c9c +#define R200_PP_TXMULTI_CTL_5 0x2cbc +#define R200_SE_VTX_STATE_CNTL 0x2180 +# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16) + + /* Registers for CP and Microcode Engine */ +#define RADEON_CP_ME_RAM_ADDR 0x07d4 +#define RADEON_CP_ME_RAM_RADDR 0x07d8 +#define RADEON_CP_ME_RAM_DATAH 0x07dc +#define RADEON_CP_ME_RAM_DATAL 0x07e0 + +#define RADEON_CP_RB_BASE 0x0700 +#define RADEON_CP_RB_CNTL 0x0704 +# define RADEON_RB_BUFSZ_SHIFT 0 +# define RADEON_RB_BUFSZ_MASK (0x3f << 0) +# define RADEON_RB_BLKSZ_SHIFT 8 +# define RADEON_RB_BLKSZ_MASK (0x3f << 8) +# define RADEON_BUF_SWAP_32BIT (2 << 16) +# define RADEON_MAX_FETCH_SHIFT 18 +# define RADEON_MAX_FETCH_MASK (0x3 << 18) +# define RADEON_RB_NO_UPDATE (1 << 27) +# define RADEON_RB_RPTR_WR_ENA (1 << 31) +#define RADEON_CP_RB_RPTR_ADDR 0x070c +#define RADEON_CP_RB_RPTR 0x0710 +#define RADEON_CP_RB_WPTR 0x0714 +#define RADEON_CP_RB_RPTR_WR 0x071c + +#define RADEON_SCRATCH_UMSK 0x0770 +#define RADEON_SCRATCH_ADDR 0x0774 + +#define R600_CP_RB_BASE 0xc100 +#define R600_CP_RB_CNTL 0xc104 +# define R600_RB_BUFSZ(x) ((x) << 0) +# define R600_RB_BLKSZ(x) ((x) << 8) +# define R600_RB_NO_UPDATE (1 << 27) +# define R600_RB_RPTR_WR_ENA (1 << 31) +#define R600_CP_RB_RPTR_WR 0xc108 +#define R600_CP_RB_RPTR_ADDR 0xc10c +#define R600_CP_RB_RPTR_ADDR_HI 0xc110 +#define R600_CP_RB_WPTR 0xc114 +#define R600_CP_RB_WPTR_ADDR 0xc118 +#define R600_CP_RB_WPTR_ADDR_HI 0xc11c +#define R600_CP_RB_RPTR 0x8700 +#define R600_CP_RB_WPTR_DELAY 0x8704 + +#define RADEON_CP_IB_BASE 0x0738 +#define RADEON_CP_IB_BUFSZ 0x073c + +#define RADEON_CP_CSQ_CNTL 0x0740 +# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) +# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) +# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) +# define RADEON_CSQ_PRIBM_INDDIS (2 << 28) +# define RADEON_CSQ_PRIPIO_INDBM (3 << 28) +# define RADEON_CSQ_PRIBM_INDBM (4 << 28) +# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) + +#define R300_CP_RESYNC_ADDR 0x778 +#define R300_CP_RESYNC_DATA 0x77c + +#define RADEON_CP_CSQ_STAT 0x07f8 +# define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0) +# define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8) +# define RADEON_CSQ_RPTR_INDIRECT_MASK (0xff << 16) +# define RADEON_CSQ_WPTR_INDIRECT_MASK (0xff << 24) +#define RADEON_CP_CSQ2_STAT 0x07fc +#define RADEON_CP_CSQ_ADDR 0x07f0 +#define RADEON_CP_CSQ_DATA 0x07f4 +#define RADEON_CP_CSQ_APER_PRIMARY 0x1000 +#define RADEON_CP_CSQ_APER_INDIRECT 0x1300 + +#define RADEON_CP_RB_WPTR_DELAY 0x0718 +# define RADEON_PRE_WRITE_TIMER_SHIFT 0 +# define RADEON_PRE_WRITE_LIMIT_SHIFT 23 +#define RADEON_CP_CSQ_MODE 0x0744 +# define RADEON_INDIRECT2_START_SHIFT 0 +# define RADEON_INDIRECT2_START_MASK (0x7f << 0) +# define RADEON_INDIRECT1_START_SHIFT 8 +# define RADEON_INDIRECT1_START_MASK (0x7f << 8) + +#define RADEON_AIC_CNTL 0x01d0 +# define RADEON_PCIGART_TRANSLATE_EN (1 << 0) +# define RADEON_DIS_OUT_OF_PCI_GART_ACCESS (1 << 1) +# define RS400_MSI_REARM (1 << 3) /* rs400/rs480 */ +#define RADEON_AIC_LO_ADDR 0x01dc +#define RADEON_AIC_PT_BASE 0x01d8 +#define RADEON_AIC_HI_ADDR 0x01e0 + + + + /* Constants */ +/* #define RADEON_LAST_FRAME_REG RADEON_GUI_SCRATCH_REG0 */ +/* efine RADEON_LAST_CLEAR_REG RADEON_GUI_SCRATCH_REG2 */ + + + + /* CP packet types */ +#define RADEON_CP_PACKET0 0x00000000 +#define RADEON_CP_PACKET1 0x40000000 +#define RADEON_CP_PACKET2 0x80000000 +#define RADEON_CP_PACKET3 0xC0000000 +# define RADEON_CP_PACKET_MASK 0xC0000000 +# define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 +# define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) +# define RADEON_CP_PACKET0_REG_MASK 0x000007ff +# define R300_CP_PACKET0_REG_MASK 0x00001fff +# define R600_CP_PACKET0_REG_MASK 0x0000ffff +# define RADEON_CP_PACKET1_REG0_MASK 0x000007ff +# define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 + +#define RADEON_CP_PACKET0_ONE_REG_WR 0x00008000 + +#define RADEON_CP_PACKET3_NOP 0xC0001000 +#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900 +#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00 +#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00 +#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 +#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400 +#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600 +#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800 +#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 +#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 +#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 +#define R200_CP_PACKET3_3D_DRAW_IMMD_2 0xc0003500 +#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 +#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 +#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 +#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300 +#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 +#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500 +#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800 +#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 +#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 +#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 + + +#define RADEON_CP_VC_FRMT_XY 0x00000000 +#define RADEON_CP_VC_FRMT_W0 0x00000001 +#define RADEON_CP_VC_FRMT_FPCOLOR 0x00000002 +#define RADEON_CP_VC_FRMT_FPALPHA 0x00000004 +#define RADEON_CP_VC_FRMT_PKCOLOR 0x00000008 +#define RADEON_CP_VC_FRMT_FPSPEC 0x00000010 +#define RADEON_CP_VC_FRMT_FPFOG 0x00000020 +#define RADEON_CP_VC_FRMT_PKSPEC 0x00000040 +#define RADEON_CP_VC_FRMT_ST0 0x00000080 +#define RADEON_CP_VC_FRMT_ST1 0x00000100 +#define RADEON_CP_VC_FRMT_Q1 0x00000200 +#define RADEON_CP_VC_FRMT_ST2 0x00000400 +#define RADEON_CP_VC_FRMT_Q2 0x00000800 +#define RADEON_CP_VC_FRMT_ST3 0x00001000 +#define RADEON_CP_VC_FRMT_Q3 0x00002000 +#define RADEON_CP_VC_FRMT_Q0 0x00004000 +#define RADEON_CP_VC_FRMT_BLND_WEIGHT_CNT_MASK 0x00038000 +#define RADEON_CP_VC_FRMT_N0 0x00040000 +#define RADEON_CP_VC_FRMT_XY1 0x08000000 +#define RADEON_CP_VC_FRMT_Z1 0x10000000 +#define RADEON_CP_VC_FRMT_W1 0x20000000 +#define RADEON_CP_VC_FRMT_N1 0x40000000 +#define RADEON_CP_VC_FRMT_Z 0x80000000 + +#define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE 0x00000000 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT 0x00000001 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE 0x00000002 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP 0x00000003 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2 0x00000007 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST 0x00000008 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST 0x0000000a +#define RADEON_CP_VC_CNTL_PRIM_WALK_IND 0x00000010 +#define RADEON_CP_VC_CNTL_PRIM_WALK_LIST 0x00000020 +#define RADEON_CP_VC_CNTL_PRIM_WALK_RING 0x00000030 +#define RADEON_CP_VC_CNTL_COLOR_ORDER_BGRA 0x00000000 +#define RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA 0x00000040 +#define RADEON_CP_VC_CNTL_MAOS_ENABLE 0x00000080 +#define RADEON_CP_VC_CNTL_VTX_FMT_NON_RADEON_MODE 0x00000000 +#define RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE 0x00000100 +#define RADEON_CP_VC_CNTL_TCL_DISABLE 0x00000000 +#define RADEON_CP_VC_CNTL_TCL_ENABLE 0x00000200 +#define RADEON_CP_VC_CNTL_NUM_SHIFT 16 + +#define RADEON_VS_MATRIX_0_ADDR 0 +#define RADEON_VS_MATRIX_1_ADDR 4 +#define RADEON_VS_MATRIX_2_ADDR 8 +#define RADEON_VS_MATRIX_3_ADDR 12 +#define RADEON_VS_MATRIX_4_ADDR 16 +#define RADEON_VS_MATRIX_5_ADDR 20 +#define RADEON_VS_MATRIX_6_ADDR 24 +#define RADEON_VS_MATRIX_7_ADDR 28 +#define RADEON_VS_MATRIX_8_ADDR 32 +#define RADEON_VS_MATRIX_9_ADDR 36 +#define RADEON_VS_MATRIX_10_ADDR 40 +#define RADEON_VS_MATRIX_11_ADDR 44 +#define RADEON_VS_MATRIX_12_ADDR 48 +#define RADEON_VS_MATRIX_13_ADDR 52 +#define RADEON_VS_MATRIX_14_ADDR 56 +#define RADEON_VS_MATRIX_15_ADDR 60 +#define RADEON_VS_LIGHT_AMBIENT_ADDR 64 +#define RADEON_VS_LIGHT_DIFFUSE_ADDR 72 +#define RADEON_VS_LIGHT_SPECULAR_ADDR 80 +#define RADEON_VS_LIGHT_DIRPOS_ADDR 88 +#define RADEON_VS_LIGHT_HWVSPOT_ADDR 96 +#define RADEON_VS_LIGHT_ATTENUATION_ADDR 104 +#define RADEON_VS_MATRIX_EYE2CLIP_ADDR 112 +#define RADEON_VS_UCP_ADDR 116 +#define RADEON_VS_GLOBAL_AMBIENT_ADDR 122 +#define RADEON_VS_FOG_PARAM_ADDR 123 +#define RADEON_VS_EYE_VECTOR_ADDR 124 + +#define RADEON_SS_LIGHT_DCD_ADDR 0 +#define RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR 8 +#define RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR 16 +#define RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR 24 +#define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR 32 +#define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR 48 +#define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR 49 +#define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR 50 +#define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51 +#define RADEON_SS_SHININESS 60 + +#define RADEON_TV_MASTER_CNTL 0x0800 +# define RADEON_TV_ASYNC_RST (1 << 0) +# define RADEON_CRT_ASYNC_RST (1 << 1) +# define RADEON_RESTART_PHASE_FIX (1 << 3) +# define RADEON_TV_FIFO_ASYNC_RST (1 << 4) +# define RADEON_VIN_ASYNC_RST (1 << 5) +# define RADEON_AUD_ASYNC_RST (1 << 6) +# define RADEON_DVS_ASYNC_RST (1 << 7) +# define RADEON_CRT_FIFO_CE_EN (1 << 9) +# define RADEON_TV_FIFO_CE_EN (1 << 10) +# define RADEON_RE_SYNC_NOW_SEL_MASK (3 << 14) +# define RADEON_TVCLK_ALWAYS_ONb (1 << 30) +# define RADEON_TV_ON (1 << 31) +#define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 +# define RADEON_Y_RED_EN (1 << 0) +# define RADEON_C_GRN_EN (1 << 1) +# define RADEON_CMP_BLU_EN (1 << 2) +# define RADEON_DAC_DITHER_EN (1 << 3) +# define RADEON_RED_MX_FORCE_DAC_DATA (6 << 4) +# define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) +# define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) +# define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 +#define RADEON_TV_RGB_CNTL 0x0804 +# define RADEON_SWITCH_TO_BLUE (1 << 4) +# define RADEON_RGB_DITHER_EN (1 << 5) +# define RADEON_RGB_SRC_SEL_MASK (3 << 8) +# define RADEON_RGB_SRC_SEL_CRTC1 (0 << 8) +# define RADEON_RGB_SRC_SEL_RMX (1 << 8) +# define RADEON_RGB_SRC_SEL_CRTC2 (2 << 8) +# define RADEON_RGB_CONVERT_BY_PASS (1 << 10) +# define RADEON_UVRAM_READ_MARGIN_SHIFT 16 +# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20 +# define RADEON_RGB_ATTEN_SEL(x) ((x) << 24) +# define RADEON_TVOUT_SCALE_EN (1 << 26) +# define RADEON_RGB_ATTEN_VAL(x) ((x) << 28) +#define RADEON_TV_SYNC_CNTL 0x0808 +# define RADEON_SYNC_OE (1 << 0) +# define RADEON_SYNC_OUT (1 << 1) +# define RADEON_SYNC_IN (1 << 2) +# define RADEON_SYNC_PUB (1 << 3) +# define RADEON_SYNC_PD (1 << 4) +# define RADEON_TV_SYNC_IO_DRIVE (1 << 5) +#define RADEON_TV_HTOTAL 0x080c +#define RADEON_TV_HDISP 0x0810 +#define RADEON_TV_HSTART 0x0818 +#define RADEON_TV_HCOUNT 0x081C +#define RADEON_TV_VTOTAL 0x0820 +#define RADEON_TV_VDISP 0x0824 +#define RADEON_TV_VCOUNT 0x0828 +#define RADEON_TV_FTOTAL 0x082c +#define RADEON_TV_FCOUNT 0x0830 +#define RADEON_TV_FRESTART 0x0834 +#define RADEON_TV_HRESTART 0x0838 +#define RADEON_TV_VRESTART 0x083c +#define RADEON_TV_HOST_READ_DATA 0x0840 +#define RADEON_TV_HOST_WRITE_DATA 0x0844 +#define RADEON_TV_HOST_RD_WT_CNTL 0x0848 +# define RADEON_HOST_FIFO_RD (1 << 12) +# define RADEON_HOST_FIFO_RD_ACK (1 << 13) +# define RADEON_HOST_FIFO_WT (1 << 14) +# define RADEON_HOST_FIFO_WT_ACK (1 << 15) +#define RADEON_TV_VSCALER_CNTL1 0x084c +# define RADEON_UV_INC_MASK 0xffff +# define RADEON_UV_INC_SHIFT 0 +# define RADEON_Y_W_EN (1 << 24) +# define RADEON_RESTART_FIELD (1 << 29) /* restart on field 0 */ +# define RADEON_Y_DEL_W_SIG_SHIFT 26 +#define RADEON_TV_TIMING_CNTL 0x0850 +# define RADEON_H_INC_MASK 0xfff +# define RADEON_H_INC_SHIFT 0 +# define RADEON_REQ_Y_FIRST (1 << 19) +# define RADEON_FORCE_BURST_ALWAYS (1 << 21) +# define RADEON_UV_POST_SCALE_BYPASS (1 << 23) +# define RADEON_UV_OUTPUT_POST_SCALE_SHIFT 24 +#define RADEON_TV_VSCALER_CNTL2 0x0854 +# define RADEON_DITHER_MODE (1 << 0) +# define RADEON_Y_OUTPUT_DITHER_EN (1 << 1) +# define RADEON_UV_OUTPUT_DITHER_EN (1 << 2) +# define RADEON_UV_TO_BUF_DITHER_EN (1 << 3) +#define RADEON_TV_Y_FALL_CNTL 0x0858 +# define RADEON_Y_FALL_PING_PONG (1 << 16) +# define RADEON_Y_COEF_EN (1 << 17) +#define RADEON_TV_Y_RISE_CNTL 0x085c +# define RADEON_Y_RISE_PING_PONG (1 << 16) +#define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860 +#define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864 +# define RADEON_YUPSAMP_EN (1 << 0) +# define RADEON_UVUPSAMP_EN (1 << 2) +#define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868 +# define RADEON_Y_GAIN_LIMIT_SHIFT 0 +# define RADEON_UV_GAIN_LIMIT_SHIFT 16 +#define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c +# define RADEON_Y_GAIN_SHIFT 0 +# define RADEON_UV_GAIN_SHIFT 16 +#define RADEON_TV_MODULATOR_CNTL1 0x0870 +# define RADEON_YFLT_EN (1 << 2) +# define RADEON_UVFLT_EN (1 << 3) +# define RADEON_ALT_PHASE_EN (1 << 6) +# define RADEON_SYNC_TIP_LEVEL (1 << 7) +# define RADEON_BLANK_LEVEL_SHIFT 8 +# define RADEON_SET_UP_LEVEL_SHIFT 16 +# define RADEON_SLEW_RATE_LIMIT (1 << 23) +# define RADEON_CY_FILT_BLEND_SHIFT 28 +#define RADEON_TV_MODULATOR_CNTL2 0x0874 +# define RADEON_TV_U_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_SHIFT 16 +#define RADEON_TV_CRC_CNTL 0x0890 +#define RADEON_TV_UV_ADR 0x08ac +# define RADEON_MAX_UV_ADR_MASK 0x000000ff +# define RADEON_MAX_UV_ADR_SHIFT 0 +# define RADEON_TABLE1_BOT_ADR_MASK 0x0000ff00 +# define RADEON_TABLE1_BOT_ADR_SHIFT 8 +# define RADEON_TABLE3_TOP_ADR_MASK 0x00ff0000 +# define RADEON_TABLE3_TOP_ADR_SHIFT 16 +# define RADEON_HCODE_TABLE_SEL_MASK 0x06000000 +# define RADEON_HCODE_TABLE_SEL_SHIFT 25 +# define RADEON_VCODE_TABLE_SEL_MASK 0x18000000 +# define RADEON_VCODE_TABLE_SEL_SHIFT 27 +# define RADEON_TV_MAX_FIFO_ADDR 0x1a7 +# define RADEON_TV_MAX_FIFO_ADDR_INTERNAL 0x1ff +#define RADEON_TV_PLL_FINE_CNTL 0x0020 /* PLL */ +#define RADEON_TV_PLL_CNTL 0x0021 /* PLL */ +# define RADEON_TV_M0LO_MASK 0xff +# define RADEON_TV_M0HI_MASK 0x7 +# define RADEON_TV_M0HI_SHIFT 18 +# define RADEON_TV_N0LO_MASK 0x1ff +# define RADEON_TV_N0LO_SHIFT 8 +# define RADEON_TV_N0HI_MASK 0x3 +# define RADEON_TV_N0HI_SHIFT 21 +# define RADEON_TV_P_MASK 0xf +# define RADEON_TV_P_SHIFT 24 +# define RADEON_TV_SLIP_EN (1 << 23) +# define RADEON_TV_DTO_EN (1 << 28) +#define RADEON_TV_PLL_CNTL1 0x0022 /* PLL */ +# define RADEON_TVPLL_RESET (1 << 1) +# define RADEON_TVPLL_SLEEP (1 << 3) +# define RADEON_TVPLL_REFCLK_SEL (1 << 4) +# define RADEON_TVPCP_SHIFT 8 +# define RADEON_TVPCP_MASK (7 << 8) +# define RADEON_TVPVG_SHIFT 11 +# define RADEON_TVPVG_MASK (7 << 11) +# define RADEON_TVPDC_SHIFT 14 +# define RADEON_TVPDC_MASK (3 << 14) +# define RADEON_TVPLL_TEST_DIS (1 << 31) +# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) + +#define RS400_DISP2_REQ_CNTL1 0xe30 +# define RS400_DISP2_START_REQ_LEVEL_SHIFT 0 +# define RS400_DISP2_START_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP2_STOP_REQ_LEVEL_SHIFT 12 +# define RS400_DISP2_STOP_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP2_ALLOW_FID_LEVEL_SHIFT 22 +# define RS400_DISP2_ALLOW_FID_LEVEL_MASK 0x3ff +#define RS400_DISP2_REQ_CNTL2 0xe34 +# define RS400_DISP2_CRITICAL_POINT_START_SHIFT 12 +# define RS400_DISP2_CRITICAL_POINT_START_MASK 0x3ff +# define RS400_DISP2_CRITICAL_POINT_STOP_SHIFT 22 +# define RS400_DISP2_CRITICAL_POINT_STOP_MASK 0x3ff +#define RS400_DMIF_MEM_CNTL1 0xe38 +# define RS400_DISP2_START_ADR_SHIFT 0 +# define RS400_DISP2_START_ADR_MASK 0x3ff +# define RS400_DISP1_CRITICAL_POINT_START_SHIFT 12 +# define RS400_DISP1_CRITICAL_POINT_START_MASK 0x3ff +# define RS400_DISP1_CRITICAL_POINT_STOP_SHIFT 22 +# define RS400_DISP1_CRITICAL_POINT_STOP_MASK 0x3ff +#define RS400_DISP1_REQ_CNTL1 0xe3c +# define RS400_DISP1_START_REQ_LEVEL_SHIFT 0 +# define RS400_DISP1_START_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP1_STOP_REQ_LEVEL_SHIFT 12 +# define RS400_DISP1_STOP_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP1_ALLOW_FID_LEVEL_SHIFT 22 +# define RS400_DISP1_ALLOW_FID_LEVEL_MASK 0x3ff + +#define RADEON_PCIE_INDEX 0x0030 +#define RADEON_PCIE_DATA 0x0034 +#define RADEON_PCIE_TX_GART_CNTL 0x10 +# define RADEON_PCIE_TX_GART_EN (1 << 0) +# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1) +# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1 << 1) +# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3 << 1) +# define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0 << 3) +# define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1 << 3) +# define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1 << 5) +# define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1 << 8) +#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11 +#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12 +#define RADEON_PCIE_TX_GART_BASE 0x13 +#define RADEON_PCIE_TX_GART_START_LO 0x14 +#define RADEON_PCIE_TX_GART_START_HI 0x15 +#define RADEON_PCIE_TX_GART_END_LO 0x16 +#define RADEON_PCIE_TX_GART_END_HI 0x17 +#define RADEON_PCIE_TX_GART_ERROR 0x18 + +#define RADEON_SCRATCH_REG0 0x15e0 +#define RADEON_SCRATCH_REG1 0x15e4 +#define RADEON_SCRATCH_REG2 0x15e8 +#define RADEON_SCRATCH_REG3 0x15ec +#define RADEON_SCRATCH_REG4 0x15f0 +#define RADEON_SCRATCH_REG5 0x15f4 + +#define RV530_GB_PIPE_SELECT2 0x4124 + +#endif diff --git a/sys/dev/drm2/radeon/radeon_ring.c b/sys/dev/drm2/radeon/radeon_ring.c new file mode 100644 index 00000000000..37d0adee879 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_ring.c @@ -0,0 +1,884 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + * Christian König + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" +#include "atom.h" + +#ifdef DUMBBELL_WIP +/* + * IB + * IBs (Indirect Buffers) and areas of GPU accessible memory where + * commands are stored. You can put a pointer to the IB in the + * command ring and the hw will fetch the commands from the IB + * and execute them. Generally userspace acceleration drivers + * produce command buffers which are send to the kernel and + * put in IBs for execution by the requested ring. + */ +static int radeon_debugfs_sa_init(struct radeon_device *rdev); +#endif /* DUMBBELL_WIP */ + +/** + * radeon_ib_get - request an IB (Indirect Buffer) + * + * @rdev: radeon_device pointer + * @ring: ring index the IB is associated with + * @ib: IB object returned + * @size: requested IB size + * + * Request an IB (all asics). IBs are allocated using the + * suballocator. + * Returns 0 on success, error on failure. + */ +int radeon_ib_get(struct radeon_device *rdev, int ring, + struct radeon_ib *ib, struct radeon_vm *vm, + unsigned size) +{ + int i, r; + + r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); + if (r) { + dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); + return r; + } + + r = radeon_semaphore_create(rdev, &ib->semaphore); + if (r) { + return r; + } + + ib->ring = ring; + ib->fence = NULL; + ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); + ib->vm = vm; + if (vm) { + /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address + * space and soffset is the offset inside the pool bo + */ + ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET; + } else { + ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); + } + ib->is_const_ib = false; + for (i = 0; i < RADEON_NUM_RINGS; ++i) + ib->sync_to[i] = NULL; + + return 0; +} + +/** + * radeon_ib_free - free an IB (Indirect Buffer) + * + * @rdev: radeon_device pointer + * @ib: IB object to free + * + * Free an IB (all asics). + */ +void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) +{ + radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); + radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); + radeon_fence_unref(&ib->fence); +} + +/** + * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring + * + * @rdev: radeon_device pointer + * @ib: IB object to schedule + * @const_ib: Const IB to schedule (SI only) + * + * Schedule an IB on the associated ring (all asics). + * Returns 0 on success, error on failure. + * + * On SI, there are two parallel engines fed from the primary ring, + * the CE (Constant Engine) and the DE (Drawing Engine). Since + * resource descriptors have moved to memory, the CE allows you to + * prime the caches while the DE is updating register state so that + * the resource descriptors will be already in cache when the draw is + * processed. To accomplish this, the userspace driver submits two + * IBs, one for the CE and one for the DE. If there is a CE IB (called + * a CONST_IB), it will be put on the ring prior to the DE IB. Prior + * to SI there was just a DE IB. + */ +int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, + struct radeon_ib *const_ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + bool need_sync = false; + int i, r = 0; + + if (!ib->length_dw || !ring->ready) { + /* TODO: Nothings in the ib we should report. */ + dev_err(rdev->dev, "couldn't schedule ib\n"); + return -EINVAL; + } + + /* 64 dwords should be enough for fence too */ + r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); + if (r) { + dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); + return r; + } + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + struct radeon_fence *fence = ib->sync_to[i]; + if (radeon_fence_need_sync(fence, ib->ring)) { + need_sync = true; + radeon_semaphore_sync_rings(rdev, ib->semaphore, + fence->ring, ib->ring); + radeon_fence_note_sync(fence, ib->ring); + } + } + /* immediately free semaphore when we don't need to sync */ + if (!need_sync) { + radeon_semaphore_free(rdev, &ib->semaphore, NULL); + } + /* if we can't remember our last VM flush then flush now! */ + if (ib->vm && !ib->vm->last_flush) { + radeon_ring_vm_flush(rdev, ib->ring, ib->vm); + } + if (const_ib) { + radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); + radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); + } + radeon_ring_ib_execute(rdev, ib->ring, ib); + r = radeon_fence_emit(rdev, &ib->fence, ib->ring); + if (r) { + dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r); + radeon_ring_unlock_undo(rdev, ring); + return r; + } + if (const_ib) { + const_ib->fence = radeon_fence_ref(ib->fence); + } + /* we just flushed the VM, remember that */ + if (ib->vm && !ib->vm->last_flush) { + ib->vm->last_flush = radeon_fence_ref(ib->fence); + } + radeon_ring_unlock_commit(rdev, ring); + return 0; +} + +/** + * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool + * + * @rdev: radeon_device pointer + * + * Initialize the suballocator to manage a pool of memory + * for use as IBs (all asics). + * Returns 0 on success, error on failure. + */ +int radeon_ib_pool_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->ib_pool_ready) { + return 0; + } + r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, + RADEON_IB_POOL_SIZE*64*1024, + RADEON_GEM_DOMAIN_GTT); + if (r) { + return r; + } + + r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); + if (r) { + return r; + } + + rdev->ib_pool_ready = true; +#ifdef DUMBBELL_WIP + if (radeon_debugfs_sa_init(rdev)) { + dev_err(rdev->dev, "failed to register debugfs file for SA\n"); + } +#endif /* DUMBBELL_WIP */ + return 0; +} + +/** + * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool + * + * @rdev: radeon_device pointer + * + * Tear down the suballocator managing the pool of memory + * for use as IBs (all asics). + */ +void radeon_ib_pool_fini(struct radeon_device *rdev) +{ + if (rdev->ib_pool_ready) { + radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); + radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); + rdev->ib_pool_ready = false; + } +} + +/** + * radeon_ib_ring_tests - test IBs on the rings + * + * @rdev: radeon_device pointer + * + * Test an IB (Indirect Buffer) on each ring. + * If the test fails, disable the ring. + * Returns 0 on success, error if the primary GFX ring + * IB test fails. + */ +int radeon_ib_ring_tests(struct radeon_device *rdev) +{ + unsigned i; + int r; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + struct radeon_ring *ring = &rdev->ring[i]; + + if (!ring->ready) + continue; + + r = radeon_ib_test(rdev, i, ring); + if (r) { + ring->ready = false; + + if (i == RADEON_RING_TYPE_GFX_INDEX) { + /* oh, oh, that's really bad */ + DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r); + rdev->accel_working = false; + return r; + + } else { + /* still not good, but we can live with it */ + DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r); + } + } + } + return 0; +} + +#ifdef DUMBBELL_WIP +/* + * Rings + * Most engines on the GPU are fed via ring buffers. Ring + * buffers are areas of GPU accessible memory that the host + * writes commands into and the GPU reads commands out of. + * There is a rptr (read pointer) that determines where the + * GPU is currently reading, and a wptr (write pointer) + * which determines where the host has written. When the + * pointers are equal, the ring is idle. When the host + * writes commands to the ring buffer, it increments the + * wptr. The GPU then starts fetching commands and executes + * them until the pointers are equal again. + */ +static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); +#endif /* DUMBBELL_WIP */ + +#if defined(DRM_DEBUG_CODE) && DRM_DEBUG_CODE != 0 +/** + * radeon_ring_write - write a value to the ring + * + * @ring: radeon_ring structure holding ring information + * @v: dword (dw) value to write + * + * Write a value to the requested ring buffer (all asics). + */ +void radeon_ring_write(struct radeon_ring *ring, uint32_t v) +{ +#if DRM_DEBUG_CODE + if (ring->count_dw <= 0) { + DRM_ERROR("radeon: writing more dwords to the ring than expected!\n"); + } +#endif + ring->ring[ring->wptr++] = v; + ring->wptr &= ring->ptr_mask; + ring->count_dw--; + ring->ring_free_dw--; +} +#endif + +/** + * radeon_ring_supports_scratch_reg - check if the ring supports + * writing to scratch registers + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Check if a specific ring supports writing to scratch registers (all asics). + * Returns true if the ring supports writing to scratch regs, false if not. + */ +bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + switch (ring->idx) { + case RADEON_RING_TYPE_GFX_INDEX: + case CAYMAN_RING_TYPE_CP1_INDEX: + case CAYMAN_RING_TYPE_CP2_INDEX: + return true; + default: + return false; + } +} + +/** + * radeon_ring_free_size - update the free size + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Update the free dw slots in the ring buffer (all asics). + */ +void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 rptr; + + if (rdev->wb.enabled) + rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); + else + rptr = RREG32(ring->rptr_reg); + ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + /* This works because ring_size is a power of 2 */ + ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4)); + ring->ring_free_dw -= ring->wptr; + ring->ring_free_dw &= ring->ptr_mask; + if (!ring->ring_free_dw) { + ring->ring_free_dw = ring->ring_size / 4; + } +} + +/** + * radeon_ring_alloc - allocate space on the ring buffer + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * @ndw: number of dwords to allocate in the ring buffer + * + * Allocate @ndw dwords in the ring buffer (all asics). + * Returns 0 on success, error on failure. + */ +int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) +{ + int r; + + /* make sure we aren't trying to allocate more space than there is on the ring */ + if (ndw > (ring->ring_size / 4)) + return -ENOMEM; + /* Align requested size with padding so unlock_commit can + * pad safely */ + ndw = (ndw + ring->align_mask) & ~ring->align_mask; + while (ndw > (ring->ring_free_dw - 1)) { + radeon_ring_free_size(rdev, ring); + if (ndw < ring->ring_free_dw) { + break; + } + r = radeon_fence_wait_next_locked(rdev, ring->idx); + if (r) + return r; + } + ring->count_dw = ndw; + ring->wptr_old = ring->wptr; + return 0; +} + +/** + * radeon_ring_lock - lock the ring and allocate space on it + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * @ndw: number of dwords to allocate in the ring buffer + * + * Lock the ring and allocate @ndw dwords in the ring buffer + * (all asics). + * Returns 0 on success, error on failure. + */ +int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) +{ + int r; + + sx_xlock(&rdev->ring_lock); + r = radeon_ring_alloc(rdev, ring, ndw); + if (r) { + sx_xunlock(&rdev->ring_lock); + return r; + } + return 0; +} + +/** + * radeon_ring_commit - tell the GPU to execute the new + * commands on the ring buffer + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Update the wptr (write pointer) to tell the GPU to + * execute new commands on the ring buffer (all asics). + */ +void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) +{ + /* We pad to match fetch size */ + while (ring->wptr & ring->align_mask) { + radeon_ring_write(ring, ring->nop); + } + DRM_MEMORYBARRIER(); + WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask); + (void)RREG32(ring->wptr_reg); +} + +/** + * radeon_ring_unlock_commit - tell the GPU to execute the new + * commands on the ring buffer and unlock it + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Call radeon_ring_commit() then unlock the ring (all asics). + */ +void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) +{ + radeon_ring_commit(rdev, ring); + sx_xunlock(&rdev->ring_lock); +} + +/** + * radeon_ring_undo - reset the wptr + * + * @ring: radeon_ring structure holding ring information + * + * Reset the driver's copy of the wptr (all asics). + */ +void radeon_ring_undo(struct radeon_ring *ring) +{ + ring->wptr = ring->wptr_old; +} + +/** + * radeon_ring_unlock_undo - reset the wptr and unlock the ring + * + * @ring: radeon_ring structure holding ring information + * + * Call radeon_ring_undo() then unlock the ring (all asics). + */ +void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) +{ + radeon_ring_undo(ring); + sx_xunlock(&rdev->ring_lock); +} + +/** + * radeon_ring_force_activity - add some nop packets to the ring + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Add some nop packets to the ring to force activity (all asics). + * Used for lockup detection to see if the rptr is advancing. + */ +void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) +{ + int r; + + radeon_ring_free_size(rdev, ring); + if (ring->rptr == ring->wptr) { + r = radeon_ring_alloc(rdev, ring, 1); + if (!r) { + radeon_ring_write(ring, ring->nop); + radeon_ring_commit(rdev, ring); + } + } +} + +/** + * radeon_ring_lockup_update - update lockup variables + * + * @ring: radeon_ring structure holding ring information + * + * Update the last rptr value and timestamp (all asics). + */ +void radeon_ring_lockup_update(struct radeon_ring *ring) +{ + ring->last_rptr = ring->rptr; + ring->last_activity = jiffies; +} + +/** + * radeon_ring_test_lockup() - check if ring is lockedup by recording information + * @rdev: radeon device structure + * @ring: radeon_ring structure holding ring information + * + * We don't need to initialize the lockup tracking information as we will either + * have CP rptr to a different value of jiffies wrap around which will force + * initialization of the lockup tracking informations. + * + * A possible false positivie is if we get call after while and last_cp_rptr == + * the current CP rptr, even if it's unlikely it might happen. To avoid this + * if the elapsed time since last call is bigger than 2 second than we return + * false and update the tracking information. Due to this the caller must call + * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported + * the fencing code should be cautious about that. + * + * Caller should write to the ring to force CP to do something so we don't get + * false positive when CP is just gived nothing to do. + * + **/ +bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + unsigned long cjiffies, elapsed; + uint32_t rptr; + + cjiffies = jiffies; + if (!time_after(cjiffies, ring->last_activity)) { + /* likely a wrap around */ + radeon_ring_lockup_update(ring); + return false; + } + rptr = RREG32(ring->rptr_reg); + ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + if (ring->rptr != ring->last_rptr) { + /* CP is still working no lockup */ + radeon_ring_lockup_update(ring); + return false; + } + elapsed = jiffies_to_msecs(cjiffies - ring->last_activity); + if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) { + dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); + return true; + } + /* give a chance to the GPU ... */ + return false; +} + +/** + * radeon_ring_backup - Back up the content of a ring + * + * @rdev: radeon_device pointer + * @ring: the ring we want to back up + * + * Saves all unprocessed commits from a ring, returns the number of dwords saved. + */ +unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, + uint32_t **data) +{ + unsigned size, ptr, i; + + /* just in case lock the ring */ + sx_xlock(&rdev->ring_lock); + *data = NULL; + + if (ring->ring_obj == NULL) { + sx_xunlock(&rdev->ring_lock); + return 0; + } + + /* it doesn't make sense to save anything if all fences are signaled */ + if (!radeon_fence_count_emitted(rdev, ring->idx)) { + sx_xunlock(&rdev->ring_lock); + return 0; + } + + /* calculate the number of dw on the ring */ + if (ring->rptr_save_reg) + ptr = RREG32(ring->rptr_save_reg); + else if (rdev->wb.enabled) + ptr = le32_to_cpu(*ring->next_rptr_cpu_addr); + else { + /* no way to read back the next rptr */ + sx_xunlock(&rdev->ring_lock); + return 0; + } + + size = ring->wptr + (ring->ring_size / 4); + size -= ptr; + size &= ring->ptr_mask; + if (size == 0) { + sx_xunlock(&rdev->ring_lock); + return 0; + } + + /* and then save the content of the ring */ + *data = malloc(size * sizeof(uint32_t), DRM_MEM_DRIVER, M_WAITOK); + if (!*data) { + sx_xunlock(&rdev->ring_lock); + return 0; + } + for (i = 0; i < size; ++i) { + (*data)[i] = ring->ring[ptr++]; + ptr &= ring->ptr_mask; + } + + sx_xunlock(&rdev->ring_lock); + return size; +} + +/** + * radeon_ring_restore - append saved commands to the ring again + * + * @rdev: radeon_device pointer + * @ring: ring to append commands to + * @size: number of dwords we want to write + * @data: saved commands + * + * Allocates space on the ring and restore the previously saved commands. + */ +int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, + unsigned size, uint32_t *data) +{ + int i, r; + + if (!size || !data) + return 0; + + /* restore the saved ring content */ + r = radeon_ring_lock(rdev, ring, size); + if (r) + return r; + + for (i = 0; i < size; ++i) { + radeon_ring_write(ring, data[i]); + } + + radeon_ring_unlock_commit(rdev, ring); + free(data, DRM_MEM_DRIVER); + return 0; +} + +/** + * radeon_ring_init - init driver ring struct. + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * @ring_size: size of the ring + * @rptr_offs: offset of the rptr writeback location in the WB buffer + * @rptr_reg: MMIO offset of the rptr register + * @wptr_reg: MMIO offset of the wptr register + * @ptr_reg_shift: bit offset of the rptr/wptr values + * @ptr_reg_mask: bit mask of the rptr/wptr values + * @nop: nop packet for this ring + * + * Initialize the driver information for the selected ring (all asics). + * Returns 0 on success, error on failure. + */ +int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, + unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, + u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) +{ + int r; + void *ring_ptr; + + ring->ring_size = ring_size; + ring->rptr_offs = rptr_offs; + ring->rptr_reg = rptr_reg; + ring->wptr_reg = wptr_reg; + ring->ptr_reg_shift = ptr_reg_shift; + ring->ptr_reg_mask = ptr_reg_mask; + ring->nop = nop; + /* Allocate ring buffer */ + if (ring->ring_obj == NULL) { + r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, + NULL, &ring->ring_obj); + if (r) { + dev_err(rdev->dev, "(%d) ring create failed\n", r); + return r; + } + r = radeon_bo_reserve(ring->ring_obj, false); + if (unlikely(r != 0)) { + radeon_bo_unref(&ring->ring_obj); + return r; + } + r = radeon_bo_pin(ring->ring_obj, RADEON_GEM_DOMAIN_GTT, + &ring->gpu_addr); + if (r) { + radeon_bo_unreserve(ring->ring_obj); + radeon_bo_unref(&ring->ring_obj); + dev_err(rdev->dev, "(%d) ring pin failed\n", r); + return r; + } + ring_ptr = &ring->ring; + r = radeon_bo_kmap(ring->ring_obj, + ring_ptr); + radeon_bo_unreserve(ring->ring_obj); + if (r) { + dev_err(rdev->dev, "(%d) ring map failed\n", r); + radeon_bo_unref(&ring->ring_obj); + return r; + } + } + ring->ptr_mask = (ring->ring_size / 4) - 1; + ring->ring_free_dw = ring->ring_size / 4; + if (rdev->wb.enabled) { + u32 index = RADEON_WB_RING0_NEXT_RPTR + (ring->idx * 4); + ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; + ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; + } +#ifdef DUMBBELL_WIP + if (radeon_debugfs_ring_init(rdev, ring)) { + DRM_ERROR("Failed to register debugfs file for rings !\n"); + } +#endif /* DUMBBELL_WIP */ + radeon_ring_lockup_update(ring); + return 0; +} + +/** + * radeon_ring_fini - tear down the driver ring struct. + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Tear down the driver information for the selected ring (all asics). + */ +void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) +{ + int r; + struct radeon_bo *ring_obj; + + sx_xlock(&rdev->ring_lock); + ring_obj = ring->ring_obj; + ring->ready = false; + ring->ring = NULL; + ring->ring_obj = NULL; + sx_xunlock(&rdev->ring_lock); + + if (ring_obj) { + r = radeon_bo_reserve(ring_obj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(ring_obj); + radeon_bo_unpin(ring_obj); + radeon_bo_unreserve(ring_obj); + } + radeon_bo_unref(&ring_obj); + } +} + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) + +static int radeon_debugfs_ring_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + int ridx = *(int*)node->info_ent->data; + struct radeon_ring *ring = &rdev->ring[ridx]; + unsigned count, i, j; + u32 tmp; + + radeon_ring_free_size(rdev, ring); + count = (ring->ring_size / 4) - ring->ring_free_dw; + tmp = RREG32(ring->wptr_reg) >> ring->ptr_reg_shift; + seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp); + tmp = RREG32(ring->rptr_reg) >> ring->ptr_reg_shift; + seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp); + if (ring->rptr_save_reg) { + seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg, + RREG32(ring->rptr_save_reg)); + } + seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); + seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); + seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); + seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); + seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); + seq_printf(m, "%u dwords in ring\n", count); + /* print 8 dw before current rptr as often it's the last executed + * packet that is the root issue + */ + i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask; + for (j = 0; j <= (count + 32); j++) { + seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]); + i = (i + 1) & ring->ptr_mask; + } + return 0; +} + +static int radeon_ring_type_gfx_index = RADEON_RING_TYPE_GFX_INDEX; +static int cayman_ring_type_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX; +static int cayman_ring_type_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; +static int radeon_ring_type_dma1_index = R600_RING_TYPE_DMA_INDEX; +static int radeon_ring_type_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; + +static struct drm_info_list radeon_debugfs_ring_info_list[] = { + {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_ring_type_gfx_index}, + {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp1_index}, + {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index}, + {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma1_index}, + {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma2_index}, +}; + +static int radeon_debugfs_sa_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + + radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m); + + return 0; + +} + +static struct drm_info_list radeon_debugfs_sa_list[] = { + {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL}, +}; + +#endif + +#ifdef DUMBBELL_WIP +static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring) +{ +#if defined(CONFIG_DEBUG_FS) + unsigned i; + for (i = 0; i < ARRAY_SIZE(radeon_debugfs_ring_info_list); ++i) { + struct drm_info_list *info = &radeon_debugfs_ring_info_list[i]; + int ridx = *(int*)radeon_debugfs_ring_info_list[i].data; + unsigned r; + + if (&rdev->ring[ridx] != ring) + continue; + + r = radeon_debugfs_add_files(rdev, info, 1); + if (r) + return r; + } +#endif + return 0; +} + +static int radeon_debugfs_sa_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1); +#else + return 0; +#endif +} +#endif /* DUMBBELL_WIP */ diff --git a/sys/dev/drm2/radeon/radeon_sa.c b/sys/dev/drm2/radeon/radeon_sa.c new file mode 100644 index 00000000000..e750812697c --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_sa.c @@ -0,0 +1,428 @@ +/* + * Copyright 2011 Red Hat Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: + * Jerome Glisse + */ +/* Algorithm: + * + * We store the last allocated bo in "hole", we always try to allocate + * after the last allocated bo. Principle is that in a linear GPU ring + * progression was is after last is the oldest bo we allocated and thus + * the first one that should no longer be in use by the GPU. + * + * If it's not the case we skip over the bo after last to the closest + * done bo if such one exist. If none exist and we are not asked to + * block we report failure to allocate. + * + * If we are asked to block we wait on all the oldest fence of all + * rings. We just wait for any of those fence to complete. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" + +static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo); +static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager); + +int radeon_sa_bo_manager_init(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager, + unsigned size, u32 domain) +{ + int i, r; + + sx_init(&sa_manager->wq_lock, "drm__radeon_sa_manager_wq_mtx"); + cv_init(&sa_manager->wq, "drm__radeon_sa_manager__wq"); + sa_manager->bo = NULL; + sa_manager->size = size; + sa_manager->domain = domain; + sa_manager->hole = &sa_manager->olist; + INIT_LIST_HEAD(&sa_manager->olist); + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + INIT_LIST_HEAD(&sa_manager->flist[i]); + } + + r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true, + RADEON_GEM_DOMAIN_CPU, NULL, &sa_manager->bo); + if (r) { + dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); + return r; + } + + return r; +} + +void radeon_sa_bo_manager_fini(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager) +{ + struct radeon_sa_bo *sa_bo, *tmp; + + if (!list_empty(&sa_manager->olist)) { + sa_manager->hole = &sa_manager->olist, + radeon_sa_bo_try_free(sa_manager); + if (!list_empty(&sa_manager->olist)) { + dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n"); + } + } + list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) { + radeon_sa_bo_remove_locked(sa_bo); + } + radeon_bo_unref(&sa_manager->bo); + sa_manager->size = 0; + cv_destroy(&sa_manager->wq); + sx_destroy(&sa_manager->wq_lock); +} + +int radeon_sa_bo_manager_start(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager) +{ + int r; + + if (sa_manager->bo == NULL) { + dev_err(rdev->dev, "no bo for sa manager\n"); + return -EINVAL; + } + + /* map the buffer */ + r = radeon_bo_reserve(sa_manager->bo, false); + if (r) { + dev_err(rdev->dev, "(%d) failed to reserve manager bo\n", r); + return r; + } + r = radeon_bo_pin(sa_manager->bo, sa_manager->domain, &sa_manager->gpu_addr); + if (r) { + radeon_bo_unreserve(sa_manager->bo); + dev_err(rdev->dev, "(%d) failed to pin manager bo\n", r); + return r; + } + r = radeon_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr); + radeon_bo_unreserve(sa_manager->bo); + return r; +} + +int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager) +{ + int r; + + if (sa_manager->bo == NULL) { + dev_err(rdev->dev, "no bo for sa manager\n"); + return -EINVAL; + } + + r = radeon_bo_reserve(sa_manager->bo, false); + if (!r) { + radeon_bo_kunmap(sa_manager->bo); + radeon_bo_unpin(sa_manager->bo); + radeon_bo_unreserve(sa_manager->bo); + } + return r; +} + +static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo) +{ + struct radeon_sa_manager *sa_manager = sa_bo->manager; + if (sa_manager->hole == &sa_bo->olist) { + sa_manager->hole = sa_bo->olist.prev; + } + list_del_init(&sa_bo->olist); + list_del_init(&sa_bo->flist); + radeon_fence_unref(&sa_bo->fence); + free(sa_bo, DRM_MEM_DRIVER); +} + +static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager) +{ + struct radeon_sa_bo *sa_bo, *tmp; + + if (sa_manager->hole->next == &sa_manager->olist) + return; + + sa_bo = list_entry(sa_manager->hole->next, struct radeon_sa_bo, olist); + list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) { + if (sa_bo->fence == NULL || !radeon_fence_signaled(sa_bo->fence)) { + return; + } + radeon_sa_bo_remove_locked(sa_bo); + } +} + +static inline unsigned radeon_sa_bo_hole_soffset(struct radeon_sa_manager *sa_manager) +{ + struct list_head *hole = sa_manager->hole; + + if (hole != &sa_manager->olist) { + return list_entry(hole, struct radeon_sa_bo, olist)->eoffset; + } + return 0; +} + +static inline unsigned radeon_sa_bo_hole_eoffset(struct radeon_sa_manager *sa_manager) +{ + struct list_head *hole = sa_manager->hole; + + if (hole->next != &sa_manager->olist) { + return list_entry(hole->next, struct radeon_sa_bo, olist)->soffset; + } + return sa_manager->size; +} + +static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager, + struct radeon_sa_bo *sa_bo, + unsigned size, unsigned align) +{ + unsigned soffset, eoffset, wasted; + + soffset = radeon_sa_bo_hole_soffset(sa_manager); + eoffset = radeon_sa_bo_hole_eoffset(sa_manager); + wasted = (align - (soffset % align)) % align; + + if ((eoffset - soffset) >= (size + wasted)) { + soffset += wasted; + + sa_bo->manager = sa_manager; + sa_bo->soffset = soffset; + sa_bo->eoffset = soffset + size; + list_add(&sa_bo->olist, sa_manager->hole); + INIT_LIST_HEAD(&sa_bo->flist); + sa_manager->hole = &sa_bo->olist; + return true; + } + return false; +} + +/** + * radeon_sa_event - Check if we can stop waiting + * + * @sa_manager: pointer to the sa_manager + * @size: number of bytes we want to allocate + * @align: alignment we need to match + * + * Check if either there is a fence we can wait for or + * enough free memory to satisfy the allocation directly + */ +static bool radeon_sa_event(struct radeon_sa_manager *sa_manager, + unsigned size, unsigned align) +{ + unsigned soffset, eoffset, wasted; + int i; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + if (!list_empty(&sa_manager->flist[i])) { + return true; + } + } + + soffset = radeon_sa_bo_hole_soffset(sa_manager); + eoffset = radeon_sa_bo_hole_eoffset(sa_manager); + wasted = (align - (soffset % align)) % align; + + if ((eoffset - soffset) >= (size + wasted)) { + return true; + } + + return false; +} + +static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, + struct radeon_fence **fences, + unsigned *tries) +{ + struct radeon_sa_bo *best_bo = NULL; + unsigned i, soffset, best, tmp; + + /* if hole points to the end of the buffer */ + if (sa_manager->hole->next == &sa_manager->olist) { + /* try again with its beginning */ + sa_manager->hole = &sa_manager->olist; + return true; + } + + soffset = radeon_sa_bo_hole_soffset(sa_manager); + /* to handle wrap around we add sa_manager->size */ + best = sa_manager->size * 2; + /* go over all fence list and try to find the closest sa_bo + * of the current last + */ + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + struct radeon_sa_bo *sa_bo; + + if (list_empty(&sa_manager->flist[i])) { + continue; + } + + sa_bo = list_first_entry(&sa_manager->flist[i], + struct radeon_sa_bo, flist); + + if (!radeon_fence_signaled(sa_bo->fence)) { + fences[i] = sa_bo->fence; + continue; + } + + /* limit the number of tries each ring gets */ + if (tries[i] > 2) { + continue; + } + + tmp = sa_bo->soffset; + if (tmp < soffset) { + /* wrap around, pretend it's after */ + tmp += sa_manager->size; + } + tmp -= soffset; + if (tmp < best) { + /* this sa bo is the closest one */ + best = tmp; + best_bo = sa_bo; + } + } + + if (best_bo) { + ++tries[best_bo->fence->ring]; + sa_manager->hole = best_bo->olist.prev; + + /* we knew that this one is signaled, + so it's save to remote it */ + radeon_sa_bo_remove_locked(best_bo); + return true; + } + return false; +} + +int radeon_sa_bo_new(struct radeon_device *rdev, + struct radeon_sa_manager *sa_manager, + struct radeon_sa_bo **sa_bo, + unsigned size, unsigned align, bool block) +{ + struct radeon_fence *fences[RADEON_NUM_RINGS]; + unsigned tries[RADEON_NUM_RINGS]; + int i, r; + + KASSERT(align <= RADEON_GPU_PAGE_SIZE, ("align > RADEON_GPU_PAGE_SIZE")); + KASSERT(size <= sa_manager->size, ("size > sa_manager->size")); + + *sa_bo = malloc(sizeof(struct radeon_sa_bo), DRM_MEM_DRIVER, M_WAITOK); + if ((*sa_bo) == NULL) { + return -ENOMEM; + } + (*sa_bo)->manager = sa_manager; + (*sa_bo)->fence = NULL; + INIT_LIST_HEAD(&(*sa_bo)->olist); + INIT_LIST_HEAD(&(*sa_bo)->flist); + + sx_xlock(&sa_manager->wq_lock); + do { + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + fences[i] = NULL; + tries[i] = 0; + } + + do { + radeon_sa_bo_try_free(sa_manager); + + if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, + size, align)) { + sx_xunlock(&sa_manager->wq_lock); + return 0; + } + + /* see if we can skip over some allocations */ + } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); + + sx_xunlock(&sa_manager->wq_lock); + r = radeon_fence_wait_any(rdev, fences, false); + sx_xlock(&sa_manager->wq_lock); + /* if we have nothing to wait for block */ + if (r == -ENOENT && block) { + while (!radeon_sa_event(sa_manager, size, align)) { + r = -cv_wait_sig(&sa_manager->wq, + &sa_manager->wq_lock); + if (r != 0) + break; + } + + } else if (r == -ENOENT) { + r = -ENOMEM; + } + + } while (!r); + + sx_xunlock(&sa_manager->wq_lock); + free(*sa_bo, DRM_MEM_DRIVER); + *sa_bo = NULL; + return r; +} + +void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, + struct radeon_fence *fence) +{ + struct radeon_sa_manager *sa_manager; + + if (sa_bo == NULL || *sa_bo == NULL) { + return; + } + + sa_manager = (*sa_bo)->manager; + sx_xlock(&sa_manager->wq_lock); + if (fence && !radeon_fence_signaled(fence)) { + (*sa_bo)->fence = radeon_fence_ref(fence); + list_add_tail(&(*sa_bo)->flist, + &sa_manager->flist[fence->ring]); + } else { + radeon_sa_bo_remove_locked(*sa_bo); + } + cv_broadcast(&sa_manager->wq); + sx_xunlock(&sa_manager->wq_lock); + *sa_bo = NULL; +} + +#if defined(CONFIG_DEBUG_FS) +void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, + struct seq_file *m) +{ + struct radeon_sa_bo *i; + + spin_lock(&sa_manager->wq.lock); + list_for_each_entry(i, &sa_manager->olist, olist) { + if (&i->olist == sa_manager->hole) { + seq_printf(m, ">"); + } else { + seq_printf(m, " "); + } + seq_printf(m, "[0x%08x 0x%08x] size %8d", + i->soffset, i->eoffset, i->eoffset - i->soffset); + if (i->fence) { + seq_printf(m, " protected by 0x%016llx on ring %d", + i->fence->seq, i->fence->ring); + } + seq_printf(m, "\n"); + } + spin_unlock(&sa_manager->wq.lock); +} +#endif diff --git a/sys/dev/drm2/radeon/radeon_semaphore.c b/sys/dev/drm2/radeon/radeon_semaphore.c new file mode 100644 index 00000000000..717a94a482d --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_semaphore.c @@ -0,0 +1,124 @@ +/* + * Copyright 2011 Christian König. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Authors: + * Christian König + */ +#include +#include "radeon.h" + + +int radeon_semaphore_create(struct radeon_device *rdev, + struct radeon_semaphore **semaphore) +{ + int r; + + *semaphore = malloc(sizeof(struct radeon_semaphore), + DRM_MEM_DRIVER, M_WAITOK); + if (*semaphore == NULL) { + return -ENOMEM; + } + r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, + &(*semaphore)->sa_bo, 8, 8, true); + if (r) { + free(*semaphore, DRM_MEM_DRIVER); + *semaphore = NULL; + return r; + } + (*semaphore)->waiters = 0; + (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); + *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; + return 0; +} + +void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, + struct radeon_semaphore *semaphore) +{ + --semaphore->waiters; + radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); +} + +void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, + struct radeon_semaphore *semaphore) +{ + ++semaphore->waiters; + radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); +} + +/* caller must hold ring lock */ +int radeon_semaphore_sync_rings(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + int signaler, int waiter) +{ + int r; + + /* no need to signal and wait on the same ring */ + if (signaler == waiter) { + return 0; + } + + /* prevent GPU deadlocks */ + if (!rdev->ring[signaler].ready) { + dev_err(rdev->dev, "Trying to sync to a disabled ring!"); + return -EINVAL; + } + + r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); + if (r) { + return r; + } + radeon_semaphore_emit_signal(rdev, signaler, semaphore); + radeon_ring_commit(rdev, &rdev->ring[signaler]); + + /* we assume caller has already allocated space on waiters ring */ + radeon_semaphore_emit_wait(rdev, waiter, semaphore); + + /* for debugging lockup only, used by sysfs debug files */ + rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; + rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; + + return 0; +} + +void radeon_semaphore_free(struct radeon_device *rdev, + struct radeon_semaphore **semaphore, + struct radeon_fence *fence) +{ + if (semaphore == NULL || *semaphore == NULL) { + return; + } + if ((*semaphore)->waiters > 0) { + dev_err(rdev->dev, "semaphore %p has more waiters than signalers," + " hardware lockup imminent!\n", *semaphore); + } + radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); + free(*semaphore, DRM_MEM_DRIVER); + *semaphore = NULL; +} diff --git a/sys/dev/drm2/radeon/radeon_state.c b/sys/dev/drm2/radeon/radeon_state.c new file mode 100644 index 00000000000..1716830f190 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_state.c @@ -0,0 +1,3262 @@ +/* radeon_state.c -- State support for Radeon -*- linux-c -*- */ +/* + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Kevin E. Martin + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "radeon_drv.h" + +/* ================================================================ + * Helper functions for client state checking and fixup + */ + +static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * + dev_priv, + struct drm_file * file_priv, + u32 *offset) +{ + u64 off = *offset; + u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1; + struct drm_radeon_driver_file_fields *radeon_priv; + + /* Hrm ... the story of the offset ... So this function converts + * the various ideas of what userland clients might have for an + * offset in the card address space into an offset into the card + * address space :) So with a sane client, it should just keep + * the value intact and just do some boundary checking. However, + * not all clients are sane. Some older clients pass us 0 based + * offsets relative to the start of the framebuffer and some may + * assume the AGP aperture it appended to the framebuffer, so we + * try to detect those cases and fix them up. + * + * Note: It might be a good idea here to make sure the offset lands + * in some "allowed" area to protect things like the PCIE GART... + */ + + /* First, the best case, the offset already lands in either the + * framebuffer or the GART mapped space + */ + if (radeon_check_offset(dev_priv, off)) + return 0; + + /* Ok, that didn't happen... now check if we have a zero based + * offset that fits in the framebuffer + gart space, apply the + * magic offset we get from SETPARAM or calculated from fb_location + */ + if (off < (dev_priv->fb_size + dev_priv->gart_size)) { + radeon_priv = file_priv->driver_priv; + off += radeon_priv->radeon_fb_delta; + } + + /* Finally, assume we aimed at a GART offset if beyond the fb */ + if (off > fb_end) + off = off - fb_end - 1 + dev_priv->gart_vm_start; + + /* Now recheck and fail if out of bounds */ + if (radeon_check_offset(dev_priv, off)) { + DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); + *offset = off; + return 0; + } + return -EINVAL; +} + +static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * + dev_priv, + struct drm_file *file_priv, + int id, struct drm_buffer *buf) +{ + u32 *data; + switch (id) { + + case RADEON_EMIT_PP_MISC: + data = drm_buffer_pointer_to_dword(buf, + (RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4); + + if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { + DRM_ERROR("Invalid depth buffer offset\n"); + return -EINVAL; + } + dev_priv->have_z_offset = 1; + break; + + case RADEON_EMIT_PP_CNTL: + data = drm_buffer_pointer_to_dword(buf, + (RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4); + + if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { + DRM_ERROR("Invalid colour buffer offset\n"); + return -EINVAL; + } + break; + + case R200_EMIT_PP_TXOFFSET_0: + case R200_EMIT_PP_TXOFFSET_1: + case R200_EMIT_PP_TXOFFSET_2: + case R200_EMIT_PP_TXOFFSET_3: + case R200_EMIT_PP_TXOFFSET_4: + case R200_EMIT_PP_TXOFFSET_5: + data = drm_buffer_pointer_to_dword(buf, 0); + if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { + DRM_ERROR("Invalid R200 texture offset\n"); + return -EINVAL; + } + break; + + case RADEON_EMIT_PP_TXFILTER_0: + case RADEON_EMIT_PP_TXFILTER_1: + case RADEON_EMIT_PP_TXFILTER_2: + data = drm_buffer_pointer_to_dword(buf, + (RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4); + if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { + DRM_ERROR("Invalid R100 texture offset\n"); + return -EINVAL; + } + break; + + case R200_EMIT_PP_CUBIC_OFFSETS_0: + case R200_EMIT_PP_CUBIC_OFFSETS_1: + case R200_EMIT_PP_CUBIC_OFFSETS_2: + case R200_EMIT_PP_CUBIC_OFFSETS_3: + case R200_EMIT_PP_CUBIC_OFFSETS_4: + case R200_EMIT_PP_CUBIC_OFFSETS_5:{ + int i; + for (i = 0; i < 5; i++) { + data = drm_buffer_pointer_to_dword(buf, i); + if (radeon_check_and_fixup_offset(dev_priv, + file_priv, + data)) { + DRM_ERROR + ("Invalid R200 cubic texture offset\n"); + return -EINVAL; + } + } + break; + } + + case RADEON_EMIT_PP_CUBIC_OFFSETS_T0: + case RADEON_EMIT_PP_CUBIC_OFFSETS_T1: + case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{ + int i; + for (i = 0; i < 5; i++) { + data = drm_buffer_pointer_to_dword(buf, i); + if (radeon_check_and_fixup_offset(dev_priv, + file_priv, + data)) { + DRM_ERROR + ("Invalid R100 cubic texture offset\n"); + return -EINVAL; + } + } + } + break; + + case R200_EMIT_VAP_CTL:{ + RING_LOCALS; + BEGIN_RING(2); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + ADVANCE_RING(); + } + break; + + case RADEON_EMIT_RB3D_COLORPITCH: + case RADEON_EMIT_RE_LINE_PATTERN: + case RADEON_EMIT_SE_LINE_WIDTH: + case RADEON_EMIT_PP_LUM_MATRIX: + case RADEON_EMIT_PP_ROT_MATRIX_0: + case RADEON_EMIT_RB3D_STENCILREFMASK: + case RADEON_EMIT_SE_VPORT_XSCALE: + case RADEON_EMIT_SE_CNTL: + case RADEON_EMIT_SE_CNTL_STATUS: + case RADEON_EMIT_RE_MISC: + case RADEON_EMIT_PP_BORDER_COLOR_0: + case RADEON_EMIT_PP_BORDER_COLOR_1: + case RADEON_EMIT_PP_BORDER_COLOR_2: + case RADEON_EMIT_SE_ZBIAS_FACTOR: + case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT: + case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED: + case R200_EMIT_PP_TXCBLEND_0: + case R200_EMIT_PP_TXCBLEND_1: + case R200_EMIT_PP_TXCBLEND_2: + case R200_EMIT_PP_TXCBLEND_3: + case R200_EMIT_PP_TXCBLEND_4: + case R200_EMIT_PP_TXCBLEND_5: + case R200_EMIT_PP_TXCBLEND_6: + case R200_EMIT_PP_TXCBLEND_7: + case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: + case R200_EMIT_TFACTOR_0: + case R200_EMIT_VTX_FMT_0: + case R200_EMIT_MATRIX_SELECT_0: + case R200_EMIT_TEX_PROC_CTL_2: + case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: + case R200_EMIT_PP_TXFILTER_0: + case R200_EMIT_PP_TXFILTER_1: + case R200_EMIT_PP_TXFILTER_2: + case R200_EMIT_PP_TXFILTER_3: + case R200_EMIT_PP_TXFILTER_4: + case R200_EMIT_PP_TXFILTER_5: + case R200_EMIT_VTE_CNTL: + case R200_EMIT_OUTPUT_VTX_COMP_SEL: + case R200_EMIT_PP_TAM_DEBUG3: + case R200_EMIT_PP_CNTL_X: + case R200_EMIT_RB3D_DEPTHXY_OFFSET: + case R200_EMIT_RE_AUX_SCISSOR_CNTL: + case R200_EMIT_RE_SCISSOR_TL_0: + case R200_EMIT_RE_SCISSOR_TL_1: + case R200_EMIT_RE_SCISSOR_TL_2: + case R200_EMIT_SE_VAP_CNTL_STATUS: + case R200_EMIT_SE_VTX_STATE_CNTL: + case R200_EMIT_RE_POINTSIZE: + case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0: + case R200_EMIT_PP_CUBIC_FACES_0: + case R200_EMIT_PP_CUBIC_FACES_1: + case R200_EMIT_PP_CUBIC_FACES_2: + case R200_EMIT_PP_CUBIC_FACES_3: + case R200_EMIT_PP_CUBIC_FACES_4: + case R200_EMIT_PP_CUBIC_FACES_5: + case RADEON_EMIT_PP_TEX_SIZE_0: + case RADEON_EMIT_PP_TEX_SIZE_1: + case RADEON_EMIT_PP_TEX_SIZE_2: + case R200_EMIT_RB3D_BLENDCOLOR: + case R200_EMIT_TCL_POINT_SPRITE_CNTL: + case RADEON_EMIT_PP_CUBIC_FACES_0: + case RADEON_EMIT_PP_CUBIC_FACES_1: + case RADEON_EMIT_PP_CUBIC_FACES_2: + case R200_EMIT_PP_TRI_PERF_CNTL: + case R200_EMIT_PP_AFS_0: + case R200_EMIT_PP_AFS_1: + case R200_EMIT_ATF_TFACTOR: + case R200_EMIT_PP_TXCTLALL_0: + case R200_EMIT_PP_TXCTLALL_1: + case R200_EMIT_PP_TXCTLALL_2: + case R200_EMIT_PP_TXCTLALL_3: + case R200_EMIT_PP_TXCTLALL_4: + case R200_EMIT_PP_TXCTLALL_5: + case R200_EMIT_VAP_PVS_CNTL: + /* These packets don't contain memory offsets */ + break; + + default: + DRM_ERROR("Unknown state packet ID %d\n", id); + return -EINVAL; + } + + return 0; +} + +static int radeon_check_and_fixup_packet3(drm_radeon_private_t * + dev_priv, + struct drm_file *file_priv, + drm_radeon_kcmd_buffer_t * + cmdbuf, + unsigned int *cmdsz) +{ + u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); + u32 offset, narrays; + int count, i, k; + + count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16); + *cmdsz = 2 + count; + + if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) { + DRM_ERROR("Not a type 3 packet\n"); + return -EINVAL; + } + + if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) { + DRM_ERROR("Packet size larger than size of data provided\n"); + return -EINVAL; + } + + switch (*cmd & 0xff00) { + /* XXX Are there old drivers needing other packets? */ + + case RADEON_3D_DRAW_IMMD: + case RADEON_3D_DRAW_VBUF: + case RADEON_3D_DRAW_INDX: + case RADEON_WAIT_FOR_IDLE: + case RADEON_CP_NOP: + case RADEON_3D_CLEAR_ZMASK: +/* case RADEON_CP_NEXT_CHAR: + case RADEON_CP_PLY_NEXTSCAN: + case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ + /* these packets are safe */ + break; + + case RADEON_CP_3D_DRAW_IMMD_2: + case RADEON_CP_3D_DRAW_VBUF_2: + case RADEON_CP_3D_DRAW_INDX_2: + case RADEON_3D_CLEAR_HIZ: + /* safe but r200 only */ + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); + return -EINVAL; + } + break; + + case RADEON_3D_LOAD_VBPNTR: + + if (count > 18) { /* 12 arrays max */ + DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", + count); + return -EINVAL; + } + + /* carefully check packet contents */ + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + + narrays = *cmd & ~0xc000; + k = 0; + i = 2; + while ((k < narrays) && (i < (count + 2))) { + i++; /* skip attribute field */ + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + cmd)) { + DRM_ERROR + ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", + k, i); + return -EINVAL; + } + k++; + i++; + if (k == narrays) + break; + /* have one more to process, they come in pairs */ + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); + + if (radeon_check_and_fixup_offset(dev_priv, + file_priv, cmd)) + { + DRM_ERROR + ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", + k, i); + return -EINVAL; + } + k++; + i++; + } + /* do the counts match what we expect ? */ + if ((k != narrays) || (i != (count + 2))) { + DRM_ERROR + ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", + k, i, narrays, count + 1); + return -EINVAL; + } + break; + + case RADEON_3D_RNDR_GEN_INDX_PRIM: + if (dev_priv->microcode_version != UCODE_R100) { + DRM_ERROR("Invalid 3d packet for r200-class chip\n"); + return -EINVAL; + } + + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) { + DRM_ERROR("Invalid rndr_gen_indx offset\n"); + return -EINVAL; + } + break; + + case RADEON_CP_INDX_BUFFER: + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); + return -EINVAL; + } + + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + if ((*cmd & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd); + return -EINVAL; + } + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); + if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd); + return -EINVAL; + } + break; + + case RADEON_CNTL_HOSTDATA_BLT: + case RADEON_CNTL_PAINT_MULTI: + case RADEON_CNTL_BITBLT_MULTI: + /* MSB of opcode: next DWORD GUI_CNTL */ + cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); + if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL + | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { + u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); + offset = *cmd2 << 10; + if (radeon_check_and_fixup_offset + (dev_priv, file_priv, &offset)) { + DRM_ERROR("Invalid first packet offset\n"); + return -EINVAL; + } + *cmd2 = (*cmd2 & 0xffc00000) | offset >> 10; + } + + if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && + (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { + u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); + offset = *cmd3 << 10; + if (radeon_check_and_fixup_offset + (dev_priv, file_priv, &offset)) { + DRM_ERROR("Invalid second packet offset\n"); + return -EINVAL; + } + *cmd3 = (*cmd3 & 0xffc00000) | offset >> 10; + } + break; + + default: + DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00); + return -EINVAL; + } + + return 0; +} + +/* ================================================================ + * CP hardware state programming functions + */ + +static void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv, + struct drm_clip_rect * box) +{ + RING_LOCALS; + + DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n", + box->x1, box->y1, box->x2, box->y2); + + BEGIN_RING(4); + OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0)); + OUT_RING((box->y1 << 16) | box->x1); + OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0)); + OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1)); + ADVANCE_RING(); +} + +/* Emit 1.1 state + */ +static int radeon_emit_state(drm_radeon_private_t * dev_priv, + struct drm_file *file_priv, + drm_radeon_context_regs_t * ctx, + drm_radeon_texture_regs_t * tex, + unsigned int dirty) +{ + RING_LOCALS; + DRM_DEBUG("dirty=0x%08x\n", dirty); + + if (dirty & RADEON_UPLOAD_CONTEXT) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + &ctx->rb3d_depthoffset)) { + DRM_ERROR("Invalid depth buffer offset\n"); + return -EINVAL; + } + + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + &ctx->rb3d_coloroffset)) { + DRM_ERROR("Invalid depth buffer offset\n"); + return -EINVAL; + } + + BEGIN_RING(14); + OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6)); + OUT_RING(ctx->pp_misc); + OUT_RING(ctx->pp_fog_color); + OUT_RING(ctx->re_solid_color); + OUT_RING(ctx->rb3d_blendcntl); + OUT_RING(ctx->rb3d_depthoffset); + OUT_RING(ctx->rb3d_depthpitch); + OUT_RING(ctx->rb3d_zstencilcntl); + OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2)); + OUT_RING(ctx->pp_cntl); + OUT_RING(ctx->rb3d_cntl); + OUT_RING(ctx->rb3d_coloroffset); + OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); + OUT_RING(ctx->rb3d_colorpitch); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_VERTFMT) { + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0)); + OUT_RING(ctx->se_coord_fmt); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_LINE) { + BEGIN_RING(5); + OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1)); + OUT_RING(ctx->re_line_pattern); + OUT_RING(ctx->re_line_state); + OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0)); + OUT_RING(ctx->se_line_width); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_BUMPMAP) { + BEGIN_RING(5); + OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0)); + OUT_RING(ctx->pp_lum_matrix); + OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1)); + OUT_RING(ctx->pp_rot_matrix_0); + OUT_RING(ctx->pp_rot_matrix_1); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_MASKS) { + BEGIN_RING(4); + OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2)); + OUT_RING(ctx->rb3d_stencilrefmask); + OUT_RING(ctx->rb3d_ropcntl); + OUT_RING(ctx->rb3d_planemask); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_VIEWPORT) { + BEGIN_RING(7); + OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5)); + OUT_RING(ctx->se_vport_xscale); + OUT_RING(ctx->se_vport_xoffset); + OUT_RING(ctx->se_vport_yscale); + OUT_RING(ctx->se_vport_yoffset); + OUT_RING(ctx->se_vport_zscale); + OUT_RING(ctx->se_vport_zoffset); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_SETUP) { + BEGIN_RING(4); + OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0)); + OUT_RING(ctx->se_cntl); + OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0)); + OUT_RING(ctx->se_cntl_status); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_MISC) { + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0)); + OUT_RING(ctx->re_misc); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_TEX0) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + &tex[0].pp_txoffset)) { + DRM_ERROR("Invalid texture offset for unit 0\n"); + return -EINVAL; + } + + BEGIN_RING(9); + OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5)); + OUT_RING(tex[0].pp_txfilter); + OUT_RING(tex[0].pp_txformat); + OUT_RING(tex[0].pp_txoffset); + OUT_RING(tex[0].pp_txcblend); + OUT_RING(tex[0].pp_txablend); + OUT_RING(tex[0].pp_tfactor); + OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0)); + OUT_RING(tex[0].pp_border_color); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_TEX1) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + &tex[1].pp_txoffset)) { + DRM_ERROR("Invalid texture offset for unit 1\n"); + return -EINVAL; + } + + BEGIN_RING(9); + OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5)); + OUT_RING(tex[1].pp_txfilter); + OUT_RING(tex[1].pp_txformat); + OUT_RING(tex[1].pp_txoffset); + OUT_RING(tex[1].pp_txcblend); + OUT_RING(tex[1].pp_txablend); + OUT_RING(tex[1].pp_tfactor); + OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0)); + OUT_RING(tex[1].pp_border_color); + ADVANCE_RING(); + } + + if (dirty & RADEON_UPLOAD_TEX2) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + &tex[2].pp_txoffset)) { + DRM_ERROR("Invalid texture offset for unit 2\n"); + return -EINVAL; + } + + BEGIN_RING(9); + OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5)); + OUT_RING(tex[2].pp_txfilter); + OUT_RING(tex[2].pp_txformat); + OUT_RING(tex[2].pp_txoffset); + OUT_RING(tex[2].pp_txcblend); + OUT_RING(tex[2].pp_txablend); + OUT_RING(tex[2].pp_tfactor); + OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0)); + OUT_RING(tex[2].pp_border_color); + ADVANCE_RING(); + } + + return 0; +} + +/* Emit 1.2 state + */ +static int radeon_emit_state2(drm_radeon_private_t * dev_priv, + struct drm_file *file_priv, + drm_radeon_state_t * state) +{ + RING_LOCALS; + + if (state->dirty & RADEON_UPLOAD_ZBIAS) { + BEGIN_RING(3); + OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1)); + OUT_RING(state->context2.se_zbias_factor); + OUT_RING(state->context2.se_zbias_constant); + ADVANCE_RING(); + } + + return radeon_emit_state(dev_priv, file_priv, &state->context, + state->tex, state->dirty); +} + +/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in + * 1.3 cmdbuffers allow all previous state to be updated as well as + * the tcl scalar and vector areas. + */ +static struct { + int start; + int len; + const char *name; +} packet[RADEON_MAX_STATE_PACKETS] = { + {RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, + {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, + {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, + {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, + {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, + {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, + {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, + {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, + {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, + {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, + {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, + {RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, + {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, + {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, + {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, + {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, + {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, + {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, + {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, + {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, + {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, + "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, + {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, + {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, + {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, + {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, + {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, + {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, + {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, + {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, + {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, + {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, + {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, + {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, + {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, + {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, + {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, + {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, + {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, + {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, + {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, + {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, + {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, + {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, + {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, + {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, + {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, + {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, + {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, + {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, + {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, + "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, + {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, + {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, + {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, + {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, + {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, + {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, + {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, + {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, + {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, + {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, + {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, + "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, + {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ + {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ + {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, + {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, + {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, + {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, + {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, + {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, + {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, + {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, + {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, + {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, + {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, + {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, + {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, + {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, + {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, + {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, + {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, + {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, + {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, + {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, + {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, + {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, + {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */ + {R200_PP_AFS_1, 32, "R200_PP_AFS_1"}, + {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, + {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, + {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, + {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, + {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, + {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, + {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, + {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, +}; + +/* ================================================================ + * Performance monitoring functions + */ + +static void radeon_clear_box(drm_radeon_private_t * dev_priv, + struct drm_radeon_master_private *master_priv, + int x, int y, int w, int h, int r, int g, int b) +{ + u32 color; + RING_LOCALS; + + x += master_priv->sarea_priv->boxes[0].x1; + y += master_priv->sarea_priv->boxes[0].y1; + + switch (dev_priv->color_fmt) { + case RADEON_COLOR_FORMAT_RGB565: + color = (((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); + break; + case RADEON_COLOR_FORMAT_ARGB8888: + default: + color = (((0xff) << 24) | (r << 16) | (g << 8) | b); + break; + } + + BEGIN_RING(4); + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); + OUT_RING(0xffffffff); + ADVANCE_RING(); + + BEGIN_RING(6); + + OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4)); + OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (dev_priv->color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); + + if (master_priv->sarea_priv->pfCurrentPage == 1) { + OUT_RING(dev_priv->front_pitch_offset); + } else { + OUT_RING(dev_priv->back_pitch_offset); + } + + OUT_RING(color); + + OUT_RING((x << 16) | y); + OUT_RING((w << 16) | h); + + ADVANCE_RING(); +} + +static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv, struct drm_radeon_master_private *master_priv) +{ + /* Collapse various things into a wait flag -- trying to + * guess if userspase slept -- better just to have them tell us. + */ + if (dev_priv->stats.last_frame_reads > 1 || + dev_priv->stats.last_clear_reads > dev_priv->stats.clears) { + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + } + + if (dev_priv->stats.freelist_loops) { + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + } + + /* Purple box for page flipping + */ + if (dev_priv->stats.boxes & RADEON_BOX_FLIP) + radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255); + + /* Red box if we have to wait for idle at any point + */ + if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE) + radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0); + + /* Blue box: lost context? + */ + + /* Yellow box for texture swaps + */ + if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD) + radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0); + + /* Green box if hardware never idles (as far as we can tell) + */ + if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) + radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0); + + /* Draw bars indicating number of buffers allocated + * (not a great measure, easily confused) + */ + if (dev_priv->stats.requested_bufs) { + if (dev_priv->stats.requested_bufs > 100) + dev_priv->stats.requested_bufs = 100; + + radeon_clear_box(dev_priv, master_priv, 4, 16, + dev_priv->stats.requested_bufs, 4, + 196, 128, 128); + } + + memset(&dev_priv->stats, 0, sizeof(dev_priv->stats)); + +} + +/* ================================================================ + * CP command dispatch functions + */ + +static void radeon_cp_dispatch_clear(struct drm_device * dev, + struct drm_master *master, + drm_radeon_clear_t * clear, + drm_radeon_clear_rect_t * depth_boxes) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; + int nbox = sarea_priv->nbox; + struct drm_clip_rect *pbox = sarea_priv->boxes; + unsigned int flags = clear->flags; + u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0; + int i; + RING_LOCALS; + DRM_DEBUG("flags = 0x%x\n", flags); + + dev_priv->stats.clears++; + + if (sarea_priv->pfCurrentPage == 1) { + unsigned int tmp = flags; + + flags &= ~(RADEON_FRONT | RADEON_BACK); + if (tmp & RADEON_FRONT) + flags |= RADEON_BACK; + if (tmp & RADEON_BACK) + flags |= RADEON_FRONT; + } + if (flags & (RADEON_DEPTH|RADEON_STENCIL)) { + if (!dev_priv->have_z_offset) { + DRM_ERROR("radeon: illegal depth clear request. Buggy mesa detected - please update.\n"); + flags &= ~(RADEON_DEPTH | RADEON_STENCIL); + } + } + + if (flags & (RADEON_FRONT | RADEON_BACK)) { + + BEGIN_RING(4); + + /* Ensure the 3D stream is idle before doing a + * 2D fill to clear the front or back buffer. + */ + RADEON_WAIT_UNTIL_3D_IDLE(); + + OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); + OUT_RING(clear->color_mask); + + ADVANCE_RING(); + + /* Make sure we restore the 3D state next time. + */ + sarea_priv->ctx_owner = 0; + + for (i = 0; i < nbox; i++) { + int x = pbox[i].x1; + int y = pbox[i].y1; + int w = pbox[i].x2 - x; + int h = pbox[i].y2 - y; + + DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n", + x, y, w, h, flags); + + if (flags & RADEON_FRONT) { + BEGIN_RING(6); + + OUT_RING(CP_PACKET3 + (RADEON_CNTL_PAINT_MULTI, 4)); + OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (dev_priv-> + color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_P | + RADEON_GMC_CLR_CMP_CNTL_DIS); + + OUT_RING(dev_priv->front_pitch_offset); + OUT_RING(clear->clear_color); + + OUT_RING((x << 16) | y); + OUT_RING((w << 16) | h); + + ADVANCE_RING(); + } + + if (flags & RADEON_BACK) { + BEGIN_RING(6); + + OUT_RING(CP_PACKET3 + (RADEON_CNTL_PAINT_MULTI, 4)); + OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (dev_priv-> + color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_P | + RADEON_GMC_CLR_CMP_CNTL_DIS); + + OUT_RING(dev_priv->back_pitch_offset); + OUT_RING(clear->clear_color); + + OUT_RING((x << 16) | y); + OUT_RING((w << 16) | h); + + ADVANCE_RING(); + } + } + } + + /* hyper z clear */ + /* no docs available, based on reverse engineering by Stephane Marchesin */ + if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) + && (flags & RADEON_CLEAR_FASTZ)) { + + int i; + int depthpixperline = + dev_priv->depth_fmt == + RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch / + 2) : (dev_priv-> + depth_pitch / 4); + + u32 clearmask; + + u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth | + ((clear->depth_mask & 0xff) << 24); + + /* Make sure we restore the 3D state next time. + * we haven't touched any "normal" state - still need this? + */ + sarea_priv->ctx_owner = 0; + + if ((dev_priv->flags & RADEON_HAS_HIERZ) + && (flags & RADEON_USE_HIERZ)) { + /* FIXME : reverse engineer that for Rx00 cards */ + /* FIXME : the mask supposedly contains low-res z values. So can't set + just to the max (0xff? or actually 0x3fff?), need to take z clear + value into account? */ + /* pattern seems to work for r100, though get slight + rendering errors with glxgears. If hierz is not enabled for r100, + only 4 bits which indicate clear (15,16,31,32, all zero) matter, the + other ones are ignored, and the same clear mask can be used. That's + very different behaviour than R200 which needs different clear mask + and different number of tiles to clear if hierz is enabled or not !?! + */ + clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f; + } else { + /* clear mask : chooses the clearing pattern. + rv250: could be used to clear only parts of macrotiles + (but that would get really complicated...)? + bit 0 and 1 (either or both of them ?!?!) are used to + not clear tile (or maybe one of the bits indicates if the tile is + compressed or not), bit 2 and 3 to not clear tile 1,...,. + Pattern is as follows: + | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29| + bits ------------------------------------------------- + | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31| + rv100: clearmask covers 2x8 4x1 tiles, but one clear still + covers 256 pixels ?!? + */ + clearmask = 0x0; + } + + BEGIN_RING(8); + RADEON_WAIT_UNTIL_2D_IDLE(); + OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE, + tempRB3D_DEPTHCLEARVALUE); + /* what offset is this exactly ? */ + OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0); + /* need ctlstat, otherwise get some strange black flickering */ + OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT, + RADEON_RB3D_ZC_FLUSH_ALL); + ADVANCE_RING(); + + for (i = 0; i < nbox; i++) { + int tileoffset, nrtilesx, nrtilesy, j; + /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ + if ((dev_priv->flags & RADEON_HAS_HIERZ) + && !(dev_priv->microcode_version == UCODE_R200)) { + /* FIXME : figure this out for r200 (when hierz is enabled). Or + maybe r200 actually doesn't need to put the low-res z value into + the tile cache like r100, but just needs to clear the hi-level z-buffer? + Works for R100, both with hierz and without. + R100 seems to operate on 2x1 8x8 tiles, but... + odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially + problematic with resolutions which are not 64 pix aligned? */ + tileoffset = + ((pbox[i].y1 >> 3) * depthpixperline + + pbox[i].x1) >> 6; + nrtilesx = + ((pbox[i].x2 & ~63) - + (pbox[i].x1 & ~63)) >> 4; + nrtilesy = + (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); + for (j = 0; j <= nrtilesy; j++) { + BEGIN_RING(4); + OUT_RING(CP_PACKET3 + (RADEON_3D_CLEAR_ZMASK, 2)); + /* first tile */ + OUT_RING(tileoffset * 8); + /* the number of tiles to clear */ + OUT_RING(nrtilesx + 4); + /* clear mask : chooses the clearing pattern. */ + OUT_RING(clearmask); + ADVANCE_RING(); + tileoffset += depthpixperline >> 6; + } + } else if (dev_priv->microcode_version == UCODE_R200) { + /* works for rv250. */ + /* find first macro tile (8x2 4x4 z-pixels on rv250) */ + tileoffset = + ((pbox[i].y1 >> 3) * depthpixperline + + pbox[i].x1) >> 5; + nrtilesx = + (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5); + nrtilesy = + (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); + for (j = 0; j <= nrtilesy; j++) { + BEGIN_RING(4); + OUT_RING(CP_PACKET3 + (RADEON_3D_CLEAR_ZMASK, 2)); + /* first tile */ + /* judging by the first tile offset needed, could possibly + directly address/clear 4x4 tiles instead of 8x2 * 4x4 + macro tiles, though would still need clear mask for + right/bottom if truly 4x4 granularity is desired ? */ + OUT_RING(tileoffset * 16); + /* the number of tiles to clear */ + OUT_RING(nrtilesx + 1); + /* clear mask : chooses the clearing pattern. */ + OUT_RING(clearmask); + ADVANCE_RING(); + tileoffset += depthpixperline >> 5; + } + } else { /* rv 100 */ + /* rv100 might not need 64 pix alignment, who knows */ + /* offsets are, hmm, weird */ + tileoffset = + ((pbox[i].y1 >> 4) * depthpixperline + + pbox[i].x1) >> 6; + nrtilesx = + ((pbox[i].x2 & ~63) - + (pbox[i].x1 & ~63)) >> 4; + nrtilesy = + (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4); + for (j = 0; j <= nrtilesy; j++) { + BEGIN_RING(4); + OUT_RING(CP_PACKET3 + (RADEON_3D_CLEAR_ZMASK, 2)); + OUT_RING(tileoffset * 128); + /* the number of tiles to clear */ + OUT_RING(nrtilesx + 4); + /* clear mask : chooses the clearing pattern. */ + OUT_RING(clearmask); + ADVANCE_RING(); + tileoffset += depthpixperline >> 6; + } + } + } + + /* TODO don't always clear all hi-level z tiles */ + if ((dev_priv->flags & RADEON_HAS_HIERZ) + && (dev_priv->microcode_version == UCODE_R200) + && (flags & RADEON_USE_HIERZ)) + /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ + /* FIXME : the mask supposedly contains low-res z values. So can't set + just to the max (0xff? or actually 0x3fff?), need to take z clear + value into account? */ + { + BEGIN_RING(4); + OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2)); + OUT_RING(0x0); /* First tile */ + OUT_RING(0x3cc0); + OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f); + ADVANCE_RING(); + } + } + + /* We have to clear the depth and/or stencil buffers by + * rendering a quad into just those buffers. Thus, we have to + * make sure the 3D engine is configured correctly. + */ + else if ((dev_priv->microcode_version == UCODE_R200) && + (flags & (RADEON_DEPTH | RADEON_STENCIL))) { + + int tempPP_CNTL; + int tempRE_CNTL; + int tempRB3D_CNTL; + int tempRB3D_ZSTENCILCNTL; + int tempRB3D_STENCILREFMASK; + int tempRB3D_PLANEMASK; + int tempSE_CNTL; + int tempSE_VTE_CNTL; + int tempSE_VTX_FMT_0; + int tempSE_VTX_FMT_1; + int tempSE_VAP_CNTL; + int tempRE_AUX_SCISSOR_CNTL; + + tempPP_CNTL = 0; + tempRE_CNTL = 0; + + tempRB3D_CNTL = depth_clear->rb3d_cntl; + + tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; + tempRB3D_STENCILREFMASK = 0x0; + + tempSE_CNTL = depth_clear->se_cntl; + + /* Disable TCL */ + + tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */ + (0x9 << + SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT)); + + tempRB3D_PLANEMASK = 0x0; + + tempRE_AUX_SCISSOR_CNTL = 0x0; + + tempSE_VTE_CNTL = + SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK; + + /* Vertex format (X, Y, Z, W) */ + tempSE_VTX_FMT_0 = + SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK | + SE_VTX_FMT_0__VTX_W0_PRESENT_MASK; + tempSE_VTX_FMT_1 = 0x0; + + /* + * Depth buffer specific enables + */ + if (flags & RADEON_DEPTH) { + /* Enable depth buffer */ + tempRB3D_CNTL |= RADEON_Z_ENABLE; + } else { + /* Disable depth buffer */ + tempRB3D_CNTL &= ~RADEON_Z_ENABLE; + } + + /* + * Stencil buffer specific enables + */ + if (flags & RADEON_STENCIL) { + tempRB3D_CNTL |= RADEON_STENCIL_ENABLE; + tempRB3D_STENCILREFMASK = clear->depth_mask; + } else { + tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE; + tempRB3D_STENCILREFMASK = 0x00000000; + } + + if (flags & RADEON_USE_COMP_ZBUF) { + tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | + RADEON_Z_DECOMPRESSION_ENABLE; + } + if (flags & RADEON_USE_HIERZ) { + tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; + } + + BEGIN_RING(26); + RADEON_WAIT_UNTIL_2D_IDLE(); + + OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL); + OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL); + OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL); + OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); + OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, + tempRB3D_STENCILREFMASK); + OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK); + OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL); + OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL); + OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0); + OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1); + OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL); + OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL); + ADVANCE_RING(); + + /* Make sure we restore the 3D state next time. + */ + sarea_priv->ctx_owner = 0; + + for (i = 0; i < nbox; i++) { + + /* Funny that this should be required -- + * sets top-left? + */ + radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); + + BEGIN_RING(14); + OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12)); + OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | + RADEON_PRIM_WALK_RING | + (3 << RADEON_NUM_VERTICES_SHIFT))); + OUT_RING(depth_boxes[i].ui[CLEAR_X1]); + OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); + OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); + OUT_RING(0x3f800000); + OUT_RING(depth_boxes[i].ui[CLEAR_X1]); + OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); + OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); + OUT_RING(0x3f800000); + OUT_RING(depth_boxes[i].ui[CLEAR_X2]); + OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); + OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); + OUT_RING(0x3f800000); + ADVANCE_RING(); + } + } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) { + + int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; + + rb3d_cntl = depth_clear->rb3d_cntl; + + if (flags & RADEON_DEPTH) { + rb3d_cntl |= RADEON_Z_ENABLE; + } else { + rb3d_cntl &= ~RADEON_Z_ENABLE; + } + + if (flags & RADEON_STENCIL) { + rb3d_cntl |= RADEON_STENCIL_ENABLE; + rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */ + } else { + rb3d_cntl &= ~RADEON_STENCIL_ENABLE; + rb3d_stencilrefmask = 0x00000000; + } + + if (flags & RADEON_USE_COMP_ZBUF) { + tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | + RADEON_Z_DECOMPRESSION_ENABLE; + } + if (flags & RADEON_USE_HIERZ) { + tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; + } + + BEGIN_RING(13); + RADEON_WAIT_UNTIL_2D_IDLE(); + + OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1)); + OUT_RING(0x00000000); + OUT_RING(rb3d_cntl); + + OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); + OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask); + OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000); + OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl); + ADVANCE_RING(); + + /* Make sure we restore the 3D state next time. + */ + sarea_priv->ctx_owner = 0; + + for (i = 0; i < nbox; i++) { + + /* Funny that this should be required -- + * sets top-left? + */ + radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); + + BEGIN_RING(15); + + OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13)); + OUT_RING(RADEON_VTX_Z_PRESENT | + RADEON_VTX_PKCOLOR_PRESENT); + OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | + RADEON_PRIM_WALK_RING | + RADEON_MAOS_ENABLE | + RADEON_VTX_FMT_RADEON_MODE | + (3 << RADEON_NUM_VERTICES_SHIFT))); + + OUT_RING(depth_boxes[i].ui[CLEAR_X1]); + OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); + OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); + OUT_RING(0x0); + + OUT_RING(depth_boxes[i].ui[CLEAR_X1]); + OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); + OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); + OUT_RING(0x0); + + OUT_RING(depth_boxes[i].ui[CLEAR_X2]); + OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); + OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); + OUT_RING(0x0); + + ADVANCE_RING(); + } + } + + /* Increment the clear counter. The client-side 3D driver must + * wait on this value before performing the clear ioctl. We + * need this because the card's so damned fast... + */ + sarea_priv->last_clear++; + + BEGIN_RING(4); + + RADEON_CLEAR_AGE(sarea_priv->last_clear); + RADEON_WAIT_UNTIL_IDLE(); + + ADVANCE_RING(); +} + +static void radeon_cp_dispatch_swap(struct drm_device *dev, struct drm_master *master) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + int nbox = sarea_priv->nbox; + struct drm_clip_rect *pbox = sarea_priv->boxes; + int i; + RING_LOCALS; + DRM_DEBUG("\n"); + + /* Do some trivial performance monitoring... + */ + if (dev_priv->do_boxes) + radeon_cp_performance_boxes(dev_priv, master_priv); + + /* Wait for the 3D stream to idle before dispatching the bitblt. + * This will prevent data corruption between the two streams. + */ + BEGIN_RING(2); + + RADEON_WAIT_UNTIL_3D_IDLE(); + + ADVANCE_RING(); + + for (i = 0; i < nbox; i++) { + int x = pbox[i].x1; + int y = pbox[i].y1; + int w = pbox[i].x2 - x; + int h = pbox[i].y2 - y; + + DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); + + BEGIN_RING(9); + + OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0)); + OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (dev_priv->color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); + + /* Make this work even if front & back are flipped: + */ + OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); + if (sarea_priv->pfCurrentPage == 0) { + OUT_RING(dev_priv->back_pitch_offset); + OUT_RING(dev_priv->front_pitch_offset); + } else { + OUT_RING(dev_priv->front_pitch_offset); + OUT_RING(dev_priv->back_pitch_offset); + } + + OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2)); + OUT_RING((x << 16) | y); + OUT_RING((x << 16) | y); + OUT_RING((w << 16) | h); + + ADVANCE_RING(); + } + + /* Increment the frame counter. The client-side 3D driver must + * throttle the framerate by waiting for this value before + * performing the swapbuffer ioctl. + */ + sarea_priv->last_frame++; + + BEGIN_RING(4); + + RADEON_FRAME_AGE(sarea_priv->last_frame); + RADEON_WAIT_UNTIL_2D_IDLE(); + + ADVANCE_RING(); +} + +void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle; + int offset = (master_priv->sarea_priv->pfCurrentPage == 1) + ? dev_priv->front_offset : dev_priv->back_offset; + RING_LOCALS; + DRM_DEBUG("pfCurrentPage=%d\n", + master_priv->sarea_priv->pfCurrentPage); + + /* Do some trivial performance monitoring... + */ + if (dev_priv->do_boxes) { + dev_priv->stats.boxes |= RADEON_BOX_FLIP; + radeon_cp_performance_boxes(dev_priv, master_priv); + } + + /* Update the frame offsets for both CRTCs + */ + BEGIN_RING(6); + + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING_REG(RADEON_CRTC_OFFSET, + ((sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7) + + offset); + OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base + + offset); + + ADVANCE_RING(); + + /* Increment the frame counter. The client-side 3D driver must + * throttle the framerate by waiting for this value before + * performing the swapbuffer ioctl. + */ + master_priv->sarea_priv->last_frame++; + master_priv->sarea_priv->pfCurrentPage = + 1 - master_priv->sarea_priv->pfCurrentPage; + + BEGIN_RING(2); + + RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame); + + ADVANCE_RING(); +} + +static int bad_prim_vertex_nr(int primitive, int nr) +{ + switch (primitive & RADEON_PRIM_TYPE_MASK) { + case RADEON_PRIM_TYPE_NONE: + case RADEON_PRIM_TYPE_POINT: + return nr < 1; + case RADEON_PRIM_TYPE_LINE: + return (nr & 1) || nr == 0; + case RADEON_PRIM_TYPE_LINE_STRIP: + return nr < 2; + case RADEON_PRIM_TYPE_TRI_LIST: + case RADEON_PRIM_TYPE_3VRT_POINT_LIST: + case RADEON_PRIM_TYPE_3VRT_LINE_LIST: + case RADEON_PRIM_TYPE_RECT_LIST: + return nr % 3 || nr == 0; + case RADEON_PRIM_TYPE_TRI_FAN: + case RADEON_PRIM_TYPE_TRI_STRIP: + return nr < 3; + default: + return 1; + } +} + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim; + unsigned int numverts; + unsigned int offset; + unsigned int vc_format; +} drm_radeon_tcl_prim_t; + +static void radeon_cp_dispatch_vertex(struct drm_device * dev, + struct drm_file *file_priv, + struct drm_buf * buf, + drm_radeon_tcl_prim_t * prim) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; + int numverts = (int)prim->numverts; + int nbox = sarea_priv->nbox; + int i = 0; + RING_LOCALS; + + DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", + prim->prim, + prim->vc_format, prim->start, prim->finish, prim->numverts); + + if (bad_prim_vertex_nr(prim->prim, prim->numverts)) { + DRM_ERROR("bad prim %x numverts %d\n", + prim->prim, prim->numverts); + return; + } + + do { + /* Emit the next cliprect */ + if (i < nbox) { + radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); + } + + /* Emit the vertex buffer rendering commands */ + BEGIN_RING(5); + + OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3)); + OUT_RING(offset); + OUT_RING(numverts); + OUT_RING(prim->vc_format); + OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST | + RADEON_COLOR_ORDER_RGBA | + RADEON_VTX_FMT_RADEON_MODE | + (numverts << RADEON_NUM_VERTICES_SHIFT)); + + ADVANCE_RING(); + + i++; + } while (i < nbox); +} + +void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_buf_priv_t *buf_priv = buf->dev_private; + RING_LOCALS; + + buf_priv->age = ++master_priv->sarea_priv->last_dispatch; + + /* Emit the vertex buffer age */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { + BEGIN_RING(3); + R600_DISPATCH_AGE(buf_priv->age); + ADVANCE_RING(); + } else { + BEGIN_RING(2); + RADEON_DISPATCH_AGE(buf_priv->age); + ADVANCE_RING(); + } + + buf->pending = 1; + buf->used = 0; +} + +static void radeon_cp_dispatch_indirect(struct drm_device * dev, + struct drm_buf * buf, int start, int end) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); + + if (start != end) { + int offset = (dev_priv->gart_buffers_offset + + buf->offset + start); + int dwords = (end - start + 3) / sizeof(u32); + + /* Indirect buffer data must be an even number of + * dwords, so if we've been given an odd number we must + * pad the data with a Type-2 CP packet. + */ + if (dwords & 1) { + u32 *data = (u32 *) + ((char *)dev->agp_buffer_map->handle + + buf->offset + start); + data[dwords++] = RADEON_CP_PACKET2; + } + + /* Fire off the indirect buffer */ + BEGIN_RING(3); + + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(offset); + OUT_RING(dwords); + + ADVANCE_RING(); + } +} + +static void radeon_cp_dispatch_indices(struct drm_device *dev, + struct drm_master *master, + struct drm_buf * elt_buf, + drm_radeon_tcl_prim_t * prim) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + int offset = dev_priv->gart_buffers_offset + prim->offset; + u32 *data; + int dwords; + int i = 0; + int start = prim->start + RADEON_INDEX_PRIM_OFFSET; + int count = (prim->finish - start) / sizeof(u16); + int nbox = sarea_priv->nbox; + + DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", + prim->prim, + prim->vc_format, + prim->start, prim->finish, prim->offset, prim->numverts); + + if (bad_prim_vertex_nr(prim->prim, count)) { + DRM_ERROR("bad prim %x count %d\n", prim->prim, count); + return; + } + + if (start >= prim->finish || (prim->start & 0x7)) { + DRM_ERROR("buffer prim %d\n", prim->prim); + return; + } + + dwords = (prim->finish - prim->start + 3) / sizeof(u32); + + data = (u32 *) ((char *)dev->agp_buffer_map->handle + + elt_buf->offset + prim->start); + + data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2); + data[1] = offset; + data[2] = prim->numverts; + data[3] = prim->vc_format; + data[4] = (prim->prim | + RADEON_PRIM_WALK_IND | + RADEON_COLOR_ORDER_RGBA | + RADEON_VTX_FMT_RADEON_MODE | + (count << RADEON_NUM_VERTICES_SHIFT)); + + do { + if (i < nbox) + radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); + + radeon_cp_dispatch_indirect(dev, elt_buf, + prim->start, prim->finish); + + i++; + } while (i < nbox); + +} + +#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE + +static int radeon_cp_dispatch_texture(struct drm_device * dev, + struct drm_file *file_priv, + drm_radeon_texture_t * tex, + drm_radeon_tex_image_t * image) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_buf *buf; + u32 format; + u32 *buffer; + const u8 __user *data; + int size, dwords, tex_width, blit_width, spitch; + u32 height; + int i; + u32 texpitch, microtile; + u32 offset, byte_offset; + RING_LOCALS; + + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { + DRM_ERROR("Invalid destination offset\n"); + return -EINVAL; + } + + dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; + + /* Flush the pixel cache. This ensures no pixel data gets mixed + * up with the texture data from the host data blit, otherwise + * part of the texture image may be corrupted. + */ + BEGIN_RING(4); + RADEON_FLUSH_CACHE(); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); + + /* The compiler won't optimize away a division by a variable, + * even if the only legal values are powers of two. Thus, we'll + * use a shift instead. + */ + switch (tex->format) { + case RADEON_TXFORMAT_ARGB8888: + case RADEON_TXFORMAT_RGBA8888: + format = RADEON_COLOR_FORMAT_ARGB8888; + tex_width = tex->width * 4; + blit_width = image->width * 4; + break; + case RADEON_TXFORMAT_AI88: + case RADEON_TXFORMAT_ARGB1555: + case RADEON_TXFORMAT_RGB565: + case RADEON_TXFORMAT_ARGB4444: + case RADEON_TXFORMAT_VYUY422: + case RADEON_TXFORMAT_YVYU422: + format = RADEON_COLOR_FORMAT_RGB565; + tex_width = tex->width * 2; + blit_width = image->width * 2; + break; + case RADEON_TXFORMAT_I8: + case RADEON_TXFORMAT_RGB332: + format = RADEON_COLOR_FORMAT_CI8; + tex_width = tex->width * 1; + blit_width = image->width * 1; + break; + default: + DRM_ERROR("invalid texture format %d\n", tex->format); + return -EINVAL; + } + spitch = blit_width >> 6; + if (spitch == 0 && image->height > 1) + return -EINVAL; + + texpitch = tex->pitch; + if ((texpitch << 22) & RADEON_DST_TILE_MICRO) { + microtile = 1; + if (tex_width < 64) { + texpitch &= ~(RADEON_DST_TILE_MICRO >> 22); + /* we got tiled coordinates, untile them */ + image->x *= 2; + } + } else + microtile = 0; + + /* this might fail for zero-sized uploads - are those illegal? */ + if (!radeon_check_offset(dev_priv, tex->offset + image->height * + blit_width - 1)) { + DRM_ERROR("Invalid final destination offset\n"); + return -EINVAL; + } + + DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width); + + do { + DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%u y=%u w=%u h=%u\n", + tex->offset >> 10, tex->pitch, tex->format, + image->x, image->y, image->width, image->height); + + /* Make a copy of some parameters in case we have to + * update them for a multi-pass texture blit. + */ + height = image->height; + data = (const u8 __user *)image->data; + + size = height * blit_width; + + if (size > RADEON_MAX_TEXTURE_SIZE) { + height = RADEON_MAX_TEXTURE_SIZE / blit_width; + size = height * blit_width; + } else if (size < 4 && size > 0) { + size = 4; + } else if (size == 0) { + return 0; + } + + buf = radeon_freelist_get(dev); + if (0 && !buf) { + radeon_do_cp_idle(dev_priv); + buf = radeon_freelist_get(dev); + } + if (!buf) { + DRM_DEBUG("EAGAIN\n"); + if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) + return -EFAULT; + return -EAGAIN; + } + + /* Dispatch the indirect buffer. + */ + buffer = + (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); + dwords = size / 4; + +#define RADEON_COPY_MT(_buf, _data, _width) \ + do { \ + if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ + DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ + return -EFAULT; \ + } \ + } while(0) + + if (microtile) { + /* texture micro tiling in use, minimum texture width is thus 16 bytes. + however, we cannot use blitter directly for texture width < 64 bytes, + since minimum tex pitch is 64 bytes and we need this to match + the texture width, otherwise the blitter will tile it wrong. + Thus, tiling manually in this case. Additionally, need to special + case tex height = 1, since our actual image will have height 2 + and we need to ensure we don't read beyond the texture size + from user space. */ + if (tex->height == 1) { + if (tex_width >= 64 || tex_width <= 16) { + RADEON_COPY_MT(buffer, data, + (int)(tex_width * sizeof(u32))); + } else if (tex_width == 32) { + RADEON_COPY_MT(buffer, data, 16); + RADEON_COPY_MT(buffer + 8, + data + 16, 16); + } + } else if (tex_width >= 64 || tex_width == 16) { + RADEON_COPY_MT(buffer, data, + (int)(dwords * sizeof(u32))); + } else if (tex_width < 16) { + for (i = 0; i < tex->height; i++) { + RADEON_COPY_MT(buffer, data, tex_width); + buffer += 4; + data += tex_width; + } + } else if (tex_width == 32) { + /* TODO: make sure this works when not fitting in one buffer + (i.e. 32bytes x 2048...) */ + for (i = 0; i < tex->height; i += 2) { + RADEON_COPY_MT(buffer, data, 16); + data += 16; + RADEON_COPY_MT(buffer + 8, data, 16); + data += 16; + RADEON_COPY_MT(buffer + 4, data, 16); + data += 16; + RADEON_COPY_MT(buffer + 12, data, 16); + data += 16; + buffer += 16; + } + } + } else { + if (tex_width >= 32) { + /* Texture image width is larger than the minimum, so we + * can upload it directly. + */ + RADEON_COPY_MT(buffer, data, + (int)(dwords * sizeof(u32))); + } else { + /* Texture image width is less than the minimum, so we + * need to pad out each image scanline to the minimum + * width. + */ + for (i = 0; i < tex->height; i++) { + RADEON_COPY_MT(buffer, data, tex_width); + buffer += 8; + data += tex_width; + } + } + } + +#undef RADEON_COPY_MT + byte_offset = (image->y & ~2047) * blit_width; + buf->file_priv = file_priv; + buf->used = size; + offset = dev_priv->gart_buffers_offset + buf->offset; + BEGIN_RING(9); + OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); + OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (format << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); + OUT_RING((spitch << 22) | (offset >> 10)); + OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10))); + OUT_RING(0); + OUT_RING((image->x << 16) | (image->y % 2048)); + OUT_RING((image->width << 16) | height); + RADEON_WAIT_UNTIL_2D_IDLE(); + ADVANCE_RING(); + COMMIT_RING(); + + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + + /* Update the input parameters for next time */ + image->y += height; + image->height -= height; + image->data = (const u8 __user *)image->data + size; + } while (image->height > 0); + + /* Flush the pixel cache after the blit completes. This ensures + * the texture data is written out to memory before rendering + * continues. + */ + BEGIN_RING(4); + RADEON_FLUSH_CACHE(); + RADEON_WAIT_UNTIL_2D_IDLE(); + ADVANCE_RING(); + COMMIT_RING(); + + return 0; +} + +static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int i; + RING_LOCALS; + DRM_DEBUG("\n"); + + BEGIN_RING(35); + + OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0)); + OUT_RING(0x00000000); + + OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31)); + for (i = 0; i < 32; i++) { + OUT_RING(stipple[i]); + } + + ADVANCE_RING(); +} + +static void radeon_apply_surface_regs(int surf_index, + drm_radeon_private_t *dev_priv) +{ + if (!dev_priv->mmio) + return; + + radeon_do_cp_idle(dev_priv); + + RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index, + dev_priv->surfaces[surf_index].flags); + RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index, + dev_priv->surfaces[surf_index].lower); + RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index, + dev_priv->surfaces[surf_index].upper); +} + +/* Allocates a virtual surface + * doesn't always allocate a real surface, will stretch an existing + * surface when possible. + * + * Note that refcount can be at most 2, since during a free refcount=3 + * might mean we have to allocate a new surface which might not always + * be available. + * For example : we allocate three contiguous surfaces ABC. If B is + * freed, we suddenly need two surfaces to store A and C, which might + * not always be available. + */ +static int alloc_surface(drm_radeon_surface_alloc_t *new, + drm_radeon_private_t *dev_priv, + struct drm_file *file_priv) +{ + struct radeon_virt_surface *s; + int i; + int virt_surface_index; + uint32_t new_upper, new_lower; + + new_lower = new->address; + new_upper = new_lower + new->size - 1; + + /* sanity check */ + if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) || + ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != + RADEON_SURF_ADDRESS_FIXED_MASK) + || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0)) + return -1; + + /* make sure there is no overlap with existing surfaces */ + for (i = 0; i < RADEON_MAX_SURFACES; i++) { + if ((dev_priv->surfaces[i].refcount != 0) && + (((new_lower >= dev_priv->surfaces[i].lower) && + (new_lower < dev_priv->surfaces[i].upper)) || + ((new_lower < dev_priv->surfaces[i].lower) && + (new_upper > dev_priv->surfaces[i].lower)))) { + return -1; + } + } + + /* find a virtual surface */ + for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) + if (dev_priv->virt_surfaces[i].file_priv == NULL) + break; + if (i == 2 * RADEON_MAX_SURFACES) { + return -1; + } + virt_surface_index = i; + + /* try to reuse an existing surface */ + for (i = 0; i < RADEON_MAX_SURFACES; i++) { + /* extend before */ + if ((dev_priv->surfaces[i].refcount == 1) && + (new->flags == dev_priv->surfaces[i].flags) && + (new_upper + 1 == dev_priv->surfaces[i].lower)) { + s = &(dev_priv->virt_surfaces[virt_surface_index]); + s->surface_index = i; + s->lower = new_lower; + s->upper = new_upper; + s->flags = new->flags; + s->file_priv = file_priv; + dev_priv->surfaces[i].refcount++; + dev_priv->surfaces[i].lower = s->lower; + radeon_apply_surface_regs(s->surface_index, dev_priv); + return virt_surface_index; + } + + /* extend after */ + if ((dev_priv->surfaces[i].refcount == 1) && + (new->flags == dev_priv->surfaces[i].flags) && + (new_lower == dev_priv->surfaces[i].upper + 1)) { + s = &(dev_priv->virt_surfaces[virt_surface_index]); + s->surface_index = i; + s->lower = new_lower; + s->upper = new_upper; + s->flags = new->flags; + s->file_priv = file_priv; + dev_priv->surfaces[i].refcount++; + dev_priv->surfaces[i].upper = s->upper; + radeon_apply_surface_regs(s->surface_index, dev_priv); + return virt_surface_index; + } + } + + /* okay, we need a new one */ + for (i = 0; i < RADEON_MAX_SURFACES; i++) { + if (dev_priv->surfaces[i].refcount == 0) { + s = &(dev_priv->virt_surfaces[virt_surface_index]); + s->surface_index = i; + s->lower = new_lower; + s->upper = new_upper; + s->flags = new->flags; + s->file_priv = file_priv; + dev_priv->surfaces[i].refcount = 1; + dev_priv->surfaces[i].lower = s->lower; + dev_priv->surfaces[i].upper = s->upper; + dev_priv->surfaces[i].flags = s->flags; + radeon_apply_surface_regs(s->surface_index, dev_priv); + return virt_surface_index; + } + } + + /* we didn't find anything */ + return -1; +} + +static int free_surface(struct drm_file *file_priv, + drm_radeon_private_t * dev_priv, + int lower) +{ + struct radeon_virt_surface *s; + int i; + /* find the virtual surface */ + for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { + s = &(dev_priv->virt_surfaces[i]); + if (s->file_priv) { + if ((lower == s->lower) && (file_priv == s->file_priv)) + { + if (dev_priv->surfaces[s->surface_index]. + lower == s->lower) + dev_priv->surfaces[s->surface_index]. + lower = s->upper; + + if (dev_priv->surfaces[s->surface_index]. + upper == s->upper) + dev_priv->surfaces[s->surface_index]. + upper = s->lower; + + dev_priv->surfaces[s->surface_index].refcount--; + if (dev_priv->surfaces[s->surface_index]. + refcount == 0) + dev_priv->surfaces[s->surface_index]. + flags = 0; + s->file_priv = NULL; + radeon_apply_surface_regs(s->surface_index, + dev_priv); + return 0; + } + } + } + return 1; +} + +static void radeon_surfaces_release(struct drm_file *file_priv, + drm_radeon_private_t * dev_priv) +{ + int i; + for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { + if (dev_priv->virt_surfaces[i].file_priv == file_priv) + free_surface(file_priv, dev_priv, + dev_priv->virt_surfaces[i].lower); + } +} + +/* ================================================================ + * IOCTL functions + */ +static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_surface_alloc_t *alloc = data; + + if (alloc_surface(alloc, dev_priv, file_priv) == -1) + return -EINVAL; + else + return 0; +} + +static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_surface_free_t *memfree = data; + + if (free_surface(file_priv, dev_priv, memfree->address)) + return -EINVAL; + else + return 0; +} + +static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + drm_radeon_clear_t *clear = data; + drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) + sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; + + if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, + sarea_priv->nbox * sizeof(depth_boxes[0]))) + return -EFAULT; + + radeon_cp_dispatch_clear(dev, file_priv->masterp, clear, depth_boxes); + + COMMIT_RING(); + return 0; +} + +/* Not sure why this isn't set all the time: + */ +static int radeon_do_init_pageflip(struct drm_device *dev, struct drm_master *master) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + RING_LOCALS; + + DRM_DEBUG("\n"); + + BEGIN_RING(6); + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0)); + OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) | + RADEON_CRTC_OFFSET_FLIP_CNTL); + OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0)); + OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) | + RADEON_CRTC_OFFSET_FLIP_CNTL); + ADVANCE_RING(); + + dev_priv->page_flipping = 1; + + if (master_priv->sarea_priv->pfCurrentPage != 1) + master_priv->sarea_priv->pfCurrentPage = 0; + + return 0; +} + +/* Swapping and flipping are different operations, need different ioctls. + * They can & should be intermixed to support multiple 3d windows. + */ +static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + + if (!dev_priv->page_flipping) + radeon_do_init_pageflip(dev, file_priv->masterp); + + radeon_cp_dispatch_flip(dev, file_priv->masterp); + + COMMIT_RING(); + return 0; +} + +static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + + DRM_DEBUG("\n"); + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) + sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_cp_dispatch_swap(dev, file_priv); + else + radeon_cp_dispatch_swap(dev, file_priv->masterp); + sarea_priv->ctx_owner = 0; + + COMMIT_RING(); + return 0; +} + +static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_sarea_t *sarea_priv; + struct drm_device_dma *dma = dev->dma; + struct drm_buf *buf; + drm_radeon_vertex_t *vertex = data; + drm_radeon_tcl_prim_t prim; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + sarea_priv = master_priv->sarea_priv; + + DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", + DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); + + if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + vertex->idx, dma->buf_count - 1); + return -EINVAL; + } + if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { + DRM_ERROR("buffer prim %d\n", vertex->prim); + return -EINVAL; + } + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + VB_AGE_TEST_WITH_RETURN(dev_priv); + + buf = dma->buflist[vertex->idx]; + + if (buf->file_priv != file_priv) { + DRM_ERROR("process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; + } + if (buf->pending) { + DRM_ERROR("sending pending buffer %d\n", vertex->idx); + return -EINVAL; + } + + /* Build up a prim_t record: + */ + if (vertex->count) { + buf->used = vertex->count; /* not used? */ + + if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { + if (radeon_emit_state(dev_priv, file_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty)) { + DRM_ERROR("radeon_emit_state failed\n"); + return -EINVAL; + } + + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES | + RADEON_UPLOAD_TEX2IMAGES | + RADEON_REQUIRE_QUIESCENCE); + } + + prim.start = 0; + prim.finish = vertex->count; /* unused */ + prim.prim = vertex->prim; + prim.numverts = vertex->count; + prim.vc_format = sarea_priv->vc_format; + + radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim); + } + + if (vertex->discard) { + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + } + + COMMIT_RING(); + return 0; +} + +static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_sarea_t *sarea_priv; + struct drm_device_dma *dma = dev->dma; + struct drm_buf *buf; + drm_radeon_indices_t *elts = data; + drm_radeon_tcl_prim_t prim; + int count; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + sarea_priv = master_priv->sarea_priv; + + DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", + DRM_CURRENTPID, elts->idx, elts->start, elts->end, + elts->discard); + + if (elts->idx < 0 || elts->idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + elts->idx, dma->buf_count - 1); + return -EINVAL; + } + if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { + DRM_ERROR("buffer prim %d\n", elts->prim); + return -EINVAL; + } + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + VB_AGE_TEST_WITH_RETURN(dev_priv); + + buf = dma->buflist[elts->idx]; + + if (buf->file_priv != file_priv) { + DRM_ERROR("process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; + } + if (buf->pending) { + DRM_ERROR("sending pending buffer %d\n", elts->idx); + return -EINVAL; + } + + count = (elts->end - elts->start) / sizeof(u16); + elts->start -= RADEON_INDEX_PRIM_OFFSET; + + if (elts->start & 0x7) { + DRM_ERROR("misaligned buffer 0x%x\n", elts->start); + return -EINVAL; + } + if (elts->start < buf->used) { + DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); + return -EINVAL; + } + + buf->used = elts->end; + + if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { + if (radeon_emit_state(dev_priv, file_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty)) { + DRM_ERROR("radeon_emit_state failed\n"); + return -EINVAL; + } + + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES | + RADEON_UPLOAD_TEX2IMAGES | + RADEON_REQUIRE_QUIESCENCE); + } + + /* Build up a prim_t record: + */ + prim.start = elts->start; + prim.finish = elts->end; + prim.prim = elts->prim; + prim.offset = 0; /* offset from start of dma buffers */ + prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + prim.vc_format = sarea_priv->vc_format; + + radeon_cp_dispatch_indices(dev, file_priv->masterp, buf, &prim); + if (elts->discard) { + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + } + + COMMIT_RING(); + return 0; +} + +static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_texture_t *tex = data; + drm_radeon_tex_image_t image; + int ret; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if (tex->image == NULL) { + DRM_ERROR("null texture image!\n"); + return -EINVAL; + } + + if (DRM_COPY_FROM_USER(&image, + (drm_radeon_tex_image_t __user *) tex->image, + sizeof(image))) + return -EFAULT; + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + VB_AGE_TEST_WITH_RETURN(dev_priv); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + ret = r600_cp_dispatch_texture(dev, file_priv, tex, &image); + else + ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image); + + return ret; +} + +static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_stipple_t *stipple = data; + u32 mask[32]; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) + return -EFAULT; + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + + radeon_cp_dispatch_stipple(dev, mask); + + COMMIT_RING(); + return 0; +} + +static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_device_dma *dma = dev->dma; + struct drm_buf *buf; + drm_radeon_indirect_t *indirect = data; + RING_LOCALS; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", + indirect->idx, indirect->start, indirect->end, + indirect->discard); + + if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + indirect->idx, dma->buf_count - 1); + return -EINVAL; + } + + buf = dma->buflist[indirect->idx]; + + if (buf->file_priv != file_priv) { + DRM_ERROR("process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; + } + if (buf->pending) { + DRM_ERROR("sending pending buffer %d\n", indirect->idx); + return -EINVAL; + } + + if (indirect->start < buf->used) { + DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", + indirect->start, buf->used); + return -EINVAL; + } + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + VB_AGE_TEST_WITH_RETURN(dev_priv); + + buf->used = indirect->end; + + /* Dispatch the indirect buffer full of commands from the + * X server. This is insecure and is thus only available to + * privileged clients. + */ + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); + else { + /* Wait for the 3D stream to idle before the indirect buffer + * containing 2D acceleration commands is processed. + */ + BEGIN_RING(2); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); + } + + if (indirect->discard) { + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + } + + COMMIT_RING(); + return 0; +} + +static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_sarea_t *sarea_priv; + struct drm_device_dma *dma = dev->dma; + struct drm_buf *buf; + drm_radeon_vertex2_t *vertex = data; + int i; + unsigned char laststate; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + sarea_priv = master_priv->sarea_priv; + + DRM_DEBUG("pid=%d index=%d discard=%d\n", + DRM_CURRENTPID, vertex->idx, vertex->discard); + + if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + vertex->idx, dma->buf_count - 1); + return -EINVAL; + } + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + VB_AGE_TEST_WITH_RETURN(dev_priv); + + buf = dma->buflist[vertex->idx]; + + if (buf->file_priv != file_priv) { + DRM_ERROR("process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; + } + + if (buf->pending) { + DRM_ERROR("sending pending buffer %d\n", vertex->idx); + return -EINVAL; + } + + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) + return -EINVAL; + + for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) { + drm_radeon_prim_t prim; + drm_radeon_tcl_prim_t tclprim; + + if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim))) + return -EFAULT; + + if (prim.stateidx != laststate) { + drm_radeon_state_t state; + + if (DRM_COPY_FROM_USER(&state, + &vertex->state[prim.stateidx], + sizeof(state))) + return -EFAULT; + + if (radeon_emit_state2(dev_priv, file_priv, &state)) { + DRM_ERROR("radeon_emit_state2 failed\n"); + return -EINVAL; + } + + laststate = prim.stateidx; + } + + tclprim.start = prim.start; + tclprim.finish = prim.finish; + tclprim.prim = prim.prim; + tclprim.vc_format = prim.vc_format; + + if (prim.prim & RADEON_PRIM_WALK_IND) { + tclprim.offset = prim.numverts * 64; + tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + + radeon_cp_dispatch_indices(dev, file_priv->masterp, buf, &tclprim); + } else { + tclprim.numverts = prim.numverts; + tclprim.offset = 0; /* not used */ + + radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim); + } + + if (sarea_priv->nbox == 1) + sarea_priv->nbox = 0; + } + + if (vertex->discard) { + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + } + + COMMIT_RING(); + return 0; +} + +static int radeon_emit_packets(drm_radeon_private_t * dev_priv, + struct drm_file *file_priv, + drm_radeon_cmd_header_t header, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + int id = (int)header.packet.packet_id; + int sz, reg; + RING_LOCALS; + + if (id >= RADEON_MAX_STATE_PACKETS) + return -EINVAL; + + sz = packet[id].len; + reg = packet[id].start; + + if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) { + DRM_ERROR("Packet size provided larger than data provided\n"); + return -EINVAL; + } + + if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, + cmdbuf->buffer)) { + DRM_ERROR("Packet verification failed\n"); + return -EINVAL; + } + + BEGIN_RING(sz + 1); + OUT_RING(CP_PACKET0(reg, (sz - 1))); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + + return 0; +} + +static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + int sz = header.scalars.count; + int start = header.scalars.offset; + int stride = header.scalars.stride; + RING_LOCALS; + + BEGIN_RING(3 + sz); + OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); + OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); + OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + return 0; +} + +/* God this is ugly + */ +static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + int sz = header.scalars.count; + int start = ((unsigned int)header.scalars.offset) + 0x100; + int stride = header.scalars.stride; + RING_LOCALS; + + BEGIN_RING(3 + sz); + OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); + OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); + OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + return 0; +} + +static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + int sz = header.vectors.count; + int start = header.vectors.offset; + int stride = header.vectors.stride; + RING_LOCALS; + + BEGIN_RING(5 + sz); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); + OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); + OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + + return 0; +} + +static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + int sz = header.veclinear.count * 4; + int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); + RING_LOCALS; + + if (!sz) + return 0; + if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) + return -EINVAL; + + BEGIN_RING(5 + sz); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); + OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); + OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); + ADVANCE_RING(); + + return 0; +} + +static int radeon_emit_packet3(struct drm_device * dev, + struct drm_file *file_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + unsigned int cmdsz; + int ret; + RING_LOCALS; + + DRM_DEBUG("\n"); + + if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, + cmdbuf, &cmdsz))) { + DRM_ERROR("Packet verification failed\n"); + return ret; + } + + BEGIN_RING(cmdsz); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz); + ADVANCE_RING(); + + return 0; +} + +static int radeon_emit_packet3_cliprect(struct drm_device *dev, + struct drm_file *file_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + int orig_nbox) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_clip_rect box; + unsigned int cmdsz; + int ret; + struct drm_clip_rect __user *boxes = cmdbuf->boxes; + int i = 0; + RING_LOCALS; + + DRM_DEBUG("\n"); + + if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, + cmdbuf, &cmdsz))) { + DRM_ERROR("Packet verification failed\n"); + return ret; + } + + if (!orig_nbox) + goto out; + + do { + if (i < cmdbuf->nbox) { + if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box))) + return -EFAULT; + /* FIXME The second and subsequent times round + * this loop, send a WAIT_UNTIL_3D_IDLE before + * calling emit_clip_rect(). This fixes a + * lockup on fast machines when sending + * several cliprects with a cmdbuf, as when + * waving a 2D window over a 3D + * window. Something in the commands from user + * space seems to hang the card when they're + * sent several times in a row. That would be + * the correct place to fix it but this works + * around it until I can figure that out - Tim + * Smith */ + if (i) { + BEGIN_RING(2); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + } + radeon_emit_clip_rect(dev_priv, &box); + } + + BEGIN_RING(cmdsz); + OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz); + ADVANCE_RING(); + + } while (++i < cmdbuf->nbox); + if (cmdbuf->nbox == 1) + cmdbuf->nbox = 0; + + return 0; + out: + drm_buffer_advance(cmdbuf->buffer, cmdsz * 4); + return 0; +} + +static int radeon_emit_wait(struct drm_device * dev, int flags) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG("%x\n", flags); + switch (flags) { + case RADEON_WAIT_2D: + BEGIN_RING(2); + RADEON_WAIT_UNTIL_2D_IDLE(); + ADVANCE_RING(); + break; + case RADEON_WAIT_3D: + BEGIN_RING(2); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + break; + case RADEON_WAIT_2D | RADEON_WAIT_3D: + BEGIN_RING(2); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_device_dma *dma = dev->dma; + struct drm_buf *buf = NULL; + drm_radeon_cmd_header_t stack_header; + int idx; + drm_radeon_kcmd_buffer_t *cmdbuf = data; + int orig_nbox; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + RING_SPACE_TEST_WITH_RETURN(dev_priv); + VB_AGE_TEST_WITH_RETURN(dev_priv); + + if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) { + return -EINVAL; + } + + /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid + * races between checking values and using those values in other code, + * and simply to avoid a lot of function calls to copy in data. + */ + if (cmdbuf->bufsz != 0) { + int rv; + void __user *buffer = cmdbuf->buffer; + rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz); + if (rv) + return rv; + rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer, + cmdbuf->bufsz); + if (rv) { + drm_buffer_free(cmdbuf->buffer); + return rv; + } + } else + goto done; + + orig_nbox = cmdbuf->nbox; + + if (dev_priv->microcode_version == UCODE_R300) { + int temp; + temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); + + drm_buffer_free(cmdbuf->buffer); + + return temp; + } + + /* microcode_version != r300 */ + while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) { + + drm_radeon_cmd_header_t *header; + header = drm_buffer_read_object(cmdbuf->buffer, + sizeof(stack_header), &stack_header); + + switch (header->header.cmd_type) { + case RADEON_CMD_PACKET: + DRM_DEBUG("RADEON_CMD_PACKET\n"); + if (radeon_emit_packets + (dev_priv, file_priv, *header, cmdbuf)) { + DRM_ERROR("radeon_emit_packets failed\n"); + goto err; + } + break; + + case RADEON_CMD_SCALARS: + DRM_DEBUG("RADEON_CMD_SCALARS\n"); + if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) { + DRM_ERROR("radeon_emit_scalars failed\n"); + goto err; + } + break; + + case RADEON_CMD_VECTORS: + DRM_DEBUG("RADEON_CMD_VECTORS\n"); + if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) { + DRM_ERROR("radeon_emit_vectors failed\n"); + goto err; + } + break; + + case RADEON_CMD_DMA_DISCARD: + DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); + idx = header->dma.buf_idx; + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + idx, dma->buf_count - 1); + goto err; + } + + buf = dma->buflist[idx]; + if (buf->file_priv != file_priv || buf->pending) { + DRM_ERROR("bad buffer %p %p %d\n", + buf->file_priv, file_priv, + buf->pending); + goto err; + } + + radeon_cp_discard_buffer(dev, file_priv->masterp, buf); + break; + + case RADEON_CMD_PACKET3: + DRM_DEBUG("RADEON_CMD_PACKET3\n"); + if (radeon_emit_packet3(dev, file_priv, cmdbuf)) { + DRM_ERROR("radeon_emit_packet3 failed\n"); + goto err; + } + break; + + case RADEON_CMD_PACKET3_CLIP: + DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); + if (radeon_emit_packet3_cliprect + (dev, file_priv, cmdbuf, orig_nbox)) { + DRM_ERROR("radeon_emit_packet3_clip failed\n"); + goto err; + } + break; + + case RADEON_CMD_SCALARS2: + DRM_DEBUG("RADEON_CMD_SCALARS2\n"); + if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) { + DRM_ERROR("radeon_emit_scalars2 failed\n"); + goto err; + } + break; + + case RADEON_CMD_WAIT: + DRM_DEBUG("RADEON_CMD_WAIT\n"); + if (radeon_emit_wait(dev, header->wait.flags)) { + DRM_ERROR("radeon_emit_wait failed\n"); + goto err; + } + break; + case RADEON_CMD_VECLINEAR: + DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); + if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) { + DRM_ERROR("radeon_emit_veclinear failed\n"); + goto err; + } + break; + + default: + DRM_ERROR("bad cmd_type %d at byte %d\n", + header->header.cmd_type, + cmdbuf->buffer->iterator); + goto err; + } + } + + drm_buffer_free(cmdbuf->buffer); + + done: + DRM_DEBUG("DONE\n"); + COMMIT_RING(); + return 0; + + err: + drm_buffer_free(cmdbuf->buffer); + return -EINVAL; +} + +static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_getparam_t *param = data; + int value; + + DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); + + switch (param->param) { + case RADEON_PARAM_GART_BUFFER_OFFSET: + value = dev_priv->gart_buffers_offset; + break; + case RADEON_PARAM_LAST_FRAME: + dev_priv->stats.last_frame_reads++; + value = GET_SCRATCH(dev_priv, 0); + break; + case RADEON_PARAM_LAST_DISPATCH: + value = GET_SCRATCH(dev_priv, 1); + break; + case RADEON_PARAM_LAST_CLEAR: + dev_priv->stats.last_clear_reads++; + value = GET_SCRATCH(dev_priv, 2); + break; + case RADEON_PARAM_IRQ_NR: + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + value = 0; + else + value = dev->irq; + break; + case RADEON_PARAM_GART_BASE: + value = dev_priv->gart_vm_start; + break; + case RADEON_PARAM_REGISTER_HANDLE: + value = dev_priv->mmio->offset; + break; + case RADEON_PARAM_STATUS_HANDLE: + value = dev_priv->ring_rptr_offset; + break; +#ifndef __LP64__ + /* + * This ioctl() doesn't work on 64-bit platforms because hw_lock is a + * pointer which can't fit into an int-sized variable. According to + * Michel Dänzer, the ioctl() is only used on embedded platforms, so + * not supporting it shouldn't be a problem. If the same functionality + * is needed on 64-bit platforms, a new ioctl() would have to be added, + * so backwards-compatibility for the embedded platforms can be + * maintained. --davidm 4-Feb-2004. + */ + case RADEON_PARAM_SAREA_HANDLE: + /* The lock is the first dword in the sarea. */ + /* no users of this parameter */ + break; +#endif + case RADEON_PARAM_GART_TEX_HANDLE: + value = dev_priv->gart_textures_offset; + break; + case RADEON_PARAM_SCRATCH_OFFSET: + if (!dev_priv->writeback_works) + return -EINVAL; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + value = R600_SCRATCH_REG_OFFSET; + else + value = RADEON_SCRATCH_REG_OFFSET; + break; + case RADEON_PARAM_CARD_TYPE: + if (dev_priv->flags & RADEON_IS_PCIE) + value = RADEON_CARD_PCIE; + else if (dev_priv->flags & RADEON_IS_AGP) + value = RADEON_CARD_AGP; + else + value = RADEON_CARD_PCI; + break; + case RADEON_PARAM_VBLANK_CRTC: + value = radeon_vblank_crtc_get(dev); + break; + case RADEON_PARAM_FB_LOCATION: + value = radeon_read_fb_location(dev_priv); + break; + case RADEON_PARAM_NUM_GB_PIPES: + value = dev_priv->num_gb_pipes; + break; + case RADEON_PARAM_NUM_Z_PIPES: + value = dev_priv->num_z_pipes; + break; + default: + DRM_DEBUG("Invalid parameter %d\n", param->param); + return -EINVAL; + } + + if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { + DRM_ERROR("copy_to_user\n"); + return -EFAULT; + } + + return 0; +} + +static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv; + drm_radeon_setparam_t *sp = data; + struct drm_radeon_driver_file_fields *radeon_priv; + + switch (sp->param) { + case RADEON_SETPARAM_FB_LOCATION: + radeon_priv = file_priv->driver_priv; + radeon_priv->radeon_fb_delta = dev_priv->fb_location - + sp->value; + break; + case RADEON_SETPARAM_SWITCH_TILING: + if (sp->value == 0) { + DRM_DEBUG("color tiling disabled\n"); + dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; + dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; + if (master_priv->sarea_priv) + master_priv->sarea_priv->tiling_enabled = 0; + } else if (sp->value == 1) { + DRM_DEBUG("color tiling enabled\n"); + dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; + dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; + if (master_priv->sarea_priv) + master_priv->sarea_priv->tiling_enabled = 1; + } + break; + case RADEON_SETPARAM_PCIGART_LOCATION: + dev_priv->pcigart_offset = sp->value; + dev_priv->pcigart_offset_set = 1; + break; + case RADEON_SETPARAM_NEW_MEMMAP: + dev_priv->new_memmap = sp->value; + break; + case RADEON_SETPARAM_PCIGART_TABLE_SIZE: + dev_priv->gart_info.table_size = sp->value; + if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + break; + case RADEON_SETPARAM_VBLANK_CRTC: + return radeon_vblank_crtc_set(dev, sp->value); + break; + default: + DRM_DEBUG("Invalid parameter %d\n", sp->param); + return -EINVAL; + } + + return 0; +} + +/* When a client dies: + * - Check for and clean up flipped page state + * - Free any alloced GART memory. + * - Free any alloced radeon surfaces. + * + * DRM infrastructure takes care of reclaiming dma buffers. + */ +void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) +{ + if (dev->dev_private) { + drm_radeon_private_t *dev_priv = dev->dev_private; + dev_priv->page_flipping = 0; + radeon_mem_release(file_priv, dev_priv->gart_heap); + radeon_mem_release(file_priv, dev_priv->fb_heap); + radeon_surfaces_release(file_priv, dev_priv); + } +} + +void radeon_driver_lastclose(struct drm_device *dev) +{ + radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private); + radeon_do_release(dev); +} + +int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_driver_file_fields *radeon_priv; + + DRM_DEBUG("\n"); + radeon_priv = malloc(sizeof(*radeon_priv), DRM_MEM_DRIVER, M_WAITOK); + + if (!radeon_priv) + return -ENOMEM; + + file_priv->driver_priv = radeon_priv; + + if (dev_priv) + radeon_priv->radeon_fb_delta = dev_priv->fb_location; + else + radeon_priv->radeon_fb_delta = 0; + return 0; +} + +void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_radeon_driver_file_fields *radeon_priv = + file_priv->driver_priv; + + free(radeon_priv, DRM_MEM_DRIVER); +} + +struct drm_ioctl_desc radeon_ioctls[] = { + DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH) +}; + +int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); diff --git a/sys/dev/drm2/radeon/radeon_test.c b/sys/dev/drm2/radeon/radeon_test.c new file mode 100644 index 00000000000..7774699332c --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_test.c @@ -0,0 +1,509 @@ +/* + * Copyright 2009 VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Michel Dänzer + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon_reg.h" +#include "radeon.h" + +#define RADEON_TEST_COPY_BLIT 1 +#define RADEON_TEST_COPY_DMA 0 + + +/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ +static void radeon_do_test_moves(struct radeon_device *rdev, int flag) +{ + struct radeon_bo *vram_obj = NULL; + struct radeon_bo **gtt_obj = NULL; + struct radeon_fence *fence = NULL; + uint64_t gtt_addr, vram_addr; + unsigned i, n, size; + int r, ring; + + switch (flag) { + case RADEON_TEST_COPY_DMA: + ring = radeon_copy_dma_ring_index(rdev); + break; + case RADEON_TEST_COPY_BLIT: + ring = radeon_copy_blit_ring_index(rdev); + break; + default: + DRM_ERROR("Unknown copy method\n"); + return; + } + + size = 1024 * 1024; + + /* Number of tests = + * (Total GTT - IB pool - writeback page - ring buffers) / test size + */ + n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024; + for (i = 0; i < RADEON_NUM_RINGS; ++i) + n -= rdev->ring[i].ring_size; + if (rdev->wb.wb_obj) + n -= RADEON_GPU_PAGE_SIZE; + if (rdev->ih.ring_obj) + n -= rdev->ih.ring_size; + n /= size; + + gtt_obj = malloc(n * sizeof(*gtt_obj), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); + if (!gtt_obj) { + DRM_ERROR("Failed to allocate %d pointers\n", n); + r = 1; + goto out_cleanup; + } + + r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, + NULL, &vram_obj); + if (r) { + DRM_ERROR("Failed to create VRAM object\n"); + goto out_cleanup; + } + r = radeon_bo_reserve(vram_obj, false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); + if (r) { + DRM_ERROR("Failed to pin VRAM object\n"); + goto out_cleanup; + } + for (i = 0; i < n; i++) { + void *gtt_map, *vram_map; + void **gtt_start, **gtt_end; + void **vram_start, **vram_end; + + r = radeon_bo_create(rdev, size, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, NULL, gtt_obj + i); + if (r) { + DRM_ERROR("Failed to create GTT object %d\n", i); + goto out_cleanup; + } + + r = radeon_bo_reserve(gtt_obj[i], false); + if (unlikely(r != 0)) + goto out_cleanup; + r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); + if (r) { + DRM_ERROR("Failed to pin GTT object %d\n", i); + goto out_cleanup; + } + + r = radeon_bo_kmap(gtt_obj[i], >t_map); + if (r) { + DRM_ERROR("Failed to map GTT object %d\n", i); + goto out_cleanup; + } + + for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size); + gtt_start < gtt_end; + gtt_start++) + *gtt_start = gtt_start; + + radeon_bo_kunmap(gtt_obj[i]); + + if (ring == R600_RING_TYPE_DMA_INDEX) + r = radeon_copy_dma(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); + else + r = radeon_copy_blit(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); + if (r) { + DRM_ERROR("Failed GTT->VRAM copy %d\n", i); + goto out_cleanup; + } + + r = radeon_fence_wait(fence, false); + if (r) { + DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); + goto out_cleanup; + } + + radeon_fence_unref(&fence); + + r = radeon_bo_kmap(vram_obj, &vram_map); + if (r) { + DRM_ERROR("Failed to map VRAM object after copy %d\n", i); + goto out_cleanup; + } + + for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size), + vram_start = vram_map, vram_end = (void *)((uintptr_t)vram_map + size); + vram_start < vram_end; + gtt_start++, vram_start++) { + if (*vram_start != gtt_start) { + DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " + "expected 0x%p (GTT/VRAM offset " + "0x%16llx/0x%16llx)\n", + i, *vram_start, gtt_start, + (unsigned long long) + ((uintptr_t)gtt_addr - (uintptr_t)rdev->mc.gtt_start + + (uintptr_t)gtt_start - (uintptr_t)gtt_map), + (unsigned long long) + ((uintptr_t)vram_addr - (uintptr_t)rdev->mc.vram_start + + (uintptr_t)gtt_start - (uintptr_t)gtt_map)); + radeon_bo_kunmap(vram_obj); + goto out_cleanup; + } + *vram_start = vram_start; + } + + radeon_bo_kunmap(vram_obj); + + if (ring == R600_RING_TYPE_DMA_INDEX) + r = radeon_copy_dma(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); + else + r = radeon_copy_blit(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); + if (r) { + DRM_ERROR("Failed VRAM->GTT copy %d\n", i); + goto out_cleanup; + } + + r = radeon_fence_wait(fence, false); + if (r) { + DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); + goto out_cleanup; + } + + radeon_fence_unref(&fence); + + r = radeon_bo_kmap(gtt_obj[i], >t_map); + if (r) { + DRM_ERROR("Failed to map GTT object after copy %d\n", i); + goto out_cleanup; + } + + for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size), + vram_start = vram_map, vram_end = (void *)((uintptr_t)vram_map + size); + gtt_start < gtt_end; + gtt_start++, vram_start++) { + if (*gtt_start != vram_start) { + DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " + "expected 0x%p (VRAM/GTT offset " + "0x%16llx/0x%16llx)\n", + i, *gtt_start, vram_start, + (unsigned long long) + ((uintptr_t)vram_addr - (uintptr_t)rdev->mc.vram_start + + (uintptr_t)vram_start - (uintptr_t)vram_map), + (unsigned long long) + ((uintptr_t)gtt_addr - (uintptr_t)rdev->mc.gtt_start + + (uintptr_t)vram_start - (uintptr_t)vram_map)); + radeon_bo_kunmap(gtt_obj[i]); + goto out_cleanup; + } + } + + radeon_bo_kunmap(gtt_obj[i]); + + DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%jx\n", + (uintmax_t)gtt_addr - rdev->mc.gtt_start); + } + +out_cleanup: + if (vram_obj) { + if (radeon_bo_is_reserved(vram_obj)) { + radeon_bo_unpin(vram_obj); + radeon_bo_unreserve(vram_obj); + } + radeon_bo_unref(&vram_obj); + } + if (gtt_obj) { + for (i = 0; i < n; i++) { + if (gtt_obj[i]) { + if (radeon_bo_is_reserved(gtt_obj[i])) { + radeon_bo_unpin(gtt_obj[i]); + radeon_bo_unreserve(gtt_obj[i]); + } + radeon_bo_unref(>t_obj[i]); + } + } + free(gtt_obj, DRM_MEM_DRIVER); + } + if (fence) { + radeon_fence_unref(&fence); + } + if (r) { + DRM_ERROR("Error while testing BO move.\n"); + } +} + +void radeon_test_moves(struct radeon_device *rdev) +{ + if (rdev->asic->copy.dma) + radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA); + if (rdev->asic->copy.blit) + radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT); +} + +void radeon_test_ring_sync(struct radeon_device *rdev, + struct radeon_ring *ringA, + struct radeon_ring *ringB) +{ + struct radeon_fence *fence1 = NULL, *fence2 = NULL; + struct radeon_semaphore *semaphore = NULL; + int r; + + r = radeon_semaphore_create(rdev, &semaphore); + if (r) { + DRM_ERROR("Failed to create semaphore\n"); + goto out_cleanup; + } + + r = radeon_ring_lock(rdev, ringA, 64); + if (r) { + DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); + goto out_cleanup; + } + radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); + r = radeon_fence_emit(rdev, &fence1, ringA->idx); + if (r) { + DRM_ERROR("Failed to emit fence 1\n"); + radeon_ring_unlock_undo(rdev, ringA); + goto out_cleanup; + } + radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); + r = radeon_fence_emit(rdev, &fence2, ringA->idx); + if (r) { + DRM_ERROR("Failed to emit fence 2\n"); + radeon_ring_unlock_undo(rdev, ringA); + goto out_cleanup; + } + radeon_ring_unlock_commit(rdev, ringA); + + DRM_MDELAY(1000); + + if (radeon_fence_signaled(fence1)) { + DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); + goto out_cleanup; + } + + r = radeon_ring_lock(rdev, ringB, 64); + if (r) { + DRM_ERROR("Failed to lock ring B %p\n", ringB); + goto out_cleanup; + } + radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); + radeon_ring_unlock_commit(rdev, ringB); + + r = radeon_fence_wait(fence1, false); + if (r) { + DRM_ERROR("Failed to wait for sync fence 1\n"); + goto out_cleanup; + } + + DRM_MDELAY(1000); + + if (radeon_fence_signaled(fence2)) { + DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); + goto out_cleanup; + } + + r = radeon_ring_lock(rdev, ringB, 64); + if (r) { + DRM_ERROR("Failed to lock ring B %p\n", ringB); + goto out_cleanup; + } + radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); + radeon_ring_unlock_commit(rdev, ringB); + + r = radeon_fence_wait(fence2, false); + if (r) { + DRM_ERROR("Failed to wait for sync fence 1\n"); + goto out_cleanup; + } + +out_cleanup: + radeon_semaphore_free(rdev, &semaphore, NULL); + + if (fence1) + radeon_fence_unref(&fence1); + + if (fence2) + radeon_fence_unref(&fence2); + + if (r) + DRM_ERROR("Error while testing ring sync (%d).\n", r); +} + +static void radeon_test_ring_sync2(struct radeon_device *rdev, + struct radeon_ring *ringA, + struct radeon_ring *ringB, + struct radeon_ring *ringC) +{ + struct radeon_fence *fenceA = NULL, *fenceB = NULL; + struct radeon_semaphore *semaphore = NULL; + bool sigA, sigB; + int i, r; + + r = radeon_semaphore_create(rdev, &semaphore); + if (r) { + DRM_ERROR("Failed to create semaphore\n"); + goto out_cleanup; + } + + r = radeon_ring_lock(rdev, ringA, 64); + if (r) { + DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); + goto out_cleanup; + } + radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); + r = radeon_fence_emit(rdev, &fenceA, ringA->idx); + if (r) { + DRM_ERROR("Failed to emit sync fence 1\n"); + radeon_ring_unlock_undo(rdev, ringA); + goto out_cleanup; + } + radeon_ring_unlock_commit(rdev, ringA); + + r = radeon_ring_lock(rdev, ringB, 64); + if (r) { + DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); + goto out_cleanup; + } + radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); + r = radeon_fence_emit(rdev, &fenceB, ringB->idx); + if (r) { + DRM_ERROR("Failed to create sync fence 2\n"); + radeon_ring_unlock_undo(rdev, ringB); + goto out_cleanup; + } + radeon_ring_unlock_commit(rdev, ringB); + + DRM_MDELAY(1000); + + if (radeon_fence_signaled(fenceA)) { + DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); + goto out_cleanup; + } + if (radeon_fence_signaled(fenceB)) { + DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); + goto out_cleanup; + } + + r = radeon_ring_lock(rdev, ringC, 64); + if (r) { + DRM_ERROR("Failed to lock ring B %p\n", ringC); + goto out_cleanup; + } + radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); + radeon_ring_unlock_commit(rdev, ringC); + + for (i = 0; i < 30; ++i) { + DRM_MDELAY(100); + sigA = radeon_fence_signaled(fenceA); + sigB = radeon_fence_signaled(fenceB); + if (sigA || sigB) + break; + } + + if (!sigA && !sigB) { + DRM_ERROR("Neither fence A nor B has been signaled\n"); + goto out_cleanup; + } else if (sigA && sigB) { + DRM_ERROR("Both fence A and B has been signaled\n"); + goto out_cleanup; + } + + DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B'); + + r = radeon_ring_lock(rdev, ringC, 64); + if (r) { + DRM_ERROR("Failed to lock ring B %p\n", ringC); + goto out_cleanup; + } + radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); + radeon_ring_unlock_commit(rdev, ringC); + + DRM_MDELAY(1000); + + r = radeon_fence_wait(fenceA, false); + if (r) { + DRM_ERROR("Failed to wait for sync fence A\n"); + goto out_cleanup; + } + r = radeon_fence_wait(fenceB, false); + if (r) { + DRM_ERROR("Failed to wait for sync fence B\n"); + goto out_cleanup; + } + +out_cleanup: + radeon_semaphore_free(rdev, &semaphore, NULL); + + if (fenceA) + radeon_fence_unref(&fenceA); + + if (fenceB) + radeon_fence_unref(&fenceB); + + if (r) + DRM_ERROR("Error while testing ring sync (%d).\n", r); +} + +void radeon_test_syncing(struct radeon_device *rdev) +{ + int i, j, k; + + for (i = 1; i < RADEON_NUM_RINGS; ++i) { + struct radeon_ring *ringA = &rdev->ring[i]; + if (!ringA->ready) + continue; + + for (j = 0; j < i; ++j) { + struct radeon_ring *ringB = &rdev->ring[j]; + if (!ringB->ready) + continue; + + DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); + radeon_test_ring_sync(rdev, ringA, ringB); + + DRM_INFO("Testing syncing between rings %d and %d...\n", j, i); + radeon_test_ring_sync(rdev, ringB, ringA); + + for (k = 0; k < j; ++k) { + struct radeon_ring *ringC = &rdev->ring[k]; + if (!ringC->ready) + continue; + + DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); + radeon_test_ring_sync2(rdev, ringA, ringB, ringC); + + DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j); + radeon_test_ring_sync2(rdev, ringA, ringC, ringB); + + DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k); + radeon_test_ring_sync2(rdev, ringB, ringA, ringC); + + DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i); + radeon_test_ring_sync2(rdev, ringB, ringC, ringA); + + DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j); + radeon_test_ring_sync2(rdev, ringC, ringA, ringB); + + DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i); + radeon_test_ring_sync2(rdev, ringC, ringB, ringA); + } + } + } +} diff --git a/sys/dev/drm2/radeon/radeon_trace.h b/sys/dev/drm2/radeon/radeon_trace.h new file mode 100644 index 00000000000..e0fe7253317 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_trace.h @@ -0,0 +1,85 @@ +#include +__FBSDID("$FreeBSD$"); + +#if !defined(_RADEON_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _RADEON_TRACE_H_ + +#include +#include +#include + +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM radeon +#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM) +#define TRACE_INCLUDE_FILE radeon_trace + +TRACE_EVENT(radeon_bo_create, + TP_PROTO(struct radeon_bo *bo), + TP_ARGS(bo), + TP_STRUCT__entry( + __field(struct radeon_bo *, bo) + __field(u32, pages) + ), + + TP_fast_assign( + __entry->bo = bo; + __entry->pages = bo->tbo.num_pages; + ), + TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages) +); + +DECLARE_EVENT_CLASS(radeon_fence_request, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno), + + TP_STRUCT__entry( + __field(u32, dev) + __field(u32, seqno) + ), + + TP_fast_assign( + __entry->dev = dev->primary->index; + __entry->seqno = seqno; + ), + + TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_emit, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_retire, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +#endif + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#include diff --git a/sys/dev/drm2/radeon/radeon_trace_points.c b/sys/dev/drm2/radeon/radeon_trace_points.c new file mode 100644 index 00000000000..5602c946d23 --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_trace_points.c @@ -0,0 +1,12 @@ +/* Copyright Red Hat Inc 2010. + * Author : Dave Airlie + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "radeon.h" + +#define CREATE_TRACE_POINTS +#include "radeon_trace.h" diff --git a/sys/dev/drm2/radeon/radeon_ttm.c b/sys/dev/drm2/radeon/radeon_ttm.c new file mode 100644 index 00000000000..22c0935b84c --- /dev/null +++ b/sys/dev/drm2/radeon/radeon_ttm.c @@ -0,0 +1,931 @@ +/* + * Copyright 2009 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: + * Jerome Glisse + * Thomas Hellstrom + * Dave Airlie + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include "radeon_reg.h" +#include "radeon.h" + +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) + +static int radeon_ttm_debugfs_init(struct radeon_device *rdev); + +static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) +{ + struct radeon_mman *mman; + struct radeon_device *rdev; + + mman = container_of(bdev, struct radeon_mman, bdev); + rdev = container_of(mman, struct radeon_device, mman); + return rdev; +} + + +/* + * Global memory. + */ +static int radeon_ttm_mem_global_init(struct drm_global_reference *ref) +{ + return ttm_mem_global_init(ref->object); +} + +static void radeon_ttm_mem_global_release(struct drm_global_reference *ref) +{ + ttm_mem_global_release(ref->object); +} + +static int radeon_ttm_global_init(struct radeon_device *rdev) +{ + struct drm_global_reference *global_ref; + int r; + + rdev->mman.mem_global_referenced = false; + global_ref = &rdev->mman.mem_global_ref; + global_ref->global_type = DRM_GLOBAL_TTM_MEM; + global_ref->size = sizeof(struct ttm_mem_global); + global_ref->init = &radeon_ttm_mem_global_init; + global_ref->release = &radeon_ttm_mem_global_release; + r = drm_global_item_ref(global_ref); + if (r != 0) { + DRM_ERROR("Failed setting up TTM memory accounting " + "subsystem.\n"); + return r; + } + + rdev->mman.bo_global_ref.mem_glob = + rdev->mman.mem_global_ref.object; + global_ref = &rdev->mman.bo_global_ref.ref; + global_ref->global_type = DRM_GLOBAL_TTM_BO; + global_ref->size = sizeof(struct ttm_bo_global); + global_ref->init = &ttm_bo_global_init; + global_ref->release = &ttm_bo_global_release; + r = drm_global_item_ref(global_ref); + if (r != 0) { + DRM_ERROR("Failed setting up TTM BO subsystem.\n"); + drm_global_item_unref(&rdev->mman.mem_global_ref); + return r; + } + + rdev->mman.mem_global_referenced = true; + return 0; +} + +static void radeon_ttm_global_fini(struct radeon_device *rdev) +{ + if (rdev->mman.mem_global_referenced) { + drm_global_item_unref(&rdev->mman.bo_global_ref.ref); + drm_global_item_unref(&rdev->mman.mem_global_ref); + rdev->mman.mem_global_referenced = false; + } +} + +static int radeon_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) +{ + return 0; +} + +static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, + struct ttm_mem_type_manager *man) +{ + struct radeon_device *rdev; + + rdev = radeon_get_rdev(bdev); + + switch (type) { + case TTM_PL_SYSTEM: + /* System memory */ + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_TT: + man->func = &ttm_bo_manager_func; + man->gpu_offset = rdev->mc.gtt_start; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; +#if __OS_HAS_AGP + if (rdev->flags & RADEON_IS_AGP) { + if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) { + DRM_ERROR("AGP is not enabled for memory type %u\n", + (unsigned)type); + return -EINVAL; + } + if (!rdev->ddev->agp->cant_use_aperture) + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + } +#endif + break; + case TTM_PL_VRAM: + /* "On-card" video ram */ + man->func = &ttm_bo_manager_func; + man->gpu_offset = rdev->mc.vram_start; + man->flags = TTM_MEMTYPE_FLAG_FIXED | + TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + break; + default: + DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); + return -EINVAL; + } + return 0; +} + +static void radeon_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *placement) +{ + struct radeon_bo *rbo; + static u32 placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + + if (!radeon_ttm_bo_is_radeon_bo(bo)) { + placement->fpfn = 0; + placement->lpfn = 0; + placement->placement = &placements; + placement->busy_placement = &placements; + placement->num_placement = 1; + placement->num_busy_placement = 1; + return; + } + rbo = container_of(bo, struct radeon_bo, tbo); + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); + break; + case TTM_PL_TT: + default: + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + } + *placement = rbo->placement; +} + +static int radeon_verify_access(struct ttm_buffer_object *bo) +{ + return 0; +} + +static void radeon_move_null(struct ttm_buffer_object *bo, + struct ttm_mem_reg *new_mem) +{ + struct ttm_mem_reg *old_mem = &bo->mem; + + KASSERT(old_mem->mm_node == NULL, ("old_mem->mm_node != NULL")); + *old_mem = *new_mem; + new_mem->mm_node = NULL; +} + +static int radeon_move_blit(struct ttm_buffer_object *bo, + bool evict, bool no_wait_gpu, + struct ttm_mem_reg *new_mem, + struct ttm_mem_reg *old_mem) +{ + struct radeon_device *rdev; + uint64_t old_start, new_start; + struct radeon_fence *fence; + int r, ridx; + + rdev = radeon_get_rdev(bo->bdev); + ridx = radeon_copy_ring_index(rdev); + old_start = old_mem->start << PAGE_SHIFT; + new_start = new_mem->start << PAGE_SHIFT; + + switch (old_mem->mem_type) { + case TTM_PL_VRAM: + old_start += rdev->mc.vram_start; + break; + case TTM_PL_TT: + old_start += rdev->mc.gtt_start; + break; + default: + DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + return -EINVAL; + } + switch (new_mem->mem_type) { + case TTM_PL_VRAM: + new_start += rdev->mc.vram_start; + break; + case TTM_PL_TT: + new_start += rdev->mc.gtt_start; + break; + default: + DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + return -EINVAL; + } + if (!rdev->ring[ridx].ready) { + DRM_ERROR("Trying to move memory with ring turned off.\n"); + return -EINVAL; + } + + CTASSERT((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) == 0); + + /* sync other rings */ + fence = bo->sync_obj; + r = radeon_copy(rdev, old_start, new_start, + new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ + &fence); + /* FIXME: handle copy error */ + r = ttm_bo_move_accel_cleanup(bo, (void *)fence, + evict, no_wait_gpu, new_mem); + radeon_fence_unref(&fence); + return r; +} + +static int radeon_move_vram_ram(struct ttm_buffer_object *bo, + bool evict, bool interruptible, + bool no_wait_gpu, + struct ttm_mem_reg *new_mem) +{ + struct radeon_device *rdev; + struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_mem_reg tmp_mem; + u32 placements; + struct ttm_placement placement; + int r; + + rdev = radeon_get_rdev(bo->bdev); + tmp_mem = *new_mem; + tmp_mem.mm_node = NULL; + placement.fpfn = 0; + placement.lpfn = 0; + placement.num_placement = 1; + placement.placement = &placements; + placement.num_busy_placement = 1; + placement.busy_placement = &placements; + placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + r = ttm_bo_mem_space(bo, &placement, &tmp_mem, + interruptible, no_wait_gpu); + if (unlikely(r)) { + return r; + } + + r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement); + if (unlikely(r)) { + goto out_cleanup; + } + + r = ttm_tt_bind(bo->ttm, &tmp_mem); + if (unlikely(r)) { + goto out_cleanup; + } + r = radeon_move_blit(bo, true, no_wait_gpu, &tmp_mem, old_mem); + if (unlikely(r)) { + goto out_cleanup; + } + r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem); +out_cleanup: + ttm_bo_mem_put(bo, &tmp_mem); + return r; +} + +static int radeon_move_ram_vram(struct ttm_buffer_object *bo, + bool evict, bool interruptible, + bool no_wait_gpu, + struct ttm_mem_reg *new_mem) +{ + struct radeon_device *rdev; + struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_mem_reg tmp_mem; + struct ttm_placement placement; + u32 placements; + int r; + + rdev = radeon_get_rdev(bo->bdev); + tmp_mem = *new_mem; + tmp_mem.mm_node = NULL; + placement.fpfn = 0; + placement.lpfn = 0; + placement.num_placement = 1; + placement.placement = &placements; + placement.num_busy_placement = 1; + placement.busy_placement = &placements; + placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + r = ttm_bo_mem_space(bo, &placement, &tmp_mem, + interruptible, no_wait_gpu); + if (unlikely(r)) { + return r; + } + r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem); + if (unlikely(r)) { + goto out_cleanup; + } + r = radeon_move_blit(bo, true, no_wait_gpu, new_mem, old_mem); + if (unlikely(r)) { + goto out_cleanup; + } +out_cleanup: + ttm_bo_mem_put(bo, &tmp_mem); + return r; +} + +static int radeon_bo_move(struct ttm_buffer_object *bo, + bool evict, bool interruptible, + bool no_wait_gpu, + struct ttm_mem_reg *new_mem) +{ + struct radeon_device *rdev; + struct ttm_mem_reg *old_mem = &bo->mem; + int r; + + rdev = radeon_get_rdev(bo->bdev); + if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { + radeon_move_null(bo, new_mem); + return 0; + } + if ((old_mem->mem_type == TTM_PL_TT && + new_mem->mem_type == TTM_PL_SYSTEM) || + (old_mem->mem_type == TTM_PL_SYSTEM && + new_mem->mem_type == TTM_PL_TT)) { + /* bind is enough */ + radeon_move_null(bo, new_mem); + return 0; + } + if (!rdev->ring[radeon_copy_ring_index(rdev)].ready || + rdev->asic->copy.copy == NULL) { + /* use memcpy */ + goto memcpy; + } + + if (old_mem->mem_type == TTM_PL_VRAM && + new_mem->mem_type == TTM_PL_SYSTEM) { + r = radeon_move_vram_ram(bo, evict, interruptible, + no_wait_gpu, new_mem); + } else if (old_mem->mem_type == TTM_PL_SYSTEM && + new_mem->mem_type == TTM_PL_VRAM) { + r = radeon_move_ram_vram(bo, evict, interruptible, + no_wait_gpu, new_mem); + } else { + r = radeon_move_blit(bo, evict, no_wait_gpu, new_mem, old_mem); + } + + if (r) { +memcpy: + r = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem); + } + return r; +} + +static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +{ + struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + struct radeon_device *rdev = radeon_get_rdev(bdev); + + mem->bus.addr = NULL; + mem->bus.offset = 0; + mem->bus.size = mem->num_pages << PAGE_SHIFT; + mem->bus.base = 0; + mem->bus.is_iomem = false; + if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) + return -EINVAL; + switch (mem->mem_type) { + case TTM_PL_SYSTEM: + /* system memory */ + return 0; + case TTM_PL_TT: +#if __OS_HAS_AGP + if (rdev->flags & RADEON_IS_AGP) { + /* RADEON_IS_AGP is set only if AGP is active */ + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = rdev->mc.agp_base; + mem->bus.is_iomem = !rdev->ddev->agp->cant_use_aperture; + } +#endif + break; + case TTM_PL_VRAM: + mem->bus.offset = mem->start << PAGE_SHIFT; + /* check if it's visible */ + if ((mem->bus.offset + mem->bus.size) > rdev->mc.visible_vram_size) + return -EINVAL; + mem->bus.base = rdev->mc.aper_base; + mem->bus.is_iomem = true; +#ifdef __alpha__ + /* + * Alpha: use bus.addr to hold the ioremap() return, + * so we can modify bus.base below. + */ + if (mem->placement & TTM_PL_FLAG_WC) + mem->bus.addr = + ioremap_wc(mem->bus.base + mem->bus.offset, + mem->bus.size); + else + mem->bus.addr = + ioremap_nocache(mem->bus.base + mem->bus.offset, + mem->bus.size); + + /* + * Alpha: Use just the bus offset plus + * the hose/domain memory base for bus.base. + * It then can be used to build PTEs for VRAM + * access, as done in ttm_bo_vm_fault(). + */ + mem->bus.base = (mem->bus.base & 0x0ffffffffUL) + + rdev->ddev->hose->dense_mem_base; +#endif + break; + default: + return -EINVAL; + } + return 0; +} + +static void radeon_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +{ +} + +static int radeon_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible) +{ + return radeon_fence_wait((struct radeon_fence *)sync_obj, interruptible); +} + +static int radeon_sync_obj_flush(void *sync_obj) +{ + return 0; +} + +static void radeon_sync_obj_unref(void **sync_obj) +{ + radeon_fence_unref((struct radeon_fence **)sync_obj); +} + +static void *radeon_sync_obj_ref(void *sync_obj) +{ + return radeon_fence_ref((struct radeon_fence *)sync_obj); +} + +static bool radeon_sync_obj_signaled(void *sync_obj) +{ + return radeon_fence_signaled((struct radeon_fence *)sync_obj); +} + +/* + * TTM backend functions. + */ +struct radeon_ttm_tt { + struct ttm_dma_tt ttm; + struct radeon_device *rdev; + u64 offset; +}; + +static int radeon_ttm_backend_bind(struct ttm_tt *ttm, + struct ttm_mem_reg *bo_mem) +{ + struct radeon_ttm_tt *gtt = (void*)ttm; + int r; + + gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT); + if (!ttm->num_pages) { + DRM_ERROR("nothing to bind %lu pages for mreg %p back %p!\n", + ttm->num_pages, bo_mem, ttm); + } + r = radeon_gart_bind(gtt->rdev, gtt->offset, + ttm->num_pages, ttm->pages, gtt->ttm.dma_address); + if (r) { + DRM_ERROR("failed to bind %lu pages at 0x%08X\n", + ttm->num_pages, (unsigned)gtt->offset); + return r; + } + return 0; +} + +static int radeon_ttm_backend_unbind(struct ttm_tt *ttm) +{ + struct radeon_ttm_tt *gtt = (void *)ttm; + + radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages); + return 0; +} + +static void radeon_ttm_backend_destroy(struct ttm_tt *ttm) +{ + struct radeon_ttm_tt *gtt = (void *)ttm; + + ttm_dma_tt_fini(>t->ttm); + free(gtt, DRM_MEM_DRIVER); +} + +static struct ttm_backend_func radeon_backend_func = { + .bind = &radeon_ttm_backend_bind, + .unbind = &radeon_ttm_backend_unbind, + .destroy = &radeon_ttm_backend_destroy, +}; + +static struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev, + unsigned long size, uint32_t page_flags, + vm_page_t dummy_read_page) +{ + struct radeon_device *rdev; + struct radeon_ttm_tt *gtt; + + rdev = radeon_get_rdev(bdev); +#if __OS_HAS_AGP +#ifdef DUMBBELL_WIP + if (rdev->flags & RADEON_IS_AGP) { + return ttm_agp_tt_create(bdev, rdev->ddev->agp->agpdev, + size, page_flags, dummy_read_page); + } +#endif /* DUMBBELL_WIP */ +#endif + + gtt = malloc(sizeof(struct radeon_ttm_tt), + DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (gtt == NULL) { + return NULL; + } + gtt->ttm.ttm.func = &radeon_backend_func; + gtt->rdev = rdev; + if (ttm_dma_tt_init(>t->ttm, bdev, size, page_flags, dummy_read_page)) { + free(gtt, DRM_MEM_DRIVER); + return NULL; + } + return >t->ttm.ttm; +} + +static int radeon_ttm_tt_populate(struct ttm_tt *ttm) +{ + struct radeon_device *rdev; + struct radeon_ttm_tt *gtt = (void *)ttm; + unsigned i; + int r; +#ifdef DUMBBELL_WIP + bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); +#endif /* DUMBBELL_WIP */ + + if (ttm->state != tt_unpopulated) + return 0; + +#ifdef DUMBBELL_WIP + /* + * Maybe unneeded on FreeBSD. + * -- dumbbell@ + */ + if (slave && ttm->sg) { + drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, + gtt->ttm.dma_address, ttm->num_pages); + ttm->state = tt_unbound; + return 0; + } +#endif /* DUMBBELL_WIP */ + + rdev = radeon_get_rdev(ttm->bdev); +#if __OS_HAS_AGP +#ifdef DUMBBELL_WIP + if (rdev->flags & RADEON_IS_AGP) { + return ttm_agp_tt_populate(ttm); + } +#endif /* DUMBBELL_WIP */ +#endif + +#ifdef CONFIG_SWIOTLB + if (swiotlb_nr_tbl()) { + return ttm_dma_populate(>t->ttm, rdev->dev); + } +#endif + + r = ttm_pool_populate(ttm); + if (r) { + return r; + } + + for (i = 0; i < ttm->num_pages; i++) { + gtt->ttm.dma_address[i] = VM_PAGE_TO_PHYS(ttm->pages[i]); +#ifdef DUMBBELL_WIP + gtt->ttm.dma_address[i] = pci_map_page(rdev->pdev, ttm->pages[i], + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) { + while (--i) { + pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + gtt->ttm.dma_address[i] = 0; + } + ttm_pool_unpopulate(ttm); + return -EFAULT; + } +#endif /* DUMBBELL_WIP */ + } + return 0; +} + +static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) +{ + struct radeon_device *rdev; + struct radeon_ttm_tt *gtt = (void *)ttm; + unsigned i; + bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); + + if (slave) + return; + + rdev = radeon_get_rdev(ttm->bdev); +#if __OS_HAS_AGP +#ifdef DUMBBELL_WIP + if (rdev->flags & RADEON_IS_AGP) { + ttm_agp_tt_unpopulate(ttm); + return; + } +#endif /* DUMBBELL_WIP */ +#endif + +#ifdef CONFIG_SWIOTLB + if (swiotlb_nr_tbl()) { + ttm_dma_unpopulate(>t->ttm, rdev->dev); + return; + } +#endif + + for (i = 0; i < ttm->num_pages; i++) { + if (gtt->ttm.dma_address[i]) { + gtt->ttm.dma_address[i] = 0; +#ifdef DUMBBELL_WIP + pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +#endif /* DUMBBELL_WIP */ + } + } + + ttm_pool_unpopulate(ttm); +} + +static struct ttm_bo_driver radeon_bo_driver = { + .ttm_tt_create = &radeon_ttm_tt_create, + .ttm_tt_populate = &radeon_ttm_tt_populate, + .ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate, + .invalidate_caches = &radeon_invalidate_caches, + .init_mem_type = &radeon_init_mem_type, + .evict_flags = &radeon_evict_flags, + .move = &radeon_bo_move, + .verify_access = &radeon_verify_access, + .sync_obj_signaled = &radeon_sync_obj_signaled, + .sync_obj_wait = &radeon_sync_obj_wait, + .sync_obj_flush = &radeon_sync_obj_flush, + .sync_obj_unref = &radeon_sync_obj_unref, + .sync_obj_ref = &radeon_sync_obj_ref, + .move_notify = &radeon_bo_move_notify, + .fault_reserve_notify = &radeon_bo_fault_reserve_notify, + .io_mem_reserve = &radeon_ttm_io_mem_reserve, + .io_mem_free = &radeon_ttm_io_mem_free, +}; + +int radeon_ttm_init(struct radeon_device *rdev) +{ + int r, r2; + + r = radeon_ttm_global_init(rdev); + if (r) { + return r; + } + /* No others user of address space so set it to 0 */ + r = ttm_bo_device_init(&rdev->mman.bdev, + rdev->mman.bo_global_ref.ref.object, + &radeon_bo_driver, DRM_FILE_PAGE_OFFSET, + rdev->need_dma32); + if (r) { + DRM_ERROR("failed initializing buffer object driver(%d).\n", r); + return r; + } + rdev->mman.initialized = true; + rdev->ddev->drm_ttm_bdev = &rdev->mman.bdev; + r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, + rdev->mc.real_vram_size >> PAGE_SHIFT); + if (r) { + DRM_ERROR("Failed initializing VRAM heap.\n"); + return r; + } + r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->stollen_vga_memory); + if (r) { + return r; + } + r = radeon_bo_reserve(rdev->stollen_vga_memory, false); + if (r) { + radeon_bo_unref(&rdev->stollen_vga_memory); + return r; + } + r = radeon_bo_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL); + radeon_bo_unreserve(rdev->stollen_vga_memory); + if (r) { + radeon_bo_unref(&rdev->stollen_vga_memory); + return r; + } + DRM_INFO("radeon: %uM of VRAM memory ready\n", + (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); + r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, + rdev->mc.gtt_size >> PAGE_SHIFT); + if (r) { + DRM_ERROR("Failed initializing GTT heap.\n"); + r2 = radeon_bo_reserve(rdev->stollen_vga_memory, false); + if (likely(r2 == 0)) { + radeon_bo_unpin(rdev->stollen_vga_memory); + radeon_bo_unreserve(rdev->stollen_vga_memory); + } + radeon_bo_unref(&rdev->stollen_vga_memory); + return r; + } + DRM_INFO("radeon: %uM of GTT memory ready.\n", + (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); + + r = radeon_ttm_debugfs_init(rdev); + if (r) { + DRM_ERROR("Failed to init debugfs\n"); + r2 = radeon_bo_reserve(rdev->stollen_vga_memory, false); + if (likely(r2 == 0)) { + radeon_bo_unpin(rdev->stollen_vga_memory); + radeon_bo_unreserve(rdev->stollen_vga_memory); + } + radeon_bo_unref(&rdev->stollen_vga_memory); + return r; + } + return 0; +} + +void radeon_ttm_fini(struct radeon_device *rdev) +{ + int r; + + if (!rdev->mman.initialized) + return; + if (rdev->stollen_vga_memory) { + r = radeon_bo_reserve(rdev->stollen_vga_memory, false); + if (r == 0) { + radeon_bo_unpin(rdev->stollen_vga_memory); + radeon_bo_unreserve(rdev->stollen_vga_memory); + } + radeon_bo_unref(&rdev->stollen_vga_memory); + } + ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM); + ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT); + ttm_bo_device_release(&rdev->mman.bdev); + radeon_gart_fini(rdev); + radeon_ttm_global_fini(rdev); + rdev->mman.initialized = false; + DRM_INFO("radeon: ttm finalized\n"); +} + +/* this should only be called at bootup or when userspace + * isn't running */ +void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) +{ + struct ttm_mem_type_manager *man; + + if (!rdev->mman.initialized) + return; + + man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + /* this just adjusts TTM size idea, which sets lpfn to the correct value */ + man->size = size >> PAGE_SHIFT; +} + +#ifdef DUMBBELL_WIP +static struct vm_operations_struct radeon_ttm_vm_ops; +static const struct vm_operations_struct *ttm_vm_ops = NULL; + +static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct ttm_buffer_object *bo; + struct radeon_device *rdev; + int r; + + bo = (struct ttm_buffer_object *)vma->vm_private_data; + if (bo == NULL) { + return VM_FAULT_NOPAGE; + } + rdev = radeon_get_rdev(bo->bdev); + sx_slock(&rdev->pm.mclk_lock); + r = ttm_vm_ops->fault(vma, vmf); + sx_sunlock(&rdev->pm.mclk_lock); + return r; +} + +int radeon_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *file_priv; + struct radeon_device *rdev; + int r; + + if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) { + return drm_mmap(filp, vma); + } + + file_priv = filp->private_data; + rdev = file_priv->minor->dev->dev_private; + if (rdev == NULL) { + return -EINVAL; + } + r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev); + if (unlikely(r != 0)) { + return r; + } + if (unlikely(ttm_vm_ops == NULL)) { + ttm_vm_ops = vma->vm_ops; + radeon_ttm_vm_ops = *ttm_vm_ops; + radeon_ttm_vm_ops.fault = &radeon_ttm_fault; + } + vma->vm_ops = &radeon_ttm_vm_ops; + return 0; +} +#endif /* DUMBBELL_WIP */ + + +#define RADEON_DEBUGFS_MEM_TYPES 2 + +#if defined(CONFIG_DEBUG_FS) +static int radeon_mm_dump_table(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_mm *mm = (struct drm_mm *)node->info_ent->data; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + int ret; + struct ttm_bo_global *glob = rdev->mman.bdev.glob; + + spin_lock(&glob->lru_lock); + ret = drm_mm_dump_table(m, mm); + spin_unlock(&glob->lru_lock); + return ret; +} +#endif + +static int radeon_ttm_debugfs_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2]; + static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32]; + unsigned i; + + for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) { + if (i == 0) + sprintf(radeon_mem_types_names[i], "radeon_vram_mm"); + else + sprintf(radeon_mem_types_names[i], "radeon_gtt_mm"); + radeon_mem_types_list[i].name = radeon_mem_types_names[i]; + radeon_mem_types_list[i].show = &radeon_mm_dump_table; + radeon_mem_types_list[i].driver_features = 0; + if (i == 0) + radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv; + else + radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv; + + } + /* Add ttm page pool to debugfs */ + sprintf(radeon_mem_types_names[i], "ttm_page_pool"); + radeon_mem_types_list[i].name = radeon_mem_types_names[i]; + radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs; + radeon_mem_types_list[i].driver_features = 0; + radeon_mem_types_list[i++].data = NULL; +#ifdef CONFIG_SWIOTLB + if (swiotlb_nr_tbl()) { + sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool"); + radeon_mem_types_list[i].name = radeon_mem_types_names[i]; + radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs; + radeon_mem_types_list[i].driver_features = 0; + radeon_mem_types_list[i++].data = NULL; + } +#endif + return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i); + +#endif + return 0; +} diff --git a/sys/dev/drm2/radeon/reg_srcs/cayman b/sys/dev/drm2/radeon/reg_srcs/cayman new file mode 100644 index 00000000000..a072fa8c46b --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/cayman @@ -0,0 +1,642 @@ +cayman 0x9400 +0x0000802C GRBM_GFX_INDEX +0x00008040 WAIT_UNTIL +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE +0x000088B0 VGT_VTX_VECT_EJECT_REG +0x000088C4 VGT_CACHE_INVALIDATION +0x000088D4 VGT_GS_VERTEX_REUSE +0x00008958 VGT_PRIMITIVE_TYPE +0x0000895C VGT_INDEX_TYPE +0x00008970 VGT_NUM_INDICES +0x00008974 VGT_NUM_INSTANCES +0x00008990 VGT_COMPUTE_DIM_X +0x00008994 VGT_COMPUTE_DIM_Y +0x00008998 VGT_COMPUTE_DIM_Z +0x0000899C VGT_COMPUTE_START_X +0x000089A0 VGT_COMPUTE_START_Y +0x000089A4 VGT_COMPUTE_START_Z +0x000089A8 VGT_COMPUTE_INDEX +0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE +0x000089B0 VGT_HS_OFFCHIP_PARAM +0x00008A14 PA_CL_ENHANCE +0x00008A60 PA_SC_LINE_STIPPLE_VALUE +0x00008B10 PA_SC_LINE_STIPPLE_STATE +0x00008BF0 PA_SC_ENHANCE +0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN +0x00008C00 SQ_CONFIG +0x00008C04 SQ_GPR_RESOURCE_MGMT_1 +0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1 +0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2 +0x00008DF8 SQ_CONST_MEM_BASE +0x00008E20 SQ_STATIC_THREAD_MGMT_1 +0x00008E24 SQ_STATIC_THREAD_MGMT_2 +0x00008E28 SQ_STATIC_THREAD_MGMT_3 +0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS +0x00009100 SPI_CONFIG_CNTL +0x0000913C SPI_CONFIG_CNTL_1 +0x00009508 TA_CNTL_AUX +0x00009830 DB_DEBUG +0x00009834 DB_DEBUG2 +0x00009838 DB_DEBUG3 +0x0000983C DB_DEBUG4 +0x00009854 DB_WATERMARKS +0x0000A400 TD_PS_BORDER_COLOR_INDEX +0x0000A404 TD_PS_BORDER_COLOR_RED +0x0000A408 TD_PS_BORDER_COLOR_GREEN +0x0000A40C TD_PS_BORDER_COLOR_BLUE +0x0000A410 TD_PS_BORDER_COLOR_ALPHA +0x0000A414 TD_VS_BORDER_COLOR_INDEX +0x0000A418 TD_VS_BORDER_COLOR_RED +0x0000A41C TD_VS_BORDER_COLOR_GREEN +0x0000A420 TD_VS_BORDER_COLOR_BLUE +0x0000A424 TD_VS_BORDER_COLOR_ALPHA +0x0000A428 TD_GS_BORDER_COLOR_INDEX +0x0000A42C TD_GS_BORDER_COLOR_RED +0x0000A430 TD_GS_BORDER_COLOR_GREEN +0x0000A434 TD_GS_BORDER_COLOR_BLUE +0x0000A438 TD_GS_BORDER_COLOR_ALPHA +0x0000A43C TD_HS_BORDER_COLOR_INDEX +0x0000A440 TD_HS_BORDER_COLOR_RED +0x0000A444 TD_HS_BORDER_COLOR_GREEN +0x0000A448 TD_HS_BORDER_COLOR_BLUE +0x0000A44C TD_HS_BORDER_COLOR_ALPHA +0x0000A450 TD_LS_BORDER_COLOR_INDEX +0x0000A454 TD_LS_BORDER_COLOR_RED +0x0000A458 TD_LS_BORDER_COLOR_GREEN +0x0000A45C TD_LS_BORDER_COLOR_BLUE +0x0000A460 TD_LS_BORDER_COLOR_ALPHA +0x0000A464 TD_CS_BORDER_COLOR_INDEX +0x0000A468 TD_CS_BORDER_COLOR_RED +0x0000A46C TD_CS_BORDER_COLOR_GREEN +0x0000A470 TD_CS_BORDER_COLOR_BLUE +0x0000A474 TD_CS_BORDER_COLOR_ALPHA +0x00028000 DB_RENDER_CONTROL +0x00028004 DB_COUNT_CONTROL +0x0002800C DB_RENDER_OVERRIDE +0x00028010 DB_RENDER_OVERRIDE2 +0x00028028 DB_STENCIL_CLEAR +0x0002802C DB_DEPTH_CLEAR +0x00028030 PA_SC_SCREEN_SCISSOR_TL +0x00028034 PA_SC_SCREEN_SCISSOR_BR +0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 +0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 +0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 +0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3 +0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4 +0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5 +0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6 +0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7 +0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8 +0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9 +0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10 +0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11 +0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12 +0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13 +0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14 +0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15 +0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0 +0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1 +0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2 +0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3 +0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4 +0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5 +0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6 +0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7 +0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8 +0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9 +0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10 +0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11 +0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12 +0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13 +0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14 +0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15 +0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0 +0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1 +0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2 +0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3 +0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4 +0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5 +0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6 +0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7 +0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8 +0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9 +0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10 +0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11 +0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12 +0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13 +0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14 +0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15 +0x00028200 PA_SC_WINDOW_OFFSET +0x00028204 PA_SC_WINDOW_SCISSOR_TL +0x00028208 PA_SC_WINDOW_SCISSOR_BR +0x0002820C PA_SC_CLIPRECT_RULE +0x00028210 PA_SC_CLIPRECT_0_TL +0x00028214 PA_SC_CLIPRECT_0_BR +0x00028218 PA_SC_CLIPRECT_1_TL +0x0002821C PA_SC_CLIPRECT_1_BR +0x00028220 PA_SC_CLIPRECT_2_TL +0x00028224 PA_SC_CLIPRECT_2_BR +0x00028228 PA_SC_CLIPRECT_3_TL +0x0002822C PA_SC_CLIPRECT_3_BR +0x00028230 PA_SC_EDGERULE +0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET +0x00028240 PA_SC_GENERIC_SCISSOR_TL +0x00028244 PA_SC_GENERIC_SCISSOR_BR +0x00028250 PA_SC_VPORT_SCISSOR_0_TL +0x00028254 PA_SC_VPORT_SCISSOR_0_BR +0x00028258 PA_SC_VPORT_SCISSOR_1_TL +0x0002825C PA_SC_VPORT_SCISSOR_1_BR +0x00028260 PA_SC_VPORT_SCISSOR_2_TL +0x00028264 PA_SC_VPORT_SCISSOR_2_BR +0x00028268 PA_SC_VPORT_SCISSOR_3_TL +0x0002826C PA_SC_VPORT_SCISSOR_3_BR +0x00028270 PA_SC_VPORT_SCISSOR_4_TL +0x00028274 PA_SC_VPORT_SCISSOR_4_BR +0x00028278 PA_SC_VPORT_SCISSOR_5_TL +0x0002827C PA_SC_VPORT_SCISSOR_5_BR +0x00028280 PA_SC_VPORT_SCISSOR_6_TL +0x00028284 PA_SC_VPORT_SCISSOR_6_BR +0x00028288 PA_SC_VPORT_SCISSOR_7_TL +0x0002828C PA_SC_VPORT_SCISSOR_7_BR +0x00028290 PA_SC_VPORT_SCISSOR_8_TL +0x00028294 PA_SC_VPORT_SCISSOR_8_BR +0x00028298 PA_SC_VPORT_SCISSOR_9_TL +0x0002829C PA_SC_VPORT_SCISSOR_9_BR +0x000282A0 PA_SC_VPORT_SCISSOR_10_TL +0x000282A4 PA_SC_VPORT_SCISSOR_10_BR +0x000282A8 PA_SC_VPORT_SCISSOR_11_TL +0x000282AC PA_SC_VPORT_SCISSOR_11_BR +0x000282B0 PA_SC_VPORT_SCISSOR_12_TL +0x000282B4 PA_SC_VPORT_SCISSOR_12_BR +0x000282B8 PA_SC_VPORT_SCISSOR_13_TL +0x000282BC PA_SC_VPORT_SCISSOR_13_BR +0x000282C0 PA_SC_VPORT_SCISSOR_14_TL +0x000282C4 PA_SC_VPORT_SCISSOR_14_BR +0x000282C8 PA_SC_VPORT_SCISSOR_15_TL +0x000282CC PA_SC_VPORT_SCISSOR_15_BR +0x000282D0 PA_SC_VPORT_ZMIN_0 +0x000282D4 PA_SC_VPORT_ZMAX_0 +0x000282D8 PA_SC_VPORT_ZMIN_1 +0x000282DC PA_SC_VPORT_ZMAX_1 +0x000282E0 PA_SC_VPORT_ZMIN_2 +0x000282E4 PA_SC_VPORT_ZMAX_2 +0x000282E8 PA_SC_VPORT_ZMIN_3 +0x000282EC PA_SC_VPORT_ZMAX_3 +0x000282F0 PA_SC_VPORT_ZMIN_4 +0x000282F4 PA_SC_VPORT_ZMAX_4 +0x000282F8 PA_SC_VPORT_ZMIN_5 +0x000282FC PA_SC_VPORT_ZMAX_5 +0x00028300 PA_SC_VPORT_ZMIN_6 +0x00028304 PA_SC_VPORT_ZMAX_6 +0x00028308 PA_SC_VPORT_ZMIN_7 +0x0002830C PA_SC_VPORT_ZMAX_7 +0x00028310 PA_SC_VPORT_ZMIN_8 +0x00028314 PA_SC_VPORT_ZMAX_8 +0x00028318 PA_SC_VPORT_ZMIN_9 +0x0002831C PA_SC_VPORT_ZMAX_9 +0x00028320 PA_SC_VPORT_ZMIN_10 +0x00028324 PA_SC_VPORT_ZMAX_10 +0x00028328 PA_SC_VPORT_ZMIN_11 +0x0002832C PA_SC_VPORT_ZMAX_11 +0x00028330 PA_SC_VPORT_ZMIN_12 +0x00028334 PA_SC_VPORT_ZMAX_12 +0x00028338 PA_SC_VPORT_ZMIN_13 +0x0002833C PA_SC_VPORT_ZMAX_13 +0x00028340 PA_SC_VPORT_ZMIN_14 +0x00028344 PA_SC_VPORT_ZMAX_14 +0x00028348 PA_SC_VPORT_ZMIN_15 +0x0002834C PA_SC_VPORT_ZMAX_15 +0x00028354 SX_SURFACE_SYNC +0x0002835C SX_SCATTER_EXPORT_SIZE +0x00028380 SQ_VTX_SEMANTIC_0 +0x00028384 SQ_VTX_SEMANTIC_1 +0x00028388 SQ_VTX_SEMANTIC_2 +0x0002838C SQ_VTX_SEMANTIC_3 +0x00028390 SQ_VTX_SEMANTIC_4 +0x00028394 SQ_VTX_SEMANTIC_5 +0x00028398 SQ_VTX_SEMANTIC_6 +0x0002839C SQ_VTX_SEMANTIC_7 +0x000283A0 SQ_VTX_SEMANTIC_8 +0x000283A4 SQ_VTX_SEMANTIC_9 +0x000283A8 SQ_VTX_SEMANTIC_10 +0x000283AC SQ_VTX_SEMANTIC_11 +0x000283B0 SQ_VTX_SEMANTIC_12 +0x000283B4 SQ_VTX_SEMANTIC_13 +0x000283B8 SQ_VTX_SEMANTIC_14 +0x000283BC SQ_VTX_SEMANTIC_15 +0x000283C0 SQ_VTX_SEMANTIC_16 +0x000283C4 SQ_VTX_SEMANTIC_17 +0x000283C8 SQ_VTX_SEMANTIC_18 +0x000283CC SQ_VTX_SEMANTIC_19 +0x000283D0 SQ_VTX_SEMANTIC_20 +0x000283D4 SQ_VTX_SEMANTIC_21 +0x000283D8 SQ_VTX_SEMANTIC_22 +0x000283DC SQ_VTX_SEMANTIC_23 +0x000283E0 SQ_VTX_SEMANTIC_24 +0x000283E4 SQ_VTX_SEMANTIC_25 +0x000283E8 SQ_VTX_SEMANTIC_26 +0x000283EC SQ_VTX_SEMANTIC_27 +0x000283F0 SQ_VTX_SEMANTIC_28 +0x000283F4 SQ_VTX_SEMANTIC_29 +0x000283F8 SQ_VTX_SEMANTIC_30 +0x000283FC SQ_VTX_SEMANTIC_31 +0x00028400 VGT_MAX_VTX_INDX +0x00028404 VGT_MIN_VTX_INDX +0x00028408 VGT_INDX_OFFSET +0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX +0x00028410 SX_ALPHA_TEST_CONTROL +0x00028414 CB_BLEND_RED +0x00028418 CB_BLEND_GREEN +0x0002841C CB_BLEND_BLUE +0x00028420 CB_BLEND_ALPHA +0x00028430 DB_STENCILREFMASK +0x00028434 DB_STENCILREFMASK_BF +0x00028438 SX_ALPHA_REF +0x0002843C PA_CL_VPORT_XSCALE_0 +0x00028440 PA_CL_VPORT_XOFFSET_0 +0x00028444 PA_CL_VPORT_YSCALE_0 +0x00028448 PA_CL_VPORT_YOFFSET_0 +0x0002844C PA_CL_VPORT_ZSCALE_0 +0x00028450 PA_CL_VPORT_ZOFFSET_0 +0x00028454 PA_CL_VPORT_XSCALE_1 +0x00028458 PA_CL_VPORT_XOFFSET_1 +0x0002845C PA_CL_VPORT_YSCALE_1 +0x00028460 PA_CL_VPORT_YOFFSET_1 +0x00028464 PA_CL_VPORT_ZSCALE_1 +0x00028468 PA_CL_VPORT_ZOFFSET_1 +0x0002846C PA_CL_VPORT_XSCALE_2 +0x00028470 PA_CL_VPORT_XOFFSET_2 +0x00028474 PA_CL_VPORT_YSCALE_2 +0x00028478 PA_CL_VPORT_YOFFSET_2 +0x0002847C PA_CL_VPORT_ZSCALE_2 +0x00028480 PA_CL_VPORT_ZOFFSET_2 +0x00028484 PA_CL_VPORT_XSCALE_3 +0x00028488 PA_CL_VPORT_XOFFSET_3 +0x0002848C PA_CL_VPORT_YSCALE_3 +0x00028490 PA_CL_VPORT_YOFFSET_3 +0x00028494 PA_CL_VPORT_ZSCALE_3 +0x00028498 PA_CL_VPORT_ZOFFSET_3 +0x0002849C PA_CL_VPORT_XSCALE_4 +0x000284A0 PA_CL_VPORT_XOFFSET_4 +0x000284A4 PA_CL_VPORT_YSCALE_4 +0x000284A8 PA_CL_VPORT_YOFFSET_4 +0x000284AC PA_CL_VPORT_ZSCALE_4 +0x000284B0 PA_CL_VPORT_ZOFFSET_4 +0x000284B4 PA_CL_VPORT_XSCALE_5 +0x000284B8 PA_CL_VPORT_XOFFSET_5 +0x000284BC PA_CL_VPORT_YSCALE_5 +0x000284C0 PA_CL_VPORT_YOFFSET_5 +0x000284C4 PA_CL_VPORT_ZSCALE_5 +0x000284C8 PA_CL_VPORT_ZOFFSET_5 +0x000284CC PA_CL_VPORT_XSCALE_6 +0x000284D0 PA_CL_VPORT_XOFFSET_6 +0x000284D4 PA_CL_VPORT_YSCALE_6 +0x000284D8 PA_CL_VPORT_YOFFSET_6 +0x000284DC PA_CL_VPORT_ZSCALE_6 +0x000284E0 PA_CL_VPORT_ZOFFSET_6 +0x000284E4 PA_CL_VPORT_XSCALE_7 +0x000284E8 PA_CL_VPORT_XOFFSET_7 +0x000284EC PA_CL_VPORT_YSCALE_7 +0x000284F0 PA_CL_VPORT_YOFFSET_7 +0x000284F4 PA_CL_VPORT_ZSCALE_7 +0x000284F8 PA_CL_VPORT_ZOFFSET_7 +0x000284FC PA_CL_VPORT_XSCALE_8 +0x00028500 PA_CL_VPORT_XOFFSET_8 +0x00028504 PA_CL_VPORT_YSCALE_8 +0x00028508 PA_CL_VPORT_YOFFSET_8 +0x0002850C PA_CL_VPORT_ZSCALE_8 +0x00028510 PA_CL_VPORT_ZOFFSET_8 +0x00028514 PA_CL_VPORT_XSCALE_9 +0x00028518 PA_CL_VPORT_XOFFSET_9 +0x0002851C PA_CL_VPORT_YSCALE_9 +0x00028520 PA_CL_VPORT_YOFFSET_9 +0x00028524 PA_CL_VPORT_ZSCALE_9 +0x00028528 PA_CL_VPORT_ZOFFSET_9 +0x0002852C PA_CL_VPORT_XSCALE_10 +0x00028530 PA_CL_VPORT_XOFFSET_10 +0x00028534 PA_CL_VPORT_YSCALE_10 +0x00028538 PA_CL_VPORT_YOFFSET_10 +0x0002853C PA_CL_VPORT_ZSCALE_10 +0x00028540 PA_CL_VPORT_ZOFFSET_10 +0x00028544 PA_CL_VPORT_XSCALE_11 +0x00028548 PA_CL_VPORT_XOFFSET_11 +0x0002854C PA_CL_VPORT_YSCALE_11 +0x00028550 PA_CL_VPORT_YOFFSET_11 +0x00028554 PA_CL_VPORT_ZSCALE_11 +0x00028558 PA_CL_VPORT_ZOFFSET_11 +0x0002855C PA_CL_VPORT_XSCALE_12 +0x00028560 PA_CL_VPORT_XOFFSET_12 +0x00028564 PA_CL_VPORT_YSCALE_12 +0x00028568 PA_CL_VPORT_YOFFSET_12 +0x0002856C PA_CL_VPORT_ZSCALE_12 +0x00028570 PA_CL_VPORT_ZOFFSET_12 +0x00028574 PA_CL_VPORT_XSCALE_13 +0x00028578 PA_CL_VPORT_XOFFSET_13 +0x0002857C PA_CL_VPORT_YSCALE_13 +0x00028580 PA_CL_VPORT_YOFFSET_13 +0x00028584 PA_CL_VPORT_ZSCALE_13 +0x00028588 PA_CL_VPORT_ZOFFSET_13 +0x0002858C PA_CL_VPORT_XSCALE_14 +0x00028590 PA_CL_VPORT_XOFFSET_14 +0x00028594 PA_CL_VPORT_YSCALE_14 +0x00028598 PA_CL_VPORT_YOFFSET_14 +0x0002859C PA_CL_VPORT_ZSCALE_14 +0x000285A0 PA_CL_VPORT_ZOFFSET_14 +0x000285A4 PA_CL_VPORT_XSCALE_15 +0x000285A8 PA_CL_VPORT_XOFFSET_15 +0x000285AC PA_CL_VPORT_YSCALE_15 +0x000285B0 PA_CL_VPORT_YOFFSET_15 +0x000285B4 PA_CL_VPORT_ZSCALE_15 +0x000285B8 PA_CL_VPORT_ZOFFSET_15 +0x000285BC PA_CL_UCP_0_X +0x000285C0 PA_CL_UCP_0_Y +0x000285C4 PA_CL_UCP_0_Z +0x000285C8 PA_CL_UCP_0_W +0x000285CC PA_CL_UCP_1_X +0x000285D0 PA_CL_UCP_1_Y +0x000285D4 PA_CL_UCP_1_Z +0x000285D8 PA_CL_UCP_1_W +0x000285DC PA_CL_UCP_2_X +0x000285E0 PA_CL_UCP_2_Y +0x000285E4 PA_CL_UCP_2_Z +0x000285E8 PA_CL_UCP_2_W +0x000285EC PA_CL_UCP_3_X +0x000285F0 PA_CL_UCP_3_Y +0x000285F4 PA_CL_UCP_3_Z +0x000285F8 PA_CL_UCP_3_W +0x000285FC PA_CL_UCP_4_X +0x00028600 PA_CL_UCP_4_Y +0x00028604 PA_CL_UCP_4_Z +0x00028608 PA_CL_UCP_4_W +0x0002860C PA_CL_UCP_5_X +0x00028610 PA_CL_UCP_5_Y +0x00028614 PA_CL_UCP_5_Z +0x00028618 PA_CL_UCP_5_W +0x0002861C SPI_VS_OUT_ID_0 +0x00028620 SPI_VS_OUT_ID_1 +0x00028624 SPI_VS_OUT_ID_2 +0x00028628 SPI_VS_OUT_ID_3 +0x0002862C SPI_VS_OUT_ID_4 +0x00028630 SPI_VS_OUT_ID_5 +0x00028634 SPI_VS_OUT_ID_6 +0x00028638 SPI_VS_OUT_ID_7 +0x0002863C SPI_VS_OUT_ID_8 +0x00028640 SPI_VS_OUT_ID_9 +0x00028644 SPI_PS_INPUT_CNTL_0 +0x00028648 SPI_PS_INPUT_CNTL_1 +0x0002864C SPI_PS_INPUT_CNTL_2 +0x00028650 SPI_PS_INPUT_CNTL_3 +0x00028654 SPI_PS_INPUT_CNTL_4 +0x00028658 SPI_PS_INPUT_CNTL_5 +0x0002865C SPI_PS_INPUT_CNTL_6 +0x00028660 SPI_PS_INPUT_CNTL_7 +0x00028664 SPI_PS_INPUT_CNTL_8 +0x00028668 SPI_PS_INPUT_CNTL_9 +0x0002866C SPI_PS_INPUT_CNTL_10 +0x00028670 SPI_PS_INPUT_CNTL_11 +0x00028674 SPI_PS_INPUT_CNTL_12 +0x00028678 SPI_PS_INPUT_CNTL_13 +0x0002867C SPI_PS_INPUT_CNTL_14 +0x00028680 SPI_PS_INPUT_CNTL_15 +0x00028684 SPI_PS_INPUT_CNTL_16 +0x00028688 SPI_PS_INPUT_CNTL_17 +0x0002868C SPI_PS_INPUT_CNTL_18 +0x00028690 SPI_PS_INPUT_CNTL_19 +0x00028694 SPI_PS_INPUT_CNTL_20 +0x00028698 SPI_PS_INPUT_CNTL_21 +0x0002869C SPI_PS_INPUT_CNTL_22 +0x000286A0 SPI_PS_INPUT_CNTL_23 +0x000286A4 SPI_PS_INPUT_CNTL_24 +0x000286A8 SPI_PS_INPUT_CNTL_25 +0x000286AC SPI_PS_INPUT_CNTL_26 +0x000286B0 SPI_PS_INPUT_CNTL_27 +0x000286B4 SPI_PS_INPUT_CNTL_28 +0x000286B8 SPI_PS_INPUT_CNTL_29 +0x000286BC SPI_PS_INPUT_CNTL_30 +0x000286C0 SPI_PS_INPUT_CNTL_31 +0x000286C4 SPI_VS_OUT_CONFIG +0x000286C8 SPI_THREAD_GROUPING +0x000286CC SPI_PS_IN_CONTROL_0 +0x000286D0 SPI_PS_IN_CONTROL_1 +0x000286D4 SPI_INTERP_CONTROL_0 +0x000286D8 SPI_INPUT_Z +0x000286DC SPI_FOG_CNTL +0x000286E0 SPI_BARYC_CNTL +0x000286E4 SPI_PS_IN_CONTROL_2 +0x000286E8 SPI_COMPUTE_INPUT_CNTL +0x000286EC SPI_COMPUTE_NUM_THREAD_X +0x000286F0 SPI_COMPUTE_NUM_THREAD_Y +0x000286F4 SPI_COMPUTE_NUM_THREAD_Z +0x000286F8 SPI_GPR_MGMT +0x000286FC SPI_LDS_MGMT +0x00028700 SPI_STACK_MGMT +0x00028704 SPI_WAVE_MGMT_1 +0x00028708 SPI_WAVE_MGMT_2 +0x00028720 GDS_ADDR_BASE +0x00028724 GDS_ADDR_SIZE +0x00028780 CB_BLEND0_CONTROL +0x00028784 CB_BLEND1_CONTROL +0x00028788 CB_BLEND2_CONTROL +0x0002878C CB_BLEND3_CONTROL +0x00028790 CB_BLEND4_CONTROL +0x00028794 CB_BLEND5_CONTROL +0x00028798 CB_BLEND6_CONTROL +0x0002879C CB_BLEND7_CONTROL +0x000287CC CS_COPY_STATE +0x000287D0 GFX_COPY_STATE +0x000287D4 PA_CL_POINT_X_RAD +0x000287D8 PA_CL_POINT_Y_RAD +0x000287DC PA_CL_POINT_SIZE +0x000287E0 PA_CL_POINT_CULL_RAD +0x00028808 CB_COLOR_CONTROL +0x0002880C DB_SHADER_CONTROL +0x00028810 PA_CL_CLIP_CNTL +0x00028814 PA_SU_SC_MODE_CNTL +0x00028818 PA_CL_VTE_CNTL +0x0002881C PA_CL_VS_OUT_CNTL +0x00028820 PA_CL_NANINF_CNTL +0x00028824 PA_SU_LINE_STIPPLE_CNTL +0x00028828 PA_SU_LINE_STIPPLE_SCALE +0x0002882C PA_SU_PRIM_FILTER_CNTL +0x00028844 SQ_PGM_RESOURCES_PS +0x00028848 SQ_PGM_RESOURCES_2_PS +0x0002884C SQ_PGM_EXPORTS_PS +0x00028860 SQ_PGM_RESOURCES_VS +0x00028864 SQ_PGM_RESOURCES_2_VS +0x00028878 SQ_PGM_RESOURCES_GS +0x0002887C SQ_PGM_RESOURCES_2_GS +0x00028890 SQ_PGM_RESOURCES_ES +0x00028894 SQ_PGM_RESOURCES_2_ES +0x000288A8 SQ_PGM_RESOURCES_FS +0x000288BC SQ_PGM_RESOURCES_HS +0x000288C0 SQ_PGM_RESOURCES_2_HS +0x000288D4 SQ_PGM_RESOURCES_LS +0x000288D8 SQ_PGM_RESOURCES_2_LS +0x000288E8 SQ_LDS_ALLOC +0x000288EC SQ_LDS_ALLOC_PS +0x000288F0 SQ_VTX_SEMANTIC_CLEAR +0x00028A00 PA_SU_POINT_SIZE +0x00028A04 PA_SU_POINT_MINMAX +0x00028A08 PA_SU_LINE_CNTL +0x00028A0C PA_SC_LINE_STIPPLE +0x00028A10 VGT_OUTPUT_PATH_CNTL +0x00028A14 VGT_HOS_CNTL +0x00028A18 VGT_HOS_MAX_TESS_LEVEL +0x00028A1C VGT_HOS_MIN_TESS_LEVEL +0x00028A20 VGT_HOS_REUSE_DEPTH +0x00028A24 VGT_GROUP_PRIM_TYPE +0x00028A28 VGT_GROUP_FIRST_DECR +0x00028A2C VGT_GROUP_DECR +0x00028A30 VGT_GROUP_VECT_0_CNTL +0x00028A34 VGT_GROUP_VECT_1_CNTL +0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL +0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL +0x00028A40 VGT_GS_MODE +0x00028A48 PA_SC_MODE_CNTL_0 +0x00028A4C PA_SC_MODE_CNTL_1 +0x00028A50 VGT_ENHANCE +0x00028A54 VGT_GS_PER_ES +0x00028A58 VGT_ES_PER_GS +0x00028A5C VGT_GS_PER_VS +0x00028A6C VGT_GS_OUT_PRIM_TYPE +0x00028A70 IA_ENHANCE +0x00028A84 VGT_PRIMITIVEID_EN +0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN +0x00028AA0 VGT_INSTANCE_STEP_RATE_0 +0x00028AA4 VGT_INSTANCE_STEP_RATE_1 +0x00028AA8 IA_MULTI_VGT_PARAM +0x00028AB4 VGT_REUSE_OFF +0x00028AB8 VGT_VTX_CNT_EN +0x00028AC0 DB_SRESULTS_COMPARE_STATE0 +0x00028AC4 DB_SRESULTS_COMPARE_STATE1 +0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE +0x00028B38 VGT_GS_MAX_VERT_OUT +0x00028B54 VGT_SHADER_STAGES_EN +0x00028B58 VGT_LS_HS_CONFIG +0x00028B6C VGT_TF_PARAM +0x00028B70 DB_ALPHA_TO_MASK +0x00028B74 VGT_DISPATCH_INITIATOR +0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL +0x00028B7C PA_SU_POLY_OFFSET_CLAMP +0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE +0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET +0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE +0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET +0x00028B74 VGT_GS_INSTANCE_CNT +0x00028BD4 PA_SC_CENTROID_PRIORITY_0 +0x00028BD8 PA_SC_CENTROID_PRIORITY_1 +0x00028BDC PA_SC_LINE_CNTL +0x00028BE4 PA_SU_VTX_CNTL +0x00028BE8 PA_CL_GB_VERT_CLIP_ADJ +0x00028BEC PA_CL_GB_VERT_DISC_ADJ +0x00028BF0 PA_CL_GB_HORZ_CLIP_ADJ +0x00028BF4 PA_CL_GB_HORZ_DISC_ADJ +0x00028BF8 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_0 +0x00028BFC PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_1 +0x00028C00 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_2 +0x00028C04 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_3 +0x00028C08 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_0 +0x00028C0C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_1 +0x00028C10 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_2 +0x00028C14 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_3 +0x00028C18 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_0 +0x00028C1C PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_1 +0x00028C20 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_2 +0x00028C24 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_3 +0x00028C28 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_0 +0x00028C2C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_1 +0x00028C30 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_2 +0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3 +0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0 +0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1 +0x00028C78 CB_COLOR0_DIM +0x00028CB4 CB_COLOR1_DIM +0x00028CF0 CB_COLOR2_DIM +0x00028D2C CB_COLOR3_DIM +0x00028D68 CB_COLOR4_DIM +0x00028DA4 CB_COLOR5_DIM +0x00028DE0 CB_COLOR6_DIM +0x00028E1C CB_COLOR7_DIM +0x00028E58 CB_COLOR8_DIM +0x00028E74 CB_COLOR9_DIM +0x00028E90 CB_COLOR10_DIM +0x00028EAC CB_COLOR11_DIM +0x00028C8C CB_COLOR0_CLEAR_WORD0 +0x00028C90 CB_COLOR0_CLEAR_WORD1 +0x00028C94 CB_COLOR0_CLEAR_WORD2 +0x00028C98 CB_COLOR0_CLEAR_WORD3 +0x00028CC8 CB_COLOR1_CLEAR_WORD0 +0x00028CCC CB_COLOR1_CLEAR_WORD1 +0x00028CD0 CB_COLOR1_CLEAR_WORD2 +0x00028CD4 CB_COLOR1_CLEAR_WORD3 +0x00028D04 CB_COLOR2_CLEAR_WORD0 +0x00028D08 CB_COLOR2_CLEAR_WORD1 +0x00028D0C CB_COLOR2_CLEAR_WORD2 +0x00028D10 CB_COLOR2_CLEAR_WORD3 +0x00028D40 CB_COLOR3_CLEAR_WORD0 +0x00028D44 CB_COLOR3_CLEAR_WORD1 +0x00028D48 CB_COLOR3_CLEAR_WORD2 +0x00028D4C CB_COLOR3_CLEAR_WORD3 +0x00028D7C CB_COLOR4_CLEAR_WORD0 +0x00028D80 CB_COLOR4_CLEAR_WORD1 +0x00028D84 CB_COLOR4_CLEAR_WORD2 +0x00028D88 CB_COLOR4_CLEAR_WORD3 +0x00028DB8 CB_COLOR5_CLEAR_WORD0 +0x00028DBC CB_COLOR5_CLEAR_WORD1 +0x00028DC0 CB_COLOR5_CLEAR_WORD2 +0x00028DC4 CB_COLOR5_CLEAR_WORD3 +0x00028DF4 CB_COLOR6_CLEAR_WORD0 +0x00028DF8 CB_COLOR6_CLEAR_WORD1 +0x00028DFC CB_COLOR6_CLEAR_WORD2 +0x00028E00 CB_COLOR6_CLEAR_WORD3 +0x00028E30 CB_COLOR7_CLEAR_WORD0 +0x00028E34 CB_COLOR7_CLEAR_WORD1 +0x00028E38 CB_COLOR7_CLEAR_WORD2 +0x00028E3C CB_COLOR7_CLEAR_WORD3 +0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0 +0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1 +0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2 +0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3 +0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4 +0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5 +0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6 +0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7 +0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8 +0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9 +0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10 +0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11 +0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12 +0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13 +0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14 +0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15 +0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0 +0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1 +0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2 +0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3 +0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4 +0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5 +0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6 +0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7 +0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8 +0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9 +0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10 +0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11 +0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12 +0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13 +0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14 +0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15 +0x0003CFF0 SQ_VTX_BASE_VTX_LOC +0x0003CFF4 SQ_VTX_START_INST_LOC +0x0003FF00 SQ_TEX_SAMPLER_CLEAR +0x0003FF04 SQ_TEX_RESOURCE_CLEAR +0x0003FF08 SQ_LOOP_BOOL_CLEAR diff --git a/sys/dev/drm2/radeon/reg_srcs/evergreen b/sys/dev/drm2/radeon/reg_srcs/evergreen new file mode 100644 index 00000000000..b912a37689b --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/evergreen @@ -0,0 +1,644 @@ +evergreen 0x9400 +0x0000802C GRBM_GFX_INDEX +0x00008040 WAIT_UNTIL +0x00008044 WAIT_UNTIL_POLL_CNTL +0x00008048 WAIT_UNTIL_POLL_MASK +0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE +0x000088B0 VGT_VTX_VECT_EJECT_REG +0x000088C4 VGT_CACHE_INVALIDATION +0x000088D4 VGT_GS_VERTEX_REUSE +0x00008958 VGT_PRIMITIVE_TYPE +0x0000895C VGT_INDEX_TYPE +0x00008970 VGT_NUM_INDICES +0x00008974 VGT_NUM_INSTANCES +0x00008990 VGT_COMPUTE_DIM_X +0x00008994 VGT_COMPUTE_DIM_Y +0x00008998 VGT_COMPUTE_DIM_Z +0x0000899C VGT_COMPUTE_START_X +0x000089A0 VGT_COMPUTE_START_Y +0x000089A4 VGT_COMPUTE_START_Z +0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE +0x00008A14 PA_CL_ENHANCE +0x00008A60 PA_SC_LINE_STIPPLE_VALUE +0x00008B10 PA_SC_LINE_STIPPLE_STATE +0x00008BF0 PA_SC_ENHANCE +0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008D90 SQ_DYN_GPR_OPTIMIZATION +0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN +0x00008D98 SQ_DYN_GPR_THREAD_LIMIT +0x00008D9C SQ_DYN_GPR_LDS_LIMIT +0x00008C00 SQ_CONFIG +0x00008C04 SQ_GPR_RESOURCE_MGMT_1 +0x00008C08 SQ_GPR_RESOURCE_MGMT_2 +0x00008C0C SQ_GPR_RESOURCE_MGMT_3 +0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1 +0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2 +0x00008C18 SQ_THREAD_RESOURCE_MGMT +0x00008C1C SQ_THREAD_RESOURCE_MGMT_2 +0x00008C20 SQ_STACK_RESOURCE_MGMT_1 +0x00008C24 SQ_STACK_RESOURCE_MGMT_2 +0x00008C28 SQ_STACK_RESOURCE_MGMT_3 +0x00008DF8 SQ_CONST_MEM_BASE +0x00008E20 SQ_STATIC_THREAD_MGMT_1 +0x00008E24 SQ_STATIC_THREAD_MGMT_2 +0x00008E28 SQ_STATIC_THREAD_MGMT_3 +0x00008E2C SQ_LDS_RESOURCE_MGMT +0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS +0x00009014 SX_MEMORY_EXPORT_SIZE +0x00009100 SPI_CONFIG_CNTL +0x0000913C SPI_CONFIG_CNTL_1 +0x00009508 TA_CNTL_AUX +0x00009700 VC_CNTL +0x00009714 VC_ENHANCE +0x00009830 DB_DEBUG +0x00009834 DB_DEBUG2 +0x00009838 DB_DEBUG3 +0x0000983C DB_DEBUG4 +0x00009854 DB_WATERMARKS +0x0000A400 TD_PS_BORDER_COLOR_INDEX +0x0000A404 TD_PS_BORDER_COLOR_RED +0x0000A408 TD_PS_BORDER_COLOR_GREEN +0x0000A40C TD_PS_BORDER_COLOR_BLUE +0x0000A410 TD_PS_BORDER_COLOR_ALPHA +0x0000A414 TD_VS_BORDER_COLOR_INDEX +0x0000A418 TD_VS_BORDER_COLOR_RED +0x0000A41C TD_VS_BORDER_COLOR_GREEN +0x0000A420 TD_VS_BORDER_COLOR_BLUE +0x0000A424 TD_VS_BORDER_COLOR_ALPHA +0x0000A428 TD_GS_BORDER_COLOR_INDEX +0x0000A42C TD_GS_BORDER_COLOR_RED +0x0000A430 TD_GS_BORDER_COLOR_GREEN +0x0000A434 TD_GS_BORDER_COLOR_BLUE +0x0000A438 TD_GS_BORDER_COLOR_ALPHA +0x0000A43C TD_HS_BORDER_COLOR_INDEX +0x0000A440 TD_HS_BORDER_COLOR_RED +0x0000A444 TD_HS_BORDER_COLOR_GREEN +0x0000A448 TD_HS_BORDER_COLOR_BLUE +0x0000A44C TD_HS_BORDER_COLOR_ALPHA +0x0000A450 TD_LS_BORDER_COLOR_INDEX +0x0000A454 TD_LS_BORDER_COLOR_RED +0x0000A458 TD_LS_BORDER_COLOR_GREEN +0x0000A45C TD_LS_BORDER_COLOR_BLUE +0x0000A460 TD_LS_BORDER_COLOR_ALPHA +0x0000A464 TD_CS_BORDER_COLOR_INDEX +0x0000A468 TD_CS_BORDER_COLOR_RED +0x0000A46C TD_CS_BORDER_COLOR_GREEN +0x0000A470 TD_CS_BORDER_COLOR_BLUE +0x0000A474 TD_CS_BORDER_COLOR_ALPHA +0x00028000 DB_RENDER_CONTROL +0x00028004 DB_COUNT_CONTROL +0x0002800C DB_RENDER_OVERRIDE +0x00028010 DB_RENDER_OVERRIDE2 +0x00028028 DB_STENCIL_CLEAR +0x0002802C DB_DEPTH_CLEAR +0x00028030 PA_SC_SCREEN_SCISSOR_TL +0x00028034 PA_SC_SCREEN_SCISSOR_BR +0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 +0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 +0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 +0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3 +0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4 +0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5 +0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6 +0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7 +0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8 +0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9 +0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10 +0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11 +0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12 +0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13 +0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14 +0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15 +0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0 +0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1 +0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2 +0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3 +0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4 +0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5 +0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6 +0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7 +0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8 +0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9 +0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10 +0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11 +0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12 +0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13 +0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14 +0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15 +0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0 +0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1 +0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2 +0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3 +0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4 +0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5 +0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6 +0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7 +0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8 +0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9 +0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10 +0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11 +0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12 +0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13 +0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14 +0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15 +0x00028200 PA_SC_WINDOW_OFFSET +0x00028204 PA_SC_WINDOW_SCISSOR_TL +0x00028208 PA_SC_WINDOW_SCISSOR_BR +0x0002820C PA_SC_CLIPRECT_RULE +0x00028210 PA_SC_CLIPRECT_0_TL +0x00028214 PA_SC_CLIPRECT_0_BR +0x00028218 PA_SC_CLIPRECT_1_TL +0x0002821C PA_SC_CLIPRECT_1_BR +0x00028220 PA_SC_CLIPRECT_2_TL +0x00028224 PA_SC_CLIPRECT_2_BR +0x00028228 PA_SC_CLIPRECT_3_TL +0x0002822C PA_SC_CLIPRECT_3_BR +0x00028230 PA_SC_EDGERULE +0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET +0x00028240 PA_SC_GENERIC_SCISSOR_TL +0x00028244 PA_SC_GENERIC_SCISSOR_BR +0x00028250 PA_SC_VPORT_SCISSOR_0_TL +0x00028254 PA_SC_VPORT_SCISSOR_0_BR +0x00028258 PA_SC_VPORT_SCISSOR_1_TL +0x0002825C PA_SC_VPORT_SCISSOR_1_BR +0x00028260 PA_SC_VPORT_SCISSOR_2_TL +0x00028264 PA_SC_VPORT_SCISSOR_2_BR +0x00028268 PA_SC_VPORT_SCISSOR_3_TL +0x0002826C PA_SC_VPORT_SCISSOR_3_BR +0x00028270 PA_SC_VPORT_SCISSOR_4_TL +0x00028274 PA_SC_VPORT_SCISSOR_4_BR +0x00028278 PA_SC_VPORT_SCISSOR_5_TL +0x0002827C PA_SC_VPORT_SCISSOR_5_BR +0x00028280 PA_SC_VPORT_SCISSOR_6_TL +0x00028284 PA_SC_VPORT_SCISSOR_6_BR +0x00028288 PA_SC_VPORT_SCISSOR_7_TL +0x0002828C PA_SC_VPORT_SCISSOR_7_BR +0x00028290 PA_SC_VPORT_SCISSOR_8_TL +0x00028294 PA_SC_VPORT_SCISSOR_8_BR +0x00028298 PA_SC_VPORT_SCISSOR_9_TL +0x0002829C PA_SC_VPORT_SCISSOR_9_BR +0x000282A0 PA_SC_VPORT_SCISSOR_10_TL +0x000282A4 PA_SC_VPORT_SCISSOR_10_BR +0x000282A8 PA_SC_VPORT_SCISSOR_11_TL +0x000282AC PA_SC_VPORT_SCISSOR_11_BR +0x000282B0 PA_SC_VPORT_SCISSOR_12_TL +0x000282B4 PA_SC_VPORT_SCISSOR_12_BR +0x000282B8 PA_SC_VPORT_SCISSOR_13_TL +0x000282BC PA_SC_VPORT_SCISSOR_13_BR +0x000282C0 PA_SC_VPORT_SCISSOR_14_TL +0x000282C4 PA_SC_VPORT_SCISSOR_14_BR +0x000282C8 PA_SC_VPORT_SCISSOR_15_TL +0x000282CC PA_SC_VPORT_SCISSOR_15_BR +0x000282D0 PA_SC_VPORT_ZMIN_0 +0x000282D4 PA_SC_VPORT_ZMAX_0 +0x000282D8 PA_SC_VPORT_ZMIN_1 +0x000282DC PA_SC_VPORT_ZMAX_1 +0x000282E0 PA_SC_VPORT_ZMIN_2 +0x000282E4 PA_SC_VPORT_ZMAX_2 +0x000282E8 PA_SC_VPORT_ZMIN_3 +0x000282EC PA_SC_VPORT_ZMAX_3 +0x000282F0 PA_SC_VPORT_ZMIN_4 +0x000282F4 PA_SC_VPORT_ZMAX_4 +0x000282F8 PA_SC_VPORT_ZMIN_5 +0x000282FC PA_SC_VPORT_ZMAX_5 +0x00028300 PA_SC_VPORT_ZMIN_6 +0x00028304 PA_SC_VPORT_ZMAX_6 +0x00028308 PA_SC_VPORT_ZMIN_7 +0x0002830C PA_SC_VPORT_ZMAX_7 +0x00028310 PA_SC_VPORT_ZMIN_8 +0x00028314 PA_SC_VPORT_ZMAX_8 +0x00028318 PA_SC_VPORT_ZMIN_9 +0x0002831C PA_SC_VPORT_ZMAX_9 +0x00028320 PA_SC_VPORT_ZMIN_10 +0x00028324 PA_SC_VPORT_ZMAX_10 +0x00028328 PA_SC_VPORT_ZMIN_11 +0x0002832C PA_SC_VPORT_ZMAX_11 +0x00028330 PA_SC_VPORT_ZMIN_12 +0x00028334 PA_SC_VPORT_ZMAX_12 +0x00028338 PA_SC_VPORT_ZMIN_13 +0x0002833C PA_SC_VPORT_ZMAX_13 +0x00028340 PA_SC_VPORT_ZMIN_14 +0x00028344 PA_SC_VPORT_ZMAX_14 +0x00028348 PA_SC_VPORT_ZMIN_15 +0x0002834C PA_SC_VPORT_ZMAX_15 +0x00028354 SX_SURFACE_SYNC +0x00028380 SQ_VTX_SEMANTIC_0 +0x00028384 SQ_VTX_SEMANTIC_1 +0x00028388 SQ_VTX_SEMANTIC_2 +0x0002838C SQ_VTX_SEMANTIC_3 +0x00028390 SQ_VTX_SEMANTIC_4 +0x00028394 SQ_VTX_SEMANTIC_5 +0x00028398 SQ_VTX_SEMANTIC_6 +0x0002839C SQ_VTX_SEMANTIC_7 +0x000283A0 SQ_VTX_SEMANTIC_8 +0x000283A4 SQ_VTX_SEMANTIC_9 +0x000283A8 SQ_VTX_SEMANTIC_10 +0x000283AC SQ_VTX_SEMANTIC_11 +0x000283B0 SQ_VTX_SEMANTIC_12 +0x000283B4 SQ_VTX_SEMANTIC_13 +0x000283B8 SQ_VTX_SEMANTIC_14 +0x000283BC SQ_VTX_SEMANTIC_15 +0x000283C0 SQ_VTX_SEMANTIC_16 +0x000283C4 SQ_VTX_SEMANTIC_17 +0x000283C8 SQ_VTX_SEMANTIC_18 +0x000283CC SQ_VTX_SEMANTIC_19 +0x000283D0 SQ_VTX_SEMANTIC_20 +0x000283D4 SQ_VTX_SEMANTIC_21 +0x000283D8 SQ_VTX_SEMANTIC_22 +0x000283DC SQ_VTX_SEMANTIC_23 +0x000283E0 SQ_VTX_SEMANTIC_24 +0x000283E4 SQ_VTX_SEMANTIC_25 +0x000283E8 SQ_VTX_SEMANTIC_26 +0x000283EC SQ_VTX_SEMANTIC_27 +0x000283F0 SQ_VTX_SEMANTIC_28 +0x000283F4 SQ_VTX_SEMANTIC_29 +0x000283F8 SQ_VTX_SEMANTIC_30 +0x000283FC SQ_VTX_SEMANTIC_31 +0x00028400 VGT_MAX_VTX_INDX +0x00028404 VGT_MIN_VTX_INDX +0x00028408 VGT_INDX_OFFSET +0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX +0x00028410 SX_ALPHA_TEST_CONTROL +0x00028414 CB_BLEND_RED +0x00028418 CB_BLEND_GREEN +0x0002841C CB_BLEND_BLUE +0x00028420 CB_BLEND_ALPHA +0x00028430 DB_STENCILREFMASK +0x00028434 DB_STENCILREFMASK_BF +0x00028438 SX_ALPHA_REF +0x0002843C PA_CL_VPORT_XSCALE_0 +0x00028440 PA_CL_VPORT_XOFFSET_0 +0x00028444 PA_CL_VPORT_YSCALE_0 +0x00028448 PA_CL_VPORT_YOFFSET_0 +0x0002844C PA_CL_VPORT_ZSCALE_0 +0x00028450 PA_CL_VPORT_ZOFFSET_0 +0x00028454 PA_CL_VPORT_XSCALE_1 +0x00028458 PA_CL_VPORT_XOFFSET_1 +0x0002845C PA_CL_VPORT_YSCALE_1 +0x00028460 PA_CL_VPORT_YOFFSET_1 +0x00028464 PA_CL_VPORT_ZSCALE_1 +0x00028468 PA_CL_VPORT_ZOFFSET_1 +0x0002846C PA_CL_VPORT_XSCALE_2 +0x00028470 PA_CL_VPORT_XOFFSET_2 +0x00028474 PA_CL_VPORT_YSCALE_2 +0x00028478 PA_CL_VPORT_YOFFSET_2 +0x0002847C PA_CL_VPORT_ZSCALE_2 +0x00028480 PA_CL_VPORT_ZOFFSET_2 +0x00028484 PA_CL_VPORT_XSCALE_3 +0x00028488 PA_CL_VPORT_XOFFSET_3 +0x0002848C PA_CL_VPORT_YSCALE_3 +0x00028490 PA_CL_VPORT_YOFFSET_3 +0x00028494 PA_CL_VPORT_ZSCALE_3 +0x00028498 PA_CL_VPORT_ZOFFSET_3 +0x0002849C PA_CL_VPORT_XSCALE_4 +0x000284A0 PA_CL_VPORT_XOFFSET_4 +0x000284A4 PA_CL_VPORT_YSCALE_4 +0x000284A8 PA_CL_VPORT_YOFFSET_4 +0x000284AC PA_CL_VPORT_ZSCALE_4 +0x000284B0 PA_CL_VPORT_ZOFFSET_4 +0x000284B4 PA_CL_VPORT_XSCALE_5 +0x000284B8 PA_CL_VPORT_XOFFSET_5 +0x000284BC PA_CL_VPORT_YSCALE_5 +0x000284C0 PA_CL_VPORT_YOFFSET_5 +0x000284C4 PA_CL_VPORT_ZSCALE_5 +0x000284C8 PA_CL_VPORT_ZOFFSET_5 +0x000284CC PA_CL_VPORT_XSCALE_6 +0x000284D0 PA_CL_VPORT_XOFFSET_6 +0x000284D4 PA_CL_VPORT_YSCALE_6 +0x000284D8 PA_CL_VPORT_YOFFSET_6 +0x000284DC PA_CL_VPORT_ZSCALE_6 +0x000284E0 PA_CL_VPORT_ZOFFSET_6 +0x000284E4 PA_CL_VPORT_XSCALE_7 +0x000284E8 PA_CL_VPORT_XOFFSET_7 +0x000284EC PA_CL_VPORT_YSCALE_7 +0x000284F0 PA_CL_VPORT_YOFFSET_7 +0x000284F4 PA_CL_VPORT_ZSCALE_7 +0x000284F8 PA_CL_VPORT_ZOFFSET_7 +0x000284FC PA_CL_VPORT_XSCALE_8 +0x00028500 PA_CL_VPORT_XOFFSET_8 +0x00028504 PA_CL_VPORT_YSCALE_8 +0x00028508 PA_CL_VPORT_YOFFSET_8 +0x0002850C PA_CL_VPORT_ZSCALE_8 +0x00028510 PA_CL_VPORT_ZOFFSET_8 +0x00028514 PA_CL_VPORT_XSCALE_9 +0x00028518 PA_CL_VPORT_XOFFSET_9 +0x0002851C PA_CL_VPORT_YSCALE_9 +0x00028520 PA_CL_VPORT_YOFFSET_9 +0x00028524 PA_CL_VPORT_ZSCALE_9 +0x00028528 PA_CL_VPORT_ZOFFSET_9 +0x0002852C PA_CL_VPORT_XSCALE_10 +0x00028530 PA_CL_VPORT_XOFFSET_10 +0x00028534 PA_CL_VPORT_YSCALE_10 +0x00028538 PA_CL_VPORT_YOFFSET_10 +0x0002853C PA_CL_VPORT_ZSCALE_10 +0x00028540 PA_CL_VPORT_ZOFFSET_10 +0x00028544 PA_CL_VPORT_XSCALE_11 +0x00028548 PA_CL_VPORT_XOFFSET_11 +0x0002854C PA_CL_VPORT_YSCALE_11 +0x00028550 PA_CL_VPORT_YOFFSET_11 +0x00028554 PA_CL_VPORT_ZSCALE_11 +0x00028558 PA_CL_VPORT_ZOFFSET_11 +0x0002855C PA_CL_VPORT_XSCALE_12 +0x00028560 PA_CL_VPORT_XOFFSET_12 +0x00028564 PA_CL_VPORT_YSCALE_12 +0x00028568 PA_CL_VPORT_YOFFSET_12 +0x0002856C PA_CL_VPORT_ZSCALE_12 +0x00028570 PA_CL_VPORT_ZOFFSET_12 +0x00028574 PA_CL_VPORT_XSCALE_13 +0x00028578 PA_CL_VPORT_XOFFSET_13 +0x0002857C PA_CL_VPORT_YSCALE_13 +0x00028580 PA_CL_VPORT_YOFFSET_13 +0x00028584 PA_CL_VPORT_ZSCALE_13 +0x00028588 PA_CL_VPORT_ZOFFSET_13 +0x0002858C PA_CL_VPORT_XSCALE_14 +0x00028590 PA_CL_VPORT_XOFFSET_14 +0x00028594 PA_CL_VPORT_YSCALE_14 +0x00028598 PA_CL_VPORT_YOFFSET_14 +0x0002859C PA_CL_VPORT_ZSCALE_14 +0x000285A0 PA_CL_VPORT_ZOFFSET_14 +0x000285A4 PA_CL_VPORT_XSCALE_15 +0x000285A8 PA_CL_VPORT_XOFFSET_15 +0x000285AC PA_CL_VPORT_YSCALE_15 +0x000285B0 PA_CL_VPORT_YOFFSET_15 +0x000285B4 PA_CL_VPORT_ZSCALE_15 +0x000285B8 PA_CL_VPORT_ZOFFSET_15 +0x000285BC PA_CL_UCP_0_X +0x000285C0 PA_CL_UCP_0_Y +0x000285C4 PA_CL_UCP_0_Z +0x000285C8 PA_CL_UCP_0_W +0x000285CC PA_CL_UCP_1_X +0x000285D0 PA_CL_UCP_1_Y +0x000285D4 PA_CL_UCP_1_Z +0x000285D8 PA_CL_UCP_1_W +0x000285DC PA_CL_UCP_2_X +0x000285E0 PA_CL_UCP_2_Y +0x000285E4 PA_CL_UCP_2_Z +0x000285E8 PA_CL_UCP_2_W +0x000285EC PA_CL_UCP_3_X +0x000285F0 PA_CL_UCP_3_Y +0x000285F4 PA_CL_UCP_3_Z +0x000285F8 PA_CL_UCP_3_W +0x000285FC PA_CL_UCP_4_X +0x00028600 PA_CL_UCP_4_Y +0x00028604 PA_CL_UCP_4_Z +0x00028608 PA_CL_UCP_4_W +0x0002860C PA_CL_UCP_5_X +0x00028610 PA_CL_UCP_5_Y +0x00028614 PA_CL_UCP_5_Z +0x00028618 PA_CL_UCP_5_W +0x0002861C SPI_VS_OUT_ID_0 +0x00028620 SPI_VS_OUT_ID_1 +0x00028624 SPI_VS_OUT_ID_2 +0x00028628 SPI_VS_OUT_ID_3 +0x0002862C SPI_VS_OUT_ID_4 +0x00028630 SPI_VS_OUT_ID_5 +0x00028634 SPI_VS_OUT_ID_6 +0x00028638 SPI_VS_OUT_ID_7 +0x0002863C SPI_VS_OUT_ID_8 +0x00028640 SPI_VS_OUT_ID_9 +0x00028644 SPI_PS_INPUT_CNTL_0 +0x00028648 SPI_PS_INPUT_CNTL_1 +0x0002864C SPI_PS_INPUT_CNTL_2 +0x00028650 SPI_PS_INPUT_CNTL_3 +0x00028654 SPI_PS_INPUT_CNTL_4 +0x00028658 SPI_PS_INPUT_CNTL_5 +0x0002865C SPI_PS_INPUT_CNTL_6 +0x00028660 SPI_PS_INPUT_CNTL_7 +0x00028664 SPI_PS_INPUT_CNTL_8 +0x00028668 SPI_PS_INPUT_CNTL_9 +0x0002866C SPI_PS_INPUT_CNTL_10 +0x00028670 SPI_PS_INPUT_CNTL_11 +0x00028674 SPI_PS_INPUT_CNTL_12 +0x00028678 SPI_PS_INPUT_CNTL_13 +0x0002867C SPI_PS_INPUT_CNTL_14 +0x00028680 SPI_PS_INPUT_CNTL_15 +0x00028684 SPI_PS_INPUT_CNTL_16 +0x00028688 SPI_PS_INPUT_CNTL_17 +0x0002868C SPI_PS_INPUT_CNTL_18 +0x00028690 SPI_PS_INPUT_CNTL_19 +0x00028694 SPI_PS_INPUT_CNTL_20 +0x00028698 SPI_PS_INPUT_CNTL_21 +0x0002869C SPI_PS_INPUT_CNTL_22 +0x000286A0 SPI_PS_INPUT_CNTL_23 +0x000286A4 SPI_PS_INPUT_CNTL_24 +0x000286A8 SPI_PS_INPUT_CNTL_25 +0x000286AC SPI_PS_INPUT_CNTL_26 +0x000286B0 SPI_PS_INPUT_CNTL_27 +0x000286B4 SPI_PS_INPUT_CNTL_28 +0x000286B8 SPI_PS_INPUT_CNTL_29 +0x000286BC SPI_PS_INPUT_CNTL_30 +0x000286C0 SPI_PS_INPUT_CNTL_31 +0x000286C4 SPI_VS_OUT_CONFIG +0x000286C8 SPI_THREAD_GROUPING +0x000286CC SPI_PS_IN_CONTROL_0 +0x000286D0 SPI_PS_IN_CONTROL_1 +0x000286D4 SPI_INTERP_CONTROL_0 +0x000286D8 SPI_INPUT_Z +0x000286DC SPI_FOG_CNTL +0x000286E0 SPI_BARYC_CNTL +0x000286E4 SPI_PS_IN_CONTROL_2 +0x000286E8 SPI_COMPUTE_INPUT_CNTL +0x000286EC SPI_COMPUTE_NUM_THREAD_X +0x000286F0 SPI_COMPUTE_NUM_THREAD_Y +0x000286F4 SPI_COMPUTE_NUM_THREAD_Z +0x00028720 GDS_ADDR_BASE +0x00028724 GDS_ADDR_SIZE +0x00028728 GDS_ORDERED_WAVE_PER_SE +0x00028780 CB_BLEND0_CONTROL +0x00028784 CB_BLEND1_CONTROL +0x00028788 CB_BLEND2_CONTROL +0x0002878C CB_BLEND3_CONTROL +0x00028790 CB_BLEND4_CONTROL +0x00028794 CB_BLEND5_CONTROL +0x00028798 CB_BLEND6_CONTROL +0x0002879C CB_BLEND7_CONTROL +0x000287CC CS_COPY_STATE +0x000287D0 GFX_COPY_STATE +0x000287D4 PA_CL_POINT_X_RAD +0x000287D8 PA_CL_POINT_Y_RAD +0x000287DC PA_CL_POINT_SIZE +0x000287E0 PA_CL_POINT_CULL_RAD +0x00028808 CB_COLOR_CONTROL +0x0002880C DB_SHADER_CONTROL +0x00028810 PA_CL_CLIP_CNTL +0x00028814 PA_SU_SC_MODE_CNTL +0x00028818 PA_CL_VTE_CNTL +0x0002881C PA_CL_VS_OUT_CNTL +0x00028820 PA_CL_NANINF_CNTL +0x00028824 PA_SU_LINE_STIPPLE_CNTL +0x00028828 PA_SU_LINE_STIPPLE_SCALE +0x0002882C PA_SU_PRIM_FILTER_CNTL +0x00028838 SQ_DYN_GPR_RESOURCE_LIMIT_1 +0x00028844 SQ_PGM_RESOURCES_PS +0x00028848 SQ_PGM_RESOURCES_2_PS +0x0002884C SQ_PGM_EXPORTS_PS +0x00028860 SQ_PGM_RESOURCES_VS +0x00028864 SQ_PGM_RESOURCES_2_VS +0x00028878 SQ_PGM_RESOURCES_GS +0x0002887C SQ_PGM_RESOURCES_2_GS +0x00028890 SQ_PGM_RESOURCES_ES +0x00028894 SQ_PGM_RESOURCES_2_ES +0x000288A8 SQ_PGM_RESOURCES_FS +0x000288BC SQ_PGM_RESOURCES_HS +0x000288C0 SQ_PGM_RESOURCES_2_HS +0x000288D4 SQ_PGM_RESOURCES_LS +0x000288D8 SQ_PGM_RESOURCES_2_LS +0x000288E8 SQ_LDS_ALLOC +0x000288EC SQ_LDS_ALLOC_PS +0x000288F0 SQ_VTX_SEMANTIC_CLEAR +0x00028A00 PA_SU_POINT_SIZE +0x00028A04 PA_SU_POINT_MINMAX +0x00028A08 PA_SU_LINE_CNTL +0x00028A0C PA_SC_LINE_STIPPLE +0x00028A10 VGT_OUTPUT_PATH_CNTL +0x00028A14 VGT_HOS_CNTL +0x00028A18 VGT_HOS_MAX_TESS_LEVEL +0x00028A1C VGT_HOS_MIN_TESS_LEVEL +0x00028A20 VGT_HOS_REUSE_DEPTH +0x00028A24 VGT_GROUP_PRIM_TYPE +0x00028A28 VGT_GROUP_FIRST_DECR +0x00028A2C VGT_GROUP_DECR +0x00028A30 VGT_GROUP_VECT_0_CNTL +0x00028A34 VGT_GROUP_VECT_1_CNTL +0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL +0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL +0x00028A40 VGT_GS_MODE +0x00028A48 PA_SC_MODE_CNTL_0 +0x00028A4C PA_SC_MODE_CNTL_1 +0x00028A50 VGT_ENHANCE +0x00028A54 VGT_GS_PER_ES +0x00028A58 VGT_ES_PER_GS +0x00028A5C VGT_GS_PER_VS +0x00028A6C VGT_GS_OUT_PRIM_TYPE +0x00028A84 VGT_PRIMITIVEID_EN +0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN +0x00028AA0 VGT_INSTANCE_STEP_RATE_0 +0x00028AA4 VGT_INSTANCE_STEP_RATE_1 +0x00028AB4 VGT_REUSE_OFF +0x00028AB8 VGT_VTX_CNT_EN +0x00028AC0 DB_SRESULTS_COMPARE_STATE0 +0x00028AC4 DB_SRESULTS_COMPARE_STATE1 +0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE +0x00028B38 VGT_GS_MAX_VERT_OUT +0x00028B54 VGT_SHADER_STAGES_EN +0x00028B58 VGT_LS_HS_CONFIG +0x00028B5C VGT_LS_SIZE +0x00028B60 VGT_HS_SIZE +0x00028B64 VGT_LS_HS_ALLOC +0x00028B68 VGT_HS_PATCH_CONST +0x00028B6C VGT_TF_PARAM +0x00028B70 DB_ALPHA_TO_MASK +0x00028B74 VGT_DISPATCH_INITIATOR +0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL +0x00028B7C PA_SU_POLY_OFFSET_CLAMP +0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE +0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET +0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE +0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET +0x00028B74 VGT_GS_INSTANCE_CNT +0x00028C00 PA_SC_LINE_CNTL +0x00028C08 PA_SU_VTX_CNTL +0x00028C0C PA_CL_GB_VERT_CLIP_ADJ +0x00028C10 PA_CL_GB_VERT_DISC_ADJ +0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ +0x00028C18 PA_CL_GB_HORZ_DISC_ADJ +0x00028C1C PA_SC_AA_SAMPLE_LOCS_0 +0x00028C20 PA_SC_AA_SAMPLE_LOCS_1 +0x00028C24 PA_SC_AA_SAMPLE_LOCS_2 +0x00028C28 PA_SC_AA_SAMPLE_LOCS_3 +0x00028C2C PA_SC_AA_SAMPLE_LOCS_4 +0x00028C30 PA_SC_AA_SAMPLE_LOCS_5 +0x00028C34 PA_SC_AA_SAMPLE_LOCS_6 +0x00028C38 PA_SC_AA_SAMPLE_LOCS_7 +0x00028C3C PA_SC_AA_MASK +0x00028C78 CB_COLOR0_DIM +0x00028CB4 CB_COLOR1_DIM +0x00028CF0 CB_COLOR2_DIM +0x00028D2C CB_COLOR3_DIM +0x00028D68 CB_COLOR4_DIM +0x00028DA4 CB_COLOR5_DIM +0x00028DE0 CB_COLOR6_DIM +0x00028E1C CB_COLOR7_DIM +0x00028E58 CB_COLOR8_DIM +0x00028E74 CB_COLOR9_DIM +0x00028E90 CB_COLOR10_DIM +0x00028EAC CB_COLOR11_DIM +0x00028C8C CB_COLOR0_CLEAR_WORD0 +0x00028C90 CB_COLOR0_CLEAR_WORD1 +0x00028C94 CB_COLOR0_CLEAR_WORD2 +0x00028C98 CB_COLOR0_CLEAR_WORD3 +0x00028CC8 CB_COLOR1_CLEAR_WORD0 +0x00028CCC CB_COLOR1_CLEAR_WORD1 +0x00028CD0 CB_COLOR1_CLEAR_WORD2 +0x00028CD4 CB_COLOR1_CLEAR_WORD3 +0x00028D04 CB_COLOR2_CLEAR_WORD0 +0x00028D08 CB_COLOR2_CLEAR_WORD1 +0x00028D0C CB_COLOR2_CLEAR_WORD2 +0x00028D10 CB_COLOR2_CLEAR_WORD3 +0x00028D40 CB_COLOR3_CLEAR_WORD0 +0x00028D44 CB_COLOR3_CLEAR_WORD1 +0x00028D48 CB_COLOR3_CLEAR_WORD2 +0x00028D4C CB_COLOR3_CLEAR_WORD3 +0x00028D7C CB_COLOR4_CLEAR_WORD0 +0x00028D80 CB_COLOR4_CLEAR_WORD1 +0x00028D84 CB_COLOR4_CLEAR_WORD2 +0x00028D88 CB_COLOR4_CLEAR_WORD3 +0x00028DB8 CB_COLOR5_CLEAR_WORD0 +0x00028DBC CB_COLOR5_CLEAR_WORD1 +0x00028DC0 CB_COLOR5_CLEAR_WORD2 +0x00028DC4 CB_COLOR5_CLEAR_WORD3 +0x00028DF4 CB_COLOR6_CLEAR_WORD0 +0x00028DF8 CB_COLOR6_CLEAR_WORD1 +0x00028DFC CB_COLOR6_CLEAR_WORD2 +0x00028E00 CB_COLOR6_CLEAR_WORD3 +0x00028E30 CB_COLOR7_CLEAR_WORD0 +0x00028E34 CB_COLOR7_CLEAR_WORD1 +0x00028E38 CB_COLOR7_CLEAR_WORD2 +0x00028E3C CB_COLOR7_CLEAR_WORD3 +0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0 +0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1 +0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2 +0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3 +0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4 +0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5 +0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6 +0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7 +0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8 +0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9 +0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10 +0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11 +0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12 +0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13 +0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14 +0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15 +0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0 +0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1 +0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2 +0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3 +0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4 +0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5 +0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6 +0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7 +0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8 +0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9 +0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10 +0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11 +0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12 +0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13 +0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14 +0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15 +0x0003CFF0 SQ_VTX_BASE_VTX_LOC +0x0003CFF4 SQ_VTX_START_INST_LOC +0x0003FF00 SQ_TEX_SAMPLER_CLEAR +0x0003FF04 SQ_TEX_RESOURCE_CLEAR +0x0003FF08 SQ_LOOP_BOOL_CLEAR diff --git a/sys/dev/drm2/radeon/reg_srcs/r100 b/sys/dev/drm2/radeon/reg_srcs/r100 new file mode 100644 index 00000000000..f7ee062f118 --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/r100 @@ -0,0 +1,105 @@ +r100 0x3294 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1810 FOG_3D_TABLE_START +0x1814 FOG_3D_TABLE_END +0x1a14 FOG_TABLE_INDEX +0x1a18 FOG_TABLE_DATA +0x1c14 PP_MISC +0x1c18 PP_FOG_COLOR +0x1c1c RE_SOLID_COLOR +0x1c20 RB3D_BLENDCNTL +0x1c4c SE_CNTL +0x1c50 SE_COORD_FMT +0x1c60 PP_TXCBLEND_0 +0x1c64 PP_TXABLEND_0 +0x1c68 PP_TFACTOR_0 +0x1c78 PP_TXCBLEND_1 +0x1c7c PP_TXABLEND_1 +0x1c80 PP_TFACTOR_1 +0x1c90 PP_TXCBLEND_2 +0x1c94 PP_TXABLEND_2 +0x1c98 PP_TFACTOR_2 +0x1cc8 RE_STIPPLE_ADDR +0x1ccc RE_STIPPLE_DATA +0x1cd0 RE_LINE_PATTERN +0x1cd4 RE_LINE_STATE +0x1d40 PP_BORDER_COLOR0 +0x1d44 PP_BORDER_COLOR1 +0x1d48 PP_BORDER_COLOR2 +0x1d7c RB3D_STENCILREFMASK +0x1d80 RB3D_ROPCNTL +0x1d84 RB3D_PLANEMASK +0x1d98 VAP_VPORT_XSCALE +0x1d9C VAP_VPORT_XOFFSET +0x1da0 VAP_VPORT_YSCALE +0x1da4 VAP_VPORT_YOFFSET +0x1da8 VAP_VPORT_ZSCALE +0x1dac VAP_VPORT_ZOFFSET +0x1db0 SE_ZBIAS_FACTOR +0x1db4 SE_ZBIAS_CONSTANT +0x1db8 SE_LINE_WIDTH +0x2140 SE_CNTL_STATUS +0x2200 SE_TCL_VECTOR_INDX_REG +0x2204 SE_TCL_VECTOR_DATA_REG +0x2208 SE_TCL_SCALAR_INDX_REG +0x220c SE_TCL_SCALAR_DATA_REG +0x2210 SE_TCL_MATERIAL_EMISSIVE_RED +0x2214 SE_TCL_MATERIAL_EMISSIVE_GREEN +0x2218 SE_TCL_MATERIAL_EMISSIVE_BLUE +0x221c SE_TCL_MATERIAL_EMISSIVE_ALPHA +0x2220 SE_TCL_MATERIAL_AMBIENT_RED +0x2224 SE_TCL_MATERIAL_AMBIENT_GREEN +0x2228 SE_TCL_MATERIAL_AMBIENT_BLUE +0x222c SE_TCL_MATERIAL_AMBIENT_ALPHA +0x2230 SE_TCL_MATERIAL_DIFFUSE_RED +0x2234 SE_TCL_MATERIAL_DIFFUSE_GREEN +0x2238 SE_TCL_MATERIAL_DIFFUSE_BLUE +0x223c SE_TCL_MATERIAL_DIFFUSE_ALPHA +0x2240 SE_TCL_MATERIAL_SPECULAR_RED +0x2244 SE_TCL_MATERIAL_SPECULAR_GREEN +0x2248 SE_TCL_MATERIAL_SPECULAR_BLUE +0x224c SE_TCL_MATERIAL_SPECULAR_ALPHA +0x2250 SE_TCL_SHININESS +0x2254 SE_TCL_OUTPUT_VTX_FMT +0x2258 SE_TCL_OUTPUT_VTX_SEL +0x225c SE_TCL_MATRIX_SELECT_0 +0x2260 SE_TCL_MATRIX_SELECT_1 +0x2264 SE_TCL_UCP_VERT_BLEND_CNTL +0x2268 SE_TCL_TEXTURE_PROC_CTL +0x226c SE_TCL_LIGHT_MODEL_CTL +0x2270 SE_TCL_PER_LIGHT_CTL_0 +0x2274 SE_TCL_PER_LIGHT_CTL_1 +0x2278 SE_TCL_PER_LIGHT_CTL_2 +0x227c SE_TCL_PER_LIGHT_CTL_3 +0x2284 SE_TCL_STATE_FLUSH +0x26c0 RE_TOP_LEFT +0x26c4 RE_MISC +0x3290 RB3D_ZPASS_DATA diff --git a/sys/dev/drm2/radeon/reg_srcs/r200 b/sys/dev/drm2/radeon/reg_srcs/r200 new file mode 100644 index 00000000000..c29ac434ac9 --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/r200 @@ -0,0 +1,186 @@ +r200 0x3294 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1c14 PP_MISC +0x1c18 PP_FOG_COLOR +0x1c1c RE_SOLID_COLOR +0x1c20 RB3D_BLENDCNTL +0x1c4c SE_CNTL +0x1c50 RE_CNTL +0x1cc8 RE_STIPPLE_ADDR +0x1ccc RE_STIPPLE_DATA +0x1cd0 RE_LINE_PATTERN +0x1cd4 RE_LINE_STATE +0x1cd8 RE_SCISSOR_TL_0 +0x1cdc RE_SCISSOR_BR_0 +0x1ce0 RE_SCISSOR_TL_1 +0x1ce4 RE_SCISSOR_BR_1 +0x1ce8 RE_SCISSOR_TL_2 +0x1cec RE_SCISSOR_BR_2 +0x1d60 RB3D_DEPTHXY_OFFSET +0x1d7c RB3D_STENCILREFMASK +0x1d80 RB3D_ROPCNTL +0x1d84 RB3D_PLANEMASK +0x1d98 VAP_VPORT_XSCALE +0x1d9c VAP_VPORT_XOFFSET +0x1da0 VAP_VPORT_YSCALE +0x1da4 VAP_VPORT_YOFFSET +0x1da8 VAP_VPORT_ZSCALE +0x1dac VAP_VPORT_ZOFFSET +0x1db0 SE_ZBIAS_FACTOR +0x1db4 SE_ZBIAS_CONSTANT +0x1db8 SE_LINE_WIDTH +0x2080 SE_VAP_CNTL +0x2090 SE_TCL_OUTPUT_VTX_FMT_0 +0x2094 SE_TCL_OUTPUT_VTX_FMT_1 +0x20b0 SE_VTE_CNTL +0x2140 SE_CNTL_STATUS +0x2180 SE_VTX_STATE_CNTL +0x2200 SE_TCL_VECTOR_INDX_REG +0x2204 SE_TCL_VECTOR_DATA_REG +0x2208 SE_TCL_SCALAR_INDX_REG +0x220c SE_TCL_SCALAR_DATA_REG +0x2230 SE_TCL_MATRIX_SEL_0 +0x2234 SE_TCL_MATRIX_SEL_1 +0x2238 SE_TCL_MATRIX_SEL_2 +0x223c SE_TCL_MATRIX_SEL_3 +0x2240 SE_TCL_MATRIX_SEL_4 +0x2250 SE_TCL_OUTPUT_VTX_COMP_SEL +0x2254 SE_TCL_INPUT_VTX_VECTOR_ADDR_0 +0x2258 SE_TCL_INPUT_VTX_VECTOR_ADDR_1 +0x225c SE_TCL_INPUT_VTX_VECTOR_ADDR_2 +0x2260 SE_TCL_INPUT_VTX_VECTOR_ADDR_3 +0x2268 SE_TCL_LIGHT_MODEL_CTL_0 +0x226c SE_TCL_LIGHT_MODEL_CTL_1 +0x2270 SE_TCL_PER_LIGHT_CTL_0 +0x2274 SE_TCL_PER_LIGHT_CTL_1 +0x2278 SE_TCL_PER_LIGHT_CTL_2 +0x227c SE_TCL_PER_LIGHT_CTL_3 +0x2284 VAP_PVS_STATE_FLUSH_REG +0x22a8 SE_TCL_TEX_PROC_CTL_2 +0x22ac SE_TCL_TEX_PROC_CTL_3 +0x22b0 SE_TCL_TEX_PROC_CTL_0 +0x22b4 SE_TCL_TEX_PROC_CTL_1 +0x22b8 SE_TCL_TEX_CYL_WRAP_CTL +0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL +0x22c4 SE_TCL_POINT_SPRITE_CNTL +0x22d0 SE_PVS_CNTL +0x22d4 SE_PVS_CONST_CNTL +0x2648 RE_POINTSIZE +0x26c0 RE_TOP_LEFT +0x26c4 RE_MISC +0x26f0 RE_AUX_SCISSOR_CNTL +0x2c14 PP_BORDER_COLOR_0 +0x2c34 PP_BORDER_COLOR_1 +0x2c54 PP_BORDER_COLOR_2 +0x2c74 PP_BORDER_COLOR_3 +0x2c94 PP_BORDER_COLOR_4 +0x2cb4 PP_BORDER_COLOR_5 +0x2cc4 PP_CNTL_X +0x2cf8 PP_TRI_PERF +0x2cfc PP_PERF_CNTL +0x2d9c PP_TAM_DEBUG3 +0x2ee0 PP_TFACTOR_0 +0x2ee4 PP_TFACTOR_1 +0x2ee8 PP_TFACTOR_2 +0x2eec PP_TFACTOR_3 +0x2ef0 PP_TFACTOR_4 +0x2ef4 PP_TFACTOR_5 +0x2ef8 PP_TFACTOR_6 +0x2efc PP_TFACTOR_7 +0x2f00 PP_TXCBLEND_0 +0x2f04 PP_TXCBLEND2_0 +0x2f08 PP_TXABLEND_0 +0x2f0c PP_TXABLEND2_0 +0x2f10 PP_TXCBLEND_1 +0x2f14 PP_TXCBLEND2_1 +0x2f18 PP_TXABLEND_1 +0x2f1c PP_TXABLEND2_1 +0x2f20 PP_TXCBLEND_2 +0x2f24 PP_TXCBLEND2_2 +0x2f28 PP_TXABLEND_2 +0x2f2c PP_TXABLEND2_2 +0x2f30 PP_TXCBLEND_3 +0x2f34 PP_TXCBLEND2_3 +0x2f38 PP_TXABLEND_3 +0x2f3c PP_TXABLEND2_3 +0x2f40 PP_TXCBLEND_4 +0x2f44 PP_TXCBLEND2_4 +0x2f48 PP_TXABLEND_4 +0x2f4c PP_TXABLEND2_4 +0x2f50 PP_TXCBLEND_5 +0x2f54 PP_TXCBLEND2_5 +0x2f58 PP_TXABLEND_5 +0x2f5c PP_TXABLEND2_5 +0x2f60 PP_TXCBLEND_6 +0x2f64 PP_TXCBLEND2_6 +0x2f68 PP_TXABLEND_6 +0x2f6c PP_TXABLEND2_6 +0x2f70 PP_TXCBLEND_7 +0x2f74 PP_TXCBLEND2_7 +0x2f78 PP_TXABLEND_7 +0x2f7c PP_TXABLEND2_7 +0x2f80 PP_TXCBLEND_8 +0x2f84 PP_TXCBLEND2_8 +0x2f88 PP_TXABLEND_8 +0x2f8c PP_TXABLEND2_8 +0x2f90 PP_TXCBLEND_9 +0x2f94 PP_TXCBLEND2_9 +0x2f98 PP_TXABLEND_9 +0x2f9c PP_TXABLEND2_9 +0x2fa0 PP_TXCBLEND_10 +0x2fa4 PP_TXCBLEND2_10 +0x2fa8 PP_TXABLEND_10 +0x2fac PP_TXABLEND2_10 +0x2fb0 PP_TXCBLEND_11 +0x2fb4 PP_TXCBLEND2_11 +0x2fb8 PP_TXABLEND_11 +0x2fbc PP_TXABLEND2_11 +0x2fc0 PP_TXCBLEND_12 +0x2fc4 PP_TXCBLEND2_12 +0x2fc8 PP_TXABLEND_12 +0x2fcc PP_TXABLEND2_12 +0x2fd0 PP_TXCBLEND_13 +0x2fd4 PP_TXCBLEND2_13 +0x2fd8 PP_TXABLEND_13 +0x2fdc PP_TXABLEND2_13 +0x2fe0 PP_TXCBLEND_14 +0x2fe4 PP_TXCBLEND2_14 +0x2fe8 PP_TXABLEND_14 +0x2fec PP_TXABLEND2_14 +0x2ff0 PP_TXCBLEND_15 +0x2ff4 PP_TXCBLEND2_15 +0x2ff8 PP_TXABLEND_15 +0x2ffc PP_TXABLEND2_15 +0x3218 RB3D_BLENCOLOR +0x321c RB3D_ABLENDCNTL +0x3220 RB3D_CBLENDCNTL +0x3290 RB3D_ZPASS_DATA + diff --git a/sys/dev/drm2/radeon/reg_srcs/r300 b/sys/dev/drm2/radeon/reg_srcs/r300 new file mode 100644 index 00000000000..e8a1786b642 --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/r300 @@ -0,0 +1,714 @@ +r300 0x4f60 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1D98 VAP_VPORT_XSCALE +0x1D9C VAP_VPORT_XOFFSET +0x1DA0 VAP_VPORT_YSCALE +0x1DA4 VAP_VPORT_YOFFSET +0x1DA8 VAP_VPORT_ZSCALE +0x1DAC VAP_VPORT_ZOFFSET +0x2080 VAP_CNTL +0x2090 VAP_OUT_VTX_FMT_0 +0x2094 VAP_OUT_VTX_FMT_1 +0x20B0 VAP_VTE_CNTL +0x2138 VAP_VF_MIN_VTX_INDX +0x2140 VAP_CNTL_STATUS +0x2150 VAP_PROG_STREAM_CNTL_0 +0x2154 VAP_PROG_STREAM_CNTL_1 +0x2158 VAP_PROG_STREAM_CNTL_2 +0x215C VAP_PROG_STREAM_CNTL_3 +0x2160 VAP_PROG_STREAM_CNTL_4 +0x2164 VAP_PROG_STREAM_CNTL_5 +0x2168 VAP_PROG_STREAM_CNTL_6 +0x216C VAP_PROG_STREAM_CNTL_7 +0x2180 VAP_VTX_STATE_CNTL +0x2184 VAP_VSM_VTX_ASSM +0x2188 VAP_VTX_STATE_IND_REG_0 +0x218C VAP_VTX_STATE_IND_REG_1 +0x2190 VAP_VTX_STATE_IND_REG_2 +0x2194 VAP_VTX_STATE_IND_REG_3 +0x2198 VAP_VTX_STATE_IND_REG_4 +0x219C VAP_VTX_STATE_IND_REG_5 +0x21A0 VAP_VTX_STATE_IND_REG_6 +0x21A4 VAP_VTX_STATE_IND_REG_7 +0x21A8 VAP_VTX_STATE_IND_REG_8 +0x21AC VAP_VTX_STATE_IND_REG_9 +0x21B0 VAP_VTX_STATE_IND_REG_10 +0x21B4 VAP_VTX_STATE_IND_REG_11 +0x21B8 VAP_VTX_STATE_IND_REG_12 +0x21BC VAP_VTX_STATE_IND_REG_13 +0x21C0 VAP_VTX_STATE_IND_REG_14 +0x21C4 VAP_VTX_STATE_IND_REG_15 +0x21DC VAP_PSC_SGN_NORM_CNTL +0x21E0 VAP_PROG_STREAM_CNTL_EXT_0 +0x21E4 VAP_PROG_STREAM_CNTL_EXT_1 +0x21E8 VAP_PROG_STREAM_CNTL_EXT_2 +0x21EC VAP_PROG_STREAM_CNTL_EXT_3 +0x21F0 VAP_PROG_STREAM_CNTL_EXT_4 +0x21F4 VAP_PROG_STREAM_CNTL_EXT_5 +0x21F8 VAP_PROG_STREAM_CNTL_EXT_6 +0x21FC VAP_PROG_STREAM_CNTL_EXT_7 +0x2200 VAP_PVS_VECTOR_INDX_REG +0x2204 VAP_PVS_VECTOR_DATA_REG +0x2208 VAP_PVS_VECTOR_DATA_REG_128 +0x221C VAP_CLIP_CNTL +0x2220 VAP_GB_VERT_CLIP_ADJ +0x2224 VAP_GB_VERT_DISC_ADJ +0x2228 VAP_GB_HORZ_CLIP_ADJ +0x222C VAP_GB_HORZ_DISC_ADJ +0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0 +0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1 +0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2 +0x223C VAP_PVS_FLOW_CNTL_ADDRS_3 +0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4 +0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5 +0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6 +0x224C VAP_PVS_FLOW_CNTL_ADDRS_7 +0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8 +0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9 +0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10 +0x225C VAP_PVS_FLOW_CNTL_ADDRS_11 +0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12 +0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13 +0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14 +0x226C VAP_PVS_FLOW_CNTL_ADDRS_15 +0x2284 VAP_PVS_STATE_FLUSH_REG +0x2288 VAP_PVS_VTX_TIMEOUT_REG +0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0 +0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1 +0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2 +0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3 +0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4 +0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5 +0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6 +0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7 +0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8 +0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9 +0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10 +0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11 +0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12 +0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13 +0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14 +0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15 +0x22D0 VAP_PVS_CODE_CNTL_0 +0x22D4 VAP_PVS_CONST_CNTL +0x22D8 VAP_PVS_CODE_CNTL_1 +0x22DC VAP_PVS_FLOW_CNTL_OPC +0x342C RB2D_DSTCACHE_CTLSTAT +0x4000 GB_VAP_RASTER_VTX_FMT_0 +0x4004 GB_VAP_RASTER_VTX_FMT_1 +0x4008 GB_ENABLE +0x4010 GB_MSPOS0 +0x4014 GB_MSPOS1 +0x401C GB_SELECT +0x4020 GB_AA_CONFIG +0x4024 GB_FIFO_SIZE +0x4100 TX_INVALTAGS +0x4200 GA_POINT_S0 +0x4204 GA_POINT_T0 +0x4208 GA_POINT_S1 +0x420C GA_POINT_T1 +0x4214 GA_TRIANGLE_STIPPLE +0x421C GA_POINT_SIZE +0x4230 GA_POINT_MINMAX +0x4234 GA_LINE_CNTL +0x4238 GA_LINE_STIPPLE_CONFIG +0x4260 GA_LINE_STIPPLE_VALUE +0x4264 GA_LINE_S0 +0x4268 GA_LINE_S1 +0x4278 GA_COLOR_CONTROL +0x427C GA_SOLID_RG +0x4280 GA_SOLID_BA +0x4288 GA_POLY_MODE +0x428C GA_ROUND_MODE +0x4290 GA_OFFSET +0x4294 GA_FOG_SCALE +0x4298 GA_FOG_OFFSET +0x42A0 SU_TEX_WRAP +0x42A4 SU_POLY_OFFSET_FRONT_SCALE +0x42A8 SU_POLY_OFFSET_FRONT_OFFSET +0x42AC SU_POLY_OFFSET_BACK_SCALE +0x42B0 SU_POLY_OFFSET_BACK_OFFSET +0x42B4 SU_POLY_OFFSET_ENABLE +0x42B8 SU_CULL_MODE +0x42C0 SU_DEPTH_SCALE +0x42C4 SU_DEPTH_OFFSET +0x42C8 SU_REG_DEST +0x4300 RS_COUNT +0x4304 RS_INST_COUNT +0x4310 RS_IP_0 +0x4314 RS_IP_1 +0x4318 RS_IP_2 +0x431C RS_IP_3 +0x4320 RS_IP_4 +0x4324 RS_IP_5 +0x4328 RS_IP_6 +0x432C RS_IP_7 +0x4330 RS_INST_0 +0x4334 RS_INST_1 +0x4338 RS_INST_2 +0x433C RS_INST_3 +0x4340 RS_INST_4 +0x4344 RS_INST_5 +0x4348 RS_INST_6 +0x434C RS_INST_7 +0x4350 RS_INST_8 +0x4354 RS_INST_9 +0x4358 RS_INST_10 +0x435C RS_INST_11 +0x4360 RS_INST_12 +0x4364 RS_INST_13 +0x4368 RS_INST_14 +0x436C RS_INST_15 +0x43A8 SC_EDGERULE +0x43B0 SC_CLIP_0_A +0x43B4 SC_CLIP_0_B +0x43B8 SC_CLIP_1_A +0x43BC SC_CLIP_1_B +0x43C0 SC_CLIP_2_A +0x43C4 SC_CLIP_2_B +0x43C8 SC_CLIP_3_A +0x43CC SC_CLIP_3_B +0x43D0 SC_CLIP_RULE +0x43E0 SC_SCISSOR0 +0x43E8 SC_SCREENDOOR +0x4440 TX_FILTER1_0 +0x4444 TX_FILTER1_1 +0x4448 TX_FILTER1_2 +0x444C TX_FILTER1_3 +0x4450 TX_FILTER1_4 +0x4454 TX_FILTER1_5 +0x4458 TX_FILTER1_6 +0x445C TX_FILTER1_7 +0x4460 TX_FILTER1_8 +0x4464 TX_FILTER1_9 +0x4468 TX_FILTER1_10 +0x446C TX_FILTER1_11 +0x4470 TX_FILTER1_12 +0x4474 TX_FILTER1_13 +0x4478 TX_FILTER1_14 +0x447C TX_FILTER1_15 +0x4580 TX_CHROMA_KEY_0 +0x4584 TX_CHROMA_KEY_1 +0x4588 TX_CHROMA_KEY_2 +0x458C TX_CHROMA_KEY_3 +0x4590 TX_CHROMA_KEY_4 +0x4594 TX_CHROMA_KEY_5 +0x4598 TX_CHROMA_KEY_6 +0x459C TX_CHROMA_KEY_7 +0x45A0 TX_CHROMA_KEY_8 +0x45A4 TX_CHROMA_KEY_9 +0x45A8 TX_CHROMA_KEY_10 +0x45AC TX_CHROMA_KEY_11 +0x45B0 TX_CHROMA_KEY_12 +0x45B4 TX_CHROMA_KEY_13 +0x45B8 TX_CHROMA_KEY_14 +0x45BC TX_CHROMA_KEY_15 +0x45C0 TX_BORDER_COLOR_0 +0x45C4 TX_BORDER_COLOR_1 +0x45C8 TX_BORDER_COLOR_2 +0x45CC TX_BORDER_COLOR_3 +0x45D0 TX_BORDER_COLOR_4 +0x45D4 TX_BORDER_COLOR_5 +0x45D8 TX_BORDER_COLOR_6 +0x45DC TX_BORDER_COLOR_7 +0x45E0 TX_BORDER_COLOR_8 +0x45E4 TX_BORDER_COLOR_9 +0x45E8 TX_BORDER_COLOR_10 +0x45EC TX_BORDER_COLOR_11 +0x45F0 TX_BORDER_COLOR_12 +0x45F4 TX_BORDER_COLOR_13 +0x45F8 TX_BORDER_COLOR_14 +0x45FC TX_BORDER_COLOR_15 +0x4600 US_CONFIG +0x4604 US_PIXSIZE +0x4608 US_CODE_OFFSET +0x460C US_RESET +0x4610 US_CODE_ADDR_0 +0x4614 US_CODE_ADDR_1 +0x4618 US_CODE_ADDR_2 +0x461C US_CODE_ADDR_3 +0x4620 US_TEX_INST_0 +0x4624 US_TEX_INST_1 +0x4628 US_TEX_INST_2 +0x462C US_TEX_INST_3 +0x4630 US_TEX_INST_4 +0x4634 US_TEX_INST_5 +0x4638 US_TEX_INST_6 +0x463C US_TEX_INST_7 +0x4640 US_TEX_INST_8 +0x4644 US_TEX_INST_9 +0x4648 US_TEX_INST_10 +0x464C US_TEX_INST_11 +0x4650 US_TEX_INST_12 +0x4654 US_TEX_INST_13 +0x4658 US_TEX_INST_14 +0x465C US_TEX_INST_15 +0x4660 US_TEX_INST_16 +0x4664 US_TEX_INST_17 +0x4668 US_TEX_INST_18 +0x466C US_TEX_INST_19 +0x4670 US_TEX_INST_20 +0x4674 US_TEX_INST_21 +0x4678 US_TEX_INST_22 +0x467C US_TEX_INST_23 +0x4680 US_TEX_INST_24 +0x4684 US_TEX_INST_25 +0x4688 US_TEX_INST_26 +0x468C US_TEX_INST_27 +0x4690 US_TEX_INST_28 +0x4694 US_TEX_INST_29 +0x4698 US_TEX_INST_30 +0x469C US_TEX_INST_31 +0x46A4 US_OUT_FMT_0 +0x46A8 US_OUT_FMT_1 +0x46AC US_OUT_FMT_2 +0x46B0 US_OUT_FMT_3 +0x46B4 US_W_FMT +0x46C0 US_ALU_RGB_ADDR_0 +0x46C4 US_ALU_RGB_ADDR_1 +0x46C8 US_ALU_RGB_ADDR_2 +0x46CC US_ALU_RGB_ADDR_3 +0x46D0 US_ALU_RGB_ADDR_4 +0x46D4 US_ALU_RGB_ADDR_5 +0x46D8 US_ALU_RGB_ADDR_6 +0x46DC US_ALU_RGB_ADDR_7 +0x46E0 US_ALU_RGB_ADDR_8 +0x46E4 US_ALU_RGB_ADDR_9 +0x46E8 US_ALU_RGB_ADDR_10 +0x46EC US_ALU_RGB_ADDR_11 +0x46F0 US_ALU_RGB_ADDR_12 +0x46F4 US_ALU_RGB_ADDR_13 +0x46F8 US_ALU_RGB_ADDR_14 +0x46FC US_ALU_RGB_ADDR_15 +0x4700 US_ALU_RGB_ADDR_16 +0x4704 US_ALU_RGB_ADDR_17 +0x4708 US_ALU_RGB_ADDR_18 +0x470C US_ALU_RGB_ADDR_19 +0x4710 US_ALU_RGB_ADDR_20 +0x4714 US_ALU_RGB_ADDR_21 +0x4718 US_ALU_RGB_ADDR_22 +0x471C US_ALU_RGB_ADDR_23 +0x4720 US_ALU_RGB_ADDR_24 +0x4724 US_ALU_RGB_ADDR_25 +0x4728 US_ALU_RGB_ADDR_26 +0x472C US_ALU_RGB_ADDR_27 +0x4730 US_ALU_RGB_ADDR_28 +0x4734 US_ALU_RGB_ADDR_29 +0x4738 US_ALU_RGB_ADDR_30 +0x473C US_ALU_RGB_ADDR_31 +0x4740 US_ALU_RGB_ADDR_32 +0x4744 US_ALU_RGB_ADDR_33 +0x4748 US_ALU_RGB_ADDR_34 +0x474C US_ALU_RGB_ADDR_35 +0x4750 US_ALU_RGB_ADDR_36 +0x4754 US_ALU_RGB_ADDR_37 +0x4758 US_ALU_RGB_ADDR_38 +0x475C US_ALU_RGB_ADDR_39 +0x4760 US_ALU_RGB_ADDR_40 +0x4764 US_ALU_RGB_ADDR_41 +0x4768 US_ALU_RGB_ADDR_42 +0x476C US_ALU_RGB_ADDR_43 +0x4770 US_ALU_RGB_ADDR_44 +0x4774 US_ALU_RGB_ADDR_45 +0x4778 US_ALU_RGB_ADDR_46 +0x477C US_ALU_RGB_ADDR_47 +0x4780 US_ALU_RGB_ADDR_48 +0x4784 US_ALU_RGB_ADDR_49 +0x4788 US_ALU_RGB_ADDR_50 +0x478C US_ALU_RGB_ADDR_51 +0x4790 US_ALU_RGB_ADDR_52 +0x4794 US_ALU_RGB_ADDR_53 +0x4798 US_ALU_RGB_ADDR_54 +0x479C US_ALU_RGB_ADDR_55 +0x47A0 US_ALU_RGB_ADDR_56 +0x47A4 US_ALU_RGB_ADDR_57 +0x47A8 US_ALU_RGB_ADDR_58 +0x47AC US_ALU_RGB_ADDR_59 +0x47B0 US_ALU_RGB_ADDR_60 +0x47B4 US_ALU_RGB_ADDR_61 +0x47B8 US_ALU_RGB_ADDR_62 +0x47BC US_ALU_RGB_ADDR_63 +0x47C0 US_ALU_ALPHA_ADDR_0 +0x47C4 US_ALU_ALPHA_ADDR_1 +0x47C8 US_ALU_ALPHA_ADDR_2 +0x47CC US_ALU_ALPHA_ADDR_3 +0x47D0 US_ALU_ALPHA_ADDR_4 +0x47D4 US_ALU_ALPHA_ADDR_5 +0x47D8 US_ALU_ALPHA_ADDR_6 +0x47DC US_ALU_ALPHA_ADDR_7 +0x47E0 US_ALU_ALPHA_ADDR_8 +0x47E4 US_ALU_ALPHA_ADDR_9 +0x47E8 US_ALU_ALPHA_ADDR_10 +0x47EC US_ALU_ALPHA_ADDR_11 +0x47F0 US_ALU_ALPHA_ADDR_12 +0x47F4 US_ALU_ALPHA_ADDR_13 +0x47F8 US_ALU_ALPHA_ADDR_14 +0x47FC US_ALU_ALPHA_ADDR_15 +0x4800 US_ALU_ALPHA_ADDR_16 +0x4804 US_ALU_ALPHA_ADDR_17 +0x4808 US_ALU_ALPHA_ADDR_18 +0x480C US_ALU_ALPHA_ADDR_19 +0x4810 US_ALU_ALPHA_ADDR_20 +0x4814 US_ALU_ALPHA_ADDR_21 +0x4818 US_ALU_ALPHA_ADDR_22 +0x481C US_ALU_ALPHA_ADDR_23 +0x4820 US_ALU_ALPHA_ADDR_24 +0x4824 US_ALU_ALPHA_ADDR_25 +0x4828 US_ALU_ALPHA_ADDR_26 +0x482C US_ALU_ALPHA_ADDR_27 +0x4830 US_ALU_ALPHA_ADDR_28 +0x4834 US_ALU_ALPHA_ADDR_29 +0x4838 US_ALU_ALPHA_ADDR_30 +0x483C US_ALU_ALPHA_ADDR_31 +0x4840 US_ALU_ALPHA_ADDR_32 +0x4844 US_ALU_ALPHA_ADDR_33 +0x4848 US_ALU_ALPHA_ADDR_34 +0x484C US_ALU_ALPHA_ADDR_35 +0x4850 US_ALU_ALPHA_ADDR_36 +0x4854 US_ALU_ALPHA_ADDR_37 +0x4858 US_ALU_ALPHA_ADDR_38 +0x485C US_ALU_ALPHA_ADDR_39 +0x4860 US_ALU_ALPHA_ADDR_40 +0x4864 US_ALU_ALPHA_ADDR_41 +0x4868 US_ALU_ALPHA_ADDR_42 +0x486C US_ALU_ALPHA_ADDR_43 +0x4870 US_ALU_ALPHA_ADDR_44 +0x4874 US_ALU_ALPHA_ADDR_45 +0x4878 US_ALU_ALPHA_ADDR_46 +0x487C US_ALU_ALPHA_ADDR_47 +0x4880 US_ALU_ALPHA_ADDR_48 +0x4884 US_ALU_ALPHA_ADDR_49 +0x4888 US_ALU_ALPHA_ADDR_50 +0x488C US_ALU_ALPHA_ADDR_51 +0x4890 US_ALU_ALPHA_ADDR_52 +0x4894 US_ALU_ALPHA_ADDR_53 +0x4898 US_ALU_ALPHA_ADDR_54 +0x489C US_ALU_ALPHA_ADDR_55 +0x48A0 US_ALU_ALPHA_ADDR_56 +0x48A4 US_ALU_ALPHA_ADDR_57 +0x48A8 US_ALU_ALPHA_ADDR_58 +0x48AC US_ALU_ALPHA_ADDR_59 +0x48B0 US_ALU_ALPHA_ADDR_60 +0x48B4 US_ALU_ALPHA_ADDR_61 +0x48B8 US_ALU_ALPHA_ADDR_62 +0x48BC US_ALU_ALPHA_ADDR_63 +0x48C0 US_ALU_RGB_INST_0 +0x48C4 US_ALU_RGB_INST_1 +0x48C8 US_ALU_RGB_INST_2 +0x48CC US_ALU_RGB_INST_3 +0x48D0 US_ALU_RGB_INST_4 +0x48D4 US_ALU_RGB_INST_5 +0x48D8 US_ALU_RGB_INST_6 +0x48DC US_ALU_RGB_INST_7 +0x48E0 US_ALU_RGB_INST_8 +0x48E4 US_ALU_RGB_INST_9 +0x48E8 US_ALU_RGB_INST_10 +0x48EC US_ALU_RGB_INST_11 +0x48F0 US_ALU_RGB_INST_12 +0x48F4 US_ALU_RGB_INST_13 +0x48F8 US_ALU_RGB_INST_14 +0x48FC US_ALU_RGB_INST_15 +0x4900 US_ALU_RGB_INST_16 +0x4904 US_ALU_RGB_INST_17 +0x4908 US_ALU_RGB_INST_18 +0x490C US_ALU_RGB_INST_19 +0x4910 US_ALU_RGB_INST_20 +0x4914 US_ALU_RGB_INST_21 +0x4918 US_ALU_RGB_INST_22 +0x491C US_ALU_RGB_INST_23 +0x4920 US_ALU_RGB_INST_24 +0x4924 US_ALU_RGB_INST_25 +0x4928 US_ALU_RGB_INST_26 +0x492C US_ALU_RGB_INST_27 +0x4930 US_ALU_RGB_INST_28 +0x4934 US_ALU_RGB_INST_29 +0x4938 US_ALU_RGB_INST_30 +0x493C US_ALU_RGB_INST_31 +0x4940 US_ALU_RGB_INST_32 +0x4944 US_ALU_RGB_INST_33 +0x4948 US_ALU_RGB_INST_34 +0x494C US_ALU_RGB_INST_35 +0x4950 US_ALU_RGB_INST_36 +0x4954 US_ALU_RGB_INST_37 +0x4958 US_ALU_RGB_INST_38 +0x495C US_ALU_RGB_INST_39 +0x4960 US_ALU_RGB_INST_40 +0x4964 US_ALU_RGB_INST_41 +0x4968 US_ALU_RGB_INST_42 +0x496C US_ALU_RGB_INST_43 +0x4970 US_ALU_RGB_INST_44 +0x4974 US_ALU_RGB_INST_45 +0x4978 US_ALU_RGB_INST_46 +0x497C US_ALU_RGB_INST_47 +0x4980 US_ALU_RGB_INST_48 +0x4984 US_ALU_RGB_INST_49 +0x4988 US_ALU_RGB_INST_50 +0x498C US_ALU_RGB_INST_51 +0x4990 US_ALU_RGB_INST_52 +0x4994 US_ALU_RGB_INST_53 +0x4998 US_ALU_RGB_INST_54 +0x499C US_ALU_RGB_INST_55 +0x49A0 US_ALU_RGB_INST_56 +0x49A4 US_ALU_RGB_INST_57 +0x49A8 US_ALU_RGB_INST_58 +0x49AC US_ALU_RGB_INST_59 +0x49B0 US_ALU_RGB_INST_60 +0x49B4 US_ALU_RGB_INST_61 +0x49B8 US_ALU_RGB_INST_62 +0x49BC US_ALU_RGB_INST_63 +0x49C0 US_ALU_ALPHA_INST_0 +0x49C4 US_ALU_ALPHA_INST_1 +0x49C8 US_ALU_ALPHA_INST_2 +0x49CC US_ALU_ALPHA_INST_3 +0x49D0 US_ALU_ALPHA_INST_4 +0x49D4 US_ALU_ALPHA_INST_5 +0x49D8 US_ALU_ALPHA_INST_6 +0x49DC US_ALU_ALPHA_INST_7 +0x49E0 US_ALU_ALPHA_INST_8 +0x49E4 US_ALU_ALPHA_INST_9 +0x49E8 US_ALU_ALPHA_INST_10 +0x49EC US_ALU_ALPHA_INST_11 +0x49F0 US_ALU_ALPHA_INST_12 +0x49F4 US_ALU_ALPHA_INST_13 +0x49F8 US_ALU_ALPHA_INST_14 +0x49FC US_ALU_ALPHA_INST_15 +0x4A00 US_ALU_ALPHA_INST_16 +0x4A04 US_ALU_ALPHA_INST_17 +0x4A08 US_ALU_ALPHA_INST_18 +0x4A0C US_ALU_ALPHA_INST_19 +0x4A10 US_ALU_ALPHA_INST_20 +0x4A14 US_ALU_ALPHA_INST_21 +0x4A18 US_ALU_ALPHA_INST_22 +0x4A1C US_ALU_ALPHA_INST_23 +0x4A20 US_ALU_ALPHA_INST_24 +0x4A24 US_ALU_ALPHA_INST_25 +0x4A28 US_ALU_ALPHA_INST_26 +0x4A2C US_ALU_ALPHA_INST_27 +0x4A30 US_ALU_ALPHA_INST_28 +0x4A34 US_ALU_ALPHA_INST_29 +0x4A38 US_ALU_ALPHA_INST_30 +0x4A3C US_ALU_ALPHA_INST_31 +0x4A40 US_ALU_ALPHA_INST_32 +0x4A44 US_ALU_ALPHA_INST_33 +0x4A48 US_ALU_ALPHA_INST_34 +0x4A4C US_ALU_ALPHA_INST_35 +0x4A50 US_ALU_ALPHA_INST_36 +0x4A54 US_ALU_ALPHA_INST_37 +0x4A58 US_ALU_ALPHA_INST_38 +0x4A5C US_ALU_ALPHA_INST_39 +0x4A60 US_ALU_ALPHA_INST_40 +0x4A64 US_ALU_ALPHA_INST_41 +0x4A68 US_ALU_ALPHA_INST_42 +0x4A6C US_ALU_ALPHA_INST_43 +0x4A70 US_ALU_ALPHA_INST_44 +0x4A74 US_ALU_ALPHA_INST_45 +0x4A78 US_ALU_ALPHA_INST_46 +0x4A7C US_ALU_ALPHA_INST_47 +0x4A80 US_ALU_ALPHA_INST_48 +0x4A84 US_ALU_ALPHA_INST_49 +0x4A88 US_ALU_ALPHA_INST_50 +0x4A8C US_ALU_ALPHA_INST_51 +0x4A90 US_ALU_ALPHA_INST_52 +0x4A94 US_ALU_ALPHA_INST_53 +0x4A98 US_ALU_ALPHA_INST_54 +0x4A9C US_ALU_ALPHA_INST_55 +0x4AA0 US_ALU_ALPHA_INST_56 +0x4AA4 US_ALU_ALPHA_INST_57 +0x4AA8 US_ALU_ALPHA_INST_58 +0x4AAC US_ALU_ALPHA_INST_59 +0x4AB0 US_ALU_ALPHA_INST_60 +0x4AB4 US_ALU_ALPHA_INST_61 +0x4AB8 US_ALU_ALPHA_INST_62 +0x4ABC US_ALU_ALPHA_INST_63 +0x4BC0 FG_FOG_BLEND +0x4BC4 FG_FOG_FACTOR +0x4BC8 FG_FOG_COLOR_R +0x4BCC FG_FOG_COLOR_G +0x4BD0 FG_FOG_COLOR_B +0x4BD4 FG_ALPHA_FUNC +0x4BD8 FG_DEPTH_SRC +0x4C00 US_ALU_CONST_R_0 +0x4C04 US_ALU_CONST_G_0 +0x4C08 US_ALU_CONST_B_0 +0x4C0C US_ALU_CONST_A_0 +0x4C10 US_ALU_CONST_R_1 +0x4C14 US_ALU_CONST_G_1 +0x4C18 US_ALU_CONST_B_1 +0x4C1C US_ALU_CONST_A_1 +0x4C20 US_ALU_CONST_R_2 +0x4C24 US_ALU_CONST_G_2 +0x4C28 US_ALU_CONST_B_2 +0x4C2C US_ALU_CONST_A_2 +0x4C30 US_ALU_CONST_R_3 +0x4C34 US_ALU_CONST_G_3 +0x4C38 US_ALU_CONST_B_3 +0x4C3C US_ALU_CONST_A_3 +0x4C40 US_ALU_CONST_R_4 +0x4C44 US_ALU_CONST_G_4 +0x4C48 US_ALU_CONST_B_4 +0x4C4C US_ALU_CONST_A_4 +0x4C50 US_ALU_CONST_R_5 +0x4C54 US_ALU_CONST_G_5 +0x4C58 US_ALU_CONST_B_5 +0x4C5C US_ALU_CONST_A_5 +0x4C60 US_ALU_CONST_R_6 +0x4C64 US_ALU_CONST_G_6 +0x4C68 US_ALU_CONST_B_6 +0x4C6C US_ALU_CONST_A_6 +0x4C70 US_ALU_CONST_R_7 +0x4C74 US_ALU_CONST_G_7 +0x4C78 US_ALU_CONST_B_7 +0x4C7C US_ALU_CONST_A_7 +0x4C80 US_ALU_CONST_R_8 +0x4C84 US_ALU_CONST_G_8 +0x4C88 US_ALU_CONST_B_8 +0x4C8C US_ALU_CONST_A_8 +0x4C90 US_ALU_CONST_R_9 +0x4C94 US_ALU_CONST_G_9 +0x4C98 US_ALU_CONST_B_9 +0x4C9C US_ALU_CONST_A_9 +0x4CA0 US_ALU_CONST_R_10 +0x4CA4 US_ALU_CONST_G_10 +0x4CA8 US_ALU_CONST_B_10 +0x4CAC US_ALU_CONST_A_10 +0x4CB0 US_ALU_CONST_R_11 +0x4CB4 US_ALU_CONST_G_11 +0x4CB8 US_ALU_CONST_B_11 +0x4CBC US_ALU_CONST_A_11 +0x4CC0 US_ALU_CONST_R_12 +0x4CC4 US_ALU_CONST_G_12 +0x4CC8 US_ALU_CONST_B_12 +0x4CCC US_ALU_CONST_A_12 +0x4CD0 US_ALU_CONST_R_13 +0x4CD4 US_ALU_CONST_G_13 +0x4CD8 US_ALU_CONST_B_13 +0x4CDC US_ALU_CONST_A_13 +0x4CE0 US_ALU_CONST_R_14 +0x4CE4 US_ALU_CONST_G_14 +0x4CE8 US_ALU_CONST_B_14 +0x4CEC US_ALU_CONST_A_14 +0x4CF0 US_ALU_CONST_R_15 +0x4CF4 US_ALU_CONST_G_15 +0x4CF8 US_ALU_CONST_B_15 +0x4CFC US_ALU_CONST_A_15 +0x4D00 US_ALU_CONST_R_16 +0x4D04 US_ALU_CONST_G_16 +0x4D08 US_ALU_CONST_B_16 +0x4D0C US_ALU_CONST_A_16 +0x4D10 US_ALU_CONST_R_17 +0x4D14 US_ALU_CONST_G_17 +0x4D18 US_ALU_CONST_B_17 +0x4D1C US_ALU_CONST_A_17 +0x4D20 US_ALU_CONST_R_18 +0x4D24 US_ALU_CONST_G_18 +0x4D28 US_ALU_CONST_B_18 +0x4D2C US_ALU_CONST_A_18 +0x4D30 US_ALU_CONST_R_19 +0x4D34 US_ALU_CONST_G_19 +0x4D38 US_ALU_CONST_B_19 +0x4D3C US_ALU_CONST_A_19 +0x4D40 US_ALU_CONST_R_20 +0x4D44 US_ALU_CONST_G_20 +0x4D48 US_ALU_CONST_B_20 +0x4D4C US_ALU_CONST_A_20 +0x4D50 US_ALU_CONST_R_21 +0x4D54 US_ALU_CONST_G_21 +0x4D58 US_ALU_CONST_B_21 +0x4D5C US_ALU_CONST_A_21 +0x4D60 US_ALU_CONST_R_22 +0x4D64 US_ALU_CONST_G_22 +0x4D68 US_ALU_CONST_B_22 +0x4D6C US_ALU_CONST_A_22 +0x4D70 US_ALU_CONST_R_23 +0x4D74 US_ALU_CONST_G_23 +0x4D78 US_ALU_CONST_B_23 +0x4D7C US_ALU_CONST_A_23 +0x4D80 US_ALU_CONST_R_24 +0x4D84 US_ALU_CONST_G_24 +0x4D88 US_ALU_CONST_B_24 +0x4D8C US_ALU_CONST_A_24 +0x4D90 US_ALU_CONST_R_25 +0x4D94 US_ALU_CONST_G_25 +0x4D98 US_ALU_CONST_B_25 +0x4D9C US_ALU_CONST_A_25 +0x4DA0 US_ALU_CONST_R_26 +0x4DA4 US_ALU_CONST_G_26 +0x4DA8 US_ALU_CONST_B_26 +0x4DAC US_ALU_CONST_A_26 +0x4DB0 US_ALU_CONST_R_27 +0x4DB4 US_ALU_CONST_G_27 +0x4DB8 US_ALU_CONST_B_27 +0x4DBC US_ALU_CONST_A_27 +0x4DC0 US_ALU_CONST_R_28 +0x4DC4 US_ALU_CONST_G_28 +0x4DC8 US_ALU_CONST_B_28 +0x4DCC US_ALU_CONST_A_28 +0x4DD0 US_ALU_CONST_R_29 +0x4DD4 US_ALU_CONST_G_29 +0x4DD8 US_ALU_CONST_B_29 +0x4DDC US_ALU_CONST_A_29 +0x4DE0 US_ALU_CONST_R_30 +0x4DE4 US_ALU_CONST_G_30 +0x4DE8 US_ALU_CONST_B_30 +0x4DEC US_ALU_CONST_A_30 +0x4DF0 US_ALU_CONST_R_31 +0x4DF4 US_ALU_CONST_G_31 +0x4DF8 US_ALU_CONST_B_31 +0x4DFC US_ALU_CONST_A_31 +0x4E08 RB3D_ABLENDCNTL_R3 +0x4E10 RB3D_CONSTANT_COLOR +0x4E14 RB3D_COLOR_CLEAR_VALUE +0x4E18 RB3D_ROPCNTL_R3 +0x4E1C RB3D_CLRCMP_FLIPE_R3 +0x4E20 RB3D_CLRCMP_CLR_R3 +0x4E24 RB3D_CLRCMP_MSK_R3 +0x4E48 RB3D_DEBUG_CTL +0x4E4C RB3D_DSTCACHE_CTLSTAT_R3 +0x4E50 RB3D_DITHER_CTL +0x4E54 RB3D_CMASK_OFFSET0 +0x4E58 RB3D_CMASK_OFFSET1 +0x4E5C RB3D_CMASK_OFFSET2 +0x4E60 RB3D_CMASK_OFFSET3 +0x4E64 RB3D_CMASK_PITCH0 +0x4E68 RB3D_CMASK_PITCH1 +0x4E6C RB3D_CMASK_PITCH2 +0x4E70 RB3D_CMASK_PITCH3 +0x4E74 RB3D_CMASK_WRINDEX +0x4E78 RB3D_CMASK_DWORD +0x4E7C RB3D_CMASK_RDINDEX +0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD +0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD +0x4F04 ZB_ZSTENCILCNTL +0x4F08 ZB_STENCILREFMASK +0x4F14 ZB_ZTOP +0x4F18 ZB_ZCACHE_CTLSTAT +0x4F28 ZB_DEPTHCLEARVALUE +0x4F58 ZB_ZPASS_DATA diff --git a/sys/dev/drm2/radeon/reg_srcs/r420 b/sys/dev/drm2/radeon/reg_srcs/r420 new file mode 100644 index 00000000000..722074e21e2 --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/r420 @@ -0,0 +1,780 @@ +r420 0x4f60 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1D98 VAP_VPORT_XSCALE +0x1D9C VAP_VPORT_XOFFSET +0x1DA0 VAP_VPORT_YSCALE +0x1DA4 VAP_VPORT_YOFFSET +0x1DA8 VAP_VPORT_ZSCALE +0x1DAC VAP_VPORT_ZOFFSET +0x2080 VAP_CNTL +0x2090 VAP_OUT_VTX_FMT_0 +0x2094 VAP_OUT_VTX_FMT_1 +0x20B0 VAP_VTE_CNTL +0x2138 VAP_VF_MIN_VTX_INDX +0x2140 VAP_CNTL_STATUS +0x2150 VAP_PROG_STREAM_CNTL_0 +0x2154 VAP_PROG_STREAM_CNTL_1 +0x2158 VAP_PROG_STREAM_CNTL_2 +0x215C VAP_PROG_STREAM_CNTL_3 +0x2160 VAP_PROG_STREAM_CNTL_4 +0x2164 VAP_PROG_STREAM_CNTL_5 +0x2168 VAP_PROG_STREAM_CNTL_6 +0x216C VAP_PROG_STREAM_CNTL_7 +0x2180 VAP_VTX_STATE_CNTL +0x2184 VAP_VSM_VTX_ASSM +0x2188 VAP_VTX_STATE_IND_REG_0 +0x218C VAP_VTX_STATE_IND_REG_1 +0x2190 VAP_VTX_STATE_IND_REG_2 +0x2194 VAP_VTX_STATE_IND_REG_3 +0x2198 VAP_VTX_STATE_IND_REG_4 +0x219C VAP_VTX_STATE_IND_REG_5 +0x21A0 VAP_VTX_STATE_IND_REG_6 +0x21A4 VAP_VTX_STATE_IND_REG_7 +0x21A8 VAP_VTX_STATE_IND_REG_8 +0x21AC VAP_VTX_STATE_IND_REG_9 +0x21B0 VAP_VTX_STATE_IND_REG_10 +0x21B4 VAP_VTX_STATE_IND_REG_11 +0x21B8 VAP_VTX_STATE_IND_REG_12 +0x21BC VAP_VTX_STATE_IND_REG_13 +0x21C0 VAP_VTX_STATE_IND_REG_14 +0x21C4 VAP_VTX_STATE_IND_REG_15 +0x21DC VAP_PSC_SGN_NORM_CNTL +0x21E0 VAP_PROG_STREAM_CNTL_EXT_0 +0x21E4 VAP_PROG_STREAM_CNTL_EXT_1 +0x21E8 VAP_PROG_STREAM_CNTL_EXT_2 +0x21EC VAP_PROG_STREAM_CNTL_EXT_3 +0x21F0 VAP_PROG_STREAM_CNTL_EXT_4 +0x21F4 VAP_PROG_STREAM_CNTL_EXT_5 +0x21F8 VAP_PROG_STREAM_CNTL_EXT_6 +0x21FC VAP_PROG_STREAM_CNTL_EXT_7 +0x2200 VAP_PVS_VECTOR_INDX_REG +0x2204 VAP_PVS_VECTOR_DATA_REG +0x2208 VAP_PVS_VECTOR_DATA_REG_128 +0x221C VAP_CLIP_CNTL +0x2220 VAP_GB_VERT_CLIP_ADJ +0x2224 VAP_GB_VERT_DISC_ADJ +0x2228 VAP_GB_HORZ_CLIP_ADJ +0x222C VAP_GB_HORZ_DISC_ADJ +0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0 +0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1 +0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2 +0x223C VAP_PVS_FLOW_CNTL_ADDRS_3 +0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4 +0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5 +0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6 +0x224C VAP_PVS_FLOW_CNTL_ADDRS_7 +0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8 +0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9 +0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10 +0x225C VAP_PVS_FLOW_CNTL_ADDRS_11 +0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12 +0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13 +0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14 +0x226C VAP_PVS_FLOW_CNTL_ADDRS_15 +0x2284 VAP_PVS_STATE_FLUSH_REG +0x2288 VAP_PVS_VTX_TIMEOUT_REG +0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0 +0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1 +0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2 +0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3 +0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4 +0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5 +0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6 +0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7 +0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8 +0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9 +0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10 +0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11 +0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12 +0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13 +0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14 +0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15 +0x22D0 VAP_PVS_CODE_CNTL_0 +0x22D4 VAP_PVS_CONST_CNTL +0x22D8 VAP_PVS_CODE_CNTL_1 +0x22DC VAP_PVS_FLOW_CNTL_OPC +0x342C RB2D_DSTCACHE_CTLSTAT +0x4000 GB_VAP_RASTER_VTX_FMT_0 +0x4004 GB_VAP_RASTER_VTX_FMT_1 +0x4008 GB_ENABLE +0x4010 GB_MSPOS0 +0x4014 GB_MSPOS1 +0x401C GB_SELECT +0x4020 GB_AA_CONFIG +0x4024 GB_FIFO_SIZE +0x4100 TX_INVALTAGS +0x4200 GA_POINT_S0 +0x4204 GA_POINT_T0 +0x4208 GA_POINT_S1 +0x420C GA_POINT_T1 +0x4214 GA_TRIANGLE_STIPPLE +0x421C GA_POINT_SIZE +0x4230 GA_POINT_MINMAX +0x4234 GA_LINE_CNTL +0x4238 GA_LINE_STIPPLE_CONFIG +0x4260 GA_LINE_STIPPLE_VALUE +0x4264 GA_LINE_S0 +0x4268 GA_LINE_S1 +0x4278 GA_COLOR_CONTROL +0x427C GA_SOLID_RG +0x4280 GA_SOLID_BA +0x4288 GA_POLY_MODE +0x428C GA_ROUND_MODE +0x4290 GA_OFFSET +0x4294 GA_FOG_SCALE +0x4298 GA_FOG_OFFSET +0x42A0 SU_TEX_WRAP +0x42A4 SU_POLY_OFFSET_FRONT_SCALE +0x42A8 SU_POLY_OFFSET_FRONT_OFFSET +0x42AC SU_POLY_OFFSET_BACK_SCALE +0x42B0 SU_POLY_OFFSET_BACK_OFFSET +0x42B4 SU_POLY_OFFSET_ENABLE +0x42B8 SU_CULL_MODE +0x42C0 SU_DEPTH_SCALE +0x42C4 SU_DEPTH_OFFSET +0x42C8 SU_REG_DEST +0x4300 RS_COUNT +0x4304 RS_INST_COUNT +0x4310 RS_IP_0 +0x4314 RS_IP_1 +0x4318 RS_IP_2 +0x431C RS_IP_3 +0x4320 RS_IP_4 +0x4324 RS_IP_5 +0x4328 RS_IP_6 +0x432C RS_IP_7 +0x4330 RS_INST_0 +0x4334 RS_INST_1 +0x4338 RS_INST_2 +0x433C RS_INST_3 +0x4340 RS_INST_4 +0x4344 RS_INST_5 +0x4348 RS_INST_6 +0x434C RS_INST_7 +0x4350 RS_INST_8 +0x4354 RS_INST_9 +0x4358 RS_INST_10 +0x435C RS_INST_11 +0x4360 RS_INST_12 +0x4364 RS_INST_13 +0x4368 RS_INST_14 +0x436C RS_INST_15 +0x43A8 SC_EDGERULE +0x43B0 SC_CLIP_0_A +0x43B4 SC_CLIP_0_B +0x43B8 SC_CLIP_1_A +0x43BC SC_CLIP_1_B +0x43C0 SC_CLIP_2_A +0x43C4 SC_CLIP_2_B +0x43C8 SC_CLIP_3_A +0x43CC SC_CLIP_3_B +0x43D0 SC_CLIP_RULE +0x43E0 SC_SCISSOR0 +0x43E8 SC_SCREENDOOR +0x4440 TX_FILTER1_0 +0x4444 TX_FILTER1_1 +0x4448 TX_FILTER1_2 +0x444C TX_FILTER1_3 +0x4450 TX_FILTER1_4 +0x4454 TX_FILTER1_5 +0x4458 TX_FILTER1_6 +0x445C TX_FILTER1_7 +0x4460 TX_FILTER1_8 +0x4464 TX_FILTER1_9 +0x4468 TX_FILTER1_10 +0x446C TX_FILTER1_11 +0x4470 TX_FILTER1_12 +0x4474 TX_FILTER1_13 +0x4478 TX_FILTER1_14 +0x447C TX_FILTER1_15 +0x4580 TX_CHROMA_KEY_0 +0x4584 TX_CHROMA_KEY_1 +0x4588 TX_CHROMA_KEY_2 +0x458C TX_CHROMA_KEY_3 +0x4590 TX_CHROMA_KEY_4 +0x4594 TX_CHROMA_KEY_5 +0x4598 TX_CHROMA_KEY_6 +0x459C TX_CHROMA_KEY_7 +0x45A0 TX_CHROMA_KEY_8 +0x45A4 TX_CHROMA_KEY_9 +0x45A8 TX_CHROMA_KEY_10 +0x45AC TX_CHROMA_KEY_11 +0x45B0 TX_CHROMA_KEY_12 +0x45B4 TX_CHROMA_KEY_13 +0x45B8 TX_CHROMA_KEY_14 +0x45BC TX_CHROMA_KEY_15 +0x45C0 TX_BORDER_COLOR_0 +0x45C4 TX_BORDER_COLOR_1 +0x45C8 TX_BORDER_COLOR_2 +0x45CC TX_BORDER_COLOR_3 +0x45D0 TX_BORDER_COLOR_4 +0x45D4 TX_BORDER_COLOR_5 +0x45D8 TX_BORDER_COLOR_6 +0x45DC TX_BORDER_COLOR_7 +0x45E0 TX_BORDER_COLOR_8 +0x45E4 TX_BORDER_COLOR_9 +0x45E8 TX_BORDER_COLOR_10 +0x45EC TX_BORDER_COLOR_11 +0x45F0 TX_BORDER_COLOR_12 +0x45F4 TX_BORDER_COLOR_13 +0x45F8 TX_BORDER_COLOR_14 +0x45FC TX_BORDER_COLOR_15 +0x4600 US_CONFIG +0x4604 US_PIXSIZE +0x4608 US_CODE_OFFSET +0x460C US_RESET +0x4610 US_CODE_ADDR_0 +0x4614 US_CODE_ADDR_1 +0x4618 US_CODE_ADDR_2 +0x461C US_CODE_ADDR_3 +0x4620 US_TEX_INST_0 +0x4624 US_TEX_INST_1 +0x4628 US_TEX_INST_2 +0x462C US_TEX_INST_3 +0x4630 US_TEX_INST_4 +0x4634 US_TEX_INST_5 +0x4638 US_TEX_INST_6 +0x463C US_TEX_INST_7 +0x4640 US_TEX_INST_8 +0x4644 US_TEX_INST_9 +0x4648 US_TEX_INST_10 +0x464C US_TEX_INST_11 +0x4650 US_TEX_INST_12 +0x4654 US_TEX_INST_13 +0x4658 US_TEX_INST_14 +0x465C US_TEX_INST_15 +0x4660 US_TEX_INST_16 +0x4664 US_TEX_INST_17 +0x4668 US_TEX_INST_18 +0x466C US_TEX_INST_19 +0x4670 US_TEX_INST_20 +0x4674 US_TEX_INST_21 +0x4678 US_TEX_INST_22 +0x467C US_TEX_INST_23 +0x4680 US_TEX_INST_24 +0x4684 US_TEX_INST_25 +0x4688 US_TEX_INST_26 +0x468C US_TEX_INST_27 +0x4690 US_TEX_INST_28 +0x4694 US_TEX_INST_29 +0x4698 US_TEX_INST_30 +0x469C US_TEX_INST_31 +0x46A4 US_OUT_FMT_0 +0x46A8 US_OUT_FMT_1 +0x46AC US_OUT_FMT_2 +0x46B0 US_OUT_FMT_3 +0x46B4 US_W_FMT +0x46B8 US_CODE_BANK +0x46BC US_CODE_EXT +0x46C0 US_ALU_RGB_ADDR_0 +0x46C4 US_ALU_RGB_ADDR_1 +0x46C8 US_ALU_RGB_ADDR_2 +0x46CC US_ALU_RGB_ADDR_3 +0x46D0 US_ALU_RGB_ADDR_4 +0x46D4 US_ALU_RGB_ADDR_5 +0x46D8 US_ALU_RGB_ADDR_6 +0x46DC US_ALU_RGB_ADDR_7 +0x46E0 US_ALU_RGB_ADDR_8 +0x46E4 US_ALU_RGB_ADDR_9 +0x46E8 US_ALU_RGB_ADDR_10 +0x46EC US_ALU_RGB_ADDR_11 +0x46F0 US_ALU_RGB_ADDR_12 +0x46F4 US_ALU_RGB_ADDR_13 +0x46F8 US_ALU_RGB_ADDR_14 +0x46FC US_ALU_RGB_ADDR_15 +0x4700 US_ALU_RGB_ADDR_16 +0x4704 US_ALU_RGB_ADDR_17 +0x4708 US_ALU_RGB_ADDR_18 +0x470C US_ALU_RGB_ADDR_19 +0x4710 US_ALU_RGB_ADDR_20 +0x4714 US_ALU_RGB_ADDR_21 +0x4718 US_ALU_RGB_ADDR_22 +0x471C US_ALU_RGB_ADDR_23 +0x4720 US_ALU_RGB_ADDR_24 +0x4724 US_ALU_RGB_ADDR_25 +0x4728 US_ALU_RGB_ADDR_26 +0x472C US_ALU_RGB_ADDR_27 +0x4730 US_ALU_RGB_ADDR_28 +0x4734 US_ALU_RGB_ADDR_29 +0x4738 US_ALU_RGB_ADDR_30 +0x473C US_ALU_RGB_ADDR_31 +0x4740 US_ALU_RGB_ADDR_32 +0x4744 US_ALU_RGB_ADDR_33 +0x4748 US_ALU_RGB_ADDR_34 +0x474C US_ALU_RGB_ADDR_35 +0x4750 US_ALU_RGB_ADDR_36 +0x4754 US_ALU_RGB_ADDR_37 +0x4758 US_ALU_RGB_ADDR_38 +0x475C US_ALU_RGB_ADDR_39 +0x4760 US_ALU_RGB_ADDR_40 +0x4764 US_ALU_RGB_ADDR_41 +0x4768 US_ALU_RGB_ADDR_42 +0x476C US_ALU_RGB_ADDR_43 +0x4770 US_ALU_RGB_ADDR_44 +0x4774 US_ALU_RGB_ADDR_45 +0x4778 US_ALU_RGB_ADDR_46 +0x477C US_ALU_RGB_ADDR_47 +0x4780 US_ALU_RGB_ADDR_48 +0x4784 US_ALU_RGB_ADDR_49 +0x4788 US_ALU_RGB_ADDR_50 +0x478C US_ALU_RGB_ADDR_51 +0x4790 US_ALU_RGB_ADDR_52 +0x4794 US_ALU_RGB_ADDR_53 +0x4798 US_ALU_RGB_ADDR_54 +0x479C US_ALU_RGB_ADDR_55 +0x47A0 US_ALU_RGB_ADDR_56 +0x47A4 US_ALU_RGB_ADDR_57 +0x47A8 US_ALU_RGB_ADDR_58 +0x47AC US_ALU_RGB_ADDR_59 +0x47B0 US_ALU_RGB_ADDR_60 +0x47B4 US_ALU_RGB_ADDR_61 +0x47B8 US_ALU_RGB_ADDR_62 +0x47BC US_ALU_RGB_ADDR_63 +0x47C0 US_ALU_ALPHA_ADDR_0 +0x47C4 US_ALU_ALPHA_ADDR_1 +0x47C8 US_ALU_ALPHA_ADDR_2 +0x47CC US_ALU_ALPHA_ADDR_3 +0x47D0 US_ALU_ALPHA_ADDR_4 +0x47D4 US_ALU_ALPHA_ADDR_5 +0x47D8 US_ALU_ALPHA_ADDR_6 +0x47DC US_ALU_ALPHA_ADDR_7 +0x47E0 US_ALU_ALPHA_ADDR_8 +0x47E4 US_ALU_ALPHA_ADDR_9 +0x47E8 US_ALU_ALPHA_ADDR_10 +0x47EC US_ALU_ALPHA_ADDR_11 +0x47F0 US_ALU_ALPHA_ADDR_12 +0x47F4 US_ALU_ALPHA_ADDR_13 +0x47F8 US_ALU_ALPHA_ADDR_14 +0x47FC US_ALU_ALPHA_ADDR_15 +0x4800 US_ALU_ALPHA_ADDR_16 +0x4804 US_ALU_ALPHA_ADDR_17 +0x4808 US_ALU_ALPHA_ADDR_18 +0x480C US_ALU_ALPHA_ADDR_19 +0x4810 US_ALU_ALPHA_ADDR_20 +0x4814 US_ALU_ALPHA_ADDR_21 +0x4818 US_ALU_ALPHA_ADDR_22 +0x481C US_ALU_ALPHA_ADDR_23 +0x4820 US_ALU_ALPHA_ADDR_24 +0x4824 US_ALU_ALPHA_ADDR_25 +0x4828 US_ALU_ALPHA_ADDR_26 +0x482C US_ALU_ALPHA_ADDR_27 +0x4830 US_ALU_ALPHA_ADDR_28 +0x4834 US_ALU_ALPHA_ADDR_29 +0x4838 US_ALU_ALPHA_ADDR_30 +0x483C US_ALU_ALPHA_ADDR_31 +0x4840 US_ALU_ALPHA_ADDR_32 +0x4844 US_ALU_ALPHA_ADDR_33 +0x4848 US_ALU_ALPHA_ADDR_34 +0x484C US_ALU_ALPHA_ADDR_35 +0x4850 US_ALU_ALPHA_ADDR_36 +0x4854 US_ALU_ALPHA_ADDR_37 +0x4858 US_ALU_ALPHA_ADDR_38 +0x485C US_ALU_ALPHA_ADDR_39 +0x4860 US_ALU_ALPHA_ADDR_40 +0x4864 US_ALU_ALPHA_ADDR_41 +0x4868 US_ALU_ALPHA_ADDR_42 +0x486C US_ALU_ALPHA_ADDR_43 +0x4870 US_ALU_ALPHA_ADDR_44 +0x4874 US_ALU_ALPHA_ADDR_45 +0x4878 US_ALU_ALPHA_ADDR_46 +0x487C US_ALU_ALPHA_ADDR_47 +0x4880 US_ALU_ALPHA_ADDR_48 +0x4884 US_ALU_ALPHA_ADDR_49 +0x4888 US_ALU_ALPHA_ADDR_50 +0x488C US_ALU_ALPHA_ADDR_51 +0x4890 US_ALU_ALPHA_ADDR_52 +0x4894 US_ALU_ALPHA_ADDR_53 +0x4898 US_ALU_ALPHA_ADDR_54 +0x489C US_ALU_ALPHA_ADDR_55 +0x48A0 US_ALU_ALPHA_ADDR_56 +0x48A4 US_ALU_ALPHA_ADDR_57 +0x48A8 US_ALU_ALPHA_ADDR_58 +0x48AC US_ALU_ALPHA_ADDR_59 +0x48B0 US_ALU_ALPHA_ADDR_60 +0x48B4 US_ALU_ALPHA_ADDR_61 +0x48B8 US_ALU_ALPHA_ADDR_62 +0x48BC US_ALU_ALPHA_ADDR_63 +0x48C0 US_ALU_RGB_INST_0 +0x48C4 US_ALU_RGB_INST_1 +0x48C8 US_ALU_RGB_INST_2 +0x48CC US_ALU_RGB_INST_3 +0x48D0 US_ALU_RGB_INST_4 +0x48D4 US_ALU_RGB_INST_5 +0x48D8 US_ALU_RGB_INST_6 +0x48DC US_ALU_RGB_INST_7 +0x48E0 US_ALU_RGB_INST_8 +0x48E4 US_ALU_RGB_INST_9 +0x48E8 US_ALU_RGB_INST_10 +0x48EC US_ALU_RGB_INST_11 +0x48F0 US_ALU_RGB_INST_12 +0x48F4 US_ALU_RGB_INST_13 +0x48F8 US_ALU_RGB_INST_14 +0x48FC US_ALU_RGB_INST_15 +0x4900 US_ALU_RGB_INST_16 +0x4904 US_ALU_RGB_INST_17 +0x4908 US_ALU_RGB_INST_18 +0x490C US_ALU_RGB_INST_19 +0x4910 US_ALU_RGB_INST_20 +0x4914 US_ALU_RGB_INST_21 +0x4918 US_ALU_RGB_INST_22 +0x491C US_ALU_RGB_INST_23 +0x4920 US_ALU_RGB_INST_24 +0x4924 US_ALU_RGB_INST_25 +0x4928 US_ALU_RGB_INST_26 +0x492C US_ALU_RGB_INST_27 +0x4930 US_ALU_RGB_INST_28 +0x4934 US_ALU_RGB_INST_29 +0x4938 US_ALU_RGB_INST_30 +0x493C US_ALU_RGB_INST_31 +0x4940 US_ALU_RGB_INST_32 +0x4944 US_ALU_RGB_INST_33 +0x4948 US_ALU_RGB_INST_34 +0x494C US_ALU_RGB_INST_35 +0x4950 US_ALU_RGB_INST_36 +0x4954 US_ALU_RGB_INST_37 +0x4958 US_ALU_RGB_INST_38 +0x495C US_ALU_RGB_INST_39 +0x4960 US_ALU_RGB_INST_40 +0x4964 US_ALU_RGB_INST_41 +0x4968 US_ALU_RGB_INST_42 +0x496C US_ALU_RGB_INST_43 +0x4970 US_ALU_RGB_INST_44 +0x4974 US_ALU_RGB_INST_45 +0x4978 US_ALU_RGB_INST_46 +0x497C US_ALU_RGB_INST_47 +0x4980 US_ALU_RGB_INST_48 +0x4984 US_ALU_RGB_INST_49 +0x4988 US_ALU_RGB_INST_50 +0x498C US_ALU_RGB_INST_51 +0x4990 US_ALU_RGB_INST_52 +0x4994 US_ALU_RGB_INST_53 +0x4998 US_ALU_RGB_INST_54 +0x499C US_ALU_RGB_INST_55 +0x49A0 US_ALU_RGB_INST_56 +0x49A4 US_ALU_RGB_INST_57 +0x49A8 US_ALU_RGB_INST_58 +0x49AC US_ALU_RGB_INST_59 +0x49B0 US_ALU_RGB_INST_60 +0x49B4 US_ALU_RGB_INST_61 +0x49B8 US_ALU_RGB_INST_62 +0x49BC US_ALU_RGB_INST_63 +0x49C0 US_ALU_ALPHA_INST_0 +0x49C4 US_ALU_ALPHA_INST_1 +0x49C8 US_ALU_ALPHA_INST_2 +0x49CC US_ALU_ALPHA_INST_3 +0x49D0 US_ALU_ALPHA_INST_4 +0x49D4 US_ALU_ALPHA_INST_5 +0x49D8 US_ALU_ALPHA_INST_6 +0x49DC US_ALU_ALPHA_INST_7 +0x49E0 US_ALU_ALPHA_INST_8 +0x49E4 US_ALU_ALPHA_INST_9 +0x49E8 US_ALU_ALPHA_INST_10 +0x49EC US_ALU_ALPHA_INST_11 +0x49F0 US_ALU_ALPHA_INST_12 +0x49F4 US_ALU_ALPHA_INST_13 +0x49F8 US_ALU_ALPHA_INST_14 +0x49FC US_ALU_ALPHA_INST_15 +0x4A00 US_ALU_ALPHA_INST_16 +0x4A04 US_ALU_ALPHA_INST_17 +0x4A08 US_ALU_ALPHA_INST_18 +0x4A0C US_ALU_ALPHA_INST_19 +0x4A10 US_ALU_ALPHA_INST_20 +0x4A14 US_ALU_ALPHA_INST_21 +0x4A18 US_ALU_ALPHA_INST_22 +0x4A1C US_ALU_ALPHA_INST_23 +0x4A20 US_ALU_ALPHA_INST_24 +0x4A24 US_ALU_ALPHA_INST_25 +0x4A28 US_ALU_ALPHA_INST_26 +0x4A2C US_ALU_ALPHA_INST_27 +0x4A30 US_ALU_ALPHA_INST_28 +0x4A34 US_ALU_ALPHA_INST_29 +0x4A38 US_ALU_ALPHA_INST_30 +0x4A3C US_ALU_ALPHA_INST_31 +0x4A40 US_ALU_ALPHA_INST_32 +0x4A44 US_ALU_ALPHA_INST_33 +0x4A48 US_ALU_ALPHA_INST_34 +0x4A4C US_ALU_ALPHA_INST_35 +0x4A50 US_ALU_ALPHA_INST_36 +0x4A54 US_ALU_ALPHA_INST_37 +0x4A58 US_ALU_ALPHA_INST_38 +0x4A5C US_ALU_ALPHA_INST_39 +0x4A60 US_ALU_ALPHA_INST_40 +0x4A64 US_ALU_ALPHA_INST_41 +0x4A68 US_ALU_ALPHA_INST_42 +0x4A6C US_ALU_ALPHA_INST_43 +0x4A70 US_ALU_ALPHA_INST_44 +0x4A74 US_ALU_ALPHA_INST_45 +0x4A78 US_ALU_ALPHA_INST_46 +0x4A7C US_ALU_ALPHA_INST_47 +0x4A80 US_ALU_ALPHA_INST_48 +0x4A84 US_ALU_ALPHA_INST_49 +0x4A88 US_ALU_ALPHA_INST_50 +0x4A8C US_ALU_ALPHA_INST_51 +0x4A90 US_ALU_ALPHA_INST_52 +0x4A94 US_ALU_ALPHA_INST_53 +0x4A98 US_ALU_ALPHA_INST_54 +0x4A9C US_ALU_ALPHA_INST_55 +0x4AA0 US_ALU_ALPHA_INST_56 +0x4AA4 US_ALU_ALPHA_INST_57 +0x4AA8 US_ALU_ALPHA_INST_58 +0x4AAC US_ALU_ALPHA_INST_59 +0x4AB0 US_ALU_ALPHA_INST_60 +0x4AB4 US_ALU_ALPHA_INST_61 +0x4AB8 US_ALU_ALPHA_INST_62 +0x4ABC US_ALU_ALPHA_INST_63 +0x4AC0 US_ALU_EXT_ADDR_0 +0x4AC4 US_ALU_EXT_ADDR_1 +0x4AC8 US_ALU_EXT_ADDR_2 +0x4ACC US_ALU_EXT_ADDR_3 +0x4AD0 US_ALU_EXT_ADDR_4 +0x4AD4 US_ALU_EXT_ADDR_5 +0x4AD8 US_ALU_EXT_ADDR_6 +0x4ADC US_ALU_EXT_ADDR_7 +0x4AE0 US_ALU_EXT_ADDR_8 +0x4AE4 US_ALU_EXT_ADDR_9 +0x4AE8 US_ALU_EXT_ADDR_10 +0x4AEC US_ALU_EXT_ADDR_11 +0x4AF0 US_ALU_EXT_ADDR_12 +0x4AF4 US_ALU_EXT_ADDR_13 +0x4AF8 US_ALU_EXT_ADDR_14 +0x4AFC US_ALU_EXT_ADDR_15 +0x4B00 US_ALU_EXT_ADDR_16 +0x4B04 US_ALU_EXT_ADDR_17 +0x4B08 US_ALU_EXT_ADDR_18 +0x4B0C US_ALU_EXT_ADDR_19 +0x4B10 US_ALU_EXT_ADDR_20 +0x4B14 US_ALU_EXT_ADDR_21 +0x4B18 US_ALU_EXT_ADDR_22 +0x4B1C US_ALU_EXT_ADDR_23 +0x4B20 US_ALU_EXT_ADDR_24 +0x4B24 US_ALU_EXT_ADDR_25 +0x4B28 US_ALU_EXT_ADDR_26 +0x4B2C US_ALU_EXT_ADDR_27 +0x4B30 US_ALU_EXT_ADDR_28 +0x4B34 US_ALU_EXT_ADDR_29 +0x4B38 US_ALU_EXT_ADDR_30 +0x4B3C US_ALU_EXT_ADDR_31 +0x4B40 US_ALU_EXT_ADDR_32 +0x4B44 US_ALU_EXT_ADDR_33 +0x4B48 US_ALU_EXT_ADDR_34 +0x4B4C US_ALU_EXT_ADDR_35 +0x4B50 US_ALU_EXT_ADDR_36 +0x4B54 US_ALU_EXT_ADDR_37 +0x4B58 US_ALU_EXT_ADDR_38 +0x4B5C US_ALU_EXT_ADDR_39 +0x4B60 US_ALU_EXT_ADDR_40 +0x4B64 US_ALU_EXT_ADDR_41 +0x4B68 US_ALU_EXT_ADDR_42 +0x4B6C US_ALU_EXT_ADDR_43 +0x4B70 US_ALU_EXT_ADDR_44 +0x4B74 US_ALU_EXT_ADDR_45 +0x4B78 US_ALU_EXT_ADDR_46 +0x4B7C US_ALU_EXT_ADDR_47 +0x4B80 US_ALU_EXT_ADDR_48 +0x4B84 US_ALU_EXT_ADDR_49 +0x4B88 US_ALU_EXT_ADDR_50 +0x4B8C US_ALU_EXT_ADDR_51 +0x4B90 US_ALU_EXT_ADDR_52 +0x4B94 US_ALU_EXT_ADDR_53 +0x4B98 US_ALU_EXT_ADDR_54 +0x4B9C US_ALU_EXT_ADDR_55 +0x4BA0 US_ALU_EXT_ADDR_56 +0x4BA4 US_ALU_EXT_ADDR_57 +0x4BA8 US_ALU_EXT_ADDR_58 +0x4BAC US_ALU_EXT_ADDR_59 +0x4BB0 US_ALU_EXT_ADDR_60 +0x4BB4 US_ALU_EXT_ADDR_61 +0x4BB8 US_ALU_EXT_ADDR_62 +0x4BBC US_ALU_EXT_ADDR_63 +0x4BC0 FG_FOG_BLEND +0x4BC4 FG_FOG_FACTOR +0x4BC8 FG_FOG_COLOR_R +0x4BCC FG_FOG_COLOR_G +0x4BD0 FG_FOG_COLOR_B +0x4BD4 FG_ALPHA_FUNC +0x4BD8 FG_DEPTH_SRC +0x4C00 US_ALU_CONST_R_0 +0x4C04 US_ALU_CONST_G_0 +0x4C08 US_ALU_CONST_B_0 +0x4C0C US_ALU_CONST_A_0 +0x4C10 US_ALU_CONST_R_1 +0x4C14 US_ALU_CONST_G_1 +0x4C18 US_ALU_CONST_B_1 +0x4C1C US_ALU_CONST_A_1 +0x4C20 US_ALU_CONST_R_2 +0x4C24 US_ALU_CONST_G_2 +0x4C28 US_ALU_CONST_B_2 +0x4C2C US_ALU_CONST_A_2 +0x4C30 US_ALU_CONST_R_3 +0x4C34 US_ALU_CONST_G_3 +0x4C38 US_ALU_CONST_B_3 +0x4C3C US_ALU_CONST_A_3 +0x4C40 US_ALU_CONST_R_4 +0x4C44 US_ALU_CONST_G_4 +0x4C48 US_ALU_CONST_B_4 +0x4C4C US_ALU_CONST_A_4 +0x4C50 US_ALU_CONST_R_5 +0x4C54 US_ALU_CONST_G_5 +0x4C58 US_ALU_CONST_B_5 +0x4C5C US_ALU_CONST_A_5 +0x4C60 US_ALU_CONST_R_6 +0x4C64 US_ALU_CONST_G_6 +0x4C68 US_ALU_CONST_B_6 +0x4C6C US_ALU_CONST_A_6 +0x4C70 US_ALU_CONST_R_7 +0x4C74 US_ALU_CONST_G_7 +0x4C78 US_ALU_CONST_B_7 +0x4C7C US_ALU_CONST_A_7 +0x4C80 US_ALU_CONST_R_8 +0x4C84 US_ALU_CONST_G_8 +0x4C88 US_ALU_CONST_B_8 +0x4C8C US_ALU_CONST_A_8 +0x4C90 US_ALU_CONST_R_9 +0x4C94 US_ALU_CONST_G_9 +0x4C98 US_ALU_CONST_B_9 +0x4C9C US_ALU_CONST_A_9 +0x4CA0 US_ALU_CONST_R_10 +0x4CA4 US_ALU_CONST_G_10 +0x4CA8 US_ALU_CONST_B_10 +0x4CAC US_ALU_CONST_A_10 +0x4CB0 US_ALU_CONST_R_11 +0x4CB4 US_ALU_CONST_G_11 +0x4CB8 US_ALU_CONST_B_11 +0x4CBC US_ALU_CONST_A_11 +0x4CC0 US_ALU_CONST_R_12 +0x4CC4 US_ALU_CONST_G_12 +0x4CC8 US_ALU_CONST_B_12 +0x4CCC US_ALU_CONST_A_12 +0x4CD0 US_ALU_CONST_R_13 +0x4CD4 US_ALU_CONST_G_13 +0x4CD8 US_ALU_CONST_B_13 +0x4CDC US_ALU_CONST_A_13 +0x4CE0 US_ALU_CONST_R_14 +0x4CE4 US_ALU_CONST_G_14 +0x4CE8 US_ALU_CONST_B_14 +0x4CEC US_ALU_CONST_A_14 +0x4CF0 US_ALU_CONST_R_15 +0x4CF4 US_ALU_CONST_G_15 +0x4CF8 US_ALU_CONST_B_15 +0x4CFC US_ALU_CONST_A_15 +0x4D00 US_ALU_CONST_R_16 +0x4D04 US_ALU_CONST_G_16 +0x4D08 US_ALU_CONST_B_16 +0x4D0C US_ALU_CONST_A_16 +0x4D10 US_ALU_CONST_R_17 +0x4D14 US_ALU_CONST_G_17 +0x4D18 US_ALU_CONST_B_17 +0x4D1C US_ALU_CONST_A_17 +0x4D20 US_ALU_CONST_R_18 +0x4D24 US_ALU_CONST_G_18 +0x4D28 US_ALU_CONST_B_18 +0x4D2C US_ALU_CONST_A_18 +0x4D30 US_ALU_CONST_R_19 +0x4D34 US_ALU_CONST_G_19 +0x4D38 US_ALU_CONST_B_19 +0x4D3C US_ALU_CONST_A_19 +0x4D40 US_ALU_CONST_R_20 +0x4D44 US_ALU_CONST_G_20 +0x4D48 US_ALU_CONST_B_20 +0x4D4C US_ALU_CONST_A_20 +0x4D50 US_ALU_CONST_R_21 +0x4D54 US_ALU_CONST_G_21 +0x4D58 US_ALU_CONST_B_21 +0x4D5C US_ALU_CONST_A_21 +0x4D60 US_ALU_CONST_R_22 +0x4D64 US_ALU_CONST_G_22 +0x4D68 US_ALU_CONST_B_22 +0x4D6C US_ALU_CONST_A_22 +0x4D70 US_ALU_CONST_R_23 +0x4D74 US_ALU_CONST_G_23 +0x4D78 US_ALU_CONST_B_23 +0x4D7C US_ALU_CONST_A_23 +0x4D80 US_ALU_CONST_R_24 +0x4D84 US_ALU_CONST_G_24 +0x4D88 US_ALU_CONST_B_24 +0x4D8C US_ALU_CONST_A_24 +0x4D90 US_ALU_CONST_R_25 +0x4D94 US_ALU_CONST_G_25 +0x4D98 US_ALU_CONST_B_25 +0x4D9C US_ALU_CONST_A_25 +0x4DA0 US_ALU_CONST_R_26 +0x4DA4 US_ALU_CONST_G_26 +0x4DA8 US_ALU_CONST_B_26 +0x4DAC US_ALU_CONST_A_26 +0x4DB0 US_ALU_CONST_R_27 +0x4DB4 US_ALU_CONST_G_27 +0x4DB8 US_ALU_CONST_B_27 +0x4DBC US_ALU_CONST_A_27 +0x4DC0 US_ALU_CONST_R_28 +0x4DC4 US_ALU_CONST_G_28 +0x4DC8 US_ALU_CONST_B_28 +0x4DCC US_ALU_CONST_A_28 +0x4DD0 US_ALU_CONST_R_29 +0x4DD4 US_ALU_CONST_G_29 +0x4DD8 US_ALU_CONST_B_29 +0x4DDC US_ALU_CONST_A_29 +0x4DE0 US_ALU_CONST_R_30 +0x4DE4 US_ALU_CONST_G_30 +0x4DE8 US_ALU_CONST_B_30 +0x4DEC US_ALU_CONST_A_30 +0x4DF0 US_ALU_CONST_R_31 +0x4DF4 US_ALU_CONST_G_31 +0x4DF8 US_ALU_CONST_B_31 +0x4DFC US_ALU_CONST_A_31 +0x4E08 RB3D_ABLENDCNTL_R3 +0x4E10 RB3D_CONSTANT_COLOR +0x4E14 RB3D_COLOR_CLEAR_VALUE +0x4E18 RB3D_ROPCNTL_R3 +0x4E1C RB3D_CLRCMP_FLIPE_R3 +0x4E20 RB3D_CLRCMP_CLR_R3 +0x4E24 RB3D_CLRCMP_MSK_R3 +0x4E48 RB3D_DEBUG_CTL +0x4E4C RB3D_DSTCACHE_CTLSTAT_R3 +0x4E50 RB3D_DITHER_CTL +0x4E54 RB3D_CMASK_OFFSET0 +0x4E58 RB3D_CMASK_OFFSET1 +0x4E5C RB3D_CMASK_OFFSET2 +0x4E60 RB3D_CMASK_OFFSET3 +0x4E64 RB3D_CMASK_PITCH0 +0x4E68 RB3D_CMASK_PITCH1 +0x4E6C RB3D_CMASK_PITCH2 +0x4E70 RB3D_CMASK_PITCH3 +0x4E74 RB3D_CMASK_WRINDEX +0x4E78 RB3D_CMASK_DWORD +0x4E7C RB3D_CMASK_RDINDEX +0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD +0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD +0x4F04 ZB_ZSTENCILCNTL +0x4F08 ZB_STENCILREFMASK +0x4F14 ZB_ZTOP +0x4F18 ZB_ZCACHE_CTLSTAT +0x4F28 ZB_DEPTHCLEARVALUE +0x4F58 ZB_ZPASS_DATA diff --git a/sys/dev/drm2/radeon/reg_srcs/r600 b/sys/dev/drm2/radeon/reg_srcs/r600 new file mode 100644 index 00000000000..20bfbda7b3f --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/r600 @@ -0,0 +1,755 @@ +r600 0x9400 +0x000287A0 R7xx_CB_SHADER_CONTROL +0x00028230 R7xx_PA_SC_EDGERULE +0x000286C8 R7xx_SPI_THREAD_GROUPING +0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE +0x000088C4 VGT_CACHE_INVALIDATION +0x00028A50 VGT_ENHANCE +0x000088CC VGT_ES_PER_GS +0x00028A2C VGT_GROUP_DECR +0x00028A28 VGT_GROUP_FIRST_DECR +0x00028A24 VGT_GROUP_PRIM_TYPE +0x00028A30 VGT_GROUP_VECT_0_CNTL +0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL +0x00028A34 VGT_GROUP_VECT_1_CNTL +0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL +0x00028A40 VGT_GS_MODE +0x00028A6C VGT_GS_OUT_PRIM_TYPE +0x000088C8 VGT_GS_PER_ES +0x000088E8 VGT_GS_PER_VS +0x000088D4 VGT_GS_VERTEX_REUSE +0x00028A14 VGT_HOS_CNTL +0x00028A18 VGT_HOS_MAX_TESS_LEVEL +0x00028A1C VGT_HOS_MIN_TESS_LEVEL +0x00028A20 VGT_HOS_REUSE_DEPTH +0x0000895C VGT_INDEX_TYPE +0x00028408 VGT_INDX_OFFSET +0x00028AA0 VGT_INSTANCE_STEP_RATE_0 +0x00028AA4 VGT_INSTANCE_STEP_RATE_1 +0x00028400 VGT_MAX_VTX_INDX +0x00028404 VGT_MIN_VTX_INDX +0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN +0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX +0x00008970 VGT_NUM_INDICES +0x00008974 VGT_NUM_INSTANCES +0x00028A10 VGT_OUTPUT_PATH_CNTL +0x00028A84 VGT_PRIMITIVEID_EN +0x00008958 VGT_PRIMITIVE_TYPE +0x00028AB4 VGT_REUSE_OFF +0x00028AB8 VGT_VTX_CNT_EN +0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE +0x00028810 PA_CL_CLIP_CNTL +0x00008A14 PA_CL_ENHANCE +0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ +0x00028C18 PA_CL_GB_HORZ_DISC_ADJ +0x00028C0C PA_CL_GB_VERT_CLIP_ADJ +0x00028C10 PA_CL_GB_VERT_DISC_ADJ +0x00028820 PA_CL_NANINF_CNTL +0x00028E1C PA_CL_POINT_CULL_RAD +0x00028E18 PA_CL_POINT_SIZE +0x00028E10 PA_CL_POINT_X_RAD +0x00028E14 PA_CL_POINT_Y_RAD +0x00028E2C PA_CL_UCP_0_W +0x00028E3C PA_CL_UCP_1_W +0x00028E4C PA_CL_UCP_2_W +0x00028E5C PA_CL_UCP_3_W +0x00028E6C PA_CL_UCP_4_W +0x00028E7C PA_CL_UCP_5_W +0x00028E20 PA_CL_UCP_0_X +0x00028E30 PA_CL_UCP_1_X +0x00028E40 PA_CL_UCP_2_X +0x00028E50 PA_CL_UCP_3_X +0x00028E60 PA_CL_UCP_4_X +0x00028E70 PA_CL_UCP_5_X +0x00028E24 PA_CL_UCP_0_Y +0x00028E34 PA_CL_UCP_1_Y +0x00028E44 PA_CL_UCP_2_Y +0x00028E54 PA_CL_UCP_3_Y +0x00028E64 PA_CL_UCP_4_Y +0x00028E74 PA_CL_UCP_5_Y +0x00028E28 PA_CL_UCP_0_Z +0x00028E38 PA_CL_UCP_1_Z +0x00028E48 PA_CL_UCP_2_Z +0x00028E58 PA_CL_UCP_3_Z +0x00028E68 PA_CL_UCP_4_Z +0x00028E78 PA_CL_UCP_5_Z +0x00028440 PA_CL_VPORT_XOFFSET_0 +0x00028458 PA_CL_VPORT_XOFFSET_1 +0x00028470 PA_CL_VPORT_XOFFSET_2 +0x00028488 PA_CL_VPORT_XOFFSET_3 +0x000284A0 PA_CL_VPORT_XOFFSET_4 +0x000284B8 PA_CL_VPORT_XOFFSET_5 +0x000284D0 PA_CL_VPORT_XOFFSET_6 +0x000284E8 PA_CL_VPORT_XOFFSET_7 +0x00028500 PA_CL_VPORT_XOFFSET_8 +0x00028518 PA_CL_VPORT_XOFFSET_9 +0x00028530 PA_CL_VPORT_XOFFSET_10 +0x00028548 PA_CL_VPORT_XOFFSET_11 +0x00028560 PA_CL_VPORT_XOFFSET_12 +0x00028578 PA_CL_VPORT_XOFFSET_13 +0x00028590 PA_CL_VPORT_XOFFSET_14 +0x000285A8 PA_CL_VPORT_XOFFSET_15 +0x0002843C PA_CL_VPORT_XSCALE_0 +0x00028454 PA_CL_VPORT_XSCALE_1 +0x0002846C PA_CL_VPORT_XSCALE_2 +0x00028484 PA_CL_VPORT_XSCALE_3 +0x0002849C PA_CL_VPORT_XSCALE_4 +0x000284B4 PA_CL_VPORT_XSCALE_5 +0x000284CC PA_CL_VPORT_XSCALE_6 +0x000284E4 PA_CL_VPORT_XSCALE_7 +0x000284FC PA_CL_VPORT_XSCALE_8 +0x00028514 PA_CL_VPORT_XSCALE_9 +0x0002852C PA_CL_VPORT_XSCALE_10 +0x00028544 PA_CL_VPORT_XSCALE_11 +0x0002855C PA_CL_VPORT_XSCALE_12 +0x00028574 PA_CL_VPORT_XSCALE_13 +0x0002858C PA_CL_VPORT_XSCALE_14 +0x000285A4 PA_CL_VPORT_XSCALE_15 +0x00028448 PA_CL_VPORT_YOFFSET_0 +0x00028460 PA_CL_VPORT_YOFFSET_1 +0x00028478 PA_CL_VPORT_YOFFSET_2 +0x00028490 PA_CL_VPORT_YOFFSET_3 +0x000284A8 PA_CL_VPORT_YOFFSET_4 +0x000284C0 PA_CL_VPORT_YOFFSET_5 +0x000284D8 PA_CL_VPORT_YOFFSET_6 +0x000284F0 PA_CL_VPORT_YOFFSET_7 +0x00028508 PA_CL_VPORT_YOFFSET_8 +0x00028520 PA_CL_VPORT_YOFFSET_9 +0x00028538 PA_CL_VPORT_YOFFSET_10 +0x00028550 PA_CL_VPORT_YOFFSET_11 +0x00028568 PA_CL_VPORT_YOFFSET_12 +0x00028580 PA_CL_VPORT_YOFFSET_13 +0x00028598 PA_CL_VPORT_YOFFSET_14 +0x000285B0 PA_CL_VPORT_YOFFSET_15 +0x00028444 PA_CL_VPORT_YSCALE_0 +0x0002845C PA_CL_VPORT_YSCALE_1 +0x00028474 PA_CL_VPORT_YSCALE_2 +0x0002848C PA_CL_VPORT_YSCALE_3 +0x000284A4 PA_CL_VPORT_YSCALE_4 +0x000284BC PA_CL_VPORT_YSCALE_5 +0x000284D4 PA_CL_VPORT_YSCALE_6 +0x000284EC PA_CL_VPORT_YSCALE_7 +0x00028504 PA_CL_VPORT_YSCALE_8 +0x0002851C PA_CL_VPORT_YSCALE_9 +0x00028534 PA_CL_VPORT_YSCALE_10 +0x0002854C PA_CL_VPORT_YSCALE_11 +0x00028564 PA_CL_VPORT_YSCALE_12 +0x0002857C PA_CL_VPORT_YSCALE_13 +0x00028594 PA_CL_VPORT_YSCALE_14 +0x000285AC PA_CL_VPORT_YSCALE_15 +0x00028450 PA_CL_VPORT_ZOFFSET_0 +0x00028468 PA_CL_VPORT_ZOFFSET_1 +0x00028480 PA_CL_VPORT_ZOFFSET_2 +0x00028498 PA_CL_VPORT_ZOFFSET_3 +0x000284B0 PA_CL_VPORT_ZOFFSET_4 +0x000284C8 PA_CL_VPORT_ZOFFSET_5 +0x000284E0 PA_CL_VPORT_ZOFFSET_6 +0x000284F8 PA_CL_VPORT_ZOFFSET_7 +0x00028510 PA_CL_VPORT_ZOFFSET_8 +0x00028528 PA_CL_VPORT_ZOFFSET_9 +0x00028540 PA_CL_VPORT_ZOFFSET_10 +0x00028558 PA_CL_VPORT_ZOFFSET_11 +0x00028570 PA_CL_VPORT_ZOFFSET_12 +0x00028588 PA_CL_VPORT_ZOFFSET_13 +0x000285A0 PA_CL_VPORT_ZOFFSET_14 +0x000285B8 PA_CL_VPORT_ZOFFSET_15 +0x0002844C PA_CL_VPORT_ZSCALE_0 +0x00028464 PA_CL_VPORT_ZSCALE_1 +0x0002847C PA_CL_VPORT_ZSCALE_2 +0x00028494 PA_CL_VPORT_ZSCALE_3 +0x000284AC PA_CL_VPORT_ZSCALE_4 +0x000284C4 PA_CL_VPORT_ZSCALE_5 +0x000284DC PA_CL_VPORT_ZSCALE_6 +0x000284F4 PA_CL_VPORT_ZSCALE_7 +0x0002850C PA_CL_VPORT_ZSCALE_8 +0x00028524 PA_CL_VPORT_ZSCALE_9 +0x0002853C PA_CL_VPORT_ZSCALE_10 +0x00028554 PA_CL_VPORT_ZSCALE_11 +0x0002856C PA_CL_VPORT_ZSCALE_12 +0x00028584 PA_CL_VPORT_ZSCALE_13 +0x0002859C PA_CL_VPORT_ZSCALE_14 +0x000285B4 PA_CL_VPORT_ZSCALE_15 +0x0002881C PA_CL_VS_OUT_CNTL +0x00028818 PA_CL_VTE_CNTL +0x00028C48 PA_SC_AA_MASK +0x00008B40 PA_SC_AA_SAMPLE_LOCS_2S +0x00008B44 PA_SC_AA_SAMPLE_LOCS_4S +0x00008B48 PA_SC_AA_SAMPLE_LOCS_8S_WD0 +0x00008B4C PA_SC_AA_SAMPLE_LOCS_8S_WD1 +0x00028C20 PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX +0x00028C1C PA_SC_AA_SAMPLE_LOCS_MCTX +0x00028214 PA_SC_CLIPRECT_0_BR +0x0002821C PA_SC_CLIPRECT_1_BR +0x00028224 PA_SC_CLIPRECT_2_BR +0x0002822C PA_SC_CLIPRECT_3_BR +0x00028210 PA_SC_CLIPRECT_0_TL +0x00028218 PA_SC_CLIPRECT_1_TL +0x00028220 PA_SC_CLIPRECT_2_TL +0x00028228 PA_SC_CLIPRECT_3_TL +0x0002820C PA_SC_CLIPRECT_RULE +0x00008BF0 PA_SC_ENHANCE +0x00028244 PA_SC_GENERIC_SCISSOR_BR +0x00028240 PA_SC_GENERIC_SCISSOR_TL +0x00028C00 PA_SC_LINE_CNTL +0x00028A0C PA_SC_LINE_STIPPLE +0x00008B10 PA_SC_LINE_STIPPLE_STATE +0x00028A4C PA_SC_MODE_CNTL +0x00028A48 PA_SC_MPASS_PS_CNTL +0x00008B20 PA_SC_MULTI_CHIP_CNTL +0x00028034 PA_SC_SCREEN_SCISSOR_BR +0x00028030 PA_SC_SCREEN_SCISSOR_TL +0x00028254 PA_SC_VPORT_SCISSOR_0_BR +0x0002825C PA_SC_VPORT_SCISSOR_1_BR +0x00028264 PA_SC_VPORT_SCISSOR_2_BR +0x0002826C PA_SC_VPORT_SCISSOR_3_BR +0x00028274 PA_SC_VPORT_SCISSOR_4_BR +0x0002827C PA_SC_VPORT_SCISSOR_5_BR +0x00028284 PA_SC_VPORT_SCISSOR_6_BR +0x0002828C PA_SC_VPORT_SCISSOR_7_BR +0x00028294 PA_SC_VPORT_SCISSOR_8_BR +0x0002829C PA_SC_VPORT_SCISSOR_9_BR +0x000282A4 PA_SC_VPORT_SCISSOR_10_BR +0x000282AC PA_SC_VPORT_SCISSOR_11_BR +0x000282B4 PA_SC_VPORT_SCISSOR_12_BR +0x000282BC PA_SC_VPORT_SCISSOR_13_BR +0x000282C4 PA_SC_VPORT_SCISSOR_14_BR +0x000282CC PA_SC_VPORT_SCISSOR_15_BR +0x00028250 PA_SC_VPORT_SCISSOR_0_TL +0x00028258 PA_SC_VPORT_SCISSOR_1_TL +0x00028260 PA_SC_VPORT_SCISSOR_2_TL +0x00028268 PA_SC_VPORT_SCISSOR_3_TL +0x00028270 PA_SC_VPORT_SCISSOR_4_TL +0x00028278 PA_SC_VPORT_SCISSOR_5_TL +0x00028280 PA_SC_VPORT_SCISSOR_6_TL +0x00028288 PA_SC_VPORT_SCISSOR_7_TL +0x00028290 PA_SC_VPORT_SCISSOR_8_TL +0x00028298 PA_SC_VPORT_SCISSOR_9_TL +0x000282A0 PA_SC_VPORT_SCISSOR_10_TL +0x000282A8 PA_SC_VPORT_SCISSOR_11_TL +0x000282B0 PA_SC_VPORT_SCISSOR_12_TL +0x000282B8 PA_SC_VPORT_SCISSOR_13_TL +0x000282C0 PA_SC_VPORT_SCISSOR_14_TL +0x000282C8 PA_SC_VPORT_SCISSOR_15_TL +0x000282D4 PA_SC_VPORT_ZMAX_0 +0x000282DC PA_SC_VPORT_ZMAX_1 +0x000282E4 PA_SC_VPORT_ZMAX_2 +0x000282EC PA_SC_VPORT_ZMAX_3 +0x000282F4 PA_SC_VPORT_ZMAX_4 +0x000282FC PA_SC_VPORT_ZMAX_5 +0x00028304 PA_SC_VPORT_ZMAX_6 +0x0002830C PA_SC_VPORT_ZMAX_7 +0x00028314 PA_SC_VPORT_ZMAX_8 +0x0002831C PA_SC_VPORT_ZMAX_9 +0x00028324 PA_SC_VPORT_ZMAX_10 +0x0002832C PA_SC_VPORT_ZMAX_11 +0x00028334 PA_SC_VPORT_ZMAX_12 +0x0002833C PA_SC_VPORT_ZMAX_13 +0x00028344 PA_SC_VPORT_ZMAX_14 +0x0002834C PA_SC_VPORT_ZMAX_15 +0x000282D0 PA_SC_VPORT_ZMIN_0 +0x000282D8 PA_SC_VPORT_ZMIN_1 +0x000282E0 PA_SC_VPORT_ZMIN_2 +0x000282E8 PA_SC_VPORT_ZMIN_3 +0x000282F0 PA_SC_VPORT_ZMIN_4 +0x000282F8 PA_SC_VPORT_ZMIN_5 +0x00028300 PA_SC_VPORT_ZMIN_6 +0x00028308 PA_SC_VPORT_ZMIN_7 +0x00028310 PA_SC_VPORT_ZMIN_8 +0x00028318 PA_SC_VPORT_ZMIN_9 +0x00028320 PA_SC_VPORT_ZMIN_10 +0x00028328 PA_SC_VPORT_ZMIN_11 +0x00028330 PA_SC_VPORT_ZMIN_12 +0x00028338 PA_SC_VPORT_ZMIN_13 +0x00028340 PA_SC_VPORT_ZMIN_14 +0x00028348 PA_SC_VPORT_ZMIN_15 +0x00028200 PA_SC_WINDOW_OFFSET +0x00028208 PA_SC_WINDOW_SCISSOR_BR +0x00028204 PA_SC_WINDOW_SCISSOR_TL +0x00028A08 PA_SU_LINE_CNTL +0x00028A04 PA_SU_POINT_MINMAX +0x00028A00 PA_SU_POINT_SIZE +0x00028E0C PA_SU_POLY_OFFSET_BACK_OFFSET +0x00028E08 PA_SU_POLY_OFFSET_BACK_SCALE +0x00028DFC PA_SU_POLY_OFFSET_CLAMP +0x00028DF8 PA_SU_POLY_OFFSET_DB_FMT_CNTL +0x00028E04 PA_SU_POLY_OFFSET_FRONT_OFFSET +0x00028E00 PA_SU_POLY_OFFSET_FRONT_SCALE +0x00028814 PA_SU_SC_MODE_CNTL +0x00028C08 PA_SU_VTX_CNTL +0x00008C04 SQ_GPR_RESOURCE_MGMT_1 +0x00008C08 SQ_GPR_RESOURCE_MGMT_2 +0x00008C10 SQ_STACK_RESOURCE_MGMT_1 +0x00008C14 SQ_STACK_RESOURCE_MGMT_2 +0x00008C0C SQ_THREAD_RESOURCE_MGMT +0x00028380 SQ_VTX_SEMANTIC_0 +0x00028384 SQ_VTX_SEMANTIC_1 +0x00028388 SQ_VTX_SEMANTIC_2 +0x0002838C SQ_VTX_SEMANTIC_3 +0x00028390 SQ_VTX_SEMANTIC_4 +0x00028394 SQ_VTX_SEMANTIC_5 +0x00028398 SQ_VTX_SEMANTIC_6 +0x0002839C SQ_VTX_SEMANTIC_7 +0x000283A0 SQ_VTX_SEMANTIC_8 +0x000283A4 SQ_VTX_SEMANTIC_9 +0x000283A8 SQ_VTX_SEMANTIC_10 +0x000283AC SQ_VTX_SEMANTIC_11 +0x000283B0 SQ_VTX_SEMANTIC_12 +0x000283B4 SQ_VTX_SEMANTIC_13 +0x000283B8 SQ_VTX_SEMANTIC_14 +0x000283BC SQ_VTX_SEMANTIC_15 +0x000283C0 SQ_VTX_SEMANTIC_16 +0x000283C4 SQ_VTX_SEMANTIC_17 +0x000283C8 SQ_VTX_SEMANTIC_18 +0x000283CC SQ_VTX_SEMANTIC_19 +0x000283D0 SQ_VTX_SEMANTIC_20 +0x000283D4 SQ_VTX_SEMANTIC_21 +0x000283D8 SQ_VTX_SEMANTIC_22 +0x000283DC SQ_VTX_SEMANTIC_23 +0x000283E0 SQ_VTX_SEMANTIC_24 +0x000283E4 SQ_VTX_SEMANTIC_25 +0x000283E8 SQ_VTX_SEMANTIC_26 +0x000283EC SQ_VTX_SEMANTIC_27 +0x000283F0 SQ_VTX_SEMANTIC_28 +0x000283F4 SQ_VTX_SEMANTIC_29 +0x000283F8 SQ_VTX_SEMANTIC_30 +0x000283FC SQ_VTX_SEMANTIC_31 +0x000288E0 SQ_VTX_SEMANTIC_CLEAR +0x0003CFF4 SQ_VTX_START_INST_LOC +0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0 +0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1 +0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2 +0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3 +0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4 +0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5 +0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6 +0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7 +0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8 +0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9 +0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10 +0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11 +0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12 +0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13 +0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14 +0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15 +0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 +0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 +0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 +0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3 +0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4 +0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5 +0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6 +0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7 +0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8 +0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9 +0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10 +0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11 +0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12 +0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13 +0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14 +0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15 +0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0 +0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1 +0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2 +0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3 +0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4 +0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5 +0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6 +0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7 +0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8 +0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9 +0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10 +0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11 +0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12 +0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13 +0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14 +0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15 +0x000288D8 SQ_PGM_CF_OFFSET_ES +0x000288DC SQ_PGM_CF_OFFSET_FS +0x000288D4 SQ_PGM_CF_OFFSET_GS +0x000288CC SQ_PGM_CF_OFFSET_PS +0x000288D0 SQ_PGM_CF_OFFSET_VS +0x00028854 SQ_PGM_EXPORTS_PS +0x00028890 SQ_PGM_RESOURCES_ES +0x000288A4 SQ_PGM_RESOURCES_FS +0x0002887C SQ_PGM_RESOURCES_GS +0x00028850 SQ_PGM_RESOURCES_PS +0x00028868 SQ_PGM_RESOURCES_VS +0x00009100 SPI_CONFIG_CNTL +0x0000913C SPI_CONFIG_CNTL_1 +0x000286DC SPI_FOG_CNTL +0x000286E4 SPI_FOG_FUNC_BIAS +0x000286E0 SPI_FOG_FUNC_SCALE +0x000286D8 SPI_INPUT_Z +0x000286D4 SPI_INTERP_CONTROL_0 +0x00028644 SPI_PS_INPUT_CNTL_0 +0x00028648 SPI_PS_INPUT_CNTL_1 +0x0002864C SPI_PS_INPUT_CNTL_2 +0x00028650 SPI_PS_INPUT_CNTL_3 +0x00028654 SPI_PS_INPUT_CNTL_4 +0x00028658 SPI_PS_INPUT_CNTL_5 +0x0002865C SPI_PS_INPUT_CNTL_6 +0x00028660 SPI_PS_INPUT_CNTL_7 +0x00028664 SPI_PS_INPUT_CNTL_8 +0x00028668 SPI_PS_INPUT_CNTL_9 +0x0002866C SPI_PS_INPUT_CNTL_10 +0x00028670 SPI_PS_INPUT_CNTL_11 +0x00028674 SPI_PS_INPUT_CNTL_12 +0x00028678 SPI_PS_INPUT_CNTL_13 +0x0002867C SPI_PS_INPUT_CNTL_14 +0x00028680 SPI_PS_INPUT_CNTL_15 +0x00028684 SPI_PS_INPUT_CNTL_16 +0x00028688 SPI_PS_INPUT_CNTL_17 +0x0002868C SPI_PS_INPUT_CNTL_18 +0x00028690 SPI_PS_INPUT_CNTL_19 +0x00028694 SPI_PS_INPUT_CNTL_20 +0x00028698 SPI_PS_INPUT_CNTL_21 +0x0002869C SPI_PS_INPUT_CNTL_22 +0x000286A0 SPI_PS_INPUT_CNTL_23 +0x000286A4 SPI_PS_INPUT_CNTL_24 +0x000286A8 SPI_PS_INPUT_CNTL_25 +0x000286AC SPI_PS_INPUT_CNTL_26 +0x000286B0 SPI_PS_INPUT_CNTL_27 +0x000286B4 SPI_PS_INPUT_CNTL_28 +0x000286B8 SPI_PS_INPUT_CNTL_29 +0x000286BC SPI_PS_INPUT_CNTL_30 +0x000286C0 SPI_PS_INPUT_CNTL_31 +0x000286CC SPI_PS_IN_CONTROL_0 +0x000286D0 SPI_PS_IN_CONTROL_1 +0x000286C4 SPI_VS_OUT_CONFIG +0x00028614 SPI_VS_OUT_ID_0 +0x00028618 SPI_VS_OUT_ID_1 +0x0002861C SPI_VS_OUT_ID_2 +0x00028620 SPI_VS_OUT_ID_3 +0x00028624 SPI_VS_OUT_ID_4 +0x00028628 SPI_VS_OUT_ID_5 +0x0002862C SPI_VS_OUT_ID_6 +0x00028630 SPI_VS_OUT_ID_7 +0x00028634 SPI_VS_OUT_ID_8 +0x00028638 SPI_VS_OUT_ID_9 +0x00028438 SX_ALPHA_REF +0x00028410 SX_ALPHA_TEST_CONTROL +0x00028354 SX_SURFACE_SYNC +0x00009014 SX_MEMORY_EXPORT_SIZE +0x00009604 TC_INVALIDATE +0x00009400 TD_FILTER4 +0x00009404 TD_FILTER4_1 +0x00009408 TD_FILTER4_2 +0x0000940C TD_FILTER4_3 +0x00009410 TD_FILTER4_4 +0x00009414 TD_FILTER4_5 +0x00009418 TD_FILTER4_6 +0x0000941C TD_FILTER4_7 +0x00009420 TD_FILTER4_8 +0x00009424 TD_FILTER4_9 +0x00009428 TD_FILTER4_10 +0x0000942C TD_FILTER4_11 +0x00009430 TD_FILTER4_12 +0x00009434 TD_FILTER4_13 +0x00009438 TD_FILTER4_14 +0x0000943C TD_FILTER4_15 +0x00009440 TD_FILTER4_16 +0x00009444 TD_FILTER4_17 +0x00009448 TD_FILTER4_18 +0x0000944C TD_FILTER4_19 +0x00009450 TD_FILTER4_20 +0x00009454 TD_FILTER4_21 +0x00009458 TD_FILTER4_22 +0x0000945C TD_FILTER4_23 +0x00009460 TD_FILTER4_24 +0x00009464 TD_FILTER4_25 +0x00009468 TD_FILTER4_26 +0x0000946C TD_FILTER4_27 +0x00009470 TD_FILTER4_28 +0x00009474 TD_FILTER4_29 +0x00009478 TD_FILTER4_30 +0x0000947C TD_FILTER4_31 +0x00009480 TD_FILTER4_32 +0x00009484 TD_FILTER4_33 +0x00009488 TD_FILTER4_34 +0x0000948C TD_FILTER4_35 +0x0000A80C TD_GS_SAMPLER0_BORDER_ALPHA +0x0000A81C TD_GS_SAMPLER1_BORDER_ALPHA +0x0000A82C TD_GS_SAMPLER2_BORDER_ALPHA +0x0000A83C TD_GS_SAMPLER3_BORDER_ALPHA +0x0000A84C TD_GS_SAMPLER4_BORDER_ALPHA +0x0000A85C TD_GS_SAMPLER5_BORDER_ALPHA +0x0000A86C TD_GS_SAMPLER6_BORDER_ALPHA +0x0000A87C TD_GS_SAMPLER7_BORDER_ALPHA +0x0000A88C TD_GS_SAMPLER8_BORDER_ALPHA +0x0000A89C TD_GS_SAMPLER9_BORDER_ALPHA +0x0000A8AC TD_GS_SAMPLER10_BORDER_ALPHA +0x0000A8BC TD_GS_SAMPLER11_BORDER_ALPHA +0x0000A8CC TD_GS_SAMPLER12_BORDER_ALPHA +0x0000A8DC TD_GS_SAMPLER13_BORDER_ALPHA +0x0000A8EC TD_GS_SAMPLER14_BORDER_ALPHA +0x0000A8FC TD_GS_SAMPLER15_BORDER_ALPHA +0x0000A90C TD_GS_SAMPLER16_BORDER_ALPHA +0x0000A91C TD_GS_SAMPLER17_BORDER_ALPHA +0x0000A808 TD_GS_SAMPLER0_BORDER_BLUE +0x0000A818 TD_GS_SAMPLER1_BORDER_BLUE +0x0000A828 TD_GS_SAMPLER2_BORDER_BLUE +0x0000A838 TD_GS_SAMPLER3_BORDER_BLUE +0x0000A848 TD_GS_SAMPLER4_BORDER_BLUE +0x0000A858 TD_GS_SAMPLER5_BORDER_BLUE +0x0000A868 TD_GS_SAMPLER6_BORDER_BLUE +0x0000A878 TD_GS_SAMPLER7_BORDER_BLUE +0x0000A888 TD_GS_SAMPLER8_BORDER_BLUE +0x0000A898 TD_GS_SAMPLER9_BORDER_BLUE +0x0000A8A8 TD_GS_SAMPLER10_BORDER_BLUE +0x0000A8B8 TD_GS_SAMPLER11_BORDER_BLUE +0x0000A8C8 TD_GS_SAMPLER12_BORDER_BLUE +0x0000A8D8 TD_GS_SAMPLER13_BORDER_BLUE +0x0000A8E8 TD_GS_SAMPLER14_BORDER_BLUE +0x0000A8F8 TD_GS_SAMPLER15_BORDER_BLUE +0x0000A908 TD_GS_SAMPLER16_BORDER_BLUE +0x0000A918 TD_GS_SAMPLER17_BORDER_BLUE +0x0000A804 TD_GS_SAMPLER0_BORDER_GREEN +0x0000A814 TD_GS_SAMPLER1_BORDER_GREEN +0x0000A824 TD_GS_SAMPLER2_BORDER_GREEN +0x0000A834 TD_GS_SAMPLER3_BORDER_GREEN +0x0000A844 TD_GS_SAMPLER4_BORDER_GREEN +0x0000A854 TD_GS_SAMPLER5_BORDER_GREEN +0x0000A864 TD_GS_SAMPLER6_BORDER_GREEN +0x0000A874 TD_GS_SAMPLER7_BORDER_GREEN +0x0000A884 TD_GS_SAMPLER8_BORDER_GREEN +0x0000A894 TD_GS_SAMPLER9_BORDER_GREEN +0x0000A8A4 TD_GS_SAMPLER10_BORDER_GREEN +0x0000A8B4 TD_GS_SAMPLER11_BORDER_GREEN +0x0000A8C4 TD_GS_SAMPLER12_BORDER_GREEN +0x0000A8D4 TD_GS_SAMPLER13_BORDER_GREEN +0x0000A8E4 TD_GS_SAMPLER14_BORDER_GREEN +0x0000A8F4 TD_GS_SAMPLER15_BORDER_GREEN +0x0000A904 TD_GS_SAMPLER16_BORDER_GREEN +0x0000A914 TD_GS_SAMPLER17_BORDER_GREEN +0x0000A800 TD_GS_SAMPLER0_BORDER_RED +0x0000A810 TD_GS_SAMPLER1_BORDER_RED +0x0000A820 TD_GS_SAMPLER2_BORDER_RED +0x0000A830 TD_GS_SAMPLER3_BORDER_RED +0x0000A840 TD_GS_SAMPLER4_BORDER_RED +0x0000A850 TD_GS_SAMPLER5_BORDER_RED +0x0000A860 TD_GS_SAMPLER6_BORDER_RED +0x0000A870 TD_GS_SAMPLER7_BORDER_RED +0x0000A880 TD_GS_SAMPLER8_BORDER_RED +0x0000A890 TD_GS_SAMPLER9_BORDER_RED +0x0000A8A0 TD_GS_SAMPLER10_BORDER_RED +0x0000A8B0 TD_GS_SAMPLER11_BORDER_RED +0x0000A8C0 TD_GS_SAMPLER12_BORDER_RED +0x0000A8D0 TD_GS_SAMPLER13_BORDER_RED +0x0000A8E0 TD_GS_SAMPLER14_BORDER_RED +0x0000A8F0 TD_GS_SAMPLER15_BORDER_RED +0x0000A900 TD_GS_SAMPLER16_BORDER_RED +0x0000A910 TD_GS_SAMPLER17_BORDER_RED +0x0000A40C TD_PS_SAMPLER0_BORDER_ALPHA +0x0000A41C TD_PS_SAMPLER1_BORDER_ALPHA +0x0000A42C TD_PS_SAMPLER2_BORDER_ALPHA +0x0000A43C TD_PS_SAMPLER3_BORDER_ALPHA +0x0000A44C TD_PS_SAMPLER4_BORDER_ALPHA +0x0000A45C TD_PS_SAMPLER5_BORDER_ALPHA +0x0000A46C TD_PS_SAMPLER6_BORDER_ALPHA +0x0000A47C TD_PS_SAMPLER7_BORDER_ALPHA +0x0000A48C TD_PS_SAMPLER8_BORDER_ALPHA +0x0000A49C TD_PS_SAMPLER9_BORDER_ALPHA +0x0000A4AC TD_PS_SAMPLER10_BORDER_ALPHA +0x0000A4BC TD_PS_SAMPLER11_BORDER_ALPHA +0x0000A4CC TD_PS_SAMPLER12_BORDER_ALPHA +0x0000A4DC TD_PS_SAMPLER13_BORDER_ALPHA +0x0000A4EC TD_PS_SAMPLER14_BORDER_ALPHA +0x0000A4FC TD_PS_SAMPLER15_BORDER_ALPHA +0x0000A50C TD_PS_SAMPLER16_BORDER_ALPHA +0x0000A51C TD_PS_SAMPLER17_BORDER_ALPHA +0x0000A408 TD_PS_SAMPLER0_BORDER_BLUE +0x0000A418 TD_PS_SAMPLER1_BORDER_BLUE +0x0000A428 TD_PS_SAMPLER2_BORDER_BLUE +0x0000A438 TD_PS_SAMPLER3_BORDER_BLUE +0x0000A448 TD_PS_SAMPLER4_BORDER_BLUE +0x0000A458 TD_PS_SAMPLER5_BORDER_BLUE +0x0000A468 TD_PS_SAMPLER6_BORDER_BLUE +0x0000A478 TD_PS_SAMPLER7_BORDER_BLUE +0x0000A488 TD_PS_SAMPLER8_BORDER_BLUE +0x0000A498 TD_PS_SAMPLER9_BORDER_BLUE +0x0000A4A8 TD_PS_SAMPLER10_BORDER_BLUE +0x0000A4B8 TD_PS_SAMPLER11_BORDER_BLUE +0x0000A4C8 TD_PS_SAMPLER12_BORDER_BLUE +0x0000A4D8 TD_PS_SAMPLER13_BORDER_BLUE +0x0000A4E8 TD_PS_SAMPLER14_BORDER_BLUE +0x0000A4F8 TD_PS_SAMPLER15_BORDER_BLUE +0x0000A508 TD_PS_SAMPLER16_BORDER_BLUE +0x0000A518 TD_PS_SAMPLER17_BORDER_BLUE +0x0000A404 TD_PS_SAMPLER0_BORDER_GREEN +0x0000A414 TD_PS_SAMPLER1_BORDER_GREEN +0x0000A424 TD_PS_SAMPLER2_BORDER_GREEN +0x0000A434 TD_PS_SAMPLER3_BORDER_GREEN +0x0000A444 TD_PS_SAMPLER4_BORDER_GREEN +0x0000A454 TD_PS_SAMPLER5_BORDER_GREEN +0x0000A464 TD_PS_SAMPLER6_BORDER_GREEN +0x0000A474 TD_PS_SAMPLER7_BORDER_GREEN +0x0000A484 TD_PS_SAMPLER8_BORDER_GREEN +0x0000A494 TD_PS_SAMPLER9_BORDER_GREEN +0x0000A4A4 TD_PS_SAMPLER10_BORDER_GREEN +0x0000A4B4 TD_PS_SAMPLER11_BORDER_GREEN +0x0000A4C4 TD_PS_SAMPLER12_BORDER_GREEN +0x0000A4D4 TD_PS_SAMPLER13_BORDER_GREEN +0x0000A4E4 TD_PS_SAMPLER14_BORDER_GREEN +0x0000A4F4 TD_PS_SAMPLER15_BORDER_GREEN +0x0000A504 TD_PS_SAMPLER16_BORDER_GREEN +0x0000A514 TD_PS_SAMPLER17_BORDER_GREEN +0x0000A400 TD_PS_SAMPLER0_BORDER_RED +0x0000A410 TD_PS_SAMPLER1_BORDER_RED +0x0000A420 TD_PS_SAMPLER2_BORDER_RED +0x0000A430 TD_PS_SAMPLER3_BORDER_RED +0x0000A440 TD_PS_SAMPLER4_BORDER_RED +0x0000A450 TD_PS_SAMPLER5_BORDER_RED +0x0000A460 TD_PS_SAMPLER6_BORDER_RED +0x0000A470 TD_PS_SAMPLER7_BORDER_RED +0x0000A480 TD_PS_SAMPLER8_BORDER_RED +0x0000A490 TD_PS_SAMPLER9_BORDER_RED +0x0000A4A0 TD_PS_SAMPLER10_BORDER_RED +0x0000A4B0 TD_PS_SAMPLER11_BORDER_RED +0x0000A4C0 TD_PS_SAMPLER12_BORDER_RED +0x0000A4D0 TD_PS_SAMPLER13_BORDER_RED +0x0000A4E0 TD_PS_SAMPLER14_BORDER_RED +0x0000A4F0 TD_PS_SAMPLER15_BORDER_RED +0x0000A500 TD_PS_SAMPLER16_BORDER_RED +0x0000A510 TD_PS_SAMPLER17_BORDER_RED +0x0000AA00 TD_PS_SAMPLER0_CLEARTYPE_KERNEL +0x0000AA04 TD_PS_SAMPLER1_CLEARTYPE_KERNEL +0x0000AA08 TD_PS_SAMPLER2_CLEARTYPE_KERNEL +0x0000AA0C TD_PS_SAMPLER3_CLEARTYPE_KERNEL +0x0000AA10 TD_PS_SAMPLER4_CLEARTYPE_KERNEL +0x0000AA14 TD_PS_SAMPLER5_CLEARTYPE_KERNEL +0x0000AA18 TD_PS_SAMPLER6_CLEARTYPE_KERNEL +0x0000AA1C TD_PS_SAMPLER7_CLEARTYPE_KERNEL +0x0000AA20 TD_PS_SAMPLER8_CLEARTYPE_KERNEL +0x0000AA24 TD_PS_SAMPLER9_CLEARTYPE_KERNEL +0x0000AA28 TD_PS_SAMPLER10_CLEARTYPE_KERNEL +0x0000AA2C TD_PS_SAMPLER11_CLEARTYPE_KERNEL +0x0000AA30 TD_PS_SAMPLER12_CLEARTYPE_KERNEL +0x0000AA34 TD_PS_SAMPLER13_CLEARTYPE_KERNEL +0x0000AA38 TD_PS_SAMPLER14_CLEARTYPE_KERNEL +0x0000AA3C TD_PS_SAMPLER15_CLEARTYPE_KERNEL +0x0000AA40 TD_PS_SAMPLER16_CLEARTYPE_KERNEL +0x0000AA44 TD_PS_SAMPLER17_CLEARTYPE_KERNEL +0x0000A60C TD_VS_SAMPLER0_BORDER_ALPHA +0x0000A61C TD_VS_SAMPLER1_BORDER_ALPHA +0x0000A62C TD_VS_SAMPLER2_BORDER_ALPHA +0x0000A63C TD_VS_SAMPLER3_BORDER_ALPHA +0x0000A64C TD_VS_SAMPLER4_BORDER_ALPHA +0x0000A65C TD_VS_SAMPLER5_BORDER_ALPHA +0x0000A66C TD_VS_SAMPLER6_BORDER_ALPHA +0x0000A67C TD_VS_SAMPLER7_BORDER_ALPHA +0x0000A68C TD_VS_SAMPLER8_BORDER_ALPHA +0x0000A69C TD_VS_SAMPLER9_BORDER_ALPHA +0x0000A6AC TD_VS_SAMPLER10_BORDER_ALPHA +0x0000A6BC TD_VS_SAMPLER11_BORDER_ALPHA +0x0000A6CC TD_VS_SAMPLER12_BORDER_ALPHA +0x0000A6DC TD_VS_SAMPLER13_BORDER_ALPHA +0x0000A6EC TD_VS_SAMPLER14_BORDER_ALPHA +0x0000A6FC TD_VS_SAMPLER15_BORDER_ALPHA +0x0000A70C TD_VS_SAMPLER16_BORDER_ALPHA +0x0000A71C TD_VS_SAMPLER17_BORDER_ALPHA +0x0000A608 TD_VS_SAMPLER0_BORDER_BLUE +0x0000A618 TD_VS_SAMPLER1_BORDER_BLUE +0x0000A628 TD_VS_SAMPLER2_BORDER_BLUE +0x0000A638 TD_VS_SAMPLER3_BORDER_BLUE +0x0000A648 TD_VS_SAMPLER4_BORDER_BLUE +0x0000A658 TD_VS_SAMPLER5_BORDER_BLUE +0x0000A668 TD_VS_SAMPLER6_BORDER_BLUE +0x0000A678 TD_VS_SAMPLER7_BORDER_BLUE +0x0000A688 TD_VS_SAMPLER8_BORDER_BLUE +0x0000A698 TD_VS_SAMPLER9_BORDER_BLUE +0x0000A6A8 TD_VS_SAMPLER10_BORDER_BLUE +0x0000A6B8 TD_VS_SAMPLER11_BORDER_BLUE +0x0000A6C8 TD_VS_SAMPLER12_BORDER_BLUE +0x0000A6D8 TD_VS_SAMPLER13_BORDER_BLUE +0x0000A6E8 TD_VS_SAMPLER14_BORDER_BLUE +0x0000A6F8 TD_VS_SAMPLER15_BORDER_BLUE +0x0000A708 TD_VS_SAMPLER16_BORDER_BLUE +0x0000A718 TD_VS_SAMPLER17_BORDER_BLUE +0x0000A604 TD_VS_SAMPLER0_BORDER_GREEN +0x0000A614 TD_VS_SAMPLER1_BORDER_GREEN +0x0000A624 TD_VS_SAMPLER2_BORDER_GREEN +0x0000A634 TD_VS_SAMPLER3_BORDER_GREEN +0x0000A644 TD_VS_SAMPLER4_BORDER_GREEN +0x0000A654 TD_VS_SAMPLER5_BORDER_GREEN +0x0000A664 TD_VS_SAMPLER6_BORDER_GREEN +0x0000A674 TD_VS_SAMPLER7_BORDER_GREEN +0x0000A684 TD_VS_SAMPLER8_BORDER_GREEN +0x0000A694 TD_VS_SAMPLER9_BORDER_GREEN +0x0000A6A4 TD_VS_SAMPLER10_BORDER_GREEN +0x0000A6B4 TD_VS_SAMPLER11_BORDER_GREEN +0x0000A6C4 TD_VS_SAMPLER12_BORDER_GREEN +0x0000A6D4 TD_VS_SAMPLER13_BORDER_GREEN +0x0000A6E4 TD_VS_SAMPLER14_BORDER_GREEN +0x0000A6F4 TD_VS_SAMPLER15_BORDER_GREEN +0x0000A704 TD_VS_SAMPLER16_BORDER_GREEN +0x0000A714 TD_VS_SAMPLER17_BORDER_GREEN +0x0000A600 TD_VS_SAMPLER0_BORDER_RED +0x0000A610 TD_VS_SAMPLER1_BORDER_RED +0x0000A620 TD_VS_SAMPLER2_BORDER_RED +0x0000A630 TD_VS_SAMPLER3_BORDER_RED +0x0000A640 TD_VS_SAMPLER4_BORDER_RED +0x0000A650 TD_VS_SAMPLER5_BORDER_RED +0x0000A660 TD_VS_SAMPLER6_BORDER_RED +0x0000A670 TD_VS_SAMPLER7_BORDER_RED +0x0000A680 TD_VS_SAMPLER8_BORDER_RED +0x0000A690 TD_VS_SAMPLER9_BORDER_RED +0x0000A6A0 TD_VS_SAMPLER10_BORDER_RED +0x0000A6B0 TD_VS_SAMPLER11_BORDER_RED +0x0000A6C0 TD_VS_SAMPLER12_BORDER_RED +0x0000A6D0 TD_VS_SAMPLER13_BORDER_RED +0x0000A6E0 TD_VS_SAMPLER14_BORDER_RED +0x0000A6F0 TD_VS_SAMPLER15_BORDER_RED +0x0000A700 TD_VS_SAMPLER16_BORDER_RED +0x0000A710 TD_VS_SAMPLER17_BORDER_RED +0x00009508 TA_CNTL_AUX +0x0002802C DB_DEPTH_CLEAR +0x00028D34 DB_PREFETCH_LIMIT +0x00028D30 DB_PRELOAD_CONTROL +0x00028D0C DB_RENDER_CONTROL +0x00028D10 DB_RENDER_OVERRIDE +0x0002880C DB_SHADER_CONTROL +0x00028D28 DB_SRESULTS_COMPARE_STATE0 +0x00028D2C DB_SRESULTS_COMPARE_STATE1 +0x00028430 DB_STENCILREFMASK +0x00028434 DB_STENCILREFMASK_BF +0x00028028 DB_STENCIL_CLEAR +0x00028780 CB_BLEND0_CONTROL +0x00028784 CB_BLEND1_CONTROL +0x00028788 CB_BLEND2_CONTROL +0x0002878C CB_BLEND3_CONTROL +0x00028790 CB_BLEND4_CONTROL +0x00028794 CB_BLEND5_CONTROL +0x00028798 CB_BLEND6_CONTROL +0x0002879C CB_BLEND7_CONTROL +0x00028804 CB_BLEND_CONTROL +0x00028420 CB_BLEND_ALPHA +0x0002841C CB_BLEND_BLUE +0x00028418 CB_BLEND_GREEN +0x00028414 CB_BLEND_RED +0x0002812C CB_CLEAR_ALPHA +0x00028128 CB_CLEAR_BLUE +0x00028124 CB_CLEAR_GREEN +0x00028120 CB_CLEAR_RED +0x00028C30 CB_CLRCMP_CONTROL +0x00028C38 CB_CLRCMP_DST +0x00028C3C CB_CLRCMP_MSK +0x00028C34 CB_CLRCMP_SRC +0x0002842C CB_FOG_BLUE +0x00028428 CB_FOG_GREEN +0x00028424 CB_FOG_RED +0x00008040 WAIT_UNTIL +0x00009714 VC_ENHANCE +0x00009830 DB_DEBUG +0x00009838 DB_WATERMARKS +0x00028D44 DB_ALPHA_TO_MASK +0x00009700 VC_CNTL diff --git a/sys/dev/drm2/radeon/reg_srcs/rn50 b/sys/dev/drm2/radeon/reg_srcs/rn50 new file mode 100644 index 00000000000..2687b630726 --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/rn50 @@ -0,0 +1,30 @@ +rn50 0x3294 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL diff --git a/sys/dev/drm2/radeon/reg_srcs/rs600 b/sys/dev/drm2/radeon/reg_srcs/rs600 new file mode 100644 index 00000000000..d9f62866bbc --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/rs600 @@ -0,0 +1,780 @@ +rs600 0x6d40 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1D98 VAP_VPORT_XSCALE +0x1D9C VAP_VPORT_XOFFSET +0x1DA0 VAP_VPORT_YSCALE +0x1DA4 VAP_VPORT_YOFFSET +0x1DA8 VAP_VPORT_ZSCALE +0x1DAC VAP_VPORT_ZOFFSET +0x2080 VAP_CNTL +0x2090 VAP_OUT_VTX_FMT_0 +0x2094 VAP_OUT_VTX_FMT_1 +0x20B0 VAP_VTE_CNTL +0x2138 VAP_VF_MIN_VTX_INDX +0x2140 VAP_CNTL_STATUS +0x2150 VAP_PROG_STREAM_CNTL_0 +0x2154 VAP_PROG_STREAM_CNTL_1 +0x2158 VAP_PROG_STREAM_CNTL_2 +0x215C VAP_PROG_STREAM_CNTL_3 +0x2160 VAP_PROG_STREAM_CNTL_4 +0x2164 VAP_PROG_STREAM_CNTL_5 +0x2168 VAP_PROG_STREAM_CNTL_6 +0x216C VAP_PROG_STREAM_CNTL_7 +0x2180 VAP_VTX_STATE_CNTL +0x2184 VAP_VSM_VTX_ASSM +0x2188 VAP_VTX_STATE_IND_REG_0 +0x218C VAP_VTX_STATE_IND_REG_1 +0x2190 VAP_VTX_STATE_IND_REG_2 +0x2194 VAP_VTX_STATE_IND_REG_3 +0x2198 VAP_VTX_STATE_IND_REG_4 +0x219C VAP_VTX_STATE_IND_REG_5 +0x21A0 VAP_VTX_STATE_IND_REG_6 +0x21A4 VAP_VTX_STATE_IND_REG_7 +0x21A8 VAP_VTX_STATE_IND_REG_8 +0x21AC VAP_VTX_STATE_IND_REG_9 +0x21B0 VAP_VTX_STATE_IND_REG_10 +0x21B4 VAP_VTX_STATE_IND_REG_11 +0x21B8 VAP_VTX_STATE_IND_REG_12 +0x21BC VAP_VTX_STATE_IND_REG_13 +0x21C0 VAP_VTX_STATE_IND_REG_14 +0x21C4 VAP_VTX_STATE_IND_REG_15 +0x21DC VAP_PSC_SGN_NORM_CNTL +0x21E0 VAP_PROG_STREAM_CNTL_EXT_0 +0x21E4 VAP_PROG_STREAM_CNTL_EXT_1 +0x21E8 VAP_PROG_STREAM_CNTL_EXT_2 +0x21EC VAP_PROG_STREAM_CNTL_EXT_3 +0x21F0 VAP_PROG_STREAM_CNTL_EXT_4 +0x21F4 VAP_PROG_STREAM_CNTL_EXT_5 +0x21F8 VAP_PROG_STREAM_CNTL_EXT_6 +0x21FC VAP_PROG_STREAM_CNTL_EXT_7 +0x2200 VAP_PVS_VECTOR_INDX_REG +0x2204 VAP_PVS_VECTOR_DATA_REG +0x2208 VAP_PVS_VECTOR_DATA_REG_128 +0x221C VAP_CLIP_CNTL +0x2220 VAP_GB_VERT_CLIP_ADJ +0x2224 VAP_GB_VERT_DISC_ADJ +0x2228 VAP_GB_HORZ_CLIP_ADJ +0x222C VAP_GB_HORZ_DISC_ADJ +0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0 +0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1 +0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2 +0x223C VAP_PVS_FLOW_CNTL_ADDRS_3 +0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4 +0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5 +0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6 +0x224C VAP_PVS_FLOW_CNTL_ADDRS_7 +0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8 +0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9 +0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10 +0x225C VAP_PVS_FLOW_CNTL_ADDRS_11 +0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12 +0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13 +0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14 +0x226C VAP_PVS_FLOW_CNTL_ADDRS_15 +0x2284 VAP_PVS_STATE_FLUSH_REG +0x2288 VAP_PVS_VTX_TIMEOUT_REG +0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0 +0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1 +0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2 +0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3 +0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4 +0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5 +0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6 +0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7 +0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8 +0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9 +0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10 +0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11 +0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12 +0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13 +0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14 +0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15 +0x22D0 VAP_PVS_CODE_CNTL_0 +0x22D4 VAP_PVS_CONST_CNTL +0x22D8 VAP_PVS_CODE_CNTL_1 +0x22DC VAP_PVS_FLOW_CNTL_OPC +0x342C RB2D_DSTCACHE_CTLSTAT +0x4000 GB_VAP_RASTER_VTX_FMT_0 +0x4004 GB_VAP_RASTER_VTX_FMT_1 +0x4008 GB_ENABLE +0x4010 GB_MSPOS0 +0x4014 GB_MSPOS1 +0x401C GB_SELECT +0x4020 GB_AA_CONFIG +0x4024 GB_FIFO_SIZE +0x4100 TX_INVALTAGS +0x4200 GA_POINT_S0 +0x4204 GA_POINT_T0 +0x4208 GA_POINT_S1 +0x420C GA_POINT_T1 +0x4214 GA_TRIANGLE_STIPPLE +0x421C GA_POINT_SIZE +0x4230 GA_POINT_MINMAX +0x4234 GA_LINE_CNTL +0x4238 GA_LINE_STIPPLE_CONFIG +0x4260 GA_LINE_STIPPLE_VALUE +0x4264 GA_LINE_S0 +0x4268 GA_LINE_S1 +0x4278 GA_COLOR_CONTROL +0x427C GA_SOLID_RG +0x4280 GA_SOLID_BA +0x4288 GA_POLY_MODE +0x428C GA_ROUND_MODE +0x4290 GA_OFFSET +0x4294 GA_FOG_SCALE +0x4298 GA_FOG_OFFSET +0x42A0 SU_TEX_WRAP +0x42A4 SU_POLY_OFFSET_FRONT_SCALE +0x42A8 SU_POLY_OFFSET_FRONT_OFFSET +0x42AC SU_POLY_OFFSET_BACK_SCALE +0x42B0 SU_POLY_OFFSET_BACK_OFFSET +0x42B4 SU_POLY_OFFSET_ENABLE +0x42B8 SU_CULL_MODE +0x42C0 SU_DEPTH_SCALE +0x42C4 SU_DEPTH_OFFSET +0x42C8 SU_REG_DEST +0x4300 RS_COUNT +0x4304 RS_INST_COUNT +0x4310 RS_IP_0 +0x4314 RS_IP_1 +0x4318 RS_IP_2 +0x431C RS_IP_3 +0x4320 RS_IP_4 +0x4324 RS_IP_5 +0x4328 RS_IP_6 +0x432C RS_IP_7 +0x4330 RS_INST_0 +0x4334 RS_INST_1 +0x4338 RS_INST_2 +0x433C RS_INST_3 +0x4340 RS_INST_4 +0x4344 RS_INST_5 +0x4348 RS_INST_6 +0x434C RS_INST_7 +0x4350 RS_INST_8 +0x4354 RS_INST_9 +0x4358 RS_INST_10 +0x435C RS_INST_11 +0x4360 RS_INST_12 +0x4364 RS_INST_13 +0x4368 RS_INST_14 +0x436C RS_INST_15 +0x43A8 SC_EDGERULE +0x43B0 SC_CLIP_0_A +0x43B4 SC_CLIP_0_B +0x43B8 SC_CLIP_1_A +0x43BC SC_CLIP_1_B +0x43C0 SC_CLIP_2_A +0x43C4 SC_CLIP_2_B +0x43C8 SC_CLIP_3_A +0x43CC SC_CLIP_3_B +0x43D0 SC_CLIP_RULE +0x43E0 SC_SCISSOR0 +0x43E8 SC_SCREENDOOR +0x4440 TX_FILTER1_0 +0x4444 TX_FILTER1_1 +0x4448 TX_FILTER1_2 +0x444C TX_FILTER1_3 +0x4450 TX_FILTER1_4 +0x4454 TX_FILTER1_5 +0x4458 TX_FILTER1_6 +0x445C TX_FILTER1_7 +0x4460 TX_FILTER1_8 +0x4464 TX_FILTER1_9 +0x4468 TX_FILTER1_10 +0x446C TX_FILTER1_11 +0x4470 TX_FILTER1_12 +0x4474 TX_FILTER1_13 +0x4478 TX_FILTER1_14 +0x447C TX_FILTER1_15 +0x4580 TX_CHROMA_KEY_0 +0x4584 TX_CHROMA_KEY_1 +0x4588 TX_CHROMA_KEY_2 +0x458C TX_CHROMA_KEY_3 +0x4590 TX_CHROMA_KEY_4 +0x4594 TX_CHROMA_KEY_5 +0x4598 TX_CHROMA_KEY_6 +0x459C TX_CHROMA_KEY_7 +0x45A0 TX_CHROMA_KEY_8 +0x45A4 TX_CHROMA_KEY_9 +0x45A8 TX_CHROMA_KEY_10 +0x45AC TX_CHROMA_KEY_11 +0x45B0 TX_CHROMA_KEY_12 +0x45B4 TX_CHROMA_KEY_13 +0x45B8 TX_CHROMA_KEY_14 +0x45BC TX_CHROMA_KEY_15 +0x45C0 TX_BORDER_COLOR_0 +0x45C4 TX_BORDER_COLOR_1 +0x45C8 TX_BORDER_COLOR_2 +0x45CC TX_BORDER_COLOR_3 +0x45D0 TX_BORDER_COLOR_4 +0x45D4 TX_BORDER_COLOR_5 +0x45D8 TX_BORDER_COLOR_6 +0x45DC TX_BORDER_COLOR_7 +0x45E0 TX_BORDER_COLOR_8 +0x45E4 TX_BORDER_COLOR_9 +0x45E8 TX_BORDER_COLOR_10 +0x45EC TX_BORDER_COLOR_11 +0x45F0 TX_BORDER_COLOR_12 +0x45F4 TX_BORDER_COLOR_13 +0x45F8 TX_BORDER_COLOR_14 +0x45FC TX_BORDER_COLOR_15 +0x4600 US_CONFIG +0x4604 US_PIXSIZE +0x4608 US_CODE_OFFSET +0x460C US_RESET +0x4610 US_CODE_ADDR_0 +0x4614 US_CODE_ADDR_1 +0x4618 US_CODE_ADDR_2 +0x461C US_CODE_ADDR_3 +0x4620 US_TEX_INST_0 +0x4624 US_TEX_INST_1 +0x4628 US_TEX_INST_2 +0x462C US_TEX_INST_3 +0x4630 US_TEX_INST_4 +0x4634 US_TEX_INST_5 +0x4638 US_TEX_INST_6 +0x463C US_TEX_INST_7 +0x4640 US_TEX_INST_8 +0x4644 US_TEX_INST_9 +0x4648 US_TEX_INST_10 +0x464C US_TEX_INST_11 +0x4650 US_TEX_INST_12 +0x4654 US_TEX_INST_13 +0x4658 US_TEX_INST_14 +0x465C US_TEX_INST_15 +0x4660 US_TEX_INST_16 +0x4664 US_TEX_INST_17 +0x4668 US_TEX_INST_18 +0x466C US_TEX_INST_19 +0x4670 US_TEX_INST_20 +0x4674 US_TEX_INST_21 +0x4678 US_TEX_INST_22 +0x467C US_TEX_INST_23 +0x4680 US_TEX_INST_24 +0x4684 US_TEX_INST_25 +0x4688 US_TEX_INST_26 +0x468C US_TEX_INST_27 +0x4690 US_TEX_INST_28 +0x4694 US_TEX_INST_29 +0x4698 US_TEX_INST_30 +0x469C US_TEX_INST_31 +0x46A4 US_OUT_FMT_0 +0x46A8 US_OUT_FMT_1 +0x46AC US_OUT_FMT_2 +0x46B0 US_OUT_FMT_3 +0x46B4 US_W_FMT +0x46B8 US_CODE_BANK +0x46BC US_CODE_EXT +0x46C0 US_ALU_RGB_ADDR_0 +0x46C4 US_ALU_RGB_ADDR_1 +0x46C8 US_ALU_RGB_ADDR_2 +0x46CC US_ALU_RGB_ADDR_3 +0x46D0 US_ALU_RGB_ADDR_4 +0x46D4 US_ALU_RGB_ADDR_5 +0x46D8 US_ALU_RGB_ADDR_6 +0x46DC US_ALU_RGB_ADDR_7 +0x46E0 US_ALU_RGB_ADDR_8 +0x46E4 US_ALU_RGB_ADDR_9 +0x46E8 US_ALU_RGB_ADDR_10 +0x46EC US_ALU_RGB_ADDR_11 +0x46F0 US_ALU_RGB_ADDR_12 +0x46F4 US_ALU_RGB_ADDR_13 +0x46F8 US_ALU_RGB_ADDR_14 +0x46FC US_ALU_RGB_ADDR_15 +0x4700 US_ALU_RGB_ADDR_16 +0x4704 US_ALU_RGB_ADDR_17 +0x4708 US_ALU_RGB_ADDR_18 +0x470C US_ALU_RGB_ADDR_19 +0x4710 US_ALU_RGB_ADDR_20 +0x4714 US_ALU_RGB_ADDR_21 +0x4718 US_ALU_RGB_ADDR_22 +0x471C US_ALU_RGB_ADDR_23 +0x4720 US_ALU_RGB_ADDR_24 +0x4724 US_ALU_RGB_ADDR_25 +0x4728 US_ALU_RGB_ADDR_26 +0x472C US_ALU_RGB_ADDR_27 +0x4730 US_ALU_RGB_ADDR_28 +0x4734 US_ALU_RGB_ADDR_29 +0x4738 US_ALU_RGB_ADDR_30 +0x473C US_ALU_RGB_ADDR_31 +0x4740 US_ALU_RGB_ADDR_32 +0x4744 US_ALU_RGB_ADDR_33 +0x4748 US_ALU_RGB_ADDR_34 +0x474C US_ALU_RGB_ADDR_35 +0x4750 US_ALU_RGB_ADDR_36 +0x4754 US_ALU_RGB_ADDR_37 +0x4758 US_ALU_RGB_ADDR_38 +0x475C US_ALU_RGB_ADDR_39 +0x4760 US_ALU_RGB_ADDR_40 +0x4764 US_ALU_RGB_ADDR_41 +0x4768 US_ALU_RGB_ADDR_42 +0x476C US_ALU_RGB_ADDR_43 +0x4770 US_ALU_RGB_ADDR_44 +0x4774 US_ALU_RGB_ADDR_45 +0x4778 US_ALU_RGB_ADDR_46 +0x477C US_ALU_RGB_ADDR_47 +0x4780 US_ALU_RGB_ADDR_48 +0x4784 US_ALU_RGB_ADDR_49 +0x4788 US_ALU_RGB_ADDR_50 +0x478C US_ALU_RGB_ADDR_51 +0x4790 US_ALU_RGB_ADDR_52 +0x4794 US_ALU_RGB_ADDR_53 +0x4798 US_ALU_RGB_ADDR_54 +0x479C US_ALU_RGB_ADDR_55 +0x47A0 US_ALU_RGB_ADDR_56 +0x47A4 US_ALU_RGB_ADDR_57 +0x47A8 US_ALU_RGB_ADDR_58 +0x47AC US_ALU_RGB_ADDR_59 +0x47B0 US_ALU_RGB_ADDR_60 +0x47B4 US_ALU_RGB_ADDR_61 +0x47B8 US_ALU_RGB_ADDR_62 +0x47BC US_ALU_RGB_ADDR_63 +0x47C0 US_ALU_ALPHA_ADDR_0 +0x47C4 US_ALU_ALPHA_ADDR_1 +0x47C8 US_ALU_ALPHA_ADDR_2 +0x47CC US_ALU_ALPHA_ADDR_3 +0x47D0 US_ALU_ALPHA_ADDR_4 +0x47D4 US_ALU_ALPHA_ADDR_5 +0x47D8 US_ALU_ALPHA_ADDR_6 +0x47DC US_ALU_ALPHA_ADDR_7 +0x47E0 US_ALU_ALPHA_ADDR_8 +0x47E4 US_ALU_ALPHA_ADDR_9 +0x47E8 US_ALU_ALPHA_ADDR_10 +0x47EC US_ALU_ALPHA_ADDR_11 +0x47F0 US_ALU_ALPHA_ADDR_12 +0x47F4 US_ALU_ALPHA_ADDR_13 +0x47F8 US_ALU_ALPHA_ADDR_14 +0x47FC US_ALU_ALPHA_ADDR_15 +0x4800 US_ALU_ALPHA_ADDR_16 +0x4804 US_ALU_ALPHA_ADDR_17 +0x4808 US_ALU_ALPHA_ADDR_18 +0x480C US_ALU_ALPHA_ADDR_19 +0x4810 US_ALU_ALPHA_ADDR_20 +0x4814 US_ALU_ALPHA_ADDR_21 +0x4818 US_ALU_ALPHA_ADDR_22 +0x481C US_ALU_ALPHA_ADDR_23 +0x4820 US_ALU_ALPHA_ADDR_24 +0x4824 US_ALU_ALPHA_ADDR_25 +0x4828 US_ALU_ALPHA_ADDR_26 +0x482C US_ALU_ALPHA_ADDR_27 +0x4830 US_ALU_ALPHA_ADDR_28 +0x4834 US_ALU_ALPHA_ADDR_29 +0x4838 US_ALU_ALPHA_ADDR_30 +0x483C US_ALU_ALPHA_ADDR_31 +0x4840 US_ALU_ALPHA_ADDR_32 +0x4844 US_ALU_ALPHA_ADDR_33 +0x4848 US_ALU_ALPHA_ADDR_34 +0x484C US_ALU_ALPHA_ADDR_35 +0x4850 US_ALU_ALPHA_ADDR_36 +0x4854 US_ALU_ALPHA_ADDR_37 +0x4858 US_ALU_ALPHA_ADDR_38 +0x485C US_ALU_ALPHA_ADDR_39 +0x4860 US_ALU_ALPHA_ADDR_40 +0x4864 US_ALU_ALPHA_ADDR_41 +0x4868 US_ALU_ALPHA_ADDR_42 +0x486C US_ALU_ALPHA_ADDR_43 +0x4870 US_ALU_ALPHA_ADDR_44 +0x4874 US_ALU_ALPHA_ADDR_45 +0x4878 US_ALU_ALPHA_ADDR_46 +0x487C US_ALU_ALPHA_ADDR_47 +0x4880 US_ALU_ALPHA_ADDR_48 +0x4884 US_ALU_ALPHA_ADDR_49 +0x4888 US_ALU_ALPHA_ADDR_50 +0x488C US_ALU_ALPHA_ADDR_51 +0x4890 US_ALU_ALPHA_ADDR_52 +0x4894 US_ALU_ALPHA_ADDR_53 +0x4898 US_ALU_ALPHA_ADDR_54 +0x489C US_ALU_ALPHA_ADDR_55 +0x48A0 US_ALU_ALPHA_ADDR_56 +0x48A4 US_ALU_ALPHA_ADDR_57 +0x48A8 US_ALU_ALPHA_ADDR_58 +0x48AC US_ALU_ALPHA_ADDR_59 +0x48B0 US_ALU_ALPHA_ADDR_60 +0x48B4 US_ALU_ALPHA_ADDR_61 +0x48B8 US_ALU_ALPHA_ADDR_62 +0x48BC US_ALU_ALPHA_ADDR_63 +0x48C0 US_ALU_RGB_INST_0 +0x48C4 US_ALU_RGB_INST_1 +0x48C8 US_ALU_RGB_INST_2 +0x48CC US_ALU_RGB_INST_3 +0x48D0 US_ALU_RGB_INST_4 +0x48D4 US_ALU_RGB_INST_5 +0x48D8 US_ALU_RGB_INST_6 +0x48DC US_ALU_RGB_INST_7 +0x48E0 US_ALU_RGB_INST_8 +0x48E4 US_ALU_RGB_INST_9 +0x48E8 US_ALU_RGB_INST_10 +0x48EC US_ALU_RGB_INST_11 +0x48F0 US_ALU_RGB_INST_12 +0x48F4 US_ALU_RGB_INST_13 +0x48F8 US_ALU_RGB_INST_14 +0x48FC US_ALU_RGB_INST_15 +0x4900 US_ALU_RGB_INST_16 +0x4904 US_ALU_RGB_INST_17 +0x4908 US_ALU_RGB_INST_18 +0x490C US_ALU_RGB_INST_19 +0x4910 US_ALU_RGB_INST_20 +0x4914 US_ALU_RGB_INST_21 +0x4918 US_ALU_RGB_INST_22 +0x491C US_ALU_RGB_INST_23 +0x4920 US_ALU_RGB_INST_24 +0x4924 US_ALU_RGB_INST_25 +0x4928 US_ALU_RGB_INST_26 +0x492C US_ALU_RGB_INST_27 +0x4930 US_ALU_RGB_INST_28 +0x4934 US_ALU_RGB_INST_29 +0x4938 US_ALU_RGB_INST_30 +0x493C US_ALU_RGB_INST_31 +0x4940 US_ALU_RGB_INST_32 +0x4944 US_ALU_RGB_INST_33 +0x4948 US_ALU_RGB_INST_34 +0x494C US_ALU_RGB_INST_35 +0x4950 US_ALU_RGB_INST_36 +0x4954 US_ALU_RGB_INST_37 +0x4958 US_ALU_RGB_INST_38 +0x495C US_ALU_RGB_INST_39 +0x4960 US_ALU_RGB_INST_40 +0x4964 US_ALU_RGB_INST_41 +0x4968 US_ALU_RGB_INST_42 +0x496C US_ALU_RGB_INST_43 +0x4970 US_ALU_RGB_INST_44 +0x4974 US_ALU_RGB_INST_45 +0x4978 US_ALU_RGB_INST_46 +0x497C US_ALU_RGB_INST_47 +0x4980 US_ALU_RGB_INST_48 +0x4984 US_ALU_RGB_INST_49 +0x4988 US_ALU_RGB_INST_50 +0x498C US_ALU_RGB_INST_51 +0x4990 US_ALU_RGB_INST_52 +0x4994 US_ALU_RGB_INST_53 +0x4998 US_ALU_RGB_INST_54 +0x499C US_ALU_RGB_INST_55 +0x49A0 US_ALU_RGB_INST_56 +0x49A4 US_ALU_RGB_INST_57 +0x49A8 US_ALU_RGB_INST_58 +0x49AC US_ALU_RGB_INST_59 +0x49B0 US_ALU_RGB_INST_60 +0x49B4 US_ALU_RGB_INST_61 +0x49B8 US_ALU_RGB_INST_62 +0x49BC US_ALU_RGB_INST_63 +0x49C0 US_ALU_ALPHA_INST_0 +0x49C4 US_ALU_ALPHA_INST_1 +0x49C8 US_ALU_ALPHA_INST_2 +0x49CC US_ALU_ALPHA_INST_3 +0x49D0 US_ALU_ALPHA_INST_4 +0x49D4 US_ALU_ALPHA_INST_5 +0x49D8 US_ALU_ALPHA_INST_6 +0x49DC US_ALU_ALPHA_INST_7 +0x49E0 US_ALU_ALPHA_INST_8 +0x49E4 US_ALU_ALPHA_INST_9 +0x49E8 US_ALU_ALPHA_INST_10 +0x49EC US_ALU_ALPHA_INST_11 +0x49F0 US_ALU_ALPHA_INST_12 +0x49F4 US_ALU_ALPHA_INST_13 +0x49F8 US_ALU_ALPHA_INST_14 +0x49FC US_ALU_ALPHA_INST_15 +0x4A00 US_ALU_ALPHA_INST_16 +0x4A04 US_ALU_ALPHA_INST_17 +0x4A08 US_ALU_ALPHA_INST_18 +0x4A0C US_ALU_ALPHA_INST_19 +0x4A10 US_ALU_ALPHA_INST_20 +0x4A14 US_ALU_ALPHA_INST_21 +0x4A18 US_ALU_ALPHA_INST_22 +0x4A1C US_ALU_ALPHA_INST_23 +0x4A20 US_ALU_ALPHA_INST_24 +0x4A24 US_ALU_ALPHA_INST_25 +0x4A28 US_ALU_ALPHA_INST_26 +0x4A2C US_ALU_ALPHA_INST_27 +0x4A30 US_ALU_ALPHA_INST_28 +0x4A34 US_ALU_ALPHA_INST_29 +0x4A38 US_ALU_ALPHA_INST_30 +0x4A3C US_ALU_ALPHA_INST_31 +0x4A40 US_ALU_ALPHA_INST_32 +0x4A44 US_ALU_ALPHA_INST_33 +0x4A48 US_ALU_ALPHA_INST_34 +0x4A4C US_ALU_ALPHA_INST_35 +0x4A50 US_ALU_ALPHA_INST_36 +0x4A54 US_ALU_ALPHA_INST_37 +0x4A58 US_ALU_ALPHA_INST_38 +0x4A5C US_ALU_ALPHA_INST_39 +0x4A60 US_ALU_ALPHA_INST_40 +0x4A64 US_ALU_ALPHA_INST_41 +0x4A68 US_ALU_ALPHA_INST_42 +0x4A6C US_ALU_ALPHA_INST_43 +0x4A70 US_ALU_ALPHA_INST_44 +0x4A74 US_ALU_ALPHA_INST_45 +0x4A78 US_ALU_ALPHA_INST_46 +0x4A7C US_ALU_ALPHA_INST_47 +0x4A80 US_ALU_ALPHA_INST_48 +0x4A84 US_ALU_ALPHA_INST_49 +0x4A88 US_ALU_ALPHA_INST_50 +0x4A8C US_ALU_ALPHA_INST_51 +0x4A90 US_ALU_ALPHA_INST_52 +0x4A94 US_ALU_ALPHA_INST_53 +0x4A98 US_ALU_ALPHA_INST_54 +0x4A9C US_ALU_ALPHA_INST_55 +0x4AA0 US_ALU_ALPHA_INST_56 +0x4AA4 US_ALU_ALPHA_INST_57 +0x4AA8 US_ALU_ALPHA_INST_58 +0x4AAC US_ALU_ALPHA_INST_59 +0x4AB0 US_ALU_ALPHA_INST_60 +0x4AB4 US_ALU_ALPHA_INST_61 +0x4AB8 US_ALU_ALPHA_INST_62 +0x4ABC US_ALU_ALPHA_INST_63 +0x4AC0 US_ALU_EXT_ADDR_0 +0x4AC4 US_ALU_EXT_ADDR_1 +0x4AC8 US_ALU_EXT_ADDR_2 +0x4ACC US_ALU_EXT_ADDR_3 +0x4AD0 US_ALU_EXT_ADDR_4 +0x4AD4 US_ALU_EXT_ADDR_5 +0x4AD8 US_ALU_EXT_ADDR_6 +0x4ADC US_ALU_EXT_ADDR_7 +0x4AE0 US_ALU_EXT_ADDR_8 +0x4AE4 US_ALU_EXT_ADDR_9 +0x4AE8 US_ALU_EXT_ADDR_10 +0x4AEC US_ALU_EXT_ADDR_11 +0x4AF0 US_ALU_EXT_ADDR_12 +0x4AF4 US_ALU_EXT_ADDR_13 +0x4AF8 US_ALU_EXT_ADDR_14 +0x4AFC US_ALU_EXT_ADDR_15 +0x4B00 US_ALU_EXT_ADDR_16 +0x4B04 US_ALU_EXT_ADDR_17 +0x4B08 US_ALU_EXT_ADDR_18 +0x4B0C US_ALU_EXT_ADDR_19 +0x4B10 US_ALU_EXT_ADDR_20 +0x4B14 US_ALU_EXT_ADDR_21 +0x4B18 US_ALU_EXT_ADDR_22 +0x4B1C US_ALU_EXT_ADDR_23 +0x4B20 US_ALU_EXT_ADDR_24 +0x4B24 US_ALU_EXT_ADDR_25 +0x4B28 US_ALU_EXT_ADDR_26 +0x4B2C US_ALU_EXT_ADDR_27 +0x4B30 US_ALU_EXT_ADDR_28 +0x4B34 US_ALU_EXT_ADDR_29 +0x4B38 US_ALU_EXT_ADDR_30 +0x4B3C US_ALU_EXT_ADDR_31 +0x4B40 US_ALU_EXT_ADDR_32 +0x4B44 US_ALU_EXT_ADDR_33 +0x4B48 US_ALU_EXT_ADDR_34 +0x4B4C US_ALU_EXT_ADDR_35 +0x4B50 US_ALU_EXT_ADDR_36 +0x4B54 US_ALU_EXT_ADDR_37 +0x4B58 US_ALU_EXT_ADDR_38 +0x4B5C US_ALU_EXT_ADDR_39 +0x4B60 US_ALU_EXT_ADDR_40 +0x4B64 US_ALU_EXT_ADDR_41 +0x4B68 US_ALU_EXT_ADDR_42 +0x4B6C US_ALU_EXT_ADDR_43 +0x4B70 US_ALU_EXT_ADDR_44 +0x4B74 US_ALU_EXT_ADDR_45 +0x4B78 US_ALU_EXT_ADDR_46 +0x4B7C US_ALU_EXT_ADDR_47 +0x4B80 US_ALU_EXT_ADDR_48 +0x4B84 US_ALU_EXT_ADDR_49 +0x4B88 US_ALU_EXT_ADDR_50 +0x4B8C US_ALU_EXT_ADDR_51 +0x4B90 US_ALU_EXT_ADDR_52 +0x4B94 US_ALU_EXT_ADDR_53 +0x4B98 US_ALU_EXT_ADDR_54 +0x4B9C US_ALU_EXT_ADDR_55 +0x4BA0 US_ALU_EXT_ADDR_56 +0x4BA4 US_ALU_EXT_ADDR_57 +0x4BA8 US_ALU_EXT_ADDR_58 +0x4BAC US_ALU_EXT_ADDR_59 +0x4BB0 US_ALU_EXT_ADDR_60 +0x4BB4 US_ALU_EXT_ADDR_61 +0x4BB8 US_ALU_EXT_ADDR_62 +0x4BBC US_ALU_EXT_ADDR_63 +0x4BC0 FG_FOG_BLEND +0x4BC4 FG_FOG_FACTOR +0x4BC8 FG_FOG_COLOR_R +0x4BCC FG_FOG_COLOR_G +0x4BD0 FG_FOG_COLOR_B +0x4BD4 FG_ALPHA_FUNC +0x4BD8 FG_DEPTH_SRC +0x4C00 US_ALU_CONST_R_0 +0x4C04 US_ALU_CONST_G_0 +0x4C08 US_ALU_CONST_B_0 +0x4C0C US_ALU_CONST_A_0 +0x4C10 US_ALU_CONST_R_1 +0x4C14 US_ALU_CONST_G_1 +0x4C18 US_ALU_CONST_B_1 +0x4C1C US_ALU_CONST_A_1 +0x4C20 US_ALU_CONST_R_2 +0x4C24 US_ALU_CONST_G_2 +0x4C28 US_ALU_CONST_B_2 +0x4C2C US_ALU_CONST_A_2 +0x4C30 US_ALU_CONST_R_3 +0x4C34 US_ALU_CONST_G_3 +0x4C38 US_ALU_CONST_B_3 +0x4C3C US_ALU_CONST_A_3 +0x4C40 US_ALU_CONST_R_4 +0x4C44 US_ALU_CONST_G_4 +0x4C48 US_ALU_CONST_B_4 +0x4C4C US_ALU_CONST_A_4 +0x4C50 US_ALU_CONST_R_5 +0x4C54 US_ALU_CONST_G_5 +0x4C58 US_ALU_CONST_B_5 +0x4C5C US_ALU_CONST_A_5 +0x4C60 US_ALU_CONST_R_6 +0x4C64 US_ALU_CONST_G_6 +0x4C68 US_ALU_CONST_B_6 +0x4C6C US_ALU_CONST_A_6 +0x4C70 US_ALU_CONST_R_7 +0x4C74 US_ALU_CONST_G_7 +0x4C78 US_ALU_CONST_B_7 +0x4C7C US_ALU_CONST_A_7 +0x4C80 US_ALU_CONST_R_8 +0x4C84 US_ALU_CONST_G_8 +0x4C88 US_ALU_CONST_B_8 +0x4C8C US_ALU_CONST_A_8 +0x4C90 US_ALU_CONST_R_9 +0x4C94 US_ALU_CONST_G_9 +0x4C98 US_ALU_CONST_B_9 +0x4C9C US_ALU_CONST_A_9 +0x4CA0 US_ALU_CONST_R_10 +0x4CA4 US_ALU_CONST_G_10 +0x4CA8 US_ALU_CONST_B_10 +0x4CAC US_ALU_CONST_A_10 +0x4CB0 US_ALU_CONST_R_11 +0x4CB4 US_ALU_CONST_G_11 +0x4CB8 US_ALU_CONST_B_11 +0x4CBC US_ALU_CONST_A_11 +0x4CC0 US_ALU_CONST_R_12 +0x4CC4 US_ALU_CONST_G_12 +0x4CC8 US_ALU_CONST_B_12 +0x4CCC US_ALU_CONST_A_12 +0x4CD0 US_ALU_CONST_R_13 +0x4CD4 US_ALU_CONST_G_13 +0x4CD8 US_ALU_CONST_B_13 +0x4CDC US_ALU_CONST_A_13 +0x4CE0 US_ALU_CONST_R_14 +0x4CE4 US_ALU_CONST_G_14 +0x4CE8 US_ALU_CONST_B_14 +0x4CEC US_ALU_CONST_A_14 +0x4CF0 US_ALU_CONST_R_15 +0x4CF4 US_ALU_CONST_G_15 +0x4CF8 US_ALU_CONST_B_15 +0x4CFC US_ALU_CONST_A_15 +0x4D00 US_ALU_CONST_R_16 +0x4D04 US_ALU_CONST_G_16 +0x4D08 US_ALU_CONST_B_16 +0x4D0C US_ALU_CONST_A_16 +0x4D10 US_ALU_CONST_R_17 +0x4D14 US_ALU_CONST_G_17 +0x4D18 US_ALU_CONST_B_17 +0x4D1C US_ALU_CONST_A_17 +0x4D20 US_ALU_CONST_R_18 +0x4D24 US_ALU_CONST_G_18 +0x4D28 US_ALU_CONST_B_18 +0x4D2C US_ALU_CONST_A_18 +0x4D30 US_ALU_CONST_R_19 +0x4D34 US_ALU_CONST_G_19 +0x4D38 US_ALU_CONST_B_19 +0x4D3C US_ALU_CONST_A_19 +0x4D40 US_ALU_CONST_R_20 +0x4D44 US_ALU_CONST_G_20 +0x4D48 US_ALU_CONST_B_20 +0x4D4C US_ALU_CONST_A_20 +0x4D50 US_ALU_CONST_R_21 +0x4D54 US_ALU_CONST_G_21 +0x4D58 US_ALU_CONST_B_21 +0x4D5C US_ALU_CONST_A_21 +0x4D60 US_ALU_CONST_R_22 +0x4D64 US_ALU_CONST_G_22 +0x4D68 US_ALU_CONST_B_22 +0x4D6C US_ALU_CONST_A_22 +0x4D70 US_ALU_CONST_R_23 +0x4D74 US_ALU_CONST_G_23 +0x4D78 US_ALU_CONST_B_23 +0x4D7C US_ALU_CONST_A_23 +0x4D80 US_ALU_CONST_R_24 +0x4D84 US_ALU_CONST_G_24 +0x4D88 US_ALU_CONST_B_24 +0x4D8C US_ALU_CONST_A_24 +0x4D90 US_ALU_CONST_R_25 +0x4D94 US_ALU_CONST_G_25 +0x4D98 US_ALU_CONST_B_25 +0x4D9C US_ALU_CONST_A_25 +0x4DA0 US_ALU_CONST_R_26 +0x4DA4 US_ALU_CONST_G_26 +0x4DA8 US_ALU_CONST_B_26 +0x4DAC US_ALU_CONST_A_26 +0x4DB0 US_ALU_CONST_R_27 +0x4DB4 US_ALU_CONST_G_27 +0x4DB8 US_ALU_CONST_B_27 +0x4DBC US_ALU_CONST_A_27 +0x4DC0 US_ALU_CONST_R_28 +0x4DC4 US_ALU_CONST_G_28 +0x4DC8 US_ALU_CONST_B_28 +0x4DCC US_ALU_CONST_A_28 +0x4DD0 US_ALU_CONST_R_29 +0x4DD4 US_ALU_CONST_G_29 +0x4DD8 US_ALU_CONST_B_29 +0x4DDC US_ALU_CONST_A_29 +0x4DE0 US_ALU_CONST_R_30 +0x4DE4 US_ALU_CONST_G_30 +0x4DE8 US_ALU_CONST_B_30 +0x4DEC US_ALU_CONST_A_30 +0x4DF0 US_ALU_CONST_R_31 +0x4DF4 US_ALU_CONST_G_31 +0x4DF8 US_ALU_CONST_B_31 +0x4DFC US_ALU_CONST_A_31 +0x4E08 RB3D_ABLENDCNTL_R3 +0x4E10 RB3D_CONSTANT_COLOR +0x4E14 RB3D_COLOR_CLEAR_VALUE +0x4E18 RB3D_ROPCNTL_R3 +0x4E1C RB3D_CLRCMP_FLIPE_R3 +0x4E20 RB3D_CLRCMP_CLR_R3 +0x4E24 RB3D_CLRCMP_MSK_R3 +0x4E48 RB3D_DEBUG_CTL +0x4E4C RB3D_DSTCACHE_CTLSTAT_R3 +0x4E50 RB3D_DITHER_CTL +0x4E54 RB3D_CMASK_OFFSET0 +0x4E58 RB3D_CMASK_OFFSET1 +0x4E5C RB3D_CMASK_OFFSET2 +0x4E60 RB3D_CMASK_OFFSET3 +0x4E64 RB3D_CMASK_PITCH0 +0x4E68 RB3D_CMASK_PITCH1 +0x4E6C RB3D_CMASK_PITCH2 +0x4E70 RB3D_CMASK_PITCH3 +0x4E74 RB3D_CMASK_WRINDEX +0x4E78 RB3D_CMASK_DWORD +0x4E7C RB3D_CMASK_RDINDEX +0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD +0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD +0x4F04 ZB_ZSTENCILCNTL +0x4F08 ZB_STENCILREFMASK +0x4F14 ZB_ZTOP +0x4F18 ZB_ZCACHE_CTLSTAT +0x4F28 ZB_DEPTHCLEARVALUE +0x4F58 ZB_ZPASS_DATA diff --git a/sys/dev/drm2/radeon/reg_srcs/rv515 b/sys/dev/drm2/radeon/reg_srcs/rv515 new file mode 100644 index 00000000000..78d5e99d759 --- /dev/null +++ b/sys/dev/drm2/radeon/reg_srcs/rv515 @@ -0,0 +1,496 @@ +rv515 0x6d40 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1D98 VAP_VPORT_XSCALE +0x1D9C VAP_VPORT_XOFFSET +0x1DA0 VAP_VPORT_YSCALE +0x1DA4 VAP_VPORT_YOFFSET +0x1DA8 VAP_VPORT_ZSCALE +0x1DAC VAP_VPORT_ZOFFSET +0x2080 VAP_CNTL +0x208C VAP_INDEX_OFFSET +0x2090 VAP_OUT_VTX_FMT_0 +0x2094 VAP_OUT_VTX_FMT_1 +0x20B0 VAP_VTE_CNTL +0x2138 VAP_VF_MIN_VTX_INDX +0x2140 VAP_CNTL_STATUS +0x2150 VAP_PROG_STREAM_CNTL_0 +0x2154 VAP_PROG_STREAM_CNTL_1 +0x2158 VAP_PROG_STREAM_CNTL_2 +0x215C VAP_PROG_STREAM_CNTL_3 +0x2160 VAP_PROG_STREAM_CNTL_4 +0x2164 VAP_PROG_STREAM_CNTL_5 +0x2168 VAP_PROG_STREAM_CNTL_6 +0x216C VAP_PROG_STREAM_CNTL_7 +0x2180 VAP_VTX_STATE_CNTL +0x2184 VAP_VSM_VTX_ASSM +0x2188 VAP_VTX_STATE_IND_REG_0 +0x218C VAP_VTX_STATE_IND_REG_1 +0x2190 VAP_VTX_STATE_IND_REG_2 +0x2194 VAP_VTX_STATE_IND_REG_3 +0x2198 VAP_VTX_STATE_IND_REG_4 +0x219C VAP_VTX_STATE_IND_REG_5 +0x21A0 VAP_VTX_STATE_IND_REG_6 +0x21A4 VAP_VTX_STATE_IND_REG_7 +0x21A8 VAP_VTX_STATE_IND_REG_8 +0x21AC VAP_VTX_STATE_IND_REG_9 +0x21B0 VAP_VTX_STATE_IND_REG_10 +0x21B4 VAP_VTX_STATE_IND_REG_11 +0x21B8 VAP_VTX_STATE_IND_REG_12 +0x21BC VAP_VTX_STATE_IND_REG_13 +0x21C0 VAP_VTX_STATE_IND_REG_14 +0x21C4 VAP_VTX_STATE_IND_REG_15 +0x21DC VAP_PSC_SGN_NORM_CNTL +0x21E0 VAP_PROG_STREAM_CNTL_EXT_0 +0x21E4 VAP_PROG_STREAM_CNTL_EXT_1 +0x21E8 VAP_PROG_STREAM_CNTL_EXT_2 +0x21EC VAP_PROG_STREAM_CNTL_EXT_3 +0x21F0 VAP_PROG_STREAM_CNTL_EXT_4 +0x21F4 VAP_PROG_STREAM_CNTL_EXT_5 +0x21F8 VAP_PROG_STREAM_CNTL_EXT_6 +0x21FC VAP_PROG_STREAM_CNTL_EXT_7 +0x2200 VAP_PVS_VECTOR_INDX_REG +0x2204 VAP_PVS_VECTOR_DATA_REG +0x2208 VAP_PVS_VECTOR_DATA_REG_128 +0x2218 VAP_TEX_TO_COLOR_CNTL +0x221C VAP_CLIP_CNTL +0x2220 VAP_GB_VERT_CLIP_ADJ +0x2224 VAP_GB_VERT_DISC_ADJ +0x2228 VAP_GB_HORZ_CLIP_ADJ +0x222C VAP_GB_HORZ_DISC_ADJ +0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0 +0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1 +0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2 +0x223C VAP_PVS_FLOW_CNTL_ADDRS_3 +0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4 +0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5 +0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6 +0x224C VAP_PVS_FLOW_CNTL_ADDRS_7 +0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8 +0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9 +0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10 +0x225C VAP_PVS_FLOW_CNTL_ADDRS_11 +0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12 +0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13 +0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14 +0x226C VAP_PVS_FLOW_CNTL_ADDRS_15 +0x2284 VAP_PVS_STATE_FLUSH_REG +0x2288 VAP_PVS_VTX_TIMEOUT_REG +0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0 +0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1 +0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2 +0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3 +0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4 +0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5 +0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6 +0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7 +0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8 +0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9 +0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10 +0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11 +0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12 +0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13 +0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14 +0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15 +0x22D0 VAP_PVS_CODE_CNTL_0 +0x22D4 VAP_PVS_CONST_CNTL +0x22D8 VAP_PVS_CODE_CNTL_1 +0x22DC VAP_PVS_FLOW_CNTL_OPC +0x2500 VAP_PVS_FLOW_CNTL_ADDRS_LW_0 +0x2504 VAP_PVS_FLOW_CNTL_ADDRS_UW_0 +0x2508 VAP_PVS_FLOW_CNTL_ADDRS_LW_1 +0x250C VAP_PVS_FLOW_CNTL_ADDRS_UW_1 +0x2510 VAP_PVS_FLOW_CNTL_ADDRS_LW_2 +0x2514 VAP_PVS_FLOW_CNTL_ADDRS_UW_2 +0x2518 VAP_PVS_FLOW_CNTL_ADDRS_LW_3 +0x251C VAP_PVS_FLOW_CNTL_ADDRS_UW_3 +0x2520 VAP_PVS_FLOW_CNTL_ADDRS_LW_4 +0x2524 VAP_PVS_FLOW_CNTL_ADDRS_UW_4 +0x2528 VAP_PVS_FLOW_CNTL_ADDRS_LW_5 +0x252C VAP_PVS_FLOW_CNTL_ADDRS_UW_5 +0x2530 VAP_PVS_FLOW_CNTL_ADDRS_LW_6 +0x2534 VAP_PVS_FLOW_CNTL_ADDRS_UW_6 +0x2538 VAP_PVS_FLOW_CNTL_ADDRS_LW_7 +0x253C VAP_PVS_FLOW_CNTL_ADDRS_UW_7 +0x2540 VAP_PVS_FLOW_CNTL_ADDRS_LW_8 +0x2544 VAP_PVS_FLOW_CNTL_ADDRS_UW_8 +0x2548 VAP_PVS_FLOW_CNTL_ADDRS_LW_9 +0x254C VAP_PVS_FLOW_CNTL_ADDRS_UW_9 +0x2550 VAP_PVS_FLOW_CNTL_ADDRS_LW_10 +0x2554 VAP_PVS_FLOW_CNTL_ADDRS_UW_10 +0x2558 VAP_PVS_FLOW_CNTL_ADDRS_LW_11 +0x255C VAP_PVS_FLOW_CNTL_ADDRS_UW_11 +0x2560 VAP_PVS_FLOW_CNTL_ADDRS_LW_12 +0x2564 VAP_PVS_FLOW_CNTL_ADDRS_UW_12 +0x2568 VAP_PVS_FLOW_CNTL_ADDRS_LW_13 +0x256C VAP_PVS_FLOW_CNTL_ADDRS_UW_13 +0x2570 VAP_PVS_FLOW_CNTL_ADDRS_LW_14 +0x2574 VAP_PVS_FLOW_CNTL_ADDRS_UW_14 +0x2578 VAP_PVS_FLOW_CNTL_ADDRS_LW_15 +0x257C VAP_PVS_FLOW_CNTL_ADDRS_UW_15 +0x342C RB2D_DSTCACHE_CTLSTAT +0x4000 GB_VAP_RASTER_VTX_FMT_0 +0x4004 GB_VAP_RASTER_VTX_FMT_1 +0x4008 GB_ENABLE +0x4010 GB_MSPOS0 +0x4014 GB_MSPOS1 +0x401C GB_SELECT +0x4020 GB_AA_CONFIG +0x4024 GB_FIFO_SIZE +0x4100 TX_INVALTAGS +0x4114 SU_TEX_WRAP_PS3 +0x4118 PS3_ENABLE +0x411c PS3_VTX_FMT +0x4120 PS3_TEX_SOURCE +0x4200 GA_POINT_S0 +0x4204 GA_POINT_T0 +0x4208 GA_POINT_S1 +0x420C GA_POINT_T1 +0x4214 GA_TRIANGLE_STIPPLE +0x421C GA_POINT_SIZE +0x4230 GA_POINT_MINMAX +0x4234 GA_LINE_CNTL +0x4238 GA_LINE_STIPPLE_CONFIG +0x4258 GA_COLOR_CONTROL_PS3 +0x4260 GA_LINE_STIPPLE_VALUE +0x4264 GA_LINE_S0 +0x4268 GA_LINE_S1 +0x4278 GA_COLOR_CONTROL +0x427C GA_SOLID_RG +0x4280 GA_SOLID_BA +0x4288 GA_POLY_MODE +0x428C GA_ROUND_MODE +0x4290 GA_OFFSET +0x4294 GA_FOG_SCALE +0x4298 GA_FOG_OFFSET +0x42A0 SU_TEX_WRAP +0x42A4 SU_POLY_OFFSET_FRONT_SCALE +0x42A8 SU_POLY_OFFSET_FRONT_OFFSET +0x42AC SU_POLY_OFFSET_BACK_SCALE +0x42B0 SU_POLY_OFFSET_BACK_OFFSET +0x42B4 SU_POLY_OFFSET_ENABLE +0x42B8 SU_CULL_MODE +0x42C0 SU_DEPTH_SCALE +0x42C4 SU_DEPTH_OFFSET +0x42C8 SU_REG_DEST +0x4300 RS_COUNT +0x4304 RS_INST_COUNT +0x4074 RS_IP_0 +0x4078 RS_IP_1 +0x407C RS_IP_2 +0x4080 RS_IP_3 +0x4084 RS_IP_4 +0x4088 RS_IP_5 +0x408C RS_IP_6 +0x4090 RS_IP_7 +0x4094 RS_IP_8 +0x4098 RS_IP_9 +0x409C RS_IP_10 +0x40A0 RS_IP_11 +0x40A4 RS_IP_12 +0x40A8 RS_IP_13 +0x40AC RS_IP_14 +0x40B0 RS_IP_15 +0x4320 RS_INST_0 +0x4324 RS_INST_1 +0x4328 RS_INST_2 +0x432C RS_INST_3 +0x4330 RS_INST_4 +0x4334 RS_INST_5 +0x4338 RS_INST_6 +0x433C RS_INST_7 +0x4340 RS_INST_8 +0x4344 RS_INST_9 +0x4348 RS_INST_10 +0x434C RS_INST_11 +0x4350 RS_INST_12 +0x4354 RS_INST_13 +0x4358 RS_INST_14 +0x435C RS_INST_15 +0x43A8 SC_EDGERULE +0x43B0 SC_CLIP_0_A +0x43B4 SC_CLIP_0_B +0x43B8 SC_CLIP_1_A +0x43BC SC_CLIP_1_B +0x43C0 SC_CLIP_2_A +0x43C4 SC_CLIP_2_B +0x43C8 SC_CLIP_3_A +0x43CC SC_CLIP_3_B +0x43D0 SC_CLIP_RULE +0x43E0 SC_SCISSOR0 +0x43E8 SC_SCREENDOOR +0x4440 TX_FILTER1_0 +0x4444 TX_FILTER1_1 +0x4448 TX_FILTER1_2 +0x444C TX_FILTER1_3 +0x4450 TX_FILTER1_4 +0x4454 TX_FILTER1_5 +0x4458 TX_FILTER1_6 +0x445C TX_FILTER1_7 +0x4460 TX_FILTER1_8 +0x4464 TX_FILTER1_9 +0x4468 TX_FILTER1_10 +0x446C TX_FILTER1_11 +0x4470 TX_FILTER1_12 +0x4474 TX_FILTER1_13 +0x4478 TX_FILTER1_14 +0x447C TX_FILTER1_15 +0x4580 TX_CHROMA_KEY_0 +0x4584 TX_CHROMA_KEY_1 +0x4588 TX_CHROMA_KEY_2 +0x458C TX_CHROMA_KEY_3 +0x4590 TX_CHROMA_KEY_4 +0x4594 TX_CHROMA_KEY_5 +0x4598 TX_CHROMA_KEY_6 +0x459C TX_CHROMA_KEY_7 +0x45A0 TX_CHROMA_KEY_8 +0x45A4 TX_CHROMA_KEY_9 +0x45A8 TX_CHROMA_KEY_10 +0x45AC TX_CHROMA_KEY_11 +0x45B0 TX_CHROMA_KEY_12 +0x45B4 TX_CHROMA_KEY_13 +0x45B8 TX_CHROMA_KEY_14 +0x45BC TX_CHROMA_KEY_15 +0x45C0 TX_BORDER_COLOR_0 +0x45C4 TX_BORDER_COLOR_1 +0x45C8 TX_BORDER_COLOR_2 +0x45CC TX_BORDER_COLOR_3 +0x45D0 TX_BORDER_COLOR_4 +0x45D4 TX_BORDER_COLOR_5 +0x45D8 TX_BORDER_COLOR_6 +0x45DC TX_BORDER_COLOR_7 +0x45E0 TX_BORDER_COLOR_8 +0x45E4 TX_BORDER_COLOR_9 +0x45E8 TX_BORDER_COLOR_10 +0x45EC TX_BORDER_COLOR_11 +0x45F0 TX_BORDER_COLOR_12 +0x45F4 TX_BORDER_COLOR_13 +0x45F8 TX_BORDER_COLOR_14 +0x45FC TX_BORDER_COLOR_15 +0x4250 GA_US_VECTOR_INDEX +0x4254 GA_US_VECTOR_DATA +0x4600 US_CONFIG +0x4604 US_PIXSIZE +0x4620 US_FC_BOOL_CONST +0x4624 US_FC_CTRL +0x4630 US_CODE_ADDR +0x4634 US_CODE_RANGE +0x4638 US_CODE_OFFSET +0x4640 US_FORMAT0_0 +0x4644 US_FORMAT0_1 +0x4648 US_FORMAT0_2 +0x464C US_FORMAT0_3 +0x4650 US_FORMAT0_4 +0x4654 US_FORMAT0_5 +0x4658 US_FORMAT0_6 +0x465C US_FORMAT0_7 +0x4660 US_FORMAT0_8 +0x4664 US_FORMAT0_9 +0x4668 US_FORMAT0_10 +0x466C US_FORMAT0_11 +0x4670 US_FORMAT0_12 +0x4674 US_FORMAT0_13 +0x4678 US_FORMAT0_14 +0x467C US_FORMAT0_15 +0x46A4 US_OUT_FMT_0 +0x46A8 US_OUT_FMT_1 +0x46AC US_OUT_FMT_2 +0x46B0 US_OUT_FMT_3 +0x46B4 US_W_FMT +0x46C0 RB3D_COLOR_CLEAR_VALUE_AR +0x46C4 RB3D_COLOR_CLEAR_VALUE_GB +0x4BC0 FG_FOG_BLEND +0x4BC4 FG_FOG_FACTOR +0x4BC8 FG_FOG_COLOR_R +0x4BCC FG_FOG_COLOR_G +0x4BD0 FG_FOG_COLOR_B +0x4BD4 FG_ALPHA_FUNC +0x4BD8 FG_DEPTH_SRC +0x4BE0 FG_ALPHA_VALUE +0x4C00 US_ALU_CONST_R_0 +0x4C04 US_ALU_CONST_G_0 +0x4C08 US_ALU_CONST_B_0 +0x4C0C US_ALU_CONST_A_0 +0x4C10 US_ALU_CONST_R_1 +0x4C14 US_ALU_CONST_G_1 +0x4C18 US_ALU_CONST_B_1 +0x4C1C US_ALU_CONST_A_1 +0x4C20 US_ALU_CONST_R_2 +0x4C24 US_ALU_CONST_G_2 +0x4C28 US_ALU_CONST_B_2 +0x4C2C US_ALU_CONST_A_2 +0x4C30 US_ALU_CONST_R_3 +0x4C34 US_ALU_CONST_G_3 +0x4C38 US_ALU_CONST_B_3 +0x4C3C US_ALU_CONST_A_3 +0x4C40 US_ALU_CONST_R_4 +0x4C44 US_ALU_CONST_G_4 +0x4C48 US_ALU_CONST_B_4 +0x4C4C US_ALU_CONST_A_4 +0x4C50 US_ALU_CONST_R_5 +0x4C54 US_ALU_CONST_G_5 +0x4C58 US_ALU_CONST_B_5 +0x4C5C US_ALU_CONST_A_5 +0x4C60 US_ALU_CONST_R_6 +0x4C64 US_ALU_CONST_G_6 +0x4C68 US_ALU_CONST_B_6 +0x4C6C US_ALU_CONST_A_6 +0x4C70 US_ALU_CONST_R_7 +0x4C74 US_ALU_CONST_G_7 +0x4C78 US_ALU_CONST_B_7 +0x4C7C US_ALU_CONST_A_7 +0x4C80 US_ALU_CONST_R_8 +0x4C84 US_ALU_CONST_G_8 +0x4C88 US_ALU_CONST_B_8 +0x4C8C US_ALU_CONST_A_8 +0x4C90 US_ALU_CONST_R_9 +0x4C94 US_ALU_CONST_G_9 +0x4C98 US_ALU_CONST_B_9 +0x4C9C US_ALU_CONST_A_9 +0x4CA0 US_ALU_CONST_R_10 +0x4CA4 US_ALU_CONST_G_10 +0x4CA8 US_ALU_CONST_B_10 +0x4CAC US_ALU_CONST_A_10 +0x4CB0 US_ALU_CONST_R_11 +0x4CB4 US_ALU_CONST_G_11 +0x4CB8 US_ALU_CONST_B_11 +0x4CBC US_ALU_CONST_A_11 +0x4CC0 US_ALU_CONST_R_12 +0x4CC4 US_ALU_CONST_G_12 +0x4CC8 US_ALU_CONST_B_12 +0x4CCC US_ALU_CONST_A_12 +0x4CD0 US_ALU_CONST_R_13 +0x4CD4 US_ALU_CONST_G_13 +0x4CD8 US_ALU_CONST_B_13 +0x4CDC US_ALU_CONST_A_13 +0x4CE0 US_ALU_CONST_R_14 +0x4CE4 US_ALU_CONST_G_14 +0x4CE8 US_ALU_CONST_B_14 +0x4CEC US_ALU_CONST_A_14 +0x4CF0 US_ALU_CONST_R_15 +0x4CF4 US_ALU_CONST_G_15 +0x4CF8 US_ALU_CONST_B_15 +0x4CFC US_ALU_CONST_A_15 +0x4D00 US_ALU_CONST_R_16 +0x4D04 US_ALU_CONST_G_16 +0x4D08 US_ALU_CONST_B_16 +0x4D0C US_ALU_CONST_A_16 +0x4D10 US_ALU_CONST_R_17 +0x4D14 US_ALU_CONST_G_17 +0x4D18 US_ALU_CONST_B_17 +0x4D1C US_ALU_CONST_A_17 +0x4D20 US_ALU_CONST_R_18 +0x4D24 US_ALU_CONST_G_18 +0x4D28 US_ALU_CONST_B_18 +0x4D2C US_ALU_CONST_A_18 +0x4D30 US_ALU_CONST_R_19 +0x4D34 US_ALU_CONST_G_19 +0x4D38 US_ALU_CONST_B_19 +0x4D3C US_ALU_CONST_A_19 +0x4D40 US_ALU_CONST_R_20 +0x4D44 US_ALU_CONST_G_20 +0x4D48 US_ALU_CONST_B_20 +0x4D4C US_ALU_CONST_A_20 +0x4D50 US_ALU_CONST_R_21 +0x4D54 US_ALU_CONST_G_21 +0x4D58 US_ALU_CONST_B_21 +0x4D5C US_ALU_CONST_A_21 +0x4D60 US_ALU_CONST_R_22 +0x4D64 US_ALU_CONST_G_22 +0x4D68 US_ALU_CONST_B_22 +0x4D6C US_ALU_CONST_A_22 +0x4D70 US_ALU_CONST_R_23 +0x4D74 US_ALU_CONST_G_23 +0x4D78 US_ALU_CONST_B_23 +0x4D7C US_ALU_CONST_A_23 +0x4D80 US_ALU_CONST_R_24 +0x4D84 US_ALU_CONST_G_24 +0x4D88 US_ALU_CONST_B_24 +0x4D8C US_ALU_CONST_A_24 +0x4D90 US_ALU_CONST_R_25 +0x4D94 US_ALU_CONST_G_25 +0x4D98 US_ALU_CONST_B_25 +0x4D9C US_ALU_CONST_A_25 +0x4DA0 US_ALU_CONST_R_26 +0x4DA4 US_ALU_CONST_G_26 +0x4DA8 US_ALU_CONST_B_26 +0x4DAC US_ALU_CONST_A_26 +0x4DB0 US_ALU_CONST_R_27 +0x4DB4 US_ALU_CONST_G_27 +0x4DB8 US_ALU_CONST_B_27 +0x4DBC US_ALU_CONST_A_27 +0x4DC0 US_ALU_CONST_R_28 +0x4DC4 US_ALU_CONST_G_28 +0x4DC8 US_ALU_CONST_B_28 +0x4DCC US_ALU_CONST_A_28 +0x4DD0 US_ALU_CONST_R_29 +0x4DD4 US_ALU_CONST_G_29 +0x4DD8 US_ALU_CONST_B_29 +0x4DDC US_ALU_CONST_A_29 +0x4DE0 US_ALU_CONST_R_30 +0x4DE4 US_ALU_CONST_G_30 +0x4DE8 US_ALU_CONST_B_30 +0x4DEC US_ALU_CONST_A_30 +0x4DF0 US_ALU_CONST_R_31 +0x4DF4 US_ALU_CONST_G_31 +0x4DF8 US_ALU_CONST_B_31 +0x4DFC US_ALU_CONST_A_31 +0x4E08 RB3D_ABLENDCNTL_R3 +0x4E10 RB3D_CONSTANT_COLOR +0x4E14 RB3D_COLOR_CLEAR_VALUE +0x4E18 RB3D_ROPCNTL_R3 +0x4E1C RB3D_CLRCMP_FLIPE_R3 +0x4E20 RB3D_CLRCMP_CLR_R3 +0x4E24 RB3D_CLRCMP_MSK_R3 +0x4E48 RB3D_DEBUG_CTL +0x4E4C RB3D_DSTCACHE_CTLSTAT_R3 +0x4E50 RB3D_DITHER_CTL +0x4E54 RB3D_CMASK_OFFSET0 +0x4E58 RB3D_CMASK_OFFSET1 +0x4E5C RB3D_CMASK_OFFSET2 +0x4E60 RB3D_CMASK_OFFSET3 +0x4E64 RB3D_CMASK_PITCH0 +0x4E68 RB3D_CMASK_PITCH1 +0x4E6C RB3D_CMASK_PITCH2 +0x4E70 RB3D_CMASK_PITCH3 +0x4E74 RB3D_CMASK_WRINDEX +0x4E78 RB3D_CMASK_DWORD +0x4E7C RB3D_CMASK_RDINDEX +0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD +0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD +0x4EF8 RB3D_CONSTANT_COLOR_AR +0x4EFC RB3D_CONSTANT_COLOR_GB +0x4F04 ZB_ZSTENCILCNTL +0x4F08 ZB_STENCILREFMASK +0x4F14 ZB_ZTOP +0x4F18 ZB_ZCACHE_CTLSTAT +0x4F58 ZB_ZPASS_DATA +0x4F28 ZB_DEPTHCLEARVALUE +0x4FD4 ZB_STENCILREFMASK_BF diff --git a/sys/dev/drm2/radeon/rn50_reg_safe.h b/sys/dev/drm2/radeon/rn50_reg_safe.h new file mode 100644 index 00000000000..043d8a45bcc --- /dev/null +++ b/sys/dev/drm2/radeon/rn50_reg_safe.h @@ -0,0 +1,31 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned rn50_reg_safe_bm[102] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, +}; diff --git a/sys/dev/drm2/radeon/rs100d.h b/sys/dev/drm2/radeon/rs100d.h new file mode 100644 index 00000000000..d90bb5157ce --- /dev/null +++ b/sys/dev/drm2/radeon/rs100d.h @@ -0,0 +1,43 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RS100D_H__ +#define __RS100D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* Registers */ +#define R_00015C_NB_TOM 0x00015C +#define S_00015C_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_00015C_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_00015C_MC_FB_START 0xFFFF0000 +#define S_00015C_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_00015C_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_00015C_MC_FB_TOP 0x0000FFFF + +#endif diff --git a/sys/dev/drm2/radeon/rs400.c b/sys/dev/drm2/radeon/rs400.c new file mode 100644 index 00000000000..f9d638d013e --- /dev/null +++ b/sys/dev/drm2/radeon/rs400.c @@ -0,0 +1,568 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "rs400d.h" + +/* This files gather functions specifics to : rs400,rs480 */ +static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev); + +void rs400_gart_adjust_size(struct radeon_device *rdev) +{ + /* Check gart size */ + switch (rdev->mc.gtt_size/(1024*1024)) { + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + break; + default: + DRM_ERROR("Unable to use IGP GART size %uM\n", + (unsigned)(rdev->mc.gtt_size >> 20)); + DRM_ERROR("Valid GART size for IGP are 32M,64M,128M,256M,512M,1G,2G\n"); + DRM_ERROR("Forcing to 32M GART size\n"); + rdev->mc.gtt_size = 32 * 1024 * 1024; + return; + } +} + +void rs400_gart_tlb_flush(struct radeon_device *rdev) +{ + uint32_t tmp; + unsigned int timeout = rdev->usec_timeout; + + WREG32_MC(RS480_GART_CACHE_CNTRL, RS480_GART_CACHE_INVALIDATE); + do { + tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); + if ((tmp & RS480_GART_CACHE_INVALIDATE) == 0) + break; + DRM_UDELAY(1); + timeout--; + } while (timeout > 0); + WREG32_MC(RS480_GART_CACHE_CNTRL, 0); +} + +int rs400_gart_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.ptr) { + DRM_ERROR("RS400 GART already initialized\n"); + return 0; + } + /* Check gart size */ + switch(rdev->mc.gtt_size / (1024 * 1024)) { + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + break; + default: + return -EINVAL; + } + /* Initialize common gart structure */ + r = radeon_gart_init(rdev); + if (r) + return r; + if (rs400_debugfs_pcie_gart_info_init(rdev)) + DRM_ERROR("Failed to register debugfs file for RS400 GART !\n"); + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; + return radeon_gart_table_ram_alloc(rdev); +} + +int rs400_gart_enable(struct radeon_device *rdev) +{ + uint32_t size_reg; + uint32_t tmp; + + radeon_gart_restore(rdev); + tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); + tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; + WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); + /* Check gart size */ + switch(rdev->mc.gtt_size / (1024 * 1024)) { + case 32: + size_reg = RS480_VA_SIZE_32MB; + break; + case 64: + size_reg = RS480_VA_SIZE_64MB; + break; + case 128: + size_reg = RS480_VA_SIZE_128MB; + break; + case 256: + size_reg = RS480_VA_SIZE_256MB; + break; + case 512: + size_reg = RS480_VA_SIZE_512MB; + break; + case 1024: + size_reg = RS480_VA_SIZE_1GB; + break; + case 2048: + size_reg = RS480_VA_SIZE_2GB; + break; + default: + return -EINVAL; + } + /* It should be fine to program it to max value */ + if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { + WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF); + WREG32_MC(RS690_MCCFG_AGP_BASE_2, 0); + } else { + WREG32(RADEON_AGP_BASE, 0xFFFFFFFF); + WREG32(RS480_AGP_BASE_2, 0); + } + tmp = REG_SET(RS690_MC_AGP_TOP, rdev->mc.gtt_end >> 16); + tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_start >> 16); + if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { + WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp); + tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); + } else { + WREG32(RADEON_MC_AGP_LOCATION, tmp); + tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); + } + /* Table should be in 32bits address space so ignore bits above. */ + tmp = (u32)rdev->gart.table_addr & 0xfffff000; + tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4; + + WREG32_MC(RS480_GART_BASE, tmp); + /* TODO: more tweaking here */ + WREG32_MC(RS480_GART_FEATURE_ID, + (RS480_TLB_ENABLE | + RS480_GTW_LAC_EN | RS480_1LEVEL_GART)); + /* Disable snooping */ + WREG32_MC(RS480_AGP_MODE_CNTL, + (1 << RS480_REQ_TYPE_SNOOP_SHIFT) | RS480_REQ_TYPE_SNOOP_DIS); + /* Disable AGP mode */ + if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { + tmp = RREG32_MC(RS690_MC_NB_CNTL); + tmp &= ~(RS690_HIDE_MMCFG_BAR | + RS690_AGPMODE30 | + RS690_AGP30ENHANCED); + WREG32_MC(RS690_MC_NB_CNTL, tmp); + WREG32_MC(RS480_MC_MISC_CNTL, + (RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN)); + } else { + WREG32_MC(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); + } + /* Enable gart */ + WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg)); + rs400_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +void rs400_gart_disable(struct radeon_device *rdev) +{ + uint32_t tmp; + + tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); + tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; + WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); + WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0); +} + +void rs400_gart_fini(struct radeon_device *rdev) +{ + radeon_gart_fini(rdev); + rs400_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); +} + +#define RS400_PTE_WRITEABLE (1 << 2) +#define RS400_PTE_READABLE (1 << 3) + +int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +{ + uint32_t entry; + u32 *gtt = rdev->gart.ptr; + + if (i < 0 || i > rdev->gart.num_gpu_pages) { + return -EINVAL; + } + + entry = (lower_32_bits(addr) & 0xfffff000) | + ((upper_32_bits(addr) & 0xff) << 4) | + RS400_PTE_WRITEABLE | RS400_PTE_READABLE; + entry = cpu_to_le32(entry); + gtt[i] = entry; + return 0; +} + +int rs400_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & RADEON_MC_IDLE) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +static void rs400_gpu_init(struct radeon_device *rdev) +{ + /* FIXME: is this correct ? */ + r420_pipes_init(rdev); + if (rs400_mc_wait_for_idle(rdev)) { + DRM_ERROR("rs400: Failed to wait MC idle while " + "programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS)); + } +} + +static void rs400_mc_init(struct radeon_device *rdev) +{ + u64 base; + + rs400_gart_adjust_size(rdev); + rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev); + /* DDR for all card after R300 & IGP */ + rdev->mc.vram_is_ddr = true; + rdev->mc.vram_width = 128; + r100_vram_init_sizes(rdev); + base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1; + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + +uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg) +{ + uint32_t r; + + WREG32(RS480_NB_MC_INDEX, reg & 0xff); + r = RREG32(RS480_NB_MC_DATA); + WREG32(RS480_NB_MC_INDEX, 0xff); + return r; +} + +void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN); + WREG32(RS480_NB_MC_DATA, (v)); + WREG32(RS480_NB_MC_INDEX, 0xff); +} + +#if defined(CONFIG_DEBUG_FS) +static int rs400_debugfs_gart_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + tmp = RREG32(RADEON_HOST_PATH_CNTL); + seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); + tmp = RREG32(RADEON_BUS_CNTL); + seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); + tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); + seq_printf(m, "AIC_CTRL_SCRATCH 0x%08x\n", tmp); + if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { + tmp = RREG32_MC(RS690_MCCFG_AGP_BASE); + seq_printf(m, "MCCFG_AGP_BASE 0x%08x\n", tmp); + tmp = RREG32_MC(RS690_MCCFG_AGP_BASE_2); + seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp); + tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION); + seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp); + tmp = RREG32_MC(RS690_MCCFG_FB_LOCATION); + seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp); + tmp = RREG32(RS690_HDP_FB_LOCATION); + seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp); + } else { + tmp = RREG32(RADEON_AGP_BASE); + seq_printf(m, "AGP_BASE 0x%08x\n", tmp); + tmp = RREG32(RS480_AGP_BASE_2); + seq_printf(m, "AGP_BASE_2 0x%08x\n", tmp); + tmp = RREG32(RADEON_MC_AGP_LOCATION); + seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); + } + tmp = RREG32_MC(RS480_GART_BASE); + seq_printf(m, "GART_BASE 0x%08x\n", tmp); + tmp = RREG32_MC(RS480_GART_FEATURE_ID); + seq_printf(m, "GART_FEATURE_ID 0x%08x\n", tmp); + tmp = RREG32_MC(RS480_AGP_MODE_CNTL); + seq_printf(m, "AGP_MODE_CONTROL 0x%08x\n", tmp); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + seq_printf(m, "MC_MISC_CNTL 0x%08x\n", tmp); + tmp = RREG32_MC(0x5F); + seq_printf(m, "MC_MISC_UMA_CNTL 0x%08x\n", tmp); + tmp = RREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE); + seq_printf(m, "AGP_ADDRESS_SPACE_SIZE 0x%08x\n", tmp); + tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); + seq_printf(m, "GART_CACHE_CNTRL 0x%08x\n", tmp); + tmp = RREG32_MC(0x3B); + seq_printf(m, "MC_GART_ERROR_ADDRESS 0x%08x\n", tmp); + tmp = RREG32_MC(0x3C); + seq_printf(m, "MC_GART_ERROR_ADDRESS_HI 0x%08x\n", tmp); + tmp = RREG32_MC(0x30); + seq_printf(m, "GART_ERROR_0 0x%08x\n", tmp); + tmp = RREG32_MC(0x31); + seq_printf(m, "GART_ERROR_1 0x%08x\n", tmp); + tmp = RREG32_MC(0x32); + seq_printf(m, "GART_ERROR_2 0x%08x\n", tmp); + tmp = RREG32_MC(0x33); + seq_printf(m, "GART_ERROR_3 0x%08x\n", tmp); + tmp = RREG32_MC(0x34); + seq_printf(m, "GART_ERROR_4 0x%08x\n", tmp); + tmp = RREG32_MC(0x35); + seq_printf(m, "GART_ERROR_5 0x%08x\n", tmp); + tmp = RREG32_MC(0x36); + seq_printf(m, "GART_ERROR_6 0x%08x\n", tmp); + tmp = RREG32_MC(0x37); + seq_printf(m, "GART_ERROR_7 0x%08x\n", tmp); + return 0; +} + +static struct drm_info_list rs400_gart_info_list[] = { + {"rs400_gart_info", rs400_debugfs_gart_info, 0, NULL}, +}; +#endif + +static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1); +#else + return 0; +#endif +} + +static void rs400_mc_program(struct radeon_device *rdev) +{ + struct r100_mc_save save; + + /* Stops all mc clients */ + r100_mc_stop(rdev, &save); + + /* Wait for mc idle */ + if (rs400_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "rs400: Wait MC idle timeout before updating MC.\n"); + WREG32(R_000148_MC_FB_LOCATION, + S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); + + r100_mc_resume(rdev, &save); +} + +static int rs400_startup(struct radeon_device *rdev) +{ + int r; + + r100_set_common_regs(rdev); + + rs400_mc_program(rdev); + /* Resume clock */ + r300_clock_startup(rdev); + /* Initialize GPU configuration (# pipes, ...) */ + rs400_gpu_init(rdev); + r100_enable_bm(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + r = rs400_gart_enable(rdev); + if (r) + return r; + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r100_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int rs400_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + rs400_gart_disable(rdev); + /* Resume clock before doing reset */ + r300_clock_startup(rdev); + /* setup MC before calling post tables */ + rs400_mc_program(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + radeon_combios_asic_init(rdev->ddev); + /* Resume clock after posting */ + r300_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = rs400_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int rs400_suspend(struct radeon_device *rdev) +{ + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); + rs400_gart_disable(rdev); + return 0; +} + +void rs400_fini(struct radeon_device *rdev) +{ + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + rs400_gart_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +int rs400_init(struct radeon_device *rdev) +{ + int r; + + /* Disable VGA */ + r100_vga_render_disable(rdev); + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* TODO: disable VGA need to use VGA request */ + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); + return -EINVAL; + } else { + r = radeon_combios_init(rdev); + if (r) + return r; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize memory controller */ + rs400_mc_init(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + r = rs400_gart_init(rdev); + if (r) + return r; + r300_set_reg_safe(rdev); + + rdev->accel_working = true; + r = rs400_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + rs400_gart_fini(rdev); + radeon_irq_kms_fini(rdev); + rdev->accel_working = false; + } + return 0; +} diff --git a/sys/dev/drm2/radeon/rs400d.h b/sys/dev/drm2/radeon/rs400d.h new file mode 100644 index 00000000000..7a01d202ec4 --- /dev/null +++ b/sys/dev/drm2/radeon/rs400d.h @@ -0,0 +1,163 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RS400D_H__ +#define __RS400D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* Registers */ +#define R_000148_MC_FB_LOCATION 0x000148 +#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000148_MC_FB_START 0xFFFF0000 +#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000148_MC_FB_TOP 0x0000FFFF +#define R_00015C_NB_TOM 0x00015C +#define S_00015C_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_00015C_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_00015C_MC_FB_START 0xFFFF0000 +#define S_00015C_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_00015C_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_00015C_MC_FB_TOP 0x0000FFFF +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/rs600.c b/sys/dev/drm2/radeon/rs600.c new file mode 100644 index 00000000000..6d3b17a495b --- /dev/null +++ b/sys/dev/drm2/radeon/rs600.c @@ -0,0 +1,1042 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +/* RS600 / Radeon X1250/X1270 integrated GPU + * + * This file gather function specific to RS600 which is the IGP of + * the X1250/X1270 family supporting intel CPU (while RS690/RS740 + * is the X1250/X1270 supporting AMD CPU). The display engine are + * the avivo one, bios is an atombios, 3D block are the one of the + * R4XX family. The GART is different from the RS400 one and is very + * close to the one of the R600 family (R600 likely being an evolution + * of the RS600 GART block). + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" +#include "rs600d.h" + +#include "rs600_reg_safe.h" + +static void rs600_gpu_init(struct radeon_device *rdev); + +static const u32 crtc_offsets[2] = +{ + 0, + AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL +}; + +void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + int i; + + if (crtc >= rdev->num_crtc) + return; + + if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)) + break; + DRM_UDELAY(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK) + break; + DRM_UDELAY(1); + } + } +} + +void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) +{ + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); +} + +void rs600_post_page_flip(struct radeon_device *rdev, int crtc) +{ + /* disable the pflip int */ + radeon_irq_kms_pflip_irq_put(rdev, crtc); +} + +u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; + + /* Lock the graphics update lock */ + tmp |= AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* update the scanout addresses */ + WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + /* Wait for update_pending to go high. */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) + break; + DRM_UDELAY(1); + } + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; +} + +void rs600_pm_misc(struct radeon_device *rdev) +{ + int requested_index = rdev->pm.requested_power_state_index; + struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; + struct radeon_voltage *voltage = &ps->clock_info[0].voltage; + u32 tmp, dyn_pwrmgt_sclk_length, dyn_sclk_vol_cntl; + u32 hdp_dyn_cntl, /*mc_host_dyn_cntl,*/ dyn_backbias_cntl; + + if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) { + if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { + tmp = RREG32(voltage->gpio.reg); + if (voltage->active_high) + tmp |= voltage->gpio.mask; + else + tmp &= ~(voltage->gpio.mask); + WREG32(voltage->gpio.reg, tmp); + if (voltage->delay) + DRM_UDELAY(voltage->delay); + } else { + tmp = RREG32(voltage->gpio.reg); + if (voltage->active_high) + tmp &= ~voltage->gpio.mask; + else + tmp |= voltage->gpio.mask; + WREG32(voltage->gpio.reg, tmp); + if (voltage->delay) + DRM_UDELAY(voltage->delay); + } + } else if (voltage->type == VOLTAGE_VDDC) + radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC); + + dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH); + dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf); + dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_LOLEN(0xf); + if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) { + if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) { + dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(2); + dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(2); + } else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) { + dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(4); + dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(4); + } + } else { + dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(1); + dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(1); + } + WREG32_PLL(DYN_PWRMGT_SCLK_LENGTH, dyn_pwrmgt_sclk_length); + + dyn_sclk_vol_cntl = RREG32_PLL(DYN_SCLK_VOL_CNTL); + if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) { + dyn_sclk_vol_cntl |= IO_CG_VOLTAGE_DROP; + if (voltage->delay) { + dyn_sclk_vol_cntl |= VOLTAGE_DROP_SYNC; + dyn_sclk_vol_cntl |= VOLTAGE_DELAY_SEL(voltage->delay); + } else + dyn_sclk_vol_cntl &= ~VOLTAGE_DROP_SYNC; + } else + dyn_sclk_vol_cntl &= ~IO_CG_VOLTAGE_DROP; + WREG32_PLL(DYN_SCLK_VOL_CNTL, dyn_sclk_vol_cntl); + + hdp_dyn_cntl = RREG32_PLL(HDP_DYN_CNTL); + if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN) + hdp_dyn_cntl &= ~HDP_FORCEON; + else + hdp_dyn_cntl |= HDP_FORCEON; + WREG32_PLL(HDP_DYN_CNTL, hdp_dyn_cntl); +#if 0 + /* mc_host_dyn seems to cause hangs from time to time */ + mc_host_dyn_cntl = RREG32_PLL(MC_HOST_DYN_CNTL); + if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN) + mc_host_dyn_cntl &= ~MC_HOST_FORCEON; + else + mc_host_dyn_cntl |= MC_HOST_FORCEON; + WREG32_PLL(MC_HOST_DYN_CNTL, mc_host_dyn_cntl); +#endif + dyn_backbias_cntl = RREG32_PLL(DYN_BACKBIAS_CNTL); + if (ps->misc & ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN) + dyn_backbias_cntl |= IO_CG_BACKBIAS_EN; + else + dyn_backbias_cntl &= ~IO_CG_BACKBIAS_EN; + WREG32_PLL(DYN_BACKBIAS_CNTL, dyn_backbias_cntl); + + /* set pcie lanes */ + if ((rdev->flags & RADEON_IS_PCIE) && + !(rdev->flags & RADEON_IS_IGP) && + rdev->asic->pm.set_pcie_lanes && + (ps->pcie_lanes != + rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) { + radeon_set_pcie_lanes(rdev, + ps->pcie_lanes); + DRM_DEBUG("Setting: p: %d\n", ps->pcie_lanes); + } +} + +void rs600_pm_prepare(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 tmp; + + /* disable any active CRTCs */ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset); + tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp); + } + } +} + +void rs600_pm_finish(struct radeon_device *rdev) +{ + struct drm_device *ddev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 tmp; + + /* enable any active CRTCs */ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp); + } + } +} + +/* hpd for digital panel detect/disconnect */ +bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = false; + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS); + if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp)) + connected = true; + break; + case RADEON_HPD_2: + tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS); + if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp)) + connected = true; + break; + default: + break; + } + return connected; +} + +void rs600_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = rs600_hpd_sense(rdev, hpd); + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); + if (connected) + tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); + else + tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); + WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); + if (connected) + tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); + else + tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + break; + default: + break; + } +} + +void rs600_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned enable = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, + S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); + break; + case RADEON_HPD_2: + WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, + S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); + break; + default: + break; + } + enable |= 1 << radeon_connector->hpd.hpd; + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + } + radeon_irq_kms_enable_hpd(rdev, enable); +} + +void rs600_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + unsigned disable = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, + S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); + break; + case RADEON_HPD_2: + WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, + S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); + break; + default: + break; + } + disable |= 1 << radeon_connector->hpd.hpd; + } + radeon_irq_kms_disable_hpd(rdev, disable); +} + +int rs600_asic_reset(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + u32 status, tmp; + int ret = 0; + + status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(status)) { + return 0; + } + /* Stops all mc clients */ + rv515_mc_stop(rdev, &save); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* stop CP */ + WREG32(RADEON_CP_CSQ_CNTL, 0); + tmp = RREG32(RADEON_CP_RB_CNTL); + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); + WREG32(RADEON_CP_RB_RPTR_WR, 0); + WREG32(RADEON_CP_RB_WPTR, 0); + WREG32(RADEON_CP_RB_CNTL, tmp); + pci_save_state(rdev->dev); + /* disable bus mastering */ + pci_disable_busmaster(rdev->dev); + DRM_MDELAY(1); + /* reset GA+VAP */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | + S_0000F0_SOFT_RESET_GA(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* reset CP */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* reset MC */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + DRM_MDELAY(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + DRM_MDELAY(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* restore PCI & busmastering */ + pci_restore_state(rdev->dev); + /* Check if GPU is idle */ + if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { + dev_err(rdev->dev, "failed to reset GPU\n"); + ret = -1; + } else + dev_info(rdev->dev, "GPU reset succeed\n"); + rv515_mc_resume(rdev, &save); + return ret; +} + +/* + * GART. + */ +void rs600_gart_tlb_flush(struct radeon_device *rdev) +{ + uint32_t tmp; + + tmp = RREG32_MC(R_000100_MC_PT0_CNTL); + tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE; + WREG32_MC(R_000100_MC_PT0_CNTL, tmp); + + tmp = RREG32_MC(R_000100_MC_PT0_CNTL); + tmp |= S_000100_INVALIDATE_ALL_L1_TLBS(1) | S_000100_INVALIDATE_L2_CACHE(1); + WREG32_MC(R_000100_MC_PT0_CNTL, tmp); + + tmp = RREG32_MC(R_000100_MC_PT0_CNTL); + tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE; + WREG32_MC(R_000100_MC_PT0_CNTL, tmp); + tmp = RREG32_MC(R_000100_MC_PT0_CNTL); +} + +static int rs600_gart_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->gart.robj) { + DRM_ERROR("RS600 GART already initialized\n"); + return 0; + } + /* Initialize common gart structure */ + r = radeon_gart_init(rdev); + if (r) { + return r; + } + rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; + return radeon_gart_table_vram_alloc(rdev); +} + +static int rs600_gart_enable(struct radeon_device *rdev) +{ + u32 tmp; + int r, i; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + /* Enable bus master */ + tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); + /* FIXME: setup default page */ + WREG32_MC(R_000100_MC_PT0_CNTL, + (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) | + S_000100_EFFECTIVE_L2_QUEUE_SIZE(6))); + + for (i = 0; i < 19; i++) { + WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i, + S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) | + S_00016C_SYSTEM_ACCESS_MODE_MASK( + V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS) | + S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS( + V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH) | + S_00016C_EFFECTIVE_L1_CACHE_SIZE(3) | + S_00016C_ENABLE_FRAGMENT_PROCESSING(1) | + S_00016C_EFFECTIVE_L1_QUEUE_SIZE(3)); + } + /* enable first context */ + WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL, + S_000102_ENABLE_PAGE_TABLE(1) | + S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT)); + + /* disable all other contexts */ + for (i = 1; i < 8; i++) + WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0); + + /* setup the page table */ + WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, + rdev->gart.table_addr); + WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start); + WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end); + WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); + + /* System context maps to VRAM space */ + WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start); + WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end); + + /* enable page tables */ + tmp = RREG32_MC(R_000100_MC_PT0_CNTL); + WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1))); + tmp = RREG32_MC(R_000009_MC_CNTL1); + WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1))); + rs600_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +static void rs600_gart_disable(struct radeon_device *rdev) +{ + u32 tmp; + + /* FIXME: disable out of gart access */ + WREG32_MC(R_000100_MC_PT0_CNTL, 0); + tmp = RREG32_MC(R_000009_MC_CNTL1); + WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES); + radeon_gart_table_vram_unpin(rdev); +} + +static void rs600_gart_fini(struct radeon_device *rdev) +{ + radeon_gart_fini(rdev); + rs600_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); +} + +#define R600_PTE_VALID (1 << 0) +#define R600_PTE_SYSTEM (1 << 1) +#define R600_PTE_SNOOPED (1 << 2) +#define R600_PTE_READABLE (1 << 5) +#define R600_PTE_WRITEABLE (1 << 6) + +int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +{ + uint64_t *ptr = rdev->gart.ptr; + + if (i < 0 || i > rdev->gart.num_gpu_pages) { + return -EINVAL; + } + addr = addr & 0xFFFFFFFFFFFFF000ULL; + addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED; + addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE; + ptr[i] = addr; + return 0; +} + +int rs600_irq_set(struct radeon_device *rdev) +{ + uint32_t tmp = 0; + uint32_t mode_int = 0; + u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) & + ~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); + u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) & + ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); + u32 hdmi0; + if (ASIC_IS_DCE2(rdev)) + hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) & + ~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); + else + hdmi0 = 0; + + if (!rdev->irq.installed) { + DRM_ERROR("Can't enable IRQ/MSI because no handler is installed\n"); + WREG32(R_000040_GEN_INT_CNTL, 0); + return -EINVAL; + } + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + tmp |= S_000040_SW_INT_EN(1); + } + if (rdev->irq.crtc_vblank_int[0] || + atomic_read(&rdev->irq.pflip[0])) { + mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); + } + if (rdev->irq.crtc_vblank_int[1] || + atomic_read(&rdev->irq.pflip[1])) { + mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); + } + if (rdev->irq.hpd[0]) { + hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); + } + if (rdev->irq.hpd[1]) { + hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); + } + if (rdev->irq.afmt[0]) { + hdmi0 |= S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); + } + WREG32(R_000040_GEN_INT_CNTL, tmp); + WREG32(R_006540_DxMODE_INT_MASK, mode_int); + WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); + if (ASIC_IS_DCE2(rdev)) + WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); + return 0; +} + +static inline u32 rs600_irq_ack(struct radeon_device *rdev) +{ + uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); + uint32_t irq_mask = S_000044_SW_INT(1); + u32 tmp; + + if (G_000044_DISPLAY_INT_STAT(irqs)) { + rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); + if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + WREG32(R_006534_D1MODE_VBLANK_STATUS, + S_006534_D1MODE_VBLANK_ACK(1)); + } + if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + WREG32(R_006D34_D2MODE_VBLANK_STATUS, + S_006D34_D2MODE_VBLANK_ACK(1)); + } + if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); + tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1); + WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); + } + if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); + tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1); + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); + } + } else { + rdev->irq.stat_regs.r500.disp_int = 0; + } + + if (ASIC_IS_DCE2(rdev)) { + rdev->irq.stat_regs.r500.hdmi0_status = RREG32(R_007404_HDMI0_STATUS) & + S_007404_HDMI0_AZ_FORMAT_WTRIG(1); + if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) { + tmp = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL); + tmp |= S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(1); + WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, tmp); + } + } else + rdev->irq.stat_regs.r500.hdmi0_status = 0; + + if (irqs) { + WREG32(R_000044_GEN_INT_STATUS, irqs); + } + return irqs & irq_mask; +} + +void rs600_irq_disable(struct radeon_device *rdev) +{ + u32 hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) & + ~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); + WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); + WREG32(R_000040_GEN_INT_CNTL, 0); + WREG32(R_006540_DxMODE_INT_MASK, 0); + /* Wait and acknowledge irq */ + DRM_MDELAY(1); + rs600_irq_ack(rdev); +} + +irqreturn_t rs600_irq_process(struct radeon_device *rdev) +{ + u32 status, msi_rearm; + bool queue_hotplug = false; + bool queue_hdmi = false; + + status = rs600_irq_ack(rdev); + if (!status && + !rdev->irq.stat_regs.r500.disp_int && + !rdev->irq.stat_regs.r500.hdmi0_status) { + return IRQ_NONE; + } + while (status || + rdev->irq.stat_regs.r500.disp_int || + rdev->irq.stat_regs.r500.hdmi0_status) { + /* SW interrupt */ + if (G_000044_SW_INT(status)) { + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + } + /* Vertical blank interrupts */ + if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_flip(rdev, 0); + } + if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_flip(rdev, 1); + } + if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + queue_hotplug = true; + DRM_DEBUG("HPD1\n"); + } + if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + queue_hotplug = true; + DRM_DEBUG("HPD2\n"); + } + if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) { + queue_hdmi = true; + DRM_DEBUG("HDMI0\n"); + } + status = rs600_irq_ack(rdev); + } + if (queue_hotplug) + taskqueue_enqueue(rdev->tq, &rdev->hotplug_work); + if (queue_hdmi) + taskqueue_enqueue(rdev->tq, &rdev->audio_work); + if (rdev->msi_enabled) { + switch (rdev->family) { + case CHIP_RS600: + case CHIP_RS690: + case CHIP_RS740: + msi_rearm = RREG32(RADEON_BUS_CNTL) & ~RS600_MSI_REARM; + WREG32(RADEON_BUS_CNTL, msi_rearm); + WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM); + break; + default: + WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); + break; + } + } + return IRQ_HANDLED; +} + +u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc) +{ + if (crtc == 0) + return RREG32(R_0060A4_D1CRTC_STATUS_FRAME_COUNT); + else + return RREG32(R_0068A4_D2CRTC_STATUS_FRAME_COUNT); +} + +int rs600_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + + for (i = 0; i < rdev->usec_timeout; i++) { + if (G_000000_MC_IDLE(RREG32_MC(R_000000_MC_STATUS))) + return 0; + DRM_UDELAY(1); + } + return -1; +} + +static void rs600_gpu_init(struct radeon_device *rdev) +{ + r420_pipes_init(rdev); + /* Wait for mc idle */ + if (rs600_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); +} + +static void rs600_mc_init(struct radeon_device *rdev) +{ + u64 base; + + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.vram_is_ddr = true; + rdev->mc.vram_width = 128; + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + base = RREG32_MC(R_000004_MC_FB_LOCATION); + base = G_000004_MC_FB_START(base) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = 0; + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + +void rs600_bandwidth_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt; + /* FIXME: implement full support */ + + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + + rs690_line_buffer_adjust(rdev, mode0, mode1); + + if (rdev->disp_priority == 2) { + d1mode_priority_a_cnt = RREG32(R_006548_D1MODE_PRIORITY_A_CNT); + d2mode_priority_a_cnt = RREG32(R_006D48_D2MODE_PRIORITY_A_CNT); + d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); + d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); + WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); + WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); + WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); + WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); + } +} + +uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg) +{ + WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) | + S_000070_MC_IND_CITF_ARB0(1)); + return RREG32(R_000074_MC_IND_DATA); +} + +void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) | + S_000070_MC_IND_CITF_ARB0(1) | S_000070_MC_IND_WR_EN(1)); + WREG32(R_000074_MC_IND_DATA, v); +} + +static void rs600_debugfs(struct radeon_device *rdev) +{ + if (r100_debugfs_rbbm_init(rdev)) + DRM_ERROR("Failed to register debugfs file for RBBM !\n"); +} + +void rs600_set_safe_registers(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(rs600_reg_safe_bm); +} + +static void rs600_mc_program(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + + /* Stops all mc clients */ + rv515_mc_stop(rdev, &save); + + /* Wait for mc idle */ + if (rs600_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); + + /* FIXME: What does AGP means for such chipset ? */ + WREG32_MC(R_000005_MC_AGP_LOCATION, 0x0FFFFFFF); + WREG32_MC(R_000006_AGP_BASE, 0); + WREG32_MC(R_000007_AGP_BASE_2, 0); + /* Program MC */ + WREG32_MC(R_000004_MC_FB_LOCATION, + S_000004_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16)); + WREG32(R_000134_HDP_FB_LOCATION, + S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); + + rv515_mc_resume(rdev, &save); +} + +static int rs600_startup(struct radeon_device *rdev) +{ + int r; + + rs600_mc_program(rdev); + /* Resume clock */ + rv515_clock_startup(rdev); + /* Initialize GPU configuration (# pipes, ...) */ + rs600_gpu_init(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + r = rs600_gart_enable(rdev); + if (r) + return r; + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + + return 0; +} + +int rs600_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + rs600_gart_disable(rdev); + /* Resume clock before doing reset */ + rv515_clock_startup(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + atom_asic_init(rdev->mode_info.atom_context); + /* Resume clock after posting */ + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = rs600_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int rs600_suspend(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + rs600_irq_disable(rdev); + rs600_gart_disable(rdev); + return 0; +} + +void rs600_fini(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + rs600_gart_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +int rs600_init(struct radeon_device *rdev) +{ + int r; + + /* Disable VGA */ + rv515_vga_render_disable(rdev); + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) + return r; + } else { + dev_err(rdev->dev, "Expecting atombios for RS600 GPU\n"); + return -EINVAL; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize memory controller */ + rs600_mc_init(rdev); + rs600_debugfs(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + r = rs600_gart_init(rdev); + if (r) + return r; + rs600_set_safe_registers(rdev); + + rdev->accel_working = true; + r = rs600_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + rs600_gart_fini(rdev); + radeon_irq_kms_fini(rdev); + rdev->accel_working = false; + } + return 0; +} diff --git a/sys/dev/drm2/radeon/rs600_reg_safe.h b/sys/dev/drm2/radeon/rs600_reg_safe.h new file mode 100644 index 00000000000..07913c90e17 --- /dev/null +++ b/sys/dev/drm2/radeon/rs600_reg_safe.h @@ -0,0 +1,60 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned rs600_reg_safe_bm[219] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, + 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFC48, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, + 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE00BFF, + 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFF800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0003FC0B, 0xFFFFFCFF, 0xFFBFFB99, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +}; diff --git a/sys/dev/drm2/radeon/rs600d.h b/sys/dev/drm2/radeon/rs600d.h new file mode 100644 index 00000000000..f7a5b716f39 --- /dev/null +++ b/sys/dev/drm2/radeon/rs600d.h @@ -0,0 +1,688 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RS600D_H__ +#define __RS600D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* Registers */ +#define R_000040_GEN_INT_CNTL 0x000040 +#define S_000040_SCRATCH_INT_MASK(x) (((x) & 0x1) << 18) +#define G_000040_SCRATCH_INT_MASK(x) (((x) >> 18) & 0x1) +#define C_000040_SCRATCH_INT_MASK 0xFFFBFFFF +#define S_000040_GUI_IDLE_MASK(x) (((x) & 0x1) << 19) +#define G_000040_GUI_IDLE_MASK(x) (((x) >> 19) & 0x1) +#define C_000040_GUI_IDLE_MASK 0xFFF7FFFF +#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13) +#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1) +#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF +#define S_000040_DMA_VIPH2_INT_EN(x) (((x) & 0x1) << 14) +#define G_000040_DMA_VIPH2_INT_EN(x) (((x) >> 14) & 0x1) +#define C_000040_DMA_VIPH2_INT_EN 0xFFFFBFFF +#define S_000040_DMA_VIPH3_INT_EN(x) (((x) & 0x1) << 15) +#define G_000040_DMA_VIPH3_INT_EN(x) (((x) >> 15) & 0x1) +#define C_000040_DMA_VIPH3_INT_EN 0xFFFF7FFF +#define S_000040_I2C_INT_EN(x) (((x) & 0x1) << 17) +#define G_000040_I2C_INT_EN(x) (((x) >> 17) & 0x1) +#define C_000040_I2C_INT_EN 0xFFFDFFFF +#define S_000040_GUI_IDLE(x) (((x) & 0x1) << 19) +#define G_000040_GUI_IDLE(x) (((x) >> 19) & 0x1) +#define C_000040_GUI_IDLE 0xFFF7FFFF +#define S_000040_VIPH_INT_EN(x) (((x) & 0x1) << 24) +#define G_000040_VIPH_INT_EN(x) (((x) >> 24) & 0x1) +#define C_000040_VIPH_INT_EN 0xFEFFFFFF +#define S_000040_SW_INT_EN(x) (((x) & 0x1) << 25) +#define G_000040_SW_INT_EN(x) (((x) >> 25) & 0x1) +#define C_000040_SW_INT_EN 0xFDFFFFFF +#define S_000040_GEYSERVILLE(x) (((x) & 0x1) << 27) +#define G_000040_GEYSERVILLE(x) (((x) >> 27) & 0x1) +#define C_000040_GEYSERVILLE 0xF7FFFFFF +#define S_000040_HDCP_AUTHORIZED_INT(x) (((x) & 0x1) << 28) +#define G_000040_HDCP_AUTHORIZED_INT(x) (((x) >> 28) & 0x1) +#define C_000040_HDCP_AUTHORIZED_INT 0xEFFFFFFF +#define S_000040_DVI_I2C_INT(x) (((x) & 0x1) << 29) +#define G_000040_DVI_I2C_INT(x) (((x) >> 29) & 0x1) +#define C_000040_DVI_I2C_INT 0xDFFFFFFF +#define S_000040_GUIDMA(x) (((x) & 0x1) << 30) +#define G_000040_GUIDMA(x) (((x) >> 30) & 0x1) +#define C_000040_GUIDMA 0xBFFFFFFF +#define S_000040_VIDDMA(x) (((x) & 0x1) << 31) +#define G_000040_VIDDMA(x) (((x) >> 31) & 0x1) +#define C_000040_VIDDMA 0x7FFFFFFF +#define R_000044_GEN_INT_STATUS 0x000044 +#define S_000044_DISPLAY_INT_STAT(x) (((x) & 0x1) << 0) +#define G_000044_DISPLAY_INT_STAT(x) (((x) >> 0) & 0x1) +#define C_000044_DISPLAY_INT_STAT 0xFFFFFFFE +#define S_000044_VGA_INT_STAT(x) (((x) & 0x1) << 1) +#define G_000044_VGA_INT_STAT(x) (((x) >> 1) & 0x1) +#define C_000044_VGA_INT_STAT 0xFFFFFFFD +#define S_000044_CAP0_INT_ACTIVE(x) (((x) & 0x1) << 8) +#define G_000044_CAP0_INT_ACTIVE(x) (((x) >> 8) & 0x1) +#define C_000044_CAP0_INT_ACTIVE 0xFFFFFEFF +#define S_000044_DMA_VIPH0_INT(x) (((x) & 0x1) << 12) +#define G_000044_DMA_VIPH0_INT(x) (((x) >> 12) & 0x1) +#define C_000044_DMA_VIPH0_INT 0xFFFFEFFF +#define S_000044_DMA_VIPH1_INT(x) (((x) & 0x1) << 13) +#define G_000044_DMA_VIPH1_INT(x) (((x) >> 13) & 0x1) +#define C_000044_DMA_VIPH1_INT 0xFFFFDFFF +#define S_000044_DMA_VIPH2_INT(x) (((x) & 0x1) << 14) +#define G_000044_DMA_VIPH2_INT(x) (((x) >> 14) & 0x1) +#define C_000044_DMA_VIPH2_INT 0xFFFFBFFF +#define S_000044_DMA_VIPH3_INT(x) (((x) & 0x1) << 15) +#define G_000044_DMA_VIPH3_INT(x) (((x) >> 15) & 0x1) +#define C_000044_DMA_VIPH3_INT 0xFFFF7FFF +#define S_000044_MC_PROBE_FAULT_STAT(x) (((x) & 0x1) << 16) +#define G_000044_MC_PROBE_FAULT_STAT(x) (((x) >> 16) & 0x1) +#define C_000044_MC_PROBE_FAULT_STAT 0xFFFEFFFF +#define S_000044_I2C_INT(x) (((x) & 0x1) << 17) +#define G_000044_I2C_INT(x) (((x) >> 17) & 0x1) +#define C_000044_I2C_INT 0xFFFDFFFF +#define S_000044_SCRATCH_INT_STAT(x) (((x) & 0x1) << 18) +#define G_000044_SCRATCH_INT_STAT(x) (((x) >> 18) & 0x1) +#define C_000044_SCRATCH_INT_STAT 0xFFFBFFFF +#define S_000044_GUI_IDLE_STAT(x) (((x) & 0x1) << 19) +#define G_000044_GUI_IDLE_STAT(x) (((x) >> 19) & 0x1) +#define C_000044_GUI_IDLE_STAT 0xFFF7FFFF +#define S_000044_ATI_OVERDRIVE_INT_STAT(x) (((x) & 0x1) << 20) +#define G_000044_ATI_OVERDRIVE_INT_STAT(x) (((x) >> 20) & 0x1) +#define C_000044_ATI_OVERDRIVE_INT_STAT 0xFFEFFFFF +#define S_000044_MC_PROTECTION_FAULT_STAT(x) (((x) & 0x1) << 21) +#define G_000044_MC_PROTECTION_FAULT_STAT(x) (((x) >> 21) & 0x1) +#define C_000044_MC_PROTECTION_FAULT_STAT 0xFFDFFFFF +#define S_000044_RBBM_READ_INT_STAT(x) (((x) & 0x1) << 22) +#define G_000044_RBBM_READ_INT_STAT(x) (((x) >> 22) & 0x1) +#define C_000044_RBBM_READ_INT_STAT 0xFFBFFFFF +#define S_000044_CB_CONTEXT_SWITCH_STAT(x) (((x) & 0x1) << 23) +#define G_000044_CB_CONTEXT_SWITCH_STAT(x) (((x) >> 23) & 0x1) +#define C_000044_CB_CONTEXT_SWITCH_STAT 0xFF7FFFFF +#define S_000044_VIPH_INT(x) (((x) & 0x1) << 24) +#define G_000044_VIPH_INT(x) (((x) >> 24) & 0x1) +#define C_000044_VIPH_INT 0xFEFFFFFF +#define S_000044_SW_INT(x) (((x) & 0x1) << 25) +#define G_000044_SW_INT(x) (((x) >> 25) & 0x1) +#define C_000044_SW_INT 0xFDFFFFFF +#define S_000044_SW_INT_SET(x) (((x) & 0x1) << 26) +#define G_000044_SW_INT_SET(x) (((x) >> 26) & 0x1) +#define C_000044_SW_INT_SET 0xFBFFFFFF +#define S_000044_IDCT_INT_STAT(x) (((x) & 0x1) << 27) +#define G_000044_IDCT_INT_STAT(x) (((x) >> 27) & 0x1) +#define C_000044_IDCT_INT_STAT 0xF7FFFFFF +#define S_000044_GUIDMA_STAT(x) (((x) & 0x1) << 30) +#define G_000044_GUIDMA_STAT(x) (((x) >> 30) & 0x1) +#define C_000044_GUIDMA_STAT 0xBFFFFFFF +#define S_000044_VIDDMA_STAT(x) (((x) & 0x1) << 31) +#define G_000044_VIDDMA_STAT(x) (((x) >> 31) & 0x1) +#define C_000044_VIDDMA_STAT 0x7FFFFFFF +#define R_00004C_BUS_CNTL 0x00004C +#define S_00004C_BUS_MASTER_DIS(x) (((x) & 0x1) << 14) +#define G_00004C_BUS_MASTER_DIS(x) (((x) >> 14) & 0x1) +#define C_00004C_BUS_MASTER_DIS 0xFFFFBFFF +#define S_00004C_BUS_MSI_REARM(x) (((x) & 0x1) << 20) +#define G_00004C_BUS_MSI_REARM(x) (((x) >> 20) & 0x1) +#define C_00004C_BUS_MSI_REARM 0xFFEFFFFF +#define R_000070_MC_IND_INDEX 0x000070 +#define S_000070_MC_IND_ADDR(x) (((x) & 0xFFFF) << 0) +#define G_000070_MC_IND_ADDR(x) (((x) >> 0) & 0xFFFF) +#define C_000070_MC_IND_ADDR 0xFFFF0000 +#define S_000070_MC_IND_SEQ_RBS_0(x) (((x) & 0x1) << 16) +#define G_000070_MC_IND_SEQ_RBS_0(x) (((x) >> 16) & 0x1) +#define C_000070_MC_IND_SEQ_RBS_0 0xFFFEFFFF +#define S_000070_MC_IND_SEQ_RBS_1(x) (((x) & 0x1) << 17) +#define G_000070_MC_IND_SEQ_RBS_1(x) (((x) >> 17) & 0x1) +#define C_000070_MC_IND_SEQ_RBS_1 0xFFFDFFFF +#define S_000070_MC_IND_SEQ_RBS_2(x) (((x) & 0x1) << 18) +#define G_000070_MC_IND_SEQ_RBS_2(x) (((x) >> 18) & 0x1) +#define C_000070_MC_IND_SEQ_RBS_2 0xFFFBFFFF +#define S_000070_MC_IND_SEQ_RBS_3(x) (((x) & 0x1) << 19) +#define G_000070_MC_IND_SEQ_RBS_3(x) (((x) >> 19) & 0x1) +#define C_000070_MC_IND_SEQ_RBS_3 0xFFF7FFFF +#define S_000070_MC_IND_AIC_RBS(x) (((x) & 0x1) << 20) +#define G_000070_MC_IND_AIC_RBS(x) (((x) >> 20) & 0x1) +#define C_000070_MC_IND_AIC_RBS 0xFFEFFFFF +#define S_000070_MC_IND_CITF_ARB0(x) (((x) & 0x1) << 21) +#define G_000070_MC_IND_CITF_ARB0(x) (((x) >> 21) & 0x1) +#define C_000070_MC_IND_CITF_ARB0 0xFFDFFFFF +#define S_000070_MC_IND_CITF_ARB1(x) (((x) & 0x1) << 22) +#define G_000070_MC_IND_CITF_ARB1(x) (((x) >> 22) & 0x1) +#define C_000070_MC_IND_CITF_ARB1 0xFFBFFFFF +#define S_000070_MC_IND_WR_EN(x) (((x) & 0x1) << 23) +#define G_000070_MC_IND_WR_EN(x) (((x) >> 23) & 0x1) +#define C_000070_MC_IND_WR_EN 0xFF7FFFFF +#define S_000070_MC_IND_RD_INV(x) (((x) & 0x1) << 24) +#define G_000070_MC_IND_RD_INV(x) (((x) >> 24) & 0x1) +#define C_000070_MC_IND_RD_INV 0xFEFFFFFF +#define R_000074_MC_IND_DATA 0x000074 +#define S_000074_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000074_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000074_MC_IND_DATA 0x00000000 +#define R_0000F0_RBBM_SOFT_RESET 0x0000F0 +#define S_0000F0_SOFT_RESET_CP(x) (((x) & 0x1) << 0) +#define G_0000F0_SOFT_RESET_CP(x) (((x) >> 0) & 0x1) +#define C_0000F0_SOFT_RESET_CP 0xFFFFFFFE +#define S_0000F0_SOFT_RESET_HI(x) (((x) & 0x1) << 1) +#define G_0000F0_SOFT_RESET_HI(x) (((x) >> 1) & 0x1) +#define C_0000F0_SOFT_RESET_HI 0xFFFFFFFD +#define S_0000F0_SOFT_RESET_VAP(x) (((x) & 0x1) << 2) +#define G_0000F0_SOFT_RESET_VAP(x) (((x) >> 2) & 0x1) +#define C_0000F0_SOFT_RESET_VAP 0xFFFFFFFB +#define S_0000F0_SOFT_RESET_RE(x) (((x) & 0x1) << 3) +#define G_0000F0_SOFT_RESET_RE(x) (((x) >> 3) & 0x1) +#define C_0000F0_SOFT_RESET_RE 0xFFFFFFF7 +#define S_0000F0_SOFT_RESET_PP(x) (((x) & 0x1) << 4) +#define G_0000F0_SOFT_RESET_PP(x) (((x) >> 4) & 0x1) +#define C_0000F0_SOFT_RESET_PP 0xFFFFFFEF +#define S_0000F0_SOFT_RESET_E2(x) (((x) & 0x1) << 5) +#define G_0000F0_SOFT_RESET_E2(x) (((x) >> 5) & 0x1) +#define C_0000F0_SOFT_RESET_E2 0xFFFFFFDF +#define S_0000F0_SOFT_RESET_RB(x) (((x) & 0x1) << 6) +#define G_0000F0_SOFT_RESET_RB(x) (((x) >> 6) & 0x1) +#define C_0000F0_SOFT_RESET_RB 0xFFFFFFBF +#define S_0000F0_SOFT_RESET_HDP(x) (((x) & 0x1) << 7) +#define G_0000F0_SOFT_RESET_HDP(x) (((x) >> 7) & 0x1) +#define C_0000F0_SOFT_RESET_HDP 0xFFFFFF7F +#define S_0000F0_SOFT_RESET_MC(x) (((x) & 0x1) << 8) +#define G_0000F0_SOFT_RESET_MC(x) (((x) >> 8) & 0x1) +#define C_0000F0_SOFT_RESET_MC 0xFFFFFEFF +#define S_0000F0_SOFT_RESET_AIC(x) (((x) & 0x1) << 9) +#define G_0000F0_SOFT_RESET_AIC(x) (((x) >> 9) & 0x1) +#define C_0000F0_SOFT_RESET_AIC 0xFFFFFDFF +#define S_0000F0_SOFT_RESET_VIP(x) (((x) & 0x1) << 10) +#define G_0000F0_SOFT_RESET_VIP(x) (((x) >> 10) & 0x1) +#define C_0000F0_SOFT_RESET_VIP 0xFFFFFBFF +#define S_0000F0_SOFT_RESET_DISP(x) (((x) & 0x1) << 11) +#define G_0000F0_SOFT_RESET_DISP(x) (((x) >> 11) & 0x1) +#define C_0000F0_SOFT_RESET_DISP 0xFFFFF7FF +#define S_0000F0_SOFT_RESET_CG(x) (((x) & 0x1) << 12) +#define G_0000F0_SOFT_RESET_CG(x) (((x) >> 12) & 0x1) +#define C_0000F0_SOFT_RESET_CG 0xFFFFEFFF +#define S_0000F0_SOFT_RESET_GA(x) (((x) & 0x1) << 13) +#define G_0000F0_SOFT_RESET_GA(x) (((x) >> 13) & 0x1) +#define C_0000F0_SOFT_RESET_GA 0xFFFFDFFF +#define S_0000F0_SOFT_RESET_IDCT(x) (((x) & 0x1) << 14) +#define G_0000F0_SOFT_RESET_IDCT(x) (((x) >> 14) & 0x1) +#define C_0000F0_SOFT_RESET_IDCT 0xFFFFBFFF +#define R_000134_HDP_FB_LOCATION 0x000134 +#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000134_HDP_FB_START 0xFFFF0000 +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF +#define R_0060A4_D1CRTC_STATUS_FRAME_COUNT 0x0060A4 +#define S_0060A4_D1CRTC_FRAME_COUNT(x) (((x) & 0xFFFFFF) << 0) +#define G_0060A4_D1CRTC_FRAME_COUNT(x) (((x) >> 0) & 0xFFFFFF) +#define C_0060A4_D1CRTC_FRAME_COUNT 0xFF000000 +#define R_006534_D1MODE_VBLANK_STATUS 0x006534 +#define S_006534_D1MODE_VBLANK_OCCURRED(x) (((x) & 0x1) << 0) +#define G_006534_D1MODE_VBLANK_OCCURRED(x) (((x) >> 0) & 0x1) +#define C_006534_D1MODE_VBLANK_OCCURRED 0xFFFFFFFE +#define S_006534_D1MODE_VBLANK_ACK(x) (((x) & 0x1) << 4) +#define G_006534_D1MODE_VBLANK_ACK(x) (((x) >> 4) & 0x1) +#define C_006534_D1MODE_VBLANK_ACK 0xFFFFFFEF +#define S_006534_D1MODE_VBLANK_STAT(x) (((x) & 0x1) << 12) +#define G_006534_D1MODE_VBLANK_STAT(x) (((x) >> 12) & 0x1) +#define C_006534_D1MODE_VBLANK_STAT 0xFFFFEFFF +#define S_006534_D1MODE_VBLANK_INTERRUPT(x) (((x) & 0x1) << 16) +#define G_006534_D1MODE_VBLANK_INTERRUPT(x) (((x) >> 16) & 0x1) +#define C_006534_D1MODE_VBLANK_INTERRUPT 0xFFFEFFFF +#define R_006540_DxMODE_INT_MASK 0x006540 +#define S_006540_D1MODE_VBLANK_INT_MASK(x) (((x) & 0x1) << 0) +#define G_006540_D1MODE_VBLANK_INT_MASK(x) (((x) >> 0) & 0x1) +#define C_006540_D1MODE_VBLANK_INT_MASK 0xFFFFFFFE +#define S_006540_D1MODE_VLINE_INT_MASK(x) (((x) & 0x1) << 4) +#define G_006540_D1MODE_VLINE_INT_MASK(x) (((x) >> 4) & 0x1) +#define C_006540_D1MODE_VLINE_INT_MASK 0xFFFFFFEF +#define S_006540_D2MODE_VBLANK_INT_MASK(x) (((x) & 0x1) << 8) +#define G_006540_D2MODE_VBLANK_INT_MASK(x) (((x) >> 8) & 0x1) +#define C_006540_D2MODE_VBLANK_INT_MASK 0xFFFFFEFF +#define S_006540_D2MODE_VLINE_INT_MASK(x) (((x) & 0x1) << 12) +#define G_006540_D2MODE_VLINE_INT_MASK(x) (((x) >> 12) & 0x1) +#define C_006540_D2MODE_VLINE_INT_MASK 0xFFFFEFFF +#define S_006540_D1MODE_VBLANK_CP_SEL(x) (((x) & 0x1) << 30) +#define G_006540_D1MODE_VBLANK_CP_SEL(x) (((x) >> 30) & 0x1) +#define C_006540_D1MODE_VBLANK_CP_SEL 0xBFFFFFFF +#define S_006540_D2MODE_VBLANK_CP_SEL(x) (((x) & 0x1) << 31) +#define G_006540_D2MODE_VBLANK_CP_SEL(x) (((x) >> 31) & 0x1) +#define C_006540_D2MODE_VBLANK_CP_SEL 0x7FFFFFFF +#define R_0068A4_D2CRTC_STATUS_FRAME_COUNT 0x0068A4 +#define S_0068A4_D2CRTC_FRAME_COUNT(x) (((x) & 0xFFFFFF) << 0) +#define G_0068A4_D2CRTC_FRAME_COUNT(x) (((x) >> 0) & 0xFFFFFF) +#define C_0068A4_D2CRTC_FRAME_COUNT 0xFF000000 +#define R_006D34_D2MODE_VBLANK_STATUS 0x006D34 +#define S_006D34_D2MODE_VBLANK_OCCURRED(x) (((x) & 0x1) << 0) +#define G_006D34_D2MODE_VBLANK_OCCURRED(x) (((x) >> 0) & 0x1) +#define C_006D34_D2MODE_VBLANK_OCCURRED 0xFFFFFFFE +#define S_006D34_D2MODE_VBLANK_ACK(x) (((x) & 0x1) << 4) +#define G_006D34_D2MODE_VBLANK_ACK(x) (((x) >> 4) & 0x1) +#define C_006D34_D2MODE_VBLANK_ACK 0xFFFFFFEF +#define S_006D34_D2MODE_VBLANK_STAT(x) (((x) & 0x1) << 12) +#define G_006D34_D2MODE_VBLANK_STAT(x) (((x) >> 12) & 0x1) +#define C_006D34_D2MODE_VBLANK_STAT 0xFFFFEFFF +#define S_006D34_D2MODE_VBLANK_INTERRUPT(x) (((x) & 0x1) << 16) +#define G_006D34_D2MODE_VBLANK_INTERRUPT(x) (((x) >> 16) & 0x1) +#define C_006D34_D2MODE_VBLANK_INTERRUPT 0xFFFEFFFF +#define R_007EDC_DISP_INTERRUPT_STATUS 0x007EDC +#define S_007EDC_LB_D1_VBLANK_INTERRUPT(x) (((x) & 0x1) << 4) +#define G_007EDC_LB_D1_VBLANK_INTERRUPT(x) (((x) >> 4) & 0x1) +#define C_007EDC_LB_D1_VBLANK_INTERRUPT 0xFFFFFFEF +#define S_007EDC_LB_D2_VBLANK_INTERRUPT(x) (((x) & 0x1) << 5) +#define G_007EDC_LB_D2_VBLANK_INTERRUPT(x) (((x) >> 5) & 0x1) +#define C_007EDC_LB_D2_VBLANK_INTERRUPT 0xFFFFFFDF +#define S_007EDC_DACA_AUTODETECT_INTERRUPT(x) (((x) & 0x1) << 16) +#define G_007EDC_DACA_AUTODETECT_INTERRUPT(x) (((x) >> 16) & 0x1) +#define C_007EDC_DACA_AUTODETECT_INTERRUPT 0xFFFEFFFF +#define S_007EDC_DACB_AUTODETECT_INTERRUPT(x) (((x) & 0x1) << 17) +#define G_007EDC_DACB_AUTODETECT_INTERRUPT(x) (((x) >> 17) & 0x1) +#define C_007EDC_DACB_AUTODETECT_INTERRUPT 0xFFFDFFFF +#define S_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x) (((x) & 0x1) << 18) +#define G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x) (((x) >> 18) & 0x1) +#define C_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT 0xFFFBFFFF +#define S_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x) (((x) & 0x1) << 19) +#define G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x) (((x) >> 19) & 0x1) +#define C_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT 0xFFF7FFFF +#define R_007828_DACA_AUTODETECT_CONTROL 0x007828 +#define S_007828_DACA_AUTODETECT_MODE(x) (((x) & 0x3) << 0) +#define G_007828_DACA_AUTODETECT_MODE(x) (((x) >> 0) & 0x3) +#define C_007828_DACA_AUTODETECT_MODE 0xFFFFFFFC +#define S_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8) +#define G_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff) +#define C_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER 0xFFFF00FF +#define S_007828_DACA_AUTODETECT_CHECK_MASK(x) (((x) & 0x3) << 16) +#define G_007828_DACA_AUTODETECT_CHECK_MASK(x) (((x) >> 16) & 0x3) +#define C_007828_DACA_AUTODETECT_CHECK_MASK 0xFFFCFFFF +#define R_007838_DACA_AUTODETECT_INT_CONTROL 0x007838 +#define S_007838_DACA_AUTODETECT_ACK(x) (((x) & 0x1) << 0) +#define C_007838_DACA_DACA_AUTODETECT_ACK 0xFFFFFFFE +#define S_007838_DACA_AUTODETECT_INT_ENABLE(x) (((x) & 0x1) << 16) +#define G_007838_DACA_AUTODETECT_INT_ENABLE(x) (((x) >> 16) & 0x1) +#define C_007838_DACA_AUTODETECT_INT_ENABLE 0xFFFCFFFF +#define R_007A28_DACB_AUTODETECT_CONTROL 0x007A28 +#define S_007A28_DACB_AUTODETECT_MODE(x) (((x) & 0x3) << 0) +#define G_007A28_DACB_AUTODETECT_MODE(x) (((x) >> 0) & 0x3) +#define C_007A28_DACB_AUTODETECT_MODE 0xFFFFFFFC +#define S_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8) +#define G_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff) +#define C_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER 0xFFFF00FF +#define S_007A28_DACB_AUTODETECT_CHECK_MASK(x) (((x) & 0x3) << 16) +#define G_007A28_DACB_AUTODETECT_CHECK_MASK(x) (((x) >> 16) & 0x3) +#define C_007A28_DACB_AUTODETECT_CHECK_MASK 0xFFFCFFFF +#define R_007A38_DACB_AUTODETECT_INT_CONTROL 0x007A38 +#define S_007A38_DACB_AUTODETECT_ACK(x) (((x) & 0x1) << 0) +#define C_007A38_DACB_DACA_AUTODETECT_ACK 0xFFFFFFFE +#define S_007A38_DACB_AUTODETECT_INT_ENABLE(x) (((x) & 0x1) << 16) +#define G_007A38_DACB_AUTODETECT_INT_ENABLE(x) (((x) >> 16) & 0x1) +#define C_007A38_DACB_AUTODETECT_INT_ENABLE 0xFFFCFFFF +#define R_007D00_DC_HOT_PLUG_DETECT1_CONTROL 0x007D00 +#define S_007D00_DC_HOT_PLUG_DETECT1_EN(x) (((x) & 0x1) << 0) +#define G_007D00_DC_HOT_PLUG_DETECT1_EN(x) (((x) >> 0) & 0x1) +#define C_007D00_DC_HOT_PLUG_DETECT1_EN 0xFFFFFFFE +#define R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS 0x007D04 +#define S_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x) (((x) & 0x1) << 0) +#define G_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x) (((x) >> 0) & 0x1) +#define C_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS 0xFFFFFFFE +#define S_007D04_DC_HOT_PLUG_DETECT1_SENSE(x) (((x) & 0x1) << 1) +#define G_007D04_DC_HOT_PLUG_DETECT1_SENSE(x) (((x) >> 1) & 0x1) +#define C_007D04_DC_HOT_PLUG_DETECT1_SENSE 0xFFFFFFFD +#define R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL 0x007D08 +#define S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(x) (((x) & 0x1) << 0) +#define C_007D08_DC_HOT_PLUG_DETECT1_INT_ACK 0xFFFFFFFE +#define S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) & 0x1) << 8) +#define G_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) >> 8) & 0x1) +#define C_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY 0xFFFFFEFF +#define S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x) (((x) & 0x1) << 16) +#define G_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x) (((x) >> 16) & 0x1) +#define C_007D08_DC_HOT_PLUG_DETECT1_INT_EN 0xFFFEFFFF +#define R_007D10_DC_HOT_PLUG_DETECT2_CONTROL 0x007D10 +#define S_007D10_DC_HOT_PLUG_DETECT2_EN(x) (((x) & 0x1) << 0) +#define G_007D10_DC_HOT_PLUG_DETECT2_EN(x) (((x) >> 0) & 0x1) +#define C_007D10_DC_HOT_PLUG_DETECT2_EN 0xFFFFFFFE +#define R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS 0x007D14 +#define S_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x) (((x) & 0x1) << 0) +#define G_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x) (((x) >> 0) & 0x1) +#define C_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS 0xFFFFFFFE +#define S_007D14_DC_HOT_PLUG_DETECT2_SENSE(x) (((x) & 0x1) << 1) +#define G_007D14_DC_HOT_PLUG_DETECT2_SENSE(x) (((x) >> 1) & 0x1) +#define C_007D14_DC_HOT_PLUG_DETECT2_SENSE 0xFFFFFFFD +#define R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL 0x007D18 +#define S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(x) (((x) & 0x1) << 0) +#define C_007D18_DC_HOT_PLUG_DETECT2_INT_ACK 0xFFFFFFFE +#define S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) & 0x1) << 8) +#define G_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) >> 8) & 0x1) +#define C_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY 0xFFFFFEFF +#define S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x) (((x) & 0x1) << 16) +#define G_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x) (((x) >> 16) & 0x1) +#define C_007D18_DC_HOT_PLUG_DETECT2_INT_EN 0xFFFEFFFF +#define R_007404_HDMI0_STATUS 0x007404 +#define S_007404_HDMI0_AZ_FORMAT_WTRIG(x) (((x) & 0x1) << 28) +#define G_007404_HDMI0_AZ_FORMAT_WTRIG(x) (((x) >> 28) & 0x1) +#define C_007404_HDMI0_AZ_FORMAT_WTRIG 0xEFFFFFFF +#define S_007404_HDMI0_AZ_FORMAT_WTRIG_INT(x) (((x) & 0x1) << 29) +#define G_007404_HDMI0_AZ_FORMAT_WTRIG_INT(x) (((x) >> 29) & 0x1) +#define C_007404_HDMI0_AZ_FORMAT_WTRIG_INT 0xDFFFFFFF +#define R_007408_HDMI0_AUDIO_PACKET_CONTROL 0x007408 +#define S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(x) (((x) & 0x1) << 28) +#define G_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(x) (((x) >> 28) & 0x1) +#define C_007408_HDMI0_AZ_FORMAT_WTRIG_MASK 0xEFFFFFFF +#define S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(x) (((x) & 0x1) << 29) +#define G_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(x) (((x) >> 29) & 0x1) +#define C_007408_HDMI0_AZ_FORMAT_WTRIG_ACK 0xDFFFFFFF + +/* MC registers */ +#define R_000000_MC_STATUS 0x000000 +#define S_000000_MC_IDLE(x) (((x) & 0x1) << 0) +#define G_000000_MC_IDLE(x) (((x) >> 0) & 0x1) +#define C_000000_MC_IDLE 0xFFFFFFFE +#define R_000004_MC_FB_LOCATION 0x000004 +#define S_000004_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000004_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000004_MC_FB_START 0xFFFF0000 +#define S_000004_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000004_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000004_MC_FB_TOP 0x0000FFFF +#define R_000005_MC_AGP_LOCATION 0x000005 +#define S_000005_MC_AGP_START(x) (((x) & 0xFFFF) << 0) +#define G_000005_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) +#define C_000005_MC_AGP_START 0xFFFF0000 +#define S_000005_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000005_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000005_MC_AGP_TOP 0x0000FFFF +#define R_000006_AGP_BASE 0x000006 +#define S_000006_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000006_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000006_AGP_BASE_ADDR 0x00000000 +#define R_000007_AGP_BASE_2 0x000007 +#define S_000007_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) +#define G_000007_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) +#define C_000007_AGP_BASE_ADDR_2 0xFFFFFFF0 +#define R_000009_MC_CNTL1 0x000009 +#define S_000009_ENABLE_PAGE_TABLES(x) (((x) & 0x1) << 26) +#define G_000009_ENABLE_PAGE_TABLES(x) (((x) >> 26) & 0x1) +#define C_000009_ENABLE_PAGE_TABLES 0xFBFFFFFF +/* FIXME don't know the various field size need feedback from AMD */ +#define R_000100_MC_PT0_CNTL 0x000100 +#define S_000100_ENABLE_PT(x) (((x) & 0x1) << 0) +#define G_000100_ENABLE_PT(x) (((x) >> 0) & 0x1) +#define C_000100_ENABLE_PT 0xFFFFFFFE +#define S_000100_EFFECTIVE_L2_CACHE_SIZE(x) (((x) & 0x7) << 15) +#define G_000100_EFFECTIVE_L2_CACHE_SIZE(x) (((x) >> 15) & 0x7) +#define C_000100_EFFECTIVE_L2_CACHE_SIZE 0xFFFC7FFF +#define S_000100_EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 0x7) << 21) +#define G_000100_EFFECTIVE_L2_QUEUE_SIZE(x) (((x) >> 21) & 0x7) +#define C_000100_EFFECTIVE_L2_QUEUE_SIZE 0xFF1FFFFF +#define S_000100_INVALIDATE_ALL_L1_TLBS(x) (((x) & 0x1) << 28) +#define G_000100_INVALIDATE_ALL_L1_TLBS(x) (((x) >> 28) & 0x1) +#define C_000100_INVALIDATE_ALL_L1_TLBS 0xEFFFFFFF +#define S_000100_INVALIDATE_L2_CACHE(x) (((x) & 0x1) << 29) +#define G_000100_INVALIDATE_L2_CACHE(x) (((x) >> 29) & 0x1) +#define C_000100_INVALIDATE_L2_CACHE 0xDFFFFFFF +#define R_000102_MC_PT0_CONTEXT0_CNTL 0x000102 +#define S_000102_ENABLE_PAGE_TABLE(x) (((x) & 0x1) << 0) +#define G_000102_ENABLE_PAGE_TABLE(x) (((x) >> 0) & 0x1) +#define C_000102_ENABLE_PAGE_TABLE 0xFFFFFFFE +#define S_000102_PAGE_TABLE_DEPTH(x) (((x) & 0x3) << 1) +#define G_000102_PAGE_TABLE_DEPTH(x) (((x) >> 1) & 0x3) +#define C_000102_PAGE_TABLE_DEPTH 0xFFFFFFF9 +#define V_000102_PAGE_TABLE_FLAT 0 +/* R600 documentation suggest that this should be a number of pages */ +#define R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR 0x000112 +#define R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR 0x000114 +#define R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x00011C +#define R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR 0x00012C +#define R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR 0x00013C +#define R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR 0x00014C +#define R_00016C_MC_PT0_CLIENT0_CNTL 0x00016C +#define S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(x) (((x) & 0x1) << 0) +#define G_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(x) (((x) >> 0) & 0x1) +#define C_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE 0xFFFFFFFE +#define S_00016C_TRANSLATION_MODE_OVERRIDE(x) (((x) & 0x1) << 1) +#define G_00016C_TRANSLATION_MODE_OVERRIDE(x) (((x) >> 1) & 0x1) +#define C_00016C_TRANSLATION_MODE_OVERRIDE 0xFFFFFFFD +#define S_00016C_SYSTEM_ACCESS_MODE_MASK(x) (((x) & 0x3) << 8) +#define G_00016C_SYSTEM_ACCESS_MODE_MASK(x) (((x) >> 8) & 0x3) +#define C_00016C_SYSTEM_ACCESS_MODE_MASK 0xFFFFFCFF +#define V_00016C_SYSTEM_ACCESS_MODE_PA_ONLY 0 +#define V_00016C_SYSTEM_ACCESS_MODE_USE_SYS_MAP 1 +#define V_00016C_SYSTEM_ACCESS_MODE_IN_SYS 2 +#define V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS 3 +#define S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(x) (((x) & 0x1) << 10) +#define G_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(x) (((x) >> 10) & 0x1) +#define C_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS 0xFFFFFBFF +#define V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH 0 +#define V_00016C_SYSTEM_APERTURE_UNMAPPED_DEFAULT_PAGE 1 +#define S_00016C_EFFECTIVE_L1_CACHE_SIZE(x) (((x) & 0x7) << 11) +#define G_00016C_EFFECTIVE_L1_CACHE_SIZE(x) (((x) >> 11) & 0x7) +#define C_00016C_EFFECTIVE_L1_CACHE_SIZE 0xFFFFC7FF +#define S_00016C_ENABLE_FRAGMENT_PROCESSING(x) (((x) & 0x1) << 14) +#define G_00016C_ENABLE_FRAGMENT_PROCESSING(x) (((x) >> 14) & 0x1) +#define C_00016C_ENABLE_FRAGMENT_PROCESSING 0xFFFFBFFF +#define S_00016C_EFFECTIVE_L1_QUEUE_SIZE(x) (((x) & 0x7) << 15) +#define G_00016C_EFFECTIVE_L1_QUEUE_SIZE(x) (((x) >> 15) & 0x7) +#define C_00016C_EFFECTIVE_L1_QUEUE_SIZE 0xFFFC7FFF +#define S_00016C_INVALIDATE_L1_TLB(x) (((x) & 0x1) << 20) +#define G_00016C_INVALIDATE_L1_TLB(x) (((x) >> 20) & 0x1) +#define C_00016C_INVALIDATE_L1_TLB 0xFFEFFFFF + +#define R_006548_D1MODE_PRIORITY_A_CNT 0x006548 +#define S_006548_D1MODE_PRIORITY_MARK_A(x) (((x) & 0x7FFF) << 0) +#define G_006548_D1MODE_PRIORITY_MARK_A(x) (((x) >> 0) & 0x7FFF) +#define C_006548_D1MODE_PRIORITY_MARK_A 0xFFFF8000 +#define S_006548_D1MODE_PRIORITY_A_OFF(x) (((x) & 0x1) << 16) +#define G_006548_D1MODE_PRIORITY_A_OFF(x) (((x) >> 16) & 0x1) +#define C_006548_D1MODE_PRIORITY_A_OFF 0xFFFEFFFF +#define S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_006548_D1MODE_PRIORITY_A_ALWAYS_ON 0xFFEFFFFF +#define S_006548_D1MODE_PRIORITY_A_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_006548_D1MODE_PRIORITY_A_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_006548_D1MODE_PRIORITY_A_FORCE_MASK 0xFEFFFFFF +#define R_00654C_D1MODE_PRIORITY_B_CNT 0x00654C +#define S_00654C_D1MODE_PRIORITY_MARK_B(x) (((x) & 0x7FFF) << 0) +#define G_00654C_D1MODE_PRIORITY_MARK_B(x) (((x) >> 0) & 0x7FFF) +#define C_00654C_D1MODE_PRIORITY_MARK_B 0xFFFF8000 +#define S_00654C_D1MODE_PRIORITY_B_OFF(x) (((x) & 0x1) << 16) +#define G_00654C_D1MODE_PRIORITY_B_OFF(x) (((x) >> 16) & 0x1) +#define C_00654C_D1MODE_PRIORITY_B_OFF 0xFFFEFFFF +#define S_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_00654C_D1MODE_PRIORITY_B_ALWAYS_ON 0xFFEFFFFF +#define S_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_00654C_D1MODE_PRIORITY_B_FORCE_MASK 0xFEFFFFFF +#define R_006D48_D2MODE_PRIORITY_A_CNT 0x006D48 +#define S_006D48_D2MODE_PRIORITY_MARK_A(x) (((x) & 0x7FFF) << 0) +#define G_006D48_D2MODE_PRIORITY_MARK_A(x) (((x) >> 0) & 0x7FFF) +#define C_006D48_D2MODE_PRIORITY_MARK_A 0xFFFF8000 +#define S_006D48_D2MODE_PRIORITY_A_OFF(x) (((x) & 0x1) << 16) +#define G_006D48_D2MODE_PRIORITY_A_OFF(x) (((x) >> 16) & 0x1) +#define C_006D48_D2MODE_PRIORITY_A_OFF 0xFFFEFFFF +#define S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_006D48_D2MODE_PRIORITY_A_ALWAYS_ON 0xFFEFFFFF +#define S_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_006D48_D2MODE_PRIORITY_A_FORCE_MASK 0xFEFFFFFF +#define R_006D4C_D2MODE_PRIORITY_B_CNT 0x006D4C +#define S_006D4C_D2MODE_PRIORITY_MARK_B(x) (((x) & 0x7FFF) << 0) +#define G_006D4C_D2MODE_PRIORITY_MARK_B(x) (((x) >> 0) & 0x7FFF) +#define C_006D4C_D2MODE_PRIORITY_MARK_B 0xFFFF8000 +#define S_006D4C_D2MODE_PRIORITY_B_OFF(x) (((x) & 0x1) << 16) +#define G_006D4C_D2MODE_PRIORITY_B_OFF(x) (((x) >> 16) & 0x1) +#define C_006D4C_D2MODE_PRIORITY_B_OFF 0xFFFEFFFF +#define S_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON 0xFFEFFFFF +#define S_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK 0xFEFFFFFF + +/* PLL regs */ +#define GENERAL_PWRMGT 0x8 +#define GLOBAL_PWRMGT_EN (1 << 0) +#define MOBILE_SU (1 << 2) +#define DYN_PWRMGT_SCLK_LENGTH 0xc +#define NORMAL_POWER_SCLK_HILEN(x) ((x) << 0) +#define NORMAL_POWER_SCLK_LOLEN(x) ((x) << 4) +#define REDUCED_POWER_SCLK_HILEN(x) ((x) << 8) +#define REDUCED_POWER_SCLK_LOLEN(x) ((x) << 12) +#define POWER_D1_SCLK_HILEN(x) ((x) << 16) +#define POWER_D1_SCLK_LOLEN(x) ((x) << 20) +#define STATIC_SCREEN_HILEN(x) ((x) << 24) +#define STATIC_SCREEN_LOLEN(x) ((x) << 28) +#define DYN_SCLK_VOL_CNTL 0xe +#define IO_CG_VOLTAGE_DROP (1 << 0) +#define VOLTAGE_DROP_SYNC (1 << 2) +#define VOLTAGE_DELAY_SEL(x) ((x) << 3) +#define HDP_DYN_CNTL 0x10 +#define HDP_FORCEON (1 << 0) +#define MC_HOST_DYN_CNTL 0x1e +#define MC_HOST_FORCEON (1 << 0) +#define DYN_BACKBIAS_CNTL 0x29 +#define IO_CG_BACKBIAS_EN (1 << 0) + +/* mmreg */ +#define DOUT_POWER_MANAGEMENT_CNTL 0x7ee0 +#define PWRDN_WAIT_BUSY_OFF (1 << 0) +#define PWRDN_WAIT_PWRSEQ_OFF (1 << 4) +#define PWRDN_WAIT_PPLL_OFF (1 << 8) +#define PWRUP_WAIT_PPLL_ON (1 << 12) +#define PWRUP_WAIT_MEM_INIT_DONE (1 << 16) +#define PM_ASSERT_RESET (1 << 20) +#define PM_PWRDN_PPLL (1 << 24) + +#endif diff --git a/sys/dev/drm2/radeon/rs690.c b/sys/dev/drm2/radeon/rs690.c new file mode 100644 index 00000000000..232053805f3 --- /dev/null +++ b/sys/dev/drm2/radeon/rs690.c @@ -0,0 +1,788 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" +#include "rs690d.h" + +int rs690_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32_MC(R_000090_MC_SYSTEM_STATUS); + if (G_000090_MC_SYSTEM_IDLE(tmp)) + return 0; + DRM_UDELAY(1); + } + return -1; +} + +static void rs690_gpu_init(struct radeon_device *rdev) +{ + /* FIXME: is this correct ? */ + r420_pipes_init(rdev); + if (rs690_mc_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait MC idle while " + "programming pipes. Bad things might happen.\n"); + } +} + +union igp_info { + struct _ATOM_INTEGRATED_SYSTEM_INFO info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_v2; +}; + +void rs690_pm_info(struct radeon_device *rdev) +{ + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + union igp_info *info; + uint16_t data_offset; + uint8_t frev, crev; + fixed20_12 tmp; + + if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, + &frev, &crev, &data_offset)) { + info = (union igp_info *)((uintptr_t)rdev->mode_info.atom_context->bios + data_offset); + + /* Get various system informations from bios */ + switch (crev) { + case 1: + tmp.full = dfixed_const(100); + rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info.ulBootUpMemoryClock)); + rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); + if (le16_to_cpu(info->info.usK8MemoryClock)) + rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); + else if (rdev->clock.default_mclk) { + rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); + rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); + } else + rdev->pm.igp_system_mclk.full = dfixed_const(400); + rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock)); + rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth); + break; + case 2: + tmp.full = dfixed_const(100); + rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpSidePortClock)); + rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); + if (le32_to_cpu(info->info_v2.ulBootUpUMAClock)) + rdev->pm.igp_system_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpUMAClock)); + else if (rdev->clock.default_mclk) + rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); + else + rdev->pm.igp_system_mclk.full = dfixed_const(66700); + rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); + rdev->pm.igp_ht_link_clk.full = dfixed_const(le32_to_cpu(info->info_v2.ulHTLinkFreq)); + rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp); + rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth)); + break; + default: + /* We assume the slower possible clock ie worst case */ + rdev->pm.igp_sideport_mclk.full = dfixed_const(200); + rdev->pm.igp_system_mclk.full = dfixed_const(200); + rdev->pm.igp_ht_link_clk.full = dfixed_const(1000); + rdev->pm.igp_ht_link_width.full = dfixed_const(8); + DRM_ERROR("No integrated system info for your GPU, using safe default\n"); + break; + } + } else { + /* We assume the slower possible clock ie worst case */ + rdev->pm.igp_sideport_mclk.full = dfixed_const(200); + rdev->pm.igp_system_mclk.full = dfixed_const(200); + rdev->pm.igp_ht_link_clk.full = dfixed_const(1000); + rdev->pm.igp_ht_link_width.full = dfixed_const(8); + DRM_ERROR("No integrated system info for your GPU, using safe default\n"); + } + /* Compute various bandwidth */ + /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ + tmp.full = dfixed_const(4); + rdev->pm.k8_bandwidth.full = dfixed_mul(rdev->pm.igp_system_mclk, tmp); + /* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8 + * = ht_clk * ht_width / 5 + */ + tmp.full = dfixed_const(5); + rdev->pm.ht_bandwidth.full = dfixed_mul(rdev->pm.igp_ht_link_clk, + rdev->pm.igp_ht_link_width); + rdev->pm.ht_bandwidth.full = dfixed_div(rdev->pm.ht_bandwidth, tmp); + if (tmp.full < rdev->pm.max_bandwidth.full) { + /* HT link is a limiting factor */ + rdev->pm.max_bandwidth.full = tmp.full; + } + /* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7 + * = (sideport_clk * 14) / 10 + */ + tmp.full = dfixed_const(14); + rdev->pm.sideport_bandwidth.full = dfixed_mul(rdev->pm.igp_sideport_mclk, tmp); + tmp.full = dfixed_const(10); + rdev->pm.sideport_bandwidth.full = dfixed_div(rdev->pm.sideport_bandwidth, tmp); +} + +static void rs690_mc_init(struct radeon_device *rdev) +{ + u64 base; + + rs400_gart_adjust_size(rdev); + rdev->mc.vram_is_ddr = true; + rdev->mc.vram_width = 128; + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.visible_vram_size = rdev->mc.aper_size; + base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); + base = G_000100_MC_FB_START(base) << 16; + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + rs690_pm_info(rdev); + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1; + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + +void rs690_line_buffer_adjust(struct radeon_device *rdev, + struct drm_display_mode *mode1, + struct drm_display_mode *mode2) +{ + u32 tmp; + + /* + * Line Buffer Setup + * There is a single line buffer shared by both display controllers. + * R_006520_DC_LB_MEMORY_SPLIT controls how that line buffer is shared between + * the display controllers. The paritioning can either be done + * manually or via one of four preset allocations specified in bits 1:0: + * 0 - line buffer is divided in half and shared between crtc + * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 + * 2 - D1 gets the whole buffer + * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 + * Setting bit 2 of R_006520_DC_LB_MEMORY_SPLIT controls switches to manual + * allocation mode. In manual allocation mode, D1 always starts at 0, + * D1 end/2 is specified in bits 14:4; D2 allocation follows D1. + */ + tmp = RREG32(R_006520_DC_LB_MEMORY_SPLIT) & C_006520_DC_LB_MEMORY_SPLIT; + tmp &= ~C_006520_DC_LB_MEMORY_SPLIT_MODE; + /* auto */ + if (mode1 && mode2) { + if (mode1->hdisplay > mode2->hdisplay) { + if (mode1->hdisplay > 2560) + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; + else + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; + } else if (mode2->hdisplay > mode1->hdisplay) { + if (mode2->hdisplay > 2560) + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; + else + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; + } else + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; + } else if (mode1) { + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_ONLY; + } else if (mode2) { + tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; + } + WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp); +} + +struct rs690_watermark { + u32 lb_request_fifo_depth; + fixed20_12 num_line_pair; + fixed20_12 estimated_width; + fixed20_12 worst_case_latency; + fixed20_12 consumption_rate; + fixed20_12 active_time; + fixed20_12 dbpp; + fixed20_12 priority_mark_max; + fixed20_12 priority_mark; + fixed20_12 sclk; +}; + +static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, + struct radeon_crtc *crtc, + struct rs690_watermark *wm) +{ + struct drm_display_mode *mode = &crtc->base.mode; + fixed20_12 a, b, c; + fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; + fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; + + if (!crtc->base.enabled) { + /* FIXME: wouldn't it better to set priority mark to maximum */ + wm->lb_request_fifo_depth = 4; + return; + } + + if (crtc->vsc.full > dfixed_const(2)) + wm->num_line_pair.full = dfixed_const(2); + else + wm->num_line_pair.full = dfixed_const(1); + + b.full = dfixed_const(mode->crtc_hdisplay); + c.full = dfixed_const(256); + a.full = dfixed_div(b, c); + request_fifo_depth.full = dfixed_mul(a, wm->num_line_pair); + request_fifo_depth.full = dfixed_ceil(request_fifo_depth); + if (a.full < dfixed_const(4)) { + wm->lb_request_fifo_depth = 4; + } else { + wm->lb_request_fifo_depth = dfixed_trunc(request_fifo_depth); + } + + /* Determine consumption rate + * pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) + * vtaps = number of vertical taps, + * vsc = vertical scaling ratio, defined as source/destination + * hsc = horizontal scaling ration, defined as source/destination + */ + a.full = dfixed_const(mode->clock); + b.full = dfixed_const(1000); + a.full = dfixed_div(a, b); + pclk.full = dfixed_div(b, a); + if (crtc->rmx_type != RMX_OFF) { + b.full = dfixed_const(2); + if (crtc->vsc.full > b.full) + b.full = crtc->vsc.full; + b.full = dfixed_mul(b, crtc->hsc); + c.full = dfixed_const(2); + b.full = dfixed_div(b, c); + consumption_time.full = dfixed_div(pclk, b); + } else { + consumption_time.full = pclk.full; + } + a.full = dfixed_const(1); + wm->consumption_rate.full = dfixed_div(a, consumption_time); + + + /* Determine line time + * LineTime = total time for one line of displayhtotal + * LineTime = total number of horizontal pixels + * pclk = pixel clock period(ns) + */ + a.full = dfixed_const(crtc->base.mode.crtc_htotal); + line_time.full = dfixed_mul(a, pclk); + + /* Determine active time + * ActiveTime = time of active region of display within one line, + * hactive = total number of horizontal active pixels + * htotal = total number of horizontal pixels + */ + a.full = dfixed_const(crtc->base.mode.crtc_htotal); + b.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + wm->active_time.full = dfixed_mul(line_time, b); + wm->active_time.full = dfixed_div(wm->active_time, a); + + /* Maximun bandwidth is the minimun bandwidth of all component */ + rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; + if (rdev->mc.igp_sideport_enabled) { + if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && + rdev->pm.sideport_bandwidth.full) + rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; +#ifdef DUMBBELL_WIP + read_delay_latency.full = dfixed_const(370 * 800 * 1000); +#endif /* DUMBBELL_WIP */ + read_delay_latency.full = UINT_MAX; + read_delay_latency.full = dfixed_div(read_delay_latency, + rdev->pm.igp_sideport_mclk); + } else { + if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full && + rdev->pm.k8_bandwidth.full) + rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth; + if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full && + rdev->pm.ht_bandwidth.full) + rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth; + read_delay_latency.full = dfixed_const(5000); + } + + /* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */ + a.full = dfixed_const(16); + rdev->pm.sclk.full = dfixed_mul(rdev->pm.max_bandwidth, a); + a.full = dfixed_const(1000); + rdev->pm.sclk.full = dfixed_div(a, rdev->pm.sclk); + /* Determine chunk time + * ChunkTime = the time it takes the DCP to send one chunk of data + * to the LB which consists of pipeline delay and inter chunk gap + * sclk = system clock(ns) + */ + a.full = dfixed_const(256 * 13); + chunk_time.full = dfixed_mul(rdev->pm.sclk, a); + a.full = dfixed_const(10); + chunk_time.full = dfixed_div(chunk_time, a); + + /* Determine the worst case latency + * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) + * WorstCaseLatency = worst case time from urgent to when the MC starts + * to return data + * READ_DELAY_IDLE_MAX = constant of 1us + * ChunkTime = time it takes the DCP to send one chunk of data to the LB + * which consists of pipeline delay and inter chunk gap + */ + if (dfixed_trunc(wm->num_line_pair) > 1) { + a.full = dfixed_const(3); + wm->worst_case_latency.full = dfixed_mul(a, chunk_time); + wm->worst_case_latency.full += read_delay_latency.full; + } else { + a.full = dfixed_const(2); + wm->worst_case_latency.full = dfixed_mul(a, chunk_time); + wm->worst_case_latency.full += read_delay_latency.full; + } + + /* Determine the tolerable latency + * TolerableLatency = Any given request has only 1 line time + * for the data to be returned + * LBRequestFifoDepth = Number of chunk requests the LB can + * put into the request FIFO for a display + * LineTime = total time for one line of display + * ChunkTime = the time it takes the DCP to send one chunk + * of data to the LB which consists of + * pipeline delay and inter chunk gap + */ + if ((2+wm->lb_request_fifo_depth) >= dfixed_trunc(request_fifo_depth)) { + tolerable_latency.full = line_time.full; + } else { + tolerable_latency.full = dfixed_const(wm->lb_request_fifo_depth - 2); + tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; + tolerable_latency.full = dfixed_mul(tolerable_latency, chunk_time); + tolerable_latency.full = line_time.full - tolerable_latency.full; + } + /* We assume worst case 32bits (4 bytes) */ + wm->dbpp.full = dfixed_const(4 * 8); + + /* Determine the maximum priority mark + * width = viewport width in pixels + */ + a.full = dfixed_const(16); + wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a); + wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max); + + /* Determine estimated width */ + estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; + estimated_width.full = dfixed_div(estimated_width, consumption_time); + if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { + wm->priority_mark.full = dfixed_const(10); + } else { + a.full = dfixed_const(16); + wm->priority_mark.full = dfixed_div(estimated_width, a); + wm->priority_mark.full = dfixed_ceil(wm->priority_mark); + wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; + } +} + +void rs690_bandwidth_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + struct rs690_watermark wm0; + struct rs690_watermark wm1; + u32 tmp; + u32 d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1); + u32 d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1); + fixed20_12 priority_mark02, priority_mark12, fill_rate; + fixed20_12 a, b; + + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + /* + * Set display0/1 priority up in the memory controller for + * modes if the user specifies HIGH for displaypriority + * option. + */ + if ((rdev->disp_priority == 2) && + ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))) { + tmp = RREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER); + tmp &= C_000104_MC_DISP0R_INIT_LAT; + tmp &= C_000104_MC_DISP1R_INIT_LAT; + if (mode0) + tmp |= S_000104_MC_DISP0R_INIT_LAT(1); + if (mode1) + tmp |= S_000104_MC_DISP1R_INIT_LAT(1); + WREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER, tmp); + } + rs690_line_buffer_adjust(rdev, mode0, mode1); + + if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) + WREG32(R_006C9C_DCP_CONTROL, 0); + if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) + WREG32(R_006C9C_DCP_CONTROL, 2); + + rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); + rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); + + tmp = (wm0.lb_request_fifo_depth - 1); + tmp |= (wm1.lb_request_fifo_depth - 1) << 16; + WREG32(R_006D58_LB_MAX_REQ_OUTSTANDING, tmp); + + if (mode0 && mode1) { + if (dfixed_trunc(wm0.dbpp) > 64) + a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + if (dfixed_trunc(wm1.dbpp) > 64) + b.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair); + else + b.full = wm1.num_line_pair.full; + a.full += b.full; + fill_rate.full = dfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm0.active_time); + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + a.full = a.full + b.full; + b.full = dfixed_const(16 * 1000); + priority_mark02.full = dfixed_div(a, b); + } else { + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark02.full = dfixed_div(a, b); + } + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm1.active_time); + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + a.full = a.full + b.full; + b.full = dfixed_const(16 * 1000); + priority_mark12.full = dfixed_div(a, b); + } else { + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark12.full = dfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (dfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (dfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); + d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); + if (rdev->disp_priority == 2) { + d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); + d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); + } + } else if (mode0) { + if (dfixed_trunc(wm0.dbpp) > 64) + a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + fill_rate.full = dfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm0.active_time); + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + a.full = a.full + b.full; + b.full = dfixed_const(16 * 1000); + priority_mark02.full = dfixed_div(a, b); + } else { + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark02.full = dfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (dfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); + if (rdev->disp_priority == 2) + d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); + } else if (mode1) { + if (dfixed_trunc(wm1.dbpp) > 64) + a.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair); + else + a.full = wm1.num_line_pair.full; + fill_rate.full = dfixed_div(wm1.sclk, a); + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm1.active_time); + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + a.full = a.full + b.full; + b.full = dfixed_const(16 * 1000); + priority_mark12.full = dfixed_div(a, b); + } else { + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark12.full = dfixed_div(a, b); + } + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (dfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); + if (rdev->disp_priority == 2) + d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); + } + + WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); + WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); + WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); + WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); +} + +uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg) +{ + uint32_t r; + + WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg)); + r = RREG32(R_00007C_MC_DATA); + WREG32(R_000078_MC_INDEX, ~C_000078_MC_IND_ADDR); + return r; +} + +void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg) | + S_000078_MC_IND_WR_EN(1)); + WREG32(R_00007C_MC_DATA, v); + WREG32(R_000078_MC_INDEX, 0x7F); +} + +static void rs690_mc_program(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + + /* Stops all mc clients */ + rv515_mc_stop(rdev, &save); + + /* Wait for mc idle */ + if (rs690_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); + /* Program MC, should be a 32bits limited address space */ + WREG32_MC(R_000100_MCCFG_FB_LOCATION, + S_000100_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000100_MC_FB_TOP(rdev->mc.vram_end >> 16)); + WREG32(R_000134_HDP_FB_LOCATION, + S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); + + rv515_mc_resume(rdev, &save); +} + +static int rs690_startup(struct radeon_device *rdev) +{ + int r; + + rs690_mc_program(rdev); + /* Resume clock */ + rv515_clock_startup(rdev); + /* Initialize GPU configuration (# pipes, ...) */ + rs690_gpu_init(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + r = rs400_gart_enable(rdev); + if (r) + return r; + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + + return 0; +} + +int rs690_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + rs400_gart_disable(rdev); + /* Resume clock before doing reset */ + rv515_clock_startup(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + atom_asic_init(rdev->mode_info.atom_context); + /* Resume clock after posting */ + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = rs690_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int rs690_suspend(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + rs600_irq_disable(rdev); + rs400_gart_disable(rdev); + return 0; +} + +void rs690_fini(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + rs400_gart_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +int rs690_init(struct radeon_device *rdev) +{ + int r; + + /* Disable VGA */ + rv515_vga_render_disable(rdev); + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* TODO: disable VGA need to use VGA request */ + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) + return r; + } else { + dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n"); + return -EINVAL; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize memory controller */ + rs690_mc_init(rdev); + rv515_debugfs(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + r = rs400_gart_init(rdev); + if (r) + return r; + rs600_set_safe_registers(rdev); + + rdev->accel_working = true; + r = rs690_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + rs400_gart_fini(rdev); + radeon_irq_kms_fini(rdev); + rdev->accel_working = false; + } + return 0; +} diff --git a/sys/dev/drm2/radeon/rs690d.h b/sys/dev/drm2/radeon/rs690d.h new file mode 100644 index 00000000000..af90d7cb1d0 --- /dev/null +++ b/sys/dev/drm2/radeon/rs690d.h @@ -0,0 +1,313 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RS690D_H__ +#define __RS690D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* Registers */ +#define R_000078_MC_INDEX 0x000078 +#define S_000078_MC_IND_ADDR(x) (((x) & 0x1FF) << 0) +#define G_000078_MC_IND_ADDR(x) (((x) >> 0) & 0x1FF) +#define C_000078_MC_IND_ADDR 0xFFFFFE00 +#define S_000078_MC_IND_WR_EN(x) (((x) & 0x1) << 9) +#define G_000078_MC_IND_WR_EN(x) (((x) >> 9) & 0x1) +#define C_000078_MC_IND_WR_EN 0xFFFFFDFF +#define R_00007C_MC_DATA 0x00007C +#define S_00007C_MC_DATA(x) (((x) & 0xFFFFFFFF) << 0) +#define G_00007C_MC_DATA(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_00007C_MC_DATA 0x00000000 +#define R_0000F8_CONFIG_MEMSIZE 0x0000F8 +#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0000F8_CONFIG_MEMSIZE 0x00000000 +#define R_000134_HDP_FB_LOCATION 0x000134 +#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000134_HDP_FB_START 0xFFFF0000 +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF +#define R_006520_DC_LB_MEMORY_SPLIT 0x006520 +#define S_006520_DC_LB_MEMORY_SPLIT(x) (((x) & 0x3) << 0) +#define G_006520_DC_LB_MEMORY_SPLIT(x) (((x) >> 0) & 0x3) +#define C_006520_DC_LB_MEMORY_SPLIT 0xFFFFFFFC +#define S_006520_DC_LB_MEMORY_SPLIT_MODE(x) (((x) & 0x1) << 2) +#define G_006520_DC_LB_MEMORY_SPLIT_MODE(x) (((x) >> 2) & 0x1) +#define C_006520_DC_LB_MEMORY_SPLIT_MODE 0xFFFFFFFB +#define V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 +#define V_006520_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 +#define V_006520_DC_LB_MEMORY_SPLIT_D1_ONLY 2 +#define V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 +#define S_006520_DC_LB_DISP1_END_ADR(x) (((x) & 0x7FF) << 4) +#define G_006520_DC_LB_DISP1_END_ADR(x) (((x) >> 4) & 0x7FF) +#define C_006520_DC_LB_DISP1_END_ADR 0xFFFF800F +#define R_006548_D1MODE_PRIORITY_A_CNT 0x006548 +#define S_006548_D1MODE_PRIORITY_MARK_A(x) (((x) & 0x7FFF) << 0) +#define G_006548_D1MODE_PRIORITY_MARK_A(x) (((x) >> 0) & 0x7FFF) +#define C_006548_D1MODE_PRIORITY_MARK_A 0xFFFF8000 +#define S_006548_D1MODE_PRIORITY_A_OFF(x) (((x) & 0x1) << 16) +#define G_006548_D1MODE_PRIORITY_A_OFF(x) (((x) >> 16) & 0x1) +#define C_006548_D1MODE_PRIORITY_A_OFF 0xFFFEFFFF +#define S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_006548_D1MODE_PRIORITY_A_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_006548_D1MODE_PRIORITY_A_ALWAYS_ON 0xFFEFFFFF +#define S_006548_D1MODE_PRIORITY_A_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_006548_D1MODE_PRIORITY_A_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_006548_D1MODE_PRIORITY_A_FORCE_MASK 0xFEFFFFFF +#define R_00654C_D1MODE_PRIORITY_B_CNT 0x00654C +#define S_00654C_D1MODE_PRIORITY_MARK_B(x) (((x) & 0x7FFF) << 0) +#define G_00654C_D1MODE_PRIORITY_MARK_B(x) (((x) >> 0) & 0x7FFF) +#define C_00654C_D1MODE_PRIORITY_MARK_B 0xFFFF8000 +#define S_00654C_D1MODE_PRIORITY_B_OFF(x) (((x) & 0x1) << 16) +#define G_00654C_D1MODE_PRIORITY_B_OFF(x) (((x) >> 16) & 0x1) +#define C_00654C_D1MODE_PRIORITY_B_OFF 0xFFFEFFFF +#define S_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_00654C_D1MODE_PRIORITY_B_ALWAYS_ON 0xFFEFFFFF +#define S_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_00654C_D1MODE_PRIORITY_B_FORCE_MASK 0xFEFFFFFF +#define R_006C9C_DCP_CONTROL 0x006C9C +#define R_006D48_D2MODE_PRIORITY_A_CNT 0x006D48 +#define S_006D48_D2MODE_PRIORITY_MARK_A(x) (((x) & 0x7FFF) << 0) +#define G_006D48_D2MODE_PRIORITY_MARK_A(x) (((x) >> 0) & 0x7FFF) +#define C_006D48_D2MODE_PRIORITY_MARK_A 0xFFFF8000 +#define S_006D48_D2MODE_PRIORITY_A_OFF(x) (((x) & 0x1) << 16) +#define G_006D48_D2MODE_PRIORITY_A_OFF(x) (((x) >> 16) & 0x1) +#define C_006D48_D2MODE_PRIORITY_A_OFF 0xFFFEFFFF +#define S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_006D48_D2MODE_PRIORITY_A_ALWAYS_ON 0xFFEFFFFF +#define S_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_006D48_D2MODE_PRIORITY_A_FORCE_MASK 0xFEFFFFFF +#define R_006D4C_D2MODE_PRIORITY_B_CNT 0x006D4C +#define S_006D4C_D2MODE_PRIORITY_MARK_B(x) (((x) & 0x7FFF) << 0) +#define G_006D4C_D2MODE_PRIORITY_MARK_B(x) (((x) >> 0) & 0x7FFF) +#define C_006D4C_D2MODE_PRIORITY_MARK_B 0xFFFF8000 +#define S_006D4C_D2MODE_PRIORITY_B_OFF(x) (((x) & 0x1) << 16) +#define G_006D4C_D2MODE_PRIORITY_B_OFF(x) (((x) >> 16) & 0x1) +#define C_006D4C_D2MODE_PRIORITY_B_OFF 0xFFFEFFFF +#define S_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x) (((x) & 0x1) << 20) +#define G_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x) (((x) >> 20) & 0x1) +#define C_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON 0xFFEFFFFF +#define S_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x) (((x) & 0x1) << 24) +#define G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x) (((x) >> 24) & 0x1) +#define C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK 0xFEFFFFFF +#define R_006D58_LB_MAX_REQ_OUTSTANDING 0x006D58 +#define S_006D58_LB_D1_MAX_REQ_OUTSTANDING(x) (((x) & 0xF) << 0) +#define G_006D58_LB_D1_MAX_REQ_OUTSTANDING(x) (((x) >> 0) & 0xF) +#define C_006D58_LB_D1_MAX_REQ_OUTSTANDING 0xFFFFFFF0 +#define S_006D58_LB_D2_MAX_REQ_OUTSTANDING(x) (((x) & 0xF) << 16) +#define G_006D58_LB_D2_MAX_REQ_OUTSTANDING(x) (((x) >> 16) & 0xF) +#define C_006D58_LB_D2_MAX_REQ_OUTSTANDING 0xFFF0FFFF + + +#define R_000090_MC_SYSTEM_STATUS 0x000090 +#define S_000090_MC_SYSTEM_IDLE(x) (((x) & 0x1) << 0) +#define G_000090_MC_SYSTEM_IDLE(x) (((x) >> 0) & 0x1) +#define C_000090_MC_SYSTEM_IDLE 0xFFFFFFFE +#define S_000090_MC_SEQUENCER_IDLE(x) (((x) & 0x1) << 1) +#define G_000090_MC_SEQUENCER_IDLE(x) (((x) >> 1) & 0x1) +#define C_000090_MC_SEQUENCER_IDLE 0xFFFFFFFD +#define S_000090_MC_ARBITER_IDLE(x) (((x) & 0x1) << 2) +#define G_000090_MC_ARBITER_IDLE(x) (((x) >> 2) & 0x1) +#define C_000090_MC_ARBITER_IDLE 0xFFFFFFFB +#define S_000090_MC_SELECT_PM(x) (((x) & 0x1) << 3) +#define G_000090_MC_SELECT_PM(x) (((x) >> 3) & 0x1) +#define C_000090_MC_SELECT_PM 0xFFFFFFF7 +#define S_000090_RESERVED4(x) (((x) & 0xF) << 4) +#define G_000090_RESERVED4(x) (((x) >> 4) & 0xF) +#define C_000090_RESERVED4 0xFFFFFF0F +#define S_000090_RESERVED8(x) (((x) & 0xF) << 8) +#define G_000090_RESERVED8(x) (((x) >> 8) & 0xF) +#define C_000090_RESERVED8 0xFFFFF0FF +#define S_000090_RESERVED12(x) (((x) & 0xF) << 12) +#define G_000090_RESERVED12(x) (((x) >> 12) & 0xF) +#define C_000090_RESERVED12 0xFFFF0FFF +#define S_000090_MCA_INIT_EXECUTED(x) (((x) & 0x1) << 16) +#define G_000090_MCA_INIT_EXECUTED(x) (((x) >> 16) & 0x1) +#define C_000090_MCA_INIT_EXECUTED 0xFFFEFFFF +#define S_000090_MCA_IDLE(x) (((x) & 0x1) << 17) +#define G_000090_MCA_IDLE(x) (((x) >> 17) & 0x1) +#define C_000090_MCA_IDLE 0xFFFDFFFF +#define S_000090_MCA_SEQ_IDLE(x) (((x) & 0x1) << 18) +#define G_000090_MCA_SEQ_IDLE(x) (((x) >> 18) & 0x1) +#define C_000090_MCA_SEQ_IDLE 0xFFFBFFFF +#define S_000090_MCA_ARB_IDLE(x) (((x) & 0x1) << 19) +#define G_000090_MCA_ARB_IDLE(x) (((x) >> 19) & 0x1) +#define C_000090_MCA_ARB_IDLE 0xFFF7FFFF +#define S_000090_RESERVED20(x) (((x) & 0xFFF) << 20) +#define G_000090_RESERVED20(x) (((x) >> 20) & 0xFFF) +#define C_000090_RESERVED20 0x000FFFFF +#define R_000100_MCCFG_FB_LOCATION 0x000100 +#define S_000100_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000100_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000100_MC_FB_START 0xFFFF0000 +#define S_000100_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000100_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000100_MC_FB_TOP 0x0000FFFF +#define R_000104_MC_INIT_MISC_LAT_TIMER 0x000104 +#define S_000104_MC_CPR_INIT_LAT(x) (((x) & 0xF) << 0) +#define G_000104_MC_CPR_INIT_LAT(x) (((x) >> 0) & 0xF) +#define C_000104_MC_CPR_INIT_LAT 0xFFFFFFF0 +#define S_000104_MC_VF_INIT_LAT(x) (((x) & 0xF) << 4) +#define G_000104_MC_VF_INIT_LAT(x) (((x) >> 4) & 0xF) +#define C_000104_MC_VF_INIT_LAT 0xFFFFFF0F +#define S_000104_MC_DISP0R_INIT_LAT(x) (((x) & 0xF) << 8) +#define G_000104_MC_DISP0R_INIT_LAT(x) (((x) >> 8) & 0xF) +#define C_000104_MC_DISP0R_INIT_LAT 0xFFFFF0FF +#define S_000104_MC_DISP1R_INIT_LAT(x) (((x) & 0xF) << 12) +#define G_000104_MC_DISP1R_INIT_LAT(x) (((x) >> 12) & 0xF) +#define C_000104_MC_DISP1R_INIT_LAT 0xFFFF0FFF +#define S_000104_MC_FIXED_INIT_LAT(x) (((x) & 0xF) << 16) +#define G_000104_MC_FIXED_INIT_LAT(x) (((x) >> 16) & 0xF) +#define C_000104_MC_FIXED_INIT_LAT 0xFFF0FFFF +#define S_000104_MC_E2R_INIT_LAT(x) (((x) & 0xF) << 20) +#define G_000104_MC_E2R_INIT_LAT(x) (((x) >> 20) & 0xF) +#define C_000104_MC_E2R_INIT_LAT 0xFF0FFFFF +#define S_000104_SAME_PAGE_PRIO(x) (((x) & 0xF) << 24) +#define G_000104_SAME_PAGE_PRIO(x) (((x) >> 24) & 0xF) +#define C_000104_SAME_PAGE_PRIO 0xF0FFFFFF +#define S_000104_MC_GLOBW_INIT_LAT(x) (((x) & 0xF) << 28) +#define G_000104_MC_GLOBW_INIT_LAT(x) (((x) >> 28) & 0xF) +#define C_000104_MC_GLOBW_INIT_LAT 0x0FFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/rv200d.h b/sys/dev/drm2/radeon/rv200d.h new file mode 100644 index 00000000000..0fec87cffae --- /dev/null +++ b/sys/dev/drm2/radeon/rv200d.h @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RV200D_H__ +#define __RV200D_H__ + +#include +__FBSDID("$FreeBSD$"); + +#define R_00015C_AGP_BASE_2 0x00015C +#define S_00015C_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) +#define G_00015C_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) +#define C_00015C_AGP_BASE_ADDR_2 0xFFFFFFF0 + +#endif diff --git a/sys/dev/drm2/radeon/rv250d.h b/sys/dev/drm2/radeon/rv250d.h new file mode 100644 index 00000000000..612273559ab --- /dev/null +++ b/sys/dev/drm2/radeon/rv250d.h @@ -0,0 +1,126 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RV250D_H__ +#define __RV250D_H__ + +#include +__FBSDID("$FreeBSD$"); + +#define R_00000D_SCLK_CNTL_M6 0x00000D +#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0) +#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7) +#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8 +#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3) +#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1) +#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7 +#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4) +#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1) +#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF +#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5) +#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1) +#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF +#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6) +#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1) +#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF +#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7) +#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1) +#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F +#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8) +#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1) +#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF +#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9) +#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1) +#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF +#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10) +#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1) +#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF +#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11) +#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1) +#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF +#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12) +#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1) +#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF +#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13) +#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1) +#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF +#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14) +#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1) +#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF +#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15) +#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1) +#define C_00000D_FORCE_DISP2 0xFFFF7FFF +#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16) +#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1) +#define C_00000D_FORCE_CP 0xFFFEFFFF +#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17) +#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1) +#define C_00000D_FORCE_HDP 0xFFFDFFFF +#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18) +#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1) +#define C_00000D_FORCE_DISP1 0xFFFBFFFF +#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19) +#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1) +#define C_00000D_FORCE_TOP 0xFFF7FFFF +#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20) +#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1) +#define C_00000D_FORCE_E2 0xFFEFFFFF +#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21) +#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1) +#define C_00000D_FORCE_SE 0xFFDFFFFF +#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22) +#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1) +#define C_00000D_FORCE_IDCT 0xFFBFFFFF +#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23) +#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1) +#define C_00000D_FORCE_VIP 0xFF7FFFFF +#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24) +#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1) +#define C_00000D_FORCE_RE 0xFEFFFFFF +#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25) +#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1) +#define C_00000D_FORCE_PB 0xFDFFFFFF +#define S_00000D_FORCE_TAM(x) (((x) & 0x1) << 26) +#define G_00000D_FORCE_TAM(x) (((x) >> 26) & 0x1) +#define C_00000D_FORCE_TAM 0xFBFFFFFF +#define S_00000D_FORCE_TDM(x) (((x) & 0x1) << 27) +#define G_00000D_FORCE_TDM(x) (((x) >> 27) & 0x1) +#define C_00000D_FORCE_TDM 0xF7FFFFFF +#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28) +#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1) +#define C_00000D_FORCE_RB 0xEFFFFFFF +#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29) +#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1) +#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF +#define S_00000D_FORCE_SUBPIC(x) (((x) & 0x1) << 30) +#define G_00000D_FORCE_SUBPIC(x) (((x) >> 30) & 0x1) +#define C_00000D_FORCE_SUBPIC 0xBFFFFFFF +#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31) +#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1) +#define C_00000D_FORCE_OV0 0x7FFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/rv350d.h b/sys/dev/drm2/radeon/rv350d.h new file mode 100644 index 00000000000..dbeaa36e0a0 --- /dev/null +++ b/sys/dev/drm2/radeon/rv350d.h @@ -0,0 +1,55 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RV350D_H__ +#define __RV350D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* RV350, RV380 registers */ +/* #define R_00000D_SCLK_CNTL 0x00000D */ +#define S_00000D_FORCE_VAP(x) (((x) & 0x1) << 21) +#define G_00000D_FORCE_VAP(x) (((x) >> 21) & 0x1) +#define C_00000D_FORCE_VAP 0xFFDFFFFF +#define S_00000D_FORCE_SR(x) (((x) & 0x1) << 25) +#define G_00000D_FORCE_SR(x) (((x) >> 25) & 0x1) +#define C_00000D_FORCE_SR 0xFDFFFFFF +#define S_00000D_FORCE_PX(x) (((x) & 0x1) << 26) +#define G_00000D_FORCE_PX(x) (((x) >> 26) & 0x1) +#define C_00000D_FORCE_PX 0xFBFFFFFF +#define S_00000D_FORCE_TX(x) (((x) & 0x1) << 27) +#define G_00000D_FORCE_TX(x) (((x) >> 27) & 0x1) +#define C_00000D_FORCE_TX 0xF7FFFFFF +#define S_00000D_FORCE_US(x) (((x) & 0x1) << 28) +#define G_00000D_FORCE_US(x) (((x) >> 28) & 0x1) +#define C_00000D_FORCE_US 0xEFFFFFFF +#define S_00000D_FORCE_SU(x) (((x) & 0x1) << 30) +#define G_00000D_FORCE_SU(x) (((x) >> 30) & 0x1) +#define C_00000D_FORCE_SU 0xBFFFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/rv515.c b/sys/dev/drm2/radeon/rv515.c new file mode 100644 index 00000000000..d83cf1ba07f --- /dev/null +++ b/sys/dev/drm2/radeon/rv515.c @@ -0,0 +1,1201 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "rv515d.h" +#include "radeon.h" +#include "radeon_asic.h" +#include "atom.h" +#include "rv515_reg_safe.h" + +/* This files gather functions specifics to: rv515 */ +static int rv515_debugfs_pipes_info_init(struct radeon_device *rdev); +static int rv515_debugfs_ga_info_init(struct radeon_device *rdev); +static void rv515_gpu_init(struct radeon_device *rdev); + +static const u32 crtc_offsets[2] = +{ + 0, + AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL +}; + +void rv515_debugfs(struct radeon_device *rdev) +{ + if (r100_debugfs_rbbm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for RBBM !\n"); + } + if (rv515_debugfs_pipes_info_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for pipes !\n"); + } + if (rv515_debugfs_ga_info_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for pipes !\n"); + } +} + +void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) +{ + int r; + + r = radeon_ring_lock(rdev, ring, 64); + if (r) { + return; + } + radeon_ring_write(ring, PACKET0(ISYNC_CNTL, 0)); + radeon_ring_write(ring, + ISYNC_ANY2D_IDLE3D | + ISYNC_ANY3D_IDLE2D | + ISYNC_WAIT_IDLEGUI | + ISYNC_CPSCRATCH_IDLEGUI); + radeon_ring_write(ring, PACKET0(WAIT_UNTIL, 0)); + radeon_ring_write(ring, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); + radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0)); + radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG); + radeon_ring_write(ring, PACKET0(GB_SELECT, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(GB_ENABLE, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(R500_SU_REG_DEST, 0)); + radeon_ring_write(ring, (1 << rdev->num_gb_pipes) - 1); + radeon_ring_write(ring, PACKET0(VAP_INDEX_OFFSET, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, RB3D_DC_FLUSH | RB3D_DC_FREE); + radeon_ring_write(ring, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, ZC_FLUSH | ZC_FREE); + radeon_ring_write(ring, PACKET0(WAIT_UNTIL, 0)); + radeon_ring_write(ring, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); + radeon_ring_write(ring, PACKET0(GB_AA_CONFIG, 0)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, RB3D_DC_FLUSH | RB3D_DC_FREE); + radeon_ring_write(ring, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(ring, ZC_FLUSH | ZC_FREE); + radeon_ring_write(ring, PACKET0(GB_MSPOS0, 0)); + radeon_ring_write(ring, + ((6 << MS_X0_SHIFT) | + (6 << MS_Y0_SHIFT) | + (6 << MS_X1_SHIFT) | + (6 << MS_Y1_SHIFT) | + (6 << MS_X2_SHIFT) | + (6 << MS_Y2_SHIFT) | + (6 << MSBD0_Y_SHIFT) | + (6 << MSBD0_X_SHIFT))); + radeon_ring_write(ring, PACKET0(GB_MSPOS1, 0)); + radeon_ring_write(ring, + ((6 << MS_X3_SHIFT) | + (6 << MS_Y3_SHIFT) | + (6 << MS_X4_SHIFT) | + (6 << MS_Y4_SHIFT) | + (6 << MS_X5_SHIFT) | + (6 << MS_Y5_SHIFT) | + (6 << MSBD1_SHIFT))); + radeon_ring_write(ring, PACKET0(GA_ENHANCE, 0)); + radeon_ring_write(ring, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL); + radeon_ring_write(ring, PACKET0(GA_POLY_MODE, 0)); + radeon_ring_write(ring, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE); + radeon_ring_write(ring, PACKET0(GA_ROUND_MODE, 0)); + radeon_ring_write(ring, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST); + radeon_ring_write(ring, PACKET0(0x20C8, 0)); + radeon_ring_write(ring, 0); + radeon_ring_unlock_commit(rdev, ring); +} + +int rv515_mc_wait_for_idle(struct radeon_device *rdev) +{ + unsigned i; + uint32_t tmp; + + for (i = 0; i < rdev->usec_timeout; i++) { + /* read MC_STATUS */ + tmp = RREG32_MC(MC_STATUS); + if (tmp & MC_STATUS_IDLE) { + return 0; + } + DRM_UDELAY(1); + } + return -1; +} + +void rv515_vga_render_disable(struct radeon_device *rdev) +{ + WREG32(R_000300_VGA_RENDER_CONTROL, + RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL); +} + +static void rv515_gpu_init(struct radeon_device *rdev) +{ + unsigned pipe_select_current, gb_pipe_select, tmp; + + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "resetting GPU. Bad things might happen.\n"); + } + rv515_vga_render_disable(rdev); + r420_pipes_init(rdev); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(R300_DST_PIPE_CONFIG); + pipe_select_current = (tmp >> 2) & 3; + tmp = (1 << pipe_select_current) | + (((gb_pipe_select >> 8) & 0xF) << 4); + WREG32_PLL(0x000D, tmp); + if (r100_gui_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait GUI idle while " + "resetting GPU. Bad things might happen.\n"); + } + if (rv515_mc_wait_for_idle(rdev)) { + DRM_ERROR("Failed to wait MC idle while " + "programming pipes. Bad things might happen.\n"); + } +} + +static void rv515_vram_get_type(struct radeon_device *rdev) +{ + uint32_t tmp; + + rdev->mc.vram_width = 128; + rdev->mc.vram_is_ddr = true; + tmp = RREG32_MC(RV515_MC_CNTL) & MEM_NUM_CHANNELS_MASK; + switch (tmp) { + case 0: + rdev->mc.vram_width = 64; + break; + case 1: + rdev->mc.vram_width = 128; + break; + default: + rdev->mc.vram_width = 128; + break; + } +} + +static void rv515_mc_init(struct radeon_device *rdev) +{ + + rv515_vram_get_type(rdev); + r100_vram_init_sizes(rdev); + radeon_vram_location(rdev, &rdev->mc, 0); + rdev->mc.gtt_base_align = 0; + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +} + +uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg) +{ + uint32_t r; + + WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); + r = RREG32(MC_IND_DATA); + WREG32(MC_IND_INDEX, 0); + return r; +} + +void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); + WREG32(MC_IND_DATA, (v)); + WREG32(MC_IND_INDEX, 0); +} + +#if defined(CONFIG_DEBUG_FS) +static int rv515_debugfs_pipes_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + tmp = RREG32(GB_PIPE_SELECT); + seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); + tmp = RREG32(SU_REG_DEST); + seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp); + tmp = RREG32(GB_TILE_CONFIG); + seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); + tmp = RREG32(DST_PIPE_CONFIG); + seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); + return 0; +} + +static int rv515_debugfs_ga_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t tmp; + + tmp = RREG32(0x2140); + seq_printf(m, "VAP_CNTL_STATUS 0x%08x\n", tmp); + radeon_asic_reset(rdev); + tmp = RREG32(0x425C); + seq_printf(m, "GA_IDLE 0x%08x\n", tmp); + return 0; +} + +static struct drm_info_list rv515_pipes_info_list[] = { + {"rv515_pipes_info", rv515_debugfs_pipes_info, 0, NULL}, +}; + +static struct drm_info_list rv515_ga_info_list[] = { + {"rv515_ga_info", rv515_debugfs_ga_info, 0, NULL}, +}; +#endif + +static int rv515_debugfs_pipes_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, rv515_pipes_info_list, 1); +#else + return 0; +#endif +} + +static int rv515_debugfs_ga_info_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, rv515_ga_info_list, 1); +#else + return 0; +#endif +} + +void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) +{ + u32 crtc_enabled, tmp, frame_count, blackout; + int i, j; + + save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); + + /* disable VGA render */ + WREG32(R_000300_VGA_RENDER_CONTROL, 0); + /* blank the display controllers */ + for (i = 0; i < rdev->num_crtc; i++) { + crtc_enabled = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN; + if (crtc_enabled) { + save->crtc_enabled[i] = true; + tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]); + if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) { + radeon_wait_for_vblank(rdev, i); + tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp); + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + DRM_UDELAY(1); + } + } else { + save->crtc_enabled[i] = false; + } + } + + radeon_mc_wait_for_idle(rdev); + + if (rdev->family >= CHIP_R600) { + if (rdev->family >= CHIP_RV770) + blackout = RREG32(R700_MC_CITF_CNTL); + else + blackout = RREG32(R600_CITF_CNTL); + if ((blackout & R600_BLACKOUT_MASK) != R600_BLACKOUT_MASK) { + /* Block CPU access */ + WREG32(R600_BIF_FB_EN, 0); + /* blackout the MC */ + blackout |= R600_BLACKOUT_MASK; + if (rdev->family >= CHIP_RV770) + WREG32(R700_MC_CITF_CNTL, blackout); + else + WREG32(R600_CITF_CNTL, blackout); + } + } + /* wait for the MC to settle */ + DRM_UDELAY(100); +} + +void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) +{ + u32 tmp, frame_count; + int i, j; + + /* update crtc base addresses */ + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->family >= CHIP_RV770) { + if (i == 1) { + WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + upper_32_bits(rdev->mc.vram_start)); + WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + upper_32_bits(rdev->mc.vram_start)); + } else { + WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + upper_32_bits(rdev->mc.vram_start)); + WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + upper_32_bits(rdev->mc.vram_start)); + } + } + WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); + WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); + } + WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); + + if (rdev->family >= CHIP_R600) { + /* unblackout the MC */ + if (rdev->family >= CHIP_RV770) + tmp = RREG32(R700_MC_CITF_CNTL); + else + tmp = RREG32(R600_CITF_CNTL); + tmp &= ~R600_BLACKOUT_MASK; + if (rdev->family >= CHIP_RV770) + WREG32(R700_MC_CITF_CNTL, tmp); + else + WREG32(R600_CITF_CNTL, tmp); + /* allow CPU access */ + WREG32(R600_BIF_FB_EN, R600_FB_READ_EN | R600_FB_WRITE_EN); + } + + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled[i]) { + tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp); + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + DRM_UDELAY(1); + } + } + } + /* Unlock vga access */ + WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); + DRM_MDELAY(1); + WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); +} + +static void rv515_mc_program(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + + /* Stops all mc clients */ + rv515_mc_stop(rdev, &save); + + /* Wait for mc idle */ + if (rv515_mc_wait_for_idle(rdev)) + dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); + /* Write VRAM size in case we are limiting it */ + WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + /* Program MC, should be a 32bits limited address space */ + WREG32_MC(R_000001_MC_FB_LOCATION, + S_000001_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000001_MC_FB_TOP(rdev->mc.vram_end >> 16)); + WREG32(R_000134_HDP_FB_LOCATION, + S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); + if (rdev->flags & RADEON_IS_AGP) { + WREG32_MC(R_000002_MC_AGP_LOCATION, + S_000002_MC_AGP_START(rdev->mc.gtt_start >> 16) | + S_000002_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); + WREG32_MC(R_000003_MC_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); + WREG32_MC(R_000004_MC_AGP_BASE_2, + S_000004_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base))); + } else { + WREG32_MC(R_000002_MC_AGP_LOCATION, 0xFFFFFFFF); + WREG32_MC(R_000003_MC_AGP_BASE, 0); + WREG32_MC(R_000004_MC_AGP_BASE_2, 0); + } + + rv515_mc_resume(rdev, &save); +} + +void rv515_clock_startup(struct radeon_device *rdev) +{ + if (radeon_dynclks != -1 && radeon_dynclks) + radeon_atom_set_clock_gating(rdev, 1); + /* We need to force on some of the block */ + WREG32_PLL(R_00000F_CP_DYN_CNTL, + RREG32_PLL(R_00000F_CP_DYN_CNTL) | S_00000F_CP_FORCEON(1)); + WREG32_PLL(R_000011_E2_DYN_CNTL, + RREG32_PLL(R_000011_E2_DYN_CNTL) | S_000011_E2_FORCEON(1)); + WREG32_PLL(R_000013_IDCT_DYN_CNTL, + RREG32_PLL(R_000013_IDCT_DYN_CNTL) | S_000013_IDCT_FORCEON(1)); +} + +static int rv515_startup(struct radeon_device *rdev) +{ + int r; + + rv515_mc_program(rdev); + /* Resume clock */ + rv515_clock_startup(rdev); + /* Initialize GPU configuration (# pipes, ...) */ + rv515_gpu_init(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_enable(rdev); + if (r) + return r; + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int rv515_resume(struct radeon_device *rdev) +{ + int r; + + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + /* Resume clock before doing reset */ + rv515_clock_startup(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* post */ + atom_asic_init(rdev->mode_info.atom_context); + /* Resume clock after posting */ + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + rdev->accel_working = true; + r = rv515_startup(rdev); + if (r) { + rdev->accel_working = false; + } + return r; +} + +int rv515_suspend(struct radeon_device *rdev) +{ + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + rs600_irq_disable(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + return 0; +} + +void rv515_set_safe_registers(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(rv515_reg_safe_bm); +} + +void rv515_fini(struct radeon_device *rdev) +{ + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_gem_fini(rdev); + rv370_pcie_gart_fini(rdev); + radeon_agp_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +int rv515_init(struct radeon_device *rdev) +{ + int r; + + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* TODO: disable VGA need to use VGA request */ + /* restore some register to sane defaults */ + r100_restore_sanity(rdev); + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) + return r; + } else { + dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n"); + return -EINVAL; + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_asic_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) { + radeon_agp_disable(rdev); + } + } + /* initialize memory controller */ + rv515_mc_init(rdev); + rv515_debugfs(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + r = radeon_irq_kms_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + r = rv370_pcie_gart_init(rdev); + if (r) + return r; + rv515_set_safe_registers(rdev); + + rdev->accel_working = true; + r = rv515_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r100_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + rv370_pcie_gart_fini(rdev); + radeon_agp_fini(rdev); + rdev->accel_working = false; + } + return 0; +} + +void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *crtc) +{ + int index_reg = 0x6578 + crtc->crtc_offset; + int data_reg = 0x657c + crtc->crtc_offset; + + WREG32(0x659C + crtc->crtc_offset, 0x0); + WREG32(0x6594 + crtc->crtc_offset, 0x705); + WREG32(0x65A4 + crtc->crtc_offset, 0x10001); + WREG32(0x65D8 + crtc->crtc_offset, 0x0); + WREG32(0x65B0 + crtc->crtc_offset, 0x0); + WREG32(0x65C0 + crtc->crtc_offset, 0x0); + WREG32(0x65D4 + crtc->crtc_offset, 0x0); + WREG32(index_reg, 0x0); + WREG32(data_reg, 0x841880A8); + WREG32(index_reg, 0x1); + WREG32(data_reg, 0x84208680); + WREG32(index_reg, 0x2); + WREG32(data_reg, 0xBFF880B0); + WREG32(index_reg, 0x100); + WREG32(data_reg, 0x83D88088); + WREG32(index_reg, 0x101); + WREG32(data_reg, 0x84608680); + WREG32(index_reg, 0x102); + WREG32(data_reg, 0xBFF080D0); + WREG32(index_reg, 0x200); + WREG32(data_reg, 0x83988068); + WREG32(index_reg, 0x201); + WREG32(data_reg, 0x84A08680); + WREG32(index_reg, 0x202); + WREG32(data_reg, 0xBFF080F8); + WREG32(index_reg, 0x300); + WREG32(data_reg, 0x83588058); + WREG32(index_reg, 0x301); + WREG32(data_reg, 0x84E08660); + WREG32(index_reg, 0x302); + WREG32(data_reg, 0xBFF88120); + WREG32(index_reg, 0x400); + WREG32(data_reg, 0x83188040); + WREG32(index_reg, 0x401); + WREG32(data_reg, 0x85008660); + WREG32(index_reg, 0x402); + WREG32(data_reg, 0xBFF88150); + WREG32(index_reg, 0x500); + WREG32(data_reg, 0x82D88030); + WREG32(index_reg, 0x501); + WREG32(data_reg, 0x85408640); + WREG32(index_reg, 0x502); + WREG32(data_reg, 0xBFF88180); + WREG32(index_reg, 0x600); + WREG32(data_reg, 0x82A08018); + WREG32(index_reg, 0x601); + WREG32(data_reg, 0x85808620); + WREG32(index_reg, 0x602); + WREG32(data_reg, 0xBFF081B8); + WREG32(index_reg, 0x700); + WREG32(data_reg, 0x82608010); + WREG32(index_reg, 0x701); + WREG32(data_reg, 0x85A08600); + WREG32(index_reg, 0x702); + WREG32(data_reg, 0x800081F0); + WREG32(index_reg, 0x800); + WREG32(data_reg, 0x8228BFF8); + WREG32(index_reg, 0x801); + WREG32(data_reg, 0x85E085E0); + WREG32(index_reg, 0x802); + WREG32(data_reg, 0xBFF88228); + WREG32(index_reg, 0x10000); + WREG32(data_reg, 0x82A8BF00); + WREG32(index_reg, 0x10001); + WREG32(data_reg, 0x82A08CC0); + WREG32(index_reg, 0x10002); + WREG32(data_reg, 0x8008BEF8); + WREG32(index_reg, 0x10100); + WREG32(data_reg, 0x81F0BF28); + WREG32(index_reg, 0x10101); + WREG32(data_reg, 0x83608CA0); + WREG32(index_reg, 0x10102); + WREG32(data_reg, 0x8018BED0); + WREG32(index_reg, 0x10200); + WREG32(data_reg, 0x8148BF38); + WREG32(index_reg, 0x10201); + WREG32(data_reg, 0x84408C80); + WREG32(index_reg, 0x10202); + WREG32(data_reg, 0x8008BEB8); + WREG32(index_reg, 0x10300); + WREG32(data_reg, 0x80B0BF78); + WREG32(index_reg, 0x10301); + WREG32(data_reg, 0x85008C20); + WREG32(index_reg, 0x10302); + WREG32(data_reg, 0x8020BEA0); + WREG32(index_reg, 0x10400); + WREG32(data_reg, 0x8028BF90); + WREG32(index_reg, 0x10401); + WREG32(data_reg, 0x85E08BC0); + WREG32(index_reg, 0x10402); + WREG32(data_reg, 0x8018BE90); + WREG32(index_reg, 0x10500); + WREG32(data_reg, 0xBFB8BFB0); + WREG32(index_reg, 0x10501); + WREG32(data_reg, 0x86C08B40); + WREG32(index_reg, 0x10502); + WREG32(data_reg, 0x8010BE90); + WREG32(index_reg, 0x10600); + WREG32(data_reg, 0xBF58BFC8); + WREG32(index_reg, 0x10601); + WREG32(data_reg, 0x87A08AA0); + WREG32(index_reg, 0x10602); + WREG32(data_reg, 0x8010BE98); + WREG32(index_reg, 0x10700); + WREG32(data_reg, 0xBF10BFF0); + WREG32(index_reg, 0x10701); + WREG32(data_reg, 0x886089E0); + WREG32(index_reg, 0x10702); + WREG32(data_reg, 0x8018BEB0); + WREG32(index_reg, 0x10800); + WREG32(data_reg, 0xBED8BFE8); + WREG32(index_reg, 0x10801); + WREG32(data_reg, 0x89408940); + WREG32(index_reg, 0x10802); + WREG32(data_reg, 0xBFE8BED8); + WREG32(index_reg, 0x20000); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x20001); + WREG32(data_reg, 0x90008000); + WREG32(index_reg, 0x20002); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x20003); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x20100); + WREG32(data_reg, 0x80108000); + WREG32(index_reg, 0x20101); + WREG32(data_reg, 0x8FE0BF70); + WREG32(index_reg, 0x20102); + WREG32(data_reg, 0xBFE880C0); + WREG32(index_reg, 0x20103); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x20200); + WREG32(data_reg, 0x8018BFF8); + WREG32(index_reg, 0x20201); + WREG32(data_reg, 0x8F80BF08); + WREG32(index_reg, 0x20202); + WREG32(data_reg, 0xBFD081A0); + WREG32(index_reg, 0x20203); + WREG32(data_reg, 0xBFF88000); + WREG32(index_reg, 0x20300); + WREG32(data_reg, 0x80188000); + WREG32(index_reg, 0x20301); + WREG32(data_reg, 0x8EE0BEC0); + WREG32(index_reg, 0x20302); + WREG32(data_reg, 0xBFB082A0); + WREG32(index_reg, 0x20303); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x20400); + WREG32(data_reg, 0x80188000); + WREG32(index_reg, 0x20401); + WREG32(data_reg, 0x8E00BEA0); + WREG32(index_reg, 0x20402); + WREG32(data_reg, 0xBF8883C0); + WREG32(index_reg, 0x20403); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x20500); + WREG32(data_reg, 0x80188000); + WREG32(index_reg, 0x20501); + WREG32(data_reg, 0x8D00BE90); + WREG32(index_reg, 0x20502); + WREG32(data_reg, 0xBF588500); + WREG32(index_reg, 0x20503); + WREG32(data_reg, 0x80008008); + WREG32(index_reg, 0x20600); + WREG32(data_reg, 0x80188000); + WREG32(index_reg, 0x20601); + WREG32(data_reg, 0x8BC0BE98); + WREG32(index_reg, 0x20602); + WREG32(data_reg, 0xBF308660); + WREG32(index_reg, 0x20603); + WREG32(data_reg, 0x80008008); + WREG32(index_reg, 0x20700); + WREG32(data_reg, 0x80108000); + WREG32(index_reg, 0x20701); + WREG32(data_reg, 0x8A80BEB0); + WREG32(index_reg, 0x20702); + WREG32(data_reg, 0xBF0087C0); + WREG32(index_reg, 0x20703); + WREG32(data_reg, 0x80008008); + WREG32(index_reg, 0x20800); + WREG32(data_reg, 0x80108000); + WREG32(index_reg, 0x20801); + WREG32(data_reg, 0x8920BED0); + WREG32(index_reg, 0x20802); + WREG32(data_reg, 0xBED08920); + WREG32(index_reg, 0x20803); + WREG32(data_reg, 0x80008010); + WREG32(index_reg, 0x30000); + WREG32(data_reg, 0x90008000); + WREG32(index_reg, 0x30001); + WREG32(data_reg, 0x80008000); + WREG32(index_reg, 0x30100); + WREG32(data_reg, 0x8FE0BF90); + WREG32(index_reg, 0x30101); + WREG32(data_reg, 0xBFF880A0); + WREG32(index_reg, 0x30200); + WREG32(data_reg, 0x8F60BF40); + WREG32(index_reg, 0x30201); + WREG32(data_reg, 0xBFE88180); + WREG32(index_reg, 0x30300); + WREG32(data_reg, 0x8EC0BF00); + WREG32(index_reg, 0x30301); + WREG32(data_reg, 0xBFC88280); + WREG32(index_reg, 0x30400); + WREG32(data_reg, 0x8DE0BEE0); + WREG32(index_reg, 0x30401); + WREG32(data_reg, 0xBFA083A0); + WREG32(index_reg, 0x30500); + WREG32(data_reg, 0x8CE0BED0); + WREG32(index_reg, 0x30501); + WREG32(data_reg, 0xBF7884E0); + WREG32(index_reg, 0x30600); + WREG32(data_reg, 0x8BA0BED8); + WREG32(index_reg, 0x30601); + WREG32(data_reg, 0xBF508640); + WREG32(index_reg, 0x30700); + WREG32(data_reg, 0x8A60BEE8); + WREG32(index_reg, 0x30701); + WREG32(data_reg, 0xBF2087A0); + WREG32(index_reg, 0x30800); + WREG32(data_reg, 0x8900BF00); + WREG32(index_reg, 0x30801); + WREG32(data_reg, 0xBF008900); +} + +struct rv515_watermark { + u32 lb_request_fifo_depth; + fixed20_12 num_line_pair; + fixed20_12 estimated_width; + fixed20_12 worst_case_latency; + fixed20_12 consumption_rate; + fixed20_12 active_time; + fixed20_12 dbpp; + fixed20_12 priority_mark_max; + fixed20_12 priority_mark; + fixed20_12 sclk; +}; + +static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, + struct radeon_crtc *crtc, + struct rv515_watermark *wm) +{ + struct drm_display_mode *mode = &crtc->base.mode; + fixed20_12 a, b, c; + fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; + fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; + + if (!crtc->base.enabled) { + /* FIXME: wouldn't it better to set priority mark to maximum */ + wm->lb_request_fifo_depth = 4; + return; + } + + if (crtc->vsc.full > dfixed_const(2)) + wm->num_line_pair.full = dfixed_const(2); + else + wm->num_line_pair.full = dfixed_const(1); + + b.full = dfixed_const(mode->crtc_hdisplay); + c.full = dfixed_const(256); + a.full = dfixed_div(b, c); + request_fifo_depth.full = dfixed_mul(a, wm->num_line_pair); + request_fifo_depth.full = dfixed_ceil(request_fifo_depth); + if (a.full < dfixed_const(4)) { + wm->lb_request_fifo_depth = 4; + } else { + wm->lb_request_fifo_depth = dfixed_trunc(request_fifo_depth); + } + + /* Determine consumption rate + * pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) + * vtaps = number of vertical taps, + * vsc = vertical scaling ratio, defined as source/destination + * hsc = horizontal scaling ration, defined as source/destination + */ + a.full = dfixed_const(mode->clock); + b.full = dfixed_const(1000); + a.full = dfixed_div(a, b); + pclk.full = dfixed_div(b, a); + if (crtc->rmx_type != RMX_OFF) { + b.full = dfixed_const(2); + if (crtc->vsc.full > b.full) + b.full = crtc->vsc.full; + b.full = dfixed_mul(b, crtc->hsc); + c.full = dfixed_const(2); + b.full = dfixed_div(b, c); + consumption_time.full = dfixed_div(pclk, b); + } else { + consumption_time.full = pclk.full; + } + a.full = dfixed_const(1); + wm->consumption_rate.full = dfixed_div(a, consumption_time); + + + /* Determine line time + * LineTime = total time for one line of displayhtotal + * LineTime = total number of horizontal pixels + * pclk = pixel clock period(ns) + */ + a.full = dfixed_const(crtc->base.mode.crtc_htotal); + line_time.full = dfixed_mul(a, pclk); + + /* Determine active time + * ActiveTime = time of active region of display within one line, + * hactive = total number of horizontal active pixels + * htotal = total number of horizontal pixels + */ + a.full = dfixed_const(crtc->base.mode.crtc_htotal); + b.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + wm->active_time.full = dfixed_mul(line_time, b); + wm->active_time.full = dfixed_div(wm->active_time, a); + + /* Determine chunk time + * ChunkTime = the time it takes the DCP to send one chunk of data + * to the LB which consists of pipeline delay and inter chunk gap + * sclk = system clock(Mhz) + */ + a.full = dfixed_const(600 * 1000); + chunk_time.full = dfixed_div(a, rdev->pm.sclk); + read_delay_latency.full = dfixed_const(1000); + + /* Determine the worst case latency + * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) + * WorstCaseLatency = worst case time from urgent to when the MC starts + * to return data + * READ_DELAY_IDLE_MAX = constant of 1us + * ChunkTime = time it takes the DCP to send one chunk of data to the LB + * which consists of pipeline delay and inter chunk gap + */ + if (dfixed_trunc(wm->num_line_pair) > 1) { + a.full = dfixed_const(3); + wm->worst_case_latency.full = dfixed_mul(a, chunk_time); + wm->worst_case_latency.full += read_delay_latency.full; + } else { + wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full; + } + + /* Determine the tolerable latency + * TolerableLatency = Any given request has only 1 line time + * for the data to be returned + * LBRequestFifoDepth = Number of chunk requests the LB can + * put into the request FIFO for a display + * LineTime = total time for one line of display + * ChunkTime = the time it takes the DCP to send one chunk + * of data to the LB which consists of + * pipeline delay and inter chunk gap + */ + if ((2+wm->lb_request_fifo_depth) >= dfixed_trunc(request_fifo_depth)) { + tolerable_latency.full = line_time.full; + } else { + tolerable_latency.full = dfixed_const(wm->lb_request_fifo_depth - 2); + tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; + tolerable_latency.full = dfixed_mul(tolerable_latency, chunk_time); + tolerable_latency.full = line_time.full - tolerable_latency.full; + } + /* We assume worst case 32bits (4 bytes) */ + wm->dbpp.full = dfixed_const(2 * 16); + + /* Determine the maximum priority mark + * width = viewport width in pixels + */ + a.full = dfixed_const(16); + wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a); + wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max); + + /* Determine estimated width */ + estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; + estimated_width.full = dfixed_div(estimated_width, consumption_time); + if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { + wm->priority_mark.full = wm->priority_mark_max.full; + } else { + a.full = dfixed_const(16); + wm->priority_mark.full = dfixed_div(estimated_width, a); + wm->priority_mark.full = dfixed_ceil(wm->priority_mark); + wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; + } +} + +void rv515_bandwidth_avivo_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + struct rv515_watermark wm0; + struct rv515_watermark wm1; + u32 tmp; + u32 d1mode_priority_a_cnt = MODE_PRIORITY_OFF; + u32 d2mode_priority_a_cnt = MODE_PRIORITY_OFF; + fixed20_12 priority_mark02, priority_mark12, fill_rate; + fixed20_12 a, b; + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + rs690_line_buffer_adjust(rdev, mode0, mode1); + + rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); + rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); + + tmp = wm0.lb_request_fifo_depth; + tmp |= wm1.lb_request_fifo_depth << 16; + WREG32(LB_MAX_REQ_OUTSTANDING, tmp); + + if (mode0 && mode1) { + if (dfixed_trunc(wm0.dbpp) > 64) + a.full = dfixed_div(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + if (dfixed_trunc(wm1.dbpp) > 64) + b.full = dfixed_div(wm1.dbpp, wm1.num_line_pair); + else + b.full = wm1.num_line_pair.full; + a.full += b.full; + fill_rate.full = dfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm0.active_time); + a.full = dfixed_const(16); + b.full = dfixed_div(b, a); + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + priority_mark02.full = a.full + b.full; + } else { + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark02.full = dfixed_div(a, b); + } + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm1.active_time); + a.full = dfixed_const(16); + b.full = dfixed_div(b, a); + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + priority_mark12.full = a.full + b.full; + } else { + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark12.full = dfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (dfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (dfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); + d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); + if (rdev->disp_priority == 2) { + d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; + d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; + } + } else if (mode0) { + if (dfixed_trunc(wm0.dbpp) > 64) + a.full = dfixed_div(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + fill_rate.full = dfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm0.active_time); + a.full = dfixed_const(16); + b.full = dfixed_div(b, a); + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + priority_mark02.full = a.full + b.full; + } else { + a.full = dfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = dfixed_const(16); + priority_mark02.full = dfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (dfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); + if (rdev->disp_priority == 2) + d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; + } else if (mode1) { + if (dfixed_trunc(wm1.dbpp) > 64) + a.full = dfixed_div(wm1.dbpp, wm1.num_line_pair); + else + a.full = wm1.num_line_pair.full; + fill_rate.full = dfixed_div(wm1.sclk, a); + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = dfixed_mul(b, wm1.active_time); + a.full = dfixed_const(16); + b.full = dfixed_div(b, a); + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + priority_mark12.full = a.full + b.full; + } else { + a.full = dfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = dfixed_const(16 * 1000); + priority_mark12.full = dfixed_div(a, b); + } + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (dfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); + if (rdev->disp_priority == 2) + d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; + } + + WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); + WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); + WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); + WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); +} + +void rv515_bandwidth_update(struct radeon_device *rdev) +{ + uint32_t tmp; + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + /* + * Set display0/1 priority up in the memory controller for + * modes if the user specifies HIGH for displaypriority + * option. + */ + if ((rdev->disp_priority == 2) && + (rdev->family == CHIP_RV515)) { + tmp = RREG32_MC(MC_MISC_LAT_TIMER); + tmp &= ~MC_DISP1R_INIT_LAT_MASK; + tmp &= ~MC_DISP0R_INIT_LAT_MASK; + if (mode1) + tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT); + if (mode0) + tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT); + WREG32_MC(MC_MISC_LAT_TIMER, tmp); + } + rv515_bandwidth_avivo_update(rdev); +} diff --git a/sys/dev/drm2/radeon/rv515_reg_safe.h b/sys/dev/drm2/radeon/rv515_reg_safe.h new file mode 100644 index 00000000000..07bd8276029 --- /dev/null +++ b/sys/dev/drm2/radeon/rv515_reg_safe.h @@ -0,0 +1,60 @@ +#include +__FBSDID("$FreeBSD$"); + +static const unsigned rv515_reg_safe_bm[219] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, + 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFEFC6, 0xF00EBFFF, 0x007C0000, + 0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x1FFFFC48, 0xFFFFE000, 0xFFFFFE1E, 0xFFFFFFFF, + 0x388F8F50, 0xFFF88082, 0xFF0000FC, 0xFAE00BFF, + 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00008CFC, 0xFFFCC1FF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE80FFFF, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0003FC0B, 0x3FFFFCFF, 0xFFBFFB99, 0xFFDFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +}; diff --git a/sys/dev/drm2/radeon/rv515d.h b/sys/dev/drm2/radeon/rv515d.h new file mode 100644 index 00000000000..38b3a2e4f27 --- /dev/null +++ b/sys/dev/drm2/radeon/rv515d.h @@ -0,0 +1,652 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RV515D_H__ +#define __RV515D_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* + * RV515 registers + */ +#define PCIE_INDEX 0x0030 +#define PCIE_DATA 0x0034 +#define MC_IND_INDEX 0x0070 +#define MC_IND_WR_EN (1 << 24) +#define MC_IND_DATA 0x0074 +#define RBBM_SOFT_RESET 0x00F0 +#define CONFIG_MEMSIZE 0x00F8 +#define HDP_FB_LOCATION 0x0134 +#define CP_CSQ_CNTL 0x0740 +#define CP_CSQ_MODE 0x0744 +#define CP_CSQ_ADDR 0x07F0 +#define CP_CSQ_DATA 0x07F4 +#define CP_CSQ_STAT 0x07F8 +#define CP_CSQ2_STAT 0x07FC +#define RBBM_STATUS 0x0E40 +#define DST_PIPE_CONFIG 0x170C +#define WAIT_UNTIL 0x1720 +#define WAIT_2D_IDLE (1 << 14) +#define WAIT_3D_IDLE (1 << 15) +#define WAIT_2D_IDLECLEAN (1 << 16) +#define WAIT_3D_IDLECLEAN (1 << 17) +#define ISYNC_CNTL 0x1724 +#define ISYNC_ANY2D_IDLE3D (1 << 0) +#define ISYNC_ANY3D_IDLE2D (1 << 1) +#define ISYNC_TRIG2D_IDLE3D (1 << 2) +#define ISYNC_TRIG3D_IDLE2D (1 << 3) +#define ISYNC_WAIT_IDLEGUI (1 << 4) +#define ISYNC_CPSCRATCH_IDLEGUI (1 << 5) +#define VAP_INDEX_OFFSET 0x208C +#define VAP_PVS_STATE_FLUSH_REG 0x2284 +#define GB_ENABLE 0x4008 +#define GB_MSPOS0 0x4010 +#define MS_X0_SHIFT 0 +#define MS_Y0_SHIFT 4 +#define MS_X1_SHIFT 8 +#define MS_Y1_SHIFT 12 +#define MS_X2_SHIFT 16 +#define MS_Y2_SHIFT 20 +#define MSBD0_Y_SHIFT 24 +#define MSBD0_X_SHIFT 28 +#define GB_MSPOS1 0x4014 +#define MS_X3_SHIFT 0 +#define MS_Y3_SHIFT 4 +#define MS_X4_SHIFT 8 +#define MS_Y4_SHIFT 12 +#define MS_X5_SHIFT 16 +#define MS_Y5_SHIFT 20 +#define MSBD1_SHIFT 24 +#define GB_TILE_CONFIG 0x4018 +#define ENABLE_TILING (1 << 0) +#define PIPE_COUNT_MASK 0x0000000E +#define PIPE_COUNT_SHIFT 1 +#define TILE_SIZE_8 (0 << 4) +#define TILE_SIZE_16 (1 << 4) +#define TILE_SIZE_32 (2 << 4) +#define SUBPIXEL_1_12 (0 << 16) +#define SUBPIXEL_1_16 (1 << 16) +#define GB_SELECT 0x401C +#define GB_AA_CONFIG 0x4020 +#define GB_PIPE_SELECT 0x402C +#define GA_ENHANCE 0x4274 +#define GA_DEADLOCK_CNTL (1 << 0) +#define GA_FASTSYNC_CNTL (1 << 1) +#define GA_POLY_MODE 0x4288 +#define FRONT_PTYPE_POINT (0 << 4) +#define FRONT_PTYPE_LINE (1 << 4) +#define FRONT_PTYPE_TRIANGE (2 << 4) +#define BACK_PTYPE_POINT (0 << 7) +#define BACK_PTYPE_LINE (1 << 7) +#define BACK_PTYPE_TRIANGE (2 << 7) +#define GA_ROUND_MODE 0x428C +#define GEOMETRY_ROUND_TRUNC (0 << 0) +#define GEOMETRY_ROUND_NEAREST (1 << 0) +#define COLOR_ROUND_TRUNC (0 << 2) +#define COLOR_ROUND_NEAREST (1 << 2) +#define SU_REG_DEST 0x42C8 +#define RB3D_DSTCACHE_CTLSTAT 0x4E4C +#define RB3D_DC_FLUSH (2 << 0) +#define RB3D_DC_FREE (2 << 2) +#define RB3D_DC_FINISH (1 << 4) +#define ZB_ZCACHE_CTLSTAT 0x4F18 +#define ZC_FLUSH (1 << 0) +#define ZC_FREE (1 << 1) +#define DC_LB_MEMORY_SPLIT 0x6520 +#define DC_LB_MEMORY_SPLIT_MASK 0x00000003 +#define DC_LB_MEMORY_SPLIT_SHIFT 0 +#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 +#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 +#define DC_LB_MEMORY_SPLIT_D1_ONLY 2 +#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 +#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) +#define DC_LB_DISP1_END_ADR_SHIFT 4 +#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0 +#define D1MODE_PRIORITY_A_CNT 0x6548 +#define MODE_PRIORITY_MARK_MASK 0x00007FFF +#define MODE_PRIORITY_OFF (1 << 16) +#define MODE_PRIORITY_ALWAYS_ON (1 << 20) +#define MODE_PRIORITY_FORCE_MASK (1 << 24) +#define D1MODE_PRIORITY_B_CNT 0x654C +#define LB_MAX_REQ_OUTSTANDING 0x6D58 +#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F +#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0 +#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000 +#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16 +#define D2MODE_PRIORITY_A_CNT 0x6D48 +#define D2MODE_PRIORITY_B_CNT 0x6D4C + +/* ix[MC] registers */ +#define MC_FB_LOCATION 0x01 +#define MC_FB_START_MASK 0x0000FFFF +#define MC_FB_START_SHIFT 0 +#define MC_FB_TOP_MASK 0xFFFF0000 +#define MC_FB_TOP_SHIFT 16 +#define MC_AGP_LOCATION 0x02 +#define MC_AGP_START_MASK 0x0000FFFF +#define MC_AGP_START_SHIFT 0 +#define MC_AGP_TOP_MASK 0xFFFF0000 +#define MC_AGP_TOP_SHIFT 16 +#define MC_AGP_BASE 0x03 +#define MC_AGP_BASE_2 0x04 +#define MC_CNTL 0x5 +#define MEM_NUM_CHANNELS_MASK 0x00000003 +#define MC_STATUS 0x08 +#define MC_STATUS_IDLE (1 << 4) +#define MC_MISC_LAT_TIMER 0x09 +#define MC_CPR_INIT_LAT_MASK 0x0000000F +#define MC_VF_INIT_LAT_MASK 0x000000F0 +#define MC_DISP0R_INIT_LAT_MASK 0x00000F00 +#define MC_DISP0R_INIT_LAT_SHIFT 8 +#define MC_DISP1R_INIT_LAT_MASK 0x0000F000 +#define MC_DISP1R_INIT_LAT_SHIFT 12 +#define MC_FIXED_INIT_LAT_MASK 0x000F0000 +#define MC_E2R_INIT_LAT_MASK 0x00F00000 +#define SAME_PAGE_PRIO_MASK 0x0F000000 +#define MC_GLOBW_INIT_LAT_MASK 0xF0000000 + + +/* + * PM4 packet + */ +#define CP_PACKET0 0x00000000 +#define PACKET0_BASE_INDEX_SHIFT 0 +#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) +#define PACKET0_COUNT_SHIFT 16 +#define PACKET0_COUNT_MASK (0x3fff << 16) +#define CP_PACKET1 0x40000000 +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) +#define CP_PACKET3 0xC0000000 +#define PACKET3_IT_OPCODE_SHIFT 8 +#define PACKET3_IT_OPCODE_MASK (0xff << 8) +#define PACKET3_COUNT_SHIFT 16 +#define PACKET3_COUNT_MASK (0x3fff << 16) +/* PACKET3 op code */ +#define PACKET3_NOP 0x10 +#define PACKET3_3D_DRAW_VBUF 0x28 +#define PACKET3_3D_DRAW_IMMD 0x29 +#define PACKET3_3D_DRAW_INDX 0x2A +#define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_INDX_BUFFER 0x33 +#define PACKET3_3D_DRAW_VBUF_2 0x34 +#define PACKET3_3D_DRAW_IMMD_2 0x35 +#define PACKET3_3D_DRAW_INDX_2 0x36 +#define PACKET3_BITBLT_MULTI 0x9B + +#define PACKET0(reg, n) (CP_PACKET0 | \ + REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ + REG_SET(PACKET0_COUNT, (n))) +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) +#define PACKET3(op, n) (CP_PACKET3 | \ + REG_SET(PACKET3_IT_OPCODE, (op)) | \ + REG_SET(PACKET3_COUNT, (n))) + +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) +#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) + +/* Registers */ +#define R_0000F0_RBBM_SOFT_RESET 0x0000F0 +#define S_0000F0_SOFT_RESET_CP(x) (((x) & 0x1) << 0) +#define G_0000F0_SOFT_RESET_CP(x) (((x) >> 0) & 0x1) +#define C_0000F0_SOFT_RESET_CP 0xFFFFFFFE +#define S_0000F0_SOFT_RESET_HI(x) (((x) & 0x1) << 1) +#define G_0000F0_SOFT_RESET_HI(x) (((x) >> 1) & 0x1) +#define C_0000F0_SOFT_RESET_HI 0xFFFFFFFD +#define S_0000F0_SOFT_RESET_VAP(x) (((x) & 0x1) << 2) +#define G_0000F0_SOFT_RESET_VAP(x) (((x) >> 2) & 0x1) +#define C_0000F0_SOFT_RESET_VAP 0xFFFFFFFB +#define S_0000F0_SOFT_RESET_RE(x) (((x) & 0x1) << 3) +#define G_0000F0_SOFT_RESET_RE(x) (((x) >> 3) & 0x1) +#define C_0000F0_SOFT_RESET_RE 0xFFFFFFF7 +#define S_0000F0_SOFT_RESET_PP(x) (((x) & 0x1) << 4) +#define G_0000F0_SOFT_RESET_PP(x) (((x) >> 4) & 0x1) +#define C_0000F0_SOFT_RESET_PP 0xFFFFFFEF +#define S_0000F0_SOFT_RESET_E2(x) (((x) & 0x1) << 5) +#define G_0000F0_SOFT_RESET_E2(x) (((x) >> 5) & 0x1) +#define C_0000F0_SOFT_RESET_E2 0xFFFFFFDF +#define S_0000F0_SOFT_RESET_RB(x) (((x) & 0x1) << 6) +#define G_0000F0_SOFT_RESET_RB(x) (((x) >> 6) & 0x1) +#define C_0000F0_SOFT_RESET_RB 0xFFFFFFBF +#define S_0000F0_SOFT_RESET_HDP(x) (((x) & 0x1) << 7) +#define G_0000F0_SOFT_RESET_HDP(x) (((x) >> 7) & 0x1) +#define C_0000F0_SOFT_RESET_HDP 0xFFFFFF7F +#define S_0000F0_SOFT_RESET_MC(x) (((x) & 0x1) << 8) +#define G_0000F0_SOFT_RESET_MC(x) (((x) >> 8) & 0x1) +#define C_0000F0_SOFT_RESET_MC 0xFFFFFEFF +#define S_0000F0_SOFT_RESET_AIC(x) (((x) & 0x1) << 9) +#define G_0000F0_SOFT_RESET_AIC(x) (((x) >> 9) & 0x1) +#define C_0000F0_SOFT_RESET_AIC 0xFFFFFDFF +#define S_0000F0_SOFT_RESET_VIP(x) (((x) & 0x1) << 10) +#define G_0000F0_SOFT_RESET_VIP(x) (((x) >> 10) & 0x1) +#define C_0000F0_SOFT_RESET_VIP 0xFFFFFBFF +#define S_0000F0_SOFT_RESET_DISP(x) (((x) & 0x1) << 11) +#define G_0000F0_SOFT_RESET_DISP(x) (((x) >> 11) & 0x1) +#define C_0000F0_SOFT_RESET_DISP 0xFFFFF7FF +#define S_0000F0_SOFT_RESET_CG(x) (((x) & 0x1) << 12) +#define G_0000F0_SOFT_RESET_CG(x) (((x) >> 12) & 0x1) +#define C_0000F0_SOFT_RESET_CG 0xFFFFEFFF +#define S_0000F0_SOFT_RESET_GA(x) (((x) & 0x1) << 13) +#define G_0000F0_SOFT_RESET_GA(x) (((x) >> 13) & 0x1) +#define C_0000F0_SOFT_RESET_GA 0xFFFFDFFF +#define S_0000F0_SOFT_RESET_IDCT(x) (((x) & 0x1) << 14) +#define G_0000F0_SOFT_RESET_IDCT(x) (((x) >> 14) & 0x1) +#define C_0000F0_SOFT_RESET_IDCT 0xFFFFBFFF +#define R_0000F8_CONFIG_MEMSIZE 0x0000F8 +#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0000F8_CONFIG_MEMSIZE 0x00000000 +#define R_000134_HDP_FB_LOCATION 0x000134 +#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000134_HDP_FB_START 0xFFFF0000 +#define R_000300_VGA_RENDER_CONTROL 0x000300 +#define S_000300_VGA_BLINK_RATE(x) (((x) & 0x1F) << 0) +#define G_000300_VGA_BLINK_RATE(x) (((x) >> 0) & 0x1F) +#define C_000300_VGA_BLINK_RATE 0xFFFFFFE0 +#define S_000300_VGA_BLINK_MODE(x) (((x) & 0x3) << 5) +#define G_000300_VGA_BLINK_MODE(x) (((x) >> 5) & 0x3) +#define C_000300_VGA_BLINK_MODE 0xFFFFFF9F +#define S_000300_VGA_CURSOR_BLINK_INVERT(x) (((x) & 0x1) << 7) +#define G_000300_VGA_CURSOR_BLINK_INVERT(x) (((x) >> 7) & 0x1) +#define C_000300_VGA_CURSOR_BLINK_INVERT 0xFFFFFF7F +#define S_000300_VGA_EXTD_ADDR_COUNT_ENABLE(x) (((x) & 0x1) << 8) +#define G_000300_VGA_EXTD_ADDR_COUNT_ENABLE(x) (((x) >> 8) & 0x1) +#define C_000300_VGA_EXTD_ADDR_COUNT_ENABLE 0xFFFFFEFF +#define S_000300_VGA_VSTATUS_CNTL(x) (((x) & 0x3) << 16) +#define G_000300_VGA_VSTATUS_CNTL(x) (((x) >> 16) & 0x3) +#define C_000300_VGA_VSTATUS_CNTL 0xFFFCFFFF +#define S_000300_VGA_LOCK_8DOT(x) (((x) & 0x1) << 24) +#define G_000300_VGA_LOCK_8DOT(x) (((x) >> 24) & 0x1) +#define C_000300_VGA_LOCK_8DOT 0xFEFFFFFF +#define S_000300_VGAREG_LINECMP_COMPATIBILITY_SEL(x) (((x) & 0x1) << 25) +#define G_000300_VGAREG_LINECMP_COMPATIBILITY_SEL(x) (((x) >> 25) & 0x1) +#define C_000300_VGAREG_LINECMP_COMPATIBILITY_SEL 0xFDFFFFFF +#define R_000310_VGA_MEMORY_BASE_ADDRESS 0x000310 +#define S_000310_VGA_MEMORY_BASE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000310_VGA_MEMORY_BASE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000310_VGA_MEMORY_BASE_ADDRESS 0x00000000 +#define R_000328_VGA_HDP_CONTROL 0x000328 +#define S_000328_VGA_MEM_PAGE_SELECT_EN(x) (((x) & 0x1) << 0) +#define G_000328_VGA_MEM_PAGE_SELECT_EN(x) (((x) >> 0) & 0x1) +#define C_000328_VGA_MEM_PAGE_SELECT_EN 0xFFFFFFFE +#define S_000328_VGA_RBBM_LOCK_DISABLE(x) (((x) & 0x1) << 8) +#define G_000328_VGA_RBBM_LOCK_DISABLE(x) (((x) >> 8) & 0x1) +#define C_000328_VGA_RBBM_LOCK_DISABLE 0xFFFFFEFF +#define S_000328_VGA_SOFT_RESET(x) (((x) & 0x1) << 16) +#define G_000328_VGA_SOFT_RESET(x) (((x) >> 16) & 0x1) +#define C_000328_VGA_SOFT_RESET 0xFFFEFFFF +#define S_000328_VGA_TEST_RESET_CONTROL(x) (((x) & 0x1) << 24) +#define G_000328_VGA_TEST_RESET_CONTROL(x) (((x) >> 24) & 0x1) +#define C_000328_VGA_TEST_RESET_CONTROL 0xFEFFFFFF +#define R_000330_D1VGA_CONTROL 0x000330 +#define S_000330_D1VGA_MODE_ENABLE(x) (((x) & 0x1) << 0) +#define G_000330_D1VGA_MODE_ENABLE(x) (((x) >> 0) & 0x1) +#define C_000330_D1VGA_MODE_ENABLE 0xFFFFFFFE +#define S_000330_D1VGA_TIMING_SELECT(x) (((x) & 0x1) << 8) +#define G_000330_D1VGA_TIMING_SELECT(x) (((x) >> 8) & 0x1) +#define C_000330_D1VGA_TIMING_SELECT 0xFFFFFEFF +#define S_000330_D1VGA_SYNC_POLARITY_SELECT(x) (((x) & 0x1) << 9) +#define G_000330_D1VGA_SYNC_POLARITY_SELECT(x) (((x) >> 9) & 0x1) +#define C_000330_D1VGA_SYNC_POLARITY_SELECT 0xFFFFFDFF +#define S_000330_D1VGA_OVERSCAN_TIMING_SELECT(x) (((x) & 0x1) << 10) +#define G_000330_D1VGA_OVERSCAN_TIMING_SELECT(x) (((x) >> 10) & 0x1) +#define C_000330_D1VGA_OVERSCAN_TIMING_SELECT 0xFFFFFBFF +#define S_000330_D1VGA_OVERSCAN_COLOR_EN(x) (((x) & 0x1) << 16) +#define G_000330_D1VGA_OVERSCAN_COLOR_EN(x) (((x) >> 16) & 0x1) +#define C_000330_D1VGA_OVERSCAN_COLOR_EN 0xFFFEFFFF +#define S_000330_D1VGA_ROTATE(x) (((x) & 0x3) << 24) +#define G_000330_D1VGA_ROTATE(x) (((x) >> 24) & 0x3) +#define C_000330_D1VGA_ROTATE 0xFCFFFFFF +#define R_000338_D2VGA_CONTROL 0x000338 +#define S_000338_D2VGA_MODE_ENABLE(x) (((x) & 0x1) << 0) +#define G_000338_D2VGA_MODE_ENABLE(x) (((x) >> 0) & 0x1) +#define C_000338_D2VGA_MODE_ENABLE 0xFFFFFFFE +#define S_000338_D2VGA_TIMING_SELECT(x) (((x) & 0x1) << 8) +#define G_000338_D2VGA_TIMING_SELECT(x) (((x) >> 8) & 0x1) +#define C_000338_D2VGA_TIMING_SELECT 0xFFFFFEFF +#define S_000338_D2VGA_SYNC_POLARITY_SELECT(x) (((x) & 0x1) << 9) +#define G_000338_D2VGA_SYNC_POLARITY_SELECT(x) (((x) >> 9) & 0x1) +#define C_000338_D2VGA_SYNC_POLARITY_SELECT 0xFFFFFDFF +#define S_000338_D2VGA_OVERSCAN_TIMING_SELECT(x) (((x) & 0x1) << 10) +#define G_000338_D2VGA_OVERSCAN_TIMING_SELECT(x) (((x) >> 10) & 0x1) +#define C_000338_D2VGA_OVERSCAN_TIMING_SELECT 0xFFFFFBFF +#define S_000338_D2VGA_OVERSCAN_COLOR_EN(x) (((x) & 0x1) << 16) +#define G_000338_D2VGA_OVERSCAN_COLOR_EN(x) (((x) >> 16) & 0x1) +#define C_000338_D2VGA_OVERSCAN_COLOR_EN 0xFFFEFFFF +#define S_000338_D2VGA_ROTATE(x) (((x) & 0x3) << 24) +#define G_000338_D2VGA_ROTATE(x) (((x) >> 24) & 0x3) +#define C_000338_D2VGA_ROTATE 0xFCFFFFFF +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_RBBM_HIBUSY(x) (((x) & 0x1) << 28) +#define G_000E40_RBBM_HIBUSY(x) (((x) >> 28) & 0x1) +#define C_000E40_RBBM_HIBUSY 0xEFFFFFFF +#define S_000E40_SKID_CFBUSY(x) (((x) & 0x1) << 29) +#define G_000E40_SKID_CFBUSY(x) (((x) >> 29) & 0x1) +#define C_000E40_SKID_CFBUSY 0xDFFFFFFF +#define S_000E40_VAP_VF_BUSY(x) (((x) & 0x1) << 30) +#define G_000E40_VAP_VF_BUSY(x) (((x) >> 30) & 0x1) +#define C_000E40_VAP_VF_BUSY 0xBFFFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF +#define R_006080_D1CRTC_CONTROL 0x006080 +#define S_006080_D1CRTC_MASTER_EN(x) (((x) & 0x1) << 0) +#define G_006080_D1CRTC_MASTER_EN(x) (((x) >> 0) & 0x1) +#define C_006080_D1CRTC_MASTER_EN 0xFFFFFFFE +#define S_006080_D1CRTC_SYNC_RESET_SEL(x) (((x) & 0x1) << 4) +#define G_006080_D1CRTC_SYNC_RESET_SEL(x) (((x) >> 4) & 0x1) +#define C_006080_D1CRTC_SYNC_RESET_SEL 0xFFFFFFEF +#define S_006080_D1CRTC_DISABLE_POINT_CNTL(x) (((x) & 0x3) << 8) +#define G_006080_D1CRTC_DISABLE_POINT_CNTL(x) (((x) >> 8) & 0x3) +#define C_006080_D1CRTC_DISABLE_POINT_CNTL 0xFFFFFCFF +#define S_006080_D1CRTC_CURRENT_MASTER_EN_STATE(x) (((x) & 0x1) << 16) +#define G_006080_D1CRTC_CURRENT_MASTER_EN_STATE(x) (((x) >> 16) & 0x1) +#define C_006080_D1CRTC_CURRENT_MASTER_EN_STATE 0xFFFEFFFF +#define S_006080_D1CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) & 0x1) << 24) +#define G_006080_D1CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) >> 24) & 0x1) +#define C_006080_D1CRTC_DISP_READ_REQUEST_DISABLE 0xFEFFFFFF +#define R_0060E8_D1CRTC_UPDATE_LOCK 0x0060E8 +#define S_0060E8_D1CRTC_UPDATE_LOCK(x) (((x) & 0x1) << 0) +#define G_0060E8_D1CRTC_UPDATE_LOCK(x) (((x) >> 0) & 0x1) +#define C_0060E8_D1CRTC_UPDATE_LOCK 0xFFFFFFFE +#define R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x006110 +#define S_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x00000000 +#define R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x006118 +#define S_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x00000000 +#define R_006880_D2CRTC_CONTROL 0x006880 +#define S_006880_D2CRTC_MASTER_EN(x) (((x) & 0x1) << 0) +#define G_006880_D2CRTC_MASTER_EN(x) (((x) >> 0) & 0x1) +#define C_006880_D2CRTC_MASTER_EN 0xFFFFFFFE +#define S_006880_D2CRTC_SYNC_RESET_SEL(x) (((x) & 0x1) << 4) +#define G_006880_D2CRTC_SYNC_RESET_SEL(x) (((x) >> 4) & 0x1) +#define C_006880_D2CRTC_SYNC_RESET_SEL 0xFFFFFFEF +#define S_006880_D2CRTC_DISABLE_POINT_CNTL(x) (((x) & 0x3) << 8) +#define G_006880_D2CRTC_DISABLE_POINT_CNTL(x) (((x) >> 8) & 0x3) +#define C_006880_D2CRTC_DISABLE_POINT_CNTL 0xFFFFFCFF +#define S_006880_D2CRTC_CURRENT_MASTER_EN_STATE(x) (((x) & 0x1) << 16) +#define G_006880_D2CRTC_CURRENT_MASTER_EN_STATE(x) (((x) >> 16) & 0x1) +#define C_006880_D2CRTC_CURRENT_MASTER_EN_STATE 0xFFFEFFFF +#define S_006880_D2CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) & 0x1) << 24) +#define G_006880_D2CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) >> 24) & 0x1) +#define C_006880_D2CRTC_DISP_READ_REQUEST_DISABLE 0xFEFFFFFF +#define R_0068E8_D2CRTC_UPDATE_LOCK 0x0068E8 +#define S_0068E8_D2CRTC_UPDATE_LOCK(x) (((x) & 0x1) << 0) +#define G_0068E8_D2CRTC_UPDATE_LOCK(x) (((x) >> 0) & 0x1) +#define C_0068E8_D2CRTC_UPDATE_LOCK 0xFFFFFFFE +#define R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x006910 +#define S_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x00000000 +#define R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x006918 +#define S_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) +#define G_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x00000000 + + +#define R_000001_MC_FB_LOCATION 0x000001 +#define S_000001_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000001_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000001_MC_FB_START 0xFFFF0000 +#define S_000001_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000001_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000001_MC_FB_TOP 0x0000FFFF +#define R_000002_MC_AGP_LOCATION 0x000002 +#define S_000002_MC_AGP_START(x) (((x) & 0xFFFF) << 0) +#define G_000002_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) +#define C_000002_MC_AGP_START 0xFFFF0000 +#define S_000002_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000002_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000002_MC_AGP_TOP 0x0000FFFF +#define R_000003_MC_AGP_BASE 0x000003 +#define S_000003_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000003_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000003_AGP_BASE_ADDR 0x00000000 +#define R_000004_MC_AGP_BASE_2 0x000004 +#define S_000004_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) +#define G_000004_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) +#define C_000004_AGP_BASE_ADDR_2 0xFFFFFFF0 + + +#define R_00000F_CP_DYN_CNTL 0x00000F +#define S_00000F_CP_FORCEON(x) (((x) & 0x1) << 0) +#define G_00000F_CP_FORCEON(x) (((x) >> 0) & 0x1) +#define C_00000F_CP_FORCEON 0xFFFFFFFE +#define S_00000F_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1) +#define G_00000F_CP_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1) +#define C_00000F_CP_MAX_DYN_STOP_LAT 0xFFFFFFFD +#define S_00000F_CP_CLOCK_STATUS(x) (((x) & 0x1) << 2) +#define G_00000F_CP_CLOCK_STATUS(x) (((x) >> 2) & 0x1) +#define C_00000F_CP_CLOCK_STATUS 0xFFFFFFFB +#define S_00000F_CP_PROG_SHUTOFF(x) (((x) & 0x1) << 3) +#define G_00000F_CP_PROG_SHUTOFF(x) (((x) >> 3) & 0x1) +#define C_00000F_CP_PROG_SHUTOFF 0xFFFFFFF7 +#define S_00000F_CP_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4) +#define G_00000F_CP_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF) +#define C_00000F_CP_PROG_DELAY_VALUE 0xFFFFF00F +#define S_00000F_CP_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12) +#define G_00000F_CP_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF) +#define C_00000F_CP_LOWER_POWER_IDLE 0xFFF00FFF +#define S_00000F_CP_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20) +#define G_00000F_CP_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1) +#define C_00000F_CP_LOWER_POWER_IGNORE 0xFFEFFFFF +#define S_00000F_CP_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21) +#define G_00000F_CP_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1) +#define C_00000F_CP_NORMAL_POWER_IGNORE 0xFFDFFFFF +#define S_00000F_SPARE(x) (((x) & 0x3) << 22) +#define G_00000F_SPARE(x) (((x) >> 22) & 0x3) +#define C_00000F_SPARE 0xFF3FFFFF +#define S_00000F_CP_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24) +#define G_00000F_CP_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF) +#define C_00000F_CP_NORMAL_POWER_BUSY 0x00FFFFFF +#define R_000011_E2_DYN_CNTL 0x000011 +#define S_000011_E2_FORCEON(x) (((x) & 0x1) << 0) +#define G_000011_E2_FORCEON(x) (((x) >> 0) & 0x1) +#define C_000011_E2_FORCEON 0xFFFFFFFE +#define S_000011_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1) +#define G_000011_E2_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1) +#define C_000011_E2_MAX_DYN_STOP_LAT 0xFFFFFFFD +#define S_000011_E2_CLOCK_STATUS(x) (((x) & 0x1) << 2) +#define G_000011_E2_CLOCK_STATUS(x) (((x) >> 2) & 0x1) +#define C_000011_E2_CLOCK_STATUS 0xFFFFFFFB +#define S_000011_E2_PROG_SHUTOFF(x) (((x) & 0x1) << 3) +#define G_000011_E2_PROG_SHUTOFF(x) (((x) >> 3) & 0x1) +#define C_000011_E2_PROG_SHUTOFF 0xFFFFFFF7 +#define S_000011_E2_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4) +#define G_000011_E2_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF) +#define C_000011_E2_PROG_DELAY_VALUE 0xFFFFF00F +#define S_000011_E2_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12) +#define G_000011_E2_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF) +#define C_000011_E2_LOWER_POWER_IDLE 0xFFF00FFF +#define S_000011_E2_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20) +#define G_000011_E2_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1) +#define C_000011_E2_LOWER_POWER_IGNORE 0xFFEFFFFF +#define S_000011_E2_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21) +#define G_000011_E2_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1) +#define C_000011_E2_NORMAL_POWER_IGNORE 0xFFDFFFFF +#define S_000011_SPARE(x) (((x) & 0x3) << 22) +#define G_000011_SPARE(x) (((x) >> 22) & 0x3) +#define C_000011_SPARE 0xFF3FFFFF +#define S_000011_E2_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24) +#define G_000011_E2_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF) +#define C_000011_E2_NORMAL_POWER_BUSY 0x00FFFFFF +#define R_000013_IDCT_DYN_CNTL 0x000013 +#define S_000013_IDCT_FORCEON(x) (((x) & 0x1) << 0) +#define G_000013_IDCT_FORCEON(x) (((x) >> 0) & 0x1) +#define C_000013_IDCT_FORCEON 0xFFFFFFFE +#define S_000013_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1) +#define G_000013_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1) +#define C_000013_IDCT_MAX_DYN_STOP_LAT 0xFFFFFFFD +#define S_000013_IDCT_CLOCK_STATUS(x) (((x) & 0x1) << 2) +#define G_000013_IDCT_CLOCK_STATUS(x) (((x) >> 2) & 0x1) +#define C_000013_IDCT_CLOCK_STATUS 0xFFFFFFFB +#define S_000013_IDCT_PROG_SHUTOFF(x) (((x) & 0x1) << 3) +#define G_000013_IDCT_PROG_SHUTOFF(x) (((x) >> 3) & 0x1) +#define C_000013_IDCT_PROG_SHUTOFF 0xFFFFFFF7 +#define S_000013_IDCT_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4) +#define G_000013_IDCT_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF) +#define C_000013_IDCT_PROG_DELAY_VALUE 0xFFFFF00F +#define S_000013_IDCT_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12) +#define G_000013_IDCT_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF) +#define C_000013_IDCT_LOWER_POWER_IDLE 0xFFF00FFF +#define S_000013_IDCT_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20) +#define G_000013_IDCT_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1) +#define C_000013_IDCT_LOWER_POWER_IGNORE 0xFFEFFFFF +#define S_000013_IDCT_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21) +#define G_000013_IDCT_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1) +#define C_000013_IDCT_NORMAL_POWER_IGNORE 0xFFDFFFFF +#define S_000013_SPARE(x) (((x) & 0x3) << 22) +#define G_000013_SPARE(x) (((x) >> 22) & 0x3) +#define C_000013_SPARE 0xFF3FFFFF +#define S_000013_IDCT_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24) +#define G_000013_IDCT_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF) +#define C_000013_IDCT_NORMAL_POWER_BUSY 0x00FFFFFF + +#endif diff --git a/sys/dev/drm2/radeon/rv770.c b/sys/dev/drm2/radeon/rv770.c new file mode 100644 index 00000000000..cb875bd9da9 --- /dev/null +++ b/sys/dev/drm2/radeon/rv770.c @@ -0,0 +1,1297 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include +#include "rv770d.h" +#include "atom.h" +#include "avivod.h" + +#define R700_PFP_UCODE_SIZE 848 +#define R700_PM4_UCODE_SIZE 1360 + +static void rv770_gpu_init(struct radeon_device *rdev); +static void rv770_pcie_gen2_enable(struct radeon_device *rdev); + +u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; + + /* Lock the graphics update lock */ + tmp |= AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* update the scanout addresses */ + if (radeon_crtc->crtc_id) { + WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + } else { + WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + } + WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + /* Wait for update_pending to go high. */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) + break; + DRM_UDELAY(1); + } + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; +} + +/* get temperature in millidegrees */ +int rv770_get_temp(struct radeon_device *rdev) +{ + u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> + ASIC_T_SHIFT; + int actual_temp; + + if (temp & 0x400) + actual_temp = -256; + else if (temp & 0x200) + actual_temp = 255; + else if (temp & 0x100) { + actual_temp = temp & 0x1ff; + actual_temp |= ~0x1ff; + } else + actual_temp = temp & 0xff; + + return (actual_temp * 1000) / 2; +} + +void rv770_pm_misc(struct radeon_device *rdev) +{ + int req_ps_idx = rdev->pm.requested_power_state_index; + int req_cm_idx = rdev->pm.requested_clock_mode_index; + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: v: %d\n", voltage->voltage); + } + } +} + +/* + * GART + */ +static int rv770_pcie_gart_enable(struct radeon_device *rdev) +{ + u32 tmp; + int r, i; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); + /* Setup TLB control */ + tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); + WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + if (rdev->family == CHIP_RV740) + WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); + WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); + WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + for (i = 1; i < 7; i++) + WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); + + r600_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +static void rv770_pcie_gart_disable(struct radeon_device *rdev) +{ + u32 tmp; + int i; + + /* Disable all tables */ + for (i = 0; i < 7; i++) + WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); + + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); + /* Setup TLB control */ + tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); + WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + radeon_gart_table_vram_unpin(rdev); +} + +static void rv770_pcie_gart_fini(struct radeon_device *rdev) +{ + radeon_gart_fini(rdev); + rv770_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); +} + + +static void rv770_agp_enable(struct radeon_device *rdev) +{ + u32 tmp; + int i; + + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); + /* Setup TLB control */ + tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); + WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + for (i = 0; i < 7; i++) + WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); +} + +static void rv770_mc_program(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + u32 tmp; + int i, j; + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + /* r7xx hw bug. Read from HDP_DEBUG1 rather + * than writing to HDP_REG_COHERENCY_FLUSH_CNTL + */ + tmp = RREG32(HDP_DEBUG1); + + rv515_mc_stop(rdev, &save); + if (r600_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Lockout access through VGA aperture*/ + WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); + /* Update configuration */ + if (rdev->flags & RADEON_IS_AGP) { + if (rdev->mc.vram_start < rdev->mc.gtt_start) { + /* VRAM before AGP */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.gtt_end >> 12); + } else { + /* VRAM after AGP */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.gtt_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.vram_end >> 12); + } + } else { + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.vram_end >> 12); + } + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); + tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; + tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); + WREG32(MC_VM_FB_LOCATION, tmp); + WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); + WREG32(HDP_NONSURFACE_INFO, (2 << 7)); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); + if (rdev->flags & RADEON_IS_AGP) { + WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16); + WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); + WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); + } else { + WREG32(MC_VM_AGP_BASE, 0); + WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); + WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); + } + if (r600_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + rv515_mc_resume(rdev, &save); + /* we need to own VRAM, so turn off the VGA renderer here + * to stop it overwriting our objects */ + rv515_vga_render_disable(rdev); +} + + +/* + * CP. + */ +void r700_cp_stop(struct radeon_device *rdev) +{ + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); + WREG32(SCRATCH_UMSK, 0); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; +} + +static int rv770_cp_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + int i; + + if (!rdev->me_fw || !rdev->pfp_fw) + return -EINVAL; + + r700_cp_stop(rdev); + WREG32(CP_RB_CNTL, +#ifdef __BIG_ENDIAN + BUF_SWAP_32BIT | +#endif + RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3)); + + /* Reset cp */ + WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); + RREG32(GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(GRBM_SOFT_RESET, 0); + + fw_data = (const __be32 *)rdev->pfp_fw->data; + WREG32(CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < R700_PFP_UCODE_SIZE; i++) + WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); + WREG32(CP_PFP_UCODE_ADDR, 0); + + fw_data = (const __be32 *)rdev->me_fw->data; + WREG32(CP_ME_RAM_WADDR, 0); + for (i = 0; i < R700_PM4_UCODE_SIZE; i++) + WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); + + WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_RADDR, 0); + return 0; +} + +void r700_cp_fini(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r700_cp_stop(rdev); + radeon_ring_fini(rdev, ring); + radeon_scratch_free(rdev, ring->rptr_save_reg); +} + +/* + * Core functions + */ +static void rv770_gpu_init(struct radeon_device *rdev) +{ + int i, j, num_qd_pipes; + u32 ta_aux_cntl; + u32 sx_debug_1; + u32 smx_dc_ctl0; + u32 db_debug3; + u32 num_gs_verts_per_thread; + u32 vgt_gs_per_es; + u32 gs_prim_buffer_depth = 0; + u32 sq_ms_fifo_sizes; + u32 sq_config; + u32 sq_thread_resource_mgmt; + u32 hdp_host_path_cntl; + u32 sq_dyn_gpr_size_simd_ab_0; + u32 gb_tiling_config = 0; + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_pipe_config = 0; + u32 mc_arb_ramcfg; + u32 db_debug4, tmp; + u32 inactive_pipes, shader_pipe_config; + u32 disabled_rb_mask; + unsigned active_number; + + /* setup chip specs */ + rdev->config.rv770.tiling_group_size = 256; + switch (rdev->family) { + case CHIP_RV770: + rdev->config.rv770.max_pipes = 4; + rdev->config.rv770.max_tile_pipes = 8; + rdev->config.rv770.max_simds = 10; + rdev->config.rv770.max_backends = 4; + rdev->config.rv770.max_gprs = 256; + rdev->config.rv770.max_threads = 248; + rdev->config.rv770.max_stack_entries = 512; + rdev->config.rv770.max_hw_contexts = 8; + rdev->config.rv770.max_gs_threads = 16 * 2; + rdev->config.rv770.sx_max_export_size = 128; + rdev->config.rv770.sx_max_export_pos_size = 16; + rdev->config.rv770.sx_max_export_smx_size = 112; + rdev->config.rv770.sq_num_cf_insts = 2; + + rdev->config.rv770.sx_num_of_sets = 7; + rdev->config.rv770.sc_prim_fifo_size = 0xF9; + rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; + rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; + break; + case CHIP_RV730: + rdev->config.rv770.max_pipes = 2; + rdev->config.rv770.max_tile_pipes = 4; + rdev->config.rv770.max_simds = 8; + rdev->config.rv770.max_backends = 2; + rdev->config.rv770.max_gprs = 128; + rdev->config.rv770.max_threads = 248; + rdev->config.rv770.max_stack_entries = 256; + rdev->config.rv770.max_hw_contexts = 8; + rdev->config.rv770.max_gs_threads = 16 * 2; + rdev->config.rv770.sx_max_export_size = 256; + rdev->config.rv770.sx_max_export_pos_size = 32; + rdev->config.rv770.sx_max_export_smx_size = 224; + rdev->config.rv770.sq_num_cf_insts = 2; + + rdev->config.rv770.sx_num_of_sets = 7; + rdev->config.rv770.sc_prim_fifo_size = 0xf9; + rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; + rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; + if (rdev->config.rv770.sx_max_export_pos_size > 16) { + rdev->config.rv770.sx_max_export_pos_size -= 16; + rdev->config.rv770.sx_max_export_smx_size += 16; + } + break; + case CHIP_RV710: + rdev->config.rv770.max_pipes = 2; + rdev->config.rv770.max_tile_pipes = 2; + rdev->config.rv770.max_simds = 2; + rdev->config.rv770.max_backends = 1; + rdev->config.rv770.max_gprs = 256; + rdev->config.rv770.max_threads = 192; + rdev->config.rv770.max_stack_entries = 256; + rdev->config.rv770.max_hw_contexts = 4; + rdev->config.rv770.max_gs_threads = 8 * 2; + rdev->config.rv770.sx_max_export_size = 128; + rdev->config.rv770.sx_max_export_pos_size = 16; + rdev->config.rv770.sx_max_export_smx_size = 112; + rdev->config.rv770.sq_num_cf_insts = 1; + + rdev->config.rv770.sx_num_of_sets = 7; + rdev->config.rv770.sc_prim_fifo_size = 0x40; + rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; + rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; + break; + case CHIP_RV740: + rdev->config.rv770.max_pipes = 4; + rdev->config.rv770.max_tile_pipes = 4; + rdev->config.rv770.max_simds = 8; + rdev->config.rv770.max_backends = 4; + rdev->config.rv770.max_gprs = 256; + rdev->config.rv770.max_threads = 248; + rdev->config.rv770.max_stack_entries = 512; + rdev->config.rv770.max_hw_contexts = 8; + rdev->config.rv770.max_gs_threads = 16 * 2; + rdev->config.rv770.sx_max_export_size = 256; + rdev->config.rv770.sx_max_export_pos_size = 32; + rdev->config.rv770.sx_max_export_smx_size = 224; + rdev->config.rv770.sq_num_cf_insts = 2; + + rdev->config.rv770.sx_num_of_sets = 7; + rdev->config.rv770.sc_prim_fifo_size = 0x100; + rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; + rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; + + if (rdev->config.rv770.sx_max_export_pos_size > 16) { + rdev->config.rv770.sx_max_export_pos_size -= 16; + rdev->config.rv770.sx_max_export_smx_size += 16; + } + break; + default: + break; + } + + /* Initialize HDP */ + j = 0; + for (i = 0; i < 32; i++) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + j += 0x18; + } + + WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); + + /* setup tiling, simd, pipe config */ + mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + + shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); + inactive_pipes = (shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; + for (i = 0, tmp = 1, active_number = 0; i < R7XX_MAX_PIPES; i++) { + if (!(inactive_pipes & tmp)) { + active_number++; + } + tmp <<= 1; + } + if (active_number == 1) { + WREG32(SPI_CONFIG_CNTL, DISABLE_INTERP_1); + } else { + WREG32(SPI_CONFIG_CNTL, 0); + } + + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; + tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16); + if (tmp < rdev->config.rv770.max_backends) { + rdev->config.rv770.max_backends = tmp; + } + + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK); + if (tmp < rdev->config.rv770.max_pipes) { + rdev->config.rv770.max_pipes = tmp; + } + tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); + if (tmp < rdev->config.rv770.max_simds) { + rdev->config.rv770.max_simds = tmp; + } + + switch (rdev->config.rv770.max_tile_pipes) { + case 1: + default: + gb_tiling_config = PIPE_TILING(0); + break; + case 2: + gb_tiling_config = PIPE_TILING(1); + break; + case 4: + gb_tiling_config = PIPE_TILING(2); + break; + case 8: + gb_tiling_config = PIPE_TILING(3); + break; + } + rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes; + + disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK; + tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; + tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends, + R7XX_MAX_BACKENDS, disabled_rb_mask); + gb_tiling_config |= tmp << 16; + rdev->config.rv770.backend_map = tmp; + + if (rdev->family == CHIP_RV770) + gb_tiling_config |= BANK_TILING(1); + else { + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + gb_tiling_config |= BANK_TILING(1); + else + gb_tiling_config |= BANK_TILING(0); + } + rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); + gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) { + gb_tiling_config |= ROW_TILING(3); + gb_tiling_config |= SAMPLE_SPLIT(3); + } else { + gb_tiling_config |= + ROW_TILING(((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT)); + gb_tiling_config |= + SAMPLE_SPLIT(((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT)); + } + + gb_tiling_config |= BANK_SWAPS(1); + rdev->config.rv770.tile_config = gb_tiling_config; + + WREG32(GB_TILING_CONFIG, gb_tiling_config); + WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + WREG32(DMA_TILING_CONFIG, (gb_tiling_config & 0xffff)); + WREG32(DMA_TILING_CONFIG2, (gb_tiling_config & 0xffff)); + + WREG32(CGTS_SYS_TCC_DISABLE, 0); + WREG32(CGTS_TCC_DISABLE, 0); + WREG32(CGTS_USER_SYS_TCC_DISABLE, 0); + WREG32(CGTS_USER_TCC_DISABLE, 0); + + + num_qd_pipes = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); + WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK); + WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK); + + /* set HW defaults for 3D engine */ + WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | + ROQ_IB2_START(0x2b))); + + WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30)); + + ta_aux_cntl = RREG32(TA_CNTL_AUX); + WREG32(TA_CNTL_AUX, ta_aux_cntl | DISABLE_CUBE_ANISO); + + sx_debug_1 = RREG32(SX_DEBUG_1); + sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; + WREG32(SX_DEBUG_1, sx_debug_1); + + smx_dc_ctl0 = RREG32(SMX_DC_CTL0); + smx_dc_ctl0 &= ~CACHE_DEPTH(0x1ff); + smx_dc_ctl0 |= CACHE_DEPTH((rdev->config.rv770.sx_num_of_sets * 64) - 1); + WREG32(SMX_DC_CTL0, smx_dc_ctl0); + + if (rdev->family != CHIP_RV740) + WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) | + GS_FLUSH_CTL(4) | + ACK_FLUSH_CTL(3) | + SYNC_FLUSH_CTL)); + + if (rdev->family != CHIP_RV770) + WREG32(SMX_SAR_CTL0, 0x00003f3f); + + db_debug3 = RREG32(DB_DEBUG3); + db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f); + switch (rdev->family) { + case CHIP_RV770: + case CHIP_RV740: + db_debug3 |= DB_CLK_OFF_DELAY(0x1f); + break; + case CHIP_RV710: + case CHIP_RV730: + default: + db_debug3 |= DB_CLK_OFF_DELAY(2); + break; + } + WREG32(DB_DEBUG3, db_debug3); + + if (rdev->family != CHIP_RV770) { + db_debug4 = RREG32(DB_DEBUG4); + db_debug4 |= DISABLE_TILE_COVERED_FOR_PS_ITER; + WREG32(DB_DEBUG4, db_debug4); + } + + WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.rv770.sx_max_export_size / 4) - 1) | + POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) | + SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1))); + + WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.rv770.sc_prim_fifo_size) | + SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) | + SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize))); + + WREG32(PA_SC_MULTI_CHIP_CNTL, 0); + + WREG32(VGT_NUM_INSTANCES, 1); + + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); + + WREG32(CP_PERFMON_CNTL, 0); + + sq_ms_fifo_sizes = (CACHE_FIFO_SIZE(16 * rdev->config.rv770.sq_num_cf_insts) | + DONE_FIFO_HIWATER(0xe0) | + ALU_UPDATE_FIFO_HIWATER(0x8)); + switch (rdev->family) { + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1); + break; + case CHIP_RV740: + default: + sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x4); + break; + } + WREG32(SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes); + + /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT + * should be adjusted as needed by the 2D/3D drivers. This just sets default values + */ + sq_config = RREG32(SQ_CONFIG); + sq_config &= ~(PS_PRIO(3) | + VS_PRIO(3) | + GS_PRIO(3) | + ES_PRIO(3)); + sq_config |= (DX9_CONSTS | + VC_ENABLE | + EXPORT_SRC_C | + PS_PRIO(0) | + VS_PRIO(1) | + GS_PRIO(2) | + ES_PRIO(3)); + if (rdev->family == CHIP_RV710) + /* no vertex cache */ + sq_config &= ~VC_ENABLE; + + WREG32(SQ_CONFIG, sq_config); + + WREG32(SQ_GPR_RESOURCE_MGMT_1, (NUM_PS_GPRS((rdev->config.rv770.max_gprs * 24)/64) | + NUM_VS_GPRS((rdev->config.rv770.max_gprs * 24)/64) | + NUM_CLAUSE_TEMP_GPRS(((rdev->config.rv770.max_gprs * 24)/64)/2))); + + WREG32(SQ_GPR_RESOURCE_MGMT_2, (NUM_GS_GPRS((rdev->config.rv770.max_gprs * 7)/64) | + NUM_ES_GPRS((rdev->config.rv770.max_gprs * 7)/64))); + + sq_thread_resource_mgmt = (NUM_PS_THREADS((rdev->config.rv770.max_threads * 4)/8) | + NUM_VS_THREADS((rdev->config.rv770.max_threads * 2)/8) | + NUM_ES_THREADS((rdev->config.rv770.max_threads * 1)/8)); + if (((rdev->config.rv770.max_threads * 1) / 8) > rdev->config.rv770.max_gs_threads) + sq_thread_resource_mgmt |= NUM_GS_THREADS(rdev->config.rv770.max_gs_threads); + else + sq_thread_resource_mgmt |= NUM_GS_THREADS((rdev->config.rv770.max_gs_threads * 1)/8); + WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); + + WREG32(SQ_STACK_RESOURCE_MGMT_1, (NUM_PS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4) | + NUM_VS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4))); + + WREG32(SQ_STACK_RESOURCE_MGMT_2, (NUM_GS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4) | + NUM_ES_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4))); + + sq_dyn_gpr_size_simd_ab_0 = (SIMDA_RING0((rdev->config.rv770.max_gprs * 38)/64) | + SIMDA_RING1((rdev->config.rv770.max_gprs * 38)/64) | + SIMDB_RING0((rdev->config.rv770.max_gprs * 38)/64) | + SIMDB_RING1((rdev->config.rv770.max_gprs * 38)/64)); + + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0); + WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0); + + WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | + FORCE_EOV_MAX_REZ_CNT(255))); + + if (rdev->family == CHIP_RV710) + WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(TC_ONLY) | + AUTO_INVLD_EN(ES_AND_GS_AUTO))); + else + WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(VC_AND_TC) | + AUTO_INVLD_EN(ES_AND_GS_AUTO))); + + switch (rdev->family) { + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV740: + gs_prim_buffer_depth = 384; + break; + case CHIP_RV710: + gs_prim_buffer_depth = 128; + break; + default: + break; + } + + num_gs_verts_per_thread = rdev->config.rv770.max_pipes * 16; + vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread; + /* Max value for this is 256 */ + if (vgt_gs_per_es > 256) + vgt_gs_per_es = 256; + + WREG32(VGT_ES_PER_GS, 128); + WREG32(VGT_GS_PER_ES, vgt_gs_per_es); + WREG32(VGT_GS_PER_VS, 2); + + /* more default values. 2D/3D driver should adjust as needed */ + WREG32(VGT_GS_VERTEX_REUSE, 16); + WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + WREG32(VGT_STRMOUT_EN, 0); + WREG32(SX_MISC, 0); + WREG32(PA_SC_MODE_CNTL, 0); + WREG32(PA_SC_EDGERULE, 0xaaaaaaaa); + WREG32(PA_SC_AA_CONFIG, 0); + WREG32(PA_SC_CLIPRECT_RULE, 0xffff); + WREG32(PA_SC_LINE_STIPPLE, 0); + WREG32(SPI_INPUT_Z, 0); + WREG32(SPI_PS_IN_CONTROL_0, NUM_INTERP(2)); + WREG32(CB_COLOR7_FRAG, 0); + + /* clear render buffer base addresses */ + WREG32(CB_COLOR0_BASE, 0); + WREG32(CB_COLOR1_BASE, 0); + WREG32(CB_COLOR2_BASE, 0); + WREG32(CB_COLOR3_BASE, 0); + WREG32(CB_COLOR4_BASE, 0); + WREG32(CB_COLOR5_BASE, 0); + WREG32(CB_COLOR6_BASE, 0); + WREG32(CB_COLOR7_BASE, 0); + + WREG32(TCP_CNTL, 0); + + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + WREG32(PA_SC_MULTI_CHIP_CNTL, 0); + + WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | + NUM_CLIP_SEQ(3))); + WREG32(VC_ENHANCE, 0); +} + +void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +{ + u64 size_bf, size_af; + + if (mc->mc_vram_size > 0xE0000000) { + /* leave room for at least 512M GTT */ + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = 0xE0000000; + mc->mc_vram_size = 0xE0000000; + } + if (rdev->flags & RADEON_IS_AGP) { + size_bf = mc->gtt_start; + size_af = 0xFFFFFFFF - mc->gtt_end; + if (size_bf > size_af) { + if (mc->mc_vram_size > size_bf) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_bf; + mc->mc_vram_size = size_bf; + } + mc->vram_start = mc->gtt_start - mc->mc_vram_size; + } else { + if (mc->mc_vram_size > size_af) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_af; + mc->mc_vram_size = size_af; + } + mc->vram_start = mc->gtt_end + 1; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %juM 0x%08jX - 0x%08jX (%juM used)\n", + (uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start, + (uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20); + } else { + radeon_vram_location(rdev, &rdev->mc, 0); + rdev->mc.gtt_base_align = 0; + radeon_gtt_location(rdev, mc); + } +} + +static int rv770_mc_init(struct radeon_device *rdev) +{ + u32 tmp; + int chansize, numchan; + + /* Get VRAM informations */ + rdev->mc.vram_is_ddr = true; + tmp = RREG32(MC_ARB_RAMCFG); + if (tmp & CHANSIZE_OVERRIDE) { + chansize = 16; + } else if (tmp & CHANSIZE_MASK) { + chansize = 64; + } else { + chansize = 32; + } + tmp = RREG32(MC_SHARED_CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + numchan = 1; + break; + case 1: + numchan = 2; + break; + case 2: + numchan = 4; + break; + case 3: + numchan = 8; + break; + } + rdev->mc.vram_width = numchan * chansize; + /* Could aper size report 0 ? */ + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + /* Setup GPU memory space */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.visible_vram_size = rdev->mc.aper_size; + r700_vram_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); + + return 0; +} + +/** + * rv770_copy_dma - copy pages using the DMA engine + * + * @rdev: radeon_device pointer + * @src_offset: src GPU address + * @dst_offset: dst GPU address + * @num_gpu_pages: number of GPU pages to xfer + * @fence: radeon fence object + * + * Copy GPU paging using the DMA engine (r7xx). + * Used by the radeon ttm implementation to move pages if + * registered as the asic copy callback. + */ +int rv770_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_semaphore *sem = NULL; + int ring_index = rdev->asic->copy.dma_ring_index; + struct radeon_ring *ring = &rdev->ring[ring_index]; + u32 size_in_dw, cur_size_in_dw; + int i, num_loops; + int r = 0; + + r = radeon_semaphore_create(rdev, &sem); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + + size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4; + num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFF); + r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + radeon_semaphore_free(rdev, &sem, NULL); + return r; + } + + if (radeon_fence_need_sync(*fence, ring->idx)) { + radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, + ring->idx); + radeon_fence_note_sync(*fence, ring->idx); + } else { + radeon_semaphore_free(rdev, &sem, NULL); + } + + for (i = 0; i < num_loops; i++) { + cur_size_in_dw = size_in_dw; + if (cur_size_in_dw > 0xFFFF) + cur_size_in_dw = 0xFFFF; + size_in_dw -= cur_size_in_dw; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw)); + radeon_ring_write(ring, dst_offset & 0xfffffffc); + radeon_ring_write(ring, src_offset & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); + radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff); + src_offset += cur_size_in_dw * 4; + dst_offset += cur_size_in_dw * 4; + } + + r = radeon_fence_emit(rdev, fence, ring->idx); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + + radeon_ring_unlock_commit(rdev, ring); + radeon_semaphore_free(rdev, &sem, *fence); + + return r; +} + +static int rv770_startup(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + int r; + + /* enable pcie gen2 link */ + rv770_pcie_gen2_enable(rdev); + + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + r = r600_vram_scratch_init(rdev); + if (r) + return r; + + rv770_mc_program(rdev); + if (rdev->flags & RADEON_IS_AGP) { + rv770_agp_enable(rdev); + } else { + r = rv770_pcie_gart_enable(rdev); + if (r) + return r; + } + + rv770_gpu_init(rdev); + r = r600_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); + rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + r600_irq_set(rdev); + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, + R600_CP_RB_RPTR, R600_CP_RB_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, + DMA_RB_RPTR, DMA_RB_WPTR, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); + if (r) + return r; + + r = rv770_cp_load_microcode(rdev); + if (r) + return r; + r = r600_cp_resume(rdev); + if (r) + return r; + + r = r600_dma_resume(rdev); + if (r) + return r; + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = r600_audio_init(rdev); + if (r) { + DRM_ERROR("radeon: audio init failed\n"); + return r; + } + + return 0; +} + +int rv770_resume(struct radeon_device *rdev) +{ + int r; + + /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, + * posting will perform necessary task to bring back GPU into good + * shape. + */ + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + + rdev->accel_working = true; + r = rv770_startup(rdev); + if (r) { + DRM_ERROR("r600 startup failed on resume\n"); + rdev->accel_working = false; + return r; + } + + return r; + +} + +int rv770_suspend(struct radeon_device *rdev) +{ + r600_audio_fini(rdev); + r700_cp_stop(rdev); + r600_dma_stop(rdev); + r600_irq_suspend(rdev); + radeon_wb_disable(rdev); + rv770_pcie_gart_disable(rdev); + + return 0; +} + +/* Plan is to move initialization in that function and use + * helper function so that radeon_device_init pretty much + * do nothing more than calling asic specific function. This + * should also allow to remove a bunch of callback function + * like vram_info. + */ +int rv770_init(struct radeon_device *rdev) +{ + int r; + + /* Read BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); + if (r) + return r; + /* Post card if necessary */ + if (!radeon_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize scratch registers */ + r600_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + /* initialize AGP */ + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + radeon_agp_disable(rdev); + } + r = rv770_mc_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); + + rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); + + r = r600_pcie_gart_init(rdev); + if (r) + return r; + + rdev->accel_working = true; + r = rv770_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + r700_cp_fini(rdev); + r600_dma_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + rv770_pcie_gart_fini(rdev); + rdev->accel_working = false; + } + + return 0; +} + +void rv770_fini(struct radeon_device *rdev) +{ + r600_blit_fini(rdev); + r700_cp_fini(rdev); + r600_dma_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + rv770_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_agp_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + r600_fini_microcode(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +static void rv770_pcie_gen2_enable(struct radeon_device *rdev) +{ + u32 link_width_cntl, lanes, speed_cntl, tmp; + u16 link_cntl2; + u32 mask; + int ret; + + if (radeon_pcie_gen2 == 0) + return; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + /* x2 cards have a special sequence */ + if (ASIC_IS_X2(rdev)) + return; + + ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); + if (ret != 0) + return; + + if (!(mask & DRM_PCIE_SPEED_50)) + return; + + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); + + /* advertise upconfig capability */ + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + link_width_cntl &= ~LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { + lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; + link_width_cntl &= ~(LC_LINK_WIDTH_MASK | + LC_RECONFIG_ARC_MISSING_ESCAPE); + link_width_cntl |= lanes | LC_RECONFIG_NOW | + LC_RENEGOTIATE_EN | LC_UPCONFIGURE_SUPPORT; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } else { + link_width_cntl |= LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && + (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { + + tmp = RREG32(0x541c); + WREG32(0x541c, tmp | 0x8); + WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); + link_cntl2 = RREG16(0x4088); + link_cntl2 &= ~TARGET_LINK_SPEED_MASK; + link_cntl2 |= 0x2; + WREG16(0x4088, link_cntl2); + WREG32(MM_CFGREGS_CNTL, 0); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + speed_cntl |= LC_GEN2_EN_STRAP; + WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); + + } else { + link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); + /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ + if (1) + link_width_cntl |= LC_UPCONFIGURE_DIS; + else + link_width_cntl &= ~LC_UPCONFIGURE_DIS; + WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); + } +} diff --git a/sys/dev/drm2/radeon/rv770d.h b/sys/dev/drm2/radeon/rv770d.h new file mode 100644 index 00000000000..1f2c23c554f --- /dev/null +++ b/sys/dev/drm2/radeon/rv770d.h @@ -0,0 +1,673 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef RV770_H +#define RV770_H + +#include +__FBSDID("$FreeBSD$"); + +#define R7XX_MAX_SH_GPRS 256 +#define R7XX_MAX_TEMP_GPRS 16 +#define R7XX_MAX_SH_THREADS 256 +#define R7XX_MAX_SH_STACK_ENTRIES 4096 +#define R7XX_MAX_BACKENDS 8 +#define R7XX_MAX_BACKENDS_MASK 0xff +#define R7XX_MAX_SIMDS 16 +#define R7XX_MAX_SIMDS_MASK 0xffff +#define R7XX_MAX_PIPES 8 +#define R7XX_MAX_PIPES_MASK 0xff + +/* Registers */ +#define CB_COLOR0_BASE 0x28040 +#define CB_COLOR1_BASE 0x28044 +#define CB_COLOR2_BASE 0x28048 +#define CB_COLOR3_BASE 0x2804C +#define CB_COLOR4_BASE 0x28050 +#define CB_COLOR5_BASE 0x28054 +#define CB_COLOR6_BASE 0x28058 +#define CB_COLOR7_BASE 0x2805C +#define CB_COLOR7_FRAG 0x280FC + +#define CC_GC_SHADER_PIPE_CONFIG 0x8950 +#define CC_RB_BACKEND_DISABLE 0x98F4 +#define BACKEND_DISABLE(x) ((x) << 16) +#define CC_SYS_RB_BACKEND_DISABLE 0x3F88 + +#define CGTS_SYS_TCC_DISABLE 0x3F90 +#define CGTS_TCC_DISABLE 0x9148 +#define CGTS_USER_SYS_TCC_DISABLE 0x3F94 +#define CGTS_USER_TCC_DISABLE 0x914C + +#define CONFIG_MEMSIZE 0x5428 + +#define CP_ME_CNTL 0x86D8 +#define CP_ME_HALT (1<<28) +#define CP_PFP_HALT (1<<26) +#define CP_ME_RAM_DATA 0xC160 +#define CP_ME_RAM_RADDR 0xC158 +#define CP_ME_RAM_WADDR 0xC15C +#define CP_MEQ_THRESHOLDS 0x8764 +#define STQ_SPLIT(x) ((x) << 0) +#define CP_PERFMON_CNTL 0x87FC +#define CP_PFP_UCODE_ADDR 0xC150 +#define CP_PFP_UCODE_DATA 0xC154 +#define CP_QUEUE_THRESHOLDS 0x8760 +#define ROQ_IB1_START(x) ((x) << 0) +#define ROQ_IB2_START(x) ((x) << 8) +#define CP_RB_CNTL 0xC104 +#define RB_BUFSZ(x) ((x) << 0) +#define RB_BLKSZ(x) ((x) << 8) +#define RB_NO_UPDATE (1 << 27) +#define RB_RPTR_WR_ENA (1 << 31) +#define BUF_SWAP_32BIT (2 << 16) +#define CP_RB_RPTR 0x8700 +#define CP_RB_RPTR_ADDR 0xC10C +#define CP_RB_RPTR_ADDR_HI 0xC110 +#define CP_RB_RPTR_WR 0xC108 +#define CP_RB_WPTR 0xC114 +#define CP_RB_WPTR_ADDR 0xC118 +#define CP_RB_WPTR_ADDR_HI 0xC11C +#define CP_RB_WPTR_DELAY 0x8704 +#define CP_SEM_WAIT_TIMER 0x85BC + +#define DB_DEBUG3 0x98B0 +#define DB_CLK_OFF_DELAY(x) ((x) << 11) +#define DB_DEBUG4 0x9B8C +#define DISABLE_TILE_COVERED_FOR_PS_ITER (1 << 6) + +#define DCP_TILING_CONFIG 0x6CA0 +#define PIPE_TILING(x) ((x) << 1) +#define BANK_TILING(x) ((x) << 4) +#define GROUP_SIZE(x) ((x) << 6) +#define ROW_TILING(x) ((x) << 8) +#define BANK_SWAPS(x) ((x) << 11) +#define SAMPLE_SPLIT(x) ((x) << 14) +#define BACKEND_MAP(x) ((x) << 16) + +#define GB_TILING_CONFIG 0x98F0 +#define PIPE_TILING__SHIFT 1 +#define PIPE_TILING__MASK 0x0000000e + +#define DMA_TILING_CONFIG 0x3ec8 +#define DMA_TILING_CONFIG2 0xd0b8 + +#define GC_USER_SHADER_PIPE_CONFIG 0x8954 +#define INACTIVE_QD_PIPES(x) ((x) << 8) +#define INACTIVE_QD_PIPES_MASK 0x0000FF00 +#define INACTIVE_QD_PIPES_SHIFT 8 +#define INACTIVE_SIMDS(x) ((x) << 16) +#define INACTIVE_SIMDS_MASK 0x00FF0000 + +#define GRBM_CNTL 0x8000 +#define GRBM_READ_TIMEOUT(x) ((x) << 0) +#define GRBM_SOFT_RESET 0x8020 +#define SOFT_RESET_CP (1<<0) +#define GRBM_STATUS 0x8010 +#define CMDFIFO_AVAIL_MASK 0x0000000F +#define GUI_ACTIVE (1<<31) +#define GRBM_STATUS2 0x8014 + +#define CG_MULT_THERMAL_STATUS 0x740 +#define ASIC_T(x) ((x) << 16) +#define ASIC_T_MASK 0x3FF0000 +#define ASIC_T_SHIFT 16 + +#define HDP_HOST_PATH_CNTL 0x2C00 +#define HDP_NONSURFACE_BASE 0x2C04 +#define HDP_NONSURFACE_INFO 0x2C08 +#define HDP_NONSURFACE_SIZE 0x2C0C +#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 +#define HDP_TILING_CONFIG 0x2F3C +#define HDP_DEBUG1 0x2F34 + +#define MC_SHARED_CHMAP 0x2004 +#define NOOFCHAN_SHIFT 12 +#define NOOFCHAN_MASK 0x00003000 +#define MC_SHARED_CHREMAP 0x2008 + +#define MC_ARB_RAMCFG 0x2760 +#define NOOFBANK_SHIFT 0 +#define NOOFBANK_MASK 0x00000003 +#define NOOFRANK_SHIFT 2 +#define NOOFRANK_MASK 0x00000004 +#define NOOFROWS_SHIFT 3 +#define NOOFROWS_MASK 0x00000038 +#define NOOFCOLS_SHIFT 6 +#define NOOFCOLS_MASK 0x000000C0 +#define CHANSIZE_SHIFT 8 +#define CHANSIZE_MASK 0x00000100 +#define BURSTLENGTH_SHIFT 9 +#define BURSTLENGTH_MASK 0x00000200 +#define CHANSIZE_OVERRIDE (1 << 11) +#define MC_VM_AGP_TOP 0x2028 +#define MC_VM_AGP_BOT 0x202C +#define MC_VM_AGP_BASE 0x2030 +#define MC_VM_FB_LOCATION 0x2024 +#define MC_VM_MB_L1_TLB0_CNTL 0x2234 +#define MC_VM_MB_L1_TLB1_CNTL 0x2238 +#define MC_VM_MB_L1_TLB2_CNTL 0x223C +#define MC_VM_MB_L1_TLB3_CNTL 0x2240 +#define ENABLE_L1_TLB (1 << 0) +#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) +#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) +#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) +#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) +#define EFFECTIVE_L1_TLB_SIZE(x) ((x)<<15) +#define EFFECTIVE_L1_QUEUE_SIZE(x) ((x)<<18) +#define MC_VM_MD_L1_TLB0_CNTL 0x2654 +#define MC_VM_MD_L1_TLB1_CNTL 0x2658 +#define MC_VM_MD_L1_TLB2_CNTL 0x265C +#define MC_VM_MD_L1_TLB3_CNTL 0x2698 +#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C +#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 +#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 + +#define PA_CL_ENHANCE 0x8A14 +#define CLIP_VTX_REORDER_ENA (1 << 0) +#define NUM_CLIP_SEQ(x) ((x) << 1) +#define PA_SC_AA_CONFIG 0x28C04 +#define PA_SC_CLIPRECT_RULE 0x2820C +#define PA_SC_EDGERULE 0x28230 +#define PA_SC_FIFO_SIZE 0x8BCC +#define SC_PRIM_FIFO_SIZE(x) ((x) << 0) +#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) +#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 +#define FORCE_EOV_MAX_CLK_CNT(x) ((x)<<0) +#define FORCE_EOV_MAX_REZ_CNT(x) ((x)<<16) +#define PA_SC_LINE_STIPPLE 0x28A0C +#define PA_SC_LINE_STIPPLE_STATE 0x8B10 +#define PA_SC_MODE_CNTL 0x28A4C +#define PA_SC_MULTI_CHIP_CNTL 0x8B20 +#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) + +#define SCRATCH_REG0 0x8500 +#define SCRATCH_REG1 0x8504 +#define SCRATCH_REG2 0x8508 +#define SCRATCH_REG3 0x850C +#define SCRATCH_REG4 0x8510 +#define SCRATCH_REG5 0x8514 +#define SCRATCH_REG6 0x8518 +#define SCRATCH_REG7 0x851C +#define SCRATCH_UMSK 0x8540 +#define SCRATCH_ADDR 0x8544 + +#define SMX_SAR_CTL0 0xA008 +#define SMX_DC_CTL0 0xA020 +#define USE_HASH_FUNCTION (1 << 0) +#define CACHE_DEPTH(x) ((x) << 1) +#define FLUSH_ALL_ON_EVENT (1 << 10) +#define STALL_ON_EVENT (1 << 11) +#define SMX_EVENT_CTL 0xA02C +#define ES_FLUSH_CTL(x) ((x) << 0) +#define GS_FLUSH_CTL(x) ((x) << 3) +#define ACK_FLUSH_CTL(x) ((x) << 6) +#define SYNC_FLUSH_CTL (1 << 8) + +#define SPI_CONFIG_CNTL 0x9100 +#define GPR_WRITE_PRIORITY(x) ((x) << 0) +#define DISABLE_INTERP_1 (1 << 5) +#define SPI_CONFIG_CNTL_1 0x913C +#define VTX_DONE_DELAY(x) ((x) << 0) +#define INTERP_ONE_PRIM_PER_ROW (1 << 4) +#define SPI_INPUT_Z 0x286D8 +#define SPI_PS_IN_CONTROL_0 0x286CC +#define NUM_INTERP(x) ((x)<<0) +#define POSITION_ENA (1<<8) +#define POSITION_CENTROID (1<<9) +#define POSITION_ADDR(x) ((x)<<10) +#define PARAM_GEN(x) ((x)<<15) +#define PARAM_GEN_ADDR(x) ((x)<<19) +#define BARYC_SAMPLE_CNTL(x) ((x)<<26) +#define PERSP_GRADIENT_ENA (1<<28) +#define LINEAR_GRADIENT_ENA (1<<29) +#define POSITION_SAMPLE (1<<30) +#define BARYC_AT_SAMPLE_ENA (1<<31) + +#define SQ_CONFIG 0x8C00 +#define VC_ENABLE (1 << 0) +#define EXPORT_SRC_C (1 << 1) +#define DX9_CONSTS (1 << 2) +#define ALU_INST_PREFER_VECTOR (1 << 3) +#define DX10_CLAMP (1 << 4) +#define CLAUSE_SEQ_PRIO(x) ((x) << 8) +#define PS_PRIO(x) ((x) << 24) +#define VS_PRIO(x) ((x) << 26) +#define GS_PRIO(x) ((x) << 28) +#define SQ_DYN_GPR_SIZE_SIMD_AB_0 0x8DB0 +#define SIMDA_RING0(x) ((x)<<0) +#define SIMDA_RING1(x) ((x)<<8) +#define SIMDB_RING0(x) ((x)<<16) +#define SIMDB_RING1(x) ((x)<<24) +#define SQ_DYN_GPR_SIZE_SIMD_AB_1 0x8DB4 +#define SQ_DYN_GPR_SIZE_SIMD_AB_2 0x8DB8 +#define SQ_DYN_GPR_SIZE_SIMD_AB_3 0x8DBC +#define SQ_DYN_GPR_SIZE_SIMD_AB_4 0x8DC0 +#define SQ_DYN_GPR_SIZE_SIMD_AB_5 0x8DC4 +#define SQ_DYN_GPR_SIZE_SIMD_AB_6 0x8DC8 +#define SQ_DYN_GPR_SIZE_SIMD_AB_7 0x8DCC +#define ES_PRIO(x) ((x) << 30) +#define SQ_GPR_RESOURCE_MGMT_1 0x8C04 +#define NUM_PS_GPRS(x) ((x) << 0) +#define NUM_VS_GPRS(x) ((x) << 16) +#define DYN_GPR_ENABLE (1 << 27) +#define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) +#define SQ_GPR_RESOURCE_MGMT_2 0x8C08 +#define NUM_GS_GPRS(x) ((x) << 0) +#define NUM_ES_GPRS(x) ((x) << 16) +#define SQ_MS_FIFO_SIZES 0x8CF0 +#define CACHE_FIFO_SIZE(x) ((x) << 0) +#define FETCH_FIFO_HIWATER(x) ((x) << 8) +#define DONE_FIFO_HIWATER(x) ((x) << 16) +#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) +#define SQ_STACK_RESOURCE_MGMT_1 0x8C10 +#define NUM_PS_STACK_ENTRIES(x) ((x) << 0) +#define NUM_VS_STACK_ENTRIES(x) ((x) << 16) +#define SQ_STACK_RESOURCE_MGMT_2 0x8C14 +#define NUM_GS_STACK_ENTRIES(x) ((x) << 0) +#define NUM_ES_STACK_ENTRIES(x) ((x) << 16) +#define SQ_THREAD_RESOURCE_MGMT 0x8C0C +#define NUM_PS_THREADS(x) ((x) << 0) +#define NUM_VS_THREADS(x) ((x) << 8) +#define NUM_GS_THREADS(x) ((x) << 16) +#define NUM_ES_THREADS(x) ((x) << 24) + +#define SX_DEBUG_1 0x9058 +#define ENABLE_NEW_SMX_ADDRESS (1 << 16) +#define SX_EXPORT_BUFFER_SIZES 0x900C +#define COLOR_BUFFER_SIZE(x) ((x) << 0) +#define POSITION_BUFFER_SIZE(x) ((x) << 8) +#define SMX_BUFFER_SIZE(x) ((x) << 16) +#define SX_MISC 0x28350 + +#define TA_CNTL_AUX 0x9508 +#define DISABLE_CUBE_WRAP (1 << 0) +#define DISABLE_CUBE_ANISO (1 << 1) +#define SYNC_GRADIENT (1 << 24) +#define SYNC_WALKER (1 << 25) +#define SYNC_ALIGNER (1 << 26) +#define BILINEAR_PRECISION_6_BIT (0 << 31) +#define BILINEAR_PRECISION_8_BIT (1 << 31) + +#define TCP_CNTL 0x9610 +#define TCP_CHAN_STEER 0x9614 + +#define VC_ENHANCE 0x9714 + +#define VGT_CACHE_INVALIDATION 0x88C4 +#define CACHE_INVALIDATION(x) ((x)<<0) +#define VC_ONLY 0 +#define TC_ONLY 1 +#define VC_AND_TC 2 +#define AUTO_INVLD_EN(x) ((x) << 6) +#define NO_AUTO 0 +#define ES_AUTO 1 +#define GS_AUTO 2 +#define ES_AND_GS_AUTO 3 +#define VGT_ES_PER_GS 0x88CC +#define VGT_GS_PER_ES 0x88C8 +#define VGT_GS_PER_VS 0x88E8 +#define VGT_GS_VERTEX_REUSE 0x88D4 +#define VGT_NUM_INSTANCES 0x8974 +#define VGT_OUT_DEALLOC_CNTL 0x28C5C +#define DEALLOC_DIST_MASK 0x0000007F +#define VGT_STRMOUT_EN 0x28AB0 +#define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 +#define VTX_REUSE_DEPTH_MASK 0x000000FF + +#define VM_CONTEXT0_CNTL 0x1410 +#define ENABLE_CONTEXT (1 << 0) +#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C +#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C +#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 +#define VM_L2_CNTL 0x1400 +#define ENABLE_L2_CACHE (1 << 0) +#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) +#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) +#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 14) +#define VM_L2_CNTL2 0x1404 +#define INVALIDATE_ALL_L1_TLBS (1 << 0) +#define INVALIDATE_L2_CACHE (1 << 1) +#define VM_L2_CNTL3 0x1408 +#define BANK_SELECT(x) ((x) << 0) +#define CACHE_UPDATE_MODE(x) ((x) << 6) +#define VM_L2_STATUS 0x140C +#define L2_BUSY (1 << 0) + +#define WAIT_UNTIL 0x8040 + +/* async DMA */ +#define DMA_RB_RPTR 0xd008 +#define DMA_RB_WPTR 0xd00c + +/* async DMA packets */ +#define DMA_PACKET(cmd, t, s, n) ((((cmd) & 0xF) << 28) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((n) & 0xFFFF) << 0)) +/* async DMA Packet types */ +#define DMA_PACKET_WRITE 0x2 +#define DMA_PACKET_COPY 0x3 +#define DMA_PACKET_INDIRECT_BUFFER 0x4 +#define DMA_PACKET_SEMAPHORE 0x5 +#define DMA_PACKET_FENCE 0x6 +#define DMA_PACKET_TRAP 0x7 +#define DMA_PACKET_CONSTANT_FILL 0xd +#define DMA_PACKET_NOP 0xf + + +#define SRBM_STATUS 0x0E50 + +/* DCE 3.2 HDMI */ +#define HDMI_CONTROL 0x7400 +# define HDMI_KEEPOUT_MODE (1 << 0) +# define HDMI_PACKET_GEN_VERSION (1 << 4) /* 0 = r6xx compat */ +# define HDMI_ERROR_ACK (1 << 8) +# define HDMI_ERROR_MASK (1 << 9) +#define HDMI_STATUS 0x7404 +# define HDMI_ACTIVE_AVMUTE (1 << 0) +# define HDMI_AUDIO_PACKET_ERROR (1 << 16) +# define HDMI_VBI_PACKET_ERROR (1 << 20) +#define HDMI_AUDIO_PACKET_CONTROL 0x7408 +# define HDMI_AUDIO_DELAY_EN(x) (((x) & 3) << 4) +# define HDMI_AUDIO_PACKETS_PER_LINE(x) (((x) & 0x1f) << 16) +#define HDMI_ACR_PACKET_CONTROL 0x740c +# define HDMI_ACR_SEND (1 << 0) +# define HDMI_ACR_CONT (1 << 1) +# define HDMI_ACR_SELECT(x) (((x) & 3) << 4) +# define HDMI_ACR_HW 0 +# define HDMI_ACR_32 1 +# define HDMI_ACR_44 2 +# define HDMI_ACR_48 3 +# define HDMI_ACR_SOURCE (1 << 8) /* 0 - hw; 1 - cts value */ +# define HDMI_ACR_AUTO_SEND (1 << 12) +#define HDMI_VBI_PACKET_CONTROL 0x7410 +# define HDMI_NULL_SEND (1 << 0) +# define HDMI_GC_SEND (1 << 4) +# define HDMI_GC_CONT (1 << 5) /* 0 - once; 1 - every frame */ +#define HDMI_INFOFRAME_CONTROL0 0x7414 +# define HDMI_AVI_INFO_SEND (1 << 0) +# define HDMI_AVI_INFO_CONT (1 << 1) +# define HDMI_AUDIO_INFO_SEND (1 << 4) +# define HDMI_AUDIO_INFO_CONT (1 << 5) +# define HDMI_MPEG_INFO_SEND (1 << 8) +# define HDMI_MPEG_INFO_CONT (1 << 9) +#define HDMI_INFOFRAME_CONTROL1 0x7418 +# define HDMI_AVI_INFO_LINE(x) (((x) & 0x3f) << 0) +# define HDMI_AUDIO_INFO_LINE(x) (((x) & 0x3f) << 8) +# define HDMI_MPEG_INFO_LINE(x) (((x) & 0x3f) << 16) +#define HDMI_GENERIC_PACKET_CONTROL 0x741c +# define HDMI_GENERIC0_SEND (1 << 0) +# define HDMI_GENERIC0_CONT (1 << 1) +# define HDMI_GENERIC1_SEND (1 << 4) +# define HDMI_GENERIC1_CONT (1 << 5) +# define HDMI_GENERIC0_LINE(x) (((x) & 0x3f) << 16) +# define HDMI_GENERIC1_LINE(x) (((x) & 0x3f) << 24) +#define HDMI_GC 0x7428 +# define HDMI_GC_AVMUTE (1 << 0) +#define AFMT_AUDIO_PACKET_CONTROL2 0x742c +# define AFMT_AUDIO_LAYOUT_OVRD (1 << 0) +# define AFMT_AUDIO_LAYOUT_SELECT (1 << 1) +# define AFMT_60958_CS_SOURCE (1 << 4) +# define AFMT_AUDIO_CHANNEL_ENABLE(x) (((x) & 0xff) << 8) +# define AFMT_DP_AUDIO_STREAM_ID(x) (((x) & 0xff) << 16) +#define AFMT_AVI_INFO0 0x7454 +# define AFMT_AVI_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define AFMT_AVI_INFO_S(x) (((x) & 3) << 8) +# define AFMT_AVI_INFO_B(x) (((x) & 3) << 10) +# define AFMT_AVI_INFO_A(x) (((x) & 1) << 12) +# define AFMT_AVI_INFO_Y(x) (((x) & 3) << 13) +# define AFMT_AVI_INFO_Y_RGB 0 +# define AFMT_AVI_INFO_Y_YCBCR422 1 +# define AFMT_AVI_INFO_Y_YCBCR444 2 +# define AFMT_AVI_INFO_Y_A_B_S(x) (((x) & 0xff) << 8) +# define AFMT_AVI_INFO_R(x) (((x) & 0xf) << 16) +# define AFMT_AVI_INFO_M(x) (((x) & 0x3) << 20) +# define AFMT_AVI_INFO_C(x) (((x) & 0x3) << 22) +# define AFMT_AVI_INFO_C_M_R(x) (((x) & 0xff) << 16) +# define AFMT_AVI_INFO_SC(x) (((x) & 0x3) << 24) +# define AFMT_AVI_INFO_Q(x) (((x) & 0x3) << 26) +# define AFMT_AVI_INFO_EC(x) (((x) & 0x3) << 28) +# define AFMT_AVI_INFO_ITC(x) (((x) & 0x1) << 31) +# define AFMT_AVI_INFO_ITC_EC_Q_SC(x) (((x) & 0xff) << 24) +#define AFMT_AVI_INFO1 0x7458 +# define AFMT_AVI_INFO_VIC(x) (((x) & 0x7f) << 0) /* don't use avi infoframe v1 */ +# define AFMT_AVI_INFO_PR(x) (((x) & 0xf) << 8) /* don't use avi infoframe v1 */ +# define AFMT_AVI_INFO_TOP(x) (((x) & 0xffff) << 16) +#define AFMT_AVI_INFO2 0x745c +# define AFMT_AVI_INFO_BOTTOM(x) (((x) & 0xffff) << 0) +# define AFMT_AVI_INFO_LEFT(x) (((x) & 0xffff) << 16) +#define AFMT_AVI_INFO3 0x7460 +# define AFMT_AVI_INFO_RIGHT(x) (((x) & 0xffff) << 0) +# define AFMT_AVI_INFO_VERSION(x) (((x) & 3) << 24) +#define AFMT_MPEG_INFO0 0x7464 +# define AFMT_MPEG_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define AFMT_MPEG_INFO_MB0(x) (((x) & 0xff) << 8) +# define AFMT_MPEG_INFO_MB1(x) (((x) & 0xff) << 16) +# define AFMT_MPEG_INFO_MB2(x) (((x) & 0xff) << 24) +#define AFMT_MPEG_INFO1 0x7468 +# define AFMT_MPEG_INFO_MB3(x) (((x) & 0xff) << 0) +# define AFMT_MPEG_INFO_MF(x) (((x) & 3) << 8) +# define AFMT_MPEG_INFO_FR(x) (((x) & 1) << 12) +#define AFMT_GENERIC0_HDR 0x746c +#define AFMT_GENERIC0_0 0x7470 +#define AFMT_GENERIC0_1 0x7474 +#define AFMT_GENERIC0_2 0x7478 +#define AFMT_GENERIC0_3 0x747c +#define AFMT_GENERIC0_4 0x7480 +#define AFMT_GENERIC0_5 0x7484 +#define AFMT_GENERIC0_6 0x7488 +#define AFMT_GENERIC1_HDR 0x748c +#define AFMT_GENERIC1_0 0x7490 +#define AFMT_GENERIC1_1 0x7494 +#define AFMT_GENERIC1_2 0x7498 +#define AFMT_GENERIC1_3 0x749c +#define AFMT_GENERIC1_4 0x74a0 +#define AFMT_GENERIC1_5 0x74a4 +#define AFMT_GENERIC1_6 0x74a8 +#define HDMI_ACR_32_0 0x74ac +# define HDMI_ACR_CTS_32(x) (((x) & 0xfffff) << 12) +#define HDMI_ACR_32_1 0x74b0 +# define HDMI_ACR_N_32(x) (((x) & 0xfffff) << 0) +#define HDMI_ACR_44_0 0x74b4 +# define HDMI_ACR_CTS_44(x) (((x) & 0xfffff) << 12) +#define HDMI_ACR_44_1 0x74b8 +# define HDMI_ACR_N_44(x) (((x) & 0xfffff) << 0) +#define HDMI_ACR_48_0 0x74bc +# define HDMI_ACR_CTS_48(x) (((x) & 0xfffff) << 12) +#define HDMI_ACR_48_1 0x74c0 +# define HDMI_ACR_N_48(x) (((x) & 0xfffff) << 0) +#define HDMI_ACR_STATUS_0 0x74c4 +#define HDMI_ACR_STATUS_1 0x74c8 +#define AFMT_AUDIO_INFO0 0x74cc +# define AFMT_AUDIO_INFO_CHECKSUM(x) (((x) & 0xff) << 0) +# define AFMT_AUDIO_INFO_CC(x) (((x) & 7) << 8) +# define AFMT_AUDIO_INFO_CHECKSUM_OFFSET(x) (((x) & 0xff) << 16) +#define AFMT_AUDIO_INFO1 0x74d0 +# define AFMT_AUDIO_INFO_CA(x) (((x) & 0xff) << 0) +# define AFMT_AUDIO_INFO_LSV(x) (((x) & 0xf) << 11) +# define AFMT_AUDIO_INFO_DM_INH(x) (((x) & 1) << 15) +# define AFMT_AUDIO_INFO_DM_INH_LSV(x) (((x) & 0xff) << 8) +#define AFMT_60958_0 0x74d4 +# define AFMT_60958_CS_A(x) (((x) & 1) << 0) +# define AFMT_60958_CS_B(x) (((x) & 1) << 1) +# define AFMT_60958_CS_C(x) (((x) & 1) << 2) +# define AFMT_60958_CS_D(x) (((x) & 3) << 3) +# define AFMT_60958_CS_MODE(x) (((x) & 3) << 6) +# define AFMT_60958_CS_CATEGORY_CODE(x) (((x) & 0xff) << 8) +# define AFMT_60958_CS_SOURCE_NUMBER(x) (((x) & 0xf) << 16) +# define AFMT_60958_CS_CHANNEL_NUMBER_L(x) (((x) & 0xf) << 20) +# define AFMT_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24) +# define AFMT_60958_CS_CLOCK_ACCURACY(x) (((x) & 3) << 28) +#define AFMT_60958_1 0x74d8 +# define AFMT_60958_CS_WORD_LENGTH(x) (((x) & 0xf) << 0) +# define AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 4) +# define AFMT_60958_CS_VALID_L(x) (((x) & 1) << 16) +# define AFMT_60958_CS_VALID_R(x) (((x) & 1) << 18) +# define AFMT_60958_CS_CHANNEL_NUMBER_R(x) (((x) & 0xf) << 20) +#define AFMT_AUDIO_CRC_CONTROL 0x74dc +# define AFMT_AUDIO_CRC_EN (1 << 0) +#define AFMT_RAMP_CONTROL0 0x74e0 +# define AFMT_RAMP_MAX_COUNT(x) (((x) & 0xffffff) << 0) +# define AFMT_RAMP_DATA_SIGN (1 << 31) +#define AFMT_RAMP_CONTROL1 0x74e4 +# define AFMT_RAMP_MIN_COUNT(x) (((x) & 0xffffff) << 0) +# define AFMT_AUDIO_TEST_CH_DISABLE(x) (((x) & 0xff) << 24) +#define AFMT_RAMP_CONTROL2 0x74e8 +# define AFMT_RAMP_INC_COUNT(x) (((x) & 0xffffff) << 0) +#define AFMT_RAMP_CONTROL3 0x74ec +# define AFMT_RAMP_DEC_COUNT(x) (((x) & 0xffffff) << 0) +#define AFMT_60958_2 0x74f0 +# define AFMT_60958_CS_CHANNEL_NUMBER_2(x) (((x) & 0xf) << 0) +# define AFMT_60958_CS_CHANNEL_NUMBER_3(x) (((x) & 0xf) << 4) +# define AFMT_60958_CS_CHANNEL_NUMBER_4(x) (((x) & 0xf) << 8) +# define AFMT_60958_CS_CHANNEL_NUMBER_5(x) (((x) & 0xf) << 12) +# define AFMT_60958_CS_CHANNEL_NUMBER_6(x) (((x) & 0xf) << 16) +# define AFMT_60958_CS_CHANNEL_NUMBER_7(x) (((x) & 0xf) << 20) +#define AFMT_STATUS 0x7600 +# define AFMT_AUDIO_ENABLE (1 << 4) +# define AFMT_AZ_FORMAT_WTRIG (1 << 28) +# define AFMT_AZ_FORMAT_WTRIG_INT (1 << 29) +# define AFMT_AZ_AUDIO_ENABLE_CHG (1 << 30) +#define AFMT_AUDIO_PACKET_CONTROL 0x7604 +# define AFMT_AUDIO_SAMPLE_SEND (1 << 0) +# define AFMT_AUDIO_TEST_EN (1 << 12) +# define AFMT_AUDIO_CHANNEL_SWAP (1 << 24) +# define AFMT_60958_CS_UPDATE (1 << 26) +# define AFMT_AZ_AUDIO_ENABLE_CHG_MASK (1 << 27) +# define AFMT_AZ_FORMAT_WTRIG_MASK (1 << 28) +# define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29) +# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30) +#define AFMT_VBI_PACKET_CONTROL 0x7608 +# define AFMT_GENERIC0_UPDATE (1 << 2) +#define AFMT_INFOFRAME_CONTROL0 0x760c +# define AFMT_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hmdi regs */ +# define AFMT_AUDIO_INFO_UPDATE (1 << 7) +# define AFMT_MPEG_INFO_UPDATE (1 << 10) +#define AFMT_GENERIC0_7 0x7610 +/* second instance starts at 0x7800 */ +#define HDMI_OFFSET0 (0x7400 - 0x7400) +#define HDMI_OFFSET1 (0x7800 - 0x7400) + +/* DCE3.2 ELD audio interface */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0 0x71c8 /* LPCM */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1 0x71cc /* AC3 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2 0x71d0 /* MPEG1 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3 0x71d4 /* MP3 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4 0x71d8 /* MPEG2 */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5 0x71dc /* AAC */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6 0x71e0 /* DTS */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7 0x71e4 /* ATRAC */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR8 0x71e8 /* one bit audio - leave at 0 (default) */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9 0x71ec /* Dolby Digital */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10 0x71f0 /* DTS-HD */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11 0x71f4 /* MAT-MLP */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR12 0x71f8 /* DTS */ +#define AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13 0x71fc /* WMA Pro */ +# define MAX_CHANNELS(x) (((x) & 0x7) << 0) +/* max channels minus one. 7 = 8 channels */ +# define SUPPORTED_FREQUENCIES(x) (((x) & 0xff) << 8) +# define DESCRIPTOR_BYTE_2(x) (((x) & 0xff) << 16) +# define SUPPORTED_FREQUENCIES_STEREO(x) (((x) & 0xff) << 24) /* LPCM only */ +/* SUPPORTED_FREQUENCIES, SUPPORTED_FREQUENCIES_STEREO + * bit0 = 32 kHz + * bit1 = 44.1 kHz + * bit2 = 48 kHz + * bit3 = 88.2 kHz + * bit4 = 96 kHz + * bit5 = 176.4 kHz + * bit6 = 192 kHz + */ + +#define AZ_HOT_PLUG_CONTROL 0x7300 +# define AZ_FORCE_CODEC_WAKE (1 << 0) +# define PIN0_JACK_DETECTION_ENABLE (1 << 4) +# define PIN1_JACK_DETECTION_ENABLE (1 << 5) +# define PIN2_JACK_DETECTION_ENABLE (1 << 6) +# define PIN3_JACK_DETECTION_ENABLE (1 << 7) +# define PIN0_UNSOLICITED_RESPONSE_ENABLE (1 << 8) +# define PIN1_UNSOLICITED_RESPONSE_ENABLE (1 << 9) +# define PIN2_UNSOLICITED_RESPONSE_ENABLE (1 << 10) +# define PIN3_UNSOLICITED_RESPONSE_ENABLE (1 << 11) +# define CODEC_HOT_PLUG_ENABLE (1 << 12) +# define PIN0_AUDIO_ENABLED (1 << 24) +# define PIN1_AUDIO_ENABLED (1 << 25) +# define PIN2_AUDIO_ENABLED (1 << 26) +# define PIN3_AUDIO_ENABLED (1 << 27) +# define AUDIO_ENABLED (1 << 31) + + +#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 +#define D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6914 +#define D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6114 +#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 +#define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c +#define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c + +/* PCIE link stuff */ +#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */ +#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */ +# define LC_LINK_WIDTH_SHIFT 0 +# define LC_LINK_WIDTH_MASK 0x7 +# define LC_LINK_WIDTH_X0 0 +# define LC_LINK_WIDTH_X1 1 +# define LC_LINK_WIDTH_X2 2 +# define LC_LINK_WIDTH_X4 3 +# define LC_LINK_WIDTH_X8 4 +# define LC_LINK_WIDTH_X16 6 +# define LC_LINK_WIDTH_RD_SHIFT 4 +# define LC_LINK_WIDTH_RD_MASK 0x70 +# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7) +# define LC_RECONFIG_NOW (1 << 8) +# define LC_RENEGOTIATION_SUPPORT (1 << 9) +# define LC_RENEGOTIATE_EN (1 << 10) +# define LC_SHORT_RECONFIG_EN (1 << 11) +# define LC_UPCONFIGURE_SUPPORT (1 << 12) +# define LC_UPCONFIGURE_DIS (1 << 13) +#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */ +# define LC_GEN2_EN_STRAP (1 << 0) +# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1) +# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 5) +# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 6) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3 +# define LC_CURRENT_DATA_RATE (1 << 11) +# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14) +# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21) +# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23) +# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 24) +#define MM_CFGREGS_CNTL 0x544c +# define MM_WR_TO_CFG_EN (1 << 3) +#define LINK_CNTL2 0x88 /* F0 */ +# define TARGET_LINK_SPEED_MASK (0xf << 0) +# define SELECTABLE_DEEMPHASIS (1 << 6) + +#endif diff --git a/sys/dev/drm2/radeon/si.c b/sys/dev/drm2/radeon/si.c new file mode 100644 index 00000000000..6a04b945ca3 --- /dev/null +++ b/sys/dev/drm2/radeon/si.c @@ -0,0 +1,4424 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include "radeon.h" +#include "radeon_asic.h" +#include +#include "sid.h" +#include "atom.h" +#include "si_blit_shaders.h" + +#define SI_PFP_UCODE_SIZE 2144 +#define SI_PM4_UCODE_SIZE 2144 +#define SI_CE_UCODE_SIZE 2144 +#define SI_RLC_UCODE_SIZE 2048 +#define SI_MC_UCODE_SIZE 7769 + +/* get temperature in millidegrees */ +int si_get_temp(struct radeon_device *rdev) +{ + u32 temp; + int actual_temp = 0; + + temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> + CTF_TEMP_SHIFT; + + if (temp & 0x200) + actual_temp = 255; + else + actual_temp = temp & 0x1ff; + + actual_temp = (actual_temp * 1000); + + return actual_temp; +} + +#define TAHITI_IO_MC_REGS_SIZE 36 + +static const u32 tahiti_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { + {0x0000006f, 0x03044000}, + {0x00000070, 0x0480c018}, + {0x00000071, 0x00000040}, + {0x00000072, 0x01000000}, + {0x00000074, 0x000000ff}, + {0x00000075, 0x00143400}, + {0x00000076, 0x08ec0800}, + {0x00000077, 0x040000cc}, + {0x00000079, 0x00000000}, + {0x0000007a, 0x21000409}, + {0x0000007c, 0x00000000}, + {0x0000007d, 0xe8000000}, + {0x0000007e, 0x044408a8}, + {0x0000007f, 0x00000003}, + {0x00000080, 0x00000000}, + {0x00000081, 0x01000000}, + {0x00000082, 0x02000000}, + {0x00000083, 0x00000000}, + {0x00000084, 0xe3f3e4f4}, + {0x00000085, 0x00052024}, + {0x00000087, 0x00000000}, + {0x00000088, 0x66036603}, + {0x00000089, 0x01000000}, + {0x0000008b, 0x1c0a0000}, + {0x0000008c, 0xff010000}, + {0x0000008e, 0xffffefff}, + {0x0000008f, 0xfff3efff}, + {0x00000090, 0xfff3efbf}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00a77400} +}; + +static const u32 pitcairn_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { + {0x0000006f, 0x03044000}, + {0x00000070, 0x0480c018}, + {0x00000071, 0x00000040}, + {0x00000072, 0x01000000}, + {0x00000074, 0x000000ff}, + {0x00000075, 0x00143400}, + {0x00000076, 0x08ec0800}, + {0x00000077, 0x040000cc}, + {0x00000079, 0x00000000}, + {0x0000007a, 0x21000409}, + {0x0000007c, 0x00000000}, + {0x0000007d, 0xe8000000}, + {0x0000007e, 0x044408a8}, + {0x0000007f, 0x00000003}, + {0x00000080, 0x00000000}, + {0x00000081, 0x01000000}, + {0x00000082, 0x02000000}, + {0x00000083, 0x00000000}, + {0x00000084, 0xe3f3e4f4}, + {0x00000085, 0x00052024}, + {0x00000087, 0x00000000}, + {0x00000088, 0x66036603}, + {0x00000089, 0x01000000}, + {0x0000008b, 0x1c0a0000}, + {0x0000008c, 0xff010000}, + {0x0000008e, 0xffffefff}, + {0x0000008f, 0xfff3efff}, + {0x00000090, 0xfff3efbf}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00a47400} +}; + +static const u32 verde_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { + {0x0000006f, 0x03044000}, + {0x00000070, 0x0480c018}, + {0x00000071, 0x00000040}, + {0x00000072, 0x01000000}, + {0x00000074, 0x000000ff}, + {0x00000075, 0x00143400}, + {0x00000076, 0x08ec0800}, + {0x00000077, 0x040000cc}, + {0x00000079, 0x00000000}, + {0x0000007a, 0x21000409}, + {0x0000007c, 0x00000000}, + {0x0000007d, 0xe8000000}, + {0x0000007e, 0x044408a8}, + {0x0000007f, 0x00000003}, + {0x00000080, 0x00000000}, + {0x00000081, 0x01000000}, + {0x00000082, 0x02000000}, + {0x00000083, 0x00000000}, + {0x00000084, 0xe3f3e4f4}, + {0x00000085, 0x00052024}, + {0x00000087, 0x00000000}, + {0x00000088, 0x66036603}, + {0x00000089, 0x01000000}, + {0x0000008b, 0x1c0a0000}, + {0x0000008c, 0xff010000}, + {0x0000008e, 0xffffefff}, + {0x0000008f, 0xfff3efff}, + {0x00000090, 0xfff3efbf}, + {0x00000094, 0x00101101}, + {0x00000095, 0x00000fff}, + {0x00000096, 0x00116fff}, + {0x00000097, 0x60010000}, + {0x00000098, 0x10010000}, + {0x00000099, 0x00006000}, + {0x0000009a, 0x00001000}, + {0x0000009f, 0x00a37400} +}; + +/* ucode loading */ +static int si_mc_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + u32 running, blackout = 0; + u32 *io_mc_regs; + int i, ucode_size, regs_size; + + if (!rdev->mc_fw) + return -EINVAL; + + switch (rdev->family) { + case CHIP_TAHITI: + io_mc_regs = (u32 *)&tahiti_io_mc_regs; + ucode_size = SI_MC_UCODE_SIZE; + regs_size = TAHITI_IO_MC_REGS_SIZE; + break; + case CHIP_PITCAIRN: + io_mc_regs = (u32 *)&pitcairn_io_mc_regs; + ucode_size = SI_MC_UCODE_SIZE; + regs_size = TAHITI_IO_MC_REGS_SIZE; + break; + case CHIP_VERDE: + default: + io_mc_regs = (u32 *)&verde_io_mc_regs; + ucode_size = SI_MC_UCODE_SIZE; + regs_size = TAHITI_IO_MC_REGS_SIZE; + break; + } + + running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; + + if (running == 0) { + if (running) { + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); + } + + /* reset the engine and set to writable */ + WREG32(MC_SEQ_SUP_CNTL, 0x00000008); + WREG32(MC_SEQ_SUP_CNTL, 0x00000010); + + /* load mc io regs */ + for (i = 0; i < regs_size; i++) { + WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); + WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); + } + /* load the MC ucode */ + fw_data = (const __be32 *)rdev->mc_fw->data; + for (i = 0; i < ucode_size; i++) + WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); + + /* put the engine back into the active state */ + WREG32(MC_SEQ_SUP_CNTL, 0x00000008); + WREG32(MC_SEQ_SUP_CNTL, 0x00000004); + WREG32(MC_SEQ_SUP_CNTL, 0x00000001); + + /* wait for training to complete */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0) + break; + DRM_UDELAY(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1) + break; + DRM_UDELAY(1); + } + + if (running) + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); + } + + return 0; +} + +static int si_init_microcode(struct radeon_device *rdev) +{ + const char *chip_name; + const char *rlc_chip_name; + size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; + char fw_name[30]; + int err; + + DRM_DEBUG("\n"); + + switch (rdev->family) { + case CHIP_TAHITI: + chip_name = "TAHITI"; + rlc_chip_name = "TAHITI"; + pfp_req_size = SI_PFP_UCODE_SIZE * 4; + me_req_size = SI_PM4_UCODE_SIZE * 4; + ce_req_size = SI_CE_UCODE_SIZE * 4; + rlc_req_size = SI_RLC_UCODE_SIZE * 4; + mc_req_size = SI_MC_UCODE_SIZE * 4; + break; + case CHIP_PITCAIRN: + chip_name = "PITCAIRN"; + rlc_chip_name = "PITCAIRN"; + pfp_req_size = SI_PFP_UCODE_SIZE * 4; + me_req_size = SI_PM4_UCODE_SIZE * 4; + ce_req_size = SI_CE_UCODE_SIZE * 4; + rlc_req_size = SI_RLC_UCODE_SIZE * 4; + mc_req_size = SI_MC_UCODE_SIZE * 4; + break; + case CHIP_VERDE: + chip_name = "VERDE"; + rlc_chip_name = "VERDE"; + pfp_req_size = SI_PFP_UCODE_SIZE * 4; + me_req_size = SI_PM4_UCODE_SIZE * 4; + ce_req_size = SI_CE_UCODE_SIZE * 4; + rlc_req_size = SI_RLC_UCODE_SIZE * 4; + mc_req_size = SI_MC_UCODE_SIZE * 4; + break; + default: panic("%s: Unsupported family %d", __func__, rdev->family); + } + + DRM_INFO("Loading %s Microcode\n", chip_name); + err = 0; + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_pfp", chip_name); + rdev->pfp_fw = firmware_get(fw_name); + if (rdev->pfp_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->pfp_fw->datasize != pfp_req_size) { + DRM_ERROR( + "si_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->pfp_fw->datasize, fw_name); + err = -EINVAL; + goto out; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_me", chip_name); + rdev->me_fw = firmware_get(fw_name); + if (rdev->me_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->me_fw->datasize != me_req_size) { + DRM_ERROR( + "si_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->me_fw->datasize, fw_name); + err = -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_ce", chip_name); + rdev->ce_fw = firmware_get(fw_name); + if (rdev->ce_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->ce_fw->datasize != ce_req_size) { + DRM_ERROR( + "si_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->ce_fw->datasize, fw_name); + err = -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_rlc", rlc_chip_name); + rdev->rlc_fw = firmware_get(fw_name); + if (rdev->rlc_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->rlc_fw->datasize != rlc_req_size) { + DRM_ERROR( + "si_rlc: Bogus length %zu in firmware \"%s\"\n", + rdev->rlc_fw->datasize, fw_name); + err = -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc", chip_name); + rdev->mc_fw = firmware_get(fw_name); + if (rdev->mc_fw == NULL) { + err = -ENOENT; + goto out; + } + if (rdev->mc_fw->datasize != mc_req_size) { + DRM_ERROR( + "si_mc: Bogus length %zu in firmware \"%s\"\n", + rdev->mc_fw->datasize, fw_name); + err = -EINVAL; + } + +out: + if (err) { + if (err != -EINVAL) + DRM_ERROR( + "si_cp: Failed to load firmware \"%s\"\n", + fw_name); + if (rdev->pfp_fw != NULL) { + firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); + rdev->pfp_fw = NULL; + } + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + if (rdev->ce_fw != NULL) { + firmware_put(rdev->ce_fw, FIRMWARE_UNLOAD); + rdev->ce_fw = NULL; + } + if (rdev->rlc_fw != NULL) { + firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); + rdev->rlc_fw = NULL; + } + if (rdev->mc_fw != NULL) { + firmware_put(rdev->mc_fw, FIRMWARE_UNLOAD); + rdev->mc_fw = NULL; + } + } + return err; +} + +/** + * si_fini_microcode - drop the firmwares image references + * + * @rdev: radeon_device pointer + * + * Drop the pfp, me, rlc, mc and ce firmware image references. + * Called at driver shutdown. + */ +static void si_fini_microcode(struct radeon_device *rdev) +{ + + if (rdev->pfp_fw != NULL) { + firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); + rdev->pfp_fw = NULL; + } + + if (rdev->me_fw != NULL) { + firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); + rdev->me_fw = NULL; + } + + if (rdev->rlc_fw != NULL) { + firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); + rdev->rlc_fw = NULL; + } + + if (rdev->mc_fw != NULL) { + firmware_put(rdev->mc_fw, FIRMWARE_UNLOAD); + rdev->mc_fw = NULL; + } + + if (rdev->ce_fw != NULL) { + firmware_put(rdev->ce_fw, FIRMWARE_UNLOAD); + rdev->ce_fw = NULL; + } +} + +/* watermark setup */ +static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, + struct radeon_crtc *radeon_crtc, + struct drm_display_mode *mode, + struct drm_display_mode *other_mode) +{ + u32 tmp; + /* + * Line Buffer Setup + * There are 3 line buffers, each one shared by 2 display controllers. + * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between + * the display controllers. The paritioning is done via one of four + * preset allocations specified in bits 21:20: + * 0 - half lb + * 2 - whole lb, other crtc must be disabled + */ + /* this can get tricky if we have two large displays on a paired group + * of crtcs. Ideally for multiple large displays we'd assign them to + * non-linked crtcs for maximum line buffer allocation. + */ + if (radeon_crtc->base.enabled && mode) { + if (other_mode) + tmp = 0; /* 1/2 */ + else + tmp = 2; /* whole */ + } else + tmp = 0; + + WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, + DC_LB_MEMORY_CONFIG(tmp)); + + if (radeon_crtc->base.enabled && mode) { + switch (tmp) { + case 0: + default: + return 4096 * 2; + case 2: + return 8192 * 2; + } + } + + /* controller not enabled, so no lb used */ + return 0; +} + +static u32 si_get_number_of_dram_channels(struct radeon_device *rdev) +{ + u32 tmp = RREG32(MC_SHARED_CHMAP); + + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + return 1; + case 1: + return 2; + case 2: + return 4; + case 3: + return 8; + case 4: + return 3; + case 5: + return 6; + case 6: + return 10; + case 7: + return 12; + case 8: + return 16; + } +} + +struct dce6_wm_params { + u32 dram_channels; /* number of dram channels */ + u32 yclk; /* bandwidth per dram data pin in kHz */ + u32 sclk; /* engine clock in kHz */ + u32 disp_clk; /* display clock in kHz */ + u32 src_width; /* viewport width */ + u32 active_time; /* active display time in ns */ + u32 blank_time; /* blank time in ns */ + bool interlaced; /* mode is interlaced */ + fixed20_12 vsc; /* vertical scale ratio */ + u32 num_heads; /* number of active crtcs */ + u32 bytes_per_pixel; /* bytes per pixel display + overlay */ + u32 lb_size; /* line buffer allocated to pipe */ + u32 vtaps; /* vertical scaler taps */ +}; + +static u32 dce6_dram_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate raw DRAM Bandwidth */ + fixed20_12 dram_efficiency; /* 0.7 */ + fixed20_12 yclk, dram_channels, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + yclk.full = dfixed_const(wm->yclk); + yclk.full = dfixed_div(yclk, a); + dram_channels.full = dfixed_const(wm->dram_channels * 4); + a.full = dfixed_const(10); + dram_efficiency.full = dfixed_const(7); + dram_efficiency.full = dfixed_div(dram_efficiency, a); + bandwidth.full = dfixed_mul(dram_channels, yclk); + bandwidth.full = dfixed_mul(bandwidth, dram_efficiency); + + return dfixed_trunc(bandwidth); +} + +static u32 dce6_dram_bandwidth_for_display(struct dce6_wm_params *wm) +{ + /* Calculate DRAM Bandwidth and the part allocated to display. */ + fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */ + fixed20_12 yclk, dram_channels, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + yclk.full = dfixed_const(wm->yclk); + yclk.full = dfixed_div(yclk, a); + dram_channels.full = dfixed_const(wm->dram_channels * 4); + a.full = dfixed_const(10); + disp_dram_allocation.full = dfixed_const(3); /* XXX worse case value 0.3 */ + disp_dram_allocation.full = dfixed_div(disp_dram_allocation, a); + bandwidth.full = dfixed_mul(dram_channels, yclk); + bandwidth.full = dfixed_mul(bandwidth, disp_dram_allocation); + + return dfixed_trunc(bandwidth); +} + +static u32 dce6_data_return_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the display Data return Bandwidth */ + fixed20_12 return_efficiency; /* 0.8 */ + fixed20_12 sclk, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + sclk.full = dfixed_const(wm->sclk); + sclk.full = dfixed_div(sclk, a); + a.full = dfixed_const(10); + return_efficiency.full = dfixed_const(8); + return_efficiency.full = dfixed_div(return_efficiency, a); + a.full = dfixed_const(32); + bandwidth.full = dfixed_mul(a, sclk); + bandwidth.full = dfixed_mul(bandwidth, return_efficiency); + + return dfixed_trunc(bandwidth); +} + +static u32 dce6_get_dmif_bytes_per_request(struct dce6_wm_params *wm) +{ + return 32; +} + +static u32 dce6_dmif_request_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the DMIF Request Bandwidth */ + fixed20_12 disp_clk_request_efficiency; /* 0.8 */ + fixed20_12 disp_clk, sclk, bandwidth; + fixed20_12 a, b1, b2; + u32 min_bandwidth; + + a.full = dfixed_const(1000); + disp_clk.full = dfixed_const(wm->disp_clk); + disp_clk.full = dfixed_div(disp_clk, a); + a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm) / 2); + b1.full = dfixed_mul(a, disp_clk); + + a.full = dfixed_const(1000); + sclk.full = dfixed_const(wm->sclk); + sclk.full = dfixed_div(sclk, a); + a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm)); + b2.full = dfixed_mul(a, sclk); + + a.full = dfixed_const(10); + disp_clk_request_efficiency.full = dfixed_const(8); + disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a); + + min_bandwidth = min(dfixed_trunc(b1), dfixed_trunc(b2)); + + a.full = dfixed_const(min_bandwidth); + bandwidth.full = dfixed_mul(a, disp_clk_request_efficiency); + + return dfixed_trunc(bandwidth); +} + +static u32 dce6_available_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the Available bandwidth. Display can use this temporarily but not in average. */ + u32 dram_bandwidth = dce6_dram_bandwidth(wm); + u32 data_return_bandwidth = dce6_data_return_bandwidth(wm); + u32 dmif_req_bandwidth = dce6_dmif_request_bandwidth(wm); + + return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth)); +} + +static u32 dce6_average_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the display mode Average Bandwidth + * DisplayMode should contain the source and destination dimensions, + * timing, etc. + */ + fixed20_12 bpp; + fixed20_12 line_time; + fixed20_12 src_width; + fixed20_12 bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + line_time.full = dfixed_const(wm->active_time + wm->blank_time); + line_time.full = dfixed_div(line_time, a); + bpp.full = dfixed_const(wm->bytes_per_pixel); + src_width.full = dfixed_const(wm->src_width); + bandwidth.full = dfixed_mul(src_width, bpp); + bandwidth.full = dfixed_mul(bandwidth, wm->vsc); + bandwidth.full = dfixed_div(bandwidth, line_time); + + return dfixed_trunc(bandwidth); +} + +static u32 dce6_latency_watermark(struct dce6_wm_params *wm) +{ + /* First calcualte the latency in ns */ + u32 mc_latency = 2000; /* 2000 ns. */ + u32 available_bandwidth = dce6_available_bandwidth(wm); + u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth; + u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth; + u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */ + u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) + + (wm->num_heads * cursor_line_pair_return_time); + u32 latency = mc_latency + other_heads_data_return_time + dc_latency; + u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time; + u32 tmp, dmif_size = 12288; + fixed20_12 a, b, c; + + if (wm->num_heads == 0) + return 0; + + a.full = dfixed_const(2); + b.full = dfixed_const(1); + if ((wm->vsc.full > a.full) || + ((wm->vsc.full > b.full) && (wm->vtaps >= 3)) || + (wm->vtaps >= 5) || + ((wm->vsc.full >= a.full) && wm->interlaced)) + max_src_lines_per_dst_line = 4; + else + max_src_lines_per_dst_line = 2; + + a.full = dfixed_const(available_bandwidth); + b.full = dfixed_const(wm->num_heads); + a.full = dfixed_div(a, b); + + b.full = dfixed_const(mc_latency + 512); + c.full = dfixed_const(wm->disp_clk); + b.full = dfixed_div(b, c); + + c.full = dfixed_const(dmif_size); + b.full = dfixed_div(c, b); + + tmp = min(dfixed_trunc(a), dfixed_trunc(b)); + + b.full = dfixed_const(1000); + c.full = dfixed_const(wm->disp_clk); + b.full = dfixed_div(c, b); + c.full = dfixed_const(wm->bytes_per_pixel); + b.full = dfixed_mul(b, c); + + lb_fill_bw = min(tmp, dfixed_trunc(b)); + + a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); + b.full = dfixed_const(1000); + c.full = dfixed_const(lb_fill_bw); + b.full = dfixed_div(c, b); + a.full = dfixed_div(a, b); + line_fill_time = dfixed_trunc(a); + + if (line_fill_time < wm->active_time) + return latency; + else + return latency + (line_fill_time - wm->active_time); + +} + +static bool dce6_average_bandwidth_vs_dram_bandwidth_for_display(struct dce6_wm_params *wm) +{ + if (dce6_average_bandwidth(wm) <= + (dce6_dram_bandwidth_for_display(wm) / wm->num_heads)) + return true; + else + return false; +}; + +static bool dce6_average_bandwidth_vs_available_bandwidth(struct dce6_wm_params *wm) +{ + if (dce6_average_bandwidth(wm) <= + (dce6_available_bandwidth(wm) / wm->num_heads)) + return true; + else + return false; +}; + +static bool dce6_check_latency_hiding(struct dce6_wm_params *wm) +{ + u32 lb_partitions = wm->lb_size / wm->src_width; + u32 line_time = wm->active_time + wm->blank_time; + u32 latency_tolerant_lines; + u32 latency_hiding; + fixed20_12 a; + + a.full = dfixed_const(1); + if (wm->vsc.full > a.full) + latency_tolerant_lines = 1; + else { + if (lb_partitions <= (wm->vtaps + 1)) + latency_tolerant_lines = 1; + else + latency_tolerant_lines = 2; + } + + latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time); + + if (dce6_latency_watermark(wm) <= latency_hiding) + return true; + else + return false; +} + +static void dce6_program_watermarks(struct radeon_device *rdev, + struct radeon_crtc *radeon_crtc, + u32 lb_size, u32 num_heads) +{ + struct drm_display_mode *mode = &radeon_crtc->base.mode; + struct dce6_wm_params wm; + u32 pixel_period; + u32 line_time = 0; + u32 latency_watermark_a = 0, latency_watermark_b = 0; + u32 priority_a_mark = 0, priority_b_mark = 0; + u32 priority_a_cnt = PRIORITY_OFF; + u32 priority_b_cnt = PRIORITY_OFF; + u32 tmp, arb_control3; + fixed20_12 a, b, c; + + if (radeon_crtc->base.enabled && num_heads && mode) { + pixel_period = 1000000 / (u32)mode->clock; + line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + priority_a_cnt = 0; + priority_b_cnt = 0; + + wm.yclk = rdev->pm.current_mclk * 10; + wm.sclk = rdev->pm.current_sclk * 10; + wm.disp_clk = mode->clock; + wm.src_width = mode->crtc_hdisplay; + wm.active_time = mode->crtc_hdisplay * pixel_period; + wm.blank_time = line_time - wm.active_time; + wm.interlaced = false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + wm.interlaced = true; + wm.vsc = radeon_crtc->vsc; + wm.vtaps = 1; + if (radeon_crtc->rmx_type != RMX_OFF) + wm.vtaps = 2; + wm.bytes_per_pixel = 4; /* XXX: get this from fb config */ + wm.lb_size = lb_size; + if (rdev->family == CHIP_ARUBA) + wm.dram_channels = evergreen_get_number_of_dram_channels(rdev); + else + wm.dram_channels = si_get_number_of_dram_channels(rdev); + wm.num_heads = num_heads; + + /* set for high clocks */ + latency_watermark_a = min(dce6_latency_watermark(&wm), (u32)65535); + /* set for low clocks */ + /* wm.yclk = low clk; wm.sclk = low clk */ + latency_watermark_b = min(dce6_latency_watermark(&wm), (u32)65535); + + /* possibly force display priority to high */ + /* should really do this at mode validation time... */ + if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm) || + !dce6_average_bandwidth_vs_available_bandwidth(&wm) || + !dce6_check_latency_hiding(&wm) || + (rdev->disp_priority == 2)) { + DRM_DEBUG_KMS("force priority to high\n"); + priority_a_cnt |= PRIORITY_ALWAYS_ON; + priority_b_cnt |= PRIORITY_ALWAYS_ON; + } + + a.full = dfixed_const(1000); + b.full = dfixed_const(mode->clock); + b.full = dfixed_div(b, a); + c.full = dfixed_const(latency_watermark_a); + c.full = dfixed_mul(c, b); + c.full = dfixed_mul(c, radeon_crtc->hsc); + c.full = dfixed_div(c, a); + a.full = dfixed_const(16); + c.full = dfixed_div(c, a); + priority_a_mark = dfixed_trunc(c); + priority_a_cnt |= priority_a_mark & PRIORITY_MARK_MASK; + + a.full = dfixed_const(1000); + b.full = dfixed_const(mode->clock); + b.full = dfixed_div(b, a); + c.full = dfixed_const(latency_watermark_b); + c.full = dfixed_mul(c, b); + c.full = dfixed_mul(c, radeon_crtc->hsc); + c.full = dfixed_div(c, a); + a.full = dfixed_const(16); + c.full = dfixed_div(c, a); + priority_b_mark = dfixed_trunc(c); + priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; + } + + /* select wm A */ + arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset); + tmp = arb_control3; + tmp &= ~LATENCY_WATERMARK_MASK(3); + tmp |= LATENCY_WATERMARK_MASK(1); + WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp); + WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset, + (LATENCY_LOW_WATERMARK(latency_watermark_a) | + LATENCY_HIGH_WATERMARK(line_time))); + /* select wm B */ + tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset); + tmp &= ~LATENCY_WATERMARK_MASK(3); + tmp |= LATENCY_WATERMARK_MASK(2); + WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp); + WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset, + (LATENCY_LOW_WATERMARK(latency_watermark_b) | + LATENCY_HIGH_WATERMARK(line_time))); + /* restore original selection */ + WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, arb_control3); + + /* write the priority marks */ + WREG32(PRIORITY_A_CNT + radeon_crtc->crtc_offset, priority_a_cnt); + WREG32(PRIORITY_B_CNT + radeon_crtc->crtc_offset, priority_b_cnt); + +} + +void dce6_bandwidth_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + u32 num_heads = 0, lb_size; + int i; + + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i]->base.enabled) + num_heads++; + } + for (i = 0; i < rdev->num_crtc; i += 2) { + mode0 = &rdev->mode_info.crtcs[i]->base.mode; + mode1 = &rdev->mode_info.crtcs[i+1]->base.mode; + lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1); + dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); + lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0); + dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i+1], lb_size, num_heads); + } +} + +/* + * Core functions + */ +static void si_tiling_mode_table_init(struct radeon_device *rdev) +{ + const u32 num_tile_mode_states = 32; + u32 reg_offset, gb_tile_moden, split_equal_to_row_size; + + switch (rdev->config.si.mem_row_size_in_kb) { + case 1: + split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_1KB; + break; + case 2: + default: + split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_2KB; + break; + case 4: + split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_4KB; + break; + } + + if ((rdev->family == CHIP_TAHITI) || + (rdev->family == CHIP_PITCAIRN)) { + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { + switch (reg_offset) { + case 0: /* non-AA compressed depth or any compressed stencil */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 1: /* 2xAA/4xAA compressed depth only */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 2: /* 8xAA compressed depth only */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 3: /* 2xAA/4xAA compressed depth with stencil (for depth buffer) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 4: /* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 5: /* Uncompressed 16bpp depth - and stencil buffer allocated with it */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 6: /* Uncompressed 32bpp depth - and stencil buffer allocated with it */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 7: /* Uncompressed 8bpp stencil without depth (drivers typically do not use) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 8: /* 1D and 1D Array Surfaces */ + gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 9: /* Displayable maps. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 10: /* Display 8bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 11: /* Display 16bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 12: /* Display 32bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 13: /* Thin. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 14: /* Thin 8 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 15: /* Thin 16 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 16: /* Thin 32 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 17: /* Thin 64 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 21: /* 8 bpp PRT. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 22: /* 16 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 23: /* 32 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 24: /* 64 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 25: /* 128 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) | + NUM_BANKS(ADDR_SURF_8_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + default: + gb_tile_moden = 0; + break; + } + WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden); + } + } else if (rdev->family == CHIP_VERDE) { + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { + switch (reg_offset) { + case 0: /* non-AA compressed depth or any compressed stencil */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 1: /* 2xAA/4xAA compressed depth only */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 2: /* 8xAA compressed depth only */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 3: /* 2xAA/4xAA compressed depth with stencil (for depth buffer) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 4: /* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 5: /* Uncompressed 16bpp depth - and stencil buffer allocated with it */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 6: /* Uncompressed 32bpp depth - and stencil buffer allocated with it */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 7: /* Uncompressed 8bpp stencil without depth (drivers typically do not use) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 8: /* 1D and 1D Array Surfaces */ + gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 9: /* Displayable maps. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 10: /* Display 8bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 11: /* Display 16bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 12: /* Display 32bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 13: /* Thin. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 14: /* Thin 8 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 15: /* Thin 16 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 16: /* Thin 32 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 17: /* Thin 64 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 21: /* 8 bpp PRT. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 22: /* 16 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 23: /* 32 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 24: /* 64 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 25: /* 128 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) | + NUM_BANKS(ADDR_SURF_8_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + default: + gb_tile_moden = 0; + break; + } + WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden); + } + } else + DRM_ERROR("unknown asic: 0x%x\n", rdev->family); +} + +static void si_select_se_sh(struct radeon_device *rdev, + u32 se_num, u32 sh_num) +{ + u32 data = INSTANCE_BROADCAST_WRITES; + + if ((se_num == 0xffffffff) && (sh_num == 0xffffffff)) + data = SH_BROADCAST_WRITES | SE_BROADCAST_WRITES; + else if (se_num == 0xffffffff) + data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num); + else if (sh_num == 0xffffffff) + data |= SH_BROADCAST_WRITES | SE_INDEX(se_num); + else + data |= SH_INDEX(sh_num) | SE_INDEX(se_num); + WREG32(GRBM_GFX_INDEX, data); +} + +static u32 si_create_bitmask(u32 bit_width) +{ + u32 i, mask = 0; + + for (i = 0; i < bit_width; i++) { + mask <<= 1; + mask |= 1; + } + return mask; +} + +static u32 si_get_cu_enabled(struct radeon_device *rdev, u32 cu_per_sh) +{ + u32 data, mask; + + data = RREG32(CC_GC_SHADER_ARRAY_CONFIG); + if (data & 1) + data &= INACTIVE_CUS_MASK; + else + data = 0; + data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG); + + data >>= INACTIVE_CUS_SHIFT; + + mask = si_create_bitmask(cu_per_sh); + + return ~data & mask; +} + +static void si_setup_spi(struct radeon_device *rdev, + u32 se_num, u32 sh_per_se, + u32 cu_per_sh) +{ + int i, j, k; + u32 data, mask, active_cu; + + for (i = 0; i < se_num; i++) { + for (j = 0; j < sh_per_se; j++) { + si_select_se_sh(rdev, i, j); + data = RREG32(SPI_STATIC_THREAD_MGMT_3); + active_cu = si_get_cu_enabled(rdev, cu_per_sh); + + mask = 1; + for (k = 0; k < 16; k++) { + mask <<= k; + if (active_cu & mask) { + data &= ~mask; + WREG32(SPI_STATIC_THREAD_MGMT_3, data); + break; + } + } + } + } + si_select_se_sh(rdev, 0xffffffff, 0xffffffff); +} + +static u32 si_get_rb_disabled(struct radeon_device *rdev, + u32 max_rb_num, u32 se_num, + u32 sh_per_se) +{ + u32 data, mask; + + data = RREG32(CC_RB_BACKEND_DISABLE); + if (data & 1) + data &= BACKEND_DISABLE_MASK; + else + data = 0; + data |= RREG32(GC_USER_RB_BACKEND_DISABLE); + + data >>= BACKEND_DISABLE_SHIFT; + + mask = si_create_bitmask(max_rb_num / se_num / sh_per_se); + + return data & mask; +} + +static void si_setup_rb(struct radeon_device *rdev, + u32 se_num, u32 sh_per_se, + u32 max_rb_num) +{ + int i, j; + u32 data, mask; + u32 disabled_rbs = 0; + u32 enabled_rbs = 0; + + for (i = 0; i < se_num; i++) { + for (j = 0; j < sh_per_se; j++) { + si_select_se_sh(rdev, i, j); + data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); + disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH); + } + } + si_select_se_sh(rdev, 0xffffffff, 0xffffffff); + + mask = 1; + for (i = 0; i < max_rb_num; i++) { + if (!(disabled_rbs & mask)) + enabled_rbs |= mask; + mask <<= 1; + } + + for (i = 0; i < se_num; i++) { + si_select_se_sh(rdev, i, 0xffffffff); + data = 0; + for (j = 0; j < sh_per_se; j++) { + switch (enabled_rbs & 3) { + case 1: + data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2); + break; + case 2: + data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2); + break; + case 3: + default: + data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2); + break; + } + enabled_rbs >>= 2; + } + WREG32(PA_SC_RASTER_CONFIG, data); + } + si_select_se_sh(rdev, 0xffffffff, 0xffffffff); +} + +static void si_gpu_init(struct radeon_device *rdev) +{ + u32 gb_addr_config = 0; + u32 mc_shared_chmap, mc_arb_ramcfg; + u32 sx_debug_1; + u32 hdp_host_path_cntl; + u32 tmp; + int i, j; + + switch (rdev->family) { + case CHIP_TAHITI: + rdev->config.si.max_shader_engines = 2; + rdev->config.si.max_tile_pipes = 12; + rdev->config.si.max_cu_per_sh = 8; + rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_backends_per_se = 4; + rdev->config.si.max_texture_channel_caches = 12; + rdev->config.si.max_gprs = 256; + rdev->config.si.max_gs_threads = 32; + rdev->config.si.max_hw_contexts = 8; + + rdev->config.si.sc_prim_fifo_size_frontend = 0x20; + rdev->config.si.sc_prim_fifo_size_backend = 0x100; + rdev->config.si.sc_hiz_tile_fifo_size = 0x30; + rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_PITCAIRN: + rdev->config.si.max_shader_engines = 2; + rdev->config.si.max_tile_pipes = 8; + rdev->config.si.max_cu_per_sh = 5; + rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_backends_per_se = 4; + rdev->config.si.max_texture_channel_caches = 8; + rdev->config.si.max_gprs = 256; + rdev->config.si.max_gs_threads = 32; + rdev->config.si.max_hw_contexts = 8; + + rdev->config.si.sc_prim_fifo_size_frontend = 0x20; + rdev->config.si.sc_prim_fifo_size_backend = 0x100; + rdev->config.si.sc_hiz_tile_fifo_size = 0x30; + rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_VERDE: + default: + rdev->config.si.max_shader_engines = 1; + rdev->config.si.max_tile_pipes = 4; + rdev->config.si.max_cu_per_sh = 2; + rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_backends_per_se = 4; + rdev->config.si.max_texture_channel_caches = 4; + rdev->config.si.max_gprs = 256; + rdev->config.si.max_gs_threads = 32; + rdev->config.si.max_hw_contexts = 8; + + rdev->config.si.sc_prim_fifo_size_frontend = 0x20; + rdev->config.si.sc_prim_fifo_size_backend = 0x40; + rdev->config.si.sc_hiz_tile_fifo_size = 0x30; + rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN; + break; + } + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + + WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); + + evergreen_fix_pci_max_read_req_size(rdev); + + WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); + mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + + rdev->config.si.num_tile_pipes = rdev->config.si.max_tile_pipes; + rdev->config.si.mem_max_burst_length_bytes = 256; + tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; + rdev->config.si.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; + if (rdev->config.si.mem_row_size_in_kb > 4) + rdev->config.si.mem_row_size_in_kb = 4; + /* XXX use MC settings? */ + rdev->config.si.shader_engine_tile_size = 32; + rdev->config.si.num_gpus = 1; + rdev->config.si.multi_gpu_tile_size = 64; + + /* fix up row size */ + gb_addr_config &= ~ROW_SIZE_MASK; + switch (rdev->config.si.mem_row_size_in_kb) { + case 1: + default: + gb_addr_config |= ROW_SIZE(0); + break; + case 2: + gb_addr_config |= ROW_SIZE(1); + break; + case 4: + gb_addr_config |= ROW_SIZE(2); + break; + } + + /* setup tiling info dword. gb_addr_config is not adequate since it does + * not have bank info, so create a custom tiling dword. + * bits 3:0 num_pipes + * bits 7:4 num_banks + * bits 11:8 group_size + * bits 15:12 row_size + */ + rdev->config.si.tile_config = 0; + switch (rdev->config.si.num_tile_pipes) { + case 1: + rdev->config.si.tile_config |= (0 << 0); + break; + case 2: + rdev->config.si.tile_config |= (1 << 0); + break; + case 4: + rdev->config.si.tile_config |= (2 << 0); + break; + case 8: + default: + /* XXX what about 12? */ + rdev->config.si.tile_config |= (3 << 0); + break; + } + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ + rdev->config.si.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.si.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.si.tile_config |= 2 << 4; + break; + } + rdev->config.si.tile_config |= + ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; + rdev->config.si.tile_config |= + ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; + + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); + WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config); + WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config); + + si_tiling_mode_table_init(rdev); + + si_setup_rb(rdev, rdev->config.si.max_shader_engines, + rdev->config.si.max_sh_per_se, + rdev->config.si.max_backends_per_se); + + si_setup_spi(rdev, rdev->config.si.max_shader_engines, + rdev->config.si.max_sh_per_se, + rdev->config.si.max_cu_per_sh); + + + /* set HW defaults for 3D engine */ + WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | + ROQ_IB2_START(0x2b))); + WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); + + sx_debug_1 = RREG32(SX_DEBUG_1); + WREG32(SX_DEBUG_1, sx_debug_1); + + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); + + WREG32(PA_SC_FIFO_SIZE, (SC_FRONTEND_PRIM_FIFO_SIZE(rdev->config.si.sc_prim_fifo_size_frontend) | + SC_BACKEND_PRIM_FIFO_SIZE(rdev->config.si.sc_prim_fifo_size_backend) | + SC_HIZ_TILE_FIFO_SIZE(rdev->config.si.sc_hiz_tile_fifo_size) | + SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.si.sc_earlyz_tile_fifo_size))); + + WREG32(VGT_NUM_INSTANCES, 1); + + WREG32(CP_PERFMON_CNTL, 0); + + WREG32(SQ_CONFIG, 0); + + WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | + FORCE_EOV_MAX_REZ_CNT(255))); + + WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | + AUTO_INVLD_EN(ES_AND_GS_AUTO)); + + WREG32(VGT_GS_VERTEX_REUSE, 16); + WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + + WREG32(CB_PERFCOUNTER0_SELECT0, 0); + WREG32(CB_PERFCOUNTER0_SELECT1, 0); + WREG32(CB_PERFCOUNTER1_SELECT0, 0); + WREG32(CB_PERFCOUNTER1_SELECT1, 0); + WREG32(CB_PERFCOUNTER2_SELECT0, 0); + WREG32(CB_PERFCOUNTER2_SELECT1, 0); + WREG32(CB_PERFCOUNTER3_SELECT0, 0); + WREG32(CB_PERFCOUNTER3_SELECT1, 0); + + tmp = RREG32(HDP_MISC_CNTL); + tmp |= HDP_FLUSH_INVALIDATE_CACHE; + WREG32(HDP_MISC_CNTL, tmp); + + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); + + DRM_UDELAY(50); +} + +/* + * GPU scratch registers helpers function. + */ +static void si_scratch_init(struct radeon_device *rdev) +{ + int i; + + rdev->scratch.num_reg = 7; + rdev->scratch.reg_base = SCRATCH_REG0; + for (i = 0; i < rdev->scratch.num_reg; i++) { + rdev->scratch.free[i] = true; + rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); + } +} + +void si_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) +{ + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + + /* flush read cache over gart */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | + PACKET3_TC_ACTION_ENA | + PACKET3_SH_KCACHE_ACTION_ENA | + PACKET3_SH_ICACHE_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ + /* EVENT_WRITE_EOP - flush caches, send int */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5)); + radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); + radeon_ring_write(ring, fence->seq); + radeon_ring_write(ring, 0); +} + +/* + * IB stuff + */ +void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) +{ + struct radeon_ring *ring = &rdev->ring[ib->ring]; + u32 header; + + if (ib->is_const_ib) { + /* set switch buffer packet before const IB */ + radeon_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + radeon_ring_write(ring, 0); + + header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); + } else { + u32 next_rptr; + if (ring->rptr_save_reg) { + next_rptr = ring->wptr + 3 + 4 + 8; + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, ((ring->rptr_save_reg - + PACKET3_SET_CONFIG_REG_START) >> 2)); + radeon_ring_write(ring, next_rptr); + } else if (rdev->wb.enabled) { + next_rptr = ring->wptr + 5 + 4 + 8; + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + radeon_ring_write(ring, (1 << 8)); + radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); + radeon_ring_write(ring, next_rptr); + } + + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); + } + + radeon_ring_write(ring, header); + radeon_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); + radeon_ring_write(ring, ib->length_dw | + (ib->vm ? (ib->vm->id << 24) : 0)); + + if (!ib->is_const_ib) { + /* flush read cache over gart for this vmid */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, ib->vm ? ib->vm->id : 0); + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | + PACKET3_TC_ACTION_ENA | + PACKET3_SH_KCACHE_ACTION_ENA | + PACKET3_SH_ICACHE_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ + } +} + +/* + * CP. + */ +static void si_cp_enable(struct radeon_device *rdev, bool enable) +{ + if (enable) + WREG32(CP_ME_CNTL, 0); + else { + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); + WREG32(SCRATCH_UMSK, 0); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + } + DRM_UDELAY(50); +} + +static int si_cp_load_microcode(struct radeon_device *rdev) +{ + const __be32 *fw_data; + int i; + + if (!rdev->me_fw || !rdev->pfp_fw) + return -EINVAL; + + si_cp_enable(rdev, false); + + /* PFP */ + fw_data = (const __be32 *)rdev->pfp_fw->data; + WREG32(CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < SI_PFP_UCODE_SIZE; i++) + WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); + WREG32(CP_PFP_UCODE_ADDR, 0); + + /* CE */ + fw_data = (const __be32 *)rdev->ce_fw->data; + WREG32(CP_CE_UCODE_ADDR, 0); + for (i = 0; i < SI_CE_UCODE_SIZE; i++) + WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++)); + WREG32(CP_CE_UCODE_ADDR, 0); + + /* ME */ + fw_data = (const __be32 *)rdev->me_fw->data; + WREG32(CP_ME_RAM_WADDR, 0); + for (i = 0; i < SI_PM4_UCODE_SIZE; i++) + WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); + WREG32(CP_ME_RAM_WADDR, 0); + + WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_CE_UCODE_ADDR, 0); + WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_RADDR, 0); + return 0; +} + +static int si_cp_start(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r, i; + + r = radeon_ring_lock(rdev, ring, 7 + 4); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + /* init the CP */ + radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(ring, 0x1); + radeon_ring_write(ring, 0x0); + radeon_ring_write(ring, rdev->config.si.max_hw_contexts - 1); + radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0); + + /* init the CE partitions */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2)); + radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE)); + radeon_ring_write(ring, 0xc000); + radeon_ring_write(ring, 0xe000); + radeon_ring_unlock_commit(rdev, ring); + + si_cp_enable(rdev, true); + + r = radeon_ring_lock(rdev, ring, si_default_size + 10); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + + /* setup clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + for (i = 0; i < si_default_size; i++) + radeon_ring_write(ring, si_default_state[i]); + + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); + + /* set clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); + radeon_ring_write(ring, 0); + + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(ring, 0x00000316); + radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + radeon_ring_write(ring, 0x00000010); /* VGT_OUT_DEALLOC_CNTL */ + + radeon_ring_unlock_commit(rdev, ring); + + for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) { + ring = &rdev->ring[i]; + r = radeon_ring_lock(rdev, ring, 2); + + /* clear the compute context state */ + radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0)); + radeon_ring_write(ring, 0); + + radeon_ring_unlock_commit(rdev, ring); + } + + return 0; +} + +static void si_cp_fini(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + si_cp_enable(rdev, false); + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + radeon_ring_fini(rdev, ring); + radeon_scratch_free(rdev, ring->rptr_save_reg); + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + radeon_ring_fini(rdev, ring); + radeon_scratch_free(rdev, ring->rptr_save_reg); + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + radeon_ring_fini(rdev, ring); + radeon_scratch_free(rdev, ring->rptr_save_reg); +} + +static int si_cp_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + u32 tmp; + u32 rb_bufsz; + int r; + + /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ + WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | + SOFT_RESET_PA | + SOFT_RESET_VGT | + SOFT_RESET_SPI | + SOFT_RESET_SX)); + RREG32(GRBM_SOFT_RESET); + DRM_MDELAY(15); + WREG32(GRBM_SOFT_RESET, 0); + RREG32(GRBM_SOFT_RESET); + + WREG32(CP_SEM_WAIT_TIMER, 0x0); + WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); + + WREG32(CP_DEBUG, 0); + WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); + + /* ring 0 - compute and gfx */ + /* Set ring buffer size */ + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB0_CNTL, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB0_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); + WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); + + if (rdev->wb.enabled) + WREG32(SCRATCH_UMSK, 0xff); + else { + tmp |= RB_NO_UPDATE; + WREG32(SCRATCH_UMSK, 0); + } + + DRM_MDELAY(1); + WREG32(CP_RB0_CNTL, tmp); + + WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); + + ring->rptr = RREG32(CP_RB0_RPTR); + + /* ring1 - compute only */ + /* Set ring buffer size */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB1_CNTL, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB1_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); + WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); + + DRM_MDELAY(1); + WREG32(CP_RB1_CNTL, tmp); + + WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); + + ring->rptr = RREG32(CP_RB1_RPTR); + + /* ring2 - compute only */ + /* Set ring buffer size */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB2_CNTL, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB2_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); + WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); + + DRM_MDELAY(1); + WREG32(CP_RB2_CNTL, tmp); + + WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); + + ring->rptr = RREG32(CP_RB2_RPTR); + + /* start the rings */ + si_cp_start(rdev); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = true; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = true; + r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + return r; + } + r = radeon_ring_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); + if (r) { + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + } + r = radeon_ring_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); + if (r) { + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + } + + return 0; +} + +bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 srbm_status; + u32 grbm_status, grbm_status2; + u32 grbm_status_se0, grbm_status_se1; + + srbm_status = RREG32(SRBM_STATUS); + grbm_status = RREG32(GRBM_STATUS); + grbm_status2 = RREG32(GRBM_STATUS2); + grbm_status_se0 = RREG32(GRBM_STATUS_SE0); + grbm_status_se1 = RREG32(GRBM_STATUS_SE1); + if (!(grbm_status & GUI_ACTIVE)) { + radeon_ring_lockup_update(ring); + return false; + } + /* force CP activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +static void si_gpu_soft_reset_gfx(struct radeon_device *rdev) +{ + u32 grbm_reset = 0; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + return; + + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", + RREG32(GRBM_STATUS2)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); + + /* reset all the gfx blocks */ + grbm_reset = (SOFT_RESET_CP | + SOFT_RESET_CB | + SOFT_RESET_DB | + SOFT_RESET_GDS | + SOFT_RESET_PA | + SOFT_RESET_SC | + SOFT_RESET_BCI | + SOFT_RESET_SPI | + SOFT_RESET_SX | + SOFT_RESET_TC | + SOFT_RESET_TA | + SOFT_RESET_VGT | + SOFT_RESET_IA); + + dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); + WREG32(GRBM_SOFT_RESET, grbm_reset); + (void)RREG32(GRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(GRBM_SOFT_RESET, 0); + (void)RREG32(GRBM_SOFT_RESET); + + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", + RREG32(GRBM_STATUS2)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); +} + +static void si_gpu_soft_reset_dma(struct radeon_device *rdev) +{ + u32 tmp; + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + return; + + dev_info(rdev->dev, " DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); + + /* dma0 */ + tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); + + /* dma1 */ + tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); + + /* Reset dma */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); + RREG32(SRBM_SOFT_RESET); + DRM_UDELAY(50); + WREG32(SRBM_SOFT_RESET, 0); + + dev_info(rdev->dev, " DMA_STATUS_REG = 0x%08X\n", + RREG32(DMA_STATUS_REG)); +} + +static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) +{ + struct evergreen_mc_save save; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + + if (reset_mask == 0) + return 0; + + dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); + + dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", + RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); + dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", + RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + + evergreen_mc_stop(rdev, &save); + if (radeon_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + + if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) + si_gpu_soft_reset_gfx(rdev); + + if (reset_mask & RADEON_RESET_DMA) + si_gpu_soft_reset_dma(rdev); + + /* Wait a little for things to settle down */ + DRM_UDELAY(50); + + evergreen_mc_resume(rdev, &save); + return 0; +} + +int si_asic_reset(struct radeon_device *rdev) +{ + return si_gpu_soft_reset(rdev, (RADEON_RESET_GFX | + RADEON_RESET_COMPUTE | + RADEON_RESET_DMA)); +} + +/* MC */ +static void si_mc_program(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 tmp; + int i, j; + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x18) { + WREG32((0x2c14 + j), 0x00000000); + WREG32((0x2c18 + j), 0x00000000); + WREG32((0x2c1c + j), 0x00000000); + WREG32((0x2c20 + j), 0x00000000); + WREG32((0x2c24 + j), 0x00000000); + } + WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); + + evergreen_mc_stop(rdev, &save); + if (radeon_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Lockout access through VGA aperture*/ + WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); + /* Update configuration */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + rdev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + rdev->mc.vram_end >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, + rdev->vram_scratch.gpu_addr >> 12); + tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; + tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); + WREG32(MC_VM_FB_LOCATION, tmp); + /* XXX double check these! */ + WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); + WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); + WREG32(MC_VM_AGP_BASE, 0); + WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); + WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); + if (radeon_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + evergreen_mc_resume(rdev, &save); + /* we need to own VRAM, so turn off the VGA renderer here + * to stop it overwriting our objects */ + rv515_vga_render_disable(rdev); +} + +/* SI MC address space is 40 bits */ +static void si_vram_location(struct radeon_device *rdev, + struct radeon_mc *mc, u64 base) +{ + mc->vram_start = base; + if (mc->mc_vram_size > (0xFFFFFFFFFFULL - base + 1)) { + dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); + mc->real_vram_size = mc->aper_size; + mc->mc_vram_size = mc->aper_size; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %juM 0x%016jX - 0x%016jX (%juM used)\n", + (uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start, + (uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20); +} + +static void si_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +{ + u64 size_af, size_bf; + + size_af = ((0xFFFFFFFFFFULL - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; + size_bf = mc->vram_start & ~mc->gtt_base_align; + if (size_bf > size_af) { + if (mc->gtt_size > size_bf) { + dev_warn(rdev->dev, "limiting GTT\n"); + mc->gtt_size = size_bf; + } + mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; + } else { + if (mc->gtt_size > size_af) { + dev_warn(rdev->dev, "limiting GTT\n"); + mc->gtt_size = size_af; + } + mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; + } + mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; + dev_info(rdev->dev, "GTT: %juM 0x%016jX - 0x%016jX\n", + (uintmax_t)mc->gtt_size >> 20, (uintmax_t)mc->gtt_start, (uintmax_t)mc->gtt_end); +} + +static void si_vram_gtt_location(struct radeon_device *rdev, + struct radeon_mc *mc) +{ + if (mc->mc_vram_size > 0xFFC0000000ULL) { + /* leave room for at least 1024M GTT */ + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = 0xFFC0000000ULL; + mc->mc_vram_size = 0xFFC0000000ULL; + } + si_vram_location(rdev, &rdev->mc, 0); + rdev->mc.gtt_base_align = 0; + si_gtt_location(rdev, mc); +} + +static int si_mc_init(struct radeon_device *rdev) +{ + u32 tmp; + int chansize, numchan; + + /* Get VRAM informations */ + rdev->mc.vram_is_ddr = true; + tmp = RREG32(MC_ARB_RAMCFG); + if (tmp & CHANSIZE_OVERRIDE) { + chansize = 16; + } else if (tmp & CHANSIZE_MASK) { + chansize = 64; + } else { + chansize = 32; + } + tmp = RREG32(MC_SHARED_CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + numchan = 1; + break; + case 1: + numchan = 2; + break; + case 2: + numchan = 4; + break; + case 3: + numchan = 8; + break; + case 4: + numchan = 3; + break; + case 5: + numchan = 6; + break; + case 6: + numchan = 10; + break; + case 7: + numchan = 12; + break; + case 8: + numchan = 16; + break; + } + rdev->mc.vram_width = numchan * chansize; + /* Could aper size report 0 ? */ + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + /* size in MB on si */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + rdev->mc.visible_vram_size = rdev->mc.aper_size; + si_vram_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); + + return 0; +} + +/* + * GART + */ +void si_pcie_gart_tlb_flush(struct radeon_device *rdev) +{ + /* flush hdp cache */ + WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); + + /* bits 0-15 are the VM contexts0-15 */ + WREG32(VM_INVALIDATE_REQUEST, 1); +} + +static int si_pcie_gart_enable(struct radeon_device *rdev) +{ + int r, i; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; + radeon_gart_restore(rdev); + /* Setup TLB control */ + WREG32(MC_VM_MX_L1_TLB_CNTL, + (0xA << 7) | + ENABLE_L1_TLB | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + ENABLE_ADVANCED_DRIVER_MODEL | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7) | + CONTEXT1_IDENTITY_ACCESS_MODE(1)); + WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); + WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + L2_CACHE_BIGK_FRAGMENT_SIZE(0)); + /* setup context0 */ + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); + WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT0_CNTL2, 0); + WREG32(VM_CONTEXT0_CNTL, (ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT)); + + WREG32(0x15D4, 0); + WREG32(0x15D8, 0); + WREG32(0x15DC, 0); + + /* empty context1-15 */ + /* set vm size, must be a multiple of 4 */ + WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); + WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ + for (i = 1; i < 16; i++) { + if (i < 8) + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), + rdev->gart.table_addr >> 12); + else + WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2), + rdev->gart.table_addr >> 12); + } + + /* enable context1-15 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | + RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | + DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | + DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | + PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | + PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | + VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | + VALID_PROTECTION_FAULT_ENABLE_DEFAULT | + READ_PROTECTION_FAULT_ENABLE_INTERRUPT | + READ_PROTECTION_FAULT_ENABLE_DEFAULT | + WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | + WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + si_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(rdev->mc.gtt_size >> 20), + (unsigned long long)rdev->gart.table_addr); + rdev->gart.ready = true; + return 0; +} + +static void si_pcie_gart_disable(struct radeon_device *rdev) +{ + /* Disable all tables */ + WREG32(VM_CONTEXT0_CNTL, 0); + WREG32(VM_CONTEXT1_CNTL, 0); + /* Setup TLB control */ + WREG32(MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7) | + CONTEXT1_IDENTITY_ACCESS_MODE(1)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + L2_CACHE_BIGK_FRAGMENT_SIZE(0)); + radeon_gart_table_vram_unpin(rdev); +} + +static void si_pcie_gart_fini(struct radeon_device *rdev) +{ + si_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); +} + +/* vm parser */ +static bool si_vm_reg_valid(u32 reg) +{ + /* context regs are fine */ + if (reg >= 0x28000) + return true; + + /* check config regs */ + switch (reg) { + case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case VGT_VTX_VECT_EJECT_REG: + case VGT_CACHE_INVALIDATION: + case VGT_ESGS_RING_SIZE: + case VGT_GSVS_RING_SIZE: + case VGT_GS_VERTEX_REUSE: + case VGT_PRIMITIVE_TYPE: + case VGT_INDEX_TYPE: + case VGT_NUM_INDICES: + case VGT_NUM_INSTANCES: + case VGT_TF_RING_SIZE: + case VGT_HS_OFFCHIP_PARAM: + case VGT_TF_MEMORY_BASE: + case PA_CL_ENHANCE: + case PA_SU_LINE_STIPPLE_VALUE: + case PA_SC_LINE_STIPPLE_STATE: + case PA_SC_ENHANCE: + case SQC_CACHES: + case SPI_STATIC_THREAD_MGMT_1: + case SPI_STATIC_THREAD_MGMT_2: + case SPI_STATIC_THREAD_MGMT_3: + case SPI_PS_MAX_WAVE_ID: + case SPI_CONFIG_CNTL: + case SPI_CONFIG_CNTL_1: + case TA_CNTL_AUX: + return true; + default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); + return false; + } +} + +static int si_vm_packet3_ce_check(struct radeon_device *rdev, + u32 *ib, struct radeon_cs_packet *pkt) +{ + switch (pkt->opcode) { + case PACKET3_NOP: + case PACKET3_SET_BASE: + case PACKET3_SET_CE_DE_COUNTERS: + case PACKET3_LOAD_CONST_RAM: + case PACKET3_WRITE_CONST_RAM: + case PACKET3_WRITE_CONST_RAM_OFFSET: + case PACKET3_DUMP_CONST_RAM: + case PACKET3_INCREMENT_CE_COUNTER: + case PACKET3_WAIT_ON_DE_COUNTER: + case PACKET3_CE_WRITE: + break; + default: + DRM_ERROR("Invalid CE packet3: 0x%x\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +static int si_vm_packet3_gfx_check(struct radeon_device *rdev, + u32 *ib, struct radeon_cs_packet *pkt) +{ + u32 idx = pkt->idx + 1; + u32 idx_value = ib[idx]; + u32 start_reg, end_reg, reg, i; + u32 command, info; + + switch (pkt->opcode) { + case PACKET3_NOP: + case PACKET3_SET_BASE: + case PACKET3_CLEAR_STATE: + case PACKET3_INDEX_BUFFER_SIZE: + case PACKET3_DISPATCH_DIRECT: + case PACKET3_DISPATCH_INDIRECT: + case PACKET3_ALLOC_GDS: + case PACKET3_WRITE_GDS_RAM: + case PACKET3_ATOMIC_GDS: + case PACKET3_ATOMIC: + case PACKET3_OCCLUSION_QUERY: + case PACKET3_SET_PREDICATION: + case PACKET3_COND_EXEC: + case PACKET3_PRED_EXEC: + case PACKET3_DRAW_INDIRECT: + case PACKET3_DRAW_INDEX_INDIRECT: + case PACKET3_INDEX_BASE: + case PACKET3_DRAW_INDEX_2: + case PACKET3_CONTEXT_CONTROL: + case PACKET3_INDEX_TYPE: + case PACKET3_DRAW_INDIRECT_MULTI: + case PACKET3_DRAW_INDEX_AUTO: + case PACKET3_DRAW_INDEX_IMMD: + case PACKET3_NUM_INSTANCES: + case PACKET3_DRAW_INDEX_MULTI_AUTO: + case PACKET3_STRMOUT_BUFFER_UPDATE: + case PACKET3_DRAW_INDEX_OFFSET_2: + case PACKET3_DRAW_INDEX_MULTI_ELEMENT: + case PACKET3_DRAW_INDEX_INDIRECT_MULTI: + case PACKET3_MPEG_INDEX: + case PACKET3_WAIT_REG_MEM: + case PACKET3_MEM_WRITE: + case PACKET3_PFP_SYNC_ME: + case PACKET3_SURFACE_SYNC: + case PACKET3_EVENT_WRITE: + case PACKET3_EVENT_WRITE_EOP: + case PACKET3_EVENT_WRITE_EOS: + case PACKET3_SET_CONTEXT_REG: + case PACKET3_SET_CONTEXT_REG_INDIRECT: + case PACKET3_SET_SH_REG: + case PACKET3_SET_SH_REG_OFFSET: + case PACKET3_INCREMENT_DE_COUNTER: + case PACKET3_WAIT_ON_CE_COUNTER: + case PACKET3_WAIT_ON_AVAIL_BUFFER: + case PACKET3_ME_WRITE: + break; + case PACKET3_COPY_DATA: + if ((idx_value & 0xf00) == 0) { + reg = ib[idx + 3] * 4; + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_WRITE_DATA: + if ((idx_value & 0xf00) == 0) { + start_reg = ib[idx + 1] * 4; + if (idx_value & 0x10000) { + if (!si_vm_reg_valid(start_reg)) + return -EINVAL; + } else { + for (i = 0; i < (pkt->count - 2); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + } + } + break; + case PACKET3_COND_WRITE: + if (idx_value & 0x100) { + reg = ib[idx + 5] * 4; + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_COPY_DW: + if (idx_value & 0x2) { + reg = ib[idx + 3] * 4; + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_SET_CONFIG_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; + end_reg = 4 * pkt->count + start_reg - 4; + if ((start_reg < PACKET3_SET_CONFIG_REG_START) || + (start_reg >= PACKET3_SET_CONFIG_REG_END) || + (end_reg >= PACKET3_SET_CONFIG_REG_END)) { + DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); + return -EINVAL; + } + for (i = 0; i < pkt->count; i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_CP_DMA: + command = ib[idx + 4]; + info = ib[idx + 1]; + if (command & PACKET3_CP_DMA_CMD_SAS) { + /* src address space is register */ + if (((info & 0x60000000) >> 29) == 0) { + start_reg = idx_value << 2; + if (command & PACKET3_CP_DMA_CMD_SAIC) { + reg = start_reg; + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } + } + } + } + if (command & PACKET3_CP_DMA_CMD_DAS) { + /* dst address space is register */ + if (((info & 0x00300000) >> 20) == 0) { + start_reg = ib[idx + 2]; + if (command & PACKET3_CP_DMA_CMD_DAIC) { + reg = start_reg; + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } + } + } + } + break; + default: + DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +static int si_vm_packet3_compute_check(struct radeon_device *rdev, + u32 *ib, struct radeon_cs_packet *pkt) +{ + u32 idx = pkt->idx + 1; + u32 idx_value = ib[idx]; + u32 start_reg, reg, i; + + switch (pkt->opcode) { + case PACKET3_NOP: + case PACKET3_SET_BASE: + case PACKET3_CLEAR_STATE: + case PACKET3_DISPATCH_DIRECT: + case PACKET3_DISPATCH_INDIRECT: + case PACKET3_ALLOC_GDS: + case PACKET3_WRITE_GDS_RAM: + case PACKET3_ATOMIC_GDS: + case PACKET3_ATOMIC: + case PACKET3_OCCLUSION_QUERY: + case PACKET3_SET_PREDICATION: + case PACKET3_COND_EXEC: + case PACKET3_PRED_EXEC: + case PACKET3_CONTEXT_CONTROL: + case PACKET3_STRMOUT_BUFFER_UPDATE: + case PACKET3_WAIT_REG_MEM: + case PACKET3_MEM_WRITE: + case PACKET3_PFP_SYNC_ME: + case PACKET3_SURFACE_SYNC: + case PACKET3_EVENT_WRITE: + case PACKET3_EVENT_WRITE_EOP: + case PACKET3_EVENT_WRITE_EOS: + case PACKET3_SET_CONTEXT_REG: + case PACKET3_SET_CONTEXT_REG_INDIRECT: + case PACKET3_SET_SH_REG: + case PACKET3_SET_SH_REG_OFFSET: + case PACKET3_INCREMENT_DE_COUNTER: + case PACKET3_WAIT_ON_CE_COUNTER: + case PACKET3_WAIT_ON_AVAIL_BUFFER: + case PACKET3_ME_WRITE: + break; + case PACKET3_COPY_DATA: + if ((idx_value & 0xf00) == 0) { + reg = ib[idx + 3] * 4; + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_WRITE_DATA: + if ((idx_value & 0xf00) == 0) { + start_reg = ib[idx + 1] * 4; + if (idx_value & 0x10000) { + if (!si_vm_reg_valid(start_reg)) + return -EINVAL; + } else { + for (i = 0; i < (pkt->count - 2); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + } + } + break; + case PACKET3_COND_WRITE: + if (idx_value & 0x100) { + reg = ib[idx + 5] * 4; + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + case PACKET3_COPY_DW: + if (idx_value & 0x2) { + reg = ib[idx + 3] * 4; + if (!si_vm_reg_valid(reg)) + return -EINVAL; + } + break; + default: + DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode); + return -EINVAL; + } + return 0; +} + +int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) +{ + int ret = 0; + u32 idx = 0; + struct radeon_cs_packet pkt; + + do { + pkt.idx = idx; + pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]); + pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]); + pkt.one_reg_wr = 0; + switch (pkt.type) { + case PACKET_TYPE0: + dev_err(rdev->dev, "Packet0 not allowed!\n"); + ret = -EINVAL; + break; + case PACKET_TYPE2: + idx += 1; + break; + case PACKET_TYPE3: + pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]); + if (ib->is_const_ib) + ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); + else { + switch (ib->ring) { + case RADEON_RING_TYPE_GFX_INDEX: + ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); + break; + case CAYMAN_RING_TYPE_CP1_INDEX: + case CAYMAN_RING_TYPE_CP2_INDEX: + ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); + break; + default: + dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->ring); + ret = -EINVAL; + break; + } + } + idx += pkt.count + 2; + break; + default: + dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); + ret = -EINVAL; + break; + } + if (ret) + break; + } while (idx < ib->length_dw); + + return ret; +} + +/* + * vm + */ +int si_vm_init(struct radeon_device *rdev) +{ + /* number of VMs */ + rdev->vm_manager.nvm = 16; + /* base offset of vram pages */ + rdev->vm_manager.vram_base_offset = 0; + + return 0; +} + +void si_vm_fini(struct radeon_device *rdev) +{ +} + +/** + * si_vm_set_page - update the page tables using the CP + * + * @rdev: radeon_device pointer + * @pe: addr of the page entry + * @addr: dst addr to write into pe + * @count: number of page entries to update + * @incr: increase next addr by incr bytes + * @flags: access flags + * + * Update the page tables using the CP (cayman-si). + */ +void si_vm_set_page(struct radeon_device *rdev, uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags) +{ + struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; + uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); + uint64_t value; + unsigned ndw; + + if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) { + while (count) { + ndw = 2 + count * 2; + if (ndw > 0x3FFE) + ndw = 0x3FFE; + + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw)); + radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | + WRITE_DATA_DST_SEL(1))); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe)); + for (; ndw > 2; ndw -= 2, --count, pe += 8) { + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + } else if (flags & RADEON_VM_PAGE_VALID) { + value = addr; + } else { + value = 0; + } + addr += incr; + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } + } + } else { + /* DMA */ + if (flags & RADEON_VM_PAGE_SYSTEM) { + while (count) { + ndw = count * 2; + if (ndw > 0xFFFFE) + ndw = 0xFFFFE; + + /* for non-physically contiguous pages (system) */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw)); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe) & 0xff); + for (; ndw > 0; ndw -= 2, --count, pe += 8) { + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + } else if (flags & RADEON_VM_PAGE_VALID) { + value = addr; + } else { + value = 0; + } + addr += incr; + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } + } + } else { + while (count) { + ndw = count * 2; + if (ndw > 0xFFFFE) + ndw = 0xFFFFE; + + if (flags & RADEON_VM_PAGE_VALID) + value = addr; + else + value = 0; + /* for physically contiguous pages (vram) */ + radeon_ring_write(ring, DMA_PTE_PDE_PACKET(ndw)); + radeon_ring_write(ring, pe); /* dst addr */ + radeon_ring_write(ring, upper_32_bits(pe) & 0xff); + radeon_ring_write(ring, r600_flags); /* mask */ + radeon_ring_write(ring, 0); + radeon_ring_write(ring, value); /* value */ + radeon_ring_write(ring, upper_32_bits(value)); + radeon_ring_write(ring, incr); /* increment size */ + radeon_ring_write(ring, 0); + pe += ndw * 4; + addr += (ndw / 2) * incr; + count -= ndw / 2; + } + } + } +} + +void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) +{ + struct radeon_ring *ring = &rdev->ring[ridx]; + + if (vm == NULL) + return; + + /* write new base address */ + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | + WRITE_DATA_DST_SEL(0))); + + if (vm->id < 8) { + radeon_ring_write(ring, + (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2); + } else { + radeon_ring_write(ring, + (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id - 8) << 2)) >> 2); + } + radeon_ring_write(ring, 0); + radeon_ring_write(ring, vm->pd_gpu_addr >> 12); + + /* flush hdp cache */ + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | + WRITE_DATA_DST_SEL(0))); + radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 0x1); + + /* bits 0-15 are the VM contexts0-15 */ + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | + WRITE_DATA_DST_SEL(0))); + radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 1 << vm->id); + + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); +} + +void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) +{ + struct radeon_ring *ring = &rdev->ring[ridx]; + + if (vm == NULL) + return; + + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + if (vm->id < 8) { + radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2)); + } else { + radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id - 8) << 2)) >> 2)); + } + radeon_ring_write(ring, vm->pd_gpu_addr >> 12); + + /* flush hdp cache */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2)); + radeon_ring_write(ring, 1); + + /* bits 0-7 are the VM contexts0-7 */ + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); + radeon_ring_write(ring, 1 << vm->id); +} + +/* + * RLC + */ +void si_rlc_fini(struct radeon_device *rdev) +{ + int r; + + /* save restore block */ + if (rdev->rlc.save_restore_obj) { + r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); + if (unlikely(r != 0)) + dev_warn(rdev->dev, "(%d) reserve RLC sr bo failed\n", r); + radeon_bo_unpin(rdev->rlc.save_restore_obj); + radeon_bo_unreserve(rdev->rlc.save_restore_obj); + + radeon_bo_unref(&rdev->rlc.save_restore_obj); + rdev->rlc.save_restore_obj = NULL; + } + + /* clear state block */ + if (rdev->rlc.clear_state_obj) { + r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); + if (unlikely(r != 0)) + dev_warn(rdev->dev, "(%d) reserve RLC c bo failed\n", r); + radeon_bo_unpin(rdev->rlc.clear_state_obj); + radeon_bo_unreserve(rdev->rlc.clear_state_obj); + + radeon_bo_unref(&rdev->rlc.clear_state_obj); + rdev->rlc.clear_state_obj = NULL; + } +} + +int si_rlc_init(struct radeon_device *rdev) +{ + int r; + + /* save restore block */ + if (rdev->rlc.save_restore_obj == NULL) { + r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_VRAM, NULL, + &rdev->rlc.save_restore_obj); + if (r) { + dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); + return r; + } + } + + r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); + if (unlikely(r != 0)) { + si_rlc_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->rlc.save_restore_gpu_addr); + radeon_bo_unreserve(rdev->rlc.save_restore_obj); + if (r) { + dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); + si_rlc_fini(rdev); + return r; + } + + /* clear state block */ + if (rdev->rlc.clear_state_obj == NULL) { + r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_VRAM, NULL, + &rdev->rlc.clear_state_obj); + if (r) { + dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r); + si_rlc_fini(rdev); + return r; + } + } + r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); + if (unlikely(r != 0)) { + si_rlc_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->rlc.clear_state_gpu_addr); + radeon_bo_unreserve(rdev->rlc.clear_state_obj); + if (r) { + dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r); + si_rlc_fini(rdev); + return r; + } + + return 0; +} + +static void si_rlc_stop(struct radeon_device *rdev) +{ + WREG32(RLC_CNTL, 0); +} + +static void si_rlc_start(struct radeon_device *rdev) +{ + WREG32(RLC_CNTL, RLC_ENABLE); +} + +static int si_rlc_resume(struct radeon_device *rdev) +{ + u32 i; + const __be32 *fw_data; + + if (!rdev->rlc_fw) + return -EINVAL; + + si_rlc_stop(rdev); + + WREG32(RLC_RL_BASE, 0); + WREG32(RLC_RL_SIZE, 0); + WREG32(RLC_LB_CNTL, 0); + WREG32(RLC_LB_CNTR_MAX, 0xffffffff); + WREG32(RLC_LB_CNTR_INIT, 0); + + WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); + WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); + + WREG32(RLC_MC_CNTL, 0); + WREG32(RLC_UCODE_CNTL, 0); + + fw_data = (const __be32 *)rdev->rlc_fw->data; + for (i = 0; i < SI_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); + } + WREG32(RLC_UCODE_ADDR, 0); + + si_rlc_start(rdev); + + return 0; +} + +static void si_enable_interrupts(struct radeon_device *rdev) +{ + u32 ih_cntl = RREG32(IH_CNTL); + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + + ih_cntl |= ENABLE_INTR; + ih_rb_cntl |= IH_RB_ENABLE; + WREG32(IH_CNTL, ih_cntl); + WREG32(IH_RB_CNTL, ih_rb_cntl); + rdev->ih.enabled = true; +} + +static void si_disable_interrupts(struct radeon_device *rdev) +{ + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + u32 ih_cntl = RREG32(IH_CNTL); + + ih_rb_cntl &= ~IH_RB_ENABLE; + ih_cntl &= ~ENABLE_INTR; + WREG32(IH_RB_CNTL, ih_rb_cntl); + WREG32(IH_CNTL, ih_cntl); + /* set rptr, wptr to 0 */ + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + rdev->ih.enabled = false; + rdev->ih.rptr = 0; +} + +static void si_disable_interrupt_state(struct radeon_device *rdev) +{ + u32 tmp; + + WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL_RING1, 0); + WREG32(CP_INT_CNTL_RING2, 0); + tmp = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE; + WREG32(DMA_CNTL + DMA0_REGISTER_OFFSET, tmp); + tmp = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE; + WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, tmp); + WREG32(GRBM_INT_CNTL, 0); + WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + if (rdev->num_crtc >= 4) { + WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } + + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } + + WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + + tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + +} + +static int si_irq_init(struct radeon_device *rdev) +{ + int ret = 0; + int rb_bufsz; + u32 interrupt_cntl, ih_cntl, ih_rb_cntl; + + /* allocate ring */ + ret = r600_ih_ring_alloc(rdev); + if (ret) + return ret; + + /* disable irqs */ + si_disable_interrupts(rdev); + + /* init rlc */ + ret = si_rlc_resume(rdev); + if (ret) { + r600_ih_ring_fini(rdev); + return ret; + } + + /* setup interrupt control */ + /* set dummy read address to ring address */ + WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); + interrupt_cntl = RREG32(INTERRUPT_CNTL); + /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi + * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN + */ + interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; + /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ + interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; + WREG32(INTERRUPT_CNTL, interrupt_cntl); + + WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); + rb_bufsz = drm_order(rdev->ih.ring_size / 4); + + ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | + IH_WPTR_OVERFLOW_CLEAR | + (rb_bufsz << 1)); + + if (rdev->wb.enabled) + ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; + + /* set the writeback address whether it's enabled or not */ + WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); + WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); + + WREG32(IH_RB_CNTL, ih_rb_cntl); + + /* set rptr, wptr to 0 */ + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + + /* Default settings for IH_CNTL (disabled at first) */ + ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10) | MC_VMID(0); + /* RPTR_REARM only works if msi's are enabled */ + if (rdev->msi_enabled) + ih_cntl |= RPTR_REARM; + WREG32(IH_CNTL, ih_cntl); + + /* force the active interrupt state to all disabled */ + si_disable_interrupt_state(rdev); + + pci_enable_busmaster(rdev->dev); + + /* enable irqs */ + si_enable_interrupts(rdev); + + return ret; +} + +int si_irq_set(struct radeon_device *rdev) +{ + u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; + u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; + u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; + u32 dma_cntl, dma_cntl1; + + if (!rdev->irq.installed) { + DRM_ERROR("Can't enable IRQ/MSI because no handler is installed\n"); + return -EINVAL; + } + /* don't enable anything if the ih is disabled */ + if (!rdev->ih.enabled) { + si_disable_interrupts(rdev); + /* force the active interrupt state to all disabled */ + si_disable_interrupt_state(rdev); + return 0; + } + + hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; + + dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE; + dma_cntl1 = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE; + + /* enable CP interrupts on all rings */ + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("si_irq_set: sw int gfx\n"); + cp_int_cntl |= TIME_STAMP_INT_ENABLE; + } + if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { + DRM_DEBUG("si_irq_set: sw int cp1\n"); + cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; + } + if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { + DRM_DEBUG("si_irq_set: sw int cp2\n"); + cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; + } + if (atomic_read(&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX])) { + DRM_DEBUG("si_irq_set: sw int dma\n"); + dma_cntl |= TRAP_ENABLE; + } + + if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_DMA1_INDEX])) { + DRM_DEBUG("si_irq_set: sw int dma1\n"); + dma_cntl1 |= TRAP_ENABLE; + } + if (rdev->irq.crtc_vblank_int[0] || + atomic_read(&rdev->irq.pflip[0])) { + DRM_DEBUG("si_irq_set: vblank 0\n"); + crtc1 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[1] || + atomic_read(&rdev->irq.pflip[1])) { + DRM_DEBUG("si_irq_set: vblank 1\n"); + crtc2 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[2] || + atomic_read(&rdev->irq.pflip[2])) { + DRM_DEBUG("si_irq_set: vblank 2\n"); + crtc3 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[3] || + atomic_read(&rdev->irq.pflip[3])) { + DRM_DEBUG("si_irq_set: vblank 3\n"); + crtc4 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[4] || + atomic_read(&rdev->irq.pflip[4])) { + DRM_DEBUG("si_irq_set: vblank 4\n"); + crtc5 |= VBLANK_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[5] || + atomic_read(&rdev->irq.pflip[5])) { + DRM_DEBUG("si_irq_set: vblank 5\n"); + crtc6 |= VBLANK_INT_MASK; + } + if (rdev->irq.hpd[0]) { + DRM_DEBUG("si_irq_set: hpd 1\n"); + hpd1 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[1]) { + DRM_DEBUG("si_irq_set: hpd 2\n"); + hpd2 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[2]) { + DRM_DEBUG("si_irq_set: hpd 3\n"); + hpd3 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[3]) { + DRM_DEBUG("si_irq_set: hpd 4\n"); + hpd4 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[4]) { + DRM_DEBUG("si_irq_set: hpd 5\n"); + hpd5 |= DC_HPDx_INT_EN; + } + if (rdev->irq.hpd[5]) { + DRM_DEBUG("si_irq_set: hpd 6\n"); + hpd6 |= DC_HPDx_INT_EN; + } + + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + WREG32(CP_INT_CNTL_RING1, cp_int_cntl1); + WREG32(CP_INT_CNTL_RING2, cp_int_cntl2); + + WREG32(DMA_CNTL + DMA0_REGISTER_OFFSET, dma_cntl); + WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, dma_cntl1); + + WREG32(GRBM_INT_CNTL, grbm_int_cntl); + + WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); + WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); + if (rdev->num_crtc >= 4) { + WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); + WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); + } + if (rdev->num_crtc >= 6) { + WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); + } + + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + } + + WREG32(DC_HPD1_INT_CONTROL, hpd1); + WREG32(DC_HPD2_INT_CONTROL, hpd2); + WREG32(DC_HPD3_INT_CONTROL, hpd3); + WREG32(DC_HPD4_INT_CONTROL, hpd4); + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + + return 0; +} + +static inline void si_irq_ack(struct radeon_device *rdev) +{ + u32 tmp; + + rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); + rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); + rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); + rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); + rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + } + + if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); + + if (rdev->num_crtc >= 4) { + if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); + } + + if (rdev->num_crtc >= 6) { + if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); + } + + if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { + tmp = RREG32(DC_HPD1_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD1_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { + tmp = RREG32(DC_HPD2_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD2_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { + tmp = RREG32(DC_HPD3_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD3_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { + tmp = RREG32(DC_HPD4_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD4_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD5_INT_CONTROL, tmp); + } + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { + tmp = RREG32(DC_HPD5_INT_CONTROL); + tmp |= DC_HPDx_INT_ACK; + WREG32(DC_HPD6_INT_CONTROL, tmp); + } +} + +static void si_irq_disable(struct radeon_device *rdev) +{ + si_disable_interrupts(rdev); + /* Wait and acknowledge irq */ + DRM_MDELAY(1); + si_irq_ack(rdev); + si_disable_interrupt_state(rdev); +} + +static void si_irq_suspend(struct radeon_device *rdev) +{ + si_irq_disable(rdev); + si_rlc_stop(rdev); +} + +static void si_irq_fini(struct radeon_device *rdev) +{ + si_irq_suspend(rdev); + r600_ih_ring_fini(rdev); +} + +static inline u32 si_get_ih_wptr(struct radeon_device *rdev) +{ + u32 wptr, tmp; + + if (rdev->wb.enabled) + wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); + else + wptr = RREG32(IH_RB_WPTR); + + if (wptr & RB_OVERFLOW) { + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", + wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); + rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); + } + return (wptr & rdev->ih.ptr_mask); +} + +/* SI IV Ring + * Each IV ring entry is 128 bits: + * [7:0] - interrupt source id + * [31:8] - reserved + * [59:32] - interrupt source data + * [63:60] - reserved + * [71:64] - RINGID + * [79:72] - VMID + * [127:80] - reserved + */ +irqreturn_t si_irq_process(struct radeon_device *rdev) +{ + u32 wptr; + u32 rptr; + u32 src_id, src_data, ring_id; + u32 ring_index; + bool queue_hotplug = false; + + if (!rdev->ih.enabled || rdev->shutdown) + return IRQ_NONE; + + wptr = si_get_ih_wptr(rdev); + +restart_ih: + /* is somebody else already processing irqs? */ + if (atomic_xchg(&rdev->ih.lock, 1)) + return IRQ_NONE; + + rptr = rdev->ih.rptr; + DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + + /* Order reading of wptr vs. reading of IH ring data */ + rmb(); + + /* display interrupts */ + si_irq_ack(rdev); + + while (rptr != wptr) { + /* wptr/rptr are in bytes! */ + ring_index = rptr / 4; + src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; + src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; + ring_id = le32_to_cpu(rdev->ih.ring[ring_index + 2]) & 0xff; + + switch (src_id) { + case 1: /* D1 vblank/vline */ + switch (src_data) { + case 0: /* D1 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_flip(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + } + break; + case 1: /* D1 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 2: /* D2 vblank/vline */ + switch (src_data) { + case 0: /* D2 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_flip(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + } + break; + case 1: /* D2 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 3: /* D3 vblank/vline */ + switch (src_data) { + case 0: /* D3 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_flip(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + } + break; + case 1: /* D3 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 4: /* D4 vblank/vline */ + switch (src_data) { + case 0: /* D4 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_flip(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + } + break; + case 1: /* D4 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 5: /* D5 vblank/vline */ + switch (src_data) { + case 0: /* D5 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_flip(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + } + break; + case 1: /* D5 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 6: /* D6 vblank/vline */ + switch (src_data) { + case 0: /* D6 vblank */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + DRM_WAKEUP(&rdev->irq.vblank_queue); + } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_flip(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + } + break; + case 1: /* D6 vline */ + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 42: /* HPD hotplug */ + switch (src_data) { + case 0: + if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + } + break; + case 1: + if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + } + break; + case 2: + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + } + break; + case 3: + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + } + break; + case 4: + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + } + break; + case 5: + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + } + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + break; + case 146: + case 147: + dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); + dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", + RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); + dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", + RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + /* reset addr and status */ + WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); + break; + case 176: /* RINGID0 CP_INT */ + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 177: /* RINGID1 CP_INT */ + radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); + break; + case 178: /* RINGID2 CP_INT */ + radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); + break; + case 181: /* CP EOP event */ + DRM_DEBUG("IH: CP EOP\n"); + switch (ring_id) { + case 0: + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 1: + radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); + break; + case 2: + radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); + break; + } + break; + case 224: /* DMA trap event */ + DRM_DEBUG("IH: DMA trap\n"); + radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX); + break; + case 233: /* GUI IDLE */ + DRM_DEBUG("IH: GUI idle\n"); + break; + case 244: /* DMA trap event */ + DRM_DEBUG("IH: DMA1 trap\n"); + radeon_fence_process(rdev, CAYMAN_RING_TYPE_DMA1_INDEX); + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); + break; + } + + /* wptr/rptr are in bytes! */ + rptr += 16; + rptr &= rdev->ih.ptr_mask; + } + if (queue_hotplug) + taskqueue_enqueue(rdev->tq, &rdev->hotplug_work); + rdev->ih.rptr = rptr; + WREG32(IH_RB_RPTR, rdev->ih.rptr); + atomic_set(&rdev->ih.lock, 0); + + /* make sure wptr hasn't changed while processing */ + wptr = si_get_ih_wptr(rdev); + if (wptr != rptr) + goto restart_ih; + + return IRQ_HANDLED; +} + +/** + * si_copy_dma - copy pages using the DMA engine + * + * @rdev: radeon_device pointer + * @src_offset: src GPU address + * @dst_offset: dst GPU address + * @num_gpu_pages: number of GPU pages to xfer + * @fence: radeon fence object + * + * Copy GPU paging using the DMA engine (SI). + * Used by the radeon ttm implementation to move pages if + * registered as the asic copy callback. + */ +int si_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_semaphore *sem = NULL; + int ring_index = rdev->asic->copy.dma_ring_index; + struct radeon_ring *ring = &rdev->ring[ring_index]; + u32 size_in_bytes, cur_size_in_bytes; + int i, num_loops; + int r = 0; + + r = radeon_semaphore_create(rdev, &sem); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + + size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT); + num_loops = DIV_ROUND_UP(size_in_bytes, 0xfffff); + r = radeon_ring_lock(rdev, ring, num_loops * 5 + 11); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + radeon_semaphore_free(rdev, &sem, NULL); + return r; + } + + if (radeon_fence_need_sync(*fence, ring->idx)) { + radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, + ring->idx); + radeon_fence_note_sync(*fence, ring->idx); + } else { + radeon_semaphore_free(rdev, &sem, NULL); + } + + for (i = 0; i < num_loops; i++) { + cur_size_in_bytes = size_in_bytes; + if (cur_size_in_bytes > 0xFFFFF) + cur_size_in_bytes = 0xFFFFF; + size_in_bytes -= cur_size_in_bytes; + radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 1, 0, 0, cur_size_in_bytes)); + radeon_ring_write(ring, dst_offset & 0xffffffff); + radeon_ring_write(ring, src_offset & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); + radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff); + src_offset += cur_size_in_bytes; + dst_offset += cur_size_in_bytes; + } + + r = radeon_fence_emit(rdev, fence, ring->idx); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + + radeon_ring_unlock_commit(rdev, ring); + radeon_semaphore_free(rdev, &sem, *fence); + + return r; +} + +/* + * startup/shutdown callbacks + */ +static int si_startup(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + int r; + + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->rlc_fw || !rdev->mc_fw) { + r = si_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + r = si_mc_load_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); + return r; + } + + r = r600_vram_scratch_init(rdev); + if (r) + return r; + + si_mc_program(rdev); + r = si_pcie_gart_enable(rdev); + if (r) + return r; + si_gpu_init(rdev); + +#if 0 + r = evergreen_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); + rdev->asic->copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } +#endif + /* allocate rlc buffers */ + r = si_rlc_init(rdev); + if (r) { + DRM_ERROR("Failed to init rlc BOs!\n"); + return r; + } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_DMA1_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); + return r; + } + + /* Enable IRQ */ + r = si_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + si_irq_set(rdev); + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, + CP_RB0_RPTR, CP_RB0_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, + CP_RB1_RPTR, CP_RB1_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, + CP_RB2_RPTR, CP_RB2_WPTR, + 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, + DMA_RB_RPTR + DMA0_REGISTER_OFFSET, + DMA_RB_WPTR + DMA0_REGISTER_OFFSET, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); + if (r) + return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, + DMA_RB_RPTR + DMA1_REGISTER_OFFSET, + DMA_RB_WPTR + DMA1_REGISTER_OFFSET, + 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); + if (r) + return r; + + r = si_cp_load_microcode(rdev); + if (r) + return r; + r = si_cp_resume(rdev); + if (r) + return r; + + r = cayman_dma_resume(rdev); + if (r) + return r; + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } + + r = radeon_vm_manager_init(rdev); + if (r) { + dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); + return r; + } + + return 0; +} + +int si_resume(struct radeon_device *rdev) +{ + int r; + + /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, + * posting will perform necessary task to bring back GPU into good + * shape. + */ + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + + rdev->accel_working = true; + r = si_startup(rdev); + if (r) { + DRM_ERROR("si startup failed on resume\n"); + rdev->accel_working = false; + return r; + } + + return r; + +} + +int si_suspend(struct radeon_device *rdev) +{ + si_cp_enable(rdev, false); + cayman_dma_stop(rdev); + si_irq_suspend(rdev); + radeon_wb_disable(rdev); + si_pcie_gart_disable(rdev); + return 0; +} + +/* Plan is to move initialization in that function and use + * helper function so that radeon_device_init pretty much + * do nothing more than calling asic specific function. This + * should also allow to remove a bunch of callback function + * like vram_info. + */ +int si_init(struct radeon_device *rdev) +{ + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* Read BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); + if (r) + return r; + + /* Post card if necessary */ + if (!radeon_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize scratch registers */ + si_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + + /* initialize memory controller */ + r = si_mc_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 1024 * 1024); + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 1024 * 1024); + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 1024 * 1024); + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 64 * 1024); + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; + ring->ring_obj = NULL; + r600_ring_init(rdev, ring, 64 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); + + r = r600_pcie_gart_init(rdev); + if (r) + return r; + + rdev->accel_working = true; + r = si_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + si_cp_fini(rdev); + cayman_dma_fini(rdev); + si_irq_fini(rdev); + si_rlc_fini(rdev); + radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_vm_manager_fini(rdev); + radeon_irq_kms_fini(rdev); + si_pcie_gart_fini(rdev); + rdev->accel_working = false; + } + + /* Don't start up if the MC ucode is missing. + * The default clocks and voltages before the MC ucode + * is loaded are not suffient for advanced operations. + */ + if (!rdev->mc_fw) { + DRM_ERROR("radeon: MC ucode required for NI+.\n"); + return -EINVAL; + } + + return 0; +} + +void si_fini(struct radeon_device *rdev) +{ +#if 0 + r600_blit_fini(rdev); +#endif + si_cp_fini(rdev); + cayman_dma_fini(rdev); + si_irq_fini(rdev); + si_rlc_fini(rdev); + radeon_wb_fini(rdev); + radeon_vm_manager_fini(rdev); + radeon_ib_pool_fini(rdev); + radeon_irq_kms_fini(rdev); + si_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + si_fini_microcode(rdev); + free(rdev->bios, DRM_MEM_DRIVER); + rdev->bios = NULL; +} + +/** + * si_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (SI). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t si_get_gpu_clock(struct radeon_device *rdev) +{ + uint64_t clock; + + sx_xlock(&rdev->gpu_clock_mutex); + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); + sx_xunlock(&rdev->gpu_clock_mutex); + return clock; +} diff --git a/sys/dev/drm2/radeon/si_blit_shaders.c b/sys/dev/drm2/radeon/si_blit_shaders.c new file mode 100644 index 00000000000..dc31fe307b3 --- /dev/null +++ b/sys/dev/drm2/radeon/si_blit_shaders.c @@ -0,0 +1,254 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Alex Deucher + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +const u32 si_default_state[] = +{ + 0xc0066900, + 0x00000000, + 0x00000060, /* DB_RENDER_CONTROL */ + 0x00000000, /* DB_COUNT_CONTROL */ + 0x00000000, /* DB_DEPTH_VIEW */ + 0x0000002a, /* DB_RENDER_OVERRIDE */ + 0x00000000, /* DB_RENDER_OVERRIDE2 */ + 0x00000000, /* DB_HTILE_DATA_BASE */ + + 0xc0046900, + 0x00000008, + 0x00000000, /* DB_DEPTH_BOUNDS_MIN */ + 0x00000000, /* DB_DEPTH_BOUNDS_MAX */ + 0x00000000, /* DB_STENCIL_CLEAR */ + 0x00000000, /* DB_DEPTH_CLEAR */ + + 0xc0036900, + 0x0000000f, + 0x00000000, /* DB_DEPTH_INFO */ + 0x00000000, /* DB_Z_INFO */ + 0x00000000, /* DB_STENCIL_INFO */ + + 0xc0016900, + 0x00000080, + 0x00000000, /* PA_SC_WINDOW_OFFSET */ + + 0xc00d6900, + 0x00000083, + 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ + 0x00000000, /* PA_SC_CLIPRECT_0_TL */ + 0x20002000, /* PA_SC_CLIPRECT_0_BR */ + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0xaaaaaaaa, /* PA_SC_EDGERULE */ + 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ + 0x0000000f, /* CB_TARGET_MASK */ + 0x0000000f, /* CB_SHADER_MASK */ + + 0xc0226900, + 0x00000094, + 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ + 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ + 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ + + 0xc0026900, + 0x000000d9, + 0x00000000, /* CP_RINGID */ + 0x00000000, /* CP_VMID */ + + 0xc0046900, + 0x00000100, + 0xffffffff, /* VGT_MAX_VTX_INDX */ + 0x00000000, /* VGT_MIN_VTX_INDX */ + 0x00000000, /* VGT_INDX_OFFSET */ + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ + + 0xc0046900, + 0x00000105, + 0x00000000, /* CB_BLEND_RED */ + 0x00000000, /* CB_BLEND_GREEN */ + 0x00000000, /* CB_BLEND_BLUE */ + 0x00000000, /* CB_BLEND_ALPHA */ + + 0xc0016900, + 0x000001e0, + 0x00000000, /* CB_BLEND0_CONTROL */ + + 0xc00e6900, + 0x00000200, + 0x00000000, /* DB_DEPTH_CONTROL */ + 0x00000000, /* DB_EQAA */ + 0x00cc0010, /* CB_COLOR_CONTROL */ + 0x00000210, /* DB_SHADER_CONTROL */ + 0x00010000, /* PA_CL_CLIP_CNTL */ + 0x00000004, /* PA_SU_SC_MODE_CNTL */ + 0x00000100, /* PA_CL_VTE_CNTL */ + 0x00000000, /* PA_CL_VS_OUT_CNTL */ + 0x00000000, /* PA_CL_NANINF_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ + 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ + 0x00000000, /* */ + 0x00000000, /* */ + + 0xc0116900, + 0x00000280, + 0x00000000, /* PA_SU_POINT_SIZE */ + 0x00000000, /* PA_SU_POINT_MINMAX */ + 0x00000008, /* PA_SU_LINE_CNTL */ + 0x00000000, /* PA_SC_LINE_STIPPLE */ + 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ + 0x00000000, /* VGT_HOS_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, /* VGT_GS_MODE */ + + 0xc0026900, + 0x00000292, + 0x00000000, /* PA_SC_MODE_CNTL_0 */ + 0x00000000, /* PA_SC_MODE_CNTL_1 */ + + 0xc0016900, + 0x000002a1, + 0x00000000, /* VGT_PRIMITIVEID_EN */ + + 0xc0016900, + 0x000002a5, + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ + + 0xc0026900, + 0x000002a8, + 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ + 0x00000000, + + 0xc0026900, + 0x000002ad, + 0x00000000, /* VGT_REUSE_OFF */ + 0x00000000, + + 0xc0016900, + 0x000002d5, + 0x00000000, /* VGT_SHADER_STAGES_EN */ + + 0xc0016900, + 0x000002dc, + 0x0000aa00, /* DB_ALPHA_TO_MASK */ + + 0xc0066900, + 0x000002de, + 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0026900, + 0x000002e5, + 0x00000000, /* VGT_STRMOUT_CONFIG */ + 0x00000000, + + 0xc01b6900, + 0x000002f5, + 0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */ + 0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */ + 0x00000000, /* PA_SC_LINE_CNTL */ + 0x00000000, /* PA_SC_AA_CONFIG */ + 0x00000005, /* PA_SU_VTX_CNTL */ + 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ + 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */ + 0xffffffff, + + 0xc0026900, + 0x00000316, + 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + 0x00000010, /* */ +}; + +const u32 si_default_size = DRM_ARRAY_SIZE(si_default_state); diff --git a/sys/dev/drm2/radeon/si_blit_shaders.h b/sys/dev/drm2/radeon/si_blit_shaders.h new file mode 100644 index 00000000000..0ba0aa89718 --- /dev/null +++ b/sys/dev/drm2/radeon/si_blit_shaders.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SI_BLIT_SHADERS_H +#define SI_BLIT_SHADERS_H + +#include +__FBSDID("$FreeBSD$"); + +extern const u32 si_default_state[]; + +extern const u32 si_default_size; + +#endif diff --git a/sys/dev/drm2/radeon/si_reg.h b/sys/dev/drm2/radeon/si_reg.h new file mode 100644 index 00000000000..aa94b66ec86 --- /dev/null +++ b/sys/dev/drm2/radeon/si_reg.h @@ -0,0 +1,108 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#ifndef __SI_REG_H__ +#define __SI_REG_H__ + +#include +__FBSDID("$FreeBSD$"); + +/* SI */ +#define SI_DC_GPIO_HPD_MASK 0x65b0 +#define SI_DC_GPIO_HPD_A 0x65b4 +#define SI_DC_GPIO_HPD_EN 0x65b8 +#define SI_DC_GPIO_HPD_Y 0x65bc + +#define SI_GRPH_CONTROL 0x6804 +# define SI_GRPH_DEPTH(x) (((x) & 0x3) << 0) +# define SI_GRPH_DEPTH_8BPP 0 +# define SI_GRPH_DEPTH_16BPP 1 +# define SI_GRPH_DEPTH_32BPP 2 +# define SI_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2) +# define SI_ADDR_SURF_2_BANK 0 +# define SI_ADDR_SURF_4_BANK 1 +# define SI_ADDR_SURF_8_BANK 2 +# define SI_ADDR_SURF_16_BANK 3 +# define SI_GRPH_Z(x) (((x) & 0x3) << 4) +# define SI_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6) +# define SI_ADDR_SURF_BANK_WIDTH_1 0 +# define SI_ADDR_SURF_BANK_WIDTH_2 1 +# define SI_ADDR_SURF_BANK_WIDTH_4 2 +# define SI_ADDR_SURF_BANK_WIDTH_8 3 +# define SI_GRPH_FORMAT(x) (((x) & 0x7) << 8) +/* 8 BPP */ +# define SI_GRPH_FORMAT_INDEXED 0 +/* 16 BPP */ +# define SI_GRPH_FORMAT_ARGB1555 0 +# define SI_GRPH_FORMAT_ARGB565 1 +# define SI_GRPH_FORMAT_ARGB4444 2 +# define SI_GRPH_FORMAT_AI88 3 +# define SI_GRPH_FORMAT_MONO16 4 +# define SI_GRPH_FORMAT_BGRA5551 5 +/* 32 BPP */ +# define SI_GRPH_FORMAT_ARGB8888 0 +# define SI_GRPH_FORMAT_ARGB2101010 1 +# define SI_GRPH_FORMAT_32BPP_DIG 2 +# define SI_GRPH_FORMAT_8B_ARGB2101010 3 +# define SI_GRPH_FORMAT_BGRA1010102 4 +# define SI_GRPH_FORMAT_8B_BGRA1010102 5 +# define SI_GRPH_FORMAT_RGB111110 6 +# define SI_GRPH_FORMAT_BGR101111 7 +# define SI_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11) +# define SI_ADDR_SURF_BANK_HEIGHT_1 0 +# define SI_ADDR_SURF_BANK_HEIGHT_2 1 +# define SI_ADDR_SURF_BANK_HEIGHT_4 2 +# define SI_ADDR_SURF_BANK_HEIGHT_8 3 +# define SI_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13) +# define SI_ADDR_SURF_TILE_SPLIT_64B 0 +# define SI_ADDR_SURF_TILE_SPLIT_128B 1 +# define SI_ADDR_SURF_TILE_SPLIT_256B 2 +# define SI_ADDR_SURF_TILE_SPLIT_512B 3 +# define SI_ADDR_SURF_TILE_SPLIT_1KB 4 +# define SI_ADDR_SURF_TILE_SPLIT_2KB 5 +# define SI_ADDR_SURF_TILE_SPLIT_4KB 6 +# define SI_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18) +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_1 0 +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_2 1 +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_4 2 +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_8 3 +# define SI_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20) +# define SI_GRPH_ARRAY_LINEAR_GENERAL 0 +# define SI_GRPH_ARRAY_LINEAR_ALIGNED 1 +# define SI_GRPH_ARRAY_1D_TILED_THIN1 2 +# define SI_GRPH_ARRAY_2D_TILED_THIN1 4 +# define SI_GRPH_PIPE_CONFIG(x) (((x) & 0x1f) << 24) +# define SI_ADDR_SURF_P2 0 +# define SI_ADDR_SURF_P4_8x16 4 +# define SI_ADDR_SURF_P4_16x16 5 +# define SI_ADDR_SURF_P4_16x32 6 +# define SI_ADDR_SURF_P4_32x32 7 +# define SI_ADDR_SURF_P8_16x16_8x16 8 +# define SI_ADDR_SURF_P8_16x32_8x16 9 +# define SI_ADDR_SURF_P8_32x32_8x16 10 +# define SI_ADDR_SURF_P8_16x32_16x16 11 +# define SI_ADDR_SURF_P8_32x32_16x16 12 +# define SI_ADDR_SURF_P8_32x32_16x32 13 +# define SI_ADDR_SURF_P8_32x64_32x32 14 + +#endif diff --git a/sys/dev/drm2/radeon/sid.h b/sys/dev/drm2/radeon/sid.h new file mode 100644 index 00000000000..028916f17eb --- /dev/null +++ b/sys/dev/drm2/radeon/sid.h @@ -0,0 +1,1065 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#ifndef SI_H +#define SI_H + +#include +__FBSDID("$FreeBSD$"); + +#define TAHITI_RB_BITMAP_WIDTH_PER_SH 2 + +#define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003 +#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002 + +#define CG_MULT_THERMAL_STATUS 0x714 +#define ASIC_MAX_TEMP(x) ((x) << 0) +#define ASIC_MAX_TEMP_MASK 0x000001ff +#define ASIC_MAX_TEMP_SHIFT 0 +#define CTF_TEMP(x) ((x) << 9) +#define CTF_TEMP_MASK 0x0003fe00 +#define CTF_TEMP_SHIFT 9 + +#define SI_MAX_SH_GPRS 256 +#define SI_MAX_TEMP_GPRS 16 +#define SI_MAX_SH_THREADS 256 +#define SI_MAX_SH_STACK_ENTRIES 4096 +#define SI_MAX_FRC_EOV_CNT 16384 +#define SI_MAX_BACKENDS 8 +#define SI_MAX_BACKENDS_MASK 0xFF +#define SI_MAX_BACKENDS_PER_SE_MASK 0x0F +#define SI_MAX_SIMDS 12 +#define SI_MAX_SIMDS_MASK 0x0FFF +#define SI_MAX_SIMDS_PER_SE_MASK 0x00FF +#define SI_MAX_PIPES 8 +#define SI_MAX_PIPES_MASK 0xFF +#define SI_MAX_PIPES_PER_SIMD_MASK 0x3F +#define SI_MAX_LDS_NUM 0xFFFF +#define SI_MAX_TCC 16 +#define SI_MAX_TCC_MASK 0xFFFF + +#define VGA_HDP_CONTROL 0x328 +#define VGA_MEMORY_DISABLE (1 << 4) + +#define DMIF_ADDR_CONFIG 0xBD4 + +#define SRBM_STATUS 0xE50 + +#define SRBM_SOFT_RESET 0x0E60 +#define SOFT_RESET_BIF (1 << 1) +#define SOFT_RESET_DC (1 << 5) +#define SOFT_RESET_DMA1 (1 << 6) +#define SOFT_RESET_GRBM (1 << 8) +#define SOFT_RESET_HDP (1 << 9) +#define SOFT_RESET_IH (1 << 10) +#define SOFT_RESET_MC (1 << 11) +#define SOFT_RESET_ROM (1 << 14) +#define SOFT_RESET_SEM (1 << 15) +#define SOFT_RESET_VMC (1 << 17) +#define SOFT_RESET_DMA (1 << 20) +#define SOFT_RESET_TST (1 << 21) +#define SOFT_RESET_REGBB (1 << 22) +#define SOFT_RESET_ORB (1 << 23) + +#define CC_SYS_RB_BACKEND_DISABLE 0xe80 +#define GC_USER_SYS_RB_BACKEND_DISABLE 0xe84 + +#define VM_L2_CNTL 0x1400 +#define ENABLE_L2_CACHE (1 << 0) +#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) +#define L2_CACHE_PTE_ENDIAN_SWAP_MODE(x) ((x) << 2) +#define L2_CACHE_PDE_ENDIAN_SWAP_MODE(x) ((x) << 4) +#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) +#define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) +#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 15) +#define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 19) +#define VM_L2_CNTL2 0x1404 +#define INVALIDATE_ALL_L1_TLBS (1 << 0) +#define INVALIDATE_L2_CACHE (1 << 1) +#define INVALIDATE_CACHE_MODE(x) ((x) << 26) +#define INVALIDATE_PTE_AND_PDE_CACHES 0 +#define INVALIDATE_ONLY_PTE_CACHES 1 +#define INVALIDATE_ONLY_PDE_CACHES 2 +#define VM_L2_CNTL3 0x1408 +#define BANK_SELECT(x) ((x) << 0) +#define L2_CACHE_UPDATE_MODE(x) ((x) << 6) +#define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) +#define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) +#define VM_L2_STATUS 0x140C +#define L2_BUSY (1 << 0) +#define VM_CONTEXT0_CNTL 0x1410 +#define ENABLE_CONTEXT (1 << 0) +#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) +#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) +#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) +#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) +#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) +#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) +#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) +#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) +#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) +#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) +#define VM_CONTEXT1_CNTL 0x1414 +#define VM_CONTEXT0_CNTL2 0x1430 +#define VM_CONTEXT1_CNTL2 0x1434 +#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR 0x1438 +#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR 0x143c +#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR 0x1440 +#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR 0x1444 +#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR 0x1448 +#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR 0x144c +#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x1450 +#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x1454 + +#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC +#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC + +#define VM_INVALIDATE_REQUEST 0x1478 +#define VM_INVALIDATE_RESPONSE 0x147c + +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 +#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c + +#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153c +#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR 0x1540 +#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR 0x1544 +#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR 0x1548 +#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR 0x154c +#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR 0x1550 +#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR 0x1554 +#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR 0x1558 +#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155c +#define VM_CONTEXT1_PAGE_TABLE_START_ADDR 0x1560 + +#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C +#define VM_CONTEXT1_PAGE_TABLE_END_ADDR 0x1580 + +#define MC_SHARED_CHMAP 0x2004 +#define NOOFCHAN_SHIFT 12 +#define NOOFCHAN_MASK 0x0000f000 +#define MC_SHARED_CHREMAP 0x2008 + +#define MC_VM_FB_LOCATION 0x2024 +#define MC_VM_AGP_TOP 0x2028 +#define MC_VM_AGP_BOT 0x202C +#define MC_VM_AGP_BASE 0x2030 +#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 +#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 +#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C + +#define MC_VM_MX_L1_TLB_CNTL 0x2064 +#define ENABLE_L1_TLB (1 << 0) +#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) +#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) +#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) +#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) +#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) + +#define MC_SHARED_BLACKOUT_CNTL 0x20ac + +#define MC_ARB_RAMCFG 0x2760 +#define NOOFBANK_SHIFT 0 +#define NOOFBANK_MASK 0x00000003 +#define NOOFRANK_SHIFT 2 +#define NOOFRANK_MASK 0x00000004 +#define NOOFROWS_SHIFT 3 +#define NOOFROWS_MASK 0x00000038 +#define NOOFCOLS_SHIFT 6 +#define NOOFCOLS_MASK 0x000000C0 +#define CHANSIZE_SHIFT 8 +#define CHANSIZE_MASK 0x00000100 +#define CHANSIZE_OVERRIDE (1 << 11) +#define NOOFGROUPS_SHIFT 12 +#define NOOFGROUPS_MASK 0x00001000 + +#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808 +#define TRAIN_DONE_D0 (1 << 30) +#define TRAIN_DONE_D1 (1 << 31) + +#define MC_SEQ_SUP_CNTL 0x28c8 +#define RUN_MASK (1 << 0) +#define MC_SEQ_SUP_PGM 0x28cc + +#define MC_IO_PAD_CNTL_D0 0x29d0 +#define MEM_FALL_OUT_CMD (1 << 8) + +#define MC_SEQ_IO_DEBUG_INDEX 0x2a44 +#define MC_SEQ_IO_DEBUG_DATA 0x2a48 + +#define HDP_HOST_PATH_CNTL 0x2C00 +#define HDP_NONSURFACE_BASE 0x2C04 +#define HDP_NONSURFACE_INFO 0x2C08 +#define HDP_NONSURFACE_SIZE 0x2C0C + +#define HDP_ADDR_CONFIG 0x2F48 +#define HDP_MISC_CNTL 0x2F4C +#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) + +#define IH_RB_CNTL 0x3e00 +# define IH_RB_ENABLE (1 << 0) +# define IH_IB_SIZE(x) ((x) << 1) /* log2 */ +# define IH_RB_FULL_DRAIN_ENABLE (1 << 6) +# define IH_WPTR_WRITEBACK_ENABLE (1 << 8) +# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ +# define IH_WPTR_OVERFLOW_ENABLE (1 << 16) +# define IH_WPTR_OVERFLOW_CLEAR (1 << 31) +#define IH_RB_BASE 0x3e04 +#define IH_RB_RPTR 0x3e08 +#define IH_RB_WPTR 0x3e0c +# define RB_OVERFLOW (1 << 0) +# define WPTR_OFFSET_MASK 0x3fffc +#define IH_RB_WPTR_ADDR_HI 0x3e10 +#define IH_RB_WPTR_ADDR_LO 0x3e14 +#define IH_CNTL 0x3e18 +# define ENABLE_INTR (1 << 0) +# define IH_MC_SWAP(x) ((x) << 1) +# define IH_MC_SWAP_NONE 0 +# define IH_MC_SWAP_16BIT 1 +# define IH_MC_SWAP_32BIT 2 +# define IH_MC_SWAP_64BIT 3 +# define RPTR_REARM (1 << 4) +# define MC_WRREQ_CREDIT(x) ((x) << 15) +# define MC_WR_CLEAN_CNT(x) ((x) << 20) +# define MC_VMID(x) ((x) << 25) + +#define CONFIG_MEMSIZE 0x5428 + +#define INTERRUPT_CNTL 0x5468 +# define IH_DUMMY_RD_OVERRIDE (1 << 0) +# define IH_DUMMY_RD_EN (1 << 1) +# define IH_REQ_NONSNOOP_EN (1 << 3) +# define GEN_IH_INT_EN (1 << 8) +#define INTERRUPT_CNTL2 0x546c + +#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 + +#define BIF_FB_EN 0x5490 +#define FB_READ_EN (1 << 0) +#define FB_WRITE_EN (1 << 1) + +#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 + +#define DC_LB_MEMORY_SPLIT 0x6b0c +#define DC_LB_MEMORY_CONFIG(x) ((x) << 20) + +#define PRIORITY_A_CNT 0x6b18 +#define PRIORITY_MARK_MASK 0x7fff +#define PRIORITY_OFF (1 << 16) +#define PRIORITY_ALWAYS_ON (1 << 20) +#define PRIORITY_B_CNT 0x6b1c + +#define DPG_PIPE_ARBITRATION_CONTROL3 0x6cc8 +# define LATENCY_WATERMARK_MASK(x) ((x) << 16) +#define DPG_PIPE_LATENCY_CONTROL 0x6ccc +# define LATENCY_LOW_WATERMARK(x) ((x) << 0) +# define LATENCY_HIGH_WATERMARK(x) ((x) << 16) + +/* 0x6bb8, 0x77b8, 0x103b8, 0x10fb8, 0x11bb8, 0x127b8 */ +#define VLINE_STATUS 0x6bb8 +# define VLINE_OCCURRED (1 << 0) +# define VLINE_ACK (1 << 4) +# define VLINE_STAT (1 << 12) +# define VLINE_INTERRUPT (1 << 16) +# define VLINE_INTERRUPT_TYPE (1 << 17) +/* 0x6bbc, 0x77bc, 0x103bc, 0x10fbc, 0x11bbc, 0x127bc */ +#define VBLANK_STATUS 0x6bbc +# define VBLANK_OCCURRED (1 << 0) +# define VBLANK_ACK (1 << 4) +# define VBLANK_STAT (1 << 12) +# define VBLANK_INTERRUPT (1 << 16) +# define VBLANK_INTERRUPT_TYPE (1 << 17) + +/* 0x6b40, 0x7740, 0x10340, 0x10f40, 0x11b40, 0x12740 */ +#define INT_MASK 0x6b40 +# define VBLANK_INT_MASK (1 << 0) +# define VLINE_INT_MASK (1 << 4) + +#define DISP_INTERRUPT_STATUS 0x60f4 +# define LB_D1_VLINE_INTERRUPT (1 << 2) +# define LB_D1_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD1_INTERRUPT (1 << 17) +# define DC_HPD1_RX_INTERRUPT (1 << 18) +# define DACA_AUTODETECT_INTERRUPT (1 << 22) +# define DACB_AUTODETECT_INTERRUPT (1 << 23) +# define DC_I2C_SW_DONE_INTERRUPT (1 << 24) +# define DC_I2C_HW_DONE_INTERRUPT (1 << 25) +#define DISP_INTERRUPT_STATUS_CONTINUE 0x60f8 +# define LB_D2_VLINE_INTERRUPT (1 << 2) +# define LB_D2_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD2_INTERRUPT (1 << 17) +# define DC_HPD2_RX_INTERRUPT (1 << 18) +# define DISP_TIMER_INTERRUPT (1 << 24) +#define DISP_INTERRUPT_STATUS_CONTINUE2 0x60fc +# define LB_D3_VLINE_INTERRUPT (1 << 2) +# define LB_D3_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD3_INTERRUPT (1 << 17) +# define DC_HPD3_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE3 0x6100 +# define LB_D4_VLINE_INTERRUPT (1 << 2) +# define LB_D4_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD4_INTERRUPT (1 << 17) +# define DC_HPD4_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE4 0x614c +# define LB_D5_VLINE_INTERRUPT (1 << 2) +# define LB_D5_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD5_INTERRUPT (1 << 17) +# define DC_HPD5_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6150 +# define LB_D6_VLINE_INTERRUPT (1 << 2) +# define LB_D6_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD6_INTERRUPT (1 << 17) +# define DC_HPD6_RX_INTERRUPT (1 << 18) + +/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ +#define GRPH_INT_STATUS 0x6858 +# define GRPH_PFLIP_INT_OCCURRED (1 << 0) +# define GRPH_PFLIP_INT_CLEAR (1 << 8) +/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ +#define GRPH_INT_CONTROL 0x685c +# define GRPH_PFLIP_INT_MASK (1 << 0) +# define GRPH_PFLIP_INT_TYPE (1 << 8) + +#define DACA_AUTODETECT_INT_CONTROL 0x66c8 + +#define DC_HPD1_INT_STATUS 0x601c +#define DC_HPD2_INT_STATUS 0x6028 +#define DC_HPD3_INT_STATUS 0x6034 +#define DC_HPD4_INT_STATUS 0x6040 +#define DC_HPD5_INT_STATUS 0x604c +#define DC_HPD6_INT_STATUS 0x6058 +# define DC_HPDx_INT_STATUS (1 << 0) +# define DC_HPDx_SENSE (1 << 1) +# define DC_HPDx_RX_INT_STATUS (1 << 8) + +#define DC_HPD1_INT_CONTROL 0x6020 +#define DC_HPD2_INT_CONTROL 0x602c +#define DC_HPD3_INT_CONTROL 0x6038 +#define DC_HPD4_INT_CONTROL 0x6044 +#define DC_HPD5_INT_CONTROL 0x6050 +#define DC_HPD6_INT_CONTROL 0x605c +# define DC_HPDx_INT_ACK (1 << 0) +# define DC_HPDx_INT_POLARITY (1 << 8) +# define DC_HPDx_INT_EN (1 << 16) +# define DC_HPDx_RX_INT_ACK (1 << 20) +# define DC_HPDx_RX_INT_EN (1 << 24) + +#define DC_HPD1_CONTROL 0x6024 +#define DC_HPD2_CONTROL 0x6030 +#define DC_HPD3_CONTROL 0x603c +#define DC_HPD4_CONTROL 0x6048 +#define DC_HPD5_CONTROL 0x6054 +#define DC_HPD6_CONTROL 0x6060 +# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0) +# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) +# define DC_HPDx_EN (1 << 28) + +/* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ +#define CRTC_STATUS_FRAME_COUNT 0x6e98 + +#define GRBM_CNTL 0x8000 +#define GRBM_READ_TIMEOUT(x) ((x) << 0) + +#define GRBM_STATUS2 0x8008 +#define RLC_RQ_PENDING (1 << 0) +#define RLC_BUSY (1 << 8) +#define TC_BUSY (1 << 9) + +#define GRBM_STATUS 0x8010 +#define CMDFIFO_AVAIL_MASK 0x0000000F +#define RING2_RQ_PENDING (1 << 4) +#define SRBM_RQ_PENDING (1 << 5) +#define RING1_RQ_PENDING (1 << 6) +#define CF_RQ_PENDING (1 << 7) +#define PF_RQ_PENDING (1 << 8) +#define GDS_DMA_RQ_PENDING (1 << 9) +#define GRBM_EE_BUSY (1 << 10) +#define DB_CLEAN (1 << 12) +#define CB_CLEAN (1 << 13) +#define TA_BUSY (1 << 14) +#define GDS_BUSY (1 << 15) +#define VGT_BUSY (1 << 17) +#define IA_BUSY_NO_DMA (1 << 18) +#define IA_BUSY (1 << 19) +#define SX_BUSY (1 << 20) +#define SPI_BUSY (1 << 22) +#define BCI_BUSY (1 << 23) +#define SC_BUSY (1 << 24) +#define PA_BUSY (1 << 25) +#define DB_BUSY (1 << 26) +#define CP_COHERENCY_BUSY (1 << 28) +#define CP_BUSY (1 << 29) +#define CB_BUSY (1 << 30) +#define GUI_ACTIVE (1 << 31) +#define GRBM_STATUS_SE0 0x8014 +#define GRBM_STATUS_SE1 0x8018 +#define SE_DB_CLEAN (1 << 1) +#define SE_CB_CLEAN (1 << 2) +#define SE_BCI_BUSY (1 << 22) +#define SE_VGT_BUSY (1 << 23) +#define SE_PA_BUSY (1 << 24) +#define SE_TA_BUSY (1 << 25) +#define SE_SX_BUSY (1 << 26) +#define SE_SPI_BUSY (1 << 27) +#define SE_SC_BUSY (1 << 29) +#define SE_DB_BUSY (1 << 30) +#define SE_CB_BUSY (1 << 31) + +#define GRBM_SOFT_RESET 0x8020 +#define SOFT_RESET_CP (1 << 0) +#define SOFT_RESET_CB (1 << 1) +#define SOFT_RESET_RLC (1 << 2) +#define SOFT_RESET_DB (1 << 3) +#define SOFT_RESET_GDS (1 << 4) +#define SOFT_RESET_PA (1 << 5) +#define SOFT_RESET_SC (1 << 6) +#define SOFT_RESET_BCI (1 << 7) +#define SOFT_RESET_SPI (1 << 8) +#define SOFT_RESET_SX (1 << 10) +#define SOFT_RESET_TC (1 << 11) +#define SOFT_RESET_TA (1 << 12) +#define SOFT_RESET_VGT (1 << 14) +#define SOFT_RESET_IA (1 << 15) + +#define GRBM_GFX_INDEX 0x802C +#define INSTANCE_INDEX(x) ((x) << 0) +#define SH_INDEX(x) ((x) << 8) +#define SE_INDEX(x) ((x) << 16) +#define SH_BROADCAST_WRITES (1 << 29) +#define INSTANCE_BROADCAST_WRITES (1 << 30) +#define SE_BROADCAST_WRITES (1 << 31) + +#define GRBM_INT_CNTL 0x8060 +# define RDERR_INT_ENABLE (1 << 0) +# define GUI_IDLE_INT_ENABLE (1 << 19) + +#define CP_STRMOUT_CNTL 0x84FC +#define SCRATCH_REG0 0x8500 +#define SCRATCH_REG1 0x8504 +#define SCRATCH_REG2 0x8508 +#define SCRATCH_REG3 0x850C +#define SCRATCH_REG4 0x8510 +#define SCRATCH_REG5 0x8514 +#define SCRATCH_REG6 0x8518 +#define SCRATCH_REG7 0x851C + +#define SCRATCH_UMSK 0x8540 +#define SCRATCH_ADDR 0x8544 + +#define CP_SEM_WAIT_TIMER 0x85BC + +#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 + +#define CP_ME_CNTL 0x86D8 +#define CP_CE_HALT (1 << 24) +#define CP_PFP_HALT (1 << 26) +#define CP_ME_HALT (1 << 28) + +#define CP_COHER_CNTL2 0x85E8 + +#define CP_RB2_RPTR 0x86f8 +#define CP_RB1_RPTR 0x86fc +#define CP_RB0_RPTR 0x8700 +#define CP_RB_WPTR_DELAY 0x8704 + +#define CP_QUEUE_THRESHOLDS 0x8760 +#define ROQ_IB1_START(x) ((x) << 0) +#define ROQ_IB2_START(x) ((x) << 8) +#define CP_MEQ_THRESHOLDS 0x8764 +#define MEQ1_START(x) ((x) << 0) +#define MEQ2_START(x) ((x) << 8) + +#define CP_PERFMON_CNTL 0x87FC + +#define VGT_VTX_VECT_EJECT_REG 0x88B0 + +#define VGT_CACHE_INVALIDATION 0x88C4 +#define CACHE_INVALIDATION(x) ((x) << 0) +#define VC_ONLY 0 +#define TC_ONLY 1 +#define VC_AND_TC 2 +#define AUTO_INVLD_EN(x) ((x) << 6) +#define NO_AUTO 0 +#define ES_AUTO 1 +#define GS_AUTO 2 +#define ES_AND_GS_AUTO 3 +#define VGT_ESGS_RING_SIZE 0x88C8 +#define VGT_GSVS_RING_SIZE 0x88CC + +#define VGT_GS_VERTEX_REUSE 0x88D4 + +#define VGT_PRIMITIVE_TYPE 0x8958 +#define VGT_INDEX_TYPE 0x895C + +#define VGT_NUM_INDICES 0x8970 +#define VGT_NUM_INSTANCES 0x8974 + +#define VGT_TF_RING_SIZE 0x8988 + +#define VGT_HS_OFFCHIP_PARAM 0x89B0 + +#define VGT_TF_MEMORY_BASE 0x89B8 + +#define CC_GC_SHADER_ARRAY_CONFIG 0x89bc +#define INACTIVE_CUS_MASK 0xFFFF0000 +#define INACTIVE_CUS_SHIFT 16 +#define GC_USER_SHADER_ARRAY_CONFIG 0x89c0 + +#define PA_CL_ENHANCE 0x8A14 +#define CLIP_VTX_REORDER_ENA (1 << 0) +#define NUM_CLIP_SEQ(x) ((x) << 1) + +#define PA_SU_LINE_STIPPLE_VALUE 0x8A60 + +#define PA_SC_LINE_STIPPLE_STATE 0x8B10 + +#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 +#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) + +#define PA_SC_FIFO_SIZE 0x8BCC +#define SC_FRONTEND_PRIM_FIFO_SIZE(x) ((x) << 0) +#define SC_BACKEND_PRIM_FIFO_SIZE(x) ((x) << 6) +#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 15) +#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 23) + +#define PA_SC_ENHANCE 0x8BF0 + +#define SQ_CONFIG 0x8C00 + +#define SQC_CACHES 0x8C08 + +#define SX_DEBUG_1 0x9060 + +#define SPI_STATIC_THREAD_MGMT_1 0x90E0 +#define SPI_STATIC_THREAD_MGMT_2 0x90E4 +#define SPI_STATIC_THREAD_MGMT_3 0x90E8 +#define SPI_PS_MAX_WAVE_ID 0x90EC + +#define SPI_CONFIG_CNTL 0x9100 + +#define SPI_CONFIG_CNTL_1 0x913C +#define VTX_DONE_DELAY(x) ((x) << 0) +#define INTERP_ONE_PRIM_PER_ROW (1 << 4) + +#define CGTS_TCC_DISABLE 0x9148 +#define CGTS_USER_TCC_DISABLE 0x914C +#define TCC_DISABLE_MASK 0xFFFF0000 +#define TCC_DISABLE_SHIFT 16 + +#define TA_CNTL_AUX 0x9508 + +#define CC_RB_BACKEND_DISABLE 0x98F4 +#define BACKEND_DISABLE(x) ((x) << 16) +#define GB_ADDR_CONFIG 0x98F8 +#define NUM_PIPES(x) ((x) << 0) +#define NUM_PIPES_MASK 0x00000007 +#define NUM_PIPES_SHIFT 0 +#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) +#define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 +#define PIPE_INTERLEAVE_SIZE_SHIFT 4 +#define NUM_SHADER_ENGINES(x) ((x) << 12) +#define NUM_SHADER_ENGINES_MASK 0x00003000 +#define NUM_SHADER_ENGINES_SHIFT 12 +#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) +#define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 +#define SHADER_ENGINE_TILE_SIZE_SHIFT 16 +#define NUM_GPUS(x) ((x) << 20) +#define NUM_GPUS_MASK 0x00700000 +#define NUM_GPUS_SHIFT 20 +#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) +#define MULTI_GPU_TILE_SIZE_MASK 0x03000000 +#define MULTI_GPU_TILE_SIZE_SHIFT 24 +#define ROW_SIZE(x) ((x) << 28) +#define ROW_SIZE_MASK 0x30000000 +#define ROW_SIZE_SHIFT 28 + +#define GB_TILE_MODE0 0x9910 +# define MICRO_TILE_MODE(x) ((x) << 0) +# define ADDR_SURF_DISPLAY_MICRO_TILING 0 +# define ADDR_SURF_THIN_MICRO_TILING 1 +# define ADDR_SURF_DEPTH_MICRO_TILING 2 +# define ARRAY_MODE(x) ((x) << 2) +# define ARRAY_LINEAR_GENERAL 0 +# define ARRAY_LINEAR_ALIGNED 1 +# define ARRAY_1D_TILED_THIN1 2 +# define ARRAY_2D_TILED_THIN1 4 +# define PIPE_CONFIG(x) ((x) << 6) +# define ADDR_SURF_P2 0 +# define ADDR_SURF_P4_8x16 4 +# define ADDR_SURF_P4_16x16 5 +# define ADDR_SURF_P4_16x32 6 +# define ADDR_SURF_P4_32x32 7 +# define ADDR_SURF_P8_16x16_8x16 8 +# define ADDR_SURF_P8_16x32_8x16 9 +# define ADDR_SURF_P8_32x32_8x16 10 +# define ADDR_SURF_P8_16x32_16x16 11 +# define ADDR_SURF_P8_32x32_16x16 12 +# define ADDR_SURF_P8_32x32_16x32 13 +# define ADDR_SURF_P8_32x64_32x32 14 +# define TILE_SPLIT(x) ((x) << 11) +# define ADDR_SURF_TILE_SPLIT_64B 0 +# define ADDR_SURF_TILE_SPLIT_128B 1 +# define ADDR_SURF_TILE_SPLIT_256B 2 +# define ADDR_SURF_TILE_SPLIT_512B 3 +# define ADDR_SURF_TILE_SPLIT_1KB 4 +# define ADDR_SURF_TILE_SPLIT_2KB 5 +# define ADDR_SURF_TILE_SPLIT_4KB 6 +# define BANK_WIDTH(x) ((x) << 14) +# define ADDR_SURF_BANK_WIDTH_1 0 +# define ADDR_SURF_BANK_WIDTH_2 1 +# define ADDR_SURF_BANK_WIDTH_4 2 +# define ADDR_SURF_BANK_WIDTH_8 3 +# define BANK_HEIGHT(x) ((x) << 16) +# define ADDR_SURF_BANK_HEIGHT_1 0 +# define ADDR_SURF_BANK_HEIGHT_2 1 +# define ADDR_SURF_BANK_HEIGHT_4 2 +# define ADDR_SURF_BANK_HEIGHT_8 3 +# define MACRO_TILE_ASPECT(x) ((x) << 18) +# define ADDR_SURF_MACRO_ASPECT_1 0 +# define ADDR_SURF_MACRO_ASPECT_2 1 +# define ADDR_SURF_MACRO_ASPECT_4 2 +# define ADDR_SURF_MACRO_ASPECT_8 3 +# define NUM_BANKS(x) ((x) << 20) +# define ADDR_SURF_2_BANK 0 +# define ADDR_SURF_4_BANK 1 +# define ADDR_SURF_8_BANK 2 +# define ADDR_SURF_16_BANK 3 + +#define CB_PERFCOUNTER0_SELECT0 0x9a20 +#define CB_PERFCOUNTER0_SELECT1 0x9a24 +#define CB_PERFCOUNTER1_SELECT0 0x9a28 +#define CB_PERFCOUNTER1_SELECT1 0x9a2c +#define CB_PERFCOUNTER2_SELECT0 0x9a30 +#define CB_PERFCOUNTER2_SELECT1 0x9a34 +#define CB_PERFCOUNTER3_SELECT0 0x9a38 +#define CB_PERFCOUNTER3_SELECT1 0x9a3c + +#define GC_USER_RB_BACKEND_DISABLE 0x9B7C +#define BACKEND_DISABLE_MASK 0x00FF0000 +#define BACKEND_DISABLE_SHIFT 16 + +#define TCP_CHAN_STEER_LO 0xac0c +#define TCP_CHAN_STEER_HI 0xac10 + +#define CP_RB0_BASE 0xC100 +#define CP_RB0_CNTL 0xC104 +#define RB_BUFSZ(x) ((x) << 0) +#define RB_BLKSZ(x) ((x) << 8) +#define BUF_SWAP_32BIT (2 << 16) +#define RB_NO_UPDATE (1 << 27) +#define RB_RPTR_WR_ENA (1 << 31) + +#define CP_RB0_RPTR_ADDR 0xC10C +#define CP_RB0_RPTR_ADDR_HI 0xC110 +#define CP_RB0_WPTR 0xC114 + +#define CP_PFP_UCODE_ADDR 0xC150 +#define CP_PFP_UCODE_DATA 0xC154 +#define CP_ME_RAM_RADDR 0xC158 +#define CP_ME_RAM_WADDR 0xC15C +#define CP_ME_RAM_DATA 0xC160 + +#define CP_CE_UCODE_ADDR 0xC168 +#define CP_CE_UCODE_DATA 0xC16C + +#define CP_RB1_BASE 0xC180 +#define CP_RB1_CNTL 0xC184 +#define CP_RB1_RPTR_ADDR 0xC188 +#define CP_RB1_RPTR_ADDR_HI 0xC18C +#define CP_RB1_WPTR 0xC190 +#define CP_RB2_BASE 0xC194 +#define CP_RB2_CNTL 0xC198 +#define CP_RB2_RPTR_ADDR 0xC19C +#define CP_RB2_RPTR_ADDR_HI 0xC1A0 +#define CP_RB2_WPTR 0xC1A4 +#define CP_INT_CNTL_RING0 0xC1A8 +#define CP_INT_CNTL_RING1 0xC1AC +#define CP_INT_CNTL_RING2 0xC1B0 +# define CNTX_BUSY_INT_ENABLE (1 << 19) +# define CNTX_EMPTY_INT_ENABLE (1 << 20) +# define WAIT_MEM_SEM_INT_ENABLE (1 << 21) +# define TIME_STAMP_INT_ENABLE (1 << 26) +# define CP_RINGID2_INT_ENABLE (1 << 29) +# define CP_RINGID1_INT_ENABLE (1 << 30) +# define CP_RINGID0_INT_ENABLE (1 << 31) +#define CP_INT_STATUS_RING0 0xC1B4 +#define CP_INT_STATUS_RING1 0xC1B8 +#define CP_INT_STATUS_RING2 0xC1BC +# define WAIT_MEM_SEM_INT_STAT (1 << 21) +# define TIME_STAMP_INT_STAT (1 << 26) +# define CP_RINGID2_INT_STAT (1 << 29) +# define CP_RINGID1_INT_STAT (1 << 30) +# define CP_RINGID0_INT_STAT (1 << 31) + +#define CP_DEBUG 0xC1FC + +#define RLC_CNTL 0xC300 +# define RLC_ENABLE (1 << 0) +#define RLC_RL_BASE 0xC304 +#define RLC_RL_SIZE 0xC308 +#define RLC_LB_CNTL 0xC30C +#define RLC_SAVE_AND_RESTORE_BASE 0xC310 +#define RLC_LB_CNTR_MAX 0xC314 +#define RLC_LB_CNTR_INIT 0xC318 + +#define RLC_CLEAR_STATE_RESTORE_BASE 0xC320 + +#define RLC_UCODE_ADDR 0xC32C +#define RLC_UCODE_DATA 0xC330 + +#define RLC_GPU_CLOCK_COUNT_LSB 0xC338 +#define RLC_GPU_CLOCK_COUNT_MSB 0xC33C +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC340 +#define RLC_MC_CNTL 0xC344 +#define RLC_UCODE_CNTL 0xC348 + +#define PA_SC_RASTER_CONFIG 0x28350 +# define RASTER_CONFIG_RB_MAP_0 0 +# define RASTER_CONFIG_RB_MAP_1 1 +# define RASTER_CONFIG_RB_MAP_2 2 +# define RASTER_CONFIG_RB_MAP_3 3 + +#define VGT_EVENT_INITIATOR 0x28a90 +# define SAMPLE_STREAMOUTSTATS1 (1 << 0) +# define SAMPLE_STREAMOUTSTATS2 (2 << 0) +# define SAMPLE_STREAMOUTSTATS3 (3 << 0) +# define CACHE_FLUSH_TS (4 << 0) +# define CACHE_FLUSH (6 << 0) +# define CS_PARTIAL_FLUSH (7 << 0) +# define VGT_STREAMOUT_RESET (10 << 0) +# define END_OF_PIPE_INCR_DE (11 << 0) +# define END_OF_PIPE_IB_END (12 << 0) +# define RST_PIX_CNT (13 << 0) +# define VS_PARTIAL_FLUSH (15 << 0) +# define PS_PARTIAL_FLUSH (16 << 0) +# define CACHE_FLUSH_AND_INV_TS_EVENT (20 << 0) +# define ZPASS_DONE (21 << 0) +# define CACHE_FLUSH_AND_INV_EVENT (22 << 0) +# define PERFCOUNTER_START (23 << 0) +# define PERFCOUNTER_STOP (24 << 0) +# define PIPELINESTAT_START (25 << 0) +# define PIPELINESTAT_STOP (26 << 0) +# define PERFCOUNTER_SAMPLE (27 << 0) +# define SAMPLE_PIPELINESTAT (30 << 0) +# define SAMPLE_STREAMOUTSTATS (32 << 0) +# define RESET_VTX_CNT (33 << 0) +# define VGT_FLUSH (36 << 0) +# define BOTTOM_OF_PIPE_TS (40 << 0) +# define DB_CACHE_FLUSH_AND_INV (42 << 0) +# define FLUSH_AND_INV_DB_DATA_TS (43 << 0) +# define FLUSH_AND_INV_DB_META (44 << 0) +# define FLUSH_AND_INV_CB_DATA_TS (45 << 0) +# define FLUSH_AND_INV_CB_META (46 << 0) +# define CS_DONE (47 << 0) +# define PS_DONE (48 << 0) +# define FLUSH_AND_INV_CB_PIXEL_DATA (49 << 0) +# define THREAD_TRACE_START (51 << 0) +# define THREAD_TRACE_STOP (52 << 0) +# define THREAD_TRACE_FLUSH (54 << 0) +# define THREAD_TRACE_FINISH (55 << 0) + +/* + * PM4 + */ +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) +#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ + (((reg) >> 2) & 0xFFFF) | \ + ((n) & 0x3FFF) << 16) +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) + +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) + +#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +#define PACKET3_COMPUTE(op, n) (PACKET3(op, n) | 1 << 1) + +/* Packet 3 types */ +#define PACKET3_NOP 0x10 +#define PACKET3_SET_BASE 0x11 +#define PACKET3_BASE_INDEX(x) ((x) << 0) +#define GDS_PARTITION_BASE 2 +#define CE_PARTITION_BASE 3 +#define PACKET3_CLEAR_STATE 0x12 +#define PACKET3_INDEX_BUFFER_SIZE 0x13 +#define PACKET3_DISPATCH_DIRECT 0x15 +#define PACKET3_DISPATCH_INDIRECT 0x16 +#define PACKET3_ALLOC_GDS 0x1B +#define PACKET3_WRITE_GDS_RAM 0x1C +#define PACKET3_ATOMIC_GDS 0x1D +#define PACKET3_ATOMIC 0x1E +#define PACKET3_OCCLUSION_QUERY 0x1F +#define PACKET3_SET_PREDICATION 0x20 +#define PACKET3_REG_RMW 0x21 +#define PACKET3_COND_EXEC 0x22 +#define PACKET3_PRED_EXEC 0x23 +#define PACKET3_DRAW_INDIRECT 0x24 +#define PACKET3_DRAW_INDEX_INDIRECT 0x25 +#define PACKET3_INDEX_BASE 0x26 +#define PACKET3_DRAW_INDEX_2 0x27 +#define PACKET3_CONTEXT_CONTROL 0x28 +#define PACKET3_INDEX_TYPE 0x2A +#define PACKET3_DRAW_INDIRECT_MULTI 0x2C +#define PACKET3_DRAW_INDEX_AUTO 0x2D +#define PACKET3_DRAW_INDEX_IMMD 0x2E +#define PACKET3_NUM_INSTANCES 0x2F +#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 +#define PACKET3_INDIRECT_BUFFER_CONST 0x31 +#define PACKET3_INDIRECT_BUFFER 0x32 +#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 +#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 +#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 +#define PACKET3_WRITE_DATA 0x37 +#define WRITE_DATA_DST_SEL(x) ((x) << 8) + /* 0 - register + * 1 - memory (sync - via GRBM) + * 2 - tc/l2 + * 3 - gds + * 4 - reserved + * 5 - memory (async - direct) + */ +#define WR_ONE_ADDR (1 << 16) +#define WR_CONFIRM (1 << 20) +#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30) + /* 0 - me + * 1 - pfp + * 2 - ce + */ +#define PACKET3_DRAW_INDEX_INDIRECT_MULTI 0x38 +#define PACKET3_MEM_SEMAPHORE 0x39 +#define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B +#define PACKET3_WAIT_REG_MEM 0x3C +#define PACKET3_MEM_WRITE 0x3D +#define PACKET3_COPY_DATA 0x40 +#define PACKET3_CP_DMA 0x41 +/* 1. header + * 2. SRC_ADDR_LO or DATA [31:0] + * 3. CP_SYNC [31] | SRC_SEL [30:29] | ENGINE [27] | DST_SEL [21:20] | + * SRC_ADDR_HI [7:0] + * 4. DST_ADDR_LO [31:0] + * 5. DST_ADDR_HI [7:0] + * 6. COMMAND [30:21] | BYTE_COUNT [20:0] + */ +# define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) + /* 0 - SRC_ADDR + * 1 - GDS + */ +# define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) + /* 0 - ME + * 1 - PFP + */ +# define PACKET3_CP_DMA_SRC_SEL(x) ((x) << 29) + /* 0 - SRC_ADDR + * 1 - GDS + * 2 - DATA + */ +# define PACKET3_CP_DMA_CP_SYNC (1 << 31) +/* COMMAND */ +# define PACKET3_CP_DMA_DIS_WC (1 << 21) +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_DST_SWAP(x) ((x) << 24) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_SAS (1 << 26) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_DAS (1 << 27) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_SAIC (1 << 28) +# define PACKET3_CP_DMA_CMD_DAIC (1 << 29) +# define PACKET3_CP_DMA_CMD_RAW_WAIT (1 << 30) +#define PACKET3_PFP_SYNC_ME 0x42 +#define PACKET3_SURFACE_SYNC 0x43 +# define PACKET3_DEST_BASE_0_ENA (1 << 0) +# define PACKET3_DEST_BASE_1_ENA (1 << 1) +# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) +# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) +# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) +# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) +# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) +# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) +# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) +# define PACKET3_DB_DEST_BASE_ENA (1 << 14) +# define PACKET3_DEST_BASE_2_ENA (1 << 19) +# define PACKET3_DEST_BASE_3_ENA (1 << 21) +# define PACKET3_TCL1_ACTION_ENA (1 << 22) +# define PACKET3_TC_ACTION_ENA (1 << 23) +# define PACKET3_CB_ACTION_ENA (1 << 25) +# define PACKET3_DB_ACTION_ENA (1 << 26) +# define PACKET3_SH_KCACHE_ACTION_ENA (1 << 27) +# define PACKET3_SH_ICACHE_ACTION_ENA (1 << 29) +#define PACKET3_ME_INITIALIZE 0x44 +#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) +#define PACKET3_COND_WRITE 0x45 +#define PACKET3_EVENT_WRITE 0x46 +#define EVENT_TYPE(x) ((x) << 0) +#define EVENT_INDEX(x) ((x) << 8) + /* 0 - any non-TS event + * 1 - ZPASS_DONE + * 2 - SAMPLE_PIPELINESTAT + * 3 - SAMPLE_STREAMOUTSTAT* + * 4 - *S_PARTIAL_FLUSH + * 5 - EOP events + * 6 - EOS events + * 7 - CACHE_FLUSH, CACHE_FLUSH_AND_INV_EVENT + */ +#define INV_L2 (1 << 20) + /* INV TC L2 cache when EVENT_INDEX = 7 */ +#define PACKET3_EVENT_WRITE_EOP 0x47 +#define DATA_SEL(x) ((x) << 29) + /* 0 - discard + * 1 - send low 32bit data + * 2 - send 64bit data + * 3 - send 64bit counter value + */ +#define INT_SEL(x) ((x) << 24) + /* 0 - none + * 1 - interrupt only (DATA_SEL = 0) + * 2 - interrupt when data write is confirmed + */ +#define PACKET3_EVENT_WRITE_EOS 0x48 +#define PACKET3_PREAMBLE_CNTL 0x4A +# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) +# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) +#define PACKET3_ONE_REG_WRITE 0x57 +#define PACKET3_LOAD_CONFIG_REG 0x5F +#define PACKET3_LOAD_CONTEXT_REG 0x60 +#define PACKET3_LOAD_SH_REG 0x61 +#define PACKET3_SET_CONFIG_REG 0x68 +#define PACKET3_SET_CONFIG_REG_START 0x00008000 +#define PACKET3_SET_CONFIG_REG_END 0x0000b000 +#define PACKET3_SET_CONTEXT_REG 0x69 +#define PACKET3_SET_CONTEXT_REG_START 0x00028000 +#define PACKET3_SET_CONTEXT_REG_END 0x00029000 +#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 +#define PACKET3_SET_RESOURCE_INDIRECT 0x74 +#define PACKET3_SET_SH_REG 0x76 +#define PACKET3_SET_SH_REG_START 0x0000b000 +#define PACKET3_SET_SH_REG_END 0x0000c000 +#define PACKET3_SET_SH_REG_OFFSET 0x77 +#define PACKET3_ME_WRITE 0x7A +#define PACKET3_SCRATCH_RAM_WRITE 0x7D +#define PACKET3_SCRATCH_RAM_READ 0x7E +#define PACKET3_CE_WRITE 0x7F +#define PACKET3_LOAD_CONST_RAM 0x80 +#define PACKET3_WRITE_CONST_RAM 0x81 +#define PACKET3_WRITE_CONST_RAM_OFFSET 0x82 +#define PACKET3_DUMP_CONST_RAM 0x83 +#define PACKET3_INCREMENT_CE_COUNTER 0x84 +#define PACKET3_INCREMENT_DE_COUNTER 0x85 +#define PACKET3_WAIT_ON_CE_COUNTER 0x86 +#define PACKET3_WAIT_ON_DE_COUNTER 0x87 +#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 +#define PACKET3_SET_CE_DE_COUNTERS 0x89 +#define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A +#define PACKET3_SWITCH_BUFFER 0x8B + +/* ASYNC DMA - first instance at 0xd000, second at 0xd800 */ +#define DMA0_REGISTER_OFFSET 0x0 /* not a register */ +#define DMA1_REGISTER_OFFSET 0x800 /* not a register */ + +#define DMA_RB_CNTL 0xd000 +# define DMA_RB_ENABLE (1 << 0) +# define DMA_RB_SIZE(x) ((x) << 1) /* log2 */ +# define DMA_RB_SWAP_ENABLE (1 << 9) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_ENABLE (1 << 12) +# define DMA_RPTR_WRITEBACK_SWAP_ENABLE (1 << 13) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_TIMER(x) ((x) << 16) /* log2 */ +#define DMA_RB_BASE 0xd004 +#define DMA_RB_RPTR 0xd008 +#define DMA_RB_WPTR 0xd00c + +#define DMA_RB_RPTR_ADDR_HI 0xd01c +#define DMA_RB_RPTR_ADDR_LO 0xd020 + +#define DMA_IB_CNTL 0xd024 +# define DMA_IB_ENABLE (1 << 0) +# define DMA_IB_SWAP_ENABLE (1 << 4) +#define DMA_IB_RPTR 0xd028 +#define DMA_CNTL 0xd02c +# define TRAP_ENABLE (1 << 0) +# define SEM_INCOMPLETE_INT_ENABLE (1 << 1) +# define SEM_WAIT_INT_ENABLE (1 << 2) +# define DATA_SWAP_ENABLE (1 << 3) +# define FENCE_SWAP_ENABLE (1 << 4) +# define CTXEMPTY_INT_ENABLE (1 << 28) +#define DMA_STATUS_REG 0xd034 +# define DMA_IDLE (1 << 0) +#define DMA_TILING_CONFIG 0xd0b8 + +#define DMA_PACKET(cmd, b, t, s, n) ((((cmd) & 0xF) << 28) | \ + (((b) & 0x1) << 26) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((n) & 0xFFFFF) << 0)) + +#define DMA_IB_PACKET(cmd, vmid, n) ((((cmd) & 0xF) << 28) | \ + (((vmid) & 0xF) << 20) | \ + (((n) & 0xFFFFF) << 0)) + +#define DMA_PTE_PDE_PACKET(n) ((2 << 28) | \ + (1 << 26) | \ + (1 << 21) | \ + (((n) & 0xFFFFF) << 0)) + +/* async DMA Packet types */ +#define DMA_PACKET_WRITE 0x2 +#define DMA_PACKET_COPY 0x3 +#define DMA_PACKET_INDIRECT_BUFFER 0x4 +#define DMA_PACKET_SEMAPHORE 0x5 +#define DMA_PACKET_FENCE 0x6 +#define DMA_PACKET_TRAP 0x7 +#define DMA_PACKET_SRBM_WRITE 0x9 +#define DMA_PACKET_CONSTANT_FILL 0xd +#define DMA_PACKET_NOP 0xf + +#endif diff --git a/sys/modules/drm2/Makefile b/sys/modules/drm2/Makefile index f8411e3df4a..02e35eaad4d 100644 --- a/sys/modules/drm2/Makefile +++ b/sys/modules/drm2/Makefile @@ -2,8 +2,14 @@ .include +.if ${MK_SOURCELESS_UCODE} != "no" +_radeonkmsfw= radeonkmsfw +.endif + SUBDIR = \ drm2 \ - i915kms + i915kms \ + radeonkms \ + ${_radeonkmsfw} .include diff --git a/sys/modules/drm2/drm2/Makefile b/sys/modules/drm2/drm2/Makefile index 9105c780d8f..acb2d331156 100644 --- a/sys/modules/drm2/drm2/Makefile +++ b/sys/modules/drm2/drm2/Makefile @@ -44,7 +44,8 @@ SRCS = \ ttm_execbuf_util.c \ ttm_memory.c \ ttm_page_alloc.c \ - ttm_bo_vm.c + ttm_bo_vm.c \ + ati_pcigart.c #ttm_agp_backend.c #ttm_page_alloc_dma.c diff --git a/sys/modules/drm2/radeonkms/Makefile b/sys/modules/drm2/radeonkms/Makefile new file mode 100644 index 00000000000..f8468f60e17 --- /dev/null +++ b/sys/modules/drm2/radeonkms/Makefile @@ -0,0 +1,107 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/drm2/radeon + +KMOD = radeonkms +SRCS = \ + rn50_reg_safe.h \ + r100_reg_safe.h \ + r200_reg_safe.h \ + rv515_reg_safe.h \ + r300_reg_safe.h \ + r420_reg_safe.h \ + rs600_reg_safe.h \ + r600_reg_safe.h \ + evergreen_reg_safe.h \ + cayman_reg_safe.h +SRCS += \ + radeon_acpi.c \ + radeon_agp.c \ + radeon_asic.c \ + radeon_atombios.c \ + radeon_atpx_handler.c \ + radeon_benchmark.c \ + radeon_bios.c \ + radeon_clocks.c \ + radeon_combios.c \ + radeon_connectors.c \ + radeon_cp.c \ + radeon_cs.c \ + radeon_cursor.c \ + radeon_device.c \ + radeon_display.c \ + radeon_drv.c \ + radeon_encoders.c \ + radeon_fb.c \ + radeon_fence.c \ + radeon_gart.c \ + radeon_gem.c \ + radeon_i2c.c \ + radeon_irq.c \ + radeon_irq_kms.c \ + radeon_kms.c \ + radeon_legacy_crtc.c \ + radeon_legacy_encoders.c \ + radeon_legacy_tv.c \ + radeon_mem.c \ + radeon_object.c \ + radeon_pm.c \ + radeon_ring.c \ + radeon_sa.c \ + radeon_semaphore.c \ + radeon_state.c \ + radeon_test.c \ + radeon_ttm.c \ + atom.c \ + atombios_crtc.c \ + atombios_dp.c \ + atombios_encoders.c \ + atombios_i2c.c \ + r100.c \ + r200.c \ + r300.c \ + r300_cmdbuf.c \ + r420.c \ + rs400.c \ + rs600.c \ + rs690.c \ + rv515.c \ + r520.c \ + r600.c \ + r600_audio.c \ + r600_blit.c \ + r600_blit_kms.c \ + r600_blit_shaders.c \ + r600_cp.c \ + r600_cs.c \ + r600_hdmi.c \ + rv770.c \ + evergreen.c \ + evergreen_blit_kms.c \ + evergreen_blit_shaders.c \ + evergreen_cs.c \ + evergreen_hdmi.c \ + cayman_blit_shaders.c \ + ni.c \ + si.c \ + si_blit_shaders.c + +#radeon_ioc32.c +#radeon_prime.c +#--radeon_trace_points.c + +SRCS += \ + opt_acpi.h \ + opt_compat.h \ + opt_drm.h \ + acpi_if.h \ + bus_if.h \ + device_if.h \ + iicbb_if.h \ + iicbus_if.h \ + pci_if.h + +CFLAGS += -I${.CURDIR}/../../../dev/drm2/radeon \ + -fms-extensions + +.include diff --git a/sys/modules/drm2/radeonkmsfw/ARUBA_me/Makefile b/sys/modules/drm2/radeonkmsfw/ARUBA_me/Makefile new file mode 100644 index 00000000000..a73cf0689df --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/ARUBA_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_ARUBA_me +IMG= ARUBA_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/ARUBA_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/ARUBA_pfp/Makefile new file mode 100644 index 00000000000..83c2d2116bd --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/ARUBA_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_ARUBA_pfp +IMG= ARUBA_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/ARUBA_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/ARUBA_rlc/Makefile new file mode 100644 index 00000000000..95cafc2d0ce --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/ARUBA_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_ARUBA_rlc +IMG= ARUBA_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/BARTS_mc/Makefile b/sys/modules/drm2/radeonkmsfw/BARTS_mc/Makefile new file mode 100644 index 00000000000..d8c530a5b22 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/BARTS_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_BARTS_mc +IMG= BARTS_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/BARTS_me/Makefile b/sys/modules/drm2/radeonkmsfw/BARTS_me/Makefile new file mode 100644 index 00000000000..86da68820e7 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/BARTS_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_BARTS_me +IMG= BARTS_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/BARTS_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/BARTS_pfp/Makefile new file mode 100644 index 00000000000..690cd3240ea --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/BARTS_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_BARTS_pfp +IMG= BARTS_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/BTC_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/BTC_rlc/Makefile new file mode 100644 index 00000000000..900a2e959e0 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/BTC_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_BTC_rlc +IMG= BTC_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAICOS_mc/Makefile b/sys/modules/drm2/radeonkmsfw/CAICOS_mc/Makefile new file mode 100644 index 00000000000..9b0fe6692da --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAICOS_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAICOS_mc +IMG= CAICOS_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAICOS_me/Makefile b/sys/modules/drm2/radeonkmsfw/CAICOS_me/Makefile new file mode 100644 index 00000000000..c3a167e6286 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAICOS_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAICOS_me +IMG= CAICOS_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAICOS_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/CAICOS_pfp/Makefile new file mode 100644 index 00000000000..bbee7aa0b14 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAICOS_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAICOS_pfp +IMG= CAICOS_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAYMAN_mc/Makefile b/sys/modules/drm2/radeonkmsfw/CAYMAN_mc/Makefile new file mode 100644 index 00000000000..98a4a9a7cb8 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAYMAN_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAYMAN_mc +IMG= CAYMAN_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAYMAN_me/Makefile b/sys/modules/drm2/radeonkmsfw/CAYMAN_me/Makefile new file mode 100644 index 00000000000..8f2c708ce51 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAYMAN_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAYMAN_me +IMG= CAYMAN_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAYMAN_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/CAYMAN_pfp/Makefile new file mode 100644 index 00000000000..6c9adfa0735 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAYMAN_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAYMAN_pfp +IMG= CAYMAN_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CAYMAN_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/CAYMAN_rlc/Makefile new file mode 100644 index 00000000000..9f8fc80797b --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CAYMAN_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CAYMAN_rlc +IMG= CAYMAN_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CEDAR_me/Makefile b/sys/modules/drm2/radeonkmsfw/CEDAR_me/Makefile new file mode 100644 index 00000000000..d693d79f02a --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CEDAR_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CEDAR_me +IMG= CEDAR_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CEDAR_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/CEDAR_pfp/Makefile new file mode 100644 index 00000000000..cef6073f757 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CEDAR_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CEDAR_pfp +IMG= CEDAR_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CEDAR_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/CEDAR_rlc/Makefile new file mode 100644 index 00000000000..d316e467d18 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CEDAR_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CEDAR_rlc +IMG= CEDAR_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CYPRESS_me/Makefile b/sys/modules/drm2/radeonkmsfw/CYPRESS_me/Makefile new file mode 100644 index 00000000000..78fe6c663e8 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CYPRESS_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CYPRESS_me +IMG= CYPRESS_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CYPRESS_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/CYPRESS_pfp/Makefile new file mode 100644 index 00000000000..7b3a6aa7d41 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CYPRESS_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CYPRESS_pfp +IMG= CYPRESS_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CYPRESS_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/CYPRESS_rlc/Makefile new file mode 100644 index 00000000000..a8475b071b4 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CYPRESS_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CYPRESS_rlc +IMG= CYPRESS_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/CYPRESS_uvd/Makefile b/sys/modules/drm2/radeonkmsfw/CYPRESS_uvd/Makefile new file mode 100644 index 00000000000..3779a09439a --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/CYPRESS_uvd/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_CYPRESS_uvd +IMG= CYPRESS_uvd + +.include diff --git a/sys/modules/drm2/radeonkmsfw/HAINAN_ce/Makefile b/sys/modules/drm2/radeonkmsfw/HAINAN_ce/Makefile new file mode 100644 index 00000000000..1aad7cf7d1e --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/HAINAN_ce/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_HAINAN_ce +IMG= HAINAN_ce + +.include diff --git a/sys/modules/drm2/radeonkmsfw/HAINAN_mc/Makefile b/sys/modules/drm2/radeonkmsfw/HAINAN_mc/Makefile new file mode 100644 index 00000000000..54727af4244 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/HAINAN_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_HAINAN_mc +IMG= HAINAN_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/HAINAN_me/Makefile b/sys/modules/drm2/radeonkmsfw/HAINAN_me/Makefile new file mode 100644 index 00000000000..6d065c0ec08 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/HAINAN_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_HAINAN_me +IMG= HAINAN_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/HAINAN_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/HAINAN_pfp/Makefile new file mode 100644 index 00000000000..ccf883413c8 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/HAINAN_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_HAINAN_pfp +IMG= HAINAN_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/HAINAN_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/HAINAN_rlc/Makefile new file mode 100644 index 00000000000..a930fe0b654 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/HAINAN_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_HAINAN_rlc +IMG= HAINAN_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/JUNIPER_me/Makefile b/sys/modules/drm2/radeonkmsfw/JUNIPER_me/Makefile new file mode 100644 index 00000000000..1d10e666619 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/JUNIPER_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_JUNIPER_me +IMG= JUNIPER_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/JUNIPER_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/JUNIPER_pfp/Makefile new file mode 100644 index 00000000000..ef53b1b5b34 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/JUNIPER_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_JUNIPER_pfp +IMG= JUNIPER_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/JUNIPER_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/JUNIPER_rlc/Makefile new file mode 100644 index 00000000000..3fa7388267e --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/JUNIPER_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_JUNIPER_rlc +IMG= JUNIPER_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/Makefile b/sys/modules/drm2/radeonkmsfw/Makefile new file mode 100644 index 00000000000..167743c96e7 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/Makefile @@ -0,0 +1,85 @@ +# $FreeBSD$ + +SUBDIR= \ + ARUBA_me \ + ARUBA_pfp \ + ARUBA_rlc \ + BARTS_mc \ + BARTS_me \ + BARTS_pfp \ + BTC_rlc \ + CAICOS_mc \ + CAICOS_me \ + CAICOS_pfp \ + CAYMAN_mc \ + CAYMAN_me \ + CAYMAN_pfp \ + CAYMAN_rlc \ + CEDAR_me \ + CEDAR_pfp \ + CEDAR_rlc \ + CYPRESS_me \ + CYPRESS_pfp \ + CYPRESS_rlc \ + JUNIPER_me \ + JUNIPER_pfp \ + JUNIPER_rlc \ + PALM_me \ + PALM_pfp \ + PITCAIRN_ce \ + PITCAIRN_mc \ + PITCAIRN_me \ + PITCAIRN_pfp \ + PITCAIRN_rlc \ + R100_cp \ + R200_cp \ + R300_cp \ + R420_cp \ + R520_cp \ + R600_me \ + R600_pfp \ + R600_rlc \ + R700_rlc \ + REDWOOD_me \ + REDWOOD_pfp \ + REDWOOD_rlc \ + RS600_cp \ + RS690_cp \ + RS780_me \ + RS780_pfp \ + RV610_me \ + RV610_pfp \ + RV620_me \ + RV620_pfp \ + RV630_me \ + RV630_pfp \ + RV635_me \ + RV635_pfp \ + RV670_me \ + RV670_pfp \ + RV710_me \ + RV710_pfp \ + RV730_me \ + RV730_pfp \ + RV770_me \ + RV770_pfp \ + SUMO2_me \ + SUMO2_pfp \ + SUMO_me \ + SUMO_pfp \ + SUMO_rlc \ + TAHITI_ce \ + TAHITI_mc \ + TAHITI_me \ + TAHITI_pfp \ + TAHITI_rlc \ + TURKS_mc \ + TURKS_me \ + TURKS_pfp \ + VERDE_ce \ + VERDE_mc \ + VERDE_me \ + VERDE_pfp \ + VERDE_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/Makefile.inc b/sys/modules/drm2/radeonkmsfw/Makefile.inc new file mode 100644 index 00000000000..f6035a19f87 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/Makefile.inc @@ -0,0 +1,18 @@ +# $FreeBSD$ +# +# Common rules for building firmware. Note this gets auto-included +# by the subdir Makefile's as a consequence of included bsd.kmod.mk. + +_FIRM= ${IMG}.bin + +CLEANFILES+= ${_FIRM} + +FIRMWS= ${_FIRM}:${KMOD} + +# +# Note that a license ack is not needed for iwn. +# +#FIRMWARE_LICENSE= + +${_FIRM}: ${.CURDIR}/../../../../contrib/dev/drm2/radeonkmsfw/${_FIRM}.uu + uudecode -p $? > ${.TARGET} diff --git a/sys/modules/drm2/radeonkmsfw/OLAND_ce/Makefile b/sys/modules/drm2/radeonkmsfw/OLAND_ce/Makefile new file mode 100644 index 00000000000..0de1de49830 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/OLAND_ce/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_OLAND_ce +IMG= OLAND_ce + +.include diff --git a/sys/modules/drm2/radeonkmsfw/OLAND_mc/Makefile b/sys/modules/drm2/radeonkmsfw/OLAND_mc/Makefile new file mode 100644 index 00000000000..161bfc0a9a4 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/OLAND_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_OLAND_mc +IMG= OLAND_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/OLAND_me/Makefile b/sys/modules/drm2/radeonkmsfw/OLAND_me/Makefile new file mode 100644 index 00000000000..fbe07cb9de8 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/OLAND_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_OLAND_me +IMG= OLAND_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/OLAND_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/OLAND_pfp/Makefile new file mode 100644 index 00000000000..193d75347c9 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/OLAND_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_OLAND_pfp +IMG= OLAND_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/OLAND_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/OLAND_rlc/Makefile new file mode 100644 index 00000000000..2490b348bc5 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/OLAND_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_OLAND_rlc +IMG= OLAND_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PALM_me/Makefile b/sys/modules/drm2/radeonkmsfw/PALM_me/Makefile new file mode 100644 index 00000000000..f73e1b8d1eb --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PALM_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PALM_me +IMG= PALM_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PALM_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/PALM_pfp/Makefile new file mode 100644 index 00000000000..2e5b2e625f2 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PALM_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PALM_pfp +IMG= PALM_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PITCAIRN_ce/Makefile b/sys/modules/drm2/radeonkmsfw/PITCAIRN_ce/Makefile new file mode 100644 index 00000000000..101d9a4970c --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PITCAIRN_ce/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PITCAIRN_ce +IMG= PITCAIRN_ce + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PITCAIRN_mc/Makefile b/sys/modules/drm2/radeonkmsfw/PITCAIRN_mc/Makefile new file mode 100644 index 00000000000..f1a86924a62 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PITCAIRN_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PITCAIRN_mc +IMG= PITCAIRN_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PITCAIRN_me/Makefile b/sys/modules/drm2/radeonkmsfw/PITCAIRN_me/Makefile new file mode 100644 index 00000000000..b41d40f55dc --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PITCAIRN_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PITCAIRN_me +IMG= PITCAIRN_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PITCAIRN_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/PITCAIRN_pfp/Makefile new file mode 100644 index 00000000000..d60d8b15a06 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PITCAIRN_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PITCAIRN_pfp +IMG= PITCAIRN_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/PITCAIRN_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/PITCAIRN_rlc/Makefile new file mode 100644 index 00000000000..ff9d7c7e082 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/PITCAIRN_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_PITCAIRN_rlc +IMG= PITCAIRN_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R100_cp/Makefile b/sys/modules/drm2/radeonkmsfw/R100_cp/Makefile new file mode 100644 index 00000000000..f5407dd3e8f --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R100_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R100_cp +IMG= R100_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R200_cp/Makefile b/sys/modules/drm2/radeonkmsfw/R200_cp/Makefile new file mode 100644 index 00000000000..bdfc803fae4 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R200_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R200_cp +IMG= R200_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R300_cp/Makefile b/sys/modules/drm2/radeonkmsfw/R300_cp/Makefile new file mode 100644 index 00000000000..41e984b7bee --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R300_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R300_cp +IMG= R300_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R420_cp/Makefile b/sys/modules/drm2/radeonkmsfw/R420_cp/Makefile new file mode 100644 index 00000000000..18e67884e63 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R420_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R420_cp +IMG= R420_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R520_cp/Makefile b/sys/modules/drm2/radeonkmsfw/R520_cp/Makefile new file mode 100644 index 00000000000..484283dd9d5 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R520_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R520_cp +IMG= R520_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R600_me/Makefile b/sys/modules/drm2/radeonkmsfw/R600_me/Makefile new file mode 100644 index 00000000000..e42d1cdf01e --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R600_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R600_me +IMG= R600_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R600_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/R600_pfp/Makefile new file mode 100644 index 00000000000..0cd74c61c6c --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R600_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R600_pfp +IMG= R600_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R600_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/R600_rlc/Makefile new file mode 100644 index 00000000000..6cb5acf3335 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R600_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R600_rlc +IMG= R600_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/R700_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/R700_rlc/Makefile new file mode 100644 index 00000000000..c6853f18ea7 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/R700_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_R700_rlc +IMG= R700_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/REDWOOD_me/Makefile b/sys/modules/drm2/radeonkmsfw/REDWOOD_me/Makefile new file mode 100644 index 00000000000..84019ba7058 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/REDWOOD_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_REDWOOD_me +IMG= REDWOOD_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/REDWOOD_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/REDWOOD_pfp/Makefile new file mode 100644 index 00000000000..f175171d36e --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/REDWOOD_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_REDWOOD_pfp +IMG= REDWOOD_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/REDWOOD_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/REDWOOD_rlc/Makefile new file mode 100644 index 00000000000..2727422f91b --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/REDWOOD_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_REDWOOD_rlc +IMG= REDWOOD_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RS600_cp/Makefile b/sys/modules/drm2/radeonkmsfw/RS600_cp/Makefile new file mode 100644 index 00000000000..d33f0e322c3 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RS600_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RS600_cp +IMG= RS600_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RS690_cp/Makefile b/sys/modules/drm2/radeonkmsfw/RS690_cp/Makefile new file mode 100644 index 00000000000..e295ced8983 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RS690_cp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RS690_cp +IMG= RS690_cp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RS780_me/Makefile b/sys/modules/drm2/radeonkmsfw/RS780_me/Makefile new file mode 100644 index 00000000000..413bf580365 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RS780_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RS780_me +IMG= RS780_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RS780_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RS780_pfp/Makefile new file mode 100644 index 00000000000..c6eb278a767 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RS780_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RS780_pfp +IMG= RS780_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV610_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV610_me/Makefile new file mode 100644 index 00000000000..c44f8415b79 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV610_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV610_me +IMG= RV610_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV610_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV610_pfp/Makefile new file mode 100644 index 00000000000..e6419fd033a --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV610_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV610_pfp +IMG= RV610_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV620_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV620_me/Makefile new file mode 100644 index 00000000000..997e913d268 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV620_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV620_me +IMG= RV620_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV620_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV620_pfp/Makefile new file mode 100644 index 00000000000..476e486e942 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV620_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV620_pfp +IMG= RV620_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV630_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV630_me/Makefile new file mode 100644 index 00000000000..0807570c4ee --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV630_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV630_me +IMG= RV630_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV630_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV630_pfp/Makefile new file mode 100644 index 00000000000..38c66dc888a --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV630_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV630_pfp +IMG= RV630_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV635_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV635_me/Makefile new file mode 100644 index 00000000000..440508e72b7 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV635_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV635_me +IMG= RV635_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV635_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV635_pfp/Makefile new file mode 100644 index 00000000000..01fc97b3604 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV635_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV635_pfp +IMG= RV635_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV670_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV670_me/Makefile new file mode 100644 index 00000000000..3c13ed1dd43 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV670_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV670_me +IMG= RV670_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV670_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV670_pfp/Makefile new file mode 100644 index 00000000000..50aee8d7e8f --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV670_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV670_pfp +IMG= RV670_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV710_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV710_me/Makefile new file mode 100644 index 00000000000..f42c7adc3cd --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV710_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV710_me +IMG= RV710_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV710_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV710_pfp/Makefile new file mode 100644 index 00000000000..5acaf3ffe4b --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV710_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV710_pfp +IMG= RV710_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV710_uvd/Makefile b/sys/modules/drm2/radeonkmsfw/RV710_uvd/Makefile new file mode 100644 index 00000000000..8146bc2cd2a --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV710_uvd/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV710_uvd +IMG= RV710_uvd + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV730_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV730_me/Makefile new file mode 100644 index 00000000000..9a0907de02b --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV730_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV730_me +IMG= RV730_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV730_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV730_pfp/Makefile new file mode 100644 index 00000000000..0ecb70cb6d9 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV730_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV730_pfp +IMG= RV730_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV770_me/Makefile b/sys/modules/drm2/radeonkmsfw/RV770_me/Makefile new file mode 100644 index 00000000000..85852a175d9 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV770_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV770_me +IMG= RV770_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/RV770_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/RV770_pfp/Makefile new file mode 100644 index 00000000000..2eebdfabb18 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/RV770_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_RV770_pfp +IMG= RV770_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/SUMO2_me/Makefile b/sys/modules/drm2/radeonkmsfw/SUMO2_me/Makefile new file mode 100644 index 00000000000..2d6091fb212 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/SUMO2_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_SUMO2_me +IMG= SUMO2_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/SUMO2_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/SUMO2_pfp/Makefile new file mode 100644 index 00000000000..2b99a5f5e54 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/SUMO2_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_SUMO2_pfp +IMG= SUMO2_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/SUMO_me/Makefile b/sys/modules/drm2/radeonkmsfw/SUMO_me/Makefile new file mode 100644 index 00000000000..e050d3e7e18 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/SUMO_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_SUMO_me +IMG= SUMO_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/SUMO_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/SUMO_pfp/Makefile new file mode 100644 index 00000000000..2fc1ac2744c --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/SUMO_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_SUMO_pfp +IMG= SUMO_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/SUMO_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/SUMO_rlc/Makefile new file mode 100644 index 00000000000..4864b1f74b1 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/SUMO_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_SUMO_rlc +IMG= SUMO_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/SUMO_uvd/Makefile b/sys/modules/drm2/radeonkmsfw/SUMO_uvd/Makefile new file mode 100644 index 00000000000..694b226b86c --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/SUMO_uvd/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_SUMO_uvd +IMG= SUMO_uvd + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TAHITI_ce/Makefile b/sys/modules/drm2/radeonkmsfw/TAHITI_ce/Makefile new file mode 100644 index 00000000000..8b757069668 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TAHITI_ce/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TAHITI_ce +IMG= TAHITI_ce + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TAHITI_mc/Makefile b/sys/modules/drm2/radeonkmsfw/TAHITI_mc/Makefile new file mode 100644 index 00000000000..af9227f15a0 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TAHITI_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TAHITI_mc +IMG= TAHITI_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TAHITI_me/Makefile b/sys/modules/drm2/radeonkmsfw/TAHITI_me/Makefile new file mode 100644 index 00000000000..b6da4a99db2 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TAHITI_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TAHITI_me +IMG= TAHITI_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TAHITI_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/TAHITI_pfp/Makefile new file mode 100644 index 00000000000..0c5322d191e --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TAHITI_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TAHITI_pfp +IMG= TAHITI_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TAHITI_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/TAHITI_rlc/Makefile new file mode 100644 index 00000000000..8af425f5df4 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TAHITI_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TAHITI_rlc +IMG= TAHITI_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TAHITI_uvd/Makefile b/sys/modules/drm2/radeonkmsfw/TAHITI_uvd/Makefile new file mode 100644 index 00000000000..89834bf16b1 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TAHITI_uvd/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TAHITI_uvd +IMG= TAHITI_uvd + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TURKS_mc/Makefile b/sys/modules/drm2/radeonkmsfw/TURKS_mc/Makefile new file mode 100644 index 00000000000..b317c78d864 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TURKS_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TURKS_mc +IMG= TURKS_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TURKS_me/Makefile b/sys/modules/drm2/radeonkmsfw/TURKS_me/Makefile new file mode 100644 index 00000000000..e7c616cc5a5 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TURKS_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TURKS_me +IMG= TURKS_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/TURKS_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/TURKS_pfp/Makefile new file mode 100644 index 00000000000..e42ce25f351 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/TURKS_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_TURKS_pfp +IMG= TURKS_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/VERDE_ce/Makefile b/sys/modules/drm2/radeonkmsfw/VERDE_ce/Makefile new file mode 100644 index 00000000000..d3b471f372a --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/VERDE_ce/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_VERDE_ce +IMG= VERDE_ce + +.include diff --git a/sys/modules/drm2/radeonkmsfw/VERDE_mc/Makefile b/sys/modules/drm2/radeonkmsfw/VERDE_mc/Makefile new file mode 100644 index 00000000000..0f1b57cb646 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/VERDE_mc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_VERDE_mc +IMG= VERDE_mc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/VERDE_me/Makefile b/sys/modules/drm2/radeonkmsfw/VERDE_me/Makefile new file mode 100644 index 00000000000..a039c19a082 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/VERDE_me/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_VERDE_me +IMG= VERDE_me + +.include diff --git a/sys/modules/drm2/radeonkmsfw/VERDE_pfp/Makefile b/sys/modules/drm2/radeonkmsfw/VERDE_pfp/Makefile new file mode 100644 index 00000000000..4e73c0c7708 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/VERDE_pfp/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_VERDE_pfp +IMG= VERDE_pfp + +.include diff --git a/sys/modules/drm2/radeonkmsfw/VERDE_rlc/Makefile b/sys/modules/drm2/radeonkmsfw/VERDE_rlc/Makefile new file mode 100644 index 00000000000..a2e882a8af1 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/VERDE_rlc/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +KMOD= radeonkmsfw_VERDE_rlc +IMG= VERDE_rlc + +.include diff --git a/sys/modules/drm2/radeonkmsfw/gen-makefiles b/sys/modules/drm2/radeonkmsfw/gen-makefiles new file mode 100755 index 00000000000..4c364a763b0 --- /dev/null +++ b/sys/modules/drm2/radeonkmsfw/gen-makefiles @@ -0,0 +1,30 @@ +#!/bin/sh +# $FreeBSD$ + +set -e + +scriptdir=$(cd $(dirname $0) && pwd) +fwdir=$scriptdir/../../../contrib/dev/drm2/radeonkmsfw + +for dir in $scriptdir/*; do + if [ ! -d $dir ]; then + continue + fi + rm -rf $dir +done + +for file in $fwdir/*.uu; do + img=$(basename $file) + img=${img%.bin.uu} + echo "Image: $img" + + mkdir -p $scriptdir/$img + cat > $scriptdir/$img/Makefile < +EOF +done diff --git a/tools/tools/drm/README b/tools/tools/drm/README index 1bb25ad4fd4..35660ed0827 100644 --- a/tools/tools/drm/README +++ b/tools/tools/drm/README @@ -2,3 +2,4 @@ gen-drm_pciids Generate drm_pciids.h based on Linux' drm_pciids.h, FreeBSD's drm_pciids.h and misc/pciids database. +radeon Tools specific to the Radeon device driver. diff --git a/tools/tools/drm/radeon/README b/tools/tools/drm/radeon/README new file mode 100644 index 00000000000..a05878ebb9e --- /dev/null +++ b/tools/tools/drm/radeon/README @@ -0,0 +1,4 @@ +# $FreeBSD$ + +firmwares Tools to handle Radeon firmwares imported into the tree. +mkregtable Generate headers used to build the Radeon driver. diff --git a/tools/tools/drm/radeon/firmwares/README b/tools/tools/drm/radeon/firmwares/README new file mode 100644 index 00000000000..1a28c83941d --- /dev/null +++ b/tools/tools/drm/radeon/firmwares/README @@ -0,0 +1,9 @@ +# $FreeBSD$ + +To update firmwares: + + 1. Clone the following Git repository: + git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git + + 2. Run this script as: + ./encode-firmwares /path/to/linux-firmwares/radeon diff --git a/tools/tools/drm/radeon/firmwares/encode-firmwares b/tools/tools/drm/radeon/firmwares/encode-firmwares new file mode 100755 index 00000000000..e95c0d2393f --- /dev/null +++ b/tools/tools/drm/radeon/firmwares/encode-firmwares @@ -0,0 +1,17 @@ +#!/bin/sh +# $FreeBSD$ + +set -e + +scriptdir=$(cd $(dirname $0) && pwd) +fwdir="$scriptdir/../../../../../sys/contrib/dev/drm2/radeonkmsfw" +srcdir=$1 + +if [ -z "$srcdir" -o ! -d "$srcdir" ]; then + echo "Syntax: $(basename $0) " 1>&2 + exit +fi + +for file in "$srcdir"/*.bin; do + uuencode -o "$fwdir"/$(basename $file).uu $file $(basename $file) +done diff --git a/tools/tools/drm/radeon/mkregtable/Makefile b/tools/tools/drm/radeon/mkregtable/Makefile new file mode 100644 index 00000000000..b83cf5ca774 --- /dev/null +++ b/tools/tools/drm/radeon/mkregtable/Makefile @@ -0,0 +1,58 @@ +# $FreeBSD$ + +all: regtables + +PROG= mkregtable + +SRCS= mkregtable.c + +NO_MAN= + +MKREGTABLE= ${PROG} +KERNSRCDIR= ${.CURDIR}/../../../../../sys +REG_SRCS_DIR= ${KERNSRCDIR}/dev/drm2/radeon/reg_srcs +REG_DEST_DIR= ${KERNSRCDIR}/dev/drm2/radeon + +regtables: \ + ${REG_DEST_DIR}/rn50_reg_safe.h \ + ${REG_DEST_DIR}/r100_reg_safe.h \ + ${REG_DEST_DIR}/r200_reg_safe.h \ + ${REG_DEST_DIR}/rv515_reg_safe.h \ + ${REG_DEST_DIR}/r300_reg_safe.h \ + ${REG_DEST_DIR}/r420_reg_safe.h \ + ${REG_DEST_DIR}/rs600_reg_safe.h \ + ${REG_DEST_DIR}/r600_reg_safe.h \ + ${REG_DEST_DIR}/evergreen_reg_safe.h \ + ${REG_DEST_DIR}/cayman_reg_safe.h + +${REG_DEST_DIR}/rn50_reg_safe.h: ${REG_SRCS_DIR}/rn50 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/rn50 > $@ + +${REG_DEST_DIR}/r100_reg_safe.h: ${REG_SRCS_DIR}/r100 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r100 > $@ + +${REG_DEST_DIR}/r200_reg_safe.h: ${REG_SRCS_DIR}/r200 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r200 > $@ + +${REG_DEST_DIR}/rv515_reg_safe.h: ${REG_SRCS_DIR}/rv515 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/rv515 > $@ + +${REG_DEST_DIR}/r300_reg_safe.h: ${REG_SRCS_DIR}/r300 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r300 > $@ + +${REG_DEST_DIR}/r420_reg_safe.h: ${REG_SRCS_DIR}/r420 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r420 > $@ + +${REG_DEST_DIR}/rs600_reg_safe.h: ${REG_SRCS_DIR}/rs600 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/rs600 > $@ + +${REG_DEST_DIR}/r600_reg_safe.h: ${REG_SRCS_DIR}/r600 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r600 > $@ + +${REG_DEST_DIR}/evergreen_reg_safe.h: ${REG_SRCS_DIR}/evergreen ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/evergreen > $@ + +${REG_DEST_DIR}/cayman_reg_safe.h: ${REG_SRCS_DIR}/cayman ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/cayman > $@ + +.include diff --git a/tools/tools/drm/radeon/mkregtable/README b/tools/tools/drm/radeon/mkregtable/README new file mode 100644 index 00000000000..12b86994b1b --- /dev/null +++ b/tools/tools/drm/radeon/mkregtable/README @@ -0,0 +1,7 @@ +# $FreeBSD$ + +"mkregtable" is a tool used to generate headers for the radeonkms +driver. Headers are regenerated by running "make" in this directory. + +Header source files are in sys/dev/drm2/radeon/reg_srcs. +Generated headers are placed in sys/dev/drm2/radeon. diff --git a/tools/tools/drm/radeon/mkregtable/mkregtable.c b/tools/tools/drm/radeon/mkregtable/mkregtable.c new file mode 100644 index 00000000000..51b8f909cd2 --- /dev/null +++ b/tools/tools/drm/radeon/mkregtable/mkregtable.c @@ -0,0 +1,733 @@ +/* utility to create the register check tables + * this includes inlined list.h safe for userspace. + * + * Copyright 2009 Jerome Glisse + * Copyright 2009 Red Hat Inc. + * + * Authors: + * Jerome Glisse + * Dave Airlie + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member)*__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +#ifndef CONFIG_DEBUG_LIST +static inline void __list_add(struct list_head *new, + struct list_head *prev, struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} +#else +extern void __list_add(struct list_head *new, + struct list_head *prev, struct list_head *next); +#endif + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +#ifndef CONFIG_DEBUG_LIST +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *)0xDEADBEEF; + entry->prev = (void *)0xBEEFDEAD; +} +#else +extern void list_del(struct list_head *entry); +#endif + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_cut_position(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + struct list_head *new_first = entry->next; + list->next = head->next; + list->next->prev = list; + list->prev = entry; + entry->next = list; + head->next = new_first; + new_first->prev = head; +} + +/** + * list_cut_position - cut a list into two + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * and if so we won't cut the list + * + * This helper moves the initial part of @head, up to and + * including @entry, from @head to @list. You should + * pass on @entry an element you know is on @head. @list + * should be an empty list or a list you do not care about + * losing its data. + * + */ +static inline void list_cut_position(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + if (list_empty(head)) + return; + if (list_is_singular(head) && (head->next != entry && head != entry)) + return; + if (entry == head) + INIT_LIST_HEAD(list); + else + __list_cut_position(list, head, entry); +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *prev, struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice - join two lists, this is designed for stacks + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; prefetch(pos->next), pos != (head); \ + pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + prefetch(pos->prev), pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + prefetch(pos->member.prev), &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + prefetch(pos->member.prev), &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +struct offset { + struct list_head list; + unsigned offset; +}; + +struct table { + struct list_head offsets; + unsigned offset_max; + unsigned nentry; + unsigned *table; + char *gpu_prefix; +}; + +static struct offset *offset_new(unsigned o) +{ + struct offset *offset; + + offset = (struct offset *)malloc(sizeof(struct offset)); + if (offset) { + INIT_LIST_HEAD(&offset->list); + offset->offset = o; + } + return offset; +} + +static void table_offset_add(struct table *t, struct offset *offset) +{ + list_add_tail(&offset->list, &t->offsets); +} + +static void table_init(struct table *t) +{ + INIT_LIST_HEAD(&t->offsets); + t->offset_max = 0; + t->nentry = 0; + t->table = NULL; +} + +static void table_print(struct table *t) +{ + unsigned nlloop, i, j, n, c, id; + + nlloop = (t->nentry + 3) / 4; + c = t->nentry; + printf( + "#include \n" + "__FBSDID(\"$" "FreeBSD" "$\");\n" + "\n" + ); + printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix, + t->nentry); + for (i = 0, id = 0; i < nlloop; i++) { + n = 4; + if (n > c) + n = c; + c -= n; + for (j = 0; j < n; j++) { + if (j == 0) + printf("\t"); + else + printf(" "); + printf("0x%08X,", t->table[id++]); + } + printf("\n"); + } + printf("};\n"); +} + +static int table_build(struct table *t) +{ + struct offset *offset; + unsigned i, m; + + t->nentry = ((t->offset_max >> 2) + 31) / 32; + t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry); + if (t->table == NULL) + return -1; + memset(t->table, 0xff, sizeof(unsigned) * t->nentry); + list_for_each_entry(offset, &t->offsets, list) { + i = (offset->offset >> 2) / 32; + m = (offset->offset >> 2) & 31; + m = 1 << m; + t->table[i] ^= m; + } + return 0; +} + +static char gpu_name[10]; +static int parser_auth(struct table *t, const char *filename) +{ + FILE *file; + regex_t mask_rex; + regmatch_t match[4]; + char buf[1024]; + size_t end; + int len; + int done = 0; + int r; + unsigned o; + struct offset *offset; + char last_reg_s[10]; + int last_reg; + + if (regcomp + (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) { + fprintf(stderr, "Failed to compile regular expression\n"); + return -1; + } + file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "Failed to open: %s\n", filename); + return -1; + } + fseek(file, 0, SEEK_END); + end = ftell(file); + fseek(file, 0, SEEK_SET); + + /* get header */ + if (fgets(buf, 1024, file) == NULL) { + fclose(file); + return -1; + } + + /* first line will contain the last register + * and gpu name */ + sscanf(buf, "%s %s", gpu_name, last_reg_s); + t->gpu_prefix = gpu_name; + last_reg = strtol(last_reg_s, NULL, 16); + + do { + if (fgets(buf, 1024, file) == NULL) { + fclose(file); + return -1; + } + len = strlen(buf); + if (ftell(file) == end) + done = 1; + if (len) { + r = regexec(&mask_rex, buf, 4, match, 0); + if (r == REG_NOMATCH) { + } else if (r) { + fprintf(stderr, + "Error matching regular expression %d in %s\n", + r, filename); + fclose(file); + return -1; + } else { + buf[match[0].rm_eo] = 0; + buf[match[1].rm_eo] = 0; + buf[match[2].rm_eo] = 0; + o = strtol(&buf[match[1].rm_so], NULL, 16); + offset = offset_new(o); + table_offset_add(t, offset); + if (o > t->offset_max) + t->offset_max = o; + } + } + } while (!done); + fclose(file); + if (t->offset_max < last_reg) + t->offset_max = last_reg; + return table_build(t); +} + +int main(int argc, char *argv[]) +{ + struct table t; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + table_init(&t); + if (parser_auth(&t, argv[1])) { + fprintf(stderr, "Failed to parse file %s\n", argv[1]); + return -1; + } + table_print(&t); + return 0; +}