Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1731 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
1912 clevermous 96
	cmp	ecx, i9xx_start
97
	jae	@f
98
	mov	byte [esp], 14h
99
@@:
1731 clevermous 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
1750 clevermous 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
1731 clevermous 311
	and	byte [esi+7000Bh], not 80h	; PIPEACONF: disable pipe
312
	and	byte [esi+7100Bh], not 80h	; PIPEBCONF: disable pipe
1750 clevermous 313
if 1
1731 clevermous 314
	mov	edx, 10000h
315
@@:
316
	mov	ecx, 1000h
317
	loop	$
318
	test	byte [esi+7000Bh], 40h	; PIPEACONF: wait until pipe disabled
319
	jz	@f
320
	dec	edx
321
	jnz	@b
322
.not_disabled:
323
	sti
324
	jmp	.return
325
@@:
326
	test	byte [esi+7100Bh], 40h	; PIPEBCONF: wait until pipe disabled
327
	jz	@f
328
	mov	ecx, 1000h
329
	loop	$
330
	dec	edx
331
	jnz	@b
332
	jmp	.not_disabled
333
@@:
1750 clevermous 334
else
335
; alternative way of waiting for pipe stop, works too
336
	mov	edx, 1000h
337
.dis1:
338
	push	dword [esi+71000h]
339
	push	dword [esi+70000h]
340
	mov	ecx, 10000h
341
	loop	$
342
	pop	eax
343
	xor	eax, [esi+70000h]
344
	and	eax, 1FFFh
345
	pop	eax
346
	jnz	.notdis1
347
	xor	eax, [esi+71000h]
348
	and	eax, 1FFFh
349
	jz	.disabled
350
.notdis1:
351
	dec	edx
352
	jnz	.dis1
353
.not_disabled:
354
	sti
355
	jmp	.return
356
.disabled:
357
end if
1731 clevermous 358
	lea	eax, [esi+61183h]
359
	cmp	[deviceType], ironlake_start
360
	jb	@f
361
	add	eax, 0xE0000 - 0x60000
362
@@:
363
	lea	edx, [esi+60000h]
364
	test	byte [eax], 40h
365
	jz	@f
366
	add	edx, 1000h
367
@@:
368
	mov	eax, [width]
369
	dec	eax
370
	shl	eax, 16
371
	mov	ax, word [height]
372
	dec	eax
373
	mov	dword [edx+1Ch], eax	; PIPEASRC: set source image size
374
	ror	eax, 16
375
	mov	dword [edx+10190h], eax	; for old cards
376
	mov	ecx, [width]
377
	add	ecx, 15
378
	and	ecx, not 15
379
	shl	ecx, 2
380
	mov	dword [edx+10188h], ecx	; DSPASTRIDE: set scanline length
381
	and	byte [esi+61233h], not 80h	; PFIT_CONTROL: disable panel fitting
1750 clevermous 382
	or	byte [edx+1000Bh], 80h		; PIPEACONF: enable pipe
383
;	and	byte [edx+1000Ah], not 0Ch	; PIPEACONF: enable Display+Cursor Planes
1731 clevermous 384
	or	byte [edx+10183h], 80h		; DSPACNTR: enable Display Plane A
385
	sti
386
; 2. Notify the kernel that resolution has changed.
387
	call	GetDisplay
388
	mov	edx, [width]
389
	mov	dword [eax+8], edx
390
	mov	edx, [height]
391
	mov	dword [eax+0Ch], edx
392
	mov	[eax+18h], ecx
393
	mov	eax, [width]
394
	dec	eax
395
	dec	edx
396
	call	SetScreen
397
.return:
398
	ret
399
 
400
align 4
401
hellomsg	db	'Intel videocard detected, PciId=8086:'
402
pciid_text	db	'0000'
403
		db	', which is ', 0
404
knownmsg	db	'known',13,10,0
405
unknownmsg	db	'unknown',13,10,0
406
 
407
if DEBUG
408
edidmsg		db	'EDID successfully read:',13,10
409
edid_text	rb	8*(16*3+1)
410
		db	0
411
end if
412
 
413
version:
414
	dd	0x50005
415
 
416
width	dd	predefined_width
417
height	dd	predefined_height
418
 
419
pciids:
1912 clevermous 420
	dw	0x3577		; i830m
421
	dw	0x2562		; 845g
422
	dw	0x3582		; i855gm
423
i865_start = ($ - pciids) / 2
424
	dw	0x2572		; i865g
425
i9xx_start = ($ - pciids) / 2
1731 clevermous 426
	dw	0x2582	; i915g
1912 clevermous 427
	dw	0x258a	; e7221g (i915g)
1731 clevermous 428
	dw	0x2592	; i915gm
429
	dw	0x2772	; i945g
430
	dw	0x27a2	; i945gm
1912 clevermous 431
	dw	0x27ae	; i945gme
1750 clevermous 432
i965_start = ($ - pciids) / 2
1912 clevermous 433
	dw	0x2972	; i946qz (i965g)
434
	dw	0x2982	; g35g (i965g)
435
	dw	0x2992	; i965q (i965g)
1731 clevermous 436
	dw	0x29a2	; i965g
1912 clevermous 437
	dw	0x29b2	; q35g
438
	dw	0x29c2	; g33g
439
	dw	0x29d2	; q33g
1731 clevermous 440
	dw	0x2a02	; i965gm
441
	dw	0x2a12	; i965gm
442
	dw	0x2a42	; gm45
443
	dw	0x2e02	; g45
444
	dw	0x2e12	; g45
445
	dw	0x2e22	; g45
446
	dw	0x2e32	; g45
447
	dw	0x2e42	; g45
448
	dw	0x2e92	; g45
449
	dw	0xa001	; pineview
450
	dw	0xa011	; pineview
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