⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intelfbhw.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Flush the ring buffer if it's enabled. */	tmp = INREG(PRI_RING_LENGTH);	if (tmp & RING_ENABLE) {#if VERBOSE > 0		DBG_MSG("reset_state: ring was enabled\n");#endif		refresh_ring(dinfo);		intelfbhw_do_sync(dinfo);		DO_RING_IDLE();	}	OUTREG(PRI_RING_LENGTH, 0);	OUTREG(PRI_RING_HEAD, 0);	OUTREG(PRI_RING_TAIL, 0);	OUTREG(PRI_RING_START, 0);}/* Stop the 2D engine, and turn off the ring buffer. */void intelfbhw_2d_stop(struct intelfb_info *dinfo){#if VERBOSE > 0	DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n",		dinfo->accel, dinfo->ring_active);#endif	if (!dinfo->accel)		return;	dinfo->ring_active = 0;	reset_state(dinfo);}/* * Enable the ring buffer, and initialise the 2D engine. * It is assumed that the graphics engine has been stopped by previously * calling intelfb_2d_stop(). */void intelfbhw_2d_start(struct intelfb_info *dinfo){#if VERBOSE > 0	DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",		dinfo->accel, dinfo->ring_active);#endif	if (!dinfo->accel)		return;	/* Initialise the primary ring buffer. */	OUTREG(PRI_RING_LENGTH, 0);	OUTREG(PRI_RING_TAIL, 0);	OUTREG(PRI_RING_HEAD, 0);	OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);	OUTREG(PRI_RING_LENGTH,		((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |		RING_NO_REPORT | RING_ENABLE);	refresh_ring(dinfo);	dinfo->ring_active = 1;}/* 2D fillrect (solid fill or invert) */void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w,			   u32 h, u32 color, u32 pitch, u32 bpp, u32 rop){	u32 br00, br09, br13, br14, br16;#if VERBOSE > 0	DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "		"rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);#endif	br00 = COLOR_BLT_CMD;	br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));	br13 = (rop << ROP_SHIFT) | pitch;	br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);	br16 = color;	switch (bpp) {	case 8:		br13 |= COLOR_DEPTH_8;		break;	case 16:		br13 |= COLOR_DEPTH_16;		break;	case 32:		br13 |= COLOR_DEPTH_32;		br00 |= WRITE_ALPHA | WRITE_RGB;		break;	}	START_RING(6);	OUT_RING(br00);	OUT_RING(br13);	OUT_RING(br14);	OUT_RING(br09);	OUT_RING(br16);	OUT_RING(MI_NOOP);	ADVANCE_RING();#if VERBOSE > 0	DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,		dinfo->ring_tail, dinfo->ring_space);#endif}voidintelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,		    u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp){	u32 br00, br09, br11, br12, br13, br22, br23, br26;#if VERBOSE > 0	DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",		curx, cury, dstx, dsty, w, h, pitch, bpp);#endif	br00 = XY_SRC_COPY_BLT_CMD;	br09 = dinfo->fb_start;	br11 = (pitch << PITCH_SHIFT);	br12 = dinfo->fb_start;	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);	br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);	br23 = ((dstx + w) << WIDTH_SHIFT) |	       ((dsty + h) << HEIGHT_SHIFT);	br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);	switch (bpp) {	case 8:		br13 |= COLOR_DEPTH_8;		break;	case 16:		br13 |= COLOR_DEPTH_16;		break;	case 32:		br13 |= COLOR_DEPTH_32;		br00 |= WRITE_ALPHA | WRITE_RGB;		break;	}	START_RING(8);	OUT_RING(br00);	OUT_RING(br13);	OUT_RING(br22);	OUT_RING(br23);	OUT_RING(br09);	OUT_RING(br26);	OUT_RING(br11);	OUT_RING(br12);	ADVANCE_RING();}int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,			   u32 h, const u8* cdat, u32 x, u32 y, u32 pitch,			   u32 bpp){	int nbytes, ndwords, pad, tmp;	u32 br00, br09, br13, br18, br19, br22, br23;	int dat, ix, iy, iw;	int i, j;#if VERBOSE > 0	DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);#endif	/* size in bytes of a padded scanline */	nbytes = ROUND_UP_TO(w, 16) / 8;	/* Total bytes of padded scanline data to write out. */	nbytes = nbytes * h;	/*	 * Check if the glyph data exceeds the immediate mode limit.	 * It would take a large font (1K pixels) to hit this limit.	 */	if (nbytes > MAX_MONO_IMM_SIZE)		return 0;	/* Src data is packaged a dword (32-bit) at a time. */	ndwords = ROUND_UP_TO(nbytes, 4) / 4;	/*	 * Ring has to be padded to a quad word. But because the command starts	   with 7 bytes, pad only if there is an even number of ndwords	 */	pad = !(ndwords % 2);	tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;	br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;	br09 = dinfo->fb_start;	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);	br18 = bg;	br19 = fg;	br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);	br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);	switch (bpp) {	case 8:		br13 |= COLOR_DEPTH_8;		break;	case 16:		br13 |= COLOR_DEPTH_16;		break;	case 32:		br13 |= COLOR_DEPTH_32;		br00 |= WRITE_ALPHA | WRITE_RGB;		break;	}	START_RING(8 + ndwords);	OUT_RING(br00);	OUT_RING(br13);	OUT_RING(br22);	OUT_RING(br23);	OUT_RING(br09);	OUT_RING(br18);	OUT_RING(br19);	ix = iy = 0;	iw = ROUND_UP_TO(w, 8) / 8;	while (ndwords--) {		dat = 0;		for (j = 0; j < 2; ++j) {			for (i = 0; i < 2; ++i) {				if (ix != iw || i == 0)					dat |= cdat[iy*iw + ix++] << (i+j*2)*8;			}			if (ix == iw && iy != (h-1)) {				ix = 0;				++iy;			}		}		OUT_RING(dat);	}	if (pad)		OUT_RING(MI_NOOP);	ADVANCE_RING();	return 1;}/* HW cursor functions. */void intelfbhw_cursor_init(struct intelfb_info *dinfo){	u32 tmp;#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_init\n");#endif	if (dinfo->mobile || IS_I9XX(dinfo)) {		if (!dinfo->cursor.physical)			return;		tmp = INREG(CURSOR_A_CONTROL);		tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |			 CURSOR_MEM_TYPE_LOCAL |			 (1 << CURSOR_PIPE_SELECT_SHIFT));		tmp |= CURSOR_MODE_DISABLE;		OUTREG(CURSOR_A_CONTROL, tmp);		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);	} else {		tmp = INREG(CURSOR_CONTROL);		tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |			 CURSOR_ENABLE | CURSOR_STRIDE_MASK);		tmp = CURSOR_FORMAT_3C;		OUTREG(CURSOR_CONTROL, tmp);		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);		tmp = (64 << CURSOR_SIZE_H_SHIFT) |		      (64 << CURSOR_SIZE_V_SHIFT);		OUTREG(CURSOR_SIZE, tmp);	}}void intelfbhw_cursor_hide(struct intelfb_info *dinfo){	u32 tmp;#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_hide\n");#endif	dinfo->cursor_on = 0;	if (dinfo->mobile || IS_I9XX(dinfo)) {		if (!dinfo->cursor.physical)			return;		tmp = INREG(CURSOR_A_CONTROL);		tmp &= ~CURSOR_MODE_MASK;		tmp |= CURSOR_MODE_DISABLE;		OUTREG(CURSOR_A_CONTROL, tmp);		/* Flush changes */		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);	} else {		tmp = INREG(CURSOR_CONTROL);		tmp &= ~CURSOR_ENABLE;		OUTREG(CURSOR_CONTROL, tmp);	}}void intelfbhw_cursor_show(struct intelfb_info *dinfo){	u32 tmp;#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_show\n");#endif	dinfo->cursor_on = 1;	if (dinfo->cursor_blanked)		return;	if (dinfo->mobile || IS_I9XX(dinfo)) {		if (!dinfo->cursor.physical)			return;		tmp = INREG(CURSOR_A_CONTROL);		tmp &= ~CURSOR_MODE_MASK;		tmp |= CURSOR_MODE_64_4C_AX;		OUTREG(CURSOR_A_CONTROL, tmp);		/* Flush changes */		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);	} else {		tmp = INREG(CURSOR_CONTROL);		tmp |= CURSOR_ENABLE;		OUTREG(CURSOR_CONTROL, tmp);	}}void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y){	u32 tmp;#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);#endif	/*	 * Sets the position. The coordinates are assumed to already	 * have any offset adjusted. Assume that the cursor is never	 * completely off-screen, and that x, y are always >= 0.	 */	tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |	      ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);	OUTREG(CURSOR_A_POSITION, tmp);	if (IS_I9XX(dinfo))		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);}void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg){#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_setcolor\n");#endif	OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);	OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);	OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);	OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);}void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,			   u8 *data){	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;	int i, j, w = width / 8;	int mod = width % 8, t_mask, d_mask;#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_load\n");#endif	if (!dinfo->cursor.virtual)		return;	t_mask = 0xff >> mod;	d_mask = ~(0xff >> mod);	for (i = height; i--; ) {		for (j = 0; j < w; j++) {			writeb(0x00, addr + j);			writeb(*(data++), addr + j+8);		}		if (mod) {			writeb(t_mask, addr + j);			writeb(*(data++) & d_mask, addr + j+8);		}		addr += 16;	}}void intelfbhw_cursor_reset(struct intelfb_info *dinfo){	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;	int i, j;#if VERBOSE > 0	DBG_MSG("intelfbhw_cursor_reset\n");#endif	if (!dinfo->cursor.virtual)		return;	for (i = 64; i--; ) {		for (j = 0; j < 8; j++) {			writeb(0xff, addr + j+0);			writeb(0x00, addr + j+8);		}		addr += 16;	}}static irqreturn_t intelfbhw_irq(int irq, void *dev_id){	u16 tmp;	struct intelfb_info *dinfo = dev_id;	spin_lock(&dinfo->int_lock);	tmp = INREG16(IIR);	if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)		tmp &= PIPE_A_EVENT_INTERRUPT;	else		tmp &= VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */	if (tmp == 0) {		spin_unlock(&dinfo->int_lock);		return IRQ_RETVAL(0); /* not us */	}	/* clear status bits 0-15 ASAP and don't touch bits 16-31 */	OUTREG(PIPEASTAT, INREG(PIPEASTAT));	OUTREG16(IIR, tmp);	if (dinfo->vsync.pan_display) {		dinfo->vsync.pan_display = 0;		OUTREG(DSPABASE, dinfo->vsync.pan_offset);	}	dinfo->vsync.count++;	wake_up_interruptible(&dinfo->vsync.wait);	spin_unlock(&dinfo->int_lock);	return IRQ_RETVAL(1);}int intelfbhw_enable_irq(struct intelfb_info *dinfo){	u16 tmp;	if (!test_and_set_bit(0, &dinfo->irq_flags)) {		if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,				"intelfb", dinfo)) {			clear_bit(0, &dinfo->irq_flags);			return -EINVAL;		}		spin_lock_irq(&dinfo->int_lock);		OUTREG16(HWSTAM, 0xfffe); /* i830 DRM uses ffff */		OUTREG16(IMR, 0);	} else		spin_lock_irq(&dinfo->int_lock);	if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)		tmp = PIPE_A_EVENT_INTERRUPT;	else		tmp = VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */	if (tmp != INREG16(IER)) {		DBG_MSG("changing IER to 0x%X\n", tmp);		OUTREG16(IER, tmp);	}	spin_unlock_irq(&dinfo->int_lock);	return 0;}void intelfbhw_disable_irq(struct intelfb_info *dinfo){	if (test_and_clear_bit(0, &dinfo->irq_flags)) {		if (dinfo->vsync.pan_display) {			dinfo->vsync.pan_display = 0;			OUTREG(DSPABASE, dinfo->vsync.pan_offset);		}		spin_lock_irq(&dinfo->int_lock);		OUTREG16(HWSTAM, 0xffff);		OUTREG16(IMR, 0xffff);		OUTREG16(IER, 0x0);		OUTREG16(IIR, INREG16(IIR)); /* clear IRQ requests */		spin_unlock_irq(&dinfo->int_lock);		free_irq(dinfo->pdev->irq, dinfo);	}}int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe){	struct intelfb_vsync *vsync;	unsigned int count;	int ret;	switch (pipe) {		case 0:			vsync = &dinfo->vsync;			break;		default:			return -ENODEV;	}	ret = intelfbhw_enable_irq(dinfo);	if (ret)		return ret;	count = vsync->count;	ret = wait_event_interruptible_timeout(vsync->wait,					       count != vsync->count, HZ / 10);	if (ret < 0)		return ret;	if (ret == 0) {		DBG_MSG("wait_for_vsync timed out!\n");		return -ETIMEDOUT;	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -