embox

Форк
0
414 строк · 11.1 Кб
1
/*
2
 * @file
3
 *
4
 * @date Dec 19, 2012
5
 * @author: Anton Bondarev
6
 */
7

8
//http://linuxconsole.sourceforge.net/fbdev/HOWTO/3.html
9

10
//http://www.faqs.org/faqs/pc-hardware-faq/supervga-programming/
11
//http://wiki.osdev.org/VGA_Hardware#The_CRT_Controller
12
//http://www.osdever.net/FreeVGA/vga/crtcreg.htm
13

14
//CIRRUS_LOGIC_GD_5446
15

16
#include <stdint.h>
17
#include <errno.h>
18
#include <string.h>
19
#include <sys/mman.h>
20

21
#include <drivers/pci/pci.h>
22
#include <drivers/pci/pci_driver.h>
23
#include <drivers/pci/pci_id.h>
24

25
#include <drivers/video/cirrus_logic.h>
26
#include <drivers/video/vga.h>
27
#include <drivers/video/fb.h>
28

29
struct cirrus_chip_info {
30
	unsigned int *regbase;
31
	const struct fb_var_screeninfo *screen_info;
32
	int doubleVCLK;
33
	int multiplexing;
34
	char *screen_base;
35
};
36

37
static struct cirrus_chip_info cirrus_chip_info;
38

39
static void mdelay(int delay) {
40

41
}
42

43
void cirrus_chip_reset(struct cirrus_chip_info *cinfo) {
44
	/* disable flickerfixer */
45
	vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
46
	mdelay(100);
47
	/* mode */
48
	vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
49
}
50

51
void udelay(int cnt) {
52
	volatile int tcnt = cnt * 1000;
53

54
	while(tcnt--) {}
55

56
}
57

58
/* write to hidden DAC registers */
59
static void WHDR(const struct cirrus_chip_info *cinfo, unsigned char val) {
60
	unsigned char dummy;
61

62
	/* now do the usual stuff to access the HDR */
63
	dummy = in8(VGA_PEL_MSK);
64
	udelay(200);
65
	dummy = in8(VGA_PEL_MSK);
66
	udelay(200);
67
	dummy = in8(VGA_PEL_MSK);
68
	udelay(200);
69
	dummy = in8(VGA_PEL_MSK);
70
	udelay(200);
71

72
	out8(val, VGA_PEL_MSK);
73
	udelay(200);
74

75
	dummy = dummy;
76
}
77

78
unsigned char RHDR(const struct cirrus_chip_info *cinfo) {
79
	unsigned char dummy;
80

81
	/* now do the usual stuff to access the HDR */
82
	dummy = in8(VGA_PEL_MSK);
83
	udelay(200);
84
	dummy = in8(VGA_PEL_MSK);
85
	udelay(200);
86
	dummy = in8(VGA_PEL_MSK);
87
	udelay(200);
88
	dummy = in8(VGA_PEL_MSK);
89
	udelay(200);
90

91
	dummy = in8(VGA_PEL_MSK);
92
	udelay(200);
93

94
	return dummy;
95

96
}
97

98
static void chipset_init(struct cirrus_chip_info *cinfo) {
99
	/* plane mask: nothing */
100
	vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_MASK, 0xff);
101
	/* character map select: doesn't even matter in gx mode */
102
	vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
103
	/* memory mode: chain4, ext. memory */
104
	vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
105

106
	/* controller-internal base address of video memory */
107
/* enable extention mode ? */
108
//	if (bi->init_sr07)
109
//		vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
110

111
	/*  vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
112
	/* EEPROM control: shouldn't be necessary to write to this at all.. */
113

114
	/* graphics cursor X position (incomplete; position gives rem. 3 bits */
115
	vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
116
	/* graphics cursor Y position (..."... ) */
117
	vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
118
	/* graphics cursor attributes */
119
	vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
120
	/* graphics cursor pattern address */
121
	vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
122

123
	/* Screen A preset row scan: none */
124
	vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
125
	/* Text cursor start: disable text cursor */
126
	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
127
	/* Text cursor end: - */
128
	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
129
	/* text cursor location high: 0 */
130
	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
131
	/* text cursor location low: 0 */
132
	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
133

134
	/* Underline Row scanline: - */
135
	vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
136

137

138
	/* Set/Reset registes: - */
139
	vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
140
	/* Set/Reset enable: - */
141
	vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
142
	/* Color Compare: - */
143
	vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
144
	/* Data Rotate: - */
145
	vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
146
	/* Read Map Select: - */
147
	vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
148
	/* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
149
	vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
150
	/* Miscellaneous: memory map base address, graphics mode */
151
	vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
152
	/* Color Don't care: involve all planes */
153
	vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
154
	/* Bit Mask: no mask at all */
155
	vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
156

157

158
	/* Graphics controller mode extensions: finer granularity,
159
	 * 8byte data latches
160
	 */
161
	vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
162

163
	vga_wgfx(cinfo->regbase, CL_GRC, 0xff);	/* Color Key compare: - */
164
	vga_wgfx(cinfo->regbase, CL_GRD, 0x00);	/* Color Key compare mask: - */
165
	vga_wgfx(cinfo->regbase, CL_GRE, 0x00);	/* Miscellaneous control: - */
166
	/* Background color byte 1: - */
167
	/*  vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
168
	/*  vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
169

170
	/* Attribute Controller palette registers: "identity mapping" */
171
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
172
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
173
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
174
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
175
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
176
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
177
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
178
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
179
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
180
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
181
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
182
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
183
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
184
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
185
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
186
	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
187

188
	/* Attribute Controller mode: graphics mode */
189
	vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
190
	/* Overscan color reg.: reg. 0 */
191
	vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
192
	/* Color Plane enable: Enable all 4 planes */
193
	vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
194
	/* Color Select: - */
195
	vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
196

197
//	WGen(cinfo, VGA_PEL_MSK, 0xff);	/* Pixel mask: no mask */
198

199
	/* BLT Start/status: Blitter reset */
200
	vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
201
	/* - " -	   : "end-of-reset" */
202
	vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
203

204
	/* misc... */
205
	WHDR(cinfo, 0);	/* Hidden DAC register: - */
206

207
}
208

209
static void setup_resolution(struct cirrus_chip_info *cinfo) {
210
	int vdispend, vsyncstart, vsyncend, vtotal;
211
	int hdispend, hsyncstart, hsyncend, htotal;
212
	int tmp;
213
	unsigned int *regbase = cinfo->regbase;
214
	const struct fb_var_screeninfo *var = cinfo->screen_info;
215

216
	hsyncstart = var->xres + var->right_margin;
217
	hsyncend = hsyncstart + var->hsync_len;
218
	htotal = (hsyncend + var->left_margin) / 8;
219
	hdispend = var->xres / 8;
220
	hsyncstart = hsyncstart / 8;
221
	hsyncend = hsyncend / 8;
222

223
	vdispend = var->yres;
224
	vsyncstart = vdispend + var->lower_margin;
225
	vsyncend = vsyncstart + var->vsync_len;
226
	vtotal = vsyncend + var->upper_margin;
227

228

229
	vdispend -= 1;
230
	vsyncstart -= 1;
231
	vsyncend -= 1;
232
	vtotal -= 2;
233

234
	if (cinfo->multiplexing) {
235
		htotal /= 2;
236
		hsyncstart /= 2;
237
		hsyncend /= 2;
238
		hdispend /= 2;
239
	}
240

241
	htotal -= 5;
242
	hdispend -= 1;
243
	hsyncstart += 1;
244
	hsyncend += 1;
245

246

247
	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
248
	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */
249
	/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
250
	* address wrap, no compat. */
251
	vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
252

253
	vga_wcrt(regbase, VGA_CRTC_H_DISP_END, hdispend);
254

255
	vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
256

257
	/* setup bit 7 to Compatible Read reg 0x10 and 0x11 */
258
	vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,((htotal + 5) % 32) | 0x80);
259

260
	vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
261

262
	tmp = hsyncend % 32;
263
	if ((htotal + 5) & 32) {
264
		tmp |= 0x80; /* setup bit 7 */
265
	}
266
	vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
267

268
	vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
269

270
	tmp = 16;		/* LineCompare bit #9 */
271
	if (vtotal & 256)
272
		tmp |= 1;
273
	if (vdispend & 256)
274
		tmp |= 2;
275
	if (vsyncstart & 256)
276
		tmp |= 4;
277
	if ((vdispend + 1) & 256)
278
		tmp |= 8;
279
	if (vtotal & 512)
280
		tmp |= 32;
281
	if (vdispend & 512)
282
		tmp |= 64;
283
	if (vsyncstart & 512)
284
		tmp |= 128;
285
	vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
286

287

288
	tmp = 0x40;		/* LineCompare bit #8 */
289
	if ((vdispend + 1) & 512)
290
		tmp |= 0x20;
291
	if (var->vmode & FB_VMODE_DOUBLE)
292
		tmp |= 0x80;
293

294
	vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
295

296
	vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
297

298
	/* bit 6 is Refresh Cycle Control
299
	 * bit 5 is Disable Vertical Interrupt
300
	 */
301
	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, (vsyncend % 16) | 0x40 | 0x20);
302

303
	vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
304

305
	vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
306

307
	vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
308

309
	vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
310

311
	tmp = var->xres >> 2;
312
	vga_wcrt(regbase, VGA_CRTC_OFFSET, tmp & 0xff);
313
	tmp >>= 8;
314

315
	/* ### add 0x40 for text modes with > 30 MHz pixclock */
316
	/* ext. display controls: ext.adr. wrap */
317
	/* add extended bit of OFFSET */
318
	vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02 | (tmp ? 0x10 : 0) );
319

320
	vga_wcrt(regbase, VGA_CRTC_MODE_CONTROL, 0xc3);
321

322
	memset(cinfo->screen_base, 0, var->xres * var->yres);
323

324
}
325

326
static int cirrus_setup_bpp16(struct cirrus_chip_info *cinfo) {
327
	unsigned int *regbase = cinfo->regbase;
328

329
	/* Extended Sequencer Mode: 256c col. mode */
330
	vga_wseq(regbase, CL_SEQR7, cinfo->doubleVCLK ? 0xa3 : 0xa7);
331
	/* mode register: 256 color mode */
332
	vga_wgfx(regbase, VGA_GFX_MODE, 64);
333

334
	WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1);
335

336
	return 0;
337
}
338

339
static int cirrus_setup_bpp24(struct cirrus_chip_info *cinfo) {
340
	unsigned int *regbase = cinfo->regbase;
341

342
	/* Extended Sequencer Mode: 256c col. mode */
343
	vga_wseq(regbase, CL_SEQR7, 0xa5);
344

345
	/* mode register: 256 color mode */
346
	vga_wgfx(regbase, VGA_GFX_MODE, 64);
347
	/* hidden dac reg: 8-8-8 mode (24 or 32) */
348
	WHDR(cinfo, 0xc5);
349

350
	return 0;
351
}
352

353
static int cirrus_setup_bits_per_pixel(struct cirrus_chip_info *cinfo) {
354
	switch(cinfo->screen_info->bits_per_pixel) {
355
	case 24:
356
		return cirrus_setup_bpp24(cinfo);
357
	case 16:
358
		return cirrus_setup_bpp16(cinfo);
359
	}
360
	return 0;
361
}
362

363
static int cl_set_var(struct fb_info *info, const struct fb_var_screeninfo *var) {
364
	cirrus_chip_info.doubleVCLK = 0;
365
	cirrus_chip_info.multiplexing = 0;
366
	cirrus_chip_info.screen_info = var;
367
	cirrus_chip_info.screen_base = info->screen_base;
368

369
	chipset_init(&cirrus_chip_info);
370

371
	setup_resolution(&cirrus_chip_info);
372

373
	cirrus_setup_bits_per_pixel(&cirrus_chip_info);
374

375
	vga_display_enable(1);
376

377
	return 0;
378
}
379

380
static int cl_get_var(struct fb_info *info, struct fb_var_screeninfo *var) {
381

382
	var->xres = 1280;
383
	var->yres = 1024;
384
	var->bits_per_pixel = 16;
385
	var->fmt = RGB565;
386
	return 0;
387
}
388

389
static const struct fb_ops cl_ops = {
390
	.fb_get_var = cl_get_var,
391
	.fb_set_var = cl_set_var,
392
};
393

394
static int cirrus_init(struct pci_slot_dev *pci_dev) {
395
	char *mmap_base = (char *)(pci_dev->bar[0] & PCI_BASE_ADDR_IO_MASK); /* FIXME */
396
	size_t mmap_len = 1024 * 1280 * 16 / 8;
397
	struct fb_info *info;
398

399
	if (MAP_FAILED == mmap_device_memory(mmap_base, mmap_len,
400
	        PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_FIXED,
401
	        (uintptr_t)mmap_base)) {
402
		return -EIO;
403
	}
404

405
	info = fb_create(&cl_ops, mmap_base, mmap_len);
406
	if (info == NULL) {
407
		munmap(mmap_base, mmap_len);
408
		return -ENOMEM;
409
	}
410

411
	return 0;
412
}
413

414
PCI_DRIVER("cl_gd5446", cirrus_init, PCI_VENDOR_ID_CIRRUS, PCI_DEV_ID_CIRRUS_5446);
415

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.