diff --git a/configure.ac b/configure.ac index b1dd287f..70ae8078 100644 --- a/configure.ac +++ b/configure.ac @@ -120,9 +120,13 @@ fi AM_CONDITIONAL(DRI, test x$DRI = xyes) if test "$DRI" = yes; then - PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto]) + PKG_CHECK_MODULES(DRI, [libdrm xf86driproto]) AC_DEFINE(XF86DRI,1,[Enable DRI driver support]) AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support]) + PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.2],[DRI_MM=yes], [DRI_MM=no]) + if test "x$DRI_MM" = xyes; then + AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management]) + fi fi AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes) @@ -148,7 +152,9 @@ AC_OUTPUT([ src/Makefile src/xvmc/Makefile src/bios_reader/Makefile + src/ch7017/Makefile src/ch7xxx/Makefile + src/ivch/Makefile src/sil164/Makefile man/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 8a52a241..80cea10a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,8 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = xvmc bios_reader ch7xxx sil164 +SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 + # this is obnoxious: # -module lets us name the module exactly how we want # -avoid-version prevents gratuitous .0.0.0 version numbers on the end @@ -88,6 +89,7 @@ i810_drv_la_SOURCES = \ i915_3d.h \ i915_reg.h \ i915_video.c \ + i965_video.c \ i830_exa.c \ i830_xaa.c \ i830_exa_render.c \ diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am new file mode 100644 index 00000000..9cf2fa49 --- /dev/null +++ b/src/ch7017/Makefile.am @@ -0,0 +1,15 @@ +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ + +ch7017_la_LTLIBRARIES = ch7017.la +ch7017_la_LDFLAGS = -module -avoid-version +ch7017_ladir = @moduledir@/drivers + +ch7017_la_SOURCES = \ + ch7017.c \ + ch7017_module.c \ + ch7017_reg.h diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c new file mode 100644 index 00000000..28bce0d2 --- /dev/null +++ b/src/ch7017/ch7017.c @@ -0,0 +1,302 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" +#include "../i830_xf86Crtc.h" +#define DPMS_SERVER +#include + +#include "../i2c_vid.h" +#include "ch7017_reg.h" + +struct ch7017_priv { + I2CDevRec d; + + CARD8 save_hapi; + CARD8 save_vali; + CARD8 save_valo; + CARD8 save_lvds_pll_vco; + CARD8 save_feedback_div; + CARD8 save_lvds_control_2; + CARD8 save_outputs_enable; + CARD8 save_lvds_power_down; +}; + +static void +ch7017_dump_regs(I2CDevPtr d); + +static Bool +ch7017_read(struct ch7017_priv *priv, int addr, CARD8 *val) +{ + if (!xf86I2CReadByte(&priv->d, addr, val)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", + priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +static Bool +ch7017_write(struct ch7017_priv *priv, int addr, CARD8 val) +{ + if (!xf86I2CWriteByte(&priv->d, addr, val)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/** Probes for a CH7017 on the given bus and slave address. */ +static void * +ch7017_init(I2CBusPtr b, I2CSlaveAddr addr) +{ + struct ch7017_priv *priv; + CARD8 val; + + xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ch7017\n"); + + priv = xcalloc(1, sizeof(struct ch7017_priv)); + if (priv == NULL) + return NULL; + + priv->d.DevName = "CH7017/7018 TMDS Controller"; + priv->d.SlaveAddr = addr; + priv->d.pI2CBus = b; + priv->d.StartTimeout = b->StartTimeout; + priv->d.BitTimeout = b->BitTimeout; + priv->d.AcknTimeout = b->AcknTimeout; + priv->d.ByteTimeout = b->ByteTimeout; + priv->d.DriverPrivate.ptr = priv; + + if (!xf86I2CReadByte(&priv->d, CH7017_DEVICE_ID, &val)) + goto fail; + + if (val != CH7017_DEVICE_ID_VALUE && val != CH7018_DEVICE_ID_VALUE) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "ch7017 not detected, got %d: from %s Slave %d.\n", + val, priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + goto fail; + } + + if (!xf86I2CDevInit(&(priv->d))) + goto fail; + + return priv; + +fail: + xfree(priv); + return NULL; +} + +static xf86OutputStatus +ch7017_detect(I2CDevPtr d) +{ + return XF86OutputStatusUnknown; +} + +static ModeStatus +ch7017_mode_valid(I2CDevPtr d, DisplayModePtr mode) +{ + if (mode->Clock > 160000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static void +ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + CARD8 lvds_pll_feedback_div, lvds_pll_vco_control; + CARD8 outputs_enable, lvds_control_2, lvds_power_down; + CARD8 horizontal_active_pixel_input; + CARD8 horizontal_active_pixel_output, vertical_active_line_output; + CARD8 active_input_line_output; + + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, + "Registers before mode setting\n"); + ch7017_dump_regs(d); + + /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/ + if (mode->Clock < 50000) { + lvds_pll_feedback_div = 45; + lvds_pll_vco_control = (2 << 4) | (3 << 0); + outputs_enable = (0 << 0); /* XXX: enables */ + lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + } else if (mode->Clock < 100000) { + lvds_pll_feedback_div = 45; + lvds_pll_vco_control = (2 << 4) | (3 << 0); + outputs_enable = (0 << 0); /* XXX: enables */ + lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + } else if (mode->Clock < 160000) { + lvds_pll_feedback_div = 35; + outputs_enable = (3 << 0); /* XXX: enables */ + lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + if (1) { /* XXX: dual panel */ + lvds_pll_vco_control = (2 << 4) | (13 << 0); + } else { + lvds_pll_vco_control = (1 << 4) | (13 << 0); + } + } else { + FatalError("Invalid mode clock (%.1fMHz)\n", + (float)mode->Clock / 1000.0); + } + + horizontal_active_pixel_input = mode->HDisplay & 0x00ff; + + vertical_active_line_output = mode->VDisplay & 0x00ff; + horizontal_active_pixel_output = mode->HDisplay & 0x00ff; + + active_input_line_output = ((mode->HDisplay & 0x0700) >> 9) | + ((mode->VDisplay & 0x0700) >> 8); + + lvds_power_down = (mode->HDisplay & 0x0f00) >> 8; + + ch7017Power(d, FALSE); + ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, + horizontal_active_pixel_input); + ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT, + horizontal_active_pixel_output); + ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, + vertical_active_line_output); + ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control); + ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div); + ch7017_write(priv, CH7017_LVDS_CONTROL_2, lvds_control_2); + ch7017_write(priv, CH7017_OUTPUTS_ENABLE, outputs_enable); + + /* Turn the LVDS back on with new settings. */ + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, lvds_power_down); + + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, + "Registers after mode setting\n"); + ch7017PrintRegs(d); +} + +/* set the CH7017 power state */ +static void +ch7017_dpms(I2CDevPtr d, int mode) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + CARD8 val; + + ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &val); + + if (mode == DPMSModeOn) { + /* Turn on the LVDS */ + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, + val & ~CH7017_LVDS_POWER_DOWN_EN); + } else { + /* Turn on the LVDS */ + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, + val | CH7017_LVDS_POWER_DOWN_EN); + } + + /* XXX: Should actually wait for update power status somehow */ + usleep(50000); +} + +static void +ch7017_dump_regs(I2CDevPtr d) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + CARD8 val; + +#define DUMP(reg) \ +do { \ + ch7017_read(priv, reg, &val); \ + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, \ + #reg ": %02x\n", val); \ +} while (0) + + DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT); + DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT); + DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT); + DUMP(CH7017_LVDS_PLL_VCO_CONTROL); + DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV); + DUMP(CH7017_LVDS_CONTROL_2); + DUMP(CH7017_OUTPUTS_ENABLE); + DUMP(CH7017_LVDS_POWER_DOWN); +} + +static void +ch7017_save(I2CDevPtr d) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + + ch7017_read(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, &priv->save_hapi); + ch7017_read(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, &priv->save_valo); + ch7017_read(priv, CH7017_LVDS_PLL_VCO_CONTROL, &priv->save_lvds_pll_vco); + ch7017_read(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, &priv->save_feedback_div); + ch7017_read(priv, CH7017_LVDS_CONTROL_2, &priv->save_lvds_control_2); + ch7017_read(priv, CH7017_OUTPUTS_ENABLE, &priv->save_outputs_enable); + ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &priv->save_lvds_power_down); +} + +static void +ch7017_restore(I2CDevPtr d) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + + /* Power down before changing mode */ + ch7017Power(d, FALSE); + + ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi); + ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo); + ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, priv->save_lvds_pll_vco); + ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, priv->save_feedback_div); + ch7017_write(priv, CH7017_LVDS_CONTROL_2, priv->save_lvds_control_2); + ch7017_write(priv, CH7017_OUTPUTS_ENABLE, priv->save_outputs_enable); + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, priv->save_lvds_power_down); +} + +I830I2CVidOutputRec ch7017_methods = { + .init = ch7017_init, + .detect = ch7017_detect, + .mode_valid = ch7017_mode_valid, + .mode_set = ch7017_mode_set, + .dpms = ch7017_dpms, + .dump_regs = ch7017_dump_regs, + .save = ch7017_save, + .restore = ch7017_restore, +}; diff --git a/src/ch7017/ch7017_module.c b/src/ch7017/ch7017_module.c new file mode 100644 index 00000000..135f3c65 --- /dev/null +++ b/src/ch7017/ch7017_module.c @@ -0,0 +1,36 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(ch7017Setup); + +static XF86ModuleVersionInfo ch7017VersRec = + { + "ch7017", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + { 0,0,0,0 } + }; + +_X_EXPORT XF86ModuleData ch7017ModuleData = { + &ch7017VersRec, + ch7017Setup, + NULL +}; + +static pointer +ch7017Setup(pointer module, pointer opts, int *errmaj, int *errmin) { + return (pointer)1; +} diff --git a/src/ch7017/ch7017_reg.h b/src/ch7017/ch7017_reg.h new file mode 100644 index 00000000..89f81cc3 --- /dev/null +++ b/src/ch7017/ch7017_reg.h @@ -0,0 +1,150 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifndef CH7017_REG_H +#define CH7017_REG_H + +#define CH7017_TV_DISPLAY_MODE 0x00 +#define CH7017_FLICKER_FILTER 0x01 +#define CH7017_VIDEO_BANDWIDTH 0x02 +#define CH7017_TEXT_ENHANCEMENT 0x03 +#define CH7017_START_ACTIVE_VIDEO 0x04 +#define CH7017_HORIZONTAL_POSITION 0x05 +#define CH7017_VERTICAL_POSITION 0x06 +#define CH7017_BLACK_LEVEL 0x07 +#define CH7017_CONTRAST_ENHANCEMENT 0x08 +#define CH7017_TV_PLL 0x09 +#define CH7017_TV_PLL_M 0x0a +#define CH7017_TV_PLL_N 0x0b +#define CH7017_SUB_CARRIER_0 0x0c +#define CH7017_CIV_CONTROL 0x10 +#define CH7017_CIV_0 0x11 +#define CH7017_CHROMA_BOOST 0x14 +#define CH7017_CLOCK_MODE 0x1c +#define CH7017_INPUT_CLOCK 0x1d +#define CH7017_GPIO_CONTROL 0x1e +#define CH7017_INPUT_DATA_FORMAT 0x1f +#define CH7017_CONNECTION_DETECT 0x20 +#define CH7017_DAC_CONTROL 0x21 +#define CH7017_BUFFERED_CLOCK_OUTPUT 0x22 +#define CH7017_DEFEAT_VSYNC 0x47 +#define CH7017_TEST_PATTERN 0x48 + +#define CH7017_POWER_MANAGEMENT 0x49 +/** Enables the TV output path. */ +#define CH7017_TV_EN (1 << 0) +#define CH7017_DAC0_POWER_DOWN (1 << 1) +#define CH7017_DAC1_POWER_DOWN (1 << 2) +#define CH7017_DAC2_POWER_DOWN (1 << 3) +#define CH7017_DAC3_POWER_DOWN (1 << 4) +/** Powers down the TV out block, and DAC0-3 */ +#define CH7017_TV_POWER_DOWN_EN (1 << 5) + +#define CH7017_VERSION_ID 0x4a + +#define CH7017_DEVICE_ID 0x4b +#define CH7017_DEVICE_ID_VALUE 0x1b +#define CH7018_DEVICE_ID_VALUE 0x1a + +#define CH7017_XCLK_D2_ADJUST 0x53 +#define CH7017_UP_SCALER_COEFF_0 0x55 +#define CH7017_UP_SCALER_COEFF_1 0x56 +#define CH7017_UP_SCALER_COEFF_2 0x57 +#define CH7017_UP_SCALER_COEFF_3 0x58 +#define CH7017_UP_SCALER_COEFF_4 0x59 +#define CH7017_UP_SCALER_VERTICAL_INC_0 0x5a +#define CH7017_UP_SCALER_VERTICAL_INC_1 0x5b +#define CH7017_GPIO_INVERT 0x5c +#define CH7017_UP_SCALER_HORIZONTAL_INC_0 0x5d +#define CH7017_UP_SCALER_HORIZONTAL_INC_1 0x5e + +#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT 0x5f +/**< Low bits of horizontal active pixel input */ + +#define CH7017_ACTIVE_INPUT_LINE_OUTPUT 0x60 +/** High bits of horizontal active pixel input */ +#define CH7017_LVDS_HAP_INPUT_MASK (0x7 << 0) +/** High bits of vertical active line output */ +#define CH7017_LVDS_VAL_HIGH_MASK (0x7 << 3) + +#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT 0x61 +/**< Low bits of vertical active line output */ + +#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT 0x62 +/**< Low bits of horizontal active pixel output */ + +#define CH7017_LVDS_POWER_DOWN 0x63 +/** High bits of horizontal active pixel output */ +#define CH7017_LVDS_HAP_HIGH_MASK (0xf << 0) +/** Enables the LVDS power down state transition */ +#define CH7017_LVDS_POWER_DOWN_EN (1 << 6) +/** Enables the LVDS upscaler */ +#define CH7017_LVDS_UPSCALER_EN (1 << 7) + +#define CH7017_LVDS_ENCODING 0x64 +#define CH7017_LVDS_DITHER_2D (1 << 2) +#define CH7017_LVDS_DITHER_DIS (1 << 3) +#define CH7017_LVDS_DUAL_CHANNEL_EN (1 << 4) +#define CH7017_LVDS_24_BIT (1 << 5) + +#define CH7017_LVDS_ENCODING_2 0x65 + +#define CH7017_LVDS_PLL_CONTROL 0x66 +/** Enables the LVDS panel output path */ +#define CH7017_LVDS_PANEN (1 << 0) +/** Enables the LVDS panel backlight */ +#define CH7017_LVDS_BKLEN (1 << 3) + +#define CH7017_POWER_SEQUENCING_T1 0x67 +#define CH7017_POWER_SEQUENCING_T2 0x68 +#define CH7017_POWER_SEQUENCING_T3 0x69 +#define CH7017_POWER_SEQUENCING_T4 0x6a +#define CH7017_POWER_SEQUENCING_T5 0x6b +#define CH7017_GPIO_DRIVER_TYPE 0x6c +#define CH7017_GPIO_DATA 0x6d +#define CH7017_GPIO_DIRECTION_CONTROL 0x6e +#define CH7017_LVDS_PLL_FEEDBACK_DIV 0x71 +#define CH7017_LVDS_PLL_VCO_CONTROL 0x72 + +#define CH7017_OUTPUTS_ENABLE 0x73 +# define CH7017_LVDS_CHANNEL_A (1 << 3) +# define CH7017_LVDS_CHANNEL_B (1 << 4) +# define CH7017_TV_DAC_A (1 << 5) +# define CH7017_TV_DAC_B (1 << 6) +# define CH7017_DDC_SELECT_DC2 (1 << 7) + +#define CH7017_LVDS_OUTPUT_AMPLITUDE 0x74 +#define CH7017_LVDS_PLL_EMI_REDUCTION 0x75 +#define CH7017_LVDS_POWER_DOWN_FLICKER 0x76 + +#define CH7017_LVDS_CONTROL_2 0x78 +# define CH7017_LOOP_FILTER_SHIFT 5 +# define CH7017_PHASE_DETECTOR_SHIFT 0 + +#define CH7017_BANG_LIMIT_CONTROL 0x7f + +#endif /* CH7017_REG_H */ diff --git a/src/i830.h b/src/i830.h index 6c03a73f..a03f8774 100644 --- a/src/i830.h +++ b/src/i830.h @@ -195,9 +195,10 @@ extern const char *i830_output_type_names[]; typedef struct _I830CrtcPrivateRec { int pipe; - Bool gammaEnabled; Rotation rotation; /* current rotation, mirror from pI830->rotation */ Rotation rotations; /* all */ + /* Lookup table values to be set when the CRTC is enabled */ + CARD8 lut_r[256], lut_g[256], lut_b[256]; } I830CrtcPrivateRec, *I830CrtcPrivatePtr; #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private) @@ -224,7 +225,6 @@ enum last_3d { typedef struct _I830PipeRec { Bool enabled; - Bool gammaEnabled; int x; int y; Bool cursorInRange; @@ -609,14 +609,6 @@ DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output); /* i830_tv.c */ void i830_tv_init(ScrnInfoPtr pScrn); -/* - * 12288 is set as the maximum, chosen because it is enough for - * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. - */ -#define I830_MAXIMUM_VBIOS_MEM 12288 -#define I830_DEFAULT_VIDEOMEM_2D (MB(32) / 1024) -#define I830_DEFAULT_VIDEOMEM_3D (MB(64) / 1024) - /* Flags for memory allocation function */ #define FROM_ANYWHERE 0x00000000 #define FROM_POOL_ONLY 0x00000001 @@ -641,14 +633,6 @@ void i830_tv_init(ScrnInfoPtr pScrn); #define _845_DRAM_RW_CONTROL 0x90 #define DRAM_WRITE 0x33330000 -/* Compat definitions for older X Servers. */ -#ifndef M_T_PREFERRED -#define M_T_PREFERRED 0x08 -#endif -#ifndef M_T_DRIVER -#define M_T_DRIVER 0x40 -#endif - /* * Xserver MM compatibility. Remove code guarded by this when the * XServer contains the libdrm mm code diff --git a/src/i830_crt.c b/src/i830_crt.c index 3be10ecc..4e9e3706 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -328,38 +328,6 @@ i830_crt_detect(xf86OutputPtr output) return XF86OutputStatusUnknown; } -static DisplayModePtr -i830_crt_get_modes(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - DisplayModePtr modes; - MonRec fixed_mon; - - modes = i830_ddc_get_modes(output); - if (modes != NULL) - return modes; - - if ((*output->funcs->detect)(output) == XF86OutputStatusDisconnected) - return NULL; - - /* We've got a potentially-connected monitor that we can't DDC. Return a - * fixed set of VESA plus user modes for a presumed multisync monitor with - * some reasonable limits. - */ - fixed_mon.nHsync = 1; - fixed_mon.hsync[0].lo = 31.0; - fixed_mon.hsync[0].hi = 100.0; - fixed_mon.nVrefresh = 1; - fixed_mon.vrefresh[0].lo = 50.0; - fixed_mon.vrefresh[0].hi = 70.0; - - modes = xf86DuplicateModes(pScrn, pScrn->monitor->Modes); - i830xf86ValidateModesSync(pScrn, modes, &fixed_mon); - i830xf86PruneInvalidModes(pScrn, &modes, TRUE); - - return modes; -} - static void i830_crt_destroy (xf86OutputPtr output) { @@ -375,7 +343,7 @@ static const xf86OutputFuncsRec i830_crt_output_funcs = { .mode_fixup = i830_crt_mode_fixup, .mode_set = i830_crt_mode_set, .detect = i830_crt_detect, - .get_modes = i830_crt_get_modes, + .get_modes = i830_ddc_get_modes, .destroy = i830_crt_destroy }; @@ -397,6 +365,8 @@ i830_crt_init(ScrnInfoPtr pScrn) i830_output->type = I830_OUTPUT_ANALOG; output->driver_private = i830_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; /* Set up the DDC bus. */ I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A"); diff --git a/src/i830_cursor.c b/src/i830_cursor.c index cb1585fb..81cb3bd8 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -130,9 +130,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force) temp = INREG(cursor_control); temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (pI830->CursorIsARGB) { - temp |= CURSOR_MODE_64_ARGB_AX; - if (intel_crtc->gammaEnabled) - temp |= MCURSOR_GAMMA_ENABLE; + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; } else temp |= CURSOR_MODE_64_4C_AX; @@ -144,9 +142,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force) temp &= ~(CURSOR_FORMAT_MASK); temp |= CURSOR_ENABLE; if (pI830->CursorIsARGB) { - temp |= CURSOR_FORMAT_ARGB; - if (intel_crtc->gammaEnabled) - temp |= CURSOR_GAMMA_ENABLE; + temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; } else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); diff --git a/src/i830_debug.c b/src/i830_debug.c index 25245fb2..897ab926 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -32,6 +32,7 @@ #include "xf86.h" #include "i830.h" #include "i830_debug.h" +#include #define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val) diff --git a/src/i830_display.c b/src/i830_display.c index b70f1ebd..3f9d882d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -350,10 +350,13 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) } if (IS_I965G(pI830)) { - OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp)); - OUTREG(dspsurf, Start); + OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp)); + (void) INREG(dspbase); + OUTREG(dspsurf, Start); + (void) INREG(dspsurf); } else { OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + (void) INREG(dspbase); } crtc->x = x; @@ -533,6 +536,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) OUTREG(dspbase_reg, INREG(dspbase_reg)); } + i830_crtc_load_lut(crtc); + /* Give the overlay scaler a chance to enable if it's on this pipe */ i830_crtc_dpms_video(crtc, TRUE); break; @@ -603,7 +608,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; @@ -716,10 +720,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, dpll |= PLL_REF_INPUT_DREFCLK; /* Set up the display plane register */ - dspcntr = 0; + dspcntr = DISPPLANE_GAMMA_ENABLE; switch (pScrn->bitsPerPixel) { case 8: - dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE; + dspcntr |= DISPPLANE_8BPP; break; case 16: if (pScrn->depth == 15) @@ -734,10 +738,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, FatalError("unknown display bpp\n"); } - if (intel_crtc->gammaEnabled) { - dspcntr |= DISPPLANE_GAMMA_ENABLE; - } - if (pipe == 0) dspcntr |= DISPPLANE_SEL_PIPE_A; else @@ -830,17 +830,58 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1)); OUTREG(dsppos_reg, 0); OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); - i830PipeSetBase(crtc, crtc->x, crtc->y); OUTREG(pipeconf_reg, pipeconf); i830WaitForVblank(pScrn); OUTREG(dspcntr_reg, dspcntr); /* Flush the plane changes */ - OUTREG(dspbase_reg, INREG(dspbase_reg)); + i830PipeSetBase(crtc, crtc->x, crtc->y); i830WaitForVblank(pScrn); } + +/** Loads the palette/gamma unit for the CRTC with the prepared values */ +void +i830_crtc_load_lut(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; + int i; + + /* The clocks have to be on to load the palette. */ + if (!crtc->enabled) + return; + + for (i = 0; i < 256; i++) { + OUTREG(palreg + 4 * i, + (intel_crtc->lut_r[i] << 16) | + (intel_crtc->lut_g[i] << 8) | + intel_crtc->lut_b[i]); + } +} + +/** Sets the color ramps on behalf of RandR */ +static void +i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, + int size) +{ + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int i; + + assert(size == 256); + + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = red[i] >> 8; + intel_crtc->lut_g[i] = green[i] >> 8; + intel_crtc->lut_b[i] = blue[i] >> 8; + } + + i830_crtc_load_lut(crtc); +} + /** * Sets the given video mode on the given pipe. * @@ -1148,6 +1189,7 @@ static const xf86CrtcFuncsRec i830_crtc_funcs = { .restore = NULL, /* XXX */ .mode_fixup = i830_crtc_mode_fixup, .mode_set = i830_crtc_mode_set, + .gamma_set = i830_crtc_gamma_set, .destroy = NULL, /* XXX */ }; @@ -1156,6 +1198,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pipe) { xf86CrtcPtr crtc; I830CrtcPrivatePtr intel_crtc; + int i; crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs); if (crtc == NULL) @@ -1164,6 +1207,12 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pipe) intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1); intel_crtc->pipe = pipe; + /* Initialize the LUTs for when we turn on the CRTC. */ + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = i; + intel_crtc->lut_g[i] = i; + intel_crtc->lut_b[i] = i; + } crtc->driver_private = intel_crtc; } diff --git a/src/i830_display.h b/src/i830_display.h index 8a982abc..66ab17e8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -42,14 +42,4 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output); void i830ReleaseLoadDetectPipe(xf86OutputPtr output); Bool i830PipeInUse(xf86CrtcPtr crtc); void i830_crtc_init(ScrnInfoPtr pScrn, int pipe); - -/** @{ - */ -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) -DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); -DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, - Bool Reduced, Bool Interlaced); -#define xf86DDCGetModes i830_xf86DDCGetModes -#define xf86CVTMode i830_xf86CVTMode -#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2) */ -/** @} */ +void i830_crtc_load_lut(xf86CrtcPtr crtc); diff --git a/src/i830_dri.c b/src/i830_dri.c index c5d7a94e..eeef2895 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -216,9 +216,9 @@ I830InitVisualConfigs(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); int numConfigs = 0; - __GLXvisualConfig *pConfigs = 0; - I830ConfigPrivPtr pI830Configs = 0; - I830ConfigPrivPtr *pI830ConfigPtrs = 0; + __GLXvisualConfig *pConfigs = NULL; + I830ConfigPrivPtr pI830Configs = NULL; + I830ConfigPrivPtr *pI830ConfigPtrs = NULL; int accum, stencil, db, depth; int i; @@ -538,7 +538,7 @@ I830DRIScreenInit(ScreenPtr pScreen) if (!(pI830DRI = (I830DRIPtr) xcalloc(sizeof(I830DRIRec), 1))) { DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; return FALSE; } pDRIInfo->devPrivate = pI830DRI; @@ -561,9 +561,9 @@ I830DRIScreenInit(ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); xfree(pDRIInfo->devPrivate); - pDRIInfo->devPrivate = 0; + pDRIInfo->devPrivate = NULL; DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; return FALSE; } @@ -655,11 +655,14 @@ I830DRIScreenInit(ScreenPtr pScreen) } pI830->drmMinor = version->version_minor; if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) { +#ifdef XF86DRI_MM if ((version->version_major > 1) || ((version->version_minor >= 7) && (version->version_major == 1))) { pI830->mmModeFlags |= I830_KERNEL_MM; - } else { + } else +#endif + { pI830->mmModeFlags |= I830_KERNEL_TEX; } } else { @@ -948,10 +951,10 @@ I830DRICloseScreen(ScreenPtr pScreen) if (pI830->pDRIInfo) { if (pI830->pDRIInfo->devPrivate) { xfree(pI830->pDRIInfo->devPrivate); - pI830->pDRIInfo->devPrivate = 0; + pI830->pDRIInfo->devPrivate = NULL; } DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; } if (pI830->pVisualConfigs) xfree(pI830->pVisualConfigs); @@ -1022,7 +1025,7 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) } } -void +static void I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext) @@ -1032,7 +1035,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, if (syncType == DRI_3D_SYNC && oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (in)\n"); @@ -1125,9 +1127,9 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, BoxPtr pbox = REGION_RECTS(prgnSrc); int nbox = REGION_NUM_RECTS(prgnSrc); - BoxPtr pboxNew1 = 0; - BoxPtr pboxNew2 = 0; - DDXPointPtr pptNew1 = 0; + BoxPtr pboxNew1 = NULL; + BoxPtr pboxNew2 = NULL; + DDXPointPtr pptNew1 = NULL; DDXPointPtr pptSrc = &ptOldOrg; int dx = pParent->drawable.x - ptOldOrg.x; diff --git a/src/i830_driver.c b/src/i830_driver.c index 5e66038c..33c3f609 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -581,106 +581,67 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - I830Ptr pI830; int i,j, index; - unsigned char r, g, b; - CARD32 val, temp; - int palreg; - int dspreg, dspbase, dspsurf; int p; + CARD16 lut_r[256], lut_g[256], lut_b[256]; DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); - pI830 = I830PTR(pScrn); - for(p=0; p < xf86_config->num_crtc; p++) - { + for(p = 0; p < xf86_config->num_crtc; p++) { xf86CrtcPtr crtc = xf86_config->crtc[p]; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - if (p == 0) { - palreg = PALETTE_A; - dspreg = DSPACNTR; - dspbase = DSPABASE; - dspsurf = DSPASURF; - } else { - palreg = PALETTE_B; - dspreg = DSPBCNTR; - dspbase = DSPBBASE; - dspsurf = DSPBSURF; + /* Initialize to the old lookup table values. */ + for (i = 0; i < 256; i++) { + lut_r[i] = intel_crtc->lut_r[i] << 8; + lut_g[i] = intel_crtc->lut_g[i] << 8; + lut_b[i] = intel_crtc->lut_b[i] << 8; } - if (crtc->enabled == 0) - continue; - - intel_crtc->gammaEnabled = 1; - - /* To ensure gamma is enabled we need to turn off and on the plane */ - temp = INREG(dspreg); - OUTREG(dspreg, temp & ~(1<<31)); - OUTREG(dspbase, INREG(dspbase)); - OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE); - OUTREG(dspbase, INREG(dspbase)); - if (IS_I965G(pI830)) - OUTREG(dspsurf, INREG(dspsurf)); - - /* It seems that an initial read is needed. */ - temp = INREG(palreg); - switch(pScrn->depth) { case 15: - for (i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index].red; - g = colors[index].green; - b = colors[index].blue; - val = (r << 16) | (g << 8) | b; - for (j = 0; j < 8; j++) { - OUTREG(palreg + index * 32 + (j * 4), val); + for (i = 0; i < numColors; i++) { + index = indices[i]; + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_g[index * 8 + j] = colors[index].green << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } } - } - break; + break; case 16: - for (i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index / 2].red; - g = colors[index].green; - b = colors[index / 2].blue; + for (i = 0; i < numColors; i++) { + index = indices[i]; - val = (r << 16) | (g << 8) | b; - OUTREG(palreg + index * 16, val); - OUTREG(palreg + index * 16 + 4, val); - OUTREG(palreg + index * 16 + 8, val); - OUTREG(palreg + index * 16 + 12, val); + if (i <= 31) { + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } - if (index <= 31) { - r = colors[index].red; - g = colors[(index * 2) + 1].green; - b = colors[index].blue; - - val = (r << 16) | (g << 8) | b; - OUTREG(palreg + index * 32, val); - OUTREG(palreg + index * 32 + 4, val); - OUTREG(palreg + index * 32 + 8, val); - OUTREG(palreg + index * 32 + 12, val); - } - } + for (j = 0; j < 4; j++) { + lut_g[index * 4 + j] = colors[index].green << 8; + } + } break; default: - for(i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index].red; - g = colors[index].green; - b = colors[index].blue; - val = (r << 16) | (g << 8) | b; - OUTREG(palreg + index * 4, val); - } - break; - } + for (i = 0; i < numColors; i++) { + index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + } + break; + } + + /* Make the change through RandR */ +#ifdef RANDR_12_INTERFACE + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); +#else + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); +#endif } - - /* Enable gamma for Cursor if ARGB */ - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) - pI830->CursorInfoRec->ShowCursor(pScrn); } int @@ -914,7 +875,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) Bool enable; const char *chipname; int num_pipe; - int max_width; + int max_width, max_height; #ifdef XF86DRI unsigned long savedMMSize; #endif @@ -1188,10 +1149,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); if (IS_I965G(pI830)) + { max_width = 16384; + max_height = 4096; + } else - max_width = 8192 / pI830->cpp; - xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048); + { + max_width = 2048; + max_height = 2048; + } + xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height); /* Some of the probing needs MMIO access, so map it here. */ I830MapMMIO(pScrn); @@ -1451,52 +1418,26 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->checkDevices = FALSE; /* - * The "VideoRam" config file parameter specifies the total amount of - * memory that will be used/allocated. When agpgart support isn't - * available (StolenOnly == TRUE), this is limited to the amount of - * pre-allocated ("stolen") memory. - */ - - /* - * Default to I830_DEFAULT_VIDEOMEM_2D (8192KB) for 2D-only, - * or I830_DEFAULT_VIDEOMEM_3D (32768KB) for 3D. If the stolen memory - * amount is higher, default to it rounded up to the nearest MB. This - * guarantees that by default there will be at least some run-time - * space for things that need a physical address. - * But, we double the amounts when dual head is enabled, and therefore - * for 2D-only we use 16384KB, and 3D we use 65536KB. The VideoRAM - * for the second head is never used, as the primary head does the - * allocation. + * The "VideoRam" config file parameter specifies the maximum amount of + * memory that will be used/allocated. When not present, we allow the + * driver to allocate as much memory as it wishes to satisfy its + * allocations, but if agpgart support isn't available (StolenOnly == TRUE), + * it gets limited to the amount of pre-allocated ("stolen") memory. */ if (!pI830->pEnt->device->videoRam) { from = X_DEFAULT; -#ifdef XF86DRI - if (!pI830->directRenderingDisabled) - pScrn->videoRam = I830_DEFAULT_VIDEOMEM_3D; - else -#endif - pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D; - - if (xf86IsEntityShared(pScrn->entityList[0])) { - if (I830IsPrimary(pScrn)) - pScrn->videoRam += I830_DEFAULT_VIDEOMEM_2D; - else - pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM; - } - - if (pI830->StolenMemory.Size / 1024 > pScrn->videoRam) - pScrn->videoRam = ROUND_TO(pI830->StolenMemory.Size / 1024, 1024); + pScrn->videoRam = pI830->FbMapSize / KB(1); } else { from = X_CONFIG; pScrn->videoRam = pI830->pEnt->device->videoRam; } /* Make sure it's on a page boundary */ - if (pScrn->videoRam & (GTT_PAGE_SIZE - 1)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "VideoRAM reduced to %d kByte " - "(page aligned - was %d)\n", pScrn->videoRam & ~(GTT_PAGE_SIZE - 1), pScrn->videoRam); - pScrn->videoRam &= ~(GTT_PAGE_SIZE - 1); + if (pScrn->videoRam & 3) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " + "(page aligned - was %d KB)\n", + pScrn->videoRam & ~3, pScrn->videoRam); + pScrn->videoRam &= ~3; } DPRINTF(PFX, @@ -1524,9 +1465,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Pre-allocated VideoRAM: %ld kByte\n", + "Pre-allocated VideoRam: %ld kByte\n", pI830->StolenMemory.Size / 1024); - xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", + xf86DrvMsg(pScrn->scrnIndex, from, "Potential VideoRam: %d kByte\n", pScrn->videoRam); pI830->TotalVideoRam = KB(pScrn->videoRam); @@ -1657,9 +1598,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024); } - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - if (!xf86RandR12PreInit (pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); @@ -1693,9 +1631,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pScrn->currentMode = pScrn->modes; -#ifndef USE_PITCHES -#define USE_PITCHES 1 -#endif pI830->disableTiling = FALSE; /* @@ -1715,18 +1650,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) { int savedDisplayWidth = pScrn->displayWidth; int memNeeded = 0; - /* Good pitches to allow tiling. Don't care about pitches < 1024. */ - static const int pitches[] = { -/* - 128 * 2, - 128 * 4, -*/ - 128 * 8, - 128 * 16, - 128 * 32, - 128 * 64, - 0 - }; + Bool tiled = FALSE; #ifdef I830_XV /* @@ -1736,16 +1660,28 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->XvEnabled = !pI830->XvDisabled; #endif - for (i = 0; pitches[i] != 0; i++) { -#if USE_PITCHES - if (pitches[i] >= pScrn->displayWidth) { - pScrn->displayWidth = pitches[i]; - break; + if (IS_I965G(pI830)) { + int tile_pixels = 512 / pI830->cpp; + pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) & + ~(tile_pixels - 1); + tiled = TRUE; + } else { + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + static const int pitches[] = { + KB(1), + KB(2), + KB(4), + KB(8), + 0 + }; + + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= pScrn->displayWidth) { + pScrn->displayWidth = pitches[i]; + tiled = TRUE; + break; + } } -#else - if (pitches[i] == pScrn->displayWidth) - break; -#endif } /* @@ -1753,7 +1689,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * memory available to enable tiling. */ savedMMSize = pI830->mmSize; - if (pScrn->displayWidth == pitches[i]) { + if (tiled) { retry_dryrun: I830ResetAllocations(pScrn, 0); if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) && @@ -1772,7 +1708,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) "to make room in AGP aperture for tiling."); goto retry_dryrun; } - + /* XXX */ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation with DRI tiling enabled would " "exceed the\n" @@ -1841,14 +1777,35 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) #endif pI830->disableTiling = TRUE; /* no DRI - so disableTiling */ - if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) { + if (pI830->pEnt->device->videoRam == 0) { + int default_videoram; + + /* Now that we've sized the allocations, reduce our default VideoRam + * allocation from the aperture size to just what we need to cover our + * allocations. Only, put in some slop for alignment and such. + */ + default_videoram = pI830->StolenPool.Total.Size + pI830->allocatedMemory; + default_videoram += KB(512); /* slop */ + /* align to 1MB increments */ + default_videoram = (default_videoram + MB(1) - 1) / MB(1) * MB(1); + + if (default_videoram < KB(pScrn->videoRam)) { + pScrn->videoRam = default_videoram / KB(1); + pI830->TotalVideoRam = KB(pScrn->videoRam); + } + } + xf86DrvMsg(pScrn->scrnIndex, + pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, + "VideoRam: %d KB\n", pScrn->videoRam); + + if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Cannot support DRI with frame buffer stride > 8K.\n"); + "Cannot support DRI with frame buffer width > 2048.\n"); pI830->disableTiling = TRUE; pI830->directRenderingDisabled = TRUE; } - if (pScrn->virtualY > 2048) { + if (!IS_I965G(pI830) && pScrn->virtualY > 2048) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n"); pI830->noAccel = TRUE; } @@ -2480,11 +2437,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn) } } -#ifdef XF86DRI -#ifndef DRM_BO_MEM_TT -#error "Wrong drm.h file included. You need to compile and install a recent libdrm." -#endif - +#ifdef XF86DRI_MM #ifndef XSERVER_LIBDRM_MM static int @@ -2559,7 +2512,7 @@ static int I830DrmMMUnlock(int fd, unsigned memType) } #endif -#endif +#endif /* XF86DRI_MM */ static Bool I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) @@ -2860,20 +2813,28 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) DPRINTF(PFX, "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); - if (I830IsPrimary(pScrn)) { - if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to init memory manager\n"); - } + if (!pI830->useEXA) { + if (I830IsPrimary(pScrn)) { + if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + } - if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.Size / pI830->cpp)) - xf86DrvMsg(scrnIndex, X_INFO, - "Using %ld bytes of offscreen memory for linear (offset=0x%lx)\n", pI830->LinearMem.Size, pI830->LinearMem.Offset); - - } else { - if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to init memory manager\n"); + if (pI830->LinearAlloc && + xf86InitFBManagerLinear(pScreen, + pI830->LinearMem.Offset / pI830->cpp, + pI830->LinearMem.Size / pI830->cpp)) + { + xf86DrvMsg(scrnIndex, X_INFO, + "Using %ld bytes of offscreen memory for linear " + "(offset=0x%lx)\n", pI830->LinearMem.Size, + pI830->LinearMem.Offset); + } + } else { + if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + } } } @@ -3004,7 +2965,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) break; } -#ifdef XF86DRI +#ifdef XF86DRI_MM if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) { unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) / GTT_PAGE_SIZE; @@ -3043,7 +3004,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } } -#endif +#endif /* XF86DRI_MM */ return TRUE; } @@ -3054,7 +3015,8 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); - xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); @@ -3066,7 +3028,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) (*pI830->AccelInfoRec->Sync)(pScrn); pI830->AccelInfoRec->NeedToSync = FALSE; } - i830PipeSetBase(crtc, x, y); + i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y); } } @@ -3104,6 +3066,7 @@ I830LeaveVT(int scrnIndex, int flags) #ifdef XF86DRI if (pI830->directRenderingOpen) { DRILock(screenInfo.screens[pScrn->scrnIndex], 0); +#ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM I830DrmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); @@ -3111,6 +3074,7 @@ I830LeaveVT(int scrnIndex, int flags) drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); #endif } +#endif /* XF86DRI_MM */ I830DRISetVBlankInterrupt (pScrn, FALSE); drmCtlUninstHandler(pI830->drmSubFD); @@ -3188,8 +3152,6 @@ I830EnterVT(int scrnIndex, int flags) if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE)) return FALSE; - - i830PipeSetBase(crtc, crtc->x, crtc->y); } i830DumpRegs (pScrn); @@ -3224,6 +3186,7 @@ I830EnterVT(int scrnIndex, int flags) for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++) sarea->texList[i].age = sarea->texAge; +#ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); @@ -3231,6 +3194,7 @@ I830EnterVT(int scrnIndex, int flags) drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); #endif } +#endif /* XF86DRI_MM */ DPRINTF(PFX, "calling dri unlock\n"); DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); @@ -3373,6 +3337,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->closing = TRUE; #ifdef XF86DRI if (pI830->directRenderingOpen) { +#ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); @@ -3380,6 +3345,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); #endif } +#endif /* XF86DRI_MM */ pI830->directRenderingOpen = FALSE; I830DRICloseScreen(pScreen); } @@ -3598,7 +3564,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) * is this. */ - xf86ProbeOutputModes (pScrn); + xf86ProbeOutputModes (pScrn, 0, 0); xf86SetScrnInfoModes (pScrn); I830DGAReInit (pScrn->pScreen); xf86SwitchMode(pScrn->pScreen, pScrn->currentMode); diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 97453ded..d938f466 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -45,13 +45,34 @@ static const char *CH7xxxSymbols[] = { NULL }; +#if 0 +static const char *ivch_symbols[] = { + "ivch_methods", + NULL +}; +#endif +#if 0 +static const char *ch7017_symbols[] = { + "ch7017_methods", + NULL +}; +#endif + /* driver list */ struct _I830DVODriver i830_dvo_drivers[] = { - { I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", - (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL}, - { I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", - (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL} + {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", + (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL}, + {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", + (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}, + /* + {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", + (0x2 << 1), ivch_symbols, NULL, NULL, NULL}, + */ + /* + { I830_DVO_CHIP_LVDS, "ch7017", "ch7017_methods", + (CH7017_ADDR_1 << 1), ch7017_symbols, NULL, NULL, NULL } + */ }; #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) @@ -183,37 +204,6 @@ i830_dvo_detect(xf86OutputPtr output) return intel_output->i2c_drv->vid_rec->detect(dev_priv); } -static Bool -I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, - struct _I830DVODriver **retdrv) -{ - int i; - void *ret_ptr; - struct _I830DVODriver *drv; - - for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) { - drv = &i830_dvo_drivers[i]; - drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename); - if (drv->modhandle == NULL) - continue; - - xf86LoaderReqSymLists(drv->symbols, NULL); - - ret_ptr = NULL; - drv->vid_rec = LoaderSymbol(drv->fntablename); - if (drv->vid_rec != NULL) - ret_ptr = drv->vid_rec->init(pI2CBus, drv->address); - - if (ret_ptr != NULL) { - drv->dev_priv = ret_ptr; - *retdrv = drv; - return TRUE; - } - xf86UnloadSubModule(drv->modhandle); - } - return FALSE; -} - static void i830_dvo_destroy (xf86OutputPtr output) { @@ -245,9 +235,14 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = { void i830_dvo_init(ScrnInfoPtr pScrn) { - xf86OutputPtr output; - I830OutputPrivatePtr intel_output; - int ret; + xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + int ret; + int i; + void *ret_ptr; + struct _I830DVODriver *drv; + int gpio_inited = 0; + I2CBusPtr pI2CBus = NULL; output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs, "TMDS"); @@ -262,15 +257,10 @@ i830_dvo_init(ScrnInfoPtr pScrn) intel_output->type = I830_OUTPUT_DVO; output->driver_private = intel_output; output->subpixel_order = SubPixelHorizontalRGB; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; - /* Set up the I2C and DDC buses */ - ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E"); - if (!ret) - { - xf86OutputDestroy (output); - return; - } - + /* Set up the DDC bus */ ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D"); if (!ret) { @@ -279,17 +269,51 @@ i830_dvo_init(ScrnInfoPtr pScrn) } /* Now, try to find a controller */ - ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus, - &intel_output->i2c_drv); - if (ret) - { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", - intel_output->i2c_drv->modulename, - intel_output->pI2CBus->DriverPrivate.uval); - } - else - { - xf86OutputDestroy (output); - return; + for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) { + int gpio; + + drv = &i830_dvo_drivers[i]; + drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename); + if (drv->modhandle == NULL) + continue; + + xf86LoaderReqSymLists(drv->symbols, NULL); + + ret_ptr = NULL; + drv->vid_rec = LoaderSymbol(drv->fntablename); + + if (drv->type & I830_DVO_CHIP_LVDS) + gpio = GPIOB; + else + gpio = GPIOE; + + /* Set up the I2C bus necessary for the chip we're probing. It appears + * that everything is on GPIOE except for panels on i830 laptops, which + * are on GPIOB (DVOA). + */ + if (gpio_inited != gpio) { + if (pI2CBus != NULL) + xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); + if (!I830I2CInit(pScrn, &pI2CBus, gpio, + gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) { + continue; + } + } + + if (drv->vid_rec != NULL) + ret_ptr = drv->vid_rec->init(pI2CBus, drv->address); + + if (ret_ptr != NULL) { + drv->dev_priv = ret_ptr; + intel_output->i2c_drv = drv; + intel_output->pI2CBus = pI2CBus; + return; + } + xf86UnloadSubModule(drv->modhandle); } + + /* Didn't find a chip, so tear down. */ + if (pI2CBus != NULL) + xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); + xf86OutputDestroy (output); } diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c index 5cef46db..31ce1000 100644 --- a/src/i830_edid_modes.c +++ b/src/i830_edid_modes.c @@ -37,6 +37,8 @@ #include "xf86DDC.h" #include "i830.h" #include "i830_display.h" +#include +#include #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) @@ -48,6 +50,8 @@ typedef enum { DDC_QUIRK_NONE = 0, /* Force detailed sync polarity to -h +v */ DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0, + /* First detailed mode is bogus, prefer largest mode at 60hz */ + DDC_QUIRK_PREFER_LARGE_60 = 1 << 1, } ddc_quirk_t; static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC) @@ -64,6 +68,16 @@ static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC) return FALSE; } +static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) +{ + /* Belinea 10 15 55 */ + if (memcmp (DDC->vendor.name, "MAX", 4) == 0 && + DDC->vendor.prod_id == 1516) + return TRUE; + + return FALSE; +} + typedef struct { Bool (*detect) (int scrnIndex, xf86MonPtr DDC); ddc_quirk_t quirk; @@ -75,6 +89,10 @@ static const ddc_quirk_map_t ddc_quirks[] = { quirk_dt_sync_hm_vp, DDC_QUIRK_DT_SYNC_HM_VP, "Set detailed timing sync polarity to -h +v" }, + { + quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60, + "Detailed timing is not preferred, use largest mode at 60Hz" + }, { NULL, DDC_QUIRK_NONE, "No known quirks" @@ -234,8 +252,9 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) quirks |= ddc_quirks[i].quirk; } - preferred = PREFERRED_TIMING_MODE(DDC->features.msc); + if (quirks & DDC_QUIRK_PREFER_LARGE_60) + preferred = 0; for (i = 0; i < DET_TIMINGS; i++) { struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; @@ -268,6 +287,33 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks); Modes = xf86ModesAdd(Modes, Mode); + if (quirks & DDC_QUIRK_PREFER_LARGE_60) + { + DisplayModePtr best = Modes; + for (Mode = Modes; Mode; Mode = Mode->next) + { + if (Mode == best) continue; + if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay) + { + best = Mode; + continue; + } + if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay) + { + double mode_refresh = xf86ModeVRefresh (Mode); + double best_refresh = xf86ModeVRefresh (best); + double mode_dist = fabs(mode_refresh - 60.0); + double best_dist = fabs(best_refresh - 60.0); + if (mode_dist < best_dist) + { + best = Mode; + continue; + } + } + } + if (best) + best->type |= M_T_PREFERRED; + } return Modes; } diff --git a/src/i830_exa.c b/src/i830_exa.c index dae8919a..3e874c97 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -36,6 +36,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i810_reg.h" #include "i830_reg.h" +#include #ifdef I830DEBUG #define DEBUG_I830FALLBACK 1 diff --git a/src/i830_lvds.c b/src/i830_lvds.c index b682b27f..18ac76bf 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -127,7 +127,19 @@ i830_lvds_restore(xf86OutputPtr output) static int i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { - return MODE_OK; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr pFixedMode = pI830->panel_fixed_mode; + + if (pFixedMode) + { + if (pMode->HDisplay > pFixedMode->HDisplay) + return MODE_PANEL; + if (pMode->VDisplay > pFixedMode->VDisplay) + return MODE_PANEL; + } + + return MODE_OK; } static Bool @@ -236,14 +248,37 @@ i830_lvds_detect(xf86OutputPtr output) static DisplayModePtr i830_lvds_get_modes(xf86OutputPtr output) { - ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr modes; + I830OutputPrivatePtr intel_output = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + xf86MonPtr edid_mon; + DisplayModePtr modes; - modes = i830_ddc_get_modes(output); + edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus); + i830_xf86OutputSetEDID (output, edid_mon); + + modes = i830_xf86OutputGetEDIDModes (output); if (modes != NULL) return modes; + if (!output->MonInfo) + { + edid_mon = xcalloc (1, sizeof (xf86Monitor)); + if (edid_mon) + { + /* Set wide sync ranges so we get all modes + * handed to valid_mode for checking + */ + edid_mon->det_mon[0].type = DS_RANGES; + edid_mon->det_mon[0].section.ranges.min_v = 0; + edid_mon->det_mon[0].section.ranges.max_v = 200; + edid_mon->det_mon[0].section.ranges.min_h = 0; + edid_mon->det_mon[0].section.ranges.max_h = 200; + + output->MonInfo = edid_mon; + } + } + if (pI830->panel_fixed_mode != NULL) return xf86DuplicateMode(pI830->panel_fixed_mode); @@ -326,6 +361,8 @@ i830_lvds_init(ScrnInfoPtr pScrn) intel_output->type = I830_OUTPUT_LVDS; output->driver_private = intel_output; output->subpixel_order = SubPixelHorizontalRGB; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_memory.c b/src/i830_memory.c index 69448636..29108c52 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -438,20 +438,33 @@ AllocateOverlay(ScrnInfoPtr pScrn, int flags) #endif static Bool -IsTileable(int pitch) +IsTileable(ScrnInfoPtr pScrn, int pitch) { + I830Ptr pI830 = I830PTR(pScrn); + + if (IS_I965G(pI830)) { + if (pitch / 512 * 512 == pitch && pitch <= KB(128)) + return TRUE; + else + return FALSE; + } + /* * Allow tiling for pitches that are a power of 2 multiple of 128 bytes, * up to 64 * 128 (= 8192) bytes. */ switch (pitch) { - case 128 * 1: - case 128 * 2: - case 128 * 4: - case 128 * 8: - case 128 * 16: - case 128 * 32: - case 128 * 64: + case 128: + case 256: + if (IS_I945G(pI830) || IS_I945GM(pI830)) + return TRUE; + else + return FALSE; + case 512: + case KB(1): + case KB(2): + case KB(4): + case KB(8): return TRUE; default: return FALSE; @@ -475,7 +488,7 @@ I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, int flags) memset(&(pI830->RotatedMem), 0, sizeof(I830MemRange)); pI830->RotatedMem.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -562,7 +575,7 @@ I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, int flags) memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange)); pI830->RotatedMem2.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); + IsTileable(pScrn, pI830Ent->pScrn_2->displayWidth * pI8302->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -624,11 +637,141 @@ GetFreeSpace(ScrnInfoPtr pScrn) return extra; } +/** + * Allocates a framebuffer for a screen. + * + * Used once for each X screen, so once with RandR 1.2 and twice with classic + * dualhead. + * + * \param pScrn ScrnInfoPtr for the screen being allocated + * \param pI830 I830Ptr for the screen being allocated. + * \param FbMemBox + */ +static Bool +I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, + I830MemRange *FrontBuffer, I830MemPool *StolenPool, + Bool secondary, const int flags) +{ + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + unsigned long minspace, avail, lineSize; + int cacheLines, maxCacheLines; + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + Bool tileable; + int align, alignflags; + long size, alloced, fb_height; + + /* Clear everything first. */ + memset(FbMemBox, 0, sizeof(*FbMemBox)); + memset(FrontBuffer, 0, sizeof(*FrontBuffer)); + FrontBuffer->Key = -1; + + /* We'll allocate the fb such that the root window will fit regardless of + * rotation. + */ + if (pScrn->virtualX > pScrn->virtualY) + fb_height = pScrn->virtualX; + else + fb_height = pScrn->virtualY; + + FbMemBox->x1 = 0; + FbMemBox->x2 = pScrn->displayWidth; + FbMemBox->y1 = 0; + FbMemBox->y2 = fb_height; + + /* Calculate how much framebuffer memory to allocate. For the + * initial allocation, calculate a reasonable minimum. This is + * enough for the virtual screen size, plus some pixmap cache + * space if we're using XAA. + */ + + lineSize = pScrn->displayWidth * pI830->cpp; + minspace = lineSize * pScrn->virtualY; + avail = pScrn->videoRam * 1024; + + if (!pI830->useEXA) { + maxCacheLines = (avail - minspace) / lineSize; + /* This shouldn't happen. */ + if (maxCacheLines < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal Error: " + "maxCacheLines < 0 in I830Allocate2DMemory()\n"); + maxCacheLines = 0; + } + if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) + maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; + + if (pI830->CacheLines >= 0) { + cacheLines = pI830->CacheLines; + } else { +#if 1 + /* Make sure there is enough for two DVD sized YUV buffers */ + cacheLines = (pScrn->depth == 24) ? 256 : 384; + if (pScrn->displayWidth <= 1024) + cacheLines *= 2; +#else + /* + * Make sure there is enough for two DVD sized YUV buffers. + * Make that 1.5MB, which is around what was allocated with + * the old algorithm + */ + cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth; +#endif + } + if (cacheLines > maxCacheLines) + cacheLines = maxCacheLines; + + FbMemBox->y2 += cacheLines; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocating at least %d scanlines for pixmap cache\n", + s, cacheLines); + } else { + /* For EXA, we have a separate allocation for the linear allocator which + * also does the pixmap cache. + */ + cacheLines = 0; + } + + tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); + if (tileable) { + if (IS_I9XX(pI830)) + align = MB(1); + else + align = KB(512); + alignflags = ALIGN_BOTH_ENDS; + } else { + align = KB(64); + alignflags = 0; + } + + size = lineSize * (fb_height + cacheLines); + size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sInitial %sframebuffer allocation size: %ld kByte\n", + s, secondary ? "secondary " : "", + size / 1024); + alloced = I830AllocVidMem(pScrn, FrontBuffer, + StolenPool, size, align, + flags | alignflags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "%sframebuffer. Is your VideoRAM set too low?\n", + secondary ? "secondary " : ""); + } + return FALSE; + } + + return TRUE; +} + /* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. */ - Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) { @@ -670,8 +813,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->StolenPool.Free.Size); if (flags & ALLOC_INITIAL) { - unsigned long minspace, avail, lineSize; - int cacheLines, maxCacheLines; if (pI830->NeedRingBufferLow) AllocateRingBuffer(pScrn, flags | FORCE_LOW); @@ -682,242 +823,45 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) I830EntPtr pI830Ent = pI830->entityPrivate; I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); - /* Clear everything first. */ - memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2)); - memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2)); - pI830->FrontBuffer2.Key = -1; - -#if 1 /* ROTATION */ - pI830->FbMemBox2.x1 = 0; - pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; - pI830->FbMemBox2.y1 = 0; - if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX; - else - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; -#else - pI830->FbMemBox2.x1 = 0; - pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; - pI830->FbMemBox2.y1 = 0; - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; -#endif - - /* - * Calculate how much framebuffer memory to allocate. For the - * initial allocation, calculate a reasonable minimum. This is - * enough for the virtual screen size, plus some pixmap cache - * space. - */ - - lineSize = pI830Ent->pScrn_2->displayWidth * pI8302->cpp; - minspace = lineSize * pI830Ent->pScrn_2->virtualY; - avail = pI830Ent->pScrn_2->videoRam * 1024; - maxCacheLines = (avail - minspace) / lineSize; - /* This shouldn't happen. */ - if (maxCacheLines < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); - maxCacheLines = 0; - } - if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY)) - maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY; - - if (pI8302->CacheLines >= 0) { - cacheLines = pI8302->CacheLines; - } else { -#if 1 - /* Make sure there is enough for two DVD sized YUV buffers */ - cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384; - if (pI830Ent->pScrn_2->displayWidth <= 1024) - cacheLines *= 2; -#else - /* - * Make sure there is enough for two DVD sized YUV buffers. - * Make that 1.5MB, which is around what was allocated with - * the old algorithm - */ - cacheLines = (MB(1) + KB(512)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth; -#endif - } - if (cacheLines > maxCacheLines) - cacheLines = maxCacheLines; - - pI830->FbMemBox2.y2 += cacheLines; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocating at least %d scanlines for pixmap cache\n", - s, cacheLines); - - tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip && - IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - -#if 1 /* ROTATION */ - if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) - size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines); - else - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#else - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#endif - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sSecondary framebuffer allocation size: %ld kByte\n", s, - size / 1024); - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR, - "Failed to allocate secondary framebuffer.\n"); - } - return FALSE; - } - } - - /* Clear everything first. */ - memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox)); - memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); - pI830->FrontBuffer.Key = -1; - -#if 1 /* ROTATION */ - pI830->FbMemBox.x1 = 0; - pI830->FbMemBox.x2 = pScrn->displayWidth; - pI830->FbMemBox.y1 = 0; - if (pScrn->virtualX > pScrn->virtualY) - pI830->FbMemBox.y2 = pScrn->virtualX; - else - pI830->FbMemBox.y2 = pScrn->virtualY; -#else - pI830->FbMemBox.x1 = 0; - pI830->FbMemBox.x2 = pScrn->displayWidth; - pI830->FbMemBox.y1 = 0; - pI830->FbMemBox.y2 = pScrn->virtualY; -#endif - - /* - * Calculate how much framebuffer memory to allocate. For the - * initial allocation, calculate a reasonable minimum. This is - * enough for the virtual screen size, plus some pixmap cache - * space. - */ - - lineSize = pScrn->displayWidth * pI830->cpp; - minspace = lineSize * pScrn->virtualY; - avail = pScrn->videoRam * 1024; - maxCacheLines = (avail - minspace) / lineSize; - /* This shouldn't happen. */ - if (maxCacheLines < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); - maxCacheLines = 0; - } - if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) - maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; - - if (pI830->CacheLines >= 0) { - cacheLines = pI830->CacheLines; - } else { -#if 1 - /* Make sure there is enough for two DVD sized YUV buffers */ - cacheLines = (pScrn->depth == 24) ? 256 : 384; - if (pScrn->displayWidth <= 1024) - cacheLines *= 2; -#else - /* - * Make sure there is enough for two DVD sized YUV buffers. - * Make that 1.5MB, which is around what was allocated with - * the old algorithm - */ - cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth; -#endif - } - if (cacheLines > maxCacheLines) - cacheLines = maxCacheLines; - - pI830->FbMemBox.y2 += cacheLines; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocating at least %d scanlines for pixmap cache\n", - s, cacheLines); - - tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn->displayWidth * pI830->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - -#if 1 /* ROTATION */ - if (pScrn->virtualX > pScrn->virtualY) - size = lineSize * (pScrn->virtualX + cacheLines); - else - size = lineSize * (pScrn->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#else - size = lineSize * (pScrn->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#endif - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sInitial framebuffer allocation size: %ld kByte\n", s, - size / 1024); - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "framebuffer. Is your VideoRAM set too low ??\n"); + if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302, + &pI830->FbMemBox2, + &pI830->FrontBuffer2, &pI830->StolenPool, + TRUE, flags)) + { + return FALSE; } + } + if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox, + &pI830->FrontBuffer, &pI830->StolenPool, + FALSE, flags)) + { return FALSE; } + #ifdef I830_USE_EXA - size = lineSize * pScrn->virtualY; - size = ROUND_TO_PAGE(size); + if (pI830->useEXA) { + /* Default EXA to having 3 screens worth of offscreen memory space + * (for pixmaps), plus a double-buffered, 1920x1088 video's worth. + */ + size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY; + size += 1920 * 1088 * 2 * 2; + size = ROUND_TO_PAGE(size); - if (tileable) { - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - - alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "offscreen memory. Not enough VRAM?\n"); + alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), + &(pI830->StolenPool), size, 1, + flags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "offscreen memory. Not enough VRAM?\n"); + } + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocation of " + "EXA offscreen memory at 0x%lx, size %ld KB\n", + pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } - return FALSE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate " - "offscreen memory at 0x%lx, size %ld KB\n", - pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } if (IS_I965G(pI830)) { memset(&(pI830->EXAStateMem), 0, sizeof(I830MemRange)); @@ -996,7 +940,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) maxFb / lineSize - pScrn->virtualY); pI830->FbMemBox.y2 = maxFb / lineSize; tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { if (IS_I9XX(pI830)) align = MB(1); @@ -1223,7 +1167,7 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer)); pI830->BackBuffer.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -1286,7 +1230,7 @@ I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags) memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer)); pI830->DepthBuffer.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -1349,7 +1293,14 @@ I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags) if (pI830->mmModeFlags & I830_KERNEL_TEX) { - size = GetFreeSpace(pScrn); + if (dryrun && pI830->pEnt->device->videoRam == 0) { + /* If we're laying out a default-sized allocation, then don't be + * too greedy and just ask for 32MB. + */ + size = MB(32); + } else { + size = GetFreeSpace(pScrn); + } if (dryrun && (size < MB(1))) size = MB(1); i = myLog2(size / I830_NR_TEX_REGIONS); @@ -1827,7 +1778,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) if (!pI830->directRenderingEnabled) return; - if (!IsTileable(pScrn->displayWidth * pI830->cpp)) { + if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I830SetupMemoryTiling: Not tileable 0x%x\n", pScrn->displayWidth * pI830->cpp); diff --git a/src/i830_modes.c b/src/i830_modes.c index 42ee79df..b4e22c35 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -55,98 +55,16 @@ #include "i830_xf86Modes.h" #include -#define DEBUG_REPROBE 1 - -#ifdef RANDR_12_INTERFACE - -#define EDID_ATOM_NAME "EDID_DATA" - -static void -i830_ddc_set_edid_property(xf86OutputPtr output, void *data, int data_len) -{ - Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE); - - /* This may get called before the RandR resources have been created */ - if (output->randr_output == NULL) - return; - - if (data_len != 0) { - RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, - PropModeReplace, data_len, data, FALSE); - } else { - RRDeleteOutputProperty(output->randr_output, edid_atom); - } -} -#endif - -/** - * Generic get_modes function using DDC, used by many outputs. - */ DisplayModePtr -i830_ddc_get_modes(xf86OutputPtr output) +i830_ddc_get_modes (xf86OutputPtr output) { - ScrnInfoPtr pScrn = output->scrn; - I830OutputPrivatePtr intel_output = output->driver_private; - xf86MonPtr ddc_mon; - DisplayModePtr ddc_modes, mode; - int i; + I830OutputPrivatePtr intel_output = output->driver_private; + xf86MonPtr edid_mon; + DisplayModePtr modes; - ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, intel_output->pDDCBus); - if (ddc_mon == NULL) { -#ifdef RANDR_12_INTERFACE - i830_ddc_set_edid_property(output, NULL, 0); -#endif - return NULL; - } - - if (output->MonInfo != NULL) - xfree(output->MonInfo); - output->MonInfo = ddc_mon; - -#ifdef RANDR_12_INTERFACE - if (output->MonInfo->ver.version == 1) { - i830_ddc_set_edid_property(output, ddc_mon->rawData, 128); - } else if (output->MonInfo->ver.version == 2) { - i830_ddc_set_edid_property(output, ddc_mon->rawData, 256); - } else { - i830_ddc_set_edid_property(output, NULL, 0); - } -#endif - - /* Debug info for now, at least */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); - xf86PrintEDID(output->MonInfo); - - ddc_modes = xf86DDCGetModes(pScrn->scrnIndex, ddc_mon); - - /* Strip out any modes that can't be supported on this output. */ - for (mode = ddc_modes; mode != NULL; mode = mode->next) { - int status = (*output->funcs->mode_valid)(output, mode); - - if (status != MODE_OK) - mode->status = status; - } - i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE); - - /* Pull out a phyiscal size from a detailed timing if available. */ - for (i = 0; i < 4; i++) { - if (ddc_mon->det_mon[i].type == DT && - ddc_mon->det_mon[i].section.d_timings.h_size != 0 && - ddc_mon->det_mon[i].section.d_timings.v_size != 0) - { - output->mm_width = ddc_mon->det_mon[i].section.d_timings.h_size; - output->mm_height = ddc_mon->det_mon[i].section.d_timings.v_size; - break; - } - } - - /* if no mm size is available from a detailed timing, check the max size field */ - if ((!output->mm_width || !output->mm_height) && - (ddc_mon->features.hsize && ddc_mon->features.vsize)) - { - output->mm_width = ddc_mon->features.hsize * 10; - output->mm_height = ddc_mon->features.vsize * 10; - } - - return ddc_modes; + edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus); + i830_xf86OutputSetEDID (output, edid_mon); + + modes = i830_xf86OutputGetEDIDModes (output); + return modes; } diff --git a/src/i830_randr.c b/src/i830_randr.c index 019e71c4..79b16e89 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -6,21 +6,21 @@ * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H @@ -95,7 +95,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) } /* Re-probe the outputs for new monitors or modes */ - xf86ProbeOutputModes (scrp); + xf86ProbeOutputModes (scrp, 0, 0); xf86SetScrnInfoModes (scrp); I830DGAReInit (pScreen); @@ -325,6 +325,44 @@ xf86RandR12SetConfig (ScreenPtr pScreen, return TRUE; } +static Bool +xf86RandR12ScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + WindowPtr pRoot = WindowTable[pScreen->myNum]; + Bool ret = TRUE; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); + pScrn->virtualX = width; + pScrn->virtualY = height; + + pScreen->width = pScrn->virtualX; + pScreen->height = pScrn->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + + xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); +#if RANDR_12_INTERFACE + if (WindowTable[pScreen->myNum]) + RRScreenSizeNotify (pScreen); +#endif + return ret; +} + Rotation xf86RandR12GetRotation(ScreenPtr pScreen) { @@ -344,37 +382,67 @@ xf86RandR12GetRotation12(RRCrtcPtr randr_crtc) Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen) { -#if 0 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); -#endif + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; + int width, height; + int mmWidth, mmHeight; #ifdef PANORAMIX /* XXX disable RandR when using Xinerama */ if (!noPanoramiXExtension) return TRUE; #endif + + /* + * Compute size of screen + */ + width = 0; height = 0; + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + int crtc_width = crtc->x + crtc->curMode.HDisplay; + int crtc_height = crtc->y + crtc->curMode.VDisplay; + + if (crtc->enabled && crtc_width > width) + width = crtc_width; + if (crtc->enabled && crtc_height > height) + height = crtc_height; + } + + if (width && height) + { + /* + * Compute physical size of screen + */ + if (monitorResolution) + { + mmWidth = width * 25.4 / monitorResolution; + mmHeight = height * 25.4 / monitorResolution; + } + else + { + mmWidth = pScreen->mmWidth; + mmHeight = pScreen->mmHeight; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Setting screen physical size to %d x %d\n", + mmWidth, mmHeight); + xf86RandR12ScreenSetSize (pScreen, + width, + height, + mmWidth, + mmHeight); + } + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } #if RANDR_12_INTERFACE if (xf86RandR12CreateScreenResources12 (pScreen)) return TRUE; -#endif -#if 0 - /* XXX deal with initial rotation */ - if (pI830->rotation != RR_Rotate_0) { - RRScreenSize p; - Rotation requestedRotation = pI830->rotation; - - pI830->rotation = RR_Rotate_0; - - /* Just setup enough for an initial rotate */ - p.width = pScreen->width; - p.height = pScreen->height; - p.mmWidth = pScreen->mmWidth; - p.mmHeight = pScreen->mmHeight; - - pI830->starting = TRUE; /* abuse this for dual head & rotation */ - xf86RandR12SetConfig (pScreen, requestedRotation, 0, &p); - pI830->starting = FALSE; - } #endif return TRUE; } @@ -474,44 +542,6 @@ xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) } #if RANDR_12_INTERFACE -static Bool -xf86RandR12ScreenSetSize (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - WindowPtr pRoot = WindowTable[pScreen->myNum]; - Bool ret = TRUE; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } - if (pRoot) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); - /* XXX don't change the actual draw window size */ - /*pScrn->virtualX = width; - *pScrn->virtualY = height; - *pScreen->width = pScrn->virtualX; - *pScreen->height = pScrn->virtualY;*/ - pScreen->width = width; - pScreen->height = height; - pScreen->mmWidth = mmWidth; - pScreen->mmHeight = mmHeight; - - xf86SetViewport (pScreen, pScreen->width, pScreen->height); - xf86SetViewport (pScreen, 0, 0); - if (pRoot) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); - if (WindowTable[pScreen->myNum]) - RRScreenSizeNotify (pScreen); - return ret; -} - static Bool xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) { @@ -679,9 +709,17 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, static Bool xf86RandR12CrtcSetGamma (ScreenPtr pScreen, - RRCrtcPtr crtc) + RRCrtcPtr randr_crtc) { - return FALSE; + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->funcs->gamma_set == NULL) + return FALSE; + + crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen, + randr_crtc->gammaBlue, randr_crtc->gammaSize); + + return TRUE; } /** @@ -788,7 +826,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) output->mm_height); xf86RROutputSetModes (output->randr_output, output->probed_modes); - switch (output->status = (*output->funcs->detect)(output)) { + switch (output->status) { case XF86OutputStatusConnected: RROutputSetConnection (output->randr_output, RR_Connected); break; @@ -834,7 +872,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86ProbeOutputModes (pScrn); + xf86ProbeOutputModes (pScrn, 0, 0); xf86SetScrnInfoModes (pScrn); I830DGAReInit (pScreen); return xf86RandR12SetInfo12 (pScreen); @@ -880,62 +918,14 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen) static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); int c; - int width, height; - int mmWidth, mmHeight; - - /* - * Compute size of screen - */ - width = 0; height = 0; - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - int crtc_width = crtc->x + crtc->curMode.HDisplay; - int crtc_height = crtc->y + crtc->curMode.VDisplay; - - if (crtc->enabled && crtc_width > width) - width = crtc_width; - if (crtc->enabled && crtc_height > height) - height = crtc_height; - } - - if (width && height) - { - /* - * Compute physical size of screen - */ - if (monitorResolution) - { - mmWidth = width * 25.4 / monitorResolution; - mmHeight = height * 25.4 / monitorResolution; - } - else - { - mmWidth = pScreen->mmWidth; - mmHeight = pScreen->mmHeight; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting screen physical size to %d x %d\n", - mmWidth, mmHeight); - xf86RandR12ScreenSetSize (pScreen, - width, - height, - mmWidth, - mmHeight); - } + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); for (c = 0; c < config->num_crtc; c++) xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } RRScreenSetSizeRange (pScreen, 320, 240, randrp->virtualX, randrp->virtualY); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 8e387794..4fc59217 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1091,6 +1091,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) return; } output->driver_private = intel_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; dev_priv = (struct i830_sdvo_priv *) (intel_output + 1); @@ -1204,7 +1206,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) } strcpy (name, name_prefix); strcat (name, name_suffix); - xf86OutputRename (output, name); + if (!xf86OutputRename (output, name)) + { + xf86OutputDestroy (output); + return; + } + /* Set the input timing to the screen. Assume always input 0. */ i830_sdvo_set_target_input(output, TRUE, FALSE); diff --git a/src/i830_tv.c b/src/i830_tv.c index 9048d089..0580a951 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -36,6 +36,7 @@ #include "xf86.h" #include "i830.h" #include "i830_display.h" +#include enum tv_type { TV_TYPE_NONE, @@ -1183,4 +1184,6 @@ i830_tv_init(ScrnInfoPtr pScrn) dev_priv->type = TV_TYPE_UNKNOWN; output->driver_private = intel_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; } diff --git a/src/i830_video.c b/src/i830_video.c index d10fd168..f031a873 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -76,6 +76,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86fbman.h" #include "regionstr.h" #include "randrstr.h" +#include "windowstr.h" +#include "damage.h" #include "i830.h" #include "i830_video.h" #include "xf86xv.h" @@ -84,8 +86,6 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xaalocal.h" #include "dixstruct.h" #include "fourcc.h" -#include "brw_defines.h" -#include "brw_structs.h" #ifndef USE_USLEEP_FOR_VIDEO #define USE_USLEEP_FOR_VIDEO 0 @@ -120,8 +120,8 @@ static int I830QueryImageAttributesTextured(ScrnInfoPtr, int, unsigned short *, static void I830BlockHandler(int, pointer, pointer, pointer); -static FBLinearPtr -I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size); +static void +I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -133,17 +133,16 @@ static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH_LEGACY 1024 #define IMAGE_MAX_HEIGHT_LEGACY 1088 -/* - * Broadwater requires a bit of extra video memory for state information - */ -#define BRW_LINEAR_EXTRA (32*1024) +/* overlay debugging printf function */ +#if 0 +#define OVERLAY_DEBUG ErrorF +#else +#define OVERLAY_DEBUG if (0) ErrorF +#endif -#if !VIDEO_DEBUG -#define ErrorF Edummy -static void -Edummy(const char *dummy, ...) -{ -} +/* Oops, I never exported this function in EXA. I meant to. */ +#ifndef exaMoveInPixmap +void exaMoveInPixmap (PixmapPtr pPixmap); #endif /* @@ -164,7 +163,7 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON); \ - ErrorF("Overlay goes from off to on\n"); \ + OVERLAY_DEBUG("Overlay goes from off to on\n"); \ *pI830->overlayOn = TRUE; \ } else { \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ @@ -178,7 +177,7 @@ Edummy(const char *dummy, ...) OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ - ErrorF("OVERLAY_UPDATE\n"); \ + OVERLAY_DEBUG("OVERLAY_UPDATE\n"); \ } while(0) #define OVERLAY_OFF \ @@ -197,13 +196,14 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ *pI830->overlayOn = FALSE; \ - ErrorF("Overlay goes from on to off\n"); \ + OVERLAY_DEBUG("Overlay goes from on to off\n"); \ while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){ \ - ErrorF("SPIN %d\n",spin); \ + OVERLAY_DEBUG("SPIN %d\n",spin); \ spin--; \ } \ - if (spin == 0) ErrorF("OVERLAY FAILED TO GO OFF\n"); \ - ErrorF("OVERLAY_OFF\n"); \ + if (spin == 0) \ + OVERLAY_DEBUG("OVERLAY FAILED TO GO OFF\n"); \ + OVERLAY_DEBUG("OVERLAY_OFF\n"); \ } \ } while(0) @@ -394,13 +394,13 @@ CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size) for (i = 0; i < size; i += 4) { val = INREG(0x30100 + i); if (val != overlay[i / 4]) { - ErrorF("0x%05x value doesn't match (0x%lx != 0x%lx)\n", + OVERLAY_DEBUG("0x%05x value doesn't match (0x%lx != 0x%lx)\n", 0x30100 + i, val, overlay[i / 4]); bad++; } } if (!bad) - ErrorF("CompareOverlay: no differences\n"); + OVERLAY_DEBUG("CompareOverlay: no differences\n"); } #endif @@ -413,8 +413,6 @@ I830InitVideo(ScreenPtr pScreen) XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; int num_adaptors; - ErrorF("I830InitVideo\n"); - #if 0 { I830OverlayRegRec tmp; @@ -487,7 +485,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); - ErrorF("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", + OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", pI830->FbBase, pI830->OverlayMem->Start, overlay); /* * Default to maximum image size in YV12 @@ -629,15 +627,19 @@ I830UpdateGamma(ScrnInfoPtr pScrn) CARD32 gamma4 = pPriv->gamma4; CARD32 gamma5 = pPriv->gamma5; +#if 0 ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", gamma0, gamma1, gamma2, gamma3, gamma4, gamma5); +#endif gamma1 = I830BoundGamma (gamma1, gamma0); gamma2 = I830BoundGamma (gamma2, gamma1); gamma3 = I830BoundGamma (gamma3, gamma2); gamma4 = I830BoundGamma (gamma4, gamma3); gamma5 = I830BoundGamma (gamma5, gamma4); +#if 0 ErrorF ("Bounded gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", gamma0, gamma1, gamma2, gamma3, gamma4, gamma5); +#endif OUTREG(OGAMC5, gamma5); OUTREG(OGAMC4, gamma4); @@ -656,7 +658,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) I830PortPrivPtr pPriv; XF86AttributePtr att; - ErrorF("I830SetupImageVideoOverlay\n"); + OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(I830PortPrivRec) + sizeof(DevUnion)))) @@ -715,7 +717,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) pPriv->contrast = 64; pPriv->saturation = 128; pPriv->pipe = 0; /* XXX must choose pipe wisely */ - pPriv->linear = NULL; + memset(&pPriv->linear, 0, sizeof(pPriv->linear)); pPriv->currentBuf = 0; pPriv->gamma5 = 0xc0c0c0; pPriv->gamma4 = 0x808080; @@ -782,7 +784,7 @@ I830SetupImageVideoTextured(ScreenPtr pScreen) int nports = 16, i; int nAttributes; - ErrorF("I830SetupImageVideoOverlay\n"); + OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); nAttributes = NUM_TEXTURED_ATTRIBUTES; @@ -838,7 +840,7 @@ I830SetupImageVideoTextured(ScreenPtr pScreen) pPriv->textured = TRUE; pPriv->videoStatus = 0; - pPriv->linear = NULL; + memset(&pPriv->linear, 0, sizeof(pPriv->linear)); pPriv->currentBuf = 0; pPriv->doubleBuffer = 0; @@ -888,7 +890,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (pPriv->textured) return; - ErrorF("I830StopVideo\n"); + OVERLAY_DEBUG("I830StopVideo\n"); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); @@ -902,10 +904,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; } - if (pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; - } + I830FreeMemory(pScrn, &pPriv->linear); pPriv->videoStatus = 0; } else { if (pPriv->videoStatus & CLIENT_VIDEO_ON) { @@ -938,14 +937,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, return BadValue; pPriv->brightness = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - ErrorF("BRIGHTNESS\n"); + OVERLAY_DEBUG("BRIGHTNESS\n"); OVERLAY_UPDATE; } else if (attribute == xvContrast) { if ((value < 0) || (value > 255)) return BadValue; pPriv->contrast = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - ErrorF("CONTRAST\n"); + OVERLAY_DEBUG("CONTRAST\n"); OVERLAY_UPDATE; } else if (attribute == xvSaturation) { if ((value < 0) || (value > 1023)) @@ -966,7 +965,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCONFIG |= OVERLAY_PIPE_A; else overlay->OCONFIG |= OVERLAY_PIPE_B; - ErrorF("PIPE CHANGE\n"); + OVERLAY_DEBUG("PIPE CHANGE\n"); OVERLAY_UPDATE; } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { pPriv->gamma0 = value; @@ -993,7 +992,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->DCLRKV = pPriv->colorKey; break; } - ErrorF("COLORKEY\n"); + OVERLAY_DEBUG("COLORKEY\n"); OVERLAY_UPDATE; REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } else if(attribute == xvDoubleBuffer) { @@ -1013,7 +1012,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, attribute == xvGamma4 || attribute == xvGamma5) && (IS_I9XX(pI830))) { CARD32 r = overlay->OCMD & OVERLAY_ENABLE; - ErrorF("GAMMA\n"); + OVERLAY_DEBUG("GAMMA\n"); overlay->OCMD &= ~OVERLAY_ENABLE; OVERLAY_UPDATE; I830UpdateGamma(pScrn); @@ -1088,8 +1087,11 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int i,j; unsigned char *s; +#if 0 ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n" - "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch); + "srcPitch: %d, dstPitch: %d\n", top, left, h, w, + srcPitch, dstPitch); +#endif src = buf + (top * srcPitch) + (left << 1); @@ -1242,14 +1244,19 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, unsigned char *s; int dstPitch2 = dstPitch << 1; +#if 0 ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n" - "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch, - h, w, top, left); + "nlines %d, npixels %d, top %d, left %d\n", + srcPitch, srcPitch2, dstPitch, + h, w, top, left); +#endif /* Copy Y data */ src1 = buf + (top * srcPitch) + left; +#if 0 ErrorF("src1 is %p, offset is %ld\n", src1, (unsigned long)src1 - (unsigned long)buf); +#endif if (pPriv->currentBuf == 0) dst1 = pI830->FbBase + pPriv->YBuf0offset; else @@ -1294,8 +1301,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, /* Copy V data for YV12, or U data for I420 */ src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1); +#if 0 ErrorF("src2 is %p, offset is %ld\n", src2, (unsigned long)src2 - (unsigned long)buf); +#endif if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) dst2 = pI830->FbBase + pPriv->UBuf0offset; @@ -1348,8 +1357,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, /* Copy U data for YV12, or V data for I420 */ src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) + ((top * srcPitch) >> 2) + (left >> 1); +#if 0 ErrorF("src3 is %p, offset is %ld\n", src3, (unsigned long)src3 - (unsigned long)buf); +#endif if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) dst3 = pI830->FbBase + pPriv->VBuf0offset; @@ -1543,8 +1554,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, unsigned int mask, shift, offsety, offsetu; int tmp; - ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, - dstPitch); + OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, + dstPitch); if (!pPriv->overlayOK) return; @@ -1600,7 +1611,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ if (!*pI830->overlayOn) { - ErrorF("TURNING ON OVERLAY BEFORE UPDATE\n"); + OVERLAY_DEBUG("TURNING ON OVERLAY BEFORE UPDATE\n"); I830ResetVideo(pScrn); OVERLAY_UPDATE; } @@ -1683,22 +1694,22 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, /* nothing do to */ if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } if ((dstBox->x1 == (pScrn->currentMode->HDisplay - 1) && dstBox->x2 == (pScrn->currentMode->HDisplay - 1)) || (dstBox->y1 == vactive && dstBox->y2 == vactive)) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } if ((dstBox->x2 - dstBox->x1) <= 2) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } } @@ -1736,7 +1747,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth -= 1; - ErrorF("Y width is %d, swidth is %d\n", width, swidth); + OVERLAY_DEBUG("Y width is %d, swidth is %d\n", width, swidth); overlay->SWIDTHSW = swidth << 2; @@ -1748,11 +1759,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth -= 1; - ErrorF("UV width is %d, swidthsw is %d\n", width / 2, swidth); + OVERLAY_DEBUG("UV width is %d, swidthsw is %d\n", width / 2, swidth); overlay->SWIDTHSW |= swidth << 18; - ErrorF("HEIGHT is %d\n",height); + OVERLAY_DEBUG("HEIGHT is %d\n",height); overlay->SHEIGHT = height | ((height / 2) << 16); break; @@ -1762,7 +1773,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = width; overlay->SWIDTH = swidth; - ErrorF("Y width is %d\n", swidth); + OVERLAY_DEBUG("Y width is %d\n", swidth); swidth = ((offsety + (width << 1) + mask) >> shift) - (offsety >> shift); @@ -1772,11 +1783,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth -= 1; - ErrorF("swidthsw is %d\n", swidth); + OVERLAY_DEBUG("swidthsw is %d\n", swidth); overlay->SWIDTHSW = swidth << 2; - ErrorF("HEIGHT is %d\n",height); + OVERLAY_DEBUG("HEIGHT is %d\n",height); overlay->SHEIGHT = height; break; @@ -1789,8 +1800,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1); - ErrorF("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); + OVERLAY_DEBUG("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", + dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2); /* buffer locations */ if (IS_I965G(pI830)) @@ -1820,10 +1831,10 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } } - ErrorF("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", overlay->OBUF_0Y, - overlay->OBUF_0U, overlay->OBUF_0V); - ErrorF("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", overlay->OBUF_1Y, - overlay->OBUF_1U, overlay->OBUF_1V); + OVERLAY_DEBUG("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", + overlay->OBUF_0Y, overlay->OBUF_0U, overlay->OBUF_0V); + OVERLAY_DEBUG("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", + overlay->OBUF_1Y, overlay->OBUF_1U, overlay->OBUF_1V); #if 0 { @@ -1847,8 +1858,9 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } #endif - ErrorF("pos: 0x%lx, size: 0x%lx\n", overlay->DWINPOS, overlay->DWINSZ); - ErrorF("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h); + OVERLAY_DEBUG("pos: 0x%lx, size: 0x%lx\n", + overlay->DWINPOS, overlay->DWINSZ); + OVERLAY_DEBUG("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h); /* * Calculate horizontal and vertical scaling factors and polyphase @@ -1891,20 +1903,20 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, xscaleIntUV = xscaleFractUV >> 12; yscaleIntUV = yscaleFractUV >> 12; - ErrorF("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt, - xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF); - ErrorF("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV, - xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF); + OVERLAY_DEBUG("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt, + xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF); + OVERLAY_DEBUG("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV, + xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF); /* shouldn't get here */ - if (xscaleInt > 7) { - ErrorF("xscale: bad scale\n"); + if (xscaleInt > 7) { + OVERLAY_DEBUG("xscale: bad scale\n"); return; } /* shouldn't get here */ - if (xscaleIntUV > 7) { - ErrorF("xscaleUV: bad scale\n"); + if (xscaleIntUV > 7) { + OVERLAY_DEBUG("xscaleUV: bad scale\n"); return; } @@ -1975,12 +1987,13 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, switch (id) { case FOURCC_YV12: case FOURCC_I420: - ErrorF("YUV420\n"); + OVERLAY_DEBUG("YUV420\n"); #if 0 /* set UV vertical phase to -0.25 */ overlay->UV_VPH = 0x30003000; #endif - ErrorF("UV stride is %d, Y stride is %d\n", dstPitch, dstPitch * 2); + OVERLAY_DEBUG("UV stride is %d, Y stride is %d\n", + dstPitch, dstPitch * 2); overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16); overlay->OCMD &= ~SOURCE_FORMAT; overlay->OCMD &= ~OV_BYTE_ORDER; @@ -1989,7 +2002,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, case FOURCC_UYVY: case FOURCC_YUY2: default: - ErrorF("YUV422\n"); + OVERLAY_DEBUG("YUV422\n"); overlay->OSTRIDE = dstPitch; overlay->OCMD &= ~SOURCE_FORMAT; overlay->OCMD |= YUV_422; @@ -2005,837 +2018,130 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, else overlay->OCMD |= BUFFER1; - ErrorF("OCMD is 0x%lx\n", overlay->OCMD); + OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD); OVERLAY_UPDATE; } -static const CARD32 sip_kernel_static[][4] = { -/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ - { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -}; - -/* - * this program computes dA/dx and dA/dy for the texture coordinates along - * with the base texture coordinate. It was extracted from the Mesa driver. - * It uses about 10 GRF registers. - */ - -#define SF_KERNEL_NUM_GRF 16 -#define SF_MAX_THREADS 1 - -static const CARD32 sf_kernel_static[][4] = { -#include "sf_prog.h" -}; - -/* - * Ok, this kernel picks up the required data flow values in g0 and g1 - * and passes those along in m0 and m1. In m2-m9, it sticks constant - * values (bright pink). - */ - -/* Our PS kernel uses less than 32 GRF registers (about 20) */ -#define PS_KERNEL_NUM_GRF 32 -#define PS_MAX_THREADS 32 - -#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) - -static const CARD32 ps_kernel_static[][4] = { -#include "wm_prog.h" -}; - -#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -#define WM_BINDING_TABLE_ENTRIES 2 - -static CARD32 float_to_uint (float f) { - union {CARD32 i; float f;} x; - x.f = f; - return x.i; -} - -#if 0 -static struct { - CARD32 svg_ctl; - char *name; -} svg_ctl_bits[] = { - { BRW_SVG_CTL_GS_BA, "General State Base Address" }, - { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, - { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, - { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, - { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, - { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, - { 0, 0 }, -}; - +#ifdef I830_USE_EXA static void -brw_debug (ScrnInfoPtr pScrn, char *when) +I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) { - I830Ptr pI830 = I830PTR(pScrn); - int i; - CARD32 v; - - I830Sync (pScrn); - ErrorF("brw_debug: %s\n", when); - for (i = 0; svg_ctl_bits[i].name; i++) { - OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); - v = INREG(BRW_SVG_RDATA); - ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); - } + struct linear_alloc *linear = area->privData; + + linear->exa = NULL; + linear->offset = 0; } -#endif - -#define WATCH_SF 0 -#define WATCH_WIZ 0 -#define WATCH_STATS 0 +#endif /* I830_USE_EXA */ +/** + * Allocates linear memory using the XFree86 (XAA) or EXA allocator. + * + * \param pPriv adaptor the memory is being allocated for. + * \param size size of the allocation, in bytes. + * \param alignment offset alignment of the allocation, in bytes. + * + * \return byte offset of the allocated memory from the start of framebuffer. + */ static void -BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, - RegionPtr dstRegion, - short width, short height, int video_pitch, - int x1, int y1, int x2, int y2, - short src_w, short src_h, - short drw_w, short drw_h, - DrawablePtr pDraw) +I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, + int align) { + ScreenPtr pScreen = pScrn->pScreen; I830Ptr pI830 = I830PTR(pScrn); - BoxPtr pbox; - int nbox, dxo, dyo; - int urb_vs_start, urb_vs_size; - int urb_gs_start, urb_gs_size; - int urb_clip_start, urb_clip_size; - int urb_sf_start, urb_sf_size; - int urb_cs_start, urb_cs_size; - struct brw_surface_state *dest_surf_state; - struct brw_surface_state *src_surf_state; - struct brw_sampler_state *src_sampler_state; - struct brw_vs_unit_state *vs_state; - struct brw_sf_unit_state *sf_state; - struct brw_wm_unit_state *wm_state; - struct brw_cc_unit_state *cc_state; - struct brw_cc_viewport *cc_viewport; - struct brw_instruction *sf_kernel; - struct brw_instruction *ps_kernel; - struct brw_instruction *sip_kernel; - float *vb; - CARD32 *binding_table; - Bool first_output = TRUE; - int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; - int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; - int wm_scratch_offset; - int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; - int binding_table_offset; - int next_offset, total_state_size; - int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ - char *state_base; - int state_base_offset; -#if 0 - ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, - video_pitch); -#endif +#ifdef I830_USE_EXA + if (pI830->useEXA) { + if (linear->exa != NULL) { + if (linear->exa->size >= size) + return; - /* enable debug */ - OUTREG (INST_PM, - (1 << (16 + 4)) | - (1 << 4)); -#if 0 - ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); -#endif - - assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); + exaOffscreenFree(pScreen, linear->exa); + linear->offset = 0; + } - /* Tell the rotation code that we have stomped its invariant state by - * setting a high bit. We don't use any invariant 3D state for video, so we - * don't have to worry about it ourselves. - */ - *pI830->used3D |= 1 << 30; - -#ifdef XF86DRI - /* Tell the DRI that we're smashing its state. */ - if (pI830->directRenderingEnabled) { - drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - - pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE, + I830VideoSave, linear); + if (linear->exa == NULL) + return; + linear->offset = linear->exa->offset; } -#endif /* XF86DRI */ - - next_offset = 0; - - /* Set up our layout of state in framebuffer. First the general state: */ - vs_offset = ALIGN(next_offset, 64); - next_offset = vs_offset + sizeof(*vs_state); - sf_offset = ALIGN(next_offset, 32); - next_offset = sf_offset + sizeof(*sf_state); - wm_offset = ALIGN(next_offset, 32); - next_offset = wm_offset + sizeof(*wm_state); - wm_scratch_offset = ALIGN(next_offset, 1024); - next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; - cc_offset = ALIGN(next_offset, 32); - next_offset = cc_offset + sizeof(*cc_state); - - sf_kernel_offset = ALIGN(next_offset, 64); - next_offset = sf_kernel_offset + sizeof (sf_kernel_static); - ps_kernel_offset = ALIGN(next_offset, 64); - next_offset = ps_kernel_offset + sizeof (ps_kernel_static); - sip_kernel_offset = ALIGN(next_offset, 64); - next_offset = sip_kernel_offset + sizeof (sip_kernel_static); - cc_viewport_offset = ALIGN(next_offset, 32); - next_offset = cc_viewport_offset + sizeof(*cc_viewport); - - src_sampler_offset = ALIGN(next_offset, 32); - next_offset = src_sampler_offset + sizeof(*src_sampler_state); - - /* Align VB to native size of elements, for safety */ - vb_offset = ALIGN(next_offset, 8); - next_offset = vb_offset + vb_size; - - /* And then the general state: */ - dest_surf_offset = ALIGN(next_offset, 32); - next_offset = dest_surf_offset + sizeof(*dest_surf_state); - src_surf_offset = ALIGN(next_offset, 32); - next_offset = src_surf_offset + sizeof(*src_surf_state); - binding_table_offset = ALIGN(next_offset, 32); - next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); - - /* Allocate an area in framebuffer for our state layout we just set up */ - total_state_size = next_offset; - assert (total_state_size < BRW_LINEAR_EXTRA); - - /* - * Use the extra space allocated at the end of the Xv buffer - */ - state_base_offset = (pPriv->YBuf0offset + - pPriv->linear->size * pI830->cpp - - BRW_LINEAR_EXTRA); - state_base_offset = ALIGN(state_base_offset, 64); - - state_base = (char *)(pI830->FbBase + state_base_offset); - /* Set up our pointers to state structures in framebuffer. It would probably - * be a good idea to fill these structures out in system memory and then dump - * them there, instead. - */ - vs_state = (void *)(state_base + vs_offset); - sf_state = (void *)(state_base + sf_offset); - wm_state = (void *)(state_base + wm_offset); - cc_state = (void *)(state_base + cc_offset); - sf_kernel = (void *)(state_base + sf_kernel_offset); - ps_kernel = (void *)(state_base + ps_kernel_offset); - sip_kernel = (void *)(state_base + sip_kernel_offset); - - cc_viewport = (void *)(state_base + cc_viewport_offset); - dest_surf_state = (void *)(state_base + dest_surf_offset); - src_surf_state = (void *)(state_base + src_surf_offset); - src_sampler_state = (void *)(state_base + src_sampler_offset); - binding_table = (void *)(state_base + binding_table_offset); - vb = (void *)(state_base + vb_offset); - - /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. - * A VUE consists of a 256-bit vertex header followed by the vertex data, - * which in our case is 4 floats (128 bits), thus a single 512-bit URB - * entry. - */ -#define URB_VS_ENTRIES 8 -#define URB_VS_ENTRY_SIZE 1 - -#define URB_GS_ENTRIES 0 -#define URB_GS_ENTRY_SIZE 0 - -#define URB_CLIP_ENTRIES 0 -#define URB_CLIP_ENTRY_SIZE 0 - - /* The SF kernel we use outputs only 4 256-bit registers, leading to an - * entry size of 2 512-bit URBs. We don't need to have many entries to - * output as we're generally working on large rectangles and don't care - * about having WM threads running on different rectangles simultaneously. - */ -#define URB_SF_ENTRIES 1 -#define URB_SF_ENTRY_SIZE 2 - -#define URB_CS_ENTRIES 0 -#define URB_CS_ENTRY_SIZE 0 - - urb_vs_start = 0; - urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; - urb_gs_start = urb_vs_start + urb_vs_size; - urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; - urb_clip_start = urb_gs_start + urb_gs_size; - urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; - urb_sf_start = urb_clip_start + urb_clip_size; - urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; - urb_cs_start = urb_sf_start + urb_sf_size; - urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - - /* We'll be poking the state buffers that could be in use by the 3d hardware - * here, but we should have synced the 3D engine already in I830PutImage. - */ - - memset (cc_viewport, 0, sizeof (*cc_viewport)); - cc_viewport->min_depth = -1.e35; - cc_viewport->max_depth = 1.e35; - - /* Color calculator state */ - memset(cc_state, 0, sizeof(*cc_state)); - cc_state->cc0.stencil_enable = 0; /* disable stencil */ - cc_state->cc2.depth_test = 0; /* disable depth test */ - cc_state->cc2.logicop_enable = 1; /* enable logic op */ - cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ - cc_state->cc3.blend_enable = 0; /* disable color blend */ - cc_state->cc3.alpha_test = 0; /* disable alpha test */ - cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5; - cc_state->cc5.dither_enable = 0; /* disable dither */ - cc_state->cc5.logicop_func = 0xc; /* WHITE */ - cc_state->cc5.statistics_enable = 1; - cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; - cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; - cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; - - /* Upload system kernel */ - memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); - - /* Set up the state buffer for the destination surface */ - memset(dest_surf_state, 0, sizeof(*dest_surf_state)); - dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; - dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; - if (pI830->cpp == 2) { - dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; - } else { - dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - } - dest_surf_state->ss0.writedisable_alpha = 0; - dest_surf_state->ss0.writedisable_red = 0; - dest_surf_state->ss0.writedisable_green = 0; - dest_surf_state->ss0.writedisable_blue = 0; - dest_surf_state->ss0.color_blend = 1; - dest_surf_state->ss0.vert_line_stride = 0; - dest_surf_state->ss0.vert_line_stride_ofs = 0; - dest_surf_state->ss0.mipmap_layout_mode = 0; - dest_surf_state->ss0.render_cache_read_mode = 0; - - dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; - dest_surf_state->ss2.height = pScrn->virtualY - 1; - dest_surf_state->ss2.width = pScrn->virtualX - 1; - dest_surf_state->ss2.mip_count = 0; - dest_surf_state->ss2.render_target_rotation = 0; - dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; - - /* Set up the source surface state buffer */ - memset(src_surf_state, 0, sizeof(*src_surf_state)); - src_surf_state->ss0.surface_type = BRW_SURFACE_2D; -/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */ - switch (id) { - case FOURCC_YUY2: - src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; - break; - case FOURCC_UYVY: - src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; - break; - } - src_surf_state->ss0.writedisable_alpha = 0; - src_surf_state->ss0.writedisable_red = 0; - src_surf_state->ss0.writedisable_green = 0; - src_surf_state->ss0.writedisable_blue = 0; - src_surf_state->ss0.color_blend = 1; - src_surf_state->ss0.vert_line_stride = 0; - src_surf_state->ss0.vert_line_stride_ofs = 0; - src_surf_state->ss0.mipmap_layout_mode = 0; - src_surf_state->ss0.render_cache_read_mode = 0; - - src_surf_state->ss1.base_addr = pPriv->YBuf0offset; - src_surf_state->ss2.width = width - 1; - src_surf_state->ss2.height = height - 1; - src_surf_state->ss2.mip_count = 0; - src_surf_state->ss2.render_target_rotation = 0; - src_surf_state->ss3.pitch = video_pitch - 1; - - /* Set up a binding table for our two surfaces. Only the PS will use it */ - /* XXX: are these offset from the right place? */ - binding_table[0] = state_base_offset + dest_surf_offset; - binding_table[1] = state_base_offset + src_surf_offset; - - /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. - */ - memset(src_sampler_state, 0, sizeof(*src_sampler_state)); - src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; - src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; - src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - - /* Set up the vertex shader to be disabled (passthrough) */ - memset(vs_state, 0, sizeof(*vs_state)); - vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; - vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; - vs_state->vs6.vs_enable = 0; - vs_state->vs6.vert_cache_disable = 1; - - /* Set up the SF kernel to do coord interp: for each attribute, - * calculate dA/dx and dA/dy. Hand these interpolation coefficients - * back to SF which then hands pixels off to WM. - */ - - memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); - memset(sf_state, 0, sizeof(*sf_state)); -#if 0 - ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); -#endif - sf_state->thread0.kernel_start_pointer = - (state_base_offset + sf_kernel_offset) >> 6; - sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); - sf_state->sf1.single_program_flow = 1; /* XXX */ - sf_state->sf1.binding_table_entry_count = 0; - sf_state->sf1.thread_priority = 0; - sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ - sf_state->sf1.illegal_op_exception_enable = 1; - sf_state->sf1.mask_stack_exception_enable = 1; - sf_state->sf1.sw_exception_enable = 1; - sf_state->thread2.per_thread_scratch_space = 0; - sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */ - sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ - sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ - sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ - sf_state->thread3.urb_entry_read_offset = 0; - sf_state->thread3.dispatch_grf_start_reg = 3; - sf_state->thread4.max_threads = SF_MAX_THREADS - 1; - sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; - sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; - sf_state->thread4.stats_enable = 1; - sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ - sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; - sf_state->sf6.scissor = 0; - sf_state->sf7.trifan_pv = 2; - sf_state->sf6.dest_org_vbias = 0x8; - sf_state->sf6.dest_org_hbias = 0x8; - - memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); -#if 0 - ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); -#endif - memset (wm_state, 0, sizeof (*wm_state)); - wm_state->thread0.kernel_start_pointer = - (state_base_offset + ps_kernel_offset) >> 6; - wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); - wm_state->thread1.single_program_flow = 1; /* XXX */ - wm_state->thread1.binding_table_entry_count = 2; - /* Though we never use the scratch space in our WM kernel, it has to be - * set, and the minimum allocation is 1024 bytes. - */ - wm_state->thread2.scratch_space_base_pointer = (state_base_offset + - wm_scratch_offset) >> 10; - wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ - wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ - wm_state->thread3.const_urb_entry_read_length = 0; - wm_state->thread3.const_urb_entry_read_offset = 0; - wm_state->thread3.urb_entry_read_length = 1; /* XXX */ - wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ - wm_state->wm4.stats_enable = 1; - wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; - wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ - wm_state->wm5.max_threads = PS_MAX_THREADS - 1; - wm_state->wm5.thread_dispatch_enable = 1; - wm_state->wm5.enable_16_pix = 1; - wm_state->wm5.enable_8_pix = 0; - wm_state->wm5.early_depth_test = 1; - - { - BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | - MI_STATE_INSTRUCTION_CACHE_FLUSH | - BRW_MI_GLOBAL_SNAPSHOT_RESET); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - } - -/* brw_debug (pScrn, "before base address modify"); */ - { BEGIN_LP_RING(12); - /* Match Mesa driver setup */ - OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); - - /* Mesa does this. Who knows... */ - OUT_RING(BRW_CS_URB_STATE | 0); - OUT_RING((0 << 4) | /* URB Entry Allocation Size */ - (0 << 0)); /* Number of URB Entries */ - - /* Zero out the two base address registers so all offsets are absolute */ - OUT_RING(BRW_STATE_BASE_ADDRESS | 4); - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ - OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* general state max addr, disabled */ - OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* media object state max addr, disabled */ - - /* Set system instruction pointer */ - OUT_RING(BRW_STATE_SIP | 0); - OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */ - - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); } - -/* brw_debug (pScrn, "after base address modify"); */ - - { BEGIN_LP_RING(42); - /* Enable VF statistics */ - OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); - - /* Pipe control */ - OUT_RING(BRW_PIPE_CONTROL | - BRW_PIPE_CONTROL_NOWRITE | - BRW_PIPE_CONTROL_IS_FLUSH | - 2); - OUT_RING(0); /* Destination address */ - OUT_RING(0); /* Immediate data low DW */ - OUT_RING(0); /* Immediate data high DW */ - - /* Binding table pointers */ - OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); - OUT_RING(0); /* vs */ - OUT_RING(0); /* gs */ - OUT_RING(0); /* clip */ - OUT_RING(0); /* sf */ - /* Only the PS uses the binding table */ - OUT_RING(state_base_offset + binding_table_offset); /* ps */ - - /* Blend constant color (magenta is fun) */ - OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); - OUT_RING(float_to_uint (1.0)); - OUT_RING(float_to_uint (0.0)); - OUT_RING(float_to_uint (1.0)); - OUT_RING(float_to_uint (1.0)); - - /* The drawing rectangle clipping is always on. Set it to values that - * shouldn't do any clipping. - */ - OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ - OUT_RING(0x00000000); /* ymin, xmin */ - OUT_RING((pScrn->virtualX - 1) | - (pScrn->virtualY - 1) << 16); /* ymax, xmax */ - OUT_RING(0x00000000); /* yorigin, xorigin */ - - /* skip the depth buffer */ - /* skip the polygon stipple */ - /* skip the polygon stipple offset */ - /* skip the line stipple */ - - /* Set the pointers to the 3d pipeline state */ - OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); - OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ - OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */ - OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */ - OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ - OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ - OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ - - /* URB fence */ - OUT_RING(BRW_URB_FENCE | - UF0_CS_REALLOC | - UF0_SF_REALLOC | - UF0_CLIP_REALLOC | - UF0_GS_REALLOC | - UF0_VS_REALLOC | - 1); - OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | - ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | - ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); - OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | - ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); - - /* Constant buffer state */ - OUT_RING(BRW_CS_URB_STATE | 0); - OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */ - (URB_CS_ENTRIES << 0)); /* Number of URB Entries */ - - /* Set up the pointer to our vertex buffer */ - OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); - OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | - VB0_VERTEXDATA | - ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */ - OUT_RING(state_base_offset + vb_offset); - OUT_RING(3); /* four corners to our rectangle */ - - /* Set up our vertex elements, sourced from the single vertex buffer. */ - OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); - /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ - OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (0 << VE0_OFFSET_SHIFT)); - OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ - OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (8 << VE0_OFFSET_SHIFT)); - OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - - OUT_RING(MI_NOOP); /* pad to quadword */ - ADVANCE_LP_RING(); } - - dxo = dstRegion->extents.x1; - dyo = dstRegion->extents.y1; - - pbox = REGION_RECTS(dstRegion); - nbox = REGION_NUM_RECTS(dstRegion); - while (nbox--) - { - int box_x1 = pbox->x1; - int box_y1 = pbox->y1; - int box_x2 = pbox->x2; - int box_y2 = pbox->y2; - int i; - float src_scale_x, src_scale_y; - - if (!first_output) { - /* Since we use the same little vertex buffer over and over, sync for - * subsequent rectangles. - */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } - } - - pbox++; - - /* Use normalized texture coordinates */ - src_scale_x = (float)1.0 / (float)drw_w; - src_scale_y = (float)1.0 / (float)drw_h; - - i = 0; - vb[i++] = (box_x2 - dxo) * src_scale_x; - vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x2; - vb[i++] = (float) box_y2; - - vb[i++] = (box_x1 - dxo) * src_scale_x; - vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y2; - - vb[i++] = (box_x1 - dxo) * src_scale_x; - vb[i++] = (box_y1 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y1; - -#if 0 - ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", - INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), - INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); - - OUTREG(BRW_VF_CTL, - BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | - BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | - BRW_VF_CTL_SNAPSHOT_ENABLE); - OUTREG(BRW_VF_STRG_VAL, 0); -#endif - -#if 0 - OUTREG(BRW_VS_CTL, - BRW_VS_CTL_SNAPSHOT_ALL_THREADS | - BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | - BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); - - OUTREG(BRW_VS_STRG_VAL, 0); -#endif - -#if WATCH_SF - OUTREG(BRW_SF_CTL, - BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | - BRW_SF_CTL_SNAPSHOT_ALL_THREADS | - BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); - OUTREG(BRW_SF_STRG_VAL, 0); -#endif - -#if WATCH_WIZ - OUTREG(BRW_WIZ_CTL, - BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | - BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | - BRW_WIZ_CTL_SNAPSHOT_ENABLE); - OUTREG(BRW_WIZ_STRG_VAL, - (box_x1) | (box_y1 << 16)); -#endif - -#if 0 - OUTREG(BRW_TS_CTL, - BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | - BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | - BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | - BRW_TS_CTL_SNAPSHOT_ENABLE); -#endif - - BEGIN_LP_RING(6); - OUT_RING(BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | /* CTG - indirect vertex count */ - 4); - OUT_RING(3); /* vertex count per instance */ - OUT_RING(0); /* start vertex offset */ - OUT_RING(1); /* single instance */ - OUT_RING(0); /* start instance location */ - OUT_RING(0); /* index buffer offset, ignored */ - ADVANCE_LP_RING(); - -#if 0 - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_VF_CTL); - if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_VF_RDATA); - OUTREG(BRW_VF_CTL, 0); - ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); -#endif - -#if 0 - for (j = 0; j < 1000000; j++) { - ctl = INREG(BRW_VS_CTL); - if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_VS_RDATA); - for (k = 0; k <= 3; k++) { - OUTREG(BRW_VS_CTL, - BRW_VS_CTL_SNAPSHOT_COMPLETE | - (k << 8)); - rdata = INREG(BRW_VS_RDATA); - ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); - } - - OUTREG(BRW_VS_CTL, 0); -#endif - -#if WATCH_SF - for (j = 0; j < 1000000; j++) { - ctl = INREG(BRW_SF_CTL); - if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) - break; - } - - for (k = 0; k <= 7; k++) { - OUTREG(BRW_SF_CTL, - BRW_SF_CTL_SNAPSHOT_COMPLETE | - (k << 8)); - rdata = INREG(BRW_SF_RDATA); - ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); - } - - OUTREG(BRW_SF_CTL, 0); -#endif - -#if WATCH_WIZ - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_WIZ_CTL); - if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_WIZ_RDATA); - OUTREG(BRW_WIZ_CTL, 0); - ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); -#endif - -#if 0 - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_TS_CTL); - if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_TS_RDATA); - OUTREG(BRW_TS_CTL, 0); - ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); - - ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", - INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), - INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); -#endif - -#if 0 - for (j = 0; j < 256; j++) { - OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); - rdata = INREG(BRW_TD_RDATA); - ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); - } -#endif - first_output = FALSE; - if (pI830->AccelInfoRec) - pI830->AccelInfoRec->NeedToSync = TRUE; - } - - if (pI830->AccelInfoRec) - (*pI830->AccelInfoRec->Sync)(pScrn); -#if WATCH_STATS - i830_dump_error_state (pScrn); -#endif -} - -static FBLinearPtr -I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) -{ - ScreenPtr pScreen; - FBLinearPtr new_linear = NULL; - - if (linear) { - if (linear->size >= size) - return linear; - - if (xf86ResizeOffscreenLinear(linear, size)) - return linear; - - xf86FreeOffscreenLinear(linear); - } - - pScreen = screenInfo.screens[pScrn->scrnIndex]; - - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); - - if (!new_linear) { +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, + /* Converts an offset from XAA's linear allocator to an offset from the + * start of fb. + */ +#define XAA_OFFSET_TO_OFFSET(x) (pI830->FrontBuffer.Start + (x * pI830->cpp)) + + /* The XFree86 linear allocator operates in units of screen pixels, + * sadly. + */ + size = (size + pI830->cpp - 1) / pI830->cpp; + align = (align + pI830->cpp - 1) / pI830->cpp; + + if (linear->xaa != NULL) { + if (linear->xaa->size >= size) { + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); + return; + } + + if (xf86ResizeOffscreenLinear(linear->xaa, size)) { + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); + return; + } + + xf86FreeOffscreenLinear(linear->xaa); + } + + linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (linear->xaa != NULL) { + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); + return; + } + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, align, PRIORITY_EXTREME); if (max_size < size) { - ErrorF("No memory available\n"); - return NULL; + ErrorF("No memory available\n"); + linear->offset = 0; + return; } xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); + linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4, + NULL, NULL, NULL); + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); } +#endif /* I830_USE_XAA */ +} - return new_linear; +static void +I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear) +{ + I830Ptr pI830 = I830PTR(pScrn); + +#ifdef I830_USE_EXA + if (pI830->useEXA) { + if (linear->exa != NULL) { + exaOffscreenFree(pScrn->pScreen, linear->exa); + linear->exa = NULL; + } + } +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { + if (linear->xaa != NULL) { + xf86FreeOffscreenLinear(linear->xaa); + linear->xaa = NULL; + } + } +#endif /* I830_USE_XAA */ + linear->offset = 0; } /* @@ -2867,6 +2173,7 @@ I830PutImage(ScrnInfoPtr pScrn, ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + PixmapPtr pPixmap; INT32 x1, x2, y1, y2; int srcPitch, srcPitch2 = 0, dstPitch, destId; int top, left, npixels, nlines, size, loops; @@ -2874,9 +2181,11 @@ I830PutImage(ScrnInfoPtr pScrn, int pitchAlignMask; int extraLinear; +#if 0 ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n" "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height); +#endif if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && @@ -2981,20 +2290,18 @@ I830PutImage(ScrnInfoPtr pScrn, extraLinear = 0; /* size is multiplied by 2 because we have two buffers that are flipping */ - pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, - (extraLinear + - (pPriv->doubleBuffer ? size * 2 : size)) / - pI830->cpp); + I830AllocateMemory(pScrn, &pPriv->linear, + extraLinear + (pPriv->doubleBuffer ? size * 2 : size), + 16); - if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY)) + if (pPriv->linear.offset == 0) return BadAlloc; + pPriv->extra_offset = pPriv->linear.offset + + (pPriv->doubleBuffer ? size * 2 : size); + /* fixup pointers */ -#if 0 - pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp; -#else - pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp; -#endif + pPriv->YBuf0offset = pPriv->linear.offset; if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); @@ -3080,6 +2387,28 @@ I830PutImage(ScrnInfoPtr pScrn, break; } + if (pDraw->type == DRAWABLE_WINDOW) { + pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); + } else { + pPixmap = (PixmapPtr)pDraw; + } + +#ifdef I830_USE_EXA + if (pI830->useEXA) { + /* Force the pixmap into framebuffer so we can draw to it. */ + exaMoveInPixmap(pPixmap); + } +#endif + + if (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) || + ((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase + + pI830->FbMapSize)) { + /* If the pixmap wasn't in framebuffer, then we have no way in XAA to + * force it there. So, we simply refuse to draw and fail. + */ + return BadAlloc; + } + if (!pPriv->textured) { /* update cliplist */ if (!RegionsEqual(&pPriv->clip, clipBoxes)) { @@ -3090,14 +2419,18 @@ I830PutImage(ScrnInfoPtr pScrn, I830DisplayVideo(pScrn, destId, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); } else if (IS_I965G(pI830)) { - BroadwaterDisplayVideoTextured (pScrn, pPriv, destId, clipBoxes, width, height, - dstPitch, x1, y1, x2, y2, - src_w, src_h, drw_w, drw_h, pDraw); + I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, + dstPitch, x1, y1, x2, y2, + src_w, src_h, drw_w, drw_h, pPixmap); } else { I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, dstPitch, x1, y1, x2, y2, - src_w, src_h, drw_w, drw_h, pDraw); + src_w, src_h, drw_w, drw_h, pPixmap); } + if (pPriv->textured) { + DamageDamageRegion(pDraw, clipBoxes); + } + pPriv->videoStatus = CLIENT_VIDEO_ON; return Success; @@ -3159,6 +2492,7 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, if (offsets) offsets[2] = size; size += tmp; +#if 0 if (pitches) ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", pitches[0], pitches[1], pitches[2]); @@ -3166,6 +2500,7 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], offsets[2]); if (offsets) ErrorF("size is %d\n", size); +#endif break; case FOURCC_UYVY: case FOURCC_YUY2: @@ -3222,7 +2557,7 @@ I830BlockHandler(int i, if (pPriv->videoStatus & OFF_TIMER) { if (pPriv->offTime < now) { /* Turn off the overlay */ - ErrorF("BLOCKHANDLER\n"); + OVERLAY_DEBUG("BLOCKHANDLER\n"); I830ResetVideo(pScrn); OVERLAY_UPDATE; @@ -3236,10 +2571,7 @@ I830BlockHandler(int i, } } else { /* FREE_TIMER */ if (pPriv->freeTime < now) { - if (pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; - } + I830FreeMemory(pScrn, &pPriv->linear); pPriv->videoStatus = 0; } } @@ -3251,7 +2583,7 @@ I830BlockHandler(int i, ***************************************************************************/ typedef struct { - FBLinearPtr linear; + struct linear_alloc linear; Bool isOn; } OffscreenPrivRec, *OffscreenPrivPtr; @@ -3261,12 +2593,11 @@ I830AllocateSurface(ScrnInfoPtr pScrn, unsigned short w, unsigned short h, XF86SurfacePtr surface) { - FBLinearPtr linear; - int pitch, fbpitch, size, bpp; + int pitch, fbpitch, size; OffscreenPrivPtr pPriv; I830Ptr pI830 = I830PTR(pScrn); - ErrorF("I830AllocateSurface\n"); + OVERLAY_DEBUG("I830AllocateSurface\n"); if (IS_845G(pI830) || IS_I830(pI830)) { if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY)) @@ -3280,48 +2611,43 @@ I830AllocateSurface(ScrnInfoPtr pScrn, if (pI830->rotation != RR_Rotate_0) return BadAlloc; - w = (w + 1) & ~1; - pitch = ((w << 1) + 15) & ~15; - bpp = pScrn->bitsPerPixel >> 3; - fbpitch = bpp * pScrn->displayWidth; - size = ((pitch * h) + bpp - 1) / bpp; - - if (!(linear = I830AllocateMemory(pScrn, NULL, size))) + if (!(surface->pitches = xalloc(sizeof(int)))) return BadAlloc; - - surface->width = w; - surface->height = h; - - if (!(surface->pitches = xalloc(sizeof(int)))) { - xf86FreeOffscreenLinear(linear); - return BadAlloc; - } if (!(surface->offsets = xalloc(sizeof(int)))) { xfree(surface->pitches); - xf86FreeOffscreenLinear(linear); return BadAlloc; } if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { xfree(surface->pitches); xfree(surface->offsets); - xf86FreeOffscreenLinear(linear); return BadAlloc; } - pPriv->linear = linear; + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + fbpitch = pI830->cpp * pScrn->displayWidth; + size = pitch * h; + + I830AllocateMemory(pScrn, &pPriv->linear, size, 16); + if (pPriv->linear.offset == 0) { + xfree(surface->pitches); + xfree(surface->offsets); + xfree(pPriv); + return BadAlloc; + } + + surface->width = w; + surface->height = h; + pPriv->isOn = FALSE; surface->pScrn = pScrn; surface->id = id; surface->pitches[0] = pitch; - surface->offsets[0] = linear->offset * bpp; + surface->offsets[0] = pPriv->linear.offset; surface->devPrivate.ptr = (pointer) pPriv; -#if 0 - memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size); -#else - memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size); -#endif + memset(pI830->FbBase + surface->offsets[0], 0, size); return Success; } @@ -3335,7 +2661,7 @@ I830StopSurface(XF86SurfacePtr surface) if (pPriv->isOn) { I830Ptr pI830 = I830PTR(pScrn); - ErrorF("StopSurface\n"); + OVERLAY_DEBUG("StopSurface\n"); I830ResetVideo(pScrn); OVERLAY_UPDATE; @@ -3358,7 +2684,7 @@ I830FreeSurface(XF86SurfacePtr surface) if (pPriv->isOn) { I830StopSurface(surface); } - xf86FreeOffscreenLinear(pPriv->linear); + I830FreeMemory(surface->pScrn, &pPriv->linear); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); @@ -3396,7 +2722,7 @@ I830DisplaySurface(XF86SurfacePtr surface, INT32 loops = 0; BoxRec dstBox; - ErrorF("I830DisplaySurface\n"); + OVERLAY_DEBUG("I830DisplaySurface\n"); if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && diff --git a/src/i830_video.h b/src/i830_video.h index 6a09a258..854d0b80 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -27,6 +27,18 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86.h" #include "xf86_OSproc.h" +/* Ugly mess to support the old XF86 allocator or EXA using the same code. + */ +struct linear_alloc { +#ifdef I830_USE_XAA + FBLinearPtr xaa; +#endif +#ifdef I830_USE_EXA + ExaOffscreenArea *exa; +#endif + unsigned int offset; +}; + typedef struct { CARD32 YBuf0offset; CARD32 UBuf0offset; @@ -57,7 +69,8 @@ typedef struct { CARD32 videoStatus; Time offTime; Time freeTime; - FBLinearPtr linear; + struct linear_alloc linear; + unsigned int extra_offset; Bool overlayOK; int oneLineMode; @@ -68,10 +81,23 @@ typedef struct { #define GET_PORT_PRIVATE(pScrn) \ (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr) +/* + * Broadwater requires a bit of extra video memory for state information + */ +#define BRW_LINEAR_EXTRA (36*1024) + void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, short width, short height, int video_pitch, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, - DrawablePtr pDraw); + PixmapPtr pPixmap); + +void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + int id, RegionPtr dstRegion, short width, + short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + PixmapPtr pPixmap); diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 0c482a2e..ceb8f2ef 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -1,25 +1,23 @@ /* - * $Id: $ - * * Copyright © 2006 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H @@ -32,9 +30,14 @@ #include "xf86.h" #include "xf86DDC.h" -#include "i830.h" +/*#include "i830.h" */ #include "i830_xf86Crtc.h" +#include "i830_xf86Modes.h" +#include "i830_randr.h" #include "X11/extensions/render.h" +#define DPMS_SERVER +#include "X11/extensions/dpms.h" +#include "X11/Xatom.h" /* * Initialize xf86CrtcConfig structure @@ -121,6 +124,79 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) /* * Output functions */ + +extern XF86ConfigPtr xf86configptr; + +typedef enum { + OPTION_PREFERRED_MODE, + OPTION_POSITION, + OPTION_BELOW, + OPTION_RIGHT_OF, + OPTION_ABOVE, + OPTION_LEFT_OF, + OPTION_ENABLE, + OPTION_DISABLE, + OPTION_MIN_CLOCK, + OPTION_MAX_CLOCK, +} OutputOpts; + +static OptionInfoRec xf86OutputOptions[] = { + {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, + {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, + {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, + {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, + {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +static void +xf86OutputSetMonitor (xf86OutputPtr output) +{ + char *option_name; + static const char monitor_prefix[] = "monitor-"; + char *monitor; + + if (output->options) + xfree (output->options); + + output->options = xnfalloc (sizeof (xf86OutputOptions)); + memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); + + option_name = xnfalloc (strlen (monitor_prefix) + + strlen (output->name) + 1); + strcpy (option_name, monitor_prefix); + strcat (option_name, output->name); + monitor = xf86findOptionValue (output->scrn->options, option_name); + if (!monitor) + monitor = output->name; + else + xf86MarkOptionUsedByName (output->scrn->options, option_name); + xfree (option_name); + output->conf_monitor = xf86findMonitor (monitor, + xf86configptr->conf_monitor_lst); + if (output->conf_monitor) + xf86ProcessOptions (output->scrn->scrnIndex, + output->conf_monitor->mon_option_lst, + output->options); +} + +static Bool +xf86OutputEnabled (xf86OutputPtr output) +{ + /* Check to see if this output was disabled in the config file */ + if (xf86ReturnOptValBool (output->options, OPTION_ENABLE, TRUE) == FALSE || + xf86ReturnOptValBool (output->options, OPTION_DISABLE, FALSE) == TRUE) + { + return FALSE; + } + return TRUE; +} + xf86OutputPtr xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, @@ -141,6 +217,8 @@ xf86OutputCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE output->randr_output = NULL; #endif + xf86OutputSetMonitor (output); + if (xf86_config->output) outputs = xrealloc (xf86_config->output, (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); @@ -151,24 +229,28 @@ xf86OutputCreate (ScrnInfoPtr scrn, xfree (output); return NULL; } + xf86_config->output = outputs; xf86_config->output[xf86_config->num_output++] = output; + return output; } -void +Bool xf86OutputRename (xf86OutputPtr output, const char *name) { int len = strlen(name); char *newname = xalloc (len + 1); if (!newname) - return; /* so sorry... */ + return FALSE; /* so sorry... */ strcpy (newname, name); if (output->name != (char *) (output + 1)) xfree (output->name); output->name = newname; + xf86OutputSetMonitor (output); + return TRUE; } void @@ -345,7 +427,9 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, * If the two outputs desire the same mode, * see if they can be cloned */ - if (xf86ModesEqual (modes[o], modes[n])) + if (xf86ModesEqual (modes[o], modes[n]) && + config->output[o]->initial_x == config->output[n]->initial_x && + config->output[o]->initial_y == config->output[n]->initial_y) { for (l = 0; l < config->num_output; l++) if (output->possible_clones & (1 << l)) @@ -373,7 +457,8 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, /* * Compute the virtual size necessary to place all of the available - * crtcs in a panorama configuration + * crtcs in the specified configuration and also large enough to + * resize any crtc to the largest available mode */ static void @@ -388,7 +473,13 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) for (c = 0; c < config->num_crtc; c++) { int crtc_width = 0, crtc_height = 0; + xf86CrtcPtr crtc = config->crtc[c]; + if (crtc->enabled) + { + crtc_width = crtc->x + crtc->desiredMode.HDisplay; + crtc_height = crtc->y + crtc->desiredMode.VDisplay; + } for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -406,7 +497,8 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) } } } - width += crtc_width; + if (crtc_width > width) + width = crtc_width; if (crtc_height > height) height = crtc_height; } @@ -418,6 +510,186 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) *heightp = height; } +#define POSITION_UNSET -100000 + +static Bool +xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + int min_x, min_y; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x = output->initial_y = POSITION_UNSET; + } + + /* + * Loop until all outputs are set + */ + for (;;) + { + Bool any_set = FALSE; + Bool keep_going = FALSE; + + for (o = 0; o < config->num_output; o++) + { + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + xf86OutputPtr output = config->output[o]; + xf86OutputPtr relative; + char *relative_name; + char *position; + OutputOpts relation; + int r; + + if (output->initial_x != POSITION_UNSET) + continue; + position = xf86GetOptValString (output->options, + OPTION_POSITION); + /* + * Absolute position wins + */ + if (position) + { + int x, y; + if (sscanf (position, "%d %d", &x, &y) == 2) + { + output->initial_x = x; + output->initial_y = y; + } + else + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Output %s position not of form \"x y\"\n", + output->name); + output->initial_x = output->initial_y = 0; + } + any_set = TRUE; + continue; + } + /* + * Next comes relative positions + */ + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + { + int or; + relative = NULL; + for (or = 0; or < config->num_output; or++) + { + xf86OutputPtr out_rel = config->output[or]; + XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; + char *name; + + if (rel_mon) + name = rel_mon->mon_identifier; + else + name = out_rel->name; + if (!strcmp (relative_name, name)) + { + relative = config->output[or]; + break; + } + } + if (!relative) + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to unknown output %s\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (relative->initial_x == POSITION_UNSET) + { + keep_going = TRUE; + continue; + } + output->initial_x = relative->initial_x; + output->initial_y = relative->initial_y; + switch (relation) { + case OPTION_BELOW: + output->initial_y += modes[or]->VDisplay; + break; + case OPTION_RIGHT_OF: + output->initial_x += modes[or]->HDisplay; + break; + case OPTION_ABOVE: + output->initial_y -= modes[o]->VDisplay; + break; + case OPTION_LEFT_OF: + output->initial_x -= modes[o]->HDisplay; + break; + default: + break; + } + any_set = TRUE; + continue; + } + + /* Nothing set, just stick them at 0,0 */ + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + } + if (!keep_going) + break; + if (!any_set) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->initial_x == POSITION_UNSET) + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Output position loop. Moving %s to 0,0\n", + output->name); + output->initial_x = output->initial_y = 0; + break; + } + } + } + } + + /* + * normalize positions + */ + min_x = 1000000; + min_y = 1000000; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->initial_x < min_x) + min_x = output->initial_x; + if (output->initial_y < min_y) + min_y = output->initial_y; + } + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x -= min_x; + output->initial_y -= min_y; + } + return TRUE; +} + /* * XXX walk the monitor mode list and prune out duplicates that * are inserted by xf86DDCMonitorSet. In an ideal world, that @@ -446,34 +718,261 @@ xf86PruneDuplicateMonitorModes (MonPtr Monitor) } } +/** Return - 0 + if a should be earlier, same or later than b in list + */ +static int +i830xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) +{ + int diff; + + diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); + if (diff) + return diff; + diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; + if (diff) + return diff; + diff = b->Clock - a->Clock; + return diff; +} + +/** + * Insertion sort input in-place and return the resulting head + */ +static DisplayModePtr +i830xf86SortModes (DisplayModePtr input) +{ + DisplayModePtr output = NULL, i, o, n, *op, prev; + + /* sort by preferred status and pixel area */ + while (input) + { + i = input; + input = input->next; + for (op = &output; (o = *op); op = &o->next) + if (i830xf86ModeCompare (o, i) > 0) + break; + i->next = *op; + *op = i; + } + /* prune identical modes */ + for (o = output; o && (n = o->next); o = n) + { + if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) + { + o->next = n->next; + xfree (n->name); + xfree (n); + n = o; + } + } + /* hook up backward links */ + prev = NULL; + for (o = output; o; o = o->next) + { + o->prev = prev; + prev = o; + } + return output; +} + +#define DEBUG_REPROBE 1 + void -xf86ProbeOutputModes (ScrnInfoPtr pScrn) +xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool properties_set = FALSE; int o; + if (maxX == 0 || maxY == 0) + xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY); + /* Elide duplicate modes before defaulting code uses them */ xf86PruneDuplicateMonitorModes (pScrn->monitor); /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode; - + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + DisplayModePtr config_modes = NULL, output_modes, default_modes; + char *preferred_mode; + xf86MonPtr edid_monitor; + XF86ConfMonitorPtr conf_monitor; + MonRec mon_rec; + int min_clock = 0; + int max_clock = 0; + double clock; + enum { sync_config, sync_edid, sync_default } sync_source = sync_default; + while (output->probed_modes != NULL) xf86DeleteMode(&output->probed_modes, output->probed_modes); - output->probed_modes = (*output->funcs->get_modes) (output); - - /* Set the DDC properties to whatever first output has DDC information. + /* + * Check connection status */ - if (output->MonInfo != NULL && !properties_set) { - xf86SetDDCproperties(pScrn, output->MonInfo); - properties_set = TRUE; + output->status = (*output->funcs->detect)(output); + + if (output->status == XF86OutputStatusDisconnected) + continue; + + memset (&mon_rec, '\0', sizeof (mon_rec)); + + conf_monitor = output->conf_monitor; + + if (conf_monitor) + { + int i; + + for (i = 0; i < conf_monitor->mon_n_hsync; i++) + { + mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; + mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; + mon_rec.nHsync++; + sync_source = sync_config; + } + for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; + mon_rec.nVrefresh++; + sync_source = sync_config; + } + config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor); + } + + output_modes = (*output->funcs->get_modes) (output); + + edid_monitor = output->MonInfo; + + if (edid_monitor) + { + int i; + Bool set_hsync = mon_rec.nHsync == 0; + Bool set_vrefresh = mon_rec.nVrefresh == 0; + + for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++) + { + if (edid_monitor->det_mon[i].type == DS_RANGES) + { + struct monitor_ranges *ranges = &edid_monitor->det_mon[i].section.ranges; + if (set_hsync && ranges->max_h) + { + mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h; + mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h; + mon_rec.nHsync++; + if (sync_source == sync_default) + sync_source = sync_edid; + } + if (set_vrefresh && ranges->max_v) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v; + mon_rec.nVrefresh++; + if (sync_source == sync_default) + sync_source = sync_edid; + } + if (ranges->max_clock > max_clock) + max_clock = ranges->max_clock; + } + } } + if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, + OPTUNITS_KHZ, &clock)) + min_clock = (int) clock; + if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, + OPTUNITS_KHZ, &clock)) + max_clock = (int) clock; + + /* + * These limits will end up setting a 1024x768@60Hz mode by default, + * which seems like a fairly good mode to use when nothing else is + * specified + */ + if (mon_rec.nHsync == 0) + { + mon_rec.hsync[0].lo = 31.0; + mon_rec.hsync[0].hi = 55.0; + mon_rec.nHsync = 1; + } + if (mon_rec.nVrefresh == 0) + { + mon_rec.vrefresh[0].lo = 58.0; + mon_rec.vrefresh[0].hi = 62.0; + mon_rec.nVrefresh = 1; + } + default_modes = i830xf86GetDefaultModes (output->interlaceAllowed, + output->doubleScanAllowed); + + if (sync_source == sync_config) + { + /* + * Check output and config modes against sync range from config file + */ + i830xf86ValidateModesSync (pScrn, output_modes, &mon_rec); + i830xf86ValidateModesSync (pScrn, config_modes, &mon_rec); + } + /* + * Check default modes against sync range + */ + i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec); + /* + * Check default modes against monitor max clock + */ + if (max_clock) + i830xf86ValidateModesClocks(pScrn, default_modes, + &min_clock, &max_clock, 1); + + output->probed_modes = NULL; + output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); + + /* + * Check all modes against max size + */ + if (maxX && maxY) + i830xf86ValidateModesSize (pScrn, output->probed_modes, + maxX, maxY, 0); + + /* + * Check all modes against output + */ + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output, mode); + + i830xf86PruneInvalidModes(pScrn, &output->probed_modes, TRUE); + + output->probed_modes = i830xf86SortModes (output->probed_modes); + + /* Check for a configured preference for a particular mode */ + preferred_mode = xf86GetOptValString (output->options, + OPTION_PREFERRED_MODE); + + if (preferred_mode) + { + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (!strcmp (preferred_mode, mode->name)) + { + if (mode != output->probed_modes) + { + if (mode->prev) + mode->prev->next = mode->next; + if (mode->next) + mode->next->prev = mode->prev; + mode->next = output->probed_modes; + output->probed_modes->prev = mode; + mode->prev = NULL; + output->probed_modes = mode; + } + mode->type |= M_T_PREFERRED; + break; + } + } + } + #ifdef DEBUG_REPROBE if (output->probed_modes != NULL) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -516,7 +1015,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn) xf86OutputPtr output; xf86CrtcPtr crtc; DisplayModePtr last, mode; - int originalVirtualX, originalVirtualY; output = config->output[config->compat_output]; if (!output->crtc) @@ -544,18 +1042,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn) /* Set pScrn->modes to the mode list for the 'compat' output */ pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes); - xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); - - /* Disable modes in the XFree86 DDX list that are larger than the current - * virtual size. - */ - i830xf86ValidateModesSize(pScrn, pScrn->modes, - originalVirtualX, originalVirtualY, - pScrn->displayWidth); - - /* Strip out anything that we threw out for virtualX/Y. */ - i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); - for (mode = pScrn->modes; mode; mode = mode->next) if (xf86ModesEqual (mode, &crtc->desiredMode)) break; @@ -591,35 +1077,33 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) DisplayModePtr target_mode = NULL; xf86CrtcPtr *crtcs; DisplayModePtr *modes; - int width, height; + Bool *enabled; + int width; + int height; - xf86ProbeOutputModes (pScrn); - - if (pScrn->display->virtualX == 0) - { - /* - * Expand virtual size to cover potential mode switches - */ - xf86DefaultScreenLimits (pScrn, &width, &height); - - pScrn->display->virtualX = width; - pScrn->display->virtualY = height; - } - else - { + if (pScrn->display->virtualX) width = pScrn->display->virtualX; + else + width = config->maxWidth; + if (pScrn->display->virtualY) height = pScrn->display->virtualY; - } - if (width > pScrn->virtualX) - pScrn->virtualX = width; - if (height > pScrn->virtualY) - pScrn->virtualY = height; - + else + height = config->maxHeight; + + xf86ProbeOutputModes (pScrn, width, height); + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + enabled = xnfcalloc (config->num_output, sizeof (Bool)); for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + modes[o] = NULL; + enabled[o] = (xf86OutputEnabled (output) && + output->status != XF86OutputStatusDisconnected); + } /* * Let outputs with preferred modes drive screen size @@ -628,7 +1112,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) { xf86OutputPtr output = config->output[o]; - if (output->status != XF86OutputStatusDisconnected && + if (enabled[o] && xf86OutputHasPreferredMode (output, width, height)) { target_mode = xf86DefaultMode (output, width, height); @@ -645,7 +1129,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; - if (output->status != XF86OutputStatusDisconnected) + if (enabled[o]) { target_mode = xf86DefaultMode (output, width, height); if (target_mode) @@ -661,10 +1145,23 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) { xf86OutputPtr output = config->output[o]; - if (output->status != XF86OutputStatusDisconnected && !modes[o]) + if (enabled[o] && !modes[o]) modes[o] = xf86ClosestMode (output, target_mode, width, height); } + /* + * Set the position of each output + */ + if (!xf86InitialOutputPositions (pScrn, modes)) + { + xfree (crtcs); + xfree (modes); + return FALSE; + } + + /* + * Assign CRTCs to fit output configuration + */ if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height)) { xfree (crtcs); @@ -684,7 +1181,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) crtc->enabled = FALSE; memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); } - + /* * Set initial configuration */ @@ -698,13 +1195,28 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) { crtc->desiredMode = *mode; crtc->enabled = TRUE; - crtc->x = 0; - crtc->y = 0; + crtc->x = output->initial_x; + crtc->y = output->initial_y; output->crtc = crtc; - /* XXX set position; for now, we clone */ } } + if (pScrn->display->virtualX == 0) + { + /* + * Expand virtual size to cover potential mode switches + */ + xf86DefaultScreenLimits (pScrn, &width, &height); + + pScrn->display->virtualX = width; + pScrn->display->virtualY = height; + } + + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + /* Mirror output modes to pScrn mode list */ xf86SetScrnInfoModes (pScrn); @@ -747,3 +1259,115 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags) } } } + +#ifdef RANDR_12_INTERFACE + +#define EDID_ATOM_NAME "EDID_DATA" + +/** + * Set the RandR EDID property + */ +static void +xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) +{ + Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE); + + /* This may get called before the RandR resources have been created */ + if (output->randr_output == NULL) + return; + + if (data_len != 0) { + RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, + PropModeReplace, data_len, data, FALSE); + } else { + RRDeleteOutputProperty(output->randr_output, edid_atom); + } +} + +#endif + +/** + * Set the EDID information for the specified output + */ +void +i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) +{ + ScrnInfoPtr pScrn = output->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; +#ifdef RANDR_12_INTERFACE + int size; +#endif + + if (output->MonInfo != NULL) + xfree(output->MonInfo); + + output->MonInfo = edid_mon; + + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); + xf86PrintEDID(edid_mon); + + /* Set the DDC properties for the 'compat' output */ + if (output == config->output[config->compat_output]) + xf86SetDDCproperties(pScrn, edid_mon); + +#ifdef RANDR_12_INTERFACE + /* Set the RandR output properties */ + size = 0; + if (edid_mon) + { + if (edid_mon->ver.version == 1) + size = 128; + else if (edid_mon->ver.version == 2) + size = 256; + } + xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); +#endif + + if (edid_mon) + { + /* Pull out a phyiscal size from a detailed timing if available. */ + for (i = 0; i < 4; i++) { + if (edid_mon->det_mon[i].type == DT && + edid_mon->det_mon[i].section.d_timings.h_size != 0 && + edid_mon->det_mon[i].section.d_timings.v_size != 0) + { + output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size; + output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size; + break; + } + } + + /* if no mm size is available from a detailed timing, check the max size field */ + if ((!output->mm_width || !output->mm_height) && + (edid_mon->features.hsize && edid_mon->features.vsize)) + { + output->mm_width = edid_mon->features.hsize * 10; + output->mm_height = edid_mon->features.vsize * 10; + } + } +} + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +i830_xf86OutputGetEDIDModes (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + xf86MonPtr edid_mon = output->MonInfo; + + if (!edid_mon) + return NULL; + return xf86DDCGetModes(pScrn->scrnIndex, edid_mon); +} + +xf86MonPtr +i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) +{ + ScrnInfoPtr pScrn = output->scrn; + + return xf86DoEDID_DDC2 (pScrn->scrnIndex, pDDCBus); +} diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 9294ccc2..8fea162e 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -25,6 +25,15 @@ #include #include "randrstr.h" #include "i830_xf86Modes.h" +#include "xf86Parser.h" + +/* Compat definitions for older X Servers. */ +#ifndef M_T_PREFERRED +#define M_T_PREFERRED 0x08 +#endif +#ifndef M_T_DRIVER +#define M_T_DRIVER 0x40 +#endif typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr; typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr; @@ -80,6 +89,11 @@ typedef struct _xf86CrtcFuncs { DisplayModePtr mode, DisplayModePtr adjusted_mode); + /* Set the color ramps for the CRTC to the given values. */ + void + (*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, + int size); + /** * Clean up driver-specific bits of the crtc */ @@ -260,6 +274,17 @@ struct _xf86Output { * Possible outputs to share the same CRTC as a mask of output indices */ CARD32 possible_clones; + + /** + * Whether this output can support interlaced modes + */ + Bool interlaceAllowed; + + /** + * Whether this output can support double scan modes + */ + Bool doubleScanAllowed; + /** * List of available modes on this output. * @@ -268,6 +293,21 @@ struct _xf86Output { */ DisplayModePtr probed_modes; + /** + * Options parsed from the related monitor section + */ + OptionInfoPtr options; + + /** + * Configured monitor section + */ + XF86ConfMonitorPtr conf_monitor; + + /** + * Desired initial position + */ + int initial_x, initial_y; + /** * Current connection status * @@ -379,14 +419,14 @@ xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name); -void +Bool xf86OutputRename (xf86OutputPtr output, const char *name); void xf86OutputDestroy (xf86OutputPtr output); void -xf86ProbeOutputModes (ScrnInfoPtr pScrn); +xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY); void xf86SetScrnInfoModes (ScrnInfoPtr pScrn); @@ -396,5 +436,21 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn); void xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); + +/** + * Set the EDID information for the specified output + */ +void +i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon); + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +i830_xf86OutputGetEDIDModes (xf86OutputPtr output); + +xf86MonPtr +i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus); #endif /* _XF86CRTC_H_ */ diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 1afda951..482a3320 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -39,6 +39,9 @@ #include "xf86.h" #include "i830.h" #include "i830_xf86Modes.h" +#include "xf86Priv.h" + +extern XF86ConfigPtr xf86configptr; /** * @file this file contains symbols from xf86Mode.c and friends that are static @@ -550,3 +553,120 @@ xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new) return modes; } + +/** + * Build a mode list from a list of config file modes + */ +static DisplayModePtr +i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) +{ + DisplayModePtr head = NULL, prev = NULL, mode; + + for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next) + { + mode = xalloc(sizeof(DisplayModeRec)); + if (!mode) + continue; + mode->name = xstrdup(conf_mode->ml_identifier); + if (!mode->name) + { + xfree (mode); + continue; + } + + memset(mode,'\0',sizeof(DisplayModeRec)); + mode->type = 0; + mode->Clock = conf_mode->ml_clock; + mode->HDisplay = conf_mode->ml_hdisplay; + mode->HSyncStart = conf_mode->ml_hsyncstart; + mode->HSyncEnd = conf_mode->ml_hsyncend; + mode->HTotal = conf_mode->ml_htotal; + mode->VDisplay = conf_mode->ml_vdisplay; + mode->VSyncStart = conf_mode->ml_vsyncstart; + mode->VSyncEnd = conf_mode->ml_vsyncend; + mode->VTotal = conf_mode->ml_vtotal; + mode->Flags = conf_mode->ml_flags; + mode->HSkew = conf_mode->ml_hskew; + mode->VScan = conf_mode->ml_vscan; + + mode->prev = prev; + mode->next = NULL; + if (prev) + prev->next = mode; + else + head = mode; + prev = mode; + } + return head; +} + +/** + * Build a mode list from a monitor configuration + */ +DisplayModePtr +i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) +{ + DisplayModePtr modes = NULL; + XF86ConfModesLinkPtr modes_link; + + if (!conf_monitor) + return NULL; + + /* + * first we collect the mode lines from the UseModes directive + */ + for (modes_link = conf_monitor->mon_modes_sect_lst; + modes_link; + modes_link = modes_link->list.next) + { + /* If this modes link hasn't been resolved, go look it up now */ + if (!modes_link->ml_modes) + modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str, + xf86configptr->conf_modes_lst); + if (modes_link->ml_modes) + modes = xf86ModesAdd (modes, + i830xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst)); + } + + return xf86ModesAdd (modes, + i830xf86GetConfigModes (conf_monitor->mon_modeline_lst)); +} + +/** + * Build a mode list containing all of the default modes + */ +DisplayModePtr +i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed) +{ + DisplayModePtr head = NULL, prev = NULL, mode; + int i; + + for (i = 0; xf86DefaultModes[i].name != NULL; i++) + { + DisplayModePtr defMode = &xf86DefaultModes[i]; + + if (!interlaceAllowed && (defMode->Flags & V_INTERLACE)) + continue; + if (!doubleScanAllowed && (defMode->Flags & V_DBLSCAN)) + continue; + + mode = xalloc(sizeof(DisplayModeRec)); + if (!mode) + continue; + memcpy(mode,&xf86DefaultModes[i],sizeof(DisplayModeRec)); + mode->name = xstrdup(xf86DefaultModes[i].name); + if (!mode->name) + { + xfree (mode); + continue; + } + mode->prev = prev; + mode->next = NULL; + if (prev) + prev->next = mode; + else + head = mode; + prev = mode; + } + return head; +} diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 98300039..a7d0839d 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -28,6 +28,7 @@ #ifndef _I830_XF86MODES_H_ #define _I830_XF86MODES_H_ #include "xorgVersion.h" +#include "xf86Parser.h" #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) double i830_xf86ModeHSync(DisplayModePtr mode); @@ -41,6 +42,10 @@ Bool i830_xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode); DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); +DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); +DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, + Bool Reduced, Bool Interlaced); + #define xf86ModeHSync i830_xf86ModeHSync #define xf86ModeVRefresh i830_xf86ModeVRefresh #define xf86DuplicateMode i830_xf86DuplicateMode @@ -50,6 +55,8 @@ DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); #define xf86ModesEqual i830_xf86ModesEqual #define xf86PrintModeline i830_xf86PrintModeline #define xf86ModesAdd i830_xf86ModesAdd +#define xf86DDCGetModes i830_xf86DDCGetModes +#define xf86CVTMode i830_xf86CVTMode #endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ void @@ -79,4 +86,10 @@ i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, void i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList); +DisplayModePtr +i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor); + +DisplayModePtr +i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed); + #endif /* _I830_XF86MODES_H_ */ diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c index dba57c82..1a2b7869 100644 --- a/src/i830_xf86cvt.c +++ b/src/i830_xf86cvt.c @@ -39,6 +39,7 @@ #include "i830.h" #include "i830_display.h" +#include #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) /* diff --git a/src/i915_video.c b/src/i915_video.c index 636b2cbd..52fe1a51 100644 --- a/src/i915_video.c +++ b/src/i915_video.c @@ -57,12 +57,12 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, short width, short height, int video_pitch, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, - DrawablePtr pDraw) + PixmapPtr pPixmap) { I830Ptr pI830 = I830PTR(pScrn); CARD32 format, ms3, s2, s5; BoxPtr pbox; - int nbox, dxo, dyo; + int nbox, dxo, dyo, pix_xoff, pix_yoff; Bool planar; #if 0 @@ -103,7 +103,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* draw rect -- just clipping */ OUT_RING(_3DSTATE_DRAW_RECT_CMD); - OUT_RING(DRAW_DITHER_OFS_X(pDraw->x & 3)| DRAW_DITHER_OFS_Y(pDraw->y & 3)); /* flags */ + OUT_RING(DRAW_DITHER_OFS_X(pPixmap->drawable.x & 3) | + DRAW_DITHER_OFS_Y(pPixmap->drawable.y & 3)); OUT_RING(0x00000000); /* ymin, xmin */ OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); /* ymax, xmax */ @@ -155,8 +156,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* front buffer, pitch, offset */ OUT_RING(_3DSTATE_BUF_INFO_CMD); OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE | - (((pI830->displayWidth * pI830->cpp) / 4) << 2)); - OUT_RING(pI830->bufferOffset); + BUF_3D_PITCH(pPixmap->devKind)); + OUT_RING(BUF_3D_ADDR((long)pPixmap->devPrivate.ptr - (long)pI830->FbBase)); ADVANCE_LP_RING(); if (!planar) { @@ -340,6 +341,17 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, ADVANCE_LP_RING(); } + /* Set up the offset for translating from the given region (in screen + * coordinates) to the backing pixmap. + */ +#ifdef COMPOSITE + pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x; + pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + pix_xoff = 0; + pix_yoff = 0; +#endif + dxo = dstRegion->extents.x1; dyo = dstRegion->extents.y1; @@ -380,8 +392,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, (vert_data_count - 1)); /* bottom right */ - OUT_RING_F(box_x2); - OUT_RING_F(box_y2); + OUT_RING_F(box_x2 + pix_xoff); + OUT_RING_F(box_y2 + pix_yoff); if (!planar) { OUT_RING_F((box_x2 - dxo) * src_scale_x); OUT_RING_F((box_y2 - dyo) * src_scale_y); @@ -393,8 +405,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, } /* bottom left */ - OUT_RING_F(box_x1); - OUT_RING_F(box_y2); + OUT_RING_F(box_x1 + pix_xoff); + OUT_RING_F(box_y2 + pix_yoff); if (!planar) { OUT_RING_F((box_x1 - dxo) * src_scale_x); OUT_RING_F((box_y2 - dyo) * src_scale_y); @@ -406,8 +418,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, } /* top left */ - OUT_RING_F(box_x1); - OUT_RING_F(box_y1); + OUT_RING_F(box_x1 + pix_xoff); + OUT_RING_F(box_y1 + pix_yoff); if (!planar) { OUT_RING_F((box_x1 - dxo) * src_scale_x); OUT_RING_F((box_y1 - dyo) * src_scale_y); diff --git a/src/i965_video.c b/src/i965_video.c new file mode 100644 index 00000000..9e96527d --- /dev/null +++ b/src/i965_video.c @@ -0,0 +1,865 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * Keith Packard + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86xv.h" +#include "fourcc.h" + +#include "i830.h" +#include "i830_video.h" +#include "brw_defines.h" +#include "brw_structs.h" +#include + +/* Make assert() work. */ +#undef NDEBUG +#include + +static const CARD32 sip_kernel_static[][4] = { +/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ + { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +}; + +/* + * this program computes dA/dx and dA/dy for the texture coordinates along + * with the base texture coordinate. It was extracted from the Mesa driver. + * It uses about 10 GRF registers. + */ + +#define SF_KERNEL_NUM_GRF 16 +#define SF_MAX_THREADS 1 + +static const CARD32 sf_kernel_static[][4] = { +#include "sf_prog.h" +}; + +/* + * Ok, this kernel picks up the required data flow values in g0 and g1 + * and passes those along in m0 and m1. In m2-m9, it sticks constant + * values (bright pink). + */ + +/* Our PS kernel uses less than 32 GRF registers (about 20) */ +#define PS_KERNEL_NUM_GRF 32 +#define PS_MAX_THREADS 32 + +#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) + +static const CARD32 ps_kernel_static[][4] = { +#include "wm_prog.h" +}; + +#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define WM_BINDING_TABLE_ENTRIES 2 + +static CARD32 float_to_uint (float f) { + union {CARD32 i; float f;} x; + x.f = f; + return x.i; +} + +#if 0 +static struct { + CARD32 svg_ctl; + char *name; +} svg_ctl_bits[] = { + { BRW_SVG_CTL_GS_BA, "General State Base Address" }, + { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, + { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, + { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, + { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, + { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, + { 0, 0 }, +}; + +static void +brw_debug (ScrnInfoPtr pScrn, char *when) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + CARD32 v; + + I830Sync (pScrn); + ErrorF("brw_debug: %s\n", when); + for (i = 0; svg_ctl_bits[i].name; i++) { + OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); + v = INREG(BRW_SVG_RDATA); + ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); + } +} +#endif + +#define WATCH_SF 0 +#define WATCH_WIZ 0 +#define WATCH_STATS 0 + +void +I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, + RegionPtr dstRegion, + short width, short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + PixmapPtr pPixmap) +{ + I830Ptr pI830 = I830PTR(pScrn); + BoxPtr pbox; + int nbox, dxo, dyo, pix_xoff, pix_yoff; + int urb_vs_start, urb_vs_size; + int urb_gs_start, urb_gs_size; + int urb_clip_start, urb_clip_size; + int urb_sf_start, urb_sf_size; + int urb_cs_start, urb_cs_size; + struct brw_surface_state *dest_surf_state; + struct brw_surface_state *src_surf_state; + struct brw_sampler_state *src_sampler_state; + struct brw_vs_unit_state *vs_state; + struct brw_sf_unit_state *sf_state; + struct brw_wm_unit_state *wm_state; + struct brw_cc_unit_state *cc_state; + struct brw_cc_viewport *cc_viewport; + struct brw_instruction *sf_kernel; + struct brw_instruction *ps_kernel; + struct brw_instruction *sip_kernel; + float *vb; + CARD32 *binding_table; + Bool first_output = TRUE; + int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; + int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; + int wm_scratch_offset; + int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; + int binding_table_offset; + int next_offset, total_state_size; + int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ + char *state_base; + int state_base_offset; + +#if 0 + ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, + video_pitch); +#endif + + /* enable debug */ + OUTREG (INST_PM, + (1 << (16 + 4)) | + (1 << 4)); +#if 0 + ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); +#endif + + assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); + + /* Tell the rotation code that we have stomped its invariant state by + * setting a high bit. We don't use any invariant 3D state for video, so + * we don't have to worry about it ourselves. + */ + *pI830->used3D |= 1 << 30; + +#ifdef XF86DRI + /* Tell the DRI that we're smashing its state. */ + if (pI830->directRenderingEnabled) { + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + } +#endif /* XF86DRI */ + + next_offset = 0; + + /* Set up our layout of state in framebuffer. First the general state: */ + vs_offset = ALIGN(next_offset, 64); + next_offset = vs_offset + sizeof(*vs_state); + sf_offset = ALIGN(next_offset, 32); + next_offset = sf_offset + sizeof(*sf_state); + wm_offset = ALIGN(next_offset, 32); + next_offset = wm_offset + sizeof(*wm_state); + wm_scratch_offset = ALIGN(next_offset, 1024); + next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; + cc_offset = ALIGN(next_offset, 32); + next_offset = cc_offset + sizeof(*cc_state); + + sf_kernel_offset = ALIGN(next_offset, 64); + next_offset = sf_kernel_offset + sizeof (sf_kernel_static); + ps_kernel_offset = ALIGN(next_offset, 64); + next_offset = ps_kernel_offset + sizeof (ps_kernel_static); + sip_kernel_offset = ALIGN(next_offset, 64); + next_offset = sip_kernel_offset + sizeof (sip_kernel_static); + cc_viewport_offset = ALIGN(next_offset, 32); + next_offset = cc_viewport_offset + sizeof(*cc_viewport); + + src_sampler_offset = ALIGN(next_offset, 32); + next_offset = src_sampler_offset + sizeof(*src_sampler_state); + + /* Align VB to native size of elements, for safety */ + vb_offset = ALIGN(next_offset, 8); + next_offset = vb_offset + vb_size; + + /* And then the general state: */ + dest_surf_offset = ALIGN(next_offset, 32); + next_offset = dest_surf_offset + sizeof(*dest_surf_state); + src_surf_offset = ALIGN(next_offset, 32); + next_offset = src_surf_offset + sizeof(*src_surf_state); + binding_table_offset = ALIGN(next_offset, 32); + next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); + + /* Allocate an area in framebuffer for our state layout we just set up */ + total_state_size = next_offset; + assert (total_state_size < BRW_LINEAR_EXTRA); + + /* + * Use the extra space allocated at the end of the Xv buffer + */ + state_base_offset = pPriv->extra_offset; + state_base_offset = ALIGN(state_base_offset, 64); + + state_base = (char *)(pI830->FbBase + state_base_offset); + /* Set up our pointers to state structures in framebuffer. It would + * probably be a good idea to fill these structures out in system memory + * and then dump them there, instead. + */ + vs_state = (void *)(state_base + vs_offset); + sf_state = (void *)(state_base + sf_offset); + wm_state = (void *)(state_base + wm_offset); + cc_state = (void *)(state_base + cc_offset); + sf_kernel = (void *)(state_base + sf_kernel_offset); + ps_kernel = (void *)(state_base + ps_kernel_offset); + sip_kernel = (void *)(state_base + sip_kernel_offset); + + cc_viewport = (void *)(state_base + cc_viewport_offset); + dest_surf_state = (void *)(state_base + dest_surf_offset); + src_surf_state = (void *)(state_base + src_surf_offset); + src_sampler_state = (void *)(state_base + src_sampler_offset); + binding_table = (void *)(state_base + binding_table_offset); + vb = (void *)(state_base + vb_offset); + +#if 0 + ErrorF("vs: 0x%08x\n", state_base_offset + vs_offset); + ErrorF("wm: 0x%08x\n", state_base_offset + wm_offset); + ErrorF("sf: 0x%08x\n", state_base_offset + sf_offset); + ErrorF("cc: 0x%08x\n", state_base_offset + cc_offset); + ErrorF("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); + ErrorF("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); + ErrorF("sip kernel: 0x%08x\n", state_base_offset + sip_kernel_offset); + ErrorF("cc_vp: 0x%08x\n", state_base_offset + cc_viewport_offset); + ErrorF("src sampler: 0x%08x\n", state_base_offset + src_sampler_offset); + ErrorF("vb: 0x%08x\n", state_base_offset + vb_offset); + ErrorF("dst surf: 0x%08x\n", state_base_offset + dest_surf_offset); + ErrorF("src surf: 0x%08x\n", state_base_offset + src_surf_offset); + ErrorF("binding table: 0x%08x\n", state_base_offset + binding_table_offset); +#endif + + /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. + * A VUE consists of a 256-bit vertex header followed by the vertex data, + * which in our case is 4 floats (128 bits), thus a single 512-bit URB + * entry. + */ +#define URB_VS_ENTRIES 8 +#define URB_VS_ENTRY_SIZE 1 + +#define URB_GS_ENTRIES 0 +#define URB_GS_ENTRY_SIZE 0 + +#define URB_CLIP_ENTRIES 0 +#define URB_CLIP_ENTRY_SIZE 0 + + /* The SF kernel we use outputs only 4 256-bit registers, leading to an + * entry size of 2 512-bit URBs. We don't need to have many entries to + * output as we're generally working on large rectangles and don't care + * about having WM threads running on different rectangles simultaneously. + */ +#define URB_SF_ENTRIES 1 +#define URB_SF_ENTRY_SIZE 2 + +#define URB_CS_ENTRIES 0 +#define URB_CS_ENTRY_SIZE 0 + + urb_vs_start = 0; + urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; + urb_gs_start = urb_vs_start + urb_vs_size; + urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; + urb_clip_start = urb_gs_start + urb_gs_size; + urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; + urb_sf_start = urb_clip_start + urb_clip_size; + urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; + urb_cs_start = urb_sf_start + urb_sf_size; + urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; + + /* We'll be poking the state buffers that could be in use by the 3d + * hardware here, but we should have synced the 3D engine already in + * I830PutImage. + */ + + memset (cc_viewport, 0, sizeof (*cc_viewport)); + cc_viewport->min_depth = -1.e35; + cc_viewport->max_depth = 1.e35; + + /* Color calculator state */ + memset(cc_state, 0, sizeof(*cc_state)); + cc_state->cc0.stencil_enable = 0; /* disable stencil */ + cc_state->cc2.depth_test = 0; /* disable depth test */ + cc_state->cc2.logicop_enable = 1; /* enable logic op */ + cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ + cc_state->cc3.blend_enable = 0; /* disable color blend */ + cc_state->cc3.alpha_test = 0; /* disable alpha test */ + cc_state->cc4.cc_viewport_state_offset = (state_base_offset + + cc_viewport_offset) >> 5; + cc_state->cc5.dither_enable = 0; /* disable dither */ + cc_state->cc5.logicop_func = 0xc; /* WHITE */ + cc_state->cc5.statistics_enable = 1; + cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; + cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; + cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; + + /* Upload system kernel */ + memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); + + /* Set up the state buffer for the destination surface */ + memset(dest_surf_state, 0, sizeof(*dest_surf_state)); + dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; + dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; + if (pI830->cpp == 2) { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; + } else { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + } + dest_surf_state->ss0.writedisable_alpha = 0; + dest_surf_state->ss0.writedisable_red = 0; + dest_surf_state->ss0.writedisable_green = 0; + dest_surf_state->ss0.writedisable_blue = 0; + dest_surf_state->ss0.color_blend = 1; + dest_surf_state->ss0.vert_line_stride = 0; + dest_surf_state->ss0.vert_line_stride_ofs = 0; + dest_surf_state->ss0.mipmap_layout_mode = 0; + dest_surf_state->ss0.render_cache_read_mode = 0; + + dest_surf_state->ss1.base_addr = (long)pPixmap->devPrivate.ptr - + (long)pI830->FbBase; + dest_surf_state->ss2.height = pScrn->virtualY - 1; + dest_surf_state->ss2.width = pScrn->virtualX - 1; + dest_surf_state->ss2.mip_count = 0; + dest_surf_state->ss2.render_target_rotation = 0; + dest_surf_state->ss3.pitch = pPixmap->devKind - 1; + + /* Set up the source surface state buffer */ + memset(src_surf_state, 0, sizeof(*src_surf_state)); + src_surf_state->ss0.surface_type = BRW_SURFACE_2D; + /* src_surf_state->ss0.data_return_format = + BRW_SURFACERETURNFORMAT_FLOAT32; */ + switch (id) { + case FOURCC_YUY2: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; + break; + case FOURCC_UYVY: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; + break; + } + src_surf_state->ss0.writedisable_alpha = 0; + src_surf_state->ss0.writedisable_red = 0; + src_surf_state->ss0.writedisable_green = 0; + src_surf_state->ss0.writedisable_blue = 0; + src_surf_state->ss0.color_blend = 1; + src_surf_state->ss0.vert_line_stride = 0; + src_surf_state->ss0.vert_line_stride_ofs = 0; + src_surf_state->ss0.mipmap_layout_mode = 0; + src_surf_state->ss0.render_cache_read_mode = 0; + + src_surf_state->ss1.base_addr = pPriv->YBuf0offset; + src_surf_state->ss2.width = width - 1; + src_surf_state->ss2.height = height - 1; + src_surf_state->ss2.mip_count = 0; + src_surf_state->ss2.render_target_rotation = 0; + src_surf_state->ss3.pitch = video_pitch - 1; + + /* Set up a binding table for our two surfaces. Only the PS will use it */ + /* XXX: are these offset from the right place? */ + binding_table[0] = state_base_offset + dest_surf_offset; + binding_table[1] = state_base_offset + src_surf_offset; + + /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. + */ + memset(src_sampler_state, 0, sizeof(*src_sampler_state)); + src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + + /* Set up the vertex shader to be disabled (passthrough) */ + memset(vs_state, 0, sizeof(*vs_state)); + vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; + vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; + vs_state->vs6.vs_enable = 0; + vs_state->vs6.vert_cache_disable = 1; + + /* Set up the SF kernel to do coord interp: for each attribute, + * calculate dA/dx and dA/dy. Hand these interpolation coefficients + * back to SF which then hands pixels off to WM. + */ + + memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); + memset(sf_state, 0, sizeof(*sf_state)); + sf_state->thread0.kernel_start_pointer = + (state_base_offset + sf_kernel_offset) >> 6; + sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); + sf_state->sf1.single_program_flow = 1; /* XXX */ + sf_state->sf1.binding_table_entry_count = 0; + sf_state->sf1.thread_priority = 0; + sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ + sf_state->sf1.illegal_op_exception_enable = 1; + sf_state->sf1.mask_stack_exception_enable = 1; + sf_state->sf1.sw_exception_enable = 1; + sf_state->thread2.per_thread_scratch_space = 0; + /* scratch space is not used in our kernel */ + sf_state->thread2.scratch_space_base_pointer = 0; + sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ + sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ + sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ + sf_state->thread3.urb_entry_read_offset = 0; + sf_state->thread3.dispatch_grf_start_reg = 3; + sf_state->thread4.max_threads = SF_MAX_THREADS - 1; + sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; + sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; + sf_state->thread4.stats_enable = 1; + sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ + sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; + sf_state->sf6.scissor = 0; + sf_state->sf7.trifan_pv = 2; + sf_state->sf6.dest_org_vbias = 0x8; + sf_state->sf6.dest_org_hbias = 0x8; + + memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); + memset (wm_state, 0, sizeof (*wm_state)); + wm_state->thread0.kernel_start_pointer = + (state_base_offset + ps_kernel_offset) >> 6; + wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); + wm_state->thread1.single_program_flow = 1; /* XXX */ + wm_state->thread1.binding_table_entry_count = 2; + /* Though we never use the scratch space in our WM kernel, it has to be + * set, and the minimum allocation is 1024 bytes. + */ + wm_state->thread2.scratch_space_base_pointer = (state_base_offset + + wm_scratch_offset) >> 10; + wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ + wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ + wm_state->thread3.const_urb_entry_read_length = 0; + wm_state->thread3.const_urb_entry_read_offset = 0; + wm_state->thread3.urb_entry_read_length = 1; /* XXX */ + wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ + wm_state->wm4.stats_enable = 1; + wm_state->wm4.sampler_state_pointer = (state_base_offset + + src_sampler_offset) >> 5; + wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ + wm_state->wm5.max_threads = PS_MAX_THREADS - 1; + wm_state->wm5.thread_dispatch_enable = 1; + wm_state->wm5.enable_16_pix = 1; + wm_state->wm5.enable_8_pix = 0; + wm_state->wm5.early_depth_test = 1; + + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | + MI_STATE_INSTRUCTION_CACHE_FLUSH | + BRW_MI_GLOBAL_SNAPSHOT_RESET); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } + + /* brw_debug (pScrn, "before base address modify"); */ + { + BEGIN_LP_RING(12); + /* Match Mesa driver setup */ + OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); + + /* Mesa does this. Who knows... */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING((0 << 4) | /* URB Entry Allocation Size */ + (0 << 0)); /* Number of URB Entries */ + + /* Zero out the two base address registers so all offsets are + * absolute + */ + OUT_RING(BRW_STATE_BASE_ADDRESS | 4); + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ + /* general state max addr, disabled */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); + /* media object state max addr, disabled */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); + + /* Set system instruction pointer */ + OUT_RING(BRW_STATE_SIP | 0); + /* system instruction pointer */ + OUT_RING(state_base_offset + sip_kernel_offset); + + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } + + /* brw_debug (pScrn, "after base address modify"); */ + + { + BEGIN_LP_RING(42); + /* Enable VF statistics */ + OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); + + /* Pipe control */ + OUT_RING(BRW_PIPE_CONTROL | + BRW_PIPE_CONTROL_NOWRITE | + BRW_PIPE_CONTROL_IS_FLUSH | + 2); + OUT_RING(0); /* Destination address */ + OUT_RING(0); /* Immediate data low DW */ + OUT_RING(0); /* Immediate data high DW */ + + /* Binding table pointers */ + OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); + OUT_RING(0); /* vs */ + OUT_RING(0); /* gs */ + OUT_RING(0); /* clip */ + OUT_RING(0); /* sf */ + /* Only the PS uses the binding table */ + OUT_RING(state_base_offset + binding_table_offset); /* ps */ + + /* Blend constant color (magenta is fun) */ + OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (0.0)); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (1.0)); + + /* The drawing rectangle clipping is always on. Set it to values that + * shouldn't do any clipping. + */ + OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | + (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ + + /* skip the depth buffer */ + /* skip the polygon stipple */ + /* skip the polygon stipple offset */ + /* skip the line stipple */ + + /* Set the pointers to the 3d pipeline state */ + OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); + OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ + /* disable GS, resulting in passthrough */ + OUT_RING(BRW_GS_DISABLE); + /* disable CLIP, resulting in passthrough */ + OUT_RING(BRW_CLIP_DISABLE); + OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ + + /* URB fence */ + OUT_RING(BRW_URB_FENCE | + UF0_CS_REALLOC | + UF0_SF_REALLOC | + UF0_CLIP_REALLOC | + UF0_GS_REALLOC | + UF0_VS_REALLOC | + 1); + OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | + ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | + ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); + OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | + ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); + + /* Constant buffer state */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | + (URB_CS_ENTRIES << 0)); + + /* Set up the pointer to our vertex buffer */ + OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); + /* four 32-bit floats per vertex */ + OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | + VB0_VERTEXDATA | + ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); + OUT_RING(state_base_offset + vb_offset); + OUT_RING(3); /* four corners to our rectangle */ + + /* Set up our vertex elements, sourced from the single vertex buffer. */ + OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); + /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (0 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (8 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + + OUT_RING(MI_NOOP); /* pad to quadword */ + ADVANCE_LP_RING(); + } + + /* Set up the offset for translating from the given region (in screen + * coordinates) to the backing pixmap. + */ +#ifdef COMPOSITE + pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x; + pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + pix_xoff = 0; + pix_yoff = 0; +#endif + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + while (nbox--) { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + int i; + float src_scale_x, src_scale_y; + + if (!first_output) { + /* Since we use the same little vertex buffer over and over, sync + * for subsequent rectangles. + */ + i830WaitSync(pScrn); + } + + pbox++; + + /* Use normalized texture coordinates */ + src_scale_x = (float)1.0 / (float)drw_w; + src_scale_y = (float)1.0 / (float)drw_h; + + i = 0; + vb[i++] = (box_x2 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x2 + pix_xoff; + vb[i++] = (float) box_y2 + pix_yoff; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x1 + pix_xoff; + vb[i++] = (float) box_y2 + pix_yoff; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y1 - dyo) * src_scale_y; + vb[i++] = (float) box_x1 + pix_xoff; + vb[i++] = (float) box_y1 + pix_yoff; + +#if 0 + ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); + + OUTREG(BRW_VF_CTL, + BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | + BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | + BRW_VF_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_VF_STRG_VAL, 0); +#endif + +#if 0 + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_ALL_THREADS | + BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | + BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); + + OUTREG(BRW_VS_STRG_VAL, 0); +#endif + +#if WATCH_SF + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | + BRW_SF_CTL_SNAPSHOT_ALL_THREADS | + BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); + OUTREG(BRW_SF_STRG_VAL, 0); +#endif + +#if WATCH_WIZ + OUTREG(BRW_WIZ_CTL, + BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | + BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | + BRW_WIZ_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_WIZ_STRG_VAL, + (box_x1) | (box_y1 << 16)); +#endif + +#if 0 + OUTREG(BRW_TS_CTL, + BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | + BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | + BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | + BRW_TS_CTL_SNAPSHOT_ENABLE); +#endif + + BEGIN_LP_RING(6); + OUT_RING(BRW_3DPRIMITIVE | + BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | + (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | + (0 << 9) | /* CTG - indirect vertex count */ + 4); + OUT_RING(3); /* vertex count per instance */ + OUT_RING(0); /* start vertex offset */ + OUT_RING(1); /* single instance */ + OUT_RING(0); /* start instance location */ + OUT_RING(0); /* index buffer offset, ignored */ + ADVANCE_LP_RING(); + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_VF_CTL); + if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VF_RDATA); + OUTREG(BRW_VF_CTL, 0); + ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_VS_CTL); + if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VS_RDATA); + for (k = 0; k <= 3; k++) { + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_VS_RDATA); + ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_VS_CTL, 0); +#endif + +#if WATCH_SF + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_SF_CTL); + if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) + break; + } + + for (k = 0; k <= 7; k++) { + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_SF_RDATA); + ErrorF("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_SF_CTL, 0); +#endif + +#if WATCH_WIZ + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_WIZ_CTL); + if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_WIZ_RDATA); + OUTREG(BRW_WIZ_CTL, 0); + ErrorF("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_TS_CTL); + if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_TS_RDATA); + OUTREG(BRW_TS_CTL, 0); + ErrorF("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); + + ErrorF("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); +#endif + +#if 0 + for (j = 0; j < 256; j++) { + OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); + rdata = INREG(BRW_TD_RDATA); + ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); + } +#endif + first_output = FALSE; + i830MarkSync(pScrn); + } + + i830WaitSync(pScrn); +#if WATCH_STATS + i830_dump_error_state(pScrn); +#endif +} diff --git a/src/ivch/Makefile.am b/src/ivch/Makefile.am new file mode 100644 index 00000000..fac074db --- /dev/null +++ b/src/ivch/Makefile.am @@ -0,0 +1,15 @@ +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ + +ivch_la_LTLIBRARIES = ivch.la +ivch_la_LDFLAGS = -module -avoid-version +ivch_ladir = @moduledir@/drivers + +ivch_la_SOURCES = \ + ivch.c \ + ivch_module.c \ + ivch_reg.h diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c new file mode 100644 index 00000000..6c5db6c9 --- /dev/null +++ b/src/ivch/ivch.c @@ -0,0 +1,234 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" +#include "../i830_xf86Crtc.h" +#define DPMS_SERVER +#include + +#include "../i2c_vid.h" +#include "ivch_reg.h" + +struct ivch_priv { + I2CDevRec d; + + CARD16 save_VR01; + CARD16 save_VR40; +}; + +static void +ivch_dump_regs(I2CDevPtr d); + +/** + * Reads a register on the ivch. + * + * Each of the 256 registers are 16 bits long. + */ +static Bool +ivch_read(struct ivch_priv *priv, int addr, CARD16 *data) +{ + if (!xf86I2CReadWord(&priv->d, addr, data)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read register 0x%02x from %s:%d.\n", + addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/** Writes a 16-bit register on the ivch */ +static Bool +ivch_write(struct ivch_priv *priv, int addr, CARD16 data) +{ + if (!xf86I2CWriteWord(&priv->d, addr, data)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write register 0x%02x to %s:%d.\n", + addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/** Probes the given bus and slave address for an ivch */ +static void * +ivch_init(I2CBusPtr b, I2CSlaveAddr addr) +{ + struct ivch_priv *priv; + CARD16 temp; + + xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n"); + + priv = xcalloc(1, sizeof(struct ivch_priv)); + if (priv = NULL) + return NULL; + + priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller"; + priv->d.SlaveAddr = addr; + priv->d.pI2CBus = b; + priv->d.StartTimeout = b->StartTimeout; + priv->d.BitTimeout = b->BitTimeout; + priv->d.AcknTimeout = b->AcknTimeout; + priv->d.ByteTimeout = b->ByteTimeout; + priv->d.DriverPrivate.ptr = priv; + + if (!xf86I2CReadWord(&priv->d, VR00, &temp)) + goto out; + + /* Since the identification bits are probably zeroes, which doesn't seem + * very unique, check that the value in the base address field matches + * the address it's responding on. + */ + if ((temp & VR00_BASE_ADDRESS_MASK) != priv->d.SlaveAddr) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "ivch detect failed due to address mismatch " + "(%d vs %d)\n", + (temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr); + } + + if (!xf86I2CDevInit(&priv->d)) { + goto out; + } + + return priv; + +out: + xfree(priv); + return NULL; +} + +static xf86OutputStatus +ivch_detect(I2CDevPtr d) +{ + return XF86OutputStatusUnknown; +} + +static ModeStatus +ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode) +{ + if (mode->Clock > 112000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +/** Sets the power state of the panel connected to the ivch */ +static void +ivch_dpms(I2CDevPtr d, int mode) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + int i; + CARD16 temp; + + /* Set the new power state of the panel. */ + if (!ivch_read(priv, VR01, &temp)) + return; + + if (mode == DPMSModeOn) + temp |= VR01_LCD_ENABLE | VR01_DVO_ENABLE; + else + temp &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE); + + ivch_write(priv, VR01, temp); + + /* Wait for the panel to make its state transition */ + for (i = 0; i < 1000; i++) { + if (!ivch_read(priv, VR30, &temp)) + break; + + if (((temp & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn)) + break; + } +} + +static void +ivch_mode_set(I2CDevPtr d, DisplayModePtr mode) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + + /* Disable panel fitting for now, until we can test. */ + ivch_write(priv, VR40, 0); + + ivch_dpms(d, DPMSModeOn); + + ivch_dump_regs(d); +} + +static void +ivch_dump_regs(I2CDevPtr d) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + CARD16 val; + + ivch_read(priv, VR00, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR00: 0x%04x\n", val); + ivch_read(priv, VR01, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR01: 0x%04x\n", val); + ivch_read(priv, VR30, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR30: 0x%04x\n", val); + ivch_read(priv, VR40, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR40: 0x%04x\n", val); + +} + +static void +ivch_save(I2CDevPtr d) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + + ivch_read(priv, VR01, &priv->save_VR01); + ivch_read(priv, VR40, &priv->save_VR40); +} + +static void +ivch_restore(I2CDevPtr d) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + + ivch_write(priv, VR01, priv->save_VR01); + ivch_write(priv, VR40, priv->save_VR40); +} + + +I830I2CVidOutputRec ivch_methods = { + .init = ivch_init, + .detect = ivch_detect, + .mode_valid = ivch_mode_valid, + .mode_set = ivch_mode_set, + .dpms = ivch_dpms, + .dump_regs = ivch_dump_regs, + .save = ivch_save, + .restore = ivch_restore, +}; diff --git a/src/ivch/ivch_module.c b/src/ivch/ivch_module.c new file mode 100644 index 00000000..1ed483b1 --- /dev/null +++ b/src/ivch/ivch_module.c @@ -0,0 +1,64 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(ivch_setup); + +static XF86ModuleVersionInfo ivch_version = { + "ivch", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + { 0,0,0,0 } +}; + +_X_EXPORT XF86ModuleData ivchModuleData = { + &ivch_version, + ivch_setup, + NULL +}; + +static pointer +ivch_setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + return (pointer)1; +} diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h new file mode 100644 index 00000000..112c97d6 --- /dev/null +++ b/src/ivch/ivch_reg.h @@ -0,0 +1,97 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/** @file + * This file contains the register definitions for the i82807aa. + * + * Documentation on this chipset can be found in datasheet #29069001 at + * intel.com. + */ +#ifndef I82807AA_REG_H +#define I82807AA_REG_H + +/** @defgroup VR00 + * @{ + */ +#define VR00 0x00 +# define VR00_BASE_ADDRESS_MASK 0x007f +/** @} */ + +/** @defgroup VR01 + * @{ + */ +#define VR01 0x01 +# define VR01_PANEL_FIT_ENABLE (1 << 3) +/** + * Enables the LCD display. + * + * This must not be set while VR01_DVO_BYPASS_ENABLE is set. + */ +# define VR01_LCD_ENABLE (1 << 2) +/** Enables the DVO repeater. */ +# define VR01_DVO_BYPASS_ENABLE (1 << 1) +/** Enables the DVO clock */ +# define VR01_DVO_ENABLE (1 << 0) +/** @} */ + +/** @defgroup VR10 + * @{ + */ +#define VR10 0x10 +/** Enables LVDS output instead of CMOS */ +# define VR10_LVDS_ENABLE (1 << 4) +/** Enables 18-bit LVDS output. */ +# define VR10_INTERFACE_1X18 (0 << 2) +/** Enables 24-bit LVDS or CMOS output */ +# define VR10_INTERFACE_1X24 (1 << 2) +/** Enables 2x18-bit LVDS or CMOS output. */ +# define VR10_INTERFACE_2X18 (2 << 2) +/** Enables 2x24-bit LVDS output */ +# define VR10_INTERFACE_2X24 (3 << 2) +/** @} */ + +/** @defgroup VR30 + * @{ + */ +#define VR30 0x30 +/** Read only bit indicating that the panel is not in a safe poweroff state. */ +# define VR30_PANEL_ON (1 << 15) +/** @} */ + +/** @defgroup VR40 + * @{ + */ +#define VR40 0x40 +# define VR40_STALL_ENABLE (1 << 13) +# define VR40_VERTICAL_INTERP_ENABLE (1 << 11) +# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10) +# define VR40_RATIO_ENABLE (1 << 9) +# define VR40_PANEL_FIT_ENABLE (1 << 8) +/** @} */ + +#endif /* I82807AA_REG_H */ diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h new file mode 100644 index 00000000..183b8572 --- /dev/null +++ b/src/xf86Optrec.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2001 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* + * This file contains the Option Record that is passed between the Parser, + * and Module setup procs. + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifndef _xf86Optrec_h_ +#define _xf86Optrec_h_ +#include + +/* + * all records that need to be linked lists should contain a GenericList as + * their first field. + */ +typedef struct generic_list_rec +{ + void *next; +} +GenericListRec, *GenericListPtr, *glp; + +/* + * All options are stored using this data type. + */ +typedef struct +{ + GenericListRec list; + char *opt_name; + char *opt_val; + int opt_used; + char *opt_comment; +} +XF86OptionRec, *XF86OptionPtr; + + +XF86OptionPtr xf86addNewOption(XF86OptionPtr head, char *name, char *val); +XF86OptionPtr xf86optionListDup(XF86OptionPtr opt); +void xf86optionListFree(XF86OptionPtr opt); +char *xf86optionName(XF86OptionPtr opt); +char *xf86optionValue(XF86OptionPtr opt); +XF86OptionPtr xf86newOption(char *name, char *value); +XF86OptionPtr xf86nextOption(XF86OptionPtr list); +XF86OptionPtr xf86findOption(XF86OptionPtr list, const char *name); +char *xf86findOptionValue(XF86OptionPtr list, const char *name); +int xf86findOptionBoolean (XF86OptionPtr, const char *, int); +XF86OptionPtr xf86optionListCreate(const char **options, int count, int used); +XF86OptionPtr xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail); +char *xf86configStrdup (const char *s); +int xf86nameCompare (const char *s1, const char *s2); +char *xf86uLongToString(unsigned long i); +void xf86debugListOptions(XF86OptionPtr); +XF86OptionPtr xf86parseOption(XF86OptionPtr head); +void xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs); + + +#endif /* _xf86Optrec_h_ */ diff --git a/src/xf86Parser.h b/src/xf86Parser.h new file mode 100644 index 00000000..a6829273 --- /dev/null +++ b/src/xf86Parser.h @@ -0,0 +1,483 @@ +/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* + * This file contains the external interfaces for the XFree86 configuration + * file parser. + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifndef _xf86Parser_h_ +#define _xf86Parser_h_ + +#include "xf86Optrec.h" + +#define HAVE_PARSER_DECLS + +typedef struct +{ + char *file_logfile; + char *file_rgbpath; + char *file_modulepath; + char *file_inputdevs; + char *file_fontpath; + char *file_comment; +} +XF86ConfFilesRec, *XF86ConfFilesPtr; + +/* Values for load_type */ +#define XF86_LOAD_MODULE 0 +#define XF86_LOAD_DRIVER 1 + +typedef struct +{ + GenericListRec list; + int load_type; + char *load_name; + XF86OptionPtr load_opt; + char *load_comment; + int ignore; +} +XF86LoadRec, *XF86LoadPtr; + +typedef struct +{ + XF86LoadPtr mod_load_lst; + char *mod_comment; +} +XF86ConfModuleRec, *XF86ConfModulePtr; + +#define CONF_IMPLICIT_KEYBOARD "Implicit Core Keyboard" + +#define CONF_IMPLICIT_POINTER "Implicit Core Pointer" + +#define XF86CONF_PHSYNC 0x0001 +#define XF86CONF_NHSYNC 0x0002 +#define XF86CONF_PVSYNC 0x0004 +#define XF86CONF_NVSYNC 0x0008 +#define XF86CONF_INTERLACE 0x0010 +#define XF86CONF_DBLSCAN 0x0020 +#define XF86CONF_CSYNC 0x0040 +#define XF86CONF_PCSYNC 0x0080 +#define XF86CONF_NCSYNC 0x0100 +#define XF86CONF_HSKEW 0x0200 /* hskew provided */ +#define XF86CONF_BCAST 0x0400 +#define XF86CONF_CUSTOM 0x0800 /* timing numbers customized by editor */ +#define XF86CONF_VSCAN 0x1000 + +typedef struct +{ + GenericListRec list; + char *ml_identifier; + int ml_clock; + int ml_hdisplay; + int ml_hsyncstart; + int ml_hsyncend; + int ml_htotal; + int ml_vdisplay; + int ml_vsyncstart; + int ml_vsyncend; + int ml_vtotal; + int ml_vscan; + int ml_flags; + int ml_hskew; + char *ml_comment; +} +XF86ConfModeLineRec, *XF86ConfModeLinePtr; + +typedef struct +{ + GenericListRec list; + char *vp_identifier; + XF86OptionPtr vp_option_lst; + char *vp_comment; +} +XF86ConfVideoPortRec, *XF86ConfVideoPortPtr; + +typedef struct +{ + GenericListRec list; + char *va_identifier; + char *va_vendor; + char *va_board; + char *va_busid; + char *va_driver; + XF86OptionPtr va_option_lst; + XF86ConfVideoPortPtr va_port_lst; + char *va_fwdref; + char *va_comment; +} +XF86ConfVideoAdaptorRec, *XF86ConfVideoAdaptorPtr; + +#define CONF_MAX_HSYNC 8 +#define CONF_MAX_VREFRESH 8 + +typedef struct +{ + float hi, lo; +} +parser_range; + +typedef struct +{ + int red, green, blue; +} +parser_rgb; + +typedef struct +{ + GenericListRec list; + char *modes_identifier; + XF86ConfModeLinePtr mon_modeline_lst; + char *modes_comment; +} +XF86ConfModesRec, *XF86ConfModesPtr; + +typedef struct +{ + GenericListRec list; + char *ml_modes_str; + XF86ConfModesPtr ml_modes; +} +XF86ConfModesLinkRec, *XF86ConfModesLinkPtr; + +typedef struct +{ + GenericListRec list; + char *mon_identifier; + char *mon_vendor; + char *mon_modelname; + int mon_width; /* in mm */ + int mon_height; /* in mm */ + XF86ConfModeLinePtr mon_modeline_lst; + int mon_n_hsync; + parser_range mon_hsync[CONF_MAX_HSYNC]; + int mon_n_vrefresh; + parser_range mon_vrefresh[CONF_MAX_VREFRESH]; + float mon_gamma_red; + float mon_gamma_green; + float mon_gamma_blue; + XF86OptionPtr mon_option_lst; + XF86ConfModesLinkPtr mon_modes_sect_lst; + char *mon_comment; +} +XF86ConfMonitorRec, *XF86ConfMonitorPtr; + +#define CONF_MAXDACSPEEDS 4 +#define CONF_MAXCLOCKS 128 + +typedef struct +{ + GenericListRec list; + char *dev_identifier; + char *dev_vendor; + char *dev_board; + char *dev_chipset; + char *dev_busid; + char *dev_card; + char *dev_driver; + char *dev_ramdac; + int dev_dacSpeeds[CONF_MAXDACSPEEDS]; + int dev_videoram; + int dev_textclockfreq; + unsigned long dev_bios_base; + unsigned long dev_mem_base; + unsigned long dev_io_base; + char *dev_clockchip; + int dev_clocks; + int dev_clock[CONF_MAXCLOCKS]; + int dev_chipid; + int dev_chiprev; + int dev_irq; + int dev_screen; + XF86OptionPtr dev_option_lst; + char *dev_comment; +} +XF86ConfDeviceRec, *XF86ConfDevicePtr; + +typedef struct +{ + GenericListRec list; + char *mode_name; +} +XF86ModeRec, *XF86ModePtr; + +typedef struct +{ + GenericListRec list; + int disp_frameX0; + int disp_frameY0; + int disp_virtualX; + int disp_virtualY; + int disp_depth; + int disp_bpp; + char *disp_visual; + parser_rgb disp_weight; + parser_rgb disp_black; + parser_rgb disp_white; + XF86ModePtr disp_mode_lst; + XF86OptionPtr disp_option_lst; + char *disp_comment; +} +XF86ConfDisplayRec, *XF86ConfDisplayPtr; + +typedef struct +{ + XF86OptionPtr flg_option_lst; + char *flg_comment; +} +XF86ConfFlagsRec, *XF86ConfFlagsPtr; + +typedef struct +{ + GenericListRec list; + char *al_adaptor_str; + XF86ConfVideoAdaptorPtr al_adaptor; +} +XF86ConfAdaptorLinkRec, *XF86ConfAdaptorLinkPtr; + +typedef struct +{ + GenericListRec list; + char *scrn_identifier; + char *scrn_obso_driver; + int scrn_defaultdepth; + int scrn_defaultbpp; + int scrn_defaultfbbpp; + char *scrn_monitor_str; + XF86ConfMonitorPtr scrn_monitor; + char *scrn_device_str; + XF86ConfDevicePtr scrn_device; + XF86ConfAdaptorLinkPtr scrn_adaptor_lst; + XF86ConfDisplayPtr scrn_display_lst; + XF86OptionPtr scrn_option_lst; + char *scrn_comment; +} +XF86ConfScreenRec, *XF86ConfScreenPtr; + +typedef struct +{ + GenericListRec list; + char *inp_identifier; + char *inp_driver; + XF86OptionPtr inp_option_lst; + char *inp_comment; +} +XF86ConfInputRec, *XF86ConfInputPtr; + +typedef struct +{ + GenericListRec list; + XF86ConfInputPtr iref_inputdev; + char *iref_inputdev_str; + XF86OptionPtr iref_option_lst; +} +XF86ConfInputrefRec, *XF86ConfInputrefPtr; + +/* Values for adj_where */ +#define CONF_ADJ_OBSOLETE -1 +#define CONF_ADJ_ABSOLUTE 0 +#define CONF_ADJ_RIGHTOF 1 +#define CONF_ADJ_LEFTOF 2 +#define CONF_ADJ_ABOVE 3 +#define CONF_ADJ_BELOW 4 +#define CONF_ADJ_RELATIVE 5 + +typedef struct +{ + GenericListRec list; + int adj_scrnum; + XF86ConfScreenPtr adj_screen; + char *adj_screen_str; + XF86ConfScreenPtr adj_top; + char *adj_top_str; + XF86ConfScreenPtr adj_bottom; + char *adj_bottom_str; + XF86ConfScreenPtr adj_left; + char *adj_left_str; + XF86ConfScreenPtr adj_right; + char *adj_right_str; + int adj_where; + int adj_x; + int adj_y; + char *adj_refscreen; +} +XF86ConfAdjacencyRec, *XF86ConfAdjacencyPtr; + +typedef struct +{ + GenericListRec list; + char *inactive_device_str; + XF86ConfDevicePtr inactive_device; +} +XF86ConfInactiveRec, *XF86ConfInactivePtr; + +typedef struct +{ + GenericListRec list; + char *lay_identifier; + XF86ConfAdjacencyPtr lay_adjacency_lst; + XF86ConfInactivePtr lay_inactive_lst; + XF86ConfInputrefPtr lay_input_lst; + XF86OptionPtr lay_option_lst; + char *lay_comment; +} +XF86ConfLayoutRec, *XF86ConfLayoutPtr; + +typedef struct +{ + GenericListRec list; + char *vs_name; + char *vs_identifier; + XF86OptionPtr vs_option_lst; + char *vs_comment; +} +XF86ConfVendSubRec, *XF86ConfVendSubPtr; + +typedef struct +{ + GenericListRec list; + char *vnd_identifier; + XF86OptionPtr vnd_option_lst; + XF86ConfVendSubPtr vnd_sub_lst; + char *vnd_comment; +} +XF86ConfVendorRec, *XF86ConfVendorPtr; + +typedef struct +{ + GenericListRec list; + int buf_count; + int buf_size; + char *buf_flags; + char *buf_comment; +} +XF86ConfBuffersRec, *XF86ConfBuffersPtr; + +typedef struct +{ + char *dri_group_name; + int dri_group; + int dri_mode; + XF86ConfBuffersPtr dri_buffers_lst; + char *dri_comment; +} +XF86ConfDRIRec, *XF86ConfDRIPtr; + +typedef struct +{ + XF86OptionPtr ext_option_lst; + char *extensions_comment; +} +XF86ConfExtensionsRec, *XF86ConfExtensionsPtr; + +typedef struct +{ + XF86ConfFilesPtr conf_files; + XF86ConfModulePtr conf_modules; + XF86ConfFlagsPtr conf_flags; + XF86ConfVideoAdaptorPtr conf_videoadaptor_lst; + XF86ConfModesPtr conf_modes_lst; + XF86ConfMonitorPtr conf_monitor_lst; + XF86ConfDevicePtr conf_device_lst; + XF86ConfScreenPtr conf_screen_lst; + XF86ConfInputPtr conf_input_lst; + XF86ConfLayoutPtr conf_layout_lst; + XF86ConfVendorPtr conf_vendor_lst; + XF86ConfDRIPtr conf_dri; + XF86ConfExtensionsPtr conf_extensions; + char *conf_comment; +} +XF86ConfigRec, *XF86ConfigPtr; + +typedef struct +{ + int token; /* id of the token */ + char *name; /* pointer to the LOWERCASED name */ +} +xf86ConfigSymTabRec, *xf86ConfigSymTabPtr; + +/* + * prototypes for public functions + */ +extern const char *xf86openConfigFile (const char *, const char *, + const char *); +extern void xf86setBuiltinConfig(const char *config[]); +extern XF86ConfigPtr xf86readConfigFile (void); +extern void xf86closeConfigFile (void); +extern void xf86freeConfig (XF86ConfigPtr p); +extern int xf86writeConfigFile (const char *, XF86ConfigPtr); +XF86ConfDevicePtr xf86findDevice(const char *ident, XF86ConfDevicePtr p); +XF86ConfLayoutPtr xf86findLayout(const char *name, XF86ConfLayoutPtr list); +XF86ConfMonitorPtr xf86findMonitor(const char *ident, XF86ConfMonitorPtr p); +XF86ConfModesPtr xf86findModes(const char *ident, XF86ConfModesPtr p); +XF86ConfModeLinePtr xf86findModeLine(const char *ident, XF86ConfModeLinePtr p); +XF86ConfScreenPtr xf86findScreen(const char *ident, XF86ConfScreenPtr p); +XF86ConfInputPtr xf86findInput(const char *ident, XF86ConfInputPtr p); +XF86ConfInputPtr xf86findInputByDriver(const char *driver, XF86ConfInputPtr p); +XF86ConfVendorPtr xf86findVendor(const char *name, XF86ConfVendorPtr list); +XF86ConfVideoAdaptorPtr xf86findVideoAdaptor(const char *ident, + XF86ConfVideoAdaptorPtr p); + +GenericListPtr xf86addListItem(GenericListPtr head, GenericListPtr c_new); +int xf86itemNotSublist(GenericListPtr list_1, GenericListPtr list_2); + +int xf86pathIsAbsolute(const char *path); +int xf86pathIsSafe(const char *path); +char *xf86addComment(char *cur, char *add); + +#endif /* _xf86Parser_h_ */