Enscript Output

extractedLnx/linux-2.6.38/drivers/video/cirrusfb.c_cirrusfb_set_par_foo.c

static int cirrusfb_set_par_foo(struct fb_info *info)
{
	struct cirrusfb_info *cinfo = info->par;
	struct fb_var_screeninfo *var = &info->var;
	u8 __iomem *regbase = cinfo->regbase;
	unsigned char tmp;
	int pitch;
	const struct cirrusfb_board_info_rec *bi;
	int hdispend, hsyncstart, hsyncend, htotal;
	int yres, vdispend, vsyncstart, vsyncend, vtotal;
	long freq;
	int nom, den, div;
	unsigned int control = 0, format = 0, threshold = 0;

	dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
	       var->xres, var->yres, var->bits_per_pixel);

	switch (var->bits_per_pixel) {
	case 1:
		info->fix.line_length = var->xres_virtual / 8;
		info->fix.visual = FB_VISUAL_MONO10;
		break;

	case 8:
		info->fix.line_length = var->xres_virtual;
		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
		break;

	case 16:
	case 24:
		info->fix.line_length = var->xres_virtual *
					var->bits_per_pixel >> 3;
		info->fix.visual = FB_VISUAL_TRUECOLOR;
		break;
	}
	info->fix.type = FB_TYPE_PACKED_PIXELS;

	init_vgachip(info);

	bi = &cirrusfb_board_info[cinfo->btype];

	hsyncstart = var->xres + var->right_margin;
	hsyncend = hsyncstart + var->hsync_len;
	htotal = (hsyncend + var->left_margin) / 8;
	hdispend = var->xres / 8;
	hsyncstart = hsyncstart / 8;
	hsyncend = hsyncend / 8;

	vdispend = var->yres;
	vsyncstart = vdispend + var->lower_margin;
	vsyncend = vsyncstart + var->vsync_len;
	vtotal = vsyncend + var->upper_margin;

	if (var->vmode & FB_VMODE_DOUBLE) {
		vdispend *= 2;
		vsyncstart *= 2;
		vsyncend *= 2;
		vtotal *= 2;
	} else if (var->vmode & FB_VMODE_INTERLACED) {
		vdispend = (vdispend + 1) / 2;
		vsyncstart = (vsyncstart + 1) / 2;
		vsyncend = (vsyncend + 1) / 2;
		vtotal = (vtotal + 1) / 2;
	}
	yres = vdispend;
	if (yres >= 1024) {
		vtotal /= 2;
		vsyncstart /= 2;
		vsyncend /= 2;
		vdispend /= 2;
	}

	vdispend -= 1;
	vsyncstart -= 1;
	vsyncend -= 1;
	vtotal -= 2;

	if (cinfo->multiplexing) {
		htotal /= 2;
		hsyncstart /= 2;
		hsyncend /= 2;
		hdispend /= 2;
	}

	htotal -= 5;
	hdispend -= 1;
	hsyncstart += 1;
	hsyncend += 1;

	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */

	/* if debugging is enabled, all parameters get output before writing */
	dev_dbg(info->device, "CRT0: %d\n", htotal);
	vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);

	dev_dbg(info->device, "CRT1: %d\n", hdispend);
	vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);

	dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
	vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);

	/*  + 128: Compatible read */
	dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
	vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
		 128 + ((htotal + 5) % 32));

	dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
	vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);

	tmp = hsyncend % 32;
	if ((htotal + 5) & 32)
		tmp += 128;
	dev_dbg(info->device, "CRT5: %d\n", tmp);
	vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);

	dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
	vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);

	tmp = 16;		/* LineCompare bit #9 */
	if (vtotal & 256)
		tmp |= 1;
	if (vdispend & 256)
		tmp |= 2;
	if (vsyncstart & 256)
		tmp |= 4;
	if ((vdispend + 1) & 256)
		tmp |= 8;
	if (vtotal & 512)
		tmp |= 32;
	if (vdispend & 512)
		tmp |= 64;
	if (vsyncstart & 512)
		tmp |= 128;
	dev_dbg(info->device, "CRT7: %d\n", tmp);
	vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);

	tmp = 0x40;		/* LineCompare bit #8 */
	if ((vdispend + 1) & 512)
		tmp |= 0x20;
	if (var->vmode & FB_VMODE_DOUBLE)
		tmp |= 0x80;
	dev_dbg(info->device, "CRT9: %d\n", tmp);
	vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);

	dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
	vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);

	dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);

	dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
	vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);

	dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
	vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);

	dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
	vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);

	dev_dbg(info->device, "CRT18: 0xff\n");
	vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);

	tmp = 0;
	if (var->vmode & FB_VMODE_INTERLACED)
		tmp |= 1;
	if ((htotal + 5) & 64)
		tmp |= 16;
	if ((htotal + 5) & 128)
		tmp |= 32;
	if (vtotal & 256)
		tmp |= 64;
	if (vtotal & 512)
		tmp |= 128;

	dev_dbg(info->device, "CRT1a: %d\n", tmp);
	vga_wcrt(regbase, CL_CRT1A, tmp);

	freq = PICOS2KHZ(var->pixclock);
	if (var->bits_per_pixel == 24)
		if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64)
			freq *= 3;
	if (cinfo->multiplexing)
		freq /= 2;
	if (cinfo->doubleVCLK)
		freq *= 2;

	bestclock(freq, &nom, &den, &div);

	dev_dbg(info->device, "VCLK freq: %ld kHz  nom: %d  den: %d  div: %d\n",
		freq, nom, den, div);

	/* set VCLK0 */
	/* hardware RefClock: 14.31818 MHz */
	/* formula: VClk = (OSC * N) / (D * (1+P)) */
	/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */

	if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 ||
	    cinfo->btype == BT_SD64) {
		/* if freq is close to mclk or mclk/2 select mclk
		 * as clock source
		 */
		int divMCLK = cirrusfb_check_mclk(info, freq);
		if (divMCLK)
			nom = 0;
		cirrusfb_set_mclk_as_source(info, divMCLK);
	}
	if (is_laguna(cinfo)) {
		long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
		unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
		unsigned short tile_control;

		if (cinfo->btype == BT_LAGUNAB) {
			tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
			tile_control &= ~0x80;
			fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
		}

		fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
		fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
		control = fb_readw(cinfo->laguna_mmio + 0x402);
		threshold = fb_readw(cinfo->laguna_mmio + 0xea);
		control &= ~0x6800;
		format = 0;
		threshold &= 0xffc0 & 0x3fbf;
	}
	if (nom) {
		tmp = den << 1;
		if (div != 0)
			tmp |= 1;
		/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
		if ((cinfo->btype == BT_SD64) ||
		    (cinfo->btype == BT_ALPINE) ||
		    (cinfo->btype == BT_GD5480))
			tmp |= 0x80;

		/* Laguna chipset has reversed clock registers */
		if (is_laguna(cinfo)) {
			vga_wseq(regbase, CL_SEQRE, tmp);
			vga_wseq(regbase, CL_SEQR1E, nom);
		} else {
			vga_wseq(regbase, CL_SEQRE, nom);
			vga_wseq(regbase, CL_SEQR1E, tmp);
		}
	}

	if (yres >= 1024)
		/* 1280x1024 */
		vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
	else
		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
		 * address wrap, no compat. */
		vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);

	/* don't know if it would hurt to also program this if no interlaced */
	/* mode is used, but I feel better this way.. :-) */
	if (var->vmode & FB_VMODE_INTERLACED)
		vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
	else
		vga_wcrt(regbase, VGA_CRTC_REGS, 0x00);	/* interlace control */

	/* adjust horizontal/vertical sync type (low/high), use VCLK3 */
	/* enable display memory & CRTC I/O address for color mode */
	tmp = 0x03 | 0xc;
	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
		tmp |= 0x40;
	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
		tmp |= 0x80;
	WGen(cinfo, VGA_MIS_W, tmp);

	/* text cursor on and start line */
	vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
	/* text cursor end line */
	vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);

	/******************************************************
	 *
	 * 1 bpp
	 *
	 */

	/* programming for different color depths */
	if (var->bits_per_pixel == 1) {
		dev_dbg(info->device, "preparing for 1 bit deep display\n");
		vga_wgfx(regbase, VGA_GFX_MODE, 0);	/* mode register */

		/* SR07 */
		switch (cinfo->btype) {
		case BT_SD64:
		case BT_PICCOLO:
		case BT_PICASSO:
		case BT_SPECTRUM:
		case BT_PICASSO4:
		case BT_ALPINE:
		case BT_GD5480:
			vga_wseq(regbase, CL_SEQR7,
				 cinfo->multiplexing ?
					bi->sr07_1bpp_mux : bi->sr07_1bpp);
			break;

		case BT_LAGUNA:
		case BT_LAGUNAB:
			vga_wseq(regbase, CL_SEQR7,
				vga_rseq(regbase, CL_SEQR7) & ~0x01);
			break;

		default:
			dev_warn(info->device, "unknown Board\n");
			break;
		}

		/* Extended Sequencer Mode */
		switch (cinfo->btype) {

		case BT_PICCOLO:
		case BT_SPECTRUM:
			/* evtl d0 bei 1 bit? avoid FIFO underruns..? */
			vga_wseq(regbase, CL_SEQRF, 0xb0);
			break;

		case BT_PICASSO:
			/* ## vorher d0 avoid FIFO underruns..? */
			vga_wseq(regbase, CL_SEQRF, 0xd0);
			break;

		case BT_SD64:
		case BT_PICASSO4:
		case BT_ALPINE:
		case BT_GD5480:
		case BT_LAGUNA:
		case BT_LAGUNAB:
			/* do nothing */
			break;

		default:
			dev_warn(info->device, "unknown Board\n");
			break;
		}

		/* pixel mask: pass-through for first plane */
		WGen(cinfo, VGA_PEL_MSK, 0x01);
		if (cinfo->multiplexing)
			/* hidden dac reg: 1280x1024 */
			WHDR(cinfo, 0x4a);
		else
			/* hidden dac: nothing */
			WHDR(cinfo, 0);
		/* memory mode: odd/even, ext. memory */
		vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
		/* plane mask: only write to first plane */
		vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
	}

	/******************************************************
	 *
	 * 8 bpp
	 *
	 */

	else if (var->bits_per_pixel == 8) {
		dev_dbg(info->device, "preparing for 8 bit deep display\n");
		switch (cinfo->btype) {
		case BT_SD64:
		case BT_PICCOLO:
		case BT_PICASSO:
		case BT_SPECTRUM:
		case BT_PICASSO4:
		case BT_ALPINE:
		case BT_GD5480:
			vga_wseq(regbase, CL_SEQR7,
				  cinfo->multiplexing ?
					bi->sr07_8bpp_mux : bi->sr07_8bpp);
			break;

		case BT_LAGUNA:
		case BT_LAGUNAB:
			vga_wseq(regbase, CL_SEQR7,
				vga_rseq(regbase, CL_SEQR7) | 0x01);
			threshold |= 0x10;
			break;

		default:
			dev_warn(info->device, "unknown Board\n");
			break;
		}

		switch (cinfo->btype) {
		case BT_PICCOLO:
		case BT_PICASSO:
		case BT_SPECTRUM:
			/* Fast Page-Mode writes */
			vga_wseq(regbase, CL_SEQRF, 0xb0);
			break;

		case BT_PICASSO4:
#ifdef CONFIG_ZORRO
			/* ### INCOMPLETE!! */
			vga_wseq(regbase, CL_SEQRF, 0xb8);
#endif
		case BT_ALPINE:
		case BT_SD64:
		case BT_GD5480:
		case BT_LAGUNA:
		case BT_LAGUNAB:
			/* do nothing */
			break;

		default:
			dev_warn(info->device, "unknown board\n");
			break;
		}

		/* mode register: 256 color mode */
		vga_wgfx(regbase, VGA_GFX_MODE, 64);
		if (cinfo->multiplexing)
			/* hidden dac reg: 1280x1024 */
			WHDR(cinfo, 0x4a);
		else
			/* hidden dac: nothing */
			WHDR(cinfo, 0);
	}

	/******************************************************
	 *
	 * 16 bpp
	 *
	 */

	else if (var->bits_per_pixel == 16) {
		dev_dbg(info->device, "preparing for 16 bit deep display\n");
		switch (cinfo->btype) {
		case BT_PICCOLO:
		case BT_SPECTRUM:
			vga_wseq(regbase, CL_SEQR7, 0x87);
			/* Fast Page-Mode writes */
			vga_wseq(regbase, CL_SEQRF, 0xb0);
			break;

		case BT_PICASSO:
			vga_wseq(regbase, CL_SEQR7, 0x27);
			/* Fast Page-Mode writes */
			vga_wseq(regbase, CL_SEQRF, 0xb0);
			break;

		case BT_SD64:
		case BT_PICASSO4:
		case BT_ALPINE:
			/* Extended Sequencer Mode: 256c col. mode */
			vga_wseq(regbase, CL_SEQR7,
					cinfo->doubleVCLK ? 0xa3 : 0xa7);
			break;

		case BT_GD5480:
			vga_wseq(regbase, CL_SEQR7, 0x17);
			/* We already set SRF and SR1F */
			break;

		case BT_LAGUNA:
		case BT_LAGUNAB:
			vga_wseq(regbase, CL_SEQR7,
				vga_rseq(regbase, CL_SEQR7) & ~0x01);
			control |= 0x2000;
			format |= 0x1400;
			threshold |= 0x10;
			break;

		default:
			dev_warn(info->device, "unknown Board\n");
			break;
		}

		/* mode register: 256 color mode */
		vga_wgfx(regbase, VGA_GFX_MODE, 64);
#ifdef CONFIG_PCI
		WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1);
#elif defined(CONFIG_ZORRO)
		/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
		WHDR(cinfo, 0xa0);	/* hidden dac reg: nothing special */
#endif
	}

	/******************************************************
	 *
	 * 24 bpp
	 *
	 */

	else if (var->bits_per_pixel == 24) {
		dev_dbg(info->device, "preparing for 24 bit deep display\n");
		switch (cinfo->btype) {
		case BT_PICCOLO:
		case BT_SPECTRUM:
			vga_wseq(regbase, CL_SEQR7, 0x85);
			/* Fast Page-Mode writes */
			vga_wseq(regbase, CL_SEQRF, 0xb0);
			break;

		case BT_PICASSO:
			vga_wseq(regbase, CL_SEQR7, 0x25);
			/* Fast Page-Mode writes */
			vga_wseq(regbase, CL_SEQRF, 0xb0);
			break;

		case BT_SD64:
		case BT_PICASSO4:
		case BT_ALPINE:
			/* Extended Sequencer Mode: 256c col. mode */
			vga_wseq(regbase, CL_SEQR7, 0xa5);
			break;

		case BT_GD5480:
			vga_wseq(regbase, CL_SEQR7, 0x15);
			/* We already set SRF and SR1F */
			break;

		case BT_LAGUNA:
		case BT_LAGUNAB:
			vga_wseq(regbase, CL_SEQR7,
				vga_rseq(regbase, CL_SEQR7) & ~0x01);
			control |= 0x4000;
			format |= 0x2400;
			threshold |= 0x20;
			break;

		default:
			dev_warn(info->device, "unknown Board\n");
			break;
		}

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

	/******************************************************
	 *
	 * unknown/unsupported bpp
	 *
	 */

	else
		dev_err(info->device,
			"What's this? requested color depth == %d.\n",
			var->bits_per_pixel);

	pitch = info->fix.line_length >> 3;
	vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
	tmp = 0x22;
	if (pitch & 0x100)
		tmp |= 0x10;	/* offset overflow bit */

	/* screen start addr #16-18, fastpagemode cycles */
	vga_wcrt(regbase, CL_CRT1B, tmp);

	/* screen start address bit 19 */
	if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
		vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);

	if (is_laguna(cinfo)) {
		tmp = 0;
		if ((htotal + 5) & 256)
			tmp |= 128;
		if (hdispend & 256)
			tmp |= 64;
		if (hsyncstart & 256)
			tmp |= 48;
		if (vtotal & 1024)
			tmp |= 8;
		if (vdispend & 1024)
			tmp |= 4;
		if (vsyncstart & 1024)
			tmp |= 3;

		vga_wcrt(regbase, CL_CRT1E, tmp);
		dev_dbg(info->device, "CRT1e: %d\n", tmp);
	}

	/* pixel panning */
	vga_wattr(regbase, CL_AR33, 0);

	/* [ EGS: SetOffset(); ] */
	/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
	AttrOn(cinfo);

	if (is_laguna(cinfo)) {
		/* no tiles */
		fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
		fb_writew(format, cinfo->laguna_mmio + 0xc0);
		fb_writew(threshold, cinfo->laguna_mmio + 0xea);
	}
	/* finally, turn on everything - turn off "FullBandwidth" bit */
	/* also, set "DotClock%2" bit where requested */
	tmp = 0x01;

/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
    if (var->vmode & FB_VMODE_CLOCK_HALVE)
	tmp |= 0x08;
*/

	vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
	dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);

#ifdef CIRRUSFB_DEBUG
	cirrusfb_dbg_reg_dump(info, NULL);
#endif

	return 0;
}

Generated by GNU enscript 1.6.4.