Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4006 yogev_ezra 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