video.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. video.c
  9. Abstract:
  10. This module fires up a basic frame buffer on the TI BeagleBone Black.
  11. Author:
  12. Evan Green 22-Dec-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <uefifw.h>
  20. #include <minoca/uefi/protocol/graphout.h>
  21. #include "bbonefw.h"
  22. #include <minoca/soc/am335x.h>
  23. //
  24. // --------------------------------------------------------------------- Macros
  25. //
  26. #define AM335_SOC_READ(_Register) \
  27. EfiReadRegister32((VOID *)(AM335_SOC_CONTROL_REGISTERS + (_Register)))
  28. #define AM335_SOC_WRITE(_Register, _Value) \
  29. EfiWriteRegister32((VOID *)(AM335_SOC_CONTROL_REGISTERS + (_Register)), \
  30. (_Value))
  31. #define AM335_LCD_READ(_Register) \
  32. EfiReadRegister32((VOID *)(AM335_LCD_REGISTERS + (_Register)))
  33. #define AM335_LCD_WRITE(_Register, _Value) \
  34. EfiWriteRegister32((VOID *)(AM335_LCD_REGISTERS + (_Register)), \
  35. (_Value))
  36. //
  37. // ---------------------------------------------------------------- Definitions
  38. //
  39. #define EFI_AM335_VIDEO_DEVICE_GUID \
  40. { \
  41. 0x19EEE1EB, 0x8F2A, 0x4DFA, \
  42. {0xB0, 0xF9, 0xB1, 0x0B, 0xD5, 0xB8, 0x71, 0x05} \
  43. }
  44. #define EFI_AM335_VIDEO_DEVICE_MAGIC 0x64695641 // 'diVA'
  45. //
  46. // Define the default mode to initialize in.
  47. //
  48. #define EFI_AM335_VIDEO_DEFAULT_MODE 1
  49. #define EFI_AM335_VIDEO_MODE_COUNT \
  50. (sizeof(EfiAm335VideoModes) / sizeof(EfiAm335VideoModes[0]))
  51. //
  52. // Define the frame buffer size, which should be large enough to support the
  53. // biggest resolution.
  54. //
  55. #define EFI_AM335_FRAME_BUFFER_SIZE \
  56. (AM335_PALETTE_SIZE + (1024 * 768 * sizeof(UINT16)))
  57. #define AM335_LCD_MODULE_CLOCK 192000000
  58. #define AM335_PALETTE_SIZE 0
  59. #define AM335_PALETTE_NONE 0x4000
  60. //
  61. // Define specific video parameters. This is calculated for standard VESA
  62. // 1024x768 60Hz display.
  63. //
  64. #if 1
  65. #define BEAGLE_BONE_BLACK_PIXEL_CLOCK 65000000
  66. #define BEAGLE_BONE_BLACK_RESOLUTION_X 1024
  67. #define BEAGLE_BONE_BLACK_HSYNC 136
  68. #define BEAGLE_BONE_BLACK_HORIZONTAL_FRONT_PORCH 24
  69. #define BEAGLE_BONE_BLACK_HORIZONTAL_BACK_PORCH 160
  70. #define BEAGLE_BONE_BLACK_RESOLUTION_Y 768
  71. #define BEAGLE_BONE_BLACK_VSYNC 6
  72. #define BEAGLE_BONE_BLACK_VERTICAL_FRONT_PORCH 3
  73. #define BEAGLE_BONE_BLACK_VERTICAL_BACK_PORCH 29
  74. #elif 0
  75. //
  76. // Other resolutions were fiddled with, not sure if they actually work though.
  77. //
  78. #define BEAGLE_BONE_BLACK_PIXEL_CLOCK 40000000
  79. #define BEAGLE_BONE_BLACK_RESOLUTION_X 800
  80. #define BEAGLE_BONE_BLACK_HSYNC 128
  81. #define BEAGLE_BONE_BLACK_HORIZONTAL_FRONT_PORCH 40
  82. #define BEAGLE_BONE_BLACK_HORIZONTAL_BACK_PORCH 88
  83. #define BEAGLE_BONE_BLACK_RESOLUTION_Y 600
  84. #define BEAGLE_BONE_BLACK_VSYNC 4
  85. #define BEAGLE_BONE_BLACK_VERTICAL_FRONT_PORCH 1
  86. #define BEAGLE_BONE_BLACK_VERTICAL_BACK_PORCH 23
  87. #else
  88. #define BEAGLE_BONE_BLACK_PIXEL_CLOCK 25175000
  89. #define BEAGLE_BONE_BLACK_RESOLUTION_X 640
  90. #define BEAGLE_BONE_BLACK_HSYNC 96
  91. #define BEAGLE_BONE_BLACK_HORIZONTAL_FRONT_PORCH 18
  92. #define BEAGLE_BONE_BLACK_HORIZONTAL_BACK_PORCH 48
  93. #define BEAGLE_BONE_BLACK_RESOLUTION_Y 480
  94. #define BEAGLE_BONE_BLACK_VSYNC 2
  95. #define BEAGLE_BONE_BLACK_VERTICAL_FRONT_PORCH 10
  96. #define BEAGLE_BONE_BLACK_VERTICAL_BACK_PORCH 33
  97. #endif
  98. //
  99. // TDA19988 definitions.
  100. //
  101. //
  102. // Define software flags for a TDA19988 video mode.
  103. //
  104. #define TDA19988_MODE_FLAG_NEGATE_HSYNC 0x00000001
  105. #define TDA19988_MODE_FLAG_NEGATE_VSYNC 0x00000002
  106. #define TDA19988_MODE_FLAG_INTERLACE 0x00000004
  107. #define TDA19988_MODE_FLAG_HORIZONTAL_SKEW 0x00000008
  108. #define TDA19988_CONTROL_RESET_DDC 0x03
  109. #define EFI_TDA19988_HDMI_BUS_ADDRESS 0x70
  110. #define EFI_TDA19988_CEC_BUS_ADDRESS 0x34
  111. #define TDA19988_CEC_FRO_IM_CLOCK_CONTROL 0xFB
  112. #define TDA19988_CEC_FRO_IM_CLOCK_CONTROL_VALUE 0x82
  113. #define TDA19988_CEC_STATUS 0xFE
  114. #define TDA19988_CEC_STATUS_RX_SENSE 0x01
  115. #define TDA19988_CEC_STATUS_HOT_PLUG_DETECT 0x02
  116. #define TDA19988_CEC_ENABLE 0xFF
  117. #define TDA19988_CEC_ENABLE_RX_SENSE 0x04
  118. #define TDA19988_CEC_ENABLE_HDMI 0x02
  119. #define TDA19988_CEC_ENABLE_ALL 0x87
  120. //
  121. // Define TDA19988 control pages.
  122. //
  123. #define TDA19988_CONTROL_PAGE 0x00
  124. #define TDA19988_PLL_PAGE 0x02
  125. #define TDA19988_EDID_PAGE 0x09
  126. #define TDA19988_INFORMATION_PAGE 0x10
  127. #define TDA19988_AUDIO_PAGE 0x11
  128. #define TDA19988_HDCP_OTP_PAGE 0x12
  129. #define TDA19988_GAMUT_PAGE 0x13
  130. //
  131. // The page select register exists in all pages.
  132. //
  133. #define TDA19988_PAGE_SELECT_REGISTER 0xFF
  134. //
  135. // Define TDA19988 control page registers.
  136. //
  137. #define TDA19988_CONTROL_REVISION_LOW 0x0000
  138. #define TDA19988_CONTROL_MAIN_CONTROL 0x0001
  139. #define TDA19988_CONTROL_REVISION_HIGH 0x0002
  140. #define TDA19988_CONTROL_RESET 0x000A
  141. #define TDA19988_CONTROL_DDC_CONTROL 0x000B
  142. #define TDA19988_CONTROL_DDC_CLOCK 0x000C
  143. #define TDA19988_CONTROL_INTERRUPT_CONTROL 0x000F
  144. #define TDA19988_CONTROL_INTERRUPT 0x0011
  145. #define TDA19988_CONTROL_ENABLE_VIDEO_0_PORT 0x0018
  146. #define TDA19988_CONTROL_ENABLE_VIDEO_1_PORT 0x0019
  147. #define TDA19988_CONTROL_ENABLE_VIDEO_2_PORT 0x001A
  148. #define TDA19988_CONTROL_ENABLE_AUDIO_PORT 0x001E
  149. #define TDA19988_CONTROL_VIP_CONTROL_0 0x0020
  150. #define TDA19988_CONTROL_VIP_CONTROL_1 0x0021
  151. #define TDA19988_CONTROL_VIP_CONTROL_2 0x0022
  152. #define TDA19988_CONTROL_VIP_CONTROL_3 0x0023
  153. #define TDA19988_CONTROL_VIP_CONTROL_4 0x0024
  154. #define TDA19988_CONTROL_VIP_CONTROL_5 0x0025
  155. #define TDA19988_CONTROL_VP_VIP_OUT 0x0027
  156. #define TDA19988_CONTROL_MATRIX_CONTROL 0x0080
  157. #define TDA19988_CONTROL_VIDEOFORMAT 0x00A0
  158. #define TDA19988_CONTROL_REFERENCE_PIXEL_HIGH 0x00A1
  159. #define TDA19988_CONTROL_REFERENCE_PIXEL_LOW 0x00A2
  160. #define TDA19988_CONTROL_REFERENCE_LINE_HIGH 0x00A3
  161. #define TDA19988_CONTROL_REFERENCE_LINE_LOW 0x00A4
  162. #define TDA19988_CONTROL_NPIXELS_HIGH 0x00A5
  163. #define TDA19988_CONTROL_NPIXELS_LOW 0x00A6
  164. #define TDA19988_CONTROL_NLINES_HIGH 0x00A7
  165. #define TDA19988_CONTROL_NLINES_LOW 0x00A8
  166. #define TDA19988_CONTROL_VS_LINE_START_1_HIGH 0x00A9
  167. #define TDA19988_CONTROL_VS_LINE_START_1_LOW 0x00AA
  168. #define TDA19988_CONTROL_VS_PIXEL_START_1_HIGH 0x00AB
  169. #define TDA19988_CONTROL_VS_PIXEL_START_1_LOW 0x00AC
  170. #define TDA19988_CONTROL_VS_LINE_END_1_HIGH 0x00AD
  171. #define TDA19988_CONTROL_VS_LINE_END_1_LOW 0x00AE
  172. #define TDA19988_CONTROL_VS_PIXEL_END_1_HIGH 0x00AF
  173. #define TDA19988_CONTROL_VS_PIXEL_END_1_LOW 0x00B0
  174. #define TDA19988_CONTROL_VS_LINE_START_2_HIGH 0x00B1
  175. #define TDA19988_CONTROL_VS_LINE_START_2_LOW 0x00B2
  176. #define TDA19988_CONTROL_VS_PIXEL_START_2_HIGH 0x00B3
  177. #define TDA19988_CONTROL_VS_PIXEL_START_2_LOW 0x00B4
  178. #define TDA19988_CONTROL_VS_LINE_END_2_HIGH 0x00B5
  179. #define TDA19988_CONTROL_VS_LINE_END_2_LOW 0x00B6
  180. #define TDA19988_CONTROL_VS_PIXEL_END_2_HIGH 0x00B7
  181. #define TDA19988_CONTROL_VS_PIXEL_END_2_LOW 0x00B8
  182. #define TDA19988_CONTROL_HS_PIXEL_START_HIGH 0x00B9
  183. #define TDA19988_CONTROL_HS_PIXEL_START_LOW 0x00BA
  184. #define TDA19988_CONTROL_HS_PIXEL_STOP_HIGH 0x00BB
  185. #define TDA19988_CONTROL_HS_PIXEL_STOP_LOW 0x00BC
  186. #define TDA19988_CONTROL_VWIN_START_1_HIGH 0x00BD
  187. #define TDA19988_CONTROL_VWIN_START_1_LOW 0x00BE
  188. #define TDA19988_CONTROL_VWIN_END_1_HIGH 0x00BF
  189. #define TDA19988_CONTROL_VWIN_END_1_LOW 0x00C0
  190. #define TDA19988_CONTROL_VWIN_START_2_HIGH 0x00C1
  191. #define TDA19988_CONTROL_VWIN_START_2_LOW 0x00C2
  192. #define TDA19988_CONTROL_VWIN_END_2_HIGH 0x00C3
  193. #define TDA19988_CONTROL_VWIN_END_2_LOW 0x00C4
  194. #define TDA19988_CONTROL_DE_START_HIGH 0x00C5
  195. #define TDA19988_CONTROL_DE_START_LOW 0x00C6
  196. #define TDA19988_CONTROL_DE_STOP_HIGH 0x00C7
  197. #define TDA19988_CONTROL_DE_STOP_LOW 0x00C8
  198. #define TDA19988_CONTROL_TBG_CONTROL_0 0x00CA
  199. #define TDA19988_CONTROL_TBG_CONTROL_1 0x00CB
  200. #define TDA19988_CONTROL_VSPACE_START_HIGH 0x00D2
  201. #define TDA19988_CONTROL_VSPACE_START_LOW 0x00D3
  202. #define TDA19988_CONTROL_VSPACE_END_HIGH 0x00D4
  203. #define TDA19988_CONTROL_VSPACE_END_LOW 0x00D5
  204. #define TDA19988_CONTROL_ENABLE_SPACE 0x00D6
  205. #define TDA19988_CONTROL_VSPACE_Y_DATA 0x00D7
  206. #define TDA19988_CONTROL_VSPACE_U_DATA 0x00D8
  207. #define TDA19988_CONTROL_VSPACE_V_DATA 0x00D9
  208. #define TDA19988_CONTROL_HVF_CONTROL_0 0x00E4
  209. #define TDA19988_CONTROL_HVF_CONTROL_1 0x00E5
  210. #define TDA19988_CONTROL_RPT_CONTROL 0x00F0
  211. #define TDA19988_CONTROL_MAIN_CONTROL_SOFT_RESET 0x01
  212. #define TDA19988_CONTROL_DDC_CONTROL_ENABLE 0x00
  213. #define TDA19988_CONTROL_DDC_CLOCK_ENABLE 0x01
  214. #define TDA19988_CONTROL_INTERRUPT_CONTROL_GLOBAL_ENABLE 0x04
  215. #define TDA19988_CONTROL_INTERRUPT_EDID 0x02
  216. #define TDA19988_CONTROL_ENABLE_ALL 0xFF
  217. #define TDA19988_CONTROL_VIP_CONTROL_0_SYNC_METHOD 0x40
  218. #define TDA19988_CONTROL_VIP_CONTROL_3_SYNC_HS (0x2 << 4)
  219. #define TDA19988_CONTROL_VIP_CONTROL_3_EMBEDDED_SYNC 0x08
  220. #define TDA19988_CONTROL_VIP_CONTROL_3_V_TOGGLE 0x04
  221. #define TDA19988_CONTROL_VIP_CONTROL_3_H_TOGGLE 0x02
  222. #define TDA19988_CONTROL_VIP_CONTROL_3_X_TOGGLE 0x01
  223. #define TDA19988_CONTROL_VIP_CONTROL_4_TEST_PATTERN 0x80
  224. #define TDA19988_CONTROL_VP_VIP_OUT_VALUE 0x24
  225. #define TDA19988_CONTROL_MATRIX_CONTROL_BYPASS 0x04
  226. #define TDA19988_CONTROL_TBG_CONTROL_0_SYNC_ONCE 0x80
  227. #define TDA19988_CONTROL_TBG_CONTROL_0_SYNC_METHOD 0x40
  228. #define TDA19988_CONTROL_TBG_CONTROL_1_DISABLE_DWIN 0x40
  229. #define TDA19988_CONTROL_TBG_CONTROL_1_TOGGLE_ENABLE 0x04
  230. #define TDA19988_CONTROL_TBG_CONTROL_1_V_TOGGLE 0x02
  231. #define TDA19988_CONTROL_TBG_CONTROL_1_H_TOGGLE 0x01
  232. #define TDA19988_CONTROL_ENABLE_SPACE_ENABLE 0x01
  233. #define TDA19988_CONTROL_HVF_CONTROL_0_SERVICE_MODE 0x80
  234. #define TDA19988_CONTROL_HVF_CONTROL_1_DEPTH_MASK 0x30
  235. #define TDA19988_CONTROL_HVF_CONTROL_1_DEPTH_COLOR_PC 0x10
  236. #define TDA19988_CONTROL_HVF_CONTROL_1_VQR_FULL (0x0 << 2)
  237. //
  238. // Define PLL register definitions.
  239. //
  240. #define TDA19988_PLL_SERIAL_1 0x0200
  241. #define TDA19988_PLL_SERIAL_2 0x0201
  242. #define TDA19988_PLL_SERIAL_3 0x0202
  243. #define TDA19988_PLL_SERIALIZER 0x0203
  244. #define TDA19988_PLL_BUFFER_OUT 0x0204
  245. #define TDA19988_PLL_SCG1 0x0205
  246. #define TDA19988_PLL_SCG2 0x0206
  247. #define TDA19988_PLL_SCGN1 0x0207
  248. #define TDA19988_PLL_SCGN2 0x0208
  249. #define TDA19988_PLL_SCGR1 0x0209
  250. #define TDA19988_PLL_SCGR2 0x020A
  251. #define TDA19988_PLL_AUDIO_DIVISOR 0x020E
  252. #define TDA19988_PLL_CLOCK_SELECT 0x0211
  253. #define TDA19988_PLL_ANALOG_CONTROL 0x0212
  254. #define TDA19988_PLL_SERIAL_1_SRL_MAN_IP 0x40
  255. #define TDA19988_PLL_SERIAL_2_SRL_NOSC(_Divisor) (((_Divisor) & 0x03) << 0)
  256. #define TDA19988_PLL_SERIAL_2_SRL_PR(_Value) (((_Value) & 0xF) << 4)
  257. #define TDA19988_PLL_SERIAL_3_SRL_CCIR 0x02
  258. #define TDA19988_PLL_SERIAL_3_DE 0x04
  259. #define TDA19988_PLL_BUFFER_OUT_SRL_FORCE_MASK 0x0C
  260. #define TDA19988_PLL_BUFFER_OUT_SRL_FORCE_0 0x08
  261. #define TDA19988_PLL_SCG2_VALUE 0x10
  262. #define TDA19988_PLL_SCGN1_VALUE 0xFA
  263. #define TDA19988_PLL_SCGR1_VALUE 0x5B
  264. #define TDA19988_PLL_AUDIO_DIVISOR_VALUE 0x03
  265. #define TDA19988_PLL_CLOCK_SELECT_VALUE 0x09
  266. #define TDA19988_PLL_ANALOG_TX_VSWING_VALUE 0x09
  267. //
  268. // Define EDID page registers.
  269. //
  270. #define TDA19988_EDID_DATA 0x0900
  271. #define TDA19988_EDID_REQUEST 0x09FA
  272. #define TDA19988_EDID_DEVICE_ADDRESS 0x09FB
  273. #define TDA19988_EDID_OFFSET 0x09FC
  274. #define TDA19988_EDID_SEGMENT_POINTER_ADDRESS 0x09FD
  275. #define TDA19988_EDID_SEGMENT_ADDRESS 0x09FE
  276. #define TDA19988_EDID_REQUEST_READ 0x01
  277. #define TDA19988_EDID_DEVICE_ADDRESS_EDID 0xA0
  278. #define TDA19988_EDID_OFFSET_VALUE 0x00
  279. #define TDA19988_EDID_SEGMENT_POINTER_ADDRESS_VALUE 0x00
  280. #define TDA19988_EDID_SEGMENT_ADDRESS_VALUE 0x00
  281. //
  282. // Define TDA19988 audio control registers.
  283. //
  284. #define TDA19988_AUDIO_AIP_CONTROL 0x1100
  285. #define TDA19988_AUDIO_ENCODE_CONTROL 0x110D
  286. #define TDA19988_AUDIO_IF_FLAGS 0x110F
  287. #define TDA19988_AUDIO_AIP_CONTROL_RESET_FIFO 0x01
  288. #define TDA19988_HDMI_REVISION_VALUE 0x0331
  289. //
  290. // Define TDA19988 HDCP/OTP page registers.
  291. //
  292. #define TDA19988_HDCP_OTP_TX3 0x129A
  293. #define TDA19988_HDCP_OTP_TX4 0x129B
  294. #define TDA19988_HDCP_OTP_TX33 0x12B8
  295. #define TDA19988_HDCP_OTP_TX3_VALUE 0x27
  296. #define TDA19988_HDCP_OTP_TX33_HDMI 0x02
  297. #define TDA19988_HDCP_OTP_TX4_PD_RAM 0x02
  298. //
  299. // ------------------------------------------------------ Data Type Definitions
  300. //
  301. /*++
  302. Structure Description:
  303. This structure stores the AM335x graphics output mode information.
  304. Members:
  305. Information - Stores the information structure.
  306. --*/
  307. typedef struct _EFI_AM335_VIDEO_MODE {
  308. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Information;
  309. } EFI_AM335_VIDEO_MODE, *PEFI_AM335_VIDEO_MODE;
  310. /*++
  311. Structure Description:
  312. This structure stores the structure of an AM335x video device path.
  313. Members:
  314. VendorPath - Stores the vendor path portion of the device path.
  315. End - Stores the end device path node.
  316. --*/
  317. typedef struct _EFI_AM335_VIDEO_DEVICE_PATH {
  318. VENDOR_DEVICE_PATH VendorPath;
  319. EFI_DEVICE_PATH_PROTOCOL End;
  320. } EFI_AM335_VIDEO_DEVICE_PATH, *PEFI_AM335_VIDEO_DEVICE_PATH;
  321. /*++
  322. Structure Description:
  323. This structure stores the internal context for an AM335x video device.
  324. Members:
  325. Magic - Stores the constant magic value EFI_OMAP4_VIDEO_DEVICE_MAGIC.
  326. Handle - Stores the graphics out handle.
  327. GraphicsOut - Stores the graphics output protocol.
  328. GraphicsOutMode - Stores the graphics output protocol mode.
  329. --*/
  330. typedef struct _EFI_AM335_VIDEO_DEVICE {
  331. UINT32 Magic;
  332. EFI_HANDLE Handle;
  333. EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOut;
  334. EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutMode;
  335. } EFI_AM335_VIDEO_DEVICE, *PEFI_AM335_VIDEO_DEVICE;
  336. typedef struct _EFI_TDA19988_MODE {
  337. UINT32 Clock;
  338. UINT32 HorizontalDisplay;
  339. UINT32 HorizontalSyncStart;
  340. UINT32 HorizontalSyncEnd;
  341. UINT32 HorizontalTotal;
  342. UINT32 HorizontalSkew;
  343. UINT32 VerticalDisplay;
  344. UINT32 VerticalSyncStart;
  345. UINT32 VerticalSyncEnd;
  346. UINT32 VerticalTotal;
  347. UINT32 VerticalScan;
  348. UINT32 Flags;
  349. } EFI_TDA19988_MODE, *PEFI_TDA19988_MODE;
  350. //
  351. // ----------------------------------------------- Internal Function Prototypes
  352. //
  353. EFIAPI
  354. EFI_STATUS
  355. EfipAm335GraphicsQueryMode (
  356. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  357. UINT32 ModeNumber,
  358. UINTN *SizeOfInfo,
  359. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  360. );
  361. EFIAPI
  362. EFI_STATUS
  363. EfipAm335GraphicsSetMode (
  364. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  365. UINT32 ModeNumber
  366. );
  367. EFIAPI
  368. EFI_STATUS
  369. EfipAm335GraphicsBlt (
  370. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  371. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  372. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  373. UINTN SourceX,
  374. UINTN SourceY,
  375. UINTN DestinationX,
  376. UINTN DestinationY,
  377. UINTN Width,
  378. UINTN Height,
  379. UINTN Delta
  380. );
  381. VOID
  382. EfipBeagleBoneBlackInitializeVideo (
  383. UINTN FrameBufferBase
  384. );
  385. VOID
  386. EfipBeagleBoneBlackSetVideoPinMuxing (
  387. VOID
  388. );
  389. VOID
  390. EfipTda19988Initialize (
  391. VOID
  392. );
  393. BOOLEAN
  394. EfipTda19988IsDisplayConnected (
  395. VOID
  396. );
  397. EFI_STATUS
  398. EfipTda19988HdmiInitialize (
  399. VOID
  400. );
  401. VOID
  402. EfipTda19988InitializeEncoder (
  403. PEFI_TDA19988_MODE Mode
  404. );
  405. EFI_STATUS
  406. EfipTda19988ReadEdid (
  407. UINT8 *Buffer,
  408. UINTN Size
  409. );
  410. VOID
  411. EfipTda19988Set (
  412. UINT16 Register,
  413. UINT8 Bits
  414. );
  415. VOID
  416. EfipTda19988Clear (
  417. UINT16 Register,
  418. UINT8 Bits
  419. );
  420. VOID
  421. EfipTda19988Read (
  422. UINT16 Register,
  423. UINT8 *Data
  424. );
  425. VOID
  426. EfipTda19988Write (
  427. UINT16 Register,
  428. UINT8 Data
  429. );
  430. VOID
  431. EfipTda19988Write2 (
  432. UINT16 Register,
  433. UINT16 Data
  434. );
  435. VOID
  436. EfipTda19988ReadMultiple (
  437. UINT16 Register,
  438. UINT8 Size,
  439. UINT8 *Data
  440. );
  441. VOID
  442. EfipTda19988SetPage (
  443. UINT8 PageNumber
  444. );
  445. //
  446. // -------------------------------------------------------------------- Globals
  447. //
  448. //
  449. // Store the device path of the video controller.
  450. //
  451. EFI_AM335_VIDEO_DEVICE_PATH EfiAm335VideoDevicePathTemplate = {
  452. {
  453. {
  454. HARDWARE_DEVICE_PATH,
  455. HW_VENDOR_DP,
  456. sizeof(VENDOR_DEVICE_PATH)
  457. },
  458. EFI_AM335_VIDEO_DEVICE_GUID,
  459. },
  460. {
  461. END_DEVICE_PATH_TYPE,
  462. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  463. END_DEVICE_PATH_LENGTH
  464. }
  465. };
  466. //
  467. // Define the supported video modes.
  468. //
  469. EFI_AM335_VIDEO_MODE EfiAm335VideoModes[] = {
  470. {
  471. {
  472. 0,
  473. 640,
  474. 480,
  475. PixelBitMask,
  476. {
  477. 0x0000001F,
  478. 0x000007E0,
  479. 0x0000F800,
  480. 0x00000000
  481. },
  482. 640
  483. },
  484. },
  485. {
  486. {
  487. 0,
  488. 1024,
  489. 768,
  490. PixelBitMask,
  491. {
  492. 0x0000001F,
  493. 0x000007E0,
  494. 0x0000F800,
  495. 0x00000000
  496. },
  497. 1024
  498. },
  499. },
  500. };
  501. EFI_TDA19988_MODE EfiTda19988Mode640x480 = {
  502. 25175,
  503. 640,
  504. 640 + 16,
  505. 640 + 16 + 96,
  506. 640 + 16 + 96 + 48,
  507. 96,
  508. 480,
  509. 480 + 10,
  510. 480 + 10 + 2,
  511. 480 + 10 + 2 + 33,
  512. 0,
  513. TDA19988_MODE_FLAG_NEGATE_HSYNC | TDA19988_MODE_FLAG_NEGATE_VSYNC |
  514. TDA19988_MODE_FLAG_HORIZONTAL_SKEW
  515. };
  516. EFI_TDA19988_MODE EfiTda19988Mode800x600 = {
  517. 40000,
  518. 800,
  519. 800 + 40,
  520. 800 + 40 + 128,
  521. 800 + 40 + 128 + 88,
  522. 0,
  523. 600,
  524. 600 + 1,
  525. 600 + 1 + 4,
  526. 600 + 1 + 4 + 22 - 1,
  527. 0,
  528. TDA19988_MODE_FLAG_HORIZONTAL_SKEW
  529. };
  530. EFI_TDA19988_MODE EfiTda19988Mode1024x768 = {
  531. 65000,
  532. 1024,
  533. 1024 + 24,
  534. 1024 + 24 + 136,
  535. 1024 + 24 + 136 + 160,
  536. 136,
  537. 768,
  538. 768 + 4,
  539. 768 + 4 + 6,
  540. 768 + 4 + 6 + 29 - 1,
  541. 0,
  542. TDA19988_MODE_FLAG_NEGATE_HSYNC | TDA19988_MODE_FLAG_NEGATE_VSYNC |
  543. TDA19988_MODE_FLAG_HORIZONTAL_SKEW
  544. };
  545. //
  546. // ------------------------------------------------------------------ Functions
  547. //
  548. EFI_STATUS
  549. EfipBeagleBoneBlackEnumerateVideo (
  550. VOID
  551. )
  552. /*++
  553. Routine Description:
  554. This routine enumerates the display on the BeagleBone Black.
  555. Arguments:
  556. None.
  557. Return Value:
  558. EFI status code.
  559. --*/
  560. {
  561. PEFI_AM335_VIDEO_DEVICE Device;
  562. EFI_PHYSICAL_ADDRESS FrameBufferBase;
  563. PEFI_AM335_VIDEO_MODE Mode;
  564. EFI_STATUS Status;
  565. FrameBufferBase = -1;
  566. Device = NULL;
  567. Mode = &(EfiAm335VideoModes[EFI_AM335_VIDEO_DEFAULT_MODE]);
  568. //
  569. // Allocate space for the frame buffer.
  570. //
  571. Status = EfiAllocatePages(AllocateAnyPages,
  572. EfiMemoryMappedIO,
  573. EFI_SIZE_TO_PAGES(EFI_AM335_FRAME_BUFFER_SIZE),
  574. &FrameBufferBase);
  575. if (EFI_ERROR(Status)) {
  576. return Status;
  577. }
  578. EfiSetMem((VOID *)(UINTN)FrameBufferBase, AM335_PALETTE_SIZE, 0);
  579. *((UINT16 *)(UINTN)FrameBufferBase) = AM335_PALETTE_NONE;
  580. //
  581. // Initialize the video to the default mode.
  582. //
  583. EfipTda19988Initialize();
  584. EfipBeagleBoneBlackInitializeVideo(FrameBufferBase);
  585. //
  586. // Everything's all set up, create the graphics output protocol.
  587. //
  588. Status = EfiAllocatePool(EfiBootServicesData,
  589. sizeof(EFI_AM335_VIDEO_DEVICE),
  590. (VOID **)&Device);
  591. if (EFI_ERROR(Status)) {
  592. goto EnumerateVideoEnd;
  593. }
  594. EfiSetMem(Device, sizeof(EFI_AM335_VIDEO_DEVICE), 0);
  595. Device->Magic = EFI_AM335_VIDEO_DEVICE_MAGIC;
  596. Device->GraphicsOut.QueryMode = EfipAm335GraphicsQueryMode;
  597. Device->GraphicsOut.SetMode = EfipAm335GraphicsSetMode;
  598. Device->GraphicsOut.Blt = EfipAm335GraphicsBlt;
  599. Device->GraphicsOut.Mode = &(Device->GraphicsOutMode);
  600. Device->GraphicsOutMode.MaxMode = EFI_AM335_VIDEO_MODE_COUNT;
  601. Device->GraphicsOutMode.Mode = EFI_AM335_VIDEO_DEFAULT_MODE;
  602. Device->GraphicsOutMode.Info = &(Mode->Information);
  603. Device->GraphicsOutMode.SizeOfInfo =
  604. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  605. Device->GraphicsOutMode.FrameBufferBase =
  606. FrameBufferBase + AM335_PALETTE_SIZE;
  607. Device->GraphicsOutMode.FrameBufferSize = EFI_AM335_FRAME_BUFFER_SIZE -
  608. AM335_PALETTE_SIZE;
  609. Status = EfiInstallMultipleProtocolInterfaces(
  610. &(Device->Handle),
  611. &EfiGraphicsOutputProtocolGuid,
  612. &(Device->GraphicsOut),
  613. &EfiDevicePathProtocolGuid,
  614. &EfiAm335VideoDevicePathTemplate,
  615. NULL);
  616. if (EFI_ERROR(Status)) {
  617. goto EnumerateVideoEnd;
  618. }
  619. EnumerateVideoEnd:
  620. if (EFI_ERROR(Status)) {
  621. if (FrameBufferBase != -1) {
  622. EfiFreePages(FrameBufferBase,
  623. EFI_SIZE_TO_PAGES(EFI_AM335_FRAME_BUFFER_SIZE));
  624. }
  625. if (Device != NULL) {
  626. EfiFreePool(Device);
  627. }
  628. }
  629. return Status;
  630. }
  631. //
  632. // --------------------------------------------------------- Internal Functions
  633. //
  634. EFIAPI
  635. EFI_STATUS
  636. EfipAm335GraphicsQueryMode (
  637. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  638. UINT32 ModeNumber,
  639. UINTN *SizeOfInfo,
  640. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  641. )
  642. /*++
  643. Routine Description:
  644. This routine returns information about available graphics modes that the
  645. graphics device and set of active video output devices support.
  646. Arguments:
  647. This - Supplies a pointer to the protocol instance.
  648. ModeNumber - Supplies the mode number to return information about.
  649. SizeOfInfo - Supplies a pointer that on input contains the size in bytes of
  650. the information buffer.
  651. Info - Supplies a pointer where a callee-allocated buffer will be returned
  652. containing information about the mode. The caller is responsible for
  653. calling FreePool to free this data.
  654. Return Value:
  655. EFI_SUCCESS on success.
  656. EFI_DEVICE_ERROR if a hardware error occurred trying to retrieve the video
  657. mode.
  658. EFI_INVALID_PARAMETER if the mode number is not valid.
  659. --*/
  660. {
  661. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information;
  662. EFI_STATUS Status;
  663. if ((ModeNumber >= EFI_AM335_VIDEO_MODE_COUNT) || (SizeOfInfo == NULL)) {
  664. return EFI_INVALID_PARAMETER;
  665. }
  666. Status = EfiAllocatePool(EfiBootServicesData,
  667. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
  668. (VOID **)&Information);
  669. if (EFI_ERROR(Status)) {
  670. return Status;
  671. }
  672. EfiCopyMem(Information,
  673. &(EfiAm335VideoModes[ModeNumber].Information),
  674. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
  675. *Info = Information;
  676. *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  677. return EFI_SUCCESS;
  678. }
  679. EFIAPI
  680. EFI_STATUS
  681. EfipAm335GraphicsSetMode (
  682. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  683. UINT32 ModeNumber
  684. )
  685. /*++
  686. Routine Description:
  687. This routine sets the video device into the specified mode and clears the
  688. visible portions of the output display to black.
  689. Arguments:
  690. This - Supplies a pointer to the protocol instance.
  691. ModeNumber - Supplies the mode number to set.
  692. Return Value:
  693. EFI_SUCCESS on success.
  694. EFI_DEVICE_ERROR if a hardware error occurred trying to set the video mode.
  695. EFI_UNSUPPORTED if the mode number is not supported by this device.
  696. --*/
  697. {
  698. PEFI_AM335_VIDEO_MODE Mode;
  699. if (ModeNumber >= EFI_AM335_VIDEO_MODE_COUNT) {
  700. return EFI_UNSUPPORTED;
  701. }
  702. Mode = &(EfiAm335VideoModes[ModeNumber]);
  703. EfipBeagleBoneBlackInitializeVideo(This->Mode->FrameBufferBase);
  704. This->Mode->Info = &(Mode->Information);
  705. This->Mode->Mode = ModeNumber;
  706. This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  707. return EFI_SUCCESS;
  708. }
  709. EFIAPI
  710. EFI_STATUS
  711. EfipAm335GraphicsBlt (
  712. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  713. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  714. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  715. UINTN SourceX,
  716. UINTN SourceY,
  717. UINTN DestinationX,
  718. UINTN DestinationY,
  719. UINTN Width,
  720. UINTN Height,
  721. UINTN Delta
  722. )
  723. /*++
  724. Routine Description:
  725. This routine performs a Blt (copy) operation of pixels on the graphics
  726. screen. Blt stands for Block Transfer for those not up on their video lingo.
  727. Arguments:
  728. This - Supplies a pointer to the protocol instance.
  729. BltBuffer - Supplies an optional pointer to the data to transfer to the
  730. graphics screen. The size must be at least width * height *
  731. sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
  732. BltOperation - Supplies the operation to perform when copying the buffer to
  733. the screen.
  734. SourceX - Supplies the X coordinate of the source of the operation.
  735. SourceY - Supplies the Y coordinate of the source of the operation.
  736. DestinationX - Supplies the X coordinate of the destination of the
  737. operation.
  738. DestinationY - Supplies the Y coordinate of the destination of the
  739. operation.
  740. Width - Supplies the width of the rectangle in pixels.
  741. Height - Supplies the height of the rectangle in pixels.
  742. Delta - Supplies an optional number of bytes in a row of the given buffer.
  743. If a delta of zero is used, the entire buffer is being operated on.
  744. This is not used for EfiBltVideoFill or EfiBltVideoToVideo operations.
  745. Return Value:
  746. EFI_SUCCESS on success.
  747. EFI_INVALID_PARAMETER if the operation was not valid.
  748. EFI_DEVICE_ERROR if a hardware error occurred and the request could not be
  749. completed.
  750. --*/
  751. {
  752. return EFI_UNSUPPORTED;
  753. }
  754. VOID
  755. EfipBeagleBoneBlackInitializeVideo (
  756. UINTN FrameBufferBase
  757. )
  758. /*++
  759. Routine Description:
  760. This routine initializes a basic frame buffer for the TI AM335x BeagleBone
  761. Black.
  762. Arguments:
  763. FrameBufferBase - Supplies the base of the frame buffer memory to use.
  764. Return Value:
  765. None.
  766. --*/
  767. {
  768. UINT32 Divisor;
  769. UINT32 HorizontalBackPorch;
  770. UINT32 HorizontalFrontPorch;
  771. UINT32 HorizontalPixels;
  772. UINT32 HorizontalSync;
  773. UINT32 Timing0;
  774. UINT32 Timing1;
  775. UINT32 Timing2;
  776. UINT32 Value;
  777. UINT32 VerticalBackPorch;
  778. UINT32 VerticalFrontPorch;
  779. UINT32 VerticalLines;
  780. UINT32 VerticalSync;
  781. EfipBeagleBoneBlackSetVideoPinMuxing();
  782. //
  783. // Enable the clocks for the DMA submodule, LIDD submodule, and for the
  784. // core (including raster active and passive). Disable raster control.
  785. //
  786. Value = AM335_LCD_CLOCK_ENABLE_CORE |
  787. AM335_LCD_CLOCK_ENABLE_DMA |
  788. AM335_LCD_CLOCK_ENABLE_LIDD;
  789. AM335_LCD_WRITE(AM335_LCD_CLOCK_ENABLE, Value);
  790. Value = AM335_LCD_READ(AM335_LCD_RASTER_CONTROL);
  791. Value &= ~AM335_LCD_RASTER_CONTROL_ENABLE;
  792. AM335_LCD_WRITE(AM335_LCD_RASTER_CONTROL, Value);
  793. //
  794. // Configure the divisor for the pixel clock. The divisor must be less than
  795. // 255.
  796. //
  797. Value = AM335_LCD_CONTROL_RASTER_MODE;
  798. AM335_LCD_WRITE(AM335_LCD_CONTROL, Value);
  799. for (Divisor = 2; Divisor < 255; Divisor += 1) {
  800. if (AM335_LCD_MODULE_CLOCK / Divisor <= BEAGLE_BONE_BLACK_PIXEL_CLOCK) {
  801. break;
  802. }
  803. }
  804. Value = AM335_LCD_CONTROL_RASTER_MODE |
  805. (Divisor << AM335_LCD_CONTROL_DIVISOR_SHIFT);
  806. AM335_LCD_WRITE(AM335_LCD_CONTROL, Value);
  807. //
  808. // Configure DMA properties of the controller.
  809. //
  810. Value = AM335_LCD_DMA_BURST_SIZE_16 | AM335_LCD_DMA_FIFO_THRESHOLD_8;
  811. AM335_LCD_WRITE(AM335_LCD_DMA_CONTROL, Value);
  812. //
  813. // Configure the LCD mode.
  814. //
  815. Value = AM335_LCD_RASTER_CONTROL_TFT;
  816. AM335_LCD_WRITE(AM335_LCD_RASTER_CONTROL, Value);
  817. //
  818. // Configure the LCD timing.
  819. //
  820. HorizontalBackPorch = BEAGLE_BONE_BLACK_HORIZONTAL_BACK_PORCH - 1;
  821. HorizontalFrontPorch = BEAGLE_BONE_BLACK_HORIZONTAL_FRONT_PORCH - 1;
  822. HorizontalPixels = BEAGLE_BONE_BLACK_RESOLUTION_X - 1;
  823. HorizontalSync = BEAGLE_BONE_BLACK_HSYNC - 1;
  824. VerticalBackPorch = BEAGLE_BONE_BLACK_VERTICAL_BACK_PORCH - 1;
  825. VerticalFrontPorch = BEAGLE_BONE_BLACK_VERTICAL_FRONT_PORCH - 1;
  826. VerticalLines = BEAGLE_BONE_BLACK_RESOLUTION_Y - 1;
  827. VerticalSync = BEAGLE_BONE_BLACK_VSYNC - 1;
  828. Timing2 = 0;
  829. Timing0 = Value = AM335_LCD_RESOLUTION_X_TO_TIMING_0(HorizontalPixels);
  830. Timing0 |= (HorizontalBackPorch &
  831. AM335_LCD_RASTER_TIMING_PORCH_LOW_MASK) <<
  832. AM335_LCD_RASTER_TIMING_0_HORIZONTAL_BACK_PORCH_SHIFT;
  833. Timing0 |= (HorizontalFrontPorch &
  834. AM335_LCD_RASTER_TIMING_PORCH_LOW_MASK) <<
  835. AM335_LCD_RASTER_TIMING_0_HORIZONTAL_FRONT_PORCH_SHIFT;
  836. Timing0 |= (HorizontalSync & AM335_LCD_RASTER_TIMING_0_HSYNC_MASK) <<
  837. AM335_LCD_RASTER_TIMING_0_HSYNC_SHIFT;
  838. Timing1 = AM335_LCD_RESOLUTION_Y_TO_TIMING_1(VerticalLines);
  839. Timing1 |= (VerticalBackPorch &
  840. AM335_LCD_RASTER_TIMING_PORCH_LOW_MASK) <<
  841. AM335_LCD_RASTER_TIMING_1_VERTICAL_BACK_PORCH_SHIFT;
  842. Timing1 |= (VerticalFrontPorch &
  843. AM335_LCD_RASTER_TIMING_PORCH_LOW_MASK) <<
  844. AM335_LCD_RASTER_TIMING_1_VERTICAL_FRONT_PORCH_SHIFT;
  845. Timing1 |= (VerticalSync & AM335_LCD_RASTER_TIMING_PORCH_LOW_MASK) <<
  846. AM335_LCD_RASTER_TIMING_1_VSYNC_SHIFT;
  847. Timing2 = AM335_LCD_RESOLUTION_Y_TO_TIMING_2(VerticalLines);
  848. Timing2 |= AM335_LCD_RASTER_TIMING_2_INVERT_VERTICAL_SYNC;
  849. Timing2 |= 255 << AM335_LCD_RASTER_TIMING_2_AC_BIAS_FREQUENCY_SHIFT;
  850. HorizontalFrontPorch >>= AM335_LCD_RASTER_TIMING_PORCH_HIGH_SHIFT;
  851. HorizontalBackPorch >>= AM335_LCD_RASTER_TIMING_PORCH_HIGH_SHIFT;
  852. HorizontalSync >>= AM335_LCD_RASTER_TIMING_HSYNC_HIGH_SHIFT;
  853. Timing2 |= (HorizontalBackPorch &
  854. AM335_LCD_RASTER_TIMING_PORCH_HIGH_MASK) <<
  855. AM335_LCD_RASTER_TIMING_2_HORIZONTAL_BACK_PORCH_HIGH_SHIFT;
  856. Timing2 |= (HorizontalFrontPorch &
  857. AM335_LCD_RASTER_TIMING_PORCH_HIGH_MASK) <<
  858. AM335_LCD_RASTER_TIMING_2_HORIZONTAL_FRONT_PORCH_HIGH_SHIFT;
  859. Timing2 |= (HorizontalSync & AM335_LCD_RASTER_TIMING_HSYNC_HIGH_MASK) <<
  860. AM335_LCD_RASTER_TIMING_2_HORIZONTAL_SYNC_HIGH_SHIFT;
  861. AM335_LCD_WRITE(AM335_LCD_RASTER_TIMING_0, Timing0);
  862. AM335_LCD_WRITE(AM335_LCD_RASTER_TIMING_1, Timing1);
  863. AM335_LCD_WRITE(AM335_LCD_RASTER_TIMING_2, Timing2);
  864. //
  865. // Configure the palette load delay.
  866. //
  867. Value = AM335_LCD_READ(AM335_LCD_RASTER_CONTROL);
  868. Value &= ~AM335_LCD_RASTER_CONTROL_FIFO_DMA_DELAY_MASK;
  869. Value |= 128 << AM335_LCD_RASTER_CONTROL_FIFO_DMA_DELAY_SHIFT;
  870. Value &= ~AM335_LCD_RASTER_CONTROL_PALETTE_LOAD_MASK;
  871. Value |= AM335_LCD_RASTER_CONTROL_PALETTE_LOAD_DATA_ONLY;
  872. AM335_LCD_WRITE(AM335_LCD_RASTER_CONTROL, Value);
  873. //
  874. // Set up the frame buffer base.
  875. //
  876. Value = FrameBufferBase;
  877. AM335_LCD_WRITE(AM335_LCD_FB0_BASE, Value);
  878. Value += EFI_AM335_FRAME_BUFFER_SIZE - 1;
  879. AM335_LCD_WRITE(AM335_LCD_FB0_CEILING, Value);
  880. //
  881. // Reset the LCD module.
  882. //
  883. Value = AM335_LCD_CLOCK_RESET_MAIN;
  884. AM335_LCD_WRITE(AM335_LCD_CLOCK_RESET, Value);
  885. EfiStall(100000);
  886. AM335_LCD_WRITE(AM335_LCD_CLOCK_RESET, 0);
  887. //
  888. // Enable output.
  889. //
  890. Value = AM335_LCD_READ(AM335_LCD_RASTER_CONTROL);
  891. Value |= AM335_LCD_RASTER_CONTROL_ENABLE;
  892. AM335_LCD_WRITE(AM335_LCD_RASTER_CONTROL, Value);
  893. Value = AM335_LCD_SYSTEM_CONFIG_STANDBY_SMART |
  894. AM335_LCD_SYSTEM_CONFIG_IDLE_SMART;
  895. AM335_LCD_WRITE(AM335_LCD_SYSTEM_CONFIG, Value);
  896. return;
  897. }
  898. VOID
  899. EfipBeagleBoneBlackSetVideoPinMuxing (
  900. VOID
  901. )
  902. /*++
  903. Routine Description:
  904. This routine sets up the proper pin muxing for the LCD on a BeagleBone
  905. Black.
  906. Arguments:
  907. None.
  908. Return Value:
  909. None.
  910. --*/
  911. {
  912. UINT32 Value;
  913. //
  914. // The first 16 data pins are mux mode 0.
  915. //
  916. Value = 0;
  917. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(0), Value);
  918. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(1), Value);
  919. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(2), Value);
  920. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(3), Value);
  921. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(4), Value);
  922. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(5), Value);
  923. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(6), Value);
  924. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(7), Value);
  925. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(8), Value);
  926. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(9), Value);
  927. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(10), Value);
  928. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(11), Value);
  929. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(12), Value);
  930. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(13), Value);
  931. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(14), Value);
  932. AM335_SOC_WRITE(AM335_PAD_LCD_DATA(15), Value);
  933. //
  934. // The other control signals are mux mode 0.
  935. //
  936. Value = 0;
  937. AM335_SOC_WRITE(AM335_SOC_CONTROL_CONF_LCD_VSYNC, Value);
  938. AM335_SOC_WRITE(AM335_SOC_CONTROL_CONF_LCD_HSYNC, Value);
  939. AM335_SOC_WRITE(AM335_SOC_CONTROL_CONF_LCD_PCLK, Value);
  940. AM335_SOC_WRITE(AM335_SOC_CONTROL_CONF_LCD_AC_BIAS_EN, Value);
  941. //
  942. // Set ball A15 to output CLKOUT1.
  943. //
  944. AM335_SOC_WRITE(AM335_SOC_CONTROL_CONF_XDMA_EVENT_INTR0, 3);
  945. return;
  946. }
  947. VOID
  948. EfipTda19988Initialize (
  949. VOID
  950. )
  951. /*++
  952. Routine Description:
  953. This routine initializes the TDA19988 HDMI framer chip.
  954. Arguments:
  955. None.
  956. Return Value:
  957. None.
  958. --*/
  959. {
  960. BOOLEAN DisplayConnected;
  961. UINT8 EdidData[128];
  962. UINT32 Try;
  963. EfipAm335I2c0Initialize();
  964. EfipTda19988HdmiInitialize();
  965. for (Try = 0; Try < 20; Try += 1) {
  966. DisplayConnected = EfipTda19988IsDisplayConnected();
  967. if (DisplayConnected != FALSE) {
  968. break;
  969. }
  970. EfiStall(10000);
  971. }
  972. //
  973. // This code always sets the resolution to 1024x768, but the framework is
  974. // here to potentially support native resolutions.
  975. //
  976. if (DisplayConnected != FALSE) {
  977. EfiSetMem(EdidData, sizeof(EdidData), 0);
  978. EfipTda19988ReadEdid(EdidData, sizeof(EdidData));
  979. }
  980. EfipTda19988InitializeEncoder(&EfiTda19988Mode1024x768);
  981. //
  982. // Write default values for RBG 4:4:4.
  983. //
  984. EfipTda19988Write(TDA19988_CONTROL_VIP_CONTROL_0, 0x23);
  985. EfipTda19988Write(TDA19988_CONTROL_VIP_CONTROL_1, 0x45);
  986. EfipTda19988Write(TDA19988_CONTROL_VIP_CONTROL_2, 0x01);
  987. return;
  988. }
  989. BOOLEAN
  990. EfipTda19988IsDisplayConnected (
  991. VOID
  992. )
  993. /*++
  994. Routine Description:
  995. This routine determines if a display is connected.
  996. Arguments:
  997. None.
  998. Return Value:
  999. None.
  1000. --*/
  1001. {
  1002. UINT8 Value;
  1003. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_CEC_BUS_ADDRESS);
  1004. EfipAm335I2c0Read(TDA19988_CEC_STATUS, 1, &Value);
  1005. //
  1006. // Accept either the official hot-plug detect or the jankier RX sense, as
  1007. // a pre-connected monitor seems to sometimes never set HPD.
  1008. //
  1009. if ((Value &
  1010. (TDA19988_CEC_STATUS_HOT_PLUG_DETECT |
  1011. TDA19988_CEC_STATUS_RX_SENSE)) != 0) {
  1012. return TRUE;
  1013. }
  1014. return FALSE;
  1015. }
  1016. EFI_STATUS
  1017. EfipTda19988HdmiInitialize (
  1018. VOID
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. This routine initializes the TDA19988.
  1023. Arguments:
  1024. None.
  1025. Return Value:
  1026. None.
  1027. --*/
  1028. {
  1029. UINT32 Revision;
  1030. UINT8 Value;
  1031. //
  1032. // Enable the CEC module.
  1033. //
  1034. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_CEC_BUS_ADDRESS);
  1035. Value = TDA19988_CEC_ENABLE_RX_SENSE | TDA19988_CEC_ENABLE_HDMI;
  1036. EfipAm335I2c0Write(TDA19988_CEC_ENABLE, 1, &Value);
  1037. EfiStall(10000);
  1038. EfipAm335I2c0Read(TDA19988_CEC_STATUS, 1, &Value);
  1039. //
  1040. // Perform a soft reset on the DDC bus.
  1041. //
  1042. Value = TDA19988_CONTROL_RESET_DDC;
  1043. EfipTda19988Set(TDA19988_CONTROL_RESET, Value);
  1044. EfiStall(100000);
  1045. EfipTda19988Clear(TDA19988_CONTROL_RESET, Value);
  1046. EfiStall(100000);
  1047. Value = TDA19988_CONTROL_MAIN_CONTROL_SOFT_RESET;
  1048. EfipTda19988Set(TDA19988_CONTROL_MAIN_CONTROL, Value);
  1049. EfiStall(10000);
  1050. EfipTda19988Clear(TDA19988_CONTROL_MAIN_CONTROL, Value);
  1051. //
  1052. // Set the TMDS bias.
  1053. //
  1054. Value = TDA19988_PLL_ANALOG_TX_VSWING_VALUE;
  1055. EfipTda19988Write(TDA19988_PLL_ANALOG_CONTROL, Value);
  1056. //
  1057. // Set PLL registers.
  1058. //
  1059. EfipTda19988Write(TDA19988_PLL_SERIAL_1, 0);
  1060. Value = TDA19988_PLL_SERIAL_2_SRL_NOSC(1);
  1061. EfipTda19988Write(TDA19988_PLL_SERIAL_2, Value);
  1062. EfipTda19988Write(TDA19988_PLL_SERIAL_3, 0);
  1063. EfipTda19988Write(TDA19988_PLL_SERIALIZER, 0);
  1064. EfipTda19988Write(TDA19988_PLL_BUFFER_OUT, 0);
  1065. EfipTda19988Write(TDA19988_PLL_SCG1, 0);
  1066. Value = TDA19988_PLL_CLOCK_SELECT_VALUE;
  1067. EfipTda19988Write(TDA19988_PLL_CLOCK_SELECT, Value);
  1068. //
  1069. // Configure for video in format that is not 480i or 576i.
  1070. //
  1071. Value = TDA19988_PLL_SCGN1_VALUE;
  1072. EfipTda19988Write(TDA19988_PLL_SCGN1, Value);
  1073. Value = 0;
  1074. EfipTda19988Write(TDA19988_PLL_SCGN2, Value);
  1075. Value = TDA19988_PLL_SCGR1_VALUE;
  1076. EfipTda19988Write(TDA19988_PLL_SCGR1, Value);
  1077. Value = 0;
  1078. EfipTda19988Write(TDA19988_PLL_SCGR2, Value);
  1079. //
  1080. // Set single edge mode (for formats that are not 480i or 576i).
  1081. //
  1082. Value = TDA19988_PLL_SCG2_VALUE;
  1083. EfipTda19988Write(TDA19988_PLL_SCG2, Value);
  1084. Value = TDA19988_CONTROL_VP_VIP_OUT_VALUE;
  1085. EfipTda19988Write(TDA19988_CONTROL_VP_VIP_OUT, Value);
  1086. //
  1087. // Verify the TDA19988 chip revision.
  1088. //
  1089. EfipTda19988Read(TDA19988_CONTROL_REVISION_LOW, &Value);
  1090. Revision = Value;
  1091. EfipTda19988Read(TDA19988_CONTROL_REVISION_HIGH, &Value);
  1092. Revision |= ((UINT32)Value) << 8;
  1093. if (Revision != TDA19988_HDMI_REVISION_VALUE) {
  1094. return EFI_NOT_FOUND;
  1095. }
  1096. //
  1097. // Enable DDC.
  1098. //
  1099. Value = TDA19988_CONTROL_DDC_CONTROL_ENABLE;
  1100. EfipTda19988Write(TDA19988_CONTROL_DDC_CONTROL, Value);
  1101. //
  1102. // Set up the DDC clock.
  1103. //
  1104. Value = TDA19988_HDCP_OTP_TX3_VALUE;
  1105. EfipTda19988Write(TDA19988_HDCP_OTP_TX3, Value);
  1106. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_CEC_BUS_ADDRESS);
  1107. Value = TDA19988_CEC_FRO_IM_CLOCK_CONTROL_VALUE;
  1108. EfipAm335I2c0Write(TDA19988_CEC_FRO_IM_CLOCK_CONTROL, 1, &Value);
  1109. return EFI_SUCCESS;
  1110. }
  1111. VOID
  1112. EfipTda19988InitializeEncoder (
  1113. PEFI_TDA19988_MODE Mode
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. This routine sets the video parameters for the HDMI encoder of the TDA19988.
  1118. Arguments:
  1119. Mode - Supplies a pointer to the requested mode.
  1120. Return Value:
  1121. None.
  1122. --*/
  1123. {
  1124. UINT16 DeStart;
  1125. UINT16 DeStop;
  1126. UINT8 Divisor;
  1127. UINT16 HsPixelStart;
  1128. UINT16 HsPixelStop;
  1129. UINT16 NumberOfLines;
  1130. UINT16 NumberOfPixels;
  1131. UINT16 ReferenceLine;
  1132. UINT16 ReferencePixel;
  1133. UINT16 Value;
  1134. UINT16 Vs1LineEnd;
  1135. UINT16 Vs1LineStart;
  1136. UINT16 Vs1PixelEnd;
  1137. UINT16 Vs1PixelStart;
  1138. UINT16 Vs2LineEnd;
  1139. UINT16 Vs2LineStart;
  1140. UINT16 Vs2PixelEnd;
  1141. UINT16 Vs2PixelStart;
  1142. UINT16 Vwin1LineEnd;
  1143. UINT16 Vwin1LineStart;
  1144. UINT16 Vwin2LineEnd;
  1145. UINT16 Vwin2LineStart;
  1146. NumberOfPixels = Mode->HorizontalTotal;
  1147. NumberOfLines = Mode->VerticalTotal;
  1148. HsPixelStop = Mode->HorizontalSyncEnd - Mode->HorizontalDisplay;
  1149. HsPixelStart = Mode->HorizontalSyncStart - Mode->HorizontalDisplay;
  1150. DeStop = Mode->HorizontalTotal;
  1151. DeStart = Mode->HorizontalTotal - Mode->HorizontalDisplay;
  1152. ReferencePixel = HsPixelStart + 3;
  1153. if ((Mode->Flags & TDA19988_MODE_FLAG_HORIZONTAL_SKEW) != 0) {
  1154. ReferencePixel += Mode->HorizontalSkew;
  1155. }
  1156. if ((Mode->Flags & TDA19988_MODE_FLAG_INTERLACE) != 0) {
  1157. ReferenceLine = ((Mode->VerticalSyncStart -
  1158. Mode->VerticalDisplay) / 2) + 1;
  1159. Vwin1LineStart = (Mode->VerticalTotal - Mode->VerticalDisplay) / 2;
  1160. Vwin1LineEnd = Vwin1LineStart + (Mode->VerticalDisplay / 2);
  1161. Vs1PixelStart = HsPixelStart;
  1162. Vs1PixelEnd = Vs1PixelStart;
  1163. Vs1LineStart = (Mode->VerticalSyncStart - Mode->VerticalDisplay) / 2;
  1164. Vs1LineEnd = Vs1LineStart +
  1165. ((Mode->VerticalSyncEnd - Mode->VerticalSyncStart) / 2);
  1166. Vwin2LineStart = Vwin1LineStart + (Mode->VerticalTotal / 2);
  1167. Vwin2LineEnd = Vwin2LineStart + (Mode->VerticalDisplay / 2);
  1168. Vs2PixelStart = HsPixelStart + (Mode->HorizontalTotal / 2);
  1169. Vs2PixelEnd = Vs1PixelStart;
  1170. Vs2LineStart = Vs1LineStart + (Mode->VerticalTotal / 2);
  1171. Vs2LineEnd = Vs2LineStart +
  1172. ((Mode->VerticalSyncEnd - Mode->VerticalSyncStart) / 2);
  1173. } else {
  1174. ReferenceLine = (Mode->VerticalSyncStart - Mode->VerticalDisplay) + 1;
  1175. Vwin1LineStart = Mode->VerticalTotal - Mode->VerticalDisplay - 1;
  1176. Vwin1LineEnd = Vwin1LineStart + Mode->VerticalDisplay;
  1177. Vs1PixelStart = HsPixelStart;
  1178. Vs1PixelEnd = Vs1PixelStart;
  1179. Vs1LineStart = Mode->VerticalSyncStart - Mode->VerticalDisplay;
  1180. Vs1LineEnd = Vs1LineStart +
  1181. Mode->VerticalSyncEnd - Mode->VerticalSyncStart;
  1182. Vwin2LineStart = 0;
  1183. Vwin2LineEnd = 0;
  1184. Vs2PixelStart = 0;
  1185. Vs2PixelEnd = 0;
  1186. Vs2LineStart = 0;
  1187. Vs2LineEnd = 0;
  1188. }
  1189. Divisor = 148500 / Mode->Clock;
  1190. if (Divisor != 0) {
  1191. Divisor -= 1;
  1192. if (Divisor > 3) {
  1193. Divisor = 3;
  1194. }
  1195. }
  1196. //
  1197. // Switch HDCP mode off for DVI.
  1198. //
  1199. Value = TDA19988_CONTROL_TBG_CONTROL_1_DISABLE_DWIN;
  1200. EfipTda19988Set(TDA19988_CONTROL_TBG_CONTROL_1, Value);
  1201. Value = TDA19988_HDCP_OTP_TX33_HDMI;
  1202. EfipTda19988Clear(TDA19988_HDCP_OTP_TX33, Value);
  1203. //
  1204. // Set the encoder to DVI mode.
  1205. //
  1206. Value = 0;
  1207. EfipTda19988Write(TDA19988_AUDIO_ENCODE_CONTROL, Value);
  1208. //
  1209. // Disable pre-filter and interpolator.
  1210. //
  1211. Value = 0;
  1212. EfipTda19988Write(TDA19988_CONTROL_HVF_CONTROL_0, Value);
  1213. EfipTda19988Write(TDA19988_CONTROL_VIP_CONTROL_5, Value);
  1214. EfipTda19988Write(TDA19988_CONTROL_VIP_CONTROL_4, Value);
  1215. Value = TDA19988_PLL_SERIAL_3_SRL_CCIR;
  1216. EfipTda19988Clear(TDA19988_PLL_SERIAL_3, Value);
  1217. Value = TDA19988_PLL_SERIAL_1_SRL_MAN_IP;
  1218. EfipTda19988Clear(TDA19988_PLL_SERIAL_1, Value);
  1219. Value = TDA19988_PLL_SERIAL_3_DE;
  1220. EfipTda19988Clear(TDA19988_PLL_SERIAL_3, Value);
  1221. Value = 0;
  1222. EfipTda19988Write(TDA19988_PLL_SERIALIZER, Value);
  1223. Value = TDA19988_CONTROL_HVF_CONTROL_1_VQR_FULL;
  1224. EfipTda19988Write(TDA19988_CONTROL_HVF_CONTROL_1, Value);
  1225. Value = 0;
  1226. EfipTda19988Write(TDA19988_CONTROL_RPT_CONTROL, Value);
  1227. Value = TDA19988_PLL_CLOCK_SELECT_VALUE;
  1228. EfipTda19988Write(TDA19988_PLL_CLOCK_SELECT, Value);
  1229. Value = TDA19988_PLL_SERIAL_2_SRL_NOSC(Divisor) |
  1230. TDA19988_PLL_SERIAL_2_SRL_PR(0);
  1231. EfipTda19988Write(TDA19988_PLL_SERIAL_2, Value);
  1232. //
  1233. // Set video input/output parameters. Set the matrix conversion to bypass
  1234. // the matrix.
  1235. //
  1236. Value = TDA19988_CONTROL_MATRIX_CONTROL_BYPASS;
  1237. EfipTda19988Set(TDA19988_CONTROL_MATRIX_CONTROL, Value);
  1238. Value = TDA19988_CONTROL_TBG_CONTROL_0_SYNC_METHOD;
  1239. EfipTda19988Clear(TDA19988_CONTROL_TBG_CONTROL_0, Value);
  1240. //
  1241. // Set the TMDS bias.
  1242. //
  1243. Value = TDA19988_PLL_ANALOG_TX_VSWING_VALUE;
  1244. EfipTda19988Write(TDA19988_PLL_ANALOG_CONTROL, Value);
  1245. //
  1246. // Sync on risiding edge.
  1247. // Set embedded sync, and enable V, H, and X toggle.
  1248. //
  1249. Value = TDA19988_CONTROL_VIP_CONTROL_3_SYNC_HS;
  1250. if ((Mode->Flags & TDA19988_MODE_FLAG_NEGATE_HSYNC) != 0) {
  1251. Value |= TDA19988_CONTROL_VIP_CONTROL_3_H_TOGGLE;
  1252. }
  1253. if ((Mode->Flags & TDA19988_MODE_FLAG_NEGATE_VSYNC) != 0) {
  1254. Value |= TDA19988_CONTROL_VIP_CONTROL_3_V_TOGGLE;
  1255. }
  1256. EfipTda19988Write(TDA19988_CONTROL_VIP_CONTROL_3, Value);
  1257. Value = TDA19988_CONTROL_TBG_CONTROL_1_TOGGLE_ENABLE;
  1258. if ((Mode->Flags & TDA19988_MODE_FLAG_NEGATE_HSYNC) != 0) {
  1259. Value |= TDA19988_CONTROL_TBG_CONTROL_1_H_TOGGLE;
  1260. }
  1261. if ((Mode->Flags & TDA19988_MODE_FLAG_NEGATE_VSYNC) != 0) {
  1262. Value |= TDA19988_CONTROL_TBG_CONTROL_1_V_TOGGLE;
  1263. }
  1264. EfipTda19988Write(TDA19988_CONTROL_TBG_CONTROL_1, Value);
  1265. //
  1266. // Set video parameters.
  1267. //
  1268. Value = 0;
  1269. EfipTda19988Write(TDA19988_CONTROL_VIDEOFORMAT, Value);
  1270. EfipTda19988Write2(TDA19988_CONTROL_REFERENCE_PIXEL_HIGH, ReferencePixel);
  1271. EfipTda19988Write2(TDA19988_CONTROL_REFERENCE_LINE_HIGH, ReferenceLine);
  1272. EfipTda19988Write2(TDA19988_CONTROL_NPIXELS_HIGH, NumberOfPixels);
  1273. EfipTda19988Write2(TDA19988_CONTROL_NLINES_HIGH, NumberOfLines);
  1274. EfipTda19988Write2(TDA19988_CONTROL_VS_LINE_START_1_HIGH, Vs1LineStart);
  1275. EfipTda19988Write2(TDA19988_CONTROL_VS_PIXEL_START_1_HIGH, Vs1PixelStart);
  1276. EfipTda19988Write2(TDA19988_CONTROL_VS_LINE_END_1_HIGH, Vs1LineEnd);
  1277. EfipTda19988Write2(TDA19988_CONTROL_VS_PIXEL_END_1_HIGH, Vs1PixelEnd);
  1278. EfipTda19988Write2(TDA19988_CONTROL_VS_LINE_START_2_HIGH, Vs2LineStart);
  1279. EfipTda19988Write2(TDA19988_CONTROL_VS_PIXEL_START_2_HIGH, Vs2PixelStart);
  1280. EfipTda19988Write2(TDA19988_CONTROL_VS_LINE_END_2_HIGH, Vs2LineEnd);
  1281. EfipTda19988Write2(TDA19988_CONTROL_VS_PIXEL_END_2_HIGH, Vs2PixelEnd);
  1282. EfipTda19988Write2(TDA19988_CONTROL_HS_PIXEL_START_HIGH, HsPixelStart);
  1283. EfipTda19988Write2(TDA19988_CONTROL_HS_PIXEL_STOP_HIGH, HsPixelStop);
  1284. EfipTda19988Write2(TDA19988_CONTROL_VWIN_START_1_HIGH, Vwin1LineStart);
  1285. EfipTda19988Write2(TDA19988_CONTROL_VWIN_END_1_HIGH, Vwin1LineEnd);
  1286. EfipTda19988Write2(TDA19988_CONTROL_VWIN_START_2_HIGH, Vwin2LineStart);
  1287. EfipTda19988Write2(TDA19988_CONTROL_VWIN_END_2_HIGH, Vwin2LineEnd);
  1288. EfipTda19988Write2(TDA19988_CONTROL_DE_START_HIGH, DeStart);
  1289. EfipTda19988Write2(TDA19988_CONTROL_DE_STOP_HIGH, DeStop);
  1290. EfipTda19988Write(TDA19988_CONTROL_ENABLE_SPACE, 0);
  1291. //
  1292. // Control 0 must be the last register set.
  1293. //
  1294. EfipTda19988Clear(TDA19988_CONTROL_TBG_CONTROL_0,
  1295. TDA19988_CONTROL_TBG_CONTROL_0_SYNC_ONCE);
  1296. return;
  1297. }
  1298. EFI_STATUS
  1299. EfipTda19988ReadEdid (
  1300. UINT8 *Buffer,
  1301. UINTN Size
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. This routine reads the EDID data from the connected monitor.
  1306. Arguments:
  1307. Buffer - Supplies a pointer where the EDID data will be returned.
  1308. Size - Supplies the number of bytes to read. This must be at least 128
  1309. bytes.
  1310. Return Value:
  1311. EFI Status code.
  1312. --*/
  1313. {
  1314. UINTN Try;
  1315. UINT8 Value;
  1316. Value = TDA19988_HDCP_OTP_TX4_PD_RAM;
  1317. EfipTda19988Clear(TDA19988_HDCP_OTP_TX4, Value);
  1318. //
  1319. // Enable the EDID block read interrupt.
  1320. //
  1321. Value = TDA19988_CONTROL_INTERRUPT_EDID;
  1322. EfipTda19988Set(TDA19988_CONTROL_INTERRUPT, Value);
  1323. //
  1324. // Enable global interrupts.
  1325. //
  1326. Value = TDA19988_CONTROL_INTERRUPT_CONTROL_GLOBAL_ENABLE;
  1327. EfipTda19988Set(TDA19988_CONTROL_INTERRUPT_CONTROL, Value);
  1328. //
  1329. // Set the device address.
  1330. //
  1331. Value = TDA19988_EDID_DEVICE_ADDRESS_EDID;
  1332. EfipTda19988Write(TDA19988_EDID_DEVICE_ADDRESS, Value);
  1333. //
  1334. // Set the EDID offset.
  1335. //
  1336. Value = TDA19988_EDID_OFFSET_VALUE;
  1337. EfipTda19988Write(TDA19988_EDID_OFFSET, Value);
  1338. //
  1339. // Set the EDID segment pointer address.
  1340. //
  1341. Value = TDA19988_EDID_SEGMENT_POINTER_ADDRESS_VALUE;
  1342. EfipTda19988Write(TDA19988_EDID_SEGMENT_POINTER_ADDRESS, Value);
  1343. //
  1344. // Set the EDID segment address.
  1345. //
  1346. Value = TDA19988_EDID_SEGMENT_ADDRESS_VALUE;
  1347. EfipTda19988Write(TDA19988_EDID_SEGMENT_ADDRESS, Value);
  1348. //
  1349. // Pulse the EDID read request bit to make the read happen.
  1350. //
  1351. Value = TDA19988_EDID_REQUEST_READ;
  1352. EfipTda19988Write(TDA19988_EDID_REQUEST, Value);
  1353. Value = 0;
  1354. EfipTda19988Write(TDA19988_EDID_REQUEST, Value);
  1355. //
  1356. // Poll the interrupt status flag.
  1357. //
  1358. Value = 0;
  1359. for (Try = 0; Try < 100; Try += 1) {
  1360. EfipTda19988Read(TDA19988_CONTROL_INTERRUPT, &Value);
  1361. if ((Value & TDA19988_CONTROL_INTERRUPT_EDID) != 0) {
  1362. break;
  1363. }
  1364. }
  1365. if ((Value & TDA19988_CONTROL_INTERRUPT_EDID) == 0) {
  1366. return EFI_DEVICE_ERROR;
  1367. }
  1368. //
  1369. // Perform the block read.
  1370. //
  1371. EfipTda19988ReadMultiple(TDA19988_EDID_DATA,
  1372. Size,
  1373. Buffer);
  1374. Value = TDA19988_HDCP_OTP_TX4_PD_RAM;
  1375. EfipTda19988Set(TDA19988_HDCP_OTP_TX4, Value);
  1376. //
  1377. // Disable the EDID read interrupt.
  1378. //
  1379. Value = TDA19988_CONTROL_INTERRUPT_EDID;
  1380. EfipTda19988Clear(TDA19988_CONTROL_INTERRUPT, Value);
  1381. return EFI_SUCCESS;
  1382. }
  1383. VOID
  1384. EfipTda19988Set (
  1385. UINT16 Register,
  1386. UINT8 Bits
  1387. )
  1388. /*++
  1389. Routine Description:
  1390. This routine performs a read-modify-write to set bits in a register.
  1391. Arguments:
  1392. Register - Supplies the register number to read. The high 8 bits contain
  1393. the page number and the low 8 bits contain the register number.
  1394. Bits - Supplies the bits to set in the register.
  1395. Return Value:
  1396. None.
  1397. --*/
  1398. {
  1399. UINT8 Data;
  1400. EfipTda19988Read(Register, &Data);
  1401. Data |= Bits;
  1402. EfipTda19988Write(Register, Data);
  1403. return;
  1404. }
  1405. VOID
  1406. EfipTda19988Clear (
  1407. UINT16 Register,
  1408. UINT8 Bits
  1409. )
  1410. /*++
  1411. Routine Description:
  1412. This routine performs a read-modify-write to clear bits in a register.
  1413. Arguments:
  1414. Register - Supplies the register number to read. The high 8 bits contain
  1415. the page number and the low 8 bits contain the register number.
  1416. Bits - Supplies the bits to set in the register.
  1417. Return Value:
  1418. None.
  1419. --*/
  1420. {
  1421. UINT8 Data;
  1422. EfipTda19988Read(Register, &Data);
  1423. Data &= ~Bits;
  1424. EfipTda19988Write(Register, Data);
  1425. return;
  1426. }
  1427. VOID
  1428. EfipTda19988Read (
  1429. UINT16 Register,
  1430. UINT8 *Data
  1431. )
  1432. /*++
  1433. Routine Description:
  1434. This routine reads from the TDA19988 HDMI block.
  1435. Arguments:
  1436. Register - Supplies the register number to read. The high 8 bits contain
  1437. the page number and the low 8 bits contain the register number.
  1438. Data - Supplies a pointer where the data will be returned on success.
  1439. Return Value:
  1440. None.
  1441. --*/
  1442. {
  1443. UINT8 PageNumber;
  1444. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_HDMI_BUS_ADDRESS);
  1445. PageNumber = Register >> 8;
  1446. EfipTda19988SetPage(PageNumber);
  1447. EfipAm335I2c0Read(Register & 0xFF, 1, Data);
  1448. return;
  1449. }
  1450. VOID
  1451. EfipTda19988Write (
  1452. UINT16 Register,
  1453. UINT8 Data
  1454. )
  1455. /*++
  1456. Routine Description:
  1457. This routine writes to the TDA19988 HDMI block.
  1458. Arguments:
  1459. Register - Supplies the register number to read. The high 8 bits contain
  1460. the page number and the low 8 bits contain the register number.
  1461. Data - Supplies a pointer to the data to write.
  1462. Return Value:
  1463. None.
  1464. --*/
  1465. {
  1466. UINT8 PageNumber;
  1467. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_HDMI_BUS_ADDRESS);
  1468. PageNumber = Register >> 8;
  1469. EfipTda19988SetPage(PageNumber);
  1470. EfipAm335I2c0Write(Register & 0xFF, 1, &Data);
  1471. return;
  1472. }
  1473. VOID
  1474. EfipTda19988Write2 (
  1475. UINT16 Register,
  1476. UINT16 Data
  1477. )
  1478. /*++
  1479. Routine Description:
  1480. This routine writes a two-byte register value to the TDA19988 HDMI block.
  1481. Arguments:
  1482. Register - Supplies the register number to read. The high 8 bits contain
  1483. the page number and the low 8 bits contain the register number.
  1484. Data - Supplies a pointer to the data to write.
  1485. Return Value:
  1486. None.
  1487. --*/
  1488. {
  1489. UINT8 PageNumber;
  1490. UINT8 Value[2];
  1491. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_HDMI_BUS_ADDRESS);
  1492. PageNumber = Register >> 8;
  1493. EfipTda19988SetPage(PageNumber);
  1494. Value[0] = Data >> 8;
  1495. Value[1] = Data & 0xFF;
  1496. EfipAm335I2c0Write(Register & 0xFF, 2, Value);
  1497. return;
  1498. }
  1499. VOID
  1500. EfipTda19988ReadMultiple (
  1501. UINT16 Register,
  1502. UINT8 Size,
  1503. UINT8 *Data
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. This routine reads multiple bytes from the TDA19988 HDMI block.
  1508. Arguments:
  1509. Register - Supplies the register number to read. The high 8 bits contain
  1510. the page number and the low 8 bits contain the register number.
  1511. Size - Supplies the number of bytes to read.
  1512. Data - Supplies a pointer where the data will be returned on success.
  1513. Return Value:
  1514. None.
  1515. --*/
  1516. {
  1517. UINT8 PageNumber;
  1518. EfipAm335I2c0SetSlaveAddress(EFI_TDA19988_HDMI_BUS_ADDRESS);
  1519. PageNumber = Register >> 8;
  1520. EfipTda19988SetPage(PageNumber);
  1521. EfipAm335I2c0Read(Register & 0xFF, Size, Data);
  1522. return;
  1523. }
  1524. VOID
  1525. EfipTda19988SetPage (
  1526. UINT8 PageNumber
  1527. )
  1528. /*++
  1529. Routine Description:
  1530. This routine sets the current register page in the TDA19988.
  1531. Arguments:
  1532. PageNumber - Supplies the page to set.
  1533. Return Value:
  1534. None.
  1535. --*/
  1536. {
  1537. EfipAm335I2c0Write(TDA19988_PAGE_SELECT_REGISTER, 1, &PageNumber);
  1538. return;
  1539. }