Subversion Repositories Kolibri OS

Rev

Rev 2456 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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