Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 61598 | Differences between
and this patch

Collapse All | Expand All

(-)linux-2.6.8-gentoo-r4/Documentation/fb/vesafb.txt (-11 / +3 lines)
Lines 246-266 Link Here
246
 o vesafb_probe
246
 o vesafb_probe
247
   - get service thread's PID (started earlier from fbmem.c)
247
   - get service thread's PID (started earlier from fbmem.c)
248
   - call vesafb_vbe_init
248
   - call vesafb_vbe_init
249
   - find a matching VBE mode
249
   - try to find the specified mode in vesa_modes modedb
250
   - try to find the specified mode in vesa_modes modedb
250
   - if the previous step failed or was skipped:
251
   - try to find the specified mode in the EDID modedb
251
     - try to find a matching mode in the VBE modedb - identify VBE mode ID
252
   - try to calculate timings with the GTF
252
     - try to find a matching mode in the EDID modedb
253
     - if the previous step failed or was skipped:
254
       - try to calculate mode timings with GTF
255
   - low level setup - request_mem_region, ioremap, etc.
253
   - low level setup - request_mem_region, ioremap, etc.
256
   - setup /proc/fb<x>/modes and /proc/fb<x>/vbe_info
254
   - setup /proc/fb<x>/modes and /proc/fb<x>/vbe_info
257
255
258
3. Used hacks
259
 
260
 o info->var.reserved[0] holds the VBE mode ID
261
 o info->var.reserved[1] holds a pointer to the VBE mode data in vesafb's
262
   mode database.
263
264
Have fun!
256
Have fun!
265
257
266
--
258
--
(-)linux-2.6.8-gentoo-r4/drivers/video/vesafb-thread.c (-14 / +5 lines)
Lines 381-398 Link Here
381
		addr -= BUFFER+REAL_MEM;					 			\
381
		addr -= BUFFER+REAL_MEM;					 			\
382
		vbe_pib(task->res)->str = (u32) (task->res + addr);					\
382
		vbe_pib(task->res)->str = (u32) (task->res + addr);					\
383
													\
383
													\
384
	/* this should never happen: someone was insane enough to put the data somewhere in the RAM;	\
384
	/* this should never happen: someone was insane enough to put the data somewhere in the RAM */	\
385
	   we need to copy as much of it as possible to our buffer */					\
386
	} else {											\
385
	} else {											\
387
		res = strlcpy((char*) (((int)&(vbe_pib(task->res)->oem_data)) + oem_offset),		\
386
		vbe_pib(task->res)->str = (u32) "";							\
388
			      (char*) addr, sizeof(vbe_pib(task->res)->oem_data) - oem_offset);		\
389
													\
390
		vbe_pib(task->res)->str = ((u32)&(vbe_pib(task->res)->oem_data)) + oem_offset;		\
391
													\
392
		oem_offset += res+1;									\
393
		if (oem_offset > sizeof(vbe_pib(task->res)->oem_data)) {				\
394
			oem_offset = sizeof(vbe_pib(task->res)->oem_data);				\
395
		}											\
396
	}												\
387
	}												\
397
}
388
}
398
389
Lines 400-406 Link Here
400
{
391
{
401
	struct vesafb_task *task;
392
	struct vesafb_task *task;
402
	struct list_head *node, *next;
393
	struct list_head *node, *next;
403
	int addr, oem_offset = 0, res;
394
	int addr, res;
404
	
395
	
405
	down(&vesafb_sem);
396
	down(&vesafb_sem);
406
	list_for_each_safe(node, next, &vesafb_task_list) {
397
	list_for_each_safe(node, next, &vesafb_task_list) {
Lines 430-437 Link Here
430
					vesafb_get_string(oem_product_rev_ptr);
421
					vesafb_get_string(oem_product_rev_ptr);
431
				}
422
				}
432
		
423
		
433
				/* this is basically the same as vesafb_get_string; the third part
424
				/* this is basically the same as vesafb_get_string */
434
				   is different though, so that's what causes all this mess */
435
				addr = ((vbe_pib(task->res)->mode_list_ptr & 0xffff0000) >> 12) +
425
				addr = ((vbe_pib(task->res)->mode_list_ptr & 0xffff0000) >> 12) +
436
					(vbe_pib(task->res)->mode_list_ptr & 0x0000ffff);
426
					(vbe_pib(task->res)->mode_list_ptr & 0x0000ffff);
437
			
427
			
Lines 444-449 Link Here
444
					vbe_pib(task->res)->mode_list_ptr = (u32) (task->res + addr);
434
					vbe_pib(task->res)->mode_list_ptr = (u32) (task->res + addr);
445
				} else {
435
				} else {
446
					res = 0;
436
					res = 0;
437
					printk(KERN_WARNING "vesafb: warning, copying modelist from somewhere in RAM!\n");
447
					while (*(u16*)(addr+res) != 0xffff && 
438
					while (*(u16*)(addr+res) != 0xffff && 
448
					       res < (sizeof(vbe_pib(task->res)->reserved) - 2) )
439
					       res < (sizeof(vbe_pib(task->res)->reserved) - 2) )
449
					{
440
					{
(-)linux-2.6.8-gentoo-r4/drivers/video/vesafb-tng.c (-242 / +252 lines)
Lines 33-38 Link Here
33
#define dac_reg	(0x3c8)
33
#define dac_reg	(0x3c8)
34
#define dac_val	(0x3c9)
34
#define dac_val	(0x3c9)
35
35
36
#define VESAFB_NEED_EXACT_RES 1
37
#define VESAFB_NEED_EXACT_DEPTH 2
38
36
/* --------------------------------------------------------------------- */
39
/* --------------------------------------------------------------------- */
37
40
38
static struct fb_var_screeninfo vesafb_defined __initdata = {
41
static struct fb_var_screeninfo vesafb_defined __initdata = {
Lines 75-81 Link Here
75
static unsigned short			maxhf          __initdata = 0; /* maximum horizontal frequency */
78
static unsigned short			maxhf          __initdata = 0; /* maximum horizontal frequency */
76
static int 				gtf            __initdata = 0; /* forces use of the GTF */
79
static int 				gtf            __initdata = 0; /* forces use of the GTF */
77
static char				*mode_option   __initdata = NULL;
80
static char				*mode_option   __initdata = NULL;
78
static unsigned short			vbemode	       __initdata = 0;
81
static unsigned short			vbemode	                  = 0;
79
82
80
extern int vesafb_pid;			/* PID of the vesafb service thread */
83
extern int vesafb_pid;			/* PID of the vesafb service thread */
81
84
Lines 87-92 Link Here
87
#define vesafb_wait_for_task(task)	{ while (task->done == 0) { schedule(); } }
90
#define vesafb_wait_for_task(task)	{ while (task->done == 0) { schedule(); } }
88
91
89
extern void vesafb_queue_task(struct vesafb_task *task);
92
extern void vesafb_queue_task(struct vesafb_task *task);
93
static int vesafb_find_vbe_mode(int xres, int yres, int bpp, unsigned char flags);
90
94
91
/* --------------------------------------------------------------------- */
95
/* --------------------------------------------------------------------- */
92
96
Lines 221-247 Link Here
221
	struct vesafb_par *par = (struct vesafb_par *) info->par;
225
	struct vesafb_par *par = (struct vesafb_par *) info->par;
222
	struct vesafb_task *mytask;
226
	struct vesafb_task *mytask;
223
	struct vesafb_crtc_info_block *crtc = NULL;	
227
	struct vesafb_crtc_info_block *crtc = NULL;	
224
	struct vesafb_mode_info_block *mode = (void*)info->var.reserved[1];
228
	struct vesafb_mode_info_block *mode = NULL;
225
	int err = 0;
229
	int err = 0, i;
226
	
227
	/* sanity check */
228
	if (info->var.reserved[0] == 0xffff)
229
		return -EINVAL;
230
230
231
	/* has the VBE mode number been specified? */
232
	if (vbemode > 0) {
233
		for (i = 0; i < vbe_modes_cnt; i++) {
234
			if (vbe_modes[i].mode_id == vbemode) {
235
				mode = &vbe_modes[i];
236
				break;
237
			}
238
		}
239
	} else {
240
		i = vesafb_find_vbe_mode(info->var.xres, info->var.yres, 
241
					 info->var.bits_per_pixel, VESAFB_NEED_EXACT_RES | VESAFB_NEED_EXACT_DEPTH);
242
		if (i > 0)
243
			mode = &vbe_modes[i];
244
	}
245
246
	if (mode == NULL)
247
		return -EINVAL;
248
	
231
	vesafb_create_task (mytask);
249
	vesafb_create_task (mytask);
232
250
233
	mytask->regs.eax = 0x4f02;
251
	mytask->regs.eax = 0x4f02;
234
	mytask->regs.ebx = (u16)info->var.reserved[0] | 0x4000;	/* use LFB */
252
	mytask->regs.ebx = mode->mode_id | 0x4000;	/* use LFB */
235
253
236
	if (vbe_ib.vbe_version >= 0x0300 && !nocrtc && 
254
	if (vbe_ib.vbe_version >= 0x0300 && !nocrtc && !vbemode) {
237
	    info->var.reserved[2] != 0xdeadbeef) {
238
255
239
		mytask->regs.ebx |= 0x0800; /* use CRTC data */
256
		mytask->regs.ebx |= 0x0800; /* use CRTC data */
240
		crtc = kmalloc(sizeof(struct vesafb_crtc_info_block), GFP_KERNEL);
257
		crtc = kmalloc(sizeof(struct vesafb_crtc_info_block), GFP_KERNEL);
241
	
258
	
242
		if (!crtc) {
259
		if (!crtc) {
243
			err = -ENOMEM;
260
			err = -ENOMEM;
244
			goto sp_end;		
261
			goto out;
245
		}
262
		}
246
		crtc->horiz_start = info->var.xres + info->var.right_margin;
263
		crtc->horiz_start = info->var.xres + info->var.right_margin;
247
		crtc->horiz_end	  = crtc->horiz_start + info->var.hsync_len;
264
		crtc->horiz_end	  = crtc->horiz_start + info->var.hsync_len;
Lines 277-287 Link Here
277
	vesafb_queue_task (mytask);
294
	vesafb_queue_task (mytask);
278
	vesafb_wait_for_task(mytask);
295
	vesafb_wait_for_task(mytask);
279
296
280
	if (mytask->regs.eax != 0x004f) {
297
	if ((mytask->regs.eax & 0xffff) != 0x004f) {
281
		printk(KERN_ERR "vesafb: mode switch failed (eax: 0x%lx)\n", mytask->regs.eax);
298
		printk(KERN_ERR "vesafb: mode switch failed (eax: 0x%lx)\n", mytask->regs.eax);
282
		err = -EINVAL;
299
		err = -EINVAL;
283
		goto sp_end;
300
		goto out;
284
	}
301
	}
302
303
	/* the VBE mode number is valid only the first time the mode is set */
304
	if (vbemode)
305
		vbemode = 0;
285
	
306
	
286
	if (vbe_ib.capabilities & VESAFB_CAP_CAN_SWITCH_DAC && mode->bits_per_pixel <= 8) {
307
	if (vbe_ib.capabilities & VESAFB_CAP_CAN_SWITCH_DAC && mode->bits_per_pixel <= 8) {
287
		mytask->done = 0;
308
		mytask->done = 0;
Lines 304-323 Link Here
304
		
325
		
305
	info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
326
	info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
306
	info->fix.line_length = mode->bytes_per_scan_line;
327
	info->fix.line_length = mode->bytes_per_scan_line;
307
	par->vbe_mode = info->var.reserved[0];
328
	par->vbe_mode = mode->mode_id;
308
329
309
	DPRINTK("set new mode %dx%d-%d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
330
	DPRINTK("set new mode %dx%d-%d (0x%x)\n", info->var.xres, info->var.yres, info->var.bits_per_pixel, mode->mode_id);
310
331
311
sp_end:
332
out:	if (crtc != NULL)
312
	if (crtc != NULL)
313
		kfree(crtc);
333
		kfree(crtc);
314
	kfree(mytask);
334
	kfree(mytask);
315
335
316
	return err;
336
	return err;
317
}
337
}
318
338
319
void vesafb_setup_var(struct fb_var_screeninfo *var, struct vesafb_mode_info_block *mode)
339
static void vesafb_setup_var(struct fb_var_screeninfo *var, struct fb_info *info, 
340
			     struct vesafb_mode_info_block *mode)
320
{
341
{
342
	var->xres = mode->x_res;
343
	var->yres = mode->y_res;
344
	var->xres_virtual = mode->x_res;
345
	var->yres_virtual = info->fix.smem_len / mode->bytes_per_scan_line;
346
	var->xoffset = 0;
347
	var->yoffset = 0;
348
	var->bits_per_pixel = mode->bits_per_pixel;
349
321
	if (var->bits_per_pixel == 15)
350
	if (var->bits_per_pixel == 15)
322
		var->bits_per_pixel = 16;
351
		var->bits_per_pixel = 16;
323
352
Lines 362-368 Link Here
362
	}
391
	}
363
}
392
}
364
393
365
int inline vesafb_check_limits(struct fb_var_screeninfo *var, struct fb_info *info)
394
static int inline vesafb_check_limits(struct fb_var_screeninfo *var, struct fb_info *info)
366
{	
395
{	
367
	if (mon_limits)
396
	if (mon_limits)
368
		return fb_validate_mode(var, info);
397
		return fb_validate_mode(var, info);
Lines 370-428 Link Here
370
		return 0;
399
		return 0;
371
}
400
}
372
401
373
int vesafb_find_vbe_mode(int xres, int yres, int bpp, unsigned char flags)
402
static int vesafb_find_vbe_mode(int xres, int yres, int bpp, unsigned char flags)
374
{
403
{
375
	int match = -1;
404
	int i, match = -1, h = 0, d = 0x7fffffff;
376
	int i;
377
	
405
	
378
	DPRINTK("looking for mode: %dx%d-%d\n", xres, yres, bpp);
379
380
	/* first try to find the exact mode the user wants to set.. */
381
	for (i = 0; i < vbe_modes_cnt; i++) {
406
	for (i = 0; i < vbe_modes_cnt; i++) {
382
407
383
		if (vbe_modes[i].x_res == xres && vbe_modes[i].y_res == yres) {
408
		h = abs(vbe_modes[i].x_res - xres) + abs(vbe_modes[i].y_res - yres) + 
384
	
409
		    (bpp - vbe_modes[i].bits_per_pixel);
385
			int h = bpp - vbe_modes[i].bits_per_pixel;
386
			
387
			/* ok, we've got an exact match */
388
			if (h == 0)
389
				return i;
390
					
391
			if (match == -1 || (bpp - vbe_modes[match].bits_per_pixel) > h)
392
				match = i;
393
		}
394
	}
395
	
396
	/* .. and if this fails look for similar modes */
397
	if (match == -1 && flags) {
398
	
399
		unsigned int min = 0xffffffff; /* just a big number */
400
		unsigned int d;
401
		
402
		DPRINTK("mode not found (1st pass)\n"); 
403
			
404
		for (i = 0; i < vbe_modes_cnt; i++) {
405
410
406
			if (vbe_modes[i].y_res < yres || vbe_modes[i].x_res < xres)
411
		if (h == 0)
407
				continue;
412
			return i;
408
413
409
			d = vbe_modes[i].y_res - yres + vbe_modes[i].x_res - xres;
414
		if (h < d) {
410
					
415
			d = h;
411
			if (d < min) {
416
			match = i;
412
				min = d;
413
				match = i;
414
			}
415
		
416
			if (d == min && (bpp - vbe_modes[match].bits_per_pixel) > 
417
	  		    (bpp - vbe_modes[i].bits_per_pixel))
418
				match = i;
419
		}
417
		}
420
	}
418
	}
421
419
420
	if (!(flags & VESAFB_NEED_EXACT_DEPTH) && d <= 24)
421
		return match;
422
423
	if (flags & VESAFB_NEED_EXACT_RES)
424
		return -1;
425
422
	return match;
426
	return match;
423
}
427
}
424
428
425
int vesafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
429
static int vesafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
426
{
430
{
427
	int match = -1;
431
	int match = -1;
428
	
432
	
Lines 433-453 Link Here
433
	if (var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))
437
	if (var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))
434
		return -EINVAL;
438
		return -EINVAL;
435
	
439
	
436
	match = vesafb_find_vbe_mode(var->xres, var->yres, var->bits_per_pixel, (vbe_ib.vbe_version >= 0x300) ? 1 : 0);
440
	match = vesafb_find_vbe_mode(var->xres, var->yres, var->bits_per_pixel, VESAFB_NEED_EXACT_RES);
437
441
438
	if (match == -1) {
442
	if (match == -1) {
439
		printk(KERN_ERR "vesafb: mode %dx%d-%d@%d not found\n", var->xres, var->yres, var->bits_per_pixel,
443
		printk(KERN_ERR "vesafb: mode %dx%d-%d@%d not found\n", var->xres, var->yres, var->bits_per_pixel,
440
				(int)(PICOS2KHZ(info->var.pixclock) /
444
				(int)(PICOS2KHZ(info->var.pixclock) /
441
				((info->var.xres + info->var.right_margin + info->var.hsync_len + info->var.left_margin) *
445
				((info->var.xres + info->var.right_margin + info->var.hsync_len + info->var.left_margin) *
442
				(info->var.yres + info->var.lower_margin + info->var.vsync_len + info->var.upper_margin))) * 1000);
446
				(info->var.yres + info->var.lower_margin + info->var.vsync_len + info->var.upper_margin))) * 1000);
443
		var->reserved[0] = 0xffff;
444
		return -EINVAL;
447
		return -EINVAL;
445
	} else {
448
	} else {
446
		var->bits_per_pixel = vbe_modes[match].bits_per_pixel;
449
		var->bits_per_pixel = vbe_modes[match].bits_per_pixel;
447
		var->reserved[0] = (u32)vbe_modes[match].mode_id;
450
		vesafb_setup_var(var, info, &vbe_modes[match]);
448
		var->reserved[1] = (u32)(&vbe_modes[match]);
449
		var->reserved[2] = 0x0;
450
		vesafb_setup_var(var, &vbe_modes[match]);
451
	
451
	
452
		DPRINTK("found mode 0x%x (%dx%d-%dbpp)\n",
452
		DPRINTK("found mode 0x%x (%dx%d-%dbpp)\n",
453
			vbe_modes[match].mode_id, vbe_modes[match].x_res, vbe_modes[match].y_res, 
453
			vbe_modes[match].mode_id, vbe_modes[match].x_res, vbe_modes[match].y_res, 
Lines 589-597 Link Here
589
{
589
{
590
	struct vesafb_task *mytask;
590
	struct vesafb_task *mytask;
591
	u16 *mode = 0;
591
	u16 *mode = 0;
592
	int off = 0;
592
	int i, off = 0;
593
	int i;
593
594
	
595
	vesafb_create_task (mytask);
594
	vesafb_create_task (mytask);
596
	mytask->regs.eax = 0x4f00;
595
	mytask->regs.eax = 0x4f00;
597
	mytask->type = VESAFB_TASK_GETVBE_IB;
596
	mytask->type = VESAFB_TASK_GETVBE_IB;
Lines 605-611 Link Here
605
		return 1;
604
		return 1;
606
	}
605
	}
607
	
606
	
608
	if (mytask->regs.eax != 0x004F) {
607
	if ((mytask->regs.eax & 0xffff) != 0x004f) {
609
		printk(KERN_ERR "vesafb: Getting mode info block failed (eax=0x%x)\n",(u32)mytask->regs.eax);
608
		printk(KERN_ERR "vesafb: Getting mode info block failed (eax=0x%x)\n",(u32)mytask->regs.eax);
610
		kfree(mytask);
609
		kfree(mytask);
611
		return 1;	
610
		return 1;	
Lines 660-666 Link Here
660
	vesafb_queue_task(mytask);
659
	vesafb_queue_task(mytask);
661
	vesafb_wait_for_task(mytask);
660
	vesafb_wait_for_task(mytask);
662
661
663
	if (mytask->regs.eax != 0x004f || mytask->regs.es < 0xc000) {
662
	if ((mytask->regs.eax & 0xffff) != 0x004f || mytask->regs.es < 0xc000) {
664
		pmi_setpal = ypan = 0;
663
		pmi_setpal = ypan = 0;
665
	} else {
664
	} else {
666
		printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n", (u16)mytask->regs.es, (u16)mytask->regs.edi);
665
		printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n", (u16)mytask->regs.es, (u16)mytask->regs.edi);
Lines 689-695 Link Here
689
	}
688
	}
690
689
691
	if (noedid || vbe_ib.vbe_version < 0x0300)
690
	if (noedid || vbe_ib.vbe_version < 0x0300)
692
		goto vi_1;
691
		goto set_monspecs;
693
	
692
	
694
	mytask->regs.eax = 0x4f15;
693
	mytask->regs.eax = 0x4f15;
695
	mytask->regs.ebx = 0;
694
	mytask->regs.ebx = 0;
Lines 699-706 Link Here
699
	vesafb_queue_task(mytask);
698
	vesafb_queue_task(mytask);
700
	vesafb_wait_for_task(mytask);
699
	vesafb_wait_for_task(mytask);
701
700
702
	if (mytask->regs.eax != 0x004f)
701
	if ((mytask->regs.eax & 0xffff) != 0x004f)
703
		goto vi_1;
702
		goto set_monspecs;
704
703
705
	if ((mytask->regs.ebx & 0x3) == 3) {
704
	if ((mytask->regs.ebx & 0x3) == 3) {
706
		printk(KERN_INFO "vesafb: hardware supports both DCC1 and DCC2 transfers\n");
705
		printk(KERN_INFO "vesafb: hardware supports both DCC1 and DCC2 transfers\n");
Lines 710-716 Link Here
710
		printk(KERN_INFO "vesafb: hardware supports DCC1 transfers\n");
709
		printk(KERN_INFO "vesafb: hardware supports DCC1 transfers\n");
711
	} else {
710
	} else {
712
		printk(KERN_INFO "vesafb: hardware doesn't support DCC transfers\n");
711
		printk(KERN_INFO "vesafb: hardware doesn't support DCC transfers\n");
713
		goto vi_1;
712
		goto set_monspecs;
714
	}
713
	}
715
	
714
	
716
	mytask->regs.eax = 0x4f15;
715
	mytask->regs.eax = 0x4f15;
Lines 722-728 Link Here
722
	vesafb_queue_task(mytask);
721
	vesafb_queue_task(mytask);
723
	vesafb_wait_for_task(mytask);
722
	vesafb_wait_for_task(mytask);
724
723
725
	if (mytask->regs.eax == 0x004F) {
724
	if ((mytask->regs.eax & 0xffff) == 0x004f) {
726
725
727
		mon_limits = !fb_get_monitor_limits(mytask->res, &info->monspecs);
726
		mon_limits = !fb_get_monitor_limits(mytask->res, &info->monspecs);
728
727
Lines 735-741 Link Here
735
	}
734
	}
736
	kfree(mytask->res);
735
	kfree(mytask->res);
737
	
736
	
738
vi_1:
737
set_monspecs:
739
	if (maxclk)
738
	if (maxclk)
740
		info->monspecs.dclkmax = maxclk * 1000000;
739
		info->monspecs.dclkmax = maxclk * 1000000;
741
740
Lines 761-773 Link Here
761
	return 0;
760
	return 0;
762
}
761
}
763
762
763
static int __init decode_mode(u32 *xres, u32 *yres, u32 *bpp, u32 *refresh)
764
{
765
	int len = strlen(mode_option), i, err = 0;
766
	u8 res_specified = 0, bpp_specified = 0, refresh_specified = 0, 
767
	   yres_specified = 0;
768
769
	for (i = len-1; i >= 0; i--) {
770
 		switch (mode_option[i]) {
771
		case '@':
772
    			len = i;
773
    			if (!refresh_specified && !bpp_specified &&
774
			    !yres_specified) {
775
				*refresh = simple_strtoul(&mode_option[i+1], NULL, 0);
776
				refresh_specified = 1;
777
			} else
778
				goto out;
779
		    	break;
780
		case '-':
781
			len = i;
782
		    	if (!bpp_specified && !yres_specified) {
783
			    	*bpp = simple_strtoul(&mode_option[i+1], NULL, 0);
784
				bpp_specified = 1;
785
		    	} else
786
				goto out;
787
		    	break;
788
		case 'x':
789
			if (!yres_specified) {
790
				*yres = simple_strtoul(&mode_option[i+1], NULL, 0);
791
				yres_specified = 1;
792
		    	} else
793
				goto out;
794
		    	break;
795
		case '0'...'9':
796
			break;
797
		default:
798
			goto out;
799
	    	}
800
	}
801
802
	if (i < 0 && yres_specified) {
803
		*xres = simple_strtoul(mode_option, NULL, 0);
804
	   	res_specified = 1;
805
	}
806
807
out:	if (!res_specified || !yres_specified) {
808
		printk(KERN_ERR "vesafb: invalid resolution, %s not specified\n",
809
				(!res_specified) ? "width" : "height");
810
		err = -EINVAL;
811
	}
812
813
	return err;
814
}
815
816
static int __init vesafb_init_set_mode(struct fb_info *info)
817
{
818
	char buf[32];
819
	int i, modeid, refresh = 0;
820
	u8 refresh_specified = 0;
821
822
	if (!mode_option)
823
		mode_option = CONFIG_FB_VESA_DEFAULT_MODE;
824
825
	if (vbemode > 0) {
826
		for (i = 0; i < vbe_modes_cnt; i++) {
827
			if (vbe_modes[i].mode_id == vbemode) {
828
				info->var.vmode = FB_VMODE_NONINTERLACED;
829
				info->var.sync = FB_SYNC_VERT_HIGH_ACT;
830
				vesafb_setup_var(&info->var, info, &vbe_modes[i]);
831
				fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &info->var, info);
832
				return i;
833
			}
834
		}
835
836
		printk(KERN_INFO "specified VBE mode %d not found\n",vbemode);
837
	}
838
839
	if (decode_mode(&info->var.xres, &info->var.yres, 
840
			&info->var.bits_per_pixel, &refresh))
841
		return -EINVAL;
842
843
	if (refresh)
844
		refresh_specified = 1;
845
	else	
846
		refresh = 60;
847
	
848
	modeid = vesafb_find_vbe_mode(info->var.xres, info->var.yres, info->var.bits_per_pixel, 0);
849
850
	if (modeid == -1) {
851
		return -EINVAL;	
852
	} else {
853
		info->var.vmode = FB_VMODE_NONINTERLACED;
854
		info->var.sync = FB_SYNC_VERT_HIGH_ACT;
855
		vesafb_setup_var(&info->var, info, &vbe_modes[modeid]);
856
	}
857
858
	if (gtf)
859
		goto timings_gtf;
860
861
	sprintf(buf, "%dx%d-%d@%d", info->var.xres, info->var.yres, info->var.bits_per_pixel, refresh);
862
	i = fb_find_mode(&info->var, info, buf, vesa_modes, VESA_MODEDB_SIZE, NULL, 0);
863
	DPRINTK("fb_find_mode returned %d\n", i);
864
865
	if (i == 1 || (i == 2 && vbe_ib.vbe_version < 0x0300))
866
		return modeid;
867
868
	if (edid_modes != NULL && !gtf) {
869
		DPRINTK("looking for EDID modes\n");
870
		
871
		for (i = 0; i < edid_modes_cnt; i++) {
872
873
			if (edid_modes[i].xres == info->var.xres && 
874
			    edid_modes[i].yres == info->var.yres && 
875
			    abs(edid_modes[i].refresh - refresh) < 5) {
876
877
				info->var.pixclock = edid_modes[i].pixclock;
878
			    	info->var.left_margin = edid_modes[i].left_margin;
879
				info->var.right_margin = edid_modes[i].right_margin;
880
				info->var.upper_margin = edid_modes[i].upper_margin;
881
				info->var.lower_margin = edid_modes[i].lower_margin;
882
				info->var.hsync_len = edid_modes[i].hsync_len;
883
				info->var.vsync_len = edid_modes[i].vsync_len;
884
				info->var.sync = edid_modes[i].sync;
885
				info->var.vmode = edid_modes[i].vmode;
886
				DPRINTK("using EDID-provided mode\n");
887
				return modeid;
888
			}
889
		}
890
	}
891
892
timings_gtf:
893
	if (refresh_specified)
894
		i = FB_VSYNCTIMINGS;
895
	else
896
		i = FB_MAXTIMINGS;
897
		
898
	if (vbe_ib.vbe_version < 0x0300) { 
899
		i = FB_VSYNCTIMINGS | FB_IGNOREMON;
900
		refresh = 60;
901
	} 
902
	
903
	if (!mon_limits)
904
		i |= FB_IGNOREMON;
905
	
906
	if (!fb_get_mode(i, refresh, &info->var, info))
907
		return modeid;
908
909
	printk(KERN_WARNING "vesafb: trying maximum allowed refresh rate\n");
910
911
	if (i & FB_VSYNCTIMINGS && refresh > 60 && mon_limits) {
912
		if (!fb_get_mode(FB_MAXTIMINGS, refresh, &info->var, info))
913
			return modeid;
914
	}
915
916
	printk(KERN_WARNING "vesafb: using default BIOS refresh rate\n");
917
	vbemode = vbe_modes[modeid].mode_id;
918
919
	return modeid;
920
}
921
764
static int __init vesafb_probe(struct device *device)
922
static int __init vesafb_probe(struct device *device)
765
{
923
{
766
	char entry[16];
924
	char entry[16];
767
	struct platform_device *dev = to_platform_device(device);
925
	struct platform_device *dev = to_platform_device(device);
768
	struct fb_info *info;
926
	struct fb_info *info;
769
	int err = 0, i;
927
	int err = 0, i;
770
928
	
771
	vesafb_info = info = framebuffer_alloc(sizeof(struct vesafb_par) + sizeof(u32) * 256, &dev->dev);
929
	vesafb_info = info = framebuffer_alloc(sizeof(struct vesafb_par) + sizeof(u32) * 256, &dev->dev);
772
	
930
	
773
	if (!info)
931
	if (!info)
Lines 776-793 Link Here
776
	if (vesafb_pid)
934
	if (vesafb_pid)
777
		vesafb_serv_thread = find_task_by_pid(vesafb_pid);
935
		vesafb_serv_thread = find_task_by_pid(vesafb_pid);
778
	else {
936
	else {
779
		printk(KERN_ERR "vesafb: vesafb thread not running - returning..\n");
937
		printk(KERN_ERR "vesafb: vesafb thread not running\n");
780
		framebuffer_release(info);
938
		framebuffer_release(info);
781
		return -EINVAL;
939
		return -EINVAL;
782
	}
940
	}
783
941
784
	if (vesafb_vbe_init(info)) {
942
	if (vesafb_vbe_init(info)) {
785
		printk(KERN_ERR "vesafb: vbe_init failed - returning..\n");
943
		printk(KERN_ERR "vesafb: vbe_init failed\n");
786
		err = -EINVAL;
944
		err = -EINVAL;
787
		goto pr_err;
945
		goto out;
788
	}
946
	}
789
947
790
	vesafb_fix.smem_len = vbe_ib.total_memory * 65536;
948
	vesafb_fix.smem_len  = vbe_ib.total_memory * 65536;
791
	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
949
	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
792
	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
950
	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
793
951
Lines 811-972 Link Here
811
969
812
	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
970
	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
813
		err = -ENXIO;
971
		err = -ENXIO;
814
		goto pr_err;
972
		goto out;
815
	}	
973
	}	
816
974
817
	if (!mode_option)
975
	i = vesafb_init_set_mode(info);
818
		mode_option = CONFIG_FB_VESA_DEFAULT_MODE;
976
	if (i < 0)
819
977
		goto out_cmap;
820
	if (vbemode > 0) {
821
		for (i = 0; i < vbe_modes_cnt; i++) {
822
			if (vbe_modes[i].mode_id == vbemode) {
823
				info->var.xres = vbe_modes[i].x_res;
824
				info->var.yres = vbe_modes[i].y_res;
825
				info->var.xres_virtual = vbe_modes[i].x_res;
826
				info->var.xoffset = 0;
827
				info->var.yoffset = 0;
828
				info->var.bits_per_pixel = vbe_modes[i].bits_per_pixel;
829
				info->var.reserved[0] = (u32)vbe_modes[i].mode_id;
830
				info->var.reserved[1] = (u32)(&vbe_modes[i]);
831
				info->var.reserved[2] = 0xdeadbeef;
832
				info->var.vmode = FB_VMODE_NONINTERLACED;
833
				info->var.sync = FB_SYNC_VERT_HIGH_ACT;
834
				vesafb_setup_var(&info->var, &vbe_modes[i]);
835
				fb_get_mode(FB_MAXTIMINGS, 60, &info->var, info);
836
				goto pr_end;
837
			}
838
		}
839
978
840
		printk(KERN_INFO "specified VBE mode %d not found\n",vbemode);
979
	info->fix.smem_start = vbe_modes[i].phys_base_ptr;
841
	}
842
843
	if (gtf)
844
		goto pr_manual;
845
846
	i = fb_find_mode(&info->var, info, mode_option, vesa_modes, 33, NULL, 0);
847
848
	DPRINTK("fb_find_mode returned %d\n", i);
849
	
850
	if (i == 0 || i >= 3) 
851
pr_manual:	
852
	{
853
		int match = -1;
854
		unsigned int len = strlen(mode_option);
855
		unsigned int xres = 0, yres = 0, bpp = 8, refresh = 60;
856
		unsigned char res_specified = 0, bpp_specified = 0, refresh_specified = 0, yres_specified = 0;
857
	
858
		for (i = len-1; i >= 0; i--) {
859
	    		switch (mode_option[i]) {
860
				case '@':
861
		    			len = i;
862
		    			if (!refresh_specified && !bpp_specified &&
863
					    !yres_specified) {
864
						refresh = simple_strtoul(&mode_option[i+1], NULL, 0);
865
						refresh_specified = 1;
866
		    			} else
867
						goto pr_modedone;
868
		    			break;
869
				case '-':
870
		    			len = i;
871
		    			if (!bpp_specified && !yres_specified) {
872
					    	bpp = simple_strtoul(&mode_option[i+1], NULL, 0);
873
						bpp_specified = 1;
874
		    			} else
875
						goto pr_modedone;
876
		    			break;
877
				case 'x':
878
		    			if (!yres_specified) {
879
						yres = simple_strtoul(&mode_option[i+1], NULL, 0);
880
						yres_specified = 1;
881
		    			} else
882
						goto pr_modedone;
883
		    			break;
884
				case '0'...'9':
885
		    			break;
886
				default:
887
		    			goto pr_modedone;
888
	    		}
889
		}
890
891
		if (i < 0 && yres_specified) {
892
	    		xres = simple_strtoul(mode_option, NULL, 0);
893
	    		res_specified = 1;
894
		}
895
896
pr_modedone:	if (!res_specified || !yres_specified) {
897
			printk(KERN_ERR "vesafb: invalid resolution, %s not specified\n",
898
					(!res_specified) ? "width" : "height");
899
			err = -EINVAL;
900
			goto pr_err1;
901
		}
902
	
903
		match = vesafb_find_vbe_mode(xres, yres, bpp, (vbe_ib.vbe_version >= 0x300) ? 1 : 0);
904
		
905
		if (match == -1) {
906
			printk(KERN_ERR "vesafb: no matching VBE mode found\n");
907
			err = -EINVAL;
908
			goto pr_err1;
909
		}
910
		
911
		info->var.xres = xres;
912
		info->var.yres = yres;
913
		info->var.xres_virtual = xres;
914
		info->var.xoffset = 0;
915
		info->var.yoffset = 0;
916
		info->var.bits_per_pixel = vbe_modes[match].bits_per_pixel;
917
		info->var.reserved[0] = (u32)vbe_modes[match].mode_id;
918
		info->var.reserved[1] = (u32)(&vbe_modes[match]);
919
		info->var.reserved[2] = 0x0;
920
		info->var.vmode = FB_VMODE_NONINTERLACED;
921
		info->var.sync = FB_SYNC_VERT_HIGH_ACT;
922
		vesafb_setup_var(&info->var, &vbe_modes[match]);
923
924
		if (edid_modes != NULL && !gtf) {
925
		
926
			DPRINTK("looking for EDID modes\n");
927
		
928
			for (i = 0; i < edid_modes_cnt; i++) {
929
930
				if (edid_modes[i].xres == xres && edid_modes[i].yres == yres && 
931
				    edid_modes[i].refresh - refresh < 5 && edid_modes[i].refresh - refresh > -5) {
932
933
					info->var.pixclock = edid_modes[i].pixclock;
934
				    	info->var.left_margin = edid_modes[i].left_margin;
935
					info->var.right_margin = edid_modes[i].right_margin;
936
					info->var.upper_margin = edid_modes[i].upper_margin;
937
					info->var.lower_margin = edid_modes[i].lower_margin;
938
					info->var.hsync_len = edid_modes[i].hsync_len;
939
					info->var.vsync_len = edid_modes[i].vsync_len;
940
					info->var.sync = edid_modes[i].sync;
941
					info->var.vmode = edid_modes[i].vmode;
942
					DPRINTK("using EDID-provided mode\n");
943
					goto pr_end;
944
				}
945
			}
946
		}
947
		
948
		if (refresh_specified)
949
			i = FB_VSYNCTIMINGS;
950
		else
951
			i = FB_MAXTIMINGS;
952
			
953
		if (vbe_ib.vbe_version < 0x0300) { 
954
			i = FB_VSYNCTIMINGS | FB_IGNOREMON;
955
			refresh = 60;
956
		} 
957
	
958
		if (!mon_limits)
959
			i |= FB_IGNOREMON;
960
		
961
		if (fb_get_mode(i, refresh, &info->var, info) != 0) {
962
			printk(KERN_ERR "vesafb: fb_get_mode failed, try a different refresh rate.\n");
963
			err = -EINVAL;
964
			goto pr_err1;
965
		}
966
	}
967
pr_end:
968
	info->var.yres_virtual = info->fix.smem_len / ((struct vesafb_mode_info_block*)info->var.reserved[1])->bytes_per_scan_line;
969
	info->fix.smem_start = ((struct vesafb_mode_info_block*)info->var.reserved[1])->phys_base_ptr;
970
980
971
	if (ypan && info->var.yres_virtual > info->var.yres) {
981
	if (ypan && info->var.yres_virtual > info->var.yres) {
972
		printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
982
		printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
Lines 993-999 Link Here
993
		       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
1003
		       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
994
			info->fix.smem_len, info->fix.smem_start);
1004
			info->fix.smem_len, info->fix.smem_start);
995
		err = -EIO;
1005
		err = -EIO;
996
		goto pr_err2;
1006
		goto out_mem;
997
 	}
1007
 	}
998
1008
999
	/* request failure does not faze us, as vgacon probably has this
1009
	/* request failure does not faze us, as vgacon probably has this
Lines 1016-1022 Link Here
1016
	if (register_framebuffer(info) < 0) {
1026
	if (register_framebuffer(info) < 0) {
1017
		printk(KERN_ERR "vesafb: failed to register framebuffer device\n");
1027
		printk(KERN_ERR "vesafb: failed to register framebuffer device\n");
1018
		err = -EINVAL;
1028
		err = -EINVAL;
1019
		goto pr_err2;
1029
		goto out_mem;
1020
	}
1030
	}
1021
1031
1022
  	printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1032
  	printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
Lines 1035-1045 Link Here
1035
	fb_destroy_modedb(edid_modes);
1045
	fb_destroy_modedb(edid_modes);
1036
	return 0;
1046
	return 0;
1037
1047
1038
pr_err2:
1048
out_mem:
1039
	release_mem_region(info->fix.smem_start, info->fix.smem_len);
1049
	release_mem_region(info->fix.smem_start, info->fix.smem_len);
1040
pr_err1:
1050
out_cmap:
1041
	fb_dealloc_cmap(&info->cmap);
1051
	fb_dealloc_cmap(&info->cmap);
1042
pr_err:	
1052
out:	
1043
	framebuffer_release(info);
1053
	framebuffer_release(info);
1044
	vesafb_info = NULL;
1054
	vesafb_info = NULL;
1045
1055
Lines 1145-1149 Link Here
1145
#endif /* MODULE */
1155
#endif /* MODULE */
1146
1156
1147
MODULE_LICENSE("GPL");
1157
MODULE_LICENSE("GPL");
1148
MODULE_AUTHOR("Micha³ Januszewski");
1158
MODULE_AUTHOR("Michal Januszewski");
1149
MODULE_DESCRIPTION("Framebuffer driver for VBE2.0-compliant graphic boards");
1159
MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphic boards");

Return to bug 61598