Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; Stub of videodriver for RDC Semiconductor Co. M2010/M2012 videocards (controller names: R3306/R3308).
  2. ; It is used in SoC produced by DMP Electronics Inc.:
  3. ;       Vortex86MX  (contains RDC M2010 graphics card, appears in eBox-3300MX)
  4. ;       Vortex86MX+ (contains RDC M2012 graphics card, appears in eBox-3310MX)
  5. ; Link to manufacturers websites -
  6. ;       RDC Semiconductor Co.:   http://www.rdc.com.tw
  7. ;       DM&P Electronics Inc.:   http://www.dmp.com.tw and http://www.compactpc.com.tw
  8. ; Code stolen from vidintel.asm driver (c) by CleverMouse and adapted for RDC.
  9.  
  10. ; When the start procedure gets control,
  11. ; it tries to detect preferred resolution,
  12. ; sets the detected resolution assuming 32-bpp VESA mode and exits
  13. ; (without registering a service).
  14. ; Detection can be overloaded with compile-time settings
  15. ; use_predefined_mode/predefined_width/predefined_height.
  16.  
  17. ; set predefined resolution here
  18. use_predefined_mode = 0;1
  19. predefined_width = 0;1366
  20. predefined_height = 0;768
  21.  
  22. ; standard driver stuff
  23. format MS COFF
  24.  
  25. DEBUG = 1
  26.  
  27. include 'proc32.inc'
  28. include 'imports.inc'
  29.  
  30. public START
  31. public version
  32.  
  33. section '.flat' code readable align 16
  34. ; the start procedure (see the description above)
  35. START:
  36. ; 1. Detect device. Abort if not found.
  37.         push    esi
  38.         call    DetectDevice
  39.         test    esi, esi
  40.         jz      .return0
  41.  
  42. ;{START}yogev_ezra: temporary exit after detection
  43.         pusha
  44.         mov     esi, exitmsg
  45.         call    SysMsgBoardStr
  46.         popa
  47.         jmp     .return0
  48. ;{END}yogev_ezra: temporary exit after detection        
  49.        
  50. ; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed.
  51. if use_predefined_mode = 0
  52.         call    DetectMode
  53. end if
  54.         cmp     [width], 0
  55.         jz      .return0_cleanup
  56. ; 3. Set the detected mode.
  57.         call    SetMode
  58. ; 4. Cleanup and return.
  59. .return0_cleanup:
  60.         stdcall FreeKernelSpace, esi
  61. .return0:
  62.         pop     esi
  63.         xor     eax, eax
  64.         ret     4
  65.  
  66. ; check that there is RDC videocard
  67. ; if so, map MMIO registers and set internal variables
  68. ; esi points to MMIO block; NULL means no device
  69. DetectDevice:
  70. ; 1. Sanity check: check that we are dealing with RDC videocard.
  71. ; Integrated video device for RDC is always at PCI:0:13:0 (bus:dev:fn=0:0d:0)
  72.         xor     esi, esi        ; initialize return value to NULL
  73. ; 1a. Get PCI VendorID and DeviceID.
  74.         push    esi             ; in: reg=0 (register) -> register 00 means return DeviceID (bits 16-31) + VendorID (bits 0-15)
  75.         push    68h             ; in: devfn=13:0 | device:5bit (0Dh = 1101) + func:3bit (0 = 000) -> total:1byte (1101000b = 68h)
  76.         push    esi             ; in: bus=0
  77.         call    PciRead32
  78. ; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID.
  79. ; Test whether we have RDC Semiconductor Co. chipset.
  80.         cmp     ax, 17F3h       ;VendorID 0x17F3, 'RDC Semiconductor Co.'
  81.         jnz     .return
  82. ; 1c. Say hi including DeviceID.
  83.         shr     eax, 10h        ; now, ax = HIWORD(eax) = PCI DeviceID
  84.         push    edi
  85.         pusha
  86.         mov     edi, pciid_text ; edi='0000'
  87.         call    WriteWord
  88.         mov     esi, hellomsg
  89.         call    SysMsgBoardStr
  90.         popa
  91. ; 1d. Test whether we know this DeviceID.
  92. ; If this is the case, remember the position of the device in line of RDC cards;
  93. ; this knowledge will be useful later.
  94. ; Tested on devices with id: 17F3:2010, 17F3:2012.
  95.         mov     ecx, pciids_num
  96.         mov     edi, pciids
  97.         repnz scasw
  98.         pop     edi
  99.         jnz     .return_unknown_pciid
  100.         sub     ecx, pciids_num - 1
  101.         neg     ecx
  102.         mov     [deviceType], ecx
  103. ; 1e. Continue saying hi with positive intonation.
  104.         pusha
  105.         mov     esi, knownmsg
  106.         call    SysMsgBoardStr
  107.         popa
  108. ; 2. Prepare MMIO region to control the card.
  109. ; 2a. Read MMIO physical address from PCI config space.
  110. ; According to RDC M2010/M2012 registers manual, their memory-mapped I/O space is located at Base address #1
  111.         push    14h             ; in: reg=14h (register) -> register 14h means Base address #1 (BAR1) in PCI configuration space
  112.         push    68h             ; in: devfn=13:0 | device:5bit (0Dh = 1101) + func:3bit (0 = 000) -> total:1byte (1101000b = 68h)
  113.         push    esi             ; in: bus=0
  114.         call    PciRead32
  115. ; 2b. Mask out PCI region type, lower 4 bits.
  116.         and     al, not 0xF
  117. ; 2c. Create virtual mapping of the physical memory.
  118.         push    1Bh
  119.         push    100000h
  120.         push    eax
  121.         call    MapIoMem
  122. ; 3. Return.
  123.         xchg    esi, eax
  124. .return:
  125.         ret
  126. ; 1f. If we do not know DeviceID, continue saying hi with negative intonation.
  127. .return_unknown_pciid:
  128.         pusha
  129.         mov     esi, unknownmsg
  130.         call    SysMsgBoardStr
  131.         popa
  132.         ret
  133.  
  134. ; Convert word in ax to hexadecimal text in edi, advance edi.
  135. WriteWord:
  136. ; 1. Convert high byte.
  137.         push    eax
  138.         mov     al, ah
  139.         call    WriteByte
  140.         pop     eax
  141. ; 2. Convert low byte.
  142. ; Fall through to WriteByte; ret from WriteByte is ret from WriteWord too.
  143.  
  144. ; Convert byte in al to hexadecimal text in edi, advance edi.
  145. WriteByte:
  146. ; 1. Convert high nibble.
  147.         push    eax
  148.         shr     al, 4
  149.         call    WriteNibble
  150.         pop     eax
  151. ; 2. Convert low nibble.
  152.         and     al, 0xF
  153. ; Fall through to WriteNibble; ret from WriteNibble is ret from WriteByte too.
  154.  
  155. ; Convert nibble in al to hexadecimal text in edi, advance edi.
  156. WriteNibble:
  157. ; Obvious, isn't it?
  158.         cmp     al, 10
  159.         sbb     al, 69h
  160.         das
  161.         stosb               ; This instruction uses EDI implicitly
  162.         ret
  163.  
  164. if use_predefined_mode = 0
  165. ; detect resolution of the flat panel
  166. DetectMode:
  167.         push    esi edi
  168. ; 1. Get the location of block of GMBUS* registers.
  169. ; Starting with Ironlake, GMBUS* registers were moved.
  170.         add     esi, 5100h
  171.         cmp     [deviceType], pciids_num ;ironlake_start
  172.         jb      @f
  173.         add     esi, 0xC0000
  174. @@:
  175. ; 2. Initialize GMBUS engine.
  176.         mov     edi, edid
  177.         mov     ecx, 0x10000
  178. @@:
  179.         test    byte [esi+8+1], 80h
  180.         loopnz  @b
  181.         jnz     .fail
  182.         mov     dword [esi], 3
  183.         test    byte [esi+8+1], 4
  184.         jz      .noreset
  185.         call    ResetGMBus
  186.         jnz     .fail
  187. .noreset:
  188. ; 3. Send read command.
  189.         and     dword [esi+20h], 0
  190.         mov     dword [esi+4], 4E8000A1h
  191. ; 4. Wait for data, writing to the buffer as data arrive.
  192. .getdata:
  193.         mov     ecx, 0x10000
  194. @@:
  195.         test    byte [esi+8+1], 8
  196.         loopz   @b
  197.         test    byte [esi+8+1], 4
  198.         jz      .dataok
  199.         call    ResetGMBus
  200.         jmp     .fail
  201. .dataok:
  202.         mov     eax, [esi+0Ch]
  203.         stosd
  204.         cmp     edi, edid+80h
  205.         jb      .getdata
  206. ; 5. Wait for bus idle.
  207.         mov     ecx, 0x10000
  208. @@:
  209.         test    byte [esi+8+1], 2
  210.         loopnz  @b
  211. ; 6. We got EDID; dump it if DEBUG.
  212. if DEBUG
  213.         pusha
  214.         xor     ecx, ecx
  215.         mov     esi, edid
  216.         mov     edi, edid_text
  217. .dumploop:
  218.         lodsb
  219.         call    WriteByte
  220.         mov     al, ' '
  221.         stosb
  222.         inc     cl
  223.         test    cl, 15
  224.         jnz     @f
  225.         mov     byte [edi-1], 13
  226.         mov     al, 10
  227.         stosb
  228. @@:
  229.         test    cl, cl
  230.         jns     .dumploop
  231.         mov     esi, edidmsg
  232.         call    SysMsgBoardStr
  233.         popa
  234. end if
  235. ; 7. Test whether EDID is good.
  236. ; 7a. Signature: 00 FF FF FF FF FF FF 00.
  237.         mov     esi, edid
  238.         cmp     dword [esi], 0xFFFFFF00
  239.         jnz     .fail
  240.         cmp     dword [esi+4], 0x00FFFFFF
  241.         jnz     .fail
  242. ; 7b. Checksum must be zero.
  243.         xor     edx, edx
  244.         mov     ecx, 80h
  245. @@:
  246.         lodsb
  247.         add     dl, al
  248.         loop    @b
  249.         jnz     .fail
  250. ; 8. Get width and height from EDID.
  251.         xor     eax, eax
  252.         mov     ah, [esi-80h+3Ah]
  253.         shr     ah, 4
  254.         mov     al, [esi-80h+38h]
  255.         mov     [width], eax
  256.         mov     ah, [esi-80h+3Dh]
  257.         shr     ah, 4
  258.         mov     al, [esi-80h+3Bh]
  259.         mov     [height], eax
  260. ; 9. Return.
  261. .fail:
  262.         pop     edi esi
  263.         ret
  264.  
  265. ; reset bus, clear all errors
  266. ResetGMBus:
  267. ; look into the PRM
  268.         mov     dword [esi+4], 80000000h
  269.         mov     dword [esi+4], 0
  270.         mov     ecx, 0x10000
  271. @@:
  272.         test    byte [esi+8+1], 2
  273.         loopnz  @b
  274.         ret
  275. end if
  276.  
  277. ; set resolution [width]*[height]
  278. SetMode:
  279. ; 1. Program the registers of videocard.
  280. ; look into the PRM
  281.         cli
  282. ;       or      byte [esi+7000Ah], 0Ch  ; PIPEACONF: disable Display+Cursor Planes
  283. ;       or      byte [esi+7100Ah], 0Ch  ; PIPEBCONF: disable Display+Cursor Planes
  284.         xor     eax, eax
  285.         xor     edx, edx
  286.         cmp     [deviceType], pciids_num ;i965_start
  287.         jb      @f
  288.         mov     dl, 9Ch - 84h
  289. @@:
  290. ;       or      byte [esi+71403h], 80h  ; VGACNTRL: VGA Display Disable
  291.         and     byte [esi+70080h], not 27h      ; CURACNTR: disable cursor A
  292.         mov     dword [esi+70084h], eax ; CURABASE: force write to CURA* regs
  293.         and     byte [esi+700C0h], not 27h      ; CURBCNTR: disable cursor B
  294.         mov     dword [esi+700C4h], eax ; CURBBASE: force write to CURB* regs
  295.         and     byte [esi+70183h], not 80h      ; DSPACNTR: disable Primary A Plane
  296.         mov     dword [esi+edx+70184h], eax     ; DSPALINOFF/DSPASURF: force write to DSPA* regs
  297.         and     byte [esi+71183h], not 80h      ; DSPBCNTR: disable Primary B Plane
  298.         mov     dword [esi+edx+71184h], eax     ; DSPBLINOFF/DSPBSURF: force write to DSPB* regs
  299. if 1
  300.         cmp     [deviceType], pciids_num ;ironlake_start
  301.         jae     .disable_pipes
  302.         mov     edx, 10000h
  303.         or      byte [esi+70024h], 2    ; PIPEASTAT: clear VBLANK status
  304.         or      byte [esi+71024h], 2    ; PIPEBSTAT: clear VBLANK status
  305. .wait_vblank_preironlake1:
  306.         mov     ecx, 1000h
  307.         loop    $
  308.         test    byte [esi+7000Bh], 80h          ; PIPEACONF: pipe A active?
  309.         jz      @f
  310.         test    byte [esi+70024h], 2            ; PIPEASTAT: got VBLANK?
  311.         jz      .wait_vblank_preironlake2
  312. @@:
  313.         test    byte [esi+7100Bh], 80h          ; PIPEBCONF: pipe B active?
  314.         jz      .disable_pipes
  315.         test    byte [esi+71024h], 2            ; PIPEBSTAT: got VBLANK?
  316.         jnz     .disable_pipes
  317. .wait_vblank_preironlake2:
  318.         dec     edx
  319.         jnz     .wait_vblank_preironlake1
  320.         jmp     .not_disabled
  321. .disable_pipes:
  322. end if
  323.         and     byte [esi+7000Bh], not 80h      ; PIPEACONF: disable pipe
  324.         and     byte [esi+7100Bh], not 80h      ; PIPEBCONF: disable pipe
  325.         cmp     [deviceType], pciids_num ;gen4_start
  326.         jb      .wait_watching_scanline
  327. ; g45 and later: use special flag from PIPE*CONF
  328.         mov     edx, 10000h
  329. @@:
  330.         mov     ecx, 1000h
  331.         loop    $
  332.         test    byte [esi+7000Bh], 40h  ; PIPEACONF: wait until pipe disabled
  333.         jz      @f
  334.         dec     edx
  335.         jnz     @b
  336.         jmp     .not_disabled
  337. @@:
  338.         test    byte [esi+7100Bh], 40h  ; PIPEBCONF: wait until pipe disabled
  339.         jz      .disabled
  340.         mov     ecx, 1000h
  341.         loop    $
  342.         dec     edx
  343.         jnz     @b
  344.         jmp     .not_disabled
  345. ; pineview and before: wait while scanline still changes
  346. .wait_watching_scanline:
  347.         mov     edx, 1000h
  348. .dis1:
  349.         push    dword [esi+71000h]
  350.         push    dword [esi+70000h]
  351.         mov     ecx, 10000h
  352.         loop    $
  353.         pop     eax
  354.         xor     eax, [esi+70000h]
  355.         and     eax, 1FFFh
  356.         pop     eax
  357.         jnz     .notdis1
  358.         xor     eax, [esi+71000h]
  359.         and     eax, 1FFFh
  360.         jz      .disabled
  361. .notdis1:
  362.         dec     edx
  363.         jnz     .dis1
  364. .not_disabled:
  365.         sti
  366.         jmp     .return
  367. .disabled:
  368.         lea     eax, [esi+61183h]
  369.         cmp     [deviceType], pciids_num ;ironlake_start
  370.         jb      @f
  371.         add     eax, 0xE0000 - 0x60000
  372. @@:
  373.         lea     edx, [esi+60000h]
  374.         test    byte [eax], 40h
  375.         jz      @f
  376.         add     edx, 1000h
  377. @@:
  378.         mov     eax, [width]
  379.         dec     eax
  380.         shl     eax, 16
  381.         mov     ax, word [height]
  382.         dec     eax
  383.         mov     dword [edx+1Ch], eax    ; PIPEASRC: set source image size
  384.         ror     eax, 16
  385.         mov     dword [edx+10190h], eax ; for old cards
  386.         mov     ecx, [width]
  387.         add     ecx, 15
  388.         and     ecx, not 15
  389.         shl     ecx, 2
  390.         mov     dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length
  391.         mov     dword [edx+10184h], 0   ; DSPALINOFF: force write to DSPA* registers
  392.         and     byte [esi+61233h], not 80h      ; PFIT_CONTROL: disable panel fitting
  393.         or      byte [edx+1000Bh], 80h          ; PIPEACONF: enable pipe
  394. ;       and     byte [edx+1000Ah], not 0Ch      ; PIPEACONF: enable Display+Cursor Planes
  395.         or      byte [edx+10183h], 80h          ; DSPACNTR: enable Display Plane A
  396.         sti
  397. ; 2. Notify the kernel that resolution has changed.
  398.         call    GetDisplay
  399.         mov     edx, [width]
  400.         mov     dword [eax+8], edx
  401.         mov     edx, [height]
  402.         mov     dword [eax+0Ch], edx
  403.         mov     [eax+18h], ecx
  404.         mov     eax, [width]
  405.         dec     eax
  406.         dec     edx
  407.         call    SetScreen
  408. .return:
  409.         ret
  410.  
  411. align 4
  412. hellomsg        db      'RDC videocard detected, PciId=17F3:'         ;VendorID 0x17F3, 'RDC Semiconductor Co.'
  413. pciid_text      db      '0000'
  414.                 db      ', which is ', 0
  415. knownmsg        db      'known',13,10,0
  416. unknownmsg      db      'unknown',13,10,0
  417. exitmsg         db      'Card detected successfully, exiting driver...',13,10,0
  418.  
  419. if DEBUG
  420. edidmsg         db      'EDID successfully read:',13,10
  421. edid_text       rb      8*(16*3+1)
  422.                 db      0
  423. end if
  424.  
  425. version:
  426.         dd      0x50005
  427.  
  428. width   dd      predefined_width
  429. height  dd      predefined_height
  430.  
  431. pciids:
  432.         dw      0x2010          ; M2010 - appears in eBox-3300MX (Vortex86MX SoC)
  433.         dw      0x2012          ; M2012 - appears in eBox-3310MX (Vortex86MX+ SoC)
  434. pciids_num = ($ - pciids) / 2
  435.  
  436. align 4
  437. deviceType      dd      ?
  438. edid    rb      0x80