From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/gfxdrivers/i810/i810.c | 1044 ++++++++++++++++++++++++++++++++ 1 file changed, 1044 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/i810/i810.c (limited to 'Source/DirectFB/gfxdrivers/i810/i810.c') diff --git a/Source/DirectFB/gfxdrivers/i810/i810.c b/Source/DirectFB/gfxdrivers/i810/i810.c new file mode 100755 index 0000000..0c3d0ff --- /dev/null +++ b/Source/DirectFB/gfxdrivers/i810/i810.c @@ -0,0 +1,1044 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Antonino Daplas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include /* FIXME: Needs to be included before dfb_types.h to work around a type clash with asm/types.h */ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +/* need fb handle to get accel, MMIO programming in the i810 is useless */ +#include +#include +#include +#include + +#include + +DFB_GRAPHICS_DRIVER( i810 ) + +#include "i810.h" + + +#define TIMER_LOOP 1000000000 +#define BUFFER_PADDING 2 +#define MMIO_SIZE 512 * 1024 + +#define I810_SUPPORTED_DRAWINGFLAGS (DSDRAW_NOFX) + +#define I810_SUPPORTED_DRAWINGFUNCTIONS \ + (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | DFXL_FILLTRIANGLE) + +#define I810_SUPPORTED_BLITTINGFLAGS \ + (DSBLIT_SRC_COLORKEY | DSBLIT_DST_COLORKEY) + +#define I810_SUPPORTED_BLITTINGFUNCTIONS \ + (DFXL_BLIT) + +static void +i810_lring_enable(I810DriverData *i810drv, u32 mode) +{ + u32 tmp; + + tmp = i810_readl(i810drv->mmio_base, LRING + 12); + tmp = (!mode) ? tmp & ~1 : tmp | 1; + + i810_writel(i810drv->mmio_base, LRING + 12, tmp); +} + + +static inline void +i810_wait_for_blit_idle(I810DriverData *i810drv, + I810DeviceData *i810dev ) +{ + u32 count = 0; + + if (i810dev != NULL) + i810dev->idle_calls++; + + while ((i810_readw(i810drv->mmio_base, INSTDONE) & 0x7b) != 0x7b && + count++ < TIMER_LOOP) { + if (i810dev != NULL) + i810dev->idle_waitcycles++; + } + + if (count >= TIMER_LOOP) { + if (i810dev != NULL) + i810dev->idle_timeoutsum++; + D_BUG("warning: idle timeout exceeded"); + } +} + +static void +i810_init_ringbuffer(I810DriverData *i810drv, + I810DeviceData *i810dev ) +{ + u32 tmp1, tmp2; + + i810_wait_for_blit_idle(i810drv, i810dev); + i810_lring_enable(i810drv, 0); + + i810_writel(i810drv->mmio_base, LRING, 0); + i810_writel(i810drv->mmio_base, LRING + 4, 0); + i810dev->cur_tail = 0; + + tmp2 = i810_readl(i810drv->mmio_base, LRING + 8) & ~RBUFFER_START_MASK; + tmp1 = i810dev->lring_bind.pg_start * 4096; + i810_writel(i810drv->mmio_base, LRING + 8, tmp2 | tmp1); + + tmp1 = i810_readl(i810drv->mmio_base, LRING + 12); + tmp1 &= ~RBUFFER_SIZE_MASK; + tmp2 = (RINGBUFFER_SIZE - 4096) & RBUFFER_SIZE_MASK; + i810_writel(i810drv->mmio_base, LRING + 12, tmp1 | tmp2); + i810_lring_enable(i810drv, 1); +} + +static inline int +i810_wait_for_space(I810DriverData *i810drv, + I810DeviceData *i810dev, + u32 space ) +{ + u32 head, count = TIMER_LOOP, tail, tries = 0; + + i810dev->waitfifo_calls++; + + tail = i810dev->cur_tail; + + space += BUFFER_PADDING; + space <<= 2; + i810dev->waitfifo_sum += space; + + while (count--) { + i810dev->fifo_waitcycles++; + head = i810_readl(i810drv->mmio_base, LRING + 4) & RBUFFER_HEAD_MASK; + if ((tail == head) || + (tail > head && (RINGBUFFER_SIZE - tail + head) >= space) || + (tail < head && (head - tail) >= space)) { + if (!tries) + i810dev->fifo_cache_hits++; + return 0; + } + tries++; + } + D_BUG("warning: buffer space timout error"); + return 1; +} + + +static void +i810FlushTextureCache(void *drv, void *dev) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + + if (BEGIN_LRING(i810drv, i810dev, 2)) return; + + PUT_LRING(PARSER | FLUSH); + PUT_LRING(NOP); + + END_LRING(i810drv); +} + +static DFBResult +i810EngineSync(void *drv, void *dev) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + + i810_wait_for_blit_idle(i810drv, i810dev); + + return DFB_OK; +} + +/* + * Set State routines + */ +static inline void +i810_set_src(I810DriverData *i810drv, + I810DeviceData *i810dev, + CardState *state) +{ + if (i810dev->i_src) + return; + i810dev->srcaddr = dfb_gfxcard_memory_physical((CoreGraphicsDevice *) i810dev, + state->src.offset); + i810dev->srcpitch = state->src.pitch; + + i810dev->i_src = 1; +} + +static inline void +i810_set_dest(I810DriverData *i810drv, + I810DeviceData *i810dev, + CardState *state) +{ + CoreSurface *destination = state->destination; + + if (i810dev->i_dst) + return; + i810dev->destaddr = dfb_gfxcard_memory_physical((CoreGraphicsDevice *) i810dev, + state->dst.offset); + i810dev->destpitch = state->dst.pitch; + + switch (destination->config.format) { + case DSPF_LUT8: + i810dev->pixeldepth = 1; + i810dev->blit_color = BPP8; + break; + case DSPF_ARGB1555: + i810dev->pixeldepth = 2; + i810dev->blit_color = BPP16; + break; + case DSPF_RGB16: + i810dev->pixeldepth = 2; + i810dev->blit_color = BPP16; + break; + case DSPF_RGB24: + i810dev->pixeldepth = 3; + i810dev->blit_color = BPP24; + break; + default: + D_BUG("unexpected pixelformat~"); + } + i810dev->i_dst = 1; +} + +static inline void +i810_set_colorkey(I810DriverData *i810drv, + I810DeviceData *i810dev, + CardState *state) +{ + if (i810dev->i_colorkey) + return; + + i810dev->colorkey_bit = 0; + if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + i810dev->colorkey_bit = 1 << 8; + i810dev->colorkey = state->src_colorkey; + } + else { + i810dev->colorkey_bit = 7 << 8; + i810dev->colorkey = state->dst_colorkey; + } + + i810dev->i_colorkey = 1; +} + +static inline void +i810_set_color(I810DriverData *i810drv, + I810DeviceData *i810dev, + CardState *state) +{ + if (i810dev->i_color) + return; + + switch (state->destination->config.format) { + case DSPF_LUT8: + i810dev->color_value = state->color_index; + break; + case DSPF_ARGB1555: + i810dev->color_value = PIXEL_ARGB1555(state->color.a, + state->color.r, + state->color.g, + state->color.b); + break; + case DSPF_RGB16: + i810dev->color_value = PIXEL_RGB16(state->color.r, + state->color.g, + state->color.b); + break; + case DSPF_RGB24: + i810dev->color_value = PIXEL_RGB32(state->color.r, + state->color.g, + state->color.b); + break; + default: + D_BUG("unexpected pixelformat~"); + } + i810dev->i_color = 1; +} + +static inline void +i810_set_clip(I810DriverData *i810drv, + I810DeviceData *i810dev, + DFBRegion *clip ) +{ + if (i810dev->i_clip) + return; + + i810dev->clip_x1 = clip->x1; + i810dev->clip_x2 = clip->x2 + 1; + i810dev->clip_y1 = clip->y1; + i810dev->clip_y2 = clip->y2 + 1; + + i810dev->i_clip = 1; +} + +static void +i810CheckState(void *drv, void *dev, + CardState *state, DFBAccelerationMask accel ) +{ + switch (state->destination->config.format) { + case DSPF_LUT8: + case DSPF_ARGB1555: + case DSPF_RGB16: + case DSPF_RGB24: + break; + default: + return; + } + + if (!(accel & ~I810_SUPPORTED_DRAWINGFUNCTIONS) && + !(state->drawingflags & ~I810_SUPPORTED_DRAWINGFLAGS)) + state->accel |= I810_SUPPORTED_DRAWINGFUNCTIONS; + + if (!(accel & ~I810_SUPPORTED_BLITTINGFUNCTIONS) && + !(state->blittingflags & ~I810_SUPPORTED_BLITTINGFLAGS)) { + if (state->source->config.format == state->destination->config.format) + state->accel |= I810_SUPPORTED_BLITTINGFUNCTIONS; + } +} + +static void +i810SetState( void *drv, void *dev, + GraphicsDeviceFuncs *funcs, + CardState *state, DFBAccelerationMask accel ) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + + if (state->mod_hw) { + if ((state->mod_hw & SMF_SOURCE) && state->source) + i810dev->i_src = 0; + if (state->mod_hw & SMF_DESTINATION) + i810dev->i_dst = 0; + if (state->mod_hw & SMF_COLOR) + i810dev->i_color = 0; + if (state->mod_hw & SMF_CLIP) + i810dev->i_clip = 0; + if (state->mod_hw & SMF_SRC_COLORKEY || + state->mod_hw & SMF_DST_COLORKEY) { + i810dev->i_colorkey = 0; + } + } + + switch (accel) { + case DFXL_DRAWRECTANGLE: + case DFXL_FILLRECTANGLE: + case DFXL_FILLTRIANGLE: + i810_set_dest(i810drv, i810dev, state); + i810_set_color(i810drv, i810dev, state); + i810_set_clip(i810drv, i810dev, &state->clip); + state->set |= DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE; + break; + case DFXL_BLIT: + i810_set_src( i810drv, i810dev, state); + i810_set_dest(i810drv, i810dev, state); + i810_set_color(i810drv, i810dev, state); + i810_set_clip(i810drv, i810dev, &state->clip); + if (state->blittingflags & DSBLIT_SRC_COLORKEY || + state->blittingflags & DSBLIT_DST_COLORKEY) + i810_set_colorkey(i810drv, i810dev, state); + state->set |= DFXL_BLIT; + break; + default: + D_BUG("unexpected drawing/blitting function"); + } + state->mod_hw = 0; +} + +static bool +i810FillRectangle( void *drv, void *dev, DFBRectangle *rect ) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + u32 dest; + + + if (rect->x < i810dev->clip_x1) + rect->x = i810dev->clip_x1; + if (i810dev->clip_x2 < rect->x + rect->w) + rect->w = i810dev->clip_x2 - rect->x; + if (rect->y < i810dev->clip_y1) + rect->y = i810dev->clip_y1; + if (i810dev->clip_y2 < rect->y + rect->h) + rect->h = i810dev->clip_y2 - rect->y; + + rect->x *= i810dev->pixeldepth; + rect->w *= i810dev->pixeldepth; + dest = i810dev->destaddr + rect->x + (rect->y * i810dev->destpitch); + + if (BEGIN_LRING(i810drv, i810dev, 6)) return false; + + PUT_LRING(BLIT | COLOR_BLT | 3); + PUT_LRING(COLOR_COPY_ROP << 16 | i810dev->destpitch | SOLIDPATTERN | + DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING(rect->h << 16 | rect->w); + PUT_LRING(dest); + PUT_LRING(i810dev->color_value); + PUT_LRING(NOP); + + END_LRING(i810drv); + + return true; +} + +static bool +i810DrawRectangle( void *drv, void *dev, DFBRectangle *rect ) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + u32 dest; + + + if (rect->x < i810dev->clip_x1) + rect->x = i810dev->clip_x1; + if (i810dev->clip_x2 < rect->x + rect->w) + rect->w = i810dev->clip_x2 - rect->x; + if (rect->y < i810dev->clip_y1) + rect->y = i810dev->clip_y1; + if (i810dev->clip_y2 < rect->y + rect->h) + rect->h = i810dev->clip_y2 - rect->y; + + + + rect->x *= i810dev->pixeldepth; + rect->w *= i810dev->pixeldepth; + + if (BEGIN_LRING(i810drv, i810dev, 20)) return false; + + /* horizontal line 1 */ + dest = i810dev->destaddr + rect->x + (rect->y * i810dev->destpitch); + PUT_LRING(BLIT | COLOR_BLT | 3); + PUT_LRING(COLOR_COPY_ROP << 16 | i810dev->destpitch | SOLIDPATTERN | + DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING(1 << 16 | rect->w); + PUT_LRING(dest); + PUT_LRING(i810dev->color_value); + + /* vertical line 1 */ + PUT_LRING(BLIT | COLOR_BLT | 3); + PUT_LRING(COLOR_COPY_ROP << 16 | i810dev->destpitch | SOLIDPATTERN | + DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING(rect->h << 16 | i810dev->pixeldepth); + PUT_LRING(dest); + PUT_LRING(i810dev->color_value); + + /* vertical line 2 */ + dest += rect->w; + PUT_LRING(BLIT | COLOR_BLT | 3); + PUT_LRING(COLOR_COPY_ROP << 16 | i810dev->destpitch | SOLIDPATTERN | + DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING(rect->h << 16 | i810dev->pixeldepth); + PUT_LRING(dest); + PUT_LRING(i810dev->color_value); + + /* horizontal line 2 */ + dest -= rect->w; + dest += rect->h * i810dev->destpitch; + PUT_LRING(BLIT | COLOR_BLT | 3); + PUT_LRING(COLOR_COPY_ROP << 16 | i810dev->destpitch | SOLIDPATTERN | + DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING(1 << 16 | rect->w); + PUT_LRING(dest); + PUT_LRING(i810dev->color_value); + + END_LRING(i810drv); + + return true; +} + +static bool +i810Blit( void *drv, void *dev, DFBRectangle *rect, int dx, int dy ) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + int xdir = INCREMENT, spitch = 0, dpitch = 0, src, dest; + + if (dx < i810dev->clip_x1) { + rect->w = MIN((i810dev->clip_x2 - i810dev->clip_x1), + (dx + rect->w) - i810dev->clip_x1); + rect->x += i810dev->clip_x1 - dx; + dx = i810dev->clip_x1; + } + if (i810dev->clip_x2 < dx + rect->w) + rect->w = i810dev->clip_x2 - dx; + + if (dy < i810dev->clip_y1) { + rect->h = MIN((i810dev->clip_y2 - i810dev->clip_y1), + (dy + rect->h) - i810dev->clip_y1); + rect->y += i810dev->clip_y1 - dy; + dy = i810dev->clip_y1; + } + if (i810dev->clip_y2 < dy + rect->h) + rect->h = i810dev->clip_y2 - dy; + + rect->x *= i810dev->pixeldepth; + dx *= i810dev->pixeldepth; + rect->w *= i810dev->pixeldepth; + + spitch = i810dev->srcpitch; + dpitch = i810dev->destpitch; + + if (i810dev->srcaddr == i810dev->destaddr) { + if (dx > rect->x && dx < rect->x + rect->w) { + xdir = DECREMENT; + rect->x += rect->w - 1; + dx += rect->w - 1; + } + if (dy > rect->y && dy < rect->y + rect->h) { + i810dev->srcpitch = (-(i810dev->srcpitch)) & 0xFFFF; + i810dev->destpitch = (-(i810dev->destpitch)) & 0xFFFF; + rect->y += rect->h - 1; + dy += rect->h - 1; + } + } + + src = i810dev->srcaddr + rect->x + (rect->y * spitch); + dest = i810dev->destaddr + dx + (dy * dpitch); + + BEGIN_LRING(i810drv, i810dev, 8); + + PUT_LRING(BLIT | FULL_BLIT | 0x6 | i810dev->colorkey_bit); + PUT_LRING(xdir | PAT_COPY_ROP << 16 | i810dev->destpitch | + DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING((rect->h << 16) | rect->w); + PUT_LRING(dest); + PUT_LRING(i810dev->srcpitch); + PUT_LRING(src); + PUT_LRING(i810dev->colorkey); + PUT_LRING((u32)(unsigned long) i810drv->pattern_base); + + END_LRING(i810drv); + + return true; +} + +/* + * The software rasterizer when rendering non-axis aligned + * edges uses line spanning. In our case, it will use + * FillRect to render a 1 pixel-high rectangle. However, + * this would be slow in the i810 since for each rectangle, + * an ioctl has to be done which is very slow. As a temporary + * replacement, I'll include a SpanLine function that will + * not do an ioctl for every line. This should be + * significantly faster. + */ + +/* borrowed heavily and shamelessly from gfxcard.c */ + +typedef struct { + int xi; + int xf; + int mi; + int mf; + int _2dy; +} DDA; + +#define SETUP_DDA(xs,ys,xe,ye,dda) \ + do { \ + int dx = xe - xs; \ + int dy = ye - ys; \ + dda.xi = xs; \ + if (dy != 0) { \ + dda.mi = dx / dy; \ + dda.mf = 2*(dx % dy); \ + dda.xf = -dy; \ + dda._2dy = 2*dy; \ + if (dda.mf < 0) { \ + dda.mf += ABS(dy)*2; \ + dda.mi--; \ + } \ + } \ + else { \ + dda.mi = 0; \ + dda.mf = 0; \ + dda.xf = 0; \ + dda._2dy = 0; \ + } \ + } while (0) + + +#define INC_DDA(dda) \ + do { \ + dda.xi += dda.mi; \ + dda.xf += dda.mf; \ + if (dda.xf > 0) { \ + dda.xi++; \ + dda.xf -= dda._2dy; \ + } \ + } while (0) + + + +/* + * The i810fill_tri function takes advantage of the buffer. + * It will fill up the buffer until it's done rendering the + * triangle. + */ +static inline bool +i810fill_tri( DFBTriangle *tri, + I810DriverData *i810drv, + I810DeviceData *i810dev ) +{ + int y, yend; + + DDA dda1, dda2; + u32 total, dest = 0; + + y = tri->y1; + yend = tri->y3; + + if (y < i810dev->clip_y1) + y = i810dev->clip_y1; + if (yend > i810dev->clip_y2) + yend = i810dev->clip_y2; + + + SETUP_DDA(tri->x1, tri->y1, tri->x3, tri->y3, dda1); + SETUP_DDA(tri->x1, tri->y1, tri->x2, tri->y2, dda2); + + total = (yend - y) * 5; + if (total + BUFFER_PADDING > RINGBUFFER_SIZE/4) { + D_BUG("fill_triangle: buffer size is too small\n"); + return false; + } + + BEGIN_LRING(i810drv, i810dev, total); + + while (y < yend) { + DFBRectangle rect; + + if (y == tri->y2) { + if (tri->y2 == tri->y3) + return true; + SETUP_DDA(tri->x2, tri->y2, tri->x3, tri->y3, dda2); + } + + rect.w = ABS(dda1.xi - dda2.xi); + rect.x = MIN(dda1.xi, dda2.xi); + + if (rect.w > 0) { + rect.y = y; + dest = i810dev->destaddr + (y * i810dev->destpitch) + (rect.x * i810dev->pixeldepth); + PUT_LRING(BLIT | COLOR_BLT | 3); + PUT_LRING(COLOR_COPY_ROP << 16 | i810dev->destpitch | + SOLIDPATTERN | DYN_COLOR_EN | i810dev->blit_color); + PUT_LRING(1 << 16 | rect.w * i810dev->pixeldepth); + PUT_LRING(dest); + PUT_LRING(i810dev->color_value); + } + + INC_DDA(dda1); + INC_DDA(dda2); + + y++; + } + END_LRING(i810drv); + return true; +} + +static bool +i810FillTriangle( void *drv, void *dev, DFBTriangle *tri) +{ + I810DriverData *i810drv = (I810DriverData *) drv; + I810DeviceData *i810dev = (I810DeviceData *) dev; + bool err = true; + + dfb_sort_triangle(tri); + + if (tri->y3 - tri->y1 > 0) + err = i810fill_tri(tri, i810drv, i810dev); + + return err; +} + +static int +driver_probe( CoreGraphicsDevice *device ) +{ + switch (dfb_gfxcard_get_accelerator( device )) { + case FB_ACCEL_I810: /* Intel 810 */ + return 1; + } + return 0; +} + + +static void +driver_get_info( CoreGraphicsDevice *device, + GraphicsDriverInfo *info ) +{ + /* fill driver info structure */ + snprintf( info->name, + DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, + "Intel 810/810E/810-DC100/815 Driver" ); + + snprintf( info->vendor, + DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, + "Tony Daplas" ); + + snprintf( info->url, + DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH, + "http://i810fb.sourceforge.net" ); + + snprintf( info->license, + DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH, + "LGPL" ); + + info->version.major = 0; + info->version.minor = 5; + + info->driver_data_size = sizeof (I810DriverData); + info->device_data_size = sizeof (I810DeviceData); +} + +static void +i810_release_resource( I810DriverData *idrv, I810DeviceData *idev ) +{ + agp_unbind unbind; + + if (idrv->flags & I810RES_STATE_SAVE) { + i810_writel( idrv->mmio_base, LP_RING, idev->lring1 ); + i810_writel( idrv->mmio_base, LP_RING + RING_HEAD, idev->lring2 ); + i810_writel( idrv->mmio_base, LP_RING + RING_START, idev->lring3 ); + i810_writel( idrv->mmio_base, LP_RING + RING_LEN, idev->lring4 ); + } + + if (idrv->flags & I810RES_MMAP) { + munmap((void *) idrv->aper_base, idev->info.aper_size * 1024 * 1024); + idrv->flags &= ~I810RES_MMAP; + } + + if (idrv->flags & I810RES_LRING_BIND) { + unbind.key = idev->lring_bind.key; + ioctl(idrv->agpgart, AGPIOC_UNBIND, &unbind); + } + + if (idrv->flags & I810RES_LRING_ACQ) + ioctl(idrv->agpgart, AGPIOC_DEALLOCATE, idev->lring_mem.key); + + if (idrv->flags & I810RES_OVL_BIND) { + unbind.key = idev->ovl_bind.key; + ioctl(idrv->agpgart, AGPIOC_UNBIND, &unbind); + } + + if (idrv->flags & I810RES_OVL_ACQ) + ioctl(idrv->agpgart, AGPIOC_DEALLOCATE, idev->ovl_mem.key); + + if (idrv->flags & I810RES_GART_ACQ) { + ioctl(idrv->agpgart, AGPIOC_RELEASE); + idrv->flags &= ~I810RES_GART_ACQ; + } + + if (idrv->flags & I810RES_GART) { + close(idrv->agpgart); + idrv->flags &= ~I810RES_GART; + } +} + +static DFBResult +i810_agp_setup( CoreGraphicsDevice *device, + I810DriverData *idrv, + I810DeviceData *idev ) +{ + idrv->agpgart = open("/dev/agpgart", O_RDWR); + if (idrv->agpgart == -1) + return DFB_IO; + D_FLAGS_SET( idrv->flags, I810RES_GART ); + + + if (ioctl(idrv->agpgart, AGPIOC_ACQUIRE)) { + D_PERROR( "I810/AGP: AGPIOC_ACQUIRE failed!\n" ); + return DFB_IO; + } + D_FLAGS_SET( idrv->flags, I810RES_GART_ACQ ); + + + if (!idev->initialized) { + agp_setup setup; + + setup.agp_mode = 0; + if (ioctl(idrv->agpgart, AGPIOC_SETUP, &setup)) { + D_PERROR( "I810/AGP: AGPIOC_SETUP failed!\n" ); + return DFB_IO; + } + + if (ioctl(idrv->agpgart, AGPIOC_INFO, &idev->info)) { + D_PERROR( "I810/AGP: AGPIOC_INFO failed!\n" ); + return DFB_IO; + } + } + + + idrv->aper_base = mmap( NULL, idev->info.aper_size * 1024 * 1024, PROT_WRITE, + MAP_SHARED, idrv->agpgart, 0 ); + if (idrv->aper_base == MAP_FAILED) { + D_PERROR( "I810/AGP: mmap() failed!\n" ); + i810_release_resource( idrv, idev ); + return DFB_IO; + } + D_FLAGS_SET( idrv->flags, I810RES_MMAP ); + + + if (!idev->initialized) { + u32 base; + + /* We'll attempt to bind at fb_base + fb_len + 1 MB, + to be safe */ + base = dfb_gfxcard_memory_physical(device, 0) - idev->info.aper_base; + base += dfb_gfxcard_memory_length(); + base += (1024 * 1024); + + idev->lring_mem.pg_count = RINGBUFFER_SIZE/4096; + idev->lring_mem.type = AGP_NORMAL_MEMORY; + if (ioctl(idrv->agpgart, AGPIOC_ALLOCATE, &idev->lring_mem)) { + D_PERROR( "I810/AGP: AGPIOC_ALLOCATE failed!\n" ); + i810_release_resource( idrv, idev ); + return DFB_IO; + } + D_FLAGS_SET( idrv->flags, I810RES_LRING_ACQ ); + + idev->lring_bind.key = idev->lring_mem.key; + idev->lring_bind.pg_start = base/4096; + if (ioctl(idrv->agpgart, AGPIOC_BIND, &idev->lring_bind)) { + D_PERROR( "I810/AGP: AGPIOC_BIND failed!\n" ); + i810_release_resource( idrv, idev ); + return DFB_IO; + } + D_FLAGS_SET( idrv->flags, I810RES_LRING_BIND ); + + idev->ovl_mem.pg_count = 1; + idev->ovl_mem.type = AGP_PHYSICAL_MEMORY; + if (ioctl(idrv->agpgart, AGPIOC_ALLOCATE, &idev->ovl_mem)) { + D_PERROR( "I810/AGP: AGPIOC_ALLOCATE failed!\n" ); + i810_release_resource( idrv, idev ); + return DFB_IO; + } + D_FLAGS_SET( idrv->flags, I810RES_OVL_ACQ ); + + idev->ovl_bind.key = idev->ovl_mem.key; + idev->ovl_bind.pg_start = (base + RINGBUFFER_SIZE)/4096; + if (ioctl(idrv->agpgart, AGPIOC_BIND, &idev->ovl_bind)) { + D_PERROR( "I810/AGP: AGPIOC_BIND failed!\n" ); + i810_release_resource( idrv, idev ); + return DFB_IO; + } + D_FLAGS_SET( idrv->flags, I810RES_OVL_BIND ); + } + + + if (idrv->flags & I810RES_GART_ACQ) { + ioctl(idrv->agpgart, AGPIOC_RELEASE); + idrv->flags &= ~I810RES_GART_ACQ; + } + + + idrv->lring_base = idrv->aper_base + idev->lring_bind.pg_start * 4096; + idrv->ovl_base = idrv->aper_base + idev->ovl_bind.pg_start * 4096; + idrv->pattern_base = idrv->ovl_base + 1024; + + if (!idev->initialized) { + memset((void *) idrv->ovl_base, 0xff, 1024); + memset((void *) idrv->pattern_base, 0xff, 4096 - 1024); + + idev->lring1 = 0;//i810_readl(idrv->mmio_base, LP_RING); + idev->lring2 = 0;//i810_readl(idrv->mmio_base, LP_RING + RING_HEAD); + idev->lring3 = 0;//i810_readl(idrv->mmio_base, LP_RING + RING_START); + idev->lring4 = 0;//i810_readl(idrv->mmio_base, LP_RING + RING_LEN); + + D_FLAGS_SET( idrv->flags, I810RES_STATE_SAVE ); + } + + idev->initialized = true; + + return DFB_OK; +} + +static DFBResult +driver_init_driver( CoreGraphicsDevice *device, + GraphicsDeviceFuncs *funcs, + void *driver_data, + void *device_data, + CoreDFB *core ) +{ + DFBResult ret; + I810DriverData *idrv = driver_data; + I810DeviceData *idev = device_data; + + idrv->idev = device_data; + + idrv->mmio_base = (volatile u8*) dfb_gfxcard_map_mmio( device, 0, -1 ); + if (!idrv->mmio_base) + return DFB_IO; + + ret = i810_agp_setup( device, idrv, idev ); + if (ret) { + dfb_gfxcard_unmap_mmio( device, idrv->mmio_base, -1 ); + return ret; + } + + idrv->info = idev->info; + + + funcs->CheckState = i810CheckState; + funcs->SetState = i810SetState; + funcs->EngineSync = i810EngineSync; + funcs->FlushTextureCache = i810FlushTextureCache; + + funcs->FillRectangle = i810FillRectangle; + funcs->DrawRectangle = i810DrawRectangle; + funcs->Blit = i810Blit; + funcs->FillTriangle = i810FillTriangle; + + dfb_layers_register( dfb_screens_at(DSCID_PRIMARY), driver_data, &i810OverlayFuncs ); + + return DFB_OK; +} + +static DFBResult +driver_init_device( CoreGraphicsDevice *device, + GraphicsDeviceInfo *device_info, + void *driver_data, + void *device_data ) +{ + I810DriverData *idrv = driver_data; + I810DeviceData *idev = device_data; + + /* fill device info */ + snprintf( device_info->name, + DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "810/810E/810-DC100/815" ); + + snprintf( device_info->vendor, + DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "Intel" ); + + device_info->caps.flags = CCF_CLIPPING; + device_info->caps.accel = I810_SUPPORTED_DRAWINGFUNCTIONS | + I810_SUPPORTED_BLITTINGFUNCTIONS; + device_info->caps.drawing = I810_SUPPORTED_DRAWINGFLAGS; + device_info->caps.blitting = I810_SUPPORTED_BLITTINGFLAGS; + + device_info->limits.surface_byteoffset_alignment = 32 * 4; + device_info->limits.surface_pixelpitch_alignment = 32; + + dfb_config->pollvsync_after = 1; + + i810_init_ringbuffer( idrv, idev ); + + return DFB_OK; +} + +static void +driver_close_device( CoreGraphicsDevice *device, + void *driver_data, + void *device_data ) +{ + I810DeviceData *i810dev = (I810DeviceData *) device_data; + I810DriverData *i810drv = (I810DriverData *) driver_data; + + i810ovlOnOff( i810drv, i810dev, false ); + + i810_wait_for_blit_idle( i810drv, i810dev ); + i810_lring_enable( i810drv, 0 ); + + i810_release_resource( i810drv, i810dev ); + + + D_DEBUG( "DirectFB/I810: DMA Buffer Performance Monitoring:\n"); + D_DEBUG( "DirectFB/I810: %9d DMA buffer size in KB\n", + RINGBUFFER_SIZE/1024 ); + D_DEBUG( "DirectFB/I810: %9d i810_wait_for_blit_idle calls\n", + i810dev->idle_calls ); + D_DEBUG( "DirectFB/I810: %9d i810_wait_for_space calls\n", + i810dev->waitfifo_calls ); + D_DEBUG( "DirectFB/I810: %9d BUFFER transfers (i810_wait_for_space sum)\n", + i810dev->waitfifo_sum ); + D_DEBUG( "DirectFB/I810: %9d BUFFER wait cycles (depends on GPU/CPU)\n", + i810dev->fifo_waitcycles ); + D_DEBUG( "DirectFB/I810: %9d IDLE wait cycles (depends on GPU/CPU)\n", + i810dev->idle_waitcycles ); + D_DEBUG( "DirectFB/I810: %9d BUFFER space cache hits(depends on BUFFER size)\n", + i810dev->fifo_cache_hits ); + D_DEBUG( "DirectFB/I810: %9d BUFFER timeout sum (possible hardware crash)\n", + i810dev->fifo_timeoutsum ); + D_DEBUG( "DirectFB/I810: %9d IDLE timeout sum (possible hardware crash)\n", + i810dev->idle_timeoutsum ); + D_DEBUG( "DirectFB/I810: Conclusion:\n" ); + D_DEBUG( "DirectFB/I810: Average buffer transfers per i810_wait_for_space " + "call: %.2f\n", + i810dev->waitfifo_sum/(float)(i810dev->waitfifo_calls) ); + D_DEBUG( "DirectFB/I810: Average wait cycles per i810_wait_for_space call:" + " %.2f\n", + i810dev->fifo_waitcycles/(float)(i810dev->waitfifo_calls) ); + D_DEBUG( "DirectFB/I810: Average wait cycles per i810_wait_for_blit_idle call:" + " %.2f\n", + i810dev->idle_waitcycles/(float)(i810dev->idle_calls) ); + D_DEBUG( "DirectFB/I810: Average buffer space cache hits: %02d%%\n", + (int)(100 * i810dev->fifo_cache_hits/ + (float)(i810dev->waitfifo_calls)) ); + +} + +static void +driver_close_driver( CoreGraphicsDevice *device, + void *driver_data ) +{ + I810DriverData *idrv = (I810DriverData *) driver_data; + + dfb_gfxcard_unmap_mmio( device, idrv->mmio_base, -1); + + if (idrv->flags & I810RES_MMAP) { + munmap((void *) idrv->aper_base, idrv->info.aper_size * 1024 * 1024); + idrv->flags &= ~I810RES_MMAP; + } + + if (idrv->flags & I810RES_GART_ACQ) { + ioctl(idrv->agpgart, AGPIOC_RELEASE); + idrv->flags &= ~I810RES_GART_ACQ; + } + + if (idrv->flags & I810RES_GART) { + close(idrv->agpgart); + idrv->flags &= ~I810RES_GART; + } +} + -- cgit